thanimpil.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 » thanimpil.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 the raster image element, based on Python Image Library.
"""

from math import fabs,pi,hypot,cos,sin,atan2
import Image, ImageTk
from itertools import izip
from p_gmath import PI2,thanNearx
from p_ggen import iterby2
import p_gtkuti
import thanintall
from thanvar import Canc,thanfiles
from thandefs import ThanImageMissing
from thantrans import T
from thanelem import ThanElement
from thanline import thanPntNearest,thanPntNearest2,thanPerpPoints,thanSegNearest


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

class ThanImage(ThanElement):
    """A raster image.

    A. Theory
  1.We assume that a pixel is rectangular in shape and the the world
    coordinates of a pixel correspond to its center.
  2.The x world
    coordinate corresponds to the column j and the y world coordinate
    corresponds to row i. To get the colour of the pixel of a PIL image
    we call the function:
      image.get((j,i))
    where j is the column and i is the row.
  3.The row i increases downwards, while the world coordinate y
    increases upwards.
  4.The column j takes values from 0 to dxp-1, where dxp is the image
    width in pixels
    The row i takes values from 0 to dxp-1, where dyp is the image
    height in pixels.
        5.The world image width is  dx=self.c2[0]-self.c1[0] and the
    the world image height is dy=self.c2[1]-self.c1[1]
  6.The world coordinates of the lower left corner of the image
    self.c1 (that means x1,y1; z1,t1,.. are ignored here) are the
    coordinates of the center of the pixel j=0, i=dyp-1
    Likewise the coordinates of the upper right corner of the image
    self.c2 are the coordinates of the center of the pixel
    j=dxp-1, i=0
  7.There are ((dxp-1)-0)+1=dxp pixels in the width and
    ((dyp-1)-0)+1=dyp pixels in the hight of the image.
    However the distance in pixels from the center of its lower left
    corner to its upper right corner are dxp-1 and dyp-1 in the
    x (column) and y (row) directions respectively.
    Suppose 10 pixel in the x (column) direction:
        0123456789
        OOOOOOOOOO
        ^        ^
    from the center of the zeroth pixel to the center of the nineth
    pixel stands the width of 9 pixels.
  8.Thus the width dxp1 and the height dyp1 of a pixel in world
    coordinates are:
    dxp1 = (x2-x1)/(dxp-1)
    dyp1 = (y2-y1)/(dyp-1)
  9.Thus, because the size of a pixel is small, but not infinitesimal,
    the image spans a little more space than intended. Its lower left
    and upper right corners are, in reality:
    x1-dxp1*0.5, y1-dyp1*0.5
    x2+dxp1*0.5, y2+dyp1*0.5
  10.In the x (column direction) the correspondence between pixels
     and world coordinates are:
     x1          -> 0
     x1-0.5*dxp1 -> 0
     x1+0.5*dxp1 -> 0
     x2          -> dxp-1
     x2-0.5*dxp1 -> dxp-1
     x2+0.5*dxp1 -> dxp-1
     In one formula, if we seek the pixel column of world coordinate x:
     j = int[(x-x1)/dxp1+0.5] =>
     j = int[ (x-x1)/((x2-x1)/(dxp-1)) + 0.5] =>
     j = int[ (x-x1)/(x2-x1)*(dxp-1) + 0.5] =>
     j = int[ (x-x1)/dx*(dxp-1) + 0.5]
     where dx = x2-x1
     j = int[ (x-x1)/dx*(dxp-1) + 0.5]
     i = int[ (y2-y)/dy*(dyp-1) + 0.5]
  11.In the y (row direction) the correspondence between pixels
     and world coordinates are:
     y2          -> 0
     y2-0.5*dyp1 -> 0
     y2+0.5*dyp1 -> 0
     y1          -> dyp-1
     y1-0.5*dyp1 -> dyp-1
     y1+0.5*dyp1 -> dyp-1
     In one formula, if we seek the pixel column of world coordinate x:
     float i = (y2-y)/dyp1
     this gives for y=y2:
     float i = (y2-y2)/dyp1 = 0  ->correct
     this gives for x=x2:
     float i = (y2-y1)/dyp1 = (y2-y1)/((y2-y1)/(dyp-1)) = dyp-1  ->correct
     The integer value of the pixel is:
     i = int[(y2-y)/dyp1 + 0.5] => ... =>
     i = int[ (y2-y)/dy*(dyp-1) + 0.5]
     where dy = y2-y1
     If we put the limits y1-0.5*dyp1, y1+0.5*dyp1, y2-0.5*dyp1,
     y2+0.5*dyp1 the results are ok.
  12.For additional safety we can limit the world coordinates to
     x1 <= x <=x2 and y1 <= y <=y2
     even thougth the image in reality is a little longer.
  13.The reverse function x, that is if we seek the world x coordinate
     of the center of pixel with column=j, row=i:
     x = x1+j*dxp1   which for j=0 and j=dxp-1 gives:
     x = x1+0*dxp1 = x1    -> correct
     x = x1+(dxp-1)*dxp1 = x1+(dxp-1)*(x2-x1)/(dxp-1) =
       = x1+(x2-x1) = x2   -> correct
     The formula becomes:
     x = x1+j*dxp1 = x1 + j*(x2-x1)/(dxp-1) =>
     x = x1 + j*dx/(dxp-1)
     It must be realised that this x coordinate is just the center of
     pixel. The pixel j,i in reality spans:
       x1+j*dx/(dxp-1) - dyp1*0.5 <= x <=x1+j*dx/(dxp-1) + dyp1*0.5
  14.The reverse function y, that is if we seek the world y coordinate
     of the center of pixel with column=j, row=i:
     y = y2-i*dyp1   which for i=0 and i=dyp-1 gives:
     y = y2-0*dyp1 = y2    -> correct
     y = y2-(dyp-1)*dyp1 = y2-(dyp-1)*(y2-y1)/(dyp-1) =
       = y2-(y2-y1) = y1   -> correct
     The formula becomes:
     y = y2-i*dyp1 = y2 - i*(y2-y1)/(dyp-1) =>
     y = y2 - i*dy/(dyp-1)
     It must be realised that this x coordinate is just the center of
     pixel. The pixel j,i in reality spans:
       y2-i*dy/(dyp-1) - dyp1*0.5 <= y <=y2-i*dy/(dyp-1) + dyp1*0.5
    B. Implementation
        1.Because the values dxp-1 and dyp-1 are used more than the dxp,dyp
    we set:
    dxp, dyp = self.image.size
    self.size = dxp-1, dyp-1
    So the width and height of the image are one less than the actual
    ones.
  2.Since dxp-1, dyp-1 are in the denominator the size of the image
    must be at least 2 pixels in x and y direction.
    """
    thanTkCompound = 100        # The number of Tkinter objects that make the element:
                                # 2=compound (Image and frame), 100=compound (frame and text)

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

    def thanSet (self, filnam, image, c1, c2, theta):
        "Sets the attributes of the image."
  assert c2[0]>=c1[0] and c2[1]>=c1[1], "Image can not have negative dimensions!"
        self.setBoundBox([c1[0], c1[1], c2[0], c2[1]])
        self.c1 = c1
        self.c2 = c2

  dxp, dyp = image.size
  if dxp < 2 or dyp < 2:
      self.image = ThanImageMissing()  # Defaults to size 100x100
      dxp, dyp = image.size
  self.size = dxp-1, dyp-1             # Make the following computations easier

  self.theta = theta % PI2             # radians assumed
  self.filnam = filnam
  self.image = image
  self.imagez = None
  self.view = [1e100, 1e100, -1e100, -1e100]
  self.visited = None                  # Placeholder of a tracker object used in semi-automatic trace
#  self.thanTags = ()                                 # thanTags is initialised in ThanElement


    def thanIsNormal(self):
        "Returns False if the image is degenerate."
        if thanNearx(self.c1[0], self.c2[0]): return False                                        # There is no degenerate image
        if thanNearx(self.c1[1], self.c2[1]): return False                                        # There is no degenerate image
        return True

    def __getstate__(self):
        odict = self.__dict__.copy()
        del odict["image"]          # Do not save the image in the file
        del odict["imagez"]
        return odict


    def __setstate__(self, odict):
        self.__dict__.update(odict)
        try:
            self.image = Image.open(self.filnam)
            dxp, dyp = self.image.size   # If it is not the same as the saved image,
            self.size = dxp-1, dyp-1     # the new image will be fitted in the same area
        except IOError:
            dxp, dyp = self.size
            self.image = ThanImageMissing((dxp+1, dyp+1))
        self.imagez = None


    def thanClone(self):
        """Makes a geometric clone of itself.

  Since PIL.copy() is a lazy operation, the cloned raster DOES NOT
  occupy more memory. But, to be sure, we return a reference to the raster
  so it is sure that no memory is wasted.
  """
  el = ThanImage()
#  el.thanSet(self.filnam, self.image.copy(), self.c1, self.c2, self.theta)
  el.thanSet(self.filnam, self.image, self.c1, self.c2, self.theta)
  return el


    def thanRotate(self):
        "Rotates the element within XY-plane with predefined angle and rotation angle."
        c1 = self.thanRotateXy(self.c1)
        self.c2[0] += c1[0]-self.c1[0]
        self.c2[1] += c1[1]-self.c1[1]
        self.c1 = c1
        self.theta += self.rotPhi
        self.theta %= PI2
        self.setBoundBox([self.c1[0], self.c1[1], self.c2[0], self.c2[1]])


    def thanMirror(self):
        "Mirrors the element within XY-plane with predefined point and unit vector."
        dbig = self.c2[0] - self.c1[0]
        cbig = list(self.c1)
        cbig[0] += dbig*cos(self.theta)
        cbig[1] += dbig*sin(self.theta)
        cbig = self.thanMirrorXy(cbig)

        c1 = self.thanMirrorXy(self.c1)
        self.c2[0] += c1[0]-self.c1[0]
        self.c2[1] += c1[1]-self.c1[1]
        self.c1 = c1

        self.theta = atan2(cbig[1]-self.c1[1], cbig[0]-self.c1[0]) % PI2
        self.setBoundBox([self.c1[0], self.c1[1], self.c2[0], self.c2[1]])


    def thanScale(self, cs, scale):
        "Scales the element in n-space with defined scale and center of scale."
        self.c1 = [cs1+(cc1-cs1)*scale for (cc1,cs1) in izip(self.c1, cs)]
        self.c2 = [cs1+(cc1-cs1)*scale for (cc1,cs1) in izip(self.c2, cs)]
        self.setBoundBox([self.c1[0], self.c1[1], self.c2[0], self.c2[1]])

    def thanMove(self, dc):
        "Moves the element with defined n-dimensional distance."
  self.c1 = [cc1+dd1 for (cc1,dd1) in izip(self.c1, dc)]
  self.c2 = [cc1+dd1 for (cc1,dd1) in izip(self.c2, dc)]
        self.setBoundBox([self.c1[0], self.c1[1], self.c2[0], self.c2[1]])

    def thanOsnap(self, proj, otypes, ccu, eother, cori):
        "Return a point of type otype nearest to ccu."
        if "ena" not in otypes: return None            # Object snap is disabled
        cp = self.__boundaryLine()
        ps = []
        if "end" in otypes:
            for c in cp:
                ps.append((fabs(c[0]-ccu[0])+fabs(c[1]-ccu[1]), "end", c))
        if "mid" in otypes:
            for ca, cb in iterby2(cp):
                c = [(ca1+cb1)*0.5 for (ca1,cb1) in izip(ca, cb)]
                ps.append((fabs(c[0]-ccu[0])+fabs(c[1]-ccu[1]), "mid", c))
        if "nea" in otypes:
            c = thanPntNearest(cp, ccu)
            if c != None:
                ps.append((fabs(c[0]-ccu[0])+fabs(c[1]-ccu[1]), "nea", c))
        if cori != None and "per" in otypes:
            for c in thanPerpPoints(cp, cori):
                ps.append((fabs(c[0]-ccu[0])+fabs(c[1]-ccu[1]), "per", c))
        if eother != None and "int" in otypes:
            ps.extend(thanintall.thanIntsnap(self, eother, ccu, proj))
        if len(ps) < 1: return None
        return min(ps)


    def __boundaryLine(self):
        "Returns the boundary as a line (a list of points)."
  cp = [self.c1, list(self.c1), self.c2, list(self.c2), self.c1]
  cp[1][0] = self.c2[0]
  cp[3][0] = self.c1[0]
#  cp = [(self.x1, self.y1), (self.x2, self.y1), (self.x2, self.y2), (self.x1, self.y2)]
        return cp


    def thanPntNearest(self, ccu):
        "Finds the nearest point of this line to a point."
        return thanPntNearest2(self.__boundaryLine(), ccu)[0]
    def thanPntNearest2(self, ccu):
        "Finds the nearest point of this line to a point."
        return thanPntNearest2(self.__boundaryLine(), ccu)
    def thanPerpPoints(self, ccu):
        "Finds perpendicular point from ccu to polyline."
        return thanPerpPoints(self.__boundaryLine(), ccu)
    def thanSegNearest(self, ccu):
        "Finds the nearest segment of the surrounding quadrilateral of this image to a point."
        return thanSegNearest(self.__boundaryLine(), ccu)


    def thanLength(self):
        "Returns the length of the polyline."
  alx = self.c2[0]-self.c1[0]    # Note that alx > 0
  aly = self.c2[1]-self.c1[1]    # Note that aly > 0
  if alx > aly: return alx
  return aly

    def thanArea(self):
        "Returns the area of the polyline."
  alx = self.c2[0]-self.c1[0]    # Note that alx > 0
  aly = self.c2[1]-self.c1[1]    # Note that aly > 0
  return alx*aly

    def thanBreak(self, c1=None, c2=None):
        "Just inform that the image can not be broken."
  return False       # Break is NOT implemented

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

    def thanTkGetold(self, proj):
        "Gets the attributes of the line interactively from a window."
        scale = 0.0254/300 * 500
  fildir = thanfiles.thanFilGetFiledir()
        while 1:
            fi = p_gtkuti.thanGudGetReadFile(proj[2], "*", "Choose image file",
          initialdir=fildir)
      print "impil.thanTkGet: fi=", fi
            if fi == None: return Canc            # Image canceled
      try:
          fr = file(fi, "rb")
            except IOError, why:
          p_gtkuti.thanGudModalMessage(proj[2], why, "Image file open failed")   # (Gu)i (d)ependent
    continue
            fr.close()
            try:
          im = Image.open(fi)
            except IOError, why:
          p_gtkuti.thanGudModalMessage(proj[2], why, "Image file open failed")   # (Gu)i (d)ependent
    continue
      break
        width, height = im.size

        res = self.__getInsPoint(proj[2])
        if res == Canc: return Canc               # Image cancelled (no destroy required)
  if res == "p":                            # Image is for pixel counting
      x1, y1 = -0.5, -0.5
      scale = 1.0
        else:
            x1, y1 = res
            scale = p_gtkuti.thanGudGetPosFloat(proj[2], "Length of 1 pixel in user data units: ", scale)
         if scale == Canc: return Canc         # Image canceled (no destroy required)

        self.thanSet(fi, im, x1, y1, x1+width*scale, y1+height*scale, 0.0)
        return True                               # Image OK


    def thanTkGet(self, proj):
        "Gets the attributes of the line interactively from a window."
  tit = T["Image file open failed"]
  fildir = thanfiles.thanFilGetFiledir()
        while True:
            fi = p_gtkuti.thanGudGetReadFile(proj[2], "*", "Choose image file",
          initialdir=fildir)
            if fi == None: return Canc            # Image canceled
      try:
          fr = file(fi, "rb")
            except IOError, why:
          p_gtkuti.thanGudModalMessage(proj[2], why, tit)   # (Gu)i (d)ependent
    continue
            fr.close()
            try:
          im = Image.open(fi)
            except IOError, why:
          p_gtkuti.thanGudModalMessage(proj[2], why, tit)   # (Gu)i (d)ependent
    continue
            dxp, dyp = im.size
      if dxp < 2 or dyp < 2:
          why = T["Image is probably corrupted: size is less than 2 pixels"]
          p_gtkuti.thanGudModalMessage(proj[2], why, tit)   # (Gu)i (d)ependent
    continue
      dxp -= 1; dyp -= 1
      break

  c1 = proj[2].thanGudGetPoint(T["Lower-left image point (pixel/<enter>): "], options=("pixel",))
        if c1 == Canc: return Canc               # Image cancelled (no destroy required)
  if c1 == "p":                            # Image is for pixel counting
      c1 = list(proj[1].thanVar["elevation"])
      c1[:2] = 0.0, 0.0    # This is the center of the lower-left pixel
      c2 = list(c1)
      c2[0] += dxp         # This is the center of the upper-right pixel
      c2[1] += dyp
        else:
            c2 = proj[2].thanGudGetRectratio(c1, T["Image width in user data units: "], float(dyp)/dxp)
         if c2 == Canc: return Canc           # Image canceled (no destroy is required)
        self.thanSet(fi, im, c1, c2, theta=0.0)
        return True                              # Image OK


    def thanTkDrawold(self, than):
        "Draws the image to a window."
        than.thanStatusTemp("Regenerating image..")
        xa, yb = than.ct.global2Local(self.c1[0], self.c1[1])    # xa, ya is the upper left point of the image
        xb, ya = than.ct.global2Local(self.c2[0], self.c2[1])    # xb, yb is the lower  right point of the image
        item1 = than.dc.create_line(xa, ya, xb, ya, xb, yb, xa, yb, xa, ya, fill=than.outline, tags=self.thanTags)     # Frame around image
        if isinstance(self.image, ThanImageMissing):
      item2 = None
      than.thanImages[item1, item2] = self
      from thantext import ThanText
      t = ThanText()
      h = (self.c2[0]-self.c1[0])/40.0
      n = len(self.filnam)
      xa = (self.c1[0] + self.c2[0])*0.5
      ya = (self.c1[1] + self.c2[1])*0.5
            t.thanSet(self.filnam, xa-n*h*0.5, ya-h*0.5, h, self.theta)
      t.thanTags = self.thanTags
      t.thanTkDraw(than)
      del t
      return

  wx = int(xb - xa); wy = int(yb - ya)
  assert wx>=0 and wy>=0, "Something wrong with coordinates systems!!!"
  if wx*wy > 4000000:            # If less than 4Mpixels render the entire image
            xymm = than.viewPort
      if self.c2[0] < xymm[0] or self.c1[0] > xymm[2] or self.c2[1] < xymm[1] or self.c1[1] > xymm[3]:
          assert False, "Image is outside visible screen!"
      self.view[0] = xn1 = max(self.c1[0], xymm[0])
      self.view[1] = yn1 = max(self.c1[1], xymm[1])
      self.view[2] = xn2 = min(self.c2[0], xymm[2])
      self.view[3] = yn2 = min(self.c2[1], xymm[3])
      for i,v in enumerate((self.c1[0], self.c1[1], self.c2[0], self.c2[1])):
          if self.view[i] == v: self.view[i] = None

            xa, yb = than.ct.global2Local(xn1, yn1)    # xa, ya is the upper left point of the image
            xb, ya = than.ct.global2Local(xn2, yn2)    # xb, yb is the lower  right point of the image
      wx = int(xb - xa); wy = int(yb - ya)
      assert wx>=0 and wy>=0, "Something wrong with coordinates systems!!!"
      assert wx*wy <= 4000000, "Reduced (!!!) image too big: %.0f x %.0f" % (wx,wy)
            dxp, dyp = self.size
      xp1 = int(linear(self.c1[0], 0,   self.c2[0], dxp, xn1)+0.5)
      xp2 = int(linear(self.c1[0], 0,   self.c2[0], dxp, xn2)+0.5)
      yp2 = int(linear(self.c1[1], dyp, self.c2[1], 0,   yn1)+0.5)
      yp1 = int(linear(self.c1[1], dyp, self.c2[1], 0,   yn2)+0.5)
      print xn1, yn1, xn2, yn2
      print xp1, yp1
      print xp2, yp2
      self.imagez = self.image.crop((xp1, yp1, xp2, yp2))    # This is a lazy operation (i.e. very fast)
      print "imagez before:", self.imagez.size
      self.imagez = ImageTk.PhotoImage(self.imagez.resize((wx, wy)))
        else:
      if self.theta == 0.0: self.imagez = ImageTk.PhotoImage(self.image.resize((wx, wy)))
      else:                 self.imagez = ImageTk.PhotoImage(self.image.resize((wx, wy)).rotate(self.theta))
      self.view = [None, None, None, None]

#        item2 = win.thanCanvas.create_image(xa, ya, image=self.imagez, anchor="sw", tags=self.thanTags)
        item2 = than.dc.create_image(xa, ya, image=self.imagez, anchor="nw", tags=self.thanTags)
  than.thanImages[item1, item2] = self
#  win.thanStatusUpdate()


    def thanTkDraw(self, than):
        "Draws the image to a window."
        xa, yb = than.ct.global2Locali(self.c1[0], self.c1[1])    # xa, ya is the upper left point of the image
        xb, ya = than.ct.global2Locali(self.c2[0], self.c2[1])    # xb, yb is the lower  right point of the image
        if isinstance(self.image, ThanImageMissing):
      item2 = None
#            item1 = than.dc.create_line(xa, ya, xb, ya, xb, yb, xa, yb, xa, ya, fill=than.outline, tags=self.thanTags)     # Frame around image
            item1 = than.dc.create_rectangle(xa, yb, xb, ya, outline=than.outline, tags=self.thanTags)     # Frame around image
      than.thanImages[item1, item2] = self
      from thantext import ThanText
      t = ThanText()
            h = (self.c2[0]-self.c1[0])/40.0
            n = len(self.filnam)
            ca = list(self.c1)
            ca[0] = (self.c1[0] + self.c2[0])*0.5 - n*h*0.5
            ca[1] = (self.c1[1] + self.c2[1])*0.5 - h*0.5
            t.thanSet(self.filnam, ca, h, self.theta)
      t.thanTags = self.thanTags
      t.thanTkDraw(than)
      del t
      return

        than.thanInfoPush(T["Regenerating image.."])
  wx = xb - xa; wy = yb - ya
  assert wx>=0 and wy>=0, "Something wrong with coordinates systems!!!"
  if wx*wy > 4000000:            # If less than 4Mpixels render the entire image
            xymm = than.viewPort
      if self.c2[0] < xymm[0] or self.c1[0] > xymm[2] or self.c2[1] < xymm[1] or self.c1[1] > xymm[3]:
          assert False, "Image is outside visible screen!"
      self.view[0] = xn1 = max(self.c1[0], xymm[0])
      self.view[1] = yn1 = max(self.c1[1], xymm[1])
      self.view[2] = xn2 = min(self.c2[0], xymm[2])
      self.view[3] = yn2 = min(self.c2[1], xymm[3])
      for i,v in enumerate((self.c1[0], self.c1[1], self.c2[0], self.c2[1])):
          if self.view[i] == v: self.view[i] = None

            xa, yb = than.ct.global2Locali(xn1, yn1)    # xa, ya is the upper left point of the image
            xb, ya = than.ct.global2Locali(xn2, yn2)    # xb, yb is the lower  right point of the image
      wx = xb-xa; wy = yb - ya
      assert wx>=0 and wy>=0, "Something wrong with coordinates systems!!!"
      assert wx*wy <= 4000000, "Reduced (!!!) image too big: %.0f x %.0f" % (wx,wy)
            xp1, yp2 = self.thanGetPixCoor([xn1, yn1])
            xp2, yp1 = self.thanGetPixCoor([xn2, yn2])
      print xn1, yn1, xn2, yn2
      print xp1, yp1
      print xp2, yp2
      self.imagez = self.image.crop((xp1, yp1, xp2, yp2))    # This is a lazy operation (i.e. very fast)
      print "imagez before:", self.imagez.size
      self.imagez = ImageTk.PhotoImage(self.imagez.resize((wx, wy)))
        else:
      if self.theta == 0.0: self.imagez = ImageTk.PhotoImage(self.image.resize((wx, wy)))
#      else:                 self.imagez = ImageTk.PhotoImage(self.image.resize((wx, wy)).rotate(self.theta*180/pi))
      else:                 self.imagez = ImageTk.PhotoImage(self.image.resize((wx, wy)))
      self.view = [None, None, None, None]

        item2 = than.dc.create_image(xa, yb, image=self.imagez, anchor="sw", tags=self.thanTags)
#        item2 = than.dc.create_image(xa, ya, image=self.imagez, anchor="nw", tags=self.thanTags)
#        item1 = than.dc.create_line(xa, ya, xb, ya, xb, yb, xa, yb, xa, ya, fill=than.outline, tags=self.thanTags)     # Frame around image
        if than.imageFrameOn:
            item1 = than.dc.create_rectangle(xa, yb, xb, ya, outline=than.outline, tags=self.thanTags)     # Frame around image
        else:
      item1 = self.thanTags[0]         # Just a unique value; nothin special
  than.thanImages[item1, item2] = self
        than.thanInfoPop()

    def thanTkHiwin(self, than):
        "Highlights with a (small) window very small elements so that they become visible."
  self.thanTkHiwinDo(than, self.thanLength(), self.c1)

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

    def thanExpDxf(self, fDxf, level=12):
        "Exports the image to dxf file."
  if level == 12:
            cp = self.__boundaryLine()
      cp.append(cp[0])
      for c in cp:
                fDxf.thanDxfPlotPolyVertex3(c[0], c[1], c[2], 2)
            fDxf.thanDxfPlotPolyVertex3(0, 0, 0, 999)
      h = (self.c2[0]-self.c1[0])/40.0
      n = len(self.filnam)
      xa = (self.c1[0] + self.c2[0])*0.5
      ya = (self.c1[1] + self.c2[1])*0.5
            fDxf.thanDxfPlotSymbol(xa-n*h*0.5, ya-h*0.5, h, self.filnam, self.theta)
  else:
      wx = fabs(self.c2[0] - self.c1[0])
      wy = fabs(self.c2[1] - self.c2[1])
            dx, dy = self.size
      dx = min(wx/float(dx), wy/float(dy))
            fDxf.thanDxfPlotImage(self.filnam, self.c1[0], self.c1[1], self.size, dx, self.theta)


    def thanExpSyk(self, than, level=0):
        "Exports the image to syk file."
  if level == 0: return
        cp = self.__boundaryLine()
  cp.append(cp[0])
  than.write("%15.3f  %s\n" % (self.c1[2], than.layname))
  for c in cp:
            than.write("%15.3f%15.3f\n" % (c[0], c[1]))
  than.write("$\n")


    def thanExpPil(self, than):
        "Exports the image to a PIL raster image."
        xymm = than.viewPort
  if self.c2[0] < xymm[0] or self.c1[0] > xymm[2] or self.c2[1] < xymm[1] or self.c1[1] > xymm[3]:
      return #Image is outside visible screen
        if not isinstance(self.image, ThanImageMissing):
      xn1 = max(self.c1[0], xymm[0])
      yn1 = max(self.c1[1], xymm[1])
         xn2 = min(self.c2[0], xymm[2])
      yn2 = min(self.c2[1], xymm[3])

            xa, yb = than.ct.global2Locali(xn1, yn1)    # xa, ya is the upper left point of the image
            xb, ya = than.ct.global2Locali(xn2, yn2)    # xb, yb is the lower  right point of the image
      wx = xb - xa; wy = yb - ya
      assert wx>=0 and wy>=0, "Something wrong with coordinates systems!!!"
      assert wx*wy <= 4000000, "Reduced (!!!) image too big: %.0f x %.0f" % (wx,wy)

            dxp, dyp = self.size
            xp1, yp2 = self.thanGetPixCoor([xn1, yn1])
            xp2, yp1 = self.thanGetPixCoor([xn2, yn2])

      imagez = self.image.crop((xp1, yp1, xp2, yp2))    # This is a lazy operation (i.e. very fast)
      imagez = imagez.resize((wx, wy))
      than.im.paste(imagez, (xa,ya,xb,yb))
        if than.imageFrameOn or isinstance(self.image, ThanImageMissing):
            cp = self.__boundaryLine()
      cp.append(cp[0])
      from thandr import ThanLine
      elem = ThanLine()
      elem.thanSet(cp)
            elem.thanExpPil(than)

    def thanList(self, than):
        "Shows information about the image element."
  than.writecom("Element: IMAGE")
  than.write("    Layer: % s\n" % than.laypath)
  than.write("Length: %s    Area: %s\n" % (than.strdis(self.thanLength()), than.strdis(self.thanArea())))
  t = ("Filename: %s" % self.filnam,
       "Bounding box: %s" % (than.strcoo(self.c1)),
       "              %s" % (than.strcoo(self.c2)),
       "Angle (not used): %s\n"% than.strang(self.theta),
      )
  than.write("\n".join(t))

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

    def thanGetPixCol(self, cw):
        "Finds the color of the pixel of the image that corresponds to the world coordinates xw, yw."
        return self.image.getpixel(self.thanGetPixCoor(cw))

    def __getitem__(self, ji):
        "Returns True if the pixel at ji is black (or less than a threshhold value non-b/w images)."
        return self.image.getpixel(ji) < 127

    def thanGetPixCoor(self, cw):
        "Finds the image pixel coordinates that corresponds to the world coordinates xw, yw."
        if cw[0]<self.c1[0] or cw[1]<self.c1[1] or cw[0]>self.c2[0] or cw[1]>self.c2[1]:
            raise IndexError, "World coordinates do not correspond to image."
        dxp, dyp = self.size                       # Note that dxp,dyp are 1 less than real dimensions
        dx, dy = self.c2[0]-self.c1[0], self.c2[1]-self.c1[1]

  jx = int( (cw[0]-self.c1[0])/dx*dxp + 0.5) # Note that dxp is one less the width in pixels
  iy = int( (self.c2[1]-cw[1])/dy*dyp + 0.5) # Note that dyp is one less the height in pixels
        return jx, iy

    def thanGetWorldCoor(self, jx, iy, celev=None):
        "Finds the the world coordinates that corresponds to the image pixel coordinates xp, yp."
  dxp, dyp = self.size
        if jx<0 or iy<0 or jx>dxp or iy>dyp: # Note that dxp,dyp are one less than actual
            raise IndexError, "Pixel coordinates do not correspond to image"
        dx, dy = self.c2[0]-self.c1[0], self.c2[1]-self.c1[1]
  if celev == None: cw = list(self.c1)
  else:             cw = list(celev)
        cw[0] = self.c1[0] + jx*dx/dxp       # Note that dxp is one less the width in pixels
        cw[1] = self.c2[1] - iy*dy/dyp       # Note that dyp is one less the height in pixels
        return cw


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.