28#include <wx/listimpl.cpp>
43#include "androidUTIL.h"
64#define NOCOVR_PLY_PERF_LIMIT 500
65#define AUX_PLY_PERF_LIMIT 500
67WX_DEFINE_LIST(PatchList);
71static int CompareScales(
const int i1,
const int i2) {
78 return cte1.GetScale() - cte2.GetScale();
81static bool CompareScalesStd(
int i1,
int i2) {
82 return CompareScales(i1, i2) < 0;
85static bool CompareScalesStdFULLSCREEN(
int i1,
int i2) {
86 return CompareScales(i1, i2) < 0;
92 return CompareScales(qc1->dbIndex, qc2->dbIndex);
95const LLRegion &QuiltCandidate::GetCandidateRegion() {
96 const ChartTableEntry &cte =
ChartData->GetChartTableEntry(dbIndex);
97 LLRegion &candidate_region =
98 const_cast<LLRegion &
>(cte.quilt_candidate_region);
100 if (!candidate_region.Empty())
return candidate_region;
102 LLRegion world_region(-90, -180, 90, 180);
106 if (
ChartData->GetDBChartType(dbIndex) == CHART_TYPE_CM93COMP) {
107 double cm93_ll_bounds[8] = {-80, -180, -80, 180, 80, 180, 80, -180};
108 candidate_region = LLRegion(4, cm93_ll_bounds);
109 return candidate_region;
113 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
114 if (nAuxPlyEntries >= 1) {
115 candidate_region.Clear();
116 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
117 float *pfp = cte.GetpAuxPlyTableEntry(ip);
118 int nAuxPly = cte.GetAuxCntTableEntry(ip);
120 candidate_region.Union(LLRegion(nAuxPly, pfp));
133 std::vector<float> vec =
ChartData->GetReducedPlyPoints(dbIndex);
135 std::vector<float> vecr;
136 for (
size_t i = 0; i < vec.size() / 2; i++) {
137 float a = vec[i * 2 + 1];
143 std::vector<float>::iterator it = vecr.begin();
145 if (vecr.size() / 2 >= 3) {
148 candidate_region = LLRegion(vecr.size() / 2, (
float *)&(*it));
150 candidate_region = world_region;
154 if (!candidate_region
156 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
157 if (nNoCovrPlyEntries) {
158 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
159 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
160 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
162 LLRegion t_region = LLRegion(nNoCovrPly, pfp);
171 if (nAuxPlyEntries > 1) {
172 for (
int ipr = 0; ipr < nAuxPlyEntries; ipr++) {
173 float *pfpr = cte.GetpAuxPlyTableEntry(ipr);
174 int nAuxPly = cte.GetAuxCntTableEntry(ipr);
175 t_region.Subtract(LLRegion(nAuxPly, pfpr));
184 if (!t_region.Empty()) {
185 LLRegion test_region = candidate_region;
186 test_region.Subtract(t_region);
187 if (!test_region.Empty()) candidate_region = test_region;
197 if ((cte.GetScale() > 90000000) &&
198 (cte.GetChartFamily() == CHART_FAMILY_RASTER))
199 candidate_region = world_region;
201 return candidate_region;
204LLRegion &QuiltCandidate::GetReducedCandidateRegion(
double factor) {
205 if (factor != last_factor) {
206 reduced_candidate_region = GetCandidateRegion();
207 reduced_candidate_region.Reduce(factor);
208 last_factor = factor;
211 return reduced_candidate_region;
214void QuiltCandidate::SetScale(
int scale) {
218 if (scale >= 1000) rounding = 5 * pow(10, log10(scale) - 2);
227 m_reference_scale = 1;
228 m_refchart_dbIndex = -1;
229 m_reference_type = CHART_TYPE_UNKNOWN;
230 m_reference_family = CHART_FAMILY_UNKNOWN;
231 m_quilt_proj = PROJECTION_UNKNOWN;
232 m_chart_familyFix = CHART_FAMILY_UNKNOWN;
233 m_lost_refchart_dbIndex = -1;
241 new ArrayOfSortedQuiltCandidates(CompareQuiltCandidateScales);
246 m_preferred_family = CHART_FAMILY_RASTER;
249 m_bquiltskew = g_bopengl;
251 m_bquiltanyproj = g_bopengl;
255 m_PatchList.DeleteContents(
true);
258 EmptyCandidateArray();
259 delete m_pcandidate_array;
261 m_extended_stack_array.clear();
266void Quilt::SetReferenceChart(
int dbIndex) {
274 m_refchart_dbIndex = dbIndex;
280bool Quilt::IsVPBlittable(
ViewPort &VPoint,
int dx,
int dy,
281 bool b_allow_vector) {
282 if (!m_vp_rendered.IsValid())
return false;
287 double deltax = p2.m_x - p1.m_x;
288 double deltay = p2.m_y - p1.m_y;
290 if ((fabs(deltax - dx) > 1e-2) || (fabs(deltay - dy) > 1e-2))
return false;
295bool Quilt::IsChartS57Overlay(
int db_index) {
296 if (db_index < 0)
return false;
298 const ChartTableEntry &cte =
ChartData->GetChartTableEntry(db_index);
299 if (CHART_FAMILY_VECTOR == cte.GetChartFamily()) {
300 return s57chart::IsCellOverlayType(cte.GetFullSystemPath());
305bool Quilt::IsChartQuiltableRef(
int db_index) {
306 if (db_index < 0 || db_index >
ChartData->GetChartTableEntries() - 1)
310 const ChartTableEntry &ctei =
ChartData->GetChartTableEntry(db_index);
312 bool bproj_match =
true;
314 double skew_norm = ctei.GetChartSkew();
315 if (skew_norm > 180.) skew_norm -= 360.;
318 fabs(skew_norm) < 1.;
319 if (m_bquiltskew) skew_match =
true;
322 bool b_noshow =
false;
323 for (
unsigned int i = 0; i < m_parent->GetQuiltNoshowIindexArray().size();
325 if (m_parent->GetQuiltNoshowIindexArray()[i] ==
333 return (bproj_match & skew_match & !b_noshow);
336bool Quilt::IsChartInQuilt(
ChartBase *pc) {
338 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
339 QuiltCandidate *pqc = m_pcandidate_array->Item(ir);
340 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
341 if (
ChartData->OpenChartFromDB(pqc->dbIndex, FULL_INIT) == pc)
348bool Quilt::IsChartInQuilt(wxString &full_path) {
350 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
351 QuiltCandidate *pqc = m_pcandidate_array->Item(ir);
352 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
353 auto &cte =
ChartData->GetChartTableEntry(pqc->dbIndex);
354 if (cte.GetpsFullPath()->IsSameAs(full_path))
return true;
360std::vector<int> Quilt::GetCandidatedbIndexArray(
bool from_ref_chart,
361 bool exclude_user_hidden) {
362 std::vector<int> ret;
363 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
364 QuiltCandidate *pqc = m_pcandidate_array->Item(ir);
367 if (pqc->Scale_ge(m_reference_scale)) {
369 if (exclude_user_hidden) {
370 bool b_noshow =
false;
371 for (
unsigned int i = 0;
372 i < m_parent->GetQuiltNoshowIindexArray().size(); i++) {
373 if (m_parent->GetQuiltNoshowIindexArray()[i] ==
380 if (!b_noshow) ret.push_back(pqc->dbIndex);
382 ret.push_back(pqc->dbIndex);
386 ret.push_back(pqc->dbIndex);
393 return (cnode->GetData());
398void Quilt::EmptyCandidateArray() {
399 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
400 delete m_pcandidate_array->Item(i);
403 m_pcandidate_array->Clear();
413 if (!m_bcomposed)
return NULL;
415 if (m_bbusy)
return NULL;
418 ChartBase *pret = NULL;
419 cnode = m_PatchList.GetFirst();
420 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetNext();
421 if (cnode && cnode->GetData()->b_Valid)
422 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
433 if (m_bbusy)
return NULL;
436 ChartBase *pret = NULL;
438 cnode = cnode->GetNext();
439 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetNext();
440 if (cnode && cnode->GetData()->b_Valid)
441 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
448ChartBase *Quilt::GetNextSmallerScaleChart() {
453 if (m_bbusy)
return NULL;
456 ChartBase *pret = NULL;
458 cnode = cnode->GetPrevious();
459 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetPrevious();
460 if (cnode && cnode->GetData()->b_Valid)
461 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
468ChartBase *Quilt::GetLargestScaleChart() {
471 if (m_bbusy)
return NULL;
474 ChartBase *pret = NULL;
475 cnode = m_PatchList.GetLast();
477 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
484 LLRegion chart_region;
485 LLRegion screen_region(vp.GetBBox());
490 if (fabs(cte.GetLonMax() - cte.GetLonMin()) > 180.) {
507 return LLRegion(-80, vp.GetBBox().GetMinLon(), 80,
508 vp.GetBBox().GetMaxLon());
512 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
513 bool aux_ply_skipped =
false;
514 if (nAuxPlyEntries >= 1) {
515 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
516 int nAuxPly = cte.GetAuxCntTableEntry(ip);
517 if (nAuxPly > AUX_PLY_PERF_LIMIT) {
520 aux_ply_skipped =
true;
523 float *pfp = cte.GetpAuxPlyTableEntry(ip);
524 LLRegion t_region(nAuxPly, pfp);
525 t_region.Intersect(screen_region);
529 if (!t_region.Empty()) chart_region.Union(t_region);
533 if (aux_ply_skipped || nAuxPlyEntries == 0) {
534 int n_ply_entries = cte.GetnPlyEntries();
535 float *pfp = cte.GetpPlyTable();
537 if (n_ply_entries >= 3)
540 LLRegion t_region(n_ply_entries, pfp);
541 t_region.Intersect(screen_region);
545 if (!t_region.Empty()) chart_region.Union(t_region);
548 chart_region = screen_region;
552 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
553 if (nNoCovrPlyEntries) {
554 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
555 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
556 if (nNoCovrPly > NOCOVR_PLY_PERF_LIMIT) {
561 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
563 LLRegion t_region(nNoCovrPly, pfp);
564 t_region.Intersect(screen_region);
575 if (!t_region.Empty()) {
576 LLRegion test_region = chart_region;
577 test_region.Subtract(t_region);
579 if (!test_region.Empty()) chart_region = test_region;
588 if ((cte.GetScale() > 90000000) &&
589 (cte.GetChartFamily() == CHART_FAMILY_RASTER))
590 chart_region = screen_region;
598bool Quilt::IsQuiltVector() {
599 if (m_bbusy)
return false;
605 PatchList::compatibility_iterator cnode = m_PatchList.GetFirst();
607 if (cnode->GetData()) {
608 QuiltPatch *pqp = cnode->GetData();
610 if ((pqp->b_Valid) && (!pqp->b_eclipsed) &&
611 (pqp->dbIndex <
ChartData->GetChartTableEntries())) {
612 const ChartTableEntry &ctei =
613 ChartData->GetChartTableEntry(pqp->dbIndex);
615 if (ctei.GetChartFamily() == CHART_FAMILY_VECTOR) {
621 cnode = cnode->GetNext();
628bool Quilt::DoesQuiltContainPlugins() {
629 if (m_bbusy)
return false;
635 PatchList::compatibility_iterator cnode = m_PatchList.GetFirst();
637 if (cnode->GetData()) {
638 QuiltPatch *pqp = cnode->GetData();
640 if ((pqp->b_Valid) && (!pqp->b_eclipsed)) {
641 const ChartTableEntry &ctei =
642 ChartData->GetChartTableEntry(pqp->dbIndex);
644 if (ctei.GetChartType() == CHART_TYPE_PLUGIN) {
650 cnode = cnode->GetNext();
657int Quilt::GetChartdbIndexAtPix(
ViewPort &VPoint, wxPoint p) {
658 if (m_bbusy)
return -1;
667 PatchList::compatibility_iterator cnode = m_PatchList.GetFirst();
669 if (cnode->GetData()->ActiveRegion.Contains(lat, lon)) {
670 ret = cnode->GetData()->dbIndex;
673 cnode = cnode->GetNext();
681 if (m_bbusy)
return NULL;
692 ChartBase *pret = NULL;
693 PatchList::compatibility_iterator cnode = m_PatchList.GetFirst();
695 QuiltPatch *pqp = cnode->GetData();
696 if (!pqp->b_overlay && (pqp->ActiveRegion.Contains(lat, lon)))
697 if (
ChartData->IsChartInCache(pqp->dbIndex)) {
698 pret =
ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
700 cnode = cnode->GetNext();
708 if (m_bbusy)
return NULL;
719 ChartBase *pret = NULL;
720 PatchList::compatibility_iterator cnode = m_PatchList.GetFirst();
722 QuiltPatch *pqp = cnode->GetData();
723 if (pqp->b_overlay && (pqp->ActiveRegion.Contains(lat, lon)))
724 pret =
ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
725 cnode = cnode->GetNext();
732void Quilt::InvalidateAllQuiltPatchs() {
743std::vector<int> Quilt::GetQuiltIndexArray() {
744 return m_index_array;
746 std::vector<int> ret;
748 if (m_bbusy)
return ret;
752 PatchList::compatibility_iterator cnode = m_PatchList.GetFirst();
754 ret.push_back(cnode->GetData()->dbIndex);
755 cnode = cnode->GetNext();
763bool Quilt::IsQuiltDelta(
ViewPort &vp) {
764 if (!m_vp_quilt.IsValid() || !m_bcomposed)
return true;
768 if (m_vp_quilt.m_projection_type != vp.m_projection_type)
return true;
770 if (m_vp_quilt.rotation != vp.
rotation)
return true;
773 wxPoint cp_last, cp_this;
775 cp_last = m_vp_quilt.GetPixFromLL(vp.
clat, vp.
clon);
778 return (cp_last != cp_this);
785 ChartBase *pRefChart =
786 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
788 if (pRefChart) pRefChart->AdjustVP(vp_last, vp_proposed);
791double Quilt::GetRefNativeScale() {
792 double ret_val = 1.0;
794 ChartBase *pc =
ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
795 if (pc) ret_val = pc->GetNativeScale();
801int Quilt::GetNewRefChart() {
807 int new_ref_dbIndex = m_refchart_dbIndex;
808 unsigned int im = m_extended_stack_array.size();
810 for (
unsigned int is = 0; is < im; is++) {
811 const ChartTableEntry &m =
812 ChartData->GetChartTableEntry(m_extended_stack_array[is]);
814 double skew_norm = m.GetChartSkew();
815 if (skew_norm > 180.) skew_norm -= 360.;
817 if ((m.Scale_ge(m_reference_scale)) &&
818 (m_reference_family == m.GetChartFamily()) &&
819 (m_bquiltanyproj || m_quilt_proj == m.GetChartProjectionType()) &&
820 (m_bquiltskew || (fabs(skew_norm) < 1.0))) {
821 new_ref_dbIndex = m_extended_stack_array[is];
826 return new_ref_dbIndex;
829int Quilt::GetNomScaleMax(
int scale, ChartTypeEnum type,
830 ChartFamilyEnum family) {
832 case CHART_FAMILY_RASTER: {
836 case CHART_FAMILY_VECTOR: {
846int Quilt::GetNomScaleMin(
int scale, ChartTypeEnum type,
847 ChartFamilyEnum family) {
848 double zoom_mod = (double)g_chart_zoom_modifier_raster;
850 if (family == CHART_FAMILY_VECTOR)
851 zoom_mod = (double)g_chart_zoom_modifier_vector;
853 double modf = zoom_mod / 5.;
854 double mod = pow(16., modf);
855 mod = wxMax(mod, .2);
856 mod = wxMin(mod, 16.0);
860 case CHART_FAMILY_RASTER: {
861 if (CHART_TYPE_MBTILES == type)
867 return scale * 1 * mod;
870 case CHART_FAMILY_VECTOR: {
871 return scale * 4 * mod;
875 mod = wxMin(mod, 2.0);
876 return scale * 2 * mod;
882 int index, nom, min, max;
885int Quilt::AdjustRefOnZoom(
bool b_zin, ChartFamilyEnum family,
886 ChartTypeEnum type,
double proposed_scale_onscreen) {
887 std::vector<scale> scales;
888 std::vector<scale> scales_mbtiles;
897 bool b_allow_fullscreen_ref =
898 (family == CHART_FAMILY_VECTOR) || b_zin || g_bopengl;
902 int smallest_scale = 1;
903 for (
size_t i = 0; i < m_extended_stack_array.size(); i++) {
904 int index = m_extended_stack_array[i];
905 if (
ChartData->GetDBChartType(index) == type)
906 smallest_scale = wxMax(smallest_scale,
ChartData->GetDBChartScale(index));
911 for (
size_t i = 0; i < m_extended_stack_array.size(); i++) {
912 int test_db_index = m_extended_stack_array[i];
914 if (b_allow_fullscreen_ref ||
915 m_parent->GetpCurrentStack()->DoesStackContaindbIndex(test_db_index)) {
916 if ((family ==
ChartData->GetDBChartFamily(test_db_index)) &&
917 IsChartQuiltableRef(test_db_index)
919 int nscale =
ChartData->GetDBChartScale(test_db_index);
921 int nmax_scale = GetNomScaleMax(nscale, type, family);
925 if (0 == i_first) nmax_scale = 1;
927 int nmin_scale = GetNomScaleMin(nscale, type, family);
930 if ((type == CHART_TYPE_KAP) && (nscale == smallest_scale))
935 if ((type == CHART_TYPE_MBTILES) && (nscale == smallest_scale))
938 if (CHART_TYPE_MBTILES ==
ChartData->GetDBChartType(test_db_index))
939 scales_mbtiles.push_back(
940 scale{test_db_index, nscale, nmin_scale, nmax_scale});
943 scale{test_db_index, nscale, nmin_scale, nmax_scale});
950 if (scales.empty()) scales = scales_mbtiles;
957 if (CHART_FAMILY_VECTOR == family) {
958 for (
size_t i = scales.size(); i; i--) {
959 int test_db_index = scales[i - 1].index;
960 if (type ==
ChartData->GetDBChartType(test_db_index)) {
961 scales[i - 1].min = scales[i - 1].nom * 80;
973 if (scales.size() > 1) {
974 for (
unsigned i = 0; i < scales.size() - 1; i++) {
975 int min_scale_test = wxMax(scales[i].min, scales[i + 1].max + 1);
976 min_scale_test = wxMin(min_scale_test, scales[i].min * 2);
977 scales[i].min = min_scale_test;
986 if (scales.size() > 2) {
987 for (
size_t i = scales.size() - 2; i >= 1; i--) {
988 scales[i].max = wxMin(scales[i].max, scales[i - 1].min - 1);
992 int new_ref_dbIndex = -1;
996 for (
size_t i = 0; i < scales.size(); i++) {
997 if ((proposed_scale_onscreen <
1000 (proposed_scale_onscreen > scales[i].max)) {
1001 new_ref_dbIndex = scales[i].index;
1006 return new_ref_dbIndex;
1009int Quilt::AdjustRefOnZoomOut(
double proposed_scale_onscreen) {
1011 m_lost_refchart_dbIndex = -1;
1013 int current_db_index = m_refchart_dbIndex;
1014 int current_family = m_reference_family;
1015 ChartTypeEnum current_type = (ChartTypeEnum)m_reference_type;
1017 if (m_refchart_dbIndex >= 0) {
1018 const ChartTableEntry &cte =
1019 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1020 current_family = cte.GetChartFamily();
1021 current_type = (ChartTypeEnum)cte.GetChartType();
1024 if (current_type == CHART_TYPE_CM93COMP)
return current_db_index;
1026 int proposed_ref_index =
1027 AdjustRefOnZoom(
false, (ChartFamilyEnum)current_family, current_type,
1028 proposed_scale_onscreen);
1031 if (proposed_ref_index < 0) {
1032 m_zout_family = current_family;
1033 m_zout_type = current_type;
1034 m_zout_dbindex = current_db_index;
1037 if (proposed_ref_index < 0) {
1038 return m_refchart_dbIndex;
1040 SetReferenceChart(proposed_ref_index);
1041 return proposed_ref_index;
1045int Quilt::AdjustRefOnZoomIn(
double proposed_scale_onscreen) {
1047 m_lost_refchart_dbIndex = -1;
1049 int current_db_index = m_refchart_dbIndex;
1050 int current_family = m_reference_family;
1051 ChartTypeEnum current_type = (ChartTypeEnum)m_reference_type;
1053 if (m_zout_family >= 0) {
1054 current_type = (ChartTypeEnum)m_zout_type;
1055 current_family = m_zout_family;
1061 if (current_type == CHART_TYPE_CM93COMP) {
1062 if (m_zout_family >= 0) {
1063 current_family =
ChartData->GetDBChartFamily(m_zout_dbindex);
1065 return current_db_index;
1068 if ((-1 == m_refchart_dbIndex) && (m_zout_dbindex >= 0))
1069 BuildExtendedChartStackAndCandidateArray(m_zout_dbindex, m_vp_quilt);
1071 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, m_vp_quilt);
1073 int proposed_ref_index =
1074 AdjustRefOnZoom(
true, (ChartFamilyEnum)current_family, current_type,
1075 proposed_scale_onscreen);
1077 if (current_db_index == -1) {
1078 SetReferenceChart(proposed_ref_index);
1079 return proposed_ref_index;
1082 if (proposed_ref_index != -1) {
1083 if (
ChartData->GetDBChartScale(current_db_index) >=
1084 ChartData->GetDBChartScale(proposed_ref_index)) {
1085 SetReferenceChart(proposed_ref_index);
1086 return proposed_ref_index;
1089 proposed_ref_index = current_db_index;
1091 SetReferenceChart(proposed_ref_index);
1093 return proposed_ref_index;
1096bool Quilt::IsChartSmallestScale(
int dbIndex) {
1101 int specified_type =
ChartData->GetDBChartType(dbIndex);
1102 int target_dbindex = -1;
1104 unsigned int target_stack_index = 0;
1105 if (m_extended_stack_array.size()) {
1106 while ((target_stack_index <= (m_extended_stack_array.size() - 1))) {
1107 int test_db_index = m_extended_stack_array[target_stack_index];
1109 if (specified_type ==
ChartData->GetDBChartType(test_db_index))
1110 target_dbindex = test_db_index;
1112 target_stack_index++;
1115 return (dbIndex == target_dbindex);
1118LLRegion Quilt::GetHiliteRegion() {
1124 for (
auto &index : m_HiLiteIndexArray) {
1125 const ChartTableEntry &cte =
ChartData->GetChartTableEntry(index);
1126 LLRegion cell_region = GetChartQuiltRegion(cte, m_vp_quilt);
1127 r.Union(cell_region);
1131 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
1132 PatchList::compatibility_iterator pcinode = m_PatchList.Item(i);
1133 QuiltPatch *piqp = pcinode->GetData();
1134 if ((index == piqp->dbIndex) && (piqp->b_Valid))
1136 r.Union(piqp->ActiveRegion);
1145LLRegion Quilt::GetHiliteRegion() {
1147 if (m_nHiLiteIndex >= 0) {
1149 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
1150 PatchList::compatibility_iterator pcinode = m_PatchList.Item(i);
1151 QuiltPatch *piqp = pcinode->GetData();
1152 if ((m_nHiLiteIndex == piqp->dbIndex) && (piqp->b_Valid))
1154 r = piqp->ActiveRegion;
1161 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1162 QuiltCandidate *pqc = m_pcandidate_array->Item(ir);
1163 if (m_nHiLiteIndex == pqc->dbIndex) {
1164 LLRegion chart_region = pqc->GetCandidateRegion();
1165 if (!chart_region.Empty()) {
1167 bool b_eclipsed =
false;
1168 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size();
1170 if (m_nHiLiteIndex == m_eclipsed_stack_array[ir]) {
1176 if (!b_eclipsed) r = chart_region;
1185 const ChartTableEntry &cte =
1186 ChartData->GetChartTableEntry(m_nHiLiteIndex);
1187 if (cte.GetChartType() == CHART_TYPE_MBTILES) {
1188 r = GetTilesetRegion(m_nHiLiteIndex);
1196const LLRegion &Quilt::GetTilesetRegion(
int dbIndex) {
1197 LLRegion world_region(-90, -180, 90, 180);
1199 const ChartTableEntry &cte =
ChartData->GetChartTableEntry(dbIndex);
1200 LLRegion &target_region =
const_cast<LLRegion &
>(cte.quilt_candidate_region);
1202 if (!target_region.Empty())
return target_region;
1205 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
1206 if (nAuxPlyEntries >= 1) {
1207 target_region.Clear();
1208 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
1209 float *pfp = cte.GetpAuxPlyTableEntry(ip);
1210 int nAuxPly = cte.GetAuxCntTableEntry(ip);
1212 target_region.Union(LLRegion(nAuxPly, pfp));
1215 std::vector<float> vec =
ChartData->GetReducedPlyPoints(dbIndex);
1217 std::vector<float> vecr;
1218 for (
size_t i = 0; i < vec.size() / 2; i++) {
1219 float a = vec[i * 2 + 1];
1225 std::vector<float>::iterator it = vecr.begin();
1227 if (vecr.size() / 2 >= 3) {
1230 target_region = LLRegion(vecr.size() / 2, (
float *)&(*it));
1232 target_region = world_region;
1236 if (!target_region.Empty()) {
1237 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
1238 if (nNoCovrPlyEntries) {
1239 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
1240 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
1241 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
1243 LLRegion t_region = LLRegion(nNoCovrPly, pfp);
1250 if (!t_region.Empty()) {
1251 LLRegion test_region = target_region;
1252 test_region.Subtract(t_region);
1254 if (!test_region.Empty()) target_region = test_region;
1268 return target_region;
1271int Quilt::SelectRefChartByFamily(ChartFamilyEnum family) {
1273 auto array = GetFullscreenIndexArray();
1275 std::sort(array.begin(), array.end(), CompareScalesStd);
1279 for (
int dbIndex : array) {
1281 const ChartTableEntry &cte_candidate =
1285 wxFileName fn(cte_candidate.GetFullPath());
1286 if (fn.GetPath().Lower().Contains(
"basemap"))
continue;
1289 if (cte_candidate.GetChartFamily() == family) {
1291 m_chart_familyFix = family;
1296 m_lost_refchart_dbIndex = -1;
1301bool Quilt::BuildExtendedChartStackAndCandidateArray(
int ref_db_index,
1303 double zoom_test_val = .002;
1306 EmptyCandidateArray();
1307 m_extended_stack_array.clear();
1308 m_fullscreen_index_array.clear();
1310 int reference_scale = 1e8;
1311 int reference_type = -1;
1312 int reference_family = -1;
1314 m_bquiltanyproj ? vp_in.m_projection_type : PROJECTION_UNKNOWN;
1316 if (ref_db_index >= 0) {
1317 const ChartTableEntry &cte_ref =
1318 ChartData->GetChartTableEntry(ref_db_index);
1319 reference_scale = cte_ref.GetScale();
1320 reference_type = cte_ref.GetChartType();
1321 if (!m_bquiltanyproj) quilt_proj =
ChartData->GetDBChartProj(ref_db_index);
1322 reference_family = cte_ref.GetChartFamily();
1325 bool b_need_resort =
false;
1327 ViewPort vp_local = vp_in;
1335 int n_charts = m_parent->GetpCurrentStack()->nEntry;
1339 for (
int ics = 0; ics < n_charts; ics++) {
1340 int istack = m_parent->GetpCurrentStack()->GetDBIndex(ics);
1341 if (istack < 0)
continue;
1342 m_extended_stack_array.push_back(istack);
1348 if (reference_type == CHART_TYPE_CM93COMP)
continue;
1350 const ChartTableEntry &cte =
ChartData->GetChartTableEntry(istack);
1352 if (cte.GetChartType() == CHART_TYPE_MBTILES) {
1353 wxFileName fn(cte.GetFullPath());
1354 if (fn.GetPath().Lower().Contains(
"basemap")) {
1355 if (!m_parent->GetbEnableBasemapTile()) {
1356 m_extended_stack_array.pop_back();
1368 if ((cte.GetChartType() == CHART_TYPE_PLUGIN) ||
1369 (reference_type == CHART_TYPE_PLUGIN)) {
1370 if (reference_family != cte.GetChartFamily()) {
1374 if (reference_type != cte.GetChartType()) {
1380 wxFileName fnb(cte.GetFullPath());
1381 if (!fnb.GetPath().Lower().Contains(
"basemap"))
continue;
1385 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1388 int candidate_chart_scale = cte.GetScale();
1389 double chart_native_ppm =
1390 m_canvas_scale_factor / (double)candidate_chart_scale;
1392 if ((zoom_factor < zoom_test_val) &&
1397 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
1398 m_extended_stack_array.pop_back();
1402 double skew_norm = cte.GetChartSkew();
1403 if (skew_norm > 180.) skew_norm -= 360.;
1405 if ((m_bquiltskew ? 1 : fabs(skew_norm) < 1.0) &&
1406 (m_bquiltanyproj || cte.GetChartProjectionType() == quilt_proj)) {
1407 QuiltCandidate *qcnew =
new QuiltCandidate;
1408 qcnew->dbIndex = istack;
1409 qcnew->SetScale(cte.GetScale());
1410 m_pcandidate_array->push_back(qcnew);
1437 int n_all_charts =
ChartData->GetChartTableEntries();
1439 LLBBox viewbox = vp_local.GetBBox();
1440 int sure_index = -1;
1441 int sure_index_scale = 0;
1442 int sure_index_type = -1;
1444 for (
int i = 0; i < n_all_charts; i++) {
1448 int groupIndex = m_parent->m_groupIndex;
1449 if ((groupIndex > 0) && (!
ChartData->IsChartInGroup(i, groupIndex)))
1452 const ChartTableEntry &cte =
ChartData->GetChartTableEntry(i);
1454 if (cte.GetChartType() == CHART_TYPE_MBTILES) {
1455 wxFileName fn(cte.GetFullPath());
1456 if (fn.GetPath().Lower().Contains(
"basemap")) {
1457 if (!m_parent->GetbEnableBasemapTile()) {
1464 if (
ChartData->IsChartDirectoryExcluded(cte.GetFullPath()))
continue;
1466 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
1467 m_fullscreen_index_array.push_back(i);
1472 wxFileName fn(cte.GetFullSystemPath());
1473 if (!androidIsDirWritable(fn.GetPath()))
continue;
1475 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1477 const LLBBox &chart_box = cte.GetBBox();
1478 if ((viewbox.IntersectOut(chart_box)))
continue;
1480 if (cte.GetChartType() == CHART_TYPE_PLUGIN) {
1481 if (!
ChartData->IsChartAvailable(i))
continue;
1484 m_fullscreen_index_array.push_back(i);
1491 bool guest_family_include =
false;
1492 if (reference_family != cte.GetChartFamily()) {
1493 wxFileName fn(cte.GetFullPath());
1494 if (fn.GetPath().Lower().Contains(
"basemap")) {
1495 guest_family_include =
true;
1498 if (m_lost_refchart_dbIndex == i) guest_family_include =
true;
1500 if ((cte.GetChartType() != CHART_TYPE_MBTILES) && !guest_family_include)
1504 if (!m_bquiltanyproj && quilt_proj != cte.GetChartProjectionType())
1507 double skew_norm = cte.GetChartSkew();
1508 if (skew_norm > 180.) skew_norm -= 360.;
1510 if (!m_bquiltskew && fabs(skew_norm) > 1.0)
continue;
1515 if( CHART_TYPE_S57 == cte.GetChartType() ) {
1517 double chart_area = (cte.GetLonMax() - cte.GetLonMin()) *
1518 (cte.GetLatMax() - cte.GetLatMin());
1519 double quilt_area = viewbox.GetLonRange() * viewbox.GetLatRange();
1520 if ((chart_area / quilt_area) < .01)
continue;
1523 int candidate_chart_scale = cte.GetScale();
1529 if (!cte.Scale_ge(reference_scale)) {
1530 if (cte.Scale_gt(sure_index_scale)) {
1532 sure_index_scale = candidate_chart_scale;
1533 sure_index_type = cte.GetChartType();
1542 double chart_native_ppm =
1543 m_canvas_scale_factor / (double)candidate_chart_scale;
1545 double zoom_factor_test_extra = 0.2;
1551 double ref_scale_test = reference_scale;
1552 if (cte.GetChartType() == CHART_TYPE_MBTILES)
1553 ref_scale_test = candidate_chart_scale;
1555 if ((cte.Scale_ge(ref_scale_test) && (zoom_factor > zoom_test_val)) ||
1556 (zoom_factor > zoom_factor_test_extra)) {
1557 LLRegion cell_region = GetChartQuiltRegion(cte, vp_local);
1562 if (!cell_region.Empty()) {
1565 bool b_exists =
false;
1566 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1567 if (i == m_extended_stack_array[ir]) {
1581 bool b_noadd =
false;
1582 auto &cte_n =
ChartData->GetChartTableEntry(i);
1583 for (
unsigned int id = 0;
id < m_extended_stack_array.size();
id++) {
1584 if (m_extended_stack_array[
id] != -1) {
1586 ChartData->GetChartTableEntry(m_extended_stack_array[
id]);
1587 bool bsameTime =
false;
1588 if (cte_m.GetFileTime() && cte_n.GetFileTime()) {
1589 if (labs(cte_m.GetFileTime() - cte_n.GetFileTime()) < 60)
1592 if (cte_m.GetChartEditionDate() == cte_n.GetChartEditionDate())
1596 if (cte_n.GetpFileName()->IsSameAs(*(cte_m.GetpFileName())))
1603 m_extended_stack_array.push_back(i);
1605 QuiltCandidate *qcnew =
new QuiltCandidate;
1608 candidate_chart_scale);
1610 m_pcandidate_array->push_back(qcnew);
1612 b_need_resort =
true;
1621 if (-1 != sure_index) {
1623 bool sure_exists =
false;
1624 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1625 if (sure_index == m_extended_stack_array[ir]) {
1632 if (!sure_exists && (sure_index_type != CHART_TYPE_MBTILES)) {
1633 m_extended_stack_array.push_back(sure_index);
1635 QuiltCandidate *qcnew =
new QuiltCandidate;
1636 qcnew->dbIndex = sure_index;
1637 qcnew->SetScale(
ChartData->GetDBChartScale(sure_index));
1638 m_pcandidate_array->push_back(qcnew);
1640 b_need_resort =
true;
1645 if (b_need_resort && m_extended_stack_array.size() > 1) {
1646 std::sort(m_extended_stack_array.begin(), m_extended_stack_array.end(),
1650 std::sort(m_fullscreen_index_array.begin(), m_fullscreen_index_array.end(),
1651 CompareScalesStdFULLSCREEN);
1656int Quilt::AdjustRefSelection(
const ViewPort &vp_in) {
1667 ViewPort vp_local = vp_in;
1671 vp_local.SetRotationAngle(0.);
1673 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1675 ChartFamilyEnum family = CHART_FAMILY_RASTER;
1676 ChartTypeEnum type = CHART_TYPE_KAP;
1679 if (m_refchart_dbIndex >= 0) {
1680 const ChartTableEntry &cte_ref =
1681 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1682 type = (ChartTypeEnum)cte_ref.GetChartType();
1683 family = (ChartFamilyEnum)cte_ref.GetChartFamily();
1686 int ret_index = AdjustRefOnZoom(
true, family, type, vp_in.
chart_scale);
1691double Quilt::GetBestStartScale(
int dbi_ref_hint,
const ViewPort &vp_in) {
1698 ViewPort vp_local = vp_in;
1701 int tentative_ref_index = dbi_ref_hint;
1702 if (dbi_ref_hint < 0) {
1709 tentative_ref_index = m_parent->GetpCurrentStack()->GetDBIndex(0);
1716 vp_local.SetRotationAngle(0.);
1718 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1722 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1723 QuiltCandidate *qc = m_pcandidate_array->Item(i);
1724 if (qc->dbIndex == tentative_ref_index) {
1730 if (!bf && m_pcandidate_array->GetCount()) {
1731 tentative_ref_index = GetNewRefChart();
1732 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1735 double proposed_scale_onscreen = vp_in.
chart_scale;
1737 if (m_pcandidate_array->GetCount()) {
1738 SetReferenceChart(tentative_ref_index);
1742 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1743 QuiltCandidate *qc = m_pcandidate_array->Item(i);
1744 if (IsChartQuiltableRef(qc->dbIndex)) {
1745 SetReferenceChart(qc->dbIndex);
1752 SetReferenceChart(m_parent->GetpCurrentStack()->GetDBIndex(0));
1755 if (m_refchart_dbIndex >= 0) {
1758 ChartBase *pc =
ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
1760 double min_ref_scale =
1761 pc->GetNormalScaleMin(m_parent->GetCanvasScaleFactor(),
false);
1762 double max_ref_scale = pc->GetNormalScaleMax(
1763 m_parent->GetCanvasScaleFactor(), m_canvas_width);
1764 if ((proposed_scale_onscreen >= min_ref_scale) &&
1765 (proposed_scale_onscreen <= max_ref_scale))
1768 proposed_scale_onscreen = wxMin(proposed_scale_onscreen, max_ref_scale);
1769 proposed_scale_onscreen = wxMax(proposed_scale_onscreen, min_ref_scale);
1773 return m_parent->GetCanvasScaleFactor() / proposed_scale_onscreen;
1777 if (m_refchart_dbIndex >= 0 &&
ChartData)
1778 return ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
1782void Quilt::UnlockQuilt() {
1783 wxASSERT(m_bbusy ==
false);
1786 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1787 QuiltCandidate *pqc = m_pcandidate_array->Item(ir);
1788 ChartData->UnLockCacheChart(pqc->dbIndex);
1798 if (!m_parent->GetpCurrentStack())
return false;
1800 if (m_bbusy)
return false;
1809 if (m_refchart_dbIndex >= 0) {
1811 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1812 m_reference_scale = cte_ref.GetScale();
1813 m_reference_type = cte_ref.GetChartType();
1814 if (!m_bquiltanyproj)
1815 m_quilt_proj =
ChartData->GetDBChartProj(m_refchart_dbIndex);
1816 m_reference_family = cte_ref.GetChartFamily();
1820 if (!m_bquiltanyproj) vp_local.SetProjectionType(m_quilt_proj);
1827 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1867 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1869 if (qc->dbIndex == m_refchart_dbIndex) {
1878 if (m_chart_familyFix == CHART_FAMILY_UNKNOWN) {
1879 if (!bf && m_pcandidate_array->GetCount() &&
1880 (m_reference_type != CHART_TYPE_CM93COMP)) {
1881 m_lost_refchart_dbIndex = m_refchart_dbIndex;
1882 int candidate_ref_index = GetNewRefChart();
1883 if (m_refchart_dbIndex != candidate_ref_index) {
1884 m_refchart_dbIndex = candidate_ref_index;
1885 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1892 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1893 if (m_pcandidate_array->GetCount()) {
1894 int alternate_index =
1895 m_pcandidate_array->Item(m_pcandidate_array->GetCount() - 1)
1898 ChartData->GetChartTableEntry(alternate_index);
1900 if (GetRefFamily() == cte_alt.GetChartFamily()) {
1901 m_refchart_dbIndex = alternate_index;
1902 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex,
1910 if ((-1 != m_lost_refchart_dbIndex) &&
1911 (m_lost_refchart_dbIndex != m_refchart_dbIndex)) {
1914 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1915 if (m_lost_refchart_dbIndex == m_extended_stack_array[ir]) {
1916 m_refchart_dbIndex = m_lost_refchart_dbIndex;
1917 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1918 m_lost_refchart_dbIndex = -1;
1924 bool b_has_overlays =
false;
1927 if (CHART_FAMILY_VECTOR == m_reference_family) {
1928 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1932 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1933 b_has_overlays =
true;
1945 const LLRegion cvp_region = vp_local.GetLLRegion(vp_local.rv_rect);
1946 LLRegion vp_region = cvp_region;
1952 for (ir = 0; ir < m_pcandidate_array->GetCount();
1956 if (pqc->dbIndex == m_refchart_dbIndex) {
1965 const double z = 111274.96299695622;
1971 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1973 LLRegion vpu_region(cvp_region);
1976 LLRegion &chart_region = pqc_ref->GetReducedCandidateRegion(factor);
1978 if (cte_ref.GetChartType() != CHART_TYPE_MBTILES) {
1979 if (!chart_region.Empty()) {
1980 vpu_region.Intersect(chart_region);
1982 if (vpu_region.Empty())
1983 pqc_ref->b_include =
false;
1985 pqc_ref->b_include =
true;
1986 vp_region.Subtract(chart_region);
1989 pqc_ref->b_include =
false;
1991 pqc_ref->b_include =
false;
1996 if (!vp_region.Empty()) {
1997 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2000 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
2007 if (CHART_FAMILY_VECTOR == m_reference_family) {
2008 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
2014 if (CHART_TYPE_MBTILES == cte.GetChartType()) {
2015 pqc->b_include =
false;
2019 if (cte.Scale_ge(m_reference_scale)) {
2023 bool b_in_noshow =
false;
2024 for (
unsigned int ins = 0;
2025 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2026 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2036 LLRegion vpu_region(cvp_region);
2039 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2041 if (!chart_region.Empty()) {
2042 vpu_region.Intersect(chart_region);
2044 if (vpu_region.Empty())
2045 pqc->b_include =
false;
2047 pqc->b_include =
true;
2048 vp_region.Subtract(chart_region);
2051 pqc->b_include =
false;
2053 pqc->b_include =
true;
2057 pqc->b_include =
false;
2060 if (vp_region.Empty())
2067 if (b_has_overlays && (CHART_FAMILY_VECTOR == m_reference_family)) {
2068 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2071 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
2075 if (cte.Scale_ge(m_reference_scale)) {
2076 bool b_in_noshow =
false;
2077 for (
unsigned int ins = 0;
2078 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2079 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2089 LLRegion vpu_region(cvp_region);
2092 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2094 if (!chart_region.Empty()) vpu_region.Intersect(chart_region);
2096 if (vpu_region.Empty())
2097 pqc->b_include =
false;
2100 s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2101 if (b_overlay) pqc->b_include =
true;
2108 ChartData->GetChartTableEntry(m_refchart_dbIndex);
2109 if (s57chart::IsCellOverlayType(cte_ref.GetFullSystemPath())) {
2110 pqc->b_include =
true;
2122 m_eclipsed_stack_array.clear();
2124 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2127 if (!pqc->b_include) {
2129 if (cte.Scale_ge(m_reference_scale) &&
2130 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
2131 m_eclipsed_stack_array.push_back(pqc->dbIndex);
2132 pqc->b_eclipsed =
true;
2139 if (((m_bquiltanyproj || m_quilt_proj == PROJECTION_MERCATOR)) &&
2140 !vp_region.Empty()) {
2141 bool b_must_add_cm93 =
true;
2148 while( updd .HaveRects()) {
2149 wxRect rect = updd.GetRect();
2150 if( ( rect.width > 2 ) && ( rect.height > 2 ) ) {
2151 b_must_add_cm93 =
true;
2158 if (b_must_add_cm93) {
2159 for (
int ics = 0; ics < m_parent->GetpCurrentStack()->nEntry; ics++) {
2160 int i = m_parent->GetpCurrentStack()->GetDBIndex(ics);
2161 if (CHART_TYPE_CM93COMP ==
ChartData->GetDBChartType(i)) {
2164 qcnew->SetScale(
ChartData->GetDBChartScale(i));
2166 m_pcandidate_array->Add(qcnew);
2177 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
2179 if (pqc->b_include) {
2185 if (!b_vis && m_pcandidate_array->GetCount()) {
2188 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2193 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2196 if (cte.GetChartType() == CHART_TYPE_MBTILES)
continue;
2199 LLRegion vpck_region(vp_local.GetBBox());
2202 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2204 if (!chart_region.Empty()) vpck_region.Intersect(chart_region);
2206 if (!vpck_region.Empty()) {
2208 if (cte.Scale_eq(add_scale)) {
2209 pqc->b_include =
true;
2212 pqc->b_include =
true;
2213 add_scale = cte.GetScale();
2222 m_PatchList.DeleteContents(
true);
2223 m_PatchList.Clear();
2225 if (m_pcandidate_array->GetCount()) {
2226 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2234 if (m.GetChartType() == CHART_TYPE_CM93COMP)
2235 pqc->b_include =
true;
2238 if (pqc->b_include) {
2240 pqp->dbIndex = pqc->dbIndex;
2241 pqp->ProjType = m.GetChartProjectionType();
2244 pqp->quilt_region = pqc->GetCandidateRegion();
2247 pqp->b_Valid =
true;
2249 m_PatchList.Append(pqp);
2256 if (!m_bquiltanyproj) {
2258 m_quilt_proj = PROJECTION_MERCATOR;
2259 ChartBase *ppc = GetLargestScaleChart();
2260 if (ppc) m_quilt_proj = ppc->GetChartProjectionType();
2264 if (!m_bquiltanyproj) {
2267 for (
auto piqp : m_PatchList) {
2268 if ((piqp->ProjType != m_quilt_proj) &&
2269 (piqp->ProjType != PROJECTION_UNKNOWN))
2270 piqp->b_Valid =
false;
2275 for (
auto *piqp : m_PatchList) {
2276 for (
unsigned int ins = 0;
2277 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2278 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2281 piqp->b_Valid =
false;
2289 m_covered_region.Clear();
2294 bool b_skipCM93 =
false;
2295 if (m_reference_type == CHART_TYPE_CM93COMP) {
2297 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2298 PatchList::compatibility_iterator pcinode = m_PatchList.Item(i);
2306 if (m.GetChartType() == CHART_TYPE_CM93COMP) {
2308 piqp->ActiveRegion = piqp->quilt_region;
2309 piqp->ActiveRegion.Intersect(cvp_region);
2313 m_covered_region.Union(piqp->quilt_region);
2323 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2324 PatchList::compatibility_iterator pcinode = m_PatchList.Item(i);
2333 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2337 piqp->ActiveRegion = piqp->quilt_region;
2340 if (!b_has_overlays && m_PatchList.GetCount() < 25)
2341 piqp->ActiveRegion.Subtract(m_covered_region);
2343 piqp->ActiveRegion.Intersect(cvp_region);
2347 if (piqp->ActiveRegion.Empty() && (piqp->dbIndex != m_refchart_dbIndex))
2348 piqp->b_eclipsed =
true;
2351 piqp->b_overlay =
false;
2352 if (cte.GetChartFamily() == CHART_FAMILY_VECTOR) {
2353 piqp->b_overlay = s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2356 if (!piqp->b_overlay) m_covered_region.Union(piqp->quilt_region);
2361 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2362 PatchList::compatibility_iterator pcinode = m_PatchList.Item(i);
2371 LLRegion vpr_region = piqp->quilt_region;
2379 for (
unsigned int k = i + 1; k < m_PatchList.GetCount(); k++) {
2380 PatchList::compatibility_iterator pnode = m_PatchList.Item(k);
2401 if (!b_has_overlays) {
2402 if (!vpr_region.Empty()) {
2404 ChartData->GetChartTableEntry(pqp->dbIndex);
2405 LLRegion larger_scale_chart_region =
2408 vpr_region.Subtract(larger_scale_chart_region);
2417 PatchList::compatibility_iterator pinode = m_PatchList.Item(i);
2419 pqpi->ActiveRegion = vpr_region;
2428 if (pqpi->ActiveRegion.Empty()) pqpi->b_eclipsed =
true;
2436 m_covered_region.Union(pqpi->ActiveRegion);
2443 unsigned int il = 0;
2444 while (il < m_PatchList.GetCount()) {
2445 PatchList::compatibility_iterator pcinode = m_PatchList.Item(il);
2447 if (piqp->b_eclipsed) {
2450 bool b_noadd =
false;
2451 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size(); ir++) {
2452 if (piqp->dbIndex == m_eclipsed_stack_array[ir]) {
2457 if (!b_noadd) m_eclipsed_stack_array.push_back(piqp->dbIndex);
2459 m_PatchList.DeleteNode(pcinode);
2478 m_parent->EnablePaint(
false);
2485 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2487 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2488 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2489 ChartData->LockCacheChart(pqc->dbIndex);
2494 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2496 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2497 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2498 ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
true);
2507 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2509 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2510 if (
ChartData->IsChartLocked(pqc->dbIndex))
2511 pqc->b_locked =
true;
2513 pqc->b_locked =
ChartData->LockCacheChart(pqc->dbIndex);
2518 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2520 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2526 if (
ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
2528 pqc->b_locked =
true;
2533 m_parent->EnablePaint(
true);
2536 m_last_index_array = m_index_array;
2538 m_index_array.clear();
2541 unsigned int kl = m_PatchList.GetCount();
2542 for (
unsigned int k = 0; k < kl; k++) {
2543 PatchList::compatibility_iterator cnode = m_PatchList.Item((kl - k) - 1);
2544 m_index_array.push_back(cnode->GetData()->dbIndex);
2545 cnode = cnode->GetNext();
2551 m_quilt_depth_unit =
"";
2554 m_quilt_depth_unit = pc->GetDepthUnits();
2556 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2557 int units = ps52plib->m_nDepthUnitDisplay;
2560 m_quilt_depth_unit =
"Feet";
2563 m_quilt_depth_unit =
"Meters";
2566 m_quilt_depth_unit =
"Fathoms";
2572 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2573 PatchList::compatibility_iterator pnode = m_PatchList.Item(k);
2581 wxString du = pc->GetDepthUnits();
2582 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2583 int units = ps52plib->m_nDepthUnitDisplay;
2596 wxString dul = du.Lower();
2597 wxString ml = m_quilt_depth_unit.Lower();
2601 if (dul.StartsWith(
"meters") && ml.StartsWith(
"meters"))
2603 else if (dul.StartsWith(
"metres") && ml.StartsWith(
"metres"))
2605 else if (dul.StartsWith(
"fathoms") && ml.StartsWith(
"fathoms"))
2607 else if (dul.StartsWith(
"met") && ml.StartsWith(
"met"))
2611 m_quilt_depth_unit =
"";
2621 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2622 PatchList::compatibility_iterator pnode = m_PatchList.Item(k);
2626 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2627 wxLogMessage(
" Quilt Compose cache miss...");
2628 ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
2629 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2630 wxLogMessage(
" Oops, removing from quilt...");
2631 pqp->b_Valid =
false;
2638 if (!
ChartData->IsChartInCache(m_refchart_dbIndex))
2639 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
2645 m_bquilt_has_overlays =
false;
2646 m_max_error_factor = 0.;
2647 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2648 PatchList::compatibility_iterator pnode = m_PatchList.Item(k);
2656 m_max_error_factor =
2657 wxMax(m_max_error_factor, pc->GetChart_Error_Factor());
2658 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2659 bool isOverlay = IsChartS57Overlay(pqp->dbIndex);
2660 pqp->b_overlay = isOverlay;
2661 if (isOverlay) m_bquilt_has_overlays =
true;
2674 unsigned long xa_hash = 5381;
2675 for (
unsigned int im = 0; im < m_extended_stack_array.size(); im++) {
2676 int dbindex = m_extended_stack_array[im];
2677 xa_hash = ((xa_hash << 5) + xa_hash) + dbindex;
2680 m_xa_hash = xa_hash;
2688 if (!m_bcomposed)
return;
2692 if (GetnCharts() && !m_bbusy && !chart_region.Empty()) {
2698 if (!(chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2699 vp.b_MercatorProjectionOverride)) {
2703 chart_region, pqp->ActiveRegion, chart->GetNativeScale());
2704 if (!get_screen_region.Empty())
2705 rendered_region.Union(get_screen_region);
2708 chart = GetNextChart();
2712 m_rendered_region = rendered_region;
2717bool Quilt::RenderQuiltRegionViewOnDCNoText(wxMemoryDC &dc,
ViewPort &vp,
2719 return DoRenderQuiltRegionViewOnDC(dc, vp, chart_region);
2722bool Quilt::RenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
2724 return DoRenderQuiltRegionViewOnDCTextOnly(dc, vp, chart_region);
2727bool Quilt::DoRenderQuiltRegionViewOnDC(wxMemoryDC &dc,
ViewPort &vp,
2729#ifdef ocpnUSE_DIBSECTION
2735 if (!m_bcomposed)
return false;
2737 OCPNRegion rendered_region;
2739 if (GetnCharts() && !m_bbusy) {
2740 OCPNRegion screen_region = chart_region;
2746 ChartBase *chart = GetFirstChart();
2747 int chartsDrawn = 0;
2749 if (!chart_region.Empty()) {
2751 bool okToRender =
true;
2753 if (chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2754 vp.b_MercatorProjectionOverride)
2758 chart = GetNextChart();
2761 QuiltPatch *pqp = GetCurrentPatch();
2763 bool b_chart_rendered =
false;
2764 LLRegion get_region = pqp->ActiveRegion;
2767 chart_region, get_region, chart->GetNativeScale());
2768 if (!get_screen_region.Empty()) {
2769 if (!pqp->b_overlay) {
2770 if (chart->GetChartType() == CHART_TYPE_CM93COMP) {
2772 chart->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2774 s57chart *Chs57 =
dynamic_cast<s57chart *
>(chart);
2776 if (Chs57->m_RAZBuilt) {
2777 b_chart_rendered = Chs57->RenderRegionViewOnDCNoText(
2778 tmp_dc, vp, get_screen_region);
2781 ChartPlugInWrapper *ChPI =
2782 dynamic_cast<ChartPlugInWrapper *
>(chart);
2784 b_chart_rendered = ChPI->RenderRegionViewOnDCNoText(
2785 tmp_dc, vp, get_screen_region);
2787 b_chart_rendered = chart->RenderRegionViewOnDC(
2788 tmp_dc, vp, get_screen_region);
2790 b_chart_rendered =
true;
2797 screen_region.Subtract(get_screen_region);
2801 OCPNRegionIterator upd(get_screen_region);
2802 while (upd.HaveRects()) {
2803 wxRect rect = upd.GetRect();
2804 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc, rect.x,
2805 rect.y, wxCOPY,
true);
2809 tmp_dc.SelectObject(wxNullBitmap);
2811 if (b_chart_rendered) rendered_region.Union(get_screen_region);
2815 chart = GetNextChart();
2819 if (!chartsDrawn) m_parent->GetVP().SetProjectionType(PROJECTION_MERCATOR);
2822 if (m_bquilt_has_overlays && !chart_region.Empty()) {
2823 chart = GetFirstChart();
2825 QuiltPatch *pqp = GetCurrentPatch();
2827 if (pqp->b_overlay) {
2828 LLRegion get_region = pqp->ActiveRegion;
2830 chart_region, get_region, chart->GetNativeScale());
2831 if (!get_region.Empty()) {
2832 s57chart *Chs57 =
dynamic_cast<s57chart *
>(chart);
2834 Chs57->RenderOverlayRegionViewOnDC(tmp_dc, vp,
2837 ChartPlugInWrapper *ChPI =
2838 dynamic_cast<ChartPlugInWrapper *
>(chart);
2840 ChPI->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2844 OCPNRegionIterator upd(get_screen_region);
2845 while (upd.HaveRects()) {
2846 wxRect rect = upd.GetRect();
2847 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc,
2848 rect.x, rect.y, wxCOPY,
true);
2851 tmp_dc.SelectObject(wxNullBitmap);
2856 chart = GetNextChart();
2862 OCPNRegionIterator clrit(screen_region);
2863 while (clrit.HaveRects()) {
2864 wxRect rect = clrit.GetRect();
2866 dc.SetPen(*wxBLACK_PEN);
2867 dc.SetBrush(*wxBLACK_BRUSH);
2868 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
2870 dc.Blit(rect.x, rect.y, rect.width, rect.height, &dc, rect.x, rect.y,
2877 if (m_nHiLiteIndex >= 0) {
2878 OCPNRegion hiregion =
2880 wxRect box = hiregion.GetBox();
2882 if (!box.IsEmpty()) {
2885 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2886 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2893 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2897 q_dc.SelectObject(*m_pBM);
2898 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2899 q_dc.SelectObject(wxNullBitmap);
2904 wxBitmap hl_mask_bm(vp.rv_rect.width, vp.rv_rect.height, 1);
2906 mdc.SelectObject(hl_mask_bm);
2907 mdc.SetBackground(*wxBLACK_BRUSH);
2909 mdc.SetClippingRegion(box);
2910 mdc.SetBackground(*wxWHITE_BRUSH);
2912 mdc.SelectObject(wxNullBitmap);
2914 if (hl_mask_bm.IsOk()) {
2915 wxMask *phl_mask =
new wxMask(hl_mask_bm);
2916 m_pBM->SetMask(phl_mask);
2917 q_dc.SelectObject(*m_pBM);
2920 wxBitmap rbm(vp.rv_rect.width, vp.rv_rect.height);
2921 wxMask *pr_mask =
new wxMask(hl_mask_bm);
2923 rbm.SetMask(pr_mask);
2924 rdc.SelectObject(rbm);
2925 unsigned char hlcolor = 255;
2926 switch (global_color_scheme) {
2927 case GLOBAL_COLOR_SCHEME_DAY:
2928 case GLOBAL_COLOR_SCHEME_DAY_HICON:
2931 case GLOBAL_COLOR_SCHEME_DUSK:
2932 case GLOBAL_COLOR_SCHEME_NIGHT_HICON:
2935 case GLOBAL_COLOR_SCHEME_NIGHT:
2943 rdc.SetBackground(wxBrush(wxColour(hlcolor, 0, 0)));
2946 OCPNRegionIterator upd(hiregion);
2947 while (upd.HaveRects()) {
2948 wxRect rect = upd.GetRect();
2949 rdc.Blit(rect.x, rect.y, rect.width, rect.height, &q_dc, rect.x,
2950 rect.y, wxOR,
true);
2954 OCPNRegionIterator updq(hiregion);
2955 while (updq.HaveRects()) {
2956 wxRect rect = updq.GetRect();
2957 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &rdc, rect.x,
2958 rect.y, wxCOPY,
true);
2962 q_dc.SelectObject(wxNullBitmap);
2963 m_pBM->SetMask(NULL);
2966 dc.SelectObject(*m_pBM);
2969 rdc.SelectObject(wxNullBitmap);
2975 if (g_fog_overzoom) {
2978 if (scale_factor > g_overzoom_emphasis_base) {
2979 float fog = ((scale_factor - g_overzoom_emphasis_base) * 255.) / 20.;
2980 fog = wxMin(fog, 200.);
2984 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2985 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2992 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2996 q_dc.SelectObject(*m_pBM);
2997 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2998 q_dc.SelectObject(wxNullBitmap);
3000 wxImage src = m_pBM->ConvertToImage();
3003 wxMin((scale_factor - g_overzoom_emphasis_base) / 4, 4);
3005 wxImage dest = src.Blur(blur_factor);
3009 unsigned char *bg = src.GetData();
3010 wxColour color = m_parent->GetFogColor();
3012 float transparency = fog;
3015 wxImage dest(vp.rv_rect.width, vp.rv_rect.height);
3016 unsigned char *dest_data = (
unsigned char *) malloc( vp.rv_rect.width * vp.rv_rect.height * 3 *
sizeof(
unsigned char) );
3017 unsigned char *d = dest_data;
3019 float alpha = 1.0 - (float)transparency / 255.0;
3020 int sb = vp.rv_rect.width * vp.rv_rect.height;
3021 for(
int i = 0; i < sb; i++ ) {
3024 int r = ( ( *bg++ ) * a ) + (1.0-a) * color.Red();
3026 int g = ( ( *bg++ ) * a ) + (1.0-a) * color.Green();
3028 int b = ( ( *bg++ ) * a ) + (1.0-a) * color.Blue();
3032 dest.SetData( dest_data );
3037 ddc.SelectObject(dim);
3039 q_dc.SelectObject(*m_pBM);
3040 OCPNRegionIterator upd(rendered_region);
3041 while (upd.HaveRects()) {
3042 wxRect rect = upd.GetRect();
3043 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &ddc, rect.x,
3048 ddc.SelectObject(wxNullBitmap);
3049 q_dc.SelectObject(wxNullBitmap);
3052 dc.SelectObject(*m_pBM);
3060 SubstituteClearDC(dc, vp);
3064 SubstituteClearDC(dc, vp);
3068 m_rendered_region = rendered_region;
3074void Quilt::SubstituteClearDC(wxMemoryDC &dc,
ViewPort &vp) {
3076 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
3077 (m_pBM->GetHeight() != vp.rv_rect.height)) {
3083 if (NULL == m_pBM) {
3084 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
3087 dc.SelectObject(wxNullBitmap);
3088 dc.SelectObject(*m_pBM);
3089 dc.SetBackground(*wxBLACK_BRUSH);
3091 m_covered_region.Clear();
3094bool Quilt::DoRenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
3096 if (!m_bcomposed)
return false;
3098 OCPNRegion rendered_region;
3100 if (GetnCharts() && !m_bbusy) {
3101 OCPNRegion screen_region = chart_region;
3105 ChartBase *chart = GetLargestScaleChart();
3108 QuiltPatch *pqp = GetCurrentPatch();
3110 s57chart *Chs57 =
dynamic_cast<s57chart *
>(chart);
3112 Chs57->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3114 ChartPlugInWrapper *ChPI =
dynamic_cast<ChartPlugInWrapper *
>(chart);
3116 ChPI->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3121 chart = GetNextSmallerScaleChart();
3125 SubstituteClearDC(dc, vp);
ChartDB * ChartData
Global instance.
Charts database management
Generic Chart canvas base.
Base class for all chart types.
ChartCanvas - Main chart display and interaction component.
An iterator class for OCPNRegion.
A wrapper class for wxRegion with additional functionality.
bool Compose(const ViewPort &vp)
ViewPort - Core geographic projection and coordinate transformation engine.
double view_scale_ppm
Requested view scale in physical pixels per meter (ppm), before applying projections.
double ref_scale
The nominal scale of the "reference chart" for this view.
double rotation
Rotation angle of the viewport in radians.
wxPoint2DDouble GetDoublePixFromLL(double lat, double lon)
Convert latitude and longitude on the ViewPort to physical pixel coordinates with double precision.
void GetLLFromPix(const wxPoint &p, double *lat, double *lon)
Convert physical pixel coordinates on the ViewPort to latitude and longitude.
OCPNRegion GetVPRegionIntersect(const OCPNRegion ®ion, const LLRegion &llregion, int chart_native_scale)
Get the intersection of the viewport with a given region.
double clon
Center longitude of the viewport in degrees.
double clat
Center latitude of the viewport in degrees.
wxPoint GetPixFromLL(double lat, double lon)
Convert latitude and longitude on the ViewPort to physical pixel coordinates.
double chart_scale
Chart scale denominator (e.g., 50000 for a 1:50000 scale).
Global variables stored in configuration file.
Optimized wxBitmap Object.
Miscellaneous utilities, many of which string related.
Represents an entry in the chart table, containing information about a single chart.