thancommod.py :  » Business-Application » ThanCad » thancad-0.0.9 » thancom » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Business Application » ThanCad 
ThanCad » thancad 0.0.9 » thancom » thancommod.py
##############################################################################
# ThanCad 0.0.9 "DoesSomething": 2dimensional CAD with raster support for engineers.
# 
# Copyright (c) 2001-2009 Thanasis Stamos,  August 23, 2009
# URL:     http://thancad.sourceforge.net
# e-mail:  cyberthanasis@excite.com
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details (www.gnu.org/licenses/gpl.html).
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
##############################################################################

"""\
ThanCad 0.0.9 "DoesSomething": 2dimensional CAD with raster support for engineers.

Package which processes commands entered by the user.
This module provides for a modification commands.
"""

from math import pi,hypot
from itertools import izip
from p_gmath import thanNear2
from thanvar import Canc,thanFiletCalc,ThanLayerError
from thantrans import T
import thancomsel
from selutil import thanSel1line,thanSel1breakable,thanSel2linsegs,thanSelCutting,thanSelMultlines


def thanModContline(proj):
    "Continues a previous line."
    lin = proj[1].thanPrevLine()
    if lin == None: return thanModCanc(proj, T["Invalid previous line."])
    proj[2].thanTkSet(lin)          # Set the attributes of lin's layer
    lin.thanTkContinue(proj)
    proj[2].thanTkSet()             # Set the attribute of current layer
    thanModEnd(proj)                # 'Reset color' is not needed, but it is called for only 1..
                                    # ..element, so it is fast

def thanModExtendline(proj):
    "Continues a previous line."
    lin = thanSel1line(proj, T["Select a line to extend:\n"])
    if lin == Canc: return thanModCanc(proj)               # Line continue was cancelled
    proj[2].thanTkSet(lin)          # Set the attributes of lin's layer
    lin.thanTkContinue(proj)
    proj[2].thanTkSet()             # Set the attribute of current layer
    thanModEnd(proj)                # 'Reset color' has already been called, but it is called again for only 1..
                                    # ..element, so it is fast

#=============================================================================

def thanModBreak(proj):
    "Breaks an element to 2 pieces if possible."
    elem = thanSel1breakable(proj, "%s\n" % T["Select an element to break"])
    if elem == Canc: return thanModCanc(proj)         # Break was cancelled
    c1 = proj[2].thanSel1coor
    if c1 == None or elem.thanPntNearest(c1) == None:
        c1 = __getNearPnt(proj, elem, T["First point of element to break: "])
        if c1 == Canc: return thanModCanc(proj)      # Break was cancelled
        c2 = __getNearPnt(proj, elem, T["Second point of element to break: "])
        if c2 == Canc: return thanModCanc(proj)      # Break was cancelled
    else:
        c2 = __getNearPnt(proj, elem, T["Second point of element to break (F for first point): "], options=("first",))
        if c2 == Canc: return thanModCanc(proj)      # Break was cancelled
  if c2 == "f":
            c1 = __getNearPnt(proj, elem, T["First point of element to break: "])
            if c1 == Canc: return thanModCanc(proj)  # Break was cancelled
            c2 = __getNearPnt(proj, elem, T["Second point of element to break: "])
            if c2 == Canc: return thanModCanc(proj)      # Break was cancelled
    e1, e2 = elem.thanBreak(c1, c2)
    if e1 == None and e2 == None: return thanModCanc(proj, T["Element can not be deleted; use 'ERASE'."])
    __modBreakDo(proj, elem, e1, e2)
#    proj[1].thanDoundo.thanAdd("break", thanModBreakRedo, (elems, c1, phi),
#                                        thanModBreakUndo, (elems, c1, phi, selold))
    thanModEnd(proj)                                  # 'Reset color' is ????


def __getNearPnt(proj, elem, stat1, options=()):
    "Get a point and check if it is near the element."
    statonce = ""
    while True:
        res = proj[2].thanGudGetPoint(stat1, statonce, options=options)
        if res == Canc: return Canc      # Break was cancelled
  for opt in options:
      if res == opt[:1]: return res
  if elem.thanPntNearest(res) != None: return res
  statonce = T["Point is not near element. Try again.\n"]


def __modBreakDo(proj, elem, e1, e2):
    "Breaks selected elements; it actualy does the job."
    import time
    t1 = time.time(); proj[2].thanGudSetSelDel()
    t2 = time.time(); proj[1].thanReplaceSel(proj, elem, e1, e2) # ThanTouch is implicitely called
    t3 = time.time()
    print "Break time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t2-t1, t3-t2, t3-t1)


def thanModBreakRedo(proj, elems, xc, yc, phi):
    "Rebreaks the previously glued element."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modRotateDo(proj, xc, yc, phi)


def thanModBreakUndo(proj, elems, xc, yc, phi, selold):
    "Glues the oreviously broken element."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modRotateDo(proj, xc, yc, -phi)
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(selold)

#=============================================================================

def thanModTrim(proj):
    """Trims elements using other elements as cutting edges, if possible.

    Note that the selection this command does, is the selection of the cutting
    edges. This selection is cancelled if the command is cancelled. And this
    is the "previous" selection of next command to be given to ThanCad.
    The selections of 1 breakable element are not recorded.
    """
    from thandr import thanintall
    selallold = proj[2].thanSelall
    elcut = thanSelCutting(proj, T["Select elements to be used as cutting edges:\n"])
    if elcut == Canc: return thanModCanc(proj)        # Trim was cancelled
#    proj[2].thanGudResetSelColor()                    # Leave the cutting edges marked
    proj[2].thanUpdateLayerButton()                   # Show current layer again
    opts = [""]
    iel = 0
    dodo = []             # Undo/Redo list
    mes1 = T["Select an element to trim"]
    while True:
        opts = []
        if iel > 0: opts.append("undo")
        if len(dodo) > iel: opts.append("redo")
        if len(opts) > 0: mes = "%s (%s): " % (mes1, "/".join(opts))
        else: mes = "%s: " % mes1
        opts.append("")
        res = thancomsel.thanSelect1Gen(proj, mes, filter=lambda e: e.thanBreak(), options=opts)
        if res == Canc: break                         # Trim was cancelled/ended
        if res == "": break                           # Trim was cancelled/ended
        if res == "u":
            iel -= 1
            elem, e1, e2 = dodo[iel]
            proj[1].thanElementDelete((e for e in (e1, e2) if e != None), proj)
            proj[1].thanElementRestore((elem,), proj)
            proj[2].thanGudSetSelRestore()            # Restores previous selection (the cutting edges)
            continue
        if res == "r":
            elem, e1, e2 = dodo[iel]
            proj[1].thanElementDelete((elem,), proj)
            proj[1].thanElementRestore((e for e in (e1, e2) if e != None), proj)
            iel += 1
            proj[2].thanGudSetSelRestore()            # Restores previous selection (the cutting edges)
            continue
        c1 = proj[2].thanSel1coor
        assert c1 != None, "thancomsel.thanSelect1Gen does not work well!"
        for elem in proj[2].thanSelall: break    # Get the element
        ps = []
        for elcut1 in elcut:
      ps.extend(thanintall.thanInt(elem, elcut1, proj))
  if len(ps) < 1:
      proj[2].thanCom.thanAppend(T["Element does not intersect cutting edges\n"], "can")
            proj[2].thanGudResetSelColor()            # Unmarks the selection
            proj[2].thanGudSetSelRestore()            # Restores previous selection (the cutting edges)
            proj[2].thanUpdateLayerButton()           # Show current layer again
      continue
  e1, e2 = elem.thanTrim(ps, c1)
  if e1 == None and e2 == None:
            proj[2].thanCom.thanAppend(T["Element can not be deleted; use 'ERASE' instead.\n"], "can")
            proj[2].thanGudResetSelColor()            # Unmarks the selection
            proj[2].thanGudSetSelRestore()            # Restores previous selection (the cutting edges)
            proj[2].thanUpdateLayerButton()           # Show current layer again
      continue
  __modBreakDo(proj, elem, e1, e2)
#        proj[2].thanGudResetSelColor()               # Unmarks the selection; not needed: the element is deleted
        proj[2].thanGudSetSelRestore()                # Restores previous selection (the cutting edges)
        proj[2].thanUpdateLayerButton()               # Show current layer again
  del dodo[iel:]
  dodo.append((elem, e1, e2))
  iel += 1
#    proj[1].thanDoundo.thanAdd("trim", thanModBreakRedo, (elems, c1, phi),
#                                       thanModBreakUndo, (elems, c1, phi, selold))
    proj[2].thanGudResetSelColor()            # Unmarks the selection
    proj[2].thanGudSetSelRestore()            # Restores previous selection (the cutting edges)
    proj[2].thanGudResetSelColor()            # Unmarks the selection (the cutting edges)
    proj[2].thanUpdateLayerButton()           # Show current layer again

    proj[2].thanGudSetSeloldElem(selallold)   # The selection before the command trim started
    if iel == 0: return thanModCanc(proj)     # Trim was cancelled: unselect cutting edges
    thanModEnd(proj)                          # 'Reset color' is ????


#=============================================================================

def thanModRotate(proj):
    "Rotates selected elements."
    res = thancomsel.thanSelectGen(proj, standalone=False)
    if res == Canc: return thanModCanc(proj)               # Rotation cancelled
    elems = proj[2].thanSelall
    selold = proj[2].thanSelold

    c1 = proj[2].thanGudGetPoint(T["Origin of rotation: "])
    if c1 == Canc: return thanModCanc(proj)                # Rotation cancelled

    un = proj[1].thanUnits
    st = "%s(%s): " % (T["Rotation angle"], un.anglunit)
    phi = un.rad2unit(0.5*pi)
    phi = proj[2].thanGudGetFloat(st, phi)
    if phi == Canc: return thanModCanc(proj)               # Rotation cancelled
    phi = un.unit2rad(phi)

    __modRotateDo(proj, c1, phi)
    proj[1].thanDoundo.thanAdd("rotate", thanModRotateRedo, (elems, c1, phi),
                                         thanModRotateUndo, (elems, c1, phi, selold))
    thanModEnd(proj)                                       # 'Reset color' is necessary here; OK!

def thanModEnd(proj, mes=None, mestype="can"):
    "House keeping for normal end."
    proj[2].thanGudResetSelColor()                   # Unmarks the selection
    proj[2].thanUpdateLayerButton()                  # Show current layer again
    proj[2].thanGudCommandEnd(mes, mestype)


def thanModCanc(proj, mes=None, mestype="can"):
    "House keeping for user cancel."
    proj[2].thanGudResetSelColor()                   # Unmarks the selection
    proj[2].thanGudSetSelRestore()                   # Restores previous selection
    proj[2].thanUpdateLayerButton()                  # Show current layer again
    proj[2].thanGudCommandCan(mes, mestype)          # Show prompt


def __modRotateDo(proj, cc, phi):
    "Rotates selected elements; it actualy does the job."
    import time
    t1 = time.time(); proj[2].thanGudSetSelRotate(cc[0], cc[1], phi)
    t2 = time.time(); proj[1].thanRotateSel(proj[2].thanSelall, cc, phi) # ThanTouch is implicitely called
    t3 = time.time()
    print "Rotate time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t2-t1, t3-t2, t3-t1)


def thanModRotateRedo(proj, elems, cc, phi):
    "Re-rotates the previously un-rotated elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modRotateDo(proj, cc, phi)


def thanModRotateUndo(proj, elems, cc, phi, selold):
    "Un-rotates the previously rotated elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modRotateDo(proj, cc, -phi)
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(selold)

#=============================================================================

def thanModMirror(proj):
    "Mirrors the selected elements."
    res = thancomsel.thanSelectGen(proj, standalone=False)
    if res == Canc: return thanModCanc(proj)               # Mirror cancelled
    elems = proj[2].thanSelall
    selold = proj[2].thanSelold

    c1 = proj[2].thanGudGetPoint(T["First point of mirror line: "])
    if c1 == Canc: return thanModCanc(proj)                # Mirror cancelled
    while True:
        c2 = proj[2].thanGudGetLine(c1, T["Second point of mirror line: "])
        if c2 == Canc: return thanModCanc(proj)            # Mirror cancelled
        if not thanNear2(c1, c2): break
        proj[2].thanCom.thanAppend("Second point coincides with first. Try again.\n", "can")
    keeporig = proj[2].thanGudGetYesno(T["Keep original elements (<yes>/no): "], default="yes")
    if keeporig == Canc: return thanModCanc(proj)               # Mirror cancelled
    t = [c2[0]-c1[0], c2[1]-c1[1]]
    tt = hypot(t[0], t[1])
    t[0] /= tt
    t[1] /= tt
    if keeporig:
        dc = [0.0]*len(c1)
        copelems = __modMirrorCopyDo(proj, elems, c1, t)
        proj[1].thanDoundo.thanAdd("mirror", thanModCopyRedo, (elems, copelems),
                                             thanModCopyUndo, (copelems, selold))
    else:
        __modMirrorDo(proj, c1, t)
        proj[1].thanDoundo.thanAdd("mirror", thanModMirrorRedo, (elems, c1, t),
                                             thanModMirrorUndo, (elems, c1, t, selold))
    thanModEnd(proj)       # 'Reset color' is necessary here; OK!


def __modMirrorCopyDo(proj, elems, c1, t):
    "Copies selected elements; it actualy does the job."
    import time
    t1 = time.time();
    dc = [0.0]*len(c1)
    copelems = proj[1].thanCopySel(elems, dc)   # thanTouch is implicitely called
    proj[1].thanMirrorSel(copelems, c1, t)
    t2 = time.time(); proj[2].thanGudDrawElemsMany(copelems)
    t3 = time.time()
    print "Mirror time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t3-t2, t2-t1, t3-t1)
    return copelems


def __modMirrorDo(proj, c1, t):
    "Mirrors selected elements; it actualy does the job."
    import time
    t1 = time.time(); proj[2].thanGudSetSelMirror(c1[0], c1[1], t)
    t2 = time.time(); proj[1].thanMirrorSel(proj[2].thanSelall, c1, t) # ThanTouch is implicitely called
    t3 = time.time()
    print "Mirror time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t2-t1, t3-t2, t3-t1)


def thanModMirrorRedo(proj, elems, c1, t):
    "Re-mirrors the previously un-mirrored elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modMirrorDo(proj, c1, t)


def thanModMirrorUndo(proj, elems, c1, t, selold):
    "Un-mirrors the previously mirrored elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modMirrorDo(proj, c1, t)
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(selold)


#=============================================================================


def thanModReverse(proj):
    "Reverses the orientation of the direction of lines."
    res = thanSelMultlines(proj, 1, T["Select lines to reverse orientation of direction\n"], strict=False)
    if res == Canc: return thanModCanc(proj)               # Reverse cancelled
    elems = proj[2].thanSelall
    selold = proj[2].thanSelold                            #FIXME:This makes nose enese since thaSelMultlines
                                                           #may call thanselectgen many times
    __modReverseDo(proj)
    proj[1].thanDoundo.thanAdd("reverse", thanModReverseRedo, (elems, ),
                                          thanModReverseUndo, (elems, selold))
    thanModEnd(proj)                                       # 'Reset color' is necessary here; OK!


def __modReverseDo(proj):
    "Rotates selected elements; it actualy does the job."
    import time
    t1 = time.time()                                             # nothing to do on the canvas
    t2 = time.time(); proj[1].thanReverseSel(proj[2].thanSelall) # ThanTouch is implicitely called
    t3 = time.time()
    print "Reverse time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t2-t1, t3-t2, t3-t1)


def thanModReverseRedo(proj, elems):
    "Re-rotates the previously un-rotated elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modReverseDo(proj, cc, phi)


def thanModReverseUndo(proj, elems, selold):
    "Un-rotates the oreviously rotated elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modReverseDo(proj)
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(selold)

#=============================================================================

def thanModExplode(proj):
    "Explodes elements to (1 level) smaller elements."
    res = thancomsel.thanSelectGen(proj, standalone=False)
    if res == Canc: return thanModCanc(proj)     # Explode was cancelled
    elems = proj[2].thanSelall
    selold = proj[2].thanSelold

    __modExplodeDo(proj)
#    proj[1].thanDoundo.thanAdd("rotate", thanModExplodeRedo, (elems, x1, y1, phi),
#                                         thanModExplodeUndo, (elems, x1, y1, phi, selold))
    thanModEnd(proj)   # 'Reset color' is not needed since the exploded fragments are redrawn. So..
                       # ..if a large number of elements are exploded, this will slow down..
           # the command. Here, there is room for optimisation!

def __modExplodeDo(proj):
    "Rotates selected elements; it actualy does the job."
    import time
    t1 = time.time(); proj[2].thanGudSetSelDel()
    t2 = time.time(); proj[1].thanExplodeSel(proj, proj[2].thanSelall) # ThanTouch is implicitely called
    t3 = time.time()
    print "Explode time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t2-t1, t3-t2, t3-t1)


def thanModExplodeRedo(proj, elems, xc, yc, phi):
    "Re-rotates the previously un-rotated elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modRotateDo(proj, xc, yc, phi)


def thanModExplodeUndo(proj, elems, xc, yc, phi, selold):
    "Un-rotates the oreviously rotated elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modRotateDo(proj, xc, yc, -phi)
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(selold)

#=============================================================================

def thanModJoin(proj):
    "Joins elements (lines) to bigger ones."
    res = thancomsel.thanSelectGen(proj, standalone=False)
    if res == Canc: return thanModCanc(proj)               # Rotation cancelled
    elems = proj[2].thanSelall
    selold = proj[2].thanSelold

    n = __modJoinDo(proj)
#    proj[1].thanDoundo.thanAdd("rotate", thanModJoinRedo, (elems, x1, y1, phi),
#                                         thanModJoinUndo, (elems, x1, y1, phi, selold))
    thanModEnd(proj, "%d joined lines were produced." % n)  # 'Reset color' is not needed..
                       # since the joined elements are redrawn. So if a large number of elements..
           # (unlikely)  are joined, this will slow down the command. Here,
           # there is room for optimisation!


def __modJoinDo(proj):
    "Rotates selected elements; it actualy does the job."
    import time
    t1 = time.time(); proj[2].thanGudSetSelDel()
    t2 = time.time(); n=proj[1].thanJoinSel(proj, proj[2].thanSelall) # ThanTouch is implicitely called
    t3 = time.time()
    print "Explode time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t2-t1, t3-t2, t3-t1)
    return n


def thanModJoinRedo(proj, elems, xc, yc, phi):
    "Re-rotates the previously un-rotated elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modRotateDo(proj, xc, yc, phi)


def thanModJoinUndo(proj, elems, xc, yc, phi, selold):
    "Un-rotates the oreviously rotated elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modRotateDo(proj, xc, yc, -phi)
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(selold)

#=============================================================================

def thanModChlayer(proj):
    "Changes the layer of selected elements."
    res = thancomsel.thanSelectGen(proj, standalone=False)
    if res == Canc: return thanModCanc(proj)               # Rotation cancelled
    elems = proj[2].thanSelall
    selold = proj[2].thanSelold

    res = proj[2].thanGudGetLayerleaf(T["Select new layer for the elements"])
    if res == Canc: return thanModCanc(proj)               # Rotation cancelled
    laynew = res

    __modChlayerDo(proj, laynew)
#    proj[1].thanDoundo.thanAdd("chlayer", thanModChlayerRedo, (elems, laynew),
#                                          thanModChlayerUndo, (elems, laynew, selold))
    thanModEnd(proj)         # 'Reset color' is necessary here (in fact, _it_ _is_ optimisation


def __modChlayerDo(proj, laynew):
    "Changes the layer of selected elements; it actualy does the job."
    import thanlayer, time
    t1 = time.time()
    if laynew.thanAtts["frozen"].thanVal:
        proj[2].thanGudSetSelDel()      # Deletes the canvas items, because the new layer is frozen
    else:
        tlays = set(elem.thanTags[1] for elem in proj[2].thanSelall)
        assert len(tlays) > 0, "How come that no layers were found, when there is at least one element????"
        dilay = proj[1].thanLayerTree.dilay
  draworder = False
        for tlay in tlays:             # Find only the attributes which differ (and thus they must be changed)
            lay = dilay[tlay]
      tagged = False
      for a in thanlayer.thanlayatts.thanLayAttsNames[2:]:   # We know that lay is NOT frozen (otherwise the elements could not be selected:) )
          nval = laynew.thanAtts[a].thanVal
          val = lay.thanAtts[a].thanAct
          if nval != val:
              if a == "moncolor":
            if False:  # Optimisation: Since thanGudResetSelColor will be called, no need to change colour now
          if not tagged: proj[2].thanGudGetSelLayerxs(lay.thanTag); tagged = True
                from thandefs.thanatt import ThanAttCol
                      proj[2].thanGudSetSelColorx(ThanAttCol(nval).thanTk)
              elif a == "draworder":
                  draworder = True
              elif a == "penthick":
                  pass              # Nothing visible changes
        proj[2].thanGudSetSelLayertag(laynew.thanTag)
        if draworder: proj[2].thanRedraw()
    t2 = time.time()

    for elem in proj[2].thanSelall:
        tags = list(elem.thanTags)
  lay = dilay[tags[1]]
        lay.thanQuad.remove(elem)
        laynew.thanQuad.add(elem)
  tags[1] = laynew.thanTag
  elem.thanTags = tuple(tags)
    proj[1].thanTouch()
    t3 = time.time()
    print "Change layer time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t2-t1, t3-t2, t3-t1)


def thanModChlayerRedo(proj, elems, laynew):
    "Re-rotates the previously un-rotated elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modRotateDo(proj, xc, yc, phi)


def thanModChlayerUndo(proj, elems, laynew, selold):
    "Un-rotates the oreviously rotated elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modRotateDo(proj, xc, yc, -phi)
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(selold)

#=============================================================================

def thanModScale(proj):
    """Scales selected elements.

    FIXME: The limits (area iterated) of the visible drawing are probably changed
    as well. It must be checked.
    """
    res = thancomsel.thanSelectGen(proj, standalone=False)
    if res == Canc: return thanModCanc(proj)               # Scale was cancelled
    elems = proj[2].thanSelall
    selold = proj[2].thanSelold

    c1 = proj[2].thanGudGetPoint(T["Origin of scale: "])
    if c1 == Canc: return thanModCanc(proj)                # Scale was cancelled
    fact = 1.0
    fact = proj[2].thanGudGetPosFloat(T["Scale factor: "], fact)
    if fact == Canc: return thanModCanc(proj)              # Scale was cancelled

    __modScaleDo(proj, c1, fact)
    proj[1].thanDoundo.thanAdd("scale", thanModScaleRedo, (elems, c1, fact),
                                        thanModScaleUndo, (elems, c1, fact, selold))
    thanModEnd(proj)                                       # 'Reset color' is necessary here


def __modScaleDo(proj, cc, fact):
    "Scales selected elements; it actualy does the job."
    import time       # thanScaleSel is called first, because thanGudSetSelScale call thanautoregen to re-render the images
    t1 = time.time(); proj[1].thanScaleSel(proj[2].thanSelall, cc, fact) # ThanTouch is implicitely called
    t2 = time.time(); proj[2].thanGudSetSelScale(cc[0], cc[1], fact)
    t3 = time.time()
    print "Scale time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t3-t2, t2-t1, t3-t1)

def thanModScaleRedo(proj, elems, cc, fact):
    "Re-scales the previously un-scaled elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modScaleDo(proj, cc, fact)


def thanModScaleUndo(proj, elems, cc, fact, selold):
    "Un-scales the oreviously scaled elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modScaleDo(proj, cc, 1.0/fact)
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(selold)

#=============================================================================

def thanModMove(proj):
    "Moves slelected elements."
    res = thancomsel.thanSelectGen(proj, standalone=False)
    if res == Canc: return thanModCanc(proj)               # Move was cancelled
    elems = proj[2].thanSelall
    selold = proj[2].thanSelold

    stat1 = T["Destination or <enter>: "]
#    n = proj[1].thanVar["dimensionality"]
#    dc = [0.0] * n
    res = proj[2].thanGudGetPoint(T["Origin or Delta coordinates: "])
    if res == Canc: return thanModCanc(proj)               # Move was cancelled
    dc = res
    res = proj[2].thanGudGetMovend(dc, stat1, options=("",))
    if res == Canc: return thanModCanc(proj)               # Move was cancelled
    if res != "":
        for i in xrange(len(dc)): dc[i] = res[i] - dc[i]

    __modMoveDo(proj, dc)
#    proj[1].thanDoundo.thanAdd("move", thanModMoveRedo, (elems, dc),
#                                       thanModMoveUndo, (elems, dc, selold))
    thanModEnd(proj)                                       # 'Reset color' is necessary here


def __modMoveDo(proj, dc):
    "Moves selected elements; it actualy does the job."
    import time
    t1 = time.time(); proj[2].thanGudSetSelMove(dc[0], dc[1])
    t2 = time.time(); proj[1].thanMoveSel(proj[2].thanSelall, dc)   # thanTouch is implicitely called
    t3 = time.time()
    print "Move time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t2-t1, t3-t2, t3-t1)


def thanModMoveRedo(proj, elems, cc, phi):
    "Re-rotates the previously un-rotated elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modRotateDo(proj, cc, phi)

#=============================================================================

def thanModCopy(proj):
    "Copies selected elements."
    res = thancomsel.thanSelectGen(proj, standalone=False)
    if res == Canc: return thanModCanc(proj)                # Copy was cancelled
    elems = proj[2].thanSelall
    selold = proj[2].thanSelold
    stat1 = T["Destination or <enter>: "]
    c1 = proj[2].thanGudGetPoint(T["Origin or Delta coordinates: "])
    if c1 == Canc: return thanModCanc(proj)                 # Copy was cancelled
    res = proj[2].thanGudGetMovend(c1, stat1, options=("",))
    if res == Canc: return thanModCanc(proj)                # Copy was cancelled
    if res == "":
        copelems = __modCopyDo(proj, elems, c1)
    else:
        dc = [b-a for a,b in izip(c1, res)]
        copelems = __modCopyDo(proj, elems, dc)
        while True:                                             # Copy multiple mode
            res = proj[2].thanGudGetMovend(c1, stat1, options=("",))
            if res == Canc or res == "": break                  # Copy is ended
            dc = [b-a for a,b in izip(c1, res)]
            e1 = __modCopyDo(proj, elems, dc)
      copelems.extend(e1)

    proj[1].thanDoundo.thanAdd("copy", thanModCopyRedo, (elems, copelems),
                                       thanModCopyUndo, (copelems, selold))
    thanModEnd(proj)                       # 'Reset color' is necessary here

def __modCopyDo(proj, elems, dc):
    "Copies selected elements; it actualy does the job."
    import time
    t1 = time.time(); copelems = proj[1].thanCopySel(elems, dc)   # thanTouch is implicitely called
    t2 = time.time(); proj[2].thanGudDrawElemsMany(copelems)
    t3 = time.time()
    print "Move time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t3-t2, t2-t1, t3-t1)
    return copelems

def thanModCopyRedo(proj, elems, copelems):
    "Recopies the previously uncopied elements."
    proj[1].thanElementRestore(copelems, proj)
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)

def thanModCopyUndo(proj, copelems, selold):
    "Uncopies the previously copied elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(copelems)
    __modEraseDo(proj)
    proj[2].thanGudSetSelElem(selold)

#=============================================================================

def thanModOffset(proj):
    "Offsets elements (1 by 1 to be compatible with thAtCad - WARNING CODE NOT FINISED."
    vdef = proj[1].thanVar["useroffsetdistance"]
    cdef = proj[1].thanUnits.strdis(vdef)
    mes = "%s (%s/<%s>): " % (T["Distance to offset"], T["Through point"], cdef)
    dis = proj[2].thanGudGetPosFloat(mes, default=vdef, options=("through",))
    if dis == Canc: return thanModCanc(proj)                # Offset cancelled
    while True:
        elem = thanSelect1(T["Select element to offset: "], options=("",))
        if elem == Canc: return thanModCanc(proj)               # Offset cancelled
        if elem == "": return thanModEnd(proj)                  # Offset ended
        if dis == "t":
            ct = proj[2].thanGudGetPoint(T["Through point: "])
            if ct == Canc: continue                             # Offset of _this_ element was cancelled
        else:
            proj[1].thanVar["useroffsetdistance"] = dis         # Set new default only if user did not cancel
            ct = proj[2].thanGudGetPoint(T["Choose direction of offset: "])
            if ct == Canc: continue                             # Offset of _this_ element was cancelled


    res = thancomsel.thanSelectGen(proj, standalone=False)
    if res == Canc: return thanModCanc(proj)               # Mirror cancelled
    elems = proj[2].thanSelall
    selold = proj[2].thanSelold

    c1 = proj[2].thanGudGetPoint(T["First point of mirror line: "])
    if c1 == Canc: return thanModCanc(proj)                # Mirror cancelled
    while True:
        c2 = proj[2].thanGudGetLine(c1, T["Second point of mirror line: "])
        if c2 == Canc: return thanModCanc(proj)            # Mirror cancelled
        if not thanNear2(c1, c2): break
        proj[2].thanCom.thanAppend("Second point coincides with first. Try again.\n", "can")
    keeporig = proj[2].thanGudGetYesno(T["Keep original elements (<yes>/no): "], default="yes")
    if keeporig == Canc: return thanModCanc(proj)               # Mirror cancelled
    t = [c2[0]-c1[0], c2[1]-c1[1]]
    tt = hypot(t[0], t[1])
    t[0] /= tt
    t[1] /= tt
    if keeporig:
        dc = [0.0]*len(c1)
        copelems = __modMirrorCopyDo(proj, elems, c1, t)
        proj[1].thanDoundo.thanAdd("mirror", thanModCopyRedo, (elems, copelems),
                                             thanModCopyUndo, (copelems, selold))
    else:
        __modMirrorDo(proj, c1, t)
        proj[1].thanDoundo.thanAdd("mirror", thanModMirrorRedo, (elems, c1, t),
                                             thanModMirrorUndo, (elems, c1, t, selold))
    thanModEnd(proj)       # 'Reset color' is necessary here; OK!


def __modMirrorCopyDo(proj, elems, c1, t):
    "Copies selected elements; it actualy does the job."
    import time
    t1 = time.time();
    dc = [0.0]*len(c1)
    copelems = proj[1].thanCopySel(elems, dc)   # thanTouch is implicitely called
    proj[1].thanMirrorSel(copelems, c1, t)
    t2 = time.time(); proj[2].thanGudDrawElemsMany(copelems)
    t3 = time.time()
    print "Mirror time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t3-t2, t2-t1, t3-t1)
    return copelems


def __modMirrorDo(proj, c1, t):
    "Mirrors selected elements; it actualy does the job."
    import time
    t1 = time.time(); proj[2].thanGudSetSelMirror(c1[0], c1[1], t)
    t2 = time.time(); proj[1].thanMirrorSel(proj[2].thanSelall, c1, t) # ThanTouch is implicitely called
    t3 = time.time()
    print "Mirror time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t2-t1, t3-t2, t3-t1)


def thanModMirrorRedo(proj, elems, c1, t):
    "Re-mirrors the previously un-mirrored elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modMirrorDo(proj, c1, t)


def thanModMirrorUndo(proj, elems, c1, t, selold):
    "Un-mirrors the previously mirrored elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modMirrorDo(proj, c1, t)
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(selold)

#=============================================================================

def thanModDDedit(proj):
    "Prompts the user to alter the text of a ThanText object."
    from thandr import ThanText
    first = True
    while True:
        elem = thancomsel.thanSelect1(proj, T["Select text to edit: "], filter=lambda e: isinstance(e, ThanText))
        if elem == Canc:
            if first: return thanModCanc(proj)            # DDedit cancelled
            else: break                                   # DDedit ended
        textold = elem.text
        textnew = proj[2].thanGudGetText1(T["Edit text"], textDefault=textold)
        if textnew == Canc: continue                      # DDedit of this text was cancelled; ask for other
        elems = [elem]
        selold = proj[2].thanSelold

        __modDDeditDo(proj, elem, textnew)
        proj[1].thanDoundo.thanAdd("ddedit", thanModDDeditRedo, (elems, textnew),
                                             thanModDDeditUndo, (elems, textold, selold))
        first = False
    thanModEnd(proj, "")


def __modDDeditDo(proj, elem, text):
    "Rotates selected elements; it actualy does the job."
    than = proj[2].than
    lt = proj[1].thanLayerTree
    thanCur1 = lt.thanCur
    dilay = lt.dilay
    lay = dilay[elem.thanTags[1]]
    if lay != thanCur1: lay.thanTkSet(than, proj[1].thanTstyles)

    elem.thanSet(text, elem.c1, elem.size, elem.theta)
    proj[2].thanGudSetSelDel()                         # Delete the text from the canvas
    elem.thanTkDraw(than)                              # Draw the new text

    if lay != thanCur1: thanCur1.thanTkSet(than, proj[1].thanTstyles)
    proj[1].thanTouch()


def thanModDDeditRedo(proj, elems, text):
    "Re-rotates the previously un-rotated elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modDDeditDo(proj, elems[0], text)


def thanModDDeditUndo(proj, elems, textold, selold):
    "Un-rotates the previously rotated elements."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modDDeditDo(proj, elems[0], textold)
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(selold)


#=============================================================================

def thanModErase(proj):
    "Erases selected elements."
    res = thancomsel.thanSelectGen(proj, standalone=False)
    if res == Canc: return thanModCanc(proj)               # Erase was cancelled
    elems = proj[2].thanSelall
    selold = proj[2].thanSelold
    __modEraseDo(proj)
    proj[1].thanDoundo.thanAdd("erase", thanModEraseRedo, (elems,),
                                        thanModEraseUndo, (elems, selold))
    thanModEnd(proj)           # 'Reset color' is completely unnecessary here, and it will slow..
                               # ..e command down. Room for optimisation here.

def __modEraseDo(proj):
    "Erases selected elements; it actualy does the job."
    import time
    t1 = time.time(); proj[2].thanGudSetSelDel()
    t2 = time.time(); proj[1].thanDelSel(proj[2].thanSelall)        # thanTouch is implicitely called
    t3 = time.time()
    print "Erase time: canvas=%.2f   elements=%.2f   sum=%.2f (secs)" % (t2-t1, t3-t2, t3-t1)
    proj[2].thanGudSetSelClear()


def thanModEraseRedo(proj, elems):
    "Erases selected elements; it actualy does the job."
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(elems)
    __modEraseDo(proj)


def thanModEraseUndo(proj, elems, selold):
    "UnErases elements; elements' structure is considered complete."
    proj[1].thanElementRestore(elems, proj)
    proj[2].thanGudSetSelClear()
    proj[2].thanGudSetSelElem(selold)

#=============================================================================

def thanModPurge(proj):
    "Purges unused declarations; for the moment unused layer declarations (but not the currrent and its parents)."
    lt = proj[1].thanLayerTree
    cl = proj[1].thanLayerTree.thanCur
    cl.thanQuad.add(None)       # Make current layer non Empty
    delnot = set((lt.thanRoot, lt.thanRoot.thanChildren[0]))   # Layers which must not be deleted
    delyes = set()                             # Layers that are going to deleted
    try:
        emptyFound = __purgeLay(proj, lt.thanRoot, delnot, delyes)
    except ThanLayerError:
        cl.thanQuad.remove(None)
        return thanModCanc(proj)                   # user cancelled purge

    if not emptyFound:
        cl.thanQuad.remove(None)
        return proj[2].thanGudCommandEnd("No unused layers.")
    if len(delyes) == 0:
        cl.thanQuad.remove(None)
        return proj[2].thanGudCommandEnd("No layers were purged.")

    for chlay in delyes:
        lay = chlay.thanParent
        chlay.thanUnlink()        # remove chlay and hierarchy from parent's children
        chlay.thanDestroy()       # Delete chaly and hierarchy
        if len(lay.thanChildren) == 0:     # This is leaf layer now; it can hold elements
            lay.thanQuad = set()
            lay.thanTag = lay.lt.thanIdLay.new()  # In order to exploit TK mechanism
    cl.thanQuad.remove(None)
    lt.thanDictRebuild()          # Inform about the new leaf layers
    proj[1].thanTouch()           # Drawinh has been modified
    proj[2].thanGudCommandEnd()   # thanModEnd() does not carry a benefit here; no elements were selected..


def __purgeLay(proj, lay, delnot, delyes):
    "Ask recursively the empty layers to be deleted."
    emptyFound = False
    for chlay in lay.thanChildren:
        if chlay in delnot: continue           # These layers can not be deleted
  if not chlay.thanIsEmpty(): continue   # Layer not empty
  emptyFound = True
        ans = proj[2].thanGudGetYesno(T["Delete empty layer %s (enter=no): "] %
      chlay.thanGetPathname(), default="no")
  if ans == Canc: raise ThanLayerError, "User cancelled purge"
  if ans: delyes.add(chlay)
    for chlay in lay.thanChildren:
        if chlay in delyes: continue           # Already marked for deletion
  emptyFound1 = __purgeLay(proj, chlay, delnot, delyes)
  emptyFound = emptyFound or emptyFound1
    return emptyFound


#=============================================================================

def thanModFilet(proj):
    "Xtends and joins 2 line segments with circular arc."
    res = thanSel2linsegs(proj, T["Select two sinle segment lines to filet:\n"])
    if res == Canc: return thanModCanc(proj)               # Filet was cancelled
    aa, bb = proj[2].thanSelall
    a, b = aa.thanClone(), bb.thanClone()
    rr = 5.0
    ierr, obj = thanFiletCalc(a, b, rr)
    if ierr == 1: return thanModCanc(T["End lines are parallel and do not intersect"])
    if ierr == 2: return thanModCanc(T["Circular arc lies beyond the line segments"])
    assert ierr == 0
    a.thanTags = aa.thanTags
    b.thanTags = bb.thanTags

    elems = proj[2].thanSelall
    selold = proj[2].thanSelold
    __modFiletDo(proj, a, b, obj)
#    proj[1].thanDoundo.thanAdd("filet", thanModEraseRedo, (elems,),
#                                        thanModEraseUndo, (elems, selold))
    thanModEnd(proj)           # 'Reset color' is completely unnecessary here, and it will slow..
                               # ..e command down. Room for optimisation here.

def __modFiletDo(proj, a, b, obj):
    "Erases selected elements; it actualy does the job."
    import time
    from thandr import ThanArc
    proj[2].thanGudSetSelDel()
    a.thanTkDraw(proj[2].than)
    b.thanTkDraw(proj[2].than)
    if obj == None: return
    arc = ThanArc()
    arc.thanSet(*obj)
    proj[1].thanElementAdd(a)
    arc.thanTkDraw(proj[2].than)


#def __sel2lines(proj):
#    "Selects 2 lines to filet."
#    from thandr import ThanLine
#    while True:
#        elems = []
#        proj[2].thanCom.thanAppend(T["Select two sinle segment lines to filet:\n"], "info1")
#        res = thancomsel.thanSelectGen(proj, standalone=False)
#        proj[2].thanGudResetSelColor()
#  if res == Canc: return Canc
#        for elem in proj[2].thanSelall:
#            if isinstance(elem, ThanLine) and len(elem.cp) == 2: elems.append(elem)
#  if len(elems) == 2: break
#        proj[2].thanCom.thanAppend(T["Two single segment line is required (%d found). Try again.\n"]%len(elems), "can")
#    return True
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.