1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use std::slice;
extern crate libc;
use self::libc::{c_void, c_double, size_t};
use super::geo::{Point, Polygon, LineString};
use super::polylabel;
use super::num::{Float};
#[repr(C)]
pub struct WrapperArray {
pub data: *const Array,
pub len: size_t,
}
#[repr(C)]
pub struct Array {
pub data: *const c_void,
pub len: size_t,
}
#[repr(C)]
pub struct Position {
pub x_pos: c_double,
pub y_pos: c_double,
}
impl<T> From<Point<T>> for Position
where T: Float
{
fn from(point: Point<T>) -> Position {
Position {
x_pos: point.x().to_f64().unwrap() as c_double,
y_pos: point.y().to_f64().unwrap() as c_double,
}
}
}
fn reconstitute(arr: &Array) -> Vec<[f64; 2]> {
unsafe { slice::from_raw_parts(arr.data as *mut [f64; 2], arr.len).to_vec() }
}
fn reconstitute2(arr: WrapperArray) -> Vec<Vec<[f64; 2]>> {
let arrays = unsafe { slice::from_raw_parts(arr.data as *mut Array, arr.len) };
arrays.into_iter().map(|x| reconstitute(x)).collect()
}
#[no_mangle]
pub extern "C" fn polylabel_ffi(outer: Array,
inners: WrapperArray,
tolerance: c_double)
-> Position {
let exterior: Vec<[f64; 2]> =
unsafe { slice::from_raw_parts(outer.data as *mut [c_double; 2], outer.len).to_vec() };
let interior: Vec<Vec<[f64; 2]>> = reconstitute2(inners);
let ls_ext = LineString(exterior.iter().map(|e| Point::new(e[0], e[1])).collect());
let ls_int: Vec<LineString<c_double>> = interior.iter()
.map(|vec| LineString(vec.iter().map(|e| Point::new(e[0], e[1])).collect()))
.collect();
let poly = Polygon(ls_ext, ls_int);
polylabel(&poly, &tolerance).into()
}
#[cfg(test)]
mod tests {
use super::{Array, WrapperArray, reconstitute2};
use super::libc::{c_void, size_t};
use std::mem;
fn gen_array(v: Vec<[f64; 2]>) -> Array {
let array = Array {
data: v.as_ptr() as *const c_void,
len: v.len() as size_t,
};
mem::forget(v);
array
}
fn gen_wrapperarray(v: Vec<Vec<[f64; 2]>>) -> WrapperArray {
let converted: Vec<Array> = v.into_iter().map(|x| gen_array(x)).collect();
let array2 = WrapperArray {
data: converted.as_ptr() as *const Array,
len: converted.len() as size_t,
};
mem::forget(converted);
array2
}
#[test]
fn test_array() {
let i_a = vec![[0.5, 0.5], [1.0, 1.0], [1.5, 0.5]];
let i_b = vec![[0.55, 0.55], [0.8, 0.8], [1.2, 0.55]];
let inners = vec![i_a, i_b];
let array = gen_wrapperarray(inners);
let rec_inners = reconstitute2(array);
assert_eq!(rec_inners[0][2], [1.5, 0.5])
}
}