25#include <unordered_map>
36#include <wx/listctrl.h>
37#include <wx/mstream.h>
39#include <wx/spinctrl.h>
40#include <wx/textfile.h>
41#include <wx/tokenzr.h>
68#include <wx/msw/msvcrt.h>
71extern s52plib *ps52plib;
75#include <wx/arrimpl.cpp>
76WX_DEFINE_OBJARRAY(Array_Of_M_COVR_Desc);
78#include <wx/listimpl.cpp>
79WX_DEFINE_LIST(List_Of_M_COVR_Desc);
81static int Get_CM93_CellIndex(
double lat,
double lon,
int scale);
83void Get_CM93_Cell_Origin(
int cellindex,
int scale,
double *lat,
double *lon);
85void appendOSDirSep(wxString *pString) {
86 wxChar sep = wxFileName::GetPathSeparator();
87 if (pString->Last() != sep) pString->Append(sep);
94M_COVR_Desc::M_COVR_Desc() {
96 gl_screen_vertices = NULL;
97 gl_screen_projection_type = PROJECTION_UNKNOWN;
101 m_centerlat_cos = 1.0;
102 m_buser_offsets =
false;
105 gl_screen_vertices = NULL;
108M_COVR_Desc::~M_COVR_Desc() {
110 delete[] gl_screen_vertices;
113int M_COVR_Desc::GetWKBSize() {
121 size += m_nvertices *
sizeof(float_2Dpt);
124 size += 8 *
sizeof(double);
129bool M_COVR_Desc::WriteWKB(
void *p) {
132 *pr++ = GetWKBSize();
134 *pr++ = m_cell_index;
140 float_2Dpt *pfo = (float_2Dpt *)pr;
141 float_2Dpt *pfi = pvertices;
142 for (
int i = 0; i < m_nvertices; i++) *pfo++ = *pfi++;
144 int *pi = (
int *)pfo;
147 double *pd = (
double *)pi;
148 *pd++ = transform_WGS84_offset_x;
149 *pd++ = transform_WGS84_offset_y;
150 *pd++ = m_covr_lat_min;
151 *pd++ = m_covr_lat_max;
152 *pd++ = m_covr_lon_min;
153 *pd++ = m_covr_lon_max;
155 double centerlat_cos =
156 cos(((m_covr_lat_min + m_covr_lat_max) / 2.) * PI / 180.);
158 *pd++ = user_xoff * centerlat_cos;
159 *pd++ = user_yoff * centerlat_cos;
165int M_COVR_Desc::ReadWKB(wxFFileInputStream &ifs) {
168 if (!ifs.Read(&length,
sizeof(
int)).Eof()) {
169 ifs.Read(&m_cell_index,
sizeof(
int));
170 ifs.Read(&m_object_id,
sizeof(
int));
171 ifs.Read(&m_subcell,
sizeof(
int));
173 ifs.Read(&m_nvertices,
sizeof(
int));
175 pvertices =
new float_2Dpt[m_nvertices];
177 ifs.Read(pvertices, m_nvertices *
sizeof(float_2Dpt));
179 ifs.Read(&m_npub_year,
sizeof(
int));
181 ifs.Read(&transform_WGS84_offset_x,
sizeof(
double));
182 ifs.Read(&transform_WGS84_offset_y,
sizeof(
double));
183 ifs.Read(&m_covr_lat_min,
sizeof(
double));
184 ifs.Read(&m_covr_lat_max,
sizeof(
double));
185 ifs.Read(&m_covr_lon_min,
sizeof(
double));
186 ifs.Read(&m_covr_lon_max,
sizeof(
double));
188 m_centerlat_cos = cos(((m_covr_lat_min + m_covr_lat_max) / 2.) * PI / 180.);
190 ifs.Read(&user_xoff,
sizeof(
double));
191 ifs.Read(&user_yoff,
sizeof(
double));
193 user_xoff /= m_centerlat_cos;
194 user_yoff /= m_centerlat_cos;
196 if ((fabs(user_xoff) > 1.) || (fabs(user_yoff) > 1.))
197 m_buser_offsets =
true;
199 m_buser_offsets =
false;
201 m_covr_bbox.Set(m_covr_lat_min, m_covr_lon_min, m_covr_lat_max,
208 float_2Dpt *p = pvertices;
210 for (
int ip = 0; ip < m_nvertices; ip++) {
212 if (fabs(plon - vp.
clon) > 180.) {
219 double easting, northing, epix, npix;
220 toSM(p->y, plon + 360., vp.
clat, vp.
clon + 360, &easting, &northing);
223 easting -= user_xoff;
225 northing -= user_yoff;
230 pwp[ip].x = (int)round((vp.
pix_width / 2) + epix);
231 pwp[ip].y = (int)round((vp.
pix_height / 2) - npix);
245char sig_version[] =
"COVR1002";
252 bool Init(wxChar scale_char, wxString &prefix);
253 unsigned int GetCoverCount() {
return m_covr_array_outlines.GetCount(); }
254 M_COVR_Desc *GetCover(
unsigned int im) {
return &m_covr_array_outlines[im]; }
257 bool IsCovrLoaded(
int cell_index);
259 M_COVR_Desc *Find_MCD(
int cell_index,
int object_id,
int sbcell);
265 wxString m_cachefile;
268 Array_Of_M_COVR_Desc m_covr_array_outlines;
272 std::unordered_map<int, int> m_cell_hash;
275covr_set::covr_set(
cm93chart *parent) { m_pParent = parent; }
277covr_set::~covr_set() {
279 if (m_cachefile.IsEmpty())
283 if (m_covr_array_outlines.GetCount()) {
284 wxFFileOutputStream ofs(m_cachefile);
286 ofs.Write(sig_version, 8);
288 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
289 int wkbsize = m_covr_array_outlines[i].GetWKBSize();
291 char *p = (
char *)malloc(wkbsize *
sizeof(
char));
292 m_covr_array_outlines[i].WriteWKB(p);
293 ofs.Write(p, wkbsize);
302bool covr_set::Init(wxChar scale_char, wxString &prefix) {
303 m_scale_char = scale_char;
305 switch (m_scale_char) {
336 wxString prefix_string = prefix;
337 wxString sep(wxFileName::GetPathSeparator());
338 prefix_string.Replace(sep,
"_");
339 prefix_string.Replace(
":",
"_");
342 appendOSDirSep(&m_cachefile);
344 m_cachefile +=
"cm93";
345 appendOSDirSep(&m_cachefile);
351 wxString cache_old_old_name = m_cachefile;
352 cache_old_old_name +=
"coverset.";
353 cache_old_old_name += m_scale_char;
355 wxString cache_old_name = m_cachefile;
356 cache_old_name +=
"coverset_sig.";
357 cache_old_name += m_scale_char;
359 m_cachefile +=
"coverset_sigp.";
360 m_cachefile += m_scale_char;
362 wxFileName fn(m_cachefile);
363 if (!fn.DirExists()) wxFileName::Mkdir(fn.GetPath(), 0777, wxPATH_MKDIR_FULL);
366 if (!wxFileName::FileExists(m_cachefile)) {
369 if (wxFileName::FileExists(cache_old_name)) ::wxRemoveFile(cache_old_name);
370 if (wxFileName::FileExists(cache_old_old_name))
371 ::wxRemoveFile(cache_old_old_name);
375 wxFFileInputStream ifs(m_cachefile);
379 if (!ifs.Read(&sig_bytes, 8).Eof()) {
380 if (strncmp(sig_bytes, sig_version, 8)) {
389 int length = pmcd->ReadWKB(ifs);
392 m_covr_array_outlines.Add(pmcd);
394 if (m_cell_hash.find(pmcd->m_cell_index) == m_cell_hash.end())
395 m_cell_hash[pmcd->m_cell_index] = 0;
397 m_cell_hash[pmcd->m_cell_index]++;
410 m_covr_array_outlines.Add(pmcd);
412 if (m_cell_hash.find(pmcd->m_cell_index) ==
414 m_cell_hash[pmcd->m_cell_index] = 0;
416 m_cell_hash[pmcd->m_cell_index]++;
419bool covr_set::IsCovrLoaded(
int cell_index) {
420 return (m_cell_hash.find(cell_index) != m_cell_hash.end());
424 if (m_cell_hash.find(pmcd->m_cell_index) ==
427 m_covr_array_outlines.Add(pmcd);
428 m_cell_hash[pmcd->m_cell_index] = 1;
436 bool b_found =
false;
437 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
438 M_COVR_Desc *pmcd_candidate = &m_covr_array_outlines[i];
439 if ((pmcd_candidate->m_cell_index == pmcd->m_cell_index) &&
440 (pmcd_candidate->m_object_id == pmcd->m_object_id) &&
441 (pmcd_candidate->m_subcell == pmcd->m_subcell))
450 m_covr_array_outlines.Add(pmcd);
451 m_cell_hash[pmcd->m_cell_index]++;
459 if (m_cell_hash.find(pmcd->m_cell_index) ==
467 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
468 M_COVR_Desc *pmcd_candidate = &m_covr_array_outlines[i];
469 if ((pmcd_candidate->m_cell_index == pmcd->m_cell_index) &&
470 (pmcd_candidate->m_object_id == pmcd->m_object_id) &&
471 (pmcd_candidate->m_subcell == pmcd->m_subcell)) {
479M_COVR_Desc *covr_set::Find_MCD(
int cell_index,
int object_id,
int subcell) {
480 if (m_cell_hash.find(cell_index) == m_cell_hash.end())
483 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
484 M_COVR_Desc *pmcd_candidate = &m_covr_array_outlines[i];
485 if ((pmcd_candidate->m_cell_index == cell_index) &&
486 (pmcd_candidate->m_object_id == object_id) &&
487 (pmcd_candidate->m_subcell == subcell))
489 return pmcd_candidate;
497static unsigned char Table_0[] = {
498 0x0CD, 0x0EA, 0x0DC, 0x048, 0x03E, 0x06D, 0x0CA, 0x07B, 0x052, 0x0E1, 0x0A4,
499 0x08E, 0x0AB, 0x005, 0x0A7, 0x097, 0x0B9, 0x060, 0x039, 0x085, 0x07C, 0x056,
500 0x07A, 0x0BA, 0x068, 0x06E, 0x0F5, 0x05D, 0x002, 0x04E, 0x00F, 0x0A1, 0x027,
501 0x024, 0x041, 0x034, 0x000, 0x05A, 0x0FE, 0x0CB, 0x0D0, 0x0FA, 0x0F8, 0x06C,
502 0x074, 0x096, 0x09E, 0x00E, 0x0C2, 0x049, 0x0E3, 0x0E5, 0x0C0, 0x03B, 0x059,
503 0x018, 0x0A9, 0x086, 0x08F, 0x030, 0x0C3, 0x0A8, 0x022, 0x00A, 0x014, 0x01A,
504 0x0B2, 0x0C9, 0x0C7, 0x0ED, 0x0AA, 0x029, 0x094, 0x075, 0x00D, 0x0AC, 0x00C,
505 0x0F4, 0x0BB, 0x0C5, 0x03F, 0x0FD, 0x0D9, 0x09C, 0x04F, 0x0D5, 0x084, 0x01E,
506 0x0B1, 0x081, 0x069, 0x0B4, 0x009, 0x0B8, 0x03C, 0x0AF, 0x0A3, 0x008, 0x0BF,
507 0x0E0, 0x09A, 0x0D7, 0x0F7, 0x08C, 0x067, 0x066, 0x0AE, 0x0D4, 0x04C, 0x0A5,
508 0x0EC, 0x0F9, 0x0B6, 0x064, 0x078, 0x006, 0x05B, 0x09B, 0x0F2, 0x099, 0x0CE,
509 0x0DB, 0x053, 0x055, 0x065, 0x08D, 0x007, 0x033, 0x004, 0x037, 0x092, 0x026,
510 0x023, 0x0B5, 0x058, 0x0DA, 0x02F, 0x0B3, 0x040, 0x05E, 0x07F, 0x04B, 0x062,
511 0x080, 0x0E4, 0x06F, 0x073, 0x01D, 0x0DF, 0x017, 0x0CC, 0x028, 0x025, 0x02D,
512 0x0EE, 0x03A, 0x098, 0x0E2, 0x001, 0x0EB, 0x0DD, 0x0BC, 0x090, 0x0B0, 0x0FC,
513 0x095, 0x076, 0x093, 0x046, 0x057, 0x02C, 0x02B, 0x050, 0x011, 0x00B, 0x0C1,
514 0x0F0, 0x0E7, 0x0D6, 0x021, 0x031, 0x0DE, 0x0FF, 0x0D8, 0x012, 0x0A6, 0x04D,
515 0x08A, 0x013, 0x043, 0x045, 0x038, 0x0D2, 0x087, 0x0A0, 0x0EF, 0x082, 0x0F1,
516 0x047, 0x089, 0x06A, 0x0C8, 0x054, 0x01B, 0x016, 0x07E, 0x079, 0x0BD, 0x06B,
517 0x091, 0x0A2, 0x071, 0x036, 0x0B7, 0x003, 0x03D, 0x072, 0x0C6, 0x044, 0x08B,
518 0x0CF, 0x015, 0x09F, 0x032, 0x0C4, 0x077, 0x083, 0x063, 0x020, 0x088, 0x0F6,
519 0x0AD, 0x0F3, 0x0E8, 0x04A, 0x0E9, 0x035, 0x01C, 0x05F, 0x019, 0x01F, 0x07D,
520 0x070, 0x0FB, 0x0D1, 0x051, 0x010, 0x0D3, 0x02E, 0x061, 0x09D, 0x05C, 0x02A,
521 0x042, 0x0BE, 0x0E6};
523static unsigned char Encode_table[256];
524static unsigned char Decode_table[256];
526static bool cm93_decode_table_created;
535 virtual wxDirTraverseResult OnFile(
const wxString &filename) {
536 wxString name = filename.AfterLast(wxFileName::GetPathSeparator()).Lower();
537 if (name ==
"cm93obj.dic") {
542 return wxDIR_CONTINUE;
545 virtual wxDirTraverseResult OnDir(
const wxString &WXUNUSED(dirname)) {
546 return wxDIR_CONTINUE;
553cm93_dictionary::cm93_dictionary() {
554 m_S57ClassArray = NULL;
556 m_GeomTypeArray = NULL;
558 m_ValTypeArray = NULL;
563bool cm93_dictionary::LoadDictionary(
const wxString &dictionary_dir) {
566 wxString dir(dictionary_dir);
567 bool ret_val =
false;
569 wxChar sep = wxFileName::GetPathSeparator();
570 if (dir.Last() != sep) dir.Append(sep);
577 sf.Append(
"CM93OBJ.DIC");
579 if (!wxFileName::FileExists(sf)) {
581 sf.Append(
"cm93obj.dic");
582 if (!wxFileName::FileExists(sf))
return false;
586 if (!file.Open(sf))
return false;
588 nline = file.GetLineCount();
590 if (!nline)
return false;
595 for (i = 0; i < nline; i++) {
596 line = file.GetLine(i);
598 wxStringTokenizer tkz(line,
"|");
602 wxString class_name = tkz.GetNextToken();
605 wxString token = tkz.GetNextToken();
607 token.ToLong(&liclass);
608 int iclass = liclass;
609 if (iclass > iclass_max) iclass_max = iclass;
612 wxString geo_type = tkz.GetNextToken();
616 m_max_class = iclass_max;
619 m_S57ClassArray =
new wxArrayString;
620 m_S57ClassArray->Add(
"NULLNM", iclass_max + 1);
623 m_GeomTypeArray = (
int *)malloc((iclass_max + 1) *
sizeof(int));
626 for (i = 0; i < nline; i++) {
627 line = file.GetLine(i);
629 wxStringTokenizer tkz(line,
"|");
633 wxString class_name = tkz.GetNextToken();
636 wxString token = tkz.GetNextToken();
638 token.ToLong(&liclass);
639 int iclass = liclass;
642 wxString geo_type = tkz.GetNextToken();
644 m_S57ClassArray->Insert(class_name, iclass);
645 m_S57ClassArray->RemoveAt(iclass + 1);
648 wxChar geo_type_primary = geo_type[0];
650 if (geo_type_primary ==
'A')
652 else if (geo_type_primary ==
'L')
654 else if (geo_type_primary ==
'P')
661 m_GeomTypeArray[iclass] = igeom_type;
669 sfa.Append(
"ATTRLUT.DIC");
671 if (!wxFileName::FileExists(sfa)) {
673 sfa.Append(
"attrlut.dic");
676 if (wxFileName::FileExists(sfa)) {
677 wxFFileInputStream filea(sfa);
683 while (!filea.Eof()) {
687 char a = filea.GetC();
688 if (filea.Eof())
break;
690 if (a == 0x0a)
break;
693 if (!line.StartsWith((
const wxChar *)
";")) {
694 wxStringTokenizer tkz(line,
"|");
697 wxString class_name = tkz.GetNextToken();
700 wxString token = tkz.GetNextToken();
702 token.ToLong(&liattr);
704 if (iattr > iattr_max) iattr_max = iattr;
709 m_max_attr = iattr_max;
715 m_AttrArray =
new wxArrayString;
716 m_AttrArray->Add(
"NULLNM", iattr_max + 1);
719 m_ValTypeArray = (
char *)malloc((iattr_max + 1) *
sizeof(char));
722 while (!filea.Eof()) {
726 char a = filea.GetC();
727 if (filea.Eof())
break;
729 if (a == 0x0a)
break;
732 if (!line.StartsWith((
const wxChar *)
";")) {
733 wxStringTokenizer tkz(line,
"|");
736 wxString attr_name = tkz.GetNextToken();
739 wxString token = tkz.GetNextToken();
741 token.ToLong(&liattr);
744 m_AttrArray->Insert(attr_name, iattr);
745 m_AttrArray->RemoveAt(iattr + 1);
748 token = tkz.GetNextToken();
749 token = tkz.GetNextToken();
750 token = tkz.GetNextToken();
751 token = tkz.GetNextToken().Trim();
754 if (token.IsSameAs(
"aFLOAT"))
756 else if (token.IsSameAs(
"aBYTE"))
758 else if (token.IsSameAs(
"aSTRING"))
760 else if (token.IsSameAs(
"aCMPLX"))
762 else if (token.IsSameAs(
"aLIST"))
764 else if (token.IsSameAs(
"aWORD10"))
766 else if (token.IsSameAs(
"aLONG"))
769 m_ValTypeArray[iattr] = atype;
783 sfa.Append(
"CM93ATTR.DIC");
785 if (!wxFileName::FileExists(sfa)) {
787 sfa.Append(
"cm93attr.dic");
790 if (wxFileName::FileExists(sfa)) {
791 wxFFileInputStream filea(sfa);
797 while (!filea.Eof()) {
801 char a = filea.GetC();
802 if (filea.Eof())
break;
804 if (a == 0x0a)
break;
807 if (line[0] !=
';') {
808 wxStringTokenizer tkz(line,
"|");
809 if (tkz.CountTokens()) {
811 wxString class_name = tkz.GetNextToken();
814 wxString token = tkz.GetNextToken();
816 token.ToLong(&liattr);
818 if (iattr > iattr_max) iattr_max = iattr;
823 m_max_attr = iattr_max;
829 m_AttrArray =
new wxArrayString;
830 m_AttrArray->Add(
"NULLNM", iattr_max + 1);
833 m_ValTypeArray = (
char *)malloc((iattr_max + 1) *
sizeof(char));
834 for (
int iat = 0; iat < iattr_max + 1; iat++) m_ValTypeArray[iat] =
'?';
837 while (!filea.Eof()) {
841 char a = filea.GetC();
842 if (filea.Eof())
break;
844 if (a == 0x0a)
break;
847 if (line[0] !=
';') {
848 wxStringTokenizer tkz(line,
"|\r\n");
849 if (tkz.CountTokens() >= 3) {
851 wxString attr_name = tkz.GetNextToken();
854 wxString token = tkz.GetNextToken();
856 token.ToLong(&liattr);
859 m_AttrArray->Insert(attr_name, iattr);
860 m_AttrArray->RemoveAt(iattr + 1);
862 token = tkz.GetNextToken().Trim();
865 if (token.IsSameAs(
"aFLOAT"))
867 else if (token.IsSameAs(
"aBYTE"))
869 else if (token.IsSameAs(
"aSTRING"))
871 else if (token.IsSameAs(
"aCMPLX"))
873 else if (token.IsSameAs(
"aLIST"))
875 else if (token.IsSameAs(
"aWORD10"))
877 else if (token.IsSameAs(
"aLONG"))
880 m_ValTypeArray[iattr] = atype;
893 wxString msg(
"Loaded CM93 Dictionary from ");
901wxString cm93_dictionary::GetClassName(
int iclass) {
902 if ((iclass > m_max_class) || (iclass < 0))
905 return (m_S57ClassArray->Item(iclass));
908wxString cm93_dictionary::GetAttrName(
int iattr) {
909 if ((iattr > m_max_attr) || (iattr < 0))
910 return (
"UnknownAttr");
912 return (m_AttrArray->Item(iattr));
916char cm93_dictionary::GetAttrType(
int iattr) {
917 if ((iattr > m_max_attr) || (iattr < 0))
920 return (m_ValTypeArray[iattr]);
923cm93_dictionary::~cm93_dictionary() {
924 delete m_S57ClassArray;
925 free(m_GeomTypeArray);
927 free(m_ValTypeArray);
932void CreateDecodeTable() {
934 for (i = 0; i < 256; i++) {
935 Encode_table[i] = Table_0[i] ^ 8;
938 for (i = 0; i < 256; i++) {
939 unsigned char a = Encode_table[i];
940 Decode_table[(int)a] = (
unsigned char)i;
944static int read_and_decode_bytes(FILE *stream,
void *p,
int nbytes) {
949 if (fread(p, nbytes, 1, stream) != 1)
return 0;
952 unsigned char *q = (
unsigned char *)p;
954 for (
int i = 0; i < nbytes; i++) {
955 unsigned char a = *q;
957 unsigned char c = Decode_table[b];
965static int read_and_decode_double(FILE *stream,
double *p) {
968 if (fread(&t,
sizeof(
double), 1, stream) != 1)
return 0;
971 unsigned char *q = (
unsigned char *)&t;
973 for (
unsigned int i = 0; i <
sizeof(double); i++) {
974 unsigned char a = *q;
976 unsigned char c = Decode_table[b];
988static int read_and_decode_int(FILE *stream,
int *p) {
991 if (fread(&t,
sizeof(
int), 1, stream) != 1)
return 0;
994 unsigned char *q = (
unsigned char *)&t;
996 for (
unsigned int i = 0; i <
sizeof(int); i++) {
997 unsigned char a = *q;
999 unsigned char c = Decode_table[b];
1011static int read_and_decode_ushort(FILE *stream,
unsigned short *p) {
1014 if (fread(&t,
sizeof(
unsigned short), 1, stream) != 1)
return 0;
1017 unsigned char *q = (
unsigned char *)&t;
1019 for (
unsigned int i = 0; i <
sizeof(
unsigned short); i++) {
1020 unsigned char a = *q;
1022 unsigned char c = Decode_table[b];
1036int Get_CM93_CellIndex(
double lat,
double lon,
int scale) {
1071 double lon1 = (lon + 360.) * 3.;
1072 while (lon1 >= 1080.0) lon1 -= 1080.0;
1073 unsigned short lon2 = (
unsigned short)floor(lon1 / dval);
1074 unsigned short lon3 = lon2 * dval;
1079 double lat1 = (lat * 3.) + 270. - 30;
1080 unsigned short lat2 = (
unsigned short)floor(lat1 / dval);
1081 unsigned short lat3 = lat2 * dval;
1083 retval += (lat3 + 30) * 10000;
1091void Get_CM93_Cell_Origin(
int cellindex,
int scale,
double *lat,
double *lon) {
1093 double idx1 = cellindex % 10000;
1094 double lont = (idx1 / 3.);
1099 int idx2 = cellindex / 10000;
1100 double lat1 = idx2 - 270.;
1106bool Is_CM93Cell_Present(wxString &fileprefix,
double lat,
double lon,
1112 switch (scale_index) {
1160 int cellindex = Get_CM93_CellIndex(lat, lon,
scale);
1165 int ilat = cellindex / 10000;
1166 int ilon = cellindex % 10000;
1168 int jlat = (((ilat - 30) / dval) * dval) + 30;
1169 int jlon = (ilon / dval) * dval;
1171 int ilatroot = (((ilat - 30) / 60) * 60) + 30;
1172 int ilonroot = (ilon / 60) * 60;
1175 fileroot.Printf(
"%04d%04d", ilatroot, ilonroot);
1176 appendOSDirSep(&fileroot);
1178 wxString sdir(fileprefix);
1183 tfile.Printf(
"?%03d%04d.", jlat, jlon);
1184 tfile += scale_char;
1187 if (!::wxDirExists(sdir)) {
1188 wxString old_scalechar(scale_char);
1189 wxString new_scalechar = old_scalechar.Lower();
1193 sdir += new_scalechar;
1196 if (::wxDirExists(sdir)) {
1199 wxArrayString file_array;
1200 int n_files = dir.GetAllFiles(sdir, &file_array, tfile, wxDIR_FILES);
1202 if (n_files)
return true;
1205 wxString old_scalechar(scale_char);
1206 wxString new_scalechar = old_scalechar.Lower();
1209 tfile1.Printf(
"?%03d%04d.", jlat, jlon);
1210 tfile1 += new_scalechar;
1212 int n_files1 = dir.GetAllFiles(sdir, &file_array, tfile1, wxDIR_FILES);
1214 if (n_files1)
return true;
1217 n_files = dir.GetAllFiles(sdir, &file_array, tfile +
".xz", wxDIR_FILES);
1219 if (n_files)
return true;
1225static bool read_header_and_populate_cib(FILE *stream,
Cell_Info_Block *pCIB) {
1234 memset((
void *)&header, 0,
sizeof(header));
1236 read_and_decode_double(stream, &header.lon_min);
1237 read_and_decode_double(stream, &header.lat_min);
1238 read_and_decode_double(stream, &header.lon_max);
1239 read_and_decode_double(stream, &header.lat_max);
1241 read_and_decode_double(stream, &header.easting_min);
1242 read_and_decode_double(stream, &header.northing_min);
1243 read_and_decode_double(stream, &header.easting_max);
1244 read_and_decode_double(stream, &header.northing_max);
1246 read_and_decode_ushort(stream, &header.usn_vector_records);
1247 read_and_decode_int(stream, &header.n_vector_record_points);
1248 read_and_decode_int(stream, &header.m_46);
1249 read_and_decode_int(stream, &header.m_4a);
1250 read_and_decode_ushort(stream, &header.usn_point3d_records);
1251 read_and_decode_int(stream, &header.m_50);
1252 read_and_decode_int(stream, &header.m_54);
1253 read_and_decode_ushort(stream, &header.usn_point2d_records);
1254 read_and_decode_ushort(stream, &header.m_5a);
1255 read_and_decode_ushort(stream, &header.m_5c);
1256 read_and_decode_ushort(stream, &header.usn_feature_records);
1258 read_and_decode_int(stream, &header.m_60);
1259 read_and_decode_int(stream, &header.m_64);
1260 read_and_decode_ushort(stream, &header.m_68);
1261 read_and_decode_ushort(stream, &header.m_6a);
1262 read_and_decode_ushort(stream, &header.m_6c);
1263 read_and_decode_int(stream, &header.m_nrelated_object_pointers);
1265 read_and_decode_int(stream, &header.m_72);
1266 read_and_decode_ushort(stream, &header.m_76);
1268 read_and_decode_int(stream, &header.m_78);
1269 read_and_decode_int(stream, &header.m_7c);
1273 double delta_x = header.easting_max - header.easting_min;
1275 delta_x += CM93_semimajor_axis_meters * 2.0 * PI;
1277 pCIB->transform_x_rate = delta_x / 65535;
1278 pCIB->transform_y_rate = (header.northing_max - header.northing_min) / 65535;
1280 pCIB->transform_x_origin = header.easting_min;
1281 pCIB->transform_y_origin = header.northing_min;
1283 pCIB->min_lat = header.lat_min;
1284 pCIB->min_lon = header.lon_min;
1292 pCIB->m_nfeature_records = header.usn_feature_records;
1293 pCIB->pobject_block =
1294 (
Object *)calloc(pCIB->m_nfeature_records *
sizeof(
Object), 1);
1296 pCIB->m_n_point2d_records = header.usn_point2d_records;
1297 pCIB->p2dpoint_array =
1300 pCIB->pprelated_object_block =
1301 (
Object **)malloc(header.m_nrelated_object_pointers *
sizeof(
Object *));
1303 pCIB->object_vector_record_descriptor_block =
1307 pCIB->attribute_block_top = (
unsigned char *)calloc(header.m_78, 1);
1309 pCIB->m_nvector_records = header.usn_vector_records;
1313 pCIB->pvector_record_block_top =
1316 pCIB->m_n_point3d_records = header.usn_point3d_records;
1320 pCIB->p3dpoint_array =
1326static bool read_vector_record_table(FILE *stream,
int count,
1331 cm93_point *q = pCIB->pvector_record_block_top;
1333 for (
int iedge = 0; iedge < count; iedge++) {
1336 unsigned short npoints;
1337 brv = !(read_and_decode_ushort(stream, &npoints) == 0);
1338 if (!brv)
return false;
1340 p->n_points = npoints;
1348 unsigned short x, y;
1349 for (
int index = 0; index < p->n_points; index++) {
1350 if (!read_and_decode_ushort(stream, &x))
return false;
1351 if (!read_and_decode_ushort(stream, &y))
return false;
1367 for (
int j = 0; j < p->n_points - 1; j++) {
1368 if (t->x >= p->x_max) p->x_max = t->x;
1370 if (t->x <= p->x_min) p->x_min = t->x;
1372 if (t->y >= p->y_max) p->y_max = t->y;
1374 if (t->y <= p->y_max) p->y_min = t->y;
1389static bool read_3dpoint_table(FILE *stream,
int count,
Cell_Info_Block *pCIB) {
1393 for (
int i = 0; i < count; i++) {
1394 unsigned short npoints;
1395 if (!read_and_decode_ushort(stream, &npoints))
return false;
1397 p->n_points = npoints;
1405 unsigned short x, y, z;
1406 for (
int index = 0; index < p->n_points; index++) {
1407 if (!read_and_decode_ushort(stream, &x))
return false;
1408 if (!read_and_decode_ushort(stream, &y))
return false;
1409 if (!read_and_decode_ushort(stream, &z))
return false;
1423static bool read_2dpoint_table(FILE *stream,
int count,
Cell_Info_Block *pCIB) {
1427 unsigned short x, y;
1428 for (
int index = 0; index < count; index++) {
1429 if (!read_and_decode_ushort(stream, &x))
return false;
1430 if (!read_and_decode_ushort(stream, &y))
return false;
1432 pCIB->p2dpoint_array[index].x = x;
1433 pCIB->p2dpoint_array[index].y = y;
1439static bool read_feature_record_table(FILE *stream,
int n_features,
1442 Object *pobj = pCIB->pobject_block;
1445 pCIB->object_vector_record_descriptor_block;
1448 pCIB->pprelated_object_block;
1451 unsigned char *puc_var10 = pCIB->attribute_block_top;
1454 unsigned char object_type;
1455 unsigned char geom_prim;
1456 unsigned short obj_desc_bytes = 0;
1459 unsigned short index;
1460 unsigned short n_elements;
1462 for (
int iobject = 0; iobject < n_features; iobject++) {
1464 read_and_decode_bytes(stream, &object_type, 1);
1465 read_and_decode_bytes(stream, &geom_prim,
1467 read_and_decode_ushort(stream,
1470 pobj->otype = object_type;
1471 pobj->geotype = geom_prim;
1473 switch (pobj->geotype & 0x0f) {
1476 if (!read_and_decode_ushort(stream, &n_elements))
return false;
1478 pobj->n_geom_elements = n_elements;
1479 t = (pobj->n_geom_elements * 2) + 2;
1480 obj_desc_bytes -= t;
1483 pobject_vector_collection;
1487 for (
unsigned short i = 0; i < pobj->n_geom_elements; i++) {
1488 if (!read_and_decode_ushort(stream, &index))
return false;
1490 if ((index & 0x1fff) > pCIB->m_nvector_records)
1496 pobject_vector_collection->pGeom_Description = u;
1497 pobject_vector_collection->segment_usage =
1498 (
unsigned char)(index >> 13);
1500 pobject_vector_collection++;
1508 if (!read_and_decode_ushort(
1509 stream, &n_elements))
1512 pobj->n_geom_elements = n_elements;
1513 t = (pobj->n_geom_elements * 2) + 2;
1514 obj_desc_bytes -= t;
1517 pobject_vector_collection;
1521 for (
unsigned short i = 0; i < pobj->n_geom_elements; i++) {
1522 unsigned short geometry_index;
1524 if (!read_and_decode_ushort(stream, &geometry_index))
return false;
1526 if ((geometry_index & 0x1fff) > pCIB->m_nvector_records)
1531 geometry_index & 0x1fff)];
1533 pobject_vector_collection->pGeom_Description = u;
1534 pobject_vector_collection->segment_usage =
1535 (
unsigned char)(geometry_index >> 13);
1537 pobject_vector_collection++;
1544 if (!read_and_decode_ushort(stream, &index))
return false;
1546 obj_desc_bytes -= 2;
1548 pobj->n_geom_elements = 1;
1550 pobj->pGeometry = &pCIB->p2dpoint_array[index];
1556 if (!read_and_decode_ushort(stream, &index))
return false;
1557 obj_desc_bytes -= 2;
1559 pobj->n_geom_elements = 1;
1562 &pCIB->point3d_descriptor_block[index];
1569 if ((pobj->geotype & 0x10) == 0x10)
1571 unsigned char nrelated;
1572 if (!read_and_decode_bytes(stream, &nrelated, 1))
return false;
1574 pobj->n_related_objects = nrelated;
1575 t = (pobj->n_related_objects * 2) + 1;
1576 obj_desc_bytes -= t;
1578 pobj->p_related_object_pointer_array = p_relob;
1579 p_relob += pobj->n_related_objects;
1581 Object **w = (
Object **)pobj->p_related_object_pointer_array;
1582 for (
unsigned char j = 0; j < pobj->n_related_objects; j++) {
1583 if (!read_and_decode_ushort(stream, &index))
return false;
1585 if (index > pCIB->m_nfeature_records)
1589 Object *prelated_object = &pCIB->pobject_block[index];
1590 *w = prelated_object;
1592 prelated_object->p_related_object_pointer_array =
1598 if ((pobj->geotype & 0x20) == 0x20) {
1599 unsigned short nrelated;
1600 if (!read_and_decode_ushort(stream, &nrelated))
return false;
1602 pobj->n_related_objects = (
unsigned char)(nrelated & 0xFF);
1603 obj_desc_bytes -= 2;
1606 if ((pobj->geotype & 0x40) == 0x40) {
1609 if ((pobj->geotype & 0x80) == 0x80)
1611 unsigned char nattr;
1612 if (!read_and_decode_bytes(stream, &nattr, 1))
return false;
1614 pobj->n_attributes = nattr;
1615 obj_desc_bytes -= 5;
1617 pobj->attributes_block = puc_var10;
1618 puc_var10 += obj_desc_bytes;
1620 puc10count += obj_desc_bytes;
1622 if (!read_and_decode_bytes(stream, pobj->attributes_block,
1626 if ((pobj->geotype & 0x0f) == 1) {
1637 printf(
"catch on read_feature_record_table\n");
1643bool Ingest_CM93_Cell(
const char *cell_file_name,
Cell_Info_Block *pCIB) {
1648 FILE *flstream = fopen(cell_file_name,
"rb");
1649 if (!flstream)
return false;
1651 fseek(flstream, 0, SEEK_END);
1652 file_length = ftell(flstream);
1656 FILE *stream = fopen(cell_file_name,
"rb");
1657 if (!stream)
return false;
1661 unsigned short word0 = 0;
1667 read_and_decode_ushort(stream,
1669 read_and_decode_int(stream, &int0);
1670 read_and_decode_int(stream, &int1);
1672 int test = word0 + int0 + int1;
1673 if (test != file_length) {
1680 if (!read_header_and_populate_cib(stream, pCIB)) {
1685 if (!read_vector_record_table(stream, pCIB->m_nvector_records, pCIB)) {
1690 if (!read_3dpoint_table(stream, pCIB->m_n_point3d_records, pCIB)) {
1695 if (!read_2dpoint_table(stream, pCIB->m_n_point2d_records, pCIB)) {
1700 if (!read_feature_record_table(stream, pCIB->m_nfeature_records, pCIB)) {
1723cm93chart::cm93chart() {
1724 m_ChartType = CHART_TYPE_CM93;
1727 if (!cm93_decode_table_created) {
1728 CreateDecodeTable();
1729 cm93_decode_table_created =
true;
1735 m_current_cell_vearray_offset = 0;
1737 m_ncontour_alloc = 100;
1738 m_pcontour_array = (
int *)malloc(m_ncontour_alloc *
sizeof(
int));
1748 m_pDrawBuffer = (wxPoint *)malloc(4 *
sizeof(wxPoint));
1749 m_nDrawBufferSize = 1;
1752 m_this_chart_context = (chart_context *)calloc(
sizeof(chart_context), 1);
1753 m_this_chart_context->chart =
this;
1757cm93chart::~cm93chart() {
1758 free(m_pcontour_array);
1762 free(m_pDrawBuffer);
1765void cm93chart::Unload_CM93_Cell() {
1766 free(m_CIB.pobject_block);
1768 free(m_CIB.p2dpoint_array);
1769 free(m_CIB.pprelated_object_block);
1770 free(m_CIB.object_vector_record_descriptor_block);
1771 free(m_CIB.attribute_block_top);
1772 free(m_CIB.edge_vector_descriptor_block);
1773 free(m_CIB.pvector_record_block_top);
1774 free(m_CIB.point3d_descriptor_block);
1775 free(m_CIB.p3dpoint_array);
1784double cm93chart::GetNormalScaleMin(
double canvas_scale_factor,
1785 bool b_allow_overzoom) {
1786 switch (GetNativeScale()) {
1808double cm93chart::GetNormalScaleMax(
double canvas_scale_factor,
1816 switch (GetNativeScale()) {
1838void cm93chart::GetPointPix(ObjRazRules *rzRules,
float north,
float east,
1840 wxPoint2DDouble en(east, north);
1841 GetPointPix(rzRules, &en, r, 1);
1844void cm93chart::GetPointPix(ObjRazRules *rzRules, wxPoint2DDouble *en,
1845 wxPoint *r,
int nPoints) {
1846 S57Obj *obj = rzRules->obj;
1848 double xr = obj->x_rate;
1849 double xo = obj->x_origin;
1850 double yr = obj->y_rate;
1851 double yo = obj->y_origin;
1853 if (m_vp_current.m_projection_type == PROJECTION_MERCATOR) {
1854 if (m_vp_current.GetBBox().GetMaxLon() >= 180. &&
1855 rzRules->obj->BBObj.GetMaxLon() < m_vp_current.GetBBox().GetMinLon())
1856 xo += mercator_k0 * WGS84_semimajor_axis_meters * 2.0 * PI;
1857 else if ((m_vp_current.GetBBox().GetMinLon() <= -180. &&
1858 rzRules->obj->BBObj.GetMinLon() >
1859 m_vp_current.GetBBox().GetMaxLon()) ||
1860 (rzRules->obj->BBObj.GetMaxLon() >= 180 &&
1861 m_vp_current.GetBBox().GetMinLon() <= 0.))
1862 xo -= mercator_k0 * WGS84_semimajor_axis_meters * 2.0 * PI;
1864 for (
int i = 0; i < nPoints; i++) {
1865 double valx = (en[i].m_x * xr) + xo;
1866 double valy = (en[i].m_y * yr) + yo;
1868 r[i].x = ((valx - m_easting_vp_center) * m_view_scale_ppm) +
1869 m_pixx_vp_center + 0.5;
1870 r[i].y = m_pixy_vp_center -
1871 ((valy - m_northing_vp_center) * m_view_scale_ppm) + 0.5;
1874 for (
int i = 0; i < nPoints; i++) {
1875 double valx = (en[i].m_x * xr) + xo;
1876 double valy = (en[i].m_y * yr) + yo;
1879 fromSM(valx - m_easting_vp_center, valy - m_northing_vp_center,
1880 m_vp_current.
clat, m_vp_current.
clon, &lat, &lon);
1882 double rotation = m_vp_current.
rotation;
1883 m_vp_current.SetRotationAngle(0);
1885 m_vp_current.SetRotationAngle(rotation);
1890void cm93chart::GetPixPoint(
int pixx,
int pixy,
double *plat,
double *plon,
1903 double xp = (dx * cos(vpt->
skew)) - (dy * sin(vpt->
skew));
1904 double yp = (dy * cos(vpt->
skew)) + (dx * sin(vpt->
skew));
1910 fromSM(d_east, d_north, vpt->
clat, vpt->
clon, &slat, &slon);
1912 if (slon > 360.) slon -= 360.;
1920 if (IsCacheValid()) {
1930 vp_last.
GetLLFromPix(wxPoint(round(p.m_x), round(p.m_y)), &xlat, &xlon);
1932 double prev_easting_c, prev_northing_c;
1933 toSM(vp_last.
clat, vp_last.
clon, ref_lat, ref_lon, &prev_easting_c,
1936 double easting_c, northing_c;
1937 toSM(vp_proposed.
clat, vp_proposed.
clon, ref_lat, ref_lon, &easting_c,
1940 double delta_pix_x =
1942 int dpix_x = (int)round(delta_pix_x);
1943 double dpx = dpix_x;
1945 double delta_pix_y =
1947 int dpix_y = (int)round(delta_pix_y);
1948 double dpy = dpix_y;
1950 double c_east_d = (dpx / vp_proposed.
view_scale_ppm) + prev_easting_c;
1951 double c_north_d = (dpy / vp_proposed.
view_scale_ppm) + prev_northing_c;
1954 fromSM(c_east_d, c_north_d, ref_lat, ref_lon, &xlat, &xlon);
1956 vp_proposed.
clon = xlon;
1957 vp_proposed.
clat = xlat;
1970void cm93chart::SetVPParms(
const ViewPort &vpt) {
1971 if (m_vp_current == vpt) {
1982 toSM(vpt.
clat, vpt.
clon, ref_lat, ref_lon, &m_easting_vp_center,
1983 &m_northing_vp_center);
1985 vp_transform.easting_vp_center = m_easting_vp_center;
1986 vp_transform.northing_vp_center = m_northing_vp_center;
1991 LLBBox box = vptl.GetBBox();
1992 double ll_lon = box.GetMinLon();
1993 double ll_lat = box.GetMinLat();
1995 double ur_lon = box.GetMaxLon();
1996 double ur_lat = box.GetMaxLat();
1999 "cm93chart::SetVPParms ll_lon: %g ll_lat: %g ur_lon: %g ur_lat: "
2001 ll_lon, ll_lat, ur_lon, ur_lat, m_dval);
2005 std::vector<int> vpcells = GetVPCellArray(vpt);
2011 for (
unsigned int i = 0; i < vpcells.size(); i++) {
2012 bcell_is_in =
false;
2013 for (
unsigned int j = 0; j < m_cells_loaded_array.size(); j++) {
2014 if (vpcells[i] == m_cells_loaded_array[j]) {
2022#ifndef __OCPN__ANDROID__
2023 AbstractPlatform::ShowBusySpinner();
2025 int cell_index = vpcells[i];
2027 if (loadcell_in_sequence(cell_index,
'0'))
2029 ProcessVectorEdges();
2032 ForceEdgePriorityEvaluate();
2034 m_cells_loaded_array.push_back(cell_index);
2039 char loadcell_key =
'A';
2043 while (loadcell_in_sequence(cell_index, loadcell_key)) {
2044 ProcessVectorEdges();
2045 CreateObjChain(cell_index, (
int)loadcell_key, vpt.
view_scale_ppm);
2047 ForceEdgePriorityEvaluate();
2049 if (std::find(m_cells_loaded_array.begin(), m_cells_loaded_array.end(),
2050 cell_index) == m_cells_loaded_array.end())
2051 m_cells_loaded_array.push_back(cell_index);
2058 AssembleLineGeometry();
2060 ClearDepthContourArray();
2061 BuildDepthContourArray();
2064 m_this_chart_context->m_pvc_hash = &Get_vc_hash();
2065 m_this_chart_context->m_pve_hash = &Get_ve_hash();
2067 m_this_chart_context->pFloatingATONArray = pFloatingATONArray;
2068 m_this_chart_context->pRigidATONArray = pRigidATONArray;
2069 m_this_chart_context->chart =
this;
2070 m_this_chart_context->chart_type = GetChartType();
2072 m_this_chart_context->safety_contour = m_next_safe_cnt;
2073 m_this_chart_context->vertex_buffer = GetLineVertexBuffer();
2074 m_this_chart_context->pt2GetAssociatedObjects =
2075 &s57chart::GetAssociatedObjects;
2080 ObjRazRules *top = razRules[i][j];
2082 if (top->obj) top->obj->m_chart_context = m_this_chart_context;
2088 AbstractPlatform::HideBusySpinner();
2093std::vector<int> cm93chart::GetVPCellArray(
const ViewPort &vpt) {
2096 LLBBox box = vptl.GetBBox();
2097 double ll_lon = box.GetMinLon();
2098 double ll_lat = box.GetMinLat();
2100 double ur_lon = box.GetMaxLon();
2101 double ur_lat = box.GetMaxLat();
2104 ur_lat = wxMin(ur_lat, 79.99999);
2107 ur_lat = wxMin(ur_lat, 79.99999);
2116 std::vector<int> vpcells;
2118 int lower_left_cell = Get_CM93_CellIndex(ll_lat, ll_lon, GetNativeScale());
2119 vpcells.push_back(lower_left_cell);
2122 printf(
"cm93chart::GetVPCellArray Adding %d\n", lower_left_cell);
2125 Get_CM93_Cell_Origin(lower_left_cell, GetNativeScale(), &rlat, &rlon);
2130 int loni_0 = (int)wxRound(rlon * 3);
2131 int loni_20 = loni_0 + (int)m_dval;
2132 int lati_20 = (int)wxRound(rlat * 3);
2134 while (lati_20 < (ur_lat * 3.)) {
2135 while (loni_20 < (ur_lon * 3.)) {
2136 unsigned int next_lon = loni_20 + 1080;
2137 while (next_lon >= 1080) next_lon -= 1080;
2139 unsigned int next_cell = next_lon;
2141 next_cell += (lati_20 + 270) * 10000;
2143 vpcells.push_back((
int)next_cell);
2145 printf(
"cm93chart::GetVPCellArray Adding %d\n", next_cell);
2147 loni_20 += (int)m_dval;
2149 lati_20 += (int)m_dval;
2156void cm93chart::ProcessVectorEdges() {
2159 auto &vehash = Get_ve_hash();
2161 m_current_cell_vearray_offset =
2165 for (
int iedge = 0; iedge < m_CIB.m_nvector_records; iedge++) {
2166 VE_Element *vep =
new VE_Element;
2167 vep->index = iedge + m_current_cell_vearray_offset;
2168 vep->nCount = pgd->n_points;
2169 vep->pPoints = NULL;
2170 vep->max_priority = -99;
2172 if (pgd->n_points) {
2173 float *pPoints = (
float *)malloc(pgd->n_points * 2 *
sizeof(
float));
2174 vep->pPoints = pPoints;
2179 double east_max = -1e7;
2180 double east_min = 1e7;
2181 double north_max = -1e7;
2182 double north_min = 1e7;
2184 for (
int ip = 0; ip < pgd->n_points; ip++) {
2185 *pPoints++ = ppt->x;
2186 *pPoints++ = ppt->y;
2188 east_max = wxMax(east_max, ppt->x);
2189 east_min = wxMin(east_min, ppt->x);
2190 north_max = wxMax(north_max, ppt->y);
2191 north_min = wxMin(north_min, ppt->y);
2197 double lat1, lon1, lat2, lon2;
2203 Transform(&p, 0, 0, &lat1, &lon1);
2207 Transform(&p, 0, 0, &lat2, &lon2);
2212 vep->edgeBBox.Set(lat1, lon1, lat2, lon2);
2215 vehash[vep->index] = vep;
2221int cm93chart::CreateObjChain(
int cell_index,
int subcell,
2222 double view_scale_ppm) {
2224 LUPname LUP_Name = PAPER_CHART;
2226 m_CIB.m_cell_mcovr_list.Clear();
2230 Object *pobjectDef = m_CIB.pobject_block;
2231 m_CIB.b_have_offsets =
false;
2233 m_CIB.b_have_user_offsets =
false;
2239 double scale = top_frame::Get()->GetBestVPScale(
this);
2240 int nativescale = GetNativeScale();
2242 while (iObj < m_CIB.m_nfeature_records) {
2243 if ((pobjectDef != NULL)) {
2244 Extended_Geometry *xgeom = BuildGeom(pobjectDef, NULL, iObj);
2249 CreateS57Obj(cell_index, iObj, subcell, pobjectDef, m_pDict, xgeom,
2250 ref_lat, ref_lon, GetNativeScale(), view_scale_ppm);
2253 wxString objnam = obj->GetAttrValueAsString(
"OBJNAM");
2254 wxString fe_name = wxString(obj->FeatureName, wxConvUTF8);
2255 if (fe_name ==
"_texto") objnam = obj->GetAttrValueAsString(
"_texta");
2256 if (objnam.Len() > 0) {
2257 wxString cellname = wxString::Format(
"%i_%i", cell_index, subcell);
2258 SendVectorChartObjectInfo(cellname, fe_name, objnam, obj->m_lat,
2259 obj->m_lon,
scale, nativescale);
2262 if (GEO_POINT == obj->Primitive_type) {
2264 if ((!strncmp(obj->FeatureName,
"LITFLT", 6)) ||
2265 (!strncmp(obj->FeatureName,
"LITVES", 6)) ||
2266 (!strncmp(obj->FeatureName,
"BOY", 3))) {
2267 pFloatingATONArray->Add(obj);
2271 if (!strncmp(obj->FeatureName,
"BCN", 3)) pRigidATONArray->Add(obj);
2274 if ((!strncmp(obj->FeatureName,
"LIT", 3)) ||
2275 (!strncmp(obj->FeatureName,
"LIGHTS", 6)) ||
2276 (!strncmp(obj->FeatureName,
"BCN", 3)) ||
2277 (!strncmp(obj->FeatureName,
"_slgto", 6)) ||
2278 (!strncmp(obj->FeatureName,
"_boygn", 6)) ||
2279 (!strncmp(obj->FeatureName,
"_bcngn", 6)) ||
2280 (!strncmp(obj->FeatureName,
"_extgn", 6)) ||
2281 (!strncmp(obj->FeatureName,
"TOWERS", 6)) ||
2282 (!strncmp(obj->FeatureName,
"BOY", 3))) {
2283 obj->bIsAton =
true;
2289 if (GEO_AREA == obj->Primitive_type) {
2290 if (!strncmp(obj->FeatureName,
"DEPARE", 6) ||
2291 !strncmp(obj->FeatureName,
"DRGARE", 6))
2292 obj->bIsAssociable =
true;
2300 switch (obj->Primitive_type) {
2304 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
2305 LUP_Name = PAPER_CHART;
2307 LUP_Name = SIMPLIFIED;
2309 if (m_b2pointLUPS) {
2311 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
2312 LUPO_Name = SIMPLIFIED;
2314 LUPO_Name = PAPER_CHART;
2318 ps52plib->S52_LUPLookup(LUPO_Name, obj->FeatureName, obj);
2320 ps52plib->_LUP2rules(LUPO, obj);
2321 _insertRules(obj, LUPO,
this);
2331 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
2332 LUP_Name = PLAIN_BOUNDARIES;
2334 LUP_Name = SYMBOLIZED_BOUNDARIES;
2338 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
2339 LUPO_Name = SYMBOLIZED_BOUNDARIES;
2341 LUPO_Name = PLAIN_BOUNDARIES;
2345 ps52plib->S52_LUPLookup(LUPO_Name, obj->FeatureName, obj);
2347 ps52plib->_LUP2rules(LUPO, obj);
2348 _insertRules(obj, LUPO,
this);
2354 LUP = ps52plib->S52_LUPLookup(LUP_Name, obj->FeatureName, obj);
2358 wxString msg(obj->FeatureName, wxConvUTF8);
2359 msg.Prepend(
" CM93 could not find LUP for ");
2360 LogMessageOnce(msg);
2362 if (0 == obj->nRef)
delete obj;
2365 ps52plib->_LUP2rules(LUP, obj);
2368 _insertRules(obj, LUP,
this);
2371 obj->m_DisplayCat = LUP->DISC;
2374 obj->m_DPRI = LUP->DPRI -
'0';
2377 obj->m_chart_context = m_this_chart_context;
2396InitReturn cm93chart::Init(
const wxString &name, ChartInitFlag flags) {
2398 m_Description = m_FullPath;
2400 wxFileName fn(name);
2402 if (!m_prefix.Len())
2403 m_prefix = fn.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
2405 m_scalechar = fn.GetExt();
2410 switch ((m_scalechar.mb_str())[(
size_t)0]) {
2440 m_Chart_Scale =
scale;
2442 switch (GetNativeScale()) {
2473 wxString data =
"CM93Chart ";
2474 data.Append(m_scalechar);
2476 s.Printf(
" 1/%d", m_Chart_Scale);
2481 if (
scale != 20000000)
2482 m_pcovr_set->Init(m_scalechar.mb_str()[(
size_t)0], m_prefix);
2484 if (flags == THUMB_ONLY) {
2492 if (flags == HEADER_ONLY)
return CreateHeaderDataFromCM93Cell();
2497 if (m_pManager->Loadcm93Dictionary(name))
2498 m_pDict = m_pManager->m_pcm93Dict;
2500 wxLogMessage(
" CM93Chart Init cannot locate CM93 dictionary.");
2501 return INIT_FAIL_REMOVE;
2506 bReadyToRender =
true;
2511Extended_Geometry *cm93chart::BuildGeom(
Object *pobject,
2512 wxFileOutputStream *postream,
2519 int geom_type_maybe = pobject->geotype;
2521 switch (geom_type_maybe) {
2559 Extended_Geometry *ret_ptr =
new Extended_Geometry;
2561 int lon_max, lat_max, lon_min, lat_min;
2573 int nsegs = pobject->n_geom_elements;
2575 ret_ptr->n_vector_indices = nsegs;
2576 ret_ptr->pvector_index = (
int *)malloc(nsegs * 3 *
sizeof(
int));
2579 int n_maxvertex = 0;
2580 for (
int i = 0; i < nsegs; i++) {
2583 n_maxvertex += pgd->n_points;
2589 wxPoint2DDouble *pPoints =
2590 (wxPoint2DDouble *)calloc((n_maxvertex) *
sizeof(wxPoint2DDouble), 1);
2593 int n_prev_vertex_index = 1;
2594 bool bnew_ring =
true;
2603 cur_end_point.x = 1;
2604 cur_end_point.y = 1;
2606 int n_max_points = -1;
2607 while (iseg < nsegs) {
2608 int type_seg = psegs[iseg].segment_usage;
2613 int npoints = pgd->n_points;
2616 n_max_points = wxMax(n_max_points, npoints);
2622 if ((type_seg & 4) == 0)
2623 start_point = rseg[0];
2625 start_point = rseg[npoints - 1];
2628 if (((type_seg & 4) == 0)) {
2629 cur_end_point = rseg[npoints - 1];
2630 for (
int j = 0; j < npoints; j++) {
2634 lon_max = wxMax(lon_max, rseg[j].x);
2635 lon_min = wxMin(lon_min, rseg[j].x);
2636 lat_max = wxMax(lat_max, rseg[j].y);
2637 lat_min = wxMin(lat_min, rseg[j].y);
2640 pPoints[ip].m_x = rseg[j].x;
2641 pPoints[ip].m_y = rseg[j].y;
2644 }
else if ((type_seg & 4) == 4)
2646 cur_end_point = rseg[0];
2647 for (
int j = npoints - 1; j >= 0; j--) {
2651 lon_max = wxMax(lon_max, rseg[j].x);
2652 lon_min = wxMin(lon_min, rseg[j].x);
2653 lat_max = wxMax(lat_max, rseg[j].y);
2654 lat_min = wxMin(lat_min, rseg[j].y);
2657 pPoints[ip].m_x = rseg[j].x;
2658 pPoints[ip].m_y = rseg[j].y;
2665 ret_ptr->pvector_index[iseg * 3 + 0] =
2667 ret_ptr->pvector_index[iseg * 3 + 1] =
2668 pgd->index + m_current_cell_vearray_offset;
2669 ret_ptr->pvector_index[iseg * 3 + 2] =
2672 if ((cur_end_point.x == start_point.x) &&
2673 (cur_end_point.y == start_point.y)) {
2678 int nRingVertex = ip - n_prev_vertex_index;
2681 if (ncontours > m_ncontour_alloc - 1) {
2682 m_ncontour_alloc *= 2;
2683 int *tmp = m_pcontour_array;
2684 m_pcontour_array = (
int *)realloc(m_pcontour_array,
2685 m_ncontour_alloc *
sizeof(
int));
2691 m_pcontour_array[ncontours] = nRingVertex;
2694 n_prev_vertex_index = ip;
2700 ret_ptr->n_max_edge_points = n_max_points;
2702 ret_ptr->n_contours =
2705 if (0 == ncontours) ncontours = 1;
2706 ret_ptr->contour_array = (
int *)malloc(ncontours *
sizeof(
int));
2707 memcpy(ret_ptr->contour_array, m_pcontour_array, ncontours *
sizeof(
int));
2709 ret_ptr->vertex_array = pPoints;
2710 ret_ptr->n_max_vertex = n_maxvertex;
2712 ret_ptr->pogrGeom = NULL;
2714 ret_ptr->xmin = lon_min;
2715 ret_ptr->xmax = lon_max;
2716 ret_ptr->ymin = lat_min;
2717 ret_ptr->ymax = lat_max;
2725 ret_ptr->pogrGeom = NULL;
2727 ret_ptr->pointx = pt->x;
2728 ret_ptr->pointy = pt->y;
2737 int nsegs = pobject->n_geom_elements;
2739 ret_ptr->n_vector_indices = nsegs;
2740 ret_ptr->pvector_index = (
int *)malloc(nsegs * 3 *
sizeof(
int));
2743 int n_maxvertex = 0;
2744 for (
int imseg = 0; imseg < nsegs; imseg++) {
2748 n_maxvertex += pgd->n_points;
2752 wxPoint2DDouble *pPoints =
2753 (wxPoint2DDouble *)malloc(n_maxvertex *
sizeof(wxPoint2DDouble));
2758 int lon_max, lat_max, lon_min, lat_min;
2763 int n_max_points = -1;
2765 for (
int iseg = 0; iseg < nsegs; iseg++) {
2766 int type_seg = psegs->segment_usage;
2773 int npoints = pgd->n_points;
2776 n_max_points = wxMax(n_max_points, npoints);
2778 if (((type_seg & 4) != 4)) {
2779 for (
int j = 0; j < npoints; j++) {
2780 lon_max = wxMax(lon_max, rseg[j].x);
2781 lon_min = wxMin(lon_min, rseg[j].x);
2782 lat_max = wxMax(lat_max, rseg[j].y);
2783 lat_min = wxMin(lat_min, rseg[j].y);
2785 pPoints[ip].m_x = rseg[j].x;
2786 pPoints[ip].m_y = rseg[j].y;
2791 else if ((type_seg & 4) == 4)
2793 for (
int j = npoints - 1; j >= 0; j--) {
2794 lon_max = wxMax(lon_max, rseg[j].x);
2795 lon_min = wxMin(lon_min, rseg[j].x);
2796 lat_max = wxMax(lat_max, rseg[j].y);
2797 lat_min = wxMin(lat_min, rseg[j].y);
2799 pPoints[ip].m_x = rseg[j].x;
2800 pPoints[ip].m_y = rseg[j].y;
2805 ret_ptr->pvector_index[iseg * 3 + 0] =
2807 ret_ptr->pvector_index[iseg * 3 + 1] =
2808 pgd->index + m_current_cell_vearray_offset;
2809 ret_ptr->pvector_index[iseg * 3 + 2] =
2814 ret_ptr->n_max_edge_points = n_max_points;
2816 ret_ptr->vertex_array = pPoints;
2817 ret_ptr->n_max_vertex = n_maxvertex;
2819 ret_ptr->pogrGeom = NULL;
2821 ret_ptr->xmin = lon_min;
2822 ret_ptr->xmax = lon_max;
2823 ret_ptr->ymin = lat_min;
2824 ret_ptr->ymax = lat_max;
2832 int npoints = pgd->n_points;
2835 OGRMultiPoint *pSMP =
new OGRMultiPoint;
2839 for (
int ip = 0; ip < npoints; ip++) {
2844 zp = double(z - 12000);
2848 OGRPoint *ppoint =
new OGRPoint(rseg[ip].x, rseg[ip].y, zp);
2849 pSMP->addGeometryDirectly(ppoint);
2851 lon_max = wxMax(lon_max, rseg[ip].x);
2852 lon_min = wxMin(lon_min, rseg[ip].x);
2853 lat_max = wxMax(lat_max, rseg[ip].y);
2854 lat_min = wxMin(lat_min, rseg[ip].y);
2857 ret_ptr->pogrGeom = pSMP;
2859 ret_ptr->xmin = lon_min;
2860 ret_ptr->xmax = lon_max;
2861 ret_ptr->ymin = lat_min;
2862 ret_ptr->ymax = lat_max;
2872 wxPrintf(
"Unexpected geomtype %d for Feature %d\n", geomtype, iobject);
2881void cm93chart::Transform(
cm93_point *s,
double trans_x,
double trans_y,
2882 double *lat,
double *lon) {
2884 double valx = (s->x * m_CIB.transform_x_rate) + m_CIB.transform_x_origin;
2885 double valy = (s->y * m_CIB.transform_y_rate) + m_CIB.transform_y_origin;
2893 (2.0 * atan(exp(valy / CM93_semimajor_axis_meters)) - PI / 2.) / DEGREE;
2894 *lon = (valx / (DEGREE * CM93_semimajor_axis_meters));
2899 m_block = (
unsigned char *)
block;
2903unsigned char *cm93_attr_block::GetNextAttr() {
2905 unsigned char *ret_val = m_block + m_cptr;
2909 unsigned char iattr = *(m_block + m_cptr);
2913 char vtype = m_pDict->GetAttrType(iattr);
2926 while (*(m_block + m_cptr)) m_cptr++;
2943 while (*(m_block + m_cptr)) m_cptr++;
2949 unsigned char nl = *(m_block + m_cptr);
2976wxString ParseSLGTA(wxString &val) {
2981 wxStringTokenizer tkz(val,
"|");
2983 s = tkz.GetNextToken();
2984 s = tkz.GetNextToken();
2985 s = tkz.GetNextToken();
2988 wxString sc, st, sp;
3001 else if (s[0] ==
'G') {
3004 }
else if (s.Mid(0, 3) ==
"W/O") {
3010 }
else if (s.Mid(0, 5) ==
"LIGHT") {
3015 if (val.Find(
"Spar") != wxNOT_FOUND) {
3019 if (val.Find(
"SPAR") != wxNOT_FOUND) {
3024 if ((type == 2) && (color == 3))
3031 sprintf(line,
" %s (%c) = %s",
"COLOUR",
'I', (
const char *)sc.mb_str());
3032 result += wxString(line, wxConvUTF8);
3035 sprintf(line,
" %s (%c) = %s",
"BOYSHP",
'I',
"4");
3036 result += wxString(line, wxConvUTF8);
3042 sprintf(line,
" %s (%c) = %s",
"BOYSHP",
'I', (
const char *)st.mb_str());
3043 result += wxString(line, wxConvUTF8);
3046 sprintf(line,
" %s (%c) = %s",
"COLOUR",
'I',
"2");
3047 result += wxString(line, wxConvUTF8);
3053 sprintf(line,
" %s (%c) = %s",
"COLPAT",
'I', (
const char *)sp.mb_str());
3054 result += wxString(line, wxConvUTF8);
3061wxString ParseTEXTA(wxString &val) {
3065 if (val.Contains(
"WK S")) {
3066 sprintf(line,
" %s (%c) = %s",
"WRKATT",
'I',
"1");
3067 result += wxString(line, wxConvUTF8);
3074void cm93chart::translate_colmar(
const wxString &sclass,
3075 S57attVal *pattValTmp) {
3076 int *pcur_attr = (
int *)pattValTmp->value;
3077 int cur_attr = *pcur_attr;
3140 if (lstring.Len()) {
3141 free(pattValTmp->value);
3143 pattValTmp->valType = OGR_STR;
3144 pattValTmp->value = strdup(lstring.mb_str());
3148S57Obj *cm93chart::CreateS57Obj(
int cell_index,
int iobject,
int subcell,
3150 Extended_Geometry *xgeom,
double ref_lat,
3151 double ref_lon,
double scale,
3152 double view_scale_ppm) {
3153#define MAX_HDR_LINE 4000
3157 int npub_year = 1993;
3159 int iclass = pobject->otype;
3160 int geomtype = pobject->geotype & 0x0f;
3162 double tmp_transform_x = 0.;
3163 double tmp_transform_y = 0.;
3166 double trans_WGS84_offset_x = 0.;
3167 double trans_WGS84_offset_y = 0.;
3169 wxString sclass = pDict->GetClassName(iclass);
3170 if (sclass ==
"Unknown") {
3172 msg.Printf(
" CM93 Error...object type %d not found in CM93OBJ.DIC",
3179 wxString sclass_sub = sclass;
3182 if (sclass.IsSameAs(
"ITDARE")) sclass_sub =
"DEPARE";
3184 if (sclass.IsSameAs(
"_m_sor")) sclass_sub =
"M_COVR";
3186 if (sclass.IsSameAs(
"SPOGRD")) sclass_sub =
"DMPGRD";
3188 if (sclass.IsSameAs(
"FSHHAV")) sclass_sub =
"FSHFAC";
3190 if (sclass.IsSameAs(
"OFSPRD")) sclass_sub =
"CTNARE";
3193 S57Obj *pobj =
new S57Obj();
3195 pobj->Index = iobject;
3198 strncpy(u, sclass_sub.mb_str(), 199);
3200 memcpy(pobj->FeatureName, u, 7);
3202 pobj->attVal =
new wxArrayOfS57attVal();
3206 for (
int jattr = 0; jattr < pobject->n_attributes; jattr++) {
3207 unsigned char *curr_attr = pab.GetNextAttr();
3209 unsigned char iattr = *curr_attr;
3211 wxString sattr = pDict->GetAttrName(iattr);
3213 char vtype = pDict->GetAttrType(iattr);
3215 unsigned char *aval = curr_attr + 1;
3228 S57attVal *pattValTmp =
new S57attVal;
3233 pAVI = (
int *)malloc(
sizeof(
int));
3235 pattValTmp->valType = OGR_INT;
3236 pattValTmp->value = pAVI;
3239 pb = (
unsigned char *)aval;
3240 pAVI = (
int *)malloc(
sizeof(
int));
3242 pattValTmp->valType = OGR_INT;
3243 pattValTmp->value = pAVI;
3246 pw = (
unsigned short *)aval;
3250 pAVR = (
double *)malloc(
sizeof(
double));
3251 *pAVR = dival / 10.;
3252 pattValTmp->valType = OGR_REAL;
3253 pattValTmp->value = pAVR;
3257 pAVI = (
int *)malloc(
sizeof(
int));
3259 pattValTmp->valType = OGR_INT;
3260 pattValTmp->value = pAVI;
3264 pAVS = strdup((
char *)aval);
3265 pattValTmp->valType = OGR_STR;
3266 pattValTmp->value = pAVS;
3270 pAVS = strdup((
const char *)&aval[3]);
3271 pattValTmp->valType = OGR_STR;
3272 pattValTmp->value = pAVS;
3275 pb = (
unsigned char *)aval;
3276 unsigned char nl = *pb++;
3279 for (
int i = 0; i < nl; i++) {
3280 sprintf(vi,
"%d,", *pb++);
3283 if (strlen(val)) val[strlen(val) - 1] = 0;
3286 pattValTmp->valType = OGR_STR;
3287 pattValTmp->value = pAVS;
3291 pAVR = (
double *)malloc(
sizeof(
double));
3295 float __attribute__((aligned(16))) tf1;
3296 unsigned char *pucf = (
unsigned char *)pf;
3298 memcpy(&tf1, pucf, sizeof(
float));
3304 pattValTmp->valType = OGR_REAL;
3305 pattValTmp->value = pAVR;
3313 if (sattr.IsSameAs(
"COLMAR")) {
3314 translate_colmar(sclass, pattValTmp);
3319 if (pattValTmp->valType == OGR_INT &&
3320 (sattr.IsSameAs(
"QUASOU") || sattr.IsSameAs(
"CATLIT"))) {
3321 int v = *(
int *)pattValTmp->value;
3322 free(pattValTmp->value);
3323 sprintf(val,
"%d", v);
3325 pattValTmp->valType = OGR_STR;
3326 pattValTmp->value = pAVS;
3330 if (sclass.IsSameAs(
"$AREAS") && (vtype ==
'S') &&
3331 sattr.IsSameAs(
"$SCODE")) {
3332 if (!strcmp((
char *)pattValTmp->value,
"II25")) {
3333 free(pattValTmp->value);
3334 pattValTmp->value = strdup(
"BACKGROUND");
3339 if (sattr.IsSameAs(
"RECDAT") || sattr.IsSameAs(
"_dgdat")) {
3340 if (sclass_sub.IsSameAs(
"M_COVR") && (vtype ==
'S')) {
3341 wxString pub_date((
char *)pattValTmp->value, wxConvUTF8);
3344 upd.ParseFormat(pub_date,
"%Y%m%d");
3345 if (!upd.IsValid()) upd.ParseFormat(
"20000101",
"%Y%m%d");
3348 pub_date.Truncate(4);
3351 pub_date.ToLong(&nyear);
3357 if (sclass_sub.IsSameAs(
"M_COVR") && (vtype ==
'R')) {
3358 if (sattr.IsSameAs(
"_wgsox")) {
3359 tmp_transform_x = *(
double *)pattValTmp->value;
3360 if (fabs(tmp_transform_x) > 1.0)
3361 m_CIB.b_have_offsets =
true;
3362 }
else if (sattr.IsSameAs(
"_wgsoy")) {
3363 tmp_transform_y = *(
double *)pattValTmp->value;
3364 if (fabs(tmp_transform_y) > 1.0) m_CIB.b_have_offsets =
true;
3369 wxASSERT(sattr.Len() == 6);
3370 wxCharBuffer dbuffer = sattr.ToUTF8();
3371 if (dbuffer.data()) {
3373 (
char *)realloc(pobj->att_array, 6 * (pobj->n_attr + 1));
3375 strncpy(pobj->att_array + (6 *
sizeof(
char) * pobj->n_attr),
3379 pobj->attVal->Add(pattValTmp);
3393 if (1 == geomtype) {
3394 if ((!strncmp(pobj->FeatureName,
"LIT", 3)) ||
3395 (!strncmp(pobj->FeatureName,
"LIGHTS", 6)) ||
3396 (!strncmp(pobj->FeatureName,
"BCN", 3)) ||
3397 (!strncmp(pobj->FeatureName,
"_slgto", 6)) ||
3398 (!strncmp(pobj->FeatureName,
"_boygn", 6)) ||
3399 (!strncmp(pobj->FeatureName,
"_bcngn", 6)) ||
3400 (!strncmp(pobj->FeatureName,
"_extgn", 6)) ||
3401 (!strncmp(pobj->FeatureName,
"TOWERS", 6)) ||
3402 (!strncmp(pobj->FeatureName,
"BOY", 3))) {
3403 bool bfound_OBJNAM = (pobj->GetAttributeIndex(
"OBJNAM") != -1);
3404 bool bfound_INFORM = (pobj->GetAttributeIndex(
"INFORM") != -1);
3406 if ((!bfound_OBJNAM) && (bfound_INFORM))
3408 char *patl = pobj->att_array;
3409 for (
int i = 0; i < pobj->n_attr; i++) {
3410 if (!strncmp(patl,
"INFORM", 6)) {
3411 memcpy(patl,
"OBJNAM", 6);
3423 pobj->Primitive_type = GEO_AREA;
3426 if (sclass_sub.IsSameAs(
"M_COVR")) {
3430 GetCoverSet()->Find_MCD(cell_index, iobject, subcell);
3431 if (NULL == pmcd_look)
3438 pmcd->m_cell_index = cell_index;
3439 pmcd->m_object_id = iobject;
3440 pmcd->m_subcell = subcell;
3443 pmcd->user_xoff = 0;
3444 pmcd->user_yoff = 0;
3445 pmcd->m_buser_offsets =
false;
3448 pmcd->m_npub_year = npub_year;
3451 int npta = xgeom->contour_array[0];
3452 float_2Dpt *geoPt =
new float_2Dpt[npta + 2];
3453 float_2Dpt *ppt = geoPt;
3455 pmcd->m_covr_lon_max = -1000.;
3456 pmcd->m_covr_lon_min = 1000.;
3457 pmcd->m_covr_lat_max = -1000.;
3458 pmcd->m_covr_lat_min = 1000.;
3462 for (
int ip = 0; ip < npta; ip++) {
3464 p.x = (int)xgeom->vertex_array[ip + 1].m_x;
3465 p.y = (int)xgeom->vertex_array[ip + 1].m_y;
3467 Transform(&p, 0, 0, &lat,
3472 pmcd->m_covr_lon_max = wxMax(pmcd->m_covr_lon_max, lon);
3473 pmcd->m_covr_lon_min = wxMin(pmcd->m_covr_lon_min, lon);
3474 pmcd->m_covr_lat_max = wxMax(pmcd->m_covr_lat_max, lat);
3475 pmcd->m_covr_lat_min = wxMin(pmcd->m_covr_lat_min, lat);
3479 pmcd->m_nvertices = npta;
3480 pmcd->pvertices = geoPt;
3482 pmcd->m_covr_bbox.Set(pmcd->m_covr_lat_min, pmcd->m_covr_lon_min,
3483 pmcd->m_covr_lat_max, pmcd->m_covr_lon_max);
3487 pmcd->transform_WGS84_offset_x = tmp_transform_x;
3488 pmcd->transform_WGS84_offset_y = tmp_transform_y;
3490 pmcd->m_centerlat_cos = cos(
3491 ((pmcd->m_covr_lat_min + pmcd->m_covr_lat_max) / 2.) * PI / 180.);
3494 GetCoverSet()->Add_Update_MCD(pmcd);
3499 if (pmcd_look->m_buser_offsets) {
3500 m_CIB.b_have_user_offsets =
true;
3502 m_CIB.user_xoff = pmcd_look->user_xoff;
3503 m_CIB.user_yoff = pmcd_look->user_yoff;
3510 m_pcovr_array_loaded.Add(pmcd);
3513 unsigned int n = pmcd->m_nvertices;
3514 double *pts =
new double[2 * n];
3517 for (
size_t i = 0; i < 2 * n; i++)
3518 pts[i] = ((
float *)pmcd->pvertices)[i];
3522 if (LLRegion::PointsCCW(n, pts))
3523 for (
size_t i = 0; i < n; i++)
3524 if (pts[2 * i + 1] < 0) pts[2 * i + 1] += 360;
3527 LLRegion rgn_covr(n, pts);
3528 m_region.Union(rgn_covr);
3536 m_CIB.m_cell_mcovr_list.Append(pmcd);
3540 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3541 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3544 pobj->m_n_lsindex = xgeom->n_vector_indices;
3545 pobj->m_lsindex_array =
3546 xgeom->pvector_index;
3547 pobj->m_n_edge_max_points = 0;
3550 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3553 pc.x = (
short unsigned int)pobj->x;
3554 pc.y = (
short unsigned int)pobj->y;
3555 Transform(&pc, 0., 0., &latc, &lonc);
3557 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(latc, lonc);
3559 trans_WGS84_offset_x = pmcd->user_xoff;
3560 trans_WGS84_offset_y = pmcd->user_yoff;
3565 double lat1, lon1, lat2, lon2;
3568 p.x = (int)xgeom->xmin;
3569 p.y = (int)xgeom->ymin;
3570 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3571 xgeom->ref_lat = lat1;
3572 xgeom->ref_lon = lon1;
3574 p.x = (int)xgeom->xmax;
3575 p.y = (int)xgeom->ymax;
3576 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat2, &lon2);
3577 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3582 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3590 xgeom->x_rate = m_CIB.transform_x_rate;
3591 xgeom->x_offset = m_CIB.transform_x_origin - trans_WGS84_offset_x;
3592 xgeom->y_rate = m_CIB.transform_y_rate;
3593 xgeom->y_offset = m_CIB.transform_y_origin - trans_WGS84_offset_y;
3595 pobj->pPolyTessGeo =
new PolyTessGeo(xgeom);
3602 pobj->Primitive_type = GEO_POINT;
3605 pobj->x = xgeom->pointx;
3606 pobj->y = xgeom->pointy;
3610 p.x = xgeom->pointx;
3611 p.y = xgeom->pointy;
3612 Transform(&p, 0., 0., &lat, &lon);
3615 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3616 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(lat, lon);
3618 trans_WGS84_offset_x = pmcd->user_xoff;
3619 trans_WGS84_offset_y = pmcd->user_yoff;
3624 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat, &lon);
3634 double llsize = 1e-3 / view_scale_ppm;
3636 pobj->BBObj.Set(lat, lon, lat, lon);
3637 pobj->BBObj.EnLarge(llsize);
3644 pobj->Primitive_type = GEO_POINT;
3647 double lat1, lon1, lat2, lon2;
3650 p.x = (int)xgeom->xmin;
3651 p.y = (int)xgeom->ymin;
3652 Transform(&p, 0., 0., &lat1, &lon1);
3654 p.x = (int)xgeom->xmax;
3655 p.y = (int)xgeom->ymax;
3656 Transform(&p, 0., 0., &lat2, &lon2);
3657 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3660 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3661 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3663 OGRMultiPoint *pGeo = (OGRMultiPoint *)xgeom->pogrGeom;
3664 pobj->npt = pGeo->getNumGeometries();
3666 pobj->geoPtz = (
double *)malloc(pobj->npt * 3 *
sizeof(
double));
3667 pobj->geoPtMulti = (
double *)malloc(pobj->npt * 2 *
sizeof(
double));
3669 double *pdd = pobj->geoPtz;
3670 double *pdl = pobj->geoPtMulti;
3672 for (
int ip = 0; ip < pobj->npt; ip++) {
3673 OGRPoint *ppt = (OGRPoint *)(pGeo->getGeometryRef(ip));
3676 p.x = (int)ppt->getX();
3677 p.y = (int)ppt->getY();
3678 double depth = ppt->getZ();
3683 double snd_trans_x = 0.;
3684 double snd_trans_y = 0.;
3687 if (m_CIB.b_have_user_offsets) {
3689 Transform(&p, 0., 0., &lats, &lons);
3691 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(lats, lons);
3694 snd_trans_x = pmcd->user_xoff;
3695 snd_trans_y = pmcd->user_yoff;
3699 east -= pmcd->user_xoff / m_CIB.transform_x_rate;
3700 north -= pmcd->user_yoff / m_CIB.transform_y_rate;
3710 Transform(&p, snd_trans_x, snd_trans_y, &lat1, &lon1);
3718 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3728 pobj->Primitive_type = GEO_LINE;
3730 pobj->npt = xgeom->n_max_vertex;
3731 pobj->geoPt = (pt *)xgeom->vertex_array;
3732 xgeom->vertex_array = NULL;
3735 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3736 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3739 pobj->m_n_lsindex = xgeom->n_vector_indices;
3740 pobj->m_lsindex_array =
3741 xgeom->pvector_index;
3742 pobj->m_n_edge_max_points = 0;
3745 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3748 pc.x = (
short unsigned int)pobj->x;
3749 pc.y = (
short unsigned int)pobj->y;
3750 Transform(&pc, 0., 0., &latc, &lonc);
3752 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(latc, lonc);
3754 trans_WGS84_offset_x = pmcd->user_xoff;
3755 trans_WGS84_offset_y = pmcd->user_yoff;
3760 double lat1, lon1, lat2, lon2;
3763 p.x = (int)xgeom->xmin;
3764 p.y = (int)xgeom->ymin;
3765 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3767 p.x = (int)xgeom->xmax;
3768 p.y = (int)xgeom->ymax;
3769 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat2, &lon2);
3770 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3775 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3784 pobj->Primitive_type = GEO_PRIM;
3791 if (!strncmp(pobj->FeatureName,
"OBSTRN", 6) ||
3792 !strncmp(pobj->FeatureName,
"WRECKS", 6) ||
3793 !strncmp(pobj->FeatureName,
"DEPCNT", 6) ||
3794 !strncmp(pobj->FeatureName,
"UWTROC", 6)) {
3795 pobj->m_bcategory_mutable =
true;
3797 pobj->m_bcategory_mutable =
false;
3810 if (geomtype != 4)
delete xgeom;
3814 m_CIB.transform_x_rate *
3815 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3817 m_CIB.transform_y_rate *
3818 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3820 m_CIB.transform_x_origin *
3821 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3823 m_CIB.transform_y_origin *
3824 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3828 pobj->x_origin -= trans_WGS84_offset_x;
3829 pobj->y_origin -= trans_WGS84_offset_y;
3832 pobj->auxParm3 = CHART_TYPE_CM93;
3838M_COVR_Desc *cm93chart::FindM_COVR_InWorkingSet(
double lat,
double lon) {
3841 if (m_CIB.m_cell_mcovr_list.GetCount() == 1) {
3842 List_Of_M_COVR_Desc::compatibility_iterator node0 =
3843 m_CIB.m_cell_mcovr_list.GetFirst();
3844 if (node0) ret = node0->GetData();
3846 List_Of_M_COVR_Desc::compatibility_iterator node =
3847 m_CIB.m_cell_mcovr_list.GetFirst();
3851 if (G_PtInPolygon_FL(pmcd->pvertices, pmcd->m_nvertices, lon, lat)) {
3856 node = node->GetNext();
3864wxPoint2DDouble cm93chart::FindM_COVROffset(
double lat,
double lon) {
3865 wxPoint2DDouble ret(0., 0.);
3868 List_Of_M_COVR_Desc::compatibility_iterator node0 =
3869 m_CIB.m_cell_mcovr_list.GetFirst();
3872 ret.m_x = pmcd0->transform_WGS84_offset_x;
3873 ret.m_y = pmcd0->transform_WGS84_offset_y;
3877 if (m_CIB.m_cell_mcovr_list.GetCount() > 1) {
3878 List_Of_M_COVR_Desc::compatibility_iterator node =
3879 m_CIB.m_cell_mcovr_list.GetFirst();
3883 if (G_PtInPolygon_FL(pmcd->pvertices, pmcd->m_nvertices, lon, lat)) {
3884 ret.m_x = pmcd->transform_WGS84_offset_x;
3885 ret.m_y = pmcd->transform_WGS84_offset_y;
3889 node = node->GetNext();
3897InitReturn cm93chart::CreateHeaderDataFromCM93Cell() {
3899 wxFileName fn(m_FullPath);
3900 wxString ext = fn.GetExt();
3903 switch ((ext.mb_str())[(
size_t)0]) {
3933 m_Chart_Scale =
scale;
3939 switch (m_Chart_Scale) {
3941 bproc = m_pManager->m_bfoundZ;
3944 bproc = m_pManager->m_bfoundA;
3947 bproc = m_pManager->m_bfoundB;
3950 bproc = m_pManager->m_bfoundC;
3953 bproc = m_pManager->m_bfoundD;
3956 bproc = m_pManager->m_bfoundE;
3959 bproc = m_pManager->m_bfoundF;
3962 bproc = m_pManager->m_bfoundG;
3966 if (bproc)
return INIT_FAIL_NOERROR;
3969 switch (m_Chart_Scale) {
3971 m_pManager->m_bfoundZ =
true;
3974 m_pManager->m_bfoundA =
true;
3977 m_pManager->m_bfoundB =
true;
3980 m_pManager->m_bfoundC =
true;
3983 m_pManager->m_bfoundD =
true;
3986 m_pManager->m_bfoundE =
true;
3989 m_pManager->m_bfoundF =
true;
3992 m_pManager->m_bfoundG =
true;
3998 m_FullExtent.ELON = 179.0;
3999 m_FullExtent.WLON = -179.0;
4000 m_FullExtent.NLAT = 80.0;
4001 m_FullExtent.SLAT = -80.0;
4002 m_bExtentSet =
true;
4006 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
4007 *m_pCOVRTablePoints = 4;
4008 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
4009 float *pf = (
float *)malloc(2 * 4 *
sizeof(
float));
4013 *pfe++ = m_FullExtent.NLAT;
4014 *pfe++ = m_FullExtent.WLON;
4016 *pfe++ = m_FullExtent.NLAT;
4017 *pfe++ = m_FullExtent.ELON;
4019 *pfe++ = m_FullExtent.SLAT;
4020 *pfe++ = m_FullExtent.ELON;
4022 *pfe++ = m_FullExtent.SLAT;
4023 *pfe++ = m_FullExtent.WLON;
4028void cm93chart::ProcessMCOVRObjects(
int cell_index,
char subcell) {
4031 Object *pobject = m_CIB.pobject_block;
4034 while (iObj < m_CIB.m_nfeature_records) {
4035 if ((pobject != NULL)) {
4037 int iclass = pobject->otype;
4039 wxString sclass = m_pDict->GetClassName(iclass);
4041 if (sclass.IsSameAs(
"_m_sor")) {
4043 m_pcovr_set->Find_MCD(cell_index, iObj, (
int)subcell);
4045 Extended_Geometry *xgeom = BuildGeom(pobject, NULL, iObj);
4049 double tmp_transform_x = 0.;
4050 double tmp_transform_y = 0.;
4053 for (
int jattr = 0; jattr < pobject->n_attributes; jattr++) {
4054 unsigned char *curr_attr = pab.GetNextAttr();
4055 unsigned char iattr = *curr_attr;
4056 wxString sattr = m_pDict->GetAttrName(iattr);
4057 char vtype = m_pDict->GetAttrType(iattr);
4058 unsigned char *aval = curr_attr + 1;
4061 float *pf = (
float *)aval;
4063 float __attribute__((aligned(16))) tf1;
4064 unsigned char *pucf = (
unsigned char *)pf;
4065 memcpy(&tf1, pucf, sizeof(
float));
4066 if (sattr.IsSameAs("_wgsox"))
4067 tmp_transform_x = tf1;
4068 else if (sattr.IsSameAs("_wgsoy"))
4069 tmp_transform_y = tf1;
4071 if (sattr.IsSameAs(
"_wgsox"))
4072 tmp_transform_x = *pf;
4073 else if (sattr.IsSameAs(
"_wgsoy"))
4074 tmp_transform_y = *pf;
4080 if (NULL != xgeom) {
4086 pmcd->m_cell_index = cell_index;
4087 pmcd->m_object_id = iObj;
4088 pmcd->m_subcell = (int)subcell;
4091 int npta = xgeom->contour_array[0];
4092 float_2Dpt *geoPt =
new float_2Dpt[npta + 2];
4093 float_2Dpt *ppt = geoPt;
4097 pmcd->m_covr_lon_max = -1000.;
4098 pmcd->m_covr_lon_min = 1000.;
4099 pmcd->m_covr_lat_max = -1000.;
4100 pmcd->m_covr_lat_min = 1000.;
4102 for (
int ip = 0; ip < npta; ip++) {
4104 p.x = (int)xgeom->vertex_array[ip + 1].m_x;
4105 p.y = (int)xgeom->vertex_array[ip + 1].m_y;
4107 Transform(&p, 0., 0., &lat, &lon);
4111 pmcd->m_covr_lon_max = wxMax(pmcd->m_covr_lon_max, lon);
4112 pmcd->m_covr_lon_min = wxMin(pmcd->m_covr_lon_min, lon);
4113 pmcd->m_covr_lat_max = wxMax(pmcd->m_covr_lat_max, lat);
4114 pmcd->m_covr_lat_min = wxMin(pmcd->m_covr_lat_min, lat);
4118 pmcd->m_nvertices = npta;
4119 pmcd->pvertices = geoPt;
4121 pmcd->m_covr_bbox.Set(pmcd->m_covr_lat_min, pmcd->m_covr_lon_min,
4122 pmcd->m_covr_lat_max, pmcd->m_covr_lon_max);
4126 pmcd->transform_WGS84_offset_x = tmp_transform_x;
4127 pmcd->transform_WGS84_offset_y = tmp_transform_y;
4129 pmcd->m_centerlat_cos =
4130 cos(((pmcd->m_covr_lat_min + pmcd->m_covr_lat_max) / 2.) * PI /
4134 m_pcovr_set->Add_Update_MCD(pmcd);
4137 free(xgeom->pvector_index);
4153bool cm93chart::UpdateCovrSet(
ViewPort *vpt) {
4155 std::vector<int> vpcells = GetVPCellArray(*vpt);
4160 for (
unsigned int i = 0; i < vpcells.size(); i++) {
4163 if (!m_pcovr_set->IsCovrLoaded(vpcells[i])) {
4164 if (loadcell_in_sequence(vpcells[i],
'0')) {
4165 ProcessMCOVRObjects(vpcells[i],
'0');
4168 m_pcovr_set->m_cell_hash[vpcells[i]] = 1;
4170 char loadcell_key =
'A';
4174 while (loadcell_in_sequence(vpcells[i], loadcell_key)) {
4177 ProcessMCOVRObjects(vpcells[i], loadcell_key);
4190bool cm93chart::IsPointInLoadedM_COVR(
double xc,
double yc) {
4193 return m_region.Contains(yc, xc);
4195 for (
unsigned int im = 0; im < m_pcovr_array_loaded.GetCount(); im++) {
4196 if (G_PtInPolygon_FL(m_pcovr_array_loaded[im]->pvertices,
4197 m_pcovr_array_loaded[im]->m_nvertices, xc, yc))
4204LLRegion cm93chart::GetValidRegion() {
return m_region; }
4206int cm93chart::loadcell_in_sequence(
int cellindex,
char subcell) {
4207 int rv = loadsubcell(cellindex, subcell);
4212int cm93chart::loadsubcell(
int cellindex, wxChar sub_char) {
4215 int ilat = cellindex / 10000;
4216 int ilon = cellindex % 10000;
4219 double dlat = m_dval / 3.;
4220 double dlon = m_dval / 3.;
4222 Get_CM93_Cell_Origin(cellindex, GetNativeScale(), &lat, &lon);
4224 "\n Attempting loadcell %d scale %lc, sub_char %lc at lat: %g/%g "
4226 cellindex, wxChar(m_scalechar[0]), sub_char, lat, lat + dlat, lon,
4230 int jlat = (int)(((ilat - 30) / m_dval) * m_dval) + 30;
4231 int jlon = (int)((ilon / m_dval) * m_dval);
4233 int ilatroot = (((ilat - 30) / 60) * 60) + 30;
4234 int ilonroot = (ilon / 60) * 60;
4237 file.Printf(
"%04d%04d.", jlat, jlon);
4238 file += m_scalechar;
4247 bool b_useNoFind =
true;
4248 if (m_noFindArray.GetCount() > 500) b_useNoFind =
false;
4251 fileroot.Printf(
"%04d%04d", ilatroot, ilonroot);
4252 appendOSDirSep(&fileroot);
4253 fileroot.append(m_scalechar);
4254 appendOSDirSep(&fileroot);
4255 wxString key = fileroot;
4257 fileroot.Prepend(m_prefix);
4259 file.Prepend(fileroot);
4263 strncpy(sfile, file.mb_str(), 199);
4265 printf(
" filename: %s\n", sfile);
4268 bool bfound =
false;
4271 if (m_noFindArray.Index(key) == wxNOT_FOUND) {
4272 if (::wxFileExists(file))
4275 m_noFindArray.Add(key);
4278 if (::wxFileExists(file)) bfound =
true;
4284 if (m_noFindArray.Index(key +
".xz") == wxNOT_FOUND) {
4285 if (::wxFileExists(file +
".xz")) {
4286 compfile = file +
".xz";
4289 m_noFindArray.Add(key +
".xz");
4292 if (::wxFileExists(file +
".xz")) compfile = file +
".xz";
4297 if (!bfound && !compfile.Length()) {
4299 wxString new_scalechar = m_scalechar.Lower();
4302 file1.Printf(
"%04d%04d.", jlat, jlon);
4303 file1 += new_scalechar;
4304 file1[0] = sub_char;
4306 fileroot.Printf(
"%04d%04d", ilatroot, ilonroot);
4307 appendOSDirSep(&fileroot);
4308 fileroot.append(new_scalechar);
4309 appendOSDirSep(&fileroot);
4313 fileroot.Prepend(m_prefix);
4315 file1.Prepend(fileroot);
4318 if (m_noFindArray.Index(key) == wxNOT_FOUND) {
4319 if (::wxFileExists(file1)) {
4323 m_noFindArray.Add(key);
4327 if (::wxFileExists(file1)) {
4335 if (m_noFindArray.Index(key +
".xz") == wxNOT_FOUND) {
4336 if (::wxFileExists(file1 +
".xz"))
4337 compfile = file1 +
".xz";
4339 m_noFindArray.Add(key +
".xz");
4342 if (::wxFileExists(file1 +
".xz")) compfile = file1 +
".xz";
4348 printf(
"noFind count: %d\n", (
int)m_noFindArray.GetCount());
4351 if (!bfound && !compfile.Length())
return 0;
4355 wxString msg(
"Loading CM93 cell ");
4361 m_LastFileName = file;
4364 if (compfile.Length()) {
4365 file = wxFileName::CreateTempFileName(wxFileName(compfile).GetFullName());
4366 if (!DecompressXZFile(compfile, file)) {
4374 strncpy(str, msg.mb_str(), 255);
4376 printf(
" %s\n", str);
4380 if (!Ingest_CM93_Cell((
const char *)file.mb_str(), &m_CIB)) {
4381 wxString msg(
" cm93chart Error ingesting ");
4385 if (compfile.Length()) wxRemoveFile(file);
4389 if (compfile.Length()) wxRemoveFile(file);
4394void cm93chart::SetUserOffsets(
int cell_index,
int object_id,
int subcell,
4395 int xoff,
int yoff) {
4396 M_COVR_Desc *pmcd = GetCoverSet()->Find_MCD(cell_index, object_id, subcell);
4398 pmcd->user_xoff = xoff;
4399 pmcd->user_yoff = yoff;
4400 pmcd->m_buser_offsets =
true;
4404wxPoint *cm93chart::GetDrawBuffer(
int nSize) {
4406 if (nSize > m_nDrawBufferSize) {
4407 wxPoint *tmp = m_pDrawBuffer;
4409 (wxPoint *)realloc(m_pDrawBuffer,
sizeof(wxPoint) * (nSize + 1));
4410 if (NULL == m_pDrawBuffer) {
4414 m_nDrawBufferSize = nSize + 1;
4416 return m_pDrawBuffer;
4423cm93manager::cm93manager() {
4436cm93manager::~cm93manager() {
delete m_pcm93Dict; }
4438bool cm93manager::Loadcm93Dictionary(
const wxString &name) {
4441 m_pcm93Dict = FindAndLoadDict(name);
4444 wxLogMessage(
" Cannot load CM93 Dictionary.");
4448 if (!m_pcm93Dict->IsOk()) {
4449 wxLogMessage(
" Error in loading CM93 Dictionary.");
4455 }
else if (!m_pcm93Dict->IsOk()) {
4456 wxLogMessage(
" CM93 Dictionary is not OK.");
4470 wxFileName fn(file);
4471 wxString path = fn.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
4475 while (i < path.Len()) {
4476 target.Append(path[i]);
4477 if (path[i] == fn.GetPathSeparator()) {
4478 if (pdict->LoadDictionary(target)) {
4482 if (pdict->LoadDictionary(target +
"CM93ATTR")) {
4491 strncpy(t, target.mb_str(), 99);
4493 if (retval == NULL)
delete pdict;
4501cm93compchart::cm93compchart() {
4502 m_ChartType = CHART_TYPE_CM93COMP;
4503 m_pDictComposite = NULL;
4506 m_FullPath =
"CM93";
4509 m_Description =
"CM93Composite";
4512 m_datum_str =
"WGS84";
4513 m_SoundingsDatum =
"Unknown";
4515 for (
int i = 0; i < 8; i++) m_pcm93chart_array[i] = NULL;
4517 m_pcm93chart_current = NULL;
4524 SetSpecialOutlineCellIndex(0, 0, 0);
4525 m_last_cell_adjustvp = NULL;
4530cm93compchart::~cm93compchart() {
4535 for (
int i = 0; i < 8; i++)
delete m_pcm93chart_array[i];
4537 delete m_pDictComposite;
4542InitReturn cm93compchart::Init(
const wxString &name, ChartInitFlag flags) {
4545 wxFileName fn(name);
4551 if (!fn.FileExists()) {
4553 if (wxDir::Exists(name)) {
4555 appendOSDirSep(&target);
4557 appendOSDirSep(&path);
4559 wxString msg(
" CM93Composite Chart Init cannot find ");
4562 return INIT_FAIL_REMOVE;
4567 path = fn.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
4571 wxFileName file_path(path);
4572 file_path.RemoveLastDir();
4573 file_path.RemoveLastDir();
4575 target = file_path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
4578 m_prefixComposite = target;
4580 wxString msg(
"CM93Composite Chart Root is ");
4581 msg.Append(m_prefixComposite);
4584 if (flags == THUMB_ONLY) {
4590 if (flags == HEADER_ONLY)
return CreateHeaderData();
4593 if (!m_pDictComposite) {
4594 if (!m_pDictComposite)
4595 m_pDictComposite = FindAndLoadDictFromDir(path);
4597 if (!m_pDictComposite) {
4599 " CM93Composite Chart Init cannot locate CM93 dictionary.");
4600 return INIT_FAIL_REMOVE;
4605 SetColorScheme(m_global_color_scheme,
false);
4607 bReadyToRender =
true;
4612void cm93compchart::Activate() {
4639void cm93compchart::Deactivate() {
4646double scale_breaks[] = {
4661int cm93compchart::GetCMScaleFromVP(
const ViewPort &vpt) {
4664 double scale_mpp_adj = scale_mpp;
4666 double scale_breaks_adj[7];
4668 for (
int i = 0; i < 7; i++) scale_breaks_adj[i] = scale_breaks[i];
4670 if (g_cm93_zoom_factor) {
4673 double efactor = ( double ) ( g_cm93_zoom_factor ) * ( .176 / 7. );
4674 for (
int i=0 ; i < 7 ; i++ )
4676 double efr = efactor * ( 7 - i );
4677 scale_breaks_adj[i] = scale_breaks[i] * pow ( 10., efr );
4679 printf (
"g_cm93_zoom_factor: %2d efactor: %6g efr:%6g, scale_breaks[i]:%6g scale_breaks_adj[i]: %6g\n",
4680 g_cm93_zoom_factor, efactor, efr, scale_breaks[i], scale_breaks_adj[i] );
4684 double efr = (double)g_cm93_zoom_factor * pow(scale_mpp, -.05);
4685 scale_mpp_adj *= pow(.6, efr);
4689 int cmscale_calc = 7;
4691 while (cmscale_calc > 0) {
4692 if (scale_mpp_adj < scale_breaks_adj[brk_index])
break;
4699 double zoom_factor = scale_breaks[7 - cmscale_calc] / vpt.
chart_scale;
4700 if (zoom_factor > 4.0) {
4701 if (cmscale_calc < 7) cmscale_calc++;
4704 return cmscale_calc;
4707void cm93compchart::SetVPParms(
const ViewPort &vpt) {
4710 int cmscale = GetCMScaleFromVP(vpt);
4711 m_cmscale = PrepareChartScale(vpt, cmscale,
false);
4715 if (m_pcm93chart_array[cmscale]) {
4716 if (!m_EdDate.IsValid() ||
4717 !m_pcm93chart_array[cmscale]->GetEditionDate().IsValid() ||
4718 m_pcm93chart_array[cmscale]->GetEditionDate().IsLaterThan(m_EdDate))
4719 m_EdDate = m_pcm93chart_array[cmscale]->GetEditionDate();
4723int cm93compchart::PrepareChartScale(
const ViewPort &vpt,
int cmscale,
4726 printf(
"\non SetVPParms, cmscale:%d, %c\n", cmscale,
4727 (
char)(
'A' + cmscale - 1));
4730 bool cellscale_is_useable =
false;
4731 bool b_nochart =
false;
4733 while (!cellscale_is_useable) {
4735 while (NULL == m_pcm93chart_array[cmscale]) {
4736 if (Is_CM93Cell_Present(m_prefixComposite, vpt.
clat, vpt.
clon, cmscale)) {
4738 printf(
" chart %c at VP clat/clon is present\n",
4739 (
char)(
'A' + cmscale - 1));
4741 m_pcm93chart_array[cmscale] =
new cm93chart();
4743 ext = (wxChar)(
'A' + cmscale - 1);
4744 if (cmscale == 0) ext =
'Z';
4746 wxString file_dummy =
"CM93.";
4749 m_pcm93chart_array[cmscale]->SetCM93Dict(m_pDictComposite);
4750 m_pcm93chart_array[cmscale]->SetCM93Prefix(m_prefixComposite);
4751 m_pcm93chart_array[cmscale]->SetCM93Manager(m_pcm93mgr);
4753 m_pcm93chart_array[cmscale]->SetColorScheme(m_global_color_scheme);
4754 m_pcm93chart_array[cmscale]->Init(file_dummy, FULL_INIT);
4755 }
else if (cmscale == 0) {
4762 " CM93 finds no chart of any scale present at Lat/Lon %g %g\n",
4772 printf(
" no %c scale chart present, adjusting cmscale to %c\n",
4773 (
char)(
'A' + cmscale), (
char)(
'A' + cmscale - 1));
4777 m_pcm93chart_current = m_pcm93chart_array[cmscale];
4780 if (g_bDebugCM93) printf(
" b_nochart return\n");
4782 m_pcm93chart_current = NULL;
4783 for (
int i = 0; i < 8; i++) {
4784 delete m_pcm93chart_array[i];
4785 m_pcm93chart_array[i] = NULL;
4791 if (m_pcm93chart_current) {
4794 m_pcm93chart_current->SetVPParms(vpt);
4798 float yc = vpt.
clat;
4799 float xc = vpt.
clon;
4801 if (!m_pcm93chart_current->GetCoverSet()->GetCoverCount()) {
4803 printf(
" chart %c has no M_COVR\n", (
char)(
'A' + cmscale - 1));
4806 if (m_pcm93chart_current->IsPointInLoadedM_COVR(xc, yc)) {
4808 printf(
" chart %c contains clat/clon\n", (
char)(
'A' + cmscale - 1));
4810 cellscale_is_useable =
true;
4824 else if (vpt.b_quilt && vpt.b_FullScreenQuilt) {
4827 covr_set *pcover = m_pcm93chart_current->GetCoverSet();
4829 bool boverlap =
false;
4830 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
4833 if (!(vp.GetBBox().IntersectOut(mcd->m_covr_bbox))) {
4838 if (boverlap) cellscale_is_useable =
true;
4842 if (!cellscale_is_useable) {
4850 printf(
" VP is not in M_COVR, adjusting cmscale to %c\n",
4851 (
char)(
'A' + cmscale - 1));
4858 double zoom_factor = scale_breaks[7 - cmscale] / vpt.
chart_scale;
4860 if (zoom_factor > 4.0) {
4863 float yc = vpt.
clat;
4864 float xc = vpt.
clon;
4867 FillScaleArray(vpt.
clat, vpt.
clon);
4868 int new_scale = cmscale;
4869 bool b_found =
false;
4870 while (new_scale <= 7) {
4871 if (m_bScale_Array[new_scale]) {
4872 double new_zoom_factor =
4876 if (new_zoom_factor < 1.0) {
4878 new_scale = cmscale;
4882 if (new_zoom_factor < 4.0) {
4883 if (NULL == m_pcm93chart_array[new_scale]) {
4884 m_pcm93chart_array[new_scale] =
new cm93chart();
4886 ext = (wxChar)(
'A' + new_scale - 1);
4887 if (new_scale == 0) ext =
'Z';
4889 wxString file_dummy =
"CM93.";
4892 m_pcm93chart_array[new_scale]->SetCM93Dict(m_pDictComposite);
4893 m_pcm93chart_array[new_scale]->SetCM93Prefix(m_prefixComposite);
4894 m_pcm93chart_array[new_scale]->SetCM93Manager(m_pcm93mgr);
4896 m_pcm93chart_array[new_scale]->SetColorScheme(
4897 m_global_color_scheme);
4898 m_pcm93chart_array[new_scale]->Init(file_dummy, FULL_INIT);
4901 m_pcm93chart_array[new_scale]->SetVPParms(vpt);
4902 if (m_pcm93chart_array[new_scale]->IsPointInLoadedM_COVR(xc, yc)) {
4911 cmscale = new_scale;
4912 m_pcm93chart_current = m_pcm93chart_array[cmscale];
4922void cm93compchart::FillScaleArray(
double lat,
double lon) {
4923 for (
int cmscale = 0; cmscale < 8; cmscale++)
4924 m_bScale_Array[cmscale] =
4925 Is_CM93Cell_Present(m_prefixComposite, lat, lon, cmscale);
4931wxString cm93compchart::GetPubDate() {
4934 if (NULL != m_pcm93chart_current)
4936 data.Printf(
"%4d", m_current_cell_pub_date);
4942int cm93compchart::GetNativeScale() {
4943 if (m_pcm93chart_current)
4944 return m_pcm93chart_current->GetNativeScale();
4949double cm93compchart::GetNormalScaleMin(
double canvas_scale_factor,
4950 bool b_allow_overzoom) {
4954 if (m_pcm93chart_current) {
4956 if (m_pcm93chart_current->m_last_vp.IsValid()) {
4957 FillScaleArray(m_pcm93chart_current->m_last_vp.clat,
4958 m_pcm93chart_current->m_last_vp.clon);
4962 while (cmscale > 0) {
4963 if (m_bScale_Array[cmscale])
break;
4971 return 20000000. / oz_factor;
4973 return 3000000. / oz_factor;
4975 return 1000000. / oz_factor;
4977 return 200000. / oz_factor;
4979 return 100000. / oz_factor;
4981 return 50000. / oz_factor;
4983 return 20000. / oz_factor;
4987 return 500. / oz_factor;
4993double cm93compchart::GetNormalScaleMax(
double canvas_scale_factor,
4995 return (180. / 360.) * PI * 2 *
4996 (WGS84_semimajor_axis_meters / (canvas_width / canvas_scale_factor));
5000wxPoint GetPixFromLLVP(
double lat,
double lon,
const ViewPort &VPoint) {
5002 double easting, northing;
5004 double s, y3, s0, y30;
5005 double z = WGS84_semimajor_axis_meters * mercator_k0;
5010 if (lon * VPoint.
clon < 0.) {
5018 if (fabs(xlon - VPoint.
clon) > 180.) {
5019 if (xlon > VPoint.
clon)
5024 easting = (xlon - VPoint.
clon) * DEGREE * z;
5026 s = sin(lat * DEGREE);
5027 y3 = (.5 * log((1 + s) / (1 - s))) * z;
5029 s0 = sin(VPoint.
clat * DEGREE);
5030 y30 = (.5 * log((1 + s0) / (1 - s0))) * z;
5031 northing = y3 - y30;
5037 r.x = (int)round((VPoint.
pix_width / 2) + epix);
5038 r.y = (int)round((VPoint.
pix_height / 2) - npix);
5045void cm93compchart::GetValidCanvasRegion(
const ViewPort &VPoint,
5049 VPoint, g_bopengl ? VPoint.rv_rect : screen_region);
5050 *pValidRegion = ret;
5053OCPNRegion cm93compchart::GetValidScreenCanvasRegion(
5061 if (m_pcm93chart_current) {
5062 int chart_native_scale = m_pcm93chart_current->GetNativeScale();
5064 for (
unsigned int im = 0;
5065 im < m_pcm93chart_current->m_pcovr_array_loaded.GetCount(); im++) {
5066 M_COVR_Desc *pmcd = (m_pcm93chart_current->m_pcovr_array_loaded[im]);
5071 if (vp.GetBBox().IntersectOut(pmcd->m_covr_bbox))
continue;
5073 wxPoint *DrawBuf = m_pcm93chart_current->GetDrawBuffer(pmcd->m_nvertices);
5076 ScreenRegion, pmcd->m_nvertices, (
float *)pmcd->pvertices,
5077 chart_native_scale, DrawBuf);
5079 if (rgn_covr.IsOk())
5080 ret_region.Union(rgn_covr);
5089LLRegion cm93compchart::GetValidRegion() {
5090 if (m_pcm93chart_current)
return m_pcm93chart_current->GetValidRegion();
5095bool cm93compchart::RenderRegionViewOnGL(
const wxGLContext &glc,
5098 const LLRegion &Region) {
5104 return DoRenderRegionViewOnGL(glc, VPoint, RectRegion, Region);
5107bool cm93compchart::DoRenderRegionViewOnGL(
const wxGLContext &glc,
5110 const LLRegion &Region) {
5117 bool render_return =
false;
5118 if (m_pcm93chart_current == 0)
return render_return;
5126 if (VPoint.b_quilt) {
5127 LLRegion vpr_empty = Region;
5128 LLRegion chart_region = GetValidRegion();
5147 if (!chart_region.Empty()) vpr_empty.Subtract(chart_region);
5149 if (!vpr_empty.Empty() &&
5153 int cmscale_save = m_cmscale;
5155 LLRegion region_vect[8];
5159 while (!vpr_empty.Empty() && m_cmscale) {
5161 m_cmscale = PrepareChartScale(vp, m_cmscale - 1,
false);
5163 if (m_pcm93chart_current) {
5164 LLRegion sscale_region = GetValidRegion();
5167 region_vect[m_cmscale] = sscale_region;
5168 region_vect[m_cmscale].Intersect(vpr_empty);
5171 vpr_empty.Subtract(sscale_region);
5178 for (
int i = 0; i < 8; i++) {
5179 if (!region_vect[i].Empty()) {
5180 m_cmscale = PrepareChartScale(vp, i,
false);
5181 if (m_pcm93chart_current)
5182 render_return |= m_pcm93chart_current->RenderRegionViewOnGL(
5183 glc, vp, RectRegion, region_vect[i]);
5188 m_cmscale = cmscale_save;
5189 m_pcm93chart_current = m_pcm93chart_array[m_cmscale];
5193 if (m_pcm93chart_current) {
5194 render_return |= m_pcm93chart_current->RenderRegionViewOnGL(
5195 glc, vp, RectRegion, Region);
5196 m_Name = m_pcm93chart_current->GetName();
5201 if (m_pcm93chart_current) {
5202 render_return = m_pcm93chart_current->RenderRegionViewOnGL(
5203 glc, vp, RectRegion, Region);
5204 m_Name = m_pcm93chart_current->GetLastFileName();
5209 if (VPoint.m_projection_type != PROJECTION_MERCATOR)
5210 return render_return;
5212 if (!m_pcm93chart_current)
return render_return;
5215 if (m_cell_index_special_outline) {
5217 wxGLCanvas *glc = top_frame::Get()->GetWxGlCanvas();
5224 covr_set *pcover = m_pcm93chart_current->GetCoverSet();
5226 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
5228 if ((pmcd->m_cell_index == m_cell_index_special_outline) &&
5229 (pmcd->m_object_id == m_object_id_special_outline) &&
5230 (pmcd->m_subcell == m_subcell_special_outline))
5240 float_2Dpt *p = pmcd->pvertices;
5241 wxPoint *pwp = m_pcm93chart_current->GetDrawBuffer(pmcd->m_nvertices);
5243 for (
int ip = 0; ip < pmcd->m_nvertices; ip++) {
5245 if (fabs(plon - VPoint.
clon) > 180.) {
5246 if (plon > VPoint.
clon)
5252 double easting, northing, epix, npix;
5253 toSM(p->y, plon + 360., VPoint.
clat, VPoint.
clon + 360, &easting,
5259 easting -= pmcd->user_xoff;
5262 northing -= pmcd->user_yoff;
5267 pwp[ip].x = (int)round((VPoint.
pix_width / 2) + epix);
5268 pwp[ip].y = (int)round((VPoint.
pix_height / 2) - npix);
5275 wxPen pen(wxTheColourDatabase->Find(
"YELLOW"), 3);
5279 pen.SetStyle(wxPENSTYLE_USER_DASH);
5280 pen.SetDashes(2, dash1);
5284 for (
int iseg = 0; iseg < pmcd->m_nvertices - 1; iseg++) {
5285 int x0 = pwp[iseg].x;
5286 int y0 = pwp[iseg].y;
5287 int x1 = pwp[iseg + 1].x;
5288 int y1 = pwp[iseg + 1].y;
5290 ClipResult res = cohen_sutherland_line_clip_i(
5291 &x0, &y0, &x1, &y1, 0, VPoint.
pix_width, 0,
5306 return render_return;
5309bool cm93compchart::RenderRegionViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint,
5316 return DoRenderRegionViewOnDC(dc, VPoint, Region);
5319bool cm93compchart::RenderViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint) {
5324 return DoRenderRegionViewOnDC(dc, VPoint, vpr);
5327bool cm93compchart::DoRenderRegionViewOnDC(wxMemoryDC &dc,
5334 printf(
"\nOn DoRenderRegionViewOnDC Ref scale is %d, %c\n", m_cmscale,
5335 (
char)(
'A' + m_cmscale - 1));
5337 while (upd.HaveRects()) {
5338 wxRect rect = upd.GetRect();
5339 printf(
" Region Rect: %d %d %d %d\n", rect.x, rect.y, rect.width,
5348 bool render_return =
false;
5349 if (m_pcm93chart_current) {
5350 m_pcm93chart_current->SetVPParms(vp);
5354 if (VPoint.b_quilt) {
5357 OCPNRegion chart_region = GetValidScreenCanvasRegion(vp, Region);
5361 "On DoRenderRegionViewOnDC : Intersecting Ref region rectangles\n");
5363 while (upd.HaveRects()) {
5364 wxRect rect = upd.GetRect();
5365 printf(
" Region Rect: %d %d %d %d\n", rect.x, rect.y, rect.width,
5371 if (!chart_region.IsEmpty()) vpr_empty.Subtract(chart_region);
5373 if (!vpr_empty.Empty() &&
5377#ifdef ocpnUSE_DIBSECTION
5382 if (!chart_region.IsEmpty())
5383 render_return = m_pcm93chart_current->RenderRegionViewOnDC(
5384 temp_dc, vp, chart_region);
5386 render_return =
false;
5389 cm93chart *m_pcm93chart_save = m_pcm93chart_current;
5395 if ((m_pDummyBM->GetWidth() != VPoint.rv_rect.width) ||
5396 (m_pDummyBM->GetHeight() != VPoint.rv_rect.height)) {
5401 if (NULL == m_pDummyBM)
5403 new wxBitmap(VPoint.rv_rect.width, VPoint.rv_rect.height, -1);
5405#ifdef ocpnUSE_DIBSECTION
5410 dumm_dc.SelectObject(*m_pDummyBM);
5411 dumm_dc.SetBackground(*wxBLACK_BRUSH);
5414 int cmscale_next = m_cmscale;
5418 while (!vpr_empty.Empty() && cmscale_next) {
5421 m_cmscale = PrepareChartScale(vp, cmscale_next,
false);
5422#ifdef ocpnUSE_DIBSECTION
5425 wxMemoryDC build_dc;
5428 if (m_pcm93chart_current) {
5430 printf(
" In DRRVOD, add quilt patch at %d, %c\n", m_cmscale,
5431 (
char)(
'A' + m_cmscale - 1));
5433 m_pcm93chart_current->RenderRegionViewOnDC(build_dc, vp, Region);
5435 OCPNRegion sscale_region = GetValidScreenCanvasRegion(vp, Region);
5438 sscale_region.Intersect(vpr_empty);
5442 while (upd.HaveRects()) {
5443 wxRect rect = upd.GetRect();
5444 dumm_dc.Blit(rect.x, rect.y, rect.width, rect.height, &build_dc,
5448 build_dc.SelectObject(wxNullBitmap);
5451 if (!sscale_region.IsEmpty()) vpr_empty.Subtract(sscale_region);
5459 while (updt.HaveRects()) {
5460 wxRect rect = updt.GetRect();
5461 dumm_dc.Blit(rect.x, rect.y, rect.width, rect.height, &temp_dc,
5465 temp_dc.SelectObject(wxNullBitmap);
5468 m_pcm93chart_current = m_pcm93chart_save;
5472 dumm_dc.SelectObject(wxNullBitmap);
5475 dc.SelectObject(*m_pDummyBM);
5477 render_return =
true;
5479 m_pcm93chart_current->RenderRegionViewOnDC(dc, vp, Region);
5480 render_return =
true;
5482 m_Name = m_pcm93chart_current->GetName();
5487 m_pcm93chart_current->RenderRegionViewOnDC(dc, vp, Region);
5488 m_Name = m_pcm93chart_current->GetLastFileName();
5496 if ((m_pDummyBM->GetWidth() != VPoint.
pix_width) ||
5497 (m_pDummyBM->GetHeight() != VPoint.
pix_height)) {
5503 if (NULL == m_pDummyBM)
5508 mdc.SelectObject(*m_pDummyBM);
5509 mdc.SetBackground(*wxBLACK_BRUSH);
5511 mdc.SelectObject(wxNullBitmap);
5513 dc.SelectObject(*m_pDummyBM);
5519 if (m_cell_index_special_outline && m_pcm93chart_current) {
5520 covr_set *pcover = m_pcm93chart_current->GetCoverSet();
5522 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
5524 if ((pmcd->m_cell_index == m_cell_index_special_outline) &&
5525 (pmcd->m_object_id == m_object_id_special_outline) &&
5526 (pmcd->m_subcell == m_subcell_special_outline))
5536 float_2Dpt *p = pmcd->pvertices;
5537 wxPoint *pwp = m_pcm93chart_current->GetDrawBuffer(pmcd->m_nvertices);
5539 for (
int ip = 0; ip < pmcd->m_nvertices; ip++) {
5541 if (fabs(plon - VPoint.
clon) > 180.) {
5542 if (plon > VPoint.
clon)
5548 double easting, northing, epix, npix;
5549 toSM(p->y, plon + 360., VPoint.
clat, VPoint.
clon + 360, &easting,
5555 easting -= pmcd->user_xoff;
5558 northing -= pmcd->user_yoff;
5563 pwp[ip].x = (int)round((VPoint.
pix_width / 2) + epix);
5564 pwp[ip].y = (int)round((VPoint.
pix_height / 2) - npix);
5587 dc.SetPen(wxPen(wxTheColourDatabase->Find(
"YELLOW"), 4,
5588 wxPENSTYLE_LONG_DASH));
5590 for (
int iseg = 0; iseg < pmcd->m_nvertices - 1; iseg++) {
5591 int x0 = pwp[iseg].x;
5592 int y0 = pwp[iseg].y;
5593 int x1 = pwp[iseg + 1].x;
5594 int y1 = pwp[iseg + 1].y;
5596 ClipResult res = cohen_sutherland_line_clip_i(
5597 &x0, &y0, &x1, &y1, 0, VPoint.
pix_width, 0,
5604 dc.DrawLine(x0, y0, x1, y1);
5612 return render_return;
5615void cm93compchart::UpdateRenderRegions(
const ViewPort &VPoint) {
5616 OCPNRegion full_screen_region(0, 0, VPoint.rv_rect.width,
5617 VPoint.rv_rect.height);
5623 if (m_pcm93chart_current) {
5624 m_pcm93chart_current->SetVPParms(vp);
5628 if (VPoint.b_quilt) {
5630 for (
int i = 0; i < 8; i++) {
5631 if (m_pcm93chart_array[i])
5632 m_pcm93chart_array[i]->m_render_region.Clear();
5638 GetValidScreenCanvasRegion(vp, full_screen_region);
5639 m_pcm93chart_current->m_render_region = chart_region;
5641 if (!chart_region.IsEmpty()) vpr_empty.Subtract(chart_region);
5643 if (!vpr_empty.Empty() &&
5647 cm93chart *m_pcm93chart_save = m_pcm93chart_current;
5649 int cmscale_next = m_cmscale;
5651 while (!vpr_empty.Empty() && cmscale_next) {
5654 m_cmscale = PrepareChartScale(vp, cmscale_next,
false);
5656 if (m_pcm93chart_current) {
5658 GetValidScreenCanvasRegion(vp, full_screen_region);
5659 sscale_region.Intersect(vpr_empty);
5660 m_pcm93chart_current->m_render_region = sscale_region;
5663 if (!sscale_region.IsEmpty()) vpr_empty.Subtract(sscale_region);
5669 m_pcm93chart_current = m_pcm93chart_save;
5675void cm93compchart::SetSpecialCellIndexOffset(
int cell_index,
int object_id,
5676 int subcell,
int xoff,
int yoff) {
5677 m_special_offset_x = xoff;
5678 m_special_offset_y = yoff;
5680 if (m_pcm93chart_current)
5681 m_pcm93chart_current->SetUserOffsets(cell_index, object_id, subcell, xoff,
5685bool cm93compchart::RenderNextSmallerCellOutlines(
ocpnDC &dc,
ViewPort &vp,
5687 if (m_cmscale >= 7)
return false;
5690 if (!glcc)
return false;
5697 int nss = m_cmscale + 1;
5706 bool bdrawn =
false;
5715 if(nss_max > m_cmscale+3)
5716 nss_max = m_cmscale+3;
5719 while (nss <= nss_max && (!bdrawn || (vp.
chart_scale < 3e6))) {
5720 cm93chart *psc = m_pcm93chart_array[nss];
5723 m_pcm93chart_array[nss] =
new cm93chart();
5724 psc = m_pcm93chart_array[nss];
5726 wxChar ext = (wxChar)(
'A' + nss - 1);
5727 if (nss == 0) ext =
'Z';
5729 wxString file_dummy =
"CM93.";
5732 psc->SetCM93Dict(m_pDictComposite);
5733 psc->SetCM93Prefix(m_prefixComposite);
5734 psc->SetCM93Manager(m_pcm93mgr);
5736 psc->SetColorScheme(m_global_color_scheme);
5737 psc->Init(file_dummy, FULL_INIT);
5743 psc->UpdateCovrSet(&vp);
5746 covr_set *pcover = psc->GetCoverSet();
5748 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
5751 if (vp.GetBBox().IntersectOut(mcd->m_covr_bbox))
continue;
5753 wxPoint *pwp = psc->GetDrawBuffer(mcd->m_nvertices);
5754 bdrawn = RenderCellOutlines(dc, vp, pwp, mcd);
5762 glDisable(GL_LINE_STIPPLE);
5763 glDisable(GL_LINE_SMOOTH);
5764 glDisable(GL_BLEND);
5770bool cm93compchart::RenderCellOutlines(
ocpnDC &dc,
ViewPort &vp, wxPoint *pwp,
5772 float_2Dpt *p = mcd->pvertices;
5773 int np = mcd->m_nvertices;
5775 for (
int ip = 0; ip < np; ip++, p++) {
5785 wxPoint p0 = pwp[0];
5786 for (
int ip = 1; ip < np; ip++) {
5787 if (((p0.x > vp.
pix_width) && (pwp[ip].x < 0)) ||
5788 ((p0.x < 0) && (pwp[ip].x > vp.
pix_width)))
5794 dc.DrawLines(mcd->m_nvertices, pwp, 0, 0,
false);
5798void cm93compchart::GetPointPix(ObjRazRules *rzRules,
float rlat,
float rlon,
5800 m_pcm93chart_current->GetPointPix(rzRules, rlat, rlon, r);
5803void cm93compchart::GetPointPix(ObjRazRules *rzRules, wxPoint2DDouble *en,
5804 wxPoint *r,
int nPoints) {
5805 m_pcm93chart_current->GetPointPix(rzRules, en, r, nPoints);
5808void cm93compchart::GetPixPoint(
int pixx,
int pixy,
double *plat,
double *plon,
5810 m_pcm93chart_current->GetPixPoint(pixx, pixy, plat, plon, vpt);
5813void cm93compchart::UpdateLUPs(
s57chart *pOwner) {
5814 for (
int i = 0; i < 8; i++) {
5815 if (m_pcm93chart_array[i]) m_pcm93chart_array[i]->UpdateLUPs(pOwner);
5819std::list<S57Obj *> *cm93compchart::GetAssociatedObjects(S57Obj *obj) {
5820 if (m_pcm93chart_current)
5821 return m_pcm93chart_current->GetAssociatedObjects(obj);
5826void cm93compchart::InvalidateCache() {
5827 for (
int i = 0; i < 8; i++) {
5828 if (m_pcm93chart_array[i]) m_pcm93chart_array[i]->InvalidateCache();
5832void cm93compchart::ForceEdgePriorityEvaluate() {
5833 for (
int i = 0; i < 8; i++) {
5834 if (m_pcm93chart_array[i])
5835 m_pcm93chart_array[i]->ForceEdgePriorityEvaluate();
5839void cm93compchart::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
5840 m_global_color_scheme = cs;
5842 for (
int i = 0; i < 8; i++) {
5843 if (m_pcm93chart_array[i])
5844 m_pcm93chart_array[i]->SetColorScheme(cs, bApplyImmediate);
5848ListOfObjRazRules *cm93compchart::GetObjRuleListAtLatLon(
float lat,
float lon,
5849 float select_radius,
5851 int selection_mask) {
5857 if (!VPoint->b_quilt)
5858 if (m_pcm93chart_current)
5859 return m_pcm93chart_current->GetObjRuleListAtLatLon(lat, alon,
5860 select_radius, &vp);
5863 ListOfObjRazRules *ret_ptr =
new ListOfObjRazRules;
5867 UpdateRenderRegions(*VPoint);
5873 for (
int i = 0; i < 8; i++) {
5874 if (m_pcm93chart_array[i]) {
5875 if (!m_pcm93chart_array[i]->m_render_region.IsEmpty()) {
5876 if (wxInRegion == m_pcm93chart_array[i]->m_render_region.Contains(p))
5877 return m_pcm93chart_array[i]->GetObjRuleListAtLatLon(
5878 lat, alon, select_radius, &vp, selection_mask);
5884 ListOfObjRazRules *ret_ptr =
new ListOfObjRazRules;
5890std::unordered_map<unsigned, VE_Element *> &cm93compchart::Get_ve_hash() {
5891 return m_pcm93chart_current->Get_ve_hash();
5894std::unordered_map<unsigned, VC_Element *> &cm93compchart::Get_vc_hash() {
5895 return m_pcm93chart_current->Get_vc_hash();
5906 m_last_cell_adjustvp = m_pcm93chart_current;
5914 if (m_pcm93chart_current)
return false;
5923 int cmscale = GetCMScaleFromVP(
5926 int cmscale_actual = PrepareChartScale(
5927 vp_proposed, cmscale,
5931 printf(
" In AdjustVP, adjustment subchart scale is %c\n",
5932 (
char)(
'A' + cmscale_actual - 1));
5938 bool single_adjust =
false;
5939 if (m_pcm93chart_array[cmscale_actual])
5941 m_pcm93chart_array[cmscale_actual]->AdjustVP(vp_last, vp_proposed);
5943 if (m_cmscale != cmscale_actual)
return false;
5947 if (vp_last.b_quilt)
return false;
5949 return single_adjust;
5952ThumbData *cm93compchart::GetThumbData(
int tnx,
int tny,
float lat,
float lon) {
5956InitReturn cm93compchart::CreateHeaderData() {
5957 m_Chart_Scale = 20000000;
5963 wxDir dirt(m_prefixComposite);
5965 wxRegEx test(
"[0-9]+");
5967 bool b_cont = dirt.GetFirst(&candidate);
5970 if (test.Matches(candidate) && (candidate.Len() == 8)) {
5971 wxString dir = m_prefixComposite;
5973 if (wxDir::Exists(dir)) {
5974 wxFileName name(dir);
5975 wxString num_name = name.GetName();
5977 if (num_name.ToLong(&number)) {
5978 int ilat = number / 10000;
5979 int ilon = number % 10000;
5981 int lat_base = (ilat - 270) / 3.;
5982 int lon_base = ilon / 3.;
5983 extent_rect.Union(wxRect(lon_base, lat_base, 20, 20));
5987 b_cont = dirt.GetNext(&candidate);
5991 m_FullExtent.ELON = ((double)extent_rect.x + (
double)extent_rect.width);
5992 m_FullExtent.WLON = ((double)extent_rect.x);
5993 m_FullExtent.NLAT = ((double)extent_rect.y + (
double)extent_rect.height);
5994 m_FullExtent.SLAT = ((double)extent_rect.y);
5995 m_bExtentSet =
true;
5999 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
6000 *m_pCOVRTablePoints = 4;
6001 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
6002 float *pf = (
float *)malloc(2 * 4 *
sizeof(
float));
6006 *pfe++ = m_FullExtent.NLAT;
6007 *pfe++ = m_FullExtent.WLON;
6009 *pfe++ = m_FullExtent.NLAT;
6010 *pfe++ = m_FullExtent.ELON;
6012 *pfe++ = m_FullExtent.SLAT;
6013 *pfe++ = m_FullExtent.ELON;
6015 *pfe++ = m_FullExtent.SLAT;
6016 *pfe++ = m_FullExtent.WLON;
6021cm93_dictionary *cm93compchart::FindAndLoadDictFromDir(
const wxString &dir) {
6026 if (pdict->LoadDictionary(dir))
return pdict;
6031 wxString path = dir;
6035 while (i < path.Len()) {
6036 target.Append(path[i]);
6037 if (path[i] == wxFileName::GetPathSeparator()) {
6041 if (pdict->LoadDictionary(target)) {
6055 wxFileName fnc(dir);
6056 wxString found_dict_file_name;
6060 path = fnc.GetPath(wxPATH_GET_VOLUME);
6062 wxString msg =
" Looking harder for CM93 dictionary in ";
6066 if ((path.Len() == 0) || path.IsSameAs(fnc.GetPathSeparator())) {
6068 wxLogMessage(
"Early break1");
6074 if ((wxNOT_FOUND == path.Lower().Find(
"cm93"))) {
6076 wxLogMessage(
"Early break2");
6084 if (dir.IsOpened()) {
6087 dir.Traverse(cm93Dictionary);
6088 bdone = found_dict_file_name.Len() != 0;
6094 if (found_dict_file_name.Len()) {
6095 wxFileName fnd(found_dict_file_name);
6097 fnd.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
6099 if (pdict->LoadDictionary(dpath)) retval = pdict;
6102 if (NULL == retval)
delete pdict;
6107void cm93compchart::CloseandReopenCurrentSubchart() {
6108 delete m_pcm93chart_current;
6109 m_pcm93chart_current = NULL;
6110 m_pcm93chart_array[m_cmscale] = NULL;
6134 const wxPoint &pos,
const wxSize &size,
long style);
6137 wxString OnGetItemText(
long item,
long column)
const;
6138 int OnGetItemColumnImage(
long item,
long column)
const;
6143OCPNOffsetListCtrl::OCPNOffsetListCtrl(
CM93OffsetDialog *parent, wxWindowID
id,
6144 const wxPoint &pos,
const wxSize &size,
6146 : wxListCtrl(parent, id, pos, size, style) {
6150OCPNOffsetListCtrl::~OCPNOffsetListCtrl() {}
6152wxString OCPNOffsetListCtrl::OnGetItemText(
long item,
long column)
const {
6154 M_COVR_Desc *pmcd = m_parent->m_pcovr_array[item];
6158 ret.Printf(
"%d", pmcd->m_cell_index);
6159 if (((
int)
'0') == pmcd->m_subcell)
6162 char t = (char)pmcd->m_subcell;
6171 ret.Printf(
"%d", pmcd->m_object_id);
6175 ret = m_parent->m_selected_chart_scale_char;
6179 ret.Printf(
"%g", pmcd->transform_WGS84_offset_x);
6183 ret.Printf(
"%g", pmcd->transform_WGS84_offset_y);
6187 ret.Printf(
"%6.0f", pmcd->user_xoff * pmcd->m_centerlat_cos);
6191 ret.Printf(
"%6.0f", pmcd->user_yoff * pmcd->m_centerlat_cos);
6200int OCPNOffsetListCtrl::OnGetItemColumnImage(
long item,
long column)
const {
6211EVT_CLOSE(CM93OffsetDialog::OnClose)
6216 m_pcompchart = NULL;
6221 m_selected_list_index = -1;
6222 m_selected_cell_index = 0;
6224 long wstyle = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER;
6225 wxDialog::Create(parent, -1, _(
"OpenCPN CM93 Cell Offset Adjustments"),
6226 wxPoint(0, 0), wxSize(800, 200), wstyle);
6232 wxBoxSizer *topSizer =
new wxBoxSizer(wxHORIZONTAL);
6237 long flags = wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_HRULES | wxLC_VRULES |
6240 flags |= wxLC_VIRTUAL;
6246 m_pListCtrlMCOVRs->Connect(
6247 wxEVT_COMMAND_LIST_ITEM_SELECTED,
6248 wxListEventHandler(CM93OffsetDialog::OnCellSelected), NULL,
this);
6250 int dx = GetCharWidth();
6251 int dy = GetCharHeight();
6254 m_pListCtrlMCOVRs->InsertColumn(tlCELL, _(
"Cell"), wxLIST_FORMAT_LEFT, width);
6257 m_pListCtrlMCOVRs->InsertColumn(tlMCOVR, _(
"M_COVR ID"), wxLIST_FORMAT_CENTER,
6261 m_pListCtrlMCOVRs->InsertColumn(tlSCALE, _(
"Cell Scale"),
6262 wxLIST_FORMAT_CENTER, width);
6265 m_pListCtrlMCOVRs->InsertColumn(tlXOFF, _(
"wgsox"), wxLIST_FORMAT_CENTER,
6269 m_pListCtrlMCOVRs->InsertColumn(tlYOFF, _(
"wgsoy"), wxLIST_FORMAT_CENTER,
6273 m_pListCtrlMCOVRs->InsertColumn(tlUXOFF, _(
"User X Offset"),
6274 wxLIST_FORMAT_CENTER, width);
6277 m_pListCtrlMCOVRs->InsertColumn(tlUYOFF, _(
"User Y Offset"),
6278 wxLIST_FORMAT_CENTER, width);
6280 topSizer->Add(m_pListCtrlMCOVRs, 1, wxEXPAND | wxALL, 0);
6282 wxBoxSizer *boxSizer02 =
new wxBoxSizer(wxVERTICAL);
6283 boxSizer02->AddSpacer(22);
6285 wxStaticText *pStaticTextXoff =
new wxStaticText(
6287 wxString::Format(
"%s (%s)", _(
"User X Offset"), _(
"meters")),
6288 wxDefaultPosition, wxDefaultSize, 0);
6289 boxSizer02->Add(pStaticTextXoff, 0, wxALL, 0);
6292 new wxSpinCtrl(
this, wxID_ANY, wxEmptyString, wxDefaultPosition,
6293 wxSize(50, -1), wxSP_ARROW_KEYS, -10000, 10000, 0);
6294 m_pSpinCtrlXoff->Connect(wxEVT_COMMAND_SPINCTRL_UPDATED,
6295 wxCommandEventHandler(CM93OffsetDialog::OnOffSetSet),
6297 boxSizer02->Add(m_pSpinCtrlXoff, 0, wxEXPAND | wxALL, 0);
6299 wxStaticText *pStaticTextYoff =
new wxStaticText(
6301 wxString::Format(
"%s (%s)", _(
"User Y Offset"), _(
"meters")),
6302 wxDefaultPosition, wxDefaultSize, 0);
6303 boxSizer02->Add(pStaticTextYoff, 0, wxALL, 0);
6306 new wxSpinCtrl(
this, wxID_ANY, wxEmptyString, wxDefaultPosition,
6307 wxSize(50, -1), wxSP_ARROW_KEYS, -10000, 10000, 0);
6308 m_pSpinCtrlYoff->Connect(wxEVT_COMMAND_SPINCTRL_UPDATED,
6309 wxCommandEventHandler(CM93OffsetDialog::OnOffSetSet),
6311 boxSizer02->Add(m_pSpinCtrlYoff, 0, wxEXPAND | wxALL, 0);
6313 m_OKButton =
new wxButton(
this, wxID_ANY, _(
"OK"), wxDefaultPosition,
6315 m_OKButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
6316 wxCommandEventHandler(CM93OffsetDialog::OnOK), NULL,
6318 boxSizer02->Add(m_OKButton, 0, wxALL, 5);
6319 m_OKButton->SetDefault();
6321 topSizer->Add(boxSizer02, 0, wxEXPAND | wxALL, 2);
6323 wxSize sz(800, dy * 8);
6325 sz = wxGetDisplaySize();
6335 SetSize(GetSize().x, GetSize().y - 1);
6349void CM93OffsetDialog::OnClose(wxCloseEvent &event) {
6351 m_pcompchart->SetSpecialOutlineCellIndex(0, 0, 0);
6353 m_pcompchart->InvalidateCache();
6356 m_pparent->Refresh(
true);
6357 top_frame::Get()->InvalidateAllGL();
6361 if (m_pListCtrlMCOVRs->GetItemCount() > m_selected_list_index)
6362 m_pListCtrlMCOVRs->SetItemState(m_selected_list_index, 0,
6363 wxLIST_STATE_SELECTED);
6368void CM93OffsetDialog::OnOK(wxCommandEvent &event) {
6376 m_pcompchart = pchart;
6379void CM93OffsetDialog::OnOffSetSet(wxCommandEvent &event) {
6380 m_xoff = m_pSpinCtrlXoff->GetValue() / m_centerlat_cos;
6381 m_yoff = m_pSpinCtrlYoff->GetValue() / m_centerlat_cos;
6388void CM93OffsetDialog::UpdateOffsets() {
6389 if (m_pcompchart && m_selected_cell_index) {
6391 m_pcompchart->SetSpecialCellIndexOffset(m_selected_cell_index,
6392 m_selected_object_id,
6393 m_selected_subcell, m_xoff, m_yoff);
6397 AbstractPlatform::ShowBusySpinner();
6398 m_pcompchart->CloseandReopenCurrentSubchart();
6399 AbstractPlatform::HideBusySpinner();
6402 m_pparent->Refresh(
true);
6403 top_frame::Get()->InvalidateAllGL();
6408void CM93OffsetDialog::SetColorScheme() { DimeControl(
this); }
6410void CM93OffsetDialog::OnCellSelected(wxListEvent &event) {
6412 m_selected_list_index =
event.GetIndex();
6414 M_COVR_Desc *mcd = m_pcovr_array.Item(event.GetIndex());
6416 if (m_selected_list_index > m_pListCtrlMCOVRs->GetItemCount())
6419 cm93chart *pchart = m_pcompchart->GetCurrentSingleScaleChart();
6421 M_COVR_Desc *cached_mcd = pchart->GetCoverSet()->Find_MCD(
6422 mcd->m_cell_index, mcd->m_object_id, mcd->m_subcell);
6424 m_pSpinCtrlXoff->SetValue(
6425 wxRound(cached_mcd->user_xoff * cached_mcd->m_centerlat_cos));
6426 m_pSpinCtrlYoff->SetValue(
6427 wxRound(cached_mcd->user_yoff * cached_mcd->m_centerlat_cos));
6431 m_pcompchart->SetSpecialOutlineCellIndex(mcd->m_cell_index,
6432 mcd->m_object_id, mcd->m_subcell);
6434 m_selected_cell_index = mcd->m_cell_index;
6435 m_selected_object_id = mcd->m_object_id;
6436 m_selected_subcell = mcd->m_subcell;
6437 m_centerlat_cos = mcd->m_centerlat_cos;
6439 m_pcompchart->InvalidateCache();
6442 m_pparent->Refresh(
true);
6443 top_frame::Get()->InvalidateAllGL();
6448void CM93OffsetDialog::UpdateMCOVRList(
const ViewPort &vpt) {
6452 cm93chart *pchart = m_pcompchart->GetCurrentSingleScaleChart();
6455 m_selected_chart_scale_char = pchart->GetScaleChar();
6457 m_pcovr_array.Clear();
6460 std::vector<int> cell_array = pchart->GetVPCellArray(vpt);
6468 covr_set *pcover = pchart->GetCoverSet();
6470 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
6473 for (
unsigned int icell = 0; icell < cell_array.size(); icell++) {
6474 if (cell_array[icell] == mcd->m_cell_index) {
6475 wxPoint *pwp = pchart->GetDrawBuffer(mcd->m_nvertices);
6482 m_pcovr_array.Add(mcd);
6490 for (
unsigned int im = 0; im < m_pcovr_array.size(); im++) {
6492 if ((m_selected_cell_index == mcd->m_cell_index) &&
6493 (m_selected_object_id == mcd->m_object_id) &&
6494 (m_selected_subcell == mcd->m_subcell)) {
6500 if (!m_pListCtrlMCOVRs->IsVirtual()) {
6501 if (m_pListCtrlMCOVRs->GetItemCount())
6502 m_pListCtrlMCOVRs->DeleteAllItems();
6504 for (
unsigned int i = 0; i < m_pcovr_array.GetCount(); i++) {
6507 m_pListCtrlMCOVRs->InsertItem(item);
6508 for (
int j = 0; j < tlUYOFF + 1; j++) {
6510 item.SetText(m_pListCtrlMCOVRs->OnGetItemText(i, j));
6511 m_pListCtrlMCOVRs->SetItem(item);
6515 m_pListCtrlMCOVRs->SetItemCount(m_pcovr_array.GetCount());
6518 if (-1 != sel_index)
6519 m_pListCtrlMCOVRs->SetItemState(sel_index, wxLIST_STATE_SELECTED,
6520 wxLIST_STATE_SELECTED);
6522 m_pListCtrlMCOVRs->SetItemState(sel_index, 0,
6523 wxLIST_STATE_SELECTED);
6525 m_pListCtrlMCOVRs->Refresh(
true);
6528 m_pListCtrlMCOVRs->Refresh(
false);
Generic Chart canvas base.
Dialog for managing CM93 chart offsets.
ChartCanvas - Main chart display and interaction component.
An iterator class for OCPNRegion.
A wrapper class for wxRegion with additional functionality.
ViewPort - Core geographic projection and coordinate transformation engine.
double view_scale_ppm
Requested view scale in physical pixels per meter (ppm), before applying projections.
int pix_height
Height of the viewport in physical pixels.
double rotation
Rotation angle of the viewport in radians.
int pix_width
Width of the viewport in physical pixels.
wxPoint2DDouble GetDoublePixFromLL(double lat, double lon)
Convert latitude and longitude on the ViewPort to physical pixel coordinates with double precision.
double skew
Angular distortion (shear transform) applied to the viewport in radians.
void GetLLFromPix(const wxPoint &p, double *lat, double *lon)
Convert physical pixel coordinates on the ViewPort to latitude and longitude.
OCPNRegion GetVPRegionIntersect(const OCPNRegion ®ion, const LLRegion &llregion, int chart_native_scale)
Get the intersection of the viewport with a given region.
double clon
Center longitude of the viewport in degrees.
double clat
Center latitude of the viewport in degrees.
wxPoint GetPixFromLL(double lat, double lon)
Convert latitude and longitude on the ViewPort to physical pixel coordinates.
double chart_scale
Chart scale denominator (e.g., 50000 for a 1:50000 scale).
Represents a single CM93 chart at a specific scale.
Represents a composite CM93 chart covering multiple scales.
OpenGL chart rendering canvas.
Device context class that can use either wxDC or OpenGL for drawing.
void DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, bool b_hiqual=true)
Draw a line between two points using either wxDC or OpenGL.
Represents an S57 format electronic navigational chart in OpenCPN.
CM93OffsetDialog * g_pCM93OffsetDialog
Global instance.
Class cm93chart and helpers – CM93 chart state.
CM93OffsetDialog * g_pCM93OffsetDialog
Global instance.
PopUpDSlide * pPopupDetailSlider
Global instance.
Chart display details slider.
OpenGL chart rendering canvas.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
General purpose GUI support.
Optimized wxBitmap Object.
@ PI_PRIO_NUM
Number of priority levels.
@ PI_LUPNAME_NUM
Total number of lookup table types.
Layer to use wxDC or opengl.
Tools to send data to plugins.
PlugInManager and helper classes – Mostly gui parts (dialogs) and plugin API stuff.
Runtime representation of a plugin block.
Abstract gFrame/MyFrame interface.