# -*- coding: iso-8859-7 -*-
##############################################################################
# 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 processes commands related to engineering.
"""
import weakref
from math import hypot
import p_ggen
import thaneng, thandr, thancomsel, thantkdia
from thanvar import Canc
from thantrans import T
from selutil import thanSel1line
from thancommod import thanModEnd,thanModCanc
def thanEngMaprect(proj):
"Topographic map rectification using known grid points."
win = thantkdia.ThanMaprect(proj[2], None, proj)
proj[2].thanTkSetFocus()
def thanEngGrid(proj):
"Makes a set of crosses which indicate a grid."
scale = proj[2].thanGudGetPosFloat(T["Engineering scale 1:x (enter=500): "], 500.0)
if scale == Canc: return proj[2].thanGudCommandCan() # Grid cancelled
c1 = proj[2].thanGudGetPoint(T["First grid corner (Quadrilateral): "], options=("quadrilateral",))
if c1 == Canc: return proj[2].thanGudCommandCan() # Grid cancelled
if c1 == "q":
cp = getquad(proj)
if cp == Canc: return proj[2].thanGudCommandCan() # Grid cancelled
else:
c3 = proj[2].thanGudGetRect(c1, T["Other grid corner: "])
if c3 == Canc: return proj[2].thanGudCommandCan() # Grid cancelled
c2 = list(c1); c2[0] = c3[0]
c4 = list(c3); c4[0] = c1[0]
cp = [c1, c2, c3, c4]
grid = thaneng.ThanGrid()
grid.thanDo(proj, scale, 0.0, 0.0, 1, cp)
ans = proj[2].thanGudGetYesno(T["Keep grid boundary (Yes/No/<Yes>): "], default="yes")
if ans == Canc: return proj[2].thanGudCommandCan()
if ans:
e = thandr.ThanLine()
cp.append(list(cp[0]))
e.thanSet(cp)
proj[1].thanElementAdd(e)
e.thanTkDraw(proj[2].than)
proj[2].thanGudCommandEnd()
def getquad(proj):
"Get a convex quadrilateral form the user."
than = proj[2].than
g2l = than.ct.global2Local
c1 = proj[2].thanGudGetPoint(T["First quadrilateral grid corner: "])
if c1 == Canc: return Canc # Grid cancelled
while True:
c2 = proj[2].thanGudGetLine(c1, T["Second quadrilateral grid corner: "])
if c2 == Canc: return Canc # Grid cancelled
temp = than.dc.create_line(g2l(c1[0], c1[1]), g2l(c2[0], c2[1]),
fill="blue", tags=("e0",))
while True:
c3 = proj[2].thanGudGetLine2(c1, c2, T["Third quadrilateral grid corner (Undo): "],
options=("undo",))
if c3 == Canc: than.dc.delete("e0"); return Canc
if c3 == "u": than.dc.delete("e0"); break
temp = than.dc.create_line(g2l(c2[0], c2[1]), g2l(c3[0], c3[1]),
fill="blue", tags=("e0","e1"))
c4 = proj[2].thanGudGetLine2(c1, c3, T["Fourth quadrilateral grid corner (Undo): "],
options=("undo",))
if c4 == Canc: than.dc.delete("e0"); return Canc
if c4 == "u": than.dc.delete("e1"); continue
temp = than.dc.create_line(g2l(c2[0], c2[1]), g2l(c3[0], c3[1]),
fill="blue", tags=("e0","e1"))
than.dc.delete("e0")
return [c1, c2, c3, c4]
if c3 == "u": continue
def thanEngTrace(proj):
"Traces semiautomatically a curve in a bitmap image."
im, cw = proj[2].thanGudGetImPoint(T["Start point of trace: "],
ptol=proj[2].BSEL/2, threshold=127)
if cw == Canc: return proj[2].thanGudCommandCan()
proj[2].thanImageCur = weakref.proxy(im)
jx, iy = im.thanGetPixCoor(cw)
res = thaneng.thanTrace(proj, jx, iy)
if res == Canc: return proj[2].thanGudCommandCan()
return proj[2].thanGudCommandEnd()
def thanEngInterchange(proj):
"Make a highway intersection."
from thanpackages.komb.kom import thanMainTcad
lin1 = thanSel1line(proj, T["Select a line with 3 point to fit highway interchange\n"])
if lin1 == Canc: return proj[2].thanGudCommandCan()
thanMainTcad(proj, lin1)
return proj[2].thanGudCommandEnd()
def thanEngDtmmake(proj):
"Asks the user to select lines to be used as DTM."
from p_gtri import ThanDTMlines
proj[2].thanCom.thanAppend(T["Select lines to generate DTM:\n"], "info1")
res = thancomsel.thanSelectGen(proj, standalone=False, filter=lambda e: isinstance(e, thandr.ThanLine))
if res == Canc: return thanModCanc(proj) # Make dtm was cancelled
dtm = ThanDTMlines()
thanAddLines(dtm, proj[2].thanSelall)
ok, ter = dtm.thanRecreate()
if not ok: return thanModCanc(proj, T["Error creating DTM: %s"]%ter)
proj[1].thanDtm = dtm
# from thansupport import thanToplayerCurrent
# thanToplayerCurrent(proj, "dtmlines", current=True, moncolor="white")
# for cp in dtm.thanLines:
# e = thandr.ThanLine()
# e.thanSet(cp)
# proj[1].thanElementAdd(e)
# e.thanTkDraw(proj[2].than)
return thanModEnd(proj, T["%d generated line segments in DTM."] % len(dtm.thanLines), "info")
def thanAddLines(self, elems):
"Add the lines of list/set of ThanCad elements (usually the elements of selection)."
ThanLine = thandr.ThanLine
for e in elems:
if isinstance(e, ThanLine): self.thanAddLine1(e.cp)
def thanAddLayers(self, lays):
"Add all the lines of certain ThanCad layers."
ThanLine = thandr.ThanLine
for lay in lays:
for e in lay.thanQuad:
if isinstance(e, ThanLine): self.thanAddLine1(e.cp)
def thanEngDtmpoint1(proj):
"Compute the z of a user selected point."
if proj[1].thanDtm == None: return thanModCanc(proj, T["Can't compute z: No DTM has been defined!"])
cp = proj[2].thanGudGetPoint(T["Specify a point: "])
if cp == Canc: return thanModCanc(proj) # Point cancelled
z = proj[1].thanDtm.thanPointZ(cp)
if z == None: return thanModCanc(proj, T["Can't compute z: No DTM lines are near point."])
cp = list(cp)
cp[2] = z
return thanModEnd(proj, T["Point with z: %s"] % proj[1].thanUnits.strcoo(cp), "info")
def thanEngDtmline(proj):
"Compute the z along a line."
if proj[1].thanDtm == None: return thanModCanc(proj, T["Can't compute z: No DTM has been defined!"])
proj[2].thanCom.thanAppend(T["Select lines to transform to 3d:\n"], "info1")
res = thancomsel.thanSelectGen(proj, standalone=False, filter=lambda e: isinstance(e, thandr.ThanLine))
if res == Canc: return thanModCanc(proj) # DTM lines was cancelled
dtm = proj[1].thanDtm
def prt(t, st="can1"): proj[2].thanCom.thanAppend("%s\n" % t, st)
nlin = 0
for e in proj[2].thanSelall:
ni, cp = dtm.thanLineZ(e.cp)
if ni == -1:
prt(T["Can't compute z: No DTM lines are near the selected line."])
else:
if ni > 0: prt(T["The z of some line points couldn't be computed: %d interpolations"] % ni)
e.thanSet(cp)
nlin += 1
proj[1].thanTouch()
if nlin == 0: return thanModEnd(proj, T["No lines were transformed; they are too far away the DTM."])
proj[2].thanGudSetSelDel() # Delete selected lines from canvas
proj[2].thanGudDrawElemsMany(proj[2].thanSelall) # Redraw the lines (with new coordinates)
proj[2].thanGudSetSelElem1(proj[2].thanSelall) # Mark the lines as selected
return thanModEnd(proj, T["%d/%d lines were transformed to 3d."]%(nlin, len(proj[2].thanSelall)), "info")
def thanEngDtmpoints(proj):
"Compute the z of multiple points."
if proj[1].thanDtm == None: return thanModCanc(proj, T["Can't compute z: No DTM has been defined!"])
proj[2].thanCom.thanAppend(T["Select points to transform to 3d:\n"], "info1")
res = thancomsel.thanSelectGen(proj, standalone=False, filter=lambda e: isinstance(e, thandr.ThanPoint))
if res == Canc: return thanModCanc(proj) # DTM lines was cancelled
dtm = proj[1].thanDtm
def prt(t, st="can1"): proj[2].thanCom.thanAppend("%s\n" % t, st)
nlin = 0
for e in proj[2].thanSelall:
z = dtm.thanPointZ(e.cp)
if z == None:
prt(T["Can't compute z: No DTM lines are near the selected point."])
else:
e.cp[2] = z
nlin += 1
proj[1].thanTouch()
if nlin == 0: return thanModEnd(proj, T["No points were transformed; they are too far away the DTM."])
proj[2].thanGudSetSelDel() # Delete selected lines from canvas
proj[2].thanGudDrawElemsMany(proj[2].thanSelall) # Redraw the lines (with new coordinates)
proj[2].thanGudSetSelElem1(proj[2].thanSelall) # Mark the lines as selected
return thanModEnd(proj, T["%d/%d points were transformed to 3d."]%(nlin, len(proj[2].thanSelall)), "info")
def thanEngLineprofile(proj):
"Creates a (3D) line profile into a new drawing."
from thanimp import ThanCadDrSave
from thansupport import ThanDxfEmu
from thancomview import thanZoomExt
from thancomfile import thanFileNewDo
proj[2].thanCom.thanAppend(T["Select 3d lines to make profiles:\n"], "info1")
res = thancomsel.thanSelectGen(proj, standalone=False, filter=lambda e: isinstance(e, thandr.ThanLine))
if res == Canc: return thanModCanc(proj) # Profile was cancelled
dfact = 0.1
for e in proj[2].thanSelall:
d = [0.0*dfact]
for ca, cb in p_ggen.iterby2(e.cp):
d.append(d[-1]+hypot(cb[1]-ca[1], cb[0]-ca[0])*dfact)
zmin = min(ca[2] for ca in e.cp)
projnew = thanFileNewDo(proj)
ts = ThanCadDrSave(projnew[1], lambda s: projnew[2].thanCom.thanAppend("%s\n" % s))
dxf = ThanDxfEmu()
dxf.thanDxfPlots(ts)
dxf.thanDxfPlot(d[0], zmin, 3)
dxf.thanDxfPlot(d[-1], zmin, 2)
dxf.thanDxfPlot(d[0], zmin, 3)
dxf.thanDxfPlot(d[0], e.cp[0][2], 2)
for i in xrange(1, len(e.cp)):
dxf.thanDxfPlot(d[i], zmin, 3)
dxf.thanDxfPlot(d[i], e.cp[i][2], 2)
dxf.thanDxfPlot(d[i-1], e.cp[i-1][2], 2)
dxf.thanDxfPlot(0, 0, 999)
projnew[1].thanLayerTree.thanDictRebuild()
projnew[2].thanRegen()
thanZoomExt(projnew)
return thanModEnd(proj, T["%d profiles were created."]%len(proj[2].thanSelall), "info")
def thanEngTri(proj):
"Asks the user to select lines to make triangulation from."
from p_gtri import ThanTri,ThanYpyka
from thansupport import thanToplayerCurrent
mes = T["Triangulation: Create/Read/Save/cOntours or"] + "\n" + \
T["draw Edges/draw Triangles/draw ceNtroids (enter=c): "]
res = proj[2].thanGudGetOpts(mes, default="C",
options=("Create", "Read", "Save", "Ontours", "Edges", "Triangles", "Ntroids"))
if res == Canc: return thanModCanc(proj) # Triangulation was cancelled
if res == "c":
return thanEngTrimake(proj)
elif res == "r":
fn = proj[0].parent / (proj[0].namebase + ".tri")
try:
fr = open(fn, "r")
except Exception, why:
return thanModCanc(proj, "Can not read triangulation from %s:\n%s" % (fn, why))
proj[1].thanTri = ThanTri()
proj[1].thanTri.readtri(fr)
fr.close()
return thanModEnd(proj, "Triangulation was succesfully read from %s" % fn, "info")
elif res == "s":
if proj[1].thanTri == None: return thanModCanc(proj, T["No triangulation has been defined!"])
fn = proj[0].parent / (proj[0].namebase + ".tri")
try:
fw = open(fn, "w")
except Exception, why:
return thanModCanc(proj, "Can not write to %s:\%s" % (fn, why))
proj[1].thanTri.writetri(fw)
fw.close()
return thanModEnd(proj, "Triangulation was saved in %s" % fn, "info")
elif res == "o":
if proj[1].thanTri == None: return thanModCanc(proj, T["No triangulation has been defined!"])
dhl = 1.0
dhx = 5.0
def prt(s): proj[2].thanCom.thanAppend("%s\n" % s, "info1")
def saveis(icod, cis):
"Draw a contour line."
his = cis[0][2]
if his % dhx < 0.01*dhl: thanToplayerCurrent(proj, "YX", current=True, moncolor="30")
else: thanToplayerCurrent(proj, "YL", current=True, moncolor="34")
e = thandr.ThanLine()
e.thanSet(cis)
proj[1].thanElementAdd(e)
e.thanTkDraw(proj[2].than)
p = ThanYpyka(proj[1].thanTri.ls, saveis, prt)
p.ypyka(dhl, 200.0)
return thanModEnd(proj)
elif res == "e":
return __tridraw(proj, edges=True)
elif res == "t":
return __tridraw(proj, triangles=True)
elif res == "n":
return __tridraw(proj, centroids=True)
elif res == "s":
if proj[1].thanTri == None: return thanModCanc(proj, T["No triangulation has been defined!"])
fn = proj[0].parent / (proj[0].namebase + ".tri")
try:
fw = open(fn, "w")
except Exception, why:
return thanModCanc(proj, "Can not write to %s:\%s" % (fn, why))
proj[1].thanTri.writetri(fw)
fw.close()
return thanModEnd(proj, "Triangulation was saved in %s" % fn, "info")
else:
assert 0, "Unknown option!"
def thanEngTrimake(proj):
"Asks the user to select lines to make triangulation from."
from p_gtri import ThanTri
from thandr import ThanLine,ThanPoint
lp = (ThanLine, ThanPoint)
proj[2].thanCom.thanAppend(T["Select points/lines to generate triangulation from:\n"], "info1")
res = thancomsel.thanSelectGen(proj, standalone=False, filter=lambda e: isinstance(e, lp))
if res == Canc: return thanModCanc(proj) # Create triangulation was cancelled
cp = []
for e in proj[2].thanSelall:
if isinstance(e, ThanLine): cp.extend(e.cp)
else: cp.append(e.cp)
tri = ThanTri(cp)
# tri.apeira()
ok, ter = tri.compute()
if not ok: return thanModCanc(proj, T["Error creating triangulation: %s"]%ter)
# tri.convex()
tri.sortlinks()
proj[2].thanCom.thanAppend("Applying break lines..\n")
for e in proj[2].thanSelall:
if isinstance(e, ThanLine):
for ca, cb in p_ggen.iterby2(e.cp):
tri.brkapply(ca, cb)
n = 0
for _ in tri.itertriangles(): n += 1
proj[1].thanTri = tri
thanModEnd(proj, T["%d triangles were generated."] % n, "info")
def __tridraw(proj, edges=False, triangles=False, centroids=False, aa=False):
"Draw triangulation."
from thansupport import thanToplayerCurrent
if proj[1].thanTri == None: return thanModCanc(proj, T["No triangulation has been defined!"])
thanToplayerCurrent(proj, "trilines", current=True, moncolor="yellow")
apmax = 500.0
if edges:
for ca, cb in proj[1].thanTri.iteredges():
e = thandr.ThanLine()
e.thanSet([ca, cb])
proj[1].thanElementAdd(e)
e.thanTkDraw(proj[2].than)
if centroids:
for ca, cb, cc in proj[1].thanTri.itertriangles(apmax):
cen = [(a+b+c)/3.0 for a,b,c in zip(ca, cb, cc)]
e = thandr.ThanPoint()
e.thanSet(cen)
proj[1].thanElementAdd(e)
e.thanTkDraw(proj[2].than)
if aa:
for ca, cb, cc in proj[1].thanTri.itertriangles(apmax):
cen = [(a+b+c)/3.0 for a,b,c in zip(ca, cb, cc)]
e = thandr.ThanText()
e.thanSet(str(ntr), cen, 1.0, 0.0)
proj[1].thanElementAdd(e)
e.thanTkDraw(proj[2].than)
if triangles:
for ca, cb, cc in proj[1].thanTri.itertriangles(apmax):
e = thandr.ThanLine()
e.thanSet([ca, cb, cc, ca])
proj[1].thanElementAdd(e)
e.thanTkDraw(proj[2].than)
thanModEnd(proj)
|