1#![allow(unused)]
16#![allow(non_snake_case)]
19#![allow(non_camel_case_types)]
20#![allow(non_upper_case_globals)]
21
22mod cshapefil;
23use cshapefil::*;
24
25mod cppbridge;
26pub use cppbridge::{ShapeC, c};
27
28use std::error::Error;
29use std::collections::BTreeMap;
30use asciiz::u8z;
31use encoding_rs;
32
33impl Drop for ShapeC {
35 fn drop(&mut self) {
37 unsafe { self.dispose(); }
38 }
39}
40
41pub fn get_pref_city(s: &str) -> Result<(i32, i32), Box<dyn Error>> {
43 if s.len() < 5 { return Err(format!("expect PPNNN but '{}'", s).into()); }
44 let pref = i32::from_str_radix(&s[0..2], 10)?; let city = i32::from_str_radix(&s[2..5], 10)?; Ok((pref, city))
47}
48
49#[macro_export]
51macro_rules! ptr_array {
52 ($a: expr, $i: expr) => {
53 std::slice::from_raw_parts($a, $i as usize + 1)[$i as usize]
54 };
55}
56pub use ptr_array;
57
58pub fn u8zs(b: Vec<u8>) -> Result<String, Box<dyn Error>> {
60 let l = b.iter().position(|&c| c == 0).ok_or("not terminated by null")?;
61 Ok(String::from_utf8(b[0..l].to_vec())?)
62}
63
64pub fn i8zs(b: *const i8, enc: &str) -> Result<String, Box<dyn Error>> {
66unsafe {
67 let mut l: usize = 0;
68 loop {
69 let c = std::slice::from_raw_parts((b as usize + l) as *const i8, 1);
70 if c[0] == 0 as i8 { break; }
71 l += 1;
72 }
73 let s = std::slice::from_raw_parts(b as *const u8, l);
74 match enc {
75 "cp932" => {
76 let (cow, enc_used, had_errors) = encoding_rs::SHIFT_JIS.decode(s);
77 Ok(cow.into_owned()) },
79 _ => Ok(String::from_utf8(s.to_vec())?)
80 }
81}
82}
83
84pub type V4d = [f64; 4];
86
87#[derive(Debug)]
89pub struct Pt2d {
90 pub x: f64,
92 pub y: f64
94}
95
96pub type Bounds4d = Vec<V4d>;
98
99pub type Contour2d = Vec<Pt2d>;
101
102pub type Contours2d = Vec<Contour2d>;
104
105pub type ShpContours = BTreeMap<i32, Contours2d>;
107
108pub type StrFields = Vec<String>;
110
111pub type RecFields = BTreeMap<i32, StrFields>;
113
114#[derive(Debug)]
116pub struct ShpContoursInf {
117 pub shp: ShpContours,
119 pub rec: RecFields,
121 pub minmax: Bounds4d
123}
124
125impl ShpContoursInf {
127 pub fn new() -> Result<ShpContoursInf, Box<dyn Error>> {
129 Ok(ShpContoursInf{
130 shp: vec![].into_iter().collect(),
131 rec: vec![].into_iter().collect(),
132 minmax: vec![[0.0; 4], [0.0; 4]]})
133 }
134}
135
136#[derive(Debug)]
138pub struct ShapeF {
139 pub fname: String,
141 pub enc: String,
143 pub h_shp: *mut SHPInfo,
145 pub h_dbf: *mut DBFInfo,
147 pub valid: bool
149}
150
151impl ShapeF {
153 pub fn new(fname: &str, enc: &str) -> Result<ShapeF, Box<dyn Error>> {
155 let mut shp = ShapeF{fname: fname.to_string(), enc: enc.to_string(),
156 h_shp: 0 as *mut SHPInfo, h_dbf: 0 as *mut DBFInfo, valid: false};
157 let fnz = u8z::U8zBuf::from_u8array(fname.as_bytes());
158 let opt = u8z::U8zBuf::from_u8array(b"rb");
159unsafe {
160 shp.h_shp = SHPOpen(fnz.as_i8p(), opt.as_i8p());
161 shp.h_dbf = DBFOpen(fnz.as_i8p(), opt.as_i8p());
162}
163 if shp.h_shp == 0 as *mut SHPInfo || shp.h_dbf == 0 as *mut DBFInfo {
164 return Err("ShapeF is not initialized".into());
165 }
166 shp.valid = true;
167 Ok(shp)
168 }
169
170 pub fn dispose(&mut self) {
172 if self.h_dbf != 0 as *mut DBFInfo {
173unsafe {
174 DBFClose(self.h_dbf);
175}
176 self.h_dbf = 0 as *mut DBFInfo;
177 }
178 if self.h_shp != 0 as *mut SHPInfo {
179unsafe {
180 SHPClose(self.h_shp);
181}
182 self.h_shp = 0 as *mut SHPInfo;
183 }
184 self.valid = false;
185 }
186
187 pub fn disp_record_inf(&self) -> Result<(), Box<dyn Error>> {
189 println!("SHP: {:?}, DBF: {:?}", self.h_shp, self.h_dbf);
190 if !self.valid { return Err("ShapeF is not valid".into()); }
191unsafe {
192 let records = DBFGetRecordCount(self.h_dbf);
193 let fields = DBFGetFieldCount(self.h_dbf);
194 println!("DBF: records: {}, fields: {}", records, fields);
195 for fld in 0..fields {
196 let mut name = vec![0u8; 12];
197 let mut fwd = (0i32, 0i32); let ft = DBFGetFieldInfo(self.h_dbf, fld,
199 &mut name[0] as *mut u8 as *mut i8, &mut fwd.0, &mut fwd.1);
200 println!(" fld: {} {:?} [{}] {} {}", fld, ft, u8zs(name)?, fwd.0, fwd.1);
201 }
202}
203 Ok(())
204 }
205
206 pub fn get_shp_contours(&self, ignore: bool) ->
208 Result<ShpContoursInf, Box<dyn Error>> {
209 if !self.valid { return Err("ShapeF is not valid".into()); }
210 let mut sci = ShpContoursInf::new()?;
211 let mut entities = 0i32;
212 let mut shape_type = 0i32;
213unsafe {
214 SHPGetInfo(self.h_shp, &mut entities, &mut shape_type,
215 &mut sci.minmax[0][0], &mut sci.minmax[1][0]);
216}
217for i in 0..entities {
225unsafe {
226 let p_shape = SHPReadObject(self.h_shp, i);
227 if p_shape == 0 as *mut tagSHPObject {
228 println!("error ReadObject at {}", i);
229 continue;
230 }
231 let shape = *p_shape;
232 if shape.nSHPType != SHPT_POLYGON as i32 {
233 println!("{} not POLYGON at {}\x07", shape.nSHPType, i);
234 }
235 let id: i32 = shape.nShapeId;
238 let parts: i32 = shape.nParts;
239 let vertices: i32 = shape.nVertices;
240if parts == 0 { println!("parts==0 at {}\x07", i); }
242
243 let fields = DBFGetFieldCount(self.h_dbf);
244 let p = DBFIsRecordDeleted(self.h_dbf, id); if p != 0 {
246 println!("no record DBF[{}]\x07", id);
247 } else {
248 let mut flds = Vec::<String>::with_capacity(fields as usize);
253 for j in 0..fields {
254 let p_i8zs = DBFReadStringAttribute(self.h_dbf, id, j);
255 flds.push(i8zs(p_i8zs, self.enc.as_str())?);
256}
258 let (pref, city) = match get_pref_city(flds[0].as_str()) {
259 Err(e) => { if !ignore { println!("{} at {}\x07", e, i) }; (0, 0) },
260 Ok(r) => r
261 };
262sci.rec.insert(id, flds); }
274 let mut contours = Vec::<Contour2d>::with_capacity(parts as usize);
275 for n in 0..parts {
276let typ: i32 = ptr_array!(shape.panPartType, n);
278 let vi_s: usize = ptr_array!(shape.panPartStart, n) as usize; let vi_e: usize = if n == parts - 1 { vertices }
280 else { ptr_array!(shape.panPartStart, n + 1) } as usize; let mut contour = Vec::<Pt2d>::with_capacity(vi_e - vi_s); for vi in vi_s..vi_e {
283 let x: f64 = ptr_array!(shape.padfX, vi);
284 let y: f64 = ptr_array!(shape.padfY, vi);
285 let z: f64 = ptr_array!(shape.padfZ, vi);
286 let m: f64 = ptr_array!(shape.padfM, vi); contour.push(Pt2d{x: x, y: y});
289 }
290 contours.push(contour);
291}
293 sci.shp.insert(id, contours); SHPDestroyObject(p_shape); }
296 }
297 Ok(sci)
299 }
300}
301
302impl Drop for ShapeF {
304 fn drop(&mut self) {
306 self.dispose();
307 }
308}