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);
70static int CompareScales(
int i1,
int i2) {
76 if (cte1.Scale_eq(cte2.GetScale())) {
78 lat1 = cte1.GetLatMax();
79 lat2 = cte2.GetLatMax();
80 if (roundf(lat1 * 100.) == roundf(lat2 * 100.)) {
82 lon1 = cte1.GetLonMin();
83 lon2 = cte2.GetLonMin();
87 return (lon1 < lon2) ? -1 : 1;
89 return (lat1 < lat2) ? 1 : -1;
91 return cte1.GetScale() - cte2.GetScale();
97static int CompareScales(
const int i1,
const int i2) {
104 return cte1.GetScale() - cte2.GetScale();
107static bool CompareScalesStd(
int i1,
int i2) {
108 return CompareScales(i1, i2) < 0;
111static bool CompareScalesStdFULLSCREEN(
int i1,
int i2) {
112 return CompareScales(i1, i2) < 0;
118 return CompareScales(qc1->dbIndex, qc2->dbIndex);
121const LLRegion &QuiltCandidate::GetCandidateRegion() {
123 LLRegion &candidate_region =
124 const_cast<LLRegion &
>(cte.quilt_candidate_region);
126 if (!candidate_region.Empty())
return candidate_region;
128 LLRegion world_region(-90, -180, 90, 180);
132 if (
ChartData->GetDBChartType(dbIndex) == CHART_TYPE_CM93COMP) {
133 double cm93_ll_bounds[8] = {-80, -180, -80, 180, 80, 180, 80, -180};
134 candidate_region = LLRegion(4, cm93_ll_bounds);
135 return candidate_region;
139 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
140 if (nAuxPlyEntries >= 1) {
141 candidate_region.Clear();
142 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
143 float *pfp = cte.GetpAuxPlyTableEntry(ip);
144 int nAuxPly = cte.GetAuxCntTableEntry(ip);
146 candidate_region.Union(LLRegion(nAuxPly, pfp));
159 std::vector<float> vec =
ChartData->GetReducedPlyPoints(dbIndex);
161 std::vector<float> vecr;
162 for (
size_t i = 0; i < vec.size() / 2; i++) {
163 float a = vec[i * 2 + 1];
169 std::vector<float>::iterator it = vecr.begin();
171 if (vecr.size() / 2 >= 3) {
174 candidate_region = LLRegion(vecr.size() / 2, (
float *)&(*it));
176 candidate_region = world_region;
180 if (!candidate_region
182 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
183 if (nNoCovrPlyEntries) {
184 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
185 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
186 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
188 LLRegion t_region = LLRegion(nNoCovrPly, pfp);
197 if (nAuxPlyEntries > 1) {
198 for (
int ipr = 0; ipr < nAuxPlyEntries; ipr++) {
199 float *pfpr = cte.GetpAuxPlyTableEntry(ipr);
200 int nAuxPly = cte.GetAuxCntTableEntry(ipr);
201 t_region.Subtract(LLRegion(nAuxPly, pfpr));
210 if (!t_region.Empty()) {
211 LLRegion test_region = candidate_region;
212 test_region.Subtract(t_region);
213 if (!test_region.Empty()) candidate_region = test_region;
223 if ((cte.GetScale() > 90000000) &&
224 (cte.GetChartFamily() == CHART_FAMILY_RASTER))
225 candidate_region = world_region;
227 return candidate_region;
230LLRegion &QuiltCandidate::GetReducedCandidateRegion(
double factor) {
231 if (factor != last_factor) {
232 reduced_candidate_region = GetCandidateRegion();
233 reduced_candidate_region.Reduce(factor);
234 last_factor = factor;
237 return reduced_candidate_region;
240void QuiltCandidate::SetScale(
int scale) {
244 if (
scale >= 1000) rounding = 5 * pow(10, log10(
scale) - 2);
253 m_reference_scale = 1;
254 m_refchart_dbIndex = -1;
255 m_reference_type = CHART_TYPE_UNKNOWN;
256 m_reference_family = CHART_FAMILY_UNKNOWN;
257 m_quilt_proj = PROJECTION_UNKNOWN;
258 m_chart_familyFix = CHART_FAMILY_UNKNOWN;
259 m_lost_refchart_dbIndex = -1;
269 new ArrayOfSortedQuiltCandidates(CompareQuiltCandidateScales);
274 m_preferred_family = CHART_FAMILY_RASTER;
277 m_bquiltskew = g_bopengl;
279 m_bquiltanyproj = g_bopengl;
283 m_PatchList.DeleteContents(
true);
286 EmptyCandidateArray();
287 delete m_pcandidate_array;
289 m_extended_stack_array.clear();
294void Quilt::SetReferenceChart(
int dbIndex) {
302 m_refchart_dbIndex = dbIndex;
308bool Quilt::IsVPBlittable(
ViewPort &VPoint,
int dx,
int dy,
309 bool b_allow_vector) {
310 if (!m_vp_rendered.IsValid())
return false;
315 double deltax = p2.m_x - p1.m_x;
316 double deltay = p2.m_y - p1.m_y;
318 if ((fabs(deltax - dx) > 1e-2) || (fabs(deltay - dy) > 1e-2))
return false;
323bool Quilt::IsChartS57Overlay(
int db_index) {
324 if (db_index < 0)
return false;
327 if (CHART_FAMILY_VECTOR == cte.GetChartFamily()) {
328 return s57chart::IsCellOverlayType(cte.GetFullSystemPath());
333bool Quilt::IsChartQuiltableRef(
int db_index) {
334 if (db_index < 0 || db_index >
ChartData->GetChartTableEntries() - 1)
340 bool bproj_match =
true;
342 double skew_norm = ctei.GetChartSkew();
343 if (skew_norm > 180.) skew_norm -= 360.;
346 fabs(skew_norm) < 1.;
347 if (m_bquiltskew) skew_match =
true;
350 bool b_noshow =
false;
351 for (
unsigned int i = 0; i < m_parent->GetQuiltNoshowIindexArray().size();
353 if (m_parent->GetQuiltNoshowIindexArray()[i] ==
361 return (bproj_match & skew_match & !b_noshow);
364bool Quilt::IsChartInQuilt(
ChartBase *pc) {
366 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
368 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
369 if (
ChartData->OpenChartFromDB(pqc->dbIndex, FULL_INIT) == pc)
376bool Quilt::IsChartInQuilt(wxString &full_path) {
378 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
380 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
381 auto &cte =
ChartData->GetChartTableEntry(pqc->dbIndex);
382 if (cte.GetpsFullPath()->IsSameAs(full_path))
return true;
388std::vector<int> Quilt::GetCandidatedbIndexArray(
bool from_ref_chart,
389 bool exclude_user_hidden) {
390 std::vector<int> ret;
391 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
395 if (pqc->Scale_ge(m_reference_scale)) {
397 if (exclude_user_hidden) {
398 bool b_noshow =
false;
399 for (
unsigned int i = 0;
400 i < m_parent->GetQuiltNoshowIindexArray().size(); i++) {
401 if (m_parent->GetQuiltNoshowIindexArray()[i] ==
408 if (!b_noshow) ret.push_back(pqc->dbIndex);
410 ret.push_back(pqc->dbIndex);
414 ret.push_back(pqc->dbIndex);
421 return (cnode->GetData());
426void Quilt::EmptyCandidateArray() {
427 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
428 delete m_pcandidate_array->Item(i);
431 m_pcandidate_array->Clear();
441 if (!m_bcomposed)
return NULL;
443 if (m_bbusy)
return NULL;
447 cnode = m_PatchList.GetFirst();
448 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetNext();
449 if (cnode && cnode->GetData()->b_Valid)
450 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
461 if (m_bbusy)
return NULL;
466 cnode = cnode->GetNext();
467 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetNext();
468 if (cnode && cnode->GetData()->b_Valid)
469 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
476ChartBase *Quilt::GetNextSmallerScaleChart() {
481 if (m_bbusy)
return NULL;
486 cnode = cnode->GetPrevious();
487 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetPrevious();
488 if (cnode && cnode->GetData()->b_Valid)
489 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
496ChartBase *Quilt::GetLargestScaleChart() {
499 if (m_bbusy)
return NULL;
503 cnode = m_PatchList.GetLast();
505 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
512 LLRegion chart_region;
513 LLRegion screen_region(vp.GetBBox());
518 if (fabs(cte.GetLonMax() - cte.GetLonMin()) > 180.) {
535 return LLRegion(-80, vp.GetBBox().GetMinLon(), 80,
536 vp.GetBBox().GetMaxLon());
540 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
541 bool aux_ply_skipped =
false;
542 if (nAuxPlyEntries >= 1) {
543 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
544 int nAuxPly = cte.GetAuxCntTableEntry(ip);
545 if (nAuxPly > AUX_PLY_PERF_LIMIT) {
548 aux_ply_skipped =
true;
551 float *pfp = cte.GetpAuxPlyTableEntry(ip);
552 LLRegion t_region(nAuxPly, pfp);
553 t_region.Intersect(screen_region);
557 if (!t_region.Empty()) chart_region.Union(t_region);
561 if (aux_ply_skipped || nAuxPlyEntries == 0) {
562 int n_ply_entries = cte.GetnPlyEntries();
563 float *pfp = cte.GetpPlyTable();
565 if (n_ply_entries >= 3)
568 LLRegion t_region(n_ply_entries, pfp);
569 t_region.Intersect(screen_region);
573 if (!t_region.Empty()) chart_region.Union(t_region);
576 chart_region = screen_region;
580 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
581 if (nNoCovrPlyEntries) {
582 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
583 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
584 if (nNoCovrPly > NOCOVR_PLY_PERF_LIMIT) {
589 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
591 LLRegion t_region(nNoCovrPly, pfp);
592 t_region.Intersect(screen_region);
603 if (!t_region.Empty()) {
604 LLRegion test_region = chart_region;
605 test_region.Subtract(t_region);
607 if (!test_region.Empty()) chart_region = test_region;
616 if ((cte.GetScale() > 90000000) &&
617 (cte.GetChartFamily() == CHART_FAMILY_RASTER))
618 chart_region = screen_region;
626bool Quilt::IsQuiltVector() {
627 if (m_bbusy)
return false;
633 wxPatchListNode *cnode = m_PatchList.GetFirst();
635 if (cnode->GetData()) {
638 if ((pqp->b_Valid) && (!pqp->b_eclipsed) &&
639 (pqp->dbIndex <
ChartData->GetChartTableEntries())) {
641 ChartData->GetChartTableEntry(pqp->dbIndex);
643 if (ctei.GetChartFamily() == CHART_FAMILY_VECTOR) {
649 cnode = cnode->GetNext();
656bool Quilt::DoesQuiltContainPlugins() {
657 if (m_bbusy)
return false;
663 wxPatchListNode *cnode = m_PatchList.GetFirst();
665 if (cnode->GetData()) {
668 if ((pqp->b_Valid) && (!pqp->b_eclipsed)) {
670 ChartData->GetChartTableEntry(pqp->dbIndex);
672 if (ctei.GetChartType() == CHART_TYPE_PLUGIN) {
678 cnode = cnode->GetNext();
685int Quilt::GetChartdbIndexAtPix(
ViewPort &VPoint, wxPoint p) {
686 if (m_bbusy)
return -1;
695 wxPatchListNode *cnode = m_PatchList.GetFirst();
697 if (cnode->GetData()->ActiveRegion.Contains(lat, lon)) {
698 ret = cnode->GetData()->dbIndex;
701 cnode = cnode->GetNext();
709 if (m_bbusy)
return NULL;
721 wxPatchListNode *cnode = m_PatchList.GetFirst();
724 if (!pqp->b_overlay && (pqp->ActiveRegion.Contains(lat, lon)))
725 if (
ChartData->IsChartInCache(pqp->dbIndex)) {
726 pret =
ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
728 cnode = cnode->GetNext();
736 if (m_bbusy)
return NULL;
748 wxPatchListNode *cnode = m_PatchList.GetFirst();
751 if (pqp->b_overlay && (pqp->ActiveRegion.Contains(lat, lon)))
752 pret =
ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
753 cnode = cnode->GetNext();
760void Quilt::InvalidateAllQuiltPatchs() {
771std::vector<int> Quilt::GetQuiltIndexArray() {
772 return m_index_array;
774 std::vector<int> ret;
776 if (m_bbusy)
return ret;
780 wxPatchListNode *cnode = m_PatchList.GetFirst();
782 ret.push_back(cnode->GetData()->dbIndex);
783 cnode = cnode->GetNext();
791bool Quilt::IsQuiltDelta(
ViewPort &vp) {
792 if (!m_vp_quilt.IsValid() || !m_bcomposed)
return true;
796 if (m_vp_quilt.m_projection_type != vp.m_projection_type)
return true;
801 wxPoint cp_last, cp_this;
806 return (cp_last != cp_this);
814 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
816 if (pRefChart) pRefChart->AdjustVP(vp_last, vp_proposed);
819double Quilt::GetRefNativeScale() {
820 double ret_val = 1.0;
823 if (pc) ret_val = pc->GetNativeScale();
829int Quilt::GetNewRefChart() {
835 int new_ref_dbIndex = m_refchart_dbIndex;
836 unsigned int im = m_extended_stack_array.size();
838 for (
unsigned int is = 0; is < im; is++) {
840 ChartData->GetChartTableEntry(m_extended_stack_array[is]);
842 double skew_norm = m.GetChartSkew();
843 if (skew_norm > 180.) skew_norm -= 360.;
845 if ((m.Scale_ge(m_reference_scale)) &&
846 (m_reference_family == m.GetChartFamily()) &&
847 (m_bquiltanyproj || m_quilt_proj == m.GetChartProjectionType()) &&
848 (m_bquiltskew || (fabs(skew_norm) < 1.0))) {
849 new_ref_dbIndex = m_extended_stack_array[is];
854 return new_ref_dbIndex;
857int Quilt::GetNomScaleMax(
int scale, ChartTypeEnum type,
858 ChartFamilyEnum family) {
860 case CHART_FAMILY_RASTER: {
864 case CHART_FAMILY_VECTOR: {
874int Quilt::GetNomScaleMin(
int scale, ChartTypeEnum type,
875 ChartFamilyEnum family) {
876 double zoom_mod = (double)g_chart_zoom_modifier_raster;
878 if (family == CHART_FAMILY_VECTOR)
879 zoom_mod = (double)g_chart_zoom_modifier_vector;
881 double modf = zoom_mod / 5.;
882 double mod = pow(16., modf);
883 mod = wxMax(mod, .2);
884 mod = wxMin(mod, 16.0);
888 case CHART_FAMILY_RASTER: {
889 if (CHART_TYPE_MBTILES == type)
895 return scale * 1 * mod;
898 case CHART_FAMILY_VECTOR: {
899 return scale * 4 * mod;
903 mod = wxMin(mod, 2.0);
904 return scale * 2 * mod;
910 int index, nom, min, max;
913int Quilt::AdjustRefOnZoom(
bool b_zin, ChartFamilyEnum family,
914 ChartTypeEnum type,
double proposed_scale_onscreen) {
915 std::vector<scale> scales;
916 std::vector<scale> scales_mbtiles;
925 bool b_allow_fullscreen_ref =
926 (family == CHART_FAMILY_VECTOR) || b_zin || g_bopengl;
930 int smallest_scale = 1;
931 for (
size_t i = 0; i < m_extended_stack_array.size(); i++) {
932 int index = m_extended_stack_array[i];
933 if (
ChartData->GetDBChartType(index) == type)
934 smallest_scale = wxMax(smallest_scale,
ChartData->GetDBChartScale(index));
939 for (
size_t i = 0; i < m_extended_stack_array.size(); i++) {
940 int test_db_index = m_extended_stack_array[i];
942 if (b_allow_fullscreen_ref ||
943 m_parent->GetpCurrentStack()->DoesStackContaindbIndex(test_db_index)) {
944 if ((family ==
ChartData->GetDBChartFamily(test_db_index)) &&
945 IsChartQuiltableRef(test_db_index)
947 int nscale =
ChartData->GetDBChartScale(test_db_index);
949 int nmax_scale = GetNomScaleMax(nscale, type, family);
953 if (0 == i_first) nmax_scale = 1;
955 int nmin_scale = GetNomScaleMin(nscale, type, family);
958 if ((type == CHART_TYPE_KAP) && (nscale == smallest_scale))
963 if ((type == CHART_TYPE_MBTILES) && (nscale == smallest_scale))
966 if (CHART_TYPE_MBTILES ==
ChartData->GetDBChartType(test_db_index))
967 scales_mbtiles.push_back(
968 scale{test_db_index, nscale, nmin_scale, nmax_scale});
971 scale{test_db_index, nscale, nmin_scale, nmax_scale});
978 if (scales.empty()) scales = scales_mbtiles;
985 if (CHART_FAMILY_VECTOR == family) {
986 for (
size_t i = scales.size(); i; i--) {
987 int test_db_index = scales[i - 1].index;
988 if (type ==
ChartData->GetDBChartType(test_db_index)) {
989 scales[i - 1].min = scales[i - 1].nom * 80;
1001 if (scales.size() > 1) {
1002 for (
unsigned i = 0; i < scales.size() - 1; i++) {
1003 int min_scale_test = wxMax(scales[i].min, scales[i + 1].max + 1);
1004 min_scale_test = wxMin(min_scale_test, scales[i].min * 2);
1005 scales[i].min = min_scale_test;
1014 if (scales.size() > 2) {
1015 for (
size_t i = scales.size() - 2; i >= 1; i--) {
1016 scales[i].max = wxMin(scales[i].max, scales[i - 1].min - 1);
1020 int new_ref_dbIndex = -1;
1024 for (
size_t i = 0; i < scales.size(); i++) {
1025 if ((proposed_scale_onscreen <
1028 (proposed_scale_onscreen > scales[i].max)) {
1029 new_ref_dbIndex = scales[i].index;
1034 return new_ref_dbIndex;
1037int Quilt::AdjustRefOnZoomOut(
double proposed_scale_onscreen) {
1039 m_lost_refchart_dbIndex = -1;
1041 int current_db_index = m_refchart_dbIndex;
1042 int current_family = m_reference_family;
1043 ChartTypeEnum current_type = (ChartTypeEnum)m_reference_type;
1045 if (m_refchart_dbIndex >= 0) {
1047 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1048 current_family = cte.GetChartFamily();
1049 current_type = (ChartTypeEnum)cte.GetChartType();
1052 if (current_type == CHART_TYPE_CM93COMP)
return current_db_index;
1054 int proposed_ref_index =
1055 AdjustRefOnZoom(
false, (ChartFamilyEnum)current_family, current_type,
1056 proposed_scale_onscreen);
1059 if (proposed_ref_index < 0) {
1060 m_zout_family = current_family;
1061 m_zout_type = current_type;
1062 m_zout_dbindex = current_db_index;
1065 if (proposed_ref_index < 0) {
1066 return m_refchart_dbIndex;
1068 SetReferenceChart(proposed_ref_index);
1069 return proposed_ref_index;
1073int Quilt::AdjustRefOnZoomIn(
double proposed_scale_onscreen) {
1075 m_lost_refchart_dbIndex = -1;
1077 int current_db_index = m_refchart_dbIndex;
1078 int current_family = m_reference_family;
1079 ChartTypeEnum current_type = (ChartTypeEnum)m_reference_type;
1081 if (m_zout_family >= 0) {
1082 current_type = (ChartTypeEnum)m_zout_type;
1083 current_family = m_zout_family;
1089 if (current_type == CHART_TYPE_CM93COMP) {
1090 if (m_zout_family >= 0) {
1091 current_family =
ChartData->GetDBChartFamily(m_zout_dbindex);
1093 return current_db_index;
1096 if ((-1 == m_refchart_dbIndex) && (m_zout_dbindex >= 0))
1097 BuildExtendedChartStackAndCandidateArray(m_zout_dbindex, m_vp_quilt);
1099 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, m_vp_quilt);
1101 int proposed_ref_index =
1102 AdjustRefOnZoom(
true, (ChartFamilyEnum)current_family, current_type,
1103 proposed_scale_onscreen);
1105 if (current_db_index == -1) {
1106 SetReferenceChart(proposed_ref_index);
1107 return proposed_ref_index;
1110 if (proposed_ref_index != -1) {
1111 if (
ChartData->GetDBChartScale(current_db_index) >=
1112 ChartData->GetDBChartScale(proposed_ref_index)) {
1113 SetReferenceChart(proposed_ref_index);
1114 return proposed_ref_index;
1117 proposed_ref_index = current_db_index;
1119 SetReferenceChart(proposed_ref_index);
1121 return proposed_ref_index;
1124bool Quilt::IsChartSmallestScale(
int dbIndex) {
1129 int specified_type =
ChartData->GetDBChartType(dbIndex);
1130 int target_dbindex = -1;
1132 unsigned int target_stack_index = 0;
1133 if (m_extended_stack_array.size()) {
1134 while ((target_stack_index <= (m_extended_stack_array.size() - 1))) {
1135 int test_db_index = m_extended_stack_array[target_stack_index];
1137 if (specified_type ==
ChartData->GetDBChartType(test_db_index))
1138 target_dbindex = test_db_index;
1140 target_stack_index++;
1143 return (dbIndex == target_dbindex);
1146LLRegion Quilt::GetHiliteRegion() {
1152 for (
auto &index : m_HiLiteIndexArray) {
1154 LLRegion cell_region = GetChartQuiltRegion(cte, m_vp_quilt);
1155 r.Union(cell_region);
1159 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
1160 wxPatchListNode *pcinode = m_PatchList.Item(i);
1162 if ((index == piqp->dbIndex) && (piqp->b_Valid))
1164 r.Union(piqp->ActiveRegion);
1173LLRegion Quilt::GetHiliteRegion() {
1175 if (m_nHiLiteIndex >= 0) {
1177 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
1178 wxPatchListNode *pcinode = m_PatchList.Item(i);
1180 if ((m_nHiLiteIndex == piqp->dbIndex) && (piqp->b_Valid))
1182 r = piqp->ActiveRegion;
1189 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1191 if (m_nHiLiteIndex == pqc->dbIndex) {
1192 LLRegion chart_region = pqc->GetCandidateRegion();
1193 if (!chart_region.Empty()) {
1195 bool b_eclipsed =
false;
1196 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size();
1198 if (m_nHiLiteIndex == m_eclipsed_stack_array[ir]) {
1204 if (!b_eclipsed) r = chart_region;
1214 ChartData->GetChartTableEntry(m_nHiLiteIndex);
1215 if (cte.GetChartType() == CHART_TYPE_MBTILES) {
1216 r = GetTilesetRegion(m_nHiLiteIndex);
1224const LLRegion &Quilt::GetTilesetRegion(
int dbIndex) {
1225 LLRegion world_region(-90, -180, 90, 180);
1228 LLRegion &target_region =
const_cast<LLRegion &
>(cte.quilt_candidate_region);
1230 if (!target_region.Empty())
return target_region;
1233 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
1234 if (nAuxPlyEntries >= 1) {
1235 target_region.Clear();
1236 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
1237 float *pfp = cte.GetpAuxPlyTableEntry(ip);
1238 int nAuxPly = cte.GetAuxCntTableEntry(ip);
1240 target_region.Union(LLRegion(nAuxPly, pfp));
1243 std::vector<float> vec =
ChartData->GetReducedPlyPoints(dbIndex);
1245 std::vector<float> vecr;
1246 for (
size_t i = 0; i < vec.size() / 2; i++) {
1247 float a = vec[i * 2 + 1];
1253 std::vector<float>::iterator it = vecr.begin();
1255 if (vecr.size() / 2 >= 3) {
1258 target_region = LLRegion(vecr.size() / 2, (
float *)&(*it));
1260 target_region = world_region;
1264 if (!target_region.Empty()) {
1265 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
1266 if (nNoCovrPlyEntries) {
1267 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
1268 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
1269 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
1271 LLRegion t_region = LLRegion(nNoCovrPly, pfp);
1278 if (!t_region.Empty()) {
1279 LLRegion test_region = target_region;
1280 test_region.Subtract(t_region);
1282 if (!test_region.Empty()) target_region = test_region;
1296 return target_region;
1299int Quilt::SelectRefChartByFamily(ChartFamilyEnum family) {
1301 auto array = GetFullscreenIndexArray();
1303 std::sort(array.begin(), array.end(), CompareScalesStd);
1307 for (
int dbIndex : array) {
1313 wxFileName fn(cte_candidate.GetFullPath());
1314 if (fn.GetPath().Lower().Contains(
"basemap"))
continue;
1317 if (cte_candidate.GetChartFamily() == family) {
1319 m_chart_familyFix = family;
1324 m_lost_refchart_dbIndex = -1;
1329bool Quilt::BuildExtendedChartStackAndCandidateArray(
int ref_db_index,
1331 double zoom_test_val = .002;
1334 EmptyCandidateArray();
1335 m_extended_stack_array.clear();
1336 m_fullscreen_index_array.clear();
1338 int reference_scale = 1e8;
1339 int reference_type = -1;
1340 int reference_family = -1;
1342 m_bquiltanyproj ? vp_in.m_projection_type : PROJECTION_UNKNOWN;
1344 if (ref_db_index >= 0) {
1346 ChartData->GetChartTableEntry(ref_db_index);
1347 reference_scale = cte_ref.GetScale();
1348 reference_type = cte_ref.GetChartType();
1349 if (!m_bquiltanyproj) quilt_proj =
ChartData->GetDBChartProj(ref_db_index);
1350 reference_family = cte_ref.GetChartFamily();
1353 bool b_need_resort =
false;
1363 int n_charts = m_parent->GetpCurrentStack()->nEntry;
1367 for (
int ics = 0; ics < n_charts; ics++) {
1368 int istack = m_parent->GetpCurrentStack()->GetDBIndex(ics);
1369 if (istack < 0)
continue;
1370 m_extended_stack_array.push_back(istack);
1376 if (reference_type == CHART_TYPE_CM93COMP)
continue;
1386 if ((cte.GetChartType() == CHART_TYPE_PLUGIN) ||
1387 (reference_type == CHART_TYPE_PLUGIN)) {
1388 if (reference_family != cte.GetChartFamily()) {
1392 if (reference_type != cte.GetChartType()) {
1398 wxFileName fn(cte.GetFullPath());
1399 if (!fn.GetPath().Lower().Contains(
"basemap"))
continue;
1403 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1406 int candidate_chart_scale = cte.GetScale();
1407 double chart_native_ppm =
1408 m_canvas_scale_factor / (double)candidate_chart_scale;
1410 if ((zoom_factor < zoom_test_val) &&
1415 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
1416 m_extended_stack_array.pop_back();
1420 double skew_norm = cte.GetChartSkew();
1421 if (skew_norm > 180.) skew_norm -= 360.;
1423 if ((m_bquiltskew ? 1 : fabs(skew_norm) < 1.0) &&
1424 (m_bquiltanyproj || cte.GetChartProjectionType() == quilt_proj)) {
1426 qcnew->dbIndex = istack;
1427 qcnew->SetScale(cte.GetScale());
1428 m_pcandidate_array->push_back(qcnew);
1455 int n_all_charts =
ChartData->GetChartTableEntries();
1457 LLBBox viewbox = vp_local.GetBBox();
1458 int sure_index = -1;
1459 int sure_index_scale = 0;
1460 int sure_index_type = -1;
1462 for (
int i = 0; i < n_all_charts; i++) {
1466 int groupIndex = m_parent->m_groupIndex;
1467 if ((groupIndex > 0) && (!
ChartData->IsChartInGroup(i, groupIndex)))
1473 if (
ChartData->IsChartDirectoryExcluded(cte.GetFullPath()))
continue;
1475 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
1476 m_fullscreen_index_array.push_back(i);
1481 wxFileName fn(cte.GetFullSystemPath());
1482 if (!androidIsDirWritable(fn.GetPath()))
continue;
1484 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1486 const LLBBox &chart_box = cte.GetBBox();
1487 if ((viewbox.IntersectOut(chart_box)))
continue;
1489 if (cte.GetChartType() == CHART_TYPE_PLUGIN) {
1490 if (!
ChartData->IsChartAvailable(i))
continue;
1493 m_fullscreen_index_array.push_back(i);
1500 bool guest_family_include =
false;
1501 if (reference_family != cte.GetChartFamily()) {
1502 wxFileName fn(cte.GetFullPath());
1503 if (fn.GetPath().Lower().Contains(
"basemap")) {
1504 guest_family_include =
true;
1507 if (m_lost_refchart_dbIndex == i) guest_family_include =
true;
1509 if ((cte.GetChartType() != CHART_TYPE_MBTILES) && !guest_family_include)
1513 if (!m_bquiltanyproj && quilt_proj != cte.GetChartProjectionType())
1516 double skew_norm = cte.GetChartSkew();
1517 if (skew_norm > 180.) skew_norm -= 360.;
1519 if (!m_bquiltskew && fabs(skew_norm) > 1.0)
continue;
1524 if( CHART_TYPE_S57 == cte.GetChartType() ) {
1526 double chart_area = (cte.GetLonMax() - cte.GetLonMin()) *
1527 (cte.GetLatMax() - cte.GetLatMin());
1528 double quilt_area = viewbox.GetLonRange() * viewbox.GetLatRange();
1529 if ((chart_area / quilt_area) < .01)
continue;
1532 int candidate_chart_scale = cte.GetScale();
1538 if (!cte.Scale_ge(reference_scale)) {
1539 if (cte.Scale_gt(sure_index_scale)) {
1541 sure_index_scale = candidate_chart_scale;
1542 sure_index_type = cte.GetChartType();
1551 double chart_native_ppm =
1552 m_canvas_scale_factor / (double)candidate_chart_scale;
1554 double zoom_factor_test_extra = 0.2;
1560 double ref_scale_test = reference_scale;
1561 if (cte.GetChartType() == CHART_TYPE_MBTILES)
1562 ref_scale_test = candidate_chart_scale;
1564 if ((cte.Scale_ge(ref_scale_test) && (zoom_factor > zoom_test_val)) ||
1565 (zoom_factor > zoom_factor_test_extra)) {
1566 LLRegion cell_region = GetChartQuiltRegion(cte, vp_local);
1571 if (!cell_region.Empty()) {
1574 bool b_exists =
false;
1575 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1576 if (i == m_extended_stack_array[ir]) {
1590 bool b_noadd =
false;
1591 auto &cte_n =
ChartData->GetChartTableEntry(i);
1592 for (
unsigned int id = 0;
id < m_extended_stack_array.size();
id++) {
1593 if (m_extended_stack_array[
id] != -1) {
1595 ChartData->GetChartTableEntry(m_extended_stack_array[
id]);
1596 bool bsameTime =
false;
1597 if (cte_m.GetFileTime() && cte_n.GetFileTime()) {
1598 if (labs(cte_m.GetFileTime() - cte_n.GetFileTime()) < 60)
1601 if (cte_m.GetChartEditionDate() == cte_n.GetChartEditionDate())
1605 if (cte_n.GetpFileName()->IsSameAs(*(cte_m.GetpFileName())))
1612 m_extended_stack_array.push_back(i);
1617 candidate_chart_scale);
1619 m_pcandidate_array->push_back(qcnew);
1621 b_need_resort =
true;
1630 if (-1 != sure_index) {
1632 bool sure_exists =
false;
1633 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1634 if (sure_index == m_extended_stack_array[ir]) {
1641 if (!sure_exists && (sure_index_type != CHART_TYPE_MBTILES)) {
1642 m_extended_stack_array.push_back(sure_index);
1645 qcnew->dbIndex = sure_index;
1646 qcnew->SetScale(
ChartData->GetDBChartScale(sure_index));
1647 m_pcandidate_array->push_back(qcnew);
1649 b_need_resort =
true;
1654 if (b_need_resort && m_extended_stack_array.size() > 1) {
1655 std::sort(m_extended_stack_array.begin(), m_extended_stack_array.end(),
1659 std::sort(m_fullscreen_index_array.begin(), m_fullscreen_index_array.end(),
1660 CompareScalesStdFULLSCREEN);
1665int Quilt::AdjustRefSelection(
const ViewPort &vp_in) {
1680 vp_local.SetRotationAngle(0.);
1682 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1684 ChartFamilyEnum family = CHART_FAMILY_RASTER;
1685 ChartTypeEnum type = CHART_TYPE_KAP;
1688 if (m_refchart_dbIndex >= 0) {
1690 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1691 type = (ChartTypeEnum)cte_ref.GetChartType();
1692 family = (ChartFamilyEnum)cte_ref.GetChartFamily();
1695 int ret_index = AdjustRefOnZoom(
true, family, type, vp_in.
chart_scale);
1700double Quilt::GetBestStartScale(
int dbi_ref_hint,
const ViewPort &vp_in) {
1710 int tentative_ref_index = dbi_ref_hint;
1711 if (dbi_ref_hint < 0) {
1718 tentative_ref_index = m_parent->GetpCurrentStack()->GetDBIndex(0);
1725 vp_local.SetRotationAngle(0.);
1727 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1731 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1733 if (qc->dbIndex == tentative_ref_index) {
1739 if (!bf && m_pcandidate_array->GetCount()) {
1740 tentative_ref_index = GetNewRefChart();
1741 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1744 double proposed_scale_onscreen = vp_in.
chart_scale;
1746 if (m_pcandidate_array->GetCount()) {
1747 SetReferenceChart(tentative_ref_index);
1751 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1753 if (IsChartQuiltableRef(qc->dbIndex)) {
1754 SetReferenceChart(qc->dbIndex);
1761 SetReferenceChart(m_parent->GetpCurrentStack()->GetDBIndex(0));
1764 if (m_refchart_dbIndex >= 0) {
1769 double min_ref_scale =
1771 double max_ref_scale = pc->GetNormalScaleMax(
1773 if ((proposed_scale_onscreen >= min_ref_scale) &&
1774 (proposed_scale_onscreen <= max_ref_scale))
1777 proposed_scale_onscreen = wxMin(proposed_scale_onscreen, max_ref_scale);
1778 proposed_scale_onscreen = wxMax(proposed_scale_onscreen, min_ref_scale);
1786 if (m_refchart_dbIndex >= 0 &&
ChartData)
1787 return ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
1791void Quilt::UnlockQuilt() {
1792 wxASSERT(m_bbusy ==
false);
1795 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1797 ChartData->UnLockCacheChart(pqc->dbIndex);
1807 if (!m_parent->GetpCurrentStack())
return false;
1809 if (m_bbusy)
return false;
1818 if (m_refchart_dbIndex >= 0) {
1820 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1821 m_reference_scale = cte_ref.GetScale();
1822 m_reference_type = cte_ref.GetChartType();
1823 if (!m_bquiltanyproj)
1824 m_quilt_proj =
ChartData->GetDBChartProj(m_refchart_dbIndex);
1825 m_reference_family = cte_ref.GetChartFamily();
1829 if (!m_bquiltanyproj) vp_local.SetProjectionType(m_quilt_proj);
1836 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1876 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1878 if (qc->dbIndex == m_refchart_dbIndex) {
1887 if (m_chart_familyFix == CHART_FAMILY_UNKNOWN) {
1888 if (!bf && m_pcandidate_array->GetCount() &&
1889 (m_reference_type != CHART_TYPE_CM93COMP)) {
1890 m_lost_refchart_dbIndex = m_refchart_dbIndex;
1891 int candidate_ref_index = GetNewRefChart();
1892 if (m_refchart_dbIndex != candidate_ref_index) {
1893 m_refchart_dbIndex = candidate_ref_index;
1894 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1901 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1902 if (m_pcandidate_array->GetCount()) {
1903 int alternate_index =
1904 m_pcandidate_array->Item(m_pcandidate_array->GetCount() - 1)
1907 ChartData->GetChartTableEntry(alternate_index);
1909 if (GetRefFamily() == cte_alt.GetChartFamily()) {
1910 m_refchart_dbIndex = alternate_index;
1911 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex,
1919 if ((-1 != m_lost_refchart_dbIndex) &&
1920 (m_lost_refchart_dbIndex != m_refchart_dbIndex)) {
1923 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1924 if (m_lost_refchart_dbIndex == m_extended_stack_array[ir]) {
1925 m_refchart_dbIndex = m_lost_refchart_dbIndex;
1926 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1927 m_lost_refchart_dbIndex = -1;
1933 bool b_has_overlays =
false;
1936 if (CHART_FAMILY_VECTOR == m_reference_family) {
1937 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1941 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1942 b_has_overlays =
true;
1954 const LLRegion cvp_region = vp_local.GetLLRegion(vp_local.rv_rect);
1955 LLRegion vp_region = cvp_region;
1961 for (ir = 0; ir < m_pcandidate_array->GetCount();
1965 if (pqc->dbIndex == m_refchart_dbIndex) {
1974 const double z = 111274.96299695622;
1980 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1982 LLRegion vpu_region(cvp_region);
1985 LLRegion &chart_region = pqc_ref->GetReducedCandidateRegion(factor);
1987 if (cte_ref.GetChartType() != CHART_TYPE_MBTILES) {
1988 if (!chart_region.Empty()) {
1989 vpu_region.Intersect(chart_region);
1991 if (vpu_region.Empty())
1992 pqc_ref->b_include =
false;
1994 pqc_ref->b_include =
true;
1995 vp_region.Subtract(chart_region);
1998 pqc_ref->b_include =
false;
2000 pqc_ref->b_include =
false;
2005 if (!vp_region.Empty()) {
2006 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2009 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
2016 if (CHART_FAMILY_VECTOR == m_reference_family) {
2017 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
2023 if (CHART_TYPE_MBTILES == cte.GetChartType()) {
2024 pqc->b_include =
false;
2028 if (cte.Scale_ge(m_reference_scale)) {
2032 bool b_in_noshow =
false;
2033 for (
unsigned int ins = 0;
2034 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2035 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2045 LLRegion vpu_region(cvp_region);
2048 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2050 if (!chart_region.Empty()) {
2051 vpu_region.Intersect(chart_region);
2053 if (vpu_region.Empty())
2054 pqc->b_include =
false;
2056 pqc->b_include =
true;
2057 vp_region.Subtract(chart_region);
2060 pqc->b_include =
false;
2062 pqc->b_include =
true;
2066 pqc->b_include =
false;
2069 if (vp_region.Empty())
2076 if (b_has_overlays && (CHART_FAMILY_VECTOR == m_reference_family)) {
2077 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2080 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
2084 if (cte.Scale_ge(m_reference_scale)) {
2085 bool b_in_noshow =
false;
2086 for (
unsigned int ins = 0;
2087 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2088 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2098 LLRegion vpu_region(cvp_region);
2101 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2103 if (!chart_region.Empty()) vpu_region.Intersect(chart_region);
2105 if (vpu_region.Empty())
2106 pqc->b_include =
false;
2109 s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2110 if (b_overlay) pqc->b_include =
true;
2117 ChartData->GetChartTableEntry(m_refchart_dbIndex);
2118 if (s57chart::IsCellOverlayType(cte_ref.GetFullSystemPath())) {
2119 pqc->b_include =
true;
2131 m_eclipsed_stack_array.clear();
2133 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2136 if (!pqc->b_include) {
2138 if (cte.Scale_ge(m_reference_scale) &&
2139 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
2140 m_eclipsed_stack_array.push_back(pqc->dbIndex);
2141 pqc->b_eclipsed =
true;
2148 if (((m_bquiltanyproj || m_quilt_proj == PROJECTION_MERCATOR)) &&
2149 !vp_region.Empty()) {
2150 bool b_must_add_cm93 =
true;
2157 while( updd .HaveRects()) {
2158 wxRect rect = updd.GetRect();
2159 if( ( rect.width > 2 ) && ( rect.height > 2 ) ) {
2160 b_must_add_cm93 =
true;
2167 if (b_must_add_cm93) {
2168 for (
int ics = 0; ics < m_parent->GetpCurrentStack()->nEntry; ics++) {
2169 int i = m_parent->GetpCurrentStack()->GetDBIndex(ics);
2170 if (CHART_TYPE_CM93COMP ==
ChartData->GetDBChartType(i)) {
2173 qcnew->SetScale(
ChartData->GetDBChartScale(i));
2175 m_pcandidate_array->Add(qcnew);
2186 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
2188 if (pqc->b_include) {
2194 if (!b_vis && m_pcandidate_array->GetCount()) {
2197 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2202 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2205 if (cte.GetChartType() == CHART_TYPE_MBTILES)
continue;
2208 LLRegion vpck_region(vp_local.GetBBox());
2211 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2213 if (!chart_region.Empty()) vpck_region.Intersect(chart_region);
2215 if (!vpck_region.Empty()) {
2217 if (cte.Scale_eq(add_scale)) {
2218 pqc->b_include =
true;
2221 pqc->b_include =
true;
2222 add_scale = cte.GetScale();
2231 m_PatchList.DeleteContents(
true);
2232 m_PatchList.Clear();
2234 if (m_pcandidate_array->GetCount()) {
2235 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2243 if (m.GetChartType() == CHART_TYPE_CM93COMP)
2244 pqc->b_include =
true;
2247 if (pqc->b_include) {
2249 pqp->dbIndex = pqc->dbIndex;
2250 pqp->ProjType = m.GetChartProjectionType();
2253 pqp->quilt_region = pqc->GetCandidateRegion();
2256 pqp->b_Valid =
true;
2258 m_PatchList.Append(pqp);
2265 if (!m_bquiltanyproj) {
2267 m_quilt_proj = PROJECTION_MERCATOR;
2268 ChartBase *ppc = GetLargestScaleChart();
2269 if (ppc) m_quilt_proj = ppc->GetChartProjectionType();
2273 if (!m_bquiltanyproj) {
2276 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2277 wxPatchListNode *pcinode = m_PatchList.Item(i);
2279 if ((piqp->ProjType != m_quilt_proj) &&
2280 (piqp->ProjType != PROJECTION_UNKNOWN))
2281 piqp->b_Valid =
false;
2286 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2287 wxPatchListNode *pcinode = m_PatchList.Item(i);
2289 for (
unsigned int ins = 0;
2290 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2291 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2294 piqp->b_Valid =
false;
2302 m_covered_region.Clear();
2307 bool b_skipCM93 =
false;
2308 if (m_reference_type == CHART_TYPE_CM93COMP) {
2310 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2311 wxPatchListNode *pcinode = m_PatchList.Item(i);
2318 if (m.GetChartType() == CHART_TYPE_CM93COMP) {
2320 piqp->ActiveRegion = piqp->quilt_region;
2321 piqp->ActiveRegion.Intersect(cvp_region);
2325 m_covered_region.Union(piqp->quilt_region);
2335 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2336 wxPatchListNode *pcinode = m_PatchList.Item(i);
2344 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2348 piqp->ActiveRegion = piqp->quilt_region;
2351 if (!b_has_overlays && m_PatchList.GetCount() < 25)
2352 piqp->ActiveRegion.Subtract(m_covered_region);
2354 piqp->ActiveRegion.Intersect(cvp_region);
2358 if (piqp->ActiveRegion.Empty() && (piqp->dbIndex != m_refchart_dbIndex))
2359 piqp->b_eclipsed =
true;
2362 piqp->b_overlay =
false;
2363 if (cte.GetChartFamily() == CHART_FAMILY_VECTOR) {
2364 piqp->b_overlay = s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2367 if (!piqp->b_overlay) m_covered_region.Union(piqp->quilt_region);
2372 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2373 wxPatchListNode *pcinode = m_PatchList.Item(i);
2382 LLRegion vpr_region = piqp->quilt_region;
2390 for (
unsigned int k = i + 1; k < m_PatchList.GetCount(); k++) {
2391 wxPatchListNode *pnode = m_PatchList.Item(k);
2412 if (!b_has_overlays) {
2413 if (!vpr_region.Empty()) {
2415 ChartData->GetChartTableEntry(pqp->dbIndex);
2416 LLRegion larger_scale_chart_region =
2419 vpr_region.Subtract(larger_scale_chart_region);
2428 wxPatchListNode *pinode = m_PatchList.Item(i);
2430 pqpi->ActiveRegion = vpr_region;
2439 if (pqpi->ActiveRegion.Empty()) pqpi->b_eclipsed =
true;
2447 m_covered_region.Union(pqpi->ActiveRegion);
2454 unsigned int il = 0;
2455 while (il < m_PatchList.GetCount()) {
2456 wxPatchListNode *pcinode = m_PatchList.Item(il);
2458 if (piqp->b_eclipsed) {
2461 bool b_noadd =
false;
2462 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size(); ir++) {
2463 if (piqp->dbIndex == m_eclipsed_stack_array[ir]) {
2468 if (!b_noadd) m_eclipsed_stack_array.push_back(piqp->dbIndex);
2470 m_PatchList.DeleteNode(pcinode);
2489 m_parent->EnablePaint(
false);
2496 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2498 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2499 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2500 ChartData->LockCacheChart(pqc->dbIndex);
2505 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2507 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2508 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2509 ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
true);
2518 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2520 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2521 if (
ChartData->IsChartLocked(pqc->dbIndex))
2522 pqc->b_locked =
true;
2524 pqc->b_locked =
ChartData->LockCacheChart(pqc->dbIndex);
2529 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2531 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2537 if (
ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
2539 pqc->b_locked =
true;
2544 m_parent->EnablePaint(
true);
2547 m_last_index_array = m_index_array;
2549 m_index_array.clear();
2552 unsigned int kl = m_PatchList.GetCount();
2553 for (
unsigned int k = 0; k < kl; k++) {
2554 wxPatchListNode *cnode = m_PatchList.Item((kl - k) - 1);
2555 m_index_array.push_back(cnode->GetData()->dbIndex);
2556 cnode = cnode->GetNext();
2562 m_quilt_depth_unit =
"";
2565 m_quilt_depth_unit = pc->GetDepthUnits();
2567 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2568 int units = ps52plib->m_nDepthUnitDisplay;
2571 m_quilt_depth_unit =
"Feet";
2574 m_quilt_depth_unit =
"Meters";
2577 m_quilt_depth_unit =
"Fathoms";
2583 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2584 wxPatchListNode *pnode = m_PatchList.Item(k);
2592 wxString du = pc->GetDepthUnits();
2593 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2594 int units = ps52plib->m_nDepthUnitDisplay;
2607 wxString dul = du.Lower();
2608 wxString ml = m_quilt_depth_unit.Lower();
2612 if (dul.StartsWith(
"meters") && ml.StartsWith(
"meters"))
2614 else if (dul.StartsWith(
"metres") && ml.StartsWith(
"metres"))
2616 else if (dul.StartsWith(
"fathoms") && ml.StartsWith(
"fathoms"))
2618 else if (dul.StartsWith(
"met") && ml.StartsWith(
"met"))
2622 m_quilt_depth_unit =
"";
2632 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2633 wxPatchListNode *pnode = m_PatchList.Item(k);
2637 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2638 wxLogMessage(
" Quilt Compose cache miss...");
2639 ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
2640 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2641 wxLogMessage(
" Oops, removing from quilt...");
2642 pqp->b_Valid =
false;
2649 if (!
ChartData->IsChartInCache(m_refchart_dbIndex))
2650 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
2656 m_bquilt_has_overlays =
false;
2657 m_max_error_factor = 0.;
2658 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2659 wxPatchListNode *pnode = m_PatchList.Item(k);
2667 m_max_error_factor =
2668 wxMax(m_max_error_factor, pc->GetChart_Error_Factor());
2669 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2670 bool isOverlay = IsChartS57Overlay(pqp->dbIndex);
2671 pqp->b_overlay = isOverlay;
2672 if (isOverlay) m_bquilt_has_overlays =
true;
2685 unsigned long xa_hash = 5381;
2686 for (
unsigned int im = 0; im < m_extended_stack_array.size(); im++) {
2687 int dbindex = m_extended_stack_array[im];
2688 xa_hash = ((xa_hash << 5) + xa_hash) + dbindex;
2691 m_xa_hash = xa_hash;
2699 if (!m_bcomposed)
return;
2703 if (GetnCharts() && !m_bbusy && !chart_region.Empty()) {
2709 if (!(chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2710 vp.b_MercatorProjectionOverride)) {
2714 chart_region, pqp->ActiveRegion, chart->GetNativeScale());
2715 if (!get_screen_region.Empty())
2716 rendered_region.Union(get_screen_region);
2719 chart = GetNextChart();
2723 m_rendered_region = rendered_region;
2728bool Quilt::RenderQuiltRegionViewOnDCNoText(wxMemoryDC &dc,
ViewPort &vp,
2730 return DoRenderQuiltRegionViewOnDC(dc, vp, chart_region);
2733bool Quilt::RenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
2735 return DoRenderQuiltRegionViewOnDCTextOnly(dc, vp, chart_region);
2738bool Quilt::DoRenderQuiltRegionViewOnDC(wxMemoryDC &dc,
ViewPort &vp,
2740#ifdef ocpnUSE_DIBSECTION
2746 if (!m_bcomposed)
return false;
2750 if (GetnCharts() && !m_bbusy) {
2758 int chartsDrawn = 0;
2760 if (!chart_region.Empty()) {
2762 bool okToRender =
true;
2764 if (chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2765 vp.b_MercatorProjectionOverride)
2769 chart = GetNextChart();
2774 bool b_chart_rendered =
false;
2775 LLRegion get_region = pqp->ActiveRegion;
2778 chart_region, get_region, chart->GetNativeScale());
2779 if (!get_screen_region.Empty()) {
2780 if (!pqp->b_overlay) {
2781 if (chart->GetChartType() == CHART_TYPE_CM93COMP) {
2783 chart->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2787 if (Chs57->m_RAZBuilt) {
2788 b_chart_rendered = Chs57->RenderRegionViewOnDCNoText(
2789 tmp_dc, vp, get_screen_region);
2795 b_chart_rendered = ChPI->RenderRegionViewOnDCNoText(
2796 tmp_dc, vp, get_screen_region);
2798 b_chart_rendered = chart->RenderRegionViewOnDC(
2799 tmp_dc, vp, get_screen_region);
2801 b_chart_rendered =
true;
2808 screen_region.Subtract(get_screen_region);
2813 while (upd.HaveRects()) {
2814 wxRect rect = upd.GetRect();
2815 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc, rect.x,
2816 rect.y, wxCOPY,
true);
2820 tmp_dc.SelectObject(wxNullBitmap);
2822 if (b_chart_rendered) rendered_region.Union(get_screen_region);
2826 chart = GetNextChart();
2830 if (!chartsDrawn) m_parent->GetVP().SetProjectionType(PROJECTION_MERCATOR);
2833 if (m_bquilt_has_overlays && !chart_region.Empty()) {
2834 chart = GetFirstChart();
2838 if (pqp->b_overlay) {
2839 LLRegion get_region = pqp->ActiveRegion;
2841 chart_region, get_region, chart->GetNativeScale());
2842 if (!get_region.Empty()) {
2845 Chs57->RenderOverlayRegionViewOnDC(tmp_dc, vp,
2851 ChPI->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2856 while (upd.HaveRects()) {
2857 wxRect rect = upd.GetRect();
2858 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc,
2859 rect.x, rect.y, wxCOPY,
true);
2862 tmp_dc.SelectObject(wxNullBitmap);
2867 chart = GetNextChart();
2874 while (clrit.HaveRects()) {
2875 wxRect rect = clrit.GetRect();
2877 dc.SetPen(*wxBLACK_PEN);
2878 dc.SetBrush(*wxBLACK_BRUSH);
2879 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
2881 dc.Blit(rect.x, rect.y, rect.width, rect.height, &dc, rect.x, rect.y,
2888 if (m_nHiLiteIndex >= 0) {
2891 wxRect box = hiregion.GetBox();
2893 if (!box.IsEmpty()) {
2896 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2897 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2904 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2908 q_dc.SelectObject(*m_pBM);
2909 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2910 q_dc.SelectObject(wxNullBitmap);
2915 wxBitmap hl_mask_bm(vp.rv_rect.width, vp.rv_rect.height, 1);
2917 mdc.SelectObject(hl_mask_bm);
2918 mdc.SetBackground(*wxBLACK_BRUSH);
2920 mdc.SetClippingRegion(box);
2921 mdc.SetBackground(*wxWHITE_BRUSH);
2923 mdc.SelectObject(wxNullBitmap);
2925 if (hl_mask_bm.IsOk()) {
2926 wxMask *phl_mask =
new wxMask(hl_mask_bm);
2927 m_pBM->SetMask(phl_mask);
2928 q_dc.SelectObject(*m_pBM);
2931 wxBitmap rbm(vp.rv_rect.width, vp.rv_rect.height);
2932 wxMask *pr_mask =
new wxMask(hl_mask_bm);
2934 rbm.SetMask(pr_mask);
2935 rdc.SelectObject(rbm);
2936 unsigned char hlcolor = 255;
2937 switch (global_color_scheme) {
2938 case GLOBAL_COLOR_SCHEME_DAY:
2941 case GLOBAL_COLOR_SCHEME_DUSK:
2944 case GLOBAL_COLOR_SCHEME_NIGHT:
2952 rdc.SetBackground(wxBrush(wxColour(hlcolor, 0, 0)));
2956 while (upd.HaveRects()) {
2957 wxRect rect = upd.GetRect();
2958 rdc.Blit(rect.x, rect.y, rect.width, rect.height, &q_dc, rect.x,
2959 rect.y, wxOR,
true);
2964 while (updq.HaveRects()) {
2965 wxRect rect = updq.GetRect();
2966 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &rdc, rect.x,
2967 rect.y, wxCOPY,
true);
2971 q_dc.SelectObject(wxNullBitmap);
2972 m_pBM->SetMask(NULL);
2975 dc.SelectObject(*m_pBM);
2978 rdc.SelectObject(wxNullBitmap);
2984 if (g_fog_overzoom) {
2987 if (scale_factor > g_overzoom_emphasis_base) {
2988 float fog = ((scale_factor - g_overzoom_emphasis_base) * 255.) / 20.;
2989 fog = wxMin(fog, 200.);
2993 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2994 (m_pBM->GetHeight() != vp.rv_rect.height)) {
3001 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
3005 q_dc.SelectObject(*m_pBM);
3006 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
3007 q_dc.SelectObject(wxNullBitmap);
3009 wxImage src = m_pBM->ConvertToImage();
3012 wxMin((scale_factor - g_overzoom_emphasis_base) / 4, 4);
3014 wxImage dest = src.Blur(blur_factor);
3018 unsigned char *bg = src.GetData();
3019 wxColour color = m_parent->GetFogColor();
3021 float transparency = fog;
3024 wxImage dest(vp.rv_rect.width, vp.rv_rect.height);
3025 unsigned char *dest_data = (
unsigned char *) malloc( vp.rv_rect.width * vp.rv_rect.height * 3 *
sizeof(
unsigned char) );
3026 unsigned char *d = dest_data;
3028 float alpha = 1.0 - (float)transparency / 255.0;
3029 int sb = vp.rv_rect.width * vp.rv_rect.height;
3030 for(
int i = 0; i < sb; i++ ) {
3033 int r = ( ( *bg++ ) * a ) + (1.0-a) * color.Red();
3035 int g = ( ( *bg++ ) * a ) + (1.0-a) * color.Green();
3037 int b = ( ( *bg++ ) * a ) + (1.0-a) * color.Blue();
3041 dest.SetData( dest_data );
3046 ddc.SelectObject(dim);
3048 q_dc.SelectObject(*m_pBM);
3050 while (upd.HaveRects()) {
3051 wxRect rect = upd.GetRect();
3052 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &ddc, rect.x,
3057 ddc.SelectObject(wxNullBitmap);
3058 q_dc.SelectObject(wxNullBitmap);
3061 dc.SelectObject(*m_pBM);
3069 SubstituteClearDC(dc, vp);
3073 SubstituteClearDC(dc, vp);
3077 m_rendered_region = rendered_region;
3083void Quilt::SubstituteClearDC(wxMemoryDC &dc,
ViewPort &vp) {
3085 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
3086 (m_pBM->GetHeight() != vp.rv_rect.height)) {
3092 if (NULL == m_pBM) {
3093 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
3096 dc.SelectObject(wxNullBitmap);
3097 dc.SelectObject(*m_pBM);
3098 dc.SetBackground(*wxBLACK_BRUSH);
3100 m_covered_region.Clear();
3103bool Quilt::DoRenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
3105 if (!m_bcomposed)
return false;
3109 if (GetnCharts() && !m_bbusy) {
3114 ChartBase *chart = GetLargestScaleChart();
3121 Chs57->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3125 ChPI->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3130 chart = GetNextSmallerScaleChart();
3134 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.