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

org.integratedmodelling.engine.geospace.utils.ThiessenLocator Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *  Copyright (C) 2007, 2015:
 *  
 *    - Ferdinando Villa 
 *    - integratedmodelling.org
 *    - any other authors listed in @author annotations
 *
 *    All rights reserved. This file is part of the k.LAB software suite,
 *    meant to enable modular, collaborative, integrated 
 *    development of interoperable data and model components. For
 *    details, see http://integratedmodelling.org.
 *    
 *    This program is free software; you can redistribute it and/or
 *    modify it under the terms of the Affero General Public License 
 *    Version 3 or any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but without any warranty; without even the implied warranty of
 *    merchantability or fitness for a particular purpose.  See the
 *    Affero General Public License for more details.
 *  
 *     You should have received a copy of the Affero General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *     The license is also available at: https://www.gnu.org/licenses/agpl.html
 *******************************************************************************/
package org.integratedmodelling.engine.geospace.utils;

import java.util.ArrayList;
import java.util.List;

import org.integratedmodelling.api.modelling.IScale;
import org.integratedmodelling.collections.Pair;
import org.integratedmodelling.common.space.IGeometricShape;
import org.integratedmodelling.engine.geospace.Geospace;
import org.integratedmodelling.engine.geospace.extents.SpaceExtent;
import org.integratedmodelling.engine.geospace.literals.ShapeValue;
import org.integratedmodelling.exceptions.KlabRuntimeException;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.triangulate.VoronoiDiagramBuilder;

/**
 * An object initialized with a raster spatial scale and a set of geometric shapes whose centroids
 * lie in or around that area. Will produce a set of Thiessen polygons describing the influence
 * zone of each shape, cut to the area, and it will create an index so that it can be queried for
 * the index of the shape selected to describe each cell in the raster.
 *  
 * @author Ferd
 *
 */
public class ThiessenLocator {

    List> pairs = new ArrayList<>();
    short[] index;
    List objects;
    
    /*
     * this isn't null only when we have a single object to distribute. Then we use that without 
     * any polygons.
     */
    T object = null;
    
    public ThiessenLocator(IScale scale, List objects) {
        
        if (scale.getSpace() == null || scale.getSpace().getGrid() == null) {
            throw new KlabRuntimeException("illegal spatial extent for ThiessenLocator: only grids are supported");
        }
        
        this.objects = objects;
        
        SpatialDisplay debug = new SpatialDisplay((SpaceExtent) scale.getSpace());

        if (objects.size() == 1) {
            
            object = objects.get(0);
            
        } else if (objects.size() > 0) {

            /*
             * generate object influence polygons and associate them to the objects in the order identified.
             */
            VoronoiDiagramBuilder db = new VoronoiDiagramBuilder();
            ArrayList sites = new ArrayList<>();
            for (IGeometricShape s : objects) {
                Point point = s.getGeometry().getCentroid();
                sites.add(new Coordinate(point.getX(), point.getY()));
                debug.add(new ShapeValue(s.getGeometry(), Geospace.get().getDefaultCRS()));
            }
            db.setSites(sites);
            Geometry diag = db.getDiagram(new GeometryFactory());

            /*
             * attribute objects to polygons
             */
            int pols = 0;
            for (pols = 0; pols < diag.getNumGeometries(); pols++) {
                Geometry g = diag.getGeometryN(pols);
                debug.add(new ShapeValue(g, Geospace.get().getDefaultCRS()), "original");
                for (int s = 0; s < objects.size(); s++) {
                    if (g.intersects(objects.get(s).getGeometry()) && g instanceof Polygon) {
                        pairs.add(new Pair<>((Polygon) g, objects.get(s)));
                    }
                }
            }

            /*
             * build index of which object is where. Drop those that fall out of
             * the context shape in the process. 
             */
            GeometryFactory pm = new GeometryFactory();
            index = new short[(int) scale.getSpace().getMultiplicity()];
            for (int i = 0; i < scale.getSpace().getMultiplicity(); i++) {
                double[] xy = scale.getSpace().getGrid().getCoordinates(i);
                Point point = pm.createPoint(new Coordinate(xy[0], xy[1]));
                for (int j = 0; j < pairs.size(); j++) {
                    if (pairs.get(j).getFirst().intersects(point)) {
                        index[i] = (short) (j + 1);
                        break;
                    }
                }
            }
        }
    }
    
    public T get(int offset) {
        return object == null ? (index == null ? null : pairs.get(index[offset] - 1).getSecond()) : object;
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy