// compute and change the arc end point
std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
GeomDataAPI_Point2D>(data()->attribute(END_ID()));
- /* must be automatically done in attributeChanged
std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEndAttr->pnt());
if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance)
anEndAttr->setValue(aProjection);
- */
std::shared_ptr<GeomAPI_Pnt> aEndPoint(aSketch->to3D(anEndAttr->x(), anEndAttr->y()));
AttributeBooleanPtr isInversed =
std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(attribute(INVERSED_ID()));
}
return;
}
- if (!aCenterAttr->isInitialized())
- return;
- if (!aStartAttr->isInitialized())
- return;
- if (!anEndAttr->isInitialized())
+ if (!isFeatureValid())
return;
// update the points in accordance to the changed point changes
- if (theID == END_ID() && !myEndUpdate) {
- myEndUpdate = true;
- // compute and change the arc end point
- std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
- new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
- std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEndAttr->pnt());
- if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance) {
- if (!isStable()) { // issue #855: trying to update only not-updated coordinate if it is possible
- if (fabs(myXEndBefore - anEndAttr->x()) < 1.e-10) { // keep Y unchanged
- double aVy = aCenterAttr->y() - anEndAttr->y();
- double aVy2 = aVy * aVy;
- double aR2 = aCircleForArc->radius() * aCircleForArc->radius();
- if (aVy2 <= aR2) {
- double aDX = sqrt(aR2 - aVy * aVy);
- if (anEndAttr->x() > aCenterAttr->x())
- aProjection->setX(aCenterAttr->x() + aDX);
- else
- aProjection->setX(aCenterAttr->x() - aDX);
- aProjection->setY(anEndAttr->y());
- }
- } else if (fabs(myYEndBefore - anEndAttr->y()) < 1.e-10) { // keep X unchanged
- double aVx = aCenterAttr->x() - anEndAttr->x();
- double aVx2 = aVx * aVx;
- double aR2 = aCircleForArc->radius() * aCircleForArc->radius();
- if (aVx2 <= aR2) {
- double aDY = sqrt(aR2 - aVx * aVx);
- if (anEndAttr->y() > aCenterAttr->y())
- aProjection->setY(aCenterAttr->y() + aDY);
- else
- aProjection->setY(aCenterAttr->y() - aDY);
- aProjection->setX(anEndAttr->x());
- }
- }
- }
-
- anEndAttr->setValue(aProjection);
- }
- myXEndBefore = anEndAttr->x();
- myYEndBefore = anEndAttr->y();
- myEndUpdate = false;
- } else if (theID == START_ID() && !myStartUpdate) {
- myStartUpdate = true;
- // compute and change the arc start point
- std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
- new GeomAPI_Circ2d(aCenterAttr->pnt(), anEndAttr->pnt()));
- std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(aStartAttr->pnt());
- if (aProjection && aStartAttr->pnt()->distance(aProjection) > tolerance)
- aStartAttr->setValue(aProjection);
- myStartUpdate = false;
- } else if (theID == CENTER_ID() && !myEndUpdate) {
+ if (theID == CENTER_ID() && !myEndUpdate) {
myEndUpdate = true;
// compute and change the arc end point
std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
SketchSolver_ConstraintLength.h
SketchSolver_ConstraintMirror.h
SketchSolver_ConstraintFixed.h
+ SketchSolver_ConstraintFixedArcRadius.h
SketchSolver_ConstraintTangent.h
SketchSolver_ConstraintMulti.h
SketchSolver_ConstraintMultiRotation.h
SketchSolver_ConstraintLength.cpp
SketchSolver_ConstraintMirror.cpp
SketchSolver_ConstraintFixed.cpp
+ SketchSolver_ConstraintFixedArcRadius.cpp
SketchSolver_ConstraintTangent.cpp
SketchSolver_ConstraintMulti.cpp
SketchSolver_ConstraintMultiRotation.cpp
if (aConstraint->valueParameter())
isFullyRemoved = remove(aConstraint->valueParameter()) && isFullyRemoved;
- if (!isFullyRemoved &&
+ if (!isFullyRemoved && aConstraint->baseConstraint() &&
(!aConstraint->baseConstraint()->data() || !aConstraint->baseConstraint()->data()->isValid()))
isFullyRemoved = true;
setNeedToResolve(true);
#include <SketchSolver_ConstraintDistance.h>
#include <SketchSolver_ConstraintEqual.h>
#include <SketchSolver_ConstraintFixed.h>
+#include <SketchSolver_ConstraintFixedArcRadius.h>
#include <SketchSolver_ConstraintLength.h>
#include <SketchSolver_ConstraintMirror.h>
#include <SketchSolver_ConstraintTangent.h>
return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theFixedFeature));
}
+SolverConstraintPtr SketchSolver_Builder::createFixedArcRadiusConstraint(FeaturePtr theArc) const
+{
+ DataPtr aData = theArc->data();
+ if (!aData || !aData->isValid())
+ return SolverConstraintPtr();
+ return SolverConstraintPtr(new SketchSolver_ConstraintFixedArcRadius(theArc));
+}
+
SolverConstraintPtr SketchSolver_Builder::createMovementConstraint(FeaturePtr theFixedFeature) const
{
DataPtr aData = theFixedFeature->data();
/// \brief Creates temporary constraint to fix the placement of the feature
SolverConstraintPtr createFixedConstraint(FeaturePtr theFixedFeature) const;
+ /// \brief Creates temporary constraint to fix radius of the arc
+ SolverConstraintPtr createFixedArcRadiusConstraint(FeaturePtr theArc) const;
+
/// \brief Creates temporary constraint to fix the feature after movement
SolverConstraintPtr createMovementConstraint(FeaturePtr theFixedFeature) const;
EntityWrapperPtr aSolverEntity;
if (myBaseFeature) {
// The feature is fixed.
- myStorage->update(myBaseFeature, myGroupID);
+ myStorage->update(myBaseFeature/*, myGroupID*/);
aSolverEntity = myStorage->entity(myBaseFeature);
} else if (myBaseConstraint) {
// Constraint Fixed is added by user.
--- /dev/null
+#include <SketchSolver_ConstraintFixedArcRadius.h>
+#include <SketchSolver_Error.h>
+#include <SketchSolver_Manager.h>
+
+#include <SketchPlugin_Arc.h>
+#include <GeomAPI_Pnt2d.h>
+
+SketchSolver_ConstraintFixedArcRadius::SketchSolver_ConstraintFixedArcRadius(FeaturePtr theFeature)
+ : SketchSolver_ConstraintFixed(theFeature)
+{
+ myType = CONSTRAINT_RADIUS;
+ process();
+}
+
+void SketchSolver_ConstraintFixedArcRadius::process()
+{
+ cleanErrorMsg();
+ if (!myBaseFeature || !myStorage || myGroupID == GID_UNKNOWN) {
+ // Not enough parameters are assigned
+ return;
+ }
+
+ if (myBaseFeature->getKind() != SketchPlugin_Arc::ID()) {
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+
+ ParameterWrapperPtr aValue;
+ std::vector<EntityWrapperPtr> anEntities;
+ getAttributes(aValue, anEntities);
+ if (!myErrorMsg.empty() || anEntities.empty())
+ return;
+ fixFeature(anEntities.front());
+}
+
+void SketchSolver_ConstraintFixedArcRadius::fixFeature(EntityWrapperPtr theFeature)
+{
+ BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+
+ // Calculate radius of the arc
+ std::list<EntityWrapperPtr> aSubs = theFeature->subEntities();
+ std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
+ std::shared_ptr<GeomAPI_Pnt2d> aCenter = aBuilder->point(*aSubIt++);
+ std::shared_ptr<GeomAPI_Pnt2d> aStart = aBuilder->point(*aSubIt++);
+ double aRadius = aCenter->distance(aStart);
+
+ // Create constraint
+ std::list<ConstraintWrapperPtr> aConstrList = aBuilder->createConstraint(ConstraintPtr(),
+ myGroupID, mySketchID, myType, aRadius, EntityWrapperPtr(), EntityWrapperPtr(), theFeature);
+ myRadiusConstraint = aConstrList.front();
+ myStorage->addConstraint(ConstraintPtr(), myRadiusConstraint);
+}
+
+bool SketchSolver_ConstraintFixedArcRadius::remove()
+{
+ bool isFullyRemoved = SketchSolver_ConstraintFixed::remove();
+ if (myRadiusConstraint)
+ isFullyRemoved = myStorage->removeConstraint(ConstraintPtr()) &&
+ myStorage->remove(myRadiusConstraint) && isFullyRemoved;
+ return isFullyRemoved;
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_ConstraintFixedArcRadiusArcRadius.h
+// Created: 22 Jan 2016
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintFixedArcRadius_H_
+#define SketchSolver_ConstraintFixedArcRadius_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_ConstraintFixed.h>
+
+/** \class SketchSolver_ConstraintFixedArcRadius
+ * \ingroup Plugins
+ * \brief Fix radius of the arc. Temporary constraint. Based on an arc, sharp!
+ */
+class SketchSolver_ConstraintFixedArcRadius : public SketchSolver_ConstraintFixed
+{
+public:
+ /// Creates temporary constraint based on feature
+ SketchSolver_ConstraintFixedArcRadius(FeaturePtr theFeature);
+
+ /// \brief Tries to remove constraint
+ /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+ virtual bool remove();
+
+protected:
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
+
+ /// \brief Fix radius of arc
+ /// \param theFeature [in] feature, converted to solver specific format
+ virtual void fixFeature(EntityWrapperPtr theFeature);
+
+private:
+ ConstraintWrapperPtr myRadiusConstraint;
+};
+
+#endif
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
+#include <SketchPlugin_Arc.h>
#include <SketchPlugin_ConstraintAngle.h>
#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_ConstraintDistance.h>
// Secondly, search attributes of the feature in the list of the Multi constraints and update them
updateMultiConstraints(myConstraints, theFeature);
+
+ // Workaround to process arcs.
+ // When move unconstrained arc, add temporary constraint to fix radius.
+ if (theFeature->getKind() == SketchPlugin_Arc::ID()) {
+ SolverConstraintPtr aFixedRadius = aBuilder->createFixedArcRadiusConstraint(theFeature);
+ if (aFixedRadius) {
+ aFixedRadius->process(myStorage, getId(), getWorkplaneId());
+ if (aFixedRadius->error().empty())
+ setTemporary(aFixedRadius);
+ }
+ }
}
// ============================================================================
bool SketchSolver_Group::resolveConstraints()
{
bool aResolved = false;
- bool isGroupEmpty = isEmpty();
+ bool isGroupEmpty = isEmpty() && myStorage->isEmpty();
if (myStorage->isNeedToResolve() && !isGroupEmpty) {
if (!mySketchSolver)
mySketchSolver = SketchSolver_Manager::instance()->builder()->createSolver();
// ============================================================================
void SketchSolver_Manager::moveEntity(std::shared_ptr<SketchPlugin_Feature> theFeature)
{
+ bool isMoved = false;
std::vector<SketchSolver_Group*>::iterator aGroupIt = myGroups.begin();
for (; aGroupIt != myGroups.end(); aGroupIt++)
- if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature))
+ if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature)) {
(*aGroupIt)->moveFeature(theFeature);
+ isMoved = true;
+ }
+
+ if (!isMoved && theFeature->getKind() == SketchPlugin_Arc::ID()) {
+ // Workaround to move arc.
+ // If the arc has not been constrained, we will push it into empty group and apply movement.
+ for (aGroupIt = myGroups.begin(); aGroupIt != myGroups.end(); aGroupIt++)
+ if ((*aGroupIt)->isEmpty())
+ (*aGroupIt)->moveFeature(theFeature);
+ }
}
// ============================================================================
if (!theSolverConstraints.empty() || aFound == myConstraintMap.end())
myConstraintMap[theConstraint] = theSolverConstraints;
// block events if necessary
- if (myEventsBlocked && theConstraint->data() && theConstraint->data()->isValid())
+ if (myEventsBlocked && theConstraint && theConstraint->data() && theConstraint->data()->isValid())
theConstraint->data()->blockSendAttributeUpdated(myEventsBlocked);
}
#include <SketchPlugin_Constraint.h>
class SketchSolver_ConstraintDistance;
+class SketchSolver_ConstraintFixedArcRadius;
typedef std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> > CoincidentPointsMap;
/// \brief Check the features is not removed
bool isConsistent() const;
+ /// \brief Check the storage has constraints
+ bool isEmpty() const
+ { return myConstraintMap.empty(); }
+
/// \brief Check the entity is fixed.
/// If the point is under verification, all coincident points are checked too.
SKETCHSOLVER_EXPORT bool isFixed(EntityWrapperPtr theEntity) const;
// to be able to update entities from constraints
friend class SketchSolver_ConstraintDistance;
+ friend class SketchSolver_ConstraintFixedArcRadius;
};
typedef std::shared_ptr<SketchSolver_Storage> StoragePtr;