jellyflow_runtime/runtime/geometry/endpoints/
resolve.rs1use jellyflow_core::core::{CanvasPoint, CanvasRect};
2
3use super::types::{
4 EdgeEndpointInput, EdgeEndpointPosition, EdgePosition, HandleBounds, HandlePosition,
5};
6
7pub fn edge_position(source: EdgeEndpointInput, target: EdgeEndpointInput) -> Option<EdgePosition> {
8 Some(EdgePosition {
9 source: handle_anchor_position(source.node_rect, source.handle, source.fallback_position)?,
10 target: handle_anchor_position(target.node_rect, target.handle, target.fallback_position)?,
11 })
12}
13
14pub fn handle_anchor_position(
15 node_rect: CanvasRect,
16 handle: Option<HandleBounds>,
17 fallback_position: HandlePosition,
18) -> Option<EdgeEndpointPosition> {
19 let (rect, position) = absolute_handle_rect(node_rect, handle, fallback_position)?;
20 let point = match position {
21 HandlePosition::Top => CanvasPoint {
22 x: rect.origin.x + rect.size.width * 0.5,
23 y: rect.origin.y,
24 },
25 HandlePosition::Right => CanvasPoint {
26 x: rect.origin.x + rect.size.width,
27 y: rect.origin.y + rect.size.height * 0.5,
28 },
29 HandlePosition::Bottom => CanvasPoint {
30 x: rect.origin.x + rect.size.width * 0.5,
31 y: rect.origin.y + rect.size.height,
32 },
33 HandlePosition::Left => CanvasPoint {
34 x: rect.origin.x,
35 y: rect.origin.y + rect.size.height * 0.5,
36 },
37 };
38
39 point
40 .is_finite()
41 .then_some(EdgeEndpointPosition { point, position })
42}
43
44pub fn handle_center_position(
45 node_rect: CanvasRect,
46 handle: Option<HandleBounds>,
47 fallback_position: HandlePosition,
48) -> Option<CanvasPoint> {
49 let (rect, _position) = absolute_handle_rect(node_rect, handle, fallback_position)?;
50 Some(CanvasPoint {
51 x: rect.origin.x + rect.size.width * 0.5,
52 y: rect.origin.y + rect.size.height * 0.5,
53 })
54}
55
56fn absolute_handle_rect(
57 node_rect: CanvasRect,
58 handle: Option<HandleBounds>,
59 fallback_position: HandlePosition,
60) -> Option<(CanvasRect, HandlePosition)> {
61 if !node_rect.is_positive_finite() {
62 return None;
63 }
64
65 let Some(handle) = handle else {
66 return Some((node_rect, fallback_position));
67 };
68
69 if !handle.rect.is_positive_finite() {
70 return None;
71 }
72
73 let rect = CanvasRect {
74 origin: CanvasPoint {
75 x: node_rect.origin.x + handle.rect.origin.x,
76 y: node_rect.origin.y + handle.rect.origin.y,
77 },
78 size: handle.rect.size,
79 };
80
81 rect.is_positive_finite().then_some((rect, handle.position))
82}