mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-19 21:10:12 +02:00
Fix crash with empty zone
This commit is contained in:
parent
263d439605
commit
c6a9d94630
@ -906,27 +906,36 @@ void CZonePlacer::assignZones(CRandomGenerator * rand)
|
||||
for(const auto & zone : zones)
|
||||
zone.second->clearTiles(); //now populate them again
|
||||
|
||||
// Assign zones to closest Penrose vertex
|
||||
PenroseTiling penrose;
|
||||
auto vertices = penrose.generatePenroseTiling(zones.size() / map.levels(), rand);
|
||||
|
||||
std::map<std::shared_ptr<Zone>, std::set<int3>> vertexMapping;
|
||||
|
||||
for (const auto & vertex : vertices)
|
||||
for (int level = 0; level < levels; level++)
|
||||
{
|
||||
distances.clear();
|
||||
for(const auto & zone : zones)
|
||||
//Create different tiling for each level
|
||||
// Assign zones to closest Penrose vertex
|
||||
// TODO: Count zones on a level exactly?
|
||||
|
||||
auto vertices = penrose.generatePenroseTiling(zones.size() / map.levels(), rand);
|
||||
|
||||
std::map<std::shared_ptr<Zone>, std::set<int3>> vertexMapping;
|
||||
|
||||
for (const auto & vertex : vertices)
|
||||
{
|
||||
distances.emplace_back(zone.second, zone.second->getCenter().dist2dSQ(float3(vertex.x(), vertex.y(), 0)));
|
||||
distances.clear();
|
||||
for(const auto & zone : zones)
|
||||
{
|
||||
if (zone.second->isUnderground() == level)
|
||||
{
|
||||
// FIXME: Only take into account zones on the same level as vertex
|
||||
// TODO: Create separate mapping for zones on different levels
|
||||
distances.emplace_back(zone.second, zone.second->getCenter().dist2dSQ(float3(vertex.x(), vertex.y(), level)));
|
||||
}
|
||||
}
|
||||
auto closestZone = boost::min_element(distances, compareByDistance)->first;
|
||||
|
||||
vertexMapping[closestZone].insert(int3(vertex.x() * width, vertex.y() * height, level)); //Closest vertex belongs to zone
|
||||
}
|
||||
auto closestZone = boost::min_element(distances, compareByDistance)->first;
|
||||
|
||||
vertexMapping[closestZone].insert(int3(vertex.x() * width, vertex.y() * height, closestZone->getPos().z)); //Closest vertex belongs to zone
|
||||
}
|
||||
|
||||
//Assign actual tiles to each zone
|
||||
for (pos.z = 0; pos.z < levels; pos.z++)
|
||||
{
|
||||
//Assign actual tiles to each zone
|
||||
pos.z = level;
|
||||
for (pos.x = 0; pos.x < width; pos.x++)
|
||||
{
|
||||
for (pos.y = 0; pos.y < height; pos.y++)
|
||||
@ -937,27 +946,38 @@ void CZonePlacer::assignZones(CRandomGenerator * rand)
|
||||
auto zone = zoneVertex.first;
|
||||
for (const auto & vertex : zoneVertex.second)
|
||||
{
|
||||
if (zone->getCenter().z == pos.z)
|
||||
if (zone->isUnderground() == level)
|
||||
distances.emplace_back(zone, metric(pos, vertex));
|
||||
else
|
||||
distances.emplace_back(zone, std::numeric_limits<float>::max());
|
||||
}
|
||||
}
|
||||
|
||||
//Tile closes to vertex belongs to zone
|
||||
//Tile closest to vertex belongs to zone
|
||||
auto closestZone = boost::min_element(distances, simpleCompareByDistance)->first;
|
||||
closestZone->area().add(pos);
|
||||
map.setZoneID(pos, closestZone->getId());
|
||||
}
|
||||
}
|
||||
|
||||
for(const auto & zone : zones)
|
||||
{
|
||||
if(zone.second->isUnderground() == level && zone.second->area().empty())
|
||||
{
|
||||
// FIXME: Some vertices are duplicated, but it's not a source of problem
|
||||
logGlobal->error("Zone %d at %s is empty, dumping Penrose tiling", zone.second->getId(), zone.second->getCenter().toString());
|
||||
for (const auto & vertex : vertices)
|
||||
{
|
||||
logGlobal->warn("Penrose Vertex: %s", vertex.toString());
|
||||
}
|
||||
throw rmgException("Empty zone after Penrose tiling");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//set position (town position) to center of mass of irregular zone
|
||||
for(const auto & zone : zones)
|
||||
{
|
||||
if(zone.second->area().empty())
|
||||
throw rmgException("Empty zone after Penrose tiling");
|
||||
|
||||
moveZoneToCenterOfMass(zone.second);
|
||||
|
||||
//TODO: similiar for islands
|
||||
|
@ -38,6 +38,16 @@ bool Point2D::operator < (const Point2D& other) const
|
||||
}
|
||||
}
|
||||
|
||||
std::string Point2D::toString() const
|
||||
{
|
||||
//Performance is important here
|
||||
std::string result = "(" +
|
||||
std::to_string(this->x()) + " " +
|
||||
std::to_string(this->y()) + ")";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Triangle::Triangle(bool t_123, const TIndices & inds):
|
||||
tiling(t_123),
|
||||
indices(inds)
|
||||
@ -57,14 +67,14 @@ Triangle::~Triangle()
|
||||
|
||||
Point2D Point2D::rotated(float radians) const
|
||||
{
|
||||
float cosAngle = cos(radians);
|
||||
float sinAngle = sin(radians);
|
||||
float cosAngle = cos(radians);
|
||||
float sinAngle = sin(radians);
|
||||
|
||||
// Apply rotation matrix transformation
|
||||
float newX = x() * cosAngle - y() * sinAngle;
|
||||
float newY = x() * sinAngle + y() * cosAngle;
|
||||
// Apply rotation matrix transformation
|
||||
float newX = x() * cosAngle - y() * sinAngle;
|
||||
float newY = x() * sinAngle + y() * cosAngle;
|
||||
|
||||
return Point2D(newX, newY);
|
||||
return Point2D(newX, newY);
|
||||
}
|
||||
|
||||
void PenroseTiling::split(Triangle& p, std::vector<Point2D>& points,
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
Point2D rotated(float radians) const;
|
||||
|
||||
bool operator < (const Point2D& other) const;
|
||||
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
Point2D rotatePoint(const Point2D& point, double radians, const Point2D& origin);
|
||||
|
Loading…
x
Reference in New Issue
Block a user