/* * 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.spatial3d; import java.io.IOException; import org.apache.lucene.spatial3d.geom.BasePlanetObject; import org.apache.lucene.spatial3d.geom.GeoShape; import org.apache.lucene.spatial3d.geom.PlanetModel; import org.apache.lucene.spatial3d.geom.XYZBounds; import org.apache.lucene.index.PointValues; import org.apache.lucene.index.LeafReader; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.search.ConstantScoreScorer; import org.apache.lucene.search.ConstantScoreWeight; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.Scorer; import org.apache.lucene.search.Weight; import org.apache.lucene.util.DocIdSetBuilder; /** Finds all previously indexed points that fall within the specified polygon. * * <p>The field must be indexed using {@link Geo3DPoint}. * * @lucene.experimental */ final class PointInGeo3DShapeQuery extends Query { final String field; final GeoShape shape; final XYZBounds shapeBounds; /** The lats/lons must be clockwise or counter-clockwise. */ public PointInGeo3DShapeQuery(String field, GeoShape shape) { this.field = field; this.shape = shape; this.shapeBounds = new XYZBounds(); shape.getBounds(shapeBounds); if (shape instanceof BasePlanetObject) { BasePlanetObject planetObject = (BasePlanetObject) shape; if (planetObject.getPlanetModel().equals(PlanetModel.WGS84) == false) { throw new IllegalArgumentException("this qurey requires PlanetModel.WGS84, but got: " + planetObject.getPlanetModel()); } } } @Override public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException { // I don't use RandomAccessWeight here: it's no good to approximate with "match all docs"; this is an inverted structure and should be // used in the first pass: return new ConstantScoreWeight(this, boost) { @Override public Scorer scorer(LeafReaderContext context) throws IOException { LeafReader reader = context.reader(); PointValues values = reader.getPointValues(field); if (values == null) { return null; } /* XYZBounds bounds = new XYZBounds(); shape.getBounds(bounds); final double planetMax = planetModel.getMaximumMagnitude(); if (planetMax != treeDV.planetMax) { throw new IllegalStateException(planetModel + " is not the same one used during indexing: planetMax=" + planetMax + " vs indexing planetMax=" + treeDV.planetMax); } */ /* GeoArea xyzSolid = GeoAreaFactory.makeGeoArea(planetModel, bounds.getMinimumX(), bounds.getMaximumX(), bounds.getMinimumY(), bounds.getMaximumY(), bounds.getMinimumZ(), bounds.getMaximumZ()); assert xyzSolid.getRelationship(shape) == GeoArea.WITHIN || xyzSolid.getRelationship(shape) == GeoArea.OVERLAPS: "expected WITHIN (1) or OVERLAPS (2) but got " + xyzSolid.getRelationship(shape) + "; shape="+shape+"; XYZSolid="+xyzSolid; */ DocIdSetBuilder result = new DocIdSetBuilder(reader.maxDoc(), values, field); values.intersect(new PointInShapeIntersectVisitor(result, shape, shapeBounds)); return new ConstantScoreScorer(this, score(), result.build().iterator()); } }; } public String getField() { return field; } public GeoShape getShape() { return shape; } @Override public boolean equals(Object other) { return sameClassAs(other) && equalsTo(getClass().cast(other)); } private boolean equalsTo(PointInGeo3DShapeQuery other) { return field.equals(other.field) && shape.equals(other.shape); } @Override public int hashCode() { int result = classHash(); result = 31 * result + field.hashCode(); result = 31 * result + shape.hashCode(); return result; } @Override public String toString(String field) { final StringBuilder sb = new StringBuilder(); sb.append(getClass().getSimpleName()); sb.append(':'); if (this.field.equals(field) == false) { sb.append(" field="); sb.append(this.field); sb.append(':'); } sb.append(" Shape: "); sb.append(shape); return sb.toString(); } }