Sketcher New Feature: Ellipse support

- Ellipse introduction button via (center,majaxis extreme, a point in edge), ellipse is always CCW so that Z axis goes in the positive direction of the sketch
- Backwards compatibility with files of previous versions of ellipse not defining a phi angle
- Art by Jim (all the icons you see and the XPMs shown on creation of an ellipse)
- Element Widget support for ellipses
- Box selection for ellipses
- Point on Ellipse constraint based on the gardener's method based on Ulrich's function proposal (radcan simplified, i.e. with simplify_radical sage function)
- Tangent: Ellipse to Line based on DeepSOIC's geometric formulation (radcan simplified)

Sketcher New Feature: Internal Alignment Constraint
- The element to which internal alignment is applied has to be selected last.
- All other elements are added in the order of priority, taking into account existing elements
- Art by Jim (beautiful icons).

Sketcher New Feature: Tool to show/hide/restore the internal geometry of an element
- New functionality for show/hide internal geometry:
  toggles between hiding all unused internal geometry elements and showing all internal geometry.
  The restore function is implicit to the showing all internal geometry

Sketcher New Feature: Arc of Ellipse support
- Part::Geometry + Python implementation
- ArcOfEllipse creation method
- Art by Jim (all the icons you see and the XPMs shown on creation of arc of ellipse elements)
- Sketcher Element widget for ArcOfEllipse.

Bug fix: Select elements associated to constraints works now for foci internal alignment constraints
This commit is contained in:
Abdullah Tahiri
2014-11-11 19:29:45 +01:00
committed by wmayer
parent 6eec2e9851
commit a458c3e6d2
33 changed files with 5024 additions and 147 deletions

View File

@@ -1793,7 +1793,580 @@ bool CmdSketcherCreateCircle::isActive(void)
{
return isCreateGeoActive(getActiveGuiDocument());
}
// ======================================================================================
/* XPM */
static const char *cursor_createellipse[]={
"32 32 3 1",
"+ c white",
"# c red",
". c None",
"......+.........................",
"......+.........................",
"......+.........................",
"......+.........................",
"......+.........................",
"................................",
"+++++...+++++...................",
"................................",
"......+.........................",
"......+.........................",
"......+.........................",
"......+.........................",
"......+.........................",
"......+..............#####......",
"..................###.....#.....",
"...............###.......##.....",
".............##..........##.....",
"...........##............##.....",
"..........##.....###....##......",
".........##.....#.#.....#.......",
"........##.....###....##........",
"........##...........##.........",
".......##..........###..........",
"......##........####............",
"......#.....####................",
"......######....................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................"};
class DrawSketchHandlerEllipse : public DrawSketchHandler
{
public:
DrawSketchHandlerEllipse() : Mode(STATUS_SEEK_First),EditCurve(34){}
virtual ~DrawSketchHandlerEllipse(){}
/// mode table
enum SelectMode {
STATUS_SEEK_First, /**< enum value ----. */
STATUS_SEEK_Second, /**< enum value ----. */
STATUS_SEEK_Third, /**< enum value ----. */
STATUS_Close
};
virtual void activated(ViewProviderSketch *sketchgui)
{
setCursor(QPixmap(cursor_createellipse),7,7);
}
virtual void mouseMove(Base::Vector2D onSketchPos)
{
if (Mode==STATUS_SEEK_First) {
setPositionText(onSketchPos);
if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) { // TODO: ellipse prio 1
renderSuggestConstraintsCursor(sugConstr1);
return;
}
}
else if (Mode==STATUS_SEEK_Second) {
double rx0 = onSketchPos.fX - EditCurve[0].fX;
double ry0 = onSketchPos.fY - EditCurve[0].fY;
for (int i=0; i < 16; i++) {
double angle = i*M_PI/16.0;
double rx = rx0 * cos(angle) + ry0 * sin(angle);
double ry = -rx0 * sin(angle) + ry0 * cos(angle);
EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + rx, EditCurve[0].fY + ry);
EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
}
EditCurve[33] = EditCurve[1];
// Display radius for user
float radius = (onSketchPos - EditCurve[0]).Length();
SbString text;
text.sprintf(" (%.1fR,%.1fR)", radius,radius);
setPositionText(onSketchPos, text);
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f),
AutoConstraint::CURVE)) {
renderSuggestConstraintsCursor(sugConstr2);
return;
}
}
else if (Mode==STATUS_SEEK_Third) {
double rx0 = EditCurve[1].fX - EditCurve[0].fX; // first semidiameter
double ry0 = EditCurve[1].fY - EditCurve[0].fY; // first semidiameter
// angle between the major axis of the ellipse and the X axis
double a = (EditCurve[1]-EditCurve[0]).Length();
double phi = atan2f(EditCurve[1].fY-EditCurve[0].fY,EditCurve[1].fX-EditCurve[0].fX);
// This is the angle at cursor point
double angleatpoint = acos((onSketchPos.fX-EditCurve[0].fX+(onSketchPos.fY-EditCurve[0].fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
double b=(onSketchPos.fY-EditCurve[0].fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi));
for (int i=1; i < 16; i++) {
double angle = i*M_PI/16.0;
double rx = a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi);
double ry = a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi);
EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + rx, EditCurve[0].fY + ry);
EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
}
EditCurve[33] = EditCurve[1];
EditCurve[17] = EditCurve[16];
// Display radius for user
SbString text;
text.sprintf(" (%.1fR,%.1fR)", a, b);
setPositionText(onSketchPos, text);
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f),
AutoConstraint::CURVE)) {
renderSuggestConstraintsCursor(sugConstr2);
return;
}
}
applyCursor();
}
virtual bool pressButton(Base::Vector2D onSketchPos)
{
if (Mode==STATUS_SEEK_First){
EditCurve[0] = onSketchPos;
Mode = STATUS_SEEK_Second;
}
else if(Mode==STATUS_SEEK_Second) {
EditCurve[1] = onSketchPos;
Mode = STATUS_SEEK_Third;
}
else {
EditCurve[2] = onSketchPos;
Mode = STATUS_Close;
}
return true;
}
virtual bool releaseButton(Base::Vector2D onSketchPos)
{
if (Mode==STATUS_Close) {
unsetCursor();
resetPositionText();
// angle between the major axis of the ellipse and the X axis
double a = (EditCurve[1]-EditCurve[0]).Length();
double phi = atan2f(EditCurve[1].fY-EditCurve[0].fY,EditCurve[1].fX-EditCurve[0].fX);
// This is the angle at cursor point
double angleatpoint = acos((EditCurve[2].fX-EditCurve[0].fX+(EditCurve[2].fY-EditCurve[0].fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
double b=(EditCurve[2].fY-EditCurve[0].fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi));
Base::Vector2D majAxisDir,minAxisDir,minAxisPoint,majAxisPoint;
// We always create a CCW ellipse, because we want our XY reference system to be in the +X +Y direction
// Our normal will then always be in the +Z axis (local +Z axis of the sketcher)
if(a>b)
{
// force second semidiameter to be perpendicular to first semidiamater
majAxisDir = EditCurve[1] - EditCurve[0];
Base::Vector2D perp(-majAxisDir.fY,majAxisDir.fX);
perp.Normalize();
perp.Scale(abs(b));
minAxisPoint = EditCurve[0]+perp;
majAxisPoint = EditCurve[0]+majAxisDir;
}
else {
// force second semidiameter to be perpendicular to first semidiamater
minAxisDir = EditCurve[1] - EditCurve[0];
Base::Vector2D perp(minAxisDir.fY,-minAxisDir.fX);
perp.Normalize();
perp.Scale(abs(b));
majAxisPoint = EditCurve[0]+perp;
minAxisPoint = EditCurve[0]+minAxisDir;
}
Gui::Command::openCommand("Add sketch ellipse");
Gui::Command::doCommand(Gui::Command::Doc,
"App.ActiveDocument.%s.addGeometry(Part.Ellipse"
"(App.Vector(%f,%f,0),App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
sketchgui->getObject()->getNameInDocument(),
majAxisPoint.fX, majAxisPoint.fY,
minAxisPoint.fX, minAxisPoint.fY,
EditCurve[0].fX, EditCurve[0].fY);
Gui::Command::commitCommand();
Gui::Command::updateActive();
// add auto constraints for the center point
if (sugConstr1.size() > 0) {
createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::mid);
sugConstr1.clear();
}
// add suggested constraints for circumference
if (sugConstr2.size() > 0) {
//createAutoConstraints(sugConstr2, getHighestCurveIndex(), Sketcher::none);
sugConstr2.clear();
}
EditCurve.clear();
sketchgui->drawEdit(EditCurve);
sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
}
return true;
}
protected:
SelectMode Mode;
std::vector<Base::Vector2D> EditCurve;
std::vector<AutoConstraint> sugConstr1, sugConstr2;
};
DEF_STD_CMD_A(CmdSketcherCreateEllipse);
CmdSketcherCreateEllipse::CmdSketcherCreateEllipse()
: Command("Sketcher_CreateEllipse")
{
sAppModule = "Sketcher";
sGroup = QT_TR_NOOP("Sketcher");
sMenuText = QT_TR_NOOP("Create ellipse");
sToolTipText = QT_TR_NOOP("Create an ellipse in the sketch");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "Sketcher_CreateEllipse";
eType = ForEdit;
}
void CmdSketcherCreateEllipse::activated(int iMsg)
{
ActivateHandler(getActiveGuiDocument(),new DrawSketchHandlerEllipse() );
}
bool CmdSketcherCreateEllipse::isActive(void)
{
return isCreateGeoActive(getActiveGuiDocument());
}
// ======================================================================================
/* XPM */
static const char *cursor_createarcofellipse[]={
"32 32 3 1",
"+ c white",
"# c red",
". c None",
"......+.........................",
"......+.........................",
"......+.........................",
"......+.........................",
"......+.........................",
"................................",
"+++++...+++++...................",
"................................",
"......+.........................",
"......+.........................",
"......+................##.......",
"......+..............##.........",
"......+............##...........",
"......+...........##............",
"................##..............",
"...............##...............",
"..............##................",
".............###................",
"............##.........###......",
"...........##.........#.#.......",
"...........##.........###.......",
"..........##....................",
".........##.....................",
"........##......................",
"........##......................",
"........##......................",
"........#.....####..............",
"........######..................",
"................................",
"................................",
"................................",
"................................"};
class DrawSketchHandlerArcOfEllipse : public DrawSketchHandler
{
public:
DrawSketchHandlerArcOfEllipse() : Mode(STATUS_SEEK_First),EditCurve(34){}
virtual ~DrawSketchHandlerArcOfEllipse(){}
/// mode table
enum SelectMode {
STATUS_SEEK_First, /**< enum value ----. */
STATUS_SEEK_Second, /**< enum value ----. */
STATUS_SEEK_Third, /**< enum value ----. */
STATUS_SEEK_Fourth, /**< enum value ----. */
STATUS_Close
};
virtual void activated(ViewProviderSketch *sketchgui)
{
setCursor(QPixmap(cursor_createarcofellipse),7,7);
}
virtual void mouseMove(Base::Vector2D onSketchPos)
{
if (Mode==STATUS_SEEK_First) {
setPositionText(onSketchPos);
if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) { // TODO: ellipse prio 1
renderSuggestConstraintsCursor(sugConstr1);
return;
}
}
else if (Mode==STATUS_SEEK_Second) {
double rx0 = onSketchPos.fX - EditCurve[0].fX;
double ry0 = onSketchPos.fY - EditCurve[0].fY;
for (int i=0; i < 16; i++) {
double angle = i*M_PI/16.0;
double rx = rx0 * cos(angle) + ry0 * sin(angle);
double ry = -rx0 * sin(angle) + ry0 * cos(angle);
EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + rx, EditCurve[0].fY + ry);
EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
}
EditCurve[33] = EditCurve[1];
// Display radius for user
float radius = (onSketchPos - EditCurve[0]).Length();
SbString text;
text.sprintf(" (%.1fR,%.1fR)", radius,radius);
setPositionText(onSketchPos, text);
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f),
AutoConstraint::CURVE)) {
renderSuggestConstraintsCursor(sugConstr2);
return;
}
}
else if (Mode==STATUS_SEEK_Third) {
double rx0 = EditCurve[1].fX - EditCurve[0].fX; // first semidiameter
double ry0 = EditCurve[1].fY - EditCurve[0].fY; // first semidiameter
// angle between the major axis of the ellipse and the X axis
double a = (EditCurve[1]-EditCurve[0]).Length();
double phi = atan2f(EditCurve[1].fY-EditCurve[0].fY,EditCurve[1].fX-EditCurve[0].fX);
// This is the angle at cursor point
double angleatpoint = acos((onSketchPos.fX-EditCurve[0].fX+(onSketchPos.fY-EditCurve[0].fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
double b=(onSketchPos.fY-EditCurve[0].fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi));
for (int i=1; i < 16; i++) {
double angle = i*M_PI/16.0;
double rx = a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi);
double ry = a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi);
EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + rx, EditCurve[0].fY + ry);
EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
}
EditCurve[33] = EditCurve[1];
EditCurve[17] = EditCurve[16];
// Display radius for user
SbString text;
text.sprintf(" (%.1fR,%.1fR)", a, b);
setPositionText(onSketchPos, text);
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr3, onSketchPos, Base::Vector2D(0.f,0.f),
AutoConstraint::CURVE)) {
renderSuggestConstraintsCursor(sugConstr3);
return;
}
}
else if (Mode==STATUS_SEEK_Fourth) { // here we differ from ellipse creation
double rx0 = axisPoint.fX - centerPoint.fX; // first semidiameter
double ry0 = axisPoint.fY - centerPoint.fY; // first semidiameter
// angle between the major axis of the ellipse and the X axis
double a = (axisPoint-centerPoint).Length();
double phi = atan2(axisPoint.fY-centerPoint.fY,axisPoint.fX-centerPoint.fX);
// This is the angle at cursor point
double angleatpoint = acos((startingPoint.fX-centerPoint.fX+(startingPoint.fY-centerPoint.fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
double b=abs((startingPoint.fY-centerPoint.fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi)));
double rxs = startingPoint.fX - centerPoint.fX;
double rys = startingPoint.fY - centerPoint.fY;
startAngle = atan2(a*(rys*cos(phi)-rxs*sin(phi)), b*(rxs*cos(phi)+rys*sin(phi))); // eccentric anomaly angle
double angle1 = atan2(a*((onSketchPos.fY - centerPoint.fY)*cos(phi)-(onSketchPos.fX - centerPoint.fX)*sin(phi)),
b*((onSketchPos.fX - centerPoint.fX)*cos(phi)+(onSketchPos.fY - centerPoint.fY)*sin(phi)))- startAngle;
double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI ;
arcAngle = abs(angle1-arcAngle) < abs(angle2-arcAngle) ? angle1 : angle2;
for (int i=0; i < 34; i++) {
double angle = startAngle+i*arcAngle/34.0;
double rx = a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi);
double ry = a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi);
EditCurve[i] = Base::Vector2D(centerPoint.fX + rx, centerPoint.fY + ry);
}
// EditCurve[33] = EditCurve[1];
// EditCurve[17] = EditCurve[16];
// Display radii and angle for user
SbString text;
text.sprintf(" (%.1fR,%.1fR,%.1fdeg)", a, b, arcAngle * 180 / M_PI);
setPositionText(onSketchPos, text);
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr4, onSketchPos, Base::Vector2D(0.f,0.f),
AutoConstraint::CURVE)) {
renderSuggestConstraintsCursor(sugConstr4);
return;
}
}
applyCursor();
}
virtual bool pressButton(Base::Vector2D onSketchPos)
{
if (Mode==STATUS_SEEK_First){
EditCurve[0] = onSketchPos;
centerPoint = onSketchPos;
Mode = STATUS_SEEK_Second;
}
else if(Mode==STATUS_SEEK_Second) {
EditCurve[1] = onSketchPos;
axisPoint = onSketchPos;
Mode = STATUS_SEEK_Third;
}
else if(Mode==STATUS_SEEK_Third) {
startingPoint = onSketchPos;
arcAngle = 0.;
arcAngle_t= 0.;
Mode = STATUS_SEEK_Fourth;
}
else { // Fourth
endPoint = onSketchPos;
Mode = STATUS_Close;
}
return true;
}
virtual bool releaseButton(Base::Vector2D onSketchPos)
{
if (Mode==STATUS_Close) {
unsetCursor();
resetPositionText();
// angle between the major axis of the ellipse and the X axis
double a = (axisPoint-centerPoint).Length();
double phi = atan2(axisPoint.fY-centerPoint.fY,axisPoint.fX-centerPoint.fX);
// This is the angle at cursor point
double angleatpoint = acos((startingPoint.fX-centerPoint.fX+(startingPoint.fY-centerPoint.fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
double b=abs((startingPoint.fY-centerPoint.fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi)));
double angle1 = atan2(a*((endPoint.fY - centerPoint.fY)*cos(phi)-(endPoint.fX - centerPoint.fX)*sin(phi)),
b*((endPoint.fX - centerPoint.fX)*cos(phi)+(endPoint.fY - centerPoint.fY)*sin(phi)))- startAngle;
double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI ;
arcAngle = abs(angle1-arcAngle) < abs(angle2-arcAngle) ? angle1 : angle2;
if (arcAngle > 0)
endAngle = startAngle + arcAngle;
else {
endAngle = startAngle;
startAngle += arcAngle;
}
Base::Vector2D majAxisDir,minAxisDir,minAxisPoint,majAxisPoint;
// We always create a CCW ellipse, because we want our XY reference system to be in the +X +Y direction
// Our normal will then always be in the +Z axis (local +Z axis of the sketcher)
if(a>b)
{
// force second semidiameter to be perpendicular to first semidiamater
majAxisDir = axisPoint - centerPoint;
Base::Vector2D perp(-majAxisDir.fY,majAxisDir.fX);
perp.Normalize();
perp.Scale(abs(b));
minAxisPoint = centerPoint+perp;
majAxisPoint = centerPoint+majAxisDir;
}
else {
// force second semidiameter to be perpendicular to first semidiamater
minAxisDir = axisPoint - centerPoint;
Base::Vector2D perp(minAxisDir.fY,-minAxisDir.fX);
perp.Normalize();
perp.Scale(abs(b));
majAxisPoint = centerPoint+perp;
minAxisPoint = centerPoint+minAxisDir;
endAngle += M_PI/2;
startAngle += M_PI/2;
}
//startAngle=-M_PI/4;
//endAngle=M_PI/4;
Gui::Command::openCommand("Add sketch arc of ellipse");
Gui::Command::doCommand(Gui::Command::Doc,
"App.ActiveDocument.%s.addGeometry(Part.ArcOfEllipse"
"(Part.Ellipse(App.Vector(%f,%f,0),App.Vector(%f,%f,0),App.Vector(%f,%f,0)),"
"%f,%f))",
sketchgui->getObject()->getNameInDocument(),
majAxisPoint.fX, majAxisPoint.fY,
minAxisPoint.fX, minAxisPoint.fY,
centerPoint.fX, centerPoint.fY,
startAngle, endAngle); //arcAngle > 0 ? 0 : 1);
Gui::Command::commitCommand();
Gui::Command::updateActive();
// add auto constraints for the center point
if (sugConstr1.size() > 0) {
createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::mid);
sugConstr1.clear();
}
// add suggested constraints for circumference
if (sugConstr2.size() > 0) {
//createAutoConstraints(sugConstr2, getHighestCurveIndex(), Sketcher::none);
sugConstr2.clear();
}
EditCurve.clear();
sketchgui->drawEdit(EditCurve);
sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
}
return true;
}
protected:
SelectMode Mode;
std::vector<Base::Vector2D> EditCurve;
Base::Vector2D centerPoint, axisPoint, startingPoint, endPoint;
double rx, ry, startAngle, endAngle, arcAngle, arcAngle_t;
std::vector<AutoConstraint> sugConstr1, sugConstr2, sugConstr3, sugConstr4;
};
DEF_STD_CMD_A(CmdSketcherCreateArcOfEllipse);
CmdSketcherCreateArcOfEllipse::CmdSketcherCreateArcOfEllipse()
: Command("Sketcher_CreateArcOfEllipse")
{
sAppModule = "Sketcher";
sGroup = QT_TR_NOOP("Sketcher");
sMenuText = QT_TR_NOOP("Create an arc of ellipse");
sToolTipText = QT_TR_NOOP("Create an arc of ellipse in the sketch");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "Sketcher_Elliptical_Arc";
eType = ForEdit;
}
void CmdSketcherCreateArcOfEllipse::activated(int iMsg)
{
ActivateHandler(getActiveGuiDocument(),new DrawSketchHandlerArcOfEllipse() );
}
bool CmdSketcherCreateArcOfEllipse::isActive(void)
{
return isCreateGeoActive(getActiveGuiDocument());
}
// ======================================================================================
@@ -2548,6 +3121,7 @@ namespace SketcherGui {
geom->getTypeId() == Part::GeomCircle::getClassTypeId()||
geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId())
return true;
// TODO: ellipse
}
return false;
}
@@ -2628,6 +3202,7 @@ public:
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
geom->getTypeId() == Part::GeomCircle::getClassTypeId()
// TODO: ellipse
) {
try {
Gui::Command::openCommand("Trim edge");
@@ -3548,6 +4123,8 @@ void CreateSketcherCommandsCreateGeo(void)
rcCmdMgr.addCommand(new CmdSketcherCreateCircle());
rcCmdMgr.addCommand(new CmdSketcherCreate3PointCircle());
rcCmdMgr.addCommand(new CmdSketcherCompCreateCircle());
rcCmdMgr.addCommand(new CmdSketcherCreateEllipse());
rcCmdMgr.addCommand(new CmdSketcherCreateArcOfEllipse());
rcCmdMgr.addCommand(new CmdSketcherCreateLine());
rcCmdMgr.addCommand(new CmdSketcherCreatePolyline());
rcCmdMgr.addCommand(new CmdSketcherCreateRectangle());