-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Polygon and MultiPolygon support? #5
Comments
Hello, I do not have time to implement this right now, but plan to do so in the future. Support for polygons with holes can be added relatively easily by converting them in preprocessing to simple polygons. For MultiPolygons, the partial polygons can simply be individually queried/registered by the CDE. An additional preprocessing step could be to merge polygons that are "touching", again by adding a degenerate edge. |
Would be nice to have then, a new propperty Name/Filename for the Items, that are also given out on the result. Only for the safty definition, I have sometimes the problem that the index is not the correct one form the input, when I try to work with 2 Apps that read the result, because the JSON is maybe parsed different. I need to check that. |
I have played around with it in Javascript and then asked the ChatGPT if he can Translate me the code to Rust: JS: https://jsfiddle.net/zwg83qje/ use std::f64;
type Point = (f64, f64);
/// Berechnet die Fläche eines Polygons, um die Laufrichtung zu bestimmen.
fn calculate_polygon_area(points: &Vec<Point>) -> f64 {
let mut area = 0.0;
for i in 0..points.len() - 1 {
let (x1, y1) = points[i];
let (x2, y2) = points[i + 1];
area += x1 * y2 - x2 * y1;
}
area / 2.0
}
/// Dreht die Punkte eines Polygons um.
fn reverse_polygon(points: &mut Vec<Point>) {
points.reverse();
}
/// Berechnet einen Punkt auf einer Linie mit minimaler Trennung.
fn interpolate_point(p1: Point, p2: Point, t: f64) -> Point {
(p1.0 + t * (p2.0 - p1.0), p1.1 + t * (p2.1 - p1.1))
}
/// Berechnet die Distanz zwischen zwei Punkten.
fn distance(p1: Point, p2: Point) -> f64 {
((p1.0 - p2.0).powi(2) + (p1.1 - p2.1).powi(2)).sqrt()
}
/// Verknüpft ein Loch mit der äußeren Umrandung eines Polygons.
fn connect_hole_to_outer(
mut outer_ring: Vec<Point>,
mut hole: Vec<Point>,
separation: f64,
) -> Vec<Point> {
// Sicherstellen, dass die Laufrichtungen korrekt sind
if calculate_polygon_area(&outer_ring) < 0.0 {
reverse_polygon(&mut outer_ring); // Äußere Umrandung CCW
}
if calculate_polygon_area(&hole) > 0.0 {
reverse_polygon(&mut hole); // Loch CW
}
let mut min_distance = f64::INFINITY;
let mut closest_outer_point = (0.0, 0.0);
let mut closest_hole_point = (0.0, 0.0);
let mut outer_index = 0;
// Finde die engsten Punkte zwischen Loch und äußerem Ring
for (i, &outer_point) in outer_ring.iter().enumerate() {
for &hole_point in &hole {
let dist = distance(outer_point, hole_point);
if dist < min_distance {
min_distance = dist;
closest_outer_point = outer_point;
closest_hole_point = hole_point;
outer_index = i;
}
}
}
// Erstelle zwei Verbindungspunkte mit minimalem Abstand
let next_outer_point = outer_ring[(outer_index + 1) % outer_ring.len()];
let connection_point1 = interpolate_point(closest_outer_point, next_outer_point, separation);
let connection_point2 = interpolate_point(closest_outer_point, next_outer_point, -separation);
// Neues Polygon durch Hinzufügen der Verbindungspunkte erstellen
let mut updated_polygon = vec![];
updated_polygon.extend(&outer_ring[..=outer_index]); // Äußere Punkte bis zur Verbindung
updated_polygon.push(connection_point1); // Erster Verbindungspunkt
updated_polygon.push(closest_hole_point); // Punkt vom Loch
updated_polygon.extend(hole); // Punkte des Lochs
updated_polygon.push(closest_hole_point); // Zurück zum Punkt vom Loch
updated_polygon.push(connection_point2); // Zweiter Verbindungspunkt
updated_polygon.extend(&outer_ring[outer_index + 1..]); // Rest des äußeren Rings
updated_polygon
}
/// Konvertiert Punkte in eine Path-Syntax (SVG-kompatibel).
fn points_to_path(points: &Vec<Point>) -> String {
points
.iter()
.map(|&(x, y)| format!("{:.6},{:.6}", x, y))
.collect::<Vec<_>>()
.join(" ")
}
fn main() {
// Beispiel: Äußerer Ring und Loch
let outer_ring = vec![
(10.0, 10.0),
(90.0, 10.0),
(90.0, 90.0),
(10.0, 90.0),
(10.0, 10.0),
];
let hole = vec![
(40.0, 40.0),
(60.0, 40.0),
(60.0, 60.0),
(40.0, 60.0),
(40.0, 40.0),
];
// Konvertiere in ein einfaches Polygon
let simple_polygon = connect_hole_to_outer(outer_ring, hole, 1e-8);
// Ausgabe als SVG-Pfad
let path_data = points_to_path(&simple_polygon);
println!("<path d=\"M {} Z\" fill=\"blue\" stroke=\"black\" stroke-width=\"0.5\" />", path_data);
}
} Would this work like this? |
Hello, is there anything in the works? Unfortunately it's not implemented yet.
Would love to help, but rust is currently in the early stages for me. Would be very helpful if things could move forward here.
Many thanks & regards
The text was updated successfully, but these errors were encountered: