Develop and Download Open Source Software

Browse CVS Repository

Contents of /autocoast/src/lib/gpc.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.7 - (show annotations) (download) (as text)
Sat Nov 27 06:36:35 2004 UTC (19 years, 4 months ago) by tmurakam
Branch: MAIN
CVS Tags: v0_3, v0_2, HEAD
Changes since 1.6: +9 -3 lines
File MIME type: text/x-c++src
bug fixed

1 //
2 // AutoCoast: Automatic Coastline scenery generator for Flight Simulator
3 //
4 // Copyright (c) 2004, Takuya Murakami. All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions
8 // are met:
9 //
10 // 1. Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 //
13 // 2. Redistributions in binary form must reproduce the above copyright
14 // notice, this list of conditions and the following disclaimer in the
15 // documentation and/or other materials provided with the distribution.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
21 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 // gpc.cc : GPC wrapper
30
31 #include <stdio.h>
32 #include <math.h>
33
34 #include "gpc.hpp"
35 #include "vector.hpp"
36
37 GpcVertexList::GpcVertexList(void)
38 {
39 vlist = NULL;
40 ownVlistMemory = true;
41 }
42
43 GpcVertexList::GpcVertexList(int n, gpc_vertex *vertex)
44 {
45 vlist = new gpc_vertex_list;
46 vlist->num_vertices = n;
47
48 if (n == 0) {
49 vlist->vertex = NULL;
50 } else {
51 vlist->vertex = new gpc_vertex[n];
52 if (vertex) {
53 for (int i = 0; i < n; i++) {
54 vlist->vertex[i] = vertex[i];
55 }
56 }
57 }
58
59 ownVlistMemory = true;
60 }
61
62 GpcVertexList::GpcVertexList(gpc_vertex_list *v)
63 {
64 vlist = v;
65 ownVlistMemory = false;
66 }
67
68 GpcVertexList::~GpcVertexList()
69 {
70 if (ownVlistMemory && vlist) {
71 if (vlist->vertex) {
72 delete [] vlist->vertex;
73 }
74 delete vlist;
75 }
76
77 vlist = NULL;
78 }
79
80 //
81 // Modify initial vertex to the edge on BoundingBox.
82 //
83 void GpcVertexList::modifyStartPointFromEdge(BoundingBox &bbox)
84 {
85 check();
86
87 int n = vlist->num_vertices;
88 int i, j;
89
90 int prev;
91 int flags;
92 int startPoint = -1;
93
94 prev = bbox.checkEdge(vx(n-1), vy(n-1));
95 for (i = 0; i < n; i++) {
96 flags = bbox.checkEdge(vx(i), vy(i));
97
98 // Leaved from edge?
99 if ((prev & ~flags) != 0 &&
100 (prev & flags) == 0) {
101 if (i == 0) {
102 startPoint = n - 1;
103 } else {
104 startPoint = i - 1;
105 }
106 break;
107 }
108 prev = flags;
109 }
110
111 if (startPoint < 0) {
112 // No start point. Do nothing.
113 return;
114 }
115
116 // Copy data
117 gpc_vertex *tmp = new gpc_vertex[n];
118 for (i = 0, j = startPoint; i < n; i++, j++) {
119 if (j >= n) j = j - n;
120
121 tmp[i] = vlist->vertex[j];
122 }
123
124 memcpy(vlist->vertex, tmp, sizeof(gpc_vertex) * n);
125 delete [] tmp;
126 }
127
128 void GpcVertexList::invert(void)
129 {
130 check();
131
132 int n = vlist->num_vertices;
133 gpc_vertex tmp;
134
135 for (int i = 0; i < n / 2; i++) {
136 tmp = vlist->vertex[i];
137 vlist->vertex[i] = vlist->vertex[n - 1 - i];
138 vlist->vertex[n - 1 - i] = tmp;
139 }
140 }
141
142 //
143 // Check drawing order
144 //
145 bool GpcVertexList::isLeftHand(void)
146 {
147 int n = vlist->num_vertices;
148
149 Vector v1, v2;
150
151 double deg, total_deg = 0.0;
152
153 // calculate rotation angles between all sides.
154 for (int i = 0; i < n; i++) {
155 int i1 = i - 1;
156 int i2 = i + 1;
157
158 if (i1 < 0) i1 += n;
159 if (i2 >= n) i2 -= n;
160
161 v1.set(&vlist->vertex[i1], &vlist->vertex[i]);
162 v2.set(&vlist->vertex[i], &vlist->vertex[i2]);
163
164 deg = v1.Angle(v2);
165 total_deg += deg;
166 }
167
168 return total_deg > 0 ? true : false;
169 }
170
171 //
172 // Smoothing
173 //
174 void GpcVertexList::smoothing(void)
175 {
176 int n = vlist->num_vertices;
177
178 Vector v1, v2, vm, first;
179
180 //
181 // move all points to the medium point between
182 // current and next points.
183 //
184 first.set(&vlist->vertex[0]);
185 for (int i = 0; i < n; i++) {
186 v1.set(&vlist->vertex[i]);
187 if (i < n - 1) {
188 v2.set(&vlist->vertex[i+1]);
189 } else {
190 v2 = first;
191 }
192
193 vm = (v1 + v2) / 2.0;
194
195 vlist->vertex[i].x = vm.x;
196 vlist->vertex[i].y = vm.y;
197 }
198 }
199
200 //
201 // Crop useless points
202 //
203 void GpcVertexList::crop(BoundingBox &bbox)
204 {
205 int n = vlist->num_vertices;
206
207 int i, j;
208 double x, y;
209 double prev_x = -99999, prev_y = -99999;
210
211 #define ERR 1.0 // degree...
212
213 for (i = 0, j = 0; i < n; i++) {
214 x = vlist->vertex[i].x;
215 y = vlist->vertex[i].y;
216
217 if (!bbox.isInbox(x, y) &&
218 ABS(x - prev_x) < ERR &&
219 ABS(y - prev_y) < ERR) {
220 // skip this point
221 continue;
222 }
223
224 // use this point
225 vlist->vertex[j] = vlist->vertex[i];
226 prev_x = vlist->vertex[i].x;
227 prev_y = vlist->vertex[i].y;
228
229 j++;
230 }
231
232 vlist->num_vertices = j;
233 }
234
235
236 ////////////////////////////////////////////////////////////////////////
237 // GpcPolygon
238 GpcPolygon::GpcPolygon()
239 {
240 polygon.num_contours = 0;
241 polygon.contour = NULL;
242 polygon.hole = NULL;
243 }
244
245 GpcPolygon::~GpcPolygon()
246 {
247 GpcPolygon::clear();
248 }
249
250 void GpcPolygon::clear(void)
251 {
252 vector<GpcVertexList*>::iterator it;
253
254 for (it = contour.begin(); it != contour.end(); it++) {
255 delete *it;
256 }
257 contour.clear();
258
259 gpc_free_polygon(&polygon);
260 }
261
262 void GpcPolygon::LoadFromFile(const char *fname)
263 {
264 FILE *fp = fopen(fname, "rb");
265 if (!fp) {
266 fprintf(stderr, "Can't open file: %s\n", fname);
267 exit(1);
268 }
269
270 gpc_free_polygon(&polygon);
271 gpc_read_polygon(fp, 0, &polygon);
272
273 fclose(fp);
274
275 BuildVertexListFromGpcPolygon();
276 }
277
278 void GpcPolygon::SaveToFile(const char *fname)
279 {
280 FILE *fp = fopen(fname, "wb");
281 if (!fp) {
282 fprintf(stderr, "Can't open file: %s\n", fname);
283 exit(1);
284 }
285
286 gpc_write_polygon(fp, 0, &polygon);
287
288 fclose(fp);
289 }
290
291 void GpcPolygon::AddVertexList(GpcVertexList *list, bool rebuild)
292 {
293 // add gpc contour (duplicate)
294 gpc_add_contour(&polygon, list->getvlist(), 0);
295
296 // rebuild GpcVertexList
297 if (rebuild) BuildVertexListFromGpcPolygon();
298 }
299
300 void GpcPolygon::Smoothing(void)
301 {
302 vector<GpcVertexList*>::iterator it;
303
304 for (it = contour.begin(); it != contour.end(); it++) {
305 (*it)->smoothing();
306 }
307 }
308
309 void GpcPolygon::Crop(BoundingBox &bbox)
310 {
311 vector<GpcVertexList*>::iterator it;
312
313 for (it = contour.begin(); it != contour.end(); it++) {
314 (*it)->crop(bbox);
315 }
316 }
317
318
319 GpcPolygon *GpcPolygon::Clipping(BoundingBox &bbox)
320 {
321 // Generate polygons for clipping.
322 GpcPolygon clip;
323
324 gpc_vertex vertex[4];
325 vertex[0].x = bbox.xmin; vertex[0].y = bbox.ymin;
326 vertex[1].x = bbox.xmax; vertex[1].y = bbox.ymin;
327 vertex[2].x = bbox.xmax; vertex[2].y = bbox.ymax;
328 vertex[3].x = bbox.xmin; vertex[3].y = bbox.ymax;
329
330 GpcVertexList contour(4, vertex);
331 clip.AddVertexList(&contour);
332
333 // clipping
334 GpcPolygon *clipped = new GpcPolygon;
335 gpc_polygon *gp = clipped->getpolygon();
336 gpc_polygon_clip(GPC_INT, &polygon, clip.getpolygon(), gp);
337
338 // create GpcVertexList strucutures...
339 clipped->BuildVertexListFromGpcPolygon();
340 return clipped;
341 }
342
343 void GpcPolygon::BuildVertexListFromGpcPolygon(void)
344 {
345 vector<GpcVertexList*>::iterator it;
346 for (it = contour.begin(); it != contour.end(); it++) {
347 delete *it;
348 }
349 contour.clear();
350
351 for (int i = 0; i < polygon.num_contours; i++) {
352 GpcVertexList *vl = new GpcVertexList(&polygon.contour[i]);
353 contour.push_back(vl);
354 }
355 }
356
357 bool GpcPolygon::isEmpty(void)
358 {
359 return polygon.num_contours > 0 ? false : true;
360 }
361
362 // check if the polygon covers whole bounding box.
363 bool GpcPolygon::isFull(BoundingBox &target)
364 {
365 if (polygon.num_contours != 1) {
366 return false;
367 }
368
369 // Check if the number of vertices == 4?
370 gpc_vertex_list *contour = &polygon.contour[0];
371
372 if (contour->num_vertices != 4) {
373 return false;
374 }
375
376 // generate Bounding Box
377 BoundingBox bbox;
378 for (int i = 0; i < 4; i++) {
379 bbox.setpoint(contour->vertex[i].x, contour->vertex[i].y);
380 }
381
382 // check each vertices
383 return bbox.compare(target);
384 }
385
386
387 void GpcPolygon::printStat(void)
388 {
389 int n = numVList();
390
391 int nv = 0;
392 for (int i = 0; i < numVList(); i++) {
393 nv += getVList(i)->numVertices();
394 }
395 fprintf(stderr, "Contour=%d Vertices=%d\n", n, nv);
396
397 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26