001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005package armyc2.c5isr.JavaLineArray;
006
007import java.util.ArrayList;
008
009import armyc2.c5isr.JavaTacticalRenderer.TGLight;
010import armyc2.c5isr.renderer.utilities.ErrorLogger;
011import armyc2.c5isr.renderer.utilities.RendererException;
012
013import java.io.*;
014import armyc2.c5isr.graphics2d.*;
015import armyc2.c5isr.renderer.utilities.IPointConversion;
016import armyc2.c5isr.JavaTacticalRenderer.mdlGeodesic;
017import armyc2.c5isr.graphics2d.GeneralPath;
018import armyc2.c5isr.graphics2d.PathIterator;
019import armyc2.c5isr.graphics2d.Point;
020import armyc2.c5isr.graphics2d.Point2D;
021import armyc2.c5isr.graphics2d.Shape;
022
023/**
024 * A class to provide the utility functions required for calculating the line
025 * points.
026 *
027 */
028public final class lineutility {
029
030    private static final String _className = "lineutility";
031    public static final int extend_left = 0;
032    public static final int extend_right = 1;
033    public static final int extend_above = 2;
034    public static final int extend_below = 3;
035
036    /**
037     * Resizes the array to the length speicifed, called by the Channels class.
038     *
039     * @param pLinePoints the array to resize
040     * @param length the length to which to resize the array.
041     * @return the resized array
042     */
043    protected static POINT2[] ResizeArray(POINT2[] pLinePoints, int length) {
044        POINT2[] array = new POINT2[length];
045        try {
046            if (pLinePoints.length <= length) {
047                return pLinePoints;
048            }
049
050            int j = 0;
051            for (j = 0; j < length; j++) {
052                array[j] = new POINT2(pLinePoints[j]);
053            }
054        } catch (Exception exc) {
055            ErrorLogger.LogException(_className, "ResizeArray",
056                    new RendererException("Failed inside ResizeArray", exc));
057        }
058        return array;
059    }
060
061    /**
062     * post-segments a line segment into 50 pixel intervals
063     *
064     * @param pt0
065     * @param pt1
066     * @param shape
067     */
068    protected static void SegmentLineShape(POINT2 pt0, POINT2 pt1, Shape2 shape) {
069        try {
070            if (pt0 == null || pt1 == null) {
071                return;
072            }
073
074            int j = 0, n = 0;
075            double dist = CalcDistanceDouble(pt0, pt1);
076            n = (int) (dist / 25d);
077            POINT2 pt = null;
078            shape.lineTo(pt0);
079            for (j = 1; j <= n; j++) {
080                pt = lineutility.ExtendAlongLineDouble(pt0, pt1, 25);
081                shape.lineTo(pt);
082            }
083            shape.lineTo(pt1);
084        } catch (Exception exc) {
085            ErrorLogger.LogException(_className, "SegmentLineShape",
086                    new RendererException("Failed inside SegmentLineShape", exc));
087        }
088    }
089
090    /**
091     * Calculates the middle segment for the Direction of Attack Aviation symbol
092     *
093     * @param pLinePoints the point array
094     * @param vblSaveCounter the size of the point array
095     * @return the middle segment
096     */
097    public static int GetDirAtkAirMiddleSegment(POINT2[] pLinePoints,
098            int vblSaveCounter) {
099        int middleSegment = -1;
100        try {
101            double d = 0;
102            int k = 0;
103            for (k = vblSaveCounter - 1; k > 0; k--) {
104                d += lineutility.CalcDistanceDouble(pLinePoints[k], pLinePoints[k - 1]);
105                if (d > 60) {
106                    break;
107                }
108            }
109            if (d > 60) {
110                middleSegment = k;
111            } else {
112                if (vblSaveCounter <= 3) {
113                    middleSegment = 1;
114                } else {
115                    middleSegment = 2;
116                }
117            }
118        } catch (Exception exc) {
119            ErrorLogger.LogException(_className, "GetDirAtkAirMiddleSegment",
120                    new RendererException("Failed inside GetDirAtkAirMiddleSegment", exc));
121        }
122        return middleSegment;
123    }
124
125    /**
126     * Computes the angle in radians between two points
127     *
128     * @param pt0 the first point
129     * @param pt1 the last point
130     *
131     * @return the angle in radians
132     */
133    protected static double CalcSegmentAngleDouble(POINT2 pt0,
134            POINT2 pt1) {
135        double dAngle = 0;
136        try {
137            //declarations
138            int nTemp = 0;
139            ref<double[]> m = new ref();
140            //end declarations
141
142            nTemp = CalcTrueSlopeDouble(pt0, pt1, m);
143            if (nTemp == 0) {
144                dAngle = Math.PI / 2;
145            } else {
146                dAngle = Math.atan(m.value[0]);
147            }
148
149        } catch (Exception exc) {
150            ErrorLogger.LogException(_className, "CalcSegmentAngleDouble",
151                    new RendererException("Failed inside CalcSegmentAngleDouble", exc));
152        }
153        return dAngle;
154    }
155
156    /**
157     * POINT2 in previous applications has been a struct that did not require
158     * initialization.
159     *
160     * @param pts array of points to instantiate.
161     */
162    protected static void InitializePOINT2Array(POINT2[] pts) {
163        //int j=0;
164        if (pts == null || pts.length == 0) {
165            return;
166        }
167        int n=pts.length;
168        //for (int j = 0; j < pts.length; j++) 
169        for (int j = 0; j < n; j++) 
170        {
171            pts[j] = new POINT2();
172        }
173    }
174
175    /**
176     * Calculates the center point of an area using the first vblCounter points
177     * in the array.
178     *
179     * @param pLinePoints the client points
180     * @param vblCounter the number of points in the array to use
181     *
182     * @return the center point
183     */
184    protected static POINT2 CalcCenterPointDouble(POINT2[] pLinePoints,
185            int vblCounter) {
186        POINT2 CenterLinePoint = new POINT2(pLinePoints[0]);
187        try {
188            //declarations
189            int j = 0;
190            double dMinX = pLinePoints[0].x,
191                    dMinY = pLinePoints[0].y,
192                    dMaxX = pLinePoints[0].x,
193                    dMaxY = pLinePoints[0].y;
194
195            //end declarations
196            dMinX = pLinePoints[0].x;
197            dMinY = pLinePoints[0].y;
198            dMaxX = pLinePoints[0].x;
199            dMaxY = pLinePoints[0].y;
200
201            for (j = 0; j < vblCounter; j++) {
202                if (pLinePoints[j].x < dMinX) {
203                    dMinX = pLinePoints[j].x;
204                }
205
206                if (pLinePoints[j].y < dMinY) {
207                    dMinY = pLinePoints[j].y;
208                }
209
210                if (pLinePoints[j].x > dMaxX) {
211                    dMaxX = pLinePoints[j].x;
212                }
213
214                if (pLinePoints[j].y > dMaxY) {
215                    dMaxY = pLinePoints[j].y;
216                }
217
218            }   //end for
219
220            CenterLinePoint.x = (dMinX + dMaxX) / 2;
221            CenterLinePoint.y = (dMinY + dMaxY) / 2;
222        } catch (Error exc) {
223            ErrorLogger.LogException(_className, "CalcCenterPointDouble",
224                    new RendererException("Failed inside CalcCenterPointDouble", exc));
225        }
226        return CenterLinePoint;
227    }
228
229    /**
230     * Called by renderer Modifier2 class after ArrayList.ToArray was called,
231     * which produces an array of objects.
232     *
233     * @param pLinePoints
234     * @param vblCounter
235     * @return
236     */
237    public static POINT2 CalcCenterPointDouble2(Object[] pLinePoints,
238            int vblCounter) {
239        POINT2 pt0 = (POINT2) pLinePoints[0];
240        POINT2 CenterLinePoint = new POINT2();
241        try {
242            //declarations
243            int j = 0;
244            double dMinX = pt0.x,
245                    dMinY = pt0.y,
246                    dMaxX = pt0.x,
247                    dMaxY = pt0.y;
248
249            //end declarations
250            dMinX = pt0.x;
251            dMinY = pt0.y;
252            dMaxX = pt0.x;
253            dMaxY = pt0.y;
254
255            POINT2 pt;
256
257            for (j = 0; j < vblCounter; j++) {
258                pt = (POINT2) pLinePoints[j];
259                if (pt.x < dMinX) {
260                    dMinX = pt.x;
261                }
262
263                if (pt.y < dMinY) {
264                    dMinY = pt.y;
265                }
266
267                if (pt.x > dMaxX) {
268                    dMaxX = pt.x;
269                }
270
271                if (pt.y > dMaxY) {
272                    dMaxY = pt.y;
273                }
274
275            }   //end for
276
277            CenterLinePoint.x = (dMinX + dMaxX) / 2;
278            CenterLinePoint.y = (dMinY + dMaxY) / 2;
279        } catch (Error exc) {
280            ErrorLogger.LogException(_className, "CalcCenterPointDouble2",
281                    new RendererException("Failed inside CalcCenterPointDouble2", exc));
282        }
283        return CenterLinePoint;
284    }
285
286    /**
287     * Calculates the distance in pixels between two points
288     *
289     * @param p1 the first point
290     * @param p2 the last point
291     *
292     * @return the distance between p1 and p2 in pixels
293     */
294    public static double CalcDistanceDouble(POINT2 p1,
295            POINT2 p2) {
296        double returnValue = 0;
297        try {
298            returnValue = Math.sqrt((p1.x - p2.x)
299                    * (p1.x - p2.x)
300                    + (p1.y - p2.y)
301                    * (p1.y - p2.y));
302
303            //sanity check
304            //return x or y distance if returnValue is 0 or infinity
305            double xdist = Math.abs(p1.x - p2.x);
306            double ydist = Math.abs(p1.y - p2.y);
307            double max = xdist;
308            if (ydist > xdist) {
309                max = ydist;
310            }
311
312            if (returnValue == 0 || Double.isInfinite(returnValue)) {
313                if (max > 0) {
314                    returnValue = max;
315                }
316            }
317        } catch (Exception exc) {
318            ErrorLogger.LogException(_className, "CalcDistanceDouble",
319                    new RendererException("Failed inside CalcDistanceDouble", exc));
320        }
321        return returnValue;
322    }
323
324    /**
325     * Calculates the distance in pixels between two points
326     *
327     * @param p1 the first point
328     * @param p2 the last point
329     *
330     * @return the distance between p1 and p2 in pixels
331     */
332    public static double CalcDistanceDouble(Point2D p1,
333                                            Point2D p2) {
334        double returnValue = 0;
335        try {
336            returnValue = Math.sqrt((p1.getX() - p2.getX())
337                    * (p1.getX() - p2.getX())
338                    + (p1.getY() - p2.getY())
339                    * (p1.getY() - p2.getY()));
340
341            //sanity check
342            //return x or y distance if returnValue is 0 or infinity
343            double xdist = Math.abs(p1.getX() - p2.getX());
344            double ydist = Math.abs(p1.getY() - p2.getY());
345            double max = xdist;
346            if (ydist > xdist) {
347                max = ydist;
348            }
349
350            if (returnValue == 0 || Double.isInfinite(returnValue)) {
351                if (max > 0) {
352                    returnValue = max;
353                }
354            }
355        } catch (Exception exc) {
356            ErrorLogger.LogException(_className, "CalcDistanceDouble",
357                    new RendererException("Failed inside CalcDistanceDouble", exc));
358        }
359        return returnValue;
360    }
361
362    /**
363     * Computes the slope of a line
364     *
365     * @param firstLinePoint the first line point
366     * @param lastLinePoint the last line point
367     * @param slope OUT - object with member to hold the slope of the line
368     *
369     * @return 1 if successful, else return 0
370     */
371    protected static int CalcTrueSlopeDouble(POINT2 firstLinePoint,
372            POINT2 lastLinePoint,
373            ref<double[]> slope)//ref is a double
374    {
375        int result = 1;
376        try {
377            if (slope.value == null) {
378                slope.value = new double[1];
379            }
380
381            double deltaX = 0, deltaY = 0;
382            deltaX = firstLinePoint.x - lastLinePoint.x;
383            //if (deltaX == 0) 
384            if (Math.abs(deltaX) < 1) 
385            {
386                //deltaX = 1;
387                if(deltaX>=0)
388                    deltaX=1;
389                else
390                    deltaX=-1;
391                result = 1;
392            }
393            deltaY = firstLinePoint.y - lastLinePoint.y;
394
395            slope.value[0] = deltaY / deltaX;   //cannot blow up
396        } catch (Error exc) {
397            ErrorLogger.LogException(_className, "CalcTrueSlopeDouble",
398                    new RendererException("Failed inside CalcTrueSlopeDouble", exc));
399        }
400        return result;
401    }
402
403    public static void WriteFile(String str) {
404        try {
405            BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("Test.txt"));
406            bufferedWriter.write(str);
407            bufferedWriter.close();
408            bufferedWriter = null;
409        } catch (Exception exc) {
410            ErrorLogger.LogException(_className, "WriteFile",
411                    new RendererException("Failed inside WriteFile", exc));
412        }
413    }
414
415    /**
416     * reverses the first vblCounter points
417     *
418     * @param pLowerLinePoints OUT - points to reverse
419     * @param vblCounter
420     */
421    protected static void ReversePointsDouble2(POINT2[] pLowerLinePoints,
422            int vblCounter) {
423        try {
424            POINT2[] pResultPoints = new POINT2[vblCounter];
425            int k = 0;
426            for (k = 0; k < vblCounter; k++) {
427                pResultPoints[k] = new POINT2(pLowerLinePoints[vblCounter - k - 1]);
428            }
429            for (k = 0; k < vblCounter; k++) {
430                pLowerLinePoints[k] = new POINT2(pResultPoints[k]);
431            }
432            pResultPoints = null;
433        } catch (Exception exc) {
434            ErrorLogger.LogException(_className, "ReversePointsDouble2",
435                    new RendererException("Failed inside ReversePointsDouble2", exc));
436        }
437    }
438
439    public static boolean CalcTrueSlopeDoubleForRoutes(POINT2 firstLinePoint,
440            POINT2 lastLinePoint,
441            ref<double[]> slope) {
442        try {
443            double deltaX = 0, deltaY = 0;
444            deltaX = (double) (firstLinePoint.x) - (double) (lastLinePoint.x);
445            if (Math.abs(deltaX) < 2) //was 2,infinite slope
446            {
447                return (false);
448            }
449
450            deltaY = (double) (firstLinePoint.y) - (double) (lastLinePoint.y);
451            if (slope.value == null) {
452                slope.value = new double[1];
453            }
454
455            slope.value[0] = deltaY / deltaX;
456        } catch (Exception exc) {
457            ErrorLogger.LogException(_className, "CalcTrueSlopeDoubleForRoutes",
458                    new RendererException("Failed inside CalcTrueSlopeDoubleForRoutes", exc));
459        }
460        return true;
461    }
462
463    /**
464     * Computes the slope of a line
465     *
466     * @param firstLinePoint the first line point
467     * @param lastLinePoint the last line point
468     * @param slope OUT - object with member to hold the slope of the line
469     *
470     * @return true if successful
471     */
472    public static boolean CalcTrueSlopeDouble2(POINT2 firstLinePoint,
473            POINT2 lastLinePoint,
474            ref<double[]> slope) {
475        Boolean result = true;
476        try {
477            double deltaX = 0, deltaY = 0;
478            deltaX = (double) (firstLinePoint.x) - (double) (lastLinePoint.x);
479            //if (deltaX == 0)
480            if (Math.abs(deltaX) < 1) 
481            {
482                //deltaX = 1;
483                if(deltaX>=0)
484                    deltaX=1;
485                else
486                    deltaX=-1;
487                result = false;
488            }
489
490            deltaY = (double) (firstLinePoint.y) - (double) (lastLinePoint.y);
491            if (slope.value == null) {
492                slope.value = new double[1];
493            }
494
495            slope.value[0] = deltaY / deltaX;
496        } catch (Exception exc) {
497            ErrorLogger.LogException(_className, "CalcTrueSlopeDouble2",
498                    new RendererException("Failed inside CalcTrueSlopeDouble2", exc));
499        }
500        return result;
501    }
502
503    /**
504     * Calculates the slopes and y intercepts in pixels for the line from pt1 to
505     * pt2 and a parallel line a vertical distance from the line
506     *
507     * @param nDistance the distance in pixels
508     * @param linePoint1 first point on the line
509     * @param linePoint2 last point on the line
510     * @param pdResult OUT - array to hold m, b for both lines
511     *
512     * @return 1 if the lines are not vertical, else return 0
513     */
514    protected static int CalcTrueLinesDouble(long nDistance,
515            POINT2 linePoint1,
516            POINT2 linePoint2,
517            ref<double[]> pdResult) //for vertical line e.g. if line equation is x=7
518    {
519        try {
520            //declarations
521            int nTemp = 0;
522            double b = 0;
523            double delta = 0;
524            ref<double[]> m = new ref();
525            //end declarations
526            nTemp = CalcTrueSlopeDouble(linePoint1, linePoint2, m);
527            pdResult.value = new double[6];
528            //Fill the result array with the line parameters
529            if (nTemp == 0) //vertical lines
530            {
531                pdResult.value[3] = linePoint1.x + (double) nDistance;  //the lower line eqn, e.g. x=7
532                pdResult.value[5] = linePoint1.x - (double) nDistance;  //the upper line eqn,
533                return 0;
534            } else {
535                b = linePoint2.y - m.value[0] * linePoint2.x;
536                delta = Math.sqrt(m.value[0] * m.value[0] * ((double) (nDistance) * (double) (nDistance))
537                        + ((double) (nDistance) * (double) (nDistance)));
538                pdResult.value[0] = m.value[0];    //original line eq'n: y = mx + b
539                pdResult.value[1] = b;
540                pdResult.value[2] = m.value[0];    //lower line eq'n: y = mx + (b+dDistance)
541                pdResult.value[3] = b + delta;
542                pdResult.value[4] = m.value[0];    //upper line eq'n: y = mx + (b-dDistance)
543                pdResult.value[5] = b - delta;
544            }
545        } catch (Exception exc) {
546            ErrorLogger.LogException(_className, "CalcTrueLinesDouble",
547                    new RendererException("Failed inside CalcTrueLinesDouble", exc));
548        }
549        return 1;
550    }
551
552    /**
553     * Calculates the intersection of two lines.
554     *
555     * @param m1 slope of first line
556     * @param b1 Y intercept of first line
557     * @param m2 slope of second line
558     * @param b2 Y intercept of second line
559     * @param bolVertical1 0 if first line is vertical, else 1
560     * @param bolVertical2 0 if second line is vertical, else 1
561     * @param X1 X intercept if first line is vertical
562     * @param X2 X intercept if 2nd line is vertical.
563     *
564     * @return intersection point
565     */
566    public static POINT2 CalcTrueIntersectDouble2(double m1,
567            double b1,
568            double m2,
569            double b2,
570            int bolVertical1,
571            int bolVertical2,
572            double X1, //x intercept if line1 is vertical
573            double X2) {
574        POINT2 ptIntersect = new POINT2();
575        try {
576            //declarations
577            double x = 0, y = 0;
578            //end declarations
579
580            //initialize ptIntersect
581            ptIntersect.x = X1;
582            ptIntersect.y = X2;
583            if (bolVertical1 == 0 && bolVertical2 == 0) //both lines vertical
584            {
585                return ptIntersect;
586            }
587            //the following 3 if blocks are the only ways to get an intersection
588            if (bolVertical1 == 0 && bolVertical2 == 1) //line1 vertical, line2 not
589            {
590                ptIntersect.x = X1;
591                ptIntersect.y = m2 * X1 + b2;
592                return ptIntersect;
593            }
594            if (bolVertical1 == 1 && bolVertical2 == 0) //line2 vertical, line1 not
595            {
596                ptIntersect.x = X2;
597                ptIntersect.y = m1 * X2 + b1;
598                return ptIntersect;
599            }
600            //if either of the lines is vertical function has already returned
601            //so both m1 and m2 should be valid
602            if (m1 != m2) {
603                x = (b2 - b1) / (m1 - m2);      //cannot blow up
604                y = (m1 * x + b1);
605                ptIntersect.x = x;
606                ptIntersect.y = y;
607                return ptIntersect;
608            }
609        } catch (Exception exc) {
610            ErrorLogger.LogException(_className, "CalcTrueIntersectDouble2",
611                    new RendererException("Failed inside CalcTrueIntersectDouble2", exc));
612        }
613        return ptIntersect;
614    }
615
616    /**
617     * Calculates an offset point for channel types which require arrows.
618     *
619     * @param startLinePoint the first point
620     * @param endLinePoint the last point
621     * @param nOffset the offset in pixels
622     *
623     * @return the offset point
624     */
625    protected static POINT2 GetOffsetPointDouble(POINT2 startLinePoint,
626            POINT2 endLinePoint,
627            long nOffset) {
628        POINT2 tempLinePoint = new POINT2(startLinePoint);
629        try {
630            //declarations
631            double dx = endLinePoint.x - startLinePoint.x,
632                    dy = endLinePoint.y - startLinePoint.y,
633                    dOffset = (double) nOffset,
634                    dHypotenuse = 0,
635                    dAngle = 0;
636
637            //end declarations
638            if (dx == 0) {
639                if (dy > 0) {
640                    tempLinePoint.x = endLinePoint.x;
641                    tempLinePoint.y = endLinePoint.y + dOffset;
642                } else {
643                    tempLinePoint.x = endLinePoint.x;
644                    tempLinePoint.y = endLinePoint.y - dOffset;
645                }
646                return tempLinePoint;
647            }
648            if (dy == 0) {
649                if (dx > 0) {
650                    tempLinePoint.x = endLinePoint.x + dOffset;
651                    tempLinePoint.y = endLinePoint.y;
652                } else {
653                    tempLinePoint.x = endLinePoint.x - dOffset;
654                    tempLinePoint.y = endLinePoint.y;
655                }
656                return tempLinePoint;
657            }
658
659            if (dy == 0) {
660                dAngle = 0;
661            } else {
662                dAngle = Math.atan(dx / dy) + Math.PI / 2;//1.570795;
663            }
664            dHypotenuse = (double) nOffset;
665            if (endLinePoint.x > startLinePoint.x) {
666                tempLinePoint.x = endLinePoint.x + dHypotenuse * Math.abs(Math.cos(dAngle));
667            } else {
668                tempLinePoint.x = endLinePoint.x - dHypotenuse * Math.abs(Math.cos(dAngle));
669            }
670            if (endLinePoint.y > startLinePoint.y) {
671                tempLinePoint.y = endLinePoint.y + dHypotenuse * Math.abs(Math.sin(dAngle));
672            } else {
673                tempLinePoint.y = endLinePoint.y - dHypotenuse * Math.abs(Math.sin(dAngle));
674            }
675
676        } catch (Exception exc) {
677            ErrorLogger.LogException(_className, "GetOffsetPointDouble",
678                    new RendererException("Failed inside GetOffsetPointDouble", exc));
679        }
680        return (tempLinePoint);
681    }
682
683    /**
684     * Used for DMAF
685     *
686     * @param pLinePoints the client points
687     * @return ArrayList of X points
688     */
689    protected static ArrayList LineOfXPoints(TGLight tg, POINT2[] pLinePoints) {
690        ArrayList xPoints = new ArrayList();
691        try {
692            int j = 0, k = 0;
693            double dist = 0;
694            int iterations = 0;
695            POINT2 frontPt = null, backPt = null;
696            POINT2 extendFrontAbove = null, extendFrontBelow = null;
697            POINT2 extendBackAbove = null, extendBackBelow = null;
698            POINT2 xPoint1 = null, xPoint2 = null;
699            int n=pLinePoints.length;
700            final double xSize = arraysupport.getScaledSize(5, tg.get_LineThickness());
701            final double dIncrement = xSize * 4;
702            //for (j = 0; j < pLinePoints.length - 1; j++) 
703            for (j = 0; j < n - 1; j++) 
704            {
705                dist = CalcDistanceDouble(pLinePoints[j], pLinePoints[j + 1]);
706                iterations = (int) ((dist - xSize) / dIncrement);
707                if (dist - iterations * dIncrement > dIncrement / 2) {
708                    iterations += 1;
709                }
710
711                for (k = 0; k < iterations; k++) {
712                    frontPt = ExtendAlongLineDouble(pLinePoints[j], pLinePoints[j + 1], k * dIncrement - xSize);
713                    backPt = ExtendAlongLineDouble(pLinePoints[j], pLinePoints[j + 1], k * dIncrement + xSize);
714                    extendFrontAbove = ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], frontPt, 2, xSize);
715                    extendFrontBelow = ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], frontPt, 3, xSize);
716                    extendBackAbove = ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], backPt, 2, xSize);
717                    extendBackBelow = ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], backPt, 3, xSize);
718                    xPoints.add(extendFrontAbove);
719                    extendBackBelow.style = 5;
720                    xPoints.add(extendBackBelow);
721                    xPoints.add(extendBackAbove);
722                    extendFrontBelow.style = 5;
723                    xPoints.add(extendFrontBelow);
724                }
725            }
726        } catch (Exception exc) {
727            ErrorLogger.LogException(_className, "LineOfXPoints",
728                    new RendererException("Failed inside LineOfXPoints", exc));
729        }
730        return xPoints;
731    }
732
733    /**
734     * Computes the distance in pixels of pt3 to the line from pt1 to pt2.
735     *
736     * @param pt1 first line point
737     * @param pt2 last line point
738     * @param pt3 point distance to compute
739     * @return distance to pt3
740     */
741    public static double CalcDistanceToLineDouble(POINT2 pt1,
742            POINT2 pt2,
743            POINT2 pt3) {
744        double dResult = 0;
745        try {
746            //declarations
747            double m1 = 1, b = 0, b1 = 0;
748            POINT2 ptIntersect = new POINT2(pt1);
749            int bolVertical = 0;
750            ref<double[]> m = new ref();
751            //end declarations
752
753            bolVertical = CalcTrueSlopeDouble(pt1, pt2, m);
754
755            //get line y intercepts
756            if (bolVertical != 0 && m.value[0] != 0) {
757                m1 = -1 / m.value[0];
758                b = pt1.y - m.value[0] * pt1.x;
759                b1 = pt3.y - m1 * pt3.x;
760                ptIntersect = CalcTrueIntersectDouble2(m.value[0], b, m1, b1, 1, 1, ptIntersect.x, ptIntersect.y);
761            }
762            if (bolVertical != 0 && m.value[0] == 0) //horizontal line
763            {
764                ptIntersect.y = pt1.y;
765                ptIntersect.x = pt3.x;
766            }
767            if (bolVertical == 0) //vertical line
768            {
769                ptIntersect.y = pt3.y;
770                ptIntersect.x = pt1.x;
771            }
772
773            dResult = CalcDistanceDouble(pt3, ptIntersect);
774        } catch (Exception exc) {
775            //System.out.println(e.getMessage());
776            ErrorLogger.LogException(_className, "CaclDistanceToLineDouble",
777                    new RendererException("Failed inside CalcDistanceToLineDouble", exc));
778        }
779        return dResult;
780    }
781
782    /**
783     * Calculates a point along a line. Returns the past point if the distance
784     * is 0.
785     *
786     * @param pt1 first line point
787     * @param pt2 last line point
788     * @param dist extension distance in pixels from the beginning of the line
789     *
790     * @return the extension point
791     */
792    public static POINT2 ExtendLineDouble(POINT2 pt1,
793            POINT2 pt2,
794            double dist) {
795        POINT2 pt3 = new POINT2();
796        try {
797            double dOriginalDistance = CalcDistanceDouble(pt1, pt2);
798            if (dOriginalDistance == 0 || dist == 0) {
799                return pt2;
800            }
801
802            pt3.x = (dOriginalDistance + dist) / dOriginalDistance * (pt2.x - pt1.x) + pt1.x;
803            pt3.y = (dOriginalDistance + dist) / dOriginalDistance * (pt2.y - pt1.y) + pt1.y;
804        } catch (Exception exc) {
805            //System.out.println(e.getMessage());
806            ErrorLogger.LogException(_className, "ExtendLineDouble",
807                    new RendererException("Failed inside ExtendLineDouble", exc));
808        }
809        return pt3;
810    }
811
812    /**
813     * Extends a point along a line. If dist is 0 returns last point.
814     *
815     * @param pt1 first point on the line
816     * @param pt2 last point on the line
817     * @param dist the distance in pixels from pt1
818     *
819     * @return the extended point
820     */
821    public static POINT2 ExtendAlongLineDouble(POINT2 pt1, POINT2 pt2, double dist) {
822        POINT2 pt3 = new POINT2();
823        try {
824            double dOriginalDistance = CalcDistanceDouble(pt1, pt2);
825            if (dOriginalDistance == 0 || dist == 0) {
826                return pt2;
827            }
828
829            pt3.x = ((dist / dOriginalDistance) * (pt2.x - pt1.x) + pt1.x);
830            pt3.y = ((dist / dOriginalDistance) * (pt2.y - pt1.y) + pt1.y);
831        } catch (Exception exc) {
832            //System.out.println(e.getMessage());
833            ErrorLogger.LogException(_className, "ExtendAlongLineDouble",
834                    new RendererException("Failed inside ExtendAlongLineDouble", exc));
835        }
836        return pt3;
837    }
838
839    public static POINT2 ExtendAlongLineDouble2(POINT2 pt1, POINT2 pt2, double dist) {
840        POINT2 pt3 = new POINT2();
841        try {
842            double dOriginalDistance = CalcDistanceDouble(pt1, pt2);
843            if (dOriginalDistance == 0 || dist == 0) {
844                return pt1;
845            }
846
847            pt3.x = (dist / dOriginalDistance * (pt2.x - pt1.x) + pt1.x);
848            pt3.y = (dist / dOriginalDistance * (pt2.y - pt1.y) + pt1.y);
849        } catch (Exception exc) {
850            //System.out.println(e.getMessage());
851            ErrorLogger.LogException(_className, "ExtendAlongLineDouble2",
852                    new RendererException("Failed inside ExtendAlongLineDouble2", exc));
853        }
854        return pt3;
855    }
856
857    public static Point2D ExtendAlongLineDouble2(Point2D pt1, Point2D pt2, double dist) {
858        try {
859            double dOriginalDistance = CalcDistanceDouble(pt1, pt2);
860            if (dOriginalDistance == 0 || dist == 0) {
861                return new Point2D.Double(pt1.getX(), pt1.getY());
862            }
863
864            double x = (dist / dOriginalDistance * (pt2.getX() - pt1.getX()) + pt1.getX());
865            double y = (dist / dOriginalDistance * (pt2.getY() - pt1.getY()) + pt1.getY());
866            return new Point2D.Double(x, y);
867        } catch (Exception exc) {
868            ErrorLogger.LogException(_className, "ExtendAlongLineDouble2",
869                    new RendererException("Failed inside ExtendAlongLineDouble2", exc));
870        }
871        return new Point2D.Double(0, 0);
872    }
873
874    public static POINT2 ExtendAlongLineDouble(POINT2 pt1, POINT2 pt2, double dist, int styl) {
875        POINT2 pt3 = new POINT2();
876        try {
877            double dOriginalDistance = CalcDistanceDouble(pt1, pt2);
878            if (dOriginalDistance == 0 || dist == 0) {
879                return pt2;
880            }
881
882            pt3.x = (dist / dOriginalDistance * (pt2.x - pt1.x) + pt1.x);
883            pt3.y = (dist / dOriginalDistance * (pt2.y - pt1.y) + pt1.y);
884            pt3.style = styl;
885        } catch (Exception exc) {
886            //System.out.println(e.getMessage());
887            ErrorLogger.LogException(_className, "ExtendAlongLineDouble",
888                    new RendererException("Failed inside ExtendAlongLineDouble", exc));
889        }
890        return pt3;
891    }
892
893    /**
894     * Extends a point above a line
895     *
896     * @param pt1 first line point
897     * @param pt2 last line point
898     * @param pt3 point at which to extend
899     * @param d distance in pixels to extend above the line
900     * @param X OUT - extended point x value
901     * @param Y OUT - extended point y value
902     * @param direction direction to extend the line
903     *
904     * @return 1 if successful, else return 0
905     */
906    protected static int ExtendLineAbove(POINT2 pt1,
907            POINT2 pt2,
908            POINT2 pt3,
909            double d,
910            ref<double[]> X,
911            ref<double[]> Y,
912            int direction) {
913        try {
914            ref<double[]> m = new ref();
915            double dx = 0, dy = 0;
916            int bolVertical = 0;
917
918            X.value = new double[1];
919            Y.value = new double[1];
920
921            bolVertical = CalcTrueSlopeDouble(pt1, pt2, m);
922            if (bolVertical == 0) {
923                return 0;       //cannot extend above a vertical line
924            }
925            if (m.value[0] == 0) {
926                X.value[0] = pt3.x;
927                if (direction == 0) //extend above the line
928                {
929                    Y.value[0] = pt3.y - Math.abs(d);
930                } else //extend below the line
931                {
932                    Y.value[0] = pt3.y + Math.abs(d);
933                }
934                return 1;
935            }
936            //the line is neither vertical nor horizontal
937            //else function would already have returned
938            if (direction == 0) //extend above the line
939            {
940                dy = -Math.abs(d / (m.value[0] * Math.sqrt(1 + 1 / (m.value[0] * m.value[0]))));
941            } else //extend below the line
942            {
943                dy = Math.abs(d / (m.value[0] * Math.sqrt(1 + 1 / (m.value[0] * m.value[0]))));
944            }
945
946            dx = -m.value[0] * dy;
947            X.value[0] = pt3.x + dx;
948            Y.value[0] = pt3.y + dy;
949        } catch (Exception exc) {
950            //System.out.println(e.getMessage());
951            ErrorLogger.LogException(_className, "ExtendLineAbove",
952                    new RendererException("Failed inside ExtendLineAbove", exc));
953        }
954        return 1;
955    }
956
957    /**
958     * Extends a point to the left of a line
959     *
960     * @param pt1 first line point
961     * @param pt2 last line point
962     * @param pt3 point at which to extend
963     * @param d distance in pixels to extend above the line
964     * @param X OUT - extended point x value
965     * @param Y OUT - extended point y value
966     * @param direction direction to extend the line
967     *
968     * @return 1 if successful, else return 0
969     */
970    protected static int ExtendLineLeft(POINT2 pt1,
971            POINT2 pt2,
972            POINT2 pt3,
973            double d,
974            ref<double[]> X,
975            ref<double[]> Y,
976            int direction) {
977        try {
978            ref<double[]> m = new ref();
979            double dx = 0, dy = 0;
980            int bolVertical = 0;
981
982            X.value = new double[1];
983            Y.value = new double[1];
984
985            bolVertical = CalcTrueSlopeDouble(pt1, pt2, m);
986            if (bolVertical != 0 && m.value[0] == 0) {
987                return 0;       //cannot left of horiz line
988            }
989            if (bolVertical == 0) //vertical line
990            {
991                Y.value[0] = pt3.y;
992                if (direction == 0) //extend left of the line
993                {
994                    X.value[0] = pt3.x - Math.abs(d);
995                } else //extend right of the line
996                {
997                    X.value[0] = pt3.x + Math.abs(d);
998                }
999
1000                return 1;
1001            }
1002            //the line is neither vertical nor horizontal
1003            //else function would already have returned
1004            if (direction == 0) //extend left of the line
1005            {
1006                dx = -Math.abs(d / Math.sqrt(1 + 1 / (m.value[0] * m.value[0])));
1007            } else //extend right of the line
1008            {
1009                dx = Math.abs(d / Math.sqrt(1 + 1 / (m.value[0] * m.value[0])));
1010            }
1011
1012            dy = -(1 / m.value[0]) * dx;
1013
1014            X.value[0] = pt3.x + dx;
1015            Y.value[0] = pt3.y + dy;
1016        } catch (Exception exc) {
1017            //System.out.println(e.getMessage());
1018            ErrorLogger.LogException(_className, "ExtendLineLeft",
1019                    new RendererException("Failed inside ExtendLineLeft", exc));
1020        }
1021        return 1;
1022    }
1023
1024    /**
1025     * Calculates the direction of a point relative to a line
1026     *
1027     * @param pt0 first point fo the line
1028     * @param pt1 last point of the line
1029     * @param pt2 relative point
1030     * @deprecated
1031     * @return 0 if left, 1 if right, 2 if above, 3 if below
1032     */
1033    protected static int CalcDirectionFromLine(POINT2 pt0,
1034            POINT2 pt1,
1035            POINT2 pt2) {
1036        int result = -1;
1037        try {
1038            double m2 = 0, b1 = 0, b2 = 0;
1039            ref<double[]> m1 = new ref();
1040            POINT2 ptIntersect = new POINT2();
1041            //int direction=-1;
1042            //handle vertical line
1043            if (pt0.x == pt1.x) {
1044                if (pt2.x < pt0.x) {
1045                    return 0;
1046                } else {
1047                    return 1;
1048                }
1049            }
1050            //handle horizontal line so that we do not have slope = 0.
1051            if (pt0.y == pt1.y) {
1052                if (pt2.y < pt0.y) {
1053                    return 2;
1054                } else {
1055                    return 3;
1056                }
1057            }
1058            CalcTrueSlopeDouble(pt0, pt1, m1);
1059            m2 = -1 / m1.value[0];      //slope for the perpendicular line from the line to pt2
1060            //b=mx-y line equation for line
1061            b1 = pt0.y - m1.value[0] * pt0.x;
1062            //b=mx-y line equation for perpendicular line which contains pt2
1063            b2 = pt2.y - m2 * pt2.x;
1064            ptIntersect = CalcTrueIntersectDouble2(m1.value[0], b1, m2, b2, 1, 1, 0, 0);
1065            //compare the intersection point with pt2 to get the direction,
1066            //i.e. the direction from the line is the same as the direction
1067            //from the interseciton point.
1068            if (m1.value[0] > 1) //line is steep, use left/right
1069            {
1070                if (pt2.x < ptIntersect.x) {
1071                    return 0;
1072                } else {
1073                    return 1;
1074                }
1075            } else //line is not steep, use above/below
1076            {
1077                if (pt2.y < ptIntersect.y) {
1078                    return 2;
1079                } else {
1080                    return 3;
1081                }
1082            }
1083            //should not reach this point
1084            //return direction;
1085        } catch (Exception e) {
1086            System.out.println(e.getMessage());
1087        }
1088        return result;
1089    }
1090
1091    /**
1092     * Returns a point extended perpendicularly from a line at a given direction
1093     *
1094     * @param pt1 first line point
1095     * @param pt2 last line point
1096     * @param pt0 on line from which to extend
1097     * @param direction the direction to extend: above, below, left, right
1098     * @param d the length to extend in pixels
1099     *
1100     */
1101    public static POINT2 ExtendDirectedLine(POINT2 pt1,
1102            POINT2 pt2,
1103            POINT2 pt0,
1104            int direction,
1105            double d) {
1106        POINT2 ptResult = new POINT2();
1107        try {
1108            ref<double[]> X = new ref(), Y = new ref();
1109            ptResult = new POINT2(pt0);
1110            switch (direction) {
1111                case 0: //extend left
1112                    ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 0);
1113                    break;
1114                case 1: //extend right
1115                    ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 1);
1116                    break;
1117                case 2: //extend above
1118                    ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 0);
1119                    break;
1120                case 3: //extend below
1121                    ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 1);
1122                    break;
1123                default:
1124                    break;
1125            }
1126            ptResult.x = X.value[0];
1127            ptResult.y = Y.value[0];
1128        } catch (Exception exc) {
1129            //System.out.println(e.getMessage());
1130            ErrorLogger.LogException(_className, "ExtendDirectedLine",
1131                    new RendererException("Failed inside ExtendDirectedLine", exc));
1132        }
1133        return ptResult;
1134    }
1135
1136    /**
1137     * @deprecated Returns a point extended perpendicularly from a line at a
1138     * given direction same as original function except it accounts for vertical
1139     * lines and negative d values
1140     *
1141     * @param pt1 first line point
1142     * @param pt2 last line point
1143     * @param pt0 on line from which to extend
1144     * @param direction the direction to extend: above, below, left, right
1145     * @param d the length to extend in pixels
1146     *
1147     */
1148    public static POINT2 ExtendDirectedLineText(POINT2 pt1,
1149            POINT2 pt2,
1150            POINT2 pt0,
1151            int direction,
1152            double d) {
1153        POINT2 ptResult = new POINT2();
1154        try {
1155            ref<double[]> X = new ref(), Y = new ref();
1156            ptResult = new POINT2(pt0);
1157            if (d < 0) {
1158                switch (direction) {
1159                    case 0:
1160                        direction = extend_right;
1161                        break;
1162                    case 1:
1163                        direction = extend_left;
1164                        break;
1165                    case 2:
1166                        direction = extend_below;
1167                        break;
1168                    case 3:
1169                        direction = extend_above;
1170                        break;
1171                    default:
1172                        break;
1173                }
1174                d = Math.abs(d);
1175            }
1176            if (pt1.y == pt2.y)//horizontal segment
1177            {
1178                switch (direction) {
1179                    case 0://left means above
1180                        direction = extend_above;
1181                        break;
1182                    case 1://right means below
1183                        direction = extend_below;
1184                        break;
1185                    default:
1186                        break;
1187                }
1188            }
1189            if (pt1.x == pt2.x)//vertical segment
1190            {
1191                switch (direction) {
1192                    case 2://above means left
1193                        direction = extend_left;
1194                        break;
1195                    case 3://below means right
1196                        direction = extend_right;
1197                        break;
1198                    default:
1199                        break;
1200                }
1201            }
1202            switch (direction) {
1203                case 0: //extend left
1204                    ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 0);
1205                    break;
1206                case 1: //extend right
1207                    ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 1);
1208                    break;
1209                case 2: //extend above
1210                    ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 0);
1211                    break;
1212                case 3: //extend below
1213                    ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 1);
1214                    break;
1215                default:
1216                    break;
1217            }
1218            ptResult.x = X.value[0];
1219            ptResult.y = Y.value[0];
1220        } catch (Exception exc) {
1221            //System.out.println(e.getMessage());
1222            ErrorLogger.LogException(_className, "ExtendDirectedLine",
1223                    new RendererException("Failed inside ExtendDirectedLine", exc));
1224        }
1225        return ptResult;
1226    }
1227
1228    /**
1229     * Returns a point extended perpendicularly from a line at a given direction
1230     *
1231     * @param pt1 first line point
1232     * @param pt2 last line point
1233     * @param pt0 on line from which to extend
1234     * @param direction the direction to extend: above, below, left, right
1235     * @param d the length to extend in pixels
1236     * @param style the style to assign the return point
1237     *
1238     */
1239    public static POINT2 ExtendDirectedLine(POINT2 pt1,
1240            POINT2 pt2,
1241            POINT2 pt0,
1242            int direction,
1243            double d,
1244            int style) {
1245        POINT2 ptResult = new POINT2(pt0);
1246        try {
1247            ref<double[]> X = new ref(), Y = new ref();
1248            //int bolResult=0;
1249            //handle parallel, perpendicular cases
1250            if (pt1.x == pt2.x) {
1251                if (direction == 2) {
1252                    direction = 0;
1253                }
1254                if (direction == 3) {
1255                    direction = 1;
1256                }
1257            }
1258            if (pt1.y == pt2.y) {
1259                if (direction == 0) {
1260                    direction = 2;
1261                }
1262                if (direction == 1) {
1263                    direction = 3;
1264                }
1265            }
1266            switch (direction) {
1267                case 0: //extend left
1268                    ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 0);
1269                    break;
1270                case 1: //extend right
1271                    ExtendLineLeft(pt1, pt2, pt0, d, X, Y, 1);
1272                    break;
1273                case 2: //extend above
1274                    ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 0);
1275                    break;
1276                case 3: //extend below
1277                    ExtendLineAbove(pt1, pt2, pt0, d, X, Y, 1);
1278                    break;
1279            }
1280            ptResult.x = X.value[0];
1281            ptResult.y = Y.value[0];
1282            ptResult.style = style;
1283        } catch (Exception exc) {
1284            ErrorLogger.LogException(_className, "ExtendDirectedLine",
1285                    new RendererException("Failed inside ExtendDirectedLine", exc));
1286        }
1287        return ptResult;
1288    }
1289
1290    /**
1291     * Calculates a point along a line
1292     *
1293     * @param pt1 first line point
1294     * @param pt2 last line point
1295     * @param dist extension distance in pixels from the beginning of the line
1296     * @param styl the line style to assign the point
1297     *
1298     * @return the extension point
1299     */
1300    protected static POINT2 ExtendLine2Double(POINT2 pt1,
1301            POINT2 pt2,
1302            double dist,
1303            int styl) {
1304        POINT2 pt3 = new POINT2();
1305        try {
1306            double dOriginalDistance = CalcDistanceDouble(pt1, pt2);
1307
1308            pt3.x = pt2.x;
1309            pt3.y = pt2.y;
1310            if (dOriginalDistance > 0) {
1311                pt3.x = ((dOriginalDistance + dist) / dOriginalDistance * (pt2.x - pt1.x) + pt1.x);
1312                pt3.y = ((dOriginalDistance + dist) / dOriginalDistance * (pt2.y - pt1.y) + pt1.y);
1313                pt3.style = styl;
1314            }
1315        } catch (Exception exc) {
1316            ErrorLogger.LogException(_className, "ExtendLine2Double",
1317                    new RendererException("Failed inside ExtendLine2Double", exc));
1318        }
1319        return pt3;
1320    }
1321
1322    /**
1323     * Extends a point at an angle from a line.
1324     *
1325     * @param pt0 the first line point
1326     * @param pt1 the second line point
1327     * @param pt2 point on line from which to extend
1328     * @param alpha angle of extension in degrees
1329     * @param d the distance in pixels to extend
1330     *
1331     * @return the extension point
1332     */
1333    public static POINT2 ExtendAngledLine(POINT2 pt0,
1334            POINT2 pt1,
1335            POINT2 pt2,
1336            double alpha,
1337            double d) {
1338        POINT2 pt = new POINT2();
1339        try {
1340            //first get the angle psi between pt0 and pt1
1341            double psi = Math.atan((pt1.y - pt0.y) / (pt1.x - pt0.x));
1342            //convert alpha to radians
1343            double alpha1 = Math.PI * alpha / 180;
1344
1345            //theta is the angle of extension from the x axis
1346            double theta = psi + alpha1;
1347            //dx is the x extension from pt2
1348            double dx = d * Math.cos(theta);
1349            //dy is the y extension form pt2
1350            double dy = d * Math.sin(theta);
1351            pt.x = pt2.x + dx;
1352            pt.y = pt2.y + dy;
1353        } catch (Exception exc) {
1354            ErrorLogger.LogException(_className, "ExtendAngledLine",
1355                    new RendererException("Failed inside ExtendAngledLine", exc));
1356        }
1357        return pt;
1358    }
1359
1360    /**
1361     * Returns an integer indicating the quadrant for the direction of the line
1362     * from pt1 to pt2
1363     *
1364     * @param pt1 first line point
1365     * @param pt2 second line point
1366     *
1367     * @return the quadrant
1368     */
1369    public static int GetQuadrantDouble(POINT2 pt1,
1370            POINT2 pt2) {
1371        int nQuadrant = 1;
1372        try {
1373            if (pt2.x >= pt1.x && pt2.y <= pt1.y) {
1374                nQuadrant = 1;
1375            }
1376            if (pt2.x >= pt1.x && pt2.y >= pt1.y) {
1377                nQuadrant = 2;
1378            }
1379            if (pt2.x <= pt1.x && pt2.y >= pt1.y) {
1380                nQuadrant = 3;
1381            }
1382            if (pt2.x <= pt1.x && pt2.y <= pt1.y) {
1383                nQuadrant = 4;
1384            }
1385
1386        } catch (Exception exc) {
1387            ErrorLogger.LogException(_className, "GetQuadrantDouble",
1388                    new RendererException("Failed inside GetQuadrantDouble", exc));
1389        }
1390        return nQuadrant;
1391    }
1392
1393    public static int GetQuadrantDouble(double x1, double y1,
1394            double x2, double y2) {
1395        int nQuadrant = 1;
1396        try {
1397//            if(pt2.x>=pt1.x && pt2.y<=pt1.y)
1398//                    nQuadrant=1;
1399//            if(pt2.x>=pt1.x && pt2.y>=pt1.y)
1400//                    nQuadrant=2;
1401//            if(pt2.x<=pt1.x && pt2.y>=pt1.y)
1402//                    nQuadrant=3;
1403//            if(pt2.x<=pt1.x && pt2.y<=pt1.y)
1404//                    nQuadrant=4;
1405
1406            if (x2 >= x1 && y2 <= y1) {
1407                nQuadrant = 1;
1408            }
1409            if (x2 >= x1 && y2 >= y1) {
1410                nQuadrant = 2;
1411            }
1412            if (x2 <= x1 && y2 >= y1) {
1413                nQuadrant = 3;
1414            }
1415            if (x2 <= x1 && y2 <= y1) {
1416                nQuadrant = 4;
1417            }
1418        } catch (Exception exc) {
1419            ErrorLogger.LogException(_className, "GetQuadrantDouble",
1420                    new RendererException("Failed inside GetQuadrantDouble", exc));
1421        }
1422        return nQuadrant;
1423    }
1424
1425    /**
1426     * Returns the smallest x and y pixel values from an array of points
1427     *
1428     * @param ptsSeize array of points from which to find minimum vaules
1429     * @param vblCounter the number of points to test in the array
1430     * @param x OUT - an object with a member to hold the xminimum
1431     * @param y OUT - an object with a member to hold the y minimum value
1432     *
1433     */
1434    public static void GetPixelsMin(POINT2[] ptsSeize,
1435            int vblCounter,
1436            ref<double[]> x,
1437            ref<double[]> y) {
1438        try {
1439            double xmin = Double.POSITIVE_INFINITY;
1440            double ymin = Double.POSITIVE_INFINITY;
1441            int j = 0;
1442
1443            for (j = 0; j < vblCounter; j++) {
1444                if (ptsSeize[j].x < xmin) {
1445                    xmin = ptsSeize[j].x;
1446                }
1447                if (ptsSeize[j].y < ymin) {
1448                    ymin = ptsSeize[j].y;
1449                }
1450            }
1451            x.value = new double[1];
1452            y.value = new double[1];
1453            x.value[0] = xmin;
1454            y.value[0] = ymin;
1455        } catch (Exception exc) {
1456            ErrorLogger.LogException(_className, "GetPixelsMin",
1457                    new RendererException("Failed inside GetPixelsMin", exc));
1458        }
1459    }
1460
1461    /**
1462     * Returns the largest x and y pixel values from an array of points
1463     *
1464     * @param ptsSeize array of points from which to find maximum values
1465     * @param vblCounter the number of points to test in the array
1466     * @param x OUT - an object with a member to hold the x maximum value
1467     * @param y OUT - an object with a member to hold the y maximum value
1468     *
1469     */
1470    public static void GetPixelsMax(POINT2[] ptsSeize,
1471                                    int vblCounter,
1472                                    ref<double[]> x,
1473                                    ref<double[]> y) {
1474        try {
1475            double xmax = Double.NEGATIVE_INFINITY;
1476            double ymax = Double.NEGATIVE_INFINITY;
1477            int j = 0;
1478
1479            for (j = 0; j < vblCounter; j++) {
1480                if (ptsSeize[j].x > xmax) {
1481                    xmax = ptsSeize[j].x;
1482                }
1483                if (ptsSeize[j].y > ymax) {
1484                    ymax = ptsSeize[j].y;
1485                }
1486            }
1487            x.value = new double[1];
1488            y.value = new double[1];
1489            x.value[0] = xmax;
1490            y.value[0] = ymax;
1491        } catch (Exception exc) {
1492            ErrorLogger.LogException(_className, "GetPixelsMax",
1493                    new RendererException("Failed inside GetPixelsMax", exc));
1494        }
1495    }
1496
1497    /**
1498     * Returns center point for a clockwise arc to connect pts 1 and 2. Also
1499     * returns an extended point on the line between pt1 and the new center
1500     * Caller passes a POINT1 array of size 2 for ptsSeize, passes pt1 and pt2
1501     * in ptsSeize Returns the radius of the 90 degree arc between C (arc
1502     * center) and pt1
1503     *
1504     * @param ptsSeize OUT - two point array also used for the returned two
1505     * points
1506     *
1507     * @return the radius
1508     */
1509    protected static double CalcClockwiseCenterDouble(POINT2[] ptsSeize) {
1510        double dRadius = 0;
1511        try {
1512            //declarations
1513            POINT2 pt1 = new POINT2(ptsSeize[0]);
1514            POINT2 pt2 = new POINT2(ptsSeize[1]);
1515            POINT2 C = new POINT2(pt1), midPt = new POINT2(pt1);        //the center to calculate
1516            POINT2 E = new POINT2(pt1); //the extended point to calculate
1517            POINT2 ptYIntercept = new POINT2(pt1);
1518            int nQuadrant = 1;
1519            double b = 0, b1 = 0, b2 = 0, dLength = 0;
1520            ref<double[]> m = new ref();
1521            int bolVertical = 0;
1522            ref<double[]> offsetX = new ref(), offsetY = new ref();
1523            POINT2[] ptsTemp = new POINT2[2];
1524            //end declarations
1525
1526            //must offset the points if necessary because there will be calculations
1527            //extending from the Y Intercept
1528            ptsTemp[0] = new POINT2(pt1);
1529            ptsTemp[1] = new POINT2(pt2);
1530            GetPixelsMin(ptsTemp, 2, offsetX, offsetY);
1531            if (offsetX.value[0] < 0) {
1532                offsetX.value[0] = offsetX.value[0] - 100;
1533            } else {
1534                offsetX.value[0] = 0;
1535            }
1536            //end section
1537
1538            midPt.x = (pt1.x + pt2.x) / 2;
1539            midPt.y = (pt1.y + pt2.y) / 2;
1540            dLength = CalcDistanceDouble(pt1, pt2);
1541            dRadius = dLength / Math.sqrt(2);
1542            nQuadrant = GetQuadrantDouble(pt1, pt2);
1543
1544            bolVertical = CalcTrueSlopeDouble(pt1, pt2, m);
1545            if (bolVertical != 0 && m.value[0] != 0) //line not vertical or horizontal
1546            {
1547                b = pt1.y - m.value[0] * pt1.x;
1548                //y intercept of line perpendicular to midPt of pt,p2
1549                b1 = midPt.y + (1 / m.value[0]) * midPt.x;
1550                //we want to shift the Y axis to the left by offsetX
1551                //so we get the new Y intercept at x=offsetX
1552                b2 = (-1 / m.value[0]) * offsetX.value[0] + b1;
1553                ptYIntercept.x = offsetX.value[0];
1554                ptYIntercept.y = b2;
1555                switch (nQuadrant) {
1556                    case 1:
1557                    case 4:
1558                        C = ExtendLineDouble(ptYIntercept, midPt, dLength / 2);
1559                        break;
1560                    case 2:
1561                    case 3:
1562                        C = ExtendLineDouble(ptYIntercept, midPt, -dLength / 2);
1563                        break;
1564                    default:
1565                        break;
1566                }
1567            }
1568            if (bolVertical != 0 && m.value[0] == 0) //horizontal line
1569            {
1570                C.x = midPt.x;
1571                if (pt1.x < pt2.x) {
1572                    C.y = midPt.y + dLength / 2;
1573                } else {
1574                    C.y = midPt.y - dLength / 2;
1575                }
1576            }
1577            if (bolVertical == 0) //vertical line
1578            {
1579                ptYIntercept.x = offsetX.value[0];
1580                ptYIntercept.y = midPt.y;
1581                switch (nQuadrant) {
1582                    case 1:
1583                    case 4:
1584                        C = ExtendLineDouble(ptYIntercept, midPt, dLength / 2);
1585                        break;
1586                    case 2:
1587                    case 3:
1588                        C = ExtendLineDouble(ptYIntercept, midPt, -dLength / 2);
1589                        break;
1590                    default:
1591                        break;
1592                }
1593            }
1594
1595            E = ExtendLineDouble(C, pt1, 50);
1596            ptsSeize[0] = new POINT2(C);
1597            ptsSeize[1] = new POINT2(E);
1598
1599            ptsTemp = null;
1600        } catch (Exception exc) {
1601            ErrorLogger.LogException(_className, "CalcClockwiseCenterDouble",
1602                    new RendererException("Failed inside CalcClockwiseCenterDouble", exc));
1603        }
1604        return dRadius;
1605    }
1606
1607    /**
1608     * Computes the points for an arrowhead based on a line segment
1609     *
1610     * @param startLinePoint segment start point
1611     * @param endLinePoint segment end point
1612     * @param nBiSector bisecotr in pixels
1613     * @param nBase base size in pixels
1614     * @param pResultLinePoints OUT - the arrowhead points
1615     * @param styl the line style to assign the last aroowhead point
1616     */
1617    protected static void GetArrowHead4Double(POINT2 startLinePoint,
1618            POINT2 endLinePoint,
1619            int nBiSector,
1620            int nBase,
1621            POINT2[] pResultLinePoints,
1622            int styl) {
1623        try {
1624            //declarations
1625            int j = 0;
1626            double dy = (double) (endLinePoint.y - startLinePoint.y),
1627                    dx = (double) (endLinePoint.x - startLinePoint.x),
1628                    dSign = 1.0,
1629                    AHBY = 0,
1630                    AHBX = 0,
1631                    AHBLY = 0,
1632                    AHBLX = 0,
1633                    AHBRY = 0,
1634                    AHBRX = 0,
1635                    dAngle = 0,
1636                    dHypotenuse = 0;
1637
1638            POINT2 tempLinePoint = new POINT2(startLinePoint);
1639            //end declarations
1640
1641            if (dy == 0) {
1642                if (dx > 0) {
1643                    dAngle = Math.PI;
1644                } else {
1645                    dAngle = 0;
1646                }
1647            } else {
1648                dAngle = Math.atan(dx / dy) + Math.PI / 2;
1649            }
1650
1651            tempLinePoint.style = 0;//PS_SOLID;
1652
1653            if (dx <= 0.0 && dy <= 0.0) {
1654                dSign = -1.0;
1655            }
1656            if (dx >= 0.0 && dy <= 0.0) {
1657                dSign = -1.0;
1658            }
1659            if (dx <= 0.0 && dy >= 0.0) {
1660                dSign = 1.0;
1661            }
1662            if (dx >= 0.0 && dy >= 0.0) {
1663                dSign = 1.0;
1664            }
1665
1666            dHypotenuse = dSign * (double) nBiSector;
1667
1668            //Find x, y for Arrow Head nBase startLinePoint POINT1
1669            AHBX = (double) endLinePoint.x + dHypotenuse * Math.cos(dAngle);
1670            AHBY = (double) endLinePoint.y - dHypotenuse * Math.sin(dAngle);
1671
1672            //Half of the arrow head's length will be 10 units
1673            dHypotenuse = dSign * (double) (nBase / 2.0);
1674
1675            //Find x, y of Arrow Head nBase Left side end POINT1
1676            AHBLX = AHBX - dHypotenuse * Math.sin(dAngle);
1677            AHBLY = AHBY - dHypotenuse * Math.cos(dAngle);
1678
1679            //Find x, y of Arrow Head nBase Right side end POINT1
1680            AHBRX = AHBX + dHypotenuse * Math.sin(dAngle);
1681            AHBRY = AHBY + dHypotenuse * Math.cos(dAngle);
1682
1683            //replacement, just trying to return the POINT1s
1684            tempLinePoint.x = (int) AHBLX;
1685            tempLinePoint.y = (int) AHBLY;
1686            pResultLinePoints[0] = new POINT2(tempLinePoint);
1687            pResultLinePoints[1] = new POINT2(endLinePoint);
1688            tempLinePoint.x = (int) AHBRX;
1689            tempLinePoint.y = (int) AHBRY;
1690            pResultLinePoints[2] = new POINT2(tempLinePoint);
1691            switch (styl) {
1692                case 0:
1693                    for (j = 0; j < 2; j++) {
1694                        pResultLinePoints[j].style = 0;
1695                    }
1696                    pResultLinePoints[2].style = 5;
1697                    break;
1698                case 9:
1699                    for (j = 0; j < 2; j++) {
1700                        pResultLinePoints[j].style = 9;
1701                    }
1702                    pResultLinePoints[2].style = 10;
1703                    break;
1704                case 18:
1705                    for (j = 0; j < 2; j++) {
1706                        pResultLinePoints[j].style = 18;
1707                    }
1708                    pResultLinePoints[2].style = 5;
1709                    break;
1710                default:
1711                    for (j = 0; j < 2; j++) {
1712                        pResultLinePoints[j].style = styl;
1713                    }
1714                    pResultLinePoints[2].style = 5;
1715                    break;
1716            }
1717        } catch (Exception exc) {
1718            ErrorLogger.LogException(_className, "GetArrowhead4Double",
1719                    new RendererException("Failed inside GetArrowhead4Double", exc));
1720        }
1721    }
1722
1723    /**
1724     * Returns the midpoint between two points.
1725     *
1726     * @param pt0 the first point
1727     * @param pt1 the second point
1728     * @param styl the style to assign the mid point
1729     *
1730     * @return the mid point
1731     */
1732    public static POINT2 MidPointDouble(POINT2 pt0,
1733            POINT2 pt1,
1734            int styl) {
1735        POINT2 ptResult = new POINT2(pt0);
1736        try {
1737            ptResult.x = (pt0.x + pt1.x) / 2;
1738            ptResult.y = (pt0.y + pt1.y) / 2;
1739            ptResult.style = styl;
1740        } catch (Exception exc) {
1741            ErrorLogger.LogException(_className, "MidPointDouble",
1742                    new RendererException("Failed inside MidPointDouble", exc));
1743        }
1744        return ptResult;
1745    }
1746
1747    /**
1748     * Rotates an the first vblCounter points in the array about its first point
1749     *
1750     * @param pLinePoints OUT - the points to rotate
1751     * @param vblCounter the number of points to rotate
1752     * @param lAngle the angle in degrees to rotate
1753     *
1754     * @return pLinePoints
1755     */
1756    protected static POINT2[] RotateGeometryDoubleOrigin(POINT2[] pLinePoints,
1757            int vblCounter,
1758            int lAngle) {
1759        try {
1760            //declarations
1761            int j = 0;
1762            double dRotate = 0,
1763                    dTheta = 0,
1764                    dGamma = 0,
1765                    x = 0,
1766                    y = 0;
1767            //end declarations
1768
1769            if (lAngle != 0) {
1770                POINT2 pdCenter = new POINT2();
1771                dRotate = (double) lAngle * Math.PI / 180d;
1772                //pdCenter = CalcCenterPointDouble(pLinePoints,vblCounter);
1773                pdCenter = new POINT2(pLinePoints[0]);
1774
1775                for (j = 0; j < vblCounter; j++) {
1776                    dGamma = Math.PI + Math.atan((pLinePoints[j].y - pdCenter.y)
1777                            / (pLinePoints[j].x - pdCenter.x));
1778
1779                    if (pLinePoints[j].x >= pdCenter.x) {
1780                        dGamma = dGamma + Math.PI;
1781                    }
1782
1783                    dTheta = dRotate + dGamma;
1784                    y = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.sin(dTheta);
1785                    x = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.cos(dTheta);
1786                    pLinePoints[j].y = pdCenter.y + y;
1787                    pLinePoints[j].x = pdCenter.x + x;
1788                }       //end for
1789
1790                return pLinePoints;
1791            }   //end if
1792        } catch (Exception exc) {
1793            ErrorLogger.LogException(_className, "RotateGeometryDoubleOrigin",
1794                    new RendererException("Failed inside RotateGeometryDoubleOrigin", exc));
1795        }
1796        return pLinePoints;
1797    }  // end function
1798
1799    /**
1800     * Returns a point a distance d pixels perpendicular to the pt0-pt1 line and
1801     * going toward pt2
1802     *
1803     * @param pt0 the first line point
1804     * @param pt1 the second line point
1805     * @param pt2 the relative line point
1806     * @param d the distance in pixels
1807     * @param styl the linestyle to assign the computed point
1808     *
1809     * @return the extended point
1810     */
1811    public static POINT2 ExtendTrueLinePerpDouble(POINT2 pt0,
1812            POINT2 pt1,
1813            POINT2 pt2,
1814            double d,
1815            int styl) {
1816        POINT2 ptResult = new POINT2(pt0);
1817        try {
1818            POINT2 ptYIntercept = new POINT2(pt0);
1819            ref<double[]> m = new ref();
1820            double b = 0, b1 = 0;       //b is the normal Y intercept (at 0)
1821            int nTemp = 0;                      //b1 is the y intercept at offsetX
1822
1823            //must obtain x minimum to get the y-intercept to the left of
1824            //the left-most point
1825            ref<double[]> offsetX = new ref(), offsetY = new ref();
1826            POINT2[] pts = new POINT2[3];
1827            pts[0] = new POINT2(pt0);
1828            pts[1] = new POINT2(pt1);
1829            pts[2] = new POINT2(pt2);
1830            GetPixelsMin(pts, 3, offsetX, offsetY);
1831
1832            if (offsetX.value[0] <= 0) //was < 0
1833            {
1834                offsetX.value[0] = offsetX.value[0] - 100;
1835            } else {
1836                offsetX.value[0] = 0;
1837            }
1838            //end section
1839
1840            nTemp = CalcTrueSlopeDouble(pt0, pt1, m);
1841            switch (nTemp) {
1842                case 0: //vertical line
1843                    if (pt0.y < pt1.y) {
1844                        ptResult.x = pt2.x - d;
1845                        ptResult.y = pt2.y;
1846                    } else {
1847                        ptResult.x = pt2.x + d;
1848                        ptResult.y = pt2.y;
1849                    }
1850                    break;
1851                default:        //non-vertical line
1852                    if (m.value[0] == 0) {
1853                        ptResult.x = pt2.x;
1854                        ptResult.y = pt2.y + d;
1855                    } else {
1856                        b = (double) pt2.y + (1 / m.value[0]) * (double) pt2.x;
1857                        //we need the y-intercept at the -offset
1858                        b1 = (-1 / m.value[0]) * offsetX.value[0] + b;
1859                        ptYIntercept.x = offsetX.value[0];
1860                        ptYIntercept.y = b1;
1861                        ptResult = ExtendLineDouble(ptYIntercept, pt2, d);
1862                    }
1863                    break;
1864            }
1865            ptResult.style = styl;
1866            pts = null;
1867        } catch (Exception exc) {
1868            ErrorLogger.LogException(_className, "ExtendTrueLinePerpDouble",
1869                    new RendererException("Failed inside ExtendTrueLinePerpDouble", exc));
1870        }
1871        return ptResult;
1872    }
1873
1874    /**
1875     * Calculates the intersection of 2 lines pelative to a point. if one of the
1876     * lines is vertical use a distance dWidth above or below the line. pass
1877     * bolVertical1 = 1, or bolVertical2 = 1 if either line segment is vertical,
1878     * else pass 0. return the unique intersection in X,Y pointers. p2 is the
1879     * point that connects the 2 line segments to which the intersecting lines
1880     * are related, i.e. the intersecting lines are a distance dWidth pixels
1881     * above or below p2. uses dWidth and lOrient for cases in which at least
1882     * one of the lines is vertical. for normal lines this function assumes the
1883     * caller has passed the m, b for the appropriate upper or lower lines to
1884     * get the desired intgercept. this function is used for calculating the
1885     * upper and lower channel lines for channel types. For lOrient: see
1886     * comments in Channels.ConnectTrueDouble2
1887     *
1888     * @param m1 slope of the first line
1889     * @param b1 intercept of the first line
1890     * @param m2 slope of the second line
1891     * @param b2 y intercept of the second line
1892     * @param p2 point that connects the 2 line segments to which the
1893     * intersecting lines are related
1894     * @param bolVerticalSlope1 1 if first segment is vertical, else 0
1895     * @param bolVerticalSlope2 1 if second line segment is vertical, else 0
1896     * @param dWidth the distance of the intersecting lines from p2 in pixels
1897     * @param lOrient the orientation of the intersecting lines relative to the
1898     * segments connecting p2
1899     * @param X OUT - object holds the x value of the intersection point
1900     * @param Y OUT - object holds the y value of the intersection point
1901     */
1902    protected static int CalcTrueIntersectDouble(double m1,
1903            double b1,
1904            double m2,
1905            double b2,
1906            POINT2 p2, //can use for vertical lines
1907            int bolVerticalSlope1,
1908            int bolVerticalSlope2,
1909            double dWidth, //use for vertical lines, use + for upper line, - for lower line
1910            int lOrient,
1911            ref<double[]> X, //intersection x value
1912            ref<double[]> Y) //intersection y value
1913    {
1914
1915        try {
1916            //case both lines are vertical
1917            double dWidth2 = Math.abs(dWidth);
1918            double b = 0;
1919            double dx = 0, dy = 0, m = 0;
1920            X.value = new double[1];
1921            Y.value = new double[1];
1922
1923            //cannot get out of having to do this
1924            //the problem is caused by inexact slopes which are created by
1925            //clsLineUtility.DisplayIntersectPixels. This occurs when setting
1926            //pt2 or pt3 with X or Y on the boundary +/-maxPixels
1927            //if you try to walk out until you get exactly the same slope
1928            //it can be thousands of pixels, so you have to accept an arbitrary
1929            //and, unfortuantely, inexact slope
1930            if (m1 != m2 && Math.abs(m1 - m2) <= Double.MIN_VALUE) {
1931                m1 = m2;
1932            }
1933            if (b1 != b2 && Math.abs(b1 - b2) <= Double.MIN_VALUE) {
1934                b1 = b2;
1935            }
1936
1937            //M. Deutch 10-24-11
1938            if (b1 == b2 && m1 + b1 == m2 + b2) {
1939                m1 = m2;
1940            }
1941
1942            if (bolVerticalSlope1 == 0 && bolVerticalSlope2 == 0) //both lines vertical
1943            {
1944                switch (lOrient) {
1945                    case 0:
1946                        X.value[0] = p2.x - dWidth2;
1947                        Y.value[0] = p2.y;
1948                        break;
1949                    case 3:
1950                        X.value[0] = p2.x + dWidth2;
1951                        Y.value[0] = p2.y;
1952                        break;
1953                    default:    //can never occur
1954                        X.value[0] = p2.x;
1955                        Y.value[0] = p2.y;
1956                        break;
1957                }
1958                return 1;
1959            }
1960            if (bolVerticalSlope1 == 0 && bolVerticalSlope2 != 0) //line1 vertical, line2 is not
1961            {   //there is a unique intersection
1962                switch (lOrient) {
1963                    case 0:     //Line1 above segment1
1964                    case 1:
1965                        X.value[0] = p2.x - dWidth2;
1966                        Y.value[0] = m2 * X.value[0] + b2;
1967                        break;
1968                    case 2:     //Line1 below segment1
1969                    case 3:
1970                        X.value[0] = p2.x + dWidth2;
1971                        Y.value[0] = m2 * X.value[0] + b2;
1972                        break;
1973                    default:    //can not occur
1974                        X.value[0] = p2.x;
1975                        Y.value[0] = p2.y;
1976                        break;
1977                }
1978                return 1;
1979            }
1980            if (bolVerticalSlope2 == 0 && bolVerticalSlope1 != 0) //line2 vertical, line1 is not
1981            {   //there is a unique intersection
1982                switch (lOrient) {
1983                    case 0:     //Line1 above segment2
1984                    case 2:
1985                        X.value[0] = p2.x - dWidth2;
1986                        Y.value[0] = m1 * (X.value[0]) + b1;
1987                        break;
1988                    case 1:     //Line1 below segment2
1989                    case 3:
1990                        X.value[0] = p2.x + dWidth2;
1991                        Y.value[0] = m1 * (X.value[0]) + b1;
1992                        break;
1993                    default:    //can not occur
1994                        X.value[0] = p2.x;
1995                        Y.value[0] = p2.y;
1996                        break;
1997                }
1998                return 1;
1999            }//end if
2000
2001            //must deal with this case separately because normal lines use m1-m2 as a denominator
2002            //but we've handled all the vertical cases above so can assume it's not vertical
2003            //if the b's are different then one is an upper line, the other is a lower, no intersection
2004            //m and b will be used to build the perpendicular line thru p2 which we will use to
2005            //build the intersection, so must assume slopes are not 0, handle separately
2006            if (m1 == m2 && m1 != 0) {
2007                if (b1 == b2) //then the intercept is the point joining the 2 segments
2008                {
2009                    //build the perpendicular line
2010                    m = -1 / m1;
2011                    b = p2.y - m * p2.x;
2012                    X.value[0] = (b2 - b) / (m - m2);   //intersect the lines (cannot blow up, m = m2 not possible)
2013                    Y.value[0] = (m1 * (X.value[0]) + b1);
2014                    return 1;
2015                } else //can not occur
2016                {
2017                    X.value[0] = p2.x;
2018                    Y.value[0] = p2.y;
2019                    return 1;
2020                }
2021            }
2022            //slope is zero
2023            if (m1 == m2 && m1 == 0) {
2024                switch (lOrient) {
2025                    case 0:     //Line1 above the line
2026                    case 1:     //should never happen
2027                        X.value[0] = p2.x;
2028                        Y.value[0] = p2.y - dWidth2;
2029                        break;
2030                    case 3:     //Line1 below the line
2031                    case 2:     //should never happen
2032                        X.value[0] = p2.x;
2033                        Y.value[0] = p2.y + dWidth2;
2034                        break;
2035                    default:    //can not occur
2036                        X.value[0] = p2.x;
2037                        Y.value[0] = p2.y;
2038                        break;
2039                }
2040                return 1;
2041            }
2042
2043            if (m1 == m2 && b1 == b2 && bolVerticalSlope1 != 0 && bolVerticalSlope2 != 0) {
2044                switch (lOrient) {
2045                    case 0:     //Line1 is above the line
2046                        if (m1 < 0) {
2047                            dy = m1 * dWidth / Math.sqrt(1 + m1 * m1);  //dy is negative
2048                            dx = dy / m1;       //dx is negative
2049                            X.value[0] = p2.x + dx;
2050                            Y.value[0] = p2.y + dy;
2051                        }
2052                        if (m1 > 0) //slope is positive
2053                        {
2054                            dy = -m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is negative
2055                            dx = -dy / m1;      //dx is positive
2056                            X.value[0] = p2.x + dx;
2057                            Y.value[0] = p2.y + dy;
2058                        }
2059                        break;
2060                    case 3:     //Line1 is below the line
2061                        if (m1 <= 0) {
2062                            dy = -m1 * dWidth / Math.sqrt(1 + m1 * m1); //dy is positive
2063                            dx = dy / m1;       //dx is positive
2064                            X.value[0] = p2.x + dx;
2065                            Y.value[0] = p2.y + dy;
2066                        } else {
2067                            dy = m1 * dWidth / Math.sqrt(1 + m1 * m1);  //dy is positive
2068                            dx = -dy / m1;      //dx is negative
2069                            X.value[0] = p2.x + dx;
2070                            Y.value[0] = p2.y + dy;
2071                        }
2072                        break;
2073                    default:
2074                        X.value[0] = p2.x;
2075                        Y.value[0] = p2.y;
2076                        break;
2077                }
2078                return 1;
2079            }//end if
2080
2081            //a normal line. no vertical or identical slopes
2082            //if m1=m2 function will not reach this point
2083            X.value[0] = (b2 - b1) / (m1 - m2); //intersect the lines
2084            Y.value[0] = (m1 * (X.value[0]) + b1);
2085            return 1;
2086        }//end try
2087        catch (Exception exc) {
2088            X.value[0] = p2.x;
2089            Y.value[0] = p2.y;
2090            ErrorLogger.LogException(_className, "CalcTrueIntersectDouble",
2091                    new RendererException("Failed inside ExtendTrueIntersectDouble", exc));
2092        }
2093        return 1;
2094    }
2095
2096    /**
2097     * Returns the distance in pixels from x1,y1 to x2,y2
2098     *
2099     * @param x1 first point x location in pixels
2100     * @param y1 first point y location in pixels
2101     * @param x2 second point x location in pixels
2102     * @param y2 second point y location in pixels
2103     *
2104     * @return the distance
2105     */
2106    protected static double CalcDistance2(long x1,
2107            long y1,
2108            long x2,
2109            long y2) {
2110        double dResult = 0;
2111        try {
2112            dResult = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
2113
2114            //sanity check
2115            //return x or y distance if return value is 0 or infinity
2116            double xdist = Math.abs(x1 - x2);
2117            double ydist = Math.abs(y1 - y2);
2118            double max = xdist;
2119            if (ydist > xdist) {
2120                max = ydist;
2121            }
2122            if (dResult == 0 || Double.isInfinite(dResult)) {
2123                if (max > 0) {
2124                    dResult = max;
2125                }
2126            }
2127        } catch (Exception exc) {
2128            ErrorLogger.LogException(_className, "CalcDistance2",
2129                    new RendererException("Failed inside CalcDistance2", exc));
2130        }
2131        return dResult;
2132    }
2133    /**
2134     * gets the middle line for Rev B air corridors AC, LLTR, MRR, UAV
2135     * Middle line is handled separately now because the line may have been segmented
2136     * @param pLinePoints
2137     * @return 
2138     */
2139    protected static POINT2[] GetSAAFRMiddleLine(POINT2[] pLinePoints) {
2140        POINT2[] pts = null;
2141        try {
2142            int j = 0, count = 0;
2143            for (j = 0; j < pLinePoints.length-1; j++) {
2144                if (pLinePoints[j].style > 0) {
2145                    count++;
2146                }
2147            }
2148            pts = new POINT2[count*2];
2149            count=0;
2150            double dMRR=0;
2151            POINT2 firstSegPt=null,lastSegPt=null,pt0=null,pt1=null;
2152            for (j = 0; j < pLinePoints.length; j++) {
2153                if(pLinePoints[j].style>=0 || j==pLinePoints.length-1)
2154                {
2155                    if(lastSegPt != null)
2156                    {
2157                        firstSegPt=new POINT2(lastSegPt);
2158                        lastSegPt=new POINT2(pLinePoints[j]);
2159                        dMRR=firstSegPt.style;
2160                        pt0 = ExtendLine2Double(lastSegPt, firstSegPt, -dMRR, 0);
2161                        pt1 = ExtendLine2Double(firstSegPt, lastSegPt, -dMRR, 5);                        
2162                        pts[count++]=pt0;
2163                        pts[count++]=pt1;
2164                    }
2165                    else
2166                    {
2167                        lastSegPt=new POINT2(pLinePoints[j]);
2168                    }
2169                }
2170            }            
2171        } catch (Exception exc) {
2172            ErrorLogger.LogException(_className, "GetSAAFRMiddleLine",
2173                    new RendererException("Failed inside GetSAAFRMiddleLine", exc));
2174        }
2175        return pts;
2176    }
2177    /**
2178     * Computes the points for a SAAFR segment
2179     *
2180     * @param pLinePoints OUT - the client points also used for the returned
2181     * points
2182     * @param lineType the line type
2183     * @param dMRR the symbol width
2184     */
2185    protected static void GetSAAFRSegment(POINT2[] pLinePoints,
2186            int lineType,
2187            double dMRR) {
2188        try {
2189            POINT2 pt0 = new POINT2();
2190            POINT2 pt1 = new POINT2();
2191            POINT2 pt2 = new POINT2();
2192            POINT2 pt3 = new POINT2();
2193            POINT2 pt4 = new POINT2();
2194            POINT2 pt5 = new POINT2();
2195            ref<double[]> m = new ref();
2196            int bolVertical = CalcTrueSlopeDouble(pLinePoints[0], pLinePoints[1], m);
2197            //shortened line
2198            //pt1=ExtendLine2Double(pLinePoints[0],pLinePoints[1],-dMRR/2,5);
2199            //pt0=ExtendLine2Double(pLinePoints[1],pLinePoints[0],-dMRR/2,0);
2200            pt1 = ExtendLine2Double(pLinePoints[0], pLinePoints[1], -dMRR, 5);
2201            pt0 = ExtendLine2Double(pLinePoints[1], pLinePoints[0], -dMRR, 0);
2202            if (bolVertical != 0 && m.value[0] < 1) {
2203                //upper line
2204                pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 2, dMRR);
2205                pt2.style = 0;
2206                pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 2, dMRR);
2207                pt3.style = 5;
2208                //lower line
2209                pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 3, dMRR);
2210                pt4.style = 0;
2211                pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 3, dMRR);
2212                pt5.style = 5;
2213            } //if( (bolVertical!=0 && m>1) || bolVertical==0)
2214            else {
2215                //left line
2216                pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 0, dMRR);
2217                pt2.style = 0;
2218                pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 0, dMRR);
2219                pt3.style = 5;
2220                //right line
2221                pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 1, dMRR);
2222                pt4.style = 0;
2223                pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 1, dMRR);
2224                pt5.style = 5;
2225            }
2226            //load the line points
2227            pLinePoints[0] = new POINT2(pt0);
2228            pLinePoints[1] = new POINT2(pt1);
2229            pLinePoints[2] = new POINT2(pt2);
2230            pLinePoints[3] = new POINT2(pt3);
2231            pLinePoints[4] = new POINT2(pt4);
2232            pLinePoints[5] = new POINT2(pt5);
2233            pLinePoints[5].style = 5;
2234            pLinePoints[0].style = 5;
2235        } catch (Exception exc) {
2236            ErrorLogger.LogException(_className, "GetSAAFRSegment",
2237                    new RendererException("Failed inside GetSAAFRSegment", exc));
2238        }
2239    }
2240    /**
2241     * Called by arraysupport for SAAFR and AC fill shapes
2242     * @param pLinePoints
2243     * @param dMRR
2244     */
2245    protected static void GetSAAFRFillSegment(POINT2[] pLinePoints,
2246            double dMRR) {
2247        try {
2248            POINT2 pt2 = new POINT2();
2249            POINT2 pt3 = new POINT2();
2250            POINT2 pt4 = new POINT2();
2251            POINT2 pt5 = new POINT2();
2252            ref<double[]> m = new ref();
2253            int bolVertical = CalcTrueSlopeDouble(pLinePoints[0], pLinePoints[1], m);
2254            if (bolVertical != 0 && m.value[0] < 1) {
2255                //upper line
2256                pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 2, dMRR);
2257                pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 2, dMRR);
2258                //lower line
2259                pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 3, dMRR);
2260                pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 3, dMRR);
2261            } //if( (bolVertical!=0 && m>1) || bolVertical==0)
2262            else {
2263                //left line
2264                pt2 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 0, dMRR);
2265                pt3 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 0, dMRR);
2266                //right line
2267                pt4 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[0], 1, dMRR);
2268                pt5 = ExtendDirectedLine(pLinePoints[0], pLinePoints[1], pLinePoints[1], 1, dMRR);
2269            }
2270            //load the line points
2271            pLinePoints[0] = new POINT2(pt2);
2272            pLinePoints[1] = new POINT2(pt3);
2273            pLinePoints[2] = new POINT2(pt5);
2274            pLinePoints[3] = new POINT2(pt4);
2275        } catch (Exception exc) {
2276            ErrorLogger.LogException(_className, "GetSAAFRFillSegment",
2277                    new RendererException("Failed inside GetSAAFRFillSegment", exc));
2278        }
2279        //return;
2280    }
2281    /**
2282     * Computes an arc.
2283     *
2284     * @param pResultLinePoints OUT - contains center and start point and holds
2285     * the result arc points
2286     * @param vblCounter the number of client points
2287     * @param dRadius the arc radius in pixels
2288     * @param linetype the linetype determines start andgle and end angle for
2289     * the arc
2290     *
2291     */
2292    protected static POINT2[] ArcArrayDouble(POINT2[] pResultLinePoints,
2293            int vblCounter,
2294            double dRadius,
2295            int linetype,
2296            IPointConversion converter) {
2297        try {
2298            //declarations
2299            double startangle = 0, //start of pArcLinePoints
2300                    endangle = 0, //end of the pArcLinePoints
2301                    increment = 0,
2302                    //m = 0,
2303                    length = 0, //length of a to e
2304                    M = 0;
2305
2306            int j, numarcpts = 0, bolVertical = 0;
2307            ref<double[]> m = new ref();
2308            //C is the center of the pArcLinePoints derived from a and e
2309            POINT2 C = new POINT2(pResultLinePoints[0]),
2310                    a = new POINT2(pResultLinePoints[1]),
2311                    e = new POINT2(pResultLinePoints[0]);
2312
2313            POINT2[] pArcLinePoints = null;
2314            //end declarations
2315
2316            bolVertical = CalcTrueSlopeDouble(a, e, m);
2317            if (bolVertical != 0) {
2318                M = Math.atan(m.value[0]);
2319            } else {
2320                if (a.y < e.y) {
2321                    M = -Math.PI / 2;
2322                } else {
2323                    M = Math.PI / 2;
2324                }
2325            }
2326            if(converter != null)
2327            {
2328                Point2D pt02d=new Point2D.Double(pResultLinePoints[0].x,pResultLinePoints[0].y);
2329                Point2D pt12d=new Point2D.Double(pResultLinePoints[1].x,pResultLinePoints[1].y);
2330                //boolean reverseM=false;
2331                pt02d=converter.PixelsToGeo(pt02d);
2332                pt12d=converter.PixelsToGeo(pt12d);
2333                //M=mdlGeodesic.GetAzimuth(pt02d,pt12d);
2334                M= mdlGeodesic.GetAzimuth(new POINT2(pt02d.getX(),pt02d.getY()),new POINT2(pt12d.getX(),pt12d.getY()  )  );
2335                M*=(Math.PI/180);
2336                if(M<0)
2337                    M+=Math.PI;
2338            }
2339            length = CalcDistanceDouble(a, e);
2340            if(converter != null)
2341            {
2342                Point2D pt02d=new Point2D.Double(pResultLinePoints[0].x,pResultLinePoints[0].y);
2343                Point2D pt12d=new Point2D.Double(pResultLinePoints[1].x,pResultLinePoints[1].y);
2344                pt02d=converter.PixelsToGeo(pt02d);
2345                pt12d=converter.PixelsToGeo(pt12d);
2346                //length=mdlGeodesic.geodesic_distance(pt02d,pt12d,null,null);
2347                length=mdlGeodesic.geodesic_distance(new POINT2(pt02d.getX(),pt02d.getY()),new POINT2(pt12d.getX(),pt12d.getY()),null,null);
2348            }
2349            switch (linetype) {
2350                case TacticalLines.CLUSTER:
2351                    startangle = M - 90 * Math.PI / 180.0;
2352                    endangle = startangle + 2 * 90 * Math.PI / 180.0;
2353                    break;
2354                case TacticalLines.TRIP:
2355                    startangle = M - 45 * Math.PI / 180.0;
2356                    endangle = startangle + 2 * 45 * Math.PI / 180.0;
2357                    break;
2358                case TacticalLines.ISOLATE:
2359                case TacticalLines.CORDONKNOCK:
2360                case TacticalLines.CORDONSEARCH:
2361                    startangle = M;
2362                    endangle = startangle + 330 * Math.PI / 180;
2363                    break;
2364                case TacticalLines.TURN:
2365                    startangle = M;
2366                    endangle = startangle + 90 * Math.PI / 180;
2367                    break;
2368                case TacticalLines.OCCUPY:
2369                case TacticalLines.RETAIN:
2370                case TacticalLines.SECURE:
2371                    startangle = M;
2372                    //if(CELineArrayGlobals.Change1==false)
2373                    endangle = startangle + 338 * Math.PI / 180;
2374                    //else
2375                    //  endangle=startangle+330*pi/180;
2376                    break;
2377                default:
2378                    startangle = 0;
2379                    endangle = 2 * Math.PI;
2380                    break;
2381            }
2382
2383            if (a.x < e.x) {
2384                switch (linetype) {
2385                    case TacticalLines.ISOLATE:
2386                    case TacticalLines.CORDONKNOCK:
2387                    case TacticalLines.CORDONSEARCH:
2388                        startangle = M - Math.PI;
2389                        endangle = startangle + 330 * Math.PI / 180;
2390                        break;
2391                    case TacticalLines.OCCUPY:
2392                    case TacticalLines.RETAIN:
2393                    case TacticalLines.SECURE:
2394                        startangle = M - Math.PI;
2395                        //if(CELineArrayGlobals.Change1==false)
2396                        endangle = startangle + 338 * Math.PI / 180;
2397                        //else
2398                        //      endangle=startangle+330*pi/180;
2399                        break;
2400                    case TacticalLines.TURN:
2401                        startangle = M - Math.PI;
2402                        endangle = startangle + 90 * Math.PI / 180;
2403                        break;
2404                    case TacticalLines.CLUSTER:
2405                        startangle = M - Math.PI + 90 * Math.PI / 180.0;
2406                        endangle = startangle - 2 * 90 * Math.PI / 180.0;
2407                        break;
2408                    case TacticalLines.TRIP:
2409                        startangle = M - Math.PI + 45 * Math.PI / 180.0;
2410                        endangle = startangle - 2 * 45 * Math.PI / 180.0;
2411                        break;
2412                    default:
2413                        break;
2414                }
2415            }
2416
2417            numarcpts = 26;
2418            pArcLinePoints = new POINT2[numarcpts];
2419            InitializePOINT2Array(pArcLinePoints);
2420            increment = (endangle - startangle) / (numarcpts - 1);
2421            if(dRadius != 0 && length != 0)
2422            {
2423                C.x = (int) ((double) e.x - (dRadius / length)
2424                        * ((double) a.x - (double) e.x));
2425                C.y = (int) ((double) e.y - (dRadius / length)
2426                        * ((double) a.y - (double) e.y));
2427            }
2428            else
2429            {
2430                C.x=e.x;
2431                C.y=e.y;
2432            }
2433            if (converter != null)
2434            {
2435                Point2D C2d=new Point2D.Double(pResultLinePoints[0].x,pResultLinePoints[0].y);
2436                C2d=converter.PixelsToGeo(C2d);    
2437                double az=0;
2438                Point2D ptGeo2d=null;
2439                POINT2 ptGeo=null;
2440                POINT2 ptPixels=null;
2441                for (j = 0; j < numarcpts; j++) {
2442                    az=startangle*180/Math.PI+j*increment*180/Math.PI;
2443                    //ptGeo=mdlGeodesic.geodesic_coordinate(C2d,length,az);
2444                    ptGeo=mdlGeodesic.geodesic_coordinate(new POINT2(C2d.getX(),C2d.getY()),length,az);
2445                    ptGeo2d=new Point2D.Double(ptGeo.x,ptGeo.y);
2446                    ptGeo2d=converter.GeoToPixels(ptGeo2d);
2447                    ptPixels=new POINT2(ptGeo2d.getX(),ptGeo2d.getY());
2448                    pArcLinePoints[j].x = ptPixels.x;
2449                    pArcLinePoints[j].y = ptPixels.y;                            
2450                }
2451            }
2452            else
2453            {
2454                for (j = 0; j < numarcpts; j++) {
2455                    //pArcLinePoints[j]=pResultLinePoints[0];   //initialize
2456                    pArcLinePoints[j].x = (int) (dRadius * Math.cos(startangle + j * increment));
2457                    pArcLinePoints[j].y = (int) (dRadius * Math.sin(startangle + j * increment));
2458                }
2459
2460                for (j = 0; j < numarcpts; j++) {
2461                    pArcLinePoints[j].x += C.x;
2462                    pArcLinePoints[j].y += C.y;
2463                }
2464            }
2465            for (j = 0; j < numarcpts; j++) {
2466                pResultLinePoints[j] = new POINT2(pArcLinePoints[j]);
2467            }
2468            pArcLinePoints = null;
2469        } catch (Exception exc) {
2470            ErrorLogger.LogException(_className, "ArcArrayDouble",
2471                    new RendererException("Failed inside ArcArrayDouble", exc));
2472        }
2473        return pResultLinePoints;
2474    }
2475    /**
2476     * Gets geodesic circle using the converter
2477     * @param Center in pixels
2478     * @param pt1 a point on the radius in pixels
2479     * @param numpts number of points to return
2480     * @param CirclePoints the result points
2481     * @param converter 
2482     */
2483    protected static void CalcCircleDouble2(POINT2 Center,
2484            POINT2 pt1,
2485            int numpts,
2486            POINT2[] CirclePoints,
2487            IPointConversion converter) {
2488        try {
2489            int j = 0;
2490            double increment = (Math.PI * 2) / (numpts - 1);
2491            Point2D ptCenter2d=new Point2D.Double(Center.x,Center.y);
2492            ptCenter2d=converter.PixelsToGeo(ptCenter2d);
2493            Point2D pt12d=new Point2D.Double(pt1.x,pt1.y);
2494            pt12d=converter.PixelsToGeo(pt12d);
2495            Center=new POINT2(ptCenter2d.getX(),ptCenter2d.getY());
2496            pt1=new POINT2(pt12d.getX(),pt12d.getY());
2497            double dist=mdlGeodesic.geodesic_distance(Center, pt1, null, null);
2498            
2499            //double dSegmentAngle = 2 * Math.PI / numpts;
2500            double az=0;
2501            double startangle=0,endAngle=Math.PI*2;
2502            POINT2 ptGeo=null,ptPixels=null;
2503            Point2D ptGeo2d=null;           
2504            for (j = 0; j < numpts - 1; j++) {
2505                az=startangle*180/Math.PI+j*increment*180/Math.PI;
2506                //ptGeo=mdlGeodesic.geodesic_coordinate(C2d,length,az);
2507                ptGeo=mdlGeodesic.geodesic_coordinate(Center,dist,az);
2508                ptGeo2d=new Point2D.Double(ptGeo.x,ptGeo.y);
2509                ptGeo2d=converter.GeoToPixels(ptGeo2d);
2510                ptPixels=new POINT2(ptGeo2d.getX(),ptGeo2d.getY());
2511                CirclePoints[j].x = ptPixels.x;
2512                CirclePoints[j].y = ptPixels.y;                            
2513            }
2514            CirclePoints[numpts - 1] = new POINT2(CirclePoints[0]);
2515
2516        } catch (Exception exc) {
2517            ErrorLogger.LogException(_className, "CalcCircleDouble2",
2518                    new RendererException("Failed inside CalcCircleDouble2", exc));
2519        }
2520        return;
2521    }
2522    /**
2523     * Computes the points for a circle. Assumes CirclePoints has been allocated
2524     * with size numpts.
2525     *
2526     * @param Center the cicle center
2527     * @param radius the circle radius in pixels
2528     * @param numpts the number of circle points
2529     * @param CirclePoints - OUT - array of circle points
2530     * @param styl the style to set the last circle point
2531     */
2532    protected static void CalcCircleDouble(POINT2 Center,
2533            double radius,
2534            int numpts,
2535            POINT2[] CirclePoints,
2536            int styl) {
2537        try {
2538            int j = 0;
2539            double dSegmentAngle = 2 * Math.PI / (numpts - 1);
2540            double x = 0, y = 0;
2541            for (j = 0; j < numpts - 1; j++) {
2542                x = Center.x + (radius * Math.cos((double) j * dSegmentAngle));
2543                y = Center.y + (radius * Math.sin((double) j * dSegmentAngle));
2544                CirclePoints[j] = new POINT2(x, y);
2545                CirclePoints[j].style = styl;
2546            }
2547            CirclePoints[numpts - 1] = new POINT2(CirclePoints[0]);
2548
2549            switch (styl) {
2550                case 0:
2551                    CirclePoints[numpts - 1].style = 0;
2552                    break;
2553                case 9:
2554                    CirclePoints[numpts - 1].style = 10;
2555                    break;
2556                case 11:
2557                    CirclePoints[numpts - 1].style = 12;
2558                    break;
2559                default:
2560                    CirclePoints[numpts - 1].style = 5;
2561                    break;
2562            }
2563        } catch (Exception exc) {
2564            ErrorLogger.LogException(_className, "CalcCircleDouble",
2565                    new RendererException("Failed inside CalcCircleDouble", exc));
2566        }
2567    }
2568
2569    protected static Shape2 CalcCircleShape(POINT2 Center,
2570            double radius,
2571            int numpts,
2572            POINT2[] CirclePoints,
2573            int styl) {
2574        Shape2 shape;
2575        if (styl == 9) {
2576            shape = new Shape2(Shape2.SHAPE_TYPE_FILL);
2577        } else {
2578            shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
2579        }
2580
2581        shape.set_Style(styl);
2582        try {
2583            int j = 0;
2584            CalcCircleDouble(Center, radius, numpts, CirclePoints, styl);
2585            shape.moveTo(CirclePoints[0]);
2586            for (j = 1; j < numpts; j++) {
2587                shape.lineTo(CirclePoints[j]);
2588            }
2589        } catch (Exception exc) {
2590            ErrorLogger.LogException(_className, "CalcCircleShape",
2591                    new RendererException("Failed inside CalcCircleShape", exc));
2592        }
2593        return shape;
2594    }
2595
2596    private static void GetSquallCurve(POINT2 StartPt,
2597            POINT2 EndPt,
2598            POINT2[] pSquallPts,
2599            int sign,
2600            double amplitude,
2601            int quantity) {
2602        try {
2603            double dist = CalcDistanceDouble(StartPt, EndPt);
2604            POINT2 ptTemp = new POINT2();
2605            int j = 0;
2606                //end declarations
2607
2608            //get points along the horizontal segment between StartPt and EndPt2;
2609            for (j = 0; j < quantity; j++) {
2610                ptTemp = ExtendLineDouble(EndPt, StartPt, -dist * (double) j / (double) quantity);
2611                pSquallPts[j].x = ptTemp.x;
2612                //calculate the sin value along the x axis
2613                pSquallPts[j].y = ptTemp.y + amplitude * sign * Math.sin((double) j * 180 / (double) quantity * Math.PI / 180);
2614            }
2615        } catch (Exception exc) {
2616            ErrorLogger.LogException(_className, "GetSquallShape",
2617                    new RendererException("Failed inside GeSquallShape", exc));
2618        }
2619    }
2620    //caller needs to instantiate sign.value
2621    /**
2622     * Gets the squall curves for a line segment Assumes pSquallPts has been
2623     * allocated the proper number of points.
2624     *
2625     * @param StartPt segment start point
2626     * @param EndPt segment end point
2627     * @param pSquallPts OUT - the squall points
2628     * @param sign OUT - an object with a member to hold the starting curve sign
2629     * for the segment.
2630     * @param amplitude the sin curve amplitutde
2631     * @param quantity the number of points for each sin curve
2632     * @param length the desired length of the curve along the segment for each
2633     * sin curve
2634     *
2635     * @return segment squall points count
2636     */
2637    protected static int GetSquallSegment(POINT2 StartPt,
2638            POINT2 EndPt,
2639            POINT2[] pSquallPts,
2640            ref<int[]> sign,
2641            double amplitude,
2642            int quantity,
2643            double length) {
2644        int counter = 0;
2645        try {
2646            POINT2 StartCurvePt, EndCurvePt;    //use these for the curve points
2647            POINT2[] pSquallPts2 = new POINT2[quantity];
2648            double dist = CalcDistanceDouble(StartPt, EndPt);
2649            int numCurves = (int) (dist / (double) length);
2650            int j = 0, k = 0;
2651            POINT2 EndPt2 = new POINT2();
2652            double angle = Math.atan((StartPt.y - EndPt.y) / (StartPt.x - EndPt.x));
2653            int lAngle = (int) ((180 / Math.PI) * angle);
2654            InitializePOINT2Array(pSquallPts2);
2655            //define EndPt2 to be the point dist from StartPt along the x axis
2656            if (StartPt.x < EndPt.x) {
2657                EndPt2.x = StartPt.x + dist;
2658            } else {
2659                EndPt2.x = StartPt.x - dist;
2660            }
2661
2662            EndPt2.y = StartPt.y;
2663
2664            EndCurvePt = StartPt;
2665            for (j = 0; j < numCurves; j++) {
2666                StartCurvePt = ExtendLineDouble(EndPt2, StartPt, -(double) (j * length));
2667                EndCurvePt = ExtendLineDouble(EndPt2, StartPt, -(double) ((j + 1) * length));
2668
2669                //get the curve points
2670                GetSquallCurve(StartCurvePt, EndCurvePt, pSquallPts2, sign.value[0], amplitude, quantity);
2671
2672                //fill the segment points with the curve points
2673                for (k = 0; k < quantity; k++) {
2674                    //pSquallPts[counter].x=pSquallPts2[k].x;
2675                    //pSquallPts[counter].y=pSquallPts2[k].y;
2676                    pSquallPts[counter] = new POINT2(pSquallPts2[k]);
2677                    counter++;
2678                }
2679                //reverse the sign
2680
2681                sign.value[0] = -sign.value[0];
2682            }
2683            if (numCurves == 0) {
2684                pSquallPts[counter] = new POINT2(StartPt);
2685                counter++;
2686                pSquallPts[counter] = new POINT2(EndPt);
2687                counter++;
2688            }
2689            //the points are along the x axis. Rotate them about the first point as the origin
2690            RotateGeometryDoubleOrigin(pSquallPts, counter, lAngle);
2691            pSquallPts2 = null;
2692        } catch (Exception exc) {
2693            ErrorLogger.LogException(_className, "GetSquallSegment",
2694                    new RendererException("Failed inside GetSquallSegment", exc));
2695        }
2696        return counter;
2697    }
2698
2699    //temporarily using 2000 pixels
2700    private static int PointInBounds(POINT2 pt) {
2701        try {
2702            //double maxPixels=CELineArrayGlobals.MaxPixels2;
2703            double maxPixels = 100000;//was 2000
2704            if (Math.abs(pt.x) <= maxPixels && Math.abs(pt.y) <= maxPixels) {
2705                return 1;
2706            } else {
2707                return 0;
2708            }
2709        } catch (Exception exc) {
2710            ErrorLogger.LogException(_className, "PointInBounds",
2711                    new RendererException("Failed inside PointInBounds", exc));
2712        }
2713        return 1;
2714    }
2715
2716    /**
2717     * @param pt
2718     * @param ul
2719     * @param lr
2720     * @return
2721     */
2722    private static int PointInBounds2(POINT2 pt, POINT2 ul, POINT2 lr) {
2723        try {
2724            double maxX = lr.x, minX = ul.x, maxY = lr.y, minY = ul.y;
2725            if (pt.x <= maxX && pt.x >= minX && pt.y <= maxY && pt.y >= minY) {
2726                return 1;
2727            } else {
2728                return 0;
2729            }
2730        } catch (Exception exc) {
2731            ErrorLogger.LogException(_className, "PointInBounds2",
2732                    new RendererException("Failed inside PointInBounds2", exc));
2733        }
2734        return 1;
2735    }
2736
2737    /**
2738     * Analyzes if line from pt0 to pt 1 intersects a side and returns the
2739     * intersection or null assumes pt0 to pt1 is not vertical. the caller will
2740     * replace pt0 with the intersection point if it is not null
2741     *
2742     * @param pt0
2743     * @param pt1
2744     * @param sidePt0 vertical or horizontal side first point
2745     * @param sidePt1
2746     * @return null if it does not intersect the side
2747     */
2748    private static POINT2 intersectSegment(POINT2 pt0, POINT2 pt1, POINT2 sidePt0, POINT2 sidePt1) {
2749        POINT2 pt = null;
2750        try {
2751            if (pt0.x == pt1.x) {
2752                return null;
2753            }
2754            double m = (pt1.y - pt0.y) / (pt1.x - pt0.x);
2755            double dx = 0, dy = 0, x = 0, y = 0;
2756            POINT2 upper = null, lower = null, left = null, right = null;
2757            Boolean bolVertical = false;
2758            //the side is either vertical or horizontal
2759            if (sidePt0.x == sidePt1.x) //vertical side
2760            {
2761                bolVertical = true;
2762                if (sidePt0.y < sidePt1.y) {
2763                    upper = sidePt0;
2764                    lower = sidePt1;
2765                } else {
2766                    upper = sidePt1;
2767                    lower = sidePt0;
2768                }
2769            } else //horizontal side
2770            {
2771                if (sidePt0.x < sidePt1.x) {
2772                    left = sidePt0;
2773                    right = sidePt1;
2774                } else {
2775                    left = sidePt1;
2776                    right = sidePt0;
2777                }
2778            }
2779            //travel in the direction from pt0 to pt1 to find the pt0 intersect
2780            if (bolVertical) {  //the side to intersect is vertical
2781                dx = upper.x - pt0.x;
2782                dy = m * dx;
2783                x = upper.x;
2784                y = pt0.y + dy;
2785                //the potential intersection point
2786                pt = new POINT2(x, y);
2787
2788                if (pt0.x <= pt.x && pt.x <= pt1.x) //left to right
2789                {
2790                    if (upper.y <= pt.y && pt.y <= lower.y) {
2791                        return pt;
2792                    }
2793                } else if (pt0.x >= pt.x && pt.x >= pt1.x) //right to left
2794                {
2795                    if (upper.y <= pt.y && pt.y <= lower.y) {
2796                        return pt;
2797                    }
2798                }
2799            } else //horizontal side
2800            {
2801                dy = left.y - pt0.y;
2802                dx = dy / m;
2803                x = pt0.x + dx;
2804                y = left.y;
2805                //the potential intersection point
2806                pt = new POINT2(x, y);
2807
2808                if (pt0.y <= pt.y && pt.y <= pt1.y) {
2809                    if (left.x <= pt.x && pt.x <= right.x) {
2810                        return pt;
2811                    }
2812                } else if (pt0.y >= pt.y && pt.y >= pt1.y) {
2813                    if (left.x <= pt.x && pt.x <= right.x) {
2814                        return pt;
2815                    }
2816                }
2817            }
2818        } catch (Exception exc) {
2819            ErrorLogger.LogException(_className, "intersectSegment",
2820                    new RendererException("Failed inside intersectSegment", exc));
2821        }
2822        return null;
2823    }
2824
2825    /**
2826     * side 1 ----- | | side 0 | | side 2 | | ------ side 3 bounds one segment
2827     * for autoshapes that need it: bydif, fordif, fix, mnfldfix if null is
2828     * returned the client should conect the original line points (i.e. no
2829     * jaggies)
2830     *
2831     * @param pt0
2832     * @param pt1
2833     * @param ul
2834     * @param lr
2835     * @return bounded segment or null
2836     */
2837    public static POINT2[] BoundOneSegment(POINT2 pt0, POINT2 pt1, POINT2 ul, POINT2 lr) {
2838        POINT2[] line = new POINT2[2];
2839        try {
2840            if (pt0.y < ul.y && pt1.y < ul.y) {
2841                return null;
2842            }
2843            if (pt0.y > lr.y && pt1.y > lr.y) {
2844                return null;
2845            }
2846            if (pt0.x < ul.x && pt1.x < ul.x) {
2847                return null;
2848            }
2849            if (pt0.x > lr.x && pt1.x > lr.x) {
2850                return null;
2851            }
2852
2853            Boolean bolVertical = false;
2854            InitializePOINT2Array(line);
2855            if (pt0.x == pt1.x) {
2856                bolVertical = true;
2857            }
2858
2859            if (bolVertical) {
2860                line[0] = new POINT2(pt0);
2861                if (line[0].y < ul.y) {
2862                    line[0].y = ul.y;
2863                }
2864                if (line[0].y > lr.y) {
2865                    line[0].y = lr.y;
2866                }
2867
2868                line[1] = new POINT2(pt1);
2869                if (line[1].y < ul.y) {
2870                    line[1].y = ul.y;
2871                }
2872                if (line[1].y > lr.y) {
2873                    line[1].y = lr.y;
2874                }
2875
2876                return line;
2877            }
2878
2879            double dx = 0, dy = 0, x = 0, y = 0;
2880            double m = (pt1.y - pt0.y) / (pt1.x - pt0.x);
2881            Boolean side0Intersect = false,
2882                    side1Intersect = false,
2883                    side2Intersect = false,
2884                    side3Intersect = false;
2885            //travel in the direction from pt0 to pt1 to find pt0 intersect
2886            POINT2 ur = new POINT2(lr.x, ul.y);
2887            POINT2 ll = new POINT2(ul.x, lr.y);
2888
2889            POINT2 pt0Intersect = null;
2890            if (PointInBounds2(pt0, ul, lr) == 1) {
2891                pt0Intersect = pt0;
2892            }
2893            if (pt0Intersect == null) {
2894                pt0Intersect = intersectSegment(pt0, pt1, ll, ul);  //interesect side 0
2895                side0Intersect = true;
2896            }
2897            if (pt0Intersect == null) {
2898                pt0Intersect = intersectSegment(pt0, pt1, ul, ur);  //interesect side 1
2899                side1Intersect = true;
2900            }
2901            if (pt0Intersect == null) {
2902                pt0Intersect = intersectSegment(pt0, pt1, ur, lr);  //interesect side 2
2903                side2Intersect = true;
2904            }
2905            if (pt0Intersect == null) {
2906                pt0Intersect = intersectSegment(pt0, pt1, ll, lr);  //interesect side 3
2907                side3Intersect = true;
2908            }
2909
2910            //travel in the direction from pt1 to pt0 to find pt1 intersect
2911            POINT2 pt1Intersect = null;
2912            if (PointInBounds2(pt1, ul, lr) == 1) {
2913                pt1Intersect = pt1;
2914            }
2915            if (pt1Intersect == null && side0Intersect == false) {
2916                pt1Intersect = intersectSegment(pt1, pt0, ll, ul);  //interesect side 0
2917            }
2918            if (pt1Intersect == null && side1Intersect == false) {
2919                pt1Intersect = intersectSegment(pt1, pt0, ul, ur);  //interesect side 1
2920            }
2921            if (pt1Intersect == null && side2Intersect == false) {
2922                pt1Intersect = intersectSegment(pt1, pt0, ur, lr);  //interesect side 2
2923            }
2924            if (pt1Intersect == null && side3Intersect == false) {
2925                pt1Intersect = intersectSegment(pt1, pt0, ll, lr);  //interesect side 3
2926            }
2927
2928            if (pt0Intersect != null && pt1Intersect != null) {
2929                line[0] = pt0Intersect;
2930                line[1] = pt1Intersect;
2931                //return line;
2932            } else {
2933                line = null;
2934            }
2935        } catch (Exception exc) {
2936            ErrorLogger.LogException(_className, "BoundOneSegment",
2937                    new RendererException("Failed inside BoundOneSegment", exc));
2938        }
2939        return line;
2940    }
2941
2942    private static int DisplayIntersectPixels(POINT2 pt0,
2943            POINT2 pt1,
2944            ref<double[]> pt2x,
2945            ref<double[]> pt2y,
2946            ref<double[]> pt3x,
2947            ref<double[]> pt3y) //POINT2 ul,
2948    //POINT2 lr)
2949    {
2950        int nResult = -1;
2951        try {
2952            //declarations
2953            double X = 0, Y = 0;
2954            ref<double[]> m = new ref();
2955            //double maxPixels=CELineArrayGlobals.MaxPixels2;
2956            double maxPixels = 2000;
2957            //double maxX=lr.x,minX=ul.x,maxY=lr.y,minY=ul.y;
2958
2959            int bol0Inside = 0, bol1Inside = 0;
2960            int bolVertical = CalcTrueSlopeDouble(pt0, pt1, m);
2961            double b = pt0.y - m.value[0] * pt0.x;      //the y intercept for the segment line
2962            POINT2 pt2, pt3;
2963            //end declarations
2964
2965            pt2x.value = new double[1];
2966            pt2y.value = new double[1];
2967            pt3x.value = new double[1];
2968            pt3y.value = new double[1];
2969            pt2 = new POINT2(pt0);
2970            pt3 = new POINT2(pt1);
2971
2972            //diagnostic
2973            if (pt0.x <= maxPixels && pt0.x >= -maxPixels
2974                    && pt0.y <= maxPixels && pt0.y >= -maxPixels) {
2975                bol0Inside = 1;
2976            }
2977            if (pt1.x <= maxPixels && pt1.x >= -maxPixels
2978                    && pt1.y <= maxPixels && pt1.y >= -maxPixels) {
2979                bol1Inside = 1;
2980            }
2981            //if both points are inside the area then use the whole segment
2982            if (bol0Inside == 1 && bol1Inside == 1) {
2983                return 0;
2984            }
2985            //if at leat one of the points is inside the area then use some of the segment
2986            if (bol0Inside == 1 || bol1Inside == 1) {
2987                nResult = 1;
2988            }
2989
2990            //segment is not vertical
2991            if (bolVertical != 0) {
2992                //analysis for side 0, get the intersection for either point if it exists
2993                //diagnostic
2994                X = -maxPixels;
2995                //X=minX;
2996
2997                Y = m.value[0] * X + b;
2998                if (pt0.x < -maxPixels && -maxPixels < pt1.x) //pt0 is outside the area
2999                {
3000                    if (-maxPixels <= Y && Y <= maxPixels) //intersection is on side 0
3001                    //if(minY<=Y && Y<=maxY)    //intersection is on side 0
3002                    {
3003                        pt2.x = X;
3004                        pt2.y = Y;
3005                        nResult = 1;    //use at least some of the pixels
3006                    }
3007                }
3008                if (pt1.x < -maxPixels && -maxPixels < pt0.x) //pt1 is outside the area
3009                //if(pt1.x<minX && minX<pt0.x)  //pt1 is outside the area
3010                {
3011                    if (-maxPixels <= Y && Y <= maxPixels) //intersection is on side 0
3012                    {
3013                        pt3.x = X;
3014                        pt3.y = Y;
3015                        nResult = 1;    //use at least some of the pixels
3016                    }
3017                }
3018
3019                //analysis for side 1, get the intersection for either point if it exists
3020                Y = -maxPixels;
3021                if (m.value[0] != 0) {
3022                    X = (Y - b) / m.value[0];
3023                    if (pt0.y < -maxPixels && -maxPixels < pt1.y) //pt0 is outside the area
3024                    {
3025                        if (-maxPixels <= X && X <= maxPixels) //intersection is on side 1
3026                        {
3027                            pt2.x = X;
3028                            pt2.y = Y;
3029                            nResult = 1;        //use at least some of the pixels
3030                        }
3031                    }
3032                    if (pt1.y <= -maxPixels && -maxPixels <= pt0.y) //pt1 is outside the area
3033                    {
3034                        if (-maxPixels < X && X < maxPixels) //intersection is on the boundary
3035                        {
3036                            pt3.x = X;
3037                            pt3.y = Y;
3038                            nResult = 1;        //use at least some of the pixels
3039                        }
3040                    }
3041                }
3042                //analysis for side 2, get the intersection for either point if it exists
3043                X = maxPixels;
3044                Y = m.value[0] * X + b;
3045                if (pt0.x < maxPixels && maxPixels < pt1.x) //pt1 is outside the area
3046                {
3047                    if (-maxPixels <= Y && Y <= maxPixels) //intersection is on the boundary
3048                    {
3049                        pt3.x = X;
3050                        pt3.y = Y;
3051                        nResult = 1;    //use at least some of the pixels
3052                    }
3053                }
3054                if (pt1.x < maxPixels && maxPixels < pt0.x) //pt0 is outside the area
3055                {
3056                    if (-maxPixels <= Y && Y <= maxPixels) //intersection is on the boundary
3057                    {
3058                        pt2.x = X;
3059                        pt2.y = Y;
3060                        nResult = 1;    //use at least some of the pixels
3061                    }
3062                }
3063
3064                //analysis for side 3, get the intersection for either point if it exists
3065                Y = maxPixels;
3066                if (m.value[0] != 0) {
3067                    X = (Y - b) / m.value[0];
3068                    if (pt0.y < maxPixels && maxPixels < pt1.y) //pt1 is outside the area
3069                    {
3070                        if (-maxPixels <= X && X <= maxPixels) //intersection is on the boundary
3071                        {
3072                            pt3.x = X;
3073                            pt3.y = Y;
3074                            nResult = 1;        //use at least some of the pixels
3075                        }
3076                    }
3077                    if (pt1.y < maxPixels && maxPixels < pt0.y) //pt0 is outside the area
3078                    {
3079                        if (-maxPixels <= X && X <= maxPixels) //intersection is on the boundary
3080                        {
3081                            pt2.x = X;
3082                            pt2.y = Y;
3083                            nResult = 1;        //use at least some of the pixels
3084                        }
3085                    }
3086                }
3087            }
3088
3089            //segment is vertical
3090            if (bolVertical == 0) {
3091                //analysis for side 1
3092                X = pt0.x;
3093                Y = -maxPixels;
3094                if (-maxPixels < pt0.x && pt0.x < maxPixels) {
3095                    if (pt0.y <= -maxPixels && -maxPixels <= pt1.y) //pt0 outside the area
3096                    {
3097                        pt2.x = X;
3098                        pt2.y = Y;
3099                        nResult = 1;    //use at least some of the pixels
3100                    }
3101                    if (pt1.y <= -maxPixels && -maxPixels <= pt0.y) //pt1 outside the area
3102                    {
3103                        pt3.x = X;
3104                        pt3.y = Y;
3105                        nResult = 1;    //use at least some of the pixels
3106                    }
3107                }
3108
3109                //analysis for side 3
3110                X = pt0.x;
3111                Y = maxPixels;
3112                if (-maxPixels < pt0.x && pt0.x < maxPixels) {
3113                    if (pt0.y <= maxPixels && maxPixels <= pt1.y) //pt1 outside the area
3114                    {
3115                        pt3.x = X;
3116                        pt3.y = Y;
3117                        nResult = 1;    //use at least some of the pixels
3118                    }
3119                    if (pt1.y <= maxPixels && maxPixels <= pt0.y) //pt0 outside the area
3120                    {
3121                        pt2.x = X;
3122                        pt2.y = Y;
3123                        nResult = 1;    //use at least some of the pixels
3124                    }
3125                }
3126            }
3127
3128            pt2x.value[0] = pt2.x;
3129            pt2y.value[0] = pt2.y;
3130            pt3x.value[0] = pt3.x;
3131            pt3y.value[0] = pt3.y;
3132        } catch (Exception exc) {
3133            ErrorLogger.LogException(_className, "DisplayIntersectPixels",
3134                    new RendererException("Failed inside DisplayIntersectPixels", exc));
3135        }
3136        return nResult;
3137    }
3138    /**
3139     * Computes Ditch spikes for the ATDITCH line types. This function uses
3140     * linestyles provided by the caller to skip segments.
3141     *
3142     * @param pLinePoints OUT - the client points also used for the return
3143     * points
3144     * @param nOldCounter the number of client points
3145     * @param bWayIs the parallel line to use (0) for inner or outer spikes
3146     * @param linetype the line type
3147     *
3148     * @return the symbol point count
3149     */
3150    protected static int GetDitchSpikeDouble(TGLight tg, POINT2[] pLinePoints,
3151            int nOldCounter,
3152            int bWayIs) {
3153        int nSpikeCounter = 0;
3154        try {
3155            //declarations
3156            int linetype = tg.get_LineType();
3157            int nNumberOfSegments = 0,
3158                    lCircleCounter = 0,
3159                    bolVertical = 0,
3160                    nTemp = 0,
3161                    i,
3162                    j;
3163            double dPrinter = 1.0;
3164            double dIntLocation1x = 0,
3165                    dIntLocation2x = 0,
3166                    dIntLocation1y = 0,
3167                    dIntLocation2y = 0,
3168                    r = 0,
3169                    s = 0,
3170                    use = 0,
3171                    length = 0,
3172                    k = 0,
3173                    bint = 0;
3174            ref<double[]> pdAnswer = new ref();//new double[6];
3175            ref<double[]> m = new ref();
3176
3177            POINT2 UpperLinePoint = new POINT2(pLinePoints[0]),
3178                    Lower1LinePoint = new POINT2(pLinePoints[0]),
3179                    Lower2LinePoint = new POINT2(pLinePoints[0]),
3180                    a = new POINT2(pLinePoints[0]),
3181                    b = new POINT2(pLinePoints[0]);
3182            POINT2[] pCirclePoints = new POINT2[pLinePoints.length];
3183            POINT2 averagePoint = new POINT2();
3184            POINT2 lastAveragePoint = new POINT2();
3185            POINT2[] pTempLinePoints = null;
3186            //end declarations
3187
3188            pTempLinePoints = new POINT2[nOldCounter];
3189            for (j = 0; j < nOldCounter; j++) {
3190                pTempLinePoints[j] = new POINT2(pLinePoints[j]);
3191            }
3192
3193            ArrayList<POINT2> basePoints = new ArrayList();
3194
3195            InitializePOINT2Array(pCirclePoints);
3196            nSpikeCounter = nOldCounter;
3197            double spikeLength = arraysupport.getScaledSize(12, tg.get_LineThickness());
3198            double spikeHeight = spikeLength * 1.25;
3199            double minLength = 2 * spikeLength;
3200            for (i = 0; i < nOldCounter - 1; i++) {
3201                if (linetype == TacticalLines.ATDITCHM && i == 0) {
3202                    double radius = arraysupport.getScaledSize(4, tg.get_LineThickness());
3203                    minLength = spikeLength * 2.5 + radius * 2;
3204                }
3205
3206                nTemp = CalcTrueLinesDouble((long) (spikeHeight * dPrinter), pLinePoints[i], pLinePoints[i + 1], pdAnswer);
3207                r = pdAnswer.value[3];
3208                s = pdAnswer.value[5];
3209                length = CalcDistanceDouble(pLinePoints[i], pLinePoints[i + 1]);
3210                bolVertical = CalcTrueSlopeDouble(pLinePoints[i], pLinePoints[i + 1], m);
3211                nNumberOfSegments = (int) ((length - 1) / (spikeLength * dPrinter));
3212
3213                if (length > minLength * dPrinter) {    //minLength was 24
3214                    if (bWayIs != 0) {
3215                        if (pLinePoints[i].x <= pLinePoints[i + 1].x) {
3216                            use = r;
3217                        }
3218                        if (pLinePoints[i].x >= pLinePoints[i + 1].x) {
3219                            use = s;
3220                        }
3221                    } //end if
3222                    else {
3223                        if (pLinePoints[i].x <= pLinePoints[i + 1].x) {
3224                            use = s;
3225                        }
3226                        if (pLinePoints[i].x >= pLinePoints[i + 1].x) {
3227                            use = r;
3228                        }
3229                    }   //end else
3230
3231                    for (j = 1; j <= nNumberOfSegments; j++) {
3232                        k = (double) j;
3233                        a = new POINT2(pLinePoints[i]);
3234                        b = new POINT2(pLinePoints[i + 1]);
3235
3236                        if (j > 1) {
3237                            dIntLocation1x = dIntLocation2x;
3238                        } else {
3239                            dIntLocation1x
3240                                    = (double) pLinePoints[i].x + ((k * spikeLength - spikeLength) * dPrinter / length)
3241                                    * (double) (pLinePoints[i + 1].x - pLinePoints[i].x);
3242                        }
3243
3244                        if (j > 1) //added M. Deutch 2-23-99
3245                        {
3246                            dIntLocation1y = dIntLocation2y;
3247                        } else {
3248                            dIntLocation1y
3249                                    = (double) pLinePoints[i].y + ((k * spikeLength - spikeLength / 2) * dPrinter / length)
3250                                    * (double) (pLinePoints[i + 1].y - pLinePoints[i].y);
3251                        }
3252
3253                        dIntLocation2x = (double) pLinePoints[i].x
3254                                + ((k * spikeLength + spikeLength / 2) * dPrinter / length)
3255                                * (double) (pLinePoints[i + 1].x
3256                                - pLinePoints[i].x);
3257
3258                        dIntLocation2y = (double) pLinePoints[i].y
3259                                + ((k * spikeLength + spikeLength / 2) * dPrinter / length)
3260                                * (double) (pLinePoints[i + 1].y
3261                                - pLinePoints[i].y);
3262
3263                        if (m.value[0] != 0 && bolVertical != 0) {
3264                            bint = (dIntLocation1y + dIntLocation2y) / 2.0
3265                                    + (1 / m.value[0]) * (dIntLocation1x + dIntLocation2x) / 2.0;
3266                            //independent of direction
3267                            UpperLinePoint = CalcTrueIntersectDouble2(m.value[0], use, -1 / m.value[0], bint, 1, 1, pLinePoints[0].x, pLinePoints[0].y);
3268                        }
3269
3270                        if (bolVertical == 0) //vertical segment
3271                        {
3272                            if (dIntLocation1y < dIntLocation2y) {
3273                                UpperLinePoint.y = (int) dIntLocation1y + (int) (length / nNumberOfSegments / 2);
3274                            } else {
3275                                UpperLinePoint.y = (int) dIntLocation1y - (int) (length / nNumberOfSegments / 2);
3276                            }
3277                            if (pLinePoints[i].y < pLinePoints[i + 1].y) {
3278                                UpperLinePoint.x = (int) dIntLocation1x + (int) (length / nNumberOfSegments);
3279                            } else {
3280                                UpperLinePoint.x = (int) dIntLocation1x - (int) (length / nNumberOfSegments);
3281                            }
3282                        }
3283                        if (m.value[0] == 0 && bolVertical != 0) {
3284                            if (dIntLocation1x < dIntLocation2x) {
3285                                UpperLinePoint.x = (int) dIntLocation1x + (int) (length / nNumberOfSegments / 2);
3286                            } else {
3287                                UpperLinePoint.x = (int) dIntLocation1x - (int) (length / nNumberOfSegments / 2);
3288                            }
3289                            if (pLinePoints[i + 1].x < pLinePoints[i].x) {
3290                                UpperLinePoint.y = (int) dIntLocation1y + (int) (length / nNumberOfSegments);
3291                            } else {
3292                                UpperLinePoint.y = (int) dIntLocation1y - (int) (length / nNumberOfSegments);
3293                            }
3294                        }
3295                        //end section
3296
3297                        Lower1LinePoint.x = dIntLocation1x;
3298                        Lower1LinePoint.y = dIntLocation1y;
3299                        Lower2LinePoint.x = dIntLocation2x;
3300                        Lower2LinePoint.y = dIntLocation2y;
3301
3302                        pLinePoints[nSpikeCounter] = new POINT2(Lower1LinePoint);
3303                        if (linetype == TacticalLines.ATDITCHC || linetype == TacticalLines.ATDITCHM) {
3304                            pLinePoints[nSpikeCounter].style = 9;
3305                        }
3306                        if (j % 2 == 1 && linetype == TacticalLines.ATDITCHM)//diagnostic 1-8-13
3307                        {
3308                            pLinePoints[nSpikeCounter].style = 5;
3309                        }
3310
3311                        nSpikeCounter++;
3312
3313                        pLinePoints[nSpikeCounter] = new POINT2(UpperLinePoint);
3314                        if (linetype == (long) TacticalLines.ATDITCHC || linetype == (long) TacticalLines.ATDITCHM) {
3315                            pLinePoints[nSpikeCounter].style = 9;
3316                        }
3317                        if (j % 2 == 1 && linetype == TacticalLines.ATDITCHM)//diagnostic 1-8-13
3318                        {
3319                            pLinePoints[nSpikeCounter].style = 5;
3320                        }
3321
3322                        nSpikeCounter++;
3323
3324                        pLinePoints[nSpikeCounter] = new POINT2(Lower2LinePoint);
3325                        if (linetype == (long) TacticalLines.ATDITCHC || linetype == (long) TacticalLines.ATDITCHM) {
3326                            pLinePoints[nSpikeCounter].style = 10;
3327                        }
3328                        if (j % 2 == 1 && linetype == TacticalLines.ATDITCHM)//diagnostic 1-8-13
3329                        {
3330                            pLinePoints[nSpikeCounter].style = 5;
3331                        }
3332
3333                        nSpikeCounter++;
3334
3335                        if (linetype == TacticalLines.ATDITCHM) {
3336                            if (j % 2 == 0) {
3337                                averagePoint = lineutility.MidPointDouble(Lower1LinePoint, Lower2LinePoint, 0);
3338                                averagePoint = lineutility.MidPointDouble(averagePoint, UpperLinePoint, 0);
3339                            } else if (j == 1) {
3340                                averagePoint = lineutility.ExtendLineDouble(Lower2LinePoint, Lower1LinePoint, 5);
3341                                averagePoint = lineutility.MidPointDouble(averagePoint, UpperLinePoint, 0);
3342                            }
3343                        }
3344                        //end section
3345                        if (j > 1 && j < nNumberOfSegments) {
3346                            basePoints.add(new POINT2(Lower1LinePoint));
3347                            //if(j==nNumberOfSegments-1)
3348                            //  basePoints.get(basePoints.size()-1).style=5;
3349                        } else if (j == 1) {
3350                            basePoints.add(new POINT2(pLinePoints[i]));
3351                        } else if (j == nNumberOfSegments) {
3352                            basePoints.add(new POINT2(pLinePoints[i + 1]));
3353                            basePoints.get(basePoints.size() - 1).style = 5;
3354                        }
3355                        if (linetype == TacticalLines.ATDITCHM && j > 1) {
3356                            if (j % 2 == 0) {
3357                                pCirclePoints[lCircleCounter] = lineutility.MidPointDouble(averagePoint, lastAveragePoint, 20);
3358                                lCircleCounter++;
3359                            }
3360                            //end section
3361                        }
3362                        if (j < nNumberOfSegments && linetype == TacticalLines.ATDITCHM) {
3363                            if (j == 1 || j % 2 == 0) {
3364                                //LastUpperLinePoint = new POINT2(UpperLinePoint);
3365                                lastAveragePoint = new POINT2(averagePoint);
3366                            }
3367                            //end section
3368                        }
3369                    }//end for j<numberOfsegments
3370                } //end if length big enough
3371                else {
3372                    //diagnostic
3373                    pLinePoints[nSpikeCounter].x = pLinePoints[i].x;
3374                    pLinePoints[nSpikeCounter].y = pLinePoints[i].y;
3375                    pLinePoints[nSpikeCounter].style = 0;
3376                    nSpikeCounter++;
3377                    pLinePoints[nSpikeCounter].x = pLinePoints[i + 1].x;
3378                    pLinePoints[nSpikeCounter].y = pLinePoints[i + 1].y;
3379                    pLinePoints[nSpikeCounter].style = 5;
3380                    nSpikeCounter++;
3381                }
3382            }
3383
3384            for (j = 0; j < nOldCounter; j++) //reverse the first nOldCounter points for
3385            {
3386                pLinePoints[j] = new POINT2(pTempLinePoints[nOldCounter - j - 1]); //purpose of drawing
3387                pLinePoints[j].style = 5;
3388            }
3389
3390            if (pLinePoints[nSpikeCounter - 1].style == 0) {
3391                pLinePoints[nSpikeCounter - 1].style = 5;
3392            }
3393            int t=basePoints.size();
3394            //for (j = nSpikeCounter; j < nSpikeCounter + basePoints.size(); j++) 
3395            for (j = nSpikeCounter; j < nSpikeCounter + t; j++) 
3396            {
3397                pLinePoints[j] = new POINT2(basePoints.get(j - nSpikeCounter));
3398                //if(linetype == TacticalLines.ATDITCHM && pLinePoints[j].style != 5)
3399                if (pLinePoints[j].style != 5) {
3400                    pLinePoints[j].style = 0;
3401                }
3402            }
3403            nSpikeCounter += basePoints.size();
3404
3405            if (linetype == (int) TacticalLines.ATDITCHM) {
3406                pLinePoints[nSpikeCounter - 1].style = 5;//was 10
3407                for (j = nSpikeCounter; j < nSpikeCounter + lCircleCounter; j++) {
3408                    pLinePoints[j] = new POINT2(pCirclePoints[j - nSpikeCounter]);
3409                    pLinePoints[j].style = 20;
3410                }
3411                nSpikeCounter += lCircleCounter;
3412            }
3413
3414        } catch (Exception exc) {
3415            ErrorLogger.LogException(_className, "GetDitchSpikeDouble",
3416                    new RendererException("Failed inside GetDitchSpikeDouble", exc));
3417        }
3418        return nSpikeCounter;
3419    }
3420
3421    /**
3422     * Moves pixels if points are identical, used for the channel types
3423     *
3424     * @param pLinePoints OUT - client points also for returned points
3425     */
3426    protected static void MoveChannelPixels(POINT2[] pLinePoints) {
3427        try {
3428            if (pLinePoints == null || pLinePoints.length <= 0) {
3429                return;
3430            }
3431
3432            double[] pixels = new double[pLinePoints.length * 2];
3433            boolean bolNoRepeats;
3434            int j, k = 0;
3435            double x1;
3436            double y1;
3437            double x2;
3438            double y2;
3439            int count = pLinePoints.length;
3440            //stuff pixels
3441            for (j = 0; j < count; j++) {
3442                pixels[k++] = pLinePoints[j].x;
3443                pixels[k++] = pLinePoints[j].y;
3444            }
3445
3446            bolNoRepeats = false;
3447            do {
3448                bolNoRepeats = true;
3449                for (j = 0; j < count - 1; j++) {
3450                    x1 = pixels[2 * j];
3451                    y1 = pixels[2 * j + 1];
3452                    x2 = pixels[2 * j + 2];
3453                    y2 = pixels[2 * j + 3];
3454                    if (x1 == x2 && y1 == y2) //it's the same point
3455                    {
3456                        bolNoRepeats = false;
3457                        pixels[2 * j + 2] = (long) x2 + 1; //move the point
3458                        break;
3459                    }
3460                }
3461            } while (bolNoRepeats == false);
3462            //stuff pLinePoints
3463            k = 0;
3464            for (j = 0; j < count; j++) {
3465                pLinePoints[j].x = pixels[k++];
3466                pLinePoints[j].y = pixels[k++];
3467            }
3468        } catch (Exception exc) {
3469            ErrorLogger.LogException(_className, "MoveChannelPixels",
3470                    new RendererException("Failed inside MoveChannelPixels", exc));
3471        }
3472    }
3473
3474    /**
3475     * Single Concertina cannot have horizontal first segment
3476     *
3477     * @param linetype
3478     * @param pLinePoints
3479     */
3480    protected static void moveSingleCPixels(int linetype, POINT2[] pLinePoints) {
3481        try {
3482            switch (linetype) {
3483                case TacticalLines.SINGLEC:
3484                    break;
3485                default:
3486                    return;
3487            }
3488            if (pLinePoints.length > 1) {
3489                if (pLinePoints[1].y == pLinePoints[0].y) {
3490                    pLinePoints[1].y++;
3491                }
3492            }
3493        } catch (Exception exc) {
3494            ErrorLogger.LogException(_className, "MoveSingleCPixels",
3495                    new RendererException("Failed inside MoveSingleCPixels", exc));
3496        }
3497    }
3498
3499    /**
3500     * Rotates an the first vblCounter points in the array about its first point
3501     *
3502     * @param pLinePoints OUT - the points to rotate
3503     * @param vblCounter the number of points to rotate
3504     * @param lAngle the angle in degrees to rotate
3505     */
3506    protected static void RotateGeometryDouble(POINT2[] pLinePoints,
3507            int vblCounter,
3508            double lAngle) {
3509        try {
3510            int j = 0;
3511            double dRotate = 0,
3512                    dTheta = 0,
3513                    dGamma = 0,
3514                    x = 0,
3515                    y = 0;
3516
3517            if (lAngle != 0) //if the angle is 0 no rotation occurs
3518            {
3519                POINT2 pdCenter;
3520                dRotate = lAngle * Math.PI / 180d;
3521                pdCenter = CalcCenterPointDouble(pLinePoints, vblCounter);
3522
3523                for (j = 0; j < vblCounter; j++) {
3524                    //added if/else to get rid of divide by zero error 5/12/04 M. Deutch
3525                    if (pLinePoints[j].x == pdCenter.x) {
3526                        if ((pLinePoints[j].y > pdCenter.y)) {
3527                            dGamma = Math.PI + Math.PI / 2;
3528                        } else {
3529                            dGamma = Math.PI / 2;
3530                        }
3531                    } else {
3532                        dGamma = Math.PI + Math.atan((pLinePoints[j].y - pdCenter.y)
3533                                / (pLinePoints[j].x - pdCenter.x));
3534                    }
3535
3536                    if ((double) pLinePoints[j].x >= pdCenter.x) {
3537                        dGamma = dGamma + Math.PI;
3538                    }
3539
3540                    dTheta = dRotate + dGamma;
3541                    y = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.sin(dTheta);
3542                    x = CalcDistanceDouble(pLinePoints[j], pdCenter) * Math.cos(dTheta);
3543                    pLinePoints[j].y = pdCenter.y + y;
3544                    pLinePoints[j].x = pdCenter.x + x;
3545                }       //end for
3546
3547                return;
3548            }   //end if
3549        } catch (Exception exc) {
3550            ErrorLogger.LogException(_className, "RotateGeometryDouble",
3551                    new RendererException("Failed inside RotateGeometryDouble", exc));
3552        }
3553    }  // end
3554
3555    /**
3556     * Returns the point perpendicular to the line (pt0 to pt1) at the midpoint
3557     * the same distance from (and on the same side of) the the line as
3558     * ptRelative.
3559     *
3560     * @param pt0 the first point
3561     * @param pt1 the second point
3562     * @param ptRelative the point to use for computing the return point
3563     *
3564     * @return the point perpendicular to the line at the midpoint
3565     */
3566    protected static POINT2 PointRelativeToLine(POINT2 pt0,
3567            POINT2 pt1,
3568            POINT2 ptRelative) {
3569        POINT2 ptResult = new POINT2(pt0);
3570        try {
3571            int bolVertical = 0;
3572            ref<double[]> m = new ref();
3573            POINT2 midPt = MidPointDouble(pt0, pt1, 0);
3574            double b1 = 0, b2 = 0;
3575            //end declarations
3576
3577            bolVertical = CalcTrueSlopeDouble(pt0, pt1, m);
3578            if (bolVertical == 0) //line is vertical
3579            {
3580                ptResult.x = ptRelative.x;
3581                ptResult.y = midPt.y;
3582            }
3583            if (bolVertical != 0 && m.value[0] == 0) {
3584                ptResult.x = midPt.x;
3585                ptResult.y = ptRelative.y;
3586            }
3587            if (bolVertical != 0 && m.value[0] != 0) {
3588                b1 = midPt.y + (1 / m.value[0]) * midPt.x;      //the line perp to midPt
3589                b2 = ptRelative.y - m.value[0] * ptRelative.x;  //the line  ptRelative with the slope of pt1-pt2
3590                ptResult = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0);
3591            }
3592        } catch (Exception exc) {
3593            ErrorLogger.LogException(_className, "PointRelativeToLine",
3594                    new RendererException("Failed inside PointRelativeToLine", exc));
3595        }
3596        return ptResult;
3597    }
3598
3599    /**
3600     * shift the control point to match the shift that occurs in
3601     * Channels.GetAXADDouble for CATKBYFIRE. This is because the rotary feature
3602     * arrow tip must align with the anchor point
3603     *
3604     * @param linetype
3605     * @param pLinePoints the anchor points including the control point
3606     * @param dist the minimum required distance from the front of the rotary
3607     * arrow
3608     */
3609    public static void adjustCATKBYFIREControlPoint(int linetype,
3610            ArrayList<POINT2> pLinePoints,
3611            double dist) {
3612        try {
3613            if (linetype != TacticalLines.CATKBYFIRE) {
3614                return;
3615            }
3616
3617            double dist2 = lineutility.CalcDistanceDouble(pLinePoints.get(0), pLinePoints.get(1));
3618            if (dist2 <= dist) {
3619                return;
3620            }
3621
3622            POINT2 pt = null;
3623            int count = pLinePoints.size();
3624            POINT2 pt0 = new POINT2(pLinePoints.get(0));
3625            POINT2 pt1 = new POINT2(pLinePoints.get(1));
3626            POINT2 controlPt = new POINT2(pLinePoints.get(count - 1));
3627            POINT2 pt4 = PointRelativeToLine(pt0, pt1, pt1, controlPt);
3628            pt = lineutility.ExtendLineDouble(pt4, controlPt, dist);
3629            pLinePoints.set(count - 1, pt);
3630        } catch (Exception exc) {
3631            ErrorLogger.LogException(_className, "adjustCATKBYFIREControlPoint",
3632                    new RendererException("Failed inside adjustCATKBYFIREControlPoint", exc));
3633        }
3634    }
3635
3636    /**
3637     * Returns the point perpendicular to the line (pt0 to pt1) at atPoint the
3638     * same distance from (and on the same side of) the the line as ptRelative.
3639     *
3640     * @param pt0 the first point
3641     * @param pt1 the second point
3642     * @param atPoint the point on the line at which to compute the extended
3643     * point
3644     * @param ptRelative the point to use for computing the return point
3645     *
3646     * @return the point perpendicular to the line at ptRelative
3647     */
3648    public static POINT2 PointRelativeToLine(POINT2 pt0,
3649            POINT2 pt1,
3650            POINT2 atPoint,
3651            POINT2 ptRelative) {
3652        POINT2 ptResult = new POINT2(pt0);
3653        try {
3654            int bolVertical = 0;
3655            ref<double[]> m = new ref();
3656            double b1 = 0, b2 = 0;
3657
3658            bolVertical = CalcTrueSlopeDouble(pt0, pt1, m);
3659            if (bolVertical == 0) //line is vertical
3660            {
3661                ptResult.x = ptRelative.x;
3662                ptResult.y = atPoint.y;
3663            }
3664            if (bolVertical != 0 && m.value[0] == 0) {
3665                ptResult.x = atPoint.x;
3666                ptResult.y = ptRelative.y;
3667            }
3668            if (bolVertical != 0 && m.value[0] != 0) {
3669                b1 = atPoint.y + (1 / m.value[0]) * atPoint.x;  //the line perp to midPt
3670                b2 = ptRelative.y - m.value[0] * ptRelative.x;  //the line  ptRelative with the slope of pt1-pt2
3671                ptResult = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0);
3672            }
3673        } catch (Exception exc) {
3674            ErrorLogger.LogException(_className, "PointRelativeToLine",
3675                    new RendererException("Failed inside PointRelativeToLine", exc));
3676        }
3677        return ptResult;
3678    }
3679
3680    /**
3681     * Returns in pt2 and pt3 the line segment parallel to segment pt0-pt1 which
3682     * would contain ptRelative. pt2 corresponds to pt0 and pt3 corresponds to
3683     * pt1.
3684     *
3685     * @param pt0 first line point
3686     * @param pt1 second line point
3687     * @param ptRelative relative line point
3688     * @param pt2 OUT - first computed relative line point
3689     * @param pt3 OUT - second computed relative line point
3690     */
3691    public static void LineRelativeToLine(POINT2 pt0,
3692            POINT2 pt1,
3693            POINT2 ptRelative,
3694            POINT2 pt2,
3695            POINT2 pt3) {
3696        try {
3697            int bolVertical = 0;
3698            ref<double[]> m = new ref();
3699            double b1 = 0, b2 = 0;
3700            POINT2 pt2Temp = null;
3701            POINT2 pt3Temp = null;
3702
3703            bolVertical = CalcTrueSlopeDouble(pt0, pt1, m);
3704            if (bolVertical == 0) //line is vertical
3705            {
3706                pt2.x = ptRelative.x;
3707                pt2.y = pt0.y;
3708                pt3.x = ptRelative.x;
3709                pt3.y = pt1.y;
3710            }
3711            if (bolVertical != 0 && m.value[0] == 0) //line is horizontal
3712            {
3713                pt2.x = pt0.x;
3714                pt2.y = ptRelative.y;
3715                pt3.x = pt1.x;
3716                pt3.y = ptRelative.y;
3717            }
3718            if (bolVertical != 0 && m.value[0] != 0) {
3719                b1 = pt0.y + (1 / m.value[0]) * pt0.x;  //the line perp to pt0
3720                b2 = ptRelative.y - m.value[0] * ptRelative.x;  //the line the ptRelative with the slope of pt0-pt1
3721                pt2Temp = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0);
3722
3723                b1 = pt1.y + (1 / m.value[0]) * pt1.x;  //the line perp to pt1
3724                //b2=ptRelative.y-m*ptRelative.x;       //the line the ptRelative with the slope of pt0-pt1
3725                pt3Temp = CalcTrueIntersectDouble2(-1 / m.value[0], b1, m.value[0], b2, 1, 1, 0, 0);
3726
3727                pt2.x = pt2Temp.x;
3728                pt2.y = pt2Temp.y;
3729                pt3.x = pt3Temp.x;
3730                pt3.y = pt3Temp.y;
3731            }
3732        } catch (Exception exc) {
3733            ErrorLogger.LogException(_className, "LineRelativeToLine",
3734                    new RendererException("Failed inside LineRelativeToLine", exc));
3735        }
3736    }
3737
3738    private static void CalcMBR(POINT2[] pLinePoints,
3739            int numpts,
3740            ref<double[]> ulx,
3741            ref<double[]> uly,
3742            ref<double[]> lrx,
3743            ref<double[]> lry) {
3744        try {
3745            int j = 0;
3746            //initialize the MBR
3747            ulx.value = new double[1];
3748            uly.value = new double[1];
3749            lrx.value = new double[1];
3750            lry.value = new double[1];
3751            ulx.value[0] = Double.MAX_VALUE;//was 99999
3752            uly.value[0] = Double.MAX_VALUE;//was 99999
3753            lrx.value[0] = -Double.MAX_VALUE;//was -99999
3754            lry.value[0] = -Double.MAX_VALUE;//was -99999
3755            for (j = 0; j < numpts; j++) {
3756                if (pLinePoints[j].x > lrx.value[0]) {
3757                    lrx.value[0] = pLinePoints[j].x;
3758                }
3759                if (pLinePoints[j].y > lry.value[0]) {
3760                    lry.value[0] = pLinePoints[j].y;
3761                }
3762                if (pLinePoints[j].x < ulx.value[0]) {
3763                    ulx.value[0] = pLinePoints[j].x;
3764                }
3765                if (pLinePoints[j].y < uly.value[0]) {
3766                    uly.value[0] = pLinePoints[j].y;
3767                }
3768            }
3769        } catch (Exception exc) {
3770            ErrorLogger.LogException(_className, "CalcMBR",
3771                    new RendererException("Failed inside CalcMBR", exc));
3772        }
3773        return;
3774    }
3775
3776    public static void CalcMBRPoints(POINT2[] pLinePoints,
3777            int numpts,
3778            POINT2 ul,
3779            POINT2 lr) {
3780        try {
3781            int j = 0;
3782            ul.x = Double.MAX_VALUE;
3783            ul.y = Double.MAX_VALUE;
3784            lr.x = -Double.MAX_VALUE;
3785            lr.y = -Double.MAX_VALUE;
3786            for (j = 0; j < numpts; j++) {
3787                if (pLinePoints[j].x > lr.x) {
3788                    lr.x = pLinePoints[j].x;
3789                }
3790                if (pLinePoints[j].y > lr.y) {
3791                    lr.y = pLinePoints[j].y;
3792                }
3793                if (pLinePoints[j].x < ul.x) {
3794                    ul.x = pLinePoints[j].x;
3795                }
3796                if (pLinePoints[j].y < ul.y) {
3797                    ul.y = pLinePoints[j].y;
3798                }
3799            }
3800        } catch (Exception exc) {
3801            ErrorLogger.LogException(_className, "CalcMBRPoints",
3802                    new RendererException("Failed inside CalcMBRPoints", exc));
3803        }
3804    }
3805
3806    /**
3807     * Computes the distance in pixels from upper left to lower right of the
3808     * minimum bounding rectangle for the first numpts of pLinePoints
3809     *
3810     * @param pLinePoints the inpupt point array
3811     * @param numpts the number of points to use
3812     *
3813     * @return the distance in pixels
3814     */
3815    protected static double MBRDistance(POINT2[] pLinePoints,
3816            int numpts) {
3817        double result = 0;
3818        try {
3819            ref<double[]> ulx = new ref(), uly = new ref(), lrx = new ref(), lry = new ref();
3820            CalcMBR(pLinePoints, numpts, ulx, uly, lrx, lry);
3821            result = Math.sqrt((lrx.value[0] - ulx.value[0]) * (lrx.value[0] - ulx.value[0]) + (lry.value[0] - uly.value[0]) * (lry.value[0] - uly.value[0]));
3822            //sanity check
3823
3824            //return x or y distance if returnValue is 0 or infinity
3825            double xdist = Math.abs(lrx.value[0] - ulx.value[0]);
3826            double ydist = Math.abs(lry.value[0] - uly.value[0]);
3827            double max = xdist;
3828            if (ydist > xdist) {
3829                max = ydist;
3830            }
3831
3832            if (result == 0 || Double.isInfinite(result)) {
3833                if (max > 0) {
3834                    result = max;
3835                }
3836            }
3837
3838        } catch (Exception exc) {
3839            ErrorLogger.LogException(_className, "MBRDistance",
3840                    new RendererException("Failed inside MBRDistance", exc));
3841        }
3842        return result;
3843    }
3844
3845    /**
3846     * Swaps two points.
3847     *
3848     * @param pt1 OUT - first point
3849     * @param pt2 OUT - second point
3850     *
3851     */
3852    protected static void Reverse2Points(POINT2 pt1, POINT2 pt2) {
3853        try {
3854            POINT2 tempPt = new POINT2();
3855            //store pt1
3856            tempPt.x = pt1.x;
3857            tempPt.y = pt1.y;
3858            pt1.x = pt2.x;
3859            pt1.y = pt2.y;
3860            pt2.x = tempPt.x;
3861            pt2.y = tempPt.y;
3862        } catch (Exception exc) {
3863            ErrorLogger.LogException(_className, "Reverse2Points",
3864                    new RendererException("Failed inside Reverse2Points", exc));
3865        }
3866    }
3867    /**
3868     * Creates a GeneralPath from a Path2D
3869     *
3870     * @param shape
3871     * @return
3872     */
3873    public static Shape createStrokedShape(Shape shape) {
3874        GeneralPath newshape = new GeneralPath(); // Start with an empty shape
3875        try {
3876            // Iterate through the specified shape, perturb its coordinates, and
3877            // use them to build up the new shape.
3878            double[] coords = new double[6];
3879            for (PathIterator i = shape.getPathIterator(null); !i.isDone(); i.next()) {
3880                int type = i.currentSegment(coords);
3881                switch (type) {
3882                    case PathIterator.SEG_MOVETO:
3883                        //perturb(coords, 2);
3884                        newshape.moveTo(coords[0], coords[1]);
3885                        break;
3886                    case PathIterator.SEG_LINETO:
3887                        //perturb(coords, 2);
3888                        newshape.lineTo(coords[0], coords[1]);
3889                        break;
3890                    case PathIterator.SEG_QUADTO:
3891                        //perturb(coords, 4);
3892                        newshape.quadTo(coords[0], coords[1], coords[2], coords[3]);
3893                        break;
3894                    case PathIterator.SEG_CUBICTO:
3895                        //perturb(coords, 6);
3896                        newshape.curveTo(coords[0], coords[1], coords[2], coords[3],
3897                                coords[4], coords[5]);
3898                        break;
3899                    case PathIterator.SEG_CLOSE:
3900                        newshape.closePath();
3901                        break;
3902                }
3903
3904            }
3905        } catch (Exception exc) {
3906            ErrorLogger.LogException(_className, "createStrokedShape",
3907                    new RendererException("Failed inside createStrokedShape", exc));
3908        }
3909        return newshape;
3910    }
3911    //These functions were added to create a minimum bounding polygon
3912    /**
3913     * @deprecated Returns the determinant of the point matrix This determinant
3914     * tells how far p3 is from vector p1p2 and on which side it is
3915     * @param p1
3916     * @param p2
3917     * @param p3
3918     * @return
3919     */
3920    static private int distance(Point p1, Point p2, Point p3) {
3921        try {
3922            int x1 = p1.x;
3923            int x2 = p2.x;
3924            int x3 = p3.x;
3925            int y1 = p1.y;
3926            int y2 = p2.y;
3927            int y3 = p3.y;
3928            return x1 * y2 + x3 * y1 + x2 * y3 - x3 * y2 - x2 * y1 - x1 * y3;
3929        } catch (Exception exc) {
3930            ErrorLogger.LogException(_className, "distance",
3931                    new RendererException("Failed inside distance", exc));
3932        }
3933        return 0;
3934    }
3935
3936    /**
3937     * @deprecated Returns the determinant of the point matrix This determinant
3938     * tells how far p3 is from vector p1p2 and on which side it is
3939     * @param p1
3940     * @param p2
3941     * @param p3
3942     * @return
3943     */
3944    static private double distance2(POINT2 p1, POINT2 p2, POINT2 p3) {
3945        try {
3946            double x1 = p1.x;
3947            double x2 = p2.x;
3948            double x3 = p3.x;
3949            double y1 = p1.y;
3950            double y2 = p2.y;
3951            double y3 = p3.y;
3952            return x1 * y2 + x3 * y1 + x2 * y3 - x3 * y2 - x2 * y1 - x1 * y3;
3953        } catch (Exception exc) {
3954            ErrorLogger.LogException(_className, "distance2",
3955                    new RendererException("Failed inside distance2", exc));
3956        }
3957        return 0;
3958    }
3959
3960    /**
3961     * @deprecated @param points
3962     * @param l
3963     * @param r
3964     * @param path
3965     */
3966    static private void cHull(ArrayList<Point> points, Point l, Point r, ArrayList<Point> path) {
3967
3968        if (points.size() < 3) {
3969            return;
3970        }
3971
3972        int maxDist = 0;
3973        int tmp;
3974        Point p = null;
3975
3976        for (Point pt : points) {
3977            if (pt != l && pt != r) {
3978                tmp = distance(l, r, pt);
3979
3980                if (tmp > maxDist) {
3981                    maxDist = tmp;
3982                    p = pt;
3983                }
3984            }
3985        }
3986
3987        ArrayList<Point> left = new ArrayList<Point>();
3988        ArrayList<Point> right = new ArrayList<Point>();
3989        left.add(l);
3990        right.add(p);
3991
3992        for (Point pt : points) {
3993            if (distance(l, p, pt) > 0) {
3994                left.add(pt);
3995            } else if (distance(p, r, pt) > 0) {
3996                right.add(pt);
3997            }
3998        }
3999
4000        left.add(p);
4001        right.add(r);
4002        cHull(left, l, p, path);
4003        path.add(p);
4004        cHull(right, p, r, path);
4005    }
4006
4007    /**
4008     * @deprecated @param points
4009     * @param l
4010     * @param r
4011     * @param path
4012     */
4013    static private void cHull2(ArrayList<POINT2> points, POINT2 l, POINT2 r, ArrayList<POINT2> path) {
4014
4015        if (points.size() < 3) {
4016            return;
4017        }
4018
4019        double maxDist = 0;
4020        double tmp;
4021        POINT2 p = null;
4022
4023        for (POINT2 pt : points) {
4024            if (pt != l && pt != r) {
4025                tmp = distance2(l, r, pt);
4026
4027                if (tmp > maxDist) {
4028                    maxDist = tmp;
4029                    p = pt;
4030                }
4031            }
4032        }
4033
4034        ArrayList<POINT2> left = new ArrayList<POINT2>();
4035        ArrayList<POINT2> right = new ArrayList<POINT2>();
4036        left.add(l);
4037        right.add(p);
4038
4039        for (POINT2 pt : points) {
4040            if (distance2(l, p, pt) > 0) {
4041                left.add(pt);
4042            } else if (distance2(p, r, pt) > 0) {
4043                right.add(pt);
4044            }
4045        }
4046
4047        left.add(p);
4048        right.add(r);
4049        cHull2(left, l, p, path);
4050        path.add(p);
4051        cHull2(right, p, r, path);
4052    }
4053    //Returns the points of convex hull in the correct order
4054    /**
4055     * @deprecated @param array
4056     * @return
4057     */
4058    static public ArrayList<Point> cHull(ArrayList<Point> array) {
4059        int size = array.size();
4060        if (size < 2) {
4061            return null;
4062        }
4063
4064        Point l = array.get(0);
4065        Point r = array.get(size - 1);
4066        ArrayList<Point> path = new ArrayList<Point>();
4067        path.add(l);
4068        cHull(array, l, r, path);
4069        path.add(r);
4070        cHull(array, r, l, path);
4071        return path;
4072    }
4073
4074    /**
4075     * @deprecated @param array
4076     * @return
4077     */
4078    static public ArrayList<POINT2> cHull2(ArrayList<POINT2> array) {
4079        try {
4080            int size = array.size();
4081            if (size < 2) {
4082                return null;
4083            }
4084
4085            POINT2 l = array.get(0);
4086            POINT2 r = array.get(size - 1);
4087            ArrayList<POINT2> path = new ArrayList<POINT2>();
4088            path.add(l);
4089            cHull2(array, l, r, path);
4090            path.add(r);
4091            cHull2(array, r, l, path);
4092            return path;
4093        } catch (Exception exc) {
4094            ErrorLogger.LogException(_className, "cHull2",
4095                    new RendererException("Failed inside cHull2", exc));
4096        }
4097        return null;
4098    }
4099
4100    public static void getExteriorPoints(POINT2[] pLinePoints,
4101            int vblCounter,
4102            int lineType,
4103            boolean interior
4104    ) {
4105        int j;
4106        int index;
4107        POINT2 pt0, pt1, pt2;
4108        ref<double[]> m01 = new ref(), m12 = new ref();
4109        int direction;
4110        POINT2 intersectPt;
4111        //ref<double[]> m1 = new ref(), m2 = new ref();
4112        ArrayList<POINT2> intersectPoints = new ArrayList();
4113        double b01, b12;        //the y intercepts for the lines corresponding to m1,m2 
4114        double dist = pLinePoints[0].style;
4115        for (j = 0; j < vblCounter; j++) {
4116            if (j == 0 || j == vblCounter - 1) {
4117                pt0 = new POINT2(pLinePoints[vblCounter - 2]);
4118                pt1 = new POINT2(pLinePoints[0]);
4119                pt2 = new POINT2(pLinePoints[1]);
4120            } else {
4121                pt0 = new POINT2(pLinePoints[j - 1]);
4122                pt1 = new POINT2(pLinePoints[j]);
4123                pt2 = new POINT2(pLinePoints[j + 1]);
4124            }
4125            if (pt1.style > 0) {
4126                dist = pt1.style;
4127            }
4128            //the exterior/interior points
4129            POINT2 pt00, pt01, pt10, pt11;
4130
4131            index = j - 1;
4132            if (index < 0) {
4133                index = vblCounter - 1;
4134            }
4135            POINT2[] pts = new POINT2[pLinePoints.length];
4136            int n=pLinePoints.length;
4137            //for (int k = 0; k < pLinePoints.length; k++) 
4138            for (int k = 0; k < n; k++) 
4139            {
4140                pts[k] = pLinePoints[k];
4141            }
4142
4143            direction = arraysupport.GetInsideOutsideDouble2(pt0, pt1, pts, vblCounter, index, lineType);
4144            //reverse the direction if these are interior points
4145            if (interior == true) {
4146                switch (direction) {
4147                    case 0:
4148                        direction = 1;
4149                        break;
4150                    case 1:
4151                        direction = 0;
4152                        break;
4153                    case 2:
4154                        direction = 3;
4155                        break;
4156                    case 3:
4157                        direction = 2;
4158                        break;
4159                    default:
4160                        break;
4161                }
4162            }
4163            //pt00-pt01 will be the interior line inside line pt0-pt1
4164            //pt00 is inside pt0, pt01 is inside pt1
4165            pt00 = lineutility.ExtendDirectedLine(pt0, pt1, pt0, direction, dist);
4166            pt01 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, direction, dist);
4167
4168            //pt10-pt11 will be the interior line inside line pt1-pt2
4169            //pt10 is inside pt1, pt11 is inside pt2
4170            index = j;
4171            if (j == vblCounter - 1) {
4172                index = 0;
4173            }
4174            direction = arraysupport.GetInsideOutsideDouble2(pt1, pt2, (POINT2[]) pts, vblCounter, index, lineType);
4175            //reverse the direction if these are interior points
4176            if (interior == true) {
4177                switch (direction) {
4178                    case 0:
4179                        direction = 1;
4180                        break;
4181                    case 1:
4182                        direction = 0;
4183                        break;
4184                    case 2:
4185                        direction = 3;
4186                        break;
4187                    case 3:
4188                        direction = 2;
4189                        break;
4190                    default:
4191                        break;
4192                }
4193            }
4194            pt10 = lineutility.ExtendDirectedLine(pt1, pt2, pt1, direction, dist);
4195            pt11 = lineutility.ExtendDirectedLine(pt1, pt2, pt2, direction, dist);
4196            //intersectPt=new POINT2(null);
4197            //get the intersection of pt01-p00 and pt10-pt11
4198            //so it it is the interior intersection of pt0-pt1 and pt1-pt2
4199
4200            //first handle the case of vertical lines.
4201            if (pt0.x == pt1.x && pt1.x == pt2.x) {
4202                intersectPt = new POINT2(pt01);
4203                intersectPoints.add(intersectPt);
4204                continue;
4205            }
4206            //it's the same situation if the slopes are identical,
4207            //simply use pt01 or pt10 since they already uniquely define the intesection
4208            lineutility.CalcTrueSlopeDouble2(pt00, pt01, m01);
4209            lineutility.CalcTrueSlopeDouble2(pt10, pt11, m12);
4210            //if(m01.dbl==m12.dbl)                                      
4211            if (m01.value[0] == m12.value[0]) {
4212                intersectPt = new POINT2(pt01);
4213                intersectPoints.add(intersectPt);
4214                continue;
4215            }
4216            //now we are assuming a non-trivial intersection
4217            //calculate the y-intercepts using y=mx+b (use b=y-mx)
4218            b01 = pt01.y - m01.value[0] * pt01.x;
4219            b12 = pt11.y - m12.value[0] * pt11.x;
4220            intersectPt = lineutility.CalcTrueIntersectDouble2(m01.value[0], b01, m12.value[0], b12, 1, 1, 0, 0);
4221            intersectPoints.add(intersectPt);
4222        }//end for
4223        int n=intersectPoints.size();
4224        //for (j = 0; j < intersectPoints.size(); j++) 
4225        for (j = 0; j < n; j++) 
4226        {
4227            pLinePoints[j] = intersectPoints.get(j);
4228        }
4229    }
4230    public static ArrayList<POINT2> getDeepCopy(ArrayList<POINT2>pts)
4231    {
4232        ArrayList<POINT2>deepCopy=null;
4233        try
4234        {
4235            if(pts == null || pts.isEmpty())
4236                return pts;
4237            deepCopy=new ArrayList();
4238            int j=0;
4239            POINT2 pt=null;
4240            for(j=0;j<pts.size();j++)
4241            {                
4242                pt=new POINT2(pts.get(j).x,pts.get(j).y,pts.get(j).style);
4243                deepCopy.add(pt);
4244            }
4245        }
4246        catch (Exception exc) {
4247            ErrorLogger.LogException(_className, "getDeepCopy",
4248                    new RendererException("Failed inside getDeepCopy", exc));
4249        }
4250        return deepCopy;
4251    }
4252
4253}//end lineutility