SectorZone: add attribute arc_boundary
[xcsoar.git] / src / Topography / TopographyFile.cpp
blob8ded59cd2c2f4a1103fc91f3ab161d9f3972b184
1 /*
2 Copyright_License {
4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "Topography/TopographyFile.hpp"
25 #include "Topography/XShape.hpp"
26 #include "Projection/WindowProjection.hpp"
28 #include <zzip/lib.h>
30 #include <algorithm>
31 #include <stdlib.h>
33 TopographyFile::TopographyFile(struct zzip_dir *_dir, const char *filename,
34 fixed _threshold,
35 fixed _label_threshold,
36 fixed _important_label_threshold,
37 const Color thecolor,
38 int _label_field, int _icon,
39 int _pen_width)
40 :dir(_dir), first(NULL),
41 label_field(_label_field), icon(_icon),
42 pen_width(_pen_width),
43 color(thecolor), scale_threshold(_threshold),
44 label_threshold(_label_threshold),
45 important_label_threshold(_important_label_threshold),
46 cache_bounds(GeoBounds::Invalid())
48 if (msShapefileOpen(&file, "rb", dir, filename, 0) == -1)
49 return;
51 if (file.numshapes == 0) {
52 msShapefileClose(&file);
53 return;
56 shapes.ResizeDiscard(file.numshapes);
57 std::fill(shapes.begin(), shapes.end(), ShapeList(NULL));
59 if (dir != NULL)
60 ++dir->refcount;
62 ++serial;
65 TopographyFile::~TopographyFile()
67 if (IsEmpty())
68 return;
70 ClearCache();
71 msShapefileClose(&file);
73 if (dir != NULL) {
74 --dir->refcount;
75 zzip_dir_free(dir);
79 void
80 TopographyFile::ClearCache()
82 for (auto i = shapes.begin(), end = shapes.end(); i != end; ++i) {
83 delete i->shape;
84 i->shape = NULL;
87 first = NULL;
90 gcc_pure
91 static rectObj
92 ConvertRect(const GeoBounds &br)
94 rectObj dest;
95 dest.minx = (double)br.GetWest().Degrees();
96 dest.maxx = (double)br.GetEast().Degrees();
97 dest.miny = (double)br.GetSouth().Degrees();
98 dest.maxy = (double)br.GetNorth().Degrees();
99 return dest;
102 bool
103 TopographyFile::Update(const WindowProjection &map_projection)
105 if (IsEmpty())
106 return false;
108 if (map_projection.GetMapScale() > scale_threshold)
109 /* not visible, don't update cache now */
110 return false;
112 const GeoBounds screenRect =
113 map_projection.GetScreenBounds();
114 if (cache_bounds.IsValid() && cache_bounds.IsInside(screenRect))
115 /* the cache is still fresh */
116 return false;
118 cache_bounds = map_projection.GetScreenBounds().Scale(fixed(2));
120 rectObj deg_bounds = ConvertRect(cache_bounds);
122 // Test which shapes are inside the given bounds and save the
123 // status to file.status
124 msShapefileWhichShapes(&file, dir, deg_bounds, 0);
126 // If not a single shape is inside the bounds
127 if (!file.status) {
128 // ... clear the whole buffer
129 ClearCache();
130 return false;
133 // Iterate through the shapefile entries
134 const ShapeList **current = &first;
135 auto it = shapes.begin();
136 for (int i = 0; i < file.numshapes; ++i, ++it) {
137 if (!msGetBit(file.status, i)) {
138 // If the shape is outside the bounds
139 // delete the shape from the cache
140 delete it->shape;
141 it->shape = NULL;
142 } else {
143 // is inside the bounds
144 if (it->shape == NULL)
145 // shape isn't cached yet -> cache the shape
146 it->shape = new XShape(&file, i, label_field);
147 // update list pointer
148 *current = it;
149 current = &it->next;
152 // end of list marker
153 *current = NULL;
155 ++serial;
156 return true;
159 void
160 TopographyFile::LoadAll()
162 // Iterate through the shapefile entries
163 const ShapeList **current = &first;
164 auto it = shapes.begin();
165 for (int i = 0; i < file.numshapes; ++i, ++it) {
166 if (it->shape == NULL)
167 // shape isn't cached yet -> cache the shape
168 it->shape = new XShape(&file, i, label_field);
169 // update list pointer
170 *current = it;
171 current = &it->next;
173 // end of list marker
174 *current = NULL;
176 ++serial;
179 unsigned
180 TopographyFile::GetSkipSteps(fixed map_scale) const
182 if (map_scale * 4 > scale_threshold * 3)
183 return 4;
184 if (map_scale * 2 > scale_threshold)
185 return 3;
186 if (map_scale * 4 > scale_threshold)
187 return 2;
188 return 1;
191 #ifdef ENABLE_OPENGL
193 unsigned
194 TopographyFile::GetThinningLevel(fixed map_scale) const
196 if (map_scale * 2 > scale_threshold)
197 return 3;
198 if (map_scale * 3 > scale_threshold)
199 return 2;
200 if (map_scale * 4 > scale_threshold)
201 return 1;
203 return 0;
206 unsigned
207 TopographyFile::GetMinimumPointDistance(unsigned level) const
209 switch (level) {
210 case 1:
211 return (unsigned)(fixed(4) * scale_threshold / 30);
212 case 2:
213 return (unsigned)(fixed(6) * scale_threshold / 30);
214 case 3:
215 return (unsigned)(fixed(9) * scale_threshold / 30);
217 return 1;
220 #endif