From e7c4184a3752e98c384b35e812120fcadc92c194 Mon Sep 17 00:00:00 2001 From: azv Date: Wed, 22 Apr 2015 11:02:20 +0300 Subject: [PATCH] Implementation of multi-translation and multi-rotation --- src/SketchPlugin/CMakeLists.txt | 4 + .../SketchPlugin_MultiRotation.cpp | 267 ++++++++++++++++++ src/SketchPlugin/SketchPlugin_MultiRotation.h | 87 ++++++ .../SketchPlugin_MultiTranslation.cpp | 246 ++++++++++++++++ .../SketchPlugin_MultiTranslation.h | 86 ++++++ src/SketchPlugin/SketchPlugin_Plugin.cpp | 8 + src/SketchPlugin/SketchPlugin_Validators.cpp | 34 +++ src/SketchPlugin/SketchPlugin_Validators.h | 18 ++ src/SketchPlugin/plugin-Sketch.xml | 57 +++- 9 files changed, 806 insertions(+), 1 deletion(-) create mode 100644 src/SketchPlugin/SketchPlugin_MultiRotation.cpp create mode 100644 src/SketchPlugin/SketchPlugin_MultiRotation.h create mode 100644 src/SketchPlugin/SketchPlugin_MultiTranslation.cpp create mode 100644 src/SketchPlugin/SketchPlugin_MultiTranslation.h diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index f7e3f9aca..b4aa3d2cd 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -28,6 +28,8 @@ SET(PROJECT_HEADERS SketchPlugin_ConstraintTangent.h SketchPlugin_ConstraintMirror.h SketchPlugin_ConstraintFillet.h + SketchPlugin_MultiRotation.h + SketchPlugin_MultiTranslation.h SketchPlugin_ExternalValidator.h SketchPlugin_Validators.h ) @@ -55,6 +57,8 @@ SET(PROJECT_SOURCES SketchPlugin_ConstraintTangent.cpp SketchPlugin_ConstraintMirror.cpp SketchPlugin_ConstraintFillet.cpp + SketchPlugin_MultiRotation.cpp + SketchPlugin_MultiTranslation.cpp SketchPlugin_ExternalValidator.cpp SketchPlugin_Validators.cpp ) diff --git a/src/SketchPlugin/SketchPlugin_MultiRotation.cpp b/src/SketchPlugin/SketchPlugin_MultiRotation.cpp new file mode 100644 index 000000000..130a8ff62 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_MultiRotation.cpp @@ -0,0 +1,267 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_MultiRotation.cpp +// Created: 21 Apr 2015 +// Author: Artem ZHIDKOV + +#include "SketchPlugin_MultiRotation.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define PI 3.1415926535897932 + +SketchPlugin_MultiRotation::SketchPlugin_MultiRotation() +{ +} + +void SketchPlugin_MultiRotation::initAttributes() +{ + data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(ANGLE_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(NUMBER_OF_COPIES_ID(), ModelAPI_AttributeDouble::typeId()/*ModelAPI_AttributeInteger::typeId()*/); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefList::typeId()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId()); + AttributeSelectionListPtr aSelection = + std::dynamic_pointer_cast(data()->addAttribute( + ROTATION_LIST_ID(), ModelAPI_AttributeSelectionList::typeId())); + aSelection->setSelectionType("EDGE"); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_A()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B()); +} + +void SketchPlugin_MultiRotation::execute() +{ + AttributeSelectionListPtr aRotationObjectRefs = selectionList(ROTATION_LIST_ID()); + int aNbCopies = (int)(std::dynamic_pointer_cast( + attribute(NUMBER_OF_COPIES_ID()))->value()); + + // Obtain center and angle of rotation + std::shared_ptr aCenter = std::dynamic_pointer_cast( + attribute(CENTER_ID())); + if (!aCenter || !aCenter->isInitialized()) + return; + double anAngle = std::dynamic_pointer_cast( + attribute(ANGLE_ID()))->value(); + // Convert angle to radians + anAngle *= PI / 180.0; + + // Wait all objects being created, then send update events + static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent); + if (isUpdateFlushed) + Events_Loop::loop()->setFlushed(anUpdateEvent, false); + + std::shared_ptr aData = data(); + AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::ENTITY_A())); + AttributeRefListPtr aRefListOfRotated = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::ENTITY_B())); + int aCurrentNbCopies = aRefListOfShapes->size() ? + aRefListOfRotated->size() / aRefListOfShapes->size() - 1 : 0; + std::list anInitialList = aRefListOfShapes->list(); + std::list aTargetList = aRefListOfRotated->list(); + std::list anAddition; + std::vector isUsed(anInitialList.size(), false); + // collect new items and check the items to remove + for(int anInd = 0; anInd < aRotationObjectRefs->size(); anInd++) { + std::shared_ptr aSelect = aRotationObjectRefs->value(anInd); + std::list::const_iterator anIt = anInitialList.begin(); + std::vector::iterator aUsedIt = isUsed.begin(); + for (; anIt != anInitialList.end(); anIt++, aUsedIt++) + if (*anIt == aSelect->context()) { + *aUsedIt = true; + break; + } + if (anIt == anInitialList.end()) + anAddition.push_back(aSelect->context()); + } + // remove unused items + std::list::iterator anInitIter = anInitialList.begin(); + std::list::iterator aTargetIter = aTargetList.begin(); + std::vector::iterator aUsedIter = isUsed.begin(); + for (; aUsedIter != isUsed.end(); aUsedIter++) { + if (!(*aUsedIter)) { + aRefListOfShapes->remove(*anInitIter); + for (int i = 0; i < aCurrentNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++) { + aRefListOfRotated->remove(*aTargetIter); + // remove the corresponding feature from the sketch + ResultConstructionPtr aRC = + std::dynamic_pointer_cast(*aTargetIter); + DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr(); + FeaturePtr aFeature = aDoc ? aDoc->feature(aRC) : FeaturePtr(); + if (aFeature) + aDoc->removeFeature(aFeature); + } + } else { + for (int i = 0; i <= aNbCopies && aTargetIter != aTargetList.end(); i++) + aTargetIter++; + } + if (anInitIter != anInitialList.end()) + anInitIter++; + } + // change number of copies + if (aCurrentNbCopies != 0 && aNbCopies != aCurrentNbCopies) { + bool isAdd = aNbCopies > aCurrentNbCopies; + int aMinCopies = isAdd ? aCurrentNbCopies : aNbCopies; + int aMaxCopies = isAdd ? aNbCopies : aCurrentNbCopies; + int ind = 0; + + aTargetList = aRefListOfRotated->list(); + aTargetIter = aTargetList.begin(); + ObjectPtr anObjToCopy = *aTargetIter; + while (aTargetIter != aTargetList.end()) { + aRefListOfRotated->remove(*aTargetIter); + aTargetIter++; + ind++; + if (ind > aMinCopies && ind <=aMaxCopies) { + while (ind <= aMaxCopies) { + if (isAdd) { + // Add new shifted item + ObjectPtr anObject = copyFeature(anObjToCopy); + aTargetList.insert(aTargetIter, anObject); + } else { + // remove object + std::list::iterator aRemoveIt = aTargetIter; + ObjectPtr anObject = *(--aRemoveIt); + aTargetList.erase(aRemoveIt); + // remove the corresponding feature from the sketch + ResultConstructionPtr aRC = + std::dynamic_pointer_cast(anObject); + DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr(); + FeaturePtr aFeature = aDoc ? aDoc->feature(aRC) : FeaturePtr(); + if (aFeature) + aDoc->removeFeature(aFeature); + } + ind++; + } + ind = 0; + if (aTargetIter != aTargetList.end()) + anObjToCopy = *aTargetIter; + } + } + + for (aTargetIter = aTargetList.begin(); aTargetIter != aTargetList.end(); aTargetIter++) + aRefListOfRotated->append(*aTargetIter); + } + // add new items + std::list::iterator anAddIter = anAddition.begin(); + for (; anAddIter != anAddition.end(); anAddIter++) { + aRefListOfShapes->append(*anAddIter); + aRefListOfRotated->append(*anAddIter); + for (int i = 0; i < aNbCopies; i++) { + ObjectPtr anObject = copyFeature(*anAddIter); + aRefListOfRotated->append(anObject); + } + } + + if (fabs(anAngle) > 1.e-12) { + // Recalculate positions of features + aTargetList = aRefListOfRotated->list(); + aTargetIter = aTargetList.begin(); + while (aTargetIter != aTargetList.end()) { + ObjectPtr anInitialObject = *aTargetIter++; + for (int i = 0; i < aNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++) + rotateFeature(anInitialObject, *aTargetIter, aCenter->x(), aCenter->y(), anAngle * (i + 1)); + } + } + + // send events to update the sub-features by the solver + if (isUpdateFlushed) + Events_Loop::loop()->setFlushed(anUpdateEvent, true); +} + +AISObjectPtr SketchPlugin_MultiRotation::getAISObject(AISObjectPtr thePrevious) +{ + if (!sketch()) + return thePrevious; + + AISObjectPtr anAIS = thePrevious; + if (!anAIS) { +// TODO: +// anAIS = SketcherPrs_Factory::mirrorConstraint(this, sketch()->coordinatePlane()); + } + return anAIS; +} + + +ObjectPtr SketchPlugin_MultiRotation::copyFeature(ObjectPtr theObject) +{ + ResultPtr aResult = std::dynamic_pointer_cast(theObject); + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + if (!aFeature || !aResult) + return ObjectPtr(); + + FeaturePtr aNewFeature = sketch()->addFeature(aFeature->getKind()); + aFeature->data()->copyTo(aNewFeature->data()); + aNewFeature->execute(); + + static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); + ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent); + + std::shared_ptr aShapeIn = aResult->shape(); + const std::list& aResults = aNewFeature->results(); + std::list::const_iterator anIt = aResults.begin(); + for (; anIt != aResults.end(); anIt++) { + ResultConstructionPtr aRC = std::dynamic_pointer_cast(*anIt); + if (!aRC) continue; + std::shared_ptr aShapeOut = aRC->shape(); + if ((aShapeIn->isVertex() && aShapeOut->isVertex()) || + (aShapeIn->isEdge() && aShapeOut->isEdge()) || + (aShapeIn->isFace() && aShapeOut->isFace())) + return aRC; + } + return ObjectPtr(); +} + +void SketchPlugin_MultiRotation::rotateFeature( + ObjectPtr theInitial, ObjectPtr theTarget, + double theCenterX, double theCenterY, double theAngle) +{ + std::shared_ptr aCenter(new GeomAPI_Pnt2d(theCenterX, theCenterY)); + double cosA = cos(theAngle); + double sinA = sin(theAngle); + + FeaturePtr anInitialFeature = ModelAPI_Feature::feature(theInitial); + FeaturePtr aTargetFeature = ModelAPI_Feature::feature(theTarget); + + // block feature update + aTargetFeature->data()->blockSendAttributeUpdated(true); + + std::list anInitAttrList = + anInitialFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::list aTargetAttrList = + aTargetFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::list::iterator anInitIt = anInitAttrList.begin(); + std::list::iterator aTargetIt = aTargetAttrList.begin(); + for (; anInitIt != anInitAttrList.end(); anInitIt++, aTargetIt++) { + std::shared_ptr aPointFrom = + std::dynamic_pointer_cast(*anInitIt); + std::shared_ptr aPointTo = + std::dynamic_pointer_cast(*aTargetIt); + std::shared_ptr aPnt = aPointFrom->pnt()->xy(); + if (aPnt->distance(aCenter->xy()) > 1.e-7) { + std::shared_ptr aDir = aPnt->decreased(aCenter->xy()); + double dx = cosA * aDir->x() - sinA * aDir->y(); + double dy = sinA * aDir->x() + cosA * aDir->y(); + aPnt->setX(aCenter->x() + dx); + aPnt->setY(aCenter->y() + dy); + } + aPointTo->setValue(aPnt->x(), aPnt->y()); + } + + // unblock feature update + aTargetFeature->data()->blockSendAttributeUpdated(false); +} + diff --git a/src/SketchPlugin/SketchPlugin_MultiRotation.h b/src/SketchPlugin/SketchPlugin_MultiRotation.h new file mode 100644 index 000000000..e743386f4 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_MultiRotation.h @@ -0,0 +1,87 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_MultiRotation.h +// Created: 21 Apr 2015 +// Author: Artem ZHIDKOV + +#ifndef SketchPlugin_MultiRotation_H_ +#define SketchPlugin_MultiRotation_H_ + +#include "SketchPlugin.h" +#include +#include "SketchPlugin_ConstraintBase.h" + +/** \class SketchPlugin_MultiRotation + * \ingroup Plugins + * \brief Feature for creation of a number of rotated copies of a list of objects + * + * This constraint has two attributes: + * SketchPlugin_Constraint::ENTITY_A() for initial list of objects and + * SketchPlugin_Constraint::ENTITY_B() for the list of created objects + * + * The list of created objects contains a number of copies of each object given in + * the NUMBER_OF_COPIES_ID() attribute plus 1 (the initial objects are stored into this + * attribute too). At the start of the list, there are collected N copies + * of first object from initial list, then N copies of second object etc. + */ +class SketchPlugin_MultiRotation : public SketchPlugin_ConstraintBase +{ + public: + /// Multi-rotation kind + inline static const std::string& ID() + { + static const std::string MY_CONSTRAINT_ROTATION_ID("SketchMultiRotation"); + return MY_CONSTRAINT_ROTATION_ID; + } + /// \brief Returns the kind of a feature + SKETCHPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = SketchPlugin_MultiRotation::ID(); + return MY_KIND; + } + + /// List of objects to be mirrored + inline static const std::string& ROTATION_LIST_ID() + { + static const std::string MY_ROTATION_LIST_ID("MultiRotationList"); + return MY_ROTATION_LIST_ID; + } + + /// Center of rotation + inline static const std::string& CENTER_ID() + { + static const std::string MY_CENTER_ID("MultiRotationCenter"); + return MY_CENTER_ID; + } + /// End point of translation + inline static const std::string& ANGLE_ID() + { + static const std::string MY_ANGLE_ID("MultiRotationAngle"); + return MY_ANGLE_ID; + } + /// Number of translated objects + inline static const std::string& NUMBER_OF_COPIES_ID() + { + static const std::string MY_NUMBER_OF_COPIES_ID("MultiRotationCopies"); + return MY_NUMBER_OF_COPIES_ID; + } + + /// \brief Creates a new part document if needed + SKETCHPLUGIN_EXPORT virtual void execute(); + + /// \brief Request for initialization of data model of the feature: adding all attributes + SKETCHPLUGIN_EXPORT virtual void initAttributes(); + + /// Returns the AIS preview + SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious); + + /// \brief Use plugin manager for features creation + SketchPlugin_MultiRotation(); + +private: + ObjectPtr copyFeature(ObjectPtr theObject); + void rotateFeature(ObjectPtr theInitial, ObjectPtr theTarget, + double theCenterX, double theCenterY, double theAngle); +}; + +#endif diff --git a/src/SketchPlugin/SketchPlugin_MultiTranslation.cpp b/src/SketchPlugin/SketchPlugin_MultiTranslation.cpp new file mode 100644 index 000000000..a59283eb5 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_MultiTranslation.cpp @@ -0,0 +1,246 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_MultiTranslation.cpp +// Created: 21 Apr 2015 +// Author: Artem ZHIDKOV + +#include "SketchPlugin_MultiTranslation.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +SketchPlugin_MultiTranslation::SketchPlugin_MultiTranslation() +{ +} + +void SketchPlugin_MultiTranslation::initAttributes() +{ + data()->addAttribute(START_POINT_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(END_POINT_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(NUMBER_OF_COPIES_ID(), ModelAPI_AttributeDouble::typeId()/*ModelAPI_AttributeInteger::typeId()*/); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefList::typeId()); + data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId()); + AttributeSelectionListPtr aSelection = + std::dynamic_pointer_cast(data()->addAttribute( + TRANSLATION_LIST_ID(), ModelAPI_AttributeSelectionList::typeId())); + aSelection->setSelectionType("EDGE"); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_A()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B()); +} + +void SketchPlugin_MultiTranslation::execute() +{ + AttributeSelectionListPtr aTranslationObjectRefs = selectionList(TRANSLATION_LIST_ID()); + int aNbCopies = (int)(std::dynamic_pointer_cast( + attribute(NUMBER_OF_COPIES_ID()))->value()); + + // Calculate shift vector + std::shared_ptr aStart = std::dynamic_pointer_cast( + attribute(START_POINT_ID())); + std::shared_ptr aEnd = std::dynamic_pointer_cast( + attribute(END_POINT_ID())); + if (!aStart || !aEnd || !aStart->isInitialized() || !aEnd->isInitialized()) + return; + std::shared_ptr aShiftVec(new GeomAPI_XY(aEnd->x() - aStart->x(), aEnd->y() - aStart->y())); + + // Wait all objects being created, then send update events + static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent); + if (isUpdateFlushed) + Events_Loop::loop()->setFlushed(anUpdateEvent, false); + + std::shared_ptr aData = data(); + AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::ENTITY_A())); + AttributeRefListPtr aRefListOfTranslated = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::ENTITY_B())); + int aCurrentNbCopies = aRefListOfShapes->size() ? + aRefListOfTranslated->size() / aRefListOfShapes->size() - 1 : 0; + std::list anInitialList = aRefListOfShapes->list(); + std::list aTargetList = aRefListOfTranslated->list(); + std::list anAddition; + std::vector isUsed(anInitialList.size(), false); + // collect new items and check the items to remove + for(int anInd = 0; anInd < aTranslationObjectRefs->size(); anInd++) { + std::shared_ptr aSelect = aTranslationObjectRefs->value(anInd); + std::list::const_iterator anIt = anInitialList.begin(); + std::vector::iterator aUsedIt = isUsed.begin(); + for (; anIt != anInitialList.end(); anIt++, aUsedIt++) + if (*anIt == aSelect->context()) { + *aUsedIt = true; + break; + } + if (anIt == anInitialList.end()) + anAddition.push_back(aSelect->context()); + } + // remove unused items + std::list::iterator anInitIter = anInitialList.begin(); + std::list::iterator aTargetIter = aTargetList.begin(); + std::vector::iterator aUsedIter = isUsed.begin(); + for (; aUsedIter != isUsed.end(); aUsedIter++) { + if (!(*aUsedIter)) { + aRefListOfShapes->remove(*anInitIter); + for (int i = 0; i < aCurrentNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++) { + aRefListOfTranslated->remove(*aTargetIter); + // remove the corresponding feature from the sketch + ResultConstructionPtr aRC = + std::dynamic_pointer_cast(*aTargetIter); + DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr(); + FeaturePtr aFeature = aDoc ? aDoc->feature(aRC) : FeaturePtr(); + if (aFeature) + aDoc->removeFeature(aFeature); + } + } else { + for (int i = 0; i <= aNbCopies && aTargetIter != aTargetList.end(); i++) + aTargetIter++; + } + if (anInitIter != anInitialList.end()) + anInitIter++; + } + // change number of copies + if (aCurrentNbCopies != 0 && aNbCopies != aCurrentNbCopies) { + bool isAdd = aNbCopies > aCurrentNbCopies; + int aMinCopies = isAdd ? aCurrentNbCopies : aNbCopies; + int aMaxCopies = isAdd ? aNbCopies : aCurrentNbCopies; + int ind = 0; + + aTargetList = aRefListOfTranslated->list(); + aTargetIter = aTargetList.begin(); + ObjectPtr anObjToCopy = *aTargetIter; + while (aTargetIter != aTargetList.end()) { + aRefListOfTranslated->remove(*aTargetIter); + aTargetIter++; + ind++; + if (ind > aMinCopies && ind <=aMaxCopies) { + while (ind <= aMaxCopies) { + if (isAdd) { + // Add new shifted item + ObjectPtr anObject = copyFeature(anObjToCopy); + aTargetList.insert(aTargetIter, anObject); + } else { + // remove object + std::list::iterator aRemoveIt = aTargetIter; + ObjectPtr anObject = *(--aRemoveIt); + aTargetList.erase(aRemoveIt); + // remove the corresponding feature from the sketch + ResultConstructionPtr aRC = + std::dynamic_pointer_cast(anObject); + DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr(); + FeaturePtr aFeature = aDoc ? aDoc->feature(aRC) : FeaturePtr(); + if (aFeature) + aDoc->removeFeature(aFeature); + } + ind++; + } + ind = 0; + if (aTargetIter != aTargetList.end()) + anObjToCopy = *aTargetIter; + } + } + + for (aTargetIter = aTargetList.begin(); aTargetIter != aTargetList.end(); aTargetIter++) + aRefListOfTranslated->append(*aTargetIter); + } + // add new items + std::list::iterator anAddIter = anAddition.begin(); + for (; anAddIter != anAddition.end(); anAddIter++) { + aRefListOfShapes->append(*anAddIter); + aRefListOfTranslated->append(*anAddIter); + for (int i = 0; i < aNbCopies; i++) { + ObjectPtr anObject = copyFeature(*anAddIter); + aRefListOfTranslated->append(anObject); + } + } + + // Recalculate positions of features + aTargetList = aRefListOfTranslated->list(); + aTargetIter = aTargetList.begin(); + while (aTargetIter != aTargetList.end()) { + ObjectPtr anInitialObject = *aTargetIter++; + for (int i = 0; i < aNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++) + shiftFeature(anInitialObject, *aTargetIter, + aShiftVec->x() * (i + 1), aShiftVec->y() * (i + 1)); + } + + // send events to update the sub-features by the solver + if (isUpdateFlushed) + Events_Loop::loop()->setFlushed(anUpdateEvent, true); +} + +AISObjectPtr SketchPlugin_MultiTranslation::getAISObject(AISObjectPtr thePrevious) +{ + if (!sketch()) + return thePrevious; + + AISObjectPtr anAIS = thePrevious; + if (!anAIS) { +// TODO: +// anAIS = SketcherPrs_Factory::mirrorConstraint(this, sketch()->coordinatePlane()); + } + return anAIS; +} + +ObjectPtr SketchPlugin_MultiTranslation::copyFeature(ObjectPtr theObject) +{ + ResultPtr aResult = std::dynamic_pointer_cast(theObject); + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + if (!aFeature || !aResult) + return ObjectPtr(); + + FeaturePtr aNewFeature = sketch()->addFeature(aFeature->getKind()); + aFeature->data()->copyTo(aNewFeature->data()); + aNewFeature->execute(); + + static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); + ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent); + + std::shared_ptr aShapeIn = aResult->shape(); + const std::list& aResults = aNewFeature->results(); + std::list::const_iterator anIt = aResults.begin(); + for (; anIt != aResults.end(); anIt++) { + ResultConstructionPtr aRC = std::dynamic_pointer_cast(*anIt); + if (!aRC) continue; + std::shared_ptr aShapeOut = aRC->shape(); + if ((aShapeIn->isVertex() && aShapeOut->isVertex()) || + (aShapeIn->isEdge() && aShapeOut->isEdge()) || + (aShapeIn->isFace() && aShapeOut->isFace())) + return aRC; + } + return ObjectPtr(); +} + +void SketchPlugin_MultiTranslation::shiftFeature( + ObjectPtr theInitial, ObjectPtr theTarget, double theDeltaX, double theDeltaY) +{ + FeaturePtr anInitialFeature = ModelAPI_Feature::feature(theInitial); + FeaturePtr aTargetFeature = ModelAPI_Feature::feature(theTarget); + + // block feature update + aTargetFeature->data()->blockSendAttributeUpdated(true); + + std::list anInitAttrList = + anInitialFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::list aTargetAttrList = + aTargetFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::list::iterator anInitIt = anInitAttrList.begin(); + std::list::iterator aTargetIt = aTargetAttrList.begin(); + for (; anInitIt != anInitAttrList.end(); anInitIt++, aTargetIt++) { + std::shared_ptr aPointFrom = + std::dynamic_pointer_cast(*anInitIt); + std::shared_ptr aPointTo = + std::dynamic_pointer_cast(*aTargetIt); + aPointTo->setValue(aPointFrom->x() + theDeltaX, aPointFrom->y() + theDeltaY); + } + + // unblock feature update + aTargetFeature->data()->blockSendAttributeUpdated(false); +} diff --git a/src/SketchPlugin/SketchPlugin_MultiTranslation.h b/src/SketchPlugin/SketchPlugin_MultiTranslation.h new file mode 100644 index 000000000..18e3c4afc --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_MultiTranslation.h @@ -0,0 +1,86 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_MultiTranslation.h +// Created: 21 Apr 2015 +// Author: Artem ZHIDKOV + +#ifndef SketchPlugin_MultiTranslation_H_ +#define SketchPlugin_MultiTranslation_H_ + +#include "SketchPlugin.h" +#include +#include "SketchPlugin_ConstraintBase.h" + +/** \class SketchPlugin_MultiTranslation + * \ingroup Plugins + * \brief Feature for creation of a number of shifted copies of a list of objects + * + * This constraint has two attributes: + * SketchPlugin_Constraint::ENTITY_A() for initial list of objects and + * SketchPlugin_Constraint::ENTITY_B() for the list of created objects + * + * The list of created objects contains a number of copies of each object given in + * the NUMBER_OF_COPIES_ID() attribute plus 1 (the initial objects are stored into this + * attribute too). At the start of the list, there are collected N copies + * of first object from initial list, then N copies of second object etc. + */ +class SketchPlugin_MultiTranslation : public SketchPlugin_ConstraintBase +{ + public: + /// Multi-translation kind + inline static const std::string& ID() + { + static const std::string MY_CONSTRAINT_TRANSLATION_ID("SketchMultiTranslation"); + return MY_CONSTRAINT_TRANSLATION_ID; + } + /// \brief Returns the kind of a feature + SKETCHPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = SketchPlugin_MultiTranslation::ID(); + return MY_KIND; + } + + /// List of objects to be mirrored + inline static const std::string& TRANSLATION_LIST_ID() + { + static const std::string MY_TRANSLATION_LIST_ID("MultiTranslationList"); + return MY_TRANSLATION_LIST_ID; + } + + /// Start point of translation + inline static const std::string& START_POINT_ID() + { + static const std::string MY_START_POINT_ID("MultiTranslationStartPoint"); + return MY_START_POINT_ID; + } + /// End point of translation + inline static const std::string& END_POINT_ID() + { + static const std::string MY_END_POINT_ID("MultiTranslationEndPoint"); + return MY_END_POINT_ID; + } + /// Number of translated objects + inline static const std::string& NUMBER_OF_COPIES_ID() + { + static const std::string MY_NUMBER_OF_COPIES_ID("MultiTranslationCopies"); + return MY_NUMBER_OF_COPIES_ID; + } + + /// \brief Creates a new part document if needed + SKETCHPLUGIN_EXPORT virtual void execute(); + + /// \brief Request for initialization of data model of the feature: adding all attributes + SKETCHPLUGIN_EXPORT virtual void initAttributes(); + + /// Returns the AIS preview + SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious); + + /// \brief Use plugin manager for features creation + SketchPlugin_MultiTranslation(); + +private: + ObjectPtr copyFeature(ObjectPtr theObject); + void shiftFeature(ObjectPtr theInitial, ObjectPtr theTarget, double theDeltaX, double theDeltaY); +}; + +#endif diff --git a/src/SketchPlugin/SketchPlugin_Plugin.cpp b/src/SketchPlugin/SketchPlugin_Plugin.cpp index ff8824f81..904fe1e22 100644 --- a/src/SketchPlugin/SketchPlugin_Plugin.cpp +++ b/src/SketchPlugin/SketchPlugin_Plugin.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -63,6 +65,8 @@ SketchPlugin_Plugin::SketchPlugin_Plugin() new SketchPlugin_MirrorAttrValidator); aFactory->registerValidator("SketchPlugin_CoincidenceAttr", new SketchPlugin_CoincidenceAttrValidator); + aFactory->registerValidator("SketchPlugin_CopyValidator", + new SketchPlugin_CopyValidator); // register this plugin ModelAPI_Session::get()->registerPlugin(this); @@ -131,6 +135,10 @@ FeaturePtr SketchPlugin_Plugin::createFeature(string theFeatureID) return FeaturePtr(new SketchPlugin_ConstraintMirror); } else if (theFeatureID == SketchPlugin_ConstraintFillet::ID()) { return FeaturePtr(new SketchPlugin_ConstraintFillet); + } else if (theFeatureID == SketchPlugin_MultiTranslation::ID()) { + return FeaturePtr(new SketchPlugin_MultiTranslation); + } else if (theFeatureID == SketchPlugin_MultiRotation::ID()) { + return FeaturePtr(new SketchPlugin_MultiRotation); } // feature of such kind is not found return FeaturePtr(); diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index 674f9de12..68857aa26 100644 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -280,3 +280,37 @@ bool SketchPlugin_CoincidenceAttrValidator::isValid( return false; } + +bool SketchPlugin_CopyValidator::isValid( + const AttributePtr& theAttribute, const std::list& theArguments ) const +{ + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + AttributeSelectionListPtr aSelAttr = + std::dynamic_pointer_cast(theAttribute); + if (!aSelAttr) + return false; + + AttributeRefListPtr aRefListOfInitial = std::dynamic_pointer_cast( + aFeature->attribute(SketchPlugin_Constraint::ENTITY_A())); + AttributeRefListPtr aRefListOfCopied = std::dynamic_pointer_cast( + aFeature->attribute(SketchPlugin_Constraint::ENTITY_B())); + std::list anInitialObjects = aRefListOfInitial->list(); + std::list aCopiedObjects = aRefListOfCopied->list(); + + std::list::iterator anObjIter; + for(int anInd = 0; anInd < aSelAttr->size(); anInd++) { + std::shared_ptr aSelect = aSelAttr->value(anInd); + anObjIter = anInitialObjects.begin(); + for (; anObjIter != anInitialObjects.end(); anObjIter++) + if (aSelect->context() == *anObjIter) + break; + if (anObjIter != anInitialObjects.end()) + continue; + anObjIter = aCopiedObjects.begin(); + for (; anObjIter != aCopiedObjects.end(); anObjIter++) + if (aSelect->context() == *anObjIter) + return false; + } + return true; +} + diff --git a/src/SketchPlugin/SketchPlugin_Validators.h b/src/SketchPlugin/SketchPlugin_Validators.h index 82e0e1fce..cd7a7d533 100644 --- a/src/SketchPlugin/SketchPlugin_Validators.h +++ b/src/SketchPlugin/SketchPlugin_Validators.h @@ -109,4 +109,22 @@ class SketchPlugin_CoincidenceAttrValidator : public ModelAPI_AttributeValidator const std::list& theArguments) const; }; + +/**\class SketchPlugin_CopyValidator + * \ingroup Validators + * \brief Validator for the constraints which create features. + * + * Applicable only for features, which creates another features. It verifies the produced + * features of current constraint don't become into the list of initial features + */ +class SketchPlugin_CopyValidator : public ModelAPI_AttributeValidator +{ + public: + //! returns true if attribute is valid + //! \param theAttribute the checked attribute + //! \param theArguments arguments of the attribute (not used) + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments) const; +}; + #endif diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 6474268be..13d388d38 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -5,7 +5,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + -- 2.39.2