|
3 | 3 | <v-card-title |
4 | 4 | class="pb-2 text-h6 text-primary font-weight-bold d-flex align-center" |
5 | 5 | > |
6 | | - <img |
| 6 | + <v-img |
7 | 7 | src="/aoi.svg" |
8 | 8 | alt="AOI icon" |
9 | 9 | class="mr-3" |
10 | 10 | width="48" |
11 | 11 | height="48" |
12 | | - color="grey-darken-2" |
13 | 12 | /> |
14 | 13 | Create Area of Interest (Bounding Box) |
15 | 14 | </v-card-title> |
|
155 | 154 | UIStore.setShowCreateTools(true) |
156 | 155 | UIStore.setShowCreatePoint(false) |
157 | 156 | UIStore.setShowCreateAOI(false) |
| 157 | + UIStore.setShowCreateVOI(false) |
158 | 158 | } |
159 | 159 |
|
160 | 160 | const UIStore = useUIStore() |
|
167 | 167 | const max_x = ref("") |
168 | 168 | const max_y = ref("") |
169 | 169 | const z = ref("") |
170 | | -
|
171 | 170 | const loading = ref(false) |
172 | 171 |
|
173 | 172 | const isFormFilled = computed(() => { |
|
183 | 182 | UIStore.setShowCreateAOI(false) |
184 | 183 | } |
185 | 184 |
|
186 | | - const safeParseFloat = (value) => { |
187 | | - const sanitizedValue = String(value).trim().replace(",", ".") |
188 | | - const result = parseFloat(sanitizedValue) |
189 | | - return isNaN(result) && sanitizedValue === "" ? NaN : result |
190 | | - } |
191 | | -
|
192 | 185 | function visibleBoundingBox() { |
193 | | - console.log("visibleBoundingBox", hybridViewerStore.genericRenderWindow) |
194 | 186 | if (!hybridViewerStore.genericRenderWindow.value) |
195 | 187 | return [-1, 1, -1, 1, -1, 1] |
196 | 188 | const renderer = hybridViewerStore.genericRenderWindow.value.getRenderer() |
|
215 | 207 | const newMinY = boundsMinY - paddingY |
216 | 208 | const newMaxY = boundsMaxY + paddingY |
217 | 209 |
|
218 | | - min_x.value = newMinX |
219 | | - max_x.value = newMaxX |
220 | | - min_y.value = newMinY |
221 | | - max_y.value = newMaxY |
222 | | - z.value = (bounds[4] + bounds[5]) / 2 |
| 210 | + min_x.value = newMinX.toFixed(2) |
| 211 | + max_x.value = newMaxX.toFixed(2) |
| 212 | + min_y.value = newMinY.toFixed(2) |
| 213 | + max_y.value = newMaxY.toFixed(2) |
| 214 | + z.value = ((bounds[4] + bounds[5]) / 2).toFixed(2) |
223 | 215 | } |
224 | 216 |
|
225 | 217 | onMounted(() => { |
226 | | - console.log("CreateAOI mounted") |
227 | 218 | initializeAOICoordinates() |
228 | 219 | }) |
229 | 220 |
|
|
232 | 223 | (newVal) => { |
233 | 224 | if (newVal) { |
234 | 225 | initializeAOICoordinates() |
| 226 | + name.value = "" |
235 | 227 | } |
236 | 228 | }, |
237 | 229 | ) |
238 | 230 |
|
| 231 | + const sanitizeNumberString = (str) => { |
| 232 | + if (str == null) return "" |
| 233 | + let value = String(str) |
| 234 | + .replace(/,/g, ".") |
| 235 | + .replace(/[^0-9eE+\-.]/g, "") |
| 236 | + if (/[eE]/.test(value)) { |
| 237 | + const parts = value.split(/[eE]/) |
| 238 | + if (parts.length > 2) { |
| 239 | + value = |
| 240 | + parts.slice(0, 2).join("e") + |
| 241 | + parts |
| 242 | + .slice(2) |
| 243 | + .join("") |
| 244 | + .replace(/[^0-9+\-.]/g, "") |
| 245 | + } |
| 246 | + } |
| 247 | + return value |
| 248 | + } |
| 249 | +
|
| 250 | + const handlePasteAOI = (event) => { |
| 251 | + const pastedText = |
| 252 | + (event && event.clipboardData && event.clipboardData.getData("text")) || |
| 253 | + "" |
| 254 | +
|
| 255 | + if (!pastedText) return |
| 256 | +
|
| 257 | + const coordinates = pastedText.match(/[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?/g) |
| 258 | + if (!coordinates || coordinates.length === 0) return |
| 259 | +
|
| 260 | + const sanitized = coordinates.map((c) => sanitizeNumberString(c)) |
| 261 | +
|
| 262 | + if (sanitized.length >= 4) { |
| 263 | + min_x.value = sanitized[0] |
| 264 | + min_y.value = sanitized[1] |
| 265 | + max_x.value = sanitized[2] |
| 266 | + max_y.value = sanitized[3] |
| 267 | + event.preventDefault() |
| 268 | + } else if (sanitized.length >= 2) { |
| 269 | + min_x.value = sanitized[0] |
| 270 | + min_y.value = sanitized[1] |
| 271 | + event.preventDefault() |
| 272 | + } |
| 273 | + } |
| 274 | +
|
| 275 | + const sanitizeInputAOI = (value, field) => { |
| 276 | + const sanitizedValue = sanitizeNumberString(value) |
| 277 | + if (field === "min_x") min_x.value = sanitizedValue |
| 278 | + else if (field === "min_y") min_y.value = sanitizedValue |
| 279 | + else if (field === "max_x") max_x.value = sanitizedValue |
| 280 | + else if (field === "max_y") max_y.value = sanitizedValue |
| 281 | + else if (field === "z") z.value = sanitizedValue |
| 282 | + } |
| 283 | +
|
| 284 | + const safeParseFloat = (value) => { |
| 285 | + const sanitizedValue = String(value).trim().replace(",", ".") |
| 286 | + const result = parseFloat(sanitizedValue) |
| 287 | + return isNaN(result) && sanitizedValue === "" ? NaN : result |
| 288 | + } |
| 289 | +
|
239 | 290 | async function registerObject(data) { |
240 | 291 | await viewer_call( |
241 | 292 | { |
|
252 | 303 | native_filename: data.native_file_name, |
253 | 304 | viewable_filename: data.viewable_file_name, |
254 | 305 | displayed_name: data.name, |
| 306 | + is_aoi: true, |
255 | 307 | vtk_js: { |
256 | 308 | binary_light_viewable: data.binary_light_viewable, |
257 | 309 | }, |
|
262 | 314 | ) |
263 | 315 | } |
264 | 316 |
|
265 | | - async function createAOI() { |
| 317 | + const createAOI = async () => { |
266 | 318 | const min_x_val = safeParseFloat(min_x.value) |
267 | 319 | const min_y_val = safeParseFloat(min_y.value) |
268 | 320 | const max_x_val = safeParseFloat(max_x.value) |
|
276 | 328 | isNaN(max_y_val) || |
277 | 329 | isNaN(z_val) |
278 | 330 |
|
279 | | - if (hasNaN) { |
280 | | - console.error( |
281 | | - "AOI creation failed: One or more coordinate values resulted in NaN after parsing. Check the input format.", |
282 | | - ) |
283 | | - loading.value = false |
284 | | - return |
285 | | - } |
286 | | -
|
287 | | - if (min_x_val >= max_x_val || min_y_val >= max_y_val) { |
288 | | - console.error( |
289 | | - "AOI creation failed: Min coordinates must be less than Max coordinates", |
290 | | - ) |
291 | | - loading.value = false |
| 331 | + if ( |
| 332 | + hasNaN || |
| 333 | + min_x_val >= max_x_val || |
| 334 | + min_y_val >= max_y_val || |
| 335 | + !name.value |
| 336 | + ) { |
292 | 337 | return |
293 | 338 | } |
294 | 339 |
|
|
307 | 352 |
|
308 | 353 | const aoiSchema = back_schemas.opengeodeweb_back.create.create_aoi |
309 | 354 |
|
310 | | - if (!aoiSchema || typeof aoiSchema !== "object") { |
311 | | - console.error( |
312 | | - "FATAL ERROR: The AOI schema is missing or invalid at back_schemas.opengeodeweb_back.create.create_aoi", |
313 | | - ) |
314 | | - loading.value = false |
315 | | - return |
316 | | - } |
317 | 355 | loading.value = true |
318 | 356 | try { |
319 | | - await api_fetch( |
| 357 | + const response = await api_fetch( |
320 | 358 | { |
321 | 359 | schema: aoiSchema, |
322 | 360 | params: aoiData, |
323 | 361 | }, |
324 | 362 | { |
325 | 363 | response_function: async (response) => { |
326 | | - await registerObject(response._data) |
| 364 | + const dataToRegister = { |
| 365 | + ...response._data, |
| 366 | + points: aoiPoints, |
| 367 | + z: z_val, |
| 368 | + } |
| 369 | + await registerObject(dataToRegister) |
327 | 370 | }, |
328 | 371 | }, |
329 | 372 | ) |
330 | 373 | } catch (error) { |
331 | | - console.error("API call failed during createAOI:", error) |
332 | 374 | } finally { |
333 | 375 | loading.value = false |
334 | 376 | } |
335 | 377 | } |
336 | | -
|
337 | | - const sanitizeNumberString = (str) => { |
338 | | - if (str == null) return "" |
339 | | - let value = String(str) |
340 | | - .replace(/,/g, ".") |
341 | | - .replace(/[^0-9eE+\-.]/g, "") |
342 | | - if (/[eE]/.test(value)) { |
343 | | - const parts = value.split(/[eE]/) |
344 | | - if (parts.length > 2) { |
345 | | - value = |
346 | | - parts.slice(0, 2).join("e") + |
347 | | - parts |
348 | | - .slice(2) |
349 | | - .join("") |
350 | | - .replace(/[^0-9+\-.]/g, "") |
351 | | - } |
352 | | - } |
353 | | - return value |
354 | | - } |
355 | | -
|
356 | | - const handlePasteAOI = (event, type, field) => { |
357 | | - const pastedText = |
358 | | - (event && event.clipboardData && event.clipboardData.getData("text")) || |
359 | | - "" |
360 | | -
|
361 | | - if (!pastedText) return |
362 | | -
|
363 | | - const coordinates = pastedText.match(/[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?/g) |
364 | | - if (!coordinates || coordinates.length === 0) return |
365 | | -
|
366 | | - const sanitized = coordinates.map((c) => sanitizeNumberString(c)) |
367 | | -
|
368 | | - const xKey = `${type}_x` |
369 | | - const yKey = `${type}_y` |
370 | | -
|
371 | | - if (sanitized.length >= 2) { |
372 | | - if (field === "x" || type === "min") { |
373 | | - min_x.value = sanitized[0] |
374 | | - } else { |
375 | | - max_x.value = sanitized[0] |
376 | | - } |
377 | | - if (field === "y" || type === "min") { |
378 | | - min_y.value = sanitized[1] |
379 | | - } else { |
380 | | - max_y.value = sanitized[1] |
381 | | - } |
382 | | - event.preventDefault() |
383 | | - } else if (sanitized.length === 1) { |
384 | | - if (field === "x") { |
385 | | - if (type === "min") { |
386 | | - min_x.value = sanitized[0] |
387 | | - } else { |
388 | | - max_x.value = sanitized[0] |
389 | | - } |
390 | | - } else { |
391 | | - if (type === "min") { |
392 | | - min_y.value = sanitized[0] |
393 | | - } else { |
394 | | - max_y.value = sanitized[0] |
395 | | - } |
396 | | - } |
397 | | - event.preventDefault() |
398 | | - } |
399 | | - } |
400 | | -
|
401 | | - const sanitizeInputAOI = (value, field) => { |
402 | | - if (field === "min_x") min_x.value = sanitizeNumberString(value) |
403 | | - else if (field === "min_y") min_y.value = sanitizeNumberString(value) |
404 | | - else if (field === "max_x") max_x.value = sanitizeNumberString(value) |
405 | | - else if (field === "max_y") max_y.value = sanitizeNumberString(value) |
406 | | - } |
407 | 378 | </script> |
0 commit comments