mirror of https://codeberg.org/topola/topola.git
router: have two navvertices, CW and CCW, for each trianvertex
This commit is contained in:
parent
d34554f075
commit
0777b781f4
|
|
@ -127,21 +127,21 @@ impl<M: MesadataTrait> Autorouter<M> {
|
|||
.filter(|ratline| {
|
||||
let (source, target) = self.ratsnest.graph().edge_endpoints(*ratline).unwrap();
|
||||
|
||||
let source_vertex = self
|
||||
let source_navvertex = self
|
||||
.ratsnest
|
||||
.graph()
|
||||
.node_weight(source)
|
||||
.unwrap()
|
||||
.node_index();
|
||||
let to_vertex = self
|
||||
let to_navvertex = self
|
||||
.ratsnest
|
||||
.graph()
|
||||
.node_weight(target)
|
||||
.unwrap()
|
||||
.node_index();
|
||||
|
||||
selection.contains_node(&self.board, source_vertex.into())
|
||||
&& selection.contains_node(&self.board, to_vertex.into())
|
||||
selection.contains_node(&self.board, source_navvertex.into())
|
||||
&& selection.contains_node(&self.board, to_navvertex.into())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@ pub enum DrawException {
|
|||
#[error("cannot finish in {0:?}")]
|
||||
CannotFinishIn(FixedDotIndex, #[source] LayoutException),
|
||||
#[error("cannot wrap around {0:?}")]
|
||||
// neither of the exceptions is the source on its own, might be useful to give them names?
|
||||
CannotWrapAround(WraparoundableIndex, LayoutException, LayoutException),
|
||||
CannotWrapAround(WraparoundableIndex, #[source] LayoutException),
|
||||
}
|
||||
|
||||
pub struct Draw<'a, R: RulesTrait> {
|
||||
|
|
@ -98,43 +97,25 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
|
|||
&mut self,
|
||||
head: Head,
|
||||
around: FixedDotIndex,
|
||||
cw: bool,
|
||||
width: f64,
|
||||
) -> Result<CaneHead, DrawException> {
|
||||
let mut tangents = self
|
||||
let tangent = self
|
||||
.guide()
|
||||
.head_around_dot_segments(&head, around.into(), width)?;
|
||||
.head_around_dot_segment(&head, around.into(), cw, width)?;
|
||||
let offset = self
|
||||
.guide()
|
||||
.head_around_dot_offset(&head, around.into(), width);
|
||||
let mut dirs = [true, false];
|
||||
|
||||
if tangents.1.euclidean_length() < tangents.0.euclidean_length() {
|
||||
tangents = (tangents.1, tangents.0);
|
||||
dirs = [false, true];
|
||||
}
|
||||
|
||||
let mut errs = vec![];
|
||||
|
||||
for (i, tangent) in [tangents.0, tangents.1].iter().enumerate() {
|
||||
match self.cane_around(
|
||||
head,
|
||||
around.into(),
|
||||
tangent.start_point(),
|
||||
tangent.end_point(),
|
||||
dirs[i],
|
||||
width,
|
||||
offset,
|
||||
) {
|
||||
Ok(ok) => return Ok(ok),
|
||||
Err(err) => errs.push(err),
|
||||
}
|
||||
}
|
||||
|
||||
Err(DrawException::CannotWrapAround(
|
||||
self.cane_around(
|
||||
head,
|
||||
around.into(),
|
||||
errs[0],
|
||||
errs[1],
|
||||
))
|
||||
tangent.start_point(),
|
||||
tangent.end_point(),
|
||||
cw,
|
||||
width,
|
||||
offset,
|
||||
)
|
||||
.map_err(|err| DrawException::CannotWrapAround(around.into(), err))
|
||||
}
|
||||
|
||||
#[debug_ensures(ret.is_ok() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() + 4))]
|
||||
|
|
@ -143,43 +124,26 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
|
|||
&mut self,
|
||||
head: Head,
|
||||
around: BendIndex,
|
||||
cw: bool,
|
||||
width: f64,
|
||||
) -> Result<CaneHead, DrawException> {
|
||||
let mut tangents = self
|
||||
let tangent = self
|
||||
.guide()
|
||||
.head_around_bend_segments(&head, around.into(), width)?;
|
||||
.head_around_bend_segment(&head, around.into(), cw, width)?;
|
||||
let offset = self
|
||||
.guide()
|
||||
.head_around_bend_offset(&head, around.into(), width);
|
||||
let mut dirs = [true, false];
|
||||
|
||||
if tangents.1.euclidean_length() < tangents.0.euclidean_length() {
|
||||
tangents = (tangents.1, tangents.0);
|
||||
dirs = [false, true];
|
||||
}
|
||||
|
||||
let mut errs = vec![];
|
||||
|
||||
for (i, tangent) in [tangents.0, tangents.1].iter().enumerate() {
|
||||
match self.cane_around(
|
||||
head,
|
||||
around.into(),
|
||||
tangent.start_point(),
|
||||
tangent.end_point(),
|
||||
dirs[i],
|
||||
width,
|
||||
offset,
|
||||
) {
|
||||
Ok(ok) => return Ok(ok),
|
||||
Err(err) => errs.push(err),
|
||||
}
|
||||
}
|
||||
|
||||
Err(DrawException::CannotWrapAround(
|
||||
self.cane_around(
|
||||
head,
|
||||
around.into(),
|
||||
errs[0],
|
||||
errs[1],
|
||||
))
|
||||
tangent.start_point(),
|
||||
tangent.end_point(),
|
||||
cw,
|
||||
width,
|
||||
offset,
|
||||
)
|
||||
.map_err(|err| DrawException::CannotWrapAround(around.into(), err))
|
||||
}
|
||||
|
||||
#[debug_ensures(ret.is_ok() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() + 4))]
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ impl HasPosition for TrianvertexWeight {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct NavvertexWeight {
|
||||
pub node: BinavvertexNodeIndex,
|
||||
pub maybe_cw: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, Clone)]
|
||||
|
|
@ -93,9 +94,9 @@ pub enum NavmeshError {
|
|||
pub struct Navmesh {
|
||||
graph: UnGraph<NavvertexWeight, (), usize>,
|
||||
source: FixedDotIndex,
|
||||
source_vertex: NodeIndex<usize>,
|
||||
source_navvertex: NodeIndex<usize>,
|
||||
target: FixedDotIndex,
|
||||
target_vertex: NodeIndex<usize>,
|
||||
target_navvertex: NodeIndex<usize>,
|
||||
}
|
||||
|
||||
impl Navmesh {
|
||||
|
|
@ -138,36 +139,62 @@ impl Navmesh {
|
|||
}
|
||||
|
||||
let mut graph: UnGraph<NavvertexWeight, (), usize> = UnGraph::default();
|
||||
let mut source_vertex = None;
|
||||
let mut target_vertex = None;
|
||||
let mut source_navvertex = None;
|
||||
let mut target_navvertex = None;
|
||||
|
||||
// `HashMap` is obviously suboptimal here.
|
||||
let mut map = HashMap::new();
|
||||
|
||||
for trianvertex in triangulation.node_identifiers() {
|
||||
let navvertex = graph.add_node(NavvertexWeight {
|
||||
node: trianvertex.into(),
|
||||
});
|
||||
let binavvertex = if trianvertex == source.into() {
|
||||
let navvertex = graph.add_node(NavvertexWeight {
|
||||
node: trianvertex.into(),
|
||||
maybe_cw: None,
|
||||
});
|
||||
|
||||
if trianvertex == source.into() {
|
||||
source_vertex = Some(navvertex);
|
||||
source_navvertex = Some(navvertex);
|
||||
(navvertex, navvertex)
|
||||
} else if trianvertex == target.into() {
|
||||
target_vertex = Some(navvertex);
|
||||
}
|
||||
let navvertex = graph.add_node(NavvertexWeight {
|
||||
node: trianvertex.into(),
|
||||
maybe_cw: None,
|
||||
});
|
||||
|
||||
map.insert(trianvertex, navvertex);
|
||||
target_navvertex = Some(navvertex);
|
||||
(navvertex, navvertex)
|
||||
} else {
|
||||
let navvertex1 = graph.add_node(NavvertexWeight {
|
||||
node: trianvertex.into(),
|
||||
maybe_cw: Some(false),
|
||||
});
|
||||
|
||||
let navvertex2 = graph.add_node(NavvertexWeight {
|
||||
node: trianvertex.into(),
|
||||
maybe_cw: Some(true),
|
||||
});
|
||||
|
||||
(navvertex1, navvertex2)
|
||||
};
|
||||
|
||||
map.insert(trianvertex, binavvertex);
|
||||
}
|
||||
|
||||
for edge in triangulation.edge_references() {
|
||||
graph.add_edge(map[&edge.source()], map[&edge.target()], ());
|
||||
let (from_navvertex1, from_navvertex2) = map[&edge.source()];
|
||||
let (to_navvertex1, to_navvertex2) = map[&edge.target()];
|
||||
|
||||
graph.update_edge(from_navvertex1, to_navvertex1, ());
|
||||
graph.update_edge(from_navvertex1, to_navvertex2, ());
|
||||
graph.update_edge(from_navvertex2, to_navvertex1, ());
|
||||
graph.update_edge(from_navvertex2, to_navvertex2, ());
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
graph,
|
||||
source,
|
||||
source_vertex: source_vertex.unwrap(),
|
||||
source_navvertex: source_navvertex.unwrap(),
|
||||
target,
|
||||
target_vertex: target_vertex.unwrap(),
|
||||
target_navvertex: target_navvertex.unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -179,15 +206,15 @@ impl Navmesh {
|
|||
self.source
|
||||
}
|
||||
|
||||
pub fn source_vertex(&self) -> NodeIndex<usize> {
|
||||
self.source_vertex
|
||||
pub fn source_navvertex(&self) -> NodeIndex<usize> {
|
||||
self.source_navvertex
|
||||
}
|
||||
|
||||
pub fn target(&self) -> FixedDotIndex {
|
||||
self.target
|
||||
}
|
||||
|
||||
pub fn target_vertex(&self) -> NodeIndex<usize> {
|
||||
self.target_vertex
|
||||
pub fn target_navvertex(&self) -> NodeIndex<usize> {
|
||||
self.target_navvertex
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,13 +142,13 @@ impl<'a, R: RulesTrait> Router<'a, R> {
|
|||
let trace = tracer.start(
|
||||
self.navmesh.graph(),
|
||||
self.navmesh.source(),
|
||||
self.navmesh.source_vertex(),
|
||||
self.navmesh.source_navvertex(),
|
||||
width,
|
||||
);
|
||||
|
||||
let (_cost, _path, band) = astar(
|
||||
self.navmesh.graph(),
|
||||
self.navmesh.source_vertex(),
|
||||
self.navmesh.source_navvertex(),
|
||||
&mut RouterAstarStrategy::new(tracer, trace, self.navmesh.target()),
|
||||
)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,11 +38,11 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
|||
&mut self,
|
||||
_graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
source: FixedDotIndex,
|
||||
source_vertex: NodeIndex<usize>,
|
||||
source_navvertex: NodeIndex<usize>,
|
||||
width: f64,
|
||||
) -> Trace {
|
||||
Trace {
|
||||
path: vec![source_vertex],
|
||||
path: vec![source_navvertex],
|
||||
head: BareHead { dot: source }.into(),
|
||||
width,
|
||||
}
|
||||
|
|
@ -132,13 +132,15 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
|||
around: NodeIndex<usize>,
|
||||
width: f64,
|
||||
) -> Result<CaneHead, DrawException> {
|
||||
let cw = self.maybe_cw(graph, around).unwrap();
|
||||
|
||||
match self.binavvertex(graph, around) {
|
||||
BinavvertexNodeIndex::FixedDot(dot) => {
|
||||
self.wrap_around_fixed_dot(graph, head, dot, width)
|
||||
self.wrap_around_fixed_dot(graph, head, dot, cw, width)
|
||||
}
|
||||
BinavvertexNodeIndex::FixedBend(_fixed_bend) => todo!(),
|
||||
BinavvertexNodeIndex::LooseBend(loose_bend) => {
|
||||
self.wrap_around_loose_bend(graph, head, loose_bend, width)
|
||||
self.wrap_around_loose_bend(graph, head, loose_bend, cw, width)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -148,9 +150,10 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
|||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
head: Head,
|
||||
around: FixedDotIndex,
|
||||
cw: bool,
|
||||
width: f64,
|
||||
) -> Result<CaneHead, DrawException> {
|
||||
let head = Draw::new(self.layout).cane_around_dot(head, around.into(), width)?;
|
||||
let head = Draw::new(self.layout).cane_around_dot(head, around.into(), cw, width)?;
|
||||
Ok(head)
|
||||
}
|
||||
|
||||
|
|
@ -159,9 +162,10 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
|||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
head: Head,
|
||||
around: LooseBendIndex,
|
||||
cw: bool,
|
||||
width: f64,
|
||||
) -> Result<CaneHead, DrawException> {
|
||||
let head = Draw::new(self.layout).cane_around_bend(head, around.into(), width)?;
|
||||
let head = Draw::new(self.layout).cane_around_bend(head, around.into(), cw, width)?;
|
||||
|
||||
Ok(head)
|
||||
}
|
||||
|
|
@ -177,19 +181,27 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
|
|||
trace.path.pop();
|
||||
}
|
||||
|
||||
fn maybe_cw(
|
||||
&self,
|
||||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
navvertex: NodeIndex<usize>,
|
||||
) -> Option<bool> {
|
||||
graph.node_weight(navvertex).unwrap().maybe_cw
|
||||
}
|
||||
|
||||
fn binavvertex(
|
||||
&self,
|
||||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
vertex: NodeIndex<usize>,
|
||||
navvertex: NodeIndex<usize>,
|
||||
) -> BinavvertexNodeIndex {
|
||||
graph.node_weight(vertex).unwrap().node
|
||||
graph.node_weight(navvertex).unwrap().node
|
||||
}
|
||||
|
||||
fn primitive(
|
||||
&self,
|
||||
graph: &UnGraph<NavvertexWeight, (), usize>,
|
||||
vertex: NodeIndex<usize>,
|
||||
navvertex: NodeIndex<usize>,
|
||||
) -> PrimitiveIndex {
|
||||
self.binavvertex(graph, vertex).into()
|
||||
self.binavvertex(graph, navvertex).into()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue