Transfer in makeElementRefine
This commit is contained in:
@@ -387,6 +387,7 @@ public:
|
||||
TopoDS_Shape removeShape(const std::vector<TopoDS_Shape>& s) const;
|
||||
void sewShape(double tolerance = 1.0e-06);
|
||||
bool fix(double, double, double);
|
||||
bool fixSolidOrientation();
|
||||
bool removeInternalWires(double);
|
||||
TopoDS_Shape removeSplitter() const;
|
||||
TopoDS_Shape defeaturing(const std::vector<TopoDS_Shape>& s) const;
|
||||
@@ -582,6 +583,36 @@ public:
|
||||
{
|
||||
return TopoShape().makeGTransform(*this, mat, op, copy);
|
||||
}
|
||||
|
||||
/** Refine the input shape by merging faces/edges that share the same geometry
|
||||
*
|
||||
* @param source: input shape
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
* @param no_fail: if true, throw exception if failed to refine. Or else,
|
||||
* the shape remains untouched if failed.
|
||||
*
|
||||
* @return The original content of this TopoShape is discarded and replaced
|
||||
* with the refined 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 &makeElementRefine(const TopoShape &source, const char *op=nullptr, bool no_fail=true);
|
||||
|
||||
/** Refine the input shape by merging faces/edges that share the same geometry
|
||||
*
|
||||
* @param source: input shape
|
||||
* @param op: optional string to be encoded into topo naming for indicating
|
||||
* the operation
|
||||
* @param no_fail: if true, throw exception if failed to refine. Or else,
|
||||
* the shape remains untouched if failed.
|
||||
*
|
||||
* @return Return a refined shape. The shape itself is not modified
|
||||
*/
|
||||
TopoShape makeElementRefine(const char *op=nullptr, bool no_fail=true) const {
|
||||
return TopoShape(Tag,Hasher).makeElementRefine(*this,op,no_fail);
|
||||
}
|
||||
|
||||
|
||||
TopoShape& makeRefine(const TopoShape& shape, const char* op = nullptr, bool no_fail = true);
|
||||
TopoShape makeRefine(const char* op = nullptr, bool no_fail = true) const
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#ifndef _PreComp_
|
||||
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <modelRefine.h>
|
||||
#include <BRepCheck_Analyzer.hxx>
|
||||
#include <BRepFill_Generator.hxx>
|
||||
#include <BRepTools.hxx>
|
||||
@@ -42,10 +43,12 @@
|
||||
|
||||
#include "TopoShape.h"
|
||||
#include "TopoShapeCache.h"
|
||||
#include "TopoShapeMapper.h"
|
||||
#include "FaceMaker.h"
|
||||
|
||||
#include "TopoShapeOpCode.h"
|
||||
#include <App/ElementNamingUtils.h>
|
||||
#include <BRepLib.hxx>
|
||||
|
||||
FC_LOG_LEVEL_INIT("TopoShape", true, true) // NOLINT
|
||||
|
||||
@@ -1511,6 +1514,49 @@ TopoShape& TopoShape::makeElementFace(const std::vector<TopoShape>& shapes,
|
||||
return *this;
|
||||
}
|
||||
|
||||
class MyRefineMaker : public BRepBuilderAPI_RefineModel
|
||||
{
|
||||
public:
|
||||
MyRefineMaker(const TopoDS_Shape &s)
|
||||
:BRepBuilderAPI_RefineModel(s)
|
||||
{}
|
||||
|
||||
void populate(ShapeMapper &mapper)
|
||||
{
|
||||
for (TopTools_DataMapIteratorOfDataMapOfShapeListOfShape it(this->myModified); it.More(); it.Next())
|
||||
{
|
||||
if (it.Key().IsNull()) continue;
|
||||
mapper.populate(MappingStatus::Generated, it.Key(), it.Value());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TopoShape &TopoShape::makeElementRefine(const TopoShape &shape, const char *op, bool no_fail) {
|
||||
if(shape.isNull()) {
|
||||
if(!no_fail)
|
||||
FC_THROWM(NullShapeException, "Null shape");
|
||||
_Shape.Nullify();
|
||||
return *this;
|
||||
}
|
||||
if(!op) op = Part::OpCodes::Refine;
|
||||
bool closed = shape.isClosed();
|
||||
try {
|
||||
MyRefineMaker mkRefine(shape.getShape());
|
||||
GenericShapeMapper mapper;
|
||||
mkRefine.populate(mapper);
|
||||
mapper.init(shape, mkRefine.Shape());
|
||||
makeShapeWithElementMap(mkRefine.Shape(), mapper, {shape}, op);
|
||||
// For some reason, refine operation may reverse the solid
|
||||
fixSolidOrientation();
|
||||
if (isClosed() == closed)
|
||||
return *this;
|
||||
}catch (Standard_Failure &) {
|
||||
if(!no_fail) throw;
|
||||
}
|
||||
*this = shape;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode and set an element name in the elementMap. If a hasher is defined, apply it to the name.
|
||||
*
|
||||
@@ -1851,4 +1897,54 @@ TopoShape& TopoShape::makeElementShellFromWires(const std::vector<TopoShape>& wi
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool TopoShape::fixSolidOrientation()
|
||||
{
|
||||
if (isNull())
|
||||
return false;
|
||||
|
||||
if (shapeType() == TopAbs_SOLID) {
|
||||
TopoDS_Solid solid = TopoDS::Solid(_Shape);
|
||||
BRepLib::OrientClosedSolid(solid);
|
||||
if (solid.IsEqual(_Shape))
|
||||
return false;
|
||||
setShape(solid, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (shapeType() == TopAbs_COMPOUND
|
||||
|| shapeType() == TopAbs_COMPSOLID)
|
||||
{
|
||||
auto shapes = getSubTopoShapes();
|
||||
bool touched = false;
|
||||
for (auto &s : shapes) {
|
||||
if (s.fixSolidOrientation())
|
||||
touched = true;
|
||||
}
|
||||
if (!touched)
|
||||
return false;
|
||||
|
||||
BRep_Builder builder;
|
||||
if (shapeType() == TopAbs_COMPOUND) {
|
||||
TopoDS_Compound comp;
|
||||
builder.MakeCompound(comp);
|
||||
for(auto &s : shapes) {
|
||||
if (!s.isNull())
|
||||
builder.Add(comp, s.getShape());
|
||||
}
|
||||
setShape(comp, false);
|
||||
} else {
|
||||
TopoDS_CompSolid comp;
|
||||
builder.MakeCompSolid(comp);
|
||||
for(auto &s : shapes) {
|
||||
if (!s.isNull())
|
||||
builder.Add(comp, s.getShape());
|
||||
}
|
||||
setShape(comp, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Part
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#include <TopoDS.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include "TopoShapeMapper.h"
|
||||
#include "Geometry.h"
|
||||
|
||||
namespace Part
|
||||
{
|
||||
@@ -96,4 +100,62 @@ void ShapeMapper::insert(MappingStatus status,
|
||||
}
|
||||
};
|
||||
|
||||
void GenericShapeMapper::init(const TopoShape &src, const TopoDS_Shape &dst)
|
||||
{
|
||||
for (TopExp_Explorer exp(dst, TopAbs_FACE); exp.More(); exp.Next()) {
|
||||
const TopoDS_Shape &dstFace = exp.Current();
|
||||
if (src.findShape(dstFace))
|
||||
continue;
|
||||
|
||||
std::unordered_map<TopoDS_Shape, int> map;
|
||||
bool found = false;
|
||||
|
||||
// Try to find a face in the src that shares at least two edges (or one
|
||||
// closed edge) with dstFace.
|
||||
// TODO: consider degenerative cases of two or more edges on the same line.
|
||||
for (TopExp_Explorer it(dstFace, TopAbs_EDGE); it.More(); it.Next()) {
|
||||
int idx = src.findShape(it.Current());
|
||||
if (!idx)
|
||||
continue;
|
||||
TopoDS_Edge e = TopoDS::Edge(it.Current());
|
||||
if(BRep_Tool::IsClosed(e))
|
||||
{
|
||||
// closed edge, one face is enough
|
||||
TopoDS_Shape face = src.findAncestorShape(
|
||||
src.getSubShape(TopAbs_EDGE,idx), TopAbs_FACE);
|
||||
if (!face.IsNull()) {
|
||||
this->insert(MappingStatus::Generated, face, dstFace);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
for (auto &face : src.findAncestorsShapes(src.getSubShape(TopAbs_EDGE,idx), TopAbs_FACE)) {
|
||||
int &cnt = map[face];
|
||||
if (++cnt == 2) {
|
||||
this->insert(MappingStatus::Generated, face, dstFace);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) continue;
|
||||
|
||||
// if no face matches, try search by geometry surface
|
||||
std::unique_ptr<Geometry> g(Geometry::fromShape(dstFace));
|
||||
if (!g) continue;
|
||||
|
||||
for (auto &v : map) {
|
||||
std::unique_ptr<Geometry> g2(Geometry::fromShape(v.first));
|
||||
if (g2 && g2->isSame(*g,1e-7,1e-12)) {
|
||||
this->insert(MappingStatus::Generated, v.first, dstFace);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Part
|
||||
|
||||
@@ -212,6 +212,13 @@ struct PartExport ShapeMapper: TopoShape::Mapper
|
||||
std::unordered_set<TopoDS_Shape, ShapeHasher, ShapeHasher> _modifiedShapes;
|
||||
};
|
||||
|
||||
/** Generic shape mapper from a given source to an output shape
|
||||
*/
|
||||
struct PartExport GenericShapeMapper: ShapeMapper {
|
||||
/// Populate the map with a given source shape to an output shape
|
||||
void init(const TopoShape &src, const TopoDS_Shape &dst);
|
||||
};
|
||||
|
||||
/// Parameters for TopoShape::makeElementFilledFace()
|
||||
struct PartExport TopoShape::BRepFillingParams
|
||||
{
|
||||
|
||||
@@ -210,7 +210,7 @@ public:
|
||||
private:
|
||||
void LogModifications(const ModelRefine::FaceUniter& uniter);
|
||||
|
||||
private:
|
||||
protected:
|
||||
TopTools_DataMapOfShapeListOfShape myModified;
|
||||
TopTools_ListOfShape myEmptyList;
|
||||
TopTools_ListOfShape myDeleted;
|
||||
|
||||
Reference in New Issue
Block a user