Changeset 1030 for cpp/frams/genetics/fS/part_distance_estimator.h
- Timestamp:
- 11/26/20 01:30:40 (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/genetics/fS/part_distance_estimator.h
r1017 r1030 8 8 #include "frams/model/geometry/meshbuilder.h" 9 9 10 class fS_Utils10 class PartDistanceEstimator 11 11 { 12 12 public: 13 static void rotateVector(Pt3D &vector, const Pt3D &rotation) 13 14 static Part *buildTemporaryPart(Part::Shape shape, const Pt3D &scale, const Pt3D &rotation) 14 15 { 15 Orient rotmatrix = Orient_1; 16 rotmatrix.rotate(rotation); 17 vector = rotmatrix.transform(vector); 16 Part *tmpPart1 = new Part(shape); 17 tmpPart1->scale = scale; 18 tmpPart1->setRot(rotation); 19 return tmpPart1; 18 20 } 19 21 20 static double avg(double a, double b) 21 { 22 return 0.5 * (a + b); 23 } 24 25 static double min3(const Pt3D &p) 26 { 27 double tmp = p.x; 28 if (p.y < tmp) 29 tmp = p.y; 30 if (p.z < tmp) 31 tmp = p.z; 32 return tmp; 33 } 34 35 static double max3(const Pt3D &p) 36 { 37 double tmp = p.x; 38 if (p.y > tmp) 39 tmp = p.y; 40 if (p.z > tmp) 41 tmp = p.z; 42 return tmp; 43 } 44 }; 45 46 class PartDistanceEstimator 47 { 48 49 public: 50 static constexpr double PRECISION = 0.05; 51 static constexpr double RELATIVE_DENSITY = 5.0; 52 53 54 static Part *buildTemporaryPart(Part::Shape shape, const Pt3D &scale, const Pt3D &rotations) 55 { 56 Part *tmpPart = new Part(shape); 57 tmpPart->scale = scale; 58 tmpPart->setRot(rotations); 59 return tmpPart; 60 } 61 62 static vector <Pt3D> findSphereCenters(Part *part) 22 /// Get some of the points from the surface of the part 23 static vector <Pt3D> findSurfacePoints(Part *part, double relativeDensity) 63 24 { 64 25 // Divide by maximal radius to avoid long computations 65 MeshBuilder::PartSurface surface( RELATIVE_DENSITY / fS_Utils::max3(part->scale));26 MeshBuilder::PartSurface surface(relativeDensity / part->scale.maxComponentValue()); 66 27 surface.initialize(part); 67 28 68 vector <Pt3D> centers;29 vector <Pt3D> points; 69 30 Pt3D point; 70 31 while (surface.tryGetNext(point)) 71 32 { 72 centers.push_back(point);33 points.push_back(point); 73 34 } 74 return centers;35 return points; 75 36 } 76 37 77 static bool isCollision(Part *parentPart, vector <Pt3D> ¢ers, Pt3D &vectorBetweenParts) 38 /// Check if there is a collision between the parts 39 static bool isCollision(Part *part, vector <Pt3D> &points, Pt3D &vectorBetweenParts) 78 40 { 79 41 static double CBRT_3 = std::cbrt(3); 80 double maxPar entReachSq = pow(CBRT_3 * fS_Utils::max3(parentPart->scale), 2);81 for (int i = 0; i < int( centers.size()); i++)42 double maxPartReachSq = pow(CBRT_3 * part->scale.maxComponentValue(), 2); 43 for (int i = 0; i < int(points.size()); i++) 82 44 { 83 Pt3D shifted = centers[i] + vectorBetweenParts;84 double distanceTo CenterSq = shifted.x * shifted.x + shifted.y * shifted.y + shifted.z * shifted.z;85 if (distanceTo CenterSq <= maxParentReachSq && GeometryUtils::isPointInsidePart(shifted, parentPart))45 Pt3D shifted = points[i] + vectorBetweenParts; 46 double distanceToPointSq = shifted.x * shifted.x + shifted.y * shifted.y + shifted.z * shifted.z; 47 if (distanceToPointSq <= maxPartReachSq && GeometryUtils::isPointInsidePart(shifted, part)) 86 48 return true; 87 49 } 88 50 return false; 89 51 } 52 53 54 static double calculateDistance(Part tmpPart1, Part tmpPart2, double distanceTolerance, double relativeDensity) 55 { 56 /// tmpPart1 and tmpPart2 are copied for purpose and should not be passed as reference 57 /// This function can change some of the properties of those parts 58 Pt3D directionVersor = tmpPart1.p - tmpPart2.p; 59 directionVersor.normalize(); 60 61 tmpPart1.p = Pt3D(0); 62 tmpPart2.p = Pt3D(0); 63 64 static double CBRT_3 = std::cbrt(3); 65 vector <Pt3D> points = PartDistanceEstimator::findSurfacePoints(&tmpPart1, relativeDensity); 66 67 double minDistance = tmpPart2.scale.minComponentValue() + tmpPart1.scale.minComponentValue(); 68 double maxDistance = CBRT_3 * (tmpPart2.scale.maxComponentValue() + tmpPart1.scale.maxComponentValue()); 69 double currentDistance = 0.5 * (maxDistance + minDistance); 70 int collisionDetected = false; 71 while (maxDistance - minDistance > distanceTolerance) 72 { 73 Pt3D vectorBetweenParts = directionVersor * currentDistance; 74 collisionDetected = PartDistanceEstimator::isCollision(&tmpPart2, points, vectorBetweenParts); 75 76 if (collisionDetected) 77 { 78 minDistance = currentDistance; 79 currentDistance = 0.5 * (maxDistance + currentDistance); 80 } else 81 { 82 maxDistance = currentDistance; 83 currentDistance = 0.5 * (currentDistance + minDistance); 84 } 85 } 86 return currentDistance; 87 } 90 88 }; 91 89 92 double Node::getDistance()93 {94 Pt3D size;95 calculateSize(size);96 Pt3D parentSize;97 parent->calculateSize(parentSize); // Here we are sure that parent is not nullptr98 Part *tmpPart = PartDistanceEstimator::buildTemporaryPart(partType, size, getRotation());99 Part *parentTmpPart = PartDistanceEstimator::buildTemporaryPart(parent->partType, parentSize, parent->getRotation());100 101 vector <Pt3D> centers = PartDistanceEstimator::findSphereCenters(tmpPart);102 103 double minDistance = 0.0;104 double maxDistance = 2 * (fS_Utils::max3(parentSize) + fS_Utils::max3(size));105 double currentDistance = fS_Utils::avg(maxDistance, minDistance);106 int collisionDetected = false;107 while (maxDistance - minDistance > PartDistanceEstimator::PRECISION)108 {109 Pt3D vectorBetweenParts = state->v * currentDistance;110 collisionDetected = PartDistanceEstimator::isCollision(parentTmpPart, centers, vectorBetweenParts);111 112 if (collisionDetected)113 {114 minDistance = currentDistance;115 currentDistance = fS_Utils::avg(maxDistance, currentDistance);116 } else117 {118 maxDistance = currentDistance;119 currentDistance = fS_Utils::avg(currentDistance, minDistance);120 }121 }122 delete tmpPart;123 delete parentTmpPart;124 return currentDistance;125 }126 90 127 91 #endif //_PART_DISTANCE_ESTIMATOR_H_
Note: See TracChangeset
for help on using the changeset viewer.