42std::ostream &operator<<(std::ostream &os,
TGeoFacet const &facet)
45 for (
int i = 0; i < facet.GetNvert(); ++i) {
46 os << facet.GetVertex(i);
47 if (i != facet.GetNvert() - 1)
80 constexpr double kTolerance = 1.e-20;
83 for (
int i = 0; i <
fNvert - 1; ++i) {
85 if (e1.Mag2() < kTolerance)
87 for (
int j = i + 1; j <
fNvert; ++j) {
89 if (e2.Mag2() < kTolerance)
93 if (normal.Mag2() < kTolerance)
107 constexpr double kTolerance = 1.e-10;
108 bool degenerated =
true;
111 std::cout <<
"Facet: " << *
this <<
" is degenerated\n";
116 double surfaceArea = 0.;
117 for (
int i = 1; i <
fNvert - 1; ++i) {
122 if (surfaceArea < kTolerance) {
123 std::cout <<
"Facet: " << *
this <<
" has zero surface area\n";
142 int nvert = nvertices;
145 if (vert[(i + 1) % nvert] == vert[i]) {
147 for (
int j = i + 2; j < nvert; ++j)
148 vert[j - 1] = vert[j];
163 bool neighbour =
false;
164 int line1[2], line2[2];
166 for (
int i = 0; i <
fNvert; ++i) {
169 for (
int j = 0; j < other.
GetNvert(); ++j) {
173 if (++npoints == 2) {
175 bool order1 = line1[1] == line1[0] + 1;
176 bool order2 = line2[1] == (line2[0] + 1) % other.
GetNvert();
177 flip = (order1 == order2);
224 Error(
"AddFacet",
"Shape %s already fully defined. Not adding",
GetName());
234 Error(
"AddFacet",
"Triangular facet at index %d degenerated. Not adding.",
GetNfacets());
239 fFacets.emplace_back(pt0, pt1, pt2);
252 Error(
"AddFacet",
"Shape %s already fully defined. Not adding",
GetName());
256 Error(
"AddFacet",
"Shape %s Cannot add facets by indices without vertices. Not adding",
GetName());
271 Error(
"AddFacet",
"Shape %s already fully defined. Not adding",
GetName());
281 Error(
"AddFacet",
"Quadrilateral facet at index %d degenerated. Not adding.",
GetNfacets());
288 fFacets.emplace_back(vert[0], vert[1], vert[2]);
290 fFacets.emplace_back(vert[0], vert[1], vert[2], vert[3]);
303 Error(
"AddFacet",
"Shape %s already fully defined. Not adding",
GetName());
307 Error(
"AddFacet",
"Shape %s Cannot add facets by indices without vertices. Not adding",
GetName());
322 constexpr double tolerance = 1.e-10;
323 constexpr int ngrid = 100;
331 invExtent[0] = 0.5 / (
fDX + tolerance);
332 invExtent[1] = 0.5 / (
fDY + tolerance);
333 invExtent[2] = 0.5 / (
fDZ + tolerance);
351 for (
const auto ¤t_vert :
fVertices) {
352 if (current_vert ==
vertex)
364 for (
int i = 0; i < 3; ++i) {
365 int ind =
int(ngrid * (
vertex[i] - minExtent[i]) * invExtent[i]);
366 assert(ind < (
int)ngrid);
367 for (
int j = i + 1; j < 3; ++j)
375 int ind[4] = {-1, -1, -1, -1};
378 int nvert = facet.GetNvert();
379 for (
int i = 0; i < nvert; ++i) {
383 facet.SetVertices(&
fVertices, nvert, ind[0], ind[1], ind[2], ind[3]);
387 using CellVec_t = std::vector<int>;
388 auto grid =
new std::array<CellVec_t, ngrid * ngrid * ngrid>;
390 int nvert = facet.GetNvert();
391 for (
int i = 0; i < nvert; ++i) {
394 int hashind = GetHashIndex(
vertex);
395 bool isAdded =
false;
396 for (
auto ivert : grid->operator[](hashind)) {
406 grid->operator[](hashind).push_back(ind[i]);
409 facet.SetVertices(&
fVertices, nvert, ind[0], ind[1], ind[2], ind[3]);
434 bool hasorphans =
false;
435 bool hasflipped =
false;
436 for (
int i = 0; i <
fNfacets; ++i) {
441 for (
int icrt = 0; icrt <
fNfacets; ++icrt) {
443 if (nn[icrt] >=
fFacets[icrt].GetNvert())
445 for (
int i = icrt + 1; i <
fNfacets; ++i) {
446 bool isneighbour =
fFacets[icrt].IsNeighbour(
fFacets[i], flipped[i]);
449 flipped[i] = !flipped[i];
454 if (nn[icrt] ==
fFacets[icrt].GetNvert())
458 if (nn[icrt] <
fFacets[icrt].GetNvert())
463 Error(
"Check",
"Tessellated solid %s has following not fully connected facets:",
GetName());
464 for (
int icrt = 0; icrt <
fNfacets; ++icrt) {
465 if (nn[icrt] <
fFacets[icrt].GetNvert())
466 std::cout << icrt <<
" (" <<
fFacets[icrt].GetNvert() <<
" edges, " << nn[icrt] <<
" neighbours)\n";
473 Warning(
"Check",
"Tessellated solid %s has following facets with flipped normals:",
GetName());
474 for (
int icrt = 0; icrt <
fNfacets; ++icrt) {
477 std::cout << icrt <<
"\n";
485 Info(
"Check",
"Automatically flipped %d facets to match first defined facet", nfixed);
501 for (
const auto &facet :
fFacets) {
502 for (
int i = 0; i < facet.GetNvert(); ++i) {
503 for (
int j = 0; j < 3; ++j) {
504 vmin[j] =
TMath::Min(vmin[j], facet.GetVertex(i).operator[](j));
505 vmax[j] =
TMath::Max(vmax[j], facet.GetVertex(i).operator[](j));
509 fDX = 0.5 * (vmax[0] - vmin[0]);
510 fDY = 0.5 * (vmax[1] - vmin[1]);
511 fDZ = 0.5 * (vmax[2] - vmin[2]);
512 for (
int i = 0; i < 3; ++i)
513 fOrigin[i] = 0.5 * (vmax[i] + vmin[i]);
533 const int nsegs =
fNseg;
548 std::cout <<
"=== Tessellated shape " <<
GetName() <<
" having " <<
GetNvertices() <<
" vertices and "
559 int *pols = buff.
fPols;
564 for (
const auto &facet :
fFacets) {
565 auto nvert = facet.GetNvert();
567 pols[indpol++] = nvert;
568 for (
auto j = 0; j < nvert; ++j) {
569 int k = (j + 1) % nvert;
572 segs[indseg++] = facet.GetVertexIndex(j);
573 segs[indseg++] = facet.GetVertexIndex(k);
575 pols[indpol + nvert - j - 1] = sind++;
614 Error(
"ResizeCenter",
"Not all faces are defined");
619 double scale = maxsize / maxedge;
620 for (
size_t i = 0; i <
fVertices.size(); ++i) {
639 const int nsegs =
fNseg;
643 if (buffer.
SetRawSizes(nvert, 3 * nvert, nsegs, 3 * nsegs, npols, 6 * npols)) {
667 vector<Vertex_t> vertices;
668 vector<string> sfacets;
676 FacetInd_t(
int a,
int b,
int c)
683 FacetInd_t(
int a,
int b,
int c,
int d)
693 vector<FacetInd_t> facets;
716 ifstream
file(objfile);
717 if (!
file.is_open()) {
718 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Unable to open %s", objfile);
723 stringstream ss(
line);
727 if (
line.rfind(
"v", 0) == 0 &&
line.rfind(
"vt", 0) != 0 &&
line.rfind(
"vn", 0) != 0 &&
line.rfind(
"vn", 0) != 0) {
729 double pos[4] = {0, 0, 0, 1};
730 ss >> tag >> pos[0] >> pos[1] >> pos[2] >> pos[3];
731 vertices.emplace_back(pos[0] * pos[3], pos[1] * pos[3], pos[2] * pos[3]);
734 else if (
line.rfind(
"f", 0) == 0) {
740 sfacets.push_back(word);
741 if (sfacets.size() > 4 || sfacets.size() < 3) {
742 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Detected face having unsupported %zu vertices",
747 for (
auto sword : sfacets) {
748 stringstream ssword(sword);
750 getline(ssword, token,
'/');
753 ind[nvert++] = stoi(token) - 1;
754 if (ind[nvert - 1] < 0) {
755 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Unsupported relative vertex index definition in %s",
761 facets.emplace_back(ind[0], ind[1], ind[2]);
763 facets.emplace_back(ind[0], ind[1], ind[2], ind[3]);
767 int nvertices = (
int)vertices.size();
768 int nfacets = (
int)facets.size();
770 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Not enough faces detected in %s", objfile);
774 string sobjfile(objfile);
776 std::cout <<
"Read " << nvertices <<
" vertices and " << nfacets <<
" facets from " << sobjfile << endl;
778 auto tsl =
new TGeoTessellated(sobjfile.erase(sobjfile.find_last_of(
'.')).c_str(), vertices);
780 for (
int i = 0; i < nfacets; ++i) {
781 auto facet = facets[i];
782 if (facet.nvert == 3)
783 tsl->AddFacet(facet.i0, facet.i1, facet.i2);
785 tsl->AddFacet(facet.i0, facet.i1, facet.i2, facet.i3);
787 tsl->CloseShape(check,
true,
verbose);
TGLVector3 Cross(const TGLVector3 &v1, const TGLVector3 &v2)
Generic 3D primitive description class.
Bool_t SectionsValid(UInt_t mask) const
void SetSectionsValid(UInt_t mask)
Bool_t SetRawSizes(UInt_t reqPnts, UInt_t reqPntsCapacity, UInt_t reqSegs, UInt_t reqSegsCapacity, UInt_t reqPols, UInt_t reqPolsCapacity)
Set kRaw tessellation section of buffer with supplied sizes.
virtual void FillBuffer3D(TBuffer3D &buffer, Int_t reqSections, Bool_t localFrame) const
Fills the supplied buffer, with sections in desired frame See TBuffer3D.h for explanation of sections...
Tessellated::VertexVec_t VertexVec_t
bool IsNeighbour(const TGeoFacet &other, bool &flip) const
Check if a connected neighbour facet has compatible normal.
static int CompactFacet(Vertex_t *vert, int nvertices)
int GetVertexIndex(int ivert) const
Vertex_t & GetVertex(int ivert)
int fNvert
array of vertices
Vertex_t ComputeNormal(bool °enerated) const
const TGeoFacet & operator=(const TGeoFacet &other)
Int_t GetBasicColor() const
Get the basic color (0-7).
void TransformPoints(Double_t *points, UInt_t NbPoints) const
Tranform a set of points (LocalToMaster)
virtual const char * GetName() const
Get the shape name.
void ResizeCenter(double maxsize)
Resize and center the shape in a box of size maxsize.
virtual void Print(Option_t *option="") const
Prints basic info.
virtual const TBuffer3D & GetBuffer3D(int reqSections, Bool_t localFrame) const
Fills a static 3D buffer and returns a reference.
virtual void SetSegsAndPols(TBuffer3D &buff) const
Fills TBuffer3D structure for segments and polygons.
bool CheckClosure(bool fixFlipped=true, bool verbose=true)
Check closure of the solid and check/fix flipped normals.
virtual void SetPoints(double *points) const
Fill tessellated points to an array.
virtual TBuffer3D * MakeBuffer3D() const
Creates a TBuffer3D describing this shape.
void CloseShape(bool check=true, bool fixFlipped=true, bool verbose=true)
Close the shape: calculate bounding box and compact vertices.
Tessellated::Vertex_t Vertex_t
std::vector< TGeoFacet > fFacets
static TGeoTessellated * ImportFromObjFormat(const char *objfile, bool check=false, bool verbose=false)
Reader from .obj format.
void ComputeBBox()
Compute bounding box.
virtual void AfterStreamer()
Function to be called after reading tessellated volumes from the geometry file.
bool AddFacet(const Vertex_t &pt0, const Vertex_t &pt1, const Vertex_t &pt2)
Adding a triangular facet from vertex positions in absolute coordinates.
virtual void GetMeshNumbers(int &nvert, int &nsegs, int &npols) const
Returns numbers of vertices, segments and polygons composing the shape mesh.
std::vector< Vertex_t > fVertices
bool fClosedBody
Shape fully defined.
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Short_t Max(Short_t a, Short_t b)
Short_t Min(Short_t a, Short_t b)
Typedefs used by the geometry group.
static int AddVertex(GLUtesselator *tess, GLdouble coords[3], void *data)
void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)