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(),
1642int Quilt::AdjustRefSelection(
const ViewPort &vp_in) {
1657 vp_local.SetRotationAngle(0.);
1659 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1661 ChartFamilyEnum family = CHART_FAMILY_RASTER;
1662 ChartTypeEnum type = CHART_TYPE_KAP;
1665 if (m_refchart_dbIndex >= 0) {
1667 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1668 type = (ChartTypeEnum)cte_ref.GetChartType();
1669 family = (ChartFamilyEnum)cte_ref.GetChartFamily();
1672 int ret_index = AdjustRefOnZoom(
true, family, type, vp_in.
chart_scale);
1677double Quilt::GetBestStartScale(
int dbi_ref_hint,
const ViewPort &vp_in) {
1687 int tentative_ref_index = dbi_ref_hint;
1688 if (dbi_ref_hint < 0) {
1695 tentative_ref_index = m_parent->GetpCurrentStack()->GetDBIndex(0);
1702 vp_local.SetRotationAngle(0.);
1704 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1708 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1710 if (qc->dbIndex == tentative_ref_index) {
1716 if (!bf && m_pcandidate_array->GetCount()) {
1717 tentative_ref_index = GetNewRefChart();
1718 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1721 double proposed_scale_onscreen = vp_in.
chart_scale;
1723 if (m_pcandidate_array->GetCount()) {
1724 SetReferenceChart(tentative_ref_index);
1728 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1730 if (IsChartQuiltableRef(qc->dbIndex)) {
1731 SetReferenceChart(qc->dbIndex);
1738 SetReferenceChart(m_parent->GetpCurrentStack()->GetDBIndex(0));
1741 if (m_refchart_dbIndex >= 0) {
1746 double min_ref_scale =
1748 double max_ref_scale = pc->GetNormalScaleMax(
1750 if ((proposed_scale_onscreen >= min_ref_scale) &&
1751 (proposed_scale_onscreen <= max_ref_scale))
1754 proposed_scale_onscreen = wxMin(proposed_scale_onscreen, max_ref_scale);
1755 proposed_scale_onscreen = wxMax(proposed_scale_onscreen, min_ref_scale);
1763 if (m_refchart_dbIndex >= 0 &&
ChartData)
1764 return ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
1768void Quilt::UnlockQuilt() {
1769 wxASSERT(m_bbusy ==
false);
1773 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1785 if (!m_parent->GetpCurrentStack())
return false;
1787 if (m_bbusy)
return false;
1796 if (m_refchart_dbIndex >= 0) {
1798 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1799 m_reference_scale = cte_ref.GetScale();
1800 m_reference_type = cte_ref.GetChartType();
1801 if (!m_bquiltanyproj)
1802 m_quilt_proj =
ChartData->GetDBChartProj(m_refchart_dbIndex);
1803 m_reference_family = cte_ref.GetChartFamily();
1807 if (!m_bquiltanyproj) vp_local.SetProjectionType(m_quilt_proj);
1814 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1854 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1856 if (qc->dbIndex == m_refchart_dbIndex) {
1865 if (m_chart_familyFix == CHART_FAMILY_UNKNOWN) {
1866 if (!bf && m_pcandidate_array->GetCount() &&
1867 (m_reference_type != CHART_TYPE_CM93COMP)) {
1868 m_lost_refchart_dbIndex = m_refchart_dbIndex;
1869 int candidate_ref_index = GetNewRefChart();
1870 if (m_refchart_dbIndex != candidate_ref_index) {
1871 m_refchart_dbIndex = candidate_ref_index;
1872 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1879 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1880 if (m_pcandidate_array->GetCount()) {
1881 int alternate_index =
1882 m_pcandidate_array->Item(m_pcandidate_array->GetCount() - 1)
1885 ChartData->GetChartTableEntry(alternate_index);
1887 if (GetRefFamily() == cte_alt.GetChartFamily()) {
1888 m_refchart_dbIndex = alternate_index;
1889 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex,
1897 if ((-1 != m_lost_refchart_dbIndex) &&
1898 (m_lost_refchart_dbIndex != m_refchart_dbIndex)) {
1901 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1902 if (m_lost_refchart_dbIndex == m_extended_stack_array[ir]) {
1903 m_refchart_dbIndex = m_lost_refchart_dbIndex;
1904 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1905 m_lost_refchart_dbIndex = -1;
1911 bool b_has_overlays =
false;
1914 if (CHART_FAMILY_VECTOR == m_reference_family) {
1915 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1919 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1920 b_has_overlays =
true;
1932 const LLRegion cvp_region = vp_local.GetLLRegion(vp_local.rv_rect);
1933 LLRegion vp_region = cvp_region;
1939 for (ir = 0; ir < m_pcandidate_array->GetCount();
1943 if (pqc->dbIndex == m_refchart_dbIndex) {
1952 const double z = 111274.96299695622;
1958 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1960 LLRegion vpu_region(cvp_region);
1963 LLRegion &chart_region = pqc_ref->GetReducedCandidateRegion(factor);
1965 if (cte_ref.GetChartType() != CHART_TYPE_MBTILES) {
1966 if (!chart_region.Empty()) {
1967 vpu_region.Intersect(chart_region);
1969 if (vpu_region.Empty())
1970 pqc_ref->b_include =
false;
1972 pqc_ref->b_include =
true;
1973 vp_region.Subtract(chart_region);
1976 pqc_ref->b_include =
false;
1978 pqc_ref->b_include =
false;
1983 if (!vp_region.Empty()) {
1984 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1987 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
1994 if (CHART_FAMILY_VECTOR == m_reference_family) {
1995 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
2001 if (CHART_TYPE_MBTILES == cte.GetChartType()) {
2002 pqc->b_include =
false;
2006 if (cte.Scale_ge(m_reference_scale)) {
2010 bool b_in_noshow =
false;
2011 for (
unsigned int ins = 0;
2012 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2013 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2023 LLRegion vpu_region(cvp_region);
2026 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2028 if (!chart_region.Empty()) {
2029 vpu_region.Intersect(chart_region);
2031 if (vpu_region.Empty())
2032 pqc->b_include =
false;
2034 pqc->b_include =
true;
2035 vp_region.Subtract(chart_region);
2038 pqc->b_include =
false;
2040 pqc->b_include =
true;
2044 pqc->b_include =
false;
2047 if (vp_region.Empty())
2054 if (b_has_overlays && (CHART_FAMILY_VECTOR == m_reference_family)) {
2055 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2058 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
2062 if (cte.Scale_ge(m_reference_scale)) {
2063 bool b_in_noshow =
false;
2064 for (
unsigned int ins = 0;
2065 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2066 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2076 LLRegion vpu_region(cvp_region);
2079 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2081 if (!chart_region.Empty()) vpu_region.Intersect(chart_region);
2083 if (vpu_region.Empty())
2084 pqc->b_include =
false;
2087 s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2088 if (b_overlay) pqc->b_include =
true;
2095 ChartData->GetChartTableEntry(m_refchart_dbIndex);
2096 if (s57chart::IsCellOverlayType(cte_ref.GetFullSystemPath())) {
2097 pqc->b_include =
true;
2109 m_eclipsed_stack_array.clear();
2111 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2114 if (!pqc->b_include) {
2116 if (cte.Scale_ge(m_reference_scale) &&
2117 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
2118 m_eclipsed_stack_array.push_back(pqc->dbIndex);
2119 pqc->b_eclipsed =
true;
2126 if (((m_bquiltanyproj || m_quilt_proj == PROJECTION_MERCATOR)) &&
2127 !vp_region.Empty()) {
2128 bool b_must_add_cm93 =
true;
2135 while( updd .HaveRects()) {
2136 wxRect rect = updd.GetRect();
2137 if( ( rect.width > 2 ) && ( rect.height > 2 ) ) {
2138 b_must_add_cm93 =
true;
2145 if (b_must_add_cm93) {
2146 for (
int ics = 0; ics < m_parent->GetpCurrentStack()->nEntry; ics++) {
2147 int i = m_parent->GetpCurrentStack()->GetDBIndex(ics);
2148 if (CHART_TYPE_CM93COMP ==
ChartData->GetDBChartType(i)) {
2151 qcnew->SetScale(
ChartData->GetDBChartScale(i));
2153 m_pcandidate_array->Add(qcnew);
2164 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
2166 if (pqc->b_include) {
2172 if (!b_vis && m_pcandidate_array->GetCount()) {
2175 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2180 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2183 if (cte.GetChartType() == CHART_TYPE_MBTILES)
continue;
2186 LLRegion vpck_region(vp_local.GetBBox());
2189 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2191 if (!chart_region.Empty()) vpck_region.Intersect(chart_region);
2193 if (!vpck_region.Empty()) {
2195 if (cte.Scale_eq(add_scale)) {
2196 pqc->b_include =
true;
2199 pqc->b_include =
true;
2200 add_scale = cte.GetScale();
2209 m_PatchList.DeleteContents(
true);
2210 m_PatchList.Clear();
2212 if (m_pcandidate_array->GetCount()) {
2213 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2221 if (m.GetChartType() == CHART_TYPE_CM93COMP)
2222 pqc->b_include =
true;
2225 if (pqc->b_include) {
2227 pqp->dbIndex = pqc->dbIndex;
2228 pqp->ProjType = m.GetChartProjectionType();
2231 pqp->quilt_region = pqc->GetCandidateRegion();
2234 pqp->b_Valid =
true;
2236 m_PatchList.Append(pqp);
2243 if (!m_bquiltanyproj) {
2245 m_quilt_proj = PROJECTION_MERCATOR;
2246 ChartBase *ppc = GetLargestScaleChart();
2247 if (ppc) m_quilt_proj = ppc->GetChartProjectionType();
2251 if (!m_bquiltanyproj) {
2254 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2255 wxPatchListNode *pcinode = m_PatchList.Item(i);
2257 if ((piqp->ProjType != m_quilt_proj) &&
2258 (piqp->ProjType != PROJECTION_UNKNOWN))
2259 piqp->b_Valid =
false;
2264 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2265 wxPatchListNode *pcinode = m_PatchList.Item(i);
2267 for (
unsigned int ins = 0;
2268 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2269 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2272 piqp->b_Valid =
false;
2280 m_covered_region.Clear();
2285 bool b_skipCM93 =
false;
2286 if (m_reference_type == CHART_TYPE_CM93COMP) {
2288 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2289 wxPatchListNode *pcinode = m_PatchList.Item(i);
2296 if (m.GetChartType() == CHART_TYPE_CM93COMP) {
2298 piqp->ActiveRegion = piqp->quilt_region;
2299 piqp->ActiveRegion.Intersect(cvp_region);
2303 m_covered_region.Union(piqp->quilt_region);
2313 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2314 wxPatchListNode *pcinode = m_PatchList.Item(i);
2322 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2326 piqp->ActiveRegion = piqp->quilt_region;
2329 if (!b_has_overlays && m_PatchList.GetCount() < 25)
2330 piqp->ActiveRegion.Subtract(m_covered_region);
2332 piqp->ActiveRegion.Intersect(cvp_region);
2336 if (piqp->ActiveRegion.Empty() && (piqp->dbIndex != m_refchart_dbIndex))
2337 piqp->b_eclipsed =
true;
2340 piqp->b_overlay =
false;
2341 if (cte.GetChartFamily() == CHART_FAMILY_VECTOR) {
2342 piqp->b_overlay = s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2345 if (!piqp->b_overlay) m_covered_region.Union(piqp->quilt_region);
2350 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2351 wxPatchListNode *pcinode = m_PatchList.Item(i);
2360 LLRegion vpr_region = piqp->quilt_region;
2368 for (
unsigned int k = i + 1; k < m_PatchList.GetCount(); k++) {
2369 wxPatchListNode *pnode = m_PatchList.Item(k);
2390 if (!b_has_overlays) {
2391 if (!vpr_region.Empty()) {
2393 ChartData->GetChartTableEntry(pqp->dbIndex);
2394 LLRegion larger_scale_chart_region =
2397 vpr_region.Subtract(larger_scale_chart_region);
2406 wxPatchListNode *pinode = m_PatchList.Item(i);
2408 pqpi->ActiveRegion = vpr_region;
2417 if (pqpi->ActiveRegion.Empty()) pqpi->b_eclipsed =
true;
2425 m_covered_region.Union(pqpi->ActiveRegion);
2432 unsigned int il = 0;
2433 while (il < m_PatchList.GetCount()) {
2434 wxPatchListNode *pcinode = m_PatchList.Item(il);
2436 if (piqp->b_eclipsed) {
2439 bool b_noadd =
false;
2440 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size(); ir++) {
2441 if (piqp->dbIndex == m_eclipsed_stack_array[ir]) {
2446 if (!b_noadd) m_eclipsed_stack_array.push_back(piqp->dbIndex);
2448 m_PatchList.DeleteNode(pcinode);
2467 m_parent->EnablePaint(
false);
2474 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2476 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2477 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2478 ChartData->LockCacheChart(pqc->dbIndex);
2483 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2485 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2486 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2487 ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
true);
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 pqc->b_locked =
true;
2502 pqc->b_locked =
ChartData->LockCacheChart(pqc->dbIndex);
2507 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2509 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2515 if (
ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
2517 pqc->b_locked =
true;
2522 m_parent->EnablePaint(
true);
2525 m_last_index_array = m_index_array;
2527 m_index_array.clear();
2530 unsigned int kl = m_PatchList.GetCount();
2531 for (
unsigned int k = 0; k < kl; k++) {
2532 wxPatchListNode *cnode = m_PatchList.Item((kl - k) - 1);
2533 m_index_array.push_back(cnode->GetData()->dbIndex);
2534 cnode = cnode->GetNext();
2540 m_quilt_depth_unit =
"";
2543 m_quilt_depth_unit = pc->GetDepthUnits();
2545 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2546 int units = ps52plib->m_nDepthUnitDisplay;
2549 m_quilt_depth_unit =
"Feet";
2552 m_quilt_depth_unit =
"Meters";
2555 m_quilt_depth_unit =
"Fathoms";
2561 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2562 wxPatchListNode *pnode = m_PatchList.Item(k);
2570 wxString du = pc->GetDepthUnits();
2571 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2572 int units = ps52plib->m_nDepthUnitDisplay;
2585 wxString dul = du.Lower();
2586 wxString ml = m_quilt_depth_unit.Lower();
2590 if (dul.StartsWith(
"meters") && ml.StartsWith(
"meters"))
2592 else if (dul.StartsWith(
"metres") && ml.StartsWith(
"metres"))
2594 else if (dul.StartsWith(
"fathoms") && ml.StartsWith(
"fathoms"))
2596 else if (dul.StartsWith(
"met") && ml.StartsWith(
"met"))
2600 m_quilt_depth_unit =
"";
2610 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2611 wxPatchListNode *pnode = m_PatchList.Item(k);
2615 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2616 wxLogMessage(
" Quilt Compose cache miss...");
2617 ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
2618 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2619 wxLogMessage(
" Oops, removing from quilt...");
2620 pqp->b_Valid =
false;
2627 if (!
ChartData->IsChartInCache(m_refchart_dbIndex))
2628 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
2634 m_bquilt_has_overlays =
false;
2635 m_max_error_factor = 0.;
2636 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2637 wxPatchListNode *pnode = m_PatchList.Item(k);
2645 m_max_error_factor =
2646 wxMax(m_max_error_factor, pc->GetChart_Error_Factor());
2647 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2648 bool isOverlay = IsChartS57Overlay(pqp->dbIndex);
2649 pqp->b_overlay = isOverlay;
2650 if (isOverlay) m_bquilt_has_overlays =
true;
2663 unsigned long xa_hash = 5381;
2664 for (
unsigned int im = 0; im < m_extended_stack_array.size(); im++) {
2665 int dbindex = m_extended_stack_array[im];
2666 xa_hash = ((xa_hash << 5) + xa_hash) + dbindex;
2669 m_xa_hash = xa_hash;
2677 if (!m_bcomposed)
return;
2681 if (GetnCharts() && !m_bbusy && !chart_region.Empty()) {
2687 if (!(chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2688 vp.b_MercatorProjectionOverride)) {
2692 chart_region, pqp->ActiveRegion, chart->GetNativeScale());
2693 if (!get_screen_region.Empty())
2694 rendered_region.Union(get_screen_region);
2697 chart = GetNextChart();
2701 m_rendered_region = rendered_region;
2706bool Quilt::RenderQuiltRegionViewOnDCNoText(wxMemoryDC &dc,
ViewPort &vp,
2708 return DoRenderQuiltRegionViewOnDC(dc, vp, chart_region);
2711bool Quilt::RenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
2713 return DoRenderQuiltRegionViewOnDCTextOnly(dc, vp, chart_region);
2716bool Quilt::DoRenderQuiltRegionViewOnDC(wxMemoryDC &dc,
ViewPort &vp,
2718#ifdef ocpnUSE_DIBSECTION
2724 if (!m_bcomposed)
return false;
2728 if (GetnCharts() && !m_bbusy) {
2736 int chartsDrawn = 0;
2738 if (!chart_region.Empty()) {
2740 bool okToRender =
true;
2742 if (chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2743 vp.b_MercatorProjectionOverride)
2747 chart = GetNextChart();
2752 bool b_chart_rendered =
false;
2753 LLRegion get_region = pqp->ActiveRegion;
2756 chart_region, get_region, chart->GetNativeScale());
2757 if (!get_screen_region.Empty()) {
2758 if (!pqp->b_overlay) {
2759 if (chart->GetChartType() == CHART_TYPE_CM93COMP) {
2761 chart->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2765 if (Chs57->m_RAZBuilt) {
2766 b_chart_rendered = Chs57->RenderRegionViewOnDCNoText(
2767 tmp_dc, vp, get_screen_region);
2773 b_chart_rendered = ChPI->RenderRegionViewOnDCNoText(
2774 tmp_dc, vp, get_screen_region);
2776 b_chart_rendered = chart->RenderRegionViewOnDC(
2777 tmp_dc, vp, get_screen_region);
2779 b_chart_rendered =
true;
2786 screen_region.Subtract(get_screen_region);
2791 while (upd.HaveRects()) {
2792 wxRect rect = upd.GetRect();
2793 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc, rect.x,
2794 rect.y, wxCOPY,
true);
2798 tmp_dc.SelectObject(wxNullBitmap);
2800 if (b_chart_rendered) rendered_region.Union(get_screen_region);
2804 chart = GetNextChart();
2808 if (!chartsDrawn) m_parent->GetVP().SetProjectionType(PROJECTION_MERCATOR);
2811 if (m_bquilt_has_overlays && !chart_region.Empty()) {
2812 chart = GetFirstChart();
2816 if (pqp->b_overlay) {
2817 LLRegion get_region = pqp->ActiveRegion;
2819 chart_region, get_region, chart->GetNativeScale());
2820 if (!get_region.Empty()) {
2823 Chs57->RenderOverlayRegionViewOnDC(tmp_dc, vp,
2829 ChPI->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2834 while (upd.HaveRects()) {
2835 wxRect rect = upd.GetRect();
2836 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc,
2837 rect.x, rect.y, wxCOPY,
true);
2840 tmp_dc.SelectObject(wxNullBitmap);
2845 chart = GetNextChart();
2852 while (clrit.HaveRects()) {
2853 wxRect rect = clrit.GetRect();
2855 dc.SetPen(*wxBLACK_PEN);
2856 dc.SetBrush(*wxBLACK_BRUSH);
2857 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
2859 dc.Blit(rect.x, rect.y, rect.width, rect.height, &dc, rect.x, rect.y,
2866 if (m_nHiLiteIndex >= 0) {
2869 wxRect box = hiregion.GetBox();
2871 if (!box.IsEmpty()) {
2874 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2875 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2882 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2886 q_dc.SelectObject(*m_pBM);
2887 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2888 q_dc.SelectObject(wxNullBitmap);
2893 wxBitmap hl_mask_bm(vp.rv_rect.width, vp.rv_rect.height, 1);
2895 mdc.SelectObject(hl_mask_bm);
2896 mdc.SetBackground(*wxBLACK_BRUSH);
2898 mdc.SetClippingRegion(box);
2899 mdc.SetBackground(*wxWHITE_BRUSH);
2901 mdc.SelectObject(wxNullBitmap);
2903 if (hl_mask_bm.IsOk()) {
2904 wxMask *phl_mask =
new wxMask(hl_mask_bm);
2905 m_pBM->SetMask(phl_mask);
2906 q_dc.SelectObject(*m_pBM);
2909 wxBitmap rbm(vp.rv_rect.width, vp.rv_rect.height);
2910 wxMask *pr_mask =
new wxMask(hl_mask_bm);
2912 rbm.SetMask(pr_mask);
2913 rdc.SelectObject(rbm);
2914 unsigned char hlcolor = 255;
2915 switch (global_color_scheme) {
2916 case GLOBAL_COLOR_SCHEME_DAY:
2919 case GLOBAL_COLOR_SCHEME_DUSK:
2922 case GLOBAL_COLOR_SCHEME_NIGHT:
2930 rdc.SetBackground(wxBrush(wxColour(hlcolor, 0, 0)));
2934 while (upd.HaveRects()) {
2935 wxRect rect = upd.GetRect();
2936 rdc.Blit(rect.x, rect.y, rect.width, rect.height, &q_dc, rect.x,
2937 rect.y, wxOR,
true);
2942 while (updq.HaveRects()) {
2943 wxRect rect = updq.GetRect();
2944 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &rdc, rect.x,
2945 rect.y, wxCOPY,
true);
2949 q_dc.SelectObject(wxNullBitmap);
2950 m_pBM->SetMask(NULL);
2953 dc.SelectObject(*m_pBM);
2956 rdc.SelectObject(wxNullBitmap);
2962 if (g_fog_overzoom) {
2965 if (scale_factor > g_overzoom_emphasis_base) {
2966 float fog = ((scale_factor - g_overzoom_emphasis_base) * 255.) / 20.;
2967 fog = wxMin(fog, 200.);
2971 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2972 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2979 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2983 q_dc.SelectObject(*m_pBM);
2984 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2985 q_dc.SelectObject(wxNullBitmap);
2987 wxImage src = m_pBM->ConvertToImage();
2990 wxMin((scale_factor - g_overzoom_emphasis_base) / 4, 4);
2992 wxImage dest = src.Blur(blur_factor);
2996 unsigned char *bg = src.GetData();
2997 wxColour color = m_parent->GetFogColor();
2999 float transparency = fog;
3002 wxImage dest(vp.rv_rect.width, vp.rv_rect.height);
3003 unsigned char *dest_data = (
unsigned char *) malloc( vp.rv_rect.width * vp.rv_rect.height * 3 *
sizeof(
unsigned char) );
3004 unsigned char *d = dest_data;
3006 float alpha = 1.0 - (float)transparency / 255.0;
3007 int sb = vp.rv_rect.width * vp.rv_rect.height;
3008 for(
int i = 0; i < sb; i++ ) {
3011 int r = ( ( *bg++ ) * a ) + (1.0-a) * color.Red();
3013 int g = ( ( *bg++ ) * a ) + (1.0-a) * color.Green();
3015 int b = ( ( *bg++ ) * a ) + (1.0-a) * color.Blue();
3019 dest.SetData( dest_data );
3024 ddc.SelectObject(dim);
3026 q_dc.SelectObject(*m_pBM);
3028 while (upd.HaveRects()) {
3029 wxRect rect = upd.GetRect();
3030 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &ddc, rect.x,
3035 ddc.SelectObject(wxNullBitmap);
3036 q_dc.SelectObject(wxNullBitmap);
3039 dc.SelectObject(*m_pBM);
3047 SubstituteClearDC(dc, vp);
3051 SubstituteClearDC(dc, vp);
3055 m_rendered_region = rendered_region;
3061void Quilt::SubstituteClearDC(wxMemoryDC &dc,
ViewPort &vp) {
3063 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
3064 (m_pBM->GetHeight() != vp.rv_rect.height)) {
3070 if (NULL == m_pBM) {
3071 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
3074 dc.SelectObject(wxNullBitmap);
3075 dc.SelectObject(*m_pBM);
3076 dc.SetBackground(*wxBLACK_BRUSH);
3078 m_covered_region.Clear();
3081bool Quilt::DoRenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
3083 if (!m_bcomposed)
return false;
3087 if (GetnCharts() && !m_bbusy) {
3092 ChartBase *chart = GetLargestScaleChart();
3099 Chs57->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3103 ChPI->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3108 chart = GetNextSmallerScaleChart();
3112 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.