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"