use super::super::bezier::*;
use super::super::bezier::path::*;
use std::fmt::Write;
pub fn graph_path_svg_string<P: Coordinate+Coordinate2D>(path: &GraphPath<P, PathLabel>, rays: Vec<(P, P)>) -> String {
let mut result = String::new();
let bounds = path.all_edges().fold(Bounds::empty(), |a, b| a.union_bounds(b.bounding_box()));
let offset = bounds.min();
let scale = 1000.0/(bounds.max() - bounds.min()).x();
let mut index = 0;
for kinds in vec![ vec![ GraphPathEdgeKind::Uncategorised, GraphPathEdgeKind::Visited, GraphPathEdgeKind::Interior ], vec![ GraphPathEdgeKind::Exterior ] ] {
for edge in path.all_edges() {
if !kinds.contains(&edge.kind()) {
continue;
}
let start_point = edge.start_point();
let end_point = edge.end_point();
let (cp1, cp2) = edge.control_points();
write!(result, "<!-- {}: Curve::from_points(Coord2({}, {}), (Coord2({}, {}), Coord2({}, {})), Coord2({}, {})) -->\n",
index,
start_point.x(), start_point.y(),
cp1.x(), cp1.y(),
cp2.x(), cp2.y(),
end_point.x(), end_point.y()).unwrap();
let start_point = (start_point - offset)*scale;
let end_point = (end_point - offset)*scale;
let cp1 = (cp1 - offset)*scale;
let cp2 = (cp2 - offset)*scale;
let kind = match edge.kind() {
GraphPathEdgeKind::Uncategorised => "yellow",
GraphPathEdgeKind::Visited => "red",
GraphPathEdgeKind::Exterior => "blue",
GraphPathEdgeKind::Interior => "green"
};
write!(result, "<path d=\"M {} {} C {} {}, {} {}, {} {}\" fill=\"transparent\" stroke-width=\"1\" stroke=\"{}\" />\n",
start_point.x(), start_point.y(),
cp1.x(), cp1.y(),
cp2.x(), cp2.y(),
end_point.x(), end_point.y(),
kind).unwrap();
write!(result, "<circle cx=\"{}\" cy=\"{}\" r=\"1.0\" fill=\"transparent\" stroke=\"magenta\" />\n", end_point.x(), end_point.y()).unwrap();
write!(result, "<text style=\"font-size: 8pt\" dx=\"{}\" dy=\"{}\">{} <- {} - {}</text>\n", end_point.x()+4.0, end_point.y()+8.0, edge.end_point_index(), edge.start_point_index(), index).unwrap();
index += 1;
}
}
for (p1, p2) in rays {
write!(result, "<!-- Ray (Coord2({}, {}), Coord2({}, {})) -->\n", p1.x(), p1.y(), p2.x(), p2.y()).unwrap();
let collisions = path.ray_collisions(&(p1, p2));
write!(result, "<!-- {} collisions -->", collisions.len()).unwrap();
let p1 = (p1 - offset) * scale;
let p2 = (p2 - offset) * scale;
let point_offset = p2-p1;
let p1 = p1 - (point_offset * 1000.0);
let p2 = p2 + (point_offset * 1000.0);
write!(result, "<path d=\"M {} {} L {} {}\" fill=\"transparent\" stroke-width=\"1\" stroke=\"red\" />\n",
p1.x(), p1.y(),
p2.x(), p2.y()).unwrap();
let ray_direction = p2-p1;
let mut collision_count = 0;
let mut collision_num = 0;
for (collision, curve_t, _line_t, pos) in collisions {
let edge = collision.edge();
let PathLabel(path_number, direction) = path.edge_label(edge);
let normal = path.get_edge(edge).normal_at_pos(curve_t);
let side = ray_direction.dot(&normal).signum() as i32;
let side = match direction {
PathDirection::Clockwise => { side },
PathDirection::Anticlockwise => { -side }
};
collision_count += side;
collision_num += 1;
let pos = (pos - offset)*scale;
let edge = path.get_edge(edge);
let start_point = edge.start_point();
let end_point = edge.end_point();
let (cp1, cp2) = edge.control_points();
write!(result, "<!-- Collision {} ({}): Curve::from_points(Coord2({}, {}), (Coord2({}, {}), Coord2({}, {})), Coord2({}, {})) -->\n",
collision_num, path_number,
start_point.x(), start_point.y(),
cp1.x(), cp1.y(),
cp2.x(), cp2.y(),
end_point.x(), end_point.y()).unwrap();
let start_point = (start_point - offset)*scale;
let end_point = (end_point - offset)*scale;
let cp1 = (cp1 - offset)*scale;
let cp2 = (cp2 - offset)*scale;
write!(result, "<path d=\"M {} {} C {} {}, {} {}, {} {}\" fill=\"transparent\" stroke-width=\"1\" stroke=\"{}\" />\n",
start_point.x(), start_point.y(),
cp1.x(), cp1.y(),
cp2.x(), cp2.y(),
end_point.x(), end_point.y(),
"cyan").unwrap();
write!(result, "<circle cx=\"{}\" cy=\"{}\" r=\"1.0\" fill=\"transparent\" stroke=\"red\" />\n", pos.x(), pos.y()).unwrap();
write!(result, "<text style=\"font-size: 6pt\" dx=\"{}\" dy=\"{}\">{}: C{} ({})</text>\n", pos.x() + 2.0, pos.y()+3.0, collision_num, collision_count, side).unwrap();
}
}
result
}