48#include <wx/wfstream.h>
49#include <wx/tokenzr.h>
50#include <wx/filename.h>
52#include <wx/fileconf.h>
57#include "ocpn_pixel.h"
58#include "chartdata_input_stream.h"
64#define OCPN_USE_CONFIG 1
66struct sigaction sa_all_chart;
67struct sigaction sa_all_previous;
71void catch_signals_chart(
int signo) {
74 siglongjmp(env_chart, 1);
86typedef __int32 int32_t;
87typedef unsigned __int32 uint32_t;
88typedef __int64 int64_t;
89typedef unsigned __int64 uint64_t;
106bool G_FloatPtInPolygon(
MyFlPoint *rgpts,
int wnumpts,
float x,
float y);
116ThumbData::ThumbData() { pDIBThumb = NULL; }
118ThumbData::~ThumbData() {
delete pDIBThumb; }
123opncpnPalette::opncpnPalette() {
127 FwdPalette = (
int *)malloc(
sizeof(
int));
128 RevPalette = (
int *)malloc(
sizeof(
int));
133opncpnPalette::~opncpnPalette() {
134 if (NULL != FwdPalette) free(FwdPalette);
135 if (NULL != RevPalette) free(RevPalette);
141ChartBase::ChartBase() {
142 m_depth_unit_id = DEPTH_UNIT_UNKNOWN;
146 m_global_color_scheme = GLOBAL_COLOR_SCHEME_RGB;
148 bReadyToRender =
false;
150 Chart_Error_Factor = 0;
152 m_Chart_Scale = 10000;
157 m_pCOVRTablePoints = NULL;
159 m_nNoCOVREntries = 0;
160 m_pNoCOVRTable = NULL;
161 m_pNoCOVRTablePoints = NULL;
163 m_EdDate = wxInvalidDateTime;
165 m_lon_datum_adjust = 0.;
166 m_lat_datum_adjust = 0.;
168 m_projection = PROJECTION_MERCATOR;
171ChartBase::~ChartBase() {
176 for (
unsigned int j = 0; j < (
unsigned int)m_nCOVREntries; j++)
177 free(m_pCOVRTable[j]);
180 free(m_pCOVRTablePoints);
184 for (
unsigned int j = 0; j < (
unsigned int)m_nNoCOVREntries; j++)
185 free(m_pNoCOVRTable[j]);
187 free(m_pNoCOVRTable);
188 free(m_pNoCOVRTablePoints);
191wxString ChartBase::GetHashKey()
const {
192 wxString key = GetFullPath();
193 wxChar separator = wxFileName::GetPathSeparator();
194 for (
unsigned int pos = 0; pos < key.size(); pos = key.find(separator, pos))
195 key.replace(pos, 1, _T(
"!"));
210ChartDummy::ChartDummy() {
212 m_ChartType = CHART_TYPE_DUMMY;
213 m_ChartFamily = CHART_FAMILY_UNKNOWN;
214 m_Chart_Scale = 22000000;
216 m_FullPath = _T(
"No Chart Available");
217 m_Description = m_FullPath;
220ChartDummy::~ChartDummy() {
delete m_pBM; }
222InitReturn ChartDummy::Init(
const wxString &name, ChartInitFlag init_flags) {
226void ChartDummy::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {}
228ThumbData *ChartDummy::GetThumbData(
int tnx,
int tny,
float lat,
float lon) {
232bool ChartDummy::UpdateThumbData(
double lat,
double lon) {
return FALSE; }
234bool ChartDummy::GetChartExtent(
Extent *pext) {
243bool ChartDummy::RenderRegionViewOnGL(
const wxGLContext &glc,
246 const LLRegion &Region) {
250bool ChartDummy::RenderRegionViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint,
252 return RenderViewOnDC(dc, VPoint);
255bool ChartDummy::RenderViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint) {
256 if (m_pBM && m_pBM->IsOk()) {
257 if ((m_pBM->GetWidth() != VPoint.pix_width) ||
258 (m_pBM->GetHeight() != VPoint.pix_height)) {
267 if (VPoint.pix_width && VPoint.pix_height) {
269 m_pBM =
new wxBitmap(VPoint.pix_width, VPoint.pix_height, -1);
271 dc.SelectObject(*m_pBM);
273 dc.SetBackground(*wxBLACK_BRUSH);
284void ChartDummy::GetValidCanvasRegion(
const ViewPort &VPoint,
286 pValidRegion->Clear();
287 pValidRegion->Union(0, 0, 1, 1);
290LLRegion ChartDummy::GetValidRegion() {
return LLRegion(); }
295ChartGEO::ChartGEO() { m_ChartType = CHART_TYPE_GEO; }
297ChartGEO::~ChartGEO() {}
299InitReturn ChartGEO::Init(
const wxString &name, ChartInitFlag init_flags) {
300#define BUF_LEN_MAX 4096
302 PreInit(name, init_flags, GLOBAL_COLOR_SCHEME_DAY);
304 char buffer[BUF_LEN_MAX];
307 new wxFFileInputStream(name);
309 m_filesize = wxFileName::GetSize(name);
311 if (!ifs_hdr->IsOk())
return INIT_FAIL_REMOVE;
317 m_Description = m_FullPath;
319 wxFileName GEOFile(m_FullPath);
322 Path = GEOFile.GetPath(wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME);
326 ifs_hdr->SeekI(0, wxFromStart);
330 while ((ReadBSBHdrLine(ifs_hdr, &buffer[0], BUF_LEN_MAX)) != 0) {
331 wxString str_buf(buffer, wxConvUTF8);
332 if (!strncmp(buffer,
"Bitmap", 6)) {
333 wxStringTokenizer tkz(str_buf, _T(
"="));
334 wxString token = tkz.GetNextToken();
335 if (token.IsSameAs(_T(
"Bitmap"), TRUE)) {
336 pBitmapFilePath =
new wxString();
339 i = tkz.GetPosition();
340 pBitmapFilePath->Clear();
342 pBitmapFilePath->Append(buffer[i]);
348 else if (!strncmp(buffer,
"Scale", 5)) {
349 wxStringTokenizer tkz(str_buf, _T(
"="));
350 wxString token = tkz.GetNextToken();
351 if (token.IsSameAs(_T(
"Scale"), TRUE))
354 i = tkz.GetPosition();
355 m_Chart_Scale = atoi(&buffer[i]);
359 else if (!strncmp(buffer,
"Depth", 5)) {
360 wxStringTokenizer tkz(str_buf, _T(
"="));
361 wxString token = tkz.GetNextToken();
362 if (token.IsSameAs(_T(
"Depth Units"), FALSE))
365 i = tkz.GetPosition();
366 wxString str(&buffer[i], wxConvUTF8);
367 m_DepthUnits = str.Trim();
371 else if (!strncmp(buffer,
"Point", 5))
375 sscanf(&buffer[0],
"Point%d=%f %f %d %d", &i, &lnr, <r, &yr, &xr);
378 pRefTable[nRefpoint].xr = xr;
379 pRefTable[nRefpoint].yr = yr;
380 pRefTable[nRefpoint].latr = ltr;
381 pRefTable[nRefpoint].lonr = lnr;
382 pRefTable[nRefpoint].bXValid = 1;
383 pRefTable[nRefpoint].bYValid = 1;
389 else if (!strncmp(buffer,
"Vertex", 6)) {
392 sscanf(buffer,
"Vertex%d=%f %f", &i, <p, &lnp);
396 if (NULL == pPlyTable) {
400 pPlyTable[nPlypoint].ltp = ltp;
401 pPlyTable[nPlypoint].lnp = lnp;
406 else if (!strncmp(buffer,
"Date Pub", 8)) {
407 char date_string[40];
409 sscanf(buffer,
"Date Published=%s\r\n", &date_string[0]);
410 wxString date_wxstr(date_string, wxConvUTF8);
412 if (dt.ParseDate(date_wxstr))
414 sprintf(date_buf,
"%d", dt.GetYear());
416 sscanf(date_string,
"%s", date_buf);
418 m_PubYear = wxString(date_buf, wxConvUTF8);
421 else if (!strncmp(buffer,
"Skew", 4)) {
422 wxStringTokenizer tkz(str_buf, _T(
"="));
423 wxString token = tkz.GetNextToken();
424 if (token.IsSameAs(_T(
"Skew Angle"), FALSE))
427 i = tkz.GetPosition();
429 sscanf(&buffer[i],
"%f,", &fcs);
434 else if (!strncmp(buffer,
"Latitude Offset", 15)) {
435 wxStringTokenizer tkz(str_buf, _T(
"="));
436 wxString token = tkz.GetNextToken();
437 if (token.IsSameAs(_T(
"Latitude Offset"), FALSE)) {
439 i = tkz.GetPosition();
441 sscanf(&buffer[i],
"%f,", <o);
446 else if (!strncmp(buffer,
"Longitude Offset", 16)) {
447 wxStringTokenizer tkz(str_buf, _T(
"="));
448 wxString token = tkz.GetNextToken();
449 if (token.IsSameAs(_T(
"Longitude Offset"), FALSE)) {
451 i = tkz.GetPosition();
453 sscanf(&buffer[i],
"%f,", &lno);
458 else if (!strncmp(buffer,
"Datum", 5)) {
459 wxStringTokenizer tkz(str_buf, _T(
"="));
460 wxString token = tkz.GetNextToken();
461 if (token.IsSameAs(_T(
"Datum"), FALSE)) {
462 token = tkz.GetNextToken();
467 else if (!strncmp(buffer,
"Name", 4)) {
468 wxStringTokenizer tkz(str_buf, _T(
"="));
469 wxString token = tkz.GetNextToken();
470 if (token.IsSameAs(_T(
"Name"), FALSE))
473 i = tkz.GetPosition();
475 while (isprint(buffer[i]) && (i < 80)) m_Name.Append(buffer[i++]);
487 if (pBitmapFilePath == NULL) {
489 return INIT_FAIL_REMOVE;
492 wxString NOS_Name(*pBitmapFilePath);
494 wxDir target_dir(Path);
495 wxArrayString file_array;
496 int nfiles = wxDir::GetAllFiles(Path, &file_array);
499 pBitmapFilePath->Prepend(Path);
501 wxFileName NOS_filename(*pBitmapFilePath);
502 if (!NOS_filename.FileExists()) {
506 wxString fname(NOS_filename.GetName());
507 wxString fext(NOS_filename.GetExt());
513 NOS_filename.SetName(fname);
514 NOS_filename.SetExt(fext);
516 if (NOS_filename.FileExists())
goto found_uclc_file;
521 NOS_filename.SetName(fname);
522 NOS_filename.SetExt(fext);
524 if (NOS_filename.FileExists())
goto found_uclc_file;
529 NOS_filename.SetName(fname);
530 NOS_filename.SetExt(fext);
532 if (NOS_filename.FileExists())
goto found_uclc_file;
537 NOS_filename.SetName(fname);
538 NOS_filename.SetExt(fext);
540 if (NOS_filename.FileExists())
goto found_uclc_file;
544 for (ifile = 0; ifile < nfiles; ifile++) {
545 wxString file_up = file_array[ifile];
548 wxString target_up = *pBitmapFilePath;
549 target_up.MakeUpper();
551 if (file_up.IsSameAs(target_up)) {
552 NOS_filename.Clear();
553 NOS_filename.Assign(file_array[ifile]);
554 goto found_uclc_file;
559 return INIT_FAIL_REMOVE;
563 delete pBitmapFilePath;
564 pBitmapFilePath =
new wxString(NOS_filename.GetFullPath());
567 new wxFFileInputStream(*pBitmapFilePath);
568 ifs_bitmap =
new wxBufferedInputStream(*ifss_bitmap);
570 if (!ifss_bitmap->IsOk()) {
572 return INIT_FAIL_REMOVE;
575 while ((ReadBSBHdrLine(ifss_bitmap, &buffer[0], BUF_LEN_MAX)) != 0) {
576 wxString str_buf(buffer, wxConvUTF8);
578 if (!strncmp(buffer,
"NOS", 3)) {
579 wxStringTokenizer tkz(str_buf, _T(
",="));
580 while (tkz.HasMoreTokens()) {
581 wxString token = tkz.GetNextToken();
582 if (token.IsSameAs(_T(
"RA"), TRUE))
587 i = tkz.GetPosition();
588 Size_X = atoi(&buffer[i]);
589 wxString token = tkz.GetNextToken();
590 i = tkz.GetPosition();
591 Size_Y = atoi(&buffer[i]);
592 }
else if (token.IsSameAs(_T(
"DU"), TRUE))
594 token = tkz.GetNextToken();
596 if (token.ToLong(&temp_du)) m_Chart_DU = temp_du;
602 else if (!strncmp(buffer,
"RGB", 3))
603 CreatePaletteEntry(buffer, COLOR_RGB_DEFAULT);
605 else if (!strncmp(buffer,
"DAY", 3))
606 CreatePaletteEntry(buffer, DAY);
608 else if (!strncmp(buffer,
"DSK", 3))
609 CreatePaletteEntry(buffer, DUSK);
611 else if (!strncmp(buffer,
"NGT", 3))
612 CreatePaletteEntry(buffer, NIGHT);
614 else if (!strncmp(buffer,
"NGR", 3))
615 CreatePaletteEntry(buffer, NIGHTRED);
617 else if (!strncmp(buffer,
"GRY", 3))
618 CreatePaletteEntry(buffer, GRAY);
620 else if (!strncmp(buffer,
"PRC", 3))
621 CreatePaletteEntry(buffer, PRC);
623 else if (!strncmp(buffer,
"PRG", 3))
624 CreatePaletteEntry(buffer, PRG);
628 if (Size_X <= 0 || Size_Y <= 0) {
630 return INIT_FAIL_REMOVE;
634 wxString msg(_T(
" Chart File contains less than 3 PLY points: "));
635 msg.Append(m_FullPath);
639 return INIT_FAIL_REMOVE;
642 if (m_datum_str.IsEmpty()) {
643 wxString msg(_T(
" Chart datum not specified on chart "));
644 msg.Append(m_FullPath);
646 wxLogMessage(_T(
" Default datum (WGS84) substituted."));
651 strncpy(d_str, m_datum_str.mb_str(), 99);
654 int datum_index = GetDatumIndex(d_str);
656 if (datum_index < 0) {
657 wxString msg(_T(
" Chart datum {"));
659 msg += _T(
"} invalid on chart ");
660 msg.Append(m_FullPath);
662 wxLogMessage(_T(
" Default datum (WGS84) substituted."));
664 datum_index = DATUM_INDEX_WGS84;
666 m_datum_index = datum_index;
671 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
672 *m_pCOVRTablePoints = nPlypoint;
673 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
674 *m_pCOVRTable = (
float *)malloc(nPlypoint * 2 *
sizeof(
float));
675 memcpy(*m_pCOVRTable, pPlyTable, nPlypoint * 2 *
sizeof(
float));
679 if (!SetMinMax())
return INIT_FAIL_REMOVE;
683 if (init_flags == HEADER_ONLY)
return INIT_OK;
687 if ((c = ifs_bitmap->GetC()) != 0x1a) {
688 return INIT_FAIL_REMOVE;
690 if ((c = ifs_bitmap->GetC()) == 0x0d) {
691 if ((c = ifs_bitmap->GetC()) != 0x0a) {
692 return INIT_FAIL_REMOVE;
694 if ((c = ifs_bitmap->GetC()) != 0x1a) {
695 return INIT_FAIL_REMOVE;
697 if ((c = ifs_bitmap->GetC()) != 0x00) {
698 return INIT_FAIL_REMOVE;
702 else if (c != 0x00) {
703 return INIT_FAIL_REMOVE;
707 nColorSize = ifs_bitmap->GetC();
708 if (nColorSize == wxEOF || nColorSize <= 0 || nColorSize > 7) {
709 wxString msg(_T(
" Invalid nColorSize data, corrupt on chart "));
710 msg.Append(m_FullPath);
712 return INIT_FAIL_REMOVE;
716 InitReturn pi_ret = PostInit();
717 if (pi_ret != INIT_OK)
727ChartKAP::ChartKAP() { m_ChartType = CHART_TYPE_KAP; }
729ChartKAP::~ChartKAP() {}
731InitReturn ChartKAP::Init(
const wxString &name, ChartInitFlag init_flags) {
732#define BUF_LEN_MAX 4096
734 ifs_hdr =
new ChartDataNonSeekableInputStream(
737 if (!ifs_hdr->IsOk())
return INIT_FAIL_REMOVE;
742 PreInit(name, init_flags, GLOBAL_COLOR_SCHEME_DAY);
744 char buffer[BUF_LEN_MAX];
747 m_Description = m_FullPath;
750 for (
int icl = 0; icl < 12; icl++) {
760 unsigned int TestBlockSize = 1999;
761 ifs_hdr->Read(buffer, TestBlockSize);
763 if (ifs_hdr->LastRead() != TestBlockSize) {
766 _T(
" Could not read first %d bytes of header for chart file: "),
771 return INIT_FAIL_REMOVE;
775 for (i = 0; i < TestBlockSize - 4; i++) {
777 if (buffer[i + 0] ==
'B' && buffer[i + 1] ==
'S' && buffer[i + 2] ==
'B' &&
778 buffer[i + 3] ==
'/')
782 if (buffer[i + 0] ==
'N' && buffer[i + 1] ==
'O' && buffer[i + 2] ==
'S' &&
783 buffer[i + 3] ==
'/')
786 if (i == TestBlockSize - 4) {
787 wxString msg(_T(
" Chart file has no BSB header, cannot Init."));
791 return INIT_FAIL_REMOVE;
795 ifs_hdr->SeekI(0, wxFromStart);
799 int done_header_parse = 0;
800 wxCSConv iso_conv(wxT(
"ISO-8859-1"));
802 while (done_header_parse == 0) {
803 if (ReadBSBHdrLine(ifs_hdr, buffer, BUF_LEN_MAX) == 0) {
809 done_header_parse = 1;
812 return INIT_FAIL_REMOVE;
818 wxString str_buf(buffer, wxConvUTF8);
820 str_buf = wxString(buffer, iso_conv);
822 if (str_buf.Find(_T(
"SHOM")) != wxNOT_FOUND) m_b_SHOM =
true;
824 if (!strncmp(buffer,
"BSB", 3)) {
825 wxString clip_str_buf(
828 wxStringTokenizer tkz(clip_str_buf, _T(
"/,="));
829 while (tkz.HasMoreTokens()) {
830 wxString token = tkz.GetNextToken();
831 if (token.IsSameAs(_T(
"RA"), TRUE))
834 i = tkz.GetPosition();
835 Size_X = atoi(&buffer[i]);
836 wxString token = tkz.GetNextToken();
837 i = tkz.GetPosition();
838 Size_Y = atoi(&buffer[i]);
839 }
else if (token.IsSameAs(_T(
"NA"), TRUE))
841 int i = tkz.GetPosition();
844 while ((buffer[i] !=
',') && (i < 80)) nbuf[j++] = buffer[i++];
846 wxString n_str(nbuf, iso_conv);
848 }
else if (token.IsSameAs(_T(
"NU"), TRUE))
850 int i = tkz.GetPosition();
853 while ((buffer[i] !=
',') && (i < 80)) nbuf[j++] = buffer[i++];
855 wxString n_str(nbuf, iso_conv);
857 }
else if (token.IsSameAs(_T(
"DU"), TRUE))
859 token = tkz.GetNextToken();
861 if (token.ToLong(&temp_du)) m_Chart_DU = temp_du;
866 else if (!strncmp(buffer,
"KNP", 3)) {
867 wxString conv_buf(buffer, iso_conv);
868 wxStringTokenizer tkz(conv_buf, _T(
"/,="));
869 while (tkz.HasMoreTokens()) {
870 wxString token = tkz.GetNextToken();
871 if (token.IsSameAs(_T(
"SC"), TRUE))
874 i = tkz.GetPosition();
875 m_Chart_Scale = atoi(&buffer[i]);
876 if (0 == m_Chart_Scale) m_Chart_Scale = 100000000;
877 }
else if (token.IsSameAs(_T(
"SK"), TRUE))
880 i = tkz.GetPosition();
882 sscanf(&buffer[i],
"%f,", &fcs);
884 }
else if (token.IsSameAs(_T(
"UN"), TRUE))
887 i = tkz.GetPosition();
888 wxString str(&buffer[i], iso_conv);
889 m_DepthUnits = str.BeforeFirst(
',');
890 }
else if (token.IsSameAs(_T(
"GD"), TRUE))
893 i = tkz.GetPosition();
894 wxString str(&buffer[i], iso_conv);
895 m_datum_str = str.BeforeFirst(
',').Trim();
896 }
else if (token.IsSameAs(_T(
"SD"), TRUE))
899 i = tkz.GetPosition();
900 wxString str(&buffer[i], iso_conv);
901 m_SoundingsDatum = str.BeforeFirst(
',').Trim();
902 }
else if (token.IsSameAs(_T(
"PP"),
906 i = tkz.GetPosition();
908 wxString str(&buffer[i], iso_conv);
909 wxString str1 = str.BeforeFirst(
',').Trim();
910 if (str1.ToDouble(&fcs)) m_proj_parameter = fcs;
911 }
else if (token.IsSameAs(_T(
"PR"), TRUE))
914 i = tkz.GetPosition();
915 wxString str(&buffer[i], iso_conv);
916 wxString stru = str.MakeUpper();
920 if (stru.Matches(_T(
"*MERCATOR*"))) {
921 m_projection = PROJECTION_MERCATOR;
925 if (stru.Matches(_T(
"*TRANSVERSE*"))) {
926 m_projection = PROJECTION_TRANSVERSE_MERCATOR;
930 if (stru.Matches(_T(
"*CONIC*"))) {
931 m_projection = PROJECTION_POLYCONIC;
935 if (stru.Matches(_T(
"*TM*"))) {
936 m_projection = PROJECTION_TRANSVERSE_MERCATOR;
940 if (stru.Matches(_T(
"*GAUSS CONFORMAL*"))) {
941 m_projection = PROJECTION_TRANSVERSE_MERCATOR;
946 m_projection = PROJECTION_UNKNOWN;
947 wxString msg(_T(
" Chart projection is "));
948 msg += tkz.GetNextToken();
949 msg += _T(
" which is unsupported. Disabling chart ");
953 return INIT_FAIL_REMOVE;
955 }
else if (token.IsSameAs(
960 i = tkz.GetPosition();
962 sscanf(&buffer[i],
"%f,", &x);
964 }
else if (token.IsSameAs(
969 i = tkz.GetPosition();
971 sscanf(&buffer[i],
"%f,", &x);
977 else if (!strncmp(buffer,
"RGB", 3))
978 CreatePaletteEntry(buffer, COLOR_RGB_DEFAULT);
980 else if (!strncmp(buffer,
"DAY", 3))
981 CreatePaletteEntry(buffer, DAY);
983 else if (!strncmp(buffer,
"DSK", 3))
984 CreatePaletteEntry(buffer, DUSK);
986 else if (!strncmp(buffer,
"NGT", 3))
987 CreatePaletteEntry(buffer, NIGHT);
989 else if (!strncmp(buffer,
"NGR", 3))
990 CreatePaletteEntry(buffer, NIGHTRED);
992 else if (!strncmp(buffer,
"GRY", 3))
993 CreatePaletteEntry(buffer, GRAY);
995 else if (!strncmp(buffer,
"PRC", 3))
996 CreatePaletteEntry(buffer, PRC);
998 else if (!strncmp(buffer,
"PRG", 3))
999 CreatePaletteEntry(buffer, PRG);
1001 else if (!strncmp(buffer,
"REF", 3)) {
1004 sscanf(&buffer[4],
"%d,%d,%d,%f,%f", &i, &xr, &yr, <r, &lnr);
1007 pRefTable[nRefpoint].xr = xr;
1008 pRefTable[nRefpoint].yr = yr;
1009 pRefTable[nRefpoint].latr = ltr;
1010 pRefTable[nRefpoint].lonr = lnr;
1011 pRefTable[nRefpoint].bXValid = 1;
1012 pRefTable[nRefpoint].bYValid = 1;
1018 else if (!strncmp(buffer,
"WPX", 3)) {
1021 wxStringTokenizer tkz(str_buf.Mid(4), _T(
","));
1022 wxString token = tkz.GetNextToken();
1024 if (token.ToLong((
long int *)&wpx_type)) {
1025 while (tkz.HasMoreTokens() && (idx < 12)) {
1026 token = tkz.GetNextToken();
1027 if (token.ToDouble(&d)) {
1036 else if (!strncmp(buffer,
"WPY", 3)) {
1039 wxStringTokenizer tkz(str_buf.Mid(4), _T(
","));
1040 wxString token = tkz.GetNextToken();
1042 if (token.ToLong((
long int *)&wpy_type)) {
1043 while (tkz.HasMoreTokens() && (idx < 12)) {
1044 token = tkz.GetNextToken();
1045 if (token.ToDouble(&d)) {
1054 else if (!strncmp(buffer,
"PWX", 3)) {
1057 wxStringTokenizer tkz(str_buf.Mid(4), _T(
","));
1058 wxString token = tkz.GetNextToken();
1060 if (token.ToLong((
long int *)&pwx_type)) {
1061 while (tkz.HasMoreTokens() && (idx < 12)) {
1062 token = tkz.GetNextToken();
1063 if (token.ToDouble(&d)) {
1072 else if (!strncmp(buffer,
"PWY", 3)) {
1075 wxStringTokenizer tkz(str_buf.Mid(4), _T(
","));
1076 wxString token = tkz.GetNextToken();
1078 if (token.ToLong((
long int *)&pwy_type)) {
1079 while (tkz.HasMoreTokens() && (idx < 12)) {
1080 token = tkz.GetNextToken();
1081 if (token.ToDouble(&d)) {
1090 else if (!strncmp(buffer,
"CPH", 3)) {
1092 sscanf(&buffer[4],
"%f", &float_cph);
1096 else if (!strncmp(buffer,
"VER", 3)) {
1097 wxStringTokenizer tkz(str_buf, _T(
"/,="));
1098 wxString token = tkz.GetNextToken();
1100 m_bsb_ver = tkz.GetNextToken();
1103 else if (!strncmp(buffer,
"DTM", 3)) {
1105 wxStringTokenizer tkz(str_buf, _T(
"/,="));
1106 wxString token = tkz.GetNextToken();
1108 token = tkz.GetNextToken();
1109 if (token.ToDouble(&val)) m_dtm_lat = val;
1111 token = tkz.GetNextToken();
1112 if (token.ToDouble(&val)) m_dtm_lon = val;
1120 else if (!strncmp(buffer,
"PLY", 3)) {
1123 if (sscanf(&buffer[4],
"%d,%f,%f", &i, <p, &lnp) != 3) {
1125 return INIT_FAIL_REMOVE;
1130 if (NULL == pPlyTable) {
1134 pPlyTable[nPlypoint].ltp = ltp;
1135 pPlyTable[nPlypoint].lnp = lnp;
1138 if (NULL == pPlyTable || nPlypoint > 1000000) {
1145 else if (!strncmp(buffer,
"CED", 3)) {
1146 wxStringTokenizer tkz(str_buf, _T(
"/,="));
1147 while (tkz.HasMoreTokens()) {
1148 wxString token = tkz.GetNextToken();
1149 if (token.IsSameAs(_T(
"ED"), TRUE))
1152 i = tkz.GetPosition();
1154 char date_string[40];
1158 sscanf(&buffer[i],
"%s\r\n", date_string);
1159 wxString date_wxstr(date_string, wxConvUTF8);
1162 if (dt.ParseDate(date_wxstr))
1173 }
else if ((iyear >= 50) && (iyear < 100)) {
1177 assert(iyear <= 9999);
1178 sprintf(date_buf,
"%d", iyear);
1183 sscanf(date_string,
"%s", date_buf);
1184 m_EdDate.Set(1, wxDateTime::Jan,
1188 m_PubYear = wxString(date_buf, wxConvUTF8);
1189 }
else if (token.IsSameAs(_T(
"SE"), TRUE))
1192 i = tkz.GetPosition();
1193 wxString str(&buffer[i], iso_conv);
1194 m_SE = str.BeforeFirst(
',');
1202 if (m_b_SHOM && (m_bsb_ver == _T(
"1.1"))) m_b_apply_dtm =
false;
1206 if (n_pwx && n_pwy && n_pwx && n_pwy) bHaveEmbeddedGeoref =
true;
1209 if (m_projection == PROJECTION_MERCATOR)
1210 m_proj_lat = m_proj_parameter;
1211 else if (m_projection == PROJECTION_TRANSVERSE_MERCATOR)
1212 m_proj_lon = m_proj_parameter;
1213 else if (m_projection == PROJECTION_POLYCONIC)
1214 m_proj_lon = m_proj_parameter;
1218 if (m_proj_lat > 82.0 || m_proj_lat < -82.0) m_proj_lat = 0.0;
1221 if (Size_X <= 0 || Size_Y <= 0) {
1223 return INIT_FAIL_REMOVE;
1226 if (nPlypoint < 3) {
1228 _T(
" Chart File contains less than 3 or too many PLY points: "));
1229 msg.Append(m_FullPath);
1232 return INIT_FAIL_REMOVE;
1235 if (m_datum_str.IsEmpty()) {
1236 wxString msg(_T(
" Chart datum not specified on chart "));
1237 msg.Append(m_FullPath);
1239 wxLogMessage(_T(
" Default datum (WGS84) substituted."));
1244 strncpy(d_str, m_datum_str.mb_str(), 99);
1247 int datum_index = GetDatumIndex(d_str);
1249 if (datum_index < 0) {
1250 wxString msg(_T(
" Chart datum {"));
1252 msg += _T(
"} invalid on chart ");
1253 msg.Append(m_FullPath);
1255 wxLogMessage(_T(
" Default datum (WGS84) substituted."));
1267 if ((m_projection != PROJECTION_MERCATOR &&
1268 m_projection != PROJECTION_TRANSVERSE_MERCATOR) ||
1271 AnalyzeRefpoints(
false);
1280 for (
int i = 0; i < nPlypoint; i++) {
1281 m_LatMax = wxMax(m_LatMax, pPlyTable[i].ltp);
1282 m_LatMin = wxMin(m_LatMin, pPlyTable[i].ltp);
1283 m_LonMax = wxMax(m_LonMax, pPlyTable[i].lnp);
1284 m_LonMin = wxMin(m_LonMin, pPlyTable[i].lnp);
1287 int count = nPlypoint;
1289 Plypoint *pOldPlyTable = pPlyTable;
1291 double lastplylat = 0.0, lastplylon = 0.0, x1 = 0.0, y1 = 0.0, x2, y2;
1292 double plylat, plylon;
1293 for (
int i = 0; i < count + 1; i++) {
1294 plylat = pOldPlyTable[i % count].ltp;
1295 plylon = pOldPlyTable[i % count].lnp;
1296 latlong_to_chartpix(plylat, plylon, x2, y2);
1298 if (lastplylon - plylon > 180.)
1300 else if (lastplylon - plylon < -180.)
1305 ceil((fabs(lastplylat - plylat) + fabs(lastplylon - plylon)) / 2);
1306 for (
double c = 0; c < steps; c++) {
1307 double d = c / steps, lat, lon;
1309 double x = (1 - d) * x1 + d * x2, y = (1 - d) * y1 + d * y2;
1310 chartpix_to_latlong(x, y, &lat, &lon);
1311 pPlyTable = (
Plypoint *)realloc(pPlyTable,
1312 sizeof(
Plypoint) * (nPlypoint + 1));
1313 pPlyTable[nPlypoint].ltp = lat;
1314 pPlyTable[nPlypoint].lnp = lon;
1319 lastplylat = plylat, lastplylon = plylon;
1333 for (
int i = 0; i < nPlypoint; i++) {
1334 m_LonMin = wxMin(m_LonMin, pPlyTable[i].lnp);
1335 m_LonMax = wxMax(m_LonMax, pPlyTable[i].lnp);
1339 bool b_adjusted =
false;
1340 if (m_LonMax * m_LonMin < 0) {
1341 if ((m_LonMax - m_LonMin) > 180.) b_test =
false;
1345 if (!bHaveEmbeddedGeoref) {
1348 AnalyzeRefpoints(
false);
1351 bool bAdjustPly =
false;
1352 wxRect bitRect(0, 0, Size_X, Size_Y);
1354 for (
int i = 0; i < nPlypoint; i++) {
1355 double pix_x, pix_y;
1356 latlong_to_chartpix(pPlyTable[i].ltp, pPlyTable[i].lnp, pix_x, pix_y);
1357 if (!bitRect.Contains(pix_x, pix_y)) {
1360 printf(
"Adjusting COVR region on: %s\n", name.ToUTF8().data());
1366 float *points =
new float[2 * nPlypoint];
1367 for (
int i = 0; i < nPlypoint; i++)
1368 points[2 * i + 0] = pPlyTable[i].ltp,
1369 points[2 * i + 1] = pPlyTable[i].lnp;
1370 LLRegion covrRegion(nPlypoint, points);
1372 covrRegion.Intersect(GetValidRegion());
1374 if (covrRegion.contours.size()) {
1376 m_nCOVREntries = covrRegion.contours.size();
1377 m_pCOVRTablePoints = (
int *)malloc(m_nCOVREntries *
sizeof(
int));
1378 m_pCOVRTable = (
float **)malloc(m_nCOVREntries *
sizeof(
float *));
1379 std::list<poly_contour>::iterator it = covrRegion.contours.begin();
1380 for (
int i = 0; i < m_nCOVREntries; i++) {
1381 m_pCOVRTablePoints[i] = it->size();
1383 (
float *)malloc(m_pCOVRTablePoints[i] * 2 *
sizeof(
float));
1384 std::list<contour_pt>::iterator jt = it->begin();
1385 for (
int j = 0; j < m_pCOVRTablePoints[i]; j++) {
1386 m_pCOVRTable[i][2 * j + 0] = jt->y;
1387 m_pCOVRTable[i][2 * j + 1] = jt->x;
1399 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
1400 *m_pCOVRTablePoints = nPlypoint;
1401 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
1402 *m_pCOVRTable = (
float *)malloc(nPlypoint * 2 *
sizeof(
float));
1403 memcpy(*m_pCOVRTable, pPlyTable, nPlypoint * 2 *
sizeof(
float));
1410 strncpy(d_str, m_datum_str.mb_str(), 99);
1413 int datum_index = GetDatumIndex(d_str);
1414 m_datum_index = datum_index;
1416 if (datum_index < 0)
1417 m_ExtraInfo = _T(
"---<<< Warning: Chart Datum may be incorrect. >>>---");
1420 m_lon_datum_adjust = (-m_dtm_lon) / 3600.;
1421 m_lat_datum_adjust = (-m_dtm_lat) / 3600.;
1425 int cnPlypoint = GetCOVRTablenPoints(0);
1427 for (
int u = 0; u < cnPlypoint; u++) {
1431 if (m_datum_index == DATUM_INDEX_WGS84 ||
1432 m_datum_index == DATUM_INDEX_UNKNOWN) {
1433 dlon = m_dtm_lon / 3600.;
1434 dlat = m_dtm_lat / 3600.;
1438 double to_lat, to_lon;
1439 MolodenskyTransform(ppp->ltp, ppp->lnp, &to_lat, &to_lon, m_datum_index,
1441 dlon = (to_lon - ppp->lnp);
1442 dlat = (to_lat - ppp->ltp);
1443 if (m_b_apply_dtm) {
1444 dlon += m_dtm_lon / 3600.;
1445 dlat += m_dtm_lat / 3600.;
1454 if (!SetMinMax())
return INIT_FAIL_REMOVE;
1458 if (init_flags == HEADER_ONLY)
return INIT_OK;
1462 bool bcorrupt =
false;
1464 if ((c = ifs_hdr->GetC()) != 0x1a) {
1467 if ((c = ifs_hdr->GetC()) == 0x0d) {
1468 if ((c = ifs_hdr->GetC()) != 0x0a) {
1471 if ((c = ifs_hdr->GetC()) != 0x1a) {
1474 if ((c = ifs_hdr->GetC()) != 0x00) {
1479 else if (c != 0x00) {
1484 wxString msg(_T(
" Chart File RLL data corrupt on chart "));
1485 msg.Append(m_FullPath);
1488 return INIT_FAIL_REMOVE;
1492 nColorSize = ifs_hdr->GetC();
1493 if (nColorSize == wxEOF || nColorSize <= 0 || nColorSize > 7) {
1494 wxString msg(_T(
" Invalid nColorSize data, corrupt on chart "));
1495 msg.Append(m_FullPath);
1497 return INIT_FAIL_REMOVE;
1500 nFileOffsetDataStart = ifs_hdr->TellI();
1504 ChartDataInputStream *stream =
1505 new ChartDataInputStream(name);
1508 tempfile = stream->TempFileName();
1510 m_filesize = wxFileName::GetSize(tempfile.empty() ? name : tempfile);
1512 ifss_bitmap = stream;
1513 ifs_bitmap =
new wxBufferedInputStream(*ifss_bitmap);
1516 InitReturn pi_ret = PostInit();
1517 if (pi_ret != INIT_OK)
return pi_ret;
1525ChartBaseBSB::ChartBaseBSB() {
1527 m_ChartFamily = CHART_FAMILY_RASTER;
1529 pBitmapFilePath = NULL;
1534 cached_image_ok = 0;
1539 bHaveEmbeddedGeoref =
false;
1545#ifdef __OCPN__ANDROID__
1546 bUseLineCache =
false;
1548 bUseLineCache =
true;
1557 m_bilinear_limit = 8;
1563 for (
int i = 0; i < N_BSB_COLORS; i++) pPalettes[i] = NULL;
1565 bGeoErrorSent =
false;
1569 m_mapped_color_index = COLOR_RGB_DEFAULT;
1571 m_datum_str = _T(
"WGS84");
1580 m_proj_parameter = 0.;
1582 m_b_apply_dtm =
true;
1586#ifdef OCPN_USE_CONFIG
1587 wxFileConfig *pfc = (wxFileConfig *)pConfig;
1588 pfc->SetPath(_T (
"/Settings" ));
1589 pfc->Read(_T (
"DebugBSBImg" ), &m_b_cdebug, 0);
1593ChartBaseBSB::~ChartBaseBSB() {
1594 if (pBitmapFilePath)
delete pBitmapFilePath;
1596 if (pline_table) free(pline_table);
1598 if (ifs_buf) free(ifs_buf);
1607 if (cPoints.status) {
1620 FreeLineCacheRows();
1625 for (
int i = 0; i < N_BSB_COLORS; i++)
delete pPalettes[i];
1628void ChartBaseBSB::FreeLineCacheRows(
int start,
int end) {
1633 end = wxMin(end, Size_Y);
1634 for (
int ylc = start; ylc < end; ylc++) {
1637 free(pt->pTileOffset);
1645bool ChartBaseBSB::HaveLineCacheRow(
int row) {
1656double ChartBaseBSB::GetNormalScaleMin(
double canvas_scale_factor,
1657 bool b_allow_overzoom) {
1659 return (canvas_scale_factor / m_ppm_avg) /
1666double ChartBaseBSB::GetNormalScaleMax(
double canvas_scale_factor,
1668 return (canvas_scale_factor / m_ppm_avg) *
1672double ChartBaseBSB::GetNearestPreferredScalePPM(
double target_scale_ppm) {
1673 return GetClosestValidNaturalScalePPM(
1674 target_scale_ppm, .01, 64.);
1678double ChartBaseBSB::GetClosestValidNaturalScalePPM(
double target_scale,
1679 double scale_factor_min,
1680 double scale_factor_max) {
1681 double chart_1x_scale = GetPPM();
1683 double binary_scale_factor = 1.;
1686 if (chart_1x_scale > target_scale) {
1687 double binary_scale_factor_max = 1 / scale_factor_min;
1689 while (binary_scale_factor < binary_scale_factor_max) {
1690 if (fabs((chart_1x_scale / binary_scale_factor) - target_scale) <
1691 (target_scale * 0.05))
1693 if ((chart_1x_scale / binary_scale_factor) < target_scale)
1696 binary_scale_factor *= 2.;
1703 int isf_max = (int)scale_factor_max;
1704 while (ibsf < isf_max) {
1705 if (fabs((chart_1x_scale * ibsf) - target_scale) < (target_scale * 0.05))
1708 else if ((chart_1x_scale * ibsf) > target_scale) {
1709 if (ibsf > 1) ibsf /= 2;
1715 binary_scale_factor = 1. / ibsf;
1718 return chart_1x_scale / binary_scale_factor;
1721InitReturn ChartBaseBSB::Init(
const wxString &name, ChartInitFlag init_flags) {
1722 m_global_color_scheme = GLOBAL_COLOR_SCHEME_RGB;
1726InitReturn ChartBaseBSB::PreInit(
const wxString &name, ChartInitFlag init_flags,
1728 m_global_color_scheme = cs;
1732void ChartBaseBSB::CreatePaletteEntry(
char *buffer,
int palette_index) {
1733 if (palette_index < N_BSB_COLORS) {
1734 if (!pPalettes[palette_index]) pPalettes[palette_index] =
new opncpnPalette;
1738 (
int *)realloc(pp->FwdPalette, (pp->nFwd + 1) *
sizeof(int));
1740 (
int *)realloc(pp->RevPalette, (pp->nRev + 1) *
sizeof(int));
1746 sscanf(&buffer[4],
"%d,%d,%d,%d", &n, &r, &g, &b);
1751 fcolor = (b << 16) + (g << 8) + r;
1752 rcolor = (r << 16) + (g << 8) + b;
1754 pp->RevPalette[i] = rcolor;
1755 pp->FwdPalette[i] = fcolor;
1759InitReturn ChartBaseBSB::PostInit(
void) {
1761 if (nColorSize == wxEOF || nColorSize <= 0 || nColorSize > 7) {
1763 _T(
" Invalid nColorSize data, corrupt in PostInit() on chart "));
1764 msg.Append(m_FullPath);
1766 return INIT_FAIL_REMOVE;
1769 if (Size_X <= 0 || Size_X > INT_MAX / 4 || Size_Y <= 0 ||
1770 Size_Y - 1 > INT_MAX / 4) {
1772 _T(
" Invalid Size_X/Size_Y data, corrupt in PostInit() on chart "));
1773 msg.Append(m_FullPath);
1775 return INIT_FAIL_REMOVE;
1781 if (pPalettes[COLOR_RGB_DEFAULT]) {
1782 nrev_def = pPalettes[COLOR_RGB_DEFAULT]->nRev;
1783 nfwd_def = pPalettes[COLOR_RGB_DEFAULT]->nFwd;
1786 for (
int i = 0; i < N_BSB_COLORS; i++) {
1787 if (pPalettes[i] == NULL) {
1790 pNullSubPal->nFwd = nfwd_def;
1791 pNullSubPal->nRev = nrev_def;
1793 free(pNullSubPal->FwdPalette);
1794 pNullSubPal->FwdPalette = (
int *)malloc(pNullSubPal->nFwd *
sizeof(
int));
1795 if (pPalettes[COLOR_RGB_DEFAULT])
1796 memcpy(pNullSubPal->FwdPalette,
1797 pPalettes[COLOR_RGB_DEFAULT]->FwdPalette,
1798 pNullSubPal->nFwd *
sizeof(
int));
1800 free(pNullSubPal->RevPalette);
1801 pNullSubPal->RevPalette = (
int *)malloc(pNullSubPal->nRev *
sizeof(
int));
1802 if (pPalettes[COLOR_RGB_DEFAULT])
1803 memcpy(pNullSubPal->RevPalette,
1804 pPalettes[COLOR_RGB_DEFAULT]->RevPalette,
1805 pNullSubPal->nRev *
sizeof(
int));
1807 pPalettes[i] = pNullSubPal;
1812 palette_direction = GetPaletteDir();
1814 SetColorScheme(m_global_color_scheme,
false);
1817 ifs_bufsize = Size_X * 4;
1818 ifs_buf = (
unsigned char *)malloc(ifs_bufsize);
1819 if (!ifs_buf)
return INIT_FAIL_REMOVE;
1821 ifs_bufend = ifs_buf + ifs_bufsize;
1822 ifs_lp = ifs_bufend;
1823 ifs_file_offset = -ifs_bufsize;
1827 pline_table = (
int *)malloc((Size_Y + 1) *
sizeof(int));
1828 if (!pline_table)
return INIT_FAIL_REMOVE;
1830 ifs_bitmap->SeekI((Size_Y + 1) * -4,
1832 pline_table[Size_Y] = ifs_bitmap->TellI();
1834 unsigned char *tmp = (
unsigned char *)malloc(Size_Y *
sizeof(
int));
1835 ifs_bitmap->Read(tmp, Size_Y *
sizeof(
int));
1836 if (ifs_bitmap->LastRead() != Size_Y *
sizeof(int)) {
1837 wxString msg(_T(
" Chart File corrupt in PostInit() on chart "));
1838 msg.Append(m_FullPath);
1842 return INIT_FAIL_REMOVE;
1846 unsigned char *b = tmp;
1847 for (
int ifplt = 0; ifplt < Size_Y; ifplt++) {
1849 offset += *b++ * 256 * 256 * 256;
1850 offset += *b++ * 256 * 256;
1851 offset += *b++ * 256;
1854 pline_table[ifplt] = offset;
1859 bool bline_index_ok =
true;
1862 wxULongLong bitmap_filesize = m_filesize;
1863 if ((m_ChartType == CHART_TYPE_GEO) && pBitmapFilePath)
1864 bitmap_filesize = wxFileName::GetSize(*pBitmapFilePath);
1867 for (
int iplt = 0; iplt < Size_Y - 1; iplt++) {
1868 if (pline_table[iplt] > bitmap_filesize) {
1869 wxString msg(_T(
" Chart File corrupt in PostInit() on chart "));
1870 msg.Append(m_FullPath);
1873 return INIT_FAIL_REMOVE;
1876 int thisline_size = pline_table[iplt + 1] - pline_table[iplt];
1877 if (thisline_size < 0) {
1878 wxString msg(_T(
" Chart File corrupt in PostInit() on chart "));
1879 msg.Append(m_FullPath);
1882 return INIT_FAIL_REMOVE;
1891 m_bsb_ver.ToDouble(&ver);
1893 for (
int iplt = 0; iplt < 10; iplt++) {
1894 if (wxInvalidOffset ==
1895 ifs_bitmap->SeekI(pline_table[iplt], wxFromStart)) {
1896 wxString msg(_T(
" Chart File corrupt in PostInit() on chart "));
1897 msg.Append(m_FullPath);
1900 return INIT_FAIL_REMOVE;
1903 int thisline_size = pline_table[iplt + 1] - pline_table[iplt];
1904 ifs_bitmap->Read(ifs_buf, thisline_size);
1906 unsigned char *lp = ifs_buf;
1908 unsigned char byNext;
1909 int nLineMarker = 0;
1912 nLineMarker = nLineMarker * 128 + (byNext & 0x7f);
1913 }
while ((byNext & 0x80) != 0);
1920 if (iplt == 0) m_nLineOffset = nLineMarker;
1922 if (nLineMarker != iplt + m_nLineOffset) {
1923 bline_index_ok =
false;
1930 if (!bline_index_ok) {
1931 wxString msg(_T(
" Line Index corrupt, recreating Index for chart "));
1932 msg.Append(m_FullPath);
1934 if (!CreateLineIndex()) {
1935 wxString msg(_T(
" Error creating Line Index for chart "));
1936 msg.Append(m_FullPath);
1938 return INIT_FAIL_REMOVE;
1943 if (bUseLineCache) {
1947 for (
int ylc = 0; ylc < Size_Y; ylc++) {
1948 pt = &pLineCache[ylc];
1951 pt->pTileOffset = NULL;
1957 wxString test_str = m_DepthUnits.Upper();
1958 if (test_str.IsSameAs(_T(
"FEET"), FALSE))
1959 m_depth_unit_id = DEPTH_UNIT_FEET;
1960 else if (test_str.IsSameAs(_T(
"METERS"), FALSE))
1961 m_depth_unit_id = DEPTH_UNIT_METERS;
1962 else if (test_str.IsSameAs(_T(
"METRES"),
1964 m_depth_unit_id = DEPTH_UNIT_METERS;
1965 else if (test_str.IsSameAs(_T(
"METRIC"), FALSE))
1966 m_depth_unit_id = DEPTH_UNIT_METERS;
1967 else if (test_str.IsSameAs(_T(
"FATHOMS"), FALSE))
1968 m_depth_unit_id = DEPTH_UNIT_FATHOMS;
1969 else if (test_str.Find(_T(
"FATHOMS")) !=
1971 m_depth_unit_id = DEPTH_UNIT_FATHOMS;
1972 else if (test_str.Find(_T(
"METERS")) !=
1974 m_depth_unit_id = DEPTH_UNIT_METERS;
1977 int analyze_ret_val = AnalyzeRefpoints();
1978 if (0 != analyze_ret_val)
return INIT_FAIL_REMOVE;
1980 bReadyToRender =
true;
1984bool ChartBaseBSB::CreateLineIndex() {
1990 ifs_bitmap->SeekI(nFileOffsetDataStart);
1992 for (
int iplt = 0; iplt < Size_Y; iplt++) {
1993 int offset = ifs_bitmap->TellI();
1995 int iscan = BSBScanScanline(ifs_bitmap);
2019 pline_table[iplt] = offset;
2026void ChartBaseBSB::InvalidateLineCache(
void) {
2029 for (
int ylc = 0; ylc < Size_Y; ylc++) {
2030 pt = &pLineCache[ylc];
2034 free(pt->pTileOffset);
2035 pt->pTileOffset = NULL;
2042bool ChartBaseBSB::GetChartExtent(
Extent *pext) {
2043 pext->NLAT = m_LatMax;
2044 pext->SLAT = m_LatMin;
2045 pext->ELON = m_LonMax;
2046 pext->WLON = m_LonMin;
2051bool ChartBaseBSB::SetMinMax(
void) {
2060 int cnPlypoint = GetCOVRTablenPoints(0);
2062 for (
int u = 0; u < cnPlypoint; u++) {
2063 if (ppp->lnp > m_LonMax) m_LonMax = ppp->lnp;
2064 if (ppp->lnp < m_LonMin) m_LonMin = ppp->lnp;
2066 if (ppp->ltp > m_LatMax) m_LatMax = ppp->ltp;
2067 if (ppp->ltp < m_LatMin) m_LatMin = ppp->ltp;
2076 if ((m_LonMax * m_LonMin) < 0)
2081 if (0 == nRefpoint)
return false;
2084 double min_dist_x = 360;
2086 for (
int ic = 0; ic < nRefpoint; ic++) {
2088 ((m_LatMax - pRefTable[ic].latr) * (m_LatMax - pRefTable[ic].latr)) +
2089 ((m_LonMax - pRefTable[ic].lonr) * (m_LonMax - pRefTable[ic].lonr)));
2091 if (dist < min_dist_x) {
2098 double min_dist_n = 360;
2100 for (
int id = 0;
id < nRefpoint;
id++) {
2102 ((m_LatMin - pRefTable[
id].latr) * (m_LatMin - pRefTable[
id].latr)) +
2103 ((m_LonMin - pRefTable[
id].lonr) * (m_LonMin - pRefTable[
id].lonr)));
2105 if (dist < min_dist_n) {
2113 if (pRefTable[imaxclose].xr < pRefTable[iminclose].xr) {
2126 int cnPlypoint = GetCOVRTablenPoints(0);
2128 for (
int u = 0; u < cnPlypoint; u++) {
2129 if (ppp->lnp < 0.) ppp->lnp += 360.;
2131 if (ppp->lnp > m_LonMax) m_LonMax = ppp->lnp;
2132 if (ppp->lnp < m_LonMin) m_LonMin = ppp->lnp;
2134 if (ppp->ltp > m_LatMax) m_LatMax = ppp->ltp;
2135 if (ppp->ltp < m_LatMin) m_LatMin = ppp->ltp;
2146 if ((m_LonMax < -180.) && (m_LonMin < -180.)) {
2151 int cnPlypoint = GetCOVRTablenPoints(0);
2153 for (
int u = 0; u < cnPlypoint; u++) {
2162void ChartBaseBSB::SetColorScheme(ColorScheme cs,
bool bApplyImmediate) {
2167 case GLOBAL_COLOR_SCHEME_RGB:
2168 m_mapped_color_index = COLOR_RGB_DEFAULT;
2170 case GLOBAL_COLOR_SCHEME_DAY:
2171 m_mapped_color_index = DAY;
2173 case GLOBAL_COLOR_SCHEME_DUSK:
2174 m_mapped_color_index = DUSK;
2176 case GLOBAL_COLOR_SCHEME_NIGHT:
2177 m_mapped_color_index = NIGHT;
2180 m_mapped_color_index = DAY;
2184 pPalette = GetPalettePtr(m_mapped_color_index);
2186 m_global_color_scheme = cs;
2189 if (bApplyImmediate) {
2190 m_cached_scale_ppm = 1.0;
2194 if (pThumbData) pThumbData->pDIBThumb = NULL;
2197wxBitmap *ChartBaseBSB::CreateThumbnail(
int tnx,
int tny, ColorScheme cs) {
2200 int divx = wxMax(1, Size_X / (4 * tnx));
2201 int divy = wxMax(1, Size_Y / (4 * tny));
2203 int div_factor = std::min(divx, divy);
2205 int des_width = Size_X / div_factor;
2206 int des_height = Size_Y / div_factor;
2212 gts.height = Size_Y;
2216 unsigned char *pLineT = (
unsigned char *)malloc((Size_X + 1) * BPP / 8);
2219 unsigned char *pPixTN =
2220 (
unsigned char *)malloc(des_width * des_height * this_bpp / 8);
2231 ColorScheme cs_tmp = m_global_color_scheme;
2232 SetColorScheme(cs,
false);
2234 while (iyd < des_height) {
2235 if (0 == BSBGetScanline(pLineT, iy, 0, Size_X, 1))
2242 yoffd = iyd * des_width * this_bpp / 8;
2246 while (ixd < des_width) {
2247 pxs = pLineT + (ix * BPP / 8);
2248 pxd = pPixTN + (yoffd + (ixd * this_bpp / 8));
2264 SetColorScheme(cs_tmp,
false);
2268#ifdef ocpnUSE_ocpnBitmap
2269 wxBitmap *bmx2 =
new ocpnBitmap(pPixTN, des_width, des_height, -1);
2270 wxImage imgx2 = bmx2->ConvertToImage();
2271 imgx2.Rescale(des_width / 4, des_height / 4, wxIMAGE_QUALITY_HIGH);
2272 retBMP =
new wxBitmap(imgx2);
2275 wxImage thumb_image(des_width, des_height, pPixTN,
true);
2276 thumb_image.Rescale(des_width / 4, des_height / 4, wxIMAGE_QUALITY_HIGH);
2277 retBMP =
new wxBitmap(thumb_image);
2290ThumbData *ChartBaseBSB::GetThumbData(
int tnx,
int tny,
float lat,
float lon) {
2292 if (!pThumbData->pDIBThumb)
2293 pThumbData->pDIBThumb = CreateThumbnail(tnx, tny, m_global_color_scheme);
2295 pThumbData->Thumb_Size_X = tnx;
2296 pThumbData->Thumb_Size_Y = tny;
2299 int divx = Size_X / tnx;
2300 int divy = Size_Y / tny;
2302 int div_factor = std::min(divx, divy);
2309 tvp.pix_width = tnx;
2310 tvp.pix_height = tny;
2311 tvp.view_scale_ppm = GetPPM() / div_factor;
2315 latlong_to_pix_vp(lat, lon, pixx, pixy, tvp);
2318 pThumbData->ShipX = pixx;
2319 pThumbData->ShipY = pixy;
2324bool ChartBaseBSB::UpdateThumbData(
double lat,
double lon) {
2328 int divx = Size_X / pThumbData->Thumb_Size_X;
2329 int divy = Size_Y / pThumbData->Thumb_Size_Y;
2331 int div_factor = std::min(divx, divy);
2333 double pixx_test, pixy_test;
2338 tvp.pix_width = pThumbData->Thumb_Size_X;
2339 tvp.pix_height = pThumbData->Thumb_Size_Y;
2340 tvp.view_scale_ppm = GetPPM() / div_factor;
2344 latlong_to_pix_vp(lat, lon, pixx_test, pixy_test, tvp);
2347 if ((pixx_test != pThumbData->ShipX) || (pixy_test != pThumbData->ShipY)) {
2348 pThumbData->ShipX = pixx_test;
2349 pThumbData->ShipY = pixy_test;
2358static double polytrans(
double *coeff,
double lon,
double lat);
2360int ChartBaseBSB::vp_pix_to_latlong(
ViewPort &vp,
double pixx,
double pixy,
2361 double *plat,
double *plon) {
2362 if (bHaveEmbeddedGeoref) {
2363 double raster_scale = GetPPM() / vp.view_scale_ppm;
2365 double px = pixx * raster_scale + Rsrc.x;
2366 double py = pixy * raster_scale + Rsrc.y;
2370 double lon = polytrans(pwx, px, py);
2371 lon = (lon < 0) ? lon + m_cph : lon - m_cph;
2372 *plon = lon - m_lon_datum_adjust;
2373 *plat = polytrans(pwy, px, py) - m_lat_datum_adjust;
2381 if (m_projection == PROJECTION_TRANSVERSE_MERCATOR) {
2384 double raster_scale = GetPPM() / vp.view_scale_ppm;
2387 double easting, northing;
2388 toTM(vp.clat + m_lat_datum_adjust, vp.clon + m_lon_datum_adjust,
2389 m_proj_lat, m_proj_lon, &easting, &northing);
2390 double xc = polytrans(cPoints.wpx, easting, northing);
2391 double yc = polytrans(cPoints.wpy, easting, northing);
2394 double px = xc + (pixx - (vp.pix_width / 2)) * raster_scale;
2395 double py = yc + (pixy - (vp.pix_height / 2)) * raster_scale;
2398 double east = polytrans(cPoints.pwx, px, py);
2399 double north = polytrans(cPoints.pwy, px, py);
2403 fromTM(east, north, m_proj_lat, m_proj_lon, &lat, &lon);
2407 double slon_p = lon - m_lon_datum_adjust;
2408 double slat_p = lat - m_lat_datum_adjust;
2415 }
else if (m_projection == PROJECTION_MERCATOR) {
2418 double raster_scale = GetPPM() / vp.view_scale_ppm;
2421 double easting, northing;
2422 toSM_ECC(vp.clat + m_lat_datum_adjust, vp.clon + m_lon_datum_adjust,
2423 m_proj_lat, m_proj_lon, &easting, &northing);
2424 double xc = polytrans(cPoints.wpx, easting, northing);
2425 double yc = polytrans(cPoints.wpy, easting, northing);
2428 double px = xc + (pixx - (vp.pix_width / 2)) * raster_scale;
2429 double py = yc + (pixy - (vp.pix_height / 2)) * raster_scale;
2432 double east = polytrans(cPoints.pwx, px, py);
2433 double north = polytrans(cPoints.pwy, px, py);
2437 fromSM_ECC(east, north, m_proj_lat, m_proj_lon, &lat, &lon);
2440 double slon_p = lon - m_lon_datum_adjust;
2441 double slat_p = lat - m_lat_datum_adjust;
2449 }
else if (m_projection == PROJECTION_POLYCONIC) {
2452 double raster_scale = GetPPM() / vp.view_scale_ppm;
2455 double easting, northing;
2456 toPOLY(vp.clat + m_lat_datum_adjust, vp.clon + m_lon_datum_adjust,
2457 m_proj_lat, m_proj_lon, &easting, &northing);
2458 double xc = polytrans(cPoints.wpx, easting, northing);
2459 double yc = polytrans(cPoints.wpy, easting, northing);
2462 double px = xc + (pixx - (vp.pix_width / 2)) * raster_scale;
2463 double py = yc + (pixy - (vp.pix_height / 2)) * raster_scale;
2466 double east = polytrans(cPoints.pwx, px, py);
2467 double north = polytrans(cPoints.pwy, px, py);
2471 fromPOLY(east, north, m_proj_lat, m_proj_lon, &lat, &lon);
2474 double slon_p = lon - m_lon_datum_adjust;
2475 double slat_p = lat - m_lat_datum_adjust;
2482 int dx = pixx - (vp.pix_width / 2);
2483 int dy = (vp.pix_height / 2) - pixy;
2485 xp = (dx * cos(vp.skew)) - (dy * sin(vp.skew));
2486 yp = (dy * cos(vp.skew)) + (dx * sin(vp.skew));
2488 double d_east = xp / vp.view_scale_ppm;
2489 double d_north = yp / vp.view_scale_ppm;
2491 fromSM_ECC(d_east, d_north, vp.clat, vp.clon, &slat, &slon);
2498 else if (slon > 180.)
2506int ChartBaseBSB::latlong_to_pix_vp(
double lat,
double lon,
double &pixx,
2510 if (bHaveEmbeddedGeoref) {
2513 alon = lon + m_lon_datum_adjust;
2514 alat = lat + m_lat_datum_adjust;
2516 AdjustLongitude(alon);
2520 double lonp = (alon < 0) ? alon + m_cph : alon - m_cph;
2521 double xd = polytrans(wpx, lonp, alat);
2522 double yd = polytrans(wpy, lonp, alat);
2524 double raster_scale = GetPPM() / vp.view_scale_ppm;
2526 pixx = (xd - Rsrc.x) / raster_scale;
2527 pixy = (yd - Rsrc.y) / raster_scale;
2532 double easting, northing;
2554 if (m_projection == PROJECTION_TRANSVERSE_MERCATOR) {
2557 alon = lon + m_lon_datum_adjust;
2558 alat = lat + m_lat_datum_adjust;
2561 toTM(alat, alon, m_proj_lat, m_proj_lon, &easting, &northing);
2564 double xd = polytrans(cPoints.wpx, easting, northing);
2565 double yd = polytrans(cPoints.wpy, easting, northing);
2568 toTM(vp.clat + m_lat_datum_adjust, vp.clon + m_lon_datum_adjust,
2569 m_proj_lat, m_proj_lon, &easting, &northing);
2570 double xc = polytrans(cPoints.wpx, easting, northing);
2571 double yc = polytrans(cPoints.wpy, easting, northing);
2574 double raster_scale = GetPPM() / vp.view_scale_ppm;
2576 double xs = xc - vp.pix_width * raster_scale / 2;
2577 double ys = yc - vp.pix_height * raster_scale / 2;
2579 pixx = (xd - xs) / raster_scale;
2580 pixy = (yd - ys) / raster_scale;
2582 }
else if (m_projection == PROJECTION_MERCATOR) {
2585 alon = lon + m_lon_datum_adjust;
2586 alat = lat + m_lat_datum_adjust;
2590 AdjustLongitude(xlon);
2591 toSM_ECC(alat, xlon, m_proj_lat, m_proj_lon, &easting, &northing);
2594 double xd = polytrans(cPoints.wpx, easting, northing);
2595 double yd = polytrans(cPoints.wpy, easting, northing);
2598 double xlonc = vp.clon;
2599 AdjustLongitude(xlonc);
2601 toSM_ECC(vp.clat + m_lat_datum_adjust, xlonc + m_lon_datum_adjust,
2602 m_proj_lat, m_proj_lon, &easting, &northing);
2603 double xc = polytrans(cPoints.wpx, easting, northing);
2604 double yc = polytrans(cPoints.wpy, easting, northing);
2607 double raster_scale = GetPPM() / vp.view_scale_ppm;
2609 double xs = xc - vp.pix_width * raster_scale / 2;
2610 double ys = yc - vp.pix_height * raster_scale / 2;
2612 pixx = (xd - xs) / raster_scale;
2613 pixy = (yd - ys) / raster_scale;
2615 }
else if (m_projection == PROJECTION_POLYCONIC) {
2618 alon = lon + m_lon_datum_adjust;
2619 alat = lat + m_lat_datum_adjust;
2622 xlon = AdjustLongitude(alon);
2623 toPOLY(alat, xlon, m_proj_lat, m_proj_lon, &easting, &northing);
2626 double xd = polytrans(cPoints.wpx, easting, northing);
2627 double yd = polytrans(cPoints.wpy, easting, northing);
2630 double xlonc = AdjustLongitude(vp.clon);
2632 toPOLY(vp.clat + m_lat_datum_adjust, xlonc + m_lon_datum_adjust,
2633 m_proj_lat, m_proj_lon, &easting, &northing);
2634 double xc = polytrans(cPoints.wpx, easting, northing);
2635 double yc = polytrans(cPoints.wpy, easting, northing);
2638 double raster_scale = GetPPM() / vp.view_scale_ppm;
2640 double xs = xc - vp.pix_width * raster_scale / 2;
2641 double ys = yc - vp.pix_height * raster_scale / 2;
2643 pixx = (xd - xs) / raster_scale;
2644 pixy = (yd - ys) / raster_scale;
2647 toSM_ECC(lat, xlon, vp.clat, vp.clon, &easting, &northing);
2649 double epix = easting * vp.view_scale_ppm;
2650 double npix = northing * vp.view_scale_ppm;
2652 double dx = epix * cos(vp.skew) + npix * sin(vp.skew);
2653 double dy = npix * cos(vp.skew) - epix * sin(vp.skew);
2655 pixx = ((double)vp.pix_width / 2) + dx;
2656 pixy = ((double)vp.pix_height / 2) - dy;
2664void ChartBaseBSB::latlong_to_chartpix(
double lat,
double lon,
double &pixx,
2670 if (bHaveEmbeddedGeoref) {
2673 alon = lon + m_lon_datum_adjust;
2674 alat = lat + m_lat_datum_adjust;
2676 alon = AdjustLongitude(alon);
2679 double lonp = (alon < 0) ? alon + m_cph : alon - m_cph;
2680 pixx = polytrans(wpx, lonp, alat);
2681 pixy = polytrans(wpy, lonp, alat);
2683 double easting, northing;
2686 if (m_projection == PROJECTION_TRANSVERSE_MERCATOR) {
2689 alon = lon + m_lon_datum_adjust;
2690 alat = lat + m_lat_datum_adjust;
2693 toTM(alat, alon, m_proj_lat, m_proj_lon, &easting, &northing);
2696 pixx = polytrans(cPoints.wpx, easting, northing);
2697 pixy = polytrans(cPoints.wpy, easting, northing);
2699 }
else if (m_projection == PROJECTION_MERCATOR) {
2702 alon = lon + m_lon_datum_adjust;
2703 alat = lat + m_lat_datum_adjust;
2706 xlon = AdjustLongitude(alon);
2708 toSM_ECC(alat, xlon, m_proj_lat, m_proj_lon, &easting, &northing);
2711 pixx = polytrans(cPoints.wpx, easting, northing);
2712 pixy = polytrans(cPoints.wpy, easting, northing);
2714 }
else if (m_projection == PROJECTION_POLYCONIC) {
2717 alon = lon + m_lon_datum_adjust;
2718 alat = lat + m_lat_datum_adjust;
2721 xlon = AdjustLongitude(alon);
2722 toPOLY(alat, xlon, m_proj_lat, m_proj_lon, &easting, &northing);
2725 pixx = polytrans(cPoints.wpx, easting, northing);
2726 pixy = polytrans(cPoints.wpy, easting, northing);
2731void ChartBaseBSB::chartpix_to_latlong(
double pixx,
double pixy,
double *plat,
2733 if (bHaveEmbeddedGeoref) {
2734 double lon = polytrans(pwx, pixx, pixy);
2735 lon = (lon < 0) ? lon + m_cph : lon - m_cph;
2736 *plon = lon - m_lon_datum_adjust;
2737 *plat = polytrans(pwy, pixx, pixy) - m_lat_datum_adjust;
2740 if (m_projection == PROJECTION_TRANSVERSE_MERCATOR) {
2744 double east = polytrans(cPoints.pwx, pixx, pixy);
2745 double north = polytrans(cPoints.pwy, pixx, pixy);
2749 fromTM(east, north, m_proj_lat, m_proj_lon, &lat, &lon);
2753 slon = lon - m_lon_datum_adjust;
2754 slat = lat - m_lat_datum_adjust;
2756 }
else if (m_projection == PROJECTION_MERCATOR) {
2759 double east = polytrans(cPoints.pwx, pixx, pixy);
2760 double north = polytrans(cPoints.pwy, pixx, pixy);
2764 fromSM_ECC(east, north, m_proj_lat, m_proj_lon, &lat, &lon);
2767 slon = lon - m_lon_datum_adjust;
2768 slat = lat - m_lat_datum_adjust;
2769 }
else if (m_projection == PROJECTION_POLYCONIC) {
2772 double east = polytrans(cPoints.pwx, pixx, pixy);
2773 double north = polytrans(cPoints.pwy, pixx, pixy);
2777 fromPOLY(east, north, m_proj_lat, m_proj_lon, &lat, &lon);
2780 slon = lon - m_lon_datum_adjust;
2781 slat = lat - m_lat_datum_adjust;
2792 else if (slon > 180.)
2798void ChartBaseBSB::ComputeSourceRectangle(
const ViewPort &vp,
2799 wxRect *pSourceRect) {
2800 m_raster_scale_factor = GetRasterScaleFactor(vp);
2802 latlong_to_chartpix(vp.clat, vp.clon, xd, yd);
2804 wxRealPoint pos, size;
2806 pos.x = xd - (vp.pix_width * m_raster_scale_factor / 2);
2807 pos.y = yd - (vp.pix_height * m_raster_scale_factor / 2);
2809 size.x = vp.pix_width * m_raster_scale_factor;
2810 size.y = vp.pix_height * m_raster_scale_factor;
2813 wxRect(wxRound(pos.x), wxRound(pos.y), wxRound(size.x), wxRound(size.y));
2816double ChartBaseBSB::GetRasterScaleFactor(
const ViewPort &vp) {
2819 return (wxRound(100000 * GetPPM() / vp.view_scale_ppm)) / 100000.;
2822void ChartBaseBSB::SetVPRasterParms(
const ViewPort &vpt) {
2826 if (m_datum_index == DATUM_INDEX_WGS84 ||
2827 m_datum_index == DATUM_INDEX_UNKNOWN) {
2828 m_lon_datum_adjust = (-m_dtm_lon) / 3600.;
2829 m_lat_datum_adjust = (-m_dtm_lat) / 3600.;
2833 double to_lat, to_lon;
2834 MolodenskyTransform(vpt.clat, vpt.clon, &to_lat, &to_lon, m_datum_index,
2836 m_lon_datum_adjust = -(to_lon - vpt.clon);
2837 m_lat_datum_adjust = -(to_lat - vpt.clat);
2838 if (m_b_apply_dtm) {
2839 m_lon_datum_adjust -= m_dtm_lon / 3600.;
2840 m_lat_datum_adjust -= m_dtm_lat / 3600.;
2844 ComputeSourceRectangle(vpt, &Rsrc);
2846 if (vpt.IsValid()) m_vp_render_last = vpt;
2850 bool bInside = G_FloatPtInPolygon((
MyFlPoint *)GetCOVRTableHead(0),
2851 GetCOVRTablenPoints(0), vp_proposed.clon,
2853 if (!bInside)
return false;
2856 double binary_scale_factor = GetPPM() / vp_proposed.view_scale_ppm;
2858 if (vp_last.IsValid()) {
2864 if (cached_image_ok && (binary_scale_factor > 1.0) &&
2865 (fabs(binary_scale_factor - wxRound(binary_scale_factor)) < 1e-5)) {
2867 printf(
" Possible Adjust VP for integer scale: %g\n",
2868 binary_scale_factor);
2871 ComputeSourceRectangle(vp_proposed, &rprop);
2874 double lon_adj, lat_adj;
2875 latlong_to_pix_vp(vp_proposed.clat, vp_proposed.clon, pixx, pixy,
2877 vp_pix_to_latlong(vp_proposed, pixx, pixy, &lat_adj, &lon_adj);
2879 vp_proposed.clat = lat_adj;
2880 vp_proposed.clon = lon_adj;
2885 return (ret_val > 0);
2888bool ChartBaseBSB::IsRenderCacheable(wxRect &source, wxRect &dest) {
2889 double scale_x = (double)source.width / (
double)dest.width;
2898 if ((fabs(scale_x - wxRound(scale_x))) > .0001) {
2905 if ((
int)(source.width / dest.width) != (
int)wxRound(scale_x)) {
2914void ChartBaseBSB::GetValidCanvasRegion(
const ViewPort &VPoint,
2916 SetVPRasterParms(VPoint);
2918 double raster_scale = VPoint.view_scale_ppm / GetPPM();
2923 rxl = wxMax(-Rsrc.x * raster_scale, VPoint.rv_rect.x);
2924 rxr = wxMin((Size_X - Rsrc.x) * raster_scale,
2925 VPoint.rv_rect.width + VPoint.rv_rect.x);
2927 ryt = wxMax(-Rsrc.y * raster_scale, VPoint.rv_rect.y);
2928 ryb = wxMin((Size_Y - Rsrc.y) * raster_scale,
2929 VPoint.rv_rect.height + VPoint.rv_rect.y);
2931 pValidRegion->Clear();
2932 pValidRegion->Union(rxl, ryt, rxr - rxl, ryb - ryt);
2935LLRegion ChartBaseBSB::GetValidRegion() {
2938 chartpix_to_latlong(0, 0, ll + 0, ll + 1);
2939 chartpix_to_latlong(0, Size_Y, ll + 2, ll + 3);
2940 chartpix_to_latlong(Size_X, Size_Y, ll + 4, ll + 5);
2941 chartpix_to_latlong(Size_X, 0, ll + 6, ll + 7);
2945 for (
int i = 1; i < 6; i += 2)
2946 if (fabs(ll[i] - ll[i + 2]) > 180) {
2948 for (
int i = 1; i < 8; i += 2)
2949 if (ll[i] < 0) ll[i] += 360;
2953 return LLRegion(4, ll);
2956bool ChartBaseBSB::GetViewUsingCache(wxRect &source, wxRect &dest,
2958 ScaleTypeEnum scale_type) {
2960 ScaleTypeEnum scale_type_corrected;
2962 if (m_b_cdebug) printf(
" source: %d %d\n", source.x, source.y);
2963 if (m_b_cdebug) printf(
" cache: %d %d\n", cache_rect.x, cache_rect.y);
2966 if ((source == cache_rect) &&
2967 (cached_image_ok)) {
2968 if (m_b_cdebug) printf(
" GVUC: Cache is good, nothing to do\n");
2972 double scale_x = (double)source.width / (
double)dest.width;
2974 if (m_b_cdebug) printf(
"GVUC: scale_x: %g\n", scale_x);
2977 scale_type_corrected = scale_type;
2978 if (scale_x > m_bilinear_limit) scale_type_corrected = RENDER_LODEF;
2986 if ((fabs(scale_x - wxRound(scale_x))) > .0001) {
2987 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: Not digital scale test 1\n");
2988 return GetView(source, dest, scale_type_corrected);
2993 if (!cached_image_ok) {
2994 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: Cache NOk\n");
2995 return GetView(source, dest, scale_type_corrected);
3000 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: Overzoom\n");
3001 return GetView(source, dest, scale_type_corrected);
3005 if ((
int)(source.width / dest.width) != (
int)wxRound(scale_x)) {
3006 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: Not digital scale test 2\n");
3007 return GetView(source, dest, scale_type_corrected);
3011 int cs1d = source.width / dest.width;
3012 if (abs(source.x - cache_rect.x) % cs1d) {
3014 printf(
" source.x: %d cache_rect.x: %d cs1d: %d\n", source.x,
3015 cache_rect.x, cs1d);
3016 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: x mismatch\n");
3017 return GetView(source, dest, scale_type_corrected);
3019 if (abs(source.y - cache_rect.y) % cs1d) {
3020 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: y mismatch\n");
3021 return GetView(source, dest, scale_type_corrected);
3024 if (pPixCache && ((pPixCache->GetWidth() != dest.width) ||
3025 (pPixCache->GetHeight() != dest.height))) {
3026 if (m_b_cdebug) printf(
" MISS<<<>>>GVUC: dest size mismatch\n");
3027 return GetView(source, dest, scale_type_corrected);
3031 (source.y + source.height) - (cache_rect.y + cache_rect.height);
3032 int scaled_stride_rows = (int)(stride_rows / scale_x);
3034 if (abs(stride_rows) >= source.height)
3035 return GetView(source, dest, scale_type_corrected);
3038 (source.x + source.width) - (cache_rect.x + cache_rect.width);
3039 int scaled_stride_pixels = (int)(stride_pixels / scale_x);
3041 if (abs(stride_pixels) >= source.width)
3042 return GetView(source, dest, scale_type_corrected);
3044 if (m_b_cdebug) printf(
" GVUC Using raster data cache\n");
3046 ScaleTypeEnum pan_scale_type_x = scale_type_corrected;
3047 ScaleTypeEnum pan_scale_type_y = scale_type_corrected;
3051 int height = pPixCache->GetHeight();
3052 int width = pPixCache->GetWidth();
3053 int buffer_stride_bytes = pPixCache->GetLinePitch();
3058 if (stride_rows > 0)
3060 ps = pPixCache->GetpData() +
3061 (abs(scaled_stride_rows) * buffer_stride_bytes);
3062 if (stride_pixels > 0) ps += scaled_stride_pixels * BPP / 8;
3064 pd = pPixCache->GetpData();
3065 if (stride_pixels <= 0) pd += abs(scaled_stride_pixels) * BPP / 8;
3067 for (
int iy = 0; iy < (height - abs(scaled_stride_rows)); iy++) {
3068 memmove(pd, ps, (width - abs(scaled_stride_pixels)) * BPP / 8);
3069 ps += buffer_stride_bytes;
3070 pd += buffer_stride_bytes;
3074 ps = pPixCache->GetpData() +
3075 ((height - abs(scaled_stride_rows) - 1) * buffer_stride_bytes);
3076 if (stride_pixels > 0)
3077 ps += scaled_stride_pixels * BPP / 8;
3079 pd = pPixCache->GetpData() + ((height - 1) * buffer_stride_bytes);
3080 if (stride_pixels <= 0)
3081 pd += abs(scaled_stride_pixels) * BPP / 8;
3083 for (
int iy = 0; iy < (height - abs(scaled_stride_rows)); iy++) {
3084 memmove(pd, ps, (width - abs(scaled_stride_pixels)) * BPP / 8);
3085 ps -= buffer_stride_bytes;
3086 pd -= buffer_stride_bytes;
3091 if (source.y != cache_rect.y) {
3092 wxRect sub_dest = dest;
3093 sub_dest.height = abs(scaled_stride_rows);
3095 if (stride_rows > 0)
3097 sub_dest.y = height - scaled_stride_rows;
3108 wxRegionContain rc = Region.Contains(sub_dest);
3109 if ((wxPartRegion == rc) || (wxInRegion == rc)) {
3110 GetAndScaleData(pPixCache->GetpData(), pPixCache->GetLength(), source,
3111 source.width, sub_dest, width, cs1d, pan_scale_type_y);
3113 pPixCache->Update();
3117 cache_rect.y = source.y;
3119 cache_rect_scaled = dest;
3120 cached_image_ok = 1;
3125 if (source.x != cache_rect.x) {
3126 wxRect sub_dest = dest;
3127 sub_dest.width = abs(scaled_stride_pixels);
3129 if (stride_pixels > 0)
3131 sub_dest.x = width - scaled_stride_pixels;
3142 wxRegionContain rc = Region.Contains(sub_dest);
3143 if ((wxPartRegion == rc) || (wxInRegion == rc)) {
3144 GetAndScaleData(pPixCache->GetpData(), pPixCache->GetLength(), source,
3145 source.width, sub_dest, width, cs1d, pan_scale_type_x);
3148 pPixCache->Update();
3151 cache_rect = source;
3152 cache_rect_scaled = dest;
3153 cached_image_ok = 1;
3164bool ChartBaseBSB::RenderViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint) {
3165 SetVPRasterParms(VPoint);
3167 OCPNRegion rgn(0, 0, VPoint.pix_width, VPoint.pix_height);
3169 bool bsame_region = (rgn == m_last_region);
3171 if (!bsame_region) cached_image_ok =
false;
3173 m_last_region = rgn;
3175 return RenderRegionViewOnDC(dc, VPoint, rgn);
3178bool ChartBaseBSB::RenderRegionViewOnGL(
const wxGLContext &glc,
3181 const LLRegion &Region) {
3185bool ChartBaseBSB::RenderRegionViewOnDC(wxMemoryDC &dc,
const ViewPort &VPoint,
3187 SetVPRasterParms(VPoint);
3189 wxRect dest(0, 0, VPoint.pix_width, VPoint.pix_height);
3191 double factor = GetRasterScaleFactor(VPoint);
3193 printf(
"%d RenderRegion ScaleType: %d factor: %g\n", s_dc++,
3194 RENDER_HIDEF, factor);
3195 printf(
"Rect list:\n");
3197 while (upd.HaveRects()) {
3198 wxRect rect = upd.GetRect();
3199 printf(
" %d %d %d %d\n", rect.x, rect.y, rect.width, rect.height);
3206 if ((fabs(m_cached_scale_ppm - VPoint.view_scale_ppm) > 1e-9) ||
3207 (m_last_vprect != dest)) {
3208 cached_image_ok =
false;
3209 m_vp_render_last.Invalidate();
3225 m_cached_scale_ppm = VPoint.view_scale_ppm;
3226 m_last_vprect = dest;
3228 if (cached_image_ok) {
3230 bool bsame_region = (Region == m_last_region);
3232 if ((bsame_region) && (Rsrc == cache_rect)) {
3233 pPixCache->SelectIntoDC(dc);
3234 if (m_b_cdebug) printf(
" Using Current PixelCache\n");
3239 m_last_region = Region;
3260 while (upd.HaveRects()) {
3265 if ((!IsRenderCacheable(Rsrc, dest) && (n_rect > 4) && (n_rect < 20)) ||
3268 printf(
" RenderRegion by rect iterator n_rect: %d\n", n_rect);
3272 wxRect dest_check_rect = dest;
3274 while (upd_check.HaveRects()) {
3275 wxRect rect = upd_check.GetRect();
3276 dest_check_rect.Union(rect);
3277 upd_check.NextRect();
3281 if ((pPixCache->GetWidth() != dest_check_rect.width) ||
3282 (pPixCache->GetHeight() != dest_check_rect.height)) {
3285 new PixelCache(dest_check_rect.width, dest_check_rect.height, BPP);
3289 new PixelCache(dest_check_rect.width, dest_check_rect.height, BPP);
3291 ScaleTypeEnum ren_type = RENDER_LODEF;
3297 while (upd.HaveRects()) {
3298 wxRect rect = upd.GetRect();
3303 if (rect.y < 0) rect.Offset(0, -rect.y);
3304 if (rect.x < 0) rect.Offset(-rect.x, 0);
3306 GetAndScaleData(pPixCache->GetpData(), pPixCache->GetLength(), Rsrc,
3307 Rsrc.width, rect, pPixCache->GetWidth(), factor,
3315 pPixCache->Update();
3319 cache_scale_method = ren_type;
3320 cached_image_ok =
false;
3323 pPixCache->SelectIntoDC(dc);
3331 if ((pPixCache->GetWidth() != dest.width) ||
3332 (pPixCache->GetHeight() != dest.height)) {
3334 pPixCache =
new PixelCache(dest.width, dest.height, BPP);
3337 pPixCache =
new PixelCache(dest.width, dest.height, BPP);
3339 if (m_b_cdebug) printf(
" Render Region By GVUC\n");
3342 ScaleTypeEnum scale_type_zoom = RENDER_HIDEF;
3343 double binary_scale_factor = VPoint.view_scale_ppm / GetPPM();
3344 if (binary_scale_factor < .20) scale_type_zoom = RENDER_LODEF;
3346 bool bnewview = GetViewUsingCache(Rsrc, dest, Region, scale_type_zoom);
3349 pPixCache->SelectIntoDC(dc);
3354wxImage *ChartBaseBSB::GetImage() {
3355 int img_size_x = ((Size_X >> 2) * 4) + 4;
3356 wxImage *img =
new wxImage(img_size_x, Size_Y,
false);
3358 unsigned char *ppnx = img->GetData();
3360 for (
int i = 0; i < Size_Y; i++) {
3361 wxRect source_rect(0, i, Size_X, 1);
3362 wxRect dest_rect(0, 0, Size_X, 1);
3364 GetAndScaleData(img->GetData(), img_size_x * Size_Y * 3, source_rect,
3365 Size_X, dest_rect, Size_X, 1.0, RENDER_HIDEF);
3367 ppnx += img_size_x * 3;
3373bool ChartBaseBSB::GetView(wxRect &source, wxRect &dest,
3374 ScaleTypeEnum scale_type) {
3375 assert(pPixCache != 0);
3381 double factor = ((double)source.width) / ((double)dest.width);
3396 GetAndScaleData(pPixCache->GetpData(), pPixCache->GetLength(), source,
3397 source.width, dest, dest.width, factor, scale_type);
3398 pPixCache->Update();
3402 cache_rect = source;
3403 cache_rect_scaled = dest;
3404 cache_scale_method = scale_type;
3406 cached_image_ok = 1;
3411bool ChartBaseBSB::GetAndScaleData(
unsigned char *ppn,
size_t data_size,
3412 wxRect &source,
int source_stride,
3413 wxRect &dest,
int dest_stride,
3414 double scale_factor,
3415 ScaleTypeEnum scale_type) {
3416 unsigned char *s_data = NULL;
3418 double factor = scale_factor;
3419 int Factor = (int)factor;
3421 int target_width = (int)wxRound((
double)source.width / factor);
3422 int target_height = (int)wxRound((
double)source.height / factor);
3424 int dest_line_length = dest_stride * BPP / 8;
3428#ifdef __PIX_CACHE_DIBSECTION__
3429 dest_line_length = (((dest_stride * 24) + 31) & ~31) >> 3;
3432 if ((target_height == 0) || (target_width == 0))
return false;
3436 unsigned char *
volatile target_data = ppn;
3437 unsigned char *data = ppn;
3441 if (scale_type == RENDER_HIDEF) {
3443 int blur_factor = wxMax(2, Factor);
3444 int wb_size = (source.width) * (blur_factor * 2) * BPP / 8;
3445 s_data = (
unsigned char *)malloc(wb_size);
3446 unsigned char *pixel;
3449 for (
int y = dest.y; y < (dest.y + dest.height); y++) {
3454 s1.y = source.y + (int)(y * factor);
3455 s1.width = source.width;
3456 s1.height = blur_factor;
3457 GetChartBits(s1, s_data, 1);
3459 target_data = data + (y * dest_line_length );
3461 for (
int x = 0; x < target_width; x++) {
3462 unsigned int avgRed = 0;
3463 unsigned int avgGreen = 0;
3464 unsigned int avgBlue = 0;
3465 unsigned int pixel_count = 0;
3466 unsigned char *pix0 = s_data + BPP / 8 * ((int)(x * factor));
3469 if ((x * Factor) < (Size_X - source.x)) {
3471 for (
int y1 = 0; y1 < blur_factor; ++y1) {
3472 pixel = pix0 + (BPP / 8 * y_offset);
3473 for (
int x1 = 0; x1 < blur_factor; ++x1) {
3475 avgGreen += pixel[1];
3476 avgBlue += pixel[2];
3482 y_offset += source.width;
3485 if (0 == pixel_count)
3488 target_data[0] = avgRed / pixel_count;
3489 target_data[1] = avgGreen / pixel_count;
3490 target_data[2] = avgBlue / pixel_count;
3491 target_data += BPP / 8;
3496 target_data += BPP / 8;
3505 else if (scale_type == RENDER_LODEF) {
3506 int get_bits_submap = 1;
3510 if (source.width > 32767)
3513 int wb_size = (Size_X) * (( 1) * 2) * BPP / 8;
3514 s_data = (
unsigned char *)malloc(wb_size);
3516 long x_delta = (source.width << scaler) / target_width;
3517 long y_delta = (source.height << scaler) / target_height;
3520 long ys = dest.y * y_delta;
3522 while (y < dest.y + dest.height) {
3527 s1.y = source.y + (ys >> scaler);
3530 GetChartBits(s1, s_data, get_bits_submap);
3532 target_data = data + (y * dest_line_length ) +
3535 long x = (source.x << scaler) + (dest.x * x_delta);
3536 long sizex16 = Size_X << scaler;
3539 while ((xt < dest.x + dest.width) && (x < 0)) {
3544 target_data += BPP / 8;
3549 while ((xt < dest.x + dest.width) && (x < sizex16)) {
3550 unsigned char *src_pixel = &s_data[(x >> scaler) * BPP / 8];
3552 target_data[0] = src_pixel[0];
3553 target_data[1] = src_pixel[1];
3554 target_data[2] = src_pixel[2];
3556 target_data += BPP / 8;
3561 while (xt < dest.x + dest.width) {
3566 target_data += BPP / 8;
3580 unsigned char *target_line_start = NULL;
3581 unsigned char *target_data_x = NULL;
3585 sigaction(SIGSEGV, NULL,
3588 struct sigaction temp;
3589 sigaction(SIGSEGV, NULL, &temp);
3591 temp.sa_handler = catch_signals_chart;
3592 sigemptyset(&temp.sa_mask);
3597 sigaction(SIGSEGV, &temp, NULL);
3599 if (sigsetjmp(env_chart,
3602 sigaction(SIGSEGV, &sa_all_previous, NULL);
3605 msg.Printf(_T(
" Caught SIGSEGV on GetandScaleData, Factor < 1"));
3609 _T(
" m_raster_scale_factor: %g source.width: %d dest.y: %d ")
3610 _T(
"dest.x: %d dest.width: %d dest.height: %d "),
3611 m_raster_scale_factor, source.width, dest.y, dest.x, dest.width,
3616 _T(
" i: %d j: %d dest_stride: %d target_line_start: %p ")
3617 _T(
"target_data_x: %p y_offset: %d"),
3618 i, j, dest_stride, target_line_start, target_data_x, y_offset);
3631 latlong_to_chartpix(m_vp_render_last.clat, m_vp_render_last.clon, xd, yd);
3633 xd - (m_vp_render_last.pix_width * m_raster_scale_factor / 2);
3635 yd - (m_vp_render_last.pix_height * m_raster_scale_factor / 2);
3636 double x_vernier = (xrd - wxRound(xrd));
3637 double y_vernier = (yrd - wxRound(yrd));
3638 int x_vernier_i = (int)wxRound(x_vernier / m_raster_scale_factor);
3639 int y_vernier_i = (int)wxRound(y_vernier / m_raster_scale_factor);
3644 int sx = wxMax(source.x, 0);
3645 s_data = (
unsigned char *)malloc((sx + source.width + 2) *
3646 (source.height + 2) * BPP / 8);
3648 wxRect vsource = source;
3649 vsource.height += 2;
3654 GetChartBits(vsource, s_data, 1);
3655 unsigned char *source_data = s_data;
3659 while (j < dest.y + dest.height) {
3660 y_offset = (int)((j - y_vernier_i) * m_raster_scale_factor) *
3664 target_data + (j * dest_line_length );
3665 target_data_x = target_line_start + ((dest.x) * BPP / 8);
3670 if ((target_data_x + (dest.width * BPP / 8)) >
3671 (target_data + data_size)) {
3672 j = dest.y + dest.height;
3674 while (i < dest.x + dest.width) {
3675 memcpy(target_data_x,
3676 source_data + BPP / 8 *
3677 (y_offset + (
int)((i + x_vernier_i) *
3678 m_raster_scale_factor)),
3681 target_data_x += BPP / 8;
3691 sigaction(SIGSEGV, &sa_all_previous, NULL);
3700bool ChartBaseBSB::GetChartBits(wxRect &source,
unsigned char *pPix,
3702 wxCriticalSectionLocker locker(m_critSect);
3714 while (iy < source.y + source.height) {
3715 if ((iy >= 0) && (iy < Size_Y)) {
3716 if (source.x >= 0) {
3717 if ((source.x + source.width) > Size_X) {
3718 if ((Size_X - source.x) < 0)
3719 memset(pCP, FILL_BYTE, source.width * BPP / 8);
3721 BSBGetScanline(pCP, iy, source.x, Size_X, sub_samp);
3722 memset(pCP + (Size_X - source.x) * BPP / 8, FILL_BYTE,
3723 (source.x + source.width - Size_X) * BPP / 8);
3726 BSBGetScanline(pCP, iy, source.x, source.x + source.width, sub_samp);
3728 if ((source.width + source.x) >= 0) {
3732 int xfill_corrected = -source.x + (source.x % sub_samp);
3733 memset(pCP, FILL_BYTE, (xfill_corrected * BPP / 8));
3734 BSBGetScanline(pCP + (xfill_corrected * BPP / 8), iy, 0,
3735 source.width + source.x, sub_samp);
3738 memset(pCP, FILL_BYTE, source.width * BPP / 8);
3745 memset(pCP, FILL_BYTE, source.width * BPP / 8);
3748 pCP += source.width * BPP / 8 * sub_samp;
3766int ChartBaseBSB::ReadBSBHdrLine(wxInputStream *ifs,
char *buf,
int buf_len_max)
3771 int line_length = 0;
3776 while (!ifs->Eof() && line_length < buf_len_max) {
3777 int c = ifs->GetC();
3780 if (0x1A == read_char) {
3781 ifs->Ungetch(read_char);
3789 if (read_char == 10 || read_char == 13) {
3791 cr_test = ifs->GetC();
3792 if (cr_test == 13) cr_test = ifs->GetC();
3794 if (cr_test != 10 && cr_test != 13) ifs->Ungetch(cr_test);
3799 if (read_char ==
'\n') {
3801 cr_test = ifs->GetC();
3803 if (cr_test !=
' ') {
3804 ifs->Ungetch(cr_test);
3810 while (cr_test ==
' ') cr_test = ifs->GetC();
3811 ifs->Ungetch(cr_test);
3827 if (line_length) *(lbuf - 1) =
'\0';
3836int ChartBaseBSB::BSBScanScanline(wxInputStream *pinStream) {
3837 int nLineMarker, nValueShift, iPixel = 0;
3838 unsigned char byValueMask, byCountMask;
3839 unsigned char byNext;
3847 byNext = pinStream->GetC();
3848 nLineMarker = nLineMarker * 128 + (byNext & 0x7f);
3849 }
while ((byNext & 0x80) != 0);
3852 nValueShift = 7 - nColorSize;
3853 byValueMask = (((1 << nColorSize)) - 1) << nValueShift;
3854 byCountMask = (1 << (7 - nColorSize)) - 1;
3858 while (((byNext = pinStream->GetC()) != 0) && (iPixel < Size_X)) {
3863 nRunCount = byNext & byCountMask;
3865 while ((byNext & 0x80) != 0) {
3866 byNext = pinStream->GetC();
3867 nRunCount = nRunCount * 128 + (byNext & 0x7f);
3870 if (iPixel + nRunCount + 1 > Size_X) nRunCount = Size_X - iPixel - 1;
3875 iPixel += nRunCount + 1;
3877 coffset = pinStream->TellI();
3887inline void memset_short(
unsigned char *dst,
unsigned char cbyte,
int count) {
3899 memset(dst, cbyte, count);
3904#define TILE_SIZE 512
3913 void Reset() { clock_gettime(CLOCK_REALTIME, &tp); }
3917 clock_gettime(CLOCK_REALTIME, &tp_end);
3918 return (tp_end.tv_sec - tp.tv_sec) * 1.e3 +
3919 (tp_end.tv_nsec - tp.tv_nsec) / 1.e6;
3929 free(pt->pTileOffset); \
3930 pt->pTileOffset = NULL; \
3933 pt->bValid = false; \
3940int ChartBaseBSB::BSBGetScanline(
unsigned char *pLineBuf,
int y,
int xs,
int xl,
3944 unsigned char *prgb = pLineBuf;
3946 unsigned char byValueMask, byCountMask;
3947 unsigned char byNext;
3954 if (bUseLineCache && pLineCache) {
3956 pt = &pLineCache[y];
3964 static double ttime;
3971 int thisline_size = pline_table[y + 1] - pline_table[y];
3974 pt->pPix = (
unsigned char *)malloc(Size_X);
3978 pt->pPix = (
unsigned char *)malloc(thisline_size);
3980 if (pline_table[y] == 0 || pline_table[y + 1] == 0) FAIL;
3985 if (ifs_bitmap->TellI() != pline_table[y] &&
3986 wxInvalidOffset == ifs_bitmap->SeekI(pline_table[y], wxFromStart))
3990 if (thisline_size > ifs_bufsize) {
3991 unsigned char *tmp = ifs_buf;
3992 if (!(ifs_buf = (
unsigned char *)realloc(ifs_buf, thisline_size))) {
3996 ifs_bufsize = thisline_size;
4003 ifs_bitmap->Read(lp, thisline_size);
4008 if (!bUseLineCache) {
4012 while ((byNext & 0x80) != 0);
4017 if (Size_X > ifs_bufsize) {
4018 unsigned char *tmp = ifs_buf;
4019 if (!(ifs_buf = (
unsigned char *)realloc(ifs_buf, Size_X))) {
4023 ifs_bufsize = Size_X;
4031 while ((byNext & 0x80) != 0);
4034 nValueShift = 7 - nColorSize;
4035 byValueMask = (((1 << nColorSize)) - 1) << nValueShift;
4036 byCountMask = (1 << (7 - nColorSize)) - 1;
4039 unsigned int iPixel = 0;
4041#ifndef USE_OLD_CACHE
4042 pt->pTileOffset[0].offset = lp - pt->pPix;
4043 pt->pTileOffset[0].pixel = 0;
4044 unsigned int tileindex = 1, nextTile = TILE_SIZE;
4046 unsigned int nRunCount;
4047 unsigned char *end = pt->pPix + thisline_size;
4048 while (iPixel < (
unsigned int)Size_X)
4051 nPixValue = (byNext & byValueMask) >> nValueShift;
4053 nRunCount = byNext & byCountMask;
4055 while ((byNext & 0x80) != 0) {
4057 nRunCount = nRunCount * 128 + (byNext & 0x7f);
4062 if (iPixel + nRunCount >
4063 (
unsigned int)Size_X)
4064 nRunCount = nRunCount - iPixel;
4067 memset_short(pCL + iPixel, nPixValue, nRunCount);
4068 iPixel += nRunCount;
4074 unsigned char *offset = lp - 1;
4075 if (byNext == 0 || lp == end) {
4077 while (tileindex < (
unsigned int)Size_X / TILE_SIZE + 1) {
4078 pt->pTileOffset[tileindex].offset = pt->pTileOffset[0].offset;
4079 pt->pTileOffset[tileindex].pixel = 0;
4085 nRunCount = byNext & byCountMask;
4087 while ((byNext & 0x80) != 0) {
4089 nRunCount = nRunCount * 128 + (byNext & 0x7f);
4094 if (iPixel + nRunCount >
4095 (
unsigned int)Size_X)
4096 nRunCount = Size_X - iPixel;
4098 while (iPixel + nRunCount > nextTile) {
4099 pt->pTileOffset[tileindex].offset = offset - pt->pPix;
4100 pt->pTileOffset[tileindex].pixel = iPixel;
4102 nextTile += TILE_SIZE;
4104 iPixel += nRunCount;
4113 if (xl > Size_X) xl = Size_X;
4116 pCL = pt->pPix + xs;
4119 if ((BPP == 24) && (1 == sub_samp)) {
4121 while (ix < xl - 1) {
4122 unsigned char cur_by = *pCL;
4123 rgbval = (int)(pPalette[cur_by]);
4124 while ((ix < xl - 1)) {
4125 if (cur_by != *pCL)
break;
4126 *((
int *)prgb) = rgbval;
4133 int dest_inc_val_bytes = (BPP / 8) * sub_samp;
4135 while (ix < xl - 1) {
4136 unsigned char cur_by = *pCL;
4137 rgbval = (int)(pPalette[cur_by]);
4138 while ((ix < xl - 1)) {
4139 if (cur_by != *pCL)
break;
4140 *((
int *)prgb) = rgbval;
4141 prgb += dest_inc_val_bytes;
4152 unsigned char *pCLast = pt->pPix + (xl - 1);
4153 unsigned char *prgb_last = pLineBuf + ((xl - 1) - xs) * BPP / 8;
4155 rgbval = (int)(pPalette[*pCLast]);
4156 unsigned char a = rgbval & 0xff;
4158 a = (rgbval >> 8) & 0xff;
4160 a = (rgbval >> 16) & 0xff;
4165 int tileindex = xs / TILE_SIZE;
4166 int tileoffset = pt->pTileOffset[tileindex].offset;
4168 lp = pt->pPix + tileoffset;
4169 ix = pt->pTileOffset[tileindex].pixel;
4173 nValueShift = 7 - nColorSize;
4174 byValueMask = (((1 << nColorSize)) - 1) << nValueShift;
4175 byCountMask = (1 << (7 - nColorSize)) - 1;
4177 bool bLastPixValueValid =
false;
4179 while (ix < xl - 1) {
4182 nPixValue = (byNext & byValueMask) >> nValueShift;
4183 unsigned int nRunCount;
4186 nRunCount = xl - ix;
4188 nRunCount = byNext & byCountMask;
4189 while ((byNext & 0x80) != 0) {
4191 nRunCount = nRunCount * 128 + (byNext & 0x7f);
4198 if (ix + nRunCount <= (
unsigned int)xs) {
4202 nRunCount -= xs - ix;
4206 if (ix + nRunCount >= (
unsigned int)xl) {
4207 nRunCount = xl - 1 - ix;
4208 bLastPixValueValid =
true;
4211 rgbval = (int)(pPalette[nPixValue]);
4217 int count = nRunCount;
4221 *(uint32_t *)prgb = rgbval;
4224 }
else if (rgbval == 0 || rgbval == 0xffffff) {
4226 memset(prgb, rgbval, nRunCount * 3);
4227 prgb += nRunCount * 3;
4241 if ((
long)prgb & 7) {
4243 *(uint32_t *)prgb = rgbval;
4245 if (!((
long)prgb & 7)) {
4246 if (count >= 8)
break;
4253 uint64_t *b = (uint64_t *)prgb;
4254 for (
int i = 0; i < 8; i++) {
4255 *(uint32_t *)prgb = rgbval;
4261 uint64_t *y = (uint64_t *)prgb;
4262 int count_d8 = count >> 3;
4263 prgb += 24 * count_d8;
4264 while (count_d8--) {
4271 int rcount = count & 0x7;
4273 *(uint32_t *)prgb = rgbval;
4286 if (!bLastPixValueValid) {
4288 nPixValue = (byNext & byValueMask) >> nValueShift;
4290 rgbval = (int)(pPalette[nPixValue]);
4291 unsigned char a = rgbval & 0xff;
4294 a = (rgbval >> 8) & 0xff;
4296 a = (rgbval >> 16) & 0xff;
4304 if (cnt == 500000) {
4306 printf(
"cache time: %d %f\n", d, ttime / 1000.0);
4313 if (!bUseLineCache) {
4314#ifndef USE_OLD_CACHE
4315 free(pt->pTileOffset);
4323int *ChartBaseBSB::GetPalettePtr(BSB_Color_Capability color_index) {
4324 if (pPalettes[color_index]) {
4325 if (palette_direction == PaletteFwd)
4326 return (
int *)(pPalettes[color_index]->FwdPalette);
4328 return (
int *)(pPalettes[color_index]->RevPalette);
4333PaletteDir ChartBaseBSB::GetPaletteDir(
void) {
4336 RGBO r = pc->GetRGBO();
4345bool ChartBaseBSB::AnalyzeSkew(
void) {
4346 double lonmin = 1000;
4347 double lonmax = -1000;
4348 double latmin = 90.;
4349 double latmax = -90.;
4351 int nlonmin, nlonmax;
4358 for (
int n = 0; n < nRefpoint; n++) {
4360 if (pRefTable[n].lonr > lonmax) {
4361 lonmax = pRefTable[n].lonr;
4364 if (pRefTable[n].lonr < lonmin) {
4365 lonmin = pRefTable[n].lonr;
4370 if (pRefTable[n].latr < latmin) {
4371 latmin = pRefTable[n].latr;
4373 if (pRefTable[n].latr > latmax) {
4374 latmax = pRefTable[n].latr;
4379 if ((lonmin * lonmax) < 0) {
4380 if (pRefTable[nlonmin].xr > pRefTable[nlonmax].xr) {
4382 for (
int n = 0; n < nRefpoint; n++) {
4383 if (pRefTable[n].lonr < 0.0) pRefTable[n].lonr += 360.;
4390 for (
int n = 0; n < nRefpoint; n++) {
4392 if (pRefTable[n].lonr > lonmax) {
4393 lonmax = pRefTable[n].lonr;
4396 if (pRefTable[n].lonr < lonmin) {
4397 lonmin = pRefTable[n].lonr;
4402 if (pRefTable[n].latr < latmin) {
4403 latmin = pRefTable[n].latr;
4405 if (pRefTable[n].latr > latmax) {
4406 latmax = pRefTable[n].latr;
4413 double dist_max = 0.;
4417 for (
int i = 0; i < nRefpoint; i++) {
4418 for (
int j = i + 1; j < nRefpoint; j++) {
4419 double dx = pRefTable[i].xr - pRefTable[j].xr;
4420 double dy = pRefTable[i].yr - pRefTable[j].yr;
4421 double dist = (dx * dx) + (dy * dy);
4422 if (dist > dist_max) {
4430 double apparent_skew = 0;
4432 if (m_projection == PROJECTION_MERCATOR) {
4433 double easting0, easting1, northing0, northing1;
4435 toSM_ECC(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat, m_proj_lon,
4436 &easting0, &northing0);
4437 toSM_ECC(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat, m_proj_lon,
4438 &easting1, &northing1);
4441 atan2((easting1 - easting0), (northing1 - northing0)) * 180. / PI;
4442 double skew_points = atan2((pRefTable[jmax].yr - pRefTable[imax].yr),
4443 (pRefTable[jmax].xr - pRefTable[imax].xr)) *
4446 apparent_skew = skew_points - skew_proj + 90.;
4449 if (fabs(apparent_skew) > 180.) {
4450 if (apparent_skew < 0.)
4451 apparent_skew += 360.;
4453 apparent_skew -= 360.;
4457 else if (m_projection == PROJECTION_TRANSVERSE_MERCATOR) {
4458 double easting0, easting1, northing0, northing1;
4460 toTM(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat, m_proj_lon,
4461 &easting0, &northing0);
4462 toTM(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat, m_proj_lon,
4463 &easting1, &northing1);
4466 atan2((easting1 - easting0), (northing1 - northing0)) * 180. / PI;
4467 double skew_points = atan2((pRefTable[jmax].yr - pRefTable[imax].yr),
4468 (pRefTable[jmax].xr - pRefTable[imax].xr)) *
4471 apparent_skew = skew_points - skew_proj + 90.;
4474 if (fabs(apparent_skew) > 180.) {
4475 if (apparent_skew < 0.)
4476 apparent_skew += 360.;
4478 apparent_skew -= 360.;
4481 if (fabs(apparent_skew - m_Chart_Skew) > 2) {
4484 double dskew = fabs(apparent_skew - m_Chart_Skew);
4485 if ((m_proj_lon < lonmin) || (m_proj_lon > lonmax)) {
4487 double tentative_proj_lon = (lonmin + lonmax) / 2.;
4489 toTM(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat,
4490 tentative_proj_lon, &easting0, &northing0);
4491 toTM(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat,
4492 tentative_proj_lon, &easting1, &northing1);
4495 atan2((easting1 - easting0), (northing1 - northing0)) * 180. / PI;
4496 skew_points = atan2((pRefTable[jmax].yr - pRefTable[imax].yr),
4497 (pRefTable[jmax].xr - pRefTable[imax].xr)) *
4500 apparent_skew = skew_points - skew_proj + 90.;
4503 if (fabs(apparent_skew) > 180.) {
4504 if (apparent_skew < 0.)
4505 apparent_skew += 360.;
4507 apparent_skew -= 360.;
4511 if (fabs(apparent_skew - m_Chart_Skew) < dskew) {
4512 m_proj_lon = tentative_proj_lon;
4518 apparent_skew = m_Chart_Skew;
4520 if (fabs(apparent_skew - m_Chart_Skew) >
4522 m_Chart_Skew = apparent_skew;
4524 wxString msg = _T(
" Warning: Skew override on chart ");
4525 msg.Append(m_FullPath);
4527 msg1.Printf(_T(
" is %5g degrees"), apparent_skew);
4538int ChartBaseBSB::AnalyzeRefpoints(
bool b_testSolution) {
4544 float lonmin = 1000;
4545 float lonmax = -1000;
4547 float latmax = -90.;
4549 int plonmin = 100000;
4551 int platmin = 100000;
4553 int nlonmin = 0, nlonmax = 0;
4558 for (n = 0; n < nRefpoint; n++) {
4560 if (pRefTable[n].lonr > lonmax) {
4561 lonmax = pRefTable[n].lonr;
4562 plonmax = (int)pRefTable[n].xr;
4565 if (pRefTable[n].lonr < lonmin) {
4566 lonmin = pRefTable[n].lonr;
4567 plonmin = (int)pRefTable[n].xr;
4572 if (pRefTable[n].latr < latmin) {
4573 latmin = pRefTable[n].latr;
4574 platmin = (int)pRefTable[n].yr;
4576 if (pRefTable[n].latr > latmax) {
4577 latmax = pRefTable[n].latr;
4578 platmax = (int)pRefTable[n].yr;
4583 if ((lonmin * lonmax) < 0) {
4584 if (pRefTable[nlonmin].xr > pRefTable[nlonmax].xr) {
4586 for (n = 0; n < nRefpoint; n++) {
4587 if (pRefTable[n].lonr < 0.0) pRefTable[n].lonr += 360.;
4594 for (n = 0; n < nRefpoint; n++) {
4596 if (pRefTable[n].lonr > lonmax) {
4597 lonmax = pRefTable[n].lonr;
4598 plonmax = (int)pRefTable[n].xr;
4601 if (pRefTable[n].lonr < lonmin) {
4602 lonmin = pRefTable[n].lonr;
4603 plonmin = (int)pRefTable[n].xr;
4608 if (pRefTable[n].latr < latmin) {
4609 latmin = pRefTable[n].latr;
4610 platmin = (int)pRefTable[n].yr;
4612 if (pRefTable[n].latr > latmax) {
4613 latmax = pRefTable[n].latr;
4614 platmax = (int)pRefTable[n].yr;
4621 cPoints.count = nRefpoint;
4622 if (cPoints.status) {
4635 cPoints.tx = (
double *)malloc(nRefpoint *
sizeof(
double));
4636 cPoints.ty = (
double *)malloc(nRefpoint *
sizeof(
double));
4637 cPoints.lon = (
double *)malloc(nRefpoint *
sizeof(
double));
4638 cPoints.lat = (
double *)malloc(nRefpoint *
sizeof(
double));
4640 cPoints.pwx = (
double *)malloc(12 *
sizeof(
double));
4641 cPoints.wpx = (
double *)malloc(12 *
sizeof(
double));
4642 cPoints.pwy = (
double *)malloc(12 *
sizeof(
double));
4643 cPoints.wpy = (
double *)malloc(12 *
sizeof(
double));
4647 double dist_max = 0.;
4651 for (i = 0; i < nRefpoint; i++) {
4652 for (
int j = i + 1; j < nRefpoint; j++) {
4653 double dx = pRefTable[i].xr - pRefTable[j].xr;
4654 double dy = pRefTable[i].yr - pRefTable[j].yr;
4655 double dist = (dx * dx) + (dy * dy);
4656 if (dist > dist_max) {
4666 if (m_projection == PROJECTION_TRANSVERSE_MERCATOR) {
4667 double easting0, easting1, northing0, northing1;
4669 toTM(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat, m_proj_lon,
4670 &easting0, &northing0);
4671 toTM(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat, m_proj_lon,
4672 &easting1, &northing1);
4675 double dx2 = (pRefTable[jmax].xr - pRefTable[imax].xr) *
4676 (pRefTable[jmax].xr - pRefTable[imax].xr);
4677 double dy2 = (pRefTable[jmax].yr - pRefTable[imax].yr) *
4678 (pRefTable[jmax].yr - pRefTable[imax].yr);
4679 double dn2 = (northing1 - northing0) * (northing1 - northing0);
4680 double de2 = (easting1 - easting0) * (easting1 - easting0);
4682 m_ppm_avg = sqrt(dx2 + dy2) / sqrt(dn2 + de2);
4687 for (
int n = 0; n < nRefpoint; n++) {
4688 double easting, northing;
4689 toTM(pRefTable[n].latr, pRefTable[n].lonr, m_proj_lat, m_proj_lon,
4690 &easting, &northing);
4692 cPoints.tx[n] = pRefTable[n].xr;
4693 cPoints.ty[n] = pRefTable[n].yr;
4694 cPoints.lon[n] = easting;
4695 cPoints.lat[n] = northing;
4699 cPoints.txmax = plonmax;
4700 cPoints.txmin = plonmin;
4701 cPoints.tymax = platmax;
4702 cPoints.tymin = platmin;
4703 toTM(latmax, lonmax, m_proj_lat, m_proj_lon, &cPoints.lonmax,
4705 toTM(latmin, lonmin, m_proj_lat, m_proj_lon, &cPoints.lonmin,
4708 Georef_Calculate_Coefficients_Proj(&cPoints);
4712 else if (m_projection == PROJECTION_MERCATOR) {
4713 double easting0, easting1, northing0, northing1;
4715 toSM_ECC(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat, m_proj_lon,
4716 &easting0, &northing0);
4717 toSM_ECC(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat, m_proj_lon,
4718 &easting1, &northing1);
4725 double dx2 = (pRefTable[jmax].xr - pRefTable[imax].xr) *
4726 (pRefTable[jmax].xr - pRefTable[imax].xr);
4727 double dy2 = (pRefTable[jmax].yr - pRefTable[imax].yr) *
4728 (pRefTable[jmax].yr - pRefTable[imax].yr);
4729 double dn2 = (northing1 - northing0) * (northing1 - northing0);
4730 double de2 = (easting1 - easting0) * (easting1 - easting0);
4732 m_ppm_avg = sqrt(dx2 + dy2) / sqrt(dn2 + de2);
4737 for (
int n = 0; n < nRefpoint; n++) {
4738 double easting, northing;
4739 toSM_ECC(pRefTable[n].latr, pRefTable[n].lonr, m_proj_lat, m_proj_lon,
4740 &easting, &northing);
4742 cPoints.tx[n] = pRefTable[n].xr;
4743 cPoints.ty[n] = pRefTable[n].yr;
4744 cPoints.lon[n] = easting;
4745 cPoints.lat[n] = northing;
4752 cPoints.txmax = plonmax;
4753 cPoints.txmin = plonmin;
4754 cPoints.tymax = platmax;
4755 cPoints.tymin = platmin;
4756 toSM_ECC(latmax, lonmax, m_proj_lat, m_proj_lon, &cPoints.lonmax,
4758 toSM_ECC(latmin, lonmin, m_proj_lat, m_proj_lon, &cPoints.lonmin,
4761 Georef_Calculate_Coefficients_Proj(&cPoints);
4783 else if (m_projection == PROJECTION_POLYCONIC) {
4792 double proj_meridian = m_proj_lon;
4794 if ((pRefTable[nlonmax].lonr >= -proj_meridian) &&
4795 (-proj_meridian >= pRefTable[nlonmin].lonr))
4796 m_proj_lon = -m_proj_lon;
4798 double easting0, easting1, northing0, northing1;
4800 toPOLY(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat, m_proj_lon,
4801 &easting0, &northing0);
4802 toPOLY(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat, m_proj_lon,
4803 &easting1, &northing1);
4806 double dx2 = (pRefTable[jmax].xr - pRefTable[imax].xr) *
4807 (pRefTable[jmax].xr - pRefTable[imax].xr);
4808 double dy2 = (pRefTable[jmax].yr - pRefTable[imax].yr) *
4809 (pRefTable[jmax].yr - pRefTable[imax].yr);
4810 double dn2 = (northing1 - northing0) * (northing1 - northing0);
4811 double de2 = (easting1 - easting0) * (easting1 - easting0);
4813 m_ppm_avg = sqrt(dx2 + dy2) / sqrt(dn2 + de2);
4826 for (
int n = 0; n < nRefpoint; n++) {
4827 double easting, northing;
4828 toPOLY(pRefTable[n].latr, pRefTable[n].lonr, m_proj_lat, m_proj_lon,
4829 &easting, &northing);
4836 cPoints.tx[n] = pRefTable[n].xr;
4837 cPoints.ty[n] = pRefTable[n].yr;
4838 cPoints.lon[n] = easting;
4839 cPoints.lat[n] = northing;
4846 cPoints.txmax = plonmax;
4847 cPoints.txmin = plonmin;
4848 cPoints.tymax = platmax;
4849 cPoints.tymin = platmin;
4850 toPOLY(latmax, lonmax, m_proj_lat, m_proj_lon, &cPoints.lonmax,
4852 toPOLY(latmin, lonmin, m_proj_lat, m_proj_lon, &cPoints.lonmin,
4855 Georef_Calculate_Coefficients_Proj(&cPoints);
4867 else if (bHaveEmbeddedGeoref) {
4869 double easting0, easting1, northing0, northing1;
4871 toSM_ECC(pRefTable[imax].latr, pRefTable[imax].lonr, m_proj_lat, m_proj_lon,
4872 &easting0, &northing0);
4873 toSM_ECC(pRefTable[jmax].latr, pRefTable[jmax].lonr, m_proj_lat, m_proj_lon,
4874 &easting1, &northing1);
4879 double dx = (pRefTable[jmax].xr - pRefTable[imax].xr);
4880 double de = (easting1 - easting0);
4882 m_ppm_avg = fabs(dx / de);
4885 _T(
"---<<< Warning: Chart georef accuracy may be poor. >>>---");
4894 vps.clat = pRefTable[0].latr;
4895 vps.clon = pRefTable[0].lonr;
4896 vps.view_scale_ppm = m_ppm_avg;
4898 vps.pix_width = 1000;
4899 vps.pix_height = 1000;
4902 latlong_to_pix_vp(latmin, (lonmax + lonmin)/2., x1, y1, vps);
4903 latlong_to_pix_vp(latmax, (lonmax + lonmin)/2., x2, y2, vps);
4905 double apparent_skew = (atan2( (y2-y1), (x2-x1) ) * 180./PI) + 90.;
4906 if(apparent_skew < 0.)
4907 apparent_skew += 360;
4908 if(apparent_skew > 360.)
4909 apparent_skew -= 360;
4911 if(fabs( apparent_skew - m_Chart_Skew ) > 2) {
4912 m_Chart_Skew = apparent_skew;
4916 if (!b_testSolution)
return (0);
4920 vp.clat = pRefTable[0].latr;
4921 vp.clon = pRefTable[0].lonr;
4922 vp.view_scale_ppm = m_ppm_avg;
4924 vp.pix_width = 1000;
4925 vp.pix_height = 1000;
4927 SetVPRasterParms(vp);
4929 double xpl_err_max = 0;
4930 double ypl_err_max = 0;
4934 pxref = (int)pRefTable[0].xr;
4935 pyref = (int)pRefTable[0].yr;
4937 for (i = 0; i < nRefpoint; i++) {
4938 px = (int)(vp.pix_width / 2 + pRefTable[i].xr) - pxref;
4939 py = (int)(vp.pix_height / 2 + pRefTable[i].yr) - pyref;
4941 vp_pix_to_latlong(vp, px, py, &elt, &elg);
4943 double lat_error = elt - pRefTable[i].latr;
4944 pRefTable[i].ypl_error = lat_error;
4946 double lon_error = elg - pRefTable[i].lonr;
4949 if (fabs(lon_error) > 180.) {
4952 else if (lon_error < 0.)
4955 pRefTable[i].xpl_error = lon_error;
4957 if (fabs(pRefTable[i].ypl_error) > fabs(ypl_err_max))
4958 ypl_err_max = pRefTable[i].ypl_error;
4959 if (fabs(pRefTable[i].xpl_error) > fabs(xpl_err_max))
4960 xpl_err_max = pRefTable[i].xpl_error;
4963 Chart_Error_Factor = fmax(fabs(xpl_err_max / (lonmax - lonmin)),
4964 fabs(ypl_err_max / (latmax - latmin)));
4965 double chart_error_meters =
4966 fmax(fabs(xpl_err_max * 60. * 1852.), fabs(ypl_err_max * 60. * 1852.));
4970 double chart_error_pixels = chart_error_meters * 4000. / m_Chart_Scale;
4973 int max_pixel_error = 4;
4975 if (chart_error_pixels > max_pixel_error) {
4977 _T(
" VP Final Check: Georeference Chart_Error_Factor on chart ");
4978 msg.Append(m_FullPath);
4980 msg1.Printf(_T(
" is %5g \n nominal pixel error is: %5g"),
4981 Chart_Error_Factor, chart_error_pixels);
4986 m_ExtraInfo = _T(
"---<<< Warning: Chart georef accuracy is poor. >>>---");
4992 if ((chart_error_pixels > max_pixel_error) && bHaveEmbeddedGeoref) {
4994 _T(
" Trying again with internally calculated georef solution ");
4997 bHaveEmbeddedGeoref =
false;
4998 SetVPRasterParms(vp);
5003 pxref = (int)pRefTable[0].xr;
5004 pyref = (int)pRefTable[0].yr;
5006 for (i = 0; i < nRefpoint; i++) {
5007 px = (int)(vp.pix_width / 2 + pRefTable[i].xr) - pxref;
5008 py = (int)(vp.pix_height / 2 + pRefTable[i].yr) - pyref;
5010 vp_pix_to_latlong(vp, px, py, &elt, &elg);
5012 double lat_error = elt - pRefTable[i].latr;
5013 pRefTable[i].ypl_error = lat_error;
5015 double lon_error = elg - pRefTable[i].lonr;
5018 if (fabs(lon_error) > 180.) {
5021 else if (lon_error < 0.)
5024 pRefTable[i].xpl_error = lon_error;
5026 if (fabs(pRefTable[i].ypl_error) > fabs(ypl_err_max))
5027 ypl_err_max = pRefTable[i].ypl_error;
5028 if (fabs(pRefTable[i].xpl_error) > fabs(xpl_err_max))
5029 xpl_err_max = pRefTable[i].xpl_error;
5032 Chart_Error_Factor = fmax(fabs(xpl_err_max / (lonmax - lonmin)),
5033 fabs(ypl_err_max / (latmax - latmin)));
5035 chart_error_meters =
5036 fmax(fabs(xpl_err_max * 60. * 1852.), fabs(ypl_err_max * 60. * 1852.));
5037 chart_error_pixels = chart_error_meters * 4000. / m_Chart_Scale;
5040 if (chart_error_pixels > max_pixel_error) {
5042 _T(
" VP Final Check with internal georef: Georeference ")
5043 _T("Chart_Error_Factor on chart ");
5044 msg.Append(m_FullPath);
5046 msg1.Printf(_T(" is %5g\n nominal pixel error is: %5g"),
5047 Chart_Error_Factor, chart_error_pixels);
5053 _T("---<<< Warning: Chart georef accuracy is poor. >>>---");
5055 wxString msg = _T(
" Result: OK, Internal georef solution used.");
5059 m_ExtraInfo = _T(
"");
5066double ChartBaseBSB::AdjustLongitude(
double lon) {
5067 double lond = (m_LonMin + m_LonMax) / 2 - lon;
5070 else if (lond < -180)
5106static double polytrans(
double *coeff,
double lon,
double lat) {
5107 double ret = coeff[0] + coeff[1] * lon + coeff[2] * lat;
5108 ret += coeff[3] * lon * lon;
5109 ret += coeff[4] * lon * lat;
5110 ret += coeff[5] * lat * lat;
5111 ret += coeff[6] * lon * lon * lon;
5112 ret += coeff[7] * lon * lon * lat;
5113 ret += coeff[8] * lon * lat * lat;
5114 ret += coeff[9] * lat * lat * lat;
5136extern int bsb_LLtoXY(BSBImage *p,
double lon,
double lat,
int* x,
int* y)
5139 lon = (lon < 0) ? lon + p->cph : lon - p->cph;
5140 double xd = polytrans( p->wpx, lon, lat );
5141 double yd = polytrans( p->wpy, lon, lat );
5142 *x = (int)(xd + 0.5);
5143 *y = (int)(yd + 0.5);
5158extern int bsb_XYtoLL(BSBImage *p,
int x,
int y,
double* lonout,
double* latout)
5160 double lon = polytrans( p->pwx, x, y );
5161 lon = (lon < 0) ? lon + p->cph : lon - p->cph;
5163 *latout = polytrans( p->pwy, x, y );