mirror of
https://github.com/vcmi/vcmi.git
synced 2025-09-16 09:26:28 +02:00
Merge pull request #3924 from vcmi/fix_road_routing
Route roads away from zone borders
This commit is contained in:
@@ -254,6 +254,11 @@ bool Area::overlap(const Area & area) const
|
|||||||
return overlap(area.getTilesVector());
|
return overlap(area.getTilesVector());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Area::distance(const int3 & tile) const
|
||||||
|
{
|
||||||
|
return nearest(tile).dist2d(tile);
|
||||||
|
}
|
||||||
|
|
||||||
int Area::distanceSqr(const int3 & tile) const
|
int Area::distanceSqr(const int3 & tile) const
|
||||||
{
|
{
|
||||||
return nearest(tile).dist2dSQ(tile);
|
return nearest(tile).dist2dSQ(tile);
|
||||||
|
@@ -51,6 +51,7 @@ namespace rmg
|
|||||||
bool contains(const Area & area) const;
|
bool contains(const Area & area) const;
|
||||||
bool overlap(const Area & area) const;
|
bool overlap(const Area & area) const;
|
||||||
bool overlap(const std::vector<int3> & tiles) const;
|
bool overlap(const std::vector<int3> & tiles) const;
|
||||||
|
int distance(const int3 & tile) const;
|
||||||
int distanceSqr(const int3 & tile) const;
|
int distanceSqr(const int3 & tile) const;
|
||||||
int distanceSqr(const Area & area) const;
|
int distanceSqr(const Area & area) const;
|
||||||
int3 nearest(const int3 & tile) const;
|
int3 nearest(const int3 & tile) const;
|
||||||
|
@@ -64,16 +64,16 @@ const rmg::Area & RoadPlacer::getRoads() const
|
|||||||
return roads;
|
return roads;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RoadPlacer::createRoad(const int3 & dst)
|
bool RoadPlacer::createRoad(const int3 & destination)
|
||||||
{
|
{
|
||||||
auto searchArea = zone.areaPossible() + zone.freePaths() + areaRoads + roads;
|
auto searchArea = zone.areaPossible() + zone.freePaths() + areaRoads + roads;
|
||||||
|
|
||||||
|
rmg::Area border(zone.area()->getBorder());
|
||||||
|
|
||||||
rmg::Path path(searchArea);
|
rmg::Path path(searchArea);
|
||||||
path.connect(roads);
|
path.connect(roads);
|
||||||
|
|
||||||
const float VISITABLE_PENALTY = 1.33f;
|
auto simpleRoutig = [this, &border](const int3& src, const int3& dst)
|
||||||
|
|
||||||
auto simpleRoutig = [this, VISITABLE_PENALTY](const int3& src, const int3& dst)
|
|
||||||
{
|
{
|
||||||
if(areaIsolated().contains(dst))
|
if(areaIsolated().contains(dst))
|
||||||
{
|
{
|
||||||
@@ -81,52 +81,28 @@ bool RoadPlacer::createRoad(const int3 & dst)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float weight = dst.dist2dSQ(src);
|
float ret = dst.dist2d(src);
|
||||||
auto ret = weight * weight;
|
|
||||||
|
|
||||||
if (visitableTiles.contains(src) || visitableTiles.contains(dst))
|
if (visitableTiles.contains(src) || visitableTiles.contains(dst))
|
||||||
{
|
{
|
||||||
ret *= VISITABLE_PENALTY;
|
ret *= VISITABLE_PENALTY;
|
||||||
}
|
}
|
||||||
|
float dist = border.distance(dst);
|
||||||
|
if(dist > 1)
|
||||||
|
{
|
||||||
|
ret /= dist;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto res = path.search(dst, true, simpleRoutig);
|
auto res = path.search(destination, true, simpleRoutig);
|
||||||
if(!res.valid())
|
if(!res.valid())
|
||||||
{
|
{
|
||||||
auto desperateRoutig = [this, VISITABLE_PENALTY](const int3& src, const int3& dst) -> float
|
res = createRoadDesperate(path, destination);
|
||||||
|
if (!res.valid())
|
||||||
{
|
{
|
||||||
//Do not allow connections straight up through object not visitable from top
|
logGlobal->warn("Failed to create road to node %s", destination.toString());
|
||||||
if(std::abs((src - dst).y) == 1)
|
|
||||||
{
|
|
||||||
if(areaIsolated().contains(dst) || areaIsolated().contains(src))
|
|
||||||
{
|
|
||||||
return 1e12;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(areaIsolated().contains(dst))
|
|
||||||
{
|
|
||||||
return 1e6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float weight = dst.dist2dSQ(src);
|
|
||||||
|
|
||||||
auto ret = weight * weight;
|
|
||||||
if (visitableTiles.contains(src) || visitableTiles.contains(dst))
|
|
||||||
{
|
|
||||||
ret *= VISITABLE_PENALTY;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
res = path.search(dst, false, desperateRoutig);
|
|
||||||
|
|
||||||
if(!res.valid())
|
|
||||||
{
|
|
||||||
logGlobal->warn("Failed to create road to node %s", dst.toString());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,6 +111,38 @@ bool RoadPlacer::createRoad(const int3 & dst)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rmg::Path RoadPlacer::createRoadDesperate(rmg::Path & path, const int3 & destination)
|
||||||
|
{
|
||||||
|
auto desperateRoutig = [this](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)
|
||||||
|
{
|
||||||
|
if(areaIsolated().contains(dst) || areaIsolated().contains(src))
|
||||||
|
{
|
||||||
|
return 1e12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(areaIsolated().contains(dst))
|
||||||
|
{
|
||||||
|
return 1e6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float weight = dst.dist2dSQ(src);
|
||||||
|
auto ret = weight * weight; // Still prefer straight paths
|
||||||
|
|
||||||
|
if (visitableTiles.contains(src) || visitableTiles.contains(dst))
|
||||||
|
{
|
||||||
|
ret *= VISITABLE_PENALTY;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
return path.search(destination, false, desperateRoutig);
|
||||||
|
}
|
||||||
|
|
||||||
void RoadPlacer::drawRoads(bool secondary)
|
void RoadPlacer::drawRoads(bool secondary)
|
||||||
{
|
{
|
||||||
//Do not draw roads on underground rock or water
|
//Do not draw roads on underground rock or water
|
||||||
|
@@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
const float VISITABLE_PENALTY = 1.33f;
|
||||||
|
|
||||||
class RoadPlacer: public Modificator
|
class RoadPlacer: public Modificator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -34,6 +36,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool createRoad(const int3 & dst);
|
bool createRoad(const int3 & dst);
|
||||||
|
rmg::Path createRoadDesperate(rmg::Path & path, const int3 & destination);
|
||||||
void drawRoads(bool secondary = false); //actually updates tiles
|
void drawRoads(bool secondary = false); //actually updates tiles
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Reference in New Issue
Block a user