-// Copyright (C) 2014-2019 CEA/DEN, EDF R&D
+// Copyright (C) 2014-2023 CEA, EDF
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
#include <PlaneGCSSolver_ScalarWrapper.h>
#include <PlaneGCSSolver_ScalarArrayWrapper.h>
#include <PlaneGCSSolver_BooleanWrapper.h>
+#include <PlaneGCSSolver_Tools.h>
#include <GeomAPI_Pnt2d.h>
#include <GeomDataAPI_Point2D.h>
#include <ModelAPI_AttributeDoubleArray.h>
#include <ModelAPI_AttributeInteger.h>
#include <SketchPlugin_BSpline.h>
+#include <SketchPlugin_BSplinePeriodic.h>
#include <SketchPlugin_ConstraintAngle.h>
#include <SketchPlugin_MultiRotation.h>
(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() &&
- theAttribute->id() == SketchPlugin_BSpline::DEGREE_ID())
+ 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
return aWrapper;
}
+template <typename TYPE>
+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)
{
- AttributeDoubleArrayPtr anArray =
- std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(theAttribute);
- if (!anArray || !anArray->isInitialized())
+ PlaneGCSSolver_Tools::AttributeArray anArray(theAttribute);
+
+ if (!anArray.isInitialized())
return EntityWrapperPtr();
PlaneGCSSolver_Storage* aStorage = theStorage;
- // Weights of B-spline curve are not processed by the solver
+ // Weights, knots and multiplicities of B-spline curve are not processed by the solver
FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
- if (anOwner->getKind() == SketchPlugin_BSpline::ID() &&
- theAttribute->id() == SketchPlugin_BSpline::WEIGHTS_ID())
+ if (nonSolverAttribute<SketchPlugin_BSpline>(anOwner, theAttribute->id()) ||
+ nonSolverAttribute<SketchPlugin_BSplinePeriodic>(anOwner, theAttribute->id()))
aStorage = 0;
- int aSize = anArray->size();
+ 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);
+ *aParam = anArray.value(index);
aParameters.push_back(aParam);
}
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<PlaneGCSSolver_PointArrayWrapper> aWrapper =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointArrayWrapper>(theEntity);
+ std::shared_ptr<GeomDataAPI_Point2DArray> anAttribute =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(theAttribute);
+
+ std::vector<PointWrapperPtr> aPointsArray = aWrapper->array();
+ std::vector<PointWrapperPtr>::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<PointWrapperPtr>::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<PlaneGCSSolver_ScalarArrayWrapper> aWrapper =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(theEntity);
+ if (aWrapper->size() != PlaneGCSSolver_Tools::AttributeArray(theAttribute).size()) {
+ aParamsToRemove = PlaneGCSSolver_Tools::parameters(aWrapper);
+ std::shared_ptr<PlaneGCSSolver_ScalarArrayWrapper> aNewArray =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(
+ 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);
+}