diff --git a/src/Mod/Sketcher/App/SketchObjectPy.xml b/src/Mod/Sketcher/App/SketchObjectPy.xml
index e8e9baf0ca..85f6374987 100644
--- a/src/Mod/Sketcher/App/SketchObjectPy.xml
+++ b/src/Mod/Sketcher/App/SketchObjectPy.xml
@@ -272,7 +272,106 @@
+
+
+
+ Automatic sketch constraining algorithm.
+
+
+
+
+
+
+ Detects Missing Point On Point Constraints. The Detect step just identifies possible missing constraints.
+ The result may be retrieved or applied using the corresponding Get / Make methods.
+
+
+
+
+
+
+ Analyses the already detected Missing Point On Point Constraints to detect endpoint tagency/perpendicular.
+ The result may be retrieved or applied using the corresponding Get / Make methods.
+
+
+
+
+
+
+ Detects Missing Horizontal/Vertical Constraints. The Detect step just identifies possible missing constraints.
+ The result may be retrieved or applied using the corresponding Get / Make methods.
+
+
+
+
+
+
+ Detects Missing Equality Constraints. The Detect step just identifies possible missing constraints.
+ The result may be retrieved or applied using the corresponding Get / Make methods.
+
+
+
+
+
+
+ Applies the detected / set Point On Point coincident constraints. If the argument is True, then solving and redundant removal is done after each individual addition.
+
+
+
+
+
+
+ Applies the detected / set Vertical/Horizontal constraints. If the argument is True, then solving and redundant removal is done after each individual addition.
+
+
+
+
+
+
+ Applies the detected / set Equality constraints. If the argument is True, then solving and redundant removal is done after each individual addition.
+
+
+
+
+
+
+ Removes constraints currently detected as redundant by the solver. If the argument is True, then the geometry is updated after solving.
+
+
+
+
+
+
+ returns a list of (First FirstPos Second SecondPos Type) tuples with all the detected endpoint constraints.
+
+
+
+
+
+
+
+ returns a list of (First FirstPos Second SecondPos Type) tuples with all the detected vertical/horizontal constraints.
+
+
+
+
+
+
+
+ returns a list of (First FirstPos Second SecondPos) tuples with all the detected line segment equality constraints.
+
+
+
+
+
+
+
+ returns a list of (First FirstPos Second SecondPos) tuples with all the detected radius constraints.
+
+
+
+
Number of Constraints in this sketch
diff --git a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp
index 160c9aaa1d..f2bbc34338 100644
--- a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp
+++ b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp
@@ -1276,6 +1276,279 @@ PyObject* SketchObjectPy::modifyBSplineKnotMultiplicity(PyObject *args)
Py_Return;
}
+PyObject* SketchObjectPy::autoconstraint(PyObject *args)
+{
+ double precision = Precision::Confusion() * 1000;
+ double angleprecision = M_PI/8;
+ PyObject* includeconstruction = Py_True;
+
+
+ if (!PyArg_ParseTuple(args, "|ddO!", &precision, &angleprecision, &PyBool_Type, &includeconstruction))
+ return 0;
+
+ if (this->getSketchObjectPtr()->autoConstraint(precision, angleprecision, PyObject_IsTrue(includeconstruction) ? true : false)) {
+ std::stringstream str;
+ str << "Unable to autoconstraint";
+ PyErr_SetString(PyExc_ValueError, str.str().c_str());
+ return 0;
+ }
+
+ Py_Return;
+}
+
+PyObject* SketchObjectPy::detectMissingPointOnPointConstraints(PyObject *args)
+{
+ double precision = Precision::Confusion() * 1000;
+ PyObject* includeconstruction = Py_True;
+
+ if (!PyArg_ParseTuple(args, "|dO!", &precision, &PyBool_Type, &includeconstruction))
+ return 0;
+
+ return Py::new_reference_to(Py::Long(this->getSketchObjectPtr()->detectMissingPointOnPointConstraints(precision, PyObject_IsTrue(includeconstruction) ? true : false)));
+}
+
+PyObject* SketchObjectPy::detectMissingVerticalHorizontalConstraints(PyObject *args)
+{
+ double angleprecision = M_PI/8;
+
+ if (!PyArg_ParseTuple(args, "|d", &angleprecision))
+ return 0;
+
+ return Py::new_reference_to(Py::Long(this->getSketchObjectPtr()->detectMissingVerticalHorizontalConstraints(angleprecision)));
+}
+
+PyObject* SketchObjectPy::detectMissingEqualityConstraints(PyObject *args)
+{
+ double precision = Precision::Confusion() * 1000;
+
+ if (!PyArg_ParseTuple(args, "|d", &precision))
+ return 0;
+
+ return Py::new_reference_to(Py::Long(this->getSketchObjectPtr()->detectMissingEqualityConstraints(precision)));
+}
+
+PyObject* SketchObjectPy::analyseMissingPointOnPointCoincident(PyObject *args)
+{
+ double angleprecision = M_PI/8;
+
+ if (!PyArg_ParseTuple(args, "|d", &angleprecision))
+ return 0;
+
+ this->getSketchObjectPtr()->analyseMissingPointOnPointCoincident(angleprecision);
+
+ Py_Return;
+}
+
+PyObject* SketchObjectPy::makeMissingPointOnPointCoincident(PyObject *args)
+{
+
+ PyObject* onebyone = Py_False;
+
+ if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &onebyone))
+ return 0;
+
+ this->getSketchObjectPtr()->makeMissingPointOnPointCoincident(PyObject_IsTrue(onebyone) ? true : false);
+
+ Py_Return;
+}
+
+PyObject* SketchObjectPy::makeMissingVerticalHorizontal(PyObject *args)
+{
+ PyObject* onebyone = Py_False;
+
+ if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &onebyone))
+ return 0;
+
+ this->getSketchObjectPtr()->makeMissingVerticalHorizontal(PyObject_IsTrue(onebyone) ? true : false);
+
+ Py_Return;
+}
+
+PyObject* SketchObjectPy::makeMissingEquality(PyObject *args)
+{
+ PyObject* onebyone = Py_True;
+
+ if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &onebyone))
+ return 0;
+
+ this->getSketchObjectPtr()->makeMissingEquality(PyObject_IsTrue(onebyone) ? true : false);
+
+ Py_Return;
+}
+
+PyObject* SketchObjectPy::autoRemoveRedundants(PyObject *args)
+{
+ PyObject* updategeo = Py_True;
+
+ if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &updategeo))
+ return 0;
+
+ this->getSketchObjectPtr()->autoRemoveRedundants(PyObject_IsTrue(updategeo) ? true : false);
+
+ Py_Return;
+}
+
+Py::List SketchObjectPy::getMissingPointOnPointConstraints(void) const
+{
+ std::vector constraints = this->getSketchObjectPtr()->getMissingPointOnPointConstraints();
+
+ Py::List list;
+ for (auto c : constraints) {
+ Py::Tuple t(5);
+ t.setItem(0, Py::Long(c.First));
+ t.setItem(1, Py::Long(((c.FirstPos == Sketcher::none)?0:(c.FirstPos == Sketcher::start)?1:(c.FirstPos == Sketcher::end)?2:3)));
+ t.setItem(2, Py::Long(c.Second));
+ t.setItem(3, Py::Long(((c.SecondPos == Sketcher::none)?0:(c.SecondPos == Sketcher::start)?1:(c.SecondPos == Sketcher::end)?2:3)));
+ t.setItem(4, Py::Long(c.Type));
+ list.append(t);
+ }
+ return list;
+}
+
+void SketchObjectPy::setMissingPointOnPointConstraints(Py::List arg)
+{
+ std::vector constraints;
+
+ auto checkpos = [](Py::Tuple &t,int i) {
+ auto checkitem = [](Py::Tuple &t,int i, int val) {return long(Py::Long(t.getItem(i)))==val;};
+ return (checkitem(t,i,0)?Sketcher::none:(checkitem(t,i,1)?Sketcher::start:(checkitem(t,i,2)?Sketcher::end:Sketcher::mid)));
+ };
+
+ for (auto ti : arg) {
+ Py::Tuple t(ti);
+ ConstraintIds c;
+ c.First = (long)Py::Long(t.getItem(0));
+ c.FirstPos = checkpos(t,1);
+ c.Second = (long)Py::Long(t.getItem(2));
+ c.SecondPos = checkpos(t,3);
+ c.Type = (Sketcher::ConstraintType)(long)Py::Long(t.getItem(4));
+
+ constraints.push_back(c);
+ }
+
+ this->getSketchObjectPtr()->setMissingPointOnPointConstraints(constraints);
+}
+
+Py::List SketchObjectPy::getMissingVerticalHorizontalConstraints(void) const
+{
+ std::vector constraints = this->getSketchObjectPtr()->getMissingVerticalHorizontalConstraints();
+
+ Py::List list;
+ for (auto c : constraints) {
+ Py::Tuple t(5);
+ t.setItem(0, Py::Long(c.First));
+ t.setItem(1, Py::Long(((c.FirstPos == Sketcher::none)?0:(c.FirstPos == Sketcher::start)?1:(c.FirstPos == Sketcher::end)?2:3)));
+ t.setItem(2, Py::Long(c.Second));
+ t.setItem(3, Py::Long(((c.SecondPos == Sketcher::none)?0:(c.SecondPos == Sketcher::start)?1:(c.SecondPos == Sketcher::end)?2:3)));
+ t.setItem(4, Py::Long(c.Type));
+ list.append(t);
+ }
+ return list;
+}
+
+void SketchObjectPy::setMissingVerticalHorizontalConstraints(Py::List arg)
+{
+ std::vector constraints;
+
+ auto checkpos = [](Py::Tuple &t,int i) {
+ auto checkitem = [](Py::Tuple &t,int i, int val) {return long(Py::Long(t.getItem(i)))==val;};
+ return (checkitem(t,i,0)?Sketcher::none:(checkitem(t,i,1)?Sketcher::start:(checkitem(t,i,2)?Sketcher::end:Sketcher::mid)));
+ };
+
+ for (auto ti : arg) {
+ Py::Tuple t(ti);
+ ConstraintIds c;
+ c.First = (long)Py::Long(t.getItem(0));
+ c.FirstPos = checkpos(t,1);
+ c.Second = (long)Py::Long(t.getItem(2));
+ c.SecondPos = checkpos(t,3);
+ c.Type = (Sketcher::ConstraintType)(long)Py::Long(t.getItem(4));
+
+ constraints.push_back(c);
+ }
+
+ this->getSketchObjectPtr()->setMissingVerticalHorizontalConstraints(constraints);
+}
+
+Py::List SketchObjectPy::getMissingLineEqualityConstraints(void) const
+{
+ std::vector constraints = this->getSketchObjectPtr()->getMissingLineEqualityConstraints();
+
+ Py::List list;
+ for (auto c : constraints) {
+ Py::Tuple t(4);
+ t.setItem(0, Py::Long(c.First));
+ t.setItem(1, Py::Long(((c.FirstPos == Sketcher::none)?0:(c.FirstPos == Sketcher::start)?1:(c.FirstPos == Sketcher::end)?2:3)));
+ t.setItem(2, Py::Long(c.Second));
+ t.setItem(3, Py::Long(((c.SecondPos == Sketcher::none)?0:(c.SecondPos == Sketcher::start)?1:(c.SecondPos == Sketcher::end)?2:3)));
+ list.append(t);
+ }
+ return list;
+}
+
+void SketchObjectPy::setMissingLineEqualityConstraints(Py::List arg)
+{
+ std::vector constraints;
+
+ auto checkpos = [](Py::Tuple &t,int i) {
+ auto checkitem = [](Py::Tuple &t,int i, int val) {return long(Py::Long(t.getItem(i)))==val;};
+ return (checkitem(t,i,0)?Sketcher::none:(checkitem(t,i,1)?Sketcher::start:(checkitem(t,i,2)?Sketcher::end:Sketcher::mid)));
+ };
+
+ for (auto ti : arg) {
+ Py::Tuple t(ti);
+ ConstraintIds c;
+ c.First = (long)Py::Long(t.getItem(0));
+ c.FirstPos = checkpos(t,1);
+ c.Second = (long)Py::Long(t.getItem(2));
+ c.SecondPos = checkpos(t,3);
+ c.Type = Sketcher::Equal;
+
+ constraints.push_back(c);
+ }
+
+ this->getSketchObjectPtr()->setMissingLineEqualityConstraints(constraints);
+}
+
+Py::List SketchObjectPy::getMissingRadiusConstraints(void) const
+{
+ std::vector constraints = this->getSketchObjectPtr()->getMissingRadiusConstraints();
+
+ Py::List list;
+ for (auto c : constraints) {
+ Py::Tuple t(4);
+ t.setItem(0, Py::Long(c.First));
+ t.setItem(1, Py::Long(((c.FirstPos == Sketcher::none)?0:(c.FirstPos == Sketcher::start)?1:(c.FirstPos == Sketcher::end)?2:3)));
+ t.setItem(2, Py::Long(c.Second));
+ t.setItem(3, Py::Long(((c.SecondPos == Sketcher::none)?0:(c.SecondPos == Sketcher::start)?1:(c.SecondPos == Sketcher::end)?2:3)));
+ list.append(t);
+ }
+ return list;
+}
+
+void SketchObjectPy::setMissingRadiusConstraints(Py::List arg)
+{
+ std::vector constraints;
+
+ auto checkpos = [](Py::Tuple &t,int i) {
+ auto checkitem = [](Py::Tuple &t,int i, int val) {return long(Py::Long(t.getItem(i)))==val;};
+ return (checkitem(t,i,0)?Sketcher::none:(checkitem(t,i,1)?Sketcher::start:(checkitem(t,i,2)?Sketcher::end:Sketcher::mid)));
+ };
+
+ for (auto ti : arg) {
+ Py::Tuple t(ti);
+ ConstraintIds c;
+ c.First = (long)Py::Long(t.getItem(0));
+ c.FirstPos = checkpos(t,1);
+ c.Second = (long)Py::Long(t.getItem(2));
+ c.SecondPos = checkpos(t,3);
+ c.Type = Sketcher::Equal;
+
+ constraints.push_back(c);
+ }
+
+ this->getSketchObjectPtr()->setMissingRadiusConstraints(constraints);
+}
PyObject* SketchObjectPy::getGeometryWithDependentParameters(PyObject *args)
{