OpenCPN Partial API docs
Loading...
Searching...
No Matches
s57obj.cpp
1/***************************************************************************
2 *
3 * Project: OpenCPN
4 * Purpose: S57 Chart Object
5 * Author: David Register
6 *
7 ***************************************************************************
8 * Copyright (C) 2010 by David S. Register *
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
24 **************************************************************************/
25
26// For compilers that support precompilation, includes "wx.h".
27#include "wx/wxprec.h"
28
29#ifndef WX_PRECOMP
30#include "wx/wx.h"
31#endif // precompiled headers
32
33#include "wx/image.h" // for some reason, needed for msvc???
34#include "wx/tokenzr.h"
35#include <wx/textfile.h>
36
37#include "dychart.h"
38#include "OCPNPlatform.h"
39
40#include "s52s57.h"
41#include "s52plib.h"
42
43#include "s57chart.h"
44
45#include "mygeom.h"
46#include "model/cutil.h"
47#include "model/georef.h"
48#include "navutil.h" // for LogMessageOnce
49#include "ocpn_pixel.h"
50#include "ocpndc.h"
51#include "s52utils.h"
52#include "model/wx28compat.h"
53
54#include "gdal/cpl_csv.h"
55#include "setjmp.h"
56
57#include "ogr_s57.h"
58
59#include "pluginmanager.h" // for S57 lights overlay
60
61#include "Osenc.h"
62
63#ifdef __VISUALC__
64#include <wx/msw/msvcrt.h>
65#endif
66
67#ifdef ocpnUSE_GL
68#include "glChartCanvas.h"
69#endif
70
71#include <algorithm> // for std::sort
72#include <map>
73
74#ifdef __MSVC__
75#define strncasecmp(x, y, z) _strnicmp(x, y, z)
76#endif
77
78extern bool g_b_EnableVBO;
79
80//----------------------------------------------------------------------------------
81// S57Obj CTOR
82//----------------------------------------------------------------------------------
83
84S57Obj::S57Obj() { Init(); }
85
86//----------------------------------------------------------------------------------
87// S57Obj DTOR
88//----------------------------------------------------------------------------------
89
90S57Obj::~S57Obj() {
91 // Don't delete any allocated records of simple copy clones
92 if (!bIsClone) {
93 if (attVal) {
94 for (unsigned int iv = 0; iv < attVal->GetCount(); iv++) {
95 S57attVal *vv = attVal->Item(iv);
96 void *v2 = vv->value;
97 free(v2);
98 delete vv;
99 }
100 delete attVal;
101 }
102 free(att_array);
103
104 if (pPolyTessGeo) {
105#ifdef ocpnUSE_GL
106 bool b_useVBO = g_b_EnableVBO && !auxParm1; // VBO allowed?
107
108 PolyTriGroup *ppg_vbo = pPolyTessGeo->Get_PolyTriGroup_head();
109 if (b_useVBO && ppg_vbo && auxParm0 > 0 && ppg_vbo->single_buffer) {
110 glDeleteBuffers(1, (GLuint *)&auxParm0);
111 }
112#endif
113 delete pPolyTessGeo;
114 }
115
116 if (FText) delete FText;
117
118 if (geoPt) free(geoPt);
119 if (geoPtz) free(geoPtz);
120 if (geoPtMulti) free(geoPtMulti);
121
122 if (m_lsindex_array) free(m_lsindex_array);
123
124 if (m_ls_list) {
125 line_segment_element *element = m_ls_list;
126 while (element) {
127 line_segment_element *next = element->next;
128 delete element;
129 element = next;
130 }
131 }
132 }
133}
134
135void S57Obj::Init() {
136 att_array = NULL;
137 attVal = NULL;
138 n_attr = 0;
139
140 pPolyTessGeo = NULL;
141
142 bCS_Added = 0;
143 CSrules = NULL;
144 FText = NULL;
145 bFText_Added = 0;
146 geoPtMulti = NULL;
147 geoPtz = NULL;
148 geoPt = NULL;
149 bIsClone = false;
150 Scamin = 1e8 + 2; // Default is very large number, effectively unused.
151 SuperScamin = -1;
152 nRef = 0;
153
154 bIsAton = false;
155 bIsAssociable = false;
156 m_n_lsindex = 0;
157 m_lsindex_array = NULL;
158 m_n_edge_max_points = 0;
159 m_ls_list = 0;
160 m_ls_list_legacy = 0;
161
162 iOBJL = -1; // deferred, done by OBJL filtering in the PLIB as needed
163 bBBObj_valid = false;
164
165 // Set default (unity) auxiliary transform coefficients
166 x_rate = 1.0;
167 y_rate = 1.0;
168 x_origin = 0.0;
169 y_origin = 0.0;
170
171 auxParm0 = 0;
172 auxParm1 = 0;
173 auxParm2 = 0;
174 auxParm3 = 0;
175}
176
177//----------------------------------------------------------------------------------
178// S57Obj CTOR from FeatureName
179//----------------------------------------------------------------------------------
180S57Obj::S57Obj(const char *featureName) {
181 Init();
182
183 attVal = new wxArrayOfS57attVal();
184
185 strncpy(FeatureName, featureName, 6);
186 FeatureName[6] = 0;
187
188 if (!strncmp(FeatureName, "DEPARE", 6) || !strncmp(FeatureName, "DRGARE", 6))
189 bIsAssociable = true;
190}
191
192bool S57Obj::AddIntegerAttribute(const char *acronym, int val) {
193 S57attVal *pattValTmp = new S57attVal;
194
195 int *pAVI = (int *)malloc(sizeof(int)); // new int;
196 *pAVI = val;
197
198 pattValTmp->valType = OGR_INT;
199 pattValTmp->value = pAVI;
200
201 att_array = (char *)realloc(att_array, 6 * (n_attr + 1));
202 strncpy(att_array + (6 * sizeof(char) * n_attr), acronym, 6);
203 n_attr++;
204
205 attVal->Add(pattValTmp);
206
207 if (!strncmp(acronym, "SCAMIN", 6)) Scamin = val;
208
209 return true;
210}
211
212bool S57Obj::AddIntegerListAttribute(const char *acronym, int *pval,
213 int nValue) {
214 return true;
215}
216
217bool S57Obj::AddDoubleAttribute(const char *acronym, double val) {
218 S57attVal *pattValTmp = new S57attVal;
219
220 double *pAVI = (double *)malloc(sizeof(double)); // new double;
221 *pAVI = val;
222
223 pattValTmp->valType = OGR_REAL;
224 pattValTmp->value = pAVI;
225
226 att_array = (char *)realloc(att_array, 6 * (n_attr + 1));
227 strncpy(att_array + (6 * sizeof(char) * n_attr), acronym, 6);
228 n_attr++;
229
230 attVal->Add(pattValTmp);
231
232 return true;
233}
234
235bool S57Obj::AddDoubleListAttribute(const char *acronym, double *pval,
236 int nValue) {
237 return true;
238}
239
240bool S57Obj::AddStringAttribute(const char *acronym, char *val) {
241 S57attVal *pattValTmp = new S57attVal;
242
243 char *pAVS = (char *)malloc(strlen(val) + 1); // new string
244 strcpy(pAVS, val);
245
246 pattValTmp->valType = OGR_STR;
247 pattValTmp->value = pAVS;
248
249 att_array = (char *)realloc(att_array, 6 * (n_attr + 1));
250 strncpy(att_array + (6 * sizeof(char) * n_attr), acronym, 6);
251 n_attr++;
252
253 attVal->Add(pattValTmp);
254
255 return true;
256}
257
258bool S57Obj::SetPointGeometry(double lat, double lon, double ref_lat,
259 double ref_lon) {
260 Primitive_type = GEO_POINT;
261
262 m_lon = lon;
263 m_lat = lat;
264
265 // Set initial BoundingBox limits to 1 NM
266 double bound = 1. / 60.; // 1 NM, nominal
267 BBObj.Set(m_lat - bound, m_lon - bound, m_lat + bound, m_lon + bound);
268 bBBObj_valid = false;
269
270 // Calculate SM from chart common reference point
271 double easting, northing;
272 toSM(lat, lon, ref_lat, ref_lon, &easting, &northing);
273
274 x = easting;
275 y = northing;
276
277 npt = 1;
278
279 return true;
280}
281
282bool S57Obj::SetLineGeometry(LineGeometryDescriptor *pGeo, GeoPrim_t geoType,
283 double ref_lat, double ref_lon) {
284 Primitive_type = geoType;
285
286 // set s57obj bbox as lat/lon
287 BBObj.Set(pGeo->extent_s_lat, pGeo->extent_w_lon, pGeo->extent_n_lat,
288 pGeo->extent_e_lon);
289 bBBObj_valid = true;
290
291 // and declare x/y of the object to be average east/north of all points
292 double e1, e2, n1, n2;
293 toSM(pGeo->extent_n_lat, pGeo->extent_e_lon, ref_lat, ref_lon, &e1, &n1);
294 toSM(pGeo->extent_s_lat, pGeo->extent_w_lon, ref_lat, ref_lon, &e2, &n2);
295
296 x = (e1 + e2) / 2.;
297 y = (n1 + n2) / 2.;
298
299 // Set the object base point
300 double xll, yll;
301 fromSM(x, y, ref_lat, ref_lon, &yll, &xll);
302 m_lon = xll;
303 m_lat = yll;
304
305 // Set the edge and connected node table indices
306 m_n_lsindex = pGeo->indexCount;
307 m_lsindex_array = pGeo->indexTable;
308
309 m_n_edge_max_points =
310 0; // TODO this could be precalulated and added to next SENC format
311
312 return true;
313}
314
315bool S57Obj::SetAreaGeometry(PolyTessGeo *ppg, double ref_lat, double ref_lon) {
316 Primitive_type = GEO_AREA;
317 pPolyTessGeo = ppg;
318
319 // Set the s57obj bounding box as lat/lon
320 BBObj.Set(ppg->Get_ymin(), ppg->Get_xmin(), ppg->Get_ymax(), ppg->Get_xmax());
321 bBBObj_valid = true;
322
323 // and declare x/y of the object to be average east/north of all points
324 double e1, e2, n1, n2;
325 toSM(ppg->Get_ymax(), ppg->Get_xmax(), ref_lat, ref_lon, &e1, &n1);
326 toSM(ppg->Get_ymin(), ppg->Get_xmin(), ref_lat, ref_lon, &e2, &n2);
327
328 x = (e1 + e2) / 2.;
329 y = (n1 + n2) / 2.;
330
331 // Set the object base point
332 double xll, yll;
333 fromSM(x, y, ref_lat, ref_lon, &yll, &xll);
334 m_lon = xll;
335 m_lat = yll;
336
337 return true;
338}
339
340bool S57Obj::SetMultipointGeometry(MultipointGeometryDescriptor *pGeo,
341 double ref_lat, double ref_lon) {
342 Primitive_type = GEO_POINT;
343
344 npt = pGeo->pointCount;
345
346 geoPtz = (double *)malloc(npt * 3 * sizeof(double));
347 geoPtMulti = (double *)malloc(npt * 2 * sizeof(double));
348
349 double *pdd = geoPtz;
350 double *pdl = geoPtMulti;
351
352 float *pfs = (float *)(pGeo->pointTable); // start of point data
353 for (int ip = 0; ip < npt; ip++) {
354 float easting, northing;
355 easting = *pfs++;
356 northing = *pfs++;
357 float depth = *pfs++;
358
359 *pdd++ = easting;
360 *pdd++ = northing;
361 *pdd++ = depth;
362
363 // Convert point from SM to lat/lon for later use in decomposed bboxes
364 double xll, yll;
365 fromSM(easting, northing, ref_lat, ref_lon, &yll, &xll);
366
367 *pdl++ = xll;
368 *pdl++ = yll;
369 }
370
371 // set s57obj bbox as lat/lon
372 BBObj.Set(pGeo->extent_s_lat, pGeo->extent_w_lon, pGeo->extent_n_lat,
373 pGeo->extent_e_lon);
374 bBBObj_valid = true;
375
376 return true;
377}
378
379int S57Obj::GetAttributeIndex(const char *AttrSeek) {
380 char *patl = att_array;
381
382 for (int i = 0; i < n_attr; i++) {
383 if (!strncmp(patl, AttrSeek, 6)) {
384 return i;
385 break;
386 }
387
388 patl += 6;
389 }
390
391 return -1;
392}
393
394wxString S57Obj::GetAttrValueAsString(const char *AttrName) {
395 wxString str;
396
397 int idx = GetAttributeIndex(AttrName);
398
399 if (idx >= 0) {
400 // using idx to get the attribute value
401
402 S57attVal *v = attVal->Item(idx);
403
404 switch (v->valType) {
405 case OGR_STR: {
406 char *val = (char *)(v->value);
407 str.Append(wxString(val, wxConvUTF8));
408 break;
409 }
410 case OGR_REAL: {
411 double dval = *(double *)(v->value);
412 str.Printf(_T("%g"), dval);
413 break;
414 }
415 case OGR_INT: {
416 int ival = *((int *)v->value);
417 str.Printf(_T("%d"), ival);
418 break;
419 }
420 default: {
421 str.Printf(_T("Unknown attribute type"));
422 break;
423 }
424 }
425 }
426 return str;
427}