Merge branch 'master' into logari81/sketcher
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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, °Min, °Max, &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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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> &);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 |
@@ -65,8 +65,6 @@ public:
|
||||
|
||||
protected:
|
||||
ViewProviderSketch *sketchView;
|
||||
std::string documentName;
|
||||
|
||||
TaskSketcherConstrains *Constraints;
|
||||
TaskSketcherGeneral *General;
|
||||
TaskSketcherMessages *Messages;
|
||||
|
||||
Reference in New Issue
Block a user