Sketcher: Reorder rounded rectangle code next to normal rectangle code

This commit is contained in:
Abdullah Tahiri
2021-06-20 07:07:22 +02:00
parent c668b4b0d8
commit cbcbb9de51

View File

@@ -615,6 +615,429 @@ bool CmdSketcherCreateRectangle::isActive(void)
return isCreateGeoActive(getActiveGuiDocument());
}
/* Create rounded oblong =======================================================*/
class DrawSketchHandlerOblong : public DrawSketchHandler
{
public:
DrawSketchHandlerOblong()
: Mode(STATUS_SEEK_First)
, lengthX(0), lengthY(0), radius(0), signX(1), signY(1)
, EditCurve(37)
{
}
virtual ~DrawSketchHandlerOblong() {}
/// mode table
enum BoxMode {
STATUS_SEEK_First, /**< enum value ----. */
STATUS_SEEK_Second, /**< enum value ----. */
STATUS_End
};
virtual void activated(ViewProviderSketch*)
{
setCrosshairCursor("Sketcher_Pointer_Oblong");
}
virtual void mouseMove(Base::Vector2d onSketchPos)
{
if (Mode == STATUS_SEEK_First) {
setPositionText(onSketchPos);
if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2d(0.f, 0.f))) {
renderSuggestConstraintsCursor(sugConstr1);
return;
}
}
else if (Mode == STATUS_SEEK_Second) {
float distanceX = onSketchPos.x - StartPos.x;
float distanceY = onSketchPos.y - StartPos.y;
lengthX = distanceX; lengthY = distanceY;
signX = Base::sgn(distanceX);
signY = Base::sgn(distanceY);
if (fabs(distanceX) > fabs(distanceY)) {
radius = fabs(distanceY) / 4; // we use a fourth of the smaller distance as default radius
}
else {
radius = fabs(distanceX) / 4;
}
// we draw the lines with 36 segments, 8 for each arc and 4 lines
// draw the arcs
for (int i = 0; i < 8; i++) {
// calculate the x,y positions forming the the arc
double angle = i * M_PI / 16.0;
double x_i = -radius * sin(angle);
double y_i = -radius * cos(angle);
// we are drawing clockwise starting with the arc that is besides StartPos
if (signX == signY) {
EditCurve[i] = Base::Vector2d(StartPos.x + signX * (radius + x_i), StartPos.y + signY * (radius + y_i));
EditCurve[9 + i] = Base::Vector2d(StartPos.x + signY * (radius + y_i), StartPos.y + lengthY - signX * (radius + x_i));
EditCurve[18 + i] = Base::Vector2d(StartPos.x + lengthX - signX * (radius + x_i), StartPos.y + lengthY - signY * (radius + y_i));
EditCurve[27 + i] = Base::Vector2d(StartPos.x + lengthX - signY * (radius + y_i), StartPos.y + signX * (radius + x_i));
}
else {
EditCurve[i] = Base::Vector2d(StartPos.x - signY * (radius + y_i), StartPos.y - signX * (radius + x_i));
EditCurve[9 + i] = Base::Vector2d(StartPos.x + lengthX - signX * (radius + x_i), StartPos.y + signY * (radius + y_i));
EditCurve[18 + i] = Base::Vector2d(StartPos.x + lengthX + signY * (radius + y_i), StartPos.y + lengthY + signX * (radius + x_i));
EditCurve[27 + i] = Base::Vector2d(StartPos.x + signX * (radius + x_i), StartPos.y + lengthY - signY * (radius + y_i));
}
}
// draw the lines
if (signX == signY) {
EditCurve[8] = Base::Vector2d(StartPos.x, StartPos.y + (signY * radius));
EditCurve[17] = Base::Vector2d(StartPos.x + (signX * radius), StartPos.y + lengthY);
EditCurve[26] = Base::Vector2d(StartPos.x + lengthX, StartPos.y + lengthY - (signY * radius));
EditCurve[35] = Base::Vector2d(StartPos.x + lengthX - (signX * radius), StartPos.y);
}
else {
EditCurve[8] = Base::Vector2d(StartPos.x + (signX * radius), StartPos.y);
EditCurve[17] = Base::Vector2d(StartPos.x + lengthX, StartPos.y + (signY * radius));
EditCurve[26] = Base::Vector2d(StartPos.x + lengthX - (signX * radius), StartPos.y + lengthY);
EditCurve[35] = Base::Vector2d(StartPos.x, StartPos.y + lengthY - (signY * radius));
}
// close the curve
EditCurve[36] = EditCurve[0];
SbString text;
text.sprintf(" (%.1fR %.1fX %.1fY)", radius, lengthX, lengthY);
setPositionText(onSketchPos, text);
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2d(0.f, 0.f))) {
renderSuggestConstraintsCursor(sugConstr2);
return;
}
}
applyCursor();
}
virtual bool pressButton(Base::Vector2d onSketchPos)
{
if (Mode == STATUS_SEEK_First) {
StartPos = onSketchPos;
Mode = STATUS_SEEK_Second;
}
else {
EndPos = onSketchPos;
Mode = STATUS_End;
}
return true;
}
virtual bool releaseButton(Base::Vector2d onSketchPos)
{
Q_UNUSED(onSketchPos);
if (Mode == STATUS_End) {
unsetCursor();
resetPositionText();
int firstCurve = getHighestCurveIndex() + 1;
// add the geometry to the sketch
// first determine the angles for the first arc
double start = 0;
double end = M_PI / 2;
if (signX > 0 && signY > 0) {
start = -2 * end;
end = -1 * end;
}
else if (signX > 0 && signY < 0) {
start = end;
end = 2 * end;
}
else if (signX < 0 && signY > 0) {
start = -1 * end;
end = 0;
}
try {
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Add rounded rectangle"));
Gui::Command::doCommand(Gui::Command::Doc,
// syntax for arcs: Part.ArcOfCircle(Part.Circle(center, axis, radius), startangle, endangle)
"geoList = []\n"
"geoList.append(Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f, 0), App.Vector(0, 0, 1), %f), %f, %f))\n"
"geoList.append(Part.LineSegment(App.Vector(%f, %f, 0), App.Vector(%f, %f, 0)))\n"
"geoList.append(Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f, 0), App.Vector(0, 0, 1), %f), %f, %f))\n"
"geoList.append(Part.LineSegment(App.Vector(%f, %f, 0), App.Vector(%f, %f, 0)))\n"
"geoList.append(Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f, 0), App.Vector(0, 0, 1), %f), %f, %f))\n"
"geoList.append(Part.LineSegment(App.Vector(%f, %f, 0), App.Vector(%f, %f, 0)))\n"
"geoList.append(Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f, 0), App.Vector(0, 0, 1), %f), %f, %f))\n"
"geoList.append(Part.LineSegment(App.Vector(%f, %f, 0), App.Vector(%f, %f, 0)))\n"
"%s.addGeometry(geoList, %s)\n"
"conList = []\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 1, %i, 1))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 2))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 1, %i, 1))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 2))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 1, %i, 1))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 2))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 1, %i, 1))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 2))\n"
"conList.append(Sketcher.Constraint('Horizontal', %i))\n"
"conList.append(Sketcher.Constraint('Horizontal', %i))\n"
"conList.append(Sketcher.Constraint('Vertical', %i))\n"
"conList.append(Sketcher.Constraint('Vertical', %i))\n"
"conList.append(Sketcher.Constraint('Equal', %i, %i))\n"
"conList.append(Sketcher.Constraint('Equal', %i, %i))\n"
"conList.append(Sketcher.Constraint('Equal', %i, %i))\n"
"%s.addConstraint(conList)\n",
StartPos.x + (signX * radius), StartPos.y + (signY * radius), // center of the arc 1
radius,
start, end, // start and end angle of arc1
EditCurve[8].x, EditCurve[8].y, EditCurve[9].x, EditCurve[9].y, // line 1
signX == signY ? StartPos.x + (signX * radius) : StartPos.x + lengthX - (signX * radius), // center of the arc 2
signX == signY ? StartPos.y + lengthY - (signY * radius) : StartPos.y + (signY * radius),
radius,
// start and end angle of arc 2
// the logic is that end is start + M_PI / 2 and start is the previous end - M_PI
end - M_PI,
end - 0.5 * M_PI,
EditCurve[17].x, EditCurve[17].y, EditCurve[18].x, EditCurve[18].y, // line 2
StartPos.x + lengthX - (signX * radius), StartPos.y + lengthY - (signY * radius), // center of the arc 3
radius,
end - 1.5 * M_PI,
end - M_PI,
EditCurve[26].x, EditCurve[26].y, EditCurve[27].x, EditCurve[27].y, // line 3
signX == signY ? StartPos.x + lengthX - (signX * radius) : StartPos.x + (signX * radius), // center of the arc 4
signX == signY ? StartPos.y + (signY * radius) : StartPos.y + lengthY - (signY * radius),
radius,
end - 2 * M_PI,
end - 1.5 * M_PI,
EditCurve[35].x, EditCurve[35].y, EditCurve[36].x, EditCurve[36].y, // line 4
Gui::Command::getObjectCmd(sketchgui->getObject()).c_str(), // the sketch
geometryCreationMode == Construction ? "True" : "False", // geometry as construction or not
firstCurve, firstCurve + 1, // tangent 1
firstCurve + 1, firstCurve + 2, // tangent 2
firstCurve + 2, firstCurve + 3, // tangent 3
firstCurve + 3, firstCurve + 4, // tangent 4
firstCurve + 4, firstCurve + 5, // tangent 5
firstCurve + 5, firstCurve + 6, // tangent 6
firstCurve + 6, firstCurve + 7, // tangent 7
firstCurve + 7, firstCurve, // tangent 8
signX == signY ? firstCurve + 3 : firstCurve + 1, // horizontal constraint
signX == signY ? firstCurve + 7 : firstCurve + 5, // horizontal constraint
signX == signY ? firstCurve + 1 : firstCurve + 3, // vertical constraint
signX == signY ? firstCurve + 5 : firstCurve + 7, // vertical constraint
firstCurve, firstCurve + 2, // equal 1
firstCurve + 2, firstCurve + 4, // equal 2
firstCurve + 4, firstCurve + 6, // equal 3
Gui::Command::getObjectCmd(sketchgui->getObject()).c_str()); // the sketch
// now add contruction geometry - two points used to take suggested constraints
Gui::Command::doCommand(Gui::Command::Doc,
"geoList = []\n"
"geoList.append(Part.Point(App.Vector(%f, %f, 0)))\n"
"geoList.append(Part.Point(App.Vector(%f, %f, 0)))\n"
"%s.addGeometry(geoList, True)\n" // geometry as construction
"conList = []\n"
"conList.append(Sketcher.Constraint('PointOnObject', %i, 1, %i, ))\n"
"conList.append(Sketcher.Constraint('PointOnObject', %i, 1, %i, ))\n"
"conList.append(Sketcher.Constraint('PointOnObject', %i, 1, %i, ))\n"
"conList.append(Sketcher.Constraint('PointOnObject', %i, 1, %i, ))\n"
"%s.addConstraint(conList)\n",
StartPos.x, StartPos.y, // point at StartPos
EndPos.x, EndPos.y, // point at EndPos
Gui::Command::getObjectCmd(sketchgui->getObject()).c_str(), // the sketch
firstCurve + 8, firstCurve + 1, // point on object constraint
firstCurve + 8, firstCurve + 7, // point on object constraint
firstCurve + 9, firstCurve + 3, // point on object constraint
firstCurve + 9, firstCurve + 5, // point on object constraint
Gui::Command::getObjectCmd(sketchgui->getObject()).c_str()); // the sketch
Gui::Command::commitCommand();
// add auto constraints at the StartPos auxiliar point
if (sugConstr1.size() > 0) {
createAutoConstraints(sugConstr1, getHighestCurveIndex() - 1, Sketcher::start);
sugConstr1.clear();
}
// add auto constraints at the EndPos auxiliar point
if (sugConstr2.size() > 0) {
createAutoConstraints(sugConstr2, getHighestCurveIndex(), Sketcher::start);
sugConstr2.clear();
}
tryAutoRecomputeIfNotSolve(static_cast<Sketcher::SketchObject*>(sketchgui->getObject()));
}
catch (const Base::Exception& e) {
Base::Console().Error("Failed to add rounded rectangle: %s\n", e.what());
Gui::Command::abortCommand();
tryAutoRecompute(static_cast<Sketcher::SketchObject*>(sketchgui->getObject()));
}
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher");
bool continuousMode = hGrp->GetBool("ContinuousCreationMode", true);
if (continuousMode) {
// This code enables the continuous creation mode.
Mode = STATUS_SEEK_First;
EditCurve.clear();
sketchgui->drawEdit(EditCurve);
EditCurve.resize(37);
applyCursor();
/* this is ok not to call to purgeHandler
* in continuous creation mode because the
* handler is destroyed by the quit() method on pressing the
* right button of the mouse */
}
else {
sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
}
}
return true;
}
protected:
BoxMode Mode;
Base::Vector2d StartPos, EndPos;
double lengthX, lengthY, radius;
float signX, signY;
std::vector<Base::Vector2d> EditCurve;
std::vector<AutoConstraint> sugConstr1, sugConstr2;
};
DEF_STD_CMD_AU(CmdSketcherCreateOblong)
CmdSketcherCreateOblong::CmdSketcherCreateOblong()
: Command("Sketcher_CreateOblong")
{
sAppModule = "Sketcher";
sGroup = QT_TR_NOOP("Sketcher");
sMenuText = QT_TR_NOOP("Create rounded rectangle");
sToolTipText = QT_TR_NOOP("Create a rounded rectangle in the sketch");
sWhatsThis = "Sketcher_CreateOblong";
sStatusTip = sToolTipText;
sPixmap = "Sketcher_CreateOblong";
sAccel = "";
eType = ForEdit;
}
void CmdSketcherCreateOblong::activated(int iMsg)
{
Q_UNUSED(iMsg);
ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerOblong());
}
void CmdSketcherCreateOblong::updateAction(int mode)
{
switch (mode) {
case Normal:
if (getAction())
getAction()->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateOblong"));
break;
case Construction:
if (getAction())
getAction()->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateOblong_Constr"));
break;
}
}
bool CmdSketcherCreateOblong::isActive(void)
{
return isCreateGeoActive(getActiveGuiDocument());
}
/* Rectangles Comp command =========================================*/
DEF_STD_CMD_ACLU(CmdSketcherCompCreateRectangles)
CmdSketcherCompCreateRectangles::CmdSketcherCompCreateRectangles()
: Command("Sketcher_CompCreateRectangles")
{
sAppModule = "Sketcher";
sGroup = QT_TR_NOOP("Sketcher");
sMenuText = QT_TR_NOOP("Create rectangles");
sToolTipText = QT_TR_NOOP("Creates a rectangle in the sketch");
sWhatsThis = "Sketcher_CompCreateRectangles";
sStatusTip = sToolTipText;
eType = ForEdit;
}
void CmdSketcherCompCreateRectangles::activated(int iMsg)
{
if (iMsg == 0)
ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerBox());
else if (iMsg == 1)
ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerOblong());
else
return;
// Since the default icon is reset when enabling/disabling the command we have
// to explicitly set the icon of the used command.
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
assert(iMsg < a.size());
pcAction->setIcon(a[iMsg]->icon());
}
Gui::Action* CmdSketcherCompCreateRectangles::createAction(void)
{
Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
pcAction->setDropDownMenu(true);
applyCommandData(this->className(), pcAction);
QAction* arc1 = pcAction->addAction(QString());
arc1->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle"));
QAction* arc2 = pcAction->addAction(QString());
arc2->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateOblong"));
_pcAction = pcAction;
languageChange();
pcAction->setIcon(arc1->icon());
int defaultId = 0;
pcAction->setProperty("defaultAction", QVariant(defaultId));
return pcAction;
}
void CmdSketcherCompCreateRectangles::updateAction(int mode)
{
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(getAction());
if (!pcAction)
return;
QList<QAction*> a = pcAction->actions();
int index = pcAction->property("defaultAction").toInt();
switch (mode) {
case Normal:
a[0]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle"));
a[1]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateOblong"));
getAction()->setIcon(a[index]->icon());
break;
case Construction:
a[0]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle_Constr"));
a[1]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateOblong_Constr"));
getAction()->setIcon(a[index]->icon());
break;
}
}
void CmdSketcherCompCreateRectangles::languageChange()
{
Command::languageChange();
if (!_pcAction)
return;
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
QAction* rectangle1 = a[0];
rectangle1->setText(QApplication::translate("CmdSketcherCompCreateRectangles", "Rectangle"));
rectangle1->setToolTip(QApplication::translate("Sketcher_CreateRectangle", "Create a rectangle"));
rectangle1->setStatusTip(rectangle1->toolTip());
QAction* rectangle2 = a[1];
rectangle2->setText(QApplication::translate("CmdSketcherCompCreateRectangles", "Rounded rectangle"));
rectangle2->setToolTip(QApplication::translate("Sketcher_CreateOblong", "Create a rounded rectangle"));
rectangle2->setStatusTip(rectangle2->toolTip());
}
bool CmdSketcherCompCreateRectangles::isActive(void)
{
return isCreateGeoActive(getActiveGuiDocument());
}
// ======================================================================================
@@ -6637,432 +7060,6 @@ bool CmdSketcherCreateSlot::isActive(void)
return isCreateGeoActive(getActiveGuiDocument());
}
/**
* Create rounded oblong
*/
class DrawSketchHandlerOblong : public DrawSketchHandler
{
public:
DrawSketchHandlerOblong()
: Mode(STATUS_SEEK_First)
, lengthX(0), lengthY(0), radius(0), signX(1), signY(1)
, EditCurve(37)
{
}
virtual ~DrawSketchHandlerOblong() {}
/// mode table
enum BoxMode {
STATUS_SEEK_First, /**< enum value ----. */
STATUS_SEEK_Second, /**< enum value ----. */
STATUS_End
};
virtual void activated(ViewProviderSketch*)
{
setCrosshairCursor("Sketcher_Pointer_Oblong");
}
virtual void mouseMove(Base::Vector2d onSketchPos)
{
if (Mode == STATUS_SEEK_First) {
setPositionText(onSketchPos);
if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2d(0.f, 0.f))) {
renderSuggestConstraintsCursor(sugConstr1);
return;
}
}
else if (Mode == STATUS_SEEK_Second) {
float distanceX = onSketchPos.x - StartPos.x;
float distanceY = onSketchPos.y - StartPos.y;
lengthX = distanceX; lengthY = distanceY;
signX = Base::sgn(distanceX);
signY = Base::sgn(distanceY);
if (fabs(distanceX) > fabs(distanceY)) {
radius = fabs(distanceY) / 4; // we use a fourth of the smaller distance as default radius
}
else {
radius = fabs(distanceX) / 4;
}
// we draw the lines with 36 segments, 8 for each arc and 4 lines
// draw the arcs
for (int i = 0; i < 8; i++) {
// calculate the x,y positions forming the the arc
double angle = i * M_PI / 16.0;
double x_i = -radius * sin(angle);
double y_i = -radius * cos(angle);
// we are drawing clockwise starting with the arc that is besides StartPos
if (signX == signY) {
EditCurve[i] = Base::Vector2d(StartPos.x + signX * (radius + x_i), StartPos.y + signY * (radius + y_i));
EditCurve[9 + i] = Base::Vector2d(StartPos.x + signY * (radius + y_i), StartPos.y + lengthY - signX * (radius + x_i));
EditCurve[18 + i] = Base::Vector2d(StartPos.x + lengthX - signX * (radius + x_i), StartPos.y + lengthY - signY * (radius + y_i));
EditCurve[27 + i] = Base::Vector2d(StartPos.x + lengthX - signY * (radius + y_i), StartPos.y + signX * (radius + x_i));
}
else {
EditCurve[i] = Base::Vector2d(StartPos.x - signY * (radius + y_i), StartPos.y - signX * (radius + x_i));
EditCurve[9 + i] = Base::Vector2d(StartPos.x + lengthX - signX * (radius + x_i), StartPos.y + signY * (radius + y_i));
EditCurve[18 + i] = Base::Vector2d(StartPos.x + lengthX + signY * (radius + y_i), StartPos.y + lengthY + signX * (radius + x_i));
EditCurve[27 + i] = Base::Vector2d(StartPos.x + signX * (radius + x_i), StartPos.y + lengthY - signY * (radius + y_i));
}
}
// draw the lines
if (signX == signY) {
EditCurve[8] = Base::Vector2d(StartPos.x, StartPos.y + (signY * radius));
EditCurve[17] = Base::Vector2d(StartPos.x + (signX * radius), StartPos.y + lengthY);
EditCurve[26] = Base::Vector2d(StartPos.x + lengthX, StartPos.y + lengthY - (signY * radius));
EditCurve[35] = Base::Vector2d(StartPos.x + lengthX - (signX * radius), StartPos.y);
}
else {
EditCurve[8] = Base::Vector2d(StartPos.x + (signX * radius), StartPos.y);
EditCurve[17] = Base::Vector2d(StartPos.x + lengthX, StartPos.y + (signY * radius));
EditCurve[26] = Base::Vector2d(StartPos.x + lengthX - (signX * radius), StartPos.y + lengthY);
EditCurve[35] = Base::Vector2d(StartPos.x, StartPos.y + lengthY - (signY * radius));
}
// close the curve
EditCurve[36] = EditCurve[0];
SbString text;
text.sprintf(" (%.1fR %.1fX %.1fY)", radius, lengthX, lengthY);
setPositionText(onSketchPos, text);
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2d(0.f, 0.f))) {
renderSuggestConstraintsCursor(sugConstr2);
return;
}
}
applyCursor();
}
virtual bool pressButton(Base::Vector2d onSketchPos)
{
if (Mode == STATUS_SEEK_First) {
StartPos = onSketchPos;
Mode = STATUS_SEEK_Second;
}
else {
EndPos = onSketchPos;
Mode = STATUS_End;
}
return true;
}
virtual bool releaseButton(Base::Vector2d onSketchPos)
{
Q_UNUSED(onSketchPos);
if (Mode == STATUS_End) {
unsetCursor();
resetPositionText();
int firstCurve = getHighestCurveIndex() + 1;
// add the geometry to the sketch
// first determine the angles for the first arc
double start = 0;
double end = M_PI / 2;
if (signX > 0 && signY > 0) {
start = -2 * end;
end = -1 * end;
}
else if (signX > 0 && signY < 0) {
start = end;
end = 2 * end;
}
else if (signX < 0 && signY > 0) {
start = -1 * end;
end = 0;
}
try {
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Add rounded rectangle"));
Gui::Command::doCommand(Gui::Command::Doc,
// syntax for arcs: Part.ArcOfCircle(Part.Circle(center, axis, radius), startangle, endangle)
"geoList = []\n"
"geoList.append(Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f, 0), App.Vector(0, 0, 1), %f), %f, %f))\n"
"geoList.append(Part.LineSegment(App.Vector(%f, %f, 0), App.Vector(%f, %f, 0)))\n"
"geoList.append(Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f, 0), App.Vector(0, 0, 1), %f), %f, %f))\n"
"geoList.append(Part.LineSegment(App.Vector(%f, %f, 0), App.Vector(%f, %f, 0)))\n"
"geoList.append(Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f, 0), App.Vector(0, 0, 1), %f), %f, %f))\n"
"geoList.append(Part.LineSegment(App.Vector(%f, %f, 0), App.Vector(%f, %f, 0)))\n"
"geoList.append(Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f, 0), App.Vector(0, 0, 1), %f), %f, %f))\n"
"geoList.append(Part.LineSegment(App.Vector(%f, %f, 0), App.Vector(%f, %f, 0)))\n"
"%s.addGeometry(geoList, %s)\n"
"conList = []\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 1, %i, 1))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 2))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 1, %i, 1))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 2))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 1, %i, 1))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 2))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 1, %i, 1))\n"
"conList.append(Sketcher.Constraint('Tangent', %i, 2, %i, 2))\n"
"conList.append(Sketcher.Constraint('Horizontal', %i))\n"
"conList.append(Sketcher.Constraint('Horizontal', %i))\n"
"conList.append(Sketcher.Constraint('Vertical', %i))\n"
"conList.append(Sketcher.Constraint('Vertical', %i))\n"
"conList.append(Sketcher.Constraint('Equal', %i, %i))\n"
"conList.append(Sketcher.Constraint('Equal', %i, %i))\n"
"conList.append(Sketcher.Constraint('Equal', %i, %i))\n"
"%s.addConstraint(conList)\n",
StartPos.x + (signX * radius), StartPos.y + (signY * radius), // center of the arc 1
radius,
start, end, // start and end angle of arc1
EditCurve[8].x, EditCurve[8].y, EditCurve[9].x, EditCurve[9].y, // line 1
signX == signY ? StartPos.x + (signX * radius) : StartPos.x + lengthX - (signX * radius), // center of the arc 2
signX == signY ? StartPos.y + lengthY - (signY * radius) : StartPos.y + (signY * radius),
radius,
// start and end angle of arc 2
// the logic is that end is start + M_PI / 2 and start is the previous end - M_PI
end - M_PI,
end - 0.5 * M_PI,
EditCurve[17].x, EditCurve[17].y, EditCurve[18].x, EditCurve[18].y, // line 2
StartPos.x + lengthX - (signX * radius), StartPos.y + lengthY - (signY * radius), // center of the arc 3
radius,
end - 1.5 * M_PI,
end - M_PI,
EditCurve[26].x, EditCurve[26].y, EditCurve[27].x, EditCurve[27].y, // line 3
signX == signY ? StartPos.x + lengthX - (signX * radius) : StartPos.x + (signX * radius), // center of the arc 4
signX == signY ? StartPos.y + (signY * radius) : StartPos.y + lengthY - (signY * radius),
radius,
end - 2 * M_PI,
end - 1.5 * M_PI,
EditCurve[35].x, EditCurve[35].y, EditCurve[36].x, EditCurve[36].y, // line 4
Gui::Command::getObjectCmd(sketchgui->getObject()).c_str(), // the sketch
geometryCreationMode == Construction ? "True" : "False", // geometry as construction or not
firstCurve, firstCurve + 1, // tangent 1
firstCurve + 1, firstCurve + 2, // tangent 2
firstCurve + 2, firstCurve + 3, // tangent 3
firstCurve + 3, firstCurve + 4, // tangent 4
firstCurve + 4, firstCurve + 5, // tangent 5
firstCurve + 5, firstCurve + 6, // tangent 6
firstCurve + 6, firstCurve + 7, // tangent 7
firstCurve + 7, firstCurve, // tangent 8
signX == signY ? firstCurve + 3 : firstCurve + 1, // horizontal constraint
signX == signY ? firstCurve + 7 : firstCurve + 5, // horizontal constraint
signX == signY ? firstCurve + 1 : firstCurve + 3, // vertical constraint
signX == signY ? firstCurve + 5 : firstCurve + 7, // vertical constraint
firstCurve, firstCurve + 2, // equal 1
firstCurve + 2, firstCurve + 4, // equal 2
firstCurve + 4, firstCurve + 6, // equal 3
Gui::Command::getObjectCmd(sketchgui->getObject()).c_str()); // the sketch
// now add contruction geometry - two points used to take suggested constraints
Gui::Command::doCommand(Gui::Command::Doc,
"geoList = []\n"
"geoList.append(Part.Point(App.Vector(%f, %f, 0)))\n"
"geoList.append(Part.Point(App.Vector(%f, %f, 0)))\n"
"%s.addGeometry(geoList, True)\n" // geometry as construction
"conList = []\n"
"conList.append(Sketcher.Constraint('PointOnObject', %i, 1, %i, ))\n"
"conList.append(Sketcher.Constraint('PointOnObject', %i, 1, %i, ))\n"
"conList.append(Sketcher.Constraint('PointOnObject', %i, 1, %i, ))\n"
"conList.append(Sketcher.Constraint('PointOnObject', %i, 1, %i, ))\n"
"%s.addConstraint(conList)\n",
StartPos.x, StartPos.y, // point at StartPos
EndPos.x, EndPos.y, // point at EndPos
Gui::Command::getObjectCmd(sketchgui->getObject()).c_str(), // the sketch
firstCurve + 8, firstCurve + 1, // point on object constraint
firstCurve + 8, firstCurve + 7, // point on object constraint
firstCurve + 9, firstCurve + 3, // point on object constraint
firstCurve + 9, firstCurve + 5, // point on object constraint
Gui::Command::getObjectCmd(sketchgui->getObject()).c_str()); // the sketch
Gui::Command::commitCommand();
// add auto constraints at the StartPos auxiliar point
if (sugConstr1.size() > 0) {
createAutoConstraints(sugConstr1, getHighestCurveIndex() - 1, Sketcher::start);
sugConstr1.clear();
}
// add auto constraints at the EndPos auxiliar point
if (sugConstr2.size() > 0) {
createAutoConstraints(sugConstr2, getHighestCurveIndex(), Sketcher::start);
sugConstr2.clear();
}
tryAutoRecomputeIfNotSolve(static_cast<Sketcher::SketchObject*>(sketchgui->getObject()));
}
catch (const Base::Exception& e) {
Base::Console().Error("Failed to add rounded rectangle: %s\n", e.what());
Gui::Command::abortCommand();
tryAutoRecompute(static_cast<Sketcher::SketchObject*>(sketchgui->getObject()));
}
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher");
bool continuousMode = hGrp->GetBool("ContinuousCreationMode", true);
if (continuousMode) {
// This code enables the continuous creation mode.
Mode = STATUS_SEEK_First;
EditCurve.clear();
sketchgui->drawEdit(EditCurve);
EditCurve.resize(37);
applyCursor();
/* this is ok not to call to purgeHandler
* in continuous creation mode because the
* handler is destroyed by the quit() method on pressing the
* right button of the mouse */
}
else {
sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
}
}
return true;
}
protected:
BoxMode Mode;
Base::Vector2d StartPos, EndPos;
double lengthX, lengthY, radius;
float signX, signY;
std::vector<Base::Vector2d> EditCurve;
std::vector<AutoConstraint> sugConstr1, sugConstr2;
};
DEF_STD_CMD_AU(CmdSketcherCreateOblong)
CmdSketcherCreateOblong::CmdSketcherCreateOblong()
: Command("Sketcher_CreateOblong")
{
sAppModule = "Sketcher";
sGroup = QT_TR_NOOP("Sketcher");
sMenuText = QT_TR_NOOP("Create rounded rectangle");
sToolTipText = QT_TR_NOOP("Create a rounded rectangle in the sketch");
sWhatsThis = "Sketcher_CreateOblong";
sStatusTip = sToolTipText;
sPixmap = "Sketcher_CreateOblong";
sAccel = "";
eType = ForEdit;
}
void CmdSketcherCreateOblong::activated(int iMsg)
{
Q_UNUSED(iMsg);
ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerOblong());
}
void CmdSketcherCreateOblong::updateAction(int mode)
{
switch (mode) {
case Normal:
if (getAction())
getAction()->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateOblong"));
break;
case Construction:
if (getAction())
getAction()->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateOblong_Constr"));
break;
}
}
bool CmdSketcherCreateOblong::isActive(void)
{
return isCreateGeoActive(getActiveGuiDocument());
}
DEF_STD_CMD_ACLU(CmdSketcherCompCreateRectangles)
CmdSketcherCompCreateRectangles::CmdSketcherCompCreateRectangles()
: Command("Sketcher_CompCreateRectangles")
{
sAppModule = "Sketcher";
sGroup = QT_TR_NOOP("Sketcher");
sMenuText = QT_TR_NOOP("Create rectangles");
sToolTipText = QT_TR_NOOP("Creates a rectangle in the sketch");
sWhatsThis = "Sketcher_CompCreateRectangles";
sStatusTip = sToolTipText;
eType = ForEdit;
}
void CmdSketcherCompCreateRectangles::activated(int iMsg)
{
if (iMsg == 0)
ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerBox());
else if (iMsg == 1)
ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerOblong());
else
return;
// Since the default icon is reset when enabling/disabling the command we have
// to explicitly set the icon of the used command.
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
assert(iMsg < a.size());
pcAction->setIcon(a[iMsg]->icon());
}
Gui::Action* CmdSketcherCompCreateRectangles::createAction(void)
{
Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
pcAction->setDropDownMenu(true);
applyCommandData(this->className(), pcAction);
QAction* arc1 = pcAction->addAction(QString());
arc1->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle"));
QAction* arc2 = pcAction->addAction(QString());
arc2->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateOblong"));
_pcAction = pcAction;
languageChange();
pcAction->setIcon(arc1->icon());
int defaultId = 0;
pcAction->setProperty("defaultAction", QVariant(defaultId));
return pcAction;
}
void CmdSketcherCompCreateRectangles::updateAction(int mode)
{
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(getAction());
if (!pcAction)
return;
QList<QAction*> a = pcAction->actions();
int index = pcAction->property("defaultAction").toInt();
switch (mode) {
case Normal:
a[0]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle"));
a[1]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateOblong"));
getAction()->setIcon(a[index]->icon());
break;
case Construction:
a[0]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle_Constr"));
a[1]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateOblong_Constr"));
getAction()->setIcon(a[index]->icon());
break;
}
}
void CmdSketcherCompCreateRectangles::languageChange()
{
Command::languageChange();
if (!_pcAction)
return;
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
QAction* rectangle1 = a[0];
rectangle1->setText(QApplication::translate("CmdSketcherCompCreateRectangles", "Rectangle"));
rectangle1->setToolTip(QApplication::translate("Sketcher_CreateRectangle", "Create a rectangle"));
rectangle1->setStatusTip(rectangle1->toolTip());
QAction* rectangle2 = a[1];
rectangle2->setText(QApplication::translate("CmdSketcherCompCreateRectangles", "Rounded rectangle"));
rectangle2->setToolTip(QApplication::translate("Sketcher_CreateOblong", "Create a rounded rectangle"));
rectangle2->setStatusTip(rectangle2->toolTip());
}
bool CmdSketcherCompCreateRectangles::isActive(void)
{
return isCreateGeoActive(getActiveGuiDocument());
}
/* Create Regular Polygon ==============================================*/
class DrawSketchHandlerRegularPolygon: public DrawSketchHandler