93 RandomizePoints(pa); |
93 RandomizePoints(pa); |
94 BezierizeEdge(pa, _0_1); |
94 BezierizeEdge(pa, _0_1); |
95 end; |
95 end; |
96 |
96 |
97 |
97 |
98 procedure FindLimits(si: LongInt; var pa: TPixAr); |
98 procedure FindPoint(si: LongInt; var newPoint: TPoint; var pa: TPixAr); |
|
99 const mapBorderMargin = 0; |
99 var p1, p2, mp, ap: TPoint; |
100 var p1, p2, mp, ap: TPoint; |
100 i, t1, t2, a, b, p, q, iy, ix, aqpb: LongInt; |
101 i, t1, t2, a, b, p, q, iy, ix, aqpb: LongInt; |
|
102 dab, d, distL, distR: LongInt; |
101 begin |
103 begin |
102 // [p1, p2] is segment we're trying to divide |
104 // [p1, p2] is segment we're trying to divide |
103 p1:= pa.ar[si]; |
105 p1:= pa.ar[si]; |
104 p2:= pa.ar[si + 1]; |
106 p2:= pa.ar[si + 1]; |
|
107 |
|
108 if (p1.x = NTPX) or (p2.x = NTPX) then |
|
109 begin |
|
110 newPoint:= p1; |
|
111 exit; |
|
112 end; |
105 |
113 |
106 // its middle point |
114 // its middle point |
107 mp.x:= (p1.x + p2.x) div 2; |
115 mp.x:= (p1.x + p2.x) div 2; |
108 mp.y:= (p1.y + p2.y) div 2; |
116 mp.y:= (p1.y + p2.y) div 2; |
109 // another point on the perpendicular bisector |
117 // another point on the perpendicular bisector |
110 ap.x:= mp.x + p2.y - p1.y; |
118 ap.x:= mp.x + p2.y - p1.y; |
111 ap.y:= mp.y + p1.x - p2.x; |
119 ap.y:= mp.y + p1.x - p2.x; |
112 |
120 // vector between these points |
113 for i:= 0 to pa.Count - 1 do |
121 a:= p2.y - p1.y; |
114 if i <> si then |
122 b:= p1.x - p2.x; |
|
123 |
|
124 // find distances to map borders |
|
125 if a <> 0 then |
|
126 begin |
|
127 // left border |
|
128 iy:= (mapBorderMargin - mp.x) * b div a + mp.y; |
|
129 d:= DistanceI(mp.x - mapBorderMargin, mp.y - iy).Round; |
|
130 t1:= a * (mp.x - mapBorderMargin) + b * (mp.y - iy); |
|
131 if t1 > 0 then distL:= d else distR:= d; |
|
132 writeln('====== Left border: ', mapBorderMargin, '; ', mp.y - iy, ', distance = ', d); |
|
133 writeln(a, ' ', -b); |
|
134 writeln(t1); |
|
135 writeln(mp.x - mapBorderMargin, ' ', mp.y - iy); |
|
136 writeln('MP: ', mp.x, ' ', mp.y); |
|
137 writeln('L: ', distL, '; R: ', distR); |
|
138 |
|
139 // right border |
|
140 iy:= (LAND_WIDTH - mapBorderMargin - mp.x) * b div a + mp.y; |
|
141 d:= DistanceI(mp.x - LAND_WIDTH + mapBorderMargin, mp.y - iy).Round; |
|
142 if t1 > 0 then distR:= d else distL:= d; |
|
143 end; |
|
144 |
|
145 if b <> 0 then |
|
146 begin |
|
147 // top border |
|
148 ix:= (mapBorderMargin - mp.y) * a div b + mp.x; |
|
149 d:= DistanceI(mp.y - mapBorderMargin, mp.x - ix).Round; |
|
150 t2:= b * (mp.y - mapBorderMargin) + a * (mp.x - ix); |
|
151 if t2 > 0 then distL:= min(d, distL) else distR:= min(d, distR); |
|
152 |
|
153 // bottom border |
|
154 ix:= (LAND_HEIGHT - mapBorderMargin - mp.y) * a div b + mp.x; |
|
155 d:= DistanceI(mp.y - LAND_HEIGHT + mapBorderMargin, mp.x - ix).Round; |
|
156 if t2 > 0 then distR:= min(d, distR) else distL:= min(d, distL); |
|
157 writeln('====== Bottom border: ', ix, '; ', LAND_HEIGHT - mapBorderMargin, ', distance = ', d); |
|
158 writeln(a, ' ', -b); |
|
159 writeln(t2); |
|
160 writeln(mp.x - ix, ' ', mp.y - LAND_HEIGHT + mapBorderMargin); |
|
161 writeln('L: ', distL, '; R: ', distR); |
|
162 end; |
|
163 |
|
164 // now go through all other segments |
|
165 for i:= 0 to pa.Count - 2 do |
|
166 if (i <> si) and (pa.ar[i].x <> NTPX) and (pa.ar[i + 1].x <> NTPX) then |
115 begin |
167 begin |
116 // check if it intersects |
168 // check if it intersects |
117 t1:= (mp.x - pa.ar[i].x) * (mp.y - ap.y) - (mp.x - ap.x) * (mp.y - pa.ar[i].y); |
169 t1:= (mp.x - pa.ar[i].x) * b - a * (mp.y - pa.ar[i].y); |
118 t2:= (mp.x - pa.ar[i + 1].x) * (mp.y - ap.y) - (mp.x - ap.x) * (mp.y - pa.ar[i + 1].y); |
170 t2:= (mp.x - pa.ar[i + 1].x) * b - a * (mp.y - pa.ar[i + 1].y); |
119 |
171 |
120 if (t1 > 0) <> (t2 > 0) then // yes it does, hard arith follows |
172 if (t1 > 0) <> (t2 > 0) then // yes it does, hard arith follows |
121 begin |
173 begin |
122 a:= p2.y - p1.y; |
|
123 b:= p1.x - p2.x; |
|
124 p:= pa.ar[i + 1].x - pa.ar[i].x; |
174 p:= pa.ar[i + 1].x - pa.ar[i].x; |
125 q:= pa.ar[i + 1].y - pa.ar[i].y; |
175 q:= pa.ar[i + 1].y - pa.ar[i].y; |
126 aqpb:= a * q - p * b; |
176 aqpb:= a * q - p * b; |
127 |
177 |
128 if (aqpb <> 0) then |
178 if (aqpb <> 0) then |
129 begin |
179 begin |
130 // (ix; iy) is intersection point |
180 // (ix; iy) is intersection point |
131 iy:= (((pa.ar[i].x - mp.x) * b + mp.y * a) * q - pa.ar[i].y * p * b); |
181 iy:= (((pa.ar[i].x - mp.x) * b + mp.y * a) * q - pa.ar[i].y * p * b); |
132 if b <> 0 then |
182 if b <> 0 then |
133 ix:= (iy - mp.y * aqpb) * a div b div aqpb + mp.x; |
183 ix:= (iy - mp.y * aqpb) * a div b div aqpb + mp.x |
134 else |
184 else |
135 ix:= (iy - pa.ar[i].y * aqpb) * p div q div aqpb + pa.ar[i].x; |
185 ix:= (iy - pa.ar[i].y * aqpb) * p div q div aqpb + pa.ar[i].x; |
136 iy:= iy div aqpb; |
186 iy:= iy div aqpb; |
137 |
187 |
138 writeln('>>> Intersection <<<'); |
188 d:= DistanceI(mp.y - iy, mp.x - ix).Round; |
139 writeln(p1.x, '; ', p1.y, ' - ', p2.x, '; ', p2.y); |
189 writeln('====== Intersection: ', ix, '; ', iy, ', distance = ', d); |
140 writeln(pa.ar[i].x, '; ', pa.ar[i].y, ' - ', pa.ar[i + 1].x, '; ', pa.ar[i + 1].y); |
190 t1:= b * (mp.y - iy) + a * (mp.x - ix); |
141 writeln('== ', ix, '; ', iy); |
191 writeln(a, ' ', -b); |
|
192 writeln(t1); |
|
193 writeln(mp.y - iy, ' ', mp.x - ix); |
|
194 if t1 > 0 then distL:= min(d, distL) else distR:= min(d, distR); |
|
195 writeln('L: ', distL, '; R: ', distR); |
142 end; |
196 end; |
143 end; |
197 end; |
144 end; |
198 end; |
|
199 |
|
200 if distR + distL < 40 then |
|
201 begin |
|
202 // limits are too narrow, leave point alone |
|
203 newPoint:= p1 |
|
204 end |
|
205 else |
|
206 begin |
|
207 // select distance within [-distL; distR] |
|
208 d:= -distL; |
|
209 //d:= distR; |
|
210 |
|
211 // calculate new point |
|
212 dab:= DistanceI(a, b).Round; |
|
213 |
|
214 newPoint.x:= mp.x + a * d div dab; |
|
215 newPoint.y:= mp.y + b * d div dab; |
|
216 |
|
217 writeln('Middle Point ', mp.x, '; ', mp.y); |
|
218 writeln('New Point ', newPoint.x, '; ', newPoint.y); |
|
219 end; |
145 end; |
220 end; |
146 |
221 |
147 procedure DivideEdges(var pa: TPixAr); |
222 procedure DivideEdges(var pa: TPixAr); |
148 var npa: TPixAr; |
223 var npa: TPixAr; |
149 i: LongInt; |
224 i: LongInt; |
|
225 newPoint: TPoint; |
150 begin |
226 begin |
151 i:= 0; |
227 i:= 0; |
152 npa.Count:= 0; |
228 npa.Count:= 0; |
153 while i < pa.Count do |
229 while i < pa.Count do |
154 begin |
230 begin |
155 if i = 0 then |
231 npa.ar[npa.Count]:= pa.ar[i]; |
156 begin |
232 inc(npa.Count); |
157 FindLimits(0, pa); |
233 |
158 npa.ar[npa.Count]:= pa.ar[i]; |
234 if i < 1 then |
159 pa.ar[i].y:= 300; |
235 begin |
160 npa.ar[npa.Count + 1]:= pa.ar[i]; |
236 FindPoint(i, newPoint, pa); |
161 inc(npa.Count, 2) |
237 if (newPoint.x <> pa.ar[i].x) or (newPoint.y <> pa.ar[i].y) then |
162 end else |
238 begin |
163 begin |
239 npa.ar[npa.Count]:= newPoint; |
164 npa.ar[npa.Count]:= pa.ar[i]; |
|
165 inc(npa.Count) |
240 inc(npa.Count) |
|
241 end; |
166 end; |
242 end; |
167 |
243 |
168 inc(i) |
244 inc(i) |
169 end; |
245 end; |
170 |
246 |