/*******************************************************************************
* Copyright (c) 2015 Voyager Search and MITRE
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Apache License, Version 2.0 which
* accompanies this distribution and is available at
* http://www.apache.org/licenses/LICENSE-2.0.txt
******************************************************************************/
package org.locationtech.spatial4j.context.jts;
import org.locationtech.spatial4j.context.SpatialContextFactory;
import org.locationtech.spatial4j.io.GeoJSONReader;
import org.locationtech.spatial4j.io.LegacyShapeReader;
import org.locationtech.spatial4j.io.LegacyShapeWriter;
import org.locationtech.spatial4j.io.PolyshapeReader;
import org.locationtech.spatial4j.io.WKTReader;
import org.locationtech.spatial4j.io.jts.*;
import org.locationtech.spatial4j.shape.jts.JtsShapeFactory;
import com.vividsolutions.jts.geom.CoordinateSequenceFactory;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.PrecisionModel;
import com.vividsolutions.jts.geom.impl.CoordinateArraySequenceFactory;
import java.util.Map;
/**
* See {@link SpatialContextFactory#makeSpatialContext(java.util.Map, ClassLoader)}.
* <p>
* The following keys are looked up in the args map, in addition to those in the
* superclass:
* <DL>
* <DT>datelineRule</DT>
* <DD>width180(default)|ccwRect|none
* -- see {@link DatelineRule}</DD>
* <DT>validationRule</DT>
* <DD>error(default)|none|repairConvexHull|repairBuffer0
* -- see {@link ValidationRule}</DD>
* <DT>autoIndex</DT>
* <DD>true|false(default) -- see {@link JtsShapeFactory#isAutoIndex()}</DD>
* <DT>allowMultiOverlap</DT>
* <DD>true|false(default) -- see {@link JtsSpatialContext#isAllowMultiOverlap()}</DD>
* <DT>precisionModel</DT>
* <DD>floating(default) | floating_single | fixed
* -- see {@link com.vividsolutions.jts.geom.PrecisionModel}.
* If {@code fixed} then you must also provide {@code precisionScale}
* -- see {@link com.vividsolutions.jts.geom.PrecisionModel#getScale()}</DD>
* <DT>useJtsPoint, useJtsLineString, useJtsMulti</DT>
* <DD>All default to true. See corresponding methods on {@link JtsShapeFactory}.</DD>
* </DL>
*/
public class JtsSpatialContextFactory extends SpatialContextFactory {
protected static final PrecisionModel defaultPrecisionModel = new PrecisionModel();//floating
//These 3 are JTS defaults for new GeometryFactory()
public PrecisionModel precisionModel = defaultPrecisionModel;
public int srid = 0;
public CoordinateSequenceFactory coordinateSequenceFactory = CoordinateArraySequenceFactory.instance();
//ignored if geo=false
public DatelineRule datelineRule = DatelineRule.width180;
public ValidationRule validationRule = ValidationRule.error;
public boolean autoIndex = false;
public boolean allowMultiOverlap = false;//ignored if geo=false
//kinda advanced options:
public boolean useJtsPoint = true;
public boolean useJtsLineString = true;
public boolean useJtsMulti = true;
public JtsSpatialContextFactory() {
super.shapeFactoryClass = JtsShapeFactory.class;
super.binaryCodecClass = JtsBinaryCodec.class;
}
@Override
protected void checkDefaultFormats() {
if (readers.isEmpty() ) {
addReaderIfNoggitExists(GeoJSONReader.class);
readers.add(WKTReader.class);
readers.add(PolyshapeReader.class);
readers.add(LegacyShapeReader.class);
}
if (writers.isEmpty()) {
writers.add(JtsGeoJSONWriter.class);
writers.add(JtsWKTWriter.class);
writers.add(JtsPolyshapeWriter.class);
writers.add(LegacyShapeWriter.class);
}
}
@Override
protected void init(Map<String, String> args, ClassLoader classLoader) {
super.init(args, classLoader);
initField("datelineRule");
initField("validationRule");
initField("autoIndex");
initField("allowMultiOverlap");
initField("useJtsPoint");
initField("useJtsLineString");
initField("useJtsMulti");
String scaleStr = args.get("precisionScale");
String modelStr = args.get("precisionModel");
if (scaleStr != null) {
if (modelStr != null && !modelStr.equals("fixed"))
throw new RuntimeException("Since precisionScale was specified; precisionModel must be 'fixed' but got: "+modelStr);
precisionModel = new PrecisionModel(Double.parseDouble(scaleStr));
} else if (modelStr != null) {
if (modelStr.equals("floating")) {
precisionModel = new PrecisionModel(PrecisionModel.FLOATING);
} else if (modelStr.equals("floating_single")) {
precisionModel = new PrecisionModel(PrecisionModel.FLOATING_SINGLE);
} else if (modelStr.equals("fixed")) {
throw new RuntimeException("For fixed model, must specifiy 'precisionScale'");
} else {
throw new RuntimeException("Unknown precisionModel: "+modelStr);
}
}
}
public GeometryFactory getGeometryFactory() {
if (precisionModel == null || coordinateSequenceFactory == null)
throw new IllegalStateException("precision model or coord seq factory can't be null");
return new GeometryFactory(precisionModel, srid, coordinateSequenceFactory);
}
@Override
public JtsSpatialContext newSpatialContext() {
return new JtsSpatialContext(this);
}
}