Răsfoiți Sursa

Route roads away from zone borders

Tomasz Zieliński 1 an în urmă
părinte
comite
a6fa6855dc
3 a modificat fișierele cu 24 adăugiri și 6 ștergeri
  1. 5 0
      lib/rmg/RmgArea.cpp
  2. 1 0
      lib/rmg/RmgArea.h
  3. 18 6
      lib/rmg/modificators/RoadPlacer.cpp

+ 5 - 0
lib/rmg/RmgArea.cpp

@@ -254,6 +254,11 @@ bool Area::overlap(const Area & area) const
 	return overlap(area.getTilesVector());
 }
 
+int Area::distance(const int3 & tile) const
+{
+	return nearest(tile).dist2d(tile);
+}
+
 int Area::distanceSqr(const int3 & tile) const
 {
 	return nearest(tile).dist2dSQ(tile);

+ 1 - 0
lib/rmg/RmgArea.h

@@ -51,6 +51,7 @@ namespace rmg
 		bool contains(const Area & area) const;
 		bool overlap(const Area & area) const;
 		bool overlap(const std::vector<int3> & tiles) const;
+		int distance(const int3 & tile) const;
 		int distanceSqr(const int3 & tile) const;
 		int distanceSqr(const Area & area) const;
 		int3 nearest(const int3 & tile) const;

+ 18 - 6
lib/rmg/modificators/RoadPlacer.cpp

@@ -68,12 +68,14 @@ bool RoadPlacer::createRoad(const int3 & dst)
 {
 	auto searchArea = zone.areaPossible() + zone.freePaths() + areaRoads + roads;
 
+	rmg::Area border(zone.area()->getBorder());
+
 	rmg::Path path(searchArea);
 	path.connect(roads);
 
 	const float VISITABLE_PENALTY = 1.33f;
 
-	auto simpleRoutig = [this, VISITABLE_PENALTY](const int3& src, const int3& dst)
+	auto simpleRoutig = [this, &border, &VISITABLE_PENALTY](const int3& src, const int3& dst)
 	{
 		if(areaIsolated().contains(dst))
 		{
@@ -81,13 +83,19 @@ bool RoadPlacer::createRoad(const int3 & dst)
 		}
 		else
 		{
-			float weight = dst.dist2dSQ(src);
-			auto ret =  weight * weight;
+			float ret = dst.dist2d(src);
+			
+			// TODO: Prefer zig-zag connections
 
 			if (visitableTiles.contains(src) || visitableTiles.contains(dst))
 			{
 				ret *= VISITABLE_PENALTY;
 			}
+			float dist = border.distance(dst);
+			if(dist > 1)
+			{
+				ret /= dist;
+			}
 			return ret;
 		}
 	};
@@ -95,7 +103,7 @@ bool RoadPlacer::createRoad(const int3 & dst)
 	auto res = path.search(dst, true, simpleRoutig);
 	if(!res.valid())
 	{
-		auto desperateRoutig = [this, VISITABLE_PENALTY](const int3& src, const int3& dst) -> float
+		auto desperateRoutig = [this, &border, &VISITABLE_PENALTY](const int3& src, const int3& dst) -> float
 		{
 			//Do not allow connections straight up through object not visitable from top
 			if(std::abs((src - dst).y) == 1)
@@ -113,13 +121,17 @@ bool RoadPlacer::createRoad(const int3 & dst)
 				}
 			}
 
-			float weight = dst.dist2dSQ(src);
+			auto ret = dst.dist2d(src);
 
-			auto ret =  weight * weight;
 			if (visitableTiles.contains(src) || visitableTiles.contains(dst))
 			{
 				ret *= VISITABLE_PENALTY;
 			}
+			float dist = border.distance(dst);
+			if(dist > 1)
+			{
+				ret /= dist;
+			}
 			return ret;
 		};
 		res = path.search(dst, false, desperateRoutig);