Merge pull request #12572 from bgbsww/bgbsww-toponamingMakeElementRevolve
Toponaming/Part: make element revolve and prism
This commit is contained in:
@@ -258,6 +258,12 @@ public:
|
||||
|
||||
void operator=(const TopoShape&);
|
||||
|
||||
bool operator == (const TopoShape &other) const {
|
||||
return _Shape.IsEqual(other._Shape);
|
||||
}
|
||||
|
||||
virtual bool isSame (const Data::ComplexGeoData &other) const;
|
||||
|
||||
/** @name Placement control */
|
||||
//@{
|
||||
/// set the transformation of the CasCade Shape
|
||||
@@ -854,6 +860,148 @@ public:
|
||||
offsetMode,join,op);
|
||||
}
|
||||
|
||||
|
||||
/** Make revolved shell around a basis shape
|
||||
*
|
||||
* @param base: the base shape
|
||||
* @param axis: the revolving axis
|
||||
* @param d: rotation angle in degree
|
||||
* @param face_maker: optional type name of the the maker used to make a
|
||||
* face from basis shape
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
*
|
||||
* @return The original content of this TopoShape is discarded and replaced
|
||||
* with the new shape. The function returns the TopoShape itself as
|
||||
* a self reference so that multiple operations can be carried out
|
||||
* for the same shape in the same line of code.
|
||||
*/
|
||||
TopoShape &makeElementRevolve(const TopoShape &base, const gp_Ax1& axis, double d,
|
||||
const char *face_maker=0, const char *op=nullptr);
|
||||
|
||||
/** Make revolved shell around a basis shape
|
||||
*
|
||||
* @param base: the basis shape
|
||||
* @param axis: the revolving axis
|
||||
* @param d: rotation angle in degree
|
||||
* @param face_maker: optional type name of the the maker used to make a
|
||||
* face from basis shape
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
*
|
||||
* @return Return the generated new shape. The TopoShape itself is not modified.
|
||||
*/
|
||||
TopoShape makeElementRevolve(const gp_Ax1& axis, double d,
|
||||
const char *face_maker=nullptr, const char *op=nullptr) const {
|
||||
return TopoShape(0,Hasher).makeElementRevolve(*this,axis,d,face_maker,op);
|
||||
}
|
||||
|
||||
|
||||
/** Make a prism that is a linear sweep of a basis shape
|
||||
*
|
||||
* @param base: the basis shape
|
||||
* @param vec: vector defines the sweep direction
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
*
|
||||
* @return The original content of this TopoShape is discarded and replaced
|
||||
* with the new shape. The function returns the TopoShape itself as
|
||||
* a self reference so that multiple operations can be carried out
|
||||
* for the same shape in the same line of code.
|
||||
*/
|
||||
TopoShape &makeElementPrism(const TopoShape &base, const gp_Vec& vec, const char *op=nullptr);
|
||||
|
||||
/** Make a prism that is a linear sweep of this shape
|
||||
*
|
||||
* @param vec: vector defines the sweep direction
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
*
|
||||
* @return Return the generated new shape. The TopoShape itself is not modified.
|
||||
*/
|
||||
TopoShape makeElementPrism(const gp_Vec& vec, const char *op=nullptr) const {
|
||||
return TopoShape(0,Hasher).makeElementPrism(*this,vec,op);
|
||||
}
|
||||
|
||||
/// Operation mode for makeElementPrismUntil()
|
||||
enum PrismMode {
|
||||
/// Remove the generated prism shape from the base shape with boolean cut
|
||||
CutFromBase = 0,
|
||||
/// Add generated prism shape to the base shape with fusion
|
||||
FuseWithBase = 1,
|
||||
/// Return the generated prism shape without base shape
|
||||
None = 2
|
||||
};
|
||||
/** Make a prism that is either depression or protrusion of a profile shape up to a given face
|
||||
*
|
||||
* @param base: the base shape
|
||||
* @param profile: profile shape used for sweeping to make the prism
|
||||
* @param supportFace: optional face serves to determining the type of
|
||||
* operation. If it is inside the basis shape, a local
|
||||
* operation such as glueing can be performed.
|
||||
* @param upToFace: sweep the profile up until this give face.
|
||||
* @param direction: the direction to sweep the profile
|
||||
* @param mode: defines what shape to return. @sa PrismMode
|
||||
* @param checkLimits: If true, then remove limit (boundary) of up to face.
|
||||
* If false, then the generate prism may go beyond the
|
||||
* boundary of the up to face.
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
*
|
||||
* @return The original content of this TopoShape is discarded and replaced
|
||||
* with the new shape. The function returns the TopoShape itself as
|
||||
* a self reference so that multiple operations can be carried out
|
||||
* for the same shape in the same line of code.
|
||||
*/
|
||||
// TODO: This code was transferred in Feb 2024 as part of the toponaming project, but appears to be
|
||||
// unused. It is potentially useful if debugged.
|
||||
// TopoShape &makeElementPrismUntil(const TopoShape &base,
|
||||
// const TopoShape& profile,
|
||||
// const TopoShape& supportFace,
|
||||
// const TopoShape& upToFace,
|
||||
// const gp_Dir& direction,
|
||||
// PrismMode mode,
|
||||
// Standard_Boolean checkLimits = Standard_True,
|
||||
// const char *op=nullptr);
|
||||
|
||||
/** Make a prism based on this shape that is either depression or protrusion of a profile shape up to a given face
|
||||
*
|
||||
* @param profile: profile shape used for sweeping to make the prism
|
||||
* @param supportFace: optional face serves to determining the type of
|
||||
* operation. If it is inside the basis shape, a local
|
||||
* operation such as glueing can be performed.
|
||||
* @param upToFace: sweep the profile up until this give face.
|
||||
* @param direction: the direction to sweep the profile
|
||||
* @param mode: defines what shape to return. @sa PrismMode
|
||||
* @param checkLimits: If true, then remove limit (boundary) of up to face.
|
||||
* If false, then the generate prism may go beyond the
|
||||
* boundary of the up to face.
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
*
|
||||
* @return Return the generated new shape. The TopoShape itself is not modified.
|
||||
*/
|
||||
// TODO: This code was transferred in Feb 2024 as part of the toponaming project, but appears to be
|
||||
// unused. It is potentially useful if debugged.
|
||||
// TopoShape makeElementPrismUntil(const TopoShape& profile,
|
||||
// const TopoShape& supportFace,
|
||||
// const TopoShape& upToFace,
|
||||
// const gp_Dir& direction,
|
||||
// PrismMode mode,
|
||||
// Standard_Boolean checkLimits = Standard_True,
|
||||
// const char *op=nullptr) const
|
||||
// {
|
||||
// return TopoShape(0,Hasher).makeElementPrismUntil(*this,
|
||||
// profile,
|
||||
// supportFace,
|
||||
// upToFace,
|
||||
// direction,
|
||||
// mode,
|
||||
// checkLimits,
|
||||
// op);
|
||||
// }
|
||||
|
||||
|
||||
/* Make a shell or solid by sweeping profile wire along a spine
|
||||
*
|
||||
* @params sources: source shapes. The first shape is used as spine. The
|
||||
@@ -1928,6 +2076,22 @@ public:
|
||||
return TopoShape(0, Hasher).makeElementShape(mkShape, *this, op);
|
||||
}
|
||||
|
||||
/** Specialized shape making for BRepBuilderAPI_MakePrism with mapped element name
|
||||
*
|
||||
* @param mkShape: OCCT shape maker.
|
||||
* @param sources: list of source shapes.
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
*
|
||||
* @return The original content of this TopoShape is discarded and replaced
|
||||
* with the new shape built by the shape maker. The function
|
||||
* returns the TopoShape itself as a self reference so that
|
||||
* multiple operations can be carried out for the same shape in the
|
||||
* same line of code.
|
||||
*/
|
||||
TopoShape &makeElementShape(BRepFeat_MakePrism &mkShape,
|
||||
const std::vector<TopoShape> &sources, const TopoShape &uptoface, const char *op);
|
||||
|
||||
/* Toponaming migration, February 2014:
|
||||
* Note that the specialized versions of makeElementShape for operations that do not
|
||||
* inherit from BRepBuilderAPI_MakeShape ( like BRepBuilderAPI_Sewing ) have been removed.
|
||||
|
||||
@@ -88,6 +88,10 @@
|
||||
#include "Geometry.h"
|
||||
|
||||
#include <App/ElementNamingUtils.h>
|
||||
#include <BRepPrimAPI_MakeRevol.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepPrimAPI_MakePrism.hxx>
|
||||
#include <BRepProj_Projection.hxx>
|
||||
|
||||
FC_LOG_LEVEL_INIT("TopoShape", true, true) // NOLINT
|
||||
|
||||
@@ -2703,6 +2707,103 @@ struct MapperThruSections: MapperMaker
|
||||
}
|
||||
};
|
||||
|
||||
struct MapperPrism: MapperMaker {
|
||||
std::unordered_map<TopoDS_Shape, TopoDS_Shape, ShapeHasher, ShapeHasher> vertexMap;
|
||||
ShapeMapper::ShapeMap edgeMap;
|
||||
|
||||
MapperPrism(BRepFeat_MakePrism &maker, const TopoShape &upTo)
|
||||
:MapperMaker(maker)
|
||||
{
|
||||
(void)upTo;
|
||||
|
||||
std::vector<TopoShape> shapes;
|
||||
for(TopTools_ListIteratorOfListOfShape it(maker.FirstShape());it.More();it.Next())
|
||||
shapes.push_back(it.Value());
|
||||
|
||||
if (shapes.size()) {
|
||||
// It seems that BRepFeat_MakePrism::newEdges() does not return
|
||||
// edges generated by extruding the profile vertices. The following
|
||||
// code assumes BRepFeat_MakePrism::myFShape is the profile, and
|
||||
// FirstShape() returns the corresponding faces in the new shape,
|
||||
// i.e. the bottom profile, and add all edges that shares a
|
||||
// vertex with the profiles as new edges.
|
||||
|
||||
std::unordered_set<TopoDS_Shape,ShapeHasher,ShapeHasher> edgeSet;
|
||||
TopoShape bottom;
|
||||
bottom.makeElementCompound(shapes, nullptr, TopoShape::SingleShapeCompoundCreationPolicy::returnShape);
|
||||
TopoShape shape(maker.Shape());
|
||||
for (auto &vertex : bottom.getSubShapes(TopAbs_VERTEX)) {
|
||||
for (auto &e : shape.findAncestorsShapes(vertex, TopAbs_EDGE)) {
|
||||
// Make sure to not visit the the same edge twice.
|
||||
// And check only edge that are not found in the bottom profile
|
||||
if (!edgeSet.insert(e).second && !bottom.findShape(e)) {
|
||||
auto otherVertex = TopExp::FirstVertex(TopoDS::Edge(e));
|
||||
if (otherVertex.IsSame(vertex))
|
||||
otherVertex = TopExp::LastVertex(TopoDS::Edge(e));
|
||||
vertexMap[vertex] = otherVertex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now map each edge in the bottom profile to the extrueded top
|
||||
// profile. vertexMap created above gives us each pair of vertexes
|
||||
// of the bottom and top profile. We use it to find the
|
||||
// corresponding edges in the top profile, what an extra criteria
|
||||
// for disambiguation. That is, the pair of edges (bottom and top)
|
||||
// must belong to the same face.
|
||||
for (auto &edge : bottom.getSubShapes(TopAbs_EDGE)) {
|
||||
std::vector<int> indices;
|
||||
auto first = TopExp::FirstVertex(TopoDS::Edge(edge));
|
||||
auto last = TopExp::LastVertex(TopoDS::Edge(edge));
|
||||
auto itFirst = vertexMap.find(first);
|
||||
auto itLast = vertexMap.find(last);
|
||||
if (itFirst == vertexMap.end() || itLast ==vertexMap.end())
|
||||
continue;
|
||||
std::vector<TopoShape> faces;
|
||||
for (int idx : shape.findAncestors(edge, TopAbs_FACE))
|
||||
faces.push_back(shape.getSubTopoShape(TopAbs_FACE, idx));
|
||||
if (faces.empty())
|
||||
continue;
|
||||
for (int idx : shape.findAncestors(itFirst->second, TopAbs_EDGE)) {
|
||||
auto e = shape.getSubTopoShape(TopAbs_EDGE, idx);
|
||||
if (!e.findShape(itLast->second))
|
||||
continue;
|
||||
for (auto &face : faces) {
|
||||
if (!face.findShape(e.getShape()))
|
||||
continue;
|
||||
auto &entry = edgeMap[edge];
|
||||
if (entry.shapeSet.insert(e.getShape()).second)
|
||||
entry.shapes.push_back(e.getShape());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual const std::vector<TopoDS_Shape> &generated(const TopoDS_Shape &s) const override {
|
||||
_res.clear();
|
||||
switch(s.ShapeType()) {
|
||||
case TopAbs_VERTEX: {
|
||||
auto it = vertexMap.find(s);
|
||||
if (it != vertexMap.end()) {
|
||||
_res.push_back(it->second);
|
||||
return _res;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TopAbs_EDGE: {
|
||||
auto it = edgeMap.find(s);
|
||||
if (it != edgeMap.end())
|
||||
return it->second.shapes;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
MapperMaker::generated(s);
|
||||
return _res;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: This method does not appear to ever be called in the codebase, and it is probably
|
||||
// broken, because using TopoShape() with no parameters means the result will not have an
|
||||
// element Map.
|
||||
@@ -2974,6 +3075,18 @@ TopoShape& TopoShape::makeElementShape(BRepBuilderAPI_MakeShape& mkShape,
|
||||
return makeShapeWithElementMap(shape, MapperMaker(mkShape), shapes, op);
|
||||
}
|
||||
|
||||
TopoShape &TopoShape::makeElementShape(BRepFeat_MakePrism &mkShape,
|
||||
const std::vector<TopoShape> &sources,
|
||||
const TopoShape &upTo,
|
||||
const char *op)
|
||||
{
|
||||
if(!op) op = Part::OpCodes::Prism;
|
||||
MapperPrism mapper(mkShape, upTo);
|
||||
makeShapeWithElementMap(mkShape.Shape(),mapper,sources,op);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
TopoShape& TopoShape::makeElementLoft(const std::vector<TopoShape>& shapes,
|
||||
IsSolid isSolid,
|
||||
IsRuled isRuled,
|
||||
@@ -3041,6 +3154,229 @@ TopoShape& TopoShape::makeElementLoft(const std::vector<TopoShape>& shapes,
|
||||
op);
|
||||
}
|
||||
|
||||
TopoShape& TopoShape::makeElementPrism(const TopoShape& base, const gp_Vec& vec, const char* op)
|
||||
{
|
||||
if (!op) {
|
||||
op = Part::OpCodes::Extrude;
|
||||
}
|
||||
if (base.isNull()) {
|
||||
FC_THROWM(NullShapeException, "Null shape");
|
||||
}
|
||||
BRepPrimAPI_MakePrism mkPrism(base.getShape(), vec);
|
||||
return makeElementShape(mkPrism, base, op);
|
||||
}
|
||||
|
||||
// TODO: This code was transferred in Feb 2024 as part of the toponaming project, but appears to be
|
||||
// unused. It is potentially useful if debugged.
|
||||
//TopoShape& TopoShape::makeElementPrismUntil(const TopoShape& _base,
|
||||
// const TopoShape& profile,
|
||||
// const TopoShape& supportFace,
|
||||
// const TopoShape& __uptoface,
|
||||
// const gp_Dir& direction,
|
||||
// PrismMode Mode,
|
||||
// Standard_Boolean checkLimits,
|
||||
// const char* op)
|
||||
//{
|
||||
// if (!op) {
|
||||
// op = Part::OpCodes::Prism;
|
||||
// }
|
||||
//
|
||||
// BRepFeat_MakePrism PrismMaker;
|
||||
//
|
||||
// TopoShape _uptoface(__uptoface);
|
||||
// if (checkLimits && _uptoface.shapeType(true) == TopAbs_FACE
|
||||
// && !BRep_Tool::NaturalRestriction(TopoDS::Face(_uptoface.getShape()))) {
|
||||
// // When using the face with BRepFeat_MakePrism::Perform(const TopoDS_Shape& Until)
|
||||
// // then the algorithm expects that the 'NaturalRestriction' flag is set in order
|
||||
// // to work as expected.
|
||||
// BRep_Builder builder;
|
||||
// _uptoface = _uptoface.makeElementCopy();
|
||||
// builder.NaturalRestriction(TopoDS::Face(_uptoface.getShape()), Standard_True);
|
||||
// }
|
||||
//
|
||||
// TopoShape uptoface(_uptoface);
|
||||
// TopoShape base(_base);
|
||||
//
|
||||
// if (base.isNull()) {
|
||||
// Mode = PrismMode::None;
|
||||
// base = profile;
|
||||
// }
|
||||
//
|
||||
// // Check whether the face has limits or not. Unlimited faces have no wire
|
||||
// // Note: Datum planes are always unlimited
|
||||
// if (checkLimits && uptoface.hasSubShape(TopAbs_WIRE)) {
|
||||
// TopoDS_Face face = TopoDS::Face(uptoface.getShape());
|
||||
// bool remove_limits = false;
|
||||
// // Remove the limits of the upToFace so that the extrusion works even if profile is larger
|
||||
// // than the upToFace
|
||||
// for (auto& sketchface : profile.getSubTopoShapes(TopAbs_FACE)) {
|
||||
// // Get outermost wire of sketch face
|
||||
// TopoShape outerWire = sketchface.splitWires();
|
||||
// BRepProj_Projection proj(TopoDS::Wire(outerWire.getShape()), face, direction);
|
||||
// if (!proj.More() || !proj.Current().Closed()) {
|
||||
// remove_limits = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // It must also be checked that all projected inner wires of the upToFace
|
||||
// // lie outside the sketch shape. If this is not the case then the sketch
|
||||
// // shape is not completely covered by the upToFace. See #0003141
|
||||
// if (!remove_limits) {
|
||||
// std::vector<TopoShape> wires;
|
||||
// uptoface.splitWires(&wires);
|
||||
// for (auto& w : wires) {
|
||||
// BRepProj_Projection proj(TopoDS::Wire(w.getShape()),
|
||||
// profile.getShape(),
|
||||
// -direction);
|
||||
// if (proj.More()) {
|
||||
// remove_limits = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (remove_limits) {
|
||||
// // Note: Using an unlimited face every time gives unnecessary failures for concave faces
|
||||
// TopLoc_Location loc = face.Location();
|
||||
// BRepAdaptor_Surface adapt(face, Standard_False);
|
||||
// // use the placement of the adapter, not of the upToFace
|
||||
// loc = TopLoc_Location(adapt.Trsf());
|
||||
// BRepBuilderAPI_MakeFace mkFace(adapt.Surface().Surface(), Precision::Confusion());
|
||||
// if (!mkFace.IsDone()) {
|
||||
// remove_limits = false;
|
||||
// }
|
||||
// else {
|
||||
// uptoface.setShape(located(mkFace.Shape(), loc), false);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// TopoShape uptofaceCopy = uptoface;
|
||||
// bool checkBase = false;
|
||||
// auto retry = [&]() {
|
||||
// if (!uptoface.isSame(_uptoface)) {
|
||||
// // retry using the original up to face in case unnecessary failure
|
||||
// // due to removing the limits
|
||||
// uptoface = _uptoface;
|
||||
// return true;
|
||||
// }
|
||||
// if ((!_base.isNull() && base.isSame(_base)) || (_base.isNull() && base.isSame(profile))) {
|
||||
// // It is unclear under exactly what condition extrude up to face
|
||||
// // can fail. Either the support face or the up to face must be part
|
||||
// // of the base, or maybe some thing else.
|
||||
// //
|
||||
// // To deal with it, we retry again by disregard the supplied base,
|
||||
// // and use up to face to extrude our own base. Later on, use the
|
||||
// // supplied base (i.e. _base) to calculate the final shape if the
|
||||
// // mode is FuseWithBase or CutWithBase.
|
||||
// checkBase = true;
|
||||
// uptoface = uptofaceCopy;
|
||||
// base.makeElementPrism(_uptoface, direction);
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// };
|
||||
//
|
||||
// std::vector<TopoShape> srcShapes;
|
||||
// TopoShape result;
|
||||
// for (;;) {
|
||||
// try {
|
||||
// result = base;
|
||||
//
|
||||
// // We do not rely on BRepFeat_MakePrism to perform fuse or cut for
|
||||
// // us because of its poor support of shape history.
|
||||
// auto mode = PrismMode::None;
|
||||
//
|
||||
// for (auto& face : profile.getSubTopoShapes(
|
||||
// profile.hasSubShape(TopAbs_FACE) ? TopAbs_FACE : TopAbs_WIRE)) {
|
||||
// srcShapes.clear();
|
||||
// if (!profile.isNull() && !result.findShape(profile.getShape())) {
|
||||
// srcShapes.push_back(profile);
|
||||
// }
|
||||
// if (!supportFace.isNull() && !result.findShape(supportFace.getShape())) {
|
||||
// srcShapes.push_back(supportFace);
|
||||
// }
|
||||
//
|
||||
// // DO NOT include uptoface for element mapping. Because OCCT
|
||||
// // BRepFeat_MakePrism will report all top extruded face being
|
||||
// // modified by the uptoface. If there are more than one face in
|
||||
// // the profile, this will cause uncessary duplicated element
|
||||
// // mapped name. And will also disrupte element history tracing
|
||||
// // back to the profile sketch.
|
||||
// //
|
||||
// // if (!uptoface.isNull() && !this->findShape(uptoface.getShape()))
|
||||
// // srcShapes.push_back(uptoface);
|
||||
//
|
||||
// srcShapes.push_back(result);
|
||||
//
|
||||
// PrismMaker.Init(result.getShape(),
|
||||
// face.getShape(),
|
||||
// TopoDS::Face(supportFace.getShape()),
|
||||
// direction,
|
||||
// mode,
|
||||
// Standard_False);
|
||||
// mode = PrismMode::FuseWithBase;
|
||||
//
|
||||
// PrismMaker.Perform(uptoface.getShape());
|
||||
//
|
||||
// if (!PrismMaker.IsDone() || PrismMaker.Shape().IsNull()) {
|
||||
// FC_THROWM(Base::CADKernelError, "BRepFeat_MakePrism: extrusion failed");
|
||||
// }
|
||||
//
|
||||
// result.makeElementShape(PrismMaker, srcShapes, uptoface, op);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// catch (Base::Exception&) {
|
||||
// if (!retry()) {
|
||||
// throw;
|
||||
// }
|
||||
// }
|
||||
// catch (Standard_Failure&) {
|
||||
// if (!retry()) {
|
||||
// throw;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!_base.isNull() && Mode != PrismMode::None) {
|
||||
// if (Mode == PrismMode::FuseWithBase) {
|
||||
// result.makeElementFuse({_base, result});
|
||||
// }
|
||||
// else {
|
||||
// result.makeElementCut({_base, result});
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// *this = result;
|
||||
// return *this;
|
||||
//}
|
||||
|
||||
TopoShape& TopoShape::makeElementRevolve(const TopoShape& _base,
|
||||
const gp_Ax1& axis,
|
||||
double d,
|
||||
const char* face_maker,
|
||||
const char* op)
|
||||
{
|
||||
if (!op) {
|
||||
op = Part::OpCodes::Revolve;
|
||||
}
|
||||
|
||||
TopoShape base(_base);
|
||||
if (base.isNull()) {
|
||||
FC_THROWM(NullShapeException, "Null shape");
|
||||
}
|
||||
if (face_maker && !base.hasSubShape(TopAbs_FACE)) {
|
||||
if (!base.hasSubShape(TopAbs_WIRE)) {
|
||||
base = base.makeElementWires();
|
||||
}
|
||||
base = base.makeElementFace(nullptr, face_maker, nullptr);
|
||||
}
|
||||
BRepPrimAPI_MakeRevol mkRevol(base.getShape(), axis, d);
|
||||
return makeElementShape(mkRevol, base, op);
|
||||
}
|
||||
|
||||
TopoShape& TopoShape::makeElementDraft(const TopoShape& shape,
|
||||
const std::vector<TopoShape>& _faces,
|
||||
const gp_Dir& pullDirection,
|
||||
@@ -3955,4 +4291,15 @@ TopoShape& TopoShape::makeElementBoolean(const char* maker,
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool TopoShape::isSame(const Data::ComplexGeoData &_other) const
|
||||
{
|
||||
if(!_other.isDerivedFrom(TopoShape::getClassTypeId()))
|
||||
return false;
|
||||
|
||||
const auto &other = static_cast<const TopoShape &>(_other);
|
||||
return Tag == other.Tag
|
||||
&& Hasher == other.Hasher
|
||||
&& _Shape.IsEqual(other._Shape);
|
||||
}
|
||||
|
||||
} // namespace Part
|
||||
|
||||
@@ -2075,4 +2075,133 @@ TEST_F(TopoShapeExpansionTest, makeElementSolid)
|
||||
EXPECT_EQ(elements[IndexedName("Face", 1)], MappedName("Face1;SLD;:H1:4,F"));
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementRevolve)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = CreateTwoCubes();
|
||||
TopoShape topoShape1 {cube1, 1L};
|
||||
gp_Ax1 axis {gp_Pnt {0, 0, 0}, gp_Dir {0, 1, 0}};
|
||||
double angle = 45;
|
||||
auto subTopoFaces = topoShape1.getSubTopoShapes(TopAbs_FACE);
|
||||
subTopoFaces[0].Tag = 2L;
|
||||
// Act
|
||||
TopoShape result = subTopoFaces[0].makeElementRevolve(axis, angle);
|
||||
auto elements = elementMap(result);
|
||||
Base::BoundBox3d bb = result.getBoundBox();
|
||||
// Assert shape is correct
|
||||
EXPECT_TRUE(PartTestHelpers::boxesMatch(
|
||||
bb,
|
||||
Base::BoundBox3d(0.0, 0.0, 0.0, 0.85090352453411933, 1.0, 1.0)));
|
||||
EXPECT_FLOAT_EQ(getVolume(result.getShape()), 0.50885141);
|
||||
// Assert elementMap is correct
|
||||
EXPECT_TRUE(
|
||||
elementsMatch(result,
|
||||
{
|
||||
"Edge1;:G;RVL;:H2:7,F",
|
||||
"Edge1;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E",
|
||||
"Edge1;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E;:L(Edge2;:G;RVL;:H2:7,F;:U;RVL;:H2:"
|
||||
"7,E|Edge3;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E|Edge4;RVL;:H2:4,E);RVL;:H2:62,F",
|
||||
"Edge1;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E;:U;RVL;:H2:7,V",
|
||||
"Edge1;RVL;:H2:4,E",
|
||||
"Edge2;:G;RVL;:H2:7,F",
|
||||
"Edge2;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E",
|
||||
"Edge2;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E;:U;RVL;:H2:7,V",
|
||||
"Edge2;RVL;:H2:4,E",
|
||||
"Edge3;:G;RVL;:H2:7,F",
|
||||
"Edge3;:G;RVL;:H2:7,F;:U;RVL;:H2:7,E",
|
||||
"Edge3;RVL;:H2:4,E",
|
||||
"Edge4;RVL;:H2:4,E",
|
||||
"Face1;RVL;:H2:4,F",
|
||||
"Vertex1;:G;RVL;:H2:7,E",
|
||||
"Vertex1;RVL;:H2:4,V",
|
||||
"Vertex2;RVL;:H2:4,V",
|
||||
"Vertex3;:G;RVL;:H2:7,E",
|
||||
"Vertex3;RVL;:H2:4,V",
|
||||
"Vertex4;RVL;:H2:4,V",
|
||||
}));
|
||||
}
|
||||
|
||||
TEST_F(TopoShapeExpansionTest, makeElementPrism)
|
||||
{
|
||||
// Arrange
|
||||
auto [cube1, cube2] = CreateTwoCubes();
|
||||
TopoShape topoShape1 {cube1, 1L};
|
||||
auto subTopoFaces = topoShape1.getSubTopoShapes(TopAbs_FACE);
|
||||
subTopoFaces[0].Tag = 2L;
|
||||
// Act
|
||||
TopoShape& result = topoShape1.makeElementPrism(subTopoFaces[0], {0.75, 0, 0});
|
||||
auto elements = elementMap(result);
|
||||
Base::BoundBox3d bb = result.getBoundBox();
|
||||
// Assert shape is correct
|
||||
EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0.0, 0.0, 0.0, 0.75, 1.0, 1.0)));
|
||||
EXPECT_FLOAT_EQ(getVolume(result.getShape()), 0.75);
|
||||
// Assert elementMap is correct
|
||||
EXPECT_TRUE(elementsMatch(
|
||||
result,
|
||||
{
|
||||
"Edge1;:G;XTR;:H2:7,F",
|
||||
"Edge1;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E",
|
||||
"Edge1;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E;:L(Edge2;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E|Edge3;:G;"
|
||||
"XTR;:H2:7,F;:U;XTR;:H2:7,E|Edge4;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E);XTR;:H2:74,F",
|
||||
"Edge1;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E;:U2;XTR;:H2:8,V",
|
||||
"Edge1;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E;:U;XTR;:H2:7,V",
|
||||
"Edge1;XTR;:H2:4,E",
|
||||
"Edge2;:G;XTR;:H2:7,F",
|
||||
"Edge2;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E",
|
||||
"Edge2;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E;:U;XTR;:H2:7,V",
|
||||
"Edge2;XTR;:H2:4,E",
|
||||
"Edge3;:G;XTR;:H2:7,F",
|
||||
"Edge3;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E",
|
||||
"Edge3;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E;:U2;XTR;:H2:8,V",
|
||||
"Edge3;XTR;:H2:4,E",
|
||||
"Edge4;:G;XTR;:H2:7,F",
|
||||
"Edge4;:G;XTR;:H2:7,F;:U;XTR;:H2:7,E",
|
||||
"Edge4;XTR;:H2:4,E",
|
||||
"Face1;XTR;:H2:4,F",
|
||||
"Vertex1;:G;XTR;:H2:7,E",
|
||||
"Vertex1;XTR;:H2:4,V",
|
||||
"Vertex2;:G;XTR;:H2:7,E",
|
||||
"Vertex2;XTR;:H2:4,V",
|
||||
"Vertex3;:G;XTR;:H2:7,E",
|
||||
"Vertex3;XTR;:H2:4,V",
|
||||
"Vertex4;:G;XTR;:H2:7,E",
|
||||
"Vertex4;XTR;:H2:4,V",
|
||||
})
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: This code was written in Feb 2024 as part of the toponaming project, but appears to be
|
||||
// unused. It is potentially useful if debugged.
|
||||
//
|
||||
// TEST_F(TopoShapeExpansionTest, makeElementPrismUntil)
|
||||
//{
|
||||
// // Arrange
|
||||
// auto [cube1, cube2] = CreateTwoCubes();
|
||||
// TopoShape cube1TS {cube1, 1L};
|
||||
// auto subFaces = cube1TS.getSubShapes(TopAbs_FACE);
|
||||
// auto subTopoFaces = cube1TS.getSubTopoShapes(TopAbs_FACE);
|
||||
// subTopoFaces[0].Tag = 2L;
|
||||
// subTopoFaces[1].Tag = 3L;
|
||||
// auto tr {gp_Trsf()};
|
||||
// auto direction = gp_Vec(gp_XYZ(0.0, 0.0, 0.25));
|
||||
// tr.SetTranslation(direction);
|
||||
// auto support = subFaces[0].Moved(TopLoc_Location(tr));
|
||||
// auto upto = support.Moved(TopLoc_Location(tr));
|
||||
// // Act
|
||||
// TopoShape result = cube1TS.makeElementPrismUntil(subTopoFaces[0],
|
||||
// TopoShape(support, 4L),
|
||||
// TopoShape(upto, 5L),
|
||||
// direction,
|
||||
// TopoShape::PrismMode::CutFromBase);
|
||||
// auto elements = elementMap(result);
|
||||
// Base::BoundBox3d bb = result.getBoundBox();
|
||||
// // Assert shape is correct
|
||||
// EXPECT_TRUE(PartTestHelpers::boxesMatch(bb, Base::BoundBox3d(0.0, -0.5, 0.0, 1.5, 1.0, 1.0)));
|
||||
// EXPECT_FLOAT_EQ(getVolume(result.getShape()), 2);
|
||||
// // Assert elementMap is correct
|
||||
// EXPECT_TRUE(elementsMatch(result,
|
||||
// {"Edge1;:G;XTR;:H2:7,F",}));
|
||||
//}
|
||||
|
||||
// NOLINTEND(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)
|
||||
|
||||
Reference in New Issue
Block a user