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);
69static int CompareScales(
int i1,
int i2) {
75 if (cte1.Scale_eq(cte2.GetScale())) {
77 lat1 = cte1.GetLatMax();
78 lat2 = cte2.GetLatMax();
79 if (roundf(lat1 * 100.) == roundf(lat2 * 100.)) {
81 lon1 = cte1.GetLonMin();
82 lon2 = cte2.GetLonMin();
86 return (lon1 < lon2) ? -1 : 1;
88 return (lat1 < lat2) ? 1 : -1;
90 return cte1.GetScale() - cte2.GetScale();
92static bool CompareScalesStd(
int i1,
int i2) {
93 return CompareScales(i1, i2) < 0;
99 return CompareScales(qc1->dbIndex, qc2->dbIndex);
102const LLRegion &QuiltCandidate::GetCandidateRegion() {
104 LLRegion &candidate_region =
105 const_cast<LLRegion &
>(cte.quilt_candidate_region);
107 if (!candidate_region.Empty())
return candidate_region;
109 LLRegion world_region(-90, -180, 90, 180);
113 if (
ChartData->GetDBChartType(dbIndex) == CHART_TYPE_CM93COMP) {
114 double cm93_ll_bounds[8] = {-80, -180, -80, 180, 80, 180, 80, -180};
115 candidate_region = LLRegion(4, cm93_ll_bounds);
116 return candidate_region;
120 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
121 if (nAuxPlyEntries >= 1) {
122 candidate_region.Clear();
123 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
124 float *pfp = cte.GetpAuxPlyTableEntry(ip);
125 int nAuxPly = cte.GetAuxCntTableEntry(ip);
127 candidate_region.Union(LLRegion(nAuxPly, pfp));
140 std::vector<float> vec =
ChartData->GetReducedPlyPoints(dbIndex);
142 std::vector<float> vecr;
143 for (
size_t i = 0; i < vec.size() / 2; i++) {
144 float a = vec[i * 2 + 1];
150 std::vector<float>::iterator it = vecr.begin();
152 if (vecr.size() / 2 >= 3) {
155 candidate_region = LLRegion(vecr.size() / 2, (
float *)&(*it));
157 candidate_region = world_region;
161 if (!candidate_region
163 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
164 if (nNoCovrPlyEntries) {
165 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
166 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
167 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
169 LLRegion t_region = LLRegion(nNoCovrPly, pfp);
178 if (nAuxPlyEntries > 1) {
179 for (
int ipr = 0; ipr < nAuxPlyEntries; ipr++) {
180 float *pfpr = cte.GetpAuxPlyTableEntry(ipr);
181 int nAuxPly = cte.GetAuxCntTableEntry(ipr);
182 t_region.Subtract(LLRegion(nAuxPly, pfpr));
191 if (!t_region.Empty()) {
192 LLRegion test_region = candidate_region;
193 test_region.Subtract(t_region);
194 if (!test_region.Empty()) candidate_region = test_region;
204 if ((cte.GetScale() > 90000000) &&
205 (cte.GetChartFamily() == CHART_FAMILY_RASTER))
206 candidate_region = world_region;
208 return candidate_region;
211LLRegion &QuiltCandidate::GetReducedCandidateRegion(
double factor) {
212 if (factor != last_factor) {
213 reduced_candidate_region = GetCandidateRegion();
214 reduced_candidate_region.Reduce(factor);
215 last_factor = factor;
218 return reduced_candidate_region;
221void QuiltCandidate::SetScale(
int scale) {
225 if (
scale >= 1000) rounding = 5 * pow(10, log10(
scale) - 2);
234 m_reference_scale = 1;
235 m_refchart_dbIndex = -1;
236 m_reference_type = CHART_TYPE_UNKNOWN;
237 m_reference_family = CHART_FAMILY_UNKNOWN;
238 m_quilt_proj = PROJECTION_UNKNOWN;
239 m_chart_familyFix = CHART_FAMILY_UNKNOWN;
240 m_lost_refchart_dbIndex = -1;
250 new ArrayOfSortedQuiltCandidates(CompareQuiltCandidateScales);
255 m_preferred_family = CHART_FAMILY_RASTER;
258 m_bquiltskew = g_bopengl;
260 m_bquiltanyproj = g_bopengl;
264 m_PatchList.DeleteContents(
true);
267 EmptyCandidateArray();
268 delete m_pcandidate_array;
270 m_extended_stack_array.clear();
275void Quilt::SetReferenceChart(
int dbIndex) {
283 m_refchart_dbIndex = dbIndex;
289bool Quilt::IsVPBlittable(
ViewPort &VPoint,
int dx,
int dy,
290 bool b_allow_vector) {
291 if (!m_vp_rendered.IsValid())
return false;
296 double deltax = p2.m_x - p1.m_x;
297 double deltay = p2.m_y - p1.m_y;
299 if ((fabs(deltax - dx) > 1e-2) || (fabs(deltay - dy) > 1e-2))
return false;
304bool Quilt::IsChartS57Overlay(
int db_index) {
305 if (db_index < 0)
return false;
308 if (CHART_FAMILY_VECTOR == cte.GetChartFamily()) {
309 return s57chart::IsCellOverlayType(cte.GetFullSystemPath());
314bool Quilt::IsChartQuiltableRef(
int db_index) {
315 if (db_index < 0 || db_index >
ChartData->GetChartTableEntries() - 1)
321 bool bproj_match =
true;
323 double skew_norm = ctei.GetChartSkew();
324 if (skew_norm > 180.) skew_norm -= 360.;
327 fabs(skew_norm) < 1.;
328 if (m_bquiltskew) skew_match =
true;
331 bool b_noshow =
false;
332 for (
unsigned int i = 0; i < m_parent->GetQuiltNoshowIindexArray().size();
334 if (m_parent->GetQuiltNoshowIindexArray()[i] ==
342 return (bproj_match & skew_match & !b_noshow);
345bool Quilt::IsChartInQuilt(
ChartBase *pc) {
347 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
349 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
350 if (
ChartData->OpenChartFromDB(pqc->dbIndex, FULL_INIT) == pc)
357bool Quilt::IsChartInQuilt(wxString &full_path) {
359 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
361 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
362 auto &cte =
ChartData->GetChartTableEntry(pqc->dbIndex);
363 if (cte.GetpsFullPath()->IsSameAs(full_path))
return true;
369std::vector<int> Quilt::GetCandidatedbIndexArray(
bool from_ref_chart,
370 bool exclude_user_hidden) {
371 std::vector<int> ret;
372 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
376 if (pqc->Scale_ge(m_reference_scale)) {
378 if (exclude_user_hidden) {
379 bool b_noshow =
false;
380 for (
unsigned int i = 0;
381 i < m_parent->GetQuiltNoshowIindexArray().size(); i++) {
382 if (m_parent->GetQuiltNoshowIindexArray()[i] ==
389 if (!b_noshow) ret.push_back(pqc->dbIndex);
391 ret.push_back(pqc->dbIndex);
395 ret.push_back(pqc->dbIndex);
402 return (cnode->GetData());
407void Quilt::EmptyCandidateArray() {
408 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
409 delete m_pcandidate_array->Item(i);
412 m_pcandidate_array->Clear();
422 if (!m_bcomposed)
return NULL;
424 if (m_bbusy)
return NULL;
428 cnode = m_PatchList.GetFirst();
429 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetNext();
430 if (cnode && cnode->GetData()->b_Valid)
431 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
442 if (m_bbusy)
return NULL;
447 cnode = cnode->GetNext();
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);
457ChartBase *Quilt::GetNextSmallerScaleChart() {
462 if (m_bbusy)
return NULL;
467 cnode = cnode->GetPrevious();
468 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetPrevious();
469 if (cnode && cnode->GetData()->b_Valid)
470 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
477ChartBase *Quilt::GetLargestScaleChart() {
480 if (m_bbusy)
return NULL;
484 cnode = m_PatchList.GetLast();
486 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
493 LLRegion chart_region;
494 LLRegion screen_region(vp.GetBBox());
499 if (fabs(cte.GetLonMax() - cte.GetLonMin()) > 180.) {
516 return LLRegion(-80, vp.GetBBox().GetMinLon(), 80,
517 vp.GetBBox().GetMaxLon());
521 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
522 bool aux_ply_skipped =
false;
523 if (nAuxPlyEntries >= 1) {
524 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
525 int nAuxPly = cte.GetAuxCntTableEntry(ip);
526 if (nAuxPly > AUX_PLY_PERF_LIMIT) {
529 aux_ply_skipped =
true;
532 float *pfp = cte.GetpAuxPlyTableEntry(ip);
533 LLRegion t_region(nAuxPly, pfp);
534 t_region.Intersect(screen_region);
538 if (!t_region.Empty()) chart_region.Union(t_region);
542 if (aux_ply_skipped || nAuxPlyEntries == 0) {
543 int n_ply_entries = cte.GetnPlyEntries();
544 float *pfp = cte.GetpPlyTable();
546 if (n_ply_entries >= 3)
549 LLRegion t_region(n_ply_entries, pfp);
550 t_region.Intersect(screen_region);
554 if (!t_region.Empty()) chart_region.Union(t_region);
557 chart_region = screen_region;
561 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
562 if (nNoCovrPlyEntries) {
563 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
564 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
565 if (nNoCovrPly > NOCOVR_PLY_PERF_LIMIT) {
570 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
572 LLRegion t_region(nNoCovrPly, pfp);
573 t_region.Intersect(screen_region);
584 if (!t_region.Empty()) {
585 LLRegion test_region = chart_region;
586 test_region.Subtract(t_region);
588 if (!test_region.Empty()) chart_region = test_region;
597 if ((cte.GetScale() > 90000000) &&
598 (cte.GetChartFamily() == CHART_FAMILY_RASTER))
599 chart_region = screen_region;
607bool Quilt::IsQuiltVector() {
608 if (m_bbusy)
return false;
614 wxPatchListNode *cnode = m_PatchList.GetFirst();
616 if (cnode->GetData()) {
619 if ((pqp->b_Valid) && (!pqp->b_eclipsed) &&
620 (pqp->dbIndex <
ChartData->GetChartTableEntries())) {
622 ChartData->GetChartTableEntry(pqp->dbIndex);
624 if (ctei.GetChartFamily() == CHART_FAMILY_VECTOR) {
630 cnode = cnode->GetNext();
637bool Quilt::DoesQuiltContainPlugins() {
638 if (m_bbusy)
return false;
644 wxPatchListNode *cnode = m_PatchList.GetFirst();
646 if (cnode->GetData()) {
649 if ((pqp->b_Valid) && (!pqp->b_eclipsed)) {
651 ChartData->GetChartTableEntry(pqp->dbIndex);
653 if (ctei.GetChartType() == CHART_TYPE_PLUGIN) {
659 cnode = cnode->GetNext();
666int Quilt::GetChartdbIndexAtPix(
ViewPort &VPoint, wxPoint p) {
667 if (m_bbusy)
return -1;
676 wxPatchListNode *cnode = m_PatchList.GetFirst();
678 if (cnode->GetData()->ActiveRegion.Contains(lat, lon)) {
679 ret = cnode->GetData()->dbIndex;
682 cnode = cnode->GetNext();
690 if (m_bbusy)
return NULL;
702 wxPatchListNode *cnode = m_PatchList.GetFirst();
705 if (!pqp->b_overlay && (pqp->ActiveRegion.Contains(lat, lon)))
706 if (
ChartData->IsChartInCache(pqp->dbIndex)) {
707 pret =
ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
709 cnode = cnode->GetNext();
717 if (m_bbusy)
return NULL;
729 wxPatchListNode *cnode = m_PatchList.GetFirst();
732 if (pqp->b_overlay && (pqp->ActiveRegion.Contains(lat, lon)))
733 pret =
ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
734 cnode = cnode->GetNext();
741void Quilt::InvalidateAllQuiltPatchs() {
752std::vector<int> Quilt::GetQuiltIndexArray() {
753 return m_index_array;
755 std::vector<int> ret;
757 if (m_bbusy)
return ret;
761 wxPatchListNode *cnode = m_PatchList.GetFirst();
763 ret.push_back(cnode->GetData()->dbIndex);
764 cnode = cnode->GetNext();
772bool Quilt::IsQuiltDelta(
ViewPort &vp) {
773 if (!m_vp_quilt.IsValid() || !m_bcomposed)
return true;
777 if (m_vp_quilt.m_projection_type != vp.m_projection_type)
return true;
782 wxPoint cp_last, cp_this;
787 return (cp_last != cp_this);
795 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
797 if (pRefChart) pRefChart->AdjustVP(vp_last, vp_proposed);
800double Quilt::GetRefNativeScale() {
801 double ret_val = 1.0;
804 if (pc) ret_val = pc->GetNativeScale();
810int Quilt::GetNewRefChart() {
816 int new_ref_dbIndex = m_refchart_dbIndex;
817 unsigned int im = m_extended_stack_array.size();
819 for (
unsigned int is = 0; is < im; is++) {
821 ChartData->GetChartTableEntry(m_extended_stack_array[is]);
823 double skew_norm = m.GetChartSkew();
824 if (skew_norm > 180.) skew_norm -= 360.;
826 if ((m.Scale_ge(m_reference_scale)) &&
827 (m_reference_family == m.GetChartFamily()) &&
828 (m_bquiltanyproj || m_quilt_proj == m.GetChartProjectionType()) &&
829 (m_bquiltskew || (fabs(skew_norm) < 1.0))) {
830 new_ref_dbIndex = m_extended_stack_array[is];
835 return new_ref_dbIndex;
838int Quilt::GetNomScaleMax(
int scale, ChartTypeEnum type,
839 ChartFamilyEnum family) {
841 case CHART_FAMILY_RASTER: {
845 case CHART_FAMILY_VECTOR: {
855int Quilt::GetNomScaleMin(
int scale, ChartTypeEnum type,
856 ChartFamilyEnum family) {
857 double zoom_mod = (double)g_chart_zoom_modifier_raster;
859 if (family == CHART_FAMILY_VECTOR)
860 zoom_mod = (double)g_chart_zoom_modifier_vector;
862 double modf = zoom_mod / 5.;
863 double mod = pow(16., modf);
864 mod = wxMax(mod, .2);
865 mod = wxMin(mod, 16.0);
869 case CHART_FAMILY_RASTER: {
870 if (CHART_TYPE_MBTILES == type)
876 return scale * 1 * mod;
879 case CHART_FAMILY_VECTOR: {
880 return scale * 4 * mod;
884 mod = wxMin(mod, 2.0);
885 return scale * 2 * mod;
891 int index, nom, min, max;
894int Quilt::AdjustRefOnZoom(
bool b_zin, ChartFamilyEnum family,
895 ChartTypeEnum type,
double proposed_scale_onscreen) {
896 std::vector<scale> scales;
897 std::vector<scale> scales_mbtiles;
906 bool b_allow_fullscreen_ref =
907 (family == CHART_FAMILY_VECTOR) || b_zin || g_bopengl;
911 int smallest_scale = 1;
912 for (
size_t i = 0; i < m_extended_stack_array.size(); i++) {
913 int index = m_extended_stack_array[i];
914 if (
ChartData->GetDBChartType(index) == type)
915 smallest_scale = wxMax(smallest_scale,
ChartData->GetDBChartScale(index));
920 for (
size_t i = 0; i < m_extended_stack_array.size(); i++) {
921 int test_db_index = m_extended_stack_array[i];
923 if (b_allow_fullscreen_ref ||
924 m_parent->GetpCurrentStack()->DoesStackContaindbIndex(test_db_index)) {
925 if ((family ==
ChartData->GetDBChartFamily(test_db_index)) &&
926 IsChartQuiltableRef(test_db_index)
928 int nscale =
ChartData->GetDBChartScale(test_db_index);
930 int nmax_scale = GetNomScaleMax(nscale, type, family);
934 if (0 == i_first) nmax_scale = 1;
936 int nmin_scale = GetNomScaleMin(nscale, type, family);
939 if ((type == CHART_TYPE_KAP) && (nscale == smallest_scale))
944 if ((type == CHART_TYPE_MBTILES) && (nscale == smallest_scale))
947 if (CHART_TYPE_MBTILES ==
ChartData->GetDBChartType(test_db_index))
948 scales_mbtiles.push_back(
949 scale{test_db_index, nscale, nmin_scale, nmax_scale});
952 scale{test_db_index, nscale, nmin_scale, nmax_scale});
959 if (scales.empty()) scales = scales_mbtiles;
966 if (CHART_FAMILY_VECTOR == family) {
967 for (
size_t i = scales.size(); i; i--) {
968 int test_db_index = scales[i - 1].index;
969 if (type ==
ChartData->GetDBChartType(test_db_index)) {
970 scales[i - 1].min = scales[i - 1].nom * 80;
982 if (scales.size() > 1) {
983 for (
unsigned i = 0; i < scales.size() - 1; i++) {
984 int min_scale_test = wxMax(scales[i].min, scales[i + 1].max + 1);
985 min_scale_test = wxMin(min_scale_test, scales[i].min * 2);
986 scales[i].min = min_scale_test;
995 if (scales.size() > 2) {
996 for (
size_t i = scales.size() - 2; i >= 1; i--) {
997 scales[i].max = wxMin(scales[i].max, scales[i - 1].min - 1);
1001 int new_ref_dbIndex = -1;
1005 for (
size_t i = 0; i < scales.size(); i++) {
1006 if ((proposed_scale_onscreen <
1009 (proposed_scale_onscreen > scales[i].max)) {
1010 new_ref_dbIndex = scales[i].index;
1015 return new_ref_dbIndex;
1018int Quilt::AdjustRefOnZoomOut(
double proposed_scale_onscreen) {
1020 m_lost_refchart_dbIndex = -1;
1022 int current_db_index = m_refchart_dbIndex;
1023 int current_family = m_reference_family;
1024 ChartTypeEnum current_type = (ChartTypeEnum)m_reference_type;
1026 if (m_refchart_dbIndex >= 0) {
1028 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1029 current_family = cte.GetChartFamily();
1030 current_type = (ChartTypeEnum)cte.GetChartType();
1033 if (current_type == CHART_TYPE_CM93COMP)
return current_db_index;
1035 int proposed_ref_index =
1036 AdjustRefOnZoom(
false, (ChartFamilyEnum)current_family, current_type,
1037 proposed_scale_onscreen);
1040 if (proposed_ref_index < 0) {
1041 m_zout_family = current_family;
1042 m_zout_type = current_type;
1043 m_zout_dbindex = current_db_index;
1046 if (proposed_ref_index < 0) {
1047 return m_refchart_dbIndex;
1049 SetReferenceChart(proposed_ref_index);
1050 return proposed_ref_index;
1054int Quilt::AdjustRefOnZoomIn(
double proposed_scale_onscreen) {
1056 m_lost_refchart_dbIndex = -1;
1058 int current_db_index = m_refchart_dbIndex;
1059 int current_family = m_reference_family;
1060 ChartTypeEnum current_type = (ChartTypeEnum)m_reference_type;
1062 if (m_zout_family >= 0) {
1063 current_type = (ChartTypeEnum)m_zout_type;
1064 current_family = m_zout_family;
1070 if (current_type == CHART_TYPE_CM93COMP) {
1071 if (m_zout_family >= 0) {
1072 current_family =
ChartData->GetDBChartFamily(m_zout_dbindex);
1074 return current_db_index;
1077 if ((-1 == m_refchart_dbIndex) && (m_zout_dbindex >= 0))
1078 BuildExtendedChartStackAndCandidateArray(m_zout_dbindex, m_vp_quilt);
1080 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, m_vp_quilt);
1082 int proposed_ref_index =
1083 AdjustRefOnZoom(
true, (ChartFamilyEnum)current_family, current_type,
1084 proposed_scale_onscreen);
1086 if (current_db_index == -1) {
1087 SetReferenceChart(proposed_ref_index);
1088 return proposed_ref_index;
1091 if (proposed_ref_index != -1) {
1092 if (
ChartData->GetDBChartScale(current_db_index) >=
1093 ChartData->GetDBChartScale(proposed_ref_index)) {
1094 SetReferenceChart(proposed_ref_index);
1095 return proposed_ref_index;
1098 proposed_ref_index = current_db_index;
1100 SetReferenceChart(proposed_ref_index);
1102 return proposed_ref_index;
1105bool Quilt::IsChartSmallestScale(
int dbIndex) {
1110 int specified_type =
ChartData->GetDBChartType(dbIndex);
1111 int target_dbindex = -1;
1113 unsigned int target_stack_index = 0;
1114 if (m_extended_stack_array.size()) {
1115 while ((target_stack_index <= (m_extended_stack_array.size() - 1))) {
1116 int test_db_index = m_extended_stack_array[target_stack_index];
1118 if (specified_type ==
ChartData->GetDBChartType(test_db_index))
1119 target_dbindex = test_db_index;
1121 target_stack_index++;
1124 return (dbIndex == target_dbindex);
1127LLRegion Quilt::GetHiliteRegion() {
1133 for (
auto &index : m_HiLiteIndexArray) {
1135 LLRegion cell_region = GetChartQuiltRegion(cte, m_vp_quilt);
1136 r.Union(cell_region);
1140 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
1141 wxPatchListNode *pcinode = m_PatchList.Item(i);
1143 if ((index == piqp->dbIndex) && (piqp->b_Valid))
1145 r.Union(piqp->ActiveRegion);
1154LLRegion Quilt::GetHiliteRegion() {
1156 if (m_nHiLiteIndex >= 0) {
1158 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
1159 wxPatchListNode *pcinode = m_PatchList.Item(i);
1161 if ((m_nHiLiteIndex == piqp->dbIndex) && (piqp->b_Valid))
1163 r = piqp->ActiveRegion;
1170 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1172 if (m_nHiLiteIndex == pqc->dbIndex) {
1173 LLRegion chart_region = pqc->GetCandidateRegion();
1174 if (!chart_region.Empty()) {
1176 bool b_eclipsed =
false;
1177 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size();
1179 if (m_nHiLiteIndex == m_eclipsed_stack_array[ir]) {
1185 if (!b_eclipsed) r = chart_region;
1195 ChartData->GetChartTableEntry(m_nHiLiteIndex);
1196 if (cte.GetChartType() == CHART_TYPE_MBTILES) {
1197 r = GetTilesetRegion(m_nHiLiteIndex);
1205const LLRegion &Quilt::GetTilesetRegion(
int dbIndex) {
1206 LLRegion world_region(-90, -180, 90, 180);
1209 LLRegion &target_region =
const_cast<LLRegion &
>(cte.quilt_candidate_region);
1211 if (!target_region.Empty())
return target_region;
1214 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
1215 if (nAuxPlyEntries >= 1) {
1216 target_region.Clear();
1217 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
1218 float *pfp = cte.GetpAuxPlyTableEntry(ip);
1219 int nAuxPly = cte.GetAuxCntTableEntry(ip);
1221 target_region.Union(LLRegion(nAuxPly, pfp));
1224 std::vector<float> vec =
ChartData->GetReducedPlyPoints(dbIndex);
1226 std::vector<float> vecr;
1227 for (
size_t i = 0; i < vec.size() / 2; i++) {
1228 float a = vec[i * 2 + 1];
1234 std::vector<float>::iterator it = vecr.begin();
1236 if (vecr.size() / 2 >= 3) {
1239 target_region = LLRegion(vecr.size() / 2, (
float *)&(*it));
1241 target_region = world_region;
1245 if (!target_region.Empty()) {
1246 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
1247 if (nNoCovrPlyEntries) {
1248 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
1249 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
1250 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
1252 LLRegion t_region = LLRegion(nNoCovrPly, pfp);
1259 if (!t_region.Empty()) {
1260 LLRegion test_region = target_region;
1261 test_region.Subtract(t_region);
1263 if (!test_region.Empty()) target_region = test_region;
1277 return target_region;
1280int Quilt::SelectRefChartByFamily(ChartFamilyEnum family) {
1282 auto array = GetFullscreenIndexArray();
1284 std::sort(array.begin(), array.end(), CompareScalesStd);
1288 for (
int dbIndex : array) {
1294 wxFileName fn(cte_candidate.GetFullPath());
1295 if (fn.GetPath().Lower().Contains(
"basemap"))
continue;
1298 if (cte_candidate.GetChartFamily() == family) {
1300 m_chart_familyFix = family;
1305 m_lost_refchart_dbIndex = -1;
1310bool Quilt::BuildExtendedChartStackAndCandidateArray(
int ref_db_index,
1312 double zoom_test_val = .002;
1315 EmptyCandidateArray();
1316 m_extended_stack_array.clear();
1317 m_fullscreen_index_array.clear();
1319 int reference_scale = 1e8;
1320 int reference_type = -1;
1321 int reference_family = -1;
1323 m_bquiltanyproj ? vp_in.m_projection_type : PROJECTION_UNKNOWN;
1325 if (ref_db_index >= 0) {
1327 ChartData->GetChartTableEntry(ref_db_index);
1328 reference_scale = cte_ref.GetScale();
1329 reference_type = cte_ref.GetChartType();
1330 if (!m_bquiltanyproj) quilt_proj =
ChartData->GetDBChartProj(ref_db_index);
1331 reference_family = cte_ref.GetChartFamily();
1334 bool b_need_resort =
false;
1344 int n_charts = m_parent->GetpCurrentStack()->nEntry;
1348 for (
int ics = 0; ics < n_charts; ics++) {
1349 int istack = m_parent->GetpCurrentStack()->GetDBIndex(ics);
1350 if (istack < 0)
continue;
1351 m_extended_stack_array.push_back(istack);
1357 if (reference_type == CHART_TYPE_CM93COMP)
continue;
1367 if ((cte.GetChartType() == CHART_TYPE_PLUGIN) ||
1368 (reference_type == CHART_TYPE_PLUGIN)) {
1369 if (reference_family != cte.GetChartFamily()) {
1373 if (reference_type != cte.GetChartType()) {
1379 wxFileName fn(cte.GetFullPath());
1380 if (!fn.GetPath().Lower().Contains(
"basemap"))
continue;
1384 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1387 int candidate_chart_scale = cte.GetScale();
1388 double chart_native_ppm =
1389 m_canvas_scale_factor / (double)candidate_chart_scale;
1391 if ((zoom_factor < zoom_test_val) &&
1396 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
1397 m_extended_stack_array.pop_back();
1401 double skew_norm = cte.GetChartSkew();
1402 if (skew_norm > 180.) skew_norm -= 360.;
1404 if ((m_bquiltskew ? 1 : fabs(skew_norm) < 1.0) &&
1405 (m_bquiltanyproj || cte.GetChartProjectionType() == quilt_proj)) {
1407 qcnew->dbIndex = istack;
1408 qcnew->SetScale(cte.GetScale());
1409 m_pcandidate_array->push_back(qcnew);
1436 int n_all_charts =
ChartData->GetChartTableEntries();
1438 LLBBox viewbox = vp_local.GetBBox();
1439 int sure_index = -1;
1440 int sure_index_scale = 0;
1441 int sure_index_type = -1;
1443 for (
int i = 0; i < n_all_charts; i++) {
1447 int groupIndex = m_parent->m_groupIndex;
1448 if ((groupIndex > 0) && (!
ChartData->IsChartInGroup(i, groupIndex)))
1454 if (
ChartData->IsChartDirectoryExcluded(cte.GetFullPath()))
continue;
1456 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
1457 m_fullscreen_index_array.push_back(i);
1462 wxFileName fn(cte.GetFullSystemPath());
1463 if (!androidIsDirWritable(fn.GetPath()))
continue;
1465 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1467 const LLBBox &chart_box = cte.GetBBox();
1468 if ((viewbox.IntersectOut(chart_box)))
continue;
1470 if (cte.GetChartType() == CHART_TYPE_PLUGIN) {
1471 if (!
ChartData->IsChartAvailable(i))
continue;
1474 m_fullscreen_index_array.push_back(i);
1481 bool guest_family_include =
false;
1482 if (reference_family != cte.GetChartFamily()) {
1483 wxFileName fn(cte.GetFullPath());
1484 if (fn.GetPath().Lower().Contains(
"basemap")) {
1485 guest_family_include =
true;
1488 if (m_lost_refchart_dbIndex == i) guest_family_include =
true;
1490 if ((cte.GetChartType() != CHART_TYPE_MBTILES) && !guest_family_include)
1494 if (!m_bquiltanyproj && quilt_proj != cte.GetChartProjectionType())
1497 double skew_norm = cte.GetChartSkew();
1498 if (skew_norm > 180.) skew_norm -= 360.;
1500 if (!m_bquiltskew && fabs(skew_norm) > 1.0)
continue;
1505 if( CHART_TYPE_S57 == cte.GetChartType() ) {
1507 double chart_area = (cte.GetLonMax() - cte.GetLonMin()) *
1508 (cte.GetLatMax() - cte.GetLatMin());
1509 double quilt_area = viewbox.GetLonRange() * viewbox.GetLatRange();
1510 if ((chart_area / quilt_area) < .01)
continue;
1513 int candidate_chart_scale = cte.GetScale();
1519 if (!cte.Scale_ge(reference_scale)) {
1520 if (cte.Scale_gt(sure_index_scale)) {
1522 sure_index_scale = candidate_chart_scale;
1523 sure_index_type = cte.GetChartType();
1532 double chart_native_ppm =
1533 m_canvas_scale_factor / (double)candidate_chart_scale;
1535 double zoom_factor_test_extra = 0.2;
1541 double ref_scale_test = reference_scale;
1542 if (cte.GetChartType() == CHART_TYPE_MBTILES)
1543 ref_scale_test = candidate_chart_scale;
1545 if ((cte.Scale_ge(ref_scale_test) && (zoom_factor > zoom_test_val)) ||
1546 (zoom_factor > zoom_factor_test_extra)) {
1547 LLRegion cell_region = GetChartQuiltRegion(cte, vp_local);
1552 if (!cell_region.Empty()) {
1555 bool b_exists =
false;
1556 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1557 if (i == m_extended_stack_array[ir]) {
1571 bool b_noadd =
false;
1572 auto &cte_n =
ChartData->GetChartTableEntry(i);
1573 for (
unsigned int id = 0;
id < m_extended_stack_array.size();
id++) {
1574 if (m_extended_stack_array[
id] != -1) {
1576 ChartData->GetChartTableEntry(m_extended_stack_array[
id]);
1577 bool bsameTime =
false;
1578 if (cte_m.GetFileTime() && cte_n.GetFileTime()) {
1579 if (labs(cte_m.GetFileTime() - cte_n.GetFileTime()) < 60)
1582 if (cte_m.GetChartEditionDate() == cte_n.GetChartEditionDate())
1586 if (cte_n.GetpFileName()->IsSameAs(*(cte_m.GetpFileName())))
1593 m_extended_stack_array.push_back(i);
1598 candidate_chart_scale);
1600 m_pcandidate_array->push_back(qcnew);
1602 b_need_resort =
true;
1611 if (-1 != sure_index) {
1613 bool sure_exists =
false;
1614 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1615 if (sure_index == m_extended_stack_array[ir]) {
1622 if (!sure_exists && (sure_index_type != CHART_TYPE_MBTILES)) {
1623 m_extended_stack_array.push_back(sure_index);
1626 qcnew->dbIndex = sure_index;
1627 qcnew->SetScale(
ChartData->GetDBChartScale(sure_index));
1628 m_pcandidate_array->push_back(qcnew);
1630 b_need_resort =
true;
1635 if (b_need_resort && m_extended_stack_array.size() > 1) {
1636 std::sort(m_extended_stack_array.begin(), m_extended_stack_array.end(),
1640 std::sort(m_fullscreen_index_array.begin(), m_fullscreen_index_array.end(),
1646int Quilt::AdjustRefSelection(
const ViewPort &vp_in) {
1661 vp_local.SetRotationAngle(0.);
1663 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1665 ChartFamilyEnum family = CHART_FAMILY_RASTER;
1666 ChartTypeEnum type = CHART_TYPE_KAP;
1669 if (m_refchart_dbIndex >= 0) {
1671 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1672 type = (ChartTypeEnum)cte_ref.GetChartType();
1673 family = (ChartFamilyEnum)cte_ref.GetChartFamily();
1676 int ret_index = AdjustRefOnZoom(
true, family, type, vp_in.
chart_scale);
1681double Quilt::GetBestStartScale(
int dbi_ref_hint,
const ViewPort &vp_in) {
1691 int tentative_ref_index = dbi_ref_hint;
1692 if (dbi_ref_hint < 0) {
1699 tentative_ref_index = m_parent->GetpCurrentStack()->GetDBIndex(0);
1706 vp_local.SetRotationAngle(0.);
1708 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1712 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1714 if (qc->dbIndex == tentative_ref_index) {
1720 if (!bf && m_pcandidate_array->GetCount()) {
1721 tentative_ref_index = GetNewRefChart();
1722 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1725 double proposed_scale_onscreen = vp_in.
chart_scale;
1727 if (m_pcandidate_array->GetCount()) {
1728 SetReferenceChart(tentative_ref_index);
1732 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1734 if (IsChartQuiltableRef(qc->dbIndex)) {
1735 SetReferenceChart(qc->dbIndex);
1742 SetReferenceChart(m_parent->GetpCurrentStack()->GetDBIndex(0));
1745 if (m_refchart_dbIndex >= 0) {
1750 double min_ref_scale =
1752 double max_ref_scale = pc->GetNormalScaleMax(
1754 if ((proposed_scale_onscreen >= min_ref_scale) &&
1755 (proposed_scale_onscreen <= max_ref_scale))
1758 proposed_scale_onscreen = wxMin(proposed_scale_onscreen, max_ref_scale);
1759 proposed_scale_onscreen = wxMax(proposed_scale_onscreen, min_ref_scale);
1767 if (m_refchart_dbIndex >= 0 &&
ChartData)
1768 return ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
1772void Quilt::UnlockQuilt() {
1773 wxASSERT(m_bbusy ==
false);
1776 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1778 ChartData->UnLockCacheChart(pqc->dbIndex);
1788 if (!m_parent->GetpCurrentStack())
return false;
1790 if (m_bbusy)
return false;
1799 if (m_refchart_dbIndex >= 0) {
1801 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1802 m_reference_scale = cte_ref.GetScale();
1803 m_reference_type = cte_ref.GetChartType();
1804 if (!m_bquiltanyproj)
1805 m_quilt_proj =
ChartData->GetDBChartProj(m_refchart_dbIndex);
1806 m_reference_family = cte_ref.GetChartFamily();
1810 if (!m_bquiltanyproj) vp_local.SetProjectionType(m_quilt_proj);
1817 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1857 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1859 if (qc->dbIndex == m_refchart_dbIndex) {
1868 if (m_chart_familyFix == CHART_FAMILY_UNKNOWN) {
1869 if (!bf && m_pcandidate_array->GetCount() &&
1870 (m_reference_type != CHART_TYPE_CM93COMP)) {
1871 m_lost_refchart_dbIndex = m_refchart_dbIndex;
1872 int candidate_ref_index = GetNewRefChart();
1873 if (m_refchart_dbIndex != candidate_ref_index) {
1874 m_refchart_dbIndex = candidate_ref_index;
1875 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1882 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1883 if (m_pcandidate_array->GetCount()) {
1884 int alternate_index =
1885 m_pcandidate_array->Item(m_pcandidate_array->GetCount() - 1)
1888 ChartData->GetChartTableEntry(alternate_index);
1890 if (GetRefFamily() == cte_alt.GetChartFamily()) {
1891 m_refchart_dbIndex = alternate_index;
1892 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex,
1900 if ((-1 != m_lost_refchart_dbIndex) &&
1901 (m_lost_refchart_dbIndex != m_refchart_dbIndex)) {
1904 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1905 if (m_lost_refchart_dbIndex == m_extended_stack_array[ir]) {
1906 m_refchart_dbIndex = m_lost_refchart_dbIndex;
1907 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1908 m_lost_refchart_dbIndex = -1;
1914 bool b_has_overlays =
false;
1917 if (CHART_FAMILY_VECTOR == m_reference_family) {
1918 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1922 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1923 b_has_overlays =
true;
1935 const LLRegion cvp_region = vp_local.GetLLRegion(vp_local.rv_rect);
1936 LLRegion vp_region = cvp_region;
1942 for (ir = 0; ir < m_pcandidate_array->GetCount();
1946 if (pqc->dbIndex == m_refchart_dbIndex) {
1955 const double z = 111274.96299695622;
1961 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1963 LLRegion vpu_region(cvp_region);
1966 LLRegion &chart_region = pqc_ref->GetReducedCandidateRegion(factor);
1968 if (cte_ref.GetChartType() != CHART_TYPE_MBTILES) {
1969 if (!chart_region.Empty()) {
1970 vpu_region.Intersect(chart_region);
1972 if (vpu_region.Empty())
1973 pqc_ref->b_include =
false;
1975 pqc_ref->b_include =
true;
1976 vp_region.Subtract(chart_region);
1979 pqc_ref->b_include =
false;
1981 pqc_ref->b_include =
false;
1986 if (!vp_region.Empty()) {
1987 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1990 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
1997 if (CHART_FAMILY_VECTOR == m_reference_family) {
1998 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
2004 if (CHART_TYPE_MBTILES == cte.GetChartType()) {
2005 pqc->b_include =
false;
2009 if (cte.Scale_ge(m_reference_scale)) {
2013 bool b_in_noshow =
false;
2014 for (
unsigned int ins = 0;
2015 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2016 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2026 LLRegion vpu_region(cvp_region);
2029 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2031 if (!chart_region.Empty()) {
2032 vpu_region.Intersect(chart_region);
2034 if (vpu_region.Empty())
2035 pqc->b_include =
false;
2037 pqc->b_include =
true;
2038 vp_region.Subtract(chart_region);
2041 pqc->b_include =
false;
2043 pqc->b_include =
true;
2047 pqc->b_include =
false;
2050 if (vp_region.Empty())
2057 if (b_has_overlays && (CHART_FAMILY_VECTOR == m_reference_family)) {
2058 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2061 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
2065 if (cte.Scale_ge(m_reference_scale)) {
2066 bool b_in_noshow =
false;
2067 for (
unsigned int ins = 0;
2068 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2069 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2079 LLRegion vpu_region(cvp_region);
2082 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2084 if (!chart_region.Empty()) vpu_region.Intersect(chart_region);
2086 if (vpu_region.Empty())
2087 pqc->b_include =
false;
2090 s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2091 if (b_overlay) pqc->b_include =
true;
2098 ChartData->GetChartTableEntry(m_refchart_dbIndex);
2099 if (s57chart::IsCellOverlayType(cte_ref.GetFullSystemPath())) {
2100 pqc->b_include =
true;
2112 m_eclipsed_stack_array.clear();
2114 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2117 if (!pqc->b_include) {
2119 if (cte.Scale_ge(m_reference_scale) &&
2120 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
2121 m_eclipsed_stack_array.push_back(pqc->dbIndex);
2122 pqc->b_eclipsed =
true;
2129 if (((m_bquiltanyproj || m_quilt_proj == PROJECTION_MERCATOR)) &&
2130 !vp_region.Empty()) {
2131 bool b_must_add_cm93 =
true;
2138 while( updd .HaveRects()) {
2139 wxRect rect = updd.GetRect();
2140 if( ( rect.width > 2 ) && ( rect.height > 2 ) ) {
2141 b_must_add_cm93 =
true;
2148 if (b_must_add_cm93) {
2149 for (
int ics = 0; ics < m_parent->GetpCurrentStack()->nEntry; ics++) {
2150 int i = m_parent->GetpCurrentStack()->GetDBIndex(ics);
2151 if (CHART_TYPE_CM93COMP ==
ChartData->GetDBChartType(i)) {
2154 qcnew->SetScale(
ChartData->GetDBChartScale(i));
2156 m_pcandidate_array->Add(qcnew);
2167 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
2169 if (pqc->b_include) {
2175 if (!b_vis && m_pcandidate_array->GetCount()) {
2178 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2183 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2186 if (cte.GetChartType() == CHART_TYPE_MBTILES)
continue;
2189 LLRegion vpck_region(vp_local.GetBBox());
2192 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2194 if (!chart_region.Empty()) vpck_region.Intersect(chart_region);
2196 if (!vpck_region.Empty()) {
2198 if (cte.Scale_eq(add_scale)) {
2199 pqc->b_include =
true;
2202 pqc->b_include =
true;
2203 add_scale = cte.GetScale();
2212 m_PatchList.DeleteContents(
true);
2213 m_PatchList.Clear();
2215 if (m_pcandidate_array->GetCount()) {
2216 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2224 if (m.GetChartType() == CHART_TYPE_CM93COMP)
2225 pqc->b_include =
true;
2228 if (pqc->b_include) {
2230 pqp->dbIndex = pqc->dbIndex;
2231 pqp->ProjType = m.GetChartProjectionType();
2234 pqp->quilt_region = pqc->GetCandidateRegion();
2237 pqp->b_Valid =
true;
2239 m_PatchList.Append(pqp);
2246 if (!m_bquiltanyproj) {
2248 m_quilt_proj = PROJECTION_MERCATOR;
2249 ChartBase *ppc = GetLargestScaleChart();
2250 if (ppc) m_quilt_proj = ppc->GetChartProjectionType();
2254 if (!m_bquiltanyproj) {
2257 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2258 wxPatchListNode *pcinode = m_PatchList.Item(i);
2260 if ((piqp->ProjType != m_quilt_proj) &&
2261 (piqp->ProjType != PROJECTION_UNKNOWN))
2262 piqp->b_Valid =
false;
2267 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2268 wxPatchListNode *pcinode = m_PatchList.Item(i);
2270 for (
unsigned int ins = 0;
2271 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2272 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2275 piqp->b_Valid =
false;
2283 m_covered_region.Clear();
2288 bool b_skipCM93 =
false;
2289 if (m_reference_type == CHART_TYPE_CM93COMP) {
2291 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2292 wxPatchListNode *pcinode = m_PatchList.Item(i);
2299 if (m.GetChartType() == CHART_TYPE_CM93COMP) {
2301 piqp->ActiveRegion = piqp->quilt_region;
2302 piqp->ActiveRegion.Intersect(cvp_region);
2306 m_covered_region.Union(piqp->quilt_region);
2316 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2317 wxPatchListNode *pcinode = m_PatchList.Item(i);
2325 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2329 piqp->ActiveRegion = piqp->quilt_region;
2332 if (!b_has_overlays && m_PatchList.GetCount() < 25)
2333 piqp->ActiveRegion.Subtract(m_covered_region);
2335 piqp->ActiveRegion.Intersect(cvp_region);
2339 if (piqp->ActiveRegion.Empty() && (piqp->dbIndex != m_refchart_dbIndex))
2340 piqp->b_eclipsed =
true;
2343 piqp->b_overlay =
false;
2344 if (cte.GetChartFamily() == CHART_FAMILY_VECTOR) {
2345 piqp->b_overlay = s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2348 if (!piqp->b_overlay) m_covered_region.Union(piqp->quilt_region);
2353 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2354 wxPatchListNode *pcinode = m_PatchList.Item(i);
2363 LLRegion vpr_region = piqp->quilt_region;
2371 for (
unsigned int k = i + 1; k < m_PatchList.GetCount(); k++) {
2372 wxPatchListNode *pnode = m_PatchList.Item(k);
2393 if (!b_has_overlays) {
2394 if (!vpr_region.Empty()) {
2396 ChartData->GetChartTableEntry(pqp->dbIndex);
2397 LLRegion larger_scale_chart_region =
2400 vpr_region.Subtract(larger_scale_chart_region);
2409 wxPatchListNode *pinode = m_PatchList.Item(i);
2411 pqpi->ActiveRegion = vpr_region;
2420 if (pqpi->ActiveRegion.Empty()) pqpi->b_eclipsed =
true;
2428 m_covered_region.Union(pqpi->ActiveRegion);
2435 unsigned int il = 0;
2436 while (il < m_PatchList.GetCount()) {
2437 wxPatchListNode *pcinode = m_PatchList.Item(il);
2439 if (piqp->b_eclipsed) {
2442 bool b_noadd =
false;
2443 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size(); ir++) {
2444 if (piqp->dbIndex == m_eclipsed_stack_array[ir]) {
2449 if (!b_noadd) m_eclipsed_stack_array.push_back(piqp->dbIndex);
2451 m_PatchList.DeleteNode(pcinode);
2470 m_parent->EnablePaint(
false);
2477 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2479 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2480 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2481 ChartData->LockCacheChart(pqc->dbIndex);
2486 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2488 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2489 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2490 ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
true);
2499 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2501 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2502 if (
ChartData->IsChartLocked(pqc->dbIndex))
2503 pqc->b_locked =
true;
2505 pqc->b_locked =
ChartData->LockCacheChart(pqc->dbIndex);
2510 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2512 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2518 if (
ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
2520 pqc->b_locked =
true;
2525 m_parent->EnablePaint(
true);
2528 m_last_index_array = m_index_array;
2530 m_index_array.clear();
2533 unsigned int kl = m_PatchList.GetCount();
2534 for (
unsigned int k = 0; k < kl; k++) {
2535 wxPatchListNode *cnode = m_PatchList.Item((kl - k) - 1);
2536 m_index_array.push_back(cnode->GetData()->dbIndex);
2537 cnode = cnode->GetNext();
2543 m_quilt_depth_unit =
"";
2546 m_quilt_depth_unit = pc->GetDepthUnits();
2548 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2549 int units = ps52plib->m_nDepthUnitDisplay;
2552 m_quilt_depth_unit =
"Feet";
2555 m_quilt_depth_unit =
"Meters";
2558 m_quilt_depth_unit =
"Fathoms";
2564 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2565 wxPatchListNode *pnode = m_PatchList.Item(k);
2573 wxString du = pc->GetDepthUnits();
2574 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2575 int units = ps52plib->m_nDepthUnitDisplay;
2588 wxString dul = du.Lower();
2589 wxString ml = m_quilt_depth_unit.Lower();
2593 if (dul.StartsWith(
"meters") && ml.StartsWith(
"meters"))
2595 else if (dul.StartsWith(
"metres") && ml.StartsWith(
"metres"))
2597 else if (dul.StartsWith(
"fathoms") && ml.StartsWith(
"fathoms"))
2599 else if (dul.StartsWith(
"met") && ml.StartsWith(
"met"))
2603 m_quilt_depth_unit =
"";
2613 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2614 wxPatchListNode *pnode = m_PatchList.Item(k);
2618 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2619 wxLogMessage(
" Quilt Compose cache miss...");
2620 ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
2621 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2622 wxLogMessage(
" Oops, removing from quilt...");
2623 pqp->b_Valid =
false;
2630 if (!
ChartData->IsChartInCache(m_refchart_dbIndex))
2631 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
2637 m_bquilt_has_overlays =
false;
2638 m_max_error_factor = 0.;
2639 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2640 wxPatchListNode *pnode = m_PatchList.Item(k);
2648 m_max_error_factor =
2649 wxMax(m_max_error_factor, pc->GetChart_Error_Factor());
2650 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2651 bool isOverlay = IsChartS57Overlay(pqp->dbIndex);
2652 pqp->b_overlay = isOverlay;
2653 if (isOverlay) m_bquilt_has_overlays =
true;
2666 unsigned long xa_hash = 5381;
2667 for (
unsigned int im = 0; im < m_extended_stack_array.size(); im++) {
2668 int dbindex = m_extended_stack_array[im];
2669 xa_hash = ((xa_hash << 5) + xa_hash) + dbindex;
2672 m_xa_hash = xa_hash;
2680 if (!m_bcomposed)
return;
2684 if (GetnCharts() && !m_bbusy && !chart_region.Empty()) {
2690 if (!(chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2691 vp.b_MercatorProjectionOverride)) {
2695 chart_region, pqp->ActiveRegion, chart->GetNativeScale());
2696 if (!get_screen_region.Empty())
2697 rendered_region.Union(get_screen_region);
2700 chart = GetNextChart();
2704 m_rendered_region = rendered_region;
2709bool Quilt::RenderQuiltRegionViewOnDCNoText(wxMemoryDC &dc,
ViewPort &vp,
2711 return DoRenderQuiltRegionViewOnDC(dc, vp, chart_region);
2714bool Quilt::RenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
2716 return DoRenderQuiltRegionViewOnDCTextOnly(dc, vp, chart_region);
2719bool Quilt::DoRenderQuiltRegionViewOnDC(wxMemoryDC &dc,
ViewPort &vp,
2721#ifdef ocpnUSE_DIBSECTION
2727 if (!m_bcomposed)
return false;
2731 if (GetnCharts() && !m_bbusy) {
2739 int chartsDrawn = 0;
2741 if (!chart_region.Empty()) {
2743 bool okToRender =
true;
2745 if (chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2746 vp.b_MercatorProjectionOverride)
2750 chart = GetNextChart();
2755 bool b_chart_rendered =
false;
2756 LLRegion get_region = pqp->ActiveRegion;
2759 chart_region, get_region, chart->GetNativeScale());
2760 if (!get_screen_region.Empty()) {
2761 if (!pqp->b_overlay) {
2762 if (chart->GetChartType() == CHART_TYPE_CM93COMP) {
2764 chart->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2768 if (Chs57->m_RAZBuilt) {
2769 b_chart_rendered = Chs57->RenderRegionViewOnDCNoText(
2770 tmp_dc, vp, get_screen_region);
2776 b_chart_rendered = ChPI->RenderRegionViewOnDCNoText(
2777 tmp_dc, vp, get_screen_region);
2779 b_chart_rendered = chart->RenderRegionViewOnDC(
2780 tmp_dc, vp, get_screen_region);
2782 b_chart_rendered =
true;
2789 screen_region.Subtract(get_screen_region);
2794 while (upd.HaveRects()) {
2795 wxRect rect = upd.GetRect();
2796 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc, rect.x,
2797 rect.y, wxCOPY,
true);
2801 tmp_dc.SelectObject(wxNullBitmap);
2803 if (b_chart_rendered) rendered_region.Union(get_screen_region);
2807 chart = GetNextChart();
2811 if (!chartsDrawn) m_parent->GetVP().SetProjectionType(PROJECTION_MERCATOR);
2814 if (m_bquilt_has_overlays && !chart_region.Empty()) {
2815 chart = GetFirstChart();
2819 if (pqp->b_overlay) {
2820 LLRegion get_region = pqp->ActiveRegion;
2822 chart_region, get_region, chart->GetNativeScale());
2823 if (!get_region.Empty()) {
2826 Chs57->RenderOverlayRegionViewOnDC(tmp_dc, vp,
2832 ChPI->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2837 while (upd.HaveRects()) {
2838 wxRect rect = upd.GetRect();
2839 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc,
2840 rect.x, rect.y, wxCOPY,
true);
2843 tmp_dc.SelectObject(wxNullBitmap);
2848 chart = GetNextChart();
2855 while (clrit.HaveRects()) {
2856 wxRect rect = clrit.GetRect();
2858 dc.SetPen(*wxBLACK_PEN);
2859 dc.SetBrush(*wxBLACK_BRUSH);
2860 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
2862 dc.Blit(rect.x, rect.y, rect.width, rect.height, &dc, rect.x, rect.y,
2869 if (m_nHiLiteIndex >= 0) {
2872 wxRect box = hiregion.GetBox();
2874 if (!box.IsEmpty()) {
2877 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2878 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2885 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2889 q_dc.SelectObject(*m_pBM);
2890 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2891 q_dc.SelectObject(wxNullBitmap);
2896 wxBitmap hl_mask_bm(vp.rv_rect.width, vp.rv_rect.height, 1);
2898 mdc.SelectObject(hl_mask_bm);
2899 mdc.SetBackground(*wxBLACK_BRUSH);
2901 mdc.SetClippingRegion(box);
2902 mdc.SetBackground(*wxWHITE_BRUSH);
2904 mdc.SelectObject(wxNullBitmap);
2906 if (hl_mask_bm.IsOk()) {
2907 wxMask *phl_mask =
new wxMask(hl_mask_bm);
2908 m_pBM->SetMask(phl_mask);
2909 q_dc.SelectObject(*m_pBM);
2912 wxBitmap rbm(vp.rv_rect.width, vp.rv_rect.height);
2913 wxMask *pr_mask =
new wxMask(hl_mask_bm);
2915 rbm.SetMask(pr_mask);
2916 rdc.SelectObject(rbm);
2917 unsigned char hlcolor = 255;
2918 switch (global_color_scheme) {
2919 case GLOBAL_COLOR_SCHEME_DAY:
2922 case GLOBAL_COLOR_SCHEME_DUSK:
2925 case GLOBAL_COLOR_SCHEME_NIGHT:
2933 rdc.SetBackground(wxBrush(wxColour(hlcolor, 0, 0)));
2937 while (upd.HaveRects()) {
2938 wxRect rect = upd.GetRect();
2939 rdc.Blit(rect.x, rect.y, rect.width, rect.height, &q_dc, rect.x,
2940 rect.y, wxOR,
true);
2945 while (updq.HaveRects()) {
2946 wxRect rect = updq.GetRect();
2947 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &rdc, rect.x,
2948 rect.y, wxCOPY,
true);
2952 q_dc.SelectObject(wxNullBitmap);
2953 m_pBM->SetMask(NULL);
2956 dc.SelectObject(*m_pBM);
2959 rdc.SelectObject(wxNullBitmap);
2965 if (g_fog_overzoom) {
2968 if (scale_factor > g_overzoom_emphasis_base) {
2969 float fog = ((scale_factor - g_overzoom_emphasis_base) * 255.) / 20.;
2970 fog = wxMin(fog, 200.);
2974 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2975 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2982 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2986 q_dc.SelectObject(*m_pBM);
2987 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2988 q_dc.SelectObject(wxNullBitmap);
2990 wxImage src = m_pBM->ConvertToImage();
2993 wxMin((scale_factor - g_overzoom_emphasis_base) / 4, 4);
2995 wxImage dest = src.Blur(blur_factor);
2999 unsigned char *bg = src.GetData();
3000 wxColour color = m_parent->GetFogColor();
3002 float transparency = fog;
3005 wxImage dest(vp.rv_rect.width, vp.rv_rect.height);
3006 unsigned char *dest_data = (
unsigned char *) malloc( vp.rv_rect.width * vp.rv_rect.height * 3 *
sizeof(
unsigned char) );
3007 unsigned char *d = dest_data;
3009 float alpha = 1.0 - (float)transparency / 255.0;
3010 int sb = vp.rv_rect.width * vp.rv_rect.height;
3011 for(
int i = 0; i < sb; i++ ) {
3014 int r = ( ( *bg++ ) * a ) + (1.0-a) * color.Red();
3016 int g = ( ( *bg++ ) * a ) + (1.0-a) * color.Green();
3018 int b = ( ( *bg++ ) * a ) + (1.0-a) * color.Blue();
3022 dest.SetData( dest_data );
3027 ddc.SelectObject(dim);
3029 q_dc.SelectObject(*m_pBM);
3031 while (upd.HaveRects()) {
3032 wxRect rect = upd.GetRect();
3033 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &ddc, rect.x,
3038 ddc.SelectObject(wxNullBitmap);
3039 q_dc.SelectObject(wxNullBitmap);
3042 dc.SelectObject(*m_pBM);
3050 SubstituteClearDC(dc, vp);
3054 SubstituteClearDC(dc, vp);
3058 m_rendered_region = rendered_region;
3064void Quilt::SubstituteClearDC(wxMemoryDC &dc,
ViewPort &vp) {
3066 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
3067 (m_pBM->GetHeight() != vp.rv_rect.height)) {
3073 if (NULL == m_pBM) {
3074 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
3077 dc.SelectObject(wxNullBitmap);
3078 dc.SelectObject(*m_pBM);
3079 dc.SetBackground(*wxBLACK_BRUSH);
3081 m_covered_region.Clear();
3084bool Quilt::DoRenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
3086 if (!m_bcomposed)
return false;
3090 if (GetnCharts() && !m_bbusy) {
3095 ChartBase *chart = GetLargestScaleChart();
3102 Chs57->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3106 ChPI->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3111 chart = GetNextSmallerScaleChart();
3115 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.