001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005
006package armyc2.c5isr.JavaLineArray;
007
008import armyc2.c5isr.JavaTacticalRenderer.TGLight;
009import armyc2.c5isr.JavaTacticalRenderer.clsUtility;
010import armyc2.c5isr.graphics2d.BasicStroke;
011import armyc2.c5isr.graphics2d.Rectangle2D;
012import armyc2.c5isr.renderer.utilities.ErrorLogger;
013import armyc2.c5isr.renderer.utilities.RendererException;
014import armyc2.c5isr.renderer.utilities.RendererSettings;
015
016/**
017 * A class which imported many of the C++ functions from Trident
018 * Systems Dismounted Intelligence Situational Awareness System (DISM) for
019 * rendering Mil-Standard-2525 tactical lines. This class does not get instantiated
020 * Much of the code is still the original DISM code.
021 */
022public final class DISMSupport
023{
024    private static final int LEFT_SIDE=0;
025    private static final int RIGHT_SIDE=1;
026    private static final int COLINEAR=2;
027
028    private static final double CONST_PI = Math.PI;
029    private static final double maxLength=100;
030    private static final double minLength=2.5;    //was 5
031    private static final String _className="DISMSupport";
032    
033//    protected static void setMinLength(double mLength)
034//    {
035//        minLength=mLength;
036//    }
037    private static double GetTGFontSize(double iLength)
038    {
039        double result=-1;
040        try
041        {
042            if (iLength < 20)
043                result = 0;
044            else if (iLength < 50)
045                result = 1;
046            else if (iLength > 250)
047                result = 3;
048            else
049                result = 2;
050        }
051        catch(Exception exc)
052        {
053            ErrorLogger.LogException(_className ,"GetTGFontSize",
054                    new RendererException("Failed inside GetTGFontSize", exc));
055        }
056        return result;
057    }
058    private static void ArcApproximationDouble(double left, double top, double right, double bottom,
059            double startx, double starty, double endx, double endy, POINT2[] lpoints)
060    {
061
062        try
063        {
064            double dstartx = startx;
065            double dstarty = starty;
066            double dendx = endx;
067            double dendy = endy;
068            double a = 0;
069            double b = 0;
070            double ctrX = 0;
071            double ctrY = 0;
072            double x1, y1, x2, y2;
073            double startAngle, endAngle;
074            double angleIncrement = 0;
075            double t=0;
076
077            int i = 0;
078            if (left > right)
079            {
080                double temp = left;
081                left = right;
082                right = temp;
083            }
084            if (top > bottom)
085            {
086                double temp = top;
087                top = bottom;
088                bottom = temp;
089            }
090
091            a = (right - left) / 2.0;
092            b = (bottom - top) / 2.0;
093            ctrX = left + a;
094            ctrY = top + b;
095
096            x1 = dstartx - ctrX;
097            x2 = dendx - ctrX;
098            y1 = ctrY - dstarty;
099            y2 = ctrY - dendy;
100
101            if (y1 == 0)
102            {
103                if (x1 > 0) startAngle = 0;
104                else startAngle = CONST_PI;
105            }
106            else if (x1 == 0)
107            {
108                if (y1 > 0) startAngle = CONST_PI * 0.5;
109                else startAngle = CONST_PI * -0.5;
110            }
111            else startAngle = Math.atan2(y1, x1);
112
113            if (y2 == 0)
114            {
115                if (x2 > 0) endAngle = 0;
116                else endAngle = CONST_PI;
117            }
118            else if (x2 == 0)
119            {
120                if (y2 > 0) endAngle = CONST_PI * 0.5;
121                else endAngle = CONST_PI * -0.5;
122            }
123            else endAngle = Math.atan2(y2, x2);
124
125            if (endAngle <= startAngle) endAngle += 2 * CONST_PI;
126            angleIncrement = (endAngle - startAngle) / 16.0;
127
128            for (t = startAngle; i < 17; t += angleIncrement, i++)
129            {
130                lpoints[i].x = ctrX + a * Math.cos(t);
131                lpoints[i].y = ctrY - b * Math.sin(t);
132            }
133            return;
134        }
135        catch(Exception exc)
136        {
137            ErrorLogger.LogException(_className ,"ArcApproximationDouble",
138                    new RendererException("Failed inside ArcApproximationDouble", exc));
139        }
140    }
141    private static void DrawOpenRectangleDouble(POINT2[] points, POINT2[] pointsCorner, POINT2[] resultpts) {
142        try {
143            // draw open-ended rectangle
144            POINT2 point_mid = new POINT2();
145            int j = 0;
146            //  POINT1 pts[4];
147            point_mid.x = (points[0].x + points[1].x) / 2;
148            point_mid.y = (points[0].y + points[1].y) / 2;
149            pointsCorner[0].x = points[0].x - point_mid.x + points[2].x;
150            pointsCorner[0].y = points[0].y - point_mid.y + points[2].y;
151            pointsCorner[1].x = points[1].x - point_mid.x + points[2].x;
152            pointsCorner[1].y = points[1].y - point_mid.y + points[2].y;
153            resultpts[0] = new POINT2(points[1]);
154            resultpts[1] = new POINT2(pointsCorner[1]);
155            resultpts[2] = new POINT2(pointsCorner[0]);
156            resultpts[3] = new POINT2(points[0]);
157            for (j = 0; j < 4; j++) {
158                resultpts[j].style = 0;
159            }
160            resultpts[3].style = 5;
161            
162        } catch (Exception exc) {
163            ErrorLogger.LogException(_className ,"DrawOpenRectangleDouble",
164                    new RendererException("Failed inside DrawOpenRectangleDouble", exc));
165        }
166        return;
167    }
168    private static int DetermineDirectionDouble(POINT2[] points) {
169        int result=0;
170        try {
171            double dP0P1M = 0;
172            double iP0P1B = 0;
173            if (points[0].x == points[1].x) {
174                if (points[2].x < points[0].x) {
175                    return 1;
176                } else {
177                    return 0;
178                }
179            } else {
180                // dP0P1M = slope of line between Point0 and Point1
181                dP0P1M = (double) (points[0].y - points[1].y) / (double) (points[0].x - points[1].x);
182                // iP0P1B = b component of y=mx+b equation of line
183                iP0P1B = (points[0].y - dP0P1M * points[0].x);
184                if (((points[2].y - iP0P1B) / dP0P1M) > points[2].x) {
185                    return 1;
186                } else {
187                    return 0;
188                }
189            }
190        } catch (Exception exc) {
191            ErrorLogger.LogException(_className ,"DetermineDirectionDouble",
192                    new RendererException("Failed inside DetermineDirectionDouble", exc));
193        }
194        return result;
195    }
196    private static void CalcEndpieceDeltasDouble(POINT2[] points, ref
197        <double[]> piDeltaX, ref <double[]> piDeltaY,
198        double dAngleDelta
199               )
200    {
201        try {
202            // find midpoint between point0 and point1
203            POINT2 pntMid = new POINT2();
204            double iDiagEOL_length = 0;
205            double dAngle1 = 0;
206
207            pntMid.x = (points[0].x + points[1].x) / 2;
208            pntMid.y = (points[0].y + points[1].y) / 2;
209            // iDiagEOL_length = length of the diagonal on end of line from line out to endpoint
210            iDiagEOL_length =  ((Math.sqrt // height of graphic
211                    (
212                    (points[1].x - points[0].x) * (points[1].x - points[0].x) +
213                    (points[1].y - points[0].y) * (points[1].y - points[0].y)) +
214                    Math.sqrt // length of graphic
215                    (
216                    (points[2].x - pntMid.x) * (points[2].x - pntMid.x) +
217                    (points[2].y - pntMid.y) * (points[2].y - pntMid.y))) / 20);
218
219            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
220            if ((double) iDiagEOL_length > maxLength/5 * DPIScaleFactor) {
221                iDiagEOL_length = maxLength/5 * DPIScaleFactor;
222            }
223            if ((double) iDiagEOL_length < minLength * DPIScaleFactor) {
224                iDiagEOL_length = minLength * DPIScaleFactor;
225            }
226
227            // dAngle1 = angle used to calculate the end-piece deltas
228            dAngle1 = Math.atan2(points[2].y - pntMid.y, points[2].x - pntMid.x) + dAngleDelta;
229            //  dAngle1 = atan2(points[2].y - pntMid.y, points[2].x - pntMid.x) + dAngleDelta;
230            piDeltaX.value=new double[1];
231            piDeltaY.value=new double[1];
232            piDeltaX.value[0] =  (iDiagEOL_length * Math.cos(dAngle1));
233            piDeltaY.value[0] = (iDiagEOL_length * Math.sin(dAngle1));
234            return;
235        } catch (Exception exc) {
236            ErrorLogger.LogException(_className ,"CalcEndpieceDeltasDouble",
237                    new RendererException("Failed inside CalcEndpieceDeltasDouble", exc));
238        }
239    }
240    /**
241     * Calculates the points for DELAY, WITHDRAW, WDRAWUP, RETIRE
242     *
243     * @param points OUT - the client points, also used for the returned points.
244     */
245    protected static int GetDelayGraphicEtcDouble(POINT2[] points) {
246        int counter=0;
247        try {
248            POINT2[] pts = new POINT2[2];
249            POINT2[] savepoints = new POINT2[3];
250            double iLength = 0;
251            double iRadius = 0;
252            double iDiagEOL_length = 0;
253            double dAngle1 = 0;
254            double iDeltaX1 = 0;
255            double iDeltaY1 = 0;
256            double iDeltaX2 = 0;
257            double iDeltaY2 = 0;
258            POINT2 ptArcCenter = new POINT2();
259            POINT2[] arcpoints = new POINT2[17];
260            POINT2[] deltapoints = new POINT2[4];
261            int j = 0;
262
263            for (j = 0; j < 3; j++) {
264                savepoints[j] = new POINT2(points[j]);
265            }
266
267            lineutility.InitializePOINT2Array(pts);
268            lineutility.InitializePOINT2Array(arcpoints);
269            lineutility.InitializePOINT2Array(deltapoints);
270
271            points[counter] = new POINT2(savepoints[0]);
272            points[counter].style = 14;
273            counter++;
274            points[counter] = new POINT2(savepoints[1]);
275            points[counter].style = 5;
276            counter++;
277
278            iLength =  Math.sqrt((savepoints[1].x - savepoints[0].x) * (savepoints[1].x - savepoints[0].x) +
279                    (savepoints[1].y - savepoints[0].y) * (savepoints[1].y - savepoints[0].y));
280            iRadius =  Math.sqrt((savepoints[2].x - savepoints[1].x) * (savepoints[2].x - savepoints[1].x) +
281                    (savepoints[2].y - savepoints[1].y) * (savepoints[2].y - savepoints[1].y)) / 2;
282            iDiagEOL_length = (iLength + iRadius * 2) / 20;           
283
284            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
285            if ((double) iDiagEOL_length > maxLength * DPIScaleFactor) {
286                iDiagEOL_length = maxLength * DPIScaleFactor;
287            }
288            if ((double) iDiagEOL_length < minLength * DPIScaleFactor) {   //was minLength
289                iDiagEOL_length = minLength * DPIScaleFactor;
290            }
291                        
292            dAngle1 = Math.atan2(points[1].y - points[0].y, points[1].x - points[0].x);
293
294            iDeltaX1 = (iDiagEOL_length * Math.cos(dAngle1 - CONST_PI / 4));
295            iDeltaY1 = (iDiagEOL_length * Math.sin(dAngle1 - CONST_PI / 4));
296            iDeltaX2 = (iDiagEOL_length * Math.cos(dAngle1 + CONST_PI / 4));
297            iDeltaY2 = (iDiagEOL_length * Math.sin(dAngle1 + CONST_PI / 4));
298            DrawEndpieceDeltasDouble(savepoints[0],
299                    iDeltaX1, iDeltaY1, iDeltaX2, iDeltaY2, deltapoints);
300
301
302            for (j = 0; j < 4; j++) {
303                points[counter] = new POINT2(deltapoints[j]);
304                counter++;
305            }
306            // draw the semicircle
307            ptArcCenter.x = (savepoints[1].x + savepoints[2].x) / 2;
308            ptArcCenter.y = (savepoints[1].y + savepoints[2].y) / 2;
309
310
311            boolean reverseArc = ReverseDelayArc(savepoints);
312            if (reverseArc == false) {
313                ArcApproximationDouble( (ptArcCenter.x - iRadius), (ptArcCenter.y - iRadius),
314                        (ptArcCenter.x + iRadius), (ptArcCenter.y + iRadius),
315                        savepoints[1].x, savepoints[1].y, savepoints[2].x, savepoints[2].y, arcpoints);
316            } else {
317                ArcApproximationDouble((ptArcCenter.x - iRadius), (ptArcCenter.y - iRadius),
318                        (ptArcCenter.x + iRadius), (ptArcCenter.y + iRadius),
319                        savepoints[2].x, savepoints[2].y, savepoints[1].x, savepoints[1].y, arcpoints);
320            }
321
322            for (j = 0; j < 17; j++) {
323                points[counter] = new POINT2(arcpoints[j]);
324                points[counter].style = 0;
325                counter++;
326            }
327
328        } catch (Exception exc) {
329            ErrorLogger.LogException(_className ,"GetDelayGraphicEtcDouble",
330                    new RendererException("Failed inside GetDelayGraphicEtcDouble", exc));
331        }
332        return counter;
333    }
334    /**
335     * Calculates the points for SCREEN, COVER, GUARD, SARA.
336     *
337     * @param points OUT - the client points, also used for the returned points.
338     * @param lineType the line type.
339     */
340    protected static int GetDISMCoverDouble(POINT2[] points,
341                                            int lineType) {
342        int counter = 0;
343        try {
344            POINT2 pt0 = new POINT2(points[0]);
345            POINT2 pt1 = new POINT2(points[1]);
346            POINT2 pt2 = new POINT2(points[2]);
347            POINT2 pt3 = new POINT2();
348            POINT2 pt4 = new POINT2();
349
350            lineutility.LineRelativeToLine(pt1, pt2, pt0, pt3, pt4);
351            //now we have the pt3-pt4 line which pt0 is on
352            //get the corresponding point back on the original line
353            lineutility.LineRelativeToLine(pt3, pt0, pt1, pt2, pt4);
354            final int quadrant = lineutility.GetQuadrantDouble(pt0, pt4);
355
356            pt1 = new POINT2(points[1]);
357            pt2 = new POINT2(points[2]);
358            final int sign;
359            if (pt1.x < pt2.x && (quadrant == 1 || quadrant == 4))
360                sign = -1;
361            else if (pt1.x > pt2.x && (quadrant == 2 || quadrant == 3))
362                sign = -1;
363            else
364                sign = 1;
365
366            POINT2 initialPt = new POINT2(points[0]);
367            initialPt.style = 0;
368            POINT2 endPt0 = new POINT2(points[1]);
369            endPt0.style = 0;
370            POINT2 endPt1 = new POINT2(points[2]);
371            endPt1.style = 0;
372
373            // Get length of each line from initial point
374            double length1 = lineutility.CalcDistanceDouble(initialPt, endPt0);
375            double length2 = lineutility.CalcDistanceDouble(initialPt, endPt1);
376            length1 = Math.min(length1, length2);
377
378            if (GetTGFontSize(length1) > 0) {
379                double delta = length1 / 15;
380
381                double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
382                if (delta > maxLength * DPIScaleFactor) {
383                    delta = maxLength * DPIScaleFactor;
384                }
385                if (delta < minLength * DPIScaleFactor) {
386                    delta = minLength * DPIScaleFactor;
387                }
388
389                POINT2[] ptsJaggyLine = new POINT2[4];
390                lineutility.InitializePOINT2Array(ptsJaggyLine);
391
392                // Draw jaggy line 1
393                final double angle0 = Math.atan2(initialPt.y - endPt0.y, initialPt.x - endPt0.x);
394                final double deltaX0a = Math.cos(angle0 + sign * CONST_PI / 4) * delta;
395                final double deltaY0a = Math.sin(angle0 + sign * CONST_PI / 4) * delta;
396                ptsJaggyLine[0] = new POINT2(initialPt);
397                if (lineType != TacticalLines.SARA) {
398                    ptsJaggyLine[0].x -= 30 * Math.cos(angle0);  //was 20
399                    ptsJaggyLine[0].y -= 30 * Math.sin(angle0);
400                }
401                POINT2 midPt0 = lineutility.MidPointDouble(ptsJaggyLine[0], endPt0, 0);
402                ptsJaggyLine[1].x = midPt0.x - deltaX0a;
403                ptsJaggyLine[1].y = midPt0.y - deltaY0a;
404                ptsJaggyLine[2].x = midPt0.x + deltaX0a;
405                ptsJaggyLine[2].y = midPt0.y + deltaY0a;
406                ptsJaggyLine[3] = new POINT2(endPt0);
407                for (int j = 0; j < 4; j++) {
408                    points[counter] = new POINT2(ptsJaggyLine[j]);
409                    counter++;
410                }
411                points[counter - 1].style = 5;
412
413                // Draw Arrow 1
414                final double deltaX0b = Math.cos(angle0 - sign * CONST_PI / 4) * delta;
415                final double deltaY0b = Math.sin(angle0 - sign * CONST_PI / 4) * delta;
416                ptsJaggyLine[0].x = ptsJaggyLine[3].x + deltaX0a;
417                ptsJaggyLine[0].y = ptsJaggyLine[3].y + deltaY0a;
418                ptsJaggyLine[1] = new POINT2(ptsJaggyLine[3]);
419                ptsJaggyLine[2].x = ptsJaggyLine[3].x + deltaX0b;
420                ptsJaggyLine[2].y = ptsJaggyLine[3].y + deltaY0b;
421                for (int j = 0; j < 3; j++) {
422                    points[counter] = new POINT2(ptsJaggyLine[j]);
423                    points[counter].style = 0;
424                    if (lineType == TacticalLines.SARA) {
425                        points[counter].style = 9;
426                    }
427
428                    counter++;
429                }
430                points[counter - 1].style = 5;
431                if (lineType == TacticalLines.SARA) {
432                    points[counter - 1].style = 9;
433                    points[counter] = new POINT2(points[counter - 3]);
434                    points[counter].style = 10;
435                    counter++;
436                }
437
438                // Draw jaggy line 2
439                final double angle1 = Math.atan2(initialPt.y - endPt1.y, initialPt.x - endPt1.x);
440                final double deltaX1a = Math.cos(angle1 - sign * CONST_PI / 4) * delta;
441                final double deltaY1a = Math.sin(angle1 - sign * CONST_PI / 4) * delta;
442                ptsJaggyLine[0] = new POINT2(initialPt);
443                if (lineType != TacticalLines.SARA) {
444                    ptsJaggyLine[0].x -= 30 * Math.cos(angle1);  //was 20
445                    ptsJaggyLine[0].y -= 30 * Math.sin(angle1);
446                }
447                POINT2 midPt1 = lineutility.MidPointDouble(ptsJaggyLine[0], endPt1, 0);
448                ptsJaggyLine[1].x = midPt1.x - deltaX1a;
449                ptsJaggyLine[1].y = midPt1.y - deltaY1a;
450                ptsJaggyLine[2].x = midPt1.x + deltaX1a;
451                ptsJaggyLine[2].y = midPt1.y + deltaY1a;
452                ptsJaggyLine[3] = new POINT2(endPt1);
453                for (int j = 0; j < 4; j++) {
454                    points[counter] = new POINT2(ptsJaggyLine[j]);
455                    counter++;
456                }
457                points[counter - 1].style = 5;
458
459                // Draw Arrow 2
460                final double deltaX1b = Math.cos(angle1 + sign * CONST_PI / 4) * delta;
461                final double deltaY1b = Math.sin(angle1 + sign * CONST_PI / 4) * delta;
462                ptsJaggyLine[0].x = ptsJaggyLine[3].x + deltaX1a;
463                ptsJaggyLine[0].y = ptsJaggyLine[3].y + deltaY1a;
464                ptsJaggyLine[1] = new POINT2(ptsJaggyLine[3]);
465                ptsJaggyLine[2].x = ptsJaggyLine[3].x + deltaX1b;
466                ptsJaggyLine[2].y = ptsJaggyLine[3].y + deltaY1b;
467                for (int j = 0; j < 3; j++) {
468                    points[counter] = new POINT2(ptsJaggyLine[j]);
469                    points[counter].style = 0;
470                    if (lineType == TacticalLines.SARA)
471                        points[counter].style = 9;
472
473                    counter++;
474                }
475                points[counter - 1].style = 5;
476                if (lineType == TacticalLines.SARA) {
477                    points[counter - 1].style = 9;
478                    points[counter] = new POINT2(points[counter - 3]);
479                    points[counter].style = 10;
480                    counter++;
481                }
482            } else {
483                points[0] = new POINT2(initialPt);
484                points[0].style = 0;
485                points[1] = new POINT2(endPt0);
486                points[1].style = 5;
487                points[2] = new POINT2(initialPt);
488                points[2].style = 0;
489                points[3] = new POINT2(endPt1);
490                return 4;
491            }
492        } catch (Exception exc) {
493            ErrorLogger.LogException(_className, "GetDISMcoverDouble",
494                    new RendererException("Failed inside GetDISMCoverDouble", exc));
495        }
496        return counter;
497    }
498    /**
499     * rev C uses 4 
500     * @param points
501     * @param linetype
502     * @return
503     */
504    protected static int GetDISMCoverDoubleRevC(POINT2[] points,
505                                            int linetype,
506                                            int vblSaveCounter) 
507    {
508            int counter = 0;
509        try 
510        {                        
511            // switch points[1] and points[2] if they are backwards
512            double dAngle0=0, dDeltaX0=0, dDeltaY0=0, dDeltaX1=0, dDeltaY1=0;
513            double iLengthPt0Pt1 = 0;
514            double iLengthPt0Pt2 = 0;
515            double iDelta = 0;
516            int j=0;
517            int t=1;
518            double iFontSize = 0;
519            double iLetterOffset = 0;
520            POINT2[] savepoints = new POINT2[3];
521            POINT2[] pts = new POINT2[2];
522            POINT2[] ptsJaggyLine = new POINT2[4];
523            //float scale = 1;
524            boolean goLeftThenRight=false;
525            int sign=1;
526            
527            //rev C with 4 points
528            POINT2[]origPoints=null;
529            if(vblSaveCounter==4)
530            {
531                origPoints=new POINT2[4];
532                for(j=0;j<vblSaveCounter;j++)
533                    origPoints[j]=new POINT2(points[j]);
534                
535                //reorder points
536                points[1]=origPoints[0];
537                points[2]=origPoints[3];
538                points[0].x=(origPoints[1].x+origPoints[2].x)/2;
539                points[0].y=(origPoints[1].y+origPoints[2].y)/2;
540            }
541                        
542            //added section for jaggy line orientation M. Deutch 6-24-11
543            POINT2 pt0=new POINT2(points[0]);
544            POINT2 pt1=new POINT2(points[1]);
545            POINT2 pt2=new POINT2(points[2]);
546            POINT2 pt3=new POINT2();
547            POINT2 pt4=new POINT2();                        
548            
549            lineutility.LineRelativeToLine(pt1, pt2, pt0, pt3, pt4);
550            //now we have the pt3-pt4 line which pt0 is on
551            //get the corresponding point back on the original line
552            lineutility.LineRelativeToLine(pt3, pt0, pt1, pt2, pt4);
553            int quadrant=lineutility.GetQuadrantDouble(pt0, pt4);
554
555            pt1=new POINT2(points[1]);
556            pt2=new POINT2(points[2]);
557            if(pt1.x<pt2.x && quadrant==1)
558                sign=-1;
559            else if(pt1.x > pt2.x && quadrant == 2)
560                sign=-1;
561            else if(pt1.x > pt2.x && quadrant == 3)
562                sign=-1;
563            else if(pt1.x < pt2.x && quadrant == 4)
564                sign=-1;
565            if(linetype==TacticalLines.SARA)
566                t=0;
567            
568            if(points[1].x<=points[2].x)
569                goLeftThenRight=true;
570
571            //save the points in the correct order
572            for (j = 0; j < 3; j++) {
573                savepoints[j] = new POINT2(points[j]);
574                savepoints[j].style = 0;
575            }
576
577            lineutility.InitializePOINT2Array(pts);
578            lineutility.InitializePOINT2Array(ptsJaggyLine);
579
580            iLengthPt0Pt1 = Math.sqrt((savepoints[1].x - savepoints[0].x) * (savepoints[1].x - savepoints[0].x) +
581                    (savepoints[1].y - savepoints[0].y) * (savepoints[1].y - savepoints[0].y));
582            iLengthPt0Pt2 = Math.sqrt((savepoints[2].x - savepoints[0].x) * (savepoints[2].x - savepoints[0].x) +
583                    (savepoints[2].y - savepoints[0].y) * (savepoints[2].y - savepoints[0].y));
584
585            if (iLengthPt0Pt1 > iLengthPt0Pt2) {
586                iLengthPt0Pt1 = iLengthPt0Pt2;
587            }
588            iFontSize = GetTGFontSize(iLengthPt0Pt1);
589            if (iFontSize > 0) 
590            {
591                iDelta = iLengthPt0Pt1 / 15;//was 15
592
593                double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
594                if (iDelta > maxLength * DPIScaleFactor) {
595                    iDelta = maxLength * DPIScaleFactor;
596                }
597                if (iDelta < minLength * DPIScaleFactor) {
598                    iDelta = minLength * DPIScaleFactor;
599                }
600                
601                // left side: draw letter in from the jaggy line
602                if(vblSaveCounter<4)//rev b
603                {
604                    if(goLeftThenRight)
605                        savepoints[0].x-=30*t;  //was 20
606                    else
607                        savepoints[0].x+=30*t;  //was 20
608                    
609                    iLetterOffset = 0;
610                    ptsJaggyLine[0].x = savepoints[0].x - iLetterOffset * 2;//was -
611                    ptsJaggyLine[0].y = savepoints[0].y;                
612                    ptsJaggyLine[0].x -= iLetterOffset;                
613                    dAngle0 = Math.atan2(ptsJaggyLine[0].y - savepoints[1].y, ptsJaggyLine[0].x - savepoints[1].x);
614                    pts[0].x = (ptsJaggyLine[0].x + savepoints[1].x) / 2;
615                    pts[0].y = (ptsJaggyLine[0].y + savepoints[1].y) / 2;
616                    dDeltaX0 = Math.cos(dAngle0 + sign*CONST_PI / 4) * iDelta;   //was +
617                    dDeltaY0 = Math.sin(dAngle0 + sign*CONST_PI / 4) * iDelta;   //was +
618                    ptsJaggyLine[1].x = pts[0].x - dDeltaX0;    //was -
619                    ptsJaggyLine[1].y = pts[0].y - dDeltaY0;    //was -
620                    ptsJaggyLine[2].x = pts[0].x + dDeltaX0;    //was +
621                    ptsJaggyLine[2].y = pts[0].y + dDeltaY0;    //was +
622                    ptsJaggyLine[3] = new POINT2(savepoints[1]);
623                    for (j = 0; j < 4; j++) 
624                    {
625                        points[counter] = new POINT2(ptsJaggyLine[j]);
626                        counter++;
627                    }
628                    points[counter - 1].style = 5;
629                }//end rev b
630                else    //rev c
631                {
632                    ptsJaggyLine[0]=new POINT2(origPoints[1]);
633                    dAngle0 = Math.atan2(ptsJaggyLine[0].y - origPoints[0].y, ptsJaggyLine[0].x - origPoints[0].x);
634                    pts[0].x = (ptsJaggyLine[0].x + origPoints[0].x) / 2;
635                    pts[0].y = (ptsJaggyLine[0].y + origPoints[0].y) / 2;
636                    dDeltaX0 = Math.cos(dAngle0 + sign*CONST_PI / 4) * iDelta;   //was +
637                    dDeltaY0 = Math.sin(dAngle0 + sign*CONST_PI / 4) * iDelta;   //was +
638                    ptsJaggyLine[1].x = pts[0].x - dDeltaX0;    //was -
639                    ptsJaggyLine[1].y = pts[0].y - dDeltaY0;    //was -
640                    ptsJaggyLine[2].x = pts[0].x + dDeltaX0;    //was +
641                    ptsJaggyLine[2].y = pts[0].y + dDeltaY0;    //was +
642                    //ptsJaggyLine[3] = new POINT2(savepoints[1]);
643                    ptsJaggyLine[3] = new POINT2(origPoints[0]);
644                    for (j = 0; j < 4; j++) 
645                    {
646                        points[counter] = new POINT2(ptsJaggyLine[j]);
647                        counter++;
648                    }
649                    points[counter - 1].style = 5;                    
650                }//end rev c
651                
652                // draw arrow at end of line
653                dDeltaX1 = Math.cos(dAngle0 - sign*CONST_PI / 4) * iDelta;   //was -
654                dDeltaY1 = Math.sin(dAngle0 - sign*CONST_PI / 4) * iDelta;   //was -
655                if(vblSaveCounter<4)
656                {
657                    ptsJaggyLine[0].x = savepoints[1].x + dDeltaX0; //was +
658                    ptsJaggyLine[0].y = savepoints[1].y + dDeltaY0; //was +
659                }
660                else
661                {
662                    ptsJaggyLine[0].x = origPoints[0].x + dDeltaX0; //was +
663                    ptsJaggyLine[0].y = origPoints[0].y + dDeltaY0; //was +                    
664                }
665                if(vblSaveCounter<4)
666                    ptsJaggyLine[1] = new POINT2(savepoints[1]);
667                else
668                    ptsJaggyLine[1] = new POINT2(origPoints[0]);
669                    
670                if(vblSaveCounter<4)
671                {
672                    ptsJaggyLine[2].x = savepoints[1].x + dDeltaX1; //was +
673                    ptsJaggyLine[2].y = savepoints[1].y + dDeltaY1; //was +
674                }
675                else
676                {
677                    ptsJaggyLine[2].x = origPoints[0].x + dDeltaX1; //was +
678                    ptsJaggyLine[2].y = origPoints[0].y + dDeltaY1; //was +                    
679                }
680                for (j = 0; j < 3; j++) {
681                    points[counter] = new POINT2(ptsJaggyLine[j]);
682                    points[counter].style = 0;
683                    if(linetype==TacticalLines.SARA)
684                    {
685                        points[counter].style = 9;
686                    }
687
688                    counter++;
689                }
690
691                points[counter - 1].style = 5;
692                if(linetype==TacticalLines.SARA)
693                {
694                    points[counter-1].style = 9;
695                    points[counter]=new POINT2(points[counter-3]);
696                    points[counter].style=10;
697                    counter++;
698                }
699
700                // right side: draw letter and jaggy line
701                if(vblSaveCounter<4)    //rev b
702                {
703                    if(goLeftThenRight)
704                        savepoints[0].x+=60*t;  //was 40
705                    else
706                        savepoints[0].x-=60*t;  //wass 40
707
708                    ptsJaggyLine[0].x = savepoints[0].x + iLetterOffset * 2;
709                    ptsJaggyLine[0].y = savepoints[0].y;
710                    ptsJaggyLine[0].x += iLetterOffset;                
711                    dAngle0 = Math.atan2(ptsJaggyLine[0].y - savepoints[2].y, ptsJaggyLine[0].x - savepoints[2].x);
712                    pts[0].x = (ptsJaggyLine[0].x + savepoints[2].x) / 2;
713                    pts[0].y = (ptsJaggyLine[0].y + savepoints[2].y) / 2;
714                    dDeltaX0 = Math.cos(dAngle0 - sign*CONST_PI / 4) * iDelta;   //was -
715                    dDeltaY0 = Math.sin(dAngle0 - sign*CONST_PI / 4) * iDelta;   //was -
716                    ptsJaggyLine[1].x = pts[0].x - dDeltaX0;    //was -
717                    ptsJaggyLine[1].y = pts[0].y - dDeltaY0;    //was -
718                    ptsJaggyLine[2].x = pts[0].x + dDeltaX0;    //was +
719                    ptsJaggyLine[2].y = pts[0].y + dDeltaY0;    //was +
720                    ptsJaggyLine[3] = new POINT2(savepoints[2]);
721                    for (j = 0; j < 4; j++) {
722                        points[counter] = new POINT2(ptsJaggyLine[j]);
723                        counter++;
724                    }
725                    points[counter - 1].style = 5;
726                    // draw arrow at end of line
727                    dDeltaX1 = Math.cos(dAngle0 + sign*CONST_PI / 4) * iDelta;   //was +
728                    dDeltaY1 = Math.sin(dAngle0 + sign*CONST_PI / 4) * iDelta;   //was +
729                    ptsJaggyLine[0].x = savepoints[2].x + dDeltaX0;
730                    ptsJaggyLine[0].y = savepoints[2].y + dDeltaY0;
731                    ptsJaggyLine[1] = savepoints[2];
732                    ptsJaggyLine[2].x = savepoints[2].x + dDeltaX1;
733                    ptsJaggyLine[2].y = savepoints[2].y + dDeltaY1;
734                }//end rev b
735                else    //rev c
736                {
737                    ptsJaggyLine[0]=new POINT2(origPoints[2]);
738                    dAngle0 = Math.atan2(ptsJaggyLine[0].y - origPoints[3].y, ptsJaggyLine[0].x - origPoints[3].x);
739                    pts[0].x = (ptsJaggyLine[0].x + origPoints[3].x) / 2;
740                    pts[0].y = (ptsJaggyLine[0].y + origPoints[3].y) / 2;
741                    dDeltaX0 = Math.cos(dAngle0 - sign*CONST_PI / 4) * iDelta;   //was -
742                    dDeltaY0 = Math.sin(dAngle0 - sign*CONST_PI / 4) * iDelta;   //was -
743                    ptsJaggyLine[1].x = pts[0].x - dDeltaX0;    //was -
744                    ptsJaggyLine[1].y = pts[0].y - dDeltaY0;    //was -
745                    ptsJaggyLine[2].x = pts[0].x + dDeltaX0;    //was +
746                    ptsJaggyLine[2].y = pts[0].y + dDeltaY0;    //was +
747                    //ptsJaggyLine[3] = new POINT2(savepoints[2]);
748                    ptsJaggyLine[3] = new POINT2(origPoints[3]);
749                    for (j = 0; j < 4; j++) {
750                        points[counter] = new POINT2(ptsJaggyLine[j]);
751                        counter++;
752                    }
753                    points[counter - 1].style = 5;
754                    // draw arrow at end of line
755                    dDeltaX1 = Math.cos(dAngle0 + sign*CONST_PI / 4) * iDelta;   //was +
756                    dDeltaY1 = Math.sin(dAngle0 + sign*CONST_PI / 4) * iDelta;   //was +
757                    ptsJaggyLine[0].x = origPoints[3].x + dDeltaX0;
758                    ptsJaggyLine[0].y = origPoints[3].y + dDeltaY0;
759                    ptsJaggyLine[1] = new POINT2(origPoints[3]);
760                    ptsJaggyLine[2].x = origPoints[3].x + dDeltaX1;
761                    ptsJaggyLine[2].y = origPoints[3].y + dDeltaY1;                    
762                }//end rev c
763                
764                for (j = 0; j < 3; j++) 
765                {
766                    points[counter] = new POINT2(ptsJaggyLine[j]);
767                    points[counter].style = 0;
768                    if(linetype==TacticalLines.SARA)
769                        points[counter].style = 9;
770
771                    counter++;
772                }
773                points[counter - 1].style = 5;
774                if(linetype==TacticalLines.SARA)
775                {
776                    points[counter-1].style = 9;
777                    points[counter]=new POINT2(points[counter-3]);
778                    points[counter].style=10;
779                    counter++;
780                }
781            }
782            else 
783            {
784                points[0] = new POINT2(savepoints[0]);
785                points[0].style = 0;
786                points[1] = new POINT2(savepoints[1]);
787                points[1].style = 5;
788                points[2] = new POINT2(savepoints[0]);
789                points[2].style = 0;
790                points[3] = new POINT2(savepoints[2]);
791                return 4;
792            }
793        } 
794        catch (Exception exc) 
795        {
796            ErrorLogger.LogException(_className ,"GetDISMcoverDoubleRevC",
797                    new RendererException("Failed inside GetDISMCoverDoubleRevc", exc));
798        }
799        return counter;
800    }
801    /**
802     * Calculates the points for BYPASS
803     *
804     * @param points OUT - the client points, also used for the returned points.
805     * @param linetype the line type.
806     */
807    protected static int GetDISMBypassDouble(POINT2[] points,
808                                            int linetype) {
809        int counter = 0;
810        try {
811            int j = 0;
812            POINT2[] pointsCorner = new POINT2[2];
813            POINT2[] rectpts = new POINT2[4];
814            POINT2[] savepoints = new POINT2[3];
815            POINT2[] deltapoints1 = new POINT2[4];
816            POINT2[] deltapoints2 = new POINT2[4];
817            ref<double[]> iDeltaX = new ref(), iDeltaY = new ref();
818            int bPointsRight = 0;
819
820            for (j = 0; j < 3; j++) {
821                savepoints[j] = new POINT2(points[j]);
822            }
823
824            lineutility.InitializePOINT2Array(pointsCorner);
825            lineutility.InitializePOINT2Array(rectpts);
826            lineutility.InitializePOINT2Array(deltapoints1);
827            lineutility.InitializePOINT2Array(deltapoints2);
828
829            DrawOpenRectangleDouble(savepoints, pointsCorner, rectpts);
830            for (j = 0; j < 4; j++) {
831                points[counter] = rectpts[j];
832                counter++;
833            }
834
835            bPointsRight = DetermineDirectionDouble(savepoints);
836
837            CalcEndpieceDeltasDouble(savepoints, iDeltaX, iDeltaY, CONST_PI / 4);
838
839            if ((savepoints[0].y - savepoints[1].y) < 0) {// Point0 is higher than Point1
840                if (bPointsRight != 0) {// figure opens to the right
841                    DrawEndpieceDeltasDouble(savepoints[0],
842                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints1);
843                    DrawEndpieceDeltasDouble(savepoints[1],
844                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints2);
845                } else {// figure opens to the left
846                    DrawEndpieceDeltasDouble(savepoints[0],
847                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints1);
848                    DrawEndpieceDeltasDouble(savepoints[1],
849                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints2);
850                }
851            } else {// Point0 is lower than Point1
852                if (bPointsRight != 0) {// figure opens to the right
853                    DrawEndpieceDeltasDouble(savepoints[0],
854                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints1);
855                    DrawEndpieceDeltasDouble(savepoints[1],
856                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints2);
857                } else {// figure opens to the left
858                    DrawEndpieceDeltasDouble(savepoints[0],
859                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints1);
860                    DrawEndpieceDeltasDouble(savepoints[1],
861                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints2);
862                }
863            }
864
865            for (j = 0; j < 4; j++) {
866                points[counter] = new POINT2(deltapoints1[j]);
867                counter++;
868            }
869            for (j = 0; j < 4; j++) {
870                points[counter] = new POINT2(deltapoints2[j]);
871                counter++;
872            }
873        } catch (Exception exc) {
874            ErrorLogger.LogException(_className ,"GetDISMBypassDouble",
875                    new RendererException("Failed inside GetDISMBypassDouble", exc));
876        }
877        return counter;
878    }
879    /**
880     * Calculates the points for BREACH.
881     *
882     * @param points OUT - the client points, also used for the returned points.
883     * @param linetype the line type.
884     */
885    protected static int GetDISMBreachDouble(POINT2[] points, int linetype) {
886        int counter = 0;
887        try {
888            POINT2[] pointsCorner = new POINT2[2];
889            POINT2[] rectpts = new POINT2[4];
890            POINT2[] deltapoints1 = new POINT2[4];
891            POINT2[] deltapoints2 = new POINT2[4];
892            ref<double[]> iDeltaX = new ref(), iDeltaY = new ref();
893            int bPointsRight = 0, j = 0;
894            POINT2[] savepoints = new POINT2[3];
895
896            for (j = 0; j < 3; j++) {
897                savepoints[j] = new POINT2(points[j]);
898            }
899
900            lineutility.InitializePOINT2Array(pointsCorner);
901            lineutility.InitializePOINT2Array(rectpts);
902            lineutility.InitializePOINT2Array(deltapoints1);
903            lineutility.InitializePOINT2Array(deltapoints2);
904
905            DrawOpenRectangleDouble(savepoints, pointsCorner, rectpts);
906            for (j = 0; j < 4; j++) {
907                points[counter] = new POINT2(rectpts[j]);
908                counter++;
909            }
910
911            bPointsRight = DetermineDirectionDouble(savepoints);
912
913            CalcEndpieceDeltasDouble(savepoints, iDeltaX, iDeltaY, CONST_PI / 4);
914
915            if ((savepoints[0].y - savepoints[1].y) < 0) {// Point0 is higher than Point1
916                if (bPointsRight != 0) {// figure opens to the right
917                    DrawEndpieceDeltasDouble(savepoints[0],
918                            iDeltaX.value[0], iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], deltapoints1);
919                    DrawEndpieceDeltasDouble(savepoints[1],
920                            iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], iDeltaX.value[0], deltapoints2);
921                } else {// figure opens to the left
922                    DrawEndpieceDeltasDouble(savepoints[0],
923                            iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], iDeltaX.value[0], deltapoints1);
924                    DrawEndpieceDeltasDouble(savepoints[1],
925                            iDeltaX.value[0], iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], deltapoints2);
926                }
927            } else {// Point0 is lower than Point1
928                if (bPointsRight != 0) {// figure opens to the right
929                    DrawEndpieceDeltasDouble(savepoints[0],
930                            iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], iDeltaX.value[0], deltapoints1);
931                    DrawEndpieceDeltasDouble(savepoints[1],
932                            iDeltaX.value[0], iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], deltapoints2);
933                } else {// figure opens to the left
934                    DrawEndpieceDeltasDouble(savepoints[0],
935                            iDeltaX.value[0], iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], deltapoints1);
936                    DrawEndpieceDeltasDouble(savepoints[1],
937                            iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], iDeltaX.value[0], deltapoints2);
938                }
939            }
940            for (j = 0; j < 4; j++) {
941                points[counter] = new POINT2(deltapoints1[j]);
942                counter++;
943            }
944            for (j = 0; j < 4; j++) {
945                points[counter] = new POINT2(deltapoints2[j]);
946                counter++;
947            }
948        } catch (Exception exc) {
949            ErrorLogger.LogException(_className ,"GetDISMBreachDouble",
950                    new RendererException("Failed inside GetDISMBreachDouble", exc));
951        }
952        return counter;
953    }
954    /**
955     * Calculates the points for CANALIZE
956     *
957     * @param points - OUT - the client points, also used for the returned points.
958     * @param linetype the line type.
959     */
960    protected static int GetDISMCanalizeDouble(POINT2[] points, int linetype) {
961        int counter = 0;
962        try {
963            POINT2[] pointsCorner = new POINT2[2];
964            POINT2[] rectpts = new POINT2[4];
965            POINT2[] deltapoints1 = new POINT2[4];
966            POINT2[] deltapoints2 = new POINT2[4];
967            int j = 0;
968            ref<double[]> iDeltaX = new ref(), iDeltaY = new ref();
969            int bPointsRight = 0;
970            POINT2[] savepoints = new POINT2[3];
971
972            for (j = 0; j < 3; j++) {
973                savepoints[j] = new POINT2(points[j]);
974            }
975
976            lineutility.InitializePOINT2Array(pointsCorner);
977            lineutility.InitializePOINT2Array(rectpts);
978            lineutility.InitializePOINT2Array(deltapoints1);
979            lineutility.InitializePOINT2Array(deltapoints2);
980
981            DrawOpenRectangleDouble(savepoints, pointsCorner, rectpts);
982
983            for (j = 0; j < 4; j++) {
984                points[counter] = new POINT2(rectpts[j]);
985                counter++;
986            }
987
988            bPointsRight = DetermineDirectionDouble(savepoints);
989
990            CalcEndpieceDeltasDouble(savepoints, iDeltaX, iDeltaY, CONST_PI / 4);
991
992            if ((savepoints[0].y - savepoints[1].y) < 0) {// Point0 is higher than Point1
993                if (bPointsRight != 0) {// figure opens to the right
994                    DrawEndpieceDeltasDouble(savepoints[1],
995                            iDeltaX.value[0], iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], deltapoints1);
996                    DrawEndpieceDeltasDouble(savepoints[0],
997                            iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], iDeltaX.value[0], deltapoints2);
998                } else {// figure opens to the left
999                    DrawEndpieceDeltasDouble(savepoints[1],
1000                            iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], iDeltaX.value[0], deltapoints1);
1001                    DrawEndpieceDeltasDouble(savepoints[0],
1002                            iDeltaX.value[0], iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], deltapoints2);
1003                }
1004            } else {// Point0 is lower than Point1
1005                if (bPointsRight != 0) {// figure opens to the right
1006                    DrawEndpieceDeltasDouble(savepoints[1],
1007                            iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], iDeltaX.value[0], deltapoints1);
1008                    DrawEndpieceDeltasDouble(savepoints[0],
1009                            iDeltaX.value[0], iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], deltapoints2);
1010                } else {// figure opens to the left
1011                    DrawEndpieceDeltasDouble(savepoints[1],
1012                            iDeltaX.value[0], iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], deltapoints1);
1013                    DrawEndpieceDeltasDouble(savepoints[0],
1014                            iDeltaY.value[0], -iDeltaX.value[0], -iDeltaY.value[0], iDeltaX.value[0], deltapoints2);
1015                }
1016            }
1017
1018            for (j = 0; j < 4; j++) {
1019                points[counter] = new POINT2(deltapoints1[j]);
1020                counter++;
1021            }
1022            for (j = 0; j < 4; j++) {
1023                points[counter] = new POINT2(deltapoints2[j]);
1024                counter++;
1025            }
1026        } catch (Exception exc) {
1027            ErrorLogger.LogException(_className ,"GetDISMCanalizeDouble",
1028                    new RendererException("Failed inside GetDISMCanalizeDouble", exc));
1029        }
1030        return counter;
1031    }
1032
1033    /**
1034     * Gets shape for Feint, decoy, or dummy indicator. Does not check if tactical graphic should have indicator
1035     * @param tg used to get line color and stroke
1036     * @param ptA bottom left point of triangle
1037     * @param ptC bottom right point of triangle
1038     * @return Dummy indicator shape
1039     */
1040    public static Shape2 getFDIShape(TGLight tg, POINT2 ptA, POINT2 ptC) {
1041        try {
1042            POINT2 midPt = lineutility.MidPointDouble(ptA, ptC, 0);
1043            double len = lineutility.CalcDistanceDouble(ptA, midPt);
1044            POINT2 ptB = lineutility.ExtendDirectedLine(ptA, ptC, midPt, lineutility.extend_above, len);
1045            Shape2 shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1046            shape.moveTo(ptA);
1047            shape.lineTo(ptB);
1048            shape.lineTo(ptC);
1049            shape.set_Style(1);
1050            shape.setLineColor(tg.get_LineColor());
1051
1052            BasicStroke stroke = clsUtility.getLineStroke(tg.get_LineThickness(), shape.get_Style(), BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER);
1053            shape.setStroke(stroke);
1054            return shape;
1055        } catch (Exception exc) {
1056            ErrorLogger.LogException(_className, "getFDIShape",
1057                    new RendererException("Failed inside getFDIShape", exc));
1058        }
1059        return null;
1060    }
1061
1062    /**
1063     * Gets shape for Feint, decoy, or dummy indicator for symbols with arrowhead. Does not check if tactical graphic should have indicator
1064     * Extends each point outside arrow as necessary
1065     * @param tg used to get line color and stroke
1066     * @param ptA bottom left point of arrow
1067     * @param ptB arrow point
1068     * @param ptC bottom right point of arrow
1069     * @return Dummy indicator shape
1070     */
1071    public static Shape2 getFDIShape(TGLight tg, POINT2 ptA, POINT2 ptB, POINT2 ptC) {
1072        try {
1073            // Extend ptA and ptC .25w
1074            double w = lineutility.CalcDistanceDouble(ptA, ptC) * 0.25;
1075            if (w < tg.get_LineThickness() * 1.5) {
1076                // lineThickness * 1.5 is minimum distance between arrow and dummy modifier
1077                w = tg.get_LineThickness() * 1.5;
1078            }
1079            ptC = lineutility.ExtendLineDouble(ptA, ptC, w);
1080            ptA = lineutility.ExtendLineDouble(ptC, ptA, w);
1081
1082            // Extend ptB .5w
1083            POINT2 midPt = lineutility.MidPointDouble(ptA, ptC, 0);
1084            w = lineutility.CalcDistanceDouble(midPt, ptB) * 0.5;
1085            if (w < tg.get_LineThickness() * 1.5) {
1086                // lineThickness * 1.5 is minimum distance between arrow and dummy modifier
1087                w = tg.get_LineThickness() * 1.5;
1088            }
1089            ptB = lineutility.ExtendLineDouble(midPt, ptB, w);
1090
1091            Shape2 shape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
1092            shape.moveTo(ptA);
1093            shape.lineTo(ptB);
1094            shape.lineTo(ptC);
1095            shape.set_Style(1);
1096            shape.setLineColor(tg.get_LineColor());
1097
1098            BasicStroke stroke = clsUtility.getLineStroke(tg.get_LineThickness(), shape.get_Style(), BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER);
1099            shape.setStroke(stroke);
1100            return shape;
1101        } catch (Exception exc) {
1102            ErrorLogger.LogException(_className, "getFDIShape",
1103                    new RendererException("Failed inside getFDIShape", exc));
1104        }
1105        return null;
1106    }
1107
1108    /**
1109     * Calculates the points for DISRUPT
1110     *
1111     * @param points OUT - the client points, also used for the returned points.
1112     * @param linetype the line type.
1113     */
1114    protected static int GetDISMDisruptDouble(POINT2[] points, int linetype) {
1115        int counter = 0;
1116        try {
1117            POINT2[] pts = new POINT2[2];
1118            POINT2[] ptsArrow = new POINT2[3];
1119            POINT2 ptCenter = new POINT2();
1120            int j = 0;
1121            POINT2[] savepoints = new POINT2[3];
1122            double dAngle1 = 0;
1123            POINT2[] deltapoints1 = new POINT2[4];
1124            POINT2[] deltapoints2 = new POINT2[4];
1125            POINT2[] deltapoints3 = new POINT2[4];
1126            double iDiagEOL_length = 0;
1127            double iDeltaX1 = 0;
1128            double iDeltaY1 = 0;
1129            double iDeltaX2 = 0;
1130            double iDeltaY2 = 0;
1131
1132            for (j = 0; j < 3; j++) {
1133                savepoints[j] = new POINT2(points[j]);
1134            }
1135
1136            lineutility.InitializePOINT2Array(pts);
1137            lineutility.InitializePOINT2Array(ptsArrow);
1138            lineutility.InitializePOINT2Array(deltapoints1);
1139            lineutility.InitializePOINT2Array(deltapoints2);
1140            lineutility.InitializePOINT2Array(deltapoints3);
1141
1142            //  DrawLine(destination, mask, color, points, 2, 2);
1143            points[counter] = new POINT2(savepoints[0]);
1144            points[counter].style = 0;
1145            counter++;
1146            points[counter] = new POINT2(savepoints[1]);
1147            points[counter].style = 5;
1148            counter++;
1149            //  pts[0] = points[1];
1150            //  pts[1] = points[2];
1151            //  DrawLine(destination, mask, color, pts, 2, 2);
1152            points[counter] = new POINT2(savepoints[1]);
1153            points[counter].style = 0;
1154            counter++;
1155            points[counter] = new POINT2(savepoints[2]);
1156            points[counter].style = 5;
1157            counter++;
1158
1159            ptCenter.x = (savepoints[0].x + savepoints[1].x) / 2;
1160            ptCenter.y = (savepoints[0].y + savepoints[1].y) / 2;
1161            ptsArrow[0] = new POINT2(savepoints[2]);
1162            ptsArrow[1].x = ptCenter.x + (savepoints[2].x - savepoints[1].x) * 4 / 5;
1163            ptsArrow[1].y = ptCenter.y + (savepoints[2].y - savepoints[1].y) * 4 / 5;
1164            ptsArrow[2].x = savepoints[0].x + (savepoints[2].x - savepoints[1].x) * 3 / 5;
1165            ptsArrow[2].y = savepoints[0].y + (savepoints[2].y - savepoints[1].y) * 3 / 5;
1166
1167            pts[0].x = ptCenter.x - (savepoints[2].x - savepoints[1].x) / 5;
1168            pts[0].y = ptCenter.y - (savepoints[2].y - savepoints[1].y) / 5;
1169            pts[1] = new POINT2(ptsArrow[1]);
1170            //  DrawLine(destination, mask, color, pts, 2, 2);
1171            points[counter] = new POINT2(pts[0]);
1172            points[counter].style = 0;
1173            counter++;
1174            points[counter] = new POINT2(pts[1]);
1175            points[counter].style = 5;
1176            counter++;
1177
1178            pts[0] = new POINT2(savepoints[0]);
1179            pts[1] = new POINT2(ptsArrow[2]);
1180            //  DrawLine(destination, mask, color, pts, 2, 2);
1181            points[counter] = new POINT2(pts[0]);
1182            points[counter].style = 0;
1183            counter++;
1184            points[counter] = new POINT2(pts[1]);
1185            points[counter].style = 5;
1186            counter++;
1187
1188            // the following code is very similar to CalcEndpieceDeltas
1189            iDiagEOL_length =  ((Math.sqrt // height of graphic
1190                    (
1191                    (savepoints[1].x - savepoints[0].x) * (savepoints[1].x - savepoints[0].x) +
1192                    (savepoints[1].y - savepoints[0].y) * (savepoints[1].y - savepoints[0].y)) +
1193                    Math.sqrt // length of graphic
1194                    (
1195                    (savepoints[2].x - savepoints[1].x) * (savepoints[2].x - savepoints[1].x) +
1196                    (savepoints[2].y - savepoints[1].y) * (savepoints[2].y - savepoints[1].y))) / 15);
1197
1198            //M. Deutch 8-18-04
1199            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
1200            if (iDiagEOL_length >  maxLength * DPIScaleFactor) {
1201                iDiagEOL_length =  maxLength * DPIScaleFactor;
1202            }
1203            if (iDiagEOL_length <  minLength * DPIScaleFactor) {//was minLength
1204                iDiagEOL_length =  minLength * DPIScaleFactor;   //was minLength
1205            }
1206
1207            // dAngle1 = angle used to calculate the end-piece deltas
1208            dAngle1 = Math.atan2(savepoints[1].y - savepoints[2].y, savepoints[1].x - savepoints[2].x);
1209            //  dAngle1 = atan2(savepoints[1].y - savepoints[2].y, savepoints[1].x - savepoints[2].x);
1210            iDeltaX1 =  (iDiagEOL_length * Math.cos(dAngle1 - CONST_PI / 6));
1211            iDeltaY1 =  (iDiagEOL_length * Math.sin(dAngle1 - CONST_PI / 6));
1212            iDeltaX2 =  (iDiagEOL_length * Math.cos(dAngle1 + CONST_PI / 6));
1213            iDeltaY2 =  (iDiagEOL_length * Math.sin(dAngle1 + CONST_PI / 6));
1214
1215            DrawEndpieceDeltasDouble(ptsArrow[0],
1216                    iDeltaX1, iDeltaY1, iDeltaX2, iDeltaY2, deltapoints1);
1217            DrawEndpieceDeltasDouble(ptsArrow[1],
1218                    iDeltaX1, iDeltaY1, iDeltaX2, iDeltaY2, deltapoints2);
1219            DrawEndpieceDeltasDouble(ptsArrow[2],
1220                    iDeltaX1, iDeltaY1, iDeltaX2, iDeltaY2, deltapoints3);
1221            for (j = 0; j < 4; j++) {
1222                points[counter] = new POINT2(deltapoints1[j]);
1223                counter++;
1224            }
1225            for (j = 0; j < 4; j++) {
1226                points[counter] = new POINT2(deltapoints2[j]);
1227                counter++;
1228            }
1229            for (j = 0; j < 4; j++) {
1230                points[counter] = new POINT2(deltapoints3[j]);
1231                counter++;
1232            }
1233        } catch (Exception exc) {
1234            ErrorLogger.LogException(_className ,"GetDISMDisruptDouble",
1235                    new RendererException("Failed inside GetDISMDisruptDouble", exc));
1236        }
1237        return counter;
1238    }
1239    /**
1240     * Calculates the points for CONTAIN
1241     *
1242     * @param points OUT - the client points, also used for the returned points.
1243     * @param linetype the line type.
1244     */
1245    protected static int GetDISMContainDouble(POINT2[] points, int linetype) {
1246        int counter = 0;
1247        try {
1248            POINT2[] pts = new POINT2[3];
1249            POINT2 ptCenter = new POINT2();
1250            POINT2 ptPerp = new POINT2(); // point used to draw perpendicular line
1251            double iPerpLength = 0;
1252            int j = 0;
1253            double dAngle1 = 0, d = 0;
1254            double dCosAngle1 = 0;
1255            double dSinAngle1 = 0;
1256            double iRadius = 0;
1257            double iDiagEOL_length = 0;
1258            double dAngle2 = 0;
1259            double dDeltaX1, dDeltaY1, dDeltaX2, dDeltaY2;
1260            POINT2[] savepoints = new POINT2[3];
1261            POINT2[] arcpoints = new POINT2[17];
1262
1263            for (j = 0; j < 3; j++) {
1264                savepoints[j] = new POINT2(points[j]);
1265            }
1266
1267            lineutility.InitializePOINT2Array(pts);
1268            lineutility.InitializePOINT2Array(arcpoints);
1269
1270            ptCenter.x = (savepoints[0].x + savepoints[1].x) / 2;
1271            ptCenter.y = (savepoints[0].y + savepoints[1].y) / 2;
1272
1273            //added section M. Deutch   8-10-06
1274            //reverse points 0 and 1 if necessary to ensure arc
1275            //has correct orientation
1276            ref<double[]> m = new ref();
1277            POINT2 ptRelative = lineutility.PointRelativeToLine(savepoints[0], savepoints[1], savepoints[2]);
1278
1279            lineutility.CalcTrueSlopeDouble2(savepoints[0], savepoints[1], m);
1280            if (m.value[0] != 0) {
1281                if (savepoints[0].y > savepoints[1].y) {
1282                    if (ptRelative.x > ptCenter.x) {
1283                        lineutility.Reverse2Points(savepoints[0], savepoints[1]);
1284                    }
1285                }
1286                if (savepoints[0].y < savepoints[1].y) {
1287                    if (ptRelative.x < ptCenter.x) {
1288                        lineutility.Reverse2Points(savepoints[0], savepoints[1]);
1289                    }
1290                }
1291            } else {
1292                if (savepoints[0].x < savepoints[1].x) {
1293                    if (ptRelative.y > ptCenter.y) {
1294                        lineutility.Reverse2Points(savepoints[0], savepoints[1]);
1295                    }
1296                }
1297                if (savepoints[0].x > savepoints[1].x) {
1298                    if (ptRelative.y < ptCenter.y) {
1299                        lineutility.Reverse2Points(savepoints[0], savepoints[1]);
1300                    }
1301                }
1302            }
1303            //end section
1304
1305            iPerpLength =  Math.sqrt((ptCenter.x - savepoints[2].x) * (ptCenter.x - savepoints[2].x) + (ptCenter.y - savepoints[2].y) * (ptCenter.y - savepoints[2].y));
1306            if (iPerpLength < 1) {
1307                iPerpLength = 1;
1308            }
1309
1310            dAngle1 = Math.atan2(savepoints[0].y - savepoints[1].y, savepoints[0].x - savepoints[1].x);
1311            dCosAngle1 = Math.cos(dAngle1 + CONST_PI / 2);
1312            dSinAngle1 = Math.sin(dAngle1 + CONST_PI / 2);
1313            
1314            ptPerp.x = ptCenter.x + dCosAngle1 * iPerpLength;
1315            ptPerp.y = ptCenter.y + dSinAngle1 * iPerpLength;
1316
1317            pts[0] = new POINT2(ptCenter);
1318
1319            pts[1] = new POINT2(savepoints[2]);
1320
1321            points[counter] = new POINT2(pts[0]);
1322            points[counter].style = 14;
1323            counter++;
1324            points[counter] = new POINT2(pts[1]);
1325            points[counter].style = 5;
1326            counter++;
1327
1328            // draw arrowhead
1329            iRadius =  Math.sqrt((ptCenter.x - savepoints[0].x) * (ptCenter.x - savepoints[0].x) + (ptCenter.y - savepoints[0].y) * (ptCenter.y - savepoints[0].y));
1330            iDiagEOL_length = (iPerpLength + iRadius) / 20;
1331
1332            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
1333            if (iDiagEOL_length >  maxLength * DPIScaleFactor) {
1334                iDiagEOL_length =  maxLength * DPIScaleFactor;
1335            }
1336            if (iDiagEOL_length <  minLength * DPIScaleFactor) {
1337                iDiagEOL_length =  minLength * DPIScaleFactor;
1338            }
1339
1340            dAngle2 = Math.atan2(ptPerp.y - ptCenter.y, ptPerp.x - ptCenter.x);
1341            dDeltaX1 = Math.cos(dAngle2 + CONST_PI / 4);
1342            dDeltaY1 = Math.sin(dAngle2 + CONST_PI / 4);
1343            dDeltaX2 = Math.cos(dAngle2 - CONST_PI / 4);
1344            dDeltaY2 = Math.sin(dAngle2 - CONST_PI / 4);
1345            pts[0].x = ptCenter.x + dDeltaX1 * iDiagEOL_length;
1346            pts[0].y = ptCenter.y + dDeltaY1 * iDiagEOL_length;
1347            pts[1] = new POINT2(ptCenter);
1348            pts[2].x = ptCenter.x + dDeltaX2 * iDiagEOL_length;
1349            pts[2].y = ptCenter.y + dDeltaY2 * iDiagEOL_length;
1350            //end section
1351            for (j = 0; j < 3; j++) {
1352                points[counter] = new POINT2(pts[j]);
1353                points[counter].style = 0;
1354                counter++;
1355            }
1356            points[counter - 1].style = 5;
1357
1358            // draw arc
1359            ArcApproximationDouble(ptCenter.x - iRadius, ptCenter.y - iRadius,
1360                    ptCenter.x + iRadius, ptCenter.y + iRadius,
1361                    savepoints[0].x, savepoints[0].y, savepoints[1].x, savepoints[1].y, arcpoints);
1362
1363            for (j = 0; j < 17; j++) {
1364                points[counter] = new POINT2(arcpoints[j]);
1365                points[counter].style = 0;
1366                counter++;
1367            }
1368            points[counter - 1].style = 5;
1369
1370            // draw spokes inside arc
1371            pts[0] = new POINT2(savepoints[0]);
1372            pts[1].x = (pts[0].x + ptCenter.x) / 2;
1373            pts[1].y = (pts[0].y + ptCenter.y) / 2;
1374            d = lineutility.CalcDistanceDouble(pts[0], pts[1]);
1375            if (d > maxLength * DPIScaleFactor) //shorten the spoke
1376            {
1377                pts[1] = lineutility.ExtendLineDouble(pts[1], pts[0], -maxLength * DPIScaleFactor);
1378            }
1379
1380            points[counter] = new POINT2(pts[0]);
1381            points[counter].style = 0;
1382            counter++;
1383            points[counter] = new POINT2(pts[1]);
1384            points[counter].style = 5;
1385            counter++;
1386
1387            pts[0] = new POINT2(savepoints[1]);
1388            pts[1].x = (pts[0].x + ptCenter.x) / 2;
1389            pts[1].y = (pts[0].y + ptCenter.y) / 2;
1390            d = lineutility.CalcDistanceDouble(pts[0], pts[1]);
1391            if (d > maxLength * DPIScaleFactor) //shorten the spoke
1392            {
1393                pts[1] = lineutility.ExtendLineDouble(pts[1], pts[0], -maxLength * DPIScaleFactor);
1394            }
1395            //  DrawLine(destination, mask, color, pts, 2, 2);
1396
1397            points[counter] = new POINT2(pts[0]);
1398            points[counter].style = 0;
1399            counter++;
1400            points[counter] = new POINT2(pts[1]);
1401            points[counter].style = 5;
1402            counter++;
1403
1404            pts[0].x = ptCenter.x - (ptPerp.x - ptCenter.x) * iRadius / iPerpLength;
1405            pts[0].y = ptCenter.y - (ptPerp.y - ptCenter.y) * iRadius / iPerpLength;
1406            pts[1].x = (ptCenter.x + pts[0].x) / 2;
1407            pts[1].y = (ptCenter.y + pts[0].y) / 2;
1408            d = lineutility.CalcDistanceDouble(pts[0], pts[1]);
1409            if (d > maxLength * DPIScaleFactor) //shorten the spoke
1410            {
1411                pts[1] = lineutility.ExtendLineDouble(pts[1], pts[0], -maxLength * DPIScaleFactor);
1412            }
1413
1414            points[counter] = new POINT2(pts[0]);
1415            points[counter].style = 0;
1416            counter++;
1417            points[counter] = new POINT2(pts[1]);
1418            points[counter].style = 5;
1419            counter++;
1420
1421            pts[0].x = ptCenter.x - dDeltaX1 * iRadius;
1422            pts[0].y = ptCenter.y - dDeltaY1 * iRadius;
1423            pts[1].x = (ptCenter.x + pts[0].x) / 2;
1424            pts[1].y = (ptCenter.y + pts[0].y) / 2;
1425            d = lineutility.CalcDistanceDouble(pts[0], pts[1]);
1426            if (d > maxLength * DPIScaleFactor) //shorten the spoke
1427            {
1428                pts[1] = lineutility.ExtendLineDouble(pts[1], pts[0], -maxLength * DPIScaleFactor);
1429            }
1430
1431            points[counter] = new POINT2(pts[0]);
1432            points[counter].style = 0;
1433            counter++;
1434            points[counter] = new POINT2(pts[1]);
1435            points[counter].style = 5;
1436            counter++;
1437
1438            pts[0].x = ptCenter.x - dDeltaX2 * iRadius;
1439            pts[0].y = ptCenter.y - dDeltaY2 * iRadius;
1440            pts[1].x = (ptCenter.x + pts[0].x) / 2;
1441            pts[1].y = (ptCenter.y + pts[0].y) / 2;
1442            d = lineutility.CalcDistanceDouble(pts[0], pts[1]);
1443            if (d > maxLength * DPIScaleFactor) //shorten the spoke
1444            {
1445                pts[1] = lineutility.ExtendLineDouble(pts[1], pts[0], -maxLength * DPIScaleFactor);
1446            }
1447
1448            points[counter] = new POINT2(pts[0]);
1449            points[counter].style = 0;
1450            counter++;
1451            points[counter] = new POINT2(pts[1]);
1452            points[counter].style = 5;
1453            counter++;
1454
1455            dDeltaX1 = Math.cos(dAngle2 + CONST_PI / 8);
1456            dDeltaY1 = Math.sin(dAngle2 + CONST_PI / 8);
1457            dDeltaX2 = Math.cos(dAngle2 - CONST_PI / 8);
1458            dDeltaY2 = Math.sin(dAngle2 - CONST_PI / 8);
1459            pts[0].x = ptCenter.x - dDeltaX1 * iRadius;
1460            pts[0].y = ptCenter.y - dDeltaY1 * iRadius;
1461            pts[1].x = (ptCenter.x + pts[0].x) / 2;
1462            pts[1].y = (ptCenter.y + pts[0].y) / 2;
1463            d = lineutility.CalcDistanceDouble(pts[0], pts[1]);
1464            if (d > maxLength * DPIScaleFactor) //shorten the spoke
1465            {
1466                pts[1] = lineutility.ExtendLineDouble(pts[1], pts[0], -maxLength * DPIScaleFactor);
1467            }
1468
1469            points[counter] = new POINT2(pts[0]);
1470            points[counter].style = 0;
1471            counter++;
1472            points[counter] = new POINT2(pts[1]);
1473            points[counter].style = 5;
1474            counter++;
1475
1476            pts[0].x = ptCenter.x - dDeltaX2 * iRadius;
1477            pts[0].y = ptCenter.y - dDeltaY2 * iRadius;
1478            pts[1].x = (ptCenter.x + pts[0].x) / 2;
1479            pts[1].y = (ptCenter.y + pts[0].y) / 2;
1480            d = lineutility.CalcDistanceDouble(pts[0], pts[1]);
1481            if (d > maxLength * DPIScaleFactor) //shorten the spoke
1482            {
1483                pts[1] = lineutility.ExtendLineDouble(pts[1], pts[0], -maxLength * DPIScaleFactor);
1484            }
1485
1486            points[counter] = new POINT2(pts[0]);
1487            points[counter].style = 0;
1488            counter++;
1489            points[counter] = new POINT2(pts[1]);
1490            points[counter].style = 5;
1491            counter++;
1492
1493            dDeltaX1 = Math.cos(dAngle2 + 3 * CONST_PI / 8);
1494            dDeltaY1 = Math.sin(dAngle2 + 3 * CONST_PI / 8);
1495            dDeltaX2 = Math.cos(dAngle2 - 3 * CONST_PI / 8);
1496            dDeltaY2 = Math.sin(dAngle2 - 3 * CONST_PI / 8);
1497            pts[0].x = ptCenter.x - dDeltaX1 * iRadius;
1498            pts[0].y = ptCenter.y - dDeltaY1 * iRadius;
1499            pts[1].x = (ptCenter.x + pts[0].x) / 2;
1500            pts[1].y = (ptCenter.y + pts[0].y) / 2;
1501            d = lineutility.CalcDistanceDouble(pts[0], pts[1]);
1502            if (d > maxLength * DPIScaleFactor) //shorten the spoke
1503            {
1504                pts[1] = lineutility.ExtendLineDouble(pts[1], pts[0], -maxLength * DPIScaleFactor);
1505            }
1506
1507            points[counter] = new POINT2(pts[0]);
1508            points[counter].style = 0;
1509            counter++;
1510            points[counter] = new POINT2(pts[1]);
1511            points[counter].style = 5;
1512            counter++;
1513
1514            pts[0].x = ptCenter.x - dDeltaX2 * iRadius;
1515            pts[0].y = ptCenter.y - dDeltaY2 * iRadius;
1516            pts[1].x = (ptCenter.x + pts[0].x) / 2;
1517            pts[1].y = (ptCenter.y + pts[0].y) / 2;
1518            d = lineutility.CalcDistanceDouble(pts[0], pts[1]);
1519            if (d > maxLength * DPIScaleFactor) //shorten the spoke
1520            {
1521                pts[1] = lineutility.ExtendLineDouble(pts[1], pts[0], -maxLength * DPIScaleFactor);
1522            }
1523
1524            points[counter] = new POINT2(pts[0]);
1525            points[counter].style = 0;
1526            counter++;
1527            points[counter] = new POINT2(pts[1]);
1528            points[counter].style = 5;
1529            counter++;
1530
1531        } catch (Exception exc) {
1532            ErrorLogger.LogException(_className ,"GetDISMContainDouble",
1533                    new RendererException("Failed inside GetDISMContainDouble", exc));
1534        }
1535        return counter;
1536    }
1537    /**
1538     * Calculates the points for FIX, MNFLDFIX
1539     *
1540     * @param points OUT - the client points, also used for the returned points.
1541     * @param linetype the line type.
1542     */
1543    protected static int GetDISMFixDouble(POINT2[] points, int linetype,Rectangle2D clipBounds) {
1544        int counter = 0;
1545        try {
1546            POINT2[] pts = new POINT2[3];
1547            POINT2[] savepoints = new POINT2[2];
1548            double dAngle1 = 0;
1549            double dLength = 0;
1550            double dJaggyHalfAmp = 0;
1551            double dJaggyHalfPeriod = 0;
1552            double dDeltaXOut = 0;
1553            double dDeltaYOut = 0;
1554            double dDeltaXAlong = 0;
1555            double dDeltaYAlong = 0;
1556            int iNumJaggies = 0;
1557            int i = 0, j = 0;
1558
1559            for (j = 0; j < 2; j++) {
1560                savepoints[j] = new POINT2(points[j]);
1561            }
1562
1563            Boolean drawJaggies=true;
1564            if(clipBounds != null)
1565            {
1566                POINT2 ul=new POINT2(clipBounds.getMinX(),clipBounds.getMinY());
1567                POINT2 lr=new POINT2(clipBounds.getMaxX(),clipBounds.getMaxY());
1568                savepoints=lineutility.BoundOneSegment(savepoints[0], savepoints[1], ul, lr);
1569            }
1570            if(savepoints==null)
1571            {
1572                savepoints=new POINT2[2];
1573                for (j = 0; j < 2; j++) {
1574                    savepoints[j] = new POINT2(points[j]);
1575                }
1576                drawJaggies=false;
1577            }
1578
1579            lineutility.InitializePOINT2Array(pts);
1580            //reverse the points
1581
1582            dAngle1 = Math.atan2(savepoints[0].y - savepoints[1].y, savepoints[0].x - savepoints[1].x);
1583            dLength = Math.sqrt((savepoints[1].x - savepoints[0].x) * (savepoints[1].x - savepoints[0].x) +
1584                    (savepoints[1].y - savepoints[0].y) * (savepoints[1].y - savepoints[0].y));
1585            //arraysupport tries to set jaggylength before the points get bounded
1586            dJaggyHalfAmp = dLength / 15; // half the amplitude of the "jaggy function"
1587
1588            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
1589            if (dJaggyHalfAmp > maxLength * DPIScaleFactor) {
1590                dJaggyHalfAmp = maxLength * DPIScaleFactor;
1591            }
1592            if (dJaggyHalfAmp < minLength * DPIScaleFactor) {
1593                dJaggyHalfAmp = minLength * DPIScaleFactor;
1594            }
1595
1596            dJaggyHalfPeriod = dJaggyHalfAmp / 1.5; // half the period of the "jaggy function"
1597            dDeltaXOut = Math.cos(dAngle1 + CONST_PI / 2) * dJaggyHalfAmp; // X-delta out from the center line
1598            dDeltaYOut = Math.sin(dAngle1 + CONST_PI / 2) * dJaggyHalfAmp; // Y-delta out from the center line
1599            dDeltaXAlong = Math.cos(dAngle1) * dJaggyHalfPeriod; // X-delta along the center line
1600            dDeltaYAlong = Math.sin(dAngle1) * dJaggyHalfPeriod; // Y-delta along the center line
1601            iNumJaggies = (int) (dLength / dJaggyHalfPeriod) - 3;
1602            i = 2;
1603            pts[0] = new POINT2(savepoints[1]);
1604            pts[1].x = savepoints[1].x + dDeltaXAlong * 1.5;
1605            pts[1].y = savepoints[1].y + dDeltaYAlong * 1.5;
1606            //DrawLine(destination, mask, color, pts, 2, 2);
1607            points[counter] = new POINT2(pts[0]);
1608            points[counter].style = 0;
1609            counter++;
1610            points[counter] = new POINT2(pts[1]);
1611            points[counter].style = 5;
1612            counter++;
1613
1614            pts[0].x = savepoints[1].x + dDeltaXOut + dDeltaXAlong * i;
1615            pts[0].y = savepoints[1].y + dDeltaYOut + dDeltaYAlong * i;
1616            i++;
1617            points[counter] = new POINT2(pts[0]);
1618            points[counter].style = 0;
1619            counter++;
1620            points[counter] = new POINT2(pts[1]);
1621            points[counter].style = 5;
1622            counter++;
1623
1624            if(drawJaggies) {
1625                while (i <= iNumJaggies) {
1626                    pts[1].x = savepoints[1].x - dDeltaXOut + dDeltaXAlong * i;
1627                    pts[1].y = savepoints[1].y - dDeltaYOut + dDeltaYAlong * i;
1628                    i++;
1629                    pts[2].x = savepoints[1].x + dDeltaXOut + dDeltaXAlong * i;
1630                    pts[2].y = savepoints[1].y + dDeltaYOut + dDeltaYAlong * i;
1631                    i++;
1632                    for (j = 0; j < 3; j++) {
1633                        points[counter] = new POINT2(pts[j]);
1634                        points[counter].style = 0;
1635                        counter++;
1636                    }
1637                    points[counter - 1].style = 5;
1638                    pts[0] = new POINT2(pts[2]);
1639                }
1640            }
1641
1642            pts[1] = new POINT2(pts[0]);
1643            pts[0].x = savepoints[1].x + dDeltaXAlong * i;
1644            pts[0].y = savepoints[1].y + dDeltaYAlong * i;
1645            points[counter] = new POINT2(pts[0]);
1646            points[counter].style = 0;
1647            counter++;
1648            points[counter] = new POINT2(pts[1]);
1649            points[counter].style = 5;
1650            counter++;
1651
1652            pts[1] = new POINT2(savepoints[0]);
1653            //DrawLine(destination, mask, color, pts, 2, 2);
1654            points[counter] = new POINT2(pts[0]);
1655            points[counter].style = 0;
1656            counter++;
1657            points[counter] = new POINT2(pts[1]);
1658            points[counter].style = 5;
1659            counter++;
1660
1661            // draw arrowhead
1662            pts[0].x = savepoints[0].x + dDeltaXOut / 1.5 - dDeltaXAlong;
1663            pts[0].y = savepoints[0].y + dDeltaYOut / 1.5 - dDeltaYAlong;
1664            pts[2].x = savepoints[0].x - dDeltaXOut / 1.5 - dDeltaXAlong;
1665            pts[2].y = savepoints[0].y - dDeltaYOut / 1.5 - dDeltaYAlong;
1666            for (j = 0; j < 3; j++) {
1667                points[counter] = new POINT2(pts[j]);
1668                if (linetype == (long) TacticalLines.MNFLDFIX) {
1669                    points[counter].style = 9;
1670                } else {
1671                    points[counter].style = 0;
1672                }
1673                counter++;
1674            }
1675            if (linetype == (long) TacticalLines.MNFLDFIX) {
1676                points[counter - 1].style = 10;
1677            } else {
1678                points[counter - 1].style = 5;
1679            }
1680
1681        } catch (Exception exc) {
1682            ErrorLogger.LogException(_className ,"GetDISMFixDouble",
1683                    new RendererException("Failed inside GetDISMFixDouble", exc));
1684        }
1685        return counter;
1686    }
1687    /**
1688     * Calculates the points for CLEAR.
1689     *
1690     * @param points OUT - the client points, also used for the returned points.
1691     * @param linetype the line type.
1692     */
1693    protected static int GetDISMClearDouble(POINT2[] points, int linetype) {
1694        int counter = 0;
1695        try {
1696            POINT2[] savepoints = new POINT2[3];
1697            int j = 0;
1698            POINT2[] pts = new POINT2[2];
1699            POINT2[] ptsArrow = new POINT2[3];
1700            double ctrX =  ((points[0].x + points[1].x) / 2);
1701            double ctrY =  ((points[0].y + points[1].y) / 2);
1702            ref<double[]> iDeltaX1 = new ref(), iDeltaY1 = new ref(), iDeltaX2 = new ref(), iDeltaY2 = new ref();
1703            POINT2[] deltapoints1 = new POINT2[4];
1704            POINT2[] deltapoints2 = new POINT2[4];
1705            POINT2[] deltapoints3 = new POINT2[4];
1706
1707            for (j = 0; j < 3; j++) {
1708                savepoints[j] = new POINT2(points[j]);
1709            }
1710
1711            lineutility.InitializePOINT2Array(pts);
1712            lineutility.InitializePOINT2Array(ptsArrow);
1713            lineutility.InitializePOINT2Array(deltapoints1);
1714            lineutility.InitializePOINT2Array(deltapoints2);
1715            lineutility.InitializePOINT2Array(deltapoints3);
1716
1717            //DrawLine(destination, mask, color, points, 2, 2);
1718            points[counter] = new POINT2(savepoints[0]);
1719            points[counter].style = 0;
1720            counter++;
1721            points[counter] = new POINT2(savepoints[1]);
1722            points[counter].style = 5;
1723            counter++;
1724
1725            pts[0].x = ctrX;
1726            pts[0].y = ctrY;
1727            pts[1] = new POINT2(savepoints[2]);
1728            ptsArrow[0] = new POINT2(pts[0]);
1729            //DrawLine(destination, mask, color, pts, 2, 2);
1730            points[counter] = new POINT2(pts[0]);
1731            points[counter].style = 0;
1732            counter++;
1733            points[counter] = new POINT2(pts[1]);
1734            points[counter].style = 5;
1735            counter++;
1736
1737            pts[0].x = (savepoints[0].x + ctrX) / 2;
1738            pts[0].y = (savepoints[0].y + ctrY) / 2;
1739            pts[1].x = savepoints[2].x + savepoints[0].x - pts[0].x;
1740            pts[1].y = savepoints[2].y + savepoints[0].y - pts[0].y;
1741            ptsArrow[1] = new POINT2(pts[0]);
1742            //DrawLine(destination, mask, color, pts, 2, 2);
1743            points[counter] = new POINT2(pts[0]);
1744            points[counter].style = 0;
1745            counter++;
1746            points[counter] = new POINT2(pts[1]);
1747            points[counter].style = 5;
1748            counter++;
1749
1750            pts[0].x = (savepoints[1].x + ctrX) / 2;
1751            pts[0].y = (savepoints[1].y + ctrY) / 2;
1752            pts[1].x = savepoints[2].x + savepoints[1].x - pts[0].x;
1753            pts[1].y = savepoints[2].y + savepoints[1].y - pts[0].y;
1754            ptsArrow[2] = new POINT2(pts[0]);
1755            points[counter] = new POINT2(pts[0]);
1756            points[counter].style = 0;
1757            counter++;
1758            points[counter] = new POINT2(pts[1]);
1759            points[counter].style = 5;
1760            counter++;
1761
1762            CalcEndpieceDeltasDouble(savepoints, iDeltaX1, iDeltaY1, CONST_PI / 6);
1763            CalcEndpieceDeltasDouble(savepoints, iDeltaX2, iDeltaY2, -CONST_PI / 6);
1764            DrawEndpieceDeltasDouble(ptsArrow[0],
1765                    iDeltaX1.value[0], iDeltaY1.value[0], iDeltaX2.value[0], iDeltaY2.value[0], deltapoints1);
1766            DrawEndpieceDeltasDouble(ptsArrow[1],
1767                    iDeltaX1.value[0], iDeltaY1.value[0], iDeltaX2.value[0], iDeltaY2.value[0], deltapoints2);
1768            DrawEndpieceDeltasDouble(ptsArrow[2],
1769                    iDeltaX1.value[0], iDeltaY1.value[0], iDeltaX2.value[0], iDeltaY2.value[0], deltapoints3);
1770            for (j = 0; j < 4; j++) {
1771                points[counter] = new POINT2(deltapoints1[j]);
1772                counter++;
1773            }
1774            for (j = 0; j < 4; j++) {
1775                points[counter] = new POINT2(deltapoints2[j]);
1776                counter++;
1777            }
1778            for (j = 0; j < 4; j++) {
1779                points[counter] = new POINT2(deltapoints3[j]);
1780                counter++;
1781            }
1782        } catch (Exception exc) {
1783            ErrorLogger.LogException(_className ,"GetDISMClearDouble",
1784                    new RendererException("Failed inside GetDISMClearDouble", exc));
1785        }
1786        return counter;
1787    }
1788    private static boolean IsSeizeArcReversed(POINT2[] pPoints){
1789        try {
1790            double dAngle1 = Math.atan2(pPoints[0].y - pPoints[1].y, pPoints[0].x - pPoints[1].x);
1791            double dDeltaX1 = Math.cos(dAngle1 + CONST_PI / 4);
1792            double dDeltaY1 = Math.sin(dAngle1 + CONST_PI / 4);
1793            double dDeltaX2 = Math.cos(dAngle1 - CONST_PI / 4);
1794            double dDeltaY2 = Math.sin(dAngle1 - CONST_PI / 4);
1795
1796            double dChordLength = Math.sqrt((pPoints[1].x - pPoints[0].x) * (pPoints[1].x - pPoints[0].x) +
1797                    (pPoints[1].y - pPoints[0].y) * (pPoints[1].y - pPoints[0].y));
1798            double dArcRadius = dChordLength / 1.414213562373; // sqrt(2) == 1.414213562373
1799            POINT2 ptArcCenter = new POINT2();
1800
1801            //get the default center
1802            ptArcCenter.x = pPoints[0].x - dDeltaX1 * dArcRadius;
1803            ptArcCenter.y = pPoints[0].y - dDeltaY1 * dArcRadius;
1804            double d = lineutility.CalcDistanceDouble(ptArcCenter, pPoints[2]);
1805
1806            //get the alternate center if the arc is reversed
1807            POINT2 ptArcCenterReversed = new POINT2();
1808            ptArcCenterReversed.x = pPoints[0].x - dDeltaX2 * dArcRadius;
1809            ptArcCenterReversed.y = pPoints[0].y - dDeltaY2 * dArcRadius;
1810            double dReversed = lineutility.CalcDistanceDouble(ptArcCenterReversed, pPoints[2]);
1811
1812            if (dReversed > d) {
1813                return true;
1814            } else {
1815                return false;
1816            }
1817        } catch (Exception exc) {
1818            ErrorLogger.LogException(_className ,"IsSeizeArcReversed",
1819                    new RendererException("Failed inside IsSeizeArcReversed", exc));
1820        }
1821        return false;
1822    }
1823    /**
1824     * Calculates the points for SEIZE
1825     *
1826     * @param points OUT - the client points, also used for the returned points.
1827     * @param linetype the line type.
1828     */
1829    protected static int GetDISMSeizeDouble(POINT2[] points,
1830            int linetype,
1831            double radius) 
1832    {
1833        int counter = 0;
1834        try {
1835            POINT2 ptArcCenter = new POINT2();
1836            POINT2 ptArcStart = new POINT2();
1837            POINT2[] savepoints = new POINT2[3];
1838            float scale = (float) 0.9;
1839            double iCircleRadius =  (25 * scale);
1840            POINT2[] arcpoints = new POINT2[17];
1841            POINT2[] pts = new POINT2[3];
1842            double dAngle1 = 0;
1843            double dDeltaX1 = 0;
1844            double dDeltaY1 = 0;
1845            double dDeltaX2 = 0;
1846            double dDeltaY2 = 0;
1847            double dChordLength = 0;
1848            double dArcRadius = 0;
1849            int j = 0;
1850            double dDeltaX3 = 0;
1851            double dDeltaY3 = 0;
1852            double iDiagEOL_length = 0;
1853            double factor = 1;
1854
1855            if(radius>0)
1856                iCircleRadius=radius;
1857            
1858            
1859            for (j = 0; j < 3; j++) {
1860                savepoints[j] = new POINT2(points[j]);
1861            }
1862            
1863            //if radius is 0 then it is rev B
1864            String client=CELineArray.getClient();
1865            if(!client.startsWith("cpof") && radius==0)
1866            {
1867                dArcRadius=lineutility.CalcDistanceDouble(savepoints[0], savepoints[1]);
1868                if(iCircleRadius>dArcRadius/2)
1869                    iCircleRadius=dArcRadius/2;
1870            }
1871
1872            lineutility.InitializePOINT2Array(pts);
1873            lineutility.InitializePOINT2Array(arcpoints);
1874            // draw circle
1875            ArcApproximationDouble(savepoints[0].x - iCircleRadius, savepoints[0].y - iCircleRadius,
1876                    savepoints[0].x + iCircleRadius, savepoints[0].y + iCircleRadius,
1877                    savepoints[0].x, savepoints[0].y, savepoints[0].x, savepoints[0].y, arcpoints);
1878            for (j = 0; j < 17; j++) {
1879                points[counter] = new POINT2(arcpoints[j]);
1880                points[counter].style = 0;
1881                counter++;
1882            }
1883            points[counter - 1].style = 5;
1884
1885            // draw arc
1886            dAngle1 = Math.atan2(savepoints[0].y - savepoints[1].y, savepoints[0].x - savepoints[1].x);
1887            dDeltaX1 = Math.cos(dAngle1 + CONST_PI / 4);
1888            dDeltaY1 = Math.sin(dAngle1 + CONST_PI / 4);
1889            dDeltaX2 = Math.cos(dAngle1 - CONST_PI / 4);
1890            dDeltaY2 = Math.sin(dAngle1 - CONST_PI / 4);
1891
1892            boolean isArcReversed = IsSeizeArcReversed(savepoints);
1893
1894            if (isArcReversed == false) {
1895                ptArcStart.x = savepoints[0].x - dDeltaX2 * iCircleRadius;
1896                ptArcStart.y = savepoints[0].y - dDeltaY2 * iCircleRadius;
1897                dChordLength = Math.sqrt((savepoints[1].x - savepoints[0].x) * (savepoints[1].x - savepoints[0].x) +
1898                        (savepoints[1].y - savepoints[0].y) * (savepoints[1].y - savepoints[0].y));
1899                dArcRadius = dChordLength / 1.414213562373; // sqrt(2) == 1.414213562373
1900                ptArcCenter.x = savepoints[0].x - dDeltaX1 * dArcRadius;
1901                ptArcCenter.y = savepoints[0].y - dDeltaY1 * dArcRadius;
1902
1903                ArcApproximationDouble((ptArcCenter.x - dArcRadius), (ptArcCenter.y - dArcRadius),
1904                        (ptArcCenter.x + dArcRadius), (ptArcCenter.y + dArcRadius),
1905                        savepoints[1].x, savepoints[1].y, ptArcStart.x, ptArcStart.y, arcpoints);
1906            } else //arc is reversed
1907            {
1908                ptArcStart.x = savepoints[0].x - dDeltaX1 * iCircleRadius;
1909                ptArcStart.y = savepoints[0].y - dDeltaY1 * iCircleRadius;
1910                dChordLength = Math.sqrt((savepoints[1].x - savepoints[0].x) * (savepoints[1].x - savepoints[0].x) +
1911                        (savepoints[1].y - savepoints[0].y) * (savepoints[1].y - savepoints[0].y));
1912                dArcRadius = dChordLength / 1.414213562373; // sqrt(2) == 1.414213562373
1913                ptArcCenter.x = savepoints[0].x - dDeltaX2 * dArcRadius;
1914                ptArcCenter.y = savepoints[0].y - dDeltaY2 * dArcRadius;
1915                ArcApproximationDouble((ptArcCenter.x - dArcRadius), (ptArcCenter.y - dArcRadius),
1916                        (ptArcCenter.x + dArcRadius), (ptArcCenter.y + dArcRadius),
1917                        ptArcStart.x, ptArcStart.y, savepoints[1].x, savepoints[1].y, arcpoints);
1918            }
1919
1920            for (j = 0; j < 17; j++) {
1921                points[counter] = new POINT2(arcpoints[j]);
1922                points[counter].style = 0;
1923                counter++;
1924            }
1925            points[counter - 1].style = 5;
1926
1927            // draw arrow
1928            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
1929            if (dChordLength / 8 > maxLength * DPIScaleFactor) {
1930                factor = dChordLength / (8 * maxLength * DPIScaleFactor);
1931            }
1932            if (factor == 0) {
1933                factor = 1;
1934            }
1935
1936
1937            if (isArcReversed == false) {
1938                pts[0].x = savepoints[1].x - (savepoints[1].x - savepoints[0].x) / (8 * factor);
1939                pts[0].y = savepoints[1].y - (savepoints[1].y - savepoints[0].y) / (8 * factor);
1940                pts[1] = new POINT2(savepoints[1]);
1941                dDeltaX3 = Math.cos(dAngle1 + CONST_PI / 2);
1942                dDeltaY3 = Math.sin(dAngle1 + CONST_PI / 2);
1943                iDiagEOL_length =  (dChordLength / 8);
1944                pts[2].x = savepoints[1].x + dDeltaX3 * iDiagEOL_length / factor;
1945                pts[2].y = savepoints[1].y + dDeltaY3 * iDiagEOL_length / factor;
1946            } //DrawLine(destination, mask, color, pts, 3, 2);
1947            //diagnostic arc reversed
1948            else {
1949                pts[0].x = savepoints[1].x - (savepoints[1].x - savepoints[0].x) / (8 * factor);
1950                pts[0].y = savepoints[1].y - (savepoints[1].y - savepoints[0].y) / (8 * factor);
1951                pts[1] = new POINT2(savepoints[1]);
1952                dDeltaX3 = Math.cos(dAngle1 - CONST_PI / 2);
1953                dDeltaY3 = Math.sin(dAngle1 - CONST_PI / 2);
1954                iDiagEOL_length =  (dChordLength / 8);
1955                pts[2].x = savepoints[1].x + dDeltaX3 * iDiagEOL_length / factor;
1956                pts[2].y = savepoints[1].y + dDeltaY3 * iDiagEOL_length / factor;
1957            }
1958            //end diagnostic
1959
1960
1961            //diagnostic
1962            //end diagnostic
1963
1964            for (j = 0; j < 3; j++) {
1965                points[counter] = new POINT2(pts[j]);
1966                points[counter].style = 0;
1967                counter++;
1968            }
1969            points[counter - 1].style = 5;
1970        } catch (Exception exc) {
1971            ErrorLogger.LogException(_className ,"GetDISMSeizeDouble",
1972                    new RendererException("Failed inside GetDISMSeizeDouble", exc));
1973        }
1974        return counter;
1975    }
1976    /**
1977     * Used twice for RIP to determine if the points are clockwise.
1978     * @param x1
1979     * @param y1
1980     * @param x2
1981     * @param y2
1982     * @param px
1983     * @param py
1984     * @return RIGHT_SIDE if 3 points are clockwise
1985     */
1986    private static int side(double x1, double y1, double x2, double y2, double px, double py) {
1987        double dx1, dx2, dy1, dy2;
1988        try {
1989            double o;
1990
1991            dx1 = x2 - x1;
1992            dy1 = y2 - y1;
1993            dx2 = px - x1;
1994            dy2 = py - y1;
1995            o = (dx1 * dy2) - (dy1 * dx2);
1996            if (o > 0.0) {
1997                return (LEFT_SIDE);
1998            }
1999            if (o < 0.0) {
2000                return (RIGHT_SIDE);
2001            }
2002        } catch (Exception exc) {
2003            ErrorLogger.LogException(_className, "side",
2004                    new RendererException("Failed inside side", exc));
2005        }
2006        return (COLINEAR);
2007    }
2008
2009    /**
2010     * Calculates the points for RIP
2011     *
2012     * @param points OUT - the client points, also used for the returned points.
2013     * @param linetype the line type
2014     */
2015    protected static int GetDISMRIPDouble(POINT2[] points, int linetype) {
2016        int counter = 0;
2017        try {
2018            // draw the straight lines
2019            POINT2[] pts = new POINT2[2];
2020            POINT2[] savepoints = new POINT2[4];
2021            int j = 0;
2022            double iLengthPt0Pt1 = 0;
2023            double iDiagEOL_length = 0;
2024            double dAngle1 = 0;
2025            double iDeltaX1 = 0;
2026            double iDeltaY1 = 0;
2027            double iDeltaX2 = 0;
2028            double iDeltaY2 = 0;
2029            double iLengthPt2Pt3 = 0;
2030            double iRadius = 0;
2031            POINT2[] deltapoints = new POINT2[4];
2032            POINT2[] arcpoints = new POINT2[17];
2033            POINT2 ptArcCenter = new POINT2();
2034
2035            boolean clockwise=false;
2036            int side01=side(points[0].x,points[0].y,points[1].x,points[1].y,points[2].x,points[2].y);
2037            int side12=side(points[1].x,points[1].y,points[2].x,points[2].y,points[3].x,points[3].y);
2038            if(side01==RIGHT_SIDE && side12==RIGHT_SIDE)
2039                clockwise=true;
2040            else if(side01==RIGHT_SIDE && side12==COLINEAR)
2041                clockwise=true;
2042            else if(side01==COLINEAR && side12==RIGHT_SIDE)
2043                clockwise=true;
2044
2045            for (j = 0; j < 4; j++) {
2046                savepoints[j] = new POINT2(points[j]);
2047            }
2048
2049            lineutility.InitializePOINT2Array(pts);
2050            lineutility.InitializePOINT2Array(deltapoints);
2051            lineutility.InitializePOINT2Array(arcpoints);
2052
2053            points[counter] = new POINT2(savepoints[0]);
2054            points[counter].style = 0;
2055            counter++;
2056            points[counter] = new POINT2(savepoints[1]);
2057            points[counter].style = 5;
2058            counter++;
2059
2060            pts[0] = new POINT2(savepoints[2]);
2061            pts[1] = new POINT2(savepoints[3]);
2062            points[counter] = new POINT2(pts[0]);
2063            points[counter].style = 0;
2064            counter++;
2065            points[counter] = new POINT2(pts[1]);
2066            points[counter].style = 5;
2067            counter++;
2068
2069            // draw the arrowhead on line between savepoints 0 and 1
2070            pts[0] = new POINT2(savepoints[0]);
2071            pts[1] = new POINT2(savepoints[1]);
2072            iLengthPt0Pt1 =  Math.sqrt((pts[1].x - pts[0].x) * (pts[1].x - pts[0].x) +
2073                    (pts[1].y - pts[0].y) * (pts[1].y - pts[0].y));
2074            iDiagEOL_length = iLengthPt0Pt1 / 8;
2075
2076            //M. Deutch 8-19-04
2077            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
2078            if (iDiagEOL_length >  maxLength * DPIScaleFactor) {
2079                iDiagEOL_length =  maxLength * DPIScaleFactor;
2080            }
2081            if (iDiagEOL_length <  minLength * DPIScaleFactor) {
2082                iDiagEOL_length =  minLength * DPIScaleFactor;
2083            }
2084
2085            dAngle1 = Math.atan2(pts[1].y - pts[0].y, pts[1].x - pts[0].x);
2086            iDeltaX1 =  (iDiagEOL_length * Math.cos(dAngle1 - CONST_PI / 4));
2087            iDeltaY1 =  (iDiagEOL_length * Math.sin(dAngle1 - CONST_PI / 4));
2088            iDeltaX2 =  (iDiagEOL_length * Math.cos(dAngle1 + CONST_PI / 4));
2089            iDeltaY2 =  (iDiagEOL_length * Math.sin(dAngle1 + CONST_PI / 4));
2090            DrawEndpieceDeltasDouble(pts[0],
2091                    iDeltaX1, iDeltaY1, iDeltaX2, iDeltaY2, deltapoints);
2092            for (j = 0; j < 4; j++) {
2093                points[counter] = new POINT2(deltapoints[j]);
2094                points[counter].style = 0;
2095                counter++;
2096            }
2097            points[counter - 3].style = 5;
2098            points[counter - 1].style = 5;
2099            // draw the arrowhead on line between savepoints 2 and 3
2100            pts[0] = new POINT2(savepoints[2]);
2101            pts[1] = new POINT2(savepoints[3]);
2102            iLengthPt2Pt3 =  Math.sqrt((pts[1].x - pts[0].x) * (pts[1].x - pts[0].x) +
2103                    (pts[1].y - pts[0].y) * (pts[1].y - pts[0].y));
2104            iDiagEOL_length = iLengthPt2Pt3 / 8;
2105
2106            //M. Deutch 8-19-04
2107            if (iDiagEOL_length >  maxLength * DPIScaleFactor) {
2108                iDiagEOL_length =  maxLength * DPIScaleFactor;
2109            }
2110            if (iDiagEOL_length <  minLength * DPIScaleFactor) {
2111                iDiagEOL_length =  minLength * DPIScaleFactor;
2112            }
2113
2114            dAngle1 = Math.atan2(pts[1].y - pts[0].y, pts[1].x - pts[0].x);
2115            iDeltaX1 =  (iDiagEOL_length * Math.cos(dAngle1 - CONST_PI / 4));
2116            iDeltaY1 =  (iDiagEOL_length * Math.sin(dAngle1 - CONST_PI / 4));
2117            iDeltaX2 =  (iDiagEOL_length * Math.cos(dAngle1 + CONST_PI / 4));
2118            iDeltaY2 =  (iDiagEOL_length * Math.sin(dAngle1 + CONST_PI / 4));
2119            DrawEndpieceDeltasDouble(pts[0],
2120                    iDeltaX1, iDeltaY1, iDeltaX2, iDeltaY2, deltapoints);
2121            for (j = 0; j < 4; j++) {
2122                points[counter] = new POINT2(deltapoints[j]);
2123                points[counter].style = 0;
2124                counter++;
2125            }
2126            points[counter - 3].style = 5;
2127            points[counter - 1].style = 5;
2128
2129            // draw the semicircle
2130            iRadius =  (Math.sqrt((savepoints[2].x - savepoints[1].x) * (savepoints[2].x - savepoints[1].x) +
2131                    (savepoints[2].y - savepoints[1].y) * (savepoints[2].y - savepoints[1].y)) / 2);
2132            ptArcCenter.x = (savepoints[1].x + savepoints[2].x) / 2;
2133            ptArcCenter.y = (savepoints[1].y + savepoints[2].y) / 2;
2134
2135            if(clockwise==false)
2136            {
2137                ArcApproximationDouble((ptArcCenter.x - iRadius), (ptArcCenter.y - iRadius),
2138                    (ptArcCenter.x + iRadius), (ptArcCenter.y + iRadius),
2139                    savepoints[2].x, savepoints[2].y, savepoints[1].x, savepoints[1].y, arcpoints);
2140            }
2141            else
2142            {
2143                ArcApproximationDouble((ptArcCenter.x - iRadius), (ptArcCenter.y - iRadius),
2144                    (ptArcCenter.x + iRadius), (ptArcCenter.y + iRadius),
2145                    savepoints[1].x, savepoints[1].y, savepoints[2].x, savepoints[2].y, arcpoints);
2146            }
2147            for (j = 0; j < 17; j++) {
2148                points[counter] = new POINT2(arcpoints[j]);
2149                points[counter].style = 0;
2150                counter++;
2151            }
2152            points[counter - 1].style = 5;
2153        } catch (Exception exc) {
2154            ErrorLogger.LogException(_className ,"GetDISMRIPDouble",
2155                    new RendererException("Failed inside GetDISMRIPDouble", exc));
2156        }
2157        return counter;
2158    }
2159    /**
2160     * Calculates the points for BYDIF
2161     *
2162     * @param points OUT - the client points, also used for the returned points.
2163     * @param linetype the line type.
2164     */
2165    protected static int GetDISMByDifDouble(POINT2[] points,
2166            int linetype,
2167            Rectangle2D clipBounds) {
2168        int counter = 0;
2169        try {
2170            POINT2[] pointsCorner = new POINT2[2];
2171            POINT2[] rectpts = new POINT2[4];
2172            POINT2[] savepoints = new POINT2[3], savepoints2 = new POINT2[2];
2173            POINT2[] deltapoints1 = new POINT2[4];
2174            POINT2[] deltapoints2 = new POINT2[4];
2175            POINT2[] pts = new POINT2[3];
2176            //POINT2 pt0 = new POINT2();
2177            //POINT2 pt1 = new POINT2();
2178            ref<double[]> iDeltaX = new ref(), iDeltaY = new ref();
2179            int bPointsRight = 0;
2180            double dAngle1 = 0;
2181            double dLength = 0;
2182            double dJaggyHalfAmp = 0;
2183            double dJaggyHalfPeriod = 0;
2184            double dDeltaXOut = 0;
2185            double dDeltaYOut = 0;
2186            double dDeltaXAlong = 0;
2187            double dDeltaYAlong = 0;
2188            int iNumJaggies = 0;
2189            int i = 0, j = 0;
2190            //int pointcounter = 0;
2191            //int[] segments = null;
2192            //end declarations
2193            //lineutility.WriteFile("made it this far");
2194            //ok to here
2195
2196            for (j = 0; j < 3; j++) {
2197                savepoints[j] = new POINT2(points[j]);
2198            }
2199
2200            lineutility.InitializePOINT2Array(pointsCorner);
2201            lineutility.InitializePOINT2Array(rectpts);
2202            lineutility.InitializePOINT2Array(pts);
2203            lineutility.InitializePOINT2Array(deltapoints1);
2204            lineutility.InitializePOINT2Array(deltapoints2);
2205
2206            DrawOpenRectangleDouble(savepoints, pointsCorner, rectpts);
2207            //save the back side for use by the jagged line
2208            savepoints2[0] = new POINT2(rectpts[1]);
2209            savepoints2[1] = new POINT2(rectpts[2]);
2210
2211            //diagnostic these hard coded because JavalineArray does not know the bounds
2212            if(clipBounds != null)
2213            {
2214                POINT2 ul=new POINT2(clipBounds.getMinX(),clipBounds.getMinY());
2215                POINT2 lr=new POINT2(clipBounds.getMaxX(),clipBounds.getMaxY());
2216                savepoints2=lineutility.BoundOneSegment(savepoints2[0], savepoints2[1], ul, lr);
2217            }
2218            Boolean drawJaggies=true;
2219            if(savepoints2==null)
2220            {
2221                savepoints2 = new POINT2[2];
2222                savepoints2[0] = new POINT2(rectpts[1]);
2223                savepoints2[1] = new POINT2(rectpts[2]);
2224                drawJaggies=false;
2225            }
2226            for (j = 0; j < 4; j++) {
2227                points[counter] = new POINT2(rectpts[j]);
2228                points[counter].style = 0;
2229                counter++;
2230            }
2231            points[1].style = 5;
2232            points[counter - 1].style = 5;
2233
2234            dAngle1 = Math.atan2(savepoints2[0].y - savepoints2[1].y, savepoints2[0].x - savepoints2[1].x);
2235            dLength = Math.sqrt((savepoints2[1].x - savepoints2[0].x) * (savepoints2[1].x - savepoints2[0].x) +
2236                    (savepoints2[1].y - savepoints2[0].y) * (savepoints2[1].y - savepoints2[0].y));
2237            dJaggyHalfAmp = dLength / 15; // half the amplitude of the "jaggy function"
2238
2239            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
2240            if (dJaggyHalfAmp > maxLength * DPIScaleFactor) {
2241                dJaggyHalfAmp = maxLength * DPIScaleFactor;
2242            }
2243            if (dJaggyHalfAmp < minLength * DPIScaleFactor) {
2244                dJaggyHalfAmp = minLength * DPIScaleFactor;
2245            }
2246
2247            dJaggyHalfPeriod = dJaggyHalfAmp / 1.5; // half the period of the "jaggy function"
2248            dDeltaXOut = Math.cos(dAngle1 + CONST_PI / 2) * dJaggyHalfAmp; // X-delta out from the center line
2249            dDeltaYOut = Math.sin(dAngle1 + CONST_PI / 2) * dJaggyHalfAmp; // Y-delta out from the center line
2250            dDeltaXAlong = Math.cos(dAngle1) * dJaggyHalfPeriod; // X-delta along the center line
2251            dDeltaYAlong = Math.sin(dAngle1) * dJaggyHalfPeriod; // Y-delta along the center line
2252
2253            iNumJaggies = (int) (dLength / dJaggyHalfPeriod) - 3;
2254            i = 2;
2255            pts[0] = new POINT2(savepoints2[1]);
2256            pts[1].x = savepoints2[1].x + dDeltaXAlong * 1.5;
2257            pts[1].y = savepoints2[1].y + dDeltaYAlong * 1.5;
2258            points[counter] = new POINT2(pts[0]);
2259            points[counter].style = 0;
2260            counter++;
2261            points[counter] = new POINT2(pts[1]);
2262            points[counter].style = 5;
2263            counter++;
2264
2265            pts[0].x = savepoints2[1].x + dDeltaXOut + dDeltaXAlong * i;
2266            pts[0].y = savepoints2[1].y + dDeltaYOut + dDeltaYAlong * i;
2267            i++;
2268            points[counter] = new POINT2(pts[0]);
2269            points[counter].style = 0;
2270            counter++;
2271            points[counter] = new POINT2(pts[1]);
2272            points[counter].style = 5;
2273            counter++;
2274            
2275            if(drawJaggies)//diagnostic
2276            {
2277                while (i <= iNumJaggies) {
2278                    pts[1].x = savepoints2[1].x - dDeltaXOut + dDeltaXAlong * i;
2279                    pts[1].y = savepoints2[1].y - dDeltaYOut + dDeltaYAlong * i;
2280                    i++;
2281                    pts[2].x = savepoints2[1].x + dDeltaXOut + dDeltaXAlong * i;
2282                    pts[2].y = savepoints2[1].y + dDeltaYOut + dDeltaYAlong * i;
2283                    i++;
2284                    for (j = 0; j < 3; j++) {
2285                        points[counter] = new POINT2(pts[j]);
2286                        points[counter].style = 0;
2287                        counter++;
2288                    }
2289                    points[counter - 1].style = 5;
2290                    pts[0] = new POINT2(pts[2]);
2291                }
2292            }
2293
2294            pts[1] = new POINT2(pts[0]);
2295            pts[0].x = savepoints2[1].x + dDeltaXAlong * i;
2296            pts[0].y = savepoints2[1].y + dDeltaYAlong * i;
2297            //DrawLine(destination, mask, color, pts, 2, 2);
2298            points[counter] = new POINT2(pts[0]);
2299            points[counter].style = 0;
2300            counter++;
2301            points[counter] = new POINT2(pts[1]);
2302            points[counter].style = 5;
2303            counter++;
2304
2305            pts[1] = new POINT2(savepoints2[0]);
2306            //DrawLine(destination, mask, color, pts, 2, 2);
2307            points[counter] = new POINT2(pts[0]);
2308            points[counter].style = 0;
2309            counter++;
2310            points[counter] = new POINT2(pts[1]);
2311            points[counter].style = 5;
2312            counter++;
2313
2314            bPointsRight = DetermineDirectionDouble(savepoints);
2315
2316            CalcEndpieceDeltasDouble(savepoints, iDeltaX, iDeltaY, CONST_PI / 4);
2317
2318            if ((savepoints[0].y - savepoints[1].y) < 0) {// Point0 is higher than Point1
2319                if (bPointsRight != 0) {// figure opens to the right
2320                    DrawEndpieceDeltasDouble(savepoints[0],
2321                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints1);
2322                    DrawEndpieceDeltasDouble(savepoints[1],
2323                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints2);
2324                } else {// figure opens to the left
2325                    DrawEndpieceDeltasDouble(savepoints[0],
2326                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints1);
2327                    DrawEndpieceDeltasDouble(savepoints[1],
2328                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints2);
2329                }
2330            } else {// Point0 is lower than Point1
2331                if (bPointsRight != 0) {// figure opens to the right
2332                    DrawEndpieceDeltasDouble(savepoints[0],
2333                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints1);
2334                    DrawEndpieceDeltasDouble(savepoints[1],
2335                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints2);
2336                } else {// figure opens to the left
2337                    DrawEndpieceDeltasDouble(savepoints[0],
2338                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints1);
2339                    DrawEndpieceDeltasDouble(savepoints[1],
2340                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints2);
2341                }
2342            }
2343            points[counter] = new POINT2(deltapoints1[1]);
2344            points[counter].style = 9;
2345            counter++;
2346            points[counter] = new POINT2(deltapoints1[0]);
2347            points[counter].style = 9;
2348            counter++;
2349            points[counter] = new POINT2(deltapoints1[3]);
2350            points[counter].style = 9;
2351            counter++;
2352            points[counter] = new POINT2(deltapoints1[3]);
2353            points[counter].style = 10;
2354            counter++;
2355
2356            points[counter] = new POINT2(deltapoints2[1]);
2357            points[counter].style = 9;
2358            counter++;
2359            points[counter] = new POINT2(deltapoints2[0]);
2360            points[counter].style = 9;
2361            counter++;
2362            points[counter] = new POINT2(deltapoints2[3]);
2363            points[counter].style = 9;
2364            counter++;
2365            points[counter] = new POINT2(deltapoints2[3]);
2366            points[counter].style = 10;
2367            counter++;
2368
2369        } catch (Exception exc) {
2370            //lineutility.WriteFile(exc.getMessage());
2371            ErrorLogger.LogException(_className ,"GetDISMByDifDouble",
2372                    new RendererException("Failed inside GetDISMByDifDouble", exc));
2373        }
2374        return counter;
2375    }
2376    /**
2377     * Calculates the points for PENETRATE
2378     *
2379     * @param points OUT - the client points, also used for the returned points.
2380     * @param linetype the line type.
2381     */
2382    protected static void GetDISMPenetrateDouble(POINT2[] points, int linetype) {
2383        try {
2384            POINT2[] arrowpts = new POINT2[3];
2385            POINT2 midpt = new POINT2();
2386            POINT2[] savepoints = new POINT2[3];
2387            int j = 0;
2388            double d = 0;
2389
2390            for (j = 0; j < 3; j++) {
2391                savepoints[j] = new POINT2(points[j]);
2392            }
2393            lineutility.InitializePOINT2Array(arrowpts);
2394
2395            points[0].x = savepoints[0].x;
2396            points[0].y = savepoints[0].y;
2397            points[0].style = 0;
2398            points[1].x = savepoints[1].x;
2399            points[1].y = savepoints[1].y;
2400            points[1].style = 5;
2401
2402            midpt = lineutility.MidPointDouble(savepoints[0], savepoints[1], 0);
2403
2404            points[2] = new POINT2(savepoints[2]);
2405
2406            points[3] = new POINT2(midpt);
2407            points[3].style = 5;
2408            d = lineutility.MBRDistance(savepoints, 3);
2409
2410            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
2411            if (d / 5 > maxLength * DPIScaleFactor) {
2412                d = 5 * maxLength * DPIScaleFactor;
2413            }
2414            if (d / 5 < minLength * DPIScaleFactor) {
2415                d = 5 * minLength * DPIScaleFactor;
2416            }
2417            String client=CELineArray.getClient();
2418            if(client.matches("cpof3d") || client.matches("cpof2d"))
2419            {
2420                if(d<400 * DPIScaleFactor)
2421                    d=400 * DPIScaleFactor;
2422            }
2423            else
2424            {
2425                if(d<150 * DPIScaleFactor)
2426                    d=150 * DPIScaleFactor;
2427            }
2428            if(d>600 * DPIScaleFactor)
2429                d=600 * DPIScaleFactor;
2430
2431            lineutility.GetArrowHead4Double(points[2], points[3], (int)d / 20,(int)d / 20, arrowpts, 0);
2432            for (j = 0; j < 3; j++) {
2433                points[4 + j] = new POINT2(arrowpts[j]);
2434            }
2435
2436        } catch (Exception exc) {
2437            ErrorLogger.LogException(_className ,"GetDISMPenetrateDouble",
2438                    new RendererException("Failed inside GetDISMPenetrateDouble", exc));
2439        }
2440    }
2441    /**
2442     * Calculates the points for BYIMP
2443     *
2444     * @param points OUT - the client points, also used for the returned points.
2445     * @param linetype the line type.
2446     */
2447    protected static int GetDISMByImpDouble(POINT2[] points,
2448            int linetype) {
2449        int counter = 0;
2450        try {
2451            int j = 0;
2452            POINT2[] pointsCorner = new POINT2[2];
2453            POINT2[] rectpts = new POINT2[4];
2454            POINT2[] savepoints = new POINT2[3];
2455            POINT2[] deltapoints1 = new POINT2[4];
2456            POINT2[] deltapoints2 = new POINT2[4];
2457            POINT2 midpt = new POINT2();
2458            POINT2[] pts = new POINT2[6];
2459            POINT2 ptRelative = new POINT2();
2460            ref<double[]> iDeltaX = new ref(), iDeltaY = new ref();
2461            int bPointsRight = 0;
2462            double dMBR = lineutility.MBRDistance(points, 3);
2463            //end declarations
2464
2465            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
2466            if (dMBR > 40 * maxLength * DPIScaleFactor) {
2467                dMBR = 40 * maxLength * DPIScaleFactor;
2468            }
2469            if (dMBR < 5 * minLength * DPIScaleFactor) {
2470                dMBR = 5 * minLength * DPIScaleFactor;
2471            }
2472            if(dMBR>250 * DPIScaleFactor)
2473                dMBR=250 * DPIScaleFactor;
2474            if(dMBR / 15 > lineutility.CalcDistanceDouble(points[0], points[1]))
2475                // Don't let gap be wider than channel
2476                dMBR = 15 * lineutility.CalcDistanceDouble(points[0], points[1]);
2477
2478            for (j = 0; j < 3; j++) {
2479                savepoints[j] = new POINT2(points[j]);
2480            }
2481
2482            lineutility.InitializePOINT2Array(rectpts);
2483            lineutility.InitializePOINT2Array(deltapoints1);
2484            lineutility.InitializePOINT2Array(deltapoints2);
2485            lineutility.InitializePOINT2Array(pts);
2486            lineutility.InitializePOINT2Array(pointsCorner);
2487
2488            DrawOpenRectangleDouble(savepoints, pointsCorner, rectpts);
2489
2490            points[counter] = new POINT2(rectpts[0]);
2491            points[counter].style = 0;
2492            counter++;
2493            points[counter] = new POINT2(rectpts[1]);
2494            points[counter].style = 0;
2495            counter++;
2496            midpt = lineutility.MidPointDouble(rectpts[1], rectpts[2], 0);
2497            pts[0] = lineutility.ExtendLine2Double(rectpts[1], midpt, -dMBR / 30, 5);
2498            pts[1] = lineutility.ExtendLine2Double(rectpts[1], midpt, dMBR / 30, 5);
2499            points[counter] = new POINT2(pts[0]);
2500            points[counter].style = 5;
2501            counter++;
2502
2503            ptRelative = lineutility.PointRelativeToLine(rectpts[0], rectpts[1], pts[0]);
2504            pts[2] = lineutility.ExtendLineDouble(ptRelative, pts[0], -dMBR / 30);
2505
2506            pts[3] = lineutility.ExtendLineDouble(ptRelative, pts[0], dMBR / 30);
2507
2508            points[counter] = new POINT2(pts[2]);
2509            points[counter].style = 0;
2510            counter++;
2511            points[counter] = new POINT2(pts[3]);
2512            points[counter].style = 5;
2513            counter++;
2514            ptRelative = lineutility.PointRelativeToLine(rectpts[2], rectpts[3], pts[1]);
2515            pts[4] = lineutility.ExtendLineDouble(ptRelative, pts[1], -dMBR / 30);
2516
2517            pts[5] = lineutility.ExtendLineDouble(ptRelative, pts[1], dMBR / 30);
2518            points[counter] = new POINT2(pts[4]);
2519            points[counter].style = 0;
2520            counter++;
2521            points[counter] = new POINT2(pts[5]);
2522            points[counter].style = 5;
2523            counter++;
2524            points[counter] = new POINT2(pts[1]);
2525            points[counter].style = 0;
2526            counter++;
2527            points[counter] = new POINT2(rectpts[2]);
2528            points[counter].style = 0;
2529            counter++;
2530            points[counter] = new POINT2(rectpts[3]);
2531            points[counter].style = 5;
2532            counter++;
2533
2534            bPointsRight = DetermineDirectionDouble(savepoints);
2535
2536            CalcEndpieceDeltasDouble(savepoints, iDeltaX, iDeltaY, CONST_PI / 4);
2537
2538            if ((savepoints[0].y - savepoints[1].y) < 0) {// Point0 is higher than Point1
2539                if (bPointsRight != 0) {// figure opens to the right
2540                    DrawEndpieceDeltasDouble(savepoints[0],
2541                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints1);
2542                    DrawEndpieceDeltasDouble(savepoints[1],
2543                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints2);
2544                } else {// figure opens to the left
2545                    DrawEndpieceDeltasDouble(savepoints[0],
2546                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints1);
2547                    DrawEndpieceDeltasDouble(savepoints[1],
2548                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints2);
2549                }
2550            } else {// Point0 is lower than Point1
2551                if (bPointsRight != 0) {// figure opens to the right
2552                    DrawEndpieceDeltasDouble(savepoints[0],
2553                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints1);
2554                    DrawEndpieceDeltasDouble(savepoints[1],
2555                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints2);
2556                } else {// figure opens to the left
2557                    DrawEndpieceDeltasDouble(savepoints[0],
2558                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints1);
2559                    DrawEndpieceDeltasDouble(savepoints[1],
2560                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints2);
2561                }
2562            }
2563
2564            points[counter] = new POINT2(deltapoints1[1]);
2565            points[counter].style = 9;
2566            counter++;
2567            points[counter] = new POINT2(deltapoints1[0]);
2568            points[counter].style = 9;
2569            counter++;
2570            points[counter] = new POINT2(deltapoints1[3]);
2571            points[counter].style = 9;
2572            counter++;
2573            points[counter] = new POINT2(deltapoints1[3]);
2574            points[counter].style = 10;
2575            counter++;
2576
2577            points[counter] = new POINT2(deltapoints2[1]);
2578            points[counter].style = 9;
2579            counter++;
2580            points[counter] = new POINT2(deltapoints2[0]);
2581            points[counter].style = 9;
2582            counter++;
2583            points[counter] = new POINT2(deltapoints2[3]);
2584            points[counter].style = 9;
2585            counter++;
2586            points[counter] = new POINT2(deltapoints2[3]);
2587            points[counter].style = 10;
2588            counter++;
2589
2590        } catch (Exception exc) {
2591            ErrorLogger.LogException(_className ,"GetDISMByImpDouble",
2592                    new RendererException("Failed inside GetDISMByImpDouble", exc));
2593        }
2594        return counter;
2595    }
2596    /**
2597     * Calculates the points for SPTBYFIRE
2598     *
2599     * @param points OUT - the client points, also used for the returned points.
2600     * @param linetype the line type.
2601     */
2602    protected static int GetDISMSupportByFireDouble(POINT2[] points,
2603            int linetype) {
2604        int counter = 0;
2605        try {
2606            POINT2[] pts = new POINT2[3];
2607            POINT2[] savepoints = new POINT2[4];
2608            int j = 0;
2609            double iDiagEOL_length = 0;
2610            double dAngle1 = 0;
2611            double iDeltaX1 = 0;
2612            double iDeltaY1 = 0;
2613            double iDeltaX2 = 0;
2614            double iDeltaY2 = 0;
2615
2616            for (j = 0; j < 4; j++) {
2617                savepoints[j] = new POINT2(points[j]);
2618            }
2619            ReorderSptByFirePoints(savepoints);
2620
2621            lineutility.InitializePOINT2Array(pts);
2622            // draw line connecting points 1 & 2
2623            points[counter] = new POINT2(savepoints[0]);
2624            points[counter].style = 0;
2625            counter++;
2626            points[counter] = new POINT2(savepoints[1]);
2627            points[counter].style = 5;
2628            counter++;
2629
2630            // draw line connecting savepoints 1 & 3
2631            pts[0] = new POINT2(savepoints[0]);
2632            pts[1] = new POINT2(savepoints[2]);
2633            points[counter] = new POINT2(pts[0]);
2634            points[counter].style = 0;
2635            counter++;
2636            points[counter] = new POINT2(pts[1]);
2637            points[counter].style = 5;
2638            counter++;
2639
2640            // draw arrow at end of line
2641            iDiagEOL_length =  (Math.sqrt(
2642                    (savepoints[0].x - savepoints[1].x) * (savepoints[0].x - savepoints[1].x) +
2643                    (savepoints[0].y - savepoints[1].y) * (savepoints[0].y - savepoints[1].y)) / 10);
2644
2645            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
2646            if (iDiagEOL_length >  maxLength * DPIScaleFactor) {
2647                iDiagEOL_length =  maxLength * DPIScaleFactor;
2648            }
2649            if (iDiagEOL_length <  minLength * DPIScaleFactor) {
2650                iDiagEOL_length =  minLength * DPIScaleFactor;
2651            }
2652
2653            dAngle1 = Math.atan2(savepoints[0].y - savepoints[2].y, savepoints[0].x - savepoints[2].x);
2654            iDeltaX1 =  (Math.cos(dAngle1 + CONST_PI / 6) * iDiagEOL_length);
2655            iDeltaY1 =  (Math.sin(dAngle1 + CONST_PI / 6) * iDiagEOL_length);
2656            iDeltaX2 =  (Math.cos(dAngle1 - CONST_PI / 6) * iDiagEOL_length);
2657            iDeltaY2 =  (Math.sin(dAngle1 - CONST_PI / 6) * iDiagEOL_length);
2658            pts[0].x = savepoints[2].x + iDeltaX1;
2659            pts[0].y = savepoints[2].y + iDeltaY1;
2660            pts[1] = new POINT2(savepoints[2]);
2661            pts[2].x = savepoints[2].x + iDeltaX2;
2662            pts[2].y = savepoints[2].y + iDeltaY2;
2663            //DrawLine(destination, mask, color, pts, 3, 2);
2664            for (j = 0; j < 3; j++) {
2665                points[counter] = new POINT2(pts[j]);
2666                points[counter].style = 0;
2667                counter++;
2668            }
2669            points[counter - 1].style = 5;
2670
2671            // draw line connecting savepoints 2 & 4
2672            pts[0] = new POINT2(savepoints[1]);
2673            pts[1] = new POINT2(savepoints[3]);
2674            points[counter] = new POINT2(pts[0]);
2675            points[counter].style = 0;
2676            counter++;
2677            points[counter] = new POINT2(pts[1]);
2678            points[counter].style = 5;
2679            counter++;
2680
2681            // draw arrow at end of line
2682            dAngle1 = Math.atan2(savepoints[1].y - savepoints[3].y, savepoints[1].x - savepoints[3].x);
2683            iDeltaX1 =  (Math.cos(dAngle1 + CONST_PI / 6) * iDiagEOL_length);
2684            iDeltaY1 =  (Math.sin(dAngle1 + CONST_PI / 6) * iDiagEOL_length);
2685            iDeltaX2 =  (Math.cos(dAngle1 - CONST_PI / 6) * iDiagEOL_length);
2686            iDeltaY2 =  (Math.sin(dAngle1 - CONST_PI / 6) * iDiagEOL_length);
2687            pts[0].x = savepoints[3].x + iDeltaX1;
2688            pts[0].y = savepoints[3].y + iDeltaY1;
2689            pts[1] = new POINT2(savepoints[3]);
2690            pts[2].x = savepoints[3].x + iDeltaX2;
2691            pts[2].y = savepoints[3].y + iDeltaY2;
2692            //DrawLine(destination, mask, color, pts, 3, 2);
2693            for (j = 0; j < 3; j++) {
2694                points[counter] = new POINT2(pts[j]);
2695                points[counter].style = 0;
2696                counter++;
2697            }
2698            points[counter - 1].style = 5;
2699
2700            // draw lines on the back of the graphic
2701            dAngle1 = Math.atan2(savepoints[1].y - savepoints[0].y, savepoints[1].x - savepoints[0].x);
2702            iDiagEOL_length *= 2;
2703            iDeltaX1 =  (Math.cos(dAngle1 - CONST_PI / 4) * iDiagEOL_length);
2704            iDeltaY1 =  (Math.sin(dAngle1 - CONST_PI / 4) * iDiagEOL_length);
2705            iDeltaX2 =  (Math.cos(dAngle1 + CONST_PI / 4) * iDiagEOL_length);
2706            iDeltaY2 =  (Math.sin(dAngle1 + CONST_PI / 4) * iDiagEOL_length);
2707            pts[0].x = savepoints[0].x - iDeltaX1;
2708            pts[0].y = savepoints[0].y - iDeltaY1;
2709            pts[1] = new POINT2(savepoints[0]);
2710            points[counter] = new POINT2(pts[0]);
2711            points[counter].style = 0;
2712            counter++;
2713            points[counter] = new POINT2(pts[1]);
2714            points[counter].style = 5;
2715            counter++;
2716
2717            pts[0].x = savepoints[1].x + iDeltaX2;
2718            pts[0].y = savepoints[1].y + iDeltaY2;
2719            pts[1] = new POINT2(savepoints[1]);
2720            points[counter] = new POINT2(pts[0]);
2721            points[counter].style = 0;
2722            counter++;
2723            points[counter] = new POINT2(pts[1]);
2724            points[counter].style = 5;
2725            counter++;
2726        }
2727        catch (Exception exc) {
2728            ErrorLogger.LogException(_className ,"GetDISMSupportbyFireDouble",
2729                    new RendererException("Failed inside GetDISMSupportByFireDouble", exc));
2730        }
2731        return counter;
2732    }
2733
2734    private static void ReorderAtkByFirePoints(POINT2[] points) {
2735        try {
2736            //assume the points were ordered correctly. then pt0 is above the line from pt1 to pt2
2737            POINT2[] savepoints = new POINT2[3];
2738            POINT2 ptAboveLine = new POINT2(), ptBelowLine = new POINT2(), ptLeftOfLine = new POINT2(), ptRightOfLine = new POINT2();
2739            double distToLine = 0, distanceToPointAboveLine = 0, distanceToPointBelowLine = 0;
2740            double distanceToPointLeftOfLine = 0, distanceToPointRightOfLine = 0;
2741            for (int j = 0; j < 3; j++) {
2742                savepoints[j] = new POINT2(points[j]);
2743            }
2744
2745            if (Math.abs(savepoints[1].x - savepoints[2].x) > 2) {
2746                distToLine = lineutility.CalcDistanceToLineDouble(savepoints[1], savepoints[2], savepoints[0]);
2747                ptAboveLine = lineutility.ExtendDirectedLine(savepoints[1], savepoints[2], savepoints[2], 2, distToLine);
2748                ptBelowLine = lineutility.ExtendDirectedLine(savepoints[1], savepoints[2], savepoints[2], 3, distToLine);
2749                distanceToPointAboveLine = lineutility.CalcDistanceDouble(savepoints[0], ptAboveLine);
2750                distanceToPointBelowLine = lineutility.CalcDistanceDouble(savepoints[0], ptBelowLine);
2751                if (distanceToPointAboveLine < distanceToPointBelowLine) {
2752                    //then pt2 - pt3 should be left to right
2753                    if (savepoints[2].x < savepoints[1].x) {
2754                        lineutility.Reverse2Points(savepoints[1], savepoints[2]);
2755                    }
2756
2757
2758                } else {
2759                    if (savepoints[2].x > savepoints[1].x) {
2760                        lineutility.Reverse2Points(savepoints[1], savepoints[2]);
2761                    }
2762
2763                }
2764            } else //the last 2 points form a vertical line
2765            {
2766                distToLine = lineutility.CalcDistanceToLineDouble(savepoints[1], savepoints[2], savepoints[0]);
2767                ptLeftOfLine = lineutility.ExtendDirectedLine(savepoints[1], savepoints[2], savepoints[2], 0, distToLine);
2768                ptRightOfLine = lineutility.ExtendDirectedLine(savepoints[1], savepoints[2], savepoints[2], 1, distToLine);
2769                distanceToPointLeftOfLine = lineutility.CalcDistanceDouble(savepoints[0], ptLeftOfLine);
2770                distanceToPointRightOfLine = lineutility.CalcDistanceDouble(savepoints[0], ptRightOfLine);
2771                if (distanceToPointRightOfLine < distanceToPointLeftOfLine) {
2772                    if (savepoints[2].y < savepoints[1].y) {
2773                        lineutility.Reverse2Points(savepoints[1], savepoints[2]);
2774                    }
2775                } else {
2776                    if (savepoints[2].y > savepoints[1].y) {
2777                        lineutility.Reverse2Points(savepoints[1], savepoints[2]);
2778                    }
2779                }
2780            }
2781            points[1].x = savepoints[1].x;
2782            points[1].y = savepoints[1].y;
2783            points[2].x = savepoints[2].x;
2784            points[2].y = savepoints[2].y;
2785        } catch (Exception exc) {
2786            ErrorLogger.LogException(_className, "ReorderAtkByFirePoints",
2787                    new RendererException("Failed inside GetDISMSupportByFireDouble", exc));
2788        }
2789    }
2790    private static void ReorderSptByFirePoints(POINT2[] points) {
2791        try {
2792            //assume the points were ordered correctly. then pt0 is above the line from pt1 to pt2
2793            POINT2 ptAboveLine = new POINT2(), ptBelowLine = new POINT2(), ptLeftOfLine = new POINT2(), ptRightOfLine = new POINT2();
2794            double distToLine = 0, distanceToPointAboveLine = 0, distanceToPointBelowLine = 0;
2795            double distanceToPointLeftOfLine = 0, distanceToPointRightOfLine = 0;
2796
2797            POINT2 midpt = lineutility.MidPointDouble(points[0], points[1], 0);
2798            if (Math.abs(points[2].x - points[3].x) > 2) {
2799                distToLine = lineutility.CalcDistanceToLineDouble(points[1], points[2], midpt);
2800                ptAboveLine = lineutility.ExtendDirectedLine(points[1], points[2], points[2], 2, distToLine);
2801                ptBelowLine = lineutility.ExtendDirectedLine(points[1], points[2], points[2], 3, distToLine);
2802                distanceToPointAboveLine = lineutility.CalcDistanceDouble(points[0], ptAboveLine);
2803                distanceToPointBelowLine = lineutility.CalcDistanceDouble(points[0], ptBelowLine);
2804                if (distanceToPointAboveLine < distanceToPointBelowLine) {
2805                    //then pt2 - pt3 should be left to right
2806                    if (points[2].x < points[1].x) {
2807                        lineutility.Reverse2Points(points[0], points[1]);
2808                        lineutility.Reverse2Points(points[2], points[3]);
2809                    }
2810                } else {
2811                    if (points[2].x > points[1].x) {
2812                        lineutility.Reverse2Points(points[0], points[1]);
2813                        lineutility.Reverse2Points(points[2], points[3]);
2814                    }
2815                }
2816            } else //the last 2 points form a vertical line
2817            {
2818                distToLine = lineutility.CalcDistanceToLineDouble(points[1], points[2], midpt);
2819                ptLeftOfLine = lineutility.ExtendDirectedLine(points[1], points[2], points[2], 0, distToLine);
2820                ptRightOfLine = lineutility.ExtendDirectedLine(points[1], points[2], points[2], 1, distToLine);
2821                distanceToPointLeftOfLine = lineutility.CalcDistanceDouble(points[0], ptLeftOfLine);
2822                distanceToPointRightOfLine = lineutility.CalcDistanceDouble(points[0], ptRightOfLine);
2823                if (distanceToPointLeftOfLine < distanceToPointRightOfLine) {
2824                    //then pt2 - pt3 should be left to right
2825                    if (points[2].y > points[1].y) {
2826                        lineutility.Reverse2Points(points[0], points[1]);
2827                        lineutility.Reverse2Points(points[2], points[3]);
2828                    }
2829                } else {
2830                    if (points[2].y < points[1].y) {
2831                        lineutility.Reverse2Points(points[0], points[1]);
2832                        lineutility.Reverse2Points(points[2], points[3]);
2833                    }
2834                }
2835
2836            }
2837        } catch (Exception exc) {
2838            ErrorLogger.LogException(_className, "ReorderSptByFire",
2839                    new RendererException("Failed inside ReorderSptByFirePoints", exc));
2840        }
2841    }
2842    /**
2843     * Calculates the points for ATKBYFIRE
2844     *
2845     * @param points OUT - the client points, also used for the returned points.
2846     * @param linetype the line type.
2847     */
2848    protected static int GetDISMATKBYFIREDouble(POINT2[] points, int linetype) {
2849        int counter = 0;
2850        try {
2851            POINT2[] pts = new POINT2[3];
2852            POINT2 ptMid = new POINT2();
2853            POINT2[] savepoints = new POINT2[3];
2854            int j = 0;
2855            double iDiagEOL_length = 0;
2856            double dAngle1 = 0;
2857            double iDeltaX1 = 0;
2858            double iDeltaY1 = 0;
2859            double iDeltaX2 = 0;
2860            double iDeltaY2 = 0;
2861
2862            for (j = 0; j < 3; j++) {
2863                savepoints[j] = new POINT2(points[j]);
2864            }
2865
2866            ReorderAtkByFirePoints(savepoints);
2867
2868            lineutility.InitializePOINT2Array(pts);
2869            // draw line across back
2870            pts[0] = new POINT2(savepoints[1]);
2871            pts[1] = new POINT2(savepoints[2]);
2872            //DrawLine(destination, mask, color, pts, 2, 2);
2873            points[counter] = new POINT2(pts[0]);
2874            points[counter].style = 0;
2875            counter++;
2876            points[counter] = new POINT2(pts[1]);
2877            points[counter].style = 5;
2878            counter++;
2879
2880            // draw perpendicular line
2881            ptMid.x = (savepoints[1].x + savepoints[2].x) / 2;
2882            ptMid.y = (savepoints[1].y + savepoints[2].y) / 2;
2883            pts[0] = new POINT2(ptMid);
2884            pts[1] = new POINT2(savepoints[0]);
2885            //DrawLine(destination, mask, color, pts, 2, 2);
2886            points[counter] = new POINT2(pts[0]);
2887            points[counter].style = 0;
2888            counter++;
2889            points[counter] = new POINT2(pts[1]);
2890            points[counter].style = 5;
2891            counter++;
2892
2893            // draw arrowhead
2894            iDiagEOL_length =  ((Math.sqrt // height of graphic
2895                    (
2896                    (savepoints[1].x - savepoints[2].x) * (savepoints[1].x - savepoints[2].x) +
2897                    (savepoints[1].y - savepoints[2].y) * (savepoints[1].y - savepoints[2].y)) +
2898                    Math.sqrt // length of graphic
2899                    (
2900                    (savepoints[0].x - ptMid.x) * (savepoints[0].x - ptMid.x) +
2901                    (savepoints[0].y - ptMid.y) * (savepoints[0].y - ptMid.y))) / 20);
2902            //if(iDiagEOL_length<10)
2903            //  iDiagEOL_length=10;
2904            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
2905            if ((double) iDiagEOL_length > maxLength/5 * DPIScaleFactor) {
2906                iDiagEOL_length =  maxLength/5 * DPIScaleFactor;
2907            }
2908            if ((double) iDiagEOL_length < minLength * DPIScaleFactor) {
2909                iDiagEOL_length =  minLength * DPIScaleFactor;
2910            }
2911
2912            dAngle1 = Math.atan2(ptMid.y - savepoints[0].y, ptMid.x - savepoints[0].x);
2913            iDeltaX1 =  (Math.cos(dAngle1 + CONST_PI / 6) * iDiagEOL_length);
2914            iDeltaY1 =  (Math.sin(dAngle1 + CONST_PI / 6) * iDiagEOL_length);
2915            iDeltaX2 =  (Math.cos(dAngle1 - CONST_PI / 6) * iDiagEOL_length);
2916            iDeltaY2 =  (Math.sin(dAngle1 - CONST_PI / 6) * iDiagEOL_length);
2917            pts[0].x = savepoints[0].x + iDeltaX1;
2918            pts[0].y = savepoints[0].y + iDeltaY1;
2919            pts[1] = new POINT2(savepoints[0]);
2920            pts[2].x = savepoints[0].x + iDeltaX2;
2921            pts[2].y = savepoints[0].y + iDeltaY2;
2922            //DrawLine(destination, mask, color, pts, 3, 2);
2923            for (j = 0; j < 3; j++) {
2924                points[counter] = new POINT2(pts[j]);
2925                points[counter].style = 0;
2926                counter++;
2927            }
2928            points[counter - 1].style = 5;
2929
2930            // draw lines on the back of the graphic
2931            dAngle1 = Math.atan2(savepoints[1].y - savepoints[2].y, savepoints[1].x - savepoints[2].x);
2932            iDeltaX1 =  (Math.cos(dAngle1 - CONST_PI / 4) * iDiagEOL_length * 2);
2933            iDeltaY1 =  (Math.sin(dAngle1 - CONST_PI / 4) * iDiagEOL_length * 2);
2934            iDeltaX2 =  (Math.cos(dAngle1 + CONST_PI / 4) * iDiagEOL_length * 2);
2935            iDeltaY2 =  (Math.sin(dAngle1 + CONST_PI / 4) * iDiagEOL_length * 2);
2936
2937            pts[0].x = savepoints[1].x + iDeltaX1;
2938            pts[0].y = savepoints[1].y + iDeltaY1;
2939            pts[1] = new POINT2(savepoints[1]);
2940            //DrawLine(destination, mask, color, pts, 2, 2);
2941            points[counter] = new POINT2(pts[0]);
2942            points[counter].style = 0;
2943            counter++;
2944            points[counter] = new POINT2(pts[1]);
2945            points[counter].style = 5;
2946            counter++;
2947
2948            pts[0].x = savepoints[2].x - iDeltaX2;
2949            pts[0].y = savepoints[2].y - iDeltaY2;
2950            pts[1] = new POINT2(savepoints[2]);
2951            //DrawLine(destination, mask, color, pts, 2, 2);
2952            points[counter] = new POINT2(pts[0]);
2953            points[counter].style = 0;
2954            counter++;
2955            points[counter] = new POINT2(pts[1]);
2956            points[counter].style = 5;
2957            counter++;
2958        } catch (Exception exc) {
2959            ErrorLogger.LogException(_className ,"GetDISMAtkByFireDouble",
2960                    new RendererException("Failed inside GetDISMAtkByFireDouble", exc));
2961        }
2962        return counter;
2963    }
2964    /**
2965     * Calculates the points for GAP
2966     *
2967     * @param points OUT - the client points, also used for the returned points.
2968     * @param linetype the line type.
2969     */
2970    protected static int GetDISMGapDouble(POINT2[] points, int linetype) {
2971        try {
2972            POINT2[] savepoints = new POINT2[4];
2973            POINT2[] pts = new POINT2[2];
2974            int j = 0;
2975            double dMBR = lineutility.MBRDistance(points, 4);
2976            //end declarations
2977
2978            for (j = 0; j < 4; j++) {
2979                savepoints[j] = new POINT2(points[j]);
2980            }
2981
2982            lineutility.InitializePOINT2Array(pts);
2983            //M. Deutch 8-19-04
2984            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
2985            if (dMBR / 10 > maxLength * DPIScaleFactor) {
2986                dMBR = 10 * maxLength * DPIScaleFactor;
2987            }
2988            if (dMBR / 10 < minLength * DPIScaleFactor) {
2989                dMBR = 10 * minLength * DPIScaleFactor;
2990            }
2991
2992            points[0] = new POINT2(savepoints[0]);
2993            points[0].style = 0;
2994            points[1] = new POINT2(savepoints[1]);
2995            points[1].style = 5;
2996            points[2] = new POINT2(savepoints[2]);
2997            points[2].style = 0;
2998            points[3] = new POINT2(savepoints[3]);
2999            points[3].style = 5;
3000
3001            double dist = dMBR / 10;
3002            if(dist > 20 * DPIScaleFactor)
3003                dist = 20 * DPIScaleFactor;
3004            double dist2 = dist;
3005
3006            //get the extension point
3007            pts[0] = lineutility.ExtendLineDouble(savepoints[1], savepoints[0], dist);
3008            pts[1] = lineutility.ExtendLineDouble(savepoints[2], savepoints[0], dist2);
3009            points[4] = new POINT2(points[0]);
3010            points[4].style = 0;
3011            points[5] = lineutility.MidPointDouble(pts[0], pts[1], 5);
3012            //get the extension point
3013            pts[0] = lineutility.ExtendLineDouble(savepoints[0], savepoints[1], dist);
3014            pts[1] = lineutility.ExtendLineDouble(savepoints[3], savepoints[1], dist2);
3015            points[6] = new POINT2(points[1]);
3016            points[6].style = 0;
3017            points[7] = lineutility.MidPointDouble(pts[0], pts[1], 5);
3018            //get the extension point
3019            pts[0] = lineutility.ExtendLineDouble(savepoints[0], savepoints[2], dist2);
3020            pts[1] = lineutility.ExtendLineDouble(savepoints[3], savepoints[2], dist);
3021            points[8] = new POINT2(points[2]);
3022            points[8].style = 0;
3023            points[9] = lineutility.MidPointDouble(pts[0], pts[1], 5);
3024            //get the extension point
3025            pts[0] = lineutility.ExtendLineDouble(savepoints[1], savepoints[3], dist2);
3026            pts[1] = lineutility.ExtendLineDouble(savepoints[2], savepoints[3], dist);
3027            points[10] = new POINT2(points[3]);
3028            points[10].style = 0;
3029            points[11] = lineutility.MidPointDouble(pts[0], pts[1], 5);
3030
3031        } catch (Exception exc) {
3032            ErrorLogger.LogException(_className ,"GetDISMGapDouble",
3033                    new RendererException("Failed inside GetDISMGapDouble", exc));
3034        }
3035        return 12;
3036    }
3037    /**
3038     * Calculates the points for MNFLDDIS
3039     *
3040     * @param points - OUT - the client points, also used for the returned points.
3041     * @param linetype the line type.
3042     */
3043    protected static int GetDISMMinefieldDisruptDouble(POINT2[] points, int linetype) {
3044        int counter=0;
3045        try {
3046            POINT2[] pts = new POINT2[2];
3047            POINT2[] ptsArrow = new POINT2[3];
3048            POINT2 ptCenter = new POINT2();
3049            int j = 0;
3050            POINT2[] savepoints = new POINT2[3];
3051            double dAngle1 = 0, d = 0, dist = 0;
3052            POINT2[] deltapoints1 = new POINT2[4];
3053            POINT2[] deltapoints2 = new POINT2[4];
3054            POINT2[] deltapoints3 = new POINT2[4];
3055            double iDiagEOL_length = 0;
3056            double iDeltaX1 = 0;
3057            double iDeltaY1 = 0;
3058            double iDeltaX2 = 0;
3059            double iDeltaY2 = 0;
3060            POINT2 ptTail = new POINT2();
3061            //end declarations
3062
3063            for (j = 0; j < 3; j++) {
3064                savepoints[j] = new POINT2(points[j]);
3065            }
3066
3067            lineutility.InitializePOINT2Array(ptsArrow);
3068            lineutility.InitializePOINT2Array(deltapoints1);
3069            lineutility.InitializePOINT2Array(deltapoints2);
3070            lineutility.InitializePOINT2Array(deltapoints3);
3071            lineutility.InitializePOINT2Array(pts);
3072            
3073            points[counter] = new POINT2(savepoints[0]);
3074            points[counter].style = 0;
3075            counter++;
3076            points[counter] = new POINT2(savepoints[1]);
3077            points[counter].style = 5;
3078            counter++;
3079
3080            ptCenter.x = (savepoints[0].x + savepoints[1].x) / 2;
3081            ptCenter.y = (savepoints[0].y + savepoints[1].y) / 2;
3082
3083            ptsArrow[0] = new POINT2(savepoints[2]);
3084            ptsArrow[1].x = ptCenter.x + (savepoints[2].x - savepoints[0].x) * 4 / 5;
3085            ptsArrow[1].y = ptCenter.y + (savepoints[2].y - savepoints[0].y) * 4 / 5;
3086            ptsArrow[2].x = savepoints[1].x + (savepoints[2].x - savepoints[0].x) * 3 / 5;
3087            ptsArrow[2].y = savepoints[1].y + (savepoints[2].y - savepoints[0].y) * 3 / 5;
3088
3089            points[counter] = new POINT2(savepoints[1]);
3090            points[counter].style = 0;
3091            counter++;
3092            points[counter] = new POINT2(ptsArrow[2]);
3093            points[counter].style = 5;
3094            counter++;
3095
3096            pts[1] = new POINT2(ptsArrow[1]);
3097
3098            //draw middle line
3099            points[counter] = new POINT2(ptCenter);
3100            points[counter].style = 0;
3101            counter++;
3102            points[counter] = new POINT2(pts[1]);
3103            points[counter].style = 5;
3104            counter++;
3105
3106            //draw tail
3107            dist = lineutility.CalcDistanceDouble(savepoints[2], savepoints[0]);
3108            d = dist;
3109            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
3110            if (d > 5 * maxLength * DPIScaleFactor) {
3111                d = 5 * maxLength * DPIScaleFactor;
3112            }
3113            if (d < 5 * minLength * DPIScaleFactor) {
3114                d = 5 * minLength * DPIScaleFactor;
3115            }
3116            ptTail = new POINT2(ptCenter);
3117            pts[0].x = ptTail.x - (savepoints[2].x - savepoints[0].x) / 5;
3118            pts[0].y = ptTail.y - (savepoints[2].y - savepoints[0].y) / 5;
3119            pts[0] = lineutility.ExtendLineDouble(pts[0], ptTail, -d / 5);
3120            points[counter] = new POINT2(ptTail);
3121            points[counter].style = 0;
3122            counter++;
3123            points[counter] = new POINT2(pts[0]);
3124            points[counter].style = 5;
3125            counter++;
3126
3127            pts[0] = new POINT2(savepoints[0]);
3128            pts[1] = new POINT2(ptsArrow[0]);
3129
3130            points[counter] = new POINT2(pts[0]);
3131            points[counter].style = 0;
3132            counter++;
3133            points[counter] = new POINT2(pts[1]);
3134            points[counter].style = 5;
3135            counter++;
3136
3137            // the following code is very similar to CalcEndpieceDeltas
3138            iDiagEOL_length =  ((Math.sqrt // height of graphic
3139                    (
3140                    (savepoints[1].x - savepoints[0].x) * (savepoints[1].x - savepoints[0].x) +
3141                    (savepoints[1].y - savepoints[0].y) * (savepoints[1].y - savepoints[0].y)) +
3142                    Math.sqrt // length of graphic
3143                    (
3144                    (savepoints[2].x - savepoints[1].x) * (savepoints[2].x - savepoints[1].x) +
3145                    (savepoints[2].y - savepoints[1].y) * (savepoints[2].y - savepoints[1].y))) / 15);
3146            // dAngle1 = angle used to calculate the end-piece deltas
3147
3148            if (iDiagEOL_length >  maxLength * DPIScaleFactor) {
3149                iDiagEOL_length =  maxLength * DPIScaleFactor;
3150            }
3151            if (iDiagEOL_length <  minLength * DPIScaleFactor) {
3152                iDiagEOL_length =  minLength * DPIScaleFactor;
3153            }
3154
3155            dAngle1 = Math.atan2(savepoints[0].y - savepoints[2].y, savepoints[0].x - savepoints[2].x);
3156            iDeltaX1 =  (iDiagEOL_length * Math.cos(dAngle1 - CONST_PI / 6));
3157            iDeltaY1 =  (iDiagEOL_length * Math.sin(dAngle1 - CONST_PI / 6));
3158            iDeltaX2 =  (iDiagEOL_length * Math.cos(dAngle1 + CONST_PI / 6));
3159            iDeltaY2 =  (iDiagEOL_length * Math.sin(dAngle1 + CONST_PI / 6));
3160
3161            DrawEndpieceDeltasDouble(ptsArrow[0],
3162                    iDeltaX1, iDeltaY1, iDeltaX2, iDeltaY2, deltapoints1);
3163            DrawEndpieceDeltasDouble(ptsArrow[1],
3164                    iDeltaX1, iDeltaY1, iDeltaX2, iDeltaY2, deltapoints2);
3165            DrawEndpieceDeltasDouble(ptsArrow[2],
3166                    iDeltaX1, iDeltaY1, iDeltaX2, iDeltaY2, deltapoints3);
3167            points[counter] = new POINT2(deltapoints1[1]);
3168            points[counter].style = 9;
3169            counter++;
3170            points[counter] = new POINT2(deltapoints1[0]);
3171            points[counter].style = 9;
3172            counter++;
3173            points[counter] = new POINT2(deltapoints1[3]);
3174            points[counter].style = 9;
3175            counter++;
3176            points[counter] = new POINT2(deltapoints1[3]);
3177            points[counter].style = 10;
3178            counter++;
3179
3180            points[counter] = new POINT2(deltapoints2[1]);
3181            points[counter].style = 9;
3182            counter++;
3183            points[counter] = new POINT2(deltapoints2[0]);
3184            points[counter].style = 9;
3185            counter++;
3186            points[counter] = new POINT2(deltapoints2[3]);
3187            points[counter].style = 9;
3188            counter++;
3189            points[counter] = new POINT2(deltapoints2[3]);
3190            points[counter].style = 10;
3191            counter++;
3192
3193            points[counter] = new POINT2(deltapoints3[1]);
3194            points[counter].style = 9;
3195            counter++;
3196            points[counter] = new POINT2(deltapoints3[0]);
3197            points[counter].style = 9;
3198            counter++;
3199            points[counter] = new POINT2(deltapoints3[3]);
3200            points[counter].style = 9;
3201            counter++;
3202            points[counter] = new POINT2(deltapoints3[3]);
3203            points[counter].style = 10;
3204            counter++;
3205
3206        } catch (Exception exc) {
3207            ErrorLogger.LogException(_className ,"GetDISMMinefieldDisruptDouble",
3208                    new RendererException("Failed inside GetDISMMinefieldDisruptDouble", exc));
3209        }
3210        return counter;
3211    }
3212    /**
3213     * Calculates the points for LINTGT
3214     *
3215     * @param points - OUT - the client points, also used for the returned points.
3216     * @param linetype the line type.
3217     * @param vblCounter the number of points required to display the symbol
3218     */
3219    protected static int GetDISMLinearTargetDouble(POINT2[] points, int linetype, int vblCounter) {
3220        int counter = 0;
3221        try {
3222            int j = 0;
3223            double dMBR = lineutility.MBRDistance(points, vblCounter-4);
3224            //end declarations
3225
3226            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
3227            if (dMBR / 20 > maxLength * DPIScaleFactor) {
3228                dMBR = 20 * maxLength * DPIScaleFactor;
3229            }
3230            if (dMBR / 20 < minLength * DPIScaleFactor) {
3231                dMBR = 20 * minLength * DPIScaleFactor;
3232            }
3233            if (dMBR < 150 * DPIScaleFactor) {
3234                dMBR = 150 * DPIScaleFactor;
3235            }
3236            if(dMBR>250 * DPIScaleFactor)
3237                dMBR=250 * DPIScaleFactor;
3238            
3239            for (j = 0; j < vblCounter - 4; j++) {
3240                points[counter].style = 0;
3241                counter++;
3242            }
3243            //for(j=vblCounter-4;j<vblCounter;j++)
3244              //  points[j]=new POINT2();
3245
3246            points[counter - 1].style = 5;
3247
3248            points[counter] = lineutility.ExtendTrueLinePerpDouble(points[0], points[1], points[0], dMBR / 20, 0);
3249            counter++;
3250            points[counter] = lineutility.ExtendTrueLinePerpDouble(points[0], points[1], points[0], -dMBR / 20, 5);
3251            counter++;
3252            points[counter] = lineutility.ExtendTrueLinePerpDouble(points[vblCounter - 5], points[vblCounter - 6], points[vblCounter - 5], dMBR / 20, 0);
3253            counter++;
3254            points[counter] = lineutility.ExtendTrueLinePerpDouble(points[vblCounter - 5], points[vblCounter - 6], points[vblCounter - 5], -dMBR / 20, 5);
3255            counter++;
3256            if (linetype == (long) TacticalLines.FPF) {
3257                points[0].style = 6;
3258            }
3259        } catch (Exception exc) {
3260            ErrorLogger.LogException(_className ,"GetDISMLinearTargetDouble",
3261                    new RendererException("Failed inside GetDISMLinearTargetDouble", exc));
3262        }
3263        return counter;
3264    }
3265    /**
3266     * Calculates the points for BLOCK, MNFLDBLK
3267     *
3268     * @param points - OUT - the client points, also used for the returned points.
3269     * @param linetype the line type.
3270     */
3271    protected static void GetDISMBlockDouble2(POINT2[] points,
3272            int linetype) {
3273        try {
3274            POINT2 ptRelative = new POINT2(points[2]);
3275            
3276            POINT2 midpt = lineutility.MidPointDouble(points[0], points[1], 0);
3277            int j = 0;
3278            points[0].style = 0;
3279            points[1].style = 5;
3280            points[2] = new POINT2(midpt);
3281            points[3] = new POINT2(ptRelative);
3282            if (linetype == (long) TacticalLines.BLOCK) {
3283                points[2].style = 14;
3284            }
3285            if (linetype == (long) TacticalLines.FPF) {
3286                points[2].style = 6;
3287            }
3288        } catch (Exception exc) {
3289            ErrorLogger.LogException(_className ,"GetDISMBlockDouble2",
3290                    new RendererException("Failed inside GetDISMBlockDouble2", exc));
3291        }
3292    }
3293    /**
3294     * Calculates the points for PAA_RECTANGULAR.
3295     *
3296     * @param points - OUT - the client points, also used for the returned points.
3297     * @param linetype the line type.
3298     */
3299    protected static void GetDISMPAADouble(POINT2[] points, int linetype) {
3300        try {
3301            POINT2 pt0 = new POINT2(points[0]);
3302            POINT2 pt1 = new POINT2(points[1]);
3303            POINT2 pt2 = new POINT2();
3304            POINT2 pt3 = new POINT2();
3305            POINT2 midpt = new POINT2();
3306            double d = lineutility.CalcDistanceDouble(pt0, pt1);
3307
3308            midpt = lineutility.MidPointDouble(pt0, pt1, 0);
3309            pt2 = lineutility.ExtendTrueLinePerpDouble(pt0, pt1, midpt, d / 2, 0);
3310            pt3 = lineutility.ExtendTrueLinePerpDouble(pt0, pt1, midpt, -d / 2, 0);
3311            d = lineutility.CalcDistanceDouble(pt0, pt2);
3312            points[0] = new POINT2(pt0);
3313            points[0].style = 14;
3314            points[1] = new POINT2(pt2);
3315            points[1].style = 14;
3316            points[2] = new POINT2(pt1);
3317            points[2].style = 14;
3318            points[3] = new POINT2(pt3);
3319            points[3].style = 14;
3320            points[4] = new POINT2(pt0);
3321            points[4].style = 5;
3322        } catch (Exception exc) {
3323            ErrorLogger.LogException(_className ,"GetDISMPAADouble",
3324                    new RendererException("Failed inside GetDISMPAADouble", exc));
3325        }
3326    }
3327
3328    private static boolean ReverseDelayArc(POINT2[] points) {
3329        POINT2 pt1 = points[0];
3330        POINT2 pt2 = points[1];
3331        POINT2 pt3 = points[2];
3332
3333        float lineAngle = getAngleBetweenPoints(pt1.x, pt1.y, pt2.x, pt2.y);
3334        float curveAngle = getAngleBetweenPoints(pt2.x, pt2.y, pt3.x, pt3.y);
3335
3336        float upperBound = curveAngle + 180;
3337        return !isInRange(curveAngle, upperBound, lineAngle);
3338    }
3339
3340    private static boolean isInRange(float min, float max, float targetAngle) {
3341        targetAngle = normalizeAngle(targetAngle);
3342        min = normalizeAngle(min);
3343        max = normalizeAngle(max);
3344
3345        if (min < max) {
3346            return min <= targetAngle && targetAngle <= max;
3347        }
3348        return min <= targetAngle || targetAngle <= max;
3349
3350    }
3351
3352    private static float getAngleBetweenPoints(double x1, double y1, double x2, double y2) {
3353        return (float) Math.toDegrees(Math.atan2(y2 - y1, x2 - x1));
3354    }
3355
3356    /**
3357     * Returns an angle from 0 to 360
3358     *
3359     * @param angle the angle to normalize
3360     * @return an angle in range from 0 to 360
3361     */
3362    public static float normalizeAngle(float angle) {
3363        return (3600000 + angle) % 360;
3364    }
3365
3366    private static void DrawEndpieceDeltasDouble(POINT2 point,
3367            double iDelta1,
3368            double iDelta2,
3369            double iDelta3,
3370            double iDelta4,
3371            POINT2[] deltapoints)
3372                {
3373        try
3374        {
3375            deltapoints[0] = new POINT2(point);
3376            deltapoints[0].style = 0;
3377            deltapoints[1].x = point.x + iDelta1;
3378            deltapoints[1].y = point.y + iDelta2;
3379            deltapoints[1].style = 5;
3380            deltapoints[2] = new POINT2(point);
3381            deltapoints[2].style = 0;
3382            deltapoints[3].x = point.x + iDelta3;
3383            deltapoints[3].y = point.y + iDelta4;
3384            deltapoints[3].style = 5;
3385        } catch (Exception exc) {
3386            ErrorLogger.LogException(_className ,"DrawEndpieceDeltasDouble",
3387                    new RendererException("Failed inside DrawEndpieceDeltasDouble", exc));
3388        }
3389    }
3390    /**
3391     * Calculates the points for EASY
3392     *
3393     * @param points - OUT - the client points, also used for the returned points.
3394     * @param linetype the line type.
3395     */
3396    protected static int GetDISMEasyDouble(POINT2[] points,
3397            int linetype) {
3398        int counter = 0;
3399        try {
3400            int j = 0;
3401            POINT2[] pointsCorner = new POINT2[2];
3402            POINT2[] rectpts = new POINT2[4];
3403            POINT2[] savepoints = new POINT2[3];
3404            POINT2[] deltapoints1 = new POINT2[4];
3405            POINT2[] deltapoints2 = new POINT2[4];
3406            ref<double[]> iDeltaX = new ref(), iDeltaY = new ref();
3407            int bPointsRight = 0;
3408            //end declarations
3409
3410            for (j = 0; j < 3; j++) {
3411                savepoints[j] = points[j];
3412            }
3413            lineutility.InitializePOINT2Array(pointsCorner);
3414            lineutility.InitializePOINT2Array(rectpts);
3415            lineutility.InitializePOINT2Array(deltapoints1);
3416            lineutility.InitializePOINT2Array(deltapoints2);
3417
3418            DrawOpenRectangleDouble(savepoints, pointsCorner, rectpts);
3419            for (j = 0; j < 4; j++) {
3420                points[counter] = new POINT2(rectpts[j]);
3421                points[counter].style = 0;
3422                counter++;
3423            }
3424            points[counter - 1].style = 5;
3425
3426            bPointsRight = DetermineDirectionDouble(savepoints);
3427
3428            CalcEndpieceDeltasDouble(savepoints, iDeltaX, iDeltaY, CONST_PI / 4);
3429
3430            if ((savepoints[0].y - savepoints[1].y) < 0) {// Point0 is higher than Point1
3431                if (bPointsRight != 0) {// figure opens to the right
3432                    DrawEndpieceDeltasDouble(savepoints[0],
3433                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints1);
3434                    DrawEndpieceDeltasDouble(savepoints[1],
3435                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints2);
3436                } else {// figure opens to the left
3437                    DrawEndpieceDeltasDouble(savepoints[0],
3438                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints1);
3439                    DrawEndpieceDeltasDouble(savepoints[1],
3440                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints2);
3441                }
3442            } else {// Point0 is lower than Point1
3443                if (bPointsRight != 0) {// figure opens to the right
3444                    DrawEndpieceDeltasDouble(savepoints[0],
3445                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints1);
3446                    DrawEndpieceDeltasDouble(savepoints[1],
3447                            iDeltaY.value[0], -iDeltaX.value[0], iDeltaX.value[0], iDeltaY.value[0], deltapoints2);
3448                } else {// figure opens to the left
3449                    DrawEndpieceDeltasDouble(savepoints[0],
3450                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints1);
3451                    DrawEndpieceDeltasDouble(savepoints[1],
3452                            iDeltaX.value[0], iDeltaY.value[0], iDeltaY.value[0], -iDeltaX.value[0], deltapoints2);
3453                }
3454            }
3455
3456            points[counter] = new POINT2(deltapoints1[1]);
3457            points[counter].style = 9;
3458            counter++;
3459            points[counter] = new POINT2(deltapoints1[0]);
3460            points[counter].style = 9;
3461            counter++;
3462            points[counter] = new POINT2(deltapoints1[3]);
3463            points[counter].style = 9;
3464            counter++;
3465            points[counter] = new POINT2(deltapoints1[3]);
3466            points[counter].style = 10;
3467            counter++;
3468
3469            points[counter] = new POINT2(deltapoints2[1]);
3470            points[counter].style = 9;
3471            counter++;
3472            points[counter] = new POINT2(deltapoints2[0]);
3473            points[counter].style = 9;
3474            counter++;
3475            points[counter] = new POINT2(deltapoints2[3]);
3476            points[counter].style = 9;
3477            counter++;
3478            points[counter] = new POINT2(deltapoints2[3]);
3479            points[counter].style = 10;
3480            counter++;
3481
3482        } catch (Exception exc) {
3483            ErrorLogger.LogException(_className ,"GetDISMEasyDouble",
3484                    new RendererException("Failed inside GetDISMEasyDouble", exc));
3485        }
3486        return counter;
3487    }
3488    
3489    /**
3490     * Calculates the points for AMBUSH
3491     *
3492     * @param pLinePoints - OUT - the client points, also used for the returned points.
3493     */
3494    protected static int AmbushPointsDouble(POINT2[] pLinePoints)
3495    {
3496        int counter=0;
3497        try
3498        {
3499            POINT2[] pts=new POINT2[3];
3500            POINT2[] savepoints=new POINT2[3];
3501            // calculate midpoint
3502            POINT2 ptMid=new POINT2();
3503            double dRadius=0,d=0;
3504            double dAngle1=0;
3505            double dAngle1c=0;
3506            double dAngle2c=0;
3507            double dAngle12c=0;
3508            double dAngle0=0;
3509            POINT2[] arcpoints=new POINT2[17];
3510            double dAngleTic = 0;
3511            double dDeltaX1=0, dDeltaY1=0;
3512            double dDeltaX2 = 0;
3513            double dDeltaY2 = 0;
3514            POINT2 ptCenter=new POINT2();
3515            int j=0,i=0;
3516            double iArrowLength=0;
3517
3518            for(j=0;j<3;j++)
3519            {
3520                savepoints[j]=new POINT2(pLinePoints[j]);
3521            }
3522
3523            //initialize the pOINT2 arrays
3524            lineutility.InitializePOINT2Array(arcpoints);
3525            lineutility.InitializePOINT2Array(pts);
3526
3527            ptMid.x = (savepoints[1].x + savepoints[2].x) / 2;
3528            ptMid.y = (savepoints[1].y + savepoints[2].y) / 2;
3529
3530            // calculate arc center
3531            dRadius = Math.sqrt( (ptMid.x-savepoints[2].x) * (ptMid.x-savepoints[2].x) +
3532                (ptMid.y-savepoints[2].y) * (ptMid.y-savepoints[2].y) );
3533
3534            // add section M. Deutch 8-25-05
3535            //consider the other possiblity for a center
3536            double dRadius2 = Math.sqrt( (ptMid.x-savepoints[1].x) * (ptMid.x-savepoints[1].x) +
3537                (ptMid.y-savepoints[1].y) * (ptMid.y-savepoints[1].y) );
3538
3539            dAngle1 = Math.atan2(savepoints[1].y - savepoints[2].y, savepoints[1].x - savepoints[2].x);
3540            ptCenter.x = ptMid.x + Math.cos(dAngle1 - CONST_PI / 2) * dRadius;
3541            ptCenter.y = ptMid.y + Math.sin(dAngle1 - CONST_PI / 2) * dRadius;
3542
3543            //added section M. Deutch 8-25-05
3544            //consider the other possibility for a center if the points were reversed
3545            double dAngle2 = Math.atan2(savepoints[2].y - savepoints[1].y, savepoints[2].x - savepoints[1].x);
3546            POINT2 ptCenter2=new POINT2();
3547            ptCenter2.x = ptMid.x + Math.cos(dAngle2 - CONST_PI / 2) * dRadius;
3548            ptCenter2.y = ptMid.y + Math.sin(dAngle2 - CONST_PI / 2) * dRadius;
3549            double dist=lineutility.CalcDistanceDouble(savepoints[0],ptCenter);
3550            double dist2=lineutility.CalcDistanceDouble(savepoints[0],ptCenter2);
3551            //if the distance to the new center is closer
3552            //then reverse the arc endpoints
3553            if(dist2>dist)
3554            {
3555                //POINT2 ptTemp=new POINT2();
3556                POINT2 ptTemp=new POINT2(savepoints[1]);
3557                savepoints[1]=new POINT2(savepoints[2]);
3558                savepoints[2]=new POINT2(ptTemp);
3559                ptCenter=new POINT2(ptCenter2);
3560                dAngle1=dAngle2;
3561            }
3562            //end section
3563
3564            dRadius = Math.sqrt ( (savepoints[1].x-ptCenter.x) * (savepoints[1].x-ptCenter.x) +
3565                (savepoints[1].y-ptCenter.y) * (savepoints[1].y-ptCenter.y) );
3566
3567            // draw arc
3568            ArcApproximationDouble ((ptCenter.x - dRadius),(ptCenter.y - dRadius),
3569                (ptCenter.x + dRadius),( ptCenter.y + dRadius),
3570                savepoints[2].x, savepoints[2].y, savepoints[1].x, savepoints[1].y, arcpoints);
3571
3572            for(j=0;j<17;j++)
3573            {
3574                pLinePoints[counter]=new POINT2(arcpoints[j]);
3575                pLinePoints[counter].style=0;
3576                counter++;
3577            }
3578            pLinePoints[counter-1].style=5;
3579
3580            // draw line out from arc to point 1
3581            pts[0] = new POINT2(savepoints[0]);
3582            dAngle1c = Math.atan2(ptCenter.y - savepoints[1].y, ptCenter.x - savepoints[1].x);
3583            dAngle2c = Math.atan2(ptCenter.y - savepoints[2].y, ptCenter.x - savepoints[2].x);
3584            dAngle12c = (dAngle1c + dAngle2c) / 2;
3585            if ( (dAngle1c > 0) && (dAngle2c < 0) )
3586            {
3587                pts[1].x = ptCenter.x + Math.cos(dAngle12c) * dRadius;
3588                pts[1].y = ptCenter.y + Math.sin(dAngle12c) * dRadius;
3589            }
3590            else
3591            {
3592                pts[1].x = ptCenter.x - Math.cos(dAngle12c) * dRadius;
3593                pts[1].y = ptCenter.y - Math.sin(dAngle12c) * dRadius;
3594            }
3595            pLinePoints[counter]=new POINT2(pts[0]);
3596            pLinePoints[counter].style=0;counter++;
3597            pLinePoints[counter]=new POINT2(pts[1]);
3598            pLinePoints[counter].style=5;counter++;
3599
3600
3601            // draw arrowhead on end of line
3602            dAngle0 = Math.atan2(pts[1].y - savepoints[0].y, pts[1].x - savepoints[0].x);
3603            iArrowLength =(
3604                (
3605                Math.sqrt // height of graphic
3606                (
3607                (savepoints[1].x-savepoints[2].x) * (savepoints[1].x-savepoints[2].x) +
3608                (savepoints[1].y-savepoints[2].y) * (savepoints[1].y-savepoints[2].y)
3609                ) +
3610                Math.sqrt // length of graphic
3611                (
3612                (savepoints[0].x-ptMid.x) * (savepoints[0].x-ptMid.x) +
3613                (savepoints[0].y-ptMid.y) * (savepoints[0].y-ptMid.y)
3614                )
3615                ) / 20);
3616
3617            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
3618            if((double)iArrowLength>maxLength * DPIScaleFactor)
3619                iArrowLength=(int)maxLength * DPIScaleFactor;
3620            if((double)iArrowLength<minLength * DPIScaleFactor)
3621                iArrowLength=(int)minLength * DPIScaleFactor;
3622
3623            pts[0].x = savepoints[0].x + Math.cos(dAngle0 + CONST_PI / 6) * iArrowLength;
3624            pts[0].y = savepoints[0].y + Math.sin(dAngle0 + CONST_PI / 6) * iArrowLength;
3625            pts[1] = savepoints[0];
3626            pts[2].x = savepoints[0].x + Math.cos(dAngle0 - CONST_PI / 6) * iArrowLength;
3627            pts[2].y = savepoints[0].y + Math.sin(dAngle0 - CONST_PI / 6) * iArrowLength;
3628            for(j=0;j<3;j++)
3629            {
3630                pLinePoints[counter]=new POINT2(pts[j]);
3631                pLinePoints[counter].style=0;
3632                counter++;
3633            }
3634            pLinePoints[counter-1].style=5;
3635
3636            // draw lines out from arc toward back of graphic
3637            d=dRadius/3;
3638            if(d>maxLength * DPIScaleFactor)
3639                    d=maxLength * DPIScaleFactor;
3640            if(d<minLength * DPIScaleFactor)
3641                    d=minLength * DPIScaleFactor;
3642
3643            dAngleTic = CONST_PI / 18; // angle in radians between tic-marks
3644            dDeltaX2 = Math.cos(dAngle1 + CONST_PI / 2) * d;
3645            dDeltaY2 = Math.sin(dAngle1 + CONST_PI / 2) * d;
3646            for (i=0; i<8; i++)
3647            {
3648                dAngle1c += dAngleTic;
3649                dDeltaX1 = Math.cos(dAngle1c) * dRadius;
3650                dDeltaY1 = Math.sin(dAngle1c) * dRadius;
3651                pts[0].x = ptCenter.x - dDeltaX1;
3652                pts[0].y = ptCenter.y - dDeltaY1;
3653                pLinePoints[counter]=new POINT2(pts[0]);
3654                pLinePoints[counter].style=0;
3655                counter++;
3656                pts[1].x = pts[0].x - dDeltaX2;
3657                pts[1].y = pts[0].y - dDeltaY2;
3658                pLinePoints[counter]=new POINT2(pts[1]);
3659                pLinePoints[counter].style=5;
3660                counter++;
3661            }
3662        }
3663        catch(Exception exc)
3664        {
3665            ErrorLogger.LogException(_className ,"AmbushPointsDouble",
3666                    new RendererException("Failed inside AmbushPointsDouble", exc));
3667        }
3668        return counter;
3669    }
3670}