geos/wkt_writer.rs
1use crate::context_handle::{with_context, PtrWrap};
2use crate::error::Error;
3use crate::functions::*;
4use crate::{AsRaw, AsRawMut, ContextHandle, GResult, Geom, OutputDimension};
5use geos_sys::*;
6use std::convert::TryFrom;
7
8/// The `WKTWriter` type is used to generate `WKT` formatted output from [`Geometry`](crate::Geometry).
9///
10/// # Example
11///
12/// ```
13/// use geos::{Geometry, WKTWriter};
14///
15/// let point_geom = Geometry::new_from_wkt("POINT (2.5 2.5)").expect("Invalid geometry");
16/// let mut writer = WKTWriter::new().expect("Failed to create WKTWriter");
17///
18/// assert_eq!(writer.write(&point_geom).unwrap(), "POINT (2.5000000000000000 2.5000000000000000)");
19/// ```
20pub struct WKTWriter {
21 ptr: PtrWrap<*mut GEOSWKTWriter>,
22}
23
24impl WKTWriter {
25 /// Creates a new `WKTWriter` instance.
26 ///
27 /// # Example
28 ///
29 /// ```
30 /// use geos::{Geometry, WKTWriter};
31 ///
32 /// let point_geom = Geometry::new_from_wkt("POINT (2.5 2.5)").expect("Invalid geometry");
33 /// let mut writer = WKTWriter::new().expect("Failed to create WKTWriter");
34 ///
35 /// assert_eq!(writer.write(&point_geom).unwrap(), "POINT (2.5000000000000000 2.5000000000000000)");
36 /// ```
37 pub fn new() -> GResult<WKTWriter> {
38 with_context(|ctx| unsafe {
39 let ptr = GEOSWKTWriter_create_r(ctx.as_raw());
40 WKTWriter::new_from_raw(ptr, ctx, "new_with_context")
41 })
42 }
43
44 pub(crate) unsafe fn new_from_raw(
45 ptr: *mut GEOSWKTWriter,
46 ctx: &ContextHandle,
47 caller: &str,
48 ) -> GResult<WKTWriter> {
49 if ptr.is_null() {
50 let extra = if let Some(x) = ctx.get_last_error() {
51 format!("\nLast error: {x}")
52 } else {
53 String::new()
54 };
55 return Err(Error::NoConstructionFromNullPtr(format!(
56 "WKTWriter::{caller}{extra}",
57 )));
58 }
59 Ok(WKTWriter { ptr: PtrWrap(ptr) })
60 }
61
62 /// Writes out the given `geometry` as WKT format.
63 ///
64 /// # Example
65 ///
66 /// ```
67 /// use geos::{Geometry, WKTWriter};
68 ///
69 /// let point_geom = Geometry::new_from_wkt("POINT (2.5 2.5)").expect("Invalid geometry");
70 /// let mut writer = WKTWriter::new().expect("Failed to create WKTWriter");
71 ///
72 /// assert_eq!(writer.write(&point_geom).unwrap(), "POINT (2.5000000000000000 2.5000000000000000)");
73 /// ```
74 pub fn write<G: Geom>(&mut self, geometry: &G) -> GResult<String> {
75 with_context(|ctx| unsafe {
76 let ptr = GEOSWKTWriter_write_r(ctx.as_raw(), self.as_raw_mut(), geometry.as_raw());
77 managed_string(ptr, ctx, "WKTWriter::write")
78 })
79 }
80
81 /// Sets the `precision` to be used when calling [`WKTWriter::write`]. Often, what users
82 /// actually want is the [`WKTWriter::set_trim`] method instead.
83 ///
84 /// # Example
85 ///
86 /// ```
87 /// use geos::{Geometry, WKTWriter};
88 ///
89 /// let point_geom = Geometry::new_from_wkt("POINT (2.5 2.5)").expect("Invalid geometry");
90 /// let mut writer = WKTWriter::new().expect("Failed to create WKTWriter");
91 ///
92 /// writer.set_rounding_precision(2);
93 /// assert_eq!(writer.write(&point_geom).unwrap(), "POINT (2.50 2.50)");
94 ///
95 /// writer.set_rounding_precision(4);
96 /// assert_eq!(writer.write(&point_geom).unwrap(), "POINT (2.5000 2.5000)");
97 /// ```
98 pub fn set_rounding_precision(&mut self, precision: u32) {
99 with_context(|ctx| unsafe {
100 GEOSWKTWriter_setRoundingPrecision_r(ctx.as_raw(), self.as_raw_mut(), precision as _)
101 })
102 }
103
104 /// Sets the number of dimensions to be used when calling [`WKTWriter::write`]. By default, it
105 /// is 2.
106 ///
107 /// # Example
108 ///
109 /// ```
110 /// use geos::{Geometry, OutputDimension, WKTWriter};
111 ///
112 /// let point_geom = Geometry::new_from_wkt("POINT (1.1 2.2 3.3)").expect("Invalid geometry");
113 /// let mut writer = WKTWriter::new().expect("Failed to create WKTWriter");
114 /// writer.set_trim(true);
115 ///
116 /// assert_eq!(writer.write(&point_geom).unwrap(), "POINT (1.1 2.2)");
117 ///
118 /// writer.set_output_dimension(OutputDimension::ThreeD);
119 /// assert_eq!(writer.write(&point_geom).unwrap(), "POINT Z (1.1 2.2 3.3)");
120 /// ```
121 pub fn set_output_dimension(&mut self, dimension: OutputDimension) {
122 with_context(|ctx| unsafe {
123 GEOSWKTWriter_setOutputDimension_r(ctx.as_raw(), self.as_raw_mut(), dimension.into())
124 })
125 }
126
127 /// Returns the number of dimensions to be used when calling [`WKTWriter::write`]. By default,
128 /// it is 2.
129 ///
130 /// # Example
131 ///
132 /// ```
133 /// use geos::{OutputDimension, WKTWriter};
134 ///
135 /// let mut writer = WKTWriter::new().expect("Failed to create WKTWriter");
136 ///
137 /// assert_eq!(writer.get_out_dimension(), Ok(OutputDimension::TwoD));
138 /// writer.set_output_dimension(OutputDimension::ThreeD);
139 /// assert_eq!(writer.get_out_dimension(), Ok(OutputDimension::ThreeD));
140 /// ```
141 pub fn get_out_dimension(&self) -> GResult<OutputDimension> {
142 with_context(|ctx| unsafe {
143 let out = GEOSWKTWriter_getOutputDimension_r(ctx.as_raw(), self.as_raw_mut_override());
144 OutputDimension::try_from(out).map_err(|e| Error::GenericError(e.to_owned()))
145 })
146 }
147
148 /// Enables/disables trimming of unnecessary decimals.
149 ///
150 /// # Example
151 ///
152 /// ```
153 /// use geos::{Geometry, WKTWriter};
154 ///
155 /// let point_geom = Geometry::new_from_wkt("POINT (2.5 2.5)").expect("Invalid geometry");
156 /// let mut writer = WKTWriter::new().expect("Failed to create WKTWriter");
157 ///
158 /// assert_eq!(writer.write(&point_geom).unwrap(), "POINT (2.5000000000000000 2.5000000000000000)");
159 ///
160 /// writer.set_trim(true);
161 /// assert_eq!(writer.write(&point_geom).unwrap(), "POINT (2.5 2.5)");
162 /// ```
163 pub fn set_trim(&mut self, trim: bool) {
164 with_context(|ctx| unsafe {
165 GEOSWKTWriter_setTrim_r(ctx.as_raw(), self.as_raw_mut(), trim as _)
166 })
167 }
168
169 /// Enables/disables old 3D/4D WKT style generation.
170 ///
171 /// # Example
172 ///
173 /// ```
174 /// use geos::{Geometry, OutputDimension, WKTWriter};
175 ///
176 /// let point_geom = Geometry::new_from_wkt("POINT (2.5 2.5 2.5)").expect("Invalid geometry");
177 /// let mut writer = WKTWriter::new().expect("Failed to create WKTWriter");
178 ///
179 /// writer.set_output_dimension(OutputDimension::ThreeD);
180 /// writer.set_trim(true);
181 ///
182 /// assert_eq!(writer.write(&point_geom).unwrap(), "POINT Z (2.5 2.5 2.5)");
183 ///
184 /// writer.set_old_3D(true);
185 /// assert_eq!(writer.write(&point_geom).unwrap(), "POINT (2.5 2.5 2.5)");
186 /// ```
187 #[allow(non_snake_case)]
188 pub fn set_old_3D(&mut self, use_old_3D: bool) {
189 with_context(|ctx| unsafe {
190 GEOSWKTWriter_setOld3D_r(ctx.as_raw(), self.as_raw_mut(), use_old_3D as _)
191 })
192 }
193}
194
195unsafe impl Send for WKTWriter {}
196unsafe impl Sync for WKTWriter {}
197
198impl Drop for WKTWriter {
199 fn drop(&mut self) {
200 with_context(|ctx| unsafe { GEOSWKTWriter_destroy_r(ctx.as_raw(), self.as_raw_mut()) });
201 }
202}
203
204impl AsRaw for WKTWriter {
205 type RawType = GEOSWKTWriter;
206
207 fn as_raw(&self) -> *const Self::RawType {
208 *self.ptr
209 }
210}
211
212impl AsRawMut for WKTWriter {
213 type RawType = GEOSWKTWriter;
214
215 unsafe fn as_raw_mut_override(&self) -> *mut Self::RawType {
216 *self.ptr
217 }
218}