27 #include "wx/wxprec.h"
33 #include <wx/textfile.h>
34 #include <wx/tokenzr.h>
35 #include <wx/arrstr.h>
36 #include <wx/mstream.h>
37 #include <wx/spinctrl.h>
38 #include <wx/listctrl.h>
42 #include <unordered_map>
44 #include "gdal/ogr_api.h"
49 #include "model/georef.h"
51 #include "model/cutil.h"
53 #include "ocpn_pixel.h"
55 #include "pluginmanager.h"
56 #include "OCPNPlatform.h"
57 #include "model/wx28compat.h"
58 #include "model/chartdata_input_stream.h"
59 #include "DetailSlider.h"
62 #include "ocpn_frame.h"
63 #include "line_clip.h"
68 #include "glChartCanvas.h"
73 #define _CRTDBG_MAP_ALLOC
76 #define DEBUG_NEW new (_NORMAL_BLOCK, __FILE__, __LINE__)
82 extern s52plib *ps52plib;
83 extern bool g_bDebugCM93;
84 extern int g_cm93_zoom_factor;
86 extern int g_detailslider_dialog_x, g_detailslider_dialog_y;
88 extern bool g_bopengl;
91 extern bool g_b_EnableVBO;
96 #include <wx/arrimpl.cpp>
97 WX_DEFINE_OBJARRAY(Array_Of_M_COVR_Desc);
99 #include <wx/listimpl.cpp>
100 WX_DEFINE_LIST(List_Of_M_COVR_Desc);
102 void appendOSDirSep(wxString *pString) {
103 wxChar sep = wxFileName::GetPathSeparator();
104 if (pString->Last() != sep) pString->Append(sep);
111 M_COVR_Desc::M_COVR_Desc() {
113 gl_screen_vertices = NULL;
114 gl_screen_projection_type = PROJECTION_UNKNOWN;
118 m_centerlat_cos = 1.0;
119 m_buser_offsets =
false;
122 gl_screen_vertices = NULL;
125 M_COVR_Desc::~M_COVR_Desc() {
127 delete[] gl_screen_vertices;
130 int M_COVR_Desc::GetWKBSize() {
138 size += m_nvertices *
sizeof(float_2Dpt);
141 size += 8 *
sizeof(double);
146 bool M_COVR_Desc::WriteWKB(
void *p) {
149 *pr++ = GetWKBSize();
151 *pr++ = m_cell_index;
157 float_2Dpt *pfo = (float_2Dpt *)pr;
158 float_2Dpt *pfi = pvertices;
159 for (
int i = 0; i < m_nvertices; i++) *pfo++ = *pfi++;
161 int *pi = (
int *)pfo;
164 double *pd = (
double *)pi;
165 *pd++ = transform_WGS84_offset_x;
166 *pd++ = transform_WGS84_offset_y;
167 *pd++ = m_covr_lat_min;
168 *pd++ = m_covr_lat_max;
169 *pd++ = m_covr_lon_min;
170 *pd++ = m_covr_lon_max;
172 double centerlat_cos =
173 cos(((m_covr_lat_min + m_covr_lat_max) / 2.) * PI / 180.);
175 *pd++ = user_xoff * centerlat_cos;
176 *pd++ = user_yoff * centerlat_cos;
182 int M_COVR_Desc::ReadWKB(wxFFileInputStream &ifs) {
185 if (!ifs.Read(&length,
sizeof(
int)).Eof()) {
186 ifs.Read(&m_cell_index,
sizeof(
int));
187 ifs.Read(&m_object_id,
sizeof(
int));
188 ifs.Read(&m_subcell,
sizeof(
int));
190 ifs.Read(&m_nvertices,
sizeof(
int));
192 pvertices =
new float_2Dpt[m_nvertices];
194 ifs.Read(pvertices, m_nvertices *
sizeof(float_2Dpt));
196 ifs.Read(&m_npub_year,
sizeof(
int));
198 ifs.Read(&transform_WGS84_offset_x,
sizeof(
double));
199 ifs.Read(&transform_WGS84_offset_y,
sizeof(
double));
200 ifs.Read(&m_covr_lat_min,
sizeof(
double));
201 ifs.Read(&m_covr_lat_max,
sizeof(
double));
202 ifs.Read(&m_covr_lon_min,
sizeof(
double));
203 ifs.Read(&m_covr_lon_max,
sizeof(
double));
205 m_centerlat_cos = cos(((m_covr_lat_min + m_covr_lat_max) / 2.) * PI / 180.);
207 ifs.Read(&user_xoff,
sizeof(
double));
208 ifs.Read(&user_yoff,
sizeof(
double));
210 user_xoff /= m_centerlat_cos;
211 user_yoff /= m_centerlat_cos;
213 if ((fabs(user_xoff) > 1.) || (fabs(user_yoff) > 1.))
214 m_buser_offsets =
true;
216 m_buser_offsets =
false;
218 m_covr_bbox.Set(m_covr_lat_min, m_covr_lon_min, m_covr_lat_max,
225 float_2Dpt *p = pvertices;
227 for (
int ip = 0; ip < m_nvertices; ip++) {
229 if (fabs(plon - vp.clon) > 180.) {
236 double easting, northing, epix, npix;
237 toSM(p->y, plon + 360., vp.clat, vp.clon + 360, &easting, &northing);
240 easting -= user_xoff;
242 northing -= user_yoff;
244 epix = easting * vp.view_scale_ppm;
245 npix = northing * vp.view_scale_ppm;
247 pwp[ip].x = (int)round((vp.pix_width / 2) + epix);
248 pwp[ip].y = (int)round((vp.pix_height / 2) - npix);
262 char sig_version[] =
"COVR1002";
269 bool Init(wxChar scale_char, wxString &prefix);
270 unsigned int GetCoverCount() {
return m_covr_array_outlines.GetCount(); }
271 M_COVR_Desc *GetCover(
unsigned int im) {
return &m_covr_array_outlines[im]; }
274 bool IsCovrLoaded(
int cell_index);
276 M_COVR_Desc *Find_MCD(
int cell_index,
int object_id,
int sbcell);
282 wxString m_cachefile;
285 Array_Of_M_COVR_Desc m_covr_array_outlines;
289 std::unordered_map<int, int> m_cell_hash;
292 covr_set::covr_set(
cm93chart *parent) { m_pParent = parent; }
294 covr_set::~covr_set() {
296 if (m_cachefile.IsEmpty())
300 if (m_covr_array_outlines.GetCount()) {
301 wxFFileOutputStream ofs(m_cachefile);
303 ofs.Write(sig_version, 8);
305 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
306 int wkbsize = m_covr_array_outlines[i].GetWKBSize();
308 char *p = (
char *)malloc(wkbsize *
sizeof(
char));
309 m_covr_array_outlines[i].WriteWKB(p);
310 ofs.Write(p, wkbsize);
319 bool covr_set::Init(wxChar scale_char, wxString &prefix) {
320 m_scale_char = scale_char;
322 switch (m_scale_char) {
353 wxString prefix_string = prefix;
354 wxString sep(wxFileName::GetPathSeparator());
355 prefix_string.Replace(sep, _T (
"_" ));
356 prefix_string.Replace(_T (
":" ), _T (
"_" ));
359 appendOSDirSep(&m_cachefile);
361 m_cachefile += _T (
"cm93" );
362 appendOSDirSep(&m_cachefile);
366 m_cachefile += _T (
"_" );
368 wxString cache_old_old_name = m_cachefile;
369 cache_old_old_name += _T (
"coverset." );
370 cache_old_old_name += m_scale_char;
372 wxString cache_old_name = m_cachefile;
373 cache_old_name += _T (
"coverset_sig." );
374 cache_old_name += m_scale_char;
376 m_cachefile += _T (
"coverset_sigp." );
377 m_cachefile += m_scale_char;
379 wxFileName fn(m_cachefile);
380 if (!fn.DirExists()) wxFileName::Mkdir(fn.GetPath(), 0777, wxPATH_MKDIR_FULL);
383 if (!wxFileName::FileExists(m_cachefile)) {
386 if (wxFileName::FileExists(cache_old_name)) ::wxRemoveFile(cache_old_name);
387 if (wxFileName::FileExists(cache_old_old_name))
388 ::wxRemoveFile(cache_old_old_name);
392 wxFFileInputStream ifs(m_cachefile);
396 if (!ifs.Read(&sig_bytes, 8).Eof()) {
397 if (strncmp(sig_bytes, sig_version, 8)) {
406 int length = pmcd->ReadWKB(ifs);
409 m_covr_array_outlines.Add(pmcd);
411 if (m_cell_hash.find(pmcd->m_cell_index) == m_cell_hash.end())
412 m_cell_hash[pmcd->m_cell_index] = 0;
414 m_cell_hash[pmcd->m_cell_index]++;
427 m_covr_array_outlines.Add(pmcd);
429 if (m_cell_hash.find(pmcd->m_cell_index) ==
431 m_cell_hash[pmcd->m_cell_index] = 0;
433 m_cell_hash[pmcd->m_cell_index]++;
436 bool covr_set::IsCovrLoaded(
int cell_index) {
437 return (m_cell_hash.find(cell_index) != m_cell_hash.end());
441 if (m_cell_hash.find(pmcd->m_cell_index) ==
444 m_covr_array_outlines.Add(pmcd);
445 m_cell_hash[pmcd->m_cell_index] = 1;
453 bool b_found =
false;
454 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
455 M_COVR_Desc *pmcd_candidate = &m_covr_array_outlines[i];
456 if ((pmcd_candidate->m_cell_index == pmcd->m_cell_index) &&
457 (pmcd_candidate->m_object_id == pmcd->m_object_id) &&
458 (pmcd_candidate->m_subcell == pmcd->m_subcell))
467 m_covr_array_outlines.Add(pmcd);
468 m_cell_hash[pmcd->m_cell_index]++;
476 if (m_cell_hash.find(pmcd->m_cell_index) ==
484 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
485 M_COVR_Desc *pmcd_candidate = &m_covr_array_outlines[i];
486 if ((pmcd_candidate->m_cell_index == pmcd->m_cell_index) &&
487 (pmcd_candidate->m_object_id == pmcd->m_object_id) &&
488 (pmcd_candidate->m_subcell == pmcd->m_subcell)) {
496 M_COVR_Desc *covr_set::Find_MCD(
int cell_index,
int object_id,
int subcell) {
497 if (m_cell_hash.find(cell_index) == m_cell_hash.end())
500 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
501 M_COVR_Desc *pmcd_candidate = &m_covr_array_outlines[i];
502 if ((pmcd_candidate->m_cell_index == cell_index) &&
503 (pmcd_candidate->m_object_id == object_id) &&
504 (pmcd_candidate->m_subcell == subcell))
506 return pmcd_candidate;
514 static unsigned char Table_0[] = {
515 0x0CD, 0x0EA, 0x0DC, 0x048, 0x03E, 0x06D, 0x0CA, 0x07B, 0x052, 0x0E1, 0x0A4,
516 0x08E, 0x0AB, 0x005, 0x0A7, 0x097, 0x0B9, 0x060, 0x039, 0x085, 0x07C, 0x056,
517 0x07A, 0x0BA, 0x068, 0x06E, 0x0F5, 0x05D, 0x002, 0x04E, 0x00F, 0x0A1, 0x027,
518 0x024, 0x041, 0x034, 0x000, 0x05A, 0x0FE, 0x0CB, 0x0D0, 0x0FA, 0x0F8, 0x06C,
519 0x074, 0x096, 0x09E, 0x00E, 0x0C2, 0x049, 0x0E3, 0x0E5, 0x0C0, 0x03B, 0x059,
520 0x018, 0x0A9, 0x086, 0x08F, 0x030, 0x0C3, 0x0A8, 0x022, 0x00A, 0x014, 0x01A,
521 0x0B2, 0x0C9, 0x0C7, 0x0ED, 0x0AA, 0x029, 0x094, 0x075, 0x00D, 0x0AC, 0x00C,
522 0x0F4, 0x0BB, 0x0C5, 0x03F, 0x0FD, 0x0D9, 0x09C, 0x04F, 0x0D5, 0x084, 0x01E,
523 0x0B1, 0x081, 0x069, 0x0B4, 0x009, 0x0B8, 0x03C, 0x0AF, 0x0A3, 0x008, 0x0BF,
524 0x0E0, 0x09A, 0x0D7, 0x0F7, 0x08C, 0x067, 0x066, 0x0AE, 0x0D4, 0x04C, 0x0A5,
525 0x0EC, 0x0F9, 0x0B6, 0x064, 0x078, 0x006, 0x05B, 0x09B, 0x0F2, 0x099, 0x0CE,
526 0x0DB, 0x053, 0x055, 0x065, 0x08D, 0x007, 0x033, 0x004, 0x037, 0x092, 0x026,
527 0x023, 0x0B5, 0x058, 0x0DA, 0x02F, 0x0B3, 0x040, 0x05E, 0x07F, 0x04B, 0x062,
528 0x080, 0x0E4, 0x06F, 0x073, 0x01D, 0x0DF, 0x017, 0x0CC, 0x028, 0x025, 0x02D,
529 0x0EE, 0x03A, 0x098, 0x0E2, 0x001, 0x0EB, 0x0DD, 0x0BC, 0x090, 0x0B0, 0x0FC,
530 0x095, 0x076, 0x093, 0x046, 0x057, 0x02C, 0x02B, 0x050, 0x011, 0x00B, 0x0C1,
531 0x0F0, 0x0E7, 0x0D6, 0x021, 0x031, 0x0DE, 0x0FF, 0x0D8, 0x012, 0x0A6, 0x04D,
532 0x08A, 0x013, 0x043, 0x045, 0x038, 0x0D2, 0x087, 0x0A0, 0x0EF, 0x082, 0x0F1,
533 0x047, 0x089, 0x06A, 0x0C8, 0x054, 0x01B, 0x016, 0x07E, 0x079, 0x0BD, 0x06B,
534 0x091, 0x0A2, 0x071, 0x036, 0x0B7, 0x003, 0x03D, 0x072, 0x0C6, 0x044, 0x08B,
535 0x0CF, 0x015, 0x09F, 0x032, 0x0C4, 0x077, 0x083, 0x063, 0x020, 0x088, 0x0F6,
536 0x0AD, 0x0F3, 0x0E8, 0x04A, 0x0E9, 0x035, 0x01C, 0x05F, 0x019, 0x01F, 0x07D,
537 0x070, 0x0FB, 0x0D1, 0x051, 0x010, 0x0D3, 0x02E, 0x061, 0x09D, 0x05C, 0x02A,
538 0x042, 0x0BE, 0x0E6};
540 static unsigned char Encode_table[256];
541 static unsigned char Decode_table[256];
543 static bool cm93_decode_table_created;
552 virtual wxDirTraverseResult OnFile(
const wxString &filename) {
553 wxString name = filename.AfterLast(wxFileName::GetPathSeparator()).Lower();
554 if (name == wxT(
"cm93obj.dic")) {
559 return wxDIR_CONTINUE;
562 virtual wxDirTraverseResult OnDir(
const wxString &WXUNUSED(dirname)) {
563 return wxDIR_CONTINUE;
570 cm93_dictionary::cm93_dictionary() {
571 m_S57ClassArray = NULL;
573 m_GeomTypeArray = NULL;
575 m_ValTypeArray = NULL;
580 bool cm93_dictionary::LoadDictionary(
const wxString &dictionary_dir) {
583 wxString dir(dictionary_dir);
584 bool ret_val =
false;
586 wxChar sep = wxFileName::GetPathSeparator();
587 if (dir.Last() != sep) dir.Append(sep);
594 sf.Append(_T (
"CM93OBJ.DIC" ));
596 if (!wxFileName::FileExists(sf)) {
598 sf.Append(_T (
"cm93obj.dic" ));
599 if (!wxFileName::FileExists(sf))
return false;
603 if (!file.Open(sf))
return false;
605 nline = file.GetLineCount();
607 if (!nline)
return false;
612 for (i = 0; i < nline; i++) {
613 line = file.GetLine(i);
615 wxStringTokenizer tkz(line, wxT(
"|"));
619 wxString class_name = tkz.GetNextToken();
622 wxString token = tkz.GetNextToken();
624 token.ToLong(&liclass);
625 int iclass = liclass;
626 if (iclass > iclass_max) iclass_max = iclass;
629 wxString geo_type = tkz.GetNextToken();
633 m_max_class = iclass_max;
636 m_S57ClassArray =
new wxArrayString;
637 m_S57ClassArray->Add(_T (
"NULLNM" ), iclass_max + 1);
640 m_GeomTypeArray = (
int *)malloc((iclass_max + 1) *
sizeof(int));
643 for (i = 0; i < nline; i++) {
644 line = file.GetLine(i);
646 wxStringTokenizer tkz(line, wxT(
"|"));
650 wxString class_name = tkz.GetNextToken();
653 wxString token = tkz.GetNextToken();
655 token.ToLong(&liclass);
656 int iclass = liclass;
659 wxString geo_type = tkz.GetNextToken();
661 m_S57ClassArray->Insert(class_name, iclass);
662 m_S57ClassArray->RemoveAt(iclass + 1);
665 wxChar geo_type_primary = geo_type[0];
667 if (geo_type_primary ==
'A')
669 else if (geo_type_primary ==
'L')
671 else if (geo_type_primary ==
'P')
678 m_GeomTypeArray[iclass] = igeom_type;
686 sfa.Append(_T (
"ATTRLUT.DIC" ));
688 if (!wxFileName::FileExists(sfa)) {
690 sfa.Append(_T (
"attrlut.dic" ));
693 if (wxFileName::FileExists(sfa)) {
694 wxFFileInputStream filea(sfa);
700 while (!filea.Eof()) {
704 char a = filea.GetC();
705 if (filea.Eof())
break;
707 if (a == 0x0a)
break;
710 if (!line.StartsWith((
const wxChar *)wxT(
";"))) {
711 wxStringTokenizer tkz(line, wxT(
"|"));
714 wxString class_name = tkz.GetNextToken();
717 wxString token = tkz.GetNextToken();
719 token.ToLong(&liattr);
721 if (iattr > iattr_max) iattr_max = iattr;
726 m_max_attr = iattr_max;
732 m_AttrArray =
new wxArrayString;
733 m_AttrArray->Add(_T (
"NULLNM" ), iattr_max + 1);
736 m_ValTypeArray = (
char *)malloc((iattr_max + 1) *
sizeof(char));
739 while (!filea.Eof()) {
743 char a = filea.GetC();
744 if (filea.Eof())
break;
746 if (a == 0x0a)
break;
749 if (!line.StartsWith((
const wxChar *)wxT(
";"))) {
750 wxStringTokenizer tkz(line, wxT(
"|"));
753 wxString attr_name = tkz.GetNextToken();
756 wxString token = tkz.GetNextToken();
758 token.ToLong(&liattr);
761 m_AttrArray->Insert(attr_name, iattr);
762 m_AttrArray->RemoveAt(iattr + 1);
765 token = tkz.GetNextToken();
766 token = tkz.GetNextToken();
767 token = tkz.GetNextToken();
768 token = tkz.GetNextToken().Trim();
771 if (token.IsSameAs(_T (
"aFLOAT" )))
773 else if (token.IsSameAs(_T (
"aBYTE" )))
775 else if (token.IsSameAs(_T (
"aSTRING" )))
777 else if (token.IsSameAs(_T (
"aCMPLX" )))
779 else if (token.IsSameAs(_T (
"aLIST" )))
781 else if (token.IsSameAs(_T (
"aWORD10" )))
783 else if (token.IsSameAs(_T (
"aLONG" )))
786 m_ValTypeArray[iattr] = atype;
800 sfa.Append(_T (
"CM93ATTR.DIC" ));
802 if (!wxFileName::FileExists(sfa)) {
804 sfa.Append(_T (
"cm93attr.dic" ));
807 if (wxFileName::FileExists(sfa)) {
808 wxFFileInputStream filea(sfa);
814 while (!filea.Eof()) {
818 char a = filea.GetC();
819 if (filea.Eof())
break;
821 if (a == 0x0a)
break;
824 if (!line.StartsWith((
const wxChar *)wxT(
";"))) {
825 wxStringTokenizer tkz(line, wxT(
"|"));
826 if (tkz.CountTokens()) {
828 wxString class_name = tkz.GetNextToken();
831 wxString token = tkz.GetNextToken();
833 token.ToLong(&liattr);
835 if (iattr > iattr_max) iattr_max = iattr;
840 m_max_attr = iattr_max;
846 m_AttrArray =
new wxArrayString;
847 m_AttrArray->Add(_T (
"NULLNM" ), iattr_max + 1);
850 m_ValTypeArray = (
char *)malloc((iattr_max + 1) *
sizeof(char));
851 for (
int iat = 0; iat < iattr_max + 1; iat++) m_ValTypeArray[iat] =
'?';
854 while (!filea.Eof()) {
858 char a = filea.GetC();
859 if (filea.Eof())
break;
861 if (a == 0x0a)
break;
864 if (!line.StartsWith((
const wxChar *)wxT(
";"))) {
865 wxStringTokenizer tkz(line, wxT(
"|\r\n"));
866 if (tkz.CountTokens() >= 3) {
868 wxString attr_name = tkz.GetNextToken();
871 wxString token = tkz.GetNextToken();
873 token.ToLong(&liattr);
876 m_AttrArray->Insert(attr_name, iattr);
877 m_AttrArray->RemoveAt(iattr + 1);
879 token = tkz.GetNextToken().Trim();
882 if (token.IsSameAs(_T (
"aFLOAT" )))
884 else if (token.IsSameAs(_T (
"aBYTE" )))
886 else if (token.IsSameAs(_T (
"aSTRING" )))
888 else if (token.IsSameAs(_T (
"aCMPLX" )))
890 else if (token.IsSameAs(_T (
"aLIST" )))
892 else if (token.IsSameAs(_T (
"aWORD10" )))
894 else if (token.IsSameAs(_T (
"aLONG" )))
897 m_ValTypeArray[iattr] = atype;
910 wxString msg(_T (
"Loaded CM93 Dictionary from " ));
918 wxString cm93_dictionary::GetClassName(
int iclass) {
919 if ((iclass > m_max_class) || (iclass < 0))
920 return (_T (
"Unknown" ));
922 return (m_S57ClassArray->Item(iclass));
925 wxString cm93_dictionary::GetAttrName(
int iattr) {
926 if ((iattr > m_max_attr) || (iattr < 0))
927 return (_T (
"UnknownAttr" ));
929 return (m_AttrArray->Item(iattr));
933 char cm93_dictionary::GetAttrType(
int iattr) {
934 if ((iattr > m_max_attr) || (iattr < 0))
937 return (m_ValTypeArray[iattr]);
940 cm93_dictionary::~cm93_dictionary() {
941 delete m_S57ClassArray;
942 free(m_GeomTypeArray);
944 free(m_ValTypeArray);
949 void CreateDecodeTable(
void) {
951 for (i = 0; i < 256; i++) {
952 Encode_table[i] = Table_0[i] ^ 8;
955 for (i = 0; i < 256; i++) {
956 unsigned char a = Encode_table[i];
957 Decode_table[(int)a] = (
unsigned char)i;
961 static int read_and_decode_bytes(FILE *stream,
void *p,
int nbytes) {
966 if (fread(p, nbytes, 1, stream) != 1)
return 0;
969 unsigned char *q = (
unsigned char *)p;
971 for (
int i = 0; i < nbytes; i++) {
972 unsigned char a = *q;
974 unsigned char c = Decode_table[b];
982 static int read_and_decode_double(FILE *stream,
double *p) {
985 if (fread(&t,
sizeof(
double), 1, stream) != 1)
return 0;
988 unsigned char *q = (
unsigned char *)&t;
990 for (
unsigned int i = 0; i <
sizeof(double); i++) {
991 unsigned char a = *q;
993 unsigned char c = Decode_table[b];
1005 static int read_and_decode_int(FILE *stream,
int *p) {
1008 if (fread(&t,
sizeof(
int), 1, stream) != 1)
return 0;
1011 unsigned char *q = (
unsigned char *)&t;
1013 for (
unsigned int i = 0; i <
sizeof(int); i++) {
1014 unsigned char a = *q;
1016 unsigned char c = Decode_table[b];
1028 static int read_and_decode_ushort(FILE *stream,
unsigned short *p) {
1031 if (fread(&t,
sizeof(
unsigned short), 1, stream) != 1)
return 0;
1034 unsigned char *q = (
unsigned char *)&t;
1036 for (
unsigned int i = 0; i <
sizeof(
unsigned short); i++) {
1037 unsigned char a = *q;
1039 unsigned char c = Decode_table[b];
1053 int Get_CM93_CellIndex(
double lat,
double lon,
int scale) {
1088 double lon1 = (lon + 360.) * 3.;
1089 while (lon1 >= 1080.0) lon1 -= 1080.0;
1090 unsigned short lon2 = (
unsigned short)floor(lon1 / dval);
1091 unsigned short lon3 = lon2 * dval;
1096 double lat1 = (lat * 3.) + 270. - 30;
1097 unsigned short lat2 = (
unsigned short)floor(lat1 / dval);
1098 unsigned short lat3 = lat2 * dval;
1100 retval += (lat3 + 30) * 10000;
1108 void Get_CM93_Cell_Origin(
int cellindex,
int scale,
double *lat,
double *lon) {
1110 double idx1 = cellindex % 10000;
1111 double lont = (idx1 / 3.);
1116 int idx2 = cellindex / 10000;
1117 double lat1 = idx2 - 270.;
1123 bool Is_CM93Cell_Present(wxString &fileprefix,
double lat,
double lon,
1129 switch (scale_index) {
1177 int cellindex = Get_CM93_CellIndex(lat, lon,
scale);
1182 int ilat = cellindex / 10000;
1183 int ilon = cellindex % 10000;
1185 int jlat = (((ilat - 30) / dval) * dval) + 30;
1186 int jlon = (ilon / dval) * dval;
1188 int ilatroot = (((ilat - 30) / 60) * 60) + 30;
1189 int ilonroot = (ilon / 60) * 60;
1192 fileroot.Printf(_T (
"%04d%04d" ), ilatroot, ilonroot);
1193 appendOSDirSep(&fileroot);
1195 wxString sdir(fileprefix);
1200 tfile.Printf(_T (
"?%03d%04d." ), jlat, jlon);
1201 tfile += scale_char;
1204 if (!::wxDirExists(sdir)) {
1205 wxString old_scalechar(scale_char);
1206 wxString new_scalechar = old_scalechar.Lower();
1210 sdir += new_scalechar;
1213 if (::wxDirExists(sdir)) {
1216 wxArrayString file_array;
1217 int n_files = dir.GetAllFiles(sdir, &file_array, tfile, wxDIR_FILES);
1219 if (n_files)
return true;
1222 wxString old_scalechar(scale_char);
1223 wxString new_scalechar = old_scalechar.Lower();
1226 tfile1.Printf(_T (
"?%03d%04d." ), jlat, jlon);
1227 tfile1 += new_scalechar;
1229 int n_files1 = dir.GetAllFiles(sdir, &file_array, tfile1, wxDIR_FILES);
1231 if (n_files1)
return true;
1235 dir.GetAllFiles(sdir, &file_array, tfile + _T(
".xz"), wxDIR_FILES);
1237 if (n_files)
return true;
1243 static bool read_header_and_populate_cib(FILE *stream,
Cell_Info_Block *pCIB) {
1252 memset((
void *)&header, 0,
sizeof(header));
1254 read_and_decode_double(stream, &header.lon_min);
1255 read_and_decode_double(stream, &header.lat_min);
1256 read_and_decode_double(stream, &header.lon_max);
1257 read_and_decode_double(stream, &header.lat_max);
1259 read_and_decode_double(stream, &header.easting_min);
1260 read_and_decode_double(stream, &header.northing_min);
1261 read_and_decode_double(stream, &header.easting_max);
1262 read_and_decode_double(stream, &header.northing_max);
1264 read_and_decode_ushort(stream, &header.usn_vector_records);
1265 read_and_decode_int(stream, &header.n_vector_record_points);
1266 read_and_decode_int(stream, &header.m_46);
1267 read_and_decode_int(stream, &header.m_4a);
1268 read_and_decode_ushort(stream, &header.usn_point3d_records);
1269 read_and_decode_int(stream, &header.m_50);
1270 read_and_decode_int(stream, &header.m_54);
1271 read_and_decode_ushort(stream, &header.usn_point2d_records);
1272 read_and_decode_ushort(stream, &header.m_5a);
1273 read_and_decode_ushort(stream, &header.m_5c);
1274 read_and_decode_ushort(stream, &header.usn_feature_records);
1276 read_and_decode_int(stream, &header.m_60);
1277 read_and_decode_int(stream, &header.m_64);
1278 read_and_decode_ushort(stream, &header.m_68);
1279 read_and_decode_ushort(stream, &header.m_6a);
1280 read_and_decode_ushort(stream, &header.m_6c);
1281 read_and_decode_int(stream, &header.m_nrelated_object_pointers);
1283 read_and_decode_int(stream, &header.m_72);
1284 read_and_decode_ushort(stream, &header.m_76);
1286 read_and_decode_int(stream, &header.m_78);
1287 read_and_decode_int(stream, &header.m_7c);
1291 double delta_x = header.easting_max - header.easting_min;
1293 delta_x += CM93_semimajor_axis_meters * 2.0 * PI;
1295 pCIB->transform_x_rate = delta_x / 65535;
1296 pCIB->transform_y_rate = (header.northing_max - header.northing_min) / 65535;
1298 pCIB->transform_x_origin = header.easting_min;
1299 pCIB->transform_y_origin = header.northing_min;
1301 pCIB->min_lat = header.lat_min;
1302 pCIB->min_lon = header.lon_min;
1310 pCIB->m_nfeature_records = header.usn_feature_records;
1311 pCIB->pobject_block =
1312 (
Object *)calloc(pCIB->m_nfeature_records *
sizeof(
Object), 1);
1314 pCIB->m_n_point2d_records = header.usn_point2d_records;
1315 pCIB->p2dpoint_array =
1318 pCIB->pprelated_object_block =
1319 (
Object **)malloc(header.m_nrelated_object_pointers *
sizeof(
Object *));
1321 pCIB->object_vector_record_descriptor_block =
1325 pCIB->attribute_block_top = (
unsigned char *)calloc(header.m_78, 1);
1327 pCIB->m_nvector_records = header.usn_vector_records;
1331 pCIB->pvector_record_block_top =
1334 pCIB->m_n_point3d_records = header.usn_point3d_records;
1338 pCIB->p3dpoint_array =
1344 static bool read_vector_record_table(FILE *stream,
int count,
1349 cm93_point *q = pCIB->pvector_record_block_top;
1351 for (
int iedge = 0; iedge < count; iedge++) {
1354 unsigned short npoints;
1355 brv = !(read_and_decode_ushort(stream, &npoints) == 0);
1356 if (!brv)
return false;
1358 p->n_points = npoints;
1366 unsigned short x, y;
1367 for (
int index = 0; index < p->n_points; index++) {
1368 if (!read_and_decode_ushort(stream, &x))
return false;
1369 if (!read_and_decode_ushort(stream, &y))
return false;
1385 for (
int j = 0; j < p->n_points - 1; j++) {
1386 if (t->x >= p->x_max) p->x_max = t->x;
1388 if (t->x <= p->x_min) p->x_min = t->x;
1390 if (t->y >= p->y_max) p->y_max = t->y;
1392 if (t->y <= p->y_max) p->y_min = t->y;
1407 static bool read_3dpoint_table(FILE *stream,
int count,
Cell_Info_Block *pCIB) {
1411 for (
int i = 0; i < count; i++) {
1412 unsigned short npoints;
1413 if (!read_and_decode_ushort(stream, &npoints))
return false;
1415 p->n_points = npoints;
1423 unsigned short x, y, z;
1424 for (
int index = 0; index < p->n_points; index++) {
1425 if (!read_and_decode_ushort(stream, &x))
return false;
1426 if (!read_and_decode_ushort(stream, &y))
return false;
1427 if (!read_and_decode_ushort(stream, &z))
return false;
1441 static bool read_2dpoint_table(FILE *stream,
int count,
Cell_Info_Block *pCIB) {
1445 unsigned short x, y;
1446 for (
int index = 0; index < count; index++) {
1447 if (!read_and_decode_ushort(stream, &x))
return false;
1448 if (!read_and_decode_ushort(stream, &y))
return false;
1450 pCIB->p2dpoint_array[index].x = x;
1451 pCIB->p2dpoint_array[index].y = y;
1457 static bool read_feature_record_table(FILE *stream,
int n_features,
1460 Object *pobj = pCIB->pobject_block;
1463 pCIB->object_vector_record_descriptor_block;
1466 pCIB->pprelated_object_block;
1469 unsigned char *puc_var10 = pCIB->attribute_block_top;
1472 unsigned char object_type;
1473 unsigned char geom_prim;
1474 unsigned short obj_desc_bytes = 0;
1477 unsigned short index;
1478 unsigned short n_elements;
1480 for (
int iobject = 0; iobject < n_features; iobject++) {
1482 read_and_decode_bytes(stream, &object_type, 1);
1483 read_and_decode_bytes(stream, &geom_prim,
1485 read_and_decode_ushort(stream,
1488 pobj->otype = object_type;
1489 pobj->geotype = geom_prim;
1491 switch (pobj->geotype & 0x0f) {
1494 if (!read_and_decode_ushort(stream, &n_elements))
return false;
1496 pobj->n_geom_elements = n_elements;
1497 t = (pobj->n_geom_elements * 2) + 2;
1498 obj_desc_bytes -= t;
1501 pobject_vector_collection;
1505 for (
unsigned short i = 0; i < pobj->n_geom_elements; i++) {
1506 if (!read_and_decode_ushort(stream, &index))
return false;
1508 if ((index & 0x1fff) > pCIB->m_nvector_records)
1514 pobject_vector_collection->pGeom_Description = u;
1515 pobject_vector_collection->segment_usage =
1516 (
unsigned char)(index >> 13);
1518 pobject_vector_collection++;
1526 if (!read_and_decode_ushort(
1527 stream, &n_elements))
1530 pobj->n_geom_elements = n_elements;
1531 t = (pobj->n_geom_elements * 2) + 2;
1532 obj_desc_bytes -= t;
1535 pobject_vector_collection;
1539 for (
unsigned short i = 0; i < pobj->n_geom_elements; i++) {
1540 unsigned short geometry_index;
1542 if (!read_and_decode_ushort(stream, &geometry_index))
return false;
1544 if ((geometry_index & 0x1fff) > pCIB->m_nvector_records)
1549 geometry_index & 0x1fff)];
1551 pobject_vector_collection->pGeom_Description = u;
1552 pobject_vector_collection->segment_usage =
1553 (
unsigned char)(geometry_index >> 13);
1555 pobject_vector_collection++;
1562 if (!read_and_decode_ushort(stream, &index))
return false;
1564 obj_desc_bytes -= 2;
1566 pobj->n_geom_elements = 1;
1568 pobj->pGeometry = &pCIB->p2dpoint_array[index];
1574 if (!read_and_decode_ushort(stream, &index))
return false;
1575 obj_desc_bytes -= 2;
1577 pobj->n_geom_elements = 1;
1580 &pCIB->point3d_descriptor_block[index];
1587 if ((pobj->geotype & 0x10) == 0x10)
1589 unsigned char nrelated;
1590 if (!read_and_decode_bytes(stream, &nrelated, 1))
return false;
1592 pobj->n_related_objects = nrelated;
1593 t = (pobj->n_related_objects * 2) + 1;
1594 obj_desc_bytes -= t;
1596 pobj->p_related_object_pointer_array = p_relob;
1597 p_relob += pobj->n_related_objects;
1599 Object **w = (
Object **)pobj->p_related_object_pointer_array;
1600 for (
unsigned char j = 0; j < pobj->n_related_objects; j++) {
1601 if (!read_and_decode_ushort(stream, &index))
return false;
1603 if (index > pCIB->m_nfeature_records)
1607 Object *prelated_object = &pCIB->pobject_block[index];
1608 *w = prelated_object;
1610 prelated_object->p_related_object_pointer_array =
1616 if ((pobj->geotype & 0x20) == 0x20) {
1617 unsigned short nrelated;
1618 if (!read_and_decode_ushort(stream, &nrelated))
return false;
1620 pobj->n_related_objects = (
unsigned char)(nrelated & 0xFF);
1621 obj_desc_bytes -= 2;
1624 if ((pobj->geotype & 0x40) == 0x40) {
1627 if ((pobj->geotype & 0x80) == 0x80)
1629 unsigned char nattr;
1630 if (!read_and_decode_bytes(stream, &nattr, 1))
return false;
1632 pobj->n_attributes = nattr;
1633 obj_desc_bytes -= 5;
1635 pobj->attributes_block = puc_var10;
1636 puc_var10 += obj_desc_bytes;
1638 puc10count += obj_desc_bytes;
1640 if (!read_and_decode_bytes(stream, pobj->attributes_block,
1644 if ((pobj->geotype & 0x0f) == 1) {
1655 printf(
"catch on read_feature_record_table\n");
1661 bool Ingest_CM93_Cell(
const char *cell_file_name,
Cell_Info_Block *pCIB) {
1666 FILE *flstream = fopen(cell_file_name,
"rb");
1667 if (!flstream)
return false;
1669 fseek(flstream, 0, SEEK_END);
1670 file_length = ftell(flstream);
1674 FILE *stream = fopen(cell_file_name,
"rb");
1675 if (!stream)
return false;
1679 unsigned short word0 = 0;
1685 read_and_decode_ushort(stream,
1687 read_and_decode_int(stream, &int0);
1688 read_and_decode_int(stream, &int1);
1690 int test = word0 + int0 + int1;
1691 if (test != file_length) {
1698 if (!read_header_and_populate_cib(stream, pCIB)) {
1703 if (!read_vector_record_table(stream, pCIB->m_nvector_records, pCIB)) {
1708 if (!read_3dpoint_table(stream, pCIB->m_n_point3d_records, pCIB)) {
1713 if (!read_2dpoint_table(stream, pCIB->m_n_point2d_records, pCIB)) {
1718 if (!read_feature_record_table(stream, pCIB->m_nfeature_records, pCIB)) {
1741 cm93chart::cm93chart() {
1742 m_ChartType = CHART_TYPE_CM93;
1745 if (!cm93_decode_table_created) {
1746 CreateDecodeTable();
1747 cm93_decode_table_created =
true;
1753 m_current_cell_vearray_offset = 0;
1755 m_ncontour_alloc = 100;
1756 m_pcontour_array = (
int *)malloc(m_ncontour_alloc *
sizeof(
int));
1766 m_pDrawBuffer = (wxPoint *)malloc(4 *
sizeof(wxPoint));
1767 m_nDrawBufferSize = 1;
1770 m_this_chart_context = (chart_context *)calloc(
sizeof(chart_context), 1);
1771 m_this_chart_context->chart =
this;
1775 cm93chart::~cm93chart() {
1776 free(m_pcontour_array);
1780 free(m_pDrawBuffer);
1783 void cm93chart::Unload_CM93_Cell(
void) {
1784 free(m_CIB.pobject_block);
1786 free(m_CIB.p2dpoint_array);
1787 free(m_CIB.pprelated_object_block);
1788 free(m_CIB.object_vector_record_descriptor_block);
1789 free(m_CIB.attribute_block_top);
1790 free(m_CIB.edge_vector_descriptor_block);
1791 free(m_CIB.pvector_record_block_top);
1792 free(m_CIB.point3d_descriptor_block);
1793 free(m_CIB.p3dpoint_array);
1802 double cm93chart::GetNormalScaleMin(
double canvas_scale_factor,
1803 bool b_allow_overzoom) {
1804 switch (GetNativeScale()) {
1826 double cm93chart::GetNormalScaleMax(
double canvas_scale_factor,
1834 switch (GetNativeScale()) {
1856 void cm93chart::GetPointPix(ObjRazRules *rzRules,
float north,
float east,
1858 wxPoint2DDouble en(east, north);
1859 GetPointPix(rzRules, &en, r, 1);
1862 void cm93chart::GetPointPix(ObjRazRules *rzRules, wxPoint2DDouble *en,
1863 wxPoint *r,
int nPoints) {
1864 S57Obj *obj = rzRules->obj;
1866 double xr = obj->x_rate;
1867 double xo = obj->x_origin;
1868 double yr = obj->y_rate;
1869 double yo = obj->y_origin;
1871 if (m_vp_current.m_projection_type == PROJECTION_MERCATOR) {
1872 if (m_vp_current.GetBBox().GetMaxLon() >= 180. &&
1873 rzRules->obj->BBObj.GetMaxLon() < m_vp_current.GetBBox().GetMinLon())
1874 xo += mercator_k0 * WGS84_semimajor_axis_meters * 2.0 * PI;
1875 else if ((m_vp_current.GetBBox().GetMinLon() <= -180. &&
1876 rzRules->obj->BBObj.GetMinLon() >
1877 m_vp_current.GetBBox().GetMaxLon()) ||
1878 (rzRules->obj->BBObj.GetMaxLon() >= 180 &&
1879 m_vp_current.GetBBox().GetMinLon() <= 0.))
1880 xo -= mercator_k0 * WGS84_semimajor_axis_meters * 2.0 * PI;
1882 for (
int i = 0; i < nPoints; i++) {
1883 double valx = (en[i].m_x * xr) + xo;
1884 double valy = (en[i].m_y * yr) + yo;
1886 r[i].x = ((valx - m_easting_vp_center) * m_view_scale_ppm) +
1887 m_pixx_vp_center + 0.5;
1888 r[i].y = m_pixy_vp_center -
1889 ((valy - m_northing_vp_center) * m_view_scale_ppm) + 0.5;
1892 for (
int i = 0; i < nPoints; i++) {
1893 double valx = (en[i].m_x * xr) + xo;
1894 double valy = (en[i].m_y * yr) + yo;
1897 fromSM(valx - m_easting_vp_center, valy - m_northing_vp_center,
1898 m_vp_current.clat, m_vp_current.clon, &lat, &lon);
1900 double rotation = m_vp_current.rotation;
1901 m_vp_current.SetRotationAngle(0);
1902 r[i] = m_vp_current.GetPixFromLL(lat, lon);
1903 m_vp_current.SetRotationAngle(rotation);
1908 void cm93chart::GetPixPoint(
int pixx,
int pixy,
double *plat,
double *plon,
1911 vpt->GetLLFromPix(wxPoint(pixx, pixy), plat, plon);
1918 int dx = pixx - (vpt->pix_width / 2);
1919 int dy = (vpt->pix_height / 2) - pixy;
1921 double xp = (dx * cos(vpt->skew)) - (dy * sin(vpt->skew));
1922 double yp = (dy * cos(vpt->skew)) + (dx * sin(vpt->skew));
1924 double d_east = xp / vpt->view_scale_ppm;
1925 double d_north = yp / vpt->view_scale_ppm;
1928 fromSM(d_east, d_north, vpt->clat, vpt->clon, &slat, &slon);
1930 if (slon > 360.) slon -= 360.;
1938 if (IsCacheValid()) {
1940 if (vp_last.view_scale_ppm == vp_proposed.view_scale_ppm) {
1944 wxPoint2DDouble p = vp_proposed.GetDoublePixFromLL(ref_lat, ref_lon) -
1945 vp_last.GetDoublePixFromLL(ref_lat, ref_lon);
1948 vp_last.GetLLFromPix(wxPoint(round(p.m_x), round(p.m_y)), &xlat, &xlon);
1950 double prev_easting_c, prev_northing_c;
1951 toSM(vp_last.clat, vp_last.clon, ref_lat, ref_lon, &prev_easting_c,
1954 double easting_c, northing_c;
1955 toSM(vp_proposed.clat, vp_proposed.clon, ref_lat, ref_lon, &easting_c,
1958 double delta_pix_x =
1959 (easting_c - prev_easting_c) * vp_proposed.view_scale_ppm;
1960 int dpix_x = (
int)round(delta_pix_x);
1961 double dpx = dpix_x;
1963 double delta_pix_y =
1964 (northing_c - prev_northing_c) * vp_proposed.view_scale_ppm;
1965 int dpix_y = (
int)round(delta_pix_y);
1966 double dpy = dpix_y;
1968 double c_east_d = (dpx / vp_proposed.view_scale_ppm) + prev_easting_c;
1969 double c_north_d = (dpy / vp_proposed.view_scale_ppm) + prev_northing_c;
1972 fromSM(c_east_d, c_north_d, ref_lat, ref_lon, &xlat, &xlon);
1974 vp_proposed.clon = xlon;
1975 vp_proposed.clat = xlat;
1988 void cm93chart::SetVPParms(
const ViewPort &vpt) {
1989 if (m_vp_current == vpt) {
1996 m_pixx_vp_center = vpt.pix_width / 2;
1997 m_pixy_vp_center = vpt.pix_height / 2;
1998 m_view_scale_ppm = vpt.view_scale_ppm;
2000 toSM(vpt.clat, vpt.clon, ref_lat, ref_lon, &m_easting_vp_center,
2001 &m_northing_vp_center);
2003 vp_transform.easting_vp_center = m_easting_vp_center;
2004 vp_transform.northing_vp_center = m_northing_vp_center;
2009 LLBBox box = vptl.GetBBox();
2010 double ll_lon = box.GetMinLon();
2011 double ll_lat = box.GetMinLat();
2013 double ur_lon = box.GetMaxLon();
2014 double ur_lat = box.GetMaxLat();
2017 "cm93chart::SetVPParms ll_lon: %g ll_lat: %g ur_lon: %g ur_lat: "
2019 ll_lon, ll_lat, ur_lon, ur_lat, m_dval);
2023 std::vector<int> vpcells = GetVPCellArray(vpt);
2029 for (
unsigned int i = 0; i < vpcells.size(); i++) {
2030 bcell_is_in =
false;
2031 for (
unsigned int j = 0; j < m_cells_loaded_array.size(); j++) {
2032 if (vpcells[i] == m_cells_loaded_array[j]) {
2040 #ifndef __OCPN__ANDROID__
2041 AbstractPlatform::ShowBusySpinner();
2043 int cell_index = vpcells[i];
2045 if (loadcell_in_sequence(cell_index,
'0'))
2047 ProcessVectorEdges();
2048 CreateObjChain(cell_index, (
int)
'0', vpt.view_scale_ppm);
2050 ForceEdgePriorityEvaluate();
2052 m_cells_loaded_array.push_back(cell_index);
2057 char loadcell_key =
'A';
2061 while (loadcell_in_sequence(cell_index, loadcell_key)) {
2062 ProcessVectorEdges();
2063 CreateObjChain(cell_index, (
int)loadcell_key, vpt.view_scale_ppm);
2065 ForceEdgePriorityEvaluate();
2067 if (std::find(m_cells_loaded_array.begin(), m_cells_loaded_array.end(),
2068 cell_index) == m_cells_loaded_array.end())
2069 m_cells_loaded_array.push_back(cell_index);
2076 AssembleLineGeometry();
2078 ClearDepthContourArray();
2079 BuildDepthContourArray();
2082 m_this_chart_context->m_pvc_hash = &Get_vc_hash();
2083 m_this_chart_context->m_pve_hash = &Get_ve_hash();
2085 m_this_chart_context->pFloatingATONArray = pFloatingATONArray;
2086 m_this_chart_context->pRigidATONArray = pRigidATONArray;
2087 m_this_chart_context->chart =
this;
2088 m_this_chart_context->chart_type = GetChartType();
2090 m_this_chart_context->safety_contour = m_next_safe_cnt;
2091 m_this_chart_context->vertex_buffer = GetLineVertexBuffer();
2092 m_this_chart_context->pt2GetAssociatedObjects = &s57chart::GetAssociatedObjects;
2095 for (
int i = 0; i < PI_PRIO_NUM; ++i) {
2096 for (
int j = 0; j < PI_LUPNAME_NUM; j++) {
2097 ObjRazRules *top = razRules[i][j];
2099 if (top->obj) top->obj->m_chart_context = m_this_chart_context;
2105 AbstractPlatform::HideBusySpinner();
2110 std::vector<int> cm93chart::GetVPCellArray(
const ViewPort &vpt) {
2113 LLBBox box = vptl.GetBBox();
2114 double ll_lon = box.GetMinLon();
2115 double ll_lat = box.GetMinLat();
2117 double ur_lon = box.GetMaxLon();
2118 double ur_lat = box.GetMaxLat();
2121 ur_lat = wxMin(ur_lat, 79.99999);
2124 ur_lat = wxMin(ur_lat, 79.99999);
2133 std::vector<int> vpcells;
2135 int lower_left_cell = Get_CM93_CellIndex(ll_lat, ll_lon, GetNativeScale());
2136 vpcells.push_back(lower_left_cell);
2139 printf(
"cm93chart::GetVPCellArray Adding %d\n", lower_left_cell);
2142 Get_CM93_Cell_Origin(lower_left_cell, GetNativeScale(), &rlat, &rlon);
2147 int loni_0 = (int)wxRound(rlon * 3);
2148 int loni_20 = loni_0 + (int)m_dval;
2149 int lati_20 = (int)wxRound(rlat * 3);
2151 while (lati_20 < (ur_lat * 3.)) {
2152 while (loni_20 < (ur_lon * 3.)) {
2153 unsigned int next_lon = loni_20 + 1080;
2154 while (next_lon >= 1080) next_lon -= 1080;
2156 unsigned int next_cell = next_lon;
2158 next_cell += (lati_20 + 270) * 10000;
2160 vpcells.push_back((
int)next_cell);
2162 printf(
"cm93chart::GetVPCellArray Adding %d\n", next_cell);
2164 loni_20 += (int)m_dval;
2166 lati_20 += (int)m_dval;
2173 void cm93chart::ProcessVectorEdges(
void) {
2176 auto &vehash = Get_ve_hash();
2178 m_current_cell_vearray_offset =
2182 for (
int iedge = 0; iedge < m_CIB.m_nvector_records; iedge++) {
2183 VE_Element *vep =
new VE_Element;
2184 vep->index = iedge + m_current_cell_vearray_offset;
2185 vep->nCount = pgd->n_points;
2186 vep->pPoints = NULL;
2187 vep->max_priority = -99;
2189 if (pgd->n_points) {
2190 float *pPoints = (
float *)malloc(pgd->n_points * 2 *
sizeof(
float));
2191 vep->pPoints = pPoints;
2196 double east_max = -1e7;
2197 double east_min = 1e7;
2198 double north_max = -1e7;
2199 double north_min = 1e7;
2201 for (
int ip = 0; ip < pgd->n_points; ip++) {
2202 *pPoints++ = ppt->x;
2203 *pPoints++ = ppt->y;
2205 east_max = wxMax(east_max, ppt->x);
2206 east_min = wxMin(east_min, ppt->x);
2207 north_max = wxMax(north_max, ppt->y);
2208 north_min = wxMin(north_min, ppt->y);
2214 double lat1, lon1, lat2, lon2;
2220 Transform(&p, 0, 0, &lat1, &lon1);
2224 Transform(&p, 0, 0, &lat2, &lon2);
2229 vep->edgeBBox.Set(lat1, lon1, lat2, lon2);
2232 vehash[vep->index] = vep;
2238 int cm93chart::CreateObjChain(
int cell_index,
int subcell,
2239 double view_scale_ppm) {
2241 LUPname LUP_Name = PAPER_CHART;
2243 m_CIB.m_cell_mcovr_list.Clear();
2247 Object *pobjectDef = m_CIB.pobject_block;
2248 m_CIB.b_have_offsets =
false;
2250 m_CIB.b_have_user_offsets =
false;
2256 double scale = gFrame->GetBestVPScale(
this);
2257 int nativescale = GetNativeScale();
2259 while (iObj < m_CIB.m_nfeature_records) {
2260 if ((pobjectDef != NULL)) {
2261 Extended_Geometry *xgeom = BuildGeom(pobjectDef, NULL, iObj);
2266 CreateS57Obj(cell_index, iObj, subcell, pobjectDef, m_pDict, xgeom,
2267 ref_lat, ref_lon, GetNativeScale(), view_scale_ppm);
2270 wxString objnam = obj->GetAttrValueAsString(
"OBJNAM");
2271 wxString fe_name = wxString(obj->FeatureName, wxConvUTF8);
2272 if (fe_name == _T(
"_texto"))
2273 objnam = obj->GetAttrValueAsString(
"_texta");
2274 if (objnam.Len() > 0) {
2276 wxString::Format(_T(
"%i_%i"), cell_index, subcell);
2277 g_pi_manager->SendVectorChartObjectInfo(cellname, fe_name, objnam,
2278 obj->m_lat, obj->m_lon,
scale,
2282 if (GEO_POINT == obj->Primitive_type) {
2284 if ((!strncmp(obj->FeatureName,
"LITFLT", 6)) ||
2285 (!strncmp(obj->FeatureName,
"LITVES", 6)) ||
2286 (!strncmp(obj->FeatureName,
"BOY", 3))) {
2287 pFloatingATONArray->Add(obj);
2291 if (!strncmp(obj->FeatureName,
"BCN", 3)) pRigidATONArray->Add(obj);
2294 if ((!strncmp(obj->FeatureName,
"LIT", 3)) ||
2295 (!strncmp(obj->FeatureName,
"LIGHTS", 6)) ||
2296 (!strncmp(obj->FeatureName,
"BCN", 3)) ||
2297 (!strncmp(obj->FeatureName,
"_slgto", 6)) ||
2298 (!strncmp(obj->FeatureName,
"_boygn", 6)) ||
2299 (!strncmp(obj->FeatureName,
"_bcngn", 6)) ||
2300 (!strncmp(obj->FeatureName,
"_extgn", 6)) ||
2301 (!strncmp(obj->FeatureName,
"TOWERS", 6)) ||
2302 (!strncmp(obj->FeatureName,
"BOY", 3))) {
2303 obj->bIsAton =
true;
2309 if (GEO_AREA == obj->Primitive_type) {
2310 if (!strncmp(obj->FeatureName,
"DEPARE", 6) ||
2311 !strncmp(obj->FeatureName,
"DRGARE", 6))
2312 obj->bIsAssociable =
true;
2320 switch (obj->Primitive_type) {
2324 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
2325 LUP_Name = PAPER_CHART;
2327 LUP_Name = SIMPLIFIED;
2329 if (m_b2pointLUPS) {
2331 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
2332 LUPO_Name = SIMPLIFIED;
2334 LUPO_Name = PAPER_CHART;
2338 ps52plib->S52_LUPLookup(LUPO_Name, obj->FeatureName, obj);
2340 ps52plib->_LUP2rules(LUPO, obj);
2341 _insertRules(obj, LUPO,
this);
2351 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
2352 LUP_Name = PLAIN_BOUNDARIES;
2354 LUP_Name = SYMBOLIZED_BOUNDARIES;
2358 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
2359 LUPO_Name = SYMBOLIZED_BOUNDARIES;
2361 LUPO_Name = PLAIN_BOUNDARIES;
2365 ps52plib->S52_LUPLookup(LUPO_Name, obj->FeatureName, obj);
2367 ps52plib->_LUP2rules(LUPO, obj);
2368 _insertRules(obj, LUPO,
this);
2374 LUP = ps52plib->S52_LUPLookup(LUP_Name, obj->FeatureName, obj);
2378 wxString msg(obj->FeatureName, wxConvUTF8);
2379 msg.Prepend(_T (
" CM93 could not find LUP for " ));
2380 LogMessageOnce(msg);
2382 if (0 == obj->nRef)
delete obj;
2385 ps52plib->_LUP2rules(LUP, obj);
2388 _insertRules(obj, LUP,
this);
2391 obj->m_DisplayCat = LUP->DISC;
2394 obj->m_DPRI = LUP->DPRI -
'0';
2397 obj->m_chart_context = m_this_chart_context;
2416 InitReturn cm93chart::Init(
const wxString &name, ChartInitFlag flags) {
2418 m_Description = m_FullPath;
2420 wxFileName fn(name);
2422 if (!m_prefix.Len())
2423 m_prefix = fn.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
2425 m_scalechar = fn.GetExt();
2430 switch ((m_scalechar.mb_str())[(
size_t)0]) {
2460 m_Chart_Scale =
scale;
2462 switch (GetNativeScale()) {
2493 wxString data = _T (
"CM93Chart " );
2494 data.Append(m_scalechar);
2496 s.Printf(_T (
" 1/%d" ), m_Chart_Scale);
2501 if (
scale != 20000000)
2502 m_pcovr_set->Init(m_scalechar.mb_str()[(
size_t)0], m_prefix);
2504 if (flags == THUMB_ONLY) {
2512 if (flags == HEADER_ONLY)
return CreateHeaderDataFromCM93Cell();
2517 if (m_pManager->Loadcm93Dictionary(name))
2518 m_pDict = m_pManager->m_pcm93Dict;
2520 wxLogMessage(_T (
" CM93Chart Init cannot locate CM93 dictionary." ));
2521 return INIT_FAIL_REMOVE;
2526 bReadyToRender =
true;
2531 Extended_Geometry *cm93chart::BuildGeom(
Object *pobject,
2532 wxFileOutputStream *postream,
2539 int geom_type_maybe = pobject->geotype;
2541 switch (geom_type_maybe) {
2579 Extended_Geometry *ret_ptr =
new Extended_Geometry;
2581 int lon_max, lat_max, lon_min, lat_min;
2593 int nsegs = pobject->n_geom_elements;
2595 ret_ptr->n_vector_indices = nsegs;
2596 ret_ptr->pvector_index = (
int *)malloc(nsegs * 3 *
sizeof(
int));
2599 int n_maxvertex = 0;
2600 for (
int i = 0; i < nsegs; i++) {
2603 n_maxvertex += pgd->n_points;
2609 wxPoint2DDouble *pPoints =
2610 (wxPoint2DDouble *)calloc((n_maxvertex) *
sizeof(wxPoint2DDouble), 1);
2613 int n_prev_vertex_index = 1;
2614 bool bnew_ring =
true;
2623 cur_end_point.x = 1;
2624 cur_end_point.y = 1;
2626 int n_max_points = -1;
2627 while (iseg < nsegs) {
2628 int type_seg = psegs[iseg].segment_usage;
2633 int npoints = pgd->n_points;
2636 n_max_points = wxMax(n_max_points, npoints);
2642 if ((type_seg & 4) == 0)
2643 start_point = rseg[0];
2645 start_point = rseg[npoints - 1];
2648 if (((type_seg & 4) == 0)) {
2649 cur_end_point = rseg[npoints - 1];
2650 for (
int j = 0; j < npoints; j++) {
2654 lon_max = wxMax(lon_max, rseg[j].x);
2655 lon_min = wxMin(lon_min, rseg[j].x);
2656 lat_max = wxMax(lat_max, rseg[j].y);
2657 lat_min = wxMin(lat_min, rseg[j].y);
2660 pPoints[ip].m_x = rseg[j].x;
2661 pPoints[ip].m_y = rseg[j].y;
2664 }
else if ((type_seg & 4) == 4)
2666 cur_end_point = rseg[0];
2667 for (
int j = npoints - 1; j >= 0; j--) {
2671 lon_max = wxMax(lon_max, rseg[j].x);
2672 lon_min = wxMin(lon_min, rseg[j].x);
2673 lat_max = wxMax(lat_max, rseg[j].y);
2674 lat_min = wxMin(lat_min, rseg[j].y);
2677 pPoints[ip].m_x = rseg[j].x;
2678 pPoints[ip].m_y = rseg[j].y;
2685 ret_ptr->pvector_index[iseg * 3 + 0] =
2687 ret_ptr->pvector_index[iseg * 3 + 1] =
2688 pgd->index + m_current_cell_vearray_offset;
2689 ret_ptr->pvector_index[iseg * 3 + 2] =
2692 if ((cur_end_point.x == start_point.x) &&
2693 (cur_end_point.y == start_point.y)) {
2698 int nRingVertex = ip - n_prev_vertex_index;
2701 if (ncontours > m_ncontour_alloc - 1) {
2702 m_ncontour_alloc *= 2;
2703 int *tmp = m_pcontour_array;
2704 m_pcontour_array = (
int *)realloc(m_pcontour_array,
2705 m_ncontour_alloc *
sizeof(
int));
2711 m_pcontour_array[ncontours] = nRingVertex;
2714 n_prev_vertex_index = ip;
2720 ret_ptr->n_max_edge_points = n_max_points;
2722 ret_ptr->n_contours =
2725 if (0 == ncontours) ncontours = 1;
2726 ret_ptr->contour_array = (
int *)malloc(ncontours *
sizeof(
int));
2727 memcpy(ret_ptr->contour_array, m_pcontour_array, ncontours *
sizeof(
int));
2729 ret_ptr->vertex_array = pPoints;
2730 ret_ptr->n_max_vertex = n_maxvertex;
2732 ret_ptr->pogrGeom = NULL;
2734 ret_ptr->xmin = lon_min;
2735 ret_ptr->xmax = lon_max;
2736 ret_ptr->ymin = lat_min;
2737 ret_ptr->ymax = lat_max;
2745 ret_ptr->pogrGeom = NULL;
2747 ret_ptr->pointx = pt->x;
2748 ret_ptr->pointy = pt->y;
2757 int nsegs = pobject->n_geom_elements;
2759 ret_ptr->n_vector_indices = nsegs;
2760 ret_ptr->pvector_index = (
int *)malloc(nsegs * 3 *
sizeof(
int));
2763 int n_maxvertex = 0;
2764 for (
int imseg = 0; imseg < nsegs; imseg++) {
2768 n_maxvertex += pgd->n_points;
2772 wxPoint2DDouble *pPoints =
2773 (wxPoint2DDouble *)malloc(n_maxvertex *
sizeof(wxPoint2DDouble));
2778 int lon_max, lat_max, lon_min, lat_min;
2783 int n_max_points = -1;
2785 for (
int iseg = 0; iseg < nsegs; iseg++) {
2786 int type_seg = psegs->segment_usage;
2793 int npoints = pgd->n_points;
2796 n_max_points = wxMax(n_max_points, npoints);
2798 if (((type_seg & 4) != 4)) {
2799 for (
int j = 0; j < npoints; j++) {
2800 lon_max = wxMax(lon_max, rseg[j].x);
2801 lon_min = wxMin(lon_min, rseg[j].x);
2802 lat_max = wxMax(lat_max, rseg[j].y);
2803 lat_min = wxMin(lat_min, rseg[j].y);
2805 pPoints[ip].m_x = rseg[j].x;
2806 pPoints[ip].m_y = rseg[j].y;
2811 else if ((type_seg & 4) == 4)
2813 for (
int j = npoints - 1; j >= 0; j--) {
2814 lon_max = wxMax(lon_max, rseg[j].x);
2815 lon_min = wxMin(lon_min, rseg[j].x);
2816 lat_max = wxMax(lat_max, rseg[j].y);
2817 lat_min = wxMin(lat_min, rseg[j].y);
2819 pPoints[ip].m_x = rseg[j].x;
2820 pPoints[ip].m_y = rseg[j].y;
2825 ret_ptr->pvector_index[iseg * 3 + 0] =
2827 ret_ptr->pvector_index[iseg * 3 + 1] =
2828 pgd->index + m_current_cell_vearray_offset;
2829 ret_ptr->pvector_index[iseg * 3 + 2] =
2834 ret_ptr->n_max_edge_points = n_max_points;
2836 ret_ptr->vertex_array = pPoints;
2837 ret_ptr->n_max_vertex = n_maxvertex;
2839 ret_ptr->pogrGeom = NULL;
2841 ret_ptr->xmin = lon_min;
2842 ret_ptr->xmax = lon_max;
2843 ret_ptr->ymin = lat_min;
2844 ret_ptr->ymax = lat_max;
2852 int npoints = pgd->n_points;
2855 OGRMultiPoint *pSMP =
new OGRMultiPoint;
2859 for (
int ip = 0; ip < npoints; ip++) {
2864 zp = double(z - 12000);
2868 OGRPoint *ppoint =
new OGRPoint(rseg[ip].x, rseg[ip].y, zp);
2869 pSMP->addGeometryDirectly(ppoint);
2871 lon_max = wxMax(lon_max, rseg[ip].x);
2872 lon_min = wxMin(lon_min, rseg[ip].x);
2873 lat_max = wxMax(lat_max, rseg[ip].y);
2874 lat_min = wxMin(lat_min, rseg[ip].y);
2877 ret_ptr->pogrGeom = pSMP;
2879 ret_ptr->xmin = lon_min;
2880 ret_ptr->xmax = lon_max;
2881 ret_ptr->ymin = lat_min;
2882 ret_ptr->ymax = lat_max;
2892 wxPrintf(_T (
"Unexpected geomtype %d for Feature %d\n" ), geomtype,
2902 void cm93chart::Transform(
cm93_point *s,
double trans_x,
double trans_y,
2903 double *lat,
double *lon) {
2905 double valx = (s->x * m_CIB.transform_x_rate) + m_CIB.transform_x_origin;
2906 double valy = (s->y * m_CIB.transform_y_rate) + m_CIB.transform_y_origin;
2914 (2.0 * atan(exp(valy / CM93_semimajor_axis_meters)) - PI / 2.) / DEGREE;
2915 *lon = (valx / (DEGREE * CM93_semimajor_axis_meters));
2920 m_block = (
unsigned char *)
block;
2924 unsigned char *cm93_attr_block::GetNextAttr() {
2926 unsigned char *ret_val = m_block + m_cptr;
2930 unsigned char iattr = *(m_block + m_cptr);
2934 char vtype = m_pDict->GetAttrType(iattr);
2947 while (*(m_block + m_cptr)) m_cptr++;
2964 while (*(m_block + m_cptr)) m_cptr++;
2970 unsigned char nl = *(m_block + m_cptr);
2997 wxString ParseSLGTA(wxString &val) {
3002 wxStringTokenizer tkz(val, wxT(
"|"));
3004 s = tkz.GetNextToken();
3005 s = tkz.GetNextToken();
3006 s = tkz.GetNextToken();
3009 wxString sc, st, sp;
3022 else if (s[0] ==
'G') {
3025 }
else if (s.Mid(0, 3) == _T (
"W/O" )) {
3031 }
else if (s.Mid(0, 5) == _T (
"LIGHT" )) {
3036 if (val.Find(_T (
"Spar" )) != wxNOT_FOUND) {
3040 if (val.Find(_T (
"SPAR" )) != wxNOT_FOUND) {
3045 if ((type == 2) && (color == 3))
3052 sprintf(line,
" %s (%c) = %s",
"COLOUR",
'I', (
const char *)sc.mb_str());
3053 result += wxString(line, wxConvUTF8);
3056 sprintf(line,
" %s (%c) = %s",
"BOYSHP",
'I',
"4");
3057 result += wxString(line, wxConvUTF8);
3063 sprintf(line,
" %s (%c) = %s",
"BOYSHP",
'I', (
const char *)st.mb_str());
3064 result += wxString(line, wxConvUTF8);
3067 sprintf(line,
" %s (%c) = %s",
"COLOUR",
'I',
"2");
3068 result += wxString(line, wxConvUTF8);
3074 sprintf(line,
" %s (%c) = %s",
"COLPAT",
'I', (
const char *)sp.mb_str());
3075 result += wxString(line, wxConvUTF8);
3082 wxString ParseTEXTA(wxString &val) {
3086 if (val.Contains(_T (
"WK S" ))) {
3087 sprintf(line,
" %s (%c) = %s",
"WRKATT",
'I',
"1");
3088 result += wxString(line, wxConvUTF8);
3095 void cm93chart::translate_colmar(
const wxString &sclass,
3096 S57attVal *pattValTmp) {
3097 int *pcur_attr = (
int *)pattValTmp->value;
3098 int cur_attr = *pcur_attr;
3104 lstring = _T (
"4" );
3107 lstring = _T (
"2" );
3110 lstring = _T (
"3" );
3113 lstring = _T (
"6" );
3116 lstring = _T (
"1" );
3119 lstring = _T (
"11" );
3122 lstring = _T (
"2,6" );
3125 lstring = _T (
"2,6,2" );
3128 lstring = _T (
"6,2" );
3131 lstring = _T (
"6,2,6" );
3134 lstring = _T (
"3,1" );
3137 lstring = _T (
"4,3,4" );
3140 lstring = _T (
"3,4,3" );
3143 lstring = _T (
"2,3,2" );
3146 lstring = _T (
"6,3,6" );
3149 lstring = _T (
"4,3" );
3152 lstring = _T (
"3,4" );
3155 lstring = _T (
"4,1" );
3161 if (lstring.Len()) {
3162 free(pattValTmp->value);
3164 pattValTmp->valType = OGR_STR;
3165 pattValTmp->value = strdup(lstring.mb_str());
3169 S57Obj *cm93chart::CreateS57Obj(
int cell_index,
int iobject,
int subcell,
3171 Extended_Geometry *xgeom,
double ref_lat,
3172 double ref_lon,
double scale,
3173 double view_scale_ppm) {
3174 #define MAX_HDR_LINE 4000
3178 int npub_year = 1993;
3180 int iclass = pobject->otype;
3181 int geomtype = pobject->geotype & 0x0f;
3183 double tmp_transform_x = 0.;
3184 double tmp_transform_y = 0.;
3187 double trans_WGS84_offset_x = 0.;
3188 double trans_WGS84_offset_y = 0.;
3190 wxString sclass = pDict->GetClassName(iclass);
3191 if (sclass == _T (
"Unknown" )) {
3193 msg.Printf(_T (
" CM93 Error...object type %d not found in CM93OBJ.DIC" ),
3200 wxString sclass_sub = sclass;
3203 if (sclass.IsSameAs(_T (
"ITDARE" ))) sclass_sub = _T (
"DEPARE" );
3205 if (sclass.IsSameAs(_T (
"_m_sor" ))) sclass_sub = _T (
"M_COVR" );
3207 if (sclass.IsSameAs(_T (
"SPOGRD" ))) sclass_sub = _T (
"DMPGRD" );
3209 if (sclass.IsSameAs(_T (
"FSHHAV" ))) sclass_sub = _T (
"FSHFAC" );
3211 if (sclass.IsSameAs(_T (
"OFSPRD" ))) sclass_sub = _T (
"CTNARE" );
3214 S57Obj *pobj =
new S57Obj();
3216 pobj->Index = iobject;
3219 strncpy(u, sclass_sub.mb_str(), 199);
3221 memcpy(pobj->FeatureName, u, 7);
3223 pobj->attVal =
new wxArrayOfS57attVal();
3227 for (
int jattr = 0; jattr < pobject->n_attributes; jattr++) {
3228 unsigned char *curr_attr = pab.GetNextAttr();
3230 unsigned char iattr = *curr_attr;
3232 wxString sattr = pDict->GetAttrName(iattr);
3234 char vtype = pDict->GetAttrType(iattr);
3236 unsigned char *aval = curr_attr + 1;
3249 S57attVal *pattValTmp =
new S57attVal;
3254 pAVI = (
int *)malloc(
sizeof(
int));
3256 pattValTmp->valType = OGR_INT;
3257 pattValTmp->value = pAVI;
3260 pb = (
unsigned char *)aval;
3261 pAVI = (
int *)malloc(
sizeof(
int));
3263 pattValTmp->valType = OGR_INT;
3264 pattValTmp->value = pAVI;
3267 pw = (
unsigned short *)aval;
3271 pAVR = (
double *)malloc(
sizeof(
double));
3272 *pAVR = dival / 10.;
3273 pattValTmp->valType = OGR_REAL;
3274 pattValTmp->value = pAVR;
3278 pAVI = (
int *)malloc(
sizeof(
int));
3280 pattValTmp->valType = OGR_INT;
3281 pattValTmp->value = pAVI;
3285 pAVS = strdup((
char*)aval);
3286 pattValTmp->valType = OGR_STR;
3287 pattValTmp->value = pAVS;
3291 pAVS = strdup((
const char*)&aval[3]);
3292 pattValTmp->valType = OGR_STR;
3293 pattValTmp->value = pAVS;
3296 pb = (
unsigned char *)aval;
3297 unsigned char nl = *pb++;
3300 for (
int i = 0; i < nl; i++) {
3301 sprintf(vi,
"%d,", *pb++);
3304 if (strlen(val)) val[strlen(val) - 1] = 0;
3307 pattValTmp->valType = OGR_STR;
3308 pattValTmp->value = pAVS;
3312 pAVR = (
double *)malloc(
sizeof(
double));
3316 float __attribute__((aligned(16))) tf1;
3317 unsigned char *pucf = (
unsigned char *)pf;
3319 memcpy(&tf1, pucf, sizeof(
float));
3325 pattValTmp->valType = OGR_REAL;
3326 pattValTmp->value = pAVR;
3334 if (sattr.IsSameAs(_T (
"COLMAR" ))) {
3335 translate_colmar(sclass, pattValTmp);
3336 sattr = _T (
"COLOUR" );
3340 if (pattValTmp->valType == OGR_INT &&
3341 (sattr.IsSameAs(_T (
"QUASOU" )) || sattr.IsSameAs(_T (
"CATLIT" )))) {
3342 int v = *(
int *)pattValTmp->value;
3343 free(pattValTmp->value);
3344 sprintf(val,
"%d", v);
3346 pattValTmp->valType = OGR_STR;
3347 pattValTmp->value = pAVS;
3351 if (sclass.IsSameAs(_T (
"$AREAS" )) && (vtype ==
'S') &&
3352 sattr.IsSameAs(_T (
"$SCODE" ))) {
3353 if (!strcmp((
char *)pattValTmp->value,
"II25")) {
3354 free(pattValTmp->value);
3355 pattValTmp->value = strdup(
"BACKGROUND");
3360 if (sattr.IsSameAs(_T (
"RECDAT" )) || sattr.IsSameAs(_T (
"_dgdat" ))) {
3361 if (sclass_sub.IsSameAs(_T (
"M_COVR" )) && (vtype ==
'S')) {
3362 wxString pub_date((
char *)pattValTmp->value, wxConvUTF8);
3365 upd.ParseFormat(pub_date, _T (
"%Y%m%d" ));
3366 if (!upd.IsValid()) upd.ParseFormat(_T (
"20000101" ), _T (
"%Y%m%d" ));
3369 pub_date.Truncate(4);
3372 pub_date.ToLong(&nyear);
3378 if (sclass_sub.IsSameAs(_T (
"M_COVR" )) && (vtype ==
'R')) {
3379 if (sattr.IsSameAs(_T (
"_wgsox" ))) {
3380 tmp_transform_x = *(
double *)pattValTmp->value;
3381 if (fabs(tmp_transform_x) > 1.0)
3382 m_CIB.b_have_offsets =
true;
3383 }
else if (sattr.IsSameAs(_T (
"_wgsoy" ))) {
3384 tmp_transform_y = *(
double *)pattValTmp->value;
3385 if (fabs(tmp_transform_y) > 1.0) m_CIB.b_have_offsets =
true;
3390 wxASSERT(sattr.Len() == 6);
3391 wxCharBuffer dbuffer = sattr.ToUTF8();
3392 if (dbuffer.data()) {
3394 (
char *)realloc(pobj->att_array, 6 * (pobj->n_attr + 1));
3396 strncpy(pobj->att_array + (6 *
sizeof(
char) * pobj->n_attr),
3400 pobj->attVal->Add(pattValTmp);
3414 if (1 == geomtype) {
3415 if ((!strncmp(pobj->FeatureName,
"LIT", 3)) ||
3416 (!strncmp(pobj->FeatureName,
"LIGHTS", 6)) ||
3417 (!strncmp(pobj->FeatureName,
"BCN", 3)) ||
3418 (!strncmp(pobj->FeatureName,
"_slgto", 6)) ||
3419 (!strncmp(pobj->FeatureName,
"_boygn", 6)) ||
3420 (!strncmp(pobj->FeatureName,
"_bcngn", 6)) ||
3421 (!strncmp(pobj->FeatureName,
"_extgn", 6)) ||
3422 (!strncmp(pobj->FeatureName,
"TOWERS", 6)) ||
3423 (!strncmp(pobj->FeatureName,
"BOY", 3))) {
3424 bool bfound_OBJNAM = (pobj->GetAttributeIndex(
"OBJNAM") != -1);
3425 bool bfound_INFORM = (pobj->GetAttributeIndex(
"INFORM") != -1);
3427 if ((!bfound_OBJNAM) && (bfound_INFORM))
3429 char *patl = pobj->att_array;
3430 for (
int i = 0; i < pobj->n_attr; i++) {
3431 if (!strncmp(patl,
"INFORM", 6)) {
3432 memcpy(patl,
"OBJNAM", 6);
3444 pobj->Primitive_type = GEO_AREA;
3447 if (sclass_sub.IsSameAs(_T (
"M_COVR" ))) {
3451 GetCoverSet()->Find_MCD(cell_index, iobject, subcell);
3452 if (NULL == pmcd_look)
3459 pmcd->m_cell_index = cell_index;
3460 pmcd->m_object_id = iobject;
3461 pmcd->m_subcell = subcell;
3464 pmcd->user_xoff = 0;
3465 pmcd->user_yoff = 0;
3466 pmcd->m_buser_offsets =
false;
3469 pmcd->m_npub_year = npub_year;
3472 int npta = xgeom->contour_array[0];
3473 float_2Dpt *geoPt =
new float_2Dpt[npta + 2];
3474 float_2Dpt *ppt = geoPt;
3476 pmcd->m_covr_lon_max = -1000.;
3477 pmcd->m_covr_lon_min = 1000.;
3478 pmcd->m_covr_lat_max = -1000.;
3479 pmcd->m_covr_lat_min = 1000.;
3483 for (
int ip = 0; ip < npta; ip++) {
3485 p.x = (int)xgeom->vertex_array[ip + 1].m_x;
3486 p.y = (
int)xgeom->vertex_array[ip + 1].m_y;
3488 Transform(&p, 0, 0, &lat,
3493 pmcd->m_covr_lon_max = wxMax(pmcd->m_covr_lon_max, lon);
3494 pmcd->m_covr_lon_min = wxMin(pmcd->m_covr_lon_min, lon);
3495 pmcd->m_covr_lat_max = wxMax(pmcd->m_covr_lat_max, lat);
3496 pmcd->m_covr_lat_min = wxMin(pmcd->m_covr_lat_min, lat);
3500 pmcd->m_nvertices = npta;
3501 pmcd->pvertices = geoPt;
3503 pmcd->m_covr_bbox.Set(pmcd->m_covr_lat_min, pmcd->m_covr_lon_min,
3504 pmcd->m_covr_lat_max, pmcd->m_covr_lon_max);
3508 pmcd->transform_WGS84_offset_x = tmp_transform_x;
3509 pmcd->transform_WGS84_offset_y = tmp_transform_y;
3511 pmcd->m_centerlat_cos = cos(
3512 ((pmcd->m_covr_lat_min + pmcd->m_covr_lat_max) / 2.) * PI / 180.);
3515 GetCoverSet()->Add_Update_MCD(pmcd);
3520 if (pmcd_look->m_buser_offsets) {
3521 m_CIB.b_have_user_offsets =
true;
3523 m_CIB.user_xoff = pmcd_look->user_xoff;
3524 m_CIB.user_yoff = pmcd_look->user_yoff;
3531 m_pcovr_array_loaded.Add(pmcd);
3534 unsigned int n = pmcd->m_nvertices;
3535 double *pts =
new double[2 * n];
3538 for (
size_t i = 0; i < 2 * n; i++)
3539 pts[i] = ((
float *)pmcd->pvertices)[i];
3543 if (LLRegion::PointsCCW(n, pts))
3544 for (
size_t i = 0; i < n; i++)
3545 if (pts[2 * i + 1] < 0) pts[2 * i + 1] += 360;
3548 LLRegion rgn_covr(n, pts);
3549 m_region.Union(rgn_covr);
3557 m_CIB.m_cell_mcovr_list.Append(pmcd);
3561 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3562 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3565 pobj->m_n_lsindex = xgeom->n_vector_indices;
3566 pobj->m_lsindex_array =
3567 xgeom->pvector_index;
3568 pobj->m_n_edge_max_points = 0;
3571 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3574 pc.x = (
short unsigned int)pobj->x;
3575 pc.y = (
short unsigned int)pobj->y;
3576 Transform(&pc, 0., 0., &latc, &lonc);
3578 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(latc, lonc);
3580 trans_WGS84_offset_x = pmcd->user_xoff;
3581 trans_WGS84_offset_y = pmcd->user_yoff;
3586 double lat1, lon1, lat2, lon2;
3589 p.x = (int)xgeom->xmin;
3590 p.y = (
int)xgeom->ymin;
3591 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3592 xgeom->ref_lat = lat1;
3593 xgeom->ref_lon = lon1;
3595 p.x = (int)xgeom->xmax;
3596 p.y = (
int)xgeom->ymax;
3597 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat2, &lon2);
3598 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3603 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3611 xgeom->x_rate = m_CIB.transform_x_rate;
3612 xgeom->x_offset = m_CIB.transform_x_origin - trans_WGS84_offset_x;
3613 xgeom->y_rate = m_CIB.transform_y_rate;
3614 xgeom->y_offset = m_CIB.transform_y_origin - trans_WGS84_offset_y;
3616 pobj->pPolyTessGeo =
new PolyTessGeo(xgeom);
3623 pobj->Primitive_type = GEO_POINT;
3626 pobj->x = xgeom->pointx;
3627 pobj->y = xgeom->pointy;
3631 p.x = xgeom->pointx;
3632 p.y = xgeom->pointy;
3633 Transform(&p, 0., 0., &lat, &lon);
3636 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3637 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(lat, lon);
3639 trans_WGS84_offset_x = pmcd->user_xoff;
3640 trans_WGS84_offset_y = pmcd->user_yoff;
3645 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat, &lon);
3655 double llsize = 1e-3 / view_scale_ppm;
3657 pobj->BBObj.Set(lat, lon, lat, lon);
3658 pobj->BBObj.EnLarge(llsize);
3665 pobj->Primitive_type = GEO_POINT;
3668 double lat1, lon1, lat2, lon2;
3671 p.x = (int)xgeom->xmin;
3672 p.y = (
int)xgeom->ymin;
3673 Transform(&p, 0., 0., &lat1, &lon1);
3675 p.x = (int)xgeom->xmax;
3676 p.y = (
int)xgeom->ymax;
3677 Transform(&p, 0., 0., &lat2, &lon2);
3678 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3681 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3682 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3684 OGRMultiPoint *pGeo = (OGRMultiPoint *)xgeom->pogrGeom;
3685 pobj->npt = pGeo->getNumGeometries();
3687 pobj->geoPtz = (
double *)malloc(pobj->npt * 3 *
sizeof(
double));
3688 pobj->geoPtMulti = (
double *)malloc(pobj->npt * 2 *
sizeof(
double));
3690 double *pdd = pobj->geoPtz;
3691 double *pdl = pobj->geoPtMulti;
3693 for (
int ip = 0; ip < pobj->npt; ip++) {
3694 OGRPoint *ppt = (OGRPoint *)(pGeo->getGeometryRef(ip));
3697 p.x = (int)ppt->getX();
3698 p.y = (int)ppt->getY();
3699 double depth = ppt->getZ();
3704 double snd_trans_x = 0.;
3705 double snd_trans_y = 0.;
3708 if (m_CIB.b_have_user_offsets) {
3710 Transform(&p, 0., 0., &lats, &lons);
3712 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(lats, lons);
3715 snd_trans_x = pmcd->user_xoff;
3716 snd_trans_y = pmcd->user_yoff;
3720 east -= pmcd->user_xoff / m_CIB.transform_x_rate;
3721 north -= pmcd->user_yoff / m_CIB.transform_y_rate;
3731 Transform(&p, snd_trans_x, snd_trans_y, &lat1, &lon1);
3739 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3749 pobj->Primitive_type = GEO_LINE;
3751 pobj->npt = xgeom->n_max_vertex;
3752 pobj->geoPt = (pt *)xgeom->vertex_array;
3753 xgeom->vertex_array = NULL;
3756 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3757 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3760 pobj->m_n_lsindex = xgeom->n_vector_indices;
3761 pobj->m_lsindex_array =
3762 xgeom->pvector_index;
3763 pobj->m_n_edge_max_points = 0;
3766 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3769 pc.x = (
short unsigned int)pobj->x;
3770 pc.y = (
short unsigned int)pobj->y;
3771 Transform(&pc, 0., 0., &latc, &lonc);
3773 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(latc, lonc);
3775 trans_WGS84_offset_x = pmcd->user_xoff;
3776 trans_WGS84_offset_y = pmcd->user_yoff;
3781 double lat1, lon1, lat2, lon2;
3784 p.x = (int)xgeom->xmin;
3785 p.y = (
int)xgeom->ymin;
3786 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3788 p.x = (int)xgeom->xmax;
3789 p.y = (
int)xgeom->ymax;
3790 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat2, &lon2);
3791 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3796 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3805 pobj->Primitive_type = GEO_PRIM;
3812 if (!strncmp(pobj->FeatureName,
"OBSTRN", 6) ||
3813 !strncmp(pobj->FeatureName,
"WRECKS", 6) ||
3814 !strncmp(pobj->FeatureName,
"DEPCNT", 6) ||
3815 !strncmp(pobj->FeatureName,
"UWTROC", 6)) {
3816 pobj->m_bcategory_mutable =
true;
3818 pobj->m_bcategory_mutable =
false;
3831 if (geomtype != 4)
delete xgeom;
3835 m_CIB.transform_x_rate *
3836 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3838 m_CIB.transform_y_rate *
3839 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3841 m_CIB.transform_x_origin *
3842 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3844 m_CIB.transform_y_origin *
3845 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3849 pobj->x_origin -= trans_WGS84_offset_x;
3850 pobj->y_origin -= trans_WGS84_offset_y;
3853 pobj->auxParm3 = CHART_TYPE_CM93;
3859 M_COVR_Desc *cm93chart::FindM_COVR_InWorkingSet(
double lat,
double lon) {
3862 if (m_CIB.m_cell_mcovr_list.GetCount() == 1) {
3863 wxList_Of_M_COVR_DescNode *node0 = m_CIB.m_cell_mcovr_list.GetFirst();
3864 if (node0) ret = node0->GetData();
3866 wxList_Of_M_COVR_DescNode *node = m_CIB.m_cell_mcovr_list.GetFirst();
3870 if (G_PtInPolygon_FL(pmcd->pvertices, pmcd->m_nvertices, lon, lat)) {
3875 node = node->GetNext();
3883 wxPoint2DDouble cm93chart::FindM_COVROffset(
double lat,
double lon) {
3884 wxPoint2DDouble ret(0., 0.);
3887 wxList_Of_M_COVR_DescNode *node0 = m_CIB.m_cell_mcovr_list.GetFirst();
3890 ret.m_x = pmcd0->transform_WGS84_offset_x;
3891 ret.m_y = pmcd0->transform_WGS84_offset_y;
3895 if (m_CIB.m_cell_mcovr_list.GetCount() > 1) {
3896 wxList_Of_M_COVR_DescNode *node = m_CIB.m_cell_mcovr_list.GetFirst();
3900 if (G_PtInPolygon_FL(pmcd->pvertices, pmcd->m_nvertices, lon, lat)) {
3901 ret.m_x = pmcd->transform_WGS84_offset_x;
3902 ret.m_y = pmcd->transform_WGS84_offset_y;
3906 node = node->GetNext();
3914 InitReturn cm93chart::CreateHeaderDataFromCM93Cell(
void) {
3916 wxFileName fn(m_FullPath);
3917 wxString ext = fn.GetExt();
3920 switch ((ext.mb_str())[(
size_t)0]) {
3950 m_Chart_Scale =
scale;
3956 switch (m_Chart_Scale) {
3958 bproc = m_pManager->m_bfoundZ;
3961 bproc = m_pManager->m_bfoundA;
3964 bproc = m_pManager->m_bfoundB;
3967 bproc = m_pManager->m_bfoundC;
3970 bproc = m_pManager->m_bfoundD;
3973 bproc = m_pManager->m_bfoundE;
3976 bproc = m_pManager->m_bfoundF;
3979 bproc = m_pManager->m_bfoundG;
3983 if (bproc)
return INIT_FAIL_NOERROR;
3986 switch (m_Chart_Scale) {
3988 m_pManager->m_bfoundZ =
true;
3991 m_pManager->m_bfoundA =
true;
3994 m_pManager->m_bfoundB =
true;
3997 m_pManager->m_bfoundC =
true;
4000 m_pManager->m_bfoundD =
true;
4003 m_pManager->m_bfoundE =
true;
4006 m_pManager->m_bfoundF =
true;
4009 m_pManager->m_bfoundG =
true;
4015 m_FullExtent.ELON = 179.0;
4016 m_FullExtent.WLON = -179.0;
4017 m_FullExtent.NLAT = 80.0;
4018 m_FullExtent.SLAT = -80.0;
4019 m_bExtentSet =
true;
4023 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
4024 *m_pCOVRTablePoints = 4;
4025 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
4026 float *pf = (
float *)malloc(2 * 4 *
sizeof(
float));
4030 *pfe++ = m_FullExtent.NLAT;
4031 *pfe++ = m_FullExtent.WLON;
4033 *pfe++ = m_FullExtent.NLAT;
4034 *pfe++ = m_FullExtent.ELON;
4036 *pfe++ = m_FullExtent.SLAT;
4037 *pfe++ = m_FullExtent.ELON;
4039 *pfe++ = m_FullExtent.SLAT;
4040 *pfe++ = m_FullExtent.WLON;
4045 void cm93chart::ProcessMCOVRObjects(
int cell_index,
char subcell) {
4048 Object *pobject = m_CIB.pobject_block;
4051 while (iObj < m_CIB.m_nfeature_records) {
4052 if ((pobject != NULL)) {
4054 int iclass = pobject->otype;
4056 wxString sclass = m_pDict->GetClassName(iclass);
4058 if (sclass.IsSameAs(_T (
"_m_sor" ))) {
4060 m_pcovr_set->Find_MCD(cell_index, iObj, (
int)subcell);
4062 Extended_Geometry *xgeom = BuildGeom(pobject, NULL, iObj);
4066 double tmp_transform_x = 0.;
4067 double tmp_transform_y = 0.;
4070 for (
int jattr = 0; jattr < pobject->n_attributes; jattr++) {
4071 unsigned char *curr_attr = pab.GetNextAttr();
4072 unsigned char iattr = *curr_attr;
4073 wxString sattr = m_pDict->GetAttrName(iattr);
4074 char vtype = m_pDict->GetAttrType(iattr);
4075 unsigned char *aval = curr_attr + 1;
4078 float *pf = (
float *)aval;
4080 float __attribute__((aligned(16))) tf1;
4081 unsigned char *pucf = (
unsigned char *)pf;
4082 memcpy(&tf1, pucf, sizeof(
float));
4083 if (sattr.IsSameAs(_T ( "_wgsox" )))
4084 tmp_transform_x = tf1;
4085 else if (sattr.IsSameAs(_T ( "_wgsoy" )))
4086 tmp_transform_y = tf1;
4088 if (sattr.IsSameAs(_T (
"_wgsox" )))
4089 tmp_transform_x = *pf;
4090 else if (sattr.IsSameAs(_T (
"_wgsoy" )))
4091 tmp_transform_y = *pf;
4097 if (NULL != xgeom) {
4103 pmcd->m_cell_index = cell_index;
4104 pmcd->m_object_id = iObj;
4105 pmcd->m_subcell = (int)subcell;
4108 int npta = xgeom->contour_array[0];
4109 float_2Dpt *geoPt =
new float_2Dpt[npta + 2];
4110 float_2Dpt *ppt = geoPt;
4114 pmcd->m_covr_lon_max = -1000.;
4115 pmcd->m_covr_lon_min = 1000.;
4116 pmcd->m_covr_lat_max = -1000.;
4117 pmcd->m_covr_lat_min = 1000.;
4119 for (
int ip = 0; ip < npta; ip++) {
4121 p.x = (int)xgeom->vertex_array[ip + 1].m_x;
4122 p.y = (
int)xgeom->vertex_array[ip + 1].m_y;
4124 Transform(&p, 0., 0., &lat, &lon);
4128 pmcd->m_covr_lon_max = wxMax(pmcd->m_covr_lon_max, lon);
4129 pmcd->m_covr_lon_min = wxMin(pmcd->m_covr_lon_min, lon);
4130 pmcd->m_covr_lat_max = wxMax(pmcd->m_covr_lat_max, lat);
4131 pmcd->m_covr_lat_min = wxMin(pmcd->m_covr_lat_min, lat);
4135 pmcd->m_nvertices = npta;
4136 pmcd->pvertices = geoPt;
4138 pmcd->m_covr_bbox.Set(pmcd->m_covr_lat_min, pmcd->m_covr_lon_min,
4139 pmcd->m_covr_lat_max, pmcd->m_covr_lon_max);
4143 pmcd->transform_WGS84_offset_x = tmp_transform_x;
4144 pmcd->transform_WGS84_offset_y = tmp_transform_y;
4146 pmcd->m_centerlat_cos =
4147 cos(((pmcd->m_covr_lat_min + pmcd->m_covr_lat_max) / 2.) * PI /
4151 m_pcovr_set->Add_Update_MCD(pmcd);
4154 free(xgeom->pvector_index);
4170 bool cm93chart::UpdateCovrSet(
ViewPort *vpt) {
4172 std::vector<int> vpcells = GetVPCellArray(*vpt);
4177 for (
unsigned int i = 0; i < vpcells.size(); i++) {
4180 if (!m_pcovr_set->IsCovrLoaded(vpcells[i])) {
4181 if (loadcell_in_sequence(vpcells[i],
'0')) {
4182 ProcessMCOVRObjects(vpcells[i],
'0');
4185 m_pcovr_set->m_cell_hash[vpcells[i]] = 1;
4187 char loadcell_key =
'A';
4191 while (loadcell_in_sequence(vpcells[i], loadcell_key)) {
4194 ProcessMCOVRObjects(vpcells[i], loadcell_key);
4207 bool cm93chart::IsPointInLoadedM_COVR(
double xc,
double yc) {
4210 return m_region.Contains(yc, xc);
4212 for (
unsigned int im = 0; im < m_pcovr_array_loaded.GetCount(); im++) {
4213 if (G_PtInPolygon_FL(m_pcovr_array_loaded[im]->pvertices,
4214 m_pcovr_array_loaded[im]->m_nvertices, xc, yc))
4221 LLRegion cm93chart::GetValidRegion() {
return m_region; }
4223 int cm93chart::loadcell_in_sequence(
int cellindex,
char subcell) {
4224 int rv = loadsubcell(cellindex, subcell);
4229 int cm93chart::loadsubcell(
int cellindex, wxChar sub_char) {
4232 int ilat = cellindex / 10000;
4233 int ilon = cellindex % 10000;
4236 double dlat = m_dval / 3.;
4237 double dlon = m_dval / 3.;
4239 Get_CM93_Cell_Origin(cellindex, GetNativeScale(), &lat, &lon);
4241 "\n Attempting loadcell %d scale %lc, sub_char %lc at lat: %g/%g "
4243 cellindex, wxChar(m_scalechar[0]), sub_char, lat, lat + dlat, lon,
4247 int jlat = (int)(((ilat - 30) / m_dval) * m_dval) + 30;
4248 int jlon = (int)((ilon / m_dval) * m_dval);
4250 int ilatroot = (((ilat - 30) / 60) * 60) + 30;
4251 int ilonroot = (ilon / 60) * 60;
4254 file.Printf(_T (
"%04d%04d." ), jlat, jlon);
4255 file += m_scalechar;
4264 bool b_useNoFind =
true;
4265 if (m_noFindArray.GetCount() > 500) b_useNoFind =
false;
4268 fileroot.Printf(_T (
"%04d%04d" ), ilatroot, ilonroot);
4269 appendOSDirSep(&fileroot);
4270 fileroot.append(m_scalechar);
4271 appendOSDirSep(&fileroot);
4272 wxString key = fileroot;
4274 fileroot.Prepend(m_prefix);
4276 file.Prepend(fileroot);
4280 strncpy(sfile, file.mb_str(), 199);
4282 printf(
" filename: %s\n", sfile);
4285 bool bfound =
false;
4288 if (m_noFindArray.Index(key) == wxNOT_FOUND) {
4289 if (::wxFileExists(file))
4292 m_noFindArray.Add(key);
4295 if (::wxFileExists(file)) bfound =
true;
4301 if (m_noFindArray.Index(key + _T(
".xz")) == wxNOT_FOUND) {
4302 if (::wxFileExists(file + _T(
".xz"))) {
4303 compfile = file + _T(
".xz");
4306 m_noFindArray.Add(key + _T(
".xz"));
4309 if (::wxFileExists(file + _T(
".xz"))) compfile = file + _T(
".xz");
4314 if (!bfound && !compfile.Length()) {
4316 wxString new_scalechar = m_scalechar.Lower();
4319 file1.Printf(_T (
"%04d%04d." ), jlat, jlon);
4320 file1 += new_scalechar;
4321 file1[0] = sub_char;
4323 fileroot.Printf(_T (
"%04d%04d" ), ilatroot, ilonroot);
4324 appendOSDirSep(&fileroot);
4325 fileroot.append(new_scalechar);
4326 appendOSDirSep(&fileroot);
4330 fileroot.Prepend(m_prefix);
4332 file1.Prepend(fileroot);
4335 if (m_noFindArray.Index(key) == wxNOT_FOUND) {
4336 if (::wxFileExists(file1)) {
4340 m_noFindArray.Add(key);
4344 if (::wxFileExists(file1)) {
4352 if (m_noFindArray.Index(key + _T(
".xz")) == wxNOT_FOUND) {
4353 if (::wxFileExists(file1 + _T(
".xz")))
4354 compfile = file1 + _T(
".xz");
4356 m_noFindArray.Add(key + _T(
".xz"));
4359 if (::wxFileExists(file1 + _T(
".xz"))) compfile = file1 + _T(
".xz");
4365 printf(
"noFind count: %d\n", (
int)m_noFindArray.GetCount());
4368 if (!bfound && !compfile.Length())
return 0;
4372 wxString msg(_T (
"Loading CM93 cell " ));
4378 m_LastFileName = file;
4381 if (compfile.Length()) {
4382 file = wxFileName::CreateTempFileName(wxFileName(compfile).GetFullName());
4383 if (!DecompressXZFile(compfile, file)) {
4391 strncpy(str, msg.mb_str(), 255);
4393 printf(
" %s\n", str);
4397 if (!Ingest_CM93_Cell((
const char *)file.mb_str(), &m_CIB)) {
4398 wxString msg(_T (
" cm93chart Error ingesting " ));
4402 if (compfile.Length()) wxRemoveFile(file);
4406 if (compfile.Length()) wxRemoveFile(file);
4411 void cm93chart::SetUserOffsets(
int cell_index,
int object_id,
int subcell,
4412 int xoff,
int yoff) {
4413 M_COVR_Desc *pmcd = GetCoverSet()->Find_MCD(cell_index, object_id, subcell);
4415 pmcd->user_xoff = xoff;
4416 pmcd->user_yoff = yoff;
4417 pmcd->m_buser_offsets =
true;
4421 wxPoint *cm93chart::GetDrawBuffer(
int nSize) {
4423 if (nSize > m_nDrawBufferSize) {
4424 wxPoint *tmp = m_pDrawBuffer;
4426 (wxPoint *)realloc(m_pDrawBuffer,
sizeof(wxPoint) * (nSize + 1));
4427 if (NULL == m_pDrawBuffer) {
4431 m_nDrawBufferSize = nSize + 1;
4433 return m_pDrawBuffer;
4440 cm93manager::cm93manager(
void) {
4453 cm93manager::~cm93manager(
void) {
delete m_pcm93Dict; }
4455 bool cm93manager::Loadcm93Dictionary(
const wxString &name) {
4458 m_pcm93Dict = FindAndLoadDict(name);
4461 wxLogMessage(_T (
" Cannot load CM93 Dictionary." ));
4465 if (!m_pcm93Dict->IsOk()) {
4466 wxLogMessage(_T (
" Error in loading CM93 Dictionary." ));
4472 }
else if (!m_pcm93Dict->IsOk()) {
4473 wxLogMessage(_T (
" CM93 Dictionary is not OK." ));
4487 wxFileName fn(file);
4488 wxString path = fn.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
4492 while (i < path.Len()) {
4493 target.Append(path[i]);
4494 if (path[i] == fn.GetPathSeparator()) {
4495 if (pdict->LoadDictionary(target)) {
4499 if (pdict->LoadDictionary(target + _T (
"CM93ATTR" ))) {
4508 strncpy(t, target.mb_str(), 99);
4510 if (retval == NULL)
delete pdict;
4518 cm93compchart::cm93compchart() {
4519 m_ChartType = CHART_TYPE_CM93COMP;
4520 m_pDictComposite = NULL;
4523 m_FullPath = _T (
"CM93" );
4526 m_Description = _T (
"CM93Composite" );
4529 m_datum_str = _T (
"WGS84" );
4530 m_SoundingsDatum = _T (
"Unknown" );
4532 for (
int i = 0; i < 8; i++) m_pcm93chart_array[i] = NULL;
4534 m_pcm93chart_current = NULL;
4541 SetSpecialOutlineCellIndex(0, 0, 0);
4542 m_last_cell_adjustvp = NULL;
4547 cm93compchart::~cm93compchart() {
4548 if (g_pCM93OffsetDialog) {
4549 g_pCM93OffsetDialog->Hide();
4552 for (
int i = 0; i < 8; i++)
delete m_pcm93chart_array[i];
4554 delete m_pDictComposite;
4559 InitReturn cm93compchart::Init(
const wxString &name, ChartInitFlag flags) {
4562 wxFileName fn(name);
4568 if (!fn.FileExists()) {
4570 if (wxDir::Exists(name)) {
4572 appendOSDirSep(&target);
4574 appendOSDirSep(&path);
4576 wxString msg(_T (
" CM93Composite Chart Init cannot find " ));
4579 return INIT_FAIL_REMOVE;
4584 path = fn.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
4588 wxFileName file_path(path);
4589 file_path.RemoveLastDir();
4590 file_path.RemoveLastDir();
4592 target = file_path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
4595 m_prefixComposite = target;
4597 wxString msg(_T (
"CM93Composite Chart Root is " ));
4598 msg.Append(m_prefixComposite);
4601 if (flags == THUMB_ONLY) {
4607 if (flags == HEADER_ONLY)
return CreateHeaderData();
4610 if (!m_pDictComposite) {
4611 if (!m_pDictComposite)
4612 m_pDictComposite = FindAndLoadDictFromDir(path);
4614 if (!m_pDictComposite) {
4616 _T (
" CM93Composite Chart Init cannot locate CM93 dictionary." ));
4617 return INIT_FAIL_REMOVE;
4622 SetColorScheme(m_global_color_scheme,
false);
4624 bReadyToRender =
true;
4629 void cm93compchart::Activate(
void) {
4656 void cm93compchart::Deactivate(
void) {
4657 if (pPopupDetailSlider) {
4658 pPopupDetailSlider->Destroy();
4659 pPopupDetailSlider = NULL;
4663 double scale_breaks[] = {
4678 int cm93compchart::GetCMScaleFromVP(
const ViewPort &vpt) {
4679 double scale_mpp = 3000 / vpt.view_scale_ppm;
4681 double scale_mpp_adj = scale_mpp;
4683 double scale_breaks_adj[7];
4685 for (
int i = 0; i < 7; i++) scale_breaks_adj[i] = scale_breaks[i];
4687 if (g_cm93_zoom_factor) {
4690 double efactor = ( double ) ( g_cm93_zoom_factor ) * ( .176 / 7. );
4691 for (
int i=0 ; i < 7 ; i++ )
4693 double efr = efactor * ( 7 - i );
4694 scale_breaks_adj[i] = scale_breaks[i] * pow ( 10., efr );
4696 printf (
"g_cm93_zoom_factor: %2d efactor: %6g efr:%6g, scale_breaks[i]:%6g scale_breaks_adj[i]: %6g\n",
4697 g_cm93_zoom_factor, efactor, efr, scale_breaks[i], scale_breaks_adj[i] );
4701 double efr = (double)g_cm93_zoom_factor * pow(scale_mpp, -.05);
4702 scale_mpp_adj *= pow(.6, efr);
4706 int cmscale_calc = 7;
4708 while (cmscale_calc > 0) {
4709 if (scale_mpp_adj < scale_breaks_adj[brk_index])
break;
4716 double zoom_factor = scale_breaks[7 - cmscale_calc] / vpt.chart_scale;
4717 if (zoom_factor > 4.0) {
4718 if (cmscale_calc < 7) cmscale_calc++;
4721 return cmscale_calc;
4724 void cm93compchart::SetVPParms(
const ViewPort &vpt) {
4727 int cmscale = GetCMScaleFromVP(vpt);
4728 m_cmscale = PrepareChartScale(vpt, cmscale,
false);
4732 if (m_pcm93chart_array[cmscale]) {
4733 if (!m_EdDate.IsValid() || !m_pcm93chart_array[cmscale]->GetEditionDate().IsValid() || m_pcm93chart_array[cmscale]->GetEditionDate().IsLaterThan(m_EdDate))
4734 m_EdDate = m_pcm93chart_array[cmscale]->GetEditionDate();
4738 int cm93compchart::PrepareChartScale(
const ViewPort &vpt,
int cmscale,
4741 printf(
"\non SetVPParms, cmscale:%d, %c\n", cmscale,
4742 (
char)(
'A' + cmscale - 1));
4745 bool cellscale_is_useable =
false;
4746 bool b_nochart =
false;
4748 while (!cellscale_is_useable) {
4750 while (NULL == m_pcm93chart_array[cmscale]) {
4751 if (Is_CM93Cell_Present(m_prefixComposite, vpt.clat, vpt.clon, cmscale)) {
4753 printf(
" chart %c at VP clat/clon is present\n",
4754 (
char)(
'A' + cmscale - 1));
4756 m_pcm93chart_array[cmscale] =
new cm93chart();
4758 ext = (wxChar)(
'A' + cmscale - 1);
4759 if (cmscale == 0) ext =
'Z';
4761 wxString file_dummy = _T (
"CM93." );
4764 m_pcm93chart_array[cmscale]->SetCM93Dict(m_pDictComposite);
4765 m_pcm93chart_array[cmscale]->SetCM93Prefix(m_prefixComposite);
4766 m_pcm93chart_array[cmscale]->SetCM93Manager(m_pcm93mgr);
4768 m_pcm93chart_array[cmscale]->SetColorScheme(m_global_color_scheme);
4769 m_pcm93chart_array[cmscale]->Init(file_dummy, FULL_INIT);
4770 }
else if (cmscale == 0) {
4777 " CM93 finds no chart of any scale present at Lat/Lon %g %g\n",
4778 vpt.clat, vpt.clon);
4787 printf(
" no %c scale chart present, adjusting cmscale to %c\n",
4788 (
char)(
'A' + cmscale), (
char)(
'A' + cmscale - 1));
4792 m_pcm93chart_current = m_pcm93chart_array[cmscale];
4795 if (g_bDebugCM93) printf(
" b_nochart return\n");
4797 m_pcm93chart_current = NULL;
4798 for (
int i = 0; i < 8; i++) {
4799 delete m_pcm93chart_array[i];
4800 m_pcm93chart_array[i] = NULL;
4806 if (m_pcm93chart_current) {
4809 m_pcm93chart_current->SetVPParms(vpt);
4813 float yc = vpt.clat;
4814 float xc = vpt.clon;
4816 if (!m_pcm93chart_current->GetCoverSet()->GetCoverCount()) {
4818 printf(
" chart %c has no M_COVR\n", (
char)(
'A' + cmscale - 1));
4821 if (m_pcm93chart_current->IsPointInLoadedM_COVR(xc, yc)) {
4823 printf(
" chart %c contains clat/clon\n", (
char)(
'A' + cmscale - 1));
4825 cellscale_is_useable =
true;
4839 else if (vpt.b_quilt && vpt.b_FullScreenQuilt) {
4842 covr_set *pcover = m_pcm93chart_current->GetCoverSet();
4844 bool boverlap =
false;
4845 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
4848 if (!(vp.GetBBox().IntersectOut(mcd->m_covr_bbox))) {
4853 if (boverlap) cellscale_is_useable =
true;
4857 if (!cellscale_is_useable) {
4865 printf(
" VP is not in M_COVR, adjusting cmscale to %c\n",
4866 (
char)(
'A' + cmscale - 1));
4873 double zoom_factor = scale_breaks[7 - cmscale] / vpt.chart_scale;
4875 if (zoom_factor > 4.0) {
4878 float yc = vpt.clat;
4879 float xc = vpt.clon;
4882 FillScaleArray(vpt.clat, vpt.clon);
4883 int new_scale = cmscale;
4884 bool b_found =
false;
4885 while (new_scale <= 7) {
4886 if (m_bScale_Array[new_scale]) {
4887 double new_zoom_factor =
4888 scale_breaks[7 - new_scale] / vpt.chart_scale;
4891 if (new_zoom_factor < 1.0) {
4893 new_scale = cmscale;
4897 if (new_zoom_factor < 4.0) {
4898 if (NULL == m_pcm93chart_array[new_scale]) {
4899 m_pcm93chart_array[new_scale] =
new cm93chart();
4901 ext = (wxChar)(
'A' + new_scale - 1);
4902 if (new_scale == 0) ext =
'Z';
4904 wxString file_dummy = _T (
"CM93." );
4907 m_pcm93chart_array[new_scale]->SetCM93Dict(m_pDictComposite);
4908 m_pcm93chart_array[new_scale]->SetCM93Prefix(m_prefixComposite);
4909 m_pcm93chart_array[new_scale]->SetCM93Manager(m_pcm93mgr);
4911 m_pcm93chart_array[new_scale]->SetColorScheme(
4912 m_global_color_scheme);
4913 m_pcm93chart_array[new_scale]->Init(file_dummy, FULL_INIT);
4916 m_pcm93chart_array[new_scale]->SetVPParms(vpt);
4917 if (m_pcm93chart_array[new_scale]->IsPointInLoadedM_COVR(xc, yc)) {
4926 cmscale = new_scale;
4927 m_pcm93chart_current = m_pcm93chart_array[cmscale];
4937 void cm93compchart::FillScaleArray(
double lat,
double lon) {
4938 for (
int cmscale = 0; cmscale < 8; cmscale++)
4939 m_bScale_Array[cmscale] =
4940 Is_CM93Cell_Present(m_prefixComposite, lat, lon, cmscale);
4946 wxString cm93compchart::GetPubDate() {
4949 if (NULL != m_pcm93chart_current)
4951 data.Printf(_T (
"%4d" ), m_current_cell_pub_date);
4953 data = _T (
"????" );
4957 int cm93compchart::GetNativeScale() {
4958 if (m_pcm93chart_current)
4959 return m_pcm93chart_current->GetNativeScale();
4964 double cm93compchart::GetNormalScaleMin(
double canvas_scale_factor,
4965 bool b_allow_overzoom) {
4969 if (m_pcm93chart_current) {
4971 if (m_pcm93chart_current->m_last_vp.IsValid()) {
4972 FillScaleArray(m_pcm93chart_current->m_last_vp.clat,
4973 m_pcm93chart_current->m_last_vp.clon);
4977 while (cmscale > 0) {
4978 if (m_bScale_Array[cmscale])
break;
4986 return 20000000. / oz_factor;
4988 return 3000000. / oz_factor;
4990 return 1000000. / oz_factor;
4992 return 200000. / oz_factor;
4994 return 100000. / oz_factor;
4996 return 50000. / oz_factor;
4998 return 20000. / oz_factor;
5002 return 500. / oz_factor;
5008 double cm93compchart::GetNormalScaleMax(
double canvas_scale_factor,
5010 return (180. / 360.) * PI * 2 *
5011 (WGS84_semimajor_axis_meters / (canvas_width / canvas_scale_factor));
5015 wxPoint GetPixFromLLVP(
double lat,
double lon,
const ViewPort &VPoint) {
5017 double easting, northing;
5019 double s, y3, s0, y30;
5020 double z = WGS84_semimajor_axis_meters * mercator_k0;
5025 if (lon * VPoint.clon < 0.) {
5033 if (fabs(xlon - VPoint.clon) > 180.) {
5034 if (xlon > VPoint.clon)
5039 easting = (xlon - VPoint.clon) * DEGREE * z;
5041 s = sin(lat * DEGREE);
5042 y3 = (.5 * log((1 + s) / (1 - s))) * z;
5044 s0 = sin(VPoint.clat * DEGREE);
5045 y30 = (.5 * log((1 + s0) / (1 - s0))) * z;
5046 northing = y3 - y30;
5050 double epix = easting * VPoint.view_scale_ppm;
5051 double npix = northing * VPoint.view_scale_ppm;
5052 r.x = (int)round((VPoint.pix_width / 2) + epix);
5053 r.y = (int)round((VPoint.pix_height / 2) - npix);
5060 void cm93compchart::GetValidCanvasRegion(
const ViewPort &VPoint,
5062 OCPNRegion screen_region(0, 0, VPoint.pix_width, VPoint.pix_height);
5064 VPoint, g_bopengl ? VPoint.rv_rect : screen_region);
5065 *pValidRegion = ret;
5068 OCPNRegion cm93compchart::GetValidScreenCanvasRegion(
5076 if (m_pcm93chart_current) {
5077 int chart_native_scale = m_pcm93chart_current->GetNativeScale();
5079 for (
unsigned int im = 0;
5080 im < m_pcm93chart_current->m_pcovr_array_loaded.GetCount(); im++) {
5081 M_COVR_Desc *pmcd = (m_pcm93chart_current->m_pcovr_array_loaded[im]);
5086 if (vp.GetBBox().IntersectOut(pmcd->m_covr_bbox))
continue;
5088 wxPoint *DrawBuf = m_pcm93chart_current->GetDrawBuffer(pmcd->m_nvertices);
5090 OCPNRegion rgn_covr = vp.GetVPRegionIntersect(
5091 ScreenRegion, pmcd->m_nvertices, (
float *)pmcd->pvertices,
5092 chart_native_scale, DrawBuf);
5094 if (rgn_covr.IsOk())
5095 ret_region.Union(rgn_covr);
5104 LLRegion cm93compchart::GetValidRegion() {
5105 if (m_pcm93chart_current)
return m_pcm93chart_current->GetValidRegion();
5110 bool cm93compchart::RenderRegionViewOnGL(
const wxGLContext &glc,
5113 const LLRegion &Region) {
5116 if (g_pCM93OffsetDialog && g_pCM93OffsetDialog->IsShown())
5117 g_pCM93OffsetDialog->UpdateMCOVRList(VPoint);
5119 return DoRenderRegionViewOnGL(glc, VPoint, RectRegion, Region);
5122 bool cm93compchart::DoRenderRegionViewOnGL(
const wxGLContext &glc,
5125 const LLRegion &Region) {
5132 bool render_return =
false;
5133 if (m_pcm93chart_current == 0)
return render_return;
5141 if (VPoint.b_quilt) {
5142 LLRegion vpr_empty = Region;
5143 LLRegion chart_region = GetValidRegion();
5162 if (!chart_region.Empty()) vpr_empty.Subtract(chart_region);
5164 if (!vpr_empty.Empty() &&
5168 int cmscale_save = m_cmscale;
5170 LLRegion region_vect[8];
5174 while (!vpr_empty.Empty() && m_cmscale) {
5176 m_cmscale = PrepareChartScale(vp, m_cmscale - 1,
false);
5178 if (m_pcm93chart_current) {
5179 LLRegion sscale_region = GetValidRegion();
5182 region_vect[m_cmscale] = sscale_region;
5183 region_vect[m_cmscale].Intersect(vpr_empty);
5186 vpr_empty.Subtract(sscale_region);
5193 for (
int i = 0; i < 8; i++) {
5194 if (!region_vect[i].Empty()) {
5195 m_cmscale = PrepareChartScale(vp, i,
false);
5196 if (m_pcm93chart_current)
5197 render_return |= m_pcm93chart_current->RenderRegionViewOnGL(
5198 glc, vp, RectRegion, region_vect[i]);
5203 m_cmscale = cmscale_save;
5204 m_pcm93chart_current = m_pcm93chart_array[m_cmscale];
5208 if (m_pcm93chart_current) {
5209 render_return |= m_pcm93chart_current->RenderRegionViewOnGL(
5210 glc, vp, RectRegion, Region);
5211 m_Name = m_pcm93chart_current->GetName();
5216 if (m_pcm93chart_current) {
5217 render_return = m_pcm93chart_current->RenderRegionViewOnGL(
5218 glc, vp, RectRegion, Region);
5219 m_Name = m_pcm93chart_current->GetLastFileName();
5224 if (VPoint.m_projection_type != PROJECTION_MERCATOR)
5225 return render_return;
5227 if (!m_pcm93chart_current)
return render_return;
5230 if (m_cell_index_special_outline) {
5234 covr_set *pcover = m_pcm93chart_current->GetCoverSet();
5236 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
5238 if ((pmcd->m_cell_index == m_cell_index_special_outline) &&
5239 (pmcd->m_object_id == m_object_id_special_outline) &&
5240 (pmcd->m_subcell == m_subcell_special_outline))
5250 float_2Dpt *p = pmcd->pvertices;
5251 wxPoint *pwp = m_pcm93chart_current->GetDrawBuffer(pmcd->m_nvertices);
5253 for (
int ip = 0; ip < pmcd->m_nvertices; ip++) {
5255 if (fabs(plon - VPoint.clon) > 180.) {
5256 if (plon > VPoint.clon)
5262 double easting, northing, epix, npix;
5263 toSM(p->y, plon + 360., VPoint.clat, VPoint.clon + 360, &easting,
5269 easting -= pmcd->user_xoff;
5272 northing -= pmcd->user_yoff;
5274 epix = easting * VPoint.view_scale_ppm;
5275 npix = northing * VPoint.view_scale_ppm;
5277 pwp[ip].x = (int)round((VPoint.pix_width / 2) + epix);
5278 pwp[ip].y = (int)round((VPoint.pix_height / 2) - npix);
5285 wxPen pen(wxTheColourDatabase->Find(_T (
"YELLOW" )), 3);
5289 pen.SetStyle(wxPENSTYLE_USER_DASH);
5290 pen.SetDashes(2, dash1);
5294 for (
int iseg = 0; iseg < pmcd->m_nvertices - 1; iseg++) {
5295 int x0 = pwp[iseg].x;
5296 int y0 = pwp[iseg].y;
5297 int x1 = pwp[iseg + 1].x;
5298 int y1 = pwp[iseg + 1].y;
5300 ClipResult res = cohen_sutherland_line_clip_i(
5301 &x0, &y0, &x1, &y1, 0, VPoint.pix_width, 0,
5308 dc.DrawLine(x0, y0, x1, y1);
5316 return render_return;
5319 bool cm93compchart::RenderRegionViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint,
5323 if (g_pCM93OffsetDialog && g_pCM93OffsetDialog->IsShown())
5324 g_pCM93OffsetDialog->UpdateMCOVRList(VPoint);
5326 return DoRenderRegionViewOnDC(dc, VPoint, Region);
5329 bool cm93compchart::RenderViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint) {
5330 const OCPNRegion vpr(0, 0, VPoint.pix_width, VPoint.pix_height);
5334 return DoRenderRegionViewOnDC(dc, VPoint, vpr);
5337 bool cm93compchart::DoRenderRegionViewOnDC(wxMemoryDC &dc,
5344 printf(
"\nOn DoRenderRegionViewOnDC Ref scale is %d, %c\n", m_cmscale,
5345 (
char)(
'A' + m_cmscale - 1));
5347 while (upd.HaveRects()) {
5348 wxRect rect = upd.GetRect();
5349 printf(
" Region Rect: %d %d %d %d\n", rect.x, rect.y, rect.width,
5358 bool render_return =
false;
5359 if (m_pcm93chart_current) {
5360 m_pcm93chart_current->SetVPParms(vp);
5364 if (VPoint.b_quilt) {
5367 OCPNRegion chart_region = GetValidScreenCanvasRegion(vp, Region);
5371 "On DoRenderRegionViewOnDC : Intersecting Ref region rectangles\n");
5373 while (upd.HaveRects()) {
5374 wxRect rect = upd.GetRect();
5375 printf(
" Region Rect: %d %d %d %d\n", rect.x, rect.y, rect.width,
5381 if (!chart_region.IsEmpty()) vpr_empty.Subtract(chart_region);
5383 if (!vpr_empty.Empty() &&
5387 #ifdef ocpnUSE_DIBSECTION
5392 if (!chart_region.IsEmpty())
5393 render_return = m_pcm93chart_current->RenderRegionViewOnDC(
5394 temp_dc, vp, chart_region);
5396 render_return =
false;
5399 cm93chart *m_pcm93chart_save = m_pcm93chart_current;
5405 if ((m_pDummyBM->GetWidth() != VPoint.rv_rect.width) ||
5406 (m_pDummyBM->GetHeight() != VPoint.rv_rect.height)) {
5411 if (NULL == m_pDummyBM)
5413 new wxBitmap(VPoint.rv_rect.width, VPoint.rv_rect.height, -1);
5416 #ifdef ocpnUSE_DIBSECTION
5421 dumm_dc.SelectObject(*m_pDummyBM);
5422 dumm_dc.SetBackground(*wxBLACK_BRUSH);
5425 int cmscale_next = m_cmscale;
5429 while (!vpr_empty.Empty() && cmscale_next) {
5432 m_cmscale = PrepareChartScale(vp, cmscale_next,
false);
5433 #ifdef ocpnUSE_DIBSECTION
5436 wxMemoryDC build_dc;
5439 if (m_pcm93chart_current) {
5441 printf(
" In DRRVOD, add quilt patch at %d, %c\n", m_cmscale,
5442 (
char)(
'A' + m_cmscale - 1));
5444 m_pcm93chart_current->RenderRegionViewOnDC(build_dc, vp, Region);
5446 OCPNRegion sscale_region = GetValidScreenCanvasRegion(vp, Region);
5449 sscale_region.Intersect(vpr_empty);
5453 while (upd.HaveRects()) {
5454 wxRect rect = upd.GetRect();
5455 dumm_dc.Blit(rect.x, rect.y, rect.width, rect.height, &build_dc,
5459 build_dc.SelectObject(wxNullBitmap);
5462 if (!sscale_region.IsEmpty()) vpr_empty.Subtract(sscale_region);
5470 while (updt.HaveRects()) {
5471 wxRect rect = updt.GetRect();
5472 dumm_dc.Blit(rect.x, rect.y, rect.width, rect.height, &temp_dc,
5476 temp_dc.SelectObject(wxNullBitmap);
5479 m_pcm93chart_current = m_pcm93chart_save;
5483 dumm_dc.SelectObject(wxNullBitmap);
5486 dc.SelectObject(*m_pDummyBM);
5488 render_return =
true;
5490 m_pcm93chart_current->RenderRegionViewOnDC(dc, vp, Region);
5491 render_return =
true;
5493 m_Name = m_pcm93chart_current->GetName();
5498 m_pcm93chart_current->RenderRegionViewOnDC(dc, vp, Region);
5499 m_Name = m_pcm93chart_current->GetLastFileName();
5507 if ((m_pDummyBM->GetWidth() != VPoint.pix_width) ||
5508 (m_pDummyBM->GetHeight() != VPoint.pix_height)) {
5514 if (NULL == m_pDummyBM)
5515 m_pDummyBM =
new wxBitmap(VPoint.pix_width, VPoint.pix_height, -1);
5519 mdc.SelectObject(*m_pDummyBM);
5520 mdc.SetBackground(*wxBLACK_BRUSH);
5522 mdc.SelectObject(wxNullBitmap);
5524 dc.SelectObject(*m_pDummyBM);
5530 if (m_cell_index_special_outline && m_pcm93chart_current) {
5531 covr_set *pcover = m_pcm93chart_current->GetCoverSet();
5533 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
5535 if ((pmcd->m_cell_index == m_cell_index_special_outline) &&
5536 (pmcd->m_object_id == m_object_id_special_outline) &&
5537 (pmcd->m_subcell == m_subcell_special_outline))
5547 float_2Dpt *p = pmcd->pvertices;
5548 wxPoint *pwp = m_pcm93chart_current->GetDrawBuffer(pmcd->m_nvertices);
5550 for (
int ip = 0; ip < pmcd->m_nvertices; ip++) {
5552 if (fabs(plon - VPoint.clon) > 180.) {
5553 if (plon > VPoint.clon)
5559 double easting, northing, epix, npix;
5560 toSM(p->y, plon + 360., VPoint.clat, VPoint.clon + 360, &easting,
5566 easting -= pmcd->user_xoff;
5569 northing -= pmcd->user_yoff;
5571 epix = easting * VPoint.view_scale_ppm;
5572 npix = northing * VPoint.view_scale_ppm;
5574 pwp[ip].x = (int)round((VPoint.pix_width / 2) + epix);
5575 pwp[ip].y = (int)round((VPoint.pix_height / 2) - npix);
5598 dc.SetPen(wxPen(wxTheColourDatabase->Find(_T (
"YELLOW" )), 4,
5599 wxPENSTYLE_LONG_DASH));
5601 for (
int iseg = 0; iseg < pmcd->m_nvertices - 1; iseg++) {
5602 int x0 = pwp[iseg].x;
5603 int y0 = pwp[iseg].y;
5604 int x1 = pwp[iseg + 1].x;
5605 int y1 = pwp[iseg + 1].y;
5607 ClipResult res = cohen_sutherland_line_clip_i(
5608 &x0, &y0, &x1, &y1, 0, VPoint.pix_width, 0,
5615 dc.DrawLine(x0, y0, x1, y1);
5623 return render_return;
5626 void cm93compchart::UpdateRenderRegions(
const ViewPort &VPoint) {
5627 OCPNRegion full_screen_region(0, 0, VPoint.rv_rect.width,
5628 VPoint.rv_rect.height);
5634 if (m_pcm93chart_current) {
5635 m_pcm93chart_current->SetVPParms(vp);
5639 if (VPoint.b_quilt) {
5641 for (
int i = 0; i < 8; i++) {
5642 if (m_pcm93chart_array[i])
5643 m_pcm93chart_array[i]->m_render_region.Clear();
5649 GetValidScreenCanvasRegion(vp, full_screen_region);
5650 m_pcm93chart_current->m_render_region = chart_region;
5652 if (!chart_region.IsEmpty()) vpr_empty.Subtract(chart_region);
5654 if (!vpr_empty.Empty() &&
5658 cm93chart *m_pcm93chart_save = m_pcm93chart_current;
5660 int cmscale_next = m_cmscale;
5662 while (!vpr_empty.Empty() && cmscale_next) {
5665 m_cmscale = PrepareChartScale(vp, cmscale_next,
false);
5667 if (m_pcm93chart_current) {
5669 GetValidScreenCanvasRegion(vp, full_screen_region);
5670 sscale_region.Intersect(vpr_empty);
5671 m_pcm93chart_current->m_render_region = sscale_region;
5674 if (!sscale_region.IsEmpty()) vpr_empty.Subtract(sscale_region);
5680 m_pcm93chart_current = m_pcm93chart_save;
5686 void cm93compchart::SetSpecialCellIndexOffset(
int cell_index,
int object_id,
5687 int subcell,
int xoff,
int yoff) {
5688 m_special_offset_x = xoff;
5689 m_special_offset_y = yoff;
5691 if (m_pcm93chart_current)
5692 m_pcm93chart_current->SetUserOffsets(cell_index, object_id, subcell, xoff,
5696 bool cm93compchart::RenderNextSmallerCellOutlines(
ocpnDC &dc,
ViewPort &vp,
5698 if (m_cmscale >= 7)
return false;
5701 if (!glcc)
return false;
5708 int nss = m_cmscale + 1;
5717 bool bdrawn =
false;
5726 if(nss_max > m_cmscale+3)
5727 nss_max = m_cmscale+3;
5730 while (nss <= nss_max && (!bdrawn || (vp.chart_scale < 3e6))) {
5731 cm93chart *psc = m_pcm93chart_array[nss];
5734 m_pcm93chart_array[nss] =
new cm93chart();
5735 psc = m_pcm93chart_array[nss];
5737 wxChar ext = (wxChar)(
'A' + nss - 1);
5738 if (nss == 0) ext =
'Z';
5740 wxString file_dummy = _T (
"CM93." );
5743 psc->SetCM93Dict(m_pDictComposite);
5744 psc->SetCM93Prefix(m_prefixComposite);
5745 psc->SetCM93Manager(m_pcm93mgr);
5747 psc->SetColorScheme(m_global_color_scheme);
5748 psc->Init(file_dummy, FULL_INIT);
5754 psc->UpdateCovrSet(&vp);
5757 covr_set *pcover = psc->GetCoverSet();
5759 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
5762 if (vp.GetBBox().IntersectOut(mcd->m_covr_bbox))
continue;
5764 wxPoint *pwp = psc->GetDrawBuffer(mcd->m_nvertices);
5765 bdrawn = RenderCellOutlines(dc, vp, pwp, mcd);
5773 glDisable(GL_LINE_STIPPLE);
5774 glDisable(GL_LINE_SMOOTH);
5775 glDisable(GL_BLEND);
5783 float_2Dpt *p = mcd->pvertices;
5784 int np = mcd->m_nvertices;
5786 for (
int ip = 0; ip < np; ip++, p++) {
5787 pwp[ip] = vp.GetPixFromLL(p->y, p->x);
5790 pwp[ip].x -= mcd->user_xoff * vp.view_scale_ppm;
5791 pwp[ip].y -= mcd->user_yoff * vp.view_scale_ppm;
5796 wxPoint p0 = pwp[0];
5797 for (
int ip = 1; ip < np; ip++) {
5798 if (((p0.x > vp.pix_width) && (pwp[ip].x < 0)) ||
5799 ((p0.x < 0) && (pwp[ip].x > vp.pix_width)))
5805 dc.DrawLines(mcd->m_nvertices, pwp, 0, 0,
false);
5809 void cm93compchart::GetPointPix(ObjRazRules *rzRules,
float rlat,
float rlon,
5811 m_pcm93chart_current->GetPointPix(rzRules, rlat, rlon, r);
5814 void cm93compchart::GetPointPix(ObjRazRules *rzRules, wxPoint2DDouble *en,
5815 wxPoint *r,
int nPoints) {
5816 m_pcm93chart_current->GetPointPix(rzRules, en, r, nPoints);
5819 void cm93compchart::GetPixPoint(
int pixx,
int pixy,
double *plat,
double *plon,
5821 m_pcm93chart_current->GetPixPoint(pixx, pixy, plat, plon, vpt);
5824 void cm93compchart::UpdateLUPs(
s57chart *pOwner) {
5825 for (
int i = 0; i < 8; i++) {
5826 if (m_pcm93chart_array[i]) m_pcm93chart_array[i]->UpdateLUPs(pOwner);
5830 std::list<S57Obj*> *cm93compchart::GetAssociatedObjects(S57Obj *obj) {
5831 if (m_pcm93chart_current)
5832 return m_pcm93chart_current->GetAssociatedObjects(obj);
5837 void cm93compchart::InvalidateCache() {
5838 for (
int i = 0; i < 8; i++) {
5839 if (m_pcm93chart_array[i]) m_pcm93chart_array[i]->InvalidateCache();
5843 void cm93compchart::ForceEdgePriorityEvaluate(
void) {
5844 for (
int i = 0; i < 8; i++) {
5845 if (m_pcm93chart_array[i])
5846 m_pcm93chart_array[i]->ForceEdgePriorityEvaluate();
5850 void cm93compchart::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
5851 m_global_color_scheme = cs;
5853 for (
int i = 0; i < 8; i++) {
5854 if (m_pcm93chart_array[i])
5855 m_pcm93chart_array[i]->SetColorScheme(cs, bApplyImmediate);
5859 ListOfObjRazRules *cm93compchart::GetObjRuleListAtLatLon(
float lat,
float lon,
5860 float select_radius,
5862 int selection_mask) {
5868 if (!VPoint->b_quilt)
5869 if (m_pcm93chart_current)
5870 return m_pcm93chart_current->GetObjRuleListAtLatLon(lat, alon,
5871 select_radius, &vp);
5874 ListOfObjRazRules *ret_ptr =
new ListOfObjRazRules;
5878 UpdateRenderRegions(*VPoint);
5882 wxPoint p = VPoint->GetPixFromLL(lat, lon);
5884 for (
int i = 0; i < 8; i++) {
5885 if (m_pcm93chart_array[i]) {
5886 if (!m_pcm93chart_array[i]->m_render_region.IsEmpty()) {
5887 if (wxInRegion == m_pcm93chart_array[i]->m_render_region.Contains(p))
5888 return m_pcm93chart_array[i]->GetObjRuleListAtLatLon(
5889 lat, alon, select_radius, &vp, selection_mask);
5895 ListOfObjRazRules *ret_ptr =
new ListOfObjRazRules;
5901 std::unordered_map<unsigned, VE_Element *> &cm93compchart::Get_ve_hash(
void) {
5902 return m_pcm93chart_current->Get_ve_hash();
5905 std::unordered_map<unsigned, VC_Element *> &cm93compchart::Get_vc_hash(
void) {
5906 return m_pcm93chart_current->Get_vc_hash();
5917 m_last_cell_adjustvp = m_pcm93chart_current;
5925 if (m_pcm93chart_current)
return false;
5934 int cmscale = GetCMScaleFromVP(
5937 int cmscale_actual = PrepareChartScale(
5938 vp_proposed, cmscale,
5942 printf(
" In AdjustVP, adjustment subchart scale is %c\n",
5943 (
char)(
'A' + cmscale_actual - 1));
5949 bool single_adjust =
false;
5950 if (m_pcm93chart_array[cmscale_actual])
5952 m_pcm93chart_array[cmscale_actual]->AdjustVP(vp_last, vp_proposed);
5954 if (m_cmscale != cmscale_actual)
return false;
5958 if (vp_last.b_quilt)
return false;
5960 return single_adjust;
5963 ThumbData *cm93compchart::GetThumbData(
int tnx,
int tny,
float lat,
float lon) {
5967 InitReturn cm93compchart::CreateHeaderData() {
5968 m_Chart_Scale = 20000000;
5974 wxDir dirt(m_prefixComposite);
5976 wxRegEx test(_T(
"[0-9]+"));
5978 bool b_cont = dirt.GetFirst(&candidate);
5981 if (test.Matches(candidate) && (candidate.Len() == 8)) {
5982 wxString dir = m_prefixComposite;
5984 if (wxDir::Exists(dir)) {
5985 wxFileName name(dir);
5986 wxString num_name = name.GetName();
5988 if (num_name.ToLong(&number)) {
5989 int ilat = number / 10000;
5990 int ilon = number % 10000;
5992 int lat_base = (ilat - 270) / 3.;
5993 int lon_base = ilon / 3.;
5994 extent_rect.Union(wxRect(lon_base, lat_base, 20, 20));
5998 b_cont = dirt.GetNext(&candidate);
6002 m_FullExtent.ELON = ((double)extent_rect.x + (
double)extent_rect.width);
6003 m_FullExtent.WLON = ((double)extent_rect.x);
6004 m_FullExtent.NLAT = ((double)extent_rect.y + (
double)extent_rect.height);
6005 m_FullExtent.SLAT = ((double)extent_rect.y);
6006 m_bExtentSet =
true;
6010 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
6011 *m_pCOVRTablePoints = 4;
6012 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
6013 float *pf = (
float *)malloc(2 * 4 *
sizeof(
float));
6017 *pfe++ = m_FullExtent.NLAT;
6018 *pfe++ = m_FullExtent.WLON;
6020 *pfe++ = m_FullExtent.NLAT;
6021 *pfe++ = m_FullExtent.ELON;
6023 *pfe++ = m_FullExtent.SLAT;
6024 *pfe++ = m_FullExtent.ELON;
6026 *pfe++ = m_FullExtent.SLAT;
6027 *pfe++ = m_FullExtent.WLON;
6032 cm93_dictionary *cm93compchart::FindAndLoadDictFromDir(
const wxString &dir) {
6037 if (pdict->LoadDictionary(dir))
return pdict;
6042 wxString path = dir;
6046 while (i < path.Len()) {
6047 target.Append(path[i]);
6048 if (path[i] == wxFileName::GetPathSeparator()) {
6052 if (pdict->LoadDictionary(target)) {
6066 wxFileName fnc(dir);
6067 wxString found_dict_file_name;
6071 path = fnc.GetPath(wxPATH_GET_VOLUME);
6073 wxString msg = _T (
" Looking harder for CM93 dictionary in " );
6077 if ((path.Len() == 0) || path.IsSameAs(fnc.GetPathSeparator())) {
6079 wxLogMessage(_T (
"Early break1" ));
6085 if ((wxNOT_FOUND == path.Lower().Find(_T (
"cm93" )))) {
6087 wxLogMessage(_T (
"Early break2" ));
6095 if (dir.IsOpened()) {
6098 dir.Traverse(cm93Dictionary);
6099 bdone = found_dict_file_name.Len() != 0;
6105 if (found_dict_file_name.Len()) {
6106 wxFileName fnd(found_dict_file_name);
6108 fnd.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
6110 if (pdict->LoadDictionary(dpath)) retval = pdict;
6113 if (NULL == retval)
delete pdict;
6118 void cm93compchart::CloseandReopenCurrentSubchart(
void) {
6119 delete m_pcm93chart_current;
6120 m_pcm93chart_current = NULL;
6121 m_pcm93chart_array[m_cmscale] = NULL;
6145 const wxPoint &pos,
const wxSize &size,
long style);
6148 wxString OnGetItemText(
long item,
long column)
const;
6149 int OnGetItemColumnImage(
long item,
long column)
const;
6154 OCPNOffsetListCtrl::OCPNOffsetListCtrl(
CM93OffsetDialog *parent, wxWindowID
id,
6155 const wxPoint &pos,
const wxSize &size,
6157 : wxListCtrl(parent, id, pos, size, style) {
6161 OCPNOffsetListCtrl::~OCPNOffsetListCtrl() {}
6163 wxString OCPNOffsetListCtrl::OnGetItemText(
long item,
long column)
const {
6165 M_COVR_Desc *pmcd = m_parent->m_pcovr_array[item];
6169 ret.Printf(_T (
"%d" ), pmcd->m_cell_index);
6170 if (((
int)
'0') == pmcd->m_subcell)
6171 ret.Prepend(_T (
"0" ));
6173 char t = (char)pmcd->m_subcell;
6175 p.Printf(_T (
"%c" ), t);
6182 ret.Printf(_T (
"%d" ), pmcd->m_object_id);
6186 ret = m_parent->m_selected_chart_scale_char;
6190 ret.Printf(_T (
"%g" ), pmcd->transform_WGS84_offset_x);
6194 ret.Printf(_T (
"%g" ), pmcd->transform_WGS84_offset_y);
6198 ret.Printf(_T (
"%6.0f" ), pmcd->user_xoff * pmcd->m_centerlat_cos);
6202 ret.Printf(_T (
"%6.0f" ), pmcd->user_yoff * pmcd->m_centerlat_cos);
6211 int OCPNOffsetListCtrl::OnGetItemColumnImage(
long item,
long column)
const {
6222 EVT_CLOSE(CM93OffsetDialog::OnClose)
6227 m_pcompchart = NULL;
6232 m_selected_list_index = -1;
6233 m_selected_cell_index = 0;
6235 long wstyle = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER;
6236 wxDialog::Create(parent, -1, _(
"OpenCPN CM93 Cell Offset Adjustments"),
6237 wxPoint(0, 0), wxSize(800, 200), wstyle);
6239 wxFont *qFont = GetOCPNScaledFont(_(
"Dialog"));
6243 wxBoxSizer *topSizer =
new wxBoxSizer(wxHORIZONTAL);
6248 long flags = wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_HRULES | wxLC_VRULES |
6251 flags |= wxLC_VIRTUAL;
6257 m_pListCtrlMCOVRs->Connect(
6258 wxEVT_COMMAND_LIST_ITEM_SELECTED,
6259 wxListEventHandler(CM93OffsetDialog::OnCellSelected), NULL,
this);
6261 int dx = GetCharWidth();
6262 int dy = GetCharHeight();
6265 m_pListCtrlMCOVRs->InsertColumn(tlCELL, _(
"Cell"), wxLIST_FORMAT_LEFT, width);
6268 m_pListCtrlMCOVRs->InsertColumn(tlMCOVR, _(
"M_COVR ID"), wxLIST_FORMAT_CENTER,
6272 m_pListCtrlMCOVRs->InsertColumn(tlSCALE, _(
"Cell Scale"),
6273 wxLIST_FORMAT_CENTER, width);
6276 m_pListCtrlMCOVRs->InsertColumn(tlXOFF, _(
"wgsox"), wxLIST_FORMAT_CENTER,
6280 m_pListCtrlMCOVRs->InsertColumn(tlYOFF, _(
"wgsoy"), wxLIST_FORMAT_CENTER,
6284 m_pListCtrlMCOVRs->InsertColumn(tlUXOFF, _(
"User X Offset"),
6285 wxLIST_FORMAT_CENTER, width);
6288 m_pListCtrlMCOVRs->InsertColumn(tlUYOFF, _(
"User Y Offset"),
6289 wxLIST_FORMAT_CENTER, width);
6291 topSizer->Add(m_pListCtrlMCOVRs, 1, wxEXPAND | wxALL, 0);
6293 wxBoxSizer *boxSizer02 =
new wxBoxSizer(wxVERTICAL);
6294 boxSizer02->AddSpacer(22);
6296 wxStaticText *pStaticTextXoff =
new wxStaticText(
6298 wxString::Format(_T(
"%s (%s)" ), _(
"User X Offset"), _(
"meters")),
6299 wxDefaultPosition, wxDefaultSize, 0);
6300 boxSizer02->Add(pStaticTextXoff, 0, wxALL, 0);
6303 new wxSpinCtrl(
this, wxID_ANY, wxEmptyString, wxDefaultPosition,
6304 wxSize(50, -1), wxSP_ARROW_KEYS, -10000, 10000, 0);
6305 m_pSpinCtrlXoff->Connect(wxEVT_COMMAND_SPINCTRL_UPDATED,
6306 wxCommandEventHandler(CM93OffsetDialog::OnOffSetSet),
6308 boxSizer02->Add(m_pSpinCtrlXoff, 0, wxEXPAND | wxALL, 0);
6310 wxStaticText *pStaticTextYoff =
new wxStaticText(
6312 wxString::Format(_T(
"%s (%s)" ), _(
"User Y Offset"), _(
"meters")),
6313 wxDefaultPosition, wxDefaultSize, 0);
6314 boxSizer02->Add(pStaticTextYoff, 0, wxALL, 0);
6317 new wxSpinCtrl(
this, wxID_ANY, wxEmptyString, wxDefaultPosition,
6318 wxSize(50, -1), wxSP_ARROW_KEYS, -10000, 10000, 0);
6319 m_pSpinCtrlYoff->Connect(wxEVT_COMMAND_SPINCTRL_UPDATED,
6320 wxCommandEventHandler(CM93OffsetDialog::OnOffSetSet),
6322 boxSizer02->Add(m_pSpinCtrlYoff, 0, wxEXPAND | wxALL, 0);
6324 m_OKButton =
new wxButton(
this, wxID_ANY, _(
"OK"), wxDefaultPosition,
6326 m_OKButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
6327 wxCommandEventHandler(CM93OffsetDialog::OnOK), NULL,
6329 boxSizer02->Add(m_OKButton, 0, wxALL, 5);
6330 m_OKButton->SetDefault();
6332 topSizer->Add(boxSizer02, 0, wxEXPAND | wxALL, 2);
6334 wxSize sz(800, dy * 8);
6336 sz = wxGetDisplaySize();
6346 SetSize(GetSize().x, GetSize().y - 1);
6358 CM93OffsetDialog::~CM93OffsetDialog() { g_pCM93OffsetDialog = NULL; }
6360 void CM93OffsetDialog::OnClose(wxCloseEvent &event) {
6362 m_pcompchart->SetSpecialOutlineCellIndex(0, 0, 0);
6364 m_pcompchart->InvalidateCache();
6367 m_pparent->Refresh(
true);
6368 gFrame->InvalidateAllGL();
6372 if (m_pListCtrlMCOVRs->GetItemCount() > m_selected_list_index)
6373 m_pListCtrlMCOVRs->SetItemState(m_selected_list_index, 0,
6374 wxLIST_STATE_SELECTED);
6379 void CM93OffsetDialog::OnOK(wxCommandEvent &event) {
6386 void CM93OffsetDialog::SetCM93Chart(
cm93compchart *pchart) {
6387 m_pcompchart = pchart;
6390 void CM93OffsetDialog::OnOffSetSet(wxCommandEvent &event) {
6391 m_xoff = m_pSpinCtrlXoff->GetValue() / m_centerlat_cos;
6392 m_yoff = m_pSpinCtrlYoff->GetValue() / m_centerlat_cos;
6399 void CM93OffsetDialog::UpdateOffsets(
void) {
6400 if (m_pcompchart && m_selected_cell_index) {
6402 m_pcompchart->SetSpecialCellIndexOffset(m_selected_cell_index,
6403 m_selected_object_id,
6404 m_selected_subcell, m_xoff, m_yoff);
6408 AbstractPlatform::ShowBusySpinner();
6409 m_pcompchart->CloseandReopenCurrentSubchart();
6410 AbstractPlatform::HideBusySpinner();
6413 m_pparent->Refresh(
true);
6414 gFrame->InvalidateAllGL();
6419 void CM93OffsetDialog::SetColorScheme() { DimeControl(
this); }
6421 void CM93OffsetDialog::OnCellSelected(wxListEvent &event) {
6423 m_selected_list_index =
event.GetIndex();
6425 M_COVR_Desc *mcd = m_pcovr_array.Item(event.GetIndex());
6427 if (m_selected_list_index > m_pListCtrlMCOVRs->GetItemCount())
6430 cm93chart *pchart = m_pcompchart->GetCurrentSingleScaleChart();
6432 M_COVR_Desc *cached_mcd = pchart->GetCoverSet()->Find_MCD(
6433 mcd->m_cell_index, mcd->m_object_id, mcd->m_subcell);
6435 m_pSpinCtrlXoff->SetValue(
6436 wxRound(cached_mcd->user_xoff * cached_mcd->m_centerlat_cos));
6437 m_pSpinCtrlYoff->SetValue(
6438 wxRound(cached_mcd->user_yoff * cached_mcd->m_centerlat_cos));
6442 m_pcompchart->SetSpecialOutlineCellIndex(mcd->m_cell_index,
6443 mcd->m_object_id, mcd->m_subcell);
6445 m_selected_cell_index = mcd->m_cell_index;
6446 m_selected_object_id = mcd->m_object_id;
6447 m_selected_subcell = mcd->m_subcell;
6448 m_centerlat_cos = mcd->m_centerlat_cos;
6450 m_pcompchart->InvalidateCache();
6453 m_pparent->Refresh(
true);
6454 gFrame->InvalidateAllGL();
6459 void CM93OffsetDialog::UpdateMCOVRList(
const ViewPort &vpt) {
6463 cm93chart *pchart = m_pcompchart->GetCurrentSingleScaleChart();
6466 m_selected_chart_scale_char = pchart->GetScaleChar();
6468 m_pcovr_array.Clear();
6471 std::vector<int> cell_array = pchart->GetVPCellArray(vpt);
6479 covr_set *pcover = pchart->GetCoverSet();
6481 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
6484 for (
unsigned int icell = 0; icell < cell_array.size(); icell++) {
6485 if (cell_array[icell] == mcd->m_cell_index) {
6486 wxPoint *pwp = pchart->GetDrawBuffer(mcd->m_nvertices);
6491 if (rgn.Contains(0, 0, vpt.pix_width, vpt.pix_height) !=
6493 m_pcovr_array.Add(mcd);
6501 for (
unsigned int im = 0; im < m_pcovr_array.size(); im++) {
6503 if ((m_selected_cell_index == mcd->m_cell_index) &&
6504 (m_selected_object_id == mcd->m_object_id) &&
6505 (m_selected_subcell == mcd->m_subcell)) {
6511 if (!m_pListCtrlMCOVRs->IsVirtual()) {
6512 if (m_pListCtrlMCOVRs->GetItemCount())
6513 m_pListCtrlMCOVRs->DeleteAllItems();
6515 for (
unsigned int i = 0; i < m_pcovr_array.GetCount(); i++) {
6518 m_pListCtrlMCOVRs->InsertItem(item);
6519 for (
int j = 0; j < tlUYOFF + 1; j++) {
6521 item.SetText(m_pListCtrlMCOVRs->OnGetItemText(i, j));
6522 m_pListCtrlMCOVRs->SetItem(item);
6526 m_pListCtrlMCOVRs->SetItemCount(m_pcovr_array.GetCount());
6529 if (-1 != sel_index)
6530 m_pListCtrlMCOVRs->SetItemState(sel_index, wxLIST_STATE_SELECTED,
6531 wxLIST_STATE_SELECTED);
6533 m_pListCtrlMCOVRs->SetItemState(sel_index, 0,
6534 wxLIST_STATE_SELECTED);
6536 m_pListCtrlMCOVRs->Refresh(
true);
6539 m_pListCtrlMCOVRs->Refresh(
false);
General purpose GUI support.
Runtime representation of a plugin block.