Ignore:
Timestamp:
11/26/20 01:30:40 (2 years ago)
Author:
Maciej Komosinski
Message:

fS: refactoring

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/genetics/fS/part_distance_estimator.h

    r1017 r1030  
    88#include "frams/model/geometry/meshbuilder.h"
    99
    10 class fS_Utils
     10class PartDistanceEstimator
    1111{
    1212public:
    13         static void rotateVector(Pt3D &vector, const Pt3D &rotation)
     13
     14        static Part *buildTemporaryPart(Part::Shape shape, const Pt3D &scale, const Pt3D &rotation)
    1415        {
    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;
    1820        }
    1921
    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)
    6324        {
    6425                // 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());
    6627                surface.initialize(part);
    6728
    68                 vector <Pt3D> centers;
     29                vector <Pt3D> points;
    6930                Pt3D point;
    7031                while (surface.tryGetNext(point))
    7132                {
    72                         centers.push_back(point);
     33                        points.push_back(point);
    7334                }
    74                 return centers;
     35                return points;
    7536        }
    7637
    77         static bool isCollision(Part *parentPart, vector <Pt3D> &centers, Pt3D &vectorBetweenParts)
     38        /// Check if there is a collision between the parts
     39        static bool isCollision(Part *part, vector <Pt3D> &points, Pt3D &vectorBetweenParts)
    7840        {
    7941                static double CBRT_3 = std::cbrt(3);
    80                 double maxParentReachSq = 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++)
    8244                {
    83                         Pt3D shifted = centers[i] + vectorBetweenParts;
    84                         double distanceToCenterSq = shifted.x * shifted.x + shifted.y * shifted.y + shifted.z * shifted.z;
    85                         if (distanceToCenterSq <= 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))
    8648                                return true;
    8749                }
    8850                return false;
    8951        }
     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        }
    9088};
    9189
    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 nullptr
    98         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                 } else
    117                 {
    118                         maxDistance = currentDistance;
    119                         currentDistance = fS_Utils::avg(currentDistance, minDistance);
    120                 }
    121         }
    122         delete tmpPart;
    123         delete parentTmpPart;
    124         return currentDistance;
    125 }
    12690
    12791#endif //_PART_DISTANCE_ESTIMATOR_H_
Note: See TracChangeset for help on using the changeset viewer.