/* * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI * for visualizing and manipulating spatial features with geometry and attributes. * * JUMP is Copyright (C) 2003 Vivid Solutions * * This program implements extensions to JUMP and is * Copyright (C) Stefan Steiniger. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) 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 * GNU General Public License for more details. * * You should have received a copy of the GNU 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. * * For more information, contact: * Stefan Steiniger * perriger@gmx.de */ /*********************************************** * created on 21.06.2006 * last modified: * * author: sstein * * description: * joins attribute values according to some spatial and statistical criterion * ***********************************************/ package org.openjump.core.attributeoperations; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.index.quadtree.Quadtree; import com.vividsolutions.jump.feature.AttributeType; import com.vividsolutions.jump.feature.BasicFeature; import com.vividsolutions.jump.feature.Feature; import com.vividsolutions.jump.feature.FeatureDataset; import com.vividsolutions.jump.feature.FeatureSchema; import com.vividsolutions.jump.task.TaskMonitor; /** * joins attribute values according to some spatial and statistical criterion * * @author sstein * */ public class JoinAttributes { /** * * @param sourceFeatures * @param targetFeatures * @param attributeName * @param attributeOp * @param spatialRelation * @param bufferRadius * @return a feature dataset */ public static FeatureDataset joinAttributes(Collection sourceFeatures, Collection targetFeatures, String attributeName, int attributeOp, int spatialRelation, double bufferRadius, TaskMonitor monitor){ /* System.out.println("Join Attributes --- attribute op:" + attributeOp + " - " + AttributeOp.getName(attributeOp) + " --- spatial op: " + spatialRelation + " - " + SpatialRelationOp.getName(spatialRelation)); */ FeatureDataset fd = null; AttributeType newAttributeType = AttributeType.DOUBLE; String newAttributeName = attributeName + "_" + AttributeOp.getName(attributeOp); if (attributeOp == AttributeOp.COUNT){ newAttributeName = AttributeOp.getName(attributeOp); } //-- put all in a tree Quadtree fqTree = new Quadtree(); FeatureSchema sourceFS = null; int count =0; for (Iterator iter = sourceFeatures.iterator(); iter.hasNext();) { Feature pt = (Feature) iter.next(); fqTree.insert(pt.getGeometry().getEnvelopeInternal(), pt); if(count == 0){ sourceFS = pt.getSchema(); } count++; } //-- get AttributeType AttributeType at = null; try{ at = sourceFS.getAttributeType(attributeName); } catch(Exception e){ at = AttributeType.GEOMETRY; attributeName = sourceFS.getAttributeName(0); System.out.println("JoinAttributes.joinAttributes: replace unknown attribute name by geometry"); } // ArrayList outPolys = new ArrayList(); int size = targetFeatures.size(); FeatureSchema targetFSnew = null; count=0; Iterator iterp = targetFeatures.iterator(); while(iterp.hasNext()){ count=count+1; if(monitor != null){ monitor.report("item: " + count + " of " + size); } Feature p = (Feature)iterp.next(); if (count == 1){ FeatureSchema targetFs = p.getSchema(); targetFSnew = copyFeatureSchema(targetFs); if (targetFSnew.hasAttribute(newAttributeName)){ //attribute will be overwriten } else{ //add attribute targetFSnew.addAttribute(newAttributeName, newAttributeType); } } //-- evaluate value for every polygon double value = evaluateSinglePolygon(p.getGeometry(), fqTree, attributeName, attributeOp, spatialRelation, bufferRadius); Feature fcopy = copyFeature(p, targetFSnew); fcopy.setAttribute(newAttributeName, new Double(value)); outPolys.add(fcopy); } fd = new FeatureDataset(targetFSnew); fd.addAll(outPolys); return fd; } /** * * @param poly * @param * @return value */ private static double evaluateSinglePolygon(Geometry poly, Quadtree fqTree, String attributeName, int attributeOp, int spatialRelation, double bufferRadius){ List items = SpatialRelationOp.evaluateSpatial(spatialRelation, fqTree, poly, bufferRadius); double val = AttributeOp.evaluateAttributes(attributeOp, items, attributeName); return val; } /** * Copy/clone the input featureSchema since it is not proper implemented in Jump * @param oldSchema * @return a clone of oldSchema */ public static FeatureSchema copyFeatureSchema(FeatureSchema oldSchema){ FeatureSchema fs = new FeatureSchema(); for (int i = 0; i < oldSchema.getAttributeCount(); i++) { AttributeType at = oldSchema.getAttributeType(i); String aname = oldSchema.getAttributeName(i); fs.addAttribute(aname,at); fs.setCoordinateSystem(oldSchema.getCoordinateSystem()); } return fs; } /** * Copy the input feature to a new Schema whereby the new * Feature Schema must be an extended or shortened one * @param feature * @param newSchema * @return a new Feature with newSchema as Schema and feature values */ public static Feature copyFeature(Feature feature, FeatureSchema newSchema){ FeatureSchema oldSchema = feature.getSchema(); Feature newF = new BasicFeature(newSchema); int n = 0; if (oldSchema.getAttributeCount() > newSchema.getAttributeCount()){ //for schema shortening n = newSchema.getAttributeCount(); } else{ //for schema extension n = oldSchema.getAttributeCount(); } for (int i = 0; i < n; i++) { String aname = oldSchema.getAttributeName(i); Object value = feature.getAttribute(aname); newF.setAttribute(aname,value); } return newF; } }