/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2014, Geomatys
*
* 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.
*/
package org.geotoolkit.gui.javafx.render2d.shape;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.paint.Paint;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.Polyline;
import javafx.scene.shape.Shape;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.shape.StrokeLineJoin;
import javafx.scene.shape.StrokeType;
import org.geotoolkit.gui.javafx.util.FXUtilities;
/**
* Convert a JTS Geometry in a JavaFX Shape.
* JavaFX has a very limited geometry model, multi part geometries and holes
* can not be create directly.
* As a result the jts geometry is translated as a group of smaller geometries.
*
* @author Johann Sorel (Geomatys)
*/
public class FXGeometry extends Group {
private final Geometry geometry;
private final Node shape;
public FXGeometry(Geometry geometry) {
this.geometry = geometry;
this.shape = toShape(geometry);
getChildren().add(shape);
}
public void setFill(final Paint paint){
FXUtilities.visit(this, (Node n) -> {if(n instanceof Shape)((Shape)n).setFill(paint);});
}
public void setStroke(final Paint paint){
FXUtilities.visit(this, (Node n) -> {if(n instanceof Shape)((Shape)n).setStroke(paint);});
}
public void setStrokeDashOffset(final double offset){
FXUtilities.visit(this, (Node n) -> {if(n instanceof Shape)((Shape)n).setStrokeDashOffset(offset);});
}
public void setStrokeLineCap(final StrokeLineCap cap){
FXUtilities.visit(this, (Node n) -> {if(n instanceof Shape)((Shape)n).setStrokeLineCap(cap);});
}
public void setStrokeLineJoin(final StrokeLineJoin join){
FXUtilities.visit(this, (Node n) -> {if(n instanceof Shape)((Shape)n).setStrokeLineJoin(join);});
}
public void setStrokeMiterLimit(final double value){
FXUtilities.visit(this, (Node n) -> {if(n instanceof Shape)((Shape)n).setStrokeMiterLimit(value);});
}
public void setStrokeType(final StrokeType type){
FXUtilities.visit(this, (Node n) -> {if(n instanceof Shape)((Shape)n).setStrokeType(type);});
}
public void setStrokeWidth(final double value){
FXUtilities.visit(this, (Node n) -> {if(n instanceof Shape)((Shape)n).setStrokeWidth(value);});
}
public void setSmooth(final boolean smooth){
FXUtilities.visit(this, (Node n) -> {if(n instanceof Shape)((Shape)n).setSmooth(smooth);});
}
private static Node toShape(Geometry jts){
if(jts.isEmpty()){
//do nothing
return new Group();
}else if(jts instanceof Point){
final Point geom = (Point) jts;
final Path fxgeom = new Path();
fxgeom.getElements().add(new MoveTo(geom.getX(),geom.getY()));
fxgeom.getElements().add(new LineTo(geom.getX(),geom.getY()));
fxgeom.setCache(false);
return fxgeom;
}else if(jts instanceof LineString){
final LineString geom = (LineString) jts;
return toShape(geom,false);
}else if(jts instanceof Polygon){
//append exterior
final Polygon geom = (Polygon) jts;
final LineString exterior = geom.getExteriorRing();
Shape fxgeom = toShape(exterior, true);
//remove holes
final int nbHole = geom.getNumInteriorRing();
for(int i=0;i<nbHole;i++){
final LineString interior = geom.getInteriorRingN(i);
fxgeom = Shape.subtract(fxgeom, toShape(interior, true));
}
fxgeom.setCache(false);
return fxgeom;
}else if(jts instanceof GeometryCollection){
final GeometryCollection geom = (GeometryCollection)jts;
final Group fxgeom = new Group();
final int nbGeom = geom.getNumGeometries();
for(int i=0;i<nbGeom;i++){
fxgeom.getChildren().add(toShape(geom.getGeometryN(i)));
}
fxgeom.setCache(false);
return fxgeom;
}else{
throw new IllegalArgumentException("Unexpected geometry type : "+jts);
}
}
private static Shape toShape(LineString geom, boolean closed){
final Coordinate[] coords = geom.getCoordinates();
final double[] vals = new double[coords.length*2];
for(int x=0,i=0;i<coords.length;i++){
vals[x++] = coords[i].x;
vals[x++] = coords[i].y;
}
final Shape fxgeom;
if(closed){
fxgeom = new javafx.scene.shape.Polygon(vals);
}else{
fxgeom = new Polyline(vals);
}
fxgeom.setCache(false);
return fxgeom;
}
}