#include "FeaturesPlugin_Extrusion.h"
#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
#include <ModelAPI_Document.h>
#include <ModelAPI_Data.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_ResultBody.h>
#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_AttributeSelectionList.h>
#include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeReference.h>
+#include <GeomAPI_Pln.h>
+#include <GeomAPI_XYZ.h>
#include <GeomAlgoAPI_Extrusion.h>
+#include <GeomAlgoAPI_FaceBuilder.h>
+#include <GeomAlgoAPI_Prism.h>
using namespace std;
#define _LATERAL_TAG 1
void FeaturesPlugin_Extrusion::initAttributes()
{
- data()->addAttribute(FeaturesPlugin_Extrusion::FACE_ID(), ModelAPI_AttributeSelection::type());
- data()->addAttribute(FeaturesPlugin_Extrusion::SIZE_ID(), ModelAPI_AttributeDouble::type());
- data()->addAttribute(FeaturesPlugin_Extrusion::REVERSE_ID(), ModelAPI_AttributeBoolean::type());
+ AttributeSelectionListPtr aSelection =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
+ FeaturesPlugin_Extrusion::LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
+ // extrusion works with faces always
+ aSelection->setSelectionType("FACE");
+
+ data()->addAttribute(FeaturesPlugin_Extrusion::TO_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(FeaturesPlugin_Extrusion::FROM_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
+
+ //data()->addAttribute(FeaturesPlugin_Extrusion::AXIS_OBJECT_ID(), ModelAPI_AttributeReference::typeId());
+
+ data()->addAttribute(FeaturesPlugin_Extrusion::FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+ data()->addAttribute(FeaturesPlugin_Extrusion::TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FeaturesPlugin_Extrusion::TO_OBJECT_ID());
}
void FeaturesPlugin_Extrusion::execute()
{
- std::shared_ptr<ModelAPI_AttributeSelection> aFaceRef = std::dynamic_pointer_cast<
- ModelAPI_AttributeSelection>(data()->attribute(FeaturesPlugin_Extrusion::FACE_ID()));
- if (!aFaceRef)
- return;
-
- std::shared_ptr<GeomAPI_Shape> aFace =
- std::dynamic_pointer_cast<GeomAPI_Shape>(aFaceRef->value());
- if (!aFace)
- return;
-
- std::shared_ptr<GeomAPI_Shape> aContext;
- ResultPtr aContextRes = aFaceRef->context();
- if (aContextRes) {
- if (aContextRes->groupName() == ModelAPI_ResultBody::group())
- aContext = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContextRes)->shape();
- else if (aContextRes->groupName() == ModelAPI_ResultConstruction::group())
- aContext = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContextRes)->shape();
+ AttributeSelectionListPtr aFaceRefs = selectionList(FeaturesPlugin_Extrusion::LIST_ID());
+
+ std::shared_ptr<GeomAPI_Shape> aFromShape;
+ std::shared_ptr<GeomAPI_Shape> aToShape;
+
+ // Getting bounding planes.
+ std::shared_ptr<ModelAPI_AttributeSelection> anObjRef = selection(FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
+ if (anObjRef) {
+ aFromShape = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
}
- if (!aContext) {
- static const std::string aContextError = "The selection context is bad";
- setError(aContextError);
- return;
+ anObjRef = selection(FeaturesPlugin_Extrusion::TO_OBJECT_ID());
+ if (anObjRef) {
+ aToShape = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
}
- double aSize = data()->real(FeaturesPlugin_Extrusion::SIZE_ID())->value();
- if (data()->boolean(FeaturesPlugin_Extrusion::REVERSE_ID())->value())
- aSize = -aSize;
+ // Getting sizes.
+ double aFromSize = real(FeaturesPlugin_Extrusion::FROM_SIZE_ID())->value();
+ double aToSize = real(FeaturesPlugin_Extrusion::TO_SIZE_ID())->value();
+
+ // for each selected face generate a result
+ int anIndex = 0, aResultIndex = 0;
+ for(; anIndex < aFaceRefs->size(); anIndex++) {
+ std::shared_ptr<ModelAPI_AttributeSelection> aFaceRef = aFaceRefs->value(anIndex);
+ ResultPtr aContextRes = aFaceRef->context();
+ std::shared_ptr<GeomAPI_Shape> aContext = aContextRes->shape();
+ if (!aContext.get()) {
+ static const std::string aContextError = "The selection context is bad";
+ setError(aContextError);
+ break;
+ }
- std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data());
- GeomAlgoAPI_Extrusion aFeature(aFace, aSize);
- if(!aFeature.isDone()) {
- static const std::string aFeatureError = "Extrusion algorithm failed";
- setError(aFeatureError);
- return;
- }
+ std::shared_ptr<GeomAPI_Shape> aValueFace = aFaceRef->value();
+ int aFacesNum = -1; // this mean that "aFace" is used
+ ResultConstructionPtr aConstruction =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContextRes);
+ if (!aValueFace.get()) { // this may be the whole sketch result selected, check and get faces
+ if (aConstruction.get()) {
+ aFacesNum = aConstruction->facesNum();
+ } else {
+ static const std::string aFaceError = "Can not find basis for extrusion";
+ setError(aFaceError);
+ break;
+ }
+ }
- // Check if shape is valid
- if (aFeature.shape()->isNull()) {
- static const std::string aShapeError = "Resulting shape is Null";
- setError(aShapeError);
- return;
+ for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) {
+ ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
+ std::shared_ptr<GeomAPI_Shape> aBaseShape;
+ if (aFacesNum == -1) {
+ aBaseShape = aValueFace;
+ } else {
+ aBaseShape = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
+ }
+
+ // If bounding faces was not set creating them.
+ std::shared_ptr<GeomAPI_Face> aBaseFace(new GeomAPI_Face(aBaseShape));
+ std::shared_ptr<GeomAPI_Pln> aBasePln = aBaseFace->getPlane();
+ std::shared_ptr<GeomAPI_Dir> aBaseDir = aBasePln->direction();
+ std::shared_ptr<GeomAPI_Pnt> aBaseLoc = aBasePln->location();
+ std::shared_ptr<GeomAPI_Shape> aBasePlane = GeomAlgoAPI_FaceBuilder::planarFace(aBaseLoc, aBaseDir);
+
+ std::shared_ptr<GeomAPI_Shape> aBoundingFromShape = aFromShape ? aFromShape : aBasePlane;
+ std::shared_ptr<GeomAPI_Shape> aBoundingToShape = aToShape ? aToShape : aBasePlane;
+
+ // Moving bounding faces according to "from" and "to" sizes.
+ std::shared_ptr<GeomAPI_Face> aFromFace(new GeomAPI_Face(aBoundingFromShape));
+ std::shared_ptr<GeomAPI_Pln> aFromPln = aFromFace->getPlane();
+ std::shared_ptr<GeomAPI_Pnt> aFromLoc = aFromPln->location();
+ std::shared_ptr<GeomAPI_Dir> aFromDir = aFromPln->direction();
+
+ std::shared_ptr<GeomAPI_Face> aToFace(new GeomAPI_Face(aBoundingToShape));
+ std::shared_ptr<GeomAPI_Pln> aToPln = aToFace->getPlane();
+ std::shared_ptr<GeomAPI_Pnt> aToLoc = aToPln->location();
+ std::shared_ptr<GeomAPI_Dir> aToDir = aToPln->direction();
+
+ bool aSign = aFromLoc->xyz()->dot(aBaseDir->xyz()) > aToLoc->xyz()->dot(aBaseDir->xyz());
+
+ std::shared_ptr<GeomAPI_Pnt> aFromPnt(new GeomAPI_Pnt(aFromLoc->xyz()->added(aBaseDir->xyz()->multiplied(aSign ? aFromSize : -aFromSize))));
+ aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
+
+ std::shared_ptr<GeomAPI_Pnt> aToPnt(new GeomAPI_Pnt(aToLoc->xyz()->added(aBaseDir->xyz()->multiplied(aSign ? -aToSize : aToSize))));
+ aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
+
+ //GeomAlgoAPI_Extrusion aFeature(aFace, aFromSize);
+ GeomAlgoAPI_Prism aFeature(aBaseShape, aBoundingFromShape, aBoundingToShape);
+ if(!aFeature.isDone()) {
+ static const std::string aFeatureError = "Extrusion algorithm failed";
+ setError(aFeatureError);
+ break;
+ }
+
+ // Check if shape is valid
+ if(aFeature.shape()->isNull()) {
+ static const std::string aShapeError = "Resulting shape is Null";
+ setError(aShapeError);
+ break;
+ }
+ if(!aFeature.isValid()) {
+ std::string aFeatureError = "Warning: resulting shape is not valid";
+ setError(aFeatureError);
+ break;
+ }
+ //LoadNamingDS
+ LoadNamingDS(aFeature, aResultBody, aBaseShape, aContext);
+
+ setResult(aResultBody, aResultIndex);
+ aResultIndex++;
+
+ if (aFacesNum == -1)
+ break;
+ }
}
- if(!aFeature.isValid()) {
- std::string aFeatureError = "Warning: resulting shape is not valid";
- setError(aFeatureError);
- return;
- }
- //LoadNamingDS
- LoadNamingDS(aFeature, aResultBody, aFace, aContext);
-
- setResult(aResultBody);
+ // remove the rest results if there were produced in the previous pass
+ removeResults(aResultIndex);
}
//============================================================================
-void FeaturesPlugin_Extrusion::LoadNamingDS(GeomAlgoAPI_Extrusion& theFeature,
- std::shared_ptr<ModelAPI_ResultBody> theResultBody,
- std::shared_ptr<GeomAPI_Shape> theBasis,
- std::shared_ptr<GeomAPI_Shape> theContext)
-{
-
-
+void FeaturesPlugin_Extrusion::LoadNamingDS(GeomAlgoAPI_Prism& theFeature,
+ std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+ std::shared_ptr<GeomAPI_Shape> theBasis,
+ std::shared_ptr<GeomAPI_Shape> theContext)
+{
//load result
if(theBasis->isEqual(theContext))
theResultBody->store(theFeature.shape());
else
- theResultBody->storeGenerated(theContext, theFeature.shape());
+ theResultBody->storeGenerated(theBasis, theFeature.shape());
GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape();
theFeature.mapOfShapes(*aSubShapes);
- std::string aPrefix = data()->name() + "/";
- //Insert lateral face : Face from Edge
- theResultBody->loadAndOrientGeneratedShapes(theFeature.makeShape(), theBasis, EDGE,_LATERAL_TAG, aPrefix, *aSubShapes);
+
+ //Insert lateral face : Face from Edge
+ std::string aLatName = "LateralFace";
+ theResultBody->loadAndOrientGeneratedShapes(theFeature.makeShape(), theBasis, EDGE,_LATERAL_TAG, aLatName, *aSubShapes);
//Insert bottom face
- std::shared_ptr<GeomAPI_Shape> aBottomFace = theFeature.firstShape();
- if (!aBottomFace->isNull()) {
- if (aSubShapes->isBound(aBottomFace)) {
- aBottomFace = aSubShapes->find(aBottomFace);
- }
- theResultBody->generated(aBottomFace, aPrefix, _FIRST_TAG);
+ std::string aBotName = "BottomFace";
+ std::shared_ptr<GeomAPI_Shape> aBottomFace = theFeature.firstShape();
+ if(!aBottomFace->isNull()) {
+ if(aSubShapes->isBound(aBottomFace)) {
+ aBottomFace = aSubShapes->find(aBottomFace);
+ }
+ theResultBody->generated(aBottomFace, aBotName, _FIRST_TAG);
}
-
-
//Insert top face
+ std::string aTopName = "TopFace";
std::shared_ptr<GeomAPI_Shape> aTopFace = theFeature.lastShape();
if (!aTopFace->isNull()) {
- if (aSubShapes->isBound(aTopFace)) {
- aTopFace = aSubShapes->find(aTopFace);
+ if (aSubShapes->isBound(aTopFace)) {
+ aTopFace = aSubShapes->find(aTopFace);
}
- theResultBody->generated(aTopFace, aPrefix, _LAST_TAG);
+ theResultBody->generated(aTopFace, aTopName, _LAST_TAG);
}
-
-
}