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() {
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;
243 new ArrayOfSortedQuiltCandidates(CompareQuiltCandidateScales);
248 m_preferred_family = CHART_FAMILY_RASTER;
251 m_bquiltskew = g_bopengl;
253 m_bquiltanyproj = g_bopengl;
257 m_PatchList.DeleteContents(
true);
260 EmptyCandidateArray();
261 delete m_pcandidate_array;
263 m_extended_stack_array.clear();
268void Quilt::SetReferenceChart(
int dbIndex) {
276 m_refchart_dbIndex = dbIndex;
282bool Quilt::IsVPBlittable(
ViewPort &VPoint,
int dx,
int dy,
283 bool b_allow_vector) {
284 if (!m_vp_rendered.IsValid())
return false;
289 double deltax = p2.m_x - p1.m_x;
290 double deltay = p2.m_y - p1.m_y;
292 if ((fabs(deltax - dx) > 1e-2) || (fabs(deltay - dy) > 1e-2))
return false;
297bool Quilt::IsChartS57Overlay(
int db_index) {
298 if (db_index < 0)
return false;
301 if (CHART_FAMILY_VECTOR == cte.GetChartFamily()) {
302 return s57chart::IsCellOverlayType(cte.GetFullSystemPath());
307bool Quilt::IsChartQuiltableRef(
int db_index) {
308 if (db_index < 0 || db_index >
ChartData->GetChartTableEntries() - 1)
314 bool bproj_match =
true;
316 double skew_norm = ctei.GetChartSkew();
317 if (skew_norm > 180.) skew_norm -= 360.;
320 fabs(skew_norm) < 1.;
321 if (m_bquiltskew) skew_match =
true;
324 bool b_noshow =
false;
325 for (
unsigned int i = 0; i < m_parent->GetQuiltNoshowIindexArray().size();
327 if (m_parent->GetQuiltNoshowIindexArray()[i] ==
335 return (bproj_match & skew_match & !b_noshow);
338bool Quilt::IsChartInQuilt(
ChartBase *pc) {
340 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
342 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
343 if (
ChartData->OpenChartFromDB(pqc->dbIndex, FULL_INIT) == pc)
350bool Quilt::IsChartInQuilt(wxString &full_path) {
352 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
354 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
355 auto &cte =
ChartData->GetChartTableEntry(pqc->dbIndex);
356 if (cte.GetpsFullPath()->IsSameAs(full_path))
return true;
362std::vector<int> Quilt::GetCandidatedbIndexArray(
bool from_ref_chart,
363 bool exclude_user_hidden) {
364 std::vector<int> ret;
365 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
369 if (pqc->Scale_ge(m_reference_scale)) {
371 if (exclude_user_hidden) {
372 bool b_noshow =
false;
373 for (
unsigned int i = 0;
374 i < m_parent->GetQuiltNoshowIindexArray().size(); i++) {
375 if (m_parent->GetQuiltNoshowIindexArray()[i] ==
382 if (!b_noshow) ret.push_back(pqc->dbIndex);
384 ret.push_back(pqc->dbIndex);
388 ret.push_back(pqc->dbIndex);
395 return (cnode->GetData());
400void Quilt::EmptyCandidateArray() {
401 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
402 delete m_pcandidate_array->Item(i);
405 m_pcandidate_array->Clear();
415 if (!m_bcomposed)
return NULL;
417 if (m_bbusy)
return NULL;
421 cnode = m_PatchList.GetFirst();
422 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetNext();
423 if (cnode && cnode->GetData()->b_Valid)
424 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
435 if (m_bbusy)
return NULL;
440 cnode = cnode->GetNext();
441 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetNext();
442 if (cnode && cnode->GetData()->b_Valid)
443 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
450ChartBase *Quilt::GetNextSmallerScaleChart() {
455 if (m_bbusy)
return NULL;
460 cnode = cnode->GetPrevious();
461 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetPrevious();
462 if (cnode && cnode->GetData()->b_Valid)
463 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
470ChartBase *Quilt::GetLargestScaleChart() {
473 if (m_bbusy)
return NULL;
477 cnode = m_PatchList.GetLast();
479 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
486 LLRegion chart_region;
487 LLRegion screen_region(vp.GetBBox());
492 if (fabs(cte.GetLonMax() - cte.GetLonMin()) > 180.) {
509 return LLRegion(-80, vp.GetBBox().GetMinLon(), 80,
510 vp.GetBBox().GetMaxLon());
514 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
515 bool aux_ply_skipped =
false;
516 if (nAuxPlyEntries >= 1) {
517 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
518 int nAuxPly = cte.GetAuxCntTableEntry(ip);
519 if (nAuxPly > AUX_PLY_PERF_LIMIT) {
522 aux_ply_skipped =
true;
525 float *pfp = cte.GetpAuxPlyTableEntry(ip);
526 LLRegion t_region(nAuxPly, pfp);
527 t_region.Intersect(screen_region);
531 if (!t_region.Empty()) chart_region.Union(t_region);
535 if (aux_ply_skipped || nAuxPlyEntries == 0) {
536 int n_ply_entries = cte.GetnPlyEntries();
537 float *pfp = cte.GetpPlyTable();
539 if (n_ply_entries >= 3)
542 LLRegion t_region(n_ply_entries, pfp);
543 t_region.Intersect(screen_region);
547 if (!t_region.Empty()) chart_region.Union(t_region);
550 chart_region = screen_region;
554 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
555 if (nNoCovrPlyEntries) {
556 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
557 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
558 if (nNoCovrPly > NOCOVR_PLY_PERF_LIMIT) {
563 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
565 LLRegion t_region(nNoCovrPly, pfp);
566 t_region.Intersect(screen_region);
577 if (!t_region.Empty()) {
578 LLRegion test_region = chart_region;
579 test_region.Subtract(t_region);
581 if (!test_region.Empty()) chart_region = test_region;
590 if ((cte.GetScale() > 90000000) &&
591 (cte.GetChartFamily() == CHART_FAMILY_RASTER))
592 chart_region = screen_region;
600bool Quilt::IsQuiltVector() {
601 if (m_bbusy)
return false;
607 wxPatchListNode *cnode = m_PatchList.GetFirst();
609 if (cnode->GetData()) {
612 if ((pqp->b_Valid) && (!pqp->b_eclipsed) &&
613 (pqp->dbIndex <
ChartData->GetChartTableEntries())) {
615 ChartData->GetChartTableEntry(pqp->dbIndex);
617 if (ctei.GetChartFamily() == CHART_FAMILY_VECTOR) {
623 cnode = cnode->GetNext();
630bool Quilt::DoesQuiltContainPlugins() {
631 if (m_bbusy)
return false;
637 wxPatchListNode *cnode = m_PatchList.GetFirst();
639 if (cnode->GetData()) {
642 if ((pqp->b_Valid) && (!pqp->b_eclipsed)) {
644 ChartData->GetChartTableEntry(pqp->dbIndex);
646 if (ctei.GetChartType() == CHART_TYPE_PLUGIN) {
652 cnode = cnode->GetNext();
659int Quilt::GetChartdbIndexAtPix(
ViewPort &VPoint, wxPoint p) {
660 if (m_bbusy)
return -1;
669 wxPatchListNode *cnode = m_PatchList.GetFirst();
671 if (cnode->GetData()->ActiveRegion.Contains(lat, lon)) {
672 ret = cnode->GetData()->dbIndex;
675 cnode = cnode->GetNext();
683 if (m_bbusy)
return NULL;
695 wxPatchListNode *cnode = m_PatchList.GetFirst();
698 if (!pqp->b_overlay && (pqp->ActiveRegion.Contains(lat, lon)))
699 if (
ChartData->IsChartInCache(pqp->dbIndex)) {
700 pret =
ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
702 cnode = cnode->GetNext();
710 if (m_bbusy)
return NULL;
722 wxPatchListNode *cnode = m_PatchList.GetFirst();
725 if (pqp->b_overlay && (pqp->ActiveRegion.Contains(lat, lon)))
726 pret =
ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
727 cnode = cnode->GetNext();
734void Quilt::InvalidateAllQuiltPatchs() {
745std::vector<int> Quilt::GetQuiltIndexArray() {
746 return m_index_array;
748 std::vector<int> ret;
750 if (m_bbusy)
return ret;
754 wxPatchListNode *cnode = m_PatchList.GetFirst();
756 ret.push_back(cnode->GetData()->dbIndex);
757 cnode = cnode->GetNext();
765bool Quilt::IsQuiltDelta(
ViewPort &vp) {
766 if (!m_vp_quilt.IsValid() || !m_bcomposed)
return true;
770 if (m_vp_quilt.m_projection_type != vp.m_projection_type)
return true;
775 wxPoint cp_last, cp_this;
780 return (cp_last != cp_this);
788 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
790 if (pRefChart) pRefChart->AdjustVP(vp_last, vp_proposed);
793double Quilt::GetRefNativeScale() {
794 double ret_val = 1.0;
797 if (pc) ret_val = pc->GetNativeScale();
803int Quilt::GetNewRefChart() {
809 int new_ref_dbIndex = m_refchart_dbIndex;
810 unsigned int im = m_extended_stack_array.size();
812 for (
unsigned int is = 0; is < im; is++) {
814 ChartData->GetChartTableEntry(m_extended_stack_array[is]);
816 double skew_norm = m.GetChartSkew();
817 if (skew_norm > 180.) skew_norm -= 360.;
819 if ((m.Scale_ge(m_reference_scale)) &&
820 (m_reference_family == m.GetChartFamily()) &&
821 (m_bquiltanyproj || m_quilt_proj == m.GetChartProjectionType()) &&
822 (m_bquiltskew || (fabs(skew_norm) < 1.0))) {
823 new_ref_dbIndex = m_extended_stack_array[is];
828 return new_ref_dbIndex;
831int Quilt::GetNomScaleMax(
int scale, ChartTypeEnum type,
832 ChartFamilyEnum family) {
834 case CHART_FAMILY_RASTER: {
838 case CHART_FAMILY_VECTOR: {
848int Quilt::GetNomScaleMin(
int scale, ChartTypeEnum type,
849 ChartFamilyEnum family) {
850 double zoom_mod = (double)g_chart_zoom_modifier_raster;
852 if (family == CHART_FAMILY_VECTOR)
853 zoom_mod = (double)g_chart_zoom_modifier_vector;
855 double modf = zoom_mod / 5.;
856 double mod = pow(16., modf);
857 mod = wxMax(mod, .2);
858 mod = wxMin(mod, 16.0);
862 case CHART_FAMILY_RASTER: {
863 if (CHART_TYPE_MBTILES == type)
869 return scale * 1 * mod;
872 case CHART_FAMILY_VECTOR: {
873 return scale * 4 * mod;
877 mod = wxMin(mod, 2.0);
878 return scale * 2 * mod;
884 int index, nom, min, max;
887int Quilt::AdjustRefOnZoom(
bool b_zin, ChartFamilyEnum family,
888 ChartTypeEnum type,
double proposed_scale_onscreen) {
889 std::vector<scale> scales;
890 std::vector<scale> scales_mbtiles;
899 bool b_allow_fullscreen_ref =
900 (family == CHART_FAMILY_VECTOR) || b_zin || g_bopengl;
904 int smallest_scale = 1;
905 for (
size_t i = 0; i < m_extended_stack_array.size(); i++) {
906 int index = m_extended_stack_array[i];
907 if (
ChartData->GetDBChartType(index) == type)
908 smallest_scale = wxMax(smallest_scale,
ChartData->GetDBChartScale(index));
913 for (
size_t i = 0; i < m_extended_stack_array.size(); i++) {
914 int test_db_index = m_extended_stack_array[i];
916 if (b_allow_fullscreen_ref ||
917 m_parent->GetpCurrentStack()->DoesStackContaindbIndex(test_db_index)) {
918 if ((family ==
ChartData->GetDBChartFamily(test_db_index)) &&
919 IsChartQuiltableRef(test_db_index)
921 int nscale =
ChartData->GetDBChartScale(test_db_index);
923 int nmax_scale = GetNomScaleMax(nscale, type, family);
927 if (0 == i_first) nmax_scale = 1;
929 int nmin_scale = GetNomScaleMin(nscale, type, family);
932 if ((type == CHART_TYPE_KAP) && (nscale == smallest_scale))
937 if ((type == CHART_TYPE_MBTILES) && (nscale == smallest_scale))
940 if (CHART_TYPE_MBTILES ==
ChartData->GetDBChartType(test_db_index))
941 scales_mbtiles.push_back(
942 scale{test_db_index, nscale, nmin_scale, nmax_scale});
945 scale{test_db_index, nscale, nmin_scale, nmax_scale});
952 if (scales.empty()) scales = scales_mbtiles;
959 if (CHART_FAMILY_VECTOR == family) {
960 for (
size_t i = scales.size(); i; i--) {
961 int test_db_index = scales[i - 1].index;
962 if (type ==
ChartData->GetDBChartType(test_db_index)) {
963 scales[i - 1].min = scales[i - 1].nom * 80;
975 if (scales.size() > 1) {
976 for (
unsigned i = 0; i < scales.size() - 1; i++) {
977 int min_scale_test = wxMax(scales[i].min, scales[i + 1].max + 1);
978 min_scale_test = wxMin(min_scale_test, scales[i].min * 2);
979 scales[i].min = min_scale_test;
988 if (scales.size() > 2) {
989 for (
size_t i = scales.size() - 2; i >= 1; i--) {
990 scales[i].max = wxMin(scales[i].max, scales[i - 1].min - 1);
994 int new_ref_dbIndex = -1;
998 for (
size_t i = 0; i < scales.size(); i++) {
999 if ((proposed_scale_onscreen <
1002 (proposed_scale_onscreen > scales[i].max)) {
1003 new_ref_dbIndex = scales[i].index;
1008 return new_ref_dbIndex;
1011int Quilt::AdjustRefOnZoomOut(
double proposed_scale_onscreen) {
1013 m_lost_refchart_dbIndex = -1;
1015 int current_db_index = m_refchart_dbIndex;
1016 int current_family = m_reference_family;
1017 ChartTypeEnum current_type = (ChartTypeEnum)m_reference_type;
1019 if (m_refchart_dbIndex >= 0) {
1021 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1022 current_family = cte.GetChartFamily();
1023 current_type = (ChartTypeEnum)cte.GetChartType();
1026 if (current_type == CHART_TYPE_CM93COMP)
return current_db_index;
1028 int proposed_ref_index =
1029 AdjustRefOnZoom(
false, (ChartFamilyEnum)current_family, current_type,
1030 proposed_scale_onscreen);
1033 if (proposed_ref_index < 0) {
1034 m_zout_family = current_family;
1035 m_zout_type = current_type;
1036 m_zout_dbindex = current_db_index;
1039 if (proposed_ref_index < 0) {
1040 return m_refchart_dbIndex;
1042 SetReferenceChart(proposed_ref_index);
1043 return proposed_ref_index;
1047int Quilt::AdjustRefOnZoomIn(
double proposed_scale_onscreen) {
1049 m_lost_refchart_dbIndex = -1;
1051 int current_db_index = m_refchart_dbIndex;
1052 int current_family = m_reference_family;
1053 ChartTypeEnum current_type = (ChartTypeEnum)m_reference_type;
1055 if (m_zout_family >= 0) {
1056 current_type = (ChartTypeEnum)m_zout_type;
1057 current_family = m_zout_family;
1063 if (current_type == CHART_TYPE_CM93COMP) {
1064 if (m_zout_family >= 0) {
1065 current_family =
ChartData->GetDBChartFamily(m_zout_dbindex);
1067 return current_db_index;
1070 if ((-1 == m_refchart_dbIndex) && (m_zout_dbindex >= 0))
1071 BuildExtendedChartStackAndCandidateArray(m_zout_dbindex, m_vp_quilt);
1073 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, m_vp_quilt);
1075 int proposed_ref_index =
1076 AdjustRefOnZoom(
true, (ChartFamilyEnum)current_family, current_type,
1077 proposed_scale_onscreen);
1079 if (current_db_index == -1) {
1080 SetReferenceChart(proposed_ref_index);
1081 return proposed_ref_index;
1084 if (proposed_ref_index != -1) {
1085 if (
ChartData->GetDBChartScale(current_db_index) >=
1086 ChartData->GetDBChartScale(proposed_ref_index)) {
1087 SetReferenceChart(proposed_ref_index);
1088 return proposed_ref_index;
1091 proposed_ref_index = current_db_index;
1093 SetReferenceChart(proposed_ref_index);
1095 return proposed_ref_index;
1098bool Quilt::IsChartSmallestScale(
int dbIndex) {
1103 int specified_type =
ChartData->GetDBChartType(dbIndex);
1104 int target_dbindex = -1;
1106 unsigned int target_stack_index = 0;
1107 if (m_extended_stack_array.size()) {
1108 while ((target_stack_index <= (m_extended_stack_array.size() - 1))) {
1109 int test_db_index = m_extended_stack_array[target_stack_index];
1111 if (specified_type ==
ChartData->GetDBChartType(test_db_index))
1112 target_dbindex = test_db_index;
1114 target_stack_index++;
1117 return (dbIndex == target_dbindex);
1120LLRegion Quilt::GetHiliteRegion() {
1126 for (
auto &index : m_HiLiteIndexArray) {
1128 LLRegion cell_region = GetChartQuiltRegion(cte, m_vp_quilt);
1129 r.Union(cell_region);
1133 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
1134 wxPatchListNode *pcinode = m_PatchList.Item(i);
1136 if ((index == piqp->dbIndex) && (piqp->b_Valid))
1138 r.Union(piqp->ActiveRegion);
1147LLRegion Quilt::GetHiliteRegion() {
1149 if (m_nHiLiteIndex >= 0) {
1151 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
1152 wxPatchListNode *pcinode = m_PatchList.Item(i);
1154 if ((m_nHiLiteIndex == piqp->dbIndex) && (piqp->b_Valid))
1156 r = piqp->ActiveRegion;
1163 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1165 if (m_nHiLiteIndex == pqc->dbIndex) {
1166 LLRegion chart_region = pqc->GetCandidateRegion();
1167 if (!chart_region.Empty()) {
1169 bool b_eclipsed =
false;
1170 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size();
1172 if (m_nHiLiteIndex == m_eclipsed_stack_array[ir]) {
1178 if (!b_eclipsed) r = chart_region;
1188 ChartData->GetChartTableEntry(m_nHiLiteIndex);
1189 if (cte.GetChartType() == CHART_TYPE_MBTILES) {
1190 r = GetTilesetRegion(m_nHiLiteIndex);
1198const LLRegion &Quilt::GetTilesetRegion(
int dbIndex) {
1199 LLRegion world_region(-90, -180, 90, 180);
1202 LLRegion &target_region =
const_cast<LLRegion &
>(cte.quilt_candidate_region);
1204 if (!target_region.Empty())
return target_region;
1207 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
1208 if (nAuxPlyEntries >= 1) {
1209 target_region.Clear();
1210 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
1211 float *pfp = cte.GetpAuxPlyTableEntry(ip);
1212 int nAuxPly = cte.GetAuxCntTableEntry(ip);
1214 target_region.Union(LLRegion(nAuxPly, pfp));
1217 std::vector<float> vec =
ChartData->GetReducedPlyPoints(dbIndex);
1219 std::vector<float> vecr;
1220 for (
size_t i = 0; i < vec.size() / 2; i++) {
1221 float a = vec[i * 2 + 1];
1227 std::vector<float>::iterator it = vecr.begin();
1229 if (vecr.size() / 2 >= 3) {
1232 target_region = LLRegion(vecr.size() / 2, (
float *)&(*it));
1234 target_region = world_region;
1238 if (!target_region.Empty()) {
1239 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
1240 if (nNoCovrPlyEntries) {
1241 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
1242 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
1243 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
1245 LLRegion t_region = LLRegion(nNoCovrPly, pfp);
1252 if (!t_region.Empty()) {
1253 LLRegion test_region = target_region;
1254 test_region.Subtract(t_region);
1256 if (!test_region.Empty()) target_region = test_region;
1270 return target_region;
1273int Quilt::SelectRefChartByFamily(ChartFamilyEnum family) {
1275 auto array = GetFullscreenIndexArray();
1277 std::sort(array.begin(), array.end(), CompareScalesStd);
1281 for (
int dbIndex : array) {
1287 wxFileName fn(cte_candidate.GetFullPath());
1288 if (fn.GetPath().Lower().Contains(
"basemap"))
continue;
1291 if (cte_candidate.GetChartFamily() == family) {
1293 m_chart_familyFix = family;
1298 m_lost_refchart_dbIndex = -1;
1303bool Quilt::BuildExtendedChartStackAndCandidateArray(
int ref_db_index,
1305 double zoom_test_val = .002;
1308 EmptyCandidateArray();
1309 m_extended_stack_array.clear();
1310 m_fullscreen_index_array.clear();
1312 int reference_scale = 1e8;
1313 int reference_type = -1;
1314 int reference_family = -1;
1316 m_bquiltanyproj ? vp_in.m_projection_type : PROJECTION_UNKNOWN;
1318 if (ref_db_index >= 0) {
1320 ChartData->GetChartTableEntry(ref_db_index);
1321 reference_scale = cte_ref.GetScale();
1322 reference_type = cte_ref.GetChartType();
1323 if (!m_bquiltanyproj) quilt_proj =
ChartData->GetDBChartProj(ref_db_index);
1324 reference_family = cte_ref.GetChartFamily();
1327 bool b_need_resort =
false;
1337 int n_charts = m_parent->GetpCurrentStack()->nEntry;
1341 for (
int ics = 0; ics < n_charts; ics++) {
1342 int istack = m_parent->GetpCurrentStack()->GetDBIndex(ics);
1343 if (istack < 0)
continue;
1344 m_extended_stack_array.push_back(istack);
1350 if (reference_type == CHART_TYPE_CM93COMP)
continue;
1354 if (cte.GetChartType() == CHART_TYPE_MBTILES) {
1355 wxFileName fn(cte.GetFullPath());
1356 if (fn.GetPath().Lower().Contains(
"basemap")) {
1357 if (!m_parent->GetbEnableBasemapTile()) {
1358 m_extended_stack_array.pop_back();
1370 if ((cte.GetChartType() == CHART_TYPE_PLUGIN) ||
1371 (reference_type == CHART_TYPE_PLUGIN)) {
1372 if (reference_family != cte.GetChartFamily()) {
1376 if (reference_type != cte.GetChartType()) {
1382 wxFileName fnb(cte.GetFullPath());
1383 if (!fnb.GetPath().Lower().Contains(
"basemap"))
continue;
1387 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1390 int candidate_chart_scale = cte.GetScale();
1391 double chart_native_ppm =
1392 m_canvas_scale_factor / (double)candidate_chart_scale;
1394 if ((zoom_factor < zoom_test_val) &&
1399 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
1400 m_extended_stack_array.pop_back();
1404 double skew_norm = cte.GetChartSkew();
1405 if (skew_norm > 180.) skew_norm -= 360.;
1407 if ((m_bquiltskew ? 1 : fabs(skew_norm) < 1.0) &&
1408 (m_bquiltanyproj || cte.GetChartProjectionType() == quilt_proj)) {
1410 qcnew->dbIndex = istack;
1411 qcnew->SetScale(cte.GetScale());
1412 m_pcandidate_array->push_back(qcnew);
1439 int n_all_charts =
ChartData->GetChartTableEntries();
1441 LLBBox viewbox = vp_local.GetBBox();
1442 int sure_index = -1;
1443 int sure_index_scale = 0;
1444 int sure_index_type = -1;
1446 for (
int i = 0; i < n_all_charts; i++) {
1450 int groupIndex = m_parent->m_groupIndex;
1451 if ((groupIndex > 0) && (!
ChartData->IsChartInGroup(i, groupIndex)))
1456 if (cte.GetChartType() == CHART_TYPE_MBTILES) {
1457 wxFileName fn(cte.GetFullPath());
1458 if (fn.GetPath().Lower().Contains(
"basemap")) {
1459 if (!m_parent->GetbEnableBasemapTile()) {
1466 if (
ChartData->IsChartDirectoryExcluded(cte.GetFullPath()))
continue;
1468 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
1469 m_fullscreen_index_array.push_back(i);
1474 wxFileName fn(cte.GetFullSystemPath());
1475 if (!androidIsDirWritable(fn.GetPath()))
continue;
1477 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1479 const LLBBox &chart_box = cte.GetBBox();
1480 if ((viewbox.IntersectOut(chart_box)))
continue;
1482 if (cte.GetChartType() == CHART_TYPE_PLUGIN) {
1483 if (!
ChartData->IsChartAvailable(i))
continue;
1486 m_fullscreen_index_array.push_back(i);
1493 bool guest_family_include =
false;
1494 if (reference_family != cte.GetChartFamily()) {
1495 wxFileName fn(cte.GetFullPath());
1496 if (fn.GetPath().Lower().Contains(
"basemap")) {
1497 guest_family_include =
true;
1500 if (m_lost_refchart_dbIndex == i) guest_family_include =
true;
1502 if ((cte.GetChartType() != CHART_TYPE_MBTILES) && !guest_family_include)
1506 if (!m_bquiltanyproj && quilt_proj != cte.GetChartProjectionType())
1509 double skew_norm = cte.GetChartSkew();
1510 if (skew_norm > 180.) skew_norm -= 360.;
1512 if (!m_bquiltskew && fabs(skew_norm) > 1.0)
continue;
1517 if( CHART_TYPE_S57 == cte.GetChartType() ) {
1519 double chart_area = (cte.GetLonMax() - cte.GetLonMin()) *
1520 (cte.GetLatMax() - cte.GetLatMin());
1521 double quilt_area = viewbox.GetLonRange() * viewbox.GetLatRange();
1522 if ((chart_area / quilt_area) < .01)
continue;
1525 int candidate_chart_scale = cte.GetScale();
1531 if (!cte.Scale_ge(reference_scale)) {
1532 if (cte.Scale_gt(sure_index_scale)) {
1534 sure_index_scale = candidate_chart_scale;
1535 sure_index_type = cte.GetChartType();
1544 double chart_native_ppm =
1545 m_canvas_scale_factor / (double)candidate_chart_scale;
1547 double zoom_factor_test_extra = 0.2;
1553 double ref_scale_test = reference_scale;
1554 if (cte.GetChartType() == CHART_TYPE_MBTILES)
1555 ref_scale_test = candidate_chart_scale;
1557 if ((cte.Scale_ge(ref_scale_test) && (zoom_factor > zoom_test_val)) ||
1558 (zoom_factor > zoom_factor_test_extra)) {
1559 LLRegion cell_region = GetChartQuiltRegion(cte, vp_local);
1564 if (!cell_region.Empty()) {
1567 bool b_exists =
false;
1568 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1569 if (i == m_extended_stack_array[ir]) {
1583 bool b_noadd =
false;
1584 auto &cte_n =
ChartData->GetChartTableEntry(i);
1585 for (
unsigned int id = 0;
id < m_extended_stack_array.size();
id++) {
1586 if (m_extended_stack_array[
id] != -1) {
1588 ChartData->GetChartTableEntry(m_extended_stack_array[
id]);
1589 bool bsameTime =
false;
1590 if (cte_m.GetFileTime() && cte_n.GetFileTime()) {
1591 if (labs(cte_m.GetFileTime() - cte_n.GetFileTime()) < 60)
1594 if (cte_m.GetChartEditionDate() == cte_n.GetChartEditionDate())
1598 if (cte_n.GetpFileName()->IsSameAs(*(cte_m.GetpFileName())))
1605 m_extended_stack_array.push_back(i);
1610 candidate_chart_scale);
1612 m_pcandidate_array->push_back(qcnew);
1614 b_need_resort =
true;
1623 if (-1 != sure_index) {
1625 bool sure_exists =
false;
1626 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1627 if (sure_index == m_extended_stack_array[ir]) {
1634 if (!sure_exists && (sure_index_type != CHART_TYPE_MBTILES)) {
1635 m_extended_stack_array.push_back(sure_index);
1638 qcnew->dbIndex = sure_index;
1639 qcnew->SetScale(
ChartData->GetDBChartScale(sure_index));
1640 m_pcandidate_array->push_back(qcnew);
1642 b_need_resort =
true;
1647 if (b_need_resort && m_extended_stack_array.size() > 1) {
1648 std::sort(m_extended_stack_array.begin(), m_extended_stack_array.end(),
1652 std::sort(m_fullscreen_index_array.begin(), m_fullscreen_index_array.end(),
1653 CompareScalesStdFULLSCREEN);
1658int Quilt::AdjustRefSelection(
const ViewPort &vp_in) {
1673 vp_local.SetRotationAngle(0.);
1675 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1677 ChartFamilyEnum family = CHART_FAMILY_RASTER;
1678 ChartTypeEnum type = CHART_TYPE_KAP;
1681 if (m_refchart_dbIndex >= 0) {
1683 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1684 type = (ChartTypeEnum)cte_ref.GetChartType();
1685 family = (ChartFamilyEnum)cte_ref.GetChartFamily();
1688 int ret_index = AdjustRefOnZoom(
true, family, type, vp_in.
chart_scale);
1693double Quilt::GetBestStartScale(
int dbi_ref_hint,
const ViewPort &vp_in) {
1703 int tentative_ref_index = dbi_ref_hint;
1704 if (dbi_ref_hint < 0) {
1711 tentative_ref_index = m_parent->GetpCurrentStack()->GetDBIndex(0);
1718 vp_local.SetRotationAngle(0.);
1720 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1724 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1726 if (qc->dbIndex == tentative_ref_index) {
1732 if (!bf && m_pcandidate_array->GetCount()) {
1733 tentative_ref_index = GetNewRefChart();
1734 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1737 double proposed_scale_onscreen = vp_in.
chart_scale;
1739 if (m_pcandidate_array->GetCount()) {
1740 SetReferenceChart(tentative_ref_index);
1744 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1746 if (IsChartQuiltableRef(qc->dbIndex)) {
1747 SetReferenceChart(qc->dbIndex);
1754 SetReferenceChart(m_parent->GetpCurrentStack()->GetDBIndex(0));
1757 if (m_refchart_dbIndex >= 0) {
1762 double min_ref_scale =
1764 double max_ref_scale = pc->GetNormalScaleMax(
1766 if ((proposed_scale_onscreen >= min_ref_scale) &&
1767 (proposed_scale_onscreen <= max_ref_scale))
1770 proposed_scale_onscreen = wxMin(proposed_scale_onscreen, max_ref_scale);
1771 proposed_scale_onscreen = wxMax(proposed_scale_onscreen, min_ref_scale);
1779 if (m_refchart_dbIndex >= 0 &&
ChartData)
1780 return ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
1784void Quilt::UnlockQuilt() {
1785 wxASSERT(m_bbusy ==
false);
1788 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1790 ChartData->UnLockCacheChart(pqc->dbIndex);
1800 if (!m_parent->GetpCurrentStack())
return false;
1802 if (m_bbusy)
return false;
1811 if (m_refchart_dbIndex >= 0) {
1813 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1814 m_reference_scale = cte_ref.GetScale();
1815 m_reference_type = cte_ref.GetChartType();
1816 if (!m_bquiltanyproj)
1817 m_quilt_proj =
ChartData->GetDBChartProj(m_refchart_dbIndex);
1818 m_reference_family = cte_ref.GetChartFamily();
1822 if (!m_bquiltanyproj) vp_local.SetProjectionType(m_quilt_proj);
1829 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1869 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1871 if (qc->dbIndex == m_refchart_dbIndex) {
1880 if (m_chart_familyFix == CHART_FAMILY_UNKNOWN) {
1881 if (!bf && m_pcandidate_array->GetCount() &&
1882 (m_reference_type != CHART_TYPE_CM93COMP)) {
1883 m_lost_refchart_dbIndex = m_refchart_dbIndex;
1884 int candidate_ref_index = GetNewRefChart();
1885 if (m_refchart_dbIndex != candidate_ref_index) {
1886 m_refchart_dbIndex = candidate_ref_index;
1887 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1894 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1895 if (m_pcandidate_array->GetCount()) {
1896 int alternate_index =
1897 m_pcandidate_array->Item(m_pcandidate_array->GetCount() - 1)
1900 ChartData->GetChartTableEntry(alternate_index);
1902 if (GetRefFamily() == cte_alt.GetChartFamily()) {
1903 m_refchart_dbIndex = alternate_index;
1904 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex,
1912 if ((-1 != m_lost_refchart_dbIndex) &&
1913 (m_lost_refchart_dbIndex != m_refchart_dbIndex)) {
1916 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1917 if (m_lost_refchart_dbIndex == m_extended_stack_array[ir]) {
1918 m_refchart_dbIndex = m_lost_refchart_dbIndex;
1919 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1920 m_lost_refchart_dbIndex = -1;
1926 bool b_has_overlays =
false;
1929 if (CHART_FAMILY_VECTOR == m_reference_family) {
1930 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1934 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1935 b_has_overlays =
true;
1947 const LLRegion cvp_region = vp_local.GetLLRegion(vp_local.rv_rect);
1948 LLRegion vp_region = cvp_region;
1954 for (ir = 0; ir < m_pcandidate_array->GetCount();
1958 if (pqc->dbIndex == m_refchart_dbIndex) {
1967 const double z = 111274.96299695622;
1973 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1975 LLRegion vpu_region(cvp_region);
1978 LLRegion &chart_region = pqc_ref->GetReducedCandidateRegion(factor);
1980 if (cte_ref.GetChartType() != CHART_TYPE_MBTILES) {
1981 if (!chart_region.Empty()) {
1982 vpu_region.Intersect(chart_region);
1984 if (vpu_region.Empty())
1985 pqc_ref->b_include =
false;
1987 pqc_ref->b_include =
true;
1988 vp_region.Subtract(chart_region);
1991 pqc_ref->b_include =
false;
1993 pqc_ref->b_include =
false;
1998 if (!vp_region.Empty()) {
1999 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2002 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
2009 if (CHART_FAMILY_VECTOR == m_reference_family) {
2010 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
2016 if (CHART_TYPE_MBTILES == cte.GetChartType()) {
2017 pqc->b_include =
false;
2021 if (cte.Scale_ge(m_reference_scale)) {
2025 bool b_in_noshow =
false;
2026 for (
unsigned int ins = 0;
2027 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2028 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2038 LLRegion vpu_region(cvp_region);
2041 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2043 if (!chart_region.Empty()) {
2044 vpu_region.Intersect(chart_region);
2046 if (vpu_region.Empty())
2047 pqc->b_include =
false;
2049 pqc->b_include =
true;
2050 vp_region.Subtract(chart_region);
2053 pqc->b_include =
false;
2055 pqc->b_include =
true;
2059 pqc->b_include =
false;
2062 if (vp_region.Empty())
2069 if (b_has_overlays && (CHART_FAMILY_VECTOR == m_reference_family)) {
2070 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2073 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
2077 if (cte.Scale_ge(m_reference_scale)) {
2078 bool b_in_noshow =
false;
2079 for (
unsigned int ins = 0;
2080 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2081 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2091 LLRegion vpu_region(cvp_region);
2094 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2096 if (!chart_region.Empty()) vpu_region.Intersect(chart_region);
2098 if (vpu_region.Empty())
2099 pqc->b_include =
false;
2102 s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2103 if (b_overlay) pqc->b_include =
true;
2110 ChartData->GetChartTableEntry(m_refchart_dbIndex);
2111 if (s57chart::IsCellOverlayType(cte_ref.GetFullSystemPath())) {
2112 pqc->b_include =
true;
2124 m_eclipsed_stack_array.clear();
2126 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2129 if (!pqc->b_include) {
2131 if (cte.Scale_ge(m_reference_scale) &&
2132 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
2133 m_eclipsed_stack_array.push_back(pqc->dbIndex);
2134 pqc->b_eclipsed =
true;
2141 if (((m_bquiltanyproj || m_quilt_proj == PROJECTION_MERCATOR)) &&
2142 !vp_region.Empty()) {
2143 bool b_must_add_cm93 =
true;
2150 while( updd .HaveRects()) {
2151 wxRect rect = updd.GetRect();
2152 if( ( rect.width > 2 ) && ( rect.height > 2 ) ) {
2153 b_must_add_cm93 =
true;
2160 if (b_must_add_cm93) {
2161 for (
int ics = 0; ics < m_parent->GetpCurrentStack()->nEntry; ics++) {
2162 int i = m_parent->GetpCurrentStack()->GetDBIndex(ics);
2163 if (CHART_TYPE_CM93COMP ==
ChartData->GetDBChartType(i)) {
2166 qcnew->SetScale(
ChartData->GetDBChartScale(i));
2168 m_pcandidate_array->Add(qcnew);
2179 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
2181 if (pqc->b_include) {
2187 if (!b_vis && m_pcandidate_array->GetCount()) {
2190 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2195 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2198 if (cte.GetChartType() == CHART_TYPE_MBTILES)
continue;
2201 LLRegion vpck_region(vp_local.GetBBox());
2204 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2206 if (!chart_region.Empty()) vpck_region.Intersect(chart_region);
2208 if (!vpck_region.Empty()) {
2210 if (cte.Scale_eq(add_scale)) {
2211 pqc->b_include =
true;
2214 pqc->b_include =
true;
2215 add_scale = cte.GetScale();
2224 m_PatchList.DeleteContents(
true);
2225 m_PatchList.Clear();
2227 if (m_pcandidate_array->GetCount()) {
2228 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2236 if (m.GetChartType() == CHART_TYPE_CM93COMP)
2237 pqc->b_include =
true;
2240 if (pqc->b_include) {
2242 pqp->dbIndex = pqc->dbIndex;
2243 pqp->ProjType = m.GetChartProjectionType();
2246 pqp->quilt_region = pqc->GetCandidateRegion();
2249 pqp->b_Valid =
true;
2251 m_PatchList.Append(pqp);
2258 if (!m_bquiltanyproj) {
2260 m_quilt_proj = PROJECTION_MERCATOR;
2261 ChartBase *ppc = GetLargestScaleChart();
2262 if (ppc) m_quilt_proj = ppc->GetChartProjectionType();
2266 if (!m_bquiltanyproj) {
2269 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2270 wxPatchListNode *pcinode = m_PatchList.Item(i);
2272 if ((piqp->ProjType != m_quilt_proj) &&
2273 (piqp->ProjType != PROJECTION_UNKNOWN))
2274 piqp->b_Valid =
false;
2279 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2280 wxPatchListNode *pcinode = m_PatchList.Item(i);
2282 for (
unsigned int ins = 0;
2283 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2284 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2287 piqp->b_Valid =
false;
2295 m_covered_region.Clear();
2300 bool b_skipCM93 =
false;
2301 if (m_reference_type == CHART_TYPE_CM93COMP) {
2303 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2304 wxPatchListNode *pcinode = m_PatchList.Item(i);
2311 if (m.GetChartType() == CHART_TYPE_CM93COMP) {
2313 piqp->ActiveRegion = piqp->quilt_region;
2314 piqp->ActiveRegion.Intersect(cvp_region);
2318 m_covered_region.Union(piqp->quilt_region);
2328 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2329 wxPatchListNode *pcinode = m_PatchList.Item(i);
2337 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2341 piqp->ActiveRegion = piqp->quilt_region;
2344 if (!b_has_overlays && m_PatchList.GetCount() < 25)
2345 piqp->ActiveRegion.Subtract(m_covered_region);
2347 piqp->ActiveRegion.Intersect(cvp_region);
2351 if (piqp->ActiveRegion.Empty() && (piqp->dbIndex != m_refchart_dbIndex))
2352 piqp->b_eclipsed =
true;
2355 piqp->b_overlay =
false;
2356 if (cte.GetChartFamily() == CHART_FAMILY_VECTOR) {
2357 piqp->b_overlay = s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2360 if (!piqp->b_overlay) m_covered_region.Union(piqp->quilt_region);
2365 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2366 wxPatchListNode *pcinode = m_PatchList.Item(i);
2375 LLRegion vpr_region = piqp->quilt_region;
2383 for (
unsigned int k = i + 1; k < m_PatchList.GetCount(); k++) {
2384 wxPatchListNode *pnode = m_PatchList.Item(k);
2405 if (!b_has_overlays) {
2406 if (!vpr_region.Empty()) {
2408 ChartData->GetChartTableEntry(pqp->dbIndex);
2409 LLRegion larger_scale_chart_region =
2412 vpr_region.Subtract(larger_scale_chart_region);
2421 wxPatchListNode *pinode = m_PatchList.Item(i);
2423 pqpi->ActiveRegion = vpr_region;
2432 if (pqpi->ActiveRegion.Empty()) pqpi->b_eclipsed =
true;
2440 m_covered_region.Union(pqpi->ActiveRegion);
2447 unsigned int il = 0;
2448 while (il < m_PatchList.GetCount()) {
2449 wxPatchListNode *pcinode = m_PatchList.Item(il);
2451 if (piqp->b_eclipsed) {
2454 bool b_noadd =
false;
2455 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size(); ir++) {
2456 if (piqp->dbIndex == m_eclipsed_stack_array[ir]) {
2461 if (!b_noadd) m_eclipsed_stack_array.push_back(piqp->dbIndex);
2463 m_PatchList.DeleteNode(pcinode);
2482 m_parent->EnablePaint(
false);
2489 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2491 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2492 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2493 ChartData->LockCacheChart(pqc->dbIndex);
2498 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2500 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2501 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2502 ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
true);
2511 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2513 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2514 if (
ChartData->IsChartLocked(pqc->dbIndex))
2515 pqc->b_locked =
true;
2517 pqc->b_locked =
ChartData->LockCacheChart(pqc->dbIndex);
2522 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2524 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2530 if (
ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
2532 pqc->b_locked =
true;
2537 m_parent->EnablePaint(
true);
2540 m_last_index_array = m_index_array;
2542 m_index_array.clear();
2545 unsigned int kl = m_PatchList.GetCount();
2546 for (
unsigned int k = 0; k < kl; k++) {
2547 wxPatchListNode *cnode = m_PatchList.Item((kl - k) - 1);
2548 m_index_array.push_back(cnode->GetData()->dbIndex);
2549 cnode = cnode->GetNext();
2555 m_quilt_depth_unit =
"";
2558 m_quilt_depth_unit = pc->GetDepthUnits();
2560 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2561 int units = ps52plib->m_nDepthUnitDisplay;
2564 m_quilt_depth_unit =
"Feet";
2567 m_quilt_depth_unit =
"Meters";
2570 m_quilt_depth_unit =
"Fathoms";
2576 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2577 wxPatchListNode *pnode = m_PatchList.Item(k);
2585 wxString du = pc->GetDepthUnits();
2586 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2587 int units = ps52plib->m_nDepthUnitDisplay;
2600 wxString dul = du.Lower();
2601 wxString ml = m_quilt_depth_unit.Lower();
2605 if (dul.StartsWith(
"meters") && ml.StartsWith(
"meters"))
2607 else if (dul.StartsWith(
"metres") && ml.StartsWith(
"metres"))
2609 else if (dul.StartsWith(
"fathoms") && ml.StartsWith(
"fathoms"))
2611 else if (dul.StartsWith(
"met") && ml.StartsWith(
"met"))
2615 m_quilt_depth_unit =
"";
2625 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2626 wxPatchListNode *pnode = m_PatchList.Item(k);
2630 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2631 wxLogMessage(
" Quilt Compose cache miss...");
2632 ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
2633 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2634 wxLogMessage(
" Oops, removing from quilt...");
2635 pqp->b_Valid =
false;
2642 if (!
ChartData->IsChartInCache(m_refchart_dbIndex))
2643 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
2649 m_bquilt_has_overlays =
false;
2650 m_max_error_factor = 0.;
2651 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2652 wxPatchListNode *pnode = m_PatchList.Item(k);
2660 m_max_error_factor =
2661 wxMax(m_max_error_factor, pc->GetChart_Error_Factor());
2662 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2663 bool isOverlay = IsChartS57Overlay(pqp->dbIndex);
2664 pqp->b_overlay = isOverlay;
2665 if (isOverlay) m_bquilt_has_overlays =
true;
2678 unsigned long xa_hash = 5381;
2679 for (
unsigned int im = 0; im < m_extended_stack_array.size(); im++) {
2680 int dbindex = m_extended_stack_array[im];
2681 xa_hash = ((xa_hash << 5) + xa_hash) + dbindex;
2684 m_xa_hash = xa_hash;
2692 if (!m_bcomposed)
return;
2696 if (GetnCharts() && !m_bbusy && !chart_region.Empty()) {
2702 if (!(chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2703 vp.b_MercatorProjectionOverride)) {
2707 chart_region, pqp->ActiveRegion, chart->GetNativeScale());
2708 if (!get_screen_region.Empty())
2709 rendered_region.Union(get_screen_region);
2712 chart = GetNextChart();
2716 m_rendered_region = rendered_region;
2721bool Quilt::RenderQuiltRegionViewOnDCNoText(wxMemoryDC &dc,
ViewPort &vp,
2723 return DoRenderQuiltRegionViewOnDC(dc, vp, chart_region);
2726bool Quilt::RenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
2728 return DoRenderQuiltRegionViewOnDCTextOnly(dc, vp, chart_region);
2731bool Quilt::DoRenderQuiltRegionViewOnDC(wxMemoryDC &dc,
ViewPort &vp,
2733#ifdef ocpnUSE_DIBSECTION
2739 if (!m_bcomposed)
return false;
2743 if (GetnCharts() && !m_bbusy) {
2751 int chartsDrawn = 0;
2753 if (!chart_region.Empty()) {
2755 bool okToRender =
true;
2757 if (chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2758 vp.b_MercatorProjectionOverride)
2762 chart = GetNextChart();
2767 bool b_chart_rendered =
false;
2768 LLRegion get_region = pqp->ActiveRegion;
2771 chart_region, get_region, chart->GetNativeScale());
2772 if (!get_screen_region.Empty()) {
2773 if (!pqp->b_overlay) {
2774 if (chart->GetChartType() == CHART_TYPE_CM93COMP) {
2776 chart->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2780 if (Chs57->m_RAZBuilt) {
2781 b_chart_rendered = Chs57->RenderRegionViewOnDCNoText(
2782 tmp_dc, vp, get_screen_region);
2788 b_chart_rendered = ChPI->RenderRegionViewOnDCNoText(
2789 tmp_dc, vp, get_screen_region);
2791 b_chart_rendered = chart->RenderRegionViewOnDC(
2792 tmp_dc, vp, get_screen_region);
2794 b_chart_rendered =
true;
2801 screen_region.Subtract(get_screen_region);
2806 while (upd.HaveRects()) {
2807 wxRect rect = upd.GetRect();
2808 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc, rect.x,
2809 rect.y, wxCOPY,
true);
2813 tmp_dc.SelectObject(wxNullBitmap);
2815 if (b_chart_rendered) rendered_region.Union(get_screen_region);
2819 chart = GetNextChart();
2823 if (!chartsDrawn) m_parent->GetVP().SetProjectionType(PROJECTION_MERCATOR);
2826 if (m_bquilt_has_overlays && !chart_region.Empty()) {
2827 chart = GetFirstChart();
2831 if (pqp->b_overlay) {
2832 LLRegion get_region = pqp->ActiveRegion;
2834 chart_region, get_region, chart->GetNativeScale());
2835 if (!get_region.Empty()) {
2838 Chs57->RenderOverlayRegionViewOnDC(tmp_dc, vp,
2844 ChPI->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2849 while (upd.HaveRects()) {
2850 wxRect rect = upd.GetRect();
2851 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc,
2852 rect.x, rect.y, wxCOPY,
true);
2855 tmp_dc.SelectObject(wxNullBitmap);
2860 chart = GetNextChart();
2867 while (clrit.HaveRects()) {
2868 wxRect rect = clrit.GetRect();
2870 dc.SetPen(*wxBLACK_PEN);
2871 dc.SetBrush(*wxBLACK_BRUSH);
2872 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
2874 dc.Blit(rect.x, rect.y, rect.width, rect.height, &dc, rect.x, rect.y,
2881 if (m_nHiLiteIndex >= 0) {
2884 wxRect box = hiregion.GetBox();
2886 if (!box.IsEmpty()) {
2889 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2890 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2897 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2901 q_dc.SelectObject(*m_pBM);
2902 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2903 q_dc.SelectObject(wxNullBitmap);
2908 wxBitmap hl_mask_bm(vp.rv_rect.width, vp.rv_rect.height, 1);
2910 mdc.SelectObject(hl_mask_bm);
2911 mdc.SetBackground(*wxBLACK_BRUSH);
2913 mdc.SetClippingRegion(box);
2914 mdc.SetBackground(*wxWHITE_BRUSH);
2916 mdc.SelectObject(wxNullBitmap);
2918 if (hl_mask_bm.IsOk()) {
2919 wxMask *phl_mask =
new wxMask(hl_mask_bm);
2920 m_pBM->SetMask(phl_mask);
2921 q_dc.SelectObject(*m_pBM);
2924 wxBitmap rbm(vp.rv_rect.width, vp.rv_rect.height);
2925 wxMask *pr_mask =
new wxMask(hl_mask_bm);
2927 rbm.SetMask(pr_mask);
2928 rdc.SelectObject(rbm);
2929 unsigned char hlcolor = 255;
2930 switch (global_color_scheme) {
2931 case GLOBAL_COLOR_SCHEME_DAY:
2934 case GLOBAL_COLOR_SCHEME_DUSK:
2937 case GLOBAL_COLOR_SCHEME_NIGHT:
2945 rdc.SetBackground(wxBrush(wxColour(hlcolor, 0, 0)));
2949 while (upd.HaveRects()) {
2950 wxRect rect = upd.GetRect();
2951 rdc.Blit(rect.x, rect.y, rect.width, rect.height, &q_dc, rect.x,
2952 rect.y, wxOR,
true);
2957 while (updq.HaveRects()) {
2958 wxRect rect = updq.GetRect();
2959 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &rdc, rect.x,
2960 rect.y, wxCOPY,
true);
2964 q_dc.SelectObject(wxNullBitmap);
2965 m_pBM->SetMask(NULL);
2968 dc.SelectObject(*m_pBM);
2971 rdc.SelectObject(wxNullBitmap);
2977 if (g_fog_overzoom) {
2980 if (scale_factor > g_overzoom_emphasis_base) {
2981 float fog = ((scale_factor - g_overzoom_emphasis_base) * 255.) / 20.;
2982 fog = wxMin(fog, 200.);
2986 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2987 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2994 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2998 q_dc.SelectObject(*m_pBM);
2999 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
3000 q_dc.SelectObject(wxNullBitmap);
3002 wxImage src = m_pBM->ConvertToImage();
3005 wxMin((scale_factor - g_overzoom_emphasis_base) / 4, 4);
3007 wxImage dest = src.Blur(blur_factor);
3011 unsigned char *bg = src.GetData();
3012 wxColour color = m_parent->GetFogColor();
3014 float transparency = fog;
3017 wxImage dest(vp.rv_rect.width, vp.rv_rect.height);
3018 unsigned char *dest_data = (
unsigned char *) malloc( vp.rv_rect.width * vp.rv_rect.height * 3 *
sizeof(
unsigned char) );
3019 unsigned char *d = dest_data;
3021 float alpha = 1.0 - (float)transparency / 255.0;
3022 int sb = vp.rv_rect.width * vp.rv_rect.height;
3023 for(
int i = 0; i < sb; i++ ) {
3026 int r = ( ( *bg++ ) * a ) + (1.0-a) * color.Red();
3028 int g = ( ( *bg++ ) * a ) + (1.0-a) * color.Green();
3030 int b = ( ( *bg++ ) * a ) + (1.0-a) * color.Blue();
3034 dest.SetData( dest_data );
3039 ddc.SelectObject(dim);
3041 q_dc.SelectObject(*m_pBM);
3043 while (upd.HaveRects()) {
3044 wxRect rect = upd.GetRect();
3045 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &ddc, rect.x,
3050 ddc.SelectObject(wxNullBitmap);
3051 q_dc.SelectObject(wxNullBitmap);
3054 dc.SelectObject(*m_pBM);
3062 SubstituteClearDC(dc, vp);
3066 SubstituteClearDC(dc, vp);
3070 m_rendered_region = rendered_region;
3076void Quilt::SubstituteClearDC(wxMemoryDC &dc,
ViewPort &vp) {
3078 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
3079 (m_pBM->GetHeight() != vp.rv_rect.height)) {
3085 if (NULL == m_pBM) {
3086 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
3089 dc.SelectObject(wxNullBitmap);
3090 dc.SelectObject(*m_pBM);
3091 dc.SetBackground(*wxBLACK_BRUSH);
3093 m_covered_region.Clear();
3096bool Quilt::DoRenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
3098 if (!m_bcomposed)
return false;
3102 if (GetnCharts() && !m_bbusy) {
3107 ChartBase *chart = GetLargestScaleChart();
3114 Chs57->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3118 ChPI->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3123 chart = GetNextSmallerScaleChart();
3127 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.
double GetCanvasScaleFactor()
Return the number of logical pixels per meter for the screen.
Wrapper class for plugin-based charts.
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).
Represents an S57 format electronic navigational chart in OpenCPN.
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.