32#include "ocpn_pixel.h"
34#ifdef __OCPN__ANDROID__
35 #include "androidUTIL.h"
41#include <wx/listimpl.cpp>
42WX_DEFINE_LIST(PatchList);
45extern s52plib *ps52plib;
46extern ColorScheme global_color_scheme;
47extern int g_chart_zoom_modifier_raster;
48extern int g_chart_zoom_modifier_vector;
49extern bool g_fog_overzoom;
50extern double g_overzoom_emphasis_base;
61#ifndef __OCPN__ANDROID__
62#define GetChartTableEntry(i) GetChartTable()[i]
71#define NOCOVR_PLY_PERF_LIMIT 500
72#define AUX_PLY_PERF_LIMIT 500
74static int CompareScales(
int i1,
int i2) {
75 if (!ChartData)
return 0;
80 if (cte1.Scale_eq(cte2.GetScale())) {
82 lat1 = cte1.GetLatMax();
83 lat2 = cte2.GetLatMax();
84 if (roundf(lat1 * 100.) == roundf(lat2 * 100.)) {
86 lon1 = cte1.GetLonMin();
87 lon2 = cte2.GetLonMin();
91 return (lon1 < lon2) ? -1 : 1;
93 return (lat1 < lat2) ? 1 : -1;
95 return cte1.GetScale() - cte2.GetScale();
97static bool CompareScalesStd(
int i1,
int i2) {
98 return CompareScales(i1, i2) < 0;
103 if (!ChartData)
return 0;
104 return CompareScales(qc1->dbIndex, qc2->dbIndex);
107const LLRegion &QuiltCandidate::GetCandidateRegion() {
109 LLRegion &candidate_region =
110 const_cast<LLRegion &
>(cte.quilt_candidate_region);
112 if (!candidate_region.Empty())
return candidate_region;
114 LLRegion world_region(-90, -180, 90, 180);
118 if (ChartData->GetDBChartType(dbIndex) == CHART_TYPE_CM93COMP) {
119 double cm93_ll_bounds[8] = {-80, -180, -80, 180, 80, 180, 80, -180};
120 candidate_region = LLRegion(4, cm93_ll_bounds);
121 return candidate_region;
125 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
126 if (nAuxPlyEntries >= 1) {
127 candidate_region.Clear();
128 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
129 float *pfp = cte.GetpAuxPlyTableEntry(ip);
130 int nAuxPly = cte.GetAuxCntTableEntry(ip);
132 candidate_region.Union(LLRegion(nAuxPly, pfp));
145 std::vector<float> vec = ChartData->GetReducedPlyPoints(dbIndex);
147 std::vector<float> vecr;
148 for (
size_t i = 0; i < vec.size() / 2; i++) {
149 float a = vec[i * 2 + 1];
155 std::vector<float>::iterator it = vecr.begin();
157 if (vecr.size() / 2 >= 3) {
160 candidate_region = LLRegion(vecr.size() / 2, (
float *)&(*it));
162 candidate_region = world_region;
166 if (!candidate_region
168 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
169 if (nNoCovrPlyEntries) {
170 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
171 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
172 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
174 LLRegion t_region = LLRegion(nNoCovrPly, pfp);
181 if (!t_region.Empty()) {
182 LLRegion test_region = candidate_region;
183 test_region.Subtract(t_region);
185 if (!test_region.Empty()) candidate_region = test_region;
195 if ((cte.GetScale() > 90000000) &&
196 (cte.GetChartFamily() == CHART_FAMILY_RASTER))
197 candidate_region = world_region;
199 return candidate_region;
202LLRegion &QuiltCandidate::GetReducedCandidateRegion(
double factor) {
203 if (factor != last_factor) {
204 reduced_candidate_region = GetCandidateRegion();
205 reduced_candidate_region.Reduce(factor);
206 last_factor = factor;
209 return reduced_candidate_region;
212void QuiltCandidate::SetScale(
int scale) {
216 if (
scale >= 1000) rounding = 5 * pow(10, log10(
scale) - 2);
225 m_reference_scale = 1;
226 m_refchart_dbIndex = -1;
227 m_reference_type = CHART_TYPE_UNKNOWN;
228 m_reference_family = CHART_FAMILY_UNKNOWN;
229 m_quilt_proj = PROJECTION_UNKNOWN;
231 m_lost_refchart_dbIndex = -1;
241 new ArrayOfSortedQuiltCandidates(CompareQuiltCandidateScales);
246 m_preferred_family = CHART_FAMILY_RASTER;
249 m_bquiltskew = g_bopengl;
251 m_bquiltanyproj = g_bopengl;
255 m_PatchList.DeleteContents(
true);
258 EmptyCandidateArray();
259 delete m_pcandidate_array;
261 m_extended_stack_array.clear();
266bool Quilt::IsVPBlittable(
ViewPort &VPoint,
int dx,
int dy,
267 bool b_allow_vector) {
268 if (!m_vp_rendered.IsValid())
return false;
271 VPoint.GetDoublePixFromLL(m_vp_rendered.clat, m_vp_rendered.clon);
272 wxPoint2DDouble p2 = VPoint.GetDoublePixFromLL(VPoint.clat, VPoint.clon);
273 double deltax = p2.m_x - p1.m_x;
274 double deltay = p2.m_y - p1.m_y;
276 if ((fabs(deltax - dx) > 1e-2) || (fabs(deltay - dy) > 1e-2))
return false;
281bool Quilt::IsChartS57Overlay(
int db_index) {
282 if (db_index < 0)
return false;
285 if (CHART_FAMILY_VECTOR == cte.GetChartFamily()) {
286 return s57chart::IsCellOverlayType(cte.GetFullSystemPath());
291bool Quilt::IsChartQuiltableRef(
int db_index) {
292 if (db_index < 0 || db_index > ChartData->GetChartTableEntries() - 1)
298 bool bproj_match =
true;
300 double skew_norm = ctei.GetChartSkew();
301 if (skew_norm > 180.) skew_norm -= 360.;
304 fabs(skew_norm) < 1.;
305 if (m_bquiltskew) skew_match =
true;
308 bool b_noshow =
false;
309 for (
unsigned int i = 0; i < m_parent->GetQuiltNoshowIindexArray().size();
311 if (m_parent->GetQuiltNoshowIindexArray()[i] ==
319 return (bproj_match & skew_match & !b_noshow);
322bool Quilt::IsChartInQuilt(
ChartBase *pc) {
324 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
326 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
327 if (ChartData->OpenChartFromDB(pqc->dbIndex, FULL_INIT) == pc)
334bool Quilt::IsChartInQuilt(wxString &full_path) {
336 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
338 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
340 if (pcte->GetpsFullPath()->IsSameAs(full_path))
return true;
346std::vector<int> Quilt::GetCandidatedbIndexArray(
bool from_ref_chart,
347 bool exclude_user_hidden) {
348 std::vector<int> ret;
349 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
353 if (pqc->Scale_ge(m_reference_scale)) {
355 if (exclude_user_hidden) {
356 bool b_noshow =
false;
357 for (
unsigned int i = 0;
358 i < m_parent->GetQuiltNoshowIindexArray().size(); i++) {
359 if (m_parent->GetQuiltNoshowIindexArray()[i] ==
366 if (!b_noshow) ret.push_back(pqc->dbIndex);
368 ret.push_back(pqc->dbIndex);
372 ret.push_back(pqc->dbIndex);
379 return (cnode->GetData());
384void Quilt::EmptyCandidateArray(
void) {
385 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
386 delete m_pcandidate_array->Item(i);
389 m_pcandidate_array->Clear();
393 if (!ChartData)
return NULL;
395 if (!ChartData->IsValid())
399 if (!m_bcomposed)
return NULL;
401 if (m_bbusy)
return NULL;
405 cnode = m_PatchList.GetFirst();
406 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetNext();
407 if (cnode && cnode->GetData()->b_Valid)
408 pret = ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
415 if (!ChartData)
return NULL;
417 if (!ChartData->IsValid())
return NULL;
419 if (m_bbusy)
return NULL;
424 cnode = cnode->GetNext();
425 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetNext();
426 if (cnode && cnode->GetData()->b_Valid)
427 pret = ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
434ChartBase *Quilt::GetNextSmallerScaleChart() {
435 if (!ChartData)
return NULL;
437 if (!ChartData->IsValid())
return NULL;
439 if (m_bbusy)
return NULL;
444 cnode = cnode->GetPrevious();
445 while (cnode && !cnode->GetData()->b_Valid) cnode = cnode->GetPrevious();
446 if (cnode && cnode->GetData()->b_Valid)
447 pret = ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
454ChartBase *Quilt::GetLargestScaleChart() {
455 if (!ChartData)
return NULL;
457 if (m_bbusy)
return NULL;
461 cnode = m_PatchList.GetLast();
463 pret = ChartData->OpenChartFromDB(cnode->GetData()->dbIndex, FULL_INIT);
470 LLRegion chart_region;
471 LLRegion screen_region(vp.GetBBox());
476 if (fabs(cte.GetLonMax() - cte.GetLonMin()) > 180.) {
493 return LLRegion(-80, vp.GetBBox().GetMinLon(), 80,
494 vp.GetBBox().GetMaxLon());
498 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
499 bool aux_ply_skipped =
false;
500 if (nAuxPlyEntries >= 1) {
501 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
502 int nAuxPly = cte.GetAuxCntTableEntry(ip);
503 if (nAuxPly > AUX_PLY_PERF_LIMIT) {
506 aux_ply_skipped =
true;
509 float *pfp = cte.GetpAuxPlyTableEntry(ip);
510 LLRegion t_region(nAuxPly, pfp);
511 t_region.Intersect(screen_region);
515 if (!t_region.Empty()) chart_region.Union(t_region);
519 if (aux_ply_skipped || nAuxPlyEntries == 0) {
520 int n_ply_entries = cte.GetnPlyEntries();
521 float *pfp = cte.GetpPlyTable();
523 if (n_ply_entries >= 3)
526 LLRegion t_region(n_ply_entries, pfp);
527 t_region.Intersect(screen_region);
531 if (!t_region.Empty()) chart_region.Union(t_region);
534 chart_region = screen_region;
538 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
539 if (nNoCovrPlyEntries) {
540 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
541 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
542 if (nNoCovrPly > NOCOVR_PLY_PERF_LIMIT) {
547 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
549 LLRegion t_region(nNoCovrPly, pfp);
550 t_region.Intersect(screen_region);
561 if (!t_region.Empty()) {
562 LLRegion test_region = chart_region;
563 test_region.Subtract(t_region);
565 if (!test_region.Empty()) chart_region = test_region;
574 if ((cte.GetScale() > 90000000) &&
575 (cte.GetChartFamily() == CHART_FAMILY_RASTER))
576 chart_region = screen_region;
584bool Quilt::IsQuiltVector(
void) {
585 if (m_bbusy)
return false;
591 wxPatchListNode *cnode = m_PatchList.GetFirst();
593 if (cnode->GetData()) {
596 if ((pqp->b_Valid) && (!pqp->b_eclipsed) &&
597 (pqp->dbIndex < ChartData->GetChartTableEntries())) {
599 ChartData->GetChartTableEntry(pqp->dbIndex);
601 if (ctei.GetChartFamily() == CHART_FAMILY_VECTOR) {
607 cnode = cnode->GetNext();
614bool Quilt::DoesQuiltContainPlugins(
void) {
615 if (m_bbusy)
return false;
621 wxPatchListNode *cnode = m_PatchList.GetFirst();
623 if (cnode->GetData()) {
626 if ((pqp->b_Valid) && (!pqp->b_eclipsed)) {
628 ChartData->GetChartTableEntry(pqp->dbIndex);
630 if (ctei.GetChartType() == CHART_TYPE_PLUGIN) {
636 cnode = cnode->GetNext();
643int Quilt::GetChartdbIndexAtPix(
ViewPort &VPoint, wxPoint p) {
644 if (m_bbusy)
return -1;
649 VPoint.GetLLFromPix(p, &lat, &lon);
653 wxPatchListNode *cnode = m_PatchList.GetFirst();
655 if (cnode->GetData()->ActiveRegion.Contains(lat, lon)) {
656 ret = cnode->GetData()->dbIndex;
659 cnode = cnode->GetNext();
667 if (m_bbusy)
return NULL;
672 VPoint.GetLLFromPix(p, &lat, &lon);
679 wxPatchListNode *cnode = m_PatchList.GetFirst();
682 if (!pqp->b_overlay && (pqp->ActiveRegion.Contains(lat, lon)))
683 if (ChartData->IsChartInCache(pqp->dbIndex)) {
684 pret = ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
686 cnode = cnode->GetNext();
694 if (m_bbusy)
return NULL;
699 VPoint.GetLLFromPix(p, &lat, &lon);
706 wxPatchListNode *cnode = m_PatchList.GetFirst();
709 if (pqp->b_overlay && (pqp->ActiveRegion.Contains(lat, lon)))
710 pret = ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
711 cnode = cnode->GetNext();
718void Quilt::InvalidateAllQuiltPatchs(
void) {
729std::vector<int> Quilt::GetQuiltIndexArray(
void) {
730 return m_index_array;
732 std::vector<int> ret;
734 if (m_bbusy)
return ret;
738 wxPatchListNode *cnode = m_PatchList.GetFirst();
740 ret.push_back(cnode->GetData()->dbIndex);
741 cnode = cnode->GetNext();
749bool Quilt::IsQuiltDelta(
ViewPort &vp) {
750 if (!m_vp_quilt.IsValid() || !m_bcomposed)
return true;
752 if (m_vp_quilt.view_scale_ppm != vp.view_scale_ppm)
return true;
754 if (m_vp_quilt.m_projection_type != vp.m_projection_type)
return true;
756 if (m_vp_quilt.rotation != vp.rotation)
return true;
759 wxPoint cp_last, cp_this;
761 cp_last = m_vp_quilt.GetPixFromLL(vp.clat, vp.clon);
762 cp_this = vp.GetPixFromLL(vp.clat, vp.clon);
764 return (cp_last != cp_this);
772 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
774 if (pRefChart) pRefChart->AdjustVP(vp_last, vp_proposed);
777double Quilt::GetRefNativeScale() {
778 double ret_val = 1.0;
780 ChartBase *pc = ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
781 if (pc) ret_val = pc->GetNativeScale();
787int Quilt::GetNewRefChart(
void) {
793 int new_ref_dbIndex = m_refchart_dbIndex;
794 unsigned int im = m_extended_stack_array.size();
796 for (
unsigned int is = 0; is < im; is++) {
798 ChartData->GetChartTableEntry(m_extended_stack_array[is]);
800 double skew_norm = m.GetChartSkew();
801 if (skew_norm > 180.) skew_norm -= 360.;
803 if ((m.Scale_ge(m_reference_scale)) &&
804 (m_reference_family == m.GetChartFamily()) &&
805 (m_bquiltanyproj || m_quilt_proj == m.GetChartProjectionType()) &&
806 (m_bquiltskew || (fabs(skew_norm) < 1.0))) {
807 new_ref_dbIndex = m_extended_stack_array[is];
812 return new_ref_dbIndex;
815int Quilt::GetNomScaleMax(
int scale, ChartTypeEnum type,
816 ChartFamilyEnum family) {
818 case CHART_FAMILY_RASTER: {
822 case CHART_FAMILY_VECTOR: {
832int Quilt::GetNomScaleMin(
int scale, ChartTypeEnum type,
833 ChartFamilyEnum family) {
834 double zoom_mod = (double)g_chart_zoom_modifier_raster;
836 if (family == CHART_FAMILY_VECTOR)
837 zoom_mod = (double)g_chart_zoom_modifier_vector;
839 double modf = zoom_mod / 5.;
840 double mod = pow(16., modf);
841 mod = wxMax(mod, .2);
842 mod = wxMin(mod, 16.0);
846 case CHART_FAMILY_RASTER: {
847 if (CHART_TYPE_MBTILES == type)
848 return scale * 4 * mod;
850 return scale * 1 * mod;
853 case CHART_FAMILY_VECTOR: {
854 return scale * 4 * mod;
858 mod = wxMin(mod, 2.0);
859 return scale * 2 * mod;
865 int index, nom, min, max;
868int Quilt::AdjustRefOnZoom(
bool b_zin, ChartFamilyEnum family,
869 ChartTypeEnum type,
double proposed_scale_onscreen) {
870 std::vector<scale> scales;
871 std::vector<scale> scales_mbtiles;
880 bool b_allow_fullscreen_ref =
881 (family == CHART_FAMILY_VECTOR) || b_zin || g_bopengl;
885 int smallest_scale = 1;
886 for (
size_t i = 0; i < m_extended_stack_array.size(); i++) {
887 int index = m_extended_stack_array[i];
888 if (ChartData->GetDBChartType(index) == type)
889 smallest_scale = wxMax(smallest_scale, ChartData->GetDBChartScale(index));
894 for (
size_t i = 0; i < m_extended_stack_array.size(); i++) {
895 int test_db_index = m_extended_stack_array[i];
897 if (b_allow_fullscreen_ref ||
898 m_parent->GetpCurrentStack()->DoesStackContaindbIndex(test_db_index)) {
899 if ((family == ChartData->GetDBChartFamily(test_db_index)) &&
900 IsChartQuiltableRef(test_db_index)
902 int nscale = ChartData->GetDBChartScale(test_db_index);
904 int nmax_scale = GetNomScaleMax(nscale, type, family);
908 if (0 == i_first) nmax_scale = 1;
910 int nmin_scale = GetNomScaleMin(nscale, type, family);
913 if((type == CHART_TYPE_KAP) && (nscale == smallest_scale))
916 if (CHART_TYPE_MBTILES == ChartData->GetDBChartType(test_db_index))
917 scales_mbtiles.push_back(
918 scale{test_db_index, nscale, nmin_scale, nmax_scale});
921 scale{test_db_index, nscale, nmin_scale, nmax_scale});
928 if (scales.empty()) scales = scales_mbtiles;
935 if (CHART_FAMILY_VECTOR == family) {
936 for (
size_t i = scales.size(); i; i--) {
937 int test_db_index = scales[i - 1].index;
938 if (type == ChartData->GetDBChartType(test_db_index)) {
939 scales[i - 1].min = scales[i - 1].nom * 80;
951 if (scales.size() > 1) {
952 for (
unsigned i = 0; i < scales.size() - 1; i++) {
953 int min_scale_test = wxMax(scales[i].min, scales[i + 1].max + 1);
954 min_scale_test = wxMin(min_scale_test, scales[i].min * 2);
955 scales[i].min = min_scale_test;
964 if (scales.size() > 2) {
965 for (
size_t i = scales.size() - 2; i >= 1; i--) {
966 scales[i].max = wxMin(scales[i].max, scales[i - 1].min - 1);
970 int new_ref_dbIndex = -1;
974 for (
size_t i = 0; i < scales.size(); i++) {
975 if ((proposed_scale_onscreen <
978 (proposed_scale_onscreen > scales[i].max)) {
979 new_ref_dbIndex = scales[i].index;
984 return new_ref_dbIndex;
987int Quilt::AdjustRefOnZoomOut(
double proposed_scale_onscreen) {
989 m_lost_refchart_dbIndex = -1;
991 int current_db_index = m_refchart_dbIndex;
992 int current_family = m_reference_family;
993 ChartTypeEnum current_type = (ChartTypeEnum)m_reference_type;
995 if (m_refchart_dbIndex >= 0) {
997 ChartData->GetChartTableEntry(m_refchart_dbIndex);
998 current_family = cte.GetChartFamily();
999 current_type = (ChartTypeEnum)cte.GetChartType();
1002 if (current_type == CHART_TYPE_CM93COMP)
return current_db_index;
1004 int proposed_ref_index =
1005 AdjustRefOnZoom(
false, (ChartFamilyEnum)current_family, current_type,
1006 proposed_scale_onscreen);
1009 if (proposed_ref_index < 0) {
1010 m_zout_family = current_family;
1011 m_zout_type = current_type;
1012 m_zout_dbindex = current_db_index;
1015 SetReferenceChart(proposed_ref_index);
1017 return proposed_ref_index;
1020int Quilt::AdjustRefOnZoomIn(
double proposed_scale_onscreen) {
1022 m_lost_refchart_dbIndex = -1;
1024 int current_db_index = m_refchart_dbIndex;
1025 int current_family = m_reference_family;
1026 ChartTypeEnum current_type = (ChartTypeEnum)m_reference_type;
1028 if (m_zout_family >= 0) {
1029 current_type = (ChartTypeEnum)m_zout_type;
1030 current_family = m_zout_family;
1036 if (current_type == CHART_TYPE_CM93COMP) {
1037 if (m_zout_family >= 0) {
1038 current_family = ChartData->GetDBChartFamily(m_zout_dbindex);
1040 return current_db_index;
1043 if ((-1 == m_refchart_dbIndex) && (m_zout_dbindex >= 0))
1044 BuildExtendedChartStackAndCandidateArray(m_zout_dbindex, m_vp_quilt);
1046 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, m_vp_quilt);
1048 int proposed_ref_index =
1049 AdjustRefOnZoom(
true, (ChartFamilyEnum)current_family, current_type,
1050 proposed_scale_onscreen);
1052 if (current_db_index == -1) {
1053 SetReferenceChart(proposed_ref_index);
1054 return proposed_ref_index;
1057 if (proposed_ref_index != -1) {
1058 if (ChartData->GetDBChartScale(current_db_index) >=
1059 ChartData->GetDBChartScale(proposed_ref_index)) {
1060 SetReferenceChart(proposed_ref_index);
1061 return proposed_ref_index;
1064 proposed_ref_index = current_db_index;
1066 SetReferenceChart(proposed_ref_index);
1068 return proposed_ref_index;
1071bool Quilt::IsChartSmallestScale(
int dbIndex) {
1072 if (!ChartData)
return false;
1076 int specified_type = ChartData->GetDBChartType(dbIndex);
1077 int target_dbindex = -1;
1079 unsigned int target_stack_index = 0;
1080 if (m_extended_stack_array.size()) {
1081 while ((target_stack_index <= (m_extended_stack_array.size() - 1))) {
1082 int test_db_index = m_extended_stack_array[target_stack_index];
1084 if (specified_type == ChartData->GetDBChartType(test_db_index))
1085 target_dbindex = test_db_index;
1087 target_stack_index++;
1090 return (dbIndex == target_dbindex);
1093LLRegion Quilt::GetHiliteRegion() {
1095 if (m_nHiLiteIndex >= 0) {
1097 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
1098 wxPatchListNode *pcinode = m_PatchList.Item(i);
1100 if ((m_nHiLiteIndex == piqp->dbIndex) && (piqp->b_Valid))
1102 r = piqp->ActiveRegion;
1109 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1111 if (m_nHiLiteIndex == pqc->dbIndex) {
1112 LLRegion chart_region = pqc->GetCandidateRegion();
1113 if (!chart_region.Empty()) {
1115 bool b_eclipsed =
false;
1116 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size();
1118 if (m_nHiLiteIndex == m_eclipsed_stack_array[ir]) {
1124 if (!b_eclipsed) r = chart_region;
1134 ChartData->GetChartTableEntry(m_nHiLiteIndex);
1135 if (cte.GetChartType() == CHART_TYPE_MBTILES) {
1136 r = GetTilesetRegion(m_nHiLiteIndex);
1143const LLRegion &Quilt::GetTilesetRegion(
int dbIndex) {
1144 LLRegion world_region(-90, -180, 90, 180);
1147 LLRegion &target_region =
const_cast<LLRegion &
>(cte.quilt_candidate_region);
1149 if (!target_region.Empty())
return target_region;
1152 int nAuxPlyEntries = cte.GetnAuxPlyEntries();
1153 if (nAuxPlyEntries >= 1) {
1154 target_region.Clear();
1155 for (
int ip = 0; ip < nAuxPlyEntries; ip++) {
1156 float *pfp = cte.GetpAuxPlyTableEntry(ip);
1157 int nAuxPly = cte.GetAuxCntTableEntry(ip);
1159 target_region.Union(LLRegion(nAuxPly, pfp));
1162 std::vector<float> vec = ChartData->GetReducedPlyPoints(dbIndex);
1164 std::vector<float> vecr;
1165 for (
size_t i = 0; i < vec.size() / 2; i++) {
1166 float a = vec[i * 2 + 1];
1172 std::vector<float>::iterator it = vecr.begin();
1174 if (vecr.size() / 2 >= 3) {
1177 target_region = LLRegion(vecr.size() / 2, (
float *)&(*it));
1179 target_region = world_region;
1183 if (!target_region.Empty()) {
1184 int nNoCovrPlyEntries = cte.GetnNoCovrPlyEntries();
1185 if (nNoCovrPlyEntries) {
1186 for (
int ip = 0; ip < nNoCovrPlyEntries; ip++) {
1187 float *pfp = cte.GetpNoCovrPlyTableEntry(ip);
1188 int nNoCovrPly = cte.GetNoCovrCntTableEntry(ip);
1190 LLRegion t_region = LLRegion(nNoCovrPly, pfp);
1197 if (!t_region.Empty()) {
1198 LLRegion test_region = target_region;
1199 test_region.Subtract(t_region);
1201 if (!test_region.Empty()) target_region = test_region;
1215 return target_region;
1218bool Quilt::BuildExtendedChartStackAndCandidateArray(
int ref_db_index,
1220 double zoom_test_val = .002;
1223 EmptyCandidateArray();
1224 m_extended_stack_array.clear();
1226 int reference_scale = 1e8;
1227 int reference_type = -1;
1228 int reference_family = -1;
1230 m_bquiltanyproj ? vp_in.m_projection_type : PROJECTION_UNKNOWN;
1232 if (ref_db_index >= 0) {
1234 ChartData->GetChartTableEntry(ref_db_index);
1235 reference_scale = cte_ref.GetScale();
1236 reference_type = cte_ref.GetChartType();
1237 if (!m_bquiltanyproj) quilt_proj = ChartData->GetDBChartProj(ref_db_index);
1238 reference_family = cte_ref.GetChartFamily();
1241 bool b_need_resort =
false;
1251 int n_charts = m_parent->GetpCurrentStack()->nEntry;
1255 for (
int ics = 0; ics < n_charts; ics++) {
1256 int istack = m_parent->GetpCurrentStack()->GetDBIndex(ics);
1257 if (istack < 0)
continue;
1258 m_extended_stack_array.push_back(istack);
1264 if (reference_type == CHART_TYPE_CM93COMP)
continue;
1274 if ((cte.GetChartType() == CHART_TYPE_PLUGIN) ||
1275 (reference_type == CHART_TYPE_PLUGIN)) {
1276 if (reference_family != cte.GetChartFamily()) {
1280 if (reference_type != cte.GetChartType()) {
1285 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1288 int candidate_chart_scale = cte.GetScale();
1289 double chart_native_ppm =
1290 m_canvas_scale_factor / (double)candidate_chart_scale;
1291 double zoom_factor = vp_local.view_scale_ppm / chart_native_ppm;
1292 if (zoom_factor < zoom_test_val){
1293 m_extended_stack_array.pop_back();
1297 double skew_norm = cte.GetChartSkew();
1298 if (skew_norm > 180.) skew_norm -= 360.;
1300 if ((m_bquiltskew ? 1 : fabs(skew_norm) < 1.0) &&
1301 (m_bquiltanyproj || cte.GetChartProjectionType() == quilt_proj)) {
1303 qcnew->dbIndex = istack;
1304 qcnew->SetScale(cte.GetScale());
1305 m_pcandidate_array->push_back(qcnew);
1333 int n_all_charts = ChartData->GetChartTableEntries();
1335 LLBBox viewbox = vp_local.GetBBox();
1336 int sure_index = -1;
1337 int sure_index_scale = 0;
1339 for (
int i = 0; i < n_all_charts; i++) {
1343 int groupIndex = m_parent->m_groupIndex;
1344 if ((groupIndex > 0) && (!ChartData->IsChartInGroup(i, groupIndex)))
1351#ifdef __OCPN__ANDROID__
1352 wxFileName fn(cte.GetFullSystemPath());
1353 if (!androidIsDirWritable( fn.GetPath()))
1357 if (reference_family != cte.GetChartFamily())
continue;
1359 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
1361 const LLBBox &chart_box = cte.GetBBox();
1362 if ((viewbox.IntersectOut(chart_box)))
continue;
1364 if (!m_bquiltanyproj && quilt_proj != cte.GetChartProjectionType())
1367 double skew_norm = cte.GetChartSkew();
1368 if (skew_norm > 180.) skew_norm -= 360.;
1370 if (!m_bquiltskew && fabs(skew_norm) > 1.0)
continue;
1373 int candidate_chart_scale = cte.GetScale();
1374 double chart_native_ppm =
1375 m_canvas_scale_factor / (double)candidate_chart_scale;
1376 double zoom_factor = vp_in.view_scale_ppm / chart_native_ppm;
1378 double zoom_factor_test = 0.2;
1382 if( CHART_TYPE_S57 == cte.GetChartType() ) {
1384 double chart_area = (cte.GetLonMax() - cte.GetLonMin()) *
1385 (cte.GetLatMax() - cte.GetLatMin());
1386 double quilt_area = viewbox.GetLonRange() * viewbox.GetLatRange();
1387 if ((chart_area / quilt_area) < .01)
1395 if (!cte.Scale_ge(reference_scale)) {
1396 if (cte.Scale_gt(sure_index_scale)) {
1398 sure_index_scale = candidate_chart_scale;
1407 if ((cte.Scale_ge(reference_scale) && (zoom_factor > zoom_test_val)) || (zoom_factor > zoom_factor_test)) {
1409 LLRegion cell_region = GetChartQuiltRegion(cte, vp_local);
1414 if (!cell_region.Empty()) {
1417 bool b_exists =
false;
1418 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1419 if (i == m_extended_stack_array[ir]) {
1432 bool b_noadd =
false;
1434 for (
unsigned int id = 0;
id < m_extended_stack_array.size();
id++) {
1435 if (m_extended_stack_array[
id] != -1) {
1437 ChartData->GetpChartTableEntry(m_extended_stack_array[
id]);
1438 bool bsameTime =
false;
1439 if (pm->GetFileTime() && pn->GetFileTime()) {
1440 if (labs(pm->GetFileTime() - pn->GetFileTime()) < 60)
1443 if (pm->GetChartEditionDate() == pn->GetChartEditionDate() )
1447 if (pn->GetpFileName()->IsSameAs(*(pm->GetpFileName())))
1454 m_extended_stack_array.push_back(i);
1459 candidate_chart_scale);
1461 m_pcandidate_array->push_back(qcnew);
1463 b_need_resort =
true;
1472 if (-1 != sure_index) {
1474 bool sure_exists =
false;
1475 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1476 if (sure_index == m_extended_stack_array[ir]) {
1484 m_extended_stack_array.push_back(sure_index);
1487 qcnew->dbIndex = sure_index;
1488 qcnew->SetScale(ChartData->GetDBChartScale(sure_index));
1489 m_pcandidate_array->push_back(qcnew);
1491 b_need_resort =
true;
1496 if (b_need_resort && m_extended_stack_array.size() > 1) {
1497 std::sort(m_extended_stack_array.begin(), m_extended_stack_array.end(),
1503int Quilt::AdjustRefSelection(
const ViewPort &vp_in) {
1508 if (!ChartData)
return false;
1518 vp_local.SetRotationAngle(0.);
1520 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1522 ChartFamilyEnum family = CHART_FAMILY_RASTER;
1523 ChartTypeEnum type = CHART_TYPE_KAP;
1526 if (m_refchart_dbIndex >= 0) {
1528 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1529 type = (ChartTypeEnum)cte_ref.GetChartType();
1530 family = (ChartFamilyEnum)cte_ref.GetChartFamily();
1533 int ret_index = AdjustRefOnZoom(
true, family, type, vp_in.chart_scale);
1538double Quilt::GetBestStartScale(
int dbi_ref_hint,
const ViewPort &vp_in) {
1539 if (!ChartData)
return vp_in.view_scale_ppm;
1543 return vp_in.view_scale_ppm;
1548 int tentative_ref_index = dbi_ref_hint;
1549 if (dbi_ref_hint < 0) {
1556 tentative_ref_index = m_parent->GetpCurrentStack()->GetDBIndex(0);
1563 vp_local.SetRotationAngle(0.);
1565 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1569 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1571 if (qc->dbIndex == tentative_ref_index) {
1577 if (!bf && m_pcandidate_array->GetCount()) {
1578 tentative_ref_index = GetNewRefChart();
1579 BuildExtendedChartStackAndCandidateArray(tentative_ref_index, vp_local);
1582 double proposed_scale_onscreen = vp_in.chart_scale;
1584 if (m_pcandidate_array->GetCount()) {
1585 m_refchart_dbIndex = tentative_ref_index;
1589 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1591 if (IsChartQuiltableRef(qc->dbIndex)) {
1592 m_refchart_dbIndex = qc->dbIndex;
1599 m_refchart_dbIndex = m_parent->GetpCurrentStack()->GetDBIndex(0);
1602 if (m_refchart_dbIndex >= 0) {
1605 ChartBase *pc = ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
1607 double min_ref_scale =
1608 pc->GetNormalScaleMin(m_parent->GetCanvasScaleFactor(),
false);
1609 double max_ref_scale = pc->GetNormalScaleMax(
1610 m_parent->GetCanvasScaleFactor(), m_canvas_width);
1611 if ((proposed_scale_onscreen >= min_ref_scale) &&
1612 (proposed_scale_onscreen <= max_ref_scale))
1613 return vp_in.view_scale_ppm;
1615 proposed_scale_onscreen = wxMin(proposed_scale_onscreen, max_ref_scale);
1616 proposed_scale_onscreen = wxMax(proposed_scale_onscreen, min_ref_scale);
1620 return m_parent->GetCanvasScaleFactor() / proposed_scale_onscreen;
1624 if (m_refchart_dbIndex >= 0 && ChartData)
1625 return ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
1629void Quilt::UnlockQuilt() {
1630 wxASSERT(m_bbusy ==
false);
1631 ChartData->UnLockCache();
1633 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1637 ChartData->UnLockCacheChart(pqc->dbIndex);
1638 pqc->b_locked =
false;
1644 if (!ChartData)
return false;
1650 if (!m_parent->GetpCurrentStack())
return false;
1652 if (m_bbusy)
return false;
1661 if (m_refchart_dbIndex >= 0) {
1663 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1664 m_reference_scale = cte_ref.GetScale();
1665 m_reference_type = cte_ref.GetChartType();
1666 if (!m_bquiltanyproj)
1667 m_quilt_proj = ChartData->GetDBChartProj(m_refchart_dbIndex);
1668 m_reference_family = cte_ref.GetChartFamily();
1672 if (!m_bquiltanyproj) vp_local.SetProjectionType(m_quilt_proj);
1679 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1718 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
1720 if (qc->dbIndex == m_refchart_dbIndex) {
1726 if (!bf && m_pcandidate_array->GetCount() &&
1727 (m_reference_type != CHART_TYPE_CM93COMP)) {
1728 m_lost_refchart_dbIndex = m_refchart_dbIndex;
1729 int candidate_ref_index = GetNewRefChart();
1730 if (m_refchart_dbIndex != candidate_ref_index) {
1731 m_refchart_dbIndex = candidate_ref_index;
1732 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1737 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1738 if (m_pcandidate_array->GetCount()) {
1739 m_refchart_dbIndex =
1740 m_pcandidate_array->Item(m_pcandidate_array->GetCount() - 1)
1742 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1747 if ((-1 != m_lost_refchart_dbIndex) &&
1748 (m_lost_refchart_dbIndex != m_refchart_dbIndex)) {
1751 for (
unsigned int ir = 0; ir < m_extended_stack_array.size(); ir++) {
1752 if (m_lost_refchart_dbIndex == m_extended_stack_array[ir]) {
1753 m_refchart_dbIndex = m_lost_refchart_dbIndex;
1754 BuildExtendedChartStackAndCandidateArray(m_refchart_dbIndex, vp_local);
1755 m_lost_refchart_dbIndex = -1;
1761 bool b_has_overlays =
false;
1764 if (CHART_FAMILY_VECTOR == m_reference_family) {
1765 for (
unsigned int ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1767 const ChartTableEntry &cte = ChartData->GetChartTableEntry(pqc->dbIndex);
1769 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1770 b_has_overlays =
true;
1783 const LLRegion cvp_region = vp_local.GetLLRegion(
1785 LLRegion vp_region = cvp_region;
1791 for (ir = 0; ir < m_pcandidate_array->GetCount();
1795 if (pqc->dbIndex == m_refchart_dbIndex) {
1804 const double z = 111274.96299695622;
1806 double factor = 8.0 / (vp_local.view_scale_ppm * z);
1810 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1812 LLRegion vpu_region(cvp_region);
1815 LLRegion &chart_region = pqc_ref->GetReducedCandidateRegion(factor);
1817 if (cte_ref.GetChartType() != CHART_TYPE_MBTILES) {
1818 if (!chart_region.Empty()) {
1819 vpu_region.Intersect(chart_region);
1821 if (vpu_region.Empty())
1822 pqc_ref->b_include =
false;
1824 pqc_ref->b_include =
true;
1825 vp_region.Subtract(chart_region);
1828 pqc_ref->b_include =
false;
1830 pqc_ref->b_include =
false;
1835 if (!vp_region.Empty()) {
1836 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1839 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
1841 const ChartTableEntry &cte = ChartData->GetChartTableEntry(pqc->dbIndex);
1846 if (CHART_FAMILY_VECTOR == m_reference_family) {
1847 if (s57chart::IsCellOverlayType(cte.GetFullSystemPath())) {
1853 if (CHART_TYPE_MBTILES == cte.GetChartType()) {
1854 pqc->b_include =
false;
1858 if (cte.Scale_ge(m_reference_scale)) {
1862 bool b_in_noshow =
false;
1863 for (
unsigned int ins = 0;
1864 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
1865 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
1875 LLRegion vpu_region(cvp_region);
1878 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
1880 if (!chart_region.Empty()) {
1881 vpu_region.Intersect(chart_region);
1883 if (vpu_region.Empty())
1884 pqc->b_include =
false;
1886 pqc->b_include =
true;
1887 vp_region.Subtract(chart_region);
1890 pqc->b_include =
false;
1892 pqc->b_include =
true;
1896 pqc->b_include =
false;
1899 if (vp_region.Empty())
1906 if (b_has_overlays && (CHART_FAMILY_VECTOR == m_reference_family)) {
1907 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1910 if (pqc->dbIndex == m_refchart_dbIndex)
continue;
1912 const ChartTableEntry &cte = ChartData->GetChartTableEntry(pqc->dbIndex);
1914 if (cte.Scale_ge(m_reference_scale)) {
1915 bool b_in_noshow =
false;
1916 for (
unsigned int ins = 0;
1917 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
1918 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
1928 LLRegion vpu_region(cvp_region);
1931 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
1933 if (!chart_region.Empty()) vpu_region.Intersect(chart_region);
1935 if (vpu_region.Empty())
1936 pqc->b_include =
false;
1939 s57chart::IsCellOverlayType(cte.GetFullSystemPath());
1940 if (b_overlay) pqc->b_include =
true;
1947 ChartData->GetChartTableEntry(m_refchart_dbIndex);
1948 if (s57chart::IsCellOverlayType(cte_ref.GetFullSystemPath())) {
1949 pqc->b_include =
true;
1961 m_eclipsed_stack_array.clear();
1963 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
1966 if (!pqc->b_include) {
1967 const ChartTableEntry &cte = ChartData->GetChartTableEntry(pqc->dbIndex);
1968 if (cte.Scale_ge(m_reference_scale) &&
1969 (cte.GetChartType() != CHART_TYPE_MBTILES)) {
1970 m_eclipsed_stack_array.push_back(pqc->dbIndex);
1971 pqc->b_eclipsed =
true;
1978 if (((m_bquiltanyproj || m_quilt_proj == PROJECTION_MERCATOR)) &&
1979 !vp_region.Empty()) {
1980 bool b_must_add_cm93 =
true;
1987 while( updd .HaveRects()) {
1988 wxRect rect = updd.GetRect();
1989 if( ( rect.width > 2 ) && ( rect.height > 2 ) ) {
1990 b_must_add_cm93 =
true;
1997 if (b_must_add_cm93) {
1998 for (
int ics = 0; ics < m_parent->GetpCurrentStack()->nEntry; ics++) {
1999 int i = m_parent->GetpCurrentStack()->GetDBIndex(ics);
2000 if (CHART_TYPE_CM93COMP == ChartData->GetDBChartType(i)) {
2003 qcnew->SetScale(ChartData->GetDBChartScale(i));
2005 m_pcandidate_array->Add(qcnew);
2016 for (
unsigned int i = 0; i < m_pcandidate_array->GetCount(); i++) {
2018 if (pqc->b_include) {
2024 if (!b_vis && m_pcandidate_array->GetCount()) {
2027 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2029 const ChartTableEntry &cte = ChartData->GetChartTableEntry(pqc->dbIndex);
2032 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2035 if (cte.GetChartType() == CHART_TYPE_MBTILES)
continue;
2038 LLRegion vpck_region(vp_local.GetBBox());
2041 LLRegion &chart_region = pqc->GetReducedCandidateRegion(factor);
2043 if (!chart_region.Empty()) vpck_region.Intersect(chart_region);
2045 if (!vpck_region.Empty()) {
2047 if (cte.Scale_eq(add_scale)) {
2048 pqc->b_include =
true;
2051 pqc->b_include =
true;
2052 add_scale = cte.GetScale();
2061 m_PatchList.DeleteContents(
true);
2062 m_PatchList.Clear();
2064 if (m_pcandidate_array->GetCount()) {
2065 for (
int i = m_pcandidate_array->GetCount() - 1; i >= 0; i--) {
2071 const ChartTableEntry &m = ChartData->GetChartTableEntry(pqc->dbIndex);
2073 if (m.GetChartType() == CHART_TYPE_CM93COMP)
2074 pqc->b_include =
true;
2077 if (pqc->b_include) {
2079 pqp->dbIndex = pqc->dbIndex;
2080 pqp->ProjType = m.GetChartProjectionType();
2083 pqp->quilt_region = pqc->GetCandidateRegion();
2086 pqp->b_Valid =
true;
2088 m_PatchList.Append(pqp);
2095 if (!m_bquiltanyproj) {
2097 m_quilt_proj = PROJECTION_MERCATOR;
2098 ChartBase *ppc = GetLargestScaleChart();
2099 if (ppc) m_quilt_proj = ppc->GetChartProjectionType();
2103 if (!m_bquiltanyproj) {
2106 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2107 wxPatchListNode *pcinode = m_PatchList.Item(i);
2109 if ((piqp->ProjType != m_quilt_proj) &&
2110 (piqp->ProjType != PROJECTION_UNKNOWN))
2111 piqp->b_Valid =
false;
2116 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2117 wxPatchListNode *pcinode = m_PatchList.Item(i);
2119 for (
unsigned int ins = 0;
2120 ins < m_parent->GetQuiltNoshowIindexArray().size(); ins++) {
2121 if (m_parent->GetQuiltNoshowIindexArray()[ins] ==
2124 piqp->b_Valid =
false;
2132 m_covered_region.Clear();
2137 bool b_skipCM93 =
false;
2138 if (m_reference_type == CHART_TYPE_CM93COMP) {
2140 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2141 wxPatchListNode *pcinode = m_PatchList.Item(i);
2146 const ChartTableEntry &m = ChartData->GetChartTableEntry(piqp->dbIndex);
2148 if (m.GetChartType() == CHART_TYPE_CM93COMP) {
2150 piqp->ActiveRegion = piqp->quilt_region;
2151 piqp->ActiveRegion.Intersect(cvp_region);
2155 m_covered_region.Union(piqp->quilt_region);
2165 for (
int i = m_PatchList.GetCount() - 1; i >= 0; i--) {
2166 wxPatchListNode *pcinode = m_PatchList.Item(i);
2171 const ChartTableEntry &cte = ChartData->GetChartTableEntry(piqp->dbIndex);
2174 if (cte.GetChartType() == CHART_TYPE_CM93COMP)
continue;
2178 piqp->ActiveRegion = piqp->quilt_region;
2181 if (!b_has_overlays && m_PatchList.GetCount() < 25)
2182 piqp->ActiveRegion.Subtract(m_covered_region);
2184 piqp->ActiveRegion.Intersect(cvp_region);
2188 if (piqp->ActiveRegion.Empty() && (piqp->dbIndex != m_refchart_dbIndex))
2189 piqp->b_eclipsed =
true;
2192 piqp->b_overlay =
false;
2193 if (cte.GetChartFamily() == CHART_FAMILY_VECTOR) {
2194 piqp->b_overlay = s57chart::IsCellOverlayType(cte.GetFullSystemPath());
2197 if (!piqp->b_overlay) m_covered_region.Union(piqp->quilt_region);
2202 for (
unsigned int i = 0; i < m_PatchList.GetCount(); i++) {
2203 wxPatchListNode *pcinode = m_PatchList.Item(i);
2209 const ChartTableEntry &ctei = ChartData->GetChartTableEntry(piqp->dbIndex);
2212 LLRegion vpr_region = piqp->quilt_region;
2220 for (
unsigned int k = i + 1; k < m_PatchList.GetCount(); k++) {
2221 wxPatchListNode *pnode = m_PatchList.Item(k);
2242 if (!b_has_overlays) {
2243 if (!vpr_region.Empty()) {
2245 ChartData->GetChartTableEntry(pqp->dbIndex);
2246 LLRegion larger_scale_chart_region =
2249 vpr_region.Subtract(larger_scale_chart_region);
2258 wxPatchListNode *pinode = m_PatchList.Item(i);
2260 pqpi->ActiveRegion = vpr_region;
2269 if (pqpi->ActiveRegion.Empty()) pqpi->b_eclipsed =
true;
2277 m_covered_region.Union(pqpi->ActiveRegion);
2284 unsigned int il = 0;
2285 while (il < m_PatchList.GetCount()) {
2286 wxPatchListNode *pcinode = m_PatchList.Item(il);
2288 if (piqp->b_eclipsed) {
2291 bool b_noadd =
false;
2292 for (
unsigned int ir = 0; ir < m_eclipsed_stack_array.size(); ir++) {
2293 if (piqp->dbIndex == m_eclipsed_stack_array[ir]) {
2298 if (!b_noadd) m_eclipsed_stack_array.push_back(piqp->dbIndex);
2300 m_PatchList.DeleteNode(pcinode);
2319 m_parent->EnablePaint(
false);
2325 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2327 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2328 if (ChartData->IsChartLocked(pqc->dbIndex))
2329 pqc->b_locked =
true;
2331 pqc->b_locked = ChartData->LockCacheChart(pqc->dbIndex);
2336 for (ir = 0; ir < m_pcandidate_array->GetCount(); ir++) {
2338 if ((pqc->b_include) && (!pqc->b_eclipsed)) {
2344 if (ChartData->OpenChartFromDBAndLock(pqc->dbIndex, FULL_INIT,
2346 pqc->b_locked =
true;
2350 m_parent->EnablePaint(
true);
2353 m_last_index_array = m_index_array;
2355 m_index_array.clear();
2358 unsigned int kl = m_PatchList.GetCount();
2359 for (
unsigned int k = 0; k < kl; k++) {
2360 wxPatchListNode *cnode = m_PatchList.Item((kl - k) - 1);
2361 m_index_array.push_back(cnode->GetData()->dbIndex);
2362 cnode = cnode->GetNext();
2368 m_quilt_depth_unit = _T(
"");
2369 ChartBase *pc = ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
2371 m_quilt_depth_unit = pc->GetDepthUnits();
2373 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2374 int units = ps52plib->m_nDepthUnitDisplay;
2377 m_quilt_depth_unit = _T(
"Feet");
2380 m_quilt_depth_unit = _T(
"Meters");
2383 m_quilt_depth_unit = _T(
"Fathoms");
2389 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2390 wxPatchListNode *pnode = m_PatchList.Item(k);
2396 ChartBase *pc = ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
2398 wxString du = pc->GetDepthUnits();
2399 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2400 int units = ps52plib->m_nDepthUnitDisplay;
2413 wxString dul = du.Lower();
2414 wxString ml = m_quilt_depth_unit.Lower();
2418 if (dul.StartsWith(_T(
"meters")) && ml.StartsWith(_T(
"meters")))
2420 else if (dul.StartsWith(_T(
"metres")) && ml.StartsWith(_T(
"metres")))
2422 else if (dul.StartsWith(_T(
"fathoms")) && ml.StartsWith(_T(
"fathoms")))
2424 else if (dul.StartsWith(_T(
"met")) && ml.StartsWith(_T(
"met")))
2428 m_quilt_depth_unit = _T(
"");
2438 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2439 wxPatchListNode *pnode = m_PatchList.Item(k);
2443 if (!ChartData->IsChartInCache(pqp->dbIndex)) {
2444 wxLogMessage(_T(
" Quilt Compose cache miss..."));
2445 ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
2446 if (!ChartData->IsChartInCache(pqp->dbIndex)) {
2447 wxLogMessage(_T(
" Oops, removing from quilt..."));
2448 pqp->b_Valid =
false;
2455 if (!ChartData->IsChartInCache(m_refchart_dbIndex))
2456 ChartData->OpenChartFromDB(m_refchart_dbIndex, FULL_INIT);
2462 m_bquilt_has_overlays =
false;
2463 m_max_error_factor = 0.;
2464 for (
unsigned int k = 0; k < m_PatchList.GetCount(); k++) {
2465 wxPatchListNode *pnode = m_PatchList.Item(k);
2471 ChartBase *pc = ChartData->OpenChartFromDB(pqp->dbIndex, FULL_INIT);
2473 m_max_error_factor =
2474 wxMax(m_max_error_factor, pc->GetChart_Error_Factor());
2475 if (pc->GetChartFamily() == CHART_FAMILY_VECTOR) {
2476 bool isOverlay = IsChartS57Overlay(pqp->dbIndex);
2477 pqp->b_overlay = isOverlay;
2478 if (isOverlay) m_bquilt_has_overlays =
true;
2487 ChartData->LockCache();
2491 unsigned long xa_hash = 5381;
2492 for (
unsigned int im = 0; im < m_extended_stack_array.size(); im++) {
2493 int dbindex = m_extended_stack_array[im];
2494 xa_hash = ((xa_hash << 5) + xa_hash) + dbindex;
2497 m_xa_hash = xa_hash;
2506 if (!m_bcomposed)
return;
2510 if (GetnCharts() && !m_bbusy && !chart_region.Empty()) {
2516 if (!(chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2517 vp.b_MercatorProjectionOverride)) {
2520 OCPNRegion get_screen_region = vp.GetVPRegionIntersect(
2521 chart_region, pqp->ActiveRegion, chart->GetNativeScale());
2522 if (!get_screen_region.Empty())
2523 rendered_region.Union(get_screen_region);
2526 chart = GetNextChart();
2530 m_rendered_region = rendered_region;
2535bool Quilt::RenderQuiltRegionViewOnDCNoText(wxMemoryDC &dc,
ViewPort &vp,
2537 return DoRenderQuiltRegionViewOnDC(dc, vp, chart_region);
2540bool Quilt::RenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
2542 return DoRenderQuiltRegionViewOnDCTextOnly(dc, vp, chart_region);
2545bool Quilt::DoRenderQuiltRegionViewOnDC(wxMemoryDC &dc,
ViewPort &vp,
2547#ifdef ocpnUSE_DIBSECTION
2553 if (!m_bcomposed)
return false;
2557 if (GetnCharts() && !m_bbusy) {
2565 int chartsDrawn = 0;
2567 if (!chart_region.Empty()) {
2569 bool okToRender =
true;
2571 if (chart->GetChartProjectionType() != PROJECTION_MERCATOR &&
2572 vp.b_MercatorProjectionOverride)
2576 chart = GetNextChart();
2581 bool b_chart_rendered =
false;
2582 LLRegion get_region = pqp->ActiveRegion;
2584 OCPNRegion get_screen_region = vp.GetVPRegionIntersect(
2585 chart_region, get_region, chart->GetNativeScale());
2586 if (!get_screen_region.Empty()) {
2587 if (!pqp->b_overlay) {
2588 if (chart->GetChartType() == CHART_TYPE_CM93COMP) {
2590 chart->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2594 if (Chs57->m_RAZBuilt) {
2595 b_chart_rendered = Chs57->RenderRegionViewOnDCNoText(
2596 tmp_dc, vp, get_screen_region);
2602 b_chart_rendered = ChPI->RenderRegionViewOnDCNoText(
2603 tmp_dc, vp, get_screen_region);
2605 b_chart_rendered = chart->RenderRegionViewOnDC(
2606 tmp_dc, vp, get_screen_region);
2608 b_chart_rendered =
true;
2615 screen_region.Subtract(get_screen_region);
2620 while (upd.HaveRects()) {
2621 wxRect rect = upd.GetRect();
2622 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc, rect.x,
2623 rect.y, wxCOPY,
true);
2627 tmp_dc.SelectObject(wxNullBitmap);
2629 if (b_chart_rendered) rendered_region.Union(get_screen_region);
2633 chart = GetNextChart();
2637 if (!chartsDrawn) m_parent->GetVP().SetProjectionType(PROJECTION_MERCATOR);
2640 if (m_bquilt_has_overlays && !chart_region.Empty()) {
2641 chart = GetFirstChart();
2645 if (pqp->b_overlay) {
2646 LLRegion get_region = pqp->ActiveRegion;
2647 OCPNRegion get_screen_region = vp.GetVPRegionIntersect(
2648 chart_region, get_region, chart->GetNativeScale());
2649 if (!get_region.Empty()) {
2652 Chs57->RenderOverlayRegionViewOnDC(tmp_dc, vp,
2658 ChPI->RenderRegionViewOnDC(tmp_dc, vp, get_screen_region);
2663 while (upd.HaveRects()) {
2664 wxRect rect = upd.GetRect();
2665 dc.Blit(rect.x, rect.y, rect.width, rect.height, &tmp_dc,
2666 rect.x, rect.y, wxCOPY,
true);
2669 tmp_dc.SelectObject(wxNullBitmap);
2674 chart = GetNextChart();
2681 while (clrit.HaveRects()) {
2682 wxRect rect = clrit.GetRect();
2684 dc.SetPen(*wxBLACK_PEN);
2685 dc.SetBrush(*wxBLACK_BRUSH);
2686 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
2688 dc.Blit(rect.x, rect.y, rect.width, rect.height, &dc, rect.x, rect.y,
2695 if (m_nHiLiteIndex >= 0) {
2697 vp.GetVPRegionIntersect(chart_region, GetHiliteRegion(), 1);
2698 wxRect box = hiregion.GetBox();
2700 if (!box.IsEmpty()) {
2703 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2704 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2711 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2715 q_dc.SelectObject(*m_pBM);
2716 q_dc.Blit(0, 0, vp.rv_rect.width, vp.rv_rect.height, &dc, 0, 0);
2717 q_dc.SelectObject(wxNullBitmap);
2722 wxBitmap hl_mask_bm(vp.rv_rect.width, vp.rv_rect.height, 1);
2724 mdc.SelectObject(hl_mask_bm);
2725 mdc.SetBackground(*wxBLACK_BRUSH);
2727 mdc.SetClippingRegion(box);
2728 mdc.SetBackground(*wxWHITE_BRUSH);
2730 mdc.SelectObject(wxNullBitmap);
2732 if (hl_mask_bm.IsOk()) {
2733 wxMask *phl_mask =
new wxMask(hl_mask_bm);
2734 m_pBM->SetMask(phl_mask);
2735 q_dc.SelectObject(*m_pBM);
2738 wxBitmap rbm(vp.rv_rect.width, vp.rv_rect.height);
2739 wxMask *pr_mask =
new wxMask(hl_mask_bm);
2741 rbm.SetMask(pr_mask);
2742 rdc.SelectObject(rbm);
2743 unsigned char hlcolor = 255;
2744 switch (global_color_scheme) {
2745 case GLOBAL_COLOR_SCHEME_DAY:
2748 case GLOBAL_COLOR_SCHEME_DUSK:
2751 case GLOBAL_COLOR_SCHEME_NIGHT:
2759 rdc.SetBackground(wxBrush(wxColour(hlcolor, 0, 0)));
2763 while (upd.HaveRects()) {
2764 wxRect rect = upd.GetRect();
2765 rdc.Blit(rect.x, rect.y, rect.width, rect.height, &q_dc, rect.x,
2766 rect.y, wxOR,
true);
2771 while (updq.HaveRects()) {
2772 wxRect rect = updq.GetRect();
2773 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &rdc, rect.x,
2774 rect.y, wxCOPY,
true);
2778 q_dc.SelectObject(wxNullBitmap);
2779 m_pBM->SetMask(NULL);
2782 dc.SelectObject(*m_pBM);
2785 rdc.SelectObject(wxNullBitmap);
2791 if (g_fog_overzoom) {
2792 double scale_factor = vp.ref_scale / vp.chart_scale;
2794 if (scale_factor > g_overzoom_emphasis_base) {
2795 float fog = ((scale_factor - g_overzoom_emphasis_base) * 255.) / 20.;
2796 fog = wxMin(fog, 200.);
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);
2816 wxImage src = m_pBM->ConvertToImage();
2819 wxMin((scale_factor - g_overzoom_emphasis_base) / 4, 4);
2821 wxImage dest = src.Blur(blur_factor);
2825 unsigned char *bg = src.GetData();
2826 wxColour color = m_parent->GetFogColor();
2828 float transparency = fog;
2831 wxImage dest(vp.rv_rect.width, vp.rv_rect.height);
2832 unsigned char *dest_data = (
unsigned char *) malloc( vp.rv_rect.width * vp.rv_rect.height * 3 *
sizeof(
unsigned char) );
2833 unsigned char *d = dest_data;
2835 float alpha = 1.0 - (float)transparency / 255.0;
2836 int sb = vp.rv_rect.width * vp.rv_rect.height;
2837 for(
int i = 0; i < sb; i++ ) {
2840 int r = ( ( *bg++ ) * a ) + (1.0-a) * color.Red();
2842 int g = ( ( *bg++ ) * a ) + (1.0-a) * color.Green();
2844 int b = ( ( *bg++ ) * a ) + (1.0-a) * color.Blue();
2848 dest.SetData( dest_data );
2853 ddc.SelectObject(dim);
2855 q_dc.SelectObject(*m_pBM);
2857 while (upd.HaveRects()) {
2858 wxRect rect = upd.GetRect();
2859 q_dc.Blit(rect.x, rect.y, rect.width, rect.height, &ddc, rect.x,
2864 ddc.SelectObject(wxNullBitmap);
2865 q_dc.SelectObject(wxNullBitmap);
2868 dc.SelectObject(*m_pBM);
2876 SubstituteClearDC(dc, vp);
2880 SubstituteClearDC(dc, vp);
2884 m_rendered_region = rendered_region;
2890void Quilt::SubstituteClearDC(wxMemoryDC &dc,
ViewPort &vp) {
2892 if ((m_pBM->GetWidth() != vp.rv_rect.width) ||
2893 (m_pBM->GetHeight() != vp.rv_rect.height)) {
2899 if (NULL == m_pBM) {
2900 m_pBM =
new wxBitmap(vp.rv_rect.width, vp.rv_rect.height);
2903 dc.SelectObject(wxNullBitmap);
2904 dc.SelectObject(*m_pBM);
2905 dc.SetBackground(*wxBLACK_BRUSH);
2907 m_covered_region.Clear();
2910bool Quilt::DoRenderQuiltRegionViewOnDCTextOnly(wxMemoryDC &dc,
ViewPort &vp,
2912 if (!m_bcomposed)
return false;
2916 if (GetnCharts() && !m_bbusy) {
2921 ChartBase *chart = GetLargestScaleChart();
2928 Chs57->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
2932 ChPI->RenderRegionViewOnDCTextOnly(dc, vp, chart_region);
2937 chart = GetNextSmallerScaleChart();
2941 SubstituteClearDC(dc, vp);
bool Compose(const ViewPort &vp)