1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
#include <BOPAlgo_Builder.hxx>
#include <BRepAlgoAPI_Splitter.hxx>
#include <BRepBndLib.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_Sewing.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <Bnd_Box.hxx>
#include <Geom_Plane.hxx>
#include <Geom_Surface.hxx>
#include <Precision.hxx>
#include <ShapeBuild_ReShape.hxx>
#include <ShapeFix_Shape.hxx>
#include <Standard_Handle.hxx>
#include <Standard_TypeDef.hxx>
#include <TopAbs_ShapeEnum.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <algorithm>
#include <gp.hxx>
#include <gp_Ax3.hxx>
#include <gp_Pln.hxx>
#include <gp_Trsf.hxx>
#include <limits>
#include "core/array.hpp"
#include "occ_utils.hpp"
#include "occgeom.hpp"
namespace netgen
{
TopoDS_Face MakePlaneFaceCoveringShape
(const TopoDS_Shape& shape,
const gp_Pln& pln,
double rel_margin = 0.05,
double abs_margin = 0.0)
{
Bnd_Box b;
BRepBndLib::Add(shape, b);
b.SetGap(0.0);
Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
b.Get(xmin, ymin, zmin, xmax, ymax, zmax);
gp_Trsf w2l;
w2l.SetTransformation(pln.Position());
auto upd = [&] (double x, double y, double z, double& umin, double& umax, double& vmin, double& vmax) {
gp_Pnt p(x, y, z);
p.Transform(w2l);
umin = std::min(umin, p.X());
umax = std::max(umax, p.X());
vmin = std::min(vmin, p.Y());
vmax = std::max(vmax, p.Y());
};
double umin = std::numeric_limits<double>::infinity();
double umax = -std::numeric_limits<double>::infinity();
double vmin = std::numeric_limits<double>::infinity();
double vmax = -std::numeric_limits<double>::infinity();
upd(xmin, ymin, zmin, umin, umax, vmin, vmax);
upd(xmin, ymin, zmax, umin, umax, vmin, vmax);
upd(xmin, ymax, zmin, umin, umax, vmin, vmax);
upd(xmin, ymax, zmax, umin, umax, vmin, vmax);
upd(xmax, ymin, zmin, umin, umax, vmin, vmax);
upd(xmax, ymin, zmax, umin, umax, vmin, vmax);
upd(xmax, ymax, zmin, umin, umax, vmin, vmax);
upd(xmax, ymax, zmax, umin, umax, vmin, vmax);
double du = umax - umin;
double dv = vmax - vmin;
double pad = std::max(abs_margin, rel_margin * std::max(du, dv));
umin -= pad;
umax += pad;
vmin -= pad;
vmax += pad;
double eps = std::max(Precision::Confusion(), 1e-9);
if (umax - umin < eps)
{
umin -= 1.0;
umax += 1.0;
}
if (vmax - vmin < eps)
{
vmin -= 1.0;
vmax += 1.0;
}
return BRepBuilderAPI_MakeFace(pln, umin, umax, vmin, vmax).Face();
}
TopoDS_Shape CrossSection (const TopoDS_Shape& shape,
const gp_Ax3& axes)
{
gp_Pln pln(axes);
TopoDS_Face planeFace = MakePlaneFaceCoveringShape(shape, axes);
auto bb = GetBoundingBox(shape);
auto diam = bb.Diam();
// Heal / unify the input
// - especially if shape comes from STEP/IGES
ShapeFix_Shape fix(shape);
fix.Perform();
TopoDS_Shape fixed = fix.Shape();
BRepAlgoAPI_Splitter splitter;
splitter.SetNonDestructive(true);
splitter.SetFuzzyValue(1e-7 * diam);
TopTools_ListOfShape args;
args.Append(shape);
TopTools_ListOfShape tools;
tools.Append(planeFace);
splitter.SetArguments(args);
splitter.SetTools(tools);
splitter.Build();
if (!splitter.IsDone())
return TopoDS_Shape();
// for each input face/edge propagate properties to generated sub-shapes
for (auto typ : {TopAbs_FACE, TopAbs_EDGE})
for (TopExp_Explorer e(shape, typ); e.More(); e.Next())
{
if (!OCCGeometry::HaveProperties(e.Current()))
continue;
auto prop = OCCGeometry::GetProperties(e.Current());
for (auto mods : splitter.Generated(e.Current()))
OCCGeometry::GetProperties(mods).Merge(prop);
}
// for each input solid, find the cut faces and propagate properties
for (auto solid : GetSolids(shape))
{
if (!OCCGeometry::HaveProperties(solid))
continue;
auto prop = OCCGeometry::GetProperties(solid);
for (auto mods : splitter.Modified(solid))
{
if (mods.ShapeType() != TopAbs_SOLID)
continue;
for (TopExp_Explorer ef(mods, TopAbs_FACE); ef.More(); ef.Next())
OCCGeometry::GetProperties(ef.Current()).Merge(prop);
}
}
TopoDS_Shape res = splitter.Shape();
const gp_Ax1 ax = axes.Axis();
const gp_Dir n = ax.Direction();
const gp_Pnt p0 = axes.Location();
Array<TopoDS_Shape> out_shapes;
for (auto f : GetFaces(res))
{
Handle(Geom_Surface) s = BRep_Tool::Surface(TopoDS::Face(f));
Handle(Geom_Plane) gp = Handle(Geom_Plane)::DownCast(s);
if (gp.IsNull())
continue;
// Check coplanarity (orientation can flip)
gp_Pln fpln = gp->Pln();
auto my_n = fpln.Position().Axis().Direction();
if (!my_n.IsParallel(n, 1e-10))
continue;
// Check distance of face plane to our plane
Standard_Real dist = fpln.Distance(p0);
if (dist > 1e-7 * diam)
continue;
if (my_n.Dot(n) > 0)
f.Reverse();
out_shapes.Append(f);
}
BRepBuilderAPI_Sewing sew(1e-7 * diam);
for (auto s : out_shapes)
sew.Add(TopoDS::Face(s));
sew.Perform();
for (auto s : out_shapes)
PropagateProperties(sew, s);
auto out = sew.SewedShape();
gp_Ax3 xy(gp::XOY());
gp_Trsf T;
T.SetTransformation(axes, xy);
BRepBuilderAPI_Transform btransf(out, T, Standard_True);
PropagateProperties(btransf, out);
return btransf.Shape();
}
} // namespace netgen
|