Changeset 1032


Ignore:
Timestamp:
11/27/20 20:54:50 (4 years ago)
Author:
Maciej Komosinski
Message:
  • fS: comma as an intuitive separator in genotype instead of weird symbols ;'
  • other minor refactorizations
Location:
cpp/frams
Files:
7 edited
1 moved

Legend:

Unmodified
Added
Removed
  • cpp/frams/genetics/fS/fS_general.cpp

    r1030 r1032  
    1212#include "../genooperators.h"
    1313#include "common/nonstd_math.h"
    14 #include "part_distance_estimator.h"
     14#include "../../model/geometry/part_distance_estimator.h"
    1515
    1616int fS_Genotype::precision = 4;
     
    8181                return std::stod(str, size);
    8282        }
    83         catch(const std::invalid_argument& ex)
     83        catch(const std::invalid_argument&)
    8484        {
    8585                throw fS_Exception("Invalid numeric value", start);
    8686        }
    87         catch(const std::out_of_range& ex)
     87        catch(const std::out_of_range&)
    8888        {
    8989                throw fS_Exception("Invalid numeric value; out of range", start);
     
    123123}
    124124
     125int findEndOfNeuronParamString(SString neuronDefinition)
     126{
     127        for(int i=1; i< neuronDefinition.size(); i++)
     128        {
     129                if(neuronDefinition[i - 1] == ',' && isdigit(neuronDefinition[i]))
     130                        return i - 1;
     131        }
     132
     133        return neuronDefinition.size();
     134}
    125135
    126136fS_Neuron::fS_Neuron(const char *str, int _start, int length)
     
    131141                return;
    132142
    133         vector<SString> inputStrings;
    134         strSplit(SString(str, length), NEURON_INTERNAL_SEPARATOR, false, inputStrings);
    135         if (inputStrings.empty())
    136                 return;
    137 
    138         int inputStart = 0;
     143        SString neuronDefinition(str, length);
     144        int endOfNeuronParamString = findEndOfNeuronParamString(neuronDefinition);
     145        SString neuronParamString = neuronDefinition.substr(0, endOfNeuronParamString);
     146        SString neuronInputString = neuronDefinition.substr(endOfNeuronParamString + 1);
     147
    139148        SString details = "N";
    140149
    141         SString tmp = inputStrings[0];
     150        SString tmp = neuronParamString;
    142151        if(tmp.indexOf(':') != -1)
    143152                tmp = tmp.substr(0, tmp.indexOf(':'));
     
    145154        if (NeuroLibrary::staticlibrary.findClassIndex(tmp, true) != -1)
    146155        {
    147                 inputStart = 1;
    148                 details = inputStrings[0];
     156                details = neuronParamString;
     157        }
     158        else{
     159                neuronInputString = neuronParamString;
    149160        }
    150161        setDetails(details);
    151162
    152         for (int i = inputStart; i < int(inputStrings.size()); i++)
     163        vector<SString> inputStrings;
     164        strSplit(neuronInputString, NEURON_INTERNAL_SEPARATOR, false, inputStrings);
     165        if (inputStrings.empty() || inputStrings[0] == SString())
     166                return;
     167        for (int i = 0; i < int(inputStrings.size()); i++)
    153168        {
    154169                SString keyValue = inputStrings[i];
     
    421436        char c;
    422437        const char *str = restOfGenotype.c_str();
     438        bool insideSpecifiation = false;        // True when inside parameter or neuron specification
    423439        for (int i = 0; i < restOfGenotype.len; i++)
    424440        {
     
    428444                if (c == BRANCH_START)
    429445                        depth++;
    430                 else if ((c == BRANCH_SEPARATOR && depth == 1) || i + 1 == restOfGenotype.len)
     446                else if (c == PARAM_START || c == NEURON_START)
     447                        insideSpecifiation = true;
     448                else if (c == PARAM_END || c == NEURON_END)
     449                        insideSpecifiation = false;
     450                else if (!insideSpecifiation && ((c == BRANCH_SEPARATOR && depth == 1) || i + 1 == restOfGenotype.len))
    431451                {
    432452                        Substring substring(restOfGenotype);
     
    453473double Node::calculateVolume()
    454474{
    455         double result;
     475        Part *tmpPart = new Part(partShape);
     476        calculateScale(tmpPart->scale);
     477        return GeometryUtils::calculateSolidVolume(tmpPart);
     478}
     479
     480bool Node::isPartScaleValid()
     481{
    456482        Pt3D scale;
    457483        calculateScale(scale);
    458         double radiiProduct = scale.x * scale.y * scale.z;
    459         switch (partShape)
    460         {
    461                 case Part::Shape::SHAPE_CUBOID:
    462                         result = 8.0 * radiiProduct;
    463                         break;
    464                 case Part::Shape::SHAPE_CYLINDER:
    465                         result = 2.0 * M_PI * radiiProduct;
    466                         break;
    467                 case Part::Shape::SHAPE_ELLIPSOID:
    468                         result = (4.0 / 3.0) * M_PI * radiiProduct;
    469                         break;
    470                 default:
    471                         logMessage("fS", "calculateVolume", LOG_ERROR, "Invalid part type");
    472         }
    473         return result;
    474 }
    475 
    476 bool Node::isPartScaleValid()
    477 {
    478         Pt3D scale;
    479         calculateScale(scale);
    480         double volume = calculateVolume();
    481         Part_MinMaxDef minP = Model::getMinPart();
    482         Part_MinMaxDef maxP = Model::getMaxPart();
    483 
    484         if (volume > maxP.volume || minP.volume > volume)
    485                 return false;
    486         if (scale.x < minP.scale.x || scale.y < minP.scale.y || scale.z < minP.scale.z)
    487                 return false;
    488         if (scale.x > maxP.scale.x || scale.y > maxP.scale.y || scale.z > maxP.scale.z)
    489                 return false;
    490 
    491         if (partShape == Part::Shape::SHAPE_ELLIPSOID && scale.maxComponentValue() != scale.minComponentValue())
    492                 // When not all radii have different values
    493                 return false;
    494         if (partShape == Part::Shape::SHAPE_CYLINDER && scale.y != scale.z)
    495                 // If base radii have different values
    496                 return false;
    497         return true;
     484        return GeometryUtils::isSolidPartScaleValid(partShape, scale);
    498485}
    499486
     
    663650}
    664651
    665 fS_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());
     652fS_Genotype::fS_Genotype(const string &geno)
     653{
    670654        try
    671655        {
     
    708692                delete startNode;
    709693                throw e;
    710         }
    711         catch(...)
    712         {
    713                 delete startNode;
    714                 throw fS_Exception("Unknown exception in fS", 0);
    715694        }
    716695}
     
    789768        geno += doubleToString(gp.modifierMultiplier, precision).c_str();
    790769        geno += ",";
    791         geno += doubleToString(gp.turnWithRotation, precision).c_str();
     770        geno += std::to_string(int(gp.turnWithRotation)).c_str();
    792771        geno += ",";
    793772        geno += doubleToString(gp.paramMutationStrength, precision).c_str();
     
    932911
    933912        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         }
     913        tmpPart->p = state->v;
     914        result = PartDistanceEstimator::calculateDistance(*tmpPart, *parentTmpPart, genotypeParams.distanceTolerance, genotypeParams.relativeDensity);
     915
    943916
    944917        delete tmpPart;
  • cpp/frams/genetics/fS/fS_general.h

    r1030 r1032  
    1919#define BRANCH_START '('
    2020#define BRANCH_END ')'
    21 #define BRANCH_SEPARATOR '^'
     21#define BRANCH_SEPARATOR ','
    2222#define PARAM_START '{'
    2323#define PARAM_END '}'
    24 const char PARAM_SEPARATOR = ';';
     24const char PARAM_SEPARATOR = ',';
    2525const char PARAM_KEY_VALUE_SEPARATOR = '=';
    2626#define NEURON_START '['
    2727const char NEURON_END = ']';
    2828const char NEURON_SEPARATOR = ';';
    29 const SString NEURON_INTERNAL_SEPARATOR("'");
     29const SString NEURON_INTERNAL_SEPARATOR(",");
    3030#define NEURON_I_W_SEPARATOR ':'
    3131//@}
     
    274274        Part *part;     /// A part object built from node. Used in building the Model
    275275        int partCodeLen; /// The length of substring that directly describes the corresponding part
     276
    276277        static std::map<string, double> minValues;      /// Min parameter values
    277278        static std::map<string, double> defaultValues;  /// Default parameter values
  • cpp/frams/genetics/fS/fS_oper.cpp

    r1030 r1032  
    226226const char *GenoOper_fS::getSimplest()
    227227{
    228         return "1.1,0,0.4: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
  • cpp/frams/genetics/genooperators.cpp

    r1023 r1032  
    455455        return isupper(firstchar) || firstchar == '|' || firstchar == '@' || firstchar == '*';
    456456}
    457 
    458 double GenoOperators::calculateSolidVolume(Part * part)
    459 {
    460         double radiiProduct = part->scale.x * part->scale.y * part->scale.z;
    461         switch (part->shape)
    462         {
    463         case Part::Shape::SHAPE_CUBOID:
    464                 return 8.0 * radiiProduct;
    465         case Part::Shape::SHAPE_CYLINDER:
    466                 return  2.0 * M_PI * radiiProduct;
    467         case Part::Shape::SHAPE_ELLIPSOID:
    468                 return  (4.0 / 3.0) * M_PI * radiiProduct;
    469         default:
    470                 logMessage("GenoOperators", "calculateSolidVolume", LOG_ERROR, "Unsupported part shape");
    471                 return -1;
    472         }
    473 }
  • cpp/frams/genetics/genooperators.h

    r1023 r1032  
    215215        static bool canStartNeuroClassName(const char firstchar); ///<determines if \e firstchar may start NeuroClass name. If not, it might start NeuroClass' (or Neuro's) property name.
    216216
    217         static double calculateSolidVolume(Part *part);
    218217
    219218        //@}
  • cpp/frams/model/geometry/geometryutils.cpp

    r1026 r1032  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2020  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
     
    369369        return M_PI * ((3 * (a+b)) - sqrt((3*a + b) * (a + 3*b)));
    370370}
     371
     372double GeometryUtils::calculateSolidVolume(Part * part)
     373{
     374        double radiiProduct = part->scale.x * part->scale.y * part->scale.z;
     375        switch (part->shape)
     376        {
     377                case Part::Shape::SHAPE_CUBOID:
     378                        return 8.0 * radiiProduct;
     379                case Part::Shape::SHAPE_CYLINDER:
     380                        return  2.0 * M_PI * radiiProduct;
     381                case Part::Shape::SHAPE_ELLIPSOID:
     382                        return  (4.0 / 3.0) * M_PI * radiiProduct;
     383                default:
     384                        logMessage("GeometryUtils", "calculateSolidVolume", LOG_ERROR, "Unsupported part shape");
     385                        return -1;
     386        }
     387}
     388
     389bool GeometryUtils::isSolidPartScaleValid(const Part::Shape &partShape, const Pt3D &scale)
     390{
     391        Part *tmpPart = new Part(partShape);
     392        tmpPart->scale = scale;
     393        double volume = GeometryUtils::calculateSolidVolume(tmpPart);
     394
     395        Part_MinMaxDef minP = Model::getMinPart();
     396        Part_MinMaxDef maxP = Model::getMaxPart();
     397
     398        if (volume > maxP.volume || minP.volume > volume)
     399                return false;
     400        if (scale.x < minP.scale.x || scale.y < minP.scale.y || scale.z < minP.scale.z)
     401                return false;
     402        if (scale.x > maxP.scale.x || scale.y > maxP.scale.y || scale.z > maxP.scale.z)
     403                return false;
     404
     405        if (partShape == Part::Shape::SHAPE_ELLIPSOID && scale.maxComponentValue() != scale.minComponentValue()) // When any radius has a different value than the others
     406                return false;
     407        if (partShape == Part::Shape::SHAPE_CYLINDER && scale.y != scale.z) // If base radii have different values
     408                return false;
     409        return true;
     410}
  • cpp/frams/model/geometry/geometryutils.h

    r286 r1032  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2020  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
     
    177177        double ellipsoidArea(const double a, const double b, const double c);
    178178        double ellipsePerimeter(const double a, const double b);
     179
     180        double calculateSolidVolume(Part *part);
     181        bool isSolidPartScaleValid(const Part::Shape &partShape, const Pt3D &scale);
    179182}
    180183
  • cpp/frams/model/geometry/part_distance_estimator.h

    r1031 r1032  
    5656                /// tmpPart1 and tmpPart2 are copied for purpose and should not be passed as reference
    5757                /// This function can change some of the properties of those parts
     58                /// tmpPart1 will be approximated by surface points.
     59                /// The collision between the parts is detected when any of those points is inside tmpPart2
     60                /// If tmpPart1 and tmpPart2 are swapped, the calculated distance may slightly differ
    5861                Pt3D directionVersor = tmpPart1.p - tmpPart2.p;
    5962                directionVersor.normalize();
    6063
    61                 tmpPart1.p = Pt3D(0);
    62                 tmpPart2.p = Pt3D(0);
     64                tmpPart1.p = Pt3D_0;
     65                tmpPart2.p = Pt3D_0;
    6366
    6467                static double CBRT_3 = std::cbrt(3);
Note: See TracChangeset for help on using the changeset viewer.