--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: BuildPlugin_Face.cpp
+// Created: 14 April 2016
+// Author: Dmitry Bobylev
+
+#include "BuildPlugin_Face.h"
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultConstruction.h>
+
+#include <Events_Error.h>
+
+#include <GeomAPI_DataMapOfShapeShape.h>
+#include <GeomAPI_PlanarEdges.h>
+#include <GeomAPI_Pln.h>
+#include <GeomAPI_ShapeExplorer.h>
+
+#include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAlgoAPI_SketchBuilder.h>
+#include <GeomAlgoAPI_WireBuilder.h>
+
+#include <algorithm>
+#include <sstream>
+
+//=================================================================================================
+BuildPlugin_Face::BuildPlugin_Face()
+{
+}
+
+//=================================================================================================
+void BuildPlugin_Face::initAttributes()
+{
+ data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
+}
+
+//=================================================================================================
+void BuildPlugin_Face::execute()
+{
+ // Get base objects list.
+ AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
+ if(!aSelectionList.get()) {
+ setError("Error: Could not get selection list.");
+ return;
+ }
+ if(aSelectionList->size() == 0) {
+ setError("Error: Empty selection list.");
+ return;
+ }
+
+ // Collect base shapes.
+ ListOfShape anEdges;
+ for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+ AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
+ GeomShapePtr aShape = aSelection->value();
+ if(!aShape.get()) {
+ aShape = aSelection->context()->shape();
+ }
+ for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+ GeomShapePtr anEdge = anExp.current();
+ anEdges.push_back(anEdge);
+ }
+ }
+
+ // Get plane.
+ std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_ShapeTools::findPlane(anEdges);
+
+ // Get faces.
+ ListOfShape aFaces;
+ GeomAlgoAPI_SketchBuilder::createFaces(aPln->location(), aPln->xDirection(), aPln->direction(), anEdges, aFaces);
+
+ // Get wires from faces.
+ ListOfShape aWires;
+ for(ListOfShape::const_iterator anIt = aFaces.cbegin(); anIt != aFaces.cend(); ++anIt) {
+ for(GeomAPI_ShapeExplorer anExp(*anIt, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
+ aWires.push_back(anExp.current());
+ }
+ }
+
+ // Make faces with holes.
+ aFaces.clear();
+ GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aPln->location(), aPln->direction(), aWires, aFaces);
+
+ // Store result.
+ int anIndex = 0;
+ for(ListOfShape::const_iterator anIt = aFaces.cbegin(); anIt != aFaces.cend(); ++anIt) {
+ ResultBodyPtr aResultBody = document()->createBody(data(), anIndex);
+ GeomShapePtr aShape = *anIt;
+ aResultBody->store(aShape);
+
+ for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+ GeomShapePtr anEdgeInResult = anExp.current();
+ for(ListOfShape::const_iterator anIt = anEdges.cbegin(); anIt != anEdges.cend(); ++anIt) {
+ std::shared_ptr<GeomAPI_Edge> anEdgeInList(new GeomAPI_Edge(*anIt));
+ if(anEdgeInList->isEqual(anEdgeInResult)) {
+ aResultBody->modified(anEdgeInList, anEdgeInResult, "Edge");
+ break;
+ }
+ }
+ }
+
+ setResult(aResultBody, anIndex);
+ ++anIndex;
+ }
+
+ removeResults(anIndex);
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: BuildPlugin_Face.h
+// Created: 14 April 2016
+// Author: Dmitry Bobylev
+
+#ifndef BuildPlugin_Face_H_
+#define BuildPlugin_Face_H_
+
+#include "BuildPlugin.h"
+
+#include <ModelAPI_Feature.h>
+
+/// \class BuildPlugin_Face
+/// \ingroup Plugins
+/// \brief Feature for creation of face from sketch edges or existing wires.
+class BuildPlugin_Face: public ModelAPI_Feature
+{
+public:
+ /// Use plugin manager for features creation
+ BuildPlugin_Face();
+
+ /// Feature kind.
+ inline static const std::string& ID()
+ {
+ static const std::string MY_ID("Face");
+ return MY_ID;
+ }
+
+ /// Attribute name of base objects.
+ inline static const std::string& BASE_OBJECTS_ID()
+ {
+ static const std::string MY_BASE_OBJECTS_ID("base_objects");
+ return MY_BASE_OBJECTS_ID;
+ }
+
+ /// \return the kind of a feature.
+ BUILDPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = BuildPlugin_Face::ID();
+ return MY_KIND;
+ }
+
+ /// Request for initialization of data model of the feature: adding all attributes.
+ BUILDPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Creates a new part document if needed.
+ BUILDPLUGIN_EXPORT virtual void execute();
+};
+
+#endif
#include <BuildPlugin_Vertex.h>
#include <BuildPlugin_Edge.h>
#include <BuildPlugin_Wire.h>
+#include <BuildPlugin_Face.h>
#include <BuildPlugin_Validators.h>
// the only created instance of this plugin
new BuildPlugin_ValidatorBaseForBuild());
aFactory->registerValidator("BuildPlugin_ValidatorBaseForWire",
new BuildPlugin_ValidatorBaseForWire());
+ aFactory->registerValidator("BuildPlugin_ValidatorBaseForFace",
+ new BuildPlugin_ValidatorBaseForFace());
// Register this plugin.
ModelAPI_Session::get()->registerPlugin(this);
return FeaturePtr(new BuildPlugin_Edge());
} else if(theFeatureID == BuildPlugin_Wire::ID()) {
return FeaturePtr(new BuildPlugin_Wire());
+ } else if(theFeatureID == BuildPlugin_Face::ID()) {
+ return FeaturePtr(new BuildPlugin_Face());
}
// Feature of such kind is not found.
#include <ModelAPI_ResultConstruction.h>
#include <GeomAPI_PlanarEdges.h>
+#include <GeomAPI_Pln.h>
+#include <GeomAPI_ShapeExplorer.h>
#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_PaveFiller.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAlgoAPI_SketchBuilder.h>
#include <GeomAlgoAPI_WireBuilder.h>
#include <GeomValidators_ShapeType.h>
{
// Get attribute.
if(theArguments.size() != 1) {
- Events_Error::send("Error: BuildPlugin_ValidatorBaseForWire should be used only with 1 parameter (ID of base objects list)");
+ Events_Error::send("Error: BuildPlugin_ValidatorBaseForWire should be used only with 1 parameter (ID of base objects list).");
return false;
}
- AttributePtr anAttribute = theFeature->attribute(theArguments.front());
-
- // Check base objects list.
- BuildPlugin_ValidatorBaseForBuild aValidatorBaseForBuild;
- std::list<std::string> anArguments;
- anArguments.push_back("edge");
- anArguments.push_back("wire");
- if(!aValidatorBaseForBuild.isValid(anAttribute, anArguments, theError)) {
+ AttributeSelectionListPtr aSelectionList = theFeature->selectionList(theArguments.front());
+ if(!aSelectionList.get()) {
+ theError = "Empty attribute \"" + theArguments.front() + "\".";
return false;
}
+
// Collect base shapes.
- AttributeSelectionListPtr aSelectionList =
- std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(anAttribute);
ListOfShape aListOfShapes;
for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
}
//=================================================================================================
-bool BuildPlugin_ValidatorBaseForWireisNotObligatory(std::string theFeature, std::string theAttribute)
+bool BuildPlugin_ValidatorBaseForWire::isNotObligatory(std::string theFeature, std::string theAttribute)
{
return false;
}
//=================================================================================================
-bool BuildPlugin_ValidatorBaseForFace::isValid(const AttributePtr& theAttribute,
+bool BuildPlugin_ValidatorBaseForFace::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
const std::list<std::string>& theArguments,
std::string& theError) const
{
- // Get base objects list.
- BuildPlugin_ValidatorBaseForBuild aValidatorBaseForBuild;
- std::list<std::string> anArguments;
- anArguments.push_back("edge");
- anArguments.push_back("wire");
- if(!aValidatorBaseForBuild.isValid(theAttribute, anArguments, theError)) {
+ // Get attribute.
+ if(theArguments.size() != 1) {
+ Events_Error::send("Error: BuildPlugin_ValidatorBaseForFace should be used only with 1 parameter (ID of base objects list).");
+ return false;
+ }
+ AttributeSelectionListPtr aSelectionList = theFeature->selectionList(theArguments.front());
+ if(!aSelectionList.get()) {
+ theError = "Empty attribute \"" + theArguments.front() + "\".";
return false;
}
// Collect base shapes.
- AttributeSelectionListPtr aSelectionList =
- std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
- ListOfShape aListOfShapes;
+ ListOfShape anEdges;
for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
GeomShapePtr aShape = aSelection->value();
if(!aShape.get()) {
aShape = aSelection->context()->shape();
}
- aListOfShapes.push_back(aShape);
+ for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+ GeomShapePtr anEdge = anExp.current();
+ anEdges.push_back(anEdge);
+ }
+ }
+
+ // Check that edges does not have intersections.
+ if(anEdges.size() > 1) {
+ GeomAlgoAPI_PaveFiller aPaveFiller(anEdges, false);
+ if(!aPaveFiller.isDone()) {
+ theError = "Error while checking if edges intersects.";
+ return false;
+ }
+ GeomShapePtr aSectedEdges = aPaveFiller.shape();
+
+ int anEdgesNum = 0;
+ for(GeomAPI_ShapeExplorer anExp(aSectedEdges, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+ anEdgesNum++;
+ }
+ if(anEdgesNum != anEdges.size()) {
+ theError = "Selected objects have intersections.";
+ return false;
+ }
}
// Check that they are planar.
- GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aListOfShapes);
+ std::shared_ptr<GeomAPI_Pln> aPln = GeomAlgoAPI_ShapeTools::findPlane(anEdges);
+ if(!aPln.get()) {
+ theError = "Selected objects are not planar.";
+ return false;
+ }
- return aCompound->isPlanar();
+ // Check that selected objects have closed contours.
+ ListOfShape aFaces;
+ GeomAlgoAPI_SketchBuilder::createFaces(aPln->location(), aPln->xDirection(), aPln->direction(), anEdges, aFaces);
+ if(aFaces.empty()) {
+ theError = "Selected objects does not have closed contours.";
+ return false;
+ }
+
+ return true;
+}
+
+//=================================================================================================
+bool BuildPlugin_ValidatorBaseForFace::isNotObligatory(std::string theFeature, std::string theAttribute)
+{
+ return false;
}
/// \class BuildPlugin_ValidatorBaseForFace
/// \ingroup Validators
/// \brief A validator for selection base shapes for face. Allows to select sketch edges, edges and
-/// wires objects that lie in the same plane.
-class BuildPlugin_ValidatorBaseForFace: public ModelAPI_AttributeValidator
+/// wires objects that lie in the same plane and don't have intersections.
+class BuildPlugin_ValidatorBaseForFace: public ModelAPI_FeatureValidator
{
public:
- //! Returns true if attribute is ok.
- //! \param[in] theAttribute the checked attribute.
- //! \param[in] theArguments arguments of the attribute.
- //! \param[out] theError error message.
- virtual bool isValid(const AttributePtr& theAttribute,
- const std::list<std::string>& theArguments,
- std::string& theError) const;
+ //! Returns true if attributes is ok.
+ //! \param theFeature the checked feature.
+ //! \param theArguments arguments of the feature.
+ //! \param theError error message.
+ virtual bool isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<std::string>& theArguments,
+ std::string& theError) const;
+
+ /// \return true if the attribute in feature is not obligatory for the feature execution
+ virtual bool isNotObligatory(std::string theFeature, std::string theAttribute);
};
#endif
// Create wire.
GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(aListOfShapes);
if(!aWire.get()) {
- setError("Error: Result wire empty. Probably it has disconnected edges or non-manifold.");
+ setError("Error: Result wire is empty. Probably it has disconnected edges or non-manifold.");
return;
}
BuildPlugin_Vertex.h
BuildPlugin_Edge.h
BuildPlugin_Wire.h
+ BuildPlugin_Face.h
BuildPlugin_Validators.h
)
BuildPlugin_Vertex.cpp
BuildPlugin_Edge.cpp
BuildPlugin_Wire.cpp
+ BuildPlugin_Face.cpp
BuildPlugin_Validators.cpp
)
vertex_widget.xml
edge_widget.xml
wire_widget.xml
+ face_widget.xml
)
SET(PROJECT_LIBRARIES
--- /dev/null
+<!-- Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+<source>
+ <multi_selector id="base_objects"
+ label="Segments and wires:"
+ tooltip="Select an edges on sketch or wires objects."
+ type_choice="edges objects">
+ <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge,wire"/>
+ </multi_selector>
+ <validator id="BuildPlugin_ValidatorBaseForFace" parameters="base_objects"/>
+</source>
<feature id="Wire" title="Wire" tooltip ="Create a wire from sketch edges and wires objects" icon="icons/Build/feature_wire.png">
<source path="wire_widget.xml"/>
</feature>
+ <feature id="Face" title="Face" tooltip ="Create a face from sketch edges and wires objects" icon="icons/Build/feature_face.png">
+ <source path="face_widget.xml"/>
+ </feature>
</group>
</workbench>
</plugin>
return std::shared_ptr<GeomAPI_Dir>(new GeomAPI_Dir(aDir.X(), aDir.Y(), aDir.Z()));
}
+std::shared_ptr<GeomAPI_Dir> GeomAPI_Pln::xDirection() const
+{
+ const gp_Dir& aDir = impl<gp_Pln>().XAxis().Direction();
+ return std::shared_ptr<GeomAPI_Dir>(new GeomAPI_Dir(aDir.X(), aDir.Y(), aDir.Z()));
+}
+
void GeomAPI_Pln::coefficients(double& theA, double& theB, double& theC, double& theD)
{
impl<gp_Pln>().Coefficients(theA, theB, theC, theD);
GEOMAPI_EXPORT
std::shared_ptr<GeomAPI_Dir> direction() const;
+ /// Returns a plane x direction
+ GEOMAPI_EXPORT
+ std::shared_ptr<GeomAPI_Dir> xDirection() const;
+
/// Returns the plane coefficients (Ax+By+Cz+D=0)
GEOMAPI_EXPORT
void coefficients(double& theA, double& theB, double& theC, double& theD);
#include <BRepBuilderAPI_FindPlane.hxx>
#include <BRepTools.hxx>
#include <Bnd_Box.hxx>
+#include <Geom_Circle.hxx>
+#include <Geom_Conic.hxx>
+#include <Geom_Curve.hxx>
+#include <Geom_Ellipse.hxx>
+#include <Geom_Hyperbola.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_Parabola.hxx>
#include <Geom_Plane.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
+#include <Geom_TrimmedCurve.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopoDS_Shape.hxx>
bool GeomAPI_Shape::isPlanar() const
{
- const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
+ TopoDS_Shape aShape = impl<TopoDS_Shape>();
if(aShape.IsNull()) {
return false;
}
TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
+ if(aShapeType == TopAbs_COMPOUND) {
+ TopoDS_Iterator anIt(aShape);
+ int aShNum = 0;
+ for(; anIt.More(); anIt.Next()) {
+ ++aShNum;
+ }
+ if(aShNum == 1) {
+ anIt.Initialize(aShape);
+ aShape = anIt.Value();
+ }
+ }
+ aShapeType = aShape.ShapeType();
if(aShapeType == TopAbs_VERTEX) {
return true;
- } else if(aShapeType == TopAbs_EDGE || aShapeType == TopAbs_WIRE || aShapeType == TopAbs_SHELL) {
- BRepBuilderAPI_FindPlane aFindPlane(aShape);
- return aFindPlane.Found() == Standard_True;
} else if(aShapeType == TopAbs_FACE) {
const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
Handle(Standard_Type) aType = aSurface->DynamicType();
}
return (aType == STANDARD_TYPE(Geom_Plane)) == Standard_True;
} else {
- return false;
+ BRepBuilderAPI_FindPlane aFindPlane(aShape);
+ bool isFound = aFindPlane.Found() == Standard_True;
+
+ if(!isFound && aShapeType == TopAbs_EDGE) {
+ Standard_Real aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(aShape), aFirst, aLast);
+ Handle(Standard_Type) aType = aCurve->DynamicType();
+
+ if(aType == STANDARD_TYPE(Geom_TrimmedCurve)) {
+ Handle(Geom_TrimmedCurve) aTrimCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve);
+ aType = aTrimCurve->BasisCurve()->DynamicType();
+ }
+
+ if(aType == STANDARD_TYPE(Geom_Line)
+ || aType == STANDARD_TYPE(Geom_Conic)
+ || aType == STANDARD_TYPE(Geom_Circle)
+ || aType == STANDARD_TYPE(Geom_Ellipse)
+ || aType == STANDARD_TYPE(Geom_Hyperbola)
+ || aType == STANDARD_TYPE(Geom_Parabola)) {
+ isFound = true;
+ }
+ }
+
+ return isFound;
}
+
+ return false;
}
GeomAPI_Shape::ShapeType GeomAPI_Shape::shapeType() const
#include <GeomAPI_Dir.h>
#include <GeomAPI_PlanarEdges.h>
+#include <GeomAPI_Pln.h>
#include <GeomAPI_Pnt.h>
#include <Bnd_Box.hxx>
#include <BRep_Builder.hxx>
#include <BRepAlgo_FaceRestrictor.hxx>
#include <BRepBndLib.hxx>
+#include <BRepBuilderAPI_FindPlane.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepGProp.hxx>
#include <BRep_Tool.hxx>
#include <TopoDS.hxx>
#include <TopExp_Explorer.hxx>
-
-void mapWireFaces(const TopoDS_Shape& theShape,
- BOPCol_IndexedDataMapOfShapeListOfShape& theMapWireFaces);
-
//=================================================================================================
double GeomAlgoAPI_ShapeTools::volume(const std::shared_ptr<GeomAPI_Shape> theShape)
{
theFaces.push_back(aShape);
}
}
+
+//=================================================================================================
+std::shared_ptr<GeomAPI_Pln> GeomAlgoAPI_ShapeTools::findPlane(const ListOfShape& theShapes)
+{
+ TopoDS_Compound aCompound;
+ BRep_Builder aBuilder;
+ aBuilder.MakeCompound(aCompound);
+
+ for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
+ aBuilder.Add(aCompound, (*anIt)->impl<TopoDS_Shape>());
+ }
+ BRepBuilderAPI_FindPlane aFindPlane(aCompound);
+
+ if(aFindPlane.Found() != Standard_True) {
+ return std::shared_ptr<GeomAPI_Pln>();
+ }
+
+ Handle(Geom_Plane) aPlane = aFindPlane.Plane();
+ gp_Pnt aLoc = aPlane->Location();
+ gp_Dir aDir = aPlane->Axis().Direction();
+
+ std::shared_ptr<GeomAPI_Pnt> aGeomPnt(new GeomAPI_Pnt(aLoc.X(), aLoc.Y(), aLoc.Z()));
+ std::shared_ptr<GeomAPI_Dir> aGeomDir(new GeomAPI_Dir(aDir.X(), aDir.Y(), aDir.Z()));
+
+ std::shared_ptr<GeomAPI_Pln> aPln(new GeomAPI_Pln(aGeomPnt, aGeomDir));
+
+ return aPln;
+}
class GeomAPI_Dir;
class GeomAPI_PlanarEdges;
+class GeomAPI_Pln;
class GeomAPI_Pnt;
/// \class GeomAlgoAPI_ShapeTools
std::shared_ptr<GeomAPI_Vertex>& theV1,
std::shared_ptr<GeomAPI_Vertex>& theV2);
- /// \Creates faces with holes from wires.
+ /// \brief Creates faces with holes from wires.
/// \param[in] theWires base wires.
/// \param[out] theFaces resulting faces.
static void makeFacesWithHoles(const std::shared_ptr<GeomAPI_Pnt> theOrigin,
const std::shared_ptr<GeomAPI_Dir> theDirection,
const ListOfShape& theWires,
ListOfShape& theFaces);
+
+ /// \brief Return a plane for list of shapes if they are all planar.
+ /// \param[in] theShapes shapes to find plane.
+ /// \return plane where all shapes lie or empty ptr if they not planar.
+ static std::shared_ptr<GeomAPI_Pln> findPlane(const ListOfShape& theShapes);
};
#endif