Revision 1137
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.102/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/resources/META-INF/services/org.gvsig.tools.library.Library | ||
---|---|---|
1 |
org.gvsig.geoprocess.algorithm.fusespatially.FuseSpatiallyLibrary |
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.102/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/resources/org/gvsig/geoprocess/algorithm/fusespatially/fusespatially.properties | ||
---|---|---|
1 |
# |
|
2 |
# gvSIG. Desktop Geographic Information System. |
|
3 |
# |
|
4 |
# Copyright (C) 2007-2012 gvSIG Association. |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
19 |
# MA 02110-1301, USA. |
|
20 |
# |
|
21 |
# For any additional information, do not hesitate to contact us |
|
22 |
# at info AT gvsig.com, or visit our website www.gvsig.com. |
|
23 |
# |
|
24 |
|
|
25 |
basic_vect_algorithms=Capas vectoriales |
|
26 |
Input_layer=Capa de entrada |
|
27 |
Selected_geometries_fuse=Geom. seleccionadas (Capa entrada) |
|
28 |
Field=Campo |
|
29 |
Function_list=Lista de funciones |
|
30 |
fusespatially=Fusionar espacialmente |
|
31 |
fuse_spatially=Fusionar espacialmente |
|
32 |
summary_function=Funci?n resumen |
|
33 |
adjacent_geometries_only=Solo geometrias adyacentes |
|
0 | 34 |
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.102/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/resources/org/gvsig/geoprocess/algorithm/fusespatially/fusespatially_en.properties | ||
---|---|---|
1 |
# |
|
2 |
# gvSIG. Desktop Geographic Information System. |
|
3 |
# |
|
4 |
# Copyright (C) 2007-2012 gvSIG Association. |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
19 |
# MA 02110-1301, USA. |
|
20 |
# |
|
21 |
# For any additional information, do not hesitate to contact us |
|
22 |
# at info AT gvsig.com, or visit our website www.gvsig.com. |
|
23 |
# |
|
24 |
|
|
25 |
basic_vect_algorithms=Vector layers tools |
|
26 |
Input_layer=Input cover |
|
27 |
Selected_geometries_fuse=Selected geometries (Input cover) |
|
28 |
Field=Field |
|
29 |
Function_list=Function list |
|
30 |
fusespatially=Fuse spatially |
|
31 |
fuse_spatially=Fuse spatially |
|
32 |
summary_function=Summary function |
|
33 |
adjacent_geometries_only=Only dissolve adjacent |
|
34 |
groupby=Group by a field |
|
0 | 35 |
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.102/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/resources/help/FuseSpatiallyAlgorithm_en.xml | ||
---|---|---|
1 |
<?xml version='1.0' encoding='ISO-8859-1' standalone='yes' ?> |
|
2 |
<!-- |
|
3 |
|
|
4 |
gvSIG. Desktop Geographic Information System. |
|
5 |
|
|
6 |
Copyright (C) 2007-2012 gvSIG Association. |
|
7 |
|
|
8 |
This program is free software; you can redistribute it and/or |
|
9 |
modify it under the terms of the GNU General Public License |
|
10 |
as published by the Free Software Foundation; either version 2 |
|
11 |
of the License, or (at your option) any later version. |
|
12 |
|
|
13 |
This program is distributed in the hope that it will be useful, |
|
14 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
16 |
GNU General Public License for more details. |
|
17 |
|
|
18 |
You should have received a copy of the GNU General Public License |
|
19 |
along with this program; if not, write to the Free Software |
|
20 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
21 |
MA 02110-1301, USA. |
|
22 |
|
|
23 |
For any additional information, do not hesitate to contact us |
|
24 |
at info AT gvsig.com, or visit our website www.gvsig.com. |
|
25 |
|
|
26 |
--> |
|
27 |
<help> |
|
28 |
<element name="DESCRIPTION" text="This geoprocess works with one only input layer, whose geometry type must be polygon. This process analize each input geometry and builds a unique polygon with all geometries which intersects each other. The attribute table will have an identifier field of each feature. <BR> Furthermore, other layer with only alphanumeric data will be created. This alphanumeric table will contain the table of the input layer and it will include a identifier field with a reference to the polygon in the first layer. In this way, each polygon in the first layer will have a reference to each feature in the second layer." description="Descripción" type="0"> |
|
29 |
<image description="" file="fusespatiallydesc.png"> |
|
30 |
</image> |
|
31 |
</element> |
|
32 |
<element name="ADDITIONAL_INFO" text="" description="Información adicional" type="0"> |
|
33 |
</element> |
|
34 |
<element name="EXTENSION_AUTHOR" text="Nacho Brodin" description="Algoritmo creado por" type="0"> |
|
35 |
</element> |
|
36 |
<element name="HELP_AUTHOR" text="" description="Ayuda creada por" type="0"> |
|
37 |
</element> |
|
38 |
<element name="USER_NOTES" text="" description="Notas de usuario" type="0"> |
|
39 |
</element> |
|
40 |
<element name="LAYER" text="" description="Capa de entrada" type="3"> |
|
41 |
</element> |
|
42 |
<element name="SELECTED_GEOM" text="" description="Geometrias seleccionadas" type="3"> |
|
43 |
</element> |
|
44 |
<element name="DISSOLV_ADJ" text="" description="Geometrias seleccionadas" type="3"> |
|
45 |
</element> |
|
46 |
<element name="FIELD" text="" description="Campo" type="3"> |
|
47 |
</element> |
|
48 |
<element name="FUNCTION_LIST" text="" description="Lista de funciones" type="3"> |
|
49 |
</element> |
|
50 |
<element name="OUTPUT_DESCRIPTION" text="" description="Descripción" type="2"> |
|
51 |
</element> |
|
52 |
<element name="RESULT" text="" description="Disolver" type="2"> |
|
53 |
</element> |
|
54 |
</help> |
|
55 |
<?xml version='1.0' encoding='ISO-8859-1' standalone='yes' ?> |
|
0 | 56 |
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.102/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/resources/help/FuseSpatiallyAlgorithm.xml | ||
---|---|---|
1 |
<?xml version='1.0' encoding='ISO-8859-1' standalone='yes' ?> |
|
2 |
<!-- |
|
3 |
|
|
4 |
gvSIG. Desktop Geographic Information System. |
|
5 |
|
|
6 |
Copyright (C) 2007-2012 gvSIG Association. |
|
7 |
|
|
8 |
This program is free software; you can redistribute it and/or |
|
9 |
modify it under the terms of the GNU General Public License |
|
10 |
as published by the Free Software Foundation; either version 2 |
|
11 |
of the License, or (at your option) any later version. |
|
12 |
|
|
13 |
This program is distributed in the hope that it will be useful, |
|
14 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
16 |
GNU General Public License for more details. |
|
17 |
|
|
18 |
You should have received a copy of the GNU General Public License |
|
19 |
along with this program; if not, write to the Free Software |
|
20 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
21 |
MA 02110-1301, USA. |
|
22 |
|
|
23 |
For any additional information, do not hesitate to contact us |
|
24 |
at info AT gvsig.com, or visit our website www.gvsig.com. |
|
25 |
|
|
26 |
--> |
|
27 |
<help> |
|
28 |
<element name="DESCRIPTION" text="Este geoproceso actúa sobre una sola capa de entrada, cuyo tipo de geometría ha de ser forzosamente de polígonos. El proceso analiza cada polígono de la capa de entrada, de tal forma que fusionará en un solo polígono aquellos polígonos que coincidan espacialmente, es decir que intersequen entre ellos. La tabla de atributos de los pol?gonos resultantes estar? formada por un campo ID que ser? el identificador del fen?meno. <BR> Adicionalmente se crear? otra capa que contendr? ?nicamente informaci?n alfanum?rica con la tabla de datos de la capa de origen. Adem?s incluir? un campo ID en el que tendr? la referencia al ID de la capa de pol?gonos creada. De esta forma, cada pol?gono har? referencia con su ID a una o varias entradas de la capa unicamente alfanum?rica para identificar la informaci?n asociada originalmente a cada pol?gono de la capa." description="Descripción" type="0"> |
|
29 |
<image description="" file="fusespatiallydesc.png"> |
|
30 |
</image> |
|
31 |
</element> |
|
32 |
<element name="ADDITIONAL_INFO" text="" description="Información adicional" type="0"> |
|
33 |
</element> |
|
34 |
<element name="EXTENSION_AUTHOR" text="Nacho Brodin" description="Algoritmo creado por" type="0"> |
|
35 |
</element> |
|
36 |
<element name="HELP_AUTHOR" text="" description="Ayuda creada por" type="0"> |
|
37 |
</element> |
|
38 |
<element name="USER_NOTES" text="" description="Notas de usuario" type="0"> |
|
39 |
</element> |
|
40 |
<element name="LAYER" text="" description="Capa de entrada" type="3"> |
|
41 |
</element> |
|
42 |
<element name="SELECTED_GEOM" text="" description="Geometrias seleccionadas" type="3"> |
|
43 |
</element> |
|
44 |
<element name="DISSOLV_ADJ" text="" description="Geometrias seleccionadas" type="3"> |
|
45 |
</element> |
|
46 |
<element name="FIELD" text="" description="Campo" type="3"> |
|
47 |
</element> |
|
48 |
<element name="FUNCTION_LIST" text="" description="Lista de funciones" type="3"> |
|
49 |
</element> |
|
50 |
<element name="OUTPUT_DESCRIPTION" text="" description="Descripción" type="2"> |
|
51 |
</element> |
|
52 |
<element name="RESULT" text="" description="Disolver" type="2"> |
|
53 |
</element> |
|
54 |
</help> |
|
55 |
<?xml version='1.0' encoding='ISO-8859-1' standalone='yes' ?> |
|
0 | 56 |
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.102/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/java/org/gvsig/geoprocess/algorithm/fusespatially/FuseSpatiallyOperation.java | ||
---|---|---|
1 |
/** |
|
2 |
* gvSIG. Desktop Geographic Information System. |
|
3 |
* |
|
4 |
* Copyright (C) 2007-2012 gvSIG Association. |
|
5 |
* |
|
6 |
* This program is free software; you can redistribute it and/or |
|
7 |
* modify it under the terms of the GNU General Public License |
|
8 |
* as published by the Free Software Foundation; either version 2 |
|
9 |
* of the License, or (at your option) any later version. |
|
10 |
* |
|
11 |
* This program is distributed in the hope that it will be useful, |
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
* GNU General Public License for more details. |
|
15 |
* |
|
16 |
* You should have received a copy of the GNU General Public License |
|
17 |
* along with this program; if not, write to the Free Software |
|
18 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
19 |
* MA 02110-1301, USA. |
|
20 |
* |
|
21 |
* For any additional information, do not hesitate to contact us |
|
22 |
* at info AT gvsig.com, or visit our website www.gvsig.com. |
|
23 |
*/ |
|
24 |
/* |
|
25 |
|
|
26 |
* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana |
|
27 |
* |
|
28 |
* Copyright (C) 2010 Generalitat Valenciana. |
|
29 |
* |
|
30 |
* This program is free software; you can redistribute it and/or |
|
31 |
* modify it under the terms of the GNU General Public License |
|
32 |
* as published by the Free Software Foundation; either version 2 |
|
33 |
* of the License, or (at your option) any later version. |
|
34 |
* |
|
35 |
* This program is distributed in the hope that it will be useful, |
|
36 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
37 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
38 |
* GNU General Public License for more details. |
|
39 |
* |
|
40 |
* You should have received a copy of the GNU General Public License |
|
41 |
* along with this program; if not, write to the Free Software |
|
42 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA. |
|
43 |
*/ |
|
44 |
|
|
45 |
package org.gvsig.geoprocess.algorithm.fusespatially; |
|
46 |
|
|
47 |
import java.util.ArrayList; |
|
48 |
import java.util.List; |
|
49 |
import java.util.Stack; |
|
50 |
|
|
51 |
import org.gvsig.fmap.dal.exception.DataException; |
|
52 |
import org.gvsig.fmap.dal.feature.EditableFeature; |
|
53 |
import org.gvsig.fmap.dal.feature.Feature; |
|
54 |
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
|
55 |
import org.gvsig.fmap.dal.feature.FeatureStore; |
|
56 |
import org.gvsig.fmap.geom.GeometryLocator; |
|
57 |
import org.gvsig.fmap.geom.GeometryManager; |
|
58 |
import org.gvsig.fmap.geom.exception.CreateGeometryException; |
|
59 |
import org.gvsig.geoprocess.algorithm.base.core.DALFeaturePersister; |
|
60 |
import org.gvsig.geoprocess.algorithm.base.core.GeometryOperation; |
|
61 |
import org.gvsig.geoprocess.algorithm.base.util.GeometryUtil; |
|
62 |
import org.gvsig.geoprocess.lib.sextante.AbstractSextanteGeoProcess; |
|
63 |
|
|
64 |
import com.vividsolutions.jts.geom.Geometry; |
|
65 |
/** |
|
66 |
* Fuse spatially operation |
|
67 |
* @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a> |
|
68 |
* @deprecated Uses FuseSpatiallyOperationFast |
|
69 |
*/ |
|
70 |
public class FuseSpatiallyOperation extends GeometryOperation { |
|
71 |
protected GeometryManager geomManager = GeometryLocator.getGeometryManager(); |
|
72 |
private int id = 0; |
|
73 |
private List<Feature> featList = null; |
|
74 |
private FeatureStore outFeatureStoreTable = null; |
|
75 |
private String idField = "FID"; |
|
76 |
|
|
77 |
public FuseSpatiallyOperation(List<Feature> f, |
|
78 |
FeatureStore outFeatStoreTable, |
|
79 |
String[] fieldNames, |
|
80 |
String idField, |
|
81 |
AbstractSextanteGeoProcess p) throws DataException { |
|
82 |
super(p); |
|
83 |
this.featList = f; |
|
84 |
this.outFeatureStoreTable = outFeatStoreTable; |
|
85 |
this.idField = idField; |
|
86 |
} |
|
87 |
|
|
88 |
public FuseSpatiallyOperation(Stack<Feature> f, |
|
89 |
FeatureStore outFeatStoreTable, |
|
90 |
String[] fieldNames, |
|
91 |
AbstractSextanteGeoProcess p) throws DataException { |
|
92 |
super(p); |
|
93 |
this.featList = f; |
|
94 |
this.outFeatureStoreTable = outFeatStoreTable; |
|
95 |
} |
|
96 |
|
|
97 |
/* |
|
98 |
* (non-Javadoc) |
|
99 |
* @see org.gvsig.geoprocess.algorithm.base.core.GeometryOperation#invoke(org.gvsig.fmap.geom.Geometry, org.gvsig.fmap.dal.feature.Feature) |
|
100 |
*/ |
|
101 |
public EditableFeature invoke(org.gvsig.fmap.geom.Geometry g, Feature feature) { |
|
102 |
try { |
|
103 |
Geometry jtsInputGeom = GeometryUtil.geomToJTS(g); |
|
104 |
insertInTable(feature); |
|
105 |
|
|
106 |
int cont = featList.size() - 1; |
|
107 |
while(cont >= 0 && !process.getTaskMonitor().isCanceled()) { |
|
108 |
Feature f = featList.get(cont); |
|
109 |
g = f.getDefaultGeometry(); |
|
110 |
Geometry jtsGeom = GeometryUtil.geomToJTS(g); //Multigeometry support |
|
111 |
if(jtsGeom.intersects(jtsInputGeom)) { |
|
112 |
jtsInputGeom = jtsInputGeom.union(jtsGeom); |
|
113 |
featList.remove(cont); |
|
114 |
process.setProgress(procesSize - featList.size(), procesSize); |
|
115 |
cont = featList.size(); |
|
116 |
insertInTable(f); |
|
117 |
} |
|
118 |
cont --; |
|
119 |
} |
|
120 |
|
|
121 |
//Cuando no genera dos capas mete los campos de la feature de entrada en la de salida perdiendose el resto |
|
122 |
if(outFeatureStoreTable == null) { |
|
123 |
String[] fieldNames = persister.getFieldNamesWithoutGeom(); |
|
124 |
ArrayList<String> fields = new ArrayList<String>(); |
|
125 |
ArrayList<Object> values = new ArrayList<Object>(); |
|
126 |
fields.add(idField); |
|
127 |
values.add(id); |
|
128 |
for (int j = 0; j < fieldNames.length; j++) { |
|
129 |
Object obj = feature.get(fieldNames[j]); |
|
130 |
if(obj != null && fieldNames[j].compareTo(idField) != 0) { |
|
131 |
fields.add(fieldNames[j]); |
|
132 |
values.add(obj); |
|
133 |
} |
|
134 |
} |
|
135 |
lastEditFeature = persister.addFeature(jtsInputGeom, fields, values); |
|
136 |
} else |
|
137 |
lastEditFeature = persister.addFeature(jtsInputGeom, idField, id); |
|
138 |
} catch (DataException e) { |
|
139 |
return null; |
|
140 |
} catch (CreateGeometryException e) { |
|
141 |
return null; |
|
142 |
} |
|
143 |
id++; |
|
144 |
return lastEditFeature; |
|
145 |
} |
|
146 |
|
|
147 |
private void insertInTable(Feature f) throws DataException { |
|
148 |
if(outFeatureStoreTable == null) |
|
149 |
return; |
|
150 |
EditableFeature edFeat = outFeatureStoreTable.createNewFeature(); |
|
151 |
edFeat.set(idField, id); |
|
152 |
FeatureAttributeDescriptor[] attrList = f.getType().getAttributeDescriptors(); |
|
153 |
for (int j = 0; j < attrList.length; j++) { |
|
154 |
if(attrList[j].getName().compareTo("GEOMETRY") != 0) { |
|
155 |
edFeat.set(attrList[j].getName(), f.get(attrList[j].getName())); |
|
156 |
} |
|
157 |
} |
|
158 |
outFeatureStoreTable.insert(edFeat); |
|
159 |
} |
|
160 |
|
|
161 |
/** |
|
162 |
* Removes duplicate fields |
|
163 |
* @param names |
|
164 |
* @return |
|
165 |
*/ |
|
166 |
public static String[] checkFields(String[] names) { |
|
167 |
if(names.length <= 1) |
|
168 |
return names; |
|
169 |
int cont = 0; |
|
170 |
|
|
171 |
int i = 1; |
|
172 |
while(i < names.length) { |
|
173 |
if(names[0].compareTo(names[i]) == 0) { |
|
174 |
names[0] = "FID_" + cont; |
|
175 |
i = 0; |
|
176 |
cont ++; |
|
177 |
} |
|
178 |
i ++; |
|
179 |
} |
|
180 |
return names; |
|
181 |
} |
|
182 |
|
|
183 |
/* |
|
184 |
* (non-Javadoc) |
|
185 |
* @see org.gvsig.geoprocess.algorithm.base.core.GeometryOperation#invoke(org.gvsig.fmap.geom.Geometry, org.gvsig.fmap.dal.feature.EditableFeature) |
|
186 |
*/ |
|
187 |
public void invoke(org.gvsig.fmap.geom.Geometry g, EditableFeature feature) { |
|
188 |
if(g == null) |
|
189 |
return; |
|
190 |
} |
|
191 |
|
|
192 |
/* |
|
193 |
* (non-Javadoc) |
|
194 |
* @see org.gvsig.geoprocess.algorithm.base.core.IOperation#getResult() |
|
195 |
*/ |
|
196 |
public Object getResult() { |
|
197 |
return lastEditFeature; |
|
198 |
} |
|
199 |
|
|
200 |
public DALFeaturePersister getWriter() { |
|
201 |
return persister; |
|
202 |
} |
|
203 |
|
|
204 |
} |
|
205 |
|
|
0 | 206 |
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.102/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/java/org/gvsig/geoprocess/algorithm/fusespatially/FuseSpatiallyOperationFast2.java | ||
---|---|---|
1 |
/** |
|
2 |
* gvSIG. Desktop Geographic Information System. |
|
3 |
* |
|
4 |
* Copyright (C) 2007-2012 gvSIG Association. |
|
5 |
* |
|
6 |
* This program is free software; you can redistribute it and/or |
|
7 |
* modify it under the terms of the GNU General Public License |
|
8 |
* as published by the Free Software Foundation; either version 2 |
|
9 |
* of the License, or (at your option) any later version. |
|
10 |
* |
|
11 |
* This program is distributed in the hope that it will be useful, |
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
* GNU General Public License for more details. |
|
15 |
* |
|
16 |
* You should have received a copy of the GNU General Public License |
|
17 |
* along with this program; if not, write to the Free Software |
|
18 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
19 |
* MA 02110-1301, USA. |
|
20 |
* |
|
21 |
* For any additional information, do not hesitate to contact us |
|
22 |
* at info AT gvsig.com, or visit our website www.gvsig.com. |
|
23 |
*/ |
|
24 |
/* |
|
25 |
|
|
26 |
* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana |
|
27 |
* |
|
28 |
* Copyright (C) 2010 Generalitat Valenciana. |
|
29 |
* |
|
30 |
* This program is free software; you can redistribute it and/or |
|
31 |
* modify it under the terms of the GNU General Public License |
|
32 |
* as published by the Free Software Foundation; either version 2 |
|
33 |
* of the License, or (at your option) any later version. |
|
34 |
* |
|
35 |
* This program is distributed in the hope that it will be useful, |
|
36 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
37 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
38 |
* GNU General Public License for more details. |
|
39 |
* |
|
40 |
* You should have received a copy of the GNU General Public License |
|
41 |
* along with this program; if not, write to the Free Software |
|
42 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA. |
|
43 |
*/ |
|
44 |
package org.gvsig.geoprocess.algorithm.fusespatially; |
|
45 |
|
|
46 |
import java.util.ArrayList; |
|
47 |
import java.util.List; |
|
48 |
|
|
49 |
import org.gvsig.fmap.dal.exception.DataException; |
|
50 |
import org.gvsig.fmap.dal.feature.EditableFeature; |
|
51 |
import org.gvsig.fmap.dal.feature.Feature; |
|
52 |
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
|
53 |
import org.gvsig.fmap.dal.feature.FeatureSelection; |
|
54 |
import org.gvsig.fmap.dal.feature.FeatureSet; |
|
55 |
import org.gvsig.fmap.dal.feature.FeatureStore; |
|
56 |
import org.gvsig.fmap.geom.exception.CreateGeometryException; |
|
57 |
import org.gvsig.geoprocess.algorithm.base.core.GeometryOperation; |
|
58 |
import org.gvsig.geoprocess.algorithm.base.util.GeometryUtil; |
|
59 |
import org.gvsig.geoprocess.algorithm.base.util.JTSFacade; |
|
60 |
import org.gvsig.geoprocess.lib.sextante.AbstractSextanteGeoProcess; |
|
61 |
import org.slf4j.Logger; |
|
62 |
import org.slf4j.LoggerFactory; |
|
63 |
|
|
64 |
import com.vividsolutions.jts.geom.Geometry; |
|
65 |
import java.util.Iterator; |
|
66 |
|
|
67 |
/** |
|
68 |
* Fuse spatially operation |
|
69 |
* |
|
70 |
* @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a> |
|
71 |
*/ |
|
72 |
public class FuseSpatiallyOperationFast2 extends GeometryOperation { |
|
73 |
|
|
74 |
private static Logger logger = LoggerFactory.getLogger(FuseSpatiallyOperationFast2.class.getName()); |
|
75 |
private ArrayList<Element> featureList = null; |
|
76 |
private String nameIdField = null; |
|
77 |
private FeatureStore outFeatStoreTable = null; |
|
78 |
private NodeTree baseTree = null; |
|
79 |
|
|
80 |
class Element { |
|
81 |
|
|
82 |
public int id = -1; |
|
83 |
public Feature feat = null; |
|
84 |
public List<Element> overlapList = new ArrayList<Element>(); |
|
85 |
public boolean insertedToJoin = false; |
|
86 |
public Geometry jtsGeom = null; |
|
87 |
} |
|
88 |
|
|
89 |
class NodeTree { |
|
90 |
|
|
91 |
public Element element = null; |
|
92 |
public int pos = 0; |
|
93 |
public NodeTree parent = null; |
|
94 |
|
|
95 |
public NodeTree(Element node, NodeTree parent) { |
|
96 |
this.element = node; |
|
97 |
this.parent = parent; |
|
98 |
} |
|
99 |
|
|
100 |
public Element getNext() { |
|
101 |
if (pos < element.overlapList.size()) { |
|
102 |
return element.overlapList.get(pos++); |
|
103 |
} |
|
104 |
return null; |
|
105 |
} |
|
106 |
} |
|
107 |
|
|
108 |
public FuseSpatiallyOperationFast2(AbstractSextanteGeoProcess process) { |
|
109 |
super(process); |
|
110 |
featureList = new ArrayList<Element>(); |
|
111 |
} |
|
112 |
|
|
113 |
@Override |
|
114 |
public EditableFeature invoke(org.gvsig.fmap.geom.Geometry g, |
|
115 |
Feature featureInput) { |
|
116 |
// TODO Auto-generated method stub |
|
117 |
return null; |
|
118 |
} |
|
119 |
|
|
120 |
@Override |
|
121 |
public void invoke(org.gvsig.fmap.geom.Geometry g, |
|
122 |
EditableFeature featureInput) { |
|
123 |
// TODO Auto-generated method stub |
|
124 |
|
|
125 |
} |
|
126 |
|
|
127 |
/** |
|
128 |
* Computes a complete operation over the input FeatureStore. The result of |
|
129 |
* this operation is stored in the output FeatureStore. This method will |
|
130 |
* call once for each geometry. |
|
131 |
* |
|
132 |
* @param inFeatStore Input FeatureStore |
|
133 |
* @param outFeatStore Output FeatureStore |
|
134 |
* @param outFeatStoreTable |
|
135 |
* @param attrNames List of attributes to build the output feature store |
|
136 |
* @param attrNamesTable |
|
137 |
* @param selectedGeomInput |
|
138 |
* @param selectedGeomOutput |
|
139 |
* @param idField |
|
140 |
* @param selectedGeom If it is true only the selected geometries will be |
|
141 |
* processed |
|
142 |
* @throws DataException |
|
143 |
*/ |
|
144 |
@SuppressWarnings("deprecation") |
|
145 |
public void computesGeometryOperation(FeatureStore inFeatStore, |
|
146 |
FeatureStore outFeatStore, |
|
147 |
FeatureStore outFeatStoreTable, |
|
148 |
String[] attrNames, |
|
149 |
String[] attrNamesTable, |
|
150 |
boolean selectedGeomInput, |
|
151 |
boolean selectedGeomOutput, |
|
152 |
String idField) throws DataException { |
|
153 |
this.outFeatStoreTable = outFeatStoreTable; |
|
154 |
this.nameIdField = idField; |
|
155 |
this.inFeatureStore = inFeatStore; |
|
156 |
this.selectedGeomInput = selectedGeomInput; |
|
157 |
this.selectedGeomOverlay = selectedGeomOutput; |
|
158 |
FeatureSet featuresSet = null; |
|
159 |
featuresSet = inFeatStore.getFeatureSet(); |
|
160 |
|
|
161 |
setFeatureStore(outFeatStore, attrNames); |
|
162 |
Iterator it = null; |
|
163 |
|
|
164 |
if (selectedGeomInput) { |
|
165 |
FeatureSelection ds = inFeatStore.getFeatureSelection(); |
|
166 |
it = ds.iterator(); |
|
167 |
numberOfFeatures = (int) ds.getSelectedCount(); |
|
168 |
} else { |
|
169 |
it = featuresSet.iterator(); |
|
170 |
numberOfFeatures = (int) featuresSet.getSize(); |
|
171 |
} |
|
172 |
|
|
173 |
if (status != null) { |
|
174 |
status.setRangeOfValues(0, numberOfFeatures); |
|
175 |
} |
|
176 |
if (process != null) { |
|
177 |
process.setProgress(0, numberOfFeatures); |
|
178 |
} |
|
179 |
|
|
180 |
//Crear lista de elementos |
|
181 |
int iCount = 0; |
|
182 |
while (it.hasNext() && !process.getTaskMonitor().isCanceled()) { |
|
183 |
Feature feat = ((Feature) it.next()).getCopy(); |
|
184 |
Element el = new Element(); |
|
185 |
el.feat = feat; |
|
186 |
el.id = iCount; |
|
187 |
featureList.add(el); |
|
188 |
if (status != null && process != null) { |
|
189 |
status.setCurValue(iCount); |
|
190 |
} |
|
191 |
if (process != null) { |
|
192 |
process.setProgress(iCount, numberOfFeatures); |
|
193 |
} |
|
194 |
iCount++; |
|
195 |
} |
|
196 |
// it.dispose(); |
|
197 |
|
|
198 |
//Crear listas de solapes para cada feature |
|
199 |
iCount = 0; |
|
200 |
while (iCount < featureList.size() && !process.getTaskMonitor().isCanceled()) { |
|
201 |
Element elem1 = featureList.get(iCount); |
|
202 |
org.gvsig.fmap.geom.Geometry geom1 = elem1.feat.getDefaultGeometry(); |
|
203 |
if (status != null) { |
|
204 |
status.setCurValue(iCount); |
|
205 |
} |
|
206 |
if (process != null) { |
|
207 |
process.setProgress(iCount, numberOfFeatures); |
|
208 |
} |
|
209 |
|
|
210 |
for (int i = iCount + 1; i < featureList.size(); i++) { |
|
211 |
Element elem2 = featureList.get(i); |
|
212 |
org.gvsig.fmap.geom.Geometry geom2 = elem2.feat.getDefaultGeometry(); |
|
213 |
if (areBBoxesOverlaping(geom1, geom2)) { |
|
214 |
if (elem1.jtsGeom == null) { |
|
215 |
elem1.jtsGeom = GeometryUtil.geomToJTS(geom1); |
|
216 |
} |
|
217 |
elem2.jtsGeom = GeometryUtil.geomToJTS(geom2); |
|
218 |
if (elem1.jtsGeom.intersects(elem2.jtsGeom)) { |
|
219 |
elem1.overlapList.add(elem2); |
|
220 |
elem2.overlapList.add(elem1); |
|
221 |
} |
|
222 |
} |
|
223 |
} |
|
224 |
iCount++; |
|
225 |
} |
|
226 |
|
|
227 |
iCount = 0; |
|
228 |
int iFeat = 0; |
|
229 |
while (iCount < featureList.size() && !process.getTaskMonitor().isCanceled()) { |
|
230 |
Element elem1 = featureList.get(iCount); |
|
231 |
if (status != null) { |
|
232 |
status.setCurValue(iCount); |
|
233 |
} |
|
234 |
if (process != null) { |
|
235 |
process.setProgress(iCount, numberOfFeatures); |
|
236 |
} |
|
237 |
|
|
238 |
if (!elem1.insertedToJoin) { |
|
239 |
buildListToJoin(elem1, iFeat); |
|
240 |
iFeat++; |
|
241 |
} |
|
242 |
|
|
243 |
iCount++; |
|
244 |
} |
|
245 |
|
|
246 |
if (persister != null) { |
|
247 |
persister.end(); |
|
248 |
} |
|
249 |
|
|
250 |
} |
|
251 |
|
|
252 |
private boolean areBBoxesOverlaping(org.gvsig.fmap.geom.Geometry g1, org.gvsig.fmap.geom.Geometry g2) { |
|
253 |
if (g1.getEnvelope().getMaximum(0) < g2.getEnvelope().getMinimum(0)) { |
|
254 |
return false; |
|
255 |
} |
|
256 |
if (g1.getEnvelope().getMinimum(0) > g2.getEnvelope().getMaximum(0)) { |
|
257 |
return false; |
|
258 |
} |
|
259 |
if (g1.getEnvelope().getMaximum(1) < g2.getEnvelope().getMinimum(1)) { |
|
260 |
return false; |
|
261 |
} |
|
262 |
if (g1.getEnvelope().getMinimum(1) > g2.getEnvelope().getMaximum(1)) { |
|
263 |
return false; |
|
264 |
} |
|
265 |
return true; |
|
266 |
} |
|
267 |
|
|
268 |
/** |
|
269 |
* Computes the union of the list of geometries |
|
270 |
* |
|
271 |
* @param listResult |
|
272 |
* @param elem1 |
|
273 |
* @return |
|
274 |
*/ |
|
275 |
private Geometry computesUnion(List<Geometry> listResult, Element elem1) { |
|
276 |
int splitValue = 500; |
|
277 |
Geometry newGeom = null; |
|
278 |
if (listResult.size() > splitValue) { |
|
279 |
List<List<Geometry>> list = splitList(listResult, splitValue); |
|
280 |
List<Geometry> result = new ArrayList<Geometry>(); |
|
281 |
for (int i = 0; i < list.size(); i++) { |
|
282 |
Geometry aux = GeometryUtil.geometryUnion(list.get(i), elem1.feat.getDefaultGeometry().getGeometryType().getType()); |
|
283 |
result.add(aux); |
|
284 |
} |
|
285 |
for (int i = 0; i < result.size(); i++) { |
|
286 |
newGeom = GeometryUtil.geometryUnion(result, elem1.feat.getDefaultGeometry().getGeometryType().getType()); |
|
287 |
} |
|
288 |
} else { |
|
289 |
newGeom = GeometryUtil.geometryUnion(listResult, elem1.feat.getDefaultGeometry().getGeometryType().getType()); |
|
290 |
} |
|
291 |
return newGeom; |
|
292 |
} |
|
293 |
|
|
294 |
private Geometry computesUnion2(List<Geometry> listResult, Element elem1) { |
|
295 |
Geometry newGeom = null; |
|
296 |
for (int i = 1; i < listResult.size(); i++) { |
|
297 |
if (i == 1) { |
|
298 |
newGeom = JTSFacade.union(listResult.get(0), listResult.get(1)); |
|
299 |
} else { |
|
300 |
newGeom = JTSFacade.union(newGeom, listResult.get(i)); |
|
301 |
} |
|
302 |
} |
|
303 |
return newGeom; |
|
304 |
} |
|
305 |
|
|
306 |
private Geometry computesUnion3(List<Geometry> listResult) { |
|
307 |
Geometry newGeom = null; |
|
308 |
int iCount = 0; |
|
309 |
int max = listResult.size(); |
|
310 |
if (process != null) { |
|
311 |
process.setName("Generating union"); |
|
312 |
} |
|
313 |
while (listResult.size() > 1) { |
|
314 |
List<Geometry> list = new ArrayList<Geometry>(); |
|
315 |
if (status != null) { |
|
316 |
status.setCurValue(iCount); |
|
317 |
} |
|
318 |
if (process != null) { |
|
319 |
process.setProgress(iCount, max); |
|
320 |
} |
|
321 |
for (int i = 0; i < listResult.size(); i = i + 2) { |
|
322 |
if (i == (listResult.size() - 1)) { |
|
323 |
list.add(listResult.get(i)); |
|
324 |
} else { |
|
325 |
newGeom = JTSFacade.union(listResult.get(i), listResult.get(i + 1)); |
|
326 |
list.add(newGeom); |
|
327 |
} |
|
328 |
} |
|
329 |
listResult = list; |
|
330 |
} |
|
331 |
return newGeom; |
|
332 |
} |
|
333 |
|
|
334 |
/** |
|
335 |
* Splits the array of geometries to compute its union because JTS cannot |
|
336 |
* support a lot of geometries |
|
337 |
* |
|
338 |
* @param list |
|
339 |
* @param n |
|
340 |
* @return |
|
341 |
*/ |
|
342 |
private List<List<Geometry>> splitList(List<Geometry> list, int n) { |
|
343 |
int elements = (int) (list.size() / n); |
|
344 |
List<List<Geometry>> l = new ArrayList<List<Geometry>>(); |
|
345 |
for (int i = 0; i < elements; i++) { |
|
346 |
l.add(list.subList((i * n), (i * n) + n)); |
|
347 |
} |
|
348 |
if (elements * n < list.size()) { |
|
349 |
l.add(list.subList((elements * n), list.size())); |
|
350 |
} |
|
351 |
return l; |
|
352 |
} |
|
353 |
|
|
354 |
/** |
|
355 |
* Builds the union of all lists |
|
356 |
* |
|
357 |
* @param listResult |
|
358 |
* @param listToJoin |
|
359 |
*/ |
|
360 |
private void buildListToJoin(Element elem, int iFeat) { |
|
361 |
Geometry newGeom = null; |
|
362 |
|
|
363 |
if (elem.overlapList.size() == 0) { |
|
364 |
if (!elem.insertedToJoin) { |
|
365 |
elem.insertedToJoin = true; |
|
366 |
} |
|
367 |
try { |
|
368 |
insertInTable(outFeatStoreTable, elem.feat, iFeat); |
|
369 |
addFeatureToOutput(elem.feat.getDefaultGeometry(), elem.feat, iFeat); |
|
370 |
} catch (DataException e) { |
|
371 |
logger.info("Imposible insertar en la tabla", e); |
|
372 |
} catch (CreateGeometryException e) { |
|
373 |
logger.info("Error a?adiendo geometr?a", e); |
|
374 |
} |
|
375 |
} else { |
|
376 |
List<Geometry> listResult = new ArrayList<Geometry>(); |
|
377 |
NodeTree subtree = new NodeTree(elem, null); |
|
378 |
//Hacemos un recorrido en profundidad del ?rbol para a?adir |
|
379 |
//todos los elementos a la lista de geometrias a unir sin |
|
380 |
//repetir ninguna. |
|
381 |
while (subtree != null) { |
|
382 |
if (!subtree.element.insertedToJoin) { |
|
383 |
listResult.add(subtree.element.jtsGeom); |
|
384 |
try { |
|
385 |
insertInTable(outFeatStoreTable, subtree.element.feat, iFeat); |
|
386 |
} catch (DataException e) { |
|
387 |
logger.info("Imposible insertar en la tabla", e); |
|
388 |
} |
|
389 |
subtree.element.insertedToJoin = true; |
|
390 |
} |
|
391 |
|
|
392 |
boolean back = false; |
|
393 |
|
|
394 |
Element l = subtree.getNext(); |
|
395 |
if (l == null) { |
|
396 |
back = true; |
|
397 |
} |
|
398 |
|
|
399 |
while (!back && l.insertedToJoin) { |
|
400 |
l = subtree.getNext(); |
|
401 |
if (l == null) { |
|
402 |
back = true; |
|
403 |
} |
|
404 |
} |
|
405 |
|
|
406 |
if (back) { |
|
407 |
subtree = subtree.parent; |
|
408 |
continue; |
|
409 |
} |
|
410 |
subtree = new NodeTree(l, subtree); |
|
411 |
} |
|
412 |
newGeom = computesUnion3(listResult); |
|
413 |
|
|
414 |
try { |
|
415 |
addFeatureToOutput(newGeom, elem.feat, iFeat); |
|
416 |
} catch (DataException e) { |
|
417 |
logger.info("Imposible insertar en la tabla", e); |
|
418 |
} catch (CreateGeometryException e) { |
|
419 |
logger.info("Error a?adiendo geometr?a", e); |
|
420 |
} |
|
421 |
} |
|
422 |
|
|
423 |
} |
|
424 |
|
|
425 |
/** |
|
426 |
* Adds a feature to the output |
|
427 |
* |
|
428 |
* @param newGeom |
|
429 |
* @param feat |
|
430 |
* @param newFeatID |
|
431 |
* @throws DataException |
|
432 |
* @throws CreateGeometryException |
|
433 |
*/ |
|
434 |
private void addFeatureToOutput(org.gvsig.fmap.geom.Geometry newGeom, |
|
435 |
Feature feat, |
|
436 |
int newFeatID) throws DataException, CreateGeometryException { |
|
437 |
//Si hay una tabla aparte esta capa solo lleva el id como referencia a la tabla de campos |
|
438 |
if (outFeatStoreTable != null) { |
|
439 |
lastEditFeature = persister.addFeature(newGeom, nameIdField, newFeatID); |
|
440 |
} else { |
|
441 |
//Si no hay tabla se ponen todos los campos de la tabla de entrada |
|
442 |
String[] fieldNames = persister.getFieldNamesWithoutGeom(); |
|
443 |
ArrayList<String> fields = new ArrayList<String>(); |
|
444 |
ArrayList<Object> values = new ArrayList<Object>(); |
|
445 |
fields.add(nameIdField); |
|
446 |
values.add(newFeatID); |
|
447 |
for (int j = 0; j < fieldNames.length; j++) { |
|
448 |
Object obj = feat.get(fieldNames[j]); |
|
449 |
if (obj != null && fieldNames[j].compareTo(nameIdField) != 0) { |
|
450 |
fields.add(fieldNames[j]); |
|
451 |
values.add(obj); |
|
452 |
} |
|
453 |
} |
|
454 |
lastEditFeature = persister.addFeature(newGeom, fields, values); |
|
455 |
} |
|
456 |
} |
|
457 |
|
|
458 |
/** |
|
459 |
* Adds a feature to the output |
|
460 |
* |
|
461 |
* @param newGeom |
|
462 |
* @param feat |
|
463 |
* @param newFeatID |
|
464 |
* @throws DataException |
|
465 |
* @throws CreateGeometryException |
|
466 |
*/ |
|
467 |
private void addFeatureToOutput(Geometry newGeom, |
|
468 |
Feature feat, |
|
469 |
int newFeatID) throws DataException, CreateGeometryException { |
|
470 |
//Si hay una tabla aparte esta capa solo lleva el id como referencia a la tabla de campos |
|
471 |
if (outFeatStoreTable != null) { |
|
472 |
lastEditFeature = persister.addFeature(newGeom, nameIdField, newFeatID); |
|
473 |
} else { |
|
474 |
//Si no hay tabla se ponen todos los campos de la tabla de entrada |
|
475 |
String[] fieldNames = persister.getFieldNamesWithoutGeom(); |
|
476 |
ArrayList<String> fields = new ArrayList<String>(); |
|
477 |
ArrayList<Object> values = new ArrayList<Object>(); |
|
478 |
fields.add(nameIdField); |
|
479 |
values.add(newFeatID); |
|
480 |
for (int j = 0; j < fieldNames.length; j++) { |
|
481 |
if (fieldNames[j].compareTo(nameIdField) != 0) { |
|
482 |
Object obj = feat.get(fieldNames[j]); |
|
483 |
if (obj != null) { |
|
484 |
fields.add(fieldNames[j]); |
|
485 |
values.add(obj); |
|
486 |
} |
|
487 |
} |
|
488 |
} |
|
489 |
|
|
490 |
lastEditFeature = persister.addFeature(newGeom, fields, values); |
|
491 |
} |
|
492 |
} |
|
493 |
|
|
494 |
/** |
|
495 |
* Insert in the output table a new feature with the fields of the input |
|
496 |
* feature. Moreover exists a field that is an identifier which is a |
|
497 |
* reference to the fusion layer. |
|
498 |
* |
|
499 |
* @param outFeatureStoreTable |
|
500 |
* @param f |
|
501 |
* @throws DataException |
|
502 |
*/ |
|
503 |
private void insertInTable(FeatureStore outFeatureStoreTable, Feature f, int reference) throws DataException { |
|
504 |
if (outFeatureStoreTable == null) { |
|
505 |
return; |
|
506 |
} |
|
507 |
EditableFeature edFeat = outFeatureStoreTable.createNewFeature(); |
|
508 |
edFeat.set(nameIdField, reference); |
|
509 |
FeatureAttributeDescriptor[] attrList = f.getType().getAttributeDescriptors(); |
|
510 |
for (int j = 0; j < attrList.length; j++) { |
|
511 |
if (attrList[j].getName().compareTo("GEOMETRY") != 0) { |
|
512 |
edFeat.set(attrList[j].getName(), f.get(attrList[j].getName())); |
|
513 |
} |
|
514 |
} |
|
515 |
outFeatureStoreTable.insert(edFeat); |
|
516 |
} |
|
517 |
|
|
518 |
} |
|
0 | 519 |
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.102/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/java/org/gvsig/geoprocess/algorithm/fusespatially/FuseSpatiallyOperationFast3.java | ||
---|---|---|
1 |
/** |
|
2 |
* gvSIG. Desktop Geographic Information System. |
|
3 |
* |
|
4 |
* Copyright (C) 2007-2012 gvSIG Association. |
|
5 |
* |
|
6 |
* This program is free software; you can redistribute it and/or |
|
7 |
* modify it under the terms of the GNU General Public License |
|
8 |
* as published by the Free Software Foundation; either version 2 |
|
9 |
* of the License, or (at your option) any later version. |
|
10 |
* |
|
11 |
* This program is distributed in the hope that it will be useful, |
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
* GNU General Public License for more details. |
|
15 |
* |
|
16 |
* You should have received a copy of the GNU General Public License |
|
17 |
* along with this program; if not, write to the Free Software |
|
18 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
19 |
* MA 02110-1301, USA. |
|
20 |
* |
|
21 |
* For any additional information, do not hesitate to contact us |
|
22 |
* at info AT gvsig.com, or visit our website www.gvsig.com. |
|
23 |
*/ |
|
24 |
/* |
|
25 |
|
|
26 |
* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana |
|
27 |
* |
|
28 |
* Copyright (C) 2010 Generalitat Valenciana. |
|
29 |
* |
|
30 |
* This program is free software; you can redistribute it and/or |
|
31 |
* modify it under the terms of the GNU General Public License |
|
32 |
* as published by the Free Software Foundation; either version 2 |
|
33 |
* of the License, or (at your option) any later version. |
|
34 |
* |
|
35 |
* This program is distributed in the hope that it will be useful, |
|
36 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
37 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
38 |
* GNU General Public License for more details. |
|
39 |
* |
|
40 |
* You should have received a copy of the GNU General Public License |
|
41 |
* along with this program; if not, write to the Free Software |
|
42 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA. |
|
43 |
*/ |
|
44 |
|
|
45 |
package org.gvsig.geoprocess.algorithm.fusespatially; |
|
46 |
|
|
47 |
import java.util.ArrayList; |
|
48 |
import java.util.List; |
|
49 |
|
|
50 |
import org.gvsig.fmap.dal.exception.DataException; |
|
51 |
import org.gvsig.fmap.dal.feature.EditableFeature; |
|
52 |
import org.gvsig.fmap.dal.feature.Feature; |
|
53 |
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
|
54 |
import org.gvsig.fmap.dal.feature.FeatureSelection; |
|
55 |
import org.gvsig.fmap.dal.feature.FeatureSet; |
|
56 |
import org.gvsig.fmap.dal.feature.FeatureStore; |
|
57 |
import org.gvsig.fmap.geom.exception.CreateGeometryException; |
|
58 |
import org.gvsig.geoprocess.algorithm.base.core.GeometryOperation; |
|
59 |
import org.gvsig.geoprocess.algorithm.base.util.GeometryUtil; |
|
60 |
import org.gvsig.geoprocess.algorithm.base.util.JTSFacade; |
|
61 |
import org.gvsig.geoprocess.lib.sextante.AbstractSextanteGeoProcess; |
|
62 |
import org.slf4j.Logger; |
|
63 |
import org.slf4j.LoggerFactory; |
|
64 |
|
|
65 |
import com.vividsolutions.jts.geom.Geometry; |
|
66 |
import java.util.Iterator; |
|
67 |
/** |
|
68 |
* Fuse spatially operation |
|
69 |
* @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a> |
|
70 |
*/ |
|
71 |
public class FuseSpatiallyOperationFast3 extends GeometryOperation { |
|
72 |
private static Logger logger = LoggerFactory.getLogger(FuseSpatiallyOperationFast3.class.getName()); |
|
73 |
private ArrayList<Element> featureList = null; |
|
74 |
private String nameIdField = null; |
|
75 |
private FeatureStore outFeatStoreTable = null; |
|
76 |
private NodeTree baseTree = null; |
|
77 |
|
|
78 |
class Element { |
|
79 |
public int id = -1; |
|
80 |
public Feature feat = null; |
|
81 |
public List<Element> overlapList = new ArrayList<Element>(); |
|
82 |
public boolean insertedToJoin = false; |
|
83 |
public Geometry jtsGeom = null; |
|
84 |
} |
|
85 |
|
|
86 |
class NodeTree { |
|
87 |
public Element element = null; |
|
88 |
public int pos = 0; |
|
89 |
public NodeTree parent = null; |
|
90 |
|
|
91 |
public NodeTree(Element node, NodeTree parent) { |
|
92 |
this.element = node; |
|
93 |
this.parent = parent; |
|
94 |
} |
|
95 |
|
|
96 |
public Element getNext() { |
|
97 |
if(pos < element.overlapList.size()) |
|
98 |
return element.overlapList.get(pos++); |
|
99 |
return null; |
|
100 |
} |
|
101 |
} |
|
102 |
|
|
103 |
public FuseSpatiallyOperationFast3(AbstractSextanteGeoProcess process) { |
|
104 |
super(process); |
|
105 |
featureList = new ArrayList<Element>(); |
|
106 |
} |
|
107 |
|
|
108 |
@Override |
|
109 |
public EditableFeature invoke(org.gvsig.fmap.geom.Geometry g, |
|
110 |
Feature featureInput) { |
|
111 |
// TODO Auto-generated method stub |
|
112 |
return null; |
|
113 |
} |
|
114 |
|
|
115 |
@Override |
|
116 |
public void invoke(org.gvsig.fmap.geom.Geometry g, |
|
117 |
EditableFeature featureInput) { |
|
118 |
// TODO Auto-generated method stub |
|
119 |
|
|
120 |
} |
|
121 |
|
|
122 |
/** |
|
123 |
* Computes a complete operation over the input FeatureStore. The result of this operation |
|
124 |
* is stored in the output FeatureStore. This method will call once for each geometry. |
|
125 |
* @param inFeatStore |
|
126 |
* Input FeatureStore |
|
127 |
* @param outFeatStore |
|
128 |
* Output FeatureStore |
|
129 |
* @param attrNames |
|
130 |
* List of attributes to build the output feature store |
|
131 |
* @param selectedGeom |
|
132 |
* If it is true only the selected geometries will be processed |
|
133 |
* @throws DataException |
|
134 |
*/ |
|
135 |
@SuppressWarnings("deprecation") |
|
136 |
public void computesGeometryOperation(FeatureStore inFeatStore, |
|
137 |
FeatureStore outFeatStore, |
|
138 |
FeatureStore outFeatStoreTable, |
|
139 |
String[] attrNames, |
|
140 |
String[] attrNamesTable, |
|
141 |
boolean selectedGeomInput, |
|
142 |
boolean selectedGeomOutput, |
|
143 |
String idField) throws DataException { |
|
144 |
this.outFeatStoreTable = outFeatStoreTable; |
|
145 |
this.nameIdField = idField; |
|
146 |
this.inFeatureStore = inFeatStore; |
|
147 |
this.selectedGeomInput = selectedGeomInput; |
|
148 |
this.selectedGeomOverlay = selectedGeomOutput; |
|
149 |
FeatureSet featuresSet = null; |
|
150 |
featuresSet = inFeatStore.getFeatureSet(); |
|
151 |
|
|
152 |
setFeatureStore(outFeatStore, attrNames); |
|
153 |
Iterator it = null; |
|
154 |
|
|
155 |
if(selectedGeomInput) { |
|
156 |
FeatureSelection ds = inFeatStore.getFeatureSelection(); |
|
157 |
it = ds.iterator(); |
|
158 |
numberOfFeatures = (int) ds.getSelectedCount(); |
|
159 |
} else { |
|
160 |
it = featuresSet.iterator(); |
|
161 |
numberOfFeatures = (int)featuresSet.getSize(); |
|
162 |
} |
|
163 |
|
|
164 |
if (status != null) |
|
165 |
status.setRangeOfValues(0, numberOfFeatures); |
|
166 |
if(process != null) |
|
167 |
process.setProgress(0, numberOfFeatures); |
|
168 |
|
|
169 |
//Crear lista de elementos |
|
170 |
int iCount = 0; |
|
171 |
while( it.hasNext() && !process.getTaskMonitor().isCanceled()) { |
|
172 |
Feature feat = (Feature)it.next(); |
|
173 |
Element el = new Element(); |
|
174 |
el.feat = feat; |
|
175 |
el.id = iCount; |
|
176 |
featureList.add(el); |
|
177 |
if (status != null && process != null) |
|
178 |
status.setCurValue(iCount); |
|
179 |
if(process != null) |
|
180 |
process.setProgress(iCount, numberOfFeatures); |
|
181 |
iCount ++; |
|
182 |
} |
|
183 |
// it.dispose(); |
|
184 |
|
|
185 |
//Crear listas de solapes para cada feature |
|
186 |
iCount = 0; |
|
187 |
while (iCount < featureList.size() && !process.getTaskMonitor().isCanceled()) { |
|
188 |
Element elem1 = featureList.get(iCount); |
|
189 |
org.gvsig.fmap.geom.Geometry geom1 = elem1.feat.getDefaultGeometry(); |
|
190 |
if (status != null) |
|
191 |
status.setCurValue(iCount); |
|
192 |
if(process != null) |
|
193 |
process.setProgress(iCount, numberOfFeatures); |
|
194 |
|
|
195 |
for (int i = iCount + 1; i < featureList.size(); i++) { |
|
196 |
Element elem2 = featureList.get(i); |
|
197 |
org.gvsig.fmap.geom.Geometry geom2 = elem2.feat.getDefaultGeometry(); |
|
198 |
if(areBBoxesOverlaping(geom1, geom2)) { |
|
199 |
if(elem1.jtsGeom == null) |
|
200 |
elem1.jtsGeom = GeometryUtil.geomToJTS(geom1); |
|
201 |
elem2.jtsGeom = GeometryUtil.geomToJTS(geom2); |
|
202 |
if(elem1.jtsGeom.intersects(elem2.jtsGeom)) { |
|
203 |
elem1.overlapList.add(elem2); |
|
204 |
elem2.overlapList.add(elem1); |
|
205 |
} |
|
206 |
} |
|
207 |
} |
|
208 |
iCount ++; |
|
209 |
} |
|
210 |
|
|
211 |
iCount = 0; |
|
212 |
int iFeat = 0; |
|
213 |
while (iCount < featureList.size() && !process.getTaskMonitor().isCanceled()) { |
|
214 |
Element elem1 = featureList.get(iCount); |
|
215 |
if (status != null) |
|
216 |
status.setCurValue(iCount); |
|
217 |
if(process != null) |
|
218 |
process.setProgress(iCount, numberOfFeatures); |
|
219 |
|
|
220 |
if(!elem1.insertedToJoin) { |
|
221 |
buildListToJoin(elem1, iFeat); |
|
222 |
iFeat ++; |
|
223 |
} |
|
224 |
iCount ++; |
|
225 |
} |
|
226 |
|
|
227 |
if(persister != null) |
|
228 |
persister.end(); |
|
229 |
|
|
230 |
} |
|
231 |
|
|
232 |
private boolean areBBoxesOverlaping(org.gvsig.fmap.geom.Geometry g1, org.gvsig.fmap.geom.Geometry g2) { |
|
233 |
if(g1.getEnvelope().getMaximum(0) < g2.getEnvelope().getMinimum(0)) |
|
234 |
return false; |
|
235 |
if(g1.getEnvelope().getMinimum(0) > g2.getEnvelope().getMaximum(0)) |
|
236 |
return false; |
|
237 |
if(g1.getEnvelope().getMaximum(1) < g2.getEnvelope().getMinimum(1)) |
|
238 |
return false; |
|
239 |
if(g1.getEnvelope().getMinimum(1) > g2.getEnvelope().getMaximum(1)) |
|
240 |
return false; |
|
241 |
return true; |
|
242 |
} |
|
243 |
|
|
244 |
/** |
|
245 |
* Computes the union of the list of geometries |
|
246 |
* @param listResult |
|
247 |
* @param elem1 |
|
248 |
* @return |
|
249 |
*/ |
|
250 |
private Geometry computesUnion(List<Geometry> listResult, Element elem1) { |
|
251 |
int splitValue = 500; |
|
252 |
Geometry newGeom = null; |
|
253 |
if(listResult.size() > splitValue) { |
|
254 |
List<List<Geometry>> list = splitList(listResult, splitValue); |
|
255 |
List<Geometry> result = new ArrayList<Geometry>(); |
|
256 |
for (int i = 0; i < list.size(); i++) { |
|
257 |
Geometry aux = GeometryUtil.geometryUnion(list.get(i), elem1.feat.getDefaultGeometry().getGeometryType().getType()); |
|
258 |
result.add(aux); |
|
259 |
} |
|
260 |
for (int i = 0; i < result.size(); i++) { |
|
261 |
newGeom = GeometryUtil.geometryUnion(result, elem1.feat.getDefaultGeometry().getGeometryType().getType()); |
|
262 |
} |
|
263 |
} else { |
|
264 |
newGeom = GeometryUtil.geometryUnion(listResult, elem1.feat.getDefaultGeometry().getGeometryType().getType()); |
|
265 |
} |
|
266 |
return newGeom; |
|
267 |
} |
|
268 |
|
|
269 |
private Geometry computesUnion2(List<Geometry> listResult, Element elem1) { |
|
270 |
Geometry newGeom = null; |
|
271 |
for (int i = 1; i < listResult.size(); i++) { |
|
272 |
if(i == 1) |
|
273 |
newGeom = JTSFacade.union(listResult.get(0), listResult.get(1)); |
|
274 |
else |
|
275 |
newGeom = JTSFacade.union(newGeom, listResult.get(i)); |
|
276 |
} |
|
277 |
return newGeom; |
|
278 |
} |
|
279 |
|
|
280 |
private Geometry computesUnion3(List<Geometry> listResult) { |
|
281 |
Geometry newGeom = null; |
|
282 |
int iCount = 0; |
|
283 |
int max = listResult.size(); |
|
284 |
if(process != null) |
|
285 |
process.setName("Generating union"); |
|
286 |
while(listResult.size() > 1) { |
|
287 |
List<Geometry> list = new ArrayList<Geometry>(); |
|
288 |
if (status != null) |
|
289 |
status.setCurValue(iCount); |
|
290 |
if(process != null) |
|
291 |
process.setProgress(iCount, max); |
|
292 |
for (int i = 0; i < listResult.size(); i = i + 2) { |
|
293 |
if(i == (listResult.size() - 1)) |
|
294 |
list.add(listResult.get(i)); |
|
295 |
else { |
|
296 |
newGeom = JTSFacade.union(listResult.get(i), listResult.get(i + 1)); |
|
297 |
list.add(newGeom); |
|
298 |
} |
|
299 |
} |
|
300 |
listResult = list; |
|
301 |
} |
|
302 |
return newGeom; |
|
303 |
} |
|
304 |
|
|
305 |
/** |
|
306 |
* Splits the array of geometries to compute its union because JTS cannot support |
|
307 |
* a lot of geometries |
|
308 |
* @param list |
|
309 |
* @param n |
|
310 |
* @return |
|
311 |
*/ |
|
312 |
private List<List<Geometry>> splitList(List<Geometry> list, int n) { |
|
313 |
int elements = (int)(list.size() / n); |
|
314 |
List<List<Geometry>> l = new ArrayList<List<Geometry>>(); |
|
315 |
for (int i = 0; i < elements; i++) { |
|
316 |
l.add(list.subList((i * n), (i * n) + n)); |
|
317 |
} |
|
318 |
if(elements * n < list.size()) { |
|
319 |
l.add(list.subList((elements * n), list.size())); |
|
320 |
} |
|
321 |
return l; |
|
322 |
} |
|
323 |
|
|
324 |
/** |
|
325 |
* Builds the union of all lists |
|
326 |
* @param listResult |
|
327 |
* @param listToJoin |
|
328 |
*/ |
|
329 |
private void buildListToJoin(Element elem, int iFeat) { |
|
330 |
Geometry newGeom = null; |
|
331 |
|
|
332 |
if(elem.overlapList.size() == 0) { |
|
333 |
if(!elem.insertedToJoin) |
|
334 |
elem.insertedToJoin = true; |
|
335 |
newGeom = elem.jtsGeom; |
|
336 |
} else { |
|
337 |
List<Geometry> listResult = new ArrayList<Geometry>(); |
|
338 |
NodeTree subtree = new NodeTree(elem, null); |
|
339 |
//Hacemos un recorrido en profundidad del ?rbol para a?adir |
|
340 |
//todos los elementos a la lista de geometrias a unir sin |
|
341 |
//repetir ninguna. |
|
342 |
while (subtree != null) { |
|
343 |
if(!subtree.element.insertedToJoin) { |
|
344 |
listResult.add(subtree.element.jtsGeom); |
|
345 |
subtree.element.insertedToJoin = true; |
|
346 |
} |
|
347 |
|
|
348 |
boolean back = false; |
|
349 |
|
|
350 |
Element l = subtree.getNext(); |
|
351 |
if(l == null) |
|
352 |
back = true; |
|
353 |
|
|
354 |
while(!back && l.insertedToJoin) { |
|
355 |
l = subtree.getNext(); |
|
356 |
if(l == null) |
|
357 |
back = true; |
|
358 |
} |
|
359 |
|
|
360 |
if(back) { |
|
361 |
subtree = subtree.parent; |
|
362 |
continue; |
|
363 |
} |
|
364 |
|
|
365 |
subtree = new NodeTree(l, subtree); |
|
366 |
} |
|
367 |
|
|
368 |
newGeom = computesUnion3(listResult); |
|
369 |
} |
|
370 |
|
|
371 |
try { |
|
372 |
insertInTable(outFeatStoreTable, elem.feat, iFeat); |
|
373 |
addFeatureToOutput(newGeom, elem.feat, iFeat); |
|
374 |
} catch (DataException e) { |
|
375 |
logger.info("Imposible insertar en la tabla", e); |
|
376 |
} catch (CreateGeometryException e) { |
|
377 |
logger.info("Error a?adiendo geometr?a", e); |
|
378 |
} |
|
379 |
|
|
380 |
} |
|
381 |
|
|
382 |
/** |
|
383 |
* Adds a feature to the output |
|
384 |
* @param newGeom |
|
385 |
* @param feat |
|
386 |
* @param newFeatID |
|
387 |
* @throws DataException |
|
388 |
* @throws CreateGeometryException |
|
389 |
*/ |
|
390 |
private void addFeatureToOutput(Geometry newGeom, |
|
391 |
Feature feat, |
|
392 |
int newFeatID) throws DataException, CreateGeometryException { |
|
393 |
//Si hay una tabla aparte esta capa solo lleva el id como referencia a la tabla de campos |
|
394 |
if(outFeatStoreTable != null) { |
|
395 |
lastEditFeature = persister.addFeature(newGeom, nameIdField, newFeatID); |
|
396 |
} else { |
|
397 |
//Si no hay tabla se ponen todos los campos de la tabla de entrada |
|
398 |
String[] fieldNames = persister.getFieldNamesWithoutGeom(); |
|
399 |
ArrayList<String> fields = new ArrayList<String>(); |
|
400 |
ArrayList<Object> values = new ArrayList<Object>(); |
|
401 |
fields.add(nameIdField); |
|
402 |
values.add(newFeatID); |
|
403 |
for (int j = 0; j < fieldNames.length; j++) { |
|
404 |
Object obj = feat.get(fieldNames[j]); |
|
405 |
if(obj != null && fieldNames[j].compareTo(nameIdField) != 0) { |
|
406 |
fields.add(fieldNames[j]); |
|
407 |
values.add(obj); |
|
408 |
} |
|
409 |
} |
|
410 |
lastEditFeature = persister.addFeature(newGeom, fields, values); |
|
411 |
} |
|
412 |
} |
|
413 |
|
|
414 |
/** |
|
415 |
* Insert in the output table a new feature with the fields of the input feature. Moreover |
|
416 |
* exists a field that is an identifier which is a reference to the fusion layer. |
|
417 |
* @param outFeatureStoreTable |
|
418 |
* @param f |
|
419 |
* @throws DataException |
|
420 |
*/ |
|
421 |
private void insertInTable(FeatureStore outFeatureStoreTable, Feature f, int reference) throws DataException { |
|
422 |
if(outFeatureStoreTable == null) |
|
423 |
return; |
|
424 |
EditableFeature edFeat = outFeatureStoreTable.createNewFeature(); |
|
425 |
edFeat.set(nameIdField, reference); |
|
426 |
FeatureAttributeDescriptor[] attrList = f.getType().getAttributeDescriptors(); |
|
427 |
for (int j = 0; j < attrList.length; j++) { |
|
428 |
if(attrList[j].getName().compareTo("GEOMETRY") != 0) { |
|
429 |
edFeat.set(attrList[j].getName(), f.get(attrList[j].getName())); |
|
430 |
} |
|
431 |
} |
|
432 |
outFeatureStoreTable.insert(edFeat); |
|
433 |
} |
|
434 |
|
|
435 |
} |
|
436 |
|
|
0 | 437 |
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.102/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/java/org/gvsig/geoprocess/algorithm/fusespatially/FuseSpatiallyLibrary.java | ||
---|---|---|
1 |
/** |
|
2 |
* gvSIG. Desktop Geographic Information System. |
|
3 |
* |
|
4 |
* Copyright (C) 2007-2012 gvSIG Association. |
|
5 |
* |
|
6 |
* This program is free software; you can redistribute it and/or |
|
7 |
* modify it under the terms of the GNU General Public License |
|
8 |
* as published by the Free Software Foundation; either version 2 |
|
9 |
* of the License, or (at your option) any later version. |
|
10 |
* |
|
11 |
* This program is distributed in the hope that it will be useful, |
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
* GNU General Public License for more details. |
|
15 |
* |
|
16 |
* You should have received a copy of the GNU General Public License |
|
17 |
* along with this program; if not, write to the Free Software |
|
18 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
19 |
* MA 02110-1301, USA. |
|
20 |
* |
|
21 |
* For any additional information, do not hesitate to contact us |
|
22 |
* at info AT gvsig.com, or visit our website www.gvsig.com. |
|
23 |
*/ |
|
24 |
package org.gvsig.geoprocess.algorithm.fusespatially; |
|
25 |
|
|
26 |
import org.gvsig.geoprocess.algorithm.base.core.AlgorithmAbstractLibrary; |
|
27 |
import org.gvsig.i18n.Messages; |
|
28 |
import org.gvsig.tools.library.LibraryException; |
|
29 |
|
|
30 |
/** |
|
31 |
* Initialization of FuseSpatiallyLibrary library. |
|
32 |
* |
|
33 |
* @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a> |
|
34 |
*/ |
|
35 |
public class FuseSpatiallyLibrary extends AlgorithmAbstractLibrary { |
|
36 |
|
|
37 |
@Override |
|
38 |
protected void doInitialize() throws LibraryException { |
|
39 |
|
|
40 |
} |
|
41 |
|
|
42 |
@Override |
|
43 |
protected void doPostInitialize() throws LibraryException { |
|
44 |
Messages.addResourceFamily( |
|
45 |
"org.gvsig.geoprocess.algorithm.fusespatially.fusespatially", |
|
46 |
FuseSpatiallyLibrary.class.getClassLoader(), FuseSpatiallyLibrary.class |
|
47 |
.getClass().getName()); |
|
48 |
|
|
49 |
registerGeoProcess(new FuseSpatiallyAlgorithm()); |
|
50 |
} |
|
51 |
|
|
52 |
} |
|
0 | 53 |
Also available in: Unified diff