This release introduces the streamlined API we've announced in 0.1.10.
Most importantly, we've simplified the type system. OpenStreetMap features are represented as nodes, ways and relations, and GeoDesk has corresponding Node
, Way
and Relation
interfaces, which derive from the Feature
supertype. In 0.2, these subtypes still exist as marker interfaces, but their specialized methods have moved to the supertype. This means that all features can simply be treated as a Feature
, which removes the need for casting and awkward generics. When working with feature sets, you'll no longer need to declare Features<?>
or Features<Node>
-- you'll simply use Features
.
This change aligns more closely with how users think about OSM data. Most points-of-interest can be modeled as nodes, ways or relations -- for example, a museum could be marked as a single point, a simple polygon (as a closed way) or a building with a courtyard (requiring a multipolygon relation). In those cases where the OSM type matters, use .isNode()
, .isWay()
or .isRelation()
(or type()
).
We've prepared a Migration Guide to ensure your upgrade goes smoothly.
Breaking changes
-
The
Features
interface is no longer generic. Iterating overFeatures
always
returnsFeature
objects. -
The typed methods (
memberNodes()
,parentRelations()
, etc.) have been
removed. To constrain a type, usemembers().nodes()
,parents().relations()
,
or include the feature type in a query string (members("n")
,parents("r")
). -
All classes from
com.geodesk.core
(such asBox
andHeading
) have moved tocom.geodesk.geom
Enhancements
-
Applying spatial filters is now much simpler. Instead of using the
Filters
factory class, filters can now be invoked directly on theFeatures
object.So instead of
biotopes.select(Filters.coveredBy(area))
simply use
biotopes.coveredBy(area)
Note that several spatial filter methods have changed names:
contains()
->containing()
crosses()
->crossing()
intersects()
->intersecting()
overlaps()
->overlapping()
touches()
->touching()
These changes make your code read more naturally:
bridges.crossing(river)
adminAreas.touching(county)
This change also resolves the ambiguity concerning
contains()
:Features.contains(Object)
checks if the given feature is part of this feature set.Features.containing(Feature)
returns the features whose geometry contains the given feature.
Deprecations
- The
Filters
factory class has been deprecated and may be removed in future releases.
The preferred way to use filters is to call the filter methods onFeatures
, as discussed above.