38 fgToleranceHalf = 0.5 * fgTolerance;
45 fGeometryType =
"TessellatedSolid";
104 if (&ss ==
this)
return *
this;
107 VUSolid::operator=(ss);
123 for (
int i = 0; i < size; ++i)
140 for (
int i = 0; i <
n; ++i)
160 UWarning, 1,
"Attempt to add facets when solid is closed.");
169 value.
mag2 = p.
x() + p.
y() + p.
z();
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;
217 UWarning, 1,
"Attempt to add facet not properly defined.");
227 vector<int> xyz = voxel;
228 stack<vector<int> >
pos;
233 vector<int> candidates;
251 for (
int i = 0; i <= 2; ++i)
253 if (xyz[i] < max[i] - 1)
281 vector<int> voxel(3), maxVoxels(3);
283 int size = maxVoxels[0] * maxVoxels[1] * maxVoxels[2];
285 UBits checked(size - 1);
290 for (voxel[2] = 0; voxel[2] < maxVoxels[2] - 1; ++voxel[2])
292 for (voxel[1] = 0; voxel[1] < maxVoxels[1] - 1; ++voxel[1])
294 for (voxel[0] = 0; voxel[0] < maxVoxels[0] - 1; ++voxel[0])
314 cout <<
"Voxelizing...\n";
321 cout <<
"Precalculating Insides...\n";
346 for (
int j = 0; j < size; ++j)
350 bool isExtreme =
true;
351 for (
int i = 0; i < vsize; ++i)
372 set<UVertexInfo, UVertexComparator> vertexListSorted;
373 set<UVertexInfo, UVertexComparator>::iterator begin = vertexListSorted.begin(), end = vertexListSorted.end(),
pos, it;
379 vector<int> newIndex(100);
383 for (
int k = 0; k < size; ++k)
388 for (
int i = 0; i <
max; ++i)
392 value.
mag2 = p.
x() + p.
y() + p.
z();
398 pos = vertexListSorted.lower_bound(value);
405 double dif = (q - p).Mag2();
406 found = (dif < fgTolerance24);
408 dif = q.
x() + q.
y() + q.
z() - value.
mag2;
409 if (dif > fgTolerance3)
break;
421 double dif = (q - p).Mag2();
422 found = (dif < fgTolerance24);
424 dif = value.
mag2 - (q.
x() + q.
y() + q.
z());
435 cout << p.
x() <<
":" << p.
y() <<
":" << p.
z() << endl;
436 cout <<
"Adding new vertex #" << i <<
" of facet " << k <<
" id " << value.
id << endl;
437 cout <<
"===" << endl;
440 vertexListSorted.insert(value);
441 begin = vertexListSorted.begin();
442 end = vertexListSorted.end();
443 newIndex[i] = value.
id;
462 cout << p.
x() <<
":" << p.
y() <<
":" << p.
z() << endl;
463 cout <<
"Vertex #" << i <<
" of facet " << k <<
" found, redirecting to " <<
id << endl;
464 cout <<
"===" << endl;
471 for (
int i = 0; i <
max; i++)
478 double previousValue = 0;
479 for (res = vertexListSorted.begin(); res != vertexListSorted.end(); ++res)
483 double value = abs(vec.
Mag());
484 if (previousValue > value)
485 cout <<
"Error!" <<
"\n";
486 previousValue = value;
497 double ratio = (double) with / without;
498 cout <<
"Allocated memory without voxel overhead " << without <<
"; with " << with <<
"; ratio: " << ratio << endl;
544 int size =
right.GetNumberOfFacets();
545 for (
int i = 0; i < size; ++i)
546 AddFacet(
right.GetFacet(i)->GetClone());
572 vector<int> startingVoxel(3);
576 int limit = startingCandidates.size();
588 for (
int i = 0; i < limit; ++i)
590 int candidate = startingCandidates[i];
592 double dist = facet.
Distance(p, minDist);
593 if (dist < minDist) minDist = dist;
613 double distFromSurfaceO = 0.0;
614 double distFromSurfaceI = 0.0;
616 bool crossingO =
false;
617 bool crossingI =
false;
625 bool nearParallel =
false;
647 vector<int> curVoxel(3);
648 curVoxel = startingVoxel;
651 bool crossed =
false;
659 if (
int candidatesCount = candidates.size())
662 for (
int i = 0 ; i < candidatesCount; ++i)
665 int candidate = candidates[i];
668 crossingO = facet.
Intersect(p, v,
true, distO, distFromSurfaceO, normalO);
669 crossingI = facet.
Intersect(p, v,
false, distI, distFromSurfaceI, normalI);
671 if (crossingO || crossingI)
676 nearParallel = (crossingO && std::fabs(normalO.
Dot(v)) <
dirTolerance) ||
680 if (crossingO && distO > 0.0 && distO < distOut)
682 if (crossingI && distI > 0.0 && distI < distIn)
688 if (nearParallel)
break;
723 std::ostringstream message;
724 int oldprc = message.precision(16);
725 message <<
"Cannot determine whether point is inside or outside volume!"
727 <<
"Solid name = " <<
GetName() << endl
729 <<
"Number of facets = " <<
fFacets.size() << endl
730 <<
"Position:" << endl << endl
731 <<
"p.x() = " << p.
x() /
mm <<
" mm" << endl
732 <<
"p.y() = " << p.
y() /
mm <<
" mm" << endl
733 <<
"p.z() = " << p.
z() /
mm <<
" mm";
734 message.precision(oldprc);
736 "GeomSolids1002",
UWarning, 1, message.str().c_str());
786 if (location != insideNoVoxels)
787 location = insideNoVoxels;
809 for (
int i = 0; i < size; ++i)
812 double dist = facet.
Distance(p, minDist);
813 if (dist < minDist) minDist = dist;
840 double distFromSurfaceO = 0.0;
841 double distFromSurfaceI = 0.0;
844 bool crossingO =
false;
845 bool crossingI =
false;
850 for (
int i = 0; i < nTry; ++i)
852 bool nearParallel =
false;
865 vector<VUFacet*>::const_iterator f =
fFacets.begin();
875 crossingO = ((*f)->Intersect(p, v,
true, distO, distFromSurfaceO, normalO));
876 crossingI = ((*f)->Intersect(p, v,
false, distI, distFromSurfaceI, normalI));
877 if (crossingO || crossingI)
879 nearParallel = (crossingO && std::fabs(normalO.
Dot(v)) <
dirTolerance) ||
883 if (crossingO && distO > 0.0 && distO < distOut) distOut = distO;
884 if (crossingI && distI > 0.0 && distI < distIn) distIn = distI;
888 while (!nearParallel && ++f !=
fFacets.end());
901 std::ostringstream message;
902 int oldprc = message.precision(16);
903 message <<
"Cannot determine whether point is inside or outside volume!"
905 <<
"Solid name = " <<
GetName() << endl
907 <<
"Number of facets = " <<
fFacets.size() << endl
908 <<
"Position:" << endl << endl
909 <<
"p.x() = " << p.
x() /
mm <<
" mm" << endl
910 <<
"p.y() = " << p.
y() /
mm <<
" mm" << endl
911 <<
"p.z() = " << p.
z() /
mm <<
" mm";
912 message.precision(oldprc);
914 "GeomSolids1002",
UWarning, 1, message.str().c_str());
935 if (i == 0) location = locationprime;
953 vector<int> curVoxel(3);
958 if (
int limit = candidates.size())
961 for (
int i = 0 ; i < limit ; ++i)
963 int candidate = candidates[i];
965 double dist = f.
Distance(p, minDist);
966 if (dist < minDist) minDist = dist;
980 for (
int i = 0; i < size; ++i)
983 double dist = f.
Distance(p, minDist);
1000 std::ostringstream message;
1001 message <<
"Point p is not on surface !?" << endl
1002 <<
" No facets found for point: " << p <<
" !" << endl
1003 <<
" Returning approximated value for normal.";
1006 UWarning, 1, message.str().c_str());
1028 double distFromSurface = 0.0;
1034 std::ostringstream message;
1035 int oldprc = message.precision(16) ;
1036 message <<
"Point p is already inside!?" << endl
1037 <<
"Position:" << endl << endl
1038 <<
" p.x() = " << p.
x() /
mm <<
" mm" << endl
1039 <<
" p.y() = " << p.
y() /
mm <<
" mm" << endl
1040 <<
" p.z() = " << p.
z() /
mm <<
" mm" << endl
1042 message.precision(oldprc) ;
1044 UWarning, 1, message.str().c_str());
1049 for (
int i = 0; i < size; ++i)
1052 if (facet.
Intersect(p, v,
false, dist, distFromSurface, normal))
1061 if (distFromSurface >
fgToleranceHalf && dist >= 0.0 && dist < minDist)
1083 double distFromSurface = 0.0;
1089 std::ostringstream message;
1090 int oldprc = message.precision(16) ;
1091 message <<
"Point p is already outside!?" << endl
1092 <<
"Position:" << endl << endl
1093 <<
" p.x() = " << p.
x() /
mm <<
" mm" << endl
1094 <<
" p.y() = " << p.
y() /
mm <<
" mm" << endl
1095 <<
" p.z() = " << p.
z() /
mm <<
" mm" << endl
1097 message.precision(oldprc) ;
1099 UWarning, 1, message.str().c_str());
1103 bool isExtreme =
false;
1105 for (
int i = 0; i < size; ++i)
1108 if (facet.
Intersect(p, v,
true, dist, distFromSurface, normal))
1120 if (dist >= 0.0 && dist < minDist)
1134 aNormalVector = minNormal;
1135 aConvex = isExtreme;
1142 Normal(p, aNormalVector);
1150 const UVector3& direction,
double& minDist,
UVector3& minNormal,
int& minCandidate )
const
1152 int candidatesCount = candidates.size();
1154 double distFromSurface = 0.0;
1157 for (
int i = 0 ; i < candidatesCount; ++i)
1159 int candidate = candidates[i];
1162 if (facet.
Intersect(aPoint, direction,
true, dist, distFromSurface, normal))
1170 minCandidate = candidate;
1173 if (dist >= 0.0 && dist < minDist)
1177 minCandidate = candidate;
1194 vector<int> curVoxel(3);
1203 int minCandidate = -1;
1210 if ( candidates.size())
1213 if (minDistance <= shift)
break;
1221 while (minDistance > shift);
1223 if (minCandidate < 0)
1228 Normal(aPoint, aNormalVector);
1243 int candidatesCount = candidates.size();
1245 double distFromSurface = 0.0;
1249 for (
int i = 0 ; i < candidatesCount; ++i)
1251 int candidate = candidates[i];
1254 if (facet.
Intersect(aPoint, direction,
false, dist, distFromSurface, normal))
1263 if (distFromSurface >
fgToleranceHalf && dist >= 0.0 && dist < minDistance)
1286 double minDistance, distance;
1295 if (shift) currentPoint += direction * shift;
1300 vector<int> curVoxel(3);
1306 if (candidates.size())
1309 if (minDistance > distance) minDistance = distance;
1310 if (distance < shift)
break;
1314 while (minDistance > shift);
1320 minDistance = distanceToInNoVoxels;
1336 const std::pair<int, double>& r)
1338 return l.second < r.second;
1353 vector<pair<int, double> > voxelsSorted(size);
1355 pair<int, double> info;
1357 for (
int i = 0; i < size; ++i)
1364 info.second = safety;
1365 voxelsSorted[i] = info;
1370 for (
int i = 0; i < size; ++i)
1372 const pair<int, double>& inf = voxelsSorted[i];
1374 double dist = inf.second;
1375 if (dist > minDist)
break;
1378 int csize = candidates.size();
1379 for (
int j = 0; j < csize; ++j)
1381 int candidate = candidates[j];
1383 dist = simple ? facet.
Distance(p, minDist) : facet.
Distance(p, minDist,
false);
1401 std::ostringstream message;
1402 int oldprc = message.precision(16) ;
1403 message <<
"Point p is already inside!?" << endl
1404 <<
"Position:" << endl << endl
1405 <<
"p.x() = " << p.
x() /
mm <<
" mm" << endl
1406 <<
"p.y() = " << p.
y() /
mm <<
" mm" << endl
1407 <<
"p.z() = " << p.
z() /
mm <<
" mm" << endl
1409 message.precision(oldprc) ;
1411 UWarning, 1, message.str().c_str());
1423 vector<int> startingVoxel(3);
1442 for (
int i = 0; i < size; ++i)
1445 double dist = facet.
Distance(p, minDist);
1446 if (dist < minDist) minDist = dist;
1464 std::ostringstream message;
1465 int oldprc = message.precision(16) ;
1466 message <<
"Point p is already outside!?" << endl
1467 <<
"Position:" << endl << endl
1468 <<
"p.x() = " << p.
x() /
mm <<
" mm" << endl
1469 <<
"p.y() = " << p.
y() /
mm <<
" mm" << endl
1470 <<
"p.z() = " << p.
z() /
mm <<
" mm" << endl
1472 message.precision(oldprc) ;
1474 UWarning, 1, message.str().c_str());
1492 for (
int i = 0; i < size; ++i)
1496 if (dist < minDist) minDist = dist;
1520 os <<
"Number of facets = " <<
fFacets.size() << endl;
1523 for (
int i = 0; i < size; ++i)
1525 os <<
"FACET # = " << i + 1 << endl;
1600 for (
int i = 0; i < size; ++i)
1615 return fFacets[i]->GetPointOnFace();
1630 fRandir[0] =
UVector3(-0.9577428892113370, 0.2732676269591740, 0.0897405271949221);
1631 fRandir[1] =
UVector3(-0.8331264504940770, -0.5162067214954600, -0.1985722492445700);
1632 fRandir[2] =
UVector3(-0.1516671651108820, 0.9666292616127460, 0.2064580868390110);
1633 fRandir[3] =
UVector3(0.6570250350323190, -0.6944539025883300, 0.2933460081893360);
1634 fRandir[4] =
UVector3(-0.4820456281280320, -0.6331060000098690, -0.6056474264406270);
1635 fRandir[5] =
UVector3(0.7629032554236800 , 0.1016854697539910, -0.6384658864065180);
1636 fRandir[6] =
UVector3(0.7689540409061150, 0.5034929891988220, 0.3939600142169160);
1637 fRandir[7] =
UVector3(0.5765188359255740, 0.5997271636278330, -0.5549354566343150);
1638 fRandir[8] =
UVector3(0.6660632777862070, -0.6362809868288380, 0.3892379937580790);
1639 fRandir[9] =
UVector3(0.3824415020414780, 0.6541792713761380, -0.6525243125110690);
1640 fRandir[10] =
UVector3(-0.5107726564526760, 0.6020905056811610, 0.6136760679616570);
1641 fRandir[11] =
UVector3(0.7459135439578050, 0.6618796061649330, 0.0743530220183488);
1642 fRandir[12] =
UVector3(0.1536405855311580, 0.8117477913978260, -0.5634359711967240);
1643 fRandir[13] =
UVector3(0.0744395301705579, -0.8707110101772920, -0.4861286795736560);
1644 fRandir[14] =
UVector3(-0.1665874645185400, 0.6018553940549240, -0.7810369397872780);
1645 fRandir[15] =
UVector3(0.7766902003633100, 0.6014617505959970, -0.1870724331097450);
1646 fRandir[16] =
UVector3(-0.8710128685847430, -0.1434320216603030, -0.4698551243971010);
1647 fRandir[17] =
UVector3(0.8901082092766820, -0.4388411398893870, 0.1229871120030100);
1648 fRandir[18] =
UVector3(-0.6430417431544370, -0.3295938228697690, 0.6912779675984150);
1649 fRandir[19] =
UVector3(0.6331124368380410, 0.6306211461665000, 0.4488714875425340);
1660 int base =
sizeof(*this);
1665 for (
int i = 0; i < limit; ++i)
1671 std::set<VUFacet*>::const_iterator beg, end, it;
1674 for (it = beg; it != end; it++)
1689 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