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"
49#include "model/georef.h"
51#include "model/cutil.h"
53#include "ocpn_pixel.h"
55#include "pluginmanager.h"
56#include "OCPNPlatform.h"
57#include "model/wx28compat.h"
59#include "model/chartdata_input_stream.h"
60#include "DetailSlider.h"
63#include "ocpn_frame.h"
69#include "glChartCanvas.h"
74#include <wx/msw/msvcrt.h>
79extern s52plib *ps52plib;
80extern bool g_bDebugCM93;
81extern int g_cm93_zoom_factor;
83extern int g_detailslider_dialog_x, g_detailslider_dialog_y;
86extern bool g_b_EnableVBO;
91#include <wx/arrimpl.cpp>
92WX_DEFINE_OBJARRAY(Array_Of_M_COVR_Desc);
94#include <wx/listimpl.cpp>
95WX_DEFINE_LIST(List_Of_M_COVR_Desc);
97void appendOSDirSep(wxString *pString) {
98 wxChar sep = wxFileName::GetPathSeparator();
99 if (pString->Last() != sep) pString->Append(sep);
106M_COVR_Desc::M_COVR_Desc() {
108 gl_screen_vertices = NULL;
109 gl_screen_projection_type = PROJECTION_UNKNOWN;
113 m_centerlat_cos = 1.0;
114 m_buser_offsets =
false;
117 gl_screen_vertices = NULL;
120M_COVR_Desc::~M_COVR_Desc() {
122 delete[] gl_screen_vertices;
125int M_COVR_Desc::GetWKBSize() {
133 size += m_nvertices *
sizeof(float_2Dpt);
136 size += 8 *
sizeof(double);
141bool M_COVR_Desc::WriteWKB(
void *p) {
144 *pr++ = GetWKBSize();
146 *pr++ = m_cell_index;
152 float_2Dpt *pfo = (float_2Dpt *)pr;
153 float_2Dpt *pfi = pvertices;
154 for (
int i = 0; i < m_nvertices; i++) *pfo++ = *pfi++;
156 int *pi = (
int *)pfo;
159 double *pd = (
double *)pi;
160 *pd++ = transform_WGS84_offset_x;
161 *pd++ = transform_WGS84_offset_y;
162 *pd++ = m_covr_lat_min;
163 *pd++ = m_covr_lat_max;
164 *pd++ = m_covr_lon_min;
165 *pd++ = m_covr_lon_max;
167 double centerlat_cos =
168 cos(((m_covr_lat_min + m_covr_lat_max) / 2.) * PI / 180.);
170 *pd++ = user_xoff * centerlat_cos;
171 *pd++ = user_yoff * centerlat_cos;
177int M_COVR_Desc::ReadWKB(wxFFileInputStream &ifs) {
180 if (!ifs.Read(&length,
sizeof(
int)).Eof()) {
181 ifs.Read(&m_cell_index,
sizeof(
int));
182 ifs.Read(&m_object_id,
sizeof(
int));
183 ifs.Read(&m_subcell,
sizeof(
int));
185 ifs.Read(&m_nvertices,
sizeof(
int));
187 pvertices =
new float_2Dpt[m_nvertices];
189 ifs.Read(pvertices, m_nvertices *
sizeof(float_2Dpt));
191 ifs.Read(&m_npub_year,
sizeof(
int));
193 ifs.Read(&transform_WGS84_offset_x,
sizeof(
double));
194 ifs.Read(&transform_WGS84_offset_y,
sizeof(
double));
195 ifs.Read(&m_covr_lat_min,
sizeof(
double));
196 ifs.Read(&m_covr_lat_max,
sizeof(
double));
197 ifs.Read(&m_covr_lon_min,
sizeof(
double));
198 ifs.Read(&m_covr_lon_max,
sizeof(
double));
200 m_centerlat_cos = cos(((m_covr_lat_min + m_covr_lat_max) / 2.) * PI / 180.);
202 ifs.Read(&user_xoff,
sizeof(
double));
203 ifs.Read(&user_yoff,
sizeof(
double));
205 user_xoff /= m_centerlat_cos;
206 user_yoff /= m_centerlat_cos;
208 if ((fabs(user_xoff) > 1.) || (fabs(user_yoff) > 1.))
209 m_buser_offsets =
true;
211 m_buser_offsets =
false;
213 m_covr_bbox.Set(m_covr_lat_min, m_covr_lon_min, m_covr_lat_max,
220 float_2Dpt *p = pvertices;
222 for (
int ip = 0; ip < m_nvertices; ip++) {
224 if (fabs(plon - vp.
clon) > 180.) {
231 double easting, northing, epix, npix;
232 toSM(p->y, plon + 360., vp.
clat, vp.
clon + 360, &easting, &northing);
235 easting -= user_xoff;
237 northing -= user_yoff;
242 pwp[ip].x = (int)round((vp.
pix_width / 2) + epix);
243 pwp[ip].y = (int)round((vp.
pix_height / 2) - npix);
257char sig_version[] =
"COVR1002";
264 bool Init(wxChar scale_char, wxString &prefix);
265 unsigned int GetCoverCount() {
return m_covr_array_outlines.GetCount(); }
266 M_COVR_Desc *GetCover(
unsigned int im) {
return &m_covr_array_outlines[im]; }
269 bool IsCovrLoaded(
int cell_index);
271 M_COVR_Desc *Find_MCD(
int cell_index,
int object_id,
int sbcell);
277 wxString m_cachefile;
280 Array_Of_M_COVR_Desc m_covr_array_outlines;
284 std::unordered_map<int, int> m_cell_hash;
287covr_set::covr_set(
cm93chart *parent) { m_pParent = parent; }
289covr_set::~covr_set() {
291 if (m_cachefile.IsEmpty())
295 if (m_covr_array_outlines.GetCount()) {
296 wxFFileOutputStream ofs(m_cachefile);
298 ofs.Write(sig_version, 8);
300 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
301 int wkbsize = m_covr_array_outlines[i].GetWKBSize();
303 char *p = (
char *)malloc(wkbsize *
sizeof(
char));
304 m_covr_array_outlines[i].WriteWKB(p);
305 ofs.Write(p, wkbsize);
314bool covr_set::Init(wxChar scale_char, wxString &prefix) {
315 m_scale_char = scale_char;
317 switch (m_scale_char) {
348 wxString prefix_string = prefix;
349 wxString sep(wxFileName::GetPathSeparator());
350 prefix_string.Replace(sep, _T (
"_" ));
351 prefix_string.Replace(_T (
":" ), _T (
"_" ));
354 appendOSDirSep(&m_cachefile);
356 m_cachefile += _T (
"cm93" );
357 appendOSDirSep(&m_cachefile);
361 m_cachefile += _T (
"_" );
363 wxString cache_old_old_name = m_cachefile;
364 cache_old_old_name += _T (
"coverset." );
365 cache_old_old_name += m_scale_char;
367 wxString cache_old_name = m_cachefile;
368 cache_old_name += _T (
"coverset_sig." );
369 cache_old_name += m_scale_char;
371 m_cachefile += _T (
"coverset_sigp." );
372 m_cachefile += m_scale_char;
374 wxFileName fn(m_cachefile);
375 if (!fn.DirExists()) wxFileName::Mkdir(fn.GetPath(), 0777, wxPATH_MKDIR_FULL);
378 if (!wxFileName::FileExists(m_cachefile)) {
381 if (wxFileName::FileExists(cache_old_name)) ::wxRemoveFile(cache_old_name);
382 if (wxFileName::FileExists(cache_old_old_name))
383 ::wxRemoveFile(cache_old_old_name);
387 wxFFileInputStream ifs(m_cachefile);
391 if (!ifs.Read(&sig_bytes, 8).Eof()) {
392 if (strncmp(sig_bytes, sig_version, 8)) {
401 int length = pmcd->ReadWKB(ifs);
404 m_covr_array_outlines.Add(pmcd);
406 if (m_cell_hash.find(pmcd->m_cell_index) == m_cell_hash.end())
407 m_cell_hash[pmcd->m_cell_index] = 0;
409 m_cell_hash[pmcd->m_cell_index]++;
422 m_covr_array_outlines.Add(pmcd);
424 if (m_cell_hash.find(pmcd->m_cell_index) ==
426 m_cell_hash[pmcd->m_cell_index] = 0;
428 m_cell_hash[pmcd->m_cell_index]++;
431bool covr_set::IsCovrLoaded(
int cell_index) {
432 return (m_cell_hash.find(cell_index) != m_cell_hash.end());
436 if (m_cell_hash.find(pmcd->m_cell_index) ==
439 m_covr_array_outlines.Add(pmcd);
440 m_cell_hash[pmcd->m_cell_index] = 1;
448 bool b_found =
false;
449 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
450 M_COVR_Desc *pmcd_candidate = &m_covr_array_outlines[i];
451 if ((pmcd_candidate->m_cell_index == pmcd->m_cell_index) &&
452 (pmcd_candidate->m_object_id == pmcd->m_object_id) &&
453 (pmcd_candidate->m_subcell == pmcd->m_subcell))
462 m_covr_array_outlines.Add(pmcd);
463 m_cell_hash[pmcd->m_cell_index]++;
471 if (m_cell_hash.find(pmcd->m_cell_index) ==
479 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
480 M_COVR_Desc *pmcd_candidate = &m_covr_array_outlines[i];
481 if ((pmcd_candidate->m_cell_index == pmcd->m_cell_index) &&
482 (pmcd_candidate->m_object_id == pmcd->m_object_id) &&
483 (pmcd_candidate->m_subcell == pmcd->m_subcell)) {
491M_COVR_Desc *covr_set::Find_MCD(
int cell_index,
int object_id,
int subcell) {
492 if (m_cell_hash.find(cell_index) == m_cell_hash.end())
495 for (
unsigned int i = 0; i < m_covr_array_outlines.GetCount(); i++) {
496 M_COVR_Desc *pmcd_candidate = &m_covr_array_outlines[i];
497 if ((pmcd_candidate->m_cell_index == cell_index) &&
498 (pmcd_candidate->m_object_id == object_id) &&
499 (pmcd_candidate->m_subcell == subcell))
501 return pmcd_candidate;
509static unsigned char Table_0[] = {
510 0x0CD, 0x0EA, 0x0DC, 0x048, 0x03E, 0x06D, 0x0CA, 0x07B, 0x052, 0x0E1, 0x0A4,
511 0x08E, 0x0AB, 0x005, 0x0A7, 0x097, 0x0B9, 0x060, 0x039, 0x085, 0x07C, 0x056,
512 0x07A, 0x0BA, 0x068, 0x06E, 0x0F5, 0x05D, 0x002, 0x04E, 0x00F, 0x0A1, 0x027,
513 0x024, 0x041, 0x034, 0x000, 0x05A, 0x0FE, 0x0CB, 0x0D0, 0x0FA, 0x0F8, 0x06C,
514 0x074, 0x096, 0x09E, 0x00E, 0x0C2, 0x049, 0x0E3, 0x0E5, 0x0C0, 0x03B, 0x059,
515 0x018, 0x0A9, 0x086, 0x08F, 0x030, 0x0C3, 0x0A8, 0x022, 0x00A, 0x014, 0x01A,
516 0x0B2, 0x0C9, 0x0C7, 0x0ED, 0x0AA, 0x029, 0x094, 0x075, 0x00D, 0x0AC, 0x00C,
517 0x0F4, 0x0BB, 0x0C5, 0x03F, 0x0FD, 0x0D9, 0x09C, 0x04F, 0x0D5, 0x084, 0x01E,
518 0x0B1, 0x081, 0x069, 0x0B4, 0x009, 0x0B8, 0x03C, 0x0AF, 0x0A3, 0x008, 0x0BF,
519 0x0E0, 0x09A, 0x0D7, 0x0F7, 0x08C, 0x067, 0x066, 0x0AE, 0x0D4, 0x04C, 0x0A5,
520 0x0EC, 0x0F9, 0x0B6, 0x064, 0x078, 0x006, 0x05B, 0x09B, 0x0F2, 0x099, 0x0CE,
521 0x0DB, 0x053, 0x055, 0x065, 0x08D, 0x007, 0x033, 0x004, 0x037, 0x092, 0x026,
522 0x023, 0x0B5, 0x058, 0x0DA, 0x02F, 0x0B3, 0x040, 0x05E, 0x07F, 0x04B, 0x062,
523 0x080, 0x0E4, 0x06F, 0x073, 0x01D, 0x0DF, 0x017, 0x0CC, 0x028, 0x025, 0x02D,
524 0x0EE, 0x03A, 0x098, 0x0E2, 0x001, 0x0EB, 0x0DD, 0x0BC, 0x090, 0x0B0, 0x0FC,
525 0x095, 0x076, 0x093, 0x046, 0x057, 0x02C, 0x02B, 0x050, 0x011, 0x00B, 0x0C1,
526 0x0F0, 0x0E7, 0x0D6, 0x021, 0x031, 0x0DE, 0x0FF, 0x0D8, 0x012, 0x0A6, 0x04D,
527 0x08A, 0x013, 0x043, 0x045, 0x038, 0x0D2, 0x087, 0x0A0, 0x0EF, 0x082, 0x0F1,
528 0x047, 0x089, 0x06A, 0x0C8, 0x054, 0x01B, 0x016, 0x07E, 0x079, 0x0BD, 0x06B,
529 0x091, 0x0A2, 0x071, 0x036, 0x0B7, 0x003, 0x03D, 0x072, 0x0C6, 0x044, 0x08B,
530 0x0CF, 0x015, 0x09F, 0x032, 0x0C4, 0x077, 0x083, 0x063, 0x020, 0x088, 0x0F6,
531 0x0AD, 0x0F3, 0x0E8, 0x04A, 0x0E9, 0x035, 0x01C, 0x05F, 0x019, 0x01F, 0x07D,
532 0x070, 0x0FB, 0x0D1, 0x051, 0x010, 0x0D3, 0x02E, 0x061, 0x09D, 0x05C, 0x02A,
533 0x042, 0x0BE, 0x0E6};
535static unsigned char Encode_table[256];
536static unsigned char Decode_table[256];
538static bool cm93_decode_table_created;
547 virtual wxDirTraverseResult OnFile(
const wxString &filename) {
548 wxString name = filename.AfterLast(wxFileName::GetPathSeparator()).Lower();
549 if (name == wxT(
"cm93obj.dic")) {
554 return wxDIR_CONTINUE;
557 virtual wxDirTraverseResult OnDir(
const wxString &WXUNUSED(dirname)) {
558 return wxDIR_CONTINUE;
565cm93_dictionary::cm93_dictionary() {
566 m_S57ClassArray = NULL;
568 m_GeomTypeArray = NULL;
570 m_ValTypeArray = NULL;
575bool cm93_dictionary::LoadDictionary(
const wxString &dictionary_dir) {
578 wxString dir(dictionary_dir);
579 bool ret_val =
false;
581 wxChar sep = wxFileName::GetPathSeparator();
582 if (dir.Last() != sep) dir.Append(sep);
589 sf.Append(_T (
"CM93OBJ.DIC" ));
591 if (!wxFileName::FileExists(sf)) {
593 sf.Append(_T (
"cm93obj.dic" ));
594 if (!wxFileName::FileExists(sf))
return false;
598 if (!file.Open(sf))
return false;
600 nline = file.GetLineCount();
602 if (!nline)
return false;
607 for (i = 0; i < nline; i++) {
608 line = file.GetLine(i);
610 wxStringTokenizer tkz(line, wxT(
"|"));
614 wxString class_name = tkz.GetNextToken();
617 wxString token = tkz.GetNextToken();
619 token.ToLong(&liclass);
620 int iclass = liclass;
621 if (iclass > iclass_max) iclass_max = iclass;
624 wxString geo_type = tkz.GetNextToken();
628 m_max_class = iclass_max;
631 m_S57ClassArray =
new wxArrayString;
632 m_S57ClassArray->Add(_T (
"NULLNM" ), iclass_max + 1);
635 m_GeomTypeArray = (
int *)malloc((iclass_max + 1) *
sizeof(int));
638 for (i = 0; i < nline; i++) {
639 line = file.GetLine(i);
641 wxStringTokenizer tkz(line, wxT(
"|"));
645 wxString class_name = tkz.GetNextToken();
648 wxString token = tkz.GetNextToken();
650 token.ToLong(&liclass);
651 int iclass = liclass;
654 wxString geo_type = tkz.GetNextToken();
656 m_S57ClassArray->Insert(class_name, iclass);
657 m_S57ClassArray->RemoveAt(iclass + 1);
660 wxChar geo_type_primary = geo_type[0];
662 if (geo_type_primary ==
'A')
664 else if (geo_type_primary ==
'L')
666 else if (geo_type_primary ==
'P')
673 m_GeomTypeArray[iclass] = igeom_type;
681 sfa.Append(_T (
"ATTRLUT.DIC" ));
683 if (!wxFileName::FileExists(sfa)) {
685 sfa.Append(_T (
"attrlut.dic" ));
688 if (wxFileName::FileExists(sfa)) {
689 wxFFileInputStream filea(sfa);
695 while (!filea.Eof()) {
699 char a = filea.GetC();
700 if (filea.Eof())
break;
702 if (a == 0x0a)
break;
705 if (!line.StartsWith((
const wxChar *)wxT(
";"))) {
706 wxStringTokenizer tkz(line, wxT(
"|"));
709 wxString class_name = tkz.GetNextToken();
712 wxString token = tkz.GetNextToken();
714 token.ToLong(&liattr);
716 if (iattr > iattr_max) iattr_max = iattr;
721 m_max_attr = iattr_max;
727 m_AttrArray =
new wxArrayString;
728 m_AttrArray->Add(_T (
"NULLNM" ), iattr_max + 1);
731 m_ValTypeArray = (
char *)malloc((iattr_max + 1) *
sizeof(char));
734 while (!filea.Eof()) {
738 char a = filea.GetC();
739 if (filea.Eof())
break;
741 if (a == 0x0a)
break;
744 if (!line.StartsWith((
const wxChar *)wxT(
";"))) {
745 wxStringTokenizer tkz(line, wxT(
"|"));
748 wxString attr_name = tkz.GetNextToken();
751 wxString token = tkz.GetNextToken();
753 token.ToLong(&liattr);
756 m_AttrArray->Insert(attr_name, iattr);
757 m_AttrArray->RemoveAt(iattr + 1);
760 token = tkz.GetNextToken();
761 token = tkz.GetNextToken();
762 token = tkz.GetNextToken();
763 token = tkz.GetNextToken().Trim();
766 if (token.IsSameAs(_T (
"aFLOAT" )))
768 else if (token.IsSameAs(_T (
"aBYTE" )))
770 else if (token.IsSameAs(_T (
"aSTRING" )))
772 else if (token.IsSameAs(_T (
"aCMPLX" )))
774 else if (token.IsSameAs(_T (
"aLIST" )))
776 else if (token.IsSameAs(_T (
"aWORD10" )))
778 else if (token.IsSameAs(_T (
"aLONG" )))
781 m_ValTypeArray[iattr] = atype;
795 sfa.Append(_T (
"CM93ATTR.DIC" ));
797 if (!wxFileName::FileExists(sfa)) {
799 sfa.Append(_T (
"cm93attr.dic" ));
802 if (wxFileName::FileExists(sfa)) {
803 wxFFileInputStream filea(sfa);
809 while (!filea.Eof()) {
813 char a = filea.GetC();
814 if (filea.Eof())
break;
816 if (a == 0x0a)
break;
819 if (!line.StartsWith((
const wxChar *)wxT(
";"))) {
820 wxStringTokenizer tkz(line, wxT(
"|"));
821 if (tkz.CountTokens()) {
823 wxString class_name = tkz.GetNextToken();
826 wxString token = tkz.GetNextToken();
828 token.ToLong(&liattr);
830 if (iattr > iattr_max) iattr_max = iattr;
835 m_max_attr = iattr_max;
841 m_AttrArray =
new wxArrayString;
842 m_AttrArray->Add(_T (
"NULLNM" ), iattr_max + 1);
845 m_ValTypeArray = (
char *)malloc((iattr_max + 1) *
sizeof(char));
846 for (
int iat = 0; iat < iattr_max + 1; iat++) m_ValTypeArray[iat] =
'?';
849 while (!filea.Eof()) {
853 char a = filea.GetC();
854 if (filea.Eof())
break;
856 if (a == 0x0a)
break;
859 if (!line.StartsWith((
const wxChar *)wxT(
";"))) {
860 wxStringTokenizer tkz(line, wxT(
"|\r\n"));
861 if (tkz.CountTokens() >= 3) {
863 wxString attr_name = tkz.GetNextToken();
866 wxString token = tkz.GetNextToken();
868 token.ToLong(&liattr);
871 m_AttrArray->Insert(attr_name, iattr);
872 m_AttrArray->RemoveAt(iattr + 1);
874 token = tkz.GetNextToken().Trim();
877 if (token.IsSameAs(_T (
"aFLOAT" )))
879 else if (token.IsSameAs(_T (
"aBYTE" )))
881 else if (token.IsSameAs(_T (
"aSTRING" )))
883 else if (token.IsSameAs(_T (
"aCMPLX" )))
885 else if (token.IsSameAs(_T (
"aLIST" )))
887 else if (token.IsSameAs(_T (
"aWORD10" )))
889 else if (token.IsSameAs(_T (
"aLONG" )))
892 m_ValTypeArray[iattr] = atype;
905 wxString msg(_T (
"Loaded CM93 Dictionary from " ));
913wxString cm93_dictionary::GetClassName(
int iclass) {
914 if ((iclass > m_max_class) || (iclass < 0))
915 return (_T (
"Unknown" ));
917 return (m_S57ClassArray->Item(iclass));
920wxString cm93_dictionary::GetAttrName(
int iattr) {
921 if ((iattr > m_max_attr) || (iattr < 0))
922 return (_T (
"UnknownAttr" ));
924 return (m_AttrArray->Item(iattr));
928char cm93_dictionary::GetAttrType(
int iattr) {
929 if ((iattr > m_max_attr) || (iattr < 0))
932 return (m_ValTypeArray[iattr]);
935cm93_dictionary::~cm93_dictionary() {
936 delete m_S57ClassArray;
937 free(m_GeomTypeArray);
939 free(m_ValTypeArray);
944void CreateDecodeTable(
void) {
946 for (i = 0; i < 256; i++) {
947 Encode_table[i] = Table_0[i] ^ 8;
950 for (i = 0; i < 256; i++) {
951 unsigned char a = Encode_table[i];
952 Decode_table[(int)a] = (
unsigned char)i;
956static int read_and_decode_bytes(FILE *stream,
void *p,
int nbytes) {
961 if (fread(p, nbytes, 1, stream) != 1)
return 0;
964 unsigned char *q = (
unsigned char *)p;
966 for (
int i = 0; i < nbytes; i++) {
967 unsigned char a = *q;
969 unsigned char c = Decode_table[b];
977static int read_and_decode_double(FILE *stream,
double *p) {
980 if (fread(&t,
sizeof(
double), 1, stream) != 1)
return 0;
983 unsigned char *q = (
unsigned char *)&t;
985 for (
unsigned int i = 0; i <
sizeof(double); i++) {
986 unsigned char a = *q;
988 unsigned char c = Decode_table[b];
1000static int read_and_decode_int(FILE *stream,
int *p) {
1003 if (fread(&t,
sizeof(
int), 1, stream) != 1)
return 0;
1006 unsigned char *q = (
unsigned char *)&t;
1008 for (
unsigned int i = 0; i <
sizeof(int); i++) {
1009 unsigned char a = *q;
1011 unsigned char c = Decode_table[b];
1023static int read_and_decode_ushort(FILE *stream,
unsigned short *p) {
1026 if (fread(&t,
sizeof(
unsigned short), 1, stream) != 1)
return 0;
1029 unsigned char *q = (
unsigned char *)&t;
1031 for (
unsigned int i = 0; i <
sizeof(
unsigned short); i++) {
1032 unsigned char a = *q;
1034 unsigned char c = Decode_table[b];
1048int Get_CM93_CellIndex(
double lat,
double lon,
int scale) {
1083 double lon1 = (lon + 360.) * 3.;
1084 while (lon1 >= 1080.0) lon1 -= 1080.0;
1085 unsigned short lon2 = (
unsigned short)floor(lon1 / dval);
1086 unsigned short lon3 = lon2 * dval;
1091 double lat1 = (lat * 3.) + 270. - 30;
1092 unsigned short lat2 = (
unsigned short)floor(lat1 / dval);
1093 unsigned short lat3 = lat2 * dval;
1095 retval += (lat3 + 30) * 10000;
1103void Get_CM93_Cell_Origin(
int cellindex,
int scale,
double *lat,
double *lon) {
1105 double idx1 = cellindex % 10000;
1106 double lont = (idx1 / 3.);
1111 int idx2 = cellindex / 10000;
1112 double lat1 = idx2 - 270.;
1118bool Is_CM93Cell_Present(wxString &fileprefix,
double lat,
double lon,
1124 switch (scale_index) {
1172 int cellindex = Get_CM93_CellIndex(lat, lon,
scale);
1177 int ilat = cellindex / 10000;
1178 int ilon = cellindex % 10000;
1180 int jlat = (((ilat - 30) / dval) * dval) + 30;
1181 int jlon = (ilon / dval) * dval;
1183 int ilatroot = (((ilat - 30) / 60) * 60) + 30;
1184 int ilonroot = (ilon / 60) * 60;
1187 fileroot.Printf(_T (
"%04d%04d" ), ilatroot, ilonroot);
1188 appendOSDirSep(&fileroot);
1190 wxString sdir(fileprefix);
1195 tfile.Printf(_T (
"?%03d%04d." ), jlat, jlon);
1196 tfile += scale_char;
1199 if (!::wxDirExists(sdir)) {
1200 wxString old_scalechar(scale_char);
1201 wxString new_scalechar = old_scalechar.Lower();
1205 sdir += new_scalechar;
1208 if (::wxDirExists(sdir)) {
1211 wxArrayString file_array;
1212 int n_files = dir.GetAllFiles(sdir, &file_array, tfile, wxDIR_FILES);
1214 if (n_files)
return true;
1217 wxString old_scalechar(scale_char);
1218 wxString new_scalechar = old_scalechar.Lower();
1221 tfile1.Printf(_T (
"?%03d%04d." ), jlat, jlon);
1222 tfile1 += new_scalechar;
1224 int n_files1 = dir.GetAllFiles(sdir, &file_array, tfile1, wxDIR_FILES);
1226 if (n_files1)
return true;
1230 dir.GetAllFiles(sdir, &file_array, tfile + _T(
".xz"), wxDIR_FILES);
1232 if (n_files)
return true;
1238static bool read_header_and_populate_cib(FILE *stream,
Cell_Info_Block *pCIB) {
1247 memset((
void *)&header, 0,
sizeof(header));
1249 read_and_decode_double(stream, &header.lon_min);
1250 read_and_decode_double(stream, &header.lat_min);
1251 read_and_decode_double(stream, &header.lon_max);
1252 read_and_decode_double(stream, &header.lat_max);
1254 read_and_decode_double(stream, &header.easting_min);
1255 read_and_decode_double(stream, &header.northing_min);
1256 read_and_decode_double(stream, &header.easting_max);
1257 read_and_decode_double(stream, &header.northing_max);
1259 read_and_decode_ushort(stream, &header.usn_vector_records);
1260 read_and_decode_int(stream, &header.n_vector_record_points);
1261 read_and_decode_int(stream, &header.m_46);
1262 read_and_decode_int(stream, &header.m_4a);
1263 read_and_decode_ushort(stream, &header.usn_point3d_records);
1264 read_and_decode_int(stream, &header.m_50);
1265 read_and_decode_int(stream, &header.m_54);
1266 read_and_decode_ushort(stream, &header.usn_point2d_records);
1267 read_and_decode_ushort(stream, &header.m_5a);
1268 read_and_decode_ushort(stream, &header.m_5c);
1269 read_and_decode_ushort(stream, &header.usn_feature_records);
1271 read_and_decode_int(stream, &header.m_60);
1272 read_and_decode_int(stream, &header.m_64);
1273 read_and_decode_ushort(stream, &header.m_68);
1274 read_and_decode_ushort(stream, &header.m_6a);
1275 read_and_decode_ushort(stream, &header.m_6c);
1276 read_and_decode_int(stream, &header.m_nrelated_object_pointers);
1278 read_and_decode_int(stream, &header.m_72);
1279 read_and_decode_ushort(stream, &header.m_76);
1281 read_and_decode_int(stream, &header.m_78);
1282 read_and_decode_int(stream, &header.m_7c);
1286 double delta_x = header.easting_max - header.easting_min;
1288 delta_x += CM93_semimajor_axis_meters * 2.0 * PI;
1290 pCIB->transform_x_rate = delta_x / 65535;
1291 pCIB->transform_y_rate = (header.northing_max - header.northing_min) / 65535;
1293 pCIB->transform_x_origin = header.easting_min;
1294 pCIB->transform_y_origin = header.northing_min;
1296 pCIB->min_lat = header.lat_min;
1297 pCIB->min_lon = header.lon_min;
1305 pCIB->m_nfeature_records = header.usn_feature_records;
1306 pCIB->pobject_block =
1307 (
Object *)calloc(pCIB->m_nfeature_records *
sizeof(
Object), 1);
1309 pCIB->m_n_point2d_records = header.usn_point2d_records;
1310 pCIB->p2dpoint_array =
1313 pCIB->pprelated_object_block =
1314 (
Object **)malloc(header.m_nrelated_object_pointers *
sizeof(
Object *));
1316 pCIB->object_vector_record_descriptor_block =
1320 pCIB->attribute_block_top = (
unsigned char *)calloc(header.m_78, 1);
1322 pCIB->m_nvector_records = header.usn_vector_records;
1326 pCIB->pvector_record_block_top =
1329 pCIB->m_n_point3d_records = header.usn_point3d_records;
1333 pCIB->p3dpoint_array =
1339static bool read_vector_record_table(FILE *stream,
int count,
1344 cm93_point *q = pCIB->pvector_record_block_top;
1346 for (
int iedge = 0; iedge < count; iedge++) {
1349 unsigned short npoints;
1350 brv = !(read_and_decode_ushort(stream, &npoints) == 0);
1351 if (!brv)
return false;
1353 p->n_points = npoints;
1361 unsigned short x, y;
1362 for (
int index = 0; index < p->n_points; index++) {
1363 if (!read_and_decode_ushort(stream, &x))
return false;
1364 if (!read_and_decode_ushort(stream, &y))
return false;
1380 for (
int j = 0; j < p->n_points - 1; j++) {
1381 if (t->x >= p->x_max) p->x_max = t->x;
1383 if (t->x <= p->x_min) p->x_min = t->x;
1385 if (t->y >= p->y_max) p->y_max = t->y;
1387 if (t->y <= p->y_max) p->y_min = t->y;
1402static bool read_3dpoint_table(FILE *stream,
int count,
Cell_Info_Block *pCIB) {
1406 for (
int i = 0; i < count; i++) {
1407 unsigned short npoints;
1408 if (!read_and_decode_ushort(stream, &npoints))
return false;
1410 p->n_points = npoints;
1418 unsigned short x, y, z;
1419 for (
int index = 0; index < p->n_points; index++) {
1420 if (!read_and_decode_ushort(stream, &x))
return false;
1421 if (!read_and_decode_ushort(stream, &y))
return false;
1422 if (!read_and_decode_ushort(stream, &z))
return false;
1436static bool read_2dpoint_table(FILE *stream,
int count,
Cell_Info_Block *pCIB) {
1440 unsigned short x, y;
1441 for (
int index = 0; index < count; index++) {
1442 if (!read_and_decode_ushort(stream, &x))
return false;
1443 if (!read_and_decode_ushort(stream, &y))
return false;
1445 pCIB->p2dpoint_array[index].x = x;
1446 pCIB->p2dpoint_array[index].y = y;
1452static bool read_feature_record_table(FILE *stream,
int n_features,
1455 Object *pobj = pCIB->pobject_block;
1458 pCIB->object_vector_record_descriptor_block;
1461 pCIB->pprelated_object_block;
1464 unsigned char *puc_var10 = pCIB->attribute_block_top;
1467 unsigned char object_type;
1468 unsigned char geom_prim;
1469 unsigned short obj_desc_bytes = 0;
1472 unsigned short index;
1473 unsigned short n_elements;
1475 for (
int iobject = 0; iobject < n_features; iobject++) {
1477 read_and_decode_bytes(stream, &object_type, 1);
1478 read_and_decode_bytes(stream, &geom_prim,
1480 read_and_decode_ushort(stream,
1483 pobj->otype = object_type;
1484 pobj->geotype = geom_prim;
1486 switch (pobj->geotype & 0x0f) {
1489 if (!read_and_decode_ushort(stream, &n_elements))
return false;
1491 pobj->n_geom_elements = n_elements;
1492 t = (pobj->n_geom_elements * 2) + 2;
1493 obj_desc_bytes -= t;
1496 pobject_vector_collection;
1500 for (
unsigned short i = 0; i < pobj->n_geom_elements; i++) {
1501 if (!read_and_decode_ushort(stream, &index))
return false;
1503 if ((index & 0x1fff) > pCIB->m_nvector_records)
1509 pobject_vector_collection->pGeom_Description = u;
1510 pobject_vector_collection->segment_usage =
1511 (
unsigned char)(index >> 13);
1513 pobject_vector_collection++;
1521 if (!read_and_decode_ushort(
1522 stream, &n_elements))
1525 pobj->n_geom_elements = n_elements;
1526 t = (pobj->n_geom_elements * 2) + 2;
1527 obj_desc_bytes -= t;
1530 pobject_vector_collection;
1534 for (
unsigned short i = 0; i < pobj->n_geom_elements; i++) {
1535 unsigned short geometry_index;
1537 if (!read_and_decode_ushort(stream, &geometry_index))
return false;
1539 if ((geometry_index & 0x1fff) > pCIB->m_nvector_records)
1544 geometry_index & 0x1fff)];
1546 pobject_vector_collection->pGeom_Description = u;
1547 pobject_vector_collection->segment_usage =
1548 (
unsigned char)(geometry_index >> 13);
1550 pobject_vector_collection++;
1557 if (!read_and_decode_ushort(stream, &index))
return false;
1559 obj_desc_bytes -= 2;
1561 pobj->n_geom_elements = 1;
1563 pobj->pGeometry = &pCIB->p2dpoint_array[index];
1569 if (!read_and_decode_ushort(stream, &index))
return false;
1570 obj_desc_bytes -= 2;
1572 pobj->n_geom_elements = 1;
1575 &pCIB->point3d_descriptor_block[index];
1582 if ((pobj->geotype & 0x10) == 0x10)
1584 unsigned char nrelated;
1585 if (!read_and_decode_bytes(stream, &nrelated, 1))
return false;
1587 pobj->n_related_objects = nrelated;
1588 t = (pobj->n_related_objects * 2) + 1;
1589 obj_desc_bytes -= t;
1591 pobj->p_related_object_pointer_array = p_relob;
1592 p_relob += pobj->n_related_objects;
1594 Object **w = (
Object **)pobj->p_related_object_pointer_array;
1595 for (
unsigned char j = 0; j < pobj->n_related_objects; j++) {
1596 if (!read_and_decode_ushort(stream, &index))
return false;
1598 if (index > pCIB->m_nfeature_records)
1602 Object *prelated_object = &pCIB->pobject_block[index];
1603 *w = prelated_object;
1605 prelated_object->p_related_object_pointer_array =
1611 if ((pobj->geotype & 0x20) == 0x20) {
1612 unsigned short nrelated;
1613 if (!read_and_decode_ushort(stream, &nrelated))
return false;
1615 pobj->n_related_objects = (
unsigned char)(nrelated & 0xFF);
1616 obj_desc_bytes -= 2;
1619 if ((pobj->geotype & 0x40) == 0x40) {
1622 if ((pobj->geotype & 0x80) == 0x80)
1624 unsigned char nattr;
1625 if (!read_and_decode_bytes(stream, &nattr, 1))
return false;
1627 pobj->n_attributes = nattr;
1628 obj_desc_bytes -= 5;
1630 pobj->attributes_block = puc_var10;
1631 puc_var10 += obj_desc_bytes;
1633 puc10count += obj_desc_bytes;
1635 if (!read_and_decode_bytes(stream, pobj->attributes_block,
1639 if ((pobj->geotype & 0x0f) == 1) {
1650 printf(
"catch on read_feature_record_table\n");
1656bool Ingest_CM93_Cell(
const char *cell_file_name,
Cell_Info_Block *pCIB) {
1661 FILE *flstream = fopen(cell_file_name,
"rb");
1662 if (!flstream)
return false;
1664 fseek(flstream, 0, SEEK_END);
1665 file_length = ftell(flstream);
1669 FILE *stream = fopen(cell_file_name,
"rb");
1670 if (!stream)
return false;
1674 unsigned short word0 = 0;
1680 read_and_decode_ushort(stream,
1682 read_and_decode_int(stream, &int0);
1683 read_and_decode_int(stream, &int1);
1685 int test = word0 + int0 + int1;
1686 if (test != file_length) {
1693 if (!read_header_and_populate_cib(stream, pCIB)) {
1698 if (!read_vector_record_table(stream, pCIB->m_nvector_records, pCIB)) {
1703 if (!read_3dpoint_table(stream, pCIB->m_n_point3d_records, pCIB)) {
1708 if (!read_2dpoint_table(stream, pCIB->m_n_point2d_records, pCIB)) {
1713 if (!read_feature_record_table(stream, pCIB->m_nfeature_records, pCIB)) {
1736cm93chart::cm93chart() {
1737 m_ChartType = CHART_TYPE_CM93;
1740 if (!cm93_decode_table_created) {
1741 CreateDecodeTable();
1742 cm93_decode_table_created =
true;
1748 m_current_cell_vearray_offset = 0;
1750 m_ncontour_alloc = 100;
1751 m_pcontour_array = (
int *)malloc(m_ncontour_alloc *
sizeof(
int));
1761 m_pDrawBuffer = (wxPoint *)malloc(4 *
sizeof(wxPoint));
1762 m_nDrawBufferSize = 1;
1765 m_this_chart_context = (chart_context *)calloc(
sizeof(chart_context), 1);
1766 m_this_chart_context->chart =
this;
1770cm93chart::~cm93chart() {
1771 free(m_pcontour_array);
1775 free(m_pDrawBuffer);
1778void cm93chart::Unload_CM93_Cell(
void) {
1779 free(m_CIB.pobject_block);
1781 free(m_CIB.p2dpoint_array);
1782 free(m_CIB.pprelated_object_block);
1783 free(m_CIB.object_vector_record_descriptor_block);
1784 free(m_CIB.attribute_block_top);
1785 free(m_CIB.edge_vector_descriptor_block);
1786 free(m_CIB.pvector_record_block_top);
1787 free(m_CIB.point3d_descriptor_block);
1788 free(m_CIB.p3dpoint_array);
1797double cm93chart::GetNormalScaleMin(
double canvas_scale_factor,
1798 bool b_allow_overzoom) {
1799 switch (GetNativeScale()) {
1821double cm93chart::GetNormalScaleMax(
double canvas_scale_factor,
1829 switch (GetNativeScale()) {
1851void cm93chart::GetPointPix(ObjRazRules *rzRules,
float north,
float east,
1853 wxPoint2DDouble en(east, north);
1854 GetPointPix(rzRules, &en, r, 1);
1857void cm93chart::GetPointPix(ObjRazRules *rzRules, wxPoint2DDouble *en,
1858 wxPoint *r,
int nPoints) {
1859 S57Obj *obj = rzRules->obj;
1861 double xr = obj->x_rate;
1862 double xo = obj->x_origin;
1863 double yr = obj->y_rate;
1864 double yo = obj->y_origin;
1866 if (m_vp_current.m_projection_type == PROJECTION_MERCATOR) {
1867 if (m_vp_current.GetBBox().GetMaxLon() >= 180. &&
1868 rzRules->obj->BBObj.GetMaxLon() < m_vp_current.GetBBox().GetMinLon())
1869 xo += mercator_k0 * WGS84_semimajor_axis_meters * 2.0 * PI;
1870 else if ((m_vp_current.GetBBox().GetMinLon() <= -180. &&
1871 rzRules->obj->BBObj.GetMinLon() >
1872 m_vp_current.GetBBox().GetMaxLon()) ||
1873 (rzRules->obj->BBObj.GetMaxLon() >= 180 &&
1874 m_vp_current.GetBBox().GetMinLon() <= 0.))
1875 xo -= mercator_k0 * WGS84_semimajor_axis_meters * 2.0 * PI;
1877 for (
int i = 0; i < nPoints; i++) {
1878 double valx = (en[i].m_x * xr) + xo;
1879 double valy = (en[i].m_y * yr) + yo;
1881 r[i].x = ((valx - m_easting_vp_center) * m_view_scale_ppm) +
1882 m_pixx_vp_center + 0.5;
1883 r[i].y = m_pixy_vp_center -
1884 ((valy - m_northing_vp_center) * m_view_scale_ppm) + 0.5;
1887 for (
int i = 0; i < nPoints; i++) {
1888 double valx = (en[i].m_x * xr) + xo;
1889 double valy = (en[i].m_y * yr) + yo;
1892 fromSM(valx - m_easting_vp_center, valy - m_northing_vp_center,
1893 m_vp_current.
clat, m_vp_current.
clon, &lat, &lon);
1895 double rotation = m_vp_current.
rotation;
1896 m_vp_current.SetRotationAngle(0);
1898 m_vp_current.SetRotationAngle(rotation);
1903void cm93chart::GetPixPoint(
int pixx,
int pixy,
double *plat,
double *plon,
1916 double xp = (dx * cos(vpt->
skew)) - (dy * sin(vpt->
skew));
1917 double yp = (dy * cos(vpt->
skew)) + (dx * sin(vpt->
skew));
1923 fromSM(d_east, d_north, vpt->
clat, vpt->
clon, &slat, &slon);
1925 if (slon > 360.) slon -= 360.;
1933 if (IsCacheValid()) {
1943 vp_last.
GetLLFromPix(wxPoint(round(p.m_x), round(p.m_y)), &xlat, &xlon);
1945 double prev_easting_c, prev_northing_c;
1946 toSM(vp_last.
clat, vp_last.
clon, ref_lat, ref_lon, &prev_easting_c,
1949 double easting_c, northing_c;
1950 toSM(vp_proposed.
clat, vp_proposed.
clon, ref_lat, ref_lon, &easting_c,
1953 double delta_pix_x =
1955 int dpix_x = (int)round(delta_pix_x);
1956 double dpx = dpix_x;
1958 double delta_pix_y =
1960 int dpix_y = (int)round(delta_pix_y);
1961 double dpy = dpix_y;
1963 double c_east_d = (dpx / vp_proposed.
view_scale_ppm) + prev_easting_c;
1964 double c_north_d = (dpy / vp_proposed.
view_scale_ppm) + prev_northing_c;
1967 fromSM(c_east_d, c_north_d, ref_lat, ref_lon, &xlat, &xlon);
1969 vp_proposed.
clon = xlon;
1970 vp_proposed.
clat = xlat;
1983void cm93chart::SetVPParms(
const ViewPort &vpt) {
1984 if (m_vp_current == vpt) {
1995 toSM(vpt.
clat, vpt.
clon, ref_lat, ref_lon, &m_easting_vp_center,
1996 &m_northing_vp_center);
1998 vp_transform.easting_vp_center = m_easting_vp_center;
1999 vp_transform.northing_vp_center = m_northing_vp_center;
2004 LLBBox box = vptl.GetBBox();
2005 double ll_lon = box.GetMinLon();
2006 double ll_lat = box.GetMinLat();
2008 double ur_lon = box.GetMaxLon();
2009 double ur_lat = box.GetMaxLat();
2012 "cm93chart::SetVPParms ll_lon: %g ll_lat: %g ur_lon: %g ur_lat: "
2014 ll_lon, ll_lat, ur_lon, ur_lat, m_dval);
2018 std::vector<int> vpcells = GetVPCellArray(vpt);
2024 for (
unsigned int i = 0; i < vpcells.size(); i++) {
2025 bcell_is_in =
false;
2026 for (
unsigned int j = 0; j < m_cells_loaded_array.size(); j++) {
2027 if (vpcells[i] == m_cells_loaded_array[j]) {
2035#ifndef __OCPN__ANDROID__
2036 AbstractPlatform::ShowBusySpinner();
2038 int cell_index = vpcells[i];
2040 if (loadcell_in_sequence(cell_index,
'0'))
2042 ProcessVectorEdges();
2045 ForceEdgePriorityEvaluate();
2047 m_cells_loaded_array.push_back(cell_index);
2052 char loadcell_key =
'A';
2056 while (loadcell_in_sequence(cell_index, loadcell_key)) {
2057 ProcessVectorEdges();
2058 CreateObjChain(cell_index, (
int)loadcell_key, vpt.
view_scale_ppm);
2060 ForceEdgePriorityEvaluate();
2062 if (std::find(m_cells_loaded_array.begin(), m_cells_loaded_array.end(),
2063 cell_index) == m_cells_loaded_array.end())
2064 m_cells_loaded_array.push_back(cell_index);
2071 AssembleLineGeometry();
2073 ClearDepthContourArray();
2074 BuildDepthContourArray();
2077 m_this_chart_context->m_pvc_hash = &Get_vc_hash();
2078 m_this_chart_context->m_pve_hash = &Get_ve_hash();
2080 m_this_chart_context->pFloatingATONArray = pFloatingATONArray;
2081 m_this_chart_context->pRigidATONArray = pRigidATONArray;
2082 m_this_chart_context->chart =
this;
2083 m_this_chart_context->chart_type = GetChartType();
2085 m_this_chart_context->safety_contour = m_next_safe_cnt;
2086 m_this_chart_context->vertex_buffer = GetLineVertexBuffer();
2087 m_this_chart_context->pt2GetAssociatedObjects =
2088 &s57chart::GetAssociatedObjects;
2091 for (
int i = 0; i < PI_PRIO_NUM; ++i) {
2092 for (
int j = 0; j < PI_LUPNAME_NUM; j++) {
2093 ObjRazRules *top = razRules[i][j];
2095 if (top->obj) top->obj->m_chart_context = m_this_chart_context;
2101 AbstractPlatform::HideBusySpinner();
2106std::vector<int> cm93chart::GetVPCellArray(
const ViewPort &vpt) {
2109 LLBBox box = vptl.GetBBox();
2110 double ll_lon = box.GetMinLon();
2111 double ll_lat = box.GetMinLat();
2113 double ur_lon = box.GetMaxLon();
2114 double ur_lat = box.GetMaxLat();
2117 ur_lat = wxMin(ur_lat, 79.99999);
2120 ur_lat = wxMin(ur_lat, 79.99999);
2129 std::vector<int> vpcells;
2131 int lower_left_cell = Get_CM93_CellIndex(ll_lat, ll_lon, GetNativeScale());
2132 vpcells.push_back(lower_left_cell);
2135 printf(
"cm93chart::GetVPCellArray Adding %d\n", lower_left_cell);
2138 Get_CM93_Cell_Origin(lower_left_cell, GetNativeScale(), &rlat, &rlon);
2143 int loni_0 = (int)wxRound(rlon * 3);
2144 int loni_20 = loni_0 + (int)m_dval;
2145 int lati_20 = (int)wxRound(rlat * 3);
2147 while (lati_20 < (ur_lat * 3.)) {
2148 while (loni_20 < (ur_lon * 3.)) {
2149 unsigned int next_lon = loni_20 + 1080;
2150 while (next_lon >= 1080) next_lon -= 1080;
2152 unsigned int next_cell = next_lon;
2154 next_cell += (lati_20 + 270) * 10000;
2156 vpcells.push_back((
int)next_cell);
2158 printf(
"cm93chart::GetVPCellArray Adding %d\n", next_cell);
2160 loni_20 += (int)m_dval;
2162 lati_20 += (int)m_dval;
2169void cm93chart::ProcessVectorEdges(
void) {
2172 auto &vehash = Get_ve_hash();
2174 m_current_cell_vearray_offset =
2178 for (
int iedge = 0; iedge < m_CIB.m_nvector_records; iedge++) {
2179 VE_Element *vep =
new VE_Element;
2180 vep->index = iedge + m_current_cell_vearray_offset;
2181 vep->nCount = pgd->n_points;
2182 vep->pPoints = NULL;
2183 vep->max_priority = -99;
2185 if (pgd->n_points) {
2186 float *pPoints = (
float *)malloc(pgd->n_points * 2 *
sizeof(
float));
2187 vep->pPoints = pPoints;
2192 double east_max = -1e7;
2193 double east_min = 1e7;
2194 double north_max = -1e7;
2195 double north_min = 1e7;
2197 for (
int ip = 0; ip < pgd->n_points; ip++) {
2198 *pPoints++ = ppt->x;
2199 *pPoints++ = ppt->y;
2201 east_max = wxMax(east_max, ppt->x);
2202 east_min = wxMin(east_min, ppt->x);
2203 north_max = wxMax(north_max, ppt->y);
2204 north_min = wxMin(north_min, ppt->y);
2210 double lat1, lon1, lat2, lon2;
2216 Transform(&p, 0, 0, &lat1, &lon1);
2220 Transform(&p, 0, 0, &lat2, &lon2);
2225 vep->edgeBBox.Set(lat1, lon1, lat2, lon2);
2228 vehash[vep->index] = vep;
2234int cm93chart::CreateObjChain(
int cell_index,
int subcell,
2235 double view_scale_ppm) {
2237 LUPname LUP_Name = PAPER_CHART;
2239 m_CIB.m_cell_mcovr_list.Clear();
2243 Object *pobjectDef = m_CIB.pobject_block;
2244 m_CIB.b_have_offsets =
false;
2246 m_CIB.b_have_user_offsets =
false;
2252 double scale = gFrame->GetBestVPScale(
this);
2253 int nativescale = GetNativeScale();
2255 while (iObj < m_CIB.m_nfeature_records) {
2256 if ((pobjectDef != NULL)) {
2257 Extended_Geometry *xgeom = BuildGeom(pobjectDef, NULL, iObj);
2262 CreateS57Obj(cell_index, iObj, subcell, pobjectDef, m_pDict, xgeom,
2263 ref_lat, ref_lon, GetNativeScale(), view_scale_ppm);
2266 wxString objnam = obj->GetAttrValueAsString(
"OBJNAM");
2267 wxString fe_name = wxString(obj->FeatureName, wxConvUTF8);
2268 if (fe_name == _T(
"_texto"))
2269 objnam = obj->GetAttrValueAsString(
"_texta");
2270 if (objnam.Len() > 0) {
2272 wxString::Format(_T(
"%i_%i"), cell_index, subcell);
2273 SendVectorChartObjectInfo(cellname, fe_name, objnam, obj->m_lat,
2274 obj->m_lon,
scale, nativescale);
2277 if (GEO_POINT == obj->Primitive_type) {
2279 if ((!strncmp(obj->FeatureName,
"LITFLT", 6)) ||
2280 (!strncmp(obj->FeatureName,
"LITVES", 6)) ||
2281 (!strncmp(obj->FeatureName,
"BOY", 3))) {
2282 pFloatingATONArray->Add(obj);
2286 if (!strncmp(obj->FeatureName,
"BCN", 3)) pRigidATONArray->Add(obj);
2289 if ((!strncmp(obj->FeatureName,
"LIT", 3)) ||
2290 (!strncmp(obj->FeatureName,
"LIGHTS", 6)) ||
2291 (!strncmp(obj->FeatureName,
"BCN", 3)) ||
2292 (!strncmp(obj->FeatureName,
"_slgto", 6)) ||
2293 (!strncmp(obj->FeatureName,
"_boygn", 6)) ||
2294 (!strncmp(obj->FeatureName,
"_bcngn", 6)) ||
2295 (!strncmp(obj->FeatureName,
"_extgn", 6)) ||
2296 (!strncmp(obj->FeatureName,
"TOWERS", 6)) ||
2297 (!strncmp(obj->FeatureName,
"BOY", 3))) {
2298 obj->bIsAton =
true;
2304 if (GEO_AREA == obj->Primitive_type) {
2305 if (!strncmp(obj->FeatureName,
"DEPARE", 6) ||
2306 !strncmp(obj->FeatureName,
"DRGARE", 6))
2307 obj->bIsAssociable =
true;
2315 switch (obj->Primitive_type) {
2319 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
2320 LUP_Name = PAPER_CHART;
2322 LUP_Name = SIMPLIFIED;
2324 if (m_b2pointLUPS) {
2326 if (PAPER_CHART == ps52plib->m_nSymbolStyle)
2327 LUPO_Name = SIMPLIFIED;
2329 LUPO_Name = PAPER_CHART;
2333 ps52plib->S52_LUPLookup(LUPO_Name, obj->FeatureName, obj);
2335 ps52plib->_LUP2rules(LUPO, obj);
2336 _insertRules(obj, LUPO,
this);
2346 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
2347 LUP_Name = PLAIN_BOUNDARIES;
2349 LUP_Name = SYMBOLIZED_BOUNDARIES;
2353 if (PLAIN_BOUNDARIES == ps52plib->m_nBoundaryStyle)
2354 LUPO_Name = SYMBOLIZED_BOUNDARIES;
2356 LUPO_Name = PLAIN_BOUNDARIES;
2360 ps52plib->S52_LUPLookup(LUPO_Name, obj->FeatureName, obj);
2362 ps52plib->_LUP2rules(LUPO, obj);
2363 _insertRules(obj, LUPO,
this);
2369 LUP = ps52plib->S52_LUPLookup(LUP_Name, obj->FeatureName, obj);
2373 wxString msg(obj->FeatureName, wxConvUTF8);
2374 msg.Prepend(_T (
" CM93 could not find LUP for " ));
2375 LogMessageOnce(msg);
2377 if (0 == obj->nRef)
delete obj;
2380 ps52plib->_LUP2rules(LUP, obj);
2383 _insertRules(obj, LUP,
this);
2386 obj->m_DisplayCat = LUP->DISC;
2389 obj->m_DPRI = LUP->DPRI -
'0';
2392 obj->m_chart_context = m_this_chart_context;
2411InitReturn cm93chart::Init(
const wxString &name, ChartInitFlag flags) {
2413 m_Description = m_FullPath;
2415 wxFileName fn(name);
2417 if (!m_prefix.Len())
2418 m_prefix = fn.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
2420 m_scalechar = fn.GetExt();
2425 switch ((m_scalechar.mb_str())[(
size_t)0]) {
2455 m_Chart_Scale =
scale;
2457 switch (GetNativeScale()) {
2488 wxString data = _T (
"CM93Chart " );
2489 data.Append(m_scalechar);
2491 s.Printf(_T (
" 1/%d" ), m_Chart_Scale);
2496 if (
scale != 20000000)
2497 m_pcovr_set->Init(m_scalechar.mb_str()[(
size_t)0], m_prefix);
2499 if (flags == THUMB_ONLY) {
2507 if (flags == HEADER_ONLY)
return CreateHeaderDataFromCM93Cell();
2512 if (m_pManager->Loadcm93Dictionary(name))
2513 m_pDict = m_pManager->m_pcm93Dict;
2515 wxLogMessage(_T (
" CM93Chart Init cannot locate CM93 dictionary." ));
2516 return INIT_FAIL_REMOVE;
2521 bReadyToRender =
true;
2526Extended_Geometry *cm93chart::BuildGeom(
Object *pobject,
2527 wxFileOutputStream *postream,
2534 int geom_type_maybe = pobject->geotype;
2536 switch (geom_type_maybe) {
2574 Extended_Geometry *ret_ptr =
new Extended_Geometry;
2576 int lon_max, lat_max, lon_min, lat_min;
2588 int nsegs = pobject->n_geom_elements;
2590 ret_ptr->n_vector_indices = nsegs;
2591 ret_ptr->pvector_index = (
int *)malloc(nsegs * 3 *
sizeof(
int));
2594 int n_maxvertex = 0;
2595 for (
int i = 0; i < nsegs; i++) {
2598 n_maxvertex += pgd->n_points;
2604 wxPoint2DDouble *pPoints =
2605 (wxPoint2DDouble *)calloc((n_maxvertex) *
sizeof(wxPoint2DDouble), 1);
2608 int n_prev_vertex_index = 1;
2609 bool bnew_ring =
true;
2618 cur_end_point.x = 1;
2619 cur_end_point.y = 1;
2621 int n_max_points = -1;
2622 while (iseg < nsegs) {
2623 int type_seg = psegs[iseg].segment_usage;
2628 int npoints = pgd->n_points;
2631 n_max_points = wxMax(n_max_points, npoints);
2637 if ((type_seg & 4) == 0)
2638 start_point = rseg[0];
2640 start_point = rseg[npoints - 1];
2643 if (((type_seg & 4) == 0)) {
2644 cur_end_point = rseg[npoints - 1];
2645 for (
int j = 0; j < npoints; j++) {
2649 lon_max = wxMax(lon_max, rseg[j].x);
2650 lon_min = wxMin(lon_min, rseg[j].x);
2651 lat_max = wxMax(lat_max, rseg[j].y);
2652 lat_min = wxMin(lat_min, rseg[j].y);
2655 pPoints[ip].m_x = rseg[j].x;
2656 pPoints[ip].m_y = rseg[j].y;
2659 }
else if ((type_seg & 4) == 4)
2661 cur_end_point = rseg[0];
2662 for (
int j = npoints - 1; j >= 0; j--) {
2666 lon_max = wxMax(lon_max, rseg[j].x);
2667 lon_min = wxMin(lon_min, rseg[j].x);
2668 lat_max = wxMax(lat_max, rseg[j].y);
2669 lat_min = wxMin(lat_min, rseg[j].y);
2672 pPoints[ip].m_x = rseg[j].x;
2673 pPoints[ip].m_y = rseg[j].y;
2680 ret_ptr->pvector_index[iseg * 3 + 0] =
2682 ret_ptr->pvector_index[iseg * 3 + 1] =
2683 pgd->index + m_current_cell_vearray_offset;
2684 ret_ptr->pvector_index[iseg * 3 + 2] =
2687 if ((cur_end_point.x == start_point.x) &&
2688 (cur_end_point.y == start_point.y)) {
2693 int nRingVertex = ip - n_prev_vertex_index;
2696 if (ncontours > m_ncontour_alloc - 1) {
2697 m_ncontour_alloc *= 2;
2698 int *tmp = m_pcontour_array;
2699 m_pcontour_array = (
int *)realloc(m_pcontour_array,
2700 m_ncontour_alloc *
sizeof(
int));
2706 m_pcontour_array[ncontours] = nRingVertex;
2709 n_prev_vertex_index = ip;
2715 ret_ptr->n_max_edge_points = n_max_points;
2717 ret_ptr->n_contours =
2720 if (0 == ncontours) ncontours = 1;
2721 ret_ptr->contour_array = (
int *)malloc(ncontours *
sizeof(
int));
2722 memcpy(ret_ptr->contour_array, m_pcontour_array, ncontours *
sizeof(
int));
2724 ret_ptr->vertex_array = pPoints;
2725 ret_ptr->n_max_vertex = n_maxvertex;
2727 ret_ptr->pogrGeom = NULL;
2729 ret_ptr->xmin = lon_min;
2730 ret_ptr->xmax = lon_max;
2731 ret_ptr->ymin = lat_min;
2732 ret_ptr->ymax = lat_max;
2740 ret_ptr->pogrGeom = NULL;
2742 ret_ptr->pointx = pt->x;
2743 ret_ptr->pointy = pt->y;
2752 int nsegs = pobject->n_geom_elements;
2754 ret_ptr->n_vector_indices = nsegs;
2755 ret_ptr->pvector_index = (
int *)malloc(nsegs * 3 *
sizeof(
int));
2758 int n_maxvertex = 0;
2759 for (
int imseg = 0; imseg < nsegs; imseg++) {
2763 n_maxvertex += pgd->n_points;
2767 wxPoint2DDouble *pPoints =
2768 (wxPoint2DDouble *)malloc(n_maxvertex *
sizeof(wxPoint2DDouble));
2773 int lon_max, lat_max, lon_min, lat_min;
2778 int n_max_points = -1;
2780 for (
int iseg = 0; iseg < nsegs; iseg++) {
2781 int type_seg = psegs->segment_usage;
2788 int npoints = pgd->n_points;
2791 n_max_points = wxMax(n_max_points, npoints);
2793 if (((type_seg & 4) != 4)) {
2794 for (
int j = 0; j < npoints; j++) {
2795 lon_max = wxMax(lon_max, rseg[j].x);
2796 lon_min = wxMin(lon_min, rseg[j].x);
2797 lat_max = wxMax(lat_max, rseg[j].y);
2798 lat_min = wxMin(lat_min, rseg[j].y);
2800 pPoints[ip].m_x = rseg[j].x;
2801 pPoints[ip].m_y = rseg[j].y;
2806 else if ((type_seg & 4) == 4)
2808 for (
int j = npoints - 1; j >= 0; j--) {
2809 lon_max = wxMax(lon_max, rseg[j].x);
2810 lon_min = wxMin(lon_min, rseg[j].x);
2811 lat_max = wxMax(lat_max, rseg[j].y);
2812 lat_min = wxMin(lat_min, rseg[j].y);
2814 pPoints[ip].m_x = rseg[j].x;
2815 pPoints[ip].m_y = rseg[j].y;
2820 ret_ptr->pvector_index[iseg * 3 + 0] =
2822 ret_ptr->pvector_index[iseg * 3 + 1] =
2823 pgd->index + m_current_cell_vearray_offset;
2824 ret_ptr->pvector_index[iseg * 3 + 2] =
2829 ret_ptr->n_max_edge_points = n_max_points;
2831 ret_ptr->vertex_array = pPoints;
2832 ret_ptr->n_max_vertex = n_maxvertex;
2834 ret_ptr->pogrGeom = NULL;
2836 ret_ptr->xmin = lon_min;
2837 ret_ptr->xmax = lon_max;
2838 ret_ptr->ymin = lat_min;
2839 ret_ptr->ymax = lat_max;
2847 int npoints = pgd->n_points;
2850 OGRMultiPoint *pSMP =
new OGRMultiPoint;
2854 for (
int ip = 0; ip < npoints; ip++) {
2859 zp = double(z - 12000);
2863 OGRPoint *ppoint =
new OGRPoint(rseg[ip].x, rseg[ip].y, zp);
2864 pSMP->addGeometryDirectly(ppoint);
2866 lon_max = wxMax(lon_max, rseg[ip].x);
2867 lon_min = wxMin(lon_min, rseg[ip].x);
2868 lat_max = wxMax(lat_max, rseg[ip].y);
2869 lat_min = wxMin(lat_min, rseg[ip].y);
2872 ret_ptr->pogrGeom = pSMP;
2874 ret_ptr->xmin = lon_min;
2875 ret_ptr->xmax = lon_max;
2876 ret_ptr->ymin = lat_min;
2877 ret_ptr->ymax = lat_max;
2887 wxPrintf(_T (
"Unexpected geomtype %d for Feature %d\n" ), geomtype,
2897void cm93chart::Transform(
cm93_point *s,
double trans_x,
double trans_y,
2898 double *lat,
double *lon) {
2900 double valx = (s->x * m_CIB.transform_x_rate) + m_CIB.transform_x_origin;
2901 double valy = (s->y * m_CIB.transform_y_rate) + m_CIB.transform_y_origin;
2909 (2.0 * atan(exp(valy / CM93_semimajor_axis_meters)) - PI / 2.) / DEGREE;
2910 *lon = (valx / (DEGREE * CM93_semimajor_axis_meters));
2915 m_block = (
unsigned char *)
block;
2919unsigned char *cm93_attr_block::GetNextAttr() {
2921 unsigned char *ret_val = m_block + m_cptr;
2925 unsigned char iattr = *(m_block + m_cptr);
2929 char vtype = m_pDict->GetAttrType(iattr);
2942 while (*(m_block + m_cptr)) m_cptr++;
2959 while (*(m_block + m_cptr)) m_cptr++;
2965 unsigned char nl = *(m_block + m_cptr);
2992wxString ParseSLGTA(wxString &val) {
2997 wxStringTokenizer tkz(val, wxT(
"|"));
2999 s = tkz.GetNextToken();
3000 s = tkz.GetNextToken();
3001 s = tkz.GetNextToken();
3004 wxString sc, st, sp;
3017 else if (s[0] ==
'G') {
3020 }
else if (s.Mid(0, 3) == _T (
"W/O" )) {
3026 }
else if (s.Mid(0, 5) == _T (
"LIGHT" )) {
3031 if (val.Find(_T (
"Spar" )) != wxNOT_FOUND) {
3035 if (val.Find(_T (
"SPAR" )) != wxNOT_FOUND) {
3040 if ((type == 2) && (color == 3))
3047 sprintf(line,
" %s (%c) = %s",
"COLOUR",
'I', (
const char *)sc.mb_str());
3048 result += wxString(line, wxConvUTF8);
3051 sprintf(line,
" %s (%c) = %s",
"BOYSHP",
'I',
"4");
3052 result += wxString(line, wxConvUTF8);
3058 sprintf(line,
" %s (%c) = %s",
"BOYSHP",
'I', (
const char *)st.mb_str());
3059 result += wxString(line, wxConvUTF8);
3062 sprintf(line,
" %s (%c) = %s",
"COLOUR",
'I',
"2");
3063 result += wxString(line, wxConvUTF8);
3069 sprintf(line,
" %s (%c) = %s",
"COLPAT",
'I', (
const char *)sp.mb_str());
3070 result += wxString(line, wxConvUTF8);
3077wxString ParseTEXTA(wxString &val) {
3081 if (val.Contains(_T (
"WK S" ))) {
3082 sprintf(line,
" %s (%c) = %s",
"WRKATT",
'I',
"1");
3083 result += wxString(line, wxConvUTF8);
3090void cm93chart::translate_colmar(
const wxString &sclass,
3091 S57attVal *pattValTmp) {
3092 int *pcur_attr = (
int *)pattValTmp->value;
3093 int cur_attr = *pcur_attr;
3099 lstring = _T (
"4" );
3102 lstring = _T (
"2" );
3105 lstring = _T (
"3" );
3108 lstring = _T (
"6" );
3111 lstring = _T (
"1" );
3114 lstring = _T (
"11" );
3117 lstring = _T (
"2,6" );
3120 lstring = _T (
"2,6,2" );
3123 lstring = _T (
"6,2" );
3126 lstring = _T (
"6,2,6" );
3129 lstring = _T (
"3,1" );
3132 lstring = _T (
"4,3,4" );
3135 lstring = _T (
"3,4,3" );
3138 lstring = _T (
"2,3,2" );
3141 lstring = _T (
"6,3,6" );
3144 lstring = _T (
"4,3" );
3147 lstring = _T (
"3,4" );
3150 lstring = _T (
"4,1" );
3156 if (lstring.Len()) {
3157 free(pattValTmp->value);
3159 pattValTmp->valType = OGR_STR;
3160 pattValTmp->value = strdup(lstring.mb_str());
3164S57Obj *cm93chart::CreateS57Obj(
int cell_index,
int iobject,
int subcell,
3166 Extended_Geometry *xgeom,
double ref_lat,
3167 double ref_lon,
double scale,
3168 double view_scale_ppm) {
3169#define MAX_HDR_LINE 4000
3173 int npub_year = 1993;
3175 int iclass = pobject->otype;
3176 int geomtype = pobject->geotype & 0x0f;
3178 double tmp_transform_x = 0.;
3179 double tmp_transform_y = 0.;
3182 double trans_WGS84_offset_x = 0.;
3183 double trans_WGS84_offset_y = 0.;
3185 wxString sclass = pDict->GetClassName(iclass);
3186 if (sclass == _T (
"Unknown" )) {
3188 msg.Printf(_T (
" CM93 Error...object type %d not found in CM93OBJ.DIC" ),
3195 wxString sclass_sub = sclass;
3198 if (sclass.IsSameAs(_T (
"ITDARE" ))) sclass_sub = _T (
"DEPARE" );
3200 if (sclass.IsSameAs(_T (
"_m_sor" ))) sclass_sub = _T (
"M_COVR" );
3202 if (sclass.IsSameAs(_T (
"SPOGRD" ))) sclass_sub = _T (
"DMPGRD" );
3204 if (sclass.IsSameAs(_T (
"FSHHAV" ))) sclass_sub = _T (
"FSHFAC" );
3206 if (sclass.IsSameAs(_T (
"OFSPRD" ))) sclass_sub = _T (
"CTNARE" );
3209 S57Obj *pobj =
new S57Obj();
3211 pobj->Index = iobject;
3214 strncpy(u, sclass_sub.mb_str(), 199);
3216 memcpy(pobj->FeatureName, u, 7);
3218 pobj->attVal =
new wxArrayOfS57attVal();
3222 for (
int jattr = 0; jattr < pobject->n_attributes; jattr++) {
3223 unsigned char *curr_attr = pab.GetNextAttr();
3225 unsigned char iattr = *curr_attr;
3227 wxString sattr = pDict->GetAttrName(iattr);
3229 char vtype = pDict->GetAttrType(iattr);
3231 unsigned char *aval = curr_attr + 1;
3244 S57attVal *pattValTmp =
new S57attVal;
3249 pAVI = (
int *)malloc(
sizeof(
int));
3251 pattValTmp->valType = OGR_INT;
3252 pattValTmp->value = pAVI;
3255 pb = (
unsigned char *)aval;
3256 pAVI = (
int *)malloc(
sizeof(
int));
3258 pattValTmp->valType = OGR_INT;
3259 pattValTmp->value = pAVI;
3262 pw = (
unsigned short *)aval;
3266 pAVR = (
double *)malloc(
sizeof(
double));
3267 *pAVR = dival / 10.;
3268 pattValTmp->valType = OGR_REAL;
3269 pattValTmp->value = pAVR;
3273 pAVI = (
int *)malloc(
sizeof(
int));
3275 pattValTmp->valType = OGR_INT;
3276 pattValTmp->value = pAVI;
3280 pAVS = strdup((
char *)aval);
3281 pattValTmp->valType = OGR_STR;
3282 pattValTmp->value = pAVS;
3286 pAVS = strdup((
const char *)&aval[3]);
3287 pattValTmp->valType = OGR_STR;
3288 pattValTmp->value = pAVS;
3291 pb = (
unsigned char *)aval;
3292 unsigned char nl = *pb++;
3295 for (
int i = 0; i < nl; i++) {
3296 sprintf(vi,
"%d,", *pb++);
3299 if (strlen(val)) val[strlen(val) - 1] = 0;
3302 pattValTmp->valType = OGR_STR;
3303 pattValTmp->value = pAVS;
3307 pAVR = (
double *)malloc(
sizeof(
double));
3311 float __attribute__((aligned(16))) tf1;
3312 unsigned char *pucf = (
unsigned char *)pf;
3314 memcpy(&tf1, pucf, sizeof(
float));
3320 pattValTmp->valType = OGR_REAL;
3321 pattValTmp->value = pAVR;
3329 if (sattr.IsSameAs(_T (
"COLMAR" ))) {
3330 translate_colmar(sclass, pattValTmp);
3331 sattr = _T (
"COLOUR" );
3335 if (pattValTmp->valType == OGR_INT &&
3336 (sattr.IsSameAs(_T (
"QUASOU" )) || sattr.IsSameAs(_T (
"CATLIT" )))) {
3337 int v = *(
int *)pattValTmp->value;
3338 free(pattValTmp->value);
3339 sprintf(val,
"%d", v);
3341 pattValTmp->valType = OGR_STR;
3342 pattValTmp->value = pAVS;
3346 if (sclass.IsSameAs(_T (
"$AREAS" )) && (vtype ==
'S') &&
3347 sattr.IsSameAs(_T (
"$SCODE" ))) {
3348 if (!strcmp((
char *)pattValTmp->value,
"II25")) {
3349 free(pattValTmp->value);
3350 pattValTmp->value = strdup(
"BACKGROUND");
3355 if (sattr.IsSameAs(_T (
"RECDAT" )) || sattr.IsSameAs(_T (
"_dgdat" ))) {
3356 if (sclass_sub.IsSameAs(_T (
"M_COVR" )) && (vtype ==
'S')) {
3357 wxString pub_date((
char *)pattValTmp->value, wxConvUTF8);
3360 upd.ParseFormat(pub_date, _T (
"%Y%m%d" ));
3361 if (!upd.IsValid()) upd.ParseFormat(_T (
"20000101" ), _T (
"%Y%m%d" ));
3364 pub_date.Truncate(4);
3367 pub_date.ToLong(&nyear);
3373 if (sclass_sub.IsSameAs(_T (
"M_COVR" )) && (vtype ==
'R')) {
3374 if (sattr.IsSameAs(_T (
"_wgsox" ))) {
3375 tmp_transform_x = *(
double *)pattValTmp->value;
3376 if (fabs(tmp_transform_x) > 1.0)
3377 m_CIB.b_have_offsets =
true;
3378 }
else if (sattr.IsSameAs(_T (
"_wgsoy" ))) {
3379 tmp_transform_y = *(
double *)pattValTmp->value;
3380 if (fabs(tmp_transform_y) > 1.0) m_CIB.b_have_offsets =
true;
3385 wxASSERT(sattr.Len() == 6);
3386 wxCharBuffer dbuffer = sattr.ToUTF8();
3387 if (dbuffer.data()) {
3389 (
char *)realloc(pobj->att_array, 6 * (pobj->n_attr + 1));
3391 strncpy(pobj->att_array + (6 *
sizeof(
char) * pobj->n_attr),
3395 pobj->attVal->Add(pattValTmp);
3409 if (1 == geomtype) {
3410 if ((!strncmp(pobj->FeatureName,
"LIT", 3)) ||
3411 (!strncmp(pobj->FeatureName,
"LIGHTS", 6)) ||
3412 (!strncmp(pobj->FeatureName,
"BCN", 3)) ||
3413 (!strncmp(pobj->FeatureName,
"_slgto", 6)) ||
3414 (!strncmp(pobj->FeatureName,
"_boygn", 6)) ||
3415 (!strncmp(pobj->FeatureName,
"_bcngn", 6)) ||
3416 (!strncmp(pobj->FeatureName,
"_extgn", 6)) ||
3417 (!strncmp(pobj->FeatureName,
"TOWERS", 6)) ||
3418 (!strncmp(pobj->FeatureName,
"BOY", 3))) {
3419 bool bfound_OBJNAM = (pobj->GetAttributeIndex(
"OBJNAM") != -1);
3420 bool bfound_INFORM = (pobj->GetAttributeIndex(
"INFORM") != -1);
3422 if ((!bfound_OBJNAM) && (bfound_INFORM))
3424 char *patl = pobj->att_array;
3425 for (
int i = 0; i < pobj->n_attr; i++) {
3426 if (!strncmp(patl,
"INFORM", 6)) {
3427 memcpy(patl,
"OBJNAM", 6);
3439 pobj->Primitive_type = GEO_AREA;
3442 if (sclass_sub.IsSameAs(_T (
"M_COVR" ))) {
3446 GetCoverSet()->Find_MCD(cell_index, iobject, subcell);
3447 if (NULL == pmcd_look)
3454 pmcd->m_cell_index = cell_index;
3455 pmcd->m_object_id = iobject;
3456 pmcd->m_subcell = subcell;
3459 pmcd->user_xoff = 0;
3460 pmcd->user_yoff = 0;
3461 pmcd->m_buser_offsets =
false;
3464 pmcd->m_npub_year = npub_year;
3467 int npta = xgeom->contour_array[0];
3468 float_2Dpt *geoPt =
new float_2Dpt[npta + 2];
3469 float_2Dpt *ppt = geoPt;
3471 pmcd->m_covr_lon_max = -1000.;
3472 pmcd->m_covr_lon_min = 1000.;
3473 pmcd->m_covr_lat_max = -1000.;
3474 pmcd->m_covr_lat_min = 1000.;
3478 for (
int ip = 0; ip < npta; ip++) {
3480 p.x = (int)xgeom->vertex_array[ip + 1].m_x;
3481 p.y = (int)xgeom->vertex_array[ip + 1].m_y;
3483 Transform(&p, 0, 0, &lat,
3488 pmcd->m_covr_lon_max = wxMax(pmcd->m_covr_lon_max, lon);
3489 pmcd->m_covr_lon_min = wxMin(pmcd->m_covr_lon_min, lon);
3490 pmcd->m_covr_lat_max = wxMax(pmcd->m_covr_lat_max, lat);
3491 pmcd->m_covr_lat_min = wxMin(pmcd->m_covr_lat_min, lat);
3495 pmcd->m_nvertices = npta;
3496 pmcd->pvertices = geoPt;
3498 pmcd->m_covr_bbox.Set(pmcd->m_covr_lat_min, pmcd->m_covr_lon_min,
3499 pmcd->m_covr_lat_max, pmcd->m_covr_lon_max);
3503 pmcd->transform_WGS84_offset_x = tmp_transform_x;
3504 pmcd->transform_WGS84_offset_y = tmp_transform_y;
3506 pmcd->m_centerlat_cos = cos(
3507 ((pmcd->m_covr_lat_min + pmcd->m_covr_lat_max) / 2.) * PI / 180.);
3510 GetCoverSet()->Add_Update_MCD(pmcd);
3515 if (pmcd_look->m_buser_offsets) {
3516 m_CIB.b_have_user_offsets =
true;
3518 m_CIB.user_xoff = pmcd_look->user_xoff;
3519 m_CIB.user_yoff = pmcd_look->user_yoff;
3526 m_pcovr_array_loaded.Add(pmcd);
3529 unsigned int n = pmcd->m_nvertices;
3530 double *pts =
new double[2 * n];
3533 for (
size_t i = 0; i < 2 * n; i++)
3534 pts[i] = ((
float *)pmcd->pvertices)[i];
3538 if (LLRegion::PointsCCW(n, pts))
3539 for (
size_t i = 0; i < n; i++)
3540 if (pts[2 * i + 1] < 0) pts[2 * i + 1] += 360;
3543 LLRegion rgn_covr(n, pts);
3544 m_region.Union(rgn_covr);
3552 m_CIB.m_cell_mcovr_list.Append(pmcd);
3556 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3557 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3560 pobj->m_n_lsindex = xgeom->n_vector_indices;
3561 pobj->m_lsindex_array =
3562 xgeom->pvector_index;
3563 pobj->m_n_edge_max_points = 0;
3566 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3569 pc.x = (
short unsigned int)pobj->x;
3570 pc.y = (
short unsigned int)pobj->y;
3571 Transform(&pc, 0., 0., &latc, &lonc);
3573 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(latc, lonc);
3575 trans_WGS84_offset_x = pmcd->user_xoff;
3576 trans_WGS84_offset_y = pmcd->user_yoff;
3581 double lat1, lon1, lat2, lon2;
3584 p.x = (int)xgeom->xmin;
3585 p.y = (int)xgeom->ymin;
3586 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3587 xgeom->ref_lat = lat1;
3588 xgeom->ref_lon = lon1;
3590 p.x = (int)xgeom->xmax;
3591 p.y = (int)xgeom->ymax;
3592 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat2, &lon2);
3593 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3598 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3606 xgeom->x_rate = m_CIB.transform_x_rate;
3607 xgeom->x_offset = m_CIB.transform_x_origin - trans_WGS84_offset_x;
3608 xgeom->y_rate = m_CIB.transform_y_rate;
3609 xgeom->y_offset = m_CIB.transform_y_origin - trans_WGS84_offset_y;
3611 pobj->pPolyTessGeo =
new PolyTessGeo(xgeom);
3618 pobj->Primitive_type = GEO_POINT;
3621 pobj->x = xgeom->pointx;
3622 pobj->y = xgeom->pointy;
3626 p.x = xgeom->pointx;
3627 p.y = xgeom->pointy;
3628 Transform(&p, 0., 0., &lat, &lon);
3631 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3632 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(lat, lon);
3634 trans_WGS84_offset_x = pmcd->user_xoff;
3635 trans_WGS84_offset_y = pmcd->user_yoff;
3640 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat, &lon);
3650 double llsize = 1e-3 / view_scale_ppm;
3652 pobj->BBObj.Set(lat, lon, lat, lon);
3653 pobj->BBObj.EnLarge(llsize);
3660 pobj->Primitive_type = GEO_POINT;
3663 double lat1, lon1, lat2, lon2;
3666 p.x = (int)xgeom->xmin;
3667 p.y = (int)xgeom->ymin;
3668 Transform(&p, 0., 0., &lat1, &lon1);
3670 p.x = (int)xgeom->xmax;
3671 p.y = (int)xgeom->ymax;
3672 Transform(&p, 0., 0., &lat2, &lon2);
3673 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3676 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3677 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3679 OGRMultiPoint *pGeo = (OGRMultiPoint *)xgeom->pogrGeom;
3680 pobj->npt = pGeo->getNumGeometries();
3682 pobj->geoPtz = (
double *)malloc(pobj->npt * 3 *
sizeof(
double));
3683 pobj->geoPtMulti = (
double *)malloc(pobj->npt * 2 *
sizeof(
double));
3685 double *pdd = pobj->geoPtz;
3686 double *pdl = pobj->geoPtMulti;
3688 for (
int ip = 0; ip < pobj->npt; ip++) {
3689 OGRPoint *ppt = (OGRPoint *)(pGeo->getGeometryRef(ip));
3692 p.x = (int)ppt->getX();
3693 p.y = (int)ppt->getY();
3694 double depth = ppt->getZ();
3699 double snd_trans_x = 0.;
3700 double snd_trans_y = 0.;
3703 if (m_CIB.b_have_user_offsets) {
3705 Transform(&p, 0., 0., &lats, &lons);
3707 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(lats, lons);
3710 snd_trans_x = pmcd->user_xoff;
3711 snd_trans_y = pmcd->user_yoff;
3715 east -= pmcd->user_xoff / m_CIB.transform_x_rate;
3716 north -= pmcd->user_yoff / m_CIB.transform_y_rate;
3726 Transform(&p, snd_trans_x, snd_trans_y, &lat1, &lon1);
3734 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3744 pobj->Primitive_type = GEO_LINE;
3746 pobj->npt = xgeom->n_max_vertex;
3747 pobj->geoPt = (pt *)xgeom->vertex_array;
3748 xgeom->vertex_array = NULL;
3751 pobj->x = (xgeom->xmin + xgeom->xmax) / 2.;
3752 pobj->y = (xgeom->ymin + xgeom->ymax) / 2.;
3755 pobj->m_n_lsindex = xgeom->n_vector_indices;
3756 pobj->m_lsindex_array =
3757 xgeom->pvector_index;
3758 pobj->m_n_edge_max_points = 0;
3761 if (m_CIB.b_have_offsets || m_CIB.b_have_user_offsets) {
3764 pc.x = (
short unsigned int)pobj->x;
3765 pc.y = (
short unsigned int)pobj->y;
3766 Transform(&pc, 0., 0., &latc, &lonc);
3768 M_COVR_Desc *pmcd = FindM_COVR_InWorkingSet(latc, lonc);
3770 trans_WGS84_offset_x = pmcd->user_xoff;
3771 trans_WGS84_offset_y = pmcd->user_yoff;
3776 double lat1, lon1, lat2, lon2;
3779 p.x = (int)xgeom->xmin;
3780 p.y = (int)xgeom->ymin;
3781 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3783 p.x = (int)xgeom->xmax;
3784 p.y = (int)xgeom->ymax;
3785 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat2, &lon2);
3786 pobj->BBObj.Set(lat1, lon1, lat2, lon2);
3791 Transform(&p, trans_WGS84_offset_x, trans_WGS84_offset_y, &lat1, &lon1);
3800 pobj->Primitive_type = GEO_PRIM;
3807 if (!strncmp(pobj->FeatureName,
"OBSTRN", 6) ||
3808 !strncmp(pobj->FeatureName,
"WRECKS", 6) ||
3809 !strncmp(pobj->FeatureName,
"DEPCNT", 6) ||
3810 !strncmp(pobj->FeatureName,
"UWTROC", 6)) {
3811 pobj->m_bcategory_mutable =
true;
3813 pobj->m_bcategory_mutable =
false;
3826 if (geomtype != 4)
delete xgeom;
3830 m_CIB.transform_x_rate *
3831 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3833 m_CIB.transform_y_rate *
3834 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3836 m_CIB.transform_x_origin *
3837 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3839 m_CIB.transform_y_origin *
3840 (mercator_k0 * WGS84_semimajor_axis_meters / CM93_semimajor_axis_meters);
3844 pobj->x_origin -= trans_WGS84_offset_x;
3845 pobj->y_origin -= trans_WGS84_offset_y;
3848 pobj->auxParm3 = CHART_TYPE_CM93;
3854M_COVR_Desc *cm93chart::FindM_COVR_InWorkingSet(
double lat,
double lon) {
3857 if (m_CIB.m_cell_mcovr_list.GetCount() == 1) {
3858 wxList_Of_M_COVR_DescNode *node0 = m_CIB.m_cell_mcovr_list.GetFirst();
3859 if (node0) ret = node0->GetData();
3861 wxList_Of_M_COVR_DescNode *node = m_CIB.m_cell_mcovr_list.GetFirst();
3865 if (G_PtInPolygon_FL(pmcd->pvertices, pmcd->m_nvertices, lon, lat)) {
3870 node = node->GetNext();
3878wxPoint2DDouble cm93chart::FindM_COVROffset(
double lat,
double lon) {
3879 wxPoint2DDouble ret(0., 0.);
3882 wxList_Of_M_COVR_DescNode *node0 = m_CIB.m_cell_mcovr_list.GetFirst();
3885 ret.m_x = pmcd0->transform_WGS84_offset_x;
3886 ret.m_y = pmcd0->transform_WGS84_offset_y;
3890 if (m_CIB.m_cell_mcovr_list.GetCount() > 1) {
3891 wxList_Of_M_COVR_DescNode *node = m_CIB.m_cell_mcovr_list.GetFirst();
3895 if (G_PtInPolygon_FL(pmcd->pvertices, pmcd->m_nvertices, lon, lat)) {
3896 ret.m_x = pmcd->transform_WGS84_offset_x;
3897 ret.m_y = pmcd->transform_WGS84_offset_y;
3901 node = node->GetNext();
3909InitReturn cm93chart::CreateHeaderDataFromCM93Cell(
void) {
3911 wxFileName fn(m_FullPath);
3912 wxString ext = fn.GetExt();
3915 switch ((ext.mb_str())[(
size_t)0]) {
3945 m_Chart_Scale =
scale;
3951 switch (m_Chart_Scale) {
3953 bproc = m_pManager->m_bfoundZ;
3956 bproc = m_pManager->m_bfoundA;
3959 bproc = m_pManager->m_bfoundB;
3962 bproc = m_pManager->m_bfoundC;
3965 bproc = m_pManager->m_bfoundD;
3968 bproc = m_pManager->m_bfoundE;
3971 bproc = m_pManager->m_bfoundF;
3974 bproc = m_pManager->m_bfoundG;
3978 if (bproc)
return INIT_FAIL_NOERROR;
3981 switch (m_Chart_Scale) {
3983 m_pManager->m_bfoundZ =
true;
3986 m_pManager->m_bfoundA =
true;
3989 m_pManager->m_bfoundB =
true;
3992 m_pManager->m_bfoundC =
true;
3995 m_pManager->m_bfoundD =
true;
3998 m_pManager->m_bfoundE =
true;
4001 m_pManager->m_bfoundF =
true;
4004 m_pManager->m_bfoundG =
true;
4010 m_FullExtent.ELON = 179.0;
4011 m_FullExtent.WLON = -179.0;
4012 m_FullExtent.NLAT = 80.0;
4013 m_FullExtent.SLAT = -80.0;
4014 m_bExtentSet =
true;
4018 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
4019 *m_pCOVRTablePoints = 4;
4020 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
4021 float *pf = (
float *)malloc(2 * 4 *
sizeof(
float));
4025 *pfe++ = m_FullExtent.NLAT;
4026 *pfe++ = m_FullExtent.WLON;
4028 *pfe++ = m_FullExtent.NLAT;
4029 *pfe++ = m_FullExtent.ELON;
4031 *pfe++ = m_FullExtent.SLAT;
4032 *pfe++ = m_FullExtent.ELON;
4034 *pfe++ = m_FullExtent.SLAT;
4035 *pfe++ = m_FullExtent.WLON;
4040void cm93chart::ProcessMCOVRObjects(
int cell_index,
char subcell) {
4043 Object *pobject = m_CIB.pobject_block;
4046 while (iObj < m_CIB.m_nfeature_records) {
4047 if ((pobject != NULL)) {
4049 int iclass = pobject->otype;
4051 wxString sclass = m_pDict->GetClassName(iclass);
4053 if (sclass.IsSameAs(_T (
"_m_sor" ))) {
4055 m_pcovr_set->Find_MCD(cell_index, iObj, (
int)subcell);
4057 Extended_Geometry *xgeom = BuildGeom(pobject, NULL, iObj);
4061 double tmp_transform_x = 0.;
4062 double tmp_transform_y = 0.;
4065 for (
int jattr = 0; jattr < pobject->n_attributes; jattr++) {
4066 unsigned char *curr_attr = pab.GetNextAttr();
4067 unsigned char iattr = *curr_attr;
4068 wxString sattr = m_pDict->GetAttrName(iattr);
4069 char vtype = m_pDict->GetAttrType(iattr);
4070 unsigned char *aval = curr_attr + 1;
4073 float *pf = (
float *)aval;
4075 float __attribute__((aligned(16))) tf1;
4076 unsigned char *pucf = (
unsigned char *)pf;
4077 memcpy(&tf1, pucf, sizeof(
float));
4078 if (sattr.IsSameAs(_T ( "_wgsox" )))
4079 tmp_transform_x = tf1;
4080 else if (sattr.IsSameAs(_T ( "_wgsoy" )))
4081 tmp_transform_y = tf1;
4083 if (sattr.IsSameAs(_T (
"_wgsox" )))
4084 tmp_transform_x = *pf;
4085 else if (sattr.IsSameAs(_T (
"_wgsoy" )))
4086 tmp_transform_y = *pf;
4092 if (NULL != xgeom) {
4098 pmcd->m_cell_index = cell_index;
4099 pmcd->m_object_id = iObj;
4100 pmcd->m_subcell = (int)subcell;
4103 int npta = xgeom->contour_array[0];
4104 float_2Dpt *geoPt =
new float_2Dpt[npta + 2];
4105 float_2Dpt *ppt = geoPt;
4109 pmcd->m_covr_lon_max = -1000.;
4110 pmcd->m_covr_lon_min = 1000.;
4111 pmcd->m_covr_lat_max = -1000.;
4112 pmcd->m_covr_lat_min = 1000.;
4114 for (
int ip = 0; ip < npta; ip++) {
4116 p.x = (int)xgeom->vertex_array[ip + 1].m_x;
4117 p.y = (int)xgeom->vertex_array[ip + 1].m_y;
4119 Transform(&p, 0., 0., &lat, &lon);
4123 pmcd->m_covr_lon_max = wxMax(pmcd->m_covr_lon_max, lon);
4124 pmcd->m_covr_lon_min = wxMin(pmcd->m_covr_lon_min, lon);
4125 pmcd->m_covr_lat_max = wxMax(pmcd->m_covr_lat_max, lat);
4126 pmcd->m_covr_lat_min = wxMin(pmcd->m_covr_lat_min, lat);
4130 pmcd->m_nvertices = npta;
4131 pmcd->pvertices = geoPt;
4133 pmcd->m_covr_bbox.Set(pmcd->m_covr_lat_min, pmcd->m_covr_lon_min,
4134 pmcd->m_covr_lat_max, pmcd->m_covr_lon_max);
4138 pmcd->transform_WGS84_offset_x = tmp_transform_x;
4139 pmcd->transform_WGS84_offset_y = tmp_transform_y;
4141 pmcd->m_centerlat_cos =
4142 cos(((pmcd->m_covr_lat_min + pmcd->m_covr_lat_max) / 2.) * PI /
4146 m_pcovr_set->Add_Update_MCD(pmcd);
4149 free(xgeom->pvector_index);
4165bool cm93chart::UpdateCovrSet(
ViewPort *vpt) {
4167 std::vector<int> vpcells = GetVPCellArray(*vpt);
4172 for (
unsigned int i = 0; i < vpcells.size(); i++) {
4175 if (!m_pcovr_set->IsCovrLoaded(vpcells[i])) {
4176 if (loadcell_in_sequence(vpcells[i],
'0')) {
4177 ProcessMCOVRObjects(vpcells[i],
'0');
4180 m_pcovr_set->m_cell_hash[vpcells[i]] = 1;
4182 char loadcell_key =
'A';
4186 while (loadcell_in_sequence(vpcells[i], loadcell_key)) {
4189 ProcessMCOVRObjects(vpcells[i], loadcell_key);
4202bool cm93chart::IsPointInLoadedM_COVR(
double xc,
double yc) {
4205 return m_region.Contains(yc, xc);
4207 for (
unsigned int im = 0; im < m_pcovr_array_loaded.GetCount(); im++) {
4208 if (G_PtInPolygon_FL(m_pcovr_array_loaded[im]->pvertices,
4209 m_pcovr_array_loaded[im]->m_nvertices, xc, yc))
4216LLRegion cm93chart::GetValidRegion() {
return m_region; }
4218int cm93chart::loadcell_in_sequence(
int cellindex,
char subcell) {
4219 int rv = loadsubcell(cellindex, subcell);
4224int cm93chart::loadsubcell(
int cellindex, wxChar sub_char) {
4227 int ilat = cellindex / 10000;
4228 int ilon = cellindex % 10000;
4231 double dlat = m_dval / 3.;
4232 double dlon = m_dval / 3.;
4234 Get_CM93_Cell_Origin(cellindex, GetNativeScale(), &lat, &lon);
4236 "\n Attempting loadcell %d scale %lc, sub_char %lc at lat: %g/%g "
4238 cellindex, wxChar(m_scalechar[0]), sub_char, lat, lat + dlat, lon,
4242 int jlat = (int)(((ilat - 30) / m_dval) * m_dval) + 30;
4243 int jlon = (int)((ilon / m_dval) * m_dval);
4245 int ilatroot = (((ilat - 30) / 60) * 60) + 30;
4246 int ilonroot = (ilon / 60) * 60;
4249 file.Printf(_T (
"%04d%04d." ), jlat, jlon);
4250 file += m_scalechar;
4259 bool b_useNoFind =
true;
4260 if (m_noFindArray.GetCount() > 500) b_useNoFind =
false;
4263 fileroot.Printf(_T (
"%04d%04d" ), ilatroot, ilonroot);
4264 appendOSDirSep(&fileroot);
4265 fileroot.append(m_scalechar);
4266 appendOSDirSep(&fileroot);
4267 wxString key = fileroot;
4269 fileroot.Prepend(m_prefix);
4271 file.Prepend(fileroot);
4275 strncpy(sfile, file.mb_str(), 199);
4277 printf(
" filename: %s\n", sfile);
4280 bool bfound =
false;
4283 if (m_noFindArray.Index(key) == wxNOT_FOUND) {
4284 if (::wxFileExists(file))
4287 m_noFindArray.Add(key);
4290 if (::wxFileExists(file)) bfound =
true;
4296 if (m_noFindArray.Index(key + _T(
".xz")) == wxNOT_FOUND) {
4297 if (::wxFileExists(file + _T(
".xz"))) {
4298 compfile = file + _T(
".xz");
4301 m_noFindArray.Add(key + _T(
".xz"));
4304 if (::wxFileExists(file + _T(
".xz"))) compfile = file + _T(
".xz");
4309 if (!bfound && !compfile.Length()) {
4311 wxString new_scalechar = m_scalechar.Lower();
4314 file1.Printf(_T (
"%04d%04d." ), jlat, jlon);
4315 file1 += new_scalechar;
4316 file1[0] = sub_char;
4318 fileroot.Printf(_T (
"%04d%04d" ), ilatroot, ilonroot);
4319 appendOSDirSep(&fileroot);
4320 fileroot.append(new_scalechar);
4321 appendOSDirSep(&fileroot);
4325 fileroot.Prepend(m_prefix);
4327 file1.Prepend(fileroot);
4330 if (m_noFindArray.Index(key) == wxNOT_FOUND) {
4331 if (::wxFileExists(file1)) {
4335 m_noFindArray.Add(key);
4339 if (::wxFileExists(file1)) {
4347 if (m_noFindArray.Index(key + _T(
".xz")) == wxNOT_FOUND) {
4348 if (::wxFileExists(file1 + _T(
".xz")))
4349 compfile = file1 + _T(
".xz");
4351 m_noFindArray.Add(key + _T(
".xz"));
4354 if (::wxFileExists(file1 + _T(
".xz"))) compfile = file1 + _T(
".xz");
4360 printf(
"noFind count: %d\n", (
int)m_noFindArray.GetCount());
4363 if (!bfound && !compfile.Length())
return 0;
4367 wxString msg(_T (
"Loading CM93 cell " ));
4373 m_LastFileName = file;
4376 if (compfile.Length()) {
4377 file = wxFileName::CreateTempFileName(wxFileName(compfile).GetFullName());
4378 if (!DecompressXZFile(compfile, file)) {
4386 strncpy(str, msg.mb_str(), 255);
4388 printf(
" %s\n", str);
4392 if (!Ingest_CM93_Cell((
const char *)file.mb_str(), &m_CIB)) {
4393 wxString msg(_T (
" cm93chart Error ingesting " ));
4397 if (compfile.Length()) wxRemoveFile(file);
4401 if (compfile.Length()) wxRemoveFile(file);
4406void cm93chart::SetUserOffsets(
int cell_index,
int object_id,
int subcell,
4407 int xoff,
int yoff) {
4408 M_COVR_Desc *pmcd = GetCoverSet()->Find_MCD(cell_index, object_id, subcell);
4410 pmcd->user_xoff = xoff;
4411 pmcd->user_yoff = yoff;
4412 pmcd->m_buser_offsets =
true;
4416wxPoint *cm93chart::GetDrawBuffer(
int nSize) {
4418 if (nSize > m_nDrawBufferSize) {
4419 wxPoint *tmp = m_pDrawBuffer;
4421 (wxPoint *)realloc(m_pDrawBuffer,
sizeof(wxPoint) * (nSize + 1));
4422 if (NULL == m_pDrawBuffer) {
4426 m_nDrawBufferSize = nSize + 1;
4428 return m_pDrawBuffer;
4435cm93manager::cm93manager(
void) {
4448cm93manager::~cm93manager(
void) {
delete m_pcm93Dict; }
4450bool cm93manager::Loadcm93Dictionary(
const wxString &name) {
4453 m_pcm93Dict = FindAndLoadDict(name);
4456 wxLogMessage(_T (
" Cannot load CM93 Dictionary." ));
4460 if (!m_pcm93Dict->IsOk()) {
4461 wxLogMessage(_T (
" Error in loading CM93 Dictionary." ));
4467 }
else if (!m_pcm93Dict->IsOk()) {
4468 wxLogMessage(_T (
" CM93 Dictionary is not OK." ));
4482 wxFileName fn(file);
4483 wxString path = fn.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
4487 while (i < path.Len()) {
4488 target.Append(path[i]);
4489 if (path[i] == fn.GetPathSeparator()) {
4490 if (pdict->LoadDictionary(target)) {
4494 if (pdict->LoadDictionary(target + _T (
"CM93ATTR" ))) {
4503 strncpy(t, target.mb_str(), 99);
4505 if (retval == NULL)
delete pdict;
4513cm93compchart::cm93compchart() {
4514 m_ChartType = CHART_TYPE_CM93COMP;
4515 m_pDictComposite = NULL;
4518 m_FullPath = _T (
"CM93" );
4521 m_Description = _T (
"CM93Composite" );
4524 m_datum_str = _T (
"WGS84" );
4525 m_SoundingsDatum = _T (
"Unknown" );
4527 for (
int i = 0; i < 8; i++) m_pcm93chart_array[i] = NULL;
4529 m_pcm93chart_current = NULL;
4536 SetSpecialOutlineCellIndex(0, 0, 0);
4537 m_last_cell_adjustvp = NULL;
4542cm93compchart::~cm93compchart() {
4543 if (g_pCM93OffsetDialog) {
4544 g_pCM93OffsetDialog->Hide();
4547 for (
int i = 0; i < 8; i++)
delete m_pcm93chart_array[i];
4549 delete m_pDictComposite;
4554InitReturn cm93compchart::Init(
const wxString &name, ChartInitFlag flags) {
4557 wxFileName fn(name);
4563 if (!fn.FileExists()) {
4565 if (wxDir::Exists(name)) {
4567 appendOSDirSep(&target);
4569 appendOSDirSep(&path);
4571 wxString msg(_T (
" CM93Composite Chart Init cannot find " ));
4574 return INIT_FAIL_REMOVE;
4579 path = fn.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
4583 wxFileName file_path(path);
4584 file_path.RemoveLastDir();
4585 file_path.RemoveLastDir();
4587 target = file_path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
4590 m_prefixComposite = target;
4592 wxString msg(_T (
"CM93Composite Chart Root is " ));
4593 msg.Append(m_prefixComposite);
4596 if (flags == THUMB_ONLY) {
4602 if (flags == HEADER_ONLY)
return CreateHeaderData();
4605 if (!m_pDictComposite) {
4606 if (!m_pDictComposite)
4607 m_pDictComposite = FindAndLoadDictFromDir(path);
4609 if (!m_pDictComposite) {
4611 _T (
" CM93Composite Chart Init cannot locate CM93 dictionary." ));
4612 return INIT_FAIL_REMOVE;
4617 SetColorScheme(m_global_color_scheme,
false);
4619 bReadyToRender =
true;
4624void cm93compchart::Activate(
void) {
4651void cm93compchart::Deactivate(
void) {
4652 if (pPopupDetailSlider) {
4653 pPopupDetailSlider->Destroy();
4654 pPopupDetailSlider = NULL;
4658double scale_breaks[] = {
4673int cm93compchart::GetCMScaleFromVP(
const ViewPort &vpt) {
4676 double scale_mpp_adj = scale_mpp;
4678 double scale_breaks_adj[7];
4680 for (
int i = 0; i < 7; i++) scale_breaks_adj[i] = scale_breaks[i];
4682 if (g_cm93_zoom_factor) {
4685 double efactor = ( double ) ( g_cm93_zoom_factor ) * ( .176 / 7. );
4686 for (
int i=0 ; i < 7 ; i++ )
4688 double efr = efactor * ( 7 - i );
4689 scale_breaks_adj[i] = scale_breaks[i] * pow ( 10., efr );
4691 printf (
"g_cm93_zoom_factor: %2d efactor: %6g efr:%6g, scale_breaks[i]:%6g scale_breaks_adj[i]: %6g\n",
4692 g_cm93_zoom_factor, efactor, efr, scale_breaks[i], scale_breaks_adj[i] );
4696 double efr = (double)g_cm93_zoom_factor * pow(scale_mpp, -.05);
4697 scale_mpp_adj *= pow(.6, efr);
4701 int cmscale_calc = 7;
4703 while (cmscale_calc > 0) {
4704 if (scale_mpp_adj < scale_breaks_adj[brk_index])
break;
4711 double zoom_factor = scale_breaks[7 - cmscale_calc] / vpt.
chart_scale;
4712 if (zoom_factor > 4.0) {
4713 if (cmscale_calc < 7) cmscale_calc++;
4716 return cmscale_calc;
4719void cm93compchart::SetVPParms(
const ViewPort &vpt) {
4722 int cmscale = GetCMScaleFromVP(vpt);
4723 m_cmscale = PrepareChartScale(vpt, cmscale,
false);
4727 if (m_pcm93chart_array[cmscale]) {
4728 if (!m_EdDate.IsValid() ||
4729 !m_pcm93chart_array[cmscale]->GetEditionDate().IsValid() ||
4730 m_pcm93chart_array[cmscale]->GetEditionDate().IsLaterThan(m_EdDate))
4731 m_EdDate = m_pcm93chart_array[cmscale]->GetEditionDate();
4735int cm93compchart::PrepareChartScale(
const ViewPort &vpt,
int cmscale,
4738 printf(
"\non SetVPParms, cmscale:%d, %c\n", cmscale,
4739 (
char)(
'A' + cmscale - 1));
4742 bool cellscale_is_useable =
false;
4743 bool b_nochart =
false;
4745 while (!cellscale_is_useable) {
4747 while (NULL == m_pcm93chart_array[cmscale]) {
4748 if (Is_CM93Cell_Present(m_prefixComposite, vpt.
clat, vpt.
clon, cmscale)) {
4750 printf(
" chart %c at VP clat/clon is present\n",
4751 (
char)(
'A' + cmscale - 1));
4753 m_pcm93chart_array[cmscale] =
new cm93chart();
4755 ext = (wxChar)(
'A' + cmscale - 1);
4756 if (cmscale == 0) ext =
'Z';
4758 wxString file_dummy = _T (
"CM93." );
4761 m_pcm93chart_array[cmscale]->SetCM93Dict(m_pDictComposite);
4762 m_pcm93chart_array[cmscale]->SetCM93Prefix(m_prefixComposite);
4763 m_pcm93chart_array[cmscale]->SetCM93Manager(m_pcm93mgr);
4765 m_pcm93chart_array[cmscale]->SetColorScheme(m_global_color_scheme);
4766 m_pcm93chart_array[cmscale]->Init(file_dummy, FULL_INIT);
4767 }
else if (cmscale == 0) {
4774 " CM93 finds no chart of any scale present at Lat/Lon %g %g\n",
4784 printf(
" no %c scale chart present, adjusting cmscale to %c\n",
4785 (
char)(
'A' + cmscale), (
char)(
'A' + cmscale - 1));
4789 m_pcm93chart_current = m_pcm93chart_array[cmscale];
4792 if (g_bDebugCM93) printf(
" b_nochart return\n");
4794 m_pcm93chart_current = NULL;
4795 for (
int i = 0; i < 8; i++) {
4796 delete m_pcm93chart_array[i];
4797 m_pcm93chart_array[i] = NULL;
4803 if (m_pcm93chart_current) {
4806 m_pcm93chart_current->SetVPParms(vpt);
4810 float yc = vpt.
clat;
4811 float xc = vpt.
clon;
4813 if (!m_pcm93chart_current->GetCoverSet()->GetCoverCount()) {
4815 printf(
" chart %c has no M_COVR\n", (
char)(
'A' + cmscale - 1));
4818 if (m_pcm93chart_current->IsPointInLoadedM_COVR(xc, yc)) {
4820 printf(
" chart %c contains clat/clon\n", (
char)(
'A' + cmscale - 1));
4822 cellscale_is_useable =
true;
4836 else if (vpt.b_quilt && vpt.b_FullScreenQuilt) {
4839 covr_set *pcover = m_pcm93chart_current->GetCoverSet();
4841 bool boverlap =
false;
4842 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
4845 if (!(vp.GetBBox().IntersectOut(mcd->m_covr_bbox))) {
4850 if (boverlap) cellscale_is_useable =
true;
4854 if (!cellscale_is_useable) {
4862 printf(
" VP is not in M_COVR, adjusting cmscale to %c\n",
4863 (
char)(
'A' + cmscale - 1));
4870 double zoom_factor = scale_breaks[7 - cmscale] / vpt.
chart_scale;
4872 if (zoom_factor > 4.0) {
4875 float yc = vpt.
clat;
4876 float xc = vpt.
clon;
4879 FillScaleArray(vpt.
clat, vpt.
clon);
4880 int new_scale = cmscale;
4881 bool b_found =
false;
4882 while (new_scale <= 7) {
4883 if (m_bScale_Array[new_scale]) {
4884 double new_zoom_factor =
4888 if (new_zoom_factor < 1.0) {
4890 new_scale = cmscale;
4894 if (new_zoom_factor < 4.0) {
4895 if (NULL == m_pcm93chart_array[new_scale]) {
4896 m_pcm93chart_array[new_scale] =
new cm93chart();
4898 ext = (wxChar)(
'A' + new_scale - 1);
4899 if (new_scale == 0) ext =
'Z';
4901 wxString file_dummy = _T (
"CM93." );
4904 m_pcm93chart_array[new_scale]->SetCM93Dict(m_pDictComposite);
4905 m_pcm93chart_array[new_scale]->SetCM93Prefix(m_prefixComposite);
4906 m_pcm93chart_array[new_scale]->SetCM93Manager(m_pcm93mgr);
4908 m_pcm93chart_array[new_scale]->SetColorScheme(
4909 m_global_color_scheme);
4910 m_pcm93chart_array[new_scale]->Init(file_dummy, FULL_INIT);
4913 m_pcm93chart_array[new_scale]->SetVPParms(vpt);
4914 if (m_pcm93chart_array[new_scale]->IsPointInLoadedM_COVR(xc, yc)) {
4923 cmscale = new_scale;
4924 m_pcm93chart_current = m_pcm93chart_array[cmscale];
4934void cm93compchart::FillScaleArray(
double lat,
double lon) {
4935 for (
int cmscale = 0; cmscale < 8; cmscale++)
4936 m_bScale_Array[cmscale] =
4937 Is_CM93Cell_Present(m_prefixComposite, lat, lon, cmscale);
4943wxString cm93compchart::GetPubDate() {
4946 if (NULL != m_pcm93chart_current)
4948 data.Printf(_T (
"%4d" ), m_current_cell_pub_date);
4950 data = _T (
"????" );
4954int cm93compchart::GetNativeScale() {
4955 if (m_pcm93chart_current)
4956 return m_pcm93chart_current->GetNativeScale();
4961double cm93compchart::GetNormalScaleMin(
double canvas_scale_factor,
4962 bool b_allow_overzoom) {
4966 if (m_pcm93chart_current) {
4968 if (m_pcm93chart_current->m_last_vp.IsValid()) {
4969 FillScaleArray(m_pcm93chart_current->m_last_vp.clat,
4970 m_pcm93chart_current->m_last_vp.clon);
4974 while (cmscale > 0) {
4975 if (m_bScale_Array[cmscale])
break;
4983 return 20000000. / oz_factor;
4985 return 3000000. / oz_factor;
4987 return 1000000. / oz_factor;
4989 return 200000. / oz_factor;
4991 return 100000. / oz_factor;
4993 return 50000. / oz_factor;
4995 return 20000. / oz_factor;
4999 return 500. / oz_factor;
5005double cm93compchart::GetNormalScaleMax(
double canvas_scale_factor,
5007 return (180. / 360.) * PI * 2 *
5008 (WGS84_semimajor_axis_meters / (canvas_width / canvas_scale_factor));
5012wxPoint GetPixFromLLVP(
double lat,
double lon,
const ViewPort &VPoint) {
5014 double easting, northing;
5016 double s, y3, s0, y30;
5017 double z = WGS84_semimajor_axis_meters * mercator_k0;
5022 if (lon * VPoint.
clon < 0.) {
5030 if (fabs(xlon - VPoint.
clon) > 180.) {
5031 if (xlon > VPoint.
clon)
5036 easting = (xlon - VPoint.
clon) * DEGREE * z;
5038 s = sin(lat * DEGREE);
5039 y3 = (.5 * log((1 + s) / (1 - s))) * z;
5041 s0 = sin(VPoint.
clat * DEGREE);
5042 y30 = (.5 * log((1 + s0) / (1 - s0))) * z;
5043 northing = y3 - y30;
5049 r.x = (int)round((VPoint.
pix_width / 2) + epix);
5050 r.y = (int)round((VPoint.
pix_height / 2) - npix);
5057void cm93compchart::GetValidCanvasRegion(
const ViewPort &VPoint,
5061 VPoint, g_bopengl ? VPoint.rv_rect : screen_region);
5062 *pValidRegion = ret;
5065OCPNRegion cm93compchart::GetValidScreenCanvasRegion(
5073 if (m_pcm93chart_current) {
5074 int chart_native_scale = m_pcm93chart_current->GetNativeScale();
5076 for (
unsigned int im = 0;
5077 im < m_pcm93chart_current->m_pcovr_array_loaded.GetCount(); im++) {
5078 M_COVR_Desc *pmcd = (m_pcm93chart_current->m_pcovr_array_loaded[im]);
5083 if (vp.GetBBox().IntersectOut(pmcd->m_covr_bbox))
continue;
5085 wxPoint *DrawBuf = m_pcm93chart_current->GetDrawBuffer(pmcd->m_nvertices);
5088 ScreenRegion, pmcd->m_nvertices, (
float *)pmcd->pvertices,
5089 chart_native_scale, DrawBuf);
5091 if (rgn_covr.IsOk())
5092 ret_region.Union(rgn_covr);
5101LLRegion cm93compchart::GetValidRegion() {
5102 if (m_pcm93chart_current)
return m_pcm93chart_current->GetValidRegion();
5107bool cm93compchart::RenderRegionViewOnGL(
const wxGLContext &glc,
5110 const LLRegion &Region) {
5113 if (g_pCM93OffsetDialog && g_pCM93OffsetDialog->IsShown())
5114 g_pCM93OffsetDialog->UpdateMCOVRList(VPoint);
5116 return DoRenderRegionViewOnGL(glc, VPoint, RectRegion, Region);
5119bool cm93compchart::DoRenderRegionViewOnGL(
const wxGLContext &glc,
5122 const LLRegion &Region) {
5129 bool render_return =
false;
5130 if (m_pcm93chart_current == 0)
return render_return;
5138 if (VPoint.b_quilt) {
5139 LLRegion vpr_empty = Region;
5140 LLRegion chart_region = GetValidRegion();
5159 if (!chart_region.Empty()) vpr_empty.Subtract(chart_region);
5161 if (!vpr_empty.Empty() &&
5165 int cmscale_save = m_cmscale;
5167 LLRegion region_vect[8];
5171 while (!vpr_empty.Empty() && m_cmscale) {
5173 m_cmscale = PrepareChartScale(vp, m_cmscale - 1,
false);
5175 if (m_pcm93chart_current) {
5176 LLRegion sscale_region = GetValidRegion();
5179 region_vect[m_cmscale] = sscale_region;
5180 region_vect[m_cmscale].Intersect(vpr_empty);
5183 vpr_empty.Subtract(sscale_region);
5190 for (
int i = 0; i < 8; i++) {
5191 if (!region_vect[i].Empty()) {
5192 m_cmscale = PrepareChartScale(vp, i,
false);
5193 if (m_pcm93chart_current)
5194 render_return |= m_pcm93chart_current->RenderRegionViewOnGL(
5195 glc, vp, RectRegion, region_vect[i]);
5200 m_cmscale = cmscale_save;
5201 m_pcm93chart_current = m_pcm93chart_array[m_cmscale];
5205 if (m_pcm93chart_current) {
5206 render_return |= m_pcm93chart_current->RenderRegionViewOnGL(
5207 glc, vp, RectRegion, Region);
5208 m_Name = m_pcm93chart_current->GetName();
5213 if (m_pcm93chart_current) {
5214 render_return = m_pcm93chart_current->RenderRegionViewOnGL(
5215 glc, vp, RectRegion, Region);
5216 m_Name = m_pcm93chart_current->GetLastFileName();
5221 if (VPoint.m_projection_type != PROJECTION_MERCATOR)
5222 return render_return;
5224 if (!m_pcm93chart_current)
return render_return;
5227 if (m_cell_index_special_outline) {
5229 glChartCanvas *glc = gFrame->GetPrimaryCanvas()->GetglCanvas();
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;
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,
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) {
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)
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;
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,
5698bool cm93compchart::RenderNextSmallerCellOutlines(
ocpnDC &dc,
ViewPort &vp,
5700 if (m_cmscale >= 7)
return false;
5703 if (!glcc)
return false;
5710 int nss = m_cmscale + 1;
5719 bool bdrawn =
false;
5728 if(nss_max > m_cmscale+3)
5729 nss_max = m_cmscale+3;
5732 while (nss <= nss_max && (!bdrawn || (vp.
chart_scale < 3e6))) {
5733 cm93chart *psc = m_pcm93chart_array[nss];
5736 m_pcm93chart_array[nss] =
new cm93chart();
5737 psc = m_pcm93chart_array[nss];
5739 wxChar ext = (wxChar)(
'A' + nss - 1);
5740 if (nss == 0) ext =
'Z';
5742 wxString file_dummy = _T (
"CM93." );
5745 psc->SetCM93Dict(m_pDictComposite);
5746 psc->SetCM93Prefix(m_prefixComposite);
5747 psc->SetCM93Manager(m_pcm93mgr);
5749 psc->SetColorScheme(m_global_color_scheme);
5750 psc->Init(file_dummy, FULL_INIT);
5756 psc->UpdateCovrSet(&vp);
5759 covr_set *pcover = psc->GetCoverSet();
5761 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
5764 if (vp.GetBBox().IntersectOut(mcd->m_covr_bbox))
continue;
5766 wxPoint *pwp = psc->GetDrawBuffer(mcd->m_nvertices);
5767 bdrawn = RenderCellOutlines(dc, vp, pwp, mcd);
5775 glDisable(GL_LINE_STIPPLE);
5776 glDisable(GL_LINE_SMOOTH);
5777 glDisable(GL_BLEND);
5783bool cm93compchart::RenderCellOutlines(
ocpnDC &dc,
ViewPort &vp, wxPoint *pwp,
5785 float_2Dpt *p = mcd->pvertices;
5786 int np = mcd->m_nvertices;
5788 for (
int ip = 0; ip < np; ip++, p++) {
5798 wxPoint p0 = pwp[0];
5799 for (
int ip = 1; ip < np; ip++) {
5800 if (((p0.x > vp.
pix_width) && (pwp[ip].x < 0)) ||
5801 ((p0.x < 0) && (pwp[ip].x > vp.
pix_width)))
5807 dc.DrawLines(mcd->m_nvertices, pwp, 0, 0,
false);
5811void cm93compchart::GetPointPix(ObjRazRules *rzRules,
float rlat,
float rlon,
5813 m_pcm93chart_current->GetPointPix(rzRules, rlat, rlon, r);
5816void cm93compchart::GetPointPix(ObjRazRules *rzRules, wxPoint2DDouble *en,
5817 wxPoint *r,
int nPoints) {
5818 m_pcm93chart_current->GetPointPix(rzRules, en, r, nPoints);
5821void cm93compchart::GetPixPoint(
int pixx,
int pixy,
double *plat,
double *plon,
5823 m_pcm93chart_current->GetPixPoint(pixx, pixy, plat, plon, vpt);
5826void cm93compchart::UpdateLUPs(
s57chart *pOwner) {
5827 for (
int i = 0; i < 8; i++) {
5828 if (m_pcm93chart_array[i]) m_pcm93chart_array[i]->UpdateLUPs(pOwner);
5832std::list<S57Obj *> *cm93compchart::GetAssociatedObjects(S57Obj *obj) {
5833 if (m_pcm93chart_current)
5834 return m_pcm93chart_current->GetAssociatedObjects(obj);
5839void cm93compchart::InvalidateCache() {
5840 for (
int i = 0; i < 8; i++) {
5841 if (m_pcm93chart_array[i]) m_pcm93chart_array[i]->InvalidateCache();
5845void cm93compchart::ForceEdgePriorityEvaluate(
void) {
5846 for (
int i = 0; i < 8; i++) {
5847 if (m_pcm93chart_array[i])
5848 m_pcm93chart_array[i]->ForceEdgePriorityEvaluate();
5852void cm93compchart::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
5853 m_global_color_scheme = cs;
5855 for (
int i = 0; i < 8; i++) {
5856 if (m_pcm93chart_array[i])
5857 m_pcm93chart_array[i]->SetColorScheme(cs, bApplyImmediate);
5861ListOfObjRazRules *cm93compchart::GetObjRuleListAtLatLon(
float lat,
float lon,
5862 float select_radius,
5864 int selection_mask) {
5870 if (!VPoint->b_quilt)
5871 if (m_pcm93chart_current)
5872 return m_pcm93chart_current->GetObjRuleListAtLatLon(lat, alon,
5873 select_radius, &vp);
5876 ListOfObjRazRules *ret_ptr =
new ListOfObjRazRules;
5880 UpdateRenderRegions(*VPoint);
5886 for (
int i = 0; i < 8; i++) {
5887 if (m_pcm93chart_array[i]) {
5888 if (!m_pcm93chart_array[i]->m_render_region.IsEmpty()) {
5889 if (wxInRegion == m_pcm93chart_array[i]->m_render_region.Contains(p))
5890 return m_pcm93chart_array[i]->GetObjRuleListAtLatLon(
5891 lat, alon, select_radius, &vp, selection_mask);
5897 ListOfObjRazRules *ret_ptr =
new ListOfObjRazRules;
5903std::unordered_map<unsigned, VE_Element *> &cm93compchart::Get_ve_hash(
void) {
5904 return m_pcm93chart_current->Get_ve_hash();
5907std::unordered_map<unsigned, VC_Element *> &cm93compchart::Get_vc_hash(
void) {
5908 return m_pcm93chart_current->Get_vc_hash();
5919 m_last_cell_adjustvp = m_pcm93chart_current;
5927 if (m_pcm93chart_current)
return false;
5936 int cmscale = GetCMScaleFromVP(
5939 int cmscale_actual = PrepareChartScale(
5940 vp_proposed, cmscale,
5944 printf(
" In AdjustVP, adjustment subchart scale is %c\n",
5945 (
char)(
'A' + cmscale_actual - 1));
5951 bool single_adjust =
false;
5952 if (m_pcm93chart_array[cmscale_actual])
5954 m_pcm93chart_array[cmscale_actual]->AdjustVP(vp_last, vp_proposed);
5956 if (m_cmscale != cmscale_actual)
return false;
5960 if (vp_last.b_quilt)
return false;
5962 return single_adjust;
5965ThumbData *cm93compchart::GetThumbData(
int tnx,
int tny,
float lat,
float lon) {
5969InitReturn cm93compchart::CreateHeaderData() {
5970 m_Chart_Scale = 20000000;
5976 wxDir dirt(m_prefixComposite);
5978 wxRegEx test(_T(
"[0-9]+"));
5980 bool b_cont = dirt.GetFirst(&candidate);
5983 if (test.Matches(candidate) && (candidate.Len() == 8)) {
5984 wxString dir = m_prefixComposite;
5986 if (wxDir::Exists(dir)) {
5987 wxFileName name(dir);
5988 wxString num_name = name.GetName();
5990 if (num_name.ToLong(&number)) {
5991 int ilat = number / 10000;
5992 int ilon = number % 10000;
5994 int lat_base = (ilat - 270) / 3.;
5995 int lon_base = ilon / 3.;
5996 extent_rect.Union(wxRect(lon_base, lat_base, 20, 20));
6000 b_cont = dirt.GetNext(&candidate);
6004 m_FullExtent.ELON = ((double)extent_rect.x + (
double)extent_rect.width);
6005 m_FullExtent.WLON = ((double)extent_rect.x);
6006 m_FullExtent.NLAT = ((double)extent_rect.y + (
double)extent_rect.height);
6007 m_FullExtent.SLAT = ((double)extent_rect.y);
6008 m_bExtentSet =
true;
6012 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
6013 *m_pCOVRTablePoints = 4;
6014 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
6015 float *pf = (
float *)malloc(2 * 4 *
sizeof(
float));
6019 *pfe++ = m_FullExtent.NLAT;
6020 *pfe++ = m_FullExtent.WLON;
6022 *pfe++ = m_FullExtent.NLAT;
6023 *pfe++ = m_FullExtent.ELON;
6025 *pfe++ = m_FullExtent.SLAT;
6026 *pfe++ = m_FullExtent.ELON;
6028 *pfe++ = m_FullExtent.SLAT;
6029 *pfe++ = m_FullExtent.WLON;
6034cm93_dictionary *cm93compchart::FindAndLoadDictFromDir(
const wxString &dir) {
6039 if (pdict->LoadDictionary(dir))
return pdict;
6044 wxString path = dir;
6048 while (i < path.Len()) {
6049 target.Append(path[i]);
6050 if (path[i] == wxFileName::GetPathSeparator()) {
6054 if (pdict->LoadDictionary(target)) {
6068 wxFileName fnc(dir);
6069 wxString found_dict_file_name;
6073 path = fnc.GetPath(wxPATH_GET_VOLUME);
6075 wxString msg = _T (
" Looking harder for CM93 dictionary in " );
6079 if ((path.Len() == 0) || path.IsSameAs(fnc.GetPathSeparator())) {
6081 wxLogMessage(_T (
"Early break1" ));
6087 if ((wxNOT_FOUND == path.Lower().Find(_T (
"cm93" )))) {
6089 wxLogMessage(_T (
"Early break2" ));
6097 if (dir.IsOpened()) {
6100 dir.Traverse(cm93Dictionary);
6101 bdone = found_dict_file_name.Len() != 0;
6107 if (found_dict_file_name.Len()) {
6108 wxFileName fnd(found_dict_file_name);
6110 fnd.GetPath((
int)(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME));
6112 if (pdict->LoadDictionary(dpath)) retval = pdict;
6115 if (NULL == retval)
delete pdict;
6120void cm93compchart::CloseandReopenCurrentSubchart(
void) {
6121 delete m_pcm93chart_current;
6122 m_pcm93chart_current = NULL;
6123 m_pcm93chart_array[m_cmscale] = NULL;
6147 const wxPoint &pos,
const wxSize &size,
long style);
6150 wxString OnGetItemText(
long item,
long column)
const;
6151 int OnGetItemColumnImage(
long item,
long column)
const;
6156OCPNOffsetListCtrl::OCPNOffsetListCtrl(
CM93OffsetDialog *parent, wxWindowID
id,
6157 const wxPoint &pos,
const wxSize &size,
6159 : wxListCtrl(parent, id, pos, size, style) {
6163OCPNOffsetListCtrl::~OCPNOffsetListCtrl() {}
6165wxString OCPNOffsetListCtrl::OnGetItemText(
long item,
long column)
const {
6167 M_COVR_Desc *pmcd = m_parent->m_pcovr_array[item];
6171 ret.Printf(_T (
"%d" ), pmcd->m_cell_index);
6172 if (((
int)
'0') == pmcd->m_subcell)
6173 ret.Prepend(_T (
"0" ));
6175 char t = (char)pmcd->m_subcell;
6177 p.Printf(_T (
"%c" ), t);
6184 ret.Printf(_T (
"%d" ), pmcd->m_object_id);
6188 ret = m_parent->m_selected_chart_scale_char;
6192 ret.Printf(_T (
"%g" ), pmcd->transform_WGS84_offset_x);
6196 ret.Printf(_T (
"%g" ), pmcd->transform_WGS84_offset_y);
6200 ret.Printf(_T (
"%6.0f" ), pmcd->user_xoff * pmcd->m_centerlat_cos);
6204 ret.Printf(_T (
"%6.0f" ), pmcd->user_yoff * pmcd->m_centerlat_cos);
6213int OCPNOffsetListCtrl::OnGetItemColumnImage(
long item,
long column)
const {
6224EVT_CLOSE(CM93OffsetDialog::OnClose)
6229 m_pcompchart = NULL;
6234 m_selected_list_index = -1;
6235 m_selected_cell_index = 0;
6237 long wstyle = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER;
6238 wxDialog::Create(parent, -1, _(
"OpenCPN CM93 Cell Offset Adjustments"),
6239 wxPoint(0, 0), wxSize(800, 200), wstyle);
6245 wxBoxSizer *topSizer =
new wxBoxSizer(wxHORIZONTAL);
6250 long flags = wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_HRULES | wxLC_VRULES |
6253 flags |= wxLC_VIRTUAL;
6259 m_pListCtrlMCOVRs->Connect(
6260 wxEVT_COMMAND_LIST_ITEM_SELECTED,
6261 wxListEventHandler(CM93OffsetDialog::OnCellSelected), NULL,
this);
6263 int dx = GetCharWidth();
6264 int dy = GetCharHeight();
6267 m_pListCtrlMCOVRs->InsertColumn(tlCELL, _(
"Cell"), wxLIST_FORMAT_LEFT, width);
6270 m_pListCtrlMCOVRs->InsertColumn(tlMCOVR, _(
"M_COVR ID"), wxLIST_FORMAT_CENTER,
6274 m_pListCtrlMCOVRs->InsertColumn(tlSCALE, _(
"Cell Scale"),
6275 wxLIST_FORMAT_CENTER, width);
6278 m_pListCtrlMCOVRs->InsertColumn(tlXOFF, _(
"wgsox"), wxLIST_FORMAT_CENTER,
6282 m_pListCtrlMCOVRs->InsertColumn(tlYOFF, _(
"wgsoy"), wxLIST_FORMAT_CENTER,
6286 m_pListCtrlMCOVRs->InsertColumn(tlUXOFF, _(
"User X Offset"),
6287 wxLIST_FORMAT_CENTER, width);
6290 m_pListCtrlMCOVRs->InsertColumn(tlUYOFF, _(
"User Y Offset"),
6291 wxLIST_FORMAT_CENTER, width);
6293 topSizer->Add(m_pListCtrlMCOVRs, 1, wxEXPAND | wxALL, 0);
6295 wxBoxSizer *boxSizer02 =
new wxBoxSizer(wxVERTICAL);
6296 boxSizer02->AddSpacer(22);
6298 wxStaticText *pStaticTextXoff =
new wxStaticText(
6300 wxString::Format(_T(
"%s (%s)" ), _(
"User X Offset"), _(
"meters")),
6301 wxDefaultPosition, wxDefaultSize, 0);
6302 boxSizer02->Add(pStaticTextXoff, 0, wxALL, 0);
6305 new wxSpinCtrl(
this, wxID_ANY, wxEmptyString, wxDefaultPosition,
6306 wxSize(50, -1), wxSP_ARROW_KEYS, -10000, 10000, 0);
6307 m_pSpinCtrlXoff->Connect(wxEVT_COMMAND_SPINCTRL_UPDATED,
6308 wxCommandEventHandler(CM93OffsetDialog::OnOffSetSet),
6310 boxSizer02->Add(m_pSpinCtrlXoff, 0, wxEXPAND | wxALL, 0);
6312 wxStaticText *pStaticTextYoff =
new wxStaticText(
6314 wxString::Format(_T(
"%s (%s)" ), _(
"User Y Offset"), _(
"meters")),
6315 wxDefaultPosition, wxDefaultSize, 0);
6316 boxSizer02->Add(pStaticTextYoff, 0, wxALL, 0);
6319 new wxSpinCtrl(
this, wxID_ANY, wxEmptyString, wxDefaultPosition,
6320 wxSize(50, -1), wxSP_ARROW_KEYS, -10000, 10000, 0);
6321 m_pSpinCtrlYoff->Connect(wxEVT_COMMAND_SPINCTRL_UPDATED,
6322 wxCommandEventHandler(CM93OffsetDialog::OnOffSetSet),
6324 boxSizer02->Add(m_pSpinCtrlYoff, 0, wxEXPAND | wxALL, 0);
6326 m_OKButton =
new wxButton(
this, wxID_ANY, _(
"OK"), wxDefaultPosition,
6328 m_OKButton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
6329 wxCommandEventHandler(CM93OffsetDialog::OnOK), NULL,
6331 boxSizer02->Add(m_OKButton, 0, wxALL, 5);
6332 m_OKButton->SetDefault();
6334 topSizer->Add(boxSizer02, 0, wxEXPAND | wxALL, 2);
6336 wxSize sz(800, dy * 8);
6338 sz = wxGetDisplaySize();
6348 SetSize(GetSize().x, GetSize().y - 1);
6360CM93OffsetDialog::~CM93OffsetDialog() { g_pCM93OffsetDialog = NULL; }
6362void CM93OffsetDialog::OnClose(wxCloseEvent &event) {
6364 m_pcompchart->SetSpecialOutlineCellIndex(0, 0, 0);
6366 m_pcompchart->InvalidateCache();
6369 m_pparent->Refresh(
true);
6370 gFrame->InvalidateAllGL();
6374 if (m_pListCtrlMCOVRs->GetItemCount() > m_selected_list_index)
6375 m_pListCtrlMCOVRs->SetItemState(m_selected_list_index, 0,
6376 wxLIST_STATE_SELECTED);
6381void CM93OffsetDialog::OnOK(wxCommandEvent &event) {
6389 m_pcompchart = pchart;
6392void CM93OffsetDialog::OnOffSetSet(wxCommandEvent &event) {
6393 m_xoff = m_pSpinCtrlXoff->GetValue() / m_centerlat_cos;
6394 m_yoff = m_pSpinCtrlYoff->GetValue() / m_centerlat_cos;
6401void CM93OffsetDialog::UpdateOffsets(
void) {
6402 if (m_pcompchart && m_selected_cell_index) {
6404 m_pcompchart->SetSpecialCellIndexOffset(m_selected_cell_index,
6405 m_selected_object_id,
6406 m_selected_subcell, m_xoff, m_yoff);
6410 AbstractPlatform::ShowBusySpinner();
6411 m_pcompchart->CloseandReopenCurrentSubchart();
6412 AbstractPlatform::HideBusySpinner();
6415 m_pparent->Refresh(
true);
6416 gFrame->InvalidateAllGL();
6421void CM93OffsetDialog::SetColorScheme() { DimeControl(
this); }
6423void CM93OffsetDialog::OnCellSelected(wxListEvent &event) {
6425 m_selected_list_index =
event.GetIndex();
6427 M_COVR_Desc *mcd = m_pcovr_array.Item(event.GetIndex());
6429 if (m_selected_list_index > m_pListCtrlMCOVRs->GetItemCount())
6432 cm93chart *pchart = m_pcompchart->GetCurrentSingleScaleChart();
6434 M_COVR_Desc *cached_mcd = pchart->GetCoverSet()->Find_MCD(
6435 mcd->m_cell_index, mcd->m_object_id, mcd->m_subcell);
6437 m_pSpinCtrlXoff->SetValue(
6438 wxRound(cached_mcd->user_xoff * cached_mcd->m_centerlat_cos));
6439 m_pSpinCtrlYoff->SetValue(
6440 wxRound(cached_mcd->user_yoff * cached_mcd->m_centerlat_cos));
6444 m_pcompchart->SetSpecialOutlineCellIndex(mcd->m_cell_index,
6445 mcd->m_object_id, mcd->m_subcell);
6447 m_selected_cell_index = mcd->m_cell_index;
6448 m_selected_object_id = mcd->m_object_id;
6449 m_selected_subcell = mcd->m_subcell;
6450 m_centerlat_cos = mcd->m_centerlat_cos;
6452 m_pcompchart->InvalidateCache();
6455 m_pparent->Refresh(
true);
6456 gFrame->InvalidateAllGL();
6461void CM93OffsetDialog::UpdateMCOVRList(
const ViewPort &vpt) {
6465 cm93chart *pchart = m_pcompchart->GetCurrentSingleScaleChart();
6468 m_selected_chart_scale_char = pchart->GetScaleChar();
6470 m_pcovr_array.Clear();
6473 std::vector<int> cell_array = pchart->GetVPCellArray(vpt);
6481 covr_set *pcover = pchart->GetCoverSet();
6483 for (
unsigned int im = 0; im < pcover->GetCoverCount(); im++) {
6486 for (
unsigned int icell = 0; icell < cell_array.size(); icell++) {
6487 if (cell_array[icell] == mcd->m_cell_index) {
6488 wxPoint *pwp = pchart->GetDrawBuffer(mcd->m_nvertices);
6495 m_pcovr_array.Add(mcd);
6503 for (
unsigned int im = 0; im < m_pcovr_array.size(); im++) {
6505 if ((m_selected_cell_index == mcd->m_cell_index) &&
6506 (m_selected_object_id == mcd->m_object_id) &&
6507 (m_selected_subcell == mcd->m_subcell)) {
6513 if (!m_pListCtrlMCOVRs->IsVirtual()) {
6514 if (m_pListCtrlMCOVRs->GetItemCount())
6515 m_pListCtrlMCOVRs->DeleteAllItems();
6517 for (
unsigned int i = 0; i < m_pcovr_array.GetCount(); i++) {
6520 m_pListCtrlMCOVRs->InsertItem(item);
6521 for (
int j = 0; j < tlUYOFF + 1; j++) {
6523 item.SetText(m_pListCtrlMCOVRs->OnGetItemText(i, j));
6524 m_pListCtrlMCOVRs->SetItem(item);
6528 m_pListCtrlMCOVRs->SetItemCount(m_pcovr_array.GetCount());
6531 if (-1 != sel_index)
6532 m_pListCtrlMCOVRs->SetItemState(sel_index, wxLIST_STATE_SELECTED,
6533 wxLIST_STATE_SELECTED);
6535 m_pListCtrlMCOVRs->SetItemState(sel_index, 0,
6536 wxLIST_STATE_SELECTED);
6538 m_pListCtrlMCOVRs->Refresh(
true);
6541 m_pListCtrlMCOVRs->Refresh(
false);
Dialog for managing CM93 chart offsets.
An iterator class for OCPNRegion.
A wrapper class for wxRegion with additional functionality.
Represents the view port for chart display in OpenCPN.
double view_scale_ppm
Requested view scale in physical pixels per meter (ppm), before applying projections.
int pix_height
Height of the viewport in physical pixels.
double rotation
Rotation angle of the viewport in radians.
int pix_width
Width of the viewport in physical pixels.
wxPoint2DDouble GetDoublePixFromLL(double lat, double lon)
Convert latitude and longitude on the ViewPort to physical pixel coordinates with double precision.
double skew
Angular distortion (shear transform) applied to the viewport in radians.
void GetLLFromPix(const wxPoint &p, double *lat, double *lon)
Convert physical pixel coordinates on the ViewPort to latitude and longitude.
OCPNRegion GetVPRegionIntersect(const OCPNRegion ®ion, const LLRegion &llregion, int chart_native_scale)
Get the intersection of the viewport with a given region.
double clon
Center longitude of the viewport in degrees.
double clat
Center latitude of the viewport in degrees.
wxPoint GetPixFromLL(double lat, double lon)
Convert latitude and longitude on the ViewPort to physical pixel coordinates.
double chart_scale
Chart scale denominator (e.g., 50000 for a 1:50000 scale).
Represents a single CM93 chart at a specific scale.
Represents a composite CM93 chart covering multiple scales.
OpenGL chart rendering canvas.
Device context class that can use either wxDC or OpenGL for drawing.
void DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, bool b_hiqual=true)
Draw a line between two points using either wxDC or OpenGL.
Represents an S57 format electronic navigational chart in OpenCPN.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
General purpose GUI support.
Tools to send data to plugins.
Runtime representation of a plugin block.