-// Copyright (C) 2014-2019 CEA/DEN, EDF R&D
+// Copyright (C) 2014-2023 CEA, EDF
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_BSpline.h>
+#include <SketchPlugin_BSplinePeriodic.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Ellipse.h>
#include <SketchPlugin_EllipticArc.h>
#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_AttributeDoubleArray.h>
#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeString.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
#include <cmath>
static const double tolerance = 1.e-7;
+static const std::string THE_KEEP_REF("true");
+
+static bool isKeepReference(AttributeStringPtr theAttr)
+{
+ return !theAttr || !theAttr->isInitialized() || theAttr->value() == THE_KEEP_REF;
+}
SketchPlugin_Projection::SketchPlugin_Projection()
{
data()->addAttribute(EXTERNAL_FEATURE_ID(), ModelAPI_AttributeSelection::typeId());
data()->addAttribute(PROJECTED_FEATURE_ID(), ModelAPI_AttributeRefAttr::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PROJECTED_FEATURE_ID());
data()->attribute(PROJECTED_FEATURE_ID())->setIsArgument(false);
data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), AUXILIARY_ID());
}
+void SketchPlugin_Projection::initDerivedClassAttributes2()
+{
+ AttributePtr aKeepRefAttr =
+ data()->addAttribute(KEEP_REFERENCE_ID(), ModelAPI_AttributeString::typeId());
+ if (!aKeepRefAttr->isInitialized()) {
+ std::dynamic_pointer_cast<ModelAPI_AttributeString>(aKeepRefAttr)->setValue(THE_KEEP_REF);
+ }
+
+ data()->addAttribute(MAKE_FIXED(), ModelAPI_AttributeBoolean::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAKE_FIXED());
+
+ data()->addAttribute(FIXED_CONSTRAINT_ID(), ModelAPI_AttributeReference::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FIXED_CONSTRAINT_ID());
+ data()->attribute(FIXED_CONSTRAINT_ID())->setIsArgument(false);
+}
+
void SketchPlugin_Projection::execute()
{
AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID());
return;
FeaturePtr aProjection = ModelAPI_Feature::feature(aRefAttr->object());
- if (!lastResult().get()) {
+ if (isKeepReference(string(KEEP_REFERENCE_ID())) && !lastResult().get()) {
bool hasProjResult = aProjection->lastResult().get() != NULL;
ResultConstructionPtr aConstr = document()->createConstruction(data());
if (hasProjResult)
computeProjection(EXTERNAL_FEATURE_ID());
}
+bool SketchPlugin_Projection::isMacro() const
+{
+ if (!data() || !data()->isValid())
+ return false;
+
+ AttributeStringPtr aKeepRefAttr =
+ const_cast<SketchPlugin_Projection*>(this)->string(KEEP_REFERENCE_ID());
+ return !isKeepReference(aKeepRefAttr);
+}
+
void SketchPlugin_Projection::attributeChanged(const std::string& theID)
{
if ((theID == EXTERNAL_FEATURE_ID() || theID == EXTERNAL_ID()) && !myIsComputing) {
static const std::set<std::string>& BSPLINE_PROJECTION()
{
static std::set<std::string> aProj;
- if (aProj.empty())
+ if (aProj.empty()) {
aProj.insert(SketchPlugin_BSpline::ID());
+ aProj.insert(SketchPlugin_BSplinePeriodic::ID());
+ }
return aProj;
}
if (!isRebuild && aResult && aResult->shape() && theID == EXTERNAL_FEATURE_ID()) {
aResult->setShape(std::shared_ptr<GeomAPI_Edge>());
if (aProjection)
- aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape());
+ aProjection->selection(EXTERNAL_ID())->setValue(ResultPtr(), GeomShapePtr());
}
keepCurrentFeature();
if (!isProjected)
return; // projection is not computed, stop processing
- aProjection->boolean(COPY_ID())->setValue(true);
+ bool keepBackRef = isKeepReference(string(KEEP_REFERENCE_ID()));
+
+ aProjection->boolean(COPY_ID())->setValue(keepBackRef);
aProjection->execute();
aRefAttr->setObject(aProjection);
restoreCurrentFeature();
- if (theID == EXTERNAL_FEATURE_ID()) {
- selection(EXTERNAL_ID())->selectValue(aExtFeature);
+ AttributeBooleanPtr aMakeFixedAttr = boolean(MAKE_FIXED());
+ bool isMakeFixed = aMakeFixedAttr && aMakeFixedAttr->isInitialized() && aMakeFixedAttr->value();
- if (aResult) {
- aResult->setShape(aProjection->lastResult()->shape());
- setResult(aResult);
- GeomShapePtr anEmptyVal;
- aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), anEmptyVal);
+ AttributeReferencePtr aFixedConstrAttr = reference(FIXED_CONSTRAINT_ID());
+ FeaturePtr aFixedConstraint;
+ if (aFixedConstrAttr && aFixedConstrAttr->isInitialized())
+ aFixedConstraint = ModelAPI_Feature::feature(aFixedConstrAttr->value());
- static const Events_ID anEvent = Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES);
- ModelAPI_EventCreator::get()->sendUpdated(aProjection, anEvent, false);
+ if (keepBackRef) {
+ if (theID == EXTERNAL_FEATURE_ID()) {
+ selection(EXTERNAL_ID())->selectValue(aExtFeature);
+
+ if (aResult) {
+ aResult->setShape(aProjection->lastResult()->shape());
+ setResult(aResult);
+ GeomShapePtr anEmptyVal;
+ aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), anEmptyVal);
+ }
}
}
+ else if (isMakeFixed) {
+ // fix the projected entity with the Fixed constraint
+ if (!aFixedConstraint)
+ aFixedConstraint = sketch()->addFeature(SketchPlugin_ConstraintRigid::ID());
+ aFixedConstraint->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(
+ aProjection->lastResult());
+ }
+
+
+ // remove Fixed constraint in case of redundance
+ if (aFixedConstraint && (keepBackRef || !isMakeFixed)) {
+ document()->removeFeature(aFixedConstraint);
+ aFixedConstraint = FeaturePtr();
+ }
+ aFixedConstrAttr->setValue(aFixedConstraint);
+
+ static const Events_ID anEvent = Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES);
+ ModelAPI_EventCreator::get()->sendUpdated(aProjection, anEvent, false);
}
bool SketchPlugin_Projection::rebuildProjectedFeature(
if (aProjectedCurve->isCircle()) {
if (aProjectedCurve->isTrimmed()) {
// ARC is a projection
- isOk = fillArc(theProjection, aProjectedCurve, aSketchPlane);
+ isOk = fillArc(theProjection, aProjectedCurve, aSketchPlane, theEdge);
}
else {
// CIRCLE is a projection
else if (aProjectedCurve->isEllipse()) {
if (aProjectedCurve->isTrimmed()) {
// ELLIPTIC ARC is a projection
- isOk = fillEllipticArc(theProjection, aProjectedCurve, aSketchPlane);
+ isOk = fillEllipticArc(theProjection, aProjectedCurve, aSketchPlane, theEdge);
}
else {
// ELLIPSE is a projection
bool SketchPlugin_Projection::fillArc(FeaturePtr& theProjection,
const GeomCurvePtr& theArc,
- const GeomPlanePtr& thePlane)
+ const GeomPlanePtr& thePlane,
+ const GeomEdgePtr& theOriginalEdge)
{
rebuildProjectedFeature(theProjection, ARC_PROJECTION(), SketchPlugin_Arc::ID());
bool isInversed = aNormalsDot < 0.;
+ GeomCirclePtr anOriginalCircle = theOriginalEdge->circle();
+ if (anOriginalCircle) {
+ double aCirclesDot = anOriginalCircle->normal()->dot(aCircle.normal());
+ if (aCirclesDot < 0.)
+ isInversed = !isInversed;
+ }
+
GeomPointPtr aCenter = thePlane->project(aCircle.center());
GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter);
bool SketchPlugin_Projection::fillEllipticArc(FeaturePtr& theProjection,
const GeomCurvePtr& theEllipticArc,
- const GeomPlanePtr& thePlane)
+ const GeomPlanePtr& thePlane,
+ const GeomEdgePtr& theOriginalEdge)
{
rebuildProjectedFeature(theProjection, ARC_PROJECTION(), SketchPlugin_EllipticArc::ID());
bool isInversed = aNormalsDot < 0.;
+ GeomEllipsePtr anOriginalEllipse = theOriginalEdge->ellipse();
+ if (anOriginalEllipse) {
+ double anEllipsesDot = anOriginalEllipse->normal()->dot(anEllipse.normal());
+ if (anEllipsesDot < 0.)
+ isInversed = !isInversed;
+ }
+
GeomPointPtr aCenter = thePlane->project(anEllipse.center());
GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter);
GeomPointPtr aFocus = thePlane->project(anEllipse.firstFocus());
bool SketchPlugin_Projection::fillBSpline(FeaturePtr& theProjection,
const GeomCurvePtr& theCurve,
- const GeomPlanePtr& thePlane)
+ const GeomPlanePtr& /*thePlane*/)
{
- rebuildProjectedFeature(theProjection, BSPLINE_PROJECTION(), SketchPlugin_BSpline::ID());
-
GeomAPI_BSpline aBSpline(theCurve);
+ rebuildProjectedFeature(theProjection, BSPLINE_PROJECTION(),
+ aBSpline.isPeriodic() ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID());
+
theProjection->integer(SketchPlugin_BSpline::DEGREE_ID())->setValue(aBSpline.degree());
AttributePoint2DArrayPtr aPolesAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(
}
else { // non-rational B-spline
aWeightsAttr->setSize((int)aWeights.size());
- std::list<double>::iterator anIt = aWeights.begin();
- for (int anIndex = 0; anIt != aWeights.end(); ++anIt, ++anIndex)
- aWeightsAttr->setValue(anIndex, *anIt);
+ std::list<double>::iterator aWIt = aWeights.begin();
+ for (int anIndex = 0; aWIt != aWeights.end(); ++aWIt, ++anIndex)
+ aWeightsAttr->setValue(anIndex, *aWIt);
}
AttributeDoubleArrayPtr aKnotsAttr =