thandwg.py :  » Business-Application » ThanCad » thancad-0.0.9 » thandr » 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 » thandr » thandwg.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.

This module defines a ThanCad drawing, which contains elements, has layers,
viewports, etc."
"""

import weakref
from math import fabs
import p_ggen
from p_gmath import thanNear3
import thanfonts, thandefs
from thanlayer import ThanLayerTree,THANNAME
from thanvar import ThanId,ThanRectCoorTransf
from thanelem import ThanElement
from thanline import ThanLine
from thantext import ThanText
from thanpoint import ThanPoint
from thanroad import ThanRoad

class ThanDoundo:
    "Implements the undo/redo scheme."

    def __init__(self):
        self.__doundo = []
  self.__i = 0

    def thanAdd(self, text, redoFun, redoArgs, undoFun, undoArgs):
        "A new command (or task) to undo/redo."
  del self.__doundo[self.__i:]
  self.__doundo.append((text, redoFun, redoArgs, undoFun, undoArgs))
  self.__i = len(self.__doundo)

    def thanRedo(self, proj):
        "Redoes previously 'undone' command/task."
  assert self.__i < len(self.__doundo), "Nothing left to redo"
  redoFun, redoArgs = self.__doundo[self.__i][1:3]
  redoFun(proj, *redoArgs)
  self.__i += 1

    def thanUndo(self, proj):
        "Undoes previous command/task."
  assert self.__i > 0, "Nothing left to undo"
  undoFun, undoArgs = self.__doundo[self.__i-1][3:5]
  undoFun(proj, *undoArgs)
  self.__i -= 1

    def thanRedotry(self):
        "Finds out if redo is possible; returns command's text if possible."
  if self.__i >= len(self.__doundo): return None  # Nothing left to redo
  return self.__doundo[self.__i][0]

    def thanUndotry(self):
        "Finds out if undo is possible; returns command's text if possible."
  if self.__i <= 0: return None                   # Nothing left to undo
  return self.__doundo[self.__i-1][0]


############################################################################
############################################################################


class ThanTagel(dict):
    "A dictionary with predefined/readonly items."

    rdlist = frozenset(("e0", "edrag", "enull"))
    __slots__ = ()

    def __init__(self, *args, **kw):
        "Set predefined items, if not already in args/kw."
        dict.__init__(self, *args, **kw)
  temp = ThanElement() # Null element: This is to ensure that temporary elemenmts..
                       # ..do not lead to KeyError, and do all operations passively
        for key in self.rdlist:
      self.setdefault(key, temp)

    def __delitem__(self, key):
        "Do not delete readonly items."
        if key in self.rdlist: return
  dict.__delitem__(self, key)


    def __setitem__(self, key, val):
        "Do not delete readonly items."
        if key in self.rdlist: raise KeyError, "Readonly item: key: %s" % key
  dict.__setitem__(self, key, val)


############################################################################
############################################################################

class ThanDrawing:
    "Represents a whole drawing."

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

    def __init__ (self):
        "Creates a new drawing instance."
        self.viewPort = [-10.0, -10.0, 100.0, 100.0]
  self.thanAreaIterated = (None, None, None, None)       # No element -> no limit in regen
  self.xMinAct = self.yMinAct = self.xMaxAct = self.yMaxAct = None

  self.thanLayerTree = ThanLayerTree()
  t = thandefs.ThanTstyle("standard", thanfonts.thanFonts["thanprime1"])
  self.thanTstyles = {t.thanName: t}
  self.thanLtypes = {}
  self.__idTag = ThanId(prefix="E")
  self.thanTagel = ThanTagel()
  self.thanUnits = thandefs.ThanUnits()
  self.thanDoundo = ThanDoundo()
  self.__variables()
  self.thanEdus = weakref.WeakKeyDictionary()
  self.__modified = False
  self.thanPrevLine = weakref.ref(p_ggen.Struct())    # An invalid weak reference
        self.thanDtm = None
        self.thanTri = None      # Triangulation

    def __variables(self):
        "Set ThanCad variables."
        self.thanVar = {}
        n = self.thanVar["dimensionality"] = 3  # Number of dimensions a node has
        self.thanVar["elevation"] = [0.0]*n     # Elevation - limited n-dimensional support
        self.thanVar["thickness"] = [0.0]*n     # Thickness - limited n-dimensional support
        self.thanVar["insbase"]   = [0.0]*n     # Insertion point of the drawing (as block)
        self.thanVar["imageframe"]= ["on"]      # If false, the bounding rectangles of images are not displayed
        self.thanVar["useroffsetdistance"] = 1.0  # Default distance for the offset command


    def __getstate__(self):
        odict = self.__dict__.copy()
  del odict["thanPrevLine"]         # Do not save weak reference (it can be built again)
        odict["thanEdus"] = odict["thanEdus"].keys()
  return odict

    def __setstate__(self, odict):
        self.__dict__.update(odict)
  self.thanPrevLine = weakref.ref(p_ggen.Struct())    # Recreate an invalid weak reference
  c = self.thanEdus
  self.thanEdus = weakref.WeakKeyDictionary()
  for e in c: self.thanEdus[e] = True

    def thanDestroy(self):
        "Destroy circular references."
  self.thanLayerTree.thanDestroy()
  del self.thanDoundo

    def thanAfterPickle(self):
        """Initialise a drawing after it is unpickled (load from a file).

        The only thing that has to be done is a regen, which will redefine
  thanAreaIterated and xyminmaxact.
  """
  pass


    def thanElementAdd(self, elem):
        "Adds an element to the drawing."
        cl = self.thanLayerTree.thanCur
  tag = self.__idTag.new()
  if elem.thanTkCompound > 1:
      elem.thanTags = tag, cl.thanTag
  else:
      elem.thanTags = tag, cl.thanTag, "nocomp"     # Not a compound element
        self.__elementAddHouse(elem, cl)


    def __elementAddHouse(self, elem, cl):
        """Do housekeeping for the new element.

  Since the new element is drawn (if not frozen) thanAreaIterated is unchanged.
  """
  self.thanTagel[elem.thanTags[0]] = elem
        cl.thanQuad.add(elem)
        if not cl.thanAtts["frozen"].thanVal:
      if self.xMinAct == None:
          self.xMinAct = elem.thanXymm[0]
          self.yMinAct = elem.thanXymm[1]
          self.xMaxAct = elem.thanXymm[2]
          self.yMaxAct = elem.thanXymm[3]
      else:
          if elem.thanXymm[0] < self.xMinAct: self.xMinAct = elem.thanXymm[0]
          if elem.thanXymm[1] < self.yMinAct: self.yMinAct = elem.thanXymm[1]
          if elem.thanXymm[2] > self.xMaxAct: self.xMaxAct = elem.thanXymm[2]
          if elem.thanXymm[3] > self.yMaxAct: self.yMaxAct = elem.thanXymm[3]
  self.__modified = True

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

    def thanTkDraw(self, than, lays="all"):
        """Draws the active elements (inside the viewport) into a gui window.

  Active are the elements which do not belong to a layer which is 'off'.
  This function checks each element of ThanDrawing and if it, or part of it,
  is inside the viewport (which is just a rectangle), draws it into 'win'.
  Thus, in general, 'win' has less elements than ThanDrawing.
  'win' has all the elements that are, at least partialy, inside viewport.

      If we assume that all elements of ThanDrawing are partialy inside
  viewport, then 'win' has actually all ThanDrawing's elements, even
  though viewport is smaller than the viewport that fully covers all
  the elements.
      It is also possible that 'win' does not have all ThanDrawing's elements,
  but all elements that are covered by a bigger rectangle than viewport.
  This bigger rectangle is called 'thanAreaIterated'. 'thanAreaIterated' is
  the rectangle which is smaller (i.e. it does not cover) any part of the
  elements not drawn.
      'thanAreaIterated' is quite useful because if the user pans or zooms
  the drawing, the new viewport may be inside  'thanAreaIterated'. It is
  thus not necessary to redraw (actualy regenerate) the elements, since
  these elements are already in 'win'. All that is needed is that 'win'
  pans or zooms its elements, which is usually much faster.
      This feature is so useful that when thanDraw is called, it draws the
  elements of a rectangle 5 (or 25) times bigger than the viewport, so
  that pan and zoom can be done faster.

      Another concept, completely unrelated to the above, is the smallest
  rectangle 'xyMinMaxAct', which covers all the active elements of
  ThanDrawing. This is needed when the user wants to zoom all.
      xyMinMaxAct are the x and y min and max of the active elements
  (elements of the visible layers). When a drawing is read, 'xyMinMaxAct'
  is computed. When an element is added, 'xyMinMaxAct' is updated.
  When a layer is turned on, all its elements are checked, to see if
  they are inside the viewport, and xyMinMaxAct is updated.
      However, when an element is deleted, and its rectangle share at
  least one edje with xyMinMaxAct, then xyMinMaxAct may no longer be valid.
  It will always cover all the active elements, but it may not be the
  smaller  rectangle which covers all the elements.
      Since thanDraw iterates through all visible elements, xyMinMaxAct
  is also computed.
      When a user zooms all, and xyMinMaxAct is within thanAreaIterated,
  thanDraw() is not called. However, it should be possible to ask the gui
  window for its version of xyMinMaxAct, and pass it here.
  """

  self.thanAreaIterated = (1, 1, -1, -1)                            # Set as invalid in case user aborts
  self.xMinAct = self.yMinAct = self.xMaxAct = self.yMaxAct = None  # Set as invalid in case user aborts
        xymm = self.viewPort
  dx = xymm[2] - xymm[0]
  dy = xymm[3] - xymm[1]
  xymm = [xymm[0]-2*dx, xymm[1]-2*dy, xymm[2]+2*dx, xymm[3]+2*dy]   # xymm is a new list now: not viewPort.thanXymm

#------Initialise min,max with first element

        if lays == "all": lays = self.thanLayerTree.dilay.values()
        lays = [(lay.thanAtts["draworder"].thanVal, lay) for lay in lays]
        lays.sort()
  lays = [lay for i,lay in lays]
        for lay in lays:
      if lay.thanAtts["frozen"].thanVal: continue
            for e in lay.thanQuad:
          self.xMinAct = e.thanXymm[0]
          self.yMinAct = e.thanXymm[1]
          self.xMaxAct = e.thanXymm[2]
          self.yMaxAct = e.thanXymm[3]
    break
      else: continue
      break
  else:
      print "no elements found in active layers"
            self.thanAreaIterated = (None, None, None, None)    # No limit in all directions
      self.xMinAct = self.yMinAct = self.xMaxAct = self.yMaxAct = None
      return    # Drawing has no elements in active layers

#-------Now iterate through all elements of active layers

        for lay in lays:
      if lay.thanAtts["frozen"].thanVal: continue
      lay.thanTkSet(than, self.thanTstyles)
            for e in lay.thanQuad:
          if e.thanXymm[0] < self.xMinAct: self.xMinAct = e.thanXymm[0]
          if e.thanXymm[1] < self.yMinAct: self.yMinAct = e.thanXymm[1]
          if e.thanXymm[2] > self.xMaxAct: self.xMaxAct = e.thanXymm[2]
          if e.thanXymm[3] > self.yMaxAct: self.yMaxAct = e.thanXymm[3]
                if e.thanInbox(xymm): e.thanTkDraw(than)

#-------Compute limits of thanAreaIterated

        if xymm[0] <= self.xMinAct: xymm[0] = None
        if xymm[1] <= self.yMinAct: xymm[1] = None
        if xymm[2] >= self.xMaxAct: xymm[2] = None
        if xymm[3] >= self.yMaxAct: xymm[3] = None
  self.thanAreaIterated = tuple(xymm)
  self.thanLayerTree.thanCur.thanTkSet(than, self.thanTstyles)

    def thanTkHiwin(self, than):
        "Lengthens (a little) very small elements so that they become visible."
  seen = set()
  tagel = self.thanTagel
  dc = than.dc
  for item in dc.find_all():
      tags = dc.gettags(item)
      if not tags: continue             # Sentinel elements
      titem = tags[0]
      if titem[0] != "E": continue      # not a ThanCad Element
      if titem in seen: continue
      print "titem=", titem
      seen.add(titem)
      el = tagel[titem]
      el.thanTkHiwin(than)

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

    def thanMoveSel(self, elems, dc):
        "Moves the selected elements."
  if all(dc1==0.0 for dc1 in dc): return
        for e in elems:
      e.thanMove(dc)
      if e.thanXymm[0] < self.xMinAct: self.xMinAct = e.thanXymm[0]
      if e.thanXymm[1] < self.yMinAct: self.yMinAct = e.thanXymm[1]
      if e.thanXymm[2] > self.xMaxAct: self.xMaxAct = e.thanXymm[2]
      if e.thanXymm[3] > self.yMaxAct: self.yMaxAct = e.thanXymm[3]
  self.thanTouch()

    def thanCopySel(self, elems, dc):
        "Copies the selected elements with offset."
        lt = self.thanLayerTree
        thanCur1 = lt.thanCur
        dilay = lt.dilay
        copelems = []
        for e in elems:
            lt.thanCur = dilay[e.thanTags[1]]
            e1 = e.thanClone()
            e1.thanMove(dc)
            self.thanElementAdd(e1)
            copelems.append(e1)
        lt.thanCur = thanCur1
        self.thanTouch()
        return copelems

    def thanRotateSel(self, elems, cc, phi):
        "Rotates the selected elements."
        if phi == 0.0: return
        ThanElement.thanRotateSet(cc, phi)
        for e in elems:
            e.thanRotate()
            if e.thanXymm[0] < self.xMinAct: self.xMinAct = e.thanXymm[0]
            if e.thanXymm[1] < self.yMinAct: self.yMinAct = e.thanXymm[1]
            if e.thanXymm[2] > self.xMaxAct: self.xMaxAct = e.thanXymm[2]
            if e.thanXymm[3] > self.yMaxAct: self.yMaxAct = e.thanXymm[3]
        self.thanTouch()


    def thanMirrorSel(self, elems, c1, t):
        "Mirrors the selected elements."
        ThanElement.thanMirrorSet(c1, t)
        for e in elems:
            e.thanMirror()
            if e.thanXymm[0] < self.xMinAct: self.xMinAct = e.thanXymm[0]
            if e.thanXymm[1] < self.yMinAct: self.yMinAct = e.thanXymm[1]
            if e.thanXymm[2] > self.xMaxAct: self.xMaxAct = e.thanXymm[2]
            if e.thanXymm[3] > self.yMaxAct: self.yMaxAct = e.thanXymm[3]
        self.thanTouch()


    def thanReverseSel(self, elems):
        "Reverses the orientation of the direction of lines."
        for e in elems:
            assert isinstance(e, ThanLine), "thanReverseSel work only for lines"
            e.cp.reverse()
        self.thanTouch()


    def thanExplodeSel(self, proj, elems):
        "Explodes the selected elements."
  than = proj[2].than
  lt = proj[1].thanLayerTree
  thanCur1 = lt.thanCur
  dilay = lt.dilay
        for e in elems:
      if isinstance(e, ThanLine):
          lay = dilay[e.thanTags[1]]
    if lay != lt.thanCur:
        lay.thanTkSet(than, proj[1].thanTstyles)
        lt.thanCur = lay
    lay.thanQuad.remove(e)
    for i in xrange(1, len(e.cp)):
        e1 = ThanLine()
        e1.thanSet(e.cp[i-1:i+1])
        if e1.thanIsNormal():
            self.thanElementAdd(e1)
            e1.thanTkDraw(than)
  lay = thanCur1
  if lay != lt.thanCur:
      lay.thanTkSet(than, proj[1].thanTstyles)
      lt.thanCur = lay
  self.thanTouch()


    def thanReplaceSel(self, proj, e, e1, e2):
        "Replace e with e1 and e2, if e1 and q2 are not both None."
  if e1 == None and e2 == None:
      proj[2].thanCom.thanAppend(T["Element can not be deleted; use 'ERASE'."], "can")
      return
        than = proj[2].than
  lt = proj[1].thanLayerTree
  thanCur1 = lt.thanCur
  dilay = lt.dilay

  lay = dilay[e.thanTags[1]]
  if lay != lt.thanCur:
      lay.thanTkSet(than, proj[1].thanTstyles)
      lt.thanCur = lay
  lay.thanQuad.remove(e)
  if e1 != None: self.thanElementAdd(e1); e1.thanTkDraw(than)
  if e2 != None: self.thanElementAdd(e2); e2.thanTkDraw(than)

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


    def thanOffsetSel(self, proj, e, dis, removeoriginal=False):
        "Offsets an element by distance dis."
  than = proj[2].than
  lt = proj[1].thanLayerTree
  thanCur1 = lt.thanCur
  dilay = lt.dilay

  e1 = e.thanOffset(dis)
  lay = dilay[e.thanTags[1]]
  if lay != lt.thanCur:
      lay.thanTkSet(than, proj[1].thanTstyles)
      lt.thanCur = lay
  if removeoriginal: lay.thanQuad.remove(e)
  if e1 != None: self.thanElementAdd(e1); e1.thanTkDraw(than)

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


    def thanJoinSel(self, proj, elems):
        "Joins consecutive lines to 1 bigger line."
  than = proj[2].than
  lt = proj[1].thanLayerTree
  thanCur1 = lt.thanCur
  dilay = lt.dilay
  lines = set(e for e in elems if isinstance(e, ThanLine))
  joinedlines = 0
  while len(lines) > 0:
            e = lines.pop()
      cbeg = e.cp[0]
      cend = e.cp[-1]
      for e1 in lines:
          if thanNear3(cbeg, e1.cp[0]):
         lay = dilay[e1.thanTags[1]]
         lay.thanQuad.remove(e1)
         lines.remove(e1)
         e1.cp.reverse(); e1.cp.pop()
         e1.cp.extend(e.cp)
         e.cp[:] = e1.cp
         lines.add(e)
         break
          elif thanNear3(cbeg, e1.cp[-1]):
         lay = dilay[e1.thanTags[1]]
         lay.thanQuad.remove(e1)
         lines.remove(e1)
         e1.cp.pop()
         e1.cp.extend(e.cp)
         e.cp[:] = e1.cp
         lines.add(e)
         break
          elif thanNear3(cend, e1.cp[0]):
         lay = dilay[e1.thanTags[1]]
         lay.thanQuad.remove(e1)
         lines.remove(e1)
         e1.cp.pop(0)
         e.cp.extend(e1.cp)
         lines.add(e)
         break
          elif thanNear3(cend, e1.cp[-1]):
         lay = dilay[e1.thanTags[1]]
         lay.thanQuad.remove(e1)
         lines.remove(e1)
         e1.cp.reverse(); e1.cp.pop(0)
         e.cp.extend(e1.cp)
         lines.add(e)
         break
      else:
          joinedlines += 1
          lay = dilay[e.thanTags[1]]
    if lay != lt.thanCur:
        lay.thanTkSet(than, proj[1].thanTstyles)
        lt.thanCur = lay
    e.thanTkDraw(than)
  lay = thanCur1
  if lay != lt.thanCur:
      lay.thanTkSet(than, proj[1].thanTstyles)
      lt.thanCur = lay
  self.thanTouch()
  return joinedlines


    def thanScaleSel(self, elems, cc, fact):
        "Scales the selected elements."
  if fact == 1.0: return
        for e in elems:
      e.thanScale(cc, fact)
      if e.thanXymm[0] < self.xMinAct: self.xMinAct = e.thanXymm[0]
      if e.thanXymm[1] < self.yMinAct: self.yMinAct = e.thanXymm[1]
      if e.thanXymm[2] > self.xMaxAct: self.xMaxAct = e.thanXymm[2]
      if e.thanXymm[3] > self.yMaxAct: self.yMaxAct = e.thanXymm[3]
  self.thanTouch()

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

    def thanDelSel(self, elems):
        "Deletes elements from the drawing as simply as possible."
        taglay = self.thanLayerTree.dilay
  for e in elems:
            lay = taglay[e.thanTags[1]]
            lay.thanQuad.remove(e)
      del self.thanTagel[e.thanTags[0]]
  self.thanTouch()


    def thanDelSelMany(self, elems):
        """Deletes a large number of elements efficiently from the drawing.

  This should be faster if the number of elements to delete are,
  say, over 10000. Again, this is not certain without actual test.
  """
        taglay = self.thanLayerTree.dilay
  elay = {}
  for e in elems:
      elay.setdefault(e.thanTags[1], set()).add(e)
      del self.thanTagel[e.thanTags[0]]
  for tlay,eset in elay.iteritems():
      lay = taglay[tlay]
      lay.thanQuad -= eset
  self.thanTouch()


    def thanElementRestore(self, elems, proj):
        """Restores previously deleted elements as simply as possible.

  It is assumed that the elements' structure is already in legal state, and that
  the layer they belong to is also in legal state.
  FIXME: maybe it will be faster to sort by layer first, and call lay.thanTkSet
  less times.
        """
  taglay = self.thanLayerTree.dilay
  than = proj[2].than
  for e in elems:
      lay = taglay[e.thanTags[1]]
      lay.thanTkSet(than, self.thanTstyles)
      self.__elementAddHouse(e, lay)
      if not lay.thanAtts["frozen"].thanVal: e.thanTkDraw(than)
  self.thanTouch()
  self.thanLayerTree.thanCur.thanTkSet(than, self.thanTstyles)


    def thanElementDelete(self, elems, proj):
        "Deletes elements from the drawing and canvas as simply as possible, leaving structures intact."
        taglay = self.thanLayerTree.dilay
  dc = proj[2].thanCanvas
  for e in elems:
            lay = taglay[e.thanTags[1]]
            lay.thanQuad.remove(e)
      dc.delete(e.thanTags[0])
  self.thanTouch()

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

    def thanIsModified(self):
        "Returns true if drawing has been modified since last save."
        return self.__modified
    def thanResetModified(self):
        "Informs that drawing has just been saved or read and so it is unmodified."
        self.__modified = 0
    def thanTouch(self):
        "Make the drawing as it it were modified."
        self.__modified = True

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

    def thanExpDxf(self, dxf, fout):
        "Exports all the elements of the drawing to dxf file."
        dxf.thanDxfPlots1(fout, vars=self.__calcVars())
        dxf.thanDxfTableDef (' ', 0)

        dxf.thanDxfTableDef('LAYER', 1)
        self.thanLayerTree.thanExpDxf(dxf)        # export layers

        dxf.thanDxfTableDef('ENTITIES', 1)
        for lay in self.thanLayerTree.dilay.itervalues():
            dxf.thanDxfSetLayer(lay.thanGetPathname("__"))
            for e in lay.thanQuad:
                e.thanExpDxf(dxf)


    def __calcVars(self):
        "Determine the values of dxf variables."
        lays = [self.thanLayerTree.thanRoot]
        leaflayers = []
        while len(lays) > 0:
            lay = lays.pop(0)
            if len(lay.thanChildren) > 0: lays.extend(lay.thanChildren)
            else:                         leaflayers.append(lay)
        vars = []
        nfillon = 0
        for lay in leaflayers:
            ia = lay.thanAtts["fill"]
            if ia.thanVal: nfillon += 1
            print "fill.thanVal=", ia.thanVal
            print "nfillon =", nfillon
        if nfillon == len(leaflayers): vars.append(("$FILLMODE", 70, 1))
        else:                          vars.append(("$FILLMODE", 70, 0))
        return vars


    def thanExpSyk(self, fSyk):
        "Exports all the linear elements of the drawing to syk file."
        than = p_ggen.Struct("ThanCad .syk file and options container")
  than.write = fSyk.write
        for lay in self.thanLayerTree.dilay.itervalues():
            than.layname = lay.thanGetPathname("__")
            for e in lay.thanQuad:
                e.thanExpSyk(than)


    def thanExpBrk(self, fSyk):
        "Exports all the linear elements of the drawing to brk file."
        than = p_ggen.Struct("ThanCad .brk file and options container")
  than.write = fSyk.write
  than.ibr = 0
  than.form = "THC%07d%15.3f%15.3f%15.3f\n"
        for lay in self.thanLayerTree.dilay.itervalues():
            than.layname = lay.thanGetPathname("__")
            for e in lay.thanQuad:
                e.thanExpBrk(than)

    def thanPlotPdf(self, scale):
        "Plots all elements of the drawing to pdf file."
  import pyx
        than = p_ggen.Struct("ThanCad .pdf file and options container")
  than.dc = pyx.canvas.canvas()
  than.ct = ThanRectCoorTransf()
  x1 = y1 = 0.0
  x2 = y2 = 1.0
  than.ct.set((x1, y1, x2, y2), (0, 0, (x2-x1)*scale, (y2-y1)*scale))
        for lay in self.thanLayerTree.dilay.itervalues():
      lay.thanPdfSet(than, self.thanTstyles)
            for e in lay.thanQuad:
                e.thanPlotPdf(than)
  return than


    def thanExpPil(self, filpath, mode, width, height, drwin):
        "Exports the circle to a PIL raster image."
  import p_ggen, Image, ImageDraw, ImageFont, ImageFilter, thanvar
  from thandefs.thanatt import ThanAttCol
        than = p_ggen.Struct("ThanCad PIL image and options container")
  page = 19.5, 29.5
#  dpi = 300.0 #120.0
#  imsize = [int(p*dpi/2.54+0.5) for p in page]
#  than.mode = "RGB"

        than.mode = mode
  imsize = width, height
        dpi = imsize[1]/(page[1]/2.54)
  print "thanExpPil(): dpi=", dpi
  if than.mode == "1" or than.mode == "L": bcol = 255
  else:                                    bcol = 255,255,255
  than.im = Image.new(than.mode, imsize, bcol)
  ib, ih = than.im.size
  than.viewPort = x1, y1, x2, y2 = self.__roundCenter(self.viewPort, (0, ih, ib, 0))
  than.dc = ImageDraw.Draw(than.im)
  than.ct = thanvar.ThanRectCoorTransf()
  than.ct.set((x1, y1, x2, y2), (0, ih, ib, 0))
  than.imageFrameOn = self.thanVar["imageframe"]
#  than.fill = ThanAttCol("red").thanVal
#  than.outline = ThanAttCol("yellow").thanVal
#  than.width = int((9+1)/2)    # for the bugged version of ThanLine.thanExpPil()
#  than.width = 0
#        f = ImageFont.load_path("/home/a12/work/tcadtree.23/grhelv-b-10.pil")
#    than.font = f


        lays = self.thanLayerTree.dilay.values()
        lays = [(lay.thanAtts["draworder"].thanVal, lay) for lay in lays]
        lays.sort()
  lays = [lay for i,lay in lays]
        for lay in lays:
      if lay.thanAtts["frozen"].thanVal: continue
      lay.thanPilSet(than, dpi, self.thanTstyles)

      than.width  = int(than.rwidth + 0.5)
      than.widthline = int((than.width+1)/2)               # Get around PIL bug for line width
      i2 = int(than.width/2)
      i1 = -i2
      if i2-i1+1 > than.width: i1 += 1
      than.widtharc = i1, i2+1                             # Simulate widths in ars, circles
      assert than.width == than.widtharc[1]-than.widtharc[0]
            for e in lay.thanQuad:
                e.thanExpPil(than)

  del than.dc
  x1, y1, x2, y2 = self.viewPort
  ix1, iy1 = than.ct.global2Locali(x1, y2)  # PIL need left,upper and ..
        ix2, iy2 = than.ct.global2Locali(x2, y1)  # ..right,lower
        box = ix1, iy1, ix2, iy2
  im1 = than.im.crop(box)                   # Crop lines etc. outside the user defined window.
#  im1 = im1.filter(ImageFilter.SMOOTH)
  than.im = Image.new(than.mode, imsize, bcol)
  than.im.paste(im1, box)
  than.im.save(filpath)

    def __roundCenter(self, w, pixPort):
        "Rounds an abstract window w, so that it fits exactly to the actual (GuiDependent) window."

        xa, ya, xb, yb = pixPort
  wpi = abs(xb - xa)
  hpi = abs(yb - ya)

        wun = w[2] - w[0]
        hun = w[3] - w[1]

        per = 6
        if wpi < 10*per or hpi < 10*per: per = 0
  per = 0
  sx = float(wpi - per) / wun
        sy = float(hpi - per) / hun
        if sy < sx: sx = sy

        dx = (wpi / sx - wun) * 0.5
        dy = (hpi / sx - hun) * 0.5
        return w[0]-dx, w[1]-dy, w[0]+wun+dx, w[1]+hun+dy


#MODULE LEVEL CODE. IT IS EXECUTED ONLY ONCE

if __name__ == "__main__":
    print __doc__
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.