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;
1270bool Quilt::BuildExtendedChartStackAndCandidateArray(
int ref_db_index,
1272 double zoom_test_val = .002;
1275 EmptyCandidateArray();
1276 m_extended_stack_array.clear();
1277 m_fullscreen_index_array.clear();
1279 int reference_scale = 1e8;
1280 int reference_type = -1;
1281 int reference_family = -1;
1283 m_bquiltanyproj ? vp_in.m_projection_type : PROJECTION_UNKNOWN;
1285 if (ref_db_index >= 0) {
1287 ChartData->GetChartTableEntry(ref_db_index);
1288 reference_scale = cte_ref.GetScale();
1289 reference_type = cte_ref.GetChartType();
1290 if (!m_bquiltanyproj) quilt_proj =
ChartData->GetDBChartProj(ref_db_index);
1291 reference_family = cte_ref.GetChartFamily();
1294 bool b_need_resort =
false;
1304 int n_charts = m_parent->GetpCurrentStack()->nEntry;
1308 for (
int ics = 0; ics < n_charts; ics++) {
1309 int istack = m_parent->GetpCurrentStack()->GetDBIndex(ics);
1310 if (istack < 0)
continue;
1311 m_extended_stack_array.push_back(istack);
1317 if (reference_type == CHART_TYPE_CM93COMP)
continue;
1327 if ((cte.GetChartType() == CHART_TYPE_PLUGIN) ||
1328 (reference_type == CHART_TYPE_PLUGIN)) {
1329 if (reference_family != cte.GetChartFamily()) {
1333 if (reference_type != cte.GetChartType()) {
1338 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1341 int candidate_chart_scale = cte.GetScale();
1342 double chart_native_ppm =
1343 m_canvas_scale_factor / (double)candidate_chart_scale;
1345 if ((zoom_factor < zoom_test_val) &&
1350 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
1351 m_extended_stack_array.pop_back();
1355 double skew_norm = cte.GetChartSkew();
1356 if (skew_norm > 180.) skew_norm -= 360.;
1358 if ((m_bquiltskew ? 1 : fabs(skew_norm) < 1.0) &&
1359 (m_bquiltanyproj || cte.GetChartProjectionType() == quilt_proj)) {
1361 qcnew->dbIndex = istack;
1362 qcnew->SetScale(cte.GetScale());
1363 m_pcandidate_array->push_back(qcnew);
1390 int n_all_charts =
ChartData->GetChartTableEntries();
1392 LLBBox viewbox = vp_local.GetBBox();
1393 int sure_index = -1;
1394 int sure_index_scale = 0;
1395 int sure_index_type = -1;
1397 for (
int i = 0; i < n_all_charts; i++) {
1401 int groupIndex = m_parent->m_groupIndex;
1402 if ((groupIndex > 0) && (!
ChartData->IsChartInGroup(i, groupIndex)))
1408 if (
ChartData->IsChartDirectoryExcluded(cte.GetFullPath()))
continue;
1410 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
1411 m_fullscreen_index_array.push_back(i);
1416 wxFileName fn(cte.GetFullSystemPath());
1417 if (!androidIsDirWritable(fn.GetPath()))
continue;
1419 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1421 const LLBBox &chart_box = cte.GetBBox();
1422 if ((viewbox.IntersectOut(chart_box)))
continue;
1424 if (cte.GetChartType() == CHART_TYPE_PLUGIN) {
1425 if (!
ChartData->IsChartAvailable(i))
continue;
1428 m_fullscreen_index_array.push_back(i);
1430 if (reference_family != cte.GetChartFamily()) {
1431 if (cte.GetChartType() != CHART_TYPE_MBTILES)
continue;
1434 if (!m_bquiltanyproj && quilt_proj != cte.GetChartProjectionType())
1437 double skew_norm = cte.GetChartSkew();
1438 if (skew_norm > 180.) skew_norm -= 360.;
1440 if (!m_bquiltskew && fabs(skew_norm) > 1.0)
continue;
1445 if( CHART_TYPE_S57 == cte.GetChartType() ) {
1447 double chart_area = (cte.GetLonMax() - cte.GetLonMin()) *
1448 (cte.GetLatMax() - cte.GetLatMin());
1449 double quilt_area = viewbox.GetLonRange() * viewbox.GetLatRange();
1450 if ((chart_area / quilt_area) < .01)
continue;
1453 int candidate_chart_scale = cte.GetScale();
1459 if (!cte.Scale_ge(reference_scale)) {
1460 if (cte.Scale_gt(sure_index_scale)) {
1462 sure_index_scale = candidate_chart_scale;
1463 sure_index_type = cte.GetChartType();
1472 double chart_native_ppm =
1473 m_canvas_scale_factor / (double)candidate_chart_scale;
1475 double zoom_factor_test_extra = 0.2;
1481 double ref_scale_test = reference_scale;
1482 if (cte.GetChartType() == CHART_TYPE_MBTILES)
1483 ref_scale_test = candidate_chart_scale;
1485 if ((cte.Scale_ge(ref_scale_test) && (zoom_factor > zoom_test_val)) ||
1486 (zoom_factor > zoom_factor_test_extra)) {
1487 LLRegion cell_region = GetChartQuiltRegion(cte, vp_local);
1492 if (!cell_region.Empty()) {
1495 bool b_exists =
false;
1496 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1497 if (i == m_extended_stack_array[ir]) {
1511 bool b_noadd =
false;
1513 for (
unsigned int id = 0;
id < m_extended_stack_array.size();
id++) {
1514 if (m_extended_stack_array[
id] != -1) {
1516 ChartData->GetpChartTableEntry(m_extended_stack_array[
id]);
1517 bool bsameTime =
false;
1518 if (pm->GetFileTime() && pn->GetFileTime()) {
1519 if (labs(pm->GetFileTime() - pn->GetFileTime()) < 60)
1522 if (pm->GetChartEditionDate() == pn->GetChartEditionDate())
1526 if (pn->GetpFileName()->IsSameAs(*(pm->GetpFileName())))
1533 m_extended_stack_array.push_back(i);
1538 candidate_chart_scale);
1540 m_pcandidate_array->push_back(qcnew);
1542 b_need_resort =
true;
1551 if (-1 != sure_index) {
1553 bool sure_exists =
false;
1554 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1555 if (sure_index == m_extended_stack_array[ir]) {
1562 if (!sure_exists && (sure_index_type != CHART_TYPE_MBTILES)) {
1563 m_extended_stack_array.push_back(sure_index);
1566 qcnew->dbIndex = sure_index;
1567 qcnew->SetScale(
ChartData->GetDBChartScale(sure_index));
1568 m_pcandidate_array->push_back(qcnew);
1570 b_need_resort =
true;
1575 if (b_need_resort && m_extended_stack_array.size() > 1) {
1576 std::sort(m_extended_stack_array.begin(), m_extended_stack_array.end(),
1582int Quilt::AdjustRefSelection(
const ViewPort &vp_in) {
1597 vp_local.SetRotationAngle(0.);
1599 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1601 ChartFamilyEnum family = CHART_FAMILY_RASTER;
1602 ChartTypeEnum type = CHART_TYPE_KAP;
1605 if (m_refchart_dbIndex >= 0) {
1607 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1608 type = (ChartTypeEnum)cte_ref.GetChartType();
1609 family = (ChartFamilyEnum)cte_ref.GetChartFamily();
1612 int ret_index = AdjustRefOnZoom(
true, family, type, vp_in.
chart_scale);
1617double Quilt::GetBestStartScale(
int dbi_ref_hint,
const ViewPort &vp_in) {
1627 int tentative_ref_index = dbi_ref_hint;
1628 if (dbi_ref_hint < 0) {
1635 tentative_ref_index = m_parent->GetpCurrentStack()->GetDBIndex(0);
1642 vp_local.SetRotationAngle(0.);
1644 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1648 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1650 if (qc->dbIndex == tentative_ref_index) {
1656 if (!bf && m_pcandidate_array->GetCount()) {
1657 tentative_ref_index = GetNewRefChart();
1658 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1661 double proposed_scale_onscreen = vp_in.
chart_scale;
1663 if (m_pcandidate_array->GetCount()) {
1664 m_refchart_dbIndex = tentative_ref_index;
1668 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1670 if (IsChartQuiltableRef(qc->dbIndex)) {
1671 m_refchart_dbIndex = qc->dbIndex;
1678 m_refchart_dbIndex = m_parent->GetpCurrentStack()->GetDBIndex(0);
1681 if (m_refchart_dbIndex >= 0) {
1686 double min_ref_scale =
1688 double max_ref_scale = pc->GetNormalScaleMax(
1690 if ((proposed_scale_onscreen >= min_ref_scale) &&
1691 (proposed_scale_onscreen <= max_ref_scale))
1694 proposed_scale_onscreen = wxMin(proposed_scale_onscreen, max_ref_scale);
1695 proposed_scale_onscreen = wxMax(proposed_scale_onscreen, min_ref_scale);
1703 if (m_refchart_dbIndex >= 0 &&
ChartData)
1704 return ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
1708void Quilt::UnlockQuilt() {
1709 wxASSERT(m_bbusy ==
false);
1712 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1714 ChartData->UnLockCacheChart(pqc->dbIndex);
1724 if (!m_parent->GetpCurrentStack())
return false;
1726 if (m_bbusy)
return false;
1735 if (m_refchart_dbIndex >= 0) {
1737 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1738 m_reference_scale = cte_ref.GetScale();
1739 m_reference_type = cte_ref.GetChartType();
1740 if (!m_bquiltanyproj)
1741 m_quilt_proj =
ChartData->GetDBChartProj(m_refchart_dbIndex);
1742 m_reference_family = cte_ref.GetChartFamily();
1746 if (!m_bquiltanyproj) vp_local.SetProjectionType(m_quilt_proj);
1753 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1793 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1795 if (qc->dbIndex == m_refchart_dbIndex) {
1801 if (!bf && m_pcandidate_array->GetCount() &&
1802 (m_reference_type != CHART_TYPE_CM93COMP)) {
1803 m_lost_refchart_dbIndex = m_refchart_dbIndex;
1804 int candidate_ref_index = GetNewRefChart();
1805 if (m_refchart_dbIndex != candidate_ref_index) {
1806 m_refchart_dbIndex = candidate_ref_index;
1807 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1812 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1813 if (m_pcandidate_array->GetCount()) {
1814 m_refchart_dbIndex =
1815 m_pcandidate_array->Item(m_pcandidate_array->GetCount() - 1)
1817 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1822 if ((-1 != m_lost_refchart_dbIndex) &&
1823 (m_lost_refchart_dbIndex != m_refchart_dbIndex)) {
1826 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1827 if (m_lost_refchart_dbIndex == m_extended_stack_array[ir]) {
1828 m_refchart_dbIndex = m_lost_refchart_dbIndex;
1829 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1830 m_lost_refchart_dbIndex = -1;
1836 bool b_has_overlays =
false;
1839 if (CHART_FAMILY_VECTOR == m_reference_family) {
1840 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1844 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1845 b_has_overlays =
true;
1858 const LLRegion cvp_region = vp_local.GetLLRegion(vp_local.rv_rect);
1859 LLRegion vp_region = cvp_region;
1865 for (ir = 0; ir < m_pcandidate_array->GetCount();
1869 if (pqc->dbIndex == m_refchart_dbIndex) {
1878 const double z = 111274.96299695622;
1884 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1886 LLRegion vpu_region(cvp_region);
1889 LLRegion &chart_region = pqc_ref->GetReducedCandidateRegion(factor);
1891 if (cte_ref.GetChartType() != CHART_TYPE_MBTILES) {
1892 if (!chart_region.Empty()) {
1893 vpu_region.Intersect(chart_region);
1895 if (vpu_region.Empty())
1896 pqc_ref->b_include =
false;
1898 pqc_ref->b_include =
true;
1899 vp_region.Subtract(chart_region);
1902 pqc_ref->b_include =
false;
1904 pqc_ref->b_include =
false;
1909 if (!vp_region.Empty()) {
1910 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1913 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
1920 if (CHART_FAMILY_VECTOR == m_reference_family) {
1921 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1927 if (CHART_TYPE_MBTILES == cte.GetChartType()) {
1928 pqc->b_include =
false;
1932 if (cte.Scale_ge(m_reference_scale)) {
1936 bool b_in_noshow =
false;
1937 for (
unsigned int ins = 0;
1938 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
1939 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
1949 LLRegion vpu_region(cvp_region);
1952 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
1954 if (!chart_region.Empty()) {
1955 vpu_region.Intersect(chart_region);
1957 if (vpu_region.Empty())
1958 pqc->b_include =
false;
1960 pqc->b_include =
true;
1961 vp_region.Subtract(chart_region);
1964 pqc->b_include =
false;
1966 pqc->b_include =
true;
1970 pqc->b_include =
false;
1973 if (vp_region.Empty())
1980 if (b_has_overlays && (CHART_FAMILY_VECTOR == m_reference_family)) {
1981 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1984 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
1988 if (cte.Scale_ge(m_reference_scale)) {
1989 bool b_in_noshow =
false;
1990 for (
unsigned int ins = 0;
1991 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
1992 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2002 LLRegion vpu_region(cvp_region);
2005 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2007 if (!chart_region.Empty()) vpu_region.Intersect(chart_region);
2009 if (vpu_region.Empty())
2010 pqc->b_include =
false;
2013 s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2014 if (b_overlay) pqc->b_include =
true;
2021 ChartData->GetChartTableEntry(m_refchart_dbIndex);
2022 if (s57chart::IsCellOverlayType(cte_ref.GetFullSystemPath())) {
2023 pqc->b_include =
true;
2035 m_eclipsed_stack_array.clear();
2037 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2040 if (!pqc->b_include) {
2042 if (cte.Scale_ge(m_reference_scale) &&
2043 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
2044 m_eclipsed_stack_array.push_back(pqc->dbIndex);
2045 pqc->b_eclipsed =
true;
2052 if (((m_bquiltanyproj || m_quilt_proj == PROJECTION_MERCATOR)) &&
2053 !vp_region.Empty()) {
2054 bool b_must_add_cm93 =
true;
2061 while( updd .HaveRects()) {
2062 wxRect rect = updd.GetRect();
2063 if( ( rect.width > 2 ) && ( rect.height > 2 ) ) {
2064 b_must_add_cm93 =
true;
2071 if (b_must_add_cm93) {
2072 for (
int ics = 0; ics < m_parent->GetpCurrentStack()->nEntry; ics++) {
2073 int i = m_parent->GetpCurrentStack()->GetDBIndex(ics);
2074 if (CHART_TYPE_CM93COMP ==
ChartData->GetDBChartType(i)) {
2077 qcnew->SetScale(
ChartData->GetDBChartScale(i));
2079 m_pcandidate_array->Add(qcnew);
2090 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
2092 if (pqc->b_include) {
2098 if (!b_vis && m_pcandidate_array->GetCount()) {
2101 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2106 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2109 if (cte.GetChartType() == CHART_TYPE_MBTILES)
continue;
2112 LLRegion vpck_region(vp_local.GetBBox());
2115 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2117 if (!chart_region.Empty()) vpck_region.Intersect(chart_region);
2119 if (!vpck_region.Empty()) {
2121 if (cte.Scale_eq(add_scale)) {
2122 pqc->b_include =
true;
2125 pqc->b_include =
true;
2126 add_scale = cte.GetScale();
2135 m_PatchList.DeleteContents(
true);
2136 m_PatchList.Clear();
2138 if (m_pcandidate_array->GetCount()) {
2139 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2147 if (m.GetChartType() == CHART_TYPE_CM93COMP)
2148 pqc->b_include =
true;
2151 if (pqc->b_include) {
2153 pqp->dbIndex = pqc->dbIndex;
2154 pqp->ProjType = m.GetChartProjectionType();
2157 pqp->quilt_region = pqc->GetCandidateRegion();
2160 pqp->b_Valid =
true;
2162 m_PatchList.Append(pqp);
2169 if (!m_bquiltanyproj) {
2171 m_quilt_proj = PROJECTION_MERCATOR;
2172 ChartBase *ppc = GetLargestScaleChart();
2173 if (ppc) m_quilt_proj = ppc->GetChartProjectionType();
2177 if (!m_bquiltanyproj) {
2180 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2181 wxPatchListNode *pcinode = m_PatchList.Item(i);
2183 if ((piqp->ProjType != m_quilt_proj) &&
2184 (piqp->ProjType != PROJECTION_UNKNOWN))
2185 piqp->b_Valid =
false;
2190 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2191 wxPatchListNode *pcinode = m_PatchList.Item(i);
2193 for (
unsigned int ins = 0;
2194 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2195 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2198 piqp->b_Valid =
false;
2206 m_covered_region.Clear();
2211 bool b_skipCM93 =
false;
2212 if (m_reference_type == CHART_TYPE_CM93COMP) {
2214 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2215 wxPatchListNode *pcinode = m_PatchList.Item(i);
2222 if (m.GetChartType() == CHART_TYPE_CM93COMP) {
2224 piqp->ActiveRegion = piqp->quilt_region;
2225 piqp->ActiveRegion.Intersect(cvp_region);
2229 m_covered_region.Union(piqp->quilt_region);
2239 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2240 wxPatchListNode *pcinode = m_PatchList.Item(i);
2248 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2252 piqp->ActiveRegion = piqp->quilt_region;
2255 if (!b_has_overlays && m_PatchList.GetCount() < 25)
2256 piqp->ActiveRegion.Subtract(m_covered_region);
2258 piqp->ActiveRegion.Intersect(cvp_region);
2262 if (piqp->ActiveRegion.Empty() && (piqp->dbIndex != m_refchart_dbIndex))
2263 piqp->b_eclipsed =
true;
2266 piqp->b_overlay =
false;
2267 if (cte.GetChartFamily() == CHART_FAMILY_VECTOR) {
2268 piqp->b_overlay = s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2271 if (!piqp->b_overlay) m_covered_region.Union(piqp->quilt_region);
2276 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2277 wxPatchListNode *pcinode = m_PatchList.Item(i);
2286 LLRegion vpr_region = piqp->quilt_region;
2294 for (
unsigned int k = i + 1; k < m_PatchList.GetCount(); k++) {
2295 wxPatchListNode *pnode = m_PatchList.Item(k);
2316 if (!b_has_overlays) {
2317 if (!vpr_region.Empty()) {
2319 ChartData->GetChartTableEntry(pqp->dbIndex);
2320 LLRegion larger_scale_chart_region =
2323 vpr_region.Subtract(larger_scale_chart_region);
2332 wxPatchListNode *pinode = m_PatchList.Item(i);
2334 pqpi->ActiveRegion = vpr_region;
2343 if (pqpi->ActiveRegion.Empty()) pqpi->b_eclipsed =
true;
2351 m_covered_region.Union(pqpi->ActiveRegion);
2358 unsigned int il = 0;
2359 while (il < m_PatchList.GetCount()) {
2360 wxPatchListNode *pcinode = m_PatchList.Item(il);
2362 if (piqp->b_eclipsed) {
2365 bool b_noadd =
false;
2366 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size(); ir++) {
2367 if (piqp->dbIndex == m_eclipsed_stack_array[ir]) {
2372 if (!b_noadd) m_eclipsed_stack_array.push_back(piqp->dbIndex);
2374 m_PatchList.DeleteNode(pcinode);
2393 m_parent->EnablePaint(
false);
2400 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2402 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2403 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2404 ChartData->LockCacheChart(pqc->dbIndex);
2409 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2411 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2412 if (!
ChartData->IsChartLocked(pqc->dbIndex))
2413 ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
true);
2422 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2424 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2425 if (
ChartData->IsChartLocked(pqc->dbIndex))
2426 pqc->b_locked =
true;
2428 pqc->b_locked =
ChartData->LockCacheChart(pqc->dbIndex);
2433 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2435 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2441 if (
ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
2443 pqc->b_locked =
true;
2448 m_parent->EnablePaint(
true);
2451 m_last_index_array = m_index_array;
2453 m_index_array.clear();
2456 unsigned int kl = m_PatchList.GetCount();
2457 for (
unsigned int k = 0; k < kl; k++) {
2458 wxPatchListNode *cnode = m_PatchList.Item((kl - k) - 1);
2459 m_index_array.push_back(cnode->GetData()->dbIndex);
2460 cnode = cnode->GetNext();
2466 m_quilt_depth_unit =
"";
2469 m_quilt_depth_unit = pc->GetDepthUnits();
2471 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2472 int units = ps52plib->m_nDepthUnitDisplay;
2475 m_quilt_depth_unit =
"Feet";
2478 m_quilt_depth_unit =
"Meters";
2481 m_quilt_depth_unit =
"Fathoms";
2487 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2488 wxPatchListNode *pnode = m_PatchList.Item(k);
2496 wxString du = pc->GetDepthUnits();
2497 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2498 int units = ps52plib->m_nDepthUnitDisplay;
2511 wxString dul = du.Lower();
2512 wxString ml = m_quilt_depth_unit.Lower();
2516 if (dul.StartsWith(
"meters") && ml.StartsWith(
"meters"))
2518 else if (dul.StartsWith(
"metres") && ml.StartsWith(
"metres"))
2520 else if (dul.StartsWith(
"fathoms") && ml.StartsWith(
"fathoms"))
2522 else if (dul.StartsWith(
"met") && ml.StartsWith(
"met"))
2526 m_quilt_depth_unit =
"";
2536 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2537 wxPatchListNode *pnode = m_PatchList.Item(k);
2541 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2542 wxLogMessage(
" Quilt Compose cache miss...");
2543 ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
2544 if (!
ChartData->IsChartInCache(pqp->dbIndex)) {
2545 wxLogMessage(
" Oops, removing from quilt...");
2546 pqp->b_Valid =
false;
2553 if (!
ChartData->IsChartInCache(m_refchart_dbIndex))
2554 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
2560 m_bquilt_has_overlays =
false;
2561 m_max_error_factor = 0.;
2562 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2563 wxPatchListNode *pnode = m_PatchList.Item(k);
2571 m_max_error_factor =
2572 wxMax(m_max_error_factor, pc->GetChart_Error_Factor());
2573 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2574 bool isOverlay = IsChartS57Overlay(pqp->dbIndex);
2575 pqp->b_overlay = isOverlay;
2576 if (isOverlay) m_bquilt_has_overlays =
true;
2589 unsigned long xa_hash = 5381;
2590 for (
unsigned int im = 0; im < m_extended_stack_array.size(); im++) {
2591 int dbindex = m_extended_stack_array[im];
2592 xa_hash = ((xa_hash << 5) + xa_hash) + dbindex;
2595 m_xa_hash = xa_hash;
2603 if (!m_bcomposed)
return;
2607 if (GetnCharts() && !m_bbusy && !chart_region.Empty()) {
2613 if (!(chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2614 vp.b_MercatorProjectionOverride)) {
2618 chart_region, pqp->ActiveRegion, chart->GetNativeScale());
2619 if (!get_screen_region.Empty())
2620 rendered_region.Union(get_screen_region);
2623 chart = GetNextChart();
2627 m_rendered_region = rendered_region;
2632bool Quilt::RenderQuiltRegionViewOnDCNoText(wxMemoryDC &dc,
ViewPort &vp,
2634 return DoRenderQuiltRegionViewOnDC(dc, vp, chart_region);
2637bool Quilt::RenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
2639 return DoRenderQuiltRegionViewOnDCTextOnly(dc, vp, chart_region);
2642bool Quilt::DoRenderQuiltRegionViewOnDC(wxMemoryDC &dc,
ViewPort &vp,
2644#ifdef ocpnUSE_DIBSECTION
2650 if (!m_bcomposed)
return false;
2654 if (GetnCharts() && !m_bbusy) {
2662 int chartsDrawn = 0;
2664 if (!chart_region.Empty()) {
2666 bool okToRender =
true;
2668 if (chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2669 vp.b_MercatorProjectionOverride)
2673 chart = GetNextChart();
2678 bool b_chart_rendered =
false;
2679 LLRegion get_region = pqp->ActiveRegion;
2682 chart_region, get_region, chart->GetNativeScale());
2683 if (!get_screen_region.Empty()) {
2684 if (!pqp->b_overlay) {
2685 if (chart->GetChartType() == CHART_TYPE_CM93COMP) {
2687 chart->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2691 if (Chs57->m_RAZBuilt) {
2692 b_chart_rendered = Chs57->RenderRegionViewOnDCNoText(
2693 tmp_dc, vp, get_screen_region);
2699 b_chart_rendered = ChPI->RenderRegionViewOnDCNoText(
2700 tmp_dc, vp, get_screen_region);
2702 b_chart_rendered = chart->RenderRegionViewOnDC(
2703 tmp_dc, vp, get_screen_region);
2705 b_chart_rendered =
true;
2712 screen_region.Subtract(get_screen_region);
2717 while (upd.HaveRects()) {
2718 wxRect rect = upd.GetRect();
2719 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc, rect.x,
2720 rect.y, wxCOPY,
true);
2724 tmp_dc.SelectObject(wxNullBitmap);
2726 if (b_chart_rendered) rendered_region.Union(get_screen_region);
2730 chart = GetNextChart();
2734 if (!chartsDrawn) m_parent->GetVP().SetProjectionType(PROJECTION_MERCATOR);
2737 if (m_bquilt_has_overlays && !chart_region.Empty()) {
2738 chart = GetFirstChart();
2742 if (pqp->b_overlay) {
2743 LLRegion get_region = pqp->ActiveRegion;
2745 chart_region, get_region, chart->GetNativeScale());
2746 if (!get_region.Empty()) {
2749 Chs57->RenderOverlayRegionViewOnDC(tmp_dc, vp,
2755 ChPI->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2760 while (upd.HaveRects()) {
2761 wxRect rect = upd.GetRect();
2762 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc,
2763 rect.x, rect.y, wxCOPY,
true);
2766 tmp_dc.SelectObject(wxNullBitmap);
2771 chart = GetNextChart();
2778 while (clrit.HaveRects()) {
2779 wxRect rect = clrit.GetRect();
2781 dc.SetPen(*wxBLACK_PEN);
2782 dc.SetBrush(*wxBLACK_BRUSH);
2783 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
2785 dc.Blit(rect.x, rect.y, rect.width, rect.height, &dc, rect.x, rect.y,
2792 if (m_nHiLiteIndex >= 0) {
2795 wxRect box = hiregion.GetBox();
2797 if (!box.IsEmpty()) {
2800 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2801 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2808 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2812 q_dc.SelectObject(*m_pBM);
2813 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2814 q_dc.SelectObject(wxNullBitmap);
2819 wxBitmap hl_mask_bm(vp.rv_rect.width, vp.rv_rect.height, 1);
2821 mdc.SelectObject(hl_mask_bm);
2822 mdc.SetBackground(*wxBLACK_BRUSH);
2824 mdc.SetClippingRegion(box);
2825 mdc.SetBackground(*wxWHITE_BRUSH);
2827 mdc.SelectObject(wxNullBitmap);
2829 if (hl_mask_bm.IsOk()) {
2830 wxMask *phl_mask =
new wxMask(hl_mask_bm);
2831 m_pBM->SetMask(phl_mask);
2832 q_dc.SelectObject(*m_pBM);
2835 wxBitmap rbm(vp.rv_rect.width, vp.rv_rect.height);
2836 wxMask *pr_mask =
new wxMask(hl_mask_bm);
2838 rbm.SetMask(pr_mask);
2839 rdc.SelectObject(rbm);
2840 unsigned char hlcolor = 255;
2841 switch (global_color_scheme) {
2842 case GLOBAL_COLOR_SCHEME_DAY:
2845 case GLOBAL_COLOR_SCHEME_DUSK:
2848 case GLOBAL_COLOR_SCHEME_NIGHT:
2856 rdc.SetBackground(wxBrush(wxColour(hlcolor, 0, 0)));
2860 while (upd.HaveRects()) {
2861 wxRect rect = upd.GetRect();
2862 rdc.Blit(rect.x, rect.y, rect.width, rect.height, &q_dc, rect.x,
2863 rect.y, wxOR,
true);
2868 while (updq.HaveRects()) {
2869 wxRect rect = updq.GetRect();
2870 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &rdc, rect.x,
2871 rect.y, wxCOPY,
true);
2875 q_dc.SelectObject(wxNullBitmap);
2876 m_pBM->SetMask(NULL);
2879 dc.SelectObject(*m_pBM);
2882 rdc.SelectObject(wxNullBitmap);
2888 if (g_fog_overzoom) {
2891 if (scale_factor > g_overzoom_emphasis_base) {
2892 float fog = ((scale_factor - g_overzoom_emphasis_base) * 255.) / 20.;
2893 fog = wxMin(fog, 200.);
2897 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2898 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2905 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2909 q_dc.SelectObject(*m_pBM);
2910 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2911 q_dc.SelectObject(wxNullBitmap);
2913 wxImage src = m_pBM->ConvertToImage();
2916 wxMin((scale_factor - g_overzoom_emphasis_base) / 4, 4);
2918 wxImage dest = src.Blur(blur_factor);
2922 unsigned char *bg = src.GetData();
2923 wxColour color = m_parent->GetFogColor();
2925 float transparency = fog;
2928 wxImage dest(vp.rv_rect.width, vp.rv_rect.height);
2929 unsigned char *dest_data = (
unsigned char *) malloc( vp.rv_rect.width * vp.rv_rect.height * 3 *
sizeof(
unsigned char) );
2930 unsigned char *d = dest_data;
2932 float alpha = 1.0 - (float)transparency / 255.0;
2933 int sb = vp.rv_rect.width * vp.rv_rect.height;
2934 for(
int i = 0; i < sb; i++ ) {
2937 int r = ( ( *bg++ ) * a ) + (1.0-a) * color.Red();
2939 int g = ( ( *bg++ ) * a ) + (1.0-a) * color.Green();
2941 int b = ( ( *bg++ ) * a ) + (1.0-a) * color.Blue();
2945 dest.SetData( dest_data );
2950 ddc.SelectObject(dim);
2952 q_dc.SelectObject(*m_pBM);
2954 while (upd.HaveRects()) {
2955 wxRect rect = upd.GetRect();
2956 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &ddc, rect.x,
2961 ddc.SelectObject(wxNullBitmap);
2962 q_dc.SelectObject(wxNullBitmap);
2965 dc.SelectObject(*m_pBM);
2973 SubstituteClearDC(dc, vp);
2977 SubstituteClearDC(dc, vp);
2981 m_rendered_region = rendered_region;
2987void Quilt::SubstituteClearDC(wxMemoryDC &dc,
ViewPort &vp) {
2989 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2990 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2996 if (NULL == m_pBM) {
2997 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
3000 dc.SelectObject(wxNullBitmap);
3001 dc.SelectObject(*m_pBM);
3002 dc.SetBackground(*wxBLACK_BRUSH);
3004 m_covered_region.Clear();
3007bool Quilt::DoRenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
3009 if (!m_bcomposed)
return false;
3013 if (GetnCharts() && !m_bbusy) {
3018 ChartBase *chart = GetLargestScaleChart();
3025 Chs57->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3029 ChPI->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
3034 chart = GetNextSmallerScaleChart();
3038 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.