1+ namespace YCode . Designer . Fluxo ;
2+
3+ public class FluxoStepLine ( FluxoDesigner designer ) : FluxoBaseLine ( LineType . Step , designer )
4+ {
5+ private readonly double _spacing = 0d ;
6+
7+ public override void DrawLine ( FluxoLineParameter @params , StreamGeometryContext context )
8+ {
9+ base . DrawLine ( @params , context ) ;
10+
11+ context . BeginFigure ( this . Parameter . Start , false , false ) ;
12+ context . LineTo ( this . Points [ 0 ] , true , true ) ;
13+ context . LineTo ( this . Points [ 1 ] , true , true ) ;
14+ context . LineTo ( this . Points [ 2 ] , true , true ) ;
15+ context . LineTo ( this . Points [ 3 ] , true , true ) ;
16+ context . LineTo ( this . Parameter . End , true , true ) ;
17+ }
18+
19+ protected override void OnHorizontal ( )
20+ {
21+ var points = GetLinePoints ( this . Parameter . Source . Right , this . Parameter . Target . Left ) ;
22+
23+ this . Points . AddRanage ( [ points . P0 , points . P1 , points . P2 , points . P3 ] ) ;
24+ }
25+
26+ protected override void OnVertical ( )
27+ {
28+ throw new NotImplementedException ( ) ;
29+ }
30+
31+ protected override void OnCross ( )
32+ {
33+ throw new NotImplementedException ( ) ;
34+ }
35+
36+ private ( Point P0 , Point P1 , Point P2 , Point P3 ) GetLinePoints ( Point source , Point target )
37+ {
38+ var sourceDir = GetConnectorDirection ( this . Parameter . SourcePosition ) ;
39+ var targetDir = GetConnectorDirection ( this . Parameter . TargetPosition ) ;
40+
41+ this . Parameter . Start = source + new Vector ( _spacing * sourceDir . X , _spacing * sourceDir . Y ) ;
42+
43+ this . Parameter . End = target + new Vector ( _spacing * targetDir . X , _spacing * targetDir . Y ) ;
44+
45+ var connectionDir = GetConnectionDirection ( this . Parameter . Start , this . Parameter . SourcePosition , this . Parameter . End ) ;
46+
47+ var horizontalConnection = connectionDir . X != 0 ;
48+
49+ if ( IsOppositePosition ( this . Parameter . SourcePosition , this . Parameter . TargetPosition ) )
50+ {
51+ var ( p1 , p2 ) = GetOppositePositionPoints ( ) ;
52+
53+ return ( this . Parameter . Start , p1 , p2 , this . Parameter . End ) ;
54+ }
55+
56+ if ( this . Parameter . SourcePosition == this . Parameter . TargetPosition )
57+ {
58+ var p = GetSamePositionPoint ( ) ;
59+ return ( this . Parameter . Start , p , p , this . Parameter . End ) ;
60+ }
61+
62+ var isSameDir = horizontalConnection ? sourceDir . X == targetDir . Y : sourceDir . Y == targetDir . X ;
63+ var startGreaterThanEnd = horizontalConnection ? this . Parameter . Start . Y > this . Parameter . End . Y : this . Parameter . Start . X > this . Parameter . End . X ;
64+
65+ var positiveDir = horizontalConnection ? sourceDir . X == 1 : sourceDir . Y == 1 ;
66+ var shouldFlip = positiveDir
67+ ? isSameDir ? ! startGreaterThanEnd : startGreaterThanEnd
68+ : isSameDir
69+ ? startGreaterThanEnd
70+ : ! startGreaterThanEnd ;
71+
72+ if ( shouldFlip )
73+ {
74+ var sourceTarget = new Point ( this . Parameter . Start . X , this . Parameter . End . Y ) ;
75+ var targetSource = new Point ( this . Parameter . End . X , this . Parameter . Start . Y ) ;
76+
77+ var pf = horizontalConnection ? sourceTarget : targetSource ;
78+ return ( this . Parameter . Start , pf , pf , this . Parameter . End ) ;
79+ }
80+
81+ var pp = GetSamePositionPoint ( ) ;
82+ return ( this . Parameter . Start , pp , pp , this . Parameter . End ) ;
83+
84+ ( Point P1 , Point P2 ) GetOppositePositionPoints ( )
85+ {
86+ var center = this . Parameter . Start + ( this . Parameter . End - this . Parameter . Start ) / 2 ;
87+
88+ ( Point P1 , Point P2 ) verticalSplit = ( new Point ( center . X , this . Parameter . Start . Y ) , new Point ( center . X , this . Parameter . End . Y ) ) ;
89+ ( Point P1 , Point P2 ) horizontalSplit = ( new Point ( this . Parameter . Start . X , center . Y ) , new Point ( this . Parameter . End . X , center . Y ) ) ;
90+
91+ if ( horizontalConnection )
92+ {
93+ // left to right / right to left
94+ return sourceDir . X == connectionDir . X ? verticalSplit : horizontalSplit ;
95+ }
96+
97+ // top to bottom / bottom to top
98+ return sourceDir . Y == connectionDir . Y ? horizontalSplit : verticalSplit ;
99+ }
100+
101+ Point GetSamePositionPoint ( )
102+ {
103+ var sourceTarget = new Point ( this . Parameter . Start . X , this . Parameter . End . Y ) ;
104+ var targetSource = new Point ( this . Parameter . End . X , this . Parameter . Start . Y ) ;
105+
106+ if ( horizontalConnection )
107+ {
108+ return sourceDir . X == connectionDir . X ? targetSource : sourceTarget ;
109+ }
110+
111+ return sourceDir . Y == connectionDir . Y ? sourceTarget : targetSource ;
112+ }
113+
114+ static Point GetConnectionDirection ( in Point source , FluxoLinePosition sourcePosition , in Point target )
115+ {
116+ return sourcePosition == FluxoLinePosition . Left || sourcePosition == FluxoLinePosition . Right
117+ ? new Point ( Math . Sign ( target . X - source . X ) , 0 )
118+ : new Point ( 0 , Math . Sign ( target . Y - source . Y ) ) ;
119+ }
120+
121+ static Point GetConnectorDirection ( FluxoLinePosition position )
122+ => position switch
123+ {
124+ FluxoLinePosition . Top => new Point ( 0 , - 1 ) ,
125+ FluxoLinePosition . Left => new Point ( - 1 , 0 ) ,
126+ FluxoLinePosition . Bottom => new Point ( 0 , 1 ) ,
127+ FluxoLinePosition . Right => new Point ( 1 , 0 ) ,
128+ _ => default ,
129+ } ;
130+
131+ static bool IsOppositePosition ( FluxoLinePosition sourcePosition , FluxoLinePosition targetPosition )
132+ {
133+ return sourcePosition == FluxoLinePosition . Left && targetPosition == FluxoLinePosition . Right
134+ || sourcePosition == FluxoLinePosition . Right && targetPosition == FluxoLinePosition . Left
135+ || sourcePosition == FluxoLinePosition . Top && targetPosition == FluxoLinePosition . Bottom
136+ || sourcePosition == FluxoLinePosition . Bottom && targetPosition == FluxoLinePosition . Top ;
137+ }
138+ }
139+
140+ public override Point GetPoint ( double target )
141+ {
142+ var current = 0d ;
143+
144+ var start = this . Points [ 0 ] ;
145+
146+ var length = this . GetLength ( ) ;
147+
148+ var targetLength = length * target ;
149+
150+ var prePoint = new Point ( start . X , start . Y ) ;
151+
152+ for ( var i = 1 ; i < this . Points . Count ; i ++ )
153+ {
154+ var pointToLength = Math . Sqrt ( Math . Pow ( prePoint . X - this . Points [ i ] . X , 2 ) +
155+ Math . Pow ( prePoint . Y - this . Points [ i ] . Y , 2 ) ) ;
156+
157+ var distance = Point . Subtract ( this . Points [ i ] , prePoint ) . Length ;
158+
159+ if ( current + distance >= targetLength )
160+ {
161+ var extra = targetLength - current ;
162+
163+ var factor = extra / distance ;
164+
165+ return new Point (
166+ prePoint . X + ( factor * this . Points [ i ] . X - prePoint . X ) ,
167+ prePoint . Y + ( factor * this . Points [ i ] . Y - prePoint . Y ) ) ;
168+ }
169+
170+ prePoint = this . Points [ i ] ;
171+
172+ current += pointToLength ;
173+ }
174+
175+ return prePoint ;
176+ }
177+
178+ public override double GetLength ( )
179+ {
180+ var start = this . Points [ 0 ] ;
181+
182+ var length = 0d ;
183+
184+ var prePoint = new Point ( start . X , start . Y ) ;
185+
186+ for ( var i = 1 ; i < this . Points . Count ; i ++ )
187+ {
188+ length += Math . Sqrt ( Math . Pow ( prePoint . X - this . Points [ i ] . X , 2 ) +
189+ Math . Pow ( prePoint . Y - this . Points [ i ] . Y , 2 ) ) ;
190+
191+ prePoint = this . Points [ i ] ;
192+ }
193+
194+ return length ;
195+ }
196+ }
0 commit comments