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 / DefaultVectorExtrusionRenderableLayer.java @ 774

History | View | Annotate | Download (16.2 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.MultiLine;
40
import org.gvsig.fmap.geom.aggregate.MultiPoint;
41
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
42
import org.gvsig.fmap.geom.primitive.Curve;
43
import org.gvsig.fmap.geom.primitive.Line;
44
import org.gvsig.fmap.geom.primitive.Point;
45
import org.gvsig.fmap.geom.primitive.Polygon;
46
import org.gvsig.fmap.geom.primitive.Ring;
47
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
48
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
49
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.fill.IFillSymbol;
50
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.ILineSymbol;
51
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.marker.ISimpleMarkerSymbol;
52
import org.gvsig.view3d.vector.lib.api.VectorElevationMode;
53
import org.gvsig.view3d.vector.lib.api.VectorExtrusionLoaderParameters;
54
import org.gvsig.view3d.vector.lib.api.VectorLoaderParameters;
55
import org.gvsig.view3d.vector.lib.impl.AbstractRenderableLayer;
56

    
57
import gov.nasa.worldwind.geom.Position;
58
import gov.nasa.worldwind.render.BasicShapeAttributes;
59
import gov.nasa.worldwind.render.ExtrudedPolygon;
60
import gov.nasa.worldwind.render.Material;
61
import gov.nasa.worldwind.render.Path;
62
import gov.nasa.worldwind.render.PointPlacemark;
63
import gov.nasa.worldwind.render.PointPlacemarkAttributes;
64
import gov.nasa.worldwind.render.Renderable;
65

    
66
/**
67
 * 
68
 * @author <a href="mailto:lmarques@disid.com">Lluis Marques</a>
69
 *
70
 */
71
public class DefaultVectorExtrusionRenderableLayer extends AbstractRenderableLayer {
72

    
73
    private BasicShapeAttributes polygonShapeAttributes;
74
    private BasicShapeAttributes sideShapeAttributes;
75
    private PointPlacemarkAttributes markAttributes;
76
    private BasicShapeAttributes lineShapeAttributes;
77

    
78
    public DefaultVectorExtrusionRenderableLayer(VectorLoaderParameters parameters, FeatureStore featureStore,
79
        IVectorLegend legend) {
80
        super(parameters, featureStore, legend);
81
    }
82

    
83
    @Override
84
    protected List<Renderable> getRenderables(Feature feature) {
85

    
86
        double heightFieldValue = 0;
87
        String heightField = ((VectorExtrusionLoaderParameters) parameters).getHeightField();
88
        if (StringUtils.isNoneBlank(heightField)) {
89
            heightFieldValue = feature.getDouble(heightField);
90
        }
91

    
92
        Geometry geom = feature.getDefaultGeometry();
93
        List<Renderable> renderables = new ArrayList<>();
94
        if (geom.getGeometryType().isTypeOf(TYPES.MULTIPOLYGON)) {
95
            MultiPolygon multiPolygon = (MultiPolygon) geom;
96
            for (int i = 0; i < multiPolygon.getPrimitivesNumber(); i++) {
97
                Polygon polygon = (Polygon) multiPolygon.getSurfaceAt(i);
98
                if (polygon.getNumVertices() >= 4) {
99
                    renderables.add(getRenderable(polygon, heightFieldValue));
100
                }
101
            }
102
        } else if (geom.getGeometryType().isTypeOf(TYPES.POLYGON)) {
103
            Polygon polygon = (Polygon) geom;
104
            if (polygon.getNumVertices() >= 4) {
105
                renderables.add(getRenderable(polygon, heightFieldValue));
106
            }
107
        } else if (geom.getGeometryType().isTypeOf(TYPES.MULTIPOINT)) {
108
            MultiPoint multiPoint = (MultiPoint) geom;
109
            for (int i = 0; i < multiPoint.getPrimitivesNumber(); i++) {
110
                renderables.add(getRenderable(multiPoint.getPointAt(i), heightFieldValue));
111
            }
112
        } else if (geom.getGeometryType().isTypeOf(TYPES.POINT)) {
113
            renderables.add(getRenderable((Point) geom, heightFieldValue));
114
        } else if (geom.getGeometryType().isTypeOf(TYPES.MULTILINE)) {
115
            MultiLine multiLine = (MultiLine) geom;
116
            for (int i = 0; i < multiLine.getPrimitivesNumber(); i++) {
117
                if (multiLine.getCurveAt(i).getNumVertices() >= 2) {
118
                    renderables.add(getRenderable(multiLine.getCurveAt(i), heightFieldValue));
119
                }
120
            }
121
        } else if (geom.getGeometryType().isTypeOf(TYPES.LINE) && ((Line) geom).getNumVertices() >= 2) {
122
            renderables.add(getRenderable((Line) geom, heightFieldValue));
123
        }
124
        return renderables;
125
    }
126

    
127
    @Override
128
    protected FeatureQuery getFeatureQuery() throws DataException {
129
        FeatureQuery featureQuery = super.getFeatureQuery();
130
        // Add field height to feature query
131
        String fieldHeight = ((VectorExtrusionLoaderParameters) parameters).getHeightField();
132
        if (StringUtils.isNotBlank(fieldHeight)) {
133
            featureQuery.addAttributeName(fieldHeight);
134
        }
135
        return featureQuery;
136
    }
137

    
138
    private ExtrudedPolygon getRenderable(Polygon polygon, double heightFieldValue) {
139
        ExtrudedPolygon renderable = new ExtrudedPolygon();
140
        boolean hasZ = polygon.getDimension() > 2;
141
        double h = 0.0;
142

    
143
        if (VectorElevationMode.CLAMP_TO_GROUND.equals(parameters.getVectorElevationMode())) {
144
            hasZ = false;
145
        } else {
146
            if (VectorElevationMode.RELATIVE_TO_GROUND.equals(parameters.getVectorElevationMode())) {
147
                hasZ = false;
148
            }
149
            if (parameters.getConstantHeight() != null) {
150
                h = parameters.getConstantHeight();
151
            }
152
        }
153
        h += heightFieldValue;
154
        h *= ((VectorExtrusionLoaderParameters) parameters).getVerticalExaggeration();
155

    
156
        ICoordTrans coordTrans = getCoordTrans(this.parameters.getLayer().getProjection());
157
        List<Position> verticesList = getVertices(polygon, h, hasZ, coordTrans);
158
        renderable.setOuterBoundary(verticesList);
159

    
160
        int numInteriorRings = polygon.getNumInteriorRings();
161
        for (int i = 0; i < numInteriorRings; i++) {
162
            renderable.addInnerBoundary(getInteriorRing(polygon.getInteriorRing(i), hasZ, h));
163
        }
164
        renderable.setAltitudeMode(getAltitudeMode(this.parameters.getVectorElevationMode()));
165
        renderable.setAttributes(getPolygonShapeAttributes(legend));
166
        renderable.setSideAttributes(getSideShapeAttributes(legend));
167
        return renderable;
168
    }
169

    
170
    private List<Position> getInteriorRing(Ring interiorRing, boolean hasZ, double h) {
171
        int internalNumVertices = interiorRing.getNumVertices();
172
        List<Position> internalVerticesList = new ArrayList<>(internalNumVertices);
173
        for (int j = 0; j < internalNumVertices; j++) {
174
            Point vertex = interiorRing.getVertex(j);
175
            if (hasZ) {
176
                double z = vertex.getCoordinateAt(2);
177
                internalVerticesList.add(Position.fromDegrees(vertex.getY(), vertex.getX(), z + h));
178
            } else {
179
                internalVerticesList.add(Position.fromDegrees(vertex.getY(), vertex.getX(), h));
180
            }
181
        }
182
        return internalVerticesList;
183
    }
184

    
185
    private BasicShapeAttributes getSideShapeAttributes(IVectorLegend legend) {
186

    
187
        if (this.sideShapeAttributes != null) {
188
            return this.sideShapeAttributes;
189
        }
190

    
191
        Material sideFillMaterial = Material.GRAY;
192
        double fillOpacity = 0.7;
193

    
194
        ISymbol symbol = legend.getDefaultSymbol();
195
        if (symbol instanceof IFillSymbol) {
196
            IFillSymbol fillSymbol = (IFillSymbol) symbol;
197
            Color fillColor = fillSymbol.getFillColor();
198
            int fillAlpha = fillSymbol.getFillAlpha();
199
            Color sideFillColor = darkenColor(fillColor);
200
            sideFillMaterial = new Material(sideFillColor);
201
            fillOpacity = fillAlpha / 255.0;
202
        } else {
203
            sideFillMaterial = new Material(this.parameters.getDefaultColor());
204
            fillOpacity = 0.7;
205
        }
206
        sideShapeAttributes = new BasicShapeAttributes();
207
        sideShapeAttributes.setInteriorMaterial(sideFillMaterial);
208
        sideShapeAttributes.setInteriorOpacity(fillOpacity);
209
        return sideShapeAttributes;
210
    }
211

    
212
    private BasicShapeAttributes getPolygonShapeAttributes(IVectorLegend legend) {
213

    
214
        if (this.polygonShapeAttributes != null) {
215
            return this.polygonShapeAttributes;
216
        }
217

    
218
        Material fillMaterial = Material.LIGHT_GRAY;
219
        Material outlineMaterial = Material.BLACK;
220
        double fillOpacity = 0.7;
221
        double outlineWidth = 2;
222

    
223
        ISymbol symbol = legend.getDefaultSymbol();
224
        if (symbol instanceof IFillSymbol) {
225
            IFillSymbol fillSymbol = (IFillSymbol) symbol;
226
            Color fillColor = fillSymbol.getFillColor();
227
            int fillAlpha = fillSymbol.getFillAlpha();
228
            ILineSymbol outline = fillSymbol.getOutline();
229
            Color lineColor = outline.getColor();
230
            fillMaterial = new Material(fillColor);
231
            outlineMaterial = new Material(lineColor);
232
            fillOpacity = fillAlpha / 255.0;
233
            outlineWidth = outline.getLineWidth();
234
        } else {
235
            outlineMaterial = new Material(this.parameters.getDefaultColor());
236
            fillMaterial = new Material(this.parameters.getDefaultColor());
237
            fillOpacity = 0.7;
238
            outlineWidth = 2;
239
        }
240
        polygonShapeAttributes = new BasicShapeAttributes();
241
        polygonShapeAttributes.setInteriorMaterial(fillMaterial);
242
        polygonShapeAttributes.setInteriorOpacity(fillOpacity);
243
        polygonShapeAttributes.setOutlineMaterial(outlineMaterial);
244
        polygonShapeAttributes.setOutlineWidth(outlineWidth);
245
        return polygonShapeAttributes;
246
    }
247

    
248
    private PointPlacemark getRenderable(Point point, double heightFieldValue) {
249
        boolean hasZ = point.getDimension() > 2;
250
        double h = 0.0;
251

    
252
        ICoordTrans coordTrans = getCoordTrans(this.parameters.getLayer().getProjection());
253
        if (coordTrans != null) {
254
            point.reProject(coordTrans);
255
        }
256

    
257
        double y = point.getY();
258
        double x = point.getX();
259

    
260
        if (VectorElevationMode.CLAMP_TO_GROUND.equals(parameters.getVectorElevationMode())) {
261
            hasZ = false;
262
        } else {
263
            if (VectorElevationMode.RELATIVE_TO_GROUND.equals(parameters.getVectorElevationMode())) {
264
                hasZ = false;
265
            }
266
            if (parameters.getConstantHeight() != null) {
267
                h = parameters.getConstantHeight();
268
            }
269
        }
270
        h += heightFieldValue;
271
        h *= ((VectorExtrusionLoaderParameters) parameters).getVerticalExaggeration();
272
        PointPlacemark marker;
273
        if (hasZ) {
274
            double z = point.getCoordinateAt(2);
275
            marker = new PointPlacemark(Position.fromDegrees(y, x, z + h));
276
        } else {
277
            Position position = Position.fromDegrees(y, x, h);
278
            marker = new PointPlacemark(position);
279
        }
280
        marker.setAltitudeMode(getAltitudeMode(parameters.getVectorElevationMode()));
281
        marker.setLineEnabled(true);
282
        marker.setAttributes(this.getBasicMarkerAttributes(legend));
283
        return marker;
284
    }
285

    
286
    private PointPlacemarkAttributes getBasicMarkerAttributes(IVectorLegend legend) {
287

    
288
        if (this.markAttributes != null) {
289
            return this.markAttributes;
290
        }
291

    
292
        double markerSize = 0;
293
        Material fillMaterial = null;
294

    
295
        if (legend == null) {
296
            fillMaterial = new Material(parameters.getDefaultColor());
297
            markerSize = 0.3;
298
        } else {
299
            ISymbol symbol = legend.getDefaultSymbol();
300
            if (symbol instanceof ISimpleMarkerSymbol) {
301
                ISimpleMarkerSymbol markerSymbol = (ISimpleMarkerSymbol) symbol;
302
                Color fillColor = markerSymbol.getColor();
303
                markerSize = markerSymbol.getSize();
304
                fillMaterial = new Material(fillColor);
305
            } else {
306
                fillMaterial = new Material(parameters.getDefaultColor());
307
                markerSize = 4;
308
            }
309
        }
310
        markAttributes = new PointPlacemarkAttributes();
311
        Color color = fillMaterial.getDiffuse();
312
        markAttributes.setImageColor(color);
313
        markAttributes.setLineMaterial(fillMaterial);
314
        markAttributes.setLineWidth(1d);
315
        markAttributes.setUsePointAsDefaultImage(true);
316
        markAttributes.setScale(markerSize);
317
        return markAttributes;
318
    }
319

    
320
    private Renderable getRenderable(Curve curve, double heightFieldValue) {
321
        boolean hasZ = curve.getDimension() > 2;
322
        double h = 0.0;
323

    
324
        if (VectorElevationMode.CLAMP_TO_GROUND.equals(parameters.getVectorElevationMode())) {
325
            hasZ = false;
326
        } else {
327
            if (VectorElevationMode.RELATIVE_TO_GROUND.equals(parameters.getVectorElevationMode())) {
328
                hasZ = false;
329
            }
330
            if (parameters.getConstantHeight() != null) {
331
                h = parameters.getConstantHeight();
332
            }
333
        }
334

    
335
        h += heightFieldValue;
336
        h *= ((VectorExtrusionLoaderParameters) parameters).getVerticalExaggeration();
337
        ICoordTrans coordTrans = getCoordTrans(this.parameters.getLayer().getProjection());
338
        List<Position> verticesList = getVertices(curve, h, hasZ, coordTrans);
339
        Path path = new Path(verticesList);
340
        path.setAltitudeMode(getAltitudeMode(this.parameters.getVectorElevationMode()));
341
        path.setAttributes(getLineShapAttributes(legend));
342
        path.setExtrude(true);
343
        return path;
344
    }
345

    
346
    private BasicShapeAttributes getLineShapAttributes(IVectorLegend legend) {
347

    
348
        if (lineShapeAttributes != null) {
349
            return this.lineShapeAttributes;
350
        }
351

    
352
        Material outlineMaterial;
353
        double outlineOpacity = 1.0;
354
        double outlineWidth = 3.0;
355

    
356
        ISymbol symbol = legend.getDefaultSymbol();
357
        if (symbol instanceof ILineSymbol) {
358
            ILineSymbol lineSymbol = (ILineSymbol) symbol;
359
            Color lineColor = lineSymbol.getColor();
360
            int lineAlpha = lineSymbol.getAlpha();
361
            outlineMaterial = new Material(lineColor);
362
            outlineOpacity = lineAlpha / 255.0;
363
            outlineWidth = lineSymbol.getLineWidth();
364
        } else {
365
            outlineMaterial = new Material(this.parameters.getDefaultColor());
366
            outlineOpacity = 1.0;
367
            outlineWidth = 3.0;
368
        }
369
        lineShapeAttributes = new BasicShapeAttributes();
370
        lineShapeAttributes.setOutlineMaterial(outlineMaterial);
371
        lineShapeAttributes.setOutlineWidth(outlineWidth);
372
        lineShapeAttributes.setOutlineOpacity(outlineOpacity);
373
        return lineShapeAttributes;
374
    }
375

    
376
    /**
377
     * Slightly darken the supplied color.
378
     * 
379
     * @param color
380
     *            the color to make darker.
381
     * @return the darker color.
382
     */
383
    private Color darkenColor(Color color) {
384
        float factor = 0.8f;
385
        int r = color.getRed();
386
        int g = color.getGreen();
387
        int b = color.getBlue();
388
        return new Color(Math.max((int) (r * factor), 0), Math.max((int) (g * factor), 0),
389
            Math.max((int) (b * factor), 0));
390
    }
391

    
392
    @Override
393
    protected void clearRenderAttributes() {
394
        this.polygonShapeAttributes = null;
395
        this.sideShapeAttributes = null;
396
        this.markAttributes = null;
397
        this.lineShapeAttributes = null;
398
    }
399
}