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>
48#include "DetailSlider.h"
51#include "model/georef.h"
55#include "ocpn_frame.h"
56#include "ocpn_pixel.h"
57#include "OCPNPlatform.h"
64#include "glChartCanvas.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, _T (
"_" ));
339 prefix_string.Replace(_T (
":" ), _T (
"_" ));
342 appendOSDirSep(&m_cachefile);
344 m_cachefile += _T (
"cm93" );
345 appendOSDirSep(&m_cachefile);
349 m_cachefile += _T (
"_" );
351 wxString cache_old_old_name = m_cachefile;
352 cache_old_old_name += _T (
"coverset." );
353 cache_old_old_name += m_scale_char;
355 wxString cache_old_name = m_cachefile;
356 cache_old_name += _T (
"coverset_sig." );
357 cache_old_name += m_scale_char;
359 m_cachefile += _T (
"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(_T (
"CM93OBJ.DIC" ));
579 if (!wxFileName::FileExists(sf)) {
581 sf.Append(_T (
"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(_T (
"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(_T (
"ATTRLUT.DIC" ));
671 if (!wxFileName::FileExists(sfa)) {
673 sfa.Append(_T (
"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(_T (
"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(_T (
"aFLOAT" )))
756 else if (token.IsSameAs(_T (
"aBYTE" )))
758 else if (token.IsSameAs(_T (
"aSTRING" )))
760 else if (token.IsSameAs(_T (
"aCMPLX" )))
762 else if (token.IsSameAs(_T (
"aLIST" )))
764 else if (token.IsSameAs(_T (
"aWORD10" )))
766 else if (token.IsSameAs(_T (
"aLONG" )))
769 m_ValTypeArray[iattr] = atype;
783 sfa.Append(_T (
"CM93ATTR.DIC" ));
785 if (!wxFileName::FileExists(sfa)) {
787 sfa.Append(_T (
"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.StartsWith((
const wxChar *)
";")) {
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(_T (
"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.StartsWith((
const wxChar *)
";")) {
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(_T (
"aFLOAT" )))
867 else if (token.IsSameAs(_T (
"aBYTE" )))
869 else if (token.IsSameAs(_T (
"aSTRING" )))
871 else if (token.IsSameAs(_T (
"aCMPLX" )))
873 else if (token.IsSameAs(_T (
"aLIST" )))
875 else if (token.IsSameAs(_T (
"aWORD10" )))
877 else if (token.IsSameAs(_T (
"aLONG" )))
880 m_ValTypeArray[iattr] = atype;
893 wxString msg(_T (
"Loaded CM93 Dictionary from " ));
901wxString cm93_dictionary::GetClassName(
int iclass) {
902 if ((iclass > m_max_class) || (iclass < 0))
903 return (_T (
"Unknown" ));
905 return (m_S57ClassArray->Item(iclass));
908wxString cm93_dictionary::GetAttrName(
int iattr) {
909 if ((iattr > m_max_attr) || (iattr < 0))
910 return (_T (
"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(
void) {
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(_T (
"%04d%04d" ), ilatroot, ilonroot);
1176 appendOSDirSep(&fileroot);
1178 wxString sdir(fileprefix);
1183 tfile.Printf(_T (
"?%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(_T (
"?%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(
void) {
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(
void) {
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 = gFrame->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(_T (
" 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 = _T (
"CM93Chart " );
2474 data.Append(m_scalechar);
2476 s.Printf(_T (
" 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(_T (
" 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(_T (
"Unexpected geomtype %d for Feature %d\n" ), geomtype,
2882void cm93chart::Transform(
cm93_point *s,
double trans_x,
double trans_y,
2883 double *lat,
double *lon) {
2885 double valx = (s->x * m_CIB.transform_x_rate) + m_CIB.transform_x_origin;
2886 double valy = (s->y * m_CIB.transform_y_rate) + m_CIB.transform_y_origin;
2894 (2.0 * atan(exp(valy / CM93_semimajor_axis_meters)) - PI / 2.) / DEGREE;
2895 *lon = (valx / (DEGREE * CM93_semimajor_axis_meters));
2900 m_block = (
unsigned char *)
block;
2904unsigned char *cm93_attr_block::GetNextAttr() {
2906 unsigned char *ret_val = m_block + m_cptr;
2910 unsigned char iattr = *(m_block + m_cptr);
2914 char vtype = m_pDict->GetAttrType(iattr);
2927 while (*(m_block + m_cptr)) m_cptr++;
2944 while (*(m_block + m_cptr)) m_cptr++;
2950 unsigned char nl = *(m_block + m_cptr);
2977wxString ParseSLGTA(wxString &val) {
2982 wxStringTokenizer tkz(val,
"|");
2984 s = tkz.GetNextToken();
2985 s = tkz.GetNextToken();
2986 s = tkz.GetNextToken();
2989 wxString sc, st, sp;
3002 else if (s[0] ==
'G') {
3005 }
else if (s.Mid(0, 3) == _T (
"W/O" )) {
3011 }
else if (s.Mid(0, 5) == _T (
"LIGHT" )) {
3016 if (val.Find(_T (
"Spar" )) != wxNOT_FOUND) {
3020 if (val.Find(_T (
"SPAR" )) != wxNOT_FOUND) {
3025 if ((type == 2) && (color == 3))
3032 sprintf(line,
" %s (%c) = %s",
"COLOUR",
'I', (
const char *)sc.mb_str());
3033 result += wxString(line, wxConvUTF8);
3036 sprintf(line,
" %s (%c) = %s",
"BOYSHP",
'I',
"4");
3037 result += wxString(line, wxConvUTF8);
3043 sprintf(line,
" %s (%c) = %s",
"BOYSHP",
'I', (
const char *)st.mb_str());
3044 result += wxString(line, wxConvUTF8);
3047 sprintf(line,
" %s (%c) = %s",
"COLOUR",
'I',
"2");
3048 result += wxString(line, wxConvUTF8);
3054 sprintf(line,
" %s (%c) = %s",
"COLPAT",
'I', (
const char *)sp.mb_str());
3055 result += wxString(line, wxConvUTF8);
3062wxString ParseTEXTA(wxString &val) {
3066 if (val.Contains(_T (
"WK S" ))) {
3067 sprintf(line,
" %s (%c) = %s",
"WRKATT",
'I',
"1");
3068 result += wxString(line, wxConvUTF8);
3075void cm93chart::translate_colmar(
const wxString &sclass,
3076 S57attVal *pattValTmp) {
3077 int *pcur_attr = (
int *)pattValTmp->value;
3078 int cur_attr = *pcur_attr;
3084 lstring = _T (
"4" );
3087 lstring = _T (
"2" );
3090 lstring = _T (
"3" );
3093 lstring = _T (
"6" );
3096 lstring = _T (
"1" );
3099 lstring = _T (
"11" );
3102 lstring = _T (
"2,6" );
3105 lstring = _T (
"2,6,2" );
3108 lstring = _T (
"6,2" );
3111 lstring = _T (
"6,2,6" );
3114 lstring = _T (
"3,1" );
3117 lstring = _T (
"4,3,4" );
3120 lstring = _T (
"3,4,3" );
3123 lstring = _T (
"2,3,2" );
3126 lstring = _T (
"6,3,6" );
3129 lstring = _T (
"4,3" );
3132 lstring = _T (
"3,4" );
3135 lstring = _T (
"4,1" );
3141 if (lstring.Len()) {
3142 free(pattValTmp->value);
3144 pattValTmp->valType = OGR_STR;
3145 pattValTmp->value = strdup(lstring.mb_str());
3149S57Obj *cm93chart::CreateS57Obj(
int cell_index,
int iobject,
int subcell,
3151 Extended_Geometry *xgeom,
double ref_lat,
3152 double ref_lon,
double scale,
3153 double view_scale_ppm) {
3154#define MAX_HDR_LINE 4000
3158 int npub_year = 1993;
3160 int iclass = pobject->otype;
3161 int geomtype = pobject->geotype & 0x0f;
3163 double tmp_transform_x = 0.;
3164 double tmp_transform_y = 0.;
3167 double trans_WGS84_offset_x = 0.;
3168 double trans_WGS84_offset_y = 0.;
3170 wxString sclass = pDict->GetClassName(iclass);
3171 if (sclass == _T (
"Unknown" )) {
3173 msg.Printf(_T (
" CM93 Error...object type %d not found in CM93OBJ.DIC" ),
3180 wxString sclass_sub = sclass;
3183 if (sclass.IsSameAs(_T (
"ITDARE" ))) sclass_sub = _T (
"DEPARE" );
3185 if (sclass.IsSameAs(_T (
"_m_sor" ))) sclass_sub = _T (
"M_COVR" );
3187 if (sclass.IsSameAs(_T (
"SPOGRD" ))) sclass_sub = _T (
"DMPGRD" );
3189 if (sclass.IsSameAs(_T (
"FSHHAV" ))) sclass_sub = _T (
"FSHFAC" );
3191 if (sclass.IsSameAs(_T (
"OFSPRD" ))) sclass_sub = _T (
"CTNARE" );
3194 S57Obj *pobj =
new S57Obj();
3196 pobj->Index = iobject;
3199 strncpy(u, sclass_sub.mb_str(), 199);
3201 memcpy(pobj->FeatureName, u, 7);
3203 pobj->attVal =
new wxArrayOfS57attVal();
3207 for (
int jattr = 0; jattr < pobject->n_attributes; jattr++) {
3208 unsigned char *curr_attr = pab.GetNextAttr();
3210 unsigned char iattr = *curr_attr;
3212 wxString sattr = pDict->GetAttrName(iattr);
3214 char vtype = pDict->GetAttrType(iattr);
3216 unsigned char *aval = curr_attr + 1;
3229 S57attVal *pattValTmp =
new S57attVal;
3234 pAVI = (
int *)malloc(
sizeof(
int));
3236 pattValTmp->valType = OGR_INT;
3237 pattValTmp->value = pAVI;
3240 pb = (
unsigned char *)aval;
3241 pAVI = (
int *)malloc(
sizeof(
int));
3243 pattValTmp->valType = OGR_INT;
3244 pattValTmp->value = pAVI;
3247 pw = (
unsigned short *)aval;
3251 pAVR = (
double *)malloc(
sizeof(
double));
3252 *pAVR = dival / 10.;
3253 pattValTmp->valType = OGR_REAL;
3254 pattValTmp->value = pAVR;
3258 pAVI = (
int *)malloc(
sizeof(
int));
3260 pattValTmp->valType = OGR_INT;
3261 pattValTmp->value = pAVI;
3265 pAVS = strdup((
char *)aval);
3266 pattValTmp->valType = OGR_STR;
3267 pattValTmp->value = pAVS;
3271 pAVS = strdup((
const char *)&aval[3]);
3272 pattValTmp->valType = OGR_STR;
3273 pattValTmp->value = pAVS;
3276 pb = (
unsigned char *)aval;
3277 unsigned char nl = *pb++;
3280 for (
int i = 0; i < nl; i++) {
3281 sprintf(vi,
"%d,", *pb++);
3284 if (strlen(val)) val[strlen(val) - 1] = 0;
3287 pattValTmp->valType = OGR_STR;
3288 pattValTmp->value = pAVS;
3292 pAVR = (
double *)malloc(
sizeof(
double));
3296 float __attribute__((aligned(16))) tf1;
3297 unsigned char *pucf = (
unsigned char *)pf;
3299 memcpy(&tf1, pucf, sizeof(
float));
3305 pattValTmp->valType = OGR_REAL;
3306 pattValTmp->value = pAVR;
3314 if (sattr.IsSameAs(_T (
"COLMAR" ))) {
3315 translate_colmar(sclass, pattValTmp);
3316 sattr = _T (
"COLOUR" );
3320 if (pattValTmp->valType == OGR_INT &&
3321 (sattr.IsSameAs(_T (
"QUASOU" )) || sattr.IsSameAs(_T (
"CATLIT" )))) {
3322 int v = *(
int *)pattValTmp->value;
3323 free(pattValTmp->value);
3324 sprintf(val,
"%d", v);
3326 pattValTmp->valType = OGR_STR;
3327 pattValTmp->value = pAVS;
3331 if (sclass.IsSameAs(_T (
"$AREAS" )) && (vtype ==
'S') &&
3332 sattr.IsSameAs(_T (
"$SCODE" ))) {
3333 if (!strcmp((
char *)pattValTmp->value,
"II25")) {
3334 free(pattValTmp->value);
3335 pattValTmp->value = strdup(
"BACKGROUND");
3340 if (sattr.IsSameAs(_T (
"RECDAT" )) || sattr.IsSameAs(_T (
"_dgdat" ))) {
3341 if (sclass_sub.IsSameAs(_T (
"M_COVR" )) && (vtype ==
'S')) {
3342 wxString pub_date((
char *)pattValTmp->value, wxConvUTF8);
3345 upd.ParseFormat(pub_date, _T (
"%Y%m%d" ));
3346 if (!upd.IsValid()) upd.ParseFormat(_T (
"20000101" ), _T (
"%Y%m%d" ));
3349 pub_date.Truncate(4);
3352 pub_date.ToLong(&nyear);
3358 if (sclass_sub.IsSameAs(_T (
"M_COVR" )) && (vtype ==
'R')) {
3359 if (sattr.IsSameAs(_T (
"_wgsox" ))) {
3360 tmp_transform_x = *(
double *)pattValTmp->value;
3361 if (fabs(tmp_transform_x) > 1.0)
3362 m_CIB.b_have_offsets =
true;
3363 }
else if (sattr.IsSameAs(_T (
"_wgsoy" ))) {
3364 tmp_transform_y = *(
double *)pattValTmp->value;
3365 if (fabs(tmp_transform_y) > 1.0) m_CIB.b_have_offsets =
true;
3370 wxASSERT(sattr.Len() == 6);
3371 wxCharBuffer dbuffer = sattr.ToUTF8();
3372 if (dbuffer.data()) {
3374 (
char *)realloc(pobj->att_array, 6 * (pobj->n_attr + 1));
3376 strncpy(pobj->att_array + (6 *
sizeof(
char) * pobj->n_attr),
3380 pobj->attVal->Add(pattValTmp);
3394 if (1 == geomtype) {
3395 if ((!strncmp(pobj->FeatureName,
"LIT", 3)) ||
3396 (!strncmp(pobj->FeatureName,
"LIGHTS", 6)) ||
3397 (!strncmp(pobj->FeatureName,
"BCN", 3)) ||
3398 (!strncmp(pobj->FeatureName,
"_slgto", 6)) ||
3399 (!strncmp(pobj->FeatureName,
"_boygn", 6)) ||
3400 (!strncmp(pobj->FeatureName,
"_bcngn", 6)) ||
3401 (!strncmp(pobj->FeatureName,
"_extgn", 6)) ||
3402 (!strncmp(pobj->FeatureName,
"TOWERS", 6)) ||
3403 (!strncmp(pobj->FeatureName,
"BOY", 3))) {
3404 bool bfound_OBJNAM = (pobj->GetAttributeIndex(
"OBJNAM") != -1);
3405 bool bfound_INFORM = (pobj->GetAttributeIndex(
"INFORM") != -1);
3407 if ((!bfound_OBJNAM) && (bfound_INFORM))
3409 char *patl = pobj->att_array;
3410 for (
int i = 0; i < pobj->n_attr; i++) {
3411 if (!strncmp(patl,
"INFORM", 6)) {
3412 memcpy(patl,
"OBJNAM", 6);
3424 pobj->Primitive_type = GEO_AREA;
3427 if (sclass_sub.IsSameAs(_T (
"M_COVR" ))) {
3431 GetCoverSet()->Find_MCD(cell_index, iobject, subcell);
3432 if (NULL == pmcd_look)
3439 pmcd->m_cell_index = cell_index;
3440 pmcd->m_object_id = iobject;
3441 pmcd->m_subcell = subcell;
3444 pmcd->user_xoff = 0;
3445 pmcd->user_yoff = 0;
3446 pmcd->m_buser_offsets =
false;
3449 pmcd->m_npub_year = npub_year;
3452 int npta = xgeom->contour_array[0];
3453 float_2Dpt *geoPt =
new float_2Dpt[npta + 2];
3454 float_2Dpt *ppt = geoPt;
3456 pmcd->m_covr_lon_max = -1000.;
3457 pmcd->m_covr_lon_min = 1000.;
3458 pmcd->m_covr_lat_max = -1000.;
3459 pmcd->m_covr_lat_min = 1000.;
3463 for (
int ip = 0; ip < npta; ip++) {
3465 p.x = (int)xgeom->vertex_array[ip + 1].m_x;
3466 p.y = (int)xgeom->vertex_array[ip + 1].m_y;
3468 Transform(&p, 0, 0, &lat,
3473 pmcd->m_covr_lon_max = wxMax(pmcd->m_covr_lon_max, lon);
3474 pmcd->m_covr_lon_min = wxMin(pmcd->m_covr_lon_min, lon);
3475 pmcd->m_covr_lat_max = wxMax(pmcd->m_covr_lat_max, lat);
3476 pmcd->m_covr_lat_min = wxMin(pmcd->m_covr_lat_min, lat);
3480 pmcd->m_nvertices = npta;
3481 pmcd->pvertices = geoPt;
3483 pmcd->m_covr_bbox.Set(pmcd->m_covr_lat_min, pmcd->m_covr_lon_min,
3484 pmcd->m_covr_lat_max, pmcd->m_covr_lon_max);
3488 pmcd->transform_WGS84_offset_x = tmp_transform_x;
3489 pmcd->transform_WGS84_offset_y = tmp_transform_y;
3491 pmcd->m_centerlat_cos = cos(
3492 ((pmcd->m_covr_lat_min + pmcd->m_covr_lat_max) / 2.) * PI / 180.);
3495 GetCoverSet()->Add_Update_MCD(pmcd);
3500 if (pmcd_look->m_buser_offsets) {
3501 m_CIB.b_have_user_offsets =
true;
3503 m_CIB.user_xoff = pmcd_look->user_xoff;
3504 m_CIB.user_yoff = pmcd_look->user_yoff;
3511 m_pcovr_array_loaded.Add(pmcd);
3514 unsigned int n = pmcd->m_nvertices;
3515 double *pts =
new double[2 * n];
3518 for (
size_t i = 0; i < 2 * n; i++)
3519 pts[i] = ((
float *)pmcd->pvertices)[i];
3523 if (LLRegion::PointsCCW(n, pts))
3524 for (
size_t i = 0; i < n; i++)
3525 if (pts[2 * i + 1] < 0) pts[2 * i + 1] += 360;
3528 LLRegion rgn_covr(n, pts);
3529 m_region.Union(rgn_covr);
3537 m_CIB.m_cell_mcovr_list.Append(pmcd);
3541 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3542 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3545 pobj->m_n_lsindex = xgeom->n_vector_indices;
3546 pobj->m_lsindex_array =
3547 xgeom->pvector_index;
3548 pobj->m_n_edge_max_points = 0;
3551 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3554 pc.x = (
short unsigned int)pobj->x;
3555 pc.y = (
short unsigned int)pobj->y;
3556 Transform(&pc, 0., 0., &latc, &lonc);
3558 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(latc, lonc);
3560 trans_WGS84_offset_x = pmcd->user_xoff;
3561 trans_WGS84_offset_y = pmcd->user_yoff;
3566 double lat1, lon1, lat2, lon2;
3569 p.x = (int)xgeom->xmin;
3570 p.y = (int)xgeom->ymin;
3571 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3572 xgeom->ref_lat = lat1;
3573 xgeom->ref_lon = lon1;
3575 p.x = (int)xgeom->xmax;
3576 p.y = (int)xgeom->ymax;
3577 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat2, &lon2);
3578 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3583 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3591 xgeom->x_rate = m_CIB.transform_x_rate;
3592 xgeom->x_offset = m_CIB.transform_x_origin - trans_WGS84_offset_x;
3593 xgeom->y_rate = m_CIB.transform_y_rate;
3594 xgeom->y_offset = m_CIB.transform_y_origin - trans_WGS84_offset_y;
3596 pobj->pPolyTessGeo =
new PolyTessGeo(xgeom);
3603 pobj->Primitive_type = GEO_POINT;
3606 pobj->x = xgeom->pointx;
3607 pobj->y = xgeom->pointy;
3611 p.x = xgeom->pointx;
3612 p.y = xgeom->pointy;
3613 Transform(&p, 0., 0., &lat, &lon);
3616 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3617 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(lat, lon);
3619 trans_WGS84_offset_x = pmcd->user_xoff;
3620 trans_WGS84_offset_y = pmcd->user_yoff;
3625 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat, &lon);
3635 double llsize = 1e-3 / view_scale_ppm;
3637 pobj->BBObj.Set(lat, lon, lat, lon);
3638 pobj->BBObj.EnLarge(llsize);
3645 pobj->Primitive_type = GEO_POINT;
3648 double lat1, lon1, lat2, lon2;
3651 p.x = (int)xgeom->xmin;
3652 p.y = (int)xgeom->ymin;
3653 Transform(&p, 0., 0., &lat1, &lon1);
3655 p.x = (int)xgeom->xmax;
3656 p.y = (int)xgeom->ymax;
3657 Transform(&p, 0., 0., &lat2, &lon2);
3658 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3661 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3662 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3664 OGRMultiPoint *pGeo = (OGRMultiPoint *)xgeom->pogrGeom;
3665 pobj->npt = pGeo->getNumGeometries();
3667 pobj->geoPtz = (
double *)malloc(pobj->npt * 3 *
sizeof(
double));
3668 pobj->geoPtMulti = (
double *)malloc(pobj->npt * 2 *
sizeof(
double));
3670 double *pdd = pobj->geoPtz;
3671 double *pdl = pobj->geoPtMulti;
3673 for (
int ip = 0; ip < pobj->npt; ip++) {
3674 OGRPoint *ppt = (OGRPoint *)(pGeo->getGeometryRef(ip));
3677 p.x = (int)ppt->getX();
3678 p.y = (int)ppt->getY();
3679 double depth = ppt->getZ();
3684 double snd_trans_x = 0.;
3685 double snd_trans_y = 0.;
3688 if (m_CIB.b_have_user_offsets) {
3690 Transform(&p, 0., 0., &lats, &lons);
3692 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(lats, lons);
3695 snd_trans_x = pmcd->user_xoff;
3696 snd_trans_y = pmcd->user_yoff;
3700 east -= pmcd->user_xoff / m_CIB.transform_x_rate;
3701 north -= pmcd->user_yoff / m_CIB.transform_y_rate;
3711 Transform(&p, snd_trans_x, snd_trans_y, &lat1, &lon1);
3719 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3729 pobj->Primitive_type = GEO_LINE;
3731 pobj->npt = xgeom->n_max_vertex;
3732 pobj->geoPt = (pt *)xgeom->vertex_array;
3733 xgeom->vertex_array = NULL;
3736 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3737 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3740 pobj->m_n_lsindex = xgeom->n_vector_indices;
3741 pobj->m_lsindex_array =
3742 xgeom->pvector_index;
3743 pobj->m_n_edge_max_points = 0;
3746 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3749 pc.x = (
short unsigned int)pobj->x;
3750 pc.y = (
short unsigned int)pobj->y;
3751 Transform(&pc, 0., 0., &latc, &lonc);
3753 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(latc, lonc);
3755 trans_WGS84_offset_x = pmcd->user_xoff;
3756 trans_WGS84_offset_y = pmcd->user_yoff;
3761 double lat1, lon1, lat2, lon2;
3764 p.x = (int)xgeom->xmin;
3765 p.y = (int)xgeom->ymin;
3766 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3768 p.x = (int)xgeom->xmax;
3769 p.y = (int)xgeom->ymax;
3770 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat2, &lon2);
3771 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3776 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3785 pobj->Primitive_type = GEO_PRIM;
3792 if (!strncmp(pobj->FeatureName,
"OBSTRN", 6) ||
3793 !strncmp(pobj->FeatureName,
"WRECKS", 6) ||
3794 !strncmp(pobj->FeatureName,
"DEPCNT", 6) ||
3795 !strncmp(pobj->FeatureName,
"UWTROC", 6)) {
3796 pobj->m_bcategory_mutable =
true;
3798 pobj->m_bcategory_mutable =
false;
3811 if (geomtype != 4)
delete xgeom;
3815 m_CIB.transform_x_rate *
3816 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3818 m_CIB.transform_y_rate *
3819 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3821 m_CIB.transform_x_origin *
3822 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3824 m_CIB.transform_y_origin *
3825 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3829 pobj->x_origin -= trans_WGS84_offset_x;
3830 pobj->y_origin -= trans_WGS84_offset_y;
3833 pobj->auxParm3 = CHART_TYPE_CM93;
3839M_COVR_Desc *cm93chart::FindM_COVR_InWorkingSet(
double lat,
double lon) {
3842 if (m_CIB.m_cell_mcovr_list.GetCount() == 1) {
3843 wxList_Of_M_COVR_DescNode *node0 = m_CIB.m_cell_mcovr_list.GetFirst();
3844 if (node0) ret = node0->GetData();
3846 wxList_Of_M_COVR_DescNode *node = m_CIB.m_cell_mcovr_list.GetFirst();
3850 if (G_PtInPolygon_FL(pmcd->pvertices, pmcd->m_nvertices, lon, lat)) {
3855 node = node->GetNext();
3863wxPoint2DDouble cm93chart::FindM_COVROffset(
double lat,
double lon) {
3864 wxPoint2DDouble ret(0., 0.);
3867 wxList_Of_M_COVR_DescNode *node0 = m_CIB.m_cell_mcovr_list.GetFirst();
3870 ret.m_x = pmcd0->transform_WGS84_offset_x;
3871 ret.m_y = pmcd0->transform_WGS84_offset_y;
3875 if (m_CIB.m_cell_mcovr_list.GetCount() > 1) {
3876 wxList_Of_M_COVR_DescNode *node = m_CIB.m_cell_mcovr_list.GetFirst();
3880 if (G_PtInPolygon_FL(pmcd->pvertices, pmcd->m_nvertices, lon, lat)) {
3881 ret.m_x = pmcd->transform_WGS84_offset_x;
3882 ret.m_y = pmcd->transform_WGS84_offset_y;
3886 node = node->GetNext();
3894InitReturn cm93chart::CreateHeaderDataFromCM93Cell(
void) {
3896 wxFileName fn(m_FullPath);
3897 wxString ext = fn.GetExt();
3900 switch ((ext.mb_str())[(
size_t)0]) {
3930 m_Chart_Scale =
scale;
3936 switch (m_Chart_Scale) {
3938 bproc = m_pManager->m_bfoundZ;
3941 bproc = m_pManager->m_bfoundA;
3944 bproc = m_pManager->m_bfoundB;
3947 bproc = m_pManager->m_bfoundC;
3950 bproc = m_pManager->m_bfoundD;
3953 bproc = m_pManager->m_bfoundE;
3956 bproc = m_pManager->m_bfoundF;
3959 bproc = m_pManager->m_bfoundG;
3963 if (bproc)
return INIT_FAIL_NOERROR;
3966 switch (m_Chart_Scale) {
3968 m_pManager->m_bfoundZ =
true;
3971 m_pManager->m_bfoundA =
true;
3974 m_pManager->m_bfoundB =
true;
3977 m_pManager->m_bfoundC =
true;
3980 m_pManager->m_bfoundD =
true;
3983 m_pManager->m_bfoundE =
true;
3986 m_pManager->m_bfoundF =
true;
3989 m_pManager->m_bfoundG =
true;
3995 m_FullExtent.ELON = 179.0;
3996 m_FullExtent.WLON = -179.0;
3997 m_FullExtent.NLAT = 80.0;
3998 m_FullExtent.SLAT = -80.0;
3999 m_bExtentSet =
true;
4003 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
4004 *m_pCOVRTablePoints = 4;
4005 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
4006 float *pf = (
float *)malloc(2 * 4 *
sizeof(
float));
4010 *pfe++ = m_FullExtent.NLAT;
4011 *pfe++ = m_FullExtent.WLON;
4013 *pfe++ = m_FullExtent.NLAT;
4014 *pfe++ = m_FullExtent.ELON;
4016 *pfe++ = m_FullExtent.SLAT;
4017 *pfe++ = m_FullExtent.ELON;
4019 *pfe++ = m_FullExtent.SLAT;
4020 *pfe++ = m_FullExtent.WLON;
4025void cm93chart::ProcessMCOVRObjects(
int cell_index,
char subcell) {
4028 Object *pobject = m_CIB.pobject_block;
4031 while (iObj < m_CIB.m_nfeature_records) {
4032 if ((pobject != NULL)) {
4034 int iclass = pobject->otype;
4036 wxString sclass = m_pDict->GetClassName(iclass);
4038 if (sclass.IsSameAs(_T (
"_m_sor" ))) {
4040 m_pcovr_set->Find_MCD(cell_index, iObj, (
int)subcell);
4042 Extended_Geometry *xgeom = BuildGeom(pobject, NULL, iObj);
4046 double tmp_transform_x = 0.;
4047 double tmp_transform_y = 0.;
4050 for (
int jattr = 0; jattr < pobject->n_attributes; jattr++) {
4051 unsigned char *curr_attr = pab.GetNextAttr();
4052 unsigned char iattr = *curr_attr;
4053 wxString sattr = m_pDict->GetAttrName(iattr);
4054 char vtype = m_pDict->GetAttrType(iattr);
4055 unsigned char *aval = curr_attr + 1;
4058 float *pf = (
float *)aval;
4060 float __attribute__((aligned(16))) tf1;
4061 unsigned char *pucf = (
unsigned char *)pf;
4062 memcpy(&tf1, pucf, sizeof(
float));
4063 if (sattr.IsSameAs(_T ( "_wgsox" )))
4064 tmp_transform_x = tf1;
4065 else if (sattr.IsSameAs(_T ( "_wgsoy" )))
4066 tmp_transform_y = tf1;
4068 if (sattr.IsSameAs(_T (
"_wgsox" )))
4069 tmp_transform_x = *pf;
4070 else if (sattr.IsSameAs(_T (
"_wgsoy" )))
4071 tmp_transform_y = *pf;
4077 if (NULL != xgeom) {
4083 pmcd->m_cell_index = cell_index;
4084 pmcd->m_object_id = iObj;
4085 pmcd->m_subcell = (int)subcell;
4088 int npta = xgeom->contour_array[0];
4089 float_2Dpt *geoPt =
new float_2Dpt[npta + 2];
4090 float_2Dpt *ppt = geoPt;
4094 pmcd->m_covr_lon_max = -1000.;
4095 pmcd->m_covr_lon_min = 1000.;
4096 pmcd->m_covr_lat_max = -1000.;
4097 pmcd->m_covr_lat_min = 1000.;
4099 for (
int ip = 0; ip < npta; ip++) {
4101 p.x = (int)xgeom->vertex_array[ip + 1].m_x;
4102 p.y = (int)xgeom->vertex_array[ip + 1].m_y;
4104 Transform(&p, 0., 0., &lat, &lon);
4108 pmcd->m_covr_lon_max = wxMax(pmcd->m_covr_lon_max, lon);
4109 pmcd->m_covr_lon_min = wxMin(pmcd->m_covr_lon_min, lon);
4110 pmcd->m_covr_lat_max = wxMax(pmcd->m_covr_lat_max, lat);
4111 pmcd->m_covr_lat_min = wxMin(pmcd->m_covr_lat_min, lat);
4115 pmcd->m_nvertices = npta;
4116 pmcd->pvertices = geoPt;
4118 pmcd->m_covr_bbox.Set(pmcd->m_covr_lat_min, pmcd->m_covr_lon_min,
4119 pmcd->m_covr_lat_max, pmcd->m_covr_lon_max);
4123 pmcd->transform_WGS84_offset_x = tmp_transform_x;
4124 pmcd->transform_WGS84_offset_y = tmp_transform_y;
4126 pmcd->m_centerlat_cos =
4127 cos(((pmcd->m_covr_lat_min + pmcd->m_covr_lat_max) / 2.) * PI /
4131 m_pcovr_set->Add_Update_MCD(pmcd);
4134 free(xgeom->pvector_index);
4150bool cm93chart::UpdateCovrSet(
ViewPort *vpt) {
4152 std::vector<int> vpcells = GetVPCellArray(*vpt);
4157 for (
unsigned int i = 0; i < vpcells.size(); i++) {
4160 if (!m_pcovr_set->IsCovrLoaded(vpcells[i])) {
4161 if (loadcell_in_sequence(vpcells[i],
'0')) {
4162 ProcessMCOVRObjects(vpcells[i],
'0');
4165 m_pcovr_set->m_cell_hash[vpcells[i]] = 1;
4167 char loadcell_key =
'A';
4171 while (loadcell_in_sequence(vpcells[i], loadcell_key)) {
4174 ProcessMCOVRObjects(vpcells[i], loadcell_key);
4187bool cm93chart::IsPointInLoadedM_COVR(
double xc,
double yc) {
4190 return m_region.Contains(yc, xc);
4192 for (
unsigned int im = 0; im < m_pcovr_array_loaded.GetCount(); im++) {
4193 if (G_PtInPolygon_FL(m_pcovr_array_loaded[im]->pvertices,
4194 m_pcovr_array_loaded[im]->m_nvertices, xc, yc))
4201LLRegion cm93chart::GetValidRegion() {
return m_region; }
4203int cm93chart::loadcell_in_sequence(
int cellindex,
char subcell) {
4204 int rv = loadsubcell(cellindex, subcell);
4209int cm93chart::loadsubcell(
int cellindex, wxChar sub_char) {
4212 int ilat = cellindex / 10000;
4213 int ilon = cellindex % 10000;
4216 double dlat = m_dval / 3.;
4217 double dlon = m_dval / 3.;
4219 Get_CM93_Cell_Origin(cellindex, GetNativeScale(), &lat, &lon);
4221 "\n Attempting loadcell %d scale %lc, sub_char %lc at lat: %g/%g "
4223 cellindex, wxChar(m_scalechar[0]), sub_char, lat, lat + dlat, lon,
4227 int jlat = (int)(((ilat - 30) / m_dval) * m_dval) + 30;
4228 int jlon = (int)((ilon / m_dval) * m_dval);
4230 int ilatroot = (((ilat - 30) / 60) * 60) + 30;
4231 int ilonroot = (ilon / 60) * 60;
4234 file.Printf(_T (
"%04d%04d." ), jlat, jlon);
4235 file += m_scalechar;
4244 bool b_useNoFind =
true;
4245 if (m_noFindArray.GetCount() > 500) b_useNoFind =
false;
4248 fileroot.Printf(_T (
"%04d%04d" ), ilatroot, ilonroot);
4249 appendOSDirSep(&fileroot);
4250 fileroot.append(m_scalechar);
4251 appendOSDirSep(&fileroot);
4252 wxString key = fileroot;
4254 fileroot.Prepend(m_prefix);
4256 file.Prepend(fileroot);
4260 strncpy(sfile, file.mb_str(), 199);
4262 printf(
" filename: %s\n", sfile);
4265 bool bfound =
false;
4268 if (m_noFindArray.Index(key) == wxNOT_FOUND) {
4269 if (::wxFileExists(file))
4272 m_noFindArray.Add(key);
4275 if (::wxFileExists(file)) bfound =
true;
4281 if (m_noFindArray.Index(key +
".xz") == wxNOT_FOUND) {
4282 if (::wxFileExists(file +
".xz")) {
4283 compfile = file +
".xz";
4286 m_noFindArray.Add(key +
".xz");
4289 if (::wxFileExists(file +
".xz")) compfile = file +
".xz";
4294 if (!bfound && !compfile.Length()) {
4296 wxString new_scalechar = m_scalechar.Lower();
4299 file1.Printf(_T (
"%04d%04d." ), jlat, jlon);
4300 file1 += new_scalechar;
4301 file1[0] = sub_char;
4303 fileroot.Printf(_T (
"%04d%04d" ), ilatroot, ilonroot);
4304 appendOSDirSep(&fileroot);
4305 fileroot.append(new_scalechar);
4306 appendOSDirSep(&fileroot);
4310 fileroot.Prepend(m_prefix);
4312 file1.Prepend(fileroot);
4315 if (m_noFindArray.Index(key) == wxNOT_FOUND) {
4316 if (::wxFileExists(file1)) {
4320 m_noFindArray.Add(key);
4324 if (::wxFileExists(file1)) {
4332 if (m_noFindArray.Index(key +
".xz") == wxNOT_FOUND) {
4333 if (::wxFileExists(file1 +
".xz"))
4334 compfile = file1 +
".xz";
4336 m_noFindArray.Add(key +
".xz");
4339 if (::wxFileExists(file1 +
".xz")) compfile = file1 +
".xz";
4345 printf(
"noFind count: %d\n", (
int)m_noFindArray.GetCount());
4348 if (!bfound && !compfile.Length())
return 0;
4352 wxString msg(_T (
"Loading CM93 cell " ));
4358 m_LastFileName = file;
4361 if (compfile.Length()) {
4362 file = wxFileName::CreateTempFileName(wxFileName(compfile).GetFullName());
4363 if (!DecompressXZFile(compfile, file)) {
4371 strncpy(str, msg.mb_str(), 255);
4373 printf(
" %s\n", str);
4377 if (!Ingest_CM93_Cell((
const char *)file.mb_str(), &m_CIB)) {
4378 wxString msg(_T (
" cm93chart Error ingesting " ));
4382 if (compfile.Length()) wxRemoveFile(file);
4386 if (compfile.Length()) wxRemoveFile(file);
4391void cm93chart::SetUserOffsets(
int cell_index,
int object_id,
int subcell,
4392 int xoff,
int yoff) {
4393 M_COVR_Desc *pmcd = GetCoverSet()->Find_MCD(cell_index, object_id, subcell);
4395 pmcd->user_xoff = xoff;
4396 pmcd->user_yoff = yoff;
4397 pmcd->m_buser_offsets =
true;
4401wxPoint *cm93chart::GetDrawBuffer(
int nSize) {
4403 if (nSize > m_nDrawBufferSize) {
4404 wxPoint *tmp = m_pDrawBuffer;
4406 (wxPoint *)realloc(m_pDrawBuffer,
sizeof(wxPoint) * (nSize + 1));
4407 if (NULL == m_pDrawBuffer) {
4411 m_nDrawBufferSize = nSize + 1;
4413 return m_pDrawBuffer;
4420cm93manager::cm93manager(
void) {
4433cm93manager::~cm93manager(
void) {
delete m_pcm93Dict; }
4435bool cm93manager::Loadcm93Dictionary(
const wxString &name) {
4438 m_pcm93Dict = FindAndLoadDict(name);
4441 wxLogMessage(_T (
" Cannot load CM93 Dictionary." ));
4445 if (!m_pcm93Dict->IsOk()) {
4446 wxLogMessage(_T (
" Error in loading CM93 Dictionary." ));
4452 }
else if (!m_pcm93Dict->IsOk()) {
4453 wxLogMessage(_T (
" CM93 Dictionary is not OK." ));
4467 wxFileName fn(file);
4468 wxString path = fn.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
4472 while (i < path.Len()) {
4473 target.Append(path[i]);
4474 if (path[i] == fn.GetPathSeparator()) {
4475 if (pdict->LoadDictionary(target)) {
4479 if (pdict->LoadDictionary(target + _T (
"CM93ATTR" ))) {
4488 strncpy(t, target.mb_str(), 99);
4490 if (retval == NULL)
delete pdict;
4498cm93compchart::cm93compchart() {
4499 m_ChartType = CHART_TYPE_CM93COMP;
4500 m_pDictComposite = NULL;
4503 m_FullPath = _T (
"CM93" );
4506 m_Description = _T (
"CM93Composite" );
4509 m_datum_str = _T (
"WGS84" );
4510 m_SoundingsDatum = _T (
"Unknown" );
4512 for (
int i = 0; i < 8; i++) m_pcm93chart_array[i] = NULL;
4514 m_pcm93chart_current = NULL;
4521 SetSpecialOutlineCellIndex(0, 0, 0);
4522 m_last_cell_adjustvp = NULL;
4527cm93compchart::~cm93compchart() {
4532 for (
int i = 0; i < 8; i++)
delete m_pcm93chart_array[i];
4534 delete m_pDictComposite;
4539InitReturn cm93compchart::Init(
const wxString &name, ChartInitFlag flags) {
4542 wxFileName fn(name);
4548 if (!fn.FileExists()) {
4550 if (wxDir::Exists(name)) {
4552 appendOSDirSep(&target);
4554 appendOSDirSep(&path);
4556 wxString msg(_T (
" CM93Composite Chart Init cannot find " ));
4559 return INIT_FAIL_REMOVE;
4564 path = fn.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
4568 wxFileName file_path(path);
4569 file_path.RemoveLastDir();
4570 file_path.RemoveLastDir();
4572 target = file_path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
4575 m_prefixComposite = target;
4577 wxString msg(_T (
"CM93Composite Chart Root is " ));
4578 msg.Append(m_prefixComposite);
4581 if (flags == THUMB_ONLY) {
4587 if (flags == HEADER_ONLY)
return CreateHeaderData();
4590 if (!m_pDictComposite) {
4591 if (!m_pDictComposite)
4592 m_pDictComposite = FindAndLoadDictFromDir(path);
4594 if (!m_pDictComposite) {
4596 _T (
" CM93Composite Chart Init cannot locate CM93 dictionary." ));
4597 return INIT_FAIL_REMOVE;
4602 SetColorScheme(m_global_color_scheme,
false);
4604 bReadyToRender =
true;
4609void cm93compchart::Activate(
void) {
4636void cm93compchart::Deactivate(
void) {
4637 if (pPopupDetailSlider) {
4638 pPopupDetailSlider->Destroy();
4639 pPopupDetailSlider = NULL;
4643double scale_breaks[] = {
4658int cm93compchart::GetCMScaleFromVP(
const ViewPort &vpt) {
4661 double scale_mpp_adj = scale_mpp;
4663 double scale_breaks_adj[7];
4665 for (
int i = 0; i < 7; i++) scale_breaks_adj[i] = scale_breaks[i];
4667 if (g_cm93_zoom_factor) {
4670 double efactor = ( double ) ( g_cm93_zoom_factor ) * ( .176 / 7. );
4671 for (
int i=0 ; i < 7 ; i++ )
4673 double efr = efactor * ( 7 - i );
4674 scale_breaks_adj[i] = scale_breaks[i] * pow ( 10., efr );
4676 printf (
"g_cm93_zoom_factor: %2d efactor: %6g efr:%6g, scale_breaks[i]:%6g scale_breaks_adj[i]: %6g\n",
4677 g_cm93_zoom_factor, efactor, efr, scale_breaks[i], scale_breaks_adj[i] );
4681 double efr = (double)g_cm93_zoom_factor * pow(scale_mpp, -.05);
4682 scale_mpp_adj *= pow(.6, efr);
4686 int cmscale_calc = 7;
4688 while (cmscale_calc > 0) {
4689 if (scale_mpp_adj < scale_breaks_adj[brk_index])
break;
4696 double zoom_factor = scale_breaks[7 - cmscale_calc] / vpt.
chart_scale;
4697 if (zoom_factor > 4.0) {
4698 if (cmscale_calc < 7) cmscale_calc++;
4701 return cmscale_calc;
4704void cm93compchart::SetVPParms(
const ViewPort &vpt) {
4707 int cmscale = GetCMScaleFromVP(vpt);
4708 m_cmscale = PrepareChartScale(vpt, cmscale,
false);
4712 if (m_pcm93chart_array[cmscale]) {
4713 if (!m_EdDate.IsValid() ||
4714 !m_pcm93chart_array[cmscale]->GetEditionDate().IsValid() ||
4715 m_pcm93chart_array[cmscale]->GetEditionDate().IsLaterThan(m_EdDate))
4716 m_EdDate = m_pcm93chart_array[cmscale]->GetEditionDate();
4720int cm93compchart::PrepareChartScale(
const ViewPort &vpt,
int cmscale,
4723 printf(
"\non SetVPParms, cmscale:%d, %c\n", cmscale,
4724 (
char)(
'A' + cmscale - 1));
4727 bool cellscale_is_useable =
false;
4728 bool b_nochart =
false;
4730 while (!cellscale_is_useable) {
4732 while (NULL == m_pcm93chart_array[cmscale]) {
4733 if (Is_CM93Cell_Present(m_prefixComposite, vpt.
clat, vpt.
clon, cmscale)) {
4735 printf(
" chart %c at VP clat/clon is present\n",
4736 (
char)(
'A' + cmscale - 1));
4738 m_pcm93chart_array[cmscale] =
new cm93chart();
4740 ext = (wxChar)(
'A' + cmscale - 1);
4741 if (cmscale == 0) ext =
'Z';
4743 wxString file_dummy = _T (
"CM93." );
4746 m_pcm93chart_array[cmscale]->SetCM93Dict(m_pDictComposite);
4747 m_pcm93chart_array[cmscale]->SetCM93Prefix(m_prefixComposite);
4748 m_pcm93chart_array[cmscale]->SetCM93Manager(m_pcm93mgr);
4750 m_pcm93chart_array[cmscale]->SetColorScheme(m_global_color_scheme);
4751 m_pcm93chart_array[cmscale]->Init(file_dummy, FULL_INIT);
4752 }
else if (cmscale == 0) {
4759 " CM93 finds no chart of any scale present at Lat/Lon %g %g\n",
4769 printf(
" no %c scale chart present, adjusting cmscale to %c\n",
4770 (
char)(
'A' + cmscale), (
char)(
'A' + cmscale - 1));
4774 m_pcm93chart_current = m_pcm93chart_array[cmscale];
4777 if (g_bDebugCM93) printf(
" b_nochart return\n");
4779 m_pcm93chart_current = NULL;
4780 for (
int i = 0; i < 8; i++) {
4781 delete m_pcm93chart_array[i];
4782 m_pcm93chart_array[i] = NULL;
4788 if (m_pcm93chart_current) {
4791 m_pcm93chart_current->SetVPParms(vpt);
4795 float yc = vpt.
clat;
4796 float xc = vpt.
clon;
4798 if (!m_pcm93chart_current->GetCoverSet()->GetCoverCount()) {
4800 printf(
" chart %c has no M_COVR\n", (
char)(
'A' + cmscale - 1));
4803 if (m_pcm93chart_current->IsPointInLoadedM_COVR(xc, yc)) {
4805 printf(
" chart %c contains clat/clon\n", (
char)(
'A' + cmscale - 1));
4807 cellscale_is_useable =
true;
4821 else if (vpt.b_quilt && vpt.b_FullScreenQuilt) {
4824 covr_set *pcover = m_pcm93chart_current->GetCoverSet();
4826 bool boverlap =
false;
4827 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
4830 if (!(vp.GetBBox().IntersectOut(mcd->m_covr_bbox))) {
4835 if (boverlap) cellscale_is_useable =
true;
4839 if (!cellscale_is_useable) {
4847 printf(
" VP is not in M_COVR, adjusting cmscale to %c\n",
4848 (
char)(
'A' + cmscale - 1));
4855 double zoom_factor = scale_breaks[7 - cmscale] / vpt.
chart_scale;
4857 if (zoom_factor > 4.0) {
4860 float yc = vpt.
clat;
4861 float xc = vpt.
clon;
4864 FillScaleArray(vpt.
clat, vpt.
clon);
4865 int new_scale = cmscale;
4866 bool b_found =
false;
4867 while (new_scale <= 7) {
4868 if (m_bScale_Array[new_scale]) {
4869 double new_zoom_factor =
4873 if (new_zoom_factor < 1.0) {
4875 new_scale = cmscale;
4879 if (new_zoom_factor < 4.0) {
4880 if (NULL == m_pcm93chart_array[new_scale]) {
4881 m_pcm93chart_array[new_scale] =
new cm93chart();
4883 ext = (wxChar)(
'A' + new_scale - 1);
4884 if (new_scale == 0) ext =
'Z';
4886 wxString file_dummy = _T (
"CM93." );
4889 m_pcm93chart_array[new_scale]->SetCM93Dict(m_pDictComposite);
4890 m_pcm93chart_array[new_scale]->SetCM93Prefix(m_prefixComposite);
4891 m_pcm93chart_array[new_scale]->SetCM93Manager(m_pcm93mgr);
4893 m_pcm93chart_array[new_scale]->SetColorScheme(
4894 m_global_color_scheme);
4895 m_pcm93chart_array[new_scale]->Init(file_dummy, FULL_INIT);
4898 m_pcm93chart_array[new_scale]->SetVPParms(vpt);
4899 if (m_pcm93chart_array[new_scale]->IsPointInLoadedM_COVR(xc, yc)) {
4908 cmscale = new_scale;
4909 m_pcm93chart_current = m_pcm93chart_array[cmscale];
4919void cm93compchart::FillScaleArray(
double lat,
double lon) {
4920 for (
int cmscale = 0; cmscale < 8; cmscale++)
4921 m_bScale_Array[cmscale] =
4922 Is_CM93Cell_Present(m_prefixComposite, lat, lon, cmscale);
4928wxString cm93compchart::GetPubDate() {
4931 if (NULL != m_pcm93chart_current)
4933 data.Printf(_T (
"%4d" ), m_current_cell_pub_date);
4935 data = _T (
"????" );
4939int cm93compchart::GetNativeScale() {
4940 if (m_pcm93chart_current)
4941 return m_pcm93chart_current->GetNativeScale();
4946double cm93compchart::GetNormalScaleMin(
double canvas_scale_factor,
4947 bool b_allow_overzoom) {
4951 if (m_pcm93chart_current) {
4953 if (m_pcm93chart_current->m_last_vp.IsValid()) {
4954 FillScaleArray(m_pcm93chart_current->m_last_vp.clat,
4955 m_pcm93chart_current->m_last_vp.clon);
4959 while (cmscale > 0) {
4960 if (m_bScale_Array[cmscale])
break;
4968 return 20000000. / oz_factor;
4970 return 3000000. / oz_factor;
4972 return 1000000. / oz_factor;
4974 return 200000. / oz_factor;
4976 return 100000. / oz_factor;
4978 return 50000. / oz_factor;
4980 return 20000. / oz_factor;
4984 return 500. / oz_factor;
4990double cm93compchart::GetNormalScaleMax(
double canvas_scale_factor,
4992 return (180. / 360.) * PI * 2 *
4993 (WGS84_semimajor_axis_meters / (canvas_width / canvas_scale_factor));
4997wxPoint GetPixFromLLVP(
double lat,
double lon,
const ViewPort &VPoint) {
4999 double easting, northing;
5001 double s, y3, s0, y30;
5002 double z = WGS84_semimajor_axis_meters * mercator_k0;
5007 if (lon * VPoint.
clon < 0.) {
5015 if (fabs(xlon - VPoint.
clon) > 180.) {
5016 if (xlon > VPoint.
clon)
5021 easting = (xlon - VPoint.
clon) * DEGREE * z;
5023 s = sin(lat * DEGREE);
5024 y3 = (.5 * log((1 + s) / (1 - s))) * z;
5026 s0 = sin(VPoint.
clat * DEGREE);
5027 y30 = (.5 * log((1 + s0) / (1 - s0))) * z;
5028 northing = y3 - y30;
5034 r.x = (int)round((VPoint.
pix_width / 2) + epix);
5035 r.y = (int)round((VPoint.
pix_height / 2) - npix);
5042void cm93compchart::GetValidCanvasRegion(
const ViewPort &VPoint,
5046 VPoint, g_bopengl ? VPoint.rv_rect : screen_region);
5047 *pValidRegion = ret;
5050OCPNRegion cm93compchart::GetValidScreenCanvasRegion(
5058 if (m_pcm93chart_current) {
5059 int chart_native_scale = m_pcm93chart_current->GetNativeScale();
5061 for (
unsigned int im = 0;
5062 im < m_pcm93chart_current->m_pcovr_array_loaded.GetCount(); im++) {
5063 M_COVR_Desc *pmcd = (m_pcm93chart_current->m_pcovr_array_loaded[im]);
5068 if (vp.GetBBox().IntersectOut(pmcd->m_covr_bbox))
continue;
5070 wxPoint *DrawBuf = m_pcm93chart_current->GetDrawBuffer(pmcd->m_nvertices);
5073 ScreenRegion, pmcd->m_nvertices, (
float *)pmcd->pvertices,
5074 chart_native_scale, DrawBuf);
5076 if (rgn_covr.IsOk())
5077 ret_region.Union(rgn_covr);
5086LLRegion cm93compchart::GetValidRegion() {
5087 if (m_pcm93chart_current)
return m_pcm93chart_current->GetValidRegion();
5092bool cm93compchart::RenderRegionViewOnGL(
const wxGLContext &glc,
5095 const LLRegion &Region) {
5101 return DoRenderRegionViewOnGL(glc, VPoint, RectRegion, Region);
5104bool cm93compchart::DoRenderRegionViewOnGL(
const wxGLContext &glc,
5107 const LLRegion &Region) {
5114 bool render_return =
false;
5115 if (m_pcm93chart_current == 0)
return render_return;
5123 if (VPoint.b_quilt) {
5124 LLRegion vpr_empty = Region;
5125 LLRegion chart_region = GetValidRegion();
5144 if (!chart_region.Empty()) vpr_empty.Subtract(chart_region);
5146 if (!vpr_empty.Empty() &&
5150 int cmscale_save = m_cmscale;
5152 LLRegion region_vect[8];
5156 while (!vpr_empty.Empty() && m_cmscale) {
5158 m_cmscale = PrepareChartScale(vp, m_cmscale - 1,
false);
5160 if (m_pcm93chart_current) {
5161 LLRegion sscale_region = GetValidRegion();
5164 region_vect[m_cmscale] = sscale_region;
5165 region_vect[m_cmscale].Intersect(vpr_empty);
5168 vpr_empty.Subtract(sscale_region);
5175 for (
int i = 0; i < 8; i++) {
5176 if (!region_vect[i].Empty()) {
5177 m_cmscale = PrepareChartScale(vp, i,
false);
5178 if (m_pcm93chart_current)
5179 render_return |= m_pcm93chart_current->RenderRegionViewOnGL(
5180 glc, vp, RectRegion, region_vect[i]);
5185 m_cmscale = cmscale_save;
5186 m_pcm93chart_current = m_pcm93chart_array[m_cmscale];
5190 if (m_pcm93chart_current) {
5191 render_return |= m_pcm93chart_current->RenderRegionViewOnGL(
5192 glc, vp, RectRegion, Region);
5193 m_Name = m_pcm93chart_current->GetName();
5198 if (m_pcm93chart_current) {
5199 render_return = m_pcm93chart_current->RenderRegionViewOnGL(
5200 glc, vp, RectRegion, Region);
5201 m_Name = m_pcm93chart_current->GetLastFileName();
5206 if (VPoint.m_projection_type != PROJECTION_MERCATOR)
5207 return render_return;
5209 if (!m_pcm93chart_current)
return render_return;
5212 if (m_cell_index_special_outline) {
5214 glChartCanvas *glc = gFrame->GetPrimaryCanvas()->GetglCanvas();
5221 covr_set *pcover = m_pcm93chart_current->GetCoverSet();
5223 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
5225 if ((pmcd->m_cell_index == m_cell_index_special_outline) &&
5226 (pmcd->m_object_id == m_object_id_special_outline) &&
5227 (pmcd->m_subcell == m_subcell_special_outline))
5237 float_2Dpt *p = pmcd->pvertices;
5238 wxPoint *pwp = m_pcm93chart_current->GetDrawBuffer(pmcd->m_nvertices);
5240 for (
int ip = 0; ip < pmcd->m_nvertices; ip++) {
5242 if (fabs(plon - VPoint.
clon) > 180.) {
5243 if (plon > VPoint.
clon)
5249 double easting, northing, epix, npix;
5250 toSM(p->y, plon + 360., VPoint.
clat, VPoint.
clon + 360, &easting,
5256 easting -= pmcd->user_xoff;
5259 northing -= pmcd->user_yoff;
5264 pwp[ip].x = (int)round((VPoint.
pix_width / 2) + epix);
5265 pwp[ip].y = (int)round((VPoint.
pix_height / 2) - npix);
5272 wxPen pen(wxTheColourDatabase->Find(_T (
"YELLOW" )), 3);
5276 pen.SetStyle(wxPENSTYLE_USER_DASH);
5277 pen.SetDashes(2, dash1);
5281 for (
int iseg = 0; iseg < pmcd->m_nvertices - 1; iseg++) {
5282 int x0 = pwp[iseg].x;
5283 int y0 = pwp[iseg].y;
5284 int x1 = pwp[iseg + 1].x;
5285 int y1 = pwp[iseg + 1].y;
5287 ClipResult res = cohen_sutherland_line_clip_i(
5288 &x0, &y0, &x1, &y1, 0, VPoint.
pix_width, 0,
5303 return render_return;
5306bool cm93compchart::RenderRegionViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint,
5313 return DoRenderRegionViewOnDC(dc, VPoint, Region);
5316bool cm93compchart::RenderViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint) {
5321 return DoRenderRegionViewOnDC(dc, VPoint, vpr);
5324bool cm93compchart::DoRenderRegionViewOnDC(wxMemoryDC &dc,
5331 printf(
"\nOn DoRenderRegionViewOnDC Ref scale is %d, %c\n", m_cmscale,
5332 (
char)(
'A' + m_cmscale - 1));
5334 while (upd.HaveRects()) {
5335 wxRect rect = upd.GetRect();
5336 printf(
" Region Rect: %d %d %d %d\n", rect.x, rect.y, rect.width,
5345 bool render_return =
false;
5346 if (m_pcm93chart_current) {
5347 m_pcm93chart_current->SetVPParms(vp);
5351 if (VPoint.b_quilt) {
5354 OCPNRegion chart_region = GetValidScreenCanvasRegion(vp, Region);
5358 "On DoRenderRegionViewOnDC : Intersecting Ref region rectangles\n");
5360 while (upd.HaveRects()) {
5361 wxRect rect = upd.GetRect();
5362 printf(
" Region Rect: %d %d %d %d\n", rect.x, rect.y, rect.width,
5368 if (!chart_region.IsEmpty()) vpr_empty.Subtract(chart_region);
5370 if (!vpr_empty.Empty() &&
5374#ifdef ocpnUSE_DIBSECTION
5379 if (!chart_region.IsEmpty())
5380 render_return = m_pcm93chart_current->RenderRegionViewOnDC(
5381 temp_dc, vp, chart_region);
5383 render_return =
false;
5386 cm93chart *m_pcm93chart_save = m_pcm93chart_current;
5392 if ((m_pDummyBM->GetWidth() != VPoint.rv_rect.width) ||
5393 (m_pDummyBM->GetHeight() != VPoint.rv_rect.height)) {
5398 if (NULL == m_pDummyBM)
5400 new wxBitmap(VPoint.rv_rect.width, VPoint.rv_rect.height, -1);
5402#ifdef ocpnUSE_DIBSECTION
5407 dumm_dc.SelectObject(*m_pDummyBM);
5408 dumm_dc.SetBackground(*wxBLACK_BRUSH);
5411 int cmscale_next = m_cmscale;
5415 while (!vpr_empty.Empty() && cmscale_next) {
5418 m_cmscale = PrepareChartScale(vp, cmscale_next,
false);
5419#ifdef ocpnUSE_DIBSECTION
5422 wxMemoryDC build_dc;
5425 if (m_pcm93chart_current) {
5427 printf(
" In DRRVOD, add quilt patch at %d, %c\n", m_cmscale,
5428 (
char)(
'A' + m_cmscale - 1));
5430 m_pcm93chart_current->RenderRegionViewOnDC(build_dc, vp, Region);
5432 OCPNRegion sscale_region = GetValidScreenCanvasRegion(vp, Region);
5435 sscale_region.Intersect(vpr_empty);
5439 while (upd.HaveRects()) {
5440 wxRect rect = upd.GetRect();
5441 dumm_dc.Blit(rect.x, rect.y, rect.width, rect.height, &build_dc,
5445 build_dc.SelectObject(wxNullBitmap);
5448 if (!sscale_region.IsEmpty()) vpr_empty.Subtract(sscale_region);
5456 while (updt.HaveRects()) {
5457 wxRect rect = updt.GetRect();
5458 dumm_dc.Blit(rect.x, rect.y, rect.width, rect.height, &temp_dc,
5462 temp_dc.SelectObject(wxNullBitmap);
5465 m_pcm93chart_current = m_pcm93chart_save;
5469 dumm_dc.SelectObject(wxNullBitmap);
5472 dc.SelectObject(*m_pDummyBM);
5474 render_return =
true;
5476 m_pcm93chart_current->RenderRegionViewOnDC(dc, vp, Region);
5477 render_return =
true;
5479 m_Name = m_pcm93chart_current->GetName();
5484 m_pcm93chart_current->RenderRegionViewOnDC(dc, vp, Region);
5485 m_Name = m_pcm93chart_current->GetLastFileName();
5493 if ((m_pDummyBM->GetWidth() != VPoint.
pix_width) ||
5494 (m_pDummyBM->GetHeight() != VPoint.
pix_height)) {
5500 if (NULL == m_pDummyBM)
5505 mdc.SelectObject(*m_pDummyBM);
5506 mdc.SetBackground(*wxBLACK_BRUSH);
5508 mdc.SelectObject(wxNullBitmap);
5510 dc.SelectObject(*m_pDummyBM);
5516 if (m_cell_index_special_outline && m_pcm93chart_current) {
5517 covr_set *pcover = m_pcm93chart_current->GetCoverSet();
5519 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
5521 if ((pmcd->m_cell_index == m_cell_index_special_outline) &&
5522 (pmcd->m_object_id == m_object_id_special_outline) &&
5523 (pmcd->m_subcell == m_subcell_special_outline))
5533 float_2Dpt *p = pmcd->pvertices;
5534 wxPoint *pwp = m_pcm93chart_current->GetDrawBuffer(pmcd->m_nvertices);
5536 for (
int ip = 0; ip < pmcd->m_nvertices; ip++) {
5538 if (fabs(plon - VPoint.
clon) > 180.) {
5539 if (plon > VPoint.
clon)
5545 double easting, northing, epix, npix;
5546 toSM(p->y, plon + 360., VPoint.
clat, VPoint.
clon + 360, &easting,
5552 easting -= pmcd->user_xoff;
5555 northing -= pmcd->user_yoff;
5560 pwp[ip].x = (int)round((VPoint.
pix_width / 2) + epix);
5561 pwp[ip].y = (int)round((VPoint.
pix_height / 2) - npix);
5584 dc.SetPen(wxPen(wxTheColourDatabase->Find(_T (
"YELLOW" )), 4,
5585 wxPENSTYLE_LONG_DASH));
5587 for (
int iseg = 0; iseg < pmcd->m_nvertices - 1; iseg++) {
5588 int x0 = pwp[iseg].x;
5589 int y0 = pwp[iseg].y;
5590 int x1 = pwp[iseg + 1].x;
5591 int y1 = pwp[iseg + 1].y;
5593 ClipResult res = cohen_sutherland_line_clip_i(
5594 &x0, &y0, &x1, &y1, 0, VPoint.
pix_width, 0,
5601 dc.DrawLine(x0, y0, x1, y1);
5609 return render_return;
5612void cm93compchart::UpdateRenderRegions(
const ViewPort &VPoint) {
5613 OCPNRegion full_screen_region(0, 0, VPoint.rv_rect.width,
5614 VPoint.rv_rect.height);
5620 if (m_pcm93chart_current) {
5621 m_pcm93chart_current->SetVPParms(vp);
5625 if (VPoint.b_quilt) {
5627 for (
int i = 0; i < 8; i++) {
5628 if (m_pcm93chart_array[i])
5629 m_pcm93chart_array[i]->m_render_region.Clear();
5635 GetValidScreenCanvasRegion(vp, full_screen_region);
5636 m_pcm93chart_current->m_render_region = chart_region;
5638 if (!chart_region.IsEmpty()) vpr_empty.Subtract(chart_region);
5640 if (!vpr_empty.Empty() &&
5644 cm93chart *m_pcm93chart_save = m_pcm93chart_current;
5646 int cmscale_next = m_cmscale;
5648 while (!vpr_empty.Empty() && cmscale_next) {
5651 m_cmscale = PrepareChartScale(vp, cmscale_next,
false);
5653 if (m_pcm93chart_current) {
5655 GetValidScreenCanvasRegion(vp, full_screen_region);
5656 sscale_region.Intersect(vpr_empty);
5657 m_pcm93chart_current->m_render_region = sscale_region;
5660 if (!sscale_region.IsEmpty()) vpr_empty.Subtract(sscale_region);
5666 m_pcm93chart_current = m_pcm93chart_save;
5672void cm93compchart::SetSpecialCellIndexOffset(
int cell_index,
int object_id,
5673 int subcell,
int xoff,
int yoff) {
5674 m_special_offset_x = xoff;
5675 m_special_offset_y = yoff;
5677 if (m_pcm93chart_current)
5678 m_pcm93chart_current->SetUserOffsets(cell_index, object_id, subcell, xoff,
5682bool cm93compchart::RenderNextSmallerCellOutlines(
ocpnDC &dc,
ViewPort &vp,
5684 if (m_cmscale >= 7)
return false;
5687 if (!glcc)
return false;
5694 int nss = m_cmscale + 1;
5703 bool bdrawn =
false;
5712 if(nss_max > m_cmscale+3)
5713 nss_max = m_cmscale+3;
5716 while (nss <= nss_max && (!bdrawn || (vp.
chart_scale < 3e6))) {
5717 cm93chart *psc = m_pcm93chart_array[nss];
5720 m_pcm93chart_array[nss] =
new cm93chart();
5721 psc = m_pcm93chart_array[nss];
5723 wxChar ext = (wxChar)(
'A' + nss - 1);
5724 if (nss == 0) ext =
'Z';
5726 wxString file_dummy = _T (
"CM93." );
5729 psc->SetCM93Dict(m_pDictComposite);
5730 psc->SetCM93Prefix(m_prefixComposite);
5731 psc->SetCM93Manager(m_pcm93mgr);
5733 psc->SetColorScheme(m_global_color_scheme);
5734 psc->Init(file_dummy, FULL_INIT);
5740 psc->UpdateCovrSet(&vp);
5743 covr_set *pcover = psc->GetCoverSet();
5745 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
5748 if (vp.GetBBox().IntersectOut(mcd->m_covr_bbox))
continue;
5750 wxPoint *pwp = psc->GetDrawBuffer(mcd->m_nvertices);
5751 bdrawn = RenderCellOutlines(dc, vp, pwp, mcd);
5759 glDisable(GL_LINE_STIPPLE);
5760 glDisable(GL_LINE_SMOOTH);
5761 glDisable(GL_BLEND);
5767bool cm93compchart::RenderCellOutlines(
ocpnDC &dc,
ViewPort &vp, wxPoint *pwp,
5769 float_2Dpt *p = mcd->pvertices;
5770 int np = mcd->m_nvertices;
5772 for (
int ip = 0; ip < np; ip++, p++) {
5782 wxPoint p0 = pwp[0];
5783 for (
int ip = 1; ip < np; ip++) {
5784 if (((p0.x > vp.
pix_width) && (pwp[ip].x < 0)) ||
5785 ((p0.x < 0) && (pwp[ip].x > vp.
pix_width)))
5791 dc.DrawLines(mcd->m_nvertices, pwp, 0, 0,
false);
5795void cm93compchart::GetPointPix(ObjRazRules *rzRules,
float rlat,
float rlon,
5797 m_pcm93chart_current->GetPointPix(rzRules, rlat, rlon, r);
5800void cm93compchart::GetPointPix(ObjRazRules *rzRules, wxPoint2DDouble *en,
5801 wxPoint *r,
int nPoints) {
5802 m_pcm93chart_current->GetPointPix(rzRules, en, r, nPoints);
5805void cm93compchart::GetPixPoint(
int pixx,
int pixy,
double *plat,
double *plon,
5807 m_pcm93chart_current->GetPixPoint(pixx, pixy, plat, plon, vpt);
5810void cm93compchart::UpdateLUPs(
s57chart *pOwner) {
5811 for (
int i = 0; i < 8; i++) {
5812 if (m_pcm93chart_array[i]) m_pcm93chart_array[i]->UpdateLUPs(pOwner);
5816std::list<S57Obj *> *cm93compchart::GetAssociatedObjects(S57Obj *obj) {
5817 if (m_pcm93chart_current)
5818 return m_pcm93chart_current->GetAssociatedObjects(obj);
5823void cm93compchart::InvalidateCache() {
5824 for (
int i = 0; i < 8; i++) {
5825 if (m_pcm93chart_array[i]) m_pcm93chart_array[i]->InvalidateCache();
5829void cm93compchart::ForceEdgePriorityEvaluate(
void) {
5830 for (
int i = 0; i < 8; i++) {
5831 if (m_pcm93chart_array[i])
5832 m_pcm93chart_array[i]->ForceEdgePriorityEvaluate();
5836void cm93compchart::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
5837 m_global_color_scheme = cs;
5839 for (
int i = 0; i < 8; i++) {
5840 if (m_pcm93chart_array[i])
5841 m_pcm93chart_array[i]->SetColorScheme(cs, bApplyImmediate);
5845ListOfObjRazRules *cm93compchart::GetObjRuleListAtLatLon(
float lat,
float lon,
5846 float select_radius,
5848 int selection_mask) {
5854 if (!VPoint->b_quilt)
5855 if (m_pcm93chart_current)
5856 return m_pcm93chart_current->GetObjRuleListAtLatLon(lat, alon,
5857 select_radius, &vp);
5860 ListOfObjRazRules *ret_ptr =
new ListOfObjRazRules;
5864 UpdateRenderRegions(*VPoint);
5870 for (
int i = 0; i < 8; i++) {
5871 if (m_pcm93chart_array[i]) {
5872 if (!m_pcm93chart_array[i]->m_render_region.IsEmpty()) {
5873 if (wxInRegion == m_pcm93chart_array[i]->m_render_region.Contains(p))
5874 return m_pcm93chart_array[i]->GetObjRuleListAtLatLon(
5875 lat, alon, select_radius, &vp, selection_mask);
5881 ListOfObjRazRules *ret_ptr =
new ListOfObjRazRules;
5887std::unordered_map<unsigned, VE_Element *> &cm93compchart::Get_ve_hash(
void) {
5888 return m_pcm93chart_current->Get_ve_hash();
5891std::unordered_map<unsigned, VC_Element *> &cm93compchart::Get_vc_hash(
void) {
5892 return m_pcm93chart_current->Get_vc_hash();
5903 m_last_cell_adjustvp = m_pcm93chart_current;
5911 if (m_pcm93chart_current)
return false;
5920 int cmscale = GetCMScaleFromVP(
5923 int cmscale_actual = PrepareChartScale(
5924 vp_proposed, cmscale,
5928 printf(
" In AdjustVP, adjustment subchart scale is %c\n",
5929 (
char)(
'A' + cmscale_actual - 1));
5935 bool single_adjust =
false;
5936 if (m_pcm93chart_array[cmscale_actual])
5938 m_pcm93chart_array[cmscale_actual]->AdjustVP(vp_last, vp_proposed);
5940 if (m_cmscale != cmscale_actual)
return false;
5944 if (vp_last.b_quilt)
return false;
5946 return single_adjust;
5949ThumbData *cm93compchart::GetThumbData(
int tnx,
int tny,
float lat,
float lon) {
5953InitReturn cm93compchart::CreateHeaderData() {
5954 m_Chart_Scale = 20000000;
5960 wxDir dirt(m_prefixComposite);
5962 wxRegEx test(
"[0-9]+");
5964 bool b_cont = dirt.GetFirst(&candidate);
5967 if (test.Matches(candidate) && (candidate.Len() == 8)) {
5968 wxString dir = m_prefixComposite;
5970 if (wxDir::Exists(dir)) {
5971 wxFileName name(dir);
5972 wxString num_name = name.GetName();
5974 if (num_name.ToLong(&number)) {
5975 int ilat = number / 10000;
5976 int ilon = number % 10000;
5978 int lat_base = (ilat - 270) / 3.;
5979 int lon_base = ilon / 3.;
5980 extent_rect.Union(wxRect(lon_base, lat_base, 20, 20));
5984 b_cont = dirt.GetNext(&candidate);
5988 m_FullExtent.ELON = ((double)extent_rect.x + (
double)extent_rect.width);
5989 m_FullExtent.WLON = ((double)extent_rect.x);
5990 m_FullExtent.NLAT = ((double)extent_rect.y + (
double)extent_rect.height);
5991 m_FullExtent.SLAT = ((double)extent_rect.y);
5992 m_bExtentSet =
true;
5996 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
5997 *m_pCOVRTablePoints = 4;
5998 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
5999 float *pf = (
float *)malloc(2 * 4 *
sizeof(
float));
6003 *pfe++ = m_FullExtent.NLAT;
6004 *pfe++ = m_FullExtent.WLON;
6006 *pfe++ = m_FullExtent.NLAT;
6007 *pfe++ = m_FullExtent.ELON;
6009 *pfe++ = m_FullExtent.SLAT;
6010 *pfe++ = m_FullExtent.ELON;
6012 *pfe++ = m_FullExtent.SLAT;
6013 *pfe++ = m_FullExtent.WLON;
6018cm93_dictionary *cm93compchart::FindAndLoadDictFromDir(
const wxString &dir) {
6023 if (pdict->LoadDictionary(dir))
return pdict;
6028 wxString path = dir;
6032 while (i < path.Len()) {
6033 target.Append(path[i]);
6034 if (path[i] == wxFileName::GetPathSeparator()) {
6038 if (pdict->LoadDictionary(target)) {
6052 wxFileName fnc(dir);
6053 wxString found_dict_file_name;
6057 path = fnc.GetPath(wxPATH_GET_VOLUME);
6059 wxString msg = _T (
" Looking harder for CM93 dictionary in " );
6063 if ((path.Len() == 0) || path.IsSameAs(fnc.GetPathSeparator())) {
6065 wxLogMessage(_T (
"Early break1" ));
6071 if ((wxNOT_FOUND == path.Lower().Find(_T (
"cm93" )))) {
6073 wxLogMessage(_T (
"Early break2" ));
6081 if (dir.IsOpened()) {
6084 dir.Traverse(cm93Dictionary);
6085 bdone = found_dict_file_name.Len() != 0;
6091 if (found_dict_file_name.Len()) {
6092 wxFileName fnd(found_dict_file_name);
6094 fnd.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
6096 if (pdict->LoadDictionary(dpath)) retval = pdict;
6099 if (NULL == retval)
delete pdict;
6104void cm93compchart::CloseandReopenCurrentSubchart(
void) {
6105 delete m_pcm93chart_current;
6106 m_pcm93chart_current = NULL;
6107 m_pcm93chart_array[m_cmscale] = NULL;
6131 const wxPoint &pos,
const wxSize &size,
long style);
6134 wxString OnGetItemText(
long item,
long column)
const;
6135 int OnGetItemColumnImage(
long item,
long column)
const;
6140OCPNOffsetListCtrl::OCPNOffsetListCtrl(
CM93OffsetDialog *parent, wxWindowID
id,
6141 const wxPoint &pos,
const wxSize &size,
6143 : wxListCtrl(parent, id, pos, size, style) {
6147OCPNOffsetListCtrl::~OCPNOffsetListCtrl() {}
6149wxString OCPNOffsetListCtrl::OnGetItemText(
long item,
long column)
const {
6151 M_COVR_Desc *pmcd = m_parent->m_pcovr_array[item];
6155 ret.Printf(_T (
"%d" ), pmcd->m_cell_index);
6156 if (((
int)
'0') == pmcd->m_subcell)
6157 ret.Prepend(_T (
"0" ));
6159 char t = (char)pmcd->m_subcell;
6161 p.Printf(_T (
"%c" ), t);
6168 ret.Printf(_T (
"%d" ), pmcd->m_object_id);
6172 ret = m_parent->m_selected_chart_scale_char;
6176 ret.Printf(_T (
"%g" ), pmcd->transform_WGS84_offset_x);
6180 ret.Printf(_T (
"%g" ), pmcd->transform_WGS84_offset_y);
6184 ret.Printf(_T (
"%6.0f" ), pmcd->user_xoff * pmcd->m_centerlat_cos);
6188 ret.Printf(_T (
"%6.0f" ), pmcd->user_yoff * pmcd->m_centerlat_cos);
6197int OCPNOffsetListCtrl::OnGetItemColumnImage(
long item,
long column)
const {
6208EVT_CLOSE(CM93OffsetDialog::OnClose)
6213 m_pcompchart = NULL;
6218 m_selected_list_index = -1;
6219 m_selected_cell_index = 0;
6221 long wstyle = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER;
6222 wxDialog::Create(parent, -1, _(
"OpenCPN CM93 Cell Offset Adjustments"),
6223 wxPoint(0, 0), wxSize(800, 200), wstyle);
6229 wxBoxSizer *topSizer =
new wxBoxSizer(wxHORIZONTAL);
6234 long flags = wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_HRULES | wxLC_VRULES |
6237 flags |= wxLC_VIRTUAL;
6243 m_pListCtrlMCOVRs->Connect(
6244 wxEVT_COMMAND_LIST_ITEM_SELECTED,
6245 wxListEventHandler(CM93OffsetDialog::OnCellSelected), NULL,
this);
6247 int dx = GetCharWidth();
6248 int dy = GetCharHeight();
6251 m_pListCtrlMCOVRs->InsertColumn(tlCELL, _(
"Cell"), wxLIST_FORMAT_LEFT, width);
6254 m_pListCtrlMCOVRs->InsertColumn(tlMCOVR, _(
"M_COVR ID"), wxLIST_FORMAT_CENTER,
6258 m_pListCtrlMCOVRs->InsertColumn(tlSCALE, _(
"Cell Scale"),
6259 wxLIST_FORMAT_CENTER, width);
6262 m_pListCtrlMCOVRs->InsertColumn(tlXOFF, _(
"wgsox"), wxLIST_FORMAT_CENTER,
6266 m_pListCtrlMCOVRs->InsertColumn(tlYOFF, _(
"wgsoy"), wxLIST_FORMAT_CENTER,
6270 m_pListCtrlMCOVRs->InsertColumn(tlUXOFF, _(
"User X Offset"),
6271 wxLIST_FORMAT_CENTER, width);
6274 m_pListCtrlMCOVRs->InsertColumn(tlUYOFF, _(
"User Y Offset"),
6275 wxLIST_FORMAT_CENTER, width);
6277 topSizer->Add(m_pListCtrlMCOVRs, 1, wxEXPAND | wxALL, 0);
6279 wxBoxSizer *boxSizer02 =
new wxBoxSizer(wxVERTICAL);
6280 boxSizer02->AddSpacer(22);
6282 wxStaticText *pStaticTextXoff =
new wxStaticText(
6284 wxString::Format(_T(
"%s (%s)" ), _(
"User X Offset"), _(
"meters")),
6285 wxDefaultPosition, wxDefaultSize, 0);
6286 boxSizer02->Add(pStaticTextXoff, 0, wxALL, 0);
6289 new wxSpinCtrl(
this, wxID_ANY, wxEmptyString, wxDefaultPosition,
6290 wxSize(50, -1), wxSP_ARROW_KEYS, -10000, 10000, 0);
6291 m_pSpinCtrlXoff->Connect(wxEVT_COMMAND_SPINCTRL_UPDATED,
6292 wxCommandEventHandler(CM93OffsetDialog::OnOffSetSet),
6294 boxSizer02->Add(m_pSpinCtrlXoff, 0, wxEXPAND | wxALL, 0);
6296 wxStaticText *pStaticTextYoff =
new wxStaticText(
6298 wxString::Format(_T(
"%s (%s)" ), _(
"User Y Offset"), _(
"meters")),
6299 wxDefaultPosition, wxDefaultSize, 0);
6300 boxSizer02->Add(pStaticTextYoff, 0, wxALL, 0);
6303 new wxSpinCtrl(
this, wxID_ANY, wxEmptyString, wxDefaultPosition,
6304 wxSize(50, -1), wxSP_ARROW_KEYS, -10000, 10000, 0);
6305 m_pSpinCtrlYoff->Connect(wxEVT_COMMAND_SPINCTRL_UPDATED,
6306 wxCommandEventHandler(CM93OffsetDialog::OnOffSetSet),
6308 boxSizer02->Add(m_pSpinCtrlYoff, 0, wxEXPAND | wxALL, 0);
6310 m_OKButton =
new wxButton(
this, wxID_ANY, _(
"OK"), wxDefaultPosition,
6312 m_OKButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
6313 wxCommandEventHandler(CM93OffsetDialog::OnOK), NULL,
6315 boxSizer02->Add(m_OKButton, 0, wxALL, 5);
6316 m_OKButton->SetDefault();
6318 topSizer->Add(boxSizer02, 0, wxEXPAND | wxALL, 2);
6320 wxSize sz(800, dy * 8);
6322 sz = wxGetDisplaySize();
6332 SetSize(GetSize().x, GetSize().y - 1);
6346void CM93OffsetDialog::OnClose(wxCloseEvent &event) {
6348 m_pcompchart->SetSpecialOutlineCellIndex(0, 0, 0);
6350 m_pcompchart->InvalidateCache();
6353 m_pparent->Refresh(
true);
6354 gFrame->InvalidateAllGL();
6358 if (m_pListCtrlMCOVRs->GetItemCount() > m_selected_list_index)
6359 m_pListCtrlMCOVRs->SetItemState(m_selected_list_index, 0,
6360 wxLIST_STATE_SELECTED);
6365void CM93OffsetDialog::OnOK(wxCommandEvent &event) {
6373 m_pcompchart = pchart;
6376void CM93OffsetDialog::OnOffSetSet(wxCommandEvent &event) {
6377 m_xoff = m_pSpinCtrlXoff->GetValue() / m_centerlat_cos;
6378 m_yoff = m_pSpinCtrlYoff->GetValue() / m_centerlat_cos;
6385void CM93OffsetDialog::UpdateOffsets(
void) {
6386 if (m_pcompchart && m_selected_cell_index) {
6388 m_pcompchart->SetSpecialCellIndexOffset(m_selected_cell_index,
6389 m_selected_object_id,
6390 m_selected_subcell, m_xoff, m_yoff);
6394 AbstractPlatform::ShowBusySpinner();
6395 m_pcompchart->CloseandReopenCurrentSubchart();
6396 AbstractPlatform::HideBusySpinner();
6399 m_pparent->Refresh(
true);
6400 gFrame->InvalidateAllGL();
6405void CM93OffsetDialog::SetColorScheme() { DimeControl(
this); }
6407void CM93OffsetDialog::OnCellSelected(wxListEvent &event) {
6409 m_selected_list_index =
event.GetIndex();
6411 M_COVR_Desc *mcd = m_pcovr_array.Item(event.GetIndex());
6413 if (m_selected_list_index > m_pListCtrlMCOVRs->GetItemCount())
6416 cm93chart *pchart = m_pcompchart->GetCurrentSingleScaleChart();
6418 M_COVR_Desc *cached_mcd = pchart->GetCoverSet()->Find_MCD(
6419 mcd->m_cell_index, mcd->m_object_id, mcd->m_subcell);
6421 m_pSpinCtrlXoff->SetValue(
6422 wxRound(cached_mcd->user_xoff * cached_mcd->m_centerlat_cos));
6423 m_pSpinCtrlYoff->SetValue(
6424 wxRound(cached_mcd->user_yoff * cached_mcd->m_centerlat_cos));
6428 m_pcompchart->SetSpecialOutlineCellIndex(mcd->m_cell_index,
6429 mcd->m_object_id, mcd->m_subcell);
6431 m_selected_cell_index = mcd->m_cell_index;
6432 m_selected_object_id = mcd->m_object_id;
6433 m_selected_subcell = mcd->m_subcell;
6434 m_centerlat_cos = mcd->m_centerlat_cos;
6436 m_pcompchart->InvalidateCache();
6439 m_pparent->Refresh(
true);
6440 gFrame->InvalidateAllGL();
6445void CM93OffsetDialog::UpdateMCOVRList(
const ViewPort &vpt) {
6449 cm93chart *pchart = m_pcompchart->GetCurrentSingleScaleChart();
6452 m_selected_chart_scale_char = pchart->GetScaleChar();
6454 m_pcovr_array.Clear();
6457 std::vector<int> cell_array = pchart->GetVPCellArray(vpt);
6465 covr_set *pcover = pchart->GetCoverSet();
6467 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
6470 for (
unsigned int icell = 0; icell < cell_array.size(); icell++) {
6471 if (cell_array[icell] == mcd->m_cell_index) {
6472 wxPoint *pwp = pchart->GetDrawBuffer(mcd->m_nvertices);
6479 m_pcovr_array.Add(mcd);
6487 for (
unsigned int im = 0; im < m_pcovr_array.size(); im++) {
6489 if ((m_selected_cell_index == mcd->m_cell_index) &&
6490 (m_selected_object_id == mcd->m_object_id) &&
6491 (m_selected_subcell == mcd->m_subcell)) {
6497 if (!m_pListCtrlMCOVRs->IsVirtual()) {
6498 if (m_pListCtrlMCOVRs->GetItemCount())
6499 m_pListCtrlMCOVRs->DeleteAllItems();
6501 for (
unsigned int i = 0; i < m_pcovr_array.GetCount(); i++) {
6504 m_pListCtrlMCOVRs->InsertItem(item);
6505 for (
int j = 0; j < tlUYOFF + 1; j++) {
6507 item.SetText(m_pListCtrlMCOVRs->OnGetItemText(i, j));
6508 m_pListCtrlMCOVRs->SetItem(item);
6512 m_pListCtrlMCOVRs->SetItemCount(m_pcovr_array.GetCount());
6515 if (-1 != sel_index)
6516 m_pListCtrlMCOVRs->SetItemState(sel_index, wxLIST_STATE_SELECTED,
6517 wxLIST_STATE_SELECTED);
6519 m_pListCtrlMCOVRs->SetItemState(sel_index, 0,
6520 wxLIST_STATE_SELECTED);
6522 m_pListCtrlMCOVRs->Refresh(
true);
6525 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.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
General purpose GUI support.
@ PI_PRIO_NUM
Number of priority levels.
@ PI_LUPNAME_NUM
Total number of lookup table types.
Tools to send data to plugins.
PlugInManager and helper classes – Mostly gui parts (dialogs) and plugin API stuff.
Runtime representation of a plugin block.