001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/graphics/displayelements/DisplayElementFactory.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstr. 19
030     53115 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041    
042     
043     ---------------------------------------------------------------------------*/
044    package org.deegree.graphics.displayelements;
045    
046    import java.lang.reflect.Constructor;
047    import java.lang.reflect.InvocationTargetException;
048    import java.util.ArrayList;
049    import java.util.List;
050    
051    import org.deegree.framework.log.ILogger;
052    import org.deegree.framework.log.LoggerFactory;
053    import org.deegree.graphics.sld.FeatureTypeStyle;
054    import org.deegree.graphics.sld.Geometry;
055    import org.deegree.graphics.sld.LineSymbolizer;
056    import org.deegree.graphics.sld.PointSymbolizer;
057    import org.deegree.graphics.sld.PolygonSymbolizer;
058    import org.deegree.graphics.sld.RasterSymbolizer;
059    import org.deegree.graphics.sld.Rule;
060    import org.deegree.graphics.sld.Symbolizer;
061    import org.deegree.graphics.sld.TextSymbolizer;
062    import org.deegree.graphics.sld.UserStyle;
063    import org.deegree.io.datastore.PropertyPathResolvingException;
064    import org.deegree.model.coverage.grid.GridCoverage;
065    import org.deegree.model.feature.Feature;
066    import org.deegree.model.feature.FeatureProperty;
067    import org.deegree.model.filterencoding.Filter;
068    import org.deegree.model.filterencoding.FilterEvaluationException;
069    import org.deegree.model.spatialschema.Curve;
070    import org.deegree.model.spatialschema.GeometryException;
071    import org.deegree.model.spatialschema.GeometryFactory;
072    import org.deegree.model.spatialschema.MultiCurve;
073    import org.deegree.model.spatialschema.MultiPoint;
074    import org.deegree.model.spatialschema.MultiPrimitive;
075    import org.deegree.model.spatialschema.MultiSurface;
076    import org.deegree.model.spatialschema.Point;
077    import org.deegree.model.spatialschema.Position;
078    import org.deegree.model.spatialschema.Surface;
079    
080    /**
081     * Factory class for the different kinds of {@link DisplayElement}s.
082     * 
083     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
084     * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider</a>
085     * @author last edited by: $Author: apoth $
086     * 
087     * @version $Revision: 9340 $, $Date: 2007-12-27 13:32:12 +0100 (Do, 27 Dez 2007) $
088     */
089    public class DisplayElementFactory {
090    
091        private static final ILogger LOG = LoggerFactory.getLogger( DisplayElementFactory.class );
092    
093        /**
094         * Returns the display elements for a {@link Feature} or {@link GridCoverage}.
095         * 
096         * @param o
097         * @param styles
098         * @return the display elements
099         * @throws ClassNotFoundException
100         * @throws IllegalAccessException
101         * @throws InstantiationException
102         * @throws NoSuchMethodException
103         * @throws InvocationTargetException
104         * @throws GeometryException
105         * 
106         * @throws PropertyPathResolvingException
107         */
108        public DisplayElement[] createDisplayElement( Object o, UserStyle[] styles )
109                                throws ClassNotFoundException, IllegalAccessException, InstantiationException,
110                                NoSuchMethodException, InvocationTargetException, GeometryException,
111                                PropertyPathResolvingException {
112    
113            ArrayList<DisplayElement> list = new ArrayList<DisplayElement>( 20 );
114    
115            if ( o instanceof Feature ) {
116                Feature feature = (Feature) o;
117    
118                try {
119                    String featureTypeName = feature.getFeatureType().getName().getPrefixedName();
120                    String qfeatureTypeName = feature.getFeatureType().getName().getFormattedString();
121    
122                    for ( int i = 0; i < styles.length; i++ ) {
123    
124                        if ( styles[i] == null ) {
125                            // create display element from default style
126                            DisplayElement de = buildDisplayElement( feature );
127                            if ( de != null ) {
128                                list.add( de );
129                            }
130                        } else {
131                            FeatureTypeStyle[] fts = styles[i].getFeatureTypeStyles();
132                            for ( int k = 0; k < fts.length; k++ ) {
133                                if ( fts[k].getFeatureTypeName() == null
134                                     || featureTypeName.equals( fts[k].getFeatureTypeName() )
135                                     || qfeatureTypeName.equals( fts[k].getFeatureTypeName() ) ) {
136                                    Rule[] rules = fts[k].getRules();
137                                    for ( int n = 0; n < rules.length; n++ ) {
138                                        // does the filter rule apply?
139                                        Filter filter = rules[n].getFilter();
140                                        if ( filter != null ) {
141                                            try {
142                                                if ( !filter.evaluate( feature ) ) {
143                                                    continue;
144                                                }
145                                            } catch ( FilterEvaluationException e ) {
146                                                LOG.logDebug( "Error evaluating filter: ", e );
147                                                continue;
148                                            }
149                                        }
150    
151                                        // Filter expression is true for this feature, so a
152                                        // corresponding DisplayElement has to be added to the
153                                        // list
154                                        Symbolizer[] symbolizers = rules[n].getSymbolizers();
155    
156                                        for ( int u = 0; u < symbolizers.length; u++ ) {
157                                            DisplayElement displayElement = DisplayElementFactory.buildDisplayElement(
158                                                                                                                       feature,
159                                                                                                                       symbolizers[u] );
160                                            if ( displayElement != null ) {
161                                                list.add( displayElement );
162                                            }
163                                        }
164                                    }
165                                }
166                            }
167                        }
168                    }
169                } catch ( IncompatibleGeometryTypeException e ) {
170                    e.printStackTrace();
171                }
172            } else {
173                for ( UserStyle style : styles ) {
174                    if ( style == null ) {
175                        list.add( buildRasterDisplayElement( (GridCoverage) o, new RasterSymbolizer() ) );
176                        continue;
177                    }
178                    for ( FeatureTypeStyle fts : style.getFeatureTypeStyles() ) {
179                        for ( Rule rule : fts.getRules() ) {
180                            for ( Symbolizer symbolizer : rule.getSymbolizers() ) {
181                                list.add( buildRasterDisplayElement( (GridCoverage) o, (RasterSymbolizer) symbolizer ) );
182                            }
183                        }
184                    }
185                }
186            }
187    
188            DisplayElement[] de = new DisplayElement[list.size()];
189            return list.toArray( de );
190        }
191    
192        /**
193         * Builds a {@link DisplayElement} using the given {@link Feature} or {@link GridCoverage} and
194         * {@link Symbolizer}.
195         * 
196         * @param o
197         *            contains the geometry or raster information (Feature or GridCoverage)
198         * @param symbolizer
199         *            contains the drawing (style) information and selects the geometry property of the
200         *            <code>Feature</code> to be drawn
201         * @throws IncompatibleGeometryTypeException
202         *             if the selected geometry of the <code>Feature</code> is not compatible with the
203         *             <code>Symbolizer</code>
204         * @return constructed <code>DisplayElement</code>
205         * @throws ClassNotFoundException
206         * @throws IllegalAccessException
207         * @throws InstantiationException
208         * @throws NoSuchMethodException
209         * @throws InvocationTargetException
210         * @throws GeometryException
211         * @throws PropertyPathResolvingException
212         */
213        public static DisplayElement buildDisplayElement( Object o, Symbolizer symbolizer )
214                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
215                                InstantiationException, NoSuchMethodException, InvocationTargetException,
216                                GeometryException, PropertyPathResolvingException {
217            DisplayElement displayElement = null;
218    
219            if ( o instanceof Feature ) {
220                Feature feature = (Feature) o;
221    
222                // determine the geometry property to be used
223                org.deegree.model.spatialschema.Geometry geometry = null;
224                Geometry symbolizerGeometry = symbolizer.getGeometry();
225    
226                if ( symbolizerGeometry != null ) {
227                    FeatureProperty property = feature.getDefaultProperty( symbolizerGeometry.getPropertyPath() );
228                    if ( property != null ) {
229                        geometry = (org.deegree.model.spatialschema.Geometry) property.getValue();
230                    }
231                } else {
232                    geometry = feature.getDefaultGeometryPropertyValue();
233                }
234    
235                // if the geometry is null, do not build a DisplayElement
236                if ( geometry == null ) {
237                    return null;
238                }
239                if ( symbolizer instanceof PointSymbolizer ) {
240                    displayElement = buildPointDisplayElement( feature, geometry, (PointSymbolizer) symbolizer );
241                } else if ( symbolizer instanceof LineSymbolizer ) {
242                    displayElement = buildLineStringDisplayElement( feature, geometry, (LineSymbolizer) symbolizer );
243                } else if ( symbolizer instanceof PolygonSymbolizer ) {
244                    displayElement = buildPolygonDisplayElement( feature, geometry, (PolygonSymbolizer) symbolizer );
245                } else if ( symbolizer instanceof TextSymbolizer ) {
246                    displayElement = buildLabelDisplayElement( feature, geometry, (TextSymbolizer) symbolizer );
247                }
248            } else {
249                if ( symbolizer instanceof RasterSymbolizer ) {
250                    LOG.logDebug( "Building RasterDisplayElement" );
251                    displayElement = buildRasterDisplayElement( (GridCoverage) o, (RasterSymbolizer) symbolizer );
252                }
253            }
254    
255            return displayElement;
256        }
257    
258        /**
259         * Builds a {@link DisplayElement} using the given {@link Feature} or {@link GridCoverage} and
260         * the default {@link Symbolizer}.
261         * 
262         * @param o
263         *            contains the geometry or raster information (Feature or GridCoverage)
264         * @throws IncompatibleGeometryTypeException
265         *             if the selected geometry of the <code>Feature</code> is not compatible with the
266         *             <code>Symbolizer</code>
267         * @return constructed <code>DisplayElement</code>
268         * @throws ClassNotFoundException
269         * @throws IllegalAccessException
270         * @throws InstantiationException
271         * @throws NoSuchMethodException
272         * @throws InvocationTargetException
273         * @throws GeometryException
274         */
275        public static DisplayElement buildDisplayElement( Object o )
276                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
277                                InstantiationException, NoSuchMethodException, InvocationTargetException, GeometryException {
278    
279            DisplayElement displayElement = null;
280    
281            if ( o instanceof GridCoverage ) {
282                RasterSymbolizer symbolizer = new RasterSymbolizer();
283                displayElement = buildRasterDisplayElement( (GridCoverage) o, symbolizer );
284            } else {
285                Feature feature = (Feature) o;
286                // determine the geometry property to be used
287                org.deegree.model.spatialschema.Geometry geoProperty = feature.getDefaultGeometryPropertyValue();
288    
289                // if the geometry property is null, do not build a DisplayElement
290                if ( geoProperty == null ) {
291                    return null;
292                }
293                // PointSymbolizer
294                if ( geoProperty instanceof Point || geoProperty instanceof MultiPoint ) {
295                    PointSymbolizer symbolizer = new PointSymbolizer();
296                    displayElement = buildPointDisplayElement( feature, geoProperty, symbolizer );
297                } // LineSymbolizer
298                else if ( geoProperty instanceof Curve || geoProperty instanceof MultiCurve ) {
299                    LineSymbolizer symbolizer = new LineSymbolizer();
300                    displayElement = buildLineStringDisplayElement( feature, geoProperty, symbolizer );
301                } // PolygonSymbolizer
302                else if ( geoProperty instanceof Surface || geoProperty instanceof MultiSurface ) {
303                    PolygonSymbolizer symbolizer = new PolygonSymbolizer();
304                    displayElement = buildPolygonDisplayElement( feature, geoProperty, symbolizer );
305                } else {
306                    throw new IncompatibleGeometryTypeException( "not a valid geometry type" );
307                }
308            }
309    
310            return displayElement;
311        }
312    
313        /**
314         * Creates a {@link PointDisplayElement} using the given geometry and style information.
315         * 
316         * @param feature
317         *            associated feature (source of the geometry information)
318         * @param geom
319         *            geometry information
320         * @param sym
321         *            style information
322         * @return constructed <code>PointDisplayElement</code>
323         * @throws ClassNotFoundException
324         * @throws IllegalAccessException
325         * @throws InstantiationException
326         * @throws NoSuchMethodException
327         * @throws InvocationTargetException
328         */
329        public static PointDisplayElement buildPointDisplayElement( Feature feature,
330                                                                    org.deegree.model.spatialschema.Geometry geom,
331                                                                    PointSymbolizer sym )
332                                throws ClassNotFoundException, IllegalAccessException, InstantiationException,
333                                NoSuchMethodException, InvocationTargetException {
334    
335            // if the geometry is not a point geometry, the centroid(s) of the
336            // geometry will be used
337            PointDisplayElement displayElement = null;
338            String className = sym.getResponsibleClass();
339            Class clss = Class.forName( className );
340            Object[] values = new Object[] { feature, geom, sym };
341            if ( geom instanceof Point ) {
342                Class[] param = new Class[] { Feature.class, Point.class, PointSymbolizer.class };
343                Constructor constructor = clss.getConstructor( param );
344                displayElement = (PointDisplayElement) constructor.newInstance( values );
345            } else if ( geom instanceof MultiPoint ) {
346                Class[] param = new Class[] { Feature.class, MultiPoint.class, PointSymbolizer.class };
347                Constructor constructor = clss.getConstructor( param );
348                displayElement = (PointDisplayElement) constructor.newInstance( values );
349            } else if ( geom instanceof MultiPrimitive ) {
350                // Primitive[] primitives = ( (MultiPrimitive) geom ).getAllPrimitives();
351                // Point[] centroids = new Point[primitives.length];
352                Point[] centroids = new Point[1];
353                centroids[0] = geom.getCentroid();
354    
355                // for ( int i = 0; i < primitives.length; i++ ) {
356                // centroids[i] = primitives[i].getCentroid();
357                // }
358    
359                try {
360                    Class[] param = new Class[] { Feature.class, MultiPoint.class, PointSymbolizer.class };
361                    Constructor constructor = clss.getConstructor( param );
362                    values[1] = GeometryFactory.createMultiPoint( centroids );
363                    displayElement = (PointDisplayElement) constructor.newInstance( values );
364                } catch ( Exception e ) {
365                    e.printStackTrace();
366                }
367            } else {
368                Class[] param = new Class[] { Feature.class, Point.class, PointSymbolizer.class };
369                Constructor constructor = clss.getConstructor( param );
370                values[1] = geom.getCentroid();
371                displayElement = (PointDisplayElement) constructor.newInstance( values );
372            }
373    
374            return displayElement;
375        }
376    
377        /**
378         * Creates a {@link LineStringDisplayElement} using the given geometry and style information.
379         * 
380         * @param feature
381         *            associated feature (source of the geometry information)
382         * @param geom
383         *            geometry information
384         * @param sym
385         *            style information
386         * @throws IncompatibleGeometryTypeException
387         *             if the geometry property is not a <code>Curve</code> or <code>MultiCurve</code>
388         * @return constructed <code>LineStringDisplayElement</code>
389         * @throws ClassNotFoundException
390         * @throws IllegalAccessException
391         * @throws InstantiationException
392         * @throws NoSuchMethodException
393         * @throws InvocationTargetException
394         * @throws GeometryException
395         */
396        public static LineStringDisplayElement buildLineStringDisplayElement(
397                                                                              Feature feature,
398                                                                              org.deegree.model.spatialschema.Geometry geom,
399                                                                              LineSymbolizer sym )
400                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
401                                InstantiationException, NoSuchMethodException, InvocationTargetException, GeometryException {
402            LineStringDisplayElement displayElement = null;
403    
404            String className = sym.getResponsibleClass();
405            Class clss = Class.forName( className );
406            Object[] values = new Object[] { feature, geom, sym };
407    
408            if ( geom instanceof Curve ) {
409                Class[] param = new Class[] { Feature.class, Curve.class, LineSymbolizer.class };
410                Constructor constructor = clss.getConstructor( param );
411                displayElement = (LineStringDisplayElement) constructor.newInstance( values );
412            } else if ( geom instanceof MultiCurve ) {
413                Class[] param = new Class[] { Feature.class, MultiCurve.class, LineSymbolizer.class };
414                Constructor constructor = clss.getConstructor( param );
415                displayElement = (LineStringDisplayElement) constructor.newInstance( values );
416            } else if ( geom instanceof Surface ) {
417                // according to OGC SLD specification it is possible to assign a
418                // LineSymbolizer to a polygon. To handle this the border of the
419                // polygon will be transformed into a lines (curves)
420                MultiCurve mc = surfaceToCurve( (Surface) geom );
421                displayElement = buildLineStringDisplayElement( feature, mc, sym );
422            } else if ( geom instanceof MultiSurface ) {
423                // according to OGC SLD specification it is possible to assign a
424                // LineSymbolizer to a multipolygon. To handle this the borders of the
425                // multipolygons will be transformed into a lines (curves)
426                MultiSurface ms = (MultiSurface) geom;
427                List<Curve> list = new ArrayList<Curve>( 500 );
428                for ( int i = 0; i < ms.getSize(); i++ ) {
429                    MultiCurve mc = surfaceToCurve( ms.getSurfaceAt( i ) );
430                    for ( int j = 0; j < mc.getSize(); j++ ) {
431                        list.add( mc.getCurveAt( j ) );
432                    }
433                }
434                Curve[] curves = list.toArray( new Curve[list.size()] );
435                MultiCurve mc = GeometryFactory.createMultiCurve( curves );
436                displayElement = buildLineStringDisplayElement( feature, mc, sym );
437            } else {
438                throw new IncompatibleGeometryTypeException( "Tried to create a LineStringDisplayElement from a geometry "
439                                                             + "with an incompatible / unsupported type: '"
440                                                             + geom.getClass().getName() + "'!" );
441            }
442    
443            return displayElement;
444        }
445    
446        /**
447         * Transforms a {@link Surface} into a {@link MultiCurve}.
448         * 
449         * @param geom
450         * @return MultiCurve
451         * @throws Exception
452         */
453        private static MultiCurve surfaceToCurve( Surface geom )
454                                throws GeometryException {
455            List<Curve> list = new ArrayList<Curve>( 100 );
456            int num = geom.getNumberOfSurfacePatches();
457            for ( int i = 0; i < num; i++ ) {
458                Position[] pos = geom.getSurfacePatchAt( i ).getExteriorRing();
459                Curve curve = GeometryFactory.createCurve( pos, geom.getCoordinateSystem() );
460                list.add( curve );
461                Position[][] inn = geom.getSurfacePatchAt( i ).getInteriorRings();
462                if ( inn != null ) {
463                    for ( int j = 0; j < inn.length; j++ ) {
464                        curve = GeometryFactory.createCurve( inn[j], geom.getCoordinateSystem() );
465                        list.add( curve );
466                    }
467                }
468            }
469            Curve[] curves = list.toArray( new Curve[list.size()] );
470            MultiCurve mc = GeometryFactory.createMultiCurve( curves );
471            return mc;
472        }
473    
474        /**
475         * Creates a {@link PolygonDisplayElement} using the given geometry and style information.
476         * 
477         * @param feature
478         *            associated feature (source of the geometry information)
479         * @param geom
480         *            geometry information
481         * @param sym
482         *            style information
483         * @throws IncompatibleGeometryTypeException
484         *             if the geometry property is not a <code>Surface</code> or
485         *             <code>MultiSurface</code>
486         * @return constructed <code>PolygonDisplayElement</code>
487         * @throws ClassNotFoundException
488         * @throws IllegalAccessException
489         * @throws InstantiationException
490         * @throws NoSuchMethodException
491         * @throws InvocationTargetException
492         */
493        public static PolygonDisplayElement buildPolygonDisplayElement( Feature feature,
494                                                                        org.deegree.model.spatialschema.Geometry geom,
495                                                                        PolygonSymbolizer sym )
496                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
497                                InstantiationException, NoSuchMethodException, InvocationTargetException {
498            PolygonDisplayElement displayElement = null;
499    
500            String className = sym.getResponsibleClass();
501            Class clss = Class.forName( className );
502            Object[] values = new Object[] { feature, geom, sym };
503            if ( geom instanceof Surface ) {
504                Class[] param = new Class[] { Feature.class, Surface.class, PolygonSymbolizer.class };
505                Constructor constructor = clss.getConstructor( param );
506                displayElement = (PolygonDisplayElement) constructor.newInstance( values );
507            } else if ( geom instanceof MultiSurface ) {
508                Class[] param = new Class[] { Feature.class, MultiSurface.class, PolygonSymbolizer.class };
509                Constructor constructor = clss.getConstructor( param );
510                displayElement = (PolygonDisplayElement) constructor.newInstance( values );
511            } else {
512                throw new IncompatibleGeometryTypeException(
513                                                             "Tried to create a LineStringDisplayElement from a geometry with "
514                                                                                     + "an incompatible / unsupported type: '"
515                                                                                     + geom.getClass().getName() + "'!" );
516            }
517    
518            return displayElement;
519        }
520    
521        /**
522         * Creates a {@link LabelDisplayElement} using the given geometry and style information.
523         * 
524         * @param feature
525         *            associated feature (source of the geometry information and label caption)
526         * @param geom
527         *            geometry information
528         * @param sym
529         *            style information
530         * @throws IncompatibleGeometryTypeException
531         *             if the geometry property is not a <code>Point</code>, a <code>Surface</code>
532         *             or <code>MultiSurface</code>
533         * @return constructed <code>LabelDisplayElement</code>
534         * @throws ClassNotFoundException
535         * @throws IllegalAccessException
536         * @throws InstantiationException
537         * @throws NoSuchMethodException
538         * @throws InvocationTargetException
539         */
540        public static LabelDisplayElement buildLabelDisplayElement( Feature feature,
541                                                                    org.deegree.model.spatialschema.Geometry geom,
542                                                                    TextSymbolizer sym )
543                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
544                                InstantiationException, NoSuchMethodException, InvocationTargetException {
545    
546            LabelDisplayElement displayElement = null;
547    
548            if ( geom instanceof Point || geom instanceof MultiPoint || geom instanceof Surface
549                 || geom instanceof MultiSurface || geom instanceof Curve || geom instanceof MultiCurve ) {
550                String className = sym.getResponsibleClass();
551                Class clss = Class.forName( className );
552                Class[] param = new Class[] { Feature.class, org.deegree.model.spatialschema.Geometry.class,
553                                             TextSymbolizer.class };
554                Object[] values = new Object[] { feature, geom, sym };
555                Constructor constructor = clss.getConstructor( param );
556                displayElement = (LabelDisplayElement) constructor.newInstance( values );
557            } else {
558                throw new IncompatibleGeometryTypeException( "Tried to create a LabelDisplayElement from a geometry with "
559                                                             + "an incompatible / unsupported type: '"
560                                                             + geom.getClass().getName() + "'!" );
561            }
562    
563            return displayElement;
564        }
565    
566        /**
567         * Creates a {@link RasterDisplayElement} from the given {@link GridCoverage}.
568         * 
569         * @param gc
570         *            grid coverage (source of the raster data)
571         * @param sym
572         *            raster symbolizer
573         * 
574         * @return RasterDisplayElement
575         */
576        public static RasterDisplayElement buildRasterDisplayElement( GridCoverage gc, RasterSymbolizer sym ) {
577            return new RasterDisplayElement( gc, sym );
578        }
579    }