Changeset 1000 for cpp/frams/genetics/fS/fS_general.cpp
- Timestamp:
- 07/13/20 13:53:25 (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/genetics/fS/fS_general.cpp
r973 r1000 11 11 #include "frams/neuro/neurolibrary.h" 12 12 #include "../genooperators.h" 13 #include "common/nonstd_math.h" 14 #include "part_distance_estimator.h" 13 15 14 16 int fS_Genotype::precision = 4; 15 17 bool fS_Genotype::TURN_WITH_ROTATION = false; 16 18 19 const std::map<string, double> defaultValues = { 20 {INGESTION, 0.5},//Model::getDefPart().ingest }, 21 {FRICTION, 0.5},//Model::getDefPart().friction}, 22 {STIFFNESS, 0.5},//Model::getDefJoint().stif}, 23 {ROT_X, 0.0}, 24 {ROT_Y, 0.0}, 25 {ROT_Z, 0.0}, 26 {RX, 0.0}, 27 {RY, 0.0}, 28 {RZ, 0.0}, 29 {SIZE, 1.0}, 30 {SIZE_X, 0.5},//Model::getDefPart().scale.x}, 31 {SIZE_Y, 0.5},//Model::getDefPart().scale.y}, 32 {SIZE_Z, 0.5}//Model::getDefPart().scale.z} 33 }; 17 34 18 35 double fS_stod(const string& str, int start, size_t* size) … … 52 69 } 53 70 54 void rotateVector(Pt3D &vector, const Pt3D &rotation)55 {56 Orient rotmatrix = Orient_1;57 rotmatrix.rotate(rotation);58 vector = rotmatrix.transform(vector);59 }60 61 71 void State::rotate(const Pt3D &rotation) 62 72 { 63 rotateVector(v, rotation);73 fS_Utils::rotateVector(v, rotation); 64 74 v.normalize(); 65 75 } … … 111 121 } 112 122 113 Node::Node(Substring &restOfGeno, Node *_parent) 114 { 123 Node::Node(Substring &restOfGeno, Node *_parent, GenotypeParams _genotypeParams) 124 { 125 partDescription = new Substring(restOfGeno); 126 genotypeParams = _genotypeParams; 115 127 parent = _parent; 116 partDescription = new Substring(restOfGeno);117 128 118 129 try … … 289 300 } 290 301 291 double avg(double a, double b)292 {293 return 0.5 * (a + b);294 }295 296 double min3(Pt3D p)297 {298 double tmp = p.x;299 if (p.y < tmp)300 tmp = p.y;301 if (p.z < tmp)302 tmp = p.z;303 return tmp;304 }305 306 double max3(Pt3D p)307 {308 double tmp = p.x;309 if (p.y > tmp)310 tmp = p.y;311 if (p.z > tmp)312 tmp = p.z;313 return tmp;314 }315 316 double getSphereCoordinate(double dimension, double sphereDiameter, double index, int count)317 {318 if (count == 1)319 return 0;320 return (dimension - sphereDiameter) * (index / (count - 1) - 0.5);321 }322 323 Pt3D *findSphereCenters(int &sphereCount, double &sphereRadius, Pt3D radii, Pt3D rotations)324 {325 double sphereRelativeDistance = SPHERE_RELATIVE_DISTANCE;326 double minRadius = min3(radii);327 if(minRadius <= 0)328 throw fS_Exception("Invalid part size", 0);329 double maxRadius = max3(radii);330 if (MAX_DIAMETER_QUOTIENT > maxRadius / minRadius)331 sphereRadius = minRadius;332 else333 {334 // When max radius is much bigger than min radius335 sphereRelativeDistance = 1.0; // Make the spheres adjacent to speed up the computation336 sphereRadius = maxRadius / MAX_DIAMETER_QUOTIENT;337 }338 double sphereDiameter = 2 * sphereRadius;339 340 double *diameters = new double[3] {2 * radii.x, 2 * radii.y, 2 * radii.z};341 int counts[3];342 for (int i = 0; i < 3; i++)343 {344 counts[i] = 1;345 if (diameters[i] > sphereDiameter)346 counts[i] += ceil((diameters[i] - sphereDiameter) / sphereDiameter / sphereRelativeDistance);347 }348 349 sphereCount = counts[0] * counts[1] * counts[2];350 double x, y, z;351 int totalCount = 0;352 Pt3D *centers = new Pt3D[sphereCount];353 for (double xi = 0; xi < counts[0]; xi++)354 {355 x = getSphereCoordinate(diameters[0], sphereDiameter, xi, counts[0]);356 for (double yi = 0; yi < counts[1]; yi++)357 {358 y = getSphereCoordinate(diameters[1], sphereDiameter, yi, counts[1]);359 for (double zi = 0; zi < counts[2]; zi++)360 {361 z = getSphereCoordinate(diameters[2], sphereDiameter, zi, counts[2]);362 centers[totalCount] = Pt3D(x, y, z);363 rotateVector(centers[totalCount], rotations);364 totalCount++;365 }366 }367 }368 delete[] diameters;369 return centers;370 }371 372 int isCollision(Pt3D *centersParent, Pt3D *centers, int parentSphereCount, int sphereCount, Pt3D &vector,373 double distanceThreshold)374 {375 double upperThreshold = distanceThreshold;376 double lowerThreshold = SPHERE_DISTANCE_TOLERANCE * distanceThreshold;377 double distance;378 double dx, dy, dz;379 bool existsAdjacent = false;380 Pt3D *tmpPoint;381 for (int sc = 0; sc < sphereCount; sc++)382 {383 Pt3D shiftedSphere = Pt3D(centers[sc]);384 shiftedSphere += vector;385 for (int psc = 0; psc < parentSphereCount; psc++)386 {387 tmpPoint = ¢ersParent[psc];388 dx = shiftedSphere.x - tmpPoint->x;389 dy = shiftedSphere.y - tmpPoint->y;390 dz = shiftedSphere.z - tmpPoint->z;391 distance = sqrt(dx * dx + dy * dy + dz * dz);392 393 if (distance <= upperThreshold)394 {395 if (distance >= lowerThreshold)396 existsAdjacent = true;397 else398 {399 return COLLISION;400 }401 }402 }403 }404 if (existsAdjacent)405 return ADJACENT;406 else407 return DISJOINT;408 }409 410 double Node::getDistance()411 {412 Pt3D size = calculateSize();413 Pt3D parentSize = parent->calculateSize(); // Here we are sure that parent is not nullptr414 int parentSphereCount, sphereCount;415 double parentSphereRadius, sphereRadius;416 Pt3D *centersParent = findSphereCenters(parentSphereCount, parentSphereRadius, parentSize, parent->getRotation());417 Pt3D *centers = findSphereCenters(sphereCount, sphereRadius, size, getRotation());418 419 double distanceThreshold = sphereRadius + parentSphereRadius;420 double minDistance = 0.0;421 double maxDistance = 2 * (max3(parentSize) + max3(size));422 double currentDistance = avg(maxDistance, minDistance);423 int result = -1;424 int iterationNo = 0;425 while (result != ADJACENT)426 {427 iterationNo++;428 Pt3D currentVector = state->v * currentDistance;429 result = isCollision(centersParent, centers, parentSphereCount, sphereCount, currentVector, distanceThreshold);430 431 if (result == DISJOINT)432 {433 maxDistance = currentDistance;434 currentDistance = avg(currentDistance, minDistance);435 } else if (result == COLLISION)436 {437 minDistance = currentDistance;438 currentDistance = avg(maxDistance, currentDistance);439 }440 441 if(maxDistance <= 0 || iterationNo > 1000)442 throw fS_Exception("Computing of distances between parts failed", 0);443 if (currentDistance > maxDistance)444 {445 throw fS_Exception("Internal error; then maximal distance between parts exceeded.", 0);446 }447 if (currentDistance < minDistance)448 throw fS_Exception("Internal error; the minimal distance between parts exceeded.", 0);449 450 }451 452 delete[] centersParent;453 delete[] centers;454 return currentDistance;455 }456 302 457 303 void Node::getState(State *_state) … … 469 315 { 470 316 char mod = it->first; 471 double multiplier = pow( MODIFIER_MULTIPLIER, it->second);317 double multiplier = pow(genotypeParams.modifierMultiplier, it->second); 472 318 if (mod == MODIFIERS[0]) 473 319 state->ing *= multiplier; … … 497 343 for (int i = 0; i < int(branches.size()); i++) 498 344 { 499 children.push_back(new Node(branches[i], this ));345 children.push_back(new Node(branches[i], this, genotypeParams)); 500 346 } 501 347 } … … 581 427 return false; 582 428 583 if (partType == Part::Shape::SHAPE_ELLIPSOID && max3(size) !=min3(size))429 if (partType == Part::Shape::SHAPE_ELLIPSOID && fS_Utils::max3(size) != fS_Utils::min3(size)) 584 430 // When not all radii have different values 585 431 return false; 586 if (partType == Part::Shape::SHAPE_CYLINDER && size. x != size.y)432 if (partType == Part::Shape::SHAPE_CYLINDER && size.y != size.z) 587 433 // If base radii have different values 588 434 return false; … … 619 465 Neuro *neuro = new Neuro(*neurons[i]); 620 466 model.addNeuro(neuro); 621 if (neuro->getClass()->preflocation == 2&& parent != nullptr)467 if (neuro->getClass()->preflocation == NeuroClass::PREFER_JOINT && parent != nullptr) 622 468 { 623 469 neuro->attachToJoint(model.getJoint(model.getJointCount() - 1)); … … 732 578 result += it->first.c_str(); // Add parameter key to string 733 579 result += PARAM_KEY_VALUE_SEPARATOR; 734 string value_text = std::to_string(it->second);735 580 // Round the value to two decimal places and add to string 736 result += value_text.substr(0, value_text.find(".") +fS_Genotype::precision).c_str();581 result += doubleToString(it->second, fS_Genotype::precision).c_str(); 737 582 } 738 583 result += PARAM_END; … … 754 599 } 755 600 756 757 bool Node::changeSizeParam(string key, bool ensureCircleSection)758 {759 double oldValue = getParam(key);760 params[key] = GenoOperators::mutateCreep('f', params[key], minValues.at(key), maxValues.at(key), true);761 if (!ensureCircleSection || isPartSizeValid())762 return true;763 else764 {765 params[key] = oldValue;766 return false;767 }768 }769 770 601 void Node::getAllNodes(vector<Node *> &allNodes) 771 602 { … … 782 613 } 783 614 784 fS_Genotype::fS_Genotype(const string &geno type)615 fS_Genotype::fS_Genotype(const string &geno) 785 616 { 786 617 try 787 618 { 788 string geno = genotype.c_str(); 789 Substring substring(geno.c_str(), 0, geno.length()); 790 startNode = new Node(substring, nullptr); 619 GenotypeParams genotypeParams; 620 genotypeParams.modifierMultiplier = 1.1; 621 622 size_t modeSeparatorIndex = geno.find(MODE_SEPARATOR); 623 if (modeSeparatorIndex == string::npos) 624 throw fS_Exception("Genotype parameters missing", 0); 625 626 genotypeParams.modifierMultiplier = fS_stod(geno, 0, &modeSeparatorIndex); 627 628 int genoStart = modeSeparatorIndex + 1; 629 Substring substring(geno.c_str(), genoStart, geno.length() - genoStart); 630 startNode = new Node(substring, nullptr, genotypeParams); 791 631 validateNeuroInputs(); 792 632 } … … 859 699 { 860 700 SString geno; 861 geno.reserve(100); // Provide a small buffer from the start to improve performance 701 geno.reserve(100); 702 703 geno += doubleToString(startNode->genotypeParams.modifierMultiplier, fS_Genotype::precision).c_str(); 704 geno += MODE_SEPARATOR; 705 862 706 startNode->getGeno(geno); 863 707 return geno;
Note: See TracChangeset
for help on using the changeset viewer.