001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005
006package armyc2.c5isr.JavaLineArray;
007import armyc2.c5isr.JavaTacticalRenderer.TGLight;
008import armyc2.c5isr.renderer.utilities.ErrorLogger;
009import armyc2.c5isr.renderer.utilities.RendererException;
010
011/**
012 * A class for calculating flot ellipses. Some functions use the same array for the client points
013 * and the return points. The caller allocates a size large enough to hold the return points.
014 *
015 */
016public final class flot {
017    private static final String _className = "flot";
018    protected static int GetAnchorageFlotSegment(int[] vbPoints,
019            int x1,
020            int y1,
021            int x2,
022            int y2,
023            int segment,
024            double floatDiameter,
025            int[] points,
026            ref<int[]>bFlip,
027            ref<int[]>lDirection,
028            ref<int[]>lLastDirection)
029    {
030        int lSegCounter = 0;
031        try {
032            int j = 0;
033            double dDistance = 0;
034            int nNumSegs = 0, m = 0;
035            int lLocx = 0, lLocy = 0;
036            double dAngle = 0;
037            int[] arcPoints = new int[30];
038            double dRemainder = 0;
039            double dNum = 0, dDen = 0;
040
041            if (segment == 0 && vbPoints[0] >= vbPoints[2]) {
042                bFlip.value[0] = 1;//TRUE;
043            }
044            if (segment == 0 && vbPoints[0] < vbPoints[2]) {
045                bFlip.value[0] = 0;//FALSE;
046            }
047
048            dNum = vbPoints[2 * segment + 3] - vbPoints[2 * segment + 1];
049            dDen = vbPoints[2 * segment + 2] - vbPoints[2 * segment];
050
051            //for some reason this did not blow up before I put the if/else
052            //instead it would assign pi/2 to dAngle when dDen=0
053            if (dDen == 0) {
054                dAngle = Math.PI / 2;
055            } else {
056                dAngle = Math.abs(Math.atan(dNum / dDen));
057            }
058
059            //convert to degrees
060            dAngle = (180 / Math.PI) * dAngle;
061
062            if (vbPoints[2 * segment + 0] <= vbPoints[2 * segment + 2] && vbPoints[2 * segment + 1] >= vbPoints[2 * segment + 3]) {
063                dAngle = 90 - dAngle;
064            } else if (vbPoints[2 * segment + 0] <= vbPoints[2 * segment + 2] && vbPoints[2 * segment + 1] <= vbPoints[2 * segment + 3]) {
065                dAngle = dAngle + 90;
066            } else if (vbPoints[2 * segment + 0] >= vbPoints[2 * segment + 2] && vbPoints[2 * segment + 1] <= vbPoints[2 * segment + 3]) {
067                dAngle = 270 - dAngle;
068            } else if (vbPoints[2 * segment + 0] >= vbPoints[2 * segment + 2] && vbPoints[2 * segment + 1] >= vbPoints[2 * segment + 3]) {
069                dAngle = 270 + dAngle;
070            }
071
072            dDistance = lineutility.CalcDistance2(x1, y1, x2, y2);
073
074            nNumSegs = (int) (dDistance / floatDiameter);
075            if (nNumSegs % 2 == 0) {
076                nNumSegs -= 1;
077            }
078
079            dRemainder = nNumSegs * floatDiameter - dDistance;
080            dDistance = dDistance + dRemainder;
081
082            //calculate the default dAngle here
083            //also establish the lDirection
084            if (vbPoints[2 * segment] >= vbPoints[2 * segment + 2]) {
085                dAngle = dAngle + 90;
086                lDirection.value[0] = 1;
087            } else {
088                dAngle = dAngle - 90;
089                lDirection.value[0] = 0;
090            }
091
092            if (segment > 0 && lDirection.value[0] != lLastDirection.value[0]) {
093                //'toggle bflip if the lDirection changes
094                if (bFlip.value[0] == 1) {
095                    bFlip.value[0] = 0;
096                } else {
097                    bFlip.value[0] = 1;
098                }
099            }
100
101            //'flip the segment if necessary
102            if (bFlip.value[0] == 1) {
103                dAngle = dAngle + 180;
104            }
105
106            //for( m = 0; m< nNumSegs;m++)
107            for (m = 0; m < nNumSegs; m += 2) //get evry other flot only for anchorage
108            {
109                lLocx = (int) (x1 + (m + 0.5) * (x2 - x1) * floatDiameter / dDistance);
110                lLocy = (int) (y1 + (m + 0.5) * (y2 - y1) * floatDiameter / dDistance);
111
112                CalcAnglePoints(lLocx, lLocy, dAngle, arcPoints, dDistance / ((double) nNumSegs * 2d));
113
114                for (j = 0; j < 30; j++) {
115                    points[lSegCounter] = arcPoints[j];
116                    lSegCounter++;
117                }
118            }
119
120            //save last lDirection
121            lLastDirection.value[0] = lDirection.value[0];
122            arcPoints = null;
123        } catch (Exception exc) {
124            ErrorLogger.LogException(_className ,"GetAnchorageFlotSegment",
125                    new RendererException("Failed inside GetAnchorageFlotSegment", exc));
126        }
127        return lSegCounter;
128    }
129
130    protected static int GetAnchorageCountDouble(POINT2[] vbPoints, double floatDiameter, int numPts) {
131        int lTotalpts = 0;
132        try {
133            //declarations
134            int j = 0, lNumSegs = 0;
135            double dDistance = 0;
136            POINT2[] vbPoints2 = null;
137            //end declarations
138
139            vbPoints2 = new POINT2[numPts];
140            for (j = 0; j < numPts; j++) {
141                vbPoints2[j] = new POINT2(vbPoints[j]);
142            }
143            for (j = 0; j < numPts - 1; j++) {
144                dDistance = lineutility.CalcDistanceDouble(vbPoints2[j], vbPoints2[j + 1]);
145                lNumSegs = (int) (dDistance / floatDiameter);
146                if (lNumSegs > 0) {
147                    lTotalpts += lNumSegs * 12; //10 points per flot + 2 end points for line
148                } else {
149                    lTotalpts += 1;
150                }
151            }
152            lTotalpts += 1;
153
154        } catch (Exception exc) {
155            ErrorLogger.LogException(_className ,"GetAnchorageCountDouble",
156                    new RendererException("Failed inside GetAnchorageCountDouble", exc));
157        }
158        return (lTotalpts);
159    }
160    protected static int GetFlotCount2Double(TGLight tg, POINT2[] vbPoints, int numPts) {
161        int lTotalpts = 0;
162        try {
163            int j = 0, lNumSegs = 0;
164            double dDistance = 0, dIncrement = 0;
165            int nFactor = 10;
166
167            switch (tg.get_LineType()) {
168                case TacticalLines.WF:
169                case TacticalLines.UWF:
170                    dIncrement = arraysupport.getScaledSize(40, tg.get_LineThickness());
171                    break;
172                case TacticalLines.WFG:
173                    dIncrement = arraysupport.getScaledSize(60, tg.get_LineThickness());
174                    nFactor = 17;
175                    break;
176                case TacticalLines.WFY:
177                    dIncrement = arraysupport.getScaledSize(60, tg.get_LineThickness());
178                    nFactor = 20;
179                    break;
180                default:
181                    dIncrement = arraysupport.getScaledSize(20, tg.get_LineThickness());
182                    break;
183            }
184
185            for (j = 0; j < numPts - 1; j++) {
186                dDistance = lineutility.CalcDistanceDouble(vbPoints[j], vbPoints[j + 1]);
187                lNumSegs = (int) (dDistance / dIncrement);   //flot diameter is 20
188                lTotalpts = lTotalpts + lNumSegs * nFactor; //10 points per flot
189                switch (tg.get_LineType()) {
190                    case TacticalLines.WFG:
191                    case TacticalLines.WFY:
192                        if (lNumSegs == 0) {
193                            lTotalpts += 2;     //add 2 points for the line segment
194                        }
195                        break;
196                    default:
197                        break;
198                }
199
200            }
201        } catch (Exception exc)
202        {
203            ErrorLogger.LogException(_className ,"GetFlotCount2Double",
204                    new RendererException("Failed inside GetFlotCount2Double", exc));
205        }
206        return lTotalpts;
207    }
208
209    protected static int GetFlot2Double(TGLight tg, POINT2[] vbPoints2, int numPts) {
210        int lFlotCounter = 0;
211        try {
212            int lineType = tg.get_LineType();
213            int j = 0, k = 0, l = 0;
214            int x1 = 0, y1 = 0;
215            int x2 = 0, y2 = 0, z2 = 0;
216            int numSegPts = -1;
217            int z = 0, lFlotCount = 0;
218            int lNumSegs = 0;
219            double dDistance = 0;
220            int[] vbPoints = null;
221            int[] points = null;
222            double dIncrement = 0;
223            POINT2[] style10Points = null;
224            int style10Counter = 0;
225            POINT2 pt0 = new POINT2(), pt1 = new POINT2(), pt2 = new POINT2();
226            POINT2 crossPt1 = new POINT2(), crossPt2 = new POINT2();
227            ref<int[]> bFlip = new ref();
228            ref<int[]> lDirection = new ref();
229            ref<int[]> lLastDirection = new ref();
230
231            bFlip.value=new int[1];
232            lDirection.value=new int[1];
233            lLastDirection.value=new int[1];
234            bFlip.value[0] = -1;
235            lDirection.value[0] = -1;
236            lLastDirection.value[0] = -1;
237            lFlotCount = GetFlotCount2Double(tg, vbPoints2, numPts);
238            if (lFlotCount <= 0) {
239                return 0;
240            }
241
242            style10Points = new POINT2[lFlotCount];
243            lineutility.InitializePOINT2Array(style10Points);
244            vbPoints = new int[2 * numPts];
245            switch (lineType) {
246                case TacticalLines.WF:
247                case TacticalLines.UWF:
248                    dIncrement = arraysupport.getScaledSize(40, tg.get_LineThickness());
249                    break;
250                case TacticalLines.WFG:
251                case TacticalLines.WFY:
252                    dIncrement = arraysupport.getScaledSize(60, tg.get_LineThickness());
253                    break;
254                default:
255                    dIncrement = arraysupport.getScaledSize(20, tg.get_LineThickness());
256                    break;
257            }
258            for (j = 0; j < numPts; j++)
259            {
260                vbPoints[k] = (int) vbPoints2[j].x;
261                k++;
262                vbPoints[k] = (int) vbPoints2[j].y;
263                k++;
264            }
265            k = 0;
266            //assume caller has dimensioned flotppoints
267            j = 0;
268            //every lSegment has 2 points
269            for (l = 0; l < numPts - 1; l++)
270            {
271                dDistance = lineutility.CalcDistance2(vbPoints[2 * l], vbPoints[2 * l + 1], vbPoints[2 * l + 2], vbPoints[2 * l + 3]);
272                lNumSegs = (int) (dDistance / dIncrement);
273                if (lNumSegs > 0) {
274                    points = new int[lNumSegs * 30];
275                    numSegPts = GetFlotSegment2(tg, vbPoints, l, points, bFlip, lDirection, lLastDirection);
276                    for (j = 0; j < numSegPts; j++) {
277                        x1 = points[k];
278                        y1 = points[k + 1];
279                        z = points[k + 2];
280                        pt0.x = x1;
281                        pt0.y = y1;
282                        pt0.style = z;
283                        if (j < numSegPts - 1) {        //used by WFZ, WFY only
284                            x2 = points[k + 3];
285                            y2 = points[k + 4];
286                            z2 = points[k + 5];
287                            pt1.x = x2;
288                            pt1.y = y2;
289                            pt1.style = z2;
290                        }
291                        k += 3;
292                        if (lFlotCounter < lFlotCount) {
293                            vbPoints2[lFlotCounter].x = x1;
294                            vbPoints2[lFlotCounter].y = y1;
295                            switch (lineType) {
296                                case TacticalLines.WF:
297                                case TacticalLines.WFG:
298                                case TacticalLines.WFY:
299                                    if ((lFlotCounter + 1) % 10 == 0) {
300                                        vbPoints2[lFlotCounter].style = 10;
301                                        //style10Points are used by WFG and WFY for the mid-segment features
302                                        if (j < numSegPts - 1) {
303                                            style10Points[style10Counter] = new POINT2(vbPoints2[lFlotCounter]);
304                                            style10Points[style10Counter].style = 0;
305                                            style10Counter++;
306                                            if (j < numSegPts - 2)
307                                            {
308                                                if (lineType == TacticalLines.WFG) {
309                                                    pt2 = new POINT2(style10Points[style10Counter - 1]);
310                                                    style10Points[style10Counter++] = lineutility.ExtendAlongLineDouble(pt2, pt1, arraysupport.getScaledSize(10, tg.get_LineThickness()), 5);
311                                                    style10Points[style10Counter++] = lineutility.ExtendAlongLineDouble(pt2, pt1, arraysupport.getScaledSize(20, tg.get_LineThickness()), 20);
312                                                    style10Points[style10Counter++] = lineutility.ExtendAlongLineDouble(pt2, pt1, arraysupport.getScaledSize(30, tg.get_LineThickness()), 0);
313                                                    style10Points[style10Counter++] = lineutility.ExtendAlongLineDouble(pt2, pt1, arraysupport.getScaledSize(70, tg.get_LineThickness()), 5);
314                                                }
315                                                if (lineType == TacticalLines.WFY) {
316                                                    pt2 = new POINT2(style10Points[style10Counter - 1]);
317                                                    style10Points[style10Counter++] = lineutility.ExtendAlongLineDouble(pt2, pt1, arraysupport.getScaledSize(10, tg.get_LineThickness()), 5);   //pt before 1st break
318                                                    style10Points[style10Counter++] = lineutility.ExtendAlongLineDouble(pt2, pt1, arraysupport.getScaledSize(15, tg.get_LineThickness()), 0);   //1st pt after 1st break;
319                                                    crossPt1 = lineutility.ExtendDirectedLine(style10Points[style10Counter - 1], pt1, style10Points[style10Counter - 1], 3, arraysupport.getScaledSize(5, tg.get_LineThickness()), 0);
320                                                    style10Points[style10Counter++] = lineutility.ExtendAlongLineDouble(pt2, pt1, arraysupport.getScaledSize(25, tg.get_LineThickness()), 5);   //2nd point after 1st break;
321                                                    crossPt2 = lineutility.ExtendDirectedLine(style10Points[style10Counter - 1], pt1, style10Points[style10Counter - 1], 2,  arraysupport.getScaledSize(5, tg.get_LineThickness()), 5);
322                                                    style10Points[style10Counter++] = new POINT2(crossPt1);
323                                                    style10Points[style10Counter++] = new POINT2(crossPt2);
324                                                    style10Points[style10Counter++] = lineutility.ExtendAlongLineDouble(pt2, pt1, arraysupport.getScaledSize(30, tg.get_LineThickness()), 0);   //1st pt after 2nd break
325                                                    style10Points[style10Counter++] = lineutility.ExtendAlongLineDouble(pt2, pt1, arraysupport.getScaledSize(60, tg.get_LineThickness()), 5);   //2nd pt after 2nd break
326                                                }
327                                            }
328                                        } else {
329                                            pt2.x = vbPoints[2 * l];
330                                            pt2.y = vbPoints[2 * l + 1];
331                                            pt2.style = 0;
332                                            style10Points[style10Counter++] = new POINT2(pt2);
333                                            style10Points[style10Counter++] = lineutility.ExtendAlongLineDouble(pt2, pt1, arraysupport.getScaledSize(40, tg.get_LineThickness()), 5);
334
335                                            pt2.x = vbPoints[2 * l + 2];
336                                            pt2.y = vbPoints[2 * l + 3];
337                                            pt2.style = 5;
338                                            style10Points[style10Counter] = new POINT2(vbPoints2[lFlotCounter]);
339                                            style10Points[style10Counter++].style = 0;
340                                            style10Points[style10Counter++] = new POINT2(pt2);
341                                        }
342                                    } else {
343                                        vbPoints2[lFlotCounter].style = 9;
344                                    }
345                                    break;
346                                default:
347                                    vbPoints2[lFlotCounter].style = 0;
348                                    break;
349                            }
350                            lFlotCounter++;
351                        }
352                    }
353                    switch (lineType)
354                    {
355                        case TacticalLines.WF:
356                        case TacticalLines.WFG:
357                        case TacticalLines.WFY:
358                            vbPoints2[lFlotCounter - 1].style = 10;
359                            break;
360                        default:
361                            vbPoints2[lFlotCounter - 1].style = 5;
362                            break;
363                    }
364                    k = 0;
365                    points = null;
366                }//end if numsegs>0
367                else
368                {
369                    style10Points[style10Counter].x = vbPoints[2 * l];
370                    style10Points[style10Counter].y = vbPoints[2 * l + 1];
371                    style10Points[style10Counter++].style = 0;
372                    style10Points[style10Counter].x = vbPoints[2 * l + 2];
373                    style10Points[style10Counter].y = vbPoints[2 * l + 3];
374                    style10Points[style10Counter++].style = 5;
375                }
376            }
377
378
379            //some do not need additional processing
380            switch (lineType) {
381                case TacticalLines.WFG:
382                case TacticalLines.WFY:
383                    break;
384                default:
385                    vbPoints = null;
386                    return lFlotCounter;
387            }
388            for (j = 0; j < style10Counter; j++)
389            {
390                vbPoints2[lFlotCounter++] = new POINT2(style10Points[j]);
391            }
392
393        } catch (Exception exc) {
394            ErrorLogger.LogException(_className ,"GetFlot2Double",
395                    new RendererException("Failed inside GetFlot2Double", exc));
396        }
397        return lFlotCounter;
398    }
399
400    private static int GetFlotSegment2(TGLight tg,
401            int[] vbPoints,
402            int segment,
403            int[] points,
404            ref<int[]> bFlip,
405            ref<int[]> lDirection,
406            ref<int[]> lLastDirection) {
407        int nNumSegs = 0;
408        try {
409            int lineType = tg.get_LineType();
410            int j = 0;
411            double dDistance = 0;
412            int m = 0;
413            int lLocx = 0, lLocy = 0;
414            int lSegCounter = 0;
415            double dAngle = 0;
416            int[] arcpoints = new int[30];
417            double dRemainder = 0;
418            double dNum = 0, dDen = 0;
419            double dIncrement = 0;
420            //end declarations
421
422            switch (lineType) {
423                case TacticalLines.WF:
424                case TacticalLines.UWF:
425                    dIncrement = arraysupport.getScaledSize(40, tg.get_LineThickness());
426                    break;
427                case TacticalLines.WFG:
428                case TacticalLines.WFY:
429                    dIncrement = arraysupport.getScaledSize(60, tg.get_LineThickness());
430                    break;
431                case TacticalLines.OCCLUDED:
432                case TacticalLines.UOF:
433                    dIncrement = arraysupport.getScaledSize(50, tg.get_LineThickness());
434                    break;
435                case TacticalLines.SF:
436                case TacticalLines.USF:
437                case TacticalLines.SFG:
438                case TacticalLines.SFY:
439                    dIncrement = arraysupport.getScaledSize(80, tg.get_LineThickness());
440                    break;
441                case TacticalLines.OFY:
442                    dIncrement = arraysupport.getScaledSize(80, tg.get_LineThickness());
443                    break;
444                default:
445                    dIncrement = arraysupport.getScaledSize(20, tg.get_LineThickness());
446                    break;
447            }
448
449            lSegCounter = 0;
450            if (segment == 0 && vbPoints[0] >= vbPoints[2])
451            {
452                if (lineType != TacticalLines.SF &&
453                        lineType != TacticalLines.USF &&
454                        lineType != TacticalLines.SFG &&
455                        lineType != TacticalLines.SFY) {
456                    bFlip.value[0] = 1;//TRUE;
457                } 
458                else
459                {
460                    bFlip.value[0] = 0;
461                }
462            }
463            if (segment == 0 && vbPoints[0] < vbPoints[2]) {
464                if (lineType !=  TacticalLines.SF &&
465                        lineType != TacticalLines.USF &&
466                        lineType != TacticalLines.SFG &&
467                        lineType != TacticalLines.SFY) {
468                    bFlip.value[0] = 0;//FALSE;
469                } else {
470                    bFlip.value[0] = 1;
471                }
472            }
473
474            dNum = vbPoints[2 * segment + 3] - vbPoints[2 * segment + 1];
475            dDen = vbPoints[2 * segment + 2] - vbPoints[2 * segment];
476
477            if (dDen == 0) {
478                dAngle = Math.PI / 2;
479            } else {
480                dAngle = Math.abs(Math.atan(dNum / dDen));
481            }
482
483            dAngle = (180 / Math.PI) * dAngle;
484
485            if (vbPoints[2 * segment + 0] <= vbPoints[2 * segment + 2] && vbPoints[2 * segment + 1] >= vbPoints[2 * segment + 3]) {
486                dAngle = 90 - dAngle;
487            } else if (vbPoints[2 * segment + 0] <= vbPoints[2 * segment + 2] && vbPoints[2 * segment + 1] <= vbPoints[2 * segment + 3]) {
488                dAngle = dAngle + 90;
489            } else if (vbPoints[2 * segment + 0] >= vbPoints[2 * segment + 2] && vbPoints[2 * segment + 1] <= vbPoints[2 * segment + 3]) {
490                dAngle = 270 - dAngle;
491            } else if (vbPoints[2 * segment + 0] >= vbPoints[2 * segment + 2] && vbPoints[2 * segment + 1] >= vbPoints[2 * segment + 3]) {
492                dAngle = 270 + dAngle;
493            }
494
495
496            dDistance = lineutility.CalcDistance2(vbPoints[2 * segment], vbPoints[2 * segment + 1], vbPoints[2 * segment + 2], vbPoints[2 * segment + 3]);
497
498            nNumSegs = (int) (dDistance / dIncrement);
499            dRemainder = nNumSegs * dIncrement - dDistance;
500            dDistance = dDistance + dRemainder;
501
502            //calculate the default dAngle here
503            //also establish the lDirection
504            if (vbPoints[2 * segment] >= vbPoints[2 * segment + 2]) {
505                dAngle = dAngle + 90;
506                lDirection.value[0] = 1;
507            } else {
508                dAngle = dAngle - 90;
509                lDirection.value[0] = 0;
510            }
511
512
513            if (segment > 0 && lDirection.value[0] != lLastDirection.value[0]) {
514                //toggle bflip if the lDirection changes
515                if (bFlip.value[0] == 1) {
516                    bFlip.value[0] = 0;
517                } else {
518                    bFlip.value[0] = 1;
519                }
520            }
521
522            //flip the segment if necessary
523            if (bFlip.value[0] == 1) {
524                dAngle = dAngle + 180;
525            }
526
527            for (m = 0; m < nNumSegs; m++) {
528                lLocx = (int) (vbPoints[2 * segment] + (m + 0.5) * (vbPoints[2 * segment + 2] - vbPoints[2 * segment]) * dIncrement / dDistance);
529                lLocy = (int) (vbPoints[2 * segment + 1] + (m + 0.5) * (vbPoints[2 * segment + 3] - vbPoints[2 * segment + 1]) * dIncrement / dDistance);
530
531                CalcAnglePoints(lLocx, lLocy, dAngle, arcpoints, arraysupport.getScaledSize(10, tg.get_LineThickness()));
532
533                for (j = 0; j < 30; j++) {
534                    points[lSegCounter] = arcpoints[j];
535                    lSegCounter = lSegCounter + 1;
536                }
537            }
538
539            //save last lDirection
540            lLastDirection.value[0] = lDirection.value[0];
541            arcpoints = null;
542        } catch (Exception exc) {
543            ErrorLogger.LogException(_className ,"GetFlotSegment2",
544                    new RendererException("Failed inside GetFlotSegment2", exc));
545        }
546        return nNumSegs * 10;
547    }
548    protected static int GetOFYCountDouble(POINT2[] pLinePoints, double interval, int numPts) {
549        int lTotalpts = 0;
550        try {
551            int j = 0, lNumSegs = 0;
552            int lNumFlots = 0, lNumSpikes = 0;
553            double dDistance = 0;
554            int nFactor = 7;
555
556            //for each segment
557            for (j = 0; j < numPts - 1; j++) {
558                dDistance = lineutility.CalcDistanceDouble(pLinePoints[j], pLinePoints[j + 1]);
559                lNumSegs = (int) (dDistance / interval);   //flot + spike = 60 pixels
560                lNumFlots = lNumSegs;
561                lNumSpikes = lNumSegs;
562                if (lNumFlots < 1) {
563                    lNumFlots = 1;
564                }
565                if (lNumSpikes < 1) {
566                    lNumSpikes = 1;
567                }
568                lTotalpts += lNumFlots * 18; //10 points per flot + 8 per line segment,
569                lTotalpts += lNumSpikes * nFactor; //3 points per spike
570            }
571            if (lTotalpts < (nFactor + 15) * numPts) {
572                lTotalpts = 25 * numPts;
573            }
574
575        } catch (Exception exc) {
576            ErrorLogger.LogException(_className ,"GetOFYCountDoulbe",
577                    new RendererException("Failed inside GetOFYCountDouble", exc));
578        }
579        return lTotalpts;
580    }
581
582    protected static int GetOccludedPointsDouble(TGLight tg,
583            POINT2[] pLinePoints,
584            int numPts) {
585        int nTotalCounter = 0;
586        try
587        {
588            int lineType = tg.get_LineType();
589            int j = 0, k = 0, lNumSegs = 0, l = 0;
590            int lNumFlots = 0, lNumSpikes = 0;
591            double dDistance = 0;
592            ref<double[]> m = new ref();
593            int lTotalPoints = 0;
594            int[] points = null;
595            POINT2[] pSpikePoints = null;
596            POINT2 pt0 = new POINT2(), tempPoint = new POINT2();
597            POINT2[] pFlotPoints = null;
598            double dSpikeSize = arraysupport.getScaledSize(20, tg.get_LineThickness()),
599                    dIncrement = arraysupport.getScaledSize(50, tg.get_LineThickness());
600            int[] vbPoints = null;
601            int nFlotCounter = 0, nSpikeCounter = 0;
602            int[] flots = null;
603            int sumOfFlots = 0;
604            double segmentLength = 0, spikeLength = 0;
605            int bolTooLong = 0;
606            double d1 = 0, d2 = 0;
607            int bolVertical = 0;
608            ref<int[]> bFlip = new ref();
609            ref<int[]> lDirection = new ref();
610            ref<int[]> lLastDirection = new ref();
611
612            m.value = new double[1];
613            bFlip.value = new int[1];
614            lDirection.value = new int[1];
615            lLastDirection.value = new int[1];
616            bFlip.value[0] = -1;
617            lDirection.value[0] = -1;
618            lLastDirection.value[0] = -1;
619            lTotalPoints = GetOccludedCountDouble(pLinePoints, numPts);
620
621            vbPoints = new int[numPts * 2];
622
623            pSpikePoints = new POINT2[3 * lTotalPoints / 13];
624            pFlotPoints = new POINT2[10 * lTotalPoints / 13];
625            int n=pSpikePoints.length;
626            //for (j = 0; j < pSpikePoints.length; j++)
627            for (j = 0; j < n; j++)
628            {
629                pSpikePoints[j] = new POINT2(pLinePoints[0]);
630                pSpikePoints[j].style = 5;
631            }
632            n=pFlotPoints.length;
633            //for (j = 0; j < pFlotPoints.length; j++)
634            for (j = 0; j < n; j++)
635            {
636                pFlotPoints[j] = new POINT2(pLinePoints[0]);
637                pFlotPoints[j].style = 5;
638            }
639            flots = new int[numPts + 1];
640            //the vbPoints long array gets used by GetFlotSegment
641            //and is based on the original points
642            for (j = 0; j < numPts; j++) {
643                vbPoints[k] = (int) pLinePoints[j].x;
644                k++;
645                vbPoints[k] = (int) pLinePoints[j].y;
646                k++;
647            }
648            k = 0;
649            //initialize flots
650            flots[0] = 0;
651            for (j = 0; j < numPts; j++)
652            {
653                flots[j + 1] = 0;
654            }
655
656            for (j = 0; j < numPts - 1; j++) {
657                bolVertical = lineutility.CalcTrueSlopeDouble(pLinePoints[j], pLinePoints[j + 1], m);
658                m.value[0] = -m.value[0];       //reverse the direction
659                dDistance = lineutility.CalcDistanceDouble(pLinePoints[j], pLinePoints[j + 1]);
660                lNumSegs = (int) (dDistance / dIncrement);   //flot(20) + spike(20) = 60 pixels
661                lNumFlots = lNumSegs;
662                lNumSpikes = lNumSegs;
663                flots[j + 1] = lNumSegs;
664
665                //get the flot segments for this line segment
666                //flot segments are 30 pixels wide with the flots in the middle, 20 pixels wide
667                k = 0;
668                if (lNumFlots > 0) {
669                    points = new int[lNumFlots * 30];
670                    GetFlotSegment2(tg, vbPoints, j, points, bFlip, lDirection, lLastDirection);
671                    for (l = 0; l < lNumFlots * 10; l++)
672                    {
673                        pFlotPoints[nFlotCounter].x = points[k];
674                        pFlotPoints[nFlotCounter].y = points[k + 1];
675                        pFlotPoints[nFlotCounter].style = 9;
676                        //straighten out the flots
677                        if ((nFlotCounter) % 10 == 0)
678                        {
679                            d1 = lineutility.CalcDistanceDouble(pLinePoints[j], pFlotPoints[nFlotCounter]);
680                            d2 = lineutility.CalcDistanceDouble(pLinePoints[j + 1], pFlotPoints[nFlotCounter]);
681                            if (d2 > d1)
682                            {
683                                pFlotPoints[nFlotCounter] = lineutility.ExtendLineDouble(pLinePoints[j + 1], pLinePoints[j], -d1);
684                            } 
685                            else
686                            {
687                                pFlotPoints[nFlotCounter] = lineutility.ExtendLineDouble(pLinePoints[j], pLinePoints[j + 1], -d2);
688                            }
689                            pFlotPoints[nFlotCounter].style = 9;
690                            if (lineType == (long) TacticalLines.UOF) {
691                                pFlotPoints[nFlotCounter].style = 0;
692                            }
693                        }
694
695                        if ((nFlotCounter + 1) % 10 == 0) {
696                            if (lineType == (long) TacticalLines.OCCLUDED ||
697                                    lineType == (long) TacticalLines.UOF) {
698                                d1 = lineutility.CalcDistanceDouble(pLinePoints[j], pFlotPoints[nFlotCounter - 9]);
699                                d2 = lineutility.CalcDistanceDouble(pLinePoints[j + 1], pFlotPoints[nFlotCounter - 9]);
700                                if (d2 > d1) {
701                                    pFlotPoints[nFlotCounter] = lineutility.ExtendLineDouble(pLinePoints[j + 1], pLinePoints[j], -d1 - dSpikeSize);
702                                } else {
703                                    pFlotPoints[nFlotCounter] = lineutility.ExtendLineDouble(pLinePoints[j], pLinePoints[j + 1], -d2 + dSpikeSize);
704                                }
705                                if (lineType == (long) TacticalLines.OCCLUDED) {
706                                    pFlotPoints[nFlotCounter].style = 10;
707                                }
708                                if (lineType == (long) TacticalLines.UOF) {
709                                    pFlotPoints[nFlotCounter].style = 5;
710                                }
711                            }
712                            if (lineType == (long) TacticalLines.SF) {
713                                pFlotPoints[nFlotCounter].style = 23;   //red fill
714                            }
715                        }
716                        k += 3;
717                        nFlotCounter++;
718                    }
719                    points = null;
720                }
721
722                //for each spike in the line segment
723                //spikes segments are 30 pixels wide with the spikes in the middle, 20 pixels wide
724                segmentLength = lineutility.CalcDistanceDouble(pLinePoints[j], pLinePoints[j + 1]);
725                for (k = 0; k < lNumSpikes - 1; k++) //get the spike
726                {
727                    //the first spike base point
728                    //has to be based on the preceding flot
729                    //if the distance goes past the end of the line segment then set the point to the
730                    //end of the line segment
731                    bolTooLong = 0;
732                    sumOfFlots = 0;
733                    for (l = 0; l <= j; l++) {
734                        sumOfFlots += flots[l];
735                    }
736
737                    //for the greatest accuracy
738                    d1 = lineutility.CalcDistanceDouble(pLinePoints[j], pFlotPoints[sumOfFlots * 10 + 10 * k]);
739                    d2 = lineutility.CalcDistanceDouble(pLinePoints[j + 1], pFlotPoints[sumOfFlots * 10 + 10 * k]);
740                    switch (lineType) {
741                        case TacticalLines.OCCLUDED:
742                        case TacticalLines.UOF:
743                            if (d2 > d1) {
744                                tempPoint = lineutility.ExtendLine2Double(pLinePoints[j + 1], pLinePoints[j], -d1 - dIncrement / 2, 0);
745                            } else {
746                                tempPoint = lineutility.ExtendLine2Double(pLinePoints[j], pLinePoints[j + 1], -d2 + dIncrement / 2, 0);
747                            }
748                            break;
749                        case TacticalLines.SF:
750                            if (d2 > d1) {
751                                tempPoint = lineutility.ExtendLine2Double(pLinePoints[j + 1], pLinePoints[j], -d1 - dIncrement / 8, 0);
752                            } else {
753                                tempPoint = lineutility.ExtendLine2Double(pLinePoints[j], pLinePoints[j + 1], -d2 + dIncrement / 8, 0);
754                            }
755                            break;
756                        default:
757                            break;
758                    }
759                    spikeLength = lineutility.CalcDistanceDouble(pLinePoints[j], tempPoint);
760                    if (spikeLength + dSpikeSize < segmentLength) {
761                        pSpikePoints[nSpikeCounter] = new POINT2(tempPoint);
762                    } else {
763                        pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
764                        bolTooLong = 1;
765                    }
766
767                    pSpikePoints[nSpikeCounter].style = 9;
768                    nSpikeCounter++;
769
770                    //extend half the spike size from the last point
771                    //do this for the accuracy of the spike point base
772                    d1 = lineutility.CalcDistanceDouble(pLinePoints[j], pSpikePoints[nSpikeCounter - 1]);
773                    d2 = lineutility.CalcDistanceDouble(pLinePoints[j + 1], pSpikePoints[nSpikeCounter - 1]);
774                    if (d1 > d2) {
775                        pt0 = lineutility.ExtendLineDouble(pLinePoints[j], pSpikePoints[nSpikeCounter - 1], dSpikeSize / 2);
776                    } else {
777                        pt0 = lineutility.ExtendLineDouble(pLinePoints[j + 1], pSpikePoints[nSpikeCounter - 1], -dSpikeSize / 2);
778                    }
779                    //the spike end (perpendicular) point
780                    if (bolTooLong == 0) {
781                        if (bolVertical != 0) //segment is not vertical
782                        {
783                            if (pLinePoints[j].x < pLinePoints[j + 1].x) {
784                                pSpikePoints[nSpikeCounter] = lineutility.ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], pt0, 2, dSpikeSize);   //extennd above the line
785                            } else {
786                                pSpikePoints[nSpikeCounter] = lineutility.ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], pt0, 3, dSpikeSize);   //extend below the line
787                            }
788                            pSpikePoints[nSpikeCounter].style = 0;
789                            nSpikeCounter++;
790                        } else //vertical segment
791                        {
792                            if (pLinePoints[j].y > pLinePoints[j + 1].y) {
793                                pSpikePoints[nSpikeCounter].x = pt0.x - dSpikeSize;
794                            } else {
795                                pSpikePoints[nSpikeCounter].x = pt0.x + dSpikeSize;
796                            }
797
798                            pSpikePoints[nSpikeCounter].y = pt0.y;
799                            nSpikeCounter++;
800                        }
801                    } else //too long
802                    {
803                        pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
804                        nSpikeCounter++;
805                    }
806                    pSpikePoints[nSpikeCounter - 1].style = 9;
807
808                    //the second spike base point. this is the third spike point
809                    if (bolTooLong == 0) {
810                        d1 = lineutility.CalcDistanceDouble(pLinePoints[j], pSpikePoints[nSpikeCounter - 2]);
811                        d2 = lineutility.CalcDistanceDouble(pLinePoints[j + 1], pSpikePoints[nSpikeCounter - 2]);
812                        if (d1 > d2) {
813                            pSpikePoints[nSpikeCounter] = lineutility.ExtendLine2Double(pLinePoints[j], pSpikePoints[nSpikeCounter - 2], dSpikeSize, 0);
814                        } else {
815                            pSpikePoints[nSpikeCounter] = lineutility.ExtendLine2Double(pLinePoints[j + 1], pSpikePoints[nSpikeCounter - 2], -dSpikeSize, 0);
816                        }
817                        if (lineType == (long) TacticalLines.OCCLUDED) {
818                            pSpikePoints[nSpikeCounter].style = 10;
819                        }
820                        if (lineType == (long) TacticalLines.UOF) {
821                            pSpikePoints[nSpikeCounter].style = 5;
822                        }
823                        if (lineType == (long) TacticalLines.SF) {
824                            pSpikePoints[nSpikeCounter].style = 24;
825                        }
826                    } else {
827                        pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
828                        pSpikePoints[nSpikeCounter].style = 5;
829                    }
830                    nSpikeCounter++;
831                }//for k= 0 to numSpikes-1
832                if (nSpikeCounter == 0) {
833                    pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j]);
834                    pSpikePoints[nSpikeCounter].style = 5;
835                    nSpikeCounter++;
836                    pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
837                    pSpikePoints[nSpikeCounter].style = 5;
838                    nSpikeCounter++;
839                    //added 6-1-05 M. Deutch
840                    pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
841                    pSpikePoints[nSpikeCounter].style = 5;
842                    nSpikeCounter++;
843                } else {
844                    pSpikePoints[nSpikeCounter] = new POINT2(pSpikePoints[nSpikeCounter - 1]);
845                    pSpikePoints[nSpikeCounter].style = 5;
846                    pSpikePoints[nSpikeCounter + 1] = new POINT2(pSpikePoints[nSpikeCounter - 1]);
847                    pSpikePoints[nSpikeCounter + 1].style = 5;
848                    pSpikePoints[nSpikeCounter + 2] = new POINT2(pSpikePoints[nSpikeCounter - 1]);
849                    pSpikePoints[nSpikeCounter + 2].style = 5;
850                    nSpikeCounter += 3;
851                }
852            }
853
854            for (j = 0; j < pLinePoints.length; j++) {
855                pLinePoints[j] = new POINT2(pSpikePoints[0]);
856                pLinePoints[j].style = 5;
857            }
858            //load the spike points into the array
859            nFlotCounter = 0;
860            nSpikeCounter = 0;
861            for (j = 0; j < lTotalPoints / 13; j++) {
862                //get the flots
863                for (k = 0; k < 10; k++) {
864                    pLinePoints[nTotalCounter] = new POINT2(pFlotPoints[j * 10 + k]);
865                    nTotalCounter++;
866                    nFlotCounter++;
867                }
868                //get the spikes
869                for (k = 0; k < 3; k++) {
870                    pLinePoints[nTotalCounter] = new POINT2(pSpikePoints[j * 3 + k]);
871                    nTotalCounter++;
872                    nSpikeCounter++;
873                }
874            }
875            n=pLinePoints.length;
876            for (j = nTotalCounter; j < n; j++) 
877            {
878                pLinePoints[j] = new POINT2(pLinePoints[nTotalCounter - 1]);
879            }
880        } catch (Exception exc) {
881            ErrorLogger.LogException(_className ,"GetOccludedPointsDouble",
882                    new RendererException("Failed inside GetOccludedPointsDouble", exc));
883        }
884        return nTotalCounter;
885    }
886
887    protected static int GetOccludedCountDouble(POINT2[] pLinePoints, int numPts) {
888        int lTotalpts = 0;
889        try {
890            int j = 0, lNumSegs = 0;
891            int lNumFlots = 0, lNumSpikes = 0;
892            double dDistance = 0;
893
894            //for each segment
895            for (j = 0; j < numPts - 1; j++) {
896                dDistance = lineutility.CalcDistanceDouble(pLinePoints[j], pLinePoints[j + 1]);
897                lNumSegs = (int) (dDistance / 50);   //flot + spike = 60 pixels
898                lNumFlots = lNumSegs;
899                lNumSpikes = lNumSegs;
900                if (lNumFlots < 1) {
901                    lNumFlots = 1;
902                }
903                if (lNumSpikes < 1) {
904                    lNumSpikes = 1;
905                }
906                lTotalpts += lNumFlots * 10; //10 points per flot,
907                lTotalpts += lNumSpikes * 3; //3 points per spike
908            }
909            if (lTotalpts < 13 * numPts) {
910                lTotalpts = 13 * numPts;
911            }
912
913            if (lTotalpts < numPts) {
914                lTotalpts = numPts;
915            }
916
917        } catch (Exception exc) {
918            ErrorLogger.LogException(_className ,"GetOccludedCountDouble",
919                    new RendererException("Failed inside GetOccludedCountDouble", exc));
920        }
921        return lTotalpts;
922    }
923
924    private static int CalcNewPoint(int locx,
925            int locY,
926            double angle,
927            int[] point,
928            double dist) {
929        try {
930            double m = 0;
931            double deltaX = 0, deltaY = 0;
932            double dx = 0, dy = 0;
933            int nQuadrant = -1;
934
935            if (angle < 0) {
936                angle = angle + 360;
937            }
938
939            if (angle > 360) {
940                angle = angle - 360;
941            }
942
943            if (0 <= angle && angle <= 90) {
944                nQuadrant = 0;
945                angle = 90 - angle;
946                angle = Math.abs(angle) * (Math.PI / 180);
947            }
948
949            if (90 < angle && angle <= 180) {
950                nQuadrant = 1;
951                angle = angle - 90;
952                angle = Math.abs(angle) * (Math.PI / 180);
953            }
954
955            if (180 < angle && angle <= 270) {
956                nQuadrant = 2;
957                angle = 270 - angle;
958                angle = Math.abs(angle) * (Math.PI / 180);
959            }
960
961            if (270 < angle && angle <= 360) {
962                nQuadrant = 3;
963                angle = angle - 270;
964                angle = Math.abs(angle) * (Math.PI / 180);
965            }
966
967            m = Math.abs(Math.tan(angle));
968            deltaX = Math.abs(dist / Math.sqrt(1 + m * m));
969            deltaY = Math.abs(m * deltaX);
970
971            switch (nQuadrant) {
972                case 0:
973                    dx = locx + deltaX;
974                    dy = locY - deltaY;
975                    break;
976                case 1:
977                    dx = locx + deltaX;
978                    dy = locY + deltaY;
979                    break;
980                case 2:
981                    dx = locx - deltaX;
982                    dy = locY + deltaY;
983                    break;
984                case 3:
985                    dx = locx - deltaX;
986                    dy = locY - deltaY;
987                    break;
988                default:
989                    break;
990            }
991
992            point[0] = (int) dx;
993            point[1] = (int) dy;
994
995        } catch (Exception exc) {
996            ErrorLogger.LogException(_className ,"CalcNewPoint",
997                    new RendererException("Failed inside CalcNewPoint", exc));
998        }
999        return 1;
1000    }
1001    /**
1002     * Calculates points for a flot segment. Assumes the caller allocated the points array
1003     * @param vbPoints the client points
1004     * @param segment the segment index
1005     * @param points the returned points
1006     * @return the number of points
1007     */
1008    private static int GetFlotSegment(int[] vbPoints,
1009            int segment,
1010            int[] points,
1011            double flotDiameter,
1012            ref<int[]> bFlip,
1013            ref<int[]> lDirection,
1014            ref<int[]> lLastDirection) {
1015        int nNumSegs = 0;
1016        try {
1017            int j = 0;
1018            double dDistance = 0;
1019            int m = 0;
1020            int lLocx = 0, lLocy = 0;
1021            int lSegCounter = 0;
1022            double dAngle = 0;
1023            int[] arcPoints = new int[30];
1024            double dRemainder = 0;
1025            double dNum = 0, dDen = 0;
1026            //end declarations
1027            lSegCounter = 0;
1028            if (segment == 0 && vbPoints[0] >= vbPoints[2]) {
1029                bFlip.value[0] = 1;//TRUE;
1030            }
1031            if (segment == 0 && vbPoints[0] < vbPoints[2]) {
1032                bFlip.value[0] = 0;//FALSE;
1033            }
1034
1035            dNum = vbPoints[2 * segment + 3] - vbPoints[2 * segment + 1];
1036            dDen = vbPoints[2 * segment + 2] - vbPoints[2 * segment];
1037
1038            //for some reason this did not blow up before I put the if/else
1039            //instead it would assign pi/2 to dAngle when dDen=0
1040            if (dDen == 0) {
1041                dAngle = Math.PI / 2;
1042                
1043            } else {
1044                dAngle = Math.abs(Math.atan(dNum / dDen));
1045
1046                //convert to degrees
1047                
1048            }
1049            dAngle = (180 / Math.PI) * dAngle;
1050
1051            if (vbPoints[2 * segment + 0] <= vbPoints[2 * segment + 2] && vbPoints[2 * segment + 1] >= vbPoints[2 * segment + 3]) {
1052                dAngle = 90 - dAngle;
1053            } else if (vbPoints[2 * segment + 0] <= vbPoints[2 * segment + 2] && vbPoints[2 * segment + 1] <= vbPoints[2 * segment + 3]) {
1054                dAngle = dAngle + 90;
1055            } else if (vbPoints[2 * segment + 0] >= vbPoints[2 * segment + 2] && vbPoints[2 * segment + 1] <= vbPoints[2 * segment + 3]) {
1056                dAngle = 270 - dAngle;
1057            } else if (vbPoints[2 * segment + 0] >= vbPoints[2 * segment + 2] && vbPoints[2 * segment + 1] >= vbPoints[2 * segment + 3]) {
1058                dAngle = 270 + dAngle;
1059            }
1060
1061            dDistance = lineutility.CalcDistance2(vbPoints[2 * segment], vbPoints[2 * segment + 1], vbPoints[2 * segment + 2], vbPoints[2 * segment + 3]);
1062
1063            nNumSegs = (int) (dDistance / flotDiameter);
1064
1065            dRemainder = nNumSegs * flotDiameter - dDistance;
1066            dDistance = dDistance + dRemainder;
1067
1068            //calculate the default dAngle here
1069            //also establish the lDirection
1070            if (vbPoints[2 * segment] >= vbPoints[2 * segment + 2]) {
1071                dAngle = dAngle + 90;
1072                lDirection.value[0] = 1;
1073            } else {
1074                dAngle = dAngle - 90;
1075                lDirection.value[0] = 0;
1076            }
1077
1078            if (segment > 0 && lDirection.value[0] != lLastDirection.value[0]) {
1079                //'toggle bflip if the lDirection changes
1080                if (bFlip.value[0] == 1) {
1081                    bFlip.value[0] = 0;
1082                    
1083                } else {
1084                    bFlip.value[0] = 1;
1085                    
1086                }
1087            }
1088
1089            //'flip the segment if necessary
1090            if (bFlip.value[0] == 1) {
1091                dAngle = dAngle + 180;
1092
1093
1094            }
1095            for (m = 0; m < nNumSegs; m++) {
1096                lLocx = (int) (vbPoints[2 * segment] + (m + 0.5) * (vbPoints[2 * segment + 2] - vbPoints[2 * segment]) * flotDiameter / dDistance);
1097                lLocy = (int) (vbPoints[2 * segment + 1] + (m + 0.5) * (vbPoints[2 * segment + 3] - vbPoints[2 * segment + 1]) * flotDiameter / dDistance);
1098
1099                CalcAnglePoints(lLocx, lLocy, dAngle, arcPoints, dDistance / (nNumSegs * 2));
1100                
1101                //9-12-12
1102                //points were set to null by the caller if the segment distance was too short
1103                //in which case GetflotSegment still must be called to set bFlip, lDirection, lLastDirection
1104                if(points!=null)
1105                {
1106                    for (j = 0; j < 30; j++) 
1107                    {
1108                        points[lSegCounter] = arcPoints[j];
1109                        lSegCounter = lSegCounter + 1;
1110                    }
1111                }
1112            }
1113
1114            //save last lDirection
1115            lLastDirection.value[0] = lDirection.value[0];
1116            arcPoints = null;
1117        } catch (Exception exc) {
1118            ErrorLogger.LogException(_className ,"GetFlotSegment",
1119                    new RendererException("Failed inside GetFlotSegment", exc));
1120        }
1121        return nNumSegs * 10;
1122    }
1123    /**
1124     * Calculates the points for FLOT, LC
1125     * @param vbPoints2 OUT the clinet points also used for the return points
1126     * @param numPts
1127     * @return
1128     */
1129    protected static int GetFlotDouble(POINT2[] vbPoints2,double flotDiameter, int numPts) {
1130        int lFlotCounter = 0;
1131        try {            
1132            ref<int[]> bFlip=new ref();bFlip.value=new int[1];bFlip.value[0]=-1;   //-1
1133            ref<int[]> lDirection=new ref();lDirection.value=new int[1];lDirection.value[0]=-1;//-1;
1134            ref<int[]> lLastDirection=new ref();lLastDirection.value=new int[1];lLastDirection.value[0]=-1;//-1;
1135            int j = 0, k = 0, l = 0, m = 0;
1136            int x1 = 0, y1 = 0;
1137            int numSegPts = -1;
1138            int z = 0, lFlotCount = 0;
1139            int lNumSegs = 0;
1140            double dDistance = 0;
1141            int[] vbPoints = null;
1142            int[] points = null;
1143
1144            lFlotCount = GetFlotCountDouble(vbPoints2, flotDiameter, numPts);
1145
1146            vbPoints = new int[2 * numPts];
1147            //lineutility.BoundPoints(ref vbPoints2,numPts,ref segments);
1148            //BoundPoints returns a segments array of booleans
1149            //which determines whether each segment should be drawn
1150
1151            for (j = 0; j < numPts; j++) {
1152                vbPoints[k] = (int) vbPoints2[j].x;
1153                k++;
1154                vbPoints[k] = (int) vbPoints2[j].y;
1155                k++;
1156            }
1157            k = 0;
1158            //assume caller has dimensioned flotpoints
1159
1160            //every lSegment has 2 points
1161            for (l = 0; l < numPts - 1; l++) {
1162                dDistance = lineutility.CalcDistance2(vbPoints[m], vbPoints[m + 1], vbPoints[m + 2], vbPoints[m + 3]);
1163                m += 2;
1164                lNumSegs = (int) (dDistance / flotDiameter);
1165                if (lNumSegs > 0) {
1166                    points = new int[lNumSegs * 30];
1167                    numSegPts = GetFlotSegment(vbPoints, l, points, flotDiameter, bFlip,lDirection,lLastDirection);
1168                    for (j = 0; j < numSegPts; j++) {
1169                        x1 = points[k];
1170                        y1 = points[k + 1];
1171                        z = points[k + 2];
1172                        k = k + 3;
1173                        if (lFlotCounter < lFlotCount) {
1174                            vbPoints2[lFlotCounter].x = x1;
1175                            vbPoints2[lFlotCounter].y = y1;
1176                            lFlotCounter++;
1177                        }
1178                    }
1179                    k = 0;
1180                    points = null;
1181                } 
1182                else 
1183                {
1184                    ///added section 9-12-12
1185                    //these points are not used but bFlip, lDirection, lLastDirection
1186                    //must be maintained between segments
1187                    points=null;
1188                    numSegPts = GetFlotSegment(vbPoints, l, points, flotDiameter, bFlip,lDirection,lLastDirection);
1189                    //end section
1190                    if (lFlotCounter < lFlotCount) 
1191                    {
1192                        vbPoints2[lFlotCounter].x = vbPoints[2 * l];
1193                        vbPoints2[lFlotCounter].y = vbPoints[2 * l + 1];
1194                        lFlotCounter++;
1195                    }
1196                }
1197            }
1198            int n=vbPoints2.length;
1199            for (j = lFlotCounter - 1; j < n; j++) 
1200            {
1201                vbPoints2[j].style = 5;
1202            }
1203            vbPoints = null;
1204        } catch (Exception exc) {
1205            ErrorLogger.LogException(_className ,"GetFlotDouble",
1206                    new RendererException("Failed inside GetFlotDouble", exc));
1207        }
1208        return lFlotCounter;
1209    }
1210
1211    private static int CalcAnglePoints(int locx,
1212            int locY,
1213            double angle,
1214            int[] points,
1215            double dist) {
1216        try {
1217            int j = 0, k = 0;
1218            int[] lTemp = new int[2];
1219
1220            for (j = 0; j < 10; j++) {
1221                CalcNewPoint(locx, locY, angle - 90 + 20 * j, lTemp, dist);
1222                points[k] = lTemp[0];
1223                points[k + 1] = lTemp[1];
1224
1225                k += 3;
1226            }
1227            lTemp = null;
1228        } catch (Exception exc) {
1229            ErrorLogger.LogException(_className ,"CalcAnglePoints",
1230                    new RendererException("Failed inside CalcAnglePoints", exc));
1231        }
1232        return 1;
1233    }
1234    /**
1235     * Calculates the number of points required for a flot
1236     * @param vbPoints the clinet points
1237     * @param numPts the number of client points
1238     * @return the number of points required
1239     */
1240    protected static int GetFlotCountDouble(POINT2[] vbPoints, double flotDiameter, int numPts) {
1241        int lTotalpts = 0;
1242        try {
1243            int j = 0, lNumSegs = 0;
1244            double dDistance = 0;
1245            POINT2[] vbPoints2 = null;
1246
1247            vbPoints2 = new POINT2[numPts];
1248            for (j = 0; j < numPts; j++) {
1249                vbPoints2[j] = vbPoints[j];
1250            }
1251            for (j = 0; j < numPts - 1; j++) {
1252                dDistance = lineutility.CalcDistanceDouble(vbPoints2[j], vbPoints2[j + 1]);
1253                lNumSegs = (int) (dDistance / flotDiameter);
1254                if (lNumSegs > 0) {
1255                    lTotalpts += lNumSegs * 10; //10 points per flot
1256                } else {
1257                    lTotalpts += 1;
1258                }
1259            }
1260            lTotalpts += 1;
1261
1262        } catch (Exception exc) {
1263            ErrorLogger.LogException(_className ,"GetFlotCountDouble",
1264                    new RendererException("Failed inside GetFlotCountDouble", exc));
1265        }
1266        return (lTotalpts);
1267    }
1268                
1269    protected static int GetOFYPointsDouble(TGLight tg,
1270            POINT2[] pLinePoints,
1271            int numPts){
1272        int nTotalCounter = 0;
1273        try
1274        {
1275            int j = 0, k = 0, lNumSegs = 0, l = 0;
1276            int lNumFlots = 0, lNumSpikes = 0;
1277            double dDistance = 0;
1278            ref<double[]> m = new ref();
1279            int lTotalPoints = 0;
1280            int[] points = null;
1281            POINT2[] pSpikePoints = null;
1282            POINT2 pt0 = new POINT2(), tempPoint = new POINT2();
1283            POINT2[] pFlotPoints = null;
1284            POINT2[] pSegmentPoints = null;
1285            double dSpikeSize = arraysupport.getScaledSize(20, tg.get_LineThickness());
1286            double dIncrement = arraysupport.getScaledSize(80, tg.get_LineThickness()); //was 70
1287            int[] vbPoints = null;
1288            int nFlotCounter = 0, nSpikeCounter = 0, nSegmentCounter = 0;
1289            int[] flots = null;
1290            double segmentLength = 0, spikeLength = 0;
1291            int bolTooLong = 0;
1292            double d1 = 0, d2 = 0;
1293            int bolVertical = 0;
1294            POINT2[] pFlotStart = null;
1295            POINT2[] pFlotEnd = null;
1296            POINT2[] pSpikeStart = null;
1297            POINT2[] pSpikeEnd = null;
1298            int nSpikeEndCounter = 0;
1299            int nFlotEndCounter = 0;
1300            ref<int[]> bFlip = new ref();
1301            ref<int[]> lDirection = new ref();
1302            ref<int[]> lLastDirection = new ref();
1303
1304            m.value = new double[1];
1305            bFlip.value = new int[1];
1306            lDirection.value = new int[1];
1307            lLastDirection.value = new int[1];
1308            lTotalPoints = GetOFYCountDouble(pLinePoints, dIncrement, numPts);
1309
1310            vbPoints = new int[numPts * 2];
1311
1312            pSpikePoints = new POINT2[lTotalPoints];
1313            pFlotPoints = new POINT2[lTotalPoints];
1314            pSegmentPoints = new POINT2[lTotalPoints];
1315            int n=pSpikePoints.length;
1316            //for (j = 0; j < pSpikePoints.length; j++) 
1317            for (j = 0; j < n; j++) 
1318            {
1319                pSpikePoints[j] = new POINT2(pLinePoints[0]);
1320                pSpikePoints[j].style = 5;
1321            }
1322            n=pFlotPoints.length;
1323            //for (j = 0; j < pFlotPoints.length; j++) 
1324            for (j = 0; j < n; j++) 
1325            {
1326                pFlotPoints[j] = new POINT2(pLinePoints[0]);
1327                pFlotPoints[j].style = 5;
1328            }
1329            lineutility.InitializePOINT2Array(pSegmentPoints);
1330
1331            flots = new int[numPts + 1];
1332            //the vbPoints long array gets used by GetFlotSegment
1333            //and is based on the original points
1334            for (j = 0; j < numPts; j++) {
1335                vbPoints[k] = (int) pLinePoints[j].x;
1336                k++;
1337                vbPoints[k] = (int) pLinePoints[j].y;
1338                k++;
1339            }
1340            k = 0;
1341            //initialize flots
1342            flots[0] = 0;
1343            for (j = 0; j < numPts; j++) {
1344                flots[j + 1] = 0;
1345            }
1346
1347            for (j = 0; j < numPts - 1; j++) {
1348                //initialize spike end counter and flot end counter for each segment
1349                nSpikeEndCounter = 0;
1350                nFlotEndCounter = 0;
1351                bolVertical = lineutility.CalcTrueSlopeDouble(pLinePoints[j], pLinePoints[j + 1], m);
1352                m.value[0] = -m.value[0];       //reverse the direction
1353                dDistance = lineutility.CalcDistanceDouble(pLinePoints[j], pLinePoints[j + 1]);
1354                lNumSegs = (int) (dDistance / dIncrement);   //flot(20) + spike(20) = 60 pixels
1355                lNumFlots = lNumSegs;
1356                lNumSpikes = lNumSegs;
1357                flots[j + 1] = lNumSegs;
1358
1359                //get the flot segments for this line segment
1360                //flot segments are 30 pixels wide with the flots in the middle, 20 pixels wide
1361                k = 0;
1362                if (lNumFlots > 0) {
1363                    points = new int[lNumFlots * 30];
1364                    pFlotStart = new POINT2[lNumFlots];
1365                    pFlotEnd = new POINT2[lNumFlots];
1366                    GetFlotSegment2(tg, vbPoints, j, points, bFlip, lDirection, lLastDirection);
1367                    for (l = 0; l < lNumFlots * 10; l++) {
1368                        pFlotPoints[nFlotCounter].x = points[k];
1369                        pFlotPoints[nFlotCounter].y = points[k + 1];
1370                        pFlotPoints[nFlotCounter].style = 9;
1371                        //straighten out the flots
1372                        if ((nFlotCounter) % 10 == 0) {
1373                            pFlotStart[l / 10] = new POINT2(pFlotPoints[nFlotCounter]);
1374                            d1 = lineutility.CalcDistanceDouble(pLinePoints[j], pFlotPoints[nFlotCounter]);
1375                            d2 = lineutility.CalcDistanceDouble(pLinePoints[j + 1], pFlotPoints[nFlotCounter]);
1376                            if (d2 > d1) {
1377                                pFlotPoints[nFlotCounter] = lineutility.ExtendLineDouble(pLinePoints[j + 1], pLinePoints[j], -d1);
1378                            } else {
1379                                pFlotPoints[nFlotCounter] = lineutility.ExtendLineDouble(pLinePoints[j], pLinePoints[j + 1], -d2);
1380                            }
1381                            pFlotPoints[nFlotCounter].style = 9;
1382                        }
1383                        if ((nFlotCounter + 1) % 10 == 0) {
1384                            pFlotEnd[l / 10] = new POINT2(pFlotPoints[nFlotCounter]);
1385                            nFlotEndCounter++;
1386                            d1 = lineutility.CalcDistanceDouble(pLinePoints[j], pFlotPoints[nFlotCounter - 9]);
1387                            d2 = lineutility.CalcDistanceDouble(pLinePoints[j + 1], pFlotPoints[nFlotCounter - 9]);
1388                            if (d2 > d1) {
1389                                pFlotPoints[nFlotCounter] = lineutility.ExtendLineDouble(pLinePoints[j + 1], pLinePoints[j], -d1 - dSpikeSize);
1390                            } else {
1391                                pFlotPoints[nFlotCounter] = lineutility.ExtendLineDouble(pLinePoints[j], pLinePoints[j + 1], -d2 + dSpikeSize);
1392                            }
1393
1394                            pFlotPoints[nFlotCounter].style = 10;
1395                        }
1396                        k += 3;
1397                        nFlotCounter++;
1398                    }
1399                    points = null;
1400                }// end if num flots>0
1401                else //segment too short
1402                {
1403                    pSegmentPoints[nSegmentCounter] = new POINT2(pLinePoints[j]);
1404                    pSegmentPoints[nSegmentCounter++].style = 0;
1405                    pSegmentPoints[nSegmentCounter] = new POINT2(pLinePoints[j + 1]);
1406                    pSegmentPoints[nSegmentCounter++].style = 5;
1407                }
1408
1409                //for each spike in the line segment
1410                //spikes segments are 30 pixels wide with the spikes in the middle, 20 pixels wide
1411                segmentLength = lineutility.CalcDistanceDouble(pLinePoints[j], pLinePoints[j + 1]);
1412                pSpikeStart = new POINT2[lNumSpikes];
1413                pSpikeEnd = new POINT2[lNumSpikes];
1414                for (k = 0; k < lNumSpikes - 1; k++) //get the spike
1415                {
1416                    //the first spike base point
1417                    //has to be based on the preceding flot
1418                    //if the distance goes past the end of the line segment then set the point to the
1419                    //end of the line segment
1420                    bolTooLong = 0;
1421
1422                    //for the greatest accuracy
1423                    d1 = lineutility.CalcDistanceDouble(pFlotEnd[k], pFlotEnd[k + 1]);
1424                    d1 = d1 / 2 - dSpikeSize;
1425                    tempPoint = lineutility.ExtendAlongLineDouble(pFlotEnd[k], pLinePoints[j + 1], d1, 0);
1426                    spikeLength = lineutility.CalcDistanceDouble(pLinePoints[j], tempPoint);
1427                    if (spikeLength + dSpikeSize < segmentLength) {
1428                        pSpikePoints[nSpikeCounter] = new POINT2(tempPoint);
1429                        pSpikeStart[k] = new POINT2(tempPoint);
1430                    } else {
1431                        pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
1432                        bolTooLong = 1;
1433                    }
1434
1435                    pSpikePoints[nSpikeCounter].style = 9;
1436                    nSpikeCounter++;
1437
1438                    pt0 = lineutility.ExtendAlongLineDouble(pSpikePoints[nSpikeCounter - 1], pLinePoints[j + 1], dSpikeSize / 2);
1439
1440                    //the spike end (perpendicular) point
1441                    if (bolTooLong == 0) {
1442                        if (bolVertical != 0) //segment is not vertical
1443                        {
1444                            if (pLinePoints[j].x < pLinePoints[j + 1].x) {
1445                                pSpikePoints[nSpikeCounter] = lineutility.ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], pt0, 2, dSpikeSize);   //extennd above the line
1446                            } else {
1447                                pSpikePoints[nSpikeCounter] = lineutility.ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], pt0, 3, dSpikeSize);   //extend below the line
1448                            }
1449                            pSpikePoints[nSpikeCounter].style = 0;
1450                            nSpikeCounter++;
1451                        } else //vertical segment
1452                        {
1453                            if (pLinePoints[j].y > pLinePoints[j + 1].y) {
1454                                pSpikePoints[nSpikeCounter].x = pt0.x - dSpikeSize;
1455                            } else {
1456                                pSpikePoints[nSpikeCounter].x = pt0.x + dSpikeSize;
1457                            }
1458
1459                            pSpikePoints[nSpikeCounter].y = pt0.y;
1460                            nSpikeCounter++;
1461                        }
1462                    } else //too long
1463                    {
1464                        pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
1465                        nSpikeCounter++;
1466                    }
1467                    pSpikePoints[nSpikeCounter - 1].style = 9;
1468
1469                    //the second spike base point. this is the third spike point
1470                    if (bolTooLong == 0) {
1471                        d1 = lineutility.CalcDistanceDouble(pLinePoints[j], pSpikePoints[nSpikeCounter - 2]);
1472                        d2 = lineutility.CalcDistanceDouble(pLinePoints[j + 1], pSpikePoints[nSpikeCounter - 2]);
1473                        if (d1 > d2) {
1474                            pSpikePoints[nSpikeCounter] = lineutility.ExtendLine2Double(pLinePoints[j], pSpikePoints[nSpikeCounter - 2], dSpikeSize, 0);
1475                        } else {
1476                            pSpikePoints[nSpikeCounter] = lineutility.ExtendLine2Double(pLinePoints[j + 1], pSpikePoints[nSpikeCounter - 2], -dSpikeSize, 0);
1477                        }
1478
1479                        pSpikeEnd[k] = new POINT2(pSpikePoints[nSpikeCounter]);
1480                        nSpikeEndCounter++;
1481                        pSpikePoints[nSpikeCounter].style = 10;
1482                    } else {
1483                        pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
1484                        pSpikePoints[nSpikeCounter].style = 5;
1485                    }
1486                    nSpikeCounter++;
1487                }//end for k= 0 to numSpikes-1
1488                //if there are no spikes
1489                if (nSpikeEndCounter == 0 && nFlotEndCounter == 1) {
1490                    pSegmentPoints[nSegmentCounter] = new POINT2(pLinePoints[j]);
1491                    pSegmentPoints[nSegmentCounter++].style = 0;
1492                    pSegmentPoints[nSegmentCounter] = new POINT2(pFlotStart[0]);
1493                    pSegmentPoints[nSegmentCounter++].style = 5;
1494
1495                    pSegmentPoints[nSegmentCounter] = new POINT2(pLinePoints[j + 1]);
1496                    pSegmentPoints[nSegmentCounter++].style = 0;
1497                    pSegmentPoints[nSegmentCounter] = new POINT2(pFlotEnd[0]);
1498                    pSegmentPoints[nSegmentCounter++].style = 5;
1499                }
1500                //put a loop here for the segment points
1501                for (l = 0; l < nSpikeEndCounter; l++) {
1502                    if (l == 0) {
1503                        pSegmentPoints[nSegmentCounter] = new POINT2(pLinePoints[j]);
1504                        pSegmentPoints[nSegmentCounter++].style = 0;
1505                        pSegmentPoints[nSegmentCounter] = new POINT2(pFlotStart[0]);
1506                        pSegmentPoints[nSegmentCounter++].style = 5;
1507                    }
1508                    if (l == nSpikeEndCounter - 1) //the last spike
1509                    {
1510                        pSegmentPoints[nSegmentCounter] = new POINT2(pLinePoints[j + 1]);
1511                        pSegmentPoints[nSegmentCounter++].style = 0;
1512                        pSegmentPoints[nSegmentCounter] = new POINT2(pFlotEnd[l + 1]);
1513                        pSegmentPoints[nSegmentCounter++].style = 5;
1514                    }
1515                    //put the cross point segments between the flots and spikes
1516                    //segment before the spike is just a line
1517                    pSegmentPoints[nSegmentCounter] = new POINT2(pSpikeEnd[l]);
1518                    pSegmentPoints[nSegmentCounter++].style = 0;
1519                    pSegmentPoints[nSegmentCounter] = new POINT2(pFlotStart[l + 1]);
1520                    pSegmentPoints[nSegmentCounter++].style = 5;
1521
1522                    //the cross points
1523                    d1 = lineutility.CalcDistanceDouble(pSpikeStart[l], pFlotEnd[l]);
1524                    pSegmentPoints[nSegmentCounter++] = lineutility.ExtendAlongLineDouble(pSpikeStart[l], pLinePoints[j], d1 / 3, 0);
1525                    pSegmentPoints[nSegmentCounter++] = lineutility.ExtendAlongLineDouble(pSpikeStart[l], pLinePoints[j], 2 * d1 / 3, 5);
1526                    tempPoint = lineutility.ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], pSegmentPoints[nSegmentCounter - 2], 2, arraysupport.getScaledSize(5, tg.get_LineThickness()), 0);
1527                    pSegmentPoints[nSegmentCounter++] = new POINT2(tempPoint);
1528                    tempPoint = lineutility.ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], pSegmentPoints[nSegmentCounter - 2], 3, arraysupport.getScaledSize(5, tg.get_LineThickness()), 5);
1529                    pSegmentPoints[nSegmentCounter++] = new POINT2(tempPoint);
1530                }
1531                if (nSpikeCounter == 0) {
1532                    pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j]);
1533                    pSpikePoints[nSpikeCounter].style = 5;
1534                    nSpikeCounter++;
1535                    pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
1536                    pSpikePoints[nSpikeCounter].style = 5;
1537                    nSpikeCounter++;
1538                    pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
1539                    pSpikePoints[nSpikeCounter].style = 5;
1540                    nSpikeCounter++;
1541                } else {
1542                    pSpikePoints[nSpikeCounter] = new POINT2(pSpikePoints[nSpikeCounter - 1]);
1543                    pSpikePoints[nSpikeCounter].style = 5;
1544                    pSpikePoints[nSpikeCounter + 1] = new POINT2(pSpikePoints[nSpikeCounter - 1]);
1545                    pSpikePoints[nSpikeCounter + 1].style = 5;
1546                    pSpikePoints[nSpikeCounter + 2] = new POINT2(pSpikePoints[nSpikeCounter - 1]);
1547                    pSpikePoints[nSpikeCounter + 2].style = 5;
1548                    nSpikeCounter += 3;
1549                }
1550            }
1551
1552            //load the spike points into the array
1553            nTotalCounter = 0;
1554            for (j = 0; j < nFlotCounter; j++) {
1555                pLinePoints[nTotalCounter++] = new POINT2(pFlotPoints[j]);
1556            }
1557            for (j = 0; j < nSpikeCounter; j++) {
1558                pLinePoints[nTotalCounter++] = new POINT2(pSpikePoints[j]);
1559            }
1560            for (j = 0; j < nSegmentCounter; j++) {
1561                pLinePoints[nTotalCounter++] = new POINT2(pSegmentPoints[j]);
1562            }
1563            n=pLinePoints.length;
1564            //for (j = nTotalCounter; j < pLinePoints.length; j++) 
1565            for (j = nTotalCounter; j < n; j++) 
1566            {
1567                pLinePoints[j] = new POINT2(pLinePoints[nTotalCounter - 1]);
1568            }
1569        } catch (Exception exc) {
1570            ErrorLogger.LogException(_className ,"GetOFYPointsDouble",
1571                    new RendererException("Failed inside GetOFYPointsDouble", exc));
1572        }
1573        return nTotalCounter;
1574    }
1575    protected static int GetSFPointsDouble(TGLight tg,
1576            POINT2[] pLinePoints,
1577            int numPts) {
1578        int nTotalCounter = 0;
1579        try {
1580            int lineType = tg.get_LineType();
1581            int lTotalPoints = 0;
1582            int j = 0, k = 0, lNumSegs = 0, l = 0;
1583            int lNumFlots = 0, lNumSpikes = 0;
1584            double dDistance = 0;
1585            ref<double[]> m = new ref();
1586            int[] points = null;
1587            POINT2[] pSpikePoints = null;
1588            POINT2 pt0 = new POINT2(), tempPoint = new POINT2();
1589            POINT2[] pFlotPoints = null;
1590            double dSpikeSize = arraysupport.getScaledSize(20, tg.get_LineThickness()),
1591                    dIncrement = arraysupport.getScaledSize(80, tg.get_LineThickness());
1592            int[] vbPoints = null;
1593            int nFlotCounter = 0, nSpikeCounter = 0, nSegCounter = 0;
1594            int[] flots = null;
1595            //int sumOfFlots = 0;
1596            double segmentLength = 0, spikeLength = 0;
1597            int bolTooLong = 0;
1598            double d1 = 0, d2 = 0;
1599            int bolVertical = 0;
1600            POINT2[] pFlotStart = null;
1601            POINT2[] pFlotEnd = null;
1602            POINT2[] pSpikeStart = null;
1603            POINT2[] pSpikeEnd = null;
1604            POINT2[] pSegPoints = null;
1605            ref<int[]> bFlip = new ref();
1606            ref<int[]> lDirection = new ref();
1607            ref<int[]> lLastDirection = new ref();
1608
1609            lTotalPoints = GetSFCountDouble(pLinePoints, numPts);
1610            m.value = new double[1];
1611            lDirection.value = new int[1];
1612            lDirection.value[0] = -1;
1613            lLastDirection.value = new int[1];
1614            lLastDirection.value[0] = -1;
1615            bFlip.value = new int[1];
1616            bFlip.value[0] = -1;
1617
1618            vbPoints = new int[numPts * 2];
1619            pSpikePoints = new POINT2[lTotalPoints];
1620            pFlotPoints = new POINT2[lTotalPoints];
1621            int n=pSpikePoints.length;
1622            //for (j = 0; j < pSpikePoints.length; j++) 
1623            for (j = 0; j < n; j++) 
1624            {
1625                pSpikePoints[j] = new POINT2(pLinePoints[0]);
1626                pSpikePoints[j].style = 5;
1627            }
1628            n=pFlotPoints.length;
1629            //for (j = 0; j < pFlotPoints.length; j++) 
1630            for (j = 0; j < n; j++) 
1631            {
1632                pFlotPoints[j] = new POINT2(pLinePoints[0]);
1633                pFlotPoints[j].style = 5;
1634            }
1635            pSegPoints = new POINT2[4 * (numPts - 1)];
1636            lineutility.InitializePOINT2Array(pSegPoints);
1637
1638            flots = new int[numPts + 1];
1639            //the vbPoints long array gets used by GetFlotSegment
1640            //and is based on the original points
1641            //for(j=0;j<numPts;j++)
1642            for (j = 0; j < numPts; j++) {
1643                vbPoints[k] = (int) pLinePoints[j].x;
1644                k++;
1645                vbPoints[k] = (int) pLinePoints[j].y;
1646                k++;
1647            }
1648            k = 0;
1649            //initialize flots
1650            flots[0] = 0;
1651            for (j = 0; j < numPts; j++) {
1652                flots[j + 1] = 0;
1653            }
1654
1655            for (j = 0; j < numPts - 1; j++) {
1656                bolVertical = lineutility.CalcTrueSlopeDouble(pLinePoints[j], pLinePoints[j + 1], m);
1657                m.value[0] = -m.value[0];       //reverse the direction
1658                dDistance = lineutility.CalcDistanceDouble(pLinePoints[j], pLinePoints[j + 1]);
1659                lNumSegs = (int) (dDistance / dIncrement);
1660                lNumFlots = lNumSegs;
1661                lNumSpikes = lNumSegs;
1662                flots[j + 1] = lNumSegs;
1663
1664                //get the flot segments for this line segment
1665                //flot segments are 30 pixels wide with the flots in the middle, 20 pixels wide
1666                k = 0;
1667                if (lNumFlots > 0) {
1668                    points = new int[lNumFlots * 30];
1669                    pFlotStart = new POINT2[lNumFlots];
1670                    lineutility.InitializePOINT2Array(pFlotStart);
1671                    pFlotEnd = new POINT2[lNumFlots];
1672                    lineutility.InitializePOINT2Array(pFlotEnd);
1673                    GetFlotSegment2(tg, vbPoints, j, points, bFlip, lDirection, lLastDirection);
1674                    for (l = 0; l < lNumFlots * 10; l++) {
1675                        pFlotPoints[nFlotCounter].x = points[k];
1676                        pFlotPoints[nFlotCounter].y = points[k + 1];
1677
1678                        if (lineType == TacticalLines.USF || lineType == TacticalLines.SF) {
1679                            pFlotPoints[nFlotCounter].style = 19;
1680                        } else {
1681                            pFlotPoints[nFlotCounter].style = 9;
1682                        }
1683
1684                        //straighten out the flots
1685                        if ((nFlotCounter) % 10 == 0) {
1686                            pFlotStart[l / 10] = pFlotPoints[nFlotCounter];
1687                            d1 = lineutility.CalcDistanceDouble(pLinePoints[j], pFlotPoints[nFlotCounter]);
1688                            d2 = lineutility.CalcDistanceDouble(pLinePoints[j + 1], pFlotPoints[nFlotCounter]);
1689                            if (d2 > d1) {
1690                                pFlotPoints[nFlotCounter] = lineutility.ExtendLineDouble(pLinePoints[j + 1], pLinePoints[j], -d1);
1691                            } else {
1692                                pFlotPoints[nFlotCounter] = lineutility.ExtendLineDouble(pLinePoints[j], pLinePoints[j + 1], -d2);
1693                            }
1694
1695                            if (lineType == TacticalLines.USF || lineType == TacticalLines.SF) {
1696                                pFlotPoints[nFlotCounter].style = 19;
1697                            } else {
1698                                pFlotPoints[nFlotCounter].style = 9;
1699                            }
1700                        }
1701
1702                        if ((nFlotCounter + 1) % 10 == 0) {
1703                            if (lineType == TacticalLines.USF || lineType == TacticalLines.SF) {
1704                                pFlotPoints[nFlotCounter].style = 5;    //end of flot
1705                            } else {
1706                                pFlotPoints[nFlotCounter].style = 23;   //red fill
1707                            }
1708                            pFlotEnd[l / 10] = new POINT2(pFlotPoints[nFlotCounter]);
1709                        }
1710                        if (l == 0) {
1711                            pSegPoints[nSegCounter] = new POINT2(pLinePoints[j]);
1712                            pSegPoints[nSegCounter++].style = 19;
1713                            pSegPoints[nSegCounter] = new POINT2(pFlotStart[l]);
1714                            pSegPoints[nSegCounter++].style = 5;
1715                        }
1716                        if (l == lNumFlots * 10 - 1) {
1717                            pSegPoints[nSegCounter] = new POINT2(pLinePoints[j + 1]);
1718                            pSegPoints[nSegCounter++].style = 19;
1719                            pSegPoints[nSegCounter] = new POINT2(pFlotStart[l / 10]);
1720                            pSegPoints[nSegCounter++].style = 5;
1721                        }
1722                        k += 3;
1723                        nFlotCounter++;
1724                    }
1725                    points = null;
1726                }//end if num flots>0
1727                else //segment too short
1728                {
1729                    pSegPoints[nSegCounter] = new POINT2(pLinePoints[j]);
1730                    pSegPoints[nSegCounter++].style = 0;
1731                    pSegPoints[nSegCounter] = new POINT2(pLinePoints[j + 1]);
1732                    pSegPoints[nSegCounter++].style = 5;
1733                }
1734
1735                //for each spike in the line segment
1736                //spikes segments are 30 pixels wide with the spikes in the middle, 20 pixels wide
1737                segmentLength = lineutility.CalcDistanceDouble(pLinePoints[j], pLinePoints[j + 1]);
1738                pSpikeStart = new POINT2[lNumSpikes];
1739                lineutility.InitializePOINT2Array(pSpikeStart);
1740                pSpikeEnd = new POINT2[lNumSpikes];
1741                lineutility.InitializePOINT2Array(pSpikeEnd);
1742                for (k = 0; k < lNumSpikes - 1; k++) //get the spike
1743                {
1744                    //the first spike base point
1745                    //has to be based on the preceding flot
1746                    //if the distance goes past the end of the line segment then set the point to the
1747                    //end of the line segment
1748                    bolTooLong = 0;
1749
1750                    d1 = lineutility.CalcDistanceDouble(pFlotStart[k], pFlotStart[k + 1]);
1751                    d1 = d1 / 2 - dSpikeSize;
1752                    tempPoint = lineutility.ExtendAlongLineDouble(pFlotStart[k], pLinePoints[j + 1], d1, 0);
1753
1754                    spikeLength = lineutility.CalcDistanceDouble(pLinePoints[j], tempPoint);
1755                    if (spikeLength + dSpikeSize < segmentLength) {
1756                        pSpikePoints[nSpikeCounter] = new POINT2(tempPoint);
1757                        pSpikeStart[k] = new POINT2(tempPoint);
1758                    } else {
1759                        pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
1760                        bolTooLong = 1;
1761                    }
1762
1763                    if (lineType == TacticalLines.USF || lineType == TacticalLines.SF) {
1764                        pSpikePoints[nSpikeCounter].style = 25;
1765                    } else {
1766                        pSpikePoints[nSpikeCounter].style = 9;
1767                    }
1768
1769                    nSpikeCounter++;
1770
1771                    pt0 = lineutility.ExtendAlongLineDouble(pSpikePoints[nSpikeCounter - 1], pLinePoints[j + 1], dSpikeSize / 2);
1772                    //the spike end (perpendicular) point
1773                    if (bolTooLong == 0) {
1774                        if (bolVertical != 0) //segment is not vertical
1775                        {
1776                            if (pLinePoints[j].x < pLinePoints[j + 1].x) {
1777                                pSpikePoints[nSpikeCounter] = lineutility.ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], pt0, 2, dSpikeSize);   //extennd above the line
1778                            } else {
1779                                pSpikePoints[nSpikeCounter] = lineutility.ExtendDirectedLine(pLinePoints[j], pLinePoints[j + 1], pt0, 3, dSpikeSize);   //extend below the line
1780                            }
1781                            pSpikePoints[nSpikeCounter].style = 0;
1782                            //pSpikeEnd[k]=pSpikePoints[nSpikeCounter];
1783                            nSpikeCounter++;
1784                        } else //vertical segment
1785                        {
1786                            if (pLinePoints[j].y > pLinePoints[j + 1].y) {
1787                                pSpikePoints[nSpikeCounter].x = pt0.x - dSpikeSize;
1788                            } else {
1789                                pSpikePoints[nSpikeCounter].x = pt0.x + dSpikeSize;
1790                            }
1791
1792                            pSpikePoints[nSpikeCounter].y = pt0.y;
1793                            nSpikeCounter++;
1794                        }
1795                    } else //too long
1796                    {
1797                        pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
1798                        nSpikeCounter++;
1799                    }
1800
1801                    if (lineType == TacticalLines.USF || lineType == TacticalLines.SF) {
1802                        pSpikePoints[nSpikeCounter - 1].style = 25;
1803                    } else {
1804                        pSpikePoints[nSpikeCounter - 1].style = 9;
1805                    }
1806
1807                    //the second spike base point. this is the third spike point
1808                    if (bolTooLong == 0) {
1809                        pSpikePoints[nSpikeCounter] = lineutility.ExtendAlongLineDouble(pSpikePoints[nSpikeCounter - 2], pLinePoints[j + 1], dSpikeSize);
1810
1811                        if (lineType == TacticalLines.USF || lineType == TacticalLines.SF) {
1812                            pSpikePoints[nSpikeCounter].style = 5;
1813                        } else {
1814                            pSpikePoints[nSpikeCounter].style = 24;
1815                        }
1816
1817                        pSpikeEnd[k] = new POINT2(pSpikePoints[nSpikeCounter]);
1818                    } else {
1819                        pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
1820                        pSpikePoints[nSpikeCounter].style = 5;
1821                    }
1822                    nSpikeCounter++;
1823                    //the segment feature points, for SF they are just lines
1824                    if (lineType == (long) TacticalLines.SF ||
1825                            lineType == (long) TacticalLines.USF) {
1826                        d1 = lineutility.CalcDistanceDouble(pFlotStart[k], pSpikeStart[k]);
1827                        pSpikePoints[nSpikeCounter] = new POINT2(pFlotStart[k]);
1828                        pSpikePoints[nSpikeCounter++].style = 19;
1829                        pSpikePoints[nSpikeCounter++] = lineutility.ExtendAlongLineDouble(pFlotStart[k], pLinePoints[j + 1], d1 / 2, 5);
1830
1831                        pSpikePoints[nSpikeCounter] = new POINT2(pFlotEnd[k]);
1832                        pSpikePoints[nSpikeCounter++].style = 19;
1833                        pSpikePoints[nSpikeCounter++] = lineutility.ExtendAlongLineDouble(pFlotEnd[k], pLinePoints[j], d1 / 2, 5);
1834
1835                        if (k == lNumSpikes - 2) {
1836                            pSpikePoints[nSpikeCounter] = new POINT2(pFlotStart[k + 1]);
1837                            pSpikePoints[nSpikeCounter++].style = 19;
1838                            pSpikePoints[nSpikeCounter++] = lineutility.ExtendAlongLineDouble(pFlotStart[k + 1], pLinePoints[j + 1], d1 / 2, 5);
1839
1840                            pSpikePoints[nSpikeCounter] = new POINT2(pFlotEnd[k + 1]);
1841                            pSpikePoints[nSpikeCounter++].style = 19;
1842                            pSpikePoints[nSpikeCounter++] = lineutility.ExtendAlongLineDouble(pFlotEnd[k + 1], pLinePoints[j], d1 / 2, 5);
1843
1844                        }
1845
1846                        pSpikePoints[nSpikeCounter] = new POINT2(pSpikeStart[k]);
1847                        pSpikePoints[nSpikeCounter++].style = 25;
1848                        pSpikePoints[nSpikeCounter++] = lineutility.ExtendAlongLineDouble(pSpikeStart[k], pLinePoints[j], d1 / 2, 5);
1849
1850                        pSpikePoints[nSpikeCounter] = new POINT2(pSpikeEnd[k]);
1851                        pSpikePoints[nSpikeCounter++].style = 25;
1852                        pSpikePoints[nSpikeCounter++] = lineutility.ExtendAlongLineDouble(pSpikeEnd[k], pLinePoints[j + 1], d1 / 2, 5);
1853
1854                        if (lineType == (long) TacticalLines.USF) {
1855                            pSpikePoints[nSpikeCounter] = new POINT2(pFlotEnd[k]);
1856                            pSpikePoints[nSpikeCounter++].style = 19;
1857                            pSpikePoints[nSpikeCounter] = new POINT2(pFlotStart[k]);
1858                            pSpikePoints[nSpikeCounter++].style = 5;
1859
1860                            if (k == lNumSpikes - 2) {
1861                                pSpikePoints[nSpikeCounter] = new POINT2(pFlotEnd[k + 1]);
1862                                pSpikePoints[nSpikeCounter++].style = 19;
1863                                pSpikePoints[nSpikeCounter] = new POINT2(pFlotStart[k + 1]);
1864                                pSpikePoints[nSpikeCounter++].style = 5;
1865                            }
1866
1867                            pSpikePoints[nSpikeCounter] = new POINT2(pSpikeEnd[k]);
1868                            pSpikePoints[nSpikeCounter++].style = 25;
1869                            pSpikePoints[nSpikeCounter] = new POINT2(pSpikeStart[k]);
1870                            pSpikePoints[nSpikeCounter++].style = 5;
1871                        }
1872                    }
1873                    if (lineType == (long) TacticalLines.SFG) {
1874                        pSpikePoints[nSpikeCounter++] = lineutility.ExtendAlongLineDouble(pSpikeStart[k], pLinePoints[j], dSpikeSize / 2, 22);
1875                        pSpikePoints[nSpikeCounter++] = lineutility.ExtendAlongLineDouble(pSpikeEnd[k], pLinePoints[j + 1], dSpikeSize / 2, 20);
1876                    }
1877                    if (lineType == (long) TacticalLines.SFY) {
1878
1879                        d1 = lineutility.CalcDistanceDouble(pFlotStart[k], pSpikeStart[k]);
1880                        pSpikePoints[nSpikeCounter] = lineutility.ExtendAlongLineDouble(pSpikeStart[k], pLinePoints[j], d1 / 4);        //was dSpikeSize/4
1881                        pSpikePoints[nSpikeCounter].style = 25; //blue
1882                        pSpikePoints[nSpikeCounter + 1] = lineutility.ExtendAlongLineDouble(pSpikeStart[k], pLinePoints[j], d1 / 2);    //was dSpikeSize/2
1883                        pSpikePoints[nSpikeCounter + 1].style = 5;      //end of blue part
1884                        pSpikePoints[nSpikeCounter + 2] = lineutility.ExtendAlongLineDouble(pSpikeStart[k], pLinePoints[j], d1 / 2);    //was dSpikeSize/2
1885                        pSpikePoints[nSpikeCounter + 2].style = 19;     //red
1886                        pSpikePoints[nSpikeCounter + 3] = lineutility.ExtendAlongLineDouble(pSpikeStart[k], pLinePoints[j], 3 * d1 / 4);                //was 1.5*dSpikeSize/2
1887                        pSpikePoints[nSpikeCounter + 3].style = 5;      //end of red part
1888                        //the cross points
1889                        pSpikePoints[nSpikeCounter + 4] = lineutility.ExtendDirectedLine(pSpikePoints[nSpikeCounter], pLinePoints[j], pSpikePoints[nSpikeCounter], 2, arraysupport.getScaledSize(5, tg.get_LineThickness()), 25);
1890                        pSpikePoints[nSpikeCounter + 5] = lineutility.ExtendDirectedLine(pSpikePoints[nSpikeCounter + 3], pLinePoints[j], pSpikePoints[nSpikeCounter + 3], 3, arraysupport.getScaledSize(5, tg.get_LineThickness()), 5);
1891                        nSpikeCounter += 6;
1892
1893                        d1 = lineutility.CalcDistanceDouble(pFlotEnd[k + 1], pSpikeEnd[k]);
1894                        pSpikePoints[nSpikeCounter] = lineutility.ExtendAlongLineDouble(pSpikeEnd[k], pLinePoints[j + 1], d1 / 4);
1895                        pSpikePoints[nSpikeCounter].style = 25;
1896                        pSpikePoints[nSpikeCounter + 1] = lineutility.ExtendAlongLineDouble(pSpikeEnd[k], pLinePoints[j + 1], d1 / 2);
1897                        pSpikePoints[nSpikeCounter + 1].style = 5;
1898                        pSpikePoints[nSpikeCounter + 2] = lineutility.ExtendAlongLineDouble(pSpikeEnd[k], pLinePoints[j + 1], d1 / 2);
1899                        pSpikePoints[nSpikeCounter + 2].style = 19;
1900                        pSpikePoints[nSpikeCounter + 3] = lineutility.ExtendAlongLineDouble(pSpikeEnd[k], pLinePoints[j + 1], 3 * d1 / 4);
1901                        pSpikePoints[nSpikeCounter + 3].style = 5;
1902                        //the cross points
1903                        pSpikePoints[nSpikeCounter + 4] = lineutility.ExtendDirectedLine(pSpikePoints[nSpikeCounter], pLinePoints[j + 1], pSpikePoints[nSpikeCounter], 3, arraysupport.getScaledSize(5, tg.get_LineThickness()), 19);
1904                        pSpikePoints[nSpikeCounter + 5] = lineutility.ExtendDirectedLine(pSpikePoints[nSpikeCounter + 3], pLinePoints[j + 1], pSpikePoints[nSpikeCounter + 3], 2, arraysupport.getScaledSize(5, tg.get_LineThickness()), 5);
1905                        nSpikeCounter += 6;
1906
1907                    }
1908                }//for k= 0 to numSpikes-1
1909                if (nSpikeCounter == 0) {
1910                    pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j]);
1911                    pSpikePoints[nSpikeCounter].style = 5;
1912                    nSpikeCounter++;
1913                    pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
1914                    pSpikePoints[nSpikeCounter].style = 5;
1915                    nSpikeCounter++;
1916                    //added 6-1-05 M. Deutch
1917                    pSpikePoints[nSpikeCounter] = new POINT2(pLinePoints[j + 1]);
1918                    pSpikePoints[nSpikeCounter].style = 5;
1919                    nSpikeCounter++;
1920                } else {
1921                    pSpikePoints[nSpikeCounter] = new POINT2(pSpikePoints[nSpikeCounter - 1]);
1922                    pSpikePoints[nSpikeCounter].style = 5;
1923                    pSpikePoints[nSpikeCounter + 1] = new POINT2(pSpikePoints[nSpikeCounter - 1]);
1924                    pSpikePoints[nSpikeCounter + 1].style = 5;
1925                    pSpikePoints[nSpikeCounter + 2] = new POINT2(pSpikePoints[nSpikeCounter - 1]);
1926                    pSpikePoints[nSpikeCounter + 2].style = 5;
1927                    nSpikeCounter += 3;
1928                }
1929            }
1930            n=pLinePoints.length;
1931            //for (j = 0; j < pLinePoints.length; j++) 
1932            for (j = 0; j < n; j++) 
1933            {
1934                pLinePoints[j] = new POINT2(pSpikePoints[0]);
1935                pLinePoints[j].style = 5;
1936            }
1937            //load the spike points into the array
1938            nTotalCounter = 0;
1939            for (j = 0; j < nFlotCounter; j++) {
1940                pLinePoints[nTotalCounter++] = new POINT2(pFlotPoints[j]);
1941            }
1942            for (j = 0; j < nSpikeCounter; j++) {
1943                pLinePoints[nTotalCounter++] = new POINT2(pSpikePoints[j]);
1944            }
1945            for (j = 0; j < nSegCounter; j++) {
1946                pLinePoints[nTotalCounter++] = new POINT2(pSegPoints[j]);
1947            }
1948            n=pLinePoints.length;
1949            //for (j = nTotalCounter; j < pLinePoints.length; j++) 
1950            for (j = nTotalCounter; j < n; j++) 
1951            {
1952                pLinePoints[j] = new POINT2(pLinePoints[nTotalCounter - 1]);
1953            }
1954
1955        } catch (Exception exc) {
1956            ErrorLogger.LogException(_className ,"GetSFPointsDouble",
1957                    new RendererException("Failed inside GetSFPointsDouble", exc));
1958        }
1959        return nTotalCounter;
1960    }
1961
1962    protected static int GetSFCountDouble(POINT2[] pLinePoints, int numPts) {
1963        int lTotalpts = 0;
1964        try {
1965            int j = 0, lNumSegs = 0;
1966            int lNumFlots = 0, lNumSpikes = 0;
1967            double dDistance = 0;
1968            //end declarations
1969
1970            //for each segment
1971            for (j = 0; j < numPts - 1; j++) {
1972                dDistance = lineutility.CalcDistanceDouble(pLinePoints[j], pLinePoints[j + 1]);
1973                lNumSegs = (int) (dDistance / 80);
1974                lNumFlots = lNumSegs;
1975                lNumSpikes = lNumSegs;
1976                if (lNumFlots < 1) {
1977                    lNumFlots = 1;
1978                }
1979                if (lNumSpikes < 1) {
1980                    lNumSpikes = 1;
1981                }
1982                lTotalpts += lNumFlots * 10; //10 points per flot,
1983                lTotalpts += lNumSpikes * 3; //3 points per spike
1984                lTotalpts += lNumSegs * 16;     // points for line features
1985                lTotalpts += numPts * 4;
1986            }
1987            if (lTotalpts < 25 * numPts) {
1988                lTotalpts = 25 * numPts;
1989            }
1990
1991            if (lTotalpts < numPts) {
1992                lTotalpts = numPts;
1993            }
1994
1995        } catch (Exception exc) {
1996            ErrorLogger.LogException(_className ,"GetSFCountDouble",
1997                    new RendererException("Failed inside GetSFCountDouble", exc));
1998        }
1999        return lTotalpts;
2000    }
2001}