Skip to content

Commit

Permalink
CBIDXT-253: Encode geometries as WKB (Well-Known Binary)
Browse files Browse the repository at this point in the history
The geometries were stored as Erlang terms on disk. This is bad for
interoperability. The geometries are now stored as WKB (Well-Known Binary).

This is a port of 59fa359 to the
Apache CouchDB compatible version for GeoCouch.

Change-Id: I76b834461bd14b5ac684b6b4f52d3da8db8b8f95
  • Loading branch information
vmx committed Jun 10, 2016
1 parent 6f638a0 commit 06087f8
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 44 deletions.
34 changes: 3 additions & 31 deletions gc-couchdb/src/couch_spatial_updater.erl
Expand Up @@ -18,11 +18,8 @@

-export([start_update/3, process_doc/3, finish_update/1]).

% for output (couch_http_spatial, couch_http_spatial_list)
-export([geocouch_to_geojsongeom/1]).

% for polygon search
-export([extract_bbox/2, geojsongeom_to_geocouch/1]).
-export([extract_bbox/2]).

-include("couch_db.hrl").
-include("couch_spatial.hrl").
Expand Down Expand Up @@ -313,7 +310,7 @@ process_result([[{Geo}|Rest]|[Value]]) ->
% The multidimensional case without a geometry
process_result([MultiDim|[Value]]) when is_list(MultiDim) ->
Tuples = process_range(MultiDim),
{Tuples, {nil, Value}};
{Tuples, {<<>>, Value}};
% There old case when only two dimensions were supported
process_result([{Geo}|[Value]]) ->
{Bbox, Geom} = process_geometry(Geo),
Expand Down Expand Up @@ -377,7 +374,7 @@ process_geometry(Geo) ->
catch _:badarg ->
throw({emit_key, <<"The supplied geometry must be valid GeoJSON.">>})
end,
Geom = geojsongeom_to_geocouch(Geo),
{ok, Geom} = wkb_writer:geojson_to_wkb({Geo}),
{Bbox, Geom}.


Expand Down Expand Up @@ -415,28 +412,3 @@ bbox([Coords|Rest], Range) ->
{erlang:min(Coord, Min), erlang:max(Coord, Max)}
end, Coords, Range),
bbox(Rest, Range2).


% @doc Transforms a GeoJSON geometry (as Erlang terms), to an internal
% structure
geojsongeom_to_geocouch(Geom) ->
Type = proplists:get_value(<<"type">>, Geom),
Coords = case Type of
<<"GeometryCollection">> ->
Geometries = proplists:get_value(<<"geometries">>, Geom),
[geojsongeom_to_geocouch(G) || {G} <- Geometries];
_ ->
proplists:get_value(<<"coordinates">>, Geom)
end,
{binary_to_atom(Type, utf8), Coords}.

% @doc Transforms internal structure to a GeoJSON geometry (as Erlang terms)
geocouch_to_geojsongeom({Type, Coords}) ->
Coords2 = case Type of
'GeometryCollection' ->
Geoms = [geocouch_to_geojsongeom(C) || C <- Coords],
{<<"geometries">>, Geoms};
_ ->
{<<"coordinates">>, Coords}
end,
{[{<<"type">>, Type}, Coords2]}.
16 changes: 3 additions & 13 deletions gc-couchdb/src/couch_spatial_util.erl
Expand Up @@ -342,22 +342,12 @@ expand_dups([KV | Rest], Acc) ->


row_to_ejson({Mbb, DocId, Geom, Value}) ->
% If there's no geometry in the output, there's no bbox to add
GeomData = case Geom of
nil ->
<<>> ->
[];
_ ->
% XXX NOTE vmx 2012-11-28: Currently the first two dimensions are
% expected to be the bounding box of the geometry
% XXX vmx 2012-11-28: I'm not sure if a bounding box should be
% emitted at all. It's duplicated information you can get from
% the key yourself.
{[{W, E}, {S, N}], _} = lists:split(2, Mbb),
[
{<<"bbox">>, [W, S, E, N]},
{<<"geometry">>,
couch_spatial_updater:geocouch_to_geojsongeom(Geom)}
]
{ok, JsonGeom} = wkb_reader:wkb_to_geojson(Geom),
[{<<"geometry">>, JsonGeom}]
end,
{[
{<<"id">>, DocId},
Expand Down

0 comments on commit 06087f8

Please sign in to comment.