001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005
006package armyc2.c5isr.RenderMultipoints;
007import armyc2.c5isr.JavaLineArray.arraysupport;
008import armyc2.c5isr.JavaLineArray.CELineArray;
009import armyc2.c5isr.JavaTacticalRenderer.clsChannelUtility;
010import armyc2.c5isr.JavaTacticalRenderer.Modifier2;
011import armyc2.c5isr.JavaTacticalRenderer.TGLight;
012import armyc2.c5isr.JavaTacticalRenderer.clsUtility;
013import armyc2.c5isr.JavaTacticalRenderer.P1;
014import armyc2.c5isr.JavaLineArray.ref;
015import armyc2.c5isr.JavaLineArray.POINT2;
016import armyc2.c5isr.JavaTacticalRenderer.clsMETOC;
017import java.util.ArrayList;
018import armyc2.c5isr.JavaLineArray.Shape2;
019import armyc2.c5isr.JavaLineArray.TacticalLines;
020import armyc2.c5isr.renderer.utilities.ErrorLogger;
021import armyc2.c5isr.renderer.utilities.MSInfo;
022import armyc2.c5isr.renderer.utilities.MSLookup;
023import armyc2.c5isr.renderer.utilities.RendererException;
024import armyc2.c5isr.renderer.utilities.IPointConversion;
025import armyc2.c5isr.JavaLineArray.lineutility;
026import java.util.HashMap;
027import armyc2.c5isr.renderer.utilities.Color;
028import armyc2.c5isr.graphics2d.*;
029import armyc2.c5isr.graphics2d.BasicStroke;
030import armyc2.c5isr.graphics2d.BufferedImage;
031import armyc2.c5isr.graphics2d.Graphics2D;
032import armyc2.c5isr.graphics2d.Point2D;
033import armyc2.c5isr.graphics2d.Rectangle;
034import armyc2.c5isr.graphics2d.Rectangle2D;
035import armyc2.c5isr.renderer.utilities.RendererSettings;
036
037/**
038 * Rendering helper class
039*
040 */
041public final class clsRenderer2 {
042    private static final String _className="clsRenderer2";
043    /**
044     * MSR and ASR use segment data for segment colors
045     * Assumes tg.H has been revised for clipping
046     * @param tg
047     * @param shapes 
048     */
049    private static void getMSRShapes(TGLight tg,
050            ArrayList<Shape2>shapes)
051    {
052        try
053        {
054            int linetype=tg.get_LineType();
055            if(linetype != TacticalLines.MSR && linetype != TacticalLines.ASR && linetype != TacticalLines.ROUTE)
056                return;
057
058            HashMap<Integer,Color> hmap= clsUtility.getMSRSegmentColors(tg);
059            Shape2 shape=null;
060            
061            BasicStroke stroke=clsUtility.getLineStroke(tg.get_LineThickness(),tg.get_LineStyle(),tg.get_lineCap(),BasicStroke.JOIN_ROUND);
062            
063            int j=0,n=tg.Pixels.size();
064            Color color=null;
065            Shape2 segShape=null;
066            shape=new Shape2(Shape2.SHAPE_TYPE_POLYLINE);
067            shape.setLineColor(tg.get_LineColor());
068            shape.setStroke(stroke);
069            
070            //if colors are not set then use one shape
071            //assumes colors may be set if string is comma delimited
072//            String strH=tg.get_H();
073//            if(strH != null && !strH.isEmpty())
074//            {               
075//                String[] strs=strH.split(",");
076//                if(strs.length<2)
077//                {
078//                    shape.moveTo(tg.Pixels.get(0));
079//                    //n=tg.Pixels.size();
080//                    //for(j=1;j<tg.Pixels.size();j++)
081//                    for(j=1;j<n;j++)
082//                    {
083//                        shape.lineTo(tg.Pixels.get(j));
084//                    }
085//                    shapes.add(shape);
086//                    return;
087//                }
088//            }
089                        
090            //if the hashmap contains the segment then use the color corresponding to the segment
091            //in the hashtable to create a one segment shape to add to the shape array.
092            //else sdd the segment to the original shape
093            Color lastColor=null;   //diagnostic
094            double dist=0,dist2=0;
095            POINT2 pt0=null,pt1=null;
096            POINT2 lastPt=null;
097            //for(j=0;j<tg.Pixels.size()-1;j++)
098            for(j=0;j<n-1;j++)
099            {
100                pt0=tg.Pixels.get(j);
101                pt1=tg.Pixels.get(j+1);
102                if(hmap !=null && hmap.containsKey(j))
103                {
104                    color=(Color)hmap.get(j);
105                    if(color != lastColor)
106                    {
107                        if(segShape != null)
108                            shapes.add(segShape);                    
109                        
110                        segShape = new Shape2(Shape2.SHAPE_TYPE_POLYLINE);                    
111                        segShape.setLineColor(color);
112                        segShape.set_Style(tg.get_LineStyle());
113                        segShape.setStroke(stroke);
114                    }
115                    segShape.moveTo(pt0);
116                    segShape.lineTo(pt1);                    
117                    lastColor=new Color(Integer.toHexString(color.toARGB()));
118               }                                    
119                else
120                {
121                    if(hmap !=null && hmap.containsKey(j+1))
122                    {
123                        shape.moveTo(pt0);
124                        shape.lineTo(pt1);
125                        lastPt=new POINT2(pt1);
126                    }
127                    else if(hmap !=null && hmap.containsKey(j-1))
128                    {
129                        shape.moveTo(pt0);
130                        shape.lineTo(pt1);                        
131                        lastPt=new POINT2(pt1);
132                    }
133                    else if(j==tg.Pixels.size()-2)
134                    {
135                        shape.moveTo(pt0);
136                        shape.lineTo(pt1);                                                
137                    }
138                    else
139                    {
140                        if(lastPt==null)
141                        {
142                            lastPt=new POINT2(pt0);
143                            shape.moveTo(lastPt);
144                            //shape.lineTo(lastPt);
145                        }                        
146                        dist=lineutility.CalcDistanceDouble(pt0, pt1);
147                        if(dist>10)
148                        {
149                            //shape.moveTo(pt0);
150                            shape.lineTo(pt1);                                                
151                            lastPt=new POINT2(pt1);                            
152                        }
153                        else
154                        {
155                            dist2=lineutility.CalcDistanceDouble(lastPt, pt1);
156                            if(dist2>10)
157                            {
158                                //shape.moveTo(pt0);
159                                shape.lineTo(pt1);                                                
160                                lastPt=new POINT2(pt1);                            
161                            }                            
162                        }
163                    }
164                    //shapes.add(shape);
165                }
166            }
167            if(segShape != null)
168                shapes.add(segShape);                    
169            
170            shapes.add(shape);
171        }
172        catch (Exception exc)
173        {
174            ErrorLogger.LogException(_className ,"getMSRShapes",
175                new RendererException("Failed inside getMSRShapes", exc));
176        }
177    }
178    /**
179     * 
180     * @param tg
181     * @param converter client converter
182     * @param isTextFlipped
183     * @return
184     */
185    public static ArrayList<Shape2> GetLineArray(TGLight tg,
186            IPointConversion converter,
187            boolean isTextFlipped,
188            Object clipBounds)
189    {
190        ArrayList<Shape2> shapes=new ArrayList();
191        try
192        {
193            if(tg.Pixels==null || tg.Pixels.isEmpty())
194                return null;            
195            double x=0;
196            double y=0;
197            double width=0;
198            double height=0;
199            Rectangle2D clipBounds2=null;
200
201            Rectangle2D clipRect=null;
202            ArrayList<Point2D>clipArray=null;
203            if(clipBounds != null)
204            {
205                if(clipBounds.getClass().isAssignableFrom(Rectangle2D.Double.class))
206                {            
207                    //clipRect=(Rectangle2D.Double)clipBounds;
208                    clipRect=(Rectangle2D)clipBounds;
209                    x=clipRect.getMinX()-50;
210                    y=clipRect.getMinY()-50;
211                    width=clipRect.getWidth()+100;
212                    height=clipRect.getHeight()+100;
213                    clipBounds2=new Rectangle2D.Double(x,y,width,height);
214                }
215                else if(clipBounds.getClass().isAssignableFrom(Rectangle.class))
216                {
217                    Rectangle rectx=(Rectangle)clipBounds;
218                    clipRect=new Rectangle2D.Double(rectx.x,rectx.y,rectx.width,rectx.height);
219                    x=clipRect.getMinX()-50;
220                    y=clipRect.getMinY()-50;
221                    width=clipRect.getWidth()+100;
222                    height=clipRect.getHeight()+100;
223                    clipBounds2=new Rectangle2D.Double(x,y,width,height);                    
224                }
225                else if(clipBounds.getClass().isAssignableFrom(ArrayList.class))
226                {
227                    clipArray=(ArrayList<Point2D>)clipBounds;
228                    clipBounds2= armyc2.c5isr.RenderMultipoints.clsUtility.getMBR(clipArray);
229                }
230            }
231
232            int lineType = tg.get_LineType();
233            // In some cases render shapes as another line type but return to input line type before adding modifiers
234            final int inputLineType = lineType;
235
236            // Render complex arrows as simple arrow when very small
237            double DPIScaleFactor = RendererSettings.getInstance().getDeviceDPI() / 96.0;
238            if ((lineType == TacticalLines.FOLLA || lineType == TacticalLines.FOLSP || lineType == TacticalLines.CONVOY)
239                    && lineutility.CalcDistanceDouble(tg.Pixels.get(0), tg.Pixels.get(1)) <= 30 * DPIScaleFactor) {
240                lineType = TacticalLines.DIRATKSPT;
241                tg.set_LineType(lineType);
242            }
243
244            int minPoints2;
245            MSInfo msInfo = MSLookup.getInstance().getMSLInfo(tg.get_SymbolId());
246            if (msInfo != null) {
247                minPoints2 = msInfo.getMinPointCount();
248            } else {
249                minPoints2 = -1;
250            }
251
252            boolean bolResult = clsUtility.IsChange1Area(lineType);
253            int bolMeTOC= clsMETOC.IsWeather(tg.get_SymbolId());
254            
255            ArrayList<POINT2>pts=new ArrayList();
256            //uncomment one line for usas1314
257            Boolean usas1314=true;
258            int j=0,n=tg.Pixels.size();
259            if (tg.get_LineType() == TacticalLines.SINGLEC) {
260                //reverse single concertina
261                pts=(ArrayList<POINT2>)tg.Pixels.clone();
262                //for(j=0;j<tg.Pixels.size();j++)
263                for(j=0;j<n;j++)
264                    tg.Pixels.set(j, pts.get(pts.size()-j-1));
265            }
266
267            //set CELineArray.shapes properties
268            BufferedImage bi=new BufferedImage(8,8,BufferedImage.TYPE_INT_ARGB);
269            Graphics2D g2d=bi.createGraphics();
270            g2d.setFont(tg.get_Font());
271
272            if(tg.Pixels.size()<minPoints2)
273            {
274                bolResult=false;
275            }
276
277            if (bolResult)
278            {
279
280                tg.Pixels.clear();
281                bolResult = clsUtilityCPOF.Change1TacticalAreas(tg, lineType, converter, shapes);
282            }
283            else if(bolMeTOC>0)
284            {
285                if(tg.Pixels.size()<2)
286                    return null;
287
288                try
289                {
290                    clsMETOC.GetMeTOCShape(tg, shapes);
291                }
292                catch(Exception exc)
293                {
294                    ErrorLogger.LogException(_className ,"GetLineArray",
295                        new RendererException("Failed inside GetLineArray", exc));
296                }
297            }
298            else
299            {
300                //this will help with click-drag mode
301                if(tg.Pixels.size()<2)
302                        return null;
303                
304                if (CELineArray.CIsChannel(lineType) == 0)
305                {
306                    if(lineType==TacticalLines.ASR || lineType==TacticalLines.MSR || lineType==TacticalLines.ROUTE)
307                    {
308                        getMSRShapes(tg,shapes);
309                    }
310                    else
311                    {
312                        tg.Pixels=arraysupport.GetLineArray2(tg, tg.Pixels,shapes, clipBounds2, converter);
313                    }
314                }
315                else //channel type
316                {
317                    clsChannelUtility.DrawChannel(tg.Pixels, lineType, tg,shapes, null, clipBounds2, converter);
318                }
319            }
320            //set CELineArray.shapes properties
321            if(bolMeTOC<=0)
322            {
323                if(lineType!=TacticalLines.ASR && lineType!=TacticalLines.MSR && lineType!=TacticalLines.ROUTE)
324                    clsUtility.SetShapeProperties(tg,shapes,bi);
325            }
326
327            if (lineType != inputLineType) {
328                // lineType was switched temporarily while rendering shapes
329                tg.set_LineType(inputLineType);
330            }
331
332            //at this point tg.Pixels has the points from CELineArray
333            //the following line adds modifiers for those sybmols which require
334            //the calculated points to use for the modifiers.
335            //currentlly only BLOCK and CONTAIN use tg.Pixels for computing
336            //the modifiers after the call to GetLineArray
337            //Modifier2.AddModifiers2(tg);//flipped only for 3d for change 1 symbols
338            Modifier2.AddModifiers2(tg, converter);
339
340            //boundary has shapes for line break
341            Modifier2.GetIntegralTextShapes(tg, g2d, shapes);
342
343            bi.flush();
344            g2d.dispose();
345            bi=null;
346            g2d=null;
347        }
348        catch (Exception exc)
349        {
350            ErrorLogger.LogException(_className ,"GetLineArray",
351                new RendererException("Failed inside GetLineArray", exc));
352        }
353        return shapes;
354    }
355    /**
356     * Isolate and others require special handling for the fill shapes.
357     * @param tg 
358     * @param shapes the existing shapes which characterize the graphic
359     */
360    static protected void getAutoshapeFillShape(TGLight tg, ArrayList<Shape2>shapes)
361    {
362        try
363        {            
364            if(shapes==null || shapes.size()==0)
365                return;
366            if(tg.Pixels==null || tg.Pixels.size()==0)
367                return;
368            if(tg.get_FillColor()==null)
369                return;
370            
371            int linetype=tg.get_LineType();
372            int j=0;
373            Shape2 shape=new Shape2(Shape2.SHAPE_TYPE_FILL);
374            shape.setFillColor(tg.get_FillColor());
375            shape.setLineColor(null);
376            int t=shapes.size();
377            int n=tg.Pixels.size();
378            switch(linetype)
379            {
380                case TacticalLines.RETAIN:
381                    if(shapes!=null && !shapes.isEmpty())
382                        //for(j=0;j<shapes.size();j++)
383                        for(j=0;j<t;j++)
384                            shapes.get(j).setFillColor(null);
385                    
386                    shape.moveTo(tg.Pixels.get(0));
387                    for(j=1;j<26;j++)                    
388                        shape.lineTo(tg.Pixels.get(j));
389                    
390                    shape.lineTo(tg.Pixels.get(0));
391                    shapes.add(0,shape);
392                    break;
393                case TacticalLines.SECURE:
394                case TacticalLines.OCCUPY:
395                    if(shapes!=null && !shapes.isEmpty())
396                        //for(j=0;j<shapes.size();j++)
397                        for(j=0;j<t;j++)
398                            shapes.get(j).setFillColor(null);
399                    
400                    shape.moveTo(tg.Pixels.get(0));
401                    //for(j=1;j<tg.Pixels.size()-3;j++)                    
402                    for(j=1;j<n-3;j++)                    
403                        shape.lineTo(tg.Pixels.get(j));
404                    
405                    shape.lineTo(tg.Pixels.get(0));
406                    shapes.add(0,shape);
407                    break;
408                case TacticalLines.CONVOY:
409                case TacticalLines.HCONVOY:
410                    if(shapes!=null && !shapes.isEmpty())
411                        //for(j=0;j<shapes.size();j++)
412                        for(j=0;j<t;j++)
413                            shapes.get(j).setFillColor(null);
414                    
415                    shape.moveTo(tg.Pixels.get(0));
416                    //for(j=1;j<tg.Pixels.size();j++)                    
417                    for(j=1;j<n;j++)                    
418                        shape.lineTo(tg.Pixels.get(j));
419                    
420                    shape.lineTo(tg.Pixels.get(0));
421                    shapes.add(0,shape);
422                    break;
423                case TacticalLines.CORDONSEARCH:
424                case TacticalLines.CORDONKNOCK:
425                case TacticalLines.ISOLATE:
426                    //set the fillcolor to null for the existing shapes
427                    //we are going to create a new fill shape
428                    if(shapes!=null && !shapes.isEmpty())
429                        //for(j=0;j<shapes.size();j++)
430                        for(j=0;j<t;j++)
431                            shapes.get(j).setFillColor(null);
432                    
433                    shape.moveTo(tg.Pixels.get(0));
434                    for(j=26;j<47;j++)                    
435                        shape.lineTo(tg.Pixels.get(j));
436                    
437                    shape.lineTo(tg.Pixels.get(23));
438                    shape.lineTo(tg.Pixels.get(24));
439                    shape.lineTo(tg.Pixels.get(25));
440                    shape.lineTo(tg.Pixels.get(0));
441                    shapes.add(0,shape);
442                    break;
443                default:
444                    return;
445            }
446        }
447        catch (Exception exc)
448        {
449            ErrorLogger.LogException(_className ,"getAutoshapeFillShape",
450                new RendererException("Failed inside getAutoshapeFillShape", exc));
451        }
452    }
453}