/*
* This file is part of JGrasstools (http://www.jgrasstools.org)
* (C) HydroloGIS - www.hydrologis.com
*
* JGrasstools is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jgrasstools.nww.layers.defaults.vector;
import java.awt.Color;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.jgrasstools.gears.utils.geometry.EGeometryType;
import org.jgrasstools.gears.utils.geometry.GeometryUtilities;
import org.jgrasstools.gears.utils.style.SimpleStyle;
import org.jgrasstools.gears.utils.style.SimpleStyleUtilities;
import org.jgrasstools.nww.layers.defaults.NwwLayer;
import org.jgrasstools.nww.shapes.FeatureLine;
import org.jgrasstools.nww.shapes.FeaturePolygon;
import org.jgrasstools.nww.utils.NwwUtilities;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.type.GeometryDescriptor;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Point;
import gov.nasa.worldwind.WorldWind;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.render.BasicShapeAttributes;
import gov.nasa.worldwind.render.Material;
import gov.nasa.worldwind.render.PointPlacemark;
import gov.nasa.worldwind.render.PointPlacemarkAttributes;
import gov.nasa.worldwind.render.airspaces.AirspaceAttributes;
/**
* A simple lines layer.
*
* @author Andrea Antonello andrea.antonello@gmail.com
*/
public class ShapefilesFolderLayer extends RenderableLayer implements NwwLayer {
private int mElevationMode = WorldWind.CLAMP_TO_GROUND;
private String title;
private AirspaceAttributes highlightAttrs;
private File[] shpFiles;
private ReferencedEnvelope bounds;
public ShapefilesFolderLayer( String folderPath ) throws IOException {
File folderFile = new File(folderPath);
shpFiles = folderFile.listFiles(new FilenameFilter(){
@Override
public boolean accept( File dir, String name ) {
return name.toLowerCase().endsWith(".shp");
}
});
this.title = folderFile.getName();
if (shpFiles.length == 0) {
throw new IOException("No data found in folder.");
}
loadData();
}
public void loadData() {
Thread t = new WorkerThread();
t.start();
}
public class WorkerThread extends Thread {
public void run() {
for( File shpFile : shpFiles ) {
try {
SimpleFeatureCollection readFC = NwwUtilities.readAndReproject(shpFile.getAbsolutePath());
ReferencedEnvelope tmpBounds = readFC.getBounds();
if (tmpBounds.getWidth() == 0 || tmpBounds.getHeight() == 0) {
continue;
}
if (bounds == null) {
bounds = new ReferencedEnvelope(tmpBounds);
} else {
bounds.expandToInclude(tmpBounds);
}
GeometryDescriptor geometryDescriptor = readFC.getSchema().getGeometryDescriptor();
if (EGeometryType.isPolygon(geometryDescriptor)) {
Material fillMaterial = Material.BLACK;
Material strokeMaterial = Material.BLACK;
double fillOpacity = 0.7;
double strokeWidth = 2;
BasicShapeAttributes shapeAttributes = new BasicShapeAttributes();
SimpleStyle style = SimpleStyleUtilities.getStyle(shpFile.getAbsolutePath(), EGeometryType.POLYGON);
if (style != null) {
fillMaterial = new Material(style.fillColor);
fillOpacity = style.fillOpacity;
strokeMaterial = new Material(style.strokeColor);
strokeWidth = style.strokeWidth;
}
shapeAttributes.setInteriorMaterial(fillMaterial);
shapeAttributes.setInteriorOpacity(fillOpacity);
shapeAttributes.setOutlineMaterial(strokeMaterial);
shapeAttributes.setOutlineWidth(strokeWidth);
SimpleFeatureIterator featureIterator = readFC.features();
try {
while( featureIterator.hasNext() ) {
SimpleFeature polygonAreaFeature = featureIterator.next();
addPolygon(polygonAreaFeature, shapeAttributes);
}
} finally {
featureIterator.close();
}
} else if (EGeometryType.isLine(geometryDescriptor)) {
Material strokeMaterial = Material.BLACK;
double strokeWidth = 2;
BasicShapeAttributes shapeAttributes = new BasicShapeAttributes();
SimpleStyle style = SimpleStyleUtilities.getStyle(shpFile.getAbsolutePath(), EGeometryType.LINE);
if (style != null) {
strokeMaterial = new Material(style.strokeColor);
strokeWidth = style.strokeWidth;
}
shapeAttributes.setOutlineMaterial(strokeMaterial);
shapeAttributes.setOutlineWidth(strokeWidth);
SimpleFeatureIterator featureIterator = readFC.features();
try {
while( featureIterator.hasNext() ) {
SimpleFeature lineFeature = featureIterator.next();
addLine(lineFeature, shapeAttributes);
}
} finally {
featureIterator.close();
}
} else if (EGeometryType.isPoint(geometryDescriptor)) {
Material fillMaterial = Material.GREEN;
double markerSize = 5d;
SimpleStyle style = SimpleStyleUtilities.getStyle(shpFile.getAbsolutePath(), EGeometryType.POINT);
if (style != null) {
fillMaterial = new Material(style.fillColor);
markerSize = style.shapeSize;
}
PointPlacemarkAttributes basicMarkerAttributes = new PointPlacemarkAttributes();
Color color = fillMaterial.getDiffuse();
basicMarkerAttributes.setImageColor(color);
// basicMarkerAttributes.setLineMaterial(new Material(darkenColor));
// basicMarkerAttributes.setLineWidth(1d);
basicMarkerAttributes.setUsePointAsDefaultImage(true);
basicMarkerAttributes.setScale(markerSize);
SimpleFeatureIterator featureIterator = readFC.features();
try {
while( featureIterator.hasNext() ) {
SimpleFeature pointFeature = featureIterator.next();
Geometry geometry = (Geometry) pointFeature.getDefaultGeometry();
if (geometry == null) {
continue;
}
int numGeometries = geometry.getNumGeometries();
for( int i = 0; i < numGeometries; i++ ) {
Geometry geometryN = geometry.getGeometryN(i);
if (geometryN instanceof Point) {
Point point = (Point) geometryN;
double x = point.getX();
double y = point.getY();
Position position = Position.fromDegrees(y, x);
PointPlacemark marker = new PointPlacemark(position);
marker.setAltitudeMode(mElevationMode);
// marker.setLineEnabled(applyExtrusion);
marker.setAttributes(basicMarkerAttributes);
}
}
}
} finally {
featureIterator.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private void addLine( SimpleFeature lineFeature, BasicShapeAttributes shapeAttributes ) {
Geometry geometry = (Geometry) lineFeature.getDefaultGeometry();
if (geometry == null) {
return;
}
Coordinate[] coordinates = geometry.getCoordinates();
if (coordinates.length < 2)
return;
int numGeometries = geometry.getNumGeometries();
for( int i = 0; i < numGeometries; i++ ) {
Geometry geometryN = geometry.getGeometryN(i);
if (geometryN instanceof LineString) {
LineString line = (LineString) geometryN;
Coordinate[] lineCoords = line.getCoordinates();
int numVertices = lineCoords.length;
List<Position> verticesList = new ArrayList<>(numVertices);
for( int j = 0; j < numVertices; j++ ) {
Coordinate c = lineCoords[j];
verticesList.add(Position.fromDegrees(c.y, c.x));
}
FeatureLine path = new FeatureLine(verticesList, null);
path.setFeature(lineFeature);
path.setAltitudeMode(mElevationMode);
path.setAttributes(shapeAttributes);
path.setHighlightAttributes(highlightAttrs);
addRenderable(path);
}
}
}
private void addPolygon( SimpleFeature polygonAreaFeature, BasicShapeAttributes shapeAttributes ) {
Geometry geometry = (Geometry) polygonAreaFeature.getDefaultGeometry();
if (geometry == null) {
return;
}
Coordinate[] coordinates = geometry.getCoordinates();
int numVertices = coordinates.length;
if (numVertices < 4)
return;
int numGeometries = geometry.getNumGeometries();
for( int i = 0; i < numGeometries; i++ ) {
Geometry geometryN = geometry.getGeometryN(i);
if (geometryN instanceof com.vividsolutions.jts.geom.Polygon) {
com.vividsolutions.jts.geom.Polygon poly = (com.vividsolutions.jts.geom.Polygon) geometryN;
FeaturePolygon polygon = new FeaturePolygon(null);
polygon.setFeature(polygonAreaFeature);
Coordinate[] extCoords = poly.getExteriorRing().getCoordinates();
int extSize = extCoords.length;
List<Position> verticesList = new ArrayList<>(extSize);
for( int n = 0; n < extSize; n++ ) {
Coordinate c = extCoords[n];
verticesList.add(Position.fromDegrees(c.y, c.x));
}
verticesList.add(verticesList.get(0));
polygon.setOuterBoundary(verticesList);
int numInteriorRings = poly.getNumInteriorRing();
for( int k = 0; k < numInteriorRings; k++ ) {
LineString interiorRing = poly.getInteriorRingN(k);
Coordinate[] intCoords = interiorRing.getCoordinates();
int internalNumVertices = intCoords.length;
List<Position> internalVerticesList = new ArrayList<>(internalNumVertices);
for( int j = 0; j < internalNumVertices; j++ ) {
Coordinate c = intCoords[j];
internalVerticesList.add(Position.fromDegrees(c.y, c.x));
}
polygon.addInnerBoundary(internalVerticesList);
}
polygon.setAltitudeMode(mElevationMode);
polygon.setAttributes(shapeAttributes);
addRenderable(polygon);
}
}
}
@Override
public String toString() {
return title != null ? title : "Lines";
}
@Override
public Coordinate getCenter() {
if (bounds != null)
return bounds.centre();
else
return new Coordinate(0, 0);
}
}