1 /**********************************************************************
3 * GEOS - Geometry Engine Open Source
4 * http://geos.osgeo.org
6 * Copyright (C) 2001-2002 Vivid Solutions Inc.
7 * Copyright (C) 2005 2006 Refractions Research Inc.
9 * This is free software; you can redistribute and/or modify it under
10 * the terms of the GNU Lesser General Public Licence as published
11 * by the Free Software Foundation.
12 * See the COPYING file for more information.
14 **********************************************************************
16 * Last port: geom/GeometryCollection.java rev. 1.41
18 **********************************************************************/
20 #include <geos/geom/GeometryCollection.h>
21 #include <geos/algorithm/CGAlgorithms.h>
22 #include <geos/util/IllegalArgumentException.h>
23 #include <geos/geom/CoordinateSequence.h>
24 #include <geos/geom/CoordinateSequenceFilter.h>
25 #include <geos/geom/CoordinateArraySequenceFactory.h>
26 #include <geos/geom/Dimension.h>
27 #include <geos/geom/GeometryFilter.h>
28 #include <geos/geom/GeometryComponentFilter.h>
29 #include <geos/geom/Envelope.h>
32 # include <geos/geom/GeometryCollection.inl>
42 namespace geom
{ // geos::geom
45 GeometryCollection::GeometryCollection(const GeometryCollection
&gc
)
49 size_t ngeoms
=gc
.geometries
->size();
51 geometries
=new vector
<Geometry
*>(ngeoms
);
52 for(size_t i
=0; i
<ngeoms
; ++i
)
54 (*geometries
)[i
]=(*gc
.geometries
)[i
]->clone();
55 // Drop SRID from inner geoms
56 (*geometries
)[i
]->setSRID(0);
61 GeometryCollection::GeometryCollection(vector
<Geometry
*> *newGeoms
, const GeometryFactory
*factory
):
65 geometries
=new vector
<Geometry
*>();
68 if (hasNullElements(newGeoms
)) {
69 throw util::IllegalArgumentException("geometries must not contain null elements\n");
74 // Drop SRID from inner geoms
75 size_t ngeoms
=geometries
->size();
76 for(size_t i
=0; i
<ngeoms
; ++i
)
78 (*geometries
)[i
]->setSRID(0);
83 * Collects all coordinates of all subgeometries into a CoordinateSequence.
85 * Returns a newly the collected coordinates
89 GeometryCollection::getCoordinates() const
91 vector
<Coordinate
> *coordinates
= new vector
<Coordinate
>(getNumPoints());
94 for (size_t i
=0; i
<geometries
->size(); ++i
) {
95 CoordinateSequence
* childCoordinates
=(*geometries
)[i
]->getCoordinates();
96 size_t npts
=childCoordinates
->getSize();
97 for (size_t j
=0; j
<npts
; ++j
) {
99 (*coordinates
)[k
] = childCoordinates
->getAt(j
);
101 delete childCoordinates
;
103 return CoordinateArraySequenceFactory::instance()->create(coordinates
);
107 GeometryCollection::isEmpty() const
109 for (size_t i
=0; i
<geometries
->size(); ++i
) {
110 if (!(*geometries
)[i
]->isEmpty()) {
117 Dimension::DimensionType
118 GeometryCollection::getDimension() const
120 Dimension::DimensionType dimension
=Dimension::False
;
121 for (size_t i
=0, n
=geometries
->size(); i
<n
; ++i
)
123 dimension
=max(dimension
,(*geometries
)[i
]->getDimension());
129 GeometryCollection::getBoundaryDimension() const
131 int dimension
=Dimension::False
;
132 for(size_t i
=0; i
<geometries
->size(); ++i
) {
133 dimension
=max(dimension
,(*geometries
)[i
]->getBoundaryDimension());
139 GeometryCollection::getCoordinateDimension() const
143 for (size_t i
=0, n
=geometries
->size(); i
<n
; ++i
)
145 dimension
=max(dimension
,(*geometries
)[i
]->getCoordinateDimension());
151 GeometryCollection::getNumGeometries() const
153 return geometries
->size();
157 GeometryCollection::getGeometryN(size_t n
) const
159 return (*geometries
)[n
];
163 GeometryCollection::getNumPoints() const
165 size_t numPoints
= 0;
166 for (size_t i
=0, n
=geometries
->size(); i
<n
; ++i
)
168 numPoints
+=(*geometries
)[i
]->getNumPoints();
174 GeometryCollection::getGeometryType() const
176 return "GeometryCollection";
180 GeometryCollection::getBoundary() const
182 throw util::IllegalArgumentException("Operation not supported by GeometryCollection\n");
186 GeometryCollection::equalsExact(const Geometry
*other
, double tolerance
) const
188 if (!isEquivalentClass(other
)) return false;
190 const GeometryCollection
* otherCollection
=dynamic_cast<const GeometryCollection
*>(other
);
191 if ( ! otherCollection
) return false;
193 if (geometries
->size()!=otherCollection
->geometries
->size()) {
196 for (size_t i
=0; i
<geometries
->size(); ++i
) {
197 if (!((*geometries
)[i
]->equalsExact((*(otherCollection
->geometries
))[i
],tolerance
)))
206 GeometryCollection::apply_rw(const CoordinateFilter
*filter
)
208 for (size_t i
=0; i
<geometries
->size(); ++i
)
210 (*geometries
)[i
]->apply_rw(filter
);
215 GeometryCollection::apply_ro(CoordinateFilter
*filter
) const
217 for (size_t i
=0; i
<geometries
->size(); ++i
)
219 (*geometries
)[i
]->apply_ro(filter
);
224 GeometryCollection::apply_ro(GeometryFilter
*filter
) const
226 filter
->filter_ro(this);
227 for(size_t i
=0; i
<geometries
->size(); ++i
)
229 (*geometries
)[i
]->apply_ro(filter
);
234 GeometryCollection::apply_rw(GeometryFilter
*filter
)
236 filter
->filter_rw(this);
237 for(size_t i
=0; i
<geometries
->size(); ++i
)
239 (*geometries
)[i
]->apply_rw(filter
);
244 GeometryCollection::normalize()
246 for (size_t i
=0; i
<geometries
->size(); ++i
) {
247 (*geometries
)[i
]->normalize();
249 sort(geometries
->begin(), geometries
->end(), GeometryGreaterThen());
253 GeometryCollection::computeEnvelopeInternal() const
255 Envelope::AutoPtr
envelope(new Envelope());
256 for (size_t i
=0; i
<geometries
->size(); i
++) {
257 const Envelope
*env
=(*geometries
)[i
]->getEnvelopeInternal();
258 envelope
->expandToInclude(env
);
264 GeometryCollection::compareToSameClass(const Geometry
*g
) const
266 const GeometryCollection
* gc
= dynamic_cast<const GeometryCollection
*>(g
);
267 return compare(*geometries
, *(gc
->geometries
));
271 GeometryCollection::getCoordinate() const
273 // should use auto_ptr here or return NULL or throw an exception !
275 if (isEmpty()) return new Coordinate();
276 return (*geometries
)[0]->getCoordinate();
280 * @return the area of this collection
283 GeometryCollection::getArea() const
286 for(size_t i
=0; i
<geometries
->size(); ++i
)
288 area
+=(*geometries
)[i
]->getArea();
294 * @return the total length of this collection
297 GeometryCollection::getLength() const
300 for(size_t i
=0; i
<geometries
->size(); ++i
)
302 sum
+=(*geometries
)[i
]->getLength();
308 GeometryCollection::apply_rw(GeometryComponentFilter
*filter
)
310 filter
->filter_rw(this);
311 for(size_t i
=0; i
<geometries
->size(); ++i
)
313 (*geometries
)[i
]->apply_rw(filter
);
318 GeometryCollection::apply_ro(GeometryComponentFilter
*filter
) const
320 filter
->filter_ro(this);
321 for(size_t i
=0; i
<geometries
->size(); ++i
)
323 (*geometries
)[i
]->apply_ro(filter
);
328 GeometryCollection::apply_rw(CoordinateSequenceFilter
& filter
)
330 size_t ngeoms
= geometries
->size();
331 if (ngeoms
== 0 ) return;
332 for (size_t i
= 0; i
< ngeoms
; ++i
)
334 (*geometries
)[i
]->apply_rw(filter
);
335 if (filter
.isDone()) break;
337 if (filter
.isGeometryChanged()) geometryChanged();
341 GeometryCollection::apply_ro(CoordinateSequenceFilter
& filter
) const
343 size_t ngeoms
= geometries
->size();
344 if (ngeoms
== 0 ) return;
345 for (size_t i
= 0; i
< ngeoms
; ++i
)
347 (*geometries
)[i
]->apply_ro(filter
);
348 if (filter
.isDone()) break;
351 assert(!filter
.isGeometryChanged()); // read-only filter...
352 //if (filter.isGeometryChanged()) geometryChanged();
355 GeometryCollection::~GeometryCollection()
357 for(size_t i
=0; i
<geometries
->size(); ++i
)
359 delete (*geometries
)[i
];
365 GeometryCollection::getGeometryTypeId() const
367 return GEOS_GEOMETRYCOLLECTION
;
370 } // namespace geos::geom