#include <SketchPlugin_Line.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_ConstraintTangent.h>
+#include <SketchPlugin_ConstraintPerpendicular.h>
#include <BRepExtrema_ExtPC.hxx>
#include <TopoDS_Vertex.hxx>
#include <TColGeom_SequenceOfCurve.hxx>
#include <gp_Dir.hxx>
+#include <array>
+
static SketcherPrs_PositionMgr* MyPosMgr = NULL;
+#define PI 3.1415926535897932
+
// The class is implemented as a singlton
SketcherPrs_PositionMgr* SketcherPrs_PositionMgr::get()
{
}
+bool SketcherPrs_PositionMgr::isPntConstraint(const std::string& theName)
+{
+ static std::list<std::string> aConstraints;
+ if (aConstraints.size() == 0) {
+ aConstraints.push_back(SketchPlugin_ConstraintTangent::ID());
+ aConstraints.push_back(SketchPlugin_ConstraintPerpendicular::ID());
+ }
+ std::list<std::string>::const_iterator aIt;
+ for (aIt = aConstraints.cbegin(); aIt != aConstraints.cend(); ++aIt) {
+ if ((*aIt) == theName)
+ return true;
+ }
+ return false;
+}
+
+bool containsPoint(const FeaturePtr& theFeature, GeomPnt2dPtr thePnt2d, GeomPointPtr thePos)
+{
+ if (theFeature->getKind() == SketchPlugin_Line::ID()) {
+ AttributePoint2DPtr aSPnt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->data()->attribute(SketchPlugin_Line::START_ID()));
+ AttributePoint2DPtr aSPnt2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->data()->attribute(SketchPlugin_Line::END_ID()));
+
+ GeomPnt2dPtr aPnt1 = aSPnt1->pnt();
+ GeomPnt2dPtr aPnt2 = aSPnt2->pnt();
+
+ if (aPnt1->isEqual(thePnt2d) || aPnt2->isEqual(thePnt2d))
+ return true;
+ } else if ((theFeature->getKind() == SketchPlugin_Circle::ID()) ||
+ (theFeature->getKind() == SketchPlugin_Arc::ID())) {
+ GeomCurvePtr aCurve;
+ ObjectPtr aResObj;
+ std::list<ResultPtr> aResults = theFeature->results();
+ std::list<ResultPtr>::const_iterator aIt;
+ for (aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) {
+ GeomShapePtr aShp = SketcherPrs_Tools::getShape((*aIt));
+ if (aShp->isEdge()) {
+ aResObj = (*aIt);
+ aCurve = std::shared_ptr<GeomAPI_Curve>(new GeomAPI_Curve(aShp));
+ break;
+ }
+ }
+ if (aCurve.get()) {
+ double aStart = aCurve->startParam();
+ double aEnd = aCurve->endParam();
+ GeomCirclePtr aCircle = GeomCirclePtr(new GeomAPI_Circ(aCurve));
+ double aParam;
+ if (aCircle->parameter(thePos, 1.e-4, aParam) && (aParam >= aStart) && (aParam <= aEnd))
+ return true;
+ }
+ }
+ return false;
+}
+
+int SketcherPrs_PositionMgr::getPositionIndex(GeomPointPtr thePos, const SketcherPrs_SymbolPrs* thePrs)
+{
+ if (myPntShapes.count(thePrs->feature()) == 0) {
+ // Renumerate positions around the specified constraint point for all constraints
+ GeomAx3Ptr aAx3 = thePrs->plane();
+ ModelAPI_CompositeFeature* aOwner = thePrs->sketcher();
+ GeomPnt2dPtr aPnt2d = thePos->to2D(aAx3->origin(), aAx3->dirX(), aAx3->dirY());
+
+ int aNbSubs = aOwner->numberOfSubs();
+ int aId = 0;
+ for (int i = 0; i < aNbSubs; i++) {
+ FeaturePtr aFeature = aOwner->subFeature(i);
+
+ if (myPntShapes.count(aFeature.get()) == 1) {
+ myPntShapes[aFeature.get()] = aId;
+ aId++;
+ } else {
+ if (isPntConstraint(aFeature->getKind())) {
+ DataPtr aData = aFeature->data();
+ AttributeRefAttrPtr aObjRef = aData->refattr(SketchPlugin_Constraint::ENTITY_A());
+ FeaturePtr aObj = ModelAPI_Feature::feature(aObjRef->object());
+ bool aContains = false;
+ if (containsPoint(aObj, aPnt2d, thePos)) {
+ aContains = true;
+ } else {
+ aObjRef = aData->refattr(SketchPlugin_Constraint::ENTITY_B());
+ aObj = ModelAPI_Feature::feature(aObjRef->object());
+ if (containsPoint(aObj, aPnt2d, thePos)) {
+ aContains = true;
+ }
+ }
+ if (aContains) {
+ myPntShapes[aFeature.get()] = aId;
+ aId++;
+ }
+ }
+ }
+ }
+ }
+ return myPntShapes[thePrs->feature()];
+}
+
+
gp_Vec getVector(ObjectPtr theShape, GeomDirPtr theDir, gp_Pnt theP)
{
gp_Vec aVec;
}
}
} else {
- double aMidParam = (aCurve->startParam() + aCurve->endParam()) / 2.;
- GeomPointPtr aPnt1 = aCurve->getPoint((aMidParam + aCurve->endParam()) / 2.);
- GeomPointPtr aPnt2 = aCurve->getPoint((aMidParam + aCurve->startParam()) / 2.);
+ GeomPointPtr aPnt1 = aCurve->getPoint(aCurve->endParam());
+ GeomPointPtr aPnt2 = aCurve->getPoint(aCurve->startParam());
gp_Pnt aPn2 = aPnt2->impl<gp_Pnt>();
if (aPn2.IsEqual(theP, Precision::Confusion()))
int aNbSubs = aOwner->numberOfSubs();
for (int i = 0; i < aNbSubs; i++) {
FeaturePtr aFeature = aOwner->subFeature(i);
+ if (!aFeature->firstResult().get()) // There is no result
+ continue;
+
if (aFeature->getKind() == SketchPlugin_Line::ID()) {
AttributePoint2DPtr aSPnt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
aFeature->data()->attribute(SketchPlugin_Line::START_ID()));
ObjectPtr theLine, const SketcherPrs_SymbolPrs* thePrs,
double theStep, GeomPointPtr thePnt)
{
- std::list<ObjectPtr> aCurves = getCurves(thePnt, thePrs);
-
gp_Pnt aP = thePnt->impl<gp_Pnt>();
- //gp_Vec aVec1 = getVector(theLine, thePrs->plane()->dirX(), aP);
- std::list<gp_Vec> aVectors;
+ GeomDirPtr aNormal = thePrs->plane()->normal();
+ gp_Dir aNormDir = aNormal->impl<gp_Dir>();
+
+ std::list<ObjectPtr> aCurves = getCurves(thePnt, thePrs);
std::list<ObjectPtr>::const_iterator aItCurv;
+ std::list<gp_Vec> aVectorsList;
+ // Calculate all vectors
for (aItCurv = aCurves.cbegin(); aItCurv != aCurves.cend(); aItCurv++) {
- ObjectPtr aObject = (*aItCurv);
- gp_Vec aVec = getVector(aObject, thePrs->plane()->dirX(), aP);
- aVectors.push_back(aVec);
+ aVectorsList.push_back(getVector((*aItCurv), thePrs->plane()->dirX(), aP));
}
- gp_Vec aBase = getVector(theLine, thePrs->plane()->dirX(), aP);
- std::list<double> aAngles;
std::list<gp_Vec>::const_iterator aItVec;
- for (aItVec = aVectors.cbegin(); aItVec != aVectors.cend(); aItVec++) {
- gp_Vec aVec = (*aItVec);
- double aAngle = aBase.Angle(aVec);
- aAngles.push_back(aAngle);
+ std::map<double, gp_Vec> aAngVectors;
+ // Select closest vectors and calculate angles between base vector and closest vector
+ for (aItVec = aVectorsList.cbegin(); aItVec != aVectorsList.cend(); aItVec++) {
+ std::list<gp_Vec>::const_iterator aIt;
+ double aMinAng = 0;
+ gp_Vec aVec = *aItVec;
+ for (aIt = aVectorsList.cbegin(); aIt != aVectorsList.cend(); aIt++) {
+ double aAng = aVec.AngleWithRef(*aIt, aNormDir);
+ if (aAng != 0) {
+ if (aAng < 0)
+ aAng = 2 * PI + aAng;
+
+ if (aMinAng == 0)
+ aMinAng = aAng;
+ else if (aAng < aMinAng) {
+ aMinAng = aAng;
+ }
+ }
+ }
+ aAngVectors[aMinAng] = aVec;
}
- // Compute shifting vector for a one symbol
- //gp_Vec aShift = aVec1.Crossed(thePrs->plane()->normal()->impl<gp_Dir>());
- //aShift.Normalize();
- //aShift.Multiply(theStep * 1.5);
- //aP.Translate(aShift);
- return aP;
+
+ // Angle size of a symbol for a first level
+ static const double aAngleStep = PI * 50./180.;
+
+ // Position of the symbol
+ int aPos = getPositionIndex(thePnt, thePrs);
+
+ //std::list<double>::const_iterator aItAng;
+ gp_Ax1 aRotAx(aP, aNormDir);
+ int aPosId = 0; // Last used position
+ double aAng;
+ gp_Vec aPrevVec;
+ std::map<double, gp_Vec>::const_iterator aItAng;
+ for (aItAng = aAngVectors.cbegin(); aItAng != aAngVectors.cend(); ++aItAng) {
+ aAng = aItAng->first;
+ aPrevVec = aItAng->second;
+ if (aAng >= aAngleStep) {
+ gp_Vec aShift;
+ int Nb = int(aAng / aAngleStep);
+ if ((aPos >= aPosId) && (aPos < (aPosId + Nb))) {
+ // rotate base vector on a necessary angle
+ aShift = aPrevVec.Rotated(aRotAx, aAngleStep + aAngleStep * (aPos - aPosId));
+ aShift.Normalize();
+ aShift.Multiply(theStep * 1.5);
+ return aP.Translated(aShift);
+ }
+ aPosId += Nb;
+ }
+ }
+ gp_Vec aShift = aPrevVec.Rotated(aRotAx, aAngleStep);
+ aShift.Normalize();
+ aShift.Multiply(theStep * 1.5);
+ return aP.Translated(aShift);
}
//*****************************************************************