package com.spatial4j.demo;
import com.spatial4j.core.context.SpatialContext;
import com.spatial4j.core.context.jts.JtsSpatialContext;
import com.spatial4j.core.shape.Rectangle;
import com.spatial4j.core.shape.Shape;
import com.spatial4j.core.shape.jts.JtsGeometry;
import com.vividsolutions.jts.util.GeometricShapeFactory;
import de.micromata.opengis.kml.v_2_2_0.ColorMode;
import de.micromata.opengis.kml.v_2_2_0.Coordinate;
import de.micromata.opengis.kml.v_2_2_0.Document;
import de.micromata.opengis.kml.v_2_2_0.Folder;
import de.micromata.opengis.kml.v_2_2_0.Kml;
import de.micromata.opengis.kml.v_2_2_0.KmlFactory;
import de.micromata.opengis.kml.v_2_2_0.LineStyle;
import de.micromata.opengis.kml.v_2_2_0.Placemark;
import de.micromata.opengis.kml.v_2_2_0.PolyStyle;
import de.micromata.opengis.kml.v_2_2_0.StyleMap;
import de.micromata.opengis.kml.v_2_2_0.StyleState;
import org.apache.lucene.spatial.prefix.tree.Cell;
import org.apache.lucene.spatial.prefix.tree.QuadPrefixTree;
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class KMLHelper
{
public static void addStyles( Document document )
{
// Intersect
document.createAndAddStyle().withId( "IntersectStyleNorm" )
.withPolyStyle( new PolyStyle().withColor( "44787878" ).withColorMode( ColorMode.NORMAL ) )
.withLineStyle( new LineStyle().withColor( "99FFFFFF" ).withColorMode( ColorMode.NORMAL ).withWidth( 3 ) );
document.createAndAddStyle().withId( "IntersectStyleHI" )
.withPolyStyle( new PolyStyle().withColor( "88787878" ).withColorMode( ColorMode.NORMAL ) )
.withLineStyle( new LineStyle().withColor( "BB1400FF" ).withColorMode( ColorMode.NORMAL ).withWidth( 3 ) );
StyleMap sm = document.createAndAddStyleMap().withId( "iii" );
sm.createAndAddPair().withKey( StyleState.NORMAL ).withStyleUrl( "#IntersectStyleNorm" );
sm.createAndAddPair().withKey( StyleState.HIGHLIGHT ).withStyleUrl( "#IntersectStyleHI" );
// Covers
document.createAndAddStyle().withId( "CoversStyleNorm" )
.withPolyStyle( new PolyStyle().withColor( "993CDC14" ).withColorMode( ColorMode.NORMAL ) )
.withLineStyle( new LineStyle().withColor( "99FFFFFF" ).withColorMode( ColorMode.NORMAL ).withWidth( 3 ) );
document.createAndAddStyle().withId( "CoversStyleHI" )
.withPolyStyle( new PolyStyle().withColor( "BB3CDC14" ).withColorMode( ColorMode.NORMAL ) )
.withLineStyle( new LineStyle().withColor( "BB1400FF" ).withColorMode( ColorMode.NORMAL ).withWidth( 3 ) );
sm = document.createAndAddStyleMap().withId( "ccc" );
sm.createAndAddPair().withKey( StyleState.NORMAL ).withStyleUrl( "#CoversStyleNorm" );
sm.createAndAddPair().withKey( StyleState.HIGHLIGHT ).withStyleUrl( "#CoversStyleHI" );
// Covers
document.createAndAddStyle().withId( "MaxStyleNorm" )
.withPolyStyle( new PolyStyle().withColor( "991400E6" ).withColorMode( ColorMode.RANDOM ) )
.withLineStyle( new LineStyle().withColor( "99FFFFFF" ).withColorMode( ColorMode.NORMAL ).withWidth( 3 ) );
document.createAndAddStyle().withId( "MaxStyleHI" )
.withPolyStyle( new PolyStyle().withColor( "BB1400E6" ).withColorMode( ColorMode.RANDOM ) )
.withLineStyle( new LineStyle().withColor( "BB1400FF" ).withColorMode( ColorMode.NORMAL ).withWidth( 3 ) );
sm = document.createAndAddStyleMap().withId( "mmm" );
sm.createAndAddPair().withKey( StyleState.NORMAL ).withStyleUrl( "#MaxStyleNorm" );
sm.createAndAddPair().withKey( StyleState.HIGHLIGHT ).withStyleUrl( "#MaxStyleHI" );
}
private static List<Coordinate> getCoords( Shape s )
{
if( s instanceof Rectangle) {
Rectangle r = (Rectangle)s;
List<Coordinate> coords = new ArrayList<Coordinate>(5);
coords.add( new Coordinate( r.getMinX(),r.getMinY() ) );
coords.add( new Coordinate( r.getMaxX(),r.getMinY() ) );
coords.add( new Coordinate( r.getMaxX(),r.getMaxY() ) );
coords.add( new Coordinate( r.getMinX(),r.getMaxY() ) );
coords.add( new Coordinate( r.getMinX(),r.getMinY() ) );
return coords;
}
throw new IllegalArgumentException( "for now only extent supported..." );
}
private static Placemark create( String key, String style, SpatialPrefixTree grid )
{
final Cell cell = grid.getCell(key);
Shape r = cell.getShape();
List<Coordinate> coords = getCoords( r );
Placemark p = new Placemark().withName( key )
.withDescription( cell.toString() )
.withStyleUrl( style );
p.createAndSetPolygon()
.withTessellate( true )
.createAndSetOuterBoundaryIs()
.createAndSetLinearRing().withCoordinates( coords );
return p;
}
public static Kml toKML(String name, SpatialPrefixTree grid, List<? extends CharSequence> tokens )
{
final Kml kml = KmlFactory.createKml();
Document document = kml.createAndSetDocument()
.withName( name ).withOpen(false);
document.withDescription( tokens.size()+"" );
addStyles( document );
Folder folder = document.createAndAddFolder().withName( "tokens" );
for( CharSequence t : tokens ) {
String token = t.toString();
String style = token.charAt(token.length()-1) == (char) Cell.LEAF_BYTE ? "#ccc" : "#mmm";
folder.getFeature().add( create( token, style, grid ) );
}
return kml;
}
public static void main( String[] args ) throws Exception
{
SpatialContext ctx = SpatialContext.GEO;
QuadPrefixTree grid = new QuadPrefixTree(ctx, 16 ); // make it like WGS84
// CRSCache cache = new CRSCache();
// CoordinateReferenceSystem crs = cache.createFromName( "epsg:3785" ) ; //"EPSG:4326" ); //epsg:3785" );
// System.out.println();
// System.out.println( crs.getName() );
// Projection projection = new CylindricalEqualAreaProjection();
// grid = SpatialGridWithProjection.create( projection, 16 );
//
grid.printInfo(System.out);
Shape shape = null;
// shape = new PointRadiusIndexible( 5,5, 5 );
//
// shape = JtsGeom.parseGeometry( "MULTIPOINT((3.5 5.6), (4.8 9.5))" );
// shape = JtsGeom.parseGeometry( "POLYGON((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2))" );
// shape = JtsGeom.parseGeometry( "LINESTRING(3 4,5 7,8 2)" );
// shape = new JTSIndexible( "POINT(6 8)" ); // very small display!
// shape = new JTSIndexible( "POINT(3.5 5.6)" );
JtsSpatialContext jtsCtx = JtsSpatialContext.GEO;
ctx = jtsCtx;
//TODO why not use jtsCtx.getGeometryFrom(circle) ?
GeometricShapeFactory gsf = new GeometricShapeFactory(jtsCtx.getGeometryFactory());
gsf.setCentre( new com.vividsolutions.jts.geom.Coordinate( 4,2 ) );
gsf.setSize( 4 );
shape = new JtsGeometry( gsf.createCircle(), jtsCtx, true, false);
// USA -- http://openlayers.org/dev/examples/vector-formats.html
shape = ctx.readShape( "POLYGON((-125.22656679154 49.089853763581, -123.99609804154 46.453135013581, -123.99609804154 44.343760013581, -124.34766054154 42.585947513581, -124.17187929154 40.828135013581, -123.29297304154 39.246103763581, -122.76562929154 36.960947513581, -121.18359804154 34.851572513581, -118.89844179154 34.324228763581, -117.66797304154 33.093760013581, -114.85547304154 33.093760013581, -111.51562929154 31.687510013581, -108.52734804154 31.863291263581, -105.71484804154 31.511728763581, -104.13281679154 29.578135013581, -101.14453554154 29.929697513581, -100.44141054154 27.644541263581, -97.277348041542 25.886728763581, -96.046879291542 28.171885013581, -93.585941791542 29.402353763581, -90.421879291542 29.402353763581, -88.488285541542 29.050791263581, -88.312504291542 30.281260013581, -83.390629291542 29.929697513581, -82.160160541542 26.765635013581, -80.226566791542 24.832041263581, -79.171879291542 27.292978763581, -80.929691791542 31.511728763581, -75.304691791542 35.554697513581, -75.304691791542 37.664072513581, -72.316410541542 41.179697513581, -69.328129291542 41.882822513581, -69.855473041542 44.167978763581, -65.988285541542 45.046885013581, -67.921879291542 48.562510013581, -70.382816791542 47.507822513581, -70.910160541542 45.925791263581, -76.710941791542 45.222666263581, -79.523441791542 44.519541263581, -82.687504291542 46.277353763581, -84.972660541542 46.804697513581, -89.894535541542 47.859385013581, -95.167973041542 49.089853763581, -125.22656679154 49.089853763581))" );
// // NZ
// shape = grid.parse( "POLYGON((172.67870664597 -34.318349361419, 172.85448789597 -35.285146236419, 173.90917539597 -36.427724361419, 174.52440977097 -37.394521236419, 174.70019102097 -38.449208736419, 173.73339414597 -38.800771236419, 172.06347227097 -40.734364986419, 171.27245664597 -41.437489986419, 170.74511289597 -42.580068111419, 167.31737852097 -44.601552486419, 166.08690977097 -45.656239986419, 166.08690977097 -46.359364986419, 167.49315977097 -46.710927486419, 169.25097227097 -47.238271236419, 171.27245664597 -45.832021236419, 171.79980039597 -44.162099361419, 173.20605039597 -43.986318111419, 173.46972227097 -43.195302486419, 174.61230039597 -41.701161861419, 176.63378477097 -41.349599361419, 177.42480039597 -39.591786861419, 179.09472227097 -37.482411861419, 178.21581602097 -37.042958736419, 177.51269102097 -37.658193111419, 176.19433164597 -37.218739986419, 176.01855039597 -36.076161861419, 174.61230039597 -34.933583736419, 172.67870664597 -34.318349361419))" );
//
// // NZ small
// shape = grid.parse( "POLYGON((177.71347045897 -39.051589965823, 177.78762817382 -39.062576293948, 177.81784057616 -39.081802368167, 177.85079956054 -39.062576293948, 177.86453247069 -39.081802368167, 177.85903930663 -39.114761352542, 177.83706665038 -39.161453247073, 177.8123474121 -39.172439575198, 177.83706665038 -39.21913146973, 177.86178588866 -39.268569946292, 177.90847778319 -39.227371215823, 177.92495727538 -39.17518615723, 177.94692993163 -39.15321350098, 177.94692993163 -39.13124084473, 177.96066284179 -39.139480590823, 177.99636840819 -39.120254516605, 178.01284790038 -39.103775024417, 177.96066284179 -39.090042114261, 177.92221069335 -39.08729553223, 177.90847778319 -39.06532287598, 177.89474487304 -39.035110473636, 177.89749145507 -38.996658325198, 177.91122436522 -38.966445922855, 177.71347045897 -39.051589965823))" );
//
// // SF
// shape = grid.parse( "POLYGON((-122.497288225 37.683619017479, -122.50003480703 37.70833825576, -122.50827455313 37.727564329979, -122.50827455313 37.746790404198, -122.50758790762 37.759836668846, -122.51376771719 37.783182616112, -122.50758790762 37.792109007714, -122.48767518789 37.792109007714, -122.47531556875 37.812708372948, -122.46776246817 37.814768309471, -122.45814943106 37.809275145409, -122.43686342031 37.812708372948, -122.42313051016 37.809275145409, -122.4093976 37.814081663964, -122.39360475332 37.805155272362, -122.3826184252 37.793482298729, -122.37918519766 37.780436034081, -122.37918519766 37.766703123925, -122.37781190664 37.756403441307, -122.37712526113 37.746790404198, -122.37918519766 37.743357176659, -122.36888551504 37.733057494042, -122.36064576895 37.737864012596, -122.35240602285 37.73031091201, -122.3565258959 37.72413110244, -122.35858583242 37.715204710839, -122.37094545156 37.717264647362, -122.3743786791 37.72413110244, -122.37575197012 37.720011229393, -122.38124513418 37.714518065331, -122.36270570547 37.70215844619, -122.36407899649 37.696665282128, -122.37025880606 37.694605345604, -122.38742494375 37.711084837792, -122.38879823477 37.711084837792, -122.3826184252 37.693918700096, -122.38055848867 37.684305662987, -122.497288225 37.683619017479))" );
// shape = shape.project( projection, false );
// shape = new RectangleImpl( -170,-85, 170, 85 );
List<String> vals = SpatialPrefixTree.cellsToTokenStrings(grid.getCells(shape,5,false,true)); //new GeometryShape( shape ) ); //new EnvelopeShape( shape.getEnvelopeInternal() ) );
System.out.println( vals );
// StringBuilder str = new StringBuilder();
// vals = new MatchInfo();
// for( int i=0; i<10; i++ ) {
// str.append( 'A' );
// vals.getLevelInfo(i, true).intersects.add( str.toString() );
// }
// vals.printInfo();
File outfile = new File( "c:/temp/test.kml" );
Kml kml = toKML( "test: 3785", grid, vals );
kml.marshal(outfile);
System.out.println( "done." );
}
}