From 322260c61b374069d25ffb5c25ec229813d4bf93 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 3 Jul 2012 11:07:54 -0300 Subject: [PATCH] Arch: Lots of bugfixes in vector rendering --- src/Mod/Arch/ArchCommands.py | 3 +- src/Mod/Arch/ArchComponent.py | 3 +- src/Mod/Arch/ArchSectionPlane.py | 4 +- src/Mod/Arch/ArchVRM.py | 30 ++-- src/Mod/Draft/Draft.py | 38 ++--- src/Mod/Draft/DraftGeomUtils.py | 252 +++++++++++++++++-------------- 6 files changed, 171 insertions(+), 159 deletions(-) diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index 674f6eb50..1ddf46495 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -154,7 +154,7 @@ 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" + #print "makeFace: start:", wires import Part if not isinstance(wires,list): @@ -162,6 +162,7 @@ def makeFace(wires,method=2,cleanup=False): raise return Part.Face(wires) elif len(wires) == 1: + import Draft;Draft.printShape(wires[0]) if len(wires[0].Vertexes) < 3: raise return Part.Face(wires[0]) diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py index 5e0206fe9..7b220f588 100644 --- a/src/Mod/Arch/ArchComponent.py +++ b/src/Mod/Arch/ArchComponent.py @@ -62,7 +62,8 @@ def addToComponent(compobject,addobject,mod=None): l = getattr(compobject,mod) l.append(addobject) setattr(compobject,mod,l) - addobject.ViewObject.hide() + if mod != "Objects": + addobject.ViewObject.hide() else: for a in attribs[:3]: if hasattr(compobject,a): diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index 2fe408e61..f71828a96 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -21,7 +21,7 @@ #* * #*************************************************************************** -import FreeCAD,FreeCADGui,ArchComponent,WorkingPlane,math,Draft,ArchCommands, DraftVecUtils +import FreeCAD,FreeCADGui,ArchComponent,WorkingPlane,math,Draft,ArchCommands,DraftVecUtils from FreeCAD import Vector from PyQt4 import QtCore from pivy import coin @@ -215,7 +215,7 @@ class _ArchDrawingView: import ArchVRM render = ArchVRM.Renderer() render.setWorkingPlane(obj.Source.Placement) - render.addObjects(Draft.getGroupContents(objs)) + render.addObjects(Draft.getGroupContents(objs,walls=True)) 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 b920acc4e..0fe897aa1 100644 --- a/src/Mod/Arch/ArchVRM.py +++ b/src/Mod/Arch/ArchVRM.py @@ -168,7 +168,7 @@ class Renderer: def projectFace(self,face): "projects a single face on the WP" - #print "VRM: projectFace start" + #print "VRM: projectFace start: ",len(face[0].Vertexes)," verts, ",len(face[0].Edges)," edges" wires = [] if not face[0].Wires: if DEBUG: print "Error: Unable to project face on the WP" @@ -177,15 +177,16 @@ class Renderer: for w in face[0].Wires: verts = [] edges = DraftGeomUtils.sortEdges(w.Edges) + #print len(edges)," edges after sorting" for e in edges: v = e.Vertexes[0].Point + #print v v = self.wp.getLocalCoords(v) verts.append(v) verts.append(verts[0]) if len(verts) > 2: - print verts + #print "new wire with ",len(verts) wires.append(Part.makePolygon(verts)) - print "wires:",wires try: sh = ArchCommands.makeFace(wires) except: @@ -196,7 +197,7 @@ class Renderer: vnorm = self.wp.getLocalCoords(norm) if vnorm.getAngle(sh.normalAt(0,0)) > 1: sh.reverse() - #print "VRM: projectFace end" + #print "VRM: projectFace end: ",len(sh.Vertexes)," verts" return [sh]+face[1:] def flattenFace(self,face): @@ -272,12 +273,8 @@ class Renderer: shapes.append([c]+sh[1:]) for f in c.Faces: faces.append([f]+sh[1:]) - sec = sol.section(cutface) - if sec.Edges: - wires = DraftGeomUtils.findWires(sec.Edges) - for w in wires: - sec = Part.Face(w) - sections.append([sec,fill]) + if DraftGeomUtils.isCoplanar([f,cutface]): + sections.append([f,fill]) self.shapes = shapes self.faces = faces self.sections = sections @@ -573,19 +570,21 @@ class Renderer: def getPathData(self,w): "Returns a SVG path data string from a 2D wire" + def tostr(val): + return str(round(val,DraftVecUtils.precision())) edges = DraftGeomUtils.sortEdges(w.Edges) v = edges[0].Vertexes[0].Point - svg = 'M '+ str(v.x) +' '+ str(v.y) + ' ' + svg = 'M '+ tostr(v.x) +' '+ tostr(v.y) + ' ' for e in edges: if isinstance(e.Curve,Part.Line) or isinstance(e.Curve,Part.BSplineCurve): v = e.Vertexes[-1].Point - svg += 'L '+ str(v.x) +' '+ str(v.y) + ' ' + svg += 'L '+ tostr(v.x) +' '+ tostr(v.y) + ' ' elif isinstance(e.Curve,Part.Circle): r = e.Curve.Radius v = e.Vertexes[-1].Point - svg += 'A '+ str(r) + ' '+ str(r) +' 0 0 1 '+ str(v.x) +' ' - svg += str(v.y) + ' ' - svg += 'z ' + svg += 'A '+ tostr(r) + ' '+ tostr(r) +' 0 0 1 '+ tostr(v.x) +' ' + svg += tostr(v.y) + ' ' + svg += 'Z ' return svg def getViewSVG(self,linewidth=0.01): @@ -625,6 +624,7 @@ class Renderer: svg +=' a2: + a1,a2 = a2,a1 + + #print "creating sketch arc from ",cu, ", p1=",v1, " (",math.degrees(a1), "d) p2=",v2," (", math.degrees(a2),"d)" + p= Part.ArcOfCircle(cu,a1,a2) + return p + else: + return edge.Curve def mirror (point, edge): "finds mirror point relative to an edge" @@ -445,98 +451,91 @@ def isLine(bsp): return True def sortEdges(lEdges, aVertex=None): - "an alternative, more accurate version of Part.__sortEdges__" + "an alternative, more accurate version of Part.__sortEdges__" - #There is no reason to limit this to lines only because every non-closed edge always - #has exactly two vertices (wmayer) - #for e in lEdges: - # if not isinstance(e.Curve,Part.Line): - # print "Warning: sortedges cannot treat wired containing curves yet." - # return lEdges - - def isSameVertex(V1, V2): - ''' Test if vertexes have same coordinates with precision 10E(-precision)''' - if round(V1.X-V2.X,1)==0 and round(V1.Y-V2.Y,1)==0 and round(V1.Z-V2.Z,1)==0 : - return True - else : - return False - - def lookfor(aVertex, inEdges): - ''' Look for (aVertex, inEdges) returns count, the position of the instance - the position in the instance and the instance of the Edge''' - count = 0 - linstances = [] #lists the instances of aVertex - for i in range(len(inEdges)) : - for j in range(2) : - if isSameVertex(aVertex,inEdges[i].Vertexes[j-1]): - instance = inEdges[i] - count += 1 - linstances += [i,j-1,instance] - return [count]+linstances - - if (len(lEdges) < 2): - if aVertex == None: - return lEdges + #There is no reason to limit this to lines only because every non-closed edge always + #has exactly two vertices (wmayer) + #for e in lEdges: + # if not isinstance(e.Curve,Part.Line): + # print "Warning: sortedges cannot treat wired containing curves yet." + # return lEdges + + def lookfor(aVertex, inEdges): + ''' Look for (aVertex, inEdges) returns count, the position of the instance + the position in the instance and the instance of the Edge''' + count = 0 + linstances = [] #lists the instances of aVertex + for i in range(len(inEdges)) : + for j in range(2) : + if aVertex.Point == inEdges[i].Vertexes[j-1].Point: + instance = inEdges[i] + count += 1 + linstances += [i,j-1,instance] + return [count]+linstances + + if (len(lEdges) < 2): + if aVertex == None: + return lEdges + else: + result = lookfor(aVertex,lEdges) + if result[0] != 0: + if aVertex.Point == result[3].Vertexes[0].Point: + return lEdges else: - result = lookfor(aVertex,lEdges) - if result[0] != 0: - if isSameVertex(aVertex,result[3].Vertexes[0]): - return lEdges - else: - if isinstance(result[3].Curve,Part.Line): - return [Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape()] - elif isinstance(result[3].Curve,Part.Circle): - mp = findMidpoint(result[3]) - return [Part.Arc(aVertex.Point,mp,result[3].Vertexes[0].Point).toShape()] - elif isinstance(result[3].Curve,Part.BSplineCurve): - if isLine(result[3].Curve): - return [Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape()] - else: - return lEdges - else: - return lEdges - - olEdges = [] # ol stands for ordered list - if aVertex == None: - for i in range(len(lEdges)*2) : - if len(lEdges[i/2].Vertexes) > 1: - result = lookfor(lEdges[i/2].Vertexes[i%2],lEdges) - if result[0] == 1 : # Have we found an end ? - olEdges = sortEdges(lEdges, result[3].Vertexes[result[2]]) - return olEdges - # if the wire is closed there is no end so choose 1st Vertex - #print "closed wire, starting from ",lEdges[0].Vertexes[0].Point - return sortEdges(lEdges, lEdges[0].Vertexes[0]) - else : - #print "looking ",aVertex.Point - result = lookfor(aVertex,lEdges) - if result[0] != 0 : - del lEdges[result[1]] - next = sortEdges(lEdges, result[3].Vertexes[-((-result[2])^1)]) - #print "result ",result[3].Vertexes[0].Point," ",result[3].Vertexes[1].Point, " compared to ",aVertex.Point - if isSameVertex(aVertex,result[3].Vertexes[0]): - #print "keeping" - olEdges += [result[3]] + next + if isinstance(result[3].Curve,Part.Line): + return [Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape()] + elif isinstance(result[3].Curve,Part.Circle): + mp = findMidpoint(result[3]) + return [Part.Arc(aVertex.Point,mp,result[3].Vertexes[0].Point).toShape()] + elif isinstance(result[3].Curve,Part.BSplineCurve): + if isLine(result[3].Curve): + return [Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape()] else: - #print "inverting", result[3].Curve - if isinstance(result[3].Curve,Part.Line): - newedge = Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape() - olEdges += [newedge] + next - elif isinstance(result[3].Curve,Part.Circle): - mp = findMidpoint(result[3]) - newedge = Part.Arc(aVertex.Point,mp,result[3].Vertexes[0].Point).toShape() - olEdges += [newedge] + next - elif isinstance(result[3].Curve,Part.BSplineCurve): - if isLine(result[3].Curve): - newedge = Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape() - olEdges += [newedge] + next - else: - olEdges += [result[3]] + next - else: - olEdges += [result[3]] + next - return olEdges - else : - return [] + return lEdges + else: + return lEdges + + olEdges = [] # ol stands for ordered list + if aVertex == None: + for i in range(len(lEdges)*2) : + if len(lEdges[i/2].Vertexes) > 1: + result = lookfor(lEdges[i/2].Vertexes[i%2],lEdges) + if result[0] == 1 : # Have we found an end ? + olEdges = sortEdges(lEdges, result[3].Vertexes[result[2]]) + return olEdges + # if the wire is closed there is no end so choose 1st Vertex + # print "closed wire, starting from ",lEdges[0].Vertexes[0].Point + return sortEdges(lEdges, lEdges[0].Vertexes[0]) + else : + #print "looking ",aVertex.Point + result = lookfor(aVertex,lEdges) + if result[0] != 0 : + del lEdges[result[1]] + next = sortEdges(lEdges, result[3].Vertexes[-((-result[2])^1)]) + #print "result ",result[3].Vertexes[0].Point," ",result[3].Vertexes[1].Point, " compared to ",aVertex.Point + if aVertex.Point == result[3].Vertexes[0].Point: + #print "keeping" + olEdges += [result[3]] + next + else: + #print "inverting", result[3].Curve + if isinstance(result[3].Curve,Part.Line): + newedge = Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape() + olEdges += [newedge] + next + elif isinstance(result[3].Curve,Part.Circle): + mp = findMidpoint(result[3]) + newedge = Part.Arc(aVertex.Point,mp,result[3].Vertexes[0].Point).toShape() + olEdges += [newedge] + next + elif isinstance(result[3].Curve,Part.BSplineCurve): + if isLine(result[3].Curve): + newedge = Part.Line(aVertex.Point,result[3].Vertexes[0].Point).toShape() + olEdges += [newedge] + next + else: + olEdges += [result[3]] + next + else: + olEdges += [result[3]] + next + return olEdges + else : + return [] def findWires(edgeslist): @@ -787,6 +786,31 @@ def getNormal(shape): if n.getAngle(vdir) < 0.78: n = DraftVecUtils.neg(n) return n +def getRotation(v1,v2=FreeCAD.Vector(0,0,1)): + '''Get the rotation Quaternion between 2 vectors''' + if (v1.dot(v2) > 0.999999) or (v1.dot(v2) < -0.999999): + # vectors are opposite + return None + axis = v1.cross(v2) + axis.normalize() + angle = math.degrees(math.sqrt((v1.Length ^ 2) * (v2.Length ^ 2)) + v1.dot(v2)) + return FreeCAD.Rotation(axis,angle) + +def calculatePlacement(shape): + '''calculatePlacement(shape): if the given shape is planar, this function + returns a placement located at the center of gravity of the shape, and oriented + towards the shape's normal. Otherwise, it returns a null placement.''' + if not isPlanar(shape): + return FreeCAD.Placement() + pos = shape.BoundBox.Center + norm = getNormal(shape) + pla = FreeCAD.Placement() + pla.Base = pos + r = getRotation(norm) + if r: + pla.Rotation = r + return pla + def offsetWire(wire,dvec,bind=False,occ=False): ''' offsetWire(wire,vector,[bind]): offsets the given wire along the @@ -982,11 +1006,13 @@ def isCoplanar(faces): "checks if all faces in the given list are coplanar" if len(faces) < 2: return True - base =faces[0].normalAt(.5,.5) + base =faces[0].normalAt(0,0) for i in range(1,len(faces)): - normal = faces[i].normalAt(.5,.5) - if (normal.getAngle(base) > .0001) and (normal.getAngle(base) < 3.1415): - return False + for v in faces[i].Vertexes: + chord = v.Point.sub(faces[0].Vertexes[0].Point) + dist = DraftVecUtils.project(chord,base) + if dist.Length > 0: + return False return True def isPlanar(shape):