Merge branch 'master' into drawingpage

This commit is contained in:
Yorik van Havre 2011-12-26 12:31:01 -02:00
commit 0ce7a0dda7
22 changed files with 1005 additions and 825 deletions

View File

@ -605,9 +605,9 @@ void PropertyLinkSubList::Save (Base::Writer &writer) const
writer.Stream() << writer.ind() << "<LinkSubList count=\"" << getSize() <<"\">" << endl;
writer.incInd();
for(int i = 0;i<getSize(); i++)
writer.Stream() << writer.ind() <<
writer.Stream() << writer.ind() <<
"<Link " <<
"obj=\"" << _lValueList[i]->getNameInDocument() <<
"obj=\"" << _lValueList[i]->getNameInDocument() << "\" " <<
"sub=\"" << _lSubList[i] <<
"\"/>" << endl; ;
writer.decInd();
@ -670,7 +670,7 @@ unsigned int PropertyLinkSubList::getMemSize (void) const
{
unsigned int size = static_cast<unsigned int>(_lValueList.size() * sizeof(App::DocumentObject *));
for(int i = 0;i<getSize(); i++)
size += _lSubList[i].size();
size += _lSubList[i].size();
return size;
}

View File

@ -51,7 +51,7 @@ class _CommandWindow:
def GetResources(self):
return {'Pixmap' : 'Arch_Window',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Window","Window"),
'Accel': "W, I",
'Accel': "W, N",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Window","Creates a window object from scratch or from a selected object (wire, rectangle or sketch)")}
def Activated(self):

View File

@ -1931,6 +1931,10 @@ class _Wire:
"The base object is the wire is formed from 2 objects")
obj.addProperty("App::PropertyLink","Tool","Base",
"The tool object is the wire is formed from 2 objects")
obj.addProperty("App::PropertyVector","Start","Base",
"The start point of this line")
obj.addProperty("App::PropertyVector","End","Base",
"The end point of this line")
obj.Proxy = self
obj.Closed = False
self.Type = "Wire"
@ -1941,6 +1945,26 @@ class _Wire:
def onChanged(self, fp, prop):
if prop in ["Points","Closed","Base","Tool"]:
self.createGeometry(fp)
if prop == "Points":
if fp.Start != fp.Points[0]:
fp.Start = fp.Points[0]
if fp.End != fp.Points[-1]:
fp.End = fp.Points[-1]
if len(fp.Points) > 2:
fp.setEditorMode('Start',2)
fp.setEditorMode('End',2)
elif prop == "Start":
pts = fp.Points
if pts:
if pts[0] != fp.Start:
pts[0] = fp.Start
fp.Points = pts
elif prop == "End":
pts = fp.Points
if len(pts) > 1:
if pts[-1] != fp.End:
pts[-1] = fp.End
fp.Points = pts
def createGeometry(self,fp):
plm = fp.Placement

View File

@ -533,11 +533,10 @@ class DraftToolBar:
self.radiusValue.selectAll()
def offUi(self):
todo.delay(FreeCADGui.Control.closeDialog,None)
if self.taskmode:
self.isTaskOn = False
todo.delay(FreeCADGui.Control.closeDialog,None)
self.baseWidget = QtGui.QWidget()
# print "UI turned off"
else:
self.setTitle(translate("draft", "None"))
self.labelx.setText(translate("draft", "X"))
@ -637,6 +636,7 @@ class DraftToolBar:
if not self.taskmode:
self.labelx.setText(translate("draft", "Pick Object"))
self.labelx.show()
self.makeDumbTask()
def editUi(self):
self.taskUi(translate("draft", "Edit"))
@ -701,6 +701,15 @@ class DraftToolBar:
else:
self.layout.setDirection(QtGui.QBoxLayout.LeftToRight)
def makeDumbTask(self):
"create a dumb taskdialog to prevent deleting the temp object"
class TaskPanel:
def __init__(self):
pass
def getStandardButtons(self):
return 0
panel = TaskPanel()
FreeCADGui.Control.showDialog(panel)
#---------------------------------------------------------------------------
# Processing functions

View File

@ -38,7 +38,17 @@ class Snapper:
and arch module to manage object snapping. It is responsible for
finding snap points and displaying snap markers. Usually You
only need to invoke it's snap() function, all the rest is taken
care of."""
care of.
3 functions are useful for the scriptwriter: snap(), constrain()
or getPoint() which is an all-in-one combo.
The indivudual snapToXXX() functions return a snap definition in
the form [real_point,marker_type,visual_point], and are not
meant to be used directly, they are all called when necessary by
the general snap() function.
"""
def __init__(self):
self.lastObj = [None,None]
@ -57,6 +67,7 @@ class Snapper:
self.extLine = None
self.grid = None
self.constrainLine = None
self.trackLine = None
# the snapmarker has "dot","circle" and "square" available styles
self.mk = {'passive':'circle',
@ -98,6 +109,8 @@ class Snapper:
self.unconstrain()
return point
snaps = []
# type conversion if needed
if isinstance(screenpos,list):
screenpos = tuple(screenpos)
@ -141,7 +154,7 @@ class Snapper:
info = FreeCADGui.ActiveDocument.ActiveView.getObjectInfo((screenpos[0],screenpos[1]))
# checking if parallel to one of the edges of the last objects
point = self.snapToExtensions(point,lastpoint)
point = self.snapToExtensions(point,lastpoint,constrain)
if not info:
@ -152,7 +165,6 @@ class Snapper:
else:
# we have an object to snap to
snaps = []
obj = FreeCAD.ActiveDocument.getObject(info['Object'])
if not obj:
@ -213,6 +225,9 @@ class Snapper:
self.lastObj[0] = self.lastObj[1]
self.lastObj[1] = obj.Name
if not snaps:
return point
# calculating the nearest snap point
shortest = 1000000000000000000
origin = Vector(info['x'],info['y'],info['z'])
@ -241,8 +256,22 @@ class Snapper:
# return the final point
return cstr(winner[2])
def snapToExtensions(self,point,last):
def snapToExtensions(self,point,last,constrain):
"returns a point snapped to extension or parallel line to last object, if any"
tsnap = self.snapToExtOrtho(last,constrain)
if tsnap:
if (tsnap[0].sub(point)).Length < self.radius:
if self.tracker:
self.tracker.setCoords(tsnap[2])
self.tracker.setMarker(self.mk[tsnap[1]])
self.tracker.on()
if self.extLine:
self.extLine.p2(tsnap[2])
self.extLine.on()
self.setCursor(tsnap[1])
return tsnap[2]
for o in [self.lastObj[1],self.lastObj[0]]:
if o:
ob = FreeCAD.ActiveDocument.getObject(o)
@ -333,24 +362,30 @@ class Snapper:
def snapToOrtho(self,shape,last,constrain):
"returns a list of ortho snap locations"
snaps = []
if constrain != None:
if constrain:
if isinstance(shape,Part.Edge):
if last:
if isinstance(shape.Curve,Part.Line):
p1 = shape.Vertexes[0].Point
p2 = shape.Vertexes[-1].Point
if (constrain == 0):
if ((last.y > p1.y) and (last.y < p2.y) or (last.y > p2.y) and (last.y < p1.y)):
pc = (last.y-p1.y)/(p2.y-p1.y)
cp = (Vector(p1.x+pc*(p2.x-p1.x),p1.y+pc*(p2.y-p1.y),p1.z+pc*(p2.z-p1.z)))
snaps.append([cp,'ortho',cp])
elif (constrain == 1):
if ((last.x > p1.x) and (last.x < p2.x) or (last.x > p2.x) and (last.x < p1.x)):
pc = (last.x-p1.x)/(p2.x-p1.x)
cp = (Vector(p1.x+pc*(p2.x-p1.x),p1.y+pc*(p2.y-p1.y),p1.z+pc*(p2.z-p1.z)))
snaps.append([cp,'ortho',cp])
if self.constraintAxis:
tmpEdge = Part.Line(last,last.add(self.constraintAxis)).toShape()
# get the intersection points
pt = fcgeo.findIntersection(tmpEdge,shape,True,True)
if pt:
for p in pt:
snaps.append([p,'ortho',p])
return snaps
def snapToExtOrtho(self,last,constrain):
"returns an ortho X extension snap location"
if constrain and last and self.constraintAxis and self.extLine:
tmpEdge1 = Part.Line(last,last.add(self.constraintAxis)).toShape()
tmpEdge2 = Part.Line(self.extLine.p1(),self.extLine.p2()).toShape()
# get the intersection points
pt = fcgeo.findIntersection(tmpEdge1,tmpEdge2,True,True)
if pt:
return [pt[0],'ortho',pt[0]]
return None
def snapToAngles(self,shape):
"returns a list of angle snap locations"
snaps = []
@ -511,316 +546,54 @@ class Snapper:
self.affinity = None
if self.constrainLine:
self.constrainLine.off()
# deprecated ##################################################################
# last snapped objects, for quick intersection calculation
lastObj = [0,0]
def getPoint(self,last=None,callback=None):
"""getPoint([last],[callback]) : gets a 3D point from the screen. You can provide an existing point,
in that case additional snap options and a tracker are available. You can also passa function as
callback, which will get called with the resulting point as argument, when a point is clicked:
def cb(point):
print "got a 3D point: ",point
FreeCADGui.Snapper.getPoint(callback=cb)
"""
self.pt = None
self.ui = FreeCADGui.draftToolBar
self.view = FreeCADGui.ActiveDocument.ActiveView
# setting a track line if we got an existing point
if last:
if not self.trackLine:
self.trackLine = DraftTrackers.lineTracker()
self.trackLine.p1(last)
self.trackLine.on()
def move(event_cb):
event = event_cb.getEvent()
mousepos = event.getPosition()
ctrl = event.wasCtrlDown()
shift = event.wasShiftDown()
self.pt = FreeCADGui.Snapper.snap(mousepos,lastpoint=last,active=ctrl,constrain=shift)
self.ui.displayPoint(self.pt,last,plane=FreeCAD.DraftWorkingPlane,mask=FreeCADGui.Snapper.affinity)
if self.trackLine:
self.trackLine.p2(self.pt)
def snapPoint(target,point,cursor,ctrl=False):
'''
Snap function used by the Draft tools
Currently has two modes: passive and active. Pressing CTRL while
clicking puts you in active mode:
- In passive mode (an open circle appears), your point is
snapped to the nearest point on any underlying geometry.
- In active mode (ctrl pressed, a filled circle appears), your point
can currently be snapped to the following points:
- Nodes and midpoints of all Part shapes
- Nodes and midpoints of lines/wires
- Centers and quadrant points of circles
- Endpoints of arcs
- Intersection between line, wires segments, arcs and circles
- When constrained (SHIFT pressed), Intersections between
constraining axis and lines/wires
'''
def getConstrainedPoint(edge,last,constrain):
"check for constrained snappoint"
p1 = edge.Vertexes[0].Point
p2 = edge.Vertexes[-1].Point
ar = []
if (constrain == 0):
if ((last.y > p1.y) and (last.y < p2.y) or (last.y > p2.y) and (last.y < p1.y)):
pc = (last.y-p1.y)/(p2.y-p1.y)
cp = (Vector(p1.x+pc*(p2.x-p1.x),p1.y+pc*(p2.y-p1.y),p1.z+pc*(p2.z-p1.z)))
ar.append([cp,1,cp]) # constrainpoint
if (constrain == 1):
if ((last.x > p1.x) and (last.x < p2.x) or (last.x > p2.x) and (last.x < p1.x)):
pc = (last.x-p1.x)/(p2.x-p1.x)
cp = (Vector(p1.x+pc*(p2.x-p1.x),p1.y+pc*(p2.y-p1.y),p1.z+pc*(p2.z-p1.z)))
ar.append([cp,1,cp]) # constrainpoint
return ar
def getPassivePoint(info):
"returns a passive snap point"
cur = Vector(info['x'],info['y'],info['z'])
return [cur,2,cur]
def getScreenDist(dist,cursor):
"returns a 3D distance from a screen pixels distance"
p1 = FreeCADGui.ActiveDocument.ActiveView.getPoint(cursor)
p2 = FreeCADGui.ActiveDocument.ActiveView.getPoint((cursor[0]+dist,cursor[1]))
return (p2.sub(p1)).Length
def getGridSnap(target,point):
"returns a grid snap point if available"
if target.grid:
return target.grid.getClosestNode(point)
return None
def getPerpendicular(edge,last):
"returns a point on an edge, perpendicular to the given point"
dv = last.sub(edge.Vertexes[0].Point)
nv = fcvec.project(dv,fcgeo.vec(edge))
np = (edge.Vertexes[0].Point).add(nv)
return np
# checking if alwaySnap setting is on
extractrl = False
if Draft.getParam("alwaysSnap"):
extractrl = ctrl
ctrl = True
# setting Radius
radius = getScreenDist(Draft.getParam("snapRange"),cursor)
# checking if parallel to one of the edges of the last objects
target.snap.off()
target.extsnap.off()
if (len(target.node) > 0):
for o in [lastObj[1],lastObj[0]]:
if o:
ob = target.doc.getObject(o)
if ob:
if ob.isDerivedFrom("Part::Feature"):
edges = ob.Shape.Edges
if len(edges)<10:
for e in edges:
if isinstance(e.Curve,Part.Line):
last = target.node[len(target.node)-1]
de = Part.Line(last,last.add(fcgeo.vec(e))).toShape()
np = getPerpendicular(e,point)
if (np.sub(point)).Length < radius:
target.snap.coords.point.setValue((np.x,np.y,np.z))
target.snap.setMarker("circle")
target.snap.on()
target.extsnap.p1(e.Vertexes[0].Point)
target.extsnap.p2(np)
target.extsnap.on()
point = np
else:
last = target.node[len(target.node)-1]
de = Part.Line(last,last.add(fcgeo.vec(e))).toShape()
np = getPerpendicular(de,point)
if (np.sub(point)).Length < radius:
target.snap.coords.point.setValue((np.x,np.y,np.z))
target.snap.setMarker("circle")
target.snap.on()
point = np
# check if we snapped to something
snapped=target.view.getObjectInfo((cursor[0],cursor[1]))
if (snapped == None):
# nothing has been snapped, check fro grid snap
gpt = getGridSnap(target,point)
if gpt:
if radius != 0:
dv = point.sub(gpt)
if dv.Length <= radius:
target.snap.coords.point.setValue((gpt.x,gpt.y,gpt.z))
target.snap.setMarker("point")
target.snap.on()
return gpt
return point
else:
# we have something to snap
obj = target.doc.getObject(snapped['Object'])
if hasattr(obj.ViewObject,"Selectable"):
if not obj.ViewObject.Selectable:
return point
if not ctrl:
# are we in passive snap?
snapArray = [getPassivePoint(snapped)]
else:
snapArray = []
comp = snapped['Component']
if obj.isDerivedFrom("Part::Feature"):
if "Edge" in comp:
# get the stored objects to calculate intersections
intedges = []
if lastObj[0]:
lo = target.doc.getObject(lastObj[0])
if lo:
if lo.isDerivedFrom("Part::Feature"):
intedges = lo.Shape.Edges
nr = int(comp[4:])-1
edge = obj.Shape.Edges[nr]
for v in edge.Vertexes:
snapArray.append([v.Point,0,v.Point])
if isinstance(edge.Curve,Part.Line):
# the edge is a line
midpoint = fcgeo.findMidpoint(edge)
snapArray.append([midpoint,1,midpoint])
if (len(target.node) > 0):
last = target.node[len(target.node)-1]
snapArray.extend(getConstrainedPoint(edge,last,target.constrain))
np = getPerpendicular(edge,last)
snapArray.append([np,1,np])
elif isinstance (edge.Curve,Part.Circle):
# the edge is an arc
rad = edge.Curve.Radius
pos = edge.Curve.Center
for i in [0,30,45,60,90,120,135,150,180,210,225,240,270,300,315,330]:
ang = math.radians(i)
cur = Vector(math.sin(ang)*rad+pos.x,math.cos(ang)*rad+pos.y,pos.z)
snapArray.append([cur,1,cur])
for i in [15,37.5,52.5,75,105,127.5,142.5,165,195,217.5,232.5,255,285,307.5,322.5,345]:
ang = math.radians(i)
cur = Vector(math.sin(ang)*rad+pos.x,math.cos(ang)*rad+pos.y,pos.z)
snapArray.append([cur,0,pos])
for e in intedges:
# get the intersection points
pt = fcgeo.findIntersection(e,edge)
if pt:
for p in pt:
snapArray.append([p,3,p])
elif "Vertex" in comp:
# directly snapped to a vertex
p = Vector(snapped['x'],snapped['y'],snapped['z'])
snapArray.append([p,0,p])
elif comp == '':
# workaround for the new view provider
p = Vector(snapped['x'],snapped['y'],snapped['z'])
snapArray.append([p,2,p])
else:
snapArray = [getPassivePoint(snapped)]
elif Draft.getType(obj) == "Dimension":
for pt in [obj.Start,obj.End,obj.Dimline]:
snapArray.append([pt,0,pt])
elif Draft.getType(obj) == "Mesh":
for v in obj.Mesh.Points:
snapArray.append([v.Vector,0,v.Vector])
if not lastObj[0]:
lastObj[0] = obj.Name
lastObj[1] = obj.Name
if (lastObj[1] != obj.Name):
lastObj[0] = lastObj[1]
lastObj[1] = obj.Name
# calculating shortest distance
shortest = 1000000000000000000
spt = Vector(snapped['x'],snapped['y'],snapped['z'])
newpoint = [Vector(0,0,0),0,Vector(0,0,0)]
for pt in snapArray:
if pt[0] == None: print "snapPoint: debug 'i[0]' is 'None'"
di = pt[0].sub(spt)
if di.Length < shortest:
shortest = di.Length
newpoint = pt
if radius != 0:
dv = point.sub(newpoint[2])
if (not extractrl) and (dv.Length > radius):
newpoint = getPassivePoint(snapped)
target.snap.coords.point.setValue((newpoint[2].x,newpoint[2].y,newpoint[2].z))
if (newpoint[1] == 1):
target.snap.setMarker("square")
elif (newpoint[1] == 0):
target.snap.setMarker("point")
elif (newpoint[1] == 3):
target.snap.setMarker("square")
else:
target.snap.setMarker("circle")
target.snap.on()
return newpoint[2]
def constrainPoint (target,pt,mobile=False,sym=False):
'''
Constrain function used by the Draft tools
On commands that need to enter several points (currently only line/wire),
you can constrain the next point to be picked to the last drawn point by
pressing SHIFT. The vertical or horizontal constraining depends on the
position of your mouse in relation to last point at the moment you press
SHIFT. if mobile=True, mobile behaviour applies. If sym=True, x alway = y
'''
point = Vector(pt)
if len(target.node) > 0:
last = target.node[-1]
dvec = point.sub(last)
affinity = FreeCAD.DraftWorkingPlane.getClosestAxis(dvec)
if ((target.constrain == None) or mobile):
if affinity == "x":
dv = fcvec.project(dvec,FreeCAD.DraftWorkingPlane.u)
point = last.add(dv)
if sym:
l = dv.Length
if dv.getAngle(FreeCAD.DraftWorkingPlane.u) > 1:
l = -l
point = last.add(FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(l,l,l)))
target.constrain = 0 #x direction
target.ui.xValue.setEnabled(True)
target.ui.yValue.setEnabled(False)
target.ui.zValue.setEnabled(False)
target.ui.xValue.setFocus()
elif affinity == "y":
dv = fcvec.project(dvec,FreeCAD.DraftWorkingPlane.v)
point = last.add(dv)
if sym:
l = dv.Length
if dv.getAngle(FreeCAD.DraftWorkingPlane.v) > 1:
l = -l
point = last.add(FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(l,l,l)))
target.constrain = 1 #y direction
target.ui.xValue.setEnabled(False)
target.ui.yValue.setEnabled(True)
target.ui.zValue.setEnabled(False)
target.ui.yValue.setFocus()
elif affinity == "z":
dv = fcvec.project(dvec,FreeCAD.DraftWorkingPlane.axis)
point = last.add(dv)
if sym:
l = dv.Length
if dv.getAngle(FreeCAD.DraftWorkingPlane.axis) > 1:
l = -l
point = last.add(FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(l,l,l)))
target.constrain = 2 #z direction
target.ui.xValue.setEnabled(False)
target.ui.yValue.setEnabled(False)
target.ui.zValue.setEnabled(True)
target.ui.zValue.setFocus()
else: target.constrain = 3
elif (target.constrain == 0):
dv = fcvec.project(dvec,FreeCAD.DraftWorkingPlane.u)
point = last.add(dv)
if sym:
l = dv.Length
if dv.getAngle(FreeCAD.DraftWorkingPlane.u) > 1:
l = -l
point = last.add(FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(l,l,l)))
elif (target.constrain == 1):
dv = fcvec.project(dvec,FreeCAD.DraftWorkingPlane.v)
point = last.add(dv)
if sym:
l = dv.Length
if dv.getAngle(FreeCAD.DraftWorkingPlane.u) > 1:
l = -l
point = last.add(FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(l,l,l)))
elif (target.constrain == 2):
dv = fcvec.project(dvec,FreeCAD.DraftWorkingPlane.axis)
point = last.add(dv)
if sym:
l = dv.Length
if dv.getAngle(FreeCAD.DraftWorkingPlane.u) > 1:
l = -l
point = last.add(FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(l,l,l)))
return point
def click(event_cb):
event = event_cb.getEvent()
if event.getState() == coin.SoMouseButtonEvent.DOWN:
self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),self.callbackClick)
self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),self.callbackMove)
FreeCADGui.Snapper.off()
self.ui.offUi()
if self.trackLine:
self.trackLine.off()
if callback:
callback(self.pt)
self.pt = None
# adding 2 callback functions
self.ui.pointUi()
self.callbackClick = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(),click)
self.callbackMove = self.view.addEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(),move)
if not hasattr(FreeCADGui,"Snapper"):
FreeCADGui.Snapper = Snapper()

View File

@ -389,24 +389,11 @@ class Line(Creator):
self.obj=self.doc.addObject("Part::Feature",self.featureName)
# self.obj.ViewObject.Selectable = False
Draft.formatObject(self.obj)
if not Draft.getParam("UiMode"): self.makeDumbTask()
self.call = self.view.addEventCallback("SoEvent",self.action)
msg(translate("draft", "Pick first point:\n"))
def makeDumbTask(self):
"create a dumb taskdialog to prevent deleting the temp object"
class TaskPanel:
def __init__(self):
pass
def getStandardButtons(self):
return 0
panel = TaskPanel()
FreeCADGui.Control.showDialog(panel)
def finish(self,closed=False,cont=False):
"terminates the operation and closes the poly if asked"
if not Draft.getParam("UiMode"):
FreeCADGui.Control.closeDialog()
if self.obj:
old = self.obj.Name
todo.delay(self.doc.removeObject,old)
@ -1627,6 +1614,12 @@ class Modifier:
def __init__(self):
self.commitList = []
def IsActive(self):
if Draft.getSelection():
return True
else:
return False
def Activated(self,name="None"):
if FreeCAD.activeDraftCommand:
@ -1655,12 +1648,6 @@ class Modifier:
self.snap = snapTracker()
self.extsnap = lineTracker(dotted=True)
self.planetrack = PlaneTracker()
def IsActive(self):
if FreeCADGui.ActiveDocument:
return True
else:
return False
def finish(self):
self.node = []

View File

@ -503,7 +503,10 @@ class wireTracker(Tracker):
def update(self,wire):
if wire:
self.line.numVertices.setValue(len(wire.Vertexes))
if self.closed:
self.line.numVertices.setValue(len(wire.Vertexes)+1)
else:
self.line.numVertices.setValue(len(wire.Vertexes))
for i in range(len(wire.Vertexes)):
p=wire.Vertexes[i].Point
self.coords.point.set1Value(i,[p.x,p.y,p.z])

View File

@ -51,8 +51,8 @@
using namespace Part;
const int Part2DObject::H_Axis = -2;
const int Part2DObject::V_Axis = -3;
const int Part2DObject::H_Axis = -1;
const int Part2DObject::V_Axis = -2;
PROPERTY_SOURCE(Part::Part2DObject, Part::Feature)

View File

@ -14,6 +14,12 @@
<Author Licence="LGPL" Name="Juergen Riegel" EMail="Juergen.Riegel@web.de" />
<UserDocu>Create a solid out of the shells of a shape</UserDocu>
</Documentation>
<Attribute Name="Mass" ReadOnly="true">
<Documentation>
<UserDocu>Returns the mass of the current system.</UserDocu>
</Documentation>
<Parameter Name="Mass" Type="Object"/>
</Attribute>
<Attribute Name="CenterOfMass" ReadOnly="true">
<Documentation>
<UserDocu>Returns the center of mass of the current system.
@ -44,6 +50,28 @@ coordinate system.</UserDocu>
</Documentation>
<Parameter Name="MatrixOfInertia" Type="Object"/>
</Attribute>
<Attribute Name="StaticMoments" ReadOnly="true">
<Documentation>
<UserDocu>Returns Ix, Iy, Iz, the static moments of inertia of the
current system; i.e. the moments of inertia about the
three axes of the Cartesian coordinate system.</UserDocu>
</Documentation>
<Parameter Name="StaticMoments" Type="Object"/>
</Attribute>
<Attribute Name="PrincipalProperties" ReadOnly="true">
<Documentation>
<UserDocu>Computes the principal properties of inertia of the current system.
There is always a set of axes for which the products
of inertia of a geometric system are equal to 0; i.e. the
matrix of inertia of the system is diagonal. These axes
are the principal axes of inertia. Their origin is
coincident with the center of mass of the system. The
associated moments are called the principal moments of inertia.
This function computes the eigen values and the
eigen vectors of the matrix of inertia of the system.</UserDocu>
</Documentation>
<Parameter Name="PrincipalProperties" Type="Dict"/>
</Attribute>
<Attribute Name="OuterShell" ReadOnly="true">
<Documentation>
<UserDocu>
@ -52,5 +80,15 @@ shape if the solid has no shells</UserDocu>
</Documentation>
<Parameter Name="OuterShell" Type="Object"/>
</Attribute>
<Methode Name="getMomentOfInertia">
<Documentation>
<UserDocu>computes the moment of inertia of the material system about the axis A.</UserDocu>
</Documentation>
</Methode>
<Methode Name="getRadiusOfGyration">
<Documentation>
<UserDocu>Returns the radius of gyration of the current system about the axis A.</UserDocu>
</Documentation>
</Methode>
</PythonExport>
</GenerateModel>

View File

@ -26,11 +26,16 @@
#include <BRepGProp.hxx>
#include <BRepTools.hxx>
#include <GProp_GProps.hxx>
#include <GProp_PrincipalProps.hxx>
#include <BRepBuilderAPI_MakeSolid.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Solid.hxx>
#include <TopoDS_Shell.hxx>
#include <gp_Ax1.hxx>
#include <gp_Pnt.hxx>
#include <gp_Dir.hxx>
#include <Standard_Failure.hxx>
#include <Base/VectorPy.h>
#include <Base/GeometryPyCXX.h>
@ -91,6 +96,22 @@ int TopoShapeSolidPy::PyInit(PyObject* args, PyObject* /*kwd*/)
return 0;
}
Py::Object TopoShapeSolidPy::getMass(void) const
{
GProp_GProps props;
BRepGProp::VolumeProperties(getTopoShapePtr()->_Shape, props);
double c = props.Mass();
return Py::Float(c);
}
Py::Object TopoShapeSolidPy::getCenterOfMass(void) const
{
GProp_GProps props;
BRepGProp::VolumeProperties(getTopoShapePtr()->_Shape, props);
gp_Pnt c = props.CentreOfMass();
return Py::Vector(Base::Vector3d(c.X(),c.Y(),c.Z()));
}
Py::Object TopoShapeSolidPy::getMatrixOfInertia(void) const
{
GProp_GProps props;
@ -105,12 +126,50 @@ Py::Object TopoShapeSolidPy::getMatrixOfInertia(void) const
return Py::Matrix(mat);
}
Py::Object TopoShapeSolidPy::getCenterOfMass(void) const
Py::Object TopoShapeSolidPy::getStaticMoments(void) const
{
GProp_GProps props;
BRepGProp::VolumeProperties(getTopoShapePtr()->_Shape, props);
gp_Pnt c = props.CentreOfMass();
return Py::Vector(Base::Vector3d(c.X(),c.Y(),c.Z()));
Standard_Real lx,ly,lz;
props.StaticMoments(lx,ly,lz);
Py::Tuple tuple(3);
tuple.setItem(0, Py::Float(lx));
tuple.setItem(1, Py::Float(ly));
tuple.setItem(2, Py::Float(lz));
return tuple;
}
Py::Dict TopoShapeSolidPy::getPrincipalProperties(void) const
{
GProp_GProps props;
BRepGProp::VolumeProperties(getTopoShapePtr()->_Shape, props);
GProp_PrincipalProps pprops = props.PrincipalProperties();
Py::Dict dict;
dict.setItem("SymmetryAxis", Py::Boolean(pprops.HasSymmetryAxis() ? true : false));
dict.setItem("SymmetryPoint", Py::Boolean(pprops.HasSymmetryPoint() ? true : false));
Standard_Real lx,ly,lz;
pprops.Moments(lx,ly,lz);
Py::Tuple tuple(3);
tuple.setItem(0, Py::Float(lx));
tuple.setItem(1, Py::Float(ly));
tuple.setItem(2, Py::Float(lz));
dict.setItem("Moments",tuple);
dict.setItem("FirstAxisOfInertia",Py::Vector(Base::convertTo
<Base::Vector3d>(pprops.FirstAxisOfInertia())));
dict.setItem("SecondAxisOfInertia",Py::Vector(Base::convertTo
<Base::Vector3d>(pprops.SecondAxisOfInertia())));
dict.setItem("ThirdAxisOfInertia",Py::Vector(Base::convertTo
<Base::Vector3d>(pprops.ThirdAxisOfInertia())));
Standard_Real Rxx,Ryy,Rzz;
pprops.RadiusOfGyration(Rxx,Ryy,Rzz);
Py::Tuple rog(3);
rog.setItem(0, Py::Float(Rxx));
rog.setItem(1, Py::Float(Ryy));
rog.setItem(2, Py::Float(Rzz));
dict.setItem("RadiusOfGyration",rog);
return dict;
}
Py::Object TopoShapeSolidPy::getOuterShell(void) const
@ -122,6 +181,52 @@ Py::Object TopoShapeSolidPy::getOuterShell(void) const
return Py::Object(new TopoShapeShellPy(new TopoShape(shell)),true);
}
PyObject* TopoShapeSolidPy::getMomentOfInertia(PyObject *args)
{
PyObject *p,*d;
if (!PyArg_ParseTuple(args, "O!O!",&Base::VectorPy::Type,&p
,&Base::VectorPy::Type,&d))
return 0;
Base::Vector3d pnt = Py::Vector(p,false).toVector();
Base::Vector3d dir = Py::Vector(d,false).toVector();
try {
GProp_GProps props;
BRepGProp::VolumeProperties(getTopoShapePtr()->_Shape, props);
double r = props.MomentOfInertia(gp_Ax1(Base::convertTo<gp_Pnt>(pnt),
Base::convertTo<gp_Dir>(dir)));
return PyFloat_FromDouble(r);
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();
PyErr_SetString(PyExc_Exception, e->GetMessageString());
return 0;
}
}
PyObject* TopoShapeSolidPy::getRadiusOfGyration(PyObject *args)
{
PyObject *p,*d;
if (!PyArg_ParseTuple(args, "O!O!",&Base::VectorPy::Type,&p
,&Base::VectorPy::Type,&d))
return 0;
Base::Vector3d pnt = Py::Vector(p,false).toVector();
Base::Vector3d dir = Py::Vector(d,false).toVector();
try {
GProp_GProps props;
BRepGProp::VolumeProperties(getTopoShapePtr()->_Shape, props);
double r = props.RadiusOfGyration(gp_Ax1(Base::convertTo<gp_Pnt>(pnt),
Base::convertTo<gp_Dir>(dir)));
return PyFloat_FromDouble(r);
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();
PyErr_SetString(PyExc_Exception, e->GetMessageString());
return 0;
}
}
PyObject *TopoShapeSolidPy::getCustomAttributes(const char* /*attr*/) const
{
return 0;

View File

@ -62,17 +62,6 @@ TYPESYSTEM_SOURCE(Sketcher::Sketch, Base::Persistence)
Sketch::Sketch()
: GCSsys(), ConstraintsCounter(0), isInitMove(false)
{
//// add the root point at 0,0
//addPoint(Base::Vector3d());
//// add x,y axis
//Part::GeomLineSegment axis;
//axis.setPoints(Base::Vector3d(0,0,0),Base::Vector3d(100,0,0));
//addLineSegment(axis);
//axis.setPoints(Base::Vector3d(0,0,0),Base::Vector3d(0,100,0));
//addLineSegment(axis);
// set them to construction elements
}
Sketch::~Sketch()
@ -108,18 +97,22 @@ void Sketch::clear(void)
}
int Sketch::setUpSketch(const std::vector<Part::Geometry *> &GeoList, const std::vector<Constraint *> &ConstraintList,
bool withDiagnose)
{
return setUpSketch(GeoList, std::vector<Part::Geometry *>(0), ConstraintList);
}
int Sketch::setUpSketch(const std::vector<Part::Geometry *> &GeoList, const std::vector<Part::Geometry *> &FixedGeoList,
const std::vector<Constraint *> &ConstraintList, bool withDiagnose)
bool withDiagnose, int extGeoCount)
{
clear();
addGeometry(GeoList);
addGeometry(FixedGeoList, true);
std::vector<Part::Geometry *> intGeoList, extGeoList;
for (int i=0; i < int(GeoList.size())-extGeoCount; i++)
intGeoList.push_back(GeoList[i]);
for (int i=int(GeoList.size())-extGeoCount; i < GeoList.size(); i++)
extGeoList.push_back(GeoList[i]);
addGeometry(intGeoList);
int extStart=Geoms.size();
addGeometry(extGeoList, true);
int extEnd=Geoms.size()-1;
for (int i=extStart; i <= extEnd; i++)
Geoms[i].external = true;
// The Geoms list might be empty after an undo/redo
if (!Geoms.empty())
@ -158,15 +151,15 @@ const char* nameByType(Sketch::GeoType type)
int Sketch::addGeometry(const Part::Geometry *geo, bool fixed)
{
if (geo->getTypeId()== GeomLineSegment::getClassTypeId()) { // add a line
if (geo->getTypeId() == GeomLineSegment::getClassTypeId()) { // add a line
const GeomLineSegment *lineSeg = dynamic_cast<const GeomLineSegment*>(geo);
// create the definition struct for that geom
return addLineSegment(*lineSeg, fixed);
} else if (geo->getTypeId()== GeomCircle::getClassTypeId()) { // add a circle
} else if (geo->getTypeId() == GeomCircle::getClassTypeId()) { // add a circle
const GeomCircle *circle = dynamic_cast<const GeomCircle*>(geo);
// create the definition struct for that geom
return addCircle(*circle, fixed);
} else if (geo->getTypeId()== GeomArcOfCircle::getClassTypeId()) { // add an arc
} else if (geo->getTypeId() == GeomArcOfCircle::getClassTypeId()) { // add an arc
const GeomArcOfCircle *aoc = dynamic_cast<const GeomArcOfCircle*>(geo);
// create the definition struct for that geom
return addArc(*aoc, fixed);
@ -178,7 +171,7 @@ int Sketch::addGeometry(const Part::Geometry *geo, bool fixed)
void Sketch::addGeometry(const std::vector<Part::Geometry *> &geo, bool fixed)
{
for (std::vector<Part::Geometry *>::const_iterator it = geo.begin();it!=geo.end();++it)
for (std::vector<Part::Geometry *>::const_iterator it=geo.begin(); it != geo.end(); ++it)
addGeometry(*it, fixed);
}
@ -190,7 +183,6 @@ int Sketch::addPoint(const Base::Vector3d &newPoint, bool fixed)
GeoDef def;
def.geo = 0;
def.type = Point;
def.construction = false;
// set the parameter for the solver
params.push_back(new double(newPoint.x));
@ -227,7 +219,6 @@ int Sketch::addLineSegment(const Part::GeomLineSegment &lineSegment, bool fixed)
GeoDef def;
def.geo = lineSeg;
def.type = Line;
def.construction = lineSeg->Construction;
// get the points from the line
Base::Vector3d start = lineSeg->getStartPoint();
@ -276,7 +267,6 @@ int Sketch::addArc(const Part::GeomArcOfCircle &circleSegment, bool fixed)
GeoDef def;
def.geo = aoc;
def.type = Arc;
def.construction = aoc->Construction;
Base::Vector3d center = aoc->getCenter();
Base::Vector3d startPnt = aoc->getStartPoint();
@ -347,7 +337,6 @@ int Sketch::addCircle(const Part::GeomCircle &cir, bool fixed)
GeoDef def;
def.geo = circ;
def.type = Circle;
def.construction = circ->Construction;
Base::Vector3d center = circ->getCenter();
double radius = circ->getRadius();
@ -387,15 +376,14 @@ int Sketch::addEllipse(const Part::GeomEllipse &ellipse, bool fixed)
return Geoms.size()-1;
}
std::vector<Part::Geometry *> Sketch::getGeometry(bool withConstrucionElements) const
std::vector<Part::Geometry *> Sketch::extractGeometry(bool withConstrucionElements,
bool withExternalElements) const
{
std::vector<Part::Geometry *> temp(Geoms.size());
int i=0;
std::vector<GeoDef>::const_iterator it=Geoms.begin();
for (;it!=Geoms.end();++it,i++)
if (!it->construction || withConstrucionElements)
temp[i] = it->geo->clone();
std::vector<Part::Geometry *> temp;
temp.reserve(Geoms.size());
for (std::vector<GeoDef>::const_iterator it=Geoms.begin(); it != Geoms.end(); ++it)
if ((!it->external || withExternalElements) && (!it->geo->Construction || withConstrucionElements))
temp.push_back(it->geo->clone());
return temp;
}
@ -404,9 +392,7 @@ Py::Tuple Sketch::getPyGeometry(void) const
{
Py::Tuple tuple(Geoms.size());
int i=0;
std::vector<GeoDef>::const_iterator it=Geoms.begin();
for (;it!=Geoms.end();++it,i++) {
for (std::vector<GeoDef>::const_iterator it=Geoms.begin(); it != Geoms.end(); ++it, i++) {
if (it->type == Line) {
GeomLineSegment *lineSeg = dynamic_cast<GeomLineSegment*>(it->geo->clone());
tuple[i] = Py::asObject(new LinePy(lineSeg));
@ -429,18 +415,12 @@ Py::Tuple Sketch::getPyGeometry(void) const
return tuple;
}
void Sketch::setConstruction(int geoId, bool isConstruction)
int Sketch::checkGeoId(int geoId)
{
assert(geoId < int(Geoms.size()));
Geoms[geoId].construction = isConstruction;
}
bool Sketch::getConstruction(int geoId) const
{
assert(geoId < int(Geoms.size()));
return Geoms[geoId].construction;
if (geoId < 0)
geoId += Geoms.size();
assert(geoId >= 0 && geoId < int(Geoms.size()));
return geoId;
}
// constraint adding ==========================================================
@ -561,6 +541,8 @@ int Sketch::addConstraints(const std::vector<Constraint *> &ConstraintList)
int Sketch::addCoordinateXConstraint(int geoId, PointPos pos, double value)
{
geoId = checkGeoId(geoId);
int pointId = getPointId(geoId, pos);
if (pointId >= 0 && pointId < int(Points.size())) {
@ -576,6 +558,8 @@ int Sketch::addCoordinateXConstraint(int geoId, PointPos pos, double value)
int Sketch::addCoordinateYConstraint(int geoId, PointPos pos, double value)
{
geoId = checkGeoId(geoId);
int pointId = getPointId(geoId, pos);
if (pointId >= 0 && pointId < int(Points.size())) {
@ -591,7 +575,8 @@ int Sketch::addCoordinateYConstraint(int geoId, PointPos pos, double value)
int Sketch::addDistanceXConstraint(int geoId, double value)
{
assert(geoId < int(Geoms.size()));
geoId = checkGeoId(geoId);
if (Geoms[geoId].type != Line)
return -1;
@ -607,7 +592,8 @@ int Sketch::addDistanceXConstraint(int geoId, double value)
int Sketch::addDistanceYConstraint(int geoId, double value)
{
assert(geoId < int(Geoms.size()));
geoId = checkGeoId(geoId);
if (Geoms[geoId].type != Line)
return -1;
@ -623,6 +609,9 @@ int Sketch::addDistanceYConstraint(int geoId, double value)
int Sketch::addDistanceXConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value)
{
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
int pointId1 = getPointId(geoId1, pos1);
int pointId2 = getPointId(geoId2, pos2);
@ -643,6 +632,9 @@ int Sketch::addDistanceXConstraint(int geoId1, PointPos pos1, int geoId2, PointP
int Sketch::addDistanceYConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value)
{
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
int pointId1 = getPointId(geoId1, pos1);
int pointId2 = getPointId(geoId2, pos2);
@ -664,7 +656,8 @@ int Sketch::addDistanceYConstraint(int geoId1, PointPos pos1, int geoId2, PointP
// horizontal line constraint
int Sketch::addHorizontalConstraint(int geoId)
{
assert(geoId < int(Geoms.size()));
geoId = checkGeoId(geoId);
if (Geoms[geoId].type != Line)
return -1;
@ -677,6 +670,9 @@ int Sketch::addHorizontalConstraint(int geoId)
// two points on a horizontal line constraint
int Sketch::addHorizontalConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2)
{
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
int pointId1 = getPointId(geoId1, pos1);
int pointId2 = getPointId(geoId2, pos2);
@ -694,7 +690,8 @@ int Sketch::addHorizontalConstraint(int geoId1, PointPos pos1, int geoId2, Point
// vertical line constraint
int Sketch::addVerticalConstraint(int geoId)
{
assert(geoId < int(Geoms.size()));
geoId = checkGeoId(geoId);
if (Geoms[geoId].type != Line)
return -1;
@ -707,6 +704,9 @@ int Sketch::addVerticalConstraint(int geoId)
// two points on a vertical line constraint
int Sketch::addVerticalConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2)
{
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
int pointId1 = getPointId(geoId1, pos1);
int pointId2 = getPointId(geoId2, pos2);
@ -723,6 +723,9 @@ int Sketch::addVerticalConstraint(int geoId1, PointPos pos1, int geoId2, PointPo
int Sketch::addPointCoincidentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2)
{
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
int pointId1 = getPointId(geoId1, pos1);
int pointId2 = getPointId(geoId2, pos2);
@ -742,8 +745,9 @@ int Sketch::addPointCoincidentConstraint(int geoId1, PointPos pos1, int geoId2,
int Sketch::addParallelConstraint(int geoId1, int geoId2)
{
assert(geoId1 < int(Geoms.size()));
assert(geoId2 < int(Geoms.size()));
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
if (Geoms[geoId1].type != Line ||
Geoms[geoId2].type != Line)
return -1;
@ -757,8 +761,8 @@ int Sketch::addParallelConstraint(int geoId1, int geoId2)
int Sketch::addPerpendicularConstraint(int geoId1, int geoId2)
{
assert(geoId1 < int(Geoms.size()));
assert(geoId2 < int(Geoms.size()));
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
if (Geoms[geoId2].type == Line) {
if (Geoms[geoId1].type == Line) {
@ -801,8 +805,8 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2)
// Circle1, Circle2/Arc2 (not implemented yet)
// 3) Arc1, Line2 (converted to case #1)
// Arc1, Circle2/Arc2 (not implemented yet)
assert(geoId1 < int(Geoms.size()));
assert(geoId2 < int(Geoms.size()));
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
if (Geoms[geoId2].type == Line) {
if (Geoms[geoId1].type == Line) {
@ -847,9 +851,10 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2)
// 4) Arc1, start/end, Line2
// 5) Arc1, start/end, Circle2 (not implemented yet)
// 6) Arc1, start/end, Arc2 (not implemented yet)
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
int pointId1 = getPointId(geoId1, pos1);
assert(geoId2 < int(Geoms.size()));
if (pointId1 < 0 || pointId1 >= int(Points.size()))
return addTangentConstraint(geoId1, geoId2);
@ -912,6 +917,8 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos
// 2) Line1, start/end/mid, Arc2, start/end
// 3) Arc1, start/end, Line2, start/end/mid (converted to case #2)
// 4) Arc1, start/end, Arc2, start/end (not implemented yet)
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
int pointId1 = getPointId(geoId1, pos1);
int pointId2 = getPointId(geoId2, pos2);
@ -1006,7 +1013,8 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos
// line length constraint
int Sketch::addDistanceConstraint(int geoId, double value)
{
assert(geoId < int(Geoms.size()));
geoId = checkGeoId(geoId);
if (Geoms[geoId].type != Line)
return -1;
@ -1024,8 +1032,8 @@ int Sketch::addDistanceConstraint(int geoId, double value)
// line to line distance constraint
int Sketch::addDistanceConstraint(int geoId1, int geoId2, double value)
{
assert(geoId1 < int(Geoms.size()));
assert(geoId2 < int(Geoms.size()));
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
//assert(Geoms[geoId1].type == Line);
//assert(Geoms[geoId2].type == Line);
@ -1038,8 +1046,11 @@ int Sketch::addDistanceConstraint(int geoId1, int geoId2, double value)
// point to line distance constraint
int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, double value)
{
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
int pointId1 = getPointId(geoId1, pos1);
assert(geoId2 < int(Geoms.size()));
if (Geoms[geoId2].type != Line)
return -1;
@ -1061,6 +1072,9 @@ int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, double
// point to point distance constraint
int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value)
{
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
int pointId1 = getPointId(geoId1, pos1);
int pointId2 = getPointId(geoId2, pos2);
@ -1082,7 +1096,7 @@ int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPo
int Sketch::addRadiusConstraint(int geoId, double value)
{
assert(geoId < int(Geoms.size()));
geoId = checkGeoId(geoId);
if (Geoms[geoId].type == Circle) {
GCS::Circle &c = Circles[Geoms[geoId].index];
@ -1108,7 +1122,8 @@ int Sketch::addRadiusConstraint(int geoId, double value)
// line orientation angle constraint
int Sketch::addAngleConstraint(int geoId, double value)
{
assert(geoId < int(Geoms.size()));
geoId = checkGeoId(geoId);
if (Geoms[geoId].type != Line)
return -1;
@ -1126,8 +1141,8 @@ int Sketch::addAngleConstraint(int geoId, double value)
// line to line angle constraint
int Sketch::addAngleConstraint(int geoId1, int geoId2, double value)
{
assert(geoId1 < int(Geoms.size()));
assert(geoId2 < int(Geoms.size()));
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
if (Geoms[geoId1].type != Line ||
Geoms[geoId2].type != Line)
@ -1148,8 +1163,8 @@ int Sketch::addAngleConstraint(int geoId1, int geoId2, double value)
// line to line angle constraint (with explicitly given start points)
int Sketch::addAngleConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value)
{
assert(geoId1 < int(Geoms.size()));
assert(geoId2 < int(Geoms.size()));
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
if (Geoms[geoId1].type != Line ||
Geoms[geoId2].type != Line)
@ -1187,8 +1202,8 @@ int Sketch::addAngleConstraint(int geoId1, PointPos pos1, int geoId2, PointPos p
int Sketch::addEqualConstraint(int geoId1, int geoId2)
{
assert(geoId1 < int(Geoms.size()));
assert(geoId2 < int(Geoms.size()));
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
if (Geoms[geoId1].type == Line &&
Geoms[geoId2].type == Line) {
@ -1246,8 +1261,10 @@ int Sketch::addEqualConstraint(int geoId1, int geoId2)
// point on object constraint
int Sketch::addPointOnObjectConstraint(int geoId1, PointPos pos1, int geoId2)
{
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
int pointId1 = getPointId(geoId1, pos1);
assert(geoId2 < int(Geoms.size()));
if (pointId1 >= 0 && pointId1 < int(Points.size())) {
GCS::Point &p1 = Points[pointId1];
@ -1277,9 +1294,9 @@ int Sketch::addPointOnObjectConstraint(int geoId1, PointPos pos1, int geoId2)
// symmetric points constraint
int Sketch::addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3)
{
assert(geoId1 < int(Geoms.size()));
assert(geoId2 < int(Geoms.size()));
assert(geoId3 < int(Geoms.size()));
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
geoId3 = checkGeoId(geoId3);
if (Geoms[geoId3].type != Line)
return -1;
@ -1302,7 +1319,7 @@ int Sketch::addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointP
bool Sketch::updateGeometry()
{
int i=0;
for (std::vector<GeoDef>::const_iterator it=Geoms.begin();it!=Geoms.end();++it,i++) {
for (std::vector<GeoDef>::const_iterator it=Geoms.begin(); it != Geoms.end(); ++it, i++) {
try {
if (it->type == Line) {
GeomLineSegment *lineSeg = dynamic_cast<GeomLineSegment*>(it->geo);
@ -1432,7 +1449,7 @@ int Sketch::solve()
int Sketch::initMove(int geoId, PointPos pos)
{
assert(geoId >= 0 && geoId < int(Geoms.size()));
geoId = checkGeoId(geoId);
GCSsys.clearByTag(-1);
GCSsys.clearByTag(-2);
@ -1547,8 +1564,7 @@ int Sketch::initMove(int geoId, PointPos pos)
int Sketch::movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool relative)
{
// index out of bounds?
assert(geoId < int(Geoms.size()));
geoId = checkGeoId(geoId);
// don't try to move sketches that contain conflicting constraints
if (hasConflicts())
@ -1558,7 +1574,7 @@ int Sketch::movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool rela
initMove(geoId, pos);
if (relative) {
for (int i=0; i < MoveParameters.size()-1; i+=2) {
for (int i=0; i < int(MoveParameters.size()-1); i+=2) {
MoveParameters[i] = InitParameters[i] + toPoint.x;
MoveParameters[i+1] = InitParameters[i+1] + toPoint.y;
}
@ -1596,7 +1612,6 @@ int Sketch::setDatum(int constrId, double value)
int Sketch::getPointId(int geoId, PointPos pos) const
{
assert(geoId < int(Geoms.size()));
switch (pos) {
case start:
return Geoms[geoId].startPointId;
@ -1612,6 +1627,7 @@ int Sketch::getPointId(int geoId, PointPos pos) const
Base::Vector3d Sketch::getPoint(int geoId, PointPos pos)
{
geoId = checkGeoId(geoId);
int pointId = getPointId(geoId, pos);
if (pointId != -1)
return Base::Vector3d(*Points[pointId].x, *Points[pointId].y, 0);
@ -1642,7 +1658,7 @@ TopoShape Sketch::toShape(void) const
bool first = true;
for (;it!=Geoms.end();++it) {
if (!it->construction) {
if (!it->geo->Construction) {
TopoDS_Shape sh = it->geo->toShape();
if (first) {
first = false;
@ -1657,9 +1673,9 @@ TopoShape Sketch::toShape(void) const
std::list<TopoDS_Edge> edge_list;
std::list<TopoDS_Wire> wires;
// collecting all (non constructive) edges out of the sketch
// collecting all (non constructive and non external) edges out of the sketch
for (;it!=Geoms.end();++it) {
if (!it->construction) {
if (!it->external && !it->geo->Construction) {
edge_list.push_back(TopoDS::Edge(it->geo->toShape()));
}
}

View File

@ -55,9 +55,7 @@ public:
void clear(void);
/// set the sketch up with geoms and constraints
int setUpSketch(const std::vector<Part::Geometry *> &GeoList, const std::vector<Constraint *> &ConstraintList,
bool withDiagnose=true);
int setUpSketch(const std::vector<Part::Geometry *> &GeoList, const std::vector<Part::Geometry *> &FixedGeoList,
const std::vector<Constraint *> &ConstraintList, bool withDiagnose=true);
bool withDiagnose=true, int extGeoCount=0);
/// return the actual geometry of the sketch a TopoShape
Part::TopoShape toShape(void) const;
/// add unspecified geometry
@ -65,15 +63,11 @@ public:
/// add unspecified geometry
void addGeometry(const std::vector<Part::Geometry *> &geo, bool fixed=false);
/// returns the actual geometry
std::vector<Part::Geometry *> getGeometry(bool withConstrucionElements = true) const;
std::vector<Part::Geometry *> extractGeometry(bool withConstrucionElements=true,
bool withExternalElements=false) const;
/// get the geometry as python objects
Py::Tuple getPyGeometry(void) const;
/// set a geometric element to a construction element
void setConstruction(int geoIndex,bool isConstruction=true);
bool getConstruction(int geoIndex) const;
/// retrieves the index of a point
int getPointId(int geoId, PointPos pos) const;
/// retrieves a point
Base::Vector3d getPoint(int geoId, PointPos pos);
@ -190,11 +184,11 @@ public:
protected:
/// container element to store and work with the geometric elements of this sketch
struct GeoDef {
GeoDef() : geo(0),type(None),construction(false),index(-1),
GeoDef() : geo(0),type(None),external(false),index(-1),
startPointId(-1),midPointId(-1),endPointId(-1) {}
Part::Geometry * geo; // pointer to the geometry
GeoType type; // type of the geometry
bool construction; // defines if this element is a construction element
bool external; // flag for external geometries
int index; // index in the corresponding storage vector (Lines, Arcs, Circles, ...)
int startPointId; // index in Points of the start point of this geometry
int midPointId; // index in Points of the start point of this geometry
@ -218,8 +212,13 @@ protected:
bool isInitMove;
private:
/// retrieves the index of a point
int getPointId(int geoId, PointPos pos) const;
bool updateGeometry(void);
/// checks if the index bounds and converts negative indices to positive
int checkGeoId(int geoId);
};
} //namespace Part

View File

@ -26,12 +26,18 @@
# include <TopoDS_Shape.hxx>
# include <TopoDS_Face.hxx>
# include <TopoDS.hxx>
# include <gp_Pln.hxx>
# include <gp_Ax3.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <Geom_Plane.hxx>
# include <GeomAPI_ProjectPointOnSurf.hxx>
#endif
#include <Base/Writer.h>
#include <Base/Reader.h>
#include <Base/Tools.h>
#include <Base/Console.h>
#include <Mod/Part/App/Geometry.h>
@ -50,9 +56,28 @@ PROPERTY_SOURCE(Sketcher::SketchObject, Part::Part2DObject)
SketchObject::SketchObject()
{
ADD_PROPERTY_TYPE(Geometry, (0) ,"Sketch",(App::PropertyType)(App::Prop_None),"Sketch geometry");
ADD_PROPERTY_TYPE(Constraints, (0) ,"Sketch",(App::PropertyType)(App::Prop_None),"Sketch constraints");
ADD_PROPERTY_TYPE(ExternalConstraints,(0,0),"Sketch",(App::PropertyType)(App::Prop_None),"Sketch external constraints");
ADD_PROPERTY_TYPE(Geometry, (0) ,"Sketch",(App::PropertyType)(App::Prop_None),"Sketch geometry");
ADD_PROPERTY_TYPE(Constraints, (0) ,"Sketch",(App::PropertyType)(App::Prop_None),"Sketch constraints");
ADD_PROPERTY_TYPE(ExternalGeometry,(0,0),"Sketch",(App::PropertyType)(App::Prop_None),"Sketch external geometry");
for (std::vector<Part::Geometry *>::iterator it=ExternalGeo.begin(); it != ExternalGeo.end(); ++it)
if (*it) delete *it;
ExternalGeo.clear();
Part::GeomLineSegment *HLine = new Part::GeomLineSegment();
Part::GeomLineSegment *VLine = new Part::GeomLineSegment();
HLine->setPoints(Base::Vector3d(0,0,0),Base::Vector3d(1,0,0));
VLine->setPoints(Base::Vector3d(0,0,0),Base::Vector3d(0,1,0));
HLine->Construction = true;
VLine->Construction = true;
ExternalGeo.push_back(HLine);
ExternalGeo.push_back(VLine);
}
SketchObject::~SketchObject()
{
for (std::vector<Part::Geometry *>::iterator it=ExternalGeo.begin(); it != ExternalGeo.end(); ++it)
if (*it) delete *it;
ExternalGeo.clear();
}
App::DocumentObjectExecReturn *SketchObject::execute(void)
@ -65,8 +90,10 @@ App::DocumentObjectExecReturn *SketchObject::execute(void)
}
// setup and diagnose the sketch
rebuildExternalGeometry();
Sketch sketch;
int dofs = sketch.setUpSketch(Geometry.getValues(), Constraints.getValues());
int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
true, getExternalGeometryCount());
if (dofs < 0) { // over-constrained sketch
std::string msg="Over-constrained sketch\n";
appendConflictMsg(sketch.getConflicting(), msg);
@ -82,9 +109,9 @@ App::DocumentObjectExecReturn *SketchObject::execute(void)
if (sketch.solve() != 0)
return new App::DocumentObjectExecReturn("Solving the sketch failed",this);
std::vector<Part::Geometry *> geomlist = sketch.getGeometry();
std::vector<Part::Geometry *> geomlist = sketch.extractGeometry();
Geometry.setValues(geomlist);
for (std::vector<Part::Geometry *>::iterator it = geomlist.begin(); it != geomlist.end(); ++it)
for (std::vector<Part::Geometry *>::iterator it=geomlist.begin(); it != geomlist.end(); ++it)
if (*it) delete *it;
Shape.setValue(sketch.toShape());
@ -96,7 +123,8 @@ int SketchObject::hasConflicts(void) const
{
// set up a sketch (including dofs counting and diagnosing of conflicts)
Sketch sketch;
int dofs = sketch.setUpSketch(Geometry.getValues(), Constraints.getValues());
int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
true, getExternalGeometryCount());
if (dofs < 0) // over-constrained sketch
return -2;
if (sketch.hasConflicts()) // conflicting constraints
@ -133,7 +161,8 @@ int SketchObject::setDatum(int ConstrId, double Datum)
// set up a sketch (including dofs counting and diagnosing of conflicts)
Sketch sketch;
int dofs = sketch.setUpSketch(Geometry.getValues(), Constraints.getValues());
int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
true, getExternalGeometryCount());
int err=0;
if (dofs < 0) // over-constrained sketch
err = -3;
@ -144,7 +173,7 @@ int SketchObject::setDatum(int ConstrId, double Datum)
if (err == 0) {
// set the newly solved geometry
std::vector<Part::Geometry *> geomlist = sketch.getGeometry();
std::vector<Part::Geometry *> geomlist = sketch.extractGeometry();
Geometry.setValues(geomlist);
for (std::vector<Part::Geometry *>::iterator it = geomlist.begin(); it != geomlist.end(); ++it)
if (*it) delete *it;
@ -155,21 +184,23 @@ int SketchObject::setDatum(int ConstrId, double Datum)
return err;
}
int SketchObject::movePoint(int geoIndex, PointPos PosId, const Base::Vector3d& toPoint, bool relative)
int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative)
{
Sketch sketch;
int dofs = sketch.setUpSketch(Geometry.getValues(), Constraints.getValues());
int dofs = sketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
true, getExternalGeometryCount());
if (dofs < 0) // over-constrained sketch
return -1;
if (sketch.hasConflicts()) // conflicting constraints
return -1;
// move the point and solve
int ret = sketch.movePoint(geoIndex, PosId, toPoint, relative);
int ret = sketch.movePoint(GeoId, PosId, toPoint, relative);
if (ret == 0) {
std::vector<Part::Geometry *> geomlist = sketch.getGeometry();
std::vector<Part::Geometry *> geomlist = sketch.extractGeometry();
Geometry.setValues(geomlist);
for (std::vector<Part::Geometry *>::iterator it = geomlist.begin(); it != geomlist.end(); ++it) {
//Constraints.acceptGeometry(getCompleteGeometry());
for (std::vector<Part::Geometry *>::iterator it=geomlist.begin(); it != geomlist.end(); ++it) {
if (*it) delete *it;
}
}
@ -177,11 +208,11 @@ int SketchObject::movePoint(int geoIndex, PointPos PosId, const Base::Vector3d&
return ret;
}
Base::Vector3d SketchObject::getPoint(int geoIndex, PointPos PosId)
Base::Vector3d SketchObject::getPoint(int GeoId, PointPos PosId) const
{
const std::vector< Part::Geometry * > &geomlist = this->Geometry.getValues();
assert(geoIndex < (int)geomlist.size());
Part::Geometry *geo = geomlist[geoIndex];
assert(GeoId == H_Axis || GeoId == V_Axis ||
(GeoId <= getHighestCurveIndex() && GeoId >= -getExternalGeometryCount()) );
const Part::Geometry *geo = getGeometry(GeoId);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment*>(geo);
if (PosId == start)
@ -207,7 +238,7 @@ Base::Vector3d SketchObject::getPoint(int geoIndex, PointPos PosId)
int SketchObject::getAxisCount(void) const
{
const std::vector< Part::Geometry * > &vals = this->Geometry.getValues();
const std::vector< Part::Geometry * > &vals = getInternalGeometry();
int count=0;
for (std::vector<Part::Geometry *>::const_iterator geo=vals.begin();
@ -221,7 +252,7 @@ int SketchObject::getAxisCount(void) const
Base::Axis SketchObject::getAxis(int axId) const
{
const std::vector< Part::Geometry * > &vals = this->Geometry.getValues();
const std::vector< Part::Geometry * > &vals = getInternalGeometry();
if (axId == H_Axis) {
return Base::Axis(Base::Vector3d(0,0,0), Base::Vector3d(1,0,0));
}
@ -253,36 +284,36 @@ int SketchObject::addGeometry(const std::vector<Part::Geometry *> &geoList)
int SketchObject::addGeometry(const Part::Geometry *geo)
{
const std::vector< Part::Geometry * > &vals = Geometry.getValues();
const std::vector< Part::Geometry * > &vals = getInternalGeometry();
std::vector< Part::Geometry * > newVals(vals);
Part::Geometry *geoNew = geo->clone();
newVals.push_back(geoNew);
Geometry.setValues(newVals);
Constraints.acceptGeometry(Geometry.getValues());
Constraints.acceptGeometry(getCompleteGeometry());
delete geoNew;
rebuildVertexIndex();
return Geometry.getSize()-1;
}
int SketchObject::delGeometry(int GeoNbr)
int SketchObject::delGeometry(int GeoId)
{
const std::vector< Part::Geometry * > &vals = this->Geometry.getValues();
if (GeoNbr < 0 || GeoNbr >= (int)vals.size())
const std::vector< Part::Geometry * > &vals = getInternalGeometry();
if (GeoId < 0 || GeoId >= (int)vals.size())
return -1;
std::vector< Part::Geometry * > newVals(vals);
newVals.erase(newVals.begin()+GeoNbr);
newVals.erase(newVals.begin()+GeoId);
const std::vector< Constraint * > &constraints = this->Constraints.getValues();
std::vector< Constraint * > newConstraints(0);
for (std::vector<Constraint *>::const_iterator it = constraints.begin();
it != constraints.end(); ++it) {
if ((*it)->First != GeoNbr && (*it)->Second != GeoNbr) {
if ((*it)->First != GeoId && (*it)->Second != GeoId) {
Constraint *copiedConstr = (*it)->clone();
if (copiedConstr->First > GeoNbr)
if (copiedConstr->First > GeoId)
copiedConstr->First -= 1;
if (copiedConstr->Second > GeoNbr)
if (copiedConstr->Second > GeoId)
copiedConstr->Second -= 1;
newConstraints.push_back(copiedConstr);
}
@ -290,25 +321,25 @@ int SketchObject::delGeometry(int GeoNbr)
this->Geometry.setValues(newVals);
this->Constraints.setValues(newConstraints);
this->Constraints.acceptGeometry(this->Geometry.getValues());
this->Constraints.acceptGeometry(getCompleteGeometry());
rebuildVertexIndex();
return 0;
}
int SketchObject::toggleConstruction(int GeoNbr)
int SketchObject::toggleConstruction(int GeoId)
{
const std::vector< Part::Geometry * > &vals = this->Geometry.getValues();
if (GeoNbr < 0 || GeoNbr >= (int)vals.size())
const std::vector< Part::Geometry * > &vals = getInternalGeometry();
if (GeoId < 0 || GeoId >= (int)vals.size())
return -1;
std::vector< Part::Geometry * > newVals(vals);
Part::Geometry *geoNew = newVals[GeoNbr]->clone();
Part::Geometry *geoNew = newVals[GeoId]->clone();
geoNew->Construction = !geoNew->Construction;
newVals[GeoNbr]=geoNew;
newVals[GeoId]=geoNew;
this->Geometry.setValues(newVals);
this->Constraints.acceptGeometry(this->Geometry.getValues());
this->Constraints.acceptGeometry(getCompleteGeometry());
return 0;
}
@ -480,17 +511,18 @@ int SketchObject::transferConstraints(int fromGeoId, PointPos fromPosId, int toG
int SketchObject::fillet(int GeoId, PointPos PosId, double radius, bool trim)
{
const std::vector<Part::Geometry *> &geomlist = this->Geometry.getValues();
assert(GeoId < int(geomlist.size()));
if (GeoId < 0 || GeoId > getHighestCurveIndex())
return -1;
// Find the other geometry Id associated with the coincident point
std::vector<int> GeoIdList;
std::vector<PointPos> PosIdList;
getCoincidentPoints(GeoId, PosId, GeoIdList, PosIdList);
// only coincident points between two edges can be filleted
if (GeoIdList.size() == 2) {
Part::Geometry *geo1 = geomlist[GeoIdList[0]];
Part::Geometry *geo2 = geomlist[GeoIdList[1]];
// only coincident points between two (non-external) edges can be filleted
if (GeoIdList.size() == 2 && GeoIdList[0] >= 0 && GeoIdList[1] >= 0) {
const Part::Geometry *geo1 = getGeometry(GeoIdList[0]);
const Part::Geometry *geo2 = getGeometry(GeoIdList[1]);
if (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
geo2->getTypeId() == Part::GeomLineSegment::getClassTypeId() ) {
const Part::GeomLineSegment *lineSeg1 = dynamic_cast<const Part::GeomLineSegment*>(geo1);
@ -509,11 +541,12 @@ int SketchObject::fillet(int GeoId1, int GeoId2,
const Base::Vector3d& refPnt1, const Base::Vector3d& refPnt2,
double radius, bool trim)
{
const std::vector<Part::Geometry *> &geomlist = this->Geometry.getValues();
assert(GeoId1 < int(geomlist.size()));
assert(GeoId2 < int(geomlist.size()));
Part::Geometry *geo1 = geomlist[GeoId1];
Part::Geometry *geo2 = geomlist[GeoId2];
if (GeoId1 < 0 || GeoId1 > getHighestCurveIndex() ||
GeoId2 < 0 || GeoId2 > getHighestCurveIndex())
return -1;
const Part::Geometry *geo1 = getGeometry(GeoId1);
const Part::Geometry *geo2 = getGeometry(GeoId2);
if (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
geo2->getTypeId() == Part::GeomLineSegment::getClassTypeId() ) {
const Part::GeomLineSegment *lineSeg1 = dynamic_cast<const Part::GeomLineSegment*>(geo1);
@ -594,10 +627,11 @@ int SketchObject::fillet(int GeoId1, int GeoId2,
int SketchObject::trim(int GeoId, const Base::Vector3d& point)
{
const std::vector<Part::Geometry *> &geomlist = this->Geometry.getValues();
const std::vector<Constraint *> &constraints = this->Constraints.getValues();
if (GeoId < 0 || GeoId > getHighestCurveIndex())
return -1;
assert(GeoId < int(geomlist.size()));
const std::vector<Part::Geometry *> &geomlist = getInternalGeometry();
const std::vector<Constraint *> &constraints = this->Constraints.getValues();
int GeoId1=Constraint::GeoUndef, GeoId2=Constraint::GeoUndef;
Base::Vector3d point1, point2;
@ -778,7 +812,7 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point)
std::vector< Part::Geometry * > newVals(geomlist);
newVals[GeoId] = geoNew;
Geometry.setValues(newVals);
Constraints.acceptGeometry(Geometry.getValues());
Constraints.acceptGeometry(getCompleteGeometry());
delete geoNew;
rebuildVertexIndex();
@ -994,53 +1028,174 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point)
int SketchObject::addExternal(App::DocumentObject *Obj, const char* SubName)
{
// so far only externals to the support of the sketch
assert(Support.getValue() == Obj);
if (Support.getValue() != Obj)
return -1;
// get the actual lists of the externals
std::vector<DocumentObject*> Objects = ExternalConstraints.getValues();
std::vector<std::string> SubElements = ExternalConstraints.getSubValues();
std::vector<DocumentObject*> Objects = ExternalGeometry.getValues();
std::vector<std::string> SubElements = ExternalGeometry.getSubValues();
std::vector<DocumentObject*> originalObjects = Objects;
std::vector<std::string> originalSubElements = SubElements;
// add the new ones
Objects.push_back(Obj);
SubElements.push_back(std::string(SubName));
// set the Link list.
ExternalConstraints.setValues(Objects,SubElements);
ExternalGeometry.setValues(Objects,SubElements);
return ExternalConstraints.getValues().size()-1;
try {
rebuildExternalGeometry();
}
catch (const Base::Exception& e) {
Base::Console().Error("%s\n", e.what());
// revert to original values
ExternalGeometry.setValues(originalObjects,originalSubElements);
return -1;
}
Constraints.acceptGeometry(getCompleteGeometry());
rebuildVertexIndex();
return ExternalGeometry.getValues().size()-1;
}
int SketchObject::delExternal(int ConstrId)
int SketchObject::delExternal(int ExtGeoId)
{
// FIXME: still to implement
return 0;
}
std::vector<Part::Geometry *> getExternalGeometry(void)
const Part::Geometry* SketchObject::getGeometry(int GeoId) const
{
std::vector<Part::Geometry *> ExtGeos;
if (GeoId >= 0) {
const std::vector<Part::Geometry *> &geomlist = getInternalGeometry();
if (GeoId < int(geomlist.size()))
return geomlist[GeoId];
}
else if (GeoId <= -1 && -GeoId <= int(ExternalGeo.size()))
return ExternalGeo[-GeoId-1];
// add the root point (0,0) the the external geos(-1)
ExtGeos.push_back(new Part::GeomPoint(Base::Vector3d(0,0,0)));
// add the X,Y (V,H) axis (-2,-3)
ExtGeos.push_back(new Part::GeomLine(Base::Vector3d(0,0,0),Base::Vector3d(1,0,0)));
ExtGeos.push_back(new Part::GeomLine(Base::Vector3d(0,0,0),Base::Vector3d(0,1,0)));
// return the result set
return ExtGeos;
return 0;
}
void SketchObject::rebuildExternalGeometry(void)
{
// get the actual lists of the externals
std::vector<DocumentObject*> Objects = ExternalGeometry.getValues();
std::vector<std::string> SubElements = ExternalGeometry.getSubValues();
if (Objects.size() == 0)
return;
Base::Placement Plm = Placement.getValue();
Base::Vector3d Pos = Plm.getPosition();
Base::Rotation Rot = Plm.getRotation();
Base::Vector3d dN(0,0,1);
Rot.multVec(dN,dN);
Base::Vector3d dX(1,0,0);
Rot.multVec(dX,dX);
Base::Placement invPlm = Plm.inverse();
gp_Ax3 sketchAx3(gp_Pnt(Pos.x,Pos.y,Pos.z),
gp_Dir(dN.x,dN.y,dN.z),
gp_Dir(dX.x,dX.y,dX.z));
gp_Pln sketchPlane(sketchAx3);
Handle(Geom_Plane) gPlane = new Geom_Plane(sketchPlane);
for (std::vector<Part::Geometry *>::iterator it=ExternalGeo.begin(); it != ExternalGeo.end(); ++it)
if (*it) delete *it;
ExternalGeo.clear();
Part::GeomLineSegment *HLine = new Part::GeomLineSegment();
Part::GeomLineSegment *VLine = new Part::GeomLineSegment();
HLine->setPoints(Base::Vector3d(0,0,0),Base::Vector3d(1,0,0));
VLine->setPoints(Base::Vector3d(0,0,0),Base::Vector3d(0,1,0));
HLine->Construction = true;
VLine->Construction = true;
ExternalGeo.push_back(HLine);
ExternalGeo.push_back(VLine);
for (int i=0; i < int(Objects.size()); i++) {
const App::DocumentObject *Obj=Objects[i];
const std::string SubElement=SubElements[i];
const Part::Feature *refObj=static_cast<const Part::Feature*>(Obj);
const Part::TopoShape& refShape=refObj->Shape.getShape();
TopoDS_Shape refSubShape=refShape.getSubShape(SubElement.c_str());
switch (refSubShape.ShapeType())
{
case TopAbs_FACE:
{
const TopoDS_Face& face = TopoDS::Face(refSubShape);
BRepAdaptor_Surface surface(face);
if (surface.GetType() == GeomAbs_Plane) {
}
throw Base::Exception("Faces are not yet supported for external geometry of sketches");
}
break;
case TopAbs_EDGE:
{
const TopoDS_Edge& edge = TopoDS::Edge(refSubShape);
BRepAdaptor_Curve curve(edge);
if (curve.GetType() == GeomAbs_Line) {
gp_Pnt P1 = curve.Value(curve.FirstParameter());
gp_Pnt P2 = curve.Value(curve.LastParameter());
GeomAPI_ProjectPointOnSurf proj1(P1,gPlane);
P1 = proj1.NearestPoint();
GeomAPI_ProjectPointOnSurf proj2(P2,gPlane);
P2 = proj2.NearestPoint();
Base::Vector3d p1(P1.X(),P1.Y(),P1.Z());
Base::Vector3d p2(P2.X(),P2.Y(),P2.Z());
invPlm.multVec(p1,p1);
invPlm.multVec(p2,p2);
if (Base::Distance(p1,p2) < Precision::Confusion()) {
std::string msg = SubElement + " perpendicular to the sketch plane cannot be used as external geometry";
throw Base::Exception(msg.c_str());
}
Part::GeomLineSegment* line = new Part::GeomLineSegment();
line->setPoints(p1,p2);
line->Construction = true;
ExternalGeo.push_back(line);
}
else {
throw Base::Exception("Not yet supported geometry for external geometry");
}
}
break;
case TopAbs_VERTEX:
throw Base::Exception("Vertices cannot be used as external geometry for sketches");
break;
default:
throw Base::Exception("Unknown type of geometry");
break;
}
}
}
std::vector<Part::Geometry*> SketchObject::getCompleteGeometry(void) const
{
std::vector<Part::Geometry*> vals=getInternalGeometry();
vals.insert(vals.end(), ExternalGeo.rbegin(), ExternalGeo.rend()); // in reverse order
return vals;
}
void SketchObject::rebuildVertexIndex(void)
{
VertexId2GeoId.resize(0);
VertexId2PosId.resize(0);
int imax=getHighestCurveIndex();
int i=0;
const std::vector< Part::Geometry * > &geometry = this->Geometry.getValues();
const std::vector< Part::Geometry * > geometry = getCompleteGeometry();
for (std::vector< Part::Geometry * >::const_iterator it = geometry.begin();
it != geometry.end(); ++it,i++) {
it != geometry.end(); ++it) {
if ((*it)->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(start);
@ -1057,6 +1212,9 @@ void SketchObject::rebuildVertexIndex(void)
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(end);
}
i++;
if (i > imax)
i = -getExternalGeometryCount();
}
}
@ -1135,14 +1293,15 @@ void SketchObject::Restore(XMLReader &reader)
{
// read the father classes
Part::Part2DObject::Restore(reader);
Constraints.acceptGeometry(Geometry.getValues());
rebuildExternalGeometry();
Constraints.acceptGeometry(getCompleteGeometry());
rebuildVertexIndex();
}
void SketchObject::onChanged(const App::Property* prop)
{
if (prop == &Geometry || prop == &Constraints)
Constraints.checkGeometry(Geometry.getValues());
Constraints.checkGeometry(getCompleteGeometry());
Part::Part2DObject::onChanged(prop);
}

View File

@ -41,11 +41,12 @@ class SketcherExport SketchObject : public Part::Part2DObject
public:
SketchObject();
~SketchObject();
/// Property
Part ::PropertyGeometryList Geometry;
Sketcher::PropertyConstraintList Constraints;
App ::PropertyLinkSubList ExternalConstraints;
App ::PropertyLinkSubList ExternalGeometry;
/** @name methods overide Feature */
//@{
/// recalculate the Feature
@ -62,7 +63,7 @@ public:
/// add unspecified geometry
int addGeometry(const std::vector<Part::Geometry *> &geoList);
/// delete geometry
int delGeometry(int GeoNbr);
int delGeometry(int GeoId);
/// add all constraints in the list
int addConstraints(const std::vector<Constraint *> &ConstraintList);
/// add constraint
@ -75,10 +76,27 @@ public:
int transferConstraints(int fromGeoId, PointPos fromPosId, int toGeoId, PointPos toPosId);
/// add an external geometry reference
int addExternal(App::DocumentObject *Obj, const char* SubName);
/// returns a list of projected external geoms
std::vector<Part::Geometry *> getExternalGeometry(void);
/// delete external
int delExternal(int ConstrId);
int delExternal(int ExtGeoId);
/** returns a pointer to a given Geometry index, possible indexes are:
* id>=0 for user defined geometries,
* id==-1 for the horizontal sketch axis,
* id==-2 for the vertical sketch axis
* id<=-3 for projected external geometries,
*/
const Part::Geometry* getGeometry(int GeoId) const;
/// returns a list of all internal geometries
const std::vector<Part::Geometry *> &getInternalGeometry(void) const { return Geometry.getValues(); }
/// returns a list of projected external geometries
const std::vector<Part::Geometry *> &getExternalGeometry(void) const { return ExternalGeo; }
/// rebuilds external geometry (projection onto the sketch plane)
void rebuildExternalGeometry(void);
/// returns the number of external Geometry entities
int getExternalGeometryCount(void) const { return ExternalGeo.size(); }
/// retrieves a vector containing both normal and external Geometry (including the sketch axes)
std::vector<Part::Geometry*> getCompleteGeometry(void) const;
/// returns non zero if the sketch contains conflicting constraints
int hasConflicts(void) const;
@ -86,12 +104,12 @@ public:
/// set the datum of a Distance or Angle constraint and solve
int setDatum(int ConstrId, double Datum);
/// move this point to a new location and solve
int movePoint(int geoIndex1, PointPos Pos1, const Base::Vector3d& toPoint, bool relative=false);
int movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative=false);
/// retrieves the coordinates of a point
Base::Vector3d getPoint(int geoIndex1, PointPos Pos1);
Base::Vector3d getPoint(int GeoId, PointPos PosId) const;
/// toggle geometry to draft line
int toggleConstruction(int GeoNbr);
int toggleConstruction(int GeoId);
/// create a fillet
int fillet(int geoId, PointPos pos, double radius, bool trim=true);
@ -104,8 +122,8 @@ public:
/// retrieves for a Vertex number the corresponding GeoId and PosId
void getGeoVertexIndex(int VertexId, int &GeoId, PointPos &PosId);
int getHighestVertexIndex(void) { return VertexId2GeoId.size() - 1; }
int getHighestCurveIndex(void) { return Geometry.getSize() - 1; }
int getHighestVertexIndex(void) const { return VertexId2GeoId.size() - 1; }
int getHighestCurveIndex(void) const { return Geometry.getSize() - 1; }
void rebuildVertexIndex(void);
/// retrieves for a Vertex number a list with all coincident points
@ -132,6 +150,8 @@ protected:
virtual void onChanged(const App::Property* /*prop*/);
private:
std::vector<Part::Geometry *> ExternalGeo;
std::vector<int> VertexId2GeoId;
std::vector<PointPos> VertexId2PosId;
};

View File

@ -152,7 +152,7 @@ PyObject* SketchObjectPy::addExternal(PyObject *args)
}
// add the external
if (this->getSketchObjectPtr()->addExternal(Obj,SubName)) {
if (this->getSketchObjectPtr()->addExternal(Obj,SubName) < 0) {
std::stringstream str;
str << "Not able to add external shape element";
PyErr_SetString(PyExc_ValueError, str.str().c_str());

View File

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="PersistencePy"
Name="SketchPy"
Twin="Sketch"
TwinPointer="Sketch"
Include="Mod/Sketcher/App/Sketch.h"
Namespace="Sketcher"
FatherInclude="Base/PersistencePy.h"
<PythonExport
Father="PersistencePy"
Name="SketchPy"
Twin="Sketch"
TwinPointer="Sketch"
Include="Mod/Sketcher/App/Sketch.h"
Namespace="Sketcher"
FatherInclude="Base/PersistencePy.h"
FatherNamespace="Base"
Constructor="true">
@ -17,7 +17,7 @@
</Documentation>
<Methode Name="solve">
<Documentation>
<UserDocu>solve the actuall set of geometry and constraints</UserDocu>
<UserDocu>solve the actual set of geometry and constraints</UserDocu>
</Documentation>
</Methode>
<Methode Name="addGeometry">

View File

@ -185,7 +185,6 @@ void CmdSketcherConstrainHorizontal::activated(int iMsg)
const std::vector<std::string> &SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
const std::vector<Part::Geometry *> &geomlist = Obj->Geometry.getValues();
std::vector<int> ids;
// go through the selected subelements
@ -194,7 +193,7 @@ void CmdSketcherConstrainHorizontal::activated(int iMsg)
if (it->size() > 4 && it->substr(0,4) == "Edge") {
int index=std::atoi(it->substr(4,4000).c_str());
Part::Geometry *geo = geomlist[index];
const Part::Geometry *geo = Obj->getGeometry(index);
if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Impossible constraint"),
QObject::tr("The selected edge is not a line segment"));
@ -220,7 +219,6 @@ void CmdSketcherConstrainHorizontal::activated(int iMsg)
}
// undo command open
openCommand("add horizontal constraint");
for (std::vector<int>::iterator it=ids.begin(); it != ids.end(); it++) {
// issue the actual commands to create the constraint
doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Horizontal',%d)) "
@ -272,17 +270,16 @@ void CmdSketcherConstrainVertical::activated(int iMsg)
const std::vector<std::string> &SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
const std::vector<Part::Geometry *> &geomlist = Obj->Geometry.getValues();
std::vector<int> ids;
// go through the selected subelements
for(std::vector<std::string>::const_iterator it=SubNames.begin();it!=SubNames.end();++it){
for (std::vector<std::string>::const_iterator it=SubNames.begin();it!=SubNames.end();++it) {
// only handle edges
if (it->size() > 4 && it->substr(0,4) == "Edge") {
int index=std::atoi(it->substr(4,4000).c_str());
Part::Geometry *geo = geomlist[index];
const Part::Geometry *geo = Obj->getGeometry(index);
if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Impossible constraint"),
QObject::tr("The selected edge is not a line segment"));
@ -523,7 +520,6 @@ void CmdSketcherConstrainDistance::activated(int iMsg)
// get the needed lists and objects
const std::vector<std::string> &SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
if (SubNames.size() < 1 || SubNames.size() > 2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
@ -535,12 +531,16 @@ void CmdSketcherConstrainDistance::activated(int iMsg)
if (SubNames.size() >= 1) {
if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
GeoId1 = std::atoi(SubNames[0].substr(4,4000).c_str());
else if (SubNames[0].size() > 12 && SubNames[0].substr(0,12) == "ExternalEdge")
GeoId1 = -3 - std::atoi(SubNames[0].substr(12,4000).c_str());
else if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex")
VtId1 = std::atoi(SubNames[0].substr(6,4000).c_str());
}
if (SubNames.size() == 2) {
if (SubNames[1].size() > 4 && SubNames[1].substr(0,4) == "Edge")
GeoId2 = std::atoi(SubNames[1].substr(4,4000).c_str());
else if (SubNames[1].size() > 12 && SubNames[1].substr(0,12) == "ExternalEdge")
GeoId2 = -3 - std::atoi(SubNames[1].substr(12,4000).c_str());
else if (SubNames[1].size() > 6 && SubNames[1].substr(0,6) == "Vertex")
VtId2 = std::atoi(SubNames[1].substr(6,4000).c_str());
}
@ -576,7 +576,7 @@ void CmdSketcherConstrainDistance::activated(int iMsg)
Sketcher::PointPos PosId1;
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
Base::Vector3d pnt = Obj->getPoint(GeoId1,PosId1);
const Part::Geometry *geom = geo[GeoId2];
const Part::Geometry *geom = Obj->getGeometry(GeoId2);
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg;
lineSeg = dynamic_cast<const Part::GeomLineSegment*>(geom);
@ -603,7 +603,7 @@ void CmdSketcherConstrainDistance::activated(int iMsg)
}
}
else if (GeoId1 >= 0) { // line length
const Part::Geometry *geom = geo[GeoId1];
const Part::Geometry *geom = Obj->getGeometry(GeoId1);
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg;
lineSeg = dynamic_cast<const Part::GeomLineSegment*>(geom);
@ -670,7 +670,6 @@ void CmdSketcherConstrainPointOnObject::activated(int iMsg)
// get the needed lists and objects
const std::vector<std::string> &SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
if (SubNames.size() < 1 || SubNames.size() > 2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
@ -683,17 +682,21 @@ void CmdSketcherConstrainPointOnObject::activated(int iMsg)
if (SubNames.size() >= 1) {
if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
GeoId1 = std::atoi(SubNames[0].substr(4,4000).c_str());
else if (SubNames[0].size() > 12 && SubNames[0].substr(0,12) == "ExternalEdge")
GeoId1 = -3 - std::atoi(SubNames[0].substr(12,4000).c_str());
else if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex")
VtId1 = std::atoi(SubNames[0].substr(6,4000).c_str());
}
if (SubNames.size() == 2) {
if (SubNames[1].size() > 4 && SubNames[1].substr(0,4) == "Edge")
GeoId2 = std::atoi(SubNames[1].substr(4,4000).c_str());
else if (SubNames[1].size() > 12 && SubNames[1].substr(0,12) == "ExternalEdge")
GeoId2 = -3 - std::atoi(SubNames[1].substr(12,4000).c_str());
else if (SubNames[1].size() > 6 && SubNames[1].substr(0,6) == "Vertex")
VtId2 = std::atoi(SubNames[1].substr(6,4000).c_str());
}
if ((VtId1 >= 0 && GeoId2 >= 0) || (VtId2 >= 0 && GeoId1 >= 0)) {
if ((VtId1 >= 0 && GeoId2 != Constraint::GeoUndef) || (VtId2 >= 0 && GeoId1 != Constraint::GeoUndef)) {
if (VtId2 >= 0 && GeoId1 >= 0) {
std::swap(VtId1,VtId2);
std::swap(GeoId1,GeoId2);
@ -702,7 +705,7 @@ void CmdSketcherConstrainPointOnObject::activated(int iMsg)
Sketcher::PointPos PosId1;
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
const Part::Geometry *geom = geo[GeoId2];
const Part::Geometry *geom = Obj->getGeometry(GeoId2);
// Currently only accepts line segments and circles
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
@ -761,7 +764,6 @@ void CmdSketcherConstrainDistanceX::activated(int iMsg)
// get the needed lists and objects
const std::vector<std::string> &SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
if (SubNames.size() < 1 || SubNames.size() > 2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
@ -773,19 +775,30 @@ void CmdSketcherConstrainDistanceX::activated(int iMsg)
if (SubNames.size() >= 1) {
if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
GeoId1 = std::atoi(SubNames[0].substr(4,4000).c_str());
else if (SubNames[0].size() == 6 && SubNames[0].substr(0,6) == "V_Axis")
GeoId1 = -2;
else if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex")
VtId1 = std::atoi(SubNames[0].substr(6,4000).c_str());
}
if (SubNames.size() == 2) {
if (SubNames[1].size() > 4 && SubNames[1].substr(0,4) == "Edge")
GeoId2 = std::atoi(SubNames[1].substr(4,4000).c_str());
else if (SubNames[1].size() == 6 && SubNames[0].substr(0,6) == "V_Axis")
GeoId2 = -2;
else if (SubNames[1].size() > 6 && SubNames[1].substr(0,6) == "Vertex")
VtId2 = std::atoi(SubNames[1].substr(6,4000).c_str());
}
if (GeoId2 == -2 && GeoId1 == Constraint::GeoUndef) {
std::swap(GeoId1,GeoId2);
std::swap(VtId1,VtId2);
}
if (VtId1 >= 0 && VtId2 >= 0) { // point to point horizontal distance
if ((GeoId1 == -2 || VtId1 >= 0) && VtId2 >= 0) { // point to point horizontal distance
Sketcher::PointPos PosId1,PosId2;
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
if (GeoId1 == -2)
PosId1 = Sketcher::start;
else
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
Base::Vector3d pnt1 = Obj->getPoint(GeoId1,PosId1);
Base::Vector3d pnt2 = Obj->getPoint(GeoId2,PosId2);
@ -807,8 +820,8 @@ void CmdSketcherConstrainDistanceX::activated(int iMsg)
getSelection().clearSelection();
return;
}
else if (GeoId1 >= 0 && GeoId2 < 0 && VtId2 < 0) { // horizontal length of a line
const Part::Geometry *geom = geo[GeoId1];
else if (GeoId1 >= 0 && GeoId2 == Constraint::GeoUndef && VtId2 < 0) { // horizontal length of a line
const Part::Geometry *geom = Obj->getGeometry(GeoId1);
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg;
lineSeg = dynamic_cast<const Part::GeomLineSegment*>(geom);
@ -896,7 +909,6 @@ void CmdSketcherConstrainDistanceY::activated(int iMsg)
// get the needed lists and objects
const std::vector<std::string> &SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
if (SubNames.size() < 1 || SubNames.size() > 2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
@ -908,19 +920,30 @@ void CmdSketcherConstrainDistanceY::activated(int iMsg)
if (SubNames.size() >= 1) {
if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge")
GeoId1 = std::atoi(SubNames[0].substr(4,4000).c_str());
else if (SubNames[0].size() == 6 && SubNames[0].substr(0,6) == "H_Axis")
GeoId1 = -1;
else if (SubNames[0].size() > 6 && SubNames[0].substr(0,6) == "Vertex")
VtId1 = std::atoi(SubNames[0].substr(6,4000).c_str());
}
if (SubNames.size() == 2) {
if (SubNames[1].size() > 4 && SubNames[1].substr(0,4) == "Edge")
GeoId2 = std::atoi(SubNames[1].substr(4,4000).c_str());
else if (SubNames[1].size() == 6 && SubNames[0].substr(0,6) == "H_Axis")
GeoId2 = -1;
else if (SubNames[1].size() > 6 && SubNames[1].substr(0,6) == "Vertex")
VtId2 = std::atoi(SubNames[1].substr(6,4000).c_str());
}
if (GeoId2 == -1 && GeoId1 == Constraint::GeoUndef) {
std::swap(GeoId1,GeoId2);
std::swap(VtId1,VtId2);
}
if (VtId1 >= 0 && VtId2 >= 0) { // point to point horizontal distance
if ((GeoId1 == -1 || VtId1 >= 0) && VtId2 >= 0) { // point to point horizontal distance
Sketcher::PointPos PosId1,PosId2;
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
if (GeoId1 == -1)
PosId1 = Sketcher::start;
else
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
Base::Vector3d pnt1 = Obj->getPoint(GeoId1,PosId1);
Base::Vector3d pnt2 = Obj->getPoint(GeoId2,PosId2);
@ -942,8 +965,8 @@ void CmdSketcherConstrainDistanceY::activated(int iMsg)
getSelection().clearSelection();
return;
}
else if (GeoId1 >= 0 && GeoId2 < 0 && VtId2 < 0) { // horizontal length of a line
const Part::Geometry *geom = geo[GeoId1];
else if (GeoId1 >= 0 && GeoId2 == Constraint::GeoUndef && VtId2 < 0) { // horizontal length of a line
const Part::Geometry *geom = Obj->getGeometry(GeoId1);
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg;
lineSeg = dynamic_cast<const Part::GeomLineSegment*>(geom);
@ -1031,9 +1054,6 @@ void CmdSketcherConstrainParallel::activated(int iMsg)
// get the needed lists and objects
const std::vector<std::string> &SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
const std::vector<Part::Geometry *> &geomlist = Obj->Geometry.getValues();
// go through the selected subelements
@ -1049,6 +1069,8 @@ void CmdSketcherConstrainParallel::activated(int iMsg)
std::string subName = *it;
if (subName.size() > 4 && subName.substr(0,4) == "Edge")
index = std::atoi(subName.substr(4,4000).c_str());
else if (subName.size() > 12 && subName.substr(0,12) == "ExternalEdge")
index = -3 - std::atoi(subName.substr(12,4000).c_str());
else {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Select a valid line"));
@ -1056,7 +1078,7 @@ void CmdSketcherConstrainParallel::activated(int iMsg)
}
// Check that the curve is a line segment
Part::Geometry *geo = geomlist[index];
const Part::Geometry *geo = Obj->getGeometry(index);
if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("The selected edge is not a valid line"));
@ -1067,16 +1089,11 @@ void CmdSketcherConstrainParallel::activated(int iMsg)
// undo command open
openCommand("add parallel constraint");
int i = 0;
for (std::vector<int>::iterator it = ids.begin(); it!=ids.end();++it, i++) {
if(i == ids.size() - 1)
break;
for (int i=0; i < int(ids.size()-1); i++) {
Gui::Command::doCommand(
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Parallel',%d,%d)) ",
selection[0].getFeatName(),ids[i],ids[i+1]);
}
// finish the transaction and update
commitCommand();
updateActive();
@ -1122,8 +1139,6 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg)
// get the needed lists and objects
const std::vector<std::string> &SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
const std::vector<Part::Geometry *> &geomlist = Obj->Geometry.getValues();
if (SubNames.size() != 2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
@ -1148,8 +1163,8 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg)
return;
}
Part::Geometry *geo1 = geomlist[GeoId1];
Part::Geometry *geo2 = geomlist[GeoId2];
const Part::Geometry *geo1 = Obj->getGeometry(GeoId1);
const Part::Geometry *geo2 = Obj->getGeometry(GeoId2);
if (geo1->getTypeId() != Part::GeomLineSegment::getClassTypeId() ||
geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
@ -1310,7 +1325,6 @@ void CmdSketcherConstrainRadius::activated(int iMsg)
// get the needed lists and objects
const std::vector<std::string> &SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
if (SubNames.size() != 1) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
@ -1321,7 +1335,7 @@ void CmdSketcherConstrainRadius::activated(int iMsg)
if (SubNames[0].size() > 4 && SubNames[0].substr(0,4) == "Edge") {
int GeoId = std::atoi(SubNames[0].substr(4,4000).c_str());
const Part::Geometry *geom = geo[GeoId];
const Part::Geometry *geom = Obj->getGeometry(GeoId);
if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *arc = dynamic_cast<const Part::GeomArcOfCircle *>(geom);
double ActRadius = arc->getRadius();
@ -1392,7 +1406,6 @@ void CmdSketcherConstrainAngle::activated(int iMsg)
// get the needed lists and objects
const std::vector<std::string> &SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
if (SubNames.size() < 1 || SubNames.size() > 2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
@ -1409,8 +1422,8 @@ void CmdSketcherConstrainAngle::activated(int iMsg)
}
if (GeoId2 >= 0) { // line to line angle
const Part::Geometry *geom1 = geo[GeoId1];
const Part::Geometry *geom2 = geo[GeoId2];
const Part::Geometry *geom1 = Obj->getGeometry(GeoId1);
const Part::Geometry *geom2 = Obj->getGeometry(GeoId2);
if (geom1->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg1 = dynamic_cast<const Part::GeomLineSegment*>(geom1);
@ -1463,7 +1476,7 @@ void CmdSketcherConstrainAngle::activated(int iMsg)
return;
}
} else if (GeoId1 >= 0) { // line angle
const Part::Geometry *geom = geo[GeoId1];
const Part::Geometry *geom = Obj->getGeometry(GeoId1);
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg;
lineSeg = dynamic_cast<const Part::GeomLineSegment*>(geom);
@ -1538,8 +1551,6 @@ void CmdSketcherConstrainEqual::activated(int iMsg)
// get the needed lists and objects
const std::vector<std::string> &SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
const std::vector<Part::Geometry *> &geomlist = Obj->Geometry.getValues();
// go through the selected subelements
@ -1563,7 +1574,7 @@ void CmdSketcherConstrainEqual::activated(int iMsg)
return;
}
Part::Geometry *geo = geomlist[index];
const Part::Geometry *geo = Obj->getGeometry(index);
if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
lineSel = true;
} else if (geo->getTypeId() != Part::GeomArcOfCircle::getClassTypeId()) {
@ -1587,10 +1598,7 @@ void CmdSketcherConstrainEqual::activated(int iMsg)
// undo command open
openCommand("add equality constraint");
int i = 0;
for (std::vector<int>::iterator it = ids.begin(); it!=ids.end();it++, i++) {
if( i == ids.size() - 1)
break;
for (int i=0; i < int(ids.size()-1); i++) {
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Equal',%d,%d)) ",
selection[0].getFeatName(),ids[i],ids[i+1]);
}
@ -1629,7 +1637,6 @@ void CmdSketcherConstrainSymmetric::activated(int iMsg)
// get the selection
std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
const std::vector<Part::Geometry *> &geo = Obj->Geometry.getValues();
// only one sketch with its subelements are allowed to be selected
if (selection.size() != 1) {
@ -1678,7 +1685,7 @@ void CmdSketcherConstrainSymmetric::activated(int iMsg)
Sketcher::PointPos PosId1,PosId2;
Obj->getGeoVertexIndex(VtId1,GeoId1,PosId1);
Obj->getGeoVertexIndex(VtId2,GeoId2,PosId2);
const Part::Geometry *geom = geo[GeoId3];
const Part::Geometry *geom = Obj->getGeometry(GeoId3);
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
// undo command open
openCommand("add symmetric constraint");

View File

@ -613,7 +613,7 @@ public:
// setup for the next line segment
// Use updated endPoint as autoconstraints can modify the position
Part::Geometry *geom = getObject()->Geometry.getValues()[getHighestCurveIndex()];
const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(getHighestCurveIndex());
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(geom);
EditCurve[0] = Base::Vector2D(lineSeg->getEndPoint().x, lineSeg->getEndPoint().y);
@ -1152,8 +1152,7 @@ namespace SketcherGui {
if (element.substr(0,4) == "Edge") {
int index=std::atoi(element.substr(4,4000).c_str());
Sketcher::SketchObject *Sketch = static_cast<Sketcher::SketchObject*>(object);
const std::vector<Part::Geometry *> &geo = Sketch->Geometry.getValues();
const Part::Geometry *geom = geo[index];
const Part::Geometry *geom = Sketch->getGeometry(index);
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId())
return true;
}
@ -1163,10 +1162,9 @@ namespace SketcherGui {
std::vector<int> GeoIdList;
std::vector<Sketcher::PointPos> PosIdList;
Sketch->getCoincidentPoints(index, GeoIdList, PosIdList);
if (GeoIdList.size() == 2) {
const std::vector<Part::Geometry *> &geo = Sketch->Geometry.getValues();
const Part::Geometry *geom1 = geo[GeoIdList[0]];
const Part::Geometry *geom2 = geo[GeoIdList[1]];
if (GeoIdList.size() == 2 && GeoIdList[0] >= 0 && GeoIdList[1] >= 0) {
const Part::Geometry *geom1 = Sketch->getGeometry(GeoIdList[0]);
const Part::Geometry *geom2 = Sketch->getGeometry(GeoIdList[1]);
if (geom1->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId())
return true;
@ -1252,8 +1250,7 @@ public:
int GeoId;
Sketcher::PointPos PosId=Sketcher::none;
sketchgui->getSketchObject()->getGeoVertexIndex(VtId,GeoId,PosId);
const std::vector<Part::Geometry *> &geo = sketchgui->getSketchObject()->Geometry.getValues();
const Part::Geometry *geom = geo[GeoId];
const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(GeoId);
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
(PosId == Sketcher::start || PosId == Sketcher::end)) {
@ -1262,15 +1259,15 @@ public:
std::vector<int> GeoIdList;
std::vector<Sketcher::PointPos> PosIdList;
sketchgui->getSketchObject()->getCoincidentPoints(GeoId, PosId, GeoIdList, PosIdList);
if (GeoIdList.size() == 2) {
const Part::Geometry *geom1 = geo[GeoIdList[0]];
const Part::Geometry *geom2 = geo[GeoIdList[1]];
if (GeoIdList.size() == 2 && GeoIdList[0] >= 0 && GeoIdList[1] >= 0) {
const Part::Geometry *geom1 = sketchgui->getSketchObject()->getGeometry(GeoIdList[0]);
const Part::Geometry *geom2 = sketchgui->getSketchObject()->getGeometry(GeoIdList[1]);
if (geom1->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg1 = dynamic_cast<const Part::GeomLineSegment *>(geom1);
const Part::GeomLineSegment *lineSeg2 = dynamic_cast<const Part::GeomLineSegment *>(geom2);
Base::Vector3d dir1 = lineSeg1->getEndPoint() - lineSeg1->getStartPoint();
Base::Vector3d dir2 = lineSeg2->getEndPoint() - lineSeg2->getStartPoint();
Base::Vector3d dir1 = lineSeg1->getEndPoint() - lineSeg1->getStartPoint();
Base::Vector3d dir2 = lineSeg2->getEndPoint() - lineSeg2->getStartPoint();
if (PosIdList[0] == Sketcher::end)
dir1 *= -1;
if (PosIdList[1] == Sketcher::end)
@ -1297,8 +1294,7 @@ public:
int GeoId = sketchgui->getPreselectCurve();
if (GeoId > -1) {
const std::vector<Part::Geometry *> &geo = sketchgui->getSketchObject()->Geometry.getValues();
const Part::Geometry *geom = geo[GeoId];
const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(GeoId);
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
if (Mode==STATUS_SEEK_First) {
firstCurve = GeoId;
@ -1319,8 +1315,10 @@ public:
Base::Vector2D secondPos = onSketchPos;
// guess fillet radius
const Part::GeomLineSegment *lineSeg1 = dynamic_cast<const Part::GeomLineSegment *>(geo[firstCurve]);
const Part::GeomLineSegment *lineSeg2 = dynamic_cast<const Part::GeomLineSegment *>(geo[secondCurve]);
const Part::GeomLineSegment *lineSeg1 = dynamic_cast<const Part::GeomLineSegment *>
(sketchgui->getSketchObject()->getGeometry(firstCurve));
const Part::GeomLineSegment *lineSeg2 = dynamic_cast<const Part::GeomLineSegment *>
(sketchgui->getSketchObject()->getGeometry(secondCurve));
Base::Vector3d refPnt1(firstPos.fX, firstPos.fY, 0.f);
Base::Vector3d refPnt2(secondPos.fX, secondPos.fY, 0.f);
double radius = Part::suggestFilletRadius(lineSeg1, lineSeg2, refPnt1, refPnt2);
@ -1401,8 +1399,7 @@ namespace SketcherGui {
if (element.substr(0,4) == "Edge") {
int index=std::atoi(element.substr(4,4000).c_str());
Sketcher::SketchObject *Sketch = static_cast<Sketcher::SketchObject*>(object);
const std::vector<Part::Geometry *> &geo = Sketch->Geometry.getValues();
const Part::Geometry *geom = geo[index];
const Part::Geometry *geom = Sketch->getGeometry(index);
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
geom->getTypeId() == Part::GeomCircle::getClassTypeId()||
geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId())
@ -1482,8 +1479,7 @@ public:
{
int GeoId = sketchgui->getPreselectCurve();
if (GeoId > -1) {
const std::vector<Part::Geometry *> &geo = sketchgui->getSketchObject()->Geometry.getValues();
const Part::Geometry *geom = geo[GeoId];
const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(GeoId);
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
geom->getTypeId() == Part::GeomCircle::getClassTypeId()

View File

@ -82,19 +82,14 @@ void DrawSketchHandler::quit(void)
//**************************************************************************
// Helpers
Sketcher::SketchObject* DrawSketchHandler::getObject(void)
{
return dynamic_cast<Sketcher::SketchObject*>(sketchgui->getObject());
}
int DrawSketchHandler::getHighestVertexIndex(void)
{
return getObject()->getHighestVertexIndex();
return sketchgui->getSketchObject()->getHighestVertexIndex();
}
int DrawSketchHandler::getHighestCurveIndex(void)
{
return getObject()->getHighestCurveIndex();
return sketchgui->getSketchObject()->getHighestCurveIndex();
}
void DrawSketchHandler::setCursor(const QPixmap &p,int x,int y)
@ -199,15 +194,15 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggested
// FIXME needs to consider when zooming out?
const float tangDeviation = 2.;
int tangId = -1;
float smlTangDist = 0;
int tangId = Constraint::GeoUndef;
float smlTangDist = 1e15;
// Get geometry list
const std::vector<Part::Geometry *> geomlist = getObject()->Geometry.getValues();
const std::vector<Part::Geometry *> geomlist = sketchgui->getSketchObject()->getCompleteGeometry();
// Iterate through geometry
int i = 0;
for (std::vector<Part::Geometry *>::const_iterator it = geomlist.begin(); it != geomlist.end(); ++it, i++) {
for (std::vector<Part::Geometry *>::const_iterator it=geomlist.begin(); it != geomlist.end(); ++it, i++) {
if ((*it)->getTypeId() == Part::GeomCircle::getClassTypeId()) {
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>((*it));
@ -221,11 +216,9 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggested
projPnt = projPnt.ProjToLine(center - tmpPos, Base::Vector3d(Dir.fX, Dir.fY));
float projDist = projPnt.Length();
if ( (projDist < radius + tangDeviation ) && (projDist > radius - tangDeviation))
{
if ( (projDist < radius + tangDeviation ) && (projDist > radius - tangDeviation)) {
// Find if nearest
if (tangId == -1 || projDist< smlTangDist)
{
if (projDist < smlTangDist) {
tangId = i;
smlTangDist = projDist;
}
@ -252,7 +245,7 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggested
// if the pnt is on correct side of arc and find if nearest
if ((angle > startAngle && angle < endAngle) &&
(tangId == -1 || projDist < smlTangDist) ) {
(projDist < smlTangDist) ) {
tangId = i;
smlTangDist = projDist;
}
@ -260,7 +253,9 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggested
}
}
if (tangId != -1) {
if (tangId != Constraint::GeoUndef) {
if (tangId > getHighestCurveIndex()) // external Geometry
tangId = getHighestCurveIndex() - tangId;
// Suggest vertical constraint
AutoConstraint tangConstr;
tangConstr.Index = tangId;
@ -272,7 +267,7 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggested
}
void DrawSketchHandler::createAutoConstraints(const std::vector<AutoConstraint> &autoConstrs,
int geoId, Sketcher::PointPos pointPos)
int geoId1, Sketcher::PointPos posId1)
{
if (!sketchgui->Autoconstraints.getValue())
return; // If Autoconstraints property is not set quit
@ -287,47 +282,47 @@ void DrawSketchHandler::createAutoConstraints(const std::vector<AutoConstraint>
switch (it->Type)
{
case Sketcher::Coincident: {
if (pointPos == Sketcher::none)
if (posId1 == Sketcher::none)
continue;
// If the auto constraint has a point create a coincident otherwise it is an edge on a point
Sketcher::PointPos pointPos2;
Sketcher::PointPos posId2;
int geoId2;
sketchgui->getSketchObject()->getGeoVertexIndex(it->Index, geoId2, pointPos2);
sketchgui->getSketchObject()->getGeoVertexIndex(it->Index, geoId2, posId2);
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%i,%i,%i,%i)) "
,sketchgui->getObject()->getNameInDocument()
,geoId, pointPos, geoId2, pointPos2
,geoId1, posId1, geoId2, posId2
);
} break;
case Sketcher::PointOnObject: {
int index = it->Index;
if (pointPos == Sketcher::none) {
if (posId1 == Sketcher::none) {
// Auto constraining an edge so swap parameters
index = geoId;
sketchgui->getSketchObject()->getGeoVertexIndex(it->Index, geoId, pointPos);
index = geoId1;
sketchgui->getSketchObject()->getGeoVertexIndex(it->Index, geoId1, posId1);
}
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('PointOnObject',%i,%i,%i)) "
,sketchgui->getObject()->getNameInDocument()
,geoId, pointPos, index
,geoId1, posId1, index
);
} break;
case Sketcher::Horizontal: {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Horizontal',%i)) "
,sketchgui->getObject()->getNameInDocument()
,geoId
,geoId1
);
} break;
case Sketcher::Vertical: {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Vertical',%i)) "
,sketchgui->getObject()->getNameInDocument()
,geoId
,geoId1
);
} break;
case Sketcher::Tangent: {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Tangent',%i, %i)) "
,sketchgui->getObject()->getNameInDocument()
,geoId, it->Index
,geoId1, it->Index
);
} break;
}

View File

@ -75,7 +75,6 @@ public:
friend class ViewProviderSketch;
Sketcher::SketchObject* getObject(void);
// get the actual highest vertex index, the next use will be +1
int getHighestVertexIndex(void);
// get the actual highest edge index, the next use will be +1
@ -94,8 +93,8 @@ protected:
// helpers
void setCursor( const QPixmap &p,int x,int y );
void unsetCursor(void);
void applyCursor(void);
void applyCursor(QCursor &newCursor);
void applyCursor(void);
void applyCursor(QCursor &newCursor);
ViewProviderSketch *sketchgui;
QCursor oldCursor;

View File

@ -102,6 +102,7 @@ using namespace Sketcher;
SbColor ViewProviderSketch::VertexColor (1.0f,0.149f,0.0f); // #FF2600 -> (255, 38, 0)
SbColor ViewProviderSketch::CurveColor (1.0f,1.0f,1.0f); // #FFFFFF -> (255,255,255)
SbColor ViewProviderSketch::CurveDraftColor (0.0f,0.0f,0.86f); // #0000DC -> ( 0, 0,220)
SbColor ViewProviderSketch::CurveExternalColor (0.8f,0.2f,0.6f); // #CC3399 -> (204, 51,153)
SbColor ViewProviderSketch::CrossColorV (0.8f,0.4f,0.4f); // #CC6666 -> (204,102,102)
SbColor ViewProviderSketch::CrossColorH (0.4f,0.8f,0.4f); // #66CC66 -> (102,204,102)
SbColor ViewProviderSketch::FullyConstrainedColor (0.0f,1.0f,0.0f); // #00FF00 -> ( 0,255, 0)
@ -162,9 +163,8 @@ struct EditData {
Sketcher::Sketch ActSketch;
// container to track our own selected parts
std::set<int> SelPointSet;
std::set<int> SelCurvSet;
std::set<int> SelCurvSet; // also holds cross axes at -1 and -2
std::set<int> SelConstraintSet;
std::set<int> SelCrossSet;
// helper data structure for the constraint rendering
std::vector<ConstraintType> vConstrType;
@ -173,18 +173,15 @@ struct EditData {
SoSeparator *EditRoot;
SoMaterial *PointsMaterials;
SoMaterial *CurvesMaterials;
SoMaterial *RootCrossMaterialsV;
SoMaterial *RootCrossMaterialsH;
SoMaterial *RootCrossMaterials;
SoMaterial *EditCurvesMaterials;
SoCoordinate3 *PointsCoordinate;
SoCoordinate3 *CurvesCoordinate;
SoCoordinate3 *RootCrossCoordinateV;
SoCoordinate3 *RootCrossCoordinateH;
SoCoordinate3 *RootCrossCoordinate;
SoCoordinate3 *EditCurvesCoordinate;
SoLineSet *CurveSet;
SoLineSet *EditCurveSet;
SoLineSet *RootCrossSetV;
SoLineSet *RootCrossSetH;
SoLineSet *RootCrossSet;
SoMarkerSet *PointSet;
SoText2 *textX;
@ -194,6 +191,15 @@ struct EditData {
};
// this function is used to simulate cyclic periodic negative geometry indices (for external geometry)
const Part::Geometry* GeoById(const std::vector<Part::Geometry*> GeoList, int Id)
{
if (Id >= 0)
return GeoList[Id];
else
return GeoList[GeoList.size()+Id];
}
//**************************************************************************
// Construction/Destruction
@ -358,19 +364,19 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe
float dci = (float) QApplication::doubleClickInterval()/1000.0f;
float length = (point - prvClickPoint).length();
if (edit->PreselectPoint >=0) {
if (edit->PreselectPoint >= 0) {
//Base::Console().Log("start dragging, point:%d\n",this->DragPoint);
Mode = STATUS_SELECT_Point;
done = true;
} else if (edit->PreselectCurve >=0) {
} else if (edit->PreselectCurve >= 0) {
//Base::Console().Log("start dragging, point:%d\n",this->DragPoint);
Mode = STATUS_SELECT_Edge;
done = true;
} else if (edit->PreselectCross >=0) {
} else if (edit->PreselectCross >= 0) {
//Base::Console().Log("start dragging, point:%d\n",this->DragPoint);
Mode = STATUS_SELECT_Cross;
done = true;
} else if (edit->PreselectConstraint >=0) {
} else if (edit->PreselectConstraint >= 0) {
//Base::Console().Log("start dragging, point:%d\n",this->DragPoint);
Mode = STATUS_SELECT_Constraint;
done = true;
@ -429,8 +435,14 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe
case STATUS_SELECT_Edge:
if (pp) {
//Base::Console().Log("Select Point:%d\n",this->DragPoint);
int maxGeoId = getSketchObject()->getHighestCurveIndex();
std::stringstream ss;
ss << "Edge" << edit->PreselectCurve;
if (edit->PreselectCurve <= maxGeoId)
ss << "Edge" << edit->PreselectCurve;
else { // external geometry
int extGeoCount = getSketchObject()->getExternalGeometryCount();
ss << "ExternalEdge" << extGeoCount - 2 - (edit->PreselectCurve - maxGeoId);
}
// If edge already selected move from selection
if (Gui::Selection().isSelected(getSketchObject()->getDocument()->getName()
@ -462,7 +474,6 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe
case 2: ss << "V_Axis" ; break;
}
// If cross already selected move from selection
if (Gui::Selection().isSelected(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument(),ss.str().c_str()) ) {
@ -531,9 +542,7 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe
return true;
case STATUS_SKETCH_DragCurve:
if (edit->DragCurve != -1 && pp) {
const std::vector<Part::Geometry *> *geomlist;
geomlist = &getSketchObject()->Geometry.getValues();
Part::Geometry *geo = (*geomlist)[edit->DragCurve];
const Part::Geometry *geo = getSketchObject()->getGeometry(edit->DragCurve);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
@ -581,11 +590,11 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe
case STATUS_NONE:
{
// A right click shouldn't change the Edit Mode
if (edit->PreselectPoint >=0) {
if (edit->PreselectPoint >= 0) {
return true;
} else if (edit->PreselectCurve >=0) {
} else if (edit->PreselectCurve >= 0) {
return true;
} else if (edit->PreselectConstraint >=0) {
} else if (edit->PreselectConstraint >= 0) {
return true;
} else {
//Get Viewer
@ -691,18 +700,21 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe
void ViewProviderSketch::editDoubleClicked(void)
{
if (edit->PreselectPoint >=0) {
Base::Console().Log("double click point:%d\n",edit->PreselectPoint);
} else if (edit->PreselectCurve >=0) {
Base::Console().Log("double click edge:%d\n",edit->PreselectCurve);
} else if (edit->PreselectCross >=0) {
Base::Console().Log("double click cross:%d\n",edit->PreselectCross);
} else if (edit->PreselectConstraint >=0) {
if (edit->PreselectPoint >= 0) {
Base::Console().Log("double click point:%d\n",edit->PreselectPoint);
}
else if (edit->PreselectCurve >= 0) {
Base::Console().Log("double click edge:%d\n",edit->PreselectCurve);
}
else if (edit->PreselectCross >= 0) {
Base::Console().Log("double click cross:%d\n",edit->PreselectCross);
}
else if (edit->PreselectConstraint >= 0) {
// Find the constraint
Base::Console().Log("double click constraint:%d\n",edit->PreselectConstraint);
const std::vector<Sketcher::Constraint *> &ConStr = getSketchObject()->Constraints.getValues();
Constraint *Constr = ConStr[edit->PreselectConstraint];
const std::vector<Sketcher::Constraint *> &constrlist = getSketchObject()->Constraints.getValues();
Constraint *Constr = constrlist[edit->PreselectConstraint];
// if its the right constraint
if (Constr->Type == Sketcher::Distance ||
@ -767,7 +779,7 @@ bool ViewProviderSketch::mouseMove(const SbVec3f &point, const SbVec3f &normal,
Mode = STATUS_SKETCH_DragCurve;
edit->DragCurve = edit->PreselectCurve;
edit->ActSketch.initMove(edit->DragCurve, Sketcher::none);
Part::Geometry *geo = getSketchObject()->Geometry.getValues()[edit->DragCurve];
const Part::Geometry *geo = getSketchObject()->getGeometry(edit->DragCurve);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
relative = true;
xInit = x;
@ -847,14 +859,19 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2D &toPo
if (!edit)
return;
const std::vector<Sketcher::Constraint *> &ConStr = getSketchObject()->Constraints.getValues();
Constraint *Constr = ConStr[constNum];
const std::vector<Sketcher::Constraint *> &constrlist = getSketchObject()->Constraints.getValues();
Constraint *Constr = constrlist[constNum];
if (Constr->Type == Distance || Constr->Type == DistanceX || Constr->Type == DistanceY ||
Constr->Type == Radius) {
const std::vector<Part::Geometry *> geomlist = edit->ActSketch.getGeometry();
assert(Constr->First < int(geomlist.size()));
int intGeoCount = getSketchObject()->getHighestCurveIndex() + 1;
int extGeoCount = getSketchObject()->getExternalGeometryCount();
const std::vector<Part::Geometry *> geomlist = edit->ActSketch.extractGeometry(true, true);
assert(int(geomlist.size()) == extGeoCount + intGeoCount);
assert((Constr->First >= -extGeoCount && Constr->First < intGeoCount)
|| Constr->First != Constraint::GeoUndef);
Base::Vector3d p1(0.,0.,0.), p2(0.,0.,0.);
if (Constr->SecondPos != Sketcher::none) { // point to point distance
@ -862,7 +879,7 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2D &toPo
p2 = edit->ActSketch.getPoint(Constr->Second, Constr->SecondPos);
} else if (Constr->Second != Constraint::GeoUndef) { // point to line distance
p1 = edit->ActSketch.getPoint(Constr->First, Constr->FirstPos);
const Part::Geometry *geo = geomlist[Constr->Second];
const Part::Geometry *geo = GeoById(geomlist, Constr->Second);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(geo);
Base::Vector3d l2p1 = lineSeg->getStartPoint();
@ -875,7 +892,7 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2D &toPo
} else if (Constr->FirstPos != Sketcher::none) {
p2 = edit->ActSketch.getPoint(Constr->First, Constr->FirstPos);
} else if (Constr->First != Constraint::GeoUndef) {
const Part::Geometry *geo = geomlist[Constr->First];
const Part::Geometry *geo = GeoById(geomlist, Constr->First);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(geo);
p1 = lineSeg->getStartPoint();
@ -918,13 +935,18 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2D &toPo
}
}
else if (Constr->Type == Angle) {
const std::vector<Part::Geometry *> geomlist = edit->ActSketch.getGeometry();
assert(Constr->First < int(geomlist.size()));
int intGeoCount = getSketchObject()->getHighestCurveIndex() + 1;
int extGeoCount = getSketchObject()->getExternalGeometryCount();
const std::vector<Part::Geometry *> geomlist = edit->ActSketch.extractGeometry(true, true);
assert(int(geomlist.size()) == extGeoCount + intGeoCount);
assert((Constr->First >= -extGeoCount && Constr->First < intGeoCount)
|| Constr->First != Constraint::GeoUndef);
Base::Vector3d p0(0.,0.,0.);
if (Constr->Second != Constraint::GeoUndef) { // line to line angle
const Part::Geometry *geo1 = geomlist[Constr->First];
const Part::Geometry *geo2 = geomlist[Constr->Second];
const Part::Geometry *geo1 = GeoById(geomlist, Constr->First);
const Part::Geometry *geo2 = GeoById(geomlist, Constr->Second);
if (geo1->getTypeId() != Part::GeomLineSegment::getClassTypeId() ||
geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId())
return;
@ -950,7 +972,7 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2D &toPo
p0 = Base::Vector3d(x,y,0);
}
} else if (Constr->First != Constraint::GeoUndef) { // line angle
const Part::Geometry *geo = geomlist[Constr->First];
const Part::Geometry *geo = GeoById(geomlist, Constr->First);
if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId())
return;
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(geo);
@ -1027,11 +1049,10 @@ void ViewProviderSketch::onSelectionChanged(const Gui::SelectionChanges& msg)
std::string temp;
if (msg.Type == Gui::SelectionChanges::ClrSelection) {
// if something selected in this object?
if (edit->SelPointSet.size() > 0 || edit->SelCurvSet.size() > 0 || edit->SelCrossSet.size() > 0 || edit->SelConstraintSet.size() > 0) {
if (edit->SelPointSet.size() > 0 || edit->SelCurvSet.size() > 0 || edit->SelConstraintSet.size() > 0) {
// clear our selection and update the color of the viewed edges and points
clearSelectPoints();
edit->SelCurvSet.clear();
edit->SelCrossSet.clear();
edit->SelConstraintSet.clear();
this->drawConstraintIcons();
this->updateColor();
@ -1048,21 +1069,26 @@ void ViewProviderSketch::onSelectionChanged(const Gui::SelectionChanges& msg)
edit->SelCurvSet.insert(index);
this->updateColor();
}
else if (shapetype.size() > 12 && shapetype.substr(0,12) == "ExternalEdge") {
int index=std::atoi(&shapetype[12]);
edit->SelCurvSet.insert(-index-3);
this->updateColor();
}
else if (shapetype.size() > 6 && shapetype.substr(0,6) == "Vertex") {
int index=std::atoi(&shapetype[6]);
addSelectPoint(index);
this->updateColor();
}
else if (shapetype == "RootPoint") {
edit->SelCrossSet.insert(0);
this->updateColor();
}
else if (shapetype == "V_Axis") {
edit->SelCrossSet.insert(2);
addSelectPoint(-1);
this->updateColor();
}
else if (shapetype == "H_Axis") {
edit->SelCrossSet.insert(1);
edit->SelCurvSet.insert(-1);
this->updateColor();
}
else if (shapetype == "V_Axis") {
edit->SelCurvSet.insert(-2);
this->updateColor();
}
else if (shapetype.size() > 10 && shapetype.substr(0,10) == "Constraint") {
@ -1087,11 +1113,28 @@ void ViewProviderSketch::onSelectionChanged(const Gui::SelectionChanges& msg)
edit->SelCurvSet.erase(index);
this->updateColor();
}
else if (shapetype.size() > 12 && shapetype.substr(0,12) == "ExternalEdge") {
int index=std::atoi(&shapetype[12]);
edit->SelCurvSet.erase(-index-3);
this->updateColor();
}
else if (shapetype.size() > 6 && shapetype.substr(0,6) == "Vertex") {
int index=std::atoi(&shapetype[6]);
removeSelectPoint(index);
this->updateColor();
}
else if (shapetype == "RootPoint") {
removeSelectPoint(-1);
this->updateColor();
}
else if (shapetype == "H_Axis") {
edit->SelCurvSet.erase(-1);
this->updateColor();
}
else if (shapetype == "V_Axis") {
edit->SelCurvSet.erase(-2);
this->updateColor();
}
else if (shapetype.size() > 10 && shapetype.substr(0,10) == "Constraint") {
int index=std::atoi(&shapetype[10]);
edit->SelConstraintSet.erase(index);
@ -1128,8 +1171,8 @@ bool ViewProviderSketch::detectPreselection(const SoPickedPoint *Point, int &PtI
PtIndex = -1;
CurvIndex = -1;
ConstrIndex = -1;
CrossIndex = -1;
ConstrIndex = -1;
if (Point) {
//Base::Console().Log("Point pick\n");
@ -1146,26 +1189,20 @@ bool ViewProviderSketch::detectPreselection(const SoPickedPoint *Point, int &PtI
PtIndex = static_cast<const SoPointDetail *>(point_detail)->getCoordinateIndex();
}
} else {
// checking for a hit in the Curves
// checking for a hit in the curves
if (tail == edit->CurveSet) {
const SoDetail *curve_detail = Point->getDetail(edit->CurveSet);
if (curve_detail && curve_detail->getTypeId() == SoLineDetail::getClassTypeId()) {
// get the index
CurvIndex = static_cast<const SoLineDetail *>(curve_detail)->getLineIndex();
}
// checking for a hit in the Cross
} else if (tail == edit->RootCrossSetV) {
//const SoDetail *cross_detail = Point->getDetail(edit->RootCrossSet);
//if (cross_detail && cross_detail->getTypeId() == SoLineDetail::getClassTypeId()) {
// get the index
CrossIndex = 1;
//}
} else if (tail == edit->RootCrossSetH) {
//const SoDetail *cross_detail = Point->getDetail(edit->RootCrossSet);
//if (cross_detail && cross_detail->getTypeId() == SoLineDetail::getClassTypeId()) {
// get the index
CrossIndex = 2;
//}
// checking for a hit in the cross
} else if (tail == edit->RootCrossSet) {
const SoDetail *cross_detail = Point->getDetail(edit->RootCrossSet);
if (cross_detail && cross_detail->getTypeId() == SoLineDetail::getClassTypeId()) {
// get the index (reserve index 0 for root point)
CrossIndex = 1 + static_cast<const SoLineDetail *>(cross_detail)->getLineIndex();
}
} else {
// checking if a constraint is hit
if (tailFather2 == edit->constrGroup)
@ -1199,8 +1236,14 @@ bool ViewProviderSketch::detectPreselection(const SoPickedPoint *Point, int &PtI
return true;
}
} else if (CurvIndex >= 0 && CurvIndex != edit->PreselectCurve) { // if a new curve is hit
int maxGeoId = getSketchObject()->getHighestCurveIndex();
std::stringstream ss;
ss << "Edge" << CurvIndex;
if (CurvIndex <= maxGeoId)
ss << "Edge" << CurvIndex;
else { // external geometry
int extGeoCount = getSketchObject()->getExternalGeometryCount();
ss << "ExternalEdge" << extGeoCount - 2 - (CurvIndex - maxGeoId);
}
bool accepted =
Gui::Selection().setPreselect(getSketchObject()->getDocument()->getName()
,getSketchObject()->getNameInDocument()
@ -1218,7 +1261,7 @@ bool ViewProviderSketch::detectPreselection(const SoPickedPoint *Point, int &PtI
edit->sketchHandler->applyCursor();
return true;
}
} else if (CrossIndex >= 0 && CrossIndex != edit->PreselectCross) {
} else if (CrossIndex >= 0 && CrossIndex != edit->PreselectCross) { // if a cross line is hit
std::stringstream ss;
switch(CrossIndex){
case 0: ss << "RootPoint" ; break;
@ -1302,8 +1345,7 @@ void ViewProviderSketch::updateColor(void)
SbColor *pcolor = edit->PointsMaterials->diffuseColor.startEditing();
int CurvNum = edit->CurvesMaterials->diffuseColor.getNum();
SbColor *color = edit->CurvesMaterials->diffuseColor.startEditing();
SbColor *ccolorV = edit->RootCrossMaterialsV->diffuseColor.startEditing();
SbColor *ccolorH = edit->RootCrossMaterialsH->diffuseColor.startEditing();
SbColor *crosscolor = edit->RootCrossMaterials->diffuseColor.startEditing();
// colors of the point set
for (int i=0; i < PtNum; i++) {
@ -1318,12 +1360,17 @@ void ViewProviderSketch::updateColor(void)
}
// colors of the curves
int intGeoCount = getSketchObject()->getHighestCurveIndex() + 1;
int extGeoCount = getSketchObject()->getExternalGeometryCount();
for (int i=0; i < CurvNum; i++) {
if (edit->SelCurvSet.find(i) != edit->SelCurvSet.end())
int GeoId = (i < intGeoCount) ? i : -(extGeoCount - (i - intGeoCount));
if (edit->SelCurvSet.find(GeoId) != edit->SelCurvSet.end())
color[i] = SelectColor;
else if (edit->PreselectCurve == i)
color[i] = PreselectColor;
else if (this->getSketchObject()->Geometry.getValues()[i]->Construction)
else if (GeoId < -2) // external Geometry
color[i] = CurveExternalColor;
else if (getSketchObject()->getGeometry(GeoId)->Construction)
color[i] = CurveDraftColor;
else if (edit->FullyConstrained)
color[i] = FullyConstrainedColor;
@ -1332,20 +1379,19 @@ void ViewProviderSketch::updateColor(void)
}
// colors of the cross
if (edit->SelCrossSet.find(1) != edit->SelCrossSet.end())
ccolorV[0] = SelectColor;
if (edit->SelCurvSet.find(-1) != edit->SelCurvSet.end())
crosscolor[0] = SelectColor;
else if (edit->PreselectCross == 1)
ccolorV[0] = PreselectColor;
crosscolor[0] = PreselectColor;
else
ccolorV[0] = CrossColorV;
crosscolor[0] = CrossColorH;
if (edit->SelCrossSet.find(2) != edit->SelCrossSet.end())
ccolorH[0] = SelectColor;
if (edit->SelCurvSet.find(-2) != edit->SelCurvSet.end())
crosscolor[1] = SelectColor;
else if (edit->PreselectCross == 2)
ccolorH[0] = PreselectColor;
crosscolor[1] = PreselectColor;
else
ccolorH[0] = CrossColorH;
crosscolor[1] = CrossColorV;
// colors of the constraints
for (int i=0; i < edit->constrGroup->getNumChildren(); i++) {
@ -1353,7 +1399,7 @@ void ViewProviderSketch::updateColor(void)
SoMaterial *m = dynamic_cast<SoMaterial *>(s->getChild(0));
// Check Constraint Type
ConstraintType type = this->getSketchObject()->Constraints.getValues()[i]->Type;
ConstraintType type = getSketchObject()->Constraints.getValues()[i]->Type;
bool hasDatumLabel = (type == Sketcher::Angle ||
type == Sketcher::Radius ||
type == Sketcher::Distance || type == Sketcher::DistanceX || type == Sketcher::DistanceY);
@ -1383,8 +1429,7 @@ void ViewProviderSketch::updateColor(void)
// end editing
edit->CurvesMaterials->diffuseColor.finishEditing();
edit->PointsMaterials->diffuseColor.finishEditing();
edit->RootCrossMaterialsV->diffuseColor.finishEditing();
edit->RootCrossMaterialsH->diffuseColor.finishEditing();
edit->RootCrossMaterials->diffuseColor.finishEditing();
}
bool ViewProviderSketch::isPointOnSketch(const SoPickedPoint *pp) const
@ -1422,8 +1467,8 @@ void ViewProviderSketch::drawConstraintIcons()
case Tangent:
icoType = QString::fromAscii("small/Constraint_Tangent_sm");
{ // second icon is available only for colinear line segments
Part::Geometry *geo1 = getSketchObject()->Geometry.getValues()[(*it)->First];
Part::Geometry *geo2 = getSketchObject()->Geometry.getValues()[(*it)->Second];
const Part::Geometry *geo1 = getSketchObject()->getGeometry((*it)->First);
const Part::Geometry *geo2 = getSketchObject()->getGeometry((*it)->Second);
if (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
geo2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
index2 = 4;
@ -1546,15 +1591,22 @@ void ViewProviderSketch::draw(bool temp)
std::vector<Base::Vector3d> Points;
std::vector<unsigned int> Index;
int intGeoCount = getSketchObject()->getHighestCurveIndex() + 1;
int extGeoCount = getSketchObject()->getExternalGeometryCount();
const std::vector<Part::Geometry *> *geomlist;
std::vector<Part::Geometry *> tempGeo;
if (temp) {
tempGeo = edit->ActSketch.getGeometry();
geomlist = &tempGeo;
} else
geomlist = &getSketchObject()->Geometry.getValues();
if (temp)
tempGeo = edit->ActSketch.extractGeometry(true, true); // with memory allocation
else
tempGeo = getSketchObject()->getCompleteGeometry(); // without memory allocation
geomlist = &tempGeo;
for (std::vector<Part::Geometry *>::const_iterator it = geomlist->begin(); it != geomlist->end(); ++it) {
assert(int(geomlist->size()) == extGeoCount + intGeoCount);
assert(int(geomlist->size()) >= 2);
for (std::vector<Part::Geometry *>::const_iterator it = geomlist->begin(); it != geomlist->end()-2; ++it) {
if ((*it)->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { // add a line
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(*it);
// create the definition struct for that geom
@ -1659,9 +1711,25 @@ void ViewProviderSketch::draw(bool temp)
int32_t *index = edit->CurveSet->numVertices.startEditing();
SbVec3f *pverts = edit->PointsCoordinate->point.startEditing();
int i=0; // setting up the line set
for (std::vector<Base::Vector3d>::const_iterator it = Coords.begin(); it != Coords.end(); ++it,i++)
verts[i].setValue(it->x,it->y,zLines);
i=0; // setting up the indexes of the line set
for (std::vector<unsigned int>::const_iterator it = Index.begin(); it != Index.end(); ++it,i++)
index[i] = *it;
i=0; // setting up the point set
for (std::vector<Base::Vector3d>::const_iterator it = Points.begin(); it != Points.end(); ++it,i++)
pverts[i].setValue(it->x,it->y,zPoints);
edit->CurvesCoordinate->point.finishEditing();
edit->CurveSet->numVertices.finishEditing();
edit->PointsCoordinate->point.finishEditing();
// set cross coordinates
edit->RootCrossSetV->numVertices.set1Value(0,2);
edit->RootCrossSetH->numVertices.set1Value(0,2);
edit->RootCrossSet->numVertices.set1Value(0,2);
edit->RootCrossSet->numVertices.set1Value(1,2);
float MiX = -exp(ceil(log(std::abs(MinX))));
MiX = std::min(MiX,(float)-exp(ceil(log(std::abs(0.1f*MaxX)))));
@ -1672,47 +1740,29 @@ void ViewProviderSketch::draw(bool temp)
float MaY = exp(ceil(log(std::abs(MaxY))));
MaY = std::max(MaY,(float)exp(ceil(log(std::abs(0.1f*MinY)))));
edit->RootCrossCoordinateV->point.set1Value(0,SbVec3f(MiX, 0.0f, zCross));
edit->RootCrossCoordinateV->point.set1Value(1,SbVec3f(MaX, 0.0f, zCross));
edit->RootCrossCoordinateH->point.set1Value(0,SbVec3f(0.0f, MiY, zCross));
edit->RootCrossCoordinateH->point.set1Value(1,SbVec3f(0.0f, MaY, zCross));
int i=0; // setting up the line set
for (std::vector<Base::Vector3d>::const_iterator it = Coords.begin(); it != Coords.end(); ++it,i++)
verts[i].setValue(it->x,it->y,zLines);
i=0; // setting up the indexes of the line set
for (std::vector<unsigned int>::const_iterator it = Index.begin(); it != Index.end(); ++it,i++)
index[i] = *it;
i=0; // setting up the point set
for (std::vector<Base::Vector3d>::const_iterator it = Points.begin(); it != Points.end(); ++it,i++)
pverts[i].setValue(it->x,it->y,zPoints);
edit->CurvesCoordinate->point.finishEditing();
edit->CurveSet->numVertices.finishEditing();
edit->PointsCoordinate->point.finishEditing();
edit->RootCrossCoordinate->point.set1Value(0,SbVec3f(MiX, 0.0f, zCross));
edit->RootCrossCoordinate->point.set1Value(1,SbVec3f(MaX, 0.0f, zCross));
edit->RootCrossCoordinate->point.set1Value(2,SbVec3f(0.0f, MiY, zCross));
edit->RootCrossCoordinate->point.set1Value(3,SbVec3f(0.0f, MaY, zCross));
// Render Constraints ===================================================
const std::vector<Sketcher::Constraint *> &ConStr = getSketchObject()->Constraints.getValues();
const std::vector<Sketcher::Constraint *> &constrlist = getSketchObject()->Constraints.getValues();
// After an undo/redo it can happen that we have an empty geometry list but a non-empty constraint list
// In this case just ignore the constraints. (See bug #0000421)
if (geomlist->empty() && !ConStr.empty()) {
if (geomlist->size() <= 2 && !constrlist.empty()) {
rebuildConstraintsVisual();
return;
}
// reset point if the constraint type has changed
Restart:
// check if a new constraint arrived
if (ConStr.size() != edit->vConstrType.size())
if (constrlist.size() != edit->vConstrType.size())
rebuildConstraintsVisual();
assert(int(ConStr.size()) == edit->constrGroup->getNumChildren());
assert(int(constrlist.size()) == edit->constrGroup->getNumChildren());
assert(int(edit->vConstrType.size()) == edit->constrGroup->getNumChildren());
// go through the constraints and update the position
i = 0;
for (std::vector<Sketcher::Constraint *>::const_iterator it = ConStr.begin(); it != ConStr.end(); ++it,i++) {
for (std::vector<Sketcher::Constraint *>::const_iterator it=constrlist.begin(); it != constrlist.end(); ++it,i++) {
// check if the type has changed
if ((*it)->Type != edit->vConstrType[i]) {
// clearing the type vector will force a rebuild of the visual nodes
@ -1728,9 +1778,9 @@ Restart:
case Horizontal: // write the new position of the Horizontal constraint Same as vertical position.
case Vertical: // write the new position of the Vertical constraint
{
assert(Constr->First < int(geomlist->size()));
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
// get the geometry
const Part::Geometry *geo = (*geomlist)[Constr->First];
const Part::Geometry *geo = GeoById(*geomlist, Constr->First);
// Vertical can only be a GeomLineSegment
assert(geo->getTypeId() == Part::GeomLineSegment::getClassTypeId());
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(geo);
@ -1762,11 +1812,11 @@ Restart:
case Perpendicular:
case Equal:
{
assert(Constr->First < int(geomlist->size()));
assert(Constr->Second < int(geomlist->size()));
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
assert(Constr->Second >= -extGeoCount && Constr->Second < intGeoCount);
// get the geometry
const Part::Geometry *geo1 = (*geomlist)[Constr->First];
const Part::Geometry *geo2 = (*geomlist)[Constr->Second];
const Part::Geometry *geo1 = GeoById(*geomlist, Constr->First);
const Part::Geometry *geo2 = GeoById(*geomlist, Constr->Second);
Base::Vector3d midpos1, dir1, norm1;
Base::Vector3d midpos2, dir2, norm2;
@ -1860,7 +1910,7 @@ Restart:
case DistanceX:
case DistanceY:
{
assert(Constr->First < int(geomlist->size()));
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
Base::Vector3d pnt1(0.,0.,0.), pnt2(0.,0.,0.);
if (Constr->SecondPos != Sketcher::none) { // point to point distance
@ -1877,7 +1927,7 @@ Restart:
} else {
pnt1 = getSketchObject()->getPoint(Constr->First, Constr->FirstPos);
}
const Part::Geometry *geo = (*geomlist)[Constr->Second];
const Part::Geometry *geo = GeoById(*geomlist, Constr->Second);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(geo);
Base::Vector3d l2p1 = lineSeg->getStartPoint();
@ -1894,7 +1944,7 @@ Restart:
pnt2 = getSketchObject()->getPoint(Constr->First, Constr->FirstPos);
}
} else if (Constr->First != Constraint::GeoUndef) {
const Part::Geometry *geo = (*geomlist)[Constr->First];
const Part::Geometry *geo = GeoById(*geomlist, Constr->First);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(geo);
pnt1 = lineSeg->getStartPoint();
@ -2000,8 +2050,8 @@ Restart:
case PointOnObject:
case Tangent:
{
assert(Constr->First < int(geomlist->size()));
assert(Constr->Second < int(geomlist->size()));
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
assert(Constr->Second >= -extGeoCount && Constr->Second < intGeoCount);
Base::Vector3d pos, relPos;
if (Constr->Type == PointOnObject) {
@ -2012,8 +2062,8 @@ Restart:
}
else if (Constr->Type == Tangent) {
// get the geometry
const Part::Geometry *geo1 = (*geomlist)[Constr->First];
const Part::Geometry *geo2 = (*geomlist)[Constr->Second];
const Part::Geometry *geo1 = GeoById(*geomlist, Constr->First);
const Part::Geometry *geo2 = GeoById(*geomlist, Constr->Second);
if (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
geo2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
@ -2113,8 +2163,8 @@ Restart:
break;
case Symmetric:
{
assert(Constr->First < int(geomlist->size()));
assert(Constr->Second < int(geomlist->size()));
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
assert(Constr->Second >= -extGeoCount && Constr->Second < intGeoCount);
Base::Vector3d pnt1 = edit->ActSketch.getPoint(Constr->First, Constr->FirstPos);
Base::Vector3d pnt2 = edit->ActSketch.getPoint(Constr->Second, Constr->SecondPos);
@ -2157,14 +2207,14 @@ Restart:
break;
case Angle:
{
assert(Constr->First < int(geomlist->size()));
assert(Constr->Second < int(geomlist->size()));
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
assert(Constr->Second >= -extGeoCount && Constr->Second < intGeoCount);
SbVec3f p0;
double startangle,range,endangle;
if (Constr->Second != Constraint::GeoUndef) {
const Part::Geometry *geo1 = (*geomlist)[Constr->First];
const Part::Geometry *geo2 = (*geomlist)[Constr->Second];
const Part::Geometry *geo1 = GeoById(*geomlist, Constr->First);
const Part::Geometry *geo2 = GeoById(*geomlist, Constr->Second);
if (geo1->getTypeId() != Part::GeomLineSegment::getClassTypeId() ||
geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId())
break;
@ -2196,7 +2246,7 @@ Restart:
endangle = startangle + range;
} else if (Constr->First != Constraint::GeoUndef) {
const Part::Geometry *geo = (*geomlist)[Constr->First];
const Part::Geometry *geo = GeoById(*geomlist, Constr->First);
if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId())
break;
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(geo);
@ -2276,11 +2326,11 @@ Restart:
break;
case Radius:
{
assert(Constr->First < int(geomlist->size()));
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
Base::Vector3d pnt1(0.,0.,0.), pnt2(0.,0.,0.);
if (Constr->First != Constraint::GeoUndef) {
const Part::Geometry *geo = (*geomlist)[Constr->First];
const Part::Geometry *geo = GeoById(*geomlist, Constr->First);
if (geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *arc = dynamic_cast<const Part::GeomArcOfCircle *>(geo);
@ -2379,8 +2429,9 @@ Restart:
this->updateColor();
// delete the cloned objects
for (std::vector<Part::Geometry *>::iterator it = tempGeo.begin(); it != tempGeo.end(); ++it)
if (*it) delete *it;
if (temp)
for (std::vector<Part::Geometry *>::iterator it=tempGeo.begin(); it != tempGeo.end(); ++it)
if (*it) delete *it;
if (mdi && mdi->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
static_cast<Gui::View3DInventor *>(mdi)->getViewer()->render();
@ -2389,12 +2440,12 @@ Restart:
void ViewProviderSketch::rebuildConstraintsVisual(void)
{
const std::vector<Sketcher::Constraint *> &ConStr = getSketchObject()->Constraints.getValues();
const std::vector<Sketcher::Constraint *> &constrlist = getSketchObject()->Constraints.getValues();
// clean up
edit->constrGroup->removeAllChildren();
edit->vConstrType.clear();
for (std::vector<Sketcher::Constraint *>::const_iterator it = ConStr.begin(); it != ConStr.end(); ++it) {
for (std::vector<Sketcher::Constraint *>::const_iterator it=constrlist.begin(); it != constrlist.end(); ++it) {
// root separator for one constraint
SoSeparator *sep = new SoSeparator();
// no caching for fluctuand data structures
@ -2473,8 +2524,8 @@ void ViewProviderSketch::rebuildConstraintsVisual(void)
sep->addChild(new SoImage()); // 2. constraint icon
if ((*it)->Type == Tangent) {
Part::Geometry *geo1 = getSketchObject()->Geometry.getValues()[(*it)->First];
Part::Geometry *geo2 = getSketchObject()->Geometry.getValues()[(*it)->Second];
const Part::Geometry *geo1 = getSketchObject()->getGeometry((*it)->First);
const Part::Geometry *geo2 = getSketchObject()->getGeometry((*it)->Second);
if (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId() &&
geo2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
sep->addChild(new SoZoomTranslation());
@ -2532,8 +2583,9 @@ void ViewProviderSketch::updateData(const App::Property *prop)
if (edit && (prop == &(getSketchObject()->Geometry) || &(getSketchObject()->Constraints))) {
edit->FullyConstrained = false;
int dofs = edit->ActSketch.setUpSketch(getSketchObject()->Geometry.getValues(),
getSketchObject()->Constraints.getValues());
int dofs = edit->ActSketch.setUpSketch(getSketchObject()->getCompleteGeometry(),
getSketchObject()->Constraints.getValues(),
true, getSketchObject()->getExternalGeometryCount());
std::string msg;
if (getSketchObject()->Geometry.getSize() == 0) {
signalSetUp(-1, 0, msg);
@ -2648,9 +2700,10 @@ bool ViewProviderSketch::setEdit(int ModNum)
color = (unsigned long)(FullyConstrainedColor.getPackedValue());
color = hGrp->GetUnsigned("FullyConstrainedColor", color);
FullyConstrainedColor.setPackedValue((uint32_t)color, transparency);
// constraints dimensions and icons colors are hard coded
// constraints dimensions, icons and external geometry colors are hard coded
// ConstrDimColor;
// ConstrIcoColor;
// CurveExternalColor;
// set the highlight color
unsigned long highlight = (unsigned long)(PreselectColor.getPackedValue());
@ -2668,8 +2721,9 @@ bool ViewProviderSketch::setEdit(int ModNum)
Gui::Control().showDialog(new TaskDlgEditSketch(this));
// set up the sketch and diagnose possible conflicts
int dofs = edit->ActSketch.setUpSketch(getSketchObject()->Geometry.getValues(),
getSketchObject()->Constraints.getValues());
int dofs = edit->ActSketch.setUpSketch(getSketchObject()->getCompleteGeometry(),
getSketchObject()->Constraints.getValues(),
true, getSketchObject()->getExternalGeometryCount());
std::string msg;
if (getSketchObject()->Geometry.getSize() == 0) {
signalSetUp(-1, 0, msg);
@ -2763,28 +2817,18 @@ void ViewProviderSketch::createEditInventorNodes(void)
DrawStyle->lineWidth = 2;
edit->EditRoot->addChild(DrawStyle);
edit->RootCrossMaterialsV = new SoMaterial;
edit->RootCrossMaterialsV->diffuseColor.set1Value(0,CrossColorV);
edit->EditRoot->addChild(edit->RootCrossMaterialsV);
edit->RootCrossMaterials = new SoMaterial;
edit->RootCrossMaterials->diffuseColor.set1Value(0,CrossColorH);
edit->RootCrossMaterials->diffuseColor.set1Value(1,CrossColorV);
edit->EditRoot->addChild(edit->RootCrossMaterials);
edit->RootCrossCoordinateV = new SoCoordinate3;
edit->EditRoot->addChild(edit->RootCrossCoordinateV);
edit->RootCrossSetV = new SoLineSet;
edit->RootCrossSetV->numVertices.set1Value(0,2);
edit->EditRoot->addChild(edit->RootCrossSetV);
edit->RootCrossMaterialsH = new SoMaterial;
edit->RootCrossMaterialsH->diffuseColor.set1Value(0,CrossColorH);
edit->EditRoot->addChild(edit->RootCrossMaterialsH);
edit->RootCrossCoordinateH = new SoCoordinate3;
edit->EditRoot->addChild(edit->RootCrossCoordinateH);
edit->RootCrossSetH = new SoLineSet;
edit->RootCrossSetH->numVertices.set1Value(0,2);
edit->EditRoot->addChild(edit->RootCrossSetH);
edit->RootCrossCoordinate = new SoCoordinate3;
edit->EditRoot->addChild(edit->RootCrossCoordinate);
edit->RootCrossSet = new SoLineSet;
edit->RootCrossSet->numVertices.set1Value(0,2);
edit->RootCrossSet->numVertices.set1Value(1,2);
edit->EditRoot->addChild(edit->RootCrossSet);
// stuff for the EditCurves +++++++++++++++++++++++++++++++++++++++
edit->EditCurvesMaterials = new SoMaterial;
@ -3025,10 +3069,15 @@ bool ViewProviderSketch::onDelete(const std::vector<std::string> &subList)
Base::Console().Error("%s\n", e.what());
}
}
for (rit = edit->SelCurvSet.rbegin(); rit != edit->SelCurvSet.rend(); rit++) {
try {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.delGeometry(%i)"
,getObject()->getNameInDocument(), *rit);
if (*rit >= 0)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.delGeometry(%i)"
,getObject()->getNameInDocument(), *rit);
else if (*rit < -2) // external geometry
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.delExternal(%i)"
,getObject()->getNameInDocument(), -3-*rit);
}
catch (const Base::Exception& e) {
Base::Console().Error("%s\n", e.what());

View File

@ -215,6 +215,7 @@ protected:
static SbColor VertexColor;
static SbColor CurveColor;
static SbColor CurveDraftColor;
static SbColor CurveExternalColor;
static SbColor CrossColorV;
static SbColor CrossColorH;
static SbColor FullyConstrainedColor;