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;
1360 if ((cte.GetChartType() == CHART_TYPE_PLUGIN) ||
1361 (reference_type == CHART_TYPE_PLUGIN)) {
1362 if (reference_family != cte.GetChartFamily()) {
1366 if (reference_type != cte.GetChartType()) {
1372 wxFileName fn(cte.GetFullPath());
1373 if (!fn.GetPath().Lower().Contains(
"basemap"))
continue;
1377 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1380 int candidate_chart_scale = cte.GetScale();
1381 double chart_native_ppm =
1382 m_canvas_scale_factor / (double)candidate_chart_scale;
1384 if ((zoom_factor < zoom_test_val) &&
1389 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
1390 m_extended_stack_array.pop_back();
1394 double skew_norm = cte.GetChartSkew();
1395 if (skew_norm > 180.) skew_norm -= 360.;
1397 if ((m_bquiltskew ? 1 : fabs(skew_norm) < 1.0) &&
1398 (m_bquiltanyproj || cte.GetChartProjectionType() == quilt_proj)) {
1400 qcnew->dbIndex = istack;
1401 qcnew->SetScale(cte.GetScale());
1402 m_pcandidate_array->push_back(qcnew);
1429 int n_all_charts =
ChartData->GetChartTableEntries();
1431 LLBBox viewbox = vp_local.GetBBox();
1432 int sure_index = -1;
1433 int sure_index_scale = 0;
1434 int sure_index_type = -1;
1436 for (
int i = 0; i < n_all_charts; i++) {
1440 int groupIndex = m_parent->m_groupIndex;
1441 if ((groupIndex > 0) && (!
ChartData->IsChartInGroup(i, groupIndex)))
1447 if (
ChartData->IsChartDirectoryExcluded(cte.GetFullPath()))
continue;
1449 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
1450 m_fullscreen_index_array.push_back(i);
1455 wxFileName fn(cte.GetFullSystemPath());
1456 if (!androidIsDirWritable(fn.GetPath()))
continue;
1458 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1460 const LLBBox &chart_box = cte.GetBBox();
1461 if ((viewbox.IntersectOut(chart_box)))
continue;
1463 if (cte.GetChartType() == CHART_TYPE_PLUGIN) {
1464 if (!
ChartData->IsChartAvailable(i))
continue;
1467 m_fullscreen_index_array.push_back(i);
1474 bool guest_family_include =
false;
1475 if (reference_family != cte.GetChartFamily()) {
1476 wxFileName fn(cte.GetFullPath());
1477 if (fn.GetPath().Lower().Contains(
"basemap")) {
1478 guest_family_include =
true;
1481 if (m_lost_refchart_dbIndex == i) guest_family_include =
true;
1483 if ((cte.GetChartType() != CHART_TYPE_MBTILES) && !guest_family_include)
1487 if (!m_bquiltanyproj && quilt_proj != cte.GetChartProjectionType())
1490 double skew_norm = cte.GetChartSkew();
1491 if (skew_norm > 180.) skew_norm -= 360.;
1493 if (!m_bquiltskew && fabs(skew_norm) > 1.0)
continue;
1498 if( CHART_TYPE_S57 == cte.GetChartType() ) {
1500 double chart_area = (cte.GetLonMax() - cte.GetLonMin()) *
1501 (cte.GetLatMax() - cte.GetLatMin());
1502 double quilt_area = viewbox.GetLonRange() * viewbox.GetLatRange();
1503 if ((chart_area / quilt_area) < .01)
continue;
1506 int candidate_chart_scale = cte.GetScale();
1512 if (!cte.Scale_ge(reference_scale)) {
1513 if (cte.Scale_gt(sure_index_scale)) {
1515 sure_index_scale = candidate_chart_scale;
1516 sure_index_type = cte.GetChartType();
1525 double chart_native_ppm =
1526 m_canvas_scale_factor / (double)candidate_chart_scale;
1528 double zoom_factor_test_extra = 0.2;
1534 double ref_scale_test = reference_scale;
1535 if (cte.GetChartType() == CHART_TYPE_MBTILES)
1536 ref_scale_test = candidate_chart_scale;
1538 if ((cte.Scale_ge(ref_scale_test) && (zoom_factor > zoom_test_val)) ||
1539 (zoom_factor > zoom_factor_test_extra)) {
1540 LLRegion cell_region = GetChartQuiltRegion(cte, vp_local);
1545 if (!cell_region.Empty()) {
1548 bool b_exists =
false;
1549 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1550 if (i == m_extended_stack_array[ir]) {
1564 bool b_noadd =
false;
1565 auto &cte_n =
ChartData->GetChartTableEntry(i);
1566 for (
unsigned int id = 0;
id < m_extended_stack_array.size();
id++) {
1567 if (m_extended_stack_array[
id] != -1) {
1569 ChartData->GetChartTableEntry(m_extended_stack_array[
id]);
1570 bool bsameTime =
false;
1571 if (cte_m.GetFileTime() && cte_n.GetFileTime()) {
1572 if (labs(cte_m.GetFileTime() - cte_n.GetFileTime()) < 60)
1575 if (cte_m.GetChartEditionDate() == cte_n.GetChartEditionDate())
1579 if (cte_n.GetpFileName()->IsSameAs(*(cte_m.GetpFileName())))
1586 m_extended_stack_array.push_back(i);
1591 candidate_chart_scale);
1593 m_pcandidate_array->push_back(qcnew);
1595 b_need_resort =
true;
1604 if (-1 != sure_index) {
1606 bool sure_exists =
false;
1607 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1608 if (sure_index == m_extended_stack_array[ir]) {
1615 if (!sure_exists && (sure_index_type != CHART_TYPE_MBTILES)) {
1616 m_extended_stack_array.push_back(sure_index);
1619 qcnew->dbIndex = sure_index;
1620 qcnew->SetScale(
ChartData->GetDBChartScale(sure_index));
1621 m_pcandidate_array->push_back(qcnew);
1623 b_need_resort =
true;
1628 if (b_need_resort && m_extended_stack_array.size() > 1) {
1629 std::sort(m_extended_stack_array.begin(), m_extended_stack_array.end(),
1633 std::sort(m_fullscreen_index_array.begin(), m_fullscreen_index_array.end(),
1634 CompareScalesStdFULLSCREEN);
1639int Quilt::AdjustRefSelection(
const ViewPort &vp_in) {
1654 vp_local.SetRotationAngle(0.);
1656 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1658 ChartFamilyEnum family = CHART_FAMILY_RASTER;
1659 ChartTypeEnum type = CHART_TYPE_KAP;
1662 if (m_refchart_dbIndex >= 0) {
1664 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1665 type = (ChartTypeEnum)cte_ref.GetChartType();
1666 family = (ChartFamilyEnum)cte_ref.GetChartFamily();
1669 int ret_index = AdjustRefOnZoom(
true, family, type, vp_in.
chart_scale);
1674double Quilt::GetBestStartScale(
int dbi_ref_hint,
const ViewPort &vp_in) {
1684 int tentative_ref_index = dbi_ref_hint;
1685 if (dbi_ref_hint < 0) {
1692 tentative_ref_index = m_parent->GetpCurrentStack()->GetDBIndex(0);
1699 vp_local.SetRotationAngle(0.);
1701 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1705 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1707 if (qc->dbIndex == tentative_ref_index) {
1713 if (!bf && m_pcandidate_array->GetCount()) {
1714 tentative_ref_index = GetNewRefChart();
1715 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1718 double proposed_scale_onscreen = vp_in.
chart_scale;
1720 if (m_pcandidate_array->GetCount()) {
1721 SetReferenceChart(tentative_ref_index);
1725 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1727 if (IsChartQuiltableRef(qc->dbIndex)) {
1728 SetReferenceChart(qc->dbIndex);
1735 SetReferenceChart(m_parent->GetpCurrentStack()->GetDBIndex(0));
1738 if (m_refchart_dbIndex >= 0) {
1743 double min_ref_scale =
1745 double max_ref_scale = pc->GetNormalScaleMax(
1747 if ((proposed_scale_onscreen >= min_ref_scale) &&
1748 (proposed_scale_onscreen <= max_ref_scale))
1751 proposed_scale_onscreen = wxMin(proposed_scale_onscreen, max_ref_scale);
1752 proposed_scale_onscreen = wxMax(proposed_scale_onscreen, min_ref_scale);
1760 if (m_refchart_dbIndex >= 0 &&
ChartData)
1761 return ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
1765void Quilt::UnlockQuilt() {
1766 wxASSERT(m_bbusy ==
false);
1769 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1771 ChartData->UnLockCacheChart(pqc->dbIndex);
1781 if (!m_parent->GetpCurrentStack())
return false;
1783 if (m_bbusy)
return false;
1792 if (m_refchart_dbIndex >= 0) {
1794 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1795 m_reference_scale = cte_ref.GetScale();
1796 m_reference_type = cte_ref.GetChartType();
1797 if (!m_bquiltanyproj)
1798 m_quilt_proj =
ChartData->GetDBChartProj(m_refchart_dbIndex);
1799 m_reference_family = cte_ref.GetChartFamily();
1803 if (!m_bquiltanyproj) vp_local.SetProjectionType(m_quilt_proj);
1810 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1850 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1852 if (qc->dbIndex == m_refchart_dbIndex) {
1861 if (m_chart_familyFix == CHART_FAMILY_UNKNOWN) {
1862 if (!bf && m_pcandidate_array->GetCount() &&
1863 (m_reference_type != CHART_TYPE_CM93COMP)) {
1864 m_lost_refchart_dbIndex = m_refchart_dbIndex;
1865 int candidate_ref_index = GetNewRefChart();
1866 if (m_refchart_dbIndex != candidate_ref_index) {
1867 m_refchart_dbIndex = candidate_ref_index;
1868 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1875 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1876 if (m_pcandidate_array->GetCount()) {
1877 int alternate_index =
1878 m_pcandidate_array->Item(m_pcandidate_array->GetCount() - 1)
1881 ChartData->GetChartTableEntry(alternate_index);
1883 if (GetRefFamily() == cte_alt.GetChartFamily()) {
1884 m_refchart_dbIndex = alternate_index;
1885 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex,
1893 if ((-1 != m_lost_refchart_dbIndex) &&
1894 (m_lost_refchart_dbIndex != m_refchart_dbIndex)) {
1897 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1898 if (m_lost_refchart_dbIndex == m_extended_stack_array[ir]) {
1899 m_refchart_dbIndex = m_lost_refchart_dbIndex;
1900 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1901 m_lost_refchart_dbIndex = -1;
1907 bool b_has_overlays =
false;
1910 if (CHART_FAMILY_VECTOR == m_reference_family) {
1911 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1915 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1916 b_has_overlays =
true;
1928 const LLRegion cvp_region = vp_local.GetLLRegion(vp_local.rv_rect);
1929 LLRegion vp_region = cvp_region;
1935 for (ir = 0; ir < m_pcandidate_array->GetCount();
1939 if (pqc->dbIndex == m_refchart_dbIndex) {
1948 const double z = 111274.96299695622;
1954 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1956 LLRegion vpu_region(cvp_region);
1959 LLRegion &chart_region = pqc_ref->GetReducedCandidateRegion(factor);
1961 if (cte_ref.GetChartType() != CHART_TYPE_MBTILES) {
1962 if (!chart_region.Empty()) {
1963 vpu_region.Intersect(chart_region);
1965 if (vpu_region.Empty())
1966 pqc_ref->b_include =
false;
1968 pqc_ref->b_include =
true;
1969 vp_region.Subtract(chart_region);
1972 pqc_ref->b_include =
false;
1974 pqc_ref->b_include =
false;
1979 if (!vp_region.Empty()) {
1980 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1983 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
1990 if (CHART_FAMILY_VECTOR == m_reference_family) {
1991 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1997 if (CHART_TYPE_MBTILES == cte.GetChartType()) {
1998 pqc->b_include =
false;
2002 if (cte.Scale_ge(m_reference_scale)) {
2006 bool b_in_noshow =
false;
2007 for (
unsigned int ins = 0;
2008 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2009 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2019 LLRegion vpu_region(cvp_region);
2022 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2024 if (!chart_region.Empty()) {
2025 vpu_region.Intersect(chart_region);
2027 if (vpu_region.Empty())
2028 pqc->b_include =
false;
2030 pqc->b_include =
true;
2031 vp_region.Subtract(chart_region);
2034 pqc->b_include =
false;
2036 pqc->b_include =
true;
2040 pqc->b_include =
false;
2043 if (vp_region.Empty())
2050 if (b_has_overlays && (CHART_FAMILY_VECTOR == m_reference_family)) {
2051 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2054 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
2058 if (cte.Scale_ge(m_reference_scale)) {
2059 bool b_in_noshow =
false;
2060 for (
unsigned int ins = 0;
2061 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2062 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2072 LLRegion vpu_region(cvp_region);
2075 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2077 if (!chart_region.Empty()) vpu_region.Intersect(chart_region);
2079 if (vpu_region.Empty())
2080 pqc->b_include =
false;
2083 s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2084 if (b_overlay) pqc->b_include =
true;
2091 ChartData->GetChartTableEntry(m_refchart_dbIndex);
2092 if (s57chart::IsCellOverlayType(cte_ref.GetFullSystemPath())) {
2093 pqc->b_include =
true;
2105 m_eclipsed_stack_array.clear();
2107 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2110 if (!pqc->b_include) {
2112 if (cte.Scale_ge(m_reference_scale) &&
2113 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
2114 m_eclipsed_stack_array.push_back(pqc->dbIndex);
2115 pqc->b_eclipsed =
true;
2122 if (((m_bquiltanyproj || m_quilt_proj == PROJECTION_MERCATOR)) &&
2123 !vp_region.Empty()) {
2124 bool b_must_add_cm93 =
true;
2131 while( updd .HaveRects()) {
2132 wxRect rect = updd.GetRect();
2133 if( ( rect.width > 2 ) && ( rect.height > 2 ) ) {
2134 b_must_add_cm93 =
true;
2141 if (b_must_add_cm93) {
2142 for (
int ics = 0; ics < m_parent->GetpCurrentStack()->nEntry; ics++) {
2143 int i = m_parent->GetpCurrentStack()->GetDBIndex(ics);
2144 if (CHART_TYPE_CM93COMP ==
ChartData->GetDBChartType(i)) {
2147 qcnew->SetScale(
ChartData->GetDBChartScale(i));
2149 m_pcandidate_array->Add(qcnew);
2160 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
2162 if (pqc->b_include) {
2168 if (!b_vis && m_pcandidate_array->GetCount()) {
2171 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2176 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2179 if (cte.GetChartType() == CHART_TYPE_MBTILES)
continue;
2182 LLRegion vpck_region(vp_local.GetBBox());
2185 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2187 if (!chart_region.Empty()) vpck_region.Intersect(chart_region);
2189 if (!vpck_region.Empty()) {
2191 if (cte.Scale_eq(add_scale)) {
2192 pqc->b_include =
true;
2195 pqc->b_include =
true;
2196 add_scale = cte.GetScale();
2205 m_PatchList.DeleteContents(
true);
2206 m_PatchList.Clear();
2208 if (m_pcandidate_array->GetCount()) {
2209 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2217 if (m.GetChartType() == CHART_TYPE_CM93COMP)
2218 pqc->b_include =
true;
2221 if (pqc->b_include) {
2223 pqp->dbIndex = pqc->dbIndex;
2224 pqp->ProjType = m.GetChartProjectionType();
2227 pqp->quilt_region = pqc->GetCandidateRegion();
2230 pqp->b_Valid =
true;
2232 m_PatchList.Append(pqp);
2239 if (!m_bquiltanyproj) {
2241 m_quilt_proj = PROJECTION_MERCATOR;
2242 ChartBase *ppc = GetLargestScaleChart();
2243 if (ppc) m_quilt_proj = ppc->GetChartProjectionType();
2247 if (!m_bquiltanyproj) {
2250 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2251 wxPatchListNode *pcinode = m_PatchList.Item(i);
2253 if ((piqp->ProjType != m_quilt_proj) &&
2254 (piqp->ProjType != PROJECTION_UNKNOWN))
2255 piqp->b_Valid =
false;
2260 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2261 wxPatchListNode *pcinode = m_PatchList.Item(i);
2263 for (
unsigned int ins = 0;
2264 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2265 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2268 piqp->b_Valid =
false;
2276 m_covered_region.Clear();
2281 bool b_skipCM93 =
false;
2282 if (m_reference_type == CHART_TYPE_CM93COMP) {
2284 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2285 wxPatchListNode *pcinode = m_PatchList.Item(i);
2292 if (m.GetChartType() == CHART_TYPE_CM93COMP) {
2294 piqp->ActiveRegion = piqp->quilt_region;
2295 piqp->ActiveRegion.Intersect(cvp_region);
2299 m_covered_region.Union(piqp->quilt_region);
2309 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2310 wxPatchListNode *pcinode = m_PatchList.Item(i);
2318 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2322 piqp->ActiveRegion = piqp->quilt_region;
2325 if (!b_has_overlays && m_PatchList.GetCount() < 25)
2326 piqp->ActiveRegion.Subtract(m_covered_region);
2328 piqp->ActiveRegion.Intersect(cvp_region);
2332 if (piqp->ActiveRegion.Empty() && (piqp->dbIndex != m_refchart_dbIndex))
2333 piqp->b_eclipsed =
true;
2336 piqp->b_overlay =
false;
2337 if (cte.GetChartFamily() == CHART_FAMILY_VECTOR) {
2338 piqp->b_overlay = s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2341 if (!piqp->b_overlay) m_covered_region.Union(piqp->quilt_region);
2346 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2347 wxPatchListNode *pcinode = m_PatchList.Item(i);
2356 LLRegion vpr_region = piqp->quilt_region;
2364 for (
unsigned int k = i + 1; k < m_PatchList.GetCount(); k++) {
2365 wxPatchListNode *pnode = m_PatchList.Item(k);
2386 if (!b_has_overlays) {
2387 if (!vpr_region.Empty()) {
2389 ChartData->GetChartTableEntry(pqp->dbIndex);
2390 LLRegion larger_scale_chart_region =
2393 vpr_region.Subtract(larger_scale_chart_region);
2402 wxPatchListNode *pinode = m_PatchList.Item(i);
2404 pqpi->ActiveRegion = vpr_region;
2413 if (pqpi->ActiveRegion.Empty()) pqpi->b_eclipsed =
true;
2421 m_covered_region.Union(pqpi->ActiveRegion);
2428 unsigned int il = 0;
2429 while (il < m_PatchList.GetCount()) {
2430 wxPatchListNode *pcinode = m_PatchList.Item(il);
2432 if (piqp->b_eclipsed) {
2435 bool b_noadd =
false;
2436 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size(); ir++) {
2437 if (piqp->dbIndex == m_eclipsed_stack_array[ir]) {
2442 if (!b_noadd) m_eclipsed_stack_array.push_back(piqp->dbIndex);
2444 m_PatchList.DeleteNode(pcinode);
2463 m_parent->EnablePaint(
false);
2470 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2472 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2473 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2474 ChartData->LockCacheChart(pqc->dbIndex);
2479 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2481 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2482 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2483 ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
true);
2492 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2494 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2495 if (
ChartData->IsChartLocked(pqc->dbIndex))
2496 pqc->b_locked =
true;
2498 pqc->b_locked =
ChartData->LockCacheChart(pqc->dbIndex);
2503 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2505 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2511 if (
ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
2513 pqc->b_locked =
true;
2518 m_parent->EnablePaint(
true);
2521 m_last_index_array = m_index_array;
2523 m_index_array.clear();
2526 unsigned int kl = m_PatchList.GetCount();
2527 for (
unsigned int k = 0; k < kl; k++) {
2528 wxPatchListNode *cnode = m_PatchList.Item((kl - k) - 1);
2529 m_index_array.push_back(cnode->GetData()->dbIndex);
2530 cnode = cnode->GetNext();
2536 m_quilt_depth_unit =
"";
2539 m_quilt_depth_unit = pc->GetDepthUnits();
2541 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2542 int units = ps52plib->m_nDepthUnitDisplay;
2545 m_quilt_depth_unit =
"Feet";
2548 m_quilt_depth_unit =
"Meters";
2551 m_quilt_depth_unit =
"Fathoms";
2557 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2558 wxPatchListNode *pnode = m_PatchList.Item(k);
2566 wxString du = pc->GetDepthUnits();
2567 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2568 int units = ps52plib->m_nDepthUnitDisplay;
2581 wxString dul = du.Lower();
2582 wxString ml = m_quilt_depth_unit.Lower();
2586 if (dul.StartsWith(
"meters") && ml.StartsWith(
"meters"))
2588 else if (dul.StartsWith(
"metres") && ml.StartsWith(
"metres"))
2590 else if (dul.StartsWith(
"fathoms") && ml.StartsWith(
"fathoms"))
2592 else if (dul.StartsWith(
"met") && ml.StartsWith(
"met"))
2596 m_quilt_depth_unit =
"";
2606 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2607 wxPatchListNode *pnode = m_PatchList.Item(k);
2611 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2612 wxLogMessage(
" Quilt Compose cache miss...");
2613 ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
2614 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2615 wxLogMessage(
" Oops, removing from quilt...");
2616 pqp->b_Valid =
false;
2623 if (!
ChartData->IsChartInCache(m_refchart_dbIndex))
2624 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
2630 m_bquilt_has_overlays =
false;
2631 m_max_error_factor = 0.;
2632 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2633 wxPatchListNode *pnode = m_PatchList.Item(k);
2641 m_max_error_factor =
2642 wxMax(m_max_error_factor, pc->GetChart_Error_Factor());
2643 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2644 bool isOverlay = IsChartS57Overlay(pqp->dbIndex);
2645 pqp->b_overlay = isOverlay;
2646 if (isOverlay) m_bquilt_has_overlays =
true;
2659 unsigned long xa_hash = 5381;
2660 for (
unsigned int im = 0; im < m_extended_stack_array.size(); im++) {
2661 int dbindex = m_extended_stack_array[im];
2662 xa_hash = ((xa_hash << 5) + xa_hash) + dbindex;
2665 m_xa_hash = xa_hash;
2673 if (!m_bcomposed)
return;
2677 if (GetnCharts() && !m_bbusy && !chart_region.Empty()) {
2683 if (!(chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2684 vp.b_MercatorProjectionOverride)) {
2688 chart_region, pqp->ActiveRegion, chart->GetNativeScale());
2689 if (!get_screen_region.Empty())
2690 rendered_region.Union(get_screen_region);
2693 chart = GetNextChart();
2697 m_rendered_region = rendered_region;
2702bool Quilt::RenderQuiltRegionViewOnDCNoText(wxMemoryDC &dc,
ViewPort &vp,
2704 return DoRenderQuiltRegionViewOnDC(dc, vp, chart_region);
2707bool Quilt::RenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
2709 return DoRenderQuiltRegionViewOnDCTextOnly(dc, vp, chart_region);
2712bool Quilt::DoRenderQuiltRegionViewOnDC(wxMemoryDC &dc,
ViewPort &vp,
2714#ifdef ocpnUSE_DIBSECTION
2720 if (!m_bcomposed)
return false;
2724 if (GetnCharts() && !m_bbusy) {
2732 int chartsDrawn = 0;
2734 if (!chart_region.Empty()) {
2736 bool okToRender =
true;
2738 if (chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2739 vp.b_MercatorProjectionOverride)
2743 chart = GetNextChart();
2748 bool b_chart_rendered =
false;
2749 LLRegion get_region = pqp->ActiveRegion;
2752 chart_region, get_region, chart->GetNativeScale());
2753 if (!get_screen_region.Empty()) {
2754 if (!pqp->b_overlay) {
2755 if (chart->GetChartType() == CHART_TYPE_CM93COMP) {
2757 chart->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2761 if (Chs57->m_RAZBuilt) {
2762 b_chart_rendered = Chs57->RenderRegionViewOnDCNoText(
2763 tmp_dc, vp, get_screen_region);
2769 b_chart_rendered = ChPI->RenderRegionViewOnDCNoText(
2770 tmp_dc, vp, get_screen_region);
2772 b_chart_rendered = chart->RenderRegionViewOnDC(
2773 tmp_dc, vp, get_screen_region);
2775 b_chart_rendered =
true;
2782 screen_region.Subtract(get_screen_region);
2787 while (upd.HaveRects()) {
2788 wxRect rect = upd.GetRect();
2789 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc, rect.x,
2790 rect.y, wxCOPY,
true);
2794 tmp_dc.SelectObject(wxNullBitmap);
2796 if (b_chart_rendered) rendered_region.Union(get_screen_region);
2800 chart = GetNextChart();
2804 if (!chartsDrawn) m_parent->GetVP().SetProjectionType(PROJECTION_MERCATOR);
2807 if (m_bquilt_has_overlays && !chart_region.Empty()) {
2808 chart = GetFirstChart();
2812 if (pqp->b_overlay) {
2813 LLRegion get_region = pqp->ActiveRegion;
2815 chart_region, get_region, chart->GetNativeScale());
2816 if (!get_region.Empty()) {
2819 Chs57->RenderOverlayRegionViewOnDC(tmp_dc, vp,
2825 ChPI->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2830 while (upd.HaveRects()) {
2831 wxRect rect = upd.GetRect();
2832 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc,
2833 rect.x, rect.y, wxCOPY,
true);
2836 tmp_dc.SelectObject(wxNullBitmap);
2841 chart = GetNextChart();
2848 while (clrit.HaveRects()) {
2849 wxRect rect = clrit.GetRect();
2851 dc.SetPen(*wxBLACK_PEN);
2852 dc.SetBrush(*wxBLACK_BRUSH);
2853 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
2855 dc.Blit(rect.x, rect.y, rect.width, rect.height, &dc, rect.x, rect.y,
2862 if (m_nHiLiteIndex >= 0) {
2865 wxRect box = hiregion.GetBox();
2867 if (!box.IsEmpty()) {
2870 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2871 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2878 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2882 q_dc.SelectObject(*m_pBM);
2883 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2884 q_dc.SelectObject(wxNullBitmap);
2889 wxBitmap hl_mask_bm(vp.rv_rect.width, vp.rv_rect.height, 1);
2891 mdc.SelectObject(hl_mask_bm);
2892 mdc.SetBackground(*wxBLACK_BRUSH);
2894 mdc.SetClippingRegion(box);
2895 mdc.SetBackground(*wxWHITE_BRUSH);
2897 mdc.SelectObject(wxNullBitmap);
2899 if (hl_mask_bm.IsOk()) {
2900 wxMask *phl_mask =
new wxMask(hl_mask_bm);
2901 m_pBM->SetMask(phl_mask);
2902 q_dc.SelectObject(*m_pBM);
2905 wxBitmap rbm(vp.rv_rect.width, vp.rv_rect.height);
2906 wxMask *pr_mask =
new wxMask(hl_mask_bm);
2908 rbm.SetMask(pr_mask);
2909 rdc.SelectObject(rbm);
2910 unsigned char hlcolor = 255;
2911 switch (global_color_scheme) {
2912 case GLOBAL_COLOR_SCHEME_DAY:
2915 case GLOBAL_COLOR_SCHEME_DUSK:
2918 case GLOBAL_COLOR_SCHEME_NIGHT:
2926 rdc.SetBackground(wxBrush(wxColour(hlcolor, 0, 0)));
2930 while (upd.HaveRects()) {
2931 wxRect rect = upd.GetRect();
2932 rdc.Blit(rect.x, rect.y, rect.width, rect.height, &q_dc, rect.x,
2933 rect.y, wxOR,
true);
2938 while (updq.HaveRects()) {
2939 wxRect rect = updq.GetRect();
2940 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &rdc, rect.x,
2941 rect.y, wxCOPY,
true);
2945 q_dc.SelectObject(wxNullBitmap);
2946 m_pBM->SetMask(NULL);
2949 dc.SelectObject(*m_pBM);
2952 rdc.SelectObject(wxNullBitmap);
2958 if (g_fog_overzoom) {
2961 if (scale_factor > g_overzoom_emphasis_base) {
2962 float fog = ((scale_factor - g_overzoom_emphasis_base) * 255.) / 20.;
2963 fog = wxMin(fog, 200.);
2967 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2968 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2975 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2979 q_dc.SelectObject(*m_pBM);
2980 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2981 q_dc.SelectObject(wxNullBitmap);
2983 wxImage src = m_pBM->ConvertToImage();
2986 wxMin((scale_factor - g_overzoom_emphasis_base) / 4, 4);
2988 wxImage dest = src.Blur(blur_factor);
2992 unsigned char *bg = src.GetData();
2993 wxColour color = m_parent->GetFogColor();
2995 float transparency = fog;
2998 wxImage dest(vp.rv_rect.width, vp.rv_rect.height);
2999 unsigned char *dest_data = (
unsigned char *) malloc( vp.rv_rect.width * vp.rv_rect.height * 3 *
sizeof(
unsigned char) );
3000 unsigned char *d = dest_data;
3002 float alpha = 1.0 - (float)transparency / 255.0;
3003 int sb = vp.rv_rect.width * vp.rv_rect.height;
3004 for(
int i = 0; i < sb; i++ ) {
3007 int r = ( ( *bg++ ) * a ) + (1.0-a) * color.Red();
3009 int g = ( ( *bg++ ) * a ) + (1.0-a) * color.Green();
3011 int b = ( ( *bg++ ) * a ) + (1.0-a) * color.Blue();
3015 dest.SetData( dest_data );
3020 ddc.SelectObject(dim);
3022 q_dc.SelectObject(*m_pBM);
3024 while (upd.HaveRects()) {
3025 wxRect rect = upd.GetRect();
3026 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &ddc, rect.x,
3031 ddc.SelectObject(wxNullBitmap);
3032 q_dc.SelectObject(wxNullBitmap);
3035 dc.SelectObject(*m_pBM);
3043 SubstituteClearDC(dc, vp);
3047 SubstituteClearDC(dc, vp);
3051 m_rendered_region = rendered_region;
3057void Quilt::SubstituteClearDC(wxMemoryDC &dc,
ViewPort &vp) {
3059 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
3060 (m_pBM->GetHeight() != vp.rv_rect.height)) {
3066 if (NULL == m_pBM) {
3067 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
3070 dc.SelectObject(wxNullBitmap);
3071 dc.SelectObject(*m_pBM);
3072 dc.SetBackground(*wxBLACK_BRUSH);
3074 m_covered_region.Clear();
3077bool Quilt::DoRenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
3079 if (!m_bcomposed)
return false;
3083 if (GetnCharts() && !m_bbusy) {
3088 ChartBase *chart = GetLargestScaleChart();
3095 Chs57->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3099 ChPI->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3104 chart = GetNextSmallerScaleChart();
3108 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.