Handle(Geom_Circle) aCurve = new Geom_Circle(*MY_CIRC);
return GeomLib_Tool::Parameter(aCurve, thePoint->impl<gp_Pnt>(), theTolerance, theParameter) == Standard_True;
}
+
+//=================================================================================================
+std::shared_ptr<GeomAPI_Dir> GeomAPI_Circ::normal() const
+{
+ const gp_Ax1& anAxis = MY_CIRC->Axis();
+ const gp_Dir& aDir = anAxis.Direction();
+ return std::shared_ptr<GeomAPI_Dir>(new GeomAPI_Dir(aDir.X(), aDir.Y(), aDir.Z()));
+}
/// Return radius of the circle
GEOMAPI_EXPORT double radius() const;
+ /// Return orthogonal direction to the circle's plane
+ GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Dir> normal() const;
+
/// Project point on circle
GEOMAPI_EXPORT const std::shared_ptr<GeomAPI_Pnt> project(
const std::shared_ptr<GeomAPI_Pnt>& thePoint) const;
double aParam = aNormal->dot(aLocation->decreased(aLineLoc)) / aDot;
return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aLineLoc->added(aLineDir->multiplied(aParam))));
}
+
+std::shared_ptr<GeomAPI_Pnt> GeomAPI_Pln::project(const std::shared_ptr<GeomAPI_Pnt>& thePoint) const
+{
+ std::shared_ptr<GeomAPI_XYZ> aNormal = direction()->xyz();
+ std::shared_ptr<GeomAPI_XYZ> aLocation = location()->xyz();
+
+ std::shared_ptr<GeomAPI_XYZ> aVec = thePoint->xyz()->decreased(aLocation);
+ double aDot = aNormal->dot(aVec);
+ std::shared_ptr<GeomAPI_XYZ> aProjection =
+ aLocation->added(aVec->decreased(aNormal->multiplied(aDot)));
+ return std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aProjection));
+}
/// Returns intersection point or empty if no intersections
GEOMAPI_EXPORT
- std::shared_ptr<GeomAPI_Pnt> intersect(const std::shared_ptr<GeomAPI_Lin>& theLine) const;
+ std::shared_ptr<GeomAPI_Pnt> intersect(const std::shared_ptr<GeomAPI_Lin>& theLine) const;
+
+ /// Returns projection of the given point onto the plane
+ GEOMAPI_EXPORT
+ std::shared_ptr<GeomAPI_Pnt> project(const std::shared_ptr<GeomAPI_Pnt>& thePoint) const;
};
#endif
SketchPlugin_ExternalValidator.h
SketchPlugin_Validators.h
SketchPlugin_Tools.h
+ SketchPlugin_Projection.h
)
SET(PROJECT_SOURCES
SketchPlugin_ExternalValidator.cpp
SketchPlugin_Validators.cpp
SketchPlugin_Tools.cpp
+ SketchPlugin_Projection.cpp
)
SET(PROJECT_LIBRARIES
#include <SketchPlugin_IntersectionPoint.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Projection.h>
#include <SketchPlugin_ConstraintAngle.h>
#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_ConstraintCollinear.h>
new SketchPlugin_ArcTangentPointValidator);
aFactory->registerValidator("SketchPlugin_IntersectionValidator",
new SketchPlugin_IntersectionValidator);
+ aFactory->registerValidator("SketchPlugin_ProjectionValidator",
+ new SketchPlugin_ProjectionValidator);
// register this plugin
ModelAPI_Session::get()->registerPlugin(this);
return FeaturePtr(new SketchPlugin_Circle);
} else if (theFeatureID == SketchPlugin_Arc::ID()) {
return FeaturePtr(new SketchPlugin_Arc);
+ } else if (theFeatureID == SketchPlugin_Projection::ID()) {
+ return FeaturePtr(new SketchPlugin_Projection);
} else if (theFeatureID == SketchPlugin_ConstraintCoincidence::ID()) {
return FeaturePtr(new SketchPlugin_ConstraintCoincidence);
} else if (theFeatureID == SketchPlugin_ConstraintCollinear::ID()) {
aMsg->setState(SketchPlugin_Line::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_Circle::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_Arc::ID(), aHasSketchPlane);
+ aMsg->setState(SketchPlugin_Projection::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintCoincidence::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintCollinear::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintDistance::ID(), aHasSketchPlane);
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File: SketchPlugin_Projection.cpp
+// Created: 07 May 2014
+// Author: Artem ZHIDKOV
+
+#include <SketchPlugin_Projection.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Sketch.h>
+
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+#include <GeomAPI_Circ.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Lin.h>
+#include <GeomAPI_Pnt.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAlgoAPI_EdgeBuilder.h>
+#include <GeomDataAPI_Point2D.h>
+
+#include <cmath>
+
+static const double tolerance = 1.e-7;
+
+SketchPlugin_Projection::SketchPlugin_Projection()
+ : SketchPlugin_SketchEntity(),
+ myIsComputing(false)
+{
+}
+
+void SketchPlugin_Projection::initDerivedClassAttributes()
+{
+ data()->addAttribute(EXTERNAL_FEATURE_ID(), ModelAPI_AttributeSelection::typeId());
+ data()->addAttribute(PROJECTED_FEATURE_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->attribute(PROJECTED_FEATURE_ID())->setIsArgument(false);
+
+ data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
+}
+
+void SketchPlugin_Projection::execute()
+{
+ AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID());
+ if (!aRefAttr || !aRefAttr->isInitialized())
+ return;
+ FeaturePtr aProjection = ModelAPI_Feature::feature(aRefAttr->object());
+
+ bool hasResult = lastResult();
+
+ std::shared_ptr<GeomAPI_Edge> anEdge;
+ if (aProjection->getKind() == SketchPlugin_Line::ID()) {
+ std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Line::START_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Line::END_ID()));
+
+ // edge to store result
+ std::shared_ptr<GeomAPI_Pnt> aFirst = sketch()->to3D(aStartPnt->x(), aStartPnt->y());
+ std::shared_ptr<GeomAPI_Pnt> aLast = sketch()->to3D(aEndPnt->x(), aEndPnt->y());
+ anEdge = GeomAlgoAPI_EdgeBuilder::line(aFirst, aLast);
+ }
+ else {
+ std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
+ std::shared_ptr<GeomAPI_Dir> aNormal = aSketchPlane->direction();
+
+ if (aProjection->getKind() == SketchPlugin_Circle::ID()) {
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Circle::CENTER_ID()));
+
+ // edge to store result
+ std::shared_ptr<GeomAPI_Pnt> aCenter = sketch()->to3D(aCenterPnt->x(), aCenterPnt->y());
+ double aRadius = aProjection->real(SketchPlugin_Circle::RADIUS_ID())->value();
+ anEdge = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius);
+ }
+ else if (aProjection->getKind() == SketchPlugin_Arc::ID()) {
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Arc::CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Arc::START_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Arc::END_ID()));
+
+ // edge to store result
+ std::shared_ptr<GeomAPI_Pnt> aCenter = sketch()->to3D(aCenterPnt->x(), aCenterPnt->y());
+ std::shared_ptr<GeomAPI_Pnt> aFirst = sketch()->to3D(aStartPnt->x(), aStartPnt->y());
+ std::shared_ptr<GeomAPI_Pnt> aLast = sketch()->to3D(aEndPnt->x(), aEndPnt->y());
+ anEdge = GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aFirst, aLast, aNormal);
+ }
+ }
+
+ std::shared_ptr<ModelAPI_ResultConstruction> aConstr = document()->createConstruction(data());
+ aConstr->setShape(anEdge);
+ aConstr->setIsInHistory(false);
+ setResult(aConstr);
+
+ if (!hasResult)
+ aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape());
+}
+
+void SketchPlugin_Projection::move(double theDeltaX, double theDeltaY)
+{
+ // feature cannot be moved
+}
+
+void SketchPlugin_Projection::attributeChanged(const std::string& theID)
+{
+ if ((theID == EXTERNAL_FEATURE_ID() || theID == EXTERNAL_ID()) && !myIsComputing) {
+ myIsComputing = true;
+ computeProjection(theID);
+ myIsComputing = false;
+ }
+}
+
+void SketchPlugin_Projection::computeProjection(const std::string& theID)
+{
+ AttributeSelectionPtr aExtFeature =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(attribute(EXTERNAL_FEATURE_ID()));
+
+ std::shared_ptr<GeomAPI_Edge> anEdge;
+ if (aExtFeature && aExtFeature->value() && aExtFeature->value()->isEdge()) {
+ anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aExtFeature->value()));
+ } else if (aExtFeature->context() && aExtFeature->context()->shape() && aExtFeature->context()->shape()->isEdge()) {
+ anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aExtFeature->context()->shape()));
+ }
+ if (!anEdge.get())
+ return;
+
+ AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID());
+ FeaturePtr aProjection;
+ if (aRefAttr && aRefAttr->isInitialized())
+ aProjection = ModelAPI_Feature::feature(aRefAttr->object());
+
+ // if the type of feature differs with already selected, remove it and create once again
+ if (aProjection) {
+ if ((anEdge->isLine() && aProjection->getKind() != SketchPlugin_Line::ID()) ||
+ (anEdge->isCircle() && aProjection->getKind() != SketchPlugin_Circle::ID()) ||
+ (anEdge->isArc() && aProjection->getKind() != SketchPlugin_Arc::ID())) {
+ DocumentPtr aDoc = sketch()->document();
+ aDoc->removeFeature(aProjection);
+ aProjection = FeaturePtr();
+ aRefAttr->setObject(aProjection);
+ }
+ }
+
+ std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
+
+ if (anEdge->isLine()) {
+ std::shared_ptr<GeomAPI_Pnt> aFirst = aSketchPlane->project(anEdge->firstPoint());
+ std::shared_ptr<GeomAPI_Pnt> aLast = aSketchPlane->project(anEdge->lastPoint());
+
+ std::shared_ptr<GeomAPI_Pnt2d> aFirstInSketch = sketch()->to2D(aFirst);
+ std::shared_ptr<GeomAPI_Pnt2d> aLastInSketch = sketch()->to2D(aLast);
+ if (aFirstInSketch->distance(aLastInSketch) < tolerance)
+ return; // line is semi-orthogonal to the sketch plane
+
+ if (!aProjection)
+ aProjection = sketch()->addFeature(SketchPlugin_Line::ID());
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Line::START_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Line::END_ID()));
+ aStartPnt->setValue(aFirstInSketch);
+ aEndPnt->setValue(aLastInSketch);
+ }
+ else if (anEdge->isCircle()) {
+ std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
+ double aRadius = aCircle->radius();
+
+ std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(aCircle->center());
+ std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
+
+ if (!aProjection)
+ aProjection = sketch()->addFeature(SketchPlugin_Circle::ID());
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Circle::CENTER_ID()));
+ aCenterPnt->setValue(aCenterInSketch);
+ aProjection->real(SketchPlugin_Circle::RADIUS_ID())->setValue(aRadius);
+ }
+ else if (anEdge->isArc()) {
+ std::shared_ptr<GeomAPI_Pnt> aFirst = aSketchPlane->project(anEdge->firstPoint());
+ std::shared_ptr<GeomAPI_Pnt> aLast = aSketchPlane->project(anEdge->lastPoint());
+ std::shared_ptr<GeomAPI_Pnt2d> aFirstInSketch = sketch()->to2D(aFirst);
+ std::shared_ptr<GeomAPI_Pnt2d> aLastInSketch = sketch()->to2D(aLast);
+
+ std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
+ std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(aCircle->center());
+ std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
+
+ if (!aProjection)
+ aProjection = sketch()->addFeature(SketchPlugin_Arc::ID());
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Arc::CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Arc::START_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Arc::END_ID()));
+ aStartPnt->setValue(aFirstInSketch);
+ aEndPnt->setValue(aLastInSketch);
+ aCenterPnt->setValue(aCenterInSketch);
+ }
+
+ aProjection->execute();
+ aRefAttr->setObject(aProjection);
+
+ if (theID == EXTERNAL_FEATURE_ID())
+ selection(EXTERNAL_ID())->setValue(aExtFeature->context(), aExtFeature->context()->shape());
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File: SketchPlugin_Projection.h
+// Created: 20 April 2016
+// Author: Artem ZHIDKOV
+
+#ifndef SketchPlugin_Projection_H_
+#define SketchPlugin_Projection_H_
+
+#include "SketchPlugin_SketchEntity.h"
+
+/** \class SketchPlugin_Projection
+ * \ingroup Plugins
+ * \brief Feature for creation of external feature as a projection onto the sketch plane.
+ */
+class SketchPlugin_Projection : public SketchPlugin_SketchEntity
+{
+public:
+ /// Projection feature kind
+ inline static const std::string& ID()
+ {
+ static const std::string MY_PROJECTION_ID("SketchProjection");
+ return MY_PROJECTION_ID;
+ }
+ /// Returns the kind of a feature
+ virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_Projection::ID();
+ return MY_KIND;
+ }
+
+ static const std::string& EXTERNAL_FEATURE_ID()
+ {
+ static std::string MY_EXT_FEATURE_ID("ExternalFeature");
+ return MY_EXT_FEATURE_ID;
+ }
+
+ static const std::string& PROJECTED_FEATURE_ID()
+ {
+ static std::string MY_PROJ_FEATURE_ID("ProjectedFeature");
+ return MY_PROJ_FEATURE_ID;
+ }
+
+ /// Returns true because projected feature is always external
+ virtual bool isFixed()
+ { return true; }
+
+ /// Creates a new part document if needed
+ SKETCHPLUGIN_EXPORT virtual void execute();
+
+ /// Moves the feature
+ /// \param theDeltaX the delta for X coordinate is moved
+ /// \param theDeltaY the delta for Y coordinate is moved
+ SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY);
+
+ /// Called on change of any argument-attribute of this object: for external point
+ SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// Use plugin manager for features creation
+ SketchPlugin_Projection();
+
+protected:
+ /// \brief Initializes attributes of derived class.
+ virtual void initDerivedClassAttributes();
+
+private:
+ /// \brief Find projection of a feature onto sketch plane
+ void computeProjection(const std::string& theID);
+
+ bool myIsComputing;
+};
+
+#endif
#include <ModelAPI_Session.h>
#include <ModelAPI_ResultConstruction.h>
+#include <GeomAPI_Circ.h>
#include <GeomAPI_Lin.h>
#include <GeomAPI_Edge.h>
#include <GeomAPI_Vertex.h>
std::shared_ptr<GeomAPI_Dir> aNormal = aPlane->direction();
return fabs(aNormal->dot(aLineDir)) > tolerance * tolerance;
}
+
+bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ std::string& theError) const
+{
+ if (theAttribute->attributeType() != ModelAPI_AttributeSelection::typeId()) {
+ theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
+ return false;
+ }
+
+ AttributeSelectionPtr aFeatureAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
+ std::shared_ptr<GeomAPI_Edge> anEdge;
+ if(aFeatureAttr && aFeatureAttr->value() && aFeatureAttr->value()->isEdge()) {
+ anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aFeatureAttr->value()));
+ } else if(aFeatureAttr->context() && aFeatureAttr->context()->shape() &&
+ aFeatureAttr->context()->shape()->isEdge()) {
+ anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aFeatureAttr->context()->shape()));
+ }
+
+ if (!anEdge) {
+ theError = "The attribute " + theAttribute->id() + " should be an edge";
+ return false;
+ }
+
+ // find a sketch
+ std::shared_ptr<SketchPlugin_Sketch> aSketch;
+ std::set<AttributePtr> aRefs = theAttribute->owner()->data()->refsToMe();
+ std::set<AttributePtr>::const_iterator anIt = aRefs.begin();
+ for (; anIt != aRefs.end(); ++anIt) {
+ CompositeFeaturePtr aComp =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>((*anIt)->owner());
+ if (aComp && aComp->getKind() == SketchPlugin_Sketch::ID()) {
+ aSketch = std::dynamic_pointer_cast<SketchPlugin_Sketch>(aComp);
+ break;
+ }
+ }
+ if (!aSketch) {
+ theError = "There is no sketch referring to the current feature";
+ return false;
+ }
+
+ std::shared_ptr<GeomAPI_Pln> aPlane = aSketch->plane();
+ std::shared_ptr<GeomAPI_Dir> aNormal = aPlane->direction();
+
+ if (anEdge->isLine()) {
+ std::shared_ptr<GeomAPI_Dir> aLineDir = anEdge->line()->direction();
+ double aDot = aNormal->dot(aLineDir);
+ return aDot > -1.0 + tolerance && aDot < 1.0 - tolerance;
+ }
+ else if (anEdge->isCircle() || anEdge->isArc()) {
+ std::shared_ptr<GeomAPI_Dir> aCircNormal = anEdge->circle()->normal();
+ double aDot = fabs(aNormal->dot(aCircNormal));
+ return fabs(aDot - 1.0) < tolerance * tolerance;
+ }
+
+ return false;
+}
std::string& theError) const;
};
+/**\class SketchPlugin_ProjectionValidator
+ * \ingroup Validators
+ * \brief Validator for the attribute to be projected onto the sketch plane.
+ */
+class SketchPlugin_ProjectionValidator : 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,
+ std::string& theError) const;
+};
+
#endif
<group id="Geometry">
<feature
id="Sketch"
- nested="SketchPoint SketchIntersectionPoint SketchLine SketchCircle SketchArc SketchRectangle SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical SketchConstraintEqual SketchConstraintTangent SketchConstraintFillet SketchConstraintCoincidence SketchConstraintMirror SketchConstraintAngle SketchMultiRotation SketchMultiTranslation SketchConstraintCollinear SketchConstraintMiddle"
+ nested="SketchPoint SketchIntersectionPoint SketchLine SketchCircle SketchArc SketchRectangle SketchProjection SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical SketchConstraintEqual SketchConstraintTangent SketchConstraintFillet SketchConstraintCoincidence SketchConstraintMirror SketchConstraintAngle SketchMultiRotation SketchMultiTranslation SketchConstraintCollinear SketchConstraintMiddle"
when_nested="accept abort"
title="Sketch"
tooltip="Create sketch"
</feature>
</group>
- <!--<group id="Projection"> -->
+ <!--<group id="Projection">-->
<!-- Intersection Point -->
<!-- feature
id="SketchIntersectionPoint"
</sketch_shape_selector>
<boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
</feature -->
+
+ <!-- Projected feature -->
+ <!--<feature
+ id="SketchProjection"
+ title="Projection"
+ tooltip="Project feature onto sketch plane"
+ icon="icons/Sketch/projection.png">
+ <sketch_shape_selector
+ id="ExternalFeature"
+ label="Edge"
+ tooltip="Select external edge."
+ shape_types="edge"
+ use_sketch_plane="false">
+ <validator id="SketchPlugin_ProjectionValidator"/>
+ </sketch_shape_selector>
+ <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
+ </feature> -->
<!--</group>-->
<group id="Replication">