[TD]fix area calculation

This commit is contained in:
wandererfan
2024-10-17 15:27:11 -04:00
committed by Yorik van Havre
parent 6c85c37b38
commit 1de4dc600d
10 changed files with 261 additions and 14 deletions

View File

@@ -82,9 +82,11 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <Mod/Part/App/FaceMakerCheese.h>
#include <Mod/Part/App/Geometry.h>
#include <Mod/Part/App/TopoShape.h>
#include "DrawViewPart.h"
#include "Geometry.h"
#include "ShapeUtils.h"
#include "DrawUtil.h"
@@ -145,10 +147,14 @@ void Wire::dump(std::string s)
BRepTools::Write(toOccWire(), s.c_str()); //debug
}
// note that the face returned is inverted in Y
TopoDS_Face Face::toOccFace() const
{
if (wires.empty()) {
return {};
}
TopoDS_Face result;
//if (!wires.empty) {
BRepBuilderAPI_MakeFace mkFace(wires.front()->toOccWire(), true);
int limit = wires.size();
int iwire = 1;
@@ -1734,3 +1740,105 @@ double GeometryUtils::edgeLength(TopoDS_Edge occEdge)
}
}
//! return a perforated shape/face (using Part::FaceMakerCheese) formed by creating holes in the input face.
TopoDS_Face GeometryUtils::makePerforatedFace(FacePtr bigCheese, const std::vector<FacePtr> &holesAll)
{
std::vector<TopoDS_Wire> cheeseIngredients;
// v0.0 brute force
// Note: TD Faces are not perforated and should only ever have 1 wire. They are capable of
// having voids, but for now we will just take the first contour wire in all cases.
if (bigCheese->wires.empty()) {
// run in circles. scream and shout.
return {};
}
auto flippedFace = ShapeUtils::fromQtAsFace(bigCheese->toOccFace());
if (holesAll.empty()) {
return flippedFace;
}
auto outer = ShapeUtils::fromQtAsWire(bigCheese->wires.front()->toOccWire());
cheeseIngredients.push_back(outer);
for (auto& hole : holesAll) {
if (hole->wires.empty()) {
continue;
}
auto holeR3 = ShapeUtils::fromQtAsWire(hole->wires.front()->toOccWire());
cheeseIngredients.push_back(holeR3);
}
TopoDS_Shape faceShape;
try {
faceShape = Part::FaceMakerCheese::makeFace(cheeseIngredients);
}
catch (const Standard_Failure &e) {
Base::Console().Warning("Area - could not make holes in face\n");
return flippedFace;
}
// v0.0 just grab the first face
TopoDS_Face foundFace;
TopExp_Explorer expFaces(faceShape, TopAbs_FACE);
if (expFaces.More()) {
foundFace = TopoDS::Face(expFaces.Current());
}
// TODO: sort out the compound => shape but !compound => face business in FaceMakerCheese here.
// first guess is it does not affect us?
return foundFace;
}
//! find faces within the bounds of the input face
std::vector<FacePtr> GeometryUtils::findHolesInFace(const DrawViewPart* dvp, const std::string& bigCheeseSubRef)
{
if (!dvp || bigCheeseSubRef.empty()) {
return {};
}
std::vector<FacePtr> holes;
auto bigCheeseIndex = DU::getIndexFromName(bigCheeseSubRef);
// v0.0 brute force
auto facesAll = dvp->getFaceGeometry();
if (facesAll.empty()) {
// tarfu
throw Base::RuntimeError("GU::findHolesInFace - no holes to find!!");
}
auto bigCheeseFace = facesAll.at(bigCheeseIndex);
auto bigCheeseOCCFace = bigCheeseFace->toOccFace();
auto bigCheeseArea = bigCheeseFace->getArea();
int iFace{0};
for (auto& face : facesAll) {
if (iFace == bigCheeseIndex) {
iFace++;
continue;
}
if (face->getArea() > bigCheeseArea) {
iFace++;
continue;
}
auto faceCenter = DU::togp_Pnt(face->getCenter());
auto faceCenterVertex = BRepBuilderAPI_MakeVertex(faceCenter);
auto distance = DU::simpleMinDist(faceCenterVertex, bigCheeseOCCFace);
if (distance > EWTOLERANCE) {
// hole center not within outer contour. not the best test but cheese maker handles it
// for us?
// FaceMakerCheese does not support partial overlaps and just ignores them?
iFace++;
continue;
}
holes.push_back(face);
iFace++;
}
return holes;
}