Merge branch 'master' into logari81/sketcher

This commit is contained in:
logari81
2012-07-17 10:15:51 +02:00
65 changed files with 2198 additions and 496 deletions

View File

@@ -75,6 +75,14 @@ def removeComponents(objectsList,host=None):
objectsList = [objectsList]
if host:
if Draft.getType(host) in ["Wall","Structure"]:
if hasattr(host,"Axes"):
a = host.Axes
print a
for o in objectsList[:]:
print o.Name
if o in a:
a.remove(o)
objectsList.remove(o)
s = host.Subtractions
for o in objectsList:
if not o in s:
@@ -154,31 +162,36 @@ 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:", wires
import Part
if not isinstance(wires,list):
if len(wires.Vertexes) < 3:
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])
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 +199,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):

View File

@@ -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):
@@ -79,7 +80,7 @@ def removeFromComponent(compobject,subobject):
it is added as a subtraction.'''
if compobject == subobject: return
found = False
attribs = ["Additions","Subtractions","Objects","Components","Base"]
attribs = ["Additions","Subtractions","Objects","Components","Base","Axes"]
for a in attribs:
if hasattr(compobject,a):
if a == "Base":

View File

@@ -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(objs)
render.addObjects(Draft.getGroupContents(objs,walls=True))
render.cut(obj.Source.Shape)
svg += render.getViewSVG(linewidth=linewidth)
svg += render.getSectionSVG(linewidth=linewidth*2)

View File

@@ -86,6 +86,8 @@ class _Structure(ArchComponent.Component):
str(translate("Arch","Axes systems this structure is built on")))
obj.addProperty("App::PropertyVector","Normal","Base",
str(translate("Arch","The normal extrusion direction of this object (keep (0,0,0) for automatic normal)")))
obj.addProperty("App::PropertyIntegerList","Exclude","Base",
str(translate("Arch","The element numbers to exclude when this structure is based on axes")))
self.Type = "Structure"
def execute(self,obj):
@@ -110,6 +112,12 @@ class _Structure(ArchComponent.Component):
pts.extend(DraftGeomUtils.findIntersection(e1,e2))
return pts
def getAxisPlacement(self,obj):
"returns an axis placement"
if obj.Axes:
return obj.Axes[0].Placement
return None
def createGeometry(self,obj):
import Part, DraftGeomUtils
@@ -174,22 +182,32 @@ class _Structure(ArchComponent.Component):
if not hole.Shape.isNull():
base = base.cut(hole.Shape)
hole.ViewObject.hide() # to be removed
# applying axes
pts = self.getAxisPoints(obj)
apl = self.getAxisPlacement(obj)
if pts:
fsh = []
for p in pts:
for i in range(len(pts)):
if hasattr(obj,"Exclude"):
if i in obj.Exclude:
continue
sh = base.copy()
sh.translate(p)
if apl:
sh.Placement.Rotation = apl.Rotation
sh.translate(pts[i])
fsh.append(sh)
obj.Shape = Part.makeCompound(fsh)
# finalizing
else:
if base:
if not base.isNull():
base = base.removeSplitter()
obj.Shape = base
if not DraftGeomUtils.isNull(pl):
obj.Placement = pl
if not DraftGeomUtils.isNull(pl):
obj.Placement = pl
class _ViewProviderStructure(ArchComponent.ViewProviderComponent):
"A View Provider for the Structure object"

View File

@@ -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,17 +168,24 @@ class Renderer:
def projectFace(self,face):
"projects a single face on the WP"
#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"
return None
norm = face[0].normalAt(0,0)
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 "new wire with ",len(verts)
wires.append(Part.makePolygon(verts))
try:
sh = ArchCommands.makeFace(wires)
@@ -188,6 +197,7 @@ class Renderer:
vnorm = self.wp.getLocalCoords(norm)
if vnorm.getAngle(sh.normalAt(0,0)) > 1:
sh.reverse()
#print "VRM: projectFace end: ",len(sh.Vertexes)," verts"
return [sh]+face[1:]
def flattenFace(self,face):
@@ -211,6 +221,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:
@@ -262,12 +273,10 @@ 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])
print "iscoplanar:",f.Vertexes[0].Point,f.normalAt(0,0),cutface.Vertexes[0].Point,cutface.normalAt(0,0)
if DraftGeomUtils.isCoplanar([f,cutface]):
print "COPLANAR"
sections.append([f,fill])
self.shapes = shapes
self.faces = faces
self.sections = sections
@@ -277,6 +286,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 +329,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 +475,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 +514,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 +529,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 +545,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"
@@ -544,19 +572,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):
@@ -566,44 +596,47 @@ class Renderer:
self.sort()
svg = ''
for f in self.faces:
fill = self.getFill(f[1])
svg +='<path '
svg += 'd="'
for w in f[0].Wires:
svg += self.getPathData(w)
svg += '" '
svg += 'stroke="#000000" '
svg += 'stroke-width="' + str(linewidth) + '" '
svg += 'style="stroke-width:' + str(linewidth) + ';'
svg += 'stroke-miterlimit:1;'
svg += 'stroke-linejoin:round;'
svg += 'stroke-dasharray:none;'
svg += 'fill:' + fill + ';'
svg += 'fill-rule: evenodd'
svg += '"/>\n'
if f:
fill = self.getFill(f[1])
svg +='<path '
svg += 'd="'
for w in f[0].Wires:
svg += self.getPathData(w)
svg += '" '
svg += 'stroke="#000000" '
svg += 'stroke-width="' + str(linewidth) + '" '
svg += 'style="stroke-width:' + str(linewidth) + ';'
svg += 'stroke-miterlimit:1;'
svg += 'stroke-linejoin:round;'
svg += 'stroke-dasharray:none;'
svg += 'fill:' + fill + ';'
svg += 'fill-rule: evenodd'
svg += '"/>\n'
return svg
def getSectionSVG(self,linewidth=0.02):
"Returns a SVG fragment from cut faces"
if DEBUG: print "Printing ", len(self.sections), " cutfaces"
if DEBUG: print "Printing ", len(self.sections), " sections"
if not self.oriented:
self.reorient()
svg = ''
for f in self.sections:
fill = self.getFill(f[1])
svg +='<path '
svg += 'd="'
for w in f[0].Wires:
svg += self.getPathData(w)
svg += '" '
svg += 'stroke="#000000" '
svg += 'stroke-width="' + str(linewidth) + '" '
svg += 'style="stroke-width:' + str(linewidth) + ';'
svg += 'stroke-miterlimit:1;'
svg += 'stroke-linejoin:round;'
svg += 'stroke-dasharray:none;'
svg += 'fill:' + fill + ';'
svg += 'fill-rule: evenodd'
svg += '"/>\n'
if f:
fill = self.getFill(f[1])
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" '
svg += 'stroke-width="' + str(linewidth) + '" '
svg += 'style="stroke-width:' + str(linewidth) + ';'
svg += 'stroke-miterlimit:1;'
svg += 'stroke-linejoin:round;'
svg += 'stroke-dasharray:none;'
svg += 'fill:' + fill + ';'
svg += 'fill-rule: evenodd'
svg += '"/>\n'
return svg

View File

@@ -72,7 +72,7 @@ How it works / how to extend:
'''
# import FreeCAD modules
import FreeCAD, math, sys, os, DraftVecUtils
import FreeCAD, math, sys, os, DraftVecUtils, Draft_rc
from FreeCAD import Vector
from pivy import coin
@@ -253,17 +253,43 @@ 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 = []
for obj in objectslist:
if obj.Type == "App::DocumentObjectGroup":
if obj.isDerivedFrom("App::DocumentObjectGroup"):
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 "edges: ", len(shape.Edges)
print "verts: ", len(shape.Vertexes)
if shape.Faces:
for f in range(len(shape.Faces)):
print "face ",f,":"
for v in shape.Faces[f].Vertexes:
print " ",v.Point
elif shape.Wires:
for w in range(len(shape.Wires)):
print "wire ",w,":"
for v in shape.Wires[w].Vertexes:
print " ",v.Point
else:
for v in shape.Vertexes:
print " ",v.Point
def formatObject(target,origin=None):
'''
formatObject(targetObject,[originObject]): This function applies
@@ -1514,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)
@@ -1560,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 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))
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)
ok = True
if ok:
FreeCAD.ActiveDocument.removeObject(obj.Name)
@@ -1945,7 +1955,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

View File

@@ -355,27 +355,33 @@ 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"
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
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)"
p= Part.ArcOfCircle(cu,a1,a2)
return p
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:
return edge.Curve
# 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,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:
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 round(dist.Length,DraftVecUtils.precision()) > 0:
return False
return True
def isPlanar(shape):

View File

@@ -288,11 +288,13 @@ class Snapper:
origin = Vector(self.snapInfo['x'],self.snapInfo['y'],self.snapInfo['z'])
winner = [Vector(0,0,0),None,Vector(0,0,0)]
for snap in snaps:
# if snap[0] == None: print "debug: Snapper: 'i[0]' is 'None'"
delta = snap[0].sub(origin)
if delta.Length < shortest:
shortest = delta.Length
winner = snap
if snap[0] == None:
print "debug: Snapper: snap point = ",snap
else:
delta = snap[0].sub(origin)
if delta.Length < shortest:
shortest = delta.Length
winner = snap
# see if we are out of the max radius, if any
if self.radius:

View File

@@ -565,7 +565,8 @@ bool MeshInput::LoadOFF (std::istream &rstrIn)
meshPoints.reserve(numPoints);
meshFacets.reserve(numFaces);
for (int i=0; i<numPoints; i++) {
int cntPoints = 0;
while (cntPoints < numPoints) {
if (!std::getline(rstrIn, line))
break;
if (boost::regex_match(line.c_str(), what, rx_p)) {
@@ -573,9 +574,12 @@ bool MeshInput::LoadOFF (std::istream &rstrIn)
fY = (float)std::atof(what[4].first);
fZ = (float)std::atof(what[7].first);
meshPoints.push_back(MeshPoint(Base::Vector3f(fX, fY, fZ)));
cntPoints++;
}
}
for (int i=0; i<numFaces; i++) {
int cntFaces = 0;
while (cntFaces < numFaces) {
if (!std::getline(rstrIn, line))
break;
if (boost::regex_match(line.c_str(), what, rx_f3)) {
@@ -586,6 +590,7 @@ bool MeshInput::LoadOFF (std::istream &rstrIn)
i3 = std::atoi(what[4].first);
item.SetVertices(i1,i2,i3);
meshFacets.push_back(item);
cntFaces++;
}
}
else if (boost::regex_match(line.c_str(), what, rx_f4)) {
@@ -601,6 +606,7 @@ bool MeshInput::LoadOFF (std::istream &rstrIn)
item.SetVertices(i3,i4,i1);
meshFacets.push_back(item);
cntFaces++;
}
}
}

View File

@@ -677,9 +677,33 @@
<UserDocu>Returns a reparametrized copy of this surface</UserDocu>
</Documentation>
</Methode>
<Methode Name="approximate">
<Documentation>
<UserDocu>
approximate(points, degMin, degMax, continuity, tol)
approximate(zPoints, degMin, degMax, continuity, tol, X0, dX, Y0, dY)
Replaces this B-Spline surface by approximating a set of points.
continuity is an integer between 0 and 3
</UserDocu>
</Documentation>
</Methode>
<Methode Name="interpolate">
<Documentation>
<UserDocu>Replaces this B-Spline surface by interpolating a set of points.</UserDocu>
<UserDocu>
interpolate(points)
interpolate(zpoints, X0, dX, Y0, dY)
Replaces this B-Spline surface by interpolating a set of points.
The resulting surface is of degree 3 and continuity C2.
Arguments:
a 2 dimensional array of vectors, that the surface passes through
or
a 2 dimensional array of floats with the z values,
the x starting point X0 (float),
the x increment dX (float),
the y starting point Y0 and increment dY
</UserDocu>
</Documentation>
</Methode>
</PythonExport>

View File

@@ -33,6 +33,7 @@
# include <TColgp_Array2OfPnt.hxx>
# include <Precision.hxx>
# include <GeomAPI_PointsToBSplineSurface.hxx>
# include <GeomAbs_Shape.hxx>
#endif
#include <Base/GeometryPyCXX.h>
@@ -43,6 +44,7 @@
#include "BSplineSurfacePy.h"
#include "BSplineSurfacePy.cpp"
using namespace Part;
// returns a string which represents the object e.g. when printed in python
@@ -1244,13 +1246,21 @@ PyObject* BSplineSurfacePy::reparametrize(PyObject * args)
}
}
PyObject* BSplineSurfacePy::interpolate(PyObject *args)
PyObject* BSplineSurfacePy::approximate(PyObject *args)
{
PyObject* obj;
double tol3d = Precision::Approximation();
PyObject* closed = Py_False;
PyObject* t1=0; PyObject* t2=0;
if (!PyArg_ParseTuple(args, "O!",&(PyList_Type), &obj))
Standard_Integer degMin=0;
Standard_Integer degMax=0;
Standard_Integer continuity=0;
Standard_Real tol3d = Precision::Approximation();
Standard_Real X0=0;
Standard_Real dX=0;
Standard_Real Y0=0;
Standard_Real dY=0;
int len = PyTuple_GET_SIZE(args);
if (!PyArg_ParseTuple(args, "O!iiid|dddd",&(PyList_Type), &obj, &degMin, &degMax, &continuity, &tol3d, &X0, &dX, &Y0, &dY))
return 0;
try {
Py::List list(obj);
@@ -1258,6 +1268,8 @@ PyObject* BSplineSurfacePy::interpolate(PyObject *args)
Py::List col(list.getItem(0));
Standard_Integer lv = col.size();
TColgp_Array2OfPnt interpolationPoints(1, lu, 1, lv);
TColStd_Array2OfReal zPoints(1, lu, 1, lv);
//Base::Console().Message("lu=%d, lv=%d\n", lu, lv);
Standard_Integer index1 = 0;
Standard_Integer index2 = 0;
@@ -1267,10 +1279,97 @@ PyObject* BSplineSurfacePy::interpolate(PyObject *args)
Py::List row(*it1);
for (Py::List::iterator it2 = row.begin(); it2 != row.end(); ++it2) {
index2++;
Py::Vector v(*it2);
Base::Vector3d pnt = v.toVector();
gp_Pnt newPoint(pnt.x,pnt.y,pnt.z);
interpolationPoints.SetValue(index1, index2, newPoint);
if(len == 5){
Py::Vector v(*it2);
Base::Vector3d pnt = v.toVector();
gp_Pnt newPoint(pnt.x,pnt.y,pnt.z);
interpolationPoints.SetValue(index1, index2, newPoint);
}
else {
Standard_Real val = PyFloat_AsDouble((*it2).ptr());
zPoints.SetValue(index1, index2, val);
}
}
}
if(continuity<0 || continuity>3){
Standard_Failure::Raise("continuity must be between 0 and 3");
}
GeomAbs_Shape c;
switch(continuity){
case 0:
c = GeomAbs_C0;
case 1:
c = GeomAbs_C1;
case 2:
c = GeomAbs_C2;
case 3:
c = GeomAbs_C3;
}
if (interpolationPoints.RowLength() < 2 || interpolationPoints.ColLength() < 2) {
Standard_Failure::Raise("not enough points given");
}
GeomAPI_PointsToBSplineSurface surInterpolation;
if(len == 5){
surInterpolation.Init(interpolationPoints, degMin, degMax, c, tol3d);
}
else {
surInterpolation.Init(zPoints, X0, dX, Y0, dY, degMin, degMax, c, tol3d);
}
Handle_Geom_BSplineSurface sur(surInterpolation.Surface());
this->getGeomBSplineSurfacePtr()->setHandle(sur);
Py_Return;
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();
std::string err = e->GetMessageString();
if (err.empty()) err = e->DynamicType()->Name();
PyErr_SetString(PyExc_Exception, err.c_str());
return 0;
}
}
PyObject* BSplineSurfacePy::interpolate(PyObject *args)
{
PyObject* obj;
Standard_Real tol3d = Precision::Approximation();
Standard_Real X0=0;
Standard_Real dX=0;
Standard_Real Y0=0;
Standard_Real dY=0;
int len = PyTuple_GET_SIZE(args);
if (!PyArg_ParseTuple(args, "O!|dddd",&(PyList_Type), &obj, &X0, &dX, &Y0, &dY))
return 0;
try {
Py::List list(obj);
Standard_Integer lu = list.size();
Py::List col(list.getItem(0));
Standard_Integer lv = col.size();
TColgp_Array2OfPnt interpolationPoints(1, lu, 1, lv);
TColStd_Array2OfReal zPoints(1, lu, 1, lv);
Standard_Integer index1 = 0;
Standard_Integer index2 = 0;
for (Py::List::iterator it1 = list.begin(); it1 != list.end(); ++it1) {
index1++;
index2=0;
Py::List row(*it1);
for (Py::List::iterator it2 = row.begin(); it2 != row.end(); ++it2) {
index2++;
if(len == 1){
Py::Vector v(*it2);
Base::Vector3d pnt = v.toVector();
gp_Pnt newPoint(pnt.x,pnt.y,pnt.z);
interpolationPoints.SetValue(index1, index2, newPoint);
}
else {
Standard_Real val = PyFloat_AsDouble((*it2).ptr());
zPoints.SetValue(index1, index2, val);
}
}
}
@@ -1279,7 +1378,12 @@ PyObject* BSplineSurfacePy::interpolate(PyObject *args)
}
GeomAPI_PointsToBSplineSurface surInterpolation;
surInterpolation.Interpolate (interpolationPoints);
if(len == 1){
surInterpolation.Interpolate (interpolationPoints);
}
else {
surInterpolation.Interpolate(zPoints, X0, dX, Y0, dY);
}
Handle_Geom_BSplineSurface sur(surInterpolation.Surface());
this->getGeomBSplineSurfacePtr()->setHandle(sur);
Py_Return;

View File

@@ -47,6 +47,7 @@
#include <Gui/Command.h>
#include <Gui/View3DInventor.h>
#include <Gui/View3DInventorViewer.h>
#include <Gui/SoFCUnifiedSelection.h>
#include <Gui/TaskView/TaskView.h>
#include <Mod/Part/App/Tools.h>
@@ -270,6 +271,9 @@ DlgPrimitives::~DlgPrimitives()
void DlgPrimitives::pickCallback(void * ud, SoEventCallback * n)
{
const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent*>(n->getEvent());
Picker* pick = reinterpret_cast<Picker*>(ud);
if (pick->exitCode >= 0)
pick->loop.exit(pick->exitCode);
// Mark all incoming mouse button events as handled, especially, to deactivate the selection node
n->setHandled();
@@ -277,16 +281,14 @@ void DlgPrimitives::pickCallback(void * ud, SoEventCallback * n)
if (mbe->getState() == SoButtonEvent::DOWN) {
const SoPickedPoint * point = n->getPickedPoint();
if (point) {
Picker* pick = reinterpret_cast<Picker*>(ud);
if (pick->pickedPoint(point)) {
pick->loop.exit(0);
pick->exitCode = 0;
}
}
}
}
else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2) {
if (mbe->getState() == SoButtonEvent::UP) {
Picker* pick = reinterpret_cast<Picker*>(ud);
pick->loop.exit(1);
}
}
@@ -305,9 +307,17 @@ void DlgPrimitives::executeCallback(Picker* p)
if (!viewer->isEditing()) {
viewer->setEditing(true);
viewer->setRedirectToSceneGraph(true);
SoNode* root = viewer->getSceneGraph();
int mode;
if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId())) {
mode = static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.getValue();
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.setValue(Gui::SoFCUnifiedSelection::OFF);
}
viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback, p);
this->setDisabled(true);
int ret = p->loop.exec();
if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId()))
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.setValue(mode);
this->setEnabled(true);
viewer->setEditing(false);
viewer->setRedirectToSceneGraph(false);
@@ -587,6 +597,9 @@ Location::~Location()
viewer->setEditing(false);
viewer->setRedirectToSceneGraph(false);
viewer->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback,this);
SoNode* root = viewer->getSceneGraph();
if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId()))
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.setValue(this->mode);
}
}
@@ -605,6 +618,11 @@ void Location::on_viewPositionButton_clicked()
viewer->setEditing(true);
viewer->setRedirectToSceneGraph(true);
viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback, this);
SoNode* root = viewer->getSceneGraph();
if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId())) {
this->mode = static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.getValue();
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.setValue(Gui::SoFCUnifiedSelection::OFF);
}
}
}
}
@@ -617,15 +635,7 @@ void Location::pickCallback(void * ud, SoEventCallback * n)
// Mark all incoming mouse button events as handled, especially, to deactivate the selection node
n->getAction()->setHandled();
if (mbe->getButton() == SoMouseButtonEvent::BUTTON1) {
if (mbe->getState() == SoButtonEvent::UP) {
n->setHandled();
view->setEditing(false);
view->setRedirectToSceneGraph(false);
Location* dlg = reinterpret_cast<Location*>(ud);
dlg->activeView = 0;
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback,ud);
}
else if (mbe->getState() == SoButtonEvent::DOWN) {
if (mbe->getState() == SoButtonEvent::DOWN) {
const SoPickedPoint * point = n->getPickedPoint();
if (point) {
SbVec3f pnt = point->getPoint();
@@ -637,6 +647,19 @@ void Location::pickCallback(void * ud, SoEventCallback * n)
}
}
}
else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2) {
if (mbe->getState() == SoButtonEvent::UP) {
n->setHandled();
view->setEditing(false);
view->setRedirectToSceneGraph(false);
Location* dlg = reinterpret_cast<Location*>(ud);
dlg->activeView = 0;
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), pickCallback,ud);
SoNode* root = view->getSceneGraph();
if (root && root->getTypeId().isDerivedFrom(Gui::SoFCUnifiedSelection::getClassTypeId()))
static_cast<Gui::SoFCUnifiedSelection*>(root)->selectionMode.setValue(static_cast<Location*>(ud)->mode);
}
}
}
QString Location::toPlacement() const

View File

@@ -39,7 +39,7 @@ namespace PartGui {
class Picker
{
public:
Picker()
Picker() : exitCode(-1)
{
}
virtual ~Picker()
@@ -51,6 +51,7 @@ public:
void createPrimitive(QWidget* widget, const QString&, Gui::Document*);
QString toPlacement(const gp_Ax2&) const;
int exitCode;
QEventLoop loop;
};
@@ -88,6 +89,7 @@ private Q_SLOTS:
private:
static void pickCallback(void * ud, SoEventCallback * n);
int mode;
QPointer<QWidget> activeView;
Ui_Location ui;
};

View File

@@ -142,6 +142,26 @@ void ViewProviderBoolean::updateData(const App::Property* prop)
this->DiffuseColor.setValues(colBool);
}
}
else if (prop->getTypeId() == App::PropertyLink::getClassTypeId()) {
App::DocumentObject *pBase = static_cast<const App::PropertyLink*>(prop)->getValue();
if (pBase)
Gui::Application::Instance->hideViewProvider(pBase);
}
}
bool ViewProviderBoolean::onDelete(const std::vector<std::string> &)
{
// get the input shapes
Part::Boolean* pBool = static_cast<Part::Boolean*>(getObject());
App::DocumentObject *pBase = pBool->Base.getValue();
App::DocumentObject *pTool = pBool->Tool.getValue();
if (pBase)
Gui::Application::Instance->showViewProvider(pBase);
if (pTool)
Gui::Application::Instance->showViewProvider(pTool);
return true;
}
PROPERTY_SOURCE(PartGui::ViewProviderMultiFuse,PartGui::ViewProviderPart)
@@ -207,6 +227,26 @@ void ViewProviderMultiFuse::updateData(const App::Property* prop)
if (setColor)
this->DiffuseColor.setValues(colBool);
}
else if (prop->getTypeId() == App::PropertyLinkList::getClassTypeId()) {
std::vector<App::DocumentObject*> pShapes = static_cast<const App::PropertyLinkList*>(prop)->getValues();
for (std::vector<App::DocumentObject*>::iterator it = pShapes.begin(); it != pShapes.end(); ++it) {
if (*it)
Gui::Application::Instance->hideViewProvider(*it);
}
}
}
bool ViewProviderMultiFuse::onDelete(const std::vector<std::string> &)
{
// get the input shapes
Part::MultiFuse* pBool = static_cast<Part::MultiFuse*>(getObject());
std::vector<App::DocumentObject*> pShapes = pBool->Shapes.getValues();
for (std::vector<App::DocumentObject*>::iterator it = pShapes.begin(); it != pShapes.end(); ++it) {
if (*it)
Gui::Application::Instance->showViewProvider(*it);
}
return true;
}
@@ -273,4 +313,24 @@ void ViewProviderMultiCommon::updateData(const App::Property* prop)
if (setColor)
this->DiffuseColor.setValues(colBool);
}
else if (prop->getTypeId() == App::PropertyLinkList::getClassTypeId()) {
std::vector<App::DocumentObject*> pShapes = static_cast<const App::PropertyLinkList*>(prop)->getValues();
for (std::vector<App::DocumentObject*>::iterator it = pShapes.begin(); it != pShapes.end(); ++it) {
if (*it)
Gui::Application::Instance->hideViewProvider(*it);
}
}
}
bool ViewProviderMultiCommon::onDelete(const std::vector<std::string> &)
{
// get the input shapes
Part::MultiCommon* pBool = static_cast<Part::MultiCommon*>(getObject());
std::vector<App::DocumentObject*> pShapes = pBool->Shapes.getValues();
for (std::vector<App::DocumentObject*>::iterator it = pShapes.begin(); it != pShapes.end(); ++it) {
if (*it)
Gui::Application::Instance->showViewProvider(*it);
}
return true;
}

View File

@@ -43,6 +43,7 @@ public:
std::vector<App::DocumentObject*> claimChildren(void) const;
QIcon getIcon(void) const;
void updateData(const App::Property*);
bool onDelete(const std::vector<std::string> &);
};
/// ViewProvider for the MultiFuse feature
@@ -60,6 +61,7 @@ public:
std::vector<App::DocumentObject*> claimChildren(void) const;
QIcon getIcon(void) const;
void updateData(const App::Property*);
bool onDelete(const std::vector<std::string> &);
};
/// ViewProvider for the MultiFuse feature
@@ -77,6 +79,7 @@ public:
std::vector<App::DocumentObject*> claimChildren(void) const;
QIcon getIcon(void) const;
void updateData(const App::Property*);
bool onDelete(const std::vector<std::string> &);
};

View File

@@ -243,6 +243,17 @@ std::vector<App::DocumentObject*> ViewProviderFillet::claimChildren() const
return temp;
}
bool ViewProviderFillet::onDelete(const std::vector<std::string> &)
{
// get the input shape
Part::Fillet* pFillet = static_cast<Part::Fillet*>(getObject());
App::DocumentObject *pBase = pFillet->Base.getValue();
if (pBase)
Gui::Application::Instance->showViewProvider(pBase);
return true;
}
// ---------------------------------------
PROPERTY_SOURCE(PartGui::ViewProviderChamfer, PartGui::ViewProviderPart)
@@ -296,6 +307,17 @@ std::vector<App::DocumentObject*> ViewProviderChamfer::claimChildren() const
return temp;
}
bool ViewProviderChamfer::onDelete(const std::vector<std::string> &)
{
// get the input shape
Part::Chamfer* pChamfer = static_cast<Part::Chamfer*>(getObject());
App::DocumentObject *pBase = pChamfer->Base.getValue();
if (pBase)
Gui::Application::Instance->showViewProvider(pBase);
return true;
}
// ---------------------------------------
PROPERTY_SOURCE(PartGui::ViewProviderRevolution, PartGui::ViewProviderPart)
@@ -315,3 +337,14 @@ std::vector<App::DocumentObject*> ViewProviderRevolution::claimChildren() const
temp.push_back(static_cast<Part::Revolution*>(getObject())->Source.getValue());
return temp;
}
bool ViewProviderRevolution::onDelete(const std::vector<std::string> &)
{
// get the input shape
Part::Revolution* pRevolve = static_cast<Part::Revolution*>(getObject());
App::DocumentObject *pBase = pRevolve->Source.getValue();
if (pBase)
Gui::Application::Instance->showViewProvider(pBase);
return true;
}

View File

@@ -64,6 +64,7 @@ public:
//@{
void setupContextMenu(QMenu*, QObject*, const char*);
std::vector<App::DocumentObject*> claimChildren() const;
bool onDelete(const std::vector<std::string> &);
protected:
bool setEdit(int ModNum);
@@ -84,6 +85,7 @@ public:
//@{
void setupContextMenu(QMenu*, QObject*, const char*);
std::vector<App::DocumentObject*> claimChildren() const;
bool onDelete(const std::vector<std::string> &);
protected:
bool setEdit(int ModNum);
@@ -103,6 +105,7 @@ public:
/// grouping handling
std::vector<App::DocumentObject*> claimChildren(void)const;
bool onDelete(const std::vector<std::string> &);
};
} // namespace PartGui

View File

@@ -102,8 +102,6 @@ void CmdRaytracingWriteCamera::activated(int iMsg)
SoInput in;
in.setBuffer((void*)ppReturn,std::strlen(ppReturn));
//if (!in.openFile(filename)) { exit(1); }
SoNode* rootNode;
SoDB::read(&in,rootNode);

View File

@@ -224,7 +224,11 @@ Base::Vector3d SketchObject::getPoint(int GeoId, PointPos PosId) const
assert(GeoId == H_Axis || GeoId == V_Axis ||
(GeoId <= getHighestCurveIndex() && GeoId >= -getExternalGeometryCount()) );
const Part::Geometry *geo = getGeometry(GeoId);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
if (geo->getTypeId() == Part::GeomPoint::getClassTypeId()) {
const Part::GeomPoint *p = dynamic_cast<const Part::GeomPoint*>(geo);
if (PosId == start || PosId == mid || PosId == end)
return p->getPoint();
} else if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment*>(geo);
if (PosId == start)
return lineSeg->getStartPoint();

View File

@@ -14,8 +14,8 @@
height="64px"
id="svg2726"
sodipodi:version="0.32"
inkscape:version="0.48.1 r9760"
sodipodi:docname="Sketcher_Point.svg"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="Sketcher_CreatePoint.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"
inkscape:export-filename="/home/yorik/Sources/FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_CreatePoint.svg.png"
@@ -87,6 +87,17 @@
id="radialGradient3888"
xlink:href="#linearGradient3144-3"
inkscape:collect="always" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3144"
id="radialGradient3767"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
cx="225.26402"
cy="672.79736"
fx="225.26402"
fy="672.79736"
r="34.345188" />
</defs>
<sodipodi:namedview
id="base"
@@ -96,17 +107,17 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.8890873"
inkscape:cx="18.496032"
inkscape:cx="33.923816"
inkscape:cy="23.749836"
inkscape:current-layer="g4289"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1280"
inkscape:window-height="756"
inkscape:window-x="0"
inkscape:window-y="22"
inkscape:window-maximized="1" />
inkscape:window-width="657"
inkscape:window-height="716"
inkscape:window-x="710"
inkscape:window-y="24"
inkscape:window-maximized="0" />
<metadata
id="metadata2731">
<rdf:RDF>
@@ -115,7 +126,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -133,35 +144,29 @@
sodipodi:cy="655.2193"
sodipodi:cx="197.14285"
id="path3162-2"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.80000019000000044;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.67000001"
style="opacity:0.67000002;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.09976673;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
sodipodi:type="arc"
transform="matrix(-2.047093,-0.04650869,0.04650869,-2.047093,549.55577,1983.2711)" />
<g
inkscape:export-ydpi="7.0721951"
inkscape:export-xdpi="7.0721951"
inkscape:export-filename="/home/yorik/Documents/Lab/Draft/icons/line.png"
transform="matrix(-2.047093,-0.04650867,0.04650867,-2.047093,528.32631,1950.9451)"
id="g3160">
<path
sodipodi:type="arc"
style="fill:#ff2100;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.80000019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path3162"
sodipodi:cx="197.14285"
sodipodi:cy="655.2193"
sodipodi:rx="48.57143"
sodipodi:ry="48.57143"
d="m 245.71428,655.2193 c 0,26.82526 -21.74617,48.57143 -48.57143,48.57143 -26.82526,0 -48.57143,-21.74617 -48.57143,-48.57143 0,-26.82526 21.74617,-48.57143 48.57143,-48.57143 26.82526,0 48.57143,21.74617 48.57143,48.57143 z" />
<path
sodipodi:type="arc"
style="fill:url(#radialGradient3850);fill-opacity:1;stroke:none"
id="path3164"
sodipodi:cx="225.26402"
sodipodi:cy="672.79736"
sodipodi:rx="34.345188"
sodipodi:ry="23.991123"
d="m 259.60921,672.79736 c 0,13.24993 -15.37686,23.99113 -34.34519,23.99113 -18.96832,0 -34.34519,-10.7412 -34.34519,-23.99113 0,-13.24993 15.37687,-23.99112 34.34519,-23.99112 18.96833,0 34.34519,10.74119 34.34519,23.99112 z"
transform="matrix(0.8513023,-0.5246754,0.5246754,0.8513023,-338.69692,214.19328)" />
</g>
transform="matrix(-1.135537,-0.02584694,0.0257987,-1.13766,378.69194,1376.1392)" />
<path
d="m 245.71428,655.2193 a 48.57143,48.57143 0 1 1 -97.14286,0 48.57143,48.57143 0 1 1 97.14286,0 z"
sodipodi:ry="48.57143"
sodipodi:rx="48.57143"
sodipodi:cy="655.2193"
sodipodi:cx="197.14285"
id="path3162"
style="fill:#ff2100;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.09976673;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
sodipodi:type="arc"
transform="matrix(-1.135537,-0.02584692,0.02579869,-1.13766,366.91582,1358.1743)" />
<path
transform="matrix(-0.9802212,0.57489869,-0.57382585,-0.98205382,757.04461,1123.2494)"
d="m 259.60921,672.79736 a 34.345188,23.991123 0 1 1 -68.69038,0 34.345188,23.991123 0 1 1 68.69038,0 z"
sodipodi:ry="23.991123"
sodipodi:rx="34.345188"
sodipodi:cy="672.79736"
sodipodi:cx="225.26402"
id="path3164"
style="fill:url(#radialGradient3767);fill-opacity:1;stroke:none"
sodipodi:type="arc" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -65,8 +65,6 @@ public:
protected:
ViewProviderSketch *sketchView;
std::string documentName;
TaskSketcherConstrains *Constraints;
TaskSketcherGeneral *General;
TaskSketcherMessages *Messages;