Skip to content

Commit 5c1ff3f

Browse files
committed
Fix infinite loops for huge non-cartesian coordinates.
1 parent fda19eb commit 5c1ff3f

File tree

3 files changed

+89
-35
lines changed

3 files changed

+89
-35
lines changed

Visual_Studio_2017/GraphicalDebugging/Geometry.cs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ private static bool IntersectsAntimeridian(Point p1, Point p2, Unit unit)
401401
double x1 = NormalizedAngleSigned(p1[0], unit);
402402
double x2 = NormalizedAngleSigned(p2[0], unit);
403403
double dist = x2 - x1;
404-
double pi = HalfAngle(unit);
404+
double pi = StraightAngle(unit);
405405
return dist < -pi || pi < dist;
406406
}
407407
}
@@ -416,7 +416,7 @@ public static double NearestAntimeridian(double x, int dir, Unit unit)
416416
}
417417
else
418418
{
419-
double pi = HalfAngle(unit);
419+
double pi = StraightAngle(unit);
420420
double ax = Math.Abs(x);
421421
double periods = (ax - pi) / (2 * pi);
422422
int calcDir = x < 0 ? -dir : dir;
@@ -487,7 +487,7 @@ public static Box EnvelopeAngle(Box box, Unit unit)
487487
Point p0 = Normalized(box.Min, unit);
488488
Point p1 = Normalized(box.Max, unit);
489489
if (p1[0] < p0[0])
490-
p1[0] += 2 * HalfAngle(unit);
490+
p1[0] += FullAngle(unit);
491491
return Envelope(p0, p1);
492492
}
493493

@@ -578,12 +578,13 @@ public static void ExpandAngle(Box box, Box b, Unit unit)
578578
double xmax1 = NormalizedAngleSigned(box.Max[0], unit);
579579
double xmin2 = NormalizedAngleSigned(b.Min[0], unit);
580580
double xmax2 = NormalizedAngleSigned(b.Max[0], unit);
581+
582+
double twoPi = FullAngle(unit);
581583
if (xmax1 < xmin1)
582-
xmax1 += 2 * HalfAngle(unit);
584+
xmax1 += twoPi;
583585
if (xmax2 < xmin2)
584-
xmax2 += 2 * HalfAngle(unit);
586+
xmax2 += twoPi;
585587

586-
double twoPi = 2 * HalfAngle(unit);
587588
double left_dist = NormalizedAngleSigned(xmin1 - xmin2, unit);
588589
double right_dist = NormalizedAngleSigned(xmax2 - xmax1, unit);
589590
if (left_dist >= 0 && right_dist >= 0)
@@ -650,15 +651,15 @@ public static Point Normalized(Point p, Unit unit)
650651

651652
public static double NormalizedAngleSigned(double x, Unit unit)
652653
{
653-
double pi = HalfAngle(unit);
654+
double pi = StraightAngle(unit);
654655
while (x < -pi) x += 2 * pi;
655656
while (x > pi) x -= 2 * pi;
656657
return x;
657658
}
658659

659660
public static double NormalizedAngleUnsigned(double x, Unit unit)
660661
{
661-
double pi = HalfAngle(unit);
662+
double pi = StraightAngle(unit);
662663
while (x < 0) x += 2 * pi;
663664
while (x > 2 * pi) x -= 2 * pi;
664665
return x;
@@ -679,14 +680,24 @@ private static void NormalizeAngle(Box b, Unit unit)
679680
NormalizeAngle(b.Min, unit);
680681
NormalizeAngle(b.Max, unit);
681682
if (b.Min[0] > b.Max[0])
682-
b.Max[0] += 2 * HalfAngle(unit);
683+
b.Max[0] += FullAngle(unit);
683684
}*/
684685

685-
public static double HalfAngle(Unit unit)
686+
public static double StraightAngle(Unit unit)
686687
{
687688
return unit == Unit.Degree ? 180 : Math.PI;
688689
}
689690

691+
public static double FullAngle(Unit unit)
692+
{
693+
return unit == Unit.Degree ? 360 : (2.0 * Math.PI);
694+
}
695+
696+
public static double RightAngle(Unit unit)
697+
{
698+
return unit == Unit.Degree ? 90 : (0.5 * Math.PI);
699+
}
700+
690701
public static double ToRadian(double angle, Unit unit)
691702
{
692703
return unit == Unit.Degree ? (angle * Math.PI / 180.0) : angle;
@@ -802,7 +813,7 @@ public static Point[] SphericalDensify(Point p0, Point p1, double length, Unit u
802813
}
803814
else
804815
{
805-
double halfPi = HalfAngle(unit) / 2;
816+
double halfPi = RightAngle(unit);
806817
if (Equals(p0[1], halfPi))
807818
axis = new Point(0, 1, 0);
808819
else if (Equals(p0[1], -halfPi))

Visual_Studio_2017/GraphicalDebugging/Util.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,5 +366,13 @@ public static bool IsOk<T1, T2, T3, T4>(T1 v1, T2 v2, T3 v3, T4 v4)
366366
&& !v3.Equals(default(T3))
367367
&& !v4.Equals(default(T4));
368368
}
369+
370+
public static bool Assign<T>(ref T v, T v2)
371+
where T : struct
372+
{
373+
bool result = !v.Equals(v2);
374+
v = v2;
375+
return result;
376+
}
369377
}
370378
}

Visual_Studio_2017/GraphicalDebugging/Viewport.cs

Lines changed: 59 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -197,23 +197,40 @@ public void DrawPeriodicPoint(LocalCS cs, Geometry.Point point, Geometry.Box box
197197
PointF p = cs.Convert(point);
198198
DrawPoint(p);
199199

200-
double pi2 = 2 * Geometry.HalfAngle(unit);
200+
double twoPi = Geometry.FullAngle(unit);
201201
Pen pen = drawDots ? this.penDot : this.pen;
202-
// draw points on the west
203-
double x_tmp = point[0] - pi2;
204-
while (x_tmp >= box.Min[0])
202+
203+
// NOTE: Use AssignChanged becasue for big coordinates subtracting/adding
204+
// twoPi doesn't change the value of x_tmp which causes infinite loop
205+
206+
float x = Math.Min(Math.Max(p.X, 0.0f), cs.Width);
207+
double nPeriodsWest = (point[0] - box.Min[0]) / twoPi;
208+
float pixelsWest = x;
209+
double nPeriodsEast = (box.Max[0] - point[0]) / twoPi;
210+
float pixelsEast = cs.Width - x;
211+
212+
if (nPeriodsWest <= pixelsWest / 5)
205213
{
206-
p.X = cs.ConvertX(x_tmp);
207-
DrawPoint(p, pen);
208-
x_tmp -= pi2;
214+
// draw points on the west
215+
double x_tmp = point[0];
216+
while (Util.Assign(ref x_tmp, x_tmp - twoPi)
217+
&& x_tmp >= box.Min[0])
218+
{
219+
p.X = cs.ConvertX(x_tmp);
220+
DrawPoint(p, pen);
221+
}
209222
}
210-
// draw points on the east
211-
x_tmp = point[0] + pi2;
212-
while (x_tmp <= box.Max[0])
223+
224+
if (nPeriodsEast <= pixelsEast / 5)
213225
{
214-
p.X = cs.ConvertX(x_tmp);
215-
DrawPoint(p, pen);
216-
x_tmp += pi2;
226+
// draw points on the east
227+
double x_tmp = point[0];
228+
while (Util.Assign(ref x_tmp, x_tmp + twoPi)
229+
&& x_tmp <= box.Max[0])
230+
{
231+
p.X = cs.ConvertX(x_tmp);
232+
DrawPoint(p, pen);
233+
}
217234
}
218235
}
219236

@@ -359,7 +376,7 @@ private static PointF[] DensifyAndConvert(LocalCS cs, Geometry.Point p0, Geometr
359376
{
360377
double distNorm = Geometry.NormalizedAngleSigned(p1[0] - p0[0], unit);
361378
bool intersPole = IsAntipodal(distNorm, unit);
362-
double halfPi = Geometry.HalfAngle(unit) / 2;
379+
double halfPi = Geometry.RightAngle(unit);
363380
double poleLat = p1[1] - p0[1] >= 0 ? halfPi : -halfPi;
364381
int intersPoleIndex = -1;
365382

@@ -400,7 +417,7 @@ private static PointF[] DensifyAndConvert(LocalCS cs, Geometry.Point p0, Geometr
400417

401418
public static bool IsAntipodal(double distNorm, Geometry.Unit unit)
402419
{
403-
double pi = Geometry.HalfAngle(unit);
420+
double pi = Geometry.StraightAngle(unit);
404421
return Math.Abs(Math.Abs(distNorm) - pi) < double.Epsilon * pi;
405422
}
406423

@@ -609,8 +626,8 @@ public void DrawPeriodic(LocalCS cs,
609626
IPeriodicDrawable drawer,
610627
bool fill, bool drawDirs, bool drawDots)
611628
{
612-
double pi = Geometry.HalfAngle(unit);
613-
float periodf = cs.ConvertDimensionX(2 * pi);
629+
double twoPi = Geometry.FullAngle(unit);
630+
float periodf = cs.ConvertDimensionX(twoPi);
614631
float box_minf = cs.ConvertX(box.Min[0]);
615632
float box_maxf = cs.ConvertX(box.Max[0]);
616633

@@ -624,22 +641,24 @@ public void DrawPeriodic(LocalCS cs,
624641
float minf_i = minf;
625642
float maxf_i = maxf;
626643
float translationf = 0;
627-
while (maxf_i >= box_minf)
644+
while (maxf_i >= box_minf
645+
&& Util.Assign(ref maxf_i, maxf_i - periodf))
628646
{
629647
translationf -= periodf;
630648
minf_i -= periodf;
631-
maxf_i -= periodf;
649+
//maxf_i -= periodf; // subtracted above
632650
if (maxf_i >= box_minf && minf_i <= box_maxf)
633651
drawer.DrawOne(this, translationf, fill, drawDirs, drawDots);
634652
}
635653
// east
636654
minf_i = minf;
637655
maxf_i = maxf;
638656
translationf = 0;
639-
while (minf_i <= box_maxf)
657+
while (minf_i <= box_maxf
658+
&& Util.Assign(ref minf_i, minf_i + periodf))
640659
{
641660
translationf += periodf;
642-
minf_i += periodf;
661+
//minf_i += periodf; // added above
643662
maxf_i += periodf;
644663
if (maxf_i >= box_minf && minf_i <= box_maxf)
645664
drawer.DrawOne(this, translationf, fill, drawDirs, drawDots);
@@ -694,7 +713,7 @@ public static bool DrawAxes(Graphics graphics, Geometry.Box box, Geometry.Unit u
694713
Pen anti_pen = new Pen(colors.AxisColor, 1);
695714
anti_pen.DashStyle = DashStyle.Custom;
696715
anti_pen.DashPattern = new float[] { 5, 5 };
697-
double pi = Geometry.HalfAngle(unit);
716+
double pi = Geometry.StraightAngle(unit);
698717
double anti_mer = Geometry.NearestAntimeridian(box.Min[0], -1, unit);
699718
double prime_mer = anti_mer + pi;
700719
double next_anti_mer = anti_mer + 2 * pi;
@@ -706,21 +725,34 @@ public static bool DrawAxes(Graphics graphics, Geometry.Box box, Geometry.Unit u
706725
float prime_mer_step = cs.ConvertX(next_prime_mer) - prime_mer_f;
707726

708727
// Antimeridians
709-
for (; anti_mer_f <= w; anti_mer_f += anti_mer_step)
728+
while (anti_mer_f <= w
729+
// NOTE: For bug coordinates anti_mer_step may be 0 which results in infinite loop
730+
&& Util.Assign(ref anti_mer_f, anti_mer_f + anti_mer_step))
710731
{
711732
if (anti_mer_f >= 0)
712733
{
713734
graphics.DrawLine(anti_pen, anti_mer_f, 0, anti_mer_f, h);
714735
}
715736
}
716737
// Prime meridians
717-
for (; prime_mer_f <= w; prime_mer_f += prime_mer_step)
738+
bool primeMeridiansDrawn = false;
739+
while (prime_mer_f <= w
740+
// NOTE: For bug coordinates anti_mer_step may be 0 which results in infinite loop
741+
&& Util.Assign(ref prime_mer_f, prime_mer_f += prime_mer_step))
718742
{
719743
if (prime_mer_f >= 0)
720744
{
721745
graphics.DrawLine(prime_pen, prime_mer_f, 0, prime_mer_f, h);
746+
primeMeridiansDrawn = true;
722747
}
723748
}
749+
// Prime meridian
750+
float p = cs.ConvertX(0.0);
751+
if (!primeMeridiansDrawn
752+
&& 0 <= p && p <= w)
753+
{
754+
graphics.DrawLine(prime_pen, p, 0, p, h);
755+
}
724756
// Equator
725757
float e = cs.ConvertY(0.0);
726758
if (0 <= e && e <= h)
@@ -1192,6 +1224,9 @@ public Geometry.Box ViewBox()
11921224
new Geometry.Point(InverseConvertX(dst_orig_w), InverseConvertY(0)));
11931225
}
11941226

1227+
public float Width { get { return dst_orig_w; } }
1228+
public float Height { get { return dst_orig_h; } }
1229+
11951230
float dst_orig_w, dst_orig_h;
11961231
float dst_x0, dst_y0;
11971232
double src_x0, src_y0;

0 commit comments

Comments
 (0)