shape_contour/
contours.rs

1//! grpcontours
2//!
3//! to control publication imported modules
4//!
5//! # Requirements
6//!
7//! - [ shapelib-rs ]( https://crates.io/crates/shapelib-rs )
8//!
9//! - ./shapelib/include/shapefil.h
10//!
11
12#![allow(unused)]
13// #![allow(unused_imports)]
14// #![allow(unused_attributes)]
15#![allow(non_snake_case)]
16#![allow(non_camel_case_types)]
17#![allow(non_upper_case_globals)]
18
19mod cshapefil;
20use cshapefil::*;
21
22use std::error::Error;
23use std::collections::BTreeMap;
24
25pub use shapelib::shape; // {Pt2d, ShpContoursInf};
26
27/// get min max from (Bounds or Contour2(d) Vec (shape::Pt2d or Pt))
28pub fn get_min_max(points: &Vec<shape::Pt2d>) -> Vec<shape::Pt2d> {
29  let mut r: Vec<shape::Pt2d> = (0..2).into_iter().map(|_| {
30    shape::Pt2d{x: points[0].x, y: points[0].y} }).collect();
31  for p in points {
32    if r[0].x > p.x { r[0].x = p.x };
33    if r[0].y > p.y { r[0].y = p.y };
34    if r[1].x < p.x { r[1].x = p.x };
35    if r[1].y < p.y { r[1].y = p.y };
36  }
37  r
38}
39
40/// get min max of contours from (Contours2(d) Vec Vec (shape::Pt2d or Pt))
41pub fn get_mm_of_contours(contours: &shape::Contours2d) -> Vec<shape::Pt2d> {
42  let mut r = Vec::<shape::Pt2d>::with_capacity(2);
43  for (i, contour) in contours.iter().enumerate() {
44    let mut q = get_min_max(&contour);
45    if i == 0 {
46      for p in q { r.push(p); } // move p initialize for r
47    } else {
48      for p in &r { q.push(shape::Pt2d{x: p.x, y: p.y}); } // not use push(*p)
49      for (j, p) in get_min_max(&q).into_iter().enumerate() {
50        r[j] = p; // move p
51      }
52    }
53  }
54  r
55}
56
57/// Pt
58#[derive(Debug)]
59pub struct Pt {
60  /// x
61  pub x: i32,
62  /// y
63  pub y: i32
64}
65
66/// Contour2
67pub type Contour2 = Vec<Pt>;
68
69/// Contours2
70pub type Contours2 = Vec<Contour2>;
71
72/// MapContours
73pub type MapContours = BTreeMap<i32, Contours2>;
74
75/// GrpContoursInf
76#[derive(Debug)]
77pub struct GrpContoursInf {
78  /// scale
79  pub scale: f64,
80  /// offset
81  pub offset: shape::Pt2d,
82  /// mm
83  pub mm: Vec<shape::Pt2d>,
84  /// grp_contours
85  pub grp_contours: Vec<i32>,
86  /// grp_scaled_contours
87  pub grp_scaled_contours: MapContours,
88  /// sci
89  pub sci: shape::ShpContoursInf
90}
91
92/// GrpContoursInf
93impl GrpContoursInf {
94  /// constructor
95  pub fn new(sci: shape::ShpContoursInf) ->
96    Result<GrpContoursInf, Box<dyn Error>> {
97    Ok(GrpContoursInf{
98      scale: 0.0,
99      offset: shape::Pt2d{x: 0.0, y: 0.0},
100      mm: (0..2).into_iter().map(|_| shape::Pt2d{x: 0.0, y: 0.0}).collect(),
101      grp_contours: vec![],
102      grp_scaled_contours: vec![].into_iter().collect(),
103      sci: sci})
104  }
105
106  /// get_grp_contours
107  pub fn get_grp_contours(&mut self, scale: f64, w_pref: i32, w_city: i32,
108    ignore: bool) -> Result<(), Box<dyn Error>> {
109    for si in 0..self.sci.shp.len() as i32 {
110      let flds = &self.sci.rec[&si];
111      let (pref, city) = match shape::get_pref_city(flds[0].as_str()) {
112      Err(e) => { if !ignore { println!("{} at {}\x07", e, si) }; (0, 0) },
113      Ok(r) => r
114      };
115/*
116      if pref != 26 { continue; } // 26 1177-1212
117      if city != 343 { continue; } // 343 1204 etc
118*/
119      if w_pref != 0 && pref != w_pref { continue; }
120      if w_city != 0 && city != w_city { continue; }
121      let shp_k = &self.sci.shp[&si];
122      let mut mmc = get_mm_of_contours(shp_k);
123      if self.grp_contours.len() == 0 {
124        // self.mm = Vec::<shape::Pt2d>::with_capacity(2); // clear self.mm
125        self.mm.clear();
126        for p in mmc { self.mm.push(p); } // move p initialize for self.mm
127      } else {
128        for p in &self.mm { mmc.push(shape::Pt2d{x: p.x, y: p.y}); } // copy *p
129        for (j, p) in get_min_max(&mmc).into_iter().enumerate() {
130          self.mm[j] = p; // move p
131        }
132      }
133      self.grp_contours.push(si);
134    }
135    let range = shape::Pt2d{
136      x: self.mm[1].x - self.mm[0].x, y: self.mm[1].y - self.mm[0].y};
137    self.offset = shape::Pt2d{x: self.mm[0].x, y: self.mm[0].y};
138    let xscale = (self.sci.minmax[1][0] - self.sci.minmax[0][0]) / range.x;
139    let yscale = (self.sci.minmax[1][1] - self.sci.minmax[0][1]) / range.y;
140    self.scale = scale * (if xscale < yscale { xscale } else { yscale });
141/*
142    print!("({:4} {:4}) scale{:7.1}", 1600, 1200, self.scale);
143    println!(" range({:9.4},{:9.4}) offset({:9.4},{:9.4})",
144      range.x * self.scale, range.y * self.scale,
145      self.offset.x * self.scale, self.offset.y * self.scale);
146*/
147/*
148all prefectures range=(maxBound - minBound)(Points)
149(  32   24) scale    1.0 range(  31.0528,  21.5116) offset( 122.9339,  24.0456)
150( 640  480) scale   20.0 range( 621.0552, 430.2325) offset(2458.6783, 480.9123)
151(1280  960) scale   40.0 range(1242.1105, 860.4649) offset(4917.3565, 961.8246)
152(1600 1200) scale   50.0 range(1552.6381,1075.5812) offset(6146.6957,1202.2808)
153shapeId=1204
154(x) scale17907.4 range(1552.6381, 648.8804) offset(2431661.2717,623000.3392)
155*/
156    Ok(())
157  }
158
159  /// get_scaled_contours
160  pub fn get_scaled_contours(&mut self, si: i32, ofs: &shape::Pt2d) ->
161    Result<i32, Box<dyn Error>> {
162    let contours = self.grp_scaled_contours.entry(si).or_insert_with(|| {
163      let mut cts = Vec::<Contour2>::with_capacity(self.sci.shp[&si].len());
164      for pts in &self.sci.shp[&si] {
165        let mut contour = Vec::<Pt>::with_capacity(pts.len());
166        for p in pts {
167          contour.push(Pt{ // add offset before scale
168            x: ((ofs.x + p.x) * self.scale) as i32,
169            y: ((ofs.y + p.y) * self.scale) as i32});
170        }
171        cts.push(contour);
172      }
173      cts
174    });
175    Ok(contours.len() as i32)
176  }
177
178  /// whole_scaled
179  pub fn whole_scaled(&mut self) -> Result<i32, Box<dyn Error>> {
180    let mut total = 0i32;
181    let offset = shape::Pt2d{x: 0.0, y: 0.0};
182    for i in 0..self.grp_contours.len() { // borrow '&si in &self.grp_contours'
183      total += self.get_scaled_contours(self.grp_contours[i], &offset)?;
184    }
185    Ok(total)
186  }
187}