nanonis_rs/client/marks.rs
1use super::NanonisClient;
2use crate::error::NanonisError;
3use crate::types::NanonisValue;
4
5/// Point mark information.
6#[derive(Debug, Clone)]
7pub struct PointMark {
8 /// X coordinate (meters)
9 pub x_m: f32,
10 /// Y coordinate (meters)
11 pub y_m: f32,
12 /// Text label
13 pub text: String,
14 /// RGB color
15 pub color: u32,
16 /// Visible flag
17 pub visible: bool,
18}
19
20/// Line mark information.
21#[derive(Debug, Clone)]
22pub struct LineMark {
23 /// Start X coordinate (meters)
24 pub start_x_m: f32,
25 /// Start Y coordinate (meters)
26 pub start_y_m: f32,
27 /// End X coordinate (meters)
28 pub end_x_m: f32,
29 /// End Y coordinate (meters)
30 pub end_y_m: f32,
31 /// RGB color
32 pub color: u32,
33 /// Visible flag
34 pub visible: bool,
35}
36
37impl NanonisClient {
38 /// Draw text at a specified point in the scan frame.
39 ///
40 /// # Arguments
41 /// * `x_m` - X coordinate in meters
42 /// * `y_m` - Y coordinate in meters
43 /// * `text` - Text to draw
44 /// * `color` - RGB color value
45 ///
46 /// # Errors
47 /// Returns `NanonisError` if communication fails.
48 ///
49 /// # Examples
50 /// ```no_run
51 /// use nanonis_rs::NanonisClient;
52 ///
53 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
54 /// // Draw red "X" at position (1nm, 2nm)
55 /// client.marks_point_draw(1e-9, 2e-9, "X", 0xFF0000)?;
56 /// # Ok::<(), Box<dyn std::error::Error>>(())
57 /// ```
58 pub fn marks_point_draw(
59 &mut self,
60 x_m: f32,
61 y_m: f32,
62 text: &str,
63 color: u32,
64 ) -> Result<(), NanonisError> {
65 self.quick_send(
66 "Marks.PointDraw",
67 vec![
68 NanonisValue::F32(x_m),
69 NanonisValue::F32(y_m),
70 NanonisValue::String(text.to_string()),
71 NanonisValue::U32(color),
72 ],
73 vec!["f", "f", "+*c", "I"],
74 vec![],
75 )?;
76 Ok(())
77 }
78
79 /// Draw text at multiple points in the scan frame.
80 ///
81 /// # Arguments
82 /// * `x_coords_m` - X coordinates in meters
83 /// * `y_coords_m` - Y coordinates in meters
84 /// * `texts` - Text labels for each point
85 /// * `colors` - RGB colors for each point
86 ///
87 /// # Errors
88 /// Returns `NanonisError` if communication fails.
89 pub fn marks_points_draw(
90 &mut self,
91 x_coords_m: &[f32],
92 y_coords_m: &[f32],
93 texts: &[String],
94 colors: &[u32],
95 ) -> Result<(), NanonisError> {
96 let num_points = x_coords_m.len() as i32;
97
98 self.quick_send(
99 "Marks.PointsDraw",
100 vec![
101 NanonisValue::I32(num_points),
102 NanonisValue::ArrayF32(x_coords_m.to_vec()),
103 NanonisValue::ArrayF32(y_coords_m.to_vec()),
104 NanonisValue::ArrayString(texts.to_vec()),
105 NanonisValue::ArrayU32(colors.to_vec()),
106 ],
107 vec!["i", "*f", "*f", "+*c", "*I"],
108 vec![],
109 )?;
110 Ok(())
111 }
112
113 /// Draw a line in the scan frame.
114 ///
115 /// # Arguments
116 /// * `start_x_m` - Start X coordinate in meters
117 /// * `start_y_m` - Start Y coordinate in meters
118 /// * `end_x_m` - End X coordinate in meters
119 /// * `end_y_m` - End Y coordinate in meters
120 /// * `color` - RGB color value
121 ///
122 /// # Errors
123 /// Returns `NanonisError` if communication fails.
124 pub fn marks_line_draw(
125 &mut self,
126 start_x_m: f32,
127 start_y_m: f32,
128 end_x_m: f32,
129 end_y_m: f32,
130 color: u32,
131 ) -> Result<(), NanonisError> {
132 self.quick_send(
133 "Marks.LineDraw",
134 vec![
135 NanonisValue::F32(start_x_m),
136 NanonisValue::F32(start_y_m),
137 NanonisValue::F32(end_x_m),
138 NanonisValue::F32(end_y_m),
139 NanonisValue::U32(color),
140 ],
141 vec!["f", "f", "f", "f", "I"],
142 vec![],
143 )?;
144 Ok(())
145 }
146
147 /// Draw multiple lines in the scan frame.
148 ///
149 /// # Arguments
150 /// * `start_x_m` - Start X coordinates in meters
151 /// * `start_y_m` - Start Y coordinates in meters
152 /// * `end_x_m` - End X coordinates in meters
153 /// * `end_y_m` - End Y coordinates in meters
154 /// * `colors` - RGB colors for each line
155 ///
156 /// # Errors
157 /// Returns `NanonisError` if communication fails.
158 pub fn marks_lines_draw(
159 &mut self,
160 start_x_m: &[f32],
161 start_y_m: &[f32],
162 end_x_m: &[f32],
163 end_y_m: &[f32],
164 colors: &[u32],
165 ) -> Result<(), NanonisError> {
166 let num_lines = start_x_m.len() as i32;
167
168 self.quick_send(
169 "Marks.LinesDraw",
170 vec![
171 NanonisValue::I32(num_lines),
172 NanonisValue::ArrayF32(start_x_m.to_vec()),
173 NanonisValue::ArrayF32(start_y_m.to_vec()),
174 NanonisValue::ArrayF32(end_x_m.to_vec()),
175 NanonisValue::ArrayF32(end_y_m.to_vec()),
176 NanonisValue::ArrayU32(colors.to_vec()),
177 ],
178 vec!["i", "*f", "*f", "*f", "*f", "*I"],
179 vec![],
180 )?;
181 Ok(())
182 }
183
184 /// Erase a point mark from the scan frame.
185 ///
186 /// # Arguments
187 /// * `point_index` - Index of point to erase (-1 to erase all)
188 ///
189 /// # Errors
190 /// Returns `NanonisError` if communication fails.
191 pub fn marks_points_erase(&mut self, point_index: i32) -> Result<(), NanonisError> {
192 self.quick_send(
193 "Marks.PointsErase",
194 vec![NanonisValue::I32(point_index)],
195 vec!["i"],
196 vec![],
197 )?;
198 Ok(())
199 }
200
201 /// Erase a line mark from the scan frame.
202 ///
203 /// # Arguments
204 /// * `line_index` - Index of line to erase (-1 to erase all)
205 ///
206 /// # Errors
207 /// Returns `NanonisError` if communication fails.
208 pub fn marks_lines_erase(&mut self, line_index: i32) -> Result<(), NanonisError> {
209 self.quick_send(
210 "Marks.LinesErase",
211 vec![NanonisValue::I32(line_index)],
212 vec!["i"],
213 vec![],
214 )?;
215 Ok(())
216 }
217
218 /// Show or hide a point mark.
219 ///
220 /// # Arguments
221 /// * `point_index` - Index of point (-1 for all)
222 /// * `visible` - True to show, false to hide
223 ///
224 /// # Errors
225 /// Returns `NanonisError` if communication fails.
226 pub fn marks_points_visible_set(
227 &mut self,
228 point_index: i32,
229 visible: bool,
230 ) -> Result<(), NanonisError> {
231 // Note: 0 = visible, 1 = invisible in the protocol
232 let flag = if visible { 0u16 } else { 1u16 };
233 self.quick_send(
234 "Marks.PointsVisibleSet",
235 vec![NanonisValue::I32(point_index), NanonisValue::U16(flag)],
236 vec!["i", "H"],
237 vec![],
238 )?;
239 Ok(())
240 }
241
242 /// Show or hide a line mark.
243 ///
244 /// # Arguments
245 /// * `line_index` - Index of line (-1 for all)
246 /// * `visible` - True to show, false to hide
247 ///
248 /// # Errors
249 /// Returns `NanonisError` if communication fails.
250 pub fn marks_lines_visible_set(
251 &mut self,
252 line_index: i32,
253 visible: bool,
254 ) -> Result<(), NanonisError> {
255 // Note: 0 = visible, 1 = invisible in the protocol
256 let flag = if visible { 0u16 } else { 1u16 };
257 self.quick_send(
258 "Marks.LinesVisibleSet",
259 vec![NanonisValue::I32(line_index), NanonisValue::U16(flag)],
260 vec!["i", "H"],
261 vec![],
262 )?;
263 Ok(())
264 }
265
266 /// Get information about all drawn point marks.
267 ///
268 /// # Returns
269 /// A vector of [`PointMark`] structs.
270 ///
271 /// # Errors
272 /// Returns `NanonisError` if communication fails.
273 pub fn marks_points_get(&mut self) -> Result<Vec<PointMark>, NanonisError> {
274 let result = self.quick_send(
275 "Marks.PointsGet",
276 vec![],
277 vec![],
278 vec!["i", "*f", "*f", "i", "*+c", "*I", "*I"],
279 )?;
280
281 if result.len() >= 7 {
282 let num_points = result[0].as_i32()? as usize;
283 let x_coords = result[1].as_f32_array()?;
284 let y_coords = result[2].as_f32_array()?;
285 let texts = result[4].as_string_array()?;
286 let colors = result[5].as_u32_array()?;
287 let visible = result[6].as_u32_array()?;
288
289 let mut points = Vec::with_capacity(num_points);
290 for i in 0..num_points {
291 if i < x_coords.len()
292 && i < y_coords.len()
293 && i < texts.len()
294 && i < colors.len()
295 && i < visible.len()
296 {
297 points.push(PointMark {
298 x_m: x_coords[i],
299 y_m: y_coords[i],
300 text: texts[i].clone(),
301 color: colors[i],
302 visible: visible[i] != 0,
303 });
304 }
305 }
306 Ok(points)
307 } else {
308 Ok(vec![])
309 }
310 }
311
312 /// Get information about all drawn line marks.
313 ///
314 /// # Returns
315 /// A vector of [`LineMark`] structs.
316 ///
317 /// # Errors
318 /// Returns `NanonisError` if communication fails.
319 pub fn marks_lines_get(&mut self) -> Result<Vec<LineMark>, NanonisError> {
320 let result = self.quick_send(
321 "Marks.LinesGet",
322 vec![],
323 vec![],
324 vec!["i", "*f", "*f", "*f", "*f", "*I", "*I"],
325 )?;
326
327 if result.len() >= 7 {
328 let num_lines = result[0].as_i32()? as usize;
329 let start_x = result[1].as_f32_array()?;
330 let start_y = result[2].as_f32_array()?;
331 let end_x = result[3].as_f32_array()?;
332 let end_y = result[4].as_f32_array()?;
333 let colors = result[5].as_u32_array()?;
334 let visible = result[6].as_u32_array()?;
335
336 let mut lines = Vec::with_capacity(num_lines);
337 for i in 0..num_lines {
338 if i < start_x.len()
339 && i < start_y.len()
340 && i < end_x.len()
341 && i < end_y.len()
342 && i < colors.len()
343 && i < visible.len()
344 {
345 lines.push(LineMark {
346 start_x_m: start_x[i],
347 start_y_m: start_y[i],
348 end_x_m: end_x[i],
349 end_y_m: end_y[i],
350 color: colors[i],
351 visible: visible[i] != 0,
352 });
353 }
354 }
355 Ok(lines)
356 } else {
357 Ok(vec![])
358 }
359 }
360}