1 : /******************************************************************************
2 : * $Id: pcrasterutil.cpp 15450 2008-10-03 10:59:32Z kdejong $
3 : *
4 : * Project: PCRaster Integration
5 : * Purpose: PCRaster driver support functions.
6 : * Author: Kor de Jong, k.dejong at geog.uu.nl
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2004, Kor de Jong
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #ifndef INCLUDED_IOSTREAM
31 : #include <iostream>
32 : #define INCLUDED_IOSTREAM
33 : #endif
34 :
35 : #ifndef INCLUDED_ALGORITHM
36 : #include <algorithm>
37 : #define INCLUDED_ALGORITHM
38 : #endif
39 :
40 : #ifndef INCLUDED_FLOAT
41 : #include <float.h>
42 : #define INCLUDED_FLOAT
43 : #endif
44 :
45 : #ifndef INCLUDED_PCRTYPES
46 : #include "pcrtypes.h"
47 : #define INCLUDED_PCRTYPES
48 : #endif
49 :
50 : #ifndef INCLUDED_PCRASTERUTIL
51 : #include "pcrasterutil.h"
52 : #define INCLUDED_PCRASTERUTIL
53 : #endif
54 :
55 :
56 :
57 : //! Converts PCRaster data type to GDAL data type.
58 : /*!
59 : \param cellRepresentation Cell representation.
60 : \return GDAL data type, GDT_Uknown if conversion is not possible.
61 : */
62 12 : GDALDataType cellRepresentation2GDALType(
63 : CSF_CR cellRepresentation)
64 : {
65 12 : GDALDataType type = GDT_Unknown;
66 :
67 12 : switch(cellRepresentation) {
68 : // CSF version 2. ----------------------------------------------------------
69 : case CR_UINT1: {
70 6 : type = GDT_Byte;
71 6 : break;
72 : }
73 : case CR_INT4: {
74 2 : type = GDT_Int32;
75 2 : break;
76 : }
77 : case CR_REAL4: {
78 4 : type = GDT_Float32;
79 4 : break;
80 : }
81 : case CR_REAL8: {
82 0 : type = GDT_Float64;
83 0 : break;
84 : }
85 : // CSF version 1. ----------------------------------------------------------
86 : case CR_INT1: {
87 0 : type = GDT_Byte;
88 0 : break;
89 : }
90 : case CR_INT2: {
91 0 : type = GDT_Int16;
92 0 : break;
93 : }
94 : case CR_UINT2: {
95 0 : type = GDT_UInt16;
96 0 : break;
97 : }
98 : case CR_UINT4: {
99 0 : type = GDT_UInt32;
100 : break;
101 : }
102 : default: {
103 : break;
104 : }
105 : }
106 :
107 12 : return type;
108 : }
109 :
110 :
111 :
112 0 : CSF_VS string2ValueScale(
113 : std::string const& string)
114 : {
115 0 : CSF_VS valueScale = VS_UNDEFINED;
116 :
117 : // CSF version 2. ------------------------------------------------------------
118 0 : if(string == "VS_BOOLEAN") {
119 0 : valueScale = VS_BOOLEAN;
120 : }
121 0 : else if(string == "VS_NOMINAL") {
122 0 : valueScale = VS_NOMINAL;
123 : }
124 0 : else if(string == "VS_ORDINAL") {
125 0 : valueScale = VS_ORDINAL;
126 : }
127 0 : else if(string == "VS_SCALAR") {
128 0 : valueScale = VS_SCALAR;
129 : }
130 0 : else if(string == "VS_DIRECTION") {
131 0 : valueScale = VS_DIRECTION;
132 : }
133 0 : else if(string == "VS_LDD") {
134 0 : valueScale = VS_LDD;
135 : }
136 : // CSF version1. -------------------------------------------------------------
137 0 : else if(string == "VS_CLASSIFIED") {
138 0 : valueScale = VS_CLASSIFIED;
139 : }
140 0 : else if(string == "VS_CONTINUOUS") {
141 0 : valueScale = VS_CONTINUOUS;
142 : }
143 0 : else if(string == "VS_NOTDETERMINED") {
144 0 : valueScale = VS_NOTDETERMINED;
145 : }
146 :
147 0 : return valueScale;
148 : }
149 :
150 :
151 :
152 12 : std::string valueScale2String(
153 : CSF_VS valueScale)
154 : {
155 12 : std::string result = "VS_UNDEFINED";
156 :
157 12 : switch(valueScale) {
158 : // CSF version 2. ----------------------------------------------------------
159 : case VS_BOOLEAN: {
160 2 : result = "VS_BOOLEAN";
161 2 : break;
162 : }
163 : case VS_NOMINAL: {
164 2 : result = "VS_NOMINAL";
165 2 : break;
166 : }
167 : case VS_ORDINAL: {
168 0 : result = "VS_ORDINAL";
169 0 : break;
170 : }
171 : case VS_SCALAR: {
172 4 : result = "VS_SCALAR";
173 4 : break;
174 : }
175 : case VS_DIRECTION: {
176 0 : result = "VS_DIRECTION";
177 0 : break;
178 : }
179 : case VS_LDD: {
180 4 : result = "VS_LDD";
181 4 : break;
182 : }
183 : // CSF version 1. ----------------------------------------------------------
184 : case VS_CLASSIFIED: {
185 0 : result = "VS_CLASSIFIED";
186 0 : break;
187 : }
188 : case VS_CONTINUOUS: {
189 0 : result = "VS_CONTINUOUS";
190 0 : break;
191 : }
192 : case VS_NOTDETERMINED: {
193 0 : result = "VS_NOTDETERMINED";
194 : break;
195 : }
196 : default: {
197 : break;
198 : }
199 : }
200 :
201 0 : return result;
202 : }
203 :
204 :
205 :
206 0 : std::string cellRepresentation2String(
207 : CSF_CR cellRepresentation)
208 : {
209 0 : std::string result = "CR_UNDEFINED";
210 :
211 0 : switch(cellRepresentation) {
212 :
213 : // CSF version 2. ----------------------------------------------------------
214 : case CR_UINT1: {
215 0 : result = "CR_UINT1";
216 0 : break;
217 : }
218 : case CR_INT4: {
219 0 : result = "CR_INT4";
220 0 : break;
221 : }
222 : case CR_REAL4: {
223 0 : result = "CR_REAL4";
224 0 : break;
225 : }
226 : case CR_REAL8: {
227 0 : result = "CR_REAL8";
228 0 : break;
229 : }
230 : // CSF version 1. ----------------------------------------------------------
231 : case CR_INT1: {
232 0 : result = "CR_INT1";
233 0 : break;
234 : }
235 : case CR_INT2: {
236 0 : result = "CR_INT2";
237 0 : break;
238 : }
239 : case CR_UINT2: {
240 0 : result = "CR_UINT2";
241 0 : break;
242 : }
243 : case CR_UINT4: {
244 0 : result = "CR_UINT4";
245 : break;
246 : }
247 : default: {
248 : break;
249 : }
250 : }
251 :
252 0 : return result;
253 : }
254 :
255 :
256 :
257 : //! Converts GDAL data type to PCRaster value scale.
258 : /*!
259 : \param type GDAL data type.
260 : \return Value scale.
261 : \warning \a type must be one of the standard numerical types and not
262 : complex.
263 :
264 : GDAL byte is regarded as PCRaster boolean, integral as nominal and float
265 : as scalar. This function will never return VS_LDD, VS_ORDINAL or
266 : VS_DIRECTION.
267 : */
268 18 : CSF_VS GDALType2ValueScale(
269 : GDALDataType type)
270 : {
271 18 : CSF_VS valueScale = VS_UNDEFINED;
272 :
273 18 : switch(type) {
274 : case GDT_Byte: {
275 : // A foreign dataset is unlikely to support our LDD's.
276 6 : valueScale = VS_BOOLEAN;
277 6 : break;
278 : }
279 : case GDT_UInt16:
280 : case GDT_UInt32:
281 : case GDT_Int16:
282 : case GDT_Int32: {
283 8 : valueScale = VS_NOMINAL;
284 8 : break;
285 : }
286 : case GDT_Float32: {
287 : // A foreign dataset is unlikely to support our directional.
288 2 : valueScale = VS_SCALAR;
289 2 : break;
290 : }
291 : case GDT_Float64: {
292 : // A foreign dataset is unlikely to support our directional.
293 2 : valueScale = VS_SCALAR;
294 2 : break;
295 : }
296 : default: {
297 0 : CPLAssert(false);
298 : break;
299 : }
300 : }
301 :
302 18 : return valueScale;
303 : }
304 :
305 :
306 :
307 : //! Converts a GDAL type to a PCRaster cell representation.
308 : /*!
309 : \param type GDAL type.
310 : \param exact Whether an exact match or a CSF2.0 supported cell
311 : representation should be returned.
312 : \return Cell representation.
313 : \warning \a type must be one of the standard numerical types and not
314 : complex.
315 :
316 : If exact is false, conversion to CSF2.0 types will take place. This is
317 : usefull for in file cell representations. If exact is true, and exact match
318 : is made. This is usefull for in app cell representations.
319 :
320 : If exact is false, this function always returns one of CR_UINT1, CR_INT4
321 : or CR_REAL4.
322 : */
323 44 : CSF_CR GDALType2CellRepresentation(
324 : GDALDataType type,
325 : bool exact)
326 : {
327 44 : CSF_CR cellRepresentation = CR_UNDEFINED;
328 :
329 44 : switch(type) {
330 : case GDT_Byte: {
331 12 : cellRepresentation = CR_UINT1;
332 12 : break;
333 : }
334 : case GDT_UInt16: {
335 4 : cellRepresentation = exact ? CR_UINT2: CR_UINT1;
336 4 : break;
337 : }
338 : case GDT_UInt32: {
339 4 : cellRepresentation = exact ? CR_UINT4: CR_UINT1;
340 4 : break;
341 : }
342 : case GDT_Int16: {
343 4 : cellRepresentation = exact ? CR_INT2: CR_INT4;
344 4 : break;
345 : }
346 : case GDT_Int32: {
347 4 : cellRepresentation = CR_INT4;
348 4 : break;
349 : }
350 : case GDT_Float32: {
351 4 : cellRepresentation = CR_REAL4;
352 4 : break;
353 : }
354 : case GDT_Float64: {
355 4 : cellRepresentation = exact ? CR_REAL8: CR_REAL4;
356 : break;
357 : }
358 : default: {
359 : break;
360 : }
361 : }
362 :
363 44 : return cellRepresentation;
364 : }
365 :
366 :
367 :
368 : //! Determines a missing value to use for data of \a cellRepresentation.
369 : /*!
370 : \param cellRepresentation Cell representation of the data.
371 : \return Missing value.
372 : \exception .
373 : \sa .
374 : */
375 20 : double missingValue(
376 : CSF_CR cellRepresentation)
377 : {
378 : // It turns out that the missing values set here should be equal to the ones
379 : // used in gdal's code to do data type conversion. Otherwise missing values
380 : // in the source raster will be lost in the destination raster. It seems that
381 : // when assigning new missing values gdal uses its own nodata values instead
382 : // of the value set in the dataset.
383 :
384 20 : double missingValue = 0.0;
385 :
386 20 : switch(cellRepresentation) {
387 : // CSF version 2. ----------------------------------------------------------
388 : case CR_UINT1: {
389 : // missingValue = static_cast<double>(MV_UINT1);
390 6 : missingValue = UINT1(255);
391 6 : break;
392 : }
393 : case CR_INT4: {
394 : // missingValue = static_cast<double>(MV_INT4);
395 2 : missingValue = INT4(-2147483647);
396 2 : break;
397 : }
398 : case CR_REAL4: {
399 : // using <limits> breaks on gcc 2.95
400 : // CPLAssert(std::numeric_limits<REAL4>::is_iec559);
401 : // missingValue = -std::numeric_limits<REAL4>::max();
402 12 : missingValue = -FLT_MAX;
403 12 : break;
404 : }
405 : // CSF version 1. ----------------------------------------------------------
406 : case CR_INT1: {
407 0 : missingValue = static_cast<double>(MV_INT1);
408 0 : break;
409 : }
410 : case CR_INT2: {
411 0 : missingValue = static_cast<double>(MV_INT2);
412 0 : break;
413 : }
414 : case CR_UINT2: {
415 0 : missingValue = static_cast<double>(MV_UINT2);
416 0 : break;
417 : }
418 : case CR_UINT4: {
419 0 : missingValue = static_cast<double>(MV_UINT4);
420 0 : break;
421 : }
422 : default: {
423 0 : CPLAssert(false);
424 : break;
425 : }
426 : }
427 :
428 20 : return missingValue;
429 : }
430 :
431 :
432 :
433 : //! Opens the raster in \a filename using mode \a mode.
434 : /*!
435 : \param filename Filename of raster to open.
436 : \return Pointer to CSF MAP structure.
437 : \exception .
438 : \warning .
439 : \sa .
440 : */
441 12 : MAP* mapOpen(
442 : std::string const& filename,
443 : MOPEN_PERM mode)
444 : {
445 12 : MAP* map = Mopen(filename.c_str(), mode);
446 :
447 12 : return map;
448 : }
449 :
450 :
451 :
452 200 : void alterFromStdMV(
453 : void* buffer,
454 : size_t size,
455 : CSF_CR cellRepresentation,
456 : double missingValue)
457 : {
458 200 : switch(cellRepresentation) {
459 : // CSF version 2. ----------------------------------------------------------
460 : case(CR_UINT1): {
461 : std::for_each(static_cast<UINT1*>(buffer),
462 : static_cast<UINT1*>(buffer) + size,
463 200 : pcr::AlterFromStdMV<UINT1>(static_cast<UINT1>(missingValue)));
464 200 : break;
465 : }
466 : case(CR_INT4): {
467 : std::for_each(static_cast<INT4*>(buffer),
468 : static_cast<INT4*>(buffer) + size,
469 0 : pcr::AlterFromStdMV<INT4>(static_cast<INT4>(missingValue)));
470 0 : break;
471 : }
472 : case(CR_REAL4): {
473 : std::for_each(static_cast<REAL4*>(buffer),
474 : static_cast<REAL4*>(buffer) + size,
475 0 : pcr::AlterFromStdMV<REAL4>(static_cast<REAL4>(missingValue)));
476 0 : break;
477 : }
478 : case(CR_REAL8): {
479 : std::for_each(static_cast<REAL8*>(buffer),
480 : static_cast<REAL8*>(buffer) + size,
481 0 : pcr::AlterFromStdMV<REAL8>(static_cast<REAL8>(missingValue)));
482 0 : break;
483 : }
484 : // CSF version 1. ----------------------------------------------------------
485 : case CR_INT1: {
486 : std::for_each(static_cast<INT1*>(buffer),
487 : static_cast<INT1*>(buffer) + size,
488 0 : pcr::AlterFromStdMV<INT1>(static_cast<INT1>(missingValue)));
489 0 : break;
490 : }
491 : case CR_INT2: {
492 : std::for_each(static_cast<INT2*>(buffer),
493 : static_cast<INT2*>(buffer) + size,
494 0 : pcr::AlterFromStdMV<INT2>(static_cast<INT2>(missingValue)));
495 0 : break;
496 : }
497 : case CR_UINT2: {
498 : std::for_each(static_cast<UINT2*>(buffer),
499 : static_cast<UINT2*>(buffer) + size,
500 0 : pcr::AlterFromStdMV<UINT2>(static_cast<UINT2>(missingValue)));
501 0 : break;
502 : }
503 : case CR_UINT4: {
504 : std::for_each(static_cast<UINT4*>(buffer),
505 : static_cast<UINT4*>(buffer) + size,
506 0 : pcr::AlterFromStdMV<UINT4>(static_cast<UINT4>(missingValue)));
507 0 : break;
508 : }
509 : default: {
510 0 : CPLAssert(false);
511 : break;
512 : }
513 : }
514 200 : }
515 :
516 :
517 :
518 0 : void alterToStdMV(
519 : void* buffer,
520 : size_t size,
521 : CSF_CR cellRepresentation,
522 : double missingValue)
523 : {
524 0 : switch(cellRepresentation) {
525 : // CSF version 2. ----------------------------------------------------------
526 : case(CR_UINT1): {
527 : std::for_each(static_cast<UINT1*>(buffer),
528 : static_cast<UINT1*>(buffer) + size,
529 0 : pcr::AlterToStdMV<UINT1>(static_cast<UINT1>(missingValue)));
530 0 : break;
531 : }
532 : case(CR_INT4): {
533 : std::for_each(static_cast<INT4*>(buffer),
534 : static_cast<INT4*>(buffer) + size,
535 0 : pcr::AlterToStdMV<INT4>(static_cast<INT4>(missingValue)));
536 0 : break;
537 : }
538 : case(CR_REAL4): {
539 : std::for_each(static_cast<REAL4*>(buffer),
540 : static_cast<REAL4*>(buffer) + size,
541 0 : pcr::AlterToStdMV<REAL4>(static_cast<REAL4>(missingValue)));
542 0 : break;
543 : }
544 : case(CR_REAL8): {
545 : std::for_each(static_cast<REAL8*>(buffer),
546 : static_cast<REAL8*>(buffer) + size,
547 0 : pcr::AlterToStdMV<REAL8>(static_cast<REAL8>(missingValue)));
548 0 : break;
549 : }
550 : // CSF version 1. ----------------------------------------------------------
551 : case CR_INT1: {
552 : std::for_each(static_cast<INT1*>(buffer),
553 : static_cast<INT1*>(buffer) + size,
554 0 : pcr::AlterToStdMV<INT1>(static_cast<INT1>(missingValue)));
555 0 : break;
556 : }
557 : case CR_INT2: {
558 : std::for_each(static_cast<INT2*>(buffer),
559 : static_cast<INT2*>(buffer) + size,
560 0 : pcr::AlterToStdMV<INT2>(static_cast<INT2>(missingValue)));
561 0 : break;
562 : }
563 : case CR_UINT2: {
564 : std::for_each(static_cast<UINT2*>(buffer),
565 : static_cast<UINT2*>(buffer) + size,
566 0 : pcr::AlterToStdMV<UINT2>(static_cast<UINT2>(missingValue)));
567 0 : break;
568 : }
569 : case CR_UINT4: {
570 : std::for_each(static_cast<UINT4*>(buffer),
571 : static_cast<UINT4*>(buffer) + size,
572 0 : pcr::AlterToStdMV<UINT4>(static_cast<UINT4>(missingValue)));
573 0 : break;
574 : }
575 : default: {
576 0 : CPLAssert(false);
577 : break;
578 : }
579 : }
580 0 : }
581 :
582 :
583 :
584 18 : CSF_VS fitValueScale(
585 : CSF_VS valueScale,
586 : CSF_CR cellRepresentation)
587 : {
588 18 : CSF_VS result = valueScale;
589 :
590 18 : switch(cellRepresentation) {
591 : case CR_UINT1: {
592 6 : switch(valueScale) {
593 : case VS_LDD: {
594 0 : result = VS_LDD;
595 0 : break;
596 : }
597 : default: {
598 6 : result = VS_BOOLEAN;
599 : break;
600 : }
601 : }
602 6 : break;
603 : }
604 : case CR_INT4: {
605 2 : switch(valueScale) {
606 : case VS_BOOLEAN: {
607 0 : result = VS_NOMINAL;
608 0 : break;
609 : }
610 : case VS_SCALAR: {
611 0 : result = VS_ORDINAL;
612 0 : break;
613 : }
614 : case VS_DIRECTION: {
615 0 : result = VS_ORDINAL;
616 0 : break;
617 : }
618 : case VS_LDD: {
619 0 : result = VS_NOMINAL;
620 0 : break;
621 : }
622 : default: {
623 2 : result = valueScale;
624 : break;
625 : }
626 : }
627 2 : break;
628 : }
629 : case CR_REAL4: {
630 2 : switch(valueScale) {
631 : case VS_DIRECTION: {
632 0 : result = VS_DIRECTION;
633 0 : break;
634 : }
635 : default: {
636 2 : result = VS_SCALAR;
637 : break;
638 : }
639 : }
640 : break;
641 : }
642 : default: {
643 : break;
644 : }
645 : }
646 :
647 18 : return result;
648 : }
649 :
650 :
651 :
652 20 : void castValuesToBooleanRange(
653 : void* buffer,
654 : size_t size,
655 : CSF_CR cellRepresentation)
656 : {
657 20 : switch(cellRepresentation) {
658 : // CSF version 2. ----------------------------------------------------------
659 : case(CR_UINT1): {
660 : std::for_each(static_cast<UINT1*>(buffer),
661 : static_cast<UINT1*>(buffer) + size,
662 20 : CastToBooleanRange<UINT1>());
663 20 : break;
664 : }
665 : case(CR_INT4): {
666 : std::for_each(static_cast<INT4*>(buffer),
667 : static_cast<INT4*>(buffer) + size,
668 0 : CastToBooleanRange<INT4>());
669 0 : break;
670 : }
671 : case(CR_REAL4): {
672 : std::for_each(static_cast<REAL4*>(buffer),
673 : static_cast<REAL4*>(buffer) + size,
674 0 : CastToBooleanRange<REAL4>());
675 0 : break;
676 : }
677 : case(CR_REAL8): {
678 : std::for_each(static_cast<REAL8*>(buffer),
679 : static_cast<REAL8*>(buffer) + size,
680 0 : CastToBooleanRange<REAL8>());
681 0 : break;
682 : }
683 : // CSF version 1. ----------------------------------------------------------
684 : case CR_INT1: {
685 : std::for_each(static_cast<INT1*>(buffer),
686 : static_cast<INT1*>(buffer) + size,
687 0 : CastToBooleanRange<INT1>());
688 0 : break;
689 : }
690 : case CR_INT2: {
691 : std::for_each(static_cast<INT2*>(buffer),
692 : static_cast<INT2*>(buffer) + size,
693 0 : CastToBooleanRange<INT2>());
694 0 : break;
695 : }
696 : case CR_UINT2: {
697 : std::for_each(static_cast<UINT2*>(buffer),
698 : static_cast<UINT2*>(buffer) + size,
699 0 : CastToBooleanRange<UINT2>());
700 0 : break;
701 : }
702 : case CR_UINT4: {
703 : std::for_each(static_cast<UINT4*>(buffer),
704 : static_cast<UINT4*>(buffer) + size,
705 0 : CastToBooleanRange<UINT4>());
706 0 : break;
707 : }
708 : default: {
709 0 : CPLAssert(false);
710 : break;
711 : }
712 : }
713 4049 : }
714 :
|