Browse Source

Significantly improved zone graph placement.

DjWarmonger 11 years ago
parent
commit
7ac3713d32
3 changed files with 64 additions and 7 deletions
  1. 4 4
      lib/rmg/CMapGenerator.cpp
  2. 52 3
      lib/rmg/CZonePlacer.cpp
  3. 8 0
      lib/rmg/float3.h

+ 4 - 4
lib/rmg/CMapGenerator.cpp

@@ -473,11 +473,11 @@ int CMapGenerator::getNextMonlithIndex()
 {
 {
 	if (monolithIndex >= VLC->objtypeh->knownSubObjects(Obj::MONOLITH_TWO_WAY).size())
 	if (monolithIndex >= VLC->objtypeh->knownSubObjects(Obj::MONOLITH_TWO_WAY).size())
 	{
 	{
-		logGlobal->errorStream() << boost::to_string(boost::format("RMG Error! There is no Monolith Two Way with index %d available!") % monolithIndex);
-		monolithIndex++;
-		return VLC->objtypeh->knownSubObjects(Obj::MONOLITH_TWO_WAY).size() - 1;
+		//logGlobal->errorStream() << boost::to_string(boost::format("RMG Error! There is no Monolith Two Way with index %d available!") % monolithIndex);
+		//monolithIndex++;
+		//return VLC->objtypeh->knownSubObjects(Obj::MONOLITH_TWO_WAY).size() - 1;
 		//TODO: interrupt map generation and report error
 		//TODO: interrupt map generation and report error
-		//throw rmgException(boost::to_string(boost::format("There is no Monolith Two Way with index %d available!") % monolithIndex));
+		throw rmgException(boost::to_string(boost::format("There is no Monolith Two Way with index %d available!") % monolithIndex));
 	}
 	}
 	else
 	else
 		return monolithIndex++;
 		return monolithIndex++;

+ 52 - 3
lib/rmg/CZonePlacer.cpp

@@ -107,12 +107,14 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
 	};
 	};
 
 
 	std::map <CRmgTemplateZone *, float3> forces;
 	std::map <CRmgTemplateZone *, float3> forces;
+	std::map <CRmgTemplateZone *, float> distances;
 	while (zoneScale < 1) //until zones reach their desired size and fill the map tightly
 	while (zoneScale < 1) //until zones reach their desired size and fill the map tightly
 	{
 	{
 		for (auto zone : zones)
 		for (auto zone : zones)
 		{
 		{
 			float3 forceVector(0,0,0);
 			float3 forceVector(0,0,0);
 			float3 pos = zone.second->getCenter();
 			float3 pos = zone.second->getCenter();
+			float totalDistance = 0;
 
 
 			//attract connected zones
 			//attract connected zones
 			for (auto con : zone.second->getConnections())
 			for (auto con : zone.second->getConnections())
@@ -124,9 +126,11 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
 				if (distance > minDistance)
 				if (distance > minDistance)
 				{
 				{
 					//WARNING: compiler used to 'optimize' that line so it never actually worked
 					//WARNING: compiler used to 'optimize' that line so it never actually worked
-					forceVector += (((otherZoneCenter - pos) / getDistance(distance))); //positive value
+					forceVector += (((otherZoneCenter - pos)*(pos.z != otherZoneCenter.z ? (distance - minDistance) : 1)/ getDistance(distance))); //positive value
+					totalDistance += distance;
 				}
 				}
 			}
 			}
+			distances[zone.second] = totalDistance;
 			//separate overlaping zones
 			//separate overlaping zones
 			for (auto otherZone : zones)
 			for (auto otherZone : zones)
 			{
 			{
@@ -139,7 +143,7 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
 				float minDistance = (zone.second->getSize() + otherZone.second->getSize())/mapSize * zoneScale;
 				float minDistance = (zone.second->getSize() + otherZone.second->getSize())/mapSize * zoneScale;
 				if (distance < minDistance)
 				if (distance < minDistance)
 				{
 				{
-					forceVector -= (otherZoneCenter - pos) / getDistance(distance); //negative value
+					forceVector -= (((otherZoneCenter - pos)*(minDistance - distance)) / getDistance(distance)); //negative value
 				}
 				}
 			}
 			}
 
 
@@ -178,7 +182,52 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
 		{
 		{
 			zone.first->setCenter (zone.first->getCenter() + zone.second);
 			zone.first->setCenter (zone.first->getCenter() + zone.second);
 		}
 		}
-		zoneScale *= inflateModifier; //increase size
+
+		//now perform drastic movement of zone that is completely not linked
+		float maxRatio = 0;
+		CRmgTemplateZone * distantZone = nullptr;
+
+		float totalDistance = 0;
+		for (auto zone : distances) //find most misplaced zone
+		{
+			totalDistance += zone.second;
+			float ratio = zone.second / forces[zone.first].mag(); //if distance to actual movement is long, the zone is misplaced
+			if (ratio > maxRatio)
+			{
+				maxRatio = ratio;
+				distantZone = zone.first;
+			}
+		}
+		logGlobal->traceStream() << boost::format("Total distance between zones in this iteration: %2.2f, Worst distance/movement ratio: %3.2f") % totalDistance % maxRatio;
+		
+		if (maxRatio > 100) //TODO: scale?
+		{
+			//find most distant zone that should be attracted and move inside it
+			
+			CRmgTemplateZone * targetZone = nullptr;
+			float maxDistance = 0;
+			float3 ourCenter = distantZone->getCenter();
+			for (auto con : distantZone->getConnections())
+			{
+				auto otherZone = zones[con];
+				float distance = otherZone->getCenter().dist2dSQ(ourCenter);
+				if (distance > maxDistance)
+				{
+					maxDistance = distance;
+					targetZone = otherZone;
+				}
+			}
+			float3 vec = targetZone->getCenter() - ourCenter;
+			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") %
+				distantZone->getId() % ourCenter() % targetZone->getId() % targetZone->getCenter()() % maxDistance;
+			logGlobal->traceStream() << boost::format("direction is %s") % vec();
+
+			distantZone->setCenter(targetZone->getCenter() - vec.unitVector() * newDistanceBetweenZones); //zones should now overlap by half size
+			logGlobal->traceStream() << boost::format("New distance %f") % targetZone->getCenter().dist2d(distantZone->getCenter());
+		}
+
+		zoneScale *= inflateModifier; //increase size of zones so they
 	}
 	}
 	for (auto zone : zones) //finalize zone positions
 	for (auto zone : zones) //finalize zone positions
 	{
 	{

+ 8 - 0
lib/rmg/float3.h

@@ -47,6 +47,14 @@ public:
 		const double dy = (y - o.y);
 		const double dy = (y - o.y);
 		return dx*dx + dy*dy;
 		return dx*dx + dy*dy;
 	}
 	}
+	double mag() const
+	{
+		return sqrt(x*x + y*y);
+	}
+	float3 unitVector() const
+	{
+		return float3(x, y, z) / mag();
+	}
 	// returns distance on Oxy plane (z coord is not used)
 	// returns distance on Oxy plane (z coord is not used)
 	double dist2d(const float3 &other) const { return std::sqrt(dist2dSQ(other)); }
 	double dist2d(const float3 &other) const { return std::sqrt(dist2dSQ(other)); }