mirror of
https://github.com/vcmi/vcmi.git
synced 2025-12-03 23:19:22 +02:00
code review: renaming
This commit is contained in:
133
mapeditor/templateeditor/GeometryAlgorithm.cpp
Normal file
133
mapeditor/templateeditor/GeometryAlgorithm.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* GeometryAlgorithm.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
|
||||
#include "GeometryAlgorithm.h"
|
||||
|
||||
double GeometryAlgorithm::distance(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
return std::sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)) + 1e-9;
|
||||
}
|
||||
|
||||
bool GeometryAlgorithm::edgesIntersect(const Node& a, const Node& b, const Node& c, const Node& d)
|
||||
{
|
||||
auto cross = [](double x1, double y1, double x2, double y2) {
|
||||
return x1 * y2 - y1 * x2;
|
||||
};
|
||||
|
||||
double dx1 = b.x - a.x, dy1 = b.y - a.y;
|
||||
double dx2 = d.x - c.x, dy2 = d.y - c.y;
|
||||
|
||||
double delta = cross(dx1, dy1, dx2, dy2);
|
||||
if (std::abs(delta) < 1e-10) return false; // Parallel
|
||||
|
||||
// Compute intersection
|
||||
double s = cross(c.x - a.x, c.y - a.y, dx2, dy2) / delta;
|
||||
double t = cross(c.x - a.x, c.y - a.y, dx1, dy1) / delta;
|
||||
|
||||
return s > 0 && s < 1 && t > 0 && t < 1;
|
||||
}
|
||||
|
||||
void GeometryAlgorithm::forceDirectedLayout(std::vector<Node> & nodes, const std::vector<Edge> & edges, int iterations, double width, double height)
|
||||
{
|
||||
const double area = width * height;
|
||||
const double k = std::sqrt(area / nodes.size());
|
||||
|
||||
for (int it = 0; it < iterations; ++it)
|
||||
{
|
||||
// Reset forces
|
||||
for (auto& node : nodes)
|
||||
node.dx = node.dy = 0;
|
||||
|
||||
// Repulsive forces
|
||||
for (size_t i = 0; i < nodes.size(); ++i)
|
||||
{
|
||||
for (size_t j = i + 1; j < nodes.size(); ++j)
|
||||
{
|
||||
double dx = nodes[i].x - nodes[j].x;
|
||||
double dy = nodes[i].y - nodes[j].y;
|
||||
double dist = distance(nodes[i].x, nodes[i].y, nodes[j].x, nodes[j].y);
|
||||
double force = (k * k) / dist;
|
||||
|
||||
nodes[i].dx += (dx / dist) * force;
|
||||
nodes[i].dy += (dy / dist) * force;
|
||||
nodes[j].dx -= (dx / dist) * force;
|
||||
nodes[j].dy -= (dy / dist) * force;
|
||||
}
|
||||
}
|
||||
|
||||
// Attractive forces
|
||||
for (const auto& edge : edges)
|
||||
{
|
||||
Node& u = nodes[edge.from];
|
||||
Node& v = nodes[edge.to];
|
||||
double dx = u.x - v.x;
|
||||
double dy = u.y - v.y;
|
||||
double dist = distance(u.x, u.y, v.x, v.y);
|
||||
double force = (dist * dist) / k;
|
||||
|
||||
double fx = (dx / dist) * force;
|
||||
double fy = (dy / dist) * force;
|
||||
|
||||
u.dx -= fx;
|
||||
u.dy -= fy;
|
||||
v.dx += fx;
|
||||
v.dy += fy;
|
||||
}
|
||||
|
||||
// Edge crossing penalty
|
||||
for (size_t i = 0; i < edges.size(); ++i) {
|
||||
for (size_t j = i + 1; j < edges.size(); ++j) {
|
||||
const Edge& e1 = edges[i];
|
||||
const Edge& e2 = edges[j];
|
||||
|
||||
if (e1.from == e2.from || e1.from == e2.to ||
|
||||
e1.to == e2.from || e1.to == e2.to)
|
||||
continue; // Skip if they share nodes
|
||||
|
||||
Node& a = nodes[e1.from];
|
||||
Node& b = nodes[e1.to];
|
||||
Node& c = nodes[e2.from];
|
||||
Node& d = nodes[e2.to];
|
||||
|
||||
if (edgesIntersect(a, b, c, d)) {
|
||||
double strength = 0.05;
|
||||
|
||||
a.dx += strength * (a.x - c.x);
|
||||
a.dy += strength * (a.y - c.y);
|
||||
b.dx += strength * (b.x - d.x);
|
||||
b.dy += strength * (b.y - d.y);
|
||||
c.dx += strength * (c.x - a.x);
|
||||
c.dy += strength * (c.y - a.y);
|
||||
d.dx += strength * (d.x - b.x);
|
||||
d.dy += strength * (d.y - b.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply displacement
|
||||
for (auto& node : nodes)
|
||||
{
|
||||
node.x += std::max(-5.0, std::min(5.0, node.dx));
|
||||
node.y += std::max(-5.0, std::min(5.0, node.dy));
|
||||
|
||||
// Keep within bounds
|
||||
node.x = std::min(width, std::max(0.0, node.x));
|
||||
node.y = std::min(height, std::max(0.0, node.y));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& node : nodes)
|
||||
{
|
||||
// Center around 0
|
||||
node.x -= width / 2;
|
||||
node.y -= height / 2;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user