Navigation Menu

Skip to content

Commit

Permalink
Sketcher: new Feature: Group creation of Sketcher geometry and other …
Browse files Browse the repository at this point in the history
…improvements and bug fixes

===============================================================================================

Group creation:
- complex geometries (consisting of several geometry elements and constraints) have been rewritten to use python list (one command call for all geometries and constraints)
- Ellipse ExposeInternalGeo as group creation of geometries and constraints

To construction mode creation:
- addGeometry python and SketchObject functions modified to take an additional optional parameter "construction" to create the geometry/geometries directly as construction.
  In addition to the shorter form, this helps generate less amount of onChange propagation and Redraws.
- all the geometry creation commands in CommandCreateGeo.cpp have been rewritten to use the new construction argument. This includes modifying the regular polygon script to
take a new optional parameter to create geometry as construction in addGeometry.
- special care is taken in group creation not make construction points
- Show/hide internal geometry implemented with this option.

To solving:
- the solve previously included after every geometry addition (when in no Update, e.i. no Recompute mode) has been removed and each Gui::Command calls either an UpdateActive
for recompute or a Solve in no Update mode. This is behaviour is less intrusive and uniform with group creation.

Bug fixes and redrawing reduction:
- Fixes the CheckId exception problem. The solution also helps further remove redraws during creation of complex geometry (e.g. Slot)
- Fixes touching the sketch by only opening it.
- Code clean up.
  • Loading branch information
abdullahtahiriyo authored and wwmayer committed Jun 15, 2015
1 parent 61bd2d4 commit ec5f3b2
Show file tree
Hide file tree
Showing 7 changed files with 236 additions and 319 deletions.
92 changes: 45 additions & 47 deletions src/Mod/Sketcher/App/SketchObject.cpp
Expand Up @@ -51,8 +51,6 @@
#include <Base/Tools.h>
#include <Base/Console.h>

#include <App/Document.h>

#include <Mod/Part/App/Geometry.h>

#include "SketchObject.h"
Expand Down Expand Up @@ -169,21 +167,8 @@ App::DocumentObjectExecReturn *SketchObject::execute(void)
return App::DocumentObject::StdReturn;
}

int SketchObject::hasConflicts(void)
{
// TODO: This must be reviewed to see if we are not setting an already set geometry again (and calculating again)
// it is unclear if we need to know if there are conflicts of an updated geometry that has not been already solved
// or not.

// set up a sketch (including dofs counting and diagnosing of conflicts)
/*lastDoF = solvedSketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
getExternalGeometryCount());
lastHasConflict = solvedSketch.hasConflicts();
lastHasRedundancies = solvedSketch.hasRedundancies();
lastConflicting=solvedSketch.getConflicting();
lastRedundant=solvedSketch.getRedundant();*/

int SketchObject::hasConflicts(void) const
{
if (lastDoF < 0) // over-constrained sketch
return -2;
if (solvedSketch.hasConflicts()) // conflicting constraints
Expand All @@ -192,8 +177,12 @@ int SketchObject::hasConflicts(void)
return 0;
}

int SketchObject::solve()
int SketchObject::solve(bool updateGeoAfterSolving/*=true*/)
{
// if updateGeoAfterSolving=false, the solver information is updated, but the Sketch is nothing
// updated. It is useful to avoid triggering an OnChange when the goeometry did not change but
// the solver needs to be updated.

// We should have an updated Sketcher geometry or this solver should not have happened
// therefore we update our sketch object geometry with the SketchObject one.
//
Expand Down Expand Up @@ -222,7 +211,7 @@ int SketchObject::solve()
lastRedundant=solvedSketch.getRedundant();
lastSolveTime=solvedSketch.SolveTime;

if (err == 0) {
if (err == 0 && updateGeoAfterSolving) {
// set the newly solved geometry
std::vector<Part::Geometry *> geomlist = solvedSketch.extractGeometry();
Geometry.setValues(geomlist);
Expand Down Expand Up @@ -360,7 +349,7 @@ int SketchObject::toggleDriving(int ConstrId)
return 0;
}

int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative, bool updateGeometry)
int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative, bool updateGeoBeforeMoving)
{
// if we are moving a point at SketchObject level, we need to start from a solved sketch
// if we have conflicts we can forget about moving. However, there is the possibility that we
Expand All @@ -370,7 +359,7 @@ int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toP
// of SketchObject upon moving. => use updateGeometry parameter = true then


if(updateGeometry || solverNeedsUpdate) {
if(updateGeoBeforeMoving || solverNeedsUpdate) {
lastDoF = solvedSketch.setUpSketch(getCompleteGeometry(), Constraints.getValues(),
getExternalGeometryCount());

Expand Down Expand Up @@ -493,38 +482,39 @@ void SketchObject::acceptGeometry()
rebuildVertexIndex();
}

int SketchObject::addGeometry(const std::vector<Part::Geometry *> &geoList)
int SketchObject::addGeometry(const std::vector<Part::Geometry *> &geoList, bool construction/*=false*/)
{
const std::vector< Part::Geometry * > &vals = getInternalGeometry();

std::vector< Part::Geometry * > newVals(vals);
for (std::vector<Part::Geometry *>::const_iterator it = geoList.begin(); it != geoList.end(); ++it) {
if((*it)->getTypeId() != Part::GeomPoint::getClassTypeId())
const_cast<Part::Geometry *>(*it)->Construction = construction;

newVals.push_back(*it);
}
Geometry.setValues(newVals);
Constraints.acceptGeometry(getCompleteGeometry());
rebuildVertexIndex();

if(noRecomputes) // if we do not have a recompute after the geometry creation, the sketch must be solved to update the DoF of the solver
solve();

return Geometry.getSize()-1;
}

int SketchObject::addGeometry(const Part::Geometry *geo)
int SketchObject::addGeometry(const Part::Geometry *geo, bool construction/*=false*/)
{
const std::vector< Part::Geometry * > &vals = getInternalGeometry();

std::vector< Part::Geometry * > newVals(vals);
Part::Geometry *geoNew = geo->clone();

if(geoNew->getTypeId() != Part::GeomPoint::getClassTypeId())
geoNew->Construction = construction;

newVals.push_back(geoNew);
Geometry.setValues(newVals);
Constraints.acceptGeometry(getCompleteGeometry());
delete geoNew;
rebuildVertexIndex();

if(noRecomputes) // if we do not have a recompute after the geometry creation, the sketch must be solved to update the DoF of the solver
solve();

return Geometry.getSize()-1;
}
Expand Down Expand Up @@ -1645,6 +1635,9 @@ int SketchObject::ExposeInternalGeometry(int GeoId)
double minord;
Base::Vector3d majdir;

std::vector<Part::Geometry *> igeo;
std::vector<Constraint *> icon;

if(geo->getTypeId() == Part::GeomEllipse::getClassTypeId()){
const Part::GeomEllipse *ellipse = static_cast<const Part::GeomEllipse *>(geo);

Expand Down Expand Up @@ -1679,45 +1672,39 @@ int SketchObject::ExposeInternalGeometry(int GeoId)
Part::GeomLineSegment *lmajor = new Part::GeomLineSegment();
lmajor->setPoints(majorpositiveend,majornegativeend);

this->addGeometry(lmajor); // create line for major axis
this->setConstruction(currentgeoid+incrgeo+1,true);
delete lmajor;
igeo.push_back(lmajor);

Sketcher::Constraint *newConstr = new Sketcher::Constraint();
newConstr->Type = Sketcher::InternalAlignment;
newConstr->AlignmentType = EllipseMajorDiameter;
newConstr->First = currentgeoid+incrgeo+1;
newConstr->Second = GeoId;

addConstraint(newConstr);
delete newConstr;
icon.push_back(newConstr);
incrgeo++;
}
if(!minor)
{
Part::GeomLineSegment *lminor = new Part::GeomLineSegment();
lminor->setPoints(minorpositiveend,minornegativeend);

this->addGeometry(lminor); // create line for major axis
this->setConstruction(currentgeoid+incrgeo+1,true);
delete lminor;
igeo.push_back(lminor);

Sketcher::Constraint *newConstr = new Sketcher::Constraint();
newConstr->Type = Sketcher::InternalAlignment;
newConstr->AlignmentType = EllipseMinorDiameter;
newConstr->First = currentgeoid+incrgeo+1;
newConstr->Second = GeoId;

addConstraint(newConstr);
delete newConstr;
icon.push_back(newConstr);
incrgeo++;
}
if(!focus1)
{
Part::GeomPoint *pf1 = new Part::GeomPoint();
pf1->setPoint(focus1P);
this->addGeometry(pf1);
delete pf1;

igeo.push_back(pf1);

Sketcher::Constraint *newConstr = new Sketcher::Constraint();
newConstr->Type = Sketcher::InternalAlignment;
Expand All @@ -1726,16 +1713,14 @@ int SketchObject::ExposeInternalGeometry(int GeoId)
newConstr->FirstPos = Sketcher::start;
newConstr->Second = GeoId;

addConstraint(newConstr);
delete newConstr;
icon.push_back(newConstr);
incrgeo++;
}
if(!focus2)
{
Part::GeomPoint *pf2 = new Part::GeomPoint();
pf2->setPoint(focus2P);
this->addGeometry(pf2);
delete pf2;
igeo.push_back(pf2);

Sketcher::Constraint *newConstr = new Sketcher::Constraint();
newConstr->Type = Sketcher::InternalAlignment;
Expand All @@ -1744,10 +1729,23 @@ int SketchObject::ExposeInternalGeometry(int GeoId)
newConstr->FirstPos = Sketcher::start;
newConstr->Second = GeoId;

addConstraint(newConstr);
delete newConstr;
icon.push_back(newConstr);
}

this->addGeometry(igeo,true);
this->addConstraints(icon);

for (std::vector<Part::Geometry *>::iterator it=igeo.begin(); it != igeo.end(); ++it)
if (*it)
delete *it;

for (std::vector<Constraint *>::iterator it=icon.begin(); it != icon.end(); ++it)
if (*it)
delete *it;

icon.clear();
igeo.clear();

return incrgeo; //number of added elements
}
else
Expand Down
20 changes: 11 additions & 9 deletions src/Mod/Sketcher/App/SketchObject.h
Expand Up @@ -51,7 +51,7 @@ class SketcherExport SketchObject : public Part::Part2DObject
App ::PropertyLinkSubList ExternalGeometry;
/** @name methods overide Feature */
//@{
/// recalculate the Feature (if no recompute is needed see also solve() and updateSolverGeometry() )
/// recalculate the Feature (if no recompute is needed see also solve() and solverNeedsUpdate boolean)
App::DocumentObjectExecReturn *execute(void);

/// returns the type name of the ViewProvider
Expand All @@ -66,14 +66,15 @@ class SketcherExport SketchObject : public Part::Part2DObject
it is just less efficient.
This flag does not regulate whether this object will recompute or not if execute() or a recompute() is actually executed,
it just regulates whether the solver is called upon geometry addition or not (relies on the solve of execute for the calculation)
it just regulates whether the solver is called or not (i.e. whether it relies on
the solve of execute for the calculation)
*/
bool noRecomputes;

/// add unspecified geometry
int addGeometry(const Part::Geometry *geo);
int addGeometry(const Part::Geometry *geo, bool construction=false);
/// add unspecified geometry
int addGeometry(const std::vector<Part::Geometry *> &geoList);
int addGeometry(const std::vector<Part::Geometry *> &geoList, bool construction=false);
/// delete geometry
int delGeometry(int GeoId);
/// add all constraints in the list
Expand Down Expand Up @@ -116,13 +117,14 @@ class SketcherExport SketchObject : public Part::Part2DObject
std::vector<Part::Geometry*> getCompleteGeometry(void) const;

/// returns non zero if the sketch contains conflicting constraints
int hasConflicts(void);
int hasConflicts(void) const;

/** solves the sketch and updates the geometry, but not all the dependent features (does not recompute)
When a recompute is necessary, recompute triggers execute() which solves the sketch and updates all dependent features
When a solve only is necessary (e.g. DoF changed), solve() solves the sketch and updates the geometry, but does not trigger any updates
When a solve only is necessary (e.g. DoF changed), solve() solves the sketch and
updates the geometry (if updateGeoAfterSolving==true), but does not trigger any updates
*/
int solve();
int solve(bool updateGeoAfterSolving=true);
/// set the datum of a Distance or Angle constraint and solve
int setDatum(int ConstrId, double Datum);
/// set the driving status of this constraint and solve
Expand All @@ -132,7 +134,7 @@ class SketcherExport SketchObject : public Part::Part2DObject
/// toggle the driving status of this constraint
int toggleDriving(int ConstrId);
/// move this point to a new location and solve
int movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative=false, bool updateGeometry=false);
int movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative=false, bool updateGeoBeforeMoving=false);
/// retrieves the coordinates of a point
Base::Vector3d getPoint(int GeoId, PointPos PosId) const;

Expand Down Expand Up @@ -227,7 +229,7 @@ class SketcherExport SketchObject : public Part::Part2DObject
/// get called by the container when a property has changed
virtual void onChanged(const App::Property* /*prop*/);
virtual void onDocumentRestored();

private:
std::vector<Part::Geometry *> ExternalGeo;

Expand Down
24 changes: 17 additions & 7 deletions src/Mod/Sketcher/App/SketchObjectPyImp.cpp
Expand Up @@ -64,9 +64,19 @@ PyObject* SketchObjectPy::solve(PyObject *args)

PyObject* SketchObjectPy::addGeometry(PyObject *args)
{
PyObject *pcObj;
if (!PyArg_ParseTuple(args, "O", &pcObj))
return 0;
PyObject *pcObj;
PyObject* construction; // this is an optional argument default false
bool isConstruction;
if (!PyArg_ParseTuple(args, "OO!", &pcObj, &PyBool_Type, &construction)) {
PyErr_Clear();
if (!PyArg_ParseTuple(args, "O", &pcObj))
return 0;
else
isConstruction=false;
}
else {
isConstruction = PyObject_IsTrue(construction) ? true : false;
}

if (PyObject_TypeCheck(pcObj, &(Part::GeometryPy::Type))) {
Part::Geometry *geo = static_cast<Part::GeometryPy*>(pcObj)->getGeometryPtr();
Expand All @@ -80,13 +90,13 @@ PyObject* SketchObjectPy::addGeometry(PyObject *args)
// create the definition struct for that geom
Part::GeomArcOfCircle aoc;
aoc.setHandle(trim);
ret = this->getSketchObjectPtr()->addGeometry(&aoc);
ret = this->getSketchObjectPtr()->addGeometry(&aoc,isConstruction);
}
else if (!ellipse.IsNull()) {
// create the definition struct for that geom
Part::GeomArcOfEllipse aoe;
aoe.setHandle(trim);
ret = this->getSketchObjectPtr()->addGeometry(&aoe);
ret = this->getSketchObjectPtr()->addGeometry(&aoe,isConstruction);
}
else {
std::stringstream str;
Expand All @@ -101,7 +111,7 @@ PyObject* SketchObjectPy::addGeometry(PyObject *args)
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ||
geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
ret = this->getSketchObjectPtr()->addGeometry(geo);
ret = this->getSketchObjectPtr()->addGeometry(geo,isConstruction);
}
else {
std::stringstream str;
Expand Down Expand Up @@ -163,7 +173,7 @@ PyObject* SketchObjectPy::addGeometry(PyObject *args)
}
}

int ret = this->getSketchObjectPtr()->addGeometry(geoList) + 1;
int ret = this->getSketchObjectPtr()->addGeometry(geoList,isConstruction) + 1;
std::size_t numGeo = geoList.size();
Py::Tuple tuple(numGeo);
for (std::size_t i=0; i<numGeo; ++i) {
Expand Down

0 comments on commit ec5f3b2

Please sign in to comment.