39 fgToleranceHalf = 0.5 * fgTolerance;
46 fGeometryType =
"UTessellatedSolid";
105 if (&ss ==
this)
return *
this;
108 VUSolid::operator=(ss);
124 for (
int i = 0; i < size; ++i)
141 for (
int i = 0; i <
n; ++i)
160 UUtils::Exception(
"UTessellatedSolid::AddFacet()",
"GeomSolids1002",
Warning, 1,
"Attempt to add facets when solid is closed.");
178 while (!found && it != end)
183 found = (facet == aFacet);
185 double dif = q.
x + q.
y + q.
z - value.
mag2;
186 if (dif > fgTolerance3)
break;
193 while (!found && it != begin)
199 found = (facet == aFacet);
201 double dif = q.
x + q.
y + q.
z - q.
Mag2();
202 if (dif > fgTolerance3)
break;
216 UUtils::Exception(
"UTessellatedSolid::AddFacet()",
"GeomSolids1002",
Warning, 1,
"Attempt to add facet not properly defined.");
226 vector<int> xyz = voxel;
227 stack<vector<int> >
pos;
232 vector<int> candidates;
250 for (
int i = 0; i <= 2; ++i)
252 if (xyz[i] < max[i] - 1)
280 vector<int> voxel(3), maxVoxels(3);
282 int size = maxVoxels[0] * maxVoxels[1] * maxVoxels[2];
284 UBits checked(size - 1);
289 for (voxel[2] = 0; voxel[2] < maxVoxels[2] - 1; ++voxel[2])
291 for (voxel[1] = 0; voxel[1] < maxVoxels[1] - 1; ++voxel[1])
293 for (voxel[0] = 0; voxel[0] < maxVoxels[0] - 1; ++voxel[0])
313 cout <<
"Voxelizing...\n";
320 cout <<
"Precalculating Insides...\n";
345 for (
int j = 0; j < size; ++j)
349 bool isExtreme =
true;
350 for (
int i = 0; i < vsize; ++i)
371 set<UVertexInfo, UVertexComparator> vertexListSorted;
372 set<UVertexInfo, UVertexComparator>::iterator begin = vertexListSorted.begin(), end = vertexListSorted.end(),
pos, it;
378 vector<int> newIndex(100);
382 for (
int k = 0; k < size; ++k)
387 for (
int i = 0; i <
max; ++i)
397 pos = vertexListSorted.lower_bound(value);
404 double dif = (q - p).Mag2();
405 found = (dif < fgTolerance24);
407 dif = q.
x + q.
y + q.
z - value.
mag2;
408 if (dif > fgTolerance3)
break;
420 double dif = (q - p).Mag2();
421 found = (dif < fgTolerance24);
423 dif = value.
mag2 - (q.
x + q.
y + q.
z);
434 cout << p.
x() <<
":" << p.
y() <<
":" << p.
z() << endl;
435 cout <<
"Adding new vertex #" << i <<
" of facet " << k <<
" id " << value.
id << endl;
436 cout <<
"===" << endl;
439 vertexListSorted.insert(value);
440 begin = vertexListSorted.begin();
441 end = vertexListSorted.end();
442 newIndex[i] = value.
id;
461 cout << p.
x() <<
":" << p.
y() <<
":" << p.
z() << endl;
462 cout <<
"Vertex #" << i <<
" of facet " << k <<
" found, redirecting to " <<
id << endl;
463 cout <<
"===" << endl;
470 for (
int i = 0; i <
max; i++)
477 double previousValue = 0;
478 for (res = vertexListSorted.begin(); res != vertexListSorted.end(); ++res)
482 double value = abs(vec.
Mag());
483 if (previousValue > value)
484 cout <<
"Error!" <<
"\n";
485 previousValue = value;
496 double ratio = (double) with / without;
497 cout <<
"Allocated memory without voxel overhead " << without <<
"; with " << with <<
"; ratio: " << ratio << endl;
543 int size =
right.GetNumberOfFacets();
544 for (
int i = 0; i < size; ++i)
545 AddFacet(
right.GetFacet(i)->GetClone());
571 vector<int> startingVoxel(3);
575 int limit = startingCandidates.size();
587 for (
int i = 0; i < limit; ++i)
589 int candidate = startingCandidates[i];
591 double dist = facet.
Distance(p, minDist);
592 if (dist < minDist) minDist = dist;
612 double distFromSurfaceO = 0.0;
613 double distFromSurfaceI = 0.0;
615 bool crossingO =
false;
616 bool crossingI =
false;
624 bool nearParallel =
false;
646 vector<int> curVoxel(3);
647 curVoxel = startingVoxel;
650 bool crossed =
false;
658 if (
int candidatesCount = candidates.size())
661 for (
int i = 0 ; i < candidatesCount; ++i)
664 int candidate = candidates[i];
667 crossingO = facet.
Intersect(p, v,
true, distO, distFromSurfaceO, normalO);
668 crossingI = facet.
Intersect(p, v,
false, distI, distFromSurfaceI, normalI);
670 if (crossingO || crossingI)
675 nearParallel = (crossingO && std::fabs(normalO.
Dot(v)) <
dirTolerance) ||
679 if (crossingO && distO > 0.0 && distO < distOut)
681 if (crossingI && distI > 0.0 && distI < distIn)
687 if (nearParallel)
break;
722 std::ostringstream message;
723 int oldprc = message.precision(16);
724 message <<
"Cannot determine whether point is inside or outside volume!"
726 <<
"Solid name = " <<
GetName() << endl
728 <<
"Number of facets = " <<
fFacets.size() << endl
729 <<
"Position:" << endl << endl
730 <<
"p.x() = " << p.
x() /
mm <<
" mm" << endl
731 <<
"p.y() = " << p.
y() /
mm <<
" mm" << endl
732 <<
"p.z() = " << p.
z() /
mm <<
" mm";
733 message.precision(oldprc);
735 "GeomSolids1002",
Warning, 1, message.str().c_str());
785 if (location != insideNoVoxels)
786 location = insideNoVoxels;
808 for (
int i = 0; i < size; ++i)
811 double dist = facet.
Distance(p, minDist);
812 if (dist < minDist) minDist = dist;
839 double distFromSurfaceO = 0.0;
840 double distFromSurfaceI = 0.0;
843 bool crossingO =
false;
844 bool crossingI =
false;
849 for (
int i = 0; i < nTry; ++i)
851 bool nearParallel =
false;
864 vector<VUFacet*>::const_iterator f =
fFacets.begin();
874 crossingO = ((*f)->Intersect(p, v,
true, distO, distFromSurfaceO, normalO));
875 crossingI = ((*f)->Intersect(p, v,
false, distI, distFromSurfaceI, normalI));
876 if (crossingO || crossingI)
878 nearParallel = (crossingO && std::fabs(normalO.
Dot(v)) <
dirTolerance) ||
882 if (crossingO && distO > 0.0 && distO < distOut) distOut = distO;
883 if (crossingI && distI > 0.0 && distI < distIn) distIn = distI;
887 while (!nearParallel && ++f !=
fFacets.end());
900 std::ostringstream message;
901 int oldprc = message.precision(16);
902 message <<
"Cannot determine whether point is inside or outside volume!"
904 <<
"Solid name = " <<
GetName() << endl
906 <<
"Number of facets = " <<
fFacets.size() << endl
907 <<
"Position:" << endl << endl
908 <<
"p.x() = " << p.
x() /
mm <<
" mm" << endl
909 <<
"p.y() = " << p.
y() /
mm <<
" mm" << endl
910 <<
"p.z() = " << p.
z() /
mm <<
" mm";
911 message.precision(oldprc);
913 "GeomSolids1002",
Warning, 1, message.str().c_str());
934 if (i == 0) location = locationprime;
952 vector<int> curVoxel(3);
957 if (
int limit = candidates.size())
960 for (
int i = 0 ; i < limit ; ++i)
962 int candidate = candidates[i];
964 double dist = f.
Distance(p, minDist);
965 if (dist < minDist) minDist = dist;
979 for (
int i = 0; i < size; ++i)
982 double dist = f.
Distance(p, minDist);
999 std::ostringstream message;
1000 message <<
"Point p is not on surface !?" << endl
1001 <<
" No facets found for point: " << p <<
" !" << endl
1002 <<
" Returning approximated value for normal.";
1005 Warning, 1, message.str().c_str());
1027 double distFromSurface = 0.0;
1033 std::ostringstream message;
1034 int oldprc = message.precision(16) ;
1035 message <<
"Point p is already inside!?" << endl
1036 <<
"Position:" << endl << endl
1037 <<
" p.x() = " << p.
x() /
mm <<
" mm" << endl
1038 <<
" p.y() = " << p.
y() /
mm <<
" mm" << endl
1039 <<
" p.z() = " << p.
z() /
mm <<
" mm" << endl
1041 message.precision(oldprc) ;
1043 Warning, 1, message.str().c_str());
1048 for (
int i = 0; i < size; ++i)
1051 if (facet.
Intersect(p, v,
false, dist, distFromSurface, normal))
1060 if (distFromSurface >
fgToleranceHalf && dist >= 0.0 && dist < minDist)
1082 double distFromSurface = 0.0;
1088 std::ostringstream message;
1089 int oldprc = message.precision(16) ;
1090 message <<
"Point p is already outside!?" << endl
1091 <<
"Position:" << endl << endl
1092 <<
" p.x() = " << p.
x() /
mm <<
" mm" << endl
1093 <<
" p.y() = " << p.
y() /
mm <<
" mm" << endl
1094 <<
" p.z() = " << p.
z() /
mm <<
" mm" << endl
1096 message.precision(oldprc) ;
1098 Warning, 1, message.str().c_str());
1102 bool isExtreme =
false;
1104 for (
int i = 0; i < size; ++i)
1107 if (facet.
Intersect(p, v,
true, dist, distFromSurface, normal))
1119 if (dist >= 0.0 && dist < minDist)
1133 aNormalVector = minNormal;
1134 aConvex = isExtreme;
1141 Normal(p, aNormalVector);
1149 const UVector3& direction,
double& minDist,
UVector3& minNormal,
int& minCandidate )
const
1151 int candidatesCount = candidates.size();
1153 double distFromSurface = 0.0;
1156 for (
int i = 0 ; i < candidatesCount; ++i)
1158 int candidate = candidates[i];
1161 if (facet.
Intersect(aPoint, direction,
true, dist, distFromSurface, normal))
1169 minCandidate = candidate;
1172 if (dist >= 0.0 && dist < minDist)
1176 minCandidate = candidate;
1193 vector<int> curVoxel(3);
1202 int minCandidate = -1;
1209 if ( candidates.size())
1212 if (minDistance <= shift)
break;
1220 while (minDistance > shift);
1222 if (minCandidate < 0)
1227 Normal(aPoint, aNormalVector);
1242 int candidatesCount = candidates.size();
1244 double distFromSurface = 0.0;
1248 for (
int i = 0 ; i < candidatesCount; ++i)
1250 int candidate = candidates[i];
1253 if (facet.
Intersect(aPoint, direction,
false, dist, distFromSurface, normal))
1262 if (distFromSurface >
fgToleranceHalf && dist >= 0.0 && dist < minDistance)
1285 double minDistance, distance;
1294 if (shift) currentPoint += direction * shift;
1299 vector<int> curVoxel(3);
1305 if (candidates.size())
1308 if (minDistance > distance) minDistance = distance;
1309 if (distance < shift)
break;
1313 while (minDistance > shift);
1319 minDistance = distanceToInNoVoxels;
1335 const std::pair<int, double>& r)
1337 return l.second < r.second;
1352 vector<pair<int, double> > voxelsSorted(size);
1354 pair<int, double> info;
1356 for (
int i = 0; i < size; ++i)
1363 info.second = safety;
1364 voxelsSorted[i] = info;
1369 for (
int i = 0; i < size; ++i)
1371 const pair<int, double>& inf = voxelsSorted[i];
1373 double dist = inf.second;
1374 if (dist > minDist)
break;
1377 int csize = candidates.size();
1378 for (
int j = 0; j < csize; ++j)
1380 int candidate = candidates[j];
1382 dist = simple ? facet.
Distance(p, minDist) : facet.
Distance(p, minDist,
false);
1400 std::ostringstream message;
1401 int oldprc = message.precision(16) ;
1402 message <<
"Point p is already inside!?" << endl
1403 <<
"Position:" << endl << endl
1404 <<
"p.x() = " << p.
x() /
mm <<
" mm" << endl
1405 <<
"p.y() = " << p.
y() /
mm <<
" mm" << endl
1406 <<
"p.z() = " << p.
z() /
mm <<
" mm" << endl
1408 message.precision(oldprc) ;
1410 Warning, 1, message.str().c_str());
1422 vector<int> startingVoxel(3);
1441 for (
int i = 0; i < size; ++i)
1444 double dist = facet.
Distance(p, minDist);
1445 if (dist < minDist) minDist = dist;
1463 std::ostringstream message;
1464 int oldprc = message.precision(16) ;
1465 message <<
"Point p is already outside!?" << endl
1466 <<
"Position:" << endl << endl
1467 <<
"p.x() = " << p.
x() /
mm <<
" mm" << endl
1468 <<
"p.y() = " << p.
y() /
mm <<
" mm" << endl
1469 <<
"p.z() = " << p.
z() /
mm <<
" mm" << endl
1471 message.precision(oldprc) ;
1473 Warning, 1, message.str().c_str());
1491 for (
int i = 0; i < size; ++i)
1495 if (dist < minDist) minDist = dist;
1519 os <<
"Number of facets = " <<
fFacets.size() << endl;
1522 for (
int i = 0; i < size; ++i)
1524 os <<
"FACET # = " << i + 1 << endl;
1599 for (
int i = 0; i < size; ++i)
1614 return fFacets[i]->GetPointOnFace();
1629 fRandir[0] =
UVector3(-0.9577428892113370, 0.2732676269591740, 0.0897405271949221);
1630 fRandir[1] =
UVector3(-0.8331264504940770, -0.5162067214954600, -0.1985722492445700);
1631 fRandir[2] =
UVector3(-0.1516671651108820, 0.9666292616127460, 0.2064580868390110);
1632 fRandir[3] =
UVector3(0.6570250350323190, -0.6944539025883300, 0.2933460081893360);
1633 fRandir[4] =
UVector3(-0.4820456281280320, -0.6331060000098690, -0.6056474264406270);
1634 fRandir[5] =
UVector3(0.7629032554236800 , 0.1016854697539910, -0.6384658864065180);
1635 fRandir[6] =
UVector3(0.7689540409061150, 0.5034929891988220, 0.3939600142169160);
1636 fRandir[7] =
UVector3(0.5765188359255740, 0.5997271636278330, -0.5549354566343150);
1637 fRandir[8] =
UVector3(0.6660632777862070, -0.6362809868288380, 0.3892379937580790);
1638 fRandir[9] =
UVector3(0.3824415020414780, 0.6541792713761380, -0.6525243125110690);
1639 fRandir[10] =
UVector3(-0.5107726564526760, 0.6020905056811610, 0.6136760679616570);
1640 fRandir[11] =
UVector3(0.7459135439578050, 0.6618796061649330, 0.0743530220183488);
1641 fRandir[12] =
UVector3(0.1536405855311580, 0.8117477913978260, -0.5634359711967240);
1642 fRandir[13] =
UVector3(0.0744395301705579, -0.8707110101772920, -0.4861286795736560);
1643 fRandir[14] =
UVector3(-0.1665874645185400, 0.6018553940549240, -0.7810369397872780);
1644 fRandir[15] =
UVector3(0.7766902003633100, 0.6014617505959970, -0.1870724331097450);
1645 fRandir[16] =
UVector3(-0.8710128685847430, -0.1434320216603030, -0.4698551243971010);
1646 fRandir[17] =
UVector3(0.8901082092766820, -0.4388411398893870, 0.1229871120030100);
1647 fRandir[18] =
UVector3(-0.6430417431544370, -0.3295938228697690, 0.6912779675984150);
1648 fRandir[19] =
UVector3(0.6331124368380410, 0.6306211461665000, 0.4488714875425340);
1659 int base =
sizeof(*this);
1664 for (
int i = 0; i < limit; ++i)
1670 std::set<VUFacet*>::const_iterator beg, end, it;
1673 for (it = beg; it != end; it++)
1688 size += sizeInsides + sizeVoxels;
double GetMaxZExtent() const
virtual UGeometryType GetEntityType() const
double GetMinYExtent() const
virtual bool Intersect(const UVector3 &, const UVector3 &, const bool, double &, double &, UVector3 &)=0
static const double dirTolerance
virtual UVector3 GetPointOnSurface() const
const std::vector< double > & GetBoundary(int index) const
int GetVoxelsIndex(int x, int y, int z) const
double DistanceToNext(const UVector3 &point, const UVector3 &direction, std::vector< int > &curVoxel) const
UTessellatedSolid & operator=(const UTessellatedSolid &s)
virtual ~UTessellatedSolid()
double GetMinXExtent() const
virtual bool Normal(const UVector3 &p, UVector3 &aNormal) const
virtual std::ostream & StreamInfo(std::ostream &os) const
std::vector< UVector3 > fRandir
double GetMaxYExtent() const
unsigned int GetNbytes() const
bool OutsideOfExtent(const UVector3 &p, double tolerance=0) const
std::set< VUFacet * > fExtremeFacets
const std::string & GetName() const
virtual int GetNumberOfVertices() const =0
static double fgTolerance
void PrecalculateInsides()
double MinDistanceFacet(const UVector3 &p, bool simple, VUFacet *&facet) const
void Voxelize(std::vector< VUSolid * > &solids, std::vector< UTransform3D > &transforms)
virtual double SafetyFromOutside(const UVector3 &p, bool aAccurate=false) const
unsigned int GetNbits() const
void SetMaxVoxels(int max)
bool AddFacet(VUFacet *aFacet)
virtual VUSolid * Clone() const
std::ostream & StreamInfo(std::ostream &os) const
int GetNumberOfFacets() const
void DistanceToOutCandidates(const std::vector< int > &candidates, const UVector3 &aPoint, const UVector3 &direction, double &minDist, UVector3 &minNormal, int &minCandidate) const
virtual UVector3 GetVertex(int i) const =0
virtual double DistanceToIn(const UVector3 &p, const UVector3 &v, double aPstep=UUtils::kInfinity) const
void GetVoxel(std::vector< int > &curVoxel, const UVector3 &point) const
static double Tolerance()
bool Contains(const UVector3 &point) const
double GetMaxXExtent() const
long long GetCountOfVoxels() const
std::vector< VUFacet * > fFacets
static double normal(HepRandomEngine *eptr)
int GetMaxVoxels(UVector3 &ratioOfReduction)
double DistanceToFirst(const UVector3 &point, const UVector3 &direction) const
static const double kInfinity
static bool CompareSortedVoxel(const std::pair< int, double > &l, const std::pair< int, double > &r)
int GetVoxelBoxesSize() const
VUSolid::EnumInside InsideNoVoxels(const UVector3 &p) const
double DistanceToOutNoVoxels(const UVector3 &p, const UVector3 &v, UVector3 &aNormalVector, bool &aConvex, double aPstep=UUtils::kInfinity) const
double DistanceToInNoVoxels(const UVector3 &p, const UVector3 &v, double aPstep=UUtils::kInfinity) const
static double MinDistanceToBox(const UVector3 &aPoint, const UVector3 &f)
int AllocatedMemoryWithoutVoxels()
void Initialize()
TODO: make a benchmark for automatic selection of number of voxels. random voxels will be selected...
virtual UVector3 GetSurfaceNormal() const =0
virtual UVector3 GetCircumcentre() const =0
double DistanceToInCandidates(const std::vector< int > &candidates, const UVector3 &aPoint, const UVector3 &aDirection) const
double DistanceToInCore(const UVector3 &p, const UVector3 &v, double aPstep=UUtils::kInfinity) const
virtual VUSolid::EnumInside Inside(const UVector3 &p) const
double Dot(const UVector3 &) const
bool IsInside(const UVector3 &p) const
virtual int AllocatedMemory()=0
void Extent(UVector3 &aMin, UVector3 &aMax) const
const UVoxelBox & GetVoxelBox(int i) const
UGeometryType fGeometryType
void SetBitNumber(unsigned int bitnumber, bool value=true)
double GetMinZExtent() const
void Exception(const char *originOfException, const char *exceptionCode, UExceptionSeverity severity, int level, const char *description)
void DisplayAllocatedMemory()
std::vector< UVector3 > fVertexList
virtual double GetArea()=0
virtual double SafetyFromInside(const UVector3 &p, bool aAccurate=false) const
const std::vector< int > & GetCandidates(std::vector< int > &curVoxel) const
virtual bool IsDefined() const =0
T max(const T t1, const T t2)
brief Return the largest of the two arguments
VUSolid::EnumInside InsideVoxels(const UVector3 &aPoint) const
const std::vector< int > & GetVoxelBoxCandidates(int i) const
virtual void SetVertices(std::vector< UVector3 > *vertices)=0
std::set< UVertexInfo, UVertexComparator > fFacetList
double DistanceToOutCore(const UVector3 &p, const UVector3 &v, UVector3 &aNormalVector, bool &aConvex, double aPstep=UUtils::kInfinity) const
bool GetSolidClosed() const
void CopyObjects(const UTessellatedSolid &s)
std::string UGeometryType
void SetSolidClosed(const bool t)
double SafetyToBoundingBox(const UVector3 &point) const
void ResetBitNumber(unsigned int bitnumber)
virtual double GetSurfaceArea()
const UBits & Empty() const
double Random(double min=0.0, double max=1.0)
virtual double DistanceToOut(const UVector3 &p, const UVector3 &v, UVector3 &aNormalVector, bool &aConvex, double aPstep=UUtils::kInfinity) const
static const G4double pos
VUFacet * GetFacet(int i) const
bool IsEmpty(int index) const
virtual void SetVertexIndex(const int i, const int j)=0
int SetAllUsingStack(const std::vector< int > &voxel, const std::vector< int > &max, bool status, UBits &checked)
virtual double Distance(const UVector3 &, const double)=0