Changeset 1030 for cpp/frams/genetics/fS
- Timestamp:
- 11/26/20 01:30:40 (4 years ago)
- Location:
- cpp/frams/genetics/fS
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/genetics/fS/fS_conv.h
r1017 r1030 17 17 GenoConv_fS0s() : GenoConverter() 18 18 { 19 name = "Solid encoding";19 name = "Solids tree-structure encoding"; 20 20 21 21 in_format = "S"; -
cpp/frams/genetics/fS/fS_general.cpp
r1017 r1030 15 15 16 16 int fS_Genotype::precision = 4; 17 bool fS_Genotype::TURN_WITH_ROTATION = false;18 17 std::map<string, double> Node::minValues; 19 18 std::map<string, double> Node::defaultValues; … … 33 32 {RY, -M_PI}, 34 33 {RZ, -M_PI}, 35 {S IZE, 0.01},36 {S IZE_X, Model::getMinPart().scale.x},37 {S IZE_Y, Model::getMinPart().scale.y},38 {S IZE_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} 39 38 }; 40 39 } … … 51 50 {RY, M_PI}, 52 51 {RZ, M_PI}, 53 {S IZE, 100.0},54 {S IZE_X, Model::getMaxPart().scale.x},55 {S IZE_Y, Model::getMaxPart().scale.y},56 {S IZE_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} 57 56 }; 58 57 } … … 68 67 {RY, 0.0}, 69 68 {RZ, 0.0}, 70 {S IZE, 1.0},71 {S IZE_X, Model::getDefPart().scale.x},72 {S IZE_Y, Model::getDefPart().scale.y},73 {S IZE_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} 74 73 }; 75 74 } … … 111 110 } 112 111 112 void rotateVector(Pt3D &vector, const Pt3D &rotation) 113 { 114 Orient rotmatrix = Orient_1; 115 rotmatrix.rotate(rotation); 116 vector = rotmatrix.transform(vector); 117 } 118 113 119 void State::rotate(const Pt3D &rotation) 114 120 { 115 fS_Utils::rotateVector(v, rotation);121 rotateVector(v, rotation); 116 122 v.normalize(); 117 123 } … … 218 224 void Node::extractModifiers(Substring &restOfGenotype) 219 225 { 220 int part TypePosition = getPartPosition(restOfGenotype);221 if (part TypePosition == -1)226 int partShapePosition = getPartPosition(restOfGenotype); 227 if (partShapePosition == -1) 222 228 throw fS_Exception("Part type missing", restOfGenotype.start); 223 229 224 for (int i = 0; i < part TypePosition; i++)230 for (int i = 0; i < partShapePosition; i++) 225 231 { 226 232 // Extract modifiers and joint … … 233 239 throw fS_Exception("Invalid modifier", restOfGenotype.start + i); 234 240 } 235 restOfGenotype.startFrom(part TypePosition);241 restOfGenotype.startFrom(partShapePosition); 236 242 } 237 243 … … 242 248 throw fS_Exception("Invalid part type", restOfGenotype.start); 243 249 244 part Type = itr->second;250 partShape = itr->second; 245 251 restOfGenotype.startFrom(1); 246 252 } … … 327 333 size_t len = length - valueStartIndex; 328 334 double value = fS_stod(val, restOfGenotype.start + start + valueStartIndex, &len); 329 if((key==S IZE_X || key==SIZE_Y || key==SIZE_Z) && value <= 0.0)335 if((key==SCALE_X || key==SCALE_Y || key==SCALE_Z) && value <= 0.0) 330 336 throw fS_Exception("Invalid value of radius parameter", restOfGenotype.start + start + valueStartIndex); 331 337 … … 342 348 if (item != params.end()) 343 349 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; 345 355 } 346 356 … … 382 392 state->rotate(getVectorRotation()); 383 393 384 double distance = getDistance();394 double distance = calculateDistanceFromParent(); 385 395 state->addVector(distance); 386 396 } … … 433 443 } 434 444 435 void Node::calculateS ize(Pt3D &scale)436 { 437 double s izeMultiplier = getParam(SIZE) * state->s;438 scale.x = getParam(S IZE_X) * sizeMultiplier;439 scale.y = getParam(S IZE_Y) * sizeMultiplier;440 scale.z = getParam(S IZE_Z) * sizeMultiplier;445 void 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; 441 451 } 442 452 … … 444 454 { 445 455 double result; 446 Pt3D s ize;447 calculateS ize(size);448 double radiiProduct = s ize.x * size.y * size.z;449 switch (part Type)456 Pt3D scale; 457 calculateScale(scale); 458 double radiiProduct = scale.x * scale.y * scale.z; 459 switch (partShape) 450 460 { 451 461 case Part::Shape::SHAPE_CUBOID: … … 464 474 } 465 475 466 bool Node::isPartS izeValid()467 { 468 Pt3D s ize;469 calculateS ize(size);476 bool Node::isPartScaleValid() 477 { 478 Pt3D scale; 479 calculateScale(scale); 470 480 double volume = calculateVolume(); 471 481 Part_MinMaxDef minP = Model::getMinPart(); … … 474 484 if (volume > maxP.volume || minP.volume > volume) 475 485 return false; 476 if (s ize.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) 477 487 return false; 478 if (s ize.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) 479 489 return false; 480 490 481 if (part Type == Part::Shape::SHAPE_ELLIPSOID && fS_Utils::max3(size) != fS_Utils::min3(size))491 if (partShape == Part::Shape::SHAPE_ELLIPSOID && scale.maxComponentValue() != scale.minComponentValue()) 482 492 // When not all radii have different values 483 493 return false; 484 if (part Type == Part::Shape::SHAPE_CYLINDER && size.y != size.z)494 if (partShape == Part::Shape::SHAPE_CYLINDER && scale.y != scale.z) 485 495 // If base radii have different values 486 496 return false; … … 488 498 } 489 499 490 bool Node::hasPartSizeParam()491 {492 return params.count(SIZE_X) > 0 || params.count(SIZE_Y) > 0 || params.count(SIZE_Z) > 0;493 }494 495 500 Pt3D Node::getVectorRotation() 496 501 { … … 501 506 { 502 507 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) 504 509 rotation += getVectorRotation(); 505 510 return rotation; … … 537 542 void Node::createPart() 538 543 { 539 part = new Part(part Type);544 part = new Part(partShape); 540 545 part->p = Pt3D(state->location); 541 546 542 547 part->friction = getParam(FRICTION) * state->fr; 543 548 part->ingest = getParam(INGESTION) * state->ing; 544 calculateS ize(part->scale);549 calculateScale(part->scale); 545 550 part->setRot(getRotation()); 546 551 } … … 581 586 result += std::string(count, mod).c_str(); 582 587 } 583 result += SHAPE_TO_GENE.at(part Type);588 result += SHAPE_TO_GENE.at(partShape); 584 589 585 590 if (!neurons.empty()) … … 658 663 } 659 664 660 fS_Genotype::fS_Genotype(const string &geno) 661 { 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()); 662 670 try 663 671 { 664 672 GenotypeParams genotypeParams; 665 673 genotypeParams.modifierMultiplier = 1.1; 674 genotypeParams.distanceTolerance = 0.1; 675 genotypeParams.relativeDensity = 10.0; 676 genotypeParams.turnWithRotation = false; 677 genotypeParams.paramMutationStrength = 0.4; 666 678 667 679 size_t modeSeparatorIndex = geno.find(MODE_SEPARATOR); … … 669 681 throw fS_Exception("Genotype parameters missing", 0); 670 682 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 } 672 700 673 701 int genoStart = modeSeparatorIndex + 1; … … 680 708 delete startNode; 681 709 throw e; 710 } 711 catch(...) 712 { 713 delete startNode; 714 throw fS_Exception("Unknown exception in fS", 0); 682 715 } 683 716 } … … 753 786 geno.reserve(100); 754 787 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(); 756 794 geno += MODE_SEPARATOR; 757 795 … … 850 888 for (int i = 0; i < int(nodes.size()); i++) 851 889 { 852 if (!nodes[i]->isPartS izeValid())890 if (!nodes[i]->isPartScaleValid()) 853 891 { 854 892 return 1 + nodes[i]->partDescription->start; … … 884 922 } 885 923 924 double 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 43 43 #define FRICTION "f" 44 44 #define STIFFNESS "st" 45 #define S IZE "s"46 #define S IZE_X "x"47 #define S IZE_Y "y"48 #define S IZE_Z "z"45 #define SCALE "s" 46 #define SCALE_X "x" 47 #define SCALE_Y "y" 48 #define SCALE_Z "z" 49 49 #define ROT_X "tx" 50 50 #define ROT_Y "ty" … … 83 83 const int JOINT_COUNT = JOINTS.length(); 84 84 const string MODIFIERS = "IFS"; 85 const char S IZE_MODIFIER = 's';86 const vector<string> PARAMS {INGESTION, FRICTION, ROT_X, ROT_Y, ROT_Z, RX, RY, RZ, S IZE, SIZE_X, SIZE_Y, SIZE_Z};87 const vector<string> S IZE_PARAMS {SIZE, SIZE_X, SIZE_Y, SIZE_Z};85 const char SCALE_MODIFIER = 's'; 86 const vector<string> PARAMS {INGESTION, FRICTION, ROT_X, ROT_Y, ROT_Z, RX, RY, RZ, SCALE, SCALE_X, SCALE_Y, SCALE_Z}; 87 const vector<string> SCALE_PARAMS {SCALE, SCALE_X, SCALE_Y, SCALE_Z}; 88 88 89 89 /** @name Default values of node parameters*/ … … 247 247 struct GenotypeParams{ 248 248 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; 249 258 }; 250 259 … … 265 274 Part *part; /// A part object built from node. Used in building the Model 266 275 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 268 279 269 280 vector<Node *> children; /// Vector of all direct children … … 273 284 void prepareParams(); 274 285 275 double getDistance();276 277 286 void cleanUp(); 278 287 288 /// Get part's rotation 279 289 Pt3D getRotation(); 280 290 291 /// Get the rotation of vector 281 292 Pt3D getVectorRotation(); 282 293 283 bool isPartSizeValid(); 284 285 bool hasPartSizeParam(); 294 bool isPartScaleValid(); 286 295 287 296 /** … … 362 371 363 372 public: 364 static std::map<string, double> minValues;365 static std::map<string, double> defaultValues;366 static std::map<string, double> maxValues;367 373 char joint = DEFAULT_JOINT; /// Set of all joints 368 Part::Shape part Type; /// The type of the part374 Part::Shape partShape; /// The type of the part 369 375 State *state = nullptr; /// The phenotypic state that inherits from ancestors 370 376 std::map<string, double> params; /// The map of all the node params 377 GenotypeParams genotypeParams; /// Parameters that affect the whole genotype 371 378 372 379 Node(Substring &genotype, Node *parent, GenotypeParams genotypeParams); … … 381 388 382 389 /** 383 * Calculate the effective s ize of the part (after applying all multipliers and params)384 * @return The effective s ize385 */ 386 void calculateS ize(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); 387 394 388 395 /** … … 404 411 double getParam(const string &key); 405 412 double getParam(const string &key, double defaultValue); 413 414 /// Calculate distance between the part its parent 415 double calculateDistanceFromParent(); 406 416 }; 407 417 … … 439 449 440 450 441 static int precision; 442 static bool TURN_WITH_ROTATION; 451 static int precision; /// Number of decimal places for numbers in genotype 443 452 444 453 /** … … 450 459 ~fS_Genotype(); 451 460 461 /// Calculate the State field for all the nodes 452 462 void getState(bool calculateLocation); 453 463 … … 495 505 496 506 /** 497 * Check if s izes of all parts in genotype are valid507 * Check if scales of all parts in genotype are valid 498 508 \retval error_position 1-based 499 509 \retval 0 when all part sizes are valid -
cpp/frams/genetics/fS/fS_oper.cpp
r1017 r1030 51 51 if (errorPosition != 0) 52 52 { 53 logPrintf("GenoOper_fS", "checkValidity", LOG_WARN, "Invalid part s ize");53 logPrintf("GenoOper_fS", "checkValidity", LOG_WARN, "Invalid part scale"); 54 54 return errorPosition; 55 55 } … … 226 226 const char *GenoOper_fS::getSimplest() 227 227 { 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}"; 229 229 } 230 230 … … 297 297 geno.getState(false); 298 298 Node *node = geno.chooseNode(); 299 char part Type = SHAPE_TO_GENE.at(availablePartShapes[rndUint(availablePartShapes.size())]);300 301 Substring substring(&part Type, 0, 1);299 char partShape = SHAPE_TO_GENE.at(availablePartShapes[rndUint(availablePartShapes.size())]); 300 301 Substring substring(&partShape, 0, 1); 302 302 Node *newNode = new Node(substring, node, node->genotypeParams); 303 303 // Add random rotation … … 322 322 newNode->params[selectedParam] = RndGen.Uni(-M_PI / 2, M_PI / 2); 323 323 } 324 // Assign part s ize to default value325 double volumeMultiplier = pow(node->getParam(S IZE) * node->state->s, 3);324 // Assign part scale to default value 325 double volumeMultiplier = pow(node->getParam(SCALE) * node->state->s, 3); 326 326 double minVolume = Model::getMinPart().volume; 327 327 double defVolume = Model::getDefPart().volume * volumeMultiplier; // Default value after applying modifiers … … 330 330 double relativeVolume = volume / volumeMultiplier; // Volume without applying modifiers 331 331 332 double newRadius = std::cbrt(relativeVolume / volumeMultipliers.at(newNode->part Type));333 newNode->params[S IZE_X] = newRadius;334 newNode->params[S IZE_Y] = newRadius;335 newNode->params[S IZE_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; 336 336 node->children.push_back(newNode); 337 337 … … 339 339 { 340 340 geno.getState(false); 341 mutateS izeParam(newNode, SIZE_X, true);342 mutateS izeParam(newNode, SIZE_Y, true);343 mutateS izeParam(newNode, SIZE_Z, true);341 mutateScaleParam(newNode, SCALE_X, true); 342 mutateScaleParam(newNode, SCALE_Y, true); 343 mutateScaleParam(newNode, SCALE_Z, true); 344 344 } 345 345 return true; … … 350 350 Node *randomNode, *selectedChild; 351 351 // Choose a parent with children 352 // It may be difficult to choose a eligible node, so the number of tries should be high352 // It may be difficult to choose an eligible node, so the number of tries should be high 353 353 for (int i = 0; i < 10 * mutationTries; i++) 354 354 { … … 380 380 Node *randomNode = geno.chooseNode(); 381 381 int index = rndUint(availShapesLen); 382 if (availablePartShapes[index] == randomNode->part Type)382 if (availablePartShapes[index] == randomNode->partShape) 383 383 index = (index + 1 + rndUint(availShapesLen - 1)) % availShapesLen; 384 384 Part::Shape newType = availablePartShapes[index]; 385 385 386 386 #ifdef _DEBUG 387 if(newType == randomNode->part Type)387 if(newType == randomNode->partShape) 388 388 throw fS_Exception("Internal error: invalid part type chosen in mutation.", 1); 389 389 #endif 390 390 391 391 geno.getState(false); 392 double s izeMultiplier = randomNode->getParam(SIZE) * randomNode->state->s;393 double relativeVolume = randomNode->calculateVolume() / pow(s izeMultiplier, 3.0);394 395 if (!ensureCircleSection || newType == Part::Shape::SHAPE_CUBOID || (randomNode->part Type == Part::Shape::SHAPE_ELLIPSOID && newType == Part::Shape::SHAPE_CYLINDER))396 { 397 double radiusQuotient = std::cbrt(volumeMultipliers.at(randomNode->part Type) / volumeMultipliers.at(newType));398 randomNode->params[S IZE_X] = randomNode->getParam(SIZE_X) * radiusQuotient;399 randomNode->params[S IZE_Y] = randomNode->getParam(SIZE_Y) * radiusQuotient;400 randomNode->params[S IZE_Z] = randomNode->getParam(SIZE_Z) * radiusQuotient;401 } else if (randomNode->part Type == Part::Shape::SHAPE_CUBOID && newType == Part::Shape::SHAPE_CYLINDER)402 { 403 double newRadius = 0.5 * (randomNode->getParam(S IZE_X) + randomNode->getParam(SIZE_Y));404 randomNode->params[S IZE_X] = 0.5 * relativeVolume / (M_PI * newRadius * newRadius);405 randomNode->params[S IZE_Y] = newRadius;406 randomNode->params[S IZE_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; 407 407 } else if (newType == Part::Shape::SHAPE_ELLIPSOID) 408 408 { 409 409 double newRelativeRadius = cbrt(relativeVolume / volumeMultipliers.at(newType)); 410 randomNode->params[S IZE_X] = newRelativeRadius;411 randomNode->params[S IZE_Y] = newRelativeRadius;412 randomNode->params[S IZE_Z] = newRelativeRadius;410 randomNode->params[SCALE_X] = newRelativeRadius; 411 randomNode->params[SCALE_Y] = newRelativeRadius; 412 randomNode->params[SCALE_Z] = newRelativeRadius; 413 413 } else 414 414 { 415 415 throw fS_Exception("Invalid part type", 1); 416 416 } 417 randomNode->part Type = newType;417 randomNode->partShape = newType; 418 418 return true; 419 419 } … … 446 446 return false; 447 447 // Do not allow invalid changes in part size 448 bool isRadiusOfBase = key == S IZE_Y || key == SIZE_Z;449 bool isRadius = isRadiusOfBase || key == S IZE_X;448 bool isRadiusOfBase = key == SCALE_Y || key == SCALE_Z; 449 bool isRadius = isRadiusOfBase || key == SCALE_X; 450 450 if (ensureCircleSection && isRadius) 451 451 { 452 if (randomNode->part Type == Part::Shape::SHAPE_ELLIPSOID)452 if (randomNode->partShape == Part::Shape::SHAPE_ELLIPSOID) 453 453 return false; 454 if (randomNode->part Type == Part::Shape::SHAPE_CYLINDER && isRadiusOfBase)454 if (randomNode->partShape == Part::Shape::SHAPE_CYLINDER && isRadiusOfBase) 455 455 return false; 456 456 } … … 490 490 bool GenoOper_fS::mutateParamValue(Node *node, string key) 491 491 { 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); 496 499 return true; 497 500 } else 498 return mutateS izeParam(node, key, ensureCircleSection);501 return mutateScaleParam(node, key, ensureCircleSection); 499 502 } 500 503 … … 524 527 randomNode->modifiers[randomModifier] += rndUint(2) == 0 ? 1 : -1; 525 528 526 bool isSizeMod = tolower(randomModifier) == S IZE_MODIFIER;529 bool isSizeMod = tolower(randomModifier) == SCALE_MODIFIER; 527 530 if (isSizeMod && geno.checkValidityOfPartSizes() != 0) 528 531 { … … 678 681 } 679 682 680 bool GenoOper_fS::mutateS izeParam(Node *node, string key, bool ensureCircleSection)683 bool GenoOper_fS::mutateScaleParam(Node *node, string key, bool ensureCircleSection) 681 684 { 682 685 double oldValue = node->getParam(key); 683 686 double volume = node->calculateVolume(); 684 687 double valueAtMinVolume, valueAtMaxVolume; 685 if(key == S IZE)688 if(key == SCALE) 686 689 { 687 690 valueAtMinVolume = oldValue * std::cbrt(Model::getMinPart().volume / volume); … … 696 699 double min = std::max(Node::minValues.at(key), valueAtMinVolume); 697 700 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()) 702 706 return true; 703 707 else -
cpp/frams/genetics/fS/fS_oper.h
r1017 r1030 142 142 143 143 /** 144 * Change the value of the s ize parameter by given multiplier145 * Do not change the value if any of the s ize restrictions is not satisfied144 * 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 146 146 * @param paramKey 147 147 * @param multiplier … … 149 149 * @return True if the parameter value was change, false otherwise 150 150 */ 151 bool mutateS izeParam(Node *node, string key, bool ensureCircleSection);151 bool mutateScaleParam(Node *node, string key, bool ensureCircleSection); 152 152 }; 153 153 -
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.