Statistics
| Revision:

gvsig-3d / 2.1 / trunk / org.gvsig.view3d / org.gvsig.view3d.vector / org.gvsig.view3d.vector.lib / org.gvsig.view3d.vector.lib.impl / src / main / java / org / gvsig / view3d / vector / lib / impl / extrusion / DefaultVectorExtrusionPolygonRenderableLayer.java @ 773

History | View | Annotate | Download (9.7 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright ? 2007-2017 gvSIG Association
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.view3d.vector.lib.impl.extrusion;
25

    
26
import java.awt.Color;
27
import java.util.ArrayList;
28
import java.util.List;
29

    
30
import org.apache.commons.lang3.StringUtils;
31
import org.cresques.cts.ICoordTrans;
32

    
33
import org.gvsig.fmap.dal.exception.DataException;
34
import org.gvsig.fmap.dal.feature.Feature;
35
import org.gvsig.fmap.dal.feature.FeatureQuery;
36
import org.gvsig.fmap.dal.feature.FeatureStore;
37
import org.gvsig.fmap.geom.Geometry;
38
import org.gvsig.fmap.geom.Geometry.TYPES;
39
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
40
import org.gvsig.fmap.geom.primitive.Point;
41
import org.gvsig.fmap.geom.primitive.Polygon;
42
import org.gvsig.fmap.geom.primitive.Ring;
43
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
44
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
45
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
46
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
47
import org.gvsig.view3d.vector.lib.api.VectorElevationMode;
48
import org.gvsig.view3d.vector.lib.api.VectorExtrusionLoaderParameters;
49
import org.gvsig.view3d.vector.lib.api.VectorLoaderParameters;
50
import org.gvsig.view3d.vector.lib.impl.AbstractRenderableLayer;
51

    
52
import gov.nasa.worldwind.geom.Position;
53
import gov.nasa.worldwind.render.BasicShapeAttributes;
54
import gov.nasa.worldwind.render.ExtrudedPolygon;
55
import gov.nasa.worldwind.render.Material;
56
import gov.nasa.worldwind.render.Renderable;
57

    
58
/**
59
 * 
60
 * @author <a href="mailto:lmarques@disid.com">Lluis Marques</a>
61
 *
62
 */
63
public class DefaultVectorExtrusionPolygonRenderableLayer extends AbstractRenderableLayer {
64

    
65
    private BasicShapeAttributes normalShapeAttributes;
66
    private BasicShapeAttributes sideShapeAttributes;
67

    
68
    public DefaultVectorExtrusionPolygonRenderableLayer(VectorLoaderParameters parameters, FeatureStore featureStore,
69
        IVectorLegend legend) {
70
        super(parameters, featureStore, legend);
71
    }
72

    
73
    @Override
74
    protected List<Renderable> getRenderables(Feature feature) {
75

    
76
        double heightFieldValue = 0;
77
        String heightField = ((VectorExtrusionLoaderParameters) parameters).getHeightField();
78
        if (StringUtils.isNoneBlank(heightField)) {
79
            heightFieldValue = feature.getDouble(heightField);
80
        }
81

    
82
        Geometry geom = feature.getDefaultGeometry();
83
        List<Renderable> renderables = new ArrayList<>();
84
        if (geom.getGeometryType().isTypeOf(TYPES.MULTIPOLYGON)) {
85
            MultiPolygon multiPolygon = (MultiPolygon) geom;
86
            for (int i = 0; i < multiPolygon.getPrimitivesNumber(); i++) {
87
                Polygon polygon = (Polygon) multiPolygon.getSurfaceAt(i);
88
                if (polygon.getNumVertices() >= 4) {
89
                    renderables.add(getRenderable(polygon, heightFieldValue));
90
                }
91
            }
92
        } else {
93
            Polygon polygon = (Polygon) geom;
94
            if (polygon.getNumVertices() >= 4) {
95
                renderables.add(getRenderable(polygon, heightFieldValue));
96
            }
97
        }
98
        return renderables;
99
    }
100
    
101
    @Override
102
    protected FeatureQuery getFeatureQuery() throws DataException {
103
        FeatureQuery featureQuery = super.getFeatureQuery();
104
        // Add field height to feature query
105
        String fieldHeight = ((VectorExtrusionLoaderParameters) parameters).getHeightField();
106
        if (StringUtils.isNotBlank(fieldHeight)) {
107
            featureQuery.addAttributeName(fieldHeight);
108
        }
109
        return featureQuery;
110
    }
111

    
112
    private ExtrudedPolygon getRenderable(Polygon polygon, double heightFieldValue) {
113
        ExtrudedPolygon renderable = new ExtrudedPolygon();
114
        boolean hasZ = polygon.getDimension() > 2;
115
        double h = 0.0;
116

    
117
        if (VectorElevationMode.CLAMP_TO_GROUND.equals(parameters.getVectorElevationMode())) {
118
            hasZ = false;
119
        } else {
120
            if (VectorElevationMode.RELATIVE_TO_GROUND.equals(parameters.getVectorElevationMode())) {
121
                hasZ = false;
122
            }
123
            if (parameters.getConstantHeight() != null) {
124
                h = parameters.getConstantHeight();
125
            }
126
        }
127
        h += heightFieldValue;
128
        h *= ((VectorExtrusionLoaderParameters) parameters).getVerticalExaggeration();
129

    
130
        ICoordTrans coordTrans = getCoordTrans(this.parameters.getLayer().getProjection());
131
        List<Position> verticesList = getVertices(polygon, h, hasZ, coordTrans);
132
        renderable.setOuterBoundary(verticesList);
133
        
134
        int numInteriorRings = polygon.getNumInteriorRings();
135
        for (int i = 0; i < numInteriorRings; i++) {
136
            renderable.addInnerBoundary(getInteriorRing(polygon.getInteriorRing(i), hasZ, h));
137
        }
138
        renderable.setAltitudeMode(getAltitudeMode(this.parameters.getVectorElevationMode()));
139
        renderable.setAttributes(getNormalShapeAttributes(legend));
140
        renderable.setSideAttributes(getSideShapeAttributes(legend));
141
        return renderable;
142
    }
143

    
144
    private List<Position> getInteriorRing(Ring interiorRing, boolean hasZ, double h) {
145
        int internalNumVertices = interiorRing.getNumVertices();
146
        List<Position> internalVerticesList = new ArrayList<>(internalNumVertices);
147
        for (int j = 0; j < internalNumVertices; j++) {
148
            Point vertex = interiorRing.getVertex(j);
149
            if (hasZ) {
150
                double z = vertex.getCoordinateAt(2);
151
                internalVerticesList.add(Position.fromDegrees(vertex.getY(), vertex.getX(), z + h));
152
            } else {
153
                internalVerticesList.add(Position.fromDegrees(vertex.getY(), vertex.getX(), h));
154
            }
155
        }
156
        return internalVerticesList;
157
    }
158

    
159
    private BasicShapeAttributes getSideShapeAttributes(IVectorLegend legend) {
160
        
161
        if(this.sideShapeAttributes != null) {
162
            return this.sideShapeAttributes;
163
        }
164
        
165
        Material sideFillMaterial = Material.GRAY;
166
        double fillOpacity = 0.7;
167

    
168
        ISymbol symbol = legend.getDefaultSymbol();
169
        if (symbol instanceof IFillSymbol) {
170
            IFillSymbol fillSymbol = (IFillSymbol) symbol;
171
            Color fillColor = fillSymbol.getFillColor();
172
            int fillAlpha = fillSymbol.getFillAlpha();
173
            Color sideFillColor = darkenColor(fillColor);
174
            sideFillMaterial = new Material(sideFillColor);
175
            fillOpacity = fillAlpha / 255.0;
176
        } else {
177
            sideFillMaterial = new Material(this.parameters.getDefaultColor());
178
            fillOpacity = 0.7;
179
        }
180
        sideShapeAttributes = new BasicShapeAttributes();
181
        sideShapeAttributes.setInteriorMaterial(sideFillMaterial);
182
        sideShapeAttributes.setInteriorOpacity(fillOpacity);
183
        return sideShapeAttributes;
184
    }
185

    
186
    private BasicShapeAttributes getNormalShapeAttributes(IVectorLegend legend) {
187
        
188
        if(this.normalShapeAttributes != null) {
189
            return this.normalShapeAttributes;
190
        }
191
        
192
        Material fillMaterial = Material.LIGHT_GRAY;
193
        Material outlineMaterial = Material.BLACK;
194
        double fillOpacity = 0.7;
195
        double outlineWidth = 2;
196

    
197
        ISymbol symbol = legend.getDefaultSymbol();
198
        if (symbol instanceof IFillSymbol) {
199
            IFillSymbol fillSymbol = (IFillSymbol) symbol;
200
            Color fillColor = fillSymbol.getFillColor();
201
            int fillAlpha = fillSymbol.getFillAlpha();
202
            ILineSymbol outline = fillSymbol.getOutline();
203
            Color lineColor = outline.getColor();
204
            fillMaterial = new Material(fillColor);
205
            outlineMaterial = new Material(lineColor);
206
            fillOpacity = fillAlpha / 255.0;
207
            outlineWidth = outline.getLineWidth();
208
        } else {
209
            outlineMaterial = new Material(this.parameters.getDefaultColor());
210
            fillMaterial = new Material(this.parameters.getDefaultColor());
211
            fillOpacity = 0.7;
212
            outlineWidth = 2;
213
        }
214
        normalShapeAttributes = new BasicShapeAttributes();
215
        normalShapeAttributes.setInteriorMaterial(fillMaterial);
216
        normalShapeAttributes.setInteriorOpacity(fillOpacity);
217
        normalShapeAttributes.setOutlineMaterial(outlineMaterial);
218
        normalShapeAttributes.setOutlineWidth(outlineWidth);
219
        return normalShapeAttributes;
220
    }
221

    
222
    /**
223
     * Slightly darken the supplied color.
224
     * 
225
     * @param color
226
     *            the color to make darker.
227
     * @return the darker color.
228
     */
229
    private Color darkenColor(Color color) {
230
        float factor = 0.8f;
231
        int r = color.getRed();
232
        int g = color.getGreen();
233
        int b = color.getBlue();
234
        return new Color(Math.max((int) (r * factor), 0), Math.max((int) (g * factor), 0),
235
            Math.max((int) (b * factor), 0));
236
    }
237

    
238
    @Override
239
    protected void clearRenderAttributes() {
240
        this.normalShapeAttributes = null;
241
        this.sideShapeAttributes = null;
242
    }
243
}