Arch: Lots of bugfixes in vector rendering
This commit is contained in:
parent
f8c299c858
commit
322260c61b
|
@ -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])
|
||||
|
|
|
@ -62,6 +62,7 @@ def addToComponent(compobject,addobject,mod=None):
|
|||
l = getattr(compobject,mod)
|
||||
l.append(addobject)
|
||||
setattr(compobject,mod,l)
|
||||
if mod != "Objects":
|
||||
addobject.ViewObject.hide()
|
||||
else:
|
||||
for a in attribs[:3]:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 +='<path '
|
||||
svg += 'd="'
|
||||
for w in f[0].Wires:
|
||||
#print "wire with ",len(w.Vertexes)," verts"
|
||||
svg += self.getPathData(w)
|
||||
svg += '" '
|
||||
svg += 'stroke="#000000" '
|
||||
|
|
|
@ -1540,7 +1540,7 @@ def makeSketch(objectslist,autoconstraints=False,addTo=None,name="Sketch"):
|
|||
ok = False
|
||||
tp = getType(obj)
|
||||
if tp == "BSpline":
|
||||
pass
|
||||
print "makeSketch: BSplines not supported"
|
||||
elif tp == "Circle":
|
||||
if obj.FirstAngle == obj.LastAngle:
|
||||
nobj.addGeometry(obj.Shape.Edges[0].Curve)
|
||||
|
@ -1586,32 +1586,16 @@ def makeSketch(objectslist,autoconstraints=False,addTo=None,name="Sketch"):
|
|||
nobj.addConstraint(Constraint("Coincident",last-1,EndPoint,segs[0],StartPoint))
|
||||
ok = True
|
||||
if (not ok) and obj.isDerivedFrom("Part::Feature"):
|
||||
if DraftGeomUtils.hasOnlyWires(obj.Shape):
|
||||
for w in obj.Shape.Wires:
|
||||
for edge in DraftGeomUtils.sortEdges(w.Edges):
|
||||
g = DraftGeomUtils.geom(edge)
|
||||
if not DraftGeomUtils.isPlanar(obj.Shape):
|
||||
print "Error: The given object is not planar and cannot be converted into a sketch."
|
||||
return None
|
||||
if not addTo:
|
||||
nobj.Placement.Rotation = DraftGeomUtils.calculatePlacement(obj.Shape).Rotation
|
||||
edges = []
|
||||
for e in obj.Shape.Edges:
|
||||
g = (DraftGeomUtils.geom(e,nobj.Placement))
|
||||
if g:
|
||||
nobj.addGeometry(g)
|
||||
if autoconstraints:
|
||||
last = nobj.GeometryCount
|
||||
segs = range(last-len(w.Edges),last-1)
|
||||
for seg in segs:
|
||||
nobj.addConstraint(Constraint("Coincident",seg,EndPoint,seg+1,StartPoint))
|
||||
if DraftGeomUtils.isAligned(nobj.Geometry[seg],"x"):
|
||||
nobj.addConstraint(Constraint("Vertical",seg))
|
||||
elif DraftGeomUtils.isAligned(nobj.Geometry[seg],"y"):
|
||||
nobj.addConstraint(Constraint("Horizontal",seg))
|
||||
if w.isClosed:
|
||||
nobj.addConstraint(Constraint("Coincident",last-1,EndPoint,segs[0],StartPoint))
|
||||
else:
|
||||
for edge in obj.Shape.Edges:
|
||||
nobj.addGeometry(DraftGeomUtils.geom(edge))
|
||||
if autoconstraints:
|
||||
last = nobj.GeometryCount - 1
|
||||
if DraftGeomUtils.isAligned(nobj.Geometry[last],"x"):
|
||||
nobj.addConstraint(Constraint("Vertical",last))
|
||||
elif DraftGeomUtils.isAligned(nobj.Geometry[last],"y"):
|
||||
nobj.addConstraint(Constraint("Horizontal",last))
|
||||
ok = True
|
||||
if ok:
|
||||
FreeCAD.ActiveDocument.removeObject(obj.Name)
|
||||
|
|
|
@ -355,23 +355,29 @@ def findIntersection(edge1,edge2,infinite1=False,infinite2=False,ex1=False,ex2=F
|
|||
else :
|
||||
print "fcgeo: Unsupported curve type: (" + str(edge1.Curve) + ", " + str(edge2.Curve) + ")"
|
||||
|
||||
def geom(edge):
|
||||
"returns a Line, ArcOfCircle or Circle geom from the given edge"
|
||||
def geom(edge,plac=FreeCAD.Placement()):
|
||||
"returns a Line, ArcOfCircle or Circle geom from the given edge, according to the given placement"
|
||||
if isinstance(edge.Curve,Part.Line):
|
||||
return edge.Curve
|
||||
elif isinstance(edge.Curve,Part.Circle):
|
||||
if len(edge.Vertexes) == 1:
|
||||
return Part.Circle(edge.Curve.Center,edge.Curve.Axis,edge.Curve.Radius)
|
||||
else:
|
||||
ref = edge.Placement.multVec(Vector(1,0,0))
|
||||
ref = ref.sub(edge.Placement.Base) # we only want the orientation
|
||||
# reorienting the arc along the correct normal
|
||||
normal = plac.Rotation.multVec(FreeCAD.Vector(0,0,1))
|
||||
v1 = edge.Vertexes[0].Point
|
||||
v2 = edge.Vertexes[-1].Point
|
||||
c = edge.Curve.Center
|
||||
cu = Part.Circle(edge.Curve.Center,edge.Curve.Axis,edge.Curve.Radius)
|
||||
a1 = -DraftVecUtils.angle(v1.sub(c),ref,edge.Curve.Axis)
|
||||
a2 = -DraftVecUtils.angle(v2.sub(c),ref,edge.Curve.Axis)
|
||||
print "creating sketch arc from ",cu, ", p1=",v1, " (",math.degrees(a1), "d) p2=",v2," (", math.degrees(a2),"d)"
|
||||
cu = Part.Circle(edge.Curve.Center,normal,edge.Curve.Radius)
|
||||
ref = plac.Rotation.multVec(Vector(1,0,0))
|
||||
a1 = math.pi + DraftVecUtils.angle(v1.sub(c),ref,normal)
|
||||
a2 = DraftVecUtils.angle(v2.sub(c),ref,normal)
|
||||
|
||||
# direction check
|
||||
if a1 > 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:
|
||||
|
@ -454,13 +460,6 @@ def sortEdges(lEdges, aVertex=None):
|
|||
# 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'''
|
||||
|
@ -468,7 +467,7 @@ def sortEdges(lEdges, aVertex=None):
|
|||
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]):
|
||||
if aVertex.Point == inEdges[i].Vertexes[j-1].Point:
|
||||
instance = inEdges[i]
|
||||
count += 1
|
||||
linstances += [i,j-1,instance]
|
||||
|
@ -480,7 +479,7 @@ def sortEdges(lEdges, aVertex=None):
|
|||
else:
|
||||
result = lookfor(aVertex,lEdges)
|
||||
if result[0] != 0:
|
||||
if isSameVertex(aVertex,result[3].Vertexes[0]):
|
||||
if aVertex.Point == result[3].Vertexes[0].Point:
|
||||
return lEdges
|
||||
else:
|
||||
if isinstance(result[3].Curve,Part.Line):
|
||||
|
@ -505,7 +504,7 @@ def sortEdges(lEdges, aVertex=None):
|
|||
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
|
||||
# print "closed wire, starting from ",lEdges[0].Vertexes[0].Point
|
||||
return sortEdges(lEdges, lEdges[0].Vertexes[0])
|
||||
else :
|
||||
#print "looking ",aVertex.Point
|
||||
|
@ -514,7 +513,7 @@ def sortEdges(lEdges, aVertex=None):
|
|||
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]):
|
||||
if aVertex.Point == result[3].Vertexes[0].Point:
|
||||
#print "keeping"
|
||||
olEdges += [result[3]] + next
|
||||
else:
|
||||
|
@ -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,10 +1006,12 @@ 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):
|
||||
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
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user