#include <GeomAPI_Edge.h>
#include <GeomAPI_Ellipse.h>
#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_Wire.h>
+#include <GeomAPI_WireExplorer.h>
#include <GeomDataAPI_Point2D.h>
#include <GeomDataAPI_Point2DArray.h>
#include <iostream>
+static const double tolerance = 1.e-7;
+
SketchPlugin_Offset::SketchPlugin_Offset()
{
}
AttributeDoublePtr aValueAttr = real(VALUE_ID());
if (!aValueAttr->isInitialized()) return;
double aValue = aValueAttr->value();
- const double tolerance = 1.e-7;
if (aValue < tolerance) return;
// 2.a. Reversed?
std::shared_ptr<GeomAlgoAPI_WireBuilder> aWireBuilder(
new GeomAlgoAPI_WireBuilder(aTopoChain));
- // 5.d. Make offset for each wire
+ GeomShapePtr aWireShape = aWireBuilder->shape();
+ GeomWirePtr aWire (new GeomAPI_Wire (aWireShape));
+
+ // Fix for a problem of offset side change with selection change.
+ // Wire direction is defined by the first selected edge of this wire.
+ if (!aWire->isClosed()) {
+ ListOfShape aModified;
+ // First selected edge of current chain
+ GeomShapePtr aFirstSel = aFeature->lastResult()->shape();
+ aWireBuilder->modified(aFirstSel, aModified);
+ GeomShapePtr aModFS = aModified.front();
+ if (aModFS->orientation() != aFirstSel->orientation())
+ aValue = -aValue;
+ }
+
+ // 5.d. Make offset for the wire
std::shared_ptr<GeomAlgoAPI_Offset> anOffsetShape(
- new GeomAlgoAPI_Offset(aPlane, aWireBuilder->shape(), aValue));
+ new GeomAlgoAPI_Offset(aPlane, aWireShape, aValue));
std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeList(new GeomAlgoAPI_MakeShapeList);
aMakeList->appendAlgo(aWireBuilder);
// 1. Find a single edge, coincident to theEndPoint by one of its ends
if (!theEndPoint) return false;
- std::shared_ptr<GeomAPI_Pnt2d> aP2d = theEndPoint->pnt();
-
FeaturePtr aNextEdgeFeature;
int nbFound = 0;
for (; aPointsIt != anAllCoincPoints.end(); aPointsIt++) {
AttributePtr aP = (*aPointsIt);
FeaturePtr aCoincFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aP->owner());
+ bool isInSet = (theEdgesSet.find(aCoincFeature) != theEdgesSet.end());
// Condition 0: not auxiliary
- if (aCoincFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()) continue;
+ if (!isInSet && aCoincFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value())
+ continue;
// Condition 1: not a point feature
if (aCoincFeature->getKind() != SketchPlugin_Point::ID()) {
if (aCoincFeature != theEdge) {
// Condition 3: it is in the set of interest.
// Empty set means all sketch edges.
- bool isInSet = true;
- if (theEdgesSet.size()) {
- isInSet = (theEdgesSet.find(aCoincFeature) != theEdgesSet.end());
- }
- if (isInSet) {
+ if (isInSet || theEdgesSet.empty()) {
// Condition 4: consider only features with two end points
std::shared_ptr<GeomDataAPI_Point2D> aP1, aP2;
SketchPlugin_SegmentationTools::getFeaturePoints(aCoincFeature, aP1, aP2);
theList->append(theValue);
}
+// Reorder shapes according to the wire's order
+static void reorderShapes(ListOfShape& theShapes, GeomShapePtr theWire)
+{
+ std::set<GeomShapePtr, GeomAPI_Shape::Comparator> aShapes;
+ aShapes.insert(theShapes.begin(), theShapes.end());
+ theShapes.clear();
+
+ GeomWirePtr aWire(new GeomAPI_Wire(theWire));
+ GeomAPI_WireExplorer anExp(aWire);
+ for (; anExp.more(); anExp.next()) {
+ GeomShapePtr aCurEdge = anExp.current();
+ auto aFound = aShapes.find(aCurEdge);
+ if (aFound != aShapes.end()) {
+ theShapes.push_back(aCurEdge);
+ aShapes.erase(aFound);
+ }
+ }
+}
+
static void removeLastFromIndex(AttributeRefListPtr theList, int theListSize, int& theLastIndex)
{
if (theLastIndex < theListSize) {
GeomShapePtr aBaseShape = aBaseFeature->lastResult()->shape();
ListOfShape aNewShapes;
for (ListOfMakeShape::const_iterator anAlgoIt = theOffsetAlgos.begin();
- anAlgoIt != theOffsetAlgos.end() && aNewShapes.empty(); ++anAlgoIt) {
+ anAlgoIt != theOffsetAlgos.end(); ++anAlgoIt) {
(*anAlgoIt)->generated(aBaseShape, aNewShapes);
+ if (!aNewShapes.empty()) {
+ reorderShapes(aNewShapes, (*anAlgoIt)->shape());
+ break;
+ }
}
// store base feature
FeaturePtr& theFeature,
std::list<ObjectPtr>& thePoolOfFeatures)
{
+ if (theFeature) {
+ // check the feature type is the same as required
+ if (theFeature->getKind() != theFeatureKind) {
+ // return feature to the pool and try to find the most appropriate
+ thePoolOfFeatures.push_back(theFeature);
+ theFeature = FeaturePtr();
+ }
+ }
if (!theFeature) {
// try to find appropriate feature in the pool
for (std::list<ObjectPtr>::iterator it = thePoolOfFeatures.begin();
findOrCreateFeatureByKind(sketch(), SketchPlugin_Arc::ID(), theFeature, thePoolOfFeatures);
+ GeomDirPtr aCircNormal = aCircEdge->normal();
+ GeomDirPtr aSketchNormal = sketch()->coordinatePlane()->normal();
+ if (aSketchNormal->dot(aCircNormal) < -tolerance)
+ std::swap(aFP, aLP);
+
bool aWasBlocked = theFeature->data()->blockSendAttributeUpdated(true);
std::dynamic_pointer_cast<GeomDataAPI_Point2D>
- (theFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->setValue(aCP);
+ (theFeature->attribute(SketchPlugin_Arc::END_ID()))->setValue(aLP);
std::dynamic_pointer_cast<GeomDataAPI_Point2D>
(theFeature->attribute(SketchPlugin_Arc::START_ID()))->setValue(aFP);
std::dynamic_pointer_cast<GeomDataAPI_Point2D>
- (theFeature->attribute(SketchPlugin_Arc::END_ID()))->setValue(aLP);
+ (theFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->setValue(aCP);
theFeature->data()->blockSendAttributeUpdated(aWasBlocked);
}
else if (aResEdge->isCircle()) {
(theFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()))->setValue(aCP);
std::dynamic_pointer_cast<GeomDataAPI_Point2D>
(theFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()))->setValue(aFocus);
- theFeature->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue(anEllipseEdge->minorRadius());
+ theFeature->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue(
+ anEllipseEdge->minorRadius());
}
}
else {
{
GeomCurvePtr aCurve (new GeomAPI_Curve (theEdge));
// Forced conversion to b-spline, if aCurve is not b-spline
- GeomAPI_BSpline aBSpline (aCurve, /*isForced*/true);
+ GeomBSplinePtr aBSpline = GeomAPI_BSpline::convertToBSpline(aCurve);
- const std::string& aBSplineKind = aBSpline.isPeriodic() ? SketchPlugin_BSplinePeriodic::ID()
- : SketchPlugin_BSpline::ID();
+ const std::string& aBSplineKind = aBSpline->isPeriodic() ? SketchPlugin_BSplinePeriodic::ID()
+ : SketchPlugin_BSpline::ID();
findOrCreateFeatureByKind(sketch(), aBSplineKind, theResult, thePoolOfFeatures);
- theResult->integer(SketchPlugin_BSpline::DEGREE_ID())->setValue(aBSpline.degree());
+ theResult->integer(SketchPlugin_BSpline::DEGREE_ID())->setValue(aBSpline->degree());
AttributePoint2DArrayPtr aPolesAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>
(theResult->attribute(SketchPlugin_BSpline::POLES_ID()));
- std::list<GeomPointPtr> aPoles = aBSpline.poles();
+ std::list<GeomPointPtr> aPoles = aBSpline->poles();
aPolesAttr->setSize((int)aPoles.size());
std::list<GeomPointPtr>::iterator anIt = aPoles.begin();
for (int anIndex = 0; anIt != aPoles.end(); ++anIt, ++anIndex) {
AttributeDoubleArrayPtr aWeightsAttr =
theResult->data()->realArray(SketchPlugin_BSpline::WEIGHTS_ID());
- std::list<double> aWeights = aBSpline.weights();
+ std::list<double> aWeights = aBSpline->weights();
if (aWeights.empty()) { // rational B-spline
int aSize = (int)aPoles.size();
aWeightsAttr->setSize(aSize);
AttributeDoubleArrayPtr aKnotsAttr =
theResult->data()->realArray(SketchPlugin_BSpline::KNOTS_ID());
- std::list<double> aKnots = aBSpline.knots();
+ std::list<double> aKnots = aBSpline->knots();
int aSize = (int)aKnots.size();
aKnotsAttr->setSize(aSize);
std::list<double>::iterator aKIt = aKnots.begin();
AttributeIntArrayPtr aMultsAttr =
theResult->data()->intArray(SketchPlugin_BSpline::MULTS_ID());
- std::list<int> aMultiplicities = aBSpline.mults();
+ std::list<int> aMultiplicities = aBSpline->mults();
aSize = (int)aMultiplicities.size();
aMultsAttr->setSize(aSize);
std::list<int>::iterator aMIt = aMultiplicities.begin();
}
}
+ bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+
// Gather chains of edges
for (anEdgesIt = anEdgesList.begin(); anEdgesIt != anEdgesList.end(); anEdgesIt++) {
FeaturePtr aFeature = ModelAPI_Feature::feature(*anEdgesIt);
}
// TODO: hilight selection in the viewer
+ data()->blockSendAttributeUpdated(aWasBlocked);
return true;
}