rozap / exshape Goto Github PK
View Code? Open in Web Editor NEWshapefiles
License: MIT License
shapefiles
License: MIT License
Example file: Zillow NY neighborhoods boundaries - https://www.zillowstatic.com/static/shp/ZillowNeighborhoods-NY.zip
"Howard Beach"
pry(9)> parts
[0, 247]
pry(10)> points
[[%Exshape.Shp.Point{x: -73.85608525799972, y: 40.65037135900031},
%Exshape.Shp.Point{x: -73.85674782907176, y: 40.65132123254244},
%Exshape.Shp.Point{x: -73.85736016361085, y: 40.65206964142362},
%Exshape.Shp.Point{x: -73.85822196777701, y: 40.65250054350653},
%Exshape.Shp.Point{x: -73.85867554891695, y: 40.65297680370385}],
[%Exshape.Shp.Point{x: -73.85892501854421, y: 40.65345306390082},
%Exshape.Shp.Point{x: -73.85915180911427, y: 40.653997361268885},
%Exshape.Shp.Point{x: -73.8594919949693, y: 40.65442826335197},
%Exshape.Shp.Point{x: -73.85962806931114, y: 40.6547684492071},
%Exshape.Shp.Point{x: -73.86037647819232, y: 40.65535810468923},
%Exshape.Shp.Point{x: -73.86073934310458, y: 40.655584895259196},
%Exshape.Shp.Point{x: -73.86155578915668, y: 40.65581168582934},
%Exshape.Shp.Point{x: -73.86216812369584, y: 40.65619722979836},
%Exshape.Shp.Point{x: -73.86230419803786, y: 40.65669616905236},
%Exshape.Shp.Point{x: -73.86239491426589, y: 40.65719510830654},
%Exshape.Shp.Point{x: -73.86268633099984, y: 40.65760322400049},
%Exshape.Shp.Point{x: -73.86317099999962, y: 40.65827700000064},
%Exshape.Shp.Point{x: -73.86150799999977, y: 40.659050000000114},
%Exshape.Shp.Point{x: -73.86121299999962, y: 40.65915400000019},
%Exshape.Shp.Point{x: -73.86075274639505, y: 40.659290117556},
%Exshape.Shp.Point{x: -73.86074299999972, y: 40.6592930000005},
%Exshape.Shp.Point{x: -73.86027299999982, y: 40.65943200000046},
....
I am really think first part should be 247 points length and not 5. It's just messing polygons (it's not closed, look at first and last points).
Cloning the latest repository and running tests with Elixir 1.5.2 produces the following error for the Exshape.from_zip/1
function.
** (ArgumentError) all arguments for System.cmd/3 must be binaries
(elixir) lib/system.ex:613: System.cmd/3
(exshape) lib/exshape.ex:37: Exshape.unzip/3
(exshape) lib/exshape.ex:72: Exshape.from_zip/2
When parsing the attached file:
seattle_basketball_points.zip
iex(5)> x = Exshape.from_zip(zip)
{:error,
{:EXIT,
{{:badmatch,
{{:file_descriptor, :prim_file, {#Port<0.5074>, 27}},
{:file_descriptor, :prim_file, {#Port<0.5072>, 26}}}},
[{:zip, :get_z_data, 8, [file: 'zip.erl', line: 1504]},
{:zip, :get_z_file, 9, [file: 'zip.erl', line: 1451]},
{:zip, :get_z_files, 5, [file: 'zip.erl', line: 1401]},
{:zip, :do_unzip, 2, [file: 'zip.erl', line: 372]},
{:zip, :unzip, 2, [file: 'zip.erl', line: 358]},
{Exshape, :from_zip, 2, [file: 'lib/exshape.ex', line: 48]},
{:erl_eval, :do_apply, 6, [file: 'erl_eval.erl', line: 670]},
{:erl_eval, :expr, 5, [file: 'erl_eval.erl', line: 438]}]}}}
Repro:
[{_name, _proj, shapes}] = Exshape.from_zip(filepath)
shape_list = Enum.into(shapes, [])
length(shape_list)
Returns 1, expected 75 (74 features and 1 header)
Neighborhoods.zip
Repro:
iex(3)> [{name, proj, stream}] = Exshape.from_zip(zip)
iex(4)> [header | features] = Enum.into(stream, [])
** (ArgumentError) argument error
:erlang.binary_to_integer(" ")
(exshape) lib/exshape/dbf.ex:52: Exshape.Dbf.munge/2
(elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
(elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
(exshape) lib/exshape/dbf.ex:25: Exshape.Dbf.emit/2
(exshape) lib/exshape/dbf.ex:107: Exshape.Dbf.next_column/1
(exshape) lib/exshape/dbf.ex:202: Exshape.Dbf.do_read/2
(exshape) lib/exshape/dbf.ex:226: anonymous fn/2 in Exshape.Dbf.read/1
Hi there ๐
This lib is just what I was looking for. Thanks for that! ๐
I believe UUID could be removed in favor of using built-in features to provide a random path name for the tmp dir used for extraction of zip files.
This would remove some warnings as showed below.
Erlang/OTP 24 [erts-12.1.5] [source] [64-bit] [smp:32:32] [ds:32:32:10] [async-threads:1] [jit]
Interactive Elixir (1.13.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Mix.install([:exshape])
Resolving Hex dependencies...
Dependency resolution completed:
New:
elixir_uuid 1.2.1
exshape 2.2.7
* Getting exshape (Hex package)
* Getting elixir_uuid (Hex package)
==> elixir_uuid
Compiling 1 file (.ex)
warning: :crypto.hash/2 defined in application :crypto is used by the current application but the current application does not depend on :crypto. To fix this, you must do one of:
1. If :crypto is part of Erlang/Elixir, you must include it under :extra_applications inside "def application" in your mix.exs
2. If :crypto is a dependency, make sure it is listed under "def deps" in your mix.exs
3. In case you don't want to add a requirement to :crypto, you may optionally skip this warning by adding [xref: [exclude: [:crypto]]] to your "def project" in mix.exs
Invalid call found at 2 locations:
lib/uuid.ex:589: UUID.namebased_uuid/2
lib/uuid.ex:593: UUID.namebased_uuid/2
warning: :crypto.strong_rand_bytes/1 defined in application :crypto is used by the current application but the current application does not depend on :crypto. To fix this, you must do one of:
1. If :crypto is part of Erlang/Elixir, you must include it under :extra_applications inside "def application" in your mix.exs
2. If :crypto is a dependency, make sure it is listed under "def deps" in your mix.exs
3. In case you don't want to add a requirement to :crypto, you may optionally skip this warning by adding [xref: [exclude: [:crypto]]] to your "def project" in mix.exs
Invalid call found at 3 locations:
lib/uuid.ex:383: UUID.uuid4/1
lib/uuid.ex:560: UUID.uuid1_clockseq/0
lib/uuid.ex:583: UUID.uuid1_node/1
Generated elixir_uuid app
==> exshape
Compiling 4 files (.ex)
Generated exshape app
What do you think? I could send a PR if you agree :)
Hello @rozap,
I have just downloaded your dbf parser and I was able to parse needed files, but I have one question.
Result:
%Exshape.Dbf.Header{
columns: [
%Exshape.Dbf.Column{
field_length: 1,
field_type: :character,
name: "EST_SYSTEM"
},
%Exshape.Dbf.Column{
field_length: 10,
field_type: :character,
name: "SW_VERSION"
},
%Exshape.Dbf.Column{
field_length: 12,
field_type: :character,
name: "DB_VERSION"
},
%Exshape.Dbf.Column{field_length: 8, field_type: :date, name: "DB_DATE"},
%Exshape.Dbf.Column{
field_length: 8,
field_type: :character,
name: "UNQFILE_ID"
},
%Exshape.Dbf.Column{field_length: 8, field_type: :character, name: "RO_ID"},
%Exshape.Dbf.Column{
field_length: 38,
field_type: :character,
name: "ESTFILE_ID"
},
%Exshape.Dbf.Column{
field_length: 3,
field_type: :character,
name: "SUPP_NO"
},
%Exshape.Dbf.Column{
field_length: 3,
field_type: :character,
name: "EST_CTRY"
},
%Exshape.Dbf.Column{
field_length: 80,
field_type: :character,
name: "TOP_SECRET"
},
%Exshape.Dbf.Column{
field_length: 9,
field_type: :character,
name: "H_TRANS_ID"
},
%Exshape.Dbf.Column{
field_length: 9,
field_type: :character,
name: "H_CTRL_NO"
},
%Exshape.Dbf.Column{
field_length: 1,
field_type: :character,
name: "TRANS_TYPE"
},
%Exshape.Dbf.Column{field_length: 1, field_type: :boolean, name: "STATUS"},
%Exshape.Dbf.Column{field_length: 8, field_type: :date, name: "CREATE_DT"},
%Exshape.Dbf.Column{
field_length: 6,
field_type: :character,
name: "CREATE_TM"
},
%Exshape.Dbf.Column{field_length: 8, field_type: :date, name: "TRANSMT_DT"},
%Exshape.Dbf.Column{
field_length: 6,
field_type: :character,
name: "TRANSMT_TM"
},
%Exshape.Dbf.Column{
field_length: 1,
field_type: :boolean,
name: "INCL_ADMIN"
},
%Exshape.Dbf.Column{field_length: 1, field_type: :boolean, name: "INCL_VEH"},
%Exshape.Dbf.Column{field_length: 1, field_type: :boolean, name: "INCL_EST"},
%Exshape.Dbf.Column{
field_length: 1,
field_type: :boolean,
name: "INCL_PROFL"
},
%Exshape.Dbf.Column{
field_length: 1,
field_type: :boolean,
name: "INCL_TOTAL"
},
%Exshape.Dbf.Column{
field_length: 1,
field_type: :boolean,
name: "INCL_VENDR"
},
%Exshape.Dbf.Column{
field_length: 5,
field_type: :character,
name: "EMS_VER"
}
],
header_byte_count: 833,
last_updated: {2018, 9, 20},
record_byte_count: 231,
record_count: 1
}
["M", "UM7.1 ", "JUL_18_V ", ~D[2018-07-23], "6346204 ", "0 ",
"6346204 ", "0 ", "USA",
";0000000;0;0000000;0;0000000; ",
" ", " ", "E", false, ~D[2018-09-20], "060731", ~D[2018-09-20],
"060831", true, true, true, true, true, false, "2.0 "]
Is there a way to map columns with corresponding values, for example:
%Exshape.Dbf.Column{
field_length: 1,
field_type: :character,
name: "EST_SYSTEM",
value: "M"
},
I'm in a process of learning Elixir so sorry if it's a dumb question.
File that was used: https://gofile.io/?c=mLj4Ar
This file had null (not-initialized) values for boolean fields, and Exshape crashes when trying to parse it, due to not matching any of the cases here:
Line 63 in 28e9805
Repro steps, where fp
is the path to the attached file
iex(2)> [{name, proj, stream}] = Exshape.from_zip(fp)
[{"geo_export_5b92efa6-5cca-4f5c-8290-87f73cdace34",
"GEOGCS[\"WGS84(DD)\", DATUM[\"WGS84\", SPHEROID[\"WGS84\", 6378137.0, 298.257223563]], PRIMEM[\"Greenwich\", 0.0], UNIT[\"degree\", 0.017453292519943295], AXIS[\"Geodetic longitude\", EAST], AXIS[\"Geodetic latitude\", NORTH]]",
#Function<66.87278901/2 in Stream.zip/2>}]
iex(3)> f_list = Enum.into(stream, [])
** (FunctionClauseError) no function clause matching in Exshape.Dbf.munge/2
(exshape) lib/exshape/dbf.ex:39: Exshape.Dbf.munge(:boolean, "?")
(elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
(elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
(exshape) lib/exshape/dbf.ex:25: Exshape.Dbf.emit/2
(exshape) lib/exshape/dbf.ex:99: Exshape.Dbf.next_column/1
(exshape) lib/exshape/dbf.ex:194: Exshape.Dbf.do_read/2
(exshape) lib/exshape/dbf.ex:218: anonymous fn/2 in Exshape.Dbf.read/1
(elixir) lib/stream.ex:740: Stream.do_transform/8
File attached.
Many Typed Geo Dataset.zip
Using the following shapefile from the Census Bureau for one of the state house districts(I forget which), I've found no way yet of having dbf data load in.
Forgive me for how short this is- my girlfriend and I are just heading out the door. Soon as I get another moment to look I can answer questions about how I found this, etc.
Speed_Enforcement_Locations.zip
The above file, when ingressed through DSMP, causes character encoding problems that makes both DSMAPI and DSMUI crash. A string with an invalid character is returned as a binary (eg):
%Dsmapi.SoQL.SoQLText{value: <<72, 101, 109, 105, 110, 103, 119, 97,
121, 32, 82, 100, ...>>}}
Which is then handed off to Poison.encode
, which can't handle binaries and so blows up. Because it blows up, it causes dsmapi to send no response to the client, which makes the client blow up as well.
Suggested fix for exshape.ex
lines 76 - 78.
prj = projection(Enum.find(components, fn c -> String.downcase(Path.extname(c)) == ".prj" end))
shp = Enum.find(components, fn c -> String.downcase(Path.extname(c)) == ".shp" end)
dbf = Enum.find(components, fn c -> String.downcase(Path.extname(c)) == ".dbf" end)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.