Package org.geotools.filter.function

Source Code of org.geotools.filter.function.FilterFunction_isometric$Segment

package org.geotools.filter.function;

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2005-2008, Open Source Geospatial Foundation (OSGeo)
*   
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation;
*    version 2.1 of the License.
*
*    This library is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*    Lesser General Public License for more details.
*/

//this was autogenerated and then hand modified to implement better support for geometry
// transformations in SLD
import static org.geotools.filter.capability.FunctionNameImpl.parameter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.geotools.filter.FunctionExpressionImpl;
import org.geotools.filter.capability.FunctionNameImpl;
import org.geotools.filter.function.FilterFunction_offset.OffsetOrdinateFilter;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.opengis.filter.capability.FunctionName;

import com.vividsolutions.jts.geom.CoordinateSequence;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.GeometryComponentFilter;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Polygon;

/**
*
*
* @source $URL$
*/
public class FilterFunction_isometric extends FunctionExpressionImpl implements
        GeometryTransformation {

    public static FunctionName NAME = new FunctionNameImpl("isometric", Geometry.class,
            parameter("geometry", Geometry.class),
            parameter("extrusion", Double.class));

    public FilterFunction_isometric() {
        super(NAME);
    }

    public Object evaluate(Object feature) {
        Geometry geom =  getExpression(0).evaluate(feature, Geometry.class);
        Double extrusion = getExpression(1).evaluate(feature, Double.class);

        if (geom != null && extrusion != null) {
            // build the vertical faces
            SegmentExtractorFilter extractor = new SegmentExtractorFilter();
            geom.apply(extractor);
            List<Polygon> faces = extractor.getFaces(geom.getFactory(), extrusion);
           
            // add the "cap"
            if(geom instanceof Polygon) {
                Polygon offseted = (Polygon) geom.clone();
                offseted.apply(new OffsetOrdinateFilter(0, extrusion));
                faces.add(0, (Polygon) geom);
                faces.add(offseted);
            } else if(geom instanceof GeometryCollection){
                GeometryCollection gc = (GeometryCollection) geom;
                for (int i = 0; i < gc.getNumGeometries(); i++) {
                    Geometry g = gc.getGeometryN(i);
                    if(g instanceof Polygon) {
                        Polygon offseted = (Polygon) g.clone();
                        offseted.apply(new OffsetOrdinateFilter(0, extrusion));
                        faces.add(0, (Polygon) g);
                        faces.add(offseted);
                    }
                }
            }
           
            Polygon[] polyArray = (Polygon[]) faces.toArray(new Polygon[faces.size()]);
            return geom.getFactory().createMultiPolygon(polyArray);
           
        } else {
            return null;
        }
    }

    /**
     * Returns an translated rendering envelope if the offsets are not using feature attributes. If
     * the offsets are feature dependent the user will have to expand the rendering area via the
     * renderer buffer parameter
     */
    public ReferencedEnvelope invert(ReferencedEnvelope renderingEnvelope) {
        Double offsetY = getExpression(1).evaluate(null, Double.class);

        if (offsetY != null) {
            ReferencedEnvelope offseted = new ReferencedEnvelope(renderingEnvelope);
            offseted.translate(0, offsetY);
            return offseted;
        } else {
            return null;
        }
    }

    /**
     * Extracts Segment objects out of the Geometry coordinate sequences
     */
    static class SegmentExtractorFilter implements GeometryComponentFilter {
        List<Segment> segments = new ArrayList<Segment>();

        public void filter(Geometry geom) {
            if(geom instanceof LineString) {
                extractSegments(((LineString) geom).getCoordinateSequence());
            }
        }

        private void extractSegments(CoordinateSequence cs) {
            for(int i = 0; i < cs.size() - 1; i++) {
                segments.add(new Segment(cs.getX(i), cs.getY(i), cs.getX(i+1), cs.getY(i+1)));
            }
        }
       
        List<Polygon> getFaces(GeometryFactory gf, double extrude) {
            // sort the segments from bottom to top
            Collections.sort(segments);
           
            // extrude each segment
            List<Polygon> result = new ArrayList<Polygon>();
            for (Segment segment : segments) {
                CoordinateSequence cs = gf.getCoordinateSequenceFactory().create(5, 2);
                cs.setOrdinate(0, 0, segment.x0);
                cs.setOrdinate(0, 1, segment.y0);
                cs.setOrdinate(3, 0, segment.x0);
                cs.setOrdinate(3, 1, segment.y0 + extrude);
                cs.setOrdinate(2, 0, segment.x1);
                cs.setOrdinate(2, 1, segment.y1 + extrude);
                cs.setOrdinate(1, 0, segment.x1);
                cs.setOrdinate(1, 1, segment.y1);
                cs.setOrdinate(4, 0, segment.x0);
                cs.setOrdinate(4, 1, segment.y0);
                result.add(gf.createPolygon(gf.createLinearRing(cs), null));
            }
           
            return result;
        }

    }
   
    static class Segment implements Comparable<Segment> {
        double x0, y0;
        double x1, y1;
       
        public Segment(double x0, double y0, double x1, double y1) {
            this.x0 = x0;
            this.y0 = y0;
            this.x1 = x1;
            this.y1 = y1;
        }

        public int compareTo(Segment other) {
            double maxY = Math.max(y0, y1);
            double otherMaxY = Math.max(other.y0, other.y1);
            if(maxY > otherMaxY)
                return -1;
            if(maxY < otherMaxY)
                return 1;
           
            double maxX = Math.max(x0, x1);
            double otherMaxX = Math.max(other.x0, other.x1);
            if(maxX > otherMaxX)
                return 1;
            if(maxX < otherMaxX)
                return -1;
            return 0;
        }
    }

}
TOP

Related Classes of org.geotools.filter.function.FilterFunction_isometric$Segment

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.