From 938fadc746acb4944bb989fe6cdf13e09e35b3e0 Mon Sep 17 00:00:00 2001 From: logari81 Date: Mon, 2 Jul 2012 00:13:34 +0200 Subject: [PATCH 1/8] Sketcher: support arcs in the polyline tool (jonasthomas) --- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 230 ++++++++++++++++---- src/Mod/Sketcher/Gui/DrawSketchHandler.h | 1 + src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 5 + 3 files changed, 199 insertions(+), 37 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index fa9679fe2..7ba72897a 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -488,8 +488,10 @@ class DrawSketchHandlerLineSet: public DrawSketchHandler { public: DrawSketchHandlerLineSet() - : Mode(STATUS_SEEK_First),EditCurve(2),firstPoint(-1),previousCurve(-1){} - virtual ~DrawSketchHandlerLineSet(){} + : Mode(STATUS_SEEK_First),LineMode(LINE_MODE_Line),EditCurve(2), + firstCurve(-1),firstPoint(-1),previousCurve(-1),previousPoint(-1), + isTangent(false) {} + virtual ~DrawSketchHandlerLineSet() {} /// mode table enum SelectMode { STATUS_SEEK_First, /**< enum value ----. */ @@ -498,6 +500,41 @@ public: STATUS_Close }; + enum SelectLineMode + { + LINE_MODE_Arc, + LINE_MODE_Line + }; + + virtual void registerPressedKey(bool pressed, int key) + { + if (key == SoKeyboardEvent::A && pressed) { + if (LineMode != LINE_MODE_Arc) { + Base::Vector2D onSketchPos = EditCurve[isTangent ? 2 : 1]; + LineMode = LINE_MODE_Arc; + if (previousCurve != -1) + isTangent = true; + else + isTangent = false; + EditCurve.resize(32); + mouseMove(onSketchPos); // trigger an update of EditCurve + } + else { + Base::Vector2D onSketchPos = EditCurve[29]; + LineMode = LINE_MODE_Line; + if (previousCurve != -1) { + const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(previousCurve); + if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) + isTangent = true; + else + isTangent = false; + } + EditCurve.resize(isTangent ? 3 : 2); + mouseMove(onSketchPos); // trigger an update of EditCurve + } + } + } + virtual void activated(ViewProviderSketch *sketchgui) { setCursor(QPixmap(cursor_createlineset),7,7); @@ -513,11 +550,72 @@ public: } } else if (Mode==STATUS_SEEK_Second){ - EditCurve[1] = onSketchPos; - sketchgui->drawEdit(EditCurve); - if (seekAutoConstraint(sugConstr2, onSketchPos, onSketchPos - EditCurve[0])) { - renderSuggestConstraintsCursor(sugConstr2); - return; + if (LineMode == LINE_MODE_Line) { + EditCurve[isTangent ? 2 : 1] = onSketchPos; + if (isTangent) { + Base::Vector2D Tangent(dirVec.x,dirVec.y); + EditCurve[1].ProjToLine(EditCurve[2] - EditCurve[0], Tangent); + EditCurve[1] = EditCurve[0] + EditCurve[1]; + } + sketchgui->drawEdit(EditCurve); + if (!isTangent) { + sugConstr2 = sugConstr1; // Copy the previously found constraints + if (seekAutoConstraint(sugConstr2, onSketchPos, onSketchPos - EditCurve[0])) { + renderSuggestConstraintsCursor(sugConstr2); + return; + } + } + } + else if (LineMode == LINE_MODE_Arc) { + Base::Vector2D Tangent(dirVec.x,dirVec.y); + float theta = Tangent.GetAngle(onSketchPos - EditCurve[0]); + arcRadius = (onSketchPos - EditCurve[0]).Length()/(2.0*sin(theta)); + // At this point we need a unit normal vector pointing torwards + // the center of the arc we are drawing. Derivation of the formula + // used here can be found at http://people.richland.edu/james/lecture/m116/matrices/area.html + float x1 = EditCurve[0].fX; + float y1 = EditCurve[0].fY; + float x2 = x1 + Tangent.fX; + float y2 = y1 + Tangent.fY; + float x3 = onSketchPos.fX; + float y3 = onSketchPos.fY; + if ((x2*y3-x3*y2)-(x1*y3-x3*y1)+(x1*y2-x2*y1) > 0) + arcRadius *= -1; + + Base::Vector3d centerVec = dirVec % Base::Vector3d(0.f,0.f,1.0); + centerVec.Normalize(); // this step should actually be redundant + + CenterPoint = EditCurve[0] + Base::Vector2D(arcRadius * centerVec.x, arcRadius * centerVec.y); + + float rx = EditCurve[0].fX - CenterPoint.fX; + float ry = EditCurve[0].fY - CenterPoint.fY; + + startAngle = atan2(ry,rx); + + float rxe = onSketchPos.fX - CenterPoint.fX; + float rye = onSketchPos.fY - CenterPoint.fY; + float arcAngle = atan2(-rxe*ry + rye*rx, rxe*rx + rye*ry); + if (arcRadius >= 0 && arcAngle > 0) + arcAngle -= 2*M_PI; + if (arcRadius < 0 && arcAngle < 0) + arcAngle += 2*M_PI; + endAngle = startAngle + arcAngle; + + for (int i=1; i <= 29; i++) { + float angle = i*arcAngle/29.0; + float dx = rx * cos(angle) - ry * sin(angle); + float dy = rx * sin(angle) + ry * cos(angle); + EditCurve[i] = Base::Vector2D(CenterPoint.fX + dx, CenterPoint.fY + dy); + } + + EditCurve[30] = CenterPoint; + EditCurve[31] = EditCurve[0]; + + sketchgui->drawEdit(EditCurve); + if (seekAutoConstraint(sugConstr3, onSketchPos, Base::Vector2D(0.f,0.f))) { + renderSuggestConstraintsCursor(sugConstr3); + return; + } } } applyCursor(); @@ -529,15 +627,31 @@ public: // remember our first point firstPoint = getHighestVertexIndex() + 1; firstCurve = getHighestCurveIndex() + 1; + // TODO: here we should check if there is a preselected point + // and set up a transition from the neighbouring segment. + // (peviousCurve, previousPoint, dirVec, isTangent) + if (LineMode == LINE_MODE_Line) + EditCurve.resize(isTangent ? 3 : 2); + else if (LineMode == LINE_MODE_Arc) + EditCurve.resize(32); EditCurve[0] = onSketchPos; Mode = STATUS_SEEK_Second; } else if (Mode==STATUS_SEEK_Second) { - EditCurve[1] = onSketchPos; + if (LineMode == LINE_MODE_Line) { + EditCurve[isTangent ? 2 : 1] = onSketchPos; + if (isTangent) { + Base::Vector2D Tangent(dirVec.x,dirVec.y); + EditCurve[1].ProjToLine(EditCurve[2] - EditCurve[0], Tangent); + EditCurve[1] = EditCurve[0] + EditCurve[1]; + } + } + else if (LineMode == LINE_MODE_Arc) + EditCurve[29] = onSketchPos; // not so important sketchgui->drawEdit(EditCurve); applyCursor(); // exit on clicking exactly at the same position (e.g. double click) - if (EditCurve[1] == EditCurve[0]) { + if (onSketchPos == EditCurve[0]) { unsetCursor(); EditCurve.clear(); resetPositionText(); @@ -554,32 +668,46 @@ public: virtual bool releaseButton(Base::Vector2D onSketchPos) { - if (Mode==STATUS_Do || Mode==STATUS_Close) { - // open the transaction - Gui::Command::openCommand("add sketch wire"); - // issue the geometry - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))", - sketchgui->getObject()->getNameInDocument(), - EditCurve[0].fX,EditCurve[0].fY,EditCurve[1].fX,EditCurve[1].fY); + if (Mode == STATUS_Do || Mode == STATUS_Close) { + if (LineMode == LINE_MODE_Line) { + // open the transaction + Gui::Command::openCommand("Add sketch wire"); + // issue the geometry + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))", + sketchgui->getObject()->getNameInDocument(), + EditCurve[0].fX,EditCurve[0].fY,EditCurve[1].fX,EditCurve[1].fY); + } + else if (LineMode == LINE_MODE_Arc) { // We're dealing with an Arc + Gui::Command::openCommand("Add sketch wire"); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.addGeometry(Part.ArcOfCircle" + "(Part.Circle(App.Vector(%f,%f,0),App.Vector(0,0,1),%f),%f,%f))", + sketchgui->getObject()->getNameInDocument(), + CenterPoint.fX, CenterPoint.fY, std::abs(arcRadius), + std::min(startAngle,endAngle), std::max(startAngle,endAngle)); + } // issue the constraint if (previousCurve != -1) { - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%i,2,%i,1)) " - ,sketchgui->getObject()->getNameInDocument() - ,previousCurve-1,previousCurve - ); - } - - if (Mode==STATUS_Close) { - // close the loop by constrain to the first curve point - Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%i,2,%i,1)) " - ,sketchgui->getObject()->getNameInDocument() - ,previousCurve,firstCurve - ); - + int coincidentPoint = (LineMode == LINE_MODE_Arc && startAngle > endAngle) ? 2 : 1; + // in case of a tangency constraint, the coincident constraint is redundant + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('%s',%i,%i,%i,%i)) ", + sketchgui->getObject()->getNameInDocument(), + isTangent ? "Tangent" : "Coincident", + previousCurve, previousPoint /* == 2 */, previousCurve+1, coincidentPoint); + if (Mode == STATUS_Close) + // close the loop by constrain to the first curve point + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%i,%i,%i,%i)) ", + sketchgui->getObject()->getNameInDocument(), + previousCurve+1,coincidentPoint,firstCurve,firstPoint); Gui::Command::commitCommand(); Gui::Command::updateActive(); + } + if (Mode == STATUS_Close) { if (sugConstr2.size() > 0) { // exclude any coincidence constraints std::vector sugConstr; @@ -612,35 +740,63 @@ public: sugConstr2.clear(); } - //remember the vertex for the next rounds constraint... - previousCurve = getHighestCurveIndex() + 1; + // remember the vertex for the next rounds constraint.. + previousCurve = getHighestCurveIndex(); + previousPoint = (LineMode == LINE_MODE_Arc && startAngle > endAngle) ? 1 : 2; // setup for the next line segment // Use updated endPoint as autoconstraints can modify the position + // Need to determine if the previous element was a line or an arc or ??? 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); + dirVec.Set(lineSeg->getEndPoint().x - lineSeg->getStartPoint().x, + lineSeg->getEndPoint().y - lineSeg->getStartPoint().y, + 0.f); } - else - EditCurve[0] = onSketchPos; + else if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { + assert(LineMode == LINE_MODE_Arc); + const Part::GeomArcOfCircle *arcSeg = dynamic_cast(geom); + if (startAngle > endAngle) { + EditCurve[0] = Base::Vector2D(arcSeg->getStartPoint().x,arcSeg->getStartPoint().y); + dirVec = Base::Vector3d(0.f,0.f,-1.0) % (arcSeg->getStartPoint()-arcSeg->getCenter()); + } + else { // cw arcs are rendered in reverse + EditCurve[0] = Base::Vector2D(arcSeg->getEndPoint().x,arcSeg->getEndPoint().y); + dirVec = Base::Vector3d(0.f,0.f,1.0) % (arcSeg->getEndPoint()-arcSeg->getCenter()); + } + } + dirVec.Normalize(); - sketchgui->drawEdit(EditCurve); applyCursor(); - Mode = STATUS_SEEK_Second; + isTangent = (LineMode == LINE_MODE_Arc); + LineMode = LINE_MODE_Line; + EditCurve.resize(isTangent ? 3 : 2); + EditCurve[1] = EditCurve[0]; + if (isTangent) + EditCurve[2] = EditCurve[0]; + sketchgui->drawEdit(EditCurve); } } return true; } protected: SelectMode Mode; + SelectLineMode LineMode; + std::vector EditCurve; - Base::Vector2D lastPos; int firstPoint; int firstCurve; + int previousPoint; int previousCurve; - std::vector sugConstr1, sugConstr2; + std::vector sugConstr1, sugConstr2, sugConstr3; + + Base::Vector2D CenterPoint; + Base::Vector3d dirVec; + bool isTangent; + float startAngle, endAngle, arcRadius; }; diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandler.h b/src/Mod/Sketcher/Gui/DrawSketchHandler.h index 68ba93d2a..980ebdf75 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandler.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandler.h @@ -72,6 +72,7 @@ public: virtual bool pressButton(Base::Vector2D onSketchPos)=0; virtual bool releaseButton(Base::Vector2D onSketchPos)=0; virtual bool onSelectionChanged(const Gui::SelectionChanges& msg) { return false; }; + virtual void registerPressedKey(bool pressed, int key){}; virtual void quit(void); diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 36c22a0db..235b4c45a 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -281,6 +281,11 @@ bool ViewProviderSketch::keyPressed(bool pressed, int key) } return false; } + default: + { + if (edit && edit->sketchHandler) + edit->sketchHandler->registerPressedKey(pressed,key); + } } return true; // handle all other key events From 2e6255305cae2be37ac515ae1b972721adbb5302 Mon Sep 17 00:00:00 2001 From: logari81 Date: Sat, 7 Jul 2012 17:32:29 +0200 Subject: [PATCH 2/8] Add python interface for Part::GeomPoint --- src/Mod/Part/App/AppPart.cpp | 2 + src/Mod/Part/App/CMakeLists.txt | 3 + src/Mod/Part/App/Makefile.am | 4 + src/Mod/Part/App/PointPy.xml | 45 +++++++++ src/Mod/Part/App/PointPyImp.cpp | 174 ++++++++++++++++++++++++++++++++ 5 files changed, 228 insertions(+) create mode 100644 src/Mod/Part/App/PointPy.xml create mode 100644 src/Mod/Part/App/PointPyImp.cpp diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp index 4e521342c..c52c467cf 100644 --- a/src/Mod/Part/App/AppPart.cpp +++ b/src/Mod/Part/App/AppPart.cpp @@ -55,6 +55,7 @@ #include "TopoShapeCompSolidPy.h" #include "TopoShapeShellPy.h" #include "LinePy.h" +#include "PointPy.h" #include "CirclePy.h" #include "EllipsePy.h" #include "ArcPy.h" @@ -106,6 +107,7 @@ void PartExport initPart() Base::Interpreter().addType(&Part::TopoShapeShellPy ::Type,partModule,"Shell"); Base::Interpreter().addType(&Part::LinePy ::Type,partModule,"Line"); + Base::Interpreter().addType(&Part::PointPy ::Type,partModule,"Point"); Base::Interpreter().addType(&Part::CirclePy ::Type,partModule,"Circle"); Base::Interpreter().addType(&Part::EllipsePy ::Type,partModule,"Ellipse"); Base::Interpreter().addType(&Part::HyperbolaPy ::Type,partModule,"Hyperbola"); diff --git a/src/Mod/Part/App/CMakeLists.txt b/src/Mod/Part/App/CMakeLists.txt index 20a33407b..079a52a3e 100644 --- a/src/Mod/Part/App/CMakeLists.txt +++ b/src/Mod/Part/App/CMakeLists.txt @@ -34,6 +34,7 @@ generate_from_xml(GeometryPy) generate_from_xml(GeometryCurvePy) generate_from_xml(GeometrySurfacePy) generate_from_xml(LinePy) +generate_from_xml(PointPy) generate_from_xml(BezierCurvePy) generate_from_xml(BSplineCurvePy) generate_from_xml(PlanePy) @@ -154,6 +155,8 @@ SET(Python_SRCS GeometrySurfacePyImp.cpp LinePy.xml LinePyImp.cpp + PointPy.xml + PointPyImp.cpp BezierCurvePy.xml BezierCurvePyImp.cpp BSplineCurvePy.xml diff --git a/src/Mod/Part/App/Makefile.am b/src/Mod/Part/App/Makefile.am index 778427814..ddb4b3946 100644 --- a/src/Mod/Part/App/Makefile.am +++ b/src/Mod/Part/App/Makefile.am @@ -14,6 +14,7 @@ BUILT_SOURCES=\ GeometryCurvePy.cpp \ GeometrySurfacePy.cpp \ LinePy.cpp \ + PointPy.cpp \ BezierCurvePy.cpp \ BSplineCurvePy.cpp \ PlanePy.cpp \ @@ -53,6 +54,7 @@ libPart_la_BUILT=\ GeometryCurvePy.h \ GeometrySurfacePy.h \ LinePy.h \ + PointPy.h \ BezierCurvePy.h \ BSplineCurvePy.h \ PlanePy.h \ @@ -94,6 +96,7 @@ libPart_la_SOURCES=\ GeometryCurvePyImp.cpp \ GeometrySurfacePyImp.cpp \ LinePyImp.cpp \ + PointPyImp.cpp \ BezierCurvePyImp.cpp \ BSplineCurvePyImp.cpp \ PlanePyImp.cpp \ @@ -273,6 +276,7 @@ EXTRA_DIST = \ GeometryCurvePy.xml \ GeometrySurfacePy.xml \ LinePy.xml \ + PointPy.xml \ BezierCurvePy.xml \ BSplineCurvePy.xml \ PlanePy.xml \ diff --git a/src/Mod/Part/App/PointPy.xml b/src/Mod/Part/App/PointPy.xml new file mode 100644 index 000000000..9ad55f961 --- /dev/null +++ b/src/Mod/Part/App/PointPy.xml @@ -0,0 +1,45 @@ + + + + + + Describes a point +To create a point there are several ways: +Part.Point() + Creates a default point + +Part.Point(Point) + Creates a copy of the given point + +Part.Point(Vector) + Creates a line for the given coordinates + + + + X component of this point. + + + + + + Y component of this point. + + + + + + Z component of this point. + + + + + diff --git a/src/Mod/Part/App/PointPyImp.cpp b/src/Mod/Part/App/PointPyImp.cpp new file mode 100644 index 000000000..91417844a --- /dev/null +++ b/src/Mod/Part/App/PointPyImp.cpp @@ -0,0 +1,174 @@ +/*************************************************************************** + * Copyright (c) 2012 Konstantinos Poulios * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +# include +#endif + +#include +#include + +#include "Geometry.h" +#include "PointPy.h" +#include "PointPy.cpp" + +using namespace Part; + +extern const char* gce_ErrorStatusText(gce_ErrorType et); + +// returns a string which represents the object e.g. when printed in python +std::string PointPy::representation(void) const +{ + std::stringstream str; + Base::Vector3d coords = getGeomPointPtr()->getPoint(); + str << ""; + return str.str(); +} + +PyObject *PointPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +{ + // create a new instance of PointPy and the Twin object + return new PointPy(new GeomPoint); +} + +// constructor method +int PointPy::PyInit(PyObject* args, PyObject* /*kwd*/) +{ + + if (PyArg_ParseTuple(args, "")) { + // default point + return 0; + } + + PyErr_Clear(); + PyObject *pPoint; + if (PyArg_ParseTuple(args, "O!", &(PointPy::Type), &pPoint)) { + // Copy point + PointPy* pcPoint = static_cast(pPoint); + // get Geom_CartesianPoint of that point + Handle_Geom_CartesianPoint that_point = Handle_Geom_CartesianPoint::DownCast + (pcPoint->getGeomPointPtr()->handle()); + // get Geom_CartesianPoint of this point + Handle_Geom_CartesianPoint this_point = Handle_Geom_CartesianPoint::DownCast + (this->getGeomPointPtr()->handle()); + + // Assign the coordinates + this_point->SetPnt(that_point->Pnt()); + return 0; + } + + PyErr_Clear(); + PyObject *pV; + if (PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type), &pV)) { + Base::Vector3d v = static_cast(pV)->value(); + Handle_Geom_CartesianPoint this_point = Handle_Geom_CartesianPoint::DownCast + (this->getGeomPointPtr()->handle()); + this_point->SetCoord(v.x,v.y,v.z); + return 0; + } + + PyErr_SetString(PyExc_TypeError, "Point constructor accepts:\n" + "-- empty parameter list\n" + "-- Point\n" + "-- Coordinates vector"); + return -1; +} + +Py::Float PointPy::getX(void) const +{ + Handle_Geom_CartesianPoint this_point = Handle_Geom_CartesianPoint::DownCast + (this->getGeomPointPtr()->handle()); + return Py::Float(this_point->X()); +} + +void PointPy::setX(Py::Float X) +{ + Handle_Geom_CartesianPoint this_point = Handle_Geom_CartesianPoint::DownCast + (this->getGeomPointPtr()->handle()); + + try { + this_point->SetX(double(X)); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(e->GetMessageString()); + } +} + +Py::Float PointPy::getY(void) const +{ + Handle_Geom_CartesianPoint this_point = Handle_Geom_CartesianPoint::DownCast + (this->getGeomPointPtr()->handle()); + return Py::Float(this_point->Y()); +} + +void PointPy::setY(Py::Float Y) +{ + Handle_Geom_CartesianPoint this_point = Handle_Geom_CartesianPoint::DownCast + (this->getGeomPointPtr()->handle()); + + try { + this_point->SetY(double(Y)); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(e->GetMessageString()); + } +} + +Py::Float PointPy::getZ(void) const +{ + Handle_Geom_CartesianPoint this_point = Handle_Geom_CartesianPoint::DownCast + (this->getGeomPointPtr()->handle()); + return Py::Float(this_point->Z()); +} + +void PointPy::setZ(Py::Float Z) +{ + Handle_Geom_CartesianPoint this_point = Handle_Geom_CartesianPoint::DownCast + (this->getGeomPointPtr()->handle()); + + try { + this_point->SetZ(double(Z)); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + throw Py::Exception(e->GetMessageString()); + } +} + + +PyObject *PointPy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int PointPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} From 093f1d1af02b259389af3543dd05e30001564cf7 Mon Sep 17 00:00:00 2001 From: logari81 Date: Sat, 7 Jul 2012 17:38:44 +0200 Subject: [PATCH 3/8] Minor typo fix --- src/Mod/Part/App/LinePyImp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mod/Part/App/LinePyImp.cpp b/src/Mod/Part/App/LinePyImp.cpp index e430484fc..2bfe5a524 100644 --- a/src/Mod/Part/App/LinePyImp.cpp +++ b/src/Mod/Part/App/LinePyImp.cpp @@ -53,8 +53,8 @@ std::string LinePy::representation(void) const Base::Vector3d start = getGeomLineSegmentPtr()->getStartPoint(); Base::Vector3d end = getGeomLineSegmentPtr()->getEndPoint(); str << ""; + << start.x << "," <"; //} return str.str(); From 714908d3e9909fb2a149cd7fbdddd00a74190f6a Mon Sep 17 00:00:00 2001 From: logari81 Date: Sun, 8 Jul 2012 12:01:07 +0200 Subject: [PATCH 4/8] Sketcher: add support for points as construction geometry --- src/Mod/Complete/Gui/Workbench.cpp | 2 + src/Mod/PartDesign/Gui/Workbench.cpp | 4 +- src/Mod/Sketcher/App/Sketch.cpp | 54 ++++++++--- src/Mod/Sketcher/App/Sketch.h | 2 +- src/Mod/Sketcher/App/SketchObject.cpp | 6 +- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 101 +++++++++++++++++++- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 71 ++++++++------ src/Mod/Sketcher/Gui/ViewProviderSketch.h | 2 +- src/Mod/Sketcher/Gui/Workbench.cpp | 4 +- 9 files changed, 195 insertions(+), 51 deletions(-) diff --git a/src/Mod/Complete/Gui/Workbench.cpp b/src/Mod/Complete/Gui/Workbench.cpp index 707e32131..149f50ea5 100644 --- a/src/Mod/Complete/Gui/Workbench.cpp +++ b/src/Mod/Complete/Gui/Workbench.cpp @@ -256,6 +256,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "Sketcher_ViewSketch" << "Sketcher_MapSketch" << "Separator" + << "Sketcher_CreatePoint" << "Sketcher_CreateArc" << "Sketcher_CreateCircle" << "Sketcher_CreateLine" @@ -484,6 +485,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const << "Sketcher_NewSketch" << "Sketcher_LeaveSketch" << "Separator" + << "Sketcher_CreatePoint" << "Sketcher_CreateArc" << "Sketcher_CreateCircle" << "Sketcher_CreateLine" diff --git a/src/Mod/PartDesign/Gui/Workbench.cpp b/src/Mod/PartDesign/Gui/Workbench.cpp index 961393e70..b4bbff345 100644 --- a/src/Mod/PartDesign/Gui/Workbench.cpp +++ b/src/Mod/PartDesign/Gui/Workbench.cpp @@ -125,7 +125,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const Gui::MenuItem* geom = new Gui::MenuItem(); geom->setCommand("Sketcher geometries"); - *geom /*<< "Sketcher_CreatePoint"*/ + *geom << "Sketcher_CreatePoint" << "Sketcher_CreateArc" << "Sketcher_CreateCircle" << "Sketcher_CreateLine" @@ -194,7 +194,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const part = new Gui::ToolBarItem(root); part->setCommand("Sketcher geometries"); - *part /*<< "Sketcher_CreatePoint" */ + *part << "Sketcher_CreatePoint" << "Sketcher_CreateArc" << "Sketcher_CreateCircle" << "Sketcher_CreateLine" diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index 1898955f3..1e85fc9e1 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -150,7 +150,11 @@ 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() == GeomPoint::getClassTypeId()) { // add a point + const GeomPoint *point = dynamic_cast(geo); + // create the definition struct for that geom + return addPoint(*point, fixed); + } else 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); @@ -174,24 +178,30 @@ void Sketch::addGeometry(const std::vector &geo, bool fixed) addGeometry(*it, fixed); } -int Sketch::addPoint(const Base::Vector3d &newPoint, bool fixed) +int Sketch::addPoint(const Part::GeomPoint &point, bool fixed) { std::vector ¶ms = fixed ? FixParameters : Parameters; + // create our own copy + GeomPoint *p = static_cast(point.clone()); + // points in a sketch are always construction elements + p->Construction = true; // create the definition struct for that geom GeoDef def; - def.geo = 0; + def.geo = p; def.type = Point; // set the parameter for the solver - params.push_back(new double(newPoint.x)); - params.push_back(new double(newPoint.y)); + params.push_back(new double(p->getPoint().x)); + params.push_back(new double(p->getPoint().y)); // set the points for later constraints GCS::Point p1; p1.x = params[params.size()-2]; p1.y = params[params.size()-1]; def.startPointId = Points.size(); + def.endPointId = Points.size(); + def.midPointId = Points.size(); Points.push_back(p1); // store complete set @@ -393,7 +403,10 @@ Py::Tuple Sketch::getPyGeometry(void) const Py::Tuple tuple(Geoms.size()); int i=0; for (std::vector::const_iterator it=Geoms.begin(); it != Geoms.end(); ++it, i++) { - if (it->type == Line) { + if (it->type == Point) { + Base::Vector3d temp(*(Points[it->startPointId].x),*(Points[it->startPointId].y),0); + tuple[i] = Py::asObject(new VectorPy(temp)); + } else if (it->type == Line) { GeomLineSegment *lineSeg = dynamic_cast(it->geo->clone()); tuple[i] = Py::asObject(new LinePy(lineSeg)); } else if (it->type == Arc) { @@ -402,9 +415,6 @@ Py::Tuple Sketch::getPyGeometry(void) const } else if (it->type == Circle) { GeomCircle *circle = dynamic_cast(it->geo->clone()); tuple[i] = Py::asObject(new CirclePy(circle)); - } else if (it->type == Point) { - Base::Vector3d temp(*(Points[Geoms[i].startPointId].x),*(Points[Geoms[i].startPointId].y),0); - tuple[i] = Py::asObject(new VectorPy(temp)); } else if (it->type == Ellipse) { GeomEllipse *ellipse = dynamic_cast(it->geo->clone()); tuple[i] = Py::asObject(new EllipsePy(ellipse)); @@ -1517,7 +1527,13 @@ bool Sketch::updateGeometry() int i=0; for (std::vector::const_iterator it=Geoms.begin(); it != Geoms.end(); ++it, i++) { try { - if (it->type == Line) { + if (it->type == Point) { + GeomPoint *point = dynamic_cast(it->geo); + point->setPoint(Vector3d(*Points[it->startPointId].x, + *Points[it->startPointId].y, + 0.0) + ); + } else if (it->type == Line) { GeomLineSegment *lineSeg = dynamic_cast(it->geo); lineSeg->setPoints(Vector3d(*Lines[it->index].p1.x, *Lines[it->index].p1.y, @@ -1653,7 +1669,18 @@ int Sketch::initMove(int geoId, PointPos pos, bool fine) return -1; } - if (Geoms[geoId].type == Line) { + if (Geoms[geoId].type == Point) { + if (pos == start) { + GCS::Point &point = Points[Geoms[geoId].startPointId]; + GCS::Point p0; + MoveParameters.resize(2); // px,py + p0.x = &MoveParameters[0]; + p0.y = &MoveParameters[1]; + *p0.x = *point.x; + *p0.y = *point.y; + GCSsys.addConstraintP2PCoincident(p0,point,-1); + } + } else if (Geoms[geoId].type == Line) { if (pos == start || pos == end) { MoveParameters.resize(2); // x,y GCS::Point p0; @@ -1771,6 +1798,11 @@ int Sketch::movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool rela MoveParameters[i] = InitParameters[i] + toPoint.x; MoveParameters[i+1] = InitParameters[i+1] + toPoint.y; } + } else if (Geoms[geoId].type == Point) { + if (pos == start) { + MoveParameters[0] = toPoint.x; + MoveParameters[1] = toPoint.y; + } } else if (Geoms[geoId].type == Line) { if (pos == start || pos == end) { MoveParameters[0] = toPoint.x; diff --git a/src/Mod/Sketcher/App/Sketch.h b/src/Mod/Sketcher/App/Sketch.h index 3ea95bc4f..ea403d9f1 100644 --- a/src/Mod/Sketcher/App/Sketch.h +++ b/src/Mod/Sketcher/App/Sketch.h @@ -108,7 +108,7 @@ public: /// add dedicated geometry //@{ /// add a point - int addPoint(const Base::Vector3d &point, bool fixed=false); + int addPoint(const Part::GeomPoint &point, bool fixed=false); /// add an infinite line int addLine(const Part::GeomLineSegment &line, bool fixed=false); /// add a line segment diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index c09cd6963..997b49831 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -75,6 +75,7 @@ SketchObject::SketchObject() VLine->Construction = true; ExternalGeo.push_back(HLine); ExternalGeo.push_back(VLine); + rebuildVertexIndex(); } SketchObject::~SketchObject() @@ -1328,7 +1329,10 @@ void SketchObject::rebuildVertexIndex(void) const std::vector< Part::Geometry * > geometry = getCompleteGeometry(); for (std::vector< Part::Geometry * >::const_iterator it = geometry.begin(); it != geometry.end(); ++it) { - if ((*it)->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + if ((*it)->getTypeId() == Part::GeomPoint::getClassTypeId()) { + VertexId2GeoId.push_back(i); + VertexId2PosId.push_back(start); + } else if ((*it)->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { VertexId2GeoId.push_back(i); VertexId2PosId.push_back(start); VertexId2GeoId.push_back(i); diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index 7ba72897a..788feb195 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -1242,6 +1242,102 @@ bool CmdSketcherCreateCircle::isActive(void) // ====================================================================================== +/* XPM */ +static const char *cursor_createpoint[]={ +"32 32 3 1", +"+ c white", +"# c red", +". c None", +"......+.........................", +"......+.........................", +"......+.........................", +"......+.........................", +"......+.........................", +"................................", +"+++++...+++++...................", +"................................", +"......+.........................", +"......+.........................", +"......+.........................", +"......+.........................", +"......+.........................", +"...............+++++++..........", +"..............++.....++.........", +".............+.........+........", +"............++.........++.......", +"...........++...........++......", +"...........+.............+......", +"...........+.............+......", +"...........+.............+......", +"...........+.............+......", +"...........+.............+......", +"...........+.............+......", +"...........++...........++......", +"............++.........++.......", +".............+.........+........", +"..............++.....++.........", +"...............+++++++..........", +"................................", +"................................", +"................................"}; + +class DrawSketchHandlerPoint: public DrawSketchHandler +{ +public: + DrawSketchHandlerPoint() : selectionDone(false) {} + virtual ~DrawSketchHandlerPoint() {} + + virtual void activated(ViewProviderSketch *sketchgui) + { + setCursor(QPixmap(cursor_createpoint),7,7); + } + + virtual void mouseMove(Base::Vector2D onSketchPos) + { + setPositionText(onSketchPos); + if (seekAutoConstraint(sugConstr, onSketchPos, Base::Vector2D(0.f,0.f))) { + renderSuggestConstraintsCursor(sugConstr); + } + applyCursor(); + } + + virtual bool pressButton(Base::Vector2D onSketchPos) + { + EditPoint = onSketchPos; + selectionDone = true; + return true; + } + + virtual bool releaseButton(Base::Vector2D onSketchPos) + { + if (selectionDone){ + unsetCursor(); + resetPositionText(); + + Gui::Command::openCommand("Add sketch point"); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Point(App.Vector(%f,%f,0)))", + sketchgui->getObject()->getNameInDocument(), + EditPoint.fX,EditPoint.fY); + Gui::Command::commitCommand(); + Gui::Command::updateActive(); + + // add auto constraints for the line segment start + if (sugConstr.size() > 0) { + createAutoConstraints(sugConstr, getHighestCurveIndex(), Sketcher::start); + sugConstr.clear(); + } + + sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider + } + return true; + } +protected: + bool selectionDone; + Base::Vector2D EditPoint; + std::vector sugConstr; +}; + + DEF_STD_CMD_A(CmdSketcherCreatePoint); CmdSketcherCreatePoint::CmdSketcherCreatePoint() @@ -1259,11 +1355,12 @@ CmdSketcherCreatePoint::CmdSketcherCreatePoint() void CmdSketcherCreatePoint::activated(int iMsg) { + ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerPoint()); } bool CmdSketcherCreatePoint::isActive(void) { - return false; + return isCreateGeoActive(getActiveGuiDocument()); } // ====================================================================================== @@ -1882,7 +1979,7 @@ void CreateSketcherCommandsCreateGeo(void) { Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); - //rcCmdMgr.addCommand(new CmdSketcherCreatePoint()); + rcCmdMgr.addCommand(new CmdSketcherCreatePoint()); rcCmdMgr.addCommand(new CmdSketcherCreateArc()); rcCmdMgr.addCommand(new CmdSketcherCreateCircle()); rcCmdMgr.addCommand(new CmdSketcherCreateLine()); diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 235b4c45a..727626a9b 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -137,7 +137,7 @@ struct EditData { CurvesMaterials(0), PointsCoordinate(0), CurvesCoordinate(0), - CurveSet(0), + CurveSet(0), EditCurveSet(0), RootCrossSet(0), PointSet(0) {} @@ -159,12 +159,13 @@ struct EditData { bool blockedPreselection; bool FullyConstrained; - // pointer to the Solver + // instance of the solver Sketcher::Sketch ActSketch; // container to track our own selected parts std::set SelPointSet; std::set SelCurvSet; // also holds cross axes at -1 and -2 std::set SelConstraintSet; + std::vector CurvIdToGeoId; // conversion of SoLineSet index to GeoId // helper data structure for the constraint rendering std::vector vConstrType; @@ -615,16 +616,16 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe Gui::MenuItem *geom = new Gui::MenuItem(); geom->setCommand("Sketcher geoms"); - *geom /*<< "Sketcher_CreatePoint"*/ - << "Sketcher_CreateArc" - << "Sketcher_CreateCircle" - << "Sketcher_CreateLine" - << "Sketcher_CreatePolyline" - << "Sketcher_CreateRectangle" - << "Sketcher_CreateFillet" - << "Sketcher_Trimming" - << "Sketcher_External" - << "Sketcher_ToggleConstruction" + *geom << "Sketcher_CreatePoint" + << "Sketcher_CreateArc" + << "Sketcher_CreateCircle" + << "Sketcher_CreateLine" + << "Sketcher_CreatePolyline" + << "Sketcher_CreateRectangle" + << "Sketcher_CreateFillet" + << "Sketcher_Trimming" + << "Sketcher_External" + << "Sketcher_ToggleConstruction" /*<< "Sketcher_CreateText"*/ /*<< "Sketcher_CreateDraftLine"*/; @@ -753,8 +754,8 @@ bool ViewProviderSketch::mouseMove(const SbVec3f &point, const SbVec3f &normal, bool preselectChanged; if (Mode!=STATUS_SKETCH_DragPoint && Mode!=STATUS_SKETCH_DragCurve && Mode!=STATUS_SKETCH_DragConstraint) { - int PtIndex,CurvIndex,ConstrIndex,CrossIndex; - preselectChanged = detectPreselection(pp,PtIndex,CurvIndex,ConstrIndex,CrossIndex); + int PtIndex,GeoIndex,ConstrIndex,CrossIndex; + preselectChanged = detectPreselection(pp,PtIndex,GeoIndex,ConstrIndex,CrossIndex); } switch (Mode) { @@ -1184,12 +1185,12 @@ void ViewProviderSketch::onSelectionChanged(const Gui::SelectionChanges& msg) } } -bool ViewProviderSketch::detectPreselection(const SoPickedPoint *Point, int &PtIndex, int &CurvIndex, int &ConstrIndex, int &CrossIndex) +bool ViewProviderSketch::detectPreselection(const SoPickedPoint *Point, int &PtIndex, int &GeoIndex, int &ConstrIndex, int &CrossIndex) { assert(edit); PtIndex = -1; - CurvIndex = -1; // valid values are 0,1,2,... for normal geometry and -3,-4,-5,... for external geometry + GeoIndex = -1; // valid values are 0,1,2,... for normal geometry and -3,-4,-5,... for external geometry CrossIndex = -1; ConstrIndex = -1; @@ -1213,12 +1214,8 @@ bool ViewProviderSketch::detectPreselection(const SoPickedPoint *Point, int &PtI 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(); - int maxGeoId = getSketchObject()->getHighestCurveIndex(); - if (CurvIndex > maxGeoId) { // hit on external geometry - int extGeoCount = getSketchObject()->getExternalGeometryCount(); - CurvIndex = -extGeoCount + (CurvIndex - maxGeoId - 1); - } + int CurvIndex = static_cast(curve_detail)->getLineIndex(); + GeoIndex = edit->CurvIdToGeoId[CurvIndex]; } // checking for a hit in the cross } else if (tail == edit->RootCrossSet) { @@ -1259,12 +1256,12 @@ bool ViewProviderSketch::detectPreselection(const SoPickedPoint *Point, int &PtI edit->sketchHandler->applyCursor(); return true; } - } else if (CurvIndex != -1 && CurvIndex != edit->PreselectCurve) { // if a new curve is hit + } else if (GeoIndex != -1 && GeoIndex != edit->PreselectCurve) { // if a new curve is hit std::stringstream ss; - if (CurvIndex >= 0) - ss << "Edge" << CurvIndex; + if (GeoIndex >= 0) + ss << "Edge" << GeoIndex; else // external geometry - ss << "ExternalEdge" << -CurvIndex - 3; // convert index start from -3 to 0 + ss << "ExternalEdge" << -GeoIndex - 3; // convert index start from -3 to 0 bool accepted = Gui::Selection().setPreselect(getSketchObject()->getDocument()->getName() ,getSketchObject()->getNameInDocument() @@ -1275,7 +1272,7 @@ bool ViewProviderSketch::detectPreselection(const SoPickedPoint *Point, int &PtI edit->blockedPreselection = !accepted; if (accepted) { resetPreselectPoint(); - edit->PreselectCurve = CurvIndex; + edit->PreselectCurve = GeoIndex; edit->PreselectCross = -1; edit->PreselectConstraint = -1; if (edit->sketchHandler) @@ -1326,7 +1323,7 @@ bool ViewProviderSketch::detectPreselection(const SoPickedPoint *Point, int &PtI edit->sketchHandler->applyCursor(); return true; } - } else if ((PtIndex == -1 && CurvIndex == -1 && CrossIndex == -1 && ConstrIndex == -1) && + } else if ((PtIndex == -1 && GeoIndex == -1 && CrossIndex == -1 && ConstrIndex == -1) && (edit->PreselectPoint != -1 || edit->PreselectCurve != -1 || edit->PreselectCross != -1 || edit->PreselectConstraint != -1 || edit->blockedPreselection)) { // we have just left a preselection @@ -1384,7 +1381,7 @@ void ViewProviderSketch::updateColor(void) int intGeoCount = getSketchObject()->getHighestCurveIndex() + 1; int extGeoCount = getSketchObject()->getExternalGeometryCount(); for (int i=0; i < CurvNum; i++) { - int GeoId = (i < intGeoCount) ? i : -(extGeoCount - (i - intGeoCount)); + int GeoId = edit->CurvIdToGeoId[i]; if (edit->SelCurvSet.find(GeoId) != edit->SelCurvSet.end()) color[i] = SelectColor; else if (edit->PreselectCurve == GeoId) @@ -1629,8 +1626,16 @@ void ViewProviderSketch::draw(bool temp) 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 + edit->CurvIdToGeoId.clear(); + int GeoId = 0; + for (std::vector::const_iterator it = geomlist->begin(); it != geomlist->end()-2; ++it, GeoId++) { + if (GeoId >= intGeoCount) + GeoId = -extGeoCount; + if ((*it)->getTypeId() == Part::GeomPoint::getClassTypeId()) { // add a point + const Part::GeomPoint *point = dynamic_cast(*it); + Points.push_back(point->getPoint()); + } + else if ((*it)->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { // add a line const Part::GeomLineSegment *lineSeg = dynamic_cast(*it); // create the definition struct for that geom Coords.push_back(lineSeg->getStartPoint()); @@ -1638,6 +1643,7 @@ void ViewProviderSketch::draw(bool temp) Points.push_back(lineSeg->getStartPoint()); Points.push_back(lineSeg->getEndPoint()); Index.push_back(2); + edit->CurvIdToGeoId.push_back(GeoId); } else if ((*it)->getTypeId() == Part::GeomCircle::getClassTypeId()) { // add a circle const Part::GeomCircle *circle = dynamic_cast(*it); @@ -1655,6 +1661,7 @@ void ViewProviderSketch::draw(bool temp) Coords.push_back(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z())); Index.push_back(countSegments+1); + edit->CurvIdToGeoId.push_back(GeoId); Points.push_back(center); } else if ((*it)->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { // add an arc @@ -1685,6 +1692,7 @@ void ViewProviderSketch::draw(bool temp) Coords.push_back(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z())); Index.push_back(countSegments+1); + edit->CurvIdToGeoId.push_back(GeoId); Points.push_back(center); Points.push_back(start); Points.push_back(end); @@ -1718,6 +1726,7 @@ void ViewProviderSketch::draw(bool temp) } Index.push_back(countSegments+1); + edit->CurvIdToGeoId.push_back(GeoId); } else { ; diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h index 356d4414d..b29f2c377 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h @@ -126,7 +126,7 @@ public: /// helper to detect preselection //bool handlePreselection(const SoPickedPoint *pp); /// helper to detect preselection - bool detectPreselection(const SoPickedPoint *Point, int &PtIndex,int &CurvIndex, int &ConstrIndex, int &CrossIndex); + bool detectPreselection(const SoPickedPoint *Point, int &PtIndex,int &GeoIndex, int &ConstrIndex, int &CrossIndex); /// helper change the color of the sketch according to selection and solver status void updateColor(void); /// get the pointer to the sketch document object diff --git a/src/Mod/Sketcher/Gui/Workbench.cpp b/src/Mod/Sketcher/Gui/Workbench.cpp index 15a285f52..c00a259ed 100644 --- a/src/Mod/Sketcher/Gui/Workbench.cpp +++ b/src/Mod/Sketcher/Gui/Workbench.cpp @@ -60,7 +60,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const sketch->setCommand("S&ketch"); Gui::MenuItem* geom = new Gui::MenuItem(); geom->setCommand("Sketcher geometries"); - *geom /*<< "Sketcher_CreatePoint"*/ + *geom << "Sketcher_CreatePoint" << "Sketcher_CreateArc" << "Sketcher_CreateCircle" << "Sketcher_CreateLine" @@ -112,7 +112,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const part = new Gui::ToolBarItem(root); part->setCommand("Sketcher geometries"); - *part /*<< "Sketcher_CreatePoint" */ + *part << "Sketcher_CreatePoint" << "Sketcher_CreateArc" << "Sketcher_CreateCircle" << "Sketcher_CreateLine" From c099e90d991df9b5ea62e191ddc9358b75f868af Mon Sep 17 00:00:00 2001 From: logari81 Date: Sun, 8 Jul 2012 12:11:53 +0200 Subject: [PATCH 5/8] Sketcher: fixes in the new polyline tool and variables naming improvements --- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 35 ++++++++++++++--------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index 788feb195..50671e71a 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -489,7 +489,7 @@ class DrawSketchHandlerLineSet: public DrawSketchHandler public: DrawSketchHandlerLineSet() : Mode(STATUS_SEEK_First),LineMode(LINE_MODE_Line),EditCurve(2), - firstCurve(-1),firstPoint(-1),previousCurve(-1),previousPoint(-1), + firstVertex(-1),firstCurve(-1),previousCurve(-1),previousPosId(-1), isTangent(false) {} virtual ~DrawSketchHandlerLineSet() {} /// mode table @@ -625,11 +625,13 @@ public: { if (Mode==STATUS_SEEK_First) { // remember our first point - firstPoint = getHighestVertexIndex() + 1; + firstVertex = getHighestVertexIndex() + 1; firstCurve = getHighestCurveIndex() + 1; // TODO: here we should check if there is a preselected point // and set up a transition from the neighbouring segment. - // (peviousCurve, previousPoint, dirVec, isTangent) + // (peviousCurve, previousPosId, dirVec, isTangent) + // in that case we should set firstCurve and firstVertex to -1 + // in order to disable closing the wire if (LineMode == LINE_MODE_Line) EditCurve.resize(isTangent ? 3 : 2); else if (LineMode == LINE_MODE_Arc) @@ -658,7 +660,7 @@ public: sketchgui->drawEdit(EditCurve); sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider } - if (sketchgui->getPreselectPoint() == firstPoint) + if (sketchgui->getPreselectPoint() == firstVertex) Mode = STATUS_Close; else Mode = STATUS_Do; @@ -672,7 +674,7 @@ public: if (LineMode == LINE_MODE_Line) { // open the transaction - Gui::Command::openCommand("Add sketch wire"); + Gui::Command::openCommand("Add line to sketch wire"); // issue the geometry Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))", @@ -680,7 +682,7 @@ public: EditCurve[0].fX,EditCurve[0].fY,EditCurve[1].fX,EditCurve[1].fY); } else if (LineMode == LINE_MODE_Arc) { // We're dealing with an Arc - Gui::Command::openCommand("Add sketch wire"); + Gui::Command::openCommand("Add arc to sketch wire"); Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.addGeometry(Part.ArcOfCircle" "(Part.Circle(App.Vector(%f,%f,0),App.Vector(0,0,1),%f),%f,%f))", @@ -690,19 +692,26 @@ public: } // issue the constraint if (previousCurve != -1) { - int coincidentPoint = (LineMode == LINE_MODE_Arc && startAngle > endAngle) ? 2 : 1; + int lastCurve = previousCurve+1; + int lastStartPosId = (LineMode == LINE_MODE_Arc && startAngle > endAngle) ? 2 : 1; + int lastEndPosId = (LineMode == LINE_MODE_Arc && startAngle > endAngle) ? 1 : 2; // in case of a tangency constraint, the coincident constraint is redundant Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('%s',%i,%i,%i,%i)) ", sketchgui->getObject()->getNameInDocument(), isTangent ? "Tangent" : "Coincident", - previousCurve, previousPoint /* == 2 */, previousCurve+1, coincidentPoint); - if (Mode == STATUS_Close) + previousCurve, previousPosId /* == 2 */, lastCurve, lastStartPosId); + if (Mode == STATUS_Close) { + int firstGeoId; + Sketcher::PointPos firstPosId; + sketchgui->getSketchObject()->getGeoVertexIndex(firstVertex, firstGeoId, firstPosId); + //assert(firstCurve == firstGeoId); // close the loop by constrain to the first curve point Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Coincident',%i,%i,%i,%i)) ", sketchgui->getObject()->getNameInDocument(), - previousCurve+1,coincidentPoint,firstCurve,firstPoint); + lastCurve,lastEndPosId,firstCurve,firstPosId); + } Gui::Command::commitCommand(); Gui::Command::updateActive(); } @@ -742,7 +751,7 @@ public: // remember the vertex for the next rounds constraint.. previousCurve = getHighestCurveIndex(); - previousPoint = (LineMode == LINE_MODE_Arc && startAngle > endAngle) ? 1 : 2; + previousPosId = (LineMode == LINE_MODE_Arc && startAngle > endAngle) ? 1 : 2; // setup for the next line segment // Use updated endPoint as autoconstraints can modify the position @@ -787,9 +796,9 @@ protected: SelectLineMode LineMode; std::vector EditCurve; - int firstPoint; + int firstVertex; int firstCurve; - int previousPoint; + int previousPosId; int previousCurve; std::vector sugConstr1, sugConstr2, sugConstr3; From 044990333ca8a156fa0adb35cf0cc66ed917a9a3 Mon Sep 17 00:00:00 2001 From: logari81 Date: Mon, 9 Jul 2012 14:00:18 +0200 Subject: [PATCH 6/8] Sketcher: skip root cross axes in vertex counting (fixes closing polylines) --- src/Mod/Sketcher/App/SketchObject.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 997b49831..0cb04d84c 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -1327,8 +1327,10 @@ void SketchObject::rebuildVertexIndex(void) int imax=getHighestCurveIndex(); int i=0; const std::vector< Part::Geometry * > geometry = getCompleteGeometry(); + if (geometry.size() <= 2) + return; for (std::vector< Part::Geometry * >::const_iterator it = geometry.begin(); - it != geometry.end(); ++it) { + it != geometry.end()-2; ++it) { if ((*it)->getTypeId() == Part::GeomPoint::getClassTypeId()) { VertexId2GeoId.push_back(i); VertexId2PosId.push_back(start); From 47c44af45379b857a2e59cd9d637ba26de6bf985 Mon Sep 17 00:00:00 2001 From: logari81 Date: Mon, 9 Jul 2012 17:19:02 +0200 Subject: [PATCH 7/8] Sketcher: fix crash in polyline with autoconstraints, disable arc mode for first polyline segment --- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index 50671e71a..cf6680aed 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -508,7 +508,7 @@ public: virtual void registerPressedKey(bool pressed, int key) { - if (key == SoKeyboardEvent::A && pressed) { + if (key == SoKeyboardEvent::A && pressed && previousCurve != -1) { if (LineMode != LINE_MODE_Arc) { Base::Vector2D onSketchPos = EditCurve[isTangent ? 2 : 1]; LineMode = LINE_MODE_Arc; @@ -559,7 +559,6 @@ public: } sketchgui->drawEdit(EditCurve); if (!isTangent) { - sugConstr2 = sugConstr1; // Copy the previously found constraints if (seekAutoConstraint(sugConstr2, onSketchPos, onSketchPos - EditCurve[0])) { renderSuggestConstraintsCursor(sugConstr2); return; @@ -612,8 +611,8 @@ public: EditCurve[31] = EditCurve[0]; sketchgui->drawEdit(EditCurve); - if (seekAutoConstraint(sugConstr3, onSketchPos, Base::Vector2D(0.f,0.f))) { - renderSuggestConstraintsCursor(sugConstr3); + if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f))) { + renderSuggestConstraintsCursor(sugConstr2); return; } } @@ -739,7 +738,7 @@ public: Gui::Command::updateActive(); // Add auto constraints - if (sugConstr1.size() > 0) { + if (sugConstr1.size() > 0) { // this is relevant only to the very first point createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::start); sugConstr1.clear(); } @@ -800,7 +799,7 @@ protected: int firstCurve; int previousPosId; int previousCurve; - std::vector sugConstr1, sugConstr2, sugConstr3; + std::vector sugConstr1, sugConstr2; Base::Vector2D CenterPoint; Base::Vector3d dirVec; From e5953cedac75bbd8eba7351007dbf7a92a88003f Mon Sep 17 00:00:00 2001 From: logari81 Date: Tue, 10 Jul 2012 15:25:27 +0200 Subject: [PATCH 8/8] Sketcher: points defined as external geometry, fix behavior of external geometry cursor, improve appearance of point creation cursor --- src/Mod/Sketcher/App/SketchObject.cpp | 44 ++++++++++++++--------- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 43 +++++++++++----------- 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 0cb04d84c..32d718d21 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -32,6 +32,7 @@ # include # include # include +# include # include # include # include @@ -1226,15 +1227,17 @@ void SketchObject::rebuildExternalGeometry(void) 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()); + Base::Vector3d p = (p1 + p2) / 2; + Part::GeomPoint* point = new Part::GeomPoint(p); + point->Construction = true; + ExternalGeo.push_back(point); + } + else { + Part::GeomLineSegment* line = new Part::GeomLineSegment(); + line->setPoints(p1,p2); + line->Construction = true; + ExternalGeo.push_back(line); } - - Part::GeomLineSegment* line = new Part::GeomLineSegment(); - line->setPoints(p1,p2); - - line->Construction = true; - ExternalGeo.push_back(line); } else { try { @@ -1256,15 +1259,17 @@ void SketchObject::rebuildExternalGeometry(void) Base::Vector3d p2(P2.X(),P2.Y(),P2.Z()); 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()); + Base::Vector3d p = (p1 + p2) / 2; + Part::GeomPoint* point = new Part::GeomPoint(p); + point->Construction = true; + ExternalGeo.push_back(point); + } + else { + Part::GeomLineSegment* line = new Part::GeomLineSegment(); + line->setPoints(p1,p2); + line->Construction = true; + ExternalGeo.push_back(line); } - - Part::GeomLineSegment* line = new Part::GeomLineSegment(); - line->setPoints(p1,p2); - - line->Construction = true; - ExternalGeo.push_back(line); } else if (curve.GetType() == GeomAbs_Circle) { gp_Circ c = curve.Circle(); @@ -1304,7 +1309,12 @@ void SketchObject::rebuildExternalGeometry(void) } break; case TopAbs_VERTEX: - throw Base::Exception("Vertices cannot be used as external geometry for sketches"); + { + gp_Pnt p = BRep_Tool::Pnt(TopoDS::Vertex(refSubShape)); + Part::GeomPoint* point = new Part::GeomPoint(Base::Vector3d(p.X(),p.Y(),p.Z())); + point->Construction = true; + ExternalGeo.push_back(point); + } break; default: throw Base::Exception("Unknown type of geometry"); diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index cf6680aed..299a5229b 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -1269,22 +1269,22 @@ static const char *cursor_createpoint[]={ "......+.........................", "......+.........................", "......+.........................", -"...............+++++++..........", -"..............++.....++.........", -".............+.........+........", -"............++.........++.......", -"...........++...........++......", -"...........+.............+......", -"...........+.............+......", -"...........+.............+......", -"...........+.............+......", -"...........+.............+......", -"...........+.............+......", -"...........++...........++......", -"............++.........++.......", -".............+.........+........", -"..............++.....++.........", -"...............+++++++..........", +"................................", +"................................", +"................................", +".................++++...........", +"................++++++..........", +"...............++++++++.........", +"...............++++++++.........", +"...............++++++++.........", +"...............++++++++.........", +"................++++++..........", +".................++++...........", +"................................", +"................................", +"................................", +"................................", +"................................", "................................", "................................", "................................"}; @@ -1843,8 +1843,9 @@ namespace SketcherGui { if (!sSubName || sSubName[0] == '\0') return false; std::string element(sSubName); - // for the moment we allow only edges - if (element.substr(0,4) == "Edge") { + // for the moment we allow only edges and vertices + if ((element.size() > 4 && element.substr(0,4) == "Edge") || + (element.size() > 6 && element.substr(0,6) == "Vertex")) { return true; } return false; @@ -1917,7 +1918,8 @@ public: virtual void mouseMove(Base::Vector2D onSketchPos) { - applyCursor(); + if (Gui::Selection().getPreselection().pObjectName) + applyCursor(); } virtual bool pressButton(Base::Vector2D onSketchPos) @@ -1935,7 +1937,8 @@ public: { if (msg.Type == Gui::SelectionChanges::AddSelection) { std::string subName(msg.pSubName); - if (subName.size() > 4 && subName.substr(0,4) == "Edge") { + if ((subName.size() > 4 && subName.substr(0,4) == "Edge") || + (subName.size() > 6 && subName.substr(0,6) == "Vertex")) { try { Gui::Command::openCommand("Add external geometry"); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addExternal(\"%s\",\"%s\")",