33#include <wx/textfile.h>
34#include <wx/tokenzr.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"
53#include "ocpn_pixel.h"
55#include "pluginmanager.h"
56#include "OCPNPlatform.h"
57#include "wx28compat.h"
58#include "chartdata_input_stream.h"
59#include "DetailSlider.h"
62#include "ocpn_frame.h"
68#include "glChartCanvas.h"
73#define _CRTDBG_MAP_ALLOC
76#define DEBUG_NEW new (_NORMAL_BLOCK, __FILE__, __LINE__)
82extern s52plib *ps52plib;
83extern bool g_bDebugCM93;
84extern int g_cm93_zoom_factor;
86extern int g_detailslider_dialog_x, g_detailslider_dialog_y;
90extern float g_GLMinSymbolLineWidth;
92extern bool g_b_EnableVBO;
97#include <wx/arrimpl.cpp>
98WX_DEFINE_OBJARRAY(Array_Of_M_COVR_Desc);
100#include <wx/listimpl.cpp>
101WX_DEFINE_LIST(List_Of_M_COVR_Desc);
103void appendOSDirSep(wxString *pString) {
104 wxChar sep = wxFileName::GetPathSeparator();
105 if (pString->Last() != sep) pString->Append(sep);
112M_COVR_Desc::M_COVR_Desc() {
114 gl_screen_vertices = NULL;
115 gl_screen_projection_type = PROJECTION_UNKNOWN;
119 m_centerlat_cos = 1.0;
120 m_buser_offsets =
false;
123 gl_screen_vertices = NULL;
126M_COVR_Desc::~M_COVR_Desc() {
128 delete[] gl_screen_vertices;
131int M_COVR_Desc::GetWKBSize() {
139 size += m_nvertices *
sizeof(float_2Dpt);
142 size += 8 *
sizeof(double);
147bool M_COVR_Desc::WriteWKB(
void *p) {
150 *pr++ = GetWKBSize();
152 *pr++ = m_cell_index;
158 float_2Dpt *pfo = (float_2Dpt *)pr;
159 float_2Dpt *pfi = pvertices;
160 for (
int i = 0; i < m_nvertices; i++) *pfo++ = *pfi++;
162 int *pi = (
int *)pfo;
165 double *pd = (
double *)pi;
166 *pd++ = transform_WGS84_offset_x;
167 *pd++ = transform_WGS84_offset_y;
168 *pd++ = m_covr_lat_min;
169 *pd++ = m_covr_lat_max;
170 *pd++ = m_covr_lon_min;
171 *pd++ = m_covr_lon_max;
173 double centerlat_cos =
174 cos(((m_covr_lat_min + m_covr_lat_max) / 2.) * PI / 180.);
176 *pd++ = user_xoff * centerlat_cos;
177 *pd++ = user_yoff * centerlat_cos;
183int M_COVR_Desc::ReadWKB(wxFFileInputStream &ifs) {
186 if (!ifs.Read(&length,
sizeof(
int)).Eof()) {
187 ifs.Read(&m_cell_index,
sizeof(
int));
188 ifs.Read(&m_object_id,
sizeof(
int));
189 ifs.Read(&m_subcell,
sizeof(
int));
191 ifs.Read(&m_nvertices,
sizeof(
int));
193 pvertices =
new float_2Dpt[m_nvertices];
195 ifs.Read(pvertices, m_nvertices *
sizeof(float_2Dpt));
197 ifs.Read(&m_npub_year,
sizeof(
int));
199 ifs.Read(&transform_WGS84_offset_x,
sizeof(
double));
200 ifs.Read(&transform_WGS84_offset_y,
sizeof(
double));
201 ifs.Read(&m_covr_lat_min,
sizeof(
double));
202 ifs.Read(&m_covr_lat_max,
sizeof(
double));
203 ifs.Read(&m_covr_lon_min,
sizeof(
double));
204 ifs.Read(&m_covr_lon_max,
sizeof(
double));
206 m_centerlat_cos = cos(((m_covr_lat_min + m_covr_lat_max) / 2.) * PI / 180.);
208 ifs.Read(&user_xoff,
sizeof(
double));
209 ifs.Read(&user_yoff,
sizeof(
double));
211 user_xoff /= m_centerlat_cos;
212 user_yoff /= m_centerlat_cos;
214 if ((fabs(user_xoff) > 1.) || (fabs(user_yoff) > 1.))
215 m_buser_offsets =
true;
217 m_buser_offsets =
false;
219 m_covr_bbox.Set(m_covr_lat_min, m_covr_lon_min, m_covr_lat_max,
226 float_2Dpt *p = pvertices;
228 for (
int ip = 0; ip < m_nvertices; ip++) {
230 if (fabs(plon - vp.clon) > 180.) {
237 double easting, northing, epix, npix;
238 toSM(p->y, plon + 360., vp.clat, vp.clon + 360, &easting, &northing);
241 easting -= user_xoff;
243 northing -= user_yoff;
245 epix = easting * vp.view_scale_ppm;
246 npix = northing * vp.view_scale_ppm;
248 pwp[ip].x = (int)round((vp.pix_width / 2) + epix);
249 pwp[ip].y = (int)round((vp.pix_height / 2) - npix);
263char sig_version[] =
"COVR1002";
270 bool Init(wxChar scale_char, wxString &prefix);
271 unsigned int GetCoverCount() {
return m_covr_array_outlines.GetCount(); }
272 M_COVR_Desc *GetCover(
unsigned int im) {
return &m_covr_array_outlines[im]; }
275 bool IsCovrLoaded(
int cell_index);
277 M_COVR_Desc *Find_MCD(
int cell_index,
int object_id,
int sbcell);
283 wxString m_cachefile;
286 Array_Of_M_COVR_Desc m_covr_array_outlines;
290 std::unordered_map<int, int> m_cell_hash;
293covr_set::covr_set(
cm93chart *parent) { m_pParent = parent; }
295covr_set::~covr_set() {
297 if (m_cachefile.IsEmpty())
301 if (m_covr_array_outlines.GetCount()) {
302 wxFFileOutputStream ofs(m_cachefile);
304 ofs.Write(sig_version, 8);
306 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
307 int wkbsize = m_covr_array_outlines[i].GetWKBSize();
309 char *p = (
char *)malloc(wkbsize *
sizeof(
char));
310 m_covr_array_outlines[i].WriteWKB(p);
311 ofs.Write(p, wkbsize);
320bool covr_set::Init(wxChar scale_char, wxString &prefix) {
321 m_scale_char = scale_char;
323 switch (m_scale_char) {
354 wxString prefix_string = prefix;
355 wxString sep(wxFileName::GetPathSeparator());
356 prefix_string.Replace(sep, _T (
"_" ));
357 prefix_string.Replace(_T (
":" ), _T (
"_" ));
359 m_cachefile = g_Platform->GetPrivateDataDir();
360 appendOSDirSep(&m_cachefile);
362 m_cachefile += _T (
"cm93" );
363 appendOSDirSep(&m_cachefile);
367 m_cachefile += _T (
"_" );
369 wxString cache_old_old_name = m_cachefile;
370 cache_old_old_name += _T (
"coverset." );
371 cache_old_old_name += m_scale_char;
373 wxString cache_old_name = m_cachefile;
374 cache_old_name += _T (
"coverset_sig." );
375 cache_old_name += m_scale_char;
377 m_cachefile += _T (
"coverset_sigp." );
378 m_cachefile += m_scale_char;
380 wxFileName fn(m_cachefile);
381 if (!fn.DirExists()) wxFileName::Mkdir(fn.GetPath(), 0777, wxPATH_MKDIR_FULL);
384 if (!wxFileName::FileExists(m_cachefile)) {
387 if (wxFileName::FileExists(cache_old_name)) ::wxRemoveFile(cache_old_name);
388 if (wxFileName::FileExists(cache_old_old_name))
389 ::wxRemoveFile(cache_old_old_name);
393 wxFFileInputStream ifs(m_cachefile);
397 if (!ifs.Read(&sig_bytes, 8).Eof()) {
398 if (strncmp(sig_bytes, sig_version, 8)) {
407 int length = pmcd->ReadWKB(ifs);
410 m_covr_array_outlines.Add(pmcd);
412 if (m_cell_hash.find(pmcd->m_cell_index) == m_cell_hash.end())
413 m_cell_hash[pmcd->m_cell_index] = 0;
415 m_cell_hash[pmcd->m_cell_index]++;
428 m_covr_array_outlines.Add(pmcd);
430 if (m_cell_hash.find(pmcd->m_cell_index) ==
432 m_cell_hash[pmcd->m_cell_index] = 0;
434 m_cell_hash[pmcd->m_cell_index]++;
437bool covr_set::IsCovrLoaded(
int cell_index) {
438 return (m_cell_hash.find(cell_index) != m_cell_hash.end());
442 if (m_cell_hash.find(pmcd->m_cell_index) ==
445 m_covr_array_outlines.Add(pmcd);
446 m_cell_hash[pmcd->m_cell_index] = 1;
454 bool b_found =
false;
455 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
456 M_COVR_Desc *pmcd_candidate = &m_covr_array_outlines[i];
457 if ((pmcd_candidate->m_cell_index == pmcd->m_cell_index) &&
458 (pmcd_candidate->m_object_id == pmcd->m_object_id) &&
459 (pmcd_candidate->m_subcell == pmcd->m_subcell))
468 m_covr_array_outlines.Add(pmcd);
469 m_cell_hash[pmcd->m_cell_index]++;
477 if (m_cell_hash.find(pmcd->m_cell_index) ==
485 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
486 M_COVR_Desc *pmcd_candidate = &m_covr_array_outlines[i];
487 if ((pmcd_candidate->m_cell_index == pmcd->m_cell_index) &&
488 (pmcd_candidate->m_object_id == pmcd->m_object_id) &&
489 (pmcd_candidate->m_subcell == pmcd->m_subcell)) {
497M_COVR_Desc *covr_set::Find_MCD(
int cell_index,
int object_id,
int subcell) {
498 if (m_cell_hash.find(cell_index) == m_cell_hash.end())
501 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
502 M_COVR_Desc *pmcd_candidate = &m_covr_array_outlines[i];
503 if ((pmcd_candidate->m_cell_index == cell_index) &&
504 (pmcd_candidate->m_object_id == object_id) &&
505 (pmcd_candidate->m_subcell == subcell))
507 return pmcd_candidate;
515static unsigned char Table_0[] = {
516 0x0CD, 0x0EA, 0x0DC, 0x048, 0x03E, 0x06D, 0x0CA, 0x07B, 0x052, 0x0E1, 0x0A4,
517 0x08E, 0x0AB, 0x005, 0x0A7, 0x097, 0x0B9, 0x060, 0x039, 0x085, 0x07C, 0x056,
518 0x07A, 0x0BA, 0x068, 0x06E, 0x0F5, 0x05D, 0x002, 0x04E, 0x00F, 0x0A1, 0x027,
519 0x024, 0x041, 0x034, 0x000, 0x05A, 0x0FE, 0x0CB, 0x0D0, 0x0FA, 0x0F8, 0x06C,
520 0x074, 0x096, 0x09E, 0x00E, 0x0C2, 0x049, 0x0E3, 0x0E5, 0x0C0, 0x03B, 0x059,
521 0x018, 0x0A9, 0x086, 0x08F, 0x030, 0x0C3, 0x0A8, 0x022, 0x00A, 0x014, 0x01A,
522 0x0B2, 0x0C9, 0x0C7, 0x0ED, 0x0AA, 0x029, 0x094, 0x075, 0x00D, 0x0AC, 0x00C,
523 0x0F4, 0x0BB, 0x0C5, 0x03F, 0x0FD, 0x0D9, 0x09C, 0x04F, 0x0D5, 0x084, 0x01E,
524 0x0B1, 0x081, 0x069, 0x0B4, 0x009, 0x0B8, 0x03C, 0x0AF, 0x0A3, 0x008, 0x0BF,
525 0x0E0, 0x09A, 0x0D7, 0x0F7, 0x08C, 0x067, 0x066, 0x0AE, 0x0D4, 0x04C, 0x0A5,
526 0x0EC, 0x0F9, 0x0B6, 0x064, 0x078, 0x006, 0x05B, 0x09B, 0x0F2, 0x099, 0x0CE,
527 0x0DB, 0x053, 0x055, 0x065, 0x08D, 0x007, 0x033, 0x004, 0x037, 0x092, 0x026,
528 0x023, 0x0B5, 0x058, 0x0DA, 0x02F, 0x0B3, 0x040, 0x05E, 0x07F, 0x04B, 0x062,
529 0x080, 0x0E4, 0x06F, 0x073, 0x01D, 0x0DF, 0x017, 0x0CC, 0x028, 0x025, 0x02D,
530 0x0EE, 0x03A, 0x098, 0x0E2, 0x001, 0x0EB, 0x0DD, 0x0BC, 0x090, 0x0B0, 0x0FC,
531 0x095, 0x076, 0x093, 0x046, 0x057, 0x02C, 0x02B, 0x050, 0x011, 0x00B, 0x0C1,
532 0x0F0, 0x0E7, 0x0D6, 0x021, 0x031, 0x0DE, 0x0FF, 0x0D8, 0x012, 0x0A6, 0x04D,
533 0x08A, 0x013, 0x043, 0x045, 0x038, 0x0D2, 0x087, 0x0A0, 0x0EF, 0x082, 0x0F1,
534 0x047, 0x089, 0x06A, 0x0C8, 0x054, 0x01B, 0x016, 0x07E, 0x079, 0x0BD, 0x06B,
535 0x091, 0x0A2, 0x071, 0x036, 0x0B7, 0x003, 0x03D, 0x072, 0x0C6, 0x044, 0x08B,
536 0x0CF, 0x015, 0x09F, 0x032, 0x0C4, 0x077, 0x083, 0x063, 0x020, 0x088, 0x0F6,
537 0x0AD, 0x0F3, 0x0E8, 0x04A, 0x0E9, 0x035, 0x01C, 0x05F, 0x019, 0x01F, 0x07D,
538 0x070, 0x0FB, 0x0D1, 0x051, 0x010, 0x0D3, 0x02E, 0x061, 0x09D, 0x05C, 0x02A,
539 0x042, 0x0BE, 0x0E6};
541static unsigned char Encode_table[256];
542static unsigned char Decode_table[256];
544static bool cm93_decode_table_created;
553 virtual wxDirTraverseResult OnFile(
const wxString &filename) {
554 wxString name = filename.AfterLast(wxFileName::GetPathSeparator()).Lower();
555 if (name == wxT(
"cm93obj.dic")) {
560 return wxDIR_CONTINUE;
563 virtual wxDirTraverseResult OnDir(
const wxString &WXUNUSED(dirname)) {
564 return wxDIR_CONTINUE;
571cm93_dictionary::cm93_dictionary() {
572 m_S57ClassArray = NULL;
574 m_GeomTypeArray = NULL;
576 m_ValTypeArray = NULL;
581bool cm93_dictionary::LoadDictionary(
const wxString &dictionary_dir) {
584 wxString dir(dictionary_dir);
585 bool ret_val =
false;
587 wxChar sep = wxFileName::GetPathSeparator();
588 if (dir.Last() != sep) dir.Append(sep);
595 sf.Append(_T (
"CM93OBJ.DIC" ));
597 if (!wxFileName::FileExists(sf)) {
599 sf.Append(_T (
"cm93obj.dic" ));
600 if (!wxFileName::FileExists(sf))
return false;
604 if (!file.Open(sf))
return false;
606 nline = file.GetLineCount();
608 if (!nline)
return false;
613 for (i = 0; i < nline; i++) {
614 line = file.GetLine(i);
616 wxStringTokenizer tkz(line, wxT(
"|"));
620 wxString class_name = tkz.GetNextToken();
623 wxString token = tkz.GetNextToken();
625 token.ToLong(&liclass);
626 int iclass = liclass;
627 if (iclass > iclass_max) iclass_max = iclass;
630 wxString geo_type = tkz.GetNextToken();
634 m_max_class = iclass_max;
637 m_S57ClassArray =
new wxArrayString;
638 m_S57ClassArray->Add(_T (
"NULLNM" ), iclass_max + 1);
641 m_GeomTypeArray = (
int *)malloc((iclass_max + 1) *
sizeof(int));
644 for (i = 0; i < nline; i++) {
645 line = file.GetLine(i);
647 wxStringTokenizer tkz(line, wxT(
"|"));
651 wxString class_name = tkz.GetNextToken();
654 wxString token = tkz.GetNextToken();
656 token.ToLong(&liclass);
657 int iclass = liclass;
660 wxString geo_type = tkz.GetNextToken();
662 m_S57ClassArray->Insert(class_name, iclass);
663 m_S57ClassArray->RemoveAt(iclass + 1);
666 wxChar geo_type_primary = geo_type[0];
668 if (geo_type_primary ==
'A')
670 else if (geo_type_primary ==
'L')
672 else if (geo_type_primary ==
'P')
679 m_GeomTypeArray[iclass] = igeom_type;
687 sfa.Append(_T (
"ATTRLUT.DIC" ));
689 if (!wxFileName::FileExists(sfa)) {
691 sfa.Append(_T (
"attrlut.dic" ));
694 if (wxFileName::FileExists(sfa)) {
695 wxFFileInputStream filea(sfa);
701 while (!filea.Eof()) {
705 char a = filea.GetC();
706 if (filea.Eof())
break;
708 if (a == 0x0a)
break;
711 if (!line.StartsWith((
const wxChar *)wxT(
";"))) {
712 wxStringTokenizer tkz(line, wxT(
"|"));
715 wxString class_name = tkz.GetNextToken();
718 wxString token = tkz.GetNextToken();
720 token.ToLong(&liattr);
722 if (iattr > iattr_max) iattr_max = iattr;
727 m_max_attr = iattr_max;
733 m_AttrArray =
new wxArrayString;
734 m_AttrArray->Add(_T (
"NULLNM" ), iattr_max + 1);
737 m_ValTypeArray = (
char *)malloc((iattr_max + 1) *
sizeof(char));
740 while (!filea.Eof()) {
744 char a = filea.GetC();
745 if (filea.Eof())
break;
747 if (a == 0x0a)
break;
750 if (!line.StartsWith((
const wxChar *)wxT(
";"))) {
751 wxStringTokenizer tkz(line, wxT(
"|"));
754 wxString attr_name = tkz.GetNextToken();
757 wxString token = tkz.GetNextToken();
759 token.ToLong(&liattr);
762 m_AttrArray->Insert(attr_name, iattr);
763 m_AttrArray->RemoveAt(iattr + 1);
766 token = tkz.GetNextToken();
767 token = tkz.GetNextToken();
768 token = tkz.GetNextToken();
769 token = tkz.GetNextToken().Trim();
772 if (token.IsSameAs(_T (
"aFLOAT" )))
774 else if (token.IsSameAs(_T (
"aBYTE" )))
776 else if (token.IsSameAs(_T (
"aSTRING" )))
778 else if (token.IsSameAs(_T (
"aCMPLX" )))
780 else if (token.IsSameAs(_T (
"aLIST" )))
782 else if (token.IsSameAs(_T (
"aWORD10" )))
784 else if (token.IsSameAs(_T (
"aLONG" )))
787 m_ValTypeArray[iattr] = atype;
801 sfa.Append(_T (
"CM93ATTR.DIC" ));
803 if (!wxFileName::FileExists(sfa)) {
805 sfa.Append(_T (
"cm93attr.dic" ));
808 if (wxFileName::FileExists(sfa)) {
809 wxFFileInputStream filea(sfa);
815 while (!filea.Eof()) {
819 char a = filea.GetC();
820 if (filea.Eof())
break;
822 if (a == 0x0a)
break;
825 if (!line.StartsWith((
const wxChar *)wxT(
";"))) {
826 wxStringTokenizer tkz(line, wxT(
"|"));
827 if (tkz.CountTokens()) {
829 wxString class_name = tkz.GetNextToken();
832 wxString token = tkz.GetNextToken();
834 token.ToLong(&liattr);
836 if (iattr > iattr_max) iattr_max = iattr;
841 m_max_attr = iattr_max;
847 m_AttrArray =
new wxArrayString;
848 m_AttrArray->Add(_T (
"NULLNM" ), iattr_max + 1);
851 m_ValTypeArray = (
char *)malloc((iattr_max + 1) *
sizeof(char));
852 for (
int iat = 0; iat < iattr_max + 1; iat++) m_ValTypeArray[iat] =
'?';
855 while (!filea.Eof()) {
859 char a = filea.GetC();
860 if (filea.Eof())
break;
862 if (a == 0x0a)
break;
865 if (!line.StartsWith((
const wxChar *)wxT(
";"))) {
866 wxStringTokenizer tkz(line, wxT(
"|\r\n"));
867 if (tkz.CountTokens() >= 3) {
869 wxString attr_name = tkz.GetNextToken();
872 wxString token = tkz.GetNextToken();
874 token.ToLong(&liattr);
877 m_AttrArray->Insert(attr_name, iattr);
878 m_AttrArray->RemoveAt(iattr + 1);
880 token = tkz.GetNextToken().Trim();
883 if (token.IsSameAs(_T (
"aFLOAT" )))
885 else if (token.IsSameAs(_T (
"aBYTE" )))
887 else if (token.IsSameAs(_T (
"aSTRING" )))
889 else if (token.IsSameAs(_T (
"aCMPLX" )))
891 else if (token.IsSameAs(_T (
"aLIST" )))
893 else if (token.IsSameAs(_T (
"aWORD10" )))
895 else if (token.IsSameAs(_T (
"aLONG" )))
898 m_ValTypeArray[iattr] = atype;
911 wxString msg(_T (
"Loaded CM93 Dictionary from " ));
919wxString cm93_dictionary::GetClassName(
int iclass) {
920 if ((iclass > m_max_class) || (iclass < 0))
921 return (_T (
"Unknown" ));
923 return (m_S57ClassArray->Item(iclass));
926wxString cm93_dictionary::GetAttrName(
int iattr) {
927 if ((iattr > m_max_attr) || (iattr < 0))
928 return (_T (
"UnknownAttr" ));
930 return (m_AttrArray->Item(iattr));
934char cm93_dictionary::GetAttrType(
int iattr) {
935 if ((iattr > m_max_attr) || (iattr < 0))
938 return (m_ValTypeArray[iattr]);
941cm93_dictionary::~cm93_dictionary() {
942 delete m_S57ClassArray;
943 free(m_GeomTypeArray);
945 free(m_ValTypeArray);
950void CreateDecodeTable(
void) {
952 for (i = 0; i < 256; i++) {
953 Encode_table[i] = Table_0[i] ^ 8;
956 for (i = 0; i < 256; i++) {
957 unsigned char a = Encode_table[i];
958 Decode_table[(int)a] = (
unsigned char)i;
962static int read_and_decode_bytes(FILE *stream,
void *p,
int nbytes) {
967 if (fread(p, nbytes, 1, stream) != 1)
return 0;
970 unsigned char *q = (
unsigned char *)p;
972 for (
int i = 0; i < nbytes; i++) {
973 unsigned char a = *q;
975 unsigned char c = Decode_table[b];
983static int read_and_decode_double(FILE *stream,
double *p) {
986 if (fread(&t,
sizeof(
double), 1, stream) != 1)
return 0;
989 unsigned char *q = (
unsigned char *)&t;
991 for (
unsigned int i = 0; i <
sizeof(double); i++) {
992 unsigned char a = *q;
994 unsigned char c = Decode_table[b];
1006static int read_and_decode_int(FILE *stream,
int *p) {
1009 if (fread(&t,
sizeof(
int), 1, stream) != 1)
return 0;
1012 unsigned char *q = (
unsigned char *)&t;
1014 for (
unsigned int i = 0; i <
sizeof(int); i++) {
1015 unsigned char a = *q;
1017 unsigned char c = Decode_table[b];
1029static int read_and_decode_ushort(FILE *stream,
unsigned short *p) {
1032 if (fread(&t,
sizeof(
unsigned short), 1, stream) != 1)
return 0;
1035 unsigned char *q = (
unsigned char *)&t;
1037 for (
unsigned int i = 0; i <
sizeof(
unsigned short); i++) {
1038 unsigned char a = *q;
1040 unsigned char c = Decode_table[b];
1054int Get_CM93_CellIndex(
double lat,
double lon,
int scale) {
1089 double lon1 = (lon + 360.) * 3.;
1090 while (lon1 >= 1080.0) lon1 -= 1080.0;
1091 unsigned short lon2 = (
unsigned short)floor(lon1 / dval);
1092 unsigned short lon3 = lon2 * dval;
1097 double lat1 = (lat * 3.) + 270. - 30;
1098 unsigned short lat2 = (
unsigned short)floor(lat1 / dval);
1099 unsigned short lat3 = lat2 * dval;
1101 retval += (lat3 + 30) * 10000;
1109void Get_CM93_Cell_Origin(
int cellindex,
int scale,
double *lat,
double *lon) {
1111 double idx1 = cellindex % 10000;
1112 double lont = (idx1 / 3.);
1117 int idx2 = cellindex / 10000;
1118 double lat1 = idx2 - 270.;
1124bool Is_CM93Cell_Present(wxString &fileprefix,
double lat,
double lon,
1130 switch (scale_index) {
1178 int cellindex = Get_CM93_CellIndex(lat, lon,
scale);
1183 int ilat = cellindex / 10000;
1184 int ilon = cellindex % 10000;
1186 int jlat = (((ilat - 30) / dval) * dval) + 30;
1187 int jlon = (ilon / dval) * dval;
1189 int ilatroot = (((ilat - 30) / 60) * 60) + 30;
1190 int ilonroot = (ilon / 60) * 60;
1193 fileroot.Printf(_T (
"%04d%04d" ), ilatroot, ilonroot);
1194 appendOSDirSep(&fileroot);
1196 wxString sdir(fileprefix);
1201 tfile.Printf(_T (
"?%03d%04d." ), jlat, jlon);
1202 tfile += scale_char;
1205 if (!::wxDirExists(sdir)) {
1206 wxString old_scalechar(scale_char);
1207 wxString new_scalechar = old_scalechar.Lower();
1211 sdir += new_scalechar;
1214 if (::wxDirExists(sdir)) {
1217 wxArrayString file_array;
1218 int n_files = dir.GetAllFiles(sdir, &file_array, tfile, wxDIR_FILES);
1220 if (n_files)
return true;
1223 wxString old_scalechar(scale_char);
1224 wxString new_scalechar = old_scalechar.Lower();
1227 tfile1.Printf(_T (
"?%03d%04d." ), jlat, jlon);
1228 tfile1 += new_scalechar;
1230 int n_files1 = dir.GetAllFiles(sdir, &file_array, tfile1, wxDIR_FILES);
1232 if (n_files1)
return true;
1236 dir.GetAllFiles(sdir, &file_array, tfile + _T(
".xz"), wxDIR_FILES);
1238 if (n_files)
return true;
1244static bool read_header_and_populate_cib(FILE *stream,
Cell_Info_Block *pCIB) {
1253 memset((
void *)&header, 0,
sizeof(header));
1255 read_and_decode_double(stream, &header.lon_min);
1256 read_and_decode_double(stream, &header.lat_min);
1257 read_and_decode_double(stream, &header.lon_max);
1258 read_and_decode_double(stream, &header.lat_max);
1260 read_and_decode_double(stream, &header.easting_min);
1261 read_and_decode_double(stream, &header.northing_min);
1262 read_and_decode_double(stream, &header.easting_max);
1263 read_and_decode_double(stream, &header.northing_max);
1265 read_and_decode_ushort(stream, &header.usn_vector_records);
1266 read_and_decode_int(stream, &header.n_vector_record_points);
1267 read_and_decode_int(stream, &header.m_46);
1268 read_and_decode_int(stream, &header.m_4a);
1269 read_and_decode_ushort(stream, &header.usn_point3d_records);
1270 read_and_decode_int(stream, &header.m_50);
1271 read_and_decode_int(stream, &header.m_54);
1272 read_and_decode_ushort(stream, &header.usn_point2d_records);
1273 read_and_decode_ushort(stream, &header.m_5a);
1274 read_and_decode_ushort(stream, &header.m_5c);
1275 read_and_decode_ushort(stream, &header.usn_feature_records);
1277 read_and_decode_int(stream, &header.m_60);
1278 read_and_decode_int(stream, &header.m_64);
1279 read_and_decode_ushort(stream, &header.m_68);
1280 read_and_decode_ushort(stream, &header.m_6a);
1281 read_and_decode_ushort(stream, &header.m_6c);
1282 read_and_decode_int(stream, &header.m_nrelated_object_pointers);
1284 read_and_decode_int(stream, &header.m_72);
1285 read_and_decode_ushort(stream, &header.m_76);
1287 read_and_decode_int(stream, &header.m_78);
1288 read_and_decode_int(stream, &header.m_7c);
1292 double delta_x = header.easting_max - header.easting_min;
1294 delta_x += CM93_semimajor_axis_meters * 2.0 * PI;
1296 pCIB->transform_x_rate = delta_x / 65535;
1297 pCIB->transform_y_rate = (header.northing_max - header.northing_min) / 65535;
1299 pCIB->transform_x_origin = header.easting_min;
1300 pCIB->transform_y_origin = header.northing_min;
1302 pCIB->min_lat = header.lat_min;
1303 pCIB->min_lon = header.lon_min;
1311 pCIB->m_nfeature_records = header.usn_feature_records;
1312 pCIB->pobject_block =
1313 (
Object *)calloc(pCIB->m_nfeature_records *
sizeof(
Object), 1);
1315 pCIB->m_n_point2d_records = header.usn_point2d_records;
1316 pCIB->p2dpoint_array =
1319 pCIB->pprelated_object_block =
1320 (
Object **)malloc(header.m_nrelated_object_pointers *
sizeof(
Object *));
1322 pCIB->object_vector_record_descriptor_block =
1326 pCIB->attribute_block_top = (
unsigned char *)calloc(header.m_78, 1);
1328 pCIB->m_nvector_records = header.usn_vector_records;
1332 pCIB->pvector_record_block_top =
1335 pCIB->m_n_point3d_records = header.usn_point3d_records;
1339 pCIB->p3dpoint_array =
1345static bool read_vector_record_table(FILE *stream,
int count,
1350 cm93_point *q = pCIB->pvector_record_block_top;
1352 for (
int iedge = 0; iedge < count; iedge++) {
1355 unsigned short npoints;
1356 brv = !(read_and_decode_ushort(stream, &npoints) == 0);
1357 if (!brv)
return false;
1359 p->n_points = npoints;
1367 unsigned short x, y;
1368 for (
int index = 0; index < p->n_points; index++) {
1369 if (!read_and_decode_ushort(stream, &x))
return false;
1370 if (!read_and_decode_ushort(stream, &y))
return false;
1386 for (
int j = 0; j < p->n_points - 1; j++) {
1387 if (t->x >= p->x_max) p->x_max = t->x;
1389 if (t->x <= p->x_min) p->x_min = t->x;
1391 if (t->y >= p->y_max) p->y_max = t->y;
1393 if (t->y <= p->y_max) p->y_min = t->y;
1408static bool read_3dpoint_table(FILE *stream,
int count,
Cell_Info_Block *pCIB) {
1412 for (
int i = 0; i < count; i++) {
1413 unsigned short npoints;
1414 if (!read_and_decode_ushort(stream, &npoints))
return false;
1416 p->n_points = npoints;
1424 unsigned short x, y, z;
1425 for (
int index = 0; index < p->n_points; index++) {
1426 if (!read_and_decode_ushort(stream, &x))
return false;
1427 if (!read_and_decode_ushort(stream, &y))
return false;
1428 if (!read_and_decode_ushort(stream, &z))
return false;
1442static bool read_2dpoint_table(FILE *stream,
int count,
Cell_Info_Block *pCIB) {
1446 unsigned short x, y;
1447 for (
int index = 0; index < count; index++) {
1448 if (!read_and_decode_ushort(stream, &x))
return false;
1449 if (!read_and_decode_ushort(stream, &y))
return false;
1451 pCIB->p2dpoint_array[index].x = x;
1452 pCIB->p2dpoint_array[index].y = y;
1458static bool read_feature_record_table(FILE *stream,
int n_features,
1461 Object *pobj = pCIB->pobject_block;
1464 pCIB->object_vector_record_descriptor_block;
1467 pCIB->pprelated_object_block;
1470 unsigned char *puc_var10 = pCIB->attribute_block_top;
1473 unsigned char object_type;
1474 unsigned char geom_prim;
1475 unsigned short obj_desc_bytes = 0;
1478 unsigned short index;
1479 unsigned short n_elements;
1481 for (
int iobject = 0; iobject < n_features; iobject++) {
1483 read_and_decode_bytes(stream, &object_type, 1);
1484 read_and_decode_bytes(stream, &geom_prim,
1486 read_and_decode_ushort(stream,
1489 pobj->otype = object_type;
1490 pobj->geotype = geom_prim;
1492 switch (pobj->geotype & 0x0f) {
1495 if (!read_and_decode_ushort(stream, &n_elements))
return false;
1497 pobj->n_geom_elements = n_elements;
1498 t = (pobj->n_geom_elements * 2) + 2;
1499 obj_desc_bytes -= t;
1502 pobject_vector_collection;
1506 for (
unsigned short i = 0; i < pobj->n_geom_elements; i++) {
1507 if (!read_and_decode_ushort(stream, &index))
return false;
1509 if ((index & 0x1fff) > pCIB->m_nvector_records)
1515 pobject_vector_collection->pGeom_Description = u;
1516 pobject_vector_collection->segment_usage =
1517 (
unsigned char)(index >> 13);
1519 pobject_vector_collection++;
1527 if (!read_and_decode_ushort(
1528 stream, &n_elements))
1531 pobj->n_geom_elements = n_elements;
1532 t = (pobj->n_geom_elements * 2) + 2;
1533 obj_desc_bytes -= t;
1536 pobject_vector_collection;
1540 for (
unsigned short i = 0; i < pobj->n_geom_elements; i++) {
1541 unsigned short geometry_index;
1543 if (!read_and_decode_ushort(stream, &geometry_index))
return false;
1545 if ((geometry_index & 0x1fff) > pCIB->m_nvector_records)
1550 geometry_index & 0x1fff)];
1552 pobject_vector_collection->pGeom_Description = u;
1553 pobject_vector_collection->segment_usage =
1554 (
unsigned char)(geometry_index >> 13);
1556 pobject_vector_collection++;
1563 if (!read_and_decode_ushort(stream, &index))
return false;
1565 obj_desc_bytes -= 2;
1567 pobj->n_geom_elements = 1;
1569 pobj->pGeometry = &pCIB->p2dpoint_array[index];
1575 if (!read_and_decode_ushort(stream, &index))
return false;
1576 obj_desc_bytes -= 2;
1578 pobj->n_geom_elements = 1;
1581 &pCIB->point3d_descriptor_block[index];
1588 if ((pobj->geotype & 0x10) == 0x10)
1590 unsigned char nrelated;
1591 if (!read_and_decode_bytes(stream, &nrelated, 1))
return false;
1593 pobj->n_related_objects = nrelated;
1594 t = (pobj->n_related_objects * 2) + 1;
1595 obj_desc_bytes -= t;
1597 pobj->p_related_object_pointer_array = p_relob;
1598 p_relob += pobj->n_related_objects;
1600 Object **w = (
Object **)pobj->p_related_object_pointer_array;
1601 for (
unsigned char j = 0; j < pobj->n_related_objects; j++) {
1602 if (!read_and_decode_ushort(stream, &index))
return false;
1604 if (index > pCIB->m_nfeature_records)
1608 Object *prelated_object = &pCIB->pobject_block[index];
1609 *w = prelated_object;
1611 prelated_object->p_related_object_pointer_array =
1617 if ((pobj->geotype & 0x20) == 0x20) {
1618 unsigned short nrelated;
1619 if (!read_and_decode_ushort(stream, &nrelated))
return false;
1621 pobj->n_related_objects = (
unsigned char)(nrelated & 0xFF);
1622 obj_desc_bytes -= 2;
1625 if ((pobj->geotype & 0x40) == 0x40) {
1628 if ((pobj->geotype & 0x80) == 0x80)
1630 unsigned char nattr;
1631 if (!read_and_decode_bytes(stream, &nattr, 1))
return false;
1633 pobj->n_attributes = nattr;
1634 obj_desc_bytes -= 5;
1636 pobj->attributes_block = puc_var10;
1637 puc_var10 += obj_desc_bytes;
1639 puc10count += obj_desc_bytes;
1641 if (!read_and_decode_bytes(stream, pobj->attributes_block,
1645 if ((pobj->geotype & 0x0f) == 1) {
1656 printf(
"catch on read_feature_record_table\n");
1662bool Ingest_CM93_Cell(
const char *cell_file_name,
Cell_Info_Block *pCIB) {
1667 FILE *flstream = fopen(cell_file_name,
"rb");
1668 if (!flstream)
return false;
1670 fseek(flstream, 0, SEEK_END);
1671 file_length = ftell(flstream);
1675 FILE *stream = fopen(cell_file_name,
"rb");
1676 if (!stream)
return false;
1680 unsigned short word0 = 0;
1686 read_and_decode_ushort(stream,
1688 read_and_decode_int(stream, &int0);
1689 read_and_decode_int(stream, &int1);
1691 int test = word0 + int0 + int1;
1692 if (test != file_length) {
1699 if (!read_header_and_populate_cib(stream, pCIB)) {
1704 if (!read_vector_record_table(stream, pCIB->m_nvector_records, pCIB)) {
1709 if (!read_3dpoint_table(stream, pCIB->m_n_point3d_records, pCIB)) {
1714 if (!read_2dpoint_table(stream, pCIB->m_n_point2d_records, pCIB)) {
1719 if (!read_feature_record_table(stream, pCIB->m_nfeature_records, pCIB)) {
1742cm93chart::cm93chart() {
1743 m_ChartType = CHART_TYPE_CM93;
1746 if (!cm93_decode_table_created) {
1747 CreateDecodeTable();
1748 cm93_decode_table_created =
true;
1754 m_current_cell_vearray_offset = 0;
1756 m_ncontour_alloc = 100;
1757 m_pcontour_array = (
int *)malloc(m_ncontour_alloc *
sizeof(
int));
1767 m_pDrawBuffer = (wxPoint *)malloc(4 *
sizeof(wxPoint));
1768 m_nDrawBufferSize = 1;
1771 m_this_chart_context = (chart_context *)calloc(
sizeof(chart_context), 1);
1772 m_this_chart_context->chart =
this;
1776cm93chart::~cm93chart() {
1777 free(m_pcontour_array);
1781 free(m_pDrawBuffer);
1784void cm93chart::Unload_CM93_Cell(
void) {
1785 free(m_CIB.pobject_block);
1787 free(m_CIB.p2dpoint_array);
1788 free(m_CIB.pprelated_object_block);
1789 free(m_CIB.object_vector_record_descriptor_block);
1790 free(m_CIB.attribute_block_top);
1791 free(m_CIB.edge_vector_descriptor_block);
1792 free(m_CIB.pvector_record_block_top);
1793 free(m_CIB.point3d_descriptor_block);
1794 free(m_CIB.p3dpoint_array);
1803double cm93chart::GetNormalScaleMin(
double canvas_scale_factor,
1804 bool b_allow_overzoom) {
1805 switch (GetNativeScale()) {
1827double cm93chart::GetNormalScaleMax(
double canvas_scale_factor,
1835 switch (GetNativeScale()) {
1857void cm93chart::GetPointPix(ObjRazRules *rzRules,
float north,
float east,
1859 wxPoint2DDouble en(east, north);
1860 GetPointPix(rzRules, &en, r, 1);
1863void cm93chart::GetPointPix(ObjRazRules *rzRules, wxPoint2DDouble *en,
1864 wxPoint *r,
int nPoints) {
1865 S57Obj *obj = rzRules->obj;
1867 double xr = obj->x_rate;
1868 double xo = obj->x_origin;
1869 double yr = obj->y_rate;
1870 double yo = obj->y_origin;
1872 if (m_vp_current.m_projection_type == PROJECTION_MERCATOR) {
1873 if (m_vp_current.GetBBox().GetMaxLon() >= 180. &&
1874 rzRules->obj->BBObj.GetMaxLon() < m_vp_current.GetBBox().GetMinLon())
1875 xo += mercator_k0 * WGS84_semimajor_axis_meters * 2.0 * PI;
1876 else if ((m_vp_current.GetBBox().GetMinLon() <= -180. &&
1877 rzRules->obj->BBObj.GetMinLon() >
1878 m_vp_current.GetBBox().GetMaxLon()) ||
1879 (rzRules->obj->BBObj.GetMaxLon() >= 180 &&
1880 m_vp_current.GetBBox().GetMinLon() <= 0.))
1881 xo -= mercator_k0 * WGS84_semimajor_axis_meters * 2.0 * PI;
1883 for (
int i = 0; i < nPoints; i++) {
1884 double valx = (en[i].m_x * xr) + xo;
1885 double valy = (en[i].m_y * yr) + yo;
1887 r[i].x = ((valx - m_easting_vp_center) * m_view_scale_ppm) +
1888 m_pixx_vp_center + 0.5;
1889 r[i].y = m_pixy_vp_center -
1890 ((valy - m_northing_vp_center) * m_view_scale_ppm) + 0.5;
1893 for (
int i = 0; i < nPoints; i++) {
1894 double valx = (en[i].m_x * xr) + xo;
1895 double valy = (en[i].m_y * yr) + yo;
1898 fromSM(valx - m_easting_vp_center, valy - m_northing_vp_center,
1899 m_vp_current.clat, m_vp_current.clon, &lat, &lon);
1901 double rotation = m_vp_current.rotation;
1902 m_vp_current.SetRotationAngle(0);
1903 r[i] = m_vp_current.GetPixFromLL(lat, lon);
1904 m_vp_current.SetRotationAngle(rotation);
1909void cm93chart::GetPixPoint(
int pixx,
int pixy,
double *plat,
double *plon,
1912 vpt->GetLLFromPix(wxPoint(pixx, pixy), plat, plon);
1919 int dx = pixx - (vpt->pix_width / 2);
1920 int dy = (vpt->pix_height / 2) - pixy;
1922 double xp = (dx * cos(vpt->skew)) - (dy * sin(vpt->skew));
1923 double yp = (dy * cos(vpt->skew)) + (dx * sin(vpt->skew));
1925 double d_east = xp / vpt->view_scale_ppm;
1926 double d_north = yp / vpt->view_scale_ppm;
1929 fromSM(d_east, d_north, vpt->clat, vpt->clon, &slat, &slon);
1931 if (slon > 360.) slon -= 360.;
1939 if (IsCacheValid()) {
1941 if (vp_last.view_scale_ppm == vp_proposed.view_scale_ppm) {
1945 wxPoint2DDouble p = vp_proposed.GetDoublePixFromLL(ref_lat, ref_lon) -
1946 vp_last.GetDoublePixFromLL(ref_lat, ref_lon);
1949 vp_last.GetLLFromPix(wxPoint(round(p.m_x), round(p.m_y)), &xlat, &xlon);
1951 double prev_easting_c, prev_northing_c;
1952 toSM(vp_last.clat, vp_last.clon, ref_lat, ref_lon, &prev_easting_c,
1955 double easting_c, northing_c;
1956 toSM(vp_proposed.clat, vp_proposed.clon, ref_lat, ref_lon, &easting_c,
1959 double delta_pix_x =
1960 (easting_c - prev_easting_c) * vp_proposed.view_scale_ppm;
1961 int dpix_x = (
int)round(delta_pix_x);
1962 double dpx = dpix_x;
1964 double delta_pix_y =
1965 (northing_c - prev_northing_c) * vp_proposed.view_scale_ppm;
1966 int dpix_y = (
int)round(delta_pix_y);
1967 double dpy = dpix_y;
1969 double c_east_d = (dpx / vp_proposed.view_scale_ppm) + prev_easting_c;
1970 double c_north_d = (dpy / vp_proposed.view_scale_ppm) + prev_northing_c;
1973 fromSM(c_east_d, c_north_d, ref_lat, ref_lon, &xlat, &xlon);
1975 vp_proposed.clon = xlon;
1976 vp_proposed.clat = xlat;
1989void cm93chart::SetVPParms(
const ViewPort &vpt) {
1990 if (m_vp_current == vpt) {
1997 m_pixx_vp_center = vpt.pix_width / 2;
1998 m_pixy_vp_center = vpt.pix_height / 2;
1999 m_view_scale_ppm = vpt.view_scale_ppm;
2001 toSM(vpt.clat, vpt.clon, ref_lat, ref_lon, &m_easting_vp_center,
2002 &m_northing_vp_center);
2004 vp_transform.easting_vp_center = m_easting_vp_center;
2005 vp_transform.northing_vp_center = m_northing_vp_center;
2010 LLBBox box = vptl.GetBBox();
2011 double ll_lon = box.GetMinLon();
2012 double ll_lat = box.GetMinLat();
2014 double ur_lon = box.GetMaxLon();
2015 double ur_lat = box.GetMaxLat();
2018 "cm93chart::SetVPParms ll_lon: %g ll_lat: %g ur_lon: %g ur_lat: "
2020 ll_lon, ll_lat, ur_lon, ur_lat, m_dval);
2024 std::vector<int> vpcells = GetVPCellArray(vpt);
2029 bool recalc_depth =
false;
2031 for (
unsigned int i = 0; i < vpcells.size(); i++) {
2032 bcell_is_in =
false;
2033 for (
unsigned int j = 0; j < m_cells_loaded_array.size(); j++) {
2034 if (vpcells[i] == m_cells_loaded_array[j]) {
2042#ifndef __OCPN__ANDROID__
2043 OCPNPlatform::ShowBusySpinner();
2045 int cell_index = vpcells[i];
2047 if (loadcell_in_sequence(cell_index,
'0'))
2049 ProcessVectorEdges();
2050 CreateObjChain(cell_index, (
int)
'0', vpt.view_scale_ppm);
2052 ForceEdgePriorityEvaluate();
2053 recalc_depth =
true;
2055 m_cells_loaded_array.push_back(cell_index);
2060 char loadcell_key =
'A';
2064 while (loadcell_in_sequence(cell_index, loadcell_key)) {
2065 ProcessVectorEdges();
2066 CreateObjChain(cell_index, (
int)loadcell_key, vpt.view_scale_ppm);
2068 ForceEdgePriorityEvaluate();
2070 if (std::find(m_cells_loaded_array.begin(), m_cells_loaded_array.end(),
2071 cell_index) == m_cells_loaded_array.end())
2072 m_cells_loaded_array.push_back(cell_index);
2079 AssembleLineGeometry();
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 = 1e6;
2091 m_this_chart_context->vertex_buffer = GetLineVertexBuffer();
2094 for (
int i = 0; i < PI_PRIO_NUM; ++i) {
2095 for (
int j = 0; j < PI_LUPNAME_NUM; j++) {
2096 ObjRazRules *top = razRules[i][j];
2098 if (top->obj) top->obj->m_chart_context = m_this_chart_context;
2103 OCPNPlatform::HideBusySpinner();
2108 ClearDepthContourArray();
2109 BuildDepthContourArray();
2113std::vector<int> cm93chart::GetVPCellArray(
const ViewPort &vpt) {
2116 LLBBox box = vptl.GetBBox();
2117 double ll_lon = box.GetMinLon();
2118 double ll_lat = box.GetMinLat();
2120 double ur_lon = box.GetMaxLon();
2121 double ur_lat = box.GetMaxLat();
2124 ur_lat = wxMin(ur_lat, 79.99999);
2127 ur_lat = wxMin(ur_lat, 79.99999);
2136 std::vector<int> vpcells;
2138 int lower_left_cell = Get_CM93_CellIndex(ll_lat, ll_lon, GetNativeScale());
2139 vpcells.push_back(lower_left_cell);
2142 printf(
"cm93chart::GetVPCellArray Adding %d\n", lower_left_cell);
2145 Get_CM93_Cell_Origin(lower_left_cell, GetNativeScale(), &rlat, &rlon);
2150 int loni_0 = (int)wxRound(rlon * 3);
2151 int loni_20 = loni_0 + (int)m_dval;
2152 int lati_20 = (int)wxRound(rlat * 3);
2154 while (lati_20 < (ur_lat * 3.)) {
2155 while (loni_20 < (ur_lon * 3.)) {
2156 unsigned int next_lon = loni_20 + 1080;
2157 while (next_lon >= 1080) next_lon -= 1080;
2159 unsigned int next_cell = next_lon;
2161 next_cell += (lati_20 + 270) * 10000;
2163 vpcells.push_back((
int)next_cell);
2165 printf(
"cm93chart::GetVPCellArray Adding %d\n", next_cell);
2167 loni_20 += (int)m_dval;
2169 lati_20 += (int)m_dval;
2176void cm93chart::ProcessVectorEdges(
void) {
2179 auto &vehash = Get_ve_hash();
2181 m_current_cell_vearray_offset =
2185 for (
int iedge = 0; iedge < m_CIB.m_nvector_records; iedge++) {
2186 VE_Element *vep =
new VE_Element;
2187 vep->index = iedge + m_current_cell_vearray_offset;
2188 vep->nCount = pgd->n_points;
2189 vep->pPoints = NULL;
2190 vep->max_priority = -99;
2192 if (pgd->n_points) {
2193 float *pPoints = (
float *)malloc(pgd->n_points * 2 *
sizeof(
float));
2194 vep->pPoints = pPoints;
2199 double east_max = -1e7;
2200 double east_min = 1e7;
2201 double north_max = -1e7;
2202 double north_min = 1e7;
2204 for (
int ip = 0; ip < pgd->n_points; ip++) {
2205 *pPoints++ = ppt->x;
2206 *pPoints++ = ppt->y;
2208 east_max = wxMax(east_max, ppt->x);
2209 east_min = wxMin(east_min, ppt->x);
2210 north_max = wxMax(north_max, ppt->y);
2211 north_min = wxMin(north_min, ppt->y);
2217 double lat1, lon1, lat2, lon2;
2223 Transform(&p, 0, 0, &lat1, &lon1);
2227 Transform(&p, 0, 0, &lat2, &lon2);
2232 vep->edgeBBox.Set(lat1, lon1, lat2, lon2);
2235 vehash[vep->index] = vep;
2241int cm93chart::CreateObjChain(
int cell_index,
int subcell,
2242 double view_scale_ppm) {
2244 LUPname LUP_Name = PAPER_CHART;
2246 m_CIB.m_cell_mcovr_list.Clear();
2250 Object *pobjectDef = m_CIB.pobject_block;
2251 m_CIB.b_have_offsets =
false;
2253 m_CIB.b_have_user_offsets =
false;
2259 double scale = gFrame->GetBestVPScale(
this);
2260 int nativescale = GetNativeScale();
2262 while (iObj < m_CIB.m_nfeature_records) {
2263 if ((pobjectDef != NULL)) {
2264 Extended_Geometry *xgeom = BuildGeom(pobjectDef, NULL, iObj);
2269 CreateS57Obj(cell_index, iObj, subcell, pobjectDef, m_pDict, xgeom,
2270 ref_lat, ref_lon, GetNativeScale(), view_scale_ppm);
2273 wxString objnam = obj->GetAttrValueAsString(
"OBJNAM");
2274 wxString fe_name = wxString(obj->FeatureName, wxConvUTF8);
2275 if (fe_name == _T(
"_texto"))
2276 objnam = obj->GetAttrValueAsString(
"_texta");
2277 if (objnam.Len() > 0) {
2279 wxString::Format(_T(
"%i_%i"), cell_index, subcell);
2280 g_pi_manager->SendVectorChartObjectInfo(cellname, fe_name, objnam,
2281 obj->m_lat, obj->m_lon,
scale,
2285 if (GEO_POINT == obj->Primitive_type) {
2287 if ((!strncmp(obj->FeatureName,
"LITFLT", 6)) ||
2288 (!strncmp(obj->FeatureName,
"LITVES", 6)) ||
2289 (!strncmp(obj->FeatureName,
"BOY", 3))) {
2290 pFloatingATONArray->Add(obj);
2294 if (!strncmp(obj->FeatureName,
"BCN", 3)) pRigidATONArray->Add(obj);
2297 if ((!strncmp(obj->FeatureName,
"LIT", 3)) ||
2298 (!strncmp(obj->FeatureName,
"LIGHTS", 6)) ||
2299 (!strncmp(obj->FeatureName,
"BCN", 3)) ||
2300 (!strncmp(obj->FeatureName,
"_slgto", 6)) ||
2301 (!strncmp(obj->FeatureName,
"_boygn", 6)) ||
2302 (!strncmp(obj->FeatureName,
"_bcngn", 6)) ||
2303 (!strncmp(obj->FeatureName,
"_extgn", 6)) ||
2304 (!strncmp(obj->FeatureName,
"TOWERS", 6)) ||
2305 (!strncmp(obj->FeatureName,
"BOY", 3))) {
2306 obj->bIsAton =
true;
2312 if (GEO_AREA == obj->Primitive_type) {
2313 if (!strncmp(obj->FeatureName,
"DEPARE", 6) ||
2314 !strncmp(obj->FeatureName,
"DRGARE", 6))
2315 obj->bIsAssociable =
true;
2323 switch (obj->Primitive_type) {
2327 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
2328 LUP_Name = PAPER_CHART;
2330 LUP_Name = SIMPLIFIED;
2332 if (m_b2pointLUPS) {
2334 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
2335 LUPO_Name = SIMPLIFIED;
2337 LUPO_Name = PAPER_CHART;
2341 ps52plib->S52_LUPLookup(LUPO_Name, obj->FeatureName, obj);
2343 ps52plib->_LUP2rules(LUPO, obj);
2344 _insertRules(obj, LUPO,
this);
2354 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
2355 LUP_Name = PLAIN_BOUNDARIES;
2357 LUP_Name = SYMBOLIZED_BOUNDARIES;
2361 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
2362 LUPO_Name = SYMBOLIZED_BOUNDARIES;
2364 LUPO_Name = PLAIN_BOUNDARIES;
2368 ps52plib->S52_LUPLookup(LUPO_Name, obj->FeatureName, obj);
2370 ps52plib->_LUP2rules(LUPO, obj);
2371 _insertRules(obj, LUPO,
this);
2377 LUP = ps52plib->S52_LUPLookup(LUP_Name, obj->FeatureName, obj);
2381 wxString msg(obj->FeatureName, wxConvUTF8);
2382 msg.Prepend(_T (
" CM93 could not find LUP for " ));
2383 LogMessageOnce(msg);
2385 if (0 == obj->nRef)
delete obj;
2388 ps52plib->_LUP2rules(LUP, obj);
2391 _insertRules(obj, LUP,
this);
2394 obj->m_DisplayCat = LUP->DISC;
2397 obj->m_DPRI = LUP->DPRI -
'0';
2400 obj->m_chart_context = m_this_chart_context;
2419InitReturn cm93chart::Init(
const wxString &name, ChartInitFlag flags) {
2421 m_Description = m_FullPath;
2423 wxFileName fn(name);
2425 if (!m_prefix.Len())
2426 m_prefix = fn.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
2428 m_scalechar = fn.GetExt();
2433 switch ((m_scalechar.mb_str())[(
size_t)0]) {
2463 m_Chart_Scale =
scale;
2465 switch (GetNativeScale()) {
2496 wxString data = _T (
"CM93Chart " );
2497 data.Append(m_scalechar);
2499 s.Printf(_T (
" 1/%d" ), m_Chart_Scale);
2504 if (
scale != 20000000)
2505 m_pcovr_set->Init(m_scalechar.mb_str()[(
size_t)0], m_prefix);
2507 if (flags == THUMB_ONLY) {
2515 if (flags == HEADER_ONLY)
return CreateHeaderDataFromCM93Cell();
2520 if (m_pManager->Loadcm93Dictionary(name))
2521 m_pDict = m_pManager->m_pcm93Dict;
2523 wxLogMessage(_T (
" CM93Chart Init cannot locate CM93 dictionary." ));
2524 return INIT_FAIL_REMOVE;
2529 bReadyToRender =
true;
2534Extended_Geometry *cm93chart::BuildGeom(
Object *pobject,
2535 wxFileOutputStream *postream,
2542 int geom_type_maybe = pobject->geotype;
2544 switch (geom_type_maybe) {
2582 Extended_Geometry *ret_ptr =
new Extended_Geometry;
2584 int lon_max, lat_max, lon_min, lat_min;
2596 int nsegs = pobject->n_geom_elements;
2598 ret_ptr->n_vector_indices = nsegs;
2599 ret_ptr->pvector_index = (
int *)malloc(nsegs * 3 *
sizeof(
int));
2602 int n_maxvertex = 0;
2603 for (
int i = 0; i < nsegs; i++) {
2606 n_maxvertex += pgd->n_points;
2612 wxPoint2DDouble *pPoints =
2613 (wxPoint2DDouble *)calloc((n_maxvertex) *
sizeof(wxPoint2DDouble), 1);
2616 int n_prev_vertex_index = 1;
2617 bool bnew_ring =
true;
2626 cur_end_point.x = 1;
2627 cur_end_point.y = 1;
2629 int n_max_points = -1;
2630 while (iseg < nsegs) {
2631 int type_seg = psegs[iseg].segment_usage;
2636 int npoints = pgd->n_points;
2639 n_max_points = wxMax(n_max_points, npoints);
2645 if ((type_seg & 4) == 0)
2646 start_point = rseg[0];
2648 start_point = rseg[npoints - 1];
2651 if (((type_seg & 4) == 0)) {
2652 cur_end_point = rseg[npoints - 1];
2653 for (
int j = 0; j < npoints; j++) {
2657 lon_max = wxMax(lon_max, rseg[j].x);
2658 lon_min = wxMin(lon_min, rseg[j].x);
2659 lat_max = wxMax(lat_max, rseg[j].y);
2660 lat_min = wxMin(lat_min, rseg[j].y);
2663 pPoints[ip].m_x = rseg[j].x;
2664 pPoints[ip].m_y = rseg[j].y;
2667 }
else if ((type_seg & 4) == 4)
2669 cur_end_point = rseg[0];
2670 for (
int j = npoints - 1; j >= 0; j--) {
2674 lon_max = wxMax(lon_max, rseg[j].x);
2675 lon_min = wxMin(lon_min, rseg[j].x);
2676 lat_max = wxMax(lat_max, rseg[j].y);
2677 lat_min = wxMin(lat_min, rseg[j].y);
2680 pPoints[ip].m_x = rseg[j].x;
2681 pPoints[ip].m_y = rseg[j].y;
2688 ret_ptr->pvector_index[iseg * 3 + 0] =
2690 ret_ptr->pvector_index[iseg * 3 + 1] =
2691 pgd->index + m_current_cell_vearray_offset;
2692 ret_ptr->pvector_index[iseg * 3 + 2] =
2695 if ((cur_end_point.x == start_point.x) &&
2696 (cur_end_point.y == start_point.y)) {
2701 int nRingVertex = ip - n_prev_vertex_index;
2704 if (ncontours > m_ncontour_alloc - 1) {
2705 m_ncontour_alloc *= 2;
2706 int *tmp = m_pcontour_array;
2707 m_pcontour_array = (
int *)realloc(m_pcontour_array,
2708 m_ncontour_alloc *
sizeof(
int));
2714 m_pcontour_array[ncontours] = nRingVertex;
2717 n_prev_vertex_index = ip;
2723 ret_ptr->n_max_edge_points = n_max_points;
2725 ret_ptr->n_contours =
2728 if (0 == ncontours) ncontours = 1;
2729 ret_ptr->contour_array = (
int *)malloc(ncontours *
sizeof(
int));
2730 memcpy(ret_ptr->contour_array, m_pcontour_array, ncontours *
sizeof(
int));
2732 ret_ptr->vertex_array = pPoints;
2733 ret_ptr->n_max_vertex = n_maxvertex;
2735 ret_ptr->pogrGeom = NULL;
2737 ret_ptr->xmin = lon_min;
2738 ret_ptr->xmax = lon_max;
2739 ret_ptr->ymin = lat_min;
2740 ret_ptr->ymax = lat_max;
2748 ret_ptr->pogrGeom = NULL;
2750 ret_ptr->pointx = pt->x;
2751 ret_ptr->pointy = pt->y;
2760 int nsegs = pobject->n_geom_elements;
2762 ret_ptr->n_vector_indices = nsegs;
2763 ret_ptr->pvector_index = (
int *)malloc(nsegs * 3 *
sizeof(
int));
2766 int n_maxvertex = 0;
2767 for (
int imseg = 0; imseg < nsegs; imseg++) {
2771 n_maxvertex += pgd->n_points;
2775 wxPoint2DDouble *pPoints =
2776 (wxPoint2DDouble *)malloc(n_maxvertex *
sizeof(wxPoint2DDouble));
2781 int lon_max, lat_max, lon_min, lat_min;
2786 int n_max_points = -1;
2788 for (
int iseg = 0; iseg < nsegs; iseg++) {
2789 int type_seg = psegs->segment_usage;
2796 int npoints = pgd->n_points;
2799 n_max_points = wxMax(n_max_points, npoints);
2801 if (((type_seg & 4) != 4)) {
2802 for (
int j = 0; j < npoints; j++) {
2803 lon_max = wxMax(lon_max, rseg[j].x);
2804 lon_min = wxMin(lon_min, rseg[j].x);
2805 lat_max = wxMax(lat_max, rseg[j].y);
2806 lat_min = wxMin(lat_min, rseg[j].y);
2808 pPoints[ip].m_x = rseg[j].x;
2809 pPoints[ip].m_y = rseg[j].y;
2814 else if ((type_seg & 4) == 4)
2816 for (
int j = npoints - 1; j >= 0; j--) {
2817 lon_max = wxMax(lon_max, rseg[j].x);
2818 lon_min = wxMin(lon_min, rseg[j].x);
2819 lat_max = wxMax(lat_max, rseg[j].y);
2820 lat_min = wxMin(lat_min, rseg[j].y);
2822 pPoints[ip].m_x = rseg[j].x;
2823 pPoints[ip].m_y = rseg[j].y;
2828 ret_ptr->pvector_index[iseg * 3 + 0] =
2830 ret_ptr->pvector_index[iseg * 3 + 1] =
2831 pgd->index + m_current_cell_vearray_offset;
2832 ret_ptr->pvector_index[iseg * 3 + 2] =
2837 ret_ptr->n_max_edge_points = n_max_points;
2839 ret_ptr->vertex_array = pPoints;
2840 ret_ptr->n_max_vertex = n_maxvertex;
2842 ret_ptr->pogrGeom = NULL;
2844 ret_ptr->xmin = lon_min;
2845 ret_ptr->xmax = lon_max;
2846 ret_ptr->ymin = lat_min;
2847 ret_ptr->ymax = lat_max;
2855 int npoints = pgd->n_points;
2858 OGRMultiPoint *pSMP =
new OGRMultiPoint;
2862 for (
int ip = 0; ip < npoints; ip++) {
2867 zp = double(z - 12000);
2871 OGRPoint *ppoint =
new OGRPoint(rseg[ip].x, rseg[ip].y, zp);
2872 pSMP->addGeometryDirectly(ppoint);
2874 lon_max = wxMax(lon_max, rseg[ip].x);
2875 lon_min = wxMin(lon_min, rseg[ip].x);
2876 lat_max = wxMax(lat_max, rseg[ip].y);
2877 lat_min = wxMin(lat_min, rseg[ip].y);
2880 ret_ptr->pogrGeom = pSMP;
2882 ret_ptr->xmin = lon_min;
2883 ret_ptr->xmax = lon_max;
2884 ret_ptr->ymin = lat_min;
2885 ret_ptr->ymax = lat_max;
2895 wxPrintf(_T (
"Unexpected geomtype %d for Feature %d\n" ), geomtype,
2905void cm93chart::Transform(
cm93_point *s,
double trans_x,
double trans_y,
2906 double *lat,
double *lon) {
2908 double valx = (s->x * m_CIB.transform_x_rate) + m_CIB.transform_x_origin;
2909 double valy = (s->y * m_CIB.transform_y_rate) + m_CIB.transform_y_origin;
2917 (2.0 * atan(exp(valy / CM93_semimajor_axis_meters)) - PI / 2.) / DEGREE;
2918 *lon = (valx / (DEGREE * CM93_semimajor_axis_meters));
2923 m_block = (
unsigned char *)
block;
2927unsigned char *cm93_attr_block::GetNextAttr() {
2929 unsigned char *ret_val = m_block + m_cptr;
2933 unsigned char iattr = *(m_block + m_cptr);
2937 char vtype = m_pDict->GetAttrType(iattr);
2950 while (*(m_block + m_cptr)) m_cptr++;
2967 while (*(m_block + m_cptr)) m_cptr++;
2973 unsigned char nl = *(m_block + m_cptr);
3000wxString ParseSLGTA(wxString &val) {
3005 wxStringTokenizer tkz(val, wxT(
"|"));
3007 s = tkz.GetNextToken();
3008 s = tkz.GetNextToken();
3009 s = tkz.GetNextToken();
3012 wxString sc, st, sp;
3025 else if (s[0] ==
'G') {
3028 }
else if (s.Mid(0, 3) == _T (
"W/O" )) {
3034 }
else if (s.Mid(0, 5) == _T (
"LIGHT" )) {
3039 if (val.Find(_T (
"Spar" )) != wxNOT_FOUND) {
3043 if (val.Find(_T (
"SPAR" )) != wxNOT_FOUND) {
3048 if ((type == 2) && (color == 3))
3055 sprintf(line,
" %s (%c) = %s",
"COLOUR",
'I', (
const char *)sc.mb_str());
3056 result += wxString(line, wxConvUTF8);
3059 sprintf(line,
" %s (%c) = %s",
"BOYSHP",
'I',
"4");
3060 result += wxString(line, wxConvUTF8);
3066 sprintf(line,
" %s (%c) = %s",
"BOYSHP",
'I', (
const char *)st.mb_str());
3067 result += wxString(line, wxConvUTF8);
3070 sprintf(line,
" %s (%c) = %s",
"COLOUR",
'I',
"2");
3071 result += wxString(line, wxConvUTF8);
3077 sprintf(line,
" %s (%c) = %s",
"COLPAT",
'I', (
const char *)sp.mb_str());
3078 result += wxString(line, wxConvUTF8);
3085wxString ParseTEXTA(wxString &val) {
3089 if (val.Contains(_T (
"WK S" ))) {
3090 sprintf(line,
" %s (%c) = %s",
"WRKATT",
'I',
"1");
3091 result += wxString(line, wxConvUTF8);
3098void cm93chart::translate_colmar(
const wxString &sclass,
3099 S57attVal *pattValTmp) {
3100 int *pcur_attr = (
int *)pattValTmp->value;
3101 int cur_attr = *pcur_attr;
3107 lstring = _T (
"4" );
3110 lstring = _T (
"2" );
3113 lstring = _T (
"3" );
3116 lstring = _T (
"6" );
3119 lstring = _T (
"1" );
3122 lstring = _T (
"11" );
3125 lstring = _T (
"2,6" );
3128 lstring = _T (
"2,6,2" );
3131 lstring = _T (
"6,2" );
3134 lstring = _T (
"6,2,6" );
3137 lstring = _T (
"3,1" );
3140 lstring = _T (
"4,3,4" );
3143 lstring = _T (
"3,4,3" );
3146 lstring = _T (
"2,3,2" );
3149 lstring = _T (
"6,3,6" );
3152 lstring = _T (
"4,3" );
3155 lstring = _T (
"3,4" );
3158 lstring = _T (
"4,1" );
3164 if (lstring.Len()) {
3165 free(pattValTmp->value);
3167 pattValTmp->valType = OGR_STR;
3168 pattValTmp->value = strdup(lstring.mb_str());
3172S57Obj *cm93chart::CreateS57Obj(
int cell_index,
int iobject,
int subcell,
3174 Extended_Geometry *xgeom,
double ref_lat,
3175 double ref_lon,
double scale,
3176 double view_scale_ppm) {
3177#define MAX_HDR_LINE 4000
3181 int npub_year = 1993;
3183 int iclass = pobject->otype;
3184 int geomtype = pobject->geotype & 0x0f;
3186 double tmp_transform_x = 0.;
3187 double tmp_transform_y = 0.;
3190 double trans_WGS84_offset_x = 0.;
3191 double trans_WGS84_offset_y = 0.;
3193 wxString sclass = pDict->GetClassName(iclass);
3194 if (sclass == _T (
"Unknown" )) {
3196 msg.Printf(_T (
" CM93 Error...object type %d not found in CM93OBJ.DIC" ),
3203 wxString sclass_sub = sclass;
3206 if (sclass.IsSameAs(_T (
"ITDARE" ))) sclass_sub = _T (
"DEPARE" );
3208 if (sclass.IsSameAs(_T (
"_m_sor" ))) sclass_sub = _T (
"M_COVR" );
3210 if (sclass.IsSameAs(_T (
"SPOGRD" ))) sclass_sub = _T (
"DMPGRD" );
3212 if (sclass.IsSameAs(_T (
"FSHHAV" ))) sclass_sub = _T (
"FSHFAC" );
3214 if (sclass.IsSameAs(_T (
"OFSPRD" ))) sclass_sub = _T (
"CTNARE" );
3217 S57Obj *pobj =
new S57Obj();
3219 pobj->Index = iobject;
3222 strncpy(u, sclass_sub.mb_str(), 199);
3224 memcpy(pobj->FeatureName, u, 7);
3226 pobj->attVal =
new wxArrayOfS57attVal();
3230 for (
int jattr = 0; jattr < pobject->n_attributes; jattr++) {
3231 unsigned char *curr_attr = pab.GetNextAttr();
3233 unsigned char iattr = *curr_attr;
3235 wxString sattr = pDict->GetAttrName(iattr);
3237 char vtype = pDict->GetAttrType(iattr);
3239 unsigned char *aval = curr_attr + 1;
3253 S57attVal *pattValTmp =
new S57attVal;
3258 pAVI = (
int *)malloc(
sizeof(
int));
3260 pattValTmp->valType = OGR_INT;
3261 pattValTmp->value = pAVI;
3264 pb = (
unsigned char *)aval;
3265 pAVI = (
int *)malloc(
sizeof(
int));
3267 pattValTmp->valType = OGR_INT;
3268 pattValTmp->value = pAVI;
3271 pw = (
unsigned short *)aval;
3275 pAVR = (
double *)malloc(
sizeof(
double));
3276 *pAVR = dival / 10.;
3277 pattValTmp->valType = OGR_REAL;
3278 pattValTmp->value = pAVR;
3282 pAVI = (
int *)malloc(
sizeof(
int));
3284 pattValTmp->valType = OGR_INT;
3285 pattValTmp->value = pAVI;
3289 pAVS = strdup((
char*)aval);
3290 pattValTmp->valType = OGR_STR;
3291 pattValTmp->value = pAVS;
3295 pAVS = strdup((
const char*)&aval[3]);
3296 pattValTmp->valType = OGR_STR;
3297 pattValTmp->value = pAVS;
3300 pb = (
unsigned char *)aval;
3301 unsigned char nl = *pb++;
3304 for (
int i = 0; i < nl; i++) {
3305 sprintf(vi,
"%d,", *pb++);
3308 if (strlen(val)) val[strlen(val) - 1] = 0;
3311 pattValTmp->valType = OGR_STR;
3312 pattValTmp->value = pAVS;
3316 pAVR = (
double *)malloc(
sizeof(
double));
3320 float __attribute__((aligned(16))) tf1;
3321 unsigned char *pucf = (
unsigned char *)pf;
3323 memcpy(&tf1, pucf, sizeof(
float));
3329 pattValTmp->valType = OGR_REAL;
3330 pattValTmp->value = pAVR;
3338 if (sattr.IsSameAs(_T (
"COLMAR" ))) {
3339 translate_colmar(sclass, pattValTmp);
3340 sattr = _T (
"COLOUR" );
3344 if (pattValTmp->valType == OGR_INT &&
3345 (sattr.IsSameAs(_T (
"QUASOU" )) || sattr.IsSameAs(_T (
"CATLIT" )))) {
3346 int v = *(
int *)pattValTmp->value;
3347 free(pattValTmp->value);
3348 sprintf(val,
"%d", v);
3350 pattValTmp->valType = OGR_STR;
3351 pattValTmp->value = pAVS;
3355 if (sclass.IsSameAs(_T (
"$AREAS" )) && (vtype ==
'S') &&
3356 sattr.IsSameAs(_T (
"$SCODE" ))) {
3357 if (!strcmp((
char *)pattValTmp->value,
"II25")) {
3358 free(pattValTmp->value);
3359 pattValTmp->value = strdup(
"BACKGROUND");
3364 if (sattr.IsSameAs(_T (
"RECDAT" )) || sattr.IsSameAs(_T (
"_dgdat" ))) {
3365 if (sclass_sub.IsSameAs(_T (
"M_COVR" )) && (vtype ==
'S')) {
3366 wxString pub_date((
char *)pattValTmp->value, wxConvUTF8);
3369 upd.ParseFormat(pub_date, _T (
"%Y%m%d" ));
3370 if (!upd.IsValid()) upd.ParseFormat(_T (
"20000101" ), _T (
"%Y%m%d" ));
3373 pub_date.Truncate(4);
3376 pub_date.ToLong(&nyear);
3382 if (sclass_sub.IsSameAs(_T (
"M_COVR" )) && (vtype ==
'R')) {
3383 if (sattr.IsSameAs(_T (
"_wgsox" ))) {
3384 tmp_transform_x = *(
double *)pattValTmp->value;
3385 if (fabs(tmp_transform_x) > 1.0)
3386 m_CIB.b_have_offsets =
true;
3387 }
else if (sattr.IsSameAs(_T (
"_wgsoy" ))) {
3388 tmp_transform_y = *(
double *)pattValTmp->value;
3389 if (fabs(tmp_transform_y) > 1.0) m_CIB.b_have_offsets =
true;
3394 wxASSERT(sattr.Len() == 6);
3395 wxCharBuffer dbuffer = sattr.ToUTF8();
3396 if (dbuffer.data()) {
3398 (
char *)realloc(pobj->att_array, 6 * (pobj->n_attr + 1));
3400 strncpy(pobj->att_array + (6 *
sizeof(
char) * pobj->n_attr),
3404 pobj->attVal->Add(pattValTmp);
3418 if (1 == geomtype) {
3419 if ((!strncmp(pobj->FeatureName,
"LIT", 3)) ||
3420 (!strncmp(pobj->FeatureName,
"LIGHTS", 6)) ||
3421 (!strncmp(pobj->FeatureName,
"BCN", 3)) ||
3422 (!strncmp(pobj->FeatureName,
"_slgto", 6)) ||
3423 (!strncmp(pobj->FeatureName,
"_boygn", 6)) ||
3424 (!strncmp(pobj->FeatureName,
"_bcngn", 6)) ||
3425 (!strncmp(pobj->FeatureName,
"_extgn", 6)) ||
3426 (!strncmp(pobj->FeatureName,
"TOWERS", 6)) ||
3427 (!strncmp(pobj->FeatureName,
"BOY", 3))) {
3428 bool bfound_OBJNAM = (pobj->GetAttributeIndex(
"OBJNAM") != -1);
3429 bool bfound_INFORM = (pobj->GetAttributeIndex(
"INFORM") != -1);
3431 if ((!bfound_OBJNAM) && (bfound_INFORM))
3433 char *patl = pobj->att_array;
3434 for (
int i = 0; i < pobj->n_attr; i++) {
3435 if (!strncmp(patl,
"INFORM", 6)) {
3436 memcpy(patl,
"OBJNAM", 6);
3448 pobj->Primitive_type = GEO_AREA;
3451 if (sclass_sub.IsSameAs(_T (
"M_COVR" ))) {
3455 GetCoverSet()->Find_MCD(cell_index, iobject, subcell);
3456 if (NULL == pmcd_look)
3463 pmcd->m_cell_index = cell_index;
3464 pmcd->m_object_id = iobject;
3465 pmcd->m_subcell = subcell;
3468 pmcd->user_xoff = 0;
3469 pmcd->user_yoff = 0;
3470 pmcd->m_buser_offsets =
false;
3473 pmcd->m_npub_year = npub_year;
3476 int npta = xgeom->contour_array[0];
3477 float_2Dpt *geoPt =
new float_2Dpt[npta + 2];
3478 float_2Dpt *ppt = geoPt;
3480 pmcd->m_covr_lon_max = -1000.;
3481 pmcd->m_covr_lon_min = 1000.;
3482 pmcd->m_covr_lat_max = -1000.;
3483 pmcd->m_covr_lat_min = 1000.;
3487 for (
int ip = 0; ip < npta; ip++) {
3489 p.x = (int)xgeom->vertex_array[ip + 1].m_x;
3490 p.y = (
int)xgeom->vertex_array[ip + 1].m_y;
3492 Transform(&p, 0, 0, &lat,
3497 pmcd->m_covr_lon_max = wxMax(pmcd->m_covr_lon_max, lon);
3498 pmcd->m_covr_lon_min = wxMin(pmcd->m_covr_lon_min, lon);
3499 pmcd->m_covr_lat_max = wxMax(pmcd->m_covr_lat_max, lat);
3500 pmcd->m_covr_lat_min = wxMin(pmcd->m_covr_lat_min, lat);
3504 pmcd->m_nvertices = npta;
3505 pmcd->pvertices = geoPt;
3507 pmcd->m_covr_bbox.Set(pmcd->m_covr_lat_min, pmcd->m_covr_lon_min,
3508 pmcd->m_covr_lat_max, pmcd->m_covr_lon_max);
3512 pmcd->transform_WGS84_offset_x = tmp_transform_x;
3513 pmcd->transform_WGS84_offset_y = tmp_transform_y;
3515 pmcd->m_centerlat_cos = cos(
3516 ((pmcd->m_covr_lat_min + pmcd->m_covr_lat_max) / 2.) * PI / 180.);
3519 GetCoverSet()->Add_Update_MCD(pmcd);
3524 if (pmcd_look->m_buser_offsets) {
3525 m_CIB.b_have_user_offsets =
true;
3527 m_CIB.user_xoff = pmcd_look->user_xoff;
3528 m_CIB.user_yoff = pmcd_look->user_yoff;
3535 m_pcovr_array_loaded.Add(pmcd);
3538 unsigned int n = pmcd->m_nvertices;
3539 double *pts =
new double[2 * n];
3542 for (
size_t i = 0; i < 2 * n; i++)
3543 pts[i] = ((
float *)pmcd->pvertices)[i];
3547 if (LLRegion::PointsCCW(n, pts))
3548 for (
size_t i = 0; i < n; i++)
3549 if (pts[2 * i + 1] < 0) pts[2 * i + 1] += 360;
3552 LLRegion rgn_covr(n, pts);
3553 m_region.Union(rgn_covr);
3561 m_CIB.m_cell_mcovr_list.Append(pmcd);
3565 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3566 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3569 pobj->m_n_lsindex = xgeom->n_vector_indices;
3570 pobj->m_lsindex_array =
3571 xgeom->pvector_index;
3572 pobj->m_n_edge_max_points = 0;
3575 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3578 pc.x = (
short unsigned int)pobj->x;
3579 pc.y = (
short unsigned int)pobj->y;
3580 Transform(&pc, 0., 0., &latc, &lonc);
3582 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(latc, lonc);
3584 trans_WGS84_offset_x = pmcd->user_xoff;
3585 trans_WGS84_offset_y = pmcd->user_yoff;
3590 double lat1, lon1, lat2, lon2;
3593 p.x = (int)xgeom->xmin;
3594 p.y = (
int)xgeom->ymin;
3595 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3596 xgeom->ref_lat = lat1;
3597 xgeom->ref_lon = lon1;
3599 p.x = (int)xgeom->xmax;
3600 p.y = (
int)xgeom->ymax;
3601 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat2, &lon2);
3602 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3607 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3615 xgeom->x_rate = m_CIB.transform_x_rate;
3616 xgeom->x_offset = m_CIB.transform_x_origin - trans_WGS84_offset_x;
3617 xgeom->y_rate = m_CIB.transform_y_rate;
3618 xgeom->y_offset = m_CIB.transform_y_origin - trans_WGS84_offset_y;
3620 pobj->pPolyTessGeo =
new PolyTessGeo(xgeom);
3627 pobj->Primitive_type = GEO_POINT;
3630 pobj->x = xgeom->pointx;
3631 pobj->y = xgeom->pointy;
3635 p.x = xgeom->pointx;
3636 p.y = xgeom->pointy;
3637 Transform(&p, 0., 0., &lat, &lon);
3640 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3641 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(lat, lon);
3643 trans_WGS84_offset_x = pmcd->user_xoff;
3644 trans_WGS84_offset_y = pmcd->user_yoff;
3649 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat, &lon);
3659 double llsize = 1e-3 / view_scale_ppm;
3661 pobj->BBObj.Set(lat, lon, lat, lon);
3662 pobj->BBObj.EnLarge(llsize);
3669 pobj->Primitive_type = GEO_POINT;
3672 double lat1, lon1, lat2, lon2;
3675 p.x = (int)xgeom->xmin;
3676 p.y = (
int)xgeom->ymin;
3677 Transform(&p, 0., 0., &lat1, &lon1);
3679 p.x = (int)xgeom->xmax;
3680 p.y = (
int)xgeom->ymax;
3681 Transform(&p, 0., 0., &lat2, &lon2);
3682 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3685 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3686 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3688 OGRMultiPoint *pGeo = (OGRMultiPoint *)xgeom->pogrGeom;
3689 pobj->npt = pGeo->getNumGeometries();
3691 pobj->geoPtz = (
double *)malloc(pobj->npt * 3 *
sizeof(
double));
3692 pobj->geoPtMulti = (
double *)malloc(pobj->npt * 2 *
sizeof(
double));
3694 double *pdd = pobj->geoPtz;
3695 double *pdl = pobj->geoPtMulti;
3697 for (
int ip = 0; ip < pobj->npt; ip++) {
3698 OGRPoint *ppt = (OGRPoint *)(pGeo->getGeometryRef(ip));
3701 p.x = (int)ppt->getX();
3702 p.y = (int)ppt->getY();
3703 double depth = ppt->getZ();
3708 double snd_trans_x = 0.;
3709 double snd_trans_y = 0.;
3712 if (m_CIB.b_have_user_offsets) {
3714 Transform(&p, 0., 0., &lats, &lons);
3716 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(lats, lons);
3719 snd_trans_x = pmcd->user_xoff;
3720 snd_trans_y = pmcd->user_yoff;
3724 east -= pmcd->user_xoff / m_CIB.transform_x_rate;
3725 north -= pmcd->user_yoff / m_CIB.transform_y_rate;
3735 Transform(&p, snd_trans_x, snd_trans_y, &lat1, &lon1);
3743 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3753 pobj->Primitive_type = GEO_LINE;
3755 pobj->npt = xgeom->n_max_vertex;
3756 pobj->geoPt = (pt *)xgeom->vertex_array;
3757 xgeom->vertex_array = NULL;
3760 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3761 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3764 pobj->m_n_lsindex = xgeom->n_vector_indices;
3765 pobj->m_lsindex_array =
3766 xgeom->pvector_index;
3767 pobj->m_n_edge_max_points = 0;
3770 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3773 pc.x = (
short unsigned int)pobj->x;
3774 pc.y = (
short unsigned int)pobj->y;
3775 Transform(&pc, 0., 0., &latc, &lonc);
3777 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(latc, lonc);
3779 trans_WGS84_offset_x = pmcd->user_xoff;
3780 trans_WGS84_offset_y = pmcd->user_yoff;
3785 double lat1, lon1, lat2, lon2;
3788 p.x = (int)xgeom->xmin;
3789 p.y = (
int)xgeom->ymin;
3790 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3792 p.x = (int)xgeom->xmax;
3793 p.y = (
int)xgeom->ymax;
3794 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat2, &lon2);
3795 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3800 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3809 pobj->Primitive_type = GEO_PRIM;
3816 if (!strncmp(pobj->FeatureName,
"OBSTRN", 6) ||
3817 !strncmp(pobj->FeatureName,
"WRECKS", 6) ||
3818 !strncmp(pobj->FeatureName,
"DEPCNT", 6) ||
3819 !strncmp(pobj->FeatureName,
"UWTROC", 6)) {
3820 pobj->m_bcategory_mutable =
true;
3822 pobj->m_bcategory_mutable =
false;
3835 if (geomtype != 4)
delete xgeom;
3839 m_CIB.transform_x_rate *
3840 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3842 m_CIB.transform_y_rate *
3843 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3845 m_CIB.transform_x_origin *
3846 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3848 m_CIB.transform_y_origin *
3849 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3853 pobj->x_origin -= trans_WGS84_offset_x;
3854 pobj->y_origin -= trans_WGS84_offset_y;
3857 pobj->auxParm3 = CHART_TYPE_CM93;
3863M_COVR_Desc *cm93chart::FindM_COVR_InWorkingSet(
double lat,
double lon) {
3866 if (m_CIB.m_cell_mcovr_list.GetCount() == 1) {
3867 wxList_Of_M_COVR_DescNode *node0 = m_CIB.m_cell_mcovr_list.GetFirst();
3868 if (node0) ret = node0->GetData();
3870 wxList_Of_M_COVR_DescNode *node = m_CIB.m_cell_mcovr_list.GetFirst();
3874 if (G_PtInPolygon_FL(pmcd->pvertices, pmcd->m_nvertices, lon, lat)) {
3879 node = node->GetNext();
3887wxPoint2DDouble cm93chart::FindM_COVROffset(
double lat,
double lon) {
3888 wxPoint2DDouble ret(0., 0.);
3891 wxList_Of_M_COVR_DescNode *node0 = m_CIB.m_cell_mcovr_list.GetFirst();
3894 ret.m_x = pmcd0->transform_WGS84_offset_x;
3895 ret.m_y = pmcd0->transform_WGS84_offset_y;
3899 if (m_CIB.m_cell_mcovr_list.GetCount() > 1) {
3900 wxList_Of_M_COVR_DescNode *node = m_CIB.m_cell_mcovr_list.GetFirst();
3904 if (G_PtInPolygon_FL(pmcd->pvertices, pmcd->m_nvertices, lon, lat)) {
3905 ret.m_x = pmcd->transform_WGS84_offset_x;
3906 ret.m_y = pmcd->transform_WGS84_offset_y;
3910 node = node->GetNext();
3918InitReturn cm93chart::CreateHeaderDataFromCM93Cell(
void) {
3920 wxFileName fn(m_FullPath);
3921 wxString ext = fn.GetExt();
3924 switch ((ext.mb_str())[(
size_t)0]) {
3954 m_Chart_Scale =
scale;
3960 switch (m_Chart_Scale) {
3962 bproc = m_pManager->m_bfoundZ;
3965 bproc = m_pManager->m_bfoundA;
3968 bproc = m_pManager->m_bfoundB;
3971 bproc = m_pManager->m_bfoundC;
3974 bproc = m_pManager->m_bfoundD;
3977 bproc = m_pManager->m_bfoundE;
3980 bproc = m_pManager->m_bfoundF;
3983 bproc = m_pManager->m_bfoundG;
3987 if (bproc)
return INIT_FAIL_NOERROR;
3990 switch (m_Chart_Scale) {
3992 m_pManager->m_bfoundZ =
true;
3995 m_pManager->m_bfoundA =
true;
3998 m_pManager->m_bfoundB =
true;
4001 m_pManager->m_bfoundC =
true;
4004 m_pManager->m_bfoundD =
true;
4007 m_pManager->m_bfoundE =
true;
4010 m_pManager->m_bfoundF =
true;
4013 m_pManager->m_bfoundG =
true;
4019 m_FullExtent.ELON = 179.0;
4020 m_FullExtent.WLON = -179.0;
4021 m_FullExtent.NLAT = 80.0;
4022 m_FullExtent.SLAT = -80.0;
4023 m_bExtentSet =
true;
4027 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
4028 *m_pCOVRTablePoints = 4;
4029 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
4030 float *pf = (
float *)malloc(2 * 4 *
sizeof(
float));
4034 *pfe++ = m_FullExtent.NLAT;
4035 *pfe++ = m_FullExtent.WLON;
4037 *pfe++ = m_FullExtent.NLAT;
4038 *pfe++ = m_FullExtent.ELON;
4040 *pfe++ = m_FullExtent.SLAT;
4041 *pfe++ = m_FullExtent.ELON;
4043 *pfe++ = m_FullExtent.SLAT;
4044 *pfe++ = m_FullExtent.WLON;
4049void cm93chart::ProcessMCOVRObjects(
int cell_index,
char subcell) {
4052 Object *pobject = m_CIB.pobject_block;
4055 while (iObj < m_CIB.m_nfeature_records) {
4056 if ((pobject != NULL)) {
4058 int iclass = pobject->otype;
4060 wxString sclass = m_pDict->GetClassName(iclass);
4062 if (sclass.IsSameAs(_T (
"_m_sor" ))) {
4064 m_pcovr_set->Find_MCD(cell_index, iObj, (
int)subcell);
4066 Extended_Geometry *xgeom = BuildGeom(pobject, NULL, iObj);
4070 double tmp_transform_x = 0.;
4071 double tmp_transform_y = 0.;
4074 for (
int jattr = 0; jattr < pobject->n_attributes; jattr++) {
4075 unsigned char *curr_attr = pab.GetNextAttr();
4076 unsigned char iattr = *curr_attr;
4077 wxString sattr = m_pDict->GetAttrName(iattr);
4078 char vtype = m_pDict->GetAttrType(iattr);
4079 unsigned char *aval = curr_attr + 1;
4082 float *pf = (
float *)aval;
4084 float __attribute__((aligned(16))) tf1;
4085 unsigned char *pucf = (
unsigned char *)pf;
4086 memcpy(&tf1, pucf, sizeof(
float));
4087 if (sattr.IsSameAs(_T ( "_wgsox" )))
4088 tmp_transform_x = tf1;
4089 else if (sattr.IsSameAs(_T ( "_wgsoy" )))
4090 tmp_transform_y = tf1;
4092 if (sattr.IsSameAs(_T (
"_wgsox" )))
4093 tmp_transform_x = *pf;
4094 else if (sattr.IsSameAs(_T (
"_wgsoy" )))
4095 tmp_transform_y = *pf;
4101 if (NULL != xgeom) {
4107 pmcd->m_cell_index = cell_index;
4108 pmcd->m_object_id = iObj;
4109 pmcd->m_subcell = (int)subcell;
4112 int npta = xgeom->contour_array[0];
4113 float_2Dpt *geoPt =
new float_2Dpt[npta + 2];
4114 float_2Dpt *ppt = geoPt;
4118 pmcd->m_covr_lon_max = -1000.;
4119 pmcd->m_covr_lon_min = 1000.;
4120 pmcd->m_covr_lat_max = -1000.;
4121 pmcd->m_covr_lat_min = 1000.;
4123 for (
int ip = 0; ip < npta; ip++) {
4125 p.x = (int)xgeom->vertex_array[ip + 1].m_x;
4126 p.y = (
int)xgeom->vertex_array[ip + 1].m_y;
4128 Transform(&p, 0., 0., &lat, &lon);
4132 pmcd->m_covr_lon_max = wxMax(pmcd->m_covr_lon_max, lon);
4133 pmcd->m_covr_lon_min = wxMin(pmcd->m_covr_lon_min, lon);
4134 pmcd->m_covr_lat_max = wxMax(pmcd->m_covr_lat_max, lat);
4135 pmcd->m_covr_lat_min = wxMin(pmcd->m_covr_lat_min, lat);
4139 pmcd->m_nvertices = npta;
4140 pmcd->pvertices = geoPt;
4142 pmcd->m_covr_bbox.Set(pmcd->m_covr_lat_min, pmcd->m_covr_lon_min,
4143 pmcd->m_covr_lat_max, pmcd->m_covr_lon_max);
4147 pmcd->transform_WGS84_offset_x = tmp_transform_x;
4148 pmcd->transform_WGS84_offset_y = tmp_transform_y;
4150 pmcd->m_centerlat_cos =
4151 cos(((pmcd->m_covr_lat_min + pmcd->m_covr_lat_max) / 2.) * PI /
4155 m_pcovr_set->Add_Update_MCD(pmcd);
4158 free(xgeom->pvector_index);
4174bool cm93chart::UpdateCovrSet(
ViewPort *vpt) {
4176 std::vector<int> vpcells = GetVPCellArray(*vpt);
4181 for (
unsigned int i = 0; i < vpcells.size(); i++) {
4184 if (!m_pcovr_set->IsCovrLoaded(vpcells[i])) {
4185 if (loadcell_in_sequence(vpcells[i],
'0')) {
4186 ProcessMCOVRObjects(vpcells[i],
'0');
4189 m_pcovr_set->m_cell_hash[vpcells[i]] = 1;
4191 char loadcell_key =
'A';
4195 while (loadcell_in_sequence(vpcells[i], loadcell_key)) {
4198 ProcessMCOVRObjects(vpcells[i], loadcell_key);
4211bool cm93chart::IsPointInLoadedM_COVR(
double xc,
double yc) {
4214 return m_region.Contains(yc, xc);
4216 for (
unsigned int im = 0; im < m_pcovr_array_loaded.GetCount(); im++) {
4217 if (G_PtInPolygon_FL(m_pcovr_array_loaded[im]->pvertices,
4218 m_pcovr_array_loaded[im]->m_nvertices, xc, yc))
4225LLRegion cm93chart::GetValidRegion() {
return m_region; }
4227int cm93chart::loadcell_in_sequence(
int cellindex,
char subcell) {
4228 int rv = loadsubcell(cellindex, subcell);
4233int cm93chart::loadsubcell(
int cellindex, wxChar sub_char) {
4236 int ilat = cellindex / 10000;
4237 int ilon = cellindex % 10000;
4240 double dlat = m_dval / 3.;
4241 double dlon = m_dval / 3.;
4243 Get_CM93_Cell_Origin(cellindex, GetNativeScale(), &lat, &lon);
4245 "\n Attempting loadcell %d scale %lc, sub_char %lc at lat: %g/%g "
4247 cellindex, wxChar(m_scalechar[0]), sub_char, lat, lat + dlat, lon,
4251 int jlat = (int)(((ilat - 30) / m_dval) * m_dval) + 30;
4252 int jlon = (int)((ilon / m_dval) * m_dval);
4254 int ilatroot = (((ilat - 30) / 60) * 60) + 30;
4255 int ilonroot = (ilon / 60) * 60;
4258 file.Printf(_T (
"%04d%04d." ), jlat, jlon);
4259 file += m_scalechar;
4268 bool b_useNoFind =
true;
4269 if (m_noFindArray.GetCount() > 500) b_useNoFind =
false;
4272 fileroot.Printf(_T (
"%04d%04d" ), ilatroot, ilonroot);
4273 appendOSDirSep(&fileroot);
4274 fileroot.append(m_scalechar);
4275 appendOSDirSep(&fileroot);
4276 wxString key = fileroot;
4278 fileroot.Prepend(m_prefix);
4280 file.Prepend(fileroot);
4284 strncpy(sfile, file.mb_str(), 199);
4286 printf(
" filename: %s\n", sfile);
4289 bool bfound =
false;
4292 if (m_noFindArray.Index(key) == wxNOT_FOUND) {
4293 if (::wxFileExists(file))
4296 m_noFindArray.Add(key);
4299 if (::wxFileExists(file)) bfound =
true;
4305 if (m_noFindArray.Index(key + _T(
".xz")) == wxNOT_FOUND) {
4306 if (::wxFileExists(file + _T(
".xz"))) {
4307 compfile = file + _T(
".xz");
4310 m_noFindArray.Add(key + _T(
".xz"));
4313 if (::wxFileExists(file + _T(
".xz"))) compfile = file + _T(
".xz");
4318 if (!bfound && !compfile.Length()) {
4320 wxString new_scalechar = m_scalechar.Lower();
4323 file1.Printf(_T (
"%04d%04d." ), jlat, jlon);
4324 file1 += new_scalechar;
4325 file1[0] = sub_char;
4327 fileroot.Printf(_T (
"%04d%04d" ), ilatroot, ilonroot);
4328 appendOSDirSep(&fileroot);
4329 fileroot.append(new_scalechar);
4330 appendOSDirSep(&fileroot);
4334 fileroot.Prepend(m_prefix);
4336 file1.Prepend(fileroot);
4339 if (m_noFindArray.Index(key) == wxNOT_FOUND) {
4340 if (::wxFileExists(file1)) {
4344 m_noFindArray.Add(key);
4348 if (::wxFileExists(file1)) {
4356 if (m_noFindArray.Index(key + _T(
".xz")) == wxNOT_FOUND) {
4357 if (::wxFileExists(file1 + _T(
".xz")))
4358 compfile = file1 + _T(
".xz");
4360 m_noFindArray.Add(key + _T(
".xz"));
4363 if (::wxFileExists(file1 + _T(
".xz"))) compfile = file1 + _T(
".xz");
4369 printf(
"noFind count: %d\n", (
int)m_noFindArray.GetCount());
4372 if (!bfound && !compfile.Length())
return 0;
4376 wxString msg(_T (
"Loading CM93 cell " ));
4382 m_LastFileName = file;
4385 if (compfile.Length()) {
4386 file = wxFileName::CreateTempFileName(wxFileName(compfile).GetFullName());
4387 if (!DecompressXZFile(compfile, file)) {
4395 strncpy(str, msg.mb_str(), 255);
4397 printf(
" %s\n", str);
4401 if (!Ingest_CM93_Cell((
const char *)file.mb_str(), &m_CIB)) {
4402 wxString msg(_T (
" cm93chart Error ingesting " ));
4406 if (compfile.Length()) wxRemoveFile(file);
4410 if (compfile.Length()) wxRemoveFile(file);
4415void cm93chart::SetUserOffsets(
int cell_index,
int object_id,
int subcell,
4416 int xoff,
int yoff) {
4417 M_COVR_Desc *pmcd = GetCoverSet()->Find_MCD(cell_index, object_id, subcell);
4419 pmcd->user_xoff = xoff;
4420 pmcd->user_yoff = yoff;
4421 pmcd->m_buser_offsets =
true;
4425wxPoint *cm93chart::GetDrawBuffer(
int nSize) {
4427 if (nSize > m_nDrawBufferSize) {
4428 wxPoint *tmp = m_pDrawBuffer;
4430 (wxPoint *)realloc(m_pDrawBuffer,
sizeof(wxPoint) * (nSize + 1));
4431 if (NULL == m_pDrawBuffer) {
4435 m_nDrawBufferSize = nSize + 1;
4437 return m_pDrawBuffer;
4444cm93manager::cm93manager(
void) {
4457cm93manager::~cm93manager(
void) {
delete m_pcm93Dict; }
4459bool cm93manager::Loadcm93Dictionary(
const wxString &name) {
4462 m_pcm93Dict = FindAndLoadDict(name);
4465 wxLogMessage(_T (
" Cannot load CM93 Dictionary." ));
4469 if (!m_pcm93Dict->IsOk()) {
4470 wxLogMessage(_T (
" Error in loading CM93 Dictionary." ));
4476 }
else if (!m_pcm93Dict->IsOk()) {
4477 wxLogMessage(_T (
" CM93 Dictionary is not OK." ));
4491 wxFileName fn(file);
4492 wxString path = fn.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
4496 while (i < path.Len()) {
4497 target.Append(path[i]);
4498 if (path[i] == fn.GetPathSeparator()) {
4499 if (pdict->LoadDictionary(target)) {
4503 if (pdict->LoadDictionary(target + _T (
"CM93ATTR" ))) {
4512 strncpy(t, target.mb_str(), 99);
4514 if (retval == NULL)
delete pdict;
4522cm93compchart::cm93compchart() {
4523 m_ChartType = CHART_TYPE_CM93COMP;
4524 m_pDictComposite = NULL;
4527 m_FullPath = _T (
"CM93" );
4530 m_Description = _T (
"CM93Composite" );
4533 m_datum_str = _T (
"WGS84" );
4534 m_SoundingsDatum = _T (
"Unknown" );
4536 for (
int i = 0; i < 8; i++) m_pcm93chart_array[i] = NULL;
4538 m_pcm93chart_current = NULL;
4545 SetSpecialOutlineCellIndex(0, 0, 0);
4546 m_last_cell_adjustvp = NULL;
4551cm93compchart::~cm93compchart() {
4552 if (g_pCM93OffsetDialog) {
4553 g_pCM93OffsetDialog->Hide();
4556 for (
int i = 0; i < 8; i++)
delete m_pcm93chart_array[i];
4558 delete m_pDictComposite;
4563InitReturn cm93compchart::Init(
const wxString &name, ChartInitFlag flags) {
4566 wxFileName fn(name);
4572 if (!fn.FileExists()) {
4574 if (wxDir::Exists(name)) {
4576 appendOSDirSep(&target);
4578 appendOSDirSep(&path);
4580 wxString msg(_T (
" CM93Composite Chart Init cannot find " ));
4583 return INIT_FAIL_REMOVE;
4588 path = fn.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
4592 wxFileName file_path(path);
4593 file_path.RemoveLastDir();
4594 file_path.RemoveLastDir();
4596 target = file_path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
4599 m_prefixComposite = target;
4601 wxString msg(_T (
"CM93Composite Chart Root is " ));
4602 msg.Append(m_prefixComposite);
4605 if (flags == THUMB_ONLY) {
4611 if (flags == HEADER_ONLY)
return CreateHeaderData();
4614 if (!m_pDictComposite) {
4615 if (!m_pDictComposite)
4616 m_pDictComposite = FindAndLoadDictFromDir(path);
4618 if (!m_pDictComposite) {
4620 _T (
" CM93Composite Chart Init cannot locate CM93 dictionary." ));
4621 return INIT_FAIL_REMOVE;
4626 SetColorScheme(m_global_color_scheme,
false);
4628 bReadyToRender =
true;
4633void cm93compchart::Activate(
void) {
4660void cm93compchart::Deactivate(
void) {
4661 if (pPopupDetailSlider) {
4662 pPopupDetailSlider->Destroy();
4663 pPopupDetailSlider = NULL;
4667double scale_breaks[] = {
4682int cm93compchart::GetCMScaleFromVP(
const ViewPort &vpt) {
4683 double scale_mpp = 3000 / vpt.view_scale_ppm;
4685 double scale_mpp_adj = scale_mpp;
4687 double scale_breaks_adj[7];
4689 for (
int i = 0; i < 7; i++) scale_breaks_adj[i] = scale_breaks[i];
4691 if (g_cm93_zoom_factor) {
4694 double efactor = ( double ) ( g_cm93_zoom_factor ) * ( .176 / 7. );
4695 for (
int i=0 ; i < 7 ; i++ )
4697 double efr = efactor * ( 7 - i );
4698 scale_breaks_adj[i] = scale_breaks[i] * pow ( 10., efr );
4700 printf (
"g_cm93_zoom_factor: %2d efactor: %6g efr:%6g, scale_breaks[i]:%6g scale_breaks_adj[i]: %6g\n",
4701 g_cm93_zoom_factor, efactor, efr, scale_breaks[i], scale_breaks_adj[i] );
4705 double efr = (double)g_cm93_zoom_factor * pow(scale_mpp, -.05);
4706 scale_mpp_adj *= pow(.6, efr);
4710 int cmscale_calc = 7;
4712 while (cmscale_calc > 0) {
4713 if (scale_mpp_adj < scale_breaks_adj[brk_index])
break;
4720 double zoom_factor = scale_breaks[7 - cmscale_calc] / vpt.chart_scale;
4721 if (zoom_factor > 4.0) {
4722 if (cmscale_calc < 7) cmscale_calc++;
4725 return cmscale_calc;
4728void cm93compchart::SetVPParms(
const ViewPort &vpt) {
4731 int cmscale = GetCMScaleFromVP(vpt);
4732 m_cmscale = PrepareChartScale(vpt, cmscale,
false);
4736 if (m_pcm93chart_array[cmscale]) {
4737 if (!m_EdDate.IsValid() || !m_pcm93chart_array[cmscale]->GetEditionDate().IsValid() || m_pcm93chart_array[cmscale]->GetEditionDate().IsLaterThan(m_EdDate))
4738 m_EdDate = m_pcm93chart_array[cmscale]->GetEditionDate();
4742int cm93compchart::PrepareChartScale(
const ViewPort &vpt,
int cmscale,
4745 printf(
"\non SetVPParms, cmscale:%d, %c\n", cmscale,
4746 (
char)(
'A' + cmscale - 1));
4749 bool cellscale_is_useable =
false;
4750 bool b_nochart =
false;
4752 while (!cellscale_is_useable) {
4754 while (NULL == m_pcm93chart_array[cmscale]) {
4755 if (Is_CM93Cell_Present(m_prefixComposite, vpt.clat, vpt.clon, cmscale)) {
4757 printf(
" chart %c at VP clat/clon is present\n",
4758 (
char)(
'A' + cmscale - 1));
4760 m_pcm93chart_array[cmscale] =
new cm93chart();
4762 ext = (wxChar)(
'A' + cmscale - 1);
4763 if (cmscale == 0) ext =
'Z';
4765 wxString file_dummy = _T (
"CM93." );
4768 m_pcm93chart_array[cmscale]->SetCM93Dict(m_pDictComposite);
4769 m_pcm93chart_array[cmscale]->SetCM93Prefix(m_prefixComposite);
4770 m_pcm93chart_array[cmscale]->SetCM93Manager(m_pcm93mgr);
4772 m_pcm93chart_array[cmscale]->SetColorScheme(m_global_color_scheme);
4773 m_pcm93chart_array[cmscale]->Init(file_dummy, FULL_INIT);
4774 }
else if (cmscale == 0) {
4781 " CM93 finds no chart of any scale present at Lat/Lon %g %g\n",
4782 vpt.clat, vpt.clon);
4791 printf(
" no %c scale chart present, adjusting cmscale to %c\n",
4792 (
char)(
'A' + cmscale), (
char)(
'A' + cmscale - 1));
4796 m_pcm93chart_current = m_pcm93chart_array[cmscale];
4799 if (g_bDebugCM93) printf(
" b_nochart return\n");
4801 m_pcm93chart_current = NULL;
4802 for (
int i = 0; i < 8; i++) {
4803 delete m_pcm93chart_array[i];
4804 m_pcm93chart_array[i] = NULL;
4810 if (m_pcm93chart_current) {
4813 m_pcm93chart_current->SetVPParms(vpt);
4817 float yc = vpt.clat;
4818 float xc = vpt.clon;
4820 if (!m_pcm93chart_current->GetCoverSet()->GetCoverCount()) {
4822 printf(
" chart %c has no M_COVR\n", (
char)(
'A' + cmscale - 1));
4825 if (m_pcm93chart_current->IsPointInLoadedM_COVR(xc, yc)) {
4827 printf(
" chart %c contains clat/clon\n", (
char)(
'A' + cmscale - 1));
4829 cellscale_is_useable =
true;
4843 else if (vpt.b_quilt && vpt.b_FullScreenQuilt) {
4846 covr_set *pcover = m_pcm93chart_current->GetCoverSet();
4848 bool boverlap =
false;
4849 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
4852 if (!(vp.GetBBox().IntersectOut(mcd->m_covr_bbox))) {
4857 if (boverlap) cellscale_is_useable =
true;
4861 if (!cellscale_is_useable) {
4869 printf(
" VP is not in M_COVR, adjusting cmscale to %c\n",
4870 (
char)(
'A' + cmscale - 1));
4877 double zoom_factor = scale_breaks[7 - cmscale] / vpt.chart_scale;
4879 if (zoom_factor > 4.0) {
4882 float yc = vpt.clat;
4883 float xc = vpt.clon;
4886 FillScaleArray(vpt.clat, vpt.clon);
4887 int new_scale = cmscale;
4888 bool b_found =
false;
4889 while (new_scale <= 7) {
4890 if (m_bScale_Array[new_scale]) {
4891 double new_zoom_factor =
4892 scale_breaks[7 - new_scale] / vpt.chart_scale;
4895 if (new_zoom_factor < 1.0) {
4897 new_scale = cmscale;
4901 if (new_zoom_factor < 4.0) {
4902 if (NULL == m_pcm93chart_array[new_scale]) {
4903 m_pcm93chart_array[new_scale] =
new cm93chart();
4905 ext = (wxChar)(
'A' + new_scale - 1);
4906 if (new_scale == 0) ext =
'Z';
4908 wxString file_dummy = _T (
"CM93." );
4911 m_pcm93chart_array[new_scale]->SetCM93Dict(m_pDictComposite);
4912 m_pcm93chart_array[new_scale]->SetCM93Prefix(m_prefixComposite);
4913 m_pcm93chart_array[new_scale]->SetCM93Manager(m_pcm93mgr);
4915 m_pcm93chart_array[new_scale]->SetColorScheme(
4916 m_global_color_scheme);
4917 m_pcm93chart_array[new_scale]->Init(file_dummy, FULL_INIT);
4920 m_pcm93chart_array[new_scale]->SetVPParms(vpt);
4921 if (m_pcm93chart_array[new_scale]->IsPointInLoadedM_COVR(xc, yc)) {
4930 cmscale = new_scale;
4931 m_pcm93chart_current = m_pcm93chart_array[cmscale];
4941void cm93compchart::FillScaleArray(
double lat,
double lon) {
4942 for (
int cmscale = 0; cmscale < 8; cmscale++)
4943 m_bScale_Array[cmscale] =
4944 Is_CM93Cell_Present(m_prefixComposite, lat, lon, cmscale);
4950wxString cm93compchart::GetPubDate() {
4953 if (NULL != m_pcm93chart_current)
4955 data.Printf(_T (
"%4d" ), m_current_cell_pub_date);
4957 data = _T (
"????" );
4961int cm93compchart::GetNativeScale() {
4962 if (m_pcm93chart_current)
4963 return m_pcm93chart_current->GetNativeScale();
4968double cm93compchart::GetNormalScaleMin(
double canvas_scale_factor,
4969 bool b_allow_overzoom) {
4973 if (m_pcm93chart_current) {
4975 if (m_pcm93chart_current->m_last_vp.IsValid()) {
4976 FillScaleArray(m_pcm93chart_current->m_last_vp.clat,
4977 m_pcm93chart_current->m_last_vp.clon);
4981 while (cmscale > 0) {
4982 if (m_bScale_Array[cmscale])
break;
4990 return 20000000. / oz_factor;
4992 return 3000000. / oz_factor;
4994 return 1000000. / oz_factor;
4996 return 200000. / oz_factor;
4998 return 100000. / oz_factor;
5000 return 50000. / oz_factor;
5002 return 20000. / oz_factor;
5006 return 500. / oz_factor;
5012double cm93compchart::GetNormalScaleMax(
double canvas_scale_factor,
5014 return (180. / 360.) * PI * 2 *
5015 (WGS84_semimajor_axis_meters / (canvas_width / canvas_scale_factor));
5019wxPoint GetPixFromLLVP(
double lat,
double lon,
const ViewPort &VPoint) {
5021 double easting, northing;
5023 double s, y3, s0, y30;
5024 double z = WGS84_semimajor_axis_meters * mercator_k0;
5029 if (lon * VPoint.clon < 0.) {
5037 if (fabs(xlon - VPoint.clon) > 180.) {
5038 if (xlon > VPoint.clon)
5043 easting = (xlon - VPoint.clon) * DEGREE * z;
5045 s = sin(lat * DEGREE);
5046 y3 = (.5 * log((1 + s) / (1 - s))) * z;
5048 s0 = sin(VPoint.clat * DEGREE);
5049 y30 = (.5 * log((1 + s0) / (1 - s0))) * z;
5050 northing = y3 - y30;
5054 double epix = easting * VPoint.view_scale_ppm;
5055 double npix = northing * VPoint.view_scale_ppm;
5056 r.x = (int)round((VPoint.pix_width / 2) + epix);
5057 r.y = (int)round((VPoint.pix_height / 2) - npix);
5064void cm93compchart::GetValidCanvasRegion(
const ViewPort &VPoint,
5066 OCPNRegion screen_region(0, 0, VPoint.pix_width, VPoint.pix_height);
5068 VPoint, g_bopengl ? VPoint.rv_rect : screen_region);
5069 *pValidRegion = ret;
5072OCPNRegion cm93compchart::GetValidScreenCanvasRegion(
5080 if (m_pcm93chart_current) {
5081 int chart_native_scale = m_pcm93chart_current->GetNativeScale();
5083 for (
unsigned int im = 0;
5084 im < m_pcm93chart_current->m_pcovr_array_loaded.GetCount(); im++) {
5085 M_COVR_Desc *pmcd = (m_pcm93chart_current->m_pcovr_array_loaded[im]);
5090 if (vp.GetBBox().IntersectOut(pmcd->m_covr_bbox))
continue;
5092 wxPoint *DrawBuf = m_pcm93chart_current->GetDrawBuffer(pmcd->m_nvertices);
5094 OCPNRegion rgn_covr = vp.GetVPRegionIntersect(
5095 ScreenRegion, pmcd->m_nvertices, (
float *)pmcd->pvertices,
5096 chart_native_scale, DrawBuf);
5098 if (rgn_covr.IsOk())
5099 ret_region.Union(rgn_covr);
5108LLRegion cm93compchart::GetValidRegion() {
5109 if (m_pcm93chart_current)
return m_pcm93chart_current->GetValidRegion();
5114bool cm93compchart::RenderRegionViewOnGL(
const wxGLContext &glc,
5117 const LLRegion &Region) {
5120 if (g_pCM93OffsetDialog && g_pCM93OffsetDialog->IsShown())
5121 g_pCM93OffsetDialog->UpdateMCOVRList(VPoint);
5123 return DoRenderRegionViewOnGL(glc, VPoint, RectRegion, Region);
5126bool cm93compchart::DoRenderRegionViewOnGL(
const wxGLContext &glc,
5129 const LLRegion &Region) {
5136 bool render_return =
false;
5137 if (m_pcm93chart_current == 0)
return render_return;
5145 if (VPoint.b_quilt) {
5146 LLRegion vpr_empty = Region;
5147 LLRegion chart_region = GetValidRegion();
5166 if (!chart_region.Empty()) vpr_empty.Subtract(chart_region);
5168 if (!vpr_empty.Empty() &&
5172 int cmscale_save = m_cmscale;
5174 LLRegion region_vect[8];
5178 while (!vpr_empty.Empty() && m_cmscale) {
5180 m_cmscale = PrepareChartScale(vp, m_cmscale - 1,
false);
5182 if (m_pcm93chart_current) {
5183 LLRegion sscale_region = GetValidRegion();
5186 region_vect[m_cmscale] = sscale_region;
5187 region_vect[m_cmscale].Intersect(vpr_empty);
5190 vpr_empty.Subtract(sscale_region);
5197 for (
int i = 0; i < 8; i++) {
5198 if (!region_vect[i].Empty()) {
5199 m_cmscale = PrepareChartScale(vp, i,
false);
5200 if (m_pcm93chart_current)
5201 render_return |= m_pcm93chart_current->RenderRegionViewOnGL(
5202 glc, vp, RectRegion, region_vect[i]);
5207 m_cmscale = cmscale_save;
5208 m_pcm93chart_current = m_pcm93chart_array[m_cmscale];
5212 if (m_pcm93chart_current) {
5213 render_return |= m_pcm93chart_current->RenderRegionViewOnGL(
5214 glc, vp, RectRegion, Region);
5215 m_Name = m_pcm93chart_current->GetName();
5220 if (m_pcm93chart_current) {
5221 render_return = m_pcm93chart_current->RenderRegionViewOnGL(
5222 glc, vp, RectRegion, Region);
5223 m_Name = m_pcm93chart_current->GetLastFileName();
5228 if (VPoint.m_projection_type != PROJECTION_MERCATOR)
5229 return render_return;
5231 if (!m_pcm93chart_current)
return render_return;
5234 if (m_cell_index_special_outline) {
5236 covr_set *pcover = m_pcm93chart_current->GetCoverSet();
5238 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
5240 if ((pmcd->m_cell_index == m_cell_index_special_outline) &&
5241 (pmcd->m_object_id == m_object_id_special_outline) &&
5242 (pmcd->m_subcell == m_subcell_special_outline))
5252 float_2Dpt *p = pmcd->pvertices;
5253 wxPoint *pwp = m_pcm93chart_current->GetDrawBuffer(pmcd->m_nvertices);
5255 for (
int ip = 0; ip < pmcd->m_nvertices; ip++) {
5257 if (fabs(plon - VPoint.clon) > 180.) {
5258 if (plon > VPoint.clon)
5264 double easting, northing, epix, npix;
5265 toSM(p->y, plon + 360., VPoint.clat, VPoint.clon + 360, &easting,
5271 easting -= pmcd->user_xoff;
5274 northing -= pmcd->user_yoff;
5276 epix = easting * VPoint.view_scale_ppm;
5277 npix = northing * VPoint.view_scale_ppm;
5279 pwp[ip].x = (int)round((VPoint.pix_width / 2) + epix);
5280 pwp[ip].y = (int)round((VPoint.pix_height / 2) - npix);
5287 wxPen pen(wxTheColourDatabase->Find(_T (
"YELLOW" )), 3);
5291 pen.SetStyle(wxPENSTYLE_USER_DASH);
5292 pen.SetDashes(2, dash1);
5296 for (
int iseg = 0; iseg < pmcd->m_nvertices - 1; iseg++) {
5297 int x0 = pwp[iseg].x;
5298 int y0 = pwp[iseg].y;
5299 int x1 = pwp[iseg + 1].x;
5300 int y1 = pwp[iseg + 1].y;
5302 ClipResult res = cohen_sutherland_line_clip_i(
5303 &x0, &y0, &x1, &y1, 0, VPoint.pix_width, 0,
5310 dc.DrawLine(x0, y0, x1, y1);
5318 return render_return;
5321bool cm93compchart::RenderRegionViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint,
5325 if (g_pCM93OffsetDialog && g_pCM93OffsetDialog->IsShown())
5326 g_pCM93OffsetDialog->UpdateMCOVRList(VPoint);
5328 return DoRenderRegionViewOnDC(dc, VPoint, Region);
5331bool cm93compchart::RenderViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint) {
5332 const OCPNRegion vpr(0, 0, VPoint.pix_width, VPoint.pix_height);
5336 return DoRenderRegionViewOnDC(dc, VPoint, vpr);
5339bool cm93compchart::DoRenderRegionViewOnDC(wxMemoryDC &dc,
5346 printf(
"\nOn DoRenderRegionViewOnDC Ref scale is %d, %c\n", m_cmscale,
5347 (
char)(
'A' + m_cmscale - 1));
5349 while (upd.HaveRects()) {
5350 wxRect rect = upd.GetRect();
5351 printf(
" Region Rect: %d %d %d %d\n", rect.x, rect.y, rect.width,
5360 bool render_return =
false;
5361 if (m_pcm93chart_current) {
5362 m_pcm93chart_current->SetVPParms(vp);
5366 if (VPoint.b_quilt) {
5369 OCPNRegion chart_region = GetValidScreenCanvasRegion(vp, Region);
5373 "On DoRenderRegionViewOnDC : Intersecting Ref region rectangles\n");
5375 while (upd.HaveRects()) {
5376 wxRect rect = upd.GetRect();
5377 printf(
" Region Rect: %d %d %d %d\n", rect.x, rect.y, rect.width,
5383 if (!chart_region.IsEmpty()) vpr_empty.Subtract(chart_region);
5385 if (!vpr_empty.Empty() &&
5389#ifdef ocpnUSE_DIBSECTION
5394 if (!chart_region.IsEmpty())
5395 render_return = m_pcm93chart_current->RenderRegionViewOnDC(
5396 temp_dc, vp, chart_region);
5398 render_return =
false;
5401 cm93chart *m_pcm93chart_save = m_pcm93chart_current;
5407 if ((m_pDummyBM->GetWidth() != VPoint.rv_rect.width) ||
5408 (m_pDummyBM->GetHeight() != VPoint.rv_rect.height)) {
5413 if (NULL == m_pDummyBM)
5415 new wxBitmap(VPoint.rv_rect.width, VPoint.rv_rect.height, -1);
5418#ifdef ocpnUSE_DIBSECTION
5423 dumm_dc.SelectObject(*m_pDummyBM);
5424 dumm_dc.SetBackground(*wxBLACK_BRUSH);
5427 int cmscale_next = m_cmscale;
5431 while (!vpr_empty.Empty() && cmscale_next) {
5434 m_cmscale = PrepareChartScale(vp, cmscale_next,
false);
5435#ifdef ocpnUSE_DIBSECTION
5438 wxMemoryDC build_dc;
5441 if (m_pcm93chart_current) {
5443 printf(
" In DRRVOD, add quilt patch at %d, %c\n", m_cmscale,
5444 (
char)(
'A' + m_cmscale - 1));
5446 m_pcm93chart_current->RenderRegionViewOnDC(build_dc, vp, Region);
5448 OCPNRegion sscale_region = GetValidScreenCanvasRegion(vp, Region);
5451 sscale_region.Intersect(vpr_empty);
5455 while (upd.HaveRects()) {
5456 wxRect rect = upd.GetRect();
5457 dumm_dc.Blit(rect.x, rect.y, rect.width, rect.height, &build_dc,
5461 build_dc.SelectObject(wxNullBitmap);
5464 if (!sscale_region.IsEmpty()) vpr_empty.Subtract(sscale_region);
5472 while (updt.HaveRects()) {
5473 wxRect rect = updt.GetRect();
5474 dumm_dc.Blit(rect.x, rect.y, rect.width, rect.height, &temp_dc,
5478 temp_dc.SelectObject(wxNullBitmap);
5481 m_pcm93chart_current = m_pcm93chart_save;
5485 dumm_dc.SelectObject(wxNullBitmap);
5488 dc.SelectObject(*m_pDummyBM);
5490 render_return =
true;
5492 m_pcm93chart_current->RenderRegionViewOnDC(dc, vp, Region);
5493 render_return =
true;
5495 m_Name = m_pcm93chart_current->GetName();
5500 m_pcm93chart_current->RenderRegionViewOnDC(dc, vp, Region);
5501 m_Name = m_pcm93chart_current->GetLastFileName();
5509 if ((m_pDummyBM->GetWidth() != VPoint.pix_width) ||
5510 (m_pDummyBM->GetHeight() != VPoint.pix_height)) {
5516 if (NULL == m_pDummyBM)
5517 m_pDummyBM =
new wxBitmap(VPoint.pix_width, VPoint.pix_height, -1);
5521 mdc.SelectObject(*m_pDummyBM);
5522 mdc.SetBackground(*wxBLACK_BRUSH);
5524 mdc.SelectObject(wxNullBitmap);
5526 dc.SelectObject(*m_pDummyBM);
5532 if (m_cell_index_special_outline && m_pcm93chart_current) {
5533 covr_set *pcover = m_pcm93chart_current->GetCoverSet();
5535 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
5537 if ((pmcd->m_cell_index == m_cell_index_special_outline) &&
5538 (pmcd->m_object_id == m_object_id_special_outline) &&
5539 (pmcd->m_subcell == m_subcell_special_outline))
5549 float_2Dpt *p = pmcd->pvertices;
5550 wxPoint *pwp = m_pcm93chart_current->GetDrawBuffer(pmcd->m_nvertices);
5552 for (
int ip = 0; ip < pmcd->m_nvertices; ip++) {
5554 if (fabs(plon - VPoint.clon) > 180.) {
5555 if (plon > VPoint.clon)
5561 double easting, northing, epix, npix;
5562 toSM(p->y, plon + 360., VPoint.clat, VPoint.clon + 360, &easting,
5568 easting -= pmcd->user_xoff;
5571 northing -= pmcd->user_yoff;
5573 epix = easting * VPoint.view_scale_ppm;
5574 npix = northing * VPoint.view_scale_ppm;
5576 pwp[ip].x = (int)round((VPoint.pix_width / 2) + epix);
5577 pwp[ip].y = (int)round((VPoint.pix_height / 2) - npix);
5600 dc.SetPen(wxPen(wxTheColourDatabase->Find(_T (
"YELLOW" )), 4,
5601 wxPENSTYLE_LONG_DASH));
5603 for (
int iseg = 0; iseg < pmcd->m_nvertices - 1; iseg++) {
5604 int x0 = pwp[iseg].x;
5605 int y0 = pwp[iseg].y;
5606 int x1 = pwp[iseg + 1].x;
5607 int y1 = pwp[iseg + 1].y;
5609 ClipResult res = cohen_sutherland_line_clip_i(
5610 &x0, &y0, &x1, &y1, 0, VPoint.pix_width, 0,
5617 dc.DrawLine(x0, y0, x1, y1);
5625 return render_return;
5628void cm93compchart::UpdateRenderRegions(
const ViewPort &VPoint) {
5629 OCPNRegion full_screen_region(0, 0, VPoint.rv_rect.width,
5630 VPoint.rv_rect.height);
5636 if (m_pcm93chart_current) {
5637 m_pcm93chart_current->SetVPParms(vp);
5641 if (VPoint.b_quilt) {
5643 for (
int i = 0; i < 8; i++) {
5644 if (m_pcm93chart_array[i])
5645 m_pcm93chart_array[i]->m_render_region.Clear();
5651 GetValidScreenCanvasRegion(vp, full_screen_region);
5652 m_pcm93chart_current->m_render_region = chart_region;
5654 if (!chart_region.IsEmpty()) vpr_empty.Subtract(chart_region);
5656 if (!vpr_empty.Empty() &&
5660 cm93chart *m_pcm93chart_save = m_pcm93chart_current;
5662 int cmscale_next = m_cmscale;
5664 while (!vpr_empty.Empty() && cmscale_next) {
5667 m_cmscale = PrepareChartScale(vp, cmscale_next,
false);
5669 if (m_pcm93chart_current) {
5671 GetValidScreenCanvasRegion(vp, full_screen_region);
5672 sscale_region.Intersect(vpr_empty);
5673 m_pcm93chart_current->m_render_region = sscale_region;
5676 if (!sscale_region.IsEmpty()) vpr_empty.Subtract(sscale_region);
5682 m_pcm93chart_current = m_pcm93chart_save;
5688void cm93compchart::SetSpecialCellIndexOffset(
int cell_index,
int object_id,
5689 int subcell,
int xoff,
int yoff) {
5690 m_special_offset_x = xoff;
5691 m_special_offset_y = yoff;
5693 if (m_pcm93chart_current)
5694 m_pcm93chart_current->SetUserOffsets(cell_index, object_id, subcell, xoff,
5700 if (m_cmscale >= 7)
return false;
5705 bool secondpass =
false;
5707 if (!glcc)
return false;
5710 wxPen pen = dc.GetPen();
5711 col = pen.GetColour();
5715 if (g_GLOptions.m_GLLineSmoothing) {
5716 glEnable(GL_LINE_SMOOTH);
5717 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
5722 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5724 glLineWidth(g_GLMinSymbolLineWidth);
5725 glDisable(GL_LINE_STIPPLE);
5728 if (g_b_EnableVBO) glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
5731 glEnableClientState(GL_VERTEX_ARRAY);
5737 if (glChartCanvas::HasNormalizedViewPort(vp)) {
5738 glcc->MultMatrixViewPort(vp);
5739 nvp = glChartCanvas::NormalizedViewPort(vp);
5744 if ((vp.m_projection_type == PROJECTION_MERCATOR ||
5745 vp.m_projection_type == PROJECTION_EQUIRECTANGULAR) &&
5746 (vp.GetBBox().GetMinLon() < -180 || vp.GetBBox().GetMaxLon() > 180))
5754 int nss = m_cmscale + 1;
5763 bool bdrawn =
false;
5772 if(nss_max > m_cmscale+3)
5773 nss_max = m_cmscale+3;
5776 while (nss <= nss_max && (!bdrawn || (vp.chart_scale < 3e6))) {
5777 cm93chart *psc = m_pcm93chart_array[nss];
5780 m_pcm93chart_array[nss] =
new cm93chart();
5781 psc = m_pcm93chart_array[nss];
5783 wxChar ext = (wxChar)(
'A' + nss - 1);
5784 if (nss == 0) ext =
'Z';
5786 wxString file_dummy = _T (
"CM93." );
5789 psc->SetCM93Dict(m_pDictComposite);
5790 psc->SetCM93Prefix(m_prefixComposite);
5791 psc->SetCM93Manager(m_pcm93mgr);
5793 psc->SetColorScheme(m_global_color_scheme);
5794 psc->Init(file_dummy, FULL_INIT);
5800 psc->UpdateCovrSet(&vp);
5803 covr_set *pcover = psc->GetCoverSet();
5805 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
5808 if (vp.GetBBox().IntersectOut(mcd->m_covr_bbox))
continue;
5813 glColor3ub(col.Red(), col.Green(), col.Blue());
5814 RenderCellOutlinesOnGL(nvp, mcd);
5819#define NORM_FACTOR 4096.0
5821 40058986 * NORM_FACTOR;
5823 glColor3ub(col.Red(), col.Green(), col.Blue());
5825 glTranslated(vp.clon < 0 ? -ts : ts, 0, 0);
5826 RenderCellOutlinesOnGL(nvp, mcd);
5835 wxPoint *pwp = psc->GetDrawBuffer(mcd->m_nvertices);
5836 bdrawn = RenderCellOutlinesOnDC(dc, vp, pwp, mcd);
5845#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
5848 glDisableClientState(GL_VERTEX_ARRAY);
5850 glDisable(GL_LINE_STIPPLE);
5851 glDisable(GL_LINE_SMOOTH);
5852 glDisable(GL_BLEND);
5858bool cm93compchart::RenderCellOutlinesOnDC(
ocpnDC &dc,
ViewPort &vp,
5860 float_2Dpt *p = mcd->pvertices;
5861 int np = mcd->m_nvertices;
5863 for (
int ip = 0; ip < np; ip++, p++) {
5864 pwp[ip] = vp.GetPixFromLL(p->y, p->x);
5867 pwp[ip].x -= mcd->user_xoff * vp.view_scale_ppm;
5868 pwp[ip].y -= mcd->user_yoff * vp.view_scale_ppm;
5873 wxPoint p0 = pwp[0];
5874 for (
int ip = 1; ip < np; ip++) {
5875 if (((p0.x > vp.pix_width) && (pwp[ip].x < 0)) ||
5876 ((p0.x < 0) && (pwp[ip].x > vp.pix_width)))
5882 dc.DrawLines(mcd->m_nvertices, pwp, 0, 0,
false);
5889 if (vp.m_projection_type != mcd->gl_screen_projection_type ||
5890 !glChartCanvas::HasNormalizedViewPort(vp) || vp.m_projection_type == PROJECTION_POLAR ) {
5891 delete[] mcd->gl_screen_vertices;
5892 mcd->gl_screen_vertices = NULL;
5896 if (!mcd->gl_screen_vertices) {
5898 double lastlat, lastlon = 0;
5900 float_2Dpt *p = mcd->pvertices;
5901 for (
int ip = 0; ip < mcd->m_nvertices; ip++, p++) {
5903 if (lon >= 180) lon -= 360;
5906 if (fabs(lon - lastlon) > 180) count++;
5912 mcd->gl_screen_vertices =
new float_2Dpt[2 * count];
5916 float_2Dpt *q = mcd->gl_screen_vertices;
5919 bool lastvalid =
false;
5920 for (
int ip = 0; ip < mcd->m_nvertices; ip++, p++) {
5923 if (lon >= 180) lon -= 360;
5926 if (fabs(lon - lastlon) > 180) {
5929 vp.GetDoublePixFromLL(lastlat, lastlon > 0 ? 180 : -180);
5930 if (!std::isnan(r.m_x)) {
5936 r.m_x -= mcd->user_xoff * vp.view_scale_ppm;
5937 r.m_y -= mcd->user_yoff * vp.view_scale_ppm;
5945 wxPoint2DDouble r = vp.GetDoublePixFromLL(lat, lon > 0 ? 180 : -180);
5946 if ((lastvalid = !std::isnan(r.m_x))) {
5947 r.m_x -= mcd->user_xoff * vp.view_scale_ppm;
5948 r.m_y -= mcd->user_yoff * vp.view_scale_ppm;
5956 wxPoint2DDouble s = vp.GetDoublePixFromLL(lat, lon);
5957 if (!std::isnan(s.m_x)) {
5959 s.m_x -= mcd->user_xoff * vp.view_scale_ppm;
5960 s.m_y -= mcd->user_yoff * vp.view_scale_ppm;
5978 mcd->m_ngl_vertices = q - mcd->gl_screen_vertices;
5979 mcd->gl_screen_projection_type = vp.m_projection_type;
5985 glVertexPointer(2, GL_FLOAT, 2 *
sizeof(
float), mcd->gl_screen_vertices);
5986 glDrawArrays(GL_LINES, 0, mcd->m_ngl_vertices);
5989 for (
int i = 0; i < mcd->m_ngl_vertices; i++)
5990 glVertex2f(mcd->gl_screen_vertices[i].y, mcd->gl_screen_vertices[i].x);
5997void cm93compchart::GetPointPix(ObjRazRules *rzRules,
float rlat,
float rlon,
5999 m_pcm93chart_current->GetPointPix(rzRules, rlat, rlon, r);
6002void cm93compchart::GetPointPix(ObjRazRules *rzRules, wxPoint2DDouble *en,
6003 wxPoint *r,
int nPoints) {
6004 m_pcm93chart_current->GetPointPix(rzRules, en, r, nPoints);
6007void cm93compchart::GetPixPoint(
int pixx,
int pixy,
double *plat,
double *plon,
6009 m_pcm93chart_current->GetPixPoint(pixx, pixy, plat, plon, vpt);
6012void cm93compchart::UpdateLUPs(
s57chart *pOwner) {
6013 for (
int i = 0; i < 8; i++) {
6014 if (m_pcm93chart_array[i]) m_pcm93chart_array[i]->UpdateLUPs(pOwner);
6018std::list<S57Obj*> *cm93compchart::GetAssociatedObjects(S57Obj *obj) {
6019 if (m_pcm93chart_current)
6020 return m_pcm93chart_current->GetAssociatedObjects(obj);
6025void cm93compchart::InvalidateCache() {
6026 for (
int i = 0; i < 8; i++) {
6027 if (m_pcm93chart_array[i]) m_pcm93chart_array[i]->InvalidateCache();
6031void cm93compchart::ForceEdgePriorityEvaluate(
void) {
6032 for (
int i = 0; i < 8; i++) {
6033 if (m_pcm93chart_array[i])
6034 m_pcm93chart_array[i]->ForceEdgePriorityEvaluate();
6038void cm93compchart::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
6039 m_global_color_scheme = cs;
6041 for (
int i = 0; i < 8; i++) {
6042 if (m_pcm93chart_array[i])
6043 m_pcm93chart_array[i]->SetColorScheme(cs, bApplyImmediate);
6047ListOfObjRazRules *cm93compchart::GetObjRuleListAtLatLon(
float lat,
float lon,
6048 float select_radius,
6050 int selection_mask) {
6056 if (!VPoint->b_quilt)
6057 if (m_pcm93chart_current)
6058 return m_pcm93chart_current->GetObjRuleListAtLatLon(lat, alon,
6059 select_radius, &vp);
6062 ListOfObjRazRules *ret_ptr =
new ListOfObjRazRules;
6066 UpdateRenderRegions(*VPoint);
6070 wxPoint p = VPoint->GetPixFromLL(lat, lon);
6072 for (
int i = 0; i < 8; i++) {
6073 if (m_pcm93chart_array[i]) {
6074 if (!m_pcm93chart_array[i]->m_render_region.IsEmpty()) {
6075 if (wxInRegion == m_pcm93chart_array[i]->m_render_region.Contains(p))
6076 return m_pcm93chart_array[i]->GetObjRuleListAtLatLon(
6077 lat, alon, select_radius, &vp, selection_mask);
6083 ListOfObjRazRules *ret_ptr =
new ListOfObjRazRules;
6089std::unordered_map<unsigned, VE_Element *> &cm93compchart::Get_ve_hash(
void) {
6090 return m_pcm93chart_current->Get_ve_hash();
6093std::unordered_map<unsigned, VC_Element *> &cm93compchart::Get_vc_hash(
void) {
6094 return m_pcm93chart_current->Get_vc_hash();
6105 m_last_cell_adjustvp = m_pcm93chart_current;
6113 if (m_pcm93chart_current)
return false;
6122 int cmscale = GetCMScaleFromVP(
6125 int cmscale_actual = PrepareChartScale(
6126 vp_proposed, cmscale,
6130 printf(
" In AdjustVP, adjustment subchart scale is %c\n",
6131 (
char)(
'A' + cmscale_actual - 1));
6137 bool single_adjust =
false;
6138 if (m_pcm93chart_array[cmscale_actual])
6140 m_pcm93chart_array[cmscale_actual]->AdjustVP(vp_last, vp_proposed);
6142 if (m_cmscale != cmscale_actual)
return false;
6146 if (vp_last.b_quilt)
return false;
6148 return single_adjust;
6151ThumbData *cm93compchart::GetThumbData(
int tnx,
int tny,
float lat,
float lon) {
6155InitReturn cm93compchart::CreateHeaderData() {
6156 m_Chart_Scale = 20000000;
6162 wxDir dirt(m_prefixComposite);
6164 wxRegEx test(_T(
"[0-9]+"));
6166 bool b_cont = dirt.GetFirst(&candidate);
6169 if (test.Matches(candidate) && (candidate.Len() == 8)) {
6170 wxString dir = m_prefixComposite;
6172 if (wxDir::Exists(dir)) {
6173 wxFileName name(dir);
6174 wxString num_name = name.GetName();
6176 if (num_name.ToLong(&number)) {
6177 int ilat = number / 10000;
6178 int ilon = number % 10000;
6180 int lat_base = (ilat - 270) / 3.;
6181 int lon_base = ilon / 3.;
6182 extent_rect.Union(wxRect(lon_base, lat_base, 20, 20));
6186 b_cont = dirt.GetNext(&candidate);
6190 m_FullExtent.ELON = ((double)extent_rect.x + (
double)extent_rect.width);
6191 m_FullExtent.WLON = ((double)extent_rect.x);
6192 m_FullExtent.NLAT = ((double)extent_rect.y + (
double)extent_rect.height);
6193 m_FullExtent.SLAT = ((double)extent_rect.y);
6194 m_bExtentSet =
true;
6198 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
6199 *m_pCOVRTablePoints = 4;
6200 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
6201 float *pf = (
float *)malloc(2 * 4 *
sizeof(
float));
6205 *pfe++ = m_FullExtent.NLAT;
6206 *pfe++ = m_FullExtent.WLON;
6208 *pfe++ = m_FullExtent.NLAT;
6209 *pfe++ = m_FullExtent.ELON;
6211 *pfe++ = m_FullExtent.SLAT;
6212 *pfe++ = m_FullExtent.ELON;
6214 *pfe++ = m_FullExtent.SLAT;
6215 *pfe++ = m_FullExtent.WLON;
6220cm93_dictionary *cm93compchart::FindAndLoadDictFromDir(
const wxString &dir) {
6225 if (pdict->LoadDictionary(dir))
return pdict;
6230 wxString path = dir;
6234 while (i < path.Len()) {
6235 target.Append(path[i]);
6236 if (path[i] == wxFileName::GetPathSeparator()) {
6240 if (pdict->LoadDictionary(target)) {
6254 wxFileName fnc(dir);
6255 wxString found_dict_file_name;
6259 path = fnc.GetPath(wxPATH_GET_VOLUME);
6261 wxString msg = _T (
" Looking harder for CM93 dictionary in " );
6265 if ((path.Len() == 0) || path.IsSameAs(fnc.GetPathSeparator())) {
6267 wxLogMessage(_T (
"Early break1" ));
6273 if ((wxNOT_FOUND == path.Lower().Find(_T (
"cm93" )))) {
6275 wxLogMessage(_T (
"Early break2" ));
6283 if (dir.IsOpened()) {
6286 dir.Traverse(cm93Dictionary);
6287 bdone = found_dict_file_name.Len() != 0;
6293 if (found_dict_file_name.Len()) {
6294 wxFileName fnd(found_dict_file_name);
6296 fnd.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
6298 if (pdict->LoadDictionary(dpath)) retval = pdict;
6301 if (NULL == retval)
delete pdict;
6306void cm93compchart::CloseandReopenCurrentSubchart(
void) {
6307 delete m_pcm93chart_current;
6308 m_pcm93chart_current = NULL;
6309 m_pcm93chart_array[m_cmscale] = NULL;
6333 const wxPoint &pos,
const wxSize &size,
long style);
6336 wxString OnGetItemText(
long item,
long column)
const;
6337 int OnGetItemColumnImage(
long item,
long column)
const;
6342OCPNOffsetListCtrl::OCPNOffsetListCtrl(
CM93OffsetDialog *parent, wxWindowID
id,
6343 const wxPoint &pos,
const wxSize &size,
6345 : wxListCtrl(parent, id, pos, size, style) {
6349OCPNOffsetListCtrl::~OCPNOffsetListCtrl() {}
6351wxString OCPNOffsetListCtrl::OnGetItemText(
long item,
long column)
const {
6353 M_COVR_Desc *pmcd = m_parent->m_pcovr_array[item];
6357 ret.Printf(_T (
"%d" ), pmcd->m_cell_index);
6358 if (((
int)
'0') == pmcd->m_subcell)
6359 ret.Prepend(_T (
"0" ));
6361 char t = (char)pmcd->m_subcell;
6363 p.Printf(_T (
"%c" ), t);
6370 ret.Printf(_T (
"%d" ), pmcd->m_object_id);
6374 ret = m_parent->m_selected_chart_scale_char;
6378 ret.Printf(_T (
"%g" ), pmcd->transform_WGS84_offset_x);
6382 ret.Printf(_T (
"%g" ), pmcd->transform_WGS84_offset_y);
6386 ret.Printf(_T (
"%6.0f" ), pmcd->user_xoff * pmcd->m_centerlat_cos);
6390 ret.Printf(_T (
"%6.0f" ), pmcd->user_yoff * pmcd->m_centerlat_cos);
6399int OCPNOffsetListCtrl::OnGetItemColumnImage(
long item,
long column)
const {
6410EVT_CLOSE(CM93OffsetDialog::OnClose)
6415 m_pcompchart = NULL;
6420 m_selected_list_index = -1;
6421 m_selected_cell_index = 0;
6423 long wstyle = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER;
6424 wxDialog::Create(parent, -1, _(
"OpenCPN CM93 Cell Offset Adjustments"),
6425 wxPoint(0, 0), wxSize(800, 200), wstyle);
6427 wxFont *qFont = GetOCPNScaledFont(_(
"Dialog"));
6431 wxBoxSizer *topSizer =
new wxBoxSizer(wxHORIZONTAL);
6436 long flags = wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_HRULES | wxLC_VRULES |
6439 flags |= wxLC_VIRTUAL;
6445 m_pListCtrlMCOVRs->Connect(
6446 wxEVT_COMMAND_LIST_ITEM_SELECTED,
6447 wxListEventHandler(CM93OffsetDialog::OnCellSelected), NULL,
this);
6449 int dx = GetCharWidth();
6450 int dy = GetCharHeight();
6453 m_pListCtrlMCOVRs->InsertColumn(tlCELL, _(
"Cell"), wxLIST_FORMAT_LEFT, width);
6456 m_pListCtrlMCOVRs->InsertColumn(tlMCOVR, _(
"M_COVR ID"), wxLIST_FORMAT_CENTER,
6460 m_pListCtrlMCOVRs->InsertColumn(tlSCALE, _(
"Cell Scale"),
6461 wxLIST_FORMAT_CENTER, width);
6464 m_pListCtrlMCOVRs->InsertColumn(tlXOFF, _(
"wgsox"), wxLIST_FORMAT_CENTER,
6468 m_pListCtrlMCOVRs->InsertColumn(tlYOFF, _(
"wgsoy"), wxLIST_FORMAT_CENTER,
6472 m_pListCtrlMCOVRs->InsertColumn(tlUXOFF, _(
"User X Offset"),
6473 wxLIST_FORMAT_CENTER, width);
6476 m_pListCtrlMCOVRs->InsertColumn(tlUYOFF, _(
"User Y Offset"),
6477 wxLIST_FORMAT_CENTER, width);
6479 topSizer->Add(m_pListCtrlMCOVRs, 1, wxEXPAND | wxALL, 0);
6481 wxBoxSizer *boxSizer02 =
new wxBoxSizer(wxVERTICAL);
6482 boxSizer02->AddSpacer(22);
6484 wxStaticText *pStaticTextXoff =
new wxStaticText(
6486 wxString::Format(_T(
"%s (%s)" ), _(
"User X Offset"), _(
"meters")),
6487 wxDefaultPosition, wxDefaultSize, 0);
6488 boxSizer02->Add(pStaticTextXoff, 0, wxALL, 0);
6491 new wxSpinCtrl(
this, wxID_ANY, wxEmptyString, wxDefaultPosition,
6492 wxSize(50, -1), wxSP_ARROW_KEYS, -10000, 10000, 0);
6493 m_pSpinCtrlXoff->Connect(wxEVT_COMMAND_SPINCTRL_UPDATED,
6494 wxCommandEventHandler(CM93OffsetDialog::OnOffSetSet),
6496 boxSizer02->Add(m_pSpinCtrlXoff, 0, wxEXPAND | wxALL, 0);
6498 wxStaticText *pStaticTextYoff =
new wxStaticText(
6500 wxString::Format(_T(
"%s (%s)" ), _(
"User Y Offset"), _(
"meters")),
6501 wxDefaultPosition, wxDefaultSize, 0);
6502 boxSizer02->Add(pStaticTextYoff, 0, wxALL, 0);
6505 new wxSpinCtrl(
this, wxID_ANY, wxEmptyString, wxDefaultPosition,
6506 wxSize(50, -1), wxSP_ARROW_KEYS, -10000, 10000, 0);
6507 m_pSpinCtrlYoff->Connect(wxEVT_COMMAND_SPINCTRL_UPDATED,
6508 wxCommandEventHandler(CM93OffsetDialog::OnOffSetSet),
6510 boxSizer02->Add(m_pSpinCtrlYoff, 0, wxEXPAND | wxALL, 0);
6512 m_OKButton =
new wxButton(
this, wxID_ANY, _(
"OK"), wxDefaultPosition,
6514 m_OKButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
6515 wxCommandEventHandler(CM93OffsetDialog::OnOK), NULL,
6517 boxSizer02->Add(m_OKButton, 0, wxALL, 5);
6518 m_OKButton->SetDefault();
6520 topSizer->Add(boxSizer02, 0, wxEXPAND | wxALL, 2);
6522 wxSize sz(800, dy * 8);
6524 sz = wxGetDisplaySize();
6534 SetSize(GetSize().x, GetSize().y - 1);
6546CM93OffsetDialog::~CM93OffsetDialog() { g_pCM93OffsetDialog = NULL; }
6548void CM93OffsetDialog::OnClose(wxCloseEvent &event) {
6550 m_pcompchart->SetSpecialOutlineCellIndex(0, 0, 0);
6552 m_pcompchart->InvalidateCache();
6555 m_pparent->Refresh(
true);
6556 gFrame->InvalidateAllGL();
6560 if (m_pListCtrlMCOVRs->GetItemCount() > m_selected_list_index)
6561 m_pListCtrlMCOVRs->SetItemState(m_selected_list_index, 0,
6562 wxLIST_STATE_SELECTED);
6567void CM93OffsetDialog::OnOK(wxCommandEvent &event) {
6575 m_pcompchart = pchart;
6578void CM93OffsetDialog::OnOffSetSet(wxCommandEvent &event) {
6579 m_xoff = m_pSpinCtrlXoff->GetValue() / m_centerlat_cos;
6580 m_yoff = m_pSpinCtrlYoff->GetValue() / m_centerlat_cos;
6587void CM93OffsetDialog::UpdateOffsets(
void) {
6588 if (m_pcompchart && m_selected_cell_index) {
6590 m_pcompchart->SetSpecialCellIndexOffset(m_selected_cell_index,
6591 m_selected_object_id,
6592 m_selected_subcell, m_xoff, m_yoff);
6596 OCPNPlatform::ShowBusySpinner();
6597 m_pcompchart->CloseandReopenCurrentSubchart();
6598 OCPNPlatform::HideBusySpinner();
6601 m_pparent->Refresh(
true);
6602 gFrame->InvalidateAllGL();
6607void CM93OffsetDialog::SetColorScheme() { DimeControl(
this); }
6609void CM93OffsetDialog::OnCellSelected(wxListEvent &event) {
6611 m_selected_list_index =
event.GetIndex();
6613 M_COVR_Desc *mcd = m_pcovr_array.Item(event.GetIndex());
6615 if (m_selected_list_index > m_pListCtrlMCOVRs->GetItemCount())
6618 cm93chart *pchart = m_pcompchart->GetCurrentSingleScaleChart();
6620 M_COVR_Desc *cached_mcd = pchart->GetCoverSet()->Find_MCD(
6621 mcd->m_cell_index, mcd->m_object_id, mcd->m_subcell);
6623 m_pSpinCtrlXoff->SetValue(
6624 wxRound(cached_mcd->user_xoff * cached_mcd->m_centerlat_cos));
6625 m_pSpinCtrlYoff->SetValue(
6626 wxRound(cached_mcd->user_yoff * cached_mcd->m_centerlat_cos));
6630 m_pcompchart->SetSpecialOutlineCellIndex(mcd->m_cell_index,
6631 mcd->m_object_id, mcd->m_subcell);
6633 m_selected_cell_index = mcd->m_cell_index;
6634 m_selected_object_id = mcd->m_object_id;
6635 m_selected_subcell = mcd->m_subcell;
6636 m_centerlat_cos = mcd->m_centerlat_cos;
6638 m_pcompchart->InvalidateCache();
6641 m_pparent->Refresh(
true);
6642 gFrame->InvalidateAllGL();
6647void CM93OffsetDialog::UpdateMCOVRList(
const ViewPort &vpt) {
6651 cm93chart *pchart = m_pcompchart->GetCurrentSingleScaleChart();
6654 m_selected_chart_scale_char = pchart->GetScaleChar();
6656 m_pcovr_array.Clear();
6659 std::vector<int> cell_array = pchart->GetVPCellArray(vpt);
6667 covr_set *pcover = pchart->GetCoverSet();
6669 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
6672 for (
unsigned int icell = 0; icell < cell_array.size(); icell++) {
6673 if (cell_array[icell] == mcd->m_cell_index) {
6674 wxPoint *pwp = pchart->GetDrawBuffer(mcd->m_nvertices);
6679 if (rgn.Contains(0, 0, vpt.pix_width, vpt.pix_height) !=
6681 m_pcovr_array.Add(mcd);
6689 for (
unsigned int im = 0; im < m_pcovr_array.size(); im++) {
6691 if ((m_selected_cell_index == mcd->m_cell_index) &&
6692 (m_selected_object_id == mcd->m_object_id) &&
6693 (m_selected_subcell == mcd->m_subcell)) {
6699 if (!m_pListCtrlMCOVRs->IsVirtual()) {
6700 if (m_pListCtrlMCOVRs->GetItemCount())
6701 m_pListCtrlMCOVRs->DeleteAllItems();
6703 for (
unsigned int i = 0; i < m_pcovr_array.GetCount(); i++) {
6706 m_pListCtrlMCOVRs->InsertItem(item);
6707 for (
int j = 0; j < tlUYOFF + 1; j++) {
6709 item.SetText(m_pListCtrlMCOVRs->OnGetItemText(i, j));
6710 m_pListCtrlMCOVRs->SetItem(item);
6714 m_pListCtrlMCOVRs->SetItemCount(m_pcovr_array.GetCount());
6717 if (-1 != sel_index)
6718 m_pListCtrlMCOVRs->SetItemState(sel_index, wxLIST_STATE_SELECTED,
6719 wxLIST_STATE_SELECTED);
6721 m_pListCtrlMCOVRs->SetItemState(sel_index, 0,
6722 wxLIST_STATE_SELECTED);
6724 m_pListCtrlMCOVRs->Refresh(
true);
6727 m_pListCtrlMCOVRs->Refresh(
false);
bool RenderNextSmallerCellOutlines(ocpnDC &dc, ViewPort &vp, ChartCanvas *cc)
Runtime representation of a plugin block.