28#include <wx/listimpl.cpp>
43#include "androidUTIL.h"
55#define GetChartTableEntry(i) GetChartTable()[i]
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)) {
363 if (pcte->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;
1573 for (
unsigned int id = 0;
id < m_extended_stack_array.size();
id++) {
1574 if (m_extended_stack_array[
id] != -1) {
1576 ChartData->GetpChartTableEntry(m_extended_stack_array[
id]);
1577 bool bsameTime =
false;
1578 if (pm->GetFileTime() && pn->GetFileTime()) {
1579 if (labs(pm->GetFileTime() - pn->GetFileTime()) < 60)
1582 if (pm->GetChartEditionDate() == pn->GetChartEditionDate())
1586 if (pn->GetpFileName()->IsSameAs(*(pm->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);
1877 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1878 if (m_pcandidate_array->GetCount()) {
1879 m_refchart_dbIndex =
1880 m_pcandidate_array->Item(m_pcandidate_array->GetCount() - 1)
1882 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex,
1889 if ((-1 != m_lost_refchart_dbIndex) &&
1890 (m_lost_refchart_dbIndex != m_refchart_dbIndex)) {
1893 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1894 if (m_lost_refchart_dbIndex == m_extended_stack_array[ir]) {
1895 m_refchart_dbIndex = m_lost_refchart_dbIndex;
1896 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1897 m_lost_refchart_dbIndex = -1;
1903 bool b_has_overlays =
false;
1906 if (CHART_FAMILY_VECTOR == m_reference_family) {
1907 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1911 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1912 b_has_overlays =
true;
1924 const LLRegion cvp_region = vp_local.GetLLRegion(vp_local.rv_rect);
1925 LLRegion vp_region = cvp_region;
1931 for (ir = 0; ir < m_pcandidate_array->GetCount();
1935 if (pqc->dbIndex == m_refchart_dbIndex) {
1944 const double z = 111274.96299695622;
1950 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1952 LLRegion vpu_region(cvp_region);
1955 LLRegion &chart_region = pqc_ref->GetReducedCandidateRegion(factor);
1957 if (cte_ref.GetChartType() != CHART_TYPE_MBTILES) {
1958 if (!chart_region.Empty()) {
1959 vpu_region.Intersect(chart_region);
1961 if (vpu_region.Empty())
1962 pqc_ref->b_include =
false;
1964 pqc_ref->b_include =
true;
1965 vp_region.Subtract(chart_region);
1968 pqc_ref->b_include =
false;
1970 pqc_ref->b_include =
false;
1975 if (!vp_region.Empty()) {
1976 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1979 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
1986 if (CHART_FAMILY_VECTOR == m_reference_family) {
1987 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1993 if (CHART_TYPE_MBTILES == cte.GetChartType()) {
1994 pqc->b_include =
false;
1998 if (cte.Scale_ge(m_reference_scale)) {
2002 bool b_in_noshow =
false;
2003 for (
unsigned int ins = 0;
2004 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2005 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2015 LLRegion vpu_region(cvp_region);
2018 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2020 if (!chart_region.Empty()) {
2021 vpu_region.Intersect(chart_region);
2023 if (vpu_region.Empty())
2024 pqc->b_include =
false;
2026 pqc->b_include =
true;
2027 vp_region.Subtract(chart_region);
2030 pqc->b_include =
false;
2032 pqc->b_include =
true;
2036 pqc->b_include =
false;
2039 if (vp_region.Empty())
2046 if (b_has_overlays && (CHART_FAMILY_VECTOR == m_reference_family)) {
2047 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2050 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
2054 if (cte.Scale_ge(m_reference_scale)) {
2055 bool b_in_noshow =
false;
2056 for (
unsigned int ins = 0;
2057 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2058 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2068 LLRegion vpu_region(cvp_region);
2071 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2073 if (!chart_region.Empty()) vpu_region.Intersect(chart_region);
2075 if (vpu_region.Empty())
2076 pqc->b_include =
false;
2079 s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2080 if (b_overlay) pqc->b_include =
true;
2087 ChartData->GetChartTableEntry(m_refchart_dbIndex);
2088 if (s57chart::IsCellOverlayType(cte_ref.GetFullSystemPath())) {
2089 pqc->b_include =
true;
2101 m_eclipsed_stack_array.clear();
2103 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2106 if (!pqc->b_include) {
2108 if (cte.Scale_ge(m_reference_scale) &&
2109 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
2110 m_eclipsed_stack_array.push_back(pqc->dbIndex);
2111 pqc->b_eclipsed =
true;
2118 if (((m_bquiltanyproj || m_quilt_proj == PROJECTION_MERCATOR)) &&
2119 !vp_region.Empty()) {
2120 bool b_must_add_cm93 =
true;
2127 while( updd .HaveRects()) {
2128 wxRect rect = updd.GetRect();
2129 if( ( rect.width > 2 ) && ( rect.height > 2 ) ) {
2130 b_must_add_cm93 =
true;
2137 if (b_must_add_cm93) {
2138 for (
int ics = 0; ics < m_parent->GetpCurrentStack()->nEntry; ics++) {
2139 int i = m_parent->GetpCurrentStack()->GetDBIndex(ics);
2140 if (CHART_TYPE_CM93COMP ==
ChartData->GetDBChartType(i)) {
2143 qcnew->SetScale(
ChartData->GetDBChartScale(i));
2145 m_pcandidate_array->Add(qcnew);
2156 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
2158 if (pqc->b_include) {
2164 if (!b_vis && m_pcandidate_array->GetCount()) {
2167 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2172 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2175 if (cte.GetChartType() == CHART_TYPE_MBTILES)
continue;
2178 LLRegion vpck_region(vp_local.GetBBox());
2181 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2183 if (!chart_region.Empty()) vpck_region.Intersect(chart_region);
2185 if (!vpck_region.Empty()) {
2187 if (cte.Scale_eq(add_scale)) {
2188 pqc->b_include =
true;
2191 pqc->b_include =
true;
2192 add_scale = cte.GetScale();
2201 m_PatchList.DeleteContents(
true);
2202 m_PatchList.Clear();
2204 if (m_pcandidate_array->GetCount()) {
2205 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2213 if (m.GetChartType() == CHART_TYPE_CM93COMP)
2214 pqc->b_include =
true;
2217 if (pqc->b_include) {
2219 pqp->dbIndex = pqc->dbIndex;
2220 pqp->ProjType = m.GetChartProjectionType();
2223 pqp->quilt_region = pqc->GetCandidateRegion();
2226 pqp->b_Valid =
true;
2228 m_PatchList.Append(pqp);
2235 if (!m_bquiltanyproj) {
2237 m_quilt_proj = PROJECTION_MERCATOR;
2238 ChartBase *ppc = GetLargestScaleChart();
2239 if (ppc) m_quilt_proj = ppc->GetChartProjectionType();
2243 if (!m_bquiltanyproj) {
2246 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2247 wxPatchListNode *pcinode = m_PatchList.Item(i);
2249 if ((piqp->ProjType != m_quilt_proj) &&
2250 (piqp->ProjType != PROJECTION_UNKNOWN))
2251 piqp->b_Valid =
false;
2256 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2257 wxPatchListNode *pcinode = m_PatchList.Item(i);
2259 for (
unsigned int ins = 0;
2260 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2261 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2264 piqp->b_Valid =
false;
2272 m_covered_region.Clear();
2277 bool b_skipCM93 =
false;
2278 if (m_reference_type == CHART_TYPE_CM93COMP) {
2280 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2281 wxPatchListNode *pcinode = m_PatchList.Item(i);
2288 if (m.GetChartType() == CHART_TYPE_CM93COMP) {
2290 piqp->ActiveRegion = piqp->quilt_region;
2291 piqp->ActiveRegion.Intersect(cvp_region);
2295 m_covered_region.Union(piqp->quilt_region);
2305 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2306 wxPatchListNode *pcinode = m_PatchList.Item(i);
2314 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2318 piqp->ActiveRegion = piqp->quilt_region;
2321 if (!b_has_overlays && m_PatchList.GetCount() < 25)
2322 piqp->ActiveRegion.Subtract(m_covered_region);
2324 piqp->ActiveRegion.Intersect(cvp_region);
2328 if (piqp->ActiveRegion.Empty() && (piqp->dbIndex != m_refchart_dbIndex))
2329 piqp->b_eclipsed =
true;
2332 piqp->b_overlay =
false;
2333 if (cte.GetChartFamily() == CHART_FAMILY_VECTOR) {
2334 piqp->b_overlay = s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2337 if (!piqp->b_overlay) m_covered_region.Union(piqp->quilt_region);
2342 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2343 wxPatchListNode *pcinode = m_PatchList.Item(i);
2352 LLRegion vpr_region = piqp->quilt_region;
2360 for (
unsigned int k = i + 1; k < m_PatchList.GetCount(); k++) {
2361 wxPatchListNode *pnode = m_PatchList.Item(k);
2382 if (!b_has_overlays) {
2383 if (!vpr_region.Empty()) {
2385 ChartData->GetChartTableEntry(pqp->dbIndex);
2386 LLRegion larger_scale_chart_region =
2389 vpr_region.Subtract(larger_scale_chart_region);
2398 wxPatchListNode *pinode = m_PatchList.Item(i);
2400 pqpi->ActiveRegion = vpr_region;
2409 if (pqpi->ActiveRegion.Empty()) pqpi->b_eclipsed =
true;
2417 m_covered_region.Union(pqpi->ActiveRegion);
2424 unsigned int il = 0;
2425 while (il < m_PatchList.GetCount()) {
2426 wxPatchListNode *pcinode = m_PatchList.Item(il);
2428 if (piqp->b_eclipsed) {
2431 bool b_noadd =
false;
2432 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size(); ir++) {
2433 if (piqp->dbIndex == m_eclipsed_stack_array[ir]) {
2438 if (!b_noadd) m_eclipsed_stack_array.push_back(piqp->dbIndex);
2440 m_PatchList.DeleteNode(pcinode);
2459 m_parent->EnablePaint(
false);
2466 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2468 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2469 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2470 ChartData->LockCacheChart(pqc->dbIndex);
2475 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2477 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2478 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2479 ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
true);
2488 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2490 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2491 if (
ChartData->IsChartLocked(pqc->dbIndex))
2492 pqc->b_locked =
true;
2494 pqc->b_locked =
ChartData->LockCacheChart(pqc->dbIndex);
2499 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2501 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2507 if (
ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
2509 pqc->b_locked =
true;
2514 m_parent->EnablePaint(
true);
2517 m_last_index_array = m_index_array;
2519 m_index_array.clear();
2522 unsigned int kl = m_PatchList.GetCount();
2523 for (
unsigned int k = 0; k < kl; k++) {
2524 wxPatchListNode *cnode = m_PatchList.Item((kl - k) - 1);
2525 m_index_array.push_back(cnode->GetData()->dbIndex);
2526 cnode = cnode->GetNext();
2532 m_quilt_depth_unit =
"";
2535 m_quilt_depth_unit = pc->GetDepthUnits();
2537 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2538 int units = ps52plib->m_nDepthUnitDisplay;
2541 m_quilt_depth_unit =
"Feet";
2544 m_quilt_depth_unit =
"Meters";
2547 m_quilt_depth_unit =
"Fathoms";
2553 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2554 wxPatchListNode *pnode = m_PatchList.Item(k);
2562 wxString du = pc->GetDepthUnits();
2563 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2564 int units = ps52plib->m_nDepthUnitDisplay;
2577 wxString dul = du.Lower();
2578 wxString ml = m_quilt_depth_unit.Lower();
2582 if (dul.StartsWith(
"meters") && ml.StartsWith(
"meters"))
2584 else if (dul.StartsWith(
"metres") && ml.StartsWith(
"metres"))
2586 else if (dul.StartsWith(
"fathoms") && ml.StartsWith(
"fathoms"))
2588 else if (dul.StartsWith(
"met") && ml.StartsWith(
"met"))
2592 m_quilt_depth_unit =
"";
2602 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2603 wxPatchListNode *pnode = m_PatchList.Item(k);
2607 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2608 wxLogMessage(
" Quilt Compose cache miss...");
2609 ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
2610 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2611 wxLogMessage(
" Oops, removing from quilt...");
2612 pqp->b_Valid =
false;
2619 if (!
ChartData->IsChartInCache(m_refchart_dbIndex))
2620 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
2626 m_bquilt_has_overlays =
false;
2627 m_max_error_factor = 0.;
2628 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2629 wxPatchListNode *pnode = m_PatchList.Item(k);
2637 m_max_error_factor =
2638 wxMax(m_max_error_factor, pc->GetChart_Error_Factor());
2639 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2640 bool isOverlay = IsChartS57Overlay(pqp->dbIndex);
2641 pqp->b_overlay = isOverlay;
2642 if (isOverlay) m_bquilt_has_overlays =
true;
2655 unsigned long xa_hash = 5381;
2656 for (
unsigned int im = 0; im < m_extended_stack_array.size(); im++) {
2657 int dbindex = m_extended_stack_array[im];
2658 xa_hash = ((xa_hash << 5) + xa_hash) + dbindex;
2661 m_xa_hash = xa_hash;
2669 if (!m_bcomposed)
return;
2673 if (GetnCharts() && !m_bbusy && !chart_region.Empty()) {
2679 if (!(chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2680 vp.b_MercatorProjectionOverride)) {
2684 chart_region, pqp->ActiveRegion, chart->GetNativeScale());
2685 if (!get_screen_region.Empty())
2686 rendered_region.Union(get_screen_region);
2689 chart = GetNextChart();
2693 m_rendered_region = rendered_region;
2698bool Quilt::RenderQuiltRegionViewOnDCNoText(wxMemoryDC &dc,
ViewPort &vp,
2700 return DoRenderQuiltRegionViewOnDC(dc, vp, chart_region);
2703bool Quilt::RenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
2705 return DoRenderQuiltRegionViewOnDCTextOnly(dc, vp, chart_region);
2708bool Quilt::DoRenderQuiltRegionViewOnDC(wxMemoryDC &dc,
ViewPort &vp,
2710#ifdef ocpnUSE_DIBSECTION
2716 if (!m_bcomposed)
return false;
2720 if (GetnCharts() && !m_bbusy) {
2728 int chartsDrawn = 0;
2730 if (!chart_region.Empty()) {
2732 bool okToRender =
true;
2734 if (chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2735 vp.b_MercatorProjectionOverride)
2739 chart = GetNextChart();
2744 bool b_chart_rendered =
false;
2745 LLRegion get_region = pqp->ActiveRegion;
2748 chart_region, get_region, chart->GetNativeScale());
2749 if (!get_screen_region.Empty()) {
2750 if (!pqp->b_overlay) {
2751 if (chart->GetChartType() == CHART_TYPE_CM93COMP) {
2753 chart->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2757 if (Chs57->m_RAZBuilt) {
2758 b_chart_rendered = Chs57->RenderRegionViewOnDCNoText(
2759 tmp_dc, vp, get_screen_region);
2765 b_chart_rendered = ChPI->RenderRegionViewOnDCNoText(
2766 tmp_dc, vp, get_screen_region);
2768 b_chart_rendered = chart->RenderRegionViewOnDC(
2769 tmp_dc, vp, get_screen_region);
2771 b_chart_rendered =
true;
2778 screen_region.Subtract(get_screen_region);
2783 while (upd.HaveRects()) {
2784 wxRect rect = upd.GetRect();
2785 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc, rect.x,
2786 rect.y, wxCOPY,
true);
2790 tmp_dc.SelectObject(wxNullBitmap);
2792 if (b_chart_rendered) rendered_region.Union(get_screen_region);
2796 chart = GetNextChart();
2800 if (!chartsDrawn) m_parent->GetVP().SetProjectionType(PROJECTION_MERCATOR);
2803 if (m_bquilt_has_overlays && !chart_region.Empty()) {
2804 chart = GetFirstChart();
2808 if (pqp->b_overlay) {
2809 LLRegion get_region = pqp->ActiveRegion;
2811 chart_region, get_region, chart->GetNativeScale());
2812 if (!get_region.Empty()) {
2815 Chs57->RenderOverlayRegionViewOnDC(tmp_dc, vp,
2821 ChPI->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2826 while (upd.HaveRects()) {
2827 wxRect rect = upd.GetRect();
2828 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc,
2829 rect.x, rect.y, wxCOPY,
true);
2832 tmp_dc.SelectObject(wxNullBitmap);
2837 chart = GetNextChart();
2844 while (clrit.HaveRects()) {
2845 wxRect rect = clrit.GetRect();
2847 dc.SetPen(*wxBLACK_PEN);
2848 dc.SetBrush(*wxBLACK_BRUSH);
2849 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
2851 dc.Blit(rect.x, rect.y, rect.width, rect.height, &dc, rect.x, rect.y,
2858 if (m_nHiLiteIndex >= 0) {
2861 wxRect box = hiregion.GetBox();
2863 if (!box.IsEmpty()) {
2866 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2867 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2874 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2878 q_dc.SelectObject(*m_pBM);
2879 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2880 q_dc.SelectObject(wxNullBitmap);
2885 wxBitmap hl_mask_bm(vp.rv_rect.width, vp.rv_rect.height, 1);
2887 mdc.SelectObject(hl_mask_bm);
2888 mdc.SetBackground(*wxBLACK_BRUSH);
2890 mdc.SetClippingRegion(box);
2891 mdc.SetBackground(*wxWHITE_BRUSH);
2893 mdc.SelectObject(wxNullBitmap);
2895 if (hl_mask_bm.IsOk()) {
2896 wxMask *phl_mask =
new wxMask(hl_mask_bm);
2897 m_pBM->SetMask(phl_mask);
2898 q_dc.SelectObject(*m_pBM);
2901 wxBitmap rbm(vp.rv_rect.width, vp.rv_rect.height);
2902 wxMask *pr_mask =
new wxMask(hl_mask_bm);
2904 rbm.SetMask(pr_mask);
2905 rdc.SelectObject(rbm);
2906 unsigned char hlcolor = 255;
2907 switch (global_color_scheme) {
2908 case GLOBAL_COLOR_SCHEME_DAY:
2911 case GLOBAL_COLOR_SCHEME_DUSK:
2914 case GLOBAL_COLOR_SCHEME_NIGHT:
2922 rdc.SetBackground(wxBrush(wxColour(hlcolor, 0, 0)));
2926 while (upd.HaveRects()) {
2927 wxRect rect = upd.GetRect();
2928 rdc.Blit(rect.x, rect.y, rect.width, rect.height, &q_dc, rect.x,
2929 rect.y, wxOR,
true);
2934 while (updq.HaveRects()) {
2935 wxRect rect = updq.GetRect();
2936 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &rdc, rect.x,
2937 rect.y, wxCOPY,
true);
2941 q_dc.SelectObject(wxNullBitmap);
2942 m_pBM->SetMask(NULL);
2945 dc.SelectObject(*m_pBM);
2948 rdc.SelectObject(wxNullBitmap);
2954 if (g_fog_overzoom) {
2957 if (scale_factor > g_overzoom_emphasis_base) {
2958 float fog = ((scale_factor - g_overzoom_emphasis_base) * 255.) / 20.;
2959 fog = wxMin(fog, 200.);
2963 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2964 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2971 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2975 q_dc.SelectObject(*m_pBM);
2976 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2977 q_dc.SelectObject(wxNullBitmap);
2979 wxImage src = m_pBM->ConvertToImage();
2982 wxMin((scale_factor - g_overzoom_emphasis_base) / 4, 4);
2984 wxImage dest = src.Blur(blur_factor);
2988 unsigned char *bg = src.GetData();
2989 wxColour color = m_parent->GetFogColor();
2991 float transparency = fog;
2994 wxImage dest(vp.rv_rect.width, vp.rv_rect.height);
2995 unsigned char *dest_data = (
unsigned char *) malloc( vp.rv_rect.width * vp.rv_rect.height * 3 *
sizeof(
unsigned char) );
2996 unsigned char *d = dest_data;
2998 float alpha = 1.0 - (float)transparency / 255.0;
2999 int sb = vp.rv_rect.width * vp.rv_rect.height;
3000 for(
int i = 0; i < sb; i++ ) {
3003 int r = ( ( *bg++ ) * a ) + (1.0-a) * color.Red();
3005 int g = ( ( *bg++ ) * a ) + (1.0-a) * color.Green();
3007 int b = ( ( *bg++ ) * a ) + (1.0-a) * color.Blue();
3011 dest.SetData( dest_data );
3016 ddc.SelectObject(dim);
3018 q_dc.SelectObject(*m_pBM);
3020 while (upd.HaveRects()) {
3021 wxRect rect = upd.GetRect();
3022 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &ddc, rect.x,
3027 ddc.SelectObject(wxNullBitmap);
3028 q_dc.SelectObject(wxNullBitmap);
3031 dc.SelectObject(*m_pBM);
3039 SubstituteClearDC(dc, vp);
3043 SubstituteClearDC(dc, vp);
3047 m_rendered_region = rendered_region;
3053void Quilt::SubstituteClearDC(wxMemoryDC &dc,
ViewPort &vp) {
3055 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
3056 (m_pBM->GetHeight() != vp.rv_rect.height)) {
3062 if (NULL == m_pBM) {
3063 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
3066 dc.SelectObject(wxNullBitmap);
3067 dc.SelectObject(*m_pBM);
3068 dc.SetBackground(*wxBLACK_BRUSH);
3070 m_covered_region.Clear();
3073bool Quilt::DoRenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
3075 if (!m_bcomposed)
return false;
3079 if (GetnCharts() && !m_bbusy) {
3084 ChartBase *chart = GetLargestScaleChart();
3091 Chs57->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3095 ChPI->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3100 chart = GetNextSmallerScaleChart();
3104 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.