All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.graphhopper.routing.util.spatialrules.SpatialRuleContainer Maven / Gradle / Ivy

/*
 *  Licensed to GraphHopper GmbH under one or more contributor
 *  license agreements. See the NOTICE file distributed with this work for
 *  additional information regarding copyright ownership.
 *
 *  GraphHopper GmbH 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 com.graphhopper.routing.util.spatialrules;

import java.util.*;

import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.geom.prep.PreparedGeometry;
import org.locationtech.jts.geom.prep.PreparedGeometryFactory;

/**
 * This class contains a collection of SpatialRule which are valid for a certain Polygon.
 *
 * @author Robin Boldt
 * @author Thomas Butz
 */
class SpatialRuleContainer {
    private static final PreparedGeometryFactory PREP_GEOM_FACTORY = new PreparedGeometryFactory();
    private static final GeometryFactory FAC = new GeometryFactory();
    private static final int GRID_SIZE = 10;
    private static final double COORD_EPSILON = 0.00001;

    private final PreparedGeometry preparedPolygon;
    private final Set rules = new LinkedHashSet<>();
    private final List filledLines;
    
    public SpatialRuleContainer(Polygon polygon) {
        this(PREP_GEOM_FACTORY.create(polygon));
    }
    
    private SpatialRuleContainer(PreparedGeometry preparedPolygon) {
        this.preparedPolygon = preparedPolygon;
        this.filledLines = findFilledLines(preparedPolygon);
    }

    public void addRule(SpatialRule spatialRule) {
        rules.add(spatialRule);
    }

    /**
     * Returns a list of all spatial rules including the EMPTY one.
     */
    public Collection getRules() {
        return rules;
    }

    public int size() {
        return this.rules.size();
    }

    public boolean covers(Point point) {
        Coordinate coord = point.getCoordinate();
        
        for (Envelope line : filledLines) {
            if (line.covers(coord)) {
                return true;
            }
        }
        
        return preparedPolygon.intersects(point);
    }

    public SpatialRuleContainer copy() {
        SpatialRuleContainer container = new SpatialRuleContainer(this.preparedPolygon);
        container.rules.addAll(this.rules);
        return container;
    }
    
    private static List findFilledLines(PreparedGeometry prepGeom) {
        List lines = new ArrayList<>();
        
        Envelope bbox = prepGeom.getGeometry().getEnvelopeInternal();
        double tileWidth  = bbox.getWidth()  / GRID_SIZE;
        double tileHeight = bbox.getHeight() / GRID_SIZE;

        Envelope tile = new Envelope();
        Envelope line;
        for (int row = 0; row < GRID_SIZE; row++) {
            line = null;
            for (int column = 0; column < GRID_SIZE; column++) {
                double minX = bbox.getMinX() + (column * tileWidth);
                double minY = bbox.getMinY() + (row * tileHeight);
                tile.init(minX, minX + tileWidth, minY, minY + tileHeight);
                
                if (prepGeom.covers(FAC.toGeometry(tile))) {
                    if (line != null && Math.abs(line.getMaxX() - tile.getMinX()) < COORD_EPSILON) {
                        line.expandToInclude(tile);
                    } else {
                        line = new Envelope(tile);
                        lines.add(line);
                    }
                }
            }
        }
        
        return lines;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy