001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/graphics/displayelements/DisplayElementFactory.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2007 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: aschmitz $
086     * 
087     * @version $Revision: 7811 $, $Date: 2007-07-23 17:57:49 +0200 (Mo, 23 Jul 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    
121                    for ( int i = 0; i < styles.length; i++ ) {
122    
123                        if ( styles[i] == null ) {
124                            // create display element from default style
125                            DisplayElement de = buildDisplayElement( feature );
126                            if ( de != null ) {
127                                list.add( de );
128                            }
129                        } else {
130                            FeatureTypeStyle[] fts = styles[i].getFeatureTypeStyles();
131                            for ( int k = 0; k < fts.length; k++ ) {
132                                if ( fts[k].getFeatureTypeName() == null
133                                     || featureTypeName.equals( fts[k].getFeatureTypeName() ) ) {
134                                    Rule[] rules = fts[k].getRules();
135                                    for ( int n = 0; n < rules.length; n++ ) {
136                                        // does the filter rule apply?
137                                        Filter filter = rules[n].getFilter();
138                                        if ( filter != null ) {
139                                            try {
140                                                if ( !filter.evaluate( feature ) ) {
141                                                    continue;
142                                                }
143                                            } catch ( FilterEvaluationException e ) {
144                                                LOG.logDebug( "Error evaluating filter: ", e );
145                                                continue;
146                                            }
147                                        }
148    
149                                        // Filter expression is true for this feature, so a
150                                        // corresponding DisplayElement has to be added to the
151                                        // list
152                                        Symbolizer[] symbolizers = rules[n].getSymbolizers();
153    
154                                        for ( int u = 0; u < symbolizers.length; u++ ) {
155                                            DisplayElement displayElement = DisplayElementFactory.buildDisplayElement(
156                                                                                                                       feature,
157                                                                                                                       symbolizers[u] );
158                                            if ( displayElement != null ) {
159                                                list.add( displayElement );
160                                            }
161                                        }
162                                    }
163                                }
164                            }
165                        }
166                    }
167                } catch ( IncompatibleGeometryTypeException e ) {
168                    e.printStackTrace();
169                }
170            } else {
171                for ( UserStyle style : styles ) {
172                    if ( style == null ) {
173                        list.add( buildRasterDisplayElement( (GridCoverage) o, new RasterSymbolizer() ) );
174                        continue;
175                    }
176                    for ( FeatureTypeStyle fts : style.getFeatureTypeStyles() ) {
177                        for ( Rule rule : fts.getRules() ) {
178                            for ( Symbolizer symbolizer : rule.getSymbolizers() ) {
179                                list.add( buildRasterDisplayElement( (GridCoverage) o, (RasterSymbolizer) symbolizer ) );
180                            }
181                        }
182                    }
183                }
184            }
185    
186            DisplayElement[] de = new DisplayElement[list.size()];
187            return list.toArray( de );
188        }
189    
190        /**
191         * Builds a {@link DisplayElement} using the given {@link Feature} or {@link GridCoverage} and
192         * {@link Symbolizer}.
193         * 
194         * @param o
195         *            contains the geometry or raster information (Feature or GridCoverage)
196         * @param symbolizer
197         *            contains the drawing (style) information and selects the geometry property of the
198         *            <code>Feature</code> to be drawn
199         * @throws IncompatibleGeometryTypeException
200         *             if the selected geometry of the <code>Feature</code> is not compatible with the
201         *             <code>Symbolizer</code>
202         * @return constructed <code>DisplayElement</code>
203         * @throws ClassNotFoundException
204         * @throws IllegalAccessException
205         * @throws InstantiationException
206         * @throws NoSuchMethodException
207         * @throws InvocationTargetException
208         * @throws GeometryException
209         * @throws PropertyPathResolvingException
210         */
211        public static DisplayElement buildDisplayElement( Object o, Symbolizer symbolizer )
212                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
213                                InstantiationException, NoSuchMethodException, InvocationTargetException,
214                                GeometryException, PropertyPathResolvingException {
215            DisplayElement displayElement = null;
216    
217            if ( o instanceof Feature ) {
218                Feature feature = (Feature) o;
219    
220                // determine the geometry property to be used
221                org.deegree.model.spatialschema.Geometry geometry = null;
222                Geometry symbolizerGeometry = symbolizer.getGeometry();
223    
224                if ( symbolizerGeometry != null ) {
225                    FeatureProperty property = feature.getDefaultProperty( symbolizerGeometry.getPropertyPath() );
226                    if ( property != null ) {
227                        geometry = (org.deegree.model.spatialschema.Geometry) property.getValue();
228                    }
229                } else {
230                    geometry = feature.getDefaultGeometryPropertyValue();
231                }
232    
233                // if the geometry is null, do not build a DisplayElement
234                if ( geometry == null ) {
235                    return null;
236                }
237                if ( symbolizer instanceof PointSymbolizer ) {
238                    displayElement = buildPointDisplayElement( feature, geometry, (PointSymbolizer) symbolizer );
239                } else if ( symbolizer instanceof LineSymbolizer ) {
240                    displayElement = buildLineStringDisplayElement( feature, geometry, (LineSymbolizer) symbolizer );
241                } else if ( symbolizer instanceof PolygonSymbolizer ) {
242                    displayElement = buildPolygonDisplayElement( feature, geometry, (PolygonSymbolizer) symbolizer );
243                } else if ( symbolizer instanceof TextSymbolizer ) {
244                    displayElement = buildLabelDisplayElement( feature, geometry, (TextSymbolizer) symbolizer );
245                }
246            } else {
247                if ( symbolizer instanceof RasterSymbolizer ) {
248                    LOG.logDebug( "Building RasterDisplayElement" );
249                    displayElement = buildRasterDisplayElement( (GridCoverage) o, (RasterSymbolizer) symbolizer );
250                }
251            }
252    
253            return displayElement;
254        }
255    
256        /**
257         * Builds a {@link DisplayElement} using the given {@link Feature} or {@link GridCoverage} and
258         * the default {@link Symbolizer}.
259         * 
260         * @param o
261         *            contains the geometry or raster information (Feature or GridCoverage)
262         * @throws IncompatibleGeometryTypeException
263         *             if the selected geometry of the <code>Feature</code> is not compatible with the
264         *             <code>Symbolizer</code>
265         * @return constructed <code>DisplayElement</code>
266         * @throws ClassNotFoundException
267         * @throws IllegalAccessException
268         * @throws InstantiationException
269         * @throws NoSuchMethodException
270         * @throws InvocationTargetException
271         * @throws GeometryException
272         */
273        public static DisplayElement buildDisplayElement( Object o )
274                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
275                                InstantiationException, NoSuchMethodException, InvocationTargetException, GeometryException {
276    
277            DisplayElement displayElement = null;
278    
279            if ( o instanceof GridCoverage ) {
280                RasterSymbolizer symbolizer = new RasterSymbolizer();
281                displayElement = buildRasterDisplayElement( (GridCoverage) o, symbolizer );
282            } else {
283                Feature feature = (Feature) o;
284                // determine the geometry property to be used
285                org.deegree.model.spatialschema.Geometry geoProperty = feature.getDefaultGeometryPropertyValue();
286    
287                // if the geometry property is null, do not build a DisplayElement
288                if ( geoProperty == null ) {
289                    return null;
290                }
291                // PointSymbolizer
292                if ( geoProperty instanceof Point || geoProperty instanceof MultiPoint ) {
293                    PointSymbolizer symbolizer = new PointSymbolizer();
294                    displayElement = buildPointDisplayElement( feature, geoProperty, symbolizer );
295                } // LineSymbolizer
296                else if ( geoProperty instanceof Curve || geoProperty instanceof MultiCurve ) {
297                    LineSymbolizer symbolizer = new LineSymbolizer();
298                    displayElement = buildLineStringDisplayElement( feature, geoProperty, symbolizer );
299                } // PolygonSymbolizer
300                else if ( geoProperty instanceof Surface || geoProperty instanceof MultiSurface ) {
301                    PolygonSymbolizer symbolizer = new PolygonSymbolizer();
302                    displayElement = buildPolygonDisplayElement( feature, geoProperty, symbolizer );
303                } else {
304                    throw new IncompatibleGeometryTypeException( "not a valid geometry type" );
305                }
306            }
307    
308            return displayElement;
309        }
310    
311        /**
312         * Creates a {@link PointDisplayElement} using the given geometry and style information.
313         * 
314         * @param feature
315         *            associated feature (source of the geometry information)
316         * @param geom
317         *            geometry information
318         * @param sym
319         *            style information
320         * @return constructed <code>PointDisplayElement</code>
321         * @throws ClassNotFoundException
322         * @throws IllegalAccessException
323         * @throws InstantiationException
324         * @throws NoSuchMethodException
325         * @throws InvocationTargetException
326         */
327        public static PointDisplayElement buildPointDisplayElement( Feature feature,
328                                                                    org.deegree.model.spatialschema.Geometry geom,
329                                                                    PointSymbolizer sym )
330                                throws ClassNotFoundException, IllegalAccessException, InstantiationException,
331                                NoSuchMethodException, InvocationTargetException {
332    
333            // if the geometry is not a point geometry, the centroid(s) of the
334            // geometry will be used
335            PointDisplayElement displayElement = null;
336            String className = sym.getResponsibleClass();
337            Class clss = Class.forName( className );
338            Object[] values = new Object[] { feature, geom, sym };
339            if ( geom instanceof Point ) {
340                Class[] param = new Class[] { Feature.class, Point.class, PointSymbolizer.class };
341                Constructor constructor = clss.getConstructor( param );
342                displayElement = (PointDisplayElement) constructor.newInstance( values );
343            } else if ( geom instanceof MultiPoint ) {
344                Class[] param = new Class[] { Feature.class, MultiPoint.class, PointSymbolizer.class };
345                Constructor constructor = clss.getConstructor( param );
346                displayElement = (PointDisplayElement) constructor.newInstance( values );
347            } else if ( geom instanceof MultiPrimitive ) {
348                // Primitive[] primitives = ( (MultiPrimitive) geom ).getAllPrimitives();
349                // Point[] centroids = new Point[primitives.length];
350                Point[] centroids = new Point[1];
351                centroids[0] = geom.getCentroid();
352    
353                // for ( int i = 0; i < primitives.length; i++ ) {
354                // centroids[i] = primitives[i].getCentroid();
355                // }
356    
357                try {
358                    Class[] param = new Class[] { Feature.class, MultiPoint.class, PointSymbolizer.class };
359                    Constructor constructor = clss.getConstructor( param );
360                    values[1] = GeometryFactory.createMultiPoint( centroids );
361                    displayElement = (PointDisplayElement) constructor.newInstance( values );
362                } catch ( Exception e ) {
363                    e.printStackTrace();
364                }
365            } else {
366                Class[] param = new Class[] { Feature.class, Point.class, PointSymbolizer.class };
367                Constructor constructor = clss.getConstructor( param );
368                values[1] = geom.getCentroid();
369                displayElement = (PointDisplayElement) constructor.newInstance( values );
370            }
371    
372            return displayElement;
373        }
374    
375        /**
376         * Creates a {@link LineStringDisplayElement} using the given geometry and style information.
377         * 
378         * @param feature
379         *            associated feature (source of the geometry information)
380         * @param geom
381         *            geometry information
382         * @param sym
383         *            style information
384         * @throws IncompatibleGeometryTypeException
385         *             if the geometry property is not a <code>Curve</code> or <code>MultiCurve</code>
386         * @return constructed <code>LineStringDisplayElement</code>
387         * @throws ClassNotFoundException
388         * @throws IllegalAccessException
389         * @throws InstantiationException
390         * @throws NoSuchMethodException
391         * @throws InvocationTargetException
392         * @throws GeometryException
393         */
394        public static LineStringDisplayElement buildLineStringDisplayElement(
395                                                                              Feature feature,
396                                                                              org.deegree.model.spatialschema.Geometry geom,
397                                                                              LineSymbolizer sym )
398                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
399                                InstantiationException, NoSuchMethodException, InvocationTargetException, GeometryException {
400            LineStringDisplayElement displayElement = null;
401    
402            String className = sym.getResponsibleClass();
403            Class clss = Class.forName( className );
404            Object[] values = new Object[] { feature, geom, sym };
405    
406            if ( geom instanceof Curve ) {
407                Class[] param = new Class[] { Feature.class, Curve.class, LineSymbolizer.class };
408                Constructor constructor = clss.getConstructor( param );
409                displayElement = (LineStringDisplayElement) constructor.newInstance( values );
410            } else if ( geom instanceof MultiCurve ) {
411                Class[] param = new Class[] { Feature.class, MultiCurve.class, LineSymbolizer.class };
412                Constructor constructor = clss.getConstructor( param );
413                displayElement = (LineStringDisplayElement) constructor.newInstance( values );
414            } else if ( geom instanceof Surface ) {
415                // according to OGC SLD specification it is possible to assign a
416                // LineSymbolizer to a polygon. To handle this the border of the
417                // polygon will be transformed into a lines (curves)
418                MultiCurve mc = surfaceToCurve( (Surface) geom );
419                displayElement = buildLineStringDisplayElement( feature, mc, sym );
420            } else if ( geom instanceof MultiSurface ) {
421                // according to OGC SLD specification it is possible to assign a
422                // LineSymbolizer to a multipolygon. To handle this the borders of the
423                // multipolygons will be transformed into a lines (curves)
424                MultiSurface ms = (MultiSurface) geom;
425                List<Curve> list = new ArrayList<Curve>( 500 );
426                for ( int i = 0; i < ms.getSize(); i++ ) {
427                    MultiCurve mc = surfaceToCurve( ms.getSurfaceAt( i ) );
428                    for ( int j = 0; j < mc.getSize(); j++ ) {
429                        list.add( mc.getCurveAt( j ) );
430                    }
431                }
432                Curve[] curves = list.toArray( new Curve[list.size()] );
433                MultiCurve mc = GeometryFactory.createMultiCurve( curves );
434                displayElement = buildLineStringDisplayElement( feature, mc, sym );
435            } else {
436                throw new IncompatibleGeometryTypeException(
437                                                             "Tried to create a LineStringDisplayElement from a geometry with "
438                                                                                     + "an incompatible / unsupported type: '"
439                                                                                     + geom.getClass().getName() + "'!" );
440            }
441    
442            return displayElement;
443        }
444    
445        /**
446         * Transforms a {@link Surface} into a {@link MultiCurve}.
447         * 
448         * @param geom
449         * @return MultiCurve
450         * @throws Exception
451         */
452        private static MultiCurve surfaceToCurve( Surface geom )
453                                throws GeometryException {
454            List<Curve> list = new ArrayList<Curve>( 100 );
455            int num = geom.getNumberOfSurfacePatches();
456            for ( int i = 0; i < num; i++ ) {
457                Position[] pos = geom.getSurfacePatchAt( i ).getExteriorRing();
458                Curve curve = GeometryFactory.createCurve( pos, geom.getCoordinateSystem() );
459                list.add( curve );
460                Position[][] inn = geom.getSurfacePatchAt( i ).getInteriorRings();
461                if ( inn != null ) {
462                    for ( int j = 0; j < inn.length; j++ ) {
463                        curve = GeometryFactory.createCurve( inn[j], geom.getCoordinateSystem() );
464                        list.add( curve );
465                    }
466                }
467            }
468            Curve[] curves = list.toArray( new Curve[list.size()] );
469            MultiCurve mc = GeometryFactory.createMultiCurve( curves );
470            return mc;
471        }
472    
473        /**
474         * Creates a {@link PolygonDisplayElement} using the given geometry and style information.
475         * 
476         * @param feature
477         *            associated feature (source of the geometry information)
478         * @param geom
479         *            geometry information
480         * @param sym
481         *            style information
482         * @throws IncompatibleGeometryTypeException
483         *             if the geometry property is not a <code>Surface</code> or
484         *             <code>MultiSurface</code>
485         * @return constructed <code>PolygonDisplayElement</code>
486         * @throws ClassNotFoundException
487         * @throws IllegalAccessException
488         * @throws InstantiationException
489         * @throws NoSuchMethodException
490         * @throws InvocationTargetException
491         */
492        public static PolygonDisplayElement buildPolygonDisplayElement( Feature feature,
493                                                                        org.deegree.model.spatialschema.Geometry geom,
494                                                                        PolygonSymbolizer sym )
495                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
496                                InstantiationException, NoSuchMethodException, InvocationTargetException {
497            PolygonDisplayElement displayElement = null;
498    
499            String className = sym.getResponsibleClass();
500            Class clss = Class.forName( className );
501            Object[] values = new Object[] { feature, geom, sym };
502            if ( geom instanceof Surface ) {
503                Class[] param = new Class[] { Feature.class, Surface.class, PolygonSymbolizer.class };
504                Constructor constructor = clss.getConstructor( param );
505                displayElement = (PolygonDisplayElement) constructor.newInstance( values );
506            } else if ( geom instanceof MultiSurface ) {
507                Class[] param = new Class[] { Feature.class, MultiSurface.class, PolygonSymbolizer.class };
508                Constructor constructor = clss.getConstructor( param );
509                displayElement = (PolygonDisplayElement) constructor.newInstance( values );
510            } else {
511                throw new IncompatibleGeometryTypeException(
512                                                             "Tried to create a LineStringDisplayElement from a geometry with "
513                                                                                     + "an incompatible / unsupported type: '"
514                                                                                     + geom.getClass().getName() + "'!" );
515            }
516    
517            return displayElement;
518        }
519    
520        /**
521         * Creates a {@link LabelDisplayElement} using the given geometry and style information.
522         * 
523         * @param feature
524         *            associated feature (source of the geometry information and label caption)
525         * @param geom
526         *            geometry information
527         * @param sym
528         *            style information
529         * @throws IncompatibleGeometryTypeException
530         *             if the geometry property is not a <code>Point</code>, a <code>Surface</code>
531         *             or <code>MultiSurface</code>
532         * @return constructed <code>LabelDisplayElement</code>
533         * @throws ClassNotFoundException
534         * @throws IllegalAccessException
535         * @throws InstantiationException
536         * @throws NoSuchMethodException
537         * @throws InvocationTargetException
538         */
539        public static LabelDisplayElement buildLabelDisplayElement( Feature feature,
540                                                                    org.deegree.model.spatialschema.Geometry geom,
541                                                                    TextSymbolizer sym )
542                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
543                                InstantiationException, NoSuchMethodException, InvocationTargetException {
544    
545            LabelDisplayElement displayElement = null;
546    
547            if ( geom instanceof Point || geom instanceof MultiPoint || geom instanceof Surface
548                 || geom instanceof MultiSurface || geom instanceof Curve || geom instanceof MultiCurve ) {
549                String className = sym.getResponsibleClass();
550                Class clss = Class.forName( className );
551                Class[] param = new Class[] { Feature.class, org.deegree.model.spatialschema.Geometry.class,
552                                             TextSymbolizer.class };
553                Object[] values = new Object[] { feature, geom, sym };
554                Constructor constructor = clss.getConstructor( param );
555                displayElement = (LabelDisplayElement) constructor.newInstance( values );
556            } else {
557                throw new IncompatibleGeometryTypeException( "Tried to create a LabelDisplayElement from a geometry with "
558                                                             + "an incompatible / unsupported type: '"
559                                                             + geom.getClass().getName() + "'!" );
560            }
561    
562            return displayElement;
563        }
564    
565        /**
566         * Creates a {@link RasterDisplayElement} from the given {@link GridCoverage}.
567         * 
568         * @param gc
569         *            grid coverage (source of the raster data)
570         * @param sym
571         *            raster symbolizer
572         * 
573         * @return RasterDisplayElement
574         */
575        public static RasterDisplayElement buildRasterDisplayElement( GridCoverage gc, RasterSymbolizer sym ) {
576            return new RasterDisplayElement( gc, sym );
577        }
578    }