new SketchPlugin_ProjectionValidator);
aFactory->registerValidator("SketchPlugin_DifferentReference",
new SketchPlugin_DifferentReferenceValidator);
+ aFactory->registerValidator("SketchPlugin_DifferentPointReference",
+ new SketchPlugin_DifferentPointReferenceValidator);
aFactory->registerValidator("SketchPlugin_CirclePassedPointValidator",
new SketchPlugin_CirclePassedPointValidator);
aFactory->registerValidator("SketchPlugin_ThirdPointValidator",
return aCoincidentFeatures;
}
+// Container for point-point coincidences.
+// Useful to find points coincident to a given point.
+class CoincidentPoints
+{
+public:
+ void addCoincidence(const AttributePoint2DPtr& thePoint1,
+ const AttributePoint2DPtr& thePoint2 = AttributePoint2DPtr())
+ {
+ std::list< std::set<AttributePoint2DPtr> >::iterator aFound1 = find(thePoint1);
+ std::list< std::set<AttributePoint2DPtr> >::iterator aFound2 = find(thePoint2);
+ if (aFound1 == myCoincidentPoints.end()) {
+ std::set<AttributePoint2DPtr> aNewSet;
+ aNewSet.insert(thePoint1);
+ if (thePoint2)
+ aNewSet.insert(thePoint2);
+ myCoincidentPoints.push_back(aNewSet);
+ } else if (aFound2 == myCoincidentPoints.end()) {
+ if (thePoint2)
+ aFound1->insert(thePoint2);
+ } else {
+ aFound1->insert(aFound2->begin(), aFound2->end());
+ myCoincidentPoints.erase(aFound2);
+ }
+ }
+
+ std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
+ {
+ std::list< std::set<AttributePoint2DPtr> >::iterator aFound = find(thePoint);
+ if (aFound == myCoincidentPoints.end())
+ return std::set<AttributePoint2DPtr>();
+ return *aFound;
+ }
+
+private:
+ std::list< std::set<AttributePoint2DPtr> >::iterator find(const AttributePoint2DPtr& thePoint)
+ {
+ std::list< std::set<AttributePoint2DPtr> >::iterator aSeek = myCoincidentPoints.begin();
+ for (; aSeek != myCoincidentPoints.end(); ++aSeek)
+ if (aSeek->find(thePoint) != aSeek->end())
+ return aSeek;
+ return myCoincidentPoints.end();
+ }
+
+private:
+ std::list< std::set<AttributePoint2DPtr> > myCoincidentPoints;
+};
+
+std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
+{
+ CoincidentPoints aCoincidentPoints;
+ AttributePoint2DPtr aPoints[2];
+
+ FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
+ std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
+ std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
+ for (; aCIt != aCoincidences.end(); ++aCIt) {
+ aPoints[0] = AttributePoint2DPtr();
+ aPoints[1] = AttributePoint2DPtr();
+ for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
+ AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
+ if (!aRefAttr)
+ continue;
+ if (!aRefAttr->isObject())
+ aPoints[aPtInd++] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
+ }
+
+ if (aPoints[0])
+ aCoincidentPoints.addCoincidence(aPoints[0], aPoints[1]);
+ }
+
+ return aCoincidentPoints.coincidentPoints(thePoint);
+}
+
void resetAttribute(SketchPlugin_Feature* theFeature,
const std::string& theId)
{
/// Find all features the point is coincident to.
std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint);
+/// Find all points the given point is coincident to.
+std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint);
+
void resetAttribute(SketchPlugin_Feature* theFeature, const std::string& theId);
/// Creates coincidence or tangent constraint.
return isOk;
}
+bool SketchPlugin_DifferentPointReferenceValidator::isValid(
+ const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
+ std::set<AttributePoint2DPtr> aReferredCoincidentPoints;
+
+ // find all points referred by attributes listed in theArguments
+ bool hasRefsToPoints = false;
+ std::list<std::string>::const_iterator anArgIt = theArguments.begin();
+ for (; anArgIt != theArguments.end(); ++anArgIt) {
+ AttributeRefAttrPtr aRefAttr = anOwner->refattr(*anArgIt);
+ if (!aRefAttr)
+ continue;
+
+ if (!aRefAttr->isObject()) {
+ AttributePoint2DPtr aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
+ if (aReferredCoincidentPoints.empty())
+ aReferredCoincidentPoints = SketchPlugin_Tools::findPointsCoincidentToPoint(aPoint);
+ else if (aReferredCoincidentPoints.find(aPoint) == aReferredCoincidentPoints.end())
+ return true; // non-coincident point has been found
+ else
+ hasRefsToPoints = true;
+ }
+ }
+
+ if (hasRefsToPoints)
+ theError = "Attributes are referred to the same point";
+ return !hasRefsToPoints;
+}
+
bool SketchPlugin_CirclePassedPointValidator::isValid(
const AttributePtr& theAttribute,
const std::list<std::string>&,
Events_InfoMessage& theError) const;
};
+/**\class SketchPlugin_DifferentPointReferenceValidator
+ * \ingroup Validators
+ * \brief Validator for attributes of a sketch feature.
+ *
+ * It checks that at least two of specified attributes refer to different points.
+ */
+class SketchPlugin_DifferentPointReferenceValidator : public ModelAPI_AttributeValidator
+{
+ public:
+ //! returns true if attribute is valid
+ //! \param theAttribute the checked attribute
+ //! \param theArguments arguments of the attribute
+ //! \param theError error message
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const;
+};
+
/**\class SketchPlugin_CirclePassedPointValidator
* \ingroup Validators
* \brief Validator for passed point of MacroCircle feature.
aDocument.removeFeature(anArc)
assert (aSketchFeature.numberOfSubs() == 9)
+#=========================================================================
+# Test 6. Create an arc by three points:
+# a. check that one point IS NOT selectable as first and second points simultaneously
+# b. check that one segment IS selectable by first and second points
+#=========================================================================
+aSession.startOperation()
+anArc = aSketchFeature.addFeature("SketchMacroArc")
+anArcPnt1 = geomDataAPI_Point2D(anArc.attribute("start_point_2"))
+anArcPnt2 = geomDataAPI_Point2D(anArc.attribute("end_point_2"))
+anArcPnt3 = geomDataAPI_Point2D(anArc.attribute("passed_point"))
+anArcPnt1Ref = anArc.refattr("start_point_ref")
+anArcPnt2Ref = anArc.refattr("end_point_ref")
+anArcPnt3Ref = anArc.refattr("passed_point_ref")
+anArcType = anArc.string("arc_type")
+# initialize attributes
+anArcType.setValue("by_three_points")
+anArcPnt1Ref.setAttr(aStartPnt)
+anArcPnt1.setValue(aStartPnt.pnt())
+anArcPnt2Ref.setAttr(aStartPnt)
+anArcPnt2.setValue(aStartPnt.pnt())
+anArcPnt3.setValue(0., 0.)
+aSession.finishOperation()
+# check the macro arc is not valid
+aLastFeature = aSketchFeature.subFeature(aSketchFeature.numberOfSubs() - 1)
+assert aLastFeature.getKind() == "SketchMacroArc", "ERROR: SketchMacroArc has NOT expected to be valid"
+# reselect first points
+aSession.startOperation()
+anArcPnt1Ref.setObject(aLine.lastResult())
+anArcPnt1.setValue(aStartPnt.pnt())
+anArcPnt2Ref.setObject(aLine.lastResult())
+anArcPnt2.setValue(aEndPnt.pnt())
+aSession.finishOperation()
+# check the macro arc is valid
+aLastFeature = aSketchFeature.subFeature(aSketchFeature.numberOfSubs() - 1)
+assert aLastFeature.getKind() != "SketchMacroArc", "ERROR: SketchMacroArc is expected to be valid"
+assert (aSketchFeature.numberOfSubs() == 12)
+# check sub-features
+model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 5)
+model.testNbSubFeatures(aSketch, "SketchConstraintTangent", 1)
+
model.do()
model.end()
tooltip="End point"
accept_expressions="0"
enable_value="enable_by_preferences">
- <validator id="SketchPlugin_DifferentReference" parameters="start_point_ref,end_point_ref"/>
+ <validator id="GeomValidators_Different" parameters="start_point_2,end_point_2"/>
+ <validator id="SketchPlugin_DifferentPointReference" parameters="start_point_ref,end_point_ref"/>
</sketch-2dpoint_selector>
<sketch-2dpoint_selector id="passed_point"
reference_attribute="passed_point_ref"