From 9a269907aaf0f274ddea66c576b9a429258bdf1e Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sat, 30 Jun 2012 18:44:16 -0300 Subject: [PATCH 1/3] 0000765: Z axis in Draft Array --- src/Mod/Draft/Draft.py | 65 +++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index 9f2eef25d..380373a33 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -2714,29 +2714,35 @@ class _Array: obj.addProperty("App::PropertyEnumeration","ArrayType","Base", "The type of array to create") obj.addProperty("App::PropertyVector","Axis","Base", - "The axis direction for polar arrays") + "The axis direction") obj.addProperty("App::PropertyInteger","NumberX","Base", - "Number of copies in X direction (ortho arrays)") + "Number of copies in X direction") obj.addProperty("App::PropertyInteger","NumberY","Base", - "Number of copies in Y direction (ortho arrays)") + "Number of copies in Y direction") + obj.addProperty("App::PropertyInteger","NumberZ","Base", + "Number of copies in Z direction") obj.addProperty("App::PropertyInteger","NumberPolar","Base", - "Number of copies (polar arrays)") + "Number of copies") obj.addProperty("App::PropertyVector","IntervalX","Base", - "Distance and orientation of intervals in X direction (ortho arrays)") + "Distance and orientation of intervals in X direction") obj.addProperty("App::PropertyVector","IntervalY","Base", - "Distance and orientation of intervals in Y direction (ortho arrays)") + "Distance and orientation of intervals in Y direction") + obj.addProperty("App::PropertyVector","IntervalZ","Base", + "Distance and orientation of intervals in Z direction") obj.addProperty("App::PropertyVector","Center","Base", - "Center point (polar arrays)") + "Center point") obj.addProperty("App::PropertyAngle","Angle","Base", - "Angle to cover with copies (polar arrays)") + "Angle to cover with copies") obj.Proxy = self self.Type = "Array" obj.ArrayType = ['ortho','polar'] obj.NumberX = 1 obj.NumberY = 1 + obj.NumberZ = 1 obj.NumberPolar = 1 obj.IntervalX = Vector(1,0,0) obj.IntervalY = Vector(0,1,0) + obj.IntervalZ = Vector(0,0,1) obj.Angle = 360 obj.Axis = Vector(0,0,1) @@ -2744,7 +2750,32 @@ class _Array: self.createGeometry(obj) def onChanged(self,obj,prop): - if prop in ["ArrayType","NumberX","NumberY","NumberPolar","IntervalX","IntervalY","Angle","Center","Axis"]: + if prop == "ArrayType": + if obj.ViewObject: + if obj.ArrayType == "ortho": + obj.ViewObject.setEditorMode('Axis',2) + obj.ViewObject.setEditorMode('NumberPolar',2) + obj.ViewObject.setEditorMode('Center',2) + obj.ViewObject.setEditorMode('Angle',2) + obj.ViewObject.setEditorMode('NumberX',0) + obj.ViewObject.setEditorMode('NumberY',0) + obj.ViewObject.setEditorMode('NumberZ',0) + obj.ViewObject.setEditorMode('IntervalX',0) + obj.ViewObject.setEditorMode('IntervalY',0) + obj.ViewObject.setEditorMode('IntervalZ',0) + else: + obj.ViewObject.setEditorMode('Axis',0) + obj.ViewObject.setEditorMode('NumberPolar',0) + obj.ViewObject.setEditorMode('Center',0) + obj.ViewObject.setEditorMode('Angle',0) + obj.ViewObject.setEditorMode('NumberX',2) + obj.ViewObject.setEditorMode('NumberY',2) + obj.ViewObject.setEditorMode('NumberY',2) + obj.ViewObject.setEditorMode('IntervalX',2) + obj.ViewObject.setEditorMode('IntervalY',2) + obj.ViewObject.setEditorMode('IntervalZ',2) + if prop in ["ArrayType","NumberX","NumberY","NumberZ","NumberPolar", + "IntervalX","IntervalY","IntervalZ","Angle","Center","Axis"]: self.createGeometry(obj) def createGeometry(self,obj): @@ -2752,14 +2783,15 @@ class _Array: if obj.Base: pl = obj.Placement if obj.ArrayType == "ortho": - sh = self.rectArray(obj.Base.Shape,obj.IntervalX,obj.IntervalY,obj.NumberX,obj.NumberY) + sh = self.rectArray(obj.Base.Shape,obj.IntervalX,obj.IntervalY, + obj.IntervalZ,obj.NumberX,obj.NumberY,obj.NumberZ) else: sh = self.polarArray(obj.Base.Shape,obj.Center,obj.Angle,obj.NumberPolar,obj.Axis) obj.Shape = sh if not DraftGeomUtils.isNull(pl): obj.Placement = pl - def rectArray(self,shape,xvector,yvector,xnum,ynum): + def rectArray(self,shape,xvector,yvector,zvector,xnum,ynum,znum): import Part base = [shape.copy()] for xcount in range(xnum): @@ -2769,12 +2801,19 @@ class _Array: nshape.translate(currentxvector) base.append(nshape) for ycount in range(ynum): - currentxvector=FreeCAD.Vector(currentxvector) - currentyvector=currentxvector.add(DraftVecUtils.scale(yvector,ycount)) + currentyvector=FreeCAD.Vector(currentxvector) + currentyvector=currentyvector.add(DraftVecUtils.scale(yvector,ycount)) if not ycount==0: nshape = shape.copy() nshape.translate(currentyvector) base.append(nshape) + for zcount in range(znum): + currentzvector=FreeCAD.Vector(currentyvector) + currentzvector=currentzvector.add(DraftVecUtils.scale(zvector,zcount)) + if not zcount==0: + nshape = shape.copy() + nshape.translate(currentzvector) + base.append(nshape) return Part.makeCompound(base) def polarArray(self,shape,center,angle,num,axis): From e882b8c35c1206962ee4fed6aa68556a35d942aa Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Sun, 1 Jul 2012 13:01:25 -0300 Subject: [PATCH 2/3] Arch: fixed bugs in vector renderer --- src/Mod/Arch/ArchCommands.py | 23 ++++---- src/Mod/Arch/ArchSectionPlane.py | 2 +- src/Mod/Arch/ArchVRM.py | 91 +++++++++++++++++++++----------- src/Mod/Draft/Draft.py | 21 +++++++- 4 files changed, 95 insertions(+), 42 deletions(-) diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index 2025a6f30..674f6eb50 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -154,31 +154,35 @@ def splitMesh(obj,mark=True): def makeFace(wires,method=2,cleanup=False): '''makeFace(wires): makes a face from a list of wires, finding which ones are holes''' - + #print "makeFace: start" import Part if not isinstance(wires,list): + if len(wires.Vertexes) < 3: + raise return Part.Face(wires) elif len(wires) == 1: + if len(wires[0].Vertexes) < 3: + raise return Part.Face(wires[0]) wires = wires[:] - print "inner wires found" + #print "makeFace: inner wires found" ext = None max_length = 0 # cleaning up rubbish in wires if cleanup: for i in range(len(wires)): wires[i] = DraftGeomUtils.removeInterVertices(wires[i]) - print "garbage removed" + #print "makeFace: garbage removed" for w in wires: # we assume that the exterior boundary is that one with # the biggest bounding box if w.BoundBox.DiagonalLength > max_length: max_length = w.BoundBox.DiagonalLength ext = w - print "exterior wire",ext + #print "makeFace: exterior wire",ext wires.remove(ext) if method == 1: @@ -186,23 +190,22 @@ def makeFace(wires,method=2,cleanup=False): # all interior wires mark a hole and must reverse # their orientation, otherwise Part.Face fails for w in wires: - print "reversing",w + #print "makeFace: reversing",w w.reverse() - print "reversed" # make sure that the exterior wires comes as first in the list wires.insert(0, ext) - print "done sorting", wires + #print "makeFace: done sorting", wires if wires: return Part.Face(wires) else: # method 2: use the cut method mf = Part.Face(ext) - print "external face:",mf + #print "makeFace: external face:",mf for w in wires: f = Part.Face(w) - print "internal face:",f + #print "makeFace: internal face:",f mf = mf.cut(f) - print "final face:",mf.Faces + #print "makeFace: final face:",mf.Faces return mf.Faces[0] def meshToShape(obj,mark=True): diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index 460d3a7d1..2fe408e61 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -215,7 +215,7 @@ class _ArchDrawingView: import ArchVRM render = ArchVRM.Renderer() render.setWorkingPlane(obj.Source.Placement) - render.addObjects(objs) + render.addObjects(Draft.getGroupContents(objs)) render.cut(obj.Source.Shape) svg += render.getViewSVG(linewidth=linewidth) svg += render.getSectionSVG(linewidth=linewidth*2) diff --git a/src/Mod/Arch/ArchVRM.py b/src/Mod/Arch/ArchVRM.py index 2eefd8f27..b920acc4e 100644 --- a/src/Mod/Arch/ArchVRM.py +++ b/src/Mod/Arch/ArchVRM.py @@ -145,12 +145,14 @@ class Renderer: def reorient(self): "reorients the faces on the WP" + #print "VRM: start reorient" if not self.faces: return self.faces = [self.projectFace(f) for f in self.faces] if self.sections: self.sections = [self.projectFace(f) for f in self.sections] self.oriented = True + #print "VRM: end reorient" def removeHidden(self): "removes faces pointing outwards" @@ -166,7 +168,11 @@ class Renderer: def projectFace(self,face): "projects a single face on the WP" + #print "VRM: projectFace start" wires = [] + if not face[0].Wires: + if DEBUG: print "Error: Unable to project face on the WP" + return None norm = face[0].normalAt(0,0) for w in face[0].Wires: verts = [] @@ -177,7 +183,9 @@ class Renderer: verts.append(v) verts.append(verts[0]) if len(verts) > 2: + print verts wires.append(Part.makePolygon(verts)) + print "wires:",wires try: sh = ArchCommands.makeFace(wires) except: @@ -188,6 +196,7 @@ class Renderer: vnorm = self.wp.getLocalCoords(norm) if vnorm.getAngle(sh.normalAt(0,0)) > 1: sh.reverse() + #print "VRM: projectFace end" return [sh]+face[1:] def flattenFace(self,face): @@ -211,6 +220,7 @@ class Renderer: def cut(self,cutplane): "Cuts through the shapes with a given cut plane and builds section faces" + if DEBUG: print "\n\n======> Starting cut\n\n" if self.iscut: return if not self.shapes: @@ -277,6 +287,7 @@ class Renderer: self.trimmed = False self.sorted = False self.joined = False + if DEBUG: print "\n\n======> Finished cut\n\n" def isInside(self,vert,face): "Returns True if the vert is inside the face in Z projection" @@ -319,6 +330,15 @@ class Renderer: def compare(self,face1,face2): "zsorts two faces. Returns 1 if face1 is closer, 2 if face2 is closer, 0 otherwise" + #print face1,face2 + + if not face1: + if DEBUG: print "Warning, undefined face!" + return 31 + elif not face2: + if DEBUG: print "Warning, undefined face!" + return 32 + # theory from # http://www.siggraph.org/education/materials/HyperGraph/scanline/visibility/painter.htm # and practical application http://vrm.ao2.it/ (blender vector renderer) @@ -456,14 +476,17 @@ class Renderer: def sort(self): "projects a shape on the WP" + if DEBUG: print "\n\n======> Starting sort\n\n" if len(self.faces) <= 1: return if not self.trimmed: self.removeHidden() + if DEBUG: print "Done hidden face removal" if len(self.faces) == 1: return if not self.oriented: self.reorient() + if DEBUG: print "Done reorientation" faces = self.faces[:] if DEBUG: print "sorting ",len(self.faces)," faces" sfaces = [] @@ -492,6 +515,7 @@ class Renderer: for f2 in faces[1:]: if DEBUG: print "comparing face",str(self.faces.index(f1))," with face",str(self.faces.index(f2)) r = self.compare(f1,f2) + print "comparison result:",r if r == 1: faces.remove(f2) sfaces.append(f2) @@ -506,6 +530,10 @@ class Renderer: sfaces.append(f2) notfoundstack = 0 break + elif r == 31: + faces.remove(f1) + elif r == 32: + faces.remove(f2) else: # nothing found, move the face to the end of the pile faces.remove(f1) @@ -518,6 +546,7 @@ class Renderer: if DEBUG: print "done Z sorting. ", len(sfaces), " faces retained, ", len(self.faces)-len(sfaces), " faces lost." self.faces = sfaces self.sorted = True + if DEBUG: print "\n\n======> Finished sort\n\n" def buildDummy(self): "Builds a dummy object with faces spaced on the Z axis, for visual check" @@ -566,21 +595,22 @@ class Renderer: self.sort() svg = '' for f in self.faces: - fill = self.getFill(f[1]) - svg +=' Date: Mon, 2 Jul 2012 09:54:41 -0300 Subject: [PATCH 3/3] Draft: small fix to dimensions --- src/Mod/Draft/Draft.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index c384fef91..5e680c116 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -253,7 +253,7 @@ def shapify(obj): FreeCAD.ActiveDocument.recompute() return newobj -def getGroupContents(objectslist): +def getGroupContents(objectslist,walls=False): '''getGroupContents(objectlist): if any object of the given list is a group, its content is appened to the list, which is returned''' newlist = [] @@ -262,13 +262,20 @@ def getGroupContents(objectslist): newlist.extend(getGroupContents(obj.Group)) else: newlist.append(obj) + if walls: + if getType(obj) == "Wall": + for o in obj.OutList: + if (getType(o) == "Window") or isClone(o,"Window"): + newlist.append(o) return newlist def printShape(shape): """prints detailed information of a shape""" print "solids: ", len(shape.Solids) print "faces: ", len(shape.Faces) - print "wires: ",len(shape.Wires) + print "wires: ", len(shape.Wires) + print "edges: ", len(shape.Edges) + print "verts: ", len(shape.Vertexes) if shape.Faces: for f in range(len(shape.Faces)): print "face ",f,":" @@ -1964,7 +1971,7 @@ class _ViewProviderDimension: [p2.x,p2.y,p2.z], [p3.x,p3.y,p3.z], [p4.x,p4.y,p4.z]]) - self.line.numVertices.setValues([4]) + self.line.numVertices.setValue(4) else: ts = (len(text)*obj.ViewObject.FontSize)/4 rm = ((p3.sub(p2)).Length/2)-ts