diff --git a/src/App/PropertyLinks.cpp b/src/App/PropertyLinks.cpp index 32c6c1301..6cc105808 100644 --- a/src/App/PropertyLinks.cpp +++ b/src/App/PropertyLinks.cpp @@ -605,9 +605,9 @@ void PropertyLinkSubList::Save (Base::Writer &writer) const writer.Stream() << writer.ind() << "" << endl; writer.incInd(); for(int i = 0;igetNameInDocument() << + "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(_lValueList.size() * sizeof(App::DocumentObject *)); for(int i = 0;i 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 diff --git a/src/Mod/Draft/DraftGui.py b/src/Mod/Draft/DraftGui.py index fc4e6f194..114d0078e 100644 --- a/src/Mod/Draft/DraftGui.py +++ b/src/Mod/Draft/DraftGui.py @@ -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 diff --git a/src/Mod/Draft/DraftSnap.py b/src/Mod/Draft/DraftSnap.py index cbcdb6842..f2f0b3d25 100644 --- a/src/Mod/Draft/DraftSnap.py +++ b/src/Mod/Draft/DraftSnap.py @@ -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() diff --git a/src/Mod/Draft/DraftTools.py b/src/Mod/Draft/DraftTools.py index ac1610bf4..e9b55d6e1 100755 --- a/src/Mod/Draft/DraftTools.py +++ b/src/Mod/Draft/DraftTools.py @@ -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 = [] diff --git a/src/Mod/Draft/DraftTrackers.py b/src/Mod/Draft/DraftTrackers.py index da064ffd9..29494d6fb 100644 --- a/src/Mod/Draft/DraftTrackers.py +++ b/src/Mod/Draft/DraftTrackers.py @@ -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]) diff --git a/src/Mod/Part/App/Part2DObject.cpp b/src/Mod/Part/App/Part2DObject.cpp index 373d60e89..eb44dc0a3 100644 --- a/src/Mod/Part/App/Part2DObject.cpp +++ b/src/Mod/Part/App/Part2DObject.cpp @@ -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) diff --git a/src/Mod/Part/App/TopoShapeSolidPy.xml b/src/Mod/Part/App/TopoShapeSolidPy.xml index 0e3a3705d..c8e4048cf 100644 --- a/src/Mod/Part/App/TopoShapeSolidPy.xml +++ b/src/Mod/Part/App/TopoShapeSolidPy.xml @@ -14,6 +14,12 @@ Create a solid out of the shells of a shape + + + Returns the mass of the current system. + + + Returns the center of mass of the current system. @@ -44,6 +50,28 @@ coordinate system. + + + 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. + + + + + + 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. + + + @@ -52,5 +80,15 @@ shape if the solid has no shells + + + computes the moment of inertia of the material system about the axis A. + + + + + Returns the radius of gyration of the current system about the axis A. + + diff --git a/src/Mod/Part/App/TopoShapeSolidPyImp.cpp b/src/Mod/Part/App/TopoShapeSolidPyImp.cpp index 291dba419..ca1a952c3 100644 --- a/src/Mod/Part/App/TopoShapeSolidPyImp.cpp +++ b/src/Mod/Part/App/TopoShapeSolidPyImp.cpp @@ -26,11 +26,16 @@ #include #include #include +#include #include #include #include #include #include +#include +#include +#include +#include #include #include @@ -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 + (pprops.FirstAxisOfInertia()))); + dict.setItem("SecondAxisOfInertia",Py::Vector(Base::convertTo + (pprops.SecondAxisOfInertia()))); + dict.setItem("ThirdAxisOfInertia",Py::Vector(Base::convertTo + (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(pnt), + Base::convertTo(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(pnt), + Base::convertTo(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; diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index 8ca398bfd..4f99c7844 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -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 &GeoList, const std::vector &ConstraintList, - bool withDiagnose) -{ - return setUpSketch(GeoList, std::vector(0), ConstraintList); -} - -int Sketch::setUpSketch(const std::vector &GeoList, const std::vector &FixedGeoList, - const std::vector &ConstraintList, bool withDiagnose) + bool withDiagnose, int extGeoCount) { clear(); - addGeometry(GeoList); - addGeometry(FixedGeoList, true); + std::vector 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(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(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(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 &geo, bool fixed) { - for (std::vector::const_iterator it = geo.begin();it!=geo.end();++it) + for (std::vector::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 Sketch::getGeometry(bool withConstrucionElements) const +std::vector Sketch::extractGeometry(bool withConstrucionElements, + bool withExternalElements) const { - std::vector temp(Geoms.size()); - int i=0; - std::vector::const_iterator it=Geoms.begin(); - - for (;it!=Geoms.end();++it,i++) - if (!it->construction || withConstrucionElements) - temp[i] = it->geo->clone(); + std::vector temp; + temp.reserve(Geoms.size()); + for (std::vector::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::const_iterator it=Geoms.begin(); - - for (;it!=Geoms.end();++it,i++) { + for (std::vector::const_iterator it=Geoms.begin(); it != Geoms.end(); ++it, i++) { if (it->type == Line) { GeomLineSegment *lineSeg = dynamic_cast(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 &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::const_iterator it=Geoms.begin();it!=Geoms.end();++it,i++) { + for (std::vector::const_iterator it=Geoms.begin(); it != Geoms.end(); ++it, i++) { try { if (it->type == Line) { GeomLineSegment *lineSeg = dynamic_cast(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 edge_list; std::list 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())); } } diff --git a/src/Mod/Sketcher/App/Sketch.h b/src/Mod/Sketcher/App/Sketch.h index 0ba9bc03c..8746ff226 100644 --- a/src/Mod/Sketcher/App/Sketch.h +++ b/src/Mod/Sketcher/App/Sketch.h @@ -55,9 +55,7 @@ public: void clear(void); /// set the sketch up with geoms and constraints int setUpSketch(const std::vector &GeoList, const std::vector &ConstraintList, - bool withDiagnose=true); - int setUpSketch(const std::vector &GeoList, const std::vector &FixedGeoList, - const std::vector &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 &geo, bool fixed=false); /// returns the actual geometry - std::vector getGeometry(bool withConstrucionElements = true) const; + std::vector 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 diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index c0c9fc65d..904b8b063 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -26,12 +26,18 @@ # include # include # include +# include +# include # include +# include +# include +# include #endif #include #include #include +#include #include @@ -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::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::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 geomlist = sketch.getGeometry(); + std::vector geomlist = sketch.extractGeometry(); Geometry.setValues(geomlist); - for (std::vector::iterator it = geomlist.begin(); it != geomlist.end(); ++it) + for (std::vector::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 geomlist = sketch.getGeometry(); + std::vector geomlist = sketch.extractGeometry(); Geometry.setValues(geomlist); for (std::vector::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 geomlist = sketch.getGeometry(); + std::vector geomlist = sketch.extractGeometry(); Geometry.setValues(geomlist); - for (std::vector::iterator it = geomlist.begin(); it != geomlist.end(); ++it) { + //Constraints.acceptGeometry(getCompleteGeometry()); + for (std::vector::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(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::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 &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::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 &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 GeoIdList; std::vector 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(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 &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(geo1); @@ -594,10 +627,11 @@ int SketchObject::fillet(int GeoId1, int GeoId2, int SketchObject::trim(int GeoId, const Base::Vector3d& point) { - const std::vector &geomlist = this->Geometry.getValues(); - const std::vector &constraints = this->Constraints.getValues(); + if (GeoId < 0 || GeoId > getHighestCurveIndex()) + return -1; - assert(GeoId < int(geomlist.size())); + const std::vector &geomlist = getInternalGeometry(); + const std::vector &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 Objects = ExternalConstraints.getValues(); - std::vector SubElements = ExternalConstraints.getSubValues(); + std::vector Objects = ExternalGeometry.getValues(); + std::vector SubElements = ExternalGeometry.getSubValues(); + + std::vector originalObjects = Objects; + std::vector 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 getExternalGeometry(void) + +const Part::Geometry* SketchObject::getGeometry(int GeoId) const { - std::vector ExtGeos; + if (GeoId >= 0) { + const std::vector &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 Objects = ExternalGeometry.getValues(); + std::vector 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::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(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 SketchObject::getCompleteGeometry(void) const +{ + std::vector 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); } diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h index 2e91d49b9..e3ae6b800 100644 --- a/src/Mod/Sketcher/App/SketchObject.h +++ b/src/Mod/Sketcher/App/SketchObject.h @@ -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 &geoList); /// delete geometry - int delGeometry(int GeoNbr); + int delGeometry(int GeoId); /// add all constraints in the list int addConstraints(const std::vector &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 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 &getInternalGeometry(void) const { return Geometry.getValues(); } + /// returns a list of projected external geometries + const std::vector &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 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 ExternalGeo; + std::vector VertexId2GeoId; std::vector VertexId2PosId; }; diff --git a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp index a9de03d91..c57e6865c 100644 --- a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp +++ b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp @@ -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()); diff --git a/src/Mod/Sketcher/App/SketchPy.xml b/src/Mod/Sketcher/App/SketchPy.xml index 86caa3ac3..df2ae6539 100644 --- a/src/Mod/Sketcher/App/SketchPy.xml +++ b/src/Mod/Sketcher/App/SketchPy.xml @@ -1,13 +1,13 @@  - @@ -17,7 +17,7 @@ - solve the actuall set of geometry and constraints + solve the actual set of geometry and constraints diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index 7567c0b2a..b00676d5e 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -185,7 +185,6 @@ void CmdSketcherConstrainHorizontal::activated(int iMsg) const std::vector &SubNames = selection[0].getSubNames(); Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject()); const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues(); - const std::vector &geomlist = Obj->Geometry.getValues(); std::vector 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::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 &SubNames = selection[0].getSubNames(); Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject()); const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues(); - const std::vector &geomlist = Obj->Geometry.getValues(); std::vector ids; // go through the selected subelements - for(std::vector::const_iterator it=SubNames.begin();it!=SubNames.end();++it){ + for (std::vector::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 &SubNames = selection[0].getSubNames(); Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject()); - const std::vector &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(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(geom); @@ -670,7 +670,6 @@ void CmdSketcherConstrainPointOnObject::activated(int iMsg) // get the needed lists and objects const std::vector &SubNames = selection[0].getSubNames(); Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject()); - const std::vector &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 &SubNames = selection[0].getSubNames(); Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject()); - const std::vector &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(geom); @@ -896,7 +909,6 @@ void CmdSketcherConstrainDistanceY::activated(int iMsg) // get the needed lists and objects const std::vector &SubNames = selection[0].getSubNames(); Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject()); - const std::vector &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(geom); @@ -1031,9 +1054,6 @@ void CmdSketcherConstrainParallel::activated(int iMsg) // get the needed lists and objects const std::vector &SubNames = selection[0].getSubNames(); Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject()); - const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues(); - const std::vector &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::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 &SubNames = selection[0].getSubNames(); Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject()); - const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues(); - const std::vector &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 &SubNames = selection[0].getSubNames(); Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject()); - const std::vector &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(geom); double ActRadius = arc->getRadius(); @@ -1392,7 +1406,6 @@ void CmdSketcherConstrainAngle::activated(int iMsg) // get the needed lists and objects const std::vector &SubNames = selection[0].getSubNames(); Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject()); - const std::vector &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(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(geom); @@ -1538,8 +1551,6 @@ void CmdSketcherConstrainEqual::activated(int iMsg) // get the needed lists and objects const std::vector &SubNames = selection[0].getSubNames(); Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject()); - const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues(); - const std::vector &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::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 selection = getSelection().getSelectionEx(); Sketcher::SketchObject* Obj = dynamic_cast(selection[0].getObject()); - const std::vector &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"); diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index 800717aa5..48129f1cd 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -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(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(object); - const std::vector &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 GeoIdList; std::vector PosIdList; Sketch->getCoincidentPoints(index, GeoIdList, PosIdList); - if (GeoIdList.size() == 2) { - const std::vector &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 &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 GeoIdList; std::vector 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(geom1); const Part::GeomLineSegment *lineSeg2 = dynamic_cast(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 &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(geo[firstCurve]); - const Part::GeomLineSegment *lineSeg2 = dynamic_cast(geo[secondCurve]); + const Part::GeomLineSegment *lineSeg1 = dynamic_cast + (sketchgui->getSketchObject()->getGeometry(firstCurve)); + const Part::GeomLineSegment *lineSeg2 = dynamic_cast + (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(object); - const std::vector &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 &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() diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp index c8a3dee02..947299062 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp +++ b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp @@ -82,19 +82,14 @@ void DrawSketchHandler::quit(void) //************************************************************************** // Helpers -Sketcher::SketchObject* DrawSketchHandler::getObject(void) -{ - return dynamic_cast(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 &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 geomlist = getObject()->Geometry.getValues(); + const std::vector geomlist = sketchgui->getSketchObject()->getCompleteGeometry(); // Iterate through geometry int i = 0; - for (std::vector::const_iterator it = geomlist.begin(); it != geomlist.end(); ++it, i++) { + for (std::vector::const_iterator it=geomlist.begin(); it != geomlist.end(); ++it, i++) { if ((*it)->getTypeId() == Part::GeomCircle::getClassTypeId()) { const Part::GeomCircle *circle = dynamic_cast((*it)); @@ -221,11 +216,9 @@ int DrawSketchHandler::seekAutoConstraint(std::vector &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 &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 &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 &suggested } void DrawSketchHandler::createAutoConstraints(const std::vector &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 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; } diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandler.h b/src/Mod/Sketcher/Gui/DrawSketchHandler.h index db8eede6f..5d58889d0 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandler.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandler.h @@ -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; diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 2dc1bfe1c..468a49a27 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -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 SelPointSet; - std::set SelCurvSet; + std::set SelCurvSet; // also holds cross axes at -1 and -2 std::set SelConstraintSet; - std::set SelCrossSet; // helper data structure for the constraint rendering std::vector 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 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 *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 &ConStr = getSketchObject()->Constraints.getValues(); - Constraint *Constr = ConStr[edit->PreselectConstraint]; + const std::vector &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 &ConStr = getSketchObject()->Constraints.getValues(); - Constraint *Constr = ConStr[constNum]; + const std::vector &constrlist = getSketchObject()->Constraints.getValues(); + Constraint *Constr = constrlist[constNum]; if (Constr->Type == Distance || Constr->Type == DistanceX || Constr->Type == DistanceY || Constr->Type == Radius) { - const std::vector geomlist = edit->ActSketch.getGeometry(); - assert(Constr->First < int(geomlist.size())); + int intGeoCount = getSketchObject()->getHighestCurveIndex() + 1; + int extGeoCount = getSketchObject()->getExternalGeometryCount(); + const std::vector 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(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(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 geomlist = edit->ActSketch.getGeometry(); - assert(Constr->First < int(geomlist.size())); + int intGeoCount = getSketchObject()->getHighestCurveIndex() + 1; + int extGeoCount = getSketchObject()->getExternalGeometryCount(); + const std::vector 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(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(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(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(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(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 Points; std::vector Index; + int intGeoCount = getSketchObject()->getHighestCurveIndex() + 1; + int extGeoCount = getSketchObject()->getExternalGeometryCount(); + const std::vector *geomlist; std::vector 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::const_iterator it = geomlist->begin(); it != geomlist->end(); ++it) { + + assert(int(geomlist->size()) == extGeoCount + intGeoCount); + assert(int(geomlist->size()) >= 2); + + for (std::vector::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(*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::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::const_iterator it = Index.begin(); it != Index.end(); ++it,i++) + index[i] = *it; + + i=0; // setting up the point set + for (std::vector::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::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::const_iterator it = Index.begin(); it != Index.end(); ++it,i++) - index[i] = *it; - - - i=0; // setting up the point set - for (std::vector::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 &ConStr = getSketchObject()->Constraints.getValues(); + const std::vector &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::const_iterator it = ConStr.begin(); it != ConStr.end(); ++it,i++) { + for (std::vector::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(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(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(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(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(geo); @@ -2379,8 +2429,9 @@ Restart: this->updateColor(); // delete the cloned objects - for (std::vector::iterator it = tempGeo.begin(); it != tempGeo.end(); ++it) - if (*it) delete *it; + if (temp) + for (std::vector::iterator it=tempGeo.begin(); it != tempGeo.end(); ++it) + if (*it) delete *it; if (mdi && mdi->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { static_cast(mdi)->getViewer()->render(); @@ -2389,12 +2440,12 @@ Restart: void ViewProviderSketch::rebuildConstraintsVisual(void) { - const std::vector &ConStr = getSketchObject()->Constraints.getValues(); + const std::vector &constrlist = getSketchObject()->Constraints.getValues(); // clean up edit->constrGroup->removeAllChildren(); edit->vConstrType.clear(); - for (std::vector::const_iterator it = ConStr.begin(); it != ConStr.end(); ++it) { + for (std::vector::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 &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()); diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h index b97ea8493..572547186 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h @@ -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;