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 "cutil.h"
47#include "georef.h"
48#include "navutil.h" // for LogMessageOnce
49#include "ocpn_pixel.h"
50#include "ocpndc.h"
51#include "s52utils.h"
52#include "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 __MSVC__
64#define _CRTDBG_MAP_ALLOC
65#include <stdlib.h>
66#include <crtdbg.h>
67#define DEBUG_NEW new (_NORMAL_BLOCK, __FILE__, __LINE__)
68#define new DEBUG_NEW
69#endif
70
71#ifdef ocpnUSE_GL
72#include "glChartCanvas.h"
73#endif
74
75#include <algorithm> // for std::sort
76#include <map>
77
78#ifdef __MSVC__
79#define strncasecmp(x, y, z) _strnicmp(x, y, z)
80#endif
81
82extern bool g_b_EnableVBO;
83
84
85//----------------------------------------------------------------------------------
86// S57Obj CTOR
87//----------------------------------------------------------------------------------
88
89S57Obj::S57Obj() { Init(); }
90
91//----------------------------------------------------------------------------------
92// S57Obj DTOR
93//----------------------------------------------------------------------------------
94
95S57Obj::~S57Obj() {
96 // Don't delete any allocated records of simple copy clones
97 if (!bIsClone) {
98 if (attVal) {
99 for (unsigned int iv = 0; iv < attVal->GetCount(); iv++) {
100 S57attVal *vv = attVal->Item(iv);
101 void *v2 = vv->value;
102 free(v2);
103 delete vv;
104 }
105 delete attVal;
106 }
107 free(att_array);
108
109 if (pPolyTessGeo) {
110#ifdef ocpnUSE_GL
111 bool b_useVBO = g_b_EnableVBO && !auxParm1; // VBO allowed?
112
113 PolyTriGroup *ppg_vbo = pPolyTessGeo->Get_PolyTriGroup_head();
114 if (b_useVBO && ppg_vbo && auxParm0 > 0 && ppg_vbo->single_buffer) {
115 glDeleteBuffers(1, (GLuint *)&auxParm0);
116 }
117#endif
118 delete pPolyTessGeo;
119 }
120
121 if (FText) delete FText;
122
123 if (geoPt) free(geoPt);
124 if (geoPtz) free(geoPtz);
125 if (geoPtMulti) free(geoPtMulti);
126
127 if (m_lsindex_array) free(m_lsindex_array);
128
129 if (m_ls_list) {
130 line_segment_element *element = m_ls_list;
131 while (element) {
132 line_segment_element *next = element->next;
133 delete element;
134 element = next;
135 }
136 }
137 }
138}
139
140void S57Obj::Init() {
141 att_array = NULL;
142 attVal = NULL;
143 n_attr = 0;
144
145 pPolyTessGeo = NULL;
146
147 bCS_Added = 0;
148 CSrules = NULL;
149 FText = NULL;
150 bFText_Added = 0;
151 geoPtMulti = NULL;
152 geoPtz = NULL;
153 geoPt = NULL;
154 bIsClone = false;
155 Scamin = 1e8+2; // Default is very large number, effectively unused.
156 SuperScamin = -1;
157 nRef = 0;
158
159 bIsAton = false;
160 bIsAssociable = false;
161 m_n_lsindex = 0;
162 m_lsindex_array = NULL;
163 m_n_edge_max_points = 0;
164 m_ls_list = 0;
165 m_ls_list_legacy = 0;
166
167 iOBJL = -1; // deferred, done by OBJL filtering in the PLIB as needed
168 bBBObj_valid = false;
169
170 // Set default (unity) auxiliary transform coefficients
171 x_rate = 1.0;
172 y_rate = 1.0;
173 x_origin = 0.0;
174 y_origin = 0.0;
175
176 auxParm0 = 0;
177 auxParm1 = 0;
178 auxParm2 = 0;
179 auxParm3 = 0;
180}
181
182//----------------------------------------------------------------------------------
183// S57Obj CTOR from FeatureName
184//----------------------------------------------------------------------------------
185S57Obj::S57Obj(const char *featureName) {
186 Init();
187
188 attVal = new wxArrayOfS57attVal();
189
190 strncpy(FeatureName, featureName, 6);
191 FeatureName[6] = 0;
192
193 if (!strncmp(FeatureName, "DEPARE", 6) || !strncmp(FeatureName, "DRGARE", 6))
194 bIsAssociable = true;
195}
196
197bool S57Obj::AddIntegerAttribute(const char *acronym, int val) {
198 S57attVal *pattValTmp = new S57attVal;
199
200 int *pAVI = (int *)malloc(sizeof(int)); // new int;
201 *pAVI = val;
202
203 pattValTmp->valType = OGR_INT;
204 pattValTmp->value = pAVI;
205
206 att_array = (char *)realloc(att_array, 6 * (n_attr + 1));
207 strncpy(att_array + (6 * sizeof(char) * n_attr), acronym, 6);
208 n_attr++;
209
210 attVal->Add(pattValTmp);
211
212 if (!strncmp(acronym, "SCAMIN", 6)) Scamin = val;
213
214 return true;
215}
216
217bool S57Obj::AddIntegerListAttribute(const char *acronym, int *pval,
218 int nValue) {
219 return true;
220}
221
222bool S57Obj::AddDoubleAttribute(const char *acronym, double val) {
223 S57attVal *pattValTmp = new S57attVal;
224
225 double *pAVI = (double *)malloc(sizeof(double)); // new double;
226 *pAVI = val;
227
228 pattValTmp->valType = OGR_REAL;
229 pattValTmp->value = pAVI;
230
231 att_array = (char *)realloc(att_array, 6 * (n_attr + 1));
232 strncpy(att_array + (6 * sizeof(char) * n_attr), acronym, 6);
233 n_attr++;
234
235 attVal->Add(pattValTmp);
236
237 return true;
238}
239
240bool S57Obj::AddDoubleListAttribute(const char *acronym, double *pval,
241 int nValue) {
242 return true;
243}
244
245bool S57Obj::AddStringAttribute(const char *acronym, char *val) {
246 S57attVal *pattValTmp = new S57attVal;
247
248 char *pAVS = (char *)malloc(strlen(val) + 1); // new string
249 strcpy(pAVS, val);
250
251 pattValTmp->valType = OGR_STR;
252 pattValTmp->value = pAVS;
253
254 att_array = (char *)realloc(att_array, 6 * (n_attr + 1));
255 strncpy(att_array + (6 * sizeof(char) * n_attr), acronym, 6);
256 n_attr++;
257
258 attVal->Add(pattValTmp);
259
260 return true;
261}
262
263bool S57Obj::SetPointGeometry(double lat, double lon, double ref_lat,
264 double ref_lon) {
265 Primitive_type = GEO_POINT;
266
267 m_lon = lon;
268 m_lat = lat;
269
270 // Set initial BoundingBox limits to 1 NM
271 double bound = 1. / 60.; // 1 NM, nominal
272 BBObj.Set(m_lat - bound, m_lon - bound, m_lat + bound, m_lon + bound);
273 bBBObj_valid = false;
274
275 // Calculate SM from chart common reference point
276 double easting, northing;
277 toSM(lat, lon, ref_lat, ref_lon, &easting, &northing);
278
279 x = easting;
280 y = northing;
281
282 npt = 1;
283
284 return true;
285}
286
287bool S57Obj::SetLineGeometry(LineGeometryDescriptor *pGeo, GeoPrim_t geoType,
288 double ref_lat, double ref_lon) {
289 Primitive_type = geoType;
290
291 // set s57obj bbox as lat/lon
292 BBObj.Set(pGeo->extent_s_lat, pGeo->extent_w_lon, pGeo->extent_n_lat,
293 pGeo->extent_e_lon);
294 bBBObj_valid = true;
295
296 // and declare x/y of the object to be average east/north of all points
297 double e1, e2, n1, n2;
298 toSM(pGeo->extent_n_lat, pGeo->extent_e_lon, ref_lat, ref_lon, &e1, &n1);
299 toSM(pGeo->extent_s_lat, pGeo->extent_w_lon, ref_lat, ref_lon, &e2, &n2);
300
301 x = (e1 + e2) / 2.;
302 y = (n1 + n2) / 2.;
303
304 // Set the object base point
305 double xll, yll;
306 fromSM(x, y, ref_lat, ref_lon, &yll, &xll);
307 m_lon = xll;
308 m_lat = yll;
309
310 // Set the edge and connected node table indices
311 m_n_lsindex = pGeo->indexCount;
312 m_lsindex_array = pGeo->indexTable;
313
314 m_n_edge_max_points =
315 0; // TODO this could be precalulated and added to next SENC format
316
317 return true;
318}
319
320bool S57Obj::SetAreaGeometry(PolyTessGeo *ppg, double ref_lat, double ref_lon) {
321 Primitive_type = GEO_AREA;
322 pPolyTessGeo = ppg;
323
324 // Set the s57obj bounding box as lat/lon
325 BBObj.Set(ppg->Get_ymin(), ppg->Get_xmin(), ppg->Get_ymax(), ppg->Get_xmax());
326 bBBObj_valid = true;
327
328 // and declare x/y of the object to be average east/north of all points
329 double e1, e2, n1, n2;
330 toSM(ppg->Get_ymax(), ppg->Get_xmax(), ref_lat, ref_lon, &e1, &n1);
331 toSM(ppg->Get_ymin(), ppg->Get_xmin(), ref_lat, ref_lon, &e2, &n2);
332
333 x = (e1 + e2) / 2.;
334 y = (n1 + n2) / 2.;
335
336 // Set the object base point
337 double xll, yll;
338 fromSM(x, y, ref_lat, ref_lon, &yll, &xll);
339 m_lon = xll;
340 m_lat = yll;
341
342 return true;
343}
344
345bool S57Obj::SetMultipointGeometry(MultipointGeometryDescriptor *pGeo,
346 double ref_lat, double ref_lon) {
347 Primitive_type = GEO_POINT;
348
349 npt = pGeo->pointCount;
350
351 geoPtz = (double *)malloc(npt * 3 * sizeof(double));
352 geoPtMulti = (double *)malloc(npt * 2 * sizeof(double));
353
354 double *pdd = geoPtz;
355 double *pdl = geoPtMulti;
356
357 float *pfs = (float *)(pGeo->pointTable); // start of point data
358 for (int ip = 0; ip < npt; ip++) {
359 float easting, northing;
360 easting = *pfs++;
361 northing = *pfs++;
362 float depth = *pfs++;
363
364 *pdd++ = easting;
365 *pdd++ = northing;
366 *pdd++ = depth;
367
368 // Convert point from SM to lat/lon for later use in decomposed bboxes
369 double xll, yll;
370 fromSM(easting, northing, ref_lat, ref_lon, &yll, &xll);
371
372 *pdl++ = xll;
373 *pdl++ = yll;
374 }
375
376 // set s57obj bbox as lat/lon
377 BBObj.Set(pGeo->extent_s_lat, pGeo->extent_w_lon, pGeo->extent_n_lat,
378 pGeo->extent_e_lon);
379 bBBObj_valid = true;
380
381 return true;
382}
383
384int S57Obj::GetAttributeIndex(const char *AttrSeek) {
385 char *patl = att_array;
386
387 for (int i = 0; i < n_attr; i++) {
388 if (!strncmp(patl, AttrSeek, 6)) {
389 return i;
390 break;
391 }
392
393 patl += 6;
394 }
395
396 return -1;
397}
398
399wxString S57Obj::GetAttrValueAsString(const char *AttrName) {
400 wxString str;
401
402 int idx = GetAttributeIndex(AttrName);
403
404 if (idx >= 0) {
405 // using idx to get the attribute value
406
407 S57attVal *v = attVal->Item(idx);
408
409 switch (v->valType) {
410 case OGR_STR: {
411 char *val = (char *)(v->value);
412 str.Append(wxString(val, wxConvUTF8));
413 break;
414 }
415 case OGR_REAL: {
416 double dval = *(double *)(v->value);
417 str.Printf(_T("%g"), dval);
418 break;
419 }
420 case OGR_INT: {
421 int ival = *((int *)v->value);
422 str.Printf(_T("%d"), ival);
423 break;
424 }
425 default: {
426 str.Printf(_T("Unknown attribute type"));
427 break;
428 }
429 }
430 }
431 return str;
432}