36#include <wx/wfstream.h>
37#include <wx/tokenzr.h>
38#include <wx/filename.h>
40#include <wx/fileconf.h>
53#define OCPN_USE_CONFIG 1
57struct sigaction sa_all_chart;
58struct sigaction sa_all_previous;
62void catch_signals_chart(
int signo) {
65 siglongjmp(env_chart, 1);
77typedef __int32 int32_t;
78typedef unsigned __int32 uint32_t;
79typedef __int64 int64_t;
80typedef unsigned __int64 uint64_t;
87bool G_FloatPtInPolygon(
MyFlPoint *rgpts,
int wnumpts,
float x,
float y);
97ThumbData::ThumbData() { pDIBThumb = NULL; }
99ThumbData::~ThumbData() {
delete pDIBThumb; }
104opncpnPalette::opncpnPalette() {
108 FwdPalette = (
int *)malloc(
sizeof(
int));
109 RevPalette = (
int *)malloc(
sizeof(
int));
114opncpnPalette::~opncpnPalette() {
115 if (NULL != FwdPalette) free(FwdPalette);
116 if (NULL != RevPalette) free(RevPalette);
122ChartBase::ChartBase() {
123 m_depth_unit_id = DEPTH_UNIT_UNKNOWN;
127 m_global_color_scheme = GLOBAL_COLOR_SCHEME_RGB;
129 bReadyToRender =
false;
131 Chart_Error_Factor = 0;
133 m_Chart_Scale = 10000;
138 m_pCOVRTablePoints = NULL;
140 m_nNoCOVREntries = 0;
141 m_pNoCOVRTable = NULL;
142 m_pNoCOVRTablePoints = NULL;
144 m_EdDate = wxInvalidDateTime;
146 m_lon_datum_adjust = 0.;
147 m_lat_datum_adjust = 0.;
149 m_projection = PROJECTION_MERCATOR;
152ChartBase::~ChartBase() {
157 for (
unsigned int j = 0; j < (
unsigned int)m_nCOVREntries; j++)
158 free(m_pCOVRTable[j]);
161 free(m_pCOVRTablePoints);
165 for (
unsigned int j = 0; j < (
unsigned int)m_nNoCOVREntries; j++)
166 free(m_pNoCOVRTable[j]);
168 free(m_pNoCOVRTable);
169 free(m_pNoCOVRTablePoints);
172wxString ChartBase::GetHashKey()
const {
173 wxString key = GetFullPath();
174 wxChar separator = wxFileName::GetPathSeparator();
175 for (
unsigned int pos = 0; pos < key.size(); pos = key.find(separator, pos))
176 key.replace(pos, 1,
"!");
191ChartDummy::ChartDummy() {
193 m_ChartType = CHART_TYPE_DUMMY;
194 m_ChartFamily = CHART_FAMILY_UNKNOWN;
195 m_Chart_Scale = 22000000;
197 m_FullPath =
"No Chart Available";
198 m_Description = m_FullPath;
201ChartDummy::~ChartDummy() {
delete m_pBM; }
203InitReturn ChartDummy::Init(
const wxString &name, ChartInitFlag init_flags) {
207void ChartDummy::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {}
209ThumbData *ChartDummy::GetThumbData(
int tnx,
int tny,
float lat,
float lon) {
213bool ChartDummy::UpdateThumbData(
double lat,
double lon) {
return FALSE; }
215bool ChartDummy::GetChartExtent(
Extent *pext) {
224bool ChartDummy::RenderRegionViewOnGL(
const wxGLContext &glc,
227 const LLRegion &Region) {
231bool ChartDummy::RenderRegionViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint,
233 return RenderViewOnDC(dc, VPoint);
236bool ChartDummy::RenderViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint) {
237 if (m_pBM && m_pBM->IsOk()) {
238 if ((m_pBM->GetWidth() != VPoint.
pix_width) ||
252 dc.SelectObject(*m_pBM);
254 dc.SetBackground(*wxBLACK_BRUSH);
265void ChartDummy::GetValidCanvasRegion(
const ViewPort &VPoint,
267 pValidRegion->Clear();
268 pValidRegion->Union(0, 0, 1, 1);
271LLRegion ChartDummy::GetValidRegion() {
return LLRegion(); }
276ChartGEO::ChartGEO() { m_ChartType = CHART_TYPE_GEO; }
278ChartGEO::~ChartGEO() {}
280InitReturn ChartGEO::Init(
const wxString &name, ChartInitFlag init_flags) {
281#define BUF_LEN_MAX 4096
283 PreInit(name, init_flags, GLOBAL_COLOR_SCHEME_DAY);
285 char buffer[BUF_LEN_MAX];
288 new wxFFileInputStream(name);
290 m_filesize = wxFileName::GetSize(name);
292 if (!ifs_hdr->IsOk())
return INIT_FAIL_REMOVE;
298 m_Description = m_FullPath;
300 wxFileName GEOFile(m_FullPath);
303 Path = GEOFile.GetPath(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME);
307 ifs_hdr->SeekI(0, wxFromStart);
311 while ((ReadBSBHdrLine(ifs_hdr, &buffer[0], BUF_LEN_MAX)) != 0) {
312 wxString str_buf(buffer, wxConvUTF8);
313 if (!strncmp(buffer,
"Bitmap", 6)) {
314 wxStringTokenizer tkz(str_buf,
"=");
315 wxString token = tkz.GetNextToken();
316 if (token.IsSameAs(
"Bitmap", TRUE)) {
317 pBitmapFilePath =
new wxString();
320 i = tkz.GetPosition();
321 pBitmapFilePath->Clear();
323 pBitmapFilePath->Append(buffer[i]);
329 else if (!strncmp(buffer,
"Scale", 5)) {
330 wxStringTokenizer tkz(str_buf,
"=");
331 wxString token = tkz.GetNextToken();
332 if (token.IsSameAs(
"Scale", TRUE))
335 i = tkz.GetPosition();
336 m_Chart_Scale = atoi(&buffer[i]);
340 else if (!strncmp(buffer,
"Depth", 5)) {
341 wxStringTokenizer tkz(str_buf,
"=");
342 wxString token = tkz.GetNextToken();
343 if (token.IsSameAs(
"Depth Units", FALSE))
346 i = tkz.GetPosition();
347 wxString str(&buffer[i], wxConvUTF8);
348 m_DepthUnits = str.Trim();
352 else if (!strncmp(buffer,
"Point", 5))
356 sscanf(&buffer[0],
"Point%d=%f %f %d %d", &i, &lnr, <r, &yr, &xr);
359 pRefTable[nRefpoint].xr = xr;
360 pRefTable[nRefpoint].yr = yr;
361 pRefTable[nRefpoint].latr = ltr;
362 pRefTable[nRefpoint].lonr = lnr;
363 pRefTable[nRefpoint].bXValid = 1;
364 pRefTable[nRefpoint].bYValid = 1;
370 else if (!strncmp(buffer,
"Vertex", 6)) {
373 sscanf(buffer,
"Vertex%d=%f %f", &i, <p, &lnp);
377 if (NULL == pPlyTable) {
381 pPlyTable[nPlypoint].ltp = ltp;
382 pPlyTable[nPlypoint].lnp = lnp;
387 else if (!strncmp(buffer,
"Date Pub", 8)) {
388 char date_string[40];
390 sscanf(buffer,
"Date Published=%s\r\n", &date_string[0]);
391 wxString date_wxstr(date_string, wxConvUTF8);
393 if (dt.ParseDate(date_wxstr))
395 sprintf(date_buf,
"%d", dt.GetYear());
397 sscanf(date_string,
"%s", date_buf);
399 m_PubYear = wxString(date_buf, wxConvUTF8);
402 else if (!strncmp(buffer,
"Skew", 4)) {
403 wxStringTokenizer tkz(str_buf,
"=");
404 wxString token = tkz.GetNextToken();
405 if (token.IsSameAs(
"Skew Angle", FALSE))
408 i = tkz.GetPosition();
410 sscanf(&buffer[i],
"%f,", &fcs);
415 else if (!strncmp(buffer,
"Latitude Offset", 15)) {
416 wxStringTokenizer tkz(str_buf,
"=");
417 wxString token = tkz.GetNextToken();
418 if (token.IsSameAs(
"Latitude Offset", FALSE)) {
420 i = tkz.GetPosition();
422 sscanf(&buffer[i],
"%f,", <o);
427 else if (!strncmp(buffer,
"Longitude Offset", 16)) {
428 wxStringTokenizer tkz(str_buf,
"=");
429 wxString token = tkz.GetNextToken();
430 if (token.IsSameAs(
"Longitude Offset", FALSE)) {
432 i = tkz.GetPosition();
434 sscanf(&buffer[i],
"%f,", &lno);
439 else if (!strncmp(buffer,
"Datum", 5)) {
440 wxStringTokenizer tkz(str_buf,
"=");
441 wxString token = tkz.GetNextToken();
442 if (token.IsSameAs(
"Datum", FALSE)) {
443 token = tkz.GetNextToken();
448 else if (!strncmp(buffer,
"Name", 4)) {
449 wxStringTokenizer tkz(str_buf,
"=");
450 wxString token = tkz.GetNextToken();
451 if (token.IsSameAs(
"Name", FALSE))
454 i = tkz.GetPosition();
456 while (isprint(buffer[i]) && (i < 80)) m_Name.Append(buffer[i++]);
468 if (pBitmapFilePath == NULL) {
470 return INIT_FAIL_REMOVE;
473 wxString NOS_Name(*pBitmapFilePath);
475 wxDir target_dir(Path);
476 wxArrayString file_array;
477 int nfiles = wxDir::GetAllFiles(Path, &file_array);
480 pBitmapFilePath->Prepend(Path);
482 wxFileName NOS_filename(*pBitmapFilePath);
483 if (!NOS_filename.FileExists()) {
487 wxString fname(NOS_filename.GetName());
488 wxString fext(NOS_filename.GetExt());
494 NOS_filename.SetName(fname);
495 NOS_filename.SetExt(fext);
497 if (NOS_filename.FileExists())
goto found_uclc_file;
502 NOS_filename.SetName(fname);
503 NOS_filename.SetExt(fext);
505 if (NOS_filename.FileExists())
goto found_uclc_file;
510 NOS_filename.SetName(fname);
511 NOS_filename.SetExt(fext);
513 if (NOS_filename.FileExists())
goto found_uclc_file;
518 NOS_filename.SetName(fname);
519 NOS_filename.SetExt(fext);
521 if (NOS_filename.FileExists())
goto found_uclc_file;
525 for (ifile = 0; ifile < nfiles; ifile++) {
526 wxString file_up = file_array[ifile];
529 wxString target_up = *pBitmapFilePath;
530 target_up.MakeUpper();
532 if (file_up.IsSameAs(target_up)) {
533 NOS_filename.Clear();
534 NOS_filename.Assign(file_array[ifile]);
535 goto found_uclc_file;
540 return INIT_FAIL_REMOVE;
544 delete pBitmapFilePath;
545 pBitmapFilePath =
new wxString(NOS_filename.GetFullPath());
548 new wxFFileInputStream(*pBitmapFilePath);
549 ifs_bitmap =
new wxBufferedInputStream(*ifss_bitmap);
551 if (!ifss_bitmap->IsOk()) {
553 return INIT_FAIL_REMOVE;
556 while ((ReadBSBHdrLine(ifss_bitmap, &buffer[0], BUF_LEN_MAX)) != 0) {
557 wxString str_buf(buffer, wxConvUTF8);
559 if (!strncmp(buffer,
"NOS", 3)) {
560 wxStringTokenizer tkz(str_buf,
",=");
561 while (tkz.HasMoreTokens()) {
562 wxString token = tkz.GetNextToken();
563 if (token.IsSameAs(
"RA", TRUE))
568 i = tkz.GetPosition();
569 Size_X = atoi(&buffer[i]);
570 wxString token = tkz.GetNextToken();
571 i = tkz.GetPosition();
572 Size_Y = atoi(&buffer[i]);
573 }
else if (token.IsSameAs(
"DU", TRUE))
575 token = tkz.GetNextToken();
577 if (token.ToLong(&temp_du)) m_Chart_DU = temp_du;
583 else if (!strncmp(buffer,
"RGB", 3))
584 CreatePaletteEntry(buffer, COLOR_RGB_DEFAULT);
586 else if (!strncmp(buffer,
"DAY", 3))
587 CreatePaletteEntry(buffer, DAY);
589 else if (!strncmp(buffer,
"DSK", 3))
590 CreatePaletteEntry(buffer, DUSK);
592 else if (!strncmp(buffer,
"NGT", 3))
593 CreatePaletteEntry(buffer, NIGHT);
595 else if (!strncmp(buffer,
"NGR", 3))
596 CreatePaletteEntry(buffer, NIGHTRED);
598 else if (!strncmp(buffer,
"GRY", 3))
599 CreatePaletteEntry(buffer, GRAY);
601 else if (!strncmp(buffer,
"PRC", 3))
602 CreatePaletteEntry(buffer, PRC);
604 else if (!strncmp(buffer,
"PRG", 3))
605 CreatePaletteEntry(buffer, PRG);
609 if (Size_X <= 0 || Size_Y <= 0) {
611 return INIT_FAIL_REMOVE;
615 wxString msg(
" Chart File contains less than 3 PLY points: ");
616 msg.Append(m_FullPath);
620 return INIT_FAIL_REMOVE;
623 if (m_datum_str.IsEmpty()) {
624 wxString msg(
" Chart datum not specified on chart ");
625 msg.Append(m_FullPath);
627 wxLogMessage(
" Default datum (WGS84) substituted.");
632 strncpy(d_str, m_datum_str.mb_str(), 99);
635 int datum_index = GetDatumIndex(d_str);
637 if (datum_index < 0) {
638 wxString msg(
" Chart datum {");
640 msg +=
"} invalid on chart ";
641 msg.Append(m_FullPath);
643 wxLogMessage(
" Default datum (WGS84) substituted.");
645 datum_index = DATUM_INDEX_WGS84;
647 m_datum_index = datum_index;
652 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
653 *m_pCOVRTablePoints = nPlypoint;
654 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
655 *m_pCOVRTable = (
float *)malloc(nPlypoint * 2 *
sizeof(
float));
656 memcpy(*m_pCOVRTable, pPlyTable, nPlypoint * 2 *
sizeof(
float));
660 if (!SetMinMax())
return INIT_FAIL_REMOVE;
664 if (init_flags == HEADER_ONLY)
return INIT_OK;
668 if ((c = ifs_bitmap->GetC()) != 0x1a) {
669 return INIT_FAIL_REMOVE;
671 if ((c = ifs_bitmap->GetC()) == 0x0d) {
672 if ((c = ifs_bitmap->GetC()) != 0x0a) {
673 return INIT_FAIL_REMOVE;
675 if ((c = ifs_bitmap->GetC()) != 0x1a) {
676 return INIT_FAIL_REMOVE;
678 if ((c = ifs_bitmap->GetC()) != 0x00) {
679 return INIT_FAIL_REMOVE;
683 else if (c != 0x00) {
684 return INIT_FAIL_REMOVE;
688 nColorSize = ifs_bitmap->GetC();
689 if (nColorSize == wxEOF || nColorSize <= 0 || nColorSize > 7) {
690 wxString msg(
" Invalid nColorSize data, corrupt on chart ");
691 msg.Append(m_FullPath);
693 return INIT_FAIL_REMOVE;
697 InitReturn pi_ret = PostInit();
698 if (pi_ret != INIT_OK)
708ChartKAP::ChartKAP() { m_ChartType = CHART_TYPE_KAP; }
710ChartKAP::~ChartKAP() {}
712InitReturn ChartKAP::Init(
const wxString &name, ChartInitFlag init_flags) {
713#define BUF_LEN_MAX 4096
715 ifs_hdr =
new ChartDataNonSeekableInputStream(
718 if (!ifs_hdr->IsOk())
return INIT_FAIL_REMOVE;
723 PreInit(name, init_flags, GLOBAL_COLOR_SCHEME_DAY);
725 char buffer[BUF_LEN_MAX];
728 m_Description = m_FullPath;
731 for (
int icl = 0; icl < 12; icl++) {
741 unsigned int TestBlockSize = 1999;
742 ifs_hdr->Read(buffer, TestBlockSize);
744 if (ifs_hdr->LastRead() != TestBlockSize) {
746 msg.Printf(
" Could not read first %d bytes of header for chart file: ",
751 return INIT_FAIL_REMOVE;
755 for (i = 0; i < TestBlockSize - 4; i++) {
757 if (buffer[i + 0] ==
'B' && buffer[i + 1] ==
'S' && buffer[i + 2] ==
'B' &&
758 buffer[i + 3] ==
'/')
762 if (buffer[i + 0] ==
'N' && buffer[i + 1] ==
'O' && buffer[i + 2] ==
'S' &&
763 buffer[i + 3] ==
'/')
766 if (i == TestBlockSize - 4) {
767 wxString msg(
" Chart file has no BSB header, cannot Init.");
771 return INIT_FAIL_REMOVE;
775 ifs_hdr->SeekI(0, wxFromStart);
779 int done_header_parse = 0;
780 wxCSConv iso_conv(
"ISO-8859-1");
782 while (done_header_parse == 0) {
783 if (ReadBSBHdrLine(ifs_hdr, buffer, BUF_LEN_MAX) == 0) {
789 done_header_parse = 1;
792 return INIT_FAIL_REMOVE;
798 wxString str_buf(buffer, wxConvUTF8);
800 str_buf = wxString(buffer, iso_conv);
802 if (str_buf.Find(
"SHOM") != wxNOT_FOUND) m_b_SHOM =
true;
804 if (!strncmp(buffer,
"BSB", 3)) {
805 wxString clip_str_buf(
808 wxStringTokenizer tkz(clip_str_buf,
"/,=");
809 while (tkz.HasMoreTokens()) {
810 wxString token = tkz.GetNextToken();
811 if (token.IsSameAs(
"RA", TRUE))
814 i = tkz.GetPosition();
815 Size_X = atoi(&buffer[i]);
816 wxString token = tkz.GetNextToken();
817 i = tkz.GetPosition();
818 Size_Y = atoi(&buffer[i]);
819 }
else if (token.IsSameAs(
"NA", TRUE))
821 int i = tkz.GetPosition();
824 while ((buffer[i] !=
',') && (i < 80)) nbuf[j++] = buffer[i++];
826 wxString n_str(nbuf, iso_conv);
828 }
else if (token.IsSameAs(
"NU", TRUE))
830 int i = tkz.GetPosition();
833 while ((buffer[i] !=
',') && (i < 80)) nbuf[j++] = buffer[i++];
835 wxString n_str(nbuf, iso_conv);
837 }
else if (token.IsSameAs(
"DU", TRUE))
839 token = tkz.GetNextToken();
841 if (token.ToLong(&temp_du)) m_Chart_DU = temp_du;
846 else if (!strncmp(buffer,
"KNP", 3)) {
847 wxString conv_buf(buffer, iso_conv);
848 wxStringTokenizer tkz(conv_buf,
"/,=");
849 while (tkz.HasMoreTokens()) {
850 wxString token = tkz.GetNextToken();
851 if (token.IsSameAs(
"SC", TRUE))
854 i = tkz.GetPosition();
855 m_Chart_Scale = atoi(&buffer[i]);
856 if (0 == m_Chart_Scale) m_Chart_Scale = 100000000;
857 }
else if (token.IsSameAs(
"SK", TRUE))
860 i = tkz.GetPosition();
862 sscanf(&buffer[i],
"%f,", &fcs);
864 }
else if (token.IsSameAs(
"UN", TRUE))
867 i = tkz.GetPosition();
868 wxString str(&buffer[i], iso_conv);
869 m_DepthUnits = str.BeforeFirst(
',');
870 }
else if (token.IsSameAs(
"GD", TRUE))
873 i = tkz.GetPosition();
874 wxString str(&buffer[i], iso_conv);
875 m_datum_str = str.BeforeFirst(
',').Trim();
876 }
else if (token.IsSameAs(
"SD", TRUE))
879 i = tkz.GetPosition();
880 wxString str(&buffer[i], iso_conv);
881 m_SoundingsDatum = str.BeforeFirst(
',').Trim();
882 }
else if (token.IsSameAs(
"PP",
886 i = tkz.GetPosition();
888 wxString str(&buffer[i], iso_conv);
889 wxString str1 = str.BeforeFirst(
',').Trim();
890 if (str1.ToDouble(&fcs)) m_proj_parameter = fcs;
891 }
else if (token.IsSameAs(
"PR", TRUE))
894 i = tkz.GetPosition();
895 wxString str(&buffer[i], iso_conv);
896 wxString stru = str.MakeUpper();
900 if (stru.Matches(
"*MERCATOR*")) {
901 m_projection = PROJECTION_MERCATOR;
905 if (stru.Matches(
"*TRANSVERSE*")) {
906 m_projection = PROJECTION_TRANSVERSE_MERCATOR;
910 if (stru.Matches(
"*CONIC*")) {
911 m_projection = PROJECTION_POLYCONIC;
915 if (stru.Matches(
"*TM*")) {
916 m_projection = PROJECTION_TRANSVERSE_MERCATOR;
920 if (stru.Matches(
"*GAUSS CONFORMAL*")) {
921 m_projection = PROJECTION_TRANSVERSE_MERCATOR;
926 m_projection = PROJECTION_UNKNOWN;
927 wxString msg(
" Chart projection is ");
928 msg += tkz.GetNextToken();
929 msg +=
" which is unsupported. Disabling chart ";
933 return INIT_FAIL_REMOVE;
935 }
else if (token.IsSameAs(
940 i = tkz.GetPosition();
942 sscanf(&buffer[i],
"%f,", &x);
944 }
else if (token.IsSameAs(
949 i = tkz.GetPosition();
951 sscanf(&buffer[i],
"%f,", &x);
957 else if (!strncmp(buffer,
"RGB", 3))
958 CreatePaletteEntry(buffer, COLOR_RGB_DEFAULT);
960 else if (!strncmp(buffer,
"DAY", 3))
961 CreatePaletteEntry(buffer, DAY);
963 else if (!strncmp(buffer,
"DSK", 3))
964 CreatePaletteEntry(buffer, DUSK);
966 else if (!strncmp(buffer,
"NGT", 3))
967 CreatePaletteEntry(buffer, NIGHT);
969 else if (!strncmp(buffer,
"NGR", 3))
970 CreatePaletteEntry(buffer, NIGHTRED);
972 else if (!strncmp(buffer,
"GRY", 3))
973 CreatePaletteEntry(buffer, GRAY);
975 else if (!strncmp(buffer,
"PRC", 3))
976 CreatePaletteEntry(buffer, PRC);
978 else if (!strncmp(buffer,
"PRG", 3))
979 CreatePaletteEntry(buffer, PRG);
981 else if (!strncmp(buffer,
"REF", 3)) {
984 sscanf(&buffer[4],
"%d,%d,%d,%f,%f", &i, &xr, &yr, <r, &lnr);
987 pRefTable[nRefpoint].xr = xr;
988 pRefTable[nRefpoint].yr = yr;
989 pRefTable[nRefpoint].latr = ltr;
990 pRefTable[nRefpoint].lonr = lnr;
991 pRefTable[nRefpoint].bXValid = 1;
992 pRefTable[nRefpoint].bYValid = 1;
998 else if (!strncmp(buffer,
"WPX", 3)) {
1001 wxStringTokenizer tkz(str_buf.Mid(4),
",");
1002 wxString token = tkz.GetNextToken();
1004 if (token.ToLong((
long int *)&wpx_type)) {
1005 while (tkz.HasMoreTokens() && (idx < 12)) {
1006 token = tkz.GetNextToken();
1007 if (token.ToDouble(&d)) {
1016 else if (!strncmp(buffer,
"WPY", 3)) {
1019 wxStringTokenizer tkz(str_buf.Mid(4),
",");
1020 wxString token = tkz.GetNextToken();
1022 if (token.ToLong((
long int *)&wpy_type)) {
1023 while (tkz.HasMoreTokens() && (idx < 12)) {
1024 token = tkz.GetNextToken();
1025 if (token.ToDouble(&d)) {
1034 else if (!strncmp(buffer,
"PWX", 3)) {
1037 wxStringTokenizer tkz(str_buf.Mid(4),
",");
1038 wxString token = tkz.GetNextToken();
1040 if (token.ToLong((
long int *)&pwx_type)) {
1041 while (tkz.HasMoreTokens() && (idx < 12)) {
1042 token = tkz.GetNextToken();
1043 if (token.ToDouble(&d)) {
1052 else if (!strncmp(buffer,
"PWY", 3)) {
1055 wxStringTokenizer tkz(str_buf.Mid(4),
",");
1056 wxString token = tkz.GetNextToken();
1058 if (token.ToLong((
long int *)&pwy_type)) {
1059 while (tkz.HasMoreTokens() && (idx < 12)) {
1060 token = tkz.GetNextToken();
1061 if (token.ToDouble(&d)) {
1070 else if (!strncmp(buffer,
"CPH", 3)) {
1072 sscanf(&buffer[4],
"%f", &float_cph);
1076 else if (!strncmp(buffer,
"VER", 3)) {
1077 wxStringTokenizer tkz(str_buf,
"/,=");
1078 wxString token = tkz.GetNextToken();
1080 m_bsb_ver = tkz.GetNextToken();
1083 else if (!strncmp(buffer,
"DTM", 3)) {
1085 wxStringTokenizer tkz(str_buf,
"/,=");
1086 wxString token = tkz.GetNextToken();
1088 token = tkz.GetNextToken();
1089 if (token.ToDouble(&val)) m_dtm_lat = val;
1091 token = tkz.GetNextToken();
1092 if (token.ToDouble(&val)) m_dtm_lon = val;
1100 else if (!strncmp(buffer,
"PLY", 3)) {
1103 if (sscanf(&buffer[4],
"%d,%f,%f", &i, <p, &lnp) != 3) {
1105 return INIT_FAIL_REMOVE;
1110 if (NULL == pPlyTable) {
1114 pPlyTable[nPlypoint].ltp = ltp;
1115 pPlyTable[nPlypoint].lnp = lnp;
1118 if (NULL == pPlyTable || nPlypoint > 1000000) {
1125 else if (!strncmp(buffer,
"CED", 3)) {
1126 wxStringTokenizer tkz(str_buf,
"/,=");
1127 while (tkz.HasMoreTokens()) {
1128 wxString token = tkz.GetNextToken();
1129 if (token.IsSameAs(
"ED", TRUE))
1132 i = tkz.GetPosition();
1134 char date_string[40];
1138 sscanf(&buffer[i],
"%s\r\n", date_string);
1139 wxString date_wxstr(date_string, wxConvUTF8);
1142 if (dt.ParseDate(date_wxstr))
1153 }
else if ((iyear >= 50) && (iyear < 100)) {
1157 assert(iyear <= 9999);
1158 sprintf(date_buf,
"%d", iyear);
1163 sscanf(date_string,
"%s", date_buf);
1164 m_EdDate.Set(1, wxDateTime::Jan,
1168 m_PubYear = wxString(date_buf, wxConvUTF8);
1169 }
else if (token.IsSameAs(
"SE", TRUE))
1172 i = tkz.GetPosition();
1173 wxString str(&buffer[i], iso_conv);
1174 m_SE = str.BeforeFirst(
',');
1182 if (m_b_SHOM && (m_bsb_ver ==
"1.1")) m_b_apply_dtm =
false;
1186 if (n_pwx && n_pwy && n_pwx && n_pwy) bHaveEmbeddedGeoref =
true;
1189 if (m_projection == PROJECTION_MERCATOR)
1190 m_proj_lat = m_proj_parameter;
1191 else if (m_projection == PROJECTION_TRANSVERSE_MERCATOR)
1192 m_proj_lon = m_proj_parameter;
1193 else if (m_projection == PROJECTION_POLYCONIC)
1194 m_proj_lon = m_proj_parameter;
1198 if (m_proj_lat > 82.0 || m_proj_lat < -82.0) m_proj_lat = 0.0;
1201 if (Size_X <= 0 || Size_Y <= 0) {
1203 return INIT_FAIL_REMOVE;
1206 if (nPlypoint < 3) {
1207 wxString msg(
" Chart File contains less than 3 or too many PLY points: ");
1208 msg.Append(m_FullPath);
1211 return INIT_FAIL_REMOVE;
1214 if (m_datum_str.IsEmpty()) {
1215 wxString msg(
" Chart datum not specified on chart ");
1216 msg.Append(m_FullPath);
1218 wxLogMessage(
" Default datum (WGS84) substituted.");
1223 strncpy(d_str, m_datum_str.mb_str(), 99);
1226 int datum_index = GetDatumIndex(d_str);
1228 if (datum_index < 0) {
1229 wxString msg(
" Chart datum {");
1231 msg +=
"} invalid on chart ";
1232 msg.Append(m_FullPath);
1234 wxLogMessage(
" Default datum (WGS84) substituted.");
1246 if ((m_projection != PROJECTION_MERCATOR &&
1247 m_projection != PROJECTION_TRANSVERSE_MERCATOR) ||
1250 AnalyzeRefpoints(
false);
1259 for (
int i = 0; i < nPlypoint; i++) {
1260 m_LatMax = wxMax(m_LatMax, pPlyTable[i].ltp);
1261 m_LatMin = wxMin(m_LatMin, pPlyTable[i].ltp);
1262 m_LonMax = wxMax(m_LonMax, pPlyTable[i].lnp);
1263 m_LonMin = wxMin(m_LonMin, pPlyTable[i].lnp);
1266 int count = nPlypoint;
1268 Plypoint *pOldPlyTable = pPlyTable;
1270 double lastplylat = 0.0, lastplylon = 0.0, x1 = 0.0, y1 = 0.0, x2, y2;
1271 double plylat, plylon;
1272 for (
int i = 0; i < count + 1; i++) {
1273 plylat = pOldPlyTable[i % count].ltp;
1274 plylon = pOldPlyTable[i % count].lnp;
1275 latlong_to_chartpix(plylat, plylon, x2, y2);
1277 if (lastplylon - plylon > 180.)
1279 else if (lastplylon - plylon < -180.)
1284 ceil((fabs(lastplylat - plylat) + fabs(lastplylon - plylon)) / 2);
1285 for (
double c = 0; c < steps; c++) {
1286 double d = c / steps, lat, lon;
1288 double x = (1 - d) * x1 + d * x2, y = (1 - d) * y1 + d * y2;
1289 chartpix_to_latlong(x, y, &lat, &lon);
1290 pPlyTable = (
Plypoint *)realloc(pPlyTable,
1291 sizeof(
Plypoint) * (nPlypoint + 1));
1292 pPlyTable[nPlypoint].ltp = lat;
1293 pPlyTable[nPlypoint].lnp = lon;
1298 lastplylat = plylat, lastplylon = plylon;
1312 for (
int i = 0; i < nPlypoint; i++) {
1313 m_LonMin = wxMin(m_LonMin, pPlyTable[i].lnp);
1314 m_LonMax = wxMax(m_LonMax, pPlyTable[i].lnp);
1318 bool b_adjusted =
false;
1319 if (m_LonMax * m_LonMin < 0) {
1320 if ((m_LonMax - m_LonMin) > 180.) b_test =
false;
1324 if (!bHaveEmbeddedGeoref) {
1327 AnalyzeRefpoints(
false);
1330 bool bAdjustPly =
false;
1331 wxRect bitRect(0, 0, Size_X, Size_Y);
1333 for (
int i = 0; i < nPlypoint; i++) {
1334 double pix_x, pix_y;
1335 latlong_to_chartpix(pPlyTable[i].ltp, pPlyTable[i].lnp, pix_x, pix_y);
1336 if (!bitRect.Contains(pix_x, pix_y)) {
1339 printf(
"Adjusting COVR region on: %s\n", name.ToUTF8().data());
1345 float *points =
new float[2 * nPlypoint];
1346 for (
int i = 0; i < nPlypoint; i++)
1347 points[2 * i + 0] = pPlyTable[i].ltp,
1348 points[2 * i + 1] = pPlyTable[i].lnp;
1349 LLRegion covrRegion(nPlypoint, points);
1351 covrRegion.Intersect(GetValidRegion());
1353 if (covrRegion.contours.size()) {
1355 m_nCOVREntries = covrRegion.contours.size();
1356 m_pCOVRTablePoints = (
int *)malloc(m_nCOVREntries *
sizeof(
int));
1357 m_pCOVRTable = (
float **)malloc(m_nCOVREntries *
sizeof(
float *));
1358 std::list<poly_contour>::iterator it = covrRegion.contours.begin();
1359 for (
int i = 0; i < m_nCOVREntries; i++) {
1360 m_pCOVRTablePoints[i] = it->size();
1362 (
float *)malloc(m_pCOVRTablePoints[i] * 2 *
sizeof(
float));
1363 std::list<contour_pt>::iterator jt = it->begin();
1364 for (
int j = 0; j < m_pCOVRTablePoints[i]; j++) {
1365 m_pCOVRTable[i][2 * j + 0] = jt->y;
1366 m_pCOVRTable[i][2 * j + 1] = jt->x;
1378 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
1379 *m_pCOVRTablePoints = nPlypoint;
1380 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
1381 *m_pCOVRTable = (
float *)malloc(nPlypoint * 2 *
sizeof(
float));
1382 memcpy(*m_pCOVRTable, pPlyTable, nPlypoint * 2 *
sizeof(
float));
1389 strncpy(d_str, m_datum_str.mb_str(), 99);
1392 int datum_index = GetDatumIndex(d_str);
1393 m_datum_index = datum_index;
1395 if (datum_index < 0)
1396 m_ExtraInfo =
"---<<< Warning: Chart Datum may be incorrect. >>>---";
1399 m_lon_datum_adjust = (-m_dtm_lon) / 3600.;
1400 m_lat_datum_adjust = (-m_dtm_lat) / 3600.;
1404 int cnPlypoint = GetCOVRTablenPoints(0);
1406 for (
int u = 0; u < cnPlypoint; u++) {
1410 if (m_datum_index == DATUM_INDEX_WGS84 ||
1411 m_datum_index == DATUM_INDEX_UNKNOWN) {
1412 dlon = m_dtm_lon / 3600.;
1413 dlat = m_dtm_lat / 3600.;
1417 double to_lat, to_lon;
1418 MolodenskyTransform(ppp->ltp, ppp->lnp, &to_lat, &to_lon, m_datum_index,
1420 dlon = (to_lon - ppp->lnp);
1421 dlat = (to_lat - ppp->ltp);
1422 if (m_b_apply_dtm) {
1423 dlon += m_dtm_lon / 3600.;
1424 dlat += m_dtm_lat / 3600.;
1433 if (!SetMinMax())
return INIT_FAIL_REMOVE;
1437 if (init_flags == HEADER_ONLY)
return INIT_OK;
1441 bool bcorrupt =
false;
1443 if ((c = ifs_hdr->GetC()) != 0x1a) {
1446 if ((c = ifs_hdr->GetC()) == 0x0d) {
1447 if ((c = ifs_hdr->GetC()) != 0x0a) {
1450 if ((c = ifs_hdr->GetC()) != 0x1a) {
1453 if ((c = ifs_hdr->GetC()) != 0x00) {
1458 else if (c != 0x00) {
1463 wxString msg(
" Chart File RLL data corrupt on chart ");
1464 msg.Append(m_FullPath);
1467 return INIT_FAIL_REMOVE;
1471 nColorSize = ifs_hdr->GetC();
1472 if (nColorSize == wxEOF || nColorSize <= 0 || nColorSize > 7) {
1473 wxString msg(
" Invalid nColorSize data, corrupt on chart ");
1474 msg.Append(m_FullPath);
1476 return INIT_FAIL_REMOVE;
1479 nFileOffsetDataStart = ifs_hdr->TellI();
1483 ChartDataInputStream *stream =
1484 new ChartDataInputStream(name);
1487 tempfile = stream->TempFileName();
1489 m_filesize = wxFileName::GetSize(tempfile.empty() ? name : tempfile);
1491 ifss_bitmap = stream;
1492 ifs_bitmap =
new wxBufferedInputStream(*ifss_bitmap);
1495 InitReturn pi_ret = PostInit();
1496 if (pi_ret != INIT_OK)
return pi_ret;
1504ChartBaseBSB::ChartBaseBSB() {
1506 m_ChartFamily = CHART_FAMILY_RASTER;
1508 pBitmapFilePath = NULL;
1513 cached_image_ok = 0;
1518 bHaveEmbeddedGeoref =
false;
1525 bUseLineCache =
false;
1527 bUseLineCache =
true;
1536 m_bilinear_limit = 8;
1542 for (
int i = 0; i < N_BSB_COLORS; i++) pPalettes[i] = NULL;
1544 bGeoErrorSent =
false;
1548 m_mapped_color_index = COLOR_RGB_DEFAULT;
1550 m_datum_str =
"WGS84";
1559 m_proj_parameter = 0.;
1561 m_b_apply_dtm =
true;
1565#ifdef OCPN_USE_CONFIG
1566 wxFileConfig *pfc = (wxFileConfig *)pConfig;
1567 pfc->SetPath(
"/Settings");
1568 pfc->Read(
"DebugBSBImg", &m_b_cdebug, 0);
1572ChartBaseBSB::~ChartBaseBSB() {
1573 if (pBitmapFilePath)
delete pBitmapFilePath;
1575 if (pline_table) free(pline_table);
1577 if (ifs_buf) free(ifs_buf);
1599 FreeLineCacheRows();
1604 for (
int i = 0; i < N_BSB_COLORS; i++)
delete pPalettes[i];
1607void ChartBaseBSB::FreeLineCacheRows(
int start,
int end) {
1612 end = wxMin(end, Size_Y);
1613 for (
int ylc = start; ylc < end; ylc++) {
1616 free(pt->pTileOffset);
1624bool ChartBaseBSB::HaveLineCacheRow(
int row) {
1635double ChartBaseBSB::GetNormalScaleMin(
double canvas_scale_factor,
1636 bool b_allow_overzoom) {
1638 return (canvas_scale_factor / m_ppm_avg) /
1645double ChartBaseBSB::GetNormalScaleMax(
double canvas_scale_factor,
1647 return (canvas_scale_factor / m_ppm_avg) *
1653 target_scale_ppm, .01, 64.);
1658 double scale_factor_min,
1659 double scale_factor_max) {
1660 double chart_1x_scale = GetPPM();
1662 double binary_scale_factor = 1.;
1665 if (chart_1x_scale > target_scale) {
1666 double binary_scale_factor_max = 1 / scale_factor_min;
1668 while (binary_scale_factor < binary_scale_factor_max) {
1669 if (fabs((chart_1x_scale / binary_scale_factor) - target_scale) <
1670 (target_scale * 0.05))
1672 if ((chart_1x_scale / binary_scale_factor) < target_scale)
1675 binary_scale_factor *= 2.;
1682 int isf_max = (int)scale_factor_max;
1683 while (ibsf < isf_max) {
1684 if (fabs((chart_1x_scale * ibsf) - target_scale) < (target_scale * 0.05))
1687 else if ((chart_1x_scale * ibsf) > target_scale) {
1688 if (ibsf > 1) ibsf /= 2;
1694 binary_scale_factor = 1. / ibsf;
1697 return chart_1x_scale / binary_scale_factor;
1700InitReturn ChartBaseBSB::Init(
const wxString &name, ChartInitFlag init_flags) {
1701 m_global_color_scheme = GLOBAL_COLOR_SCHEME_RGB;
1705InitReturn ChartBaseBSB::PreInit(
const wxString &name, ChartInitFlag init_flags,
1707 m_global_color_scheme = cs;
1711void ChartBaseBSB::CreatePaletteEntry(
char *buffer,
int palette_index) {
1712 if (palette_index < N_BSB_COLORS) {
1713 if (!pPalettes[palette_index]) pPalettes[palette_index] =
new opncpnPalette;
1717 (
int *)realloc(pp->FwdPalette, (pp->nFwd + 1) *
sizeof(int));
1719 (
int *)realloc(pp->RevPalette, (pp->nRev + 1) *
sizeof(int));
1725 sscanf(&buffer[4],
"%d,%d,%d,%d", &n, &r, &g, &b);
1730 fcolor = (b << 16) + (g << 8) + r;
1731 rcolor = (r << 16) + (g << 8) + b;
1733 pp->RevPalette[i] = rcolor;
1734 pp->FwdPalette[i] = fcolor;
1738InitReturn ChartBaseBSB::PostInit() {
1740 if (nColorSize == wxEOF || nColorSize <= 0 || nColorSize > 7) {
1741 wxString msg(
" Invalid nColorSize data, corrupt in PostInit() on chart ");
1742 msg.Append(m_FullPath);
1744 return INIT_FAIL_REMOVE;
1747 if (Size_X <= 0 || Size_X > INT_MAX / 4 || Size_Y <= 0 ||
1748 Size_Y - 1 > INT_MAX / 4) {
1750 " Invalid Size_X/Size_Y data, corrupt in PostInit() on chart ");
1751 msg.Append(m_FullPath);
1753 return INIT_FAIL_REMOVE;
1759 if (pPalettes[COLOR_RGB_DEFAULT]) {
1760 nrev_def = pPalettes[COLOR_RGB_DEFAULT]->nRev;
1761 nfwd_def = pPalettes[COLOR_RGB_DEFAULT]->nFwd;
1764 for (
int i = 0; i < N_BSB_COLORS; i++) {
1765 if (pPalettes[i] == NULL) {
1768 pNullSubPal->nFwd = nfwd_def;
1769 pNullSubPal->nRev = nrev_def;
1771 free(pNullSubPal->FwdPalette);
1772 pNullSubPal->FwdPalette = (
int *)malloc(pNullSubPal->nFwd *
sizeof(
int));
1773 if (pPalettes[COLOR_RGB_DEFAULT])
1774 memcpy(pNullSubPal->FwdPalette,
1775 pPalettes[COLOR_RGB_DEFAULT]->FwdPalette,
1776 pNullSubPal->nFwd *
sizeof(
int));
1778 free(pNullSubPal->RevPalette);
1779 pNullSubPal->RevPalette = (
int *)malloc(pNullSubPal->nRev *
sizeof(
int));
1780 if (pPalettes[COLOR_RGB_DEFAULT])
1781 memcpy(pNullSubPal->RevPalette,
1782 pPalettes[COLOR_RGB_DEFAULT]->RevPalette,
1783 pNullSubPal->nRev *
sizeof(
int));
1785 pPalettes[i] = pNullSubPal;
1790 palette_direction = GetPaletteDir();
1792 SetColorScheme(m_global_color_scheme,
false);
1795 ifs_bufsize = Size_X * 4;
1796 ifs_buf = (
unsigned char *)malloc(ifs_bufsize);
1797 if (!ifs_buf)
return INIT_FAIL_REMOVE;
1799 ifs_bufend = ifs_buf + ifs_bufsize;
1800 ifs_lp = ifs_bufend;
1801 ifs_file_offset = -ifs_bufsize;
1805 pline_table = (
int *)malloc((Size_Y + 1) *
sizeof(int));
1806 if (!pline_table)
return INIT_FAIL_REMOVE;
1808 ifs_bitmap->SeekI((Size_Y + 1) * -4,
1810 pline_table[Size_Y] = ifs_bitmap->TellI();
1812 unsigned char *tmp = (
unsigned char *)malloc(Size_Y *
sizeof(
int));
1813 ifs_bitmap->Read(tmp, Size_Y *
sizeof(
int));
1814 if (ifs_bitmap->LastRead() != Size_Y *
sizeof(int)) {
1815 wxString msg(
" Chart File corrupt in PostInit() on chart ");
1816 msg.Append(m_FullPath);
1820 return INIT_FAIL_REMOVE;
1824 unsigned char *b = tmp;
1825 for (
int ifplt = 0; ifplt < Size_Y; ifplt++) {
1827 offset += *b++ * 256 * 256 * 256;
1828 offset += *b++ * 256 * 256;
1829 offset += *b++ * 256;
1832 pline_table[ifplt] = offset;
1837 bool bline_index_ok =
true;
1840 wxULongLong bitmap_filesize = m_filesize;
1841 if ((m_ChartType == CHART_TYPE_GEO) && pBitmapFilePath)
1842 bitmap_filesize = wxFileName::GetSize(*pBitmapFilePath);
1845 for (
int iplt = 0; iplt < Size_Y - 1; iplt++) {
1846 if (pline_table[iplt] > bitmap_filesize) {
1847 wxString msg(
" Chart File corrupt in PostInit() on chart ");
1848 msg.Append(m_FullPath);
1851 return INIT_FAIL_REMOVE;
1854 int thisline_size = pline_table[iplt + 1] - pline_table[iplt];
1855 if (thisline_size < 0) {
1856 wxString msg(
" Chart File corrupt in PostInit() on chart ");
1857 msg.Append(m_FullPath);
1860 return INIT_FAIL_REMOVE;
1869 m_bsb_ver.ToDouble(&ver);
1871 for (
int iplt = 0; iplt < 10; iplt++) {
1872 if (wxInvalidOffset ==
1873 ifs_bitmap->SeekI(pline_table[iplt], wxFromStart)) {
1874 wxString msg(
" Chart File corrupt in PostInit() on chart ");
1875 msg.Append(m_FullPath);
1878 return INIT_FAIL_REMOVE;
1881 int thisline_size = pline_table[iplt + 1] - pline_table[iplt];
1882 ifs_bitmap->Read(ifs_buf, thisline_size);
1884 unsigned char *lp = ifs_buf;
1886 unsigned char byNext;
1887 int nLineMarker = 0;
1890 nLineMarker = nLineMarker * 128 + (byNext & 0x7f);
1891 }
while ((byNext & 0x80) != 0);
1898 if (iplt == 0) m_nLineOffset = nLineMarker;
1900 if (nLineMarker != iplt + m_nLineOffset) {
1901 bline_index_ok =
false;
1908 if (!bline_index_ok) {
1909 wxString msg(
" Line Index corrupt, recreating Index for chart ");
1910 msg.Append(m_FullPath);
1912 if (!CreateLineIndex()) {
1913 wxString msg(
" Error creating Line Index for chart ");
1914 msg.Append(m_FullPath);
1916 return INIT_FAIL_REMOVE;
1921 if (bUseLineCache) {
1925 for (
int ylc = 0; ylc < Size_Y; ylc++) {
1926 pt = &pLineCache[ylc];
1929 pt->pTileOffset = NULL;
1935 wxString test_str = m_DepthUnits.Upper();
1936 if (test_str.IsSameAs(
"FEET", FALSE))
1937 m_depth_unit_id = DEPTH_UNIT_FEET;
1938 else if (test_str.IsSameAs(
"METERS", FALSE))
1939 m_depth_unit_id = DEPTH_UNIT_METERS;
1940 else if (test_str.IsSameAs(
"METRES",
1942 m_depth_unit_id = DEPTH_UNIT_METERS;
1943 else if (test_str.IsSameAs(
"METRIC", FALSE))
1944 m_depth_unit_id = DEPTH_UNIT_METERS;
1945 else if (test_str.IsSameAs(
"FATHOMS", FALSE))
1946 m_depth_unit_id = DEPTH_UNIT_FATHOMS;
1947 else if (test_str.Find(
"FATHOMS") !=
1949 m_depth_unit_id = DEPTH_UNIT_FATHOMS;
1950 else if (test_str.Find(
"METERS") !=
1952 m_depth_unit_id = DEPTH_UNIT_METERS;
1955 int analyze_ret_val = AnalyzeRefpoints();
1956 if (0 != analyze_ret_val)
return INIT_FAIL_REMOVE;
1958 bReadyToRender =
true;
1962bool ChartBaseBSB::CreateLineIndex() {
1968 ifs_bitmap->SeekI(nFileOffsetDataStart);
1970 for (
int iplt = 0; iplt < Size_Y; iplt++) {
1971 int offset = ifs_bitmap->TellI();
1973 int iscan = BSBScanScanline(ifs_bitmap);
1997 pline_table[iplt] = offset;
2004void ChartBaseBSB::InvalidateLineCache() {
2007 for (
int ylc = 0; ylc < Size_Y; ylc++) {
2008 pt = &pLineCache[ylc];
2012 free(pt->pTileOffset);
2013 pt->pTileOffset = NULL;
2020bool ChartBaseBSB::GetChartExtent(
Extent *pext) {
2021 pext->NLAT = m_LatMax;
2022 pext->SLAT = m_LatMin;
2023 pext->ELON = m_LonMax;
2024 pext->WLON = m_LonMin;
2029bool ChartBaseBSB::SetMinMax() {
2038 int cnPlypoint = GetCOVRTablenPoints(0);
2040 for (
int u = 0; u < cnPlypoint; u++) {
2041 if (ppp->lnp > m_LonMax) m_LonMax = ppp->lnp;
2042 if (ppp->lnp < m_LonMin) m_LonMin = ppp->lnp;
2044 if (ppp->ltp > m_LatMax) m_LatMax = ppp->ltp;
2045 if (ppp->ltp < m_LatMin) m_LatMin = ppp->ltp;
2054 if ((m_LonMax * m_LonMin) < 0)
2059 if (0 == nRefpoint)
return false;
2062 double min_dist_x = 360;
2064 for (
int ic = 0; ic < nRefpoint; ic++) {
2066 ((m_LatMax - pRefTable[ic].latr) * (m_LatMax - pRefTable[ic].latr)) +
2067 ((m_LonMax - pRefTable[ic].lonr) * (m_LonMax - pRefTable[ic].lonr)));
2069 if (dist < min_dist_x) {
2076 double min_dist_n = 360;
2078 for (
int id = 0;
id < nRefpoint;
id++) {
2080 ((m_LatMin - pRefTable[
id].latr) * (m_LatMin - pRefTable[
id].latr)) +
2081 ((m_LonMin - pRefTable[
id].lonr) * (m_LonMin - pRefTable[
id].lonr)));
2083 if (dist < min_dist_n) {
2091 if (pRefTable[imaxclose].xr < pRefTable[iminclose].xr) {
2104 int cnPlypoint = GetCOVRTablenPoints(0);
2106 for (
int u = 0; u < cnPlypoint; u++) {
2107 if (ppp->lnp < 0.) ppp->lnp += 360.;
2109 if (ppp->lnp > m_LonMax) m_LonMax = ppp->lnp;
2110 if (ppp->lnp < m_LonMin) m_LonMin = ppp->lnp;
2112 if (ppp->ltp > m_LatMax) m_LatMax = ppp->ltp;
2113 if (ppp->ltp < m_LatMin) m_LatMin = ppp->ltp;
2124 if ((m_LonMax < -180.) && (m_LonMin < -180.)) {
2129 int cnPlypoint = GetCOVRTablenPoints(0);
2131 for (
int u = 0; u < cnPlypoint; u++) {
2140void ChartBaseBSB::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
2145 case GLOBAL_COLOR_SCHEME_RGB:
2146 m_mapped_color_index = COLOR_RGB_DEFAULT;
2148 case GLOBAL_COLOR_SCHEME_DAY:
2149 m_mapped_color_index = DAY;
2151 case GLOBAL_COLOR_SCHEME_DUSK:
2152 m_mapped_color_index = DUSK;
2154 case GLOBAL_COLOR_SCHEME_NIGHT:
2155 m_mapped_color_index = NIGHT;
2158 m_mapped_color_index = DAY;
2162 pPalette = GetPalettePtr(m_mapped_color_index);
2164 m_global_color_scheme = cs;
2167 if (bApplyImmediate) {
2168 m_cached_scale_ppm = 1.0;
2172 if (pThumbData) pThumbData->pDIBThumb = NULL;
2175wxBitmap *ChartBaseBSB::CreateThumbnail(
int tnx,
int tny, ColorScheme cs) {
2178 int divx = wxMax(1, Size_X / (4 * tnx));
2179 int divy = wxMax(1, Size_Y / (4 * tny));
2181 int div_factor = std::min(divx, divy);
2183 int des_width = Size_X / div_factor;
2184 int des_height = Size_Y / div_factor;
2190 gts.height = Size_Y;
2194 unsigned char *pLineT = (
unsigned char *)malloc((Size_X + 1) * BPP / 8);
2197 unsigned char *pPixTN =
2198 (
unsigned char *)malloc(des_width * des_height * this_bpp / 8);
2209 ColorScheme cs_tmp = m_global_color_scheme;
2210 SetColorScheme(cs,
false);
2212 while (iyd < des_height) {
2213 if (0 == BSBGetScanline(pLineT, iy, 0, Size_X, 1))
2220 yoffd = iyd * des_width * this_bpp / 8;
2224 while (ixd < des_width) {
2225 pxs = pLineT + (ix * BPP / 8);
2226 pxd = pPixTN + (yoffd + (ixd * this_bpp / 8));
2242 SetColorScheme(cs_tmp,
false);
2246#ifdef ocpnUSE_ocpnBitmap
2247 wxBitmap *bmx2 =
new ocpnBitmap(pPixTN, des_width, des_height, -1);
2248 wxImage imgx2 = bmx2->ConvertToImage();
2249 imgx2.Rescale(des_width / 4, des_height / 4, wxIMAGE_QUALITY_HIGH);
2250 retBMP =
new wxBitmap(imgx2);
2253 wxImage thumb_image(des_width, des_height, pPixTN,
true);
2254 thumb_image.Rescale(des_width / 4, des_height / 4, wxIMAGE_QUALITY_HIGH);
2255 retBMP =
new wxBitmap(thumb_image);
2268ThumbData *ChartBaseBSB::GetThumbData(
int tnx,
int tny,
float lat,
float lon) {
2270 if (!pThumbData->pDIBThumb)
2271 pThumbData->pDIBThumb = CreateThumbnail(tnx, tny, m_global_color_scheme);
2273 pThumbData->Thumb_Size_X = tnx;
2274 pThumbData->Thumb_Size_Y = tny;
2277 int divx = Size_X / tnx;
2278 int divy = Size_Y / tny;
2280 int div_factor = std::min(divx, divy);
2293 latlong_to_pix_vp(lat, lon, pixx, pixy, tvp);
2296 pThumbData->ShipX = pixx;
2297 pThumbData->ShipY = pixy;
2302bool ChartBaseBSB::UpdateThumbData(
double lat,
double lon) {
2306 int divx = Size_X / pThumbData->Thumb_Size_X;
2307 int divy = Size_Y / pThumbData->Thumb_Size_Y;
2309 int div_factor = std::min(divx, divy);
2311 double pixx_test, pixy_test;
2316 tvp.
pix_width = pThumbData->Thumb_Size_X;
2322 latlong_to_pix_vp(lat, lon, pixx_test, pixy_test, tvp);
2325 if ((pixx_test != pThumbData->ShipX) || (pixy_test != pThumbData->ShipY)) {
2326 pThumbData->ShipX = pixx_test;
2327 pThumbData->ShipY = pixy_test;
2336static double polytrans(
double *coeff,
double lon,
double lat);
2338int ChartBaseBSB::vp_pix_to_latlong(
ViewPort &vp,
double pixx,
double pixy,
2339 double *plat,
double *plon) {
2340 if (bHaveEmbeddedGeoref) {
2343 double px = pixx * raster_scale + Rsrc.x;
2344 double py = pixy * raster_scale + Rsrc.y;
2348 double lon = polytrans(pwx, px, py);
2349 lon = (lon < 0) ? lon + m_cph : lon - m_cph;
2350 *plon = lon - m_lon_datum_adjust;
2351 *plat = polytrans(pwy, px, py) - m_lat_datum_adjust;
2359 if (m_projection == PROJECTION_TRANSVERSE_MERCATOR) {
2365 double easting, northing;
2366 toTM(vp.
clat + m_lat_datum_adjust, vp.
clon + m_lon_datum_adjust,
2367 m_proj_lat, m_proj_lon, &easting, &northing);
2368 double xc = polytrans(cPoints.
wpx, easting, northing);
2369 double yc = polytrans(cPoints.
wpy, easting, northing);
2372 double px = xc + (pixx - (vp.
pix_width / 2)) * raster_scale;
2373 double py = yc + (pixy - (vp.
pix_height / 2)) * raster_scale;
2376 double east = polytrans(cPoints.
pwx, px, py);
2377 double north = polytrans(cPoints.
pwy, px, py);
2381 fromTM(east, north, m_proj_lat, m_proj_lon, &lat, &lon);
2385 double slon_p = lon - m_lon_datum_adjust;
2386 double slat_p = lat - m_lat_datum_adjust;
2393 }
else if (m_projection == PROJECTION_MERCATOR) {
2399 double easting, northing;
2400 toSM_ECC(vp.
clat + m_lat_datum_adjust, vp.
clon + m_lon_datum_adjust,
2401 m_proj_lat, m_proj_lon, &easting, &northing);
2402 double xc = polytrans(cPoints.
wpx, easting, northing);
2403 double yc = polytrans(cPoints.
wpy, easting, northing);
2406 double px = xc + (pixx - (vp.
pix_width / 2)) * raster_scale;
2407 double py = yc + (pixy - (vp.
pix_height / 2)) * raster_scale;
2410 double east = polytrans(cPoints.
pwx, px, py);
2411 double north = polytrans(cPoints.
pwy, px, py);
2415 fromSM_ECC(east, north, m_proj_lat, m_proj_lon, &lat, &lon);
2418 double slon_p = lon - m_lon_datum_adjust;
2419 double slat_p = lat - m_lat_datum_adjust;
2427 }
else if (m_projection == PROJECTION_POLYCONIC) {
2433 double easting, northing;
2434 toPOLY(vp.
clat + m_lat_datum_adjust, vp.
clon + m_lon_datum_adjust,
2435 m_proj_lat, m_proj_lon, &easting, &northing);
2436 double xc = polytrans(cPoints.
wpx, easting, northing);
2437 double yc = polytrans(cPoints.
wpy, easting, northing);
2440 double px = xc + (pixx - (vp.
pix_width / 2)) * raster_scale;
2441 double py = yc + (pixy - (vp.
pix_height / 2)) * raster_scale;
2444 double east = polytrans(cPoints.
pwx, px, py);
2445 double north = polytrans(cPoints.
pwy, px, py);
2449 fromPOLY(east, north, m_proj_lat, m_proj_lon, &lat, &lon);
2452 double slon_p = lon - m_lon_datum_adjust;
2453 double slat_p = lat - m_lat_datum_adjust;
2463 xp = (dx * cos(vp.
skew)) - (dy * sin(vp.
skew));
2464 yp = (dy * cos(vp.
skew)) + (dx * sin(vp.
skew));
2469 fromSM_ECC(d_east, d_north, vp.
clat, vp.
clon, &slat, &slon);
2476 else if (slon > 180.)
2484int ChartBaseBSB::latlong_to_pix_vp(
double lat,
double lon,
double &pixx,
2488 if (bHaveEmbeddedGeoref) {
2491 alon = lon + m_lon_datum_adjust;
2492 alat = lat + m_lat_datum_adjust;
2494 AdjustLongitude(alon);
2498 double lonp = (alon < 0) ? alon + m_cph : alon - m_cph;
2499 double xd = polytrans(wpx, lonp, alat);
2500 double yd = polytrans(wpy, lonp, alat);
2504 pixx = (xd - Rsrc.x) / raster_scale;
2505 pixy = (yd - Rsrc.y) / raster_scale;
2510 double easting, northing;
2532 if (m_projection == PROJECTION_TRANSVERSE_MERCATOR) {
2535 alon = lon + m_lon_datum_adjust;
2536 alat = lat + m_lat_datum_adjust;
2539 toTM(alat, alon, m_proj_lat, m_proj_lon, &easting, &northing);
2542 double xd = polytrans(cPoints.
wpx, easting, northing);
2543 double yd = polytrans(cPoints.
wpy, easting, northing);
2546 toTM(vp.
clat + m_lat_datum_adjust, vp.
clon + m_lon_datum_adjust,
2547 m_proj_lat, m_proj_lon, &easting, &northing);
2548 double xc = polytrans(cPoints.
wpx, easting, northing);
2549 double yc = polytrans(cPoints.
wpy, easting, northing);
2554 double xs = xc - vp.
pix_width * raster_scale / 2;
2555 double ys = yc - vp.
pix_height * raster_scale / 2;
2557 pixx = (xd - xs) / raster_scale;
2558 pixy = (yd - ys) / raster_scale;
2560 }
else if (m_projection == PROJECTION_MERCATOR) {
2563 alon = lon + m_lon_datum_adjust;
2564 alat = lat + m_lat_datum_adjust;
2568 AdjustLongitude(xlon);
2569 toSM_ECC(alat, xlon, m_proj_lat, m_proj_lon, &easting, &northing);
2572 double xd = polytrans(cPoints.
wpx, easting, northing);
2573 double yd = polytrans(cPoints.
wpy, easting, northing);
2576 double xlonc = vp.
clon;
2577 AdjustLongitude(xlonc);
2579 toSM_ECC(vp.
clat + m_lat_datum_adjust, xlonc + m_lon_datum_adjust,
2580 m_proj_lat, m_proj_lon, &easting, &northing);
2581 double xc = polytrans(cPoints.
wpx, easting, northing);
2582 double yc = polytrans(cPoints.
wpy, easting, northing);
2587 double xs = xc - vp.
pix_width * raster_scale / 2;
2588 double ys = yc - vp.
pix_height * raster_scale / 2;
2590 pixx = (xd - xs) / raster_scale;
2591 pixy = (yd - ys) / raster_scale;
2593 }
else if (m_projection == PROJECTION_POLYCONIC) {
2596 alon = lon + m_lon_datum_adjust;
2597 alat = lat + m_lat_datum_adjust;
2600 xlon = AdjustLongitude(alon);
2601 toPOLY(alat, xlon, m_proj_lat, m_proj_lon, &easting, &northing);
2604 double xd = polytrans(cPoints.
wpx, easting, northing);
2605 double yd = polytrans(cPoints.
wpy, easting, northing);
2608 double xlonc = AdjustLongitude(vp.
clon);
2610 toPOLY(vp.
clat + m_lat_datum_adjust, xlonc + m_lon_datum_adjust,
2611 m_proj_lat, m_proj_lon, &easting, &northing);
2612 double xc = polytrans(cPoints.
wpx, easting, northing);
2613 double yc = polytrans(cPoints.
wpy, easting, northing);
2618 double xs = xc - vp.
pix_width * raster_scale / 2;
2619 double ys = yc - vp.
pix_height * raster_scale / 2;
2621 pixx = (xd - xs) / raster_scale;
2622 pixy = (yd - ys) / raster_scale;
2625 toSM_ECC(lat, xlon, vp.
clat, vp.
clon, &easting, &northing);
2630 double dx = epix * cos(vp.
skew) + npix * sin(vp.
skew);
2631 double dy = npix * cos(vp.
skew) - epix * sin(vp.
skew);
2642void ChartBaseBSB::latlong_to_chartpix(
double lat,
double lon,
double &pixx,
2648 if (bHaveEmbeddedGeoref) {
2651 alon = lon + m_lon_datum_adjust;
2652 alat = lat + m_lat_datum_adjust;
2654 alon = AdjustLongitude(alon);
2657 double lonp = (alon < 0) ? alon + m_cph : alon - m_cph;
2658 pixx = polytrans(wpx, lonp, alat);
2659 pixy = polytrans(wpy, lonp, alat);
2661 double easting, northing;
2664 if (m_projection == PROJECTION_TRANSVERSE_MERCATOR) {
2667 alon = lon + m_lon_datum_adjust;
2668 alat = lat + m_lat_datum_adjust;
2671 toTM(alat, alon, m_proj_lat, m_proj_lon, &easting, &northing);
2674 pixx = polytrans(cPoints.
wpx, easting, northing);
2675 pixy = polytrans(cPoints.
wpy, easting, northing);
2677 }
else if (m_projection == PROJECTION_MERCATOR) {
2680 alon = lon + m_lon_datum_adjust;
2681 alat = lat + m_lat_datum_adjust;
2684 xlon = AdjustLongitude(alon);
2686 toSM_ECC(alat, xlon, m_proj_lat, m_proj_lon, &easting, &northing);
2689 pixx = polytrans(cPoints.
wpx, easting, northing);
2690 pixy = polytrans(cPoints.
wpy, easting, northing);
2692 }
else if (m_projection == PROJECTION_POLYCONIC) {
2695 alon = lon + m_lon_datum_adjust;
2696 alat = lat + m_lat_datum_adjust;
2699 xlon = AdjustLongitude(alon);
2700 toPOLY(alat, xlon, m_proj_lat, m_proj_lon, &easting, &northing);
2703 pixx = polytrans(cPoints.
wpx, easting, northing);
2704 pixy = polytrans(cPoints.
wpy, easting, northing);
2709void ChartBaseBSB::chartpix_to_latlong(
double pixx,
double pixy,
double *plat,
2711 if (bHaveEmbeddedGeoref) {
2712 double lon = polytrans(pwx, pixx, pixy);
2713 lon = (lon < 0) ? lon + m_cph : lon - m_cph;
2714 *plon = lon - m_lon_datum_adjust;
2715 *plat = polytrans(pwy, pixx, pixy) - m_lat_datum_adjust;
2718 if (m_projection == PROJECTION_TRANSVERSE_MERCATOR) {
2722 double east = polytrans(cPoints.
pwx, pixx, pixy);
2723 double north = polytrans(cPoints.
pwy, pixx, pixy);
2727 fromTM(east, north, m_proj_lat, m_proj_lon, &lat, &lon);
2731 slon = lon - m_lon_datum_adjust;
2732 slat = lat - m_lat_datum_adjust;
2734 }
else if (m_projection == PROJECTION_MERCATOR) {
2737 double east = polytrans(cPoints.
pwx, pixx, pixy);
2738 double north = polytrans(cPoints.
pwy, pixx, pixy);
2742 fromSM_ECC(east, north, m_proj_lat, m_proj_lon, &lat, &lon);
2745 slon = lon - m_lon_datum_adjust;
2746 slat = lat - m_lat_datum_adjust;
2747 }
else if (m_projection == PROJECTION_POLYCONIC) {
2750 double east = polytrans(cPoints.
pwx, pixx, pixy);
2751 double north = polytrans(cPoints.
pwy, pixx, pixy);
2755 fromPOLY(east, north, m_proj_lat, m_proj_lon, &lat, &lon);
2758 slon = lon - m_lon_datum_adjust;
2759 slat = lat - m_lat_datum_adjust;
2770 else if (slon > 180.)
2776void ChartBaseBSB::ComputeSourceRectangle(
const ViewPort &vp,
2777 wxRect *pSourceRect) {
2778 m_raster_scale_factor = GetRasterScaleFactor(vp);
2780 latlong_to_chartpix(vp.
clat, vp.
clon, xd, yd);
2782 wxRealPoint pos, size;
2784 pos.x = xd - (vp.
pix_width * m_raster_scale_factor / 2);
2785 pos.y = yd - (vp.
pix_height * m_raster_scale_factor / 2);
2787 size.x = vp.
pix_width * m_raster_scale_factor;
2788 size.y = vp.
pix_height * m_raster_scale_factor;
2791 wxRect(wxRound(pos.x), wxRound(pos.y), wxRound(size.x), wxRound(size.y));
2794double ChartBaseBSB::GetRasterScaleFactor(
const ViewPort &vp) {
2797 return (wxRound(100000 * GetPPM() / vp.
view_scale_ppm)) / 100000.;
2800void ChartBaseBSB::SetVPRasterParms(
const ViewPort &vpt) {
2804 if (m_datum_index == DATUM_INDEX_WGS84 ||
2805 m_datum_index == DATUM_INDEX_UNKNOWN) {
2806 m_lon_datum_adjust = (-m_dtm_lon) / 3600.;
2807 m_lat_datum_adjust = (-m_dtm_lat) / 3600.;
2811 double to_lat, to_lon;
2812 MolodenskyTransform(vpt.
clat, vpt.
clon, &to_lat, &to_lon, m_datum_index,
2814 m_lon_datum_adjust = -(to_lon - vpt.
clon);
2815 m_lat_datum_adjust = -(to_lat - vpt.
clat);
2816 if (m_b_apply_dtm) {
2817 m_lon_datum_adjust -= m_dtm_lon / 3600.;
2818 m_lat_datum_adjust -= m_dtm_lat / 3600.;
2822 ComputeSourceRectangle(vpt, &Rsrc);
2824 if (vpt.IsValid()) m_vp_render_last = vpt;
2828 bool bInside = G_FloatPtInPolygon((
MyFlPoint *)GetCOVRTableHead(0),
2829 GetCOVRTablenPoints(0), vp_proposed.
clon,
2831 if (!bInside)
return false;
2834 double binary_scale_factor = GetPPM() / vp_proposed.
view_scale_ppm;
2836 if (vp_last.IsValid()) {
2842 if (cached_image_ok && (binary_scale_factor > 1.0) &&
2843 (fabs(binary_scale_factor - wxRound(binary_scale_factor)) < 1e-5)) {
2845 printf(
" Possible Adjust VP for integer scale: %g\n",
2846 binary_scale_factor);
2849 ComputeSourceRectangle(vp_proposed, &rprop);
2852 double lon_adj, lat_adj;
2853 latlong_to_pix_vp(vp_proposed.
clat, vp_proposed.
clon, pixx, pixy,
2855 vp_pix_to_latlong(vp_proposed, pixx, pixy, &lat_adj, &lon_adj);
2857 vp_proposed.
clat = lat_adj;
2858 vp_proposed.
clon = lon_adj;
2863 return (ret_val > 0);
2866bool ChartBaseBSB::IsRenderCacheable(wxRect &source, wxRect &dest) {
2867 double scale_x = (double)source.width / (
double)dest.width;
2876 if ((fabs(scale_x - wxRound(scale_x))) > .0001) {
2883 if ((
int)(source.width / dest.width) != (
int)wxRound(scale_x)) {
2892void ChartBaseBSB::GetValidCanvasRegion(
const ViewPort &VPoint,
2894 SetVPRasterParms(VPoint);
2901 rxl = wxMax(-Rsrc.x * raster_scale, VPoint.rv_rect.x);
2902 rxr = wxMin((Size_X - Rsrc.x) * raster_scale,
2903 VPoint.rv_rect.width + VPoint.rv_rect.x);
2905 ryt = wxMax(-Rsrc.y * raster_scale, VPoint.rv_rect.y);
2906 ryb = wxMin((Size_Y - Rsrc.y) * raster_scale,
2907 VPoint.rv_rect.height + VPoint.rv_rect.y);
2909 pValidRegion->Clear();
2910 pValidRegion->Union(rxl, ryt, rxr - rxl, ryb - ryt);
2913LLRegion ChartBaseBSB::GetValidRegion() {
2916 chartpix_to_latlong(0, 0, ll + 0, ll + 1);
2917 chartpix_to_latlong(0, Size_Y, ll + 2, ll + 3);
2918 chartpix_to_latlong(Size_X, Size_Y, ll + 4, ll + 5);
2919 chartpix_to_latlong(Size_X, 0, ll + 6, ll + 7);
2923 for (
int i = 1; i < 6; i += 2)
2924 if (fabs(ll[i] - ll[i + 2]) > 180) {
2926 for (
int i = 1; i < 8; i += 2)
2927 if (ll[i] < 0) ll[i] += 360;
2931 return LLRegion(4, ll);
2934bool ChartBaseBSB::GetViewUsingCache(wxRect &source, wxRect &dest,
2936 ScaleTypeEnum scale_type) {
2938 ScaleTypeEnum scale_type_corrected;
2940 if (m_b_cdebug) printf(
" source: %d %d\n", source.x, source.y);
2941 if (m_b_cdebug) printf(
" cache: %d %d\n", cache_rect.x, cache_rect.y);
2944 if ((source == cache_rect) &&
2945 (cached_image_ok)) {
2946 if (m_b_cdebug) printf(
" GVUC: Cache is good, nothing to do\n");
2950 double scale_x = (double)source.width / (
double)dest.width;
2952 if (m_b_cdebug) printf(
"GVUC: scale_x: %g\n", scale_x);
2955 scale_type_corrected = scale_type;
2956 if (scale_x > m_bilinear_limit) scale_type_corrected = RENDER_LODEF;
2964 if ((fabs(scale_x - wxRound(scale_x))) > .0001) {
2965 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: Not digital scale test 1\n");
2966 return GetView(source, dest, scale_type_corrected);
2971 if (!cached_image_ok) {
2972 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: Cache NOk\n");
2973 return GetView(source, dest, scale_type_corrected);
2978 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: Overzoom\n");
2979 return GetView(source, dest, scale_type_corrected);
2983 if ((
int)(source.width / dest.width) != (
int)wxRound(scale_x)) {
2984 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: Not digital scale test 2\n");
2985 return GetView(source, dest, scale_type_corrected);
2989 int cs1d = source.width / dest.width;
2990 if (abs(source.x - cache_rect.x) % cs1d) {
2992 printf(
" source.x: %d cache_rect.x: %d cs1d: %d\n", source.x,
2993 cache_rect.x, cs1d);
2994 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: x mismatch\n");
2995 return GetView(source, dest, scale_type_corrected);
2997 if (abs(source.y - cache_rect.y) % cs1d) {
2998 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: y mismatch\n");
2999 return GetView(source, dest, scale_type_corrected);
3002 if (pPixCache && ((pPixCache->GetWidth() != dest.width) ||
3003 (pPixCache->GetHeight() != dest.height))) {
3004 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: dest size mismatch\n");
3005 return GetView(source, dest, scale_type_corrected);
3009 (source.y + source.height) - (cache_rect.y + cache_rect.height);
3010 int scaled_stride_rows = (int)(stride_rows / scale_x);
3012 if (abs(stride_rows) >= source.height)
3013 return GetView(source, dest, scale_type_corrected);
3016 (source.x + source.width) - (cache_rect.x + cache_rect.width);
3017 int scaled_stride_pixels = (int)(stride_pixels / scale_x);
3019 if (abs(stride_pixels) >= source.width)
3020 return GetView(source, dest, scale_type_corrected);
3022 if (m_b_cdebug) printf(
" GVUC Using raster data cache\n");
3024 ScaleTypeEnum pan_scale_type_x = scale_type_corrected;
3025 ScaleTypeEnum pan_scale_type_y = scale_type_corrected;
3029 int height = pPixCache->GetHeight();
3030 int width = pPixCache->GetWidth();
3031 int buffer_stride_bytes = pPixCache->GetLinePitch();
3036 if (stride_rows > 0)
3038 ps = pPixCache->GetpData() +
3039 (abs(scaled_stride_rows) * buffer_stride_bytes);
3040 if (stride_pixels > 0) ps += scaled_stride_pixels * BPP / 8;
3042 pd = pPixCache->GetpData();
3043 if (stride_pixels <= 0) pd += abs(scaled_stride_pixels) * BPP / 8;
3045 for (
int iy = 0; iy < (height - abs(scaled_stride_rows)); iy++) {
3046 memmove(pd, ps, (width - abs(scaled_stride_pixels)) * BPP / 8);
3047 ps += buffer_stride_bytes;
3048 pd += buffer_stride_bytes;
3052 ps = pPixCache->GetpData() +
3053 ((height - abs(scaled_stride_rows) - 1) * buffer_stride_bytes);
3054 if (stride_pixels > 0)
3055 ps += scaled_stride_pixels * BPP / 8;
3057 pd = pPixCache->GetpData() + ((height - 1) * buffer_stride_bytes);
3058 if (stride_pixels <= 0)
3059 pd += abs(scaled_stride_pixels) * BPP / 8;
3061 for (
int iy = 0; iy < (height - abs(scaled_stride_rows)); iy++) {
3062 memmove(pd, ps, (width - abs(scaled_stride_pixels)) * BPP / 8);
3063 ps -= buffer_stride_bytes;
3064 pd -= buffer_stride_bytes;
3069 if (source.y != cache_rect.y) {
3070 wxRect sub_dest = dest;
3071 sub_dest.height = abs(scaled_stride_rows);
3073 if (stride_rows > 0)
3075 sub_dest.y = height - scaled_stride_rows;
3086 wxRegionContain rc = Region.Contains(sub_dest);
3087 if ((wxPartRegion == rc) || (wxInRegion == rc)) {
3088 GetAndScaleData(pPixCache->GetpData(), pPixCache->GetLength(), source,
3089 source.width, sub_dest, width, cs1d, pan_scale_type_y);
3091 pPixCache->Update();
3095 cache_rect.y = source.y;
3097 cache_rect_scaled = dest;
3098 cached_image_ok = 1;
3103 if (source.x != cache_rect.x) {
3104 wxRect sub_dest = dest;
3105 sub_dest.width = abs(scaled_stride_pixels);
3107 if (stride_pixels > 0)
3109 sub_dest.x = width - scaled_stride_pixels;
3120 wxRegionContain rc = Region.Contains(sub_dest);
3121 if ((wxPartRegion == rc) || (wxInRegion == rc)) {
3122 GetAndScaleData(pPixCache->GetpData(), pPixCache->GetLength(), source,
3123 source.width, sub_dest, width, cs1d, pan_scale_type_x);
3126 pPixCache->Update();
3129 cache_rect = source;
3130 cache_rect_scaled = dest;
3131 cached_image_ok = 1;
3142bool ChartBaseBSB::RenderViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint) {
3143 SetVPRasterParms(VPoint);
3147 bool bsame_region = (rgn == m_last_region);
3149 if (!bsame_region) cached_image_ok =
false;
3151 m_last_region = rgn;
3153 return RenderRegionViewOnDC(dc, VPoint, rgn);
3156bool ChartBaseBSB::RenderRegionViewOnGL(
const wxGLContext &glc,
3159 const LLRegion &Region) {
3163bool ChartBaseBSB::RenderRegionViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint,
3165 SetVPRasterParms(VPoint);
3169 double factor = GetRasterScaleFactor(VPoint);
3171 printf(
"%d RenderRegion ScaleType: %d factor: %g\n", s_dc++,
3172 RENDER_HIDEF, factor);
3173 printf(
"Rect list:\n");
3175 while (upd.HaveRects()) {
3176 wxRect rect = upd.GetRect();
3177 printf(
" %d %d %d %d\n", rect.x, rect.y, rect.width, rect.height);
3185 (m_last_vprect != dest)) {
3186 cached_image_ok =
false;
3187 m_vp_render_last.Invalidate();
3204 m_last_vprect = dest;
3206 if (cached_image_ok) {
3208 bool bsame_region = (Region == m_last_region);
3210 if ((bsame_region) && (Rsrc == cache_rect)) {
3211 pPixCache->SelectIntoDC(dc);
3212 if (m_b_cdebug) printf(
" Using Current PixelCache\n");
3217 m_last_region = Region;
3238 while (upd.HaveRects()) {
3243 if ((!IsRenderCacheable(Rsrc, dest) && (n_rect > 4) && (n_rect < 20)) ||
3246 printf(
" RenderRegion by rect iterator n_rect: %d\n", n_rect);
3250 wxRect dest_check_rect = dest;
3252 while (upd_check.HaveRects()) {
3253 wxRect rect = upd_check.GetRect();
3254 dest_check_rect.Union(rect);
3255 upd_check.NextRect();
3259 if ((pPixCache->GetWidth() != dest_check_rect.width) ||
3260 (pPixCache->GetHeight() != dest_check_rect.height)) {
3263 new PixelCache(dest_check_rect.width, dest_check_rect.height, BPP);
3267 new PixelCache(dest_check_rect.width, dest_check_rect.height, BPP);
3269 ScaleTypeEnum ren_type = RENDER_LODEF;
3275 while (upd.HaveRects()) {
3276 wxRect rect = upd.GetRect();
3281 if (rect.y < 0) rect.Offset(0, -rect.y);
3282 if (rect.x < 0) rect.Offset(-rect.x, 0);
3284 GetAndScaleData(pPixCache->GetpData(), pPixCache->GetLength(), Rsrc,
3285 Rsrc.width, rect, pPixCache->GetWidth(), factor,
3293 pPixCache->Update();
3297 cache_scale_method = ren_type;
3298 cached_image_ok =
false;
3301 pPixCache->SelectIntoDC(dc);
3309 if ((pPixCache->GetWidth() != dest.width) ||
3310 (pPixCache->GetHeight() != dest.height)) {
3312 pPixCache =
new PixelCache(dest.width, dest.height, BPP);
3315 pPixCache =
new PixelCache(dest.width, dest.height, BPP);
3317 if (m_b_cdebug) printf(
" Render Region By GVUC\n");
3320 ScaleTypeEnum scale_type_zoom = RENDER_HIDEF;
3322 if (binary_scale_factor < .20) scale_type_zoom = RENDER_LODEF;
3324 bool bnewview = GetViewUsingCache(Rsrc, dest, Region, scale_type_zoom);
3327 pPixCache->SelectIntoDC(dc);
3332wxImage *ChartBaseBSB::GetImage() {
3333 int img_size_x = ((Size_X >> 2) * 4) + 4;
3334 wxImage *img =
new wxImage(img_size_x, Size_Y,
false);
3336 unsigned char *ppnx = img->GetData();
3338 for (
int i = 0; i < Size_Y; i++) {
3339 wxRect source_rect(0, i, Size_X, 1);
3340 wxRect dest_rect(0, 0, Size_X, 1);
3342 GetAndScaleData(img->GetData(), img_size_x * Size_Y * 3, source_rect,
3343 Size_X, dest_rect, Size_X, 1.0, RENDER_HIDEF);
3345 ppnx += img_size_x * 3;
3351bool ChartBaseBSB::GetView(wxRect &source, wxRect &dest,
3352 ScaleTypeEnum scale_type) {
3353 assert(pPixCache != 0);
3359 double factor = ((double)source.width) / ((double)dest.width);
3374 GetAndScaleData(pPixCache->GetpData(), pPixCache->GetLength(), source,
3375 source.width, dest, dest.width, factor, scale_type);
3376 pPixCache->Update();
3380 cache_rect = source;
3381 cache_rect_scaled = dest;
3382 cache_scale_method = scale_type;
3384 cached_image_ok = 1;
3389bool ChartBaseBSB::GetAndScaleData(
unsigned char *ppn,
size_t data_size,
3390 wxRect &source,
int source_stride,
3391 wxRect &dest,
int dest_stride,
3392 double scale_factor,
3393 ScaleTypeEnum scale_type) {
3394 unsigned char *s_data = NULL;
3396 double factor = scale_factor;
3397 int Factor = (int)factor;
3399 int target_width = (int)wxRound((
double)source.width / factor);
3400 int target_height = (int)wxRound((
double)source.height / factor);
3402 int dest_line_length = dest_stride * BPP / 8;
3406#ifdef __PIX_CACHE_DIBSECTION__
3407 dest_line_length = (((dest_stride * 24) + 31) & ~31) >> 3;
3410 if ((target_height == 0) || (target_width == 0))
return false;
3414 unsigned char *
volatile target_data = ppn;
3415 unsigned char *data = ppn;
3419 if (scale_type == RENDER_HIDEF) {
3421 int blur_factor = wxMax(2, Factor);
3422 int wb_size = (source.width) * (blur_factor * 2) * BPP / 8;
3423 s_data = (
unsigned char *)malloc(wb_size);
3424 unsigned char *pixel;
3427 for (
int y = dest.y; y < (dest.y + dest.height); y++) {
3432 s1.y = source.y + (int)(y * factor);
3433 s1.width = source.width;
3434 s1.height = blur_factor;
3435 GetChartBits(s1, s_data, 1);
3437 target_data = data + (y * dest_line_length );
3439 for (
int x = 0; x < target_width; x++) {
3440 unsigned int avgRed = 0;
3441 unsigned int avgGreen = 0;
3442 unsigned int avgBlue = 0;
3443 unsigned int pixel_count = 0;
3444 unsigned char *pix0 = s_data + BPP / 8 * ((int)(x * factor));
3447 if ((x * Factor) < (Size_X - source.x)) {
3449 for (
int y1 = 0; y1 < blur_factor; ++y1) {
3450 pixel = pix0 + (BPP / 8 * y_offset);
3451 for (
int x1 = 0; x1 < blur_factor; ++x1) {
3453 avgGreen += pixel[1];
3454 avgBlue += pixel[2];
3460 y_offset += source.width;
3463 if (0 == pixel_count)
3466 target_data[0] = avgRed / pixel_count;
3467 target_data[1] = avgGreen / pixel_count;
3468 target_data[2] = avgBlue / pixel_count;
3469 target_data += BPP / 8;
3474 target_data += BPP / 8;
3483 else if (scale_type == RENDER_LODEF) {
3484 int get_bits_submap = 1;
3488 if (source.width > 32767)
3491 int wb_size = (Size_X) * (( 1) * 2) * BPP / 8;
3492 s_data = (
unsigned char *)malloc(wb_size);
3494 long x_delta = (source.width << scaler) / target_width;
3495 long y_delta = (source.height << scaler) / target_height;
3498 long ys = dest.y * y_delta;
3500 while (y < dest.y + dest.height) {
3505 s1.y = source.y + (ys >> scaler);
3508 GetChartBits(s1, s_data, get_bits_submap);
3510 target_data = data + (y * dest_line_length ) +
3513 long x = (source.x << scaler) + (dest.x * x_delta);
3514 long sizex16 = Size_X << scaler;
3517 while ((xt < dest.x + dest.width) && (x < 0)) {
3522 target_data += BPP / 8;
3527 while ((xt < dest.x + dest.width) && (x < sizex16)) {
3528 unsigned char *src_pixel = &s_data[(x >> scaler) * BPP / 8];
3530 target_data[0] = src_pixel[0];
3531 target_data[1] = src_pixel[1];
3532 target_data[2] = src_pixel[2];
3534 target_data += BPP / 8;
3539 while (xt < dest.x + dest.width) {
3544 target_data += BPP / 8;
3558 unsigned char *target_line_start = NULL;
3559 unsigned char *target_data_x = NULL;
3563 sigaction(SIGSEGV, NULL,
3566 struct sigaction temp;
3567 sigaction(SIGSEGV, NULL, &temp);
3569 temp.sa_handler = catch_signals_chart;
3570 sigemptyset(&temp.sa_mask);
3575 sigaction(SIGSEGV, &temp, NULL);
3577 if (sigsetjmp(env_chart,
3580 sigaction(SIGSEGV, &sa_all_previous, NULL);
3583 msg.Printf(
" Caught SIGSEGV on GetandScaleData, Factor < 1");
3587 " m_raster_scale_factor: %g source.width: %d dest.y: %d "
3588 "dest.x: %d dest.width: %d dest.height: %d ",
3589 m_raster_scale_factor, source.width, dest.y, dest.x, dest.width,
3594 " i: %d j: %d dest_stride: %d target_line_start: %p "
3595 "target_data_x: %p y_offset: %d",
3596 i, j, dest_stride, target_line_start, target_data_x, y_offset);
3609 latlong_to_chartpix(m_vp_render_last.
clat, m_vp_render_last.
clon, xd, yd);
3611 xd - (m_vp_render_last.
pix_width * m_raster_scale_factor / 2);
3613 yd - (m_vp_render_last.
pix_height * m_raster_scale_factor / 2);
3614 double x_vernier = (xrd - wxRound(xrd));
3615 double y_vernier = (yrd - wxRound(yrd));
3616 int x_vernier_i = (int)wxRound(x_vernier / m_raster_scale_factor);
3617 int y_vernier_i = (int)wxRound(y_vernier / m_raster_scale_factor);
3622 int sx = wxMax(source.x, 0);
3623 s_data = (
unsigned char *)malloc((sx + source.width + 2) *
3624 (source.height + 2) * BPP / 8);
3626 wxRect vsource = source;
3627 vsource.height += 2;
3632 GetChartBits(vsource, s_data, 1);
3633 unsigned char *source_data = s_data;
3637 while (j < dest.y + dest.height) {
3638 y_offset = (int)((j - y_vernier_i) * m_raster_scale_factor) *
3642 target_data + (j * dest_line_length );
3643 target_data_x = target_line_start + ((dest.x) * BPP / 8);
3648 if ((target_data_x + (dest.width * BPP / 8)) >
3649 (target_data + data_size)) {
3650 j = dest.y + dest.height;
3652 while (i < dest.x + dest.width) {
3653 memcpy(target_data_x,
3654 source_data + BPP / 8 *
3655 (y_offset + (
int)((i + x_vernier_i) *
3656 m_raster_scale_factor)),
3659 target_data_x += BPP / 8;
3669 sigaction(SIGSEGV, &sa_all_previous, NULL);
3678bool ChartBaseBSB::GetChartBits(wxRect &source,
unsigned char *pPix,
3680 wxCriticalSectionLocker locker(m_critSect);
3692 while (iy < source.y + source.height) {
3693 if ((iy >= 0) && (iy < Size_Y)) {
3694 if (source.x >= 0) {
3695 if ((source.x + source.width) > Size_X) {
3696 if ((Size_X - source.x) < 0)
3697 memset(pCP, FILL_BYTE, source.width * BPP / 8);
3699 BSBGetScanline(pCP, iy, source.x, Size_X, sub_samp);
3700 memset(pCP + (Size_X - source.x) * BPP / 8, FILL_BYTE,
3701 (source.x + source.width - Size_X) * BPP / 8);
3704 BSBGetScanline(pCP, iy, source.x, source.x + source.width, sub_samp);
3706 if ((source.width + source.x) >= 0) {
3710 int xfill_corrected = -source.x + (source.x % sub_samp);
3711 memset(pCP, FILL_BYTE, (xfill_corrected * BPP / 8));
3712 BSBGetScanline(pCP + (xfill_corrected * BPP / 8), iy, 0,
3713 source.width + source.x, sub_samp);
3716 memset(pCP, FILL_BYTE, source.width * BPP / 8);
3723 memset(pCP, FILL_BYTE, source.width * BPP / 8);
3726 pCP += source.width * BPP / 8 * sub_samp;
3744int ChartBaseBSB::ReadBSBHdrLine(wxInputStream *ifs,
char *buf,
int buf_len_max)
3749 int line_length = 0;
3754 while (!ifs->Eof() && line_length < buf_len_max) {
3755 int c = ifs->GetC();
3758 if (0x1A == read_char) {
3759 ifs->Ungetch(read_char);
3767 if (read_char == 10 || read_char == 13) {
3769 cr_test = ifs->GetC();
3770 if (cr_test == 13) cr_test = ifs->GetC();
3772 if (cr_test != 10 && cr_test != 13) ifs->Ungetch(cr_test);
3777 if (read_char ==
'\n') {
3779 cr_test = ifs->GetC();
3781 if (cr_test !=
' ') {
3782 ifs->Ungetch(cr_test);
3788 while (cr_test ==
' ') cr_test = ifs->GetC();
3789 ifs->Ungetch(cr_test);
3805 if (line_length) *(lbuf - 1) =
'\0';
3814int ChartBaseBSB::BSBScanScanline(wxInputStream *pinStream) {
3815 int nLineMarker, nValueShift, iPixel = 0;
3816 unsigned char byValueMask, byCountMask;
3817 unsigned char byNext;
3825 byNext = pinStream->GetC();
3826 nLineMarker = nLineMarker * 128 + (byNext & 0x7f);
3827 }
while ((byNext & 0x80) != 0);
3830 nValueShift = 7 - nColorSize;
3831 byValueMask = (((1 << nColorSize)) - 1) << nValueShift;
3832 byCountMask = (1 << (7 - nColorSize)) - 1;
3836 while (((byNext = pinStream->GetC()) != 0) && (iPixel < Size_X)) {
3841 nRunCount = byNext & byCountMask;
3843 while ((byNext & 0x80) != 0) {
3844 byNext = pinStream->GetC();
3845 nRunCount = nRunCount * 128 + (byNext & 0x7f);
3848 if (iPixel + nRunCount + 1 > Size_X) nRunCount = Size_X - iPixel - 1;
3853 iPixel += nRunCount + 1;
3855 coffset = pinStream->TellI();
3865inline void memset_short(
unsigned char *dst,
unsigned char cbyte,
int count) {
3877 memset(dst, cbyte, count);
3882#define TILE_SIZE 512
3891 void Reset() { clock_gettime(CLOCK_REALTIME, &tp); }
3895 clock_gettime(CLOCK_REALTIME, &tp_end);
3896 return (tp_end.tv_sec - tp.tv_sec) * 1.e3 +
3897 (tp_end.tv_nsec - tp.tv_nsec) / 1.e6;
3907 free(pt->pTileOffset); \
3908 pt->pTileOffset = NULL; \
3911 pt->bValid = false; \
3918int ChartBaseBSB::BSBGetScanline(
unsigned char *pLineBuf,
int y,
int xs,
int xl,
3922 unsigned char *prgb = pLineBuf;
3924 unsigned char byValueMask, byCountMask;
3925 unsigned char byNext;
3933 if (bUseLineCache && pLineCache) {
3935 pt = &pLineCache[y];
3943 static double ttime;
3950 pt->size = pline_table[y + 1] - pline_table[y];
3953 pt->pPix = (
unsigned char *)malloc(Size_X);
3957 pt->pPix = (
unsigned char *)malloc(pt->size);
3959 if (pline_table[y] == 0 || pline_table[y + 1] == 0) FAIL;
3964 if (ifs_bitmap->TellI() != pline_table[y] &&
3965 wxInvalidOffset == ifs_bitmap->SeekI(pline_table[y], wxFromStart))
3969 if (pt->size > ifs_bufsize) {
3970 unsigned char *tmp = ifs_buf;
3971 if (!(ifs_buf = (
unsigned char *)realloc(ifs_buf, pt->size))) {
3975 ifs_bufsize = pt->size;
3982 ifs_bitmap->Read(lp, pt->size);
3987 if (!bUseLineCache) {
3991 if (pos < pt->size) {
3997 }
while ((byNext & 0x80) != 0);
4002 if (Size_X > ifs_bufsize) {
4003 unsigned char *tmp = ifs_buf;
4004 if (!(ifs_buf = (
unsigned char *)realloc(ifs_buf, Size_X))) {
4008 ifs_bufsize = Size_X;
4016 if (pos < pt->size) {
4022 }
while ((byNext & 0x80) != 0);
4025 nValueShift = 7 - nColorSize;
4026 byValueMask = (((1 << nColorSize)) - 1) << nValueShift;
4027 byCountMask = (1 << (7 - nColorSize)) - 1;
4030 unsigned int iPixel = 0;
4032#ifndef USE_OLD_CACHE
4033 pt->pTileOffset[0].offset = lp - pt->pPix;
4034 pt->pTileOffset[0].pixel = 0;
4035 unsigned int tileindex = 1, nextTile = TILE_SIZE;
4037 unsigned int nRunCount;
4038 unsigned char *end = pt->pPix + pt->size;
4039 while (iPixel < (
unsigned int)Size_X)
4042 nPixValue = (byNext & byValueMask) >> nValueShift;
4044 nRunCount = byNext & byCountMask;
4046 while ((byNext & 0x80) != 0) {
4048 nRunCount = nRunCount * 128 + (byNext & 0x7f);
4053 if (iPixel + nRunCount >
4054 (
unsigned int)Size_X)
4055 nRunCount = nRunCount - iPixel;
4058 memset_short(pCL + iPixel, nPixValue, nRunCount);
4059 iPixel += nRunCount;
4064 if (pos < pt->size) {
4070 unsigned char *offset = lp - 1;
4071 if (byNext == 0 || lp == end) {
4073 while (tileindex < (
unsigned int)Size_X / TILE_SIZE + 1) {
4074 pt->pTileOffset[tileindex].offset = pt->pTileOffset[0].offset;
4075 pt->pTileOffset[tileindex].pixel = 0;
4081 nRunCount = byNext & byCountMask;
4083 while ((byNext & 0x80) != 0) {
4084 if (pos < pt->size) {
4090 nRunCount = nRunCount * 128 + (byNext & 0x7f);
4095 if (iPixel + nRunCount >
4096 (
unsigned int)Size_X)
4097 nRunCount = Size_X - iPixel;
4099 while (iPixel + nRunCount > nextTile) {
4100 pt->pTileOffset[tileindex].offset = offset - pt->pPix;
4101 pt->pTileOffset[tileindex].pixel = iPixel;
4103 nextTile += TILE_SIZE;
4105 iPixel += nRunCount;
4114 if (xl > Size_X) xl = Size_X;
4117 pCL = pt->pPix + xs;
4120 if ((BPP == 24) && (1 == sub_samp)) {
4122 while (ix < xl - 1) {
4123 unsigned char cur_by = *pCL;
4124 rgbval = (int)(pPalette[cur_by]);
4125 while ((ix < xl - 1)) {
4126 if (cur_by != *pCL)
break;
4127 *((
int *)prgb) = rgbval;
4134 int dest_inc_val_bytes = (BPP / 8) * sub_samp;
4136 while (ix < xl - 1) {
4137 unsigned char cur_by = *pCL;
4138 rgbval = (int)(pPalette[cur_by]);
4139 while ((ix < xl - 1)) {
4140 if (cur_by != *pCL)
break;
4141 *((
int *)prgb) = rgbval;
4142 prgb += dest_inc_val_bytes;
4153 unsigned char *pCLast = pt->pPix + (xl - 1);
4154 unsigned char *prgb_last = pLineBuf + ((xl - 1) - xs) * BPP / 8;
4156 rgbval = (int)(pPalette[*pCLast]);
4157 unsigned char a = rgbval & 0xff;
4159 a = (rgbval >> 8) & 0xff;
4161 a = (rgbval >> 16) & 0xff;
4166 int tileindex = xs / TILE_SIZE;
4167 int tileoffset = pt->pTileOffset[tileindex].offset;
4169 lp = pt->pPix + tileoffset;
4171 ix = pt->pTileOffset[tileindex].pixel;
4175 nValueShift = 7 - nColorSize;
4176 byValueMask = (((1 << nColorSize)) - 1) << nValueShift;
4177 byCountMask = (1 << (7 - nColorSize)) - 1;
4179 bool bLastPixValueValid =
false;
4180 while (ix < xl - 1) {
4181 if (pos < pt->size) {
4188 nPixValue = (byNext & byValueMask) >> nValueShift;
4189 unsigned int nRunCount;
4192 nRunCount = xl - ix;
4194 nRunCount = byNext & byCountMask;
4195 while ((byNext & 0x80) != 0) {
4196 if (pos < pt->size) {
4200 nRunCount = xl - ix;
4203 nRunCount = nRunCount * 128 + (byNext & 0x7f);
4210 if (ix + nRunCount <= (
unsigned int)xs) {
4214 nRunCount -= xs - ix;
4218 if (ix + nRunCount >= (
unsigned int)xl) {
4219 nRunCount = xl - 1 - ix;
4220 bLastPixValueValid =
true;
4223 rgbval = (int)(pPalette[nPixValue]);
4229 int count = nRunCount;
4233 *(uint32_t *)prgb = rgbval;
4236 }
else if (rgbval == 0 || rgbval == 0xffffff) {
4238 memset(prgb, rgbval, nRunCount * 3);
4239 prgb += nRunCount * 3;
4253 if ((
long)prgb & 7) {
4255 *(uint32_t *)prgb = rgbval;
4257 if (!((
long)prgb & 7)) {
4258 if (count >= 8)
break;
4265 uint64_t *b = (uint64_t *)prgb;
4266 for (
int i = 0; i < 8; i++) {
4267 *(uint32_t *)prgb = rgbval;
4273 uint64_t *y = (uint64_t *)prgb;
4274 int count_d8 = count >> 3;
4275 prgb += 24 * count_d8;
4276 while (count_d8--) {
4283 int rcount = count & 0x7;
4285 *(uint32_t *)prgb = rgbval;
4298 if (!bLastPixValueValid) {
4299 if (pos < pt->size) {
4305 nPixValue = (byNext & byValueMask) >> nValueShift;
4307 rgbval = (int)(pPalette[nPixValue]);
4308 unsigned char a = rgbval & 0xff;
4311 a = (rgbval >> 8) & 0xff;
4313 a = (rgbval >> 16) & 0xff;
4321 if (cnt == 500000) {
4323 printf(
"cache time: %d %f\n", d, ttime / 1000.0);
4330 if (!bUseLineCache) {
4331#ifndef USE_OLD_CACHE
4332 free(pt->pTileOffset);
4340int *ChartBaseBSB::GetPalettePtr(BSB_Color_Capability color_index) {
4341 if (pPalettes[color_index]) {
4342 if (palette_direction == PaletteFwd)
4343 return (
int *)(pPalettes[color_index]->FwdPalette);
4345 return (
int *)(pPalettes[color_index]->RevPalette);
4350PaletteDir ChartBaseBSB::GetPaletteDir() {
4353 RGBO r = pc->GetRGBO();
4362bool ChartBaseBSB::AnalyzeSkew() {
4363 double lonmin = 1000;
4364 double lonmax = -1000;
4365 double latmin = 90.;
4366 double latmax = -90.;
4368 int nlonmin, nlonmax;
4375 for (
int n = 0; n < nRefpoint; n++) {
4377 if (pRefTable[n].lonr > lonmax) {
4378 lonmax = pRefTable[n].lonr;
4381 if (pRefTable[n].lonr < lonmin) {
4382 lonmin = pRefTable[n].lonr;
4387 if (pRefTable[n].latr < latmin) {
4388 latmin = pRefTable[n].latr;
4390 if (pRefTable[n].latr > latmax) {
4391 latmax = pRefTable[n].latr;
4396 if ((lonmin * lonmax) < 0) {
4397 if (pRefTable[nlonmin].xr > pRefTable[nlonmax].xr) {
4399 for (
int n = 0; n < nRefpoint; n++) {
4400 if (pRefTable[n].lonr < 0.0) pRefTable[n].lonr += 360.;
4407 for (
int n = 0; n < nRefpoint; n++) {
4409 if (pRefTable[n].lonr > lonmax) {
4410 lonmax = pRefTable[n].lonr;
4413 if (pRefTable[n].lonr < lonmin) {
4414 lonmin = pRefTable[n].lonr;
4419 if (pRefTable[n].latr < latmin) {
4420 latmin = pRefTable[n].latr;
4422 if (pRefTable[n].latr > latmax) {
4423 latmax = pRefTable[n].latr;
4430 double dist_max = 0.;
4434 for (
int i = 0; i < nRefpoint; i++) {
4435 for (
int j = i + 1; j < nRefpoint; j++) {
4436 double dx = pRefTable[i].xr - pRefTable[j].xr;
4437 double dy = pRefTable[i].yr - pRefTable[j].yr;
4438 double dist = (dx * dx) + (dy * dy);
4439 if (dist > dist_max) {
4447 double apparent_skew = 0;
4449 if (m_projection == PROJECTION_MERCATOR) {
4450 double easting0, easting1, northing0, northing1;
4452 toSM_ECC(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat, m_proj_lon,
4453 &easting0, &northing0);
4454 toSM_ECC(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat, m_proj_lon,
4455 &easting1, &northing1);
4458 atan2((easting1 - easting0), (northing1 - northing0)) * 180. / PI;
4459 double skew_points = atan2((pRefTable[jmax].yr - pRefTable[imax].yr),
4460 (pRefTable[jmax].xr - pRefTable[imax].xr)) *
4463 apparent_skew = skew_points - skew_proj + 90.;
4466 if (fabs(apparent_skew) > 180.) {
4467 if (apparent_skew < 0.)
4468 apparent_skew += 360.;
4470 apparent_skew -= 360.;
4474 else if (m_projection == PROJECTION_TRANSVERSE_MERCATOR) {
4475 double easting0, easting1, northing0, northing1;
4477 toTM(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat, m_proj_lon,
4478 &easting0, &northing0);
4479 toTM(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat, m_proj_lon,
4480 &easting1, &northing1);
4483 atan2((easting1 - easting0), (northing1 - northing0)) * 180. / PI;
4484 double skew_points = atan2((pRefTable[jmax].yr - pRefTable[imax].yr),
4485 (pRefTable[jmax].xr - pRefTable[imax].xr)) *
4488 apparent_skew = skew_points - skew_proj + 90.;
4491 if (fabs(apparent_skew) > 180.) {
4492 if (apparent_skew < 0.)
4493 apparent_skew += 360.;
4495 apparent_skew -= 360.;
4498 if (fabs(apparent_skew - m_Chart_Skew) > 2) {
4501 double dskew = fabs(apparent_skew - m_Chart_Skew);
4502 if ((m_proj_lon < lonmin) || (m_proj_lon > lonmax)) {
4504 double tentative_proj_lon = (lonmin + lonmax) / 2.;
4506 toTM(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat,
4507 tentative_proj_lon, &easting0, &northing0);
4508 toTM(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat,
4509 tentative_proj_lon, &easting1, &northing1);
4512 atan2((easting1 - easting0), (northing1 - northing0)) * 180. / PI;
4513 skew_points = atan2((pRefTable[jmax].yr - pRefTable[imax].yr),
4514 (pRefTable[jmax].xr - pRefTable[imax].xr)) *
4517 apparent_skew = skew_points - skew_proj + 90.;
4520 if (fabs(apparent_skew) > 180.) {
4521 if (apparent_skew < 0.)
4522 apparent_skew += 360.;
4524 apparent_skew -= 360.;
4528 if (fabs(apparent_skew - m_Chart_Skew) < dskew) {
4529 m_proj_lon = tentative_proj_lon;
4535 apparent_skew = m_Chart_Skew;
4537 if (fabs(apparent_skew - m_Chart_Skew) >
4539 m_Chart_Skew = apparent_skew;
4541 wxString msg =
" Warning: Skew override on chart ";
4542 msg.Append(m_FullPath);
4544 msg1.Printf(
" is %5g degrees", apparent_skew);
4555int ChartBaseBSB::AnalyzeRefpoints(
bool b_testSolution) {
4561 float lonmin = 1000;
4562 float lonmax = -1000;
4564 float latmax = -90.;
4566 int plonmin = 100000;
4568 int platmin = 100000;
4570 int nlonmin = 0, nlonmax = 0;
4575 for (n = 0; n < nRefpoint; n++) {
4577 if (pRefTable[n].lonr > lonmax) {
4578 lonmax = pRefTable[n].lonr;
4579 plonmax = (int)pRefTable[n].xr;
4582 if (pRefTable[n].lonr < lonmin) {
4583 lonmin = pRefTable[n].lonr;
4584 plonmin = (int)pRefTable[n].xr;
4589 if (pRefTable[n].latr < latmin) {
4590 latmin = pRefTable[n].latr;
4591 platmin = (int)pRefTable[n].yr;
4593 if (pRefTable[n].latr > latmax) {
4594 latmax = pRefTable[n].latr;
4595 platmax = (int)pRefTable[n].yr;
4600 if ((lonmin * lonmax) < 0) {
4601 if (pRefTable[nlonmin].xr > pRefTable[nlonmax].xr) {
4603 for (n = 0; n < nRefpoint; n++) {
4604 if (pRefTable[n].lonr < 0.0) pRefTable[n].lonr += 360.;
4611 for (n = 0; n < nRefpoint; n++) {
4613 if (pRefTable[n].lonr > lonmax) {
4614 lonmax = pRefTable[n].lonr;
4615 plonmax = (int)pRefTable[n].xr;
4618 if (pRefTable[n].lonr < lonmin) {
4619 lonmin = pRefTable[n].lonr;
4620 plonmin = (int)pRefTable[n].xr;
4625 if (pRefTable[n].latr < latmin) {
4626 latmin = pRefTable[n].latr;
4627 platmin = (int)pRefTable[n].yr;
4629 if (pRefTable[n].latr > latmax) {
4630 latmax = pRefTable[n].latr;
4631 platmax = (int)pRefTable[n].yr;
4638 cPoints.
count = nRefpoint;
4652 cPoints.
tx = (
double *)malloc(nRefpoint *
sizeof(
double));
4653 cPoints.
ty = (
double *)malloc(nRefpoint *
sizeof(
double));
4654 cPoints.
lon = (
double *)malloc(nRefpoint *
sizeof(
double));
4655 cPoints.
lat = (
double *)malloc(nRefpoint *
sizeof(
double));
4657 cPoints.
pwx = (
double *)malloc(12 *
sizeof(
double));
4658 cPoints.
wpx = (
double *)malloc(12 *
sizeof(
double));
4659 cPoints.
pwy = (
double *)malloc(12 *
sizeof(
double));
4660 cPoints.
wpy = (
double *)malloc(12 *
sizeof(
double));
4664 double dist_max = 0.;
4668 for (i = 0; i < nRefpoint; i++) {
4669 for (
int j = i + 1; j < nRefpoint; j++) {
4670 double dx = pRefTable[i].xr - pRefTable[j].xr;
4671 double dy = pRefTable[i].yr - pRefTable[j].yr;
4672 double dist = (dx * dx) + (dy * dy);
4673 if (dist > dist_max) {
4683 if (m_projection == PROJECTION_TRANSVERSE_MERCATOR) {
4684 double easting0, easting1, northing0, northing1;
4686 toTM(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat, m_proj_lon,
4687 &easting0, &northing0);
4688 toTM(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat, m_proj_lon,
4689 &easting1, &northing1);
4692 double dx2 = (pRefTable[jmax].xr - pRefTable[imax].xr) *
4693 (pRefTable[jmax].xr - pRefTable[imax].xr);
4694 double dy2 = (pRefTable[jmax].yr - pRefTable[imax].yr) *
4695 (pRefTable[jmax].yr - pRefTable[imax].yr);
4696 double dn2 = (northing1 - northing0) * (northing1 - northing0);
4697 double de2 = (easting1 - easting0) * (easting1 - easting0);
4699 m_ppm_avg = sqrt(dx2 + dy2) / sqrt(dn2 + de2);
4704 for (
int n = 0; n < nRefpoint; n++) {
4705 double easting, northing;
4706 toTM(pRefTable[n].latr, pRefTable[n].lonr, m_proj_lat, m_proj_lon,
4707 &easting, &northing);
4709 cPoints.
tx[n] = pRefTable[n].xr;
4710 cPoints.
ty[n] = pRefTable[n].yr;
4711 cPoints.
lon[n] = easting;
4712 cPoints.
lat[n] = northing;
4716 cPoints.
txmax = plonmax;
4717 cPoints.
txmin = plonmin;
4718 cPoints.
tymax = platmax;
4719 cPoints.
tymin = platmin;
4720 toTM(latmax, lonmax, m_proj_lat, m_proj_lon, &cPoints.
lonmax,
4722 toTM(latmin, lonmin, m_proj_lat, m_proj_lon, &cPoints.
lonmin,
4725 Georef_Calculate_Coefficients_Proj(&cPoints);
4729 else if (m_projection == PROJECTION_MERCATOR) {
4730 double easting0, easting1, northing0, northing1;
4732 toSM_ECC(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat, m_proj_lon,
4733 &easting0, &northing0);
4734 toSM_ECC(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat, m_proj_lon,
4735 &easting1, &northing1);
4742 double dx2 = (pRefTable[jmax].xr - pRefTable[imax].xr) *
4743 (pRefTable[jmax].xr - pRefTable[imax].xr);
4744 double dy2 = (pRefTable[jmax].yr - pRefTable[imax].yr) *
4745 (pRefTable[jmax].yr - pRefTable[imax].yr);
4746 double dn2 = (northing1 - northing0) * (northing1 - northing0);
4747 double de2 = (easting1 - easting0) * (easting1 - easting0);
4749 m_ppm_avg = sqrt(dx2 + dy2) / sqrt(dn2 + de2);
4754 for (
int n = 0; n < nRefpoint; n++) {
4755 double easting, northing;
4756 toSM_ECC(pRefTable[n].latr, pRefTable[n].lonr, m_proj_lat, m_proj_lon,
4757 &easting, &northing);
4759 cPoints.
tx[n] = pRefTable[n].xr;
4760 cPoints.
ty[n] = pRefTable[n].yr;
4761 cPoints.
lon[n] = easting;
4762 cPoints.
lat[n] = northing;
4769 cPoints.
txmax = plonmax;
4770 cPoints.
txmin = plonmin;
4771 cPoints.
tymax = platmax;
4772 cPoints.
tymin = platmin;
4773 toSM_ECC(latmax, lonmax, m_proj_lat, m_proj_lon, &cPoints.
lonmax,
4775 toSM_ECC(latmin, lonmin, m_proj_lat, m_proj_lon, &cPoints.
lonmin,
4778 Georef_Calculate_Coefficients_Proj(&cPoints);
4800 else if (m_projection == PROJECTION_POLYCONIC) {
4809 double proj_meridian = m_proj_lon;
4811 if ((pRefTable[nlonmax].lonr >= -proj_meridian) &&
4812 (-proj_meridian >= pRefTable[nlonmin].lonr))
4813 m_proj_lon = -m_proj_lon;
4815 double easting0, easting1, northing0, northing1;
4817 toPOLY(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat, m_proj_lon,
4818 &easting0, &northing0);
4819 toPOLY(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat, m_proj_lon,
4820 &easting1, &northing1);
4823 double dx2 = (pRefTable[jmax].xr - pRefTable[imax].xr) *
4824 (pRefTable[jmax].xr - pRefTable[imax].xr);
4825 double dy2 = (pRefTable[jmax].yr - pRefTable[imax].yr) *
4826 (pRefTable[jmax].yr - pRefTable[imax].yr);
4827 double dn2 = (northing1 - northing0) * (northing1 - northing0);
4828 double de2 = (easting1 - easting0) * (easting1 - easting0);
4830 m_ppm_avg = sqrt(dx2 + dy2) / sqrt(dn2 + de2);
4843 for (
int n = 0; n < nRefpoint; n++) {
4844 double easting, northing;
4845 toPOLY(pRefTable[n].latr, pRefTable[n].lonr, m_proj_lat, m_proj_lon,
4846 &easting, &northing);
4853 cPoints.
tx[n] = pRefTable[n].xr;
4854 cPoints.
ty[n] = pRefTable[n].yr;
4855 cPoints.
lon[n] = easting;
4856 cPoints.
lat[n] = northing;
4863 cPoints.
txmax = plonmax;
4864 cPoints.
txmin = plonmin;
4865 cPoints.
tymax = platmax;
4866 cPoints.
tymin = platmin;
4867 toPOLY(latmax, lonmax, m_proj_lat, m_proj_lon, &cPoints.
lonmax,
4869 toPOLY(latmin, lonmin, m_proj_lat, m_proj_lon, &cPoints.
lonmin,
4872 Georef_Calculate_Coefficients_Proj(&cPoints);
4884 else if (bHaveEmbeddedGeoref) {
4886 double easting0, easting1, northing0, northing1;
4888 toSM_ECC(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat, m_proj_lon,
4889 &easting0, &northing0);
4890 toSM_ECC(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat, m_proj_lon,
4891 &easting1, &northing1);
4896 double dx = (pRefTable[jmax].xr - pRefTable[imax].xr);
4897 double de = (easting1 - easting0);
4899 m_ppm_avg = fabs(dx / de);
4901 m_ExtraInfo =
"---<<< Warning: Chart georef accuracy may be poor. >>>---";
4910 vps.
clat = pRefTable[0].latr;
4911 vps.
clon = pRefTable[0].lonr;
4918 latlong_to_pix_vp(latmin, (lonmax + lonmin)/2., x1, y1, vps);
4919 latlong_to_pix_vp(latmax, (lonmax + lonmin)/2., x2, y2, vps);
4921 double apparent_skew = (atan2( (y2-y1), (x2-x1) ) * 180./PI) + 90.;
4922 if(apparent_skew < 0.)
4923 apparent_skew += 360;
4924 if(apparent_skew > 360.)
4925 apparent_skew -= 360;
4927 if(fabs( apparent_skew - m_Chart_Skew ) > 2) {
4928 m_Chart_Skew = apparent_skew;
4932 if (!b_testSolution)
return (0);
4936 vp.
clat = pRefTable[0].latr;
4937 vp.
clon = pRefTable[0].lonr;
4943 SetVPRasterParms(vp);
4945 double xpl_err_max = 0;
4946 double ypl_err_max = 0;
4950 pxref = (int)pRefTable[0].xr;
4951 pyref = (int)pRefTable[0].yr;
4953 for (i = 0; i < nRefpoint; i++) {
4954 px = (int)(vp.
pix_width / 2 + pRefTable[i].xr) - pxref;
4955 py = (int)(vp.
pix_height / 2 + pRefTable[i].yr) - pyref;
4957 vp_pix_to_latlong(vp, px, py, &elt, &elg);
4959 double lat_error = elt - pRefTable[i].latr;
4960 pRefTable[i].ypl_error = lat_error;
4962 double lon_error = elg - pRefTable[i].lonr;
4965 if (fabs(lon_error) > 180.) {
4968 else if (lon_error < 0.)
4971 pRefTable[i].xpl_error = lon_error;
4973 if (fabs(pRefTable[i].ypl_error) > fabs(ypl_err_max))
4974 ypl_err_max = pRefTable[i].ypl_error;
4975 if (fabs(pRefTable[i].xpl_error) > fabs(xpl_err_max))
4976 xpl_err_max = pRefTable[i].xpl_error;
4979 Chart_Error_Factor = fmax(fabs(xpl_err_max / (lonmax - lonmin)),
4980 fabs(ypl_err_max / (latmax - latmin)));
4981 double chart_error_meters =
4982 fmax(fabs(xpl_err_max * 60. * 1852.), fabs(ypl_err_max * 60. * 1852.));
4986 double chart_error_pixels = chart_error_meters * 4000. / m_Chart_Scale;
4989 int max_pixel_error = 4;
4991 if (chart_error_pixels > max_pixel_error) {
4993 " VP Final Check: Georeference Chart_Error_Factor on chart ";
4994 msg.Append(m_FullPath);
4996 msg1.Printf(
" is %5g \n nominal pixel error is: %5g",
4997 Chart_Error_Factor, chart_error_pixels);
5002 m_ExtraInfo =
"---<<< Warning: Chart georef accuracy is poor. >>>---";
5008 if ((chart_error_pixels > max_pixel_error) && bHaveEmbeddedGeoref) {
5010 " Trying again with internally calculated georef solution ";
5013 bHaveEmbeddedGeoref =
false;
5014 SetVPRasterParms(vp);
5019 pxref = (int)pRefTable[0].xr;
5020 pyref = (int)pRefTable[0].yr;
5022 for (i = 0; i < nRefpoint; i++) {
5023 px = (int)(vp.
pix_width / 2 + pRefTable[i].xr) - pxref;
5024 py = (int)(vp.
pix_height / 2 + pRefTable[i].yr) - pyref;
5026 vp_pix_to_latlong(vp, px, py, &elt, &elg);
5028 double lat_error = elt - pRefTable[i].latr;
5029 pRefTable[i].ypl_error = lat_error;
5031 double lon_error = elg - pRefTable[i].lonr;
5034 if (fabs(lon_error) > 180.) {
5037 else if (lon_error < 0.)
5040 pRefTable[i].xpl_error = lon_error;
5042 if (fabs(pRefTable[i].ypl_error) > fabs(ypl_err_max))
5043 ypl_err_max = pRefTable[i].ypl_error;
5044 if (fabs(pRefTable[i].xpl_error) > fabs(xpl_err_max))
5045 xpl_err_max = pRefTable[i].xpl_error;
5048 Chart_Error_Factor = fmax(fabs(xpl_err_max / (lonmax - lonmin)),
5049 fabs(ypl_err_max / (latmax - latmin)));
5051 chart_error_meters =
5052 fmax(fabs(xpl_err_max * 60. * 1852.), fabs(ypl_err_max * 60. * 1852.));
5053 chart_error_pixels = chart_error_meters * 4000. / m_Chart_Scale;
5056 if (chart_error_pixels > max_pixel_error) {
5058 " VP Final Check with internal georef: Georeference "
5059 "Chart_Error_Factor on chart ";
5060 msg.Append(m_FullPath);
5062 msg1.Printf(
" is %5g\n nominal pixel error is: %5g",
5063 Chart_Error_Factor, chart_error_pixels);
5068 m_ExtraInfo =
"---<<< Warning: Chart georef accuracy is poor. >>>---";
5070 wxString msg =
" Result: OK, Internal georef solution used.";
5081double ChartBaseBSB::AdjustLongitude(
double lon) {
5082 double lond = (m_LonMin + m_LonMax) / 2 - lon;
5085 else if (lond < -180)
5121static double polytrans(
double *coeff,
double lon,
double lat) {
5122 double ret = coeff[0] + coeff[1] * lon + coeff[2] * lat;
5123 ret += coeff[3] * lon * lon;
5124 ret += coeff[4] * lon * lat;
5125 ret += coeff[5] * lat * lat;
5126 ret += coeff[6] * lon * lon * lon;
5127 ret += coeff[7] * lon * lon * lat;
5128 ret += coeff[8] * lon * lat * lat;
5129 ret += coeff[9] * lat * lat * lat;
5151extern int bsb_LLtoXY(BSBImage *p,
double lon,
double lat,
int* x,
int* y)
5154 lon = (lon < 0) ? lon + p->cph : lon - p->cph;
5155 double xd = polytrans( p->wpx, lon, lat );
5156 double yd = polytrans( p->wpy, lon, lat );
5157 *x = (int)(xd + 0.5);
5158 *y = (int)(yd + 0.5);
5173extern int bsb_XYtoLL(BSBImage *p,
int x,
int y,
double* lonout,
double* latout)
5175 double lon = polytrans( p->pwx, x, y );
5176 lon = (lon < 0) ? lon + p->cph : lon - p->cph;
5178 *latout = polytrans( p->pwy, x, y );
virtual double GetNearestPreferredScalePPM(double target_scale_ppm)
Find the nearest preferred viewport scale (in pixels/meter) for this chart.
double GetClosestValidNaturalScalePPM(double target_scale, double scale_factor_min, double scale_factor_max)
Find closest valid scale that's a power of 2 multiple of chart's native scale.
An iterator class for OCPNRegion.
A wrapper class for wxRegion with additional functionality.
ViewPort - Core geographic projection and coordinate transformation engine.
double view_scale_ppm
Requested view scale in physical pixels per meter (ppm), before applying projections.
int pix_height
Height of the viewport in physical pixels.
int pix_width
Width of the viewport in physical pixels.
double skew
Angular distortion (shear transform) applied to the viewport in radians.
double clon
Center longitude of the viewport in degrees.
double clat
Center latitude of the viewport in degrees.
Optimized wxBitmap Object.
double lonmin
Minimum longitude in reference data.
int count
Number of reference points used.
double lonmax
Maximum longitude in reference data.
int txmin
Minimum x value in target space.
double * pwx
Polynomial coefficients for pixel-to-world longitude transformation.
double * tx
Array of x-coordinates in target (typically pixel) space.
double * wpx
Polynomial coefficients for world-to-pixel x transformation.
double * lat
Array of latitudes corresponding to reference points.
double * lon
Array of longitudes corresponding to reference points.
int status
Status of the georeferencing (0 = valid, other values indicate errors)
int tymin
Minimum y value in target space.
double * ty
Array of y-coordinates in target (typically pixel) space.
int tymax
Maximum y value in target space.
double latmin
Minimum latitude in reference data.
int txmax
Maximum x value in target space.
double latmax
Maximum latitude in reference data.
double * wpy
Polynomial coefficients for world-to-pixel y transformation.
double * pwy
Polynomial coefficients for pixel-to-world latitude transformation.