X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FPlaneGCSSolver%2FPlaneGCSSolver_AttributeBuilder.cpp;h=439a18f17be450dc0d5ee3f1b08f3261ded27311;hb=645e2cb70c0e40290725f28fdc5fec8a93338d28;hp=ca463c53d70f063745d9f062bf7c250cc6810d24;hpb=8038897b81335a9ec1ff08522ff652299cd2ff3f;p=modules%2Fshaper.git diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp index ca463c53d..439a18f17 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp @@ -19,12 +19,21 @@ #include #include +#include #include #include +#include #include +#include +#include #include +#include #include +#include +#include +#include +#include #include #include @@ -58,9 +67,17 @@ static EntityWrapperPtr createBoolean(const AttributePtr& theAttribute) static EntityWrapperPtr createScalar(const AttributePtr& theAttribute, PlaneGCSSolver_Storage* theStorage) { - AttributeDoublePtr aScalar = std::dynamic_pointer_cast(theAttribute); - if (!aScalar) - return EntityWrapperPtr(); + double aValue = 0.0; + AttributeDoublePtr aDouble = std::dynamic_pointer_cast(theAttribute); + if (aDouble) + aValue = aDouble->isInitialized() ? aDouble->value() : 0.0; + else { + AttributeIntegerPtr anInt = std::dynamic_pointer_cast(theAttribute); + if (anInt) + aValue = anInt->isInitialized() ? anInt->value() : 0.0; + else + return EntityWrapperPtr(); + } ScalarWrapperPtr aWrapper; // following attributes should be converted from degrees to radians @@ -72,14 +89,66 @@ static EntityWrapperPtr createScalar(const AttributePtr& theAttribute, (theAttribute->id() == SketchPlugin_MultiRotation::ANGLE_ID() && anOwner->getKind() == SketchPlugin_MultiRotation::ID())) aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_AngleWrapper(createParameter(theStorage))); + else if ((anOwner->getKind() == SketchPlugin_BSpline::ID() || + anOwner->getKind() == SketchPlugin_BSplinePeriodic::ID()) && + theAttribute->id() == SketchPlugin_BSplineBase::DEGREE_ID()) + // Degree of B-spline is not processed by the solver + aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(nullptr))); else aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(theStorage))); - if (aScalar->isInitialized()) - aWrapper->setValue(aScalar->value()); + aWrapper->setValue(aValue); return aWrapper; } +template +static bool nonSolverAttribute(const FeaturePtr theOwner, const std::string& theAttrId) +{ + return theOwner->getKind() == TYPE::ID() && (theAttrId == TYPE::WEIGHTS_ID() + || theAttrId == TYPE::KNOTS_ID() || theAttrId == TYPE::MULTS_ID()); +} + +static EntityWrapperPtr createScalarArray(const AttributePtr& theAttribute, + PlaneGCSSolver_Storage* theStorage) +{ + PlaneGCSSolver_Tools::AttributeArray anArray(theAttribute); + + if (!anArray.isInitialized()) + return EntityWrapperPtr(); + + PlaneGCSSolver_Storage* aStorage = theStorage; + // Weights, knots and multiplicities of B-spline curve are not processed by the solver + FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner()); + if (nonSolverAttribute(anOwner, theAttribute->id()) || + nonSolverAttribute(anOwner, theAttribute->id())) + aStorage = 0; + + int aSize = anArray.size(); + GCS::VEC_pD aParameters; + aParameters.reserve(aSize); + for (int index = 0; index < aSize; ++index) { + double* aParam = createParameter(aStorage); + *aParam = anArray.value(index); + aParameters.push_back(aParam); + } + + return EntityWrapperPtr(new PlaneGCSSolver_ScalarArrayWrapper(aParameters)); +} + +static PointWrapperPtr createPoint(const GeomPnt2dPtr& thePoint, PlaneGCSSolver_Storage* theStorage) +{ + GCSPointPtr aNewPoint(new GCS::Point); + + aNewPoint->x = createParameter(theStorage); + aNewPoint->y = createParameter(theStorage); + if (thePoint) { + *(aNewPoint->x) = thePoint->x(); + *(aNewPoint->y) = thePoint->y(); + } + + return PointWrapperPtr(new PlaneGCSSolver_PointWrapper(aNewPoint)); +} + static EntityWrapperPtr createPoint(const AttributePtr& theAttribute, PlaneGCSSolver_Storage* theStorage) { @@ -88,16 +157,29 @@ static EntityWrapperPtr createPoint(const AttributePtr& theAttribute, if (!aPoint2D) return EntityWrapperPtr(); - GCSPointPtr aNewPoint(new GCS::Point); + GeomPnt2dPtr aPnt; + if (aPoint2D->isInitialized()) + aPnt = aPoint2D->pnt(); - aNewPoint->x = createParameter(theStorage); - aNewPoint->y = createParameter(theStorage); - if (aPoint2D->isInitialized()) { - *(aNewPoint->x) = aPoint2D->x(); - *(aNewPoint->y) = aPoint2D->y(); - } + return createPoint(aPnt, theStorage); +} + +static EntityWrapperPtr createPointArray(const AttributePtr& theAttribute, + PlaneGCSSolver_Storage* theStorage) +{ + std::shared_ptr aPointArray = + std::dynamic_pointer_cast(theAttribute); + if (!aPointArray) + return EntityWrapperPtr(); + + int aSize = aPointArray->size(); - return EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(aNewPoint)); + std::vector aPointWrappers; + aPointWrappers.reserve(aSize); + for (int index = 0; index < aSize; ++index) + aPointWrappers.push_back(createPoint(aPointArray->pnt(index), theStorage)); + + return EntityWrapperPtr(new PlaneGCSSolver_PointArrayWrapper(aPointWrappers)); } EntityWrapperPtr PlaneGCSSolver_AttributeBuilder::createAttribute( @@ -112,7 +194,85 @@ EntityWrapperPtr PlaneGCSSolver_AttributeBuilder::createAttribute( aResult = createScalar(theAttribute, myStorage); if (!aResult) aResult = createBoolean(theAttribute); + if (!aResult) + aResult = createPointArray(theAttribute, myStorage); + if (!aResult) + aResult = createScalarArray(theAttribute, myStorage); if (aResult && !myStorage) aResult->setExternal(true); return aResult; } + +bool PlaneGCSSolver_AttributeBuilder::updateAttribute( + AttributePtr theAttribute, + EntityWrapperPtr theEntity) +{ + bool isUpdated = false; + GCS::SET_pD aParamsToRemove; + // rebuild array if its size is changed + if (theEntity->type() == ENTITY_POINT_ARRAY) { + std::shared_ptr aWrapper = + std::dynamic_pointer_cast(theEntity); + std::shared_ptr anAttribute = + std::dynamic_pointer_cast(theAttribute); + + std::vector aPointsArray = aWrapper->array(); + std::vector::iterator aPos = aPointsArray.begin(); + if (aWrapper->size() != anAttribute->size()) { + while (anAttribute->size() > (int)aPointsArray.size()) { + // add points to the middle of array + GeomPnt2dPtr aValue; + for (; aPos != aPointsArray.end(); ++aPos) { + aValue = anAttribute->pnt(aPos - aPointsArray.begin()); + if (aValue->distance(PlaneGCSSolver_Tools::point(*aPos)) > tolerance) + break; + } + int aShift = aPos - aPointsArray.begin(); + aPointsArray.insert(aPos, createPoint(aValue, myStorage)); + aPos = aPointsArray.begin() + aShift; + } + + while (anAttribute->size() < (int)aPointsArray.size()) { + // remove middle points + std::vector::iterator anIt = --aPointsArray.end(); + GCS::SET_pD aParams = PlaneGCSSolver_Tools::parameters(*anIt); + aParamsToRemove.insert(aParams.begin(), aParams.end()); + aPointsArray.erase(anIt); + } + + aWrapper->setArray(aPointsArray); + } + else { + // update coordinates of points + for (int anIndex = 0; aPos != aPointsArray.end(); ++aPos, ++anIndex) { + const GCSPointPtr& aGCSPoint = (*aPos)->point(); + GeomPnt2dPtr aCoord = anAttribute->pnt(anIndex); + *aGCSPoint->x = aCoord->x(); + *aGCSPoint->y = aCoord->y(); + } + } + } + else if (theEntity->type() == ENTITY_SCALAR_ARRAY) { + std::shared_ptr aWrapper = + std::dynamic_pointer_cast(theEntity); + if (aWrapper->size() != PlaneGCSSolver_Tools::AttributeArray(theAttribute).size()) { + aParamsToRemove = PlaneGCSSolver_Tools::parameters(aWrapper); + std::shared_ptr aNewArray = + std::dynamic_pointer_cast( + createScalarArray(theAttribute, myStorage)); + aWrapper->setArray(aNewArray->array()); + isUpdated = true; + } + } + + if (!aParamsToRemove.empty()) { + if (myStorage) + myStorage->removeParameters(aParamsToRemove); + else { + std::for_each(aParamsToRemove.begin(), aParamsToRemove.end(), + [](double* theParam) { delete theParam; }); + } + } + + return isUpdated || theEntity->update(theAttribute); +}