Changeset 1030 for cpp/frams/genetics


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

fS: refactoring

Location:
cpp/frams/genetics/fS
Files:
6 edited

Legend:

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

    r1017 r1030  
    1717        GenoConv_fS0s() : GenoConverter()
    1818        {
    19                 name = "Solid encoding";
     19                name = "Solids tree-structure encoding";
    2020
    2121                in_format = "S";
  • cpp/frams/genetics/fS/fS_general.cpp

    r1017 r1030  
    1515
    1616int fS_Genotype::precision = 4;
    17 bool fS_Genotype::TURN_WITH_ROTATION = false;
    1817std::map<string, double> Node::minValues;
    1918std::map<string, double> Node::defaultValues;
     
    3332                                {RY,        -M_PI},
    3433                                {RZ,        -M_PI},
    35                                 {SIZE,      0.01},
    36                                 {SIZE_X,    Model::getMinPart().scale.x},
    37                                 {SIZE_Y,    Model::getMinPart().scale.y},
    38                                 {SIZE_Z,    Model::getMinPart().scale.z}
     34                                {SCALE,      0.01},
     35                                {SCALE_X,    Model::getMinPart().scale.x},
     36                                {SCALE_Y,    Model::getMinPart().scale.y},
     37                                {SCALE_Z,    Model::getMinPart().scale.z}
    3938                };
    4039        }
     
    5150                                {RY,        M_PI},
    5251                                {RZ,        M_PI},
    53                                 {SIZE,      100.0},
    54                                 {SIZE_X,    Model::getMaxPart().scale.x},
    55                                 {SIZE_Y,    Model::getMaxPart().scale.y},
    56                                 {SIZE_Z,    Model::getMaxPart().scale.z}
     52                                {SCALE,      100.0},
     53                                {SCALE_X,    Model::getMaxPart().scale.x},
     54                                {SCALE_Y,    Model::getMaxPart().scale.y},
     55                                {SCALE_Z,    Model::getMaxPart().scale.z}
    5756                };
    5857        }
     
    6867                                {RY,        0.0},
    6968                                {RZ,        0.0},
    70                                 {SIZE,      1.0},
    71                                 {SIZE_X,    Model::getDefPart().scale.x},
    72                                 {SIZE_Y,    Model::getDefPart().scale.y},
    73                                 {SIZE_Z,    Model::getDefPart().scale.z}
     69                                {SCALE,      1.0},
     70                                {SCALE_X,    Model::getDefPart().scale.x},
     71                                {SCALE_Y,    Model::getDefPart().scale.y},
     72                                {SCALE_Z,    Model::getDefPart().scale.z}
    7473                };
    7574        }
     
    111110}
    112111
     112void rotateVector(Pt3D &vector, const Pt3D &rotation)
     113{
     114        Orient rotmatrix = Orient_1;
     115        rotmatrix.rotate(rotation);
     116        vector = rotmatrix.transform(vector);
     117}
     118
    113119void State::rotate(const Pt3D &rotation)
    114120{
    115        fS_Utils::rotateVector(v, rotation);
     121       rotateVector(v, rotation);
    116122       v.normalize();
    117123}
     
    218224void Node::extractModifiers(Substring &restOfGenotype)
    219225{
    220         int partTypePosition = getPartPosition(restOfGenotype);
    221         if (partTypePosition == -1)
     226        int partShapePosition = getPartPosition(restOfGenotype);
     227        if (partShapePosition == -1)
    222228                throw fS_Exception("Part type missing", restOfGenotype.start);
    223229
    224         for (int i = 0; i < partTypePosition; i++)
     230        for (int i = 0; i < partShapePosition; i++)
    225231        {
    226232                // Extract modifiers and joint
     
    233239                        throw fS_Exception("Invalid modifier", restOfGenotype.start + i);
    234240        }
    235         restOfGenotype.startFrom(partTypePosition);
     241        restOfGenotype.startFrom(partShapePosition);
    236242}
    237243
     
    242248                throw fS_Exception("Invalid part type", restOfGenotype.start);
    243249
    244         partType = itr->second;
     250        partShape = itr->second;
    245251        restOfGenotype.startFrom(1);
    246252}
     
    327333                size_t len = length - valueStartIndex;
    328334                double value = fS_stod(val, restOfGenotype.start + start + valueStartIndex, &len);
    329                 if((key==SIZE_X || key==SIZE_Y || key==SIZE_Z) && value <= 0.0)
     335                if((key==SCALE_X || key==SCALE_Y || key==SCALE_Z) && value <= 0.0)
    330336                        throw fS_Exception("Invalid value of radius parameter", restOfGenotype.start + start + valueStartIndex);
    331337
     
    342348        if (item != params.end())
    343349                return item->second;
    344         return defaultValues.at(key);
     350
     351        auto defaultItem = defaultValues.find(key);
     352        if(defaultItem == defaultValues.end())
     353                throw fS_Exception("Default value missing", 0);
     354        return defaultItem->second;
    345355}
    346356
     
    382392                state->rotate(getVectorRotation());
    383393
    384                 double distance = getDistance();
     394                double distance = calculateDistanceFromParent();
    385395                state->addVector(distance);
    386396        }
     
    433443}
    434444
    435 void Node::calculateSize(Pt3D &scale)
    436 {
    437         double sizeMultiplier = getParam(SIZE) * state->s;
    438         scale.x = getParam(SIZE_X) * sizeMultiplier;
    439         scale.y = getParam(SIZE_Y) * sizeMultiplier;
    440         scale.z = getParam(SIZE_Z) * sizeMultiplier;
     445void Node::calculateScale(Pt3D &scale)
     446{
     447        double scaleMultiplier = getParam(SCALE) * state->s;
     448        scale.x = getParam(SCALE_X) * scaleMultiplier;
     449        scale.y = getParam(SCALE_Y) * scaleMultiplier;
     450        scale.z = getParam(SCALE_Z) * scaleMultiplier;
    441451}
    442452
     
    444454{
    445455        double result;
    446         Pt3D size;
    447         calculateSize(size);
    448         double radiiProduct = size.x * size.y * size.z;
    449         switch (partType)
     456        Pt3D scale;
     457        calculateScale(scale);
     458        double radiiProduct = scale.x * scale.y * scale.z;
     459        switch (partShape)
    450460        {
    451461                case Part::Shape::SHAPE_CUBOID:
     
    464474}
    465475
    466 bool Node::isPartSizeValid()
    467 {
    468         Pt3D size;
    469         calculateSize(size);
     476bool Node::isPartScaleValid()
     477{
     478        Pt3D scale;
     479        calculateScale(scale);
    470480        double volume = calculateVolume();
    471481        Part_MinMaxDef minP = Model::getMinPart();
     
    474484        if (volume > maxP.volume || minP.volume > volume)
    475485                return false;
    476         if (size.x < minP.scale.x || size.y < minP.scale.y || size.z < minP.scale.z)
     486        if (scale.x < minP.scale.x || scale.y < minP.scale.y || scale.z < minP.scale.z)
    477487                return false;
    478         if (size.x > maxP.scale.x || size.y > maxP.scale.y || size.z > maxP.scale.z)
     488        if (scale.x > maxP.scale.x || scale.y > maxP.scale.y || scale.z > maxP.scale.z)
    479489                return false;
    480490
    481         if (partType == Part::Shape::SHAPE_ELLIPSOID && fS_Utils::max3(size) != fS_Utils::min3(size))
     491        if (partShape == Part::Shape::SHAPE_ELLIPSOID && scale.maxComponentValue() != scale.minComponentValue())
    482492                // When not all radii have different values
    483493                return false;
    484         if (partType == Part::Shape::SHAPE_CYLINDER && size.y != size.z)
     494        if (partShape == Part::Shape::SHAPE_CYLINDER && scale.y != scale.z)
    485495                // If base radii have different values
    486496                return false;
     
    488498}
    489499
    490 bool Node::hasPartSizeParam()
    491 {
    492         return params.count(SIZE_X) > 0 || params.count(SIZE_Y) > 0 || params.count(SIZE_Z) > 0;
    493 }
    494 
    495500Pt3D Node::getVectorRotation()
    496501{
     
    501506{
    502507        Pt3D rotation = Pt3D(getParam(RX, 0.0), getParam(RY, 0.0), getParam(RZ, 0.0));
    503         if(fS_Genotype::TURN_WITH_ROTATION)
     508        if(genotypeParams.turnWithRotation)
    504509                rotation += getVectorRotation();
    505510        return rotation;
     
    537542void Node::createPart()
    538543{
    539         part = new Part(partType);
     544        part = new Part(partShape);
    540545        part->p = Pt3D(state->location);
    541546
    542547        part->friction = getParam(FRICTION) * state->fr;
    543548        part->ingest = getParam(INGESTION) * state->ing;
    544         calculateSize(part->scale);
     549        calculateScale(part->scale);
    545550        part->setRot(getRotation());
    546551}
     
    581586                result += std::string(count, mod).c_str();
    582587        }
    583         result += SHAPE_TO_GENE.at(partType);
     588        result += SHAPE_TO_GENE.at(partShape);
    584589
    585590        if (!neurons.empty())
     
    658663}
    659664
    660 fS_Genotype::fS_Genotype(const string &geno)
    661 {
     665fS_Genotype::fS_Genotype(const string &g)
     666{
     667        string geno(g);
     668        geno.erase(remove(geno.begin(), geno.end(), ' '), geno.end());
     669        geno.erase(remove(geno.begin(), geno.end(), '\n'), geno.end());
    662670        try
    663671        {
    664672                GenotypeParams genotypeParams;
    665673                genotypeParams.modifierMultiplier = 1.1;
     674                genotypeParams.distanceTolerance = 0.1;
     675                genotypeParams.relativeDensity = 10.0;
     676                genotypeParams.turnWithRotation = false;
     677                genotypeParams.paramMutationStrength = 0.4;
    666678
    667679                size_t modeSeparatorIndex = geno.find(MODE_SEPARATOR);
     
    669681                        throw fS_Exception("Genotype parameters missing", 0);
    670682
    671                 genotypeParams.modifierMultiplier = fS_stod(geno, 0, &modeSeparatorIndex);
     683                std::vector<SString> paramStrings;
     684                strSplit(SString(geno.c_str(), modeSeparatorIndex), ',', false, paramStrings);
     685
     686                if(paramStrings.size() >= 1 && paramStrings[0] != "")
     687                {
     688                        size_t len0 = paramStrings[0].length();
     689                        genotypeParams.modifierMultiplier = fS_stod(paramStrings[0].c_str(), 0, &len0);
     690                }
     691                if(paramStrings.size() >= 2 && paramStrings[1] != "")
     692                {
     693                        genotypeParams.turnWithRotation = bool(atoi(paramStrings[1].c_str()));
     694                }
     695                if(paramStrings.size() >= 3 && paramStrings[2] != "")
     696                {
     697                        size_t len2 = paramStrings[2].length();
     698                        genotypeParams.paramMutationStrength = fS_stod(paramStrings[2].c_str(), 0, &len2);
     699                }
    672700
    673701                int genoStart = modeSeparatorIndex + 1;
     
    680708                delete startNode;
    681709                throw e;
     710        }
     711        catch(...)
     712        {
     713                delete startNode;
     714                throw fS_Exception("Unknown exception in fS", 0);
    682715        }
    683716}
     
    753786        geno.reserve(100);
    754787
    755         geno += doubleToString(startNode->genotypeParams.modifierMultiplier, fS_Genotype::precision).c_str();
     788        GenotypeParams gp = startNode->genotypeParams;
     789        geno += doubleToString(gp.modifierMultiplier, precision).c_str();
     790        geno += ",";
     791        geno += doubleToString(gp.turnWithRotation, precision).c_str();
     792        geno += ",";
     793        geno += doubleToString(gp.paramMutationStrength, precision).c_str();
    756794        geno += MODE_SEPARATOR;
    757795
     
    850888        for (int i = 0; i < int(nodes.size()); i++)
    851889        {
    852                 if (!nodes[i]->isPartSizeValid())
     890                if (!nodes[i]->isPartScaleValid())
    853891                {
    854892                        return 1 + nodes[i]->partDescription->start;
     
    884922}
    885923
     924double Node::calculateDistanceFromParent()
     925{
     926        Pt3D scale;
     927        calculateScale(scale);
     928        Pt3D parentScale;
     929        parent->calculateScale(parentScale);    // Here we are sure that parent is not nullptr
     930        Part *tmpPart = PartDistanceEstimator::buildTemporaryPart(partShape, scale, getRotation());
     931        Part *parentTmpPart = PartDistanceEstimator::buildTemporaryPart(parent->partShape, parentScale, parent->getRotation());
     932
     933        double result;
     934        try
     935        {
     936                tmpPart->p = state->v;
     937                result = PartDistanceEstimator::calculateDistance(*tmpPart, *parentTmpPart, genotypeParams.distanceTolerance, genotypeParams.relativeDensity);
     938        }
     939        catch (...)
     940        {
     941                throw fS_Exception("Exception thrown while calculating distance from parent", 0);
     942        }
     943
     944        delete tmpPart;
     945        delete parentTmpPart;
     946        return result;
     947}
  • cpp/frams/genetics/fS/fS_general.h

    r1017 r1030  
    4343#define FRICTION "f"
    4444#define STIFFNESS "st"
    45 #define SIZE "s"
    46 #define SIZE_X "x"
    47 #define SIZE_Y "y"
    48 #define SIZE_Z "z"
     45#define SCALE "s"
     46#define SCALE_X "x"
     47#define SCALE_Y "y"
     48#define SCALE_Z "z"
    4949#define ROT_X "tx"
    5050#define ROT_Y "ty"
     
    8383const int JOINT_COUNT = JOINTS.length();
    8484const string MODIFIERS = "IFS";
    85 const char SIZE_MODIFIER = 's';
    86 const vector<string> PARAMS {INGESTION, FRICTION, ROT_X, ROT_Y, ROT_Z, RX, RY, RZ, SIZE, SIZE_X, SIZE_Y, SIZE_Z};
    87 const vector<string> SIZE_PARAMS {SIZE, SIZE_X, SIZE_Y, SIZE_Z};
     85const char SCALE_MODIFIER = 's';
     86const vector<string> PARAMS {INGESTION, FRICTION, ROT_X, ROT_Y, ROT_Z, RX, RY, RZ, SCALE, SCALE_X, SCALE_Y, SCALE_Z};
     87const vector<string> SCALE_PARAMS {SCALE, SCALE_X, SCALE_Y, SCALE_Z};
    8888
    8989/** @name Default values of node parameters*/
     
    247247struct GenotypeParams{
    248248        double modifierMultiplier;      // Every modifier changes the underlying value by this multiplier
     249        /// When calculating the distance between parts, the internal result is a range of numbers
     250        /// distanceTolerance is the maximal allowed size of this range
     251        double distanceTolerance;
     252        /// Used for deriving density for MeshBuilder
     253        double relativeDensity;
     254        ///
     255        bool turnWithRotation;
     256        ///
     257        double paramMutationStrength;
    249258};
    250259
     
    265274        Part *part;     /// A part object built from node. Used in building the Model
    266275        int partCodeLen; /// The length of substring that directly describes the corresponding part
    267         GenotypeParams genotypeParams;
     276        static std::map<string, double> minValues;      /// Min parameter values
     277        static std::map<string, double> defaultValues;  /// Default parameter values
     278        static std::map<string, double> maxValues;      /// Max parameter values
    268279
    269280        vector<Node *> children;    /// Vector of all direct children
     
    273284        void prepareParams();
    274285
    275         double getDistance();
    276 
    277286        void cleanUp();
    278287
     288        /// Get part's  rotation
    279289        Pt3D getRotation();
    280290
     291        /// Get the rotation of vector
    281292        Pt3D getVectorRotation();
    282293
    283         bool isPartSizeValid();
    284 
    285         bool hasPartSizeParam();
     294        bool isPartScaleValid();
    286295
    287296        /**
     
    362371
    363372public:
    364         static std::map<string, double> minValues;
    365         static std::map<string, double> defaultValues;
    366         static std::map<string, double> maxValues;
    367373        char joint = DEFAULT_JOINT;           /// Set of all joints
    368         Part::Shape partType;  /// The type of the part
     374        Part::Shape partShape;  /// The type of the part
    369375        State *state = nullptr; /// The phenotypic state that inherits from ancestors
    370376        std::map<string, double> params; /// The map of all the node params
     377        GenotypeParams genotypeParams; /// Parameters that affect the whole genotype
    371378
    372379        Node(Substring &genotype, Node *parent, GenotypeParams genotypeParams);
     
    381388
    382389        /**
    383          * Calculate the effective size of the part (after applying all multipliers and params)
    384          * @return The effective size
    385          */
    386         void calculateSize(Pt3D &scale);
     390         * Calculate the effective scale of the part (after applying all multipliers and params)
     391         * @return The effective scales
     392         */
     393        void calculateScale(Pt3D &scale);
    387394
    388395        /**
     
    404411        double getParam(const string &key);
    405412        double getParam(const string &key, double defaultValue);
     413
     414        /// Calculate distance between the part its parent
     415        double calculateDistanceFromParent();
    406416};
    407417
     
    439449
    440450
    441         static int precision;
    442         static bool TURN_WITH_ROTATION;
     451        static int precision; /// Number of decimal places for numbers in genotype
    443452
    444453        /**
     
    450459        ~fS_Genotype();
    451460
     461        /// Calculate the State field for all the nodes
    452462        void getState(bool calculateLocation);
    453463
     
    495505
    496506        /**
    497          * Check if sizes of all parts in genotype are valid
     507         * Check if scales of all parts in genotype are valid
    498508        \retval error_position 1-based
    499509        \retval 0 when all part sizes are valid
  • cpp/frams/genetics/fS/fS_oper.cpp

    r1017 r1030  
    5151                if (errorPosition != 0)
    5252                {
    53                         logPrintf("GenoOper_fS", "checkValidity", LOG_WARN, "Invalid part size");
     53                        logPrintf("GenoOper_fS", "checkValidity", LOG_WARN, "Invalid part scale");
    5454                        return errorPosition;
    5555                }
     
    226226const char *GenoOper_fS::getSimplest()
    227227{
    228         return "1.1:C{x=0.80599;y=0.80599;z=0.80599}";
     228        return "1.1,0,0.4:C{x=0.80599;y=0.80599;z=0.80599}";
    229229}
    230230
     
    297297        geno.getState(false);
    298298        Node *node = geno.chooseNode();
    299         char partType = SHAPE_TO_GENE.at(availablePartShapes[rndUint(availablePartShapes.size())]);
    300 
    301         Substring substring(&partType, 0, 1);
     299        char partShape = SHAPE_TO_GENE.at(availablePartShapes[rndUint(availablePartShapes.size())]);
     300
     301        Substring substring(&partShape, 0, 1);
    302302        Node *newNode = new Node(substring, node, node->genotypeParams);
    303303        // Add random rotation
     
    322322                newNode->params[selectedParam] = RndGen.Uni(-M_PI / 2, M_PI / 2);
    323323        }
    324         // Assign part size to default value
    325         double volumeMultiplier = pow(node->getParam(SIZE) * node->state->s, 3);
     324        // Assign part scale to default value
     325        double volumeMultiplier = pow(node->getParam(SCALE) * node->state->s, 3);
    326326        double minVolume = Model::getMinPart().volume;
    327327        double defVolume = Model::getDefPart().volume * volumeMultiplier;    // Default value after applying modifiers
     
    330330        double relativeVolume = volume / volumeMultiplier;    // Volume without applying modifiers
    331331
    332         double newRadius = std::cbrt(relativeVolume / volumeMultipliers.at(newNode->partType));
    333         newNode->params[SIZE_X] = newRadius;
    334         newNode->params[SIZE_Y] = newRadius;
    335         newNode->params[SIZE_Z] = newRadius;
     332        double newRadius = std::cbrt(relativeVolume / volumeMultipliers.at(newNode->partShape));
     333        newNode->params[SCALE_X] = newRadius;
     334        newNode->params[SCALE_Y] = newRadius;
     335        newNode->params[SCALE_Z] = newRadius;
    336336        node->children.push_back(newNode);
    337337
     
    339339        {
    340340                geno.getState(false);
    341                 mutateSizeParam(newNode, SIZE_X, true);
    342                 mutateSizeParam(newNode, SIZE_Y, true);
    343                 mutateSizeParam(newNode, SIZE_Z, true);
     341                mutateScaleParam(newNode, SCALE_X, true);
     342                mutateScaleParam(newNode, SCALE_Y, true);
     343                mutateScaleParam(newNode, SCALE_Z, true);
    344344        }
    345345        return true;
     
    350350        Node *randomNode, *selectedChild;
    351351        // Choose a parent with children
    352         // It may be difficult to choose a eligible node, so the number of tries should be high
     352        // It may be difficult to choose an eligible node, so the number of tries should be high
    353353        for (int i = 0; i < 10 * mutationTries; i++)
    354354        {
     
    380380                Node *randomNode = geno.chooseNode();
    381381                int index = rndUint(availShapesLen);
    382                 if (availablePartShapes[index] == randomNode->partType)
     382                if (availablePartShapes[index] == randomNode->partShape)
    383383                        index = (index + 1 + rndUint(availShapesLen - 1)) % availShapesLen;
    384384                Part::Shape newType = availablePartShapes[index];
    385385
    386386#ifdef _DEBUG
    387                 if(newType == randomNode->partType)
     387                if(newType == randomNode->partShape)
    388388                        throw fS_Exception("Internal error: invalid part type chosen in mutation.", 1);
    389389#endif
    390390
    391391                geno.getState(false);
    392                 double sizeMultiplier = randomNode->getParam(SIZE) * randomNode->state->s;
    393                 double relativeVolume = randomNode->calculateVolume() / pow(sizeMultiplier, 3.0);
    394 
    395                 if (!ensureCircleSection || newType == Part::Shape::SHAPE_CUBOID || (randomNode->partType == Part::Shape::SHAPE_ELLIPSOID && newType == Part::Shape::SHAPE_CYLINDER))
    396                 {
    397                         double radiusQuotient = std::cbrt(volumeMultipliers.at(randomNode->partType) / volumeMultipliers.at(newType));
    398                         randomNode->params[SIZE_X] = randomNode->getParam(SIZE_X) * radiusQuotient;
    399                         randomNode->params[SIZE_Y] = randomNode->getParam(SIZE_Y) * radiusQuotient;
    400                         randomNode->params[SIZE_Z] = randomNode->getParam(SIZE_Z) * radiusQuotient;
    401                 } else if (randomNode->partType == Part::Shape::SHAPE_CUBOID && newType == Part::Shape::SHAPE_CYLINDER)
    402                 {
    403                         double newRadius = 0.5 * (randomNode->getParam(SIZE_X) + randomNode->getParam(SIZE_Y));
    404                         randomNode->params[SIZE_X] = 0.5 * relativeVolume / (M_PI * newRadius * newRadius);
    405                         randomNode->params[SIZE_Y] = newRadius;
    406                         randomNode->params[SIZE_Z] = newRadius;
     392                double scaleMultiplier = randomNode->getParam(SCALE) * randomNode->state->s;
     393                double relativeVolume = randomNode->calculateVolume() / pow(scaleMultiplier, 3.0);
     394
     395                if (!ensureCircleSection || newType == Part::Shape::SHAPE_CUBOID || (randomNode->partShape == Part::Shape::SHAPE_ELLIPSOID && newType == Part::Shape::SHAPE_CYLINDER))
     396                {
     397                        double radiusQuotient = std::cbrt(volumeMultipliers.at(randomNode->partShape) / volumeMultipliers.at(newType));
     398                        randomNode->params[SCALE_X] = randomNode->getParam(SCALE_X) * radiusQuotient;
     399                        randomNode->params[SCALE_Y] = randomNode->getParam(SCALE_Y) * radiusQuotient;
     400                        randomNode->params[SCALE_Z] = randomNode->getParam(SCALE_Z) * radiusQuotient;
     401                } else if (randomNode->partShape == Part::Shape::SHAPE_CUBOID && newType == Part::Shape::SHAPE_CYLINDER)
     402                {
     403                        double newRadius = 0.5 * (randomNode->getParam(SCALE_X) + randomNode->getParam(SCALE_Y));
     404                        randomNode->params[SCALE_X] = 0.5 * relativeVolume / (M_PI * newRadius * newRadius);
     405                        randomNode->params[SCALE_Y] = newRadius;
     406                        randomNode->params[SCALE_Z] = newRadius;
    407407                } else if (newType == Part::Shape::SHAPE_ELLIPSOID)
    408408                {
    409409                        double newRelativeRadius = cbrt(relativeVolume / volumeMultipliers.at(newType));
    410                         randomNode->params[SIZE_X] = newRelativeRadius;
    411                         randomNode->params[SIZE_Y] = newRelativeRadius;
    412                         randomNode->params[SIZE_Z] = newRelativeRadius;
     410                        randomNode->params[SCALE_X] = newRelativeRadius;
     411                        randomNode->params[SCALE_Y] = newRelativeRadius;
     412                        randomNode->params[SCALE_Z] = newRelativeRadius;
    413413                } else
    414414                {
    415415                        throw fS_Exception("Invalid part type", 1);
    416416                }
    417                 randomNode->partType = newType;
     417                randomNode->partShape = newType;
    418418                return true;
    419419        }
     
    446446                return false;
    447447        // Do not allow invalid changes in part size
    448         bool isRadiusOfBase = key == SIZE_Y || key == SIZE_Z;
    449         bool isRadius = isRadiusOfBase || key == SIZE_X;
     448        bool isRadiusOfBase = key == SCALE_Y || key == SCALE_Z;
     449        bool isRadius = isRadiusOfBase || key == SCALE_X;
    450450        if (ensureCircleSection && isRadius)
    451451        {
    452                 if (randomNode->partType == Part::Shape::SHAPE_ELLIPSOID)
     452                if (randomNode->partShape == Part::Shape::SHAPE_ELLIPSOID)
    453453                        return false;
    454                 if (randomNode->partType == Part::Shape::SHAPE_CYLINDER && isRadiusOfBase)
     454                if (randomNode->partShape == Part::Shape::SHAPE_CYLINDER && isRadiusOfBase)
    455455                        return false;
    456456        }
     
    490490bool GenoOper_fS::mutateParamValue(Node *node, string key)
    491491{
    492         // Do not allow invalid changes in part size
    493         if (std::find(SIZE_PARAMS.begin(), SIZE_PARAMS.end(), key) == SIZE_PARAMS.end())
    494         {
    495                 node->params[key] = GenoOperators::mutateCreep('f', node->getParam(key), Node::minValues.at(key), Node::maxValues.at(key), true);
     492        // Do not allow invalid changes in part scale
     493        if (std::find(SCALE_PARAMS.begin(), SCALE_PARAMS.end(), key) == SCALE_PARAMS.end())
     494        {
     495                double max = Node::maxValues.at(key);
     496                double min = Node::minValues.at(key);
     497                double stddev = (max - min) * node->genotypeParams.paramMutationStrength;
     498                node->params[key] = GenoOperators::mutateCreep('f', node->getParam(key), min, max, stddev, true);
    496499                return true;
    497500        } else
    498                 return mutateSizeParam(node, key, ensureCircleSection);
     501                return mutateScaleParam(node, key, ensureCircleSection);
    499502}
    500503
     
    524527        randomNode->modifiers[randomModifier] += rndUint(2) == 0 ? 1 : -1;
    525528
    526         bool isSizeMod = tolower(randomModifier) == SIZE_MODIFIER;
     529        bool isSizeMod = tolower(randomModifier) == SCALE_MODIFIER;
    527530        if (isSizeMod && geno.checkValidityOfPartSizes() != 0)
    528531        {
     
    678681}
    679682
    680 bool GenoOper_fS::mutateSizeParam(Node *node, string key, bool ensureCircleSection)
     683bool GenoOper_fS::mutateScaleParam(Node *node, string key, bool ensureCircleSection)
    681684{
    682685        double oldValue = node->getParam(key);
    683686        double volume = node->calculateVolume();
    684687        double valueAtMinVolume, valueAtMaxVolume;
    685         if(key == SIZE)
     688        if(key == SCALE)
    686689        {
    687690                valueAtMinVolume = oldValue * std::cbrt(Model::getMinPart().volume / volume);
     
    696699        double min = std::max(Node::minValues.at(key), valueAtMinVolume);
    697700        double max = std::min(Node::maxValues.at(key), valueAtMaxVolume);
    698 
    699         node->params[key] = GenoOperators::mutateCreep('f', node->getParam(key), min, max, true);
    700 
    701         if (!ensureCircleSection || node->isPartSizeValid())
     701        double stdev = (max - min) * node->genotypeParams.paramMutationStrength;
     702
     703        node->params[key] = GenoOperators::mutateCreep('f', node->getParam(key), min, max, stdev, true);
     704
     705        if (!ensureCircleSection || node->isPartScaleValid())
    702706                return true;
    703707        else
  • cpp/frams/genetics/fS/fS_oper.h

    r1017 r1030  
    142142
    143143        /**
    144          * Change the value of the size parameter by given multiplier
    145          * Do not change the value if any of the size restrictions is not satisfied
     144         * Change the value of the scale parameter by given multiplier
     145         * Do not change the value if any of the scale restrictions is not satisfied
    146146         * @param paramKey
    147147         * @param multiplier
     
    149149         * @return True if the parameter value was change, false otherwise
    150150         */
    151         bool mutateSizeParam(Node *node, string key, bool ensureCircleSection);
     151        bool mutateScaleParam(Node *node, string key, bool ensureCircleSection);
    152152};
    153153
  • 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.