Newer
Older
#include "unitcells/UnitCellBuilder.h"
#include "unitcells/UnitCellBCC.h"
#include "BRepAlgoAPI_Fuse.hxx"
#include "BRepAlgoAPI_Common.hxx"
#include "BRepBuilderAPI_Transform.hxx"
#include "BRepPrimAPI_MakeBox.hxx"
template<class UnitCell>
class BuildLattice
{
samuel.hayden
committed
/* Data to build lattice */
double _cellX, _cellY, _cellZ;
std::vector<double> _cellRadii;
std::vector<gp_Pnt> _cellPositions;
samuel.hayden
committed
/* Built objects */
TopoDS_ListOfShape _unitCells;
TopoDS_Shape _tmpUnitCell;
TopoDS_Shape _lattice;
TopoDS_Solid _boundingBox;
protected:
bool buildCell(double w, double d, double h, double r);
bool translateCell(double dx, double dy, double dz);
bool mergeCells();
bool trimLattice();
samuel.hayden
committed
void determineBoundingBox()
{
// Compute Basic Bounding Box
double x0 = DBL_MAX, y0 = DBL_MAX, z0 = DBL_MAX;
double x1 = -DBL_MAX, y1 = -DBL_MAX, z1 = -DBL_MAX;
for (const gp_Pnt& point : _cellPositions)
{
x0 = point.X() < x0 ? point.X() : x0;
y0 = point.Y() < y0 ? point.Y() : y0;
z0 = point.Z() < z0 ? point.Z() : z0;
x1 = point.X() > x1 ? point.X() : x1;
y1 = point.Y() > y1 ? point.Y() : y1;
z1 = point.Z() > z1 ? point.Z() : z1;
}
samuel.hayden
committed
x1 += _cellX;
y1 += _cellY;
z1 += _cellZ;
_boundingBox = BRepPrimAPI_MakeBox(gp_Pnt(x0, y0, z0), gp_Pnt(x1, y1, z1));
}
samuel.hayden
committed
public:
BuildLattice()
: _cellX(0.0), _cellY(0.0), _cellZ(0.0)
{}
bool buildLattice();
TopoDS_Shape getLattice() { return _lattice; }
bool hasErrors() { return _errors.size() > 0; }
void dumpErrors()
{
for (const ErrorCodes& code : _errors)
{
ERROR_MSG("BuildLattice", code);
}
}
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
};
// Builds a cell of type UnitCell
template<class UnitCell>
bool BuildLattice<UnitCell>::buildCell(double w, double d, double h, double r)
{
UnitCell cellBuilder(w, d, h, r);
cellBuilder.buildUnitCell();
if (!cellBuilder.status())
{
std::cout << "[Error](buildCell) Error building unit cell" << std::endl;
return false;
}
_tmpUnitCell = cellBuilder.getUnitCell();
return true;
}
// Translates cell to position dx, dy, dz
template<class UnitCell>
bool BuildLattice<UnitCell>::translateCell(double dx, double dy, double dz)
{
gp_Trsf translationVector;
translationVector.SetTranslation(gp_Vec(dx, dy, dz));
_unitCells.Append(BRepBuilderAPI_Transform(_tmpUnitCell, translationVector));
return true;
}
// Merges all unit cells
template<class UnitCell>
bool BuildLattice<UnitCell>::mergeCells()
{
BRepAlgoAPI_Fuse fuser;
TopoDS_ListOfShape arg;
arg.Append(_unitCells.First());
_unitCells.RemoveFirst();
fuser.SetArguments(arg);
fuser.SetTools(_unitCells);
fuser.SetRunParallel(true);
fuser.SetFuzzyValue(1e-4);
fuser.Build();
if (fuser.HasErrors())
{
fuser.DumpErrors(std::cout);
if (fuser.HasErrors())
{
fuser.DumpErrors(std::cout);
_errors.emplace_back(ErrorCodes::FailedToMergeCells);
return false;
}
_lattice = fuser.Shape();
return true;
}
// Trims outside of lattice
template<class UnitCell>
bool BuildLattice<UnitCell>::trimLattice()
{
if (_lattice.IsNull())
_errors.emplace_back(ErrorCodes::LatticeIsNull);
if (_boundingBox.IsNull())
_errors.emplace_back(ErrorCodes::BoundingBoxIsNull);
if (hasErrors())
BRepAlgoAPI_Common trimmer(_lattice, _boundingBox);
if (trimmer.HasErrors())
{
trimmer.DumpErrors(std::cout);
_errors.emplace_back(ErrorCodes::FailedToTrimLattice);
return false;
}
_lattice = trimmer.Shape();
return true;
}
template<class UnitCell>
inline bool BuildLattice<UnitCell>::buildLattice()
{
samuel.hayden
committed
if (_boundingBox.IsNull())
determineBoundingBox();
size_t nCells = _cellRadii.size();
std::cout << "[Info](buildLattice) Building " << nCells << " cells" << std::endl;
for (size_t i = 0; i < nCells; i++)
{
samuel.hayden
committed
if (!buildCell(_cellX, _cellY, _cellZ, _cellRadii[i]))
return false;
const gp_Pnt& pos = _cellPositions[i];
if (!translateCell(pos.X(), pos.Y(), pos.Z()))
return false;
if (i % 10 == 0)
std::cout << "[Info](bulidLattice) (" << i << "/" << nCells << ") built" << std::endl;
}
std::cout << "[Info](bulidLattice) (" << nCells << "/" << nCells << ") built" << std::endl;
std::cout << "[Info](buildLattice) All cells built" << std::endl;
std::cout << "[Info](buildLattice) Merging cells (this step takes some time)" << std::endl;
if (!mergeCells())
return false;
std::cout << "[Info](buildLattice) Trimming lattice" << std::endl;
if (!trimLattice())
return false;
return true;
}