While trying to resolve issue #2735 I hit a roadblock in the form of a question regarding the angle constraint. It appears that every constraint has a set of GeoId properties that indicate the feature(s) that are constrained, which are accessible from python, and a set of PosId properties that indicate the specific points, if any, on those features that are constrained, which are kept at C++ level. The PosId properties make sense for some constraints, like distance and coincident. But what do they mean for Angle constraints?
Angles make sense only for a pair of lines or line segments, but the FirstPosId and SecondPosID properties are still not set to None, which is probably a better option. However, they might also indicate the direction of the line wrt which the angle should be computed: if the angle is "A" between lines "l " and "m", it is (pi - A) between "l" and "-m". I can't find any documentation that tells what it means, so I'm asking it here.
[Sketcher] [C++] Issue 0002735, and Meaning of PosIDs in Angle constraint?
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
Re: [Sketcher] [C++] Issue 0002735, and Meaning of PosIDs in Angle constraint?
Hi!
I am not sure if I am replying to what you are asking. Anyway:
GeoId is the identifier of a geometric object. There are a maximum of 3 GeoIds used within a Constraint (so a constraint can maximally involve 3 different objects):
PosId is a subidentifier within a geometric object. This is generally used to indicate the edge (none), starting point, ending point and mid point. Not all geometric objects have starting point, end point or midpoint. It is defined in Constraint.h as:
There are two types of angle constraints, the normal angle constraint, which defines two edges (so PosId=none) and the one implemented via "AngleViaPoint" (courtesy of DeepSOIC), which is defined by three points (those three points that you see in an angle, endpoints and vertex) and has an autolocking mechanism that substantially avoids the angle from flipping when dragging the whole (or during solving). For this second one, you define three points so PosId!=none for all three elements.
If you want to check this, open the sketcher, select a first point defining an endpoint, a second point defining another endpoint and a third point being the vertex where it hinges.
If you are curious about the code, the angle constraint creation code is in CommandConstraints.cpp, a excerpt:
Regards,
Abdullah
I am not sure if I am replying to what you are asking. Anyway:
GeoId is the identifier of a geometric object. There are a maximum of 3 GeoIds used within a Constraint (so a constraint can maximally involve 3 different objects):
Code: Select all
class SketcherExport Constraint : public Base::Persistence
{
TYPESYSTEM_HEADER();
public:
Constraint();
Constraint(const Constraint&);
virtual ~Constraint();
virtual Constraint *clone(void) const; // does copy the tag, it will be treated as a rename by the expression engine.
virtual Constraint *copy(void) const; // does not copy the tag, but generates a new one
static const int GeoUndef;
// from base class
virtual unsigned int getMemSize(void) const;
virtual void Save(Base::Writer &/*writer*/) const;
virtual void Restore(Base::XMLReader &/*reader*/);
virtual PyObject *getPyObject(void);
void setValue(double newValue);
Base::Quantity getPresentationValue() const;
double getValue() const;
friend class Sketch;
friend class PropertyConstraintList;
private:
double Value;
public:
ConstraintType Type;
InternalAlignmentType AlignmentType;
std::string Name;
int First;
PointPos FirstPos;
int Second;
PointPos SecondPos;
int Third;
PointPos ThirdPos;
float LabelDistance;
float LabelPosition;
bool isDriving;
protected:
boost::uuids::uuid tag;
};
Code: Select all
/// define if you want to use the end or start point
enum PointPos { none, start, end, mid };
If you want to check this, open the sketcher, select a first point defining an endpoint, a second point defining another endpoint and a third point being the vertex where it hinges.
If you are curious about the code, the angle constraint creation code is in CommandConstraints.cpp, a excerpt:
Code: Select all
if (SubNames.size() == 3){//standalone implementation of angle-via-point
//let's sink the point to be GeoId3. We want to keep the order the two curves have been selected in.
if ( isVertex(GeoId1, PosId1) ){
std::swap(GeoId1,GeoId2);
std::swap(PosId1,PosId2);
};
if ( isVertex(GeoId2, PosId2) ){
std::swap(GeoId2,GeoId3);
std::swap(PosId2,PosId3);
};
bool bothexternal=checkBothExternal(GeoId1, GeoId2);
if (isEdge(GeoId1, PosId1) && isEdge(GeoId2, PosId2) && isVertex(GeoId3, PosId3)) {
double ActAngle = 0.0;
openCommand("Add angle constraint");
//add missing point-on-object constraints
if(! IsPointAlreadyOnCurve(GeoId1, GeoId3, PosId3, Obj)){
Gui::Command::doCommand(
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('PointOnObject',%d,%d,%d)) ",
selection[0].getFeatName(),GeoId3,PosId3,GeoId1);
};
if(! IsPointAlreadyOnCurve(GeoId2, GeoId3, PosId3, Obj)){
Gui::Command::doCommand(
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('PointOnObject',%d,%d,%d)) ",
selection[0].getFeatName(),GeoId3,PosId3,GeoId2);
};
if(! IsPointAlreadyOnCurve(GeoId1, GeoId3, PosId3, Obj)){//FIXME: it's a good idea to add a check if the sketch is solved
Gui::Command::doCommand(
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('PointOnObject',%d,%d,%d)) ",
selection[0].getFeatName(),GeoId3,PosId3,GeoId1);
};
//assuming point-on-curves have been solved, calculate the angle.
//DeepSOIC: this may be slow, but I wanted to reuse the conversion from Geometry to GCS shapes that is done in Sketch
Base::Vector3d p = Obj->getPoint(GeoId3, PosId3 );
ActAngle = Obj->calculateAngleViaPoint(GeoId1,GeoId2,p.x,p.y);
//negative constraint value avoidance
if (ActAngle < -Precision::Angular()){
std::swap(GeoId1, GeoId2);
std::swap(PosId1, PosId2);
ActAngle = -ActAngle;
}
Gui::Command::doCommand(
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('AngleViaPoint',%d,%d,%d,%d,%f)) ",
selection[0].getFeatName(),GeoId1,GeoId2,GeoId3,PosId3,ActAngle);
if (bothexternal || constraintCreationMode==Reference) { // it is a constraint on a external line, make it non-driving
const std::vector<Sketcher::Constraint *> &ConStr = Obj->Constraints.getValues();
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)",
selection[0].getFeatName(),ConStr.size()-1,"False");
finishDistanceConstraint(this, Obj,false);
}
else
finishDistanceConstraint(this, Obj,true);
return;
};
}
Abdullah
Re: [Sketcher] [C++] Issue 0002735, and Meaning of PosIDs in Angle constraint?
Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs