1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

New zone placement algorithm

This commit is contained in:
DjWarmonger 2014-12-23 11:39:41 +01:00
parent 0e34775770
commit 868d2f61ee

View File

@ -198,7 +198,7 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
//now perform drastic movement of zone that is completely not linked //now perform drastic movement of zone that is completely not linked
float maxRatio = 0; float maxRatio = 0;
CRmgTemplateZone * distantZone = nullptr; CRmgTemplateZone * misplacedZone = nullptr;
float totalDistance = 0; float totalDistance = 0;
float totalOverlap = 0; float totalOverlap = 0;
@ -211,13 +211,13 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
if (ratio > maxRatio) if (ratio > maxRatio)
{ {
maxRatio = ratio; maxRatio = ratio;
distantZone = zone.first; misplacedZone = zone.first;
} }
} }
logGlobal->traceStream() << boost::format("Total distance between zones in this iteration: %2.4f, Total overlap: %2.4f, Worst misplacement/movement ratio: %3.2f") % totalDistance % totalOverlap % maxRatio; logGlobal->traceStream() << boost::format("Total distance between zones in this iteration: %2.4f, Total overlap: %2.4f, Worst misplacement/movement ratio: %3.2f") % totalDistance % totalOverlap % maxRatio;
//save best solution before drastic jump //save best solution before drastic jump
if (totalDistance <= bestTotalDistance && totalOverlap <= bestTotalOverlap) if (totalDistance + totalOverlap < bestTotalDistance + bestTotalOverlap)
{ {
bestTotalDistance = totalDistance; bestTotalDistance = totalDistance;
bestTotalOverlap = totalOverlap; bestTotalOverlap = totalOverlap;
@ -230,35 +230,58 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
if (maxRatio > maxDistanceMovementRatio) if (maxRatio > maxDistanceMovementRatio)
{ {
//simply move the zone further in same direction
//distantZone->setCenter(distantZone->getCenter() + forces[distantZone] * maxRatio / maxDistanceMovementRatio);
//logGlobal->traceStream() << boost::format("Trying to move zone %d %s further") % distantZone->getId() % distantZone->getCenter()();
//find most distant zone that should be attracted and move inside it
CRmgTemplateZone * targetZone = nullptr; CRmgTemplateZone * targetZone = nullptr;
float maxDistance = 0; float3 ourCenter = misplacedZone->getCenter();
float3 ourCenter = distantZone->getCenter();
for (auto con : distantZone->getConnections()) if (totalDistance > totalOverlap)
{ {
auto otherZone = zones[con]; //find most distant zone that should be attracted and move inside it
float distance = otherZone->getCenter().dist2dSQ(ourCenter); float maxDistance = 0;
if (distance > maxDistance) for (auto con : misplacedZone->getConnections())
{ {
maxDistance = distance; auto otherZone = zones[con];
targetZone = otherZone; float distance = otherZone->getCenter().dist2dSQ(ourCenter);
if (distance > maxDistance)
{
maxDistance = distance;
targetZone = otherZone;
}
} }
float3 vec = targetZone->getCenter() - ourCenter;
float newDistanceBetweenZones = (std::max(misplacedZone->getSize(), targetZone->getSize())) * zoneScale / mapSize;
logGlobal->traceStream() << boost::format("Trying to move zone %d %s towards %d %s. Old distance %f") %
misplacedZone->getId() % ourCenter() % targetZone->getId() % targetZone->getCenter()() % maxDistance;
logGlobal->traceStream() << boost::format("direction is %s") % vec();
misplacedZone->setCenter(targetZone->getCenter() - vec.unitVector() * newDistanceBetweenZones); //zones should now overlap by half size
logGlobal->traceStream() << boost::format("New distance %f") % targetZone->getCenter().dist2d(misplacedZone->getCenter());
} }
float3 vec = targetZone->getCenter() - ourCenter; else
float newDistanceBetweenZones = (std::max (distantZone->getSize(),targetZone->getSize())) * zoneScale / mapSize; {
logGlobal->traceStream() << boost::format("Trying to move zone %d %s towards %d %s. Old distance %f") % float maxOverlap = 0;
distantZone->getId() % ourCenter() % targetZone->getId() % targetZone->getCenter()() % maxDistance; for (auto otherZone : zones)
logGlobal->traceStream() << boost::format("direction is %s") % vec(); {
float3 otherZoneCenter = otherZone.second->getCenter();
distantZone->setCenter(targetZone->getCenter() - vec.unitVector() * newDistanceBetweenZones); //zones should now overlap by half size if (otherZone.second == misplacedZone || otherZoneCenter.z != ourCenter.z)
logGlobal->traceStream() << boost::format("New distance %f") % targetZone->getCenter().dist2d(distantZone->getCenter()); continue;
//TODO: do the same with overlapping zones? float distance = otherZoneCenter.dist2dSQ(ourCenter);
if (distance > maxOverlap)
{
maxOverlap = distance;
targetZone = otherZone.second;
}
}
float3 vec = ourCenter - targetZone->getCenter();
float newDistanceBetweenZones = (misplacedZone->getSize() + targetZone->getSize()) * zoneScale / mapSize;
logGlobal->traceStream() << boost::format("Trying to move zone %d %s away from %d %s. Old distance %f") %
misplacedZone->getId() % ourCenter() % targetZone->getId() % targetZone->getCenter()() % maxOverlap;
logGlobal->traceStream() << boost::format("direction is %s") % vec();
misplacedZone->setCenter(targetZone->getCenter() + vec.unitVector() * newDistanceBetweenZones); //zones should now be just separated
logGlobal->traceStream() << boost::format("New distance %f") % targetZone->getCenter().dist2d(misplacedZone->getCenter());
}
} }
zoneScale *= inflateModifier; //increase size of zones so they zoneScale *= inflateModifier; //increase size of zones so they