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;
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) {
276 m_refchart_dbIndex = dbIndex;
282bool Quilt::IsVPBlittable(
ViewPort &VPoint,
int dx,
int dy,
283 bool b_allow_vector) {
284 if (!m_vp_rendered.IsValid())
return false;
289 double deltax = p2.m_x - p1.m_x;
290 double deltay = p2.m_y - p1.m_y;
292 if ((fabs(deltax - dx) > 1e-2) || (fabs(deltay - dy) > 1e-2))
return false;
297bool Quilt::IsChartS57Overlay(
int db_index) {
298 if (db_index < 0)
return false;
301 if (CHART_FAMILY_VECTOR == cte.GetChartFamily()) {
302 return s57chart::IsCellOverlayType(cte.GetFullSystemPath());
307bool Quilt::IsChartQuiltableRef(
int db_index) {
308 if (db_index < 0 || db_index >
ChartData->GetChartTableEntries() - 1)
314 bool bproj_match =
true;
316 double skew_norm = ctei.GetChartSkew();
317 if (skew_norm > 180.) skew_norm -= 360.;
320 fabs(skew_norm) < 1.;
321 if (m_bquiltskew) skew_match =
true;
324 bool b_noshow =
false;
325 for (
unsigned int i = 0; i < m_parent->GetQuiltNoshowIindexArray().size();
327 if (m_parent->GetQuiltNoshowIindexArray()[i] ==
335 return (bproj_match & skew_match & !b_noshow);
338bool Quilt::IsChartInQuilt(
ChartBase *pc) {
340 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
342 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
343 if (
ChartData->OpenChartFromDB(pqc->dbIndex, FULL_INIT) == pc)
350bool Quilt::IsChartInQuilt(wxString &full_path) {
352 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
354 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
356 if (pcte->GetpsFullPath()->IsSameAs(full_path))
return true;
362std::vector<int> Quilt::GetCandidatedbIndexArray(
bool from_ref_chart,
363 bool exclude_user_hidden) {
364 std::vector<int> ret;
365 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
369 if (pqc->Scale_ge(m_reference_scale)) {
371 if (exclude_user_hidden) {
372 bool b_noshow =
false;
373 for (
unsigned int i = 0;
374 i < m_parent->GetQuiltNoshowIindexArray().size(); i++) {
375 if (m_parent->GetQuiltNoshowIindexArray()[i] ==
382 if (!b_noshow) ret.push_back(pqc->dbIndex);
384 ret.push_back(pqc->dbIndex);
388 ret.push_back(pqc->dbIndex);
395 return (cnode->GetData());
400void Quilt::EmptyCandidateArray() {
401 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
402 delete m_pcandidate_array->Item(i);
405 m_pcandidate_array->Clear();
415 if (!m_bcomposed)
return NULL;
417 if (m_bbusy)
return NULL;
421 cnode = m_PatchList.GetFirst();
422 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetNext();
423 if (cnode && cnode->GetData()->b_Valid)
424 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
435 if (m_bbusy)
return NULL;
440 cnode = cnode->GetNext();
441 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetNext();
442 if (cnode && cnode->GetData()->b_Valid)
443 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
450ChartBase *Quilt::GetNextSmallerScaleChart() {
455 if (m_bbusy)
return NULL;
460 cnode = cnode->GetPrevious();
461 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetPrevious();
462 if (cnode && cnode->GetData()->b_Valid)
463 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
470ChartBase *Quilt::GetLargestScaleChart() {
473 if (m_bbusy)
return NULL;
477 cnode = m_PatchList.GetLast();
479 pret =
ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
486 LLRegion chart_region;
487 LLRegion screen_region(vp.GetBBox());
492 if (fabs(cte.GetLonMax() - cte.GetLonMin()) > 180.) {
509 return LLRegion(-80, vp.GetBBox().GetMinLon(), 80,
510 vp.GetBBox().GetMaxLon());
514 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
515 bool aux_ply_skipped =
false;
516 if (nAuxPlyEntries >= 1) {
517 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
518 int nAuxPly = cte.GetAuxCntTableEntry(ip);
519 if (nAuxPly > AUX_PLY_PERF_LIMIT) {
522 aux_ply_skipped =
true;
525 float *pfp = cte.GetpAuxPlyTableEntry(ip);
526 LLRegion t_region(nAuxPly, pfp);
527 t_region.Intersect(screen_region);
531 if (!t_region.Empty()) chart_region.Union(t_region);
535 if (aux_ply_skipped || nAuxPlyEntries == 0) {
536 int n_ply_entries = cte.GetnPlyEntries();
537 float *pfp = cte.GetpPlyTable();
539 if (n_ply_entries >= 3)
542 LLRegion t_region(n_ply_entries, pfp);
543 t_region.Intersect(screen_region);
547 if (!t_region.Empty()) chart_region.Union(t_region);
550 chart_region = screen_region;
554 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
555 if (nNoCovrPlyEntries) {
556 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
557 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
558 if (nNoCovrPly > NOCOVR_PLY_PERF_LIMIT) {
563 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
565 LLRegion t_region(nNoCovrPly, pfp);
566 t_region.Intersect(screen_region);
577 if (!t_region.Empty()) {
578 LLRegion test_region = chart_region;
579 test_region.Subtract(t_region);
581 if (!test_region.Empty()) chart_region = test_region;
590 if ((cte.GetScale() > 90000000) &&
591 (cte.GetChartFamily() == CHART_FAMILY_RASTER))
592 chart_region = screen_region;
600bool Quilt::IsQuiltVector() {
601 if (m_bbusy)
return false;
607 wxPatchListNode *cnode = m_PatchList.GetFirst();
609 if (cnode->GetData()) {
612 if ((pqp->b_Valid) && (!pqp->b_eclipsed) &&
613 (pqp->dbIndex <
ChartData->GetChartTableEntries())) {
615 ChartData->GetChartTableEntry(pqp->dbIndex);
617 if (ctei.GetChartFamily() == CHART_FAMILY_VECTOR) {
623 cnode = cnode->GetNext();
630bool Quilt::DoesQuiltContainPlugins() {
631 if (m_bbusy)
return false;
637 wxPatchListNode *cnode = m_PatchList.GetFirst();
639 if (cnode->GetData()) {
642 if ((pqp->b_Valid) && (!pqp->b_eclipsed)) {
644 ChartData->GetChartTableEntry(pqp->dbIndex);
646 if (ctei.GetChartType() == CHART_TYPE_PLUGIN) {
652 cnode = cnode->GetNext();
659int Quilt::GetChartdbIndexAtPix(
ViewPort &VPoint, wxPoint p) {
660 if (m_bbusy)
return -1;
669 wxPatchListNode *cnode = m_PatchList.GetFirst();
671 if (cnode->GetData()->ActiveRegion.Contains(lat, lon)) {
672 ret = cnode->GetData()->dbIndex;
675 cnode = cnode->GetNext();
683 if (m_bbusy)
return NULL;
695 wxPatchListNode *cnode = m_PatchList.GetFirst();
698 if (!pqp->b_overlay && (pqp->ActiveRegion.Contains(lat, lon)))
699 if (
ChartData->IsChartInCache(pqp->dbIndex)) {
700 pret =
ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
702 cnode = cnode->GetNext();
710 if (m_bbusy)
return NULL;
722 wxPatchListNode *cnode = m_PatchList.GetFirst();
725 if (pqp->b_overlay && (pqp->ActiveRegion.Contains(lat, lon)))
726 pret =
ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
727 cnode = cnode->GetNext();
734void Quilt::InvalidateAllQuiltPatchs() {
745std::vector<int> Quilt::GetQuiltIndexArray() {
746 return m_index_array;
748 std::vector<int> ret;
750 if (m_bbusy)
return ret;
754 wxPatchListNode *cnode = m_PatchList.GetFirst();
756 ret.push_back(cnode->GetData()->dbIndex);
757 cnode = cnode->GetNext();
765bool Quilt::IsQuiltDelta(
ViewPort &vp) {
766 if (!m_vp_quilt.IsValid() || !m_bcomposed)
return true;
770 if (m_vp_quilt.m_projection_type != vp.m_projection_type)
return true;
775 wxPoint cp_last, cp_this;
780 return (cp_last != cp_this);
788 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
790 if (pRefChart) pRefChart->AdjustVP(vp_last, vp_proposed);
793double Quilt::GetRefNativeScale() {
794 double ret_val = 1.0;
797 if (pc) ret_val = pc->GetNativeScale();
803int Quilt::GetNewRefChart() {
809 int new_ref_dbIndex = m_refchart_dbIndex;
810 unsigned int im = m_extended_stack_array.size();
812 for (
unsigned int is = 0; is < im; is++) {
814 ChartData->GetChartTableEntry(m_extended_stack_array[is]);
816 double skew_norm = m.GetChartSkew();
817 if (skew_norm > 180.) skew_norm -= 360.;
819 if ((m.Scale_ge(m_reference_scale)) &&
820 (m_reference_family == m.GetChartFamily()) &&
821 (m_bquiltanyproj || m_quilt_proj == m.GetChartProjectionType()) &&
822 (m_bquiltskew || (fabs(skew_norm) < 1.0))) {
823 new_ref_dbIndex = m_extended_stack_array[is];
828 return new_ref_dbIndex;
831int Quilt::GetNomScaleMax(
int scale, ChartTypeEnum type,
832 ChartFamilyEnum family) {
834 case CHART_FAMILY_RASTER: {
838 case CHART_FAMILY_VECTOR: {
848int Quilt::GetNomScaleMin(
int scale, ChartTypeEnum type,
849 ChartFamilyEnum family) {
850 double zoom_mod = (double)g_chart_zoom_modifier_raster;
852 if (family == CHART_FAMILY_VECTOR)
853 zoom_mod = (double)g_chart_zoom_modifier_vector;
855 double modf = zoom_mod / 5.;
856 double mod = pow(16., modf);
857 mod = wxMax(mod, .2);
858 mod = wxMin(mod, 16.0);
862 case CHART_FAMILY_RASTER: {
863 if (CHART_TYPE_MBTILES == type)
869 return scale * 1 * mod;
872 case CHART_FAMILY_VECTOR: {
873 return scale * 4 * mod;
877 mod = wxMin(mod, 2.0);
878 return scale * 2 * mod;
884 int index, nom, min, max;
887int Quilt::AdjustRefOnZoom(
bool b_zin, ChartFamilyEnum family,
888 ChartTypeEnum type,
double proposed_scale_onscreen) {
889 std::vector<scale> scales;
890 std::vector<scale> scales_mbtiles;
899 bool b_allow_fullscreen_ref =
900 (family == CHART_FAMILY_VECTOR) || b_zin || g_bopengl;
904 int smallest_scale = 1;
905 for (
size_t i = 0; i < m_extended_stack_array.size(); i++) {
906 int index = m_extended_stack_array[i];
907 if (
ChartData->GetDBChartType(index) == type)
908 smallest_scale = wxMax(smallest_scale,
ChartData->GetDBChartScale(index));
913 for (
size_t i = 0; i < m_extended_stack_array.size(); i++) {
914 int test_db_index = m_extended_stack_array[i];
916 if (b_allow_fullscreen_ref ||
917 m_parent->GetpCurrentStack()->DoesStackContaindbIndex(test_db_index)) {
918 if ((family ==
ChartData->GetDBChartFamily(test_db_index)) &&
919 IsChartQuiltableRef(test_db_index)
921 int nscale =
ChartData->GetDBChartScale(test_db_index);
923 int nmax_scale = GetNomScaleMax(nscale, type, family);
927 if (0 == i_first) nmax_scale = 1;
929 int nmin_scale = GetNomScaleMin(nscale, type, family);
932 if ((type == CHART_TYPE_KAP) && (nscale == smallest_scale))
937 if ((type == CHART_TYPE_MBTILES) && (nscale == smallest_scale))
940 if (CHART_TYPE_MBTILES ==
ChartData->GetDBChartType(test_db_index))
941 scales_mbtiles.push_back(
942 scale{test_db_index, nscale, nmin_scale, nmax_scale});
945 scale{test_db_index, nscale, nmin_scale, nmax_scale});
952 if (scales.empty()) scales = scales_mbtiles;
959 if (CHART_FAMILY_VECTOR == family) {
960 for (
size_t i = scales.size(); i; i--) {
961 int test_db_index = scales[i - 1].index;
962 if (type ==
ChartData->GetDBChartType(test_db_index)) {
963 scales[i - 1].min = scales[i - 1].nom * 80;
975 if (scales.size() > 1) {
976 for (
unsigned i = 0; i < scales.size() - 1; i++) {
977 int min_scale_test = wxMax(scales[i].min, scales[i + 1].max + 1);
978 min_scale_test = wxMin(min_scale_test, scales[i].min * 2);
979 scales[i].min = min_scale_test;
988 if (scales.size() > 2) {
989 for (
size_t i = scales.size() - 2; i >= 1; i--) {
990 scales[i].max = wxMin(scales[i].max, scales[i - 1].min - 1);
994 int new_ref_dbIndex = -1;
998 for (
size_t i = 0; i < scales.size(); i++) {
999 if ((proposed_scale_onscreen <
1002 (proposed_scale_onscreen > scales[i].max)) {
1003 new_ref_dbIndex = scales[i].index;
1008 return new_ref_dbIndex;
1011int Quilt::AdjustRefOnZoomOut(
double proposed_scale_onscreen) {
1013 m_lost_refchart_dbIndex = -1;
1015 int current_db_index = m_refchart_dbIndex;
1016 int current_family = m_reference_family;
1017 ChartTypeEnum current_type = (ChartTypeEnum)m_reference_type;
1019 if (m_refchart_dbIndex >= 0) {
1021 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1022 current_family = cte.GetChartFamily();
1023 current_type = (ChartTypeEnum)cte.GetChartType();
1026 if (current_type == CHART_TYPE_CM93COMP)
return current_db_index;
1028 int proposed_ref_index =
1029 AdjustRefOnZoom(
false, (ChartFamilyEnum)current_family, current_type,
1030 proposed_scale_onscreen);
1033 if (proposed_ref_index < 0) {
1034 m_zout_family = current_family;
1035 m_zout_type = current_type;
1036 m_zout_dbindex = current_db_index;
1039 SetReferenceChart(proposed_ref_index);
1041 return proposed_ref_index;
1044int Quilt::AdjustRefOnZoomIn(
double proposed_scale_onscreen) {
1046 m_lost_refchart_dbIndex = -1;
1048 int current_db_index = m_refchart_dbIndex;
1049 int current_family = m_reference_family;
1050 ChartTypeEnum current_type = (ChartTypeEnum)m_reference_type;
1052 if (m_zout_family >= 0) {
1053 current_type = (ChartTypeEnum)m_zout_type;
1054 current_family = m_zout_family;
1060 if (current_type == CHART_TYPE_CM93COMP) {
1061 if (m_zout_family >= 0) {
1062 current_family =
ChartData->GetDBChartFamily(m_zout_dbindex);
1064 return current_db_index;
1067 if ((-1 == m_refchart_dbIndex) && (m_zout_dbindex >= 0))
1068 BuildExtendedChartStackAndCandidateArray(m_zout_dbindex, m_vp_quilt);
1070 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, m_vp_quilt);
1072 int proposed_ref_index =
1073 AdjustRefOnZoom(
true, (ChartFamilyEnum)current_family, current_type,
1074 proposed_scale_onscreen);
1076 if (current_db_index == -1) {
1077 SetReferenceChart(proposed_ref_index);
1078 return proposed_ref_index;
1081 if (proposed_ref_index != -1) {
1082 if (
ChartData->GetDBChartScale(current_db_index) >=
1083 ChartData->GetDBChartScale(proposed_ref_index)) {
1084 SetReferenceChart(proposed_ref_index);
1085 return proposed_ref_index;
1088 proposed_ref_index = current_db_index;
1090 SetReferenceChart(proposed_ref_index);
1092 return proposed_ref_index;
1095bool Quilt::IsChartSmallestScale(
int dbIndex) {
1100 int specified_type =
ChartData->GetDBChartType(dbIndex);
1101 int target_dbindex = -1;
1103 unsigned int target_stack_index = 0;
1104 if (m_extended_stack_array.size()) {
1105 while ((target_stack_index <= (m_extended_stack_array.size() - 1))) {
1106 int test_db_index = m_extended_stack_array[target_stack_index];
1108 if (specified_type ==
ChartData->GetDBChartType(test_db_index))
1109 target_dbindex = test_db_index;
1111 target_stack_index++;
1114 return (dbIndex == target_dbindex);
1117LLRegion Quilt::GetHiliteRegion() {
1123 for (
auto &index : m_HiLiteIndexArray) {
1125 LLRegion cell_region = GetChartQuiltRegion(cte, m_vp_quilt);
1126 r.Union(cell_region);
1130 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
1131 wxPatchListNode *pcinode = m_PatchList.Item(i);
1133 if ((index == piqp->dbIndex) && (piqp->b_Valid))
1135 r.Union(piqp->ActiveRegion);
1144LLRegion Quilt::GetHiliteRegion() {
1146 if (m_nHiLiteIndex >= 0) {
1148 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
1149 wxPatchListNode *pcinode = m_PatchList.Item(i);
1151 if ((m_nHiLiteIndex == piqp->dbIndex) && (piqp->b_Valid))
1153 r = piqp->ActiveRegion;
1160 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1162 if (m_nHiLiteIndex == pqc->dbIndex) {
1163 LLRegion chart_region = pqc->GetCandidateRegion();
1164 if (!chart_region.Empty()) {
1166 bool b_eclipsed =
false;
1167 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size();
1169 if (m_nHiLiteIndex == m_eclipsed_stack_array[ir]) {
1175 if (!b_eclipsed) r = chart_region;
1185 ChartData->GetChartTableEntry(m_nHiLiteIndex);
1186 if (cte.GetChartType() == CHART_TYPE_MBTILES) {
1187 r = GetTilesetRegion(m_nHiLiteIndex);
1195const LLRegion &Quilt::GetTilesetRegion(
int dbIndex) {
1196 LLRegion world_region(-90, -180, 90, 180);
1199 LLRegion &target_region =
const_cast<LLRegion &
>(cte.quilt_candidate_region);
1201 if (!target_region.Empty())
return target_region;
1204 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
1205 if (nAuxPlyEntries >= 1) {
1206 target_region.Clear();
1207 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
1208 float *pfp = cte.GetpAuxPlyTableEntry(ip);
1209 int nAuxPly = cte.GetAuxCntTableEntry(ip);
1211 target_region.Union(LLRegion(nAuxPly, pfp));
1214 std::vector<float> vec =
ChartData->GetReducedPlyPoints(dbIndex);
1216 std::vector<float> vecr;
1217 for (
size_t i = 0; i < vec.size() / 2; i++) {
1218 float a = vec[i * 2 + 1];
1224 std::vector<float>::iterator it = vecr.begin();
1226 if (vecr.size() / 2 >= 3) {
1229 target_region = LLRegion(vecr.size() / 2, (
float *)&(*it));
1231 target_region = world_region;
1235 if (!target_region.Empty()) {
1236 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
1237 if (nNoCovrPlyEntries) {
1238 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
1239 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
1240 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
1242 LLRegion t_region = LLRegion(nNoCovrPly, pfp);
1249 if (!t_region.Empty()) {
1250 LLRegion test_region = target_region;
1251 test_region.Subtract(t_region);
1253 if (!test_region.Empty()) target_region = test_region;
1267 return target_region;
1270int Quilt::SelectRefChartByFamily(ChartFamilyEnum family) {
1272 auto array = GetFullscreenIndexArray();
1274 std::sort(array.begin(), array.end(), CompareScalesStd);
1278 for (
int dbIndex : array) {
1284 wxFileName fn(cte_candidate.GetFullPath());
1285 if (fn.GetPath().Lower().Contains(
"basemap"))
continue;
1288 if (cte_candidate.GetChartFamily() == family) {
1297bool Quilt::BuildExtendedChartStackAndCandidateArray(
int ref_db_index,
1299 double zoom_test_val = .002;
1302 EmptyCandidateArray();
1303 m_extended_stack_array.clear();
1304 m_fullscreen_index_array.clear();
1306 int reference_scale = 1e8;
1307 int reference_type = -1;
1308 int reference_family = -1;
1310 m_bquiltanyproj ? vp_in.m_projection_type : PROJECTION_UNKNOWN;
1312 if (ref_db_index >= 0) {
1314 ChartData->GetChartTableEntry(ref_db_index);
1315 reference_scale = cte_ref.GetScale();
1316 reference_type = cte_ref.GetChartType();
1317 if (!m_bquiltanyproj) quilt_proj =
ChartData->GetDBChartProj(ref_db_index);
1318 reference_family = cte_ref.GetChartFamily();
1321 bool b_need_resort =
false;
1331 int n_charts = m_parent->GetpCurrentStack()->nEntry;
1335 for (
int ics = 0; ics < n_charts; ics++) {
1336 int istack = m_parent->GetpCurrentStack()->GetDBIndex(ics);
1337 if (istack < 0)
continue;
1338 m_extended_stack_array.push_back(istack);
1344 if (reference_type == CHART_TYPE_CM93COMP)
continue;
1354 if ((cte.GetChartType() == CHART_TYPE_PLUGIN) ||
1355 (reference_type == CHART_TYPE_PLUGIN)) {
1356 if (reference_family != cte.GetChartFamily()) {
1360 if (reference_type != cte.GetChartType()) {
1366 wxFileName fn(cte.GetFullPath());
1367 if (!fn.GetPath().Lower().Contains(
"basemap"))
continue;
1371 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1374 int candidate_chart_scale = cte.GetScale();
1375 double chart_native_ppm =
1376 m_canvas_scale_factor / (double)candidate_chart_scale;
1378 if ((zoom_factor < zoom_test_val) &&
1383 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
1384 m_extended_stack_array.pop_back();
1388 double skew_norm = cte.GetChartSkew();
1389 if (skew_norm > 180.) skew_norm -= 360.;
1391 if ((m_bquiltskew ? 1 : fabs(skew_norm) < 1.0) &&
1392 (m_bquiltanyproj || cte.GetChartProjectionType() == quilt_proj)) {
1394 qcnew->dbIndex = istack;
1395 qcnew->SetScale(cte.GetScale());
1396 m_pcandidate_array->push_back(qcnew);
1423 int n_all_charts =
ChartData->GetChartTableEntries();
1425 LLBBox viewbox = vp_local.GetBBox();
1426 int sure_index = -1;
1427 int sure_index_scale = 0;
1428 int sure_index_type = -1;
1430 for (
int i = 0; i < n_all_charts; i++) {
1434 int groupIndex = m_parent->m_groupIndex;
1435 if ((groupIndex > 0) && (!
ChartData->IsChartInGroup(i, groupIndex)))
1441 if (
ChartData->IsChartDirectoryExcluded(cte.GetFullPath()))
continue;
1443 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
1444 m_fullscreen_index_array.push_back(i);
1449 wxFileName fn(cte.GetFullSystemPath());
1450 if (!androidIsDirWritable(fn.GetPath()))
continue;
1452 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1454 const LLBBox &chart_box = cte.GetBBox();
1455 if ((viewbox.IntersectOut(chart_box)))
continue;
1457 if (cte.GetChartType() == CHART_TYPE_PLUGIN) {
1458 if (!
ChartData->IsChartAvailable(i))
continue;
1461 m_fullscreen_index_array.push_back(i);
1468 bool guest_family_include =
false;
1469 if (reference_family != cte.GetChartFamily()) {
1470 wxFileName fn(cte.GetFullPath());
1471 if (fn.GetPath().Lower().Contains(
"basemap")) {
1472 guest_family_include =
true;
1475 if ((cte.GetChartType() != CHART_TYPE_MBTILES) && !guest_family_include)
1479 if (!m_bquiltanyproj && quilt_proj != cte.GetChartProjectionType())
1482 double skew_norm = cte.GetChartSkew();
1483 if (skew_norm > 180.) skew_norm -= 360.;
1485 if (!m_bquiltskew && fabs(skew_norm) > 1.0)
continue;
1490 if( CHART_TYPE_S57 == cte.GetChartType() ) {
1492 double chart_area = (cte.GetLonMax() - cte.GetLonMin()) *
1493 (cte.GetLatMax() - cte.GetLatMin());
1494 double quilt_area = viewbox.GetLonRange() * viewbox.GetLatRange();
1495 if ((chart_area / quilt_area) < .01)
continue;
1498 int candidate_chart_scale = cte.GetScale();
1504 if (!cte.Scale_ge(reference_scale)) {
1505 if (cte.Scale_gt(sure_index_scale)) {
1507 sure_index_scale = candidate_chart_scale;
1508 sure_index_type = cte.GetChartType();
1517 double chart_native_ppm =
1518 m_canvas_scale_factor / (double)candidate_chart_scale;
1520 double zoom_factor_test_extra = 0.2;
1526 double ref_scale_test = reference_scale;
1527 if (cte.GetChartType() == CHART_TYPE_MBTILES)
1528 ref_scale_test = candidate_chart_scale;
1530 if ((cte.Scale_ge(ref_scale_test) && (zoom_factor > zoom_test_val)) ||
1531 (zoom_factor > zoom_factor_test_extra)) {
1532 LLRegion cell_region = GetChartQuiltRegion(cte, vp_local);
1537 if (!cell_region.Empty()) {
1540 bool b_exists =
false;
1541 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1542 if (i == m_extended_stack_array[ir]) {
1556 bool b_noadd =
false;
1558 for (
unsigned int id = 0;
id < m_extended_stack_array.size();
id++) {
1559 if (m_extended_stack_array[
id] != -1) {
1561 ChartData->GetpChartTableEntry(m_extended_stack_array[
id]);
1562 bool bsameTime =
false;
1563 if (pm->GetFileTime() && pn->GetFileTime()) {
1564 if (labs(pm->GetFileTime() - pn->GetFileTime()) < 60)
1567 if (pm->GetChartEditionDate() == pn->GetChartEditionDate())
1571 if (pn->GetpFileName()->IsSameAs(*(pm->GetpFileName())))
1578 m_extended_stack_array.push_back(i);
1583 candidate_chart_scale);
1585 m_pcandidate_array->push_back(qcnew);
1587 b_need_resort =
true;
1596 if (-1 != sure_index) {
1598 bool sure_exists =
false;
1599 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1600 if (sure_index == m_extended_stack_array[ir]) {
1607 if (!sure_exists && (sure_index_type != CHART_TYPE_MBTILES)) {
1608 m_extended_stack_array.push_back(sure_index);
1611 qcnew->dbIndex = sure_index;
1612 qcnew->SetScale(
ChartData->GetDBChartScale(sure_index));
1613 m_pcandidate_array->push_back(qcnew);
1615 b_need_resort =
true;
1620 if (b_need_resort && m_extended_stack_array.size() > 1) {
1621 std::sort(m_extended_stack_array.begin(), m_extended_stack_array.end(),
1627int Quilt::AdjustRefSelection(
const ViewPort &vp_in) {
1642 vp_local.SetRotationAngle(0.);
1644 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1646 ChartFamilyEnum family = CHART_FAMILY_RASTER;
1647 ChartTypeEnum type = CHART_TYPE_KAP;
1650 if (m_refchart_dbIndex >= 0) {
1652 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1653 type = (ChartTypeEnum)cte_ref.GetChartType();
1654 family = (ChartFamilyEnum)cte_ref.GetChartFamily();
1657 int ret_index = AdjustRefOnZoom(
true, family, type, vp_in.
chart_scale);
1662double Quilt::GetBestStartScale(
int dbi_ref_hint,
const ViewPort &vp_in) {
1672 int tentative_ref_index = dbi_ref_hint;
1673 if (dbi_ref_hint < 0) {
1680 tentative_ref_index = m_parent->GetpCurrentStack()->GetDBIndex(0);
1687 vp_local.SetRotationAngle(0.);
1689 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1693 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1695 if (qc->dbIndex == tentative_ref_index) {
1701 if (!bf && m_pcandidate_array->GetCount()) {
1702 tentative_ref_index = GetNewRefChart();
1703 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1706 double proposed_scale_onscreen = vp_in.
chart_scale;
1708 if (m_pcandidate_array->GetCount()) {
1709 m_refchart_dbIndex = tentative_ref_index;
1713 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1715 if (IsChartQuiltableRef(qc->dbIndex)) {
1716 m_refchart_dbIndex = qc->dbIndex;
1723 m_refchart_dbIndex = m_parent->GetpCurrentStack()->GetDBIndex(0);
1726 if (m_refchart_dbIndex >= 0) {
1731 double min_ref_scale =
1733 double max_ref_scale = pc->GetNormalScaleMax(
1735 if ((proposed_scale_onscreen >= min_ref_scale) &&
1736 (proposed_scale_onscreen <= max_ref_scale))
1739 proposed_scale_onscreen = wxMin(proposed_scale_onscreen, max_ref_scale);
1740 proposed_scale_onscreen = wxMax(proposed_scale_onscreen, min_ref_scale);
1748 if (m_refchart_dbIndex >= 0 &&
ChartData)
1749 return ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
1753void Quilt::UnlockQuilt() {
1754 wxASSERT(m_bbusy ==
false);
1757 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1759 ChartData->UnLockCacheChart(pqc->dbIndex);
1769 if (!m_parent->GetpCurrentStack())
return false;
1771 if (m_bbusy)
return false;
1780 if (m_refchart_dbIndex >= 0) {
1782 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1783 m_reference_scale = cte_ref.GetScale();
1784 m_reference_type = cte_ref.GetChartType();
1785 if (!m_bquiltanyproj)
1786 m_quilt_proj =
ChartData->GetDBChartProj(m_refchart_dbIndex);
1787 m_reference_family = cte_ref.GetChartFamily();
1791 if (!m_bquiltanyproj) vp_local.SetProjectionType(m_quilt_proj);
1798 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1838 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1840 if (qc->dbIndex == m_refchart_dbIndex) {
1846 if (!bf && m_pcandidate_array->GetCount() &&
1847 (m_reference_type != CHART_TYPE_CM93COMP)) {
1848 m_lost_refchart_dbIndex = m_refchart_dbIndex;
1849 int candidate_ref_index = GetNewRefChart();
1850 if (m_refchart_dbIndex != candidate_ref_index) {
1851 m_refchart_dbIndex = candidate_ref_index;
1852 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1857 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1858 if (m_pcandidate_array->GetCount()) {
1859 m_refchart_dbIndex =
1860 m_pcandidate_array->Item(m_pcandidate_array->GetCount() - 1)
1862 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1867 if ((-1 != m_lost_refchart_dbIndex) &&
1868 (m_lost_refchart_dbIndex != m_refchart_dbIndex)) {
1871 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1872 if (m_lost_refchart_dbIndex == m_extended_stack_array[ir]) {
1873 m_refchart_dbIndex = m_lost_refchart_dbIndex;
1874 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1875 m_lost_refchart_dbIndex = -1;
1881 bool b_has_overlays =
false;
1884 if (CHART_FAMILY_VECTOR == m_reference_family) {
1885 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1889 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1890 b_has_overlays =
true;
1903 const LLRegion cvp_region = vp_local.GetLLRegion(vp_local.rv_rect);
1904 LLRegion vp_region = cvp_region;
1910 for (ir = 0; ir < m_pcandidate_array->GetCount();
1914 if (pqc->dbIndex == m_refchart_dbIndex) {
1923 const double z = 111274.96299695622;
1929 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1931 LLRegion vpu_region(cvp_region);
1934 LLRegion &chart_region = pqc_ref->GetReducedCandidateRegion(factor);
1936 if (cte_ref.GetChartType() != CHART_TYPE_MBTILES) {
1937 if (!chart_region.Empty()) {
1938 vpu_region.Intersect(chart_region);
1940 if (vpu_region.Empty())
1941 pqc_ref->b_include =
false;
1943 pqc_ref->b_include =
true;
1944 vp_region.Subtract(chart_region);
1947 pqc_ref->b_include =
false;
1949 pqc_ref->b_include =
false;
1954 if (!vp_region.Empty()) {
1955 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1958 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
1965 if (CHART_FAMILY_VECTOR == m_reference_family) {
1966 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1972 if (CHART_TYPE_MBTILES == cte.GetChartType()) {
1973 pqc->b_include =
false;
1977 if (cte.Scale_ge(m_reference_scale)) {
1981 bool b_in_noshow =
false;
1982 for (
unsigned int ins = 0;
1983 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
1984 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
1994 LLRegion vpu_region(cvp_region);
1997 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
1999 if (!chart_region.Empty()) {
2000 vpu_region.Intersect(chart_region);
2002 if (vpu_region.Empty())
2003 pqc->b_include =
false;
2005 pqc->b_include =
true;
2006 vp_region.Subtract(chart_region);
2009 pqc->b_include =
false;
2011 pqc->b_include =
true;
2015 pqc->b_include =
false;
2018 if (vp_region.Empty())
2025 if (b_has_overlays && (CHART_FAMILY_VECTOR == m_reference_family)) {
2026 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2029 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
2033 if (cte.Scale_ge(m_reference_scale)) {
2034 bool b_in_noshow =
false;
2035 for (
unsigned int ins = 0;
2036 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2037 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2047 LLRegion vpu_region(cvp_region);
2050 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2052 if (!chart_region.Empty()) vpu_region.Intersect(chart_region);
2054 if (vpu_region.Empty())
2055 pqc->b_include =
false;
2058 s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2059 if (b_overlay) pqc->b_include =
true;
2066 ChartData->GetChartTableEntry(m_refchart_dbIndex);
2067 if (s57chart::IsCellOverlayType(cte_ref.GetFullSystemPath())) {
2068 pqc->b_include =
true;
2080 m_eclipsed_stack_array.clear();
2082 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2085 if (!pqc->b_include) {
2087 if (cte.Scale_ge(m_reference_scale) &&
2088 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
2089 m_eclipsed_stack_array.push_back(pqc->dbIndex);
2090 pqc->b_eclipsed =
true;
2097 if (((m_bquiltanyproj || m_quilt_proj == PROJECTION_MERCATOR)) &&
2098 !vp_region.Empty()) {
2099 bool b_must_add_cm93 =
true;
2106 while( updd .HaveRects()) {
2107 wxRect rect = updd.GetRect();
2108 if( ( rect.width > 2 ) && ( rect.height > 2 ) ) {
2109 b_must_add_cm93 =
true;
2116 if (b_must_add_cm93) {
2117 for (
int ics = 0; ics < m_parent->GetpCurrentStack()->nEntry; ics++) {
2118 int i = m_parent->GetpCurrentStack()->GetDBIndex(ics);
2119 if (CHART_TYPE_CM93COMP ==
ChartData->GetDBChartType(i)) {
2122 qcnew->SetScale(
ChartData->GetDBChartScale(i));
2124 m_pcandidate_array->Add(qcnew);
2135 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
2137 if (pqc->b_include) {
2143 if (!b_vis && m_pcandidate_array->GetCount()) {
2146 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2151 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2154 if (cte.GetChartType() == CHART_TYPE_MBTILES)
continue;
2157 LLRegion vpck_region(vp_local.GetBBox());
2160 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2162 if (!chart_region.Empty()) vpck_region.Intersect(chart_region);
2164 if (!vpck_region.Empty()) {
2166 if (cte.Scale_eq(add_scale)) {
2167 pqc->b_include =
true;
2170 pqc->b_include =
true;
2171 add_scale = cte.GetScale();
2180 m_PatchList.DeleteContents(
true);
2181 m_PatchList.Clear();
2183 if (m_pcandidate_array->GetCount()) {
2184 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2192 if (m.GetChartType() == CHART_TYPE_CM93COMP)
2193 pqc->b_include =
true;
2196 if (pqc->b_include) {
2198 pqp->dbIndex = pqc->dbIndex;
2199 pqp->ProjType = m.GetChartProjectionType();
2202 pqp->quilt_region = pqc->GetCandidateRegion();
2205 pqp->b_Valid =
true;
2207 m_PatchList.Append(pqp);
2214 if (!m_bquiltanyproj) {
2216 m_quilt_proj = PROJECTION_MERCATOR;
2217 ChartBase *ppc = GetLargestScaleChart();
2218 if (ppc) m_quilt_proj = ppc->GetChartProjectionType();
2222 if (!m_bquiltanyproj) {
2225 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2226 wxPatchListNode *pcinode = m_PatchList.Item(i);
2228 if ((piqp->ProjType != m_quilt_proj) &&
2229 (piqp->ProjType != PROJECTION_UNKNOWN))
2230 piqp->b_Valid =
false;
2235 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2236 wxPatchListNode *pcinode = m_PatchList.Item(i);
2238 for (
unsigned int ins = 0;
2239 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2240 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2243 piqp->b_Valid =
false;
2251 m_covered_region.Clear();
2256 bool b_skipCM93 =
false;
2257 if (m_reference_type == CHART_TYPE_CM93COMP) {
2259 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2260 wxPatchListNode *pcinode = m_PatchList.Item(i);
2267 if (m.GetChartType() == CHART_TYPE_CM93COMP) {
2269 piqp->ActiveRegion = piqp->quilt_region;
2270 piqp->ActiveRegion.Intersect(cvp_region);
2274 m_covered_region.Union(piqp->quilt_region);
2284 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2285 wxPatchListNode *pcinode = m_PatchList.Item(i);
2293 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2297 piqp->ActiveRegion = piqp->quilt_region;
2300 if (!b_has_overlays && m_PatchList.GetCount() < 25)
2301 piqp->ActiveRegion.Subtract(m_covered_region);
2303 piqp->ActiveRegion.Intersect(cvp_region);
2307 if (piqp->ActiveRegion.Empty() && (piqp->dbIndex != m_refchart_dbIndex))
2308 piqp->b_eclipsed =
true;
2311 piqp->b_overlay =
false;
2312 if (cte.GetChartFamily() == CHART_FAMILY_VECTOR) {
2313 piqp->b_overlay = s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2316 if (!piqp->b_overlay) m_covered_region.Union(piqp->quilt_region);
2321 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2322 wxPatchListNode *pcinode = m_PatchList.Item(i);
2331 LLRegion vpr_region = piqp->quilt_region;
2339 for (
unsigned int k = i + 1; k < m_PatchList.GetCount(); k++) {
2340 wxPatchListNode *pnode = m_PatchList.Item(k);
2361 if (!b_has_overlays) {
2362 if (!vpr_region.Empty()) {
2364 ChartData->GetChartTableEntry(pqp->dbIndex);
2365 LLRegion larger_scale_chart_region =
2368 vpr_region.Subtract(larger_scale_chart_region);
2377 wxPatchListNode *pinode = m_PatchList.Item(i);
2379 pqpi->ActiveRegion = vpr_region;
2388 if (pqpi->ActiveRegion.Empty()) pqpi->b_eclipsed =
true;
2396 m_covered_region.Union(pqpi->ActiveRegion);
2403 unsigned int il = 0;
2404 while (il < m_PatchList.GetCount()) {
2405 wxPatchListNode *pcinode = m_PatchList.Item(il);
2407 if (piqp->b_eclipsed) {
2410 bool b_noadd =
false;
2411 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size(); ir++) {
2412 if (piqp->dbIndex == m_eclipsed_stack_array[ir]) {
2417 if (!b_noadd) m_eclipsed_stack_array.push_back(piqp->dbIndex);
2419 m_PatchList.DeleteNode(pcinode);
2438 m_parent->EnablePaint(
false);
2445 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2447 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2448 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2449 ChartData->LockCacheChart(pqc->dbIndex);
2454 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2456 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2457 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2458 ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
true);
2467 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2469 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2470 if (
ChartData->IsChartLocked(pqc->dbIndex))
2471 pqc->b_locked =
true;
2473 pqc->b_locked =
ChartData->LockCacheChart(pqc->dbIndex);
2478 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2480 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2486 if (
ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
2488 pqc->b_locked =
true;
2493 m_parent->EnablePaint(
true);
2496 m_last_index_array = m_index_array;
2498 m_index_array.clear();
2501 unsigned int kl = m_PatchList.GetCount();
2502 for (
unsigned int k = 0; k < kl; k++) {
2503 wxPatchListNode *cnode = m_PatchList.Item((kl - k) - 1);
2504 m_index_array.push_back(cnode->GetData()->dbIndex);
2505 cnode = cnode->GetNext();
2511 m_quilt_depth_unit =
"";
2514 m_quilt_depth_unit = pc->GetDepthUnits();
2516 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2517 int units = ps52plib->m_nDepthUnitDisplay;
2520 m_quilt_depth_unit =
"Feet";
2523 m_quilt_depth_unit =
"Meters";
2526 m_quilt_depth_unit =
"Fathoms";
2532 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2533 wxPatchListNode *pnode = m_PatchList.Item(k);
2541 wxString du = pc->GetDepthUnits();
2542 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2543 int units = ps52plib->m_nDepthUnitDisplay;
2556 wxString dul = du.Lower();
2557 wxString ml = m_quilt_depth_unit.Lower();
2561 if (dul.StartsWith(
"meters") && ml.StartsWith(
"meters"))
2563 else if (dul.StartsWith(
"metres") && ml.StartsWith(
"metres"))
2565 else if (dul.StartsWith(
"fathoms") && ml.StartsWith(
"fathoms"))
2567 else if (dul.StartsWith(
"met") && ml.StartsWith(
"met"))
2571 m_quilt_depth_unit =
"";
2581 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2582 wxPatchListNode *pnode = m_PatchList.Item(k);
2586 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2587 wxLogMessage(
" Quilt Compose cache miss...");
2588 ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
2589 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2590 wxLogMessage(
" Oops, removing from quilt...");
2591 pqp->b_Valid =
false;
2598 if (!
ChartData->IsChartInCache(m_refchart_dbIndex))
2599 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
2605 m_bquilt_has_overlays =
false;
2606 m_max_error_factor = 0.;
2607 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2608 wxPatchListNode *pnode = m_PatchList.Item(k);
2616 m_max_error_factor =
2617 wxMax(m_max_error_factor, pc->GetChart_Error_Factor());
2618 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2619 bool isOverlay = IsChartS57Overlay(pqp->dbIndex);
2620 pqp->b_overlay = isOverlay;
2621 if (isOverlay) m_bquilt_has_overlays =
true;
2634 unsigned long xa_hash = 5381;
2635 for (
unsigned int im = 0; im < m_extended_stack_array.size(); im++) {
2636 int dbindex = m_extended_stack_array[im];
2637 xa_hash = ((xa_hash << 5) + xa_hash) + dbindex;
2640 m_xa_hash = xa_hash;
2648 if (!m_bcomposed)
return;
2652 if (GetnCharts() && !m_bbusy && !chart_region.Empty()) {
2658 if (!(chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2659 vp.b_MercatorProjectionOverride)) {
2663 chart_region, pqp->ActiveRegion, chart->GetNativeScale());
2664 if (!get_screen_region.Empty())
2665 rendered_region.Union(get_screen_region);
2668 chart = GetNextChart();
2672 m_rendered_region = rendered_region;
2677bool Quilt::RenderQuiltRegionViewOnDCNoText(wxMemoryDC &dc,
ViewPort &vp,
2679 return DoRenderQuiltRegionViewOnDC(dc, vp, chart_region);
2682bool Quilt::RenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
2684 return DoRenderQuiltRegionViewOnDCTextOnly(dc, vp, chart_region);
2687bool Quilt::DoRenderQuiltRegionViewOnDC(wxMemoryDC &dc,
ViewPort &vp,
2689#ifdef ocpnUSE_DIBSECTION
2695 if (!m_bcomposed)
return false;
2699 if (GetnCharts() && !m_bbusy) {
2707 int chartsDrawn = 0;
2709 if (!chart_region.Empty()) {
2711 bool okToRender =
true;
2713 if (chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2714 vp.b_MercatorProjectionOverride)
2718 chart = GetNextChart();
2723 bool b_chart_rendered =
false;
2724 LLRegion get_region = pqp->ActiveRegion;
2727 chart_region, get_region, chart->GetNativeScale());
2728 if (!get_screen_region.Empty()) {
2729 if (!pqp->b_overlay) {
2730 if (chart->GetChartType() == CHART_TYPE_CM93COMP) {
2732 chart->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2736 if (Chs57->m_RAZBuilt) {
2737 b_chart_rendered = Chs57->RenderRegionViewOnDCNoText(
2738 tmp_dc, vp, get_screen_region);
2744 b_chart_rendered = ChPI->RenderRegionViewOnDCNoText(
2745 tmp_dc, vp, get_screen_region);
2747 b_chart_rendered = chart->RenderRegionViewOnDC(
2748 tmp_dc, vp, get_screen_region);
2750 b_chart_rendered =
true;
2757 screen_region.Subtract(get_screen_region);
2762 while (upd.HaveRects()) {
2763 wxRect rect = upd.GetRect();
2764 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc, rect.x,
2765 rect.y, wxCOPY,
true);
2769 tmp_dc.SelectObject(wxNullBitmap);
2771 if (b_chart_rendered) rendered_region.Union(get_screen_region);
2775 chart = GetNextChart();
2779 if (!chartsDrawn) m_parent->GetVP().SetProjectionType(PROJECTION_MERCATOR);
2782 if (m_bquilt_has_overlays && !chart_region.Empty()) {
2783 chart = GetFirstChart();
2787 if (pqp->b_overlay) {
2788 LLRegion get_region = pqp->ActiveRegion;
2790 chart_region, get_region, chart->GetNativeScale());
2791 if (!get_region.Empty()) {
2794 Chs57->RenderOverlayRegionViewOnDC(tmp_dc, vp,
2800 ChPI->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2805 while (upd.HaveRects()) {
2806 wxRect rect = upd.GetRect();
2807 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc,
2808 rect.x, rect.y, wxCOPY,
true);
2811 tmp_dc.SelectObject(wxNullBitmap);
2816 chart = GetNextChart();
2823 while (clrit.HaveRects()) {
2824 wxRect rect = clrit.GetRect();
2826 dc.SetPen(*wxBLACK_PEN);
2827 dc.SetBrush(*wxBLACK_BRUSH);
2828 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
2830 dc.Blit(rect.x, rect.y, rect.width, rect.height, &dc, rect.x, rect.y,
2837 if (m_nHiLiteIndex >= 0) {
2840 wxRect box = hiregion.GetBox();
2842 if (!box.IsEmpty()) {
2845 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2846 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2853 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2857 q_dc.SelectObject(*m_pBM);
2858 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2859 q_dc.SelectObject(wxNullBitmap);
2864 wxBitmap hl_mask_bm(vp.rv_rect.width, vp.rv_rect.height, 1);
2866 mdc.SelectObject(hl_mask_bm);
2867 mdc.SetBackground(*wxBLACK_BRUSH);
2869 mdc.SetClippingRegion(box);
2870 mdc.SetBackground(*wxWHITE_BRUSH);
2872 mdc.SelectObject(wxNullBitmap);
2874 if (hl_mask_bm.IsOk()) {
2875 wxMask *phl_mask =
new wxMask(hl_mask_bm);
2876 m_pBM->SetMask(phl_mask);
2877 q_dc.SelectObject(*m_pBM);
2880 wxBitmap rbm(vp.rv_rect.width, vp.rv_rect.height);
2881 wxMask *pr_mask =
new wxMask(hl_mask_bm);
2883 rbm.SetMask(pr_mask);
2884 rdc.SelectObject(rbm);
2885 unsigned char hlcolor = 255;
2886 switch (global_color_scheme) {
2887 case GLOBAL_COLOR_SCHEME_DAY:
2890 case GLOBAL_COLOR_SCHEME_DUSK:
2893 case GLOBAL_COLOR_SCHEME_NIGHT:
2901 rdc.SetBackground(wxBrush(wxColour(hlcolor, 0, 0)));
2905 while (upd.HaveRects()) {
2906 wxRect rect = upd.GetRect();
2907 rdc.Blit(rect.x, rect.y, rect.width, rect.height, &q_dc, rect.x,
2908 rect.y, wxOR,
true);
2913 while (updq.HaveRects()) {
2914 wxRect rect = updq.GetRect();
2915 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &rdc, rect.x,
2916 rect.y, wxCOPY,
true);
2920 q_dc.SelectObject(wxNullBitmap);
2921 m_pBM->SetMask(NULL);
2924 dc.SelectObject(*m_pBM);
2927 rdc.SelectObject(wxNullBitmap);
2933 if (g_fog_overzoom) {
2936 if (scale_factor > g_overzoom_emphasis_base) {
2937 float fog = ((scale_factor - g_overzoom_emphasis_base) * 255.) / 20.;
2938 fog = wxMin(fog, 200.);
2942 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2943 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2950 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2954 q_dc.SelectObject(*m_pBM);
2955 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2956 q_dc.SelectObject(wxNullBitmap);
2958 wxImage src = m_pBM->ConvertToImage();
2961 wxMin((scale_factor - g_overzoom_emphasis_base) / 4, 4);
2963 wxImage dest = src.Blur(blur_factor);
2967 unsigned char *bg = src.GetData();
2968 wxColour color = m_parent->GetFogColor();
2970 float transparency = fog;
2973 wxImage dest(vp.rv_rect.width, vp.rv_rect.height);
2974 unsigned char *dest_data = (
unsigned char *) malloc( vp.rv_rect.width * vp.rv_rect.height * 3 *
sizeof(
unsigned char) );
2975 unsigned char *d = dest_data;
2977 float alpha = 1.0 - (float)transparency / 255.0;
2978 int sb = vp.rv_rect.width * vp.rv_rect.height;
2979 for(
int i = 0; i < sb; i++ ) {
2982 int r = ( ( *bg++ ) * a ) + (1.0-a) * color.Red();
2984 int g = ( ( *bg++ ) * a ) + (1.0-a) * color.Green();
2986 int b = ( ( *bg++ ) * a ) + (1.0-a) * color.Blue();
2990 dest.SetData( dest_data );
2995 ddc.SelectObject(dim);
2997 q_dc.SelectObject(*m_pBM);
2999 while (upd.HaveRects()) {
3000 wxRect rect = upd.GetRect();
3001 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &ddc, rect.x,
3006 ddc.SelectObject(wxNullBitmap);
3007 q_dc.SelectObject(wxNullBitmap);
3010 dc.SelectObject(*m_pBM);
3018 SubstituteClearDC(dc, vp);
3022 SubstituteClearDC(dc, vp);
3026 m_rendered_region = rendered_region;
3032void Quilt::SubstituteClearDC(wxMemoryDC &dc,
ViewPort &vp) {
3034 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
3035 (m_pBM->GetHeight() != vp.rv_rect.height)) {
3041 if (NULL == m_pBM) {
3042 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
3045 dc.SelectObject(wxNullBitmap);
3046 dc.SelectObject(*m_pBM);
3047 dc.SetBackground(*wxBLACK_BRUSH);
3049 m_covered_region.Clear();
3052bool Quilt::DoRenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
3054 if (!m_bcomposed)
return false;
3058 if (GetnCharts() && !m_bbusy) {
3063 ChartBase *chart = GetLargestScaleChart();
3070 Chs57->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3074 ChPI->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3079 chart = GetNextSmallerScaleChart();
3083 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.