Skip to content

Commit

Permalink
Sketcher - Add new Split Edge action
Browse files Browse the repository at this point in the history
  • Loading branch information
pavltom authored and abdullahtahiriyo committed Apr 24, 2021
1 parent ae0a315 commit 4d6b1f3
Show file tree
Hide file tree
Showing 11 changed files with 1,276 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/Mod/Part/App/Geometry.cpp
Expand Up @@ -684,7 +684,7 @@ bool GeomCurve::normalAt(double u, Base::Vector3d& dir) const
return false;
}

bool GeomCurve::intersect( GeomCurve * c,
bool GeomCurve::intersect( const GeomCurve *c,
std::vector<std::pair<Base::Vector3d, Base::Vector3d>>& points,
double tol) const
{
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/Part/App/Geometry.h
Expand Up @@ -197,7 +197,7 @@ class PartExport GeomCurve : public Geometry
double curvatureAt(double u) const;
double length(double u, double v) const;
bool normalAt(double u, Base::Vector3d& dir) const;
bool intersect(GeomCurve * c,
bool intersect(const GeomCurve *c,
std::vector<std::pair<Base::Vector3d, Base::Vector3d>>& points,
double tol = Precision::Confusion()) const;

Expand Down
356 changes: 346 additions & 10 deletions src/Mod/Sketcher/App/SketchObject.cpp

Large diffs are not rendered by default.

12 changes: 11 additions & 1 deletion src/Mod/Sketcher/App/SketchObject.h
Expand Up @@ -157,7 +157,12 @@ class SketcherExport SketchObject : public Part::Part2DObject
/// Deletes all constraints referencing an external geometry
int delConstraintsToExternal();
/// transfers all constraints of a point to a new point
int transferConstraints(int fromGeoId, PointPos fromPosId, int toGeoId, PointPos toPosId);
int transferConstraints(int fromGeoId, PointPos fromPosId, int toGeoId, PointPos toPosId,
bool tangencyHolds = false);

/// swaps original GeoId for a new one
void swapInvolvedGeometry(Constraint *constraint, int fromGeoId, int toGeoId);

/// Carbon copy another sketch geometry and constraints
int carbonCopy(App::DocumentObject * pObj, bool construction = true);
/// add an external geometry reference
Expand Down Expand Up @@ -282,6 +287,8 @@ class SketcherExport SketchObject : public Part::Part2DObject
int trim(int geoId, const Base::Vector3d& point);
/// extend a curve
int extend(int geoId, double increment, int endPoint);
/// split a curve
int split(int geoId, const Base::Vector3d &point);

/// adds symmetric geometric elements with respect to the refGeoId (line or point)
int addSymmetric(const std::vector<int> &geoIdList, int refGeoId, Sketcher::PointPos refPosId=Sketcher::none);
Expand Down Expand Up @@ -358,6 +365,9 @@ class SketcherExport SketchObject : public Part::Part2DObject
void getDirectlyCoincidentPoints(int VertexId, std::vector<int> &GeoIdList, std::vector<PointPos> &PosIdList);
bool arePointsCoincident(int GeoId1, PointPos PosId1, int GeoId2, PointPos PosId2);

/// fetches all constraints involving given GeoId
void getAppliedConstraints(int GeoId, std::vector<int> &constraintList);

/// generates a warning message about constraint conflicts and appends it to the given message
static void appendConflictMsg(const std::vector<int> &conflicting, std::string &msg);
/// generates a warning message about redundant constraints and appends it to the given message
Expand Down
5 changes: 5 additions & 0 deletions src/Mod/Sketcher/App/SketchObjectPy.xml
Expand Up @@ -217,6 +217,11 @@ If there is no such constraint an exception is raised.
<UserDocu>extend a curve to new start and end positions</UserDocu>
</Documentation>
</Methode>
<Methode Name="split">
<Documentation>
<UserDocu>split a curve with a given id at a given reference point</UserDocu>
</Documentation>
</Methode>
<Methode Name="addSymmetric">
<Documentation>
<UserDocu>add a symmetric geometric objects to the sketch with respect to a reference point or line</UserDocu>
Expand Down
21 changes: 20 additions & 1 deletion src/Mod/Sketcher/App/SketchObjectPyImp.cpp
Expand Up @@ -570,7 +570,7 @@ PyObject* SketchObjectPy::delConstraintOnPoint(PyObject *args)
if (!PyArg_ParseTuple(args, "i|i", &Index, &pos))
return 0;

if (pos>=0 && pos<3) { // Sketcher::none Sketcher::mid
if (pos>=0 && pos<=3) { // Sketcher::none Sketcher::mid
if (this->getSketchObjectPtr()->delConstraintOnPoint(Index,(Sketcher::PointPos)pos)) {
std::stringstream str;
str << "Not able to delete a constraint on point with the given index: " << Index
Expand Down Expand Up @@ -1120,6 +1120,25 @@ PyObject* SketchObjectPy::extend(PyObject *args)
return 0;
}

PyObject* SketchObjectPy::split(PyObject *args)
{
PyObject *pcObj;
int GeoId;

if (!PyArg_ParseTuple(args, "iO!", &GeoId, &(Base::VectorPy::Type), &pcObj))
return 0;

Base::Vector3d v1 = static_cast<Base::VectorPy*>(pcObj)->value();
if (this->getSketchObjectPtr()->split(GeoId,v1)) {
std::stringstream str;
str << "Not able to split curve with the given index: " << GeoId;
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}

Py_Return;
}

PyObject* SketchObjectPy::addSymmetric(PyObject *args)
{
PyObject *pcObj;
Expand Down
120 changes: 120 additions & 0 deletions src/Mod/Sketcher/Gui/CommandCreateGeo.cpp
Expand Up @@ -5904,6 +5904,125 @@ bool CmdSketcherExtend::isActive(void)
}


// ======================================================================================

namespace SketcherGui {
class SplittingSelection : public Gui::SelectionFilterGate
{
App::DocumentObject* object;
public:
SplittingSelection(App::DocumentObject* obj)
: Gui::SelectionFilterGate((Gui::SelectionFilter*)0), object(obj)
{}

bool allow(App::Document * /*pDoc*/, App::DocumentObject *pObj, const char *sSubName)
{
if (pObj != this->object)
return false;
if (!sSubName || sSubName[0] == '\0')
return false;
std::string element(sSubName);
if (element.substr(0,4) == "Edge") {
int GeoId = std::atoi(element.substr(4,4000).c_str()) - 1;
Sketcher::SketchObject *Sketch = static_cast<Sketcher::SketchObject*>(object);
const Part::Geometry *geom = Sketch->getGeometry(GeoId);
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()
|| geom->getTypeId() == Part::GeomCircle::getClassTypeId()
|| geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
return true;
}
}
return false;
}
};
}

class DrawSketchHandlerSplitting: public DrawSketchHandler
{
public:
DrawSketchHandlerSplitting() {}
virtual ~DrawSketchHandlerSplitting()
{
Gui::Selection().rmvSelectionGate();
}

virtual void activated(ViewProviderSketch *sketchgui)
{
Gui::Selection().clearSelection();
Gui::Selection().rmvSelectionGate();
Gui::Selection().addSelectionGate(new SplittingSelection(sketchgui->getObject()));
setCrosshairCursor("Sketcher_Pointer_Splitting");
}

virtual void mouseMove(Base::Vector2d onSketchPos)
{
Q_UNUSED(onSketchPos);
}

virtual bool pressButton(Base::Vector2d onSketchPos)
{
Q_UNUSED(onSketchPos);
return true;
}

virtual bool releaseButton(Base::Vector2d onSketchPos)
{
int GeoId = sketchgui->getPreselectCurve();
if (GeoId >= 0) {
const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(GeoId);
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()
|| geom->getTypeId() == Part::GeomCircle::getClassTypeId()
|| geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
try {
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Split edge"));
Gui::cmdAppObjectArgs(sketchgui->getObject(), "split(%d,App.Vector(%f,%f,0))",
GeoId, onSketchPos.x, onSketchPos.y);
Gui::Command::commitCommand();
tryAutoRecompute(static_cast<Sketcher::SketchObject *>(sketchgui->getObject()));
}
catch (const Base::Exception& e) {
Base::Console().Error("Failed to split edge: %s\n", e.what());
Gui::Command::abortCommand();
}
}
}
else {
sketchgui->purgeHandler();
}

return true;
}
};

DEF_STD_CMD_A(CmdSketcherSplit)

//TODO: fix the translations for this
CmdSketcherSplit::CmdSketcherSplit()
: Command("Sketcher_Split")
{
sAppModule = "Sketcher";
sGroup = QT_TR_NOOP("Sketcher");
sMenuText = QT_TR_NOOP("Split edge");
sToolTipText = QT_TR_NOOP("Splits an edge into two while preserving constraints");
sWhatsThis = "Sketcher_Split";
sStatusTip = sToolTipText;
sPixmap = "Sketcher_Split";
sAccel = "T,S";
eType = ForEdit;
}

void CmdSketcherSplit::activated(int iMsg)
{
Q_UNUSED(iMsg);
ActivateHandler(getActiveGuiDocument(), new DrawSketchHandlerSplitting());
}

bool CmdSketcherSplit::isActive(void)
{
return isCreateGeoActive(getActiveGuiDocument());
}


namespace SketcherGui {
class ExternalSelection : public Gui::SelectionFilterGate
{
Expand Down Expand Up @@ -7061,6 +7180,7 @@ void CreateSketcherCommandsCreateGeo(void)
//rcCmdMgr.addCommand(new CmdSketcherCreateDraftLine());
rcCmdMgr.addCommand(new CmdSketcherTrimming());
rcCmdMgr.addCommand(new CmdSketcherExtend());
rcCmdMgr.addCommand(new CmdSketcherSplit());
rcCmdMgr.addCommand(new CmdSketcherExternal());
rcCmdMgr.addCommand(new CmdSketcherCarbonCopy());
}
2 changes: 2 additions & 0 deletions src/Mod/Sketcher/Gui/Resources/Sketcher.qrc
Expand Up @@ -161,6 +161,7 @@
<file>icons/geometry/Sketcher_CreateTriangle_Constr.svg</file>
<file>icons/geometry/Sketcher_Extend.svg</file>
<file>icons/geometry/Sketcher_External.svg</file>
<file>icons/geometry/Sketcher_Split.svg</file>
<file>icons/geometry/Sketcher_ToggleConstruction.svg</file>
<file>icons/geometry/Sketcher_Trimming.svg</file>
</qresource>
Expand Down Expand Up @@ -195,6 +196,7 @@
<file>icons/pointers/Sketcher_Pointer_External.svg</file>
<file>icons/pointers/Sketcher_Pointer_Regular_Polygon.svg</file>
<file>icons/pointers/Sketcher_Pointer_Slot.svg</file>
<file>icons/pointers/Sketcher_Pointer_Splitting.svg</file>
<file>icons/pointers/Sketcher_Pointer_Trimming.svg</file>
</qresource>
<qresource>
Expand Down

1 comment on commit 4d6b1f3

@0penBrain
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.