/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.spatial.pending.jts;
import com.spatial4j.core.context.jts.JtsSpatialContext;
import com.spatial4j.core.exception.InvalidShapeException;
import com.spatial4j.core.shape.Point;
import com.spatial4j.core.shape.Shape;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.WKBWriter;
import com.vividsolutions.jts.simplify.TopologyPreservingSimplifier;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.SortedDocValuesField;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.Filter;
import org.apache.lucene.spatial.SpatialStrategy;
import org.apache.lucene.spatial.query.SpatialArgs;
import org.apache.lucene.util.BytesRef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Put raw WKB in DocValues
*/
public class JtsGeoStrategy extends SpatialStrategy {
private static final Logger logger = LoggerFactory.getLogger(JtsGeoStrategy.class);
private int max_wkb_length = 32000;
public JtsGeoStrategy(JtsSpatialContext ctx, String name) {
super(ctx, name);
}
@Override
public Field[] createIndexableFields(Shape shape) {
Geometry geo = ((JtsSpatialContext)ctx).getGeometryFrom(shape);
WKBWriter writer = new WKBWriter();
BytesRef wkb = new BytesRef(writer.write(geo));
if (max_wkb_length > 0 && wkb.length > max_wkb_length) {
long last = wkb.length;
Envelope env = geo.getEnvelopeInternal();
double mins = Math.min(env.getWidth(), env.getHeight());
double div = 1000;
while (true) {
double tolerance = mins / div;
if (logger.isInfoEnabled()) {
logger.info("Simplifying long geometry: WKB.length=" + wkb.length + " tolerance=" + tolerance);
}
Geometry simple = TopologyPreservingSimplifier.simplify(geo, tolerance);
wkb = new BytesRef(writer.write(simple));
if (wkb.length < max_wkb_length) {
break;
}
if (wkb.length == last) {
throw new InvalidShapeException("Can not simplify geometry smaller then max. " + last);
}
last = wkb.length;
div *= .70;
}
}
return new Field[]{new SortedDocValuesField(getFieldName(), wkb)};
}
@Override
public ValueSource makeDistanceValueSource(Point queryPoint, double multiplier) {
throw new UnsupportedOperationException();
}
@Override
public Filter makeFilter(SpatialArgs args) {
Geometry geo = ((JtsSpatialContext)ctx).getGeometryFrom(args.getShape());
GeometryTest tester = GeometryTestFactory.get(args.getOperation(), geo);
return new GeometryOperationFilter(getFieldName(), tester, ((JtsSpatialContext)ctx));
}
}