diff --git a/Bounding_volumes/include/CGAL/Min_circle_2.h b/Bounding_volumes/include/CGAL/Min_circle_2.h index 856317940b8..d59566ac0a5 100644 --- a/Bounding_volumes/include/CGAL/Min_circle_2.h +++ b/Bounding_volumes/include/CGAL/Min_circle_2.h @@ -58,7 +58,7 @@ class Min_circle_2 { Min_circle_2( InputIterator first, InputIterator last, bool randomize = false, - Random& random = default_random, + Random& random = get_default_random(), const Traits& traits = Traits()); Min_circle_2( const Traits& traits = Traits()); @@ -302,7 +302,7 @@ class Min_circle_2 { = false #endif , - Random& random = default_random, + Random& random = get_default_random(), const Traits& traits = Traits()) : tco( traits) { diff --git a/Bounding_volumes/include/CGAL/Min_ellipse_2.h b/Bounding_volumes/include/CGAL/Min_ellipse_2.h index 274ab47e8c0..31e766e02e1 100644 --- a/Bounding_volumes/include/CGAL/Min_ellipse_2.h +++ b/Bounding_volumes/include/CGAL/Min_ellipse_2.h @@ -57,7 +57,7 @@ class Min_ellipse_2 { Min_ellipse_2( InputIterator first, InputIterator last, bool randomize = false, - Random& random = default_random, + Random& random = get_default_random(), const Traits& traits = Traits()); Min_ellipse_2( const Traits& traits = Traits()); @@ -328,7 +328,7 @@ class Min_ellipse_2 { = false #endif , - Random& random = default_random, + Random& random = get_default_random(), const Traits& traits = Traits()) : tco( traits) { diff --git a/Bounding_volumes/test/Bounding_volumes/rectangular_p_center_2_random1_test.cpp b/Bounding_volumes/test/Bounding_volumes/rectangular_p_center_2_random1_test.cpp index dfef6980a5e..60122b18196 100644 --- a/Bounding_volumes/test/Bounding_volumes/rectangular_p_center_2_random1_test.cpp +++ b/Bounding_volumes/test/Bounding_volumes/rectangular_p_center_2_random1_test.cpp @@ -45,7 +45,6 @@ using CGAL::Creator_uniform_2; using CGAL::Random_points_in_square_2; using CGAL::Random; using CGAL::Timer; -using CGAL::default_random; using CGAL::rectangular_p_center_2; #ifndef CGAL_PCENTER_NO_OUTPUT using std::ostream; @@ -108,7 +107,7 @@ public: Random_p_clusters_2(int n_, double c_size_, double r = 1, - Random& rnd = default_random) + Random& rnd = CGAL::get_default_random()) : Base(r - c_size_, rnd), n(n_), c_size(c_size_), @@ -163,7 +162,7 @@ main(int argc, char* argv[]) #endif // CGAL_PCENTER_NO_OUTPUT // generate random seed - random_seed = default_random.get_int(0, (1 << 30)); + random_seed = CGAL::get_default_random().get_int(0, (1 << 30)); } else random_seed = atoi(argv[2]); diff --git a/Bounding_volumes/test/Bounding_volumes/rectangular_p_center_2_random2_test.cpp b/Bounding_volumes/test/Bounding_volumes/rectangular_p_center_2_random2_test.cpp index 3b9bedddae7..22b280152d1 100644 --- a/Bounding_volumes/test/Bounding_volumes/rectangular_p_center_2_random2_test.cpp +++ b/Bounding_volumes/test/Bounding_volumes/rectangular_p_center_2_random2_test.cpp @@ -50,7 +50,6 @@ using CGAL::Creator_uniform_2; using CGAL::Random_points_in_square_2; using CGAL::Random; using CGAL::Timer; -using CGAL::default_random; using CGAL::rectangular_p_center_2; #ifndef CGAL_PCENTER_NO_OUTPUT using std::ostream; @@ -110,7 +109,7 @@ public: Random_p_clusters_2(int n_, double c_size_, double r = 1, - Random& rnd = default_random) + Random& rnd = CGAL::get_default_random()) : Base(r - c_size_, rnd), n(n_), c_size(c_size_), @@ -165,7 +164,7 @@ main(int argc, char* argv[]) #endif // CGAL_PCENTER_NO_OUTPUT // generate random seed - random_seed = default_random.get_int(0, (1 << 30)); + random_seed = CGAL::get_default_random().get_int(0, (1 << 30)); } else random_seed = std::atoi(argv[2]); diff --git a/Bounding_volumes/test/Bounding_volumes/test_Min_annulus_d_2.cpp b/Bounding_volumes/test/Bounding_volumes/test_Min_annulus_d_2.cpp index 7515da92efa..6032734721e 100644 --- a/Bounding_volumes/test/Bounding_volumes/test_Min_annulus_d_2.cpp +++ b/Bounding_volumes/test/Bounding_volumes/test_Min_annulus_d_2.cpp @@ -73,8 +73,8 @@ void process () for ( int i = 0; i < 100; ++i) { points.push_back (typename K::Point_2 - (CGAL::default_random( 0x100000), - CGAL::default_random( 0x100000), + (CGAL::get_default_random()( 0x100000), + CGAL::get_default_random()( 0x100000), hom)); } diff --git a/Bounding_volumes/test/Bounding_volumes/test_Min_annulus_d_3.cpp b/Bounding_volumes/test/Bounding_volumes/test_Min_annulus_d_3.cpp index 3f6fa8b8f85..9a333abc68f 100644 --- a/Bounding_volumes/test/Bounding_volumes/test_Min_annulus_d_3.cpp +++ b/Bounding_volumes/test/Bounding_volumes/test_Min_annulus_d_3.cpp @@ -73,9 +73,9 @@ void process () for ( int i = 0; i < 100; ++i) { points.push_back (typename K::Point_3 - (CGAL::default_random( 0x100000), - CGAL::default_random( 0x100000), - CGAL::default_random( 0x100000), + (CGAL::get_default_random()( 0x100000), + CGAL::get_default_random()( 0x100000), + CGAL::get_default_random()( 0x100000), hom)); } diff --git a/Bounding_volumes/test/Bounding_volumes/test_Min_annulus_d_d.cpp b/Bounding_volumes/test/Bounding_volumes/test_Min_annulus_d_d.cpp index e4db5fffeab..2eeb684def3 100644 --- a/Bounding_volumes/test/Bounding_volumes/test_Min_annulus_d_d.cpp +++ b/Bounding_volumes/test/Bounding_volumes/test_Min_annulus_d_d.cpp @@ -75,7 +75,7 @@ void process () double hom = 2.0; for ( i = 0; i < 100; ++i) { for (j=0; jBigRat - BigFloat(const BigRat& R, const extLong& r = defRelPrec, - const extLong& a = defAbsPrec) + BigFloat(const BigRat& R, const extLong& r = get_static_defRelPrec(), + const extLong& a = get_static_defAbsPrec()) : RCBigFloat(new BigFloatRep()) { rep->approx(R, r, a); } @@ -94,8 +94,8 @@ public: // know about Expr, but BigFloat has a special role in our system! // =============================== /// constructor for Expr - explicit BigFloat(const Expr& E, const extLong& r = defRelPrec, - const extLong& a = defAbsPrec); + explicit BigFloat(const Expr& E, const extLong& r = get_static_defRelPrec(), + const extLong& a = get_static_defAbsPrec()); //Dummy explicit BigFloat(const BigFloat& E, const extLong& , @@ -162,7 +162,7 @@ public: /// operator/= BigFloat& operator/= (const BigFloat& x) { BigFloat z; - z.rep->div(*rep, *x.rep, defBFdivRelPrec); + z.rep->div(*rep, *x.rep, get_static_defBFdivRelPrec()); *this = z; return *this; } @@ -183,11 +183,11 @@ public: /// \name String Conversion Functions //@{ /// set value from const char* (base = 10) - void fromString(const char* s, const extLong& p=defBigFloatInputDigits) { + void fromString(const char* s, const extLong& p=get_static_defBigFloatInputDigits()) { rep->fromString(s, p); } /// convert to std::string (base = 10) - std::string toString(long prec=defBigFloatOutputDigits, bool sci=false) const { + std::string toString(long prec=get_static_defBigFloatOutputDigits(), bool sci=false) const { return rep->toString(prec, sci); } std::string str() const { @@ -436,7 +436,7 @@ inline BigFloat operator* (const BigFloat& x, const BigFloat& y) { /// operator/ inline BigFloat operator/ (const BigFloat& x, const BigFloat& y) { BigFloat z; - z.getRep().div(x.getRep(),y.getRep(),defBFdivRelPrec); + z.getRep().div(x.getRep(),y.getRep(),get_static_defBFdivRelPrec()); return z; } @@ -491,12 +491,12 @@ inline BigFloat power(const BigFloat& x, unsigned long p) { /// The argument x is an initial approximation. BigFloat root(const BigFloat&, unsigned long k, const extLong&, const BigFloat&); inline BigFloat root(const BigFloat& x, unsigned long k) { - return root(x, k, defBFsqrtAbsPrec, x); + return root(x, k, get_static_defBFsqrtAbsPrec(), x); } /// sqrt to defAbsPrec: inline BigFloat sqrt(const BigFloat& x) { - return x.sqrt(defBFsqrtAbsPrec); + return x.sqrt(get_static_defBFsqrtAbsPrec()); } /// convert an BigFloat Interval to a BigFloat with error bits @@ -626,4 +626,10 @@ inline BigRat::BigRat(const BigFloat& f) : RCBigRat(new BigRatRep()){ *this = f.BigRatValue(); } } //namespace CORE + +#ifdef CGAL_HEADER_ONLY +#include +#include +#endif // CGAL_HEADER_ONLY + #endif // _CORE_BIGFLOAT_H_ diff --git a/CGAL_Core/include/CGAL/CORE/BigFloatRep.h b/CGAL_Core/include/CGAL/CORE/BigFloatRep.h index 53a470a6c0c..a0abc217c8c 100644 --- a/CGAL_Core/include/CGAL/CORE/BigFloatRep.h +++ b/CGAL_Core/include/CGAL/CORE/BigFloatRep.h @@ -144,11 +144,11 @@ private: // conversion // toString() Joaquin Grech 31/5/2003 - std::string toString(long prec=defBigFloatOutputDigits, bool sci=false) const; + std::string toString(long prec=get_static_defBigFloatOutputDigits(), bool sci=false) const; std::string round(std::string inRep, long& L10, unsigned int width) const; - DecimalOutput toDecimal(unsigned int width=defBigFloatOutputDigits, + DecimalOutput toDecimal(unsigned int width=get_static_defBigFloatOutputDigits(), bool Scientific=false) const; - void fromString(const char *p, const extLong & prec = defBigFloatInputDigits); + void fromString(const char *p, const extLong & prec = get_static_defBigFloatInputDigits()); void dump() const; //inline long adjustE(long E, BigInt M, long e) const; diff --git a/CGAL_Core/include/CGAL/CORE/BigFloat_impl.h b/CGAL_Core/include/CGAL/CORE/BigFloat_impl.h new file mode 100644 index 00000000000..d1750ef6d4d --- /dev/null +++ b/CGAL_Core/include/CGAL/CORE/BigFloat_impl.h @@ -0,0 +1,1325 @@ +/**************************************************************************** + * Core Library Version 1.7, August 2004 + * Copyright (c) 1995-2004 Exact Computation Project + * All rights reserved. + * + * This file is part of CORE (http://cs.nyu.edu/exact/core/). + * You can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * Licensees holding a valid commercial license may use this file in + * accordance with the commercial license agreement provided with the + * software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * File: BigFloat.cpp + * Synopsis: + * BigFloat numbers with error bounds + * + * EXACTNESS PROPERTY: + * ================== + * For BigFloats that are exact (i.e., error=0), + * addition/subtraction and multiplication return the + * exact result (i.e., error=0). We also introduce the operation + * div2(), which simply divides a BigFloat by 2, + * but this again preserves exactness. Such exactness + * properties are used in our Newton iteration/Sturm Sequences. + * + * Written by + * Chee Yap + * Chen Li + * Zilin Du + * + * WWW URL: http://cs.nyu.edu/exact/ + * Email: exact@cs.nyu.edu + * + * $URL$ + * $Id$ + ***************************************************************************/ + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include + +namespace CORE { + + +//////////////////////////////////////////////////////////// +// Misc Helper Functions +//////////////////////////////////////////////////////////// + +CGAL_INLINE_FUNCTION +BigInt FiveTo(unsigned long exp) { + if (exp == 0) + return BigInt(1); + else if (exp == 1) + return BigInt(5); + else { + BigInt x = FiveTo(exp / 2); + + x = x * x; + + if (exp & 1) + x *= 5; + + return x; + } +} + +//////////////////////////////////////////////////////////// +// class BigFloat +//////////////////////////////////////////////////////////// + +// STATIC BIGFLOAT CONSTANTS +// ZERO +CGAL_INLINE_FUNCTION +const BigFloat& BigFloat::getZero() { + static BigFloat Zero(0); + return Zero; +} +// ONE +CGAL_INLINE_FUNCTION +const BigFloat& BigFloat::getOne() { + static BigFloat One(1); + return One; +} + +// A special constructor for BigFloat from Expr +// -- this method is somewhat of an anomaly (we normally do not expect +// BigFloats to know about Expr). +CGAL_INLINE_FUNCTION +BigFloat::BigFloat(const Expr& E, const extLong& r, const extLong& a) + : RCBigFloat(new BigFloatRep()) { + *this = E.approx(r, a).BigFloatValue(); // lazy implementaion, any other way? +} + +//////////////////////////////////////////////////////////// +// class BigFloatRep +//////////////////////////////////////////////////////////// + +CGAL_INLINE_FUNCTION +BigFloatRep::BigFloatRep(double d) : m(0), err(0), exp(0) { + if (d != 0.0) { + int isNegative = 0; + + if (d < 0.0) { + isNegative = 1; + d = - d; + } + + int binExp; + double f = frexp(d, &binExp); + + exp = chunkFloor(binExp); + + long s = binExp - bits(exp); + + long stop = 0; + double intPart; + + // convert f into a BigInt + while (f != 0.0 && stop < DBL_MAX_CHUNK) { + f = ldexp(f, (int)CHUNK_BIT); + f = modf(f, &intPart); + m <<= CHUNK_BIT; + m += (long)intPart; + exp--; + stop++; + } +#ifdef CORE_DEBUG + assert (s >= 0); +#endif + + if (s) + m <<= s; + if (isNegative) + negate(m); + } +}//BigFloatRep constructor + +// approximation +CGAL_INLINE_FUNCTION +void BigFloatRep::trunc(const BigInt& I, const extLong& r, const extLong& a) { + if (sign(I)) { + long tr = chunkFloor((- r + bitLength(I)).asLong()); + long ta = chunkFloor(- a.asLong()); + long t; + + if (r.isInfty() || a.isTiny()) + t = ta; + else if (a.isInfty()) + t = tr; + else + t = ta < tr ? tr : ta; + + if (t > 0) { // BigInt remainder; + m = chunkShift(I, - t); + err = 1; + exp = t; + } else { // t <= 0 + m = I; + err = 0; + exp = 0; + } + } else {// I == 0 + m = 0; + err = 0; + exp = 0; + } +} + +CGAL_INLINE_FUNCTION +void BigFloatRep :: truncM(const BigFloatRep& B, const extLong& r, const extLong& a) { + if (sign(B.m)) { + long tr = chunkFloor((- 1 - r + bitLength(B.m)).asLong()); + long ta = chunkFloor(- 1 - a.asLong()) - B.exp; + long t; + + if (r.isInfty() || a.isTiny()) + t = ta; + else if (a.isInfty()) + t = tr; + else + t = ta < tr ? tr : ta; + + if (t >= chunkCeil(clLg(B.err))) { + m = chunkShift(B.m, - t); + err = 2; + exp = B.exp + t; + } else // t < chunkCeil(clLg(B.err)) + core_error(std::string("BigFloat error: truncM called with stricter") + + "precision than current error.", __FILE__, __LINE__, true); + } else {// B.m == 0 + long t = chunkFloor(- a.asLong()) - B.exp; + + if (t >= chunkCeil(clLg(B.err))) { + m = 0; + err = 1; + exp = B.exp + t; + } else // t < chunkCeil(clLg(B.err)) + core_error(std::string("BigFloat error: truncM called with stricter") + + "precision than current error.", __FILE__, __LINE__, true); + } +} + +// This is the main approximation function +// REMARK: would be useful to have a self-modifying version +// of this function (e.g., for Newton). +CGAL_INLINE_FUNCTION +void BigFloatRep::approx(const BigFloatRep& B, + const extLong& r, const extLong& a) { + if (B.err) { + if (1 + clLg(B.err) <= bitLength(B.m)) + truncM(B, r + 1, a); + else // 1 + clLg(B.err) > lg(B.m) + truncM(B, CORE_posInfty, a); + } else {// B.err == 0 + trunc(B.m, r, a - bits(B.exp)); + exp += B.exp; + } + // Call normalization globally -- IP 10/9/98 + normal(); +} + +CGAL_INLINE_FUNCTION +void BigFloatRep::div(const BigInt& N, const BigInt& D, + const extLong& r, const extLong& a) { + if (sign(D)) { + if (sign(N)) { + long tr = chunkFloor((- r + bitLength(N) - bitLength(D) - 1).asLong()); + long ta = chunkFloor(- a.asLong()); + + if (r.isInfty() || a.isTiny()) + exp = ta; + else if (a.isInfty()) + exp = tr; + else + exp = ta < tr ? tr : ta; + + BigInt remainder; + + // divide(chunkShift(N, - exp), D, m, remainder); + div_rem(m, remainder, chunkShift(N, - exp), D); + + if (exp <= 0 && sign(remainder) == 0) + err = 0; + else + err = 1; + } else {// N == 0 + m = 0; + err = 0; + exp = 0; + } + } else // D == 0 + core_error( "BigFloat error: zero divisor.", __FILE__, __LINE__, true); + + // Call normalization globally -- IP 10/9/98 + normal(); +}//div + +// error-normalization +CGAL_INLINE_FUNCTION +void BigFloatRep::normal() { + long le = flrLg(err); + + if (le >= CHUNK_BIT + 2) { // so we do not carry more than 16 = CHUNK_BIT + 2 + // bits of error + long f = chunkFloor(--le); // f is roughly equal to floor(le/CHUNK_BIT) + long bits_f = bits(f); // f chunks will have bits_f many bits +#ifdef CORE_DEBUG + assert (bits_f >= 0); +#endif + + m >>= bits_f; // reduce mantissa by bits_f many bits + err >>= bits_f; // same for err + err += 2; // why 2? + exp += f; + } + if (err == 0) // unlikely, if err += 2 above + eliminateTrailingZeroes(); +} + +// bigNormal(err) +// convert a bigInt error value (=err) into an error that fits into +// a long number. This is done by +// by increasing the exponent, and corresponding decrease +// in the bit lengths of the mantissa and error. +// +CGAL_INLINE_FUNCTION +void BigFloatRep::bigNormal(BigInt& bigErr) { + long le = bitLength(bigErr); + + if (le < CHUNK_BIT + 2) { + err = ulongValue(bigErr); + } else { + long f = chunkFloor(--le); + long bits_f = bits(f); +#ifdef CORE_DEBUG + assert(bits_f >= 0); +#endif + + m >>= bits_f; + bigErr >>= bits_f; + err = ulongValue(bigErr) + 2; // you need to add "2" because "1" comes + // from truncation error in the mantissa, and another + // "1" comes from the truncation error in the bigErr. + // (But there is danger of overflow...) + exp += f; + } + + if (err == 0) + eliminateTrailingZeroes(); +} + +// ARITHMETIC: +// Addition +CGAL_INLINE_FUNCTION +void BigFloatRep::add(const BigFloatRep& x, const BigFloatRep& y) { + long expDiff = x.exp - y.exp; + + if (expDiff > 0) {// x.exp > y.exp + if (!x.err) { + m = chunkShift(x.m, expDiff) + y.m; + err = y.err; + exp = y.exp; + } else {// x.err > 0 + m = x.m + chunkShift(y.m, - expDiff); // negative shift! + err = x.err + 5; // To account for y.err (but why 5?) + exp = x.exp; // + // normal(); + } + } else if (!expDiff) {// x.exp == y.exp + m = x.m + y.m; + err = x.err + y.err; + exp = x.exp; + // normal(); + } else {// x.exp < y.exp + if (!y.err) { + m = x.m + chunkShift(y.m, - expDiff); + err = x.err; + exp = x.exp; + } else {// y.err > 0 + m = chunkShift(x.m, expDiff) + y.m; + err = y.err + 5; + exp = y.exp; + // normal(); + } + } + // Call normalization globally -- IP 10/9/98 + normal(); +} + +// Subtraction +CGAL_INLINE_FUNCTION +void BigFloatRep::sub(const BigFloatRep& x, const BigFloatRep& y) { + long expDiff = x.exp - y.exp; + + if (expDiff > 0) {// x.exp > y.exp + if (!x.err) { + m = chunkShift(x.m, expDiff) - y.m; + err = y.err; + exp = y.exp; + } else {// x.err > 0 + m = x.m - chunkShift(y.m, - expDiff); + err = x.err + 5; + exp = x.exp; + // normal(); + } + } else if (!expDiff) { + m = x.m - y.m; + err = x.err + y.err; + exp = x.exp; + // normal(); + } else { // x.exp < y.exp + if (!y.err) { + m = x.m - chunkShift(y.m, - expDiff); + err = x.err; + exp = x.exp; + } else {// y.err > 0 + m = chunkShift(x.m, expDiff) - y.m; + err = y.err + 5; + exp = y.exp; + // normal(); + } + } + // Call normalization globally -- IP 10/9/98 + normal(); +} + +CGAL_INLINE_FUNCTION +void BigFloatRep::mul(const BigFloatRep& x, const BigFloatRep& y) { + m = x.m * y.m; + exp = x.exp + y.exp; + // compute error (new code, much faster. Zilin Du, Nov 2003) + if (x.err == 0 && y.err == 0) { + err = 0; + eliminateTrailingZeroes(); + } else { + BigInt bigErr(0); + if (y.err != 0) + bigErr += abs(x.m)*y.err; + if (x.err != 0) + bigErr += abs(y.m)*x.err; + if (x.err !=0 && y.err != 0) + bigErr += x.err*y.err; + bigNormal(bigErr); + } +} +// BigFloat div2 will half the value of x, exactly with NO error +// REMARK: should generalize this to dividing by any power of 2 +// We need this in our use of BigFloats to maintain isolation +// intervals (e.g., in Sturm sequences) --Chee/Vikram 4/2003 +// +CGAL_INLINE_FUNCTION +void BigFloatRep :: div2(const BigFloatRep& x) { + if (isEven(x.m)) { + m = (x.m >> 1); + exp = x.exp ; + } else { + m = (x.m << static_cast(CHUNK_BIT-1)); + exp = x.exp -1; + } +} + +// Converts a BigFloat interval into one BigFloat with almost same error bound +// This routine ignores the errors in inputs a and b. +// But you cannot really ignore them since, they are taken into account +// when you compute "r.sub(a,b)"... +CGAL_INLINE_FUNCTION +void BigFloatRep::centerize(const BigFloatRep& a, const BigFloatRep& b) { + if ((a.m == b.m) && (a.err == b.err) && (a.exp == b.exp)) { + m = a.m; + err = a.err; + exp = a.exp; + return; + } + + BigFloatRep r; + r.sub(a, b); + r.div2(r); + + //setup mantissa and exponent, but not error bits + // But this already sets the error bits? Chee + add(a,b); + div2(*this); + // error bits = ceil ( B^{-exp}*|a-b|/2 ) + + // bug fixed: possible overflow on converting + // Zilin & Vikram, 08/24/04 + // err = 1 + longValue(chunkShift(r.m, r.exp - exp)); + BigInt E = chunkShift(r.m, r.exp - exp); + bigNormal(E); +} + +// BigFloat Division, computing x/y: +// Unlike +,-,*, this one takes a relative precision bound R +// Note that R is only used when x and y are error-free! +// (This remark means that we may be less efficient than we could be) +// +// Assert( R>0 && R< CORE_Infty ) +// +CGAL_INLINE_FUNCTION +void BigFloatRep :: div(const BigFloatRep& x, const BigFloatRep& y, + const extLong& R) { + if (!y.isZeroIn()) { // y.m > y.err, so we are not dividing by 0 + if (!x.err && !y.err) { + if (R < 0 || R.isInfty()) //Oct 9, 2002: fixed major bug! [Zilin/Chee] + div(x.m, y.m, get_static_defBFdivRelPrec(), CORE_posInfty); + else + div(x.m, y.m, R, CORE_posInfty); + exp += x.exp - y.exp; // chen: adjust exp. + } else {// x.err > 0 or y.err > 0 + BigInt bigErr, errRemainder; + + if (x.isZeroIn()) { // x.m <= x.err + m = 0; + exp = x.exp - y.exp; + + div_rem(bigErr, errRemainder, abs(x.m) + static_cast(x.err), + abs(y.m) - static_cast(y.err)); + } else { // x.m > x.err + long lx = bitLength(x.m); + long ly = bitLength(y.m); + long r; + + if (!x.err) // x.err == 0 and y.err > 0 + r = ly + 2; + else if(!y.err) // x.err > 0 and y.err == 0 + r = lx + 2; + else // x.err > 0 and y.err > 0 + r = lx < ly ? lx + 2: ly + 2; + + long t = chunkFloor(- r + lx - ly - 1); + BigInt remainder; + + div_rem(m, remainder, chunkShift(x.m, - t), y.m); + exp = t + x.exp - y.exp; + + long delta = ((t > 0) ? 2 : 0); + + // Chen Li: 9/9/99 + // here again, it use ">>" operator with a negative + // right operand. So the result is not well defined. + // Erroneous code: + // divide(abs(remainder) + (static_cast(x.err) >> bits(t)) + // + delta + static_cast(y.err) * abs(m), + // abs(y.m) - static_cast(y.err), + // bigErr, + // errRemainder); + // New code: + BigInt errx_over_Bexp = x.err; + long bits_Bexp = bits(t); + if (bits_Bexp >= 0) { + errx_over_Bexp >>= bits_Bexp; + } else { + errx_over_Bexp <<= (-bits_Bexp); + } + + // divide(abs(remainder) + errx_over_Bexp + // + delta + static_cast(y.err) * abs(m), + // abs(y.m) - static_cast(y.err), + // bigErr, + // errRemainder); + div_rem(bigErr, errRemainder, + abs(remainder) + errx_over_Bexp + delta + static_cast(y.err) * abs(m), + abs(y.m) - static_cast(y.err)); + } + + if (sign(errRemainder)) + ++bigErr; + + bigNormal(bigErr); + } + } else {// y.m <= y.err + core_error("BigFloat error: possible zero divisor.", + __FILE__, __LINE__, true); + } + + // Call normalization globally -- IP 10/9/98 + // normal(); -- Chen: after calling bigNormal, this call is redundant. +}// BigFloatRep::div + +// squareroot for BigInt argument, without initial approximation +// sqrt(x,a) computes sqrt of x to absolute precision a. +// -- this is where Newton is applied +// -- this is called by BigFloatRep::sqrt(BigFloat, extLong) +CGAL_INLINE_FUNCTION +void BigFloatRep::sqrt(const BigInt& x, const extLong& a) { + sqrt(x, a, BigFloat(x, 0, 0)); +} // sqrt(BigInt x, extLong a) , without initial approx + +// sqrt(x,a,A) where +// x = bigInt whose sqrt is to be computed +// a = absolute precision bound +// A = initial approximation in BigFloat +// -- this is where Newton is applied +// -- it is called by BigFloatRep::sqrt(BigFloatRep, extLong, BigFloat) +CGAL_INLINE_FUNCTION +void BigFloatRep::sqrt(const BigInt& x, const extLong& a, const BigFloat& A) { + if (sign(x) == 0) { + m = 0; + err = 0; + exp = 0; + } else if (x == 1) { + m = 1; + err = 0; + exp = 0; + } else {// main case + // here is where we use the initial approximation + m = A.m(); + err = 0; + exp = A.exp(); + + BigFloatRep q, z; + extLong aa; + // need this to make sure that in case the + // initial approximation A is less than sqrt(x) + // then Newton iteration will still proceed at + // least one step. + bool firstTime = true; + for (;;) { + aa = a - bits(exp); + q.div(x, m, CORE_posInfty, aa); + q.err = 0; + q.exp -= exp; + + z.sub(*this, q); // this=current approximation, so z = this - q + /*if (sign(z.m) <= 0 || z.MSB() < - a) // justification: see Koji's + break; // thesis (p. 28) which states + // that we can exit when + // " (*this) <= q + 2**(-a)" + */ + // The preceding code is replaced by what follows: + if (z.MSB() < -a) + break; + if (sign(z.m) <= 0) { + if (firstTime) + firstTime = false; + else + break; + } + + z.add(*this, q); + // Chen Li: a bug fixed here. + // m = z.m >> 1; + // err = 0; + // exp = z.exp; + if ((z.m > 1) && isEven(z.m)) { + m = z.m >> 1; // exact division by 2 + err = 0; + exp = z.exp; + } else { // need to shift left before division by 2 + m = chunkShift(z.m, 1) >> 1; + err = 0; + exp = z.exp - 1; + }//else + }//for + }//else +} // sqrt of BigInt, with initial approx + +// MAIN ENTRY INTO SQRT FUNCTION (BIGFLOAT ARGUMENT, WITHOUT INITIAL APPROX) +CGAL_INLINE_FUNCTION +void BigFloatRep::sqrt(const BigFloatRep& x, const extLong& a) { + sqrt(x, a, BigFloat(x.m, 0, x.exp)); +} //sqrt(BigFloat, extLong a) + +// MAIN ENTRY INTO SQRT FUNCTION (BIGFLOAT ARGUMENT WITH INITIAL APPROXIMATION) +CGAL_INLINE_FUNCTION +void BigFloatRep::sqrt(const BigFloatRep& x, const extLong& a, const BigFloat& A) { + // This computes the sqrt of x to absolute precision a, starting with + // the initial approximation A + if (sign(x.m) >= 0) { // x.m >= 0 + int delta = x.exp & 1; // delta=0 if x.exp is even, otherwise delta=1 + + if (x.isZeroIn()) { // x.m <= x.err + m = 0; + if (!x.err) + err = 0; + else { // x.err > 0 + err = (long)(std::sqrt((double)x.err)); + err++; + err <<= 1; + if (delta) + err <<= HALF_CHUNK_BIT; + } + exp = x.exp >> 1; + normal(); + } else { + long aExp = A.exp() - (x.exp >> 1); + BigFloat AA( chunkShift(A.m(), delta), 0, aExp); + + if (!x.err) { // x.m > x.err = 0 (ERROR FREE CASE) + BigFloatRep z; + extLong ppp; + if (a.isInfty()) //Oct 9, 2002: fixed major bug! [Zilin/Chee] + ppp = get_static_defBFsqrtAbsPrec(); + else + ppp = a + EXTLONG_ONE; + extLong absp = ppp + bits(x.exp >> 1); + + z.sqrt(chunkShift(x.m, delta), absp, AA); // call sqrt(BigInt, a, AA) + + long p = (absp + bits(z.exp)).asLong(); + + // Next, normalize the error: + if (p <= 0) { + m = z.m; + // Chen Li: a bug fixed + // BigInt bigErr = 1 << (-p); + BigInt bigErr(1); + bigErr = bigErr << static_cast(-p); + exp = z.exp + (x.exp >> 1); + bigNormal(bigErr); + } else { // p > 0 + m = chunkShift(z.m, chunkCeil(p)); + long r = CHUNK_BIT - 1 - (p + CHUNK_BIT - 1) % CHUNK_BIT; +#ifdef CORE_DEBUG + assert(r >= 0); +#endif + + err = 1 >> r; + exp = - chunkCeil(ppp.asLong()); + normal(); + } + } else { // x.m > x.err > 0 (mantissa has error) + BigFloatRep z; + extLong absp=-flrLg(x.err)+bitLength(x.m)-(bits(delta) >> 1)+EXTLONG_FOUR; + + z.sqrt(chunkShift(x.m, delta), absp, AA); + + long qqq = - 1 + (bitLength(x.m) >> 1) - delta * HALF_CHUNK_BIT; + long qq = qqq - clLg(x.err); + long q = qq + bits(z.exp); + + if (q <= 0) { + m = z.m; + long qqqq = - qqq - bits(z.exp); + // Chen Li (09/08/99), a bug fixed here: + // BigInt bigErr = x.err << - qqqq; + // when (-qqqq) is negative, the result is not correct. + // how "<<" and ">>" process negative second operand is + // not well defined. Seems it just take it as a unsigned + // integer and extract the last few bits. + // x.err is a long number which easily overflows. + // From page 22 of Koji's paper, I think the exponent is + // wrong here. So I rewrote it as: + BigInt bigErr = x.err; + if (qqqq >= 0) { + bigErr <<= qqqq; + } else { + bigErr >>= (-qqqq); + ++bigErr; // we need to keep its ceiling. + } + + exp = z.exp + (x.exp >> 1); + bigNormal(bigErr); + } else { // q > 0 + m = chunkShift(z.m, chunkCeil(q)); + long r = CHUNK_BIT - 1 - (q + CHUNK_BIT - 1) % CHUNK_BIT; +#ifdef CORE_DEBUG + assert(r >= 0); +#endif + + err = 1 >> r; + exp = (x.exp >> 1) - chunkCeil(qq); + normal(); + } + } // end of case with error in mantissa + }//else + } else + core_error("BigFloat error: squareroot called with negative operand.", + __FILE__, __LINE__, true); +} //sqrt with initial approximation + +// compareMExp(x) +// returns 1 if *this > x +// 0 if *this = x, +// -1 if *this < x, +// +// Main comparison method for BigFloat +// This is called by BigFloat::compare() +// BE CAREFUL: The error bits are ignored! +// Need another version if we want to take care of error bits + +CGAL_INLINE_FUNCTION +int BigFloatRep :: compareMExp(const BigFloatRep& x) const { + int st = sign(m); + int sx = sign(x.m); + + if (st > sx) + return 1; + else if (st == 0 && sx == 0) + return 0; + else if (st < sx) + return - 1; + else { // need to compare m && exp + long expDiff = exp - x.exp; + + if (expDiff > 0) // exp > x.exp + return cmp(chunkShift(m, expDiff), x.m); + else if (!expDiff) + return cmp(m, x.m); + else // exp < x.exp + return cmp(m, chunkShift(x.m, - expDiff)); + } +} + +// 3/6/2000: +// This is a private function used by BigFloatRep::operator<< +// to get the exact value +// of floor(log10(M * 2^ e)) where E is an initial guess. +// We will return the correct E which satisfies +// 10^E <= M * 2^e < 10^{E+1} +// But we convert this into +// mm <= M < 10.mm + +CGAL_INLINE_FUNCTION +long BigFloatRep :: adjustE( long E, BigInt M, long ee) const { + if (M<0) + M=-M; + BigInt mm(1); + if (ee > 0) + M = (M<(ee)); + else + mm = (mm << static_cast(-ee)); + if (E > 0) + mm *= (FiveTo(E)<< static_cast(E)); + else + M *= (FiveTo(-E) << static_cast(-E)); + + if (M < mm) { + do { + E--; + M *= 10; + } while (M < mm); + } else if (M >= 10*mm) { + mm *= 10; + do { + E++; + mm *= 10; + } while (M >= mm); + } + return E; +} + +CGAL_INLINE_FUNCTION +BigFloatRep::DecimalOutput +BigFloatRep::toDecimal(unsigned int width, bool Scientific) const { + BigFloatRep::DecimalOutput decOut; // to be returned + if (err > 0) { + decOut.isExact = false; + } else { // err == 0 + decOut.isExact = true; + } + + if (err > 0 && err >= abs(m)) { + // if err is larger than mantissa, sign and significant values + // can not be determined. + core_error("BigFloat error: Error is too big!", + __FILE__, __LINE__, false); + decOut.rep = "0.0e0"; // error is too big + decOut.isScientific = false; + decOut.noSignificant = 0; + decOut.errorCode = 1; // sign of this number is unknown + return decOut; + } + + decOut.sign = sign(m); + decOut.errorCode = 0; + + BigInt M(m); // temporary mantissa + long lm = bitLength(M); // binary length of mantissa + long e2 = bits(exp); // binary shift length represented by exponent + long le = clLg(err); // binary length of err + if (le == -1) + le = 0; + + long L10 = 0; + if (M != 0) { + L10 = (long)std::floor((lm + e2) / lgTenM); + L10 = adjustE(L10, m, e2); // L10: floor[log10(M 2^(e2))], M != 0 + } else { + L10 = 0; + } + // Convention: in the positional format, when the output is + // the following string of 8 characters: + // (d0, d1, d2, d3, ".", d4, d5, d6, d7) + // then the decimal point is said to be in the 4th position. + // E.g., (d0, ".", d1, d2) has the decimal point in the 1st position. + // The value of L10 says that the decimal point of output should be at + // the (L10 + 1)st position. This is + // true regardingless of whether M = 0 or not. For zero, we output + // {0.0*} so L10=0. In general, the |value| is less than 10 + // if and only if L10 is 0 and the + // decimal point is in the 1st place. Note that L10 is defined even if + // the output is an integer (in which case it does not physically appear + // but conceptually terminates the sequence of digits). + + // First, get the decimal representaion of (m * B^(exp)). + if (e2 < 0) { + M *= FiveTo(-e2); // M = x * 10^(-e2) + } else if (e2 > 0) { + M <<= e2; // M = x * 2^(e2) + } + + std::string decRep = M.get_str(); + // Determine the "significant part" of this string, i.e. the part which + // is guaranteed to be correct in the presence of error, + // except that the last digit which might be subject to +/- 1. + + if (err != 0) { // valid = number of significant digits + unsigned long valid = floorlg10(m) - (long)std::floor(std::log10(float(err))); + if (decRep.length() > valid) { + decRep.erase(valid); + } + } + + // All the digits in decM are correct, except the last one might + // subject to an error +/- 1. + + if ((decRep[0] == '+') || (decRep[0] == '-')) { + decRep.erase(0, 1); + } + + // Second, make choice between positional representation + // and scientific notation. Use scientific notation when: + // 0) if scientific notation flag is on + // 1) err * B^exp >= 1, the error contribute to the integral part. + // 2) (1 + L10) >= width, there is not have enough places to hold the + // positional representation, not including decimal point. + // 3) The distance between the first significant digit and decimal + // point is too large for the width limit. This is equivalent to + // Either ((L10 >= 0 and (L10 + 1) > width)) + // Or ((L10 < 0) and (-L10 + 1) > width). + + if (Scientific || + ((err > 0) && (le + e2) >= 0) || // if err*B^exp >= 1 + ((L10 >= 0) && (L10 + 1 >= (long)width )) || + ((L10 < 0) && (-L10 + 1 > (long)width ))) { + // use scientific notation + decRep = round(decRep, L10, width); + decOut.noSignificant = width; + decRep.insert(1, "."); + if (L10 != 0) { + decRep += 'e'; + if (L10 > 0) { + decRep += '+'; + } else { // L10 < 0 + decRep += '-'; + } + char eBuf[48]; // enought to hold long number L10 + int ne = 0; + if ((ne = sprintf(eBuf, "%ld", labs(L10))) >= 0) { + eBuf[ne] = '\0'; + } else { + //perror("BigFloat.cpp: Problem in outputing the exponent!"); + core_error("BigFloat error: Problem in outputing the exponent", + __FILE__, __LINE__, true); + } + decRep += eBuf; + decOut.isScientific = true; + } + } else { + // use conventional positional notation. + if (L10 >= 0) { // x >= 1 or x == 0 and L10 + 1 <= width + // round when necessary + if (decRep.length() > width ) { + decRep = round(decRep, L10, width ); + if (decRep.length() > width ) { + // overflow happens! use scientific notation + return toDecimal(width, true); + } + } + decOut.noSignificant = decRep.length(); + if (L10 + 1 < (long)width ) { + decRep.insert(L10 + 1, "."); + } else { // L10 + 1 == width + // do nothing + } + } else { // L10 < 0, 0 < x < 1 + // (-L10) leading zeroes, including one to the left of decimal dot + // need to be added in beginning. + decRep = std::string(-L10, '0') + decRep; + // then round when necessary + if (decRep.length() > width ) { + decRep = round(decRep, L10, width ); + // cannot overflow since there are L10 leading zeroes. + } + decOut.noSignificant = decRep.length() - (-L10); + decRep.insert(1, "."); + } + decOut.isScientific = false; + } +#ifdef CORE_DEBUG + assert(decOut.noSignificant >= 0); +#endif + + decOut.rep = decRep; + return decOut; +}//toDecimal + +CGAL_INLINE_FUNCTION +std::string BigFloatRep::round(std::string inRep, long& L10, unsigned int width) const { + // round inRep so that the length would not exceed width. + if (inRep.length() <= width) + return inRep; + + int i = width; // < length + bool carry = false; + + if ((inRep[i] >= '5') && (inRep[i] <= '9')) { + carry = true; + i--; + while ((i >= 0) && carry) { + if (carry) { + inRep[i] ++; + if (inRep[i] > '9') { + inRep[i] = '0'; + carry = true; + } else { + carry = false; + } + } + i-- ; + } + + if ((i < 0) && carry) { // overflow + inRep.insert(inRep.begin(), '1'); + L10 ++; + width ++; + } + } + + return inRep.substr(0, width); +}//round(string,width) + + +// This function fromString(str, prec) is similar to the +// constructor Real(char * str, extLong prec) +// See the file Real.cc for the differences + +CGAL_INLINE_FUNCTION +void BigFloatRep :: fromString(const char *str, const extLong & prec ) { + // NOTE: prec defaults to get_static_defBigFloatInputDigits() (see BigFloat.h) + // check that prec is not INFTY + if (prec.isInfty()) + core_error("BigFloat error: infinite precision not allowed", + __FILE__, __LINE__, true); + + const char *e = strchr(str, 'e'); + int dot = 0; + long e10 = 0; + if (e != NULL) + e10 = atol(e+1); // e10 is decimal precision of the input string + // i.e., input is A/10^{e10}. + else { + e = str + strlen(str); +#ifdef CORE_DEBUG + assert(*e == '\0'); +#endif + + } + + const char *p = str; + if (*p == '-' || *p == '+') + p++; + m = 0; + exp = 0; + + for (; p < e; p++) { + if (*p == '.') { + dot = 1; + continue; + } + m = m * 10 + (*p - '0'); + if (dot) + e10--; + } + + BigInt one = 1; + long t = (e10 < 0) ? -e10 : e10; + BigInt ten = FiveTo(t) * (one << static_cast(t)); + + // HERE IS WHERE WE USE THE SYSTEM CONSTANT + // defBigFloatInputDigits + // Note: this constant is rather similar to defInputDigits which + // is used by Real and Expr for controlling + // input accuracy. The difference is that defInputDigits can + // be CORE_INFTY, but defBigFloatInputDigits must be finite. + + if (e10 < 0) + div(m, ten, CORE_posInfty, 4 * prec); + else + m *= ten; + if (*str == '-') + m = -m; +}//BigFloatRep::fromString + +CGAL_INLINE_FUNCTION +std::istream& BigFloatRep :: operator >>(std::istream& i) { + int size = 20; + char *str = new char[size]; + char *p = str; + char c; + int d = 0, e = 0, s = 0; + // d=1 means dot is found + // e=1 means 'e' or 'E' is found + // int done = 0; + + // Chen Li: fixed a bug, the original statement is + // for (i.get(c); c == ' '; i.get(c)); + // use isspace instead of testing c == ' ', since it must also + // skip tab, catridge/return, etc. + // Change to: + // int status; + do { + c = i.get(); + } while (isspace(c)); /* loop if met end-of-file, or + char read in is white-space. */ + // Chen Li, "if (c == EOF)" is unsafe since c is of char type and + // EOF is of int tyep with a negative value -1 + if (i.eof()) { + i.clear(std::ios::eofbit | std::ios::failbit); + return i; + } + + // the current content in "c" should be the first non-whitespace char + if (c == '-' || c == '+') { + *p++ = c; + i.get(c); + } + + for (; isdigit(c) || (!d && c=='.') || + (!e && ((c=='e') || (c=='E'))) || (!s && (c=='-' || c=='+')); i.get(c)) { + if (!e && (c == '-' || c == '+')) + break; + // Chen Li: put one more rule to prohibite input like + // xxxx.xxxe+xxx.xxx: + if (e && (c == '.')) + break; + if (p - str == size) { + char *t = str; + str = new char[size*2]; + memcpy(str, t, size); + delete [] t; + p = str + size; + size *= 2; + } +#ifdef CORE_DEBUG + assert((p-str) < size); +#endif + + *p++ = c; + if (c == '.') + d = 1; + // Chen Li: fix a bug -- the sign of exponent can not happen before + // the character "e" appears! It must follow the "e' actually. + // if (e || c == '-' || c == '+') s = 1; + if (e) + s = 1; + if ((c == 'e') || (c=='E')) + e = 1; + } + + // chenli: make sure that the p is still in the range + if (p - str >= size) { + int len = p - str; + char *t = str; + str = new char[len + 1]; + memcpy(str, t, len); + delete [] t; + p = str + len; + } + +#ifdef CORE_DEBUG + assert(p - str < size); +#endif + + *p = '\0'; + i.putback(c); + fromString(str); + delete [] str; + return i; +}//operator >> + + +// BigFloatRep::toDouble() +// converts the BigFloat to a machine double +// This is a dangerous function as the method +// is silent when it does not fit into a machine double! +// ToDo: fix this by return a machine NaN, +/- Infinity, +/- 0, +// when appropriate. +// Return NaN when error is larger than mantissa +// Return +/- Infinity if BigFloat is too big +// Return +/- 0 if BigFloat is too small +#ifdef _MSC_VER +#pragma warning(disable: 4723) +#endif +CGAL_INLINE_FUNCTION +double BigFloatRep :: toDouble() const { + if (m == 0) + return (sign(m) * 0.0); + + long e2 = bits(exp); + long le = clLg(err); // if err=0, le will be -1 + if (le == -1) + le = 0; + + BigInt M = m >> static_cast(le);// remove error bits in mantissa + + // Below, we want to return NaN by computing 0.0/0.0. + // To avoid compiler warnings about divide by zero, we do this: + + double foolCompilerZero; + foolCompilerZero = 0.0; + + // COMMENT: we should directly store the + // special IEEE values NaN, +/-Infinity, +/-0 in the code!! + + if (M == 0) + return ( 0.0/foolCompilerZero ) ; // return NaN + + e2 += le; // adjust exponent corresponding to error bits + + int len = bitLength(M) - 53; // this is positive if M is too large + + if (len > 0) { + M >>= len; + e2 += len; + } + + double tt = doubleValue(M); + + int ee = e2 + bitLength(M) - 1; // real exponent. + + if (ee >= 1024) // overflow! + return ( sign(m)/foolCompilerZero ); // return a signed infinity + + if (ee <= -1075) // underflow! + // NOTE: if (-52 < ee <= 0) get denormalized number + return ( sign(m) * 0.0 ); // return signed zero. + + // Execute this loop if e2 < 0; + for (int i = 0; i > e2; i--) + tt /= 2; + + // Execute this loop if e2 > 0; + for (int j = 0; j < e2; j++) + tt *= 2; + + return tt; +}//toDouble +#ifdef _MSC_VER +#pragma warning(default: 4723) +#endif +CGAL_INLINE_FUNCTION +BigInt BigFloatRep::toBigInt() const { + long e2 = bits(exp); + long le = clLg(err); + if (le == -1) + le = 0; +#ifdef CORE_DEBUG + assert (le >= 0); +#endif + + BigInt M = m >> static_cast(le); // discard the contaminated bits. + e2 += le; // adjust the exponent + + if (e2 < 0) + return M >> static_cast(-e2); + else if (e2 > 0) + return M << static_cast(e2); + else + return M; +} + +CGAL_INLINE_FUNCTION +long BigFloatRep :: toLong() const { + // convert a BigFloat to a long integer, rounded toward -\infty. + long e2 = bits(exp); + long le = clLg(err); +#ifdef CORE_DEBUG + assert (le >= 0); +#endif + + BigInt M = m >> static_cast(le); // discard the contaminated bits. + e2 += le; // adjust the exponent + long t; + if (e2 < 0) + t = ulongValue(M >> static_cast(-e2)); + else if (e2 > 0) + t = ulongValue(M << static_cast(e2)); + else + t = ulongValue(M); + // t = M.as_long(); + // Note: as_long() will return LONG_MAX in case of overflow. + + return t; +} + +// pow(r,n) function for BigFloat +// Note: power(r,n) calls pow(r,n) +CGAL_INLINE_FUNCTION +BigFloat pow(const BigFloat& r, unsigned long n) { + if (n == 0) + return BigFloat(1); + else if (n == 1) + return r; + else { + BigFloat x = r; + while ((n % 2) == 0) { // n is even + x *= x; + n >>= 1; + } + BigFloat u = x; + while (true) { + n >>= 1; + if (n == 0) + return u; + x *= x; + if ((n % 2) == 1) // n is odd + u *= x; + } + //return u; // unreachable + } +}//pow + +// experimental +CGAL_INLINE_FUNCTION +BigFloat root(const BigFloat& x, unsigned long k, + const extLong& a, const BigFloat& A) { + if (x.sign() == 0) { + return BigFloat(0); + } else if (x == 1) { + return BigFloat(1); + } else { + BigFloat q, del, zz; + BigFloat z = A; + BigFloat bk = long(k); + for (; ;) { + zz = pow(z, k-1); + q = x.div(zz, a); + q.makeExact(); + del = z - q; + del.makeExact(); + if (del.MSB() < -a) + break; + z = ((bk-1)*z + q).div(bk, a); + // newton's iteration: z_{n+1}=((k-1)z_n+x/z_n^{k-1})/k + z.makeExact(); + } + return z; + } +}//root + +} //namespace CORE diff --git a/CGAL_Core/include/CGAL/CORE/BigInt.h b/CGAL_Core/include/CGAL/CORE/BigInt.h index 45d1fc16975..03103df37d0 100644 --- a/CGAL_Core/include/CGAL/CORE/BigInt.h +++ b/CGAL_Core/include/CGAL/CORE/BigInt.h @@ -559,4 +559,9 @@ inline BigInt randomize(const BigInt& a) { //@} } //namespace CORE + +#ifdef CGAL_HEADER_ONLY +//#include +#endif // CGAL_HEADER_ONLY + #endif // _CORE_BIGINT_H_ diff --git a/CGAL_Core/include/CGAL/CORE/CoreAux.h b/CGAL_Core/include/CGAL/CORE/CoreAux.h index ca1cbad227c..37eb1e3eb1f 100644 --- a/CGAL_Core/include/CGAL/CORE/CoreAux.h +++ b/CGAL_Core/include/CGAL/CORE/CoreAux.h @@ -181,4 +181,9 @@ inline void core_debug(std::string msg){ } //namespace CORE + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // _CORE_COREAUX_H_ diff --git a/CGAL_Core/include/CGAL/CORE/CoreAux_impl.h b/CGAL_Core/include/CGAL/CORE/CoreAux_impl.h new file mode 100644 index 00000000000..98f31a78e43 --- /dev/null +++ b/CGAL_Core/include/CGAL/CORE/CoreAux_impl.h @@ -0,0 +1,229 @@ +/**************************************************************************** + * Core Library Version 1.7, August 2004 + * Copyright (c) 1995-2004 Exact Computation Project + * All rights reserved. + * + * This file is part of CORE (http://cs.nyu.edu/exact/core/). + * You can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * Licensees holding a valid commercial license may use this file in + * accordance with the commercial license agreement provided with the + * software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * File: CoreAux.cpp + * Synopsis: + * Auxiliary routines such as ceiling of log_2, etc. + * they are not specific to any Core classes. + * + * Written by + * Chee Yap + * Chen Li + * Zilin Du + * + * WWW URL: http://cs.nyu.edu/exact/ + * Email: exact@cs.nyu.edu + * + * $URL$ + * $Id$ + ***************************************************************************/ + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include + +namespace CORE { + +//////////////////////////////////////////////////////////// +// More useful functions to implement: +// +// To convert digits into bits: +// given X, compute X * log_2(10) +// To convert bits into digits: +// given X, compute X * log_10(2) +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// flrLg(x) +// returns floor log base 2 of abs(x) +// CONVENTION lg(0) = -1 (Slight improvement, Zilin/Chee 8/5/02) +//////////////////////////////////////////////////////////// +CGAL_INLINE_FUNCTION +int flrLg(long x) { + if (x == LONG_MIN) { + // special treatment as -LONG_MIN would be not representable as "long" + return LONG_BIT - 1; + } else { + // 1 <= |x| <= LONG_MAX + if (x < 0) + x = - x; + + int lg = -1; + while (x > 0) { + lg++; + x >>= 1; + } + return lg; + } +} + +//////////////////////////////////////////////////////////// +// floor log base 2 of unsigned long x +// CONVENTION lg(0) = -1 (Slight improvement, Zilin/Chee 8/5/02) +//////////////////////////////////////////////////////////// +CGAL_INLINE_FUNCTION +int flrLg(unsigned long x) { + int lg = -1; + while (x > 0) { + lg++; + x >>= 1; + } + return lg; +} + +//////////////////////////////////////////////////////////// +// ceiling log base 2 of abs(x) +// CONVENTION lg(0) = -1 (Slight improvement, Zilin/Chee 8/5/02) +//////////////////////////////////////////////////////////// +CGAL_INLINE_FUNCTION +int clLg(long x) { + if (x == LONG_MIN) + return LONG_BIT - 1; + if (x < 0) + x = -x; // use absolute value + if (x > (LONG_MAX >> 1)) // the leading data bit is 1 + return (LONG_BIT - 1); // exclude the sign bit + if (x >= 2) + return flrLg((unsigned long)((x << 1) - 1)); + // SINCE ceilLog_2(x) = floorLog_2(2x-1) for x>=2 + if (x == 1) + return 0; + return -1; // x must be 0 here +} + +//////////////////////////////////////////////////////////// +// ceiling log base 2 of unsigned long x +// CONVENTION lg(0) = -1 +//////////////////////////////////////////////////////////// +CGAL_INLINE_FUNCTION +int clLg(unsigned long x) { + if (x > (ULONG_MAX >> 1)) // the leading bit is 1 + return LONG_BIT; + if (x >= 2) + return flrLg((x << 1) - 1); + // SINCE ceilLog_2(x) = floorLog_2(2x-1) for x>=2. + if (x == 1) + return 0; + return -1; // x must be equal to 0 +} + +/// gcd for machine type long +/** This is needed when we construct Polynomials with int or long coefficients */ +CGAL_INLINE_FUNCTION +long gcd(long m, long n) { + if (m == 0) + return core_abs(n); + if (n == 0) + return core_abs(m); + long p = core_abs(m); + long q = core_abs(n); + if (p0) { + long r = p % q; + p = q; + q = r; + } + return p; +} + +// return a gmp_randstate_t structure +CGAL_INLINE_FUNCTION +gmp_randstate_t* getRandstate() { + static gmp_randstate_t rstate; + static bool initialized = false; + if (!initialized) { + gmp_randinit(rstate, GMP_RAND_ALG_DEFAULT, 32L); + initialized = true; + } + return &rstate; +} + +// char* core_itoa(int n, char* buffer) +// returns a pointer to the null-terminated string in buffer +// NOTES: +// 0. Buffer size should be 17 bytes (resp., 33 bytes, 65 bytes) on 16-bit +// (resp., 32-bit, 64-bit) machines. Formula: 1+sizeof(int)*8 bytes. +// 1. itoa(...) is available on some stdlib.h, but it is +// not defined by ANSI-C and so not all compilers support it. +// 2. Our use of sprintf(...) to do the job is known to +// be inefficient, but this is hardly critical for our usage. +// 3. A more general program should take a 3rd argument (the radix of +// output number). We assume radix 10. +CGAL_INLINE_FUNCTION +char * core_itoa(int n, char* buffer) { + std::sprintf(buffer, "%d", n); + return buffer; +} + +/// implements the "integer mantissa" function +// (See CORE_PATH/progs/ieee/frexp.cpp for details) +CGAL_INLINE_FUNCTION +double IntMantissa(double d) { + int e; + return std::ldexp(std::frexp(d, &e), 53); +} + +/// implements the "integer exponent" function +// (See CORE_PATH/progs/ieee/frexp.cpp for details) +CGAL_INLINE_FUNCTION +int IntExponent(double d) { + int e; + std::frexp(d, &e); + return e-53; +} + +/// CORE_DIAGFILE is file name for core_error(..) output. +const char* CORE_DIAGFILE = "Core_Diagnostics"; // global file name + +/// core_error is the method to write Core Library warning or error messages +/** Both warnings and errors are written to a file called CORE_DIAGFILE. + * But errors are also written on std:cerr (similar to std::perror()). + * */ +// Usage: core_error(message, file_with_error, line_number, err_type) +// where err_type=0 means WARNING, error_type=0 means ERROR +CGAL_INLINE_FUNCTION +void core_error(std::string msg, std::string file, int lineno, bool err) { + std::ofstream outFile(CORE_DIAGFILE, std::ios::app); // open to append + if (!outFile) { + // perror("CORE ERROR: cannot open Core Diagnostics file"); + std::cerr << "CORE ERROR: can't open Core Diagnostics file"< +#ifdef CGAL_HEADER_ONLY + + #define CGAL_GLOBAL_STATE_VAR(TYPE, NAME, VALUE) \ + inline TYPE & get_static_##NAME() \ + { \ + static TYPE NAME = VALUE; \ + return NAME; \ + } + +#else // CGAL_HEADER_ONLY + + #define CGAL_GLOBAL_STATE_VAR(TYPE, NAME, VALUE) \ + CGAL_EXPORT extern TYPE NAME; \ + inline TYPE& get_static_##NAME() \ + { \ + return NAME; \ + } + +#endif // CGAL_HEADER_ONLY + namespace CORE { ////////////////////////////////////////////////////////////// @@ -60,34 +80,34 @@ namespace CORE { /** The normal behavior is to abort when an invalid expression * is constructed. This flag can be used to turn off this abort. * In any case, an error message will be printed */ -CGAL_CORE_EXPORT extern bool AbortFlag; +CGAL_GLOBAL_STATE_VAR(bool, AbortFlag, true) /// Invalid Flag -- initiallly value is non-negative /** If the Abort Flag is false, then the Invalid flag will be set to * a negative value whenever an invalid expression is constructed. * It is the user's responsibility to check this flag and to make * it non-negative again. */ -CGAL_CORE_EXPORT extern int InvalidFlag; +CGAL_GLOBAL_STATE_VAR(int, InvalidFlag, 0) /// Escape Precision in bits -CGAL_CORE_EXPORT extern extLong EscapePrec; +CGAL_GLOBAL_STATE_VAR(extLong, EscapePrec, CORE_posInfty) /// current ur when EscapePrec triggered /** this flag becomes negative when default EscapePrec is applied */ -CGAL_CORE_EXPORT extern long EscapePrecFlag; +CGAL_GLOBAL_STATE_VAR(long, EscapePrecFlag, 0) /// Escape Precision Warning Flag /** this flag is true by default, and will cause a warning to be printed when EscapePrec is reached */ -CGAL_CORE_EXPORT extern bool EscapePrecWarning; +CGAL_GLOBAL_STATE_VAR(bool, EscapePrecWarning, true) // These following two values determine the precision of computing // approximations in Expr. /// default Relative Precision in bits -CGAL_CORE_EXPORT extern extLong defRelPrec; +CGAL_GLOBAL_STATE_VAR(extLong, defRelPrec, 60) /// default Absolute Precision in bits -CGAL_CORE_EXPORT extern extLong defAbsPrec; +CGAL_GLOBAL_STATE_VAR(extLong, defAbsPrec, CORE_posInfty) /// default # of decimal digits for conversion from a BF to string. /** This value cannot be CORE_INFTY. @@ -97,42 +117,41 @@ CGAL_CORE_EXPORT extern extLong defAbsPrec; "controls the printout precision of std::cout for BigFloat" Perhaps, we should merge defOutputDigits and defBigFloatOutputDigits? */ -CGAL_CORE_EXPORT extern long defBigFloatOutputDigits; +CGAL_GLOBAL_STATE_VAR(long, defBigFloatOutputDigits, 10) /// default input precision in digits for converting a string to a Real or Expr /** This value can be CORE_INFTY */ -CGAL_CORE_EXPORT extern extLong defInputDigits; +CGAL_GLOBAL_STATE_VAR(extLong, defInputDigits, CORE_posInfty) /// controls the printout precision of std::cout for Real and Expr /** This value cannot be CORE_INFTY See also defBigFloatOutputDigits. (it really should be an int, as in std::cout.setprecision(int)). */ -CGAL_CORE_EXPORT extern long defOutputDigits; +CGAL_GLOBAL_STATE_VAR(long, defOutputDigits, get_static_defBigFloatOutputDigits()) /// default input precision in digits for converting a string to a BigFloat /** This value cannot be CORE_INFTY. */ -CGAL_CORE_EXPORT extern long defBigFloatInputDigits; +CGAL_GLOBAL_STATE_VAR(long, defBigFloatInputDigits, 16) /// default BigFloat Division Relative Precision -CGAL_CORE_EXPORT extern extLong defBFdivRelPrec; - +CGAL_GLOBAL_STATE_VAR(extLong, defBFdivRelPrec, 54) /// default BigFloat Sqrt Absolute Precision -CGAL_CORE_EXPORT extern extLong defBFsqrtAbsPrec; +CGAL_GLOBAL_STATE_VAR(extLong, defBFsqrtAbsPrec, 54) ////////////////////////////////////////////////////////////// // Mode parameters: incremental, progressive, filters ////////////////////////////////////////////////////////////// /// floating point filter flag -CGAL_CORE_EXPORT extern bool fpFilterFlag; +CGAL_GLOBAL_STATE_VAR(bool, fpFilterFlag, true) /// if true, evaluation of expressions would be incremental -CGAL_CORE_EXPORT extern bool incrementalEvalFlag; +CGAL_GLOBAL_STATE_VAR(bool, incrementalEvalFlag, true) /// progressive evaluation flag -CGAL_CORE_EXPORT extern bool progressiveEvalFlag; +CGAL_GLOBAL_STATE_VAR(bool, progressiveEvalFlag, true) /// rational reduction flag -CGAL_CORE_EXPORT extern bool rationalReduceFlag; +CGAL_GLOBAL_STATE_VAR(bool, rationalReduceFlag, false) /// default initial (bit) precision for AddSub Progressive Evaluation -CGAL_CORE_EXPORT extern long defInitialProgressivePrec; +CGAL_GLOBAL_STATE_VAR(long, defInitialProgressivePrec, 64) ////////////////////////////////////////////////////////////// // methods for setting global precision parameters @@ -144,87 +163,87 @@ CGAL_CORE_EXPORT extern long defInitialProgressivePrec; /** It determines the precision to which an Expr evaluates its (exact, implicit) constant value. */ inline void setDefaultPrecision(const extLong &r, const extLong &a) { - defRelPrec = r; - defAbsPrec = a; + get_static_defRelPrec() = r; + get_static_defAbsPrec() = a; } /// set default relative precision inline extLong setDefaultRelPrecision(const extLong &r) { - extLong old = defRelPrec; - defRelPrec = r; + extLong old = get_static_defRelPrec(); + get_static_defRelPrec() = r; return old; } /// set default absolute precision inline extLong setDefaultAbsPrecision(const extLong &a) { - extLong old = defAbsPrec; - defAbsPrec = a; + extLong old = get_static_defAbsPrec(); + get_static_defAbsPrec() = a; return old; } /// set default input digits (for Expr, Real) /** it controls the absolute error */ inline extLong setDefaultInputDigits(const extLong &d) { - extLong old = defInputDigits; - defInputDigits = d; + extLong old = get_static_defInputDigits(); + get_static_defInputDigits() = d; return old; } /// set default output digits (for Expr, Real) -inline long setDefaultOutputDigits(long d = defOutputDigits, +inline long setDefaultOutputDigits(long d = get_static_defOutputDigits(), std::ostream& o = std::cout) { - long old = defOutputDigits; - defOutputDigits = d; + long old = get_static_defOutputDigits(); + get_static_defOutputDigits() = d; o.precision(d); return old; } /// set default input digits for BigFloat inline long setDefaultBFInputDigits(long d) { - long old = defBigFloatInputDigits; - defBigFloatInputDigits = d; + long old = get_static_defBigFloatInputDigits(); + get_static_defBigFloatInputDigits() = d; return old; } /// set default output digits for BigFloat inline long setDefaultBFOutputDigits(long d) { - long old = defBigFloatOutputDigits; - defBigFloatOutputDigits = d; + long old = get_static_defBigFloatOutputDigits(); + get_static_defBigFloatOutputDigits() = d; return old; } /// turn floating-point filter on/off inline bool setFpFilterFlag(bool f) { - bool oldf = fpFilterFlag; - fpFilterFlag = f; + bool oldf = get_static_fpFilterFlag(); + get_static_fpFilterFlag() = f; return oldf; } /// turn incremental evaluation flag on/off inline bool setIncrementalEvalFlag(bool f) { - bool oldf = incrementalEvalFlag; - incrementalEvalFlag = f; + bool oldf = get_static_incrementalEvalFlag(); + get_static_incrementalEvalFlag() = f; return oldf; } /// turn progressive evaluation flag on/off inline bool setProgressiveEvalFlag(bool f) { - bool oldf = progressiveEvalFlag; - progressiveEvalFlag = f; + bool oldf = get_static_progressiveEvalFlag(); + get_static_progressiveEvalFlag() = f; return oldf; } /// set initial bit precision for progressive evaluation: inline long setDefInitialProgressivePrec(long n) { - long oldn = defInitialProgressivePrec; - defInitialProgressivePrec = n; + long oldn = get_static_defInitialProgressivePrec(); + get_static_defInitialProgressivePrec() = n; return oldn; } /// turn rational reduction flag on/off inline bool setRationalReduceFlag(bool f) { - bool oldf = rationalReduceFlag; - rationalReduceFlag = f; + bool oldf = get_static_rationalReduceFlag(); + get_static_rationalReduceFlag() = f; return oldf; } @@ -235,9 +254,9 @@ inline bool setRationalReduceFlag(bool f) { e.g., overriding the default std::cout precision (most systems initializes this value to 6) to our own */ inline void CORE_init(long d) { - defAbsPrec = CORE_posInfty; - defOutputDigits = d; - std::setprecision(defOutputDigits); + get_static_defAbsPrec() = CORE_posInfty; + get_static_defOutputDigits() = d; + std::setprecision(get_static_defOutputDigits()); } /// change to scientific output format @@ -251,4 +270,9 @@ inline void setPositionalFormat(std::ostream& o = std::cout) { } } //namespace CORE + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // _CORE_COREDEFS_H_ diff --git a/CGAL_Core/include/CGAL/CORE/CoreDefs_impl.h b/CGAL_Core/include/CGAL/CORE/CoreDefs_impl.h new file mode 100644 index 00000000000..b74464b902b --- /dev/null +++ b/CGAL_Core/include/CGAL/CORE/CoreDefs_impl.h @@ -0,0 +1,163 @@ +/**************************************************************************** + * Core Library Version 1.7, August 2004 + * Copyright (c) 1995-2004 Exact Computation Project + * All rights reserved. + * + * This file is part of CORE (http://cs.nyu.edu/exact/core/). + * You can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * Licensees holding a valid commercial license may use this file in + * accordance with the commercial license agreement provided with the + * software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * File: CoreDefs.cpp + * Synopsis: + * Useful parameters for Core Library which users may change + * + * Written by + * Chee Yap + * Chen Li + * Zilin Du + * + * WWW URL: http://cs.nyu.edu/exact/ + * Email: exact@cs.nyu.edu + * + * $URL$ + * $Id$ + ***************************************************************************/ + +#include "CGAL/CORE/CoreDefs.h" + +namespace CORE { + +// Default Values + +/* ************************************************************ + * ERROR FLAGS + * ************************************************************ */ + +#ifndef CGAL_HEADER_ONLY + +/** I/O error flag (Default value 0, indicating no error) + * User's responsibility to check and reset value to 0. */ +// This is currently used in geom2d/points2d.cpp for I/O of points + +// Note from 2014: does not seem to be used anywhere, and it is not declared +// in CoreDefs.h so it is not accessible +// Left here for compatibilty when CGAL_HEADER_ONLY is not defined + +int IOErrorFlag = 0; + +/** + * If AbortFlag is true when invalid expression is constructed, system will abort + */ + +bool AbortFlag = true; + +/** + * InvalidFlag is set to negative whenever an invalid expression is constructed. + * The user has the responsibility to reset to non-negative value. + */ + +int InvalidFlag = 0; + +/* ************************************************************ + * PRECISION PARAMETERS + * ************************************************************ */ + +/** + * Default BigFloat Division Relative Precision + * -- this is used by BigFloat division when the arguments are error-free. + */ + +extLong defBFdivRelPrec = 54; + +/** + * Default BigFloat Sqrt Absolute Precision + * -- this is used by BigFloat sqrt when the argument is error-free. + */ + +extLong defBFsqrtAbsPrec = 54; + +/** + * Escape Precision + * -- we will not compare a number to precision higher than this + * -- if this is infinity, there there is no escape precision */ +extLong EscapePrec = CORE_posInfty; + +/** this flag becomes negative if the EscapePrec is used. */ +long EscapePrecFlag = 0; + +/// Escape Precision Warning Flag +/** this flag is true by default, and will cause a warning to be printed + when EscapePrec is reached */ +bool EscapePrecWarning = true; + +/** The Composite Precision [defAbsPrec, defRelPrec] + * determines the precision to which an Expr evaluates its + * (exact, implicit) constant value. */ + +/** absolute precision = 2^31 - 1 */ +extLong defAbsPrec = CORE_posInfty; +/** default relative precision is 60 relative bits. + * Why 60? We would really like this to be 54, so that the default + * conversion duplicates the IEEE double precision. But it turns out + * (see README file under BUGS), we need 59 to ensure this. + * Chee Yap (7/1/01) */ +extLong defRelPrec = 60; + +/** number of BigFloat digits to print out */ +long defBigFloatOutputDigits = 10; + +/** NORMALLY, we like to make this equal to defBigFloatOutputDigits + * 8/3/01, Chee: re-introduced this parameter */ +long defOutputDigits = defBigFloatOutputDigits; + +/** String Input Precision */ + +/** Set this to 16 if you want machine precision. This controls the + * absolute error in string decimal inputs to Real or Expr. + * If defInputDigits is finite, then the absolute error will be + * at most 10^{-defInputDigits}. Otherwise, the input is exactly + * represented by some BigFloat or BigRat value. */ +extLong defInputDigits = CORE_posInfty; + +/** This controls the absolute error in converting from string to BigFloat + * The absolute error will be at most 10^{-defInputDigits} */ +long defBigFloatInputDigits = 16; + +/* ************************************************************ + * EVALUATION FLAGS + * ************************************************************ */ + +/** Floating Point filter + * true = turn on floating point filter */ +bool fpFilterFlag = true; + +/** IncrementaL evaluation flag + * incremental evaluation is requested, This means, we try to use previous + * approximate values to improve an approximation */ +bool incrementalEvalFlag = true; + +/** Progressive evaluation flag + * true = turn on progressive evaluation flag */ +bool progressiveEvalFlag = true; + +/** Initial progressive evaluation precision + * Used by AddSubRep */ +long defInitialProgressivePrec = 64; + +/** RATIONAL REDUCTION FLAG + * true = turn on rational reduction */ +bool rationalReduceFlag = false; + +#endif // CGAL_HEADER_ONLY + +} //namespace CORE + diff --git a/CGAL_Core/include/CGAL/CORE/CoreIO_impl.h b/CGAL_Core/include/CGAL/CORE/CoreIO_impl.h new file mode 100644 index 00000000000..2e3e10bcd8f --- /dev/null +++ b/CGAL_Core/include/CGAL/CORE/CoreIO_impl.h @@ -0,0 +1,488 @@ +/**************************************************************************** + * Core Library Version 1.7, August 2004 + * Copyright (c) 1995-2004 Exact Computation Project + * All rights reserved. + * + * This file is part of CORE (http://cs.nyu.edu/exact/core/). + * You can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * Licensees holding a valid commercial license may use this file in + * accordance with the commercial license agreement provided with the + * software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * File: CoreIO.cpp + * + * Written by + * Zilin Du + * Chee Yap + * + * WWW URL: http://cs.nyu.edu/exact/ + * Email: exact@cs.nyu.edu + * + * $URL$ + * $Id$ + ***************************************************************************/ + +#ifndef _COREIO_IMPL_H_ +#define _COREIO_IMPL_H_ + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#ifdef CGAL_HEADER_ONLY +#define CGAL_HEADERONLY_STATIC_FUNCTION static +#else +#define CGAL_HEADERONLY_STATIC_FUNCTION +#endif + +#include +#include +#include + +namespace CORE { + +CGAL_HEADERONLY_STATIC_FUNCTION +void core_io_error_handler(const char *f, const char *m) { + std::cout << "\n error_handler"; + std::cout << "::" << f << "::" << m << "\n"; + std::cout.flush(); + std::abort(); +} + +CGAL_HEADERONLY_STATIC_FUNCTION +void core_io_memory_handler(char *t, const char *f, const char *m) { + if (t == NULL) { + std::cout << "\n memory_handler"; + std::cout << "::" << f << "::" << m; + std::cout << "memory exhausted\n"; + std::cout.flush(); + std::abort(); + } +} + +// s has size old_size and will be resized to new_size. +CGAL_HEADERONLY_STATIC_FUNCTION +void allocate (char * &s, int old_size, int new_size) { + if (old_size > new_size) + old_size = new_size; + + if (s == NULL) + old_size = 0; + + char *t = new char[new_size]; + core_io_memory_handler(t, "CoreIO", "allocate::out of memory error"); + + int i; + for (i = 0; i < old_size; i++) + t[i] = s[i]; + + delete[] s; + s = t; +} + +// appends c to s at position pos. +// sz is the size of s +CGAL_HEADERONLY_STATIC_FUNCTION +void append_char (char * &s, int & sz, int pos, char c) { + if (pos > sz) + core_io_error_handler("CoreIO", "append_char::invalid argument"); + + if (pos == sz) { + allocate(s, sz, 2*sz); + sz *= 2; + } + + s[pos] = c; +} + +// skip blanks, tabs, line breaks and comment lines +CGAL_HEADERONLY_STATIC_FUNCTION +int skip_comment_line (std::istream & in) { + int c; + + do { + c = in.get(); + while ( c == '#' ) { + do { + c = in.get(); + } while ( c != '\n' ); + c = in.get(); + } + } while (c == ' ' || c == '\t' || c == '\n'); + + if (c == EOF) + core_io_error_handler("CoreIO::read_from_file()","unexpected end of file."); + + in.putback(c); + return c; +} + +// skips '\\' followed by '\n' +CGAL_HEADERONLY_STATIC_FUNCTION +int skip_backslash_new_line (std::istream & in) { + int c = in.get(); + + while (c == '\\') { + c = in.get(); + + if (c == '\n') + c = in.get(); + else + core_io_error_handler("CoreIO::operator>>", "\\ must be immediately followed by new line."); + } + + return c; +} + +CGAL_HEADERONLY_STATIC_FUNCTION +void read_string(std::istream& in, char* &buffer, int sz) { + int c, pos=0; + skip_comment_line(in); + + while ( (c = in.get()) != EOF ) { + if ( c == ' ' || c == '\t' || c == '\n' || c == '#') + break; + else + append_char(buffer, sz, pos++, c); + } + append_char(buffer, sz, pos, '\0'); +} + +CGAL_HEADERONLY_STATIC_FUNCTION +void read_base_number(std::istream& in, BigInt& m, long length, long maxBits) { + char *buffer; + int size, offset; + int base; + bool is_negate; + + int c, pos = 0; + skip_comment_line(in); + + // read sign + c = in.get(); + if (c == '-') { + is_negate = true; + c = in.get(); + } else + is_negate = false; + + // read base and compute digits + if (c == '0') { + c = in.get(); + if (c == 'b') { + base = 2; + size = (maxBits == 0 || maxBits > length) ? length : maxBits; + offset = length - size; + } else if (c == 'x') { + base = 16; + size = (maxBits == 0) ? length : (maxBits+3) >> 2; + size = (size > length) ? length : size; + offset = (length - size) << 2; + } else { + base = 8; + size = (maxBits == 0) ? length : (maxBits+2) / 3; + size = (size > length) ? length : size; + offset = (length - size) * 3; + in.putback(c); + } + } else { + base = 10; + size = (maxBits == 0) ? length : (int)std::ceil(maxBits*std::log(2.0)/std::log(10.0)); + size = (size > length) ? length : size; + offset = length - size; + in.putback(c); + } + + buffer = new char[size+2]; + // read digits + for (int i=0; (i 0 && base != 10) { + m <<= offset; + } + + if (is_negate) + negate(m); +} + + +CGAL_HEADERONLY_STATIC_FUNCTION +void write_base_number(std::ostream& out, char* buffer, int length, int base, int charsPerLine) { + // write big number in a format that gmp's mpz_set_str() can + // automatically recognize with argument base = 0. + if (base == 2) + out << "0b"; + else if (base == 16) + out << "0x"; + else if (base == 8) + out << '0'; + + // write big number in charsPerLine. + char* start, *end, c; + for (int i=0; i= length) + out << start; + else { + end = start + charsPerLine; + c = *end; + *end = '\0'; + + out << start << "\\\n"; + *end = c; + } + } +} + +CGAL_INLINE_FUNCTION +void readFromFile(BigInt& z, std::istream& in, long maxLength) { + char *buffer; + long length; + + // check type name whether it is Integer or not. + buffer = new char[8]; + read_string(in, buffer, sizeof(buffer)); + if ( std::strcmp(buffer, "Integer") != 0) + core_io_error_handler("BigInt::read_from_file()","type name expected."); + delete[] buffer; + + // read the bit length field. + buffer = new char[100]; + read_string(in, buffer, sizeof(buffer)); + length = std::atol(buffer); + delete[] buffer; + + // read bigint + read_base_number(in, z, length, maxLength); +} + +CGAL_INLINE_FUNCTION +void writeToFile(const BigInt& z, std::ostream& out, int base, int charsPerLine) { + BigInt c = abs(z); + + // get the absoulte value string + char* buffer = new char[mpz_sizeinbase(c.get_mp(), base) + 2]; + mpz_get_str(buffer, base, c.get_mp()); + int length = std::strlen(buffer); + + // write type name of big number and length + //out << "# This is an experimental big number format.\n"; + out << "Integer " << length << "\n"; + + // if bigint is negative, then write an sign '-'. + if ( sign(z) < 0 ) + out << '-'; + + write_base_number(out, buffer, length, base, charsPerLine); + out << "\n"; + delete[] buffer; +} + +CGAL_INLINE_FUNCTION +void readFromFile(BigFloat& bf, std::istream& in, long maxLength) { + char *buffer; + long length; + long exponent; + BigInt mantissa; + + // check type name whether it is Float + buffer = new char[6]; + read_string(in, buffer, sizeof(buffer)); + if (std::strcmp(buffer, "Float") != 0) + core_io_error_handler("BigFloat::read_from_file()", "type name expected"); + delete[] buffer; + + // read base (default is 16384) + buffer = new char[8]; + read_string(in, buffer, sizeof(buffer)); + if (std::strcmp(buffer, "(16384)") != 0) + core_io_error_handler("BigFloat::read_from_file()", "base expected"); + delete[] buffer; + + // read the bit length field. + buffer = new char[100]; + read_string(in, buffer, sizeof(buffer)); + length = std::atol(buffer); + delete[] buffer; + + // read exponent + buffer = new char[100]; + read_string(in, buffer, sizeof(buffer)); + exponent = std::atol(buffer); + delete[] buffer; + + // read mantissa + read_base_number(in, mantissa, length, maxLength); + + // construct BigFloat + bf = BigFloat(mantissa, 0, exponent); +} + +CGAL_INLINE_FUNCTION +void writeToFile(const BigFloat& bf, std::ostream& out, int base, int charsPerLine) { + BigInt c(CORE::abs(bf.m())); + + // get the absoulte value string + char* buffer = new char[mpz_sizeinbase(c.get_mp(), base) + 2]; + mpz_get_str(buffer, base, c.get_mp()); + int length = std::strlen(buffer); + + + // write type name, base, length + //out << "# This is an experimental Big Float format." << std::endl; + out << "Float (16384) " << length << std::endl; + // write exponent + out << bf.exp() << std::endl; + + // write mantissa + if ( CORE::sign(bf.m()) < 0 ) + out << '-'; + + write_base_number(out, buffer, length, base, charsPerLine); + out << '\n'; + delete[] buffer; +} + +/* Underconstruction ---- +void BigFloat::read_from_file2(std::istream& in, long maxLength) { + long length = 1024; + char *buffer; + + // check type name whether it is Float + buffer = new char[7]; + BigInt::read_string(in, buffer, sizeof(buffer)); + if (strcmp(buffer, "NFloat") != 0) + core_io_error_handler("BigFloat::read_from_file2()", "type name expected"); + delete[] buffer; + + // read base (default is 16) + buffer = new char[5]; + BigInt::read_string(in, buffer, sizeof(buffer)); + if (strcmp(buffer, "(16)") != 0) + core_io_error_handler("BigFloat::read_from_file2()", "base expected"); + delete[] buffer; + + // read length field + buffer = new char[100]; + BigInt::read_string(in, buffer, sizeof(buffer)); + + // get the length field if it is not null. + if (buffer[0] != '\0') { + length = atol(buffer); + if (maxLength > 0 && length >= maxLength) + length = maxLength; + } + delete[] buffer; + + // read exponent + buffer = new char[100]; + BigInt::read_string(in, buffer, sizeof(buffer)); + long exp16 = atol(buffer); + delete[] buffer; + + // read mantissa + buffer = new char[length+2]; + //BigInt::read_base_number(in, buffer, length); + + BigInt m16(buffer); + delete[] buffer; + + // convert to base CHUNK_BIT + exp16 = exp16 - length + 1; + if ( m16.is_negative() ) + exp16 ++; + + long tmp_exp = exp16 * 4; + long q = tmp_exp / CHUNK_BIT; + long r = tmp_exp % CHUNK_BIT; + if ( r < 0 ) { + r += CHUNK_BIT; + q --; + } + + BigInt mantissa = m16 << r; + long exponent = q; + + // construct BigFloat + if (--rep->refCount == 0) + delete rep; + + rep = new BigFloatRep(mantissa, 0, exponent); + rep->refCount++; + +} + +// write normal float +// now it assumed to write in hex base, i.e. B=2^4=16 +// (note: our default base B=2^(CHUNK_BIT)=2^14=16384 +void BigFloat::write_to_file2(std::ostream& out, int base, int charsPerLine) { + // convert to base 16. + long new_base = 4; // 2^4 = 16 + long tmp_exp = (rep->exp) * CHUNK_BIT; + long q = tmp_exp / new_base; + long r = tmp_exp % new_base; + std::cout << "CORE_DEBUG: q=" << q << ", r=" << r << std::endl; + if ( r < 0 ) { + r += new_base; + q--; + } + std::cout << "CORE_DEBUG: q=" << q << ", r=" << r << std::endl; + + BigInt m16 = (rep->m) << r; + + int size = mpz_sizeinbase(m16.I, base) + 2; + std::cout << "size=" << size << std::endl; + char* buffer = new char[size]; + + int length = bigint_to_string(m16, buffer, base); + std::cout << "length=" << length << std::endl; + + long exp16 = q + length - 1; + if ( m16.is_negative() ) + exp16 --; + + // write type name, base, length + out << "# This is an experimental Big Float format." << std::endl; + out << "NFloat (16) " << length << std::endl; + + // write exponent + out << exp16 << std::endl; + + // write mantissa + if ( m16.is_negative() ) { + out << '-'; + buffer ++; + } + + BigInt::write_base_number(out, buffer, length, base, charsPerLine); + out << '\n'; + delete[] buffer; +} +*/ + +} //namespace CORE + +#endif // _COREIO_IMPL_H_ diff --git a/CGAL_Core/include/CGAL/CORE/Expr.h b/CGAL_Core/include/CGAL/CORE/Expr.h index f1215cdf985..6768c64a244 100644 --- a/CGAL_Core/include/CGAL/CORE/Expr.h +++ b/CGAL_Core/include/CGAL/CORE/Expr.h @@ -36,6 +36,10 @@ * $Id$ ***************************************************************************/ +// We need to include BigFloat.h here because there is a circular dependency +// between Expr and BigFloat. +#include + #ifndef _CORE_EXPR_H_ #define _CORE_EXPR_H_ @@ -79,9 +83,9 @@ public: // (i.e., not infinite and not NaN) if (! CGAL_CORE_finite(f)) { std::cerr << " ERROR : constructed an invalid float! " << std::endl; - if (AbortFlag) + if (get_static_AbortFlag()) abort(); - InvalidFlag = -1; + get_static_InvalidFlag() = -1; } rep = new ConstDoubleRep(f); } @@ -90,9 +94,9 @@ public: // (i.e., not infinite and not NaN) if (! CGAL_CORE_finite(d)) { std::cerr << " ERROR : constructed an invalid double! " << std::endl; - if (AbortFlag) + if (get_static_AbortFlag()) abort(); - InvalidFlag = -2; + get_static_InvalidFlag() = -2; } rep = new ConstDoubleRep(d); } @@ -112,11 +116,11 @@ public: * it is generally recommended that the (String) constructor be used in * preference to the (double) constructor. */ - Expr(const char *s, const extLong& p = defInputDigits) + Expr(const char *s, const extLong& p = get_static_defInputDigits()) : RCExpr(new ConstRealRep(Real(s, p))) {} /// constructor for std::string - Expr(const std::string& s, const extLong& p = defInputDigits) + Expr(const std::string& s, const extLong& p = get_static_defInputDigits()) : RCExpr(new ConstRealRep(Real(s, p))) {} /// constructor for Real @@ -180,9 +184,9 @@ public: Expr& operator/=(const Expr& e) { if ((e.rep)->getSign() == 0) { std::cerr << " ERROR : division by zero ! " << std::endl; - if (AbortFlag) + if (get_static_AbortFlag()) abort(); - InvalidFlag = -3; + get_static_InvalidFlag() = -3; } *this = new DivRep(rep, e.rep); return *this; @@ -226,12 +230,12 @@ public: /// \name String Conversion Functions //@{ /// set value from const char* - void fromString(const char* s, const extLong& prec = defInputDigits) { + void fromString(const char* s, const extLong& prec = get_static_defInputDigits()) { *this = Expr(s, prec); } /// convert to std::string /** give decimal string representation */ - std::string toString(long prec=defOutputDigits, bool sci=false) const { + std::string toString(long prec=get_static_defOutputDigits(), bool sci=false) const { return rep->toString(prec, sci); } //@} @@ -283,8 +287,8 @@ public: /** Here is the definition of what this means: If e is the exact value and ee is the approximate value, then |e - ee| <= 2^{-a} or |e - ee| <= 2^{-r} |e|. */ - const Real & approx(const extLong& relPrec = defRelPrec, - const extLong& absPrec = defAbsPrec) const { + const Real & approx(const extLong& relPrec = get_static_defRelPrec(), + const extLong& absPrec = get_static_defAbsPrec()) const { return rep->getAppValue(relPrec, absPrec); } //@} @@ -356,7 +360,7 @@ inline std::ostream& operator<<(std::ostream& o, const Expr& e) { /// I/O Stream operator>> inline std::istream& operator>>(std::istream& i, Expr& e) { Real rVal; - i >> rVal; // precision is = defInputDigits + i >> rVal; // precision is = get_static_defInputDigits() if (i) e = rVal; // only assign when reading is successful. return i; @@ -383,9 +387,9 @@ inline Expr operator*(const Expr& e1, const Expr& e2) { inline Expr operator/(const Expr& e1, const Expr& e2) { if (e2.sign() == 0) { std::cerr << " ERROR : division by zero ! " << std::endl; - if (AbortFlag) + if (get_static_AbortFlag()) abort(); - InvalidFlag = -4; + get_static_InvalidFlag() = -4; } return Expr(new DivRep(e1.Rep(), e2.Rep())); } @@ -486,9 +490,9 @@ inline bool isDivisible(const Expr& e1, const Expr& e2) { inline Expr sqrt(const Expr& e) { if (e.sign() < 0) { std::cerr << " ERROR : sqrt of negative value ! " << std::endl; - if (AbortFlag) + if (get_static_AbortFlag()) abort(); - InvalidFlag = -5; + get_static_InvalidFlag() = -5; } return Expr(new SqrtRep(e.Rep())); } @@ -549,4 +553,9 @@ inline Expr radical(const NT& n, int m) { #include } //namespace CORE + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // _CORE_EXPR_H_ diff --git a/CGAL_Core/include/CGAL/CORE/ExprRep.h b/CGAL_Core/include/CGAL/CORE/ExprRep.h index 5c2bf59ed59..8ae250f9923 100644 --- a/CGAL_Core/include/CGAL/CORE/ExprRep.h +++ b/CGAL_Core/include/CGAL/CORE/ExprRep.h @@ -45,7 +45,7 @@ namespace CORE { -#ifdef CORE_DEBUG_BOUND +#if defined(CORE_DEBUG_BOUND) && !defined(CGAL_HEADER_ONLY) // These counters are incremented each time each bound is recognized as equal // to the best one in computeBound(). extern unsigned int BFMSS_counter; @@ -189,8 +189,8 @@ public: /// \name Helper Functions //@{ /// Get the approximate value - CGAL_CORE_EXPORT const Real & getAppValue(const extLong& relPrec = defRelPrec, - const extLong& absPrec = defAbsPrec); + CGAL_CORE_EXPORT const Real & getAppValue(const extLong& relPrec = get_static_defRelPrec(), + const extLong& absPrec = get_static_defAbsPrec()); /// Get the sign. int getSign(); int getExactSign(); @@ -389,8 +389,8 @@ public: BigFloat BigFloatValue(); /// represent as a string in decimal value // toString() Joaquin Grech 31/5/2003 - std::string toString(long prec=defOutputDigits, bool sci=false) { - return (getAppValue(defRelPrec, defAbsPrec)).toString(prec,sci); + std::string toString(long prec=get_static_defOutputDigits(), bool sci=false) { + return (getAppValue(get_static_defRelPrec(), get_static_defAbsPrec())).toString(prec,sci); } //@} @@ -677,7 +677,7 @@ protected: tc() = ceilLg(ss.seq[0].getTailCoeff()); // no rational reduction - if (rationalReduceFlag) + if (get_static_rationalReduceFlag()) ratFlag() = -1; flagsComputed() = true; @@ -838,7 +838,12 @@ protected: /// \brief "functor" class used as parameter to AddSubRep<> struct Add { /// name +#ifndef CGAL_HEADER_ONLY CGAL_CORE_EXPORT static const char* name; +#endif + static const char* get_name() { + return "+"; + } /// unary operator template @@ -857,7 +862,12 @@ struct Add { /// \brief "functor" class used as parameter to AddSubRep<> struct Sub { /// name +#ifndef CGAL_HEADER_ONLY CGAL_CORE_EXPORT static const char* name; +#endif + static const char* get_name() { + return "-"; + } /// unary operator template @@ -895,7 +905,7 @@ protected: void computeApproxValue(const extLong&, const extLong&); /// return operator in string const std::string op() const { - return Operator::name; + return Operator::get_name(); } private: static Operator Op; @@ -925,7 +935,7 @@ void AddSubRep::computeExactFlags() { reduceTo(second); sign() = Op(ss); appValue() = Op(appValue()); - if (rationalReduceFlag && ratFlag() > 0) + if (get_static_rationalReduceFlag() && ratFlag() > 0) *(ratValue()) = Op(*(ratValue())); return; } else if (ss == 0) { // second operand is zero @@ -933,7 +943,7 @@ void AddSubRep::computeExactFlags() { return; } // rational node - if (rationalReduceFlag) { + if (get_static_rationalReduceFlag()) { if (first->ratFlag() > 0 && second->ratFlag() > 0) { BigRat val=Op(*(first->ratValue()), *(second->ratValue())); reduceToBigRat(val); @@ -1046,7 +1056,7 @@ void AddSubRep::computeExactFlags() { if (lowBound <= EXTLONG_ZERO) lowBound = EXTLONG_ONE; - if (!progressiveEvalFlag) { + if (!get_static_progressiveEvalFlag()) { // convert the absolute error requirement "lowBound" to // a relative error requirement "ur", s.t. // |x|*2^(-ur) <= 2^(-lowBound). @@ -1085,7 +1095,7 @@ void AddSubRep::computeExactFlags() { // larger than lowBound AND the defaultInitialProgressivePrec, // so that we do at least one iteration of the for-loop. So: // i is the variable for iteration. - extLong i = core_min(defInitialProgressivePrec, lowBound.asLong()); + extLong i = core_min(get_static_defInitialProgressivePrec(), lowBound.asLong()); extLong ua = lowBound.asLong() + EXTLONG_ONE; // NOTE: ua is allowed to be CORE_INFTY @@ -1096,7 +1106,7 @@ void AddSubRep::computeExactFlags() { lMSB() = CORE_negInfty; sign() = 0; - EscapePrecFlag = 0; // reset the Escape Flag + get_static_EscapePrecFlag() = 0; // reset the Escape Flag // Now we try to determine the real lMSB and sign, // in case it is not really zero: @@ -1151,22 +1161,22 @@ void AddSubRep::computeExactFlags() { break; // assert -- this must happen in the loop if nonzero! } //8/9/01, Chee: implement escape precision here: - if (i> EscapePrec) { - EscapePrecFlag = -i.asLong();//negative means EscapePrec is used + if (i> get_static_EscapePrec()) { + get_static_EscapePrecFlag() = -i.asLong();//negative means EscapePrec is used core_error("Escape precision triggered at", __FILE__, __LINE__, false); - if (EscapePrecWarning) + if (get_static_EscapePrecWarning()) std::cout<< "Escape Precision triggered at " - << EscapePrec << " bits" << std::endl; + << get_static_EscapePrec() << " bits" << std::endl; #ifdef CORE_DEBUG - std::cout << "EscapePrecFlags=" << EscapePrecFlag << std::endl; + std::cout << "EscapePrecFlags=" << get_static_EscapePrecFlag() << std::endl; std::cout << "ua =" << ua << ",lowBound=" << lowBound << std::endl; #endif break; }// if }// for (long i=1...) -#ifdef CORE_DEBUG_BOUND +#if defined(CORE_DEBUG_BOUND) && !defined(CGAL_HEADER_ONLY) rootBoundHitCounter++; #endif diff --git a/CGAL_Core/include/CGAL/CORE/Expr_impl.h b/CGAL_Core/include/CGAL/CORE/Expr_impl.h new file mode 100644 index 00000000000..42ef3136c61 --- /dev/null +++ b/CGAL_Core/include/CGAL/CORE/Expr_impl.h @@ -0,0 +1,1213 @@ +/**************************************************************************** + * Core Library Version 1.7, August 2004 + * Copyright (c) 1995-2004 Exact Computation Project + * All rights reserved. + * + * This file is part of CORE (http://cs.nyu.edu/exact/core/). + * You can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * Licensees holding a valid commercial license may use this file in + * accordance with the commercial license agreement provided with the + * software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * File: Expr.cpp + * + * Written by + * Koji Ouchi + * Chee Yap + * Igor Pechtchanski + * Vijay Karamcheti + * Chen Li + * Zilin Du + * Sylvain Pion + * + * WWW URL: http://cs.nyu.edu/exact/ + * Email: exact@cs.nyu.edu + * + * $URL$ + * $Id$ + ***************************************************************************/ + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include + +namespace CORE { + +#if defined(CORE_DEBUG_BOUND) && !defined(CGAL_HEADER_ONLY) +unsigned int BFMSS_counter = 0; +unsigned int BFMSS_only_counter = 0; +unsigned int Measure_counter = 0; +unsigned int Measure_only_counter = 0; +unsigned int Cauchy_counter = 0; +unsigned int Cauchy_only_counter = 0; +unsigned int LiYap_counter = 0; +unsigned int LiYap_only_counter = 0; +unsigned int rootBoundHitCounter = 0; +unsigned int computeBoundCallsCounter = 0; +#endif + +#ifndef CGAL_HEADER_ONLY +const char* Add::name = "+"; +const char* Sub::name = "-"; +#endif + +/******************************************************** + * class Expr + ********************************************************/ +CGAL_INLINE_FUNCTION +const Expr& Expr::getZero() { + static Expr Zero(0); + return Zero; +} +CGAL_INLINE_FUNCTION +const Expr& Expr::getOne() { + static Expr One(1); + return One; +} + +// computes an interval comprising a pair of doubles +// Note: +// +// This function returns are two consecutive representable binary +// IEEE double values whichs contain the real value, but when you print out +// them, you might be confused by the decimal represention due to round. +// +CGAL_INLINE_FUNCTION +void Expr::doubleInterval(double & lb, double & ub) const { + double d = doubleValue(); + if (! CGAL_CORE_finite(d)) { // if overflow, underflow or NaN + lb = ub = d; + return; + } + int sign = ((* this) -Expr(d)).sign(); + // Seems like doubleValue() always give a lower bound, + // so sign = 0 or 1 (never -1). + //std::cout << "Sign = " << sign << std::endl; + if (sign == 0) { + lb = ub = d; + return; + } + int exp; + frexp(d, & exp); // get the exponent of d + exp--; // the exp from frexp satisfies + // 2^{exp-1} <= d < 2^{exp} + // But, we want exp to satisfy + // 2^{exp} <= d < 2^{exp+1} + if (sign > 0) { + lb = d; + ub = d + ldexp(1.0, -52+exp); + return; + } else { + ub = d; + lb = d - ldexp(1.0, -52+exp); + return; + } +} + +// floor(e, sub) returns the floor(e), and puts the +// remainder into sub. +CGAL_INLINE_FUNCTION +BigInt floor(const Expr& e, Expr &sub) { + if (e==0) { + return 0; + } + BigInt f = e.approx(CORE_INFTY, 2).BigIntValue(); + sub = e-f; + // Adjustment + if (sub<0) + ++sub, --f; + if (sub>=1) + --sub, ++f; + assert(sub >=0 && sub<1); // got an assertion error? (Chee 3/24/04) + return f; +} + +// Chenli: implemented algorithm from Goldberg's article. +// 7/01: Thanks to Serge Pashkov for fixing infinite loop when n=0. +CGAL_INLINE_FUNCTION +Expr pow(const Expr& e, unsigned long n) { + if (n == 0) + return Expr(1); + else if (n == 1) + return e; + else { + Expr x = e; + while ((n % 2) == 0) { // n is even + x *= x; + n >>= 1; + } + Expr u = x; + while (true) { + n >>= 1; + if (n == 0) + return u; + x *= x; + if ((n % 2) == 1) // n is odd + u *= x; + } + //return u; // unreachable + } +}//pow + +CGAL_INLINE_FUNCTION +NodeInfo::NodeInfo() : appValue(CORE_REAL_ZERO), appComputed(false), + flagsComputed(false), knownPrecision(CORE_negInfty), +#ifdef CORE_DEBUG + relPrecision(EXTLONG_ZERO), absPrecision(CORE_negInfty), numNodes(0), +#endif + // Most of the following data members don't need to be + // initialized here. + d_e(EXTLONG_ZERO), visited(false), sign(0), + uMSB(CORE_negInfty), lMSB(CORE_negInfty), + // length(0), + measure(EXTLONG_ZERO), high(EXTLONG_ZERO), low(EXTLONG_ONE), + lc(EXTLONG_ZERO), tc(EXTLONG_ZERO), + v2p(EXTLONG_ZERO), v2m(EXTLONG_ZERO), + v5p(EXTLONG_ZERO), v5m(EXTLONG_ZERO), + u25(EXTLONG_ZERO), l25(EXTLONG_ZERO), + ratFlag(0), ratValue(NULL) { } + +/******************************************************** + * class ExprRep + ********************************************************/ +// constructor +CGAL_INLINE_FUNCTION +ExprRep::ExprRep() : refCount(1), nodeInfo(NULL), ffVal(0.0) { } + +// Computes the root bit bound of the expression. +// In effect, computeBound() returns the current value of low. +CGAL_INLINE_FUNCTION +extLong ExprRep::computeBound() { + extLong measureBd = measure(); + // extLong cauchyBd = length(); + extLong ourBd = (d_e() - EXTLONG_ONE) * high() + lc(); + // BFMSS[2,5] bound. + extLong bfmsskBd; + if (v2p().isInfty() || v2m().isInfty()) + bfmsskBd = CORE_INFTY; + else + bfmsskBd = l25() + u25() * (d_e() - EXTLONG_ONE) - v2() - ceilLg5(v5()); + + // since we might compute \infty - \infty for this bound + if (bfmsskBd.isNaN()) + bfmsskBd = CORE_INFTY; + + extLong bd = core_min(measureBd, + // core_min(cauchyBd, + core_min(bfmsskBd, ourBd)); +#ifdef CORE_SHOW_BOUNDS + std::cout << "Bounds (" << measureBd << + "," << bfmsskBd << ", " << ourBd << "), "; + std::cout << "MIN = " << bd << std::endl; + std::cout << "d_e= " << d_e() << std::endl; +#endif + +#if defined(CORE_DEBUG_BOUND) && !defined(CGAL_HEADER_ONLY) + // Some statistics about which one is/are the winner[s]. + computeBoundCallsCounter++; + int number_of_winners = 0; + std::cerr << " New contest " << std::endl; + if (bd == bfmsskBd) { + BFMSS_counter++; + number_of_winners++; + std::cerr << " BFMSS is the winner " << std::endl; + } + if (bd == measureBd) { + Measure_counter++; + number_of_winners++; + std::cerr << " measureBd is the winner " << std::endl; + } + /* if (bd == cauchyBd) { + Cauchy_counter++; + number_of_winners++; + std::cerr << " cauchyBd is the winner " << std::endl; + } + */ + if (bd == ourBd) { + LiYap_counter++; + number_of_winners++; + std::cerr << " ourBd is the winner " << std::endl; + } + + assert(number_of_winners >= 1); + + if (number_of_winners == 1) { + if (bd == bfmsskBd) { + BFMSS_only_counter++; + std::cerr << " BFMSSBd is the only winner " << std::endl; + } else if (bd == measureBd) { + Measure_only_counter++; + std::cerr << " measureBd is the only winner " << std::endl; + } + /* else if (bd == cauchyBd) { + Cauchy_only_counter++; + std::cerr << " cauchyBd is the only winner " << std::endl; + } */ + else if (bd == ourBd) { + LiYap_only_counter++; + std::cerr << " ourBd is the only winner " << std::endl; + } + } +#endif + + return bd; +}//computeBound() + +CGAL_INLINE_FUNCTION +void ExprRep::reduceToBigRat(const BigRat& rat) { + Real value(rat); + + //appValue() = value; + appComputed() = false; // since appValue is not assigned until approx() is called + flagsComputed() = true; + knownPrecision() = CORE_negInfty; + +#ifdef CORE_DEBUG + relPrecision() = EXTLONG_ZERO; + absPrecision() = CORE_negInfty; + //numNodes() = numNodes(); +#endif + + d_e() = EXTLONG_ONE; + //visited() = e->visited(); + sign() = value.sign(); + uMSB() = value.MSB(); + lMSB() = value.MSB(); + // length() = value.length(); // fixed? original = 1 + measure() = value.height(); // measure <= height for rational value + + // BFMSS[2,5] bound. + value.ULV_E(u25(), l25(), v2p(), v2m(), v5p(), v5m()); + + extLong u_e = u25() + v2p(); + extLong l_e = l25() + v2m(); + + u_e = u_e + ceilLg5(v5p()); + l_e = l_e + ceilLg5(v5m()); + + if (l_e == EXTLONG_ZERO) { // no divisions introduced + high() = u_e; + low() = EXTLONG_ONE - u_e; // - (u_e - 1) + } else { + high() = u_e - l_e + EXTLONG_ONE; + low() = 2 - high(); + } + + lc() = l_e; + tc() = u_e; + + if (ratValue() == NULL) + ratValue() = new BigRat(rat); + else + *(ratValue()) = rat; +} + +// This only copies the current information of the argument e to +// *this ExprRep. +CGAL_INLINE_FUNCTION +void ExprRep::reduceTo(const ExprRep *e) { + if (e->appComputed()) { + appValue() = e->appValue(); + appComputed() = true; + flagsComputed() = true; + knownPrecision() = e->knownPrecision(); +#ifdef CORE_DEBUG + relPrecision() = e->relPrecision(); + absPrecision() = e->absPrecision(); + numNodes() = e->numNodes(); +#endif + + } + d_e() = e->d_e(); + //visited() = e->visited(); + sign() = e->sign(); + uMSB() = e->uMSB(); + lMSB() = e->lMSB(); + // length() = e->length(); // fixed? original = 1 + measure() = e->measure(); + + // BFMSS[2,5] bound. + u25() = e->u25(); + l25() = e->l25(); + v2p() = e->v2p(); + v2m() = e->v2m(); + v5p() = e->v5p(); + v5m() = e->v5m(); + + high() = e->high(); + low() = e->low(); // fixed? original = 0 + lc() = e->lc(); + tc() = e->tc(); + + // Chee (Mar 23, 2004), Notes on ratFlag(): + // =============================================================== + // For more information on the use of this flag, see progs/pentagon. + // This is an integer valued member of the NodeInfo class. + // Its value is used to determine whether + // we can ``reduce'' an Expression to a single node containing + // a BigRat value. This reduction is done if the global variable + // get_static_rationalReduceFlag()=true. The default value is false. + // This is the intepretation of ratFlag: + // ratFlag < 0 means irrational + // ratFlag = 0 means not initialized + // ratFlag > 0 means rational + // Currently, ratFlag>0 is an upper bound on the size of the expression, + // since we recursively compute + // ratFlag(v) = ratFlag(v.lchild)+ratFlag(v.rchild) + 1. + // PROPOSAL: if ratFlag() > RAT_REDUCE_THRESHHOLD + // then we automatically do a reduction. We must determine + // an empirical value for RAT_REDUCE_THRESHOLD + + if (get_static_rationalReduceFlag()) { + ratFlag() = e->ratFlag(); + + if (e->ratFlag() > 0 && e->ratValue() != NULL) { + ratFlag() ++; + if (ratValue() == NULL) + ratValue() = new BigRat(*(e->ratValue())); + else + *(ratValue()) = *(e->ratValue()); + } else + ratFlag() = -1; + } +} + +CGAL_INLINE_FUNCTION +void ExprRep::reduceToZero() { + appValue() = CORE_REAL_ZERO; + appComputed() = true; + flagsComputed() = true; + knownPrecision() = CORE_negInfty; +#ifdef CORE_DEBUG + relPrecision() = EXTLONG_ZERO; + absPrecision() = CORE_negInfty; + // numNodes() = 0; +#endif + + d_e() = EXTLONG_ONE; + visited() = false; + sign() = 0; + uMSB() = CORE_negInfty; + lMSB() = CORE_negInfty; + // length() = 0; // fixed? original = 1 + measure() = EXTLONG_ZERO; + + // BFMSS[2,5] bound. + u25() = l25() = v2p() = v2m() = v5p() = v5m() = EXTLONG_ZERO; + + low() = EXTLONG_ONE; // fixed? original = 0 + high() = lc() = tc() = EXTLONG_ZERO; + + if (get_static_rationalReduceFlag()) { + if (ratFlag() > 0) { + ratFlag() ++; + if (ratValue() == NULL) + ratValue() = new BigRat(0); + else + *(ratValue()) = 0; + } else + ratFlag() = 1; + } +} + +//////////////////////////////////////////////////////////// +// Test whether the current approximate value satisfies +// the composite precision requirements [relPrec, absPrec]. +//////////////////////////////////////////////////////////// + +CGAL_INLINE_FUNCTION +bool ExprRep::withinKnownPrecision(const extLong& relPrec, + const extLong& absPrec) { + if (appComputed()) { // an approximate value has been evaluated. + if (appValue().isExact()) { + return true; + } else { // approximation has certain error. + // decide to which position it is required to compute correctly. + extLong required = core_max(-absPrec, appValue().lMSB()-relPrec); + // see whether the existing error is smaller than the requirement. + return (knownPrecision() <= required); + } + } else + return false; +}//withinKnownPrecision(a, r) + +// approximate the expression to certain precisions when +// necessary (either no approximate value available or +// the existing one is not accurate enough). +CGAL_INLINE_FUNCTION +void ExprRep::approx(const extLong& relPrec = get_static_defRelPrec(), + const extLong& absPrec = get_static_defAbsPrec()) { + if (!getSign()) + return; // if it is exactly zero... + + // NOTE: The Filter might give a precise enough approximation already. + if (!getExactSign()) + return; + + if (!appComputed() || (!withinKnownPrecision(relPrec, absPrec))) { + // it's necessary to re-evaluate. + // to avoid huge lMSB which would cause long time and problems. + + // if it is a rational node + if (get_static_rationalReduceFlag() && ratFlag() > 0 && ratValue() != NULL) + appValue() = Real(*(ratValue())).approx(relPrec, absPrec); //< shouldn't + // this case be done by computeApproxValue()? + else + computeApproxValue(relPrec, absPrec); + + // update flags + appComputed() = true; + knownPrecision() = appValue().clLgErr(); +#ifdef CORE_DEBUG + if (relPrecision() < relPrec) + relPrecision() = relPrec; + if (absPrecision() < absPrec) + absPrecision() = absPrec; +#endif + + } +} + +// return an approximate value to certain precision. +CGAL_INLINE_FUNCTION +const Real& ExprRep::getAppValue(const extLong& relPrec, + const extLong& absPrec) { + if (getSign()) { + approx(relPrec, absPrec); + return appValue(); + } else + return CORE_REAL_ZERO; +} + +CGAL_INLINE_FUNCTION +std::ostream& operator<<(std::ostream& o, ExprRep& rep) { + if (rep.getSign()) { + rep.approx(get_static_defRelPrec(), get_static_defAbsPrec()); + o << rep.appValue(); + } else { + o << "0"; + } + return o; +} + +// Chee, Zilin: July 17, 2002 +// Original algorithm is wrongly implemented, and can take time +// exponential in the size of the dag. +// +// METHOD: +// Inductively assume that all "visited" flags are false. +// This calls for a reimplementation of "count()" and "clearFlag()". +// Actually, we did not have to fix the count() function. +// +// (1) First recursively compute d_e for each node +// by calling the count() function. +// Important thing is count() will turn the "visited" flags +// to be true, so that there is no double counting. +// Furthermore, if d_e had already been computed, the +// arithmetic for d_e can be avoided (in this case, +// it is only the setting of "visited" flag that we +// are interested in! +// (2) At the end of count(), we have set all reachable nodes +// to "visited", and their d_e have been computed. +// (3) Now, call clearFlag() to recursively clear all reachable +// nodes. NOTE THAT PREVIOUSLY, clearFlag() was called +// first! This obvious is wrong + +CGAL_INLINE_FUNCTION +extLong ExprRep::degreeBound() { + if (d_e() == EXTLONG_ONE) // no radical nodes below + return EXTLONG_ONE; + count(); + clearFlag(); + return d_e(); +} +// class ConstRealRep +// constructor +CGAL_INLINE_FUNCTION +ConstRealRep::ConstRealRep(const Real & r) : value(r) { + if (!value.isExact()) { + // clone the BigFloat and set its error to zero. + value = value.BigFloatValue().makeExact(); + } + ffVal = filteredFp(value); +} + +// initialize nodeInfo +CGAL_INLINE_FUNCTION +void ConstRep::initNodeInfo() { + nodeInfo = new NodeInfo(); + d_e() = EXTLONG_ONE; +} +CGAL_INLINE_FUNCTION +void UnaryOpRep::initNodeInfo() { + if (child->nodeInfo == NULL) + child->initNodeInfo(); + nodeInfo = new NodeInfo(); +} +CGAL_INLINE_FUNCTION +void BinOpRep::initNodeInfo() { + if (first->nodeInfo == NULL) + first->initNodeInfo(); + if (second->nodeInfo == NULL) + second->initNodeInfo(); + nodeInfo = new NodeInfo(); +} + +#ifdef CORE_DEBUG +CGAL_INLINE_FUNCTION +unsigned long ConstRep::dagSize() { + if (!visited()) { + visited() = true; + numNodes() = 1; + } else + numNodes() = 0; + return numNodes(); +} + +CGAL_INLINE_FUNCTION +unsigned long UnaryOpRep::dagSize() { + if (!visited()) { + visited() = true; + numNodes() = child->dagSize() + 1; + } else + numNodes() = 0; + return numNodes(); +} + +CGAL_INLINE_FUNCTION +unsigned long BinOpRep::dagSize() { + if (!visited()) { + visited() = true; + numNodes() = first->dagSize() + second->dagSize() + 1; + } else + numNodes() = 0; + return numNodes(); +} + +CGAL_INLINE_FUNCTION +void ConstRep::fullClearFlag() { + if (visited()) + visited() = false; +} + +CGAL_INLINE_FUNCTION +void UnaryOpRep::fullClearFlag() { + if (visited()) { + child->fullClearFlag(); + visited() = false; + } +} + +CGAL_INLINE_FUNCTION +void BinOpRep::fullClearFlag() { + if (visited()) { + first->fullClearFlag(); + second->fullClearFlag(); + visited() = false; + } +} +#endif + +// +// clear visited flag +// +/* see Expr.h + void ConstRep::clearFlag() + { visited = false; } +*/ +CGAL_INLINE_FUNCTION +void UnaryOpRep::clearFlag() { + if (d_e() == EXTLONG_ONE) + return; // no radicals below. + if (visited()) { + visited() = false; + child->clearFlag(); + } +} +// class BinOpRep +CGAL_INLINE_FUNCTION +void BinOpRep::clearFlag() { + if (d_e() == EXTLONG_ONE) + return; // rational below + if (visited()) { + visited() = false; + first->clearFlag(); + second->clearFlag(); + } +} + +// +// count # of squareroot +// +CGAL_INLINE_FUNCTION +extLong ConstRep::count() { + if (visited()) + return EXTLONG_ONE; + visited() = true; + return d_e(); +} + +CGAL_INLINE_FUNCTION +extLong NegRep::count() { + if (d_e() == EXTLONG_ONE) + return EXTLONG_ONE; + if (visited()) + return EXTLONG_ONE; + visited() = true; + d_e() = child->count(); + return d_e(); +} + +CGAL_INLINE_FUNCTION +extLong SqrtRep::count() { + if (d_e() == EXTLONG_ONE) + return EXTLONG_ONE; + if (visited()) + return EXTLONG_ONE; + visited() = true; + d_e() = child->count() * EXTLONG_TWO; + return d_e(); +} + +CGAL_INLINE_FUNCTION +extLong BinOpRep::count() { + if (d_e() == EXTLONG_ONE) + return EXTLONG_ONE; + if (visited()) + return EXTLONG_ONE; + visited() = true; + d_e() = first->count() * second->count(); + return d_e(); +} + +// +// compute exact flags functions +// +// exact value + +CGAL_INLINE_FUNCTION +void computeExactFlags_temp(ConstRep* t, const Real &value) { + // Chen Li: the following is incorrect: + // uMSB = lMSB = value.MSB(); + // because the value could be a BigFloat which is an interval. + if (value.isExact()) { + t->uMSB() = t->lMSB() = value.MSB(); + } else { + t->uMSB() = value.uMSB(); + t->lMSB() = value.lMSB(); + core_error("Leaves in DAG is not exact!", __FILE__, __LINE__, true); + } + + t->sign() = value.sign(); + // t->length() = value.length(); + t->measure() = value.height(); // for rationals and integers, + // measure = height. + + // BFMSS[2,5] bound. + value.ULV_E(t->u25(), t->l25(), t->v2p(), t->v2m(), t->v5p(), t->v5m()); + + // The original BFMSS parameters can be set from the BFMSS[2,5] parameters. + // Here we just need them locally. + extLong u_e = t->u25() + t->v2p() + ceilLg5(t->v5p()); + extLong l_e = t->l25() + t->v2m() + ceilLg5(t->v5m()); + +#ifdef ORIGINAL_BFMSS + // To go back to the original BFMSS : + t->u25() = u_e; + t->l25() = l_e; + t->v2p() = t->v2m() = t->v5p() = t->v5m() = EXTLONG_ZERO; +#elif defined BFMSS_2_ONLY + // To go back to BFMSS[2] only : + t->u25() = t->u25() + ceilLg5(t->v5p()); + t->l25() = t->l25() + ceilLg5(t->v5m()); + t->v5p() = t->v5m() = EXTLONG_ZERO; +#endif + + if (l_e == EXTLONG_ZERO) { // no divisions introduced + t->high() = u_e; + t->low() = EXTLONG_ONE - u_e; // - (u_e - 1) + } else { + t->high() = u_e - l_e + EXTLONG_ONE; + t->low() = EXTLONG_TWO - t->high(); + } + + t->lc() = l_e; + t->tc() = u_e; + + // set BigRat value + if (get_static_rationalReduceFlag()) { + t->ratFlag() = 1; + t->ratValue() = new BigRat(value.BigRatValue()); + } + + t->flagsComputed() = true; +} + +CGAL_INLINE_FUNCTION +void ConstDoubleRep::computeExactFlags() {// can be made more efficient + computeExactFlags_temp(this, Real(ffVal.getValue())); +} + +CGAL_INLINE_FUNCTION +void ConstRealRep::computeExactFlags() { + computeExactFlags_temp(this, value); +} + +CGAL_INLINE_FUNCTION +void NegRep::computeExactFlags() { + if (!child->flagsComputed()) + child->computeExactFlags(); + + if (child->sign() == 0) { + reduceToZero(); + return; + } + + if (get_static_rationalReduceFlag()) { + if (child->ratFlag()>0 && child->ratValue() != NULL) { + BigRat val = -(*(child->ratValue())); + reduceToBigRat(val); + ratFlag() = child->ratFlag()+1; + return; + } else + ratFlag() = -1; + } + + sign() = -child->sign(); + uMSB() = child->uMSB(); + lMSB() = child->lMSB(); + + // length() = child->length(); + measure() = child->measure(); + u25() = child->u25(); + l25() = child->l25(); + v2p() = child->v2p(); + v2m() = child->v2m(); + v5p() = child->v5p(); + v5m() = child->v5m(); + high() = child->high(); + low() = child->low(); + lc() = child->lc(); + tc() = child->tc(); + flagsComputed() = true; +}//NegRep::computeExactFlags + +CGAL_INLINE_FUNCTION +void SqrtRep::computeExactFlags() { + if (!child->flagsComputed()) + child->computeExactFlags(); + + if (get_static_rationalReduceFlag()) + ratFlag() = -1; + + sign() = child->sign(); + if (sign() < 0) + core_error("squareroot is called with negative operand.", + __FILE__, __LINE__, true); + + uMSB() = child->uMSB() / EXTLONG_TWO; + lMSB() = child->lMSB() / EXTLONG_TWO; + + // length() = child->length(); + measure() = child->measure(); + + // BFMSS[2,5] bound. + if (child->v2p() + ceilLg5(child->v5p()) + child->u25() >= + child->v2m() + ceilLg5(child->v5m()) + child->l25()) { + extLong vtilda2 = child->v2p() + child->v2m(); + v2p() = vtilda2 / EXTLONG_TWO; + v2m() = child->v2m(); + extLong vmod2; + if (v2p().isInfty()) + vmod2 = CORE_INFTY; + else + vmod2 = vtilda2 - EXTLONG_TWO*v2p(); // == vtilda2 % 2 + extLong vtilda5 = child->v5p() + child->v5m(); + v5p() = vtilda5 / EXTLONG_TWO; + v5m() = child->v5m(); + extLong vmod5; + if (v5p().isInfty()) + vmod5 = CORE_INFTY; + else + vmod5 = vtilda5 - EXTLONG_TWO*v5p(); // == vtilda5 % 2 + u25() = (child->u25() + child->l25() + vmod2 + ceilLg5(vmod5) + EXTLONG_ONE) / EXTLONG_TWO; + l25() = child->l25(); + } else { + extLong vtilda2 = child->v2p() + child->v2m(); + v2p() = child->v2p(); + v2m() = vtilda2 / EXTLONG_TWO; + extLong vmod2; + if (v2m().isInfty()) + vmod2 = CORE_INFTY; + else + vmod2 = vtilda2 - EXTLONG_TWO*v2m(); // == vtilda2 % 2 + extLong vtilda5 = child->v5p() + child->v5m(); + v5p() = child->v5p(); + v5m() = vtilda5 / EXTLONG_TWO; + u25() = child->u25(); + extLong vmod5; + if (v5m().isInfty()) + vmod5 = CORE_INFTY; + else + vmod5 = vtilda5 - EXTLONG_TWO*v5m(); // == vtilda5 % 2 + l25() = (child->u25() + child->l25() + vmod2 + ceilLg5(vmod5) + EXTLONG_ONE) / EXTLONG_TWO; + } + + high() = (child->high() +EXTLONG_ONE)/EXTLONG_TWO; + low() = child->low() / EXTLONG_TWO; + lc() = child->lc(); + tc() = child->tc(); + flagsComputed() = true; +}// SqrtRep::computeExactFlags + +CGAL_INLINE_FUNCTION +void MultRep::computeExactFlags() { + if (!first->flagsComputed()) + first->computeExactFlags(); + if (!second->flagsComputed()) + second->computeExactFlags(); + + if ((!first->sign()) || (!second->sign())) { + // value must be exactly zero. + reduceToZero(); + return; + } + // rational node + if (get_static_rationalReduceFlag()) { + if (first->ratFlag() > 0 && second->ratFlag() > 0) { + BigRat val = (*(first->ratValue()))*(*(second->ratValue())); + reduceToBigRat(val); + ratFlag() = first->ratFlag() + second->ratFlag(); + return; + } else + ratFlag() = -1; + } + + // value is irrational. + uMSB() = first->uMSB() + second->uMSB() + EXTLONG_ONE; + lMSB() = first->lMSB() + second->lMSB(); + sign() = first->sign() * second->sign(); + + extLong df = first->d_e(); + extLong ds = second->d_e(); + // extLong lf = first->length(); + // extLong ls = second->length(); + + // length() = df * ls + ds * lf; + measure() = (first->measure()) * ds+(second->measure()) * df; + + // BFMSS[2,5] bound. + v2p() = first->v2p() + second->v2p(); + v2m() = first->v2m() + second->v2m(); + v5p() = first->v5p() + second->v5p(); + v5m() = first->v5m() + second->v5m(); + u25() = first->u25() + second->u25(); + l25() = first->l25() + second->l25(); + + high() = first->high() + second->high(); + low() = first->low() + second->low(); + + lc() = ds * first->lc() + df * second->lc(); + tc() = core_min(ds * first->tc() + df * second->tc(), measure()); + + flagsComputed() = true; +}// MultRep::computeExactFlags + +CGAL_INLINE_FUNCTION +void DivRep::computeExactFlags() { + if (!first->flagsComputed()) + first->computeExactFlags(); + if (!second->flagsComputed()) + second->computeExactFlags(); + + if (!second->sign()) + core_error("zero divisor.", __FILE__, __LINE__, true); + + if (!first->sign()) {// value must be exactly zero. + reduceToZero(); + return; + } + + // rational node + if (get_static_rationalReduceFlag()) { + if (first->ratFlag() > 0 && second->ratFlag() > 0) { + BigRat val = (*(first->ratValue()))/(*(second->ratValue())); + reduceToBigRat(val); + ratFlag() = first->ratFlag() + second->ratFlag(); + return; + } else + ratFlag() = -1; + } + + // value is irrational. + uMSB() = first->uMSB() - second->lMSB(); + lMSB() = first->lMSB() - second->uMSB() - EXTLONG_ONE; + sign() = first->sign() * second->sign(); + + extLong df = first->d_e(); + extLong ds = second->d_e(); + // extLong lf = first->length(); + // extLong ls = second->length(); + + // length() = df * ls + ds * lf; + measure() = (first->measure())*ds + (second->measure())*df; + + // BFMSS[2,5] bound. + v2p() = first->v2p() + second->v2m(); + v2m() = first->v2m() + second->v2p(); + v5p() = first->v5p() + second->v5m(); + v5m() = first->v5m() + second->v5p(); + u25() = first->u25() + second->l25(); + l25() = first->l25() + second->u25(); + + high() = first->high() + second->low(); + low() = first->low() + second->high(); + + lc() = ds * first->lc() + df * second->tc(); + tc() = core_min(ds * first->tc() + df * second->lc(), measure()); + + flagsComputed() = true; +} + +// +// approximation functions +// +CGAL_INLINE_FUNCTION +void ConstDoubleRep::computeApproxValue(const extLong& /*relPrec*/, + const extLong& /*absPrec*/) +// can ignore precision bounds since ffVal.getValue() returns exact value +{ + appValue() = Real(ffVal.getValue()); +} + +CGAL_INLINE_FUNCTION +void ConstRealRep::computeApproxValue(const extLong& relPrec, + const extLong& absPrec) { + appValue() = value.approx(relPrec, absPrec); +} + +CGAL_INLINE_FUNCTION +void NegRep::computeApproxValue(const extLong& relPrec, + const extLong& absPrec) { + appValue() = -child->getAppValue(relPrec, absPrec); +} + +CGAL_INLINE_FUNCTION +void SqrtRep::computeApproxValue(const extLong& relPrec, + const extLong& absPrec) { + extLong r = relPrec + relPrec + EXTLONG_EIGHT; // chenli: ??? + extLong a = absPrec + absPrec + EXTLONG_EIGHT; + extLong pr = - lMSB() + r; + extLong p = pr < a ? pr : a; + + Real val = child->getAppValue(r, a); + if (get_static_incrementalEvalFlag()) { + if (appValue() == CORE_REAL_ZERO) + appValue() = val; + appValue() = val.sqrt(p, appValue().BigFloatValue()); + } else + appValue() = val.sqrt(p); +} + +CGAL_INLINE_FUNCTION +void MultRep::computeApproxValue(const extLong& relPrec, + const extLong& absPrec) { + if (lMSB() < EXTLONG_BIG && lMSB() > EXTLONG_SMALL) { + extLong r = relPrec + EXTLONG_FOUR; + extLong afr = - first->lMSB() + EXTLONG_ONE; + extLong afa = second->uMSB() + absPrec + EXTLONG_FIVE; + extLong af = afr > afa ? afr : afa; + extLong asr = - second->lMSB() + EXTLONG_ONE; + extLong asa = first->uMSB() + absPrec + EXTLONG_FIVE; + extLong as = asr > asa ? asr : asa; + appValue() = first->getAppValue(r, af)*second->getAppValue(r, as); + } else { + std::cerr << "lMSB = " << lMSB() << std::endl; + core_error("a huge lMSB in MulRep", __FILE__, __LINE__, false); + } +} + +CGAL_INLINE_FUNCTION +void DivRep::computeApproxValue(const extLong& relPrec, + const extLong& absPrec) { + if (lMSB() < EXTLONG_BIG && lMSB() > EXTLONG_SMALL) { + extLong rr = relPrec + EXTLONG_SEVEN; // These rules come from + extLong ra = uMSB() + absPrec + EXTLONG_EIGHT; // Koji's Master Thesis, page 65 + extLong ra2 = core_max(ra, EXTLONG_TWO); + extLong r = core_min(rr, ra2); + extLong af = - first->lMSB() + r; + extLong as = - second->lMSB() + r; + + extLong pr = relPrec + EXTLONG_SIX; + extLong pa = uMSB() + absPrec + EXTLONG_SEVEN; + extLong p = core_min(pr, pa); // Seems to be an error: + // p can be negative here! + // Also, this does not conform to + // Koji's thesis which has a default + // relative precision (p.65). + + appValue() = first->getAppValue(r, af).div(second->getAppValue(r, as), p); + } else { + std::cerr << "lMSB = " << lMSB() << std::endl; + core_error("a huge lMSB in DivRep", __FILE__, __LINE__, false); + } +} + +// +// Debug Help Functions +// +CGAL_INLINE_FUNCTION +void Expr::debug(int mode, int level, int depthLimit) const { + std::cout << "-------- Expr debug() -----------" << std::endl; + std::cout << "rep = " << rep << std::endl; + if (mode == Expr::LIST_MODE) + rep->debugList(level, depthLimit); + else if (mode == Expr::TREE_MODE) + rep->debugTree(level, 0, depthLimit); + else + core_error("unknown debugging mode", __FILE__, __LINE__, false); + std::cout << "---- End Expr debug(): " << std::endl; +} + + +CGAL_INLINE_FUNCTION +const std::string ExprRep::dump(int level) const { + std::ostringstream ost; + if (level == OPERATOR_ONLY) { + ost << op(); + } else if (level == VALUE_ONLY) { + ost << appValue(); + } else if (level == OPERATOR_VALUE) { + ost << op() << "[val: " << appValue() << "]"; + } else if (level == FULL_DUMP) { + ost << op() + << "[val: " << appValue() << "; " + << "kp: " << knownPrecision() << "; " +#ifdef CORE_DEBUG + << "r: " << relPrecision() << "; " + << "a: " << absPrecision() << "; " +#endif + << "lMSB: " << lMSB() << "; " + << "uMSB: " << uMSB() << "; " + << "sign: " << sign() << "; " + // << "length: " << length() << "; " + << "measure: " << measure() << "; " + << "d_e: " << d_e() << "; " + << "u25: " << u25() << "; " + << "l25: " << l25() << "; " + << "v2p: " << v2p() << "; " + << "v2m: " << v2m() << "; " + << "v5p: " << v5p() << "; " + << "v5m: " << v5m() << "; " + << "high: " << high() << "; " + << "low: " << low() << "; " + << "lc: " << lc() << "; " + << "tc: " << tc() + << "]"; + } + return std::string(ost.str()); + // note that str() return an array not properly terminated! +} + + +CGAL_INLINE_FUNCTION +void UnaryOpRep::debugList(int level, int depthLimit) const { + if (depthLimit <= 0) + return; + if (level == Expr::SIMPLE_LEVEL) { + std::cout << "(" << dump(OPERATOR_VALUE); + child->debugList(level, depthLimit - 1); + std::cout << ")"; + } else if (level == Expr::DETAIL_LEVEL) { + std::cout << "(" << dump(FULL_DUMP); + child->debugList(level, depthLimit - 1); + std::cout << ")"; + } +} + +CGAL_INLINE_FUNCTION +void UnaryOpRep::debugTree(int level, int indent, int depthLimit) const { + if (depthLimit <= 0) + return; + for (int i = 0; idebugTree(level, indent + 2, depthLimit - 1); +} + +CGAL_INLINE_FUNCTION +void ConstRep::debugList(int level, int depthLimit) const { + if (depthLimit <= 0) + return; + if (level == Expr::SIMPLE_LEVEL) { + std::cout << "(" << dump(OPERATOR_VALUE) << ")"; + } else if (level == Expr::DETAIL_LEVEL) { + std::cout << "(" << dump(FULL_DUMP) << ")"; + } +} + +CGAL_INLINE_FUNCTION +void ConstRep::debugTree(int level, int indent, int depthLimit) const { + if (depthLimit <= 0) + return; + for (int i=0; idebugList(level, depthLimit - 1); + std::cout << ", "; + second->debugList(level, depthLimit - 1); + std::cout << ")" ; +} + +CGAL_INLINE_FUNCTION +void BinOpRep::debugTree(int level, int indent, int depthLimit) const { + if (depthLimit <= 0) + return; + for (int i=0; idebugTree(level, indent + 2, depthLimit - 1); + second->debugTree(level, indent + 2, depthLimit - 1); +} + +} //namespace CORE diff --git a/CGAL_Core/include/CGAL/CORE/Filter.h b/CGAL_Core/include/CGAL/CORE/Filter.h index 4a8ff2dea7b..b2147bddbb7 100644 --- a/CGAL_Core/include/CGAL/CORE/Filter.h +++ b/CGAL_Core/include/CGAL/CORE/Filter.h @@ -103,7 +103,7 @@ public: } /// check whether the sign (!) of the filtered value is OK bool isOK() const { - return (fpFilterFlag && // To disable filter + return (get_static_fpFilterFlag() && // To disable filter CGAL_CORE_finite(fpVal) && // Test for infinite and NaNs (core_abs(fpVal) >= maxAbs*ind*CORE_EPS)); } diff --git a/CGAL_Core/include/CGAL/CORE/Gmp.h b/CGAL_Core/include/CGAL/CORE/Gmp.h index 8faf2d2ca5a..cfa7574fc4a 100644 --- a/CGAL_Core/include/CGAL/CORE/Gmp.h +++ b/CGAL_Core/include/CGAL/CORE/Gmp.h @@ -39,4 +39,9 @@ CGAL_CORE_EXPORT std::istream& io_read (std::istream &, mpq_ptr); //std::istream& operator>> (std::istream &, mpq_ptr); } //namespace CORE + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // _CORE_GMP_H_ diff --git a/CGAL_Core/include/CGAL/CORE/Gmp_impl.h b/CGAL_Core/include/CGAL/CORE/Gmp_impl.h new file mode 100644 index 00000000000..32cec37e7ed --- /dev/null +++ b/CGAL_Core/include/CGAL/CORE/Gmp_impl.h @@ -0,0 +1,280 @@ +/**************************************************************************** + * Core Library Version 1.7, August 2004 + * Copyright (c) 1995-2004 Exact Computation Project + * All rights reserved. + * + * file: GmpIO.cpp + * Adapted from multi-files under /cxx in GMP's source distribution + * + * Zilin Du, 2003 + * + * $URL$ + * $Id$ + ***************************************************************************/ + +/* Auxiliary functions for C++-style input of GMP types. + +Copyright 2001 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +MA 02110-1301, USA. */ + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include +#include +#include + +using namespace std; + +namespace CORE { + +CGAL_INLINE_FUNCTION +int +__gmp_istream_set_base (istream &i, char &c, bool &zero, bool &showbase) +{ + int base; + + zero = showbase = false; + switch (i.flags() & ios::basefield) + { + case ios::dec: + base = 10; + break; + case ios::hex: + base = 16; + break; + case ios::oct: + base = 8; + break; + default: + showbase = true; // look for initial "0" or "0x" or "0X" + if (c == '0') + { + if (! i.get(c)) + c = 0; // reset or we might loop indefinitely + + if (c == 'x' || c == 'X') + { + base = 16; + i.get(c); + } + else + { + base = 8; + zero = true; // if no other digit is read, the "0" counts + } + } + else + base = 10; + break; + } + + return base; +} + +CGAL_INLINE_FUNCTION +void +__gmp_istream_set_digits (string &s, istream &i, char &c, bool &ok, int base) +{ + switch (base) + { + case 10: + while (isdigit(c)) + { + ok = true; // at least a valid digit was read + s += c; + if (! i.get(c)) + break; + } + break; + case 8: + while (isdigit(c) && c != '8' && c != '9') + { + ok = true; // at least a valid digit was read + s += c; + if (! i.get(c)) + break; + } + break; + case 16: + while (isxdigit(c)) + { + ok = true; // at least a valid digit was read + s += c; + if (! i.get(c)) + break; + } + break; + } +} + +CGAL_INLINE_FUNCTION +istream & +//operator>> (istream &i, mpz_ptr z) +io_read (istream &i, mpz_ptr z) +{ + int base; + char c = 0; + string s; + bool ok = false, zero, showbase; + + i.get(c); // start reading + + if (i.flags() & ios::skipws) // skip initial whitespace + while (isspace(c) && i.get(c)) + ; + + if (c == '-' || c == '+') // sign + { + if (c == '-') // mpz_set_str doesn't accept '+' + s = "-"; + i.get(c); + } + + while (isspace(c) && i.get(c)) // skip whitespace + ; + + base = __gmp_istream_set_base(i, c, zero, showbase); // select the base + __gmp_istream_set_digits(s, i, c, ok, base); // read the number + + if (i.good()) // last character read was non-numeric + i.putback(c); + else if (i.eof() && (ok || zero)) // stopped just before eof + i.clear(); + + if (ok) + mpz_set_str(z, s.c_str(), base); // extract the number + else if (zero) + mpz_set_ui(z, 0); + else + i.setstate(ios::failbit); // read failed + + return i; +} + +CGAL_INLINE_FUNCTION +istream & +//operator>> (istream &i, mpq_ptr q) +io_read (istream &i, mpq_ptr q) +{ + int base; + char c = 0; + string s; + bool ok = false, zero, showbase; + + i.get(c); // start reading + + if (i.flags() & ios::skipws) // skip initial whitespace + while (isspace(c) && i.get(c)) + ; + + if (c == '-' || c == '+') // sign + { + if (c == '-') + s = "-"; + i.get(c); + } + + while (isspace(c) && i.get(c)) // skip whitespace + ; + + base = __gmp_istream_set_base(i, c, zero, showbase); // select the base + __gmp_istream_set_digits(s, i, c, ok, base); // read the numerator + + if (! ok && zero) // the only digit read was "0" + { + base = 10; + s += '0'; + ok = true; + } + + if (i.flags() & ios::skipws) + while (isspace(c) && i.get(c)) // skip whitespace + ; + + if (c == '/') // there's a denominator + { + bool zero2 = false; + int base2 = base; + + s += '/'; + ok = false; // denominator is mandatory + i.get(c); + + while (isspace(c) && i.get(c)) // skip whitespace + ; + + if (showbase) // check base of denominator + base2 = __gmp_istream_set_base(i, c, zero2, showbase); + + if (base2 == base || base2 == 10) // read the denominator + __gmp_istream_set_digits(s, i, c, ok, base); + + if (! ok && zero2) // the only digit read was "0" + { // denominator is 0, but that's your business + s += '0'; + ok = true; + } + } + + if (i.good()) // last character read was non-numeric + i.putback(c); + else if (i.eof() && ok) // stopped just before eof + i.clear(); + + if (ok) + mpq_set_str(q, s.c_str(), base); // extract the number + else + i.setstate(ios::failbit); // read failed + + return i; +} + +CGAL_INLINE_FUNCTION +ostream& +//operator<< (ostream &o, mpz_srcptr z) +io_write (ostream &o, mpz_srcptr z) +{ + char *str = new char [mpz_sizeinbase(z,10) + 2]; + str = mpz_get_str(str, 10, z); + o << str ; + delete[] str; + return o; +} + +CGAL_INLINE_FUNCTION +ostream& +//operator<< (ostream &o, mpq_srcptr q) +io_write (ostream &o, mpq_srcptr q) +{ + // size according to GMP documentation + char *str = new char [mpz_sizeinbase(mpq_numref(q), 10) + + mpz_sizeinbase (mpq_denref(q), 10) + 3]; + str = mpq_get_str(str, 10, q); + o << str ; + delete[] str; + return o; +} + +} //namespace CORE diff --git a/CGAL_Core/include/CGAL/CORE/Real.h b/CGAL_Core/include/CGAL/CORE/Real.h index 6360c95418d..9c6d1468f8c 100644 --- a/CGAL_Core/include/CGAL/CORE/Real.h +++ b/CGAL_Core/include/CGAL/CORE/Real.h @@ -57,10 +57,10 @@ public: Real(const BigInt& I) : RCReal(new RealBigInt(I)) {} Real(const BigRat& R) : RCReal(new RealBigRat(R)) {} Real(const BigFloat& F) : RCReal(new RealBigFloat(F)) {} - Real(const char* s, const extLong& prec=defInputDigits) : RCReal(NULL) { + Real(const char* s, const extLong& prec=get_static_defInputDigits()) : RCReal(NULL) { constructFromString(s, prec); } - Real(const std::string& s, const extLong& prec=defInputDigits) : RCReal(NULL){ + Real(const std::string& s, const extLong& prec=get_static_defInputDigits()) : RCReal(NULL){ constructFromString(s.c_str(), prec); } @@ -134,12 +134,12 @@ public: /// \name String Conversion Functions //@{ /// set value from const char* - void fromString(const char* s, const extLong& prec = defInputDigits) { + void fromString(const char* s, const extLong& prec = get_static_defInputDigits()) { *this = Real(s, prec); } /// convert to std::string /** give decimal string representation */ - std::string toString(long prec=defOutputDigits, bool sci=false) const { + std::string toString(long prec=get_static_defOutputDigits(), bool sci=false) const { return rep->toString(prec, sci); } //@} @@ -179,7 +179,8 @@ public: /// \name Aprroximation Function //@{ /// approximation - Real approx(const extLong& r=defRelPrec, const extLong& a=defAbsPrec) const { + Real approx(const extLong& r=get_static_defRelPrec(), + const extLong& a=get_static_defAbsPrec()) const { return rep->approx(r, a); } //@} @@ -395,7 +396,7 @@ inline Real& Real::operator*=(const Real& rhs) { return *this; } inline Real& Real::operator/=(const Real& rhs) { - *this = real_div::eval(getRep(), rhs.getRep(), defRelPrec); + *this = real_div::eval(getRep(), rhs.getRep(), get_static_defRelPrec()); return *this; } @@ -413,7 +414,7 @@ inline Real operator*(const Real& x, const Real& y) { } // operator/ inline Real operator/(const Real& x, const Real& y) { - return real_div::eval(x.getRep(), y.getRep(), defRelPrec); + return real_div::eval(x.getRep(), y.getRep(), get_static_defRelPrec()); } // div w/ precision inline Real Real::div(const Real& x, const extLong& r) const { @@ -478,7 +479,7 @@ inline Real power(const Real& r, unsigned long p) { } /// square root inline Real sqrt(const Real& x) { - return x.sqrt(defAbsPrec); + return x.sqrt(get_static_defAbsPrec()); } // class Realbase_for (need defined after Real) @@ -493,4 +494,9 @@ inline Real RealLong::operator-() const { } } //namespace CORE + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // _CORE_REAL_H_ diff --git a/CGAL_Core/include/CGAL/CORE/Real_impl.h b/CGAL_Core/include/CGAL/CORE/Real_impl.h new file mode 100644 index 00000000000..4916e8057e6 --- /dev/null +++ b/CGAL_Core/include/CGAL/CORE/Real_impl.h @@ -0,0 +1,291 @@ +/**************************************************************************** + * Core Library Version 1.7, August 2004 + * Copyright (c) 1995-2004 Exact Computation Project + * All rights reserved. + * + * This file is part of CORE (http://cs.nyu.edu/exact/core/). + * You can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * Licensees holding a valid commercial license may use this file in + * accordance with the commercial license agreement provided with the + * software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * File: Real.cpp + * Synopsis: The Real class is a superclass for all the number + * systems in the Core Library (int, long, float, double, + * BigInt, BigRat, BigFloat, etc) + * + * Written by + * Koji Ouchi + * Chee Yap + * Chen Li + * Zilin Du + * Sylvain Pion + * + * WWW URL: http://cs.nyu.edu/exact/ + * Email: exact@cs.nyu.edu + * + * $URL$ + * $Id$ + ***************************************************************************/ + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include + +#ifdef CGAL_HEADER_ONLY +#include // for FiveTo +#endif + +namespace CORE { + +CGAL_INLINE_FUNCTION +const Real& Real::getZero() { + static Real Zero(0); + return Zero; +} + +CGAL_INLINE_FUNCTION +BigInt floor(const Real& r, Real &sub) { + BigInt f = r.approx(CORE_INFTY, 2).BigIntValue(); + sub = r-f; + // Adjustment + if (sub<0) + ++sub, --f; + if (sub>=1) + --sub, ++f; + assert(sub >=0 && sub<1); + return f; +} + +// pow(r,n) and power(r, n) are the same function +// +CGAL_INLINE_FUNCTION +Real pow(const Real& r, unsigned long n) { + if (n == 0) + return Real(1); + else if (n == 1) + return r; + else { + Real x = r; + while ((n % 2) == 0) { // n is even + x *= x; + n >>= 1; + } + Real u = x; + while (true) { + n >>= 1; + if (n == 0) + return u; + x *= x; + if ((n % 2) == 1) // n is odd + u *= x; + } + //return u; // unreachable + } +}//pow + +extern BigInt FiveTo(unsigned long exp); + +// Construct Real from String +// Note: +// -- Zilin Du: 06/03/2003 +// -- Original it is the code for Real's constructor for "const char*". +// I change it to a function so that two constrcutors can share the code. +// now it is private and no default value. +// +// --Default value of the argument "prec" is get_static_defInputDigits() +// --If prec is CORE_posInfty, then the input is +// read in exactly. Otherwise, we convert to a RealBigFloat +// with absolute error at most 10^{-prec} + +// Constructor Real( char *str, extLong& prec) +// is very similar to +// BigFloatRep::fromString( char *str, extLong& prec); +// Differences: +// In BigFloat(str, prec), the value of prec cannot be infinity, and +// it defaults to defBigFloatInputDigits; +// In Real(str, prec), the value of prec is allowed to be infinity, and +// it defaults to defInputDigits. +// +// Why do we have the two versions? It allows us to use the BigFloat class +// directly, without relying on Real class. + +CGAL_INLINE_FUNCTION +void Real::constructFromString(const char *str, const extLong& prec ) +// NOTE: prec defaults to get_static_defInputDigits() (see Real.h) +{ + // 8/8/01, Chee and Zilin: add a new rational string format: + // this format is indicated by the presence of a slash "/" + // Moreover, the value of prec is ignored (basically + // assumed to be infinity). + + if (std::strchr(str, '/') != NULL) { // this is a rational number + rep = new RealBigRat(BigRat(str)); + return; + } + + const char *e = std::strchr(str, 'e'); + int dot = 0; + long e10 = 0; + if (e != NULL) + e10 = std::atol(e+1); // e10 is decimal precision of the input string + // i.e., input is A/10^{e10}. + else { + e = str + std::strlen(str); +#ifdef CORE_DEBUG + assert(*e == '\0'); +#endif + } + + const char *p = str; + if (*p == '-' || *p == '+') + p++; + BigInt m(0); + + for (; p < e; p++) { + if (*p == '.') { + dot = 1; + continue; + } + m = m * 10 + (*p - '0'); + if (dot) + e10--; + } + + long t = (e10 < 0) ? -e10 : e10; + BigInt one(1); + BigInt ten = FiveTo(t) * (one << static_cast(t)); + if (*str == '-') + m = -m; + if (e10 >= 0) { + // convert exactly from integer numbers + m *= ten; + rep = new RealBigInt(m); + } else { // e10 < 0, fractional numbers + // HERE IS WHERE WE USE THE SYSTEM CONSTANT + // get_static_defInputDigits() + // Note: get_static_defInputDigits() should be at least log_2(10). + // We default get_static_defInputDigits() to 4. + //std::cout << "(m,ten)=" << m << "," << ten << std::endl; + BigRat r(m, ten); + if (prec.isInfty()) { // convert exactly! to a big rational + rep = new RealBigRat(r); + } else { + // convert approximately, to a BigFloat within the + // specified precision: + // BigFloat bf(r, CORE_posInfty, prec * lgTenM) ; + BigFloat bf(r, CORE_posInfty, prec * 4) ; + rep = new RealBigFloat(bf); + } + } +}// Real(str, prec) + +// The operator >>(i,x) calls the constructor Real(char*) +CGAL_INLINE_FUNCTION +std::istream& operator >>(std::istream& i, Real& x) { + int size = 20; + char *str = new char[size]; + char *p = str; + char c; + int d = 0, e = 0, s = 0; + // int done = 0; + + // Chen Li: fixed a bug, the original statement is + // for (i.get(c); c == ' '; i.get(c)); + // use isspace instead of testing c == ' ', since it must also + // skip tab, catridge/return, etc. + // Change to: + // int status; + do { + i.get(c); + } while (!i.eof() && isspace(c)); /* loop if met end-of-file, or + char read in is white-space. */ + // Chen Li, + // original "if (c == EOF) ..." is unsafe since c is of char type and + // EOF is of int tyep with a negative value -1 + + if (i.eof()) { + i.clear(std::ios::eofbit | std::ios::failbit); + delete [] str; + return i; + } + + // the current content in "c" should be the first non-whitespace char + if (c == '-' || c == '+') { + *p++ = c; + i.get(c); + } + + for (; isdigit(c) || (!d && c=='.') || + (!e && c=='e') || (!s && (c=='-' || c=='+')); i.get(c)) { + if (!i) break; + if (!e && (c == '-' || c == '+')) + break; + // Chen Li: put one more rule to prohibite input like + // xxxx.xxxe+xxx.xxx: + if (e && (c == '.')) + break; + if (p - str == size) { + char *t = str; + str = new char[size*2]; + std::memcpy(str, t, size); + delete [] t; + p = str + size; + size *= 2; + } +#ifdef CORE_DEBUG + assert((p-str) < size); +#endif + + *p++ = c; + if (c == '.') + d = 1; + // Chen Li: fix a bug -- the sign of exponent can not happen before + // the character "e" appears! It must follow the "e' actually. + // if (e || c == '-' || c == '+') s = 1; + if (e) + s = 1; + if (c == 'e') + e = 1; + } + + if (!i && !i.eof()) { + delete [] str; + return i; + } + // chenli: make sure that the p is still in the range + if (p - str >= size) { + int len = p - str; + char *t = str; + str = new char[len + 1]; + std::memcpy(str, t, len); + delete [] t; + p = str + len; + } + +#ifdef CORE_DEBUG + assert(p - str < size); +#endif + + *p = '\0'; + i.putback(c); + i.clear(); + // old: x = Real(str, i.precision()); // use precision of input stream. + x = Real(str); // default precision = get_static_defInputDigits() + delete [] str; + return i; +}//operator >> (std::istream&, Real&) + +} //namespace CORE diff --git a/CGAL_Core/include/CGAL/CORE/extLong.h b/CGAL_Core/include/CGAL/CORE/extLong.h index 0962d160b76..b42e5a466bf 100644 --- a/CGAL_Core/include/CGAL/CORE/extLong.h +++ b/CGAL_Core/include/CGAL/CORE/extLong.h @@ -294,4 +294,9 @@ inline bool extLong::isNaN() const { } } //namespace CORE + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // _CORE_EXTLONG_H_ diff --git a/CGAL_Core/include/CGAL/CORE/extLong_impl.h b/CGAL_Core/include/CGAL/CORE/extLong_impl.h new file mode 100644 index 00000000000..238e2164ec0 --- /dev/null +++ b/CGAL_Core/include/CGAL/CORE/extLong_impl.h @@ -0,0 +1,212 @@ +/**************************************************************************** + * Core Library Version 1.7, August 2004 + * Copyright (c) 1995-2004 Exact Computation Project + * All rights reserved. + * + * This file is part of CORE (http://cs.nyu.edu/exact/core/). + * You can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * Licensees holding a valid commercial license may use this file in + * accordance with the commercial license agreement provided with the + * software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * File: extLong.cpp + * Synopsis: + * The class extLong is basically a wrapper around the machine + * type long. It is an important class to provide several + * additional facilities to detect overflows and undefined values. + * Future development includes extensions to level arithmetic + * (i.e., if a number overflows level i, we will go to level i+1). + * Level i representation of a number n is just i iterations + * of log_2 applied to n. + * + * Written by + * Chee Yap + * Chen Li + * Zilin Du + * Sylvain Pion + * + * WWW URL: http://cs.nyu.edu/exact/ + * Email: exact@cs.nyu.edu + * + * $URL$ + * $Id$ + ***************************************************************************/ + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include + +namespace CORE { + +CGAL_INLINE_FUNCTION +const extLong& extLong::getNaNLong() { + static extLong NaNLong(true); + return NaNLong; +} + +CGAL_INLINE_FUNCTION +const extLong& extLong::getPosInfty() { + static extLong posInfty(EXTLONG_MAX); + return posInfty; +} + +CGAL_INLINE_FUNCTION +const extLong& extLong::getNegInfty() { + static extLong negInfty(EXTLONG_MIN); + return negInfty; +} + +CGAL_INLINE_FUNCTION +void extLong::add(extLong& z, long x, long y) { + if (x > 0 && y > 0 && x >= EXTLONG_MAX - y) { + z.val = EXTLONG_MAX; + z.flag = 1; + } else if (x < 0 && y < 0 && x <= EXTLONG_MIN - y) { + z.val = EXTLONG_MIN; + z.flag = -1; + } else { + z.val = x + y; + z.flag = 0; + } +} + +// arithmetic and assignment operators +CGAL_INLINE_FUNCTION +extLong& extLong::operator+= (const extLong& y) { + if (flag == 2 || y.flag == 2 || (flag * y.flag < 0)) { +#ifdef CORE_DEBUG + if (flag * y.flag < 0) //want a message at the first creation of NaN + core_error("extLong NaN Error in addition.", __FILE__, __LINE__, false); +#endif + + *this = CORE_NaNLong; + } else if (flag == 1 || y.flag == 1) { // one of them is +Inf + *this = CORE_posInfty; + } else if (flag == -1 || y.flag == -1) { // one of them is -Inf + *this = CORE_negInfty; + } else { // x and y are normal now + add(*this, val, y.val); + } + return *this; +} + +CGAL_INLINE_FUNCTION +extLong& extLong::operator-= (const extLong& y) { + if (flag == 2 || y.flag == 2 || (flag * y.flag > 0)) { +#ifdef CORE_DEBUG + if (flag * y.flag > 0) //want a message at the first creation of NaN + core_error("extLong NaN Error in subtraction.", __FILE__, __LINE__, false); +#endif + + *this = CORE_NaNLong; + } else if (flag == 1 || y.flag == -1) { + *this = CORE_posInfty; + } else if (flag == -1 || y.flag == 1) { + *this = CORE_negInfty; + } else { + add(*this, val, -y.val); + } + return *this; +} + +CGAL_INLINE_FUNCTION +extLong& extLong::operator*= (const extLong& y) { + if (flag == 2 || y.flag == 2) { + *this = CORE_NaNLong; + } else if ((flag != 0) || (y.flag != 0)) { + if (sign() * y.sign() > 0) + *this = CORE_posInfty; + else + *this = CORE_negInfty; + } else { // flag == 0 and y.flag == 0 + double d = double(val) * double(y.val); + long p = val * y.val; + if (std::fabs(d - p) <= std::fabs(d) * relEps) { + val = p; + flag = 0; + } else if (d > EXTLONG_MAX) { + *this = CORE_posInfty; + } else if (d < EXTLONG_MIN) { + *this = CORE_negInfty; + } else { +#ifdef CORE_DEBUG + core_error("extLong NaN Error in multiplication.",__FILE__,__LINE__,false); +#endif + *this = CORE_NaNLong; + } + } + return *this; +} + +CGAL_INLINE_FUNCTION +extLong& extLong::operator/= (const extLong& y) { + if (flag==2 || y.flag==2 || ((flag != 0) && (y.flag != 0)) || (y.val == 0)) { +#ifdef CORE_DEBUG + if (y.val == 0) + core_error("extLong NaN Error, Divide by Zero.", __FILE__, __LINE__, false); + else if ((flag !=0) && (y.flag !=0)) + core_error("extLong NaN Error, +/-Inf/Inf.", __FILE__, __LINE__, false); +#endif + + *this = CORE_NaNLong; + } else if ((flag != 0) || (y.flag != 0)) { // y.flag == 0 now and y != 0 + if (sign() * y.sign() > 0) + *this = CORE_posInfty; + else + *this = CORE_negInfty; + } else { // flag == 0 and y.flag == 0 + val /= y.val; // no overflow in divisions + flag = 0; + } + return *this; +} + +// unary minus +CGAL_INLINE_FUNCTION +extLong extLong::operator- () const { + if (flag == 0) + return extLong(-val); + else if (flag == 1) + return CORE_negInfty; + else if (flag == -1) + return CORE_posInfty; + else // NaN + return CORE_NaNLong; +} + +// sign +// You should check "flag" before calling this, otherwise +// you cannot interprete the returned value! +CGAL_INLINE_FUNCTION +int extLong::sign() const { + if (flag == 2) + core_error("NaN Sign can not be determined!", __FILE__, __LINE__, false); + return ((val == 0) ? 0 : ((val > 0) ? 1 : -1)); +} + +// stream operators +CGAL_INLINE_FUNCTION +std::ostream& operator<< (std::ostream& o, const extLong& x) { + if (x.flag == 1) + o << " infty "; + else if (x.flag == - 1) + o << " tiny "; + else if (x.flag == 2) + o << " NaN "; + else + o << x.val; + return o; +} + +} //namespace CORE diff --git a/CGAL_Core/include/CGAL/CORE/poly/Poly.h b/CGAL_Core/include/CGAL/CORE/poly/Poly.h index 83cd7a2fe86..3e1d85e73ec 100644 --- a/CGAL_Core/include/CGAL/CORE/poly/Poly.h +++ b/CGAL_Core/include/CGAL/CORE/poly/Poly.h @@ -206,7 +206,8 @@ public: /// Polynomial evaluation where the coefficients are approximated first /// Returns a BigFloat with error that contains the value BigFloat evalApprox(const BigFloat& f, - const extLong& r=defRelPrec, const extLong& a=defAbsPrec) const; + const extLong& r=get_static_defRelPrec(), + const extLong& a=get_static_defAbsPrec()) const; /// Polynomial evaluation at a BigFloat value. /// The returned BigFloat (with error) has the exact sign. /// In particular, if the value is 0, we return 0. diff --git a/CGAL_Core/src/CGAL_Core/BigFloat.cpp b/CGAL_Core/src/CGAL_Core/BigFloat.cpp index 65d4aff6a69..9d92e7c0d4b 100644 --- a/CGAL_Core/src/CGAL_Core/BigFloat.cpp +++ b/CGAL_Core/src/CGAL_Core/BigFloat.cpp @@ -41,1247 +41,9 @@ * $Id$ ***************************************************************************/ -#include +#ifndef CGAL_HEADER_ONLY + #include -#include +#include -namespace CORE { - - -//////////////////////////////////////////////////////////// -// Misc Helper Functions -//////////////////////////////////////////////////////////// - -BigInt FiveTo(unsigned long exp) { - if (exp == 0) - return BigInt(1); - else if (exp == 1) - return BigInt(5); - else { - BigInt x = FiveTo(exp / 2); - - x = x * x; - - if (exp & 1) - x *= 5; - - return x; - } -} - -//////////////////////////////////////////////////////////// -// class BigFloat -//////////////////////////////////////////////////////////// - -// STATIC BIGFLOAT CONSTANTS -// ZERO -const BigFloat& BigFloat::getZero() { - static BigFloat Zero(0); - return Zero; -} -// ONE -const BigFloat& BigFloat::getOne() { - static BigFloat One(1); - return One; -} - -// A special constructor for BigFloat from Expr -// -- this method is somewhat of an anomaly (we normally do not expect -// BigFloats to know about Expr). -BigFloat::BigFloat(const Expr& E, const extLong& r, const extLong& a) - : RCBigFloat(new BigFloatRep()) { - *this = E.approx(r, a).BigFloatValue(); // lazy implementaion, any other way? -} - -//////////////////////////////////////////////////////////// -// class BigFloatRep -//////////////////////////////////////////////////////////// - -BigFloatRep::BigFloatRep(double d) : m(0), err(0), exp(0) { - if (d != 0.0) { - int isNegative = 0; - - if (d < 0.0) { - isNegative = 1; - d = - d; - } - - int binExp; - double f = frexp(d, &binExp); - - exp = chunkFloor(binExp); - - long s = binExp - bits(exp); - - long stop = 0; - double intPart; - - // convert f into a BigInt - while (f != 0.0 && stop < DBL_MAX_CHUNK) { - f = ldexp(f, (int)CHUNK_BIT); - f = modf(f, &intPart); - m <<= CHUNK_BIT; - m += (long)intPart; - exp--; - stop++; - } -#ifdef CORE_DEBUG - assert (s >= 0); #endif - - if (s) - m <<= s; - if (isNegative) - negate(m); - } -}//BigFloatRep constructor - -// approximation -void BigFloatRep::trunc(const BigInt& I, const extLong& r, const extLong& a) { - if (sign(I)) { - long tr = chunkFloor((- r + bitLength(I)).asLong()); - long ta = chunkFloor(- a.asLong()); - long t; - - if (r.isInfty() || a.isTiny()) - t = ta; - else if (a.isInfty()) - t = tr; - else - t = ta < tr ? tr : ta; - - if (t > 0) { // BigInt remainder; - m = chunkShift(I, - t); - err = 1; - exp = t; - } else { // t <= 0 - m = I; - err = 0; - exp = 0; - } - } else {// I == 0 - m = 0; - err = 0; - exp = 0; - } -} - -void BigFloatRep :: truncM(const BigFloatRep& B, const extLong& r, const extLong& a) { - if (sign(B.m)) { - long tr = chunkFloor((- 1 - r + bitLength(B.m)).asLong()); - long ta = chunkFloor(- 1 - a.asLong()) - B.exp; - long t; - - if (r.isInfty() || a.isTiny()) - t = ta; - else if (a.isInfty()) - t = tr; - else - t = ta < tr ? tr : ta; - - if (t >= chunkCeil(clLg(B.err))) { - m = chunkShift(B.m, - t); - err = 2; - exp = B.exp + t; - } else // t < chunkCeil(clLg(B.err)) - core_error(std::string("BigFloat error: truncM called with stricter") - + "precision than current error.", __FILE__, __LINE__, true); - } else {// B.m == 0 - long t = chunkFloor(- a.asLong()) - B.exp; - - if (t >= chunkCeil(clLg(B.err))) { - m = 0; - err = 1; - exp = B.exp + t; - } else // t < chunkCeil(clLg(B.err)) - core_error(std::string("BigFloat error: truncM called with stricter") - + "precision than current error.", __FILE__, __LINE__, true); - } -} - -// This is the main approximation function -// REMARK: would be useful to have a self-modifying version -// of this function (e.g., for Newton). -void BigFloatRep::approx(const BigFloatRep& B, - const extLong& r, const extLong& a) { - if (B.err) { - if (1 + clLg(B.err) <= bitLength(B.m)) - truncM(B, r + 1, a); - else // 1 + clLg(B.err) > lg(B.m) - truncM(B, CORE_posInfty, a); - } else {// B.err == 0 - trunc(B.m, r, a - bits(B.exp)); - exp += B.exp; - } - // Call normalization globally -- IP 10/9/98 - normal(); -} - -void BigFloatRep::div(const BigInt& N, const BigInt& D, - const extLong& r, const extLong& a) { - if (sign(D)) { - if (sign(N)) { - long tr = chunkFloor((- r + bitLength(N) - bitLength(D) - 1).asLong()); - long ta = chunkFloor(- a.asLong()); - - if (r.isInfty() || a.isTiny()) - exp = ta; - else if (a.isInfty()) - exp = tr; - else - exp = ta < tr ? tr : ta; - - BigInt remainder; - - // divide(chunkShift(N, - exp), D, m, remainder); - div_rem(m, remainder, chunkShift(N, - exp), D); - - if (exp <= 0 && sign(remainder) == 0) - err = 0; - else - err = 1; - } else {// N == 0 - m = 0; - err = 0; - exp = 0; - } - } else // D == 0 - core_error( "BigFloat error: zero divisor.", __FILE__, __LINE__, true); - - // Call normalization globally -- IP 10/9/98 - normal(); -}//div - -// error-normalization -void BigFloatRep::normal() { - long le = flrLg(err); - - if (le >= CHUNK_BIT + 2) { // so we do not carry more than 16 = CHUNK_BIT + 2 - // bits of error - long f = chunkFloor(--le); // f is roughly equal to floor(le/CHUNK_BIT) - long bits_f = bits(f); // f chunks will have bits_f many bits -#ifdef CORE_DEBUG - assert (bits_f >= 0); -#endif - - m >>= bits_f; // reduce mantissa by bits_f many bits - err >>= bits_f; // same for err - err += 2; // why 2? - exp += f; - } - if (err == 0) // unlikely, if err += 2 above - eliminateTrailingZeroes(); -} - -// bigNormal(err) -// convert a bigInt error value (=err) into an error that fits into -// a long number. This is done by -// by increasing the exponent, and corresponding decrease -// in the bit lengths of the mantissa and error. -// -void BigFloatRep::bigNormal(BigInt& bigErr) { - long le = bitLength(bigErr); - - if (le < CHUNK_BIT + 2) { - err = ulongValue(bigErr); - } else { - long f = chunkFloor(--le); - long bits_f = bits(f); -#ifdef CORE_DEBUG - assert(bits_f >= 0); -#endif - - m >>= bits_f; - bigErr >>= bits_f; - err = ulongValue(bigErr) + 2; // you need to add "2" because "1" comes - // from truncation error in the mantissa, and another - // "1" comes from the truncation error in the bigErr. - // (But there is danger of overflow...) - exp += f; - } - - if (err == 0) - eliminateTrailingZeroes(); -} - -// ARITHMETIC: -// Addition -void BigFloatRep::add(const BigFloatRep& x, const BigFloatRep& y) { - long expDiff = x.exp - y.exp; - - if (expDiff > 0) {// x.exp > y.exp - if (!x.err) { - m = chunkShift(x.m, expDiff) + y.m; - err = y.err; - exp = y.exp; - } else {// x.err > 0 - m = x.m + chunkShift(y.m, - expDiff); // negative shift! - err = x.err + 5; // To account for y.err (but why 5?) - exp = x.exp; // - // normal(); - } - } else if (!expDiff) {// x.exp == y.exp - m = x.m + y.m; - err = x.err + y.err; - exp = x.exp; - // normal(); - } else {// x.exp < y.exp - if (!y.err) { - m = x.m + chunkShift(y.m, - expDiff); - err = x.err; - exp = x.exp; - } else {// y.err > 0 - m = chunkShift(x.m, expDiff) + y.m; - err = y.err + 5; - exp = y.exp; - // normal(); - } - } - // Call normalization globally -- IP 10/9/98 - normal(); -} - -// Subtraction -void BigFloatRep::sub(const BigFloatRep& x, const BigFloatRep& y) { - long expDiff = x.exp - y.exp; - - if (expDiff > 0) {// x.exp > y.exp - if (!x.err) { - m = chunkShift(x.m, expDiff) - y.m; - err = y.err; - exp = y.exp; - } else {// x.err > 0 - m = x.m - chunkShift(y.m, - expDiff); - err = x.err + 5; - exp = x.exp; - // normal(); - } - } else if (!expDiff) { - m = x.m - y.m; - err = x.err + y.err; - exp = x.exp; - // normal(); - } else { // x.exp < y.exp - if (!y.err) { - m = x.m - chunkShift(y.m, - expDiff); - err = x.err; - exp = x.exp; - } else {// y.err > 0 - m = chunkShift(x.m, expDiff) - y.m; - err = y.err + 5; - exp = y.exp; - // normal(); - } - } - // Call normalization globally -- IP 10/9/98 - normal(); -} - -void BigFloatRep::mul(const BigFloatRep& x, const BigFloatRep& y) { - m = x.m * y.m; - exp = x.exp + y.exp; - // compute error (new code, much faster. Zilin Du, Nov 2003) - if (x.err == 0 && y.err == 0) { - err = 0; - eliminateTrailingZeroes(); - } else { - BigInt bigErr(0); - if (y.err != 0) - bigErr += abs(x.m)*y.err; - if (x.err != 0) - bigErr += abs(y.m)*x.err; - if (x.err !=0 && y.err != 0) - bigErr += x.err*y.err; - bigNormal(bigErr); - } -} -// BigFloat div2 will half the value of x, exactly with NO error -// REMARK: should generalize this to dividing by any power of 2 -// We need this in our use of BigFloats to maintain isolation -// intervals (e.g., in Sturm sequences) --Chee/Vikram 4/2003 -// -void BigFloatRep :: div2(const BigFloatRep& x) { - if (isEven(x.m)) { - m = (x.m >> 1); - exp = x.exp ; - } else { - m = (x.m << static_cast(CHUNK_BIT-1)); - exp = x.exp -1; - } -} - -// Converts a BigFloat interval into one BigFloat with almost same error bound -// This routine ignores the errors in inputs a and b. -// But you cannot really ignore them since, they are taken into account -// when you compute "r.sub(a,b)"... -void BigFloatRep::centerize(const BigFloatRep& a, const BigFloatRep& b) { - if ((a.m == b.m) && (a.err == b.err) && (a.exp == b.exp)) { - m = a.m; - err = a.err; - exp = a.exp; - return; - } - - BigFloatRep r; - r.sub(a, b); - r.div2(r); - - //setup mantissa and exponent, but not error bits - // But this already sets the error bits? Chee - add(a,b); - div2(*this); - // error bits = ceil ( B^{-exp}*|a-b|/2 ) - - // bug fixed: possible overflow on converting - // Zilin & Vikram, 08/24/04 - // err = 1 + longValue(chunkShift(r.m, r.exp - exp)); - BigInt E = chunkShift(r.m, r.exp - exp); - bigNormal(E); -} - -// BigFloat Division, computing x/y: -// Unlike +,-,*, this one takes a relative precision bound R -// Note that R is only used when x and y are error-free! -// (This remark means that we may be less efficient than we could be) -// -// Assert( R>0 && R< CORE_Infty ) -// -void BigFloatRep :: div(const BigFloatRep& x, const BigFloatRep& y, - const extLong& R) { - if (!y.isZeroIn()) { // y.m > y.err, so we are not dividing by 0 - if (!x.err && !y.err) { - if (R < 0 || R.isInfty()) //Oct 9, 2002: fixed major bug! [Zilin/Chee] - div(x.m, y.m, defBFdivRelPrec, CORE_posInfty); - else - div(x.m, y.m, R, CORE_posInfty); - exp += x.exp - y.exp; // chen: adjust exp. - } else {// x.err > 0 or y.err > 0 - BigInt bigErr, errRemainder; - - if (x.isZeroIn()) { // x.m <= x.err - m = 0; - exp = x.exp - y.exp; - - div_rem(bigErr, errRemainder, abs(x.m) + static_cast(x.err), - abs(y.m) - static_cast(y.err)); - } else { // x.m > x.err - long lx = bitLength(x.m); - long ly = bitLength(y.m); - long r; - - if (!x.err) // x.err == 0 and y.err > 0 - r = ly + 2; - else if(!y.err) // x.err > 0 and y.err == 0 - r = lx + 2; - else // x.err > 0 and y.err > 0 - r = lx < ly ? lx + 2: ly + 2; - - long t = chunkFloor(- r + lx - ly - 1); - BigInt remainder; - - div_rem(m, remainder, chunkShift(x.m, - t), y.m); - exp = t + x.exp - y.exp; - - long delta = ((t > 0) ? 2 : 0); - - // Chen Li: 9/9/99 - // here again, it use ">>" operator with a negative - // right operand. So the result is not well defined. - // Erroneous code: - // divide(abs(remainder) + (static_cast(x.err) >> bits(t)) - // + delta + static_cast(y.err) * abs(m), - // abs(y.m) - static_cast(y.err), - // bigErr, - // errRemainder); - // New code: - BigInt errx_over_Bexp = x.err; - long bits_Bexp = bits(t); - if (bits_Bexp >= 0) { - errx_over_Bexp >>= bits_Bexp; - } else { - errx_over_Bexp <<= (-bits_Bexp); - } - - // divide(abs(remainder) + errx_over_Bexp - // + delta + static_cast(y.err) * abs(m), - // abs(y.m) - static_cast(y.err), - // bigErr, - // errRemainder); - div_rem(bigErr, errRemainder, - abs(remainder) + errx_over_Bexp + delta + static_cast(y.err) * abs(m), - abs(y.m) - static_cast(y.err)); - } - - if (sign(errRemainder)) - ++bigErr; - - bigNormal(bigErr); - } - } else {// y.m <= y.err - core_error("BigFloat error: possible zero divisor.", - __FILE__, __LINE__, true); - } - - // Call normalization globally -- IP 10/9/98 - // normal(); -- Chen: after calling bigNormal, this call is redundant. -}// BigFloatRep::div - -// squareroot for BigInt argument, without initial approximation -// sqrt(x,a) computes sqrt of x to absolute precision a. -// -- this is where Newton is applied -// -- this is called by BigFloatRep::sqrt(BigFloat, extLong) -void BigFloatRep::sqrt(const BigInt& x, const extLong& a) { - sqrt(x, a, BigFloat(x, 0, 0)); -} // sqrt(BigInt x, extLong a) , without initial approx - -// sqrt(x,a,A) where -// x = bigInt whose sqrt is to be computed -// a = absolute precision bound -// A = initial approximation in BigFloat -// -- this is where Newton is applied -// -- it is called by BigFloatRep::sqrt(BigFloatRep, extLong, BigFloat) -void BigFloatRep::sqrt(const BigInt& x, const extLong& a, const BigFloat& A) { - if (sign(x) == 0) { - m = 0; - err = 0; - exp = 0; - } else if (x == 1) { - m = 1; - err = 0; - exp = 0; - } else {// main case - // here is where we use the initial approximation - m = A.m(); - err = 0; - exp = A.exp(); - - BigFloatRep q, z; - extLong aa; - // need this to make sure that in case the - // initial approximation A is less than sqrt(x) - // then Newton iteration will still proceed at - // least one step. - bool firstTime = true; - for (;;) { - aa = a - bits(exp); - q.div(x, m, CORE_posInfty, aa); - q.err = 0; - q.exp -= exp; - - z.sub(*this, q); // this=current approximation, so z = this - q - /*if (sign(z.m) <= 0 || z.MSB() < - a) // justification: see Koji's - break; // thesis (p. 28) which states - // that we can exit when - // " (*this) <= q + 2**(-a)" - */ - // The preceding code is replaced by what follows: - if (z.MSB() < -a) - break; - if (sign(z.m) <= 0) { - if (firstTime) - firstTime = false; - else - break; - } - - z.add(*this, q); - // Chen Li: a bug fixed here. - // m = z.m >> 1; - // err = 0; - // exp = z.exp; - if ((z.m > 1) && isEven(z.m)) { - m = z.m >> 1; // exact division by 2 - err = 0; - exp = z.exp; - } else { // need to shift left before division by 2 - m = chunkShift(z.m, 1) >> 1; - err = 0; - exp = z.exp - 1; - }//else - }//for - }//else -} // sqrt of BigInt, with initial approx - -// MAIN ENTRY INTO SQRT FUNCTION (BIGFLOAT ARGUMENT, WITHOUT INITIAL APPROX) -void BigFloatRep::sqrt(const BigFloatRep& x, const extLong& a) { - sqrt(x, a, BigFloat(x.m, 0, x.exp)); -} //sqrt(BigFloat, extLong a) - -// MAIN ENTRY INTO SQRT FUNCTION (BIGFLOAT ARGUMENT WITH INITIAL APPROXIMATION) -void BigFloatRep::sqrt(const BigFloatRep& x, const extLong& a, const BigFloat& A) { - // This computes the sqrt of x to absolute precision a, starting with - // the initial approximation A - if (sign(x.m) >= 0) { // x.m >= 0 - int delta = x.exp & 1; // delta=0 if x.exp is even, otherwise delta=1 - - if (x.isZeroIn()) { // x.m <= x.err - m = 0; - if (!x.err) - err = 0; - else { // x.err > 0 - err = (long)(std::sqrt((double)x.err)); - err++; - err <<= 1; - if (delta) - err <<= HALF_CHUNK_BIT; - } - exp = x.exp >> 1; - normal(); - } else { - long aExp = A.exp() - (x.exp >> 1); - BigFloat AA( chunkShift(A.m(), delta), 0, aExp); - - if (!x.err) { // x.m > x.err = 0 (ERROR FREE CASE) - BigFloatRep z; - extLong ppp; - if (a.isInfty()) //Oct 9, 2002: fixed major bug! [Zilin/Chee] - ppp = defBFsqrtAbsPrec; - else - ppp = a + EXTLONG_ONE; - extLong absp = ppp + bits(x.exp >> 1); - - z.sqrt(chunkShift(x.m, delta), absp, AA); // call sqrt(BigInt, a, AA) - - long p = (absp + bits(z.exp)).asLong(); - - // Next, normalize the error: - if (p <= 0) { - m = z.m; - // Chen Li: a bug fixed - // BigInt bigErr = 1 << (-p); - BigInt bigErr(1); - bigErr = bigErr << static_cast(-p); - exp = z.exp + (x.exp >> 1); - bigNormal(bigErr); - } else { // p > 0 - m = chunkShift(z.m, chunkCeil(p)); - long r = CHUNK_BIT - 1 - (p + CHUNK_BIT - 1) % CHUNK_BIT; -#ifdef CORE_DEBUG - assert(r >= 0); -#endif - - err = 1 >> r; - exp = - chunkCeil(ppp.asLong()); - normal(); - } - } else { // x.m > x.err > 0 (mantissa has error) - BigFloatRep z; - extLong absp=-flrLg(x.err)+bitLength(x.m)-(bits(delta) >> 1)+EXTLONG_FOUR; - - z.sqrt(chunkShift(x.m, delta), absp, AA); - - long qqq = - 1 + (bitLength(x.m) >> 1) - delta * HALF_CHUNK_BIT; - long qq = qqq - clLg(x.err); - long q = qq + bits(z.exp); - - if (q <= 0) { - m = z.m; - long qqqq = - qqq - bits(z.exp); - // Chen Li (09/08/99), a bug fixed here: - // BigInt bigErr = x.err << - qqqq; - // when (-qqqq) is negative, the result is not correct. - // how "<<" and ">>" process negative second operand is - // not well defined. Seems it just take it as a unsigned - // integer and extract the last few bits. - // x.err is a long number which easily overflows. - // From page 22 of Koji's paper, I think the exponent is - // wrong here. So I rewrote it as: - BigInt bigErr = x.err; - if (qqqq >= 0) { - bigErr <<= qqqq; - } else { - bigErr >>= (-qqqq); - ++bigErr; // we need to keep its ceiling. - } - - exp = z.exp + (x.exp >> 1); - bigNormal(bigErr); - } else { // q > 0 - m = chunkShift(z.m, chunkCeil(q)); - long r = CHUNK_BIT - 1 - (q + CHUNK_BIT - 1) % CHUNK_BIT; -#ifdef CORE_DEBUG - assert(r >= 0); -#endif - - err = 1 >> r; - exp = (x.exp >> 1) - chunkCeil(qq); - normal(); - } - } // end of case with error in mantissa - }//else - } else - core_error("BigFloat error: squareroot called with negative operand.", - __FILE__, __LINE__, true); -} //sqrt with initial approximation - -// compareMExp(x) -// returns 1 if *this > x -// 0 if *this = x, -// -1 if *this < x, -// -// Main comparison method for BigFloat -// This is called by BigFloat::compare() -// BE CAREFUL: The error bits are ignored! -// Need another version if we want to take care of error bits - -int BigFloatRep :: compareMExp(const BigFloatRep& x) const { - int st = sign(m); - int sx = sign(x.m); - - if (st > sx) - return 1; - else if (st == 0 && sx == 0) - return 0; - else if (st < sx) - return - 1; - else { // need to compare m && exp - long expDiff = exp - x.exp; - - if (expDiff > 0) // exp > x.exp - return cmp(chunkShift(m, expDiff), x.m); - else if (!expDiff) - return cmp(m, x.m); - else // exp < x.exp - return cmp(m, chunkShift(x.m, - expDiff)); - } -} - -// 3/6/2000: -// This is a private function used by BigFloatRep::operator<< -// to get the exact value -// of floor(log10(M * 2^ e)) where E is an initial guess. -// We will return the correct E which satisfies -// 10^E <= M * 2^e < 10^{E+1} -// But we convert this into -// mm <= M < 10.mm - -long BigFloatRep :: adjustE( long E, BigInt M, long ee) const { - if (M<0) - M=-M; - BigInt mm(1); - if (ee > 0) - M = (M<(ee)); - else - mm = (mm << static_cast(-ee)); - if (E > 0) - mm *= (FiveTo(E)<< static_cast(E)); - else - M *= (FiveTo(-E) << static_cast(-E)); - - if (M < mm) { - do { - E--; - M *= 10; - } while (M < mm); - } else if (M >= 10*mm) { - mm *= 10; - do { - E++; - mm *= 10; - } while (M >= mm); - } - return E; -} - -BigFloatRep::DecimalOutput -BigFloatRep::toDecimal(unsigned int width, bool Scientific) const { - BigFloatRep::DecimalOutput decOut; // to be returned - if (err > 0) { - decOut.isExact = false; - } else { // err == 0 - decOut.isExact = true; - } - - if (err > 0 && err >= abs(m)) { - // if err is larger than mantissa, sign and significant values - // can not be determined. - core_error("BigFloat error: Error is too big!", - __FILE__, __LINE__, false); - decOut.rep = "0.0e0"; // error is too big - decOut.isScientific = false; - decOut.noSignificant = 0; - decOut.errorCode = 1; // sign of this number is unknown - return decOut; - } - - decOut.sign = sign(m); - decOut.errorCode = 0; - - BigInt M(m); // temporary mantissa - long lm = bitLength(M); // binary length of mantissa - long e2 = bits(exp); // binary shift length represented by exponent - long le = clLg(err); // binary length of err - if (le == -1) - le = 0; - - long L10 = 0; - if (M != 0) { - L10 = (long)std::floor((lm + e2) / lgTenM); - L10 = adjustE(L10, m, e2); // L10: floor[log10(M 2^(e2))], M != 0 - } else { - L10 = 0; - } - // Convention: in the positional format, when the output is - // the following string of 8 characters: - // (d0, d1, d2, d3, ".", d4, d5, d6, d7) - // then the decimal point is said to be in the 4th position. - // E.g., (d0, ".", d1, d2) has the decimal point in the 1st position. - // The value of L10 says that the decimal point of output should be at - // the (L10 + 1)st position. This is - // true regardingless of whether M = 0 or not. For zero, we output - // {0.0*} so L10=0. In general, the |value| is less than 10 - // if and only if L10 is 0 and the - // decimal point is in the 1st place. Note that L10 is defined even if - // the output is an integer (in which case it does not physically appear - // but conceptually terminates the sequence of digits). - - // First, get the decimal representaion of (m * B^(exp)). - if (e2 < 0) { - M *= FiveTo(-e2); // M = x * 10^(-e2) - } else if (e2 > 0) { - M <<= e2; // M = x * 2^(e2) - } - - std::string decRep = M.get_str(); - // Determine the "significant part" of this string, i.e. the part which - // is guaranteed to be correct in the presence of error, - // except that the last digit which might be subject to +/- 1. - - if (err != 0) { // valid = number of significant digits - unsigned long valid = floorlg10(m) - (long)std::floor(std::log10(float(err))); - if (decRep.length() > valid) { - decRep.erase(valid); - } - } - - // All the digits in decM are correct, except the last one might - // subject to an error +/- 1. - - if ((decRep[0] == '+') || (decRep[0] == '-')) { - decRep.erase(0, 1); - } - - // Second, make choice between positional representation - // and scientific notation. Use scientific notation when: - // 0) if scientific notation flag is on - // 1) err * B^exp >= 1, the error contribute to the integral part. - // 2) (1 + L10) >= width, there is not have enough places to hold the - // positional representation, not including decimal point. - // 3) The distance between the first significant digit and decimal - // point is too large for the width limit. This is equivalent to - // Either ((L10 >= 0 and (L10 + 1) > width)) - // Or ((L10 < 0) and (-L10 + 1) > width). - - if (Scientific || - ((err > 0) && (le + e2) >= 0) || // if err*B^exp >= 1 - ((L10 >= 0) && (L10 + 1 >= (long)width )) || - ((L10 < 0) && (-L10 + 1 > (long)width ))) { - // use scientific notation - decRep = round(decRep, L10, width); - decOut.noSignificant = width; - decRep.insert(1, "."); - if (L10 != 0) { - decRep += 'e'; - if (L10 > 0) { - decRep += '+'; - } else { // L10 < 0 - decRep += '-'; - } - char eBuf[48]; // enought to hold long number L10 - int ne = 0; - if ((ne = sprintf(eBuf, "%ld", labs(L10))) >= 0) { - eBuf[ne] = '\0'; - } else { - //perror("BigFloat.cpp: Problem in outputing the exponent!"); - core_error("BigFloat error: Problem in outputing the exponent", - __FILE__, __LINE__, true); - } - decRep += eBuf; - decOut.isScientific = true; - } - } else { - // use conventional positional notation. - if (L10 >= 0) { // x >= 1 or x == 0 and L10 + 1 <= width - // round when necessary - if (decRep.length() > width ) { - decRep = round(decRep, L10, width ); - if (decRep.length() > width ) { - // overflow happens! use scientific notation - return toDecimal(width, true); - } - } - decOut.noSignificant = decRep.length(); - if (L10 + 1 < (long)width ) { - decRep.insert(L10 + 1, "."); - } else { // L10 + 1 == width - // do nothing - } - } else { // L10 < 0, 0 < x < 1 - // (-L10) leading zeroes, including one to the left of decimal dot - // need to be added in beginning. - decRep = std::string(-L10, '0') + decRep; - // then round when necessary - if (decRep.length() > width ) { - decRep = round(decRep, L10, width ); - // cannot overflow since there are L10 leading zeroes. - } - decOut.noSignificant = decRep.length() - (-L10); - decRep.insert(1, "."); - } - decOut.isScientific = false; - } -#ifdef CORE_DEBUG - assert(decOut.noSignificant >= 0); -#endif - - decOut.rep = decRep; - return decOut; -}//toDecimal - -std::string BigFloatRep::round(std::string inRep, long& L10, unsigned int width) const { - // round inRep so that the length would not exceed width. - if (inRep.length() <= width) - return inRep; - - int i = width; // < length - bool carry = false; - - if ((inRep[i] >= '5') && (inRep[i] <= '9')) { - carry = true; - i--; - while ((i >= 0) && carry) { - if (carry) { - inRep[i] ++; - if (inRep[i] > '9') { - inRep[i] = '0'; - carry = true; - } else { - carry = false; - } - } - i-- ; - } - - if ((i < 0) && carry) { // overflow - inRep.insert(inRep.begin(), '1'); - L10 ++; - width ++; - } - } - - return inRep.substr(0, width); -}//round(string,width) - - -// This function fromString(str, prec) is similar to the -// constructor Real(char * str, extLong prec) -// See the file Real.cc for the differences - -void BigFloatRep :: fromString(const char *str, const extLong & prec ) { - // NOTE: prec defaults to defBigFloatInputDigits (see BigFloat.h) - // check that prec is not INFTY - if (prec.isInfty()) - core_error("BigFloat error: infinite precision not allowed", - __FILE__, __LINE__, true); - - const char *e = strchr(str, 'e'); - int dot = 0; - long e10 = 0; - if (e != NULL) - e10 = atol(e+1); // e10 is decimal precision of the input string - // i.e., input is A/10^{e10}. - else { - e = str + strlen(str); -#ifdef CORE_DEBUG - assert(*e == '\0'); -#endif - - } - - const char *p = str; - if (*p == '-' || *p == '+') - p++; - m = 0; - exp = 0; - - for (; p < e; p++) { - if (*p == '.') { - dot = 1; - continue; - } - m = m * 10 + (*p - '0'); - if (dot) - e10--; - } - - BigInt one = 1; - long t = (e10 < 0) ? -e10 : e10; - BigInt ten = FiveTo(t) * (one << static_cast(t)); - - // HERE IS WHERE WE USE THE SYSTEM CONSTANT - // defBigFloatInputDigits - // Note: this constant is rather similar to defInputDigits which - // is used by Real and Expr for controlling - // input accuracy. The difference is that defInputDigits can - // be CORE_INFTY, but defBigFloatInputDigits must be finite. - - if (e10 < 0) - div(m, ten, CORE_posInfty, 4 * prec); - else - m *= ten; - if (*str == '-') - m = -m; -}//BigFloatRep::fromString - -std::istream& BigFloatRep :: operator >>(std::istream& i) { - int size = 20; - char *str = new char[size]; - char *p = str; - char c; - int d = 0, e = 0, s = 0; - // d=1 means dot is found - // e=1 means 'e' or 'E' is found - // int done = 0; - - // Chen Li: fixed a bug, the original statement is - // for (i.get(c); c == ' '; i.get(c)); - // use isspace instead of testing c == ' ', since it must also - // skip tab, catridge/return, etc. - // Change to: - // int status; - do { - c = i.get(); - } while (isspace(c)); /* loop if met end-of-file, or - char read in is white-space. */ - // Chen Li, "if (c == EOF)" is unsafe since c is of char type and - // EOF is of int tyep with a negative value -1 - if (i.eof()) { - i.clear(std::ios::eofbit | std::ios::failbit); - return i; - } - - // the current content in "c" should be the first non-whitespace char - if (c == '-' || c == '+') { - *p++ = c; - i.get(c); - } - - for (; isdigit(c) || (!d && c=='.') || - (!e && ((c=='e') || (c=='E'))) || (!s && (c=='-' || c=='+')); i.get(c)) { - if (!e && (c == '-' || c == '+')) - break; - // Chen Li: put one more rule to prohibite input like - // xxxx.xxxe+xxx.xxx: - if (e && (c == '.')) - break; - if (p - str == size) { - char *t = str; - str = new char[size*2]; - memcpy(str, t, size); - delete [] t; - p = str + size; - size *= 2; - } -#ifdef CORE_DEBUG - assert((p-str) < size); -#endif - - *p++ = c; - if (c == '.') - d = 1; - // Chen Li: fix a bug -- the sign of exponent can not happen before - // the character "e" appears! It must follow the "e' actually. - // if (e || c == '-' || c == '+') s = 1; - if (e) - s = 1; - if ((c == 'e') || (c=='E')) - e = 1; - } - - // chenli: make sure that the p is still in the range - if (p - str >= size) { - int len = p - str; - char *t = str; - str = new char[len + 1]; - memcpy(str, t, len); - delete [] t; - p = str + len; - } - -#ifdef CORE_DEBUG - assert(p - str < size); -#endif - - *p = '\0'; - i.putback(c); - fromString(str); - delete [] str; - return i; -}//operator >> - - -// BigFloatRep::toDouble() -// converts the BigFloat to a machine double -// This is a dangerous function as the method -// is silent when it does not fit into a machine double! -// ToDo: fix this by return a machine NaN, +/- Infinity, +/- 0, -// when appropriate. -// Return NaN when error is larger than mantissa -// Return +/- Infinity if BigFloat is too big -// Return +/- 0 if BigFloat is too small -#ifdef _MSC_VER -#pragma warning(disable: 4723) -#endif -double BigFloatRep :: toDouble() const { - if (m == 0) - return (sign(m) * 0.0); - - long e2 = bits(exp); - long le = clLg(err); // if err=0, le will be -1 - if (le == -1) - le = 0; - - BigInt M = m >> static_cast(le);// remove error bits in mantissa - - // Below, we want to return NaN by computing 0.0/0.0. - // To avoid compiler warnings about divide by zero, we do this: - - double foolCompilerZero; - foolCompilerZero = 0.0; - - // COMMENT: we should directly store the - // special IEEE values NaN, +/-Infinity, +/-0 in the code!! - - if (M == 0) - return ( 0.0/foolCompilerZero ) ; // return NaN - - e2 += le; // adjust exponent corresponding to error bits - - int len = bitLength(M) - 53; // this is positive if M is too large - - if (len > 0) { - M >>= len; - e2 += len; - } - - double tt = doubleValue(M); - - int ee = e2 + bitLength(M) - 1; // real exponent. - - if (ee >= 1024) // overflow! - return ( sign(m)/foolCompilerZero ); // return a signed infinity - - if (ee <= -1075) // underflow! - // NOTE: if (-52 < ee <= 0) get denormalized number - return ( sign(m) * 0.0 ); // return signed zero. - - // Execute this loop if e2 < 0; - for (int i = 0; i > e2; i--) - tt /= 2; - - // Execute this loop if e2 > 0; - for (int j = 0; j < e2; j++) - tt *= 2; - - return tt; -}//toDouble -#ifdef _MSC_VER -#pragma warning(default: 4723) -#endif -BigInt BigFloatRep::toBigInt() const { - long e2 = bits(exp); - long le = clLg(err); - if (le == -1) - le = 0; -#ifdef CORE_DEBUG - assert (le >= 0); -#endif - - BigInt M = m >> static_cast(le); // discard the contaminated bits. - e2 += le; // adjust the exponent - - if (e2 < 0) - return M >> static_cast(-e2); - else if (e2 > 0) - return M << static_cast(e2); - else - return M; -} - -long BigFloatRep :: toLong() const { - // convert a BigFloat to a long integer, rounded toward -\infty. - long e2 = bits(exp); - long le = clLg(err); -#ifdef CORE_DEBUG - assert (le >= 0); -#endif - - BigInt M = m >> static_cast(le); // discard the contaminated bits. - e2 += le; // adjust the exponent - long t; - if (e2 < 0) - t = ulongValue(M >> static_cast(-e2)); - else if (e2 > 0) - t = ulongValue(M << static_cast(e2)); - else - t = ulongValue(M); - // t = M.as_long(); - // Note: as_long() will return LONG_MAX in case of overflow. - - return t; -} - -// pow(r,n) function for BigFloat -// Note: power(r,n) calls pow(r,n) -BigFloat pow(const BigFloat& r, unsigned long n) { - if (n == 0) - return BigFloat(1); - else if (n == 1) - return r; - else { - BigFloat x = r; - while ((n % 2) == 0) { // n is even - x *= x; - n >>= 1; - } - BigFloat u = x; - while (true) { - n >>= 1; - if (n == 0) - return u; - x *= x; - if ((n % 2) == 1) // n is odd - u *= x; - } - //return u; // unreachable - } -}//pow - -// experimental -BigFloat root(const BigFloat& x, unsigned long k, - const extLong& a, const BigFloat& A) { - if (x.sign() == 0) { - return BigFloat(0); - } else if (x == 1) { - return BigFloat(1); - } else { - BigFloat q, del, zz; - BigFloat z = A; - BigFloat bk = long(k); - for (; ;) { - zz = pow(z, k-1); - q = x.div(zz, a); - q.makeExact(); - del = z - q; - del.makeExact(); - if (del.MSB() < -a) - break; - z = ((bk-1)*z + q).div(bk, a); - // newton's iteration: z_{n+1}=((k-1)z_n+x/z_n^{k-1})/k - z.makeExact(); - } - return z; - } -}//root - -} //namespace CORE diff --git a/CGAL_Core/src/CGAL_Core/CoreAux.cpp b/CGAL_Core/src/CGAL_Core/CoreAux.cpp index 6215a333047..a8f7d2494a6 100644 --- a/CGAL_Core/src/CGAL_Core/CoreAux.cpp +++ b/CGAL_Core/src/CGAL_Core/CoreAux.cpp @@ -33,181 +33,9 @@ * $Id$ ***************************************************************************/ -#include "CGAL/CORE/CoreAux.h" -#include +#ifndef CGAL_HEADER_ONLY -namespace CORE { +#include +#include -//////////////////////////////////////////////////////////// -// More useful functions to implement: -// -// To convert digits into bits: -// given X, compute X * log_2(10) -// To convert bits into digits: -// given X, compute X * log_10(2) -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// flrLg(x) -// returns floor log base 2 of abs(x) -// CONVENTION lg(0) = -1 (Slight improvement, Zilin/Chee 8/5/02) -//////////////////////////////////////////////////////////// -int flrLg(long x) { - if (x == LONG_MIN) { - // special treatment as -LONG_MIN would be not representable as "long" - return LONG_BIT - 1; - } else { - // 1 <= |x| <= LONG_MAX - if (x < 0) - x = - x; - - int lg = -1; - while (x > 0) { - lg++; - x >>= 1; - } - return lg; - } -} - -//////////////////////////////////////////////////////////// -// floor log base 2 of unsigned long x -// CONVENTION lg(0) = -1 (Slight improvement, Zilin/Chee 8/5/02) -//////////////////////////////////////////////////////////// -int flrLg(unsigned long x) { - int lg = -1; - while (x > 0) { - lg++; - x >>= 1; - } - return lg; -} - -//////////////////////////////////////////////////////////// -// ceiling log base 2 of abs(x) -// CONVENTION lg(0) = -1 (Slight improvement, Zilin/Chee 8/5/02) -//////////////////////////////////////////////////////////// -int clLg(long x) { - if (x == LONG_MIN) - return LONG_BIT - 1; - if (x < 0) - x = -x; // use absolute value - if (x > (LONG_MAX >> 1)) // the leading data bit is 1 - return (LONG_BIT - 1); // exclude the sign bit - if (x >= 2) - return flrLg((unsigned long)((x << 1) - 1)); - // SINCE ceilLog_2(x) = floorLog_2(2x-1) for x>=2 - if (x == 1) - return 0; - return -1; // x must be 0 here -} - -//////////////////////////////////////////////////////////// -// ceiling log base 2 of unsigned long x -// CONVENTION lg(0) = -1 -//////////////////////////////////////////////////////////// -int clLg(unsigned long x) { - if (x > (ULONG_MAX >> 1)) // the leading bit is 1 - return LONG_BIT; - if (x >= 2) - return flrLg((x << 1) - 1); - // SINCE ceilLog_2(x) = floorLog_2(2x-1) for x>=2. - if (x == 1) - return 0; - return -1; // x must be equal to 0 -} - -/// gcd for machine type long -/** This is needed when we construct Polynomials with int or long coefficients */ -long gcd(long m, long n) { - if (m == 0) - return core_abs(n); - if (n == 0) - return core_abs(m); - long p = core_abs(m); - long q = core_abs(n); - if (p0) { - long r = p % q; - p = q; - q = r; - } - return p; -} - -// return a gmp_randstate_t structure -gmp_randstate_t* getRandstate() { - static gmp_randstate_t rstate; - static bool initialized = false; - if (!initialized) { - gmp_randinit(rstate, GMP_RAND_ALG_DEFAULT, 32L); - initialized = true; - } - return &rstate; -} - -// char* core_itoa(int n, char* buffer) -// returns a pointer to the null-terminated string in buffer -// NOTES: -// 0. Buffer size should be 17 bytes (resp., 33 bytes, 65 bytes) on 16-bit -// (resp., 32-bit, 64-bit) machines. Formula: 1+sizeof(int)*8 bytes. -// 1. itoa(...) is available on some stdlib.h, but it is -// not defined by ANSI-C and so not all compilers support it. -// 2. Our use of sprintf(...) to do the job is known to -// be inefficient, but this is hardly critical for our usage. -// 3. A more general program should take a 3rd argument (the radix of -// output number). We assume radix 10. -char * core_itoa(int n, char* buffer) { - std::sprintf(buffer, "%d", n); - return buffer; -} - -/// implements the "integer mantissa" function -// (See CORE_PATH/progs/ieee/frexp.cpp for details) -double IntMantissa(double d) { - int e; - return std::ldexp(std::frexp(d, &e), 53); -} - -/// implements the "integer exponent" function -// (See CORE_PATH/progs/ieee/frexp.cpp for details) -int IntExponent(double d) { - int e; - std::frexp(d, &e); - return e-53; -} - -/// CORE_DIAGFILE is file name for core_error(..) output. -const char* CORE_DIAGFILE = "Core_Diagnostics"; // global file name - -/// core_error is the method to write Core Library warning or error messages -/** Both warnings and errors are written to a file called CORE_DIAGFILE. - * But errors are also written on std:cerr (similar to std::perror()). - * */ -// Usage: core_error(message, file_with_error, line_number, err_type) -// where err_type=0 means WARNING, error_type=0 means ERROR -void core_error(std::string msg, std::string file, int lineno, bool err) { - std::ofstream outFile(CORE_DIAGFILE, std::ios::app); // open to append - if (!outFile) { - // perror("CORE ERROR: cannot open Core Diagnostics file"); - std::cerr << "CORE ERROR: can't open Core Diagnostics file"< +#include +#endif diff --git a/CGAL_Core/src/CGAL_Core/CoreIO.cpp b/CGAL_Core/src/CGAL_Core/CoreIO.cpp index c64e41d8dc6..b63e8ae7e02 100644 --- a/CGAL_Core/src/CGAL_Core/CoreIO.cpp +++ b/CGAL_Core/src/CGAL_Core/CoreIO.cpp @@ -29,430 +29,6 @@ * $Id$ ***************************************************************************/ -#include -#include - -namespace CORE { - -void core_io_error_handler(const char *f, const char *m) { - std::cout << "\n error_handler"; - std::cout << "::" << f << "::" << m << "\n"; - std::cout.flush(); - std::abort(); -} - -void core_io_memory_handler(char *t, const char *f, const char *m) { - if (t == NULL) { - std::cout << "\n memory_handler"; - std::cout << "::" << f << "::" << m; - std::cout << "memory exhausted\n"; - std::cout.flush(); - std::abort(); - } -} - -// s has size old_size and will be resized to new_size. -void allocate (char * &s, int old_size, int new_size) { - if (old_size > new_size) - old_size = new_size; - - if (s == NULL) - old_size = 0; - - char *t = new char[new_size]; - core_io_memory_handler(t, "CoreIO", "allocate::out of memory error"); - - int i; - for (i = 0; i < old_size; i++) - t[i] = s[i]; - - delete[] s; - s = t; -} - -// appends c to s at position pos. -// sz is the size of s -void append_char (char * &s, int & sz, int pos, char c) { - if (pos > sz) - core_io_error_handler("CoreIO", "append_char::invalid argument"); - - if (pos == sz) { - allocate(s, sz, 2*sz); - sz *= 2; - } - - s[pos] = c; -} - -// skip blanks, tabs, line breaks and comment lines -int skip_comment_line (std::istream & in) { - int c; - - do { - c = in.get(); - while ( c == '#' ) { - do { - c = in.get(); - } while ( c != '\n' ); - c = in.get(); - } - } while (c == ' ' || c == '\t' || c == '\n'); - - if (c == EOF) - core_io_error_handler("CoreIO::read_from_file()","unexpected end of file."); - - in.putback(c); - return c; -} - -// skips '\\' followed by '\n' -int skip_backslash_new_line (std::istream & in) { - int c = in.get(); - - while (c == '\\') { - c = in.get(); - - if (c == '\n') - c = in.get(); - else - core_io_error_handler("CoreIO::operator>>", "\\ must be immediately followed by new line."); - } - - return c; -} - -void read_string(std::istream& in, char* &buffer, int sz) { - int c, pos=0; - skip_comment_line(in); - - while ( (c = in.get()) != EOF ) { - if ( c == ' ' || c == '\t' || c == '\n' || c == '#') - break; - else - append_char(buffer, sz, pos++, c); - } - append_char(buffer, sz, pos, '\0'); -} - -void read_base_number(std::istream& in, BigInt& m, long length, long maxBits) { - char *buffer; - int size, offset; - int base; - bool is_negate; - - int c, pos = 0; - skip_comment_line(in); - - // read sign - c = in.get(); - if (c == '-') { - is_negate = true; - c = in.get(); - } else - is_negate = false; - - // read base and compute digits - if (c == '0') { - c = in.get(); - if (c == 'b') { - base = 2; - size = (maxBits == 0 || maxBits > length) ? length : maxBits; - offset = length - size; - } else if (c == 'x') { - base = 16; - size = (maxBits == 0) ? length : (maxBits+3) >> 2; - size = (size > length) ? length : size; - offset = (length - size) << 2; - } else { - base = 8; - size = (maxBits == 0) ? length : (maxBits+2) / 3; - size = (size > length) ? length : size; - offset = (length - size) * 3; - in.putback(c); - } - } else { - base = 10; - size = (maxBits == 0) ? length : (int)std::ceil(maxBits*std::log(2.0)/std::log(10.0)); - size = (size > length) ? length : size; - offset = length - size; - in.putback(c); - } - - buffer = new char[size+2]; - // read digits - for (int i=0; (i 0 && base != 10) { - m <<= offset; - } - - if (is_negate) - negate(m); -} - - -void write_base_number(std::ostream& out, char* buffer, int length, int base, int charsPerLine) { - // write big number in a format that gmp's mpz_set_str() can - // automatically recognize with argument base = 0. - if (base == 2) - out << "0b"; - else if (base == 16) - out << "0x"; - else if (base == 8) - out << '0'; - - // write big number in charsPerLine. - char* start, *end, c; - for (int i=0; i= length) - out << start; - else { - end = start + charsPerLine; - c = *end; - *end = '\0'; - - out << start << "\\\n"; - *end = c; - } - } -} - -void readFromFile(BigInt& z, std::istream& in, long maxLength) { - char *buffer; - long length; - - // check type name whether it is Integer or not. - buffer = new char[8]; - read_string(in, buffer, sizeof(buffer)); - if ( std::strcmp(buffer, "Integer") != 0) - core_io_error_handler("BigInt::read_from_file()","type name expected."); - delete[] buffer; - - // read the bit length field. - buffer = new char[100]; - read_string(in, buffer, sizeof(buffer)); - length = std::atol(buffer); - delete[] buffer; - - // read bigint - read_base_number(in, z, length, maxLength); -} - -void writeToFile(const BigInt& z, std::ostream& out, int base, int charsPerLine) { - BigInt c = abs(z); - - // get the absoulte value string - char* buffer = new char[mpz_sizeinbase(c.get_mp(), base) + 2]; - mpz_get_str(buffer, base, c.get_mp()); - int length = std::strlen(buffer); - - // write type name of big number and length - //out << "# This is an experimental big number format.\n"; - out << "Integer " << length << "\n"; - - // if bigint is negative, then write an sign '-'. - if ( sign(z) < 0 ) - out << '-'; - - write_base_number(out, buffer, length, base, charsPerLine); - out << "\n"; - delete[] buffer; -} - -void readFromFile(BigFloat& bf, std::istream& in, long maxLength) { - char *buffer; - long length; - long exponent; - BigInt mantissa; - - // check type name whether it is Float - buffer = new char[6]; - read_string(in, buffer, sizeof(buffer)); - if (std::strcmp(buffer, "Float") != 0) - core_io_error_handler("BigFloat::read_from_file()", "type name expected"); - delete[] buffer; - - // read base (default is 16384) - buffer = new char[8]; - read_string(in, buffer, sizeof(buffer)); - if (std::strcmp(buffer, "(16384)") != 0) - core_io_error_handler("BigFloat::read_from_file()", "base expected"); - delete[] buffer; - - // read the bit length field. - buffer = new char[100]; - read_string(in, buffer, sizeof(buffer)); - length = std::atol(buffer); - delete[] buffer; - - // read exponent - buffer = new char[100]; - read_string(in, buffer, sizeof(buffer)); - exponent = std::atol(buffer); - delete[] buffer; - - // read mantissa - read_base_number(in, mantissa, length, maxLength); - - // construct BigFloat - bf = BigFloat(mantissa, 0, exponent); -} - -void writeToFile(const BigFloat& bf, std::ostream& out, int base, int charsPerLine) { - BigInt c(CORE::abs(bf.m())); - - // get the absoulte value string - char* buffer = new char[mpz_sizeinbase(c.get_mp(), base) + 2]; - mpz_get_str(buffer, base, c.get_mp()); - int length = std::strlen(buffer); - - - // write type name, base, length - //out << "# This is an experimental Big Float format." << std::endl; - out << "Float (16384) " << length << std::endl; - // write exponent - out << bf.exp() << std::endl; - - // write mantissa - if ( CORE::sign(bf.m()) < 0 ) - out << '-'; - - write_base_number(out, buffer, length, base, charsPerLine); - out << '\n'; - delete[] buffer; -} - -/* Underconstruction ---- -void BigFloat::read_from_file2(std::istream& in, long maxLength) { - long length = 1024; - char *buffer; - - // check type name whether it is Float - buffer = new char[7]; - BigInt::read_string(in, buffer, sizeof(buffer)); - if (strcmp(buffer, "NFloat") != 0) - core_io_error_handler("BigFloat::read_from_file2()", "type name expected"); - delete[] buffer; - - // read base (default is 16) - buffer = new char[5]; - BigInt::read_string(in, buffer, sizeof(buffer)); - if (strcmp(buffer, "(16)") != 0) - core_io_error_handler("BigFloat::read_from_file2()", "base expected"); - delete[] buffer; - - // read length field - buffer = new char[100]; - BigInt::read_string(in, buffer, sizeof(buffer)); - - // get the length field if it is not null. - if (buffer[0] != '\0') { - length = atol(buffer); - if (maxLength > 0 && length >= maxLength) - length = maxLength; - } - delete[] buffer; - - // read exponent - buffer = new char[100]; - BigInt::read_string(in, buffer, sizeof(buffer)); - long exp16 = atol(buffer); - delete[] buffer; - - // read mantissa - buffer = new char[length+2]; - //BigInt::read_base_number(in, buffer, length); - - BigInt m16(buffer); - delete[] buffer; - - // convert to base CHUNK_BIT - exp16 = exp16 - length + 1; - if ( m16.is_negative() ) - exp16 ++; - - long tmp_exp = exp16 * 4; - long q = tmp_exp / CHUNK_BIT; - long r = tmp_exp % CHUNK_BIT; - if ( r < 0 ) { - r += CHUNK_BIT; - q --; - } - - BigInt mantissa = m16 << r; - long exponent = q; - - // construct BigFloat - if (--rep->refCount == 0) - delete rep; - - rep = new BigFloatRep(mantissa, 0, exponent); - rep->refCount++; - -} - -// write normal float -// now it assumed to write in hex base, i.e. B=2^4=16 -// (note: our default base B=2^(CHUNK_BIT)=2^14=16384 -void BigFloat::write_to_file2(std::ostream& out, int base, int charsPerLine) { - // convert to base 16. - long new_base = 4; // 2^4 = 16 - long tmp_exp = (rep->exp) * CHUNK_BIT; - long q = tmp_exp / new_base; - long r = tmp_exp % new_base; - std::cout << "CORE_DEBUG: q=" << q << ", r=" << r << std::endl; - if ( r < 0 ) { - r += new_base; - q--; - } - std::cout << "CORE_DEBUG: q=" << q << ", r=" << r << std::endl; - - BigInt m16 = (rep->m) << r; - - int size = mpz_sizeinbase(m16.I, base) + 2; - std::cout << "size=" << size << std::endl; - char* buffer = new char[size]; - - int length = bigint_to_string(m16, buffer, base); - std::cout << "length=" << length << std::endl; - - long exp16 = q + length - 1; - if ( m16.is_negative() ) - exp16 --; - - // write type name, base, length - out << "# This is an experimental Big Float format." << std::endl; - out << "NFloat (16) " << length << std::endl; - - // write exponent - out << exp16 << std::endl; - - // write mantissa - if ( m16.is_negative() ) { - out << '-'; - buffer ++; - } - - BigInt::write_base_number(out, buffer, length, base, charsPerLine); - out << '\n'; - delete[] buffer; -} -*/ - -} //namespace CORE - +#ifndef CGAL_HEADER_ONLY +#include +#endif diff --git a/CGAL_Core/src/CGAL_Core/Expr.cpp b/CGAL_Core/src/CGAL_Core/Expr.cpp index 3eeba25b86b..0bb43159505 100644 --- a/CGAL_Core/src/CGAL_Core/Expr.cpp +++ b/CGAL_Core/src/CGAL_Core/Expr.cpp @@ -34,1119 +34,9 @@ * $Id$ ***************************************************************************/ +#ifndef CGAL_HEADER_ONLY + #include -#include +#include -namespace CORE { - -#ifdef CORE_DEBUG_BOUND -unsigned int BFMSS_counter = 0; -unsigned int BFMSS_only_counter = 0; -unsigned int Measure_counter = 0; -unsigned int Measure_only_counter = 0; -unsigned int Cauchy_counter = 0; -unsigned int Cauchy_only_counter = 0; -unsigned int LiYap_counter = 0; -unsigned int LiYap_only_counter = 0; -unsigned int rootBoundHitCounter = 0; -unsigned int computeBoundCallsCounter = 0; #endif - -const char* Add::name = "+"; -const char* Sub::name = "-"; - -/******************************************************** - * class Expr - ********************************************************/ -const Expr& Expr::getZero() { - static Expr Zero(0); - return Zero; -} -const Expr& Expr::getOne() { - static Expr One(1); - return One; -} - -// computes an interval comprising a pair of doubles -// Note: -// -// This function returns are two consecutive representable binary -// IEEE double values whichs contain the real value, but when you print out -// them, you might be confused by the decimal represention due to round. -// -void Expr::doubleInterval(double & lb, double & ub) const { - double d = doubleValue(); - if (! CGAL_CORE_finite(d)) { // if overflow, underflow or NaN - lb = ub = d; - return; - } - int sign = ((* this) -Expr(d)).sign(); - // Seems like doubleValue() always give a lower bound, - // so sign = 0 or 1 (never -1). - //std::cout << "Sign = " << sign << std::endl; - if (sign == 0) { - lb = ub = d; - return; - } - int exp; - frexp(d, & exp); // get the exponent of d - exp--; // the exp from frexp satisfies - // 2^{exp-1} <= d < 2^{exp} - // But, we want exp to satisfy - // 2^{exp} <= d < 2^{exp+1} - if (sign > 0) { - lb = d; - ub = d + ldexp(1.0, -52+exp); - return; - } else { - ub = d; - lb = d - ldexp(1.0, -52+exp); - return; - } -} - -// floor(e, sub) returns the floor(e), and puts the -// remainder into sub. -BigInt floor(const Expr& e, Expr &sub) { - if (e==0) { - return 0; - } - BigInt f = e.approx(CORE_INFTY, 2).BigIntValue(); - sub = e-f; - // Adjustment - if (sub<0) - ++sub, --f; - if (sub>=1) - --sub, ++f; - assert(sub >=0 && sub<1); // got an assertion error? (Chee 3/24/04) - return f; -} - -// Chenli: implemented algorithm from Goldberg's article. -// 7/01: Thanks to Serge Pashkov for fixing infinite loop when n=0. -Expr pow(const Expr& e, unsigned long n) { - if (n == 0) - return Expr(1); - else if (n == 1) - return e; - else { - Expr x = e; - while ((n % 2) == 0) { // n is even - x *= x; - n >>= 1; - } - Expr u = x; - while (true) { - n >>= 1; - if (n == 0) - return u; - x *= x; - if ((n % 2) == 1) // n is odd - u *= x; - } - //return u; // unreachable - } -}//pow - -NodeInfo::NodeInfo() : appValue(CORE_REAL_ZERO), appComputed(false), - flagsComputed(false), knownPrecision(CORE_negInfty), -#ifdef CORE_DEBUG - relPrecision(EXTLONG_ZERO), absPrecision(CORE_negInfty), numNodes(0), -#endif - // Most of the following data members don't need to be - // initialized here. - d_e(EXTLONG_ZERO), visited(false), sign(0), - uMSB(CORE_negInfty), lMSB(CORE_negInfty), - // length(0), - measure(EXTLONG_ZERO), high(EXTLONG_ZERO), low(EXTLONG_ONE), - lc(EXTLONG_ZERO), tc(EXTLONG_ZERO), - v2p(EXTLONG_ZERO), v2m(EXTLONG_ZERO), - v5p(EXTLONG_ZERO), v5m(EXTLONG_ZERO), - u25(EXTLONG_ZERO), l25(EXTLONG_ZERO), - ratFlag(0), ratValue(NULL) { } - -/******************************************************** - * class ExprRep - ********************************************************/ -// constructor -ExprRep::ExprRep() : refCount(1), nodeInfo(NULL), ffVal(0.0) { } - -// Computes the root bit bound of the expression. -// In effect, computeBound() returns the current value of low. -extLong ExprRep::computeBound() { - extLong measureBd = measure(); - // extLong cauchyBd = length(); - extLong ourBd = (d_e() - EXTLONG_ONE) * high() + lc(); - // BFMSS[2,5] bound. - extLong bfmsskBd; - if (v2p().isInfty() || v2m().isInfty()) - bfmsskBd = CORE_INFTY; - else - bfmsskBd = l25() + u25() * (d_e() - EXTLONG_ONE) - v2() - ceilLg5(v5()); - - // since we might compute \infty - \infty for this bound - if (bfmsskBd.isNaN()) - bfmsskBd = CORE_INFTY; - - extLong bd = core_min(measureBd, - // core_min(cauchyBd, - core_min(bfmsskBd, ourBd)); -#ifdef CORE_SHOW_BOUNDS - std::cout << "Bounds (" << measureBd << - "," << bfmsskBd << ", " << ourBd << "), "; - std::cout << "MIN = " << bd << std::endl; - std::cout << "d_e= " << d_e() << std::endl; -#endif - -#ifdef CORE_DEBUG_BOUND - // Some statistics about which one is/are the winner[s]. - computeBoundCallsCounter++; - int number_of_winners = 0; - std::cerr << " New contest " << std::endl; - if (bd == bfmsskBd) { - BFMSS_counter++; - number_of_winners++; - std::cerr << " BFMSS is the winner " << std::endl; - } - if (bd == measureBd) { - Measure_counter++; - number_of_winners++; - std::cerr << " measureBd is the winner " << std::endl; - } - /* if (bd == cauchyBd) { - Cauchy_counter++; - number_of_winners++; - std::cerr << " cauchyBd is the winner " << std::endl; - } - */ - if (bd == ourBd) { - LiYap_counter++; - number_of_winners++; - std::cerr << " ourBd is the winner " << std::endl; - } - - assert(number_of_winners >= 1); - - if (number_of_winners == 1) { - if (bd == bfmsskBd) { - BFMSS_only_counter++; - std::cerr << " BFMSSBd is the only winner " << std::endl; - } else if (bd == measureBd) { - Measure_only_counter++; - std::cerr << " measureBd is the only winner " << std::endl; - } - /* else if (bd == cauchyBd) { - Cauchy_only_counter++; - std::cerr << " cauchyBd is the only winner " << std::endl; - } */ - else if (bd == ourBd) { - LiYap_only_counter++; - std::cerr << " ourBd is the only winner " << std::endl; - } - } -#endif - - return bd; -}//computeBound() - -void ExprRep::reduceToBigRat(const BigRat& rat) { - Real value(rat); - - //appValue() = value; - appComputed() = false; // since appValue is not assigned until approx() is called - flagsComputed() = true; - knownPrecision() = CORE_negInfty; - -#ifdef CORE_DEBUG - relPrecision() = EXTLONG_ZERO; - absPrecision() = CORE_negInfty; - //numNodes() = numNodes(); -#endif - - d_e() = EXTLONG_ONE; - //visited() = e->visited(); - sign() = value.sign(); - uMSB() = value.MSB(); - lMSB() = value.MSB(); - // length() = value.length(); // fixed? original = 1 - measure() = value.height(); // measure <= height for rational value - - // BFMSS[2,5] bound. - value.ULV_E(u25(), l25(), v2p(), v2m(), v5p(), v5m()); - - extLong u_e = u25() + v2p(); - extLong l_e = l25() + v2m(); - - u_e = u_e + ceilLg5(v5p()); - l_e = l_e + ceilLg5(v5m()); - - if (l_e == EXTLONG_ZERO) { // no divisions introduced - high() = u_e; - low() = EXTLONG_ONE - u_e; // - (u_e - 1) - } else { - high() = u_e - l_e + EXTLONG_ONE; - low() = 2 - high(); - } - - lc() = l_e; - tc() = u_e; - - if (ratValue() == NULL) - ratValue() = new BigRat(rat); - else - *(ratValue()) = rat; -} - -// This only copies the current information of the argument e to -// *this ExprRep. -void ExprRep::reduceTo(const ExprRep *e) { - if (e->appComputed()) { - appValue() = e->appValue(); - appComputed() = true; - flagsComputed() = true; - knownPrecision() = e->knownPrecision(); -#ifdef CORE_DEBUG - relPrecision() = e->relPrecision(); - absPrecision() = e->absPrecision(); - numNodes() = e->numNodes(); -#endif - - } - d_e() = e->d_e(); - //visited() = e->visited(); - sign() = e->sign(); - uMSB() = e->uMSB(); - lMSB() = e->lMSB(); - // length() = e->length(); // fixed? original = 1 - measure() = e->measure(); - - // BFMSS[2,5] bound. - u25() = e->u25(); - l25() = e->l25(); - v2p() = e->v2p(); - v2m() = e->v2m(); - v5p() = e->v5p(); - v5m() = e->v5m(); - - high() = e->high(); - low() = e->low(); // fixed? original = 0 - lc() = e->lc(); - tc() = e->tc(); - - // Chee (Mar 23, 2004), Notes on ratFlag(): - // =============================================================== - // For more information on the use of this flag, see progs/pentagon. - // This is an integer valued member of the NodeInfo class. - // Its value is used to determine whether - // we can ``reduce'' an Expression to a single node containing - // a BigRat value. This reduction is done if the global variable - // rationalReduceFlag=true. The default value is false. - // This is the intepretation of ratFlag: - // ratFlag < 0 means irrational - // ratFlag = 0 means not initialized - // ratFlag > 0 means rational - // Currently, ratFlag>0 is an upper bound on the size of the expression, - // since we recursively compute - // ratFlag(v) = ratFlag(v.lchild)+ratFlag(v.rchild) + 1. - // PROPOSAL: if ratFlag() > RAT_REDUCE_THRESHHOLD - // then we automatically do a reduction. We must determine - // an empirical value for RAT_REDUCE_THRESHOLD - - if (rationalReduceFlag) { - ratFlag() = e->ratFlag(); - - if (e->ratFlag() > 0 && e->ratValue() != NULL) { - ratFlag() ++; - if (ratValue() == NULL) - ratValue() = new BigRat(*(e->ratValue())); - else - *(ratValue()) = *(e->ratValue()); - } else - ratFlag() = -1; - } -} - -void ExprRep::reduceToZero() { - appValue() = CORE_REAL_ZERO; - appComputed() = true; - flagsComputed() = true; - knownPrecision() = CORE_negInfty; -#ifdef CORE_DEBUG - relPrecision() = EXTLONG_ZERO; - absPrecision() = CORE_negInfty; - // numNodes() = 0; -#endif - - d_e() = EXTLONG_ONE; - visited() = false; - sign() = 0; - uMSB() = CORE_negInfty; - lMSB() = CORE_negInfty; - // length() = 0; // fixed? original = 1 - measure() = EXTLONG_ZERO; - - // BFMSS[2,5] bound. - u25() = l25() = v2p() = v2m() = v5p() = v5m() = EXTLONG_ZERO; - - low() = EXTLONG_ONE; // fixed? original = 0 - high() = lc() = tc() = EXTLONG_ZERO; - - if (rationalReduceFlag) { - if (ratFlag() > 0) { - ratFlag() ++; - if (ratValue() == NULL) - ratValue() = new BigRat(0); - else - *(ratValue()) = 0; - } else - ratFlag() = 1; - } -} - -//////////////////////////////////////////////////////////// -// Test whether the current approximate value satisfies -// the composite precision requirements [relPrec, absPrec]. -//////////////////////////////////////////////////////////// - -bool ExprRep::withinKnownPrecision(const extLong& relPrec, - const extLong& absPrec) { - if (appComputed()) { // an approximate value has been evaluated. - if (appValue().isExact()) { - return true; - } else { // approximation has certain error. - // decide to which position it is required to compute correctly. - extLong required = core_max(-absPrec, appValue().lMSB()-relPrec); - // see whether the existing error is smaller than the requirement. - return (knownPrecision() <= required); - } - } else - return false; -}//withinKnownPrecision(a, r) - -// approximate the expression to certain precisions when -// necessary (either no approximate value available or -// the existing one is not accurate enough). -void ExprRep::approx(const extLong& relPrec = defRelPrec, - const extLong& absPrec = defAbsPrec) { - if (!getSign()) - return; // if it is exactly zero... - - // NOTE: The Filter might give a precise enough approximation already. - if (!getExactSign()) - return; - - if (!appComputed() || (!withinKnownPrecision(relPrec, absPrec))) { - // it's necessary to re-evaluate. - // to avoid huge lMSB which would cause long time and problems. - - // if it is a rational node - if (rationalReduceFlag && ratFlag() > 0 && ratValue() != NULL) - appValue() = Real(*(ratValue())).approx(relPrec, absPrec); //< shouldn't - // this case be done by computeApproxValue()? - else - computeApproxValue(relPrec, absPrec); - - // update flags - appComputed() = true; - knownPrecision() = appValue().clLgErr(); -#ifdef CORE_DEBUG - if (relPrecision() < relPrec) - relPrecision() = relPrec; - if (absPrecision() < absPrec) - absPrecision() = absPrec; -#endif - - } -} - -// return an approximate value to certain precision. -const Real& ExprRep::getAppValue(const extLong& relPrec, - const extLong& absPrec) { - if (getSign()) { - approx(relPrec, absPrec); - return appValue(); - } else - return CORE_REAL_ZERO; -} - -std::ostream& operator<<(std::ostream& o, ExprRep& rep) { - if (rep.getSign()) { - rep.approx(defRelPrec, defAbsPrec); - o << rep.appValue(); - } else { - o << "0"; - } - return o; -} - -// Chee, Zilin: July 17, 2002 -// Original algorithm is wrongly implemented, and can take time -// exponential in the size of the dag. -// -// METHOD: -// Inductively assume that all "visited" flags are false. -// This calls for a reimplementation of "count()" and "clearFlag()". -// Actually, we did not have to fix the count() function. -// -// (1) First recursively compute d_e for each node -// by calling the count() function. -// Important thing is count() will turn the "visited" flags -// to be true, so that there is no double counting. -// Furthermore, if d_e had already been computed, the -// arithmetic for d_e can be avoided (in this case, -// it is only the setting of "visited" flag that we -// are interested in! -// (2) At the end of count(), we have set all reachable nodes -// to "visited", and their d_e have been computed. -// (3) Now, call clearFlag() to recursively clear all reachable -// nodes. NOTE THAT PREVIOUSLY, clearFlag() was called -// first! This obvious is wrong - -extLong ExprRep::degreeBound() { - if (d_e() == EXTLONG_ONE) // no radical nodes below - return EXTLONG_ONE; - count(); - clearFlag(); - return d_e(); -} -// class ConstRealRep -// constructor -ConstRealRep::ConstRealRep(const Real & r) : value(r) { - if (!value.isExact()) { - // clone the BigFloat and set its error to zero. - value = value.BigFloatValue().makeExact(); - } - ffVal = filteredFp(value); -} - -// initialize nodeInfo -void ConstRep::initNodeInfo() { - nodeInfo = new NodeInfo(); - d_e() = EXTLONG_ONE; -} -void UnaryOpRep::initNodeInfo() { - if (child->nodeInfo == NULL) - child->initNodeInfo(); - nodeInfo = new NodeInfo(); -} -void BinOpRep::initNodeInfo() { - if (first->nodeInfo == NULL) - first->initNodeInfo(); - if (second->nodeInfo == NULL) - second->initNodeInfo(); - nodeInfo = new NodeInfo(); -} - -#ifdef CORE_DEBUG -unsigned long ConstRep::dagSize() { - if (!visited()) { - visited() = true; - numNodes() = 1; - } else - numNodes() = 0; - return numNodes(); -} - -unsigned long UnaryOpRep::dagSize() { - if (!visited()) { - visited() = true; - numNodes() = child->dagSize() + 1; - } else - numNodes() = 0; - return numNodes(); -} - -unsigned long BinOpRep::dagSize() { - if (!visited()) { - visited() = true; - numNodes() = first->dagSize() + second->dagSize() + 1; - } else - numNodes() = 0; - return numNodes(); -} - -void ConstRep::fullClearFlag() { - if (visited()) - visited() = false; -} - -void UnaryOpRep::fullClearFlag() { - if (visited()) { - child->fullClearFlag(); - visited() = false; - } -} - -void BinOpRep::fullClearFlag() { - if (visited()) { - first->fullClearFlag(); - second->fullClearFlag(); - visited() = false; - } -} -#endif - -// -// clear visited flag -// -/* see Expr.h - void ConstRep::clearFlag() - { visited = false; } -*/ -void UnaryOpRep::clearFlag() { - if (d_e() == EXTLONG_ONE) - return; // no radicals below. - if (visited()) { - visited() = false; - child->clearFlag(); - } -} -// class BinOpRep -void BinOpRep::clearFlag() { - if (d_e() == EXTLONG_ONE) - return; // rational below - if (visited()) { - visited() = false; - first->clearFlag(); - second->clearFlag(); - } -} - -// -// count # of squareroot -// -extLong ConstRep::count() { - if (visited()) - return EXTLONG_ONE; - visited() = true; - return d_e(); -} - -extLong NegRep::count() { - if (d_e() == EXTLONG_ONE) - return EXTLONG_ONE; - if (visited()) - return EXTLONG_ONE; - visited() = true; - d_e() = child->count(); - return d_e(); -} - -extLong SqrtRep::count() { - if (d_e() == EXTLONG_ONE) - return EXTLONG_ONE; - if (visited()) - return EXTLONG_ONE; - visited() = true; - d_e() = child->count() * EXTLONG_TWO; - return d_e(); -} - -extLong BinOpRep::count() { - if (d_e() == EXTLONG_ONE) - return EXTLONG_ONE; - if (visited()) - return EXTLONG_ONE; - visited() = true; - d_e() = first->count() * second->count(); - return d_e(); -} - -// -// compute exact flags functions -// -// exact value - -void computeExactFlags_temp(ConstRep* t, const Real &value) { - // Chen Li: the following is incorrect: - // uMSB = lMSB = value.MSB(); - // because the value could be a BigFloat which is an interval. - if (value.isExact()) { - t->uMSB() = t->lMSB() = value.MSB(); - } else { - t->uMSB() = value.uMSB(); - t->lMSB() = value.lMSB(); - core_error("Leaves in DAG is not exact!", __FILE__, __LINE__, true); - } - - t->sign() = value.sign(); - // t->length() = value.length(); - t->measure() = value.height(); // for rationals and integers, - // measure = height. - - // BFMSS[2,5] bound. - value.ULV_E(t->u25(), t->l25(), t->v2p(), t->v2m(), t->v5p(), t->v5m()); - - // The original BFMSS parameters can be set from the BFMSS[2,5] parameters. - // Here we just need them locally. - extLong u_e = t->u25() + t->v2p() + ceilLg5(t->v5p()); - extLong l_e = t->l25() + t->v2m() + ceilLg5(t->v5m()); - -#ifdef ORIGINAL_BFMSS - // To go back to the original BFMSS : - t->u25() = u_e; - t->l25() = l_e; - t->v2p() = t->v2m() = t->v5p() = t->v5m() = EXTLONG_ZERO; -#elif defined BFMSS_2_ONLY - // To go back to BFMSS[2] only : - t->u25() = t->u25() + ceilLg5(t->v5p()); - t->l25() = t->l25() + ceilLg5(t->v5m()); - t->v5p() = t->v5m() = EXTLONG_ZERO; -#endif - - if (l_e == EXTLONG_ZERO) { // no divisions introduced - t->high() = u_e; - t->low() = EXTLONG_ONE - u_e; // - (u_e - 1) - } else { - t->high() = u_e - l_e + EXTLONG_ONE; - t->low() = EXTLONG_TWO - t->high(); - } - - t->lc() = l_e; - t->tc() = u_e; - - // set BigRat value - if (rationalReduceFlag) { - t->ratFlag() = 1; - t->ratValue() = new BigRat(value.BigRatValue()); - } - - t->flagsComputed() = true; -} - -void ConstDoubleRep::computeExactFlags() {// can be made more efficient - computeExactFlags_temp(this, Real(ffVal.getValue())); -} - -void ConstRealRep::computeExactFlags() { - computeExactFlags_temp(this, value); -} - -void NegRep::computeExactFlags() { - if (!child->flagsComputed()) - child->computeExactFlags(); - - if (child->sign() == 0) { - reduceToZero(); - return; - } - - if (rationalReduceFlag) { - if (child->ratFlag()>0 && child->ratValue() != NULL) { - BigRat val = -(*(child->ratValue())); - reduceToBigRat(val); - ratFlag() = child->ratFlag()+1; - return; - } else - ratFlag() = -1; - } - - sign() = -child->sign(); - uMSB() = child->uMSB(); - lMSB() = child->lMSB(); - - // length() = child->length(); - measure() = child->measure(); - u25() = child->u25(); - l25() = child->l25(); - v2p() = child->v2p(); - v2m() = child->v2m(); - v5p() = child->v5p(); - v5m() = child->v5m(); - high() = child->high(); - low() = child->low(); - lc() = child->lc(); - tc() = child->tc(); - flagsComputed() = true; -}//NegRep::computeExactFlags - -void SqrtRep::computeExactFlags() { - if (!child->flagsComputed()) - child->computeExactFlags(); - - if (rationalReduceFlag) - ratFlag() = -1; - - sign() = child->sign(); - if (sign() < 0) - core_error("squareroot is called with negative operand.", - __FILE__, __LINE__, true); - - uMSB() = child->uMSB() / EXTLONG_TWO; - lMSB() = child->lMSB() / EXTLONG_TWO; - - // length() = child->length(); - measure() = child->measure(); - - // BFMSS[2,5] bound. - if (child->v2p() + ceilLg5(child->v5p()) + child->u25() >= - child->v2m() + ceilLg5(child->v5m()) + child->l25()) { - extLong vtilda2 = child->v2p() + child->v2m(); - v2p() = vtilda2 / EXTLONG_TWO; - v2m() = child->v2m(); - extLong vmod2; - if (v2p().isInfty()) - vmod2 = CORE_INFTY; - else - vmod2 = vtilda2 - EXTLONG_TWO*v2p(); // == vtilda2 % 2 - extLong vtilda5 = child->v5p() + child->v5m(); - v5p() = vtilda5 / EXTLONG_TWO; - v5m() = child->v5m(); - extLong vmod5; - if (v5p().isInfty()) - vmod5 = CORE_INFTY; - else - vmod5 = vtilda5 - EXTLONG_TWO*v5p(); // == vtilda5 % 2 - u25() = (child->u25() + child->l25() + vmod2 + ceilLg5(vmod5) + EXTLONG_ONE) / EXTLONG_TWO; - l25() = child->l25(); - } else { - extLong vtilda2 = child->v2p() + child->v2m(); - v2p() = child->v2p(); - v2m() = vtilda2 / EXTLONG_TWO; - extLong vmod2; - if (v2m().isInfty()) - vmod2 = CORE_INFTY; - else - vmod2 = vtilda2 - EXTLONG_TWO*v2m(); // == vtilda2 % 2 - extLong vtilda5 = child->v5p() + child->v5m(); - v5p() = child->v5p(); - v5m() = vtilda5 / EXTLONG_TWO; - u25() = child->u25(); - extLong vmod5; - if (v5m().isInfty()) - vmod5 = CORE_INFTY; - else - vmod5 = vtilda5 - EXTLONG_TWO*v5m(); // == vtilda5 % 2 - l25() = (child->u25() + child->l25() + vmod2 + ceilLg5(vmod5) + EXTLONG_ONE) / EXTLONG_TWO; - } - - high() = (child->high() +EXTLONG_ONE)/EXTLONG_TWO; - low() = child->low() / EXTLONG_TWO; - lc() = child->lc(); - tc() = child->tc(); - flagsComputed() = true; -}// SqrtRep::computeExactFlags - -void MultRep::computeExactFlags() { - if (!first->flagsComputed()) - first->computeExactFlags(); - if (!second->flagsComputed()) - second->computeExactFlags(); - - if ((!first->sign()) || (!second->sign())) { - // value must be exactly zero. - reduceToZero(); - return; - } - // rational node - if (rationalReduceFlag) { - if (first->ratFlag() > 0 && second->ratFlag() > 0) { - BigRat val = (*(first->ratValue()))*(*(second->ratValue())); - reduceToBigRat(val); - ratFlag() = first->ratFlag() + second->ratFlag(); - return; - } else - ratFlag() = -1; - } - - // value is irrational. - uMSB() = first->uMSB() + second->uMSB() + EXTLONG_ONE; - lMSB() = first->lMSB() + second->lMSB(); - sign() = first->sign() * second->sign(); - - extLong df = first->d_e(); - extLong ds = second->d_e(); - // extLong lf = first->length(); - // extLong ls = second->length(); - - // length() = df * ls + ds * lf; - measure() = (first->measure()) * ds+(second->measure()) * df; - - // BFMSS[2,5] bound. - v2p() = first->v2p() + second->v2p(); - v2m() = first->v2m() + second->v2m(); - v5p() = first->v5p() + second->v5p(); - v5m() = first->v5m() + second->v5m(); - u25() = first->u25() + second->u25(); - l25() = first->l25() + second->l25(); - - high() = first->high() + second->high(); - low() = first->low() + second->low(); - - lc() = ds * first->lc() + df * second->lc(); - tc() = core_min(ds * first->tc() + df * second->tc(), measure()); - - flagsComputed() = true; -}// MultRep::computeExactFlags - -void DivRep::computeExactFlags() { - if (!first->flagsComputed()) - first->computeExactFlags(); - if (!second->flagsComputed()) - second->computeExactFlags(); - - if (!second->sign()) - core_error("zero divisor.", __FILE__, __LINE__, true); - - if (!first->sign()) {// value must be exactly zero. - reduceToZero(); - return; - } - - // rational node - if (rationalReduceFlag) { - if (first->ratFlag() > 0 && second->ratFlag() > 0) { - BigRat val = (*(first->ratValue()))/(*(second->ratValue())); - reduceToBigRat(val); - ratFlag() = first->ratFlag() + second->ratFlag(); - return; - } else - ratFlag() = -1; - } - - // value is irrational. - uMSB() = first->uMSB() - second->lMSB(); - lMSB() = first->lMSB() - second->uMSB() - EXTLONG_ONE; - sign() = first->sign() * second->sign(); - - extLong df = first->d_e(); - extLong ds = second->d_e(); - // extLong lf = first->length(); - // extLong ls = second->length(); - - // length() = df * ls + ds * lf; - measure() = (first->measure())*ds + (second->measure())*df; - - // BFMSS[2,5] bound. - v2p() = first->v2p() + second->v2m(); - v2m() = first->v2m() + second->v2p(); - v5p() = first->v5p() + second->v5m(); - v5m() = first->v5m() + second->v5p(); - u25() = first->u25() + second->l25(); - l25() = first->l25() + second->u25(); - - high() = first->high() + second->low(); - low() = first->low() + second->high(); - - lc() = ds * first->lc() + df * second->tc(); - tc() = core_min(ds * first->tc() + df * second->lc(), measure()); - - flagsComputed() = true; -} - -// -// approximation functions -// -void ConstDoubleRep::computeApproxValue(const extLong& /*relPrec*/, - const extLong& /*absPrec*/) -// can ignore precision bounds since ffVal.getValue() returns exact value -{ - appValue() = Real(ffVal.getValue()); -} - -void ConstRealRep::computeApproxValue(const extLong& relPrec, - const extLong& absPrec) { - appValue() = value.approx(relPrec, absPrec); -} - -void NegRep::computeApproxValue(const extLong& relPrec, - const extLong& absPrec) { - appValue() = -child->getAppValue(relPrec, absPrec); -} - -void SqrtRep::computeApproxValue(const extLong& relPrec, - const extLong& absPrec) { - extLong r = relPrec + relPrec + EXTLONG_EIGHT; // chenli: ??? - extLong a = absPrec + absPrec + EXTLONG_EIGHT; - extLong pr = - lMSB() + r; - extLong p = pr < a ? pr : a; - - Real val = child->getAppValue(r, a); - if (incrementalEvalFlag) { - if (appValue() == CORE_REAL_ZERO) - appValue() = val; - appValue() = val.sqrt(p, appValue().BigFloatValue()); - } else - appValue() = val.sqrt(p); -} - -void MultRep::computeApproxValue(const extLong& relPrec, - const extLong& absPrec) { - if (lMSB() < EXTLONG_BIG && lMSB() > EXTLONG_SMALL) { - extLong r = relPrec + EXTLONG_FOUR; - extLong afr = - first->lMSB() + EXTLONG_ONE; - extLong afa = second->uMSB() + absPrec + EXTLONG_FIVE; - extLong af = afr > afa ? afr : afa; - extLong asr = - second->lMSB() + EXTLONG_ONE; - extLong asa = first->uMSB() + absPrec + EXTLONG_FIVE; - extLong as = asr > asa ? asr : asa; - appValue() = first->getAppValue(r, af)*second->getAppValue(r, as); - } else { - std::cerr << "lMSB = " << lMSB() << std::endl; - core_error("a huge lMSB in MulRep", __FILE__, __LINE__, false); - } -} - -void DivRep::computeApproxValue(const extLong& relPrec, - const extLong& absPrec) { - if (lMSB() < EXTLONG_BIG && lMSB() > EXTLONG_SMALL) { - extLong rr = relPrec + EXTLONG_SEVEN; // These rules come from - extLong ra = uMSB() + absPrec + EXTLONG_EIGHT; // Koji's Master Thesis, page 65 - extLong ra2 = core_max(ra, EXTLONG_TWO); - extLong r = core_min(rr, ra2); - extLong af = - first->lMSB() + r; - extLong as = - second->lMSB() + r; - - extLong pr = relPrec + EXTLONG_SIX; - extLong pa = uMSB() + absPrec + EXTLONG_SEVEN; - extLong p = core_min(pr, pa); // Seems to be an error: - // p can be negative here! - // Also, this does not conform to - // Koji's thesis which has a default - // relative precision (p.65). - - appValue() = first->getAppValue(r, af).div(second->getAppValue(r, as), p); - } else { - std::cerr << "lMSB = " << lMSB() << std::endl; - core_error("a huge lMSB in DivRep", __FILE__, __LINE__, false); - } -} - -// -// Debug Help Functions -// -void Expr::debug(int mode, int level, int depthLimit) const { - std::cout << "-------- Expr debug() -----------" << std::endl; - std::cout << "rep = " << rep << std::endl; - if (mode == Expr::LIST_MODE) - rep->debugList(level, depthLimit); - else if (mode == Expr::TREE_MODE) - rep->debugTree(level, 0, depthLimit); - else - core_error("unknown debugging mode", __FILE__, __LINE__, false); - std::cout << "---- End Expr debug(): " << std::endl; -} - - -const std::string ExprRep::dump(int level) const { - std::ostringstream ost; - if (level == OPERATOR_ONLY) { - ost << op(); - } else if (level == VALUE_ONLY) { - ost << appValue(); - } else if (level == OPERATOR_VALUE) { - ost << op() << "[val: " << appValue() << "]"; - } else if (level == FULL_DUMP) { - ost << op() - << "[val: " << appValue() << "; " - << "kp: " << knownPrecision() << "; " -#ifdef CORE_DEBUG - << "r: " << relPrecision() << "; " - << "a: " << absPrecision() << "; " -#endif - << "lMSB: " << lMSB() << "; " - << "uMSB: " << uMSB() << "; " - << "sign: " << sign() << "; " - // << "length: " << length() << "; " - << "measure: " << measure() << "; " - << "d_e: " << d_e() << "; " - << "u25: " << u25() << "; " - << "l25: " << l25() << "; " - << "v2p: " << v2p() << "; " - << "v2m: " << v2m() << "; " - << "v5p: " << v5p() << "; " - << "v5m: " << v5m() << "; " - << "high: " << high() << "; " - << "low: " << low() << "; " - << "lc: " << lc() << "; " - << "tc: " << tc() - << "]"; - } - return std::string(ost.str()); - // note that str() return an array not properly terminated! -} - - -void UnaryOpRep::debugList(int level, int depthLimit) const { - if (depthLimit <= 0) - return; - if (level == Expr::SIMPLE_LEVEL) { - std::cout << "(" << dump(OPERATOR_VALUE); - child->debugList(level, depthLimit - 1); - std::cout << ")"; - } else if (level == Expr::DETAIL_LEVEL) { - std::cout << "(" << dump(FULL_DUMP); - child->debugList(level, depthLimit - 1); - std::cout << ")"; - } -} - -void UnaryOpRep::debugTree(int level, int indent, int depthLimit) const { - if (depthLimit <= 0) - return; - for (int i = 0; idebugTree(level, indent + 2, depthLimit - 1); -} - -void ConstRep::debugList(int level, int depthLimit) const { - if (depthLimit <= 0) - return; - if (level == Expr::SIMPLE_LEVEL) { - std::cout << "(" << dump(OPERATOR_VALUE) << ")"; - } else if (level == Expr::DETAIL_LEVEL) { - std::cout << "(" << dump(FULL_DUMP) << ")"; - } -} - -void ConstRep::debugTree(int level, int indent, int depthLimit) const { - if (depthLimit <= 0) - return; - for (int i=0; idebugList(level, depthLimit - 1); - std::cout << ", "; - second->debugList(level, depthLimit - 1); - std::cout << ")" ; -} - -void BinOpRep::debugTree(int level, int indent, int depthLimit) const { - if (depthLimit <= 0) - return; - for (int i=0; idebugTree(level, indent + 2, depthLimit - 1); - second->debugTree(level, indent + 2, depthLimit - 1); -} - -} //namespace CORE diff --git a/CGAL_Core/src/CGAL_Core/GmpIO.cpp b/CGAL_Core/src/CGAL_Core/GmpIO.cpp index 3d665366a08..9b74ba289e7 100644 --- a/CGAL_Core/src/CGAL_Core/GmpIO.cpp +++ b/CGAL_Core/src/CGAL_Core/GmpIO.cpp @@ -12,257 +12,9 @@ * $Id$ ***************************************************************************/ -/* Auxiliary functions for C++-style input of GMP types. - -Copyright 2001 Free Software Foundation, Inc. - -This file is part of the GNU MP Library. - -The GNU MP Library is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 3 of the License, or (at your -option) any later version. - -The GNU MP Library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with the GNU MP Library; see the file COPYING.LIB. If not, write to -the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -MA 02110-1301, USA. */ +#ifndef CGAL_HEADER_ONLY #include -#include -#include -#include -#include +#include -using namespace std; - -namespace CORE { - -int -__gmp_istream_set_base (istream &i, char &c, bool &zero, bool &showbase) -{ - int base; - - zero = showbase = false; - switch (i.flags() & ios::basefield) - { - case ios::dec: - base = 10; - break; - case ios::hex: - base = 16; - break; - case ios::oct: - base = 8; - break; - default: - showbase = true; // look for initial "0" or "0x" or "0X" - if (c == '0') - { - if (! i.get(c)) - c = 0; // reset or we might loop indefinitely - - if (c == 'x' || c == 'X') - { - base = 16; - i.get(c); - } - else - { - base = 8; - zero = true; // if no other digit is read, the "0" counts - } - } - else - base = 10; - break; - } - - return base; -} - -void -__gmp_istream_set_digits (string &s, istream &i, char &c, bool &ok, int base) -{ - switch (base) - { - case 10: - while (isdigit(c)) - { - ok = true; // at least a valid digit was read - s += c; - if (! i.get(c)) - break; - } - break; - case 8: - while (isdigit(c) && c != '8' && c != '9') - { - ok = true; // at least a valid digit was read - s += c; - if (! i.get(c)) - break; - } - break; - case 16: - while (isxdigit(c)) - { - ok = true; // at least a valid digit was read - s += c; - if (! i.get(c)) - break; - } - break; - } -} - -istream & -//operator>> (istream &i, mpz_ptr z) -io_read (istream &i, mpz_ptr z) -{ - int base; - char c = 0; - string s; - bool ok = false, zero, showbase; - - i.get(c); // start reading - - if (i.flags() & ios::skipws) // skip initial whitespace - while (isspace(c) && i.get(c)) - ; - - if (c == '-' || c == '+') // sign - { - if (c == '-') // mpz_set_str doesn't accept '+' - s = "-"; - i.get(c); - } - - while (isspace(c) && i.get(c)) // skip whitespace - ; - - base = __gmp_istream_set_base(i, c, zero, showbase); // select the base - __gmp_istream_set_digits(s, i, c, ok, base); // read the number - - if (i.good()) // last character read was non-numeric - i.putback(c); - else if (i.eof() && (ok || zero)) // stopped just before eof - i.clear(); - - if (ok) - mpz_set_str(z, s.c_str(), base); // extract the number - else if (zero) - mpz_set_ui(z, 0); - else - i.setstate(ios::failbit); // read failed - - return i; -} - -istream & -//operator>> (istream &i, mpq_ptr q) -io_read (istream &i, mpq_ptr q) -{ - int base; - char c = 0; - string s; - bool ok = false, zero, showbase; - - i.get(c); // start reading - - if (i.flags() & ios::skipws) // skip initial whitespace - while (isspace(c) && i.get(c)) - ; - - if (c == '-' || c == '+') // sign - { - if (c == '-') - s = "-"; - i.get(c); - } - - while (isspace(c) && i.get(c)) // skip whitespace - ; - - base = __gmp_istream_set_base(i, c, zero, showbase); // select the base - __gmp_istream_set_digits(s, i, c, ok, base); // read the numerator - - if (! ok && zero) // the only digit read was "0" - { - base = 10; - s += '0'; - ok = true; - } - - if (i.flags() & ios::skipws) - while (isspace(c) && i.get(c)) // skip whitespace - ; - - if (c == '/') // there's a denominator - { - bool zero2 = false; - int base2 = base; - - s += '/'; - ok = false; // denominator is mandatory - i.get(c); - - while (isspace(c) && i.get(c)) // skip whitespace - ; - - if (showbase) // check base of denominator - base2 = __gmp_istream_set_base(i, c, zero2, showbase); - - if (base2 == base || base2 == 10) // read the denominator - __gmp_istream_set_digits(s, i, c, ok, base); - - if (! ok && zero2) // the only digit read was "0" - { // denominator is 0, but that's your business - s += '0'; - ok = true; - } - } - - if (i.good()) // last character read was non-numeric - i.putback(c); - else if (i.eof() && ok) // stopped just before eof - i.clear(); - - if (ok) - mpq_set_str(q, s.c_str(), base); // extract the number - else - i.setstate(ios::failbit); // read failed - - return i; -} - -ostream& -//operator<< (ostream &o, mpz_srcptr z) -io_write (ostream &o, mpz_srcptr z) -{ - char *str = new char [mpz_sizeinbase(z,10) + 2]; - str = mpz_get_str(str, 10, z); - o << str ; - delete[] str; - return o; -} - -ostream& -//operator<< (ostream &o, mpq_srcptr q) -io_write (ostream &o, mpq_srcptr q) -{ - // size according to GMP documentation - char *str = new char [mpz_sizeinbase(mpq_numref(q), 10) + - mpz_sizeinbase (mpq_denref(q), 10) + 3]; - str = mpq_get_str(str, 10, q); - o << str ; - delete[] str; - return o; -} - -} //namespace CORE +#endif diff --git a/CGAL_Core/src/CGAL_Core/Real.cpp b/CGAL_Core/src/CGAL_Core/Real.cpp index 02694a2f495..21b6f191176 100644 --- a/CGAL_Core/src/CGAL_Core/Real.cpp +++ b/CGAL_Core/src/CGAL_Core/Real.cpp @@ -35,242 +35,9 @@ * $Id$ ***************************************************************************/ -#include +#ifndef CGAL_HEADER_ONLY + #include +#include -namespace CORE { - -const Real& Real::getZero() { - static Real Zero(0); - return Zero; -} - -BigInt floor(const Real& r, Real &sub) { - BigInt f = r.approx(CORE_INFTY, 2).BigIntValue(); - sub = r-f; - // Adjustment - if (sub<0) - ++sub, --f; - if (sub>=1) - --sub, ++f; - assert(sub >=0 && sub<1); - return f; -} - -// pow(r,n) and power(r, n) are the same function -// -Real pow(const Real& r, unsigned long n) { - if (n == 0) - return Real(1); - else if (n == 1) - return r; - else { - Real x = r; - while ((n % 2) == 0) { // n is even - x *= x; - n >>= 1; - } - Real u = x; - while (true) { - n >>= 1; - if (n == 0) - return u; - x *= x; - if ((n % 2) == 1) // n is odd - u *= x; - } - //return u; // unreachable - } -}//pow - -extern BigInt FiveTo(unsigned long exp); - -// Construct Real from String -// Note: -// -- Zilin Du: 06/03/2003 -// -- Original it is the code for Real's constructor for "const char*". -// I change it to a function so that two constrcutors can share the code. -// now it is private and no default value. -// -// --Default value of the argument "prec" is defInputDigits -// --If prec is CORE_posInfty, then the input is -// read in exactly. Otherwise, we convert to a RealBigFloat -// with absolute error at most 10^{-prec} - -// Constructor Real( char *str, extLong& prec) -// is very similar to -// BigFloatRep::fromString( char *str, extLong& prec); -// Differences: -// In BigFloat(str, prec), the value of prec cannot be infinity, and -// it defaults to defBigFloatInputDigits; -// In Real(str, prec), the value of prec is allowed to be infinity, and -// it defaults to defInputDigits. -// -// Why do we have the two versions? It allows us to use the BigFloat class -// directly, without relying on Real class. - -void Real::constructFromString(const char *str, const extLong& prec ) -// NOTE: prec defaults to defInputDigits (see Real.h) -{ - // 8/8/01, Chee and Zilin: add a new rational string format: - // this format is indicated by the presence of a slash "/" - // Moreover, the value of prec is ignored (basically - // assumed to be infinity). - - if (std::strchr(str, '/') != NULL) { // this is a rational number - rep = new RealBigRat(BigRat(str)); - return; - } - - const char *e = std::strchr(str, 'e'); - int dot = 0; - long e10 = 0; - if (e != NULL) - e10 = std::atol(e+1); // e10 is decimal precision of the input string - // i.e., input is A/10^{e10}. - else { - e = str + std::strlen(str); -#ifdef CORE_DEBUG - assert(*e == '\0'); #endif - } - - const char *p = str; - if (*p == '-' || *p == '+') - p++; - BigInt m(0); - - for (; p < e; p++) { - if (*p == '.') { - dot = 1; - continue; - } - m = m * 10 + (*p - '0'); - if (dot) - e10--; - } - - long t = (e10 < 0) ? -e10 : e10; - BigInt one(1); - BigInt ten = FiveTo(t) * (one << static_cast(t)); - if (*str == '-') - m = -m; - if (e10 >= 0) { - // convert exactly from integer numbers - m *= ten; - rep = new RealBigInt(m); - } else { // e10 < 0, fractional numbers - // HERE IS WHERE WE USE THE SYSTEM CONSTANT - // defInputDigits - // Note: defInputDigits should be at least log_2(10). - // We default defInputDigits to 4. - //std::cout << "(m,ten)=" << m << "," << ten << std::endl; - BigRat r(m, ten); - if (prec.isInfty()) { // convert exactly! to a big rational - rep = new RealBigRat(r); - } else { - // convert approximately, to a BigFloat within the - // specified precision: - // BigFloat bf(r, CORE_posInfty, prec * lgTenM) ; - BigFloat bf(r, CORE_posInfty, prec * 4) ; - rep = new RealBigFloat(bf); - } - } -}// Real(str, prec) - -// The operator >>(i,x) calls the constructor Real(char*) -std::istream& operator >>(std::istream& i, Real& x) { - int size = 20; - char *str = new char[size]; - char *p = str; - char c; - int d = 0, e = 0, s = 0; - // int done = 0; - - // Chen Li: fixed a bug, the original statement is - // for (i.get(c); c == ' '; i.get(c)); - // use isspace instead of testing c == ' ', since it must also - // skip tab, catridge/return, etc. - // Change to: - // int status; - do { - i.get(c); - } while (!i.eof() && isspace(c)); /* loop if met end-of-file, or - char read in is white-space. */ - // Chen Li, - // original "if (c == EOF) ..." is unsafe since c is of char type and - // EOF is of int tyep with a negative value -1 - - if (i.eof()) { - i.clear(std::ios::eofbit | std::ios::failbit); - delete [] str; - return i; - } - - // the current content in "c" should be the first non-whitespace char - if (c == '-' || c == '+') { - *p++ = c; - i.get(c); - } - - for (; isdigit(c) || (!d && c=='.') || - (!e && c=='e') || (!s && (c=='-' || c=='+')); i.get(c)) { - if (!i) break; - if (!e && (c == '-' || c == '+')) - break; - // Chen Li: put one more rule to prohibite input like - // xxxx.xxxe+xxx.xxx: - if (e && (c == '.')) - break; - if (p - str == size) { - char *t = str; - str = new char[size*2]; - std::memcpy(str, t, size); - delete [] t; - p = str + size; - size *= 2; - } -#ifdef CORE_DEBUG - assert((p-str) < size); -#endif - - *p++ = c; - if (c == '.') - d = 1; - // Chen Li: fix a bug -- the sign of exponent can not happen before - // the character "e" appears! It must follow the "e' actually. - // if (e || c == '-' || c == '+') s = 1; - if (e) - s = 1; - if (c == 'e') - e = 1; - } - - if (!i && !i.eof()) { - delete [] str; - return i; - } - // chenli: make sure that the p is still in the range - if (p - str >= size) { - int len = p - str; - char *t = str; - str = new char[len + 1]; - std::memcpy(str, t, len); - delete [] t; - p = str + len; - } - -#ifdef CORE_DEBUG - assert(p - str < size); -#endif - - *p = '\0'; - i.putback(c); - i.clear(); - // old: x = Real(str, i.precision()); // use precision of input stream. - x = Real(str); // default precision = defInputDigits - delete [] str; - return i; -}//operator >> (std::istream&, Real&) - -} //namespace CORE diff --git a/CGAL_Core/src/CGAL_Core/extLong.cpp b/CGAL_Core/src/CGAL_Core/extLong.cpp index d45519fc496..e3746d8da18 100644 --- a/CGAL_Core/src/CGAL_Core/extLong.cpp +++ b/CGAL_Core/src/CGAL_Core/extLong.cpp @@ -39,157 +39,9 @@ * $Id$ ***************************************************************************/ +#ifndef CGAL_HEADER_ONLY + #include +#include -namespace CORE { - -const extLong& extLong::getNaNLong() { - static extLong NaNLong(true); - return NaNLong; -} - -const extLong& extLong::getPosInfty() { - static extLong posInfty(EXTLONG_MAX); - return posInfty; -} - -const extLong& extLong::getNegInfty() { - static extLong negInfty(EXTLONG_MIN); - return negInfty; -} - -void extLong::add(extLong& z, long x, long y) { - if (x > 0 && y > 0 && x >= EXTLONG_MAX - y) { - z.val = EXTLONG_MAX; - z.flag = 1; - } else if (x < 0 && y < 0 && x <= EXTLONG_MIN - y) { - z.val = EXTLONG_MIN; - z.flag = -1; - } else { - z.val = x + y; - z.flag = 0; - } -} - -// arithmetic and assignment operators -extLong& extLong::operator+= (const extLong& y) { - if (flag == 2 || y.flag == 2 || (flag * y.flag < 0)) { -#ifdef CORE_DEBUG - if (flag * y.flag < 0) //want a message at the first creation of NaN - core_error("extLong NaN Error in addition.", __FILE__, __LINE__, false); #endif - - *this = CORE_NaNLong; - } else if (flag == 1 || y.flag == 1) { // one of them is +Inf - *this = CORE_posInfty; - } else if (flag == -1 || y.flag == -1) { // one of them is -Inf - *this = CORE_negInfty; - } else { // x and y are normal now - add(*this, val, y.val); - } - return *this; -} - -extLong& extLong::operator-= (const extLong& y) { - if (flag == 2 || y.flag == 2 || (flag * y.flag > 0)) { -#ifdef CORE_DEBUG - if (flag * y.flag > 0) //want a message at the first creation of NaN - core_error("extLong NaN Error in subtraction.", __FILE__, __LINE__, false); -#endif - - *this = CORE_NaNLong; - } else if (flag == 1 || y.flag == -1) { - *this = CORE_posInfty; - } else if (flag == -1 || y.flag == 1) { - *this = CORE_negInfty; - } else { - add(*this, val, -y.val); - } - return *this; -} - -extLong& extLong::operator*= (const extLong& y) { - if (flag == 2 || y.flag == 2) { - *this = CORE_NaNLong; - } else if ((flag != 0) || (y.flag != 0)) { - if (sign() * y.sign() > 0) - *this = CORE_posInfty; - else - *this = CORE_negInfty; - } else { // flag == 0 and y.flag == 0 - double d = double(val) * double(y.val); - long p = val * y.val; - if (std::fabs(d - p) <= std::fabs(d) * relEps) { - val = p; - flag = 0; - } else if (d > EXTLONG_MAX) { - *this = CORE_posInfty; - } else if (d < EXTLONG_MIN) { - *this = CORE_negInfty; - } else { -#ifdef CORE_DEBUG - core_error("extLong NaN Error in multiplication.",__FILE__,__LINE__,false); -#endif - *this = CORE_NaNLong; - } - } - return *this; -} - -extLong& extLong::operator/= (const extLong& y) { - if (flag==2 || y.flag==2 || ((flag != 0) && (y.flag != 0)) || (y.val == 0)) { -#ifdef CORE_DEBUG - if (y.val == 0) - core_error("extLong NaN Error, Divide by Zero.", __FILE__, __LINE__, false); - else if ((flag !=0) && (y.flag !=0)) - core_error("extLong NaN Error, +/-Inf/Inf.", __FILE__, __LINE__, false); -#endif - - *this = CORE_NaNLong; - } else if ((flag != 0) || (y.flag != 0)) { // y.flag == 0 now and y != 0 - if (sign() * y.sign() > 0) - *this = CORE_posInfty; - else - *this = CORE_negInfty; - } else { // flag == 0 and y.flag == 0 - val /= y.val; // no overflow in divisions - flag = 0; - } - return *this; -} - -// unary minus -extLong extLong::operator- () const { - if (flag == 0) - return extLong(-val); - else if (flag == 1) - return CORE_negInfty; - else if (flag == -1) - return CORE_posInfty; - else // NaN - return CORE_NaNLong; -} - -// sign -// You should check "flag" before calling this, otherwise -// you cannot interprete the returned value! -int extLong::sign() const { - if (flag == 2) - core_error("NaN Sign can not be determined!", __FILE__, __LINE__, false); - return ((val == 0) ? 0 : ((val > 0) ? 1 : -1)); -} - -// stream operators -std::ostream& operator<< (std::ostream& o, const extLong& x) { - if (x.flag == 1) - o << " infty "; - else if (x.flag == - 1) - o << " tiny "; - else if (x.flag == 2) - o << " NaN "; - else - o << x.val; - return o; -} - -} //namespace CORE diff --git a/CGAL_ImageIO/include/CGAL/ImageIO.h b/CGAL_ImageIO/include/CGAL/ImageIO.h index 29978fdd3da..c296b99aa39 100644 --- a/CGAL_ImageIO/include/CGAL/ImageIO.h +++ b/CGAL_ImageIO/include/CGAL/ImageIO.h @@ -700,5 +700,8 @@ CGAL_IMAGEIO_EXPORT float evaluate(const _image* image,const std::size_t i,const */ CGAL_IMAGEIO_EXPORT void convertImageTypeToFloat(_image* image); +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY #endif // end IMAGEIO_H diff --git a/CGAL_ImageIO/include/CGAL/ImageIO_impl.h b/CGAL_ImageIO/include/CGAL/ImageIO_impl.h new file mode 100644 index 00000000000..2ba5536e3f7 --- /dev/null +++ b/CGAL_ImageIO/include/CGAL/ImageIO_impl.h @@ -0,0 +1,1626 @@ +// Copyright (c) 2005, 2006 ASCLEPIOS Project, INRIA Sophia-Antipolis (France) +// Copyright (c) 2007 Geometrica Project, INRIA Sophia-Antipolis (France) +// Copyright (c) 2008 GeometryFactory, Sophia-Antipolis (France) +// All rights reserved. +// +// The files in this directory are part of the ImageIO Library. +// You can redistribute them and/or modify them under the terms of the +// GNU Lesser General Public License as published by the Free Software Foundation; +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE. +// +// $URL$ +// $Id$ +// + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#ifdef _MSC_VER +// Suppress deprecated warning for fileno and strdup +# pragma warning(disable:4996) + +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include + +/* formats actuellement lus + + format | extension(s) | lecture | ecriture + INRIMAGE | .inr[.gz] | X | X -> + .gradient[.gz] + .gradient_direction[.gz] + GIS | .dim, .ima[.gz] | X | X + ANALYZE | .hdr, .img[.gz] | X | X + PNM | .ppm, .pgm | X | X + GIF | .gif | X | + BMP | .gif | X | +*/ +#include "inr.h" +#include "gif.h" +#include "gis.h" +#include "pnm.h" +#include "bmp.h" +#include "iris.h" +#include "analyze.h" +#ifdef MINC_FILES +#include "mincio.h" +#endif + + + +/** the first file format is initialized to null */ +static PTRIMAGE_FORMAT firstFormat=NULL; + +/** the Inrimage file format (default format) is initialized to null */ +static PTRIMAGE_FORMAT InrimageFormat=NULL; + + + + + +/*-------------------------------------------------- + * + * mimics standard routines + * + --------------------------------------------------*/ + + + +extern "C" { + /* default allocation routine */ + static void *(*allocRoutine)(size_t) = 0; + /* default deallocation routine */ + static void (*deleteRoutine)(void *) = 0; +} + +CGAL_INLINE_FUNCTION +void *ImageIO_alloc(size_t s) { + if(!allocRoutine) allocRoutine = malloc; + return ( (*allocRoutine)(s) ); +} +/* call allocation routine */ +CGAL_INLINE_FUNCTION +void ImageIO_free(void *m) { + if(!deleteRoutine) deleteRoutine = free; + (*deleteRoutine)(m); +} +/* call deallocation routine */ + + + +/* mimics fwrite() function. + According to _openWriteImage(), openMode will has one + of the following value: + - OM_STD (for stdout) + - OM_GZ + - OM_FILE +*/ +CGAL_INLINE_FUNCTION +size_t ImageIO_write(const _image *im, const void *buf, size_t len) { + + switch(im->openMode) { + default : + case OM_CLOSE : + return 0; + case OM_STD : +#ifdef CGAL_USE_ZLIB + return gzwrite(im->fd, (void *) buf, len); +#else + return fwrite(buf, 1, len, im->fd); +#endif +#ifdef CGAL_USE_ZLIB + case OM_GZ : + return gzwrite(im->fd, (void *) buf, len); +#endif + case OM_FILE: + return fwrite(buf, 1, len, (FILE*)im->fd); + } + //return 0; +} + + + +/* mimics fread() function. + According to _openReadImage(), openMode will has one + of the following value: + - OM_STD (for stdin) + - OM_GZ *or* OM_FILE +*/ +CGAL_INLINE_FUNCTION +size_t ImageIO_read(const _image *im, void *buf, size_t len) +{ + size_t to_be_read = len; + int l = -1; + char *b = (char*)buf; + + switch(im->openMode) { + default : + case OM_CLOSE : + return 0; + case OM_STD : +#ifdef CGAL_USE_ZLIB + while ( (to_be_read > 0) && ((l = gzread(im->fd, (void *) b, to_be_read)) > 0) ) { + to_be_read -= l; + b += l; + } +#else + while ( (to_be_read > 0) && ((l = fread( b, 1, to_be_read, im->fd )) > 0) ) { + to_be_read -= l; + b += l; + } +#endif + return ( len - to_be_read ); +#ifdef CGAL_USE_ZLIB + case OM_GZ : + while ( (to_be_read > 0) && ((l = gzread(im->fd, (void *) b, to_be_read)) > 0) ) { + to_be_read -= l; + b += l; + } + if(l<0) + { + int errnum; + fprintf(stderr, "zlib error: %s\n", gzerror(im->fd, &errnum)); + } + return ( len - to_be_read ); +#else + case OM_FILE : + while ( (to_be_read > 0) && ((l = fread( b, 1, to_be_read, im->fd )) > 0) ) { + to_be_read -= l; + b += l; + } + return ( len - to_be_read ); +#endif + } + + //return 0; +} + + + +/* mimics fgets() function. + According to _openReadImage(), openMode will has one + of the following value: + - OM_STD (for stdout) + - OM_GZ *or* OM_FILE +*/ +CGAL_INLINE_FUNCTION +char *ImageIO_gets( const _image *im, char *str, int size ) +{ + char *ret = NULL; + switch(im->openMode) { + default : + case OM_CLOSE : + return NULL; + case OM_STD : +#ifdef CGAL_USE_ZLIB + ret = (char *) gzgets(im->fd, str, size ); +#else + ret = fgets(str, size, im->fd); +#endif + break; +#ifdef CGAL_USE_ZLIB + case OM_GZ : + ret = (char *) gzgets(im->fd, str, size); + break; +#else + case OM_FILE : + ret = fgets(str, size, im->fd); + break; +#endif + } + return ret; +} + + + +CGAL_INLINE_FUNCTION +int ImageIO_seek( const _image *im, long offset, int whence ) { + switch(im->openMode) { + case OM_CLOSE : + default : + return -1; +#ifdef CGAL_USE_ZLIB + case OM_GZ: + return gzseek(im->fd, offset, whence ); +#endif + case OM_FILE: + return fseek( (FILE*)im->fd, offset, whence ); + } +} + +/* return non 0 in case of error + */ +CGAL_INLINE_FUNCTION +int ImageIO_error( const _image *im ) +{ + switch(im->openMode) { + case OM_CLOSE : + default : + return 0; +#ifdef CGAL_USE_ZLIB + case OM_GZ : + static int errnum; + (void)gzerror(im->fd, &errnum); + return( (errnum != Z_OK) || gzeof(im->fd) ); +#endif + case OM_FILE : + return( ferror( (FILE*)im->fd ) || feof( (FILE*)im->fd ) ); + } + //return 0; +} + + + +/* Upon successful completion 0 is returned. + + Closing the standard output with gzclose() + is necessary as it will flush the pending output. + */ +CGAL_INLINE_FUNCTION +int ImageIO_close( _image* im ) +{ + int ret=0; + + switch ( im->openMode ) { + default : + case OM_CLOSE : + break; +#ifdef CGAL_USE_ZLIB + case OM_GZ : + case OM_STD : + ret = gzclose( im->fd ); + break; +#else + case OM_STD : + break; +#endif + case OM_FILE : + ret = fclose( (FILE*)im->fd ); + } + im->fd = NULL; + im->openMode = OM_CLOSE; + + return ret; +} + + + + + + + +/* given an initialized file descriptor and a file name, + open file from stdin (if name == NULL, or name == "-", or name == "<"), + or a standard/gzipped file otherwise (gzipped files are handled assuming + that it is compiled and linked with zlib). + openMode will have one of the following value: + - OM_STD (for stdin) + - OM_GZ *or* OM_FILE +*/ +CGAL_INLINE_FUNCTION +void _openReadImage(_image* im, const char *name) { + if(im->openMode == OM_CLOSE) { + + /* open from stdin */ + if( name == NULL || name[0] == '\0' + || (name[0] == '-' && name[1] == '\0') + || (name[0] == '<' && name[1] == '\0') ) { +#ifdef CGAL_USE_ZLIB + im->fd = gzdopen(fileno(stdin), "rb"); +#else + im->fd = fdopen(fileno(stdin), "rb"); +#endif + im->openMode = OM_STD; + } + + else { +#ifdef CGAL_USE_ZLIB + im->fd = gzopen(name, "rb"); + if(im->fd) im->openMode = OM_GZ; +#else + im->fd = fopen(name, "rb"); + if(im->fd) im->openMode = OM_FILE; +#endif + + } + + } +} + + + + + +/* given an initialized file descriptor and a file name, + open file from stdout (if name == NULL, or name == "-", or name == ">"), + a gzipped pipe (if name got the extension ".gz") + or a standard file otherwise. + openMode will have one of the following value: + - OM_STD (for stdout) + - OM_GZ + - OM_FILE +*/ +CGAL_INLINE_FUNCTION +void _openWriteImage(_image* im, const char *name) +{ + im->openMode = OM_CLOSE; + + if( name == NULL || name[0] == '\0' + || (name[0] == '-' && name[1] == '\0') + || (name[0] == '>' && name[1] == '\0') ) { + +#ifdef CGAL_USE_ZLIB +#if (defined _LINUX_) || (defined _SOLARIS_) || (defined _SGI_) + im->fd = gzdopen(1, "wb"); +#else + im->fd = gzdopen(fileno(stdout), "wb"); +#endif +#else + im->fd = (_ImageIO_file) stdout; +#endif + im->openMode = OM_STD; + } + + else{ +#ifdef CGAL_USE_ZLIB + + /* from gzopen() doc: + ... The mode parameter is as in fopen ("rb" or "wb") but can + also include a compression level ("wb9") or a strategy: 'f' for + filtered data as in "wb6f", 'h' for Huffman only compression as + in "wb1h" ... + However, a small .gz header will be written ... thus gz(d)open can not + be used for rgular files. + */ + + if( !strncmp(name+strlen(name)-3, ".gz", 3) ) + { +#ifdef _MSC_VER + int ffd=_open(name,_O_RDWR | _O_CREAT| _O_TRUNC | _O_BINARY, _S_IREAD|_S_IWRITE); + im->fd = gzdopen( ffd, "wb" ); +#else + im->fd = gzopen( name, "wb" ); +#endif + im->openMode = OM_GZ; + } + else +#endif + { + im->fd = (_ImageIO_file) fopen(name, "wb"); + im->openMode = OM_FILE; + } + } +} + + + +/* set allocation and deallocation routines */ +CGAL_INLINE_FUNCTION +void setImageIOAllocationRoutines(ALLOCATION_FUNCTION alloc, + DEALLOCATION_FUNCTION del) { + if(alloc != NULL) allocRoutine = alloc; + if(del != NULL) deleteRoutine = del; +} + + + + + +/*-------------------------------------------------- + * + * + * + --------------------------------------------------*/ + + + + + +CGAL_INLINE_FUNCTION +ENDIANNESS _getEndianness() +{ + union { + unsigned char uc[2]; + unsigned short us; + } twobytes; + twobytes.us = 255; + /* on linux or dec + */ + if ( twobytes.uc[1] == 0 ) return( END_LITTLE ); + /* on solaris or sgi + */ + return( END_BIG ); +} + + + + + + + +/* Allocates and initializes an image descriptor */ +CGAL_INLINE_FUNCTION +_image *_initImage() { + _image *im; + + im = (_image *) ImageIO_alloc(sizeof(_image)); + if ( im == NULL ) return( im ); + + /* default image size is 1*1*1 */ + im->xdim = im->ydim = im->zdim = im->vdim = 1; + /* default image voxel size is 1.0*1.0*1.0 */ + im->vx = im->vy = im->vz = 1.0; + + /* default image center is 0 0 0 */ + im->cx = im->cy = im->cz = 0; + + /* default image offset is 0 0 0 */ + im->tx = im->ty = im->tz = 0.0; + + /* default image rotation is 0 0 0 */ + im->rx = im->ry = im->rz = 0.0; + + /* no data yet */ + im->data = NULL; + + /* no file associated to image */ + im->fd = NULL; + im->openMode = OM_CLOSE; + im->endianness = END_UNKNOWN; + + /* unknown data kind + default is binary + */ + im->dataMode = DM_BINARY; + + /* no user string */ + im->user = NULL; + im->nuser = 0; + + /* unknown word kind */ + im->wdim = 0; + im->wordKind = WK_UNKNOWN; + im->vectMode = VM_SCALAR; + im->sign = SGN_UNKNOWN; + im->imageFormat = NULL; + + /** eventually initializes the supported file formats */ + if (firstFormat==NULL) + initSupportedFileFormat(); + /* return image descriptor */ + return im; +} + +CGAL_INLINE_FUNCTION +_image *_createImage(int x, int y, int z, int v, + float vx, float vy, float vz, int w, + WORD_KIND wk, SIGN sgn) +{ + _image *im; + + im = (_image *) ImageIO_alloc(sizeof(_image)); + if ( im == NULL ) return( im ); + + im->xdim = x; + im->ydim = y; + im->zdim = z; + im->vdim = v; + im->vx = vx; + im->vy = vy; + im->vz = vz; + + /* default image center is 0 0 0 */ + im->cx = im->cy = im->cz = 0; + + /* default image offset is 0 0 0 */ + im->tx = im->ty = im->tz = 0.0; + + /* default image rotation is 0 0 0 */ + im->rx = im->ry = im->rz = 0.0; + + /* no data yet */ + im->data = ImageIO_alloc(x*y*z*v*w); + + /* no file associated to image */ + im->fd = NULL; + im->openMode = OM_CLOSE; + im->endianness = END_UNKNOWN; + + /* unknown data kind + default is binary + */ + im->dataMode = DM_BINARY; + + /* no user string */ + im->user = NULL; + im->nuser = 0; + + /* unknown word kind */ + im->wdim = w; + im->wordKind = wk; + im->vectMode = VM_SCALAR; + im->sign = sgn; + im->imageFormat = NULL; + + /** eventually initializes the supported file formats */ + if (firstFormat==NULL) + initSupportedFileFormat(); + /* return image descriptor */ + return im; +} + +/* return the bounding box of the image */ +CGAL_INLINE_FUNCTION +void _get_image_bounding_box(_image* im, + double* x_min, double* y_min, double* z_min, + double* x_max, double* y_max, double* z_max) { + *x_min = im->tx; + *y_min = im->ty; + *z_min = im->tz; + *x_max = (im->xdim - 1.0f)*(im->vx) + *x_min ; + *y_max = (im->ydim - 1.0f)*(im->vy) + *y_min ; + *z_max = (im->zdim - 1.0f)*(im->vz) + *z_min ; +} + +/* Free an image descriptor */ +CGAL_INLINE_FUNCTION +void _freeImage(_image *im) { + unsigned int i; + + if ( im == NULL ) return; + + /* close image if opened */ + if(im->openMode != OM_CLOSE) ImageIO_close(im); + + /* free data if any */ + if(im->data != NULL) ImageIO_free(im->data); + im->data = NULL; + + /* free user string array if any */ + if( (im->nuser > 0) && (im->user != NULL) ) { + for(i = 0; i < im->nuser; i++) + if ( im->user[i] != NULL ) ImageIO_free(im->user[i]); + ImageIO_free(im->user); + } + im->nuser = 0; + im->user = NULL; + + /* free given descriptor */ + ImageIO_free(im); +} + + + + + +/* Reads an image from a file and returns an image descriptor or NULL if + reading failed. + Reads from stdin if image name is NULL. */ +CGAL_INLINE_FUNCTION +_image* _readImage(const char *name) { + _image *im; + + + /* read header */ + im = _readImageHeader( name ); + + if(im != NULL && im->openMode != OM_CLOSE) { + /* read body */ + if(_readImageData(im) < 0) { + fprintf(stderr, "_readImage: error: invalid data encountered in \'%s\'\n", + name); + _freeImage(im); + return NULL; + } + ImageIO_close(im); + } + + return im; +} + +// raw +CGAL_INLINE_FUNCTION +_image* _readImage_raw(const char *name, + const unsigned int rx, + const unsigned int ry, + const unsigned int rz, + const double vx, + const double vy, + const double vz, + const unsigned int offset) +{ + _image *im = NULL; + im = (_image *) ImageIO_alloc(sizeof(_image)); + if ( im == NULL ) + return NULL; + + im->xdim = rx; + im->ydim = ry; + im->zdim = rz; + im->vdim = 1; + im->vx = vx; + im->vy = vy; + im->vz = vz; + + // image center + im->cx = im->cy = im->cz = 0; + + // image offset + im->tx = im->ty = im->tz = 0.0; + + // image rotation + im->rx = im->ry = im->rz = 0.0; + + + im->fd = NULL; + im->openMode = OM_CLOSE; + im->endianness = END_UNKNOWN; + + im->dataMode = DM_BINARY; + + // no user string + im->user = NULL; + im->nuser = 0; + + // word type (unsigned byte) + im->wdim = 1; + im->wordKind = WK_FIXED; + im->vectMode = VM_SCALAR; + im->sign = SGN_UNSIGNED; + im->imageFormat = NULL; + + // read file + ::_openReadImage(im, name); + if(!im->fd) { + fprintf(stderr, "_readImage_raw: error: unable to open file \'%s\'\n", name); + _freeImage(im); + return NULL; + } + + // read offset + if(offset > 0) { + im->data = ImageIO_alloc(offset+1); + ImageIO_read(im, im->data, offset); + ImageIO_free(im->data); + } + // allocate memory + im->data = ImageIO_alloc(rx*ry*rz); + if(im->data == NULL) + return NULL; + + // read + ImageIO_read(im, im->data, rx*ry*rz); + + ImageIO_close(im); + /* + unsigned int i,j,k; + unsigned char *data = (unsigned char *)im->data; + int dimxy = rx * ry; + for(i=0;i + reading failed.
+ Reads from stdin if image name is NULL. + If the image is vectorial, it is uninterlaced. */ +CGAL_INLINE_FUNCTION +_image* _readNonInterlacedImage(const char *name) { + _image *im; + + /* read header */ + im = _readImageHeader(name); + + if(im && im->openMode != OM_CLOSE) { + /* read scalar image body */ + if(im->vdim == 1) { + if(_readImageData(im) < 0) { + fprintf(stderr, "_readImage: error: invalid data encountered in \'%s\'\n", + name); + _freeImage(im); + return NULL; + } + } + /* read vectorial image body */ + else { + im->vectMode = VM_NON_INTERLACED; + if(_readNonInterlacedImageData(im) < 0) { + fprintf(stderr, "_readImage: error: invalid data encountered in \'%s\'\n", + name); + _freeImage(im); + return NULL; + } + } + ImageIO_close(im); + } + + return im; +} + + + + + + + + + + + +/* Write inrimage given in inr in file name. If file name's suffix is + .gz, the image is gziped. If file name's suffix is .hdr, the image + is written in ANALYZE format. If file name is NULL, image is written + on stdout */ +CGAL_INLINE_FUNCTION +int _writeImage(_image *im, const char *name_to_be_written ) { + + int r = ImageIO_NO_ERROR; + int length = 0; + char *name = NULL; + char *baseName = NULL; + + if ( im == NULL ) return -1; + + /* different conventions for the standard input + */ + if ( name_to_be_written == NULL || name_to_be_written[0] == '\0' + || (name_to_be_written[0] == '-' && name_to_be_written[1] == '\0') + || (name_to_be_written[0] == '>' && name_to_be_written[1] == '\0') ) { + name = NULL; + } + else { + name = strdup( name_to_be_written ); + } + + initSupportedFileFormat(); + + /* what is the wanted format + */ + if ( name == NULL ) { + im->imageFormat = InrimageFormat; + } else { + int i,extLength; + PTRIMAGE_FORMAT f; + char ext[IMAGE_FORMAT_NAME_LENGTH]; + char *ptr; + + + /* scan all formats; */ + im->imageFormat=NULL; + length=strlen(name); + + for(f=firstFormat;(f!=NULL)&& (im->imageFormat==NULL);f=f->next) { + /* scan all extensions for that format */ + ptr=&f->fileExtension[0]; + + do { + /* get next file extension */ + i=0; + for(i=0;((*ptr)!=',' && (*ptr)!='\0');i++,ptr++) { + ext[i]=(*ptr); + } + if ((*ptr)==',') { + ext[i]='\0'; + ptr++; + } + else { + ext[i]='\0'; + } + extLength=strlen(ext); + + /* test if the tail of name matches the extension */ + if ( (length > extLength) && (!strcmp( name + length - extLength, ext)) ) { + im->imageFormat=f; + /* copy original name and removes extension */ + baseName=strdup(name); + for(i= length - extLength;iimageFormat==NULL)); + } + + if (!im->imageFormat) { + fprintf(stderr, "_writeImage: warning : unknown extension in %s = assuming Inrimage\n",name); + im->imageFormat=InrimageFormat; + baseName=strdup(name); + } + } + + + /* open file descriptor */ + /* _openWriteImage( im, name ) ; + + + + if(!im->fd) { + fprintf(stderr, "_writeImage: error: open failed\n"); + if ( name != NULL ) free( name ); + if ( baseName != NULL ) free( baseName ); + return ImageIO_OPENING; + } + */ + + if (im->imageFormat) { + + if (im->imageFormat->writeImage==NULL) { + im->imageFormat=InrimageFormat; + } + + if ( 0 ) { + fprintf(stderr, "_writeImage: will write '%s' with '%s' format\n", + name, im->imageFormat->realName ); + } + + if ((*im->imageFormat->writeImage)(name, im)<0) { + fprintf(stderr, "_writeImage: error: unable to write \'%s\'\n", + name); + r = ImageIO_WRITING_HEADER; + } + + } + + + + /* close file descriptor */ + ImageIO_close( im ); + + im->fd = NULL; + im->openMode = OM_CLOSE; + + if ( baseName != NULL ) free( baseName ); + if ( name != NULL ) free( name ); + + return r; +} + + + + + + + + + + + + +/* read header from an image file + + if standard input, it's an inrimage + if not, get a magic string + and try to find the good format + + if data are in a separate file, + the header reading procedure will open + the data file. + + error: + 0 success + -1 unknown image type + -2 error while opening + -3 error while reading header + -4 error while reading header or data + */ +CGAL_INLINE_FUNCTION +_image *_readImageHeader( const char *name ) { + int error = 0; + return( _readImageHeaderAndGetError( name, &error ) ); +} + + + +CGAL_INLINE_FUNCTION +_image *_readImageHeaderAndGetError( const char *name_to_be_read, int *error ) +{ + _image *im; + char magic[5]; + char *name = NULL; + PTRIMAGE_FORMAT f; + int res; + + *error = ImageIO_NO_ERROR; + + /* open image file */ + im = _initImage(); + if ( name_to_be_read == NULL || name_to_be_read[0] == '\0' + || (name_to_be_read[0] == '-' && name_to_be_read[1] == '\0') + || (name_to_be_read[0] == '<' && name_to_be_read[1] == '\0') ) { + name = NULL; + } + else { + name = strdup( name_to_be_read ); + } + + + _openReadImage(im, name); + + if(!im->fd) { + fprintf(stderr, "_readImageHeaderAndGetError: error: unable to open file \'%s\'\n", name); + _freeImage(im); + *error = ImageIO_OPENING; + if ( name != NULL ) free( name ); + return NULL; + } + + initSupportedFileFormat(); + + /* what is the wanted format ? + assume that stdin is inrimage + */ + if(im->openMode == OM_STD) { + im->imageFormat=InrimageFormat; + } + else { + /* get magic string for disk files + */ + ImageIO_read(im, magic, 4); + magic[4] = '\0'; + ImageIO_seek(im, 0L, SEEK_SET); + /** test each format */ + for(f=firstFormat;(f!=NULL)&& (im->imageFormat==NULL);f=f->next) { + /* test if it is the correct format based on magic and file extension */ + if (((*f->testImageFormat)(magic, name)) >=0) { + im->imageFormat=f; + } + } + } + + if ( im->imageFormat == NULL ) { + fprintf(stderr, "_readImageHeaderAndGetError: does not find image format for \'%s\'\n", name); + ImageIO_close( im ); + _freeImage(im); + *error = ImageIO_UNKNOWN_TYPE; + if ( name != NULL ) free( name ); + return NULL; + } + + /* now tests if the header can be read correctly */ + + res=(*(im->imageFormat)->readImageHeader)(name,im); + /* could read header only */ + if (res == 0) { + if ( name != NULL ) free( name ); + return( im ); + } + /* could read header and data */ + else if ( res > 0 ) { + ImageIO_close(im); + if ( name != NULL ) free( name ); + return im; + } + + /* could not read error : throw error */ + fprintf(stderr, "_readImageHeaderAndGetError: an error occurs when reading image\n" ); + if ( name == NULL || im->openMode == OM_STD) { + fprintf(stderr, "\t from \'standard input\'" ); + } + else { + fprintf(stderr, "\t from file \'%s\'", name ); + } + fprintf(stderr, " using format \'%s\'\n", (im->imageFormat)->realName ); + ImageIO_close( im ); + _freeImage(im); + *error = ImageIO_READING_HEADER; + if ( name != NULL ) free( name ); + return NULL; + +} + + + + + + + +CGAL_INLINE_FUNCTION +static void _swapImageData( _image *im ) +{ + unsigned char *ptr1, *ptr2, b[8]; + unsigned short int si, *ptr3, *ptr4; + unsigned int i, *ptr5, *ptr6; + int size, length; + + if( _getEndianness() != im->endianness) { + + size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim; + if ( size <= 0 ) return; + + length = size / im->wdim; + ptr1 = ptr2 = (unsigned char *) im->data; + + /* 2 bytes swap */ + if(im->wdim == 2) { + /* + while(length--) { + b[0] = *ptr1++; + b[1] = *ptr1++; + *ptr2++ = b[1]; + *ptr2++ = b[0]; + } + */ + ptr3 = ptr4 = (unsigned short int *) im->data; + while( length-- ) { + si = *ptr3++; + *ptr4++ = ((si >> 8) & 0xff) | (si << 8); + } + } + + /* 4 bytes swap */ + else if(im->wdim == 4) { + /* + while(length--) { + b[0] = *ptr1++; + b[1] = *ptr1++; + b[2] = *ptr1++; + b[3] = *ptr1++; + *ptr2++ = b[3]; + *ptr2++ = b[2]; + *ptr2++ = b[1]; + *ptr2++ = b[0]; + } + */ + ptr5 = ptr6 = (unsigned int *) im->data; + while( length-- ) { + i = *ptr5++; + *ptr6++ = (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | ((i >> 24) & 0xff); + } + } + /* 8 bytes swap */ + else if(im->wdim == 8) { + while(length--) { + b[0] = *ptr1++; + b[1] = *ptr1++; + b[2] = *ptr1++; + b[3] = *ptr1++; + b[4] = *ptr1++; + b[5] = *ptr1++; + b[6] = *ptr1++; + b[7] = *ptr1++; + *ptr2++ = b[7]; + *ptr2++ = b[6]; + *ptr2++ = b[5]; + *ptr2++ = b[4]; + *ptr2++ = b[3]; + *ptr2++ = b[2]; + *ptr2++ = b[1]; + *ptr2++ = b[0]; + } + } + } +} + + + + + + +/* Read data of an inrimage. + If im->data is not NULL, assume that the buffer was previously allocated + Swap bytes depending on the endianness and the current architecture */ +CGAL_INLINE_FUNCTION +int _readImageData(_image *im) { + unsigned long size, nread; + + if(im->openMode != OM_CLOSE) { + size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim; + + if ( size <= 0 ) return -3; + + if(!im->data) { + im->data = (unsigned char *) ImageIO_alloc(size); + if(!im->data) return -2; + } + + nread = ImageIO_read(im, im->data, size); + if(nread != size) return -1; + + + /* architecture is big endian and data little endian + length = nb of points + */ + _swapImageData( im ); + + + } + + return 1; +} + + + + + +/* Read data of a vectorial inrimage, making the resulting buffer non- + inerlaced. + If im->data is not NULL, assume that the buffer was previously allocated + Swap bytes depending on the endianness and the current architecture. */ +CGAL_INLINE_FUNCTION +int _readNonInterlacedImageData(_image *im) { + unsigned long size, nread; + unsigned char **vp, *buf; + unsigned int i, j, k, v, w; + + if(im->vdim == 1) return _readImageData(im); + + if(im->openMode != OM_CLOSE) { + size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim; + + if ( size <= 0 ) return -3; + + if(!im->data) { + im->data = (unsigned char *) ImageIO_alloc(size); + if(!im->data) return -2; + } + + vp = (unsigned char **) ImageIO_alloc(im->vdim * sizeof(unsigned char *)); + buf = (unsigned char *) ImageIO_alloc(im->vdim * im->wdim); + size = im->xdim * im->ydim * im->zdim * im->wdim; + for(v = 0; v < im->vdim; v++) + vp[v] = (unsigned char *) im->data + v * size; + + for(k = 0; k < im->zdim; k++) { + for(j = 0; j < im->ydim; j++) { + for(i = 0; i < im->xdim; i++) { + nread = ImageIO_read(im, buf, im->vdim * im->wdim); + if(nread != im->vdim * im->wdim) return -1; + for(v = 0; v < im->vdim; v++) + for(w = 0; w < im->wdim; w++) + *vp[v]++ = *buf++; + buf -= im->vdim * im->wdim; + } + } + } + + ImageIO_free(buf); + ImageIO_free(vp); + + /* architecture is big endian and data little endian */ + _swapImageData( im ); + + + /* reorder lines */ + /* no non-interlaced data for ANALYZE. But if ever... */ +/* if( im->imageFormat == IF_ANALYZE ) { */ +/* int v ; */ +/* int vdim = im->vdim ; */ +/* int lineSize = im->wdim * im->xdim ; */ +/* int vsize = lineSize * im->ydim * im->zdim ; */ +/* char* swapped = ImageIO_alloc(lineSize) ; */ +/* for( v = 0 ; v < vdim ; ++v ) */ +/* { */ +/* char* buf1 = (char*)im->data + v*vsize ; */ +/* char* buf2 = buf1 + vsize - lineSize ; */ + +/* while( buf1 < buf2 ) */ +/* { */ +/* memcpy( swapped, buf1, lineSize ) ; */ +/* memcpy( buf1, buf2, lineSize ) ; */ +/* memcpy( buf2, swapped, lineSize ) ; */ +/* buf1 += lineSize ; */ +/* buf2 -= lineSize ; */ +/* } */ + +/* ImageIO_free( swapped ) ; */ +/* } */ +/* } */ + } + + return 1; +} + + +/* Reads body from a non-interlaced vectorial inrimage whose header has + been read by _readImageHeader. The image buffer is interlaced. */ +CGAL_INLINE_FUNCTION +int _readNonInterlacedFileData(_image *im) { + unsigned long size, nread; + unsigned char *ptr1, *vp, *buf; + unsigned int i, j, k, v, w; + + if(im->vdim == 1) return _readImageData(im); + + if(im->openMode != OM_CLOSE) { + size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim; + + if ( size <= 0 ) return -3; + + if(!im->data) { + im->data = (unsigned char *) ImageIO_alloc(size); + if(!im->data) return -2; + } + + size = im->xdim * im->ydim * im->zdim * im->wdim; + buf = ptr1 = (unsigned char *) ImageIO_alloc(size); + + for(v = 0; v < im->vdim; v++) { + buf = ptr1; + nread = ImageIO_read(im, buf, size); + if(nread != size) return -1; + vp = (unsigned char *) im->data + (v * im->wdim); + for(k = 0; k < im->zdim; k++) { + for(j = 0; j < im->ydim; j++) { + for(i = 0; i < im->xdim; i++) { + for(w = 0; w < im->wdim; w++) *vp++ = *buf++; + vp += (im->vdim - 1) * im->wdim; + } + } + } + } + + ImageIO_free(buf); + + /* architecture is big endian and data little endian */ + _swapImageData( im ); + + + /* reorder lines */ + /* no non-interlaced data for ANALYZE. But if ever... */ +/* if( im->imageFormat == IF_ANALYZE ) { */ +/* int v ; */ +/* int vdim = im->vdim ; */ +/* int lineSize = im->wdim * im->xdim ; */ +/* int vsize = lineSize * im->ydim * im->zdim ; */ +/* char* swapped = ImageIO_alloc(lineSize) ; */ +/* for( v = 0 ; v < vdim ; ++v ) */ +/* { */ +/* char* buf1 = (char*)im->data + v*vsize ; */ +/* char* buf2 = buf1 + vsize - lineSize ; */ + +/* while( buf1 < buf2 ) */ +/* { */ +/* memcpy( swapped, buf1, lineSize ) ; */ +/* memcpy( buf1, buf2, lineSize ) ; */ +/* memcpy( buf2, swapped, lineSize ) ; */ +/* buf1 += lineSize ; */ +/* buf2 -= lineSize ; */ +/* } */ + +/* ImageIO_free( swapped ) ; */ +/* } */ +/* } */ + } + + return 1; +} + + + + + + + + + + +/*-------------------------------------------------- + * + * ????? + * + --------------------------------------------------*/ + + + + + +/* check the type of image in fileName */ +CGAL_INLINE_FUNCTION +PTRIMAGE_FORMAT imageType(const char *fileName) { + _ImageIO_file f; + char magic[5]; + PTRIMAGE_FORMAT format; + + if(!fileName) { +#ifdef CGAL_USE_ZLIB + f = gzdopen(fileno(stdin), "rb"); +#else + f = fdopen(fileno(stdin), "rb"); +#endif + } + else { +#ifdef CGAL_USE_ZLIB + f = gzopen(fileName, "rb"); +#else + f = fopen(fileName, "rb"); +#endif + } + + if(!f) return NULL; + +#ifdef CGAL_USE_ZLIB + gzread( f, (void *) magic, 4); +#else + fread( (void *) magic, 1, 4, f ); +#endif + + + magic[4] = '\0'; + +#ifdef CGAL_USE_ZLIB + gzclose( f ); +#else + if(fileName) fclose( f ); +#endif + + if (firstFormat==NULL) + initSupportedFileFormat(); + + for(format=firstFormat;(format!=NULL);format=format->next) { + /* test if it is the correct header based on magic and file extension */ + if (((*format->testImageFormat)(magic,fileName)) >=0) { + return format; + } + } + return 0; + +} + + + + + +/*-------------------------------------------------- + * + * Image Format Management + * + --------------------------------------------------*/ + + + + + +/** adds a format at the beginning of the list of image formats. + Test if all mandatory fields have been filled */ +CGAL_INLINE_FUNCTION +int addImageFormat( PTRIMAGE_FORMAT format) +{ + if ( (format->testImageFormat) && + (format->readImageHeader) && + (strlen(format->fileExtension)>0) && + (strlen(format->realName)>0) ) { + + format->next=firstFormat; + firstFormat=format; + + return 0; + + } + else { + fprintf(stderr,"addImageFormat: information missing in file format %s\n", + format->realName); + return -1; + } +} + +/** adds a format at the end of the list of image formats. + Test if all mandatory fields have been filled */ +CGAL_INLINE_FUNCTION +int addImageFormatAtEnd( PTRIMAGE_FORMAT format) +{ + PTRIMAGE_FORMAT f; + if ( (format->testImageFormat) && + (format->readImageHeader) && + (strlen(format->fileExtension)>0) && + (strlen(format->realName)>0) ) { + + format->next = NULL; + + if (firstFormat == NULL) { + firstFormat=format; + } + else { + for(f=firstFormat;(f->next!=NULL);f=f->next) + ; + f->next=format; + } + + return 0; + + } + else { + fprintf(stderr,"addImageFormatAtEnd: information missing in file format %s\n", + format->realName); + return -1; + } +} + + +/** creates supported image formats */ +CGAL_INLINE_FUNCTION +void initSupportedFileFormat() +{ + PTRIMAGE_FORMAT f; + if ( InrimageFormat == NULL ) { + f = createAnalyzeFormat(); + addImageFormatAtEnd( f ); + f = createBMPFormat(); + addImageFormatAtEnd( f ); + f = createGifFormat(); + addImageFormatAtEnd( f ); + f = createGisFormat(); + addImageFormatAtEnd( f ); + f = createIrisFormat(); + addImageFormatAtEnd( f ); + f = createPgmFormat(); + addImageFormatAtEnd( f ); + f = createPgmAscIIFormat(); + addImageFormatAtEnd( f ); + f = createPpmFormat(); + addImageFormatAtEnd( f ); + InrimageFormat = createInrimageFormat(); + addImageFormat( InrimageFormat ); + } +} + + + +CGAL_INLINE_FUNCTION +PTRIMAGE_FORMAT firstImageFormat() { + return firstFormat; +} + + + +/** prints supported image formats */ +CGAL_INLINE_FUNCTION +void printSupportedFileFormat() { + PTRIMAGE_FORMAT f; + int i; + + initSupportedFileFormat(); + + for(i=0, f=firstFormat;(f!=NULL);i++, f=f->next) { + if ( (f->testImageFormat) && + (f->readImageHeader) && + (strlen(f->fileExtension)>0) && + (strlen(f->realName)>0)) { + fprintf( stderr, "#%2d: format name ='%s', extensions='%s'", + i, f->realName, f->fileExtension ); + if (f->readImageHeader) + fprintf( stderr, ", read" ); + if (f->writeImage) + fprintf( stderr, ", write" ); + fprintf( stderr, "\n" ); + } + } +} + + +/** remove supported image formats */ +CGAL_INLINE_FUNCTION +void removeSupportedFileFormat() { + PTRIMAGE_FORMAT f=firstFormat; + + while( f != NULL) { + PTRIMAGE_FORMAT f_old = f; + f = f->next; + ImageIO_free( f_old); + } + InrimageFormat=NULL; + +} + + +/** trilinear interpolation in an _image float type + */ +CGAL_INLINE_FUNCTION +float triLinInterp(const _image* image, + float posx, + float posy, + float posz, + float value_outside /*= 0.f */) +{ + const int dimx = image->xdim; + const int dimy = image->ydim; + const int dimz = image->zdim; + const int dimxy = dimx*dimy; + + if(posx < 0.f || posy < 0.f || posz < 0.f ) + return value_outside; + + posx = static_cast(posx /(image->vx)); + posy = static_cast(posy /(image->vy)); + posz = static_cast(posz /(image->vz)); + + //patch suggested by J.Cugnoni to prevent integer overflow + if(posz >= dimz-1 || posy >= dimy-1 || posx >= dimx-1) + return value_outside; + + const int i1 = (int)(posz); + const int j1 = (int)(posy); + const int k1 = (int)(posx); + + const int i2 = i1 + 1; + const int j2 = j1 + 1; + const int k2 = k1 + 1; + + const float KI2 = i2-posz; + const float KI1 = posz-i1; + const float KJ2 = j2-posy; + const float KJ1 = posy-j1; + + CGAL_IMAGE_IO_CASE + (image, + Word *array = (Word *) image->data; + return (((float)array[i1 * dimxy + j1 * dimx + k1] * KI2 + + (float)array[i2 * dimxy + j1 * dimx + k1] * KI1) * KJ2 + + ((float)array[i1 * dimxy + j2 * dimx + k1] * KI2 + + (float)array[i2 * dimxy + j2 * dimx + k1] * KI1) * KJ1) * (k2-posx)+ + (((float)array[i1 * dimxy + j1 * dimx + k2] * KI2 + + (float)array[i2 * dimxy + j1 * dimx + k2] * KI1) * KJ2 + + ((float)array[i1 * dimxy + j2 * dimx + k2] * KI2 + + (float)array[i2 * dimxy + j2 * dimx + k2] * KI1) * KJ1) * (posx-k1); + ); + return 0.f; +} + +// Gives the value of the image at pixel (i,j,k), converted in float. +CGAL_INLINE_FUNCTION +float evaluate(const _image* image, + const std::size_t i, + const std::size_t j, + const std::size_t k) +{ + using CGAL::IMAGEIO::static_evaluate; + + CGAL_IMAGE_IO_CASE(image, return (float)static_evaluate(image, i, j, k); ); + + return 0.f; +} + +/** convert the data of the image to float +*/ +CGAL_INLINE_FUNCTION +void convertImageTypeToFloat(_image* image){ + if(image->wordKind == WK_FLOAT && image->wdim == 4) + return; + + const unsigned int dimx = image->xdim; + const unsigned int dimy = image->ydim; + const unsigned int dimz = image->zdim; + + float * array = (float*)ImageIO_alloc (dimx * dimy * dimz *sizeof(float)); + if (array == NULL ) { + fprintf ( stderr, "allocation error\n" ); + return; + } + + CGAL_IMAGE_IO_CASE + (image, + Word * typedArray = (Word *)(image->data); + for(unsigned int i = 0; idata ); + image->data = array; + + image->wordKind = WK_FLOAT; + image->wdim = 4; +} + diff --git a/CGAL_ImageIO/include/CGAL/Image_3.h b/CGAL_ImageIO/include/CGAL/Image_3.h index 3ae3164931a..e1846e174ab 100644 --- a/CGAL_ImageIO/include/CGAL/Image_3.h +++ b/CGAL_ImageIO/include/CGAL/Image_3.h @@ -490,10 +490,12 @@ Image_3::labellized_trilinear_interpolation(const Coord_type& x, } // end namespace CGAL +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY #if defined(BOOST_MSVC) # pragma warning(pop) #endif - #endif // CGAL_IMAGE_3_H diff --git a/CGAL_ImageIO/include/CGAL/Image_3_impl.h b/CGAL_ImageIO/include/CGAL/Image_3_impl.h new file mode 100644 index 00000000000..7fda2193521 --- /dev/null +++ b/CGAL_ImageIO/include/CGAL/Image_3_impl.h @@ -0,0 +1,232 @@ +// Copyright (c) 2005-2008 INRIA Sophia-Antipolis (France). +// 2008 GeometryFactory, Sophia Antipolis (France) +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Laurent Rineau, Pierre Alliez + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include + +namespace CGAL { + +CGAL_INLINE_FUNCTION +bool Image_3::private_read(_image* im) +{ + if(im != 0) + { + if(image() != 0) + { + ::_freeImage(image()); + } + image_ptr = Image_shared_ptr(im, Image_deleter()); + +// std::cerr << +// boost::format("image=%1% (xdim=%2%, ydim=%3%, zdim=%4%)\n") +// % image_ptr.get() % image_ptr->xdim % image_ptr->ydim % image_ptr->zdim; + + } + return im != 0; +} + +CGAL_INLINE_FUNCTION +void Image_3::gl_draw(const float point_size, + const unsigned char r, + const unsigned char g, + const unsigned char b) +{ + if(image_ptr.get() == NULL) + return; + + glPointSize(point_size); + glColor3ub(r,g,b); + glBegin(GL_POINTS); + unsigned char *pData = (unsigned char*)image_ptr->data; + unsigned int xy = image_ptr->xdim * image_ptr->ydim; + for(unsigned int i=0;ixdim;i+=5) + for(unsigned int j=0;jydim;j+=5) + for(unsigned int k=0;kzdim;k+=5) + { + unsigned char value = pData[xy*k + j*image_ptr->xdim + i]; + if(value > 0) + { + double x = image_ptr->vx * i; + double y = image_ptr->vy * j; + double z = image_ptr->vz * k; + glVertex3d(x,y,z); + } + } + glEnd(); +} // end Image_3::gl_draw + + +CGAL_INLINE_FUNCTION +void Image_3::gl_draw_bbox(const float line_width, + const unsigned char red, + const unsigned char green, + const unsigned char blue) +{ + if(!image_ptr) + return; + + glLineWidth(line_width); + glColor3ub(red,green,blue); + glBegin(GL_LINES); + + struct Point { + double x_; + double y_; + double z_; + Point(double x, double y, double z) : x_(x), y_(y), z_(z) {}; + + double x() const { return x_; } + double y() const { return y_; } + double z() const { return z_; } + }; + + const double xmax = (image_ptr->xdim - 1.0)*(image_ptr->vx); + const double ymax = (image_ptr->ydim - 1.0)*(image_ptr->vy); + const double zmax = (image_ptr->zdim - 1.0)*(image_ptr->vz); + + Point a(0.0, 0.0, 0.0); + Point b(0.0, ymax, 0.0); + Point c(0.0, ymax, zmax); + Point d(0.0, 0.0, zmax); + Point e(xmax, 0.0, 0.0); + Point f(xmax, ymax, 0.0); + Point g(xmax, ymax, zmax); + Point h(xmax, 0.0, zmax); + + glVertex3d(a.x(),a.y(),a.z()); + glVertex3d(b.x(),b.y(),b.z()); + + glVertex3d(b.x(),b.y(),b.z()); + glVertex3d(c.x(),c.y(),c.z()); + + glVertex3d(c.x(),c.y(),c.z()); + glVertex3d(d.x(),d.y(),d.z()); + + glVertex3d(d.x(),d.y(),d.z()); + glVertex3d(a.x(),a.y(),a.z()); + + glVertex3d(e.x(),e.y(),e.z()); + glVertex3d(f.x(),f.y(),f.z()); + + glVertex3d(f.x(),f.y(),f.z()); + glVertex3d(g.x(),g.y(),g.z()); + + glVertex3d(g.x(),g.y(),g.z()); + glVertex3d(h.x(),h.y(),h.z()); + + glVertex3d(h.x(),h.y(),h.z()); + glVertex3d(e.x(),e.y(),e.z()); + + glVertex3d(a.x(),a.y(),a.z()); + glVertex3d(e.x(),e.y(),e.z()); + + glVertex3d(d.x(),d.y(),d.z()); + glVertex3d(h.x(),h.y(),h.z()); + + glVertex3d(c.x(),c.y(),c.z()); + glVertex3d(g.x(),g.y(),g.z()); + + glVertex3d(b.x(),b.y(),b.z()); + glVertex3d(f.x(),f.y(),f.z()); + + glEnd(); +} // end Image_3::gl_draw_bbox + +} // end namespace CGAL + +#ifdef CGAL_USE_VTK + +#include +#include + +namespace CGAL { + +namespace { + +struct VTK_to_ImageIO_type_mapper { + WORD_KIND wordKind; + SIGN sign; + unsigned int wdim; +}; + +static const VTK_to_ImageIO_type_mapper VTK_to_ImageIO_type[VTK_ID_TYPE] = + { { WK_UNKNOWN, SGN_UNKNOWN, 0}, // 0=VTK_VOID + { WK_UNKNOWN, SGN_UNKNOWN, 0}, // 1=VTK_BIT + { WK_FIXED, SGN_SIGNED, 1}, // 2=VTK_CHAR + { WK_FIXED, SGN_UNSIGNED, 1}, // 3=VTK_UNSIGNED_CHAR + { WK_FIXED, SGN_SIGNED, 2}, // 4=VTK_SHORT + { WK_FIXED, SGN_UNSIGNED, 2}, // 5=VTK_UNSIGNED_SHORT + { WK_FIXED, SGN_SIGNED, 4}, // 6=VTK_INT + { WK_FIXED, SGN_UNSIGNED, 4}, // 7=VTK_UNSIGNED_INT + { WK_FIXED, SGN_SIGNED, 8}, // 8=VTK_LONG + { WK_FIXED, SGN_UNSIGNED, 8}, // 9=VTK_UNSIGNED_LONG + { WK_FLOAT, SGN_SIGNED, 4}, // 10=VTK_FLOAT + { WK_FIXED, SGN_SIGNED, 8} // 11=VTK_DOUBLE + }; + +} //end anonymous namespace + +CGAL_INLINE_FUNCTION +bool +Image_3::read_vtk_image_data(vtkImageData* vtk_image) +{ + if(!vtk_image) + return false; + + _image* image = ::_initImage(); + const int* dims = vtk_image->GetDimensions(); + const double* spacing = vtk_image->GetSpacing(); + image->vectMode = VM_SCALAR; + image->xdim = dims[0]; + image->ydim = dims[1]; + image->zdim = dims[2]; + image->vdim = 1; + image->vx = spacing[0]; + image->vy = spacing[1]; + image->vz = spacing[2]; + vtk_image->Update(); + image->endianness = ::_getEndianness(); + int vtk_type = vtk_image->GetScalarType(); + if(vtk_type == VTK_SIGNED_CHAR) vtk_type = VTK_CHAR; + if(vtk_type < 0 || vtk_type > VTK_DOUBLE) + vtk_type = VTK_DOUBLE; + const VTK_to_ImageIO_type_mapper& imageio_type = + VTK_to_ImageIO_type[vtk_type]; + image->wdim = imageio_type.wdim; + image->wordKind = imageio_type.wordKind; + image->sign = imageio_type.sign; + image->data = ::ImageIO_alloc(dims[0]*dims[1]*dims[2]*image->wdim); + std::cerr << "GetNumberOfTuples()=" << vtk_image->GetPointData()->GetScalars()->GetNumberOfTuples() + << "\nimage->size()=" << dims[0]*dims[1]*dims[2] + << "\nwdim=" << image->wdim << '\n'; + assert(vtk_image->GetPointData()->GetScalars()->GetNumberOfTuples() == dims[0]*dims[1]*dims[2]); + vtk_image->GetPointData()->GetScalars()->ExportToVoidPointer(image->data); + + return this->private_read(image); +} + +} // end namespace CGAL + +#endif // CGAL_USE_VTK diff --git a/CGAL_ImageIO/include/CGAL/Image_3_vtk_interface.h b/CGAL_ImageIO/include/CGAL/Image_3_vtk_interface.h index 89b4bd7ea03..a58eb24418e 100644 --- a/CGAL_ImageIO/include/CGAL/Image_3_vtk_interface.h +++ b/CGAL_ImageIO/include/CGAL/Image_3_vtk_interface.h @@ -21,7 +21,7 @@ #ifndef CGAL_IMAGE_3_VTK_INTERFACE_H #define CGAL_IMAGE_3_VTK_INTERFACE_H -#include +#include "config.h" #ifdef CGAL_USE_VTK #include diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/CMakeLists.txt b/CGAL_ImageIO/src/CGAL_ImageIO/CMakeLists.txt index ae175c265f1..795e89ac10d 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/CMakeLists.txt +++ b/CGAL_ImageIO/src/CGAL_ImageIO/CMakeLists.txt @@ -47,7 +47,7 @@ if(OPENGL_FOUND) use_essential_libs() - include_directories( SYSTEM ${CGAL_3RD_PARTY_INCLUDE_DIRS} ${CGAL_ImageIO_3RD_PARTY_INCLUDE_DIRS} ) + include_directories( SYSTEM ${CGAL_3RD_PARTY_INCLUDE_DIRS} ${CGAL_ImageIO_3RD_PARTY_INCLUDE_DIRS} .) link_directories ( ${CGAL_LIBRARIES_DIR} ${CGAL_3RD_PARTY_LIBRARIES_DIRS} ) diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/ImageIO.cpp b/CGAL_ImageIO/src/CGAL_ImageIO/ImageIO.cpp index 9198b14a801..8142f0b55e8 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/ImageIO.cpp +++ b/CGAL_ImageIO/src/CGAL_ImageIO/ImageIO.cpp @@ -19,1568 +19,9 @@ // $Id$ // -#ifdef _MSC_VER -// Suppress deprecated warning for fileno and strdup -# pragma warning(disable:4996) - -#include -#include -#include -#include -#include -#endif - -#include -#include -#include -#include +#ifndef CGAL_HEADER_ONLY #include +#include -/* formats actuellement lus - - format | extension(s) | lecture | ecriture - INRIMAGE | .inr[.gz] | X | X -> + .gradient[.gz] + .gradient_direction[.gz] - GIS | .dim, .ima[.gz] | X | X - ANALYZE | .hdr, .img[.gz] | X | X - PNM | .ppm, .pgm | X | X - GIF | .gif | X | - BMP | .gif | X | -*/ -#include "inr.h" -#include "gif.h" -#include "gis.h" -#include "pnm.h" -#include "bmp.h" -#include "iris.h" -#include "analyze.h" -#ifdef MINC_FILES -# include "mincio.h" -#endif - - - -/** the first file format is initialized to null */ -static PTRIMAGE_FORMAT firstFormat=NULL; - -/** the Inrimage file format (default format) is initialized to null */ -static PTRIMAGE_FORMAT InrimageFormat=NULL; - - - - - -/*-------------------------------------------------- - * - * mimics standard routines - * - --------------------------------------------------*/ - - - -extern "C" { - /* default allocation routine */ - static void *(*allocRoutine)(size_t) = 0; - /* default deallocation routine */ - static void (*deleteRoutine)(void *) = 0; -} - -void *ImageIO_alloc(size_t s) { - if(!allocRoutine) allocRoutine = malloc; - return ( (*allocRoutine)(s) ); -} -/* call allocation routine */ -void ImageIO_free(void *m) { - if(!deleteRoutine) deleteRoutine = free; - (*deleteRoutine)(m); -} -/* call deallocation routine */ - - - -/* mimics fwrite() function. - According to _openWriteImage(), openMode will has one - of the following value: - - OM_STD (for stdout) - - OM_GZ - - OM_FILE -*/ -size_t ImageIO_write(const _image *im, const void *buf, size_t len) { - - switch(im->openMode) { - default : - case OM_CLOSE : - return 0; - case OM_STD : -#ifdef CGAL_USE_ZLIB - return gzwrite(im->fd, (void *) buf, len); -#else - return fwrite(buf, 1, len, im->fd); -#endif -#ifdef CGAL_USE_ZLIB - case OM_GZ : - return gzwrite(im->fd, (void *) buf, len); -#endif - case OM_FILE: - return fwrite(buf, 1, len, (FILE*)im->fd); - } - //return 0; -} - - - -/* mimics fread() function. - According to _openReadImage(), openMode will has one - of the following value: - - OM_STD (for stdin) - - OM_GZ *or* OM_FILE -*/ -size_t ImageIO_read(const _image *im, void *buf, size_t len) -{ - size_t to_be_read = len; - int l = -1; - char *b = (char*)buf; - - switch(im->openMode) { - default : - case OM_CLOSE : - return 0; - case OM_STD : -#ifdef CGAL_USE_ZLIB - while ( (to_be_read > 0) && ((l = gzread(im->fd, (void *) b, to_be_read)) > 0) ) { - to_be_read -= l; - b += l; - } -#else - while ( (to_be_read > 0) && ((l = fread( b, 1, to_be_read, im->fd )) > 0) ) { - to_be_read -= l; - b += l; - } -#endif - return ( len - to_be_read ); -#ifdef CGAL_USE_ZLIB - case OM_GZ : - while ( (to_be_read > 0) && ((l = gzread(im->fd, (void *) b, to_be_read)) > 0) ) { - to_be_read -= l; - b += l; - } - if(l<0) - { - int errnum; - fprintf(stderr, "zlib error: %s\n", gzerror(im->fd, &errnum)); - } - return ( len - to_be_read ); -#else - case OM_FILE : - while ( (to_be_read > 0) && ((l = fread( b, 1, to_be_read, im->fd )) > 0) ) { - to_be_read -= l; - b += l; - } - return ( len - to_be_read ); -#endif - } - - //return 0; -} - - - -/* mimics fgets() function. - According to _openReadImage(), openMode will has one - of the following value: - - OM_STD (for stdout) - - OM_GZ *or* OM_FILE -*/ -char *ImageIO_gets( const _image *im, char *str, int size ) -{ - char *ret = NULL; - switch(im->openMode) { - default : - case OM_CLOSE : - return NULL; - case OM_STD : -#ifdef CGAL_USE_ZLIB - ret = (char *) gzgets(im->fd, str, size ); -#else - ret = fgets(str, size, im->fd); -#endif - break; -#ifdef CGAL_USE_ZLIB - case OM_GZ : - ret = (char *) gzgets(im->fd, str, size); - break; -#else - case OM_FILE : - ret = fgets(str, size, im->fd); - break; -#endif - } - return ret; -} - - - -int ImageIO_seek( const _image *im, long offset, int whence ) { - switch(im->openMode) { - case OM_CLOSE : - default : - return -1; -#ifdef CGAL_USE_ZLIB - case OM_GZ: - return gzseek(im->fd, offset, whence ); -#endif - case OM_FILE: - return fseek( (FILE*)im->fd, offset, whence ); - } -} - -/* return non 0 in case of error - */ -int ImageIO_error( const _image *im ) -{ - switch(im->openMode) { - case OM_CLOSE : - default : - return 0; -#ifdef CGAL_USE_ZLIB - case OM_GZ : - static int errnum; - (void)gzerror(im->fd, &errnum); - return( (errnum != Z_OK) || gzeof(im->fd) ); -#endif - case OM_FILE : - return( ferror( (FILE*)im->fd ) || feof( (FILE*)im->fd ) ); - } - //return 0; -} - - - -/* Upon successful completion 0 is returned. - - Closing the standard output with gzclose() - is necessary as it will flush the pending output. - */ -int ImageIO_close( _image* im ) -{ - int ret=0; - - switch ( im->openMode ) { - default : - case OM_CLOSE : - break; -#ifdef CGAL_USE_ZLIB - case OM_GZ : - case OM_STD : - ret = gzclose( im->fd ); - break; -#else - case OM_STD : - break; -#endif - case OM_FILE : - ret = fclose( (FILE*)im->fd ); - } - im->fd = NULL; - im->openMode = OM_CLOSE; - - return ret; -} - - - - - - - -/* given an initialized file descriptor and a file name, - open file from stdin (if name == NULL, or name == "-", or name == "<"), - or a standard/gzipped file otherwise (gzipped files are handled assuming - that it is compiled and linked with zlib). - openMode will have one of the following value: - - OM_STD (for stdin) - - OM_GZ *or* OM_FILE -*/ -void _openReadImage(_image* im, const char *name) { - if(im->openMode == OM_CLOSE) { - - /* open from stdin */ - if( name == NULL || name[0] == '\0' - || (name[0] == '-' && name[1] == '\0') - || (name[0] == '<' && name[1] == '\0') ) { -#ifdef CGAL_USE_ZLIB - im->fd = gzdopen(fileno(stdin), "rb"); -#else - im->fd = fdopen(fileno(stdin), "rb"); -#endif - im->openMode = OM_STD; - } - - else { -#ifdef CGAL_USE_ZLIB - im->fd = gzopen(name, "rb"); - if(im->fd) im->openMode = OM_GZ; -#else - im->fd = fopen(name, "rb"); - if(im->fd) im->openMode = OM_FILE; -#endif - - } - - } -} - - - - - -/* given an initialized file descriptor and a file name, - open file from stdout (if name == NULL, or name == "-", or name == ">"), - a gzipped pipe (if name got the extension ".gz") - or a standard file otherwise. - openMode will have one of the following value: - - OM_STD (for stdout) - - OM_GZ - - OM_FILE -*/ -void _openWriteImage(_image* im, const char *name) -{ - im->openMode = OM_CLOSE; - - if( name == NULL || name[0] == '\0' - || (name[0] == '-' && name[1] == '\0') - || (name[0] == '>' && name[1] == '\0') ) { - -#ifdef CGAL_USE_ZLIB -#if (defined _LINUX_) || (defined _SOLARIS_) || (defined _SGI_) - im->fd = gzdopen(1, "wb"); -#else - im->fd = gzdopen(fileno(stdout), "wb"); -#endif -#else - im->fd = (_ImageIO_file) stdout; -#endif - im->openMode = OM_STD; - } - - else{ -#ifdef CGAL_USE_ZLIB - - /* from gzopen() doc: - ... The mode parameter is as in fopen ("rb" or "wb") but can - also include a compression level ("wb9") or a strategy: 'f' for - filtered data as in "wb6f", 'h' for Huffman only compression as - in "wb1h" ... - However, a small .gz header will be written ... thus gz(d)open can not - be used for rgular files. - */ - - if( !strncmp(name+strlen(name)-3, ".gz", 3) ) - { -#ifdef _MSC_VER - int ffd=_open(name,_O_RDWR | _O_CREAT| _O_TRUNC | _O_BINARY, _S_IREAD|_S_IWRITE); - im->fd = gzdopen( ffd, "wb" ); -#else - im->fd = gzopen( name, "wb" ); -#endif - im->openMode = OM_GZ; - } - else -#endif - { - im->fd = (_ImageIO_file) fopen(name, "wb"); - im->openMode = OM_FILE; - } - } -} - - - -/* set allocation and deallocation routines */ -void setImageIOAllocationRoutines(ALLOCATION_FUNCTION alloc, - DEALLOCATION_FUNCTION del) { - if(alloc != NULL) allocRoutine = alloc; - if(del != NULL) deleteRoutine = del; -} - - - - - -/*-------------------------------------------------- - * - * - * - --------------------------------------------------*/ - - - - - -ENDIANNESS _getEndianness() -{ - union { - unsigned char uc[2]; - unsigned short us; - } twobytes; - twobytes.us = 255; - /* on linux or dec - */ - if ( twobytes.uc[1] == 0 ) return( END_LITTLE ); - /* on solaris or sgi - */ - return( END_BIG ); -} - - - - - - - -/* Allocates and initializes an image descriptor */ -_image *_initImage() { - _image *im; - - im = (_image *) ImageIO_alloc(sizeof(_image)); - if ( im == NULL ) return( im ); - - /* default image size is 1*1*1 */ - im->xdim = im->ydim = im->zdim = im->vdim = 1; - /* default image voxel size is 1.0*1.0*1.0 */ - im->vx = im->vy = im->vz = 1.0; - - /* default image center is 0 0 0 */ - im->cx = im->cy = im->cz = 0; - - /* default image offset is 0 0 0 */ - im->tx = im->ty = im->tz = 0.0; - - /* default image rotation is 0 0 0 */ - im->rx = im->ry = im->rz = 0.0; - - /* no data yet */ - im->data = NULL; - - /* no file associated to image */ - im->fd = NULL; - im->openMode = OM_CLOSE; - im->endianness = END_UNKNOWN; - - /* unknown data kind - default is binary - */ - im->dataMode = DM_BINARY; - - /* no user string */ - im->user = NULL; - im->nuser = 0; - - /* unknown word kind */ - im->wdim = 0; - im->wordKind = WK_UNKNOWN; - im->vectMode = VM_SCALAR; - im->sign = SGN_UNKNOWN; - im->imageFormat = NULL; - - /** eventually initializes the supported file formats */ - if (firstFormat==NULL) - initSupportedFileFormat(); - /* return image descriptor */ - return im; -} - -_image *_createImage(int x, int y, int z, int v, - float vx, float vy, float vz, int w, - WORD_KIND wk, SIGN sgn) -{ - _image *im; - - im = (_image *) ImageIO_alloc(sizeof(_image)); - if ( im == NULL ) return( im ); - - im->xdim = x; - im->ydim = y; - im->zdim = z; - im->vdim = v; - im->vx = vx; - im->vy = vy; - im->vz = vz; - - /* default image center is 0 0 0 */ - im->cx = im->cy = im->cz = 0; - - /* default image offset is 0 0 0 */ - im->tx = im->ty = im->tz = 0.0; - - /* default image rotation is 0 0 0 */ - im->rx = im->ry = im->rz = 0.0; - - /* no data yet */ - im->data = ImageIO_alloc(x*y*z*v*w); - - /* no file associated to image */ - im->fd = NULL; - im->openMode = OM_CLOSE; - im->endianness = END_UNKNOWN; - - /* unknown data kind - default is binary - */ - im->dataMode = DM_BINARY; - - /* no user string */ - im->user = NULL; - im->nuser = 0; - - /* unknown word kind */ - im->wdim = w; - im->wordKind = wk; - im->vectMode = VM_SCALAR; - im->sign = sgn; - im->imageFormat = NULL; - - /** eventually initializes the supported file formats */ - if (firstFormat==NULL) - initSupportedFileFormat(); - /* return image descriptor */ - return im; -} - -/* return the bounding box of the image */ -void _get_image_bounding_box(_image* im, - double* x_min, double* y_min, double* z_min, - double* x_max, double* y_max, double* z_max) { - *x_min = im->tx; - *y_min = im->ty; - *z_min = im->tz; - *x_max = (im->xdim - 1.0f)*(im->vx) + *x_min ; - *y_max = (im->ydim - 1.0f)*(im->vy) + *y_min ; - *z_max = (im->zdim - 1.0f)*(im->vz) + *z_min ; -} - -/* Free an image descriptor */ -void _freeImage(_image *im) { - unsigned int i; - - if ( im == NULL ) return; - - /* close image if opened */ - if(im->openMode != OM_CLOSE) ImageIO_close(im); - - /* free data if any */ - if(im->data != NULL) ImageIO_free(im->data); - im->data = NULL; - - /* free user string array if any */ - if( (im->nuser > 0) && (im->user != NULL) ) { - for(i = 0; i < im->nuser; i++) - if ( im->user[i] != NULL ) ImageIO_free(im->user[i]); - ImageIO_free(im->user); - } - im->nuser = 0; - im->user = NULL; - - /* free given descriptor */ - ImageIO_free(im); -} - - - - - -/* Reads an image from a file and returns an image descriptor or NULL if - reading failed. - Reads from stdin if image name is NULL. */ -_image* _readImage(const char *name) { - _image *im; - - - /* read header */ - im = _readImageHeader( name ); - - if(im != NULL && im->openMode != OM_CLOSE) { - /* read body */ - if(_readImageData(im) < 0) { - fprintf(stderr, "_readImage: error: invalid data encountered in \'%s\'\n", - name); - _freeImage(im); - return NULL; - } - ImageIO_close(im); - } - - return im; -} - -// raw -_image* _readImage_raw(const char *name, - const unsigned int rx, - const unsigned int ry, - const unsigned int rz, - const double vx, - const double vy, - const double vz, - const unsigned int offset) -{ - _image *im = NULL; - im = (_image *) ImageIO_alloc(sizeof(_image)); - if ( im == NULL ) - return NULL; - - im->xdim = rx; - im->ydim = ry; - im->zdim = rz; - im->vdim = 1; - im->vx = vx; - im->vy = vy; - im->vz = vz; - - // image center - im->cx = im->cy = im->cz = 0; - - // image offset - im->tx = im->ty = im->tz = 0.0; - - // image rotation - im->rx = im->ry = im->rz = 0.0; - - - im->fd = NULL; - im->openMode = OM_CLOSE; - im->endianness = END_UNKNOWN; - - im->dataMode = DM_BINARY; - - // no user string - im->user = NULL; - im->nuser = 0; - - // word type (unsigned byte) - im->wdim = 1; - im->wordKind = WK_FIXED; - im->vectMode = VM_SCALAR; - im->sign = SGN_UNSIGNED; - im->imageFormat = NULL; - - // read file - ::_openReadImage(im, name); - if(!im->fd) { - fprintf(stderr, "_readImage_raw: error: unable to open file \'%s\'\n", name); - _freeImage(im); - return NULL; - } - - // read offset - if(offset > 0) { - im->data = ImageIO_alloc(offset+1); - ImageIO_read(im, im->data, offset); - ImageIO_free(im->data); - } - // allocate memory - im->data = ImageIO_alloc(rx*ry*rz); - if(im->data == NULL) - return NULL; - - // read - ImageIO_read(im, im->data, rx*ry*rz); - - ImageIO_close(im); - /* - unsigned int i,j,k; - unsigned char *data = (unsigned char *)im->data; - int dimxy = rx * ry; - for(i=0;i - reading failed.
- Reads from stdin if image name is NULL. - If the image is vectorial, it is uninterlaced. */ -_image* _readNonInterlacedImage(const char *name) { - _image *im; - - /* read header */ - im = _readImageHeader(name); - - if(im && im->openMode != OM_CLOSE) { - /* read scalar image body */ - if(im->vdim == 1) { - if(_readImageData(im) < 0) { - fprintf(stderr, "_readImage: error: invalid data encountered in \'%s\'\n", - name); - _freeImage(im); - return NULL; - } - } - /* read vectorial image body */ - else { - im->vectMode = VM_NON_INTERLACED; - if(_readNonInterlacedImageData(im) < 0) { - fprintf(stderr, "_readImage: error: invalid data encountered in \'%s\'\n", - name); - _freeImage(im); - return NULL; - } - } - ImageIO_close(im); - } - - return im; -} - - - - - - - - - - - -/* Write inrimage given in inr in file name. If file name's suffix is - .gz, the image is gziped. If file name's suffix is .hdr, the image - is written in ANALYZE format. If file name is NULL, image is written - on stdout */ -int _writeImage(_image *im, const char *name_to_be_written ) { - - int r = ImageIO_NO_ERROR; - int length = 0; - char *name = NULL; - char *baseName = NULL; - - if ( im == NULL ) return -1; - - /* different conventions for the standard input - */ - if ( name_to_be_written == NULL || name_to_be_written[0] == '\0' - || (name_to_be_written[0] == '-' && name_to_be_written[1] == '\0') - || (name_to_be_written[0] == '>' && name_to_be_written[1] == '\0') ) { - name = NULL; - } - else { - name = strdup( name_to_be_written ); - } - - initSupportedFileFormat(); - - /* what is the wanted format - */ - if ( name == NULL ) { - im->imageFormat = InrimageFormat; - } else { - int i,extLength; - PTRIMAGE_FORMAT f; - char ext[IMAGE_FORMAT_NAME_LENGTH]; - char *ptr; - - - /* scan all formats; */ - im->imageFormat=NULL; - length=strlen(name); - - for(f=firstFormat;(f!=NULL)&& (im->imageFormat==NULL);f=f->next) { - /* scan all extensions for that format */ - ptr=&f->fileExtension[0]; - - do { - /* get next file extension */ - i=0; - for(i=0;((*ptr)!=',' && (*ptr)!='\0');i++,ptr++) { - ext[i]=(*ptr); - } - if ((*ptr)==',') { - ext[i]='\0'; - ptr++; - } - else { - ext[i]='\0'; - } - extLength=strlen(ext); - - /* test if the tail of name matches the extension */ - if ( (length > extLength) && (!strcmp( name + length - extLength, ext)) ) { - im->imageFormat=f; - /* copy original name and removes extension */ - baseName=strdup(name); - for(i= length - extLength;iimageFormat==NULL)); - } - - if (!im->imageFormat) { - fprintf(stderr, "_writeImage: warning : unknown extension in %s = assuming Inrimage\n",name); - im->imageFormat=InrimageFormat; - baseName=strdup(name); - } - } - - - /* open file descriptor */ - /* _openWriteImage( im, name ) ; - - - - if(!im->fd) { - fprintf(stderr, "_writeImage: error: open failed\n"); - if ( name != NULL ) free( name ); - if ( baseName != NULL ) free( baseName ); - return ImageIO_OPENING; - } - */ - - if (im->imageFormat) { - - if (im->imageFormat->writeImage==NULL) { - im->imageFormat=InrimageFormat; - } - - if ( 0 ) { - fprintf(stderr, "_writeImage: will write '%s' with '%s' format\n", - name, im->imageFormat->realName ); - } - - if ((*im->imageFormat->writeImage)(name, im)<0) { - fprintf(stderr, "_writeImage: error: unable to write \'%s\'\n", - name); - r = ImageIO_WRITING_HEADER; - } - - } - - - - /* close file descriptor */ - ImageIO_close( im ); - - im->fd = NULL; - im->openMode = OM_CLOSE; - - if ( baseName != NULL ) free( baseName ); - if ( name != NULL ) free( name ); - - return r; -} - - - - - - - - - - - - -/* read header from an image file - - if standard input, it's an inrimage - if not, get a magic string - and try to find the good format - - if data are in a separate file, - the header reading procedure will open - the data file. - - error: - 0 success - -1 unknown image type - -2 error while opening - -3 error while reading header - -4 error while reading header or data - */ -_image *_readImageHeader( const char *name ) { - int error = 0; - return( _readImageHeaderAndGetError( name, &error ) ); -} - - - -_image *_readImageHeaderAndGetError( const char *name_to_be_read, int *error ) -{ - _image *im; - char magic[5]; - char *name = NULL; - PTRIMAGE_FORMAT f; - int res; - - *error = ImageIO_NO_ERROR; - - /* open image file */ - im = _initImage(); - if ( name_to_be_read == NULL || name_to_be_read[0] == '\0' - || (name_to_be_read[0] == '-' && name_to_be_read[1] == '\0') - || (name_to_be_read[0] == '<' && name_to_be_read[1] == '\0') ) { - name = NULL; - } - else { - name = strdup( name_to_be_read ); - } - - - _openReadImage(im, name); - - if(!im->fd) { - fprintf(stderr, "_readImageHeaderAndGetError: error: unable to open file \'%s\'\n", name); - _freeImage(im); - *error = ImageIO_OPENING; - if ( name != NULL ) free( name ); - return NULL; - } - - initSupportedFileFormat(); - - /* what is the wanted format ? - assume that stdin is inrimage - */ - if(im->openMode == OM_STD) { - im->imageFormat=InrimageFormat; - } - else { - /* get magic string for disk files - */ - ImageIO_read(im, magic, 4); - magic[4] = '\0'; - ImageIO_seek(im, 0L, SEEK_SET); - /** test each format */ - for(f=firstFormat;(f!=NULL)&& (im->imageFormat==NULL);f=f->next) { - /* test if it is the correct format based on magic and file extension */ - if (((*f->testImageFormat)(magic, name)) >=0) { - im->imageFormat=f; - } - } - } - - if ( im->imageFormat == NULL ) { - fprintf(stderr, "_readImageHeaderAndGetError: does not find image format for \'%s\'\n", name); - ImageIO_close( im ); - _freeImage(im); - *error = ImageIO_UNKNOWN_TYPE; - if ( name != NULL ) free( name ); - return NULL; - } - - /* now tests if the header can be read correctly */ - - res=(*(im->imageFormat)->readImageHeader)(name,im); - /* could read header only */ - if (res == 0) { - if ( name != NULL ) free( name ); - return( im ); - } - /* could read header and data */ - else if ( res > 0 ) { - ImageIO_close(im); - if ( name != NULL ) free( name ); - return im; - } - - /* could not read error : throw error */ - fprintf(stderr, "_readImageHeaderAndGetError: an error occurs when reading image\n" ); - if ( name == NULL || im->openMode == OM_STD) { - fprintf(stderr, "\t from \'standard input\'" ); - } - else { - fprintf(stderr, "\t from file \'%s\'", name ); - } - fprintf(stderr, " using format \'%s\'\n", (im->imageFormat)->realName ); - ImageIO_close( im ); - _freeImage(im); - *error = ImageIO_READING_HEADER; - if ( name != NULL ) free( name ); - return NULL; - -} - - - - - - - -static void _swapImageData( _image *im ) -{ - unsigned char *ptr1, *ptr2, b[8]; - unsigned short int si, *ptr3, *ptr4; - unsigned int i, *ptr5, *ptr6; - int size, length; - - if( _getEndianness() != im->endianness) { - - size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim; - if ( size <= 0 ) return; - - length = size / im->wdim; - ptr1 = ptr2 = (unsigned char *) im->data; - - /* 2 bytes swap */ - if(im->wdim == 2) { - /* - while(length--) { - b[0] = *ptr1++; - b[1] = *ptr1++; - *ptr2++ = b[1]; - *ptr2++ = b[0]; - } - */ - ptr3 = ptr4 = (unsigned short int *) im->data; - while( length-- ) { - si = *ptr3++; - *ptr4++ = ((si >> 8) & 0xff) | (si << 8); - } - } - - /* 4 bytes swap */ - else if(im->wdim == 4) { - /* - while(length--) { - b[0] = *ptr1++; - b[1] = *ptr1++; - b[2] = *ptr1++; - b[3] = *ptr1++; - *ptr2++ = b[3]; - *ptr2++ = b[2]; - *ptr2++ = b[1]; - *ptr2++ = b[0]; - } - */ - ptr5 = ptr6 = (unsigned int *) im->data; - while( length-- ) { - i = *ptr5++; - *ptr6++ = (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | ((i >> 24) & 0xff); - } - } - /* 8 bytes swap */ - else if(im->wdim == 8) { - while(length--) { - b[0] = *ptr1++; - b[1] = *ptr1++; - b[2] = *ptr1++; - b[3] = *ptr1++; - b[4] = *ptr1++; - b[5] = *ptr1++; - b[6] = *ptr1++; - b[7] = *ptr1++; - *ptr2++ = b[7]; - *ptr2++ = b[6]; - *ptr2++ = b[5]; - *ptr2++ = b[4]; - *ptr2++ = b[3]; - *ptr2++ = b[2]; - *ptr2++ = b[1]; - *ptr2++ = b[0]; - } - } - } -} - - - - - - -/* Read data of an inrimage. - If im->data is not NULL, assume that the buffer was previously allocated - Swap bytes depending on the endianness and the current architecture */ -int _readImageData(_image *im) { - unsigned long size, nread; - - if(im->openMode != OM_CLOSE) { - size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim; - - if ( size <= 0 ) return -3; - - if(!im->data) { - im->data = (unsigned char *) ImageIO_alloc(size); - if(!im->data) return -2; - } - - nread = ImageIO_read(im, im->data, size); - if(nread != size) return -1; - - - /* architecture is big endian and data little endian - length = nb of points - */ - _swapImageData( im ); - - - } - - return 1; -} - - - - - -/* Read data of a vectorial inrimage, making the resulting buffer non- - inerlaced. - If im->data is not NULL, assume that the buffer was previously allocated - Swap bytes depending on the endianness and the current architecture. */ -int _readNonInterlacedImageData(_image *im) { - unsigned long size, nread; - unsigned char **vp, *buf; - unsigned int i, j, k, v, w; - - if(im->vdim == 1) return _readImageData(im); - - if(im->openMode != OM_CLOSE) { - size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim; - - if ( size <= 0 ) return -3; - - if(!im->data) { - im->data = (unsigned char *) ImageIO_alloc(size); - if(!im->data) return -2; - } - - vp = (unsigned char **) ImageIO_alloc(im->vdim * sizeof(unsigned char *)); - buf = (unsigned char *) ImageIO_alloc(im->vdim * im->wdim); - size = im->xdim * im->ydim * im->zdim * im->wdim; - for(v = 0; v < im->vdim; v++) - vp[v] = (unsigned char *) im->data + v * size; - - for(k = 0; k < im->zdim; k++) { - for(j = 0; j < im->ydim; j++) { - for(i = 0; i < im->xdim; i++) { - nread = ImageIO_read(im, buf, im->vdim * im->wdim); - if(nread != im->vdim * im->wdim) return -1; - for(v = 0; v < im->vdim; v++) - for(w = 0; w < im->wdim; w++) - *vp[v]++ = *buf++; - buf -= im->vdim * im->wdim; - } - } - } - - ImageIO_free(buf); - ImageIO_free(vp); - - /* architecture is big endian and data little endian */ - _swapImageData( im ); - - - /* reorder lines */ - /* no non-interlaced data for ANALYZE. But if ever... */ -/* if( im->imageFormat == IF_ANALYZE ) { */ -/* int v ; */ -/* int vdim = im->vdim ; */ -/* int lineSize = im->wdim * im->xdim ; */ -/* int vsize = lineSize * im->ydim * im->zdim ; */ -/* char* swapped = ImageIO_alloc(lineSize) ; */ -/* for( v = 0 ; v < vdim ; ++v ) */ -/* { */ -/* char* buf1 = (char*)im->data + v*vsize ; */ -/* char* buf2 = buf1 + vsize - lineSize ; */ - -/* while( buf1 < buf2 ) */ -/* { */ -/* memcpy( swapped, buf1, lineSize ) ; */ -/* memcpy( buf1, buf2, lineSize ) ; */ -/* memcpy( buf2, swapped, lineSize ) ; */ -/* buf1 += lineSize ; */ -/* buf2 -= lineSize ; */ -/* } */ - -/* ImageIO_free( swapped ) ; */ -/* } */ -/* } */ - } - - return 1; -} - - -/* Reads body from a non-interlaced vectorial inrimage whose header has - been read by _readImageHeader. The image buffer is interlaced. */ -int _readNonInterlacedFileData(_image *im) { - unsigned long size, nread; - unsigned char *ptr1, *vp, *buf; - unsigned int i, j, k, v, w; - - if(im->vdim == 1) return _readImageData(im); - - if(im->openMode != OM_CLOSE) { - size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim; - - if ( size <= 0 ) return -3; - - if(!im->data) { - im->data = (unsigned char *) ImageIO_alloc(size); - if(!im->data) return -2; - } - - size = im->xdim * im->ydim * im->zdim * im->wdim; - buf = ptr1 = (unsigned char *) ImageIO_alloc(size); - - for(v = 0; v < im->vdim; v++) { - buf = ptr1; - nread = ImageIO_read(im, buf, size); - if(nread != size) return -1; - vp = (unsigned char *) im->data + (v * im->wdim); - for(k = 0; k < im->zdim; k++) { - for(j = 0; j < im->ydim; j++) { - for(i = 0; i < im->xdim; i++) { - for(w = 0; w < im->wdim; w++) *vp++ = *buf++; - vp += (im->vdim - 1) * im->wdim; - } - } - } - } - - ImageIO_free(buf); - - /* architecture is big endian and data little endian */ - _swapImageData( im ); - - - /* reorder lines */ - /* no non-interlaced data for ANALYZE. But if ever... */ -/* if( im->imageFormat == IF_ANALYZE ) { */ -/* int v ; */ -/* int vdim = im->vdim ; */ -/* int lineSize = im->wdim * im->xdim ; */ -/* int vsize = lineSize * im->ydim * im->zdim ; */ -/* char* swapped = ImageIO_alloc(lineSize) ; */ -/* for( v = 0 ; v < vdim ; ++v ) */ -/* { */ -/* char* buf1 = (char*)im->data + v*vsize ; */ -/* char* buf2 = buf1 + vsize - lineSize ; */ - -/* while( buf1 < buf2 ) */ -/* { */ -/* memcpy( swapped, buf1, lineSize ) ; */ -/* memcpy( buf1, buf2, lineSize ) ; */ -/* memcpy( buf2, swapped, lineSize ) ; */ -/* buf1 += lineSize ; */ -/* buf2 -= lineSize ; */ -/* } */ - -/* ImageIO_free( swapped ) ; */ -/* } */ -/* } */ - } - - return 1; -} - - - - - - - - - - -/*-------------------------------------------------- - * - * ????? - * - --------------------------------------------------*/ - - - - - -/* check the type of image in fileName */ -PTRIMAGE_FORMAT imageType(const char *fileName) { - _ImageIO_file f; - char magic[5]; - PTRIMAGE_FORMAT format; - - if(!fileName) { -#ifdef CGAL_USE_ZLIB - f = gzdopen(fileno(stdin), "rb"); -#else - f = fdopen(fileno(stdin), "rb"); -#endif - } - else { -#ifdef CGAL_USE_ZLIB - f = gzopen(fileName, "rb"); -#else - f = fopen(fileName, "rb"); -#endif - } - - if(!f) return NULL; - -#ifdef CGAL_USE_ZLIB - gzread( f, (void *) magic, 4); -#else - fread( (void *) magic, 1, 4, f ); -#endif - - - magic[4] = '\0'; - -#ifdef CGAL_USE_ZLIB - gzclose( f ); -#else - if(fileName) fclose( f ); -#endif - - if (firstFormat==NULL) - initSupportedFileFormat(); - - for(format=firstFormat;(format!=NULL);format=format->next) { - /* test if it is the correct header based on magic and file extension */ - if (((*format->testImageFormat)(magic,fileName)) >=0) { - return format; - } - } - return 0; - -} - - - - - -/*-------------------------------------------------- - * - * Image Format Management - * - --------------------------------------------------*/ - - - - - -/** adds a format at the beginning of the list of image formats. - Test if all mandatory fields have been filled */ -int addImageFormat( PTRIMAGE_FORMAT format) -{ - if ( (format->testImageFormat) && - (format->readImageHeader) && - (strlen(format->fileExtension)>0) && - (strlen(format->realName)>0) ) { - - format->next=firstFormat; - firstFormat=format; - - return 0; - - } - else { - fprintf(stderr,"addImageFormat: information missing in file format %s\n", - format->realName); - return -1; - } -} - -/** adds a format at the end of the list of image formats. - Test if all mandatory fields have been filled */ -int addImageFormatAtEnd( PTRIMAGE_FORMAT format) -{ - PTRIMAGE_FORMAT f; - if ( (format->testImageFormat) && - (format->readImageHeader) && - (strlen(format->fileExtension)>0) && - (strlen(format->realName)>0) ) { - - format->next = NULL; - - if (firstFormat == NULL) { - firstFormat=format; - } - else { - for(f=firstFormat;(f->next!=NULL);f=f->next) - ; - f->next=format; - } - - return 0; - - } - else { - fprintf(stderr,"addImageFormatAtEnd: information missing in file format %s\n", - format->realName); - return -1; - } -} - - -/** creates supported image formats */ -void initSupportedFileFormat() -{ - PTRIMAGE_FORMAT f; - if ( InrimageFormat == NULL ) { - f = createAnalyzeFormat(); - addImageFormatAtEnd( f ); - f = createBMPFormat(); - addImageFormatAtEnd( f ); - f = createGifFormat(); - addImageFormatAtEnd( f ); - f = createGisFormat(); - addImageFormatAtEnd( f ); - f = createIrisFormat(); - addImageFormatAtEnd( f ); - f = createPgmFormat(); - addImageFormatAtEnd( f ); - f = createPgmAscIIFormat(); - addImageFormatAtEnd( f ); - f = createPpmFormat(); - addImageFormatAtEnd( f ); - InrimageFormat = createInrimageFormat(); - addImageFormat( InrimageFormat ); - } -} - - - -PTRIMAGE_FORMAT firstImageFormat() { - return firstFormat; -} - - - -/** prints supported image formats */ -void printSupportedFileFormat() { - PTRIMAGE_FORMAT f; - int i; - - initSupportedFileFormat(); - - for(i=0, f=firstFormat;(f!=NULL);i++, f=f->next) { - if ( (f->testImageFormat) && - (f->readImageHeader) && - (strlen(f->fileExtension)>0) && - (strlen(f->realName)>0)) { - fprintf( stderr, "#%2d: format name ='%s', extensions='%s'", - i, f->realName, f->fileExtension ); - if (f->readImageHeader) - fprintf( stderr, ", read" ); - if (f->writeImage) - fprintf( stderr, ", write" ); - fprintf( stderr, "\n" ); - } - } -} - - -/** remove supported image formats */ -void removeSupportedFileFormat() { - PTRIMAGE_FORMAT f=firstFormat; - - while( f != NULL) { - PTRIMAGE_FORMAT f_old = f; - f = f->next; - ImageIO_free( f_old); - } - InrimageFormat=NULL; - -} - - -/** trilinear interpolation in an _image float type - */ -float triLinInterp(const _image* image, - float posx, - float posy, - float posz, - float value_outside /*= 0.f */) -{ - const int dimx = image->xdim; - const int dimy = image->ydim; - const int dimz = image->zdim; - const int dimxy = dimx*dimy; - - if(posx < 0.f || posy < 0.f || posz < 0.f ) - return value_outside; - - posx = static_cast(posx /(image->vx)); - posy = static_cast(posy /(image->vy)); - posz = static_cast(posz /(image->vz)); - - //patch suggested by J.Cugnoni to prevent integer overflow - if(posz >= dimz-1 || posy >= dimy-1 || posx >= dimx-1) - return value_outside; - - const int i1 = (int)(posz); - const int j1 = (int)(posy); - const int k1 = (int)(posx); - - const int i2 = i1 + 1; - const int j2 = j1 + 1; - const int k2 = k1 + 1; - - const float KI2 = i2-posz; - const float KI1 = posz-i1; - const float KJ2 = j2-posy; - const float KJ1 = posy-j1; - - CGAL_IMAGE_IO_CASE - (image, - Word *array = (Word *) image->data; - return (((float)array[i1 * dimxy + j1 * dimx + k1] * KI2 + - (float)array[i2 * dimxy + j1 * dimx + k1] * KI1) * KJ2 + - ((float)array[i1 * dimxy + j2 * dimx + k1] * KI2 + - (float)array[i2 * dimxy + j2 * dimx + k1] * KI1) * KJ1) * (k2-posx)+ - (((float)array[i1 * dimxy + j1 * dimx + k2] * KI2 + - (float)array[i2 * dimxy + j1 * dimx + k2] * KI1) * KJ2 + - ((float)array[i1 * dimxy + j2 * dimx + k2] * KI2 + - (float)array[i2 * dimxy + j2 * dimx + k2] * KI1) * KJ1) * (posx-k1); - ); - return 0.f; -} - -// Gives the value of the image at pixel (i,j,k), converted in float. -float evaluate(const _image* image, - const std::size_t i, - const std::size_t j, - const std::size_t k) -{ - using CGAL::IMAGEIO::static_evaluate; - - CGAL_IMAGE_IO_CASE(image, return (float)static_evaluate(image, i, j, k); ); - - return 0.f; -} - -/** convert the data of the image to float -*/ -void convertImageTypeToFloat(_image* image){ - if(image->wordKind == WK_FLOAT && image->wdim == 4) - return; - - const unsigned int dimx = image->xdim; - const unsigned int dimy = image->ydim; - const unsigned int dimz = image->zdim; - - float * array = (float*)ImageIO_alloc (dimx * dimy * dimz *sizeof(float)); - if (array == NULL ) { - fprintf ( stderr, "allocation error\n" ); - return; - } - - CGAL_IMAGE_IO_CASE - (image, - Word * typedArray = (Word *)(image->data); - for(unsigned int i = 0; idata ); - image->data = array; - - image->wordKind = WK_FLOAT; - image->wdim = 4; -} - +#endif // CGAL_HEADER_ONLY diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/Image_3.cpp b/CGAL_ImageIO/src/CGAL_ImageIO/Image_3.cpp index e92bbca6e8f..e16e8601161 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/Image_3.cpp +++ b/CGAL_ImageIO/src/CGAL_ImageIO/Image_3.cpp @@ -18,205 +18,9 @@ // // Author(s) : Laurent Rineau, Pierre Alliez +#ifndef CGAL_HEADER_ONLY + #include -#include +#include -namespace CGAL { - -bool Image_3::private_read(_image* im) -{ - if(im != 0) - { - if(image() != 0) - { - ::_freeImage(image()); - } - image_ptr = Image_shared_ptr(im, Image_deleter()); - -// std::cerr << -// boost::format("image=%1% (xdim=%2%, ydim=%3%, zdim=%4%)\n") -// % image_ptr.get() % image_ptr->xdim % image_ptr->ydim % image_ptr->zdim; - - } - return im != 0; -} - -void Image_3::gl_draw(const float point_size, - const unsigned char r, - const unsigned char g, - const unsigned char b) -{ - if(image_ptr.get() == NULL) - return; - - glPointSize(point_size); - glColor3ub(r,g,b); - glBegin(GL_POINTS); - unsigned char *pData = (unsigned char*)image_ptr->data; - unsigned int xy = image_ptr->xdim * image_ptr->ydim; - for(unsigned int i=0;ixdim;i+=5) - for(unsigned int j=0;jydim;j+=5) - for(unsigned int k=0;kzdim;k+=5) - { - unsigned char value = pData[xy*k + j*image_ptr->xdim + i]; - if(value > 0) - { - double x = image_ptr->vx * i; - double y = image_ptr->vy * j; - double z = image_ptr->vz * k; - glVertex3d(x,y,z); - } - } - glEnd(); -} // end Image_3::gl_draw - - -void Image_3::gl_draw_bbox(const float line_width, - const unsigned char red, - const unsigned char green, - const unsigned char blue) -{ - if(!image_ptr) - return; - - glLineWidth(line_width); - glColor3ub(red,green,blue); - glBegin(GL_LINES); - - struct Point { - double x_; - double y_; - double z_; - Point(double x, double y, double z) : x_(x), y_(y), z_(z) {}; - - double x() const { return x_; } - double y() const { return y_; } - double z() const { return z_; } - }; - - const double xmax = (image_ptr->xdim - 1.0)*(image_ptr->vx); - const double ymax = (image_ptr->ydim - 1.0)*(image_ptr->vy); - const double zmax = (image_ptr->zdim - 1.0)*(image_ptr->vz); - - Point a(0.0, 0.0, 0.0); - Point b(0.0, ymax, 0.0); - Point c(0.0, ymax, zmax); - Point d(0.0, 0.0, zmax); - Point e(xmax, 0.0, 0.0); - Point f(xmax, ymax, 0.0); - Point g(xmax, ymax, zmax); - Point h(xmax, 0.0, zmax); - - glVertex3d(a.x(),a.y(),a.z()); - glVertex3d(b.x(),b.y(),b.z()); - - glVertex3d(b.x(),b.y(),b.z()); - glVertex3d(c.x(),c.y(),c.z()); - - glVertex3d(c.x(),c.y(),c.z()); - glVertex3d(d.x(),d.y(),d.z()); - - glVertex3d(d.x(),d.y(),d.z()); - glVertex3d(a.x(),a.y(),a.z()); - - glVertex3d(e.x(),e.y(),e.z()); - glVertex3d(f.x(),f.y(),f.z()); - - glVertex3d(f.x(),f.y(),f.z()); - glVertex3d(g.x(),g.y(),g.z()); - - glVertex3d(g.x(),g.y(),g.z()); - glVertex3d(h.x(),h.y(),h.z()); - - glVertex3d(h.x(),h.y(),h.z()); - glVertex3d(e.x(),e.y(),e.z()); - - glVertex3d(a.x(),a.y(),a.z()); - glVertex3d(e.x(),e.y(),e.z()); - - glVertex3d(d.x(),d.y(),d.z()); - glVertex3d(h.x(),h.y(),h.z()); - - glVertex3d(c.x(),c.y(),c.z()); - glVertex3d(g.x(),g.y(),g.z()); - - glVertex3d(b.x(),b.y(),b.z()); - glVertex3d(f.x(),f.y(),f.z()); - - glEnd(); -} // end Image_3::gl_draw_bbox - -} // end namespace CGAL - -#ifdef CGAL_USE_VTK - -#include -#include - -namespace CGAL { - -namespace { - -struct VTK_to_ImageIO_type_mapper { - WORD_KIND wordKind; - SIGN sign; - unsigned int wdim; -}; - -static const VTK_to_ImageIO_type_mapper VTK_to_ImageIO_type[VTK_ID_TYPE] = - { { WK_UNKNOWN, SGN_UNKNOWN, 0}, // 0=VTK_VOID - { WK_UNKNOWN, SGN_UNKNOWN, 0}, // 1=VTK_BIT - { WK_FIXED, SGN_SIGNED, 1}, // 2=VTK_CHAR - { WK_FIXED, SGN_UNSIGNED, 1}, // 3=VTK_UNSIGNED_CHAR - { WK_FIXED, SGN_SIGNED, 2}, // 4=VTK_SHORT - { WK_FIXED, SGN_UNSIGNED, 2}, // 5=VTK_UNSIGNED_SHORT - { WK_FIXED, SGN_SIGNED, 4}, // 6=VTK_INT - { WK_FIXED, SGN_UNSIGNED, 4}, // 7=VTK_UNSIGNED_INT - { WK_FIXED, SGN_SIGNED, 8}, // 8=VTK_LONG - { WK_FIXED, SGN_UNSIGNED, 8}, // 9=VTK_UNSIGNED_LONG - { WK_FLOAT, SGN_SIGNED, 4}, // 10=VTK_FLOAT - { WK_FIXED, SGN_SIGNED, 8} // 11=VTK_DOUBLE - }; - -} //end anonymous namespace - -bool -Image_3::read_vtk_image_data(vtkImageData* vtk_image) -{ - if(!vtk_image) - return false; - - _image* image = ::_initImage(); - const int* dims = vtk_image->GetDimensions(); - const double* spacing = vtk_image->GetSpacing(); - image->vectMode = VM_SCALAR; - image->xdim = dims[0]; - image->ydim = dims[1]; - image->zdim = dims[2]; - image->vdim = 1; - image->vx = spacing[0]; - image->vy = spacing[1]; - image->vz = spacing[2]; - image->endianness = ::_getEndianness(); - int vtk_type = vtk_image->GetScalarType(); - if(vtk_type == VTK_SIGNED_CHAR) vtk_type = VTK_CHAR; - if(vtk_type < 0 || vtk_type > VTK_DOUBLE) - vtk_type = VTK_DOUBLE; - const VTK_to_ImageIO_type_mapper& imageio_type = - VTK_to_ImageIO_type[vtk_type]; - image->wdim = imageio_type.wdim; - image->wordKind = imageio_type.wordKind; - image->sign = imageio_type.sign; - image->data = ::ImageIO_alloc(dims[0]*dims[1]*dims[2]*image->wdim); - std::cerr << "GetNumberOfTuples()=" << vtk_image->GetPointData()->GetScalars()->GetNumberOfTuples() - << "\nimage->size()=" << dims[0]*dims[1]*dims[2] - << "\nwdim=" << image->wdim << '\n'; - assert(vtk_image->GetPointData()->GetScalars()->GetNumberOfTuples() == dims[0]*dims[1]*dims[2]); - vtk_image->GetPointData()->GetScalars()->ExportToVoidPointer(image->data); - - return this->private_read(image); -} - -} // end namespace CGAL - -#endif // CGAL_USE_VTK +#endif // CGAL_HEADER_ONLY diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/analyze.cpp b/CGAL_ImageIO/src/CGAL_ImageIO/analyze.cpp index fbc09641344..a40db327bba 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/analyze.cpp +++ b/CGAL_ImageIO/src/CGAL_ImageIO/analyze.cpp @@ -19,820 +19,9 @@ // // Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau -#include +#ifndef CGAL_HEADER_ONLY #include "analyze.h" +#include "analyze_impl.h" -/* compile time endianness */ -/* replaced by _getEndianness() - see below -#if (defined (_ALPHA_) || defined (_LINUX_)) -#define ARCHITECTURE_ENDIANNESS END_LITTLE -#else -#define ARCHITECTURE_ENDIANNESS END_BIG -#endif -*/ - -/** Magic header for ANALYZE files written in little endian format */ -#define ANALYZE_LE_MAGIC "\000\000\001\134" -/** Magic header for ANALYZE files written in big endian format */ -#define ANALYZE_BE_MAGIC "\134\001\000\000" - -#define DT_NONE 0 -#define DT_UNKNOWN 0 /*Unknown data type*/ -#define DT_BINARY 1 /*Binary (1 bit per voxel)*/ -#define DT_UNSIGNED_CHAR 2 /*Unsigned character (8 bits per voxel)*/ -#define DT_SIGNED_SHORT 4 /*Signed short (16 bits per voxel)*/ -#define DT_SIGNED_INT 8 /*Signed integer (32 bits per voxel)*/ -#define DT_FLOAT 16 /*Floating point (32 bits per voxel)*/ -#define DT_COMPLEX 32 /*Complex (64 bits per voxel; 2 floating point numbers) */ -#define DT_DOUBLE 64 /*Double precision (64 bits per voxel)*/ -#define DT_RGB 128 /* */ -#define DT_ALL 255 /* */ - -struct header_key /* header_key */ - { /* off + size*/ - int sizeof_hdr; /* 0 + 4 */ - char data_type[10]; /* 4 + 10 */ - char db_name[18]; /* 14 + 18 */ - int extents; /* 32 + 4 */ - short int session_error; /* 36 + 2 */ - char regular; /* 38 + 1 */ - char hkey_un0; /* 39 + 1 */ - }; /* total=40 */ - -struct image_dimension /* image_dimension */ - { /* off + size*/ - short int dim[8]; /* 0 + 16 */ - char vox_units[4]; /* 16 + 4 */ - char cal_units[8]; /* 20 + 4 */ - short int unused1; /* 24 + 2 */ - short int datatype; /* 30 + 2 */ - short int bitpix; /* 32 + 2 */ - short int dim_un0; /* 34 + 2 */ - float pixdim[8]; /* 36 + 32 */ - /* - pixdim[] specifies the voxel dimensions: - pixdim[1] - voxel width - pixdim[2] - voxel height - pixdim[3] - interslice distance - ..etc - */ - float vox_offset; /* 68 + 4 */ - float funused1; /* 72 + 4 */ - float funused2; /* 76 + 4 */ - float funused3; /* 80 + 4 */ - float cal_max; /* 84 + 4 */ - float cal_min; /* 88 + 4 */ - int compressed; /* 92 + 4 */ - int verified; /* 96 + 4 */ - int glmax, glmin; /* 100 + 8 */ - }; /* total=108 */ - -struct data_history /* data_history */ - { /* off + size*/ - char descrip[80]; /* 0 + 80 */ - char aux_file[24]; /* 80 + 24 */ - char orient; /* 104 + 1 */ - char originator[10]; /* 105 + 10 */ - char generated[10]; /* 115 + 10 */ - char scannum[10]; /* 125 + 10 */ - char patient_id[10]; /* 135 + 10 */ - char exp_date[10]; /* 145 + 10 */ - char exp_time[10]; /* 155 + 10 */ - char hist_un0[3]; /* 165 + 3 */ - int views; /* 168 + 4 */ - int vols_added; /* 172 + 4 */ - int start_field; /* 176 + 4 */ - int field_skip; /* 180 + 4 */ - int omax,omin; /* 184 + 8 */ - int smax,smin; /* 192 + 8 */ - }; - - -struct dsr /* dsr */ - { /* off + size*/ - struct header_key hk; /* 0 + 40 */ - struct image_dimension dime; /* 40 + 108 */ - struct data_history hist; /* 148 + 200 */ - }; /* total=348 */ - - - - -/*---------------- _swapLong ------------------------------------------------*/ - -static void _swapLong( unsigned char *pntr) -{ - unsigned char b0, b1, b2, b3; - - b0 = *pntr; - b1 = *(pntr+1); - b2 = *(pntr+2); - b3 = *(pntr+3); - - *pntr = b3; - *(pntr+1) = b2; - *(pntr+2) = b1; - *(pntr+3) = b0; -} - -/*---------------- _swapShort -----------------------------------------------*/ - -static void _swapShort( unsigned char *pntr) -{ - unsigned char b0, b1; - - b0 = *pntr; - b1 = *(pntr+1); - - *pntr = b1; - *(pntr+1) = b0; -} - -/*---------------- _swapAnalyzeHdr ------------------------------------------*/ - -static void _swapAnalyzeHdr( struct dsr *pntr) -{ - - _swapLong((unsigned char*) &pntr->hk.sizeof_hdr) ; - _swapLong((unsigned char*) &pntr->hk.extents) ; - _swapShort((unsigned char*) &pntr->hk.session_error) ; - _swapShort((unsigned char*) &pntr->dime.dim[0]) ; - _swapShort((unsigned char*) &pntr->dime.dim[1]) ; - _swapShort((unsigned char*) &pntr->dime.dim[2]) ; - _swapShort((unsigned char*) &pntr->dime.dim[3]) ; - _swapShort((unsigned char*) &pntr->dime.dim[4]) ; - _swapShort((unsigned char*) &pntr->dime.dim[5]) ; - _swapShort((unsigned char*) &pntr->dime.dim[6]) ; - _swapShort((unsigned char*) &pntr->dime.dim[7]) ; - _swapShort((unsigned char*) &pntr->dime.unused1) ; - _swapShort((unsigned char*) &pntr->dime.datatype) ; - _swapShort((unsigned char*) &pntr->dime.bitpix) ; - _swapLong((unsigned char*) &pntr->dime.pixdim[0]) ; - _swapLong((unsigned char*) &pntr->dime.pixdim[1]) ; - _swapLong((unsigned char*) &pntr->dime.pixdim[2]) ; - _swapLong((unsigned char*) &pntr->dime.pixdim[3]) ; - _swapLong((unsigned char*) &pntr->dime.pixdim[4]) ; - _swapLong((unsigned char*) &pntr->dime.pixdim[5]) ; - _swapLong((unsigned char*) &pntr->dime.pixdim[6]) ; - _swapLong((unsigned char*) &pntr->dime.pixdim[7]) ; - _swapLong((unsigned char*) &pntr->dime.vox_offset) ; - _swapLong((unsigned char*) &pntr->dime.funused1) ; - _swapLong((unsigned char*) &pntr->dime.funused2) ; - _swapLong((unsigned char*) &pntr->dime.cal_max) ; - _swapLong((unsigned char*) &pntr->dime.cal_min) ; - _swapLong((unsigned char*) &pntr->dime.compressed) ; - _swapLong((unsigned char*) &pntr->dime.verified) ; - _swapShort((unsigned char*) &pntr->dime.dim_un0) ; - _swapLong((unsigned char*) &pntr->dime.glmax) ; - _swapLong((unsigned char*) &pntr->dime.glmin) ; -} -PTRIMAGE_FORMAT createAnalyzeFormat() { - PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); - - f->testImageFormat=&testAnalyzeHeader; - f->readImageHeader=&readAnalyzeHeader; - f->writeImage=&writeAnalyze; - strcpy(f->fileExtension,".hdr,.hdr.gz,.img,.img.gz"); - strcpy(f->realName,"Analyze"); - return f; -} - -int testAnalyzeHeader(char *magic,const char *) { - /* opened image is an ANALYZE */ - if( !memcmp(magic,ANALYZE_LE_MAGIC,4) || - !memcmp(magic,ANALYZE_BE_MAGIC,4)) - return 0; - else - return -1; -} - -int writeAnalyze( char *name, _image* im) { - char *outputName; - int length, extLength=0, res; - - - length=strlen(name); - outputName= (char *)ImageIO_alloc(length+8); - - if ( strncmp( name+length-4, ".hdr", 4 ) == 0 ) { - extLength = 4; - } - else if ( strncmp( name+length-4, ".img", 4 ) == 0 ) { - extLength = 4; - } - else if ( strncmp( name+length-7, ".img.gz", 7 ) == 0 ) { - extLength = 7; - } - else if ( strncmp( name+length-7, ".hdr.gz", 7 ) == 0 ) { - extLength = 7; - } - - strncpy( outputName, name, length-extLength ); - if ( strncmp( name+length-7, ".hdr.gz", 7 ) == 0 ) - strcpy( outputName+length-extLength, ".hdr.gz" ); - else - strcpy( outputName+length-extLength, ".hdr" ); - - _openWriteImage(im, outputName); - if( !im->fd ) { - fprintf(stderr, "writeAnalyze: error: unable to open file \'%s\'\n", outputName); - if ( outputName != NULL ) ImageIO_free( outputName ); - return ImageIO_OPENING; - } - - res = writeAnalyzeHeader(im); - if ( res < 0 ) { - fprintf(stderr, "writeAnalyze: error: unable to write header of \'%s\'\n", - outputName); - if ( outputName != NULL ) ImageIO_free( outputName ); - ImageIO_close( im ); - im->fd = NULL; - im->openMode = OM_CLOSE; - return( res ); - } - - ImageIO_close(im); - - strncpy( outputName, name, length-extLength ); - if ( strncmp( name+length-3, ".gz", 3 ) == 0 ) { - strcpy( outputName+length-extLength, ".img.gz" ); - } - else { - strcpy( outputName+length-extLength, ".img" ); - } - - _openWriteImage(im, outputName); - - if( !im->fd ) { - fprintf(stderr, "writeAnalyze: error: unable to open file \'%s\'\n", outputName); - if ( outputName != NULL ) ImageIO_free( outputName ); - return ImageIO_OPENING; - } - - res = writeAnalyzeData(im); - if (res < 0) { - fprintf(stderr, "writeAnalyze: error: unable to write data in \'%s\'\n", - outputName ); - ImageIO_close( im ); - im->fd = NULL; - im->openMode = OM_CLOSE; - return( res ); - } - - if ( outputName != NULL ) ImageIO_free( outputName ); - ImageIO_close( im ); - im->fd = NULL; - im->openMode = OM_CLOSE; - - return ( res ); -} - -/* - return: - -1: error - 0: success - */ - -int _readAnalyzeHeader( _image* im, const char* name, - struct dsr *analyzeHeader ) -{ - - unsigned int i ; - /* compile time endianness */ - ENDIANNESS ARCHITECTURE_ENDIANNESS = _getEndianness(); - - if(im->openMode != OM_CLOSE) { - - ImageIO_read( im, analyzeHeader, sizeof(struct dsr) ); - - if( analyzeHeader->hk.sizeof_hdr == sizeof(struct dsr) ) - { - im->endianness = ARCHITECTURE_ENDIANNESS ; - } - else - { - _swapAnalyzeHdr( analyzeHeader ); - if( analyzeHeader->hk.sizeof_hdr != sizeof(struct dsr) ) - { - fprintf (stderr, - "_readAnalyzeHeader: error: unknown magic (%d)...\n", - analyzeHeader->hk.sizeof_hdr ); - return -1; - } - if( ARCHITECTURE_ENDIANNESS == END_LITTLE ) - { - im->endianness = END_BIG; - } - else - { - im->endianness = END_LITTLE; - } - } - - if ( analyzeHeader->dime.dim[0] > 4 ) { - fprintf (stderr, - "_readAnalyzeHeader: error: dimensionality not supported (%d)...\n", - analyzeHeader->dime.dim[0] ); - return -1; - } - - im->xdim = analyzeHeader->dime.dim[1]; - im->ydim = analyzeHeader->dime.dim[2]; - im->zdim = analyzeHeader->dime.dim[3]; - - /* 0 time-points is a convention for one volume only at MNI */ - /* Corrected by X. Pennec following a bug report by Irina Kezele at MNI */ - if( analyzeHeader->dime.dim[4] == 0 ){ - fprintf (stderr, - "_readAnalyzeHeader: warning: time dimension / number if volume (dim[4]) is 0. Assuming this means 1 (otherwise there would be no image...). \n"); - analyzeHeader->dime.dim[4] = 1; - } - - /* Analyze doesn't support vector images. - The forth dimension relates to time. */ - if( analyzeHeader->dime.dim[4] != 1 ) - { - fprintf (stderr, - "_readAnalyzeHeader: error: time dimension not supported (%d)...\n", - analyzeHeader->dime.dim[4] ); - return -1; - } - im->vectMode = VM_SCALAR; - - im->vx = analyzeHeader->dime.pixdim[1]; - im->vy = analyzeHeader->dime.pixdim[2]; - im->vz = analyzeHeader->dime.pixdim[3]; - - if( im->vx == 0.0 ) im->vx = 1.0 ; - if( im->vy == 0.0 ) im->vy = im->vx ; - if( im->vz == 0.0 ) im->vz = im->vy ; - - switch(analyzeHeader->dime.datatype) - { - case DT_BINARY: - case DT_UNSIGNED_CHAR: - case DT_SIGNED_SHORT: - case DT_SIGNED_INT: - case DT_FLOAT: - case DT_COMPLEX: - case DT_DOUBLE: - im->vdim = 1; - break ; - - case DT_RGB: - im->vdim = 3; - break ; - - default: - fprintf (stderr, - "_readAnalyzeHeader: error: data type not supported (%d)...\n", - analyzeHeader->dime.datatype ); - return -1; - } - - switch(analyzeHeader->dime.datatype) - { - case DT_BINARY: - case DT_UNSIGNED_CHAR: - case DT_SIGNED_SHORT: - case DT_SIGNED_INT: - case DT_RGB: - im->wordKind = WK_FIXED; - break ; - - case DT_FLOAT: - case DT_COMPLEX: - case DT_DOUBLE: - im->wordKind = WK_FLOAT; - break ; - - default: - fprintf (stderr, - "_readAnalyzeHeader: error: data type not supported (%d)...\n", - analyzeHeader->dime.datatype ); - return -1; - } - - switch(analyzeHeader->dime.datatype) - { - case DT_BINARY: - case DT_UNSIGNED_CHAR: - case DT_RGB: - im->sign = SGN_UNSIGNED; - break ; - - case DT_SIGNED_SHORT: - case DT_SIGNED_INT: - case DT_FLOAT: - case DT_COMPLEX: - case DT_DOUBLE: - im->sign = SGN_SIGNED; - break ; - - default: - fprintf (stderr, - "_readAnalyzeHeader: error: data type not supported (%d)...\n", - analyzeHeader->dime.datatype ); - return -1; - } - - im->wdim = analyzeHeader->dime.bitpix; - if( analyzeHeader->dime.datatype == DT_RGB ) - { - im->wdim /= 3 ; - } - if(im->wdim != 8 && im->wdim != 16 && im->wdim != 32 && im->wdim != 64) - { - fprintf (stderr, - "_readAnalyzeHeader: error: pixel size not supported (%d)...\n", - analyzeHeader->dime.bitpix ); - return -1; - } - im->wdim >>= 3 ; - - /* There are 17 optional data fields - be careful in the allocation - */ - im->nuser = 1 + 17 ; - im->user = (char **) ImageIO_alloc(im->nuser * sizeof(char *)); - for ( i=0; inuser; i++ ) im->user[i] = NULL; - i = 0 ; - - im->user[i] = (char *) ImageIO_alloc((strlen("Data lost in the Analyze -> ImageIO conversion:") + 1)); - sprintf( im->user[i++], "Data lost in the Analyze -> ImageIO conversion:" ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" descrip: ") + 1 + strlen(analyzeHeader->hist.descrip) )); - sprintf( im->user[i++], " descrip: %s", analyzeHeader->hist.descrip ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" aux_file: ") + 1 + strlen(analyzeHeader->hist.descrip) )); - sprintf( im->user[i++], " aux_file: %s", analyzeHeader->hist.descrip ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" orient: ") + 1+ 2)); - sprintf( im->user[i++], " orient: %d", analyzeHeader->hist.orient ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" originator: ") + 1 + strlen(analyzeHeader->hist.originator) )); - sprintf( im->user[i++], " originator: %s", analyzeHeader->hist.originator ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" generated: ") + 1 + strlen(analyzeHeader->hist.generated) )); - sprintf( im->user[i++], " generated: %s", analyzeHeader->hist.generated ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" scannum: ") + 1 + strlen(analyzeHeader->hist.scannum) )); - sprintf( im->user[i++], " scannum: %s", analyzeHeader->hist.scannum ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" patient_id: ") + 1 + strlen(analyzeHeader->hist.patient_id) )); - sprintf( im->user[i++], " patient_id: %s", analyzeHeader->hist.patient_id ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" exp_date: ") + 1 + strlen(analyzeHeader->hist.exp_date) )); - sprintf( im->user[i++], " exp_date: %s", analyzeHeader->hist.exp_date ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" exp_time: ") + 1 + strlen(analyzeHeader->hist.exp_time) )); - sprintf( im->user[i++], " exp_time: %s", analyzeHeader->hist.exp_time ); - - /* A 32 bit int doesn't print on more than 11 chars */ - im->user[i] = (char *) ImageIO_alloc((strlen(" views: ") + 11 + 1)); - sprintf( im->user[i++], " views: %d", analyzeHeader->hist.views ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" vols_added: ") + 11 + 1)); - sprintf( im->user[i++], " vols_added: %d", analyzeHeader->hist.vols_added ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" start_field: ") + 11 + 1)); - sprintf( im->user[i++], " start_field: %d", analyzeHeader->hist.start_field ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" field_skip: ") + 11 + 1)); - sprintf( im->user[i++], " field_skip: %d", analyzeHeader->hist.field_skip ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" omax: ") + 11 + 1)); - sprintf( im->user[i++], " omax: %d", analyzeHeader->hist.omax ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" omin: ") + 11 + 1)); - sprintf( im->user[i++], " omin: %d", analyzeHeader->hist.omin ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" smax: ") + 11 + 1)); - sprintf( im->user[i++], " smax: %d", analyzeHeader->hist.smax ); - - im->user[i] = (char *) ImageIO_alloc((strlen(" smin: ") + 11 + 1)); - sprintf( im->user[i++], " smin: %d", analyzeHeader->hist.smin ); - - - /* header is read. close header file and open data file. */ - if( name != NULL ) { - - int length = strlen(name) ; - char* data_filename = (char *) ImageIO_alloc(length+4) ; - - if( strcmp( name+length-4, ".hdr" ) ) - { - fprintf (stderr, - "_readAnalyzeHeader: error: file header extension must be .hdr\n"); - ImageIO_free( data_filename ); - return -1; - } - - ImageIO_close(im); - - strcpy(data_filename,name); - strcpy(data_filename+length-3, "img.gz"); - _openReadImage(im,data_filename); - - if(!im->fd) { - - strcpy(data_filename,name); - strcpy(data_filename+length-3, "img"); - _openReadImage(im,data_filename); - if(!im->fd) { - fprintf(stderr, "_readAnalyzeHeader: error: unable to open data file \'%s\'\n", data_filename); - ImageIO_free( data_filename ); - return -1; - - } - } - ImageIO_free( data_filename ); - } - - /* check header validity */ - if(im->xdim > 0 && im->ydim > 0 && im->zdim > 0 && im->vdim > 0 && - im->vx > 0.0 && im->vy > 0.0 && im->vz > 0.0 && - (im->wordKind == WK_FLOAT || (im->wordKind == WK_FIXED && - im->sign != SGN_UNKNOWN)) && - im->endianness != END_UNKNOWN) { - return 0; - } - else return -1; - } - else return -1; -} - - - - - - - -int readAnalyzeHeader( const char* name, _image* im) -{ - struct dsr analyzeHeader ; - return( _readAnalyzeHeader( im, name, &analyzeHeader ) ); -} - - - -int -writeAnalyzeHeader( const _image* im ) -{ - const char *proc = "writeAnalyzeHeader"; - struct dsr hdr; - int i ; - int imin = 0; - int imax = 0; - - memset(&hdr,0, sizeof(struct dsr)); - - for(i=0;i<8;i++) { - hdr.dime.pixdim[i] = 0.0; - } - hdr.dime.vox_offset = 0.0; - hdr.dime.funused1 = 0.0; - hdr.dime.funused2 = 0.0; - hdr.dime.funused3 = 0.0; - hdr.dime.cal_max = 0.0; - hdr.dime.cal_min = 0.0; - - hdr.dime.dim[0] = 4; - hdr.dime.dim[1] = im->xdim; - hdr.dime.dim[2] = im->ydim; - hdr.dime.dim[3] = im->zdim; - hdr.dime.dim[4] = 1 ; - - if ( im->wordKind == WK_FIXED && im->sign == SGN_UNSIGNED ) { - if( im->wdim == 1 ) { - - if ( im->vdim == 1 ) { - hdr.dime.datatype = DT_UNSIGNED_CHAR ; - } - else if ( im->vdim == 3 ) { - hdr.dime.datatype = DT_RGB ; - } - else { - fprintf( stderr, "%s: unsupported image type\n", proc ); - return -1; - } - - { - unsigned char *buf = (unsigned char *)im->data; - int size = im->xdim * im->ydim * im->zdim * im->vdim; - imin = imax = *buf; - for (i=0; i *buf ) imin = *buf; - } - } - - } - else if ( im->wdim == 2 ) { - if ( im->vdim == 1 ) { - unsigned short int *buf = (unsigned short int*)im->data; - int size = im->xdim * im->ydim *im->zdim; - int i; - imin = imax = *buf; - for (i=0; i *buf ) imin = *buf; - } - if ( imax < 32768 ) { - hdr.dime.datatype = DT_SIGNED_SHORT ; - } - else { - fprintf( stderr, "%s: conversion from unsigned short to short impossible, max=%d\n", proc, imax ); - return -1; - } - } - else { - fprintf( stderr, "%s: unsupported image type\n", proc ); - return -1; - } - } - - else { - fprintf( stderr, "%s: unsupported image type\n", proc ); - return -1; - } - - } /* if ( im->wordKind == WK_FIXED && im->sign == SGN_UNSIGNED ) */ - - else if( im->wordKind == WK_FIXED && im->sign == SGN_SIGNED ) { - if ( im->vdim != 1 ) { - fprintf( stderr, "%s: unsupported image type\n", proc ); - return -1; - } - if( im->wdim == 2 ) { - short int *buf = (short int*)im->data; - int size = im->xdim * im->ydim *im->zdim; - int i; - imin = imax = *buf; - for (i=0; i *buf ) imin = *buf; - } - hdr.dime.datatype = DT_SIGNED_SHORT ; - } - else if( im->wdim == 4 ) { - int *buf = (int*)im->data; - int size = im->xdim * im->ydim *im->zdim; - int i; - imin = imax = *buf; - for (i=0; i *buf ) imin = *buf; - } - hdr.dime.datatype = DT_SIGNED_INT ; - } - else { - fprintf( stderr, "%s: unsupported image type\n", proc ); - return -1; - } - } - else if( im->wordKind == WK_FLOAT ) { - if ( im->vdim != 1 ) { - fprintf( stderr, "%s: unsupported image type\n", proc ); - return -1; - } - if( im->wdim == 4 ) { - hdr.dime.datatype = DT_FLOAT ; - } - else if( im->wdim == 8 ) { - hdr.dime.datatype = DT_DOUBLE ; - } - else { - fprintf( stderr, "%s: unsupported image type\n", proc ); - return -1; - } - } - else - { - fprintf( stderr, "%s: unsupported image type\n", proc ); - return -1; - } - - hdr.dime.bitpix = 8*im->wdim*im->vdim ; - - hdr.hk.regular = 'r'; - hdr.hk.sizeof_hdr = sizeof(struct dsr); - - /* this is probably bad and should be changed to the - real values, but I'm too lazy to do it now. AG */ - hdr.dime.glmax = 0 ; /* maximum voxel value */ - hdr.dime.glmin = 0 ; /* minimum voxel value */ - - /* corrected GM - */ - hdr.dime.glmax = imax ; /* maximum voxel value */ - hdr.dime.glmin = imin ; /* minimum voxel value */ - -/* Set the voxel dimension fields: - A value of 0.0 for these fields implies that the value is unknown. - Change these values to what is appropriate for your data - or pass additional command line arguments */ - - hdr.dime.pixdim[1] = (float)im->vx; - hdr.dime.pixdim[2] = (float)im->vy; - hdr.dime.pixdim[3] = (float)im->vz; - -/* Assume zero offset in .img file, byte at which pixel - data starts in the image file */ - - hdr.dime.vox_offset = 0.0; - -/* Planar Orientation; */ -/* Movie flag OFF: 0 = transverse, 1 = coronal, 2 = sagittal - Movie flag ON: 3 = transverse, 4 = coronal, 5 = sagittal */ - - hdr.hist.orient = 0; - -/* up to 3 characters for the voxels units label; i.e. mm., um., cm. */ - - strcpy(hdr.dime.vox_units,"mm."); - -/* up to 7 characters for the calibration units label; i.e. HU */ - - strcpy(hdr.dime.cal_units," "); - -/* Calibration maximum and minimum values; - values of 0.0 for both fields imply that no - calibration max and min values are used */ - - hdr.dime.cal_max = 0.0; - hdr.dime.cal_min = 0.0; - - if(ImageIO_write(im, &hdr, sizeof(struct dsr)) !=sizeof(struct dsr) ) - return -1; - - return 1 ; -} - - - - - -/* Writes the given image body in an already opened file.*/ -int writeAnalyzeData(const _image *im) { - unsigned int lineSize = im->wdim * im->xdim * im->vdim ; - unsigned long size = lineSize * im->ydim * im->zdim; - unsigned int nwrt ; - - if(im->openMode != OM_CLOSE) { - -#ifdef _REVERSE_LINES_IN_ANALYZE_ - char* data = (char *)im->data ; - char* buf = data + size - lineSize ; - - while( buf >= data ) - { - nwrt = ImageIO_write(im, buf, lineSize); - if(nwrt != lineSize) return -1; - buf -= lineSize ; - } -#else - nwrt = ImageIO_write(im, im->data, size); - if(nwrt != size) return -1; -#endif - - return 1 ; - } - else return -1; -} - - -/* Writes the given image body in an already opened file.*/ -int printAnalyzeHeader( const char* name ) -{ - _image *im; - struct dsr analyzeHeader ; - - im = _initImage(); - _openReadImage(im, name); - if(!im->fd) { - fprintf(stderr, "printAnalyzeHeader: error: unable to open file \'%s\'\n", name); - _freeImage(im); - return -1; - } - - if ( _readAnalyzeHeader( im, name, &analyzeHeader ) != 1 ) { - fprintf(stderr, "printAnalyzeHeader: error: unable to read header in file \'%s\'\n", name); - _freeImage(im); - return -1; - } - - - - - - ImageIO_close(im); - im->fd = NULL; - im->openMode = OM_CLOSE; - _freeImage(im); - return( 1 ); - - -} +#endif // CGAL_HEADER_ONLY diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/analyze.h b/CGAL_ImageIO/src/CGAL_ImageIO/analyze.h index c4d88543b3f..7014b92b6de 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/analyze.h +++ b/CGAL_ImageIO/src/CGAL_ImageIO/analyze.h @@ -67,5 +67,8 @@ int writeAnalyzeHeader( const _image* im ) ; */ int writeAnalyzeData( const _image* im ) ; +#ifdef CGAL_HEADER_ONLY +#include "analyze_impl.h" +#endif // CGAL_HEADER_ONLY #endif diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/analyze_impl.h b/CGAL_ImageIO/src/CGAL_ImageIO/analyze_impl.h new file mode 100644 index 00000000000..10d082bbaa2 --- /dev/null +++ b/CGAL_ImageIO/src/CGAL_ImageIO/analyze_impl.h @@ -0,0 +1,848 @@ +// Copyright (c) 2005-2008 ASCLEPIOS Project, INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of the ImageIO Library, and as been adapted for +// CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the +// GNU Lesser General Public License as published by the Free Software Foundation; +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +/* compile time endianness */ +/* replaced by _getEndianness() + see below +#if (defined (_ALPHA_) || defined (_LINUX_)) +#define ARCHITECTURE_ENDIANNESS END_LITTLE +#else +#define ARCHITECTURE_ENDIANNESS END_BIG +#endif +*/ + +/** Magic header for ANALYZE files written in little endian format */ +#define ANALYZE_LE_MAGIC "\000\000\001\134" +/** Magic header for ANALYZE files written in big endian format */ +#define ANALYZE_BE_MAGIC "\134\001\000\000" + +#define DT_NONE 0 +#define DT_UNKNOWN 0 /*Unknown data type*/ +#define DT_BINARY 1 /*Binary (1 bit per voxel)*/ +#define DT_UNSIGNED_CHAR 2 /*Unsigned character (8 bits per voxel)*/ +#define DT_SIGNED_SHORT 4 /*Signed short (16 bits per voxel)*/ +#define DT_SIGNED_INT 8 /*Signed integer (32 bits per voxel)*/ +#define DT_FLOAT 16 /*Floating point (32 bits per voxel)*/ +#define DT_COMPLEX 32 /*Complex (64 bits per voxel; 2 floating point numbers) */ +#define DT_DOUBLE 64 /*Double precision (64 bits per voxel)*/ +#define DT_RGB 128 /* */ +#define DT_ALL 255 /* */ + +struct header_key /* header_key */ + { /* off + size*/ + int sizeof_hdr; /* 0 + 4 */ + char data_type[10]; /* 4 + 10 */ + char db_name[18]; /* 14 + 18 */ + int extents; /* 32 + 4 */ + short int session_error; /* 36 + 2 */ + char regular; /* 38 + 1 */ + char hkey_un0; /* 39 + 1 */ + }; /* total=40 */ + +struct image_dimension /* image_dimension */ + { /* off + size*/ + short int dim[8]; /* 0 + 16 */ + char vox_units[4]; /* 16 + 4 */ + char cal_units[8]; /* 20 + 4 */ + short int unused1; /* 24 + 2 */ + short int datatype; /* 30 + 2 */ + short int bitpix; /* 32 + 2 */ + short int dim_un0; /* 34 + 2 */ + float pixdim[8]; /* 36 + 32 */ + /* + pixdim[] specifies the voxel dimensions: + pixdim[1] - voxel width + pixdim[2] - voxel height + pixdim[3] - interslice distance + ..etc + */ + float vox_offset; /* 68 + 4 */ + float funused1; /* 72 + 4 */ + float funused2; /* 76 + 4 */ + float funused3; /* 80 + 4 */ + float cal_max; /* 84 + 4 */ + float cal_min; /* 88 + 4 */ + int compressed; /* 92 + 4 */ + int verified; /* 96 + 4 */ + int glmax, glmin; /* 100 + 8 */ + }; /* total=108 */ + +struct data_history /* data_history */ + { /* off + size*/ + char descrip[80]; /* 0 + 80 */ + char aux_file[24]; /* 80 + 24 */ + char orient; /* 104 + 1 */ + char originator[10]; /* 105 + 10 */ + char generated[10]; /* 115 + 10 */ + char scannum[10]; /* 125 + 10 */ + char patient_id[10]; /* 135 + 10 */ + char exp_date[10]; /* 145 + 10 */ + char exp_time[10]; /* 155 + 10 */ + char hist_un0[3]; /* 165 + 3 */ + int views; /* 168 + 4 */ + int vols_added; /* 172 + 4 */ + int start_field; /* 176 + 4 */ + int field_skip; /* 180 + 4 */ + int omax,omin; /* 184 + 8 */ + int smax,smin; /* 192 + 8 */ + }; + + +struct dsr /* dsr */ + { /* off + size*/ + struct header_key hk; /* 0 + 40 */ + struct image_dimension dime; /* 40 + 108 */ + struct data_history hist; /* 148 + 200 */ + }; /* total=348 */ + + + + +/*---------------- _swapLong ------------------------------------------------*/ +CGAL_INLINE_FUNCTION +static void _swapLong( unsigned char *pntr) +{ + unsigned char b0, b1, b2, b3; + + b0 = *pntr; + b1 = *(pntr+1); + b2 = *(pntr+2); + b3 = *(pntr+3); + + *pntr = b3; + *(pntr+1) = b2; + *(pntr+2) = b1; + *(pntr+3) = b0; +} + +/*---------------- _swapShort -----------------------------------------------*/ +CGAL_INLINE_FUNCTION +static void _swapShort( unsigned char *pntr) +{ + unsigned char b0, b1; + + b0 = *pntr; + b1 = *(pntr+1); + + *pntr = b1; + *(pntr+1) = b0; +} + +/*---------------- _swapAnalyzeHdr ------------------------------------------*/ +CGAL_INLINE_FUNCTION +static void _swapAnalyzeHdr( struct dsr *pntr) +{ + + _swapLong((unsigned char*) &pntr->hk.sizeof_hdr) ; + _swapLong((unsigned char*) &pntr->hk.extents) ; + _swapShort((unsigned char*) &pntr->hk.session_error) ; + _swapShort((unsigned char*) &pntr->dime.dim[0]) ; + _swapShort((unsigned char*) &pntr->dime.dim[1]) ; + _swapShort((unsigned char*) &pntr->dime.dim[2]) ; + _swapShort((unsigned char*) &pntr->dime.dim[3]) ; + _swapShort((unsigned char*) &pntr->dime.dim[4]) ; + _swapShort((unsigned char*) &pntr->dime.dim[5]) ; + _swapShort((unsigned char*) &pntr->dime.dim[6]) ; + _swapShort((unsigned char*) &pntr->dime.dim[7]) ; + _swapShort((unsigned char*) &pntr->dime.unused1) ; + _swapShort((unsigned char*) &pntr->dime.datatype) ; + _swapShort((unsigned char*) &pntr->dime.bitpix) ; + _swapLong((unsigned char*) &pntr->dime.pixdim[0]) ; + _swapLong((unsigned char*) &pntr->dime.pixdim[1]) ; + _swapLong((unsigned char*) &pntr->dime.pixdim[2]) ; + _swapLong((unsigned char*) &pntr->dime.pixdim[3]) ; + _swapLong((unsigned char*) &pntr->dime.pixdim[4]) ; + _swapLong((unsigned char*) &pntr->dime.pixdim[5]) ; + _swapLong((unsigned char*) &pntr->dime.pixdim[6]) ; + _swapLong((unsigned char*) &pntr->dime.pixdim[7]) ; + _swapLong((unsigned char*) &pntr->dime.vox_offset) ; + _swapLong((unsigned char*) &pntr->dime.funused1) ; + _swapLong((unsigned char*) &pntr->dime.funused2) ; + _swapLong((unsigned char*) &pntr->dime.cal_max) ; + _swapLong((unsigned char*) &pntr->dime.cal_min) ; + _swapLong((unsigned char*) &pntr->dime.compressed) ; + _swapLong((unsigned char*) &pntr->dime.verified) ; + _swapShort((unsigned char*) &pntr->dime.dim_un0) ; + _swapLong((unsigned char*) &pntr->dime.glmax) ; + _swapLong((unsigned char*) &pntr->dime.glmin) ; +} + +CGAL_INLINE_FUNCTION +PTRIMAGE_FORMAT createAnalyzeFormat() { + PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); + + f->testImageFormat=&testAnalyzeHeader; + f->readImageHeader=&readAnalyzeHeader; + f->writeImage=&writeAnalyze; + strcpy(f->fileExtension,".hdr,.hdr.gz,.img,.img.gz"); + strcpy(f->realName,"Analyze"); + return f; +} + +CGAL_INLINE_FUNCTION +int testAnalyzeHeader(char *magic,const char *) { + /* opened image is an ANALYZE */ + if( !memcmp(magic,ANALYZE_LE_MAGIC,4) || + !memcmp(magic,ANALYZE_BE_MAGIC,4)) + return 0; + else + return -1; +} + +CGAL_INLINE_FUNCTION +int writeAnalyze( char *name, _image* im) { + char *outputName; + int length, extLength=0, res; + + + length=strlen(name); + outputName= (char *)ImageIO_alloc(length+8); + + if ( strncmp( name+length-4, ".hdr", 4 ) == 0 ) { + extLength = 4; + } + else if ( strncmp( name+length-4, ".img", 4 ) == 0 ) { + extLength = 4; + } + else if ( strncmp( name+length-7, ".img.gz", 7 ) == 0 ) { + extLength = 7; + } + else if ( strncmp( name+length-7, ".hdr.gz", 7 ) == 0 ) { + extLength = 7; + } + + strncpy( outputName, name, length-extLength ); + if ( strncmp( name+length-7, ".hdr.gz", 7 ) == 0 ) + strcpy( outputName+length-extLength, ".hdr.gz" ); + else + strcpy( outputName+length-extLength, ".hdr" ); + + _openWriteImage(im, outputName); + if( !im->fd ) { + fprintf(stderr, "writeAnalyze: error: unable to open file \'%s\'\n", outputName); + if ( outputName != NULL ) ImageIO_free( outputName ); + return ImageIO_OPENING; + } + + res = writeAnalyzeHeader(im); + if ( res < 0 ) { + fprintf(stderr, "writeAnalyze: error: unable to write header of \'%s\'\n", + outputName); + if ( outputName != NULL ) ImageIO_free( outputName ); + ImageIO_close( im ); + im->fd = NULL; + im->openMode = OM_CLOSE; + return( res ); + } + + ImageIO_close(im); + + strncpy( outputName, name, length-extLength ); + if ( strncmp( name+length-3, ".gz", 3 ) == 0 ) { + strcpy( outputName+length-extLength, ".img.gz" ); + } + else { + strcpy( outputName+length-extLength, ".img" ); + } + + _openWriteImage(im, outputName); + + if( !im->fd ) { + fprintf(stderr, "writeAnalyze: error: unable to open file \'%s\'\n", outputName); + if ( outputName != NULL ) ImageIO_free( outputName ); + return ImageIO_OPENING; + } + + res = writeAnalyzeData(im); + if (res < 0) { + fprintf(stderr, "writeAnalyze: error: unable to write data in \'%s\'\n", + outputName ); + ImageIO_close( im ); + im->fd = NULL; + im->openMode = OM_CLOSE; + return( res ); + } + + if ( outputName != NULL ) ImageIO_free( outputName ); + ImageIO_close( im ); + im->fd = NULL; + im->openMode = OM_CLOSE; + + return ( res ); +} + +/* + return: + -1: error + 0: success + */ + +CGAL_INLINE_FUNCTION +int _readAnalyzeHeader( _image* im, const char* name, + struct dsr *analyzeHeader ) +{ + + unsigned int i ; + /* compile time endianness */ + ENDIANNESS ARCHITECTURE_ENDIANNESS = _getEndianness(); + + if(im->openMode != OM_CLOSE) { + + ImageIO_read( im, analyzeHeader, sizeof(struct dsr) ); + + if( analyzeHeader->hk.sizeof_hdr == sizeof(struct dsr) ) + { + im->endianness = ARCHITECTURE_ENDIANNESS ; + } + else + { + _swapAnalyzeHdr( analyzeHeader ); + if( analyzeHeader->hk.sizeof_hdr != sizeof(struct dsr) ) + { + fprintf (stderr, + "_readAnalyzeHeader: error: unknown magic (%d)...\n", + analyzeHeader->hk.sizeof_hdr ); + return -1; + } + if( ARCHITECTURE_ENDIANNESS == END_LITTLE ) + { + im->endianness = END_BIG; + } + else + { + im->endianness = END_LITTLE; + } + } + + if ( analyzeHeader->dime.dim[0] > 4 ) { + fprintf (stderr, + "_readAnalyzeHeader: error: dimensionality not supported (%d)...\n", + analyzeHeader->dime.dim[0] ); + return -1; + } + + im->xdim = analyzeHeader->dime.dim[1]; + im->ydim = analyzeHeader->dime.dim[2]; + im->zdim = analyzeHeader->dime.dim[3]; + + /* 0 time-points is a convention for one volume only at MNI */ + /* Corrected by X. Pennec following a bug report by Irina Kezele at MNI */ + if( analyzeHeader->dime.dim[4] == 0 ){ + fprintf (stderr, + "_readAnalyzeHeader: warning: time dimension / number if volume (dim[4]) is 0. Assuming this means 1 (otherwise there would be no image...). \n"); + analyzeHeader->dime.dim[4] = 1; + } + + /* Analyze doesn't support vector images. + The forth dimension relates to time. */ + if( analyzeHeader->dime.dim[4] != 1 ) + { + fprintf (stderr, + "_readAnalyzeHeader: error: time dimension not supported (%d)...\n", + analyzeHeader->dime.dim[4] ); + return -1; + } + im->vectMode = VM_SCALAR; + + im->vx = analyzeHeader->dime.pixdim[1]; + im->vy = analyzeHeader->dime.pixdim[2]; + im->vz = analyzeHeader->dime.pixdim[3]; + + if( im->vx == 0.0 ) im->vx = 1.0 ; + if( im->vy == 0.0 ) im->vy = im->vx ; + if( im->vz == 0.0 ) im->vz = im->vy ; + + switch(analyzeHeader->dime.datatype) + { + case DT_BINARY: + case DT_UNSIGNED_CHAR: + case DT_SIGNED_SHORT: + case DT_SIGNED_INT: + case DT_FLOAT: + case DT_COMPLEX: + case DT_DOUBLE: + im->vdim = 1; + break ; + + case DT_RGB: + im->vdim = 3; + break ; + + default: + fprintf (stderr, + "_readAnalyzeHeader: error: data type not supported (%d)...\n", + analyzeHeader->dime.datatype ); + return -1; + } + + switch(analyzeHeader->dime.datatype) + { + case DT_BINARY: + case DT_UNSIGNED_CHAR: + case DT_SIGNED_SHORT: + case DT_SIGNED_INT: + case DT_RGB: + im->wordKind = WK_FIXED; + break ; + + case DT_FLOAT: + case DT_COMPLEX: + case DT_DOUBLE: + im->wordKind = WK_FLOAT; + break ; + + default: + fprintf (stderr, + "_readAnalyzeHeader: error: data type not supported (%d)...\n", + analyzeHeader->dime.datatype ); + return -1; + } + + switch(analyzeHeader->dime.datatype) + { + case DT_BINARY: + case DT_UNSIGNED_CHAR: + case DT_RGB: + im->sign = SGN_UNSIGNED; + break ; + + case DT_SIGNED_SHORT: + case DT_SIGNED_INT: + case DT_FLOAT: + case DT_COMPLEX: + case DT_DOUBLE: + im->sign = SGN_SIGNED; + break ; + + default: + fprintf (stderr, + "_readAnalyzeHeader: error: data type not supported (%d)...\n", + analyzeHeader->dime.datatype ); + return -1; + } + + im->wdim = analyzeHeader->dime.bitpix; + if( analyzeHeader->dime.datatype == DT_RGB ) + { + im->wdim /= 3 ; + } + if(im->wdim != 8 && im->wdim != 16 && im->wdim != 32 && im->wdim != 64) + { + fprintf (stderr, + "_readAnalyzeHeader: error: pixel size not supported (%d)...\n", + analyzeHeader->dime.bitpix ); + return -1; + } + im->wdim >>= 3 ; + + /* There are 17 optional data fields + be careful in the allocation + */ + im->nuser = 1 + 17 ; + im->user = (char **) ImageIO_alloc(im->nuser * sizeof(char *)); + for ( i=0; inuser; i++ ) im->user[i] = NULL; + i = 0 ; + + im->user[i] = (char *) ImageIO_alloc((strlen("Data lost in the Analyze -> ImageIO conversion:") + 1)); + sprintf( im->user[i++], "Data lost in the Analyze -> ImageIO conversion:" ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" descrip: ") + 1 + strlen(analyzeHeader->hist.descrip) )); + sprintf( im->user[i++], " descrip: %s", analyzeHeader->hist.descrip ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" aux_file: ") + 1 + strlen(analyzeHeader->hist.descrip) )); + sprintf( im->user[i++], " aux_file: %s", analyzeHeader->hist.descrip ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" orient: ") + 1+ 2)); + sprintf( im->user[i++], " orient: %d", analyzeHeader->hist.orient ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" originator: ") + 1 + strlen(analyzeHeader->hist.originator) )); + sprintf( im->user[i++], " originator: %s", analyzeHeader->hist.originator ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" generated: ") + 1 + strlen(analyzeHeader->hist.generated) )); + sprintf( im->user[i++], " generated: %s", analyzeHeader->hist.generated ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" scannum: ") + 1 + strlen(analyzeHeader->hist.scannum) )); + sprintf( im->user[i++], " scannum: %s", analyzeHeader->hist.scannum ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" patient_id: ") + 1 + strlen(analyzeHeader->hist.patient_id) )); + sprintf( im->user[i++], " patient_id: %s", analyzeHeader->hist.patient_id ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" exp_date: ") + 1 + strlen(analyzeHeader->hist.exp_date) )); + sprintf( im->user[i++], " exp_date: %s", analyzeHeader->hist.exp_date ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" exp_time: ") + 1 + strlen(analyzeHeader->hist.exp_time) )); + sprintf( im->user[i++], " exp_time: %s", analyzeHeader->hist.exp_time ); + + /* A 32 bit int doesn't print on more than 11 chars */ + im->user[i] = (char *) ImageIO_alloc((strlen(" views: ") + 11 + 1)); + sprintf( im->user[i++], " views: %d", analyzeHeader->hist.views ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" vols_added: ") + 11 + 1)); + sprintf( im->user[i++], " vols_added: %d", analyzeHeader->hist.vols_added ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" start_field: ") + 11 + 1)); + sprintf( im->user[i++], " start_field: %d", analyzeHeader->hist.start_field ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" field_skip: ") + 11 + 1)); + sprintf( im->user[i++], " field_skip: %d", analyzeHeader->hist.field_skip ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" omax: ") + 11 + 1)); + sprintf( im->user[i++], " omax: %d", analyzeHeader->hist.omax ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" omin: ") + 11 + 1)); + sprintf( im->user[i++], " omin: %d", analyzeHeader->hist.omin ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" smax: ") + 11 + 1)); + sprintf( im->user[i++], " smax: %d", analyzeHeader->hist.smax ); + + im->user[i] = (char *) ImageIO_alloc((strlen(" smin: ") + 11 + 1)); + sprintf( im->user[i++], " smin: %d", analyzeHeader->hist.smin ); + + + /* header is read. close header file and open data file. */ + if( name != NULL ) { + + int length = strlen(name) ; + char* data_filename = (char *) ImageIO_alloc(length+4) ; + + if( strcmp( name+length-4, ".hdr" ) ) + { + fprintf (stderr, + "_readAnalyzeHeader: error: file header extension must be .hdr\n"); + ImageIO_free( data_filename ); + return -1; + } + + ImageIO_close(im); + + strcpy(data_filename,name); + strcpy(data_filename+length-3, "img.gz"); + _openReadImage(im,data_filename); + + if(!im->fd) { + + strcpy(data_filename,name); + strcpy(data_filename+length-3, "img"); + _openReadImage(im,data_filename); + if(!im->fd) { + fprintf(stderr, "_readAnalyzeHeader: error: unable to open data file \'%s\'\n", data_filename); + ImageIO_free( data_filename ); + return -1; + + } + } + ImageIO_free( data_filename ); + } + + /* check header validity */ + if(im->xdim > 0 && im->ydim > 0 && im->zdim > 0 && im->vdim > 0 && + im->vx > 0.0 && im->vy > 0.0 && im->vz > 0.0 && + (im->wordKind == WK_FLOAT || (im->wordKind == WK_FIXED && + im->sign != SGN_UNKNOWN)) && + im->endianness != END_UNKNOWN) { + return 0; + } + else return -1; + } + else return -1; +} + + + + + + +CGAL_INLINE_FUNCTION +int readAnalyzeHeader( const char* name, _image* im) +{ + struct dsr analyzeHeader ; + return( _readAnalyzeHeader( im, name, &analyzeHeader ) ); +} + + + +CGAL_INLINE_FUNCTION +int +writeAnalyzeHeader( const _image* im ) +{ + const char *proc = "writeAnalyzeHeader"; + struct dsr hdr; + int i ; + int imin = 0; + int imax = 0; + + memset(&hdr,0, sizeof(struct dsr)); + + for(i=0;i<8;i++) { + hdr.dime.pixdim[i] = 0.0; + } + hdr.dime.vox_offset = 0.0; + hdr.dime.funused1 = 0.0; + hdr.dime.funused2 = 0.0; + hdr.dime.funused3 = 0.0; + hdr.dime.cal_max = 0.0; + hdr.dime.cal_min = 0.0; + + hdr.dime.dim[0] = 4; + hdr.dime.dim[1] = im->xdim; + hdr.dime.dim[2] = im->ydim; + hdr.dime.dim[3] = im->zdim; + hdr.dime.dim[4] = 1 ; + + if ( im->wordKind == WK_FIXED && im->sign == SGN_UNSIGNED ) { + if( im->wdim == 1 ) { + + if ( im->vdim == 1 ) { + hdr.dime.datatype = DT_UNSIGNED_CHAR ; + } + else if ( im->vdim == 3 ) { + hdr.dime.datatype = DT_RGB ; + } + else { + fprintf( stderr, "%s: unsupported image type\n", proc ); + return -1; + } + + { + unsigned char *buf = (unsigned char *)im->data; + int size = im->xdim * im->ydim * im->zdim * im->vdim; + imin = imax = *buf; + for (i=0; i *buf ) imin = *buf; + } + } + + } + else if ( im->wdim == 2 ) { + if ( im->vdim == 1 ) { + unsigned short int *buf = (unsigned short int*)im->data; + int size = im->xdim * im->ydim *im->zdim; + int i; + imin = imax = *buf; + for (i=0; i *buf ) imin = *buf; + } + if ( imax < 32768 ) { + hdr.dime.datatype = DT_SIGNED_SHORT ; + } + else { + fprintf( stderr, "%s: conversion from unsigned short to short impossible, max=%d\n", proc, imax ); + return -1; + } + } + else { + fprintf( stderr, "%s: unsupported image type\n", proc ); + return -1; + } + } + + else { + fprintf( stderr, "%s: unsupported image type\n", proc ); + return -1; + } + + } /* if ( im->wordKind == WK_FIXED && im->sign == SGN_UNSIGNED ) */ + + else if( im->wordKind == WK_FIXED && im->sign == SGN_SIGNED ) { + if ( im->vdim != 1 ) { + fprintf( stderr, "%s: unsupported image type\n", proc ); + return -1; + } + if( im->wdim == 2 ) { + short int *buf = (short int*)im->data; + int size = im->xdim * im->ydim *im->zdim; + int i; + imin = imax = *buf; + for (i=0; i *buf ) imin = *buf; + } + hdr.dime.datatype = DT_SIGNED_SHORT ; + } + else if( im->wdim == 4 ) { + int *buf = (int*)im->data; + int size = im->xdim * im->ydim *im->zdim; + int i; + imin = imax = *buf; + for (i=0; i *buf ) imin = *buf; + } + hdr.dime.datatype = DT_SIGNED_INT ; + } + else { + fprintf( stderr, "%s: unsupported image type\n", proc ); + return -1; + } + } + else if( im->wordKind == WK_FLOAT ) { + if ( im->vdim != 1 ) { + fprintf( stderr, "%s: unsupported image type\n", proc ); + return -1; + } + if( im->wdim == 4 ) { + hdr.dime.datatype = DT_FLOAT ; + } + else if( im->wdim == 8 ) { + hdr.dime.datatype = DT_DOUBLE ; + } + else { + fprintf( stderr, "%s: unsupported image type\n", proc ); + return -1; + } + } + else + { + fprintf( stderr, "%s: unsupported image type\n", proc ); + return -1; + } + + hdr.dime.bitpix = 8*im->wdim*im->vdim ; + + hdr.hk.regular = 'r'; + hdr.hk.sizeof_hdr = sizeof(struct dsr); + + /* this is probably bad and should be changed to the + real values, but I'm too lazy to do it now. AG */ + hdr.dime.glmax = 0 ; /* maximum voxel value */ + hdr.dime.glmin = 0 ; /* minimum voxel value */ + + /* corrected GM + */ + hdr.dime.glmax = imax ; /* maximum voxel value */ + hdr.dime.glmin = imin ; /* minimum voxel value */ + +/* Set the voxel dimension fields: + A value of 0.0 for these fields implies that the value is unknown. + Change these values to what is appropriate for your data + or pass additional command line arguments */ + + hdr.dime.pixdim[1] = (float)im->vx; + hdr.dime.pixdim[2] = (float)im->vy; + hdr.dime.pixdim[3] = (float)im->vz; + +/* Assume zero offset in .img file, byte at which pixel + data starts in the image file */ + + hdr.dime.vox_offset = 0.0; + +/* Planar Orientation; */ +/* Movie flag OFF: 0 = transverse, 1 = coronal, 2 = sagittal + Movie flag ON: 3 = transverse, 4 = coronal, 5 = sagittal */ + + hdr.hist.orient = 0; + +/* up to 3 characters for the voxels units label; i.e. mm., um., cm. */ + + strcpy(hdr.dime.vox_units,"mm."); + +/* up to 7 characters for the calibration units label; i.e. HU */ + + strcpy(hdr.dime.cal_units," "); + +/* Calibration maximum and minimum values; + values of 0.0 for both fields imply that no + calibration max and min values are used */ + + hdr.dime.cal_max = 0.0; + hdr.dime.cal_min = 0.0; + + if(ImageIO_write(im, &hdr, sizeof(struct dsr)) !=sizeof(struct dsr) ) + return -1; + + return 1 ; +} + + + + + +/* Writes the given image body in an already opened file.*/ +CGAL_INLINE_FUNCTION +int writeAnalyzeData(const _image *im) { + unsigned int lineSize = im->wdim * im->xdim * im->vdim ; + unsigned long size = lineSize * im->ydim * im->zdim; + unsigned int nwrt ; + + if(im->openMode != OM_CLOSE) { + +#ifdef _REVERSE_LINES_IN_ANALYZE_ + char* data = (char *)im->data ; + char* buf = data + size - lineSize ; + + while( buf >= data ) + { + nwrt = ImageIO_write(im, buf, lineSize); + if(nwrt != lineSize) return -1; + buf -= lineSize ; + } +#else + nwrt = ImageIO_write(im, im->data, size); + if(nwrt != size) return -1; +#endif + + return 1 ; + } + else return -1; +} + + +/* Writes the given image body in an already opened file.*/ +CGAL_INLINE_FUNCTION +int printAnalyzeHeader( const char* name ) +{ + _image *im; + struct dsr analyzeHeader ; + + im = _initImage(); + _openReadImage(im, name); + if(!im->fd) { + fprintf(stderr, "printAnalyzeHeader: error: unable to open file \'%s\'\n", name); + _freeImage(im); + return -1; + } + + if ( _readAnalyzeHeader( im, name, &analyzeHeader ) != 1 ) { + fprintf(stderr, "printAnalyzeHeader: error: unable to read header in file \'%s\'\n", name); + _freeImage(im); + return -1; + } + + + + + + ImageIO_close(im); + im->fd = NULL; + im->openMode = OM_CLOSE; + _freeImage(im); + return( 1 ); + + +} diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/bmp.cpp b/CGAL_ImageIO/src/CGAL_ImageIO/bmp.cpp index 739fd21e8d5..e9b862ecc81 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/bmp.cpp +++ b/CGAL_ImageIO/src/CGAL_ImageIO/bmp.cpp @@ -19,487 +19,9 @@ // // Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau -#include -#include -#include "bmptypes.h" -#include "bmpendian.h" -#include "bmpread.h" - - +#ifndef CGAL_HEADER_ONLY #include "bmp.h" +#include "bmp_impl.h" - - -/** Magic header for bmp */ -#define BMP_MAGIC "BM" - - - -static int _VERBOSE_BMP_ = 1; - - - -int testBmpHeader(char *magic,const char *) { - if( !strncmp(magic, BMP_MAGIC, strlen(BMP_MAGIC))) - return 0; - else - return -1; -} - -PTRIMAGE_FORMAT createBMPFormat() { - PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); - - f->testImageFormat=&testBmpHeader; - f->readImageHeader=&readBmpImage; - f->writeImage=0; - strcpy(f->fileExtension,".bmp"); - strcpy(f->realName,"BMP"); - return f; -} - -int readBmpImage( const char *name,_image *im) -{ - int dimx, dimy, dimv; - - im->data = _readBmpImage( name, &dimx, &dimy, &dimv ); - if ( im->data == NULL ) { - fprintf( stderr, "readBmpImage: unable to read \'%s\'\n", name ); - return( -1 ); - } - - im->xdim = dimx; - im->ydim = dimy; - im->vdim = dimv; - - im->zdim = 1; - - im->wdim = 1; - im->wordKind = WK_FIXED; - im->sign = SGN_UNSIGNED; - - return 1; -} - - - -void *_readBmpImage( const char *name, - int *dimx, int *dimy, int *dimz ) -{ - const char *proc="_readBmpImage"; - void *buf = (void*)NULL; - unsigned char *myBuf; - - FILE *fp; - RGB **argbs; - char **xorMasks, **andMasks; - CGAL_UINT32 *heights, *widths, row, col; - CGAL_UINT16 fileType; - long filePos; - int numImages, i; - int rc; - - fp = fopen(name, "rb"); - if (fp == NULL) { - if ( _VERBOSE_BMP_ ) - fprintf( stderr, "%s: error in opening %s\n", proc, name ); - return( (void*)NULL ); - } - - - /* - * Read the first two bytes as little-endian to determine the file type. - * Preserve the file position. - */ - filePos = ftell(fp); - rc = readUINT16little(fp, &fileType); - if (rc != 0) { - if ( _VERBOSE_BMP_ ) - fprintf( stderr, "%s: error in getting file type %s\n", proc, name ); - return( (void*)NULL ); - } - fseek(fp, filePos, SEEK_SET); - - /* - * Read the images. - */ - switch (fileType) { - case TYPE_ARRAY: - /* - * If this is an array of images, read them. All the arrays we need - * will be allocated by the reader function. - */ - rc = readMultipleImage(fp, &argbs, &xorMasks, &andMasks, &heights, - &widths, &numImages); - break; - case TYPE_BMP: - case TYPE_ICO: - case TYPE_ICO_COLOR: - case TYPE_PTR: - case TYPE_PTR_COLOR: - /* - * If this is a single-image file, we've a little more work. In order - * to make the output part of this test program easy to write, we're - * going to allocate dummy arrays that represent what - * readMultipleImage would have allocated. We'll read the data into - * those arrays. - */ - argbs = (RGB **)calloc(1, sizeof(RGB *)); - if (argbs == NULL) - { - rc = 1005; - break; - } - xorMasks = (char **)calloc(1, sizeof(char *)); - if (xorMasks == NULL) - { - free(argbs); - rc = 1005; - break; - } - andMasks = (char **)calloc(1, sizeof(char *)); - if (andMasks == NULL) - { - free(argbs); - free(xorMasks); - rc = 1005; - break; - } - heights = (CGAL_UINT32 *)calloc(1, sizeof(CGAL_UINT32)); - if (heights == NULL) - { - free(argbs); - free(xorMasks); - free(andMasks); - rc = 1005; - break; - } - widths = (CGAL_UINT32 *)calloc(1, sizeof(CGAL_UINT32)); - if (widths == NULL) - { - free(argbs); - free(xorMasks); - free(andMasks); - free(heights); - rc = 1005; - break; - } - numImages = 1; - - /* - * Now that we have our arrays allocted, read the image into them. - */ - switch (fileType) { - case TYPE_BMP: - rc = readSingleImageBMP(fp, argbs, widths, heights); - break; - case TYPE_ICO: - case TYPE_PTR: - rc = readSingleImageICOPTR(fp, xorMasks, andMasks, widths, - heights); - break; - case TYPE_ICO_COLOR: - case TYPE_PTR_COLOR: - rc = readSingleImageColorICOPTR(fp, argbs, xorMasks, andMasks, - widths, heights); - break; - } - break; - default: - rc = 1000; - } - fclose(fp); - - - - /* - * At this point, everything's been read. Display status messages based - * on the return values. - */ - switch (rc) { - case 1000: - case 1006: - if ( _VERBOSE_BMP_ ) - fprintf( stderr, "%s: File is not a valid bitmap file\n", proc ); - break; - case 1001: - if ( _VERBOSE_BMP_ ) - fprintf( stderr, "%s: Illegal information in an image\n", proc ); - break; - case 1002: - if ( _VERBOSE_BMP_ ) - fprintf( stderr, "%s: Legal information that I can't handle yet in an image\n", proc ); - break; - case 1003: - case 1004: - case 1005: - if ( _VERBOSE_BMP_ ) - fprintf( stderr, "%s: Ran out of memory\n", proc ); - break; - case 0: - if ( _VERBOSE_BMP_ > 1 ) - fprintf( stderr, "%s: Got good data from file, writing results\n", proc ); - break; - default: - if ( _VERBOSE_BMP_ ) - fprintf( stderr, "%s: Error reading file rc=%d\n", proc,rc ); - break; - } - - /* - * If the return value wasn't 0, something went wrong. - */ - if (rc != 0) - { - if (rc != 1000 && rc != 1005) - { - for (i=0; i 1 ) - fprintf (stderr, "%s: There are %d images in the file\n", proc, numImages); - - if ( numImages >= 2 ) - fprintf (stderr, "%s: read only first image among %d\n", proc, numImages ); - - /* - * my stuff: - * just reading one bmp image - */ - if ( (numImages > 0) && - (argbs[0] != NULL) ) { - - buf = (void*)malloc( widths[0]*heights[0]*3 * sizeof( unsigned char ) ); - if ( buf == (void*)NULL ) { - if ( _VERBOSE_BMP_ ) - fprintf( stderr, "%s: error in allocating data buffer for %s\n", proc, name ); - - for (i=0; i +#include +#include "bmptypes.h" +#include "bmpendian.h" +#include "bmpread.h" + + + + + + +/** Magic header for bmp */ +#define BMP_MAGIC "BM" + + +#ifdef CGAL_HEADER_ONLY + +inline int& get_static_verbose_bmp() +{ + static int _VERBOSE_BMP_ = 1; + return _VERBOSE_BMP_; +} + +#else // CGAL_HEADER_ONLY + +static int _VERBOSE_BMP_ = 1; +inline int& get_static_verbose_bmp() +{ return _VERBOSE_BMP_; } + +#endif // CGAL_HEADER_ONLY + + +CGAL_INLINE_FUNCTION +int testBmpHeader(char *magic,const char *) { + if( !strncmp(magic, BMP_MAGIC, strlen(BMP_MAGIC))) + return 0; + else + return -1; +} + +CGAL_INLINE_FUNCTION +PTRIMAGE_FORMAT createBMPFormat() { + PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); + + f->testImageFormat=&testBmpHeader; + f->readImageHeader=&readBmpImage; + f->writeImage=0; + strcpy(f->fileExtension,".bmp"); + strcpy(f->realName,"BMP"); + return f; +} + +CGAL_INLINE_FUNCTION +int readBmpImage( const char *name,_image *im) +{ + int dimx, dimy, dimv; + + im->data = _readBmpImage( name, &dimx, &dimy, &dimv ); + if ( im->data == NULL ) { + fprintf( stderr, "readBmpImage: unable to read \'%s\'\n", name ); + return( -1 ); + } + + im->xdim = dimx; + im->ydim = dimy; + im->vdim = dimv; + + im->zdim = 1; + + im->wdim = 1; + im->wordKind = WK_FIXED; + im->sign = SGN_UNSIGNED; + + return 1; +} + + + +CGAL_INLINE_FUNCTION +void *_readBmpImage( const char *name, + int *dimx, int *dimy, int *dimz ) +{ + const char *proc="_readBmpImage"; + void *buf = (void*)NULL; + unsigned char *myBuf; + + FILE *fp; + RGB **argbs; + char **xorMasks, **andMasks; + CGAL_UINT32 *heights, *widths, row, col; + CGAL_UINT16 fileType; + long filePos; + int numImages, i; + int rc; + + fp = fopen(name, "rb"); + if (fp == NULL) { + if ( get_static_verbose_bmp() ) + fprintf( stderr, "%s: error in opening %s\n", proc, name ); + return( (void*)NULL ); + } + + + /* + * Read the first two bytes as little-endian to determine the file type. + * Preserve the file position. + */ + filePos = ftell(fp); + rc = readUINT16little(fp, &fileType); + if (rc != 0) { + if ( get_static_verbose_bmp() ) + fprintf( stderr, "%s: error in getting file type %s\n", proc, name ); + return( (void*)NULL ); + } + fseek(fp, filePos, SEEK_SET); + + /* + * Read the images. + */ + switch (fileType) { + case TYPE_ARRAY: + /* + * If this is an array of images, read them. All the arrays we need + * will be allocated by the reader function. + */ + rc = readMultipleImage(fp, &argbs, &xorMasks, &andMasks, &heights, + &widths, &numImages); + break; + case TYPE_BMP: + case TYPE_ICO: + case TYPE_ICO_COLOR: + case TYPE_PTR: + case TYPE_PTR_COLOR: + /* + * If this is a single-image file, we've a little more work. In order + * to make the output part of this test program easy to write, we're + * going to allocate dummy arrays that represent what + * readMultipleImage would have allocated. We'll read the data into + * those arrays. + */ + argbs = (RGB **)calloc(1, sizeof(RGB *)); + if (argbs == NULL) + { + rc = 1005; + break; + } + xorMasks = (char **)calloc(1, sizeof(char *)); + if (xorMasks == NULL) + { + free(argbs); + rc = 1005; + break; + } + andMasks = (char **)calloc(1, sizeof(char *)); + if (andMasks == NULL) + { + free(argbs); + free(xorMasks); + rc = 1005; + break; + } + heights = (CGAL_UINT32 *)calloc(1, sizeof(CGAL_UINT32)); + if (heights == NULL) + { + free(argbs); + free(xorMasks); + free(andMasks); + rc = 1005; + break; + } + widths = (CGAL_UINT32 *)calloc(1, sizeof(CGAL_UINT32)); + if (widths == NULL) + { + free(argbs); + free(xorMasks); + free(andMasks); + free(heights); + rc = 1005; + break; + } + numImages = 1; + + /* + * Now that we have our arrays allocted, read the image into them. + */ + switch (fileType) { + case TYPE_BMP: + rc = readSingleImageBMP(fp, argbs, widths, heights); + break; + case TYPE_ICO: + case TYPE_PTR: + rc = readSingleImageICOPTR(fp, xorMasks, andMasks, widths, + heights); + break; + case TYPE_ICO_COLOR: + case TYPE_PTR_COLOR: + rc = readSingleImageColorICOPTR(fp, argbs, xorMasks, andMasks, + widths, heights); + break; + } + break; + default: + rc = 1000; + } + fclose(fp); + + + + /* + * At this point, everything's been read. Display status messages based + * on the return values. + */ + switch (rc) { + case 1000: + case 1006: + if ( get_static_verbose_bmp() ) + fprintf( stderr, "%s: File is not a valid bitmap file\n", proc ); + break; + case 1001: + if ( get_static_verbose_bmp() ) + fprintf( stderr, "%s: Illegal information in an image\n", proc ); + break; + case 1002: + if ( get_static_verbose_bmp() ) + fprintf( stderr, "%s: Legal information that I can't handle yet in an image\n", proc ); + break; + case 1003: + case 1004: + case 1005: + if ( get_static_verbose_bmp() ) + fprintf( stderr, "%s: Ran out of memory\n", proc ); + break; + case 0: + if ( get_static_verbose_bmp() > 1 ) + fprintf( stderr, "%s: Got good data from file, writing results\n", proc ); + break; + default: + if ( get_static_verbose_bmp() ) + fprintf( stderr, "%s: Error reading file rc=%d\n", proc,rc ); + break; + } + + /* + * If the return value wasn't 0, something went wrong. + */ + if (rc != 0) + { + if (rc != 1000 && rc != 1005) + { + for (i=0; i 1 ) + fprintf (stderr, "%s: There are %d images in the file\n", proc, numImages); + + if ( numImages >= 2 ) + fprintf (stderr, "%s: read only first image among %d\n", proc, numImages ); + + /* + * my stuff: + * just reading one bmp image + */ + if ( (numImages > 0) && + (argbs[0] != NULL) ) { + + buf = (void*)malloc( widths[0]*heights[0]*3 * sizeof( unsigned char ) ); + if ( buf == (void*)NULL ) { + if ( get_static_verbose_bmp() ) + fprintf( stderr, "%s: error in allocating data buffer for %s\n", proc, name ); + + for (i=0; i -#include "bmptypes.h" #include "bmpendian.h" +#include "bmpendian_impl.h" -/***************************************************************************** -* -* Read functions. All read functions take an open file pointer as the first -* parameter and a pointer to data as the second parameter. The return value -* will be 0 on success, and EOF on failure. If successful, the second -* parameter will point to the data read. -*/ - -/* - * The CGAL_INT8 and CGAL_UINT8 types are stored as a single byte on disk. The INT8 - * type is a signed integer with range (-128..127). The CGAL_UINT8 type is an - * unsigned integer with range (0..255). - */ -int readINT8little(FILE *f, CGAL_INT8 *i) -{ - int rc; - - rc = fgetc(f); - if (rc == EOF) - return rc; - - *i = (rc & 0xff); - return 0; -} - -int readUINT8little(FILE *f, CGAL_UINT8 *i) -{ - int rc; - - rc = fgetc(f); - if (rc == EOF) - return rc; - - *i = (rc & 0xff); - return 0; -} - - -/* - * The CGAL_INT16 and CGAL_UINT16 types are stored as two bytes on disk. The INT16 type - * is a signed integer with range (-32768..32767). The CGAL_UINT16 type is an - * unisgned integer with range (0..65535). - */ -int readINT16little(FILE *f, CGAL_INT16 *i) -{ - int rc; - CGAL_INT16 temp = 0; - - temp = (fgetc(f) & 0xff); - - rc = fgetc(f); - if (rc == EOF) - return rc; - - temp |= ((rc & 0xff) << 8); - *i = temp; - return 0; -} - -int readUINT16little(FILE *f, CGAL_UINT16 *i) -{ - int rc; - CGAL_UINT16 temp = 0; - - temp = (fgetc(f) & 0xff); - - rc = fgetc(f); - if (rc == EOF) - return rc; - - temp |= ((rc & 0xff) << 8); - *i = temp; - return 0; -} - -/* - * The CGAL_INT32 and CGAL_UINT32 types are stored as four bytes on disk. The INT32 - * type is a signed integer with range (-2147483648..2147483647). The CGAL_UINT32 - * type is an unisgned integer with range (0..4294967295). - */ -int readINT32little(FILE *f, CGAL_INT32 *i) -{ - int rc; - CGAL_INT32 temp = 0; - - temp = ((long)fgetc(f) & 0xff); - temp |= (((long)fgetc(f) & 0xff) << 8); - temp |= (((long)fgetc(f) & 0xff) << 16); - - rc = fgetc(f); - if (rc == EOF) - return rc; - - temp |= (((long)rc & 0xff) << 24); - *i = temp; - return 0; -} - -int readUINT32little(FILE *f, CGAL_UINT32 *i) -{ - int rc; - CGAL_UINT32 temp = 0; - - temp = ((long)fgetc(f) & 0xff); - temp |= (((long)fgetc(f) & 0xff) << 8); - temp |= (((long)fgetc(f) & 0xff) << 16); - - rc = fgetc(f); - if (rc == EOF) - return rc; - - temp |= (((long)rc & 0xff) << 24); - *i = temp; - return 0; -} - -/***************************************************************************** -* -* Write functions. All write functions take an open file pointer as the first -* parameter and a data as the second parameter. The return value will be 0 on -* success, and EOF on failure. If successful, the second parameter will have -* been written to the open file. -*/ - -int writeINT8little(FILE *f, CGAL_INT8 i) -{ - return fputc(i, f); -} - -int writeUINT8little(FILE *f, CGAL_UINT8 i) -{ - return fputc(i, f); -} - -int writeINT16little(FILE *f, CGAL_INT16 i) -{ - int rc; - - rc = fputc((i & 0xff), f); - if (rc == EOF) - return rc; - - return fputc(((i >> 8) & 0xff), f); -} - -int writeUINT16little(FILE *f, CGAL_UINT16 i) -{ - int rc; - - rc = fputc((i & 0xff), f); - if (rc == EOF) - return rc; - - return fputc(((i >> 8) & 0xff), f); -} - -int writeINT32little(FILE *f, CGAL_INT32 i) -{ - int rc; - - rc = fputc((i & 0xff), f); - if (rc == EOF) - return rc; - - rc = fputc(((i >> 8) & 0xff), f); - if (rc == EOF) - return rc; - - rc = fputc(((i >> 16) & 0xff), f); - if (rc == EOF) - return rc; - - return fputc(((i >> 24) & 0xff), f); -} - - -int writeUINT32little(FILE *f, CGAL_UINT32 i) -{ - int rc; - - rc = fputc((i & 0xff), f); - if (rc == EOF) - return rc; - - rc = fputc(((i >> 8) & 0xff), f); - if (rc == EOF) - return rc; - - rc = fputc(((i >> 16) & 0xff), f); - if (rc == EOF) - return rc; - - return fputc(((i >> 24) & 0xff), f); -} - -/* - * Formatting information for emacs in c-mode - * - * Local Variables: - * c-indent-level:4 - * c-continued-statement-offset:4 - * c-brace-offset:-4 - * c-brace-imaginary-offset:0 - * c-argdecl-indent:4 - * c-label-offset:-4 - * End: - */ - +#endif // CGAL_HEADER_ONLY diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/bmpendian.h b/CGAL_ImageIO/src/CGAL_ImageIO/bmpendian.h index 76a7fb67511..40cf71ef279 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/bmpendian.h +++ b/CGAL_ImageIO/src/CGAL_ImageIO/bmpendian.h @@ -31,7 +31,9 @@ #ifndef __ENDIAN_H_INCLUDED__ #define __ENDIAN_H_INCLUDED__ - + +#include "bmptypes.h" + /* * Read the basic types as little-endian values. The return value will be * zero if successful, EOF, otherwise. @@ -54,6 +56,10 @@ int writeUINT8little(FILE *f, CGAL_UINT8 i); int writeUINT16little(FILE *f, CGAL_UINT16 i); int writeUINT32little(FILE *f, CGAL_UINT32 i); +#ifdef CGAL_HEADER_ONLY +#include "bmpendian_impl.h" +#endif // CGAL_HEADER_ONLY + #endif /* __ENDIAN_H_INCLUDED__ */ diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/bmpendian_impl.h b/CGAL_ImageIO/src/CGAL_ImageIO/bmpendian_impl.h new file mode 100644 index 00000000000..8686a187759 --- /dev/null +++ b/CGAL_ImageIO/src/CGAL_ImageIO/bmpendian_impl.h @@ -0,0 +1,257 @@ +// Copyright (c) 2005-2008 ASCLEPIOS Project, INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of the ImageIO Library, and as been adapted for +// CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the +// GNU Lesser General Public License as published by the Free Software Foundation; +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +/* + * These functions read and write our basic integer types from a little-endian + * file. The endian and word-size of the host machine will not affect this + * code. The only assumption made is that the C data type (char) is one byte + * long. This should be a safe assumption. + */ + +#include +#include "bmptypes.h" + +/***************************************************************************** +* +* Read functions. All read functions take an open file pointer as the first +* parameter and a pointer to data as the second parameter. The return value +* will be 0 on success, and EOF on failure. If successful, the second +* parameter will point to the data read. +*/ + +/* + * The CGAL_INT8 and CGAL_UINT8 types are stored as a single byte on disk. The INT8 + * type is a signed integer with range (-128..127). The CGAL_UINT8 type is an + * unsigned integer with range (0..255). + */ +CGAL_INLINE_FUNCTION +int readINT8little(FILE *f, CGAL_INT8 *i) +{ + int rc; + + rc = fgetc(f); + if (rc == EOF) + return rc; + + *i = (rc & 0xff); + return 0; +} + +CGAL_INLINE_FUNCTION +int readUINT8little(FILE *f, CGAL_UINT8 *i) +{ + int rc; + + rc = fgetc(f); + if (rc == EOF) + return rc; + + *i = (rc & 0xff); + return 0; +} + + +/* + * The CGAL_INT16 and CGAL_UINT16 types are stored as two bytes on disk. The INT16 type + * is a signed integer with range (-32768..32767). The CGAL_UINT16 type is an + * unisgned integer with range (0..65535). + */ +CGAL_INLINE_FUNCTION +int readINT16little(FILE *f, CGAL_INT16 *i) +{ + int rc; + CGAL_INT16 temp = 0; + + temp = (fgetc(f) & 0xff); + + rc = fgetc(f); + if (rc == EOF) + return rc; + + temp |= ((rc & 0xff) << 8); + *i = temp; + return 0; +} + +CGAL_INLINE_FUNCTION +int readUINT16little(FILE *f, CGAL_UINT16 *i) +{ + int rc; + CGAL_UINT16 temp = 0; + + temp = (fgetc(f) & 0xff); + + rc = fgetc(f); + if (rc == EOF) + return rc; + + temp |= ((rc & 0xff) << 8); + *i = temp; + return 0; +} + +/* + * The CGAL_INT32 and CGAL_UINT32 types are stored as four bytes on disk. The INT32 + * type is a signed integer with range (-2147483648..2147483647). The CGAL_UINT32 + * type is an unisgned integer with range (0..4294967295). + */ +CGAL_INLINE_FUNCTION +int readINT32little(FILE *f, CGAL_INT32 *i) +{ + int rc; + CGAL_INT32 temp = 0; + + temp = ((long)fgetc(f) & 0xff); + temp |= (((long)fgetc(f) & 0xff) << 8); + temp |= (((long)fgetc(f) & 0xff) << 16); + + rc = fgetc(f); + if (rc == EOF) + return rc; + + temp |= (((long)rc & 0xff) << 24); + *i = temp; + return 0; +} + +CGAL_INLINE_FUNCTION +int readUINT32little(FILE *f, CGAL_UINT32 *i) +{ + int rc; + CGAL_UINT32 temp = 0; + + temp = ((long)fgetc(f) & 0xff); + temp |= (((long)fgetc(f) & 0xff) << 8); + temp |= (((long)fgetc(f) & 0xff) << 16); + + rc = fgetc(f); + if (rc == EOF) + return rc; + + temp |= (((long)rc & 0xff) << 24); + *i = temp; + return 0; +} + +/***************************************************************************** +* +* Write functions. All write functions take an open file pointer as the first +* parameter and a data as the second parameter. The return value will be 0 on +* success, and EOF on failure. If successful, the second parameter will have +* been written to the open file. +*/ + +CGAL_INLINE_FUNCTION +int writeINT8little(FILE *f, CGAL_INT8 i) +{ + return fputc(i, f); +} + +CGAL_INLINE_FUNCTION +int writeUINT8little(FILE *f, CGAL_UINT8 i) +{ + return fputc(i, f); +} + +CGAL_INLINE_FUNCTION +int writeINT16little(FILE *f, CGAL_INT16 i) +{ + int rc; + + rc = fputc((i & 0xff), f); + if (rc == EOF) + return rc; + + return fputc(((i >> 8) & 0xff), f); +} + +CGAL_INLINE_FUNCTION +int writeUINT16little(FILE *f, CGAL_UINT16 i) +{ + int rc; + + rc = fputc((i & 0xff), f); + if (rc == EOF) + return rc; + + return fputc(((i >> 8) & 0xff), f); +} + +CGAL_INLINE_FUNCTION +int writeINT32little(FILE *f, CGAL_INT32 i) +{ + int rc; + + rc = fputc((i & 0xff), f); + if (rc == EOF) + return rc; + + rc = fputc(((i >> 8) & 0xff), f); + if (rc == EOF) + return rc; + + rc = fputc(((i >> 16) & 0xff), f); + if (rc == EOF) + return rc; + + return fputc(((i >> 24) & 0xff), f); +} + + +CGAL_INLINE_FUNCTION +int writeUINT32little(FILE *f, CGAL_UINT32 i) +{ + int rc; + + rc = fputc((i & 0xff), f); + if (rc == EOF) + return rc; + + rc = fputc(((i >> 8) & 0xff), f); + if (rc == EOF) + return rc; + + rc = fputc(((i >> 16) & 0xff), f); + if (rc == EOF) + return rc; + + return fputc(((i >> 24) & 0xff), f); +} + +/* + * Formatting information for emacs in c-mode + * + * Local Variables: + * c-indent-level:4 + * c-continued-statement-offset:4 + * c-brace-offset:-4 + * c-brace-imaginary-offset:0 + * c-argdecl-indent:4 + * c-label-offset:-4 + * End: + */ + diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/bmpread.cpp b/CGAL_ImageIO/src/CGAL_ImageIO/bmpread.cpp index 2e7d28fe8bb..6e77cb06b59 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/bmpread.cpp +++ b/CGAL_ImageIO/src/CGAL_ImageIO/bmpread.cpp @@ -19,1207 +19,9 @@ // // Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau -/* - * from bmp.zip, see the url http://www.ddj.com/ftp/1995/1995.03/ - * author Dr. Dobb's - */ +#ifndef CGAL_HEADER_ONLY -/* - * This file contains mid-level functions for reading bitmap structures and - * high-level functions that read bitmap files. - */ - -#include -#include -#include -#include "bmptypes.h" -#include "bmpendian.h" #include "bmpread.h" +#include "bmpread_impl.h" -/***************************************************************************** - * - * Mid-level functions. - * - * These functions read in the various structures defined in bmptypes.h. Each - * function assumes that the file pointer is positioned at the start of the - * given structure. Upon completion, each function will leave the file - * pointer positioned on the byte immediately following the structure. Return - * values will be 0 for success and non-zero for failure. In all cases, a - * return value of non-zero means that the file position has been left in an - * indeterminate state and further reading should not be attempted. - */ - -/* - * Read a Bitmapfileheader structure. - */ -int readBitmapFileHeader(FILE *fp, Bitmapfileheader *bfh) -{ - int rc; - - rc = readUINT16little(fp, &(bfh->type)); - if (rc != 0) - return rc; - - rc = readUINT32little(fp, &(bfh->size)); - if (rc != 0) - return rc; - - rc = readINT16little(fp, &(bfh->xHotspot)); - if (rc != 0) - return rc; - - rc = readINT16little(fp, &(bfh->yHotspot)); - if (rc != 0) - return rc; - - rc = readUINT32little(fp, &(bfh->offsetToBits)); - return rc; -} - -/* - * Read a BITMAPARRAYHEADER - */ -int readBitmapArrayHeader(FILE *fp, BITMAPARRAYHEADER *bah) -{ - int rc; - - rc = readUINT16little(fp, &(bah->type)); - if (rc != 0) - return rc; - rc = readUINT32little(fp, &(bah->size)); - if (rc != 0) - return rc; - rc = readUINT32little(fp, &(bah->next)); - if (rc != 0) - return rc; - rc = readUINT16little(fp, &(bah->screenWidth)); - if (rc != 0) - return rc; - rc = readUINT16little(fp, &(bah->screenHeight)); - return rc; -} - -/* - * Read the BITMAPHEADER structure. This one requires a bit of sanity - * checking. The length of the structure on the disk is specified in the - * first field. We must stop reading after that many bytes, and if that value - * is longer than sizeof(BITMAPHEADER), we must skip over any leftover bytes. - * Finally, if size is 12, then width an height are really 16-bit values, and - * we have to read them differently so they'll be properly stored in the - * 32-bit fields BITMAPHEADER uses. - */ -int readBitmapHeader(FILE *fp, BITMAPHEADER *bh) -{ - int rc, oldFormat; - unsigned int bytesRead; - CGAL_UINT16 tempVal; - - /* - * Clear the structure. Default values for all fields are zeros. This - * will prevent garbage from being returned if the structure is truncated - * on disk. - */ - memset(bh, 0, sizeof(BITMAPHEADER)); - - /* - * Read the size of the structure. From here on in, we'll have to be sure - * we don't read more bytes than this value. - */ - rc = readUINT32little(fp, &(bh->size)); - if (rc != 0) - return rc; - bytesRead = 4; - - /* - * If the size is 12 bytes or less, than this is an "old format" - * structure. So the width and height fields will have to be read - * differently. - */ - if (bh->size <= 12) - oldFormat = 1; - else - oldFormat = 0; - - /* - * Width and height are read differently for old and new format files. In - * the old format, they're 16-bit values. In the new format, they're - * 32-bits long. - */ - if (oldFormat) - { - rc = readUINT16little(fp, &tempVal); - if (rc != 0) - return rc; - bh->width = tempVal; - bytesRead += 2; - } - else - { - rc = readINT32little(fp, &(bh->width)); - if (rc != 0) - return rc; - bytesRead += 4; - } - if (bytesRead >= bh->size) - return 0; - - if (oldFormat) - { - rc = readUINT16little(fp, &tempVal); - if (rc != 0) - return rc; - bh->height = tempVal; - bytesRead += 2; - } - else - { - rc = readINT32little(fp, &(bh->height)); - if (rc != 0) - return rc; - bytesRead += 4; - } - if (bytesRead >= bh->size) - return 0; - - /* - * From this point on, old and new formats are identical to each other, - * and we can proceed as if there was no difference. For each field, we - * read it in and increment the count of bytes read. If at any time we - * have read the amount we got earlier (in the size field), then stop and - * leave the rest of the fields as zeros. - */ - rc = readUINT16little(fp, &(bh->numBitPlanes)); - if (rc != 0) - return rc; - bytesRead += 2; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT16little(fp, &(bh->numBitsPerPlane)); - if (rc != 0) - return rc; - bytesRead += 2; - if (bytesRead >= bh->size) - return 0; - - /* - * Old format stop here. But we don't have to check, because in that - * format, 12 bytes have been read and the function will have exited - * without any extra checking. - */ - rc = readUINT32little(fp, &(bh->compressionScheme)); - if (rc != 0) - return rc; - bytesRead += 4; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT32little(fp, &(bh->sizeOfImageData)); - if (rc != 0) - return rc; - bytesRead += 4; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT32little(fp, &(bh->xResolution)); - if (rc != 0) - return rc; - bytesRead += 4; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT32little(fp, &(bh->yResolution)); - if (rc != 0) - return rc; - bytesRead += 4; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT32little(fp, &(bh->numColorsUsed)); - if (rc != 0) - return rc; - bytesRead += 4; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT32little(fp, &(bh->numImportantColors)); - if (rc != 0) - return rc; - bytesRead += 4; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT16little(fp, &(bh->resolutionUnits)); - if (rc != 0) - return rc; - bytesRead += 2; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT16little(fp, &(bh->padding)); - if (rc != 0) - return rc; - bytesRead += 2; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT16little(fp, &(bh->origin)); - if (rc != 0) - return rc; - bytesRead += 2; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT16little(fp, &(bh->halftoning)); - if (rc != 0) - return rc; - bytesRead += 2; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT32little(fp, &(bh->halftoningParam1)); - if (rc != 0) - return rc; - bytesRead += 4; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT32little(fp, &(bh->halftoningParam2)); - if (rc != 0) - return rc; - bytesRead += 4; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT32little(fp, &(bh->colorEncoding)); - if (rc != 0) - return rc; - bytesRead += 4; - if (bytesRead >= bh->size) - return 0; - - rc = readUINT32little(fp, &(bh->identifier)); - if (rc != 0) - return rc; - bytesRead += 4; - if (bytesRead >= bh->size) - return 0; - - /* - * If there are more bytes in the file than this, then the file is using a - * future format that doesn't exist yet. Skip over the bytes. Assuming - * this future format somewhat resembles what we know now, ignoring the - * fields will be safe. We _MUST_ skip them, though, since the color - * table begins on the byte after this structure, and we have to position - * the file pointer there. - */ - return fseek(fp, (bh->size - bytesRead), SEEK_CUR); -} - - -/* - * readRgb reads in a single RGB structure from the disk. The numBytes field - * indicates how many bytes the field occupies on the disk. It assumes that - * each component is one byte on disk and the rest is padding. This will - * compensate for the old/new differences in color tables. (Old format - * bitmaps use 3 bytes per entry, while new format bitmaps use 4.) Note how - * it will never read more than the number of bytes requested. - */ -int readRgb(FILE *fp, RGB *rgb, int numBytes) -{ - int rc; - - if (numBytes == 0) - return 0; - rc = readUINT8little(fp, &(rgb->blue)); - if (rc != 0) - return rc; - - if (numBytes == 1) - return 0; - rc = readUINT8little(fp, &(rgb->green)); - if (rc != 0) - return rc; - - if (numBytes == 2) - return 0; - rc = readUINT8little(fp, &(rgb->red)); - if (rc != 0) - return rc; - - if (numBytes == 3) - return 0; - - /* Skip over extra bytes if more than three were requested */ - return fseek(fp, (numBytes - 3), SEEK_CUR); -} - -/* - * A color table is a block of RGB structures, all the same size. Read it by - * calling readRgb repeatedly. - */ -int readColorTable(FILE *fp, RGB *rgb, int numEntries, int numBytesPerEntry) -{ - int i, rc; - - for (i=0; i 24)) - padBytes = 0; - else if ((width % 32) <= 8) - padBytes = 3; - else if ((width % 32) <= 16) - padBytes = 2; - else - padBytes = 1; - - for (row = height; row > 0; row--) - { - for (column = width; column > 0; column -= 8) - { - rc = readUINT8little(fp, &temp); - if (rc != 0) - return rc; - for (i=0; i < ((column < 8) ? column : 8); i++) - { - /* - * For each byte read, bit-decompose it. Note that the - * last byte on a row could have less than 8 bits used. - * Most significant bits come first. - */ - value = ((temp & (1 << (7-i))) == 0) ? 0 : 1; - image[pixel].red = colorTable[value].red; - image[pixel].green = colorTable[value].green; - image[pixel].blue = colorTable[value].blue; - pixel++; - } - } - if (padBytes != 0) - { - rc = fseek(fp, padBytes, SEEK_CUR); - if (rc != 0) - return rc; - } - } - break; - - case 4: - /* - * For 4 bits per pixel, each byte is two pixels. The upper half go to - * the first pixel, and the lower half to the second. - */ - pixel = 0; - if (((width % 8) == 0) || ((width % 8) > 6)) - padBytes = 0; - else if ((width % 8) <= 2) - padBytes = 3; - else if ((width % 8) <= 4) - padBytes = 2; - else - padBytes = 1; - - for (row = height; row > 0; row--) - { - for (column = width; column > 0; column -= 2) - { - /* - * Each byte here is two pixels. Note that the last byte on a - * row may only contain one pixel. - */ - rc = readUINT8little(fp, &temp); - if (rc != 0) - return rc; - /* - * First pixel is the upper 4 bits - */ - value = temp >> 4; - image[pixel].red = colorTable[value].red; - image[pixel].green = colorTable[value].green; - image[pixel].blue = colorTable[value].blue; - pixel++; - - /* - * Second pixel is lower 4 bits. If this is the last byte in - * the row, and there are an odd number of pixels per row, then - * this is not valid data. - */ - if (column == 1) - { - value = temp & 0x0f; - image[pixel].red = colorTable[value].red; - image[pixel].green = colorTable[value].green; - image[pixel].blue = colorTable[value].blue; - pixel++; - } - } - if (padBytes != 0) - { - rc = fseek(fp, padBytes, SEEK_CUR); - if (rc != 0) - return rc; - } - } - break; - - case 8: - /* - * For 8 bits per pixel, each byte is one pixel. - */ - pixel = 0; - padBytes = ((width % 4) == 0) ? 0 : (4 - (width % 4)); - - for (row=height; row > 0; row--) - { - for (column=width; column > 0; column--) - { - rc = readUINT8little(fp, &temp); - if (rc != 0) - return rc; - image[pixel].red = colorTable[temp].red; - image[pixel].green = colorTable[temp].green; - image[pixel].blue = colorTable[temp].blue; - pixel++; - } - if (padBytes != 0) - { - rc = fseek(fp, padBytes, SEEK_CUR); - if (rc != 0) - return rc; - } - } - break; - - case 16: - /* - * For 16 bits per pixel, you must read two bytes per pixel. But - * there's a catch. The data is big endian! This is because all pixel - * data (for all formats, actually) is stored as a packed array, - * stored in pixel order. - */ - pixel = 0; - padBytes = ((width % 2) == 0) ? 0 : 2; - for (row=height; row > 0; row--) - { - for (column=width; column > 0; column--) - { - /* - * Read a 16-bit integer as big endian. Do this by reading - * two bytes and mathematically combine them. After that, - * proceed as usual. - */ - rc = readUINT8little(fp, &temp); - if (rc != 0) - return rc; - value = ((long)temp) << 8; - rc = readUINT8little(fp, &temp); - if (rc != 0) - return rc; - value |= temp; - - image[pixel].red = colorTable[value].red; - image[pixel].green = colorTable[value].green; - image[pixel].blue = colorTable[value].blue; - pixel++; - } - if (padBytes != 0) - { - rc = fseek(fp, padBytes, SEEK_CUR); - if (rc != 0) - return rc; - } - } - break; - - case 24: - /* - * For 24 bits per pixel, it's an RGB structure. Note that the color - * table is ignore for bit depths greater than 24 bits. - */ - pixel = 0; - padBytes = width % 4; - - for (row=height; row > 0; row--) - { - for (column=width; column > 0; column--) - { - rc = readRgb(fp, image+pixel, 3); - pixel++; - } - if (padBytes != 0) - { - rc = fseek(fp, padBytes, SEEK_CUR); - if (rc != 0) - return rc; - } - } - break; - } - - return 0; -} - - -/* - * ReadMaskBitsUncompressed. Reads a monochrome mask into an array of - * characters. It assmes that there is no compression. This is very similar - * (internally) to the readBitsUncompressed function. Note that if the data - * read isn't really one-bit-deep data, you'll probably get garbage back. - */ -int readMaskBitsUncompressed(FILE *fp, char *image, int width, int height) -{ - CGAL_UINT8 temp; - int rc, padBytes, i; - long row, column, pixel; - char value; - - /* - * see the one-bit-depth part of readBitsUncompressed for comments - */ - pixel = 0; - if (((width % 32) == 0) || ((width % 32) > 24)) - padBytes = 0; - else if ((width % 32) <= 8) - padBytes = 3; - else if ((width % 32) <= 16) - padBytes = 2; - else - padBytes = 1; - - for (row = height; row > 0; row--) - { - for (column = width; column > 0; column -= 8) - { - rc = readUINT8little(fp, &temp); - if (rc != 0) - return rc; - for (i=0; i < ((column < 8) ? column : 8); i++) - { - value = ((temp & (1 << (7-i))) == 0) ? 0 : 1; - image[pixel] = value; - pixel++; - } - } - if (padBytes != 0) - { - rc = fseek(fp, padBytes, SEEK_CUR); - if (rc != 0) - return rc; - } - } - - return 0; -} - - -/* - * reflectYRGB takes an array of RGB vales and the dimensions they represent - * and flips it vertically. This will convert a bottom-left origin array to a - * top-left origin array. - */ -void reflectYRGB(RGB *image, int width, int height) -{ - int row, col; - RGB temp; - - for (row = 0; row < (height / 2); row++) - { - for (col = 0; col < width; col++) - { - /* Swap pixels at (x,y) with (x,height-y) */ - memcpy(&temp, image+(row * width + col), sizeof(RGB)); - memcpy(image+(row * width + col), - image+((height - row - 1) * width + col), sizeof(RGB)); - memcpy(image+((height - row - 1) * width + col), &temp, - sizeof(RGB)); - } - } -} -/* - * reflectYchar takes an array of char values and the dimensions they - * represent and flips it vertically. This will convert a bottom-left origin - * array to a top-left origin array. - */ -void reflectYchar(char *image, int width, int height) -{ - int row, col; - char temp; - - for (row = 0; row < (height / 2); row++) - { - for (col = 0; col < width; col++) - { - /* Swap values at (x,y) with (x,height-y) */ - temp = image[row * width + col]; - image[row * width + col]=image[(height - row - 1) * width + col]; - image[(height - row - 1) * width + col] = temp; - } - } -} - -/***************************************************************************** - * - * High-level functions - * - * These functions read in specific types of bitmap files. Each assumes that - * the file pointer is positioned at the appropriate place in a bitmap file. - * (At the start of a Bitmapfileheader for all functions except - * readMultipleImages, which assumes the file pointer to be positioned on the - * start of a BITMAPARRAYHEADER. These functions will leave the file pointer - * on the byte after the image's color table. - * - * The coordinate speaces in the returned arrays will have an upper-left - * origin. As before, a non-zero return value indicates that something went - * wrong. - * - * Note that the BMP and mono-ICO functions will not return 1000 if the image - * is of type color-icon. This is because a color icon consists of a bitmap - * and a monochrome icon. - * - * return values: - * 0 - success - * 1000 - incorrect file type for the routine called - * 1001 - image data out of range or damaged file - * 1002 - good data, but the routine called can't handle it (yet) - * 1003 - out of memory allocating color table - * 1004 - out of memory allocating image - * 1005 - out of memory allocating image arrays - * 1006 - Illegal image type in a multi-image array - * - * other - I/O error of some kind - */ - - -/* - * readSingleImageBMP will read a single BMP image and generate an array of RGB - * triples that contain the RGB values for every pixel. It will also return - * the dimensions of the image. - */ -int readSingleImageBMP(FILE *fp, RGB **argb, CGAL_UINT32 *width, CGAL_UINT32 *height) -{ - Bitmapfileheader bfh; - BITMAPHEADER bh; - RGB *colorTable = (RGB*)NULL; - RGB *image = (RGB*)NULL; - int rc, depth, inverted; - long numColors, numPixels, endPos; - - /* - * First, get the file header and sanity check it. The type field must be - * TYPE_BMP or we're aborting. - */ - rc = readBitmapFileHeader(fp, &bfh); - if (rc != 0) - return rc; - if ((bfh.type != TYPE_BMP) && - (bfh.type != TYPE_ICO_COLOR) && - (bfh.type != TYPE_PTR_COLOR)) - return 1000; - - /* - * Immediately following a file header is always the bitmap header. Read - * it. Sanity check any values we might need. Specifically, less than - * 32-bit depth, known compression scheme, known origin, and known color - * encoding, and valid height/width. Note that negative height is OK, - * that indicates an upper-left origin for a Windows bitmap. - */ - rc = readBitmapHeader(fp, &bh); - if (rc != 0) - return rc; - depth = bh.numBitPlanes * bh.numBitsPerPlane; - if ((depth > 32) || - (bh.compressionScheme > COMPRESSION_LAST) || - (bh.origin > ORIGIN_LAST) || - (bh.colorEncoding > COLOR_ENCODING_LAST) || - (bh.width < 1) || - (bh.height == 0)) - return 1001; - - /* - * If the height is negative, then this is a Windows bitmap whose origin - * is the upper-left corner and not the lower-left. The inverted flag - * indicates a lower-left origin. Our code will be outputting an - * upper-left origin pixel array. - */ - if (bh.height < 0) - { - inverted = 0; - bh.height = -bh.height; - } - else - inverted = 1; - - /* - * Now, sanity check a few fields that are valid, but I don't have code to - * deal with them yet. This includes: more than one bit plane, any - * compression scheme, and bit depths that are not 1, 4, 8, 16, or 24. - */ - if ((bh.numBitPlanes > 1) || - ((bh.numBitsPerPlane != 1) && - (bh.numBitsPerPlane != 4) && - (bh.numBitsPerPlane != 8) && - (bh.numBitsPerPlane != 16) && - (bh.numBitsPerPlane != 24)) || - (bh.compressionScheme != COMPRESSION_NONE)) - return 1002; - - /* - * Allocate and read the color table. The file pointer has been - * positioned in the right place by the readBitmapHeader function. Note - * that images with 24-bits or more color depth have no color table. They - * are already RGB. When reading the color table, be sure to check for - * old/new format bitmaps. - */ - if (depth < 24) - { - numColors = 1 << depth; - colorTable = (RGB *)calloc(numColors, sizeof(RGB)); - if (colorTable == NULL) - return 1003; - if (bh.size <= 12) - rc = readColorTable(fp, colorTable, numColors, 3); - else - rc = readColorTable(fp, colorTable, numColors, 4); - if (rc != 0) - { - free(colorTable); - return rc; - } - } - - /* - * We're at the end of the color table. Preserve this position. We'll - * need to leave the file pointer there before returning from this - * function. - */ - endPos = ftell(fp); - - /* - * Allocate the array of pixels and fill it in. - */ - numPixels = bh.width * bh.height; - image = (RGB *)calloc(numPixels, sizeof(RGB)); - if (image == NULL) - { - free (colorTable); - return 1004; - } - - /* - * Seek to the bits - */ - rc = fseek(fp, bfh.offsetToBits, SEEK_SET); - if (rc != 0) - { - free (colorTable); - free (image); - return rc; - } - - /* - * Read the bits. If code for decompressing bits should be written, - * insert the call here. - */ - switch ((int)bh.compressionScheme) { - case COMPRESSION_NONE: - rc = readBitsUncompressed(fp, image, bh.width, bh.height, depth, - colorTable); - break; - } - - if (rc != 0) - { - free(image); - return rc; - } - - /* - * If the origin is lower-left, flip the image upside down - */ - if (inverted) - reflectYRGB(image, bh.width, bh.height); - - /* - * Return the output values. Set the file pointer to the byte after the - * color table. - */ - *argb = image; - *width = bh.width; - *height = bh.height; - fseek(fp, endPos, SEEK_SET); - - /* - * Clean up and return. Note that we don't return the color table. This - * is because we're returning an array of RGB values for the image - such - * a table would be redundant. - */ - if (colorTable != NULL) - free(colorTable); - - return 0; -} - - -/* - * Read in a monochrome OS/2 icon/pointer. return two arrays of bytes - * (interpreted as booleans) for the XOR and AND masks. - */ -int readSingleImageICOPTR(FILE *fp, char **xorMask, char **andMask, - CGAL_UINT32 *width, CGAL_UINT32 *height) -{ - Bitmapfileheader bfh; - BITMAPHEADER bh; - char *mask1, *mask2; - int rc; - long numPixels, endPos; - - /* - * Read and sanity check the header. Monochrom OS/2 icons are TYPE_ICO. - * Monochrome pointers are TYPE_PTR. Color ICO and PTR is also allowed, - * because monochrome masks are part of those images. - */ - rc = readBitmapFileHeader(fp, &bfh); - if (rc != 0) - return rc; - if ((bfh.type != TYPE_ICO) && - (bfh.type != TYPE_PTR) && - (bfh.type != TYPE_ICO_COLOR) && - (bfh.type != TYPE_PTR_COLOR)) - return 1000; - - /* - * Now read the bitmap data and sanity check it. Since this is a - * monochrome icon, bit depth must be 1. Additionally, a known - * compression scheme, known origin, known color encoding, and valid - * height/width. Height can't be less than 0, as it can with color - * images, since this code is only used on for OS/2-type images. - */ - rc = readBitmapHeader(fp, &bh); - if (rc != 0) - return rc; - if ((bh.numBitPlanes != 1) || - (bh.numBitsPerPlane != 1) || - (bh.compressionScheme > COMPRESSION_LAST) || - (bh.origin > ORIGIN_LAST) || - (bh.colorEncoding > COLOR_ENCODING_LAST) || - (bh.width < 1) || - (bh.height < 1)) - return 1001; - - /* - * Sanity check some valid fields that I can't deal with yet. - */ - if (bh.compressionScheme != COMPRESSION_NONE) - return 1002; - - /* - * Skip over the color table, since this is a monochrome mask. Note that - * the size is already known - 2 entries - which is 6 or 8 bytes. - * this isn't, and we don't. - */ - if (bh.size <= 12) - rc = fseek(fp, 6, SEEK_CUR); - else - rc = fseek(fp, 8, SEEK_CUR); - if (rc != 0) - { - return rc; - } - - /* - * Save this file position. we'll have to seek back to it after reading - * in the image data. - */ - endPos = ftell(fp); - - /* - * The image is actually two images. The top half is an AND mask and the - * bottom half is an XOR mask. Allocate the images. - */ - numPixels = bh.width * bh.height / 2; - mask1 = (char *)malloc(numPixels); - if (mask1 == NULL) - return 1004; - mask2 = (char *)malloc(numPixels); - if (mask2 == NULL) - { - free(mask1); - return 1004; - } - - /* - * Seek to the bit data - */ - rc = fseek(fp, bfh.offsetToBits, SEEK_SET); - if (rc != 0) - { - free (mask1); - free (mask2); - return rc; - } - - /* - * Read in the bits. Note: since these are really two images, two calls - * to readMaskBitsUncompressed are made, and the height used is 1/2 the - * height mentioned in the header. - */ - switch ((int) bh.compressionScheme) { - case COMPRESSION_NONE: - rc = readMaskBitsUncompressed(fp, mask1, bh.width, bh.height/2); - if (rc == 0) - rc = readMaskBitsUncompressed(fp, mask2, bh.width, bh.height/2); - break; - } - - if (rc != 0) - { - free (mask1); - free (mask2); - return rc; - } - - /* - * A mask will never have an upper-left origin, since Windows will never - * produce one in a bitmap file. - */ - reflectYchar(mask1, bh.width, bh.height / 2); - reflectYchar(mask2, bh.width, bh.height / 2); - - /* - * Return everything we've read. - */ - *xorMask = mask1; - *andMask = mask2; - *width = bh.width; - *height = bh.height / 2; - fseek(fp, endPos, SEEK_SET); - - return 0; -} - - -/* - * Read in a color OS/2 icon. return an array of RGBs for the colors. - * and two arrays of bytes (interpreted as booleans) for the XOR and AND - * masks. - */ -int readSingleImageColorICOPTR(FILE *fp, RGB **argb, char **xorMask, - char **andMask, CGAL_UINT32 *width, CGAL_UINT32 *height) -{ - CGAL_UINT32 width1, height1, width2, height2; - int rc; - - /* - * Color icons consist of a monochrome icon followed by a bitmap. This - * makes reading them easy - first do a monochrome mask read, and then do - * a color bitmap read. We should probably add some more descriptive - * error codes here. - * - * First read the mask. - */ - rc = readSingleImageICOPTR(fp, xorMask, andMask, &width2, &height2); - if (rc != 0) - { - return rc; - } - - /* - * Next, read the color bitmap part - */ - rc = readSingleImageBMP(fp, argb, &width1, &height1); - if (rc != 0) - { - return rc; - } - - /* - * Now, just sanity check the image - the dimensions for the image should - * match the dimensions of the masks. - */ - if ((width1 != width2) || (height1 != height2)) - return 1001; - - *width = width1; - *height = height1; - return 0; -} - - -/* - * readMultipleImage runs down the list of images in a file and returns them - * all. ImageCount is the number of images in the file. The other returned - * values are parallel arrays. If an element in aargb, axorMask, or aandMask - * is NULL, then that image has no such array. (Bitmaps have no xor or and - * masks, monochrome icons have no color arrays. - * - * Note that on errors other than 1000 and 1005, the arrays will contain good - * data - the images that have been read properly will be in the arrays. - * Images that have not yet been read will consist of NULL pointers in the - * arrays. - */ -int readMultipleImage(FILE *fp, RGB ***argbs, char ***xorMasks, - char ***andMasks, CGAL_UINT32 **widths, CGAL_UINT32 **heights, - int *imageCount) -{ - int rc; - long filePos; - BITMAPARRAYHEADER bah; - CGAL_UINT16 imageType; - int count; - - /* - * First count the images. Preserve the file position for later. If some - * structure in the list isn't an array header, return 1000. - */ - filePos = ftell(fp); - count = 0; - do - { - rc = readBitmapArrayHeader(fp, &bah); - if (rc != 0) - return rc; - if (bah.type != TYPE_ARRAY) - return 1000; - fseek(fp, bah.next, SEEK_SET); - count++; - } while (bah.next != 0); - fseek(fp, filePos, SEEK_SET); - - /* - * Allocate the arrays. Return 1005 on any failures - */ - *argbs = (RGB **)calloc(count, sizeof(RGB *)); - if (*argbs == NULL) - return 1005; - *xorMasks = (char **)calloc(count, sizeof(char *)); - if (*xorMasks == NULL) - { - free(*argbs); - return 1005; - } - *andMasks = (char **)calloc(count, sizeof(char *)); - if (*andMasks == NULL) - { - free(*argbs); - free(*xorMasks); - return 1005; - } - *widths = (CGAL_UINT32 *)calloc(count, sizeof(CGAL_UINT32)); - if (*widths == NULL) - { - free(*argbs); - free(*xorMasks); - free(*andMasks); - return 1005; - } - *heights = (CGAL_UINT32 *)calloc(count, sizeof(CGAL_UINT32)); - if (*heights == NULL) - { - free(*argbs); - free(*xorMasks); - free(*andMasks); - free(*widths); - return 1005; - } - *imageCount = count; - - /* - * Loop through the images again. This time, read each image - */ - count = 0; - do - { - rc = readBitmapArrayHeader(fp, &bah); - if (rc != 0) - return rc; - /* - * Get the image type. Preserve the position, since we're reading - * into the next structure. - */ - filePos = ftell(fp); - rc = readUINT16little(fp, &imageType); - if (rc != 0) - return rc; - rc = fseek(fp, filePos, SEEK_SET); - - /* - * Now that we know what kind of image we're about to read, read it. - */ - switch(imageType) { - case TYPE_BMP: - rc = readSingleImageBMP(fp, (*argbs)+count, (*widths)+count, - (*heights)+count); - break; - case TYPE_ICO: - case TYPE_PTR: - rc = readSingleImageICOPTR(fp, (*xorMasks)+count, - (*andMasks)+count, (*widths)+count, - (*heights)+count); - break; - case TYPE_ICO_COLOR: - case TYPE_PTR_COLOR: - rc = readSingleImageColorICOPTR(fp, (*argbs)+count, - (*xorMasks)+count, - (*andMasks)+count, - (*widths)+count, - (*heights)+count); - break; - default: - return 1006; - } - if (rc != 0) - return rc; - - fseek(fp, bah.next, SEEK_SET); - count++; - } while (bah.next != 0); - - return 0; -} - - -/* - * Formatting information for emacs in c-mode - * - * Local Variables: - * c-indent-level:4 - * c-continued-statement-offset:4 - * c-brace-offset:-4 - * c-brace-imaginary-offset:0 - * c-argdecl-indent:4 - * c-label-offset:-4 - * End: - */ - +#endif // CGAL_HEADER_ONLY diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/bmpread.h b/CGAL_ImageIO/src/CGAL_ImageIO/bmpread.h index 71b3d2fa3cc..9fe7cb963dd 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/bmpread.h +++ b/CGAL_ImageIO/src/CGAL_ImageIO/bmpread.h @@ -60,6 +60,10 @@ int readMultipleImage(FILE *fp, RGB ***argbs, char ***xorMasks, char ***andMasks, CGAL_UINT32 **widths, CGAL_UINT32 **heights, int *imageCount); +#ifdef CGAL_HEADER_ONLY +#include "bmpread_impl.h" +#endif // CGAL_HEADER_ONLY + #endif /* diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/bmpread_impl.h b/CGAL_ImageIO/src/CGAL_ImageIO/bmpread_impl.h new file mode 100644 index 00000000000..1b36398081a --- /dev/null +++ b/CGAL_ImageIO/src/CGAL_ImageIO/bmpread_impl.h @@ -0,0 +1,1243 @@ +// Copyright (c) 2005-2008 ASCLEPIOS Project, INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of the ImageIO Library, and as been adapted for +// CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the +// GNU Lesser General Public License as published by the Free Software Foundation; +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau + +/* + * from bmp.zip, see the url http://www.ddj.com/ftp/1995/1995.03/ + * author Dr. Dobb's + */ + +/* + * This file contains mid-level functions for reading bitmap structures and + * high-level functions that read bitmap files. + */ + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include +#include "bmptypes.h" +#include "bmpendian.h" + +/***************************************************************************** + * + * Mid-level functions. + * + * These functions read in the various structures defined in bmptypes.h. Each + * function assumes that the file pointer is positioned at the start of the + * given structure. Upon completion, each function will leave the file + * pointer positioned on the byte immediately following the structure. Return + * values will be 0 for success and non-zero for failure. In all cases, a + * return value of non-zero means that the file position has been left in an + * indeterminate state and further reading should not be attempted. + */ + +/* + * Read a Bitmapfileheader structure. + */ +CGAL_INLINE_FUNCTION +int readBitmapFileHeader(FILE *fp, Bitmapfileheader *bfh) +{ + int rc; + + rc = readUINT16little(fp, &(bfh->type)); + if (rc != 0) + return rc; + + rc = readUINT32little(fp, &(bfh->size)); + if (rc != 0) + return rc; + + rc = readINT16little(fp, &(bfh->xHotspot)); + if (rc != 0) + return rc; + + rc = readINT16little(fp, &(bfh->yHotspot)); + if (rc != 0) + return rc; + + rc = readUINT32little(fp, &(bfh->offsetToBits)); + return rc; +} + +/* + * Read a BITMAPARRAYHEADER + */ +CGAL_INLINE_FUNCTION +int readBitmapArrayHeader(FILE *fp, BITMAPARRAYHEADER *bah) +{ + int rc; + + rc = readUINT16little(fp, &(bah->type)); + if (rc != 0) + return rc; + rc = readUINT32little(fp, &(bah->size)); + if (rc != 0) + return rc; + rc = readUINT32little(fp, &(bah->next)); + if (rc != 0) + return rc; + rc = readUINT16little(fp, &(bah->screenWidth)); + if (rc != 0) + return rc; + rc = readUINT16little(fp, &(bah->screenHeight)); + return rc; +} + +/* + * Read the BITMAPHEADER structure. This one requires a bit of sanity + * checking. The length of the structure on the disk is specified in the + * first field. We must stop reading after that many bytes, and if that value + * is longer than sizeof(BITMAPHEADER), we must skip over any leftover bytes. + * Finally, if size is 12, then width an height are really 16-bit values, and + * we have to read them differently so they'll be properly stored in the + * 32-bit fields BITMAPHEADER uses. + */ +CGAL_INLINE_FUNCTION +int readBitmapHeader(FILE *fp, BITMAPHEADER *bh) +{ + int rc, oldFormat; + unsigned int bytesRead; + CGAL_UINT16 tempVal; + + /* + * Clear the structure. Default values for all fields are zeros. This + * will prevent garbage from being returned if the structure is truncated + * on disk. + */ + memset(bh, 0, sizeof(BITMAPHEADER)); + + /* + * Read the size of the structure. From here on in, we'll have to be sure + * we don't read more bytes than this value. + */ + rc = readUINT32little(fp, &(bh->size)); + if (rc != 0) + return rc; + bytesRead = 4; + + /* + * If the size is 12 bytes or less, than this is an "old format" + * structure. So the width and height fields will have to be read + * differently. + */ + if (bh->size <= 12) + oldFormat = 1; + else + oldFormat = 0; + + /* + * Width and height are read differently for old and new format files. In + * the old format, they're 16-bit values. In the new format, they're + * 32-bits long. + */ + if (oldFormat) + { + rc = readUINT16little(fp, &tempVal); + if (rc != 0) + return rc; + bh->width = tempVal; + bytesRead += 2; + } + else + { + rc = readINT32little(fp, &(bh->width)); + if (rc != 0) + return rc; + bytesRead += 4; + } + if (bytesRead >= bh->size) + return 0; + + if (oldFormat) + { + rc = readUINT16little(fp, &tempVal); + if (rc != 0) + return rc; + bh->height = tempVal; + bytesRead += 2; + } + else + { + rc = readINT32little(fp, &(bh->height)); + if (rc != 0) + return rc; + bytesRead += 4; + } + if (bytesRead >= bh->size) + return 0; + + /* + * From this point on, old and new formats are identical to each other, + * and we can proceed as if there was no difference. For each field, we + * read it in and increment the count of bytes read. If at any time we + * have read the amount we got earlier (in the size field), then stop and + * leave the rest of the fields as zeros. + */ + rc = readUINT16little(fp, &(bh->numBitPlanes)); + if (rc != 0) + return rc; + bytesRead += 2; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT16little(fp, &(bh->numBitsPerPlane)); + if (rc != 0) + return rc; + bytesRead += 2; + if (bytesRead >= bh->size) + return 0; + + /* + * Old format stop here. But we don't have to check, because in that + * format, 12 bytes have been read and the function will have exited + * without any extra checking. + */ + rc = readUINT32little(fp, &(bh->compressionScheme)); + if (rc != 0) + return rc; + bytesRead += 4; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT32little(fp, &(bh->sizeOfImageData)); + if (rc != 0) + return rc; + bytesRead += 4; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT32little(fp, &(bh->xResolution)); + if (rc != 0) + return rc; + bytesRead += 4; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT32little(fp, &(bh->yResolution)); + if (rc != 0) + return rc; + bytesRead += 4; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT32little(fp, &(bh->numColorsUsed)); + if (rc != 0) + return rc; + bytesRead += 4; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT32little(fp, &(bh->numImportantColors)); + if (rc != 0) + return rc; + bytesRead += 4; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT16little(fp, &(bh->resolutionUnits)); + if (rc != 0) + return rc; + bytesRead += 2; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT16little(fp, &(bh->padding)); + if (rc != 0) + return rc; + bytesRead += 2; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT16little(fp, &(bh->origin)); + if (rc != 0) + return rc; + bytesRead += 2; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT16little(fp, &(bh->halftoning)); + if (rc != 0) + return rc; + bytesRead += 2; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT32little(fp, &(bh->halftoningParam1)); + if (rc != 0) + return rc; + bytesRead += 4; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT32little(fp, &(bh->halftoningParam2)); + if (rc != 0) + return rc; + bytesRead += 4; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT32little(fp, &(bh->colorEncoding)); + if (rc != 0) + return rc; + bytesRead += 4; + if (bytesRead >= bh->size) + return 0; + + rc = readUINT32little(fp, &(bh->identifier)); + if (rc != 0) + return rc; + bytesRead += 4; + if (bytesRead >= bh->size) + return 0; + + /* + * If there are more bytes in the file than this, then the file is using a + * future format that doesn't exist yet. Skip over the bytes. Assuming + * this future format somewhat resembles what we know now, ignoring the + * fields will be safe. We _MUST_ skip them, though, since the color + * table begins on the byte after this structure, and we have to position + * the file pointer there. + */ + return fseek(fp, (bh->size - bytesRead), SEEK_CUR); +} + + +/* + * readRgb reads in a single RGB structure from the disk. The numBytes field + * indicates how many bytes the field occupies on the disk. It assumes that + * each component is one byte on disk and the rest is padding. This will + * compensate for the old/new differences in color tables. (Old format + * bitmaps use 3 bytes per entry, while new format bitmaps use 4.) Note how + * it will never read more than the number of bytes requested. + */ +CGAL_INLINE_FUNCTION +int readRgb(FILE *fp, RGB *rgb, int numBytes) +{ + int rc; + + if (numBytes == 0) + return 0; + rc = readUINT8little(fp, &(rgb->blue)); + if (rc != 0) + return rc; + + if (numBytes == 1) + return 0; + rc = readUINT8little(fp, &(rgb->green)); + if (rc != 0) + return rc; + + if (numBytes == 2) + return 0; + rc = readUINT8little(fp, &(rgb->red)); + if (rc != 0) + return rc; + + if (numBytes == 3) + return 0; + + /* Skip over extra bytes if more than three were requested */ + return fseek(fp, (numBytes - 3), SEEK_CUR); +} + +/* + * A color table is a block of RGB structures, all the same size. Read it by + * calling readRgb repeatedly. + */ +CGAL_INLINE_FUNCTION +int readColorTable(FILE *fp, RGB *rgb, int numEntries, int numBytesPerEntry) +{ + int i, rc; + + for (i=0; i 24)) + padBytes = 0; + else if ((width % 32) <= 8) + padBytes = 3; + else if ((width % 32) <= 16) + padBytes = 2; + else + padBytes = 1; + + for (row = height; row > 0; row--) + { + for (column = width; column > 0; column -= 8) + { + rc = readUINT8little(fp, &temp); + if (rc != 0) + return rc; + for (i=0; i < ((column < 8) ? column : 8); i++) + { + /* + * For each byte read, bit-decompose it. Note that the + * last byte on a row could have less than 8 bits used. + * Most significant bits come first. + */ + value = ((temp & (1 << (7-i))) == 0) ? 0 : 1; + image[pixel].red = colorTable[value].red; + image[pixel].green = colorTable[value].green; + image[pixel].blue = colorTable[value].blue; + pixel++; + } + } + if (padBytes != 0) + { + rc = fseek(fp, padBytes, SEEK_CUR); + if (rc != 0) + return rc; + } + } + break; + + case 4: + /* + * For 4 bits per pixel, each byte is two pixels. The upper half go to + * the first pixel, and the lower half to the second. + */ + pixel = 0; + if (((width % 8) == 0) || ((width % 8) > 6)) + padBytes = 0; + else if ((width % 8) <= 2) + padBytes = 3; + else if ((width % 8) <= 4) + padBytes = 2; + else + padBytes = 1; + + for (row = height; row > 0; row--) + { + for (column = width; column > 0; column -= 2) + { + /* + * Each byte here is two pixels. Note that the last byte on a + * row may only contain one pixel. + */ + rc = readUINT8little(fp, &temp); + if (rc != 0) + return rc; + /* + * First pixel is the upper 4 bits + */ + value = temp >> 4; + image[pixel].red = colorTable[value].red; + image[pixel].green = colorTable[value].green; + image[pixel].blue = colorTable[value].blue; + pixel++; + + /* + * Second pixel is lower 4 bits. If this is the last byte in + * the row, and there are an odd number of pixels per row, then + * this is not valid data. + */ + if (column == 1) + { + value = temp & 0x0f; + image[pixel].red = colorTable[value].red; + image[pixel].green = colorTable[value].green; + image[pixel].blue = colorTable[value].blue; + pixel++; + } + } + if (padBytes != 0) + { + rc = fseek(fp, padBytes, SEEK_CUR); + if (rc != 0) + return rc; + } + } + break; + + case 8: + /* + * For 8 bits per pixel, each byte is one pixel. + */ + pixel = 0; + padBytes = ((width % 4) == 0) ? 0 : (4 - (width % 4)); + + for (row=height; row > 0; row--) + { + for (column=width; column > 0; column--) + { + rc = readUINT8little(fp, &temp); + if (rc != 0) + return rc; + image[pixel].red = colorTable[temp].red; + image[pixel].green = colorTable[temp].green; + image[pixel].blue = colorTable[temp].blue; + pixel++; + } + if (padBytes != 0) + { + rc = fseek(fp, padBytes, SEEK_CUR); + if (rc != 0) + return rc; + } + } + break; + + case 16: + /* + * For 16 bits per pixel, you must read two bytes per pixel. But + * there's a catch. The data is big endian! This is because all pixel + * data (for all formats, actually) is stored as a packed array, + * stored in pixel order. + */ + pixel = 0; + padBytes = ((width % 2) == 0) ? 0 : 2; + for (row=height; row > 0; row--) + { + for (column=width; column > 0; column--) + { + /* + * Read a 16-bit integer as big endian. Do this by reading + * two bytes and mathematically combine them. After that, + * proceed as usual. + */ + rc = readUINT8little(fp, &temp); + if (rc != 0) + return rc; + value = ((long)temp) << 8; + rc = readUINT8little(fp, &temp); + if (rc != 0) + return rc; + value |= temp; + + image[pixel].red = colorTable[value].red; + image[pixel].green = colorTable[value].green; + image[pixel].blue = colorTable[value].blue; + pixel++; + } + if (padBytes != 0) + { + rc = fseek(fp, padBytes, SEEK_CUR); + if (rc != 0) + return rc; + } + } + break; + + case 24: + /* + * For 24 bits per pixel, it's an RGB structure. Note that the color + * table is ignore for bit depths greater than 24 bits. + */ + pixel = 0; + padBytes = width % 4; + + for (row=height; row > 0; row--) + { + for (column=width; column > 0; column--) + { + rc = readRgb(fp, image+pixel, 3); + pixel++; + } + if (padBytes != 0) + { + rc = fseek(fp, padBytes, SEEK_CUR); + if (rc != 0) + return rc; + } + } + break; + } + + return 0; +} + + +/* + * ReadMaskBitsUncompressed. Reads a monochrome mask into an array of + * characters. It assmes that there is no compression. This is very similar + * (internally) to the readBitsUncompressed function. Note that if the data + * read isn't really one-bit-deep data, you'll probably get garbage back. + */ +CGAL_INLINE_FUNCTION +int readMaskBitsUncompressed(FILE *fp, char *image, int width, int height) +{ + CGAL_UINT8 temp; + int rc, padBytes, i; + long row, column, pixel; + char value; + + /* + * see the one-bit-depth part of readBitsUncompressed for comments + */ + pixel = 0; + if (((width % 32) == 0) || ((width % 32) > 24)) + padBytes = 0; + else if ((width % 32) <= 8) + padBytes = 3; + else if ((width % 32) <= 16) + padBytes = 2; + else + padBytes = 1; + + for (row = height; row > 0; row--) + { + for (column = width; column > 0; column -= 8) + { + rc = readUINT8little(fp, &temp); + if (rc != 0) + return rc; + for (i=0; i < ((column < 8) ? column : 8); i++) + { + value = ((temp & (1 << (7-i))) == 0) ? 0 : 1; + image[pixel] = value; + pixel++; + } + } + if (padBytes != 0) + { + rc = fseek(fp, padBytes, SEEK_CUR); + if (rc != 0) + return rc; + } + } + + return 0; +} + + +/* + * reflectYRGB takes an array of RGB vales and the dimensions they represent + * and flips it vertically. This will convert a bottom-left origin array to a + * top-left origin array. + */ +CGAL_INLINE_FUNCTION +void reflectYRGB(RGB *image, int width, int height) +{ + int row, col; + RGB temp; + + for (row = 0; row < (height / 2); row++) + { + for (col = 0; col < width; col++) + { + /* Swap pixels at (x,y) with (x,height-y) */ + memcpy(&temp, image+(row * width + col), sizeof(RGB)); + memcpy(image+(row * width + col), + image+((height - row - 1) * width + col), sizeof(RGB)); + memcpy(image+((height - row - 1) * width + col), &temp, + sizeof(RGB)); + } + } +} +/* + * reflectYchar takes an array of char values and the dimensions they + * represent and flips it vertically. This will convert a bottom-left origin + * array to a top-left origin array. + */ +CGAL_INLINE_FUNCTION +void reflectYchar(char *image, int width, int height) +{ + int row, col; + char temp; + + for (row = 0; row < (height / 2); row++) + { + for (col = 0; col < width; col++) + { + /* Swap values at (x,y) with (x,height-y) */ + temp = image[row * width + col]; + image[row * width + col]=image[(height - row - 1) * width + col]; + image[(height - row - 1) * width + col] = temp; + } + } +} + +/***************************************************************************** + * + * High-level functions + * + * These functions read in specific types of bitmap files. Each assumes that + * the file pointer is positioned at the appropriate place in a bitmap file. + * (At the start of a Bitmapfileheader for all functions except + * readMultipleImages, which assumes the file pointer to be positioned on the + * start of a BITMAPARRAYHEADER. These functions will leave the file pointer + * on the byte after the image's color table. + * + * The coordinate speaces in the returned arrays will have an upper-left + * origin. As before, a non-zero return value indicates that something went + * wrong. + * + * Note that the BMP and mono-ICO functions will not return 1000 if the image + * is of type color-icon. This is because a color icon consists of a bitmap + * and a monochrome icon. + * + * return values: + * 0 - success + * 1000 - incorrect file type for the routine called + * 1001 - image data out of range or damaged file + * 1002 - good data, but the routine called can't handle it (yet) + * 1003 - out of memory allocating color table + * 1004 - out of memory allocating image + * 1005 - out of memory allocating image arrays + * 1006 - Illegal image type in a multi-image array + * + * other - I/O error of some kind + */ + + +/* + * readSingleImageBMP will read a single BMP image and generate an array of RGB + * triples that contain the RGB values for every pixel. It will also return + * the dimensions of the image. + */ +CGAL_INLINE_FUNCTION +int readSingleImageBMP(FILE *fp, RGB **argb, CGAL_UINT32 *width, CGAL_UINT32 *height) +{ + Bitmapfileheader bfh; + BITMAPHEADER bh; + RGB *colorTable = (RGB*)NULL; + RGB *image = (RGB*)NULL; + int rc, depth, inverted; + long numColors, numPixels, endPos; + + /* + * First, get the file header and sanity check it. The type field must be + * TYPE_BMP or we're aborting. + */ + rc = readBitmapFileHeader(fp, &bfh); + if (rc != 0) + return rc; + if ((bfh.type != TYPE_BMP) && + (bfh.type != TYPE_ICO_COLOR) && + (bfh.type != TYPE_PTR_COLOR)) + return 1000; + + /* + * Immediately following a file header is always the bitmap header. Read + * it. Sanity check any values we might need. Specifically, less than + * 32-bit depth, known compression scheme, known origin, and known color + * encoding, and valid height/width. Note that negative height is OK, + * that indicates an upper-left origin for a Windows bitmap. + */ + rc = readBitmapHeader(fp, &bh); + if (rc != 0) + return rc; + depth = bh.numBitPlanes * bh.numBitsPerPlane; + if ((depth > 32) || + (bh.compressionScheme > COMPRESSION_LAST) || + (bh.origin > ORIGIN_LAST) || + (bh.colorEncoding > COLOR_ENCODING_LAST) || + (bh.width < 1) || + (bh.height == 0)) + return 1001; + + /* + * If the height is negative, then this is a Windows bitmap whose origin + * is the upper-left corner and not the lower-left. The inverted flag + * indicates a lower-left origin. Our code will be outputting an + * upper-left origin pixel array. + */ + if (bh.height < 0) + { + inverted = 0; + bh.height = -bh.height; + } + else + inverted = 1; + + /* + * Now, sanity check a few fields that are valid, but I don't have code to + * deal with them yet. This includes: more than one bit plane, any + * compression scheme, and bit depths that are not 1, 4, 8, 16, or 24. + */ + if ((bh.numBitPlanes > 1) || + ((bh.numBitsPerPlane != 1) && + (bh.numBitsPerPlane != 4) && + (bh.numBitsPerPlane != 8) && + (bh.numBitsPerPlane != 16) && + (bh.numBitsPerPlane != 24)) || + (bh.compressionScheme != COMPRESSION_NONE)) + return 1002; + + /* + * Allocate and read the color table. The file pointer has been + * positioned in the right place by the readBitmapHeader function. Note + * that images with 24-bits or more color depth have no color table. They + * are already RGB. When reading the color table, be sure to check for + * old/new format bitmaps. + */ + if (depth < 24) + { + numColors = 1 << depth; + colorTable = (RGB *)calloc(numColors, sizeof(RGB)); + if (colorTable == NULL) + return 1003; + if (bh.size <= 12) + rc = readColorTable(fp, colorTable, numColors, 3); + else + rc = readColorTable(fp, colorTable, numColors, 4); + if (rc != 0) + { + free(colorTable); + return rc; + } + } + + /* + * We're at the end of the color table. Preserve this position. We'll + * need to leave the file pointer there before returning from this + * function. + */ + endPos = ftell(fp); + + /* + * Allocate the array of pixels and fill it in. + */ + numPixels = bh.width * bh.height; + image = (RGB *)calloc(numPixels, sizeof(RGB)); + if (image == NULL) + { + free (colorTable); + return 1004; + } + + /* + * Seek to the bits + */ + rc = fseek(fp, bfh.offsetToBits, SEEK_SET); + if (rc != 0) + { + free (colorTable); + free (image); + return rc; + } + + /* + * Read the bits. If code for decompressing bits should be written, + * insert the call here. + */ + switch ((int)bh.compressionScheme) { + case COMPRESSION_NONE: + rc = readBitsUncompressed(fp, image, bh.width, bh.height, depth, + colorTable); + break; + } + + if (rc != 0) + { + free(image); + return rc; + } + + /* + * If the origin is lower-left, flip the image upside down + */ + if (inverted) + reflectYRGB(image, bh.width, bh.height); + + /* + * Return the output values. Set the file pointer to the byte after the + * color table. + */ + *argb = image; + *width = bh.width; + *height = bh.height; + fseek(fp, endPos, SEEK_SET); + + /* + * Clean up and return. Note that we don't return the color table. This + * is because we're returning an array of RGB values for the image - such + * a table would be redundant. + */ + if (colorTable != NULL) + free(colorTable); + + return 0; +} + + +/* + * Read in a monochrome OS/2 icon/pointer. return two arrays of bytes + * (interpreted as booleans) for the XOR and AND masks. + */ +CGAL_INLINE_FUNCTION +int readSingleImageICOPTR(FILE *fp, char **xorMask, char **andMask, + CGAL_UINT32 *width, CGAL_UINT32 *height) +{ + Bitmapfileheader bfh; + BITMAPHEADER bh; + char *mask1, *mask2; + int rc; + long numPixels, endPos; + + /* + * Read and sanity check the header. Monochrom OS/2 icons are TYPE_ICO. + * Monochrome pointers are TYPE_PTR. Color ICO and PTR is also allowed, + * because monochrome masks are part of those images. + */ + rc = readBitmapFileHeader(fp, &bfh); + if (rc != 0) + return rc; + if ((bfh.type != TYPE_ICO) && + (bfh.type != TYPE_PTR) && + (bfh.type != TYPE_ICO_COLOR) && + (bfh.type != TYPE_PTR_COLOR)) + return 1000; + + /* + * Now read the bitmap data and sanity check it. Since this is a + * monochrome icon, bit depth must be 1. Additionally, a known + * compression scheme, known origin, known color encoding, and valid + * height/width. Height can't be less than 0, as it can with color + * images, since this code is only used on for OS/2-type images. + */ + rc = readBitmapHeader(fp, &bh); + if (rc != 0) + return rc; + if ((bh.numBitPlanes != 1) || + (bh.numBitsPerPlane != 1) || + (bh.compressionScheme > COMPRESSION_LAST) || + (bh.origin > ORIGIN_LAST) || + (bh.colorEncoding > COLOR_ENCODING_LAST) || + (bh.width < 1) || + (bh.height < 1)) + return 1001; + + /* + * Sanity check some valid fields that I can't deal with yet. + */ + if (bh.compressionScheme != COMPRESSION_NONE) + return 1002; + + /* + * Skip over the color table, since this is a monochrome mask. Note that + * the size is already known - 2 entries - which is 6 or 8 bytes. + * this isn't, and we don't. + */ + if (bh.size <= 12) + rc = fseek(fp, 6, SEEK_CUR); + else + rc = fseek(fp, 8, SEEK_CUR); + if (rc != 0) + { + return rc; + } + + /* + * Save this file position. we'll have to seek back to it after reading + * in the image data. + */ + endPos = ftell(fp); + + /* + * The image is actually two images. The top half is an AND mask and the + * bottom half is an XOR mask. Allocate the images. + */ + numPixels = bh.width * bh.height / 2; + mask1 = (char *)malloc(numPixels); + if (mask1 == NULL) + return 1004; + mask2 = (char *)malloc(numPixels); + if (mask2 == NULL) + { + free(mask1); + return 1004; + } + + /* + * Seek to the bit data + */ + rc = fseek(fp, bfh.offsetToBits, SEEK_SET); + if (rc != 0) + { + free (mask1); + free (mask2); + return rc; + } + + /* + * Read in the bits. Note: since these are really two images, two calls + * to readMaskBitsUncompressed are made, and the height used is 1/2 the + * height mentioned in the header. + */ + switch ((int) bh.compressionScheme) { + case COMPRESSION_NONE: + rc = readMaskBitsUncompressed(fp, mask1, bh.width, bh.height/2); + if (rc == 0) + rc = readMaskBitsUncompressed(fp, mask2, bh.width, bh.height/2); + break; + } + + if (rc != 0) + { + free (mask1); + free (mask2); + return rc; + } + + /* + * A mask will never have an upper-left origin, since Windows will never + * produce one in a bitmap file. + */ + reflectYchar(mask1, bh.width, bh.height / 2); + reflectYchar(mask2, bh.width, bh.height / 2); + + /* + * Return everything we've read. + */ + *xorMask = mask1; + *andMask = mask2; + *width = bh.width; + *height = bh.height / 2; + fseek(fp, endPos, SEEK_SET); + + return 0; +} + + +/* + * Read in a color OS/2 icon. return an array of RGBs for the colors. + * and two arrays of bytes (interpreted as booleans) for the XOR and AND + * masks. + */ +CGAL_INLINE_FUNCTION +int readSingleImageColorICOPTR(FILE *fp, RGB **argb, char **xorMask, + char **andMask, CGAL_UINT32 *width, CGAL_UINT32 *height) +{ + CGAL_UINT32 width1, height1, width2, height2; + int rc; + + /* + * Color icons consist of a monochrome icon followed by a bitmap. This + * makes reading them easy - first do a monochrome mask read, and then do + * a color bitmap read. We should probably add some more descriptive + * error codes here. + * + * First read the mask. + */ + rc = readSingleImageICOPTR(fp, xorMask, andMask, &width2, &height2); + if (rc != 0) + { + return rc; + } + + /* + * Next, read the color bitmap part + */ + rc = readSingleImageBMP(fp, argb, &width1, &height1); + if (rc != 0) + { + return rc; + } + + /* + * Now, just sanity check the image - the dimensions for the image should + * match the dimensions of the masks. + */ + if ((width1 != width2) || (height1 != height2)) + return 1001; + + *width = width1; + *height = height1; + return 0; +} + + +/* + * readMultipleImage runs down the list of images in a file and returns them + * all. ImageCount is the number of images in the file. The other returned + * values are parallel arrays. If an element in aargb, axorMask, or aandMask + * is NULL, then that image has no such array. (Bitmaps have no xor or and + * masks, monochrome icons have no color arrays. + * + * Note that on errors other than 1000 and 1005, the arrays will contain good + * data - the images that have been read properly will be in the arrays. + * Images that have not yet been read will consist of NULL pointers in the + * arrays. + */ +CGAL_INLINE_FUNCTION +int readMultipleImage(FILE *fp, RGB ***argbs, char ***xorMasks, + char ***andMasks, CGAL_UINT32 **widths, CGAL_UINT32 **heights, + int *imageCount) +{ + int rc; + long filePos; + BITMAPARRAYHEADER bah; + CGAL_UINT16 imageType; + int count; + + /* + * First count the images. Preserve the file position for later. If some + * structure in the list isn't an array header, return 1000. + */ + filePos = ftell(fp); + count = 0; + do + { + rc = readBitmapArrayHeader(fp, &bah); + if (rc != 0) + return rc; + if (bah.type != TYPE_ARRAY) + return 1000; + fseek(fp, bah.next, SEEK_SET); + count++; + } while (bah.next != 0); + fseek(fp, filePos, SEEK_SET); + + /* + * Allocate the arrays. Return 1005 on any failures + */ + *argbs = (RGB **)calloc(count, sizeof(RGB *)); + if (*argbs == NULL) + return 1005; + *xorMasks = (char **)calloc(count, sizeof(char *)); + if (*xorMasks == NULL) + { + free(*argbs); + return 1005; + } + *andMasks = (char **)calloc(count, sizeof(char *)); + if (*andMasks == NULL) + { + free(*argbs); + free(*xorMasks); + return 1005; + } + *widths = (CGAL_UINT32 *)calloc(count, sizeof(CGAL_UINT32)); + if (*widths == NULL) + { + free(*argbs); + free(*xorMasks); + free(*andMasks); + return 1005; + } + *heights = (CGAL_UINT32 *)calloc(count, sizeof(CGAL_UINT32)); + if (*heights == NULL) + { + free(*argbs); + free(*xorMasks); + free(*andMasks); + free(*widths); + return 1005; + } + *imageCount = count; + + /* + * Loop through the images again. This time, read each image + */ + count = 0; + do + { + rc = readBitmapArrayHeader(fp, &bah); + if (rc != 0) + return rc; + /* + * Get the image type. Preserve the position, since we're reading + * into the next structure. + */ + filePos = ftell(fp); + rc = readUINT16little(fp, &imageType); + if (rc != 0) + return rc; + rc = fseek(fp, filePos, SEEK_SET); + + /* + * Now that we know what kind of image we're about to read, read it. + */ + switch(imageType) { + case TYPE_BMP: + rc = readSingleImageBMP(fp, (*argbs)+count, (*widths)+count, + (*heights)+count); + break; + case TYPE_ICO: + case TYPE_PTR: + rc = readSingleImageICOPTR(fp, (*xorMasks)+count, + (*andMasks)+count, (*widths)+count, + (*heights)+count); + break; + case TYPE_ICO_COLOR: + case TYPE_PTR_COLOR: + rc = readSingleImageColorICOPTR(fp, (*argbs)+count, + (*xorMasks)+count, + (*andMasks)+count, + (*widths)+count, + (*heights)+count); + break; + default: + return 1006; + } + if (rc != 0) + return rc; + + fseek(fp, bah.next, SEEK_SET); + count++; + } while (bah.next != 0); + + return 0; +} + + +/* + * Formatting information for emacs in c-mode + * + * Local Variables: + * c-indent-level:4 + * c-continued-statement-offset:4 + * c-brace-offset:-4 + * c-brace-imaginary-offset:0 + * c-argdecl-indent:4 + * c-label-offset:-4 + * End: + */ + diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/convert.cpp b/CGAL_ImageIO/src/CGAL_ImageIO/convert.cpp index b1223cabac2..52e879286b4 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/convert.cpp +++ b/CGAL_ImageIO/src/CGAL_ImageIO/convert.cpp @@ -19,463 +19,9 @@ // // Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau -/************************************************************************* - * convert.c - conversion between types - * - * $Id$ - * - * Copyright©INRIA 1999 - * - * AUTHOR: - * Gregoire Malandain (greg@sophia.inria.fr) - * - * CREATION DATE: - * June, 9 1998 - * - * ADDITIONS, CHANGES - * - * - Tue Feb 22 11:25:39 MET 2000 (G. Malandain) - * add in ConvertBuffer(): - * USHORT to UCHAR - * USHORT to SHORT - * - */ +#ifndef CGAL_HEADER_ONLY #include "convert.h" +#include "convert_impl.h" -void ConvertBuffer( void *bufferIn, - bufferType typeIn, - void *bufferOut, - bufferType typeOut, - int bufferLength ) -{ - const char *proc = "ConvertBuffer"; - register int i, min, max; - register u8 *u8buf; - register s8 *s8buf; - register u16 *u16buf; - register s16 *s16buf; - register s32 *s32buf; - register r32 *r32buf; - register r64 *r64buf; - - if ( (typeOut == typeIn) && (bufferOut == bufferIn) ) - return; - - if ( bufferLength <= 0 ) { - fprintf( stderr, " Fatal error in %s: buffer length is negative or zero.\n", - proc ); - return; - } - if ( (bufferIn == (void*)NULL) || (bufferOut == (void*)NULL) ) { - fprintf( stderr, " Fatal error in %s: NULL buffer(s).\n", - proc ); - return; - } - - switch ( typeOut ) { - case CGAL_SCHAR : - s8buf = (s8*)bufferOut; - min = -128; max = 127; - switch( typeIn ) { - case CGAL_SCHAR : - if ( bufferOut == bufferIn ) return; - (void)memcpy( bufferOut, bufferIn, bufferLength * sizeof(s8) ); - break; - case CGAL_FLOAT : - r32buf = (r32*)bufferIn; - for (i=bufferLength; i>0; i--, s8buf++, r32buf++ ) { - if ( *r32buf < min ) *s8buf = min; - else if ( *r32buf < 0.0 ) *s8buf = (int)(*r32buf - 0.5); - else if ( *r32buf < max ) *s8buf = (int)(*r32buf + 0.5); - else *s8buf = max; - } - break; - case CGAL_DOUBLE : - r64buf = (r64*)bufferIn; - for (i=bufferLength; i>0; i--, s8buf++, r64buf++ ) { - if ( *r64buf < min ) *s8buf = min; - else if ( *r64buf < 0.0 ) *s8buf = (int)(*r64buf - 0.5); - else if ( *r64buf < max ) *s8buf = (int)(*r64buf + 0.5); - else *s8buf = max; - } - break; - default : - fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", - proc ); - return; - } - break; /* end case typeOut = CGAL_SCHAR */ - - - - - - case CGAL_UCHAR : - u8buf = (u8*)bufferOut; - min = 0; max = 255; - switch( typeIn ) { - case CGAL_UCHAR : - if ( bufferOut == bufferIn ) return; - (void)memcpy( bufferOut, bufferIn, bufferLength * sizeof(u8) ); - break; - case CGAL_USHORT : - u16buf = (u16*)bufferIn; - for (i=bufferLength; i>0; i--, u8buf++, u16buf++ ) { - if ( *u16buf < max ) *u8buf = (u8)*u16buf; - else *u8buf = max; - } - break; - case CGAL_FLOAT : - r32buf = (r32*)bufferIn; - for (i=bufferLength; i>0; i--, u8buf++, r32buf++ ) { - if ( *r32buf < min ) *u8buf = min; - else if ( *r32buf < max ) *u8buf = (int)(*r32buf + 0.5); - else *u8buf = max; - } - break; - case CGAL_DOUBLE : - r64buf = (r64*)bufferIn; - for (i=bufferLength; i>0; i--, u8buf++, r64buf++ ) { - if ( *r64buf < min ) *u8buf = min; - else if ( *r64buf < max ) *u8buf = (int)(*r64buf + 0.5); - else *u8buf = max; - } - break; - default : - fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", - proc ); - return; - } - break; /* end case typeOut = CGAL_UCHAR */ - - - - - - - case CGAL_SSHORT : - s16buf = (s16*)bufferOut; - min = -32768; max = 32767; - switch( typeIn ) { - case CGAL_SSHORT : - if ( bufferOut == bufferIn ) return; - (void)memcpy( bufferOut, bufferIn, bufferLength * sizeof(s16) ); - break; - case CGAL_USHORT : - u16buf = (u16*)bufferIn; - for (i=bufferLength; i>0; i--, s16buf++, u16buf++ ) { - if ( *u16buf < max ) *s16buf = (s16)*u16buf; - else *s16buf = max; - } - break; - case CGAL_FLOAT : - r32buf = (r32*)bufferIn; - for (i=bufferLength; i>0; i--, s16buf++, r32buf++ ) { - if ( *r32buf < min ) *s16buf = min; - else if ( *r32buf < 0.0 ) *s16buf = (int)(*r32buf - 0.5); - else if ( *r32buf < max ) *s16buf = (int)(*r32buf + 0.5); - else *s16buf = max; - } - break; - case CGAL_DOUBLE : - r64buf = (r64*)bufferIn; - for (i=bufferLength; i>0; i--, s16buf++, r64buf++ ) { - if ( *r64buf < min ) *s16buf = min; - else if ( *r64buf < 0.0 ) *s16buf = (int)(*r64buf - 0.5); - else if ( *r64buf < max ) *s16buf = (int)(*r64buf + 0.5); - else *s16buf = max; - } - break; - default : - fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", - proc ); - return; - } - break; /* end case typeOut = CGAL_SSHORT */ - - - - - - case CGAL_USHORT : - u16buf = (u16*)bufferOut; - min = 0; max = 65535; - switch( typeIn ) { - case CGAL_USHORT : - if ( bufferOut == bufferIn ) return; - (void)memcpy( bufferOut, bufferIn, bufferLength * sizeof(u16) ); - break; - case CGAL_FLOAT : - r32buf = (r32*)bufferIn; - for (i=bufferLength; i>0; i--, u16buf++, r32buf++ ) { - if ( *r32buf < min ) *u16buf = min; - else if ( *r32buf < 0.0 ) *u16buf = (int)(*r32buf - 0.5); - else if ( *r32buf < max ) *u16buf = (int)(*r32buf + 0.5); - else *u16buf = max; - } - break; - case CGAL_DOUBLE : - r64buf = (r64*)bufferIn; - for (i=bufferLength; i>0; i--, u16buf++, r64buf++ ) { - if ( *r64buf < min ) *u16buf = min; - else if ( *r64buf < 0.0 ) *u16buf = (int)(*r64buf - 0.5); - else if ( *r64buf < max ) *u16buf = (int)(*r64buf + 0.5); - else *u16buf = max; - } - break; - default : - fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", - proc ); - return; - } - break; /* end case typeOut = CGAL_USHORT */ - - - - - - - case CGAL_INT : - s32buf = (s32*)bufferOut; - switch( typeIn ) { - case CGAL_INT : - if ( bufferOut == bufferIn ) return; - (void)memcpy( bufferOut, bufferIn, bufferLength * sizeof(s32) ); - break; - case CGAL_FLOAT : - r32buf = (r32*)bufferIn; - for (i=bufferLength; i>0; i--, s32buf++, r32buf++ ) { - *s32buf = (int)(*r32buf); - } - break; - case CGAL_DOUBLE : - r64buf = (r64*)bufferIn; - for (i=bufferLength; i>0; i--, s32buf++, r64buf++ ) { - *s32buf = (int)(*r64buf); - } - break; - default : - fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", - proc ); - return; - } - break; /* end case typeOut = CGAL_INT */ - - - - - - - case CGAL_FLOAT : - r32buf = (r32*)bufferOut; - switch( typeIn ) { - case CGAL_UCHAR : - u8buf = (u8*)bufferIn; - for (i=bufferLength; i>0; i--, r32buf++, u8buf++ ) { - *r32buf = (float)(*u8buf); - } - break; - case CGAL_SCHAR : - s8buf = (s8*)bufferIn; - for (i=bufferLength; i>0; i--, r32buf++, s8buf++ ) { - *r32buf = (float)(*s8buf); - } - break; - case CGAL_USHORT : - u16buf = (u16*)bufferIn; - for (i=bufferLength; i>0; i--, r32buf++, u16buf++ ) { - *r32buf = (float)(*u16buf); - } - break; - case CGAL_SSHORT : - s16buf = (s16*)bufferIn; - for (i=bufferLength; i>0; i--, r32buf++, s16buf++ ) { - *r32buf = (float)(*s16buf); - } - break; - case CGAL_INT : - s32buf = (s32*)bufferIn; - for (i=bufferLength; i>0; i--, r32buf++, s32buf++ ) { - *r32buf = (float)(*s32buf); - } - break; - case CGAL_FLOAT : - if ( bufferOut == bufferIn ) return; - (void)memcpy( bufferOut, bufferIn, bufferLength * sizeof(r32) ); - break; - case CGAL_DOUBLE : - r64buf = (r64*)bufferIn; - for (i=bufferLength; i>0; i--, r32buf++, r64buf++ ) { - *r32buf = (float)(*r64buf); - } - break; - default : - fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", - proc ); - return; - } - break; /* end case typeOut = CGAL_FLOAT */ - - - - - - case CGAL_DOUBLE : - r64buf = (r64*)bufferOut; - switch( typeIn ) { - case CGAL_UCHAR : - u8buf = (u8*)bufferIn; - for (i=bufferLength; i>0; i--, r64buf++, u8buf++ ) { - *r64buf = (double)(*u8buf); - } - break; - case CGAL_SCHAR : - s8buf = (s8*)bufferIn; - for (i=bufferLength; i>0; i--, r64buf++, s8buf++ ) { - *r64buf = (double)(*s8buf); - } - break; - case CGAL_USHORT : - u16buf = (u16*)bufferIn; - for (i=bufferLength; i>0; i--, r64buf++, u16buf++ ) { - *r64buf = (double)(*u16buf); - } - break; - case CGAL_SSHORT : - s16buf = (s16*)bufferIn; - for (i=bufferLength; i>0; i--, r64buf++, s16buf++ ) { - *r64buf = (double)(*s16buf); - } - break; - case CGAL_INT : - s32buf = (s32*)bufferIn; - for (i=bufferLength; i>0; i--, r64buf++, s32buf++ ) { - *r64buf = (double)(*s32buf); - } - break; - case CGAL_FLOAT : - r32buf = (r32*)bufferIn; - for (i=bufferLength; i>0; i--, r32buf++, r64buf++ ) { - *r64buf = (double)(*r32buf); - } - break; - case CGAL_DOUBLE : - if ( bufferOut == bufferIn ) return; - (void)memcpy( bufferOut, bufferIn, bufferLength * sizeof(r64) ); - break; - default : - fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", - proc ); - return; - } - break; /* end case typeOut = CGAL_DOUBLE */ - - - - - default : - fprintf( stderr, " Error in %s: such output type not yet handled.\n", - proc ); - return; - } -} - - - - - -void Convert_r32_to_s8( r32 *theBuf, - s8 *resBuf, - int size ) -{ - register int i; - register r32* tb = theBuf; - register s8* rb = resBuf; - - for ( i=0; i0; i--, s8buf++, r32buf++ ) { + if ( *r32buf < min ) *s8buf = min; + else if ( *r32buf < 0.0 ) *s8buf = (int)(*r32buf - 0.5); + else if ( *r32buf < max ) *s8buf = (int)(*r32buf + 0.5); + else *s8buf = max; + } + break; + case CGAL_DOUBLE : + r64buf = (r64*)bufferIn; + for (i=bufferLength; i>0; i--, s8buf++, r64buf++ ) { + if ( *r64buf < min ) *s8buf = min; + else if ( *r64buf < 0.0 ) *s8buf = (int)(*r64buf - 0.5); + else if ( *r64buf < max ) *s8buf = (int)(*r64buf + 0.5); + else *s8buf = max; + } + break; + default : + fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", + proc ); + return; + } + break; /* end case typeOut = CGAL_SCHAR */ + + + + + + case CGAL_UCHAR : + u8buf = (u8*)bufferOut; + min = 0; max = 255; + switch( typeIn ) { + case CGAL_UCHAR : + if ( bufferOut == bufferIn ) return; + (void)memcpy( bufferOut, bufferIn, bufferLength * sizeof(u8) ); + break; + case CGAL_USHORT : + u16buf = (u16*)bufferIn; + for (i=bufferLength; i>0; i--, u8buf++, u16buf++ ) { + if ( *u16buf < max ) *u8buf = (u8)*u16buf; + else *u8buf = max; + } + break; + case CGAL_FLOAT : + r32buf = (r32*)bufferIn; + for (i=bufferLength; i>0; i--, u8buf++, r32buf++ ) { + if ( *r32buf < min ) *u8buf = min; + else if ( *r32buf < max ) *u8buf = (int)(*r32buf + 0.5); + else *u8buf = max; + } + break; + case CGAL_DOUBLE : + r64buf = (r64*)bufferIn; + for (i=bufferLength; i>0; i--, u8buf++, r64buf++ ) { + if ( *r64buf < min ) *u8buf = min; + else if ( *r64buf < max ) *u8buf = (int)(*r64buf + 0.5); + else *u8buf = max; + } + break; + default : + fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", + proc ); + return; + } + break; /* end case typeOut = CGAL_UCHAR */ + + + + + + + case CGAL_SSHORT : + s16buf = (s16*)bufferOut; + min = -32768; max = 32767; + switch( typeIn ) { + case CGAL_SSHORT : + if ( bufferOut == bufferIn ) return; + (void)memcpy( bufferOut, bufferIn, bufferLength * sizeof(s16) ); + break; + case CGAL_USHORT : + u16buf = (u16*)bufferIn; + for (i=bufferLength; i>0; i--, s16buf++, u16buf++ ) { + if ( *u16buf < max ) *s16buf = (s16)*u16buf; + else *s16buf = max; + } + break; + case CGAL_FLOAT : + r32buf = (r32*)bufferIn; + for (i=bufferLength; i>0; i--, s16buf++, r32buf++ ) { + if ( *r32buf < min ) *s16buf = min; + else if ( *r32buf < 0.0 ) *s16buf = (int)(*r32buf - 0.5); + else if ( *r32buf < max ) *s16buf = (int)(*r32buf + 0.5); + else *s16buf = max; + } + break; + case CGAL_DOUBLE : + r64buf = (r64*)bufferIn; + for (i=bufferLength; i>0; i--, s16buf++, r64buf++ ) { + if ( *r64buf < min ) *s16buf = min; + else if ( *r64buf < 0.0 ) *s16buf = (int)(*r64buf - 0.5); + else if ( *r64buf < max ) *s16buf = (int)(*r64buf + 0.5); + else *s16buf = max; + } + break; + default : + fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", + proc ); + return; + } + break; /* end case typeOut = CGAL_SSHORT */ + + + + + + case CGAL_USHORT : + u16buf = (u16*)bufferOut; + min = 0; max = 65535; + switch( typeIn ) { + case CGAL_USHORT : + if ( bufferOut == bufferIn ) return; + (void)memcpy( bufferOut, bufferIn, bufferLength * sizeof(u16) ); + break; + case CGAL_FLOAT : + r32buf = (r32*)bufferIn; + for (i=bufferLength; i>0; i--, u16buf++, r32buf++ ) { + if ( *r32buf < min ) *u16buf = min; + else if ( *r32buf < 0.0 ) *u16buf = (int)(*r32buf - 0.5); + else if ( *r32buf < max ) *u16buf = (int)(*r32buf + 0.5); + else *u16buf = max; + } + break; + case CGAL_DOUBLE : + r64buf = (r64*)bufferIn; + for (i=bufferLength; i>0; i--, u16buf++, r64buf++ ) { + if ( *r64buf < min ) *u16buf = min; + else if ( *r64buf < 0.0 ) *u16buf = (int)(*r64buf - 0.5); + else if ( *r64buf < max ) *u16buf = (int)(*r64buf + 0.5); + else *u16buf = max; + } + break; + default : + fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", + proc ); + return; + } + break; /* end case typeOut = CGAL_USHORT */ + + + + + + + case CGAL_INT : + s32buf = (s32*)bufferOut; + switch( typeIn ) { + case CGAL_INT : + if ( bufferOut == bufferIn ) return; + (void)memcpy( bufferOut, bufferIn, bufferLength * sizeof(s32) ); + break; + case CGAL_FLOAT : + r32buf = (r32*)bufferIn; + for (i=bufferLength; i>0; i--, s32buf++, r32buf++ ) { + *s32buf = (int)(*r32buf); + } + break; + case CGAL_DOUBLE : + r64buf = (r64*)bufferIn; + for (i=bufferLength; i>0; i--, s32buf++, r64buf++ ) { + *s32buf = (int)(*r64buf); + } + break; + default : + fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", + proc ); + return; + } + break; /* end case typeOut = CGAL_INT */ + + + + + + + case CGAL_FLOAT : + r32buf = (r32*)bufferOut; + switch( typeIn ) { + case CGAL_UCHAR : + u8buf = (u8*)bufferIn; + for (i=bufferLength; i>0; i--, r32buf++, u8buf++ ) { + *r32buf = (float)(*u8buf); + } + break; + case CGAL_SCHAR : + s8buf = (s8*)bufferIn; + for (i=bufferLength; i>0; i--, r32buf++, s8buf++ ) { + *r32buf = (float)(*s8buf); + } + break; + case CGAL_USHORT : + u16buf = (u16*)bufferIn; + for (i=bufferLength; i>0; i--, r32buf++, u16buf++ ) { + *r32buf = (float)(*u16buf); + } + break; + case CGAL_SSHORT : + s16buf = (s16*)bufferIn; + for (i=bufferLength; i>0; i--, r32buf++, s16buf++ ) { + *r32buf = (float)(*s16buf); + } + break; + case CGAL_INT : + s32buf = (s32*)bufferIn; + for (i=bufferLength; i>0; i--, r32buf++, s32buf++ ) { + *r32buf = (float)(*s32buf); + } + break; + case CGAL_FLOAT : + if ( bufferOut == bufferIn ) return; + (void)memcpy( bufferOut, bufferIn, bufferLength * sizeof(r32) ); + break; + case CGAL_DOUBLE : + r64buf = (r64*)bufferIn; + for (i=bufferLength; i>0; i--, r32buf++, r64buf++ ) { + *r32buf = (float)(*r64buf); + } + break; + default : + fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", + proc ); + return; + } + break; /* end case typeOut = CGAL_FLOAT */ + + + + + + case CGAL_DOUBLE : + r64buf = (r64*)bufferOut; + switch( typeIn ) { + case CGAL_UCHAR : + u8buf = (u8*)bufferIn; + for (i=bufferLength; i>0; i--, r64buf++, u8buf++ ) { + *r64buf = (double)(*u8buf); + } + break; + case CGAL_SCHAR : + s8buf = (s8*)bufferIn; + for (i=bufferLength; i>0; i--, r64buf++, s8buf++ ) { + *r64buf = (double)(*s8buf); + } + break; + case CGAL_USHORT : + u16buf = (u16*)bufferIn; + for (i=bufferLength; i>0; i--, r64buf++, u16buf++ ) { + *r64buf = (double)(*u16buf); + } + break; + case CGAL_SSHORT : + s16buf = (s16*)bufferIn; + for (i=bufferLength; i>0; i--, r64buf++, s16buf++ ) { + *r64buf = (double)(*s16buf); + } + break; + case CGAL_INT : + s32buf = (s32*)bufferIn; + for (i=bufferLength; i>0; i--, r64buf++, s32buf++ ) { + *r64buf = (double)(*s32buf); + } + break; + case CGAL_FLOAT : + r32buf = (r32*)bufferIn; + for (i=bufferLength; i>0; i--, r32buf++, r64buf++ ) { + *r64buf = (double)(*r32buf); + } + break; + case CGAL_DOUBLE : + if ( bufferOut == bufferIn ) return; + (void)memcpy( bufferOut, bufferIn, bufferLength * sizeof(r64) ); + break; + default : + fprintf( stderr, " Error in %s: such conversion not yet implemented.\n", + proc ); + return; + } + break; /* end case typeOut = CGAL_DOUBLE */ + + + + + default : + fprintf( stderr, " Error in %s: such output type not yet handled.\n", + proc ); + return; + } +} + + + + + +CGAL_INLINE_FUNCTION +void Convert_r32_to_s8( r32 *theBuf, + s8 *resBuf, + int size ) +{ + register int i; + register r32* tb = theBuf; + register s8* rb = resBuf; + + for ( i=0; i +#ifndef CGAL_HEADER_ONLY -#include "gis.h" -#include "inr.h" +#include "fgetns.h" +#include "fgetns_impl.h" -/* get a string from a file and discard the ending newline character - if any */ -char *fgetns(char *str, int n, _image *im ) { - char *ret; - int l; - - memset( str, 0, n ); - ret = ImageIO_gets( im, str, n ); - - if(!ret) return NULL; - - l = strlen(str); - if(l > 0 && str[l-1] == '\n') str[l-1] = '\0'; - return ret; -} +#endif // CGAL_HEADER_ONLY diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/fgetns.h b/CGAL_ImageIO/src/CGAL_ImageIO/fgetns.h index 8cb1764d010..73f2f58bd13 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/fgetns.h +++ b/CGAL_ImageIO/src/CGAL_ImageIO/fgetns.h @@ -19,11 +19,17 @@ // // Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau -#include +#ifndef FGETNS_H +#define FGETNS_H -#include "gis.h" -#include "inr.h" +#include /* get a string from a file and discard the ending newline character if any */ char *fgetns(char *str, int n, _image *im ); + +#ifdef CGAL_HEADER_ONLY +#include "fgetns_impl.h" +#endif // CGAL_HEADER_ONLY + +#endif // FGETNS_H diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/fgetns_impl.h b/CGAL_ImageIO/src/CGAL_ImageIO/fgetns_impl.h new file mode 100644 index 00000000000..c1ded434a9d --- /dev/null +++ b/CGAL_ImageIO/src/CGAL_ImageIO/fgetns_impl.h @@ -0,0 +1,45 @@ +// Copyright (c) 2005-2008 ASCLEPIOS Project, INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of the ImageIO Library, and as been adapted for +// CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the +// GNU Lesser General Public License as published by the Free Software Foundation; +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include + +/* get a string from a file and discard the ending newline character + if any */ +CGAL_INLINE_FUNCTION +char *fgetns(char *str, int n, _image *im ) { + char *ret; + int l; + + memset( str, 0, n ); + ret = ImageIO_gets( im, str, n ); + + if(!ret) return NULL; + + l = strlen(str); + if(l > 0 && str[l-1] == '\n') str[l-1] = '\0'; + return ret; +} diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/gif.cpp b/CGAL_ImageIO/src/CGAL_ImageIO/gif.cpp index ffb865a3e76..c1735c610b4 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/gif.cpp +++ b/CGAL_ImageIO/src/CGAL_ImageIO/gif.cpp @@ -19,640 +19,9 @@ // // Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau -#include +#ifndef CGAL_HEADER_ONLY #include "gif.h" +#include "gif_impl.h" -#ifdef WIN32 -#include -#endif - - - -/** Magic header for GIF files */ -#define GIF_MAGIC "GIF8" - - - -typedef unsigned char byte; -#define TRUE 1 -#define FALSE 0 - -#define NEXTBYTE (*ptr++) -#define EXTENSION 0x21 -#define IMAGESEP 0x2c -#define TRAILER 0x3b -#define INTERLACEMASK 0x40 -#define COLORMAPMASK 0x80 - - -#define DEBUG 0 - -FILE *fp; -int gif89 = 0; -const char *id87 = "GIF87a"; -const char *id89 = "GIF89a"; - -static int EGApalette[16][3] = { - {0,0,0}, {0,0,128}, {0,128,0}, {0,128,128}, - {128,0,0}, {128,0,128}, {128,128,0}, {200,200,200}, - {100,100,100}, {100,100,255}, {100,255,100}, {100,255,255}, - {255,100,100}, {255,100,255}, {255,255,100}, {255,255,255} }; - - -static int ReadCode(); -static void DoInterlace(byte); -static int GifError(const char *); - - -byte *Raster; /* The raster data stream, unblocked */ -byte *RawGIF; -byte *r,*g,*b; /* The colormap */ -int BitOffset = 0, /* Bit Offset of next code */ - XC = 0, YC = 0, /* Output X and Y coords of current pixel */ - CodeSize, /* Code size, read from GIF header */ - ReadMask, /* Code AND mask for current code size */ - Pass = 0, /* Used by output routine if interlaced pic */ - Width, Height; /* image dimensions */ - -unsigned char *org, *buf; - -int testGifHeader(char *magic,const char *) { - if (!strcmp(magic, GIF_MAGIC)) - return 0; - else - return -1; -} -PTRIMAGE_FORMAT createGifFormat() { - PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); - - f->testImageFormat=&testGifHeader; - f->readImageHeader=&readGifImage; - f->writeImage=0; - strcpy(f->fileExtension,".gif"); - strcpy(f->realName,"Gif"); - return f; -} - -void use(int) {} // warning killer - -/*****************************/ -int readGifImage(const char *name,_image *im) { - register byte ch, ch1; - register byte *ptr, *ptr1; - register int i, block; - int npixels, maxpixels, aspect, filesize; - float normaspect; - int OutCount = 0, /* Decompressor output 'stack count' */ - RWidth, RHeight, /* screen dimensions */ - /*LeftOfs, TopOfs, image offset */ - BitsPerPixel, /* Bits per pixel, read from GIF header */ - ColorMapSize, /* number of colors */ - Background, /* background color */ - InitCodeSize, /* Starting code size, used during Clear */ - Code, /* Value returned by ReadCode */ - MaxCode, /* limiting value for current code size */ - ClearCode, /* GIF clear code */ - EOFCode, /* GIF end-of-information code */ - CurCode, OldCode=0, InCode, /* Decompressor variables */ - FirstFree, /* First free code, generated per GIF spec */ - FreeCode, /* Decompressor,next free slot in hash table */ - FinChar=0, /* Decompressor variable */ - BitMask, /* AND mask for data size */ - Misc; /* miscellaneous bits (interlace, local cmap)*/ - int Interlace, HasColormap; - /* not used - */ - /* char header[10]; */ - - /* The hash table used by the decompressor */ - int Prefix[4096]; - int Suffix[4096]; - /* An output array used by the decompressor */ - int OutCode[4097]; - - /* initialize variables */ - BitOffset = XC = YC = Pass = OutCount = npixels = maxpixels = 0; - RawGIF = Raster = NULL; - gif89 = 0; - -#ifdef WIN32 - fp = fopen(name,"rb"); -#else - fp = fopen(name,"r"); -#endif - fp = fopen(name,"rb"); - if (!fp) { - return(GifError("could not open a GIF file")); - } - /* find the size of the file */ - fseek(fp, 0L, 2); - filesize = ftell(fp); - fseek(fp, 0L, 0); - - /* the +256's are so we can read truncated GIF files without fear of - segmentation violation */ - if (!(ptr = RawGIF = (byte *) ImageIO_alloc(filesize+256))) - return( GifError("not enough memory to read gif file") ); - - if (!(Raster = (byte *) ImageIO_alloc(filesize+256))) - return( GifError("not enough memory to read gif file") ); - - if (fread(ptr, filesize, 1, fp) != 1) - return( GifError("GIF data read failed") ); - if (strncmp((char *) ptr, id87, 6)==0) gif89 = 0; - else if (strncmp((char *) ptr, id89, 6)==0) gif89 = 1; - else return( GifError("not a GIF file")); - - ptr += 6; - /* Get variables from the GIF screen descriptor */ - - ch = NEXTBYTE; - RWidth = ch + 0x100 * NEXTBYTE; /* screen dimensions... not used. */ - ch = NEXTBYTE; - RHeight = ch + 0x100 * NEXTBYTE; - use(RWidth); - use(RHeight); - - ch = NEXTBYTE; - HasColormap = ((ch & COLORMAPMASK) ? TRUE : FALSE); - - BitsPerPixel = (ch & 7) + 1; - ColorMapSize = 1 << BitsPerPixel; - BitMask = ColorMapSize - 1; - - Background = NEXTBYTE; /* background color... not used. */ - use(Background); - - - aspect = NEXTBYTE; - if (aspect) { - if (!gif89) return(GifError("corrupt GIF file (screen descriptor)")); - else normaspect = (float) (aspect + 15) / 64.0f; /* gif89 aspect ratio */ - if (DEBUG) fprintf(stderr,"GIF89 aspect = %f\n", normaspect); - } - - - /* Read in global colormap. */ - if (HasColormap) - { - r = (byte *) ImageIO_alloc(ColorMapSize * sizeof(byte)); - g = (byte *) ImageIO_alloc(ColorMapSize * sizeof(byte)); - b = (byte *) ImageIO_alloc(ColorMapSize * sizeof(byte)); - - for (i = 0; i < ColorMapSize; i++) { - r[i] = NEXTBYTE; - g[i] = NEXTBYTE; - b[i] = NEXTBYTE; - } - } - else { - /* no colormap in GIF file */ - /* put std EGA palette (repeated 16 times) into colormap, for lack of - anything better to do */ - ColorMapSize = 256; - r = (byte *) ImageIO_alloc(256 * sizeof(byte)); - g = (byte *) ImageIO_alloc(256 * sizeof(byte)); - b = (byte *) ImageIO_alloc(256 * sizeof(byte)); - - for (i = 0; i < 256; i++) { - r[i] = EGApalette[i&15][0]; - g[i] = EGApalette[i&15][1]; - b[i] = EGApalette[i&15][2]; - } - } - - /* possible things at this point are: - * an application extension block - * a comment extension block - * an (optional) graphic control extension block - * followed by either an image - * or a plaintext extension - */ - while (1) { - block = NEXTBYTE; - - if (block == EXTENSION) { /* parse extension blocks */ - int i, fn, blocksize, aspnum, aspden; - - /* read extension block */ - fn = NEXTBYTE; - - if (DEBUG) fprintf(stderr,"GIF extension type 0x%02x\n", fn); - - if (fn == 'R') { /* GIF87 aspect extension */ - blocksize = NEXTBYTE; - if (blocksize == 2) { - aspnum = NEXTBYTE; - aspden = NEXTBYTE; - if (aspden>0 && aspnum>0) - normaspect = (float) aspnum / (float) aspden; - else { normaspect = 1.0; aspnum = aspden = 1; } - - if (DEBUG) fprintf(stderr,"GIF87 aspect extension: %d:%d = %f\n\n", - aspnum, aspden,normaspect); - } - else { - for (i=0; i filesize) { - /* SetISTR(ISTR_WARNING, - "This GIF file seems to be truncated. Winging it.");*/ - break; - } - } while(ch1); - ImageIO_free(RawGIF); RawGIF = NULL; - - - if (DEBUG) { - fprintf(stderr,"xv: LoadGIF() - picture is %dx%d, %d bits, %sinterlaced\n", - Width, Height, BitsPerPixel, Interlace ? "" : "non-"); - } - - - /* Allocate the 'pic' */ - maxpixels = Width*Height; - im->xdim = Width; - im->ydim = Height; - im->zdim = 1; - im->vdim = 3; - im->wdim = 1; - im->wordKind = WK_FIXED; - im->sign = SGN_UNSIGNED; - im->data = ImageIO_alloc(Width * Height * 3); - org = buf = (unsigned char *) im->data; - - if (!org) - return( GifError("not enough memory for image buffer") ); - - - /* Decompress the file, continuing until you see the GIF EOF code. - * One obvious enhancement is to add checking for corrupt files here. - */ - Code = ReadCode(); - while (Code != EOFCode) { - /* Clear code sets everything back to its initial value, then reads the - * immediately subsequent code as uncompressed data. - */ - - if (Code == ClearCode) { - CodeSize = InitCodeSize; - MaxCode = (1 << CodeSize); - ReadMask = MaxCode - 1; - FreeCode = FirstFree; - Code = ReadCode(); - CurCode = OldCode = Code; - FinChar = CurCode & BitMask; - if (!Interlace) { - *buf++ = r[FinChar]; - *buf++ = g[FinChar]; - *buf++ = b[FinChar]; - } - else DoInterlace((byte)FinChar); - npixels++; - } - - else { - /* If not a clear code, must be data: save same as CurCode and InCode */ - - /* if we're at maxcode and didn't get a clear, stop loading */ - if (FreeCode>=4096) { - printf("freecode blew up\n"); - break; - } - - CurCode = InCode = Code; - - /* If greater or equal to FreeCode, not in the hash table yet; - * repeat the last character decoded - */ - - if (CurCode >= FreeCode) { - CurCode = OldCode; - if (OutCount > 4096) { - printf("outcount1 blew up\n"); break; } - OutCode[OutCount++] = FinChar; - } - - /* Unless this code is raw data, pursue the chain pointed to by CurCode - * through the hash table to its end; each code in the chain puts its - * associated output code on the output queue. - */ - - while (CurCode > BitMask) { - if (OutCount > 4096) { - fprintf(stderr,"outcount2 blew up\n"); break;} /* corrupt file */ - OutCode[OutCount++] = Suffix[CurCode]; - CurCode = Prefix[CurCode]; - } - - if (OutCount > 4096) { - printf("outcount blew up\n"); break; } - - /* The last code in the chain is treated as raw data. */ - - FinChar = CurCode & BitMask; - OutCode[OutCount++] = FinChar; - - /* Now we put the data out to the Output routine. - * It's been stacked LIFO, so deal with it that way... - */ - - /* safety thing: prevent exceeding range of 'pic' */ - if (npixels + OutCount > maxpixels) OutCount = maxpixels-npixels; - - npixels += OutCount; - if (!Interlace) for (i=OutCount-1; i>=0; i--) { - *buf++ = r[OutCode[i]]; - *buf++ = g[OutCode[i]]; - *buf++ = b[OutCode[i]]; - } - else for (i=OutCount-1; i>=0; i--) DoInterlace((byte)OutCode[i]); - OutCount = 0; - - /* Build the hash table on-the-fly. No table is stored in the file. */ - - Prefix[FreeCode] = OldCode; - Suffix[FreeCode] = FinChar; - OldCode = InCode; - - /* Point to the next slot in the table. If we exceed the current - * MaxCode value, increment the code size unless it's already 12. If it - * is, do nothing: the next code decompressed better be CLEAR - */ - - FreeCode++; - if (FreeCode >= MaxCode) { - if (CodeSize < 12) { - CodeSize++; - MaxCode *= 2; - ReadMask = (1 << CodeSize) - 1; - } - } - } - Code = ReadCode(); - if (npixels >= maxpixels) break; - } - ImageIO_free(Raster); Raster = NULL; - - if (npixels != maxpixels) { - /* SetISTR(ISTR_WARNING,"This GIF file seems to be truncated. Winging it.");*/ - if (!Interlace) - memset(buf, 0, 3*(maxpixels-npixels)); /* clear to EOBuffer */ - } - /* SetDirRButt(F_FORMAT, F_GIF); - SetDirRButt(F_COLORS, F_FULLCOLOR);*/ - return 1; -} - - -/* Fetch the next code from the raster data stream. The codes can be - * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to - * maintain our location in the Raster array as a BIT Offset. We compute - * the byte Offset into the raster array by dividing this by 8, pick up - * three bytes, compute the bit Offset into our 24-bit chunk, shift to - * bring the desired code to the bottom, then mask it off and return it. - */ - -static int ReadCode() -{ - int RawCode, ByteOffset; - - ByteOffset = BitOffset / 8; - RawCode = Raster[ByteOffset] + (Raster[ByteOffset + 1] << 8); - if (CodeSize >= 8) - RawCode += ( ((int) Raster[ByteOffset + 2]) << 16); - RawCode >>= (BitOffset % 8); - BitOffset += CodeSize; - - return(RawCode & ReadMask); -} - - -/***************************/ -static void DoInterlace(byte Index) { - static byte *ptr = NULL; - static int oldYC = -1; - - if (oldYC != YC) { - ptr = org + 3 * YC * Width; - oldYC = YC; - } - - if (YC < Height) { - *ptr++ = r[Index]; - *ptr++ = g[Index]; - *ptr++ = b[Index]; - } - - /* Update the X-coordinate, and if it overflows, update the Y-coordinate */ - if (++XC == Width) { - - /* deal with the interlace as described in the GIF - * spec. Put the decoded scan line out to the screen if we haven't gone - * past the bottom of it - */ - - XC = 0; - - switch (Pass) { - case 0: - YC += 8; - if (YC >= Height) { Pass++; YC = 4; } - break; - - case 1: - YC += 8; - if (YC >= Height) { Pass++; YC = 2; } - break; - - case 2: - YC += 4; - if (YC >= Height) { Pass++; YC = 1; } - break; - - case 3: - YC += 2; break; - - default: - break; - } - } -} - - - -/*****************************/ -static int GifError(const char *st) { - fprintf(stderr,"readGifImage: error: %s\n",st); - - if (RawGIF != NULL) ImageIO_free(RawGIF); - if (Raster != NULL) ImageIO_free(Raster); - - return -1; -} - +#endif // CGAL_HEADER_ONLY diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/gif.h b/CGAL_ImageIO/src/CGAL_ImageIO/gif.h index a3612201c34..467f9183f2a 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/gif.h +++ b/CGAL_ImageIO/src/CGAL_ImageIO/gif.h @@ -31,5 +31,8 @@ int testGifHeader(char *magic,const char *name); /** creates an return the file format structure associated with the Gif file format */ PTRIMAGE_FORMAT createGifFormat(); +#ifdef CGAL_HEADER_ONLY +#include "gif_impl.h" +#endif // CGAL_HEADER_ONLY #endif diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/gif_impl.h b/CGAL_ImageIO/src/CGAL_ImageIO/gif_impl.h new file mode 100644 index 00000000000..994bbfa5bdf --- /dev/null +++ b/CGAL_ImageIO/src/CGAL_ImageIO/gif_impl.h @@ -0,0 +1,700 @@ +// Copyright (c) 2005-2008 ASCLEPIOS Project, INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of the ImageIO Library, and as been adapted for +// CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the +// GNU Lesser General Public License as published by the Free Software Foundation; +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include + +#ifdef WIN32 +#include +#endif + +#ifdef CGAL_HEADER_ONLY + + #define CGAL_GLOBAL_STATE_VAR(TYPE, NAME, VALUE) \ + inline TYPE & get_static_##NAME() \ + { \ + static TYPE NAME = VALUE; \ + return NAME; \ + } + +#else // CGAL_HEADER_ONLY + + #define CGAL_GLOBAL_STATE_VAR(TYPE, NAME, VALUE) \ + TYPE NAME; \ + inline TYPE& get_static_##NAME() \ + { \ + return NAME; \ + } + +#endif // CGAL_HEADER_ONLY + + +/** Magic header for GIF files */ +#define GIF_MAGIC "GIF8" + + + +typedef unsigned char byte; +#define TRUE 1 +#define FALSE 0 + +#define NEXTBYTE (*ptr++) +#define EXTENSION 0x21 +#define IMAGESEP 0x2c +#define TRAILER 0x3b +#define INTERLACEMASK 0x40 +#define COLORMAPMASK 0x80 + + +#define DEBUG 0 + +//FILE *fp; +//int gif89 = 0; +static const char *id87 = "GIF87a"; +static const char *id89 = "GIF89a"; + +static int EGApalette[16][3] = { + {0,0,0}, {0,0,128}, {0,128,0}, {0,128,128}, + {128,0,0}, {128,0,128}, {128,128,0}, {200,200,200}, + {100,100,100}, {100,100,255}, {100,255,100}, {100,255,255}, + {255,100,100}, {255,100,255}, {255,255,100}, {255,255,255} }; + + +static int ReadCode(); +static void DoInterlace(byte); +static int GifError(const char *); + +CGAL_GLOBAL_STATE_VAR(byte *, Raster, NULL) /* The raster data stream, unblocked */ +CGAL_GLOBAL_STATE_VAR(byte *, RawGIF, NULL) +CGAL_GLOBAL_STATE_VAR(byte *, r, NULL) +CGAL_GLOBAL_STATE_VAR(byte *, g, NULL) +CGAL_GLOBAL_STATE_VAR(byte *, b, NULL) /* The colormap */ +CGAL_GLOBAL_STATE_VAR(int, BitOffset, 0) /* Bit Offset of next code */ +CGAL_GLOBAL_STATE_VAR(int, XC, 0) +CGAL_GLOBAL_STATE_VAR(int, YC, 0) /* Output X and Y coords of current pixel */ +CGAL_GLOBAL_STATE_VAR(int, CodeSize, 0) /* Code size, read from GIF header */ +CGAL_GLOBAL_STATE_VAR(int, ReadMask, 0) /* Code AND mask for current code size */ +CGAL_GLOBAL_STATE_VAR(int, Pass, 0) /* Used by output routine if interlaced pic */ +CGAL_GLOBAL_STATE_VAR(int, Width, 0) +CGAL_GLOBAL_STATE_VAR(int, Height, 0) /* image dimensions */ +CGAL_GLOBAL_STATE_VAR(unsigned char *, org, NULL) +CGAL_GLOBAL_STATE_VAR(unsigned char *, buf, NULL) + +CGAL_INLINE_FUNCTION +int testGifHeader(char *magic,const char *) { + if (!strcmp(magic, GIF_MAGIC)) + return 0; + else + return -1; +} +CGAL_INLINE_FUNCTION +PTRIMAGE_FORMAT createGifFormat() { + PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); + + f->testImageFormat=&testGifHeader; + f->readImageHeader=&readGifImage; + f->writeImage=0; + strcpy(f->fileExtension,".gif"); + strcpy(f->realName,"Gif"); + return f; +} + +CGAL_INLINE_FUNCTION +void use(int) {} // warning killer + +/*****************************/ +CGAL_INLINE_FUNCTION +int readGifImage(const char *name,_image *im) { +FILE *fp; +int gif89 = 0; + + register byte ch, ch1; + register byte *ptr, *ptr1; + register int i, block; + int npixels, maxpixels, aspect, filesize; + float normaspect; + int OutCount = 0, /* Decompressor output 'stack count' */ + RWidth, RHeight, /* screen dimensions */ + /*LeftOfs, TopOfs, image offset */ + BitsPerPixel, /* Bits per pixel, read from GIF header */ + ColorMapSize, /* number of colors */ + Background, /* background color */ + InitCodeSize, /* Starting code size, used during Clear */ + Code, /* Value returned by ReadCode */ + MaxCode, /* limiting value for current code size */ + ClearCode, /* GIF clear code */ + EOFCode, /* GIF end-of-information code */ + CurCode, OldCode=0, InCode, /* Decompressor variables */ + FirstFree, /* First free code, generated per GIF spec */ + FreeCode, /* Decompressor,next free slot in hash table */ + FinChar=0, /* Decompressor variable */ + BitMask, /* AND mask for data size */ + Misc; /* miscellaneous bits (interlace, local cmap)*/ + int Interlace, HasColormap; + /* not used + */ + /* char header[10]; */ + + /* The hash table used by the decompressor */ + int Prefix[4096]; + int Suffix[4096]; + /* An output array used by the decompressor */ + int OutCode[4097]; + + /* initialize variables */ + get_static_BitOffset() = + get_static_XC() = + get_static_YC() = + get_static_Pass() = + OutCount = + npixels = + maxpixels = 0; + get_static_RawGIF() = get_static_Raster() = NULL; + gif89 = 0; + +#ifdef WIN32 + fp = fopen(name,"rb"); +#else + fp = fopen(name,"r"); +#endif + fp = fopen(name,"rb"); + if (!fp) { + return(GifError("could not open a GIF file")); + } + /* find the size of the file */ + fseek(fp, 0L, 2); + filesize = ftell(fp); + fseek(fp, 0L, 0); + + /* the +256's are so we can read truncated GIF files without fear of + segmentation violation */ + if (!(ptr = get_static_RawGIF() = (byte *) ImageIO_alloc(filesize+256))) + return( GifError("not enough memory to read gif file") ); + + if (!(get_static_Raster() = (byte *) ImageIO_alloc(filesize+256))) + return( GifError("not enough memory to read gif file") ); + + if (fread(ptr, filesize, 1, fp) != 1) + return( GifError("GIF data read failed") ); + if (strncmp((char *) ptr, id87, 6)==0) gif89 = 0; + else if (strncmp((char *) ptr, id89, 6)==0) gif89 = 1; + else return( GifError("not a GIF file")); + + ptr += 6; + /* Get variables from the GIF screen descriptor */ + + ch = NEXTBYTE; + RWidth = ch + 0x100 * NEXTBYTE; /* screen dimensions... not used. */ + ch = NEXTBYTE; + RHeight = ch + 0x100 * NEXTBYTE; + use(RWidth); + use(RHeight); + + ch = NEXTBYTE; + HasColormap = ((ch & COLORMAPMASK) ? TRUE : FALSE); + + BitsPerPixel = (ch & 7) + 1; + ColorMapSize = 1 << BitsPerPixel; + BitMask = ColorMapSize - 1; + + Background = NEXTBYTE; /* background color... not used. */ + use(Background); + + + aspect = NEXTBYTE; + if (aspect) { + if (!gif89) return(GifError("corrupt GIF file (screen descriptor)")); + else normaspect = (float) (aspect + 15) / 64.0f; /* gif89 aspect ratio */ + if (DEBUG) fprintf(stderr,"GIF89 aspect = %f\n", normaspect); + } + + + /* Read in global colormap. */ + if (HasColormap) + { + get_static_r() = (byte *) ImageIO_alloc(ColorMapSize * sizeof(byte)); + get_static_g() = (byte *) ImageIO_alloc(ColorMapSize * sizeof(byte)); + get_static_b() = (byte *) ImageIO_alloc(ColorMapSize * sizeof(byte)); + + for (i = 0; i < ColorMapSize; i++) { + get_static_r()[i] = NEXTBYTE; + get_static_g()[i] = NEXTBYTE; + get_static_b()[i] = NEXTBYTE; + } + } + else { + /* no colormap in GIF file */ + /* put std EGA palette (repeated 16 times) into colormap, for lack of + anything better to do */ + ColorMapSize = 256; + get_static_r() = (byte *) ImageIO_alloc(256 * sizeof(byte)); + get_static_g() = (byte *) ImageIO_alloc(256 * sizeof(byte)); + get_static_b() = (byte *) ImageIO_alloc(256 * sizeof(byte)); + + for (i = 0; i < 256; i++) { + get_static_r()[i] = EGApalette[i&15][0]; + get_static_g()[i] = EGApalette[i&15][1]; + get_static_b()[i] = EGApalette[i&15][2]; + } + } + + /* possible things at this point are: + * an application extension block + * a comment extension block + * an (optional) graphic control extension block + * followed by either an image + * or a plaintext extension + */ + while (1) { + block = NEXTBYTE; + + if (block == EXTENSION) { /* parse extension blocks */ + int i, fn, blocksize, aspnum, aspden; + + /* read extension block */ + fn = NEXTBYTE; + + if (DEBUG) fprintf(stderr,"GIF extension type 0x%02x\n", fn); + + if (fn == 'R') { /* GIF87 aspect extension */ + blocksize = NEXTBYTE; + if (blocksize == 2) { + aspnum = NEXTBYTE; + aspden = NEXTBYTE; + if (aspden>0 && aspnum>0) + normaspect = (float) aspnum / (float) aspden; + else { normaspect = 1.0; aspnum = aspden = 1; } + + if (DEBUG) fprintf(stderr,"GIF87 aspect extension: %d:%d = %f\n\n", + aspnum, aspden,normaspect); + } + else { + for (i=0; i filesize) { + /* SetISTR(ISTR_WARNING, + "This GIF file seems to be truncated. Winging it.");*/ + break; + } + } while(ch1); + ImageIO_free(get_static_RawGIF()); get_static_RawGIF() = NULL; + + + if (DEBUG) { + fprintf(stderr,"xv: LoadGIF() - picture is %dx%d, %d bits, %sinterlaced\n", + get_static_Width(), get_static_Height(), BitsPerPixel, Interlace ? "" : "non-"); + } + + + /* Allocate the 'pic' */ + maxpixels = get_static_Width()*get_static_Height(); + im->xdim = get_static_Width(); + im->ydim = get_static_Height(); + im->zdim = 1; + im->vdim = 3; + im->wdim = 1; + im->wordKind = WK_FIXED; + im->sign = SGN_UNSIGNED; + im->data = ImageIO_alloc(get_static_Width() * get_static_Height() * 3); + get_static_org() = get_static_buf() = (unsigned char *) im->data; + + if (!get_static_org()) + return( GifError("not enough memory for image buffer") ); + + + /* Decompress the file, continuing until you see the GIF EOF code. + * One obvious enhancement is to add checking for corrupt files here. + */ + Code = ReadCode(); + while (Code != EOFCode) { + /* Clear code sets everything back to its initial value, then reads the + * immediately subsequent code as uncompressed data. + */ + + if (Code == ClearCode) { + get_static_CodeSize() = InitCodeSize; + MaxCode = (1 << get_static_CodeSize()); + get_static_ReadMask() = MaxCode - 1; + FreeCode = FirstFree; + Code = ReadCode(); + CurCode = OldCode = Code; + FinChar = CurCode & BitMask; + if (!Interlace) { + *get_static_buf()++ = get_static_r()[FinChar]; + *get_static_buf()++ = get_static_g()[FinChar]; + *get_static_buf()++ = get_static_b()[FinChar]; + } + else DoInterlace((byte)FinChar); + npixels++; + } + + else { + /* If not a clear code, must be data: save same as CurCode and InCode */ + + /* if we're at maxcode and didn't get a clear, stop loading */ + if (FreeCode>=4096) { + printf("freecode blew up\n"); + break; + } + + CurCode = InCode = Code; + + /* If greater or equal to FreeCode, not in the hash table yet; + * repeat the last character decoded + */ + + if (CurCode >= FreeCode) { + CurCode = OldCode; + if (OutCount > 4096) { + printf("outcount1 blew up\n"); break; } + OutCode[OutCount++] = FinChar; + } + + /* Unless this code is raw data, pursue the chain pointed to by CurCode + * through the hash table to its end; each code in the chain puts its + * associated output code on the output queue. + */ + + while (CurCode > BitMask) { + if (OutCount > 4096) { + fprintf(stderr,"outcount2 blew up\n"); break;} /* corrupt file */ + OutCode[OutCount++] = Suffix[CurCode]; + CurCode = Prefix[CurCode]; + } + + if (OutCount > 4096) { + printf("outcount blew up\n"); break; } + + /* The last code in the chain is treated as raw data. */ + + FinChar = CurCode & BitMask; + OutCode[OutCount++] = FinChar; + + /* Now we put the data out to the Output routine. + * It's been stacked LIFO, so deal with it that way... + */ + + /* safety thing: prevent exceeding range of 'pic' */ + if (npixels + OutCount > maxpixels) OutCount = maxpixels-npixels; + + npixels += OutCount; + if (!Interlace) for (i=OutCount-1; i>=0; i--) { + *get_static_buf()++ = get_static_r()[OutCode[i]]; + *get_static_buf()++ = get_static_g()[OutCode[i]]; + *get_static_buf()++ = get_static_b()[OutCode[i]]; + } + else for (i=OutCount-1; i>=0; i--) DoInterlace((byte)OutCode[i]); + OutCount = 0; + + /* Build the hash table on-the-fly. No table is stored in the file. */ + + Prefix[FreeCode] = OldCode; + Suffix[FreeCode] = FinChar; + OldCode = InCode; + + /* Point to the next slot in the table. If we exceed the current + * MaxCode value, increment the code size unless it's already 12. If it + * is, do nothing: the next code decompressed better be CLEAR + */ + + FreeCode++; + if (FreeCode >= MaxCode) { + if (get_static_CodeSize() < 12) { + get_static_CodeSize()++; + MaxCode *= 2; + get_static_ReadMask() = (1 << get_static_CodeSize()) - 1; + } + } + } + Code = ReadCode(); + if (npixels >= maxpixels) break; + } + ImageIO_free(get_static_Raster()); get_static_Raster() = NULL; + + if (npixels != maxpixels) { + /* SetISTR(ISTR_WARNING,"This GIF file seems to be truncated. Winging it.");*/ + if (!Interlace) + memset(get_static_buf(), 0, 3*(maxpixels-npixels)); /* clear to EOBuffer */ + } + /* SetDirRButt(F_FORMAT, F_GIF); + SetDirRButt(F_COLORS, F_FULLCOLOR);*/ + return 1; +} + + +/* Fetch the next code from the raster data stream. The codes can be + * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to + * maintain our location in the Raster array as a BIT Offset. We compute + * the byte Offset into the raster array by dividing this by 8, pick up + * three bytes, compute the bit Offset into our 24-bit chunk, shift to + * bring the desired code to the bottom, then mask it off and return it. + */ + +CGAL_INLINE_FUNCTION +static int ReadCode() +{ + int RawCode, ByteOffset; + + ByteOffset = get_static_BitOffset() / 8; + RawCode = get_static_Raster()[ByteOffset] + (get_static_Raster()[ByteOffset + 1] << 8); + if (get_static_CodeSize() >= 8) + RawCode += ( ((int) get_static_Raster()[ByteOffset + 2]) << 16); + RawCode >>= (get_static_BitOffset() % 8); + get_static_BitOffset() += get_static_CodeSize(); + + return(RawCode & get_static_ReadMask()); +} + + +/***************************/ +CGAL_INLINE_FUNCTION +static void DoInterlace(byte Index) { + static byte *ptr = NULL; + static int oldYC = -1; + + if (oldYC != get_static_YC()) { + ptr = get_static_org() + 3 * get_static_YC() * get_static_Width(); + oldYC = get_static_YC(); + } + + if (get_static_YC() < get_static_Height()) { + *ptr++ = get_static_r()[Index]; + *ptr++ = get_static_g()[Index]; + *ptr++ = get_static_b()[Index]; + } + + /* Update the X-coordinate, and if it overflows, update the Y-coordinate */ + if (++get_static_XC() == get_static_Width()) { + + /* deal with the interlace as described in the GIF + * spec. Put the decoded scan line out to the screen if we haven't gone + * past the bottom of it + */ + + get_static_XC() = 0; + + switch (get_static_Pass()) { + case 0: + get_static_YC() += 8; + if (get_static_YC() >= get_static_Height()) { get_static_Pass()++; get_static_YC() = 4; } + break; + + case 1: + get_static_YC() += 8; + if (get_static_YC() >= get_static_Height()) { get_static_Pass()++; get_static_YC() = 2; } + break; + + case 2: + get_static_YC() += 4; + if (get_static_YC() >= get_static_Height()) { get_static_Pass()++; get_static_YC() = 1; } + break; + + case 3: + get_static_YC() += 2; break; + + default: + break; + } + } +} + + + +/*****************************/ +CGAL_INLINE_FUNCTION +static int GifError(const char *st) { + fprintf(stderr,"readGifImage: error: %s\n",st); + + if (get_static_RawGIF() != NULL) ImageIO_free(get_static_RawGIF()); + if (get_static_Raster() != NULL) ImageIO_free(get_static_Raster()); + + return -1; +} + diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/gis.cpp b/CGAL_ImageIO/src/CGAL_ImageIO/gis.cpp index 80ede0fec02..bc3bd71310c 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/gis.cpp +++ b/CGAL_ImageIO/src/CGAL_ImageIO/gis.cpp @@ -19,700 +19,9 @@ // // Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau -#include -#include +#ifndef CGAL_HEADER_ONLY -#include "gis.h" -#include "inr.h" -#include "fgetns.h" +#include "gis.h" +#include "gis_impl.h" -#define _LGTH_STRING_ 1024 - -PTRIMAGE_FORMAT createGisFormat() { - PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); - - f->testImageFormat=&testGisHeader; - f->readImageHeader=&readGisHeader; - f->writeImage=&writeGis; - strcpy(f->fileExtension,".dim,.dim.gz,.ima,.ima.gz"); - strcpy(f->realName,"Gis"); - return f; -} -int writeGis( char *name, _image* im) { - char *outputName; - int length, extLength=0, res; - - - length=strlen(name); - outputName= (char *)ImageIO_alloc(length+8); - - if ( strncmp( name+length-4, ".dim", 4 ) == 0 ) { - extLength = 4; - } - else if ( strncmp( name+length-4, ".ima", 4 ) == 0 ) { - extLength = 4; - } - else if ( strncmp( name+length-7, ".ima.gz", 7 ) == 0 ) { - extLength = 7; - } - else if ( strncmp( name+length-7, ".dim.gz", 7 ) == 0 ) { - extLength = 7; - } - - strncpy( outputName, name, length-extLength ); - if ( strncmp( name+length-7, ".dim.gz", 7 ) == 0 ) - strcpy( outputName+length-extLength, ".dim.gz" ); - else - strcpy( outputName+length-extLength, ".dim" ); - - _openWriteImage(im, outputName); - if( !im->fd ) { - fprintf(stderr, "writeGis: error: unable to open file \'%s\'\n", outputName); - if ( outputName != NULL ) ImageIO_free( outputName ); - return ImageIO_OPENING; - } - - res = writeGisHeader(im); - if (res < 0 ) { - fprintf(stderr, "writeGis: error: unable to write header of \'%s\'\n", - outputName); - if ( outputName != NULL ) ImageIO_free( outputName ); - ImageIO_close( im ); - im->fd = NULL; - im->openMode = OM_CLOSE; - return( res ); - } - - ImageIO_close(im); - - strncpy( outputName, name, length-extLength ); - if ( strncmp( name+length-3, ".gz", 3 ) == 0 ) { - strcpy( outputName+length-extLength, ".ima.gz" ); - } - else { - strcpy( outputName+length-extLength, ".ima" ); - } - - _openWriteImage(im, outputName); - - if( !im->fd ) { - fprintf(stderr, "writeGis: error: unable to open file \'%s\'\n", outputName); - if ( outputName != NULL ) ImageIO_free( outputName ); - return ImageIO_OPENING; - } - - if ( im->dataMode == DM_ASCII ) { - int i, j, n, size; - char *str = (char*)ImageIO_alloc( _LGTH_STRING_+1 ); - size = im->xdim * im->ydim * im->zdim * im->vdim; - n = ( im->xdim < 16 ) ? im->xdim : 16; - i = 0; - - switch( im->wordKind ) { - default : - fprintf(stderr, "writeGis: such word kind not handled in ascii mode for file \'%s\'\n", outputName); - if ( outputName != NULL ) ImageIO_free( outputName ); - return( -3 ); - case WK_FIXED : - switch ( im->wdim ) { - default : - fprintf(stderr, "writeGis: such word dim not handled in ascii mode for file \'%s\'\n", outputName); - if ( outputName != NULL ) ImageIO_free( outputName ); - return( -3 ); - case 1 : - switch ( im->sign ) { - default : - fprintf(stderr, "writeGis: such sign not handled in ascii mode for file \'%s\'\n", outputName); - if ( outputName != NULL ) ImageIO_free( outputName ); - return( -3 ); - case SGN_UNSIGNED : - { - unsigned char *theBuf = ( unsigned char * )im->data; - do { - memset( str, 0, _LGTH_STRING_ ); - for ( j=0; jdata; - do { - memset( str, 0, _LGTH_STRING_ ); - for ( j=0; jsign ) */ - break; - case 2 : - switch ( im->sign ) { - default : - fprintf(stderr, "writeGis: such sign not handled in ascii mode for file \'%s\'\n", outputName); - if ( outputName != NULL ) ImageIO_free( outputName ); - return( -3 ); - case SGN_UNSIGNED : - { - unsigned short int *theBuf = ( unsigned short int * )im->data; - do { - memset( str, 0, _LGTH_STRING_ ); - for ( j=0; jdata; - do { - memset( str, 0, _LGTH_STRING_ ); - for ( j=0; jsign ) */ - break; - } /* end of switch ( im->wdim ) */ - } /* end of switch( im->wordKind ) */ - - ImageIO_free( str ); - } - else { - res = _writeInrimageData(im); - } - if ( outputName != NULL ) ImageIO_free( outputName ); - return res; - -} - -int testGisHeader(char *,const char *name) { - if (( !strncmp(name+strlen(name)-4, ".dim", 4)) || - ( !strncmp(name+strlen(name)-4, ".ima", 4)) || - ( !strncmp(name+strlen(name)-7, ".ima.gz", 7)) || - ( !strncmp(name+strlen(name)-7, ".dim.gz", 7)) ) - return 0; - else - return -1; -} - - - -int readGisHeader( const char* name,_image* im) -{ - char *s, *str = NULL; - int status; - int n=0, nusermax = 20; - - str = (char*)ImageIO_alloc( _LGTH_STRING_+1 ); - - if ( !fgetns(str, _LGTH_STRING_, im) ) - { ImageIO_free( str ); return -1; } - - std::istringstream iss; - iss.str(str); - iss >> im->xdim >> im->ydim >> im->zdim >> im->vdim; - - status = iss.str().length(); - switch ( status ) { - case 2 : im->zdim = 1; - case 3 : im->vdim = 1; - case 4 : break; - default : - fprintf( stderr, "readGisHeader: unable to read dimensions in '%s'\n", name ); - ImageIO_free( str ); - return -1; - } - if ( im->vdim > 1 ) { - im->vectMode = VM_INTERLACED; - } - else { - im->vectMode = VM_SCALAR; - } -#define ADD_USER_STRING { \ - if ( n == 0 ) { \ - im->user = (char**)ImageIO_alloc( nusermax * sizeof( char*) ); \ - for ( n=0; nuser[n] = NULL; \ - n = 0; \ - } \ - im->user[n] = (char*)ImageIO_alloc( 1+strlen( s ) ); \ - strcpy( im->user[n++], s ); \ - } - - - - while( fgetns( str, _LGTH_STRING_, im ) != 0 ) { - s = str; - do { - - while ( *s == ' ' || *s == '\t' ) s++; - - if ( !strncmp( s, "-dx ", 4 ) ) { - s += 4; - status = sscanf( s, "%lf", &(im->vx) ); - if ( status != 1 ) { - fprintf( stderr, "readGisHeader: error while reading -dx in '%s'\n", s-4 ); - *s = '\0'; - } - else { - while ( *s == '.' || (*s >= '0' && *s <= '9') ) s++; - } - } - else if ( !strncmp( s, "-dy ", 4 ) ) { - s += 4; - status = sscanf( s, "%lf", &(im->vy) ); - if ( status != 1 ) { - fprintf( stderr, "readGisHeader: error while reading -dy in '%s'\n", s-4 ); - *s = '\0'; - } - else { - while ( *s == '.' || (*s >= '0' && *s <= '9') ) s++; - } - } - else if ( !strncmp( s, "-dz ", 4 ) ) { - s += 4; - status = sscanf( s, "%lf", &(im->vz) ); - if ( status != 1 ) { - fprintf( stderr, "readGisHeader: error while reading -dz in '%s'\n", s-4 ); - *s = '\0'; - } - else { - while ( *s == '.' || (*s >= '0' && *s <= '9') ) s++; - } - } - else if ( !strncmp( s, "-dt ", 4 ) ) { - ADD_USER_STRING - s += 4; - while ( *s == '.' || (*s >= '0' && *s <= '9') ) s++; - } - - else if ( !strncmp( s, "-type ", 6 ) ) { - s += 6; - if ( !strncmp( s, "U8", 2 ) ) { - im->wdim = 1; - im->wordKind = WK_FIXED; - im->sign = SGN_UNSIGNED; - s += 2; - } - else if ( !strncmp( s, "S8", 2 ) ) { - im->wdim = 1; - im->wordKind = WK_FIXED; - im->sign = SGN_SIGNED; - s += 2; - } - else if ( !strncmp( s, "U16", 3 ) ) { - im->wdim = 2; - im->wordKind = WK_FIXED; - im->sign = SGN_UNSIGNED; - s += 3; - } - else if ( !strncmp( s, "S16", 3 ) ) { - im->wdim = 2; - im->wordKind = WK_FIXED; - im->sign = SGN_SIGNED; - s += 3; - } - else if ( !strncmp( s, "U32", 3 ) ) { - im->wdim = 4; - im->wordKind = WK_FIXED; - im->sign = SGN_UNSIGNED; - s += 3; - } - else if ( !strncmp( s, "S32", 3 ) ) { - im->wdim = 4; - im->wordKind = WK_FIXED; - im->sign = SGN_SIGNED; - s += 3; - } - else if ( !strncmp( s, "FLOAT", 5 ) ) { - im->wdim = sizeof( float ); - im->wordKind = WK_FLOAT; - im->sign = SGN_UNKNOWN; - s += 5; - } - else if ( !strncmp( s, "DOUBLE", 6 ) ) { - im->wdim = sizeof( double ); - im->wordKind = WK_FLOAT; - im->sign = SGN_UNKNOWN; - s += 6; - } - else { - fprintf( stderr, "readGisHeader: unknown type '%s'\n", s-6 ); - *s = '\0'; - } - } - - else if ( !strncmp( s, "-bo ", 4 ) ) { - s += 4; - if ( !strncmp( s, "ABCD", 4 ) ) { - im->endianness = END_BIG; - s += 4; - } - else if ( !strncmp( s, "SUN", 3 ) ) { - im->endianness = END_BIG; - s += 3; - } - else if ( !strncmp( s, "DCBA", 4 ) ) { - im->endianness = END_LITTLE; - s += 4; - } - else if ( !strncmp( s, "ALPHA", 5 ) ) { - im->endianness = END_LITTLE; - s += 5; - } - else { - fprintf( stderr, "readGisHeader: unknown byte order '%s'\n", s-4 ); - *s = '\0'; - } - } - - else if ( !strncmp( s, "-ar ", 4 ) ) { - s += 4; - if ( !strncmp( s, "SUN", 3 ) ) { - im->endianness = END_BIG; - s += 3; - } - else if ( !strncmp( s, "ALPHA", 5 ) ) { - im->endianness = END_LITTLE; - s += 5; - } - else { - fprintf( stderr, "readGisHeader: unknown architecture '%s'\n", s-4 ); - *s = '\0'; - } - } - - else if ( !strncmp( s, "-om ", 4 ) ) { - s += 4; - if ( !strncmp( s, "binar", 5 ) ) { - im->dataMode = DM_BINARY; - s += 5; - } - else if ( !strncmp( s, "ascii", 5 ) ) { - im->dataMode = DM_ASCII; - s += 5; - } - else { - fprintf( stderr, "readGisHeader: unknown data type '%s'\n", s-4 ); - ImageIO_free( str ); - return -1; - } - } - - - else { - fprintf( stderr, "readGisHeader: unknown indentifier '%s'\n", s ); - ADD_USER_STRING - *s = '\0'; - } - - } while( *s != '\0' && *s != '\n' ); - - } - ImageIO_free( str ); - - - if ( im->endianness == END_UNKNOWN ) { - im->endianness = _getEndianness(); - } - - - /* header is read. close header file and open data file. */ - if( name != NULL ) { - - int length = strlen(name) ; - char* data_filename = (char *) ImageIO_alloc(length+4) ; - - if( strcmp( name+length-4, ".dim" ) ) { - fprintf (stderr, - "readGisHeader: error: file header extension must be .dim\n"); - ImageIO_free( data_filename ); - return -1; - } - - ImageIO_close(im); - - - /* open data file - */ - - strcpy(data_filename,name); - strcpy(data_filename+length-3, "ima.gz"); - _openReadImage(im,data_filename); - - if(!im->fd) { - - strcpy(data_filename,name); - strcpy(data_filename+length-3, "ima"); - _openReadImage(im,data_filename); - if(!im->fd) { - fprintf(stderr, "readGisHeader: error: unable to open data file \'%s\'\n", data_filename); - ImageIO_free( data_filename ); - return -1; - - } - } - ImageIO_free( data_filename ); - - - - - - /* read data if ascii - only U8 and S8 - */ - if ( im->dataMode == DM_ASCII ) { - int size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim; - unsigned int n; - char *tmp; - int ret, iv=0; - - if ( im->wdim != 1 || im->wordKind != WK_FIXED ) { - fprintf(stderr, "readGisHeader: error: unable to read such ascii type\n" ); - return -1; - } - - n = 0 ; - if ( size <= 0 ) return -1; - if(!im->data) { - im->data = ( void*) ImageIO_alloc(size); - if(!im->data) return -1; - } - - n = 0; - str = (char*)ImageIO_alloc( _LGTH_STRING_+1 ); - while( fgetns( str, _LGTH_STRING_, im ) != 0 && - n < im->xdim * im->ydim * im->zdim * im->vdim ) { - tmp = str; - while ( *tmp != '\n' && *tmp != '\0' && *tmp != EOF && - n < im->xdim * im->ydim * im->zdim * im->vdim ) { - /* skip trailing whitespace - */ - while ( *tmp == ' ' || *tmp == '\t' ) - tmp++; - if ( *tmp == '\0' || *tmp == '\n' || *tmp == EOF ) - continue; - - /* read a number - */ - switch ( im->wordKind ) { - case WK_FIXED : - ret = sscanf( tmp, "%d", &iv ); - break; - default : - ImageIO_free( im->data ); im->data = NULL; - ImageIO_free( str ); - return -1; - } - - if ( ret != 1 ) { - fprintf( stderr, "readGisHeader: error in reading ascii data\n" ); - ImageIO_free( im->data ); im->data = NULL; - ImageIO_free( str ); - return -1; - } - - if ( im->wordKind == WK_FIXED - && im->sign == SGN_UNSIGNED - && im->wdim == 1 ) { - unsigned char *buf = (unsigned char *)im->data; - buf += n; - if ( iv < 0 ) *buf = (unsigned char)0; - else if ( iv > 255 ) *buf = (unsigned char)255; - else *buf = (unsigned char)iv; - n ++; - } - else if ( im->wordKind == WK_FIXED - && im->sign == SGN_SIGNED - && im->wdim == 1 ) { - char *buf = (char *)im->data; - buf += n; - if ( iv < -128 ) *buf = (char)-128; - else if ( iv > 127 ) *buf = (char)127; - else *buf = (char)iv; - n ++; - } - else if ( im->wordKind == WK_FIXED - && im->sign == SGN_UNSIGNED - && im->wdim == 2 ) { - unsigned short int *buf = (unsigned short int *)im->data; - buf += n; - if ( iv < 0 ) *buf = (unsigned short int)0; - else if ( iv > 65535 ) *buf = (unsigned short int)65535; - else *buf = (unsigned short int)iv; - n ++; - } - else if ( im->wordKind == WK_FIXED - && im->sign == SGN_SIGNED - && im->wdim == 2 ) { - short int *buf = (short int *)im->data; - buf += n; - if ( iv < -32768 ) *buf = (short int)-32768; - else if ( iv > 32767 ) *buf = (short int)32767; - else *buf = (short int)iv; - n ++; - } - else { - ImageIO_free( im->data ); im->data = NULL; - ImageIO_free( str ); - return -1; - } - - - - /* skip a number - */ - while ( (*tmp >= '0' && *tmp <= '9') || *tmp == '.' || *tmp == '-' ) - tmp++; - } - } - ImageIO_free( str ); - ImageIO_close(im); - } - - } - - - /* check header validity */ - if ( im->xdim > 0 && im->ydim > 0 && im->zdim > 0 && im->vdim > 0 && - im->vx > 0.0 && im->vy > 0.0 && im->vz > 0.0 && - ( im->wordKind == WK_FLOAT || - (im->wordKind == WK_FIXED && im->sign != SGN_UNKNOWN) ) && - im->endianness != END_UNKNOWN ) { - return 0; - } - - return -1; -} - - - -int writeGisHeader( const _image* inr ) -{ - const char *proc = "writeGisHeader"; - std::ostringstream oss; - - if ( inr->vectMode == VM_NON_INTERLACED ) { - fprintf( stderr, "%s: can not write non interlaced data\n", proc ); - return -1; - } - - /* dimensions - */ - oss << " " << inr->xdim << " " << inr->ydim; - if ( inr->vdim > 1 ) { - oss << " " << inr->zdim << " " << inr->vdim; - } - else if ( inr->zdim > 1 ) { - oss << " " << inr->zdim; - } - oss << "\n"; - - /* type - */ - oss << "-type "; - switch ( inr->wordKind ) { - case WK_FIXED : - switch( inr->sign ) { - case SGN_UNSIGNED : - oss << "U" << 8*inr->wdim; - break; - case SGN_SIGNED : - oss << "S" << 8*inr->wdim; - break; - default : - fprintf( stderr, "%s: unknown wordSign\n", proc ); - return -1; - } - break; - case WK_FLOAT : - if ( inr->wdim == sizeof( float ) ) { - oss << "FLOAT"; - } - else if ( inr->wdim == sizeof( double ) ) { - oss << "DOUBLE"; - } - else { - fprintf( stderr, "%s: unknown WK_FLOAT word dim\n", proc ); - return -1; - } - break; - default : - fprintf( stderr, "%s: unknown wordKind for image\n", proc ); - return -1; - } - oss << "\n"; - - oss << "-dx "<< inr->vx <<"\n"; - oss << "-dy "<< inr->vy <<"\n"; - if ( inr->zdim > 1 ) - oss << "-dz " << inr->vz << "\n"; - - if ( inr->wdim > 1 ) { - oss << "-bo "; - switch ( _getEndianness() ) { - default : - case END_LITTLE : - oss << "DCBA"; break; - case END_BIG : - oss << "ABCD"; break; - } - oss << "\n"; - } - switch ( inr->dataMode ) { - default : - case DM_BINARY : - oss << "-om binar\n"; - break; - case DM_ASCII : - oss << "-om ascii\n"; - } - if( ImageIO_write( inr, oss.str().data(), oss.str().length()) == 0) { - return -1; - } - return 1; -} - - -int writeGisData( const _image*) -{ - return -1; -} +#endif // CGAL_HEADER_ONLY diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/gis.h b/CGAL_ImageIO/src/CGAL_ImageIO/gis.h index 1bfabb6f744..c12cc7641b7 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/gis.h +++ b/CGAL_ImageIO/src/CGAL_ImageIO/gis.h @@ -134,5 +134,8 @@ int writeGisHeader( const _image* im ) ; */ int writeGisData( const _image* im ) ; +#ifdef CGAL_HEADER_ONLY +#include "gis_impl.h" +#endif // CGAL_HEADER_ONLY #endif diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/gis_impl.h b/CGAL_ImageIO/src/CGAL_ImageIO/gis_impl.h new file mode 100644 index 00000000000..fbd3b53a819 --- /dev/null +++ b/CGAL_ImageIO/src/CGAL_ImageIO/gis_impl.h @@ -0,0 +1,730 @@ +// Copyright (c) 2005-2008 ASCLEPIOS Project, INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of the ImageIO Library, and as been adapted for +// CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the +// GNU Lesser General Public License as published by the Free Software Foundation; +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include + +#include "inr.h" +#include "fgetns.h" + +#define _LGTH_STRING_ 1024 + +CGAL_INLINE_FUNCTION +PTRIMAGE_FORMAT createGisFormat() { + PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); + + f->testImageFormat=&testGisHeader; + f->readImageHeader=&readGisHeader; + f->writeImage=&writeGis; + strcpy(f->fileExtension,".dim,.dim.gz,.ima,.ima.gz"); + strcpy(f->realName,"Gis"); + return f; +} +CGAL_INLINE_FUNCTION +int writeGis( char *name, _image* im) { + char *outputName; + int length, extLength=0, res; + + + length=strlen(name); + outputName= (char *)ImageIO_alloc(length+8); + + if ( strncmp( name+length-4, ".dim", 4 ) == 0 ) { + extLength = 4; + } + else if ( strncmp( name+length-4, ".ima", 4 ) == 0 ) { + extLength = 4; + } + else if ( strncmp( name+length-7, ".ima.gz", 7 ) == 0 ) { + extLength = 7; + } + else if ( strncmp( name+length-7, ".dim.gz", 7 ) == 0 ) { + extLength = 7; + } + + strncpy( outputName, name, length-extLength ); + if ( strncmp( name+length-7, ".dim.gz", 7 ) == 0 ) + strcpy( outputName+length-extLength, ".dim.gz" ); + else + strcpy( outputName+length-extLength, ".dim" ); + + _openWriteImage(im, outputName); + if( !im->fd ) { + fprintf(stderr, "writeGis: error: unable to open file \'%s\'\n", outputName); + if ( outputName != NULL ) ImageIO_free( outputName ); + return ImageIO_OPENING; + } + + res = writeGisHeader(im); + if (res < 0 ) { + fprintf(stderr, "writeGis: error: unable to write header of \'%s\'\n", + outputName); + if ( outputName != NULL ) ImageIO_free( outputName ); + ImageIO_close( im ); + im->fd = NULL; + im->openMode = OM_CLOSE; + return( res ); + } + + ImageIO_close(im); + + strncpy( outputName, name, length-extLength ); + if ( strncmp( name+length-3, ".gz", 3 ) == 0 ) { + strcpy( outputName+length-extLength, ".ima.gz" ); + } + else { + strcpy( outputName+length-extLength, ".ima" ); + } + + _openWriteImage(im, outputName); + + if( !im->fd ) { + fprintf(stderr, "writeGis: error: unable to open file \'%s\'\n", outputName); + if ( outputName != NULL ) ImageIO_free( outputName ); + return ImageIO_OPENING; + } + + if ( im->dataMode == DM_ASCII ) { + int i, j, n, size; + char *str = (char*)ImageIO_alloc( _LGTH_STRING_+1 ); + size = im->xdim * im->ydim * im->zdim * im->vdim; + n = ( im->xdim < 16 ) ? im->xdim : 16; + i = 0; + + switch( im->wordKind ) { + default : + fprintf(stderr, "writeGis: such word kind not handled in ascii mode for file \'%s\'\n", outputName); + if ( outputName != NULL ) ImageIO_free( outputName ); + return( -3 ); + case WK_FIXED : + switch ( im->wdim ) { + default : + fprintf(stderr, "writeGis: such word dim not handled in ascii mode for file \'%s\'\n", outputName); + if ( outputName != NULL ) ImageIO_free( outputName ); + return( -3 ); + case 1 : + switch ( im->sign ) { + default : + fprintf(stderr, "writeGis: such sign not handled in ascii mode for file \'%s\'\n", outputName); + if ( outputName != NULL ) ImageIO_free( outputName ); + return( -3 ); + case SGN_UNSIGNED : + { + unsigned char *theBuf = ( unsigned char * )im->data; + do { + memset( str, 0, _LGTH_STRING_ ); + for ( j=0; jdata; + do { + memset( str, 0, _LGTH_STRING_ ); + for ( j=0; jsign ) */ + break; + case 2 : + switch ( im->sign ) { + default : + fprintf(stderr, "writeGis: such sign not handled in ascii mode for file \'%s\'\n", outputName); + if ( outputName != NULL ) ImageIO_free( outputName ); + return( -3 ); + case SGN_UNSIGNED : + { + unsigned short int *theBuf = ( unsigned short int * )im->data; + do { + memset( str, 0, _LGTH_STRING_ ); + for ( j=0; jdata; + do { + memset( str, 0, _LGTH_STRING_ ); + for ( j=0; jsign ) */ + break; + } /* end of switch ( im->wdim ) */ + } /* end of switch( im->wordKind ) */ + + ImageIO_free( str ); + } + else { + res = _writeInrimageData(im); + } + if ( outputName != NULL ) ImageIO_free( outputName ); + return res; + +} + +CGAL_INLINE_FUNCTION +int testGisHeader(char *,const char *name) { + if (( !strncmp(name+strlen(name)-4, ".dim", 4)) || + ( !strncmp(name+strlen(name)-4, ".ima", 4)) || + ( !strncmp(name+strlen(name)-7, ".ima.gz", 7)) || + ( !strncmp(name+strlen(name)-7, ".dim.gz", 7)) ) + return 0; + else + return -1; +} + + + +CGAL_INLINE_FUNCTION +int readGisHeader( const char* name,_image* im) +{ + char *s, *str = NULL; + int status; + int n=0, nusermax = 20; + + str = (char*)ImageIO_alloc( _LGTH_STRING_+1 ); + + if ( !fgetns(str, _LGTH_STRING_, im) ) + { ImageIO_free( str ); return -1; } + + std::istringstream iss; + iss.str(str); + iss >> im->xdim >> im->ydim >> im->zdim >> im->vdim; + + status = iss.str().length(); + switch ( status ) { + case 2 : im->zdim = 1; + case 3 : im->vdim = 1; + case 4 : break; + default : + fprintf( stderr, "readGisHeader: unable to read dimensions in '%s'\n", name ); + ImageIO_free( str ); + return -1; + } + if ( im->vdim > 1 ) { + im->vectMode = VM_INTERLACED; + } + else { + im->vectMode = VM_SCALAR; + } +#define ADD_USER_STRING { \ + if ( n == 0 ) { \ + im->user = (char**)ImageIO_alloc( nusermax * sizeof( char*) ); \ + for ( n=0; nuser[n] = NULL; \ + n = 0; \ + } \ + im->user[n] = (char*)ImageIO_alloc( 1+strlen( s ) ); \ + strcpy( im->user[n++], s ); \ + } + + + + while( fgetns( str, _LGTH_STRING_, im ) != 0 ) { + s = str; + do { + + while ( *s == ' ' || *s == '\t' ) s++; + + if ( !strncmp( s, "-dx ", 4 ) ) { + s += 4; + status = sscanf( s, "%lf", &(im->vx) ); + if ( status != 1 ) { + fprintf( stderr, "readGisHeader: error while reading -dx in '%s'\n", s-4 ); + *s = '\0'; + } + else { + while ( *s == '.' || (*s >= '0' && *s <= '9') ) s++; + } + } + else if ( !strncmp( s, "-dy ", 4 ) ) { + s += 4; + status = sscanf( s, "%lf", &(im->vy) ); + if ( status != 1 ) { + fprintf( stderr, "readGisHeader: error while reading -dy in '%s'\n", s-4 ); + *s = '\0'; + } + else { + while ( *s == '.' || (*s >= '0' && *s <= '9') ) s++; + } + } + else if ( !strncmp( s, "-dz ", 4 ) ) { + s += 4; + status = sscanf( s, "%lf", &(im->vz) ); + if ( status != 1 ) { + fprintf( stderr, "readGisHeader: error while reading -dz in '%s'\n", s-4 ); + *s = '\0'; + } + else { + while ( *s == '.' || (*s >= '0' && *s <= '9') ) s++; + } + } + else if ( !strncmp( s, "-dt ", 4 ) ) { + ADD_USER_STRING + s += 4; + while ( *s == '.' || (*s >= '0' && *s <= '9') ) s++; + } + + else if ( !strncmp( s, "-type ", 6 ) ) { + s += 6; + if ( !strncmp( s, "U8", 2 ) ) { + im->wdim = 1; + im->wordKind = WK_FIXED; + im->sign = SGN_UNSIGNED; + s += 2; + } + else if ( !strncmp( s, "S8", 2 ) ) { + im->wdim = 1; + im->wordKind = WK_FIXED; + im->sign = SGN_SIGNED; + s += 2; + } + else if ( !strncmp( s, "U16", 3 ) ) { + im->wdim = 2; + im->wordKind = WK_FIXED; + im->sign = SGN_UNSIGNED; + s += 3; + } + else if ( !strncmp( s, "S16", 3 ) ) { + im->wdim = 2; + im->wordKind = WK_FIXED; + im->sign = SGN_SIGNED; + s += 3; + } + else if ( !strncmp( s, "U32", 3 ) ) { + im->wdim = 4; + im->wordKind = WK_FIXED; + im->sign = SGN_UNSIGNED; + s += 3; + } + else if ( !strncmp( s, "S32", 3 ) ) { + im->wdim = 4; + im->wordKind = WK_FIXED; + im->sign = SGN_SIGNED; + s += 3; + } + else if ( !strncmp( s, "FLOAT", 5 ) ) { + im->wdim = sizeof( float ); + im->wordKind = WK_FLOAT; + im->sign = SGN_UNKNOWN; + s += 5; + } + else if ( !strncmp( s, "DOUBLE", 6 ) ) { + im->wdim = sizeof( double ); + im->wordKind = WK_FLOAT; + im->sign = SGN_UNKNOWN; + s += 6; + } + else { + fprintf( stderr, "readGisHeader: unknown type '%s'\n", s-6 ); + *s = '\0'; + } + } + + else if ( !strncmp( s, "-bo ", 4 ) ) { + s += 4; + if ( !strncmp( s, "ABCD", 4 ) ) { + im->endianness = END_BIG; + s += 4; + } + else if ( !strncmp( s, "SUN", 3 ) ) { + im->endianness = END_BIG; + s += 3; + } + else if ( !strncmp( s, "DCBA", 4 ) ) { + im->endianness = END_LITTLE; + s += 4; + } + else if ( !strncmp( s, "ALPHA", 5 ) ) { + im->endianness = END_LITTLE; + s += 5; + } + else { + fprintf( stderr, "readGisHeader: unknown byte order '%s'\n", s-4 ); + *s = '\0'; + } + } + + else if ( !strncmp( s, "-ar ", 4 ) ) { + s += 4; + if ( !strncmp( s, "SUN", 3 ) ) { + im->endianness = END_BIG; + s += 3; + } + else if ( !strncmp( s, "ALPHA", 5 ) ) { + im->endianness = END_LITTLE; + s += 5; + } + else { + fprintf( stderr, "readGisHeader: unknown architecture '%s'\n", s-4 ); + *s = '\0'; + } + } + + else if ( !strncmp( s, "-om ", 4 ) ) { + s += 4; + if ( !strncmp( s, "binar", 5 ) ) { + im->dataMode = DM_BINARY; + s += 5; + } + else if ( !strncmp( s, "ascii", 5 ) ) { + im->dataMode = DM_ASCII; + s += 5; + } + else { + fprintf( stderr, "readGisHeader: unknown data type '%s'\n", s-4 ); + ImageIO_free( str ); + return -1; + } + } + + + else { + fprintf( stderr, "readGisHeader: unknown indentifier '%s'\n", s ); + ADD_USER_STRING + *s = '\0'; + } + + } while( *s != '\0' && *s != '\n' ); + + } + ImageIO_free( str ); + + + if ( im->endianness == END_UNKNOWN ) { + im->endianness = _getEndianness(); + } + + + /* header is read. close header file and open data file. */ + if( name != NULL ) { + + int length = strlen(name) ; + char* data_filename = (char *) ImageIO_alloc(length+4) ; + + if( strcmp( name+length-4, ".dim" ) ) { + fprintf (stderr, + "readGisHeader: error: file header extension must be .dim\n"); + ImageIO_free( data_filename ); + return -1; + } + + ImageIO_close(im); + + + /* open data file + */ + + strcpy(data_filename,name); + strcpy(data_filename+length-3, "ima.gz"); + _openReadImage(im,data_filename); + + if(!im->fd) { + + strcpy(data_filename,name); + strcpy(data_filename+length-3, "ima"); + _openReadImage(im,data_filename); + if(!im->fd) { + fprintf(stderr, "readGisHeader: error: unable to open data file \'%s\'\n", data_filename); + ImageIO_free( data_filename ); + return -1; + + } + } + ImageIO_free( data_filename ); + + + + + + /* read data if ascii + only U8 and S8 + */ + if ( im->dataMode == DM_ASCII ) { + int size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim; + unsigned int n; + char *tmp; + int ret, iv=0; + + if ( im->wdim != 1 || im->wordKind != WK_FIXED ) { + fprintf(stderr, "readGisHeader: error: unable to read such ascii type\n" ); + return -1; + } + + n = 0 ; + if ( size <= 0 ) return -1; + if(!im->data) { + im->data = ( void*) ImageIO_alloc(size); + if(!im->data) return -1; + } + + n = 0; + str = (char*)ImageIO_alloc( _LGTH_STRING_+1 ); + while( fgetns( str, _LGTH_STRING_, im ) != 0 && + n < im->xdim * im->ydim * im->zdim * im->vdim ) { + tmp = str; + while ( *tmp != '\n' && *tmp != '\0' && *tmp != EOF && + n < im->xdim * im->ydim * im->zdim * im->vdim ) { + /* skip trailing whitespace + */ + while ( *tmp == ' ' || *tmp == '\t' ) + tmp++; + if ( *tmp == '\0' || *tmp == '\n' || *tmp == EOF ) + continue; + + /* read a number + */ + switch ( im->wordKind ) { + case WK_FIXED : + ret = sscanf( tmp, "%d", &iv ); + break; + default : + ImageIO_free( im->data ); im->data = NULL; + ImageIO_free( str ); + return -1; + } + + if ( ret != 1 ) { + fprintf( stderr, "readGisHeader: error in reading ascii data\n" ); + ImageIO_free( im->data ); im->data = NULL; + ImageIO_free( str ); + return -1; + } + + if ( im->wordKind == WK_FIXED + && im->sign == SGN_UNSIGNED + && im->wdim == 1 ) { + unsigned char *buf = (unsigned char *)im->data; + buf += n; + if ( iv < 0 ) *buf = (unsigned char)0; + else if ( iv > 255 ) *buf = (unsigned char)255; + else *buf = (unsigned char)iv; + n ++; + } + else if ( im->wordKind == WK_FIXED + && im->sign == SGN_SIGNED + && im->wdim == 1 ) { + char *buf = (char *)im->data; + buf += n; + if ( iv < -128 ) *buf = (char)-128; + else if ( iv > 127 ) *buf = (char)127; + else *buf = (char)iv; + n ++; + } + else if ( im->wordKind == WK_FIXED + && im->sign == SGN_UNSIGNED + && im->wdim == 2 ) { + unsigned short int *buf = (unsigned short int *)im->data; + buf += n; + if ( iv < 0 ) *buf = (unsigned short int)0; + else if ( iv > 65535 ) *buf = (unsigned short int)65535; + else *buf = (unsigned short int)iv; + n ++; + } + else if ( im->wordKind == WK_FIXED + && im->sign == SGN_SIGNED + && im->wdim == 2 ) { + short int *buf = (short int *)im->data; + buf += n; + if ( iv < -32768 ) *buf = (short int)-32768; + else if ( iv > 32767 ) *buf = (short int)32767; + else *buf = (short int)iv; + n ++; + } + else { + ImageIO_free( im->data ); im->data = NULL; + ImageIO_free( str ); + return -1; + } + + + + /* skip a number + */ + while ( (*tmp >= '0' && *tmp <= '9') || *tmp == '.' || *tmp == '-' ) + tmp++; + } + } + ImageIO_free( str ); + ImageIO_close(im); + } + + } + + + /* check header validity */ + if ( im->xdim > 0 && im->ydim > 0 && im->zdim > 0 && im->vdim > 0 && + im->vx > 0.0 && im->vy > 0.0 && im->vz > 0.0 && + ( im->wordKind == WK_FLOAT || + (im->wordKind == WK_FIXED && im->sign != SGN_UNKNOWN) ) && + im->endianness != END_UNKNOWN ) { + return 0; + } + + return -1; +} + + + +CGAL_INLINE_FUNCTION +int writeGisHeader( const _image* inr ) +{ + const char *proc = "writeGisHeader"; + std::ostringstream oss; + + if ( inr->vectMode == VM_NON_INTERLACED ) { + fprintf( stderr, "%s: can not write non interlaced data\n", proc ); + return -1; + } + + /* dimensions + */ + oss << " " << inr->xdim << " " << inr->ydim; + if ( inr->vdim > 1 ) { + oss << " " << inr->zdim << " " << inr->vdim; + } + else if ( inr->zdim > 1 ) { + oss << " " << inr->zdim; + } + oss << "\n"; + + /* type + */ + oss << "-type "; + switch ( inr->wordKind ) { + case WK_FIXED : + switch( inr->sign ) { + case SGN_UNSIGNED : + oss << "U" << 8*inr->wdim; + break; + case SGN_SIGNED : + oss << "S" << 8*inr->wdim; + break; + default : + fprintf( stderr, "%s: unknown wordSign\n", proc ); + return -1; + } + break; + case WK_FLOAT : + if ( inr->wdim == sizeof( float ) ) { + oss << "FLOAT"; + } + else if ( inr->wdim == sizeof( double ) ) { + oss << "DOUBLE"; + } + else { + fprintf( stderr, "%s: unknown WK_FLOAT word dim\n", proc ); + return -1; + } + break; + default : + fprintf( stderr, "%s: unknown wordKind for image\n", proc ); + return -1; + } + oss << "\n"; + + oss << "-dx "<< inr->vx <<"\n"; + oss << "-dy "<< inr->vy <<"\n"; + if ( inr->zdim > 1 ) + oss << "-dz " << inr->vz << "\n"; + + if ( inr->wdim > 1 ) { + oss << "-bo "; + switch ( _getEndianness() ) { + default : + case END_LITTLE : + oss << "DCBA"; break; + case END_BIG : + oss << "ABCD"; break; + } + oss << "\n"; + } + switch ( inr->dataMode ) { + default : + case DM_BINARY : + oss << "-om binar\n"; + break; + case DM_ASCII : + oss << "-om ascii\n"; + } + if( ImageIO_write( inr, oss.str().data(), oss.str().length()) == 0) { + return -1; + } + return 1; +} + + +CGAL_INLINE_FUNCTION +int writeGisData( const _image*) +{ + return -1; +} diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/inr.cpp b/CGAL_ImageIO/src/CGAL_ImageIO/inr.cpp index 94d5571e340..6560f7462f3 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/inr.cpp +++ b/CGAL_ImageIO/src/CGAL_ImageIO/inr.cpp @@ -19,488 +19,9 @@ // // Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau +#ifndef CGAL_HEADER_ONLY + #include "inr.h" -#include "fgetns.h" +#include "inr_impl.h" -#include -#include - -/* Magic header for inrimages v4 */ -#define INR4_MAGIC "#INRIMAGE-4#{" - - -/** Magic header for inrimages */ -#define INR_MAGIC "#INR" - -typedef struct stringListElementStruct { - char *string; - struct stringListElementStruct *next; -} stringListElement; -/* list element with a pointer on a string */ - -typedef struct { - stringListElement *begin, *end; -} stringListHead; -/* string list descriptor */ - -#include -class Set_numeric_locale { - const char * old_locale; -public: - Set_numeric_locale(const char* locale) - : old_locale(std::setlocale(LC_NUMERIC, locale)) - { - } - - ~Set_numeric_locale() { - std::setlocale(LC_NUMERIC, old_locale); - } -}; - -static void addStringElement(stringListHead *strhead, - const char *str); -/* add a string element at the tail of given list */ - -static void concatStringElement(const stringListHead *strhead, - const char *str); -/* concat given string at the last element of given list */ - - -/* Writes the given inrimage header in an already opened file.*/ -int _writeInrimageHeader(const _image *im, ENDIANNESS end) { - unsigned int pos, i; - char type[30], endianness[5], buf[257], scale[20]; - std::ostringstream oss; - - Set_numeric_locale num_locale("C"); - - if(im->openMode != OM_CLOSE) { - /* fix word kind */ - switch(im->wordKind) { - - case WK_FLOAT: - sprintf(type, "float"); - scale[0] = '\0'; - break; - - case WK_FIXED: - switch(im->sign) { - case SGN_SIGNED: - sprintf(type, "signed fixed"); - break; - case SGN_UNSIGNED: - sprintf(type, "unsigned fixed"); - break; - default: - return -1; - } - sprintf(scale, "SCALE=2**0\n"); - break; - - default: - return -1; - } - - switch(end) { - case END_LITTLE: - sprintf(endianness, "decm"); - break; - case END_BIG: - sprintf(endianness, "sun"); - break; - default: - /* fix architecture endianness */ - if( _getEndianness() == END_LITTLE) - sprintf(endianness, "decm"); - else - sprintf(endianness, "sun"); - break; - } - - /* write header information */ - oss << INR4_MAGIC << "\n"; - oss << "XDIM=" << im->xdim << "\n"; - oss << "YDIM=" << im->ydim << "\n"; - oss << "ZDIM=" << im->zdim << "\n"; - oss << "VDIM=" << im->vdim << "\n"; - oss << "TYPE=" << type << "\n"; - oss << "PIXSIZE=" << im->wdim*8 <<" bits\n"; - oss << scale << "CPU=" << endianness << "\n"; - oss << "VX=" << im->vx << "\n"; - oss << "VY=" << im->vy << "\n"; - oss << "VZ=" << im->vz << "\n"; - - if ( im->cx != 0 ) - oss << "XO="<< im->cx << "\n"; - if ( im->cy != 0 ) - oss << "YO="<< im->cy << "\n"; - if ( im->cz != 0 ) - oss << "ZO="<< im->cz << "\n"; - if ( im->tx != 0.0 ) - oss << "TX="<< im->tx << "\n"; - if ( im->ty != 0.0 ) - oss << "TY="<< im->ty << "\n"; - if ( im->tz != 0.0 ) - oss << "TZ="<< im->tz << "\n"; - if ( im->rx != 0.0 ) - oss << "RX="<< im->rx <<"\n"; - if ( im->ry != 0.0 ) - oss << "RY="<< im->ry << "\n"; - if ( im->rz != 0.0 ) - oss << "RZ=" << im->rz <<"\n"; - - pos = oss.str().length(); - - if(ImageIO_write(im, oss.str().data(), oss.str().length()) == 0) - return -1; - - - /* write user strings */ - if ( im->user != NULL ) { - for(i = 0; i < im->nuser; i++) { - if ( im->user[i] == NULL ) continue; - pos += strlen(im->user[i]) + 2; - if(ImageIO_write(im, "#", 1) == 0) return -1; - if(ImageIO_write(im, im->user[i], strlen(im->user[i])) == 0) return -1; - if(ImageIO_write(im, "\n", 1) == 0) return -1; - } - } - /* write end of header */ - pos = pos % 256; - if(pos > 252) { - for(i = pos; i < 256; i++) - if(ImageIO_write(im, "\n", 1) != 1) return -1; - pos = 0; - } - buf[0] = '\0'; - for(i = pos; i < 252; i++) strcat(buf, "\n"); - strcat(buf, "##}\n"); - - if(ImageIO_write(im, buf, strlen(buf)) == 0) return -1; - else return 1; - } - - else return -1; -} - - - -/* Writes the given image body in an already opened file.*/ -int _writeInrimageData(const _image *im) { - unsigned long size, nbv, nwrt, i; - unsigned int v; - unsigned char **vp; - - if(im->openMode != OM_CLOSE) { - - /* scalar or interlaced vectors */ - if(im->vectMode != VM_NON_INTERLACED) { - size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim; - nwrt = ImageIO_write(im, im->data, size); - if(nwrt != size) return -1; - else return 1; - } - - /* non interlaced vectors: interlace for saving */ - else { - nbv = im->xdim * im->ydim * im->zdim; - size = im->xdim * im->ydim * im->zdim * im->wdim; - vp = (unsigned char **) ImageIO_alloc(im->vdim * sizeof(unsigned char *)); - for(v = 0; v < im->vdim; v++) - vp[v] = (unsigned char *) im->data + v * size; - for(i = 0; i < nbv; i++) - for(v = 0; v < im->vdim; v++) { - if(ImageIO_write(im, (const void *) vp[v], im->wdim) != im->wdim) - return -1; - vp[v] += im->wdim; - } - ImageIO_free(vp); - return 1; - } - } - else return -1; -} - - - - -/* read header of an opened inrimage */ -int readInrimageHeader(const char *,_image *im) { - char str[257]; - int n, nusr; - stringListHead strl = { NULL, NULL }; - stringListElement *oel, *el; - - Set_numeric_locale num_locale("C"); - - if(im->openMode != OM_CLOSE) { - /* read image magic number */ - if(!fgetns(str, 257, im )) return -1; - if(strcmp(str, INR4_MAGIC)) return -1; - - - /* while read line does not begin with '#' or '\n', read line - and decode field */ - if(!fgetns(str, 257, im)) return -1; - - while(str[0] != '#' && str[0] != '\0') { - - if(!strncmp(str, "XDIM=", 5)) { - std::istringstream iss(str+5); - if(!(iss >> im->xdim)) return -1; - } - else if(!strncmp(str, "YDIM=", 5)) { - std::istringstream iss(str+5); - if(!(iss >> im->ydim)) return -1; - } - else if(!strncmp(str, "ZDIM=", 5)) { - std::istringstream iss(str+5); - if(!(iss >> im->zdim)) return -1; - } - else if(!strncmp(str, "VDIM=", 5)) { - std::istringstream iss(str+5); - if(!(iss >> im->vdim)) return -1; - if(im->vdim == 1) im->vectMode = VM_SCALAR; - else im->vectMode = VM_INTERLACED; - } - else if(!strncmp(str, "VX=", 3)) { - std::istringstream iss(str+3); - if(!(iss >> im->vx)) return -1; - } - else if(!strncmp(str, "VY=", 3)) { - std::istringstream iss(str+3); - if(!(iss >> im->vy)) return -1; - } - else if(!strncmp(str, "VZ=", 3)) { - std::istringstream iss(str+3); - if(!(iss >> im->vz)) return -1; - } - else if(!strncmp(str, "TYPE=", 5)) { - if(!strncmp(str+5, "float", 5)) im->wordKind = WK_FLOAT; - else { - if(!strncmp(str+5, "signed fixed", 12)) { - im->wordKind = WK_FIXED; - im->sign = SGN_SIGNED; - } - else if(!strncmp(str+5, "unsigned fixed", 14)) { - im->wordKind = WK_FIXED; - im->sign = SGN_UNSIGNED; - } - else return -1; - } - } - /* before "sscanf(str+8, "%i %n", &im->wdim, &n) != 1" - was used. - However the man said - ... - n Nothing is expected; instead, the number of charac­ - ters consumed thus far from the input is stored - through the next pointer, which must be a pointer - to int. This is not a conversion, although it can - be suppressed with the * flag. The C standard - says: `Execution of a %n directive does not incre­ - ment the assignment count returned at the comple­ - tion of execution' but the Corrigendum seems to - contradict this. Probably it is wise not to make - any assumptions on the effect of %n conversions on - the return value. - ... - Thus I change it. It was yielding a RETURN_FAILURE with - insight (GM). - */ - else if(!strncmp(str, "PIXSIZE=", 8)) { - std::istringstream iss(str+8); - if(!(iss >> im->wdim)) return -1; - if(im->wdim != 8 && im->wdim != 16 && im->wdim != 32 && - im->wdim != 64) return -1; - - if ( im->wdim <= 9 ) { - if(strncmp(str+8+1, " bits", 5)) return -1; - } - else if ( im->wdim <= 99 ) { - if(strncmp(str+8+2, " bits", 5)) return -1; - } - else { - return -1; - } - - im->wdim >>= 3; - } - else if(!strncmp(str, "SCALE=", 6)) ; - else if(!strncmp(str, "CPU=", 4)) { - if(!strncmp(str+4, "decm", 4)) im->endianness = END_LITTLE; - else if(!strncmp(str+4, "alpha", 5)) im->endianness = END_LITTLE; - else if(!strncmp(str+4, "pc", 2)) im->endianness = END_LITTLE; - else if(!strncmp(str+4, "sun", 3)) im->endianness = END_BIG; - else if(!strncmp(str+4, "sgi", 3)) im->endianness = END_BIG; - else return -1; - } - - else if(!strncmp(str, "XO=", 3)) { - std::istringstream iss(str+3); - if(!(iss >> im->cx)) return -1; - } - else if(!strncmp(str, "YO=", 3)) { - std::istringstream iss(str+3); - if(!(iss >> im->cy)) return -1; - } - else if(!strncmp(str, "ZO=", 3)) { - std::istringstream iss(str+3); - if(!(iss >> im->cz)) return -1; - } - - else if(!strncmp(str, "TX=", 3)) { - std::istringstream iss(str+3); - if(!(iss >> im->tx)) return -1; - } - else if(!strncmp(str, "TY=", 3)) { - std::istringstream iss(str+3); - if(!(iss >> im->ty)) return -1; - } - else if(!strncmp(str, "TZ=", 3)) { - std::istringstream iss(str+3); - if(!(iss >> im->tz)) return -1; - } - else if(!strncmp(str, "RX=", 3)) { - std::istringstream iss(str+3); - if(!(iss >> im->rx)) return -1; - } - else if(!strncmp(str, "RY=", 3)) { - std::istringstream iss(str+3); - if(!(iss >> im->ry)) return -1; - } - else if(!strncmp(str, "RZ=", 3)) { - std::istringstream iss(str+3); - if(!(iss >> im->rz)) return -1; - } - - if(!fgetns(str, 257, im)) return -1; - } - - /* parse user strings */ - im->nuser = nusr = 0; - while(str[0] == '#' && strncmp(str, "##}", 3)) { - addStringElement(&strl, str + 1); - while(strlen(str) == 256) { - if(!fgetns(str, 257, im)) return -1; - concatStringElement(&strl, str); - } - nusr++; - if(!fgetns(str, 257, im)) return -1; - } - - /* go to end of header */ - while(strncmp(str, "##}", 3)) { - if(!fgetns(str, 257, im)) return -1; - } - - - /* check header validity */ - if(im->xdim > 0 && im->ydim > 0 && im->zdim > 0 && im->vdim > 0 && - im->vx > 0.0 && im->vy > 0.0 && im->vz > 0.0 && - (im->wordKind == WK_FLOAT || (im->wordKind == WK_FIXED && - im->sign != SGN_UNKNOWN)) && - im->endianness != END_UNKNOWN) { - if(nusr > 0) { - im->nuser = nusr; - im->user = (char **) ImageIO_alloc(im->nuser * sizeof(char *)); - oel = NULL; - for(el = strl.begin, n = 0; el != NULL; el = oel, n++) { - im->user[n] = el->string; - oel = el->next; - ImageIO_free(el); - } - } - return 0; - } - else return -1; - - } - else return -1; -} - - - -/* add a string element at the tail of given list */ -static void addStringElement(stringListHead *strhead, const char *str) { - stringListElement *el; - - el = (stringListElement *) ImageIO_alloc(sizeof(stringListElement)); - /* was strdup(str); */ - el->string = (char*)ImageIO_alloc( strlen(str)+1); - memcpy(el->string, str, strlen(str)+1); - el->next = NULL; - if(strhead->begin == NULL) - strhead->begin = strhead->end = el; - else { - strhead->end->next = el; - strhead->end = el; - } -} - - -/* concat given string at the last element of given list */ -static void concatStringElement(const stringListHead *strhead, - const char *str) { - stringListElement *el; - - el = strhead->end; - el->string = (char *) realloc(el->string, - strlen(el->string) + strlen(str) + 1); - strcat(el->string, str); -} - -int testInrimageHeader(char *magic,const char *) { - if (!strcmp(magic, INR_MAGIC)) - return 0; - else - return -1; -} - -int writeInrimage(char *name,_image *im) { - int res; - - _openWriteImage( im, name ); - - if(!im->fd) { - fprintf(stderr, "writeInrimage: error: unable to open file \'%s\'\n", name ); - return ImageIO_OPENING; - } - - res = _writeInrimageHeader(im, END_UNKNOWN); - if (res < 0) { - fprintf(stderr, "writeInrimage: error: unable to write header of \'%s\'\n", - name); - ImageIO_close( im ); - im->fd = NULL; - im->openMode = OM_CLOSE; - return( res ); - } - - res = _writeInrimageData( im ); - if (res < 0) { - fprintf(stderr, "writeInrimage: error: unable to write data of \'%s\'\n", - name); - ImageIO_close( im ); - im->fd = NULL; - im->openMode = OM_CLOSE; - return( res ); - } - - ImageIO_close( im ); - im->fd = NULL; - im->openMode = OM_CLOSE; - - return ( res ); -} - -PTRIMAGE_FORMAT createInrimageFormat() { - PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); - - f->testImageFormat=&testInrimageHeader; - f->readImageHeader=&readInrimageHeader; - f->writeImage=&writeInrimage; - strcpy(f->fileExtension,".inr,.inr.gz,.gradient,.gradient.gz,.gradient_direction,.gradient_direction.gz"); - strcpy(f->realName,"Inrimage"); - return f; -} +#endif // CGAL_HEADER_ONLY diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/inr.h b/CGAL_ImageIO/src/CGAL_ImageIO/inr.h index 1a5e6383dc5..5ec646040ba 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/inr.h +++ b/CGAL_ImageIO/src/CGAL_ImageIO/inr.h @@ -57,5 +57,9 @@ int writeInrimage(char *basename,_image *im); /** creates an return the file format structure associated with the Inrimage file format */ PTRIMAGE_FORMAT createInrimageFormat(); +#ifdef CGAL_HEADER_ONLY +#include "inr_impl.h" +#endif // CGAL_HEADER_ONLY + #endif diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/inr_impl.h b/CGAL_ImageIO/src/CGAL_ImageIO/inr_impl.h new file mode 100644 index 00000000000..a2c9fe065ba --- /dev/null +++ b/CGAL_ImageIO/src/CGAL_ImageIO/inr_impl.h @@ -0,0 +1,516 @@ +// Copyright (c) 2005-2008 ASCLEPIOS Project, INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of the ImageIO Library, and as been adapted for +// CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the +// GNU Lesser General Public License as published by the Free Software Foundation; +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include "fgetns.h" + +#include +#include + +/* Magic header for inrimages v4 */ +#define INR4_MAGIC "#INRIMAGE-4#{" + + +/** Magic header for inrimages */ +#define INR_MAGIC "#INR" + +typedef struct stringListElementStruct { + char *string; + struct stringListElementStruct *next; +} stringListElement; +/* list element with a pointer on a string */ + +typedef struct { + stringListElement *begin, *end; +} stringListHead; +/* string list descriptor */ + +#include +class Set_numeric_locale { + const char * old_locale; +public: + Set_numeric_locale(const char* locale) + : old_locale(std::setlocale(LC_NUMERIC, locale)) + { + } + + ~Set_numeric_locale() { + std::setlocale(LC_NUMERIC, old_locale); + } +}; + +static void addStringElement(stringListHead *strhead, + const char *str); +/* add a string element at the tail of given list */ + +static void concatStringElement(const stringListHead *strhead, + const char *str); +/* concat given string at the last element of given list */ + + +/* Writes the given inrimage header in an already opened file.*/ +CGAL_INLINE_FUNCTION +int _writeInrimageHeader(const _image *im, ENDIANNESS end) { + unsigned int pos, i; + char type[30], endianness[5], buf[257], scale[20]; + std::ostringstream oss; + + Set_numeric_locale num_locale("C"); + + if(im->openMode != OM_CLOSE) { + /* fix word kind */ + switch(im->wordKind) { + + case WK_FLOAT: + sprintf(type, "float"); + scale[0] = '\0'; + break; + + case WK_FIXED: + switch(im->sign) { + case SGN_SIGNED: + sprintf(type, "signed fixed"); + break; + case SGN_UNSIGNED: + sprintf(type, "unsigned fixed"); + break; + default: + return -1; + } + sprintf(scale, "SCALE=2**0\n"); + break; + + default: + return -1; + } + + switch(end) { + case END_LITTLE: + sprintf(endianness, "decm"); + break; + case END_BIG: + sprintf(endianness, "sun"); + break; + default: + /* fix architecture endianness */ + if( _getEndianness() == END_LITTLE) + sprintf(endianness, "decm"); + else + sprintf(endianness, "sun"); + break; + } + + /* write header information */ + oss << INR4_MAGIC << "\n"; + oss << "XDIM=" << im->xdim << "\n"; + oss << "YDIM=" << im->ydim << "\n"; + oss << "ZDIM=" << im->zdim << "\n"; + oss << "VDIM=" << im->vdim << "\n"; + oss << "TYPE=" << type << "\n"; + oss << "PIXSIZE=" << im->wdim*8 <<" bits\n"; + oss << scale << "CPU=" << endianness << "\n"; + oss << "VX=" << im->vx << "\n"; + oss << "VY=" << im->vy << "\n"; + oss << "VZ=" << im->vz << "\n"; + + if ( im->cx != 0 ) + oss << "XO="<< im->cx << "\n"; + if ( im->cy != 0 ) + oss << "YO="<< im->cy << "\n"; + if ( im->cz != 0 ) + oss << "ZO="<< im->cz << "\n"; + if ( im->tx != 0.0 ) + oss << "TX="<< im->tx << "\n"; + if ( im->ty != 0.0 ) + oss << "TY="<< im->ty << "\n"; + if ( im->tz != 0.0 ) + oss << "TZ="<< im->tz << "\n"; + if ( im->rx != 0.0 ) + oss << "RX="<< im->rx <<"\n"; + if ( im->ry != 0.0 ) + oss << "RY="<< im->ry << "\n"; + if ( im->rz != 0.0 ) + oss << "RZ=" << im->rz <<"\n"; + + pos = oss.str().length(); + + if(ImageIO_write(im, oss.str().data(), oss.str().length()) == 0) + return -1; + + + /* write user strings */ + if ( im->user != NULL ) { + for(i = 0; i < im->nuser; i++) { + if ( im->user[i] == NULL ) continue; + pos += strlen(im->user[i]) + 2; + if(ImageIO_write(im, "#", 1) == 0) return -1; + if(ImageIO_write(im, im->user[i], strlen(im->user[i])) == 0) return -1; + if(ImageIO_write(im, "\n", 1) == 0) return -1; + } + } + /* write end of header */ + pos = pos % 256; + if(pos > 252) { + for(i = pos; i < 256; i++) + if(ImageIO_write(im, "\n", 1) != 1) return -1; + pos = 0; + } + buf[0] = '\0'; + for(i = pos; i < 252; i++) strcat(buf, "\n"); + strcat(buf, "##}\n"); + + if(ImageIO_write(im, buf, strlen(buf)) == 0) return -1; + else return 1; + } + + else return -1; +} + + + +/* Writes the given image body in an already opened file.*/ +CGAL_INLINE_FUNCTION +int _writeInrimageData(const _image *im) { + unsigned long size, nbv, nwrt, i; + unsigned int v; + unsigned char **vp; + + if(im->openMode != OM_CLOSE) { + + /* scalar or interlaced vectors */ + if(im->vectMode != VM_NON_INTERLACED) { + size = im->xdim * im->ydim * im->zdim * im->vdim * im->wdim; + nwrt = ImageIO_write(im, im->data, size); + if(nwrt != size) return -1; + else return 1; + } + + /* non interlaced vectors: interlace for saving */ + else { + nbv = im->xdim * im->ydim * im->zdim; + size = im->xdim * im->ydim * im->zdim * im->wdim; + vp = (unsigned char **) ImageIO_alloc(im->vdim * sizeof(unsigned char *)); + for(v = 0; v < im->vdim; v++) + vp[v] = (unsigned char *) im->data + v * size; + for(i = 0; i < nbv; i++) + for(v = 0; v < im->vdim; v++) { + if(ImageIO_write(im, (const void *) vp[v], im->wdim) != im->wdim) + return -1; + vp[v] += im->wdim; + } + ImageIO_free(vp); + return 1; + } + } + else return -1; +} + + + + +/* read header of an opened inrimage */ +CGAL_INLINE_FUNCTION +int readInrimageHeader(const char *,_image *im) { + char str[257]; + int n, nusr; + stringListHead strl = { NULL, NULL }; + stringListElement *oel, *el; + + Set_numeric_locale num_locale("C"); + + if(im->openMode != OM_CLOSE) { + /* read image magic number */ + if(!fgetns(str, 257, im )) return -1; + if(strcmp(str, INR4_MAGIC)) return -1; + + + /* while read line does not begin with '#' or '\n', read line + and decode field */ + if(!fgetns(str, 257, im)) return -1; + + while(str[0] != '#' && str[0] != '\0') { + + if(!strncmp(str, "XDIM=", 5)) { + std::istringstream iss(str+5); + if(!(iss >> im->xdim)) return -1; + } + else if(!strncmp(str, "YDIM=", 5)) { + std::istringstream iss(str+5); + if(!(iss >> im->ydim)) return -1; + } + else if(!strncmp(str, "ZDIM=", 5)) { + std::istringstream iss(str+5); + if(!(iss >> im->zdim)) return -1; + } + else if(!strncmp(str, "VDIM=", 5)) { + std::istringstream iss(str+5); + if(!(iss >> im->vdim)) return -1; + if(im->vdim == 1) im->vectMode = VM_SCALAR; + else im->vectMode = VM_INTERLACED; + } + else if(!strncmp(str, "VX=", 3)) { + std::istringstream iss(str+3); + if(!(iss >> im->vx)) return -1; + } + else if(!strncmp(str, "VY=", 3)) { + std::istringstream iss(str+3); + if(!(iss >> im->vy)) return -1; + } + else if(!strncmp(str, "VZ=", 3)) { + std::istringstream iss(str+3); + if(!(iss >> im->vz)) return -1; + } + else if(!strncmp(str, "TYPE=", 5)) { + if(!strncmp(str+5, "float", 5)) im->wordKind = WK_FLOAT; + else { + if(!strncmp(str+5, "signed fixed", 12)) { + im->wordKind = WK_FIXED; + im->sign = SGN_SIGNED; + } + else if(!strncmp(str+5, "unsigned fixed", 14)) { + im->wordKind = WK_FIXED; + im->sign = SGN_UNSIGNED; + } + else return -1; + } + } + /* before "sscanf(str+8, "%i %n", &im->wdim, &n) != 1" + was used. + However the man said + ... + n Nothing is expected; instead, the number of charac­ + ters consumed thus far from the input is stored + through the next pointer, which must be a pointer + to int. This is not a conversion, although it can + be suppressed with the * flag. The C standard + says: `Execution of a %n directive does not incre­ + ment the assignment count returned at the comple­ + tion of execution' but the Corrigendum seems to + contradict this. Probably it is wise not to make + any assumptions on the effect of %n conversions on + the return value. + ... + Thus I change it. It was yielding a RETURN_FAILURE with + insight (GM). + */ + else if(!strncmp(str, "PIXSIZE=", 8)) { + std::istringstream iss(str+8); + if(!(iss >> im->wdim)) return -1; + if(im->wdim != 8 && im->wdim != 16 && im->wdim != 32 && + im->wdim != 64) return -1; + + if ( im->wdim <= 9 ) { + if(strncmp(str+8+1, " bits", 5)) return -1; + } + else if ( im->wdim <= 99 ) { + if(strncmp(str+8+2, " bits", 5)) return -1; + } + else { + return -1; + } + + im->wdim >>= 3; + } + else if(!strncmp(str, "SCALE=", 6)) ; + else if(!strncmp(str, "CPU=", 4)) { + if(!strncmp(str+4, "decm", 4)) im->endianness = END_LITTLE; + else if(!strncmp(str+4, "alpha", 5)) im->endianness = END_LITTLE; + else if(!strncmp(str+4, "pc", 2)) im->endianness = END_LITTLE; + else if(!strncmp(str+4, "sun", 3)) im->endianness = END_BIG; + else if(!strncmp(str+4, "sgi", 3)) im->endianness = END_BIG; + else return -1; + } + + else if(!strncmp(str, "XO=", 3)) { + std::istringstream iss(str+3); + if(!(iss >> im->cx)) return -1; + } + else if(!strncmp(str, "YO=", 3)) { + std::istringstream iss(str+3); + if(!(iss >> im->cy)) return -1; + } + else if(!strncmp(str, "ZO=", 3)) { + std::istringstream iss(str+3); + if(!(iss >> im->cz)) return -1; + } + + else if(!strncmp(str, "TX=", 3)) { + std::istringstream iss(str+3); + if(!(iss >> im->tx)) return -1; + } + else if(!strncmp(str, "TY=", 3)) { + std::istringstream iss(str+3); + if(!(iss >> im->ty)) return -1; + } + else if(!strncmp(str, "TZ=", 3)) { + std::istringstream iss(str+3); + if(!(iss >> im->tz)) return -1; + } + else if(!strncmp(str, "RX=", 3)) { + std::istringstream iss(str+3); + if(!(iss >> im->rx)) return -1; + } + else if(!strncmp(str, "RY=", 3)) { + std::istringstream iss(str+3); + if(!(iss >> im->ry)) return -1; + } + else if(!strncmp(str, "RZ=", 3)) { + std::istringstream iss(str+3); + if(!(iss >> im->rz)) return -1; + } + + if(!fgetns(str, 257, im)) return -1; + } + + /* parse user strings */ + im->nuser = nusr = 0; + while(str[0] == '#' && strncmp(str, "##}", 3)) { + addStringElement(&strl, str + 1); + while(strlen(str) == 256) { + if(!fgetns(str, 257, im)) return -1; + concatStringElement(&strl, str); + } + nusr++; + if(!fgetns(str, 257, im)) return -1; + } + + /* go to end of header */ + while(strncmp(str, "##}", 3)) { + if(!fgetns(str, 257, im)) return -1; + } + + + /* check header validity */ + if(im->xdim > 0 && im->ydim > 0 && im->zdim > 0 && im->vdim > 0 && + im->vx > 0.0 && im->vy > 0.0 && im->vz > 0.0 && + (im->wordKind == WK_FLOAT || (im->wordKind == WK_FIXED && + im->sign != SGN_UNKNOWN)) && + im->endianness != END_UNKNOWN) { + if(nusr > 0) { + im->nuser = nusr; + im->user = (char **) ImageIO_alloc(im->nuser * sizeof(char *)); + oel = NULL; + for(el = strl.begin, n = 0; el != NULL; el = oel, n++) { + im->user[n] = el->string; + oel = el->next; + ImageIO_free(el); + } + } + return 0; + } + else return -1; + + } + else return -1; +} + + + +/* add a string element at the tail of given list */ +static void addStringElement(stringListHead *strhead, const char *str) { + stringListElement *el; + + el = (stringListElement *) ImageIO_alloc(sizeof(stringListElement)); + /* was strdup(str); */ + el->string = (char*)ImageIO_alloc( strlen(str)+1); + memcpy(el->string, str, strlen(str)+1); + el->next = NULL; + if(strhead->begin == NULL) + strhead->begin = strhead->end = el; + else { + strhead->end->next = el; + strhead->end = el; + } +} + + +/* concat given string at the last element of given list */ +static void concatStringElement(const stringListHead *strhead, + const char *str) { + stringListElement *el; + + el = strhead->end; + el->string = (char *) realloc(el->string, + strlen(el->string) + strlen(str) + 1); + strcat(el->string, str); +} + +CGAL_INLINE_FUNCTION +int testInrimageHeader(char *magic,const char *) { + if (!strcmp(magic, INR_MAGIC)) + return 0; + else + return -1; +} +CGAL_INLINE_FUNCTION +int writeInrimage(char *name,_image *im) { + int res; + + _openWriteImage( im, name ); + + if(!im->fd) { + fprintf(stderr, "writeInrimage: error: unable to open file \'%s\'\n", name ); + return ImageIO_OPENING; + } + + res = _writeInrimageHeader(im, END_UNKNOWN); + if (res < 0) { + fprintf(stderr, "writeInrimage: error: unable to write header of \'%s\'\n", + name); + ImageIO_close( im ); + im->fd = NULL; + im->openMode = OM_CLOSE; + return( res ); + } + + res = _writeInrimageData( im ); + if (res < 0) { + fprintf(stderr, "writeInrimage: error: unable to write data of \'%s\'\n", + name); + ImageIO_close( im ); + im->fd = NULL; + im->openMode = OM_CLOSE; + return( res ); + } + + ImageIO_close( im ); + im->fd = NULL; + im->openMode = OM_CLOSE; + + return ( res ); +} + +CGAL_INLINE_FUNCTION +PTRIMAGE_FORMAT createInrimageFormat() { + PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); + + f->testImageFormat=&testInrimageHeader; + f->readImageHeader=&readInrimageHeader; + f->writeImage=&writeInrimage; + strcpy(f->fileExtension,".inr,.inr.gz,.gradient,.gradient.gz,.gradient_direction,.gradient_direction.gz"); + strcpy(f->realName,"Inrimage"); + return f; +} diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/iris.cpp b/CGAL_ImageIO/src/CGAL_ImageIO/iris.cpp index 2cce0587b84..711313748c6 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/iris.cpp +++ b/CGAL_ImageIO/src/CGAL_ImageIO/iris.cpp @@ -19,473 +19,9 @@ // // Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau -/* - * xviris.c - load routine for IRIS 'rgb' format pictures - * - * LoadIRIS() - * WriteIRIS() - */ -#include -#include -#include +#ifndef CGAL_HEADER_ONLY + #include "iris.h" +#include "iris_impl.h" - - -/** Magic header for RGB files */ -#define IRIS_MAGIC 0732 - - - -typedef unsigned char byte; - -#define BPPMASK 0x00ff -#define ITYPE_VERBATIM 0x0000 -#define ITYPE_RLE 0x0100 -#define ISRLE(type) (((type) & 0xff00) == ITYPE_RLE) -#define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM) -#define BPP(type) ((type) & BPPMASK) -#define RLE(bpp) (ITYPE_RLE | (bpp)) -#define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp)) - - - - - - -#define TAGLEN (5) - -#define RINTLUM (79) -#define GINTLUM (156) -#define BINTLUM (21) - -#define OFFSET_R 3 /* this is byte order dependent */ -#define OFFSET_G 2 -#define OFFSET_B 1 -#define OFFSET_A 0 - -#define ILUM(r,g,b) ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8) -#define CHANOFFSET(z) (3-(z)) /* this is byte order dependent */ - -static byte *getimagedata (const _image *im, unsigned short, int, int, int); -static void interleaverow (byte *, byte *, int, int); -static void expandrow (byte *, byte *, int); -static void readtab (const _image *im, unsigned long *, int); -static void addimgtag (byte *, int, int); - - -static unsigned short getshort (const _image *im); -static unsigned long getlong (const _image *im); - - - -int testIrisHeader(char *magic,const char *) { - if((((unsigned char *)magic)[0]<<8) + ((unsigned char *)magic)[1] - == IRIS_MAGIC) - return 0; - else - return -1; -} - -PTRIMAGE_FORMAT createIrisFormat() { - PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); - - f->testImageFormat=&testIrisHeader; - f->readImageHeader=&readIrisImage; - f->writeImage=0; - strcpy(f->fileExtension,".rgb"); - strcpy(f->realName,"IRIS"); - return f; -} - - - -/******************************************/ -static void interleaverow(byte *lptr, byte *cptr, int z, int n) -{ - lptr += z; - while(n--) { - *lptr = *cptr++; - lptr += 4; - } -} - - -/******************************************/ -static void expandrow(byte *optr, byte *iptr, int z) -{ - byte pixel, count; - - optr += z; - while (1) { - pixel = *iptr++; - if ( !(count = (pixel & 0x7f)) ) return; - if (pixel & 0x80) { - while (count>=8) { - optr[0*4] = iptr[0]; - optr[1*4] = iptr[1]; - optr[2*4] = iptr[2]; - optr[3*4] = iptr[3]; - optr[4*4] = iptr[4]; - optr[5*4] = iptr[5]; - optr[6*4] = iptr[6]; - optr[7*4] = iptr[7]; - optr += 8*4; - iptr += 8; - count -= 8; - } - while(count--) { - *optr = *iptr++; - optr+=4; - } - } - else { - pixel = *iptr++; - while(count>=8) { - optr[0*4] = pixel; - optr[1*4] = pixel; - optr[2*4] = pixel; - optr[3*4] = pixel; - optr[4*4] = pixel; - optr[5*4] = pixel; - optr[6*4] = pixel; - optr[7*4] = pixel; - optr += 8*4; - count -= 8; - } - while(count--) { - *optr = pixel; - optr+=4; - } - } - } -} - -/****************************************************/ -static void readtab(const _image *im, unsigned long *tab, int n) -{ - while (n) { - *tab++ = getlong(im); - n--; - } -} - - -/*****************************************************/ -static void addimgtag(byte *dptr, int xsize, int ysize) -{ - /* this is used to extract image data from core dumps. - I doubt this is necessary... --jhb */ - - dptr = dptr + (xsize * ysize * 4); - dptr[0] = 0x12; dptr[1] = 0x34; dptr[2] = 0x56; dptr[3] = 0x78; - dptr += 4; - - dptr[0] = 0x59; dptr[1] = 0x49; dptr[2] = 0x33; dptr[3] = 0x33; - dptr += 4; - - dptr[0] = 0x69; dptr[1] = 0x43; dptr[2] = 0x42; dptr[3] = 0x22; - dptr += 4; - - dptr[0] = (xsize>>24)&0xff; - dptr[1] = (xsize>>16)&0xff; - dptr[2] = (xsize>> 8)&0xff; - dptr[3] = (xsize )&0xff; - dptr += 4; - - dptr[0] = (ysize>>24)&0xff; - dptr[1] = (ysize>>16)&0xff; - dptr[2] = (ysize>> 8)&0xff; - dptr[3] = (ysize )&0xff; -} - -/* byte order independent read/write of shorts and longs. */ -/*****************************************************/ -static unsigned short getshort( const _image *im) -{ - byte buf[2]; - ImageIO_read( im, buf, (size_t) 2); - return (buf[0]<<8)+(buf[1]<<0); -} - -/*****************************************************/ -static unsigned long getlong( const _image *im ) -{ - byte buf[4]; - ImageIO_read( im, buf, (size_t) 4); - return (((unsigned long) buf[0])<<24) + (((unsigned long) buf[1])<<16) - + (((unsigned long) buf[2])<<8) + buf[3]; -} - -/*****************************************************/ -int readIrisImage( const char *, _image *im ) { - byte *rawdata, *rptr; - byte *pic824, *bptr, *iptr; - int i, j, size; - unsigned short imagic, type; - int xsize, ysize, zsize; - - - /* read header information from file */ - imagic = getshort( im ); - type = getshort( im ); - getshort( im ); - xsize = getshort( im ); - ysize = getshort( im ); - zsize = getshort( im ); - - if ( ImageIO_error(im) ) return( 0 ); - - if (imagic != IRIS_MAGIC) return( 0 ); - - rawdata = getimagedata(im, type, xsize, ysize, zsize); - if (!rawdata) return( 0 ); - - if ( ImageIO_error(im) ) return( 0 ); /* probably truncated file */ - - - /* t1=texture_alloc(); - (void) strcpy(t1->name,fname); - t1->type=IRIS; - - t1->nrows = ysize; - t1->ncols = xsize; - - t1->image = create_int_array(t1->nrows,t1->ncols);*/ - - /* got the raw image data. Convert to an XV image (1,3 bytes / pix) */ - if (zsize < 3) - { /* grayscale */ - im->xdim = xsize; - im->ydim = ysize; - im->zdim = 1; - im->vdim = 1; - im->wdim = 1; - im->wordKind = WK_FIXED; - im->sign = SGN_UNSIGNED; - im->data = ImageIO_alloc(xsize * ysize); - - pic824 = (byte *) ImageIO_alloc((size_t) xsize * ysize); - if (!pic824) exit(-1); - - /* copy plane 3 from rawdata into pic824, inverting pic vertically */ - for (i = 0, bptr = pic824; i < (int) ysize; i++) - { - rptr = rawdata + 3 + ((ysize - 1) - i) * (xsize * 4); - for (j = 0; j < (int) xsize; j++, bptr++, rptr += 4) - *bptr = *rptr; - } - - - size = im->xdim * im->ydim; - for (bptr = pic824, iptr = (unsigned char *) im->data, - i = 0; i < size; ++i, ++iptr, ++bptr) - { - *iptr = *bptr; - } - - ImageIO_free(pic824); - - } - - else { /* truecolor */ - im->xdim = xsize; - im->ydim = ysize; - im->zdim = zsize / 3; - im->vdim = 4; - im->wdim = 1; - im->wordKind = WK_FIXED; - im->sign = SGN_UNSIGNED; - im->data = ImageIO_alloc(xsize * ysize * im->zdim * 4); - - pic824 = (byte *) ImageIO_alloc((size_t) xsize * ysize * 3); - if (!pic824) - exit(1); - - /* copy plane 3 from rawdata into pic824, inverting pic vertically */ - for (i = 0, bptr = pic824; i<(int) ysize; i++) - { - rptr = rawdata + ((ysize - 1) - i) * (xsize * 4); - - for (j=0; j<(int) xsize; j++, rptr += 4) { - *bptr++ = rptr[3]; - *bptr++ = rptr[2]; - *bptr++ = rptr[1]; - } - } - - - size = im->xdim * im->ydim; - for (bptr = pic824, iptr = (unsigned char *) im->data, i = 0; - i < size; ++i, iptr += 4, bptr += 3) - { - if ( _getEndianness() == END_LITTLE ) { - iptr[0] = 0xFF; - iptr[1] = bptr[2]; - iptr[2] = bptr[1]; - iptr[3] = bptr[0]; - } - else { - iptr[0] = bptr[0]; - iptr[1] = bptr[1]; - iptr[2] = bptr[2]; - iptr[3] = 0xFF; - } - } - ImageIO_free(pic824); - } - - ImageIO_free(rawdata); - - return 1; -} - - - - -/****************************************************/ -static byte *getimagedata(const _image *im, unsigned short type, int xsize, int ysize, - int zsize) -{ - /* read in a B/W RGB or RGBA iris image file and return a - pointer to an array of 4-byte pixels, arranged ABGR, NULL on error */ - - byte *base, *lptr; - byte *verdat; - int y, z, tablen; - int bpp, rle, badorder; - int rlebuflen; - byte *rledat; - unsigned long *starttab, *lengthtab, cur; - - - rle = ISRLE(type); - bpp = BPP(type); - - if (bpp != 1) { - return (byte *) NULL; - } - - if (rle) { - - rlebuflen = 2 * xsize + 10; - tablen = ysize * zsize; - starttab = (unsigned long *) ImageIO_alloc((size_t) tablen * sizeof(long)); - lengthtab = (unsigned long *) ImageIO_alloc((size_t) tablen * sizeof(long)); - rledat = (byte *) ImageIO_alloc((size_t) rlebuflen); - - if (!starttab || !lengthtab || !rledat) - exit(1); - - ImageIO_seek( im, 512L, SEEK_SET ); - readtab(im, starttab, tablen); - readtab(im, lengthtab, tablen); - - if ( ImageIO_error(im) ) { - ImageIO_free(starttab); ImageIO_free(lengthtab); ImageIO_free(rledat); - return (byte *) NULL; - } - - - /* check data order */ - cur = 0; - badorder = 0; - for (y=0; y(unsigned long)rlebuflen) { - ImageIO_free(starttab); ImageIO_free(lengthtab); ImageIO_free(rledat); ImageIO_free(base); - return (byte *) NULL; - } - ImageIO_read(im, rledat, (size_t) lengthtab[y+z*ysize]); - cur += lengthtab[y+z*ysize]; - expandrow(lptr,rledat,3-z); - lptr += (xsize * 4); - } - } - } - else { - lptr = base; - for (y=0; y +#endif // CGAL_HEADER_ONLY #endif diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/iris_impl.h b/CGAL_ImageIO/src/CGAL_ImageIO/iris_impl.h new file mode 100644 index 00000000000..c42f296f688 --- /dev/null +++ b/CGAL_ImageIO/src/CGAL_ImageIO/iris_impl.h @@ -0,0 +1,499 @@ +// Copyright (c) 2005-2008 ASCLEPIOS Project, INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of the ImageIO Library, and as been adapted for +// CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the +// GNU Lesser General Public License as published by the Free Software Foundation; +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau + +/* + * xviris.c - load routine for IRIS 'rgb' format pictures + * + * LoadIRIS() + * WriteIRIS() + */ + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include + + + +/** Magic header for RGB files */ +#define IRIS_MAGIC 0732 + + + +typedef unsigned char byte; + +#define BPPMASK 0x00ff +#define ITYPE_VERBATIM 0x0000 +#define ITYPE_RLE 0x0100 +#define ISRLE(type) (((type) & 0xff00) == ITYPE_RLE) +#define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM) +#define BPP(type) ((type) & BPPMASK) +#define RLE(bpp) (ITYPE_RLE | (bpp)) +#define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp)) + + + + + + +#define TAGLEN (5) + +#define RINTLUM (79) +#define GINTLUM (156) +#define BINTLUM (21) + +#define OFFSET_R 3 /* this is byte order dependent */ +#define OFFSET_G 2 +#define OFFSET_B 1 +#define OFFSET_A 0 + +#define ILUM(r,g,b) ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8) +#define CHANOFFSET(z) (3-(z)) /* this is byte order dependent */ + +static byte *getimagedata (const _image *im, unsigned short, int, int, int); +static void interleaverow (byte *, byte *, int, int); +static void expandrow (byte *, byte *, int); +static void readtab (const _image *im, unsigned long *, int); +static void addimgtag (byte *, int, int); + + +static unsigned short getshort (const _image *im); +static unsigned long getlong (const _image *im); + + +CGAL_INLINE_FUNCTION +int testIrisHeader(char *magic,const char *) { + if((((unsigned char *)magic)[0]<<8) + ((unsigned char *)magic)[1] + == IRIS_MAGIC) + return 0; + else + return -1; +} + +CGAL_INLINE_FUNCTION +PTRIMAGE_FORMAT createIrisFormat() { + PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); + + f->testImageFormat=&testIrisHeader; + f->readImageHeader=&readIrisImage; + f->writeImage=0; + strcpy(f->fileExtension,".rgb"); + strcpy(f->realName,"IRIS"); + return f; +} + + + +/******************************************/ +static void interleaverow(byte *lptr, byte *cptr, int z, int n) +{ + lptr += z; + while(n--) { + *lptr = *cptr++; + lptr += 4; + } +} + + +/******************************************/ +static void expandrow(byte *optr, byte *iptr, int z) +{ + byte pixel, count; + + optr += z; + while (1) { + pixel = *iptr++; + if ( !(count = (pixel & 0x7f)) ) return; + if (pixel & 0x80) { + while (count>=8) { + optr[0*4] = iptr[0]; + optr[1*4] = iptr[1]; + optr[2*4] = iptr[2]; + optr[3*4] = iptr[3]; + optr[4*4] = iptr[4]; + optr[5*4] = iptr[5]; + optr[6*4] = iptr[6]; + optr[7*4] = iptr[7]; + optr += 8*4; + iptr += 8; + count -= 8; + } + while(count--) { + *optr = *iptr++; + optr+=4; + } + } + else { + pixel = *iptr++; + while(count>=8) { + optr[0*4] = pixel; + optr[1*4] = pixel; + optr[2*4] = pixel; + optr[3*4] = pixel; + optr[4*4] = pixel; + optr[5*4] = pixel; + optr[6*4] = pixel; + optr[7*4] = pixel; + optr += 8*4; + count -= 8; + } + while(count--) { + *optr = pixel; + optr+=4; + } + } + } +} + +/****************************************************/ +static void readtab(const _image *im, unsigned long *tab, int n) +{ + while (n) { + *tab++ = getlong(im); + n--; + } +} + + +/*****************************************************/ +static void addimgtag(byte *dptr, int xsize, int ysize) +{ + /* this is used to extract image data from core dumps. + I doubt this is necessary... --jhb */ + + dptr = dptr + (xsize * ysize * 4); + dptr[0] = 0x12; dptr[1] = 0x34; dptr[2] = 0x56; dptr[3] = 0x78; + dptr += 4; + + dptr[0] = 0x59; dptr[1] = 0x49; dptr[2] = 0x33; dptr[3] = 0x33; + dptr += 4; + + dptr[0] = 0x69; dptr[1] = 0x43; dptr[2] = 0x42; dptr[3] = 0x22; + dptr += 4; + + dptr[0] = (xsize>>24)&0xff; + dptr[1] = (xsize>>16)&0xff; + dptr[2] = (xsize>> 8)&0xff; + dptr[3] = (xsize )&0xff; + dptr += 4; + + dptr[0] = (ysize>>24)&0xff; + dptr[1] = (ysize>>16)&0xff; + dptr[2] = (ysize>> 8)&0xff; + dptr[3] = (ysize )&0xff; +} + +/* byte order independent read/write of shorts and longs. */ +/*****************************************************/ +static unsigned short getshort( const _image *im) +{ + byte buf[2]; + ImageIO_read( im, buf, (size_t) 2); + return (buf[0]<<8)+(buf[1]<<0); +} + +/*****************************************************/ +static unsigned long getlong( const _image *im ) +{ + byte buf[4]; + ImageIO_read( im, buf, (size_t) 4); + return (((unsigned long) buf[0])<<24) + (((unsigned long) buf[1])<<16) + + (((unsigned long) buf[2])<<8) + buf[3]; +} + +/*****************************************************/ +CGAL_INLINE_FUNCTION +int readIrisImage( const char *, _image *im ) { + byte *rawdata, *rptr; + byte *pic824, *bptr, *iptr; + int i, j, size; + unsigned short imagic, type; + int xsize, ysize, zsize; + + + /* read header information from file */ + imagic = getshort( im ); + type = getshort( im ); + getshort( im ); + xsize = getshort( im ); + ysize = getshort( im ); + zsize = getshort( im ); + + if ( ImageIO_error(im) ) return( 0 ); + + if (imagic != IRIS_MAGIC) return( 0 ); + + rawdata = getimagedata(im, type, xsize, ysize, zsize); + if (!rawdata) return( 0 ); + + if ( ImageIO_error(im) ) return( 0 ); /* probably truncated file */ + + + /* t1=texture_alloc(); + (void) strcpy(t1->name,fname); + t1->type=IRIS; + + t1->nrows = ysize; + t1->ncols = xsize; + + t1->image = create_int_array(t1->nrows,t1->ncols);*/ + + /* got the raw image data. Convert to an XV image (1,3 bytes / pix) */ + if (zsize < 3) + { /* grayscale */ + im->xdim = xsize; + im->ydim = ysize; + im->zdim = 1; + im->vdim = 1; + im->wdim = 1; + im->wordKind = WK_FIXED; + im->sign = SGN_UNSIGNED; + im->data = ImageIO_alloc(xsize * ysize); + + pic824 = (byte *) ImageIO_alloc((size_t) xsize * ysize); + if (!pic824) exit(-1); + + /* copy plane 3 from rawdata into pic824, inverting pic vertically */ + for (i = 0, bptr = pic824; i < (int) ysize; i++) + { + rptr = rawdata + 3 + ((ysize - 1) - i) * (xsize * 4); + for (j = 0; j < (int) xsize; j++, bptr++, rptr += 4) + *bptr = *rptr; + } + + + size = im->xdim * im->ydim; + for (bptr = pic824, iptr = (unsigned char *) im->data, + i = 0; i < size; ++i, ++iptr, ++bptr) + { + *iptr = *bptr; + } + + ImageIO_free(pic824); + + } + + else { /* truecolor */ + im->xdim = xsize; + im->ydim = ysize; + im->zdim = zsize / 3; + im->vdim = 4; + im->wdim = 1; + im->wordKind = WK_FIXED; + im->sign = SGN_UNSIGNED; + im->data = ImageIO_alloc(xsize * ysize * im->zdim * 4); + + pic824 = (byte *) ImageIO_alloc((size_t) xsize * ysize * 3); + if (!pic824) + exit(1); + + /* copy plane 3 from rawdata into pic824, inverting pic vertically */ + for (i = 0, bptr = pic824; i<(int) ysize; i++) + { + rptr = rawdata + ((ysize - 1) - i) * (xsize * 4); + + for (j=0; j<(int) xsize; j++, rptr += 4) { + *bptr++ = rptr[3]; + *bptr++ = rptr[2]; + *bptr++ = rptr[1]; + } + } + + + size = im->xdim * im->ydim; + for (bptr = pic824, iptr = (unsigned char *) im->data, i = 0; + i < size; ++i, iptr += 4, bptr += 3) + { + if ( _getEndianness() == END_LITTLE ) { + iptr[0] = 0xFF; + iptr[1] = bptr[2]; + iptr[2] = bptr[1]; + iptr[3] = bptr[0]; + } + else { + iptr[0] = bptr[0]; + iptr[1] = bptr[1]; + iptr[2] = bptr[2]; + iptr[3] = 0xFF; + } + } + ImageIO_free(pic824); + } + + ImageIO_free(rawdata); + + return 1; +} + + + + +/****************************************************/ +static byte *getimagedata(const _image *im, unsigned short type, int xsize, int ysize, + int zsize) +{ + /* read in a B/W RGB or RGBA iris image file and return a + pointer to an array of 4-byte pixels, arranged ABGR, NULL on error */ + + byte *base, *lptr; + byte *verdat; + int y, z, tablen; + int bpp, rle, badorder; + int rlebuflen; + byte *rledat; + unsigned long *starttab, *lengthtab, cur; + + + rle = ISRLE(type); + bpp = BPP(type); + + if (bpp != 1) { + return (byte *) NULL; + } + + if (rle) { + + rlebuflen = 2 * xsize + 10; + tablen = ysize * zsize; + starttab = (unsigned long *) ImageIO_alloc((size_t) tablen * sizeof(long)); + lengthtab = (unsigned long *) ImageIO_alloc((size_t) tablen * sizeof(long)); + rledat = (byte *) ImageIO_alloc((size_t) rlebuflen); + + if (!starttab || !lengthtab || !rledat) + exit(1); + + ImageIO_seek( im, 512L, SEEK_SET ); + readtab(im, starttab, tablen); + readtab(im, lengthtab, tablen); + + if ( ImageIO_error(im) ) { + ImageIO_free(starttab); ImageIO_free(lengthtab); ImageIO_free(rledat); + return (byte *) NULL; + } + + + /* check data order */ + cur = 0; + badorder = 0; + for (y=0; y(unsigned long)rlebuflen) { + ImageIO_free(starttab); ImageIO_free(lengthtab); ImageIO_free(rledat); ImageIO_free(base); + return (byte *) NULL; + } + ImageIO_read(im, rledat, (size_t) lengthtab[y+z*ysize]); + cur += lengthtab[y+z*ysize]; + expandrow(lptr,rledat,3-z); + lptr += (xsize * 4); + } + } + } + else { + lptr = base; + for (y=0; y -#include -#include -#include +#include "mincio_impl.h" - - -/** Magic header for MINC (MNI NetCDF) file format */ -#ifdef MINC_FILES -# define MINC_MAGIC "CDF" -#endif - - - -int readMincHeader(_image *im, const char* filename, - double *startx, double *starty, double *startz, - double *stepx, double *stepy, double *stepz, - double *Xcosines, double *Ycosines, double *Zcosines) { - int fin, varid, minc_icv, id, ndims, i, dim[256], length, - minfound = 0, maxfound = 0; - long start[3] = {0, 0, 0}, count[3]; - unsigned int plane1, plane2, line, shift[3], ct[3]; - nc_type type; - char sign_type[MI_MAX_ATTSTR_LEN], name[MAX_NC_NAME]; - void *data; - double range[2], swap; - - /* open minc file */ - fin = miopen((char *) filename, NC_NOWRITE); - if(fin == MI_ERROR) return 0; - - /* get number of dimensions and type */ - id = ncvarid(fin, MIimage); - (void) ncvarinq(fin, id, NULL, &type, &ndims, dim, NULL); - if(ndims != 3) { - fprintf(stderr, "unsupported %i dimensional minc file\n", ndims); - return 0; - } - - /* get sign */ - if ((miattgetstr(fin, id, MIsigntype, MI_MAX_ATTSTR_LEN, sign_type) - == NULL) || ((strcmp(sign_type, MI_UNSIGNED)!=0) && - (strcmp(sign_type, MI_SIGNED)!=0))) { - if (type == NC_BYTE) - (void) strcpy(sign_type, MI_UNSIGNED); - else - (void) strcpy(sign_type, MI_SIGNED); - } - im->sign = (!strcmp(sign_type, MI_UNSIGNED)) ? SGN_UNSIGNED : SGN_SIGNED; - - switch(type) { - case NC_CHAR: - case NC_BYTE: - im->wdim = 1; - im->wordKind = WK_FIXED; - im->sign = SGN_UNSIGNED; - break; - case NC_SHORT: - im->wdim = 2; - im->wordKind = WK_FIXED; - break; - case NC_LONG: - im->wdim = 4; - im->wordKind = WK_FIXED; - break; - case NC_FLOAT: - im->wdim = 4; - im->wordKind = WK_FLOAT; - im->sign = SGN_UNKNOWN; - break; - case NC_DOUBLE: - im->wdim = 8; - im->wordKind = WK_FLOAT; - im->sign = SGN_UNKNOWN; - break; - default: - fprintf(stderr, "unsupported minc type\n"); - return 0; - break; - } - - - /* get dimensions length and voxel size */ - ncopts = 0; - for(i = 0; i < ndims; i++) { - (void) ncdiminq(fin, dim[i], name, &count[i]); - varid = ncvarid(fin, name); - if(!strcmp(name, MIxspace)) { - im->xdim = count[i]; - if(miattget1(fin, varid, MIstep, NC_DOUBLE, stepx) == MI_ERROR) - *stepx = 1.0; - im->vx = fabs(*stepx); - if(miattget1(fin, varid, MIstart, NC_DOUBLE, startx) == MI_ERROR) - *startx = 0.0; - if(miattget(fin, varid, MIdirection_cosines, NC_DOUBLE, 3, - (void *) Xcosines, (int *) 0) == MI_ERROR ) { - Xcosines[0] = 0.0; - Xcosines[1] = 0.0; - Xcosines[2] = 0.0; - } - } - else if(!strcmp(name, MIyspace)) { - im->ydim = count[i]; - if(miattget1(fin, varid, MIstep, NC_DOUBLE, stepy) == MI_ERROR) - *stepy = 1.0; - im->vy = fabs(*stepy); - if(miattget1(fin, varid, MIstart, NC_DOUBLE, starty) == MI_ERROR) - *starty = 0.0; - if(miattget(fin, varid, MIdirection_cosines, NC_DOUBLE, 3, - (void *) Ycosines, (int *) 0) == MI_ERROR ) { - Ycosines[0] = 0.0; - Ycosines[1] = 0.0; - Ycosines[2] = 0.0; - } - } - else if(!strcmp(name, MIzspace)) { - im->zdim = count[i]; - if(miattget1(fin, varid, MIstep, NC_DOUBLE, stepz) == MI_ERROR) - *stepz = 1.0; - im->vz = fabs(*stepz); - if(miattget1(fin, varid, MIstart, NC_DOUBLE, startz) == MI_ERROR) - *startz = 0.0; - if(miattget(fin, varid, MIdirection_cosines, NC_DOUBLE, 3, - (void *) Zcosines, (int *) 0) == MI_ERROR ) { - Zcosines[0] = 0.0; - Zcosines[1] = 0.0; - Zcosines[2] = 0.0; - } - } else { - fprintf(stderr, "unsupported dimension %s\n", name); - return 0; - } - } - - - if( miattget( fin, id, MIvalid_range, NC_DOUBLE, 2, - (void *) range, &length) == MI_ERROR || length != 2 ) { - if( miattget1( fin, id, MIvalid_min, NC_DOUBLE, - (void *) &range[0] ) != MI_ERROR ) - minfound = 1; - if( miattget1( fin, id, MIvalid_max, NC_DOUBLE, - (void *) &range[1] ) != MI_ERROR ) - maxfound = 1; - } - else { - if( range[0] > range[1] ) { - swap = range[0]; - range[0] = range[1]; - range[1] = swap; - } - minfound = 1; - maxfound = 1; - } - - if(!minfound) { - switch(type) { - case NC_CHAR: - case NC_BYTE: - range[0] = 0; - break; - case NC_SHORT: - if(im->sign == SGN_SIGNED) range[0] = -32768.0; - else range[0] = 0; - break; - case NC_LONG: - if(im->sign == SGN_SIGNED) range[0] = -2147483648.0; - else range[0] = 0; - break; - default: - range[0] = 0.0; - break; - } - } - if(!maxfound) { - switch(type) { - case NC_CHAR: - case NC_BYTE: - range[1] = 255.0; - break; - case NC_SHORT: - if(im->sign == SGN_SIGNED) range[1] = 32767.0; - else range[1] = 65535.0; - break; - case NC_LONG: - if(im->sign == SGN_SIGNED) range[1] = 2147483647.0; - else range[1] = 4294967295.0; - break; - default: - range[1] = 1.0; - break; - } - } - - ncopts = NC_VERBOSE | NC_FATAL; - im->vdim = 1; - - /* read data bytes */ - im->data = ImageIO_alloc(im->xdim * im->ydim * im->zdim * im->vdim * - im->wdim); - - minc_icv = miicv_create(); - (void) miicv_setint( minc_icv, MI_ICV_TYPE, type ); - (void) miicv_setstr( minc_icv, MI_ICV_SIGN, sign_type ); - (void) miicv_setint( minc_icv, MI_ICV_DO_NORM, 1 ); - (void) miicv_setint( minc_icv, MI_ICV_DO_FILLVALUE, 1 ); - (void) miicv_setdbl( minc_icv, MI_ICV_VALID_MIN, range[0] ); - (void) miicv_setdbl( minc_icv, MI_ICV_VALID_MAX, range[1] ); - - (void) miicv_attach( minc_icv, fin, id ); - - if(miicv_get(minc_icv, start, count, im->data) == MI_ERROR) { - fprintf(stderr, "error while reading file\n"); - return 0; - } - (void) miicv_detach( minc_icv ); - (void) miicv_free( minc_icv ); - - ImageIO_closeImage(im); - - /* order data in ZYX */ - (void) ncdiminq(fin, dim[0], name, NULL); - if(!strcmp(name, MIzspace)) { - (void) ncdiminq(fin, dim[1], name, NULL); - /* file is ZYX */ - if(!strcmp(name, MIyspace)) { - miclose(fin); - return 1; - } - } - - (void) ncdiminq(fin, dim[0], name, NULL); - /* file is ZXY */ - if(!strcmp(name, MIzspace)) { - shift[0] = 0; - shift[1] = 2; - shift[2] = 1; - plane2 = im->xdim * im->ydim; - line = im->ydim; - } - /* file is Y first */ - else if(!strcmp(name, MIyspace)) { - shift[0] = 1; - plane2 = im->xdim * im->zdim; - (void) ncdiminq(fin, dim[1], name, NULL); - /* file is YXZ */ - if(!strcmp(name, MIxspace)) { - shift[1] = 2; - shift[2] = 0; - line = im->zdim; - } - /* file is YZX */ - else { - shift[1] = 0; - shift[2] = 2; - line = im->xdim; - } - } - /* file is X first */ - else { - shift[0] = 2; - plane2 = im->ydim * im->zdim; - (void) ncdiminq(fin, dim[1], name, NULL); - /* file is XYZ */ - if(!strcmp(name, MIyspace)) { - shift[1] = 1; - shift[2] = 0; - line = im->zdim; - } - /* file is XZY */ - else { - shift[1] = 0; - shift[2] = 1; - line = im->ydim; - } - } - - data = ImageIO_alloc(im->xdim * im->ydim * im->zdim * im->vdim * im->wdim); - plane1 = im->xdim * im->ydim; - - for(ct[0] = 0; ct[0] < im->zdim; ct[0]++) { - for(ct[1] = 0; ct[1] < im->ydim; ct[1]++) { - for(ct[2] = 0; ct[2] < im->xdim; ct[2]++) { - memcpy((unsigned char *) data + - (ct[0] * plane1 + ct[1] * im->xdim + ct[2]) * im->wdim, - (unsigned char *) im->data + - (ct[shift[0]] * plane2 + ct[shift[1]] * line + ct[shift[2]]) - * im->wdim, im->wdim); - } - } - } - - ImageIO_free(im->data); - im->data = data; - - /* close file */ - miclose(fin); - return 1; -} - - - - -int writeMincFile( const _image* im, const char *filename, - const char *sourcename, - double startx, double starty, double startz, - double stepx, double stepy, double stepz, - const double *Xcosine, const double *Ycosine, - const double *Zcosine, const double *range ) { - int i, cdfid, minc_icv, dim_vars[3], dim_ids[3], img_var_id, min_id, max_id, - src_cdfid, src_img_var, varid, n_excluded, excluded_vars[10], - src_min_id, src_max_id, src_root_id, old_att_length, same_file = 0; - long org[3] = {0, 0, 0}, count[3] = { im->zdim, im->ydim, im->xdim }; - char *dim_names[3] = { MIzspace, MIyspace, MIxspace }, *history, - *excluded_list[3] = { MIxspace, MIyspace, MIzspace }, *newname; - nc_type type, datatype; - double start[3] = { startz, starty, startx }, - vx[3] = { stepz, stepy, stepx }; - - /* if filename is the same file that sourcename, it is needed to create - a temporary file for output */ - newname = (char *) filename; - if(sourcename) { - struct stat out, org; - same_file = (stat(sourcename, &org) == 0) && (stat(filename, &out) == 0) - && (org.st_ino == out.st_ino); - if(same_file) { - newname = (char *) malloc((strlen(filename) + 10) * sizeof(char)); - for(i = strlen(filename) - 1; i > 0 && filename[i] != '/'; i--) ; - if(filename[i] == '/') { - strncpy(newname, filename, i + 1); - newname[i+1] = '\0'; - strcat(newname, "#TMP#"); - strcat(newname, filename + i + 1); - } - else - sprintf(newname, "#TMP#%s", filename); - } - } - - /* open file */ - cdfid = micreate( (char *) newname, NC_CLOBBER ); - if( cdfid == MI_ERROR ) { - fprintf(stderr, "Error: opening MINC file \"%s\".\n", filename ); - return -1; - } - - /* set word type */ - switch(im->wordKind) { - case WK_FIXED: - if(im->wdim == 1) type = NC_BYTE; - else if(im->wdim == 2) type = NC_SHORT; - else type = NC_LONG; - break; - case WK_FLOAT: - default: - if(im->wdim == 4) type = NC_FLOAT; - else type = NC_DOUBLE; - break; - } - - /* create dimensions variables */ - for(i = 0; i < 3; i++) - dim_vars[i] = ncdimdef( cdfid, dim_names[i], count[i] ); - - for(i = 0; i < 3; i++ ) { - dim_ids[i] = micreate_std_variable( cdfid, dim_names[i], NC_DOUBLE, - 0, NULL); - if( dim_ids[i] < 0 ) return -1; - (void) miattputdbl( cdfid, dim_ids[i], MIstep, vx[i]); - (void) miattputdbl( cdfid, dim_ids[i], MIstart, start[i]); - } - if(Zcosine[0] != 0.0 || Zcosine[1] != 0.0 || Zcosine[2] != 0.0) - (void) ncattput(cdfid, dim_ids[0], MIdirection_cosines, NC_DOUBLE, 3, - Zcosine); - if(Ycosine[0] != 0.0 || Ycosine[1] != 0.0 || Ycosine[2] != 0.0) - (void) ncattput(cdfid, dim_ids[1], MIdirection_cosines, NC_DOUBLE, 3, - Ycosine); - if(Xcosine[0] != 0.0 || Xcosine[1] != 0.0 || Xcosine[2] != 0.0) - (void) ncattput(cdfid, dim_ids[2], MIdirection_cosines, NC_DOUBLE, 3, - Xcosine); - - /* create image variable */ - img_var_id = micreate_std_variable( cdfid, MIimage, type, 3, dim_vars ); - (void) miattputstr( cdfid, img_var_id, MIcomplete, MI_FALSE ); - if(im->sign == SGN_SIGNED) - (void) miattputstr( cdfid, img_var_id, MIsigntype, MI_SIGNED ); - else - (void) miattputstr( cdfid, img_var_id, MIsigntype, MI_UNSIGNED ); - (void) ncattput(cdfid, img_var_id, MIvalid_range ,NC_DOUBLE, 2, range); - - min_id = micreate_std_variable(cdfid, MIimagemin, NC_DOUBLE, 0, 0 ); - max_id = micreate_std_variable(cdfid, MIimagemax, NC_DOUBLE, 0, 0 ); - - /* if the image comes from a minc file, duplicate all minc attributes */ - if(sourcename) { - if( (src_cdfid = miopen((char *) sourcename, NC_NOWRITE)) == MI_ERROR ) { - fprintf(stderr, "Error opening %s\n", sourcename ); - return -1; - } - - n_excluded = 0; - for( i = 0; i < 3; i++ ) { - if( (varid = ncvarid(src_cdfid, excluded_list[i] )) != MI_ERROR ) - excluded_vars[n_excluded++] = varid; - } - - if( (src_img_var = ncvarid(src_cdfid, MIimage )) != MI_ERROR ) - excluded_vars[n_excluded++] = src_img_var; - if( (src_max_id = ncvarid(src_cdfid, MIimagemax )) != MI_ERROR ) - excluded_vars[n_excluded++] = src_max_id; - if( (src_min_id = ncvarid(src_cdfid, MIimagemin )) != MI_ERROR ) - excluded_vars[n_excluded++] = src_min_id; - if( (src_root_id = ncvarid(src_cdfid, MIrootvariable )) != MI_ERROR ) - excluded_vars[n_excluded++] = src_root_id; - - (void) micopy_all_var_defs( src_cdfid, cdfid, n_excluded, excluded_vars ); - - if( src_img_var != MI_ERROR ) - (void) micopy_all_atts( src_cdfid, src_img_var, cdfid, img_var_id ); - if( src_root_id != MI_ERROR ) - (void) micopy_all_atts( src_cdfid, src_root_id, cdfid, - ncvarid( cdfid, MIrootvariable) ); - - ncopts = 0; - if(ncattinq(cdfid, NC_GLOBAL, MIhistory, &datatype, &old_att_length) - == MI_ERROR || datatype != NC_CHAR ) - old_att_length = 0; - - history = (char *) malloc(sizeof(char) * old_att_length); - history[0] = (char) 0; - (void) miattgetstr( cdfid, NC_GLOBAL, MIhistory, old_att_length+1, - history ); - ncopts = NC_VERBOSE | NC_FATAL; - (void) miattputstr( cdfid, NC_GLOBAL, MIhistory, history ); - free(history); - - (void) miclose( src_cdfid ); - } - - - /* write data */ - if(ncendef(cdfid) == MI_ERROR) return -1; - minc_icv = miicv_create(); - (void) miicv_setint( minc_icv, MI_ICV_TYPE, type); - (void) miicv_setstr( minc_icv, MI_ICV_SIGN, - (im->sign == SGN_SIGNED) ? MI_SIGNED : MI_UNSIGNED ); - (void) miicv_setint( minc_icv, MI_ICV_DO_NORM, 1 ); - (void) miicv_setint( minc_icv, MI_ICV_USER_NORM, 1 ); - (void) miicv_attach( minc_icv, cdfid, img_var_id ); - - if( miicv_put(minc_icv, org, count, im->data) == MI_ERROR ) - return -1; - - (void) miattputstr( cdfid, img_var_id, MIcomplete, MI_TRUE); - (void) miclose( cdfid ); - (void) miicv_free( minc_icv ); - - if(same_file) { - unlink(filename); - link(newname, filename); - unlink(newname); - free(newname); - } - - return 0; -} - - -#endif +#endif // CGAL_HEADER_ONLY diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/mincio.h b/CGAL_ImageIO/src/CGAL_ImageIO/mincio.h index 53c33a505c0..46cd034abca 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/mincio.h +++ b/CGAL_ImageIO/src/CGAL_ImageIO/mincio.h @@ -70,4 +70,8 @@ int writeMincFile( const _image* im, const char *name, const char *sourceName, #endif +#ifdef CGAL_HEADER_ONLY +#include "mincio_impl.h" +#endif // CGAL_HEADER_ONLY + #endif diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/mincio_impl.h b/CGAL_ImageIO/src/CGAL_ImageIO/mincio_impl.h new file mode 100644 index 00000000000..a8ff990ade9 --- /dev/null +++ b/CGAL_ImageIO/src/CGAL_ImageIO/mincio_impl.h @@ -0,0 +1,502 @@ +// Copyright (c) 2005-2008 ASCLEPIOS Project, INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of the ImageIO Library, and as been adapted for +// CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the +// GNU Lesser General Public License as published by the Free Software Foundation; +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#ifdef _MSC_VER +#pragma warning ( disable : 4068 4786 4081 ) +#endif + +#ifdef MINC_FILES + +#include +#include +#include +#include + + + +/** Magic header for MINC (MNI NetCDF) file format */ +#ifdef MINC_FILES +# define MINC_MAGIC "CDF" +#endif + + +CGAL_INLINE_FUNCTION +int readMincHeader(_image *im, const char* filename, + double *startx, double *starty, double *startz, + double *stepx, double *stepy, double *stepz, + double *Xcosines, double *Ycosines, double *Zcosines) { + int fin, varid, minc_icv, id, ndims, i, dim[256], length, + minfound = 0, maxfound = 0; + long start[3] = {0, 0, 0}, count[3]; + unsigned int plane1, plane2, line, shift[3], ct[3]; + nc_type type; + char sign_type[MI_MAX_ATTSTR_LEN], name[MAX_NC_NAME]; + void *data; + double range[2], swap; + + /* open minc file */ + fin = miopen((char *) filename, NC_NOWRITE); + if(fin == MI_ERROR) return 0; + + /* get number of dimensions and type */ + id = ncvarid(fin, MIimage); + (void) ncvarinq(fin, id, NULL, &type, &ndims, dim, NULL); + if(ndims != 3) { + fprintf(stderr, "unsupported %i dimensional minc file\n", ndims); + return 0; + } + + /* get sign */ + if ((miattgetstr(fin, id, MIsigntype, MI_MAX_ATTSTR_LEN, sign_type) + == NULL) || ((strcmp(sign_type, MI_UNSIGNED)!=0) && + (strcmp(sign_type, MI_SIGNED)!=0))) { + if (type == NC_BYTE) + (void) strcpy(sign_type, MI_UNSIGNED); + else + (void) strcpy(sign_type, MI_SIGNED); + } + im->sign = (!strcmp(sign_type, MI_UNSIGNED)) ? SGN_UNSIGNED : SGN_SIGNED; + + switch(type) { + case NC_CHAR: + case NC_BYTE: + im->wdim = 1; + im->wordKind = WK_FIXED; + im->sign = SGN_UNSIGNED; + break; + case NC_SHORT: + im->wdim = 2; + im->wordKind = WK_FIXED; + break; + case NC_LONG: + im->wdim = 4; + im->wordKind = WK_FIXED; + break; + case NC_FLOAT: + im->wdim = 4; + im->wordKind = WK_FLOAT; + im->sign = SGN_UNKNOWN; + break; + case NC_DOUBLE: + im->wdim = 8; + im->wordKind = WK_FLOAT; + im->sign = SGN_UNKNOWN; + break; + default: + fprintf(stderr, "unsupported minc type\n"); + return 0; + break; + } + + + /* get dimensions length and voxel size */ + ncopts = 0; + for(i = 0; i < ndims; i++) { + (void) ncdiminq(fin, dim[i], name, &count[i]); + varid = ncvarid(fin, name); + if(!strcmp(name, MIxspace)) { + im->xdim = count[i]; + if(miattget1(fin, varid, MIstep, NC_DOUBLE, stepx) == MI_ERROR) + *stepx = 1.0; + im->vx = fabs(*stepx); + if(miattget1(fin, varid, MIstart, NC_DOUBLE, startx) == MI_ERROR) + *startx = 0.0; + if(miattget(fin, varid, MIdirection_cosines, NC_DOUBLE, 3, + (void *) Xcosines, (int *) 0) == MI_ERROR ) { + Xcosines[0] = 0.0; + Xcosines[1] = 0.0; + Xcosines[2] = 0.0; + } + } + else if(!strcmp(name, MIyspace)) { + im->ydim = count[i]; + if(miattget1(fin, varid, MIstep, NC_DOUBLE, stepy) == MI_ERROR) + *stepy = 1.0; + im->vy = fabs(*stepy); + if(miattget1(fin, varid, MIstart, NC_DOUBLE, starty) == MI_ERROR) + *starty = 0.0; + if(miattget(fin, varid, MIdirection_cosines, NC_DOUBLE, 3, + (void *) Ycosines, (int *) 0) == MI_ERROR ) { + Ycosines[0] = 0.0; + Ycosines[1] = 0.0; + Ycosines[2] = 0.0; + } + } + else if(!strcmp(name, MIzspace)) { + im->zdim = count[i]; + if(miattget1(fin, varid, MIstep, NC_DOUBLE, stepz) == MI_ERROR) + *stepz = 1.0; + im->vz = fabs(*stepz); + if(miattget1(fin, varid, MIstart, NC_DOUBLE, startz) == MI_ERROR) + *startz = 0.0; + if(miattget(fin, varid, MIdirection_cosines, NC_DOUBLE, 3, + (void *) Zcosines, (int *) 0) == MI_ERROR ) { + Zcosines[0] = 0.0; + Zcosines[1] = 0.0; + Zcosines[2] = 0.0; + } + } else { + fprintf(stderr, "unsupported dimension %s\n", name); + return 0; + } + } + + + if( miattget( fin, id, MIvalid_range, NC_DOUBLE, 2, + (void *) range, &length) == MI_ERROR || length != 2 ) { + if( miattget1( fin, id, MIvalid_min, NC_DOUBLE, + (void *) &range[0] ) != MI_ERROR ) + minfound = 1; + if( miattget1( fin, id, MIvalid_max, NC_DOUBLE, + (void *) &range[1] ) != MI_ERROR ) + maxfound = 1; + } + else { + if( range[0] > range[1] ) { + swap = range[0]; + range[0] = range[1]; + range[1] = swap; + } + minfound = 1; + maxfound = 1; + } + + if(!minfound) { + switch(type) { + case NC_CHAR: + case NC_BYTE: + range[0] = 0; + break; + case NC_SHORT: + if(im->sign == SGN_SIGNED) range[0] = -32768.0; + else range[0] = 0; + break; + case NC_LONG: + if(im->sign == SGN_SIGNED) range[0] = -2147483648.0; + else range[0] = 0; + break; + default: + range[0] = 0.0; + break; + } + } + if(!maxfound) { + switch(type) { + case NC_CHAR: + case NC_BYTE: + range[1] = 255.0; + break; + case NC_SHORT: + if(im->sign == SGN_SIGNED) range[1] = 32767.0; + else range[1] = 65535.0; + break; + case NC_LONG: + if(im->sign == SGN_SIGNED) range[1] = 2147483647.0; + else range[1] = 4294967295.0; + break; + default: + range[1] = 1.0; + break; + } + } + + ncopts = NC_VERBOSE | NC_FATAL; + im->vdim = 1; + + /* read data bytes */ + im->data = ImageIO_alloc(im->xdim * im->ydim * im->zdim * im->vdim * + im->wdim); + + minc_icv = miicv_create(); + (void) miicv_setint( minc_icv, MI_ICV_TYPE, type ); + (void) miicv_setstr( minc_icv, MI_ICV_SIGN, sign_type ); + (void) miicv_setint( minc_icv, MI_ICV_DO_NORM, 1 ); + (void) miicv_setint( minc_icv, MI_ICV_DO_FILLVALUE, 1 ); + (void) miicv_setdbl( minc_icv, MI_ICV_VALID_MIN, range[0] ); + (void) miicv_setdbl( minc_icv, MI_ICV_VALID_MAX, range[1] ); + + (void) miicv_attach( minc_icv, fin, id ); + + if(miicv_get(minc_icv, start, count, im->data) == MI_ERROR) { + fprintf(stderr, "error while reading file\n"); + return 0; + } + (void) miicv_detach( minc_icv ); + (void) miicv_free( minc_icv ); + + ImageIO_closeImage(im); + + /* order data in ZYX */ + (void) ncdiminq(fin, dim[0], name, NULL); + if(!strcmp(name, MIzspace)) { + (void) ncdiminq(fin, dim[1], name, NULL); + /* file is ZYX */ + if(!strcmp(name, MIyspace)) { + miclose(fin); + return 1; + } + } + + (void) ncdiminq(fin, dim[0], name, NULL); + /* file is ZXY */ + if(!strcmp(name, MIzspace)) { + shift[0] = 0; + shift[1] = 2; + shift[2] = 1; + plane2 = im->xdim * im->ydim; + line = im->ydim; + } + /* file is Y first */ + else if(!strcmp(name, MIyspace)) { + shift[0] = 1; + plane2 = im->xdim * im->zdim; + (void) ncdiminq(fin, dim[1], name, NULL); + /* file is YXZ */ + if(!strcmp(name, MIxspace)) { + shift[1] = 2; + shift[2] = 0; + line = im->zdim; + } + /* file is YZX */ + else { + shift[1] = 0; + shift[2] = 2; + line = im->xdim; + } + } + /* file is X first */ + else { + shift[0] = 2; + plane2 = im->ydim * im->zdim; + (void) ncdiminq(fin, dim[1], name, NULL); + /* file is XYZ */ + if(!strcmp(name, MIyspace)) { + shift[1] = 1; + shift[2] = 0; + line = im->zdim; + } + /* file is XZY */ + else { + shift[1] = 0; + shift[2] = 1; + line = im->ydim; + } + } + + data = ImageIO_alloc(im->xdim * im->ydim * im->zdim * im->vdim * im->wdim); + plane1 = im->xdim * im->ydim; + + for(ct[0] = 0; ct[0] < im->zdim; ct[0]++) { + for(ct[1] = 0; ct[1] < im->ydim; ct[1]++) { + for(ct[2] = 0; ct[2] < im->xdim; ct[2]++) { + memcpy((unsigned char *) data + + (ct[0] * plane1 + ct[1] * im->xdim + ct[2]) * im->wdim, + (unsigned char *) im->data + + (ct[shift[0]] * plane2 + ct[shift[1]] * line + ct[shift[2]]) + * im->wdim, im->wdim); + } + } + } + + ImageIO_free(im->data); + im->data = data; + + /* close file */ + miclose(fin); + return 1; +} + + + +CGAL_INLINE_FUNCTION +int writeMincFile( const _image* im, const char *filename, + const char *sourcename, + double startx, double starty, double startz, + double stepx, double stepy, double stepz, + const double *Xcosine, const double *Ycosine, + const double *Zcosine, const double *range ) { + int i, cdfid, minc_icv, dim_vars[3], dim_ids[3], img_var_id, min_id, max_id, + src_cdfid, src_img_var, varid, n_excluded, excluded_vars[10], + src_min_id, src_max_id, src_root_id, old_att_length, same_file = 0; + long org[3] = {0, 0, 0}, count[3] = { im->zdim, im->ydim, im->xdim }; + char *dim_names[3] = { MIzspace, MIyspace, MIxspace }, *history, + *excluded_list[3] = { MIxspace, MIyspace, MIzspace }, *newname; + nc_type type, datatype; + double start[3] = { startz, starty, startx }, + vx[3] = { stepz, stepy, stepx }; + + /* if filename is the same file that sourcename, it is needed to create + a temporary file for output */ + newname = (char *) filename; + if(sourcename) { + struct stat out, org; + same_file = (stat(sourcename, &org) == 0) && (stat(filename, &out) == 0) + && (org.st_ino == out.st_ino); + if(same_file) { + newname = (char *) malloc((strlen(filename) + 10) * sizeof(char)); + for(i = strlen(filename) - 1; i > 0 && filename[i] != '/'; i--) ; + if(filename[i] == '/') { + strncpy(newname, filename, i + 1); + newname[i+1] = '\0'; + strcat(newname, "#TMP#"); + strcat(newname, filename + i + 1); + } + else + sprintf(newname, "#TMP#%s", filename); + } + } + + /* open file */ + cdfid = micreate( (char *) newname, NC_CLOBBER ); + if( cdfid == MI_ERROR ) { + fprintf(stderr, "Error: opening MINC file \"%s\".\n", filename ); + return -1; + } + + /* set word type */ + switch(im->wordKind) { + case WK_FIXED: + if(im->wdim == 1) type = NC_BYTE; + else if(im->wdim == 2) type = NC_SHORT; + else type = NC_LONG; + break; + case WK_FLOAT: + default: + if(im->wdim == 4) type = NC_FLOAT; + else type = NC_DOUBLE; + break; + } + + /* create dimensions variables */ + for(i = 0; i < 3; i++) + dim_vars[i] = ncdimdef( cdfid, dim_names[i], count[i] ); + + for(i = 0; i < 3; i++ ) { + dim_ids[i] = micreate_std_variable( cdfid, dim_names[i], NC_DOUBLE, + 0, NULL); + if( dim_ids[i] < 0 ) return -1; + (void) miattputdbl( cdfid, dim_ids[i], MIstep, vx[i]); + (void) miattputdbl( cdfid, dim_ids[i], MIstart, start[i]); + } + if(Zcosine[0] != 0.0 || Zcosine[1] != 0.0 || Zcosine[2] != 0.0) + (void) ncattput(cdfid, dim_ids[0], MIdirection_cosines, NC_DOUBLE, 3, + Zcosine); + if(Ycosine[0] != 0.0 || Ycosine[1] != 0.0 || Ycosine[2] != 0.0) + (void) ncattput(cdfid, dim_ids[1], MIdirection_cosines, NC_DOUBLE, 3, + Ycosine); + if(Xcosine[0] != 0.0 || Xcosine[1] != 0.0 || Xcosine[2] != 0.0) + (void) ncattput(cdfid, dim_ids[2], MIdirection_cosines, NC_DOUBLE, 3, + Xcosine); + + /* create image variable */ + img_var_id = micreate_std_variable( cdfid, MIimage, type, 3, dim_vars ); + (void) miattputstr( cdfid, img_var_id, MIcomplete, MI_FALSE ); + if(im->sign == SGN_SIGNED) + (void) miattputstr( cdfid, img_var_id, MIsigntype, MI_SIGNED ); + else + (void) miattputstr( cdfid, img_var_id, MIsigntype, MI_UNSIGNED ); + (void) ncattput(cdfid, img_var_id, MIvalid_range ,NC_DOUBLE, 2, range); + + min_id = micreate_std_variable(cdfid, MIimagemin, NC_DOUBLE, 0, 0 ); + max_id = micreate_std_variable(cdfid, MIimagemax, NC_DOUBLE, 0, 0 ); + + /* if the image comes from a minc file, duplicate all minc attributes */ + if(sourcename) { + if( (src_cdfid = miopen((char *) sourcename, NC_NOWRITE)) == MI_ERROR ) { + fprintf(stderr, "Error opening %s\n", sourcename ); + return -1; + } + + n_excluded = 0; + for( i = 0; i < 3; i++ ) { + if( (varid = ncvarid(src_cdfid, excluded_list[i] )) != MI_ERROR ) + excluded_vars[n_excluded++] = varid; + } + + if( (src_img_var = ncvarid(src_cdfid, MIimage )) != MI_ERROR ) + excluded_vars[n_excluded++] = src_img_var; + if( (src_max_id = ncvarid(src_cdfid, MIimagemax )) != MI_ERROR ) + excluded_vars[n_excluded++] = src_max_id; + if( (src_min_id = ncvarid(src_cdfid, MIimagemin )) != MI_ERROR ) + excluded_vars[n_excluded++] = src_min_id; + if( (src_root_id = ncvarid(src_cdfid, MIrootvariable )) != MI_ERROR ) + excluded_vars[n_excluded++] = src_root_id; + + (void) micopy_all_var_defs( src_cdfid, cdfid, n_excluded, excluded_vars ); + + if( src_img_var != MI_ERROR ) + (void) micopy_all_atts( src_cdfid, src_img_var, cdfid, img_var_id ); + if( src_root_id != MI_ERROR ) + (void) micopy_all_atts( src_cdfid, src_root_id, cdfid, + ncvarid( cdfid, MIrootvariable) ); + + ncopts = 0; + if(ncattinq(cdfid, NC_GLOBAL, MIhistory, &datatype, &old_att_length) + == MI_ERROR || datatype != NC_CHAR ) + old_att_length = 0; + + history = (char *) malloc(sizeof(char) * old_att_length); + history[0] = (char) 0; + (void) miattgetstr( cdfid, NC_GLOBAL, MIhistory, old_att_length+1, + history ); + ncopts = NC_VERBOSE | NC_FATAL; + (void) miattputstr( cdfid, NC_GLOBAL, MIhistory, history ); + free(history); + + (void) miclose( src_cdfid ); + } + + + /* write data */ + if(ncendef(cdfid) == MI_ERROR) return -1; + minc_icv = miicv_create(); + (void) miicv_setint( minc_icv, MI_ICV_TYPE, type); + (void) miicv_setstr( minc_icv, MI_ICV_SIGN, + (im->sign == SGN_SIGNED) ? MI_SIGNED : MI_UNSIGNED ); + (void) miicv_setint( minc_icv, MI_ICV_DO_NORM, 1 ); + (void) miicv_setint( minc_icv, MI_ICV_USER_NORM, 1 ); + (void) miicv_attach( minc_icv, cdfid, img_var_id ); + + if( miicv_put(minc_icv, org, count, im->data) == MI_ERROR ) + return -1; + + (void) miattputstr( cdfid, img_var_id, MIcomplete, MI_TRUE); + (void) miclose( cdfid ); + (void) miicv_free( minc_icv ); + + if(same_file) { + unlink(filename); + link(newname, filename); + unlink(newname); + free(newname); + } + + return 0; +} + + +#endif diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/pnm.cpp b/CGAL_ImageIO/src/CGAL_ImageIO/pnm.cpp index ad0c5a59fae..47e0eb2ac45 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/pnm.cpp +++ b/CGAL_ImageIO/src/CGAL_ImageIO/pnm.cpp @@ -19,612 +19,9 @@ // // Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau -#ifdef _MSC_VER -#pragma warning ( disable : 4068 4786 4081 ) -#endif - -#include -#include +#ifndef CGAL_HEADER_ONLY #include "pnm.h" -#include "fgetns.h" - - - - -/** pnm - portable anymap file format */ -/** Magic header for pgm - portable graymap file format */ -#define PGM_ASCII_MAGIC "P2" -#define PGM_MAGIC "P5" - -/** Magic header for ppm - portable pixmap file format */ -#define PPM_MAGIC "P6" - - - -#define _LGTH_STRING_ 1024 - - - -int testPpmHeader(char *magic,const char *) { - if( !strncmp(magic, PPM_MAGIC, strlen(PPM_MAGIC))) - return 0; - else - return -1; -} -int testPgmHeader(char *magic,const char *) { - if (( !strncmp(magic, PGM_MAGIC, strlen(PGM_MAGIC)))) - return 0; - else - return -1; -} -int testPgmAsciiHeader(char *magic,const char *) { - if ( !strncmp(magic, PGM_ASCII_MAGIC, strlen(PGM_ASCII_MAGIC))) - return 0; - else - return -1; -} - -PTRIMAGE_FORMAT createPgmFormat() { - PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); - - f->testImageFormat=&testPgmHeader; - f->readImageHeader=&readPgmImage; - f->writeImage=&writePgmImage; - strcpy(f->fileExtension,".pgm,.pgm.gz"); - strcpy(f->realName,"Pgm"); - return f; -} - -PTRIMAGE_FORMAT createPgmAscIIFormat() { - PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); - - f->testImageFormat=&testPgmAsciiHeader; - f->readImageHeader=&readPgmAsciiImage; - f->writeImage=&writePgmImage; - strcpy(f->fileExtension,".pgm,.pgm.gz"); - strcpy(f->realName,"Pgm-ASCII"); - return f; -} - -PTRIMAGE_FORMAT createPpmFormat() { - PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); - - f->testImageFormat=&testPpmHeader; - f->readImageHeader=&readPpmImage; - f->writeImage=&writePpmImage; - strcpy(f->fileExtension,".ppm,.ppm.gz"); - strcpy(f->realName,"Ppm"); - return f; -} - - -/* - The portable pixmap format is a lowest common denominator - color image file format. - - The definition is as follows: - - - A "magic number" for identifying the file type. A pgm - file's magic number is the two characters "P6". - - - Whitespace (blanks, TABs, CRs, LFs). - - - A width, formatted as ASCII characters in decimal. - - - Whitespace. - - - A height, again in ASCII decimal. - - Whitespace. - - - The maximum color value (Maxval), again in ASCII deci- - mal. Must be less than 65536. - - - Newline or other single whitespace character. - - - A raster of Width * Height pixels, proceeding through - the image in normal English reading order. Each pixel - is a triplet of red, green, and blue samples, in that - order. Each sample is represented in pure binary by - either 1 or 2 bytes. If the Maxval is less than 256, it - is 1 byte. Otherwise, it is 2 bytes. The most signifi- - cant byte is first. - - - In the raster, the sample values are proportional to the - intensity of the CIE Rec. 709 red, green, and blue in - the pixel. A value of Maxval for all three samples rep- - resents CIE D65 white and the most intense color in the - color universe of which the image is part (the color - universe is all the colors in all images to which this - image might be compared). - - - Characters from a "#" to the next end-of-line, before - the maxval line, are comments and are ignored. - -*/ -int readPpmImage(const char *name,_image *im) -{ - char string[256]; - int x=0, y=0; - int max=0; - - fgetns( string, 255, im ); - if ( strncmp(string, PPM_MAGIC, strlen(PPM_MAGIC) ) ) { - fprintf( stderr, "readPpmImage: bad magic string in \'%s\'\n", name ); - return( -1 ); - } - - do { - fgetns( string, 255, im ); - - if ( string[0] != '#' ) { - if ( x == 0 && y == 0 ) { - sscanf( string, "%d %d", &x, &y ); - } - else if ( max == 0 ) { - sscanf( string, "%d", &max ); - } - } - } while ( max == 0 ); - - - im->xdim = static_cast(x); - im->ydim = static_cast(y); - im->zdim = 1; - im->vdim = 3; - - im->wordKind = WK_FIXED; - im->sign = SGN_UNSIGNED; - - if ( max < 256 ) im->wdim = 1; - else if ( max < 65536 ) { - im->wdim = 2; - fprintf( stderr, "readPpmImage: Warning, data of \'%s\' may have to be swapped\n", name ); - } - else { - fprintf( stderr, "readPpmImage: max value too large (%d) in \'%s\'\n", max, name ); - return( -1 ); - } - im->data = ImageIO_alloc( x*y*3 ); - - ImageIO_read( im, im->data, x*y*3 ); - - return 1; -} - - -int writePpmImage( char *name,_image *im ) -{ - std::ostringstream string; - int max; - unsigned int i; - - if ( im->xdim <= 0 || im->ydim <= 0 || im->zdim != 1 || im->vdim != 3 ) { - fprintf( stderr, "writePpmImage: bad dimensions, unable to write '%s'\n", name ); - return -1; - } - if ( im->wordKind != WK_FIXED || im->sign != SGN_UNSIGNED - || ( im->wdim != 1 && im->wdim != 2 ) ) { - fprintf( stderr, "writePpmImage: bad type, unable to write '%s'\n", name ); - return -1; - } - - _openWriteImage( im, name ); - - if(!im->fd) { - fprintf(stderr, "writeInrimage: error: unable to open file \'%s\'\n", name ); - return ImageIO_OPENING; - } - - string << PPM_MAGIC << "\n"; - string << "# CREATOR: pnm.c $Revision$ $Date$\n"; - string << im->xdim << " " << im->ydim << "\n"; - - max = 0; - switch ( im->wdim ) { - case 1 : - { - unsigned char *buf = (unsigned char *)im->data; - for ( i=0; ixdim*im->ydim*3; i++, buf++ ) - if ( max < *buf ) max = *buf; - } - break; - case 2 : - { - unsigned short *buf = (unsigned short *)im->data; - for ( i=0; ixdim*im->ydim*3; i++, buf++ ) - if ( max < *buf ) max = *buf; - } - break; - } - - if ( max == 0 ) max = 1; - string << max << "\n"; - ImageIO_write(im, string.str().data(), string.str().length()); - - if ( im->wdim == 1 || ( im->wdim == 2 && max > 255 ) ) { - ImageIO_write( im, im->data, im->xdim*im->ydim*3*im->wdim ); - } - else { - /* 2 octets, but max <= 255 - has to be converted on one octet - */ - unsigned short *buf = (unsigned short *)im->data; - unsigned char *tmp = (unsigned char *)ImageIO_alloc( im->xdim*im->ydim*3 ); - if ( tmp == NULL ) { - fprintf( stderr, "writePpmImage: unable to allocate auxiliary buffer\n" ); - return -1; - } - for ( i=0; ixdim*im->ydim*3; i++, buf++ ) - tmp[i] = (unsigned char)*buf; - ImageIO_write( im, tmp, im->xdim*im->ydim*3 ); - ImageIO_free( tmp ); - } - ImageIO_close( im ); - im->openMode = OM_CLOSE; - return 1; -} - - - -/* - The portable graymap format is a lowest common denominator - grayscale file format. The definition is as follows: - - - A "magic number" for identifying the file type. A pgm - file's magic number is the two characters "P2". - - - Whitespace (blanks, TABs, CRs, LFs). - - - A width, formatted as ASCII characters in decimal. - - - Whitespace. - - A height, again in ASCII decimal. - - - Whitespace. - - - The maximum gray value (Maxval), again in ASCII decimal. - Must be less than 65536. - - - Newline or other single whitespace character. - - - A raster of Width * Height gray values, proceeding - through the image in normal English reading order. Each - gray value is a number from 0 through Maxval, with 0 - being black and Maxval being white. Each gray value is - represented in pure binary by either 1 or 2 bytes. If - the Maxval is less than 256, it is 1 byte. Otherwise, - it is 2 bytes. The most significant byte is first. - - - Characters from a "#" to the next end-of-line, before - the maxval line, are comments and are ignored. -*/ -int readPgmAsciiImage(const char *name,_image *im) -{ - char string[256]; - int x=0, y=0; - int max=0; - - int n; - char *tmp; - int iv; - - fgetns( string, 255, im ); - if ( strncmp(string, PGM_ASCII_MAGIC, strlen(PGM_ASCII_MAGIC) ) ) { - fprintf( stderr, "readAsciiPgmImage: bad magic string in \'%s\'\n", name ); - return( -1 ); - } - - do { - fgetns( string, 255, im ); - - if ( string[0] != '#' ) { - if ( x == 0 && y == 0 ) { - sscanf( string, "%d %d", &x, &y ); - } - else if ( max == 0 ) { - sscanf( string, "%d", &max ); - } - } - } while ( max == 0 ); - - im->xdim = x; - im->ydim = y; - im->zdim = 1; - im->vdim = 1; - - im->wordKind = WK_FIXED; - im->sign = SGN_UNSIGNED; - - if ( max < 256 ) im->wdim = 1; - else if ( max < 65536 ) { - im->wdim = 2; - } - else { - fprintf( stderr, "readAsciiPgmImage: max value too large (%d) in \'%s\'\n", max, name ); - return( -1 ); - } - im->data = ImageIO_alloc( x*y ); - - n=0; - - while( fgetns( string, 255, im ) != 0 && n < x*y ) { - tmp = string; - while ( *tmp != '\n' && *tmp != '\0' && *tmp != EOF && n < x*y ) { - /* skip trailing whitespace - */ - while ( *tmp == ' ' || *tmp == '\t' ) - tmp++; - if ( *tmp == '\0' || *tmp == '\n' || *tmp == EOF ) - continue; - - /* read a number - */ - switch ( im->wordKind ) { - case WK_FIXED : - if ( sscanf( tmp, "%d", &iv ) != 1 ) { - fprintf( stderr, "readAsciiPgmImage: error in reading ascii data\n" ); - ImageIO_free( im->data ); im->data = NULL; - return 0; - } - break; - default : - ImageIO_free( im->data ); im->data = NULL; - return 0; - } - - if ( im->wdim == 1 ) { - unsigned char *buf = (unsigned char *)im->data; - buf += n; - if ( iv < 0 ) *buf = (unsigned char)0; - else if ( iv > 255 ) *buf = (unsigned char)255; - else *buf = (unsigned char)iv; - n ++; - } - else if ( im->wdim == 2 ) { - unsigned short int *buf = (unsigned short int *)im->data; - buf += n; - if ( iv < 0 ) *buf = (unsigned short int)0; - else if ( iv > 65535 ) *buf = (unsigned short int)65535; - else *buf = (unsigned short int)iv; - n ++; - } - else { - fprintf( stderr, "readAsciiPgmImage: word im not handled\n" ); - ImageIO_free( im->data ); im->data = NULL; - return 0; - } - - /* skip a number - */ - while ( (*tmp >= '0' && *tmp <= '9') || *tmp == '.' || *tmp == '-' ) - tmp++; - } - } - - - return 1; -} - - - - -/* - The portable graymap format is a lowest common denominator - grayscale file format. The definition is as follows: - - - A "magic number" for identifying the file type. A pgm - file's magic number is the two characters "P5". - - - Whitespace (blanks, TABs, CRs, LFs). - - - A width, formatted as ASCII characters in decimal. - - - Whitespace. - - A height, again in ASCII decimal. - - - Whitespace. - - - The maximum gray value (Maxval), again in ASCII decimal. - Must be less than 65536. - - - Newline or other single whitespace character. - - - A raster of Width * Height gray values, proceeding - through the image in normal English reading order. Each - gray value is a number from 0 through Maxval, with 0 - being black and Maxval being white. Each gray value is - represented in pure binary by either 1 or 2 bytes. If - the Maxval is less than 256, it is 1 byte. Otherwise, - it is 2 bytes. The most significant byte is first. - - - Characters from a "#" to the next end-of-line, before - the maxval line, are comments and are ignored. -*/ -int readPgmImage(const char *name,_image *im) -{ - - char string[256]; - int x=0, y=0; - int max=0; - - fgetns( string, 255, im ); - if ( strncmp(string, PGM_MAGIC, strlen(PGM_MAGIC) ) ) { - fprintf( stderr, "readPgmImage: bad magic string in \'%s\'\n", name ); - return( -1 ); - } - - do { - fgetns( string, 255, im ); - - if ( string[0] != '#' ) { - if ( x == 0 && y == 0 ) { - sscanf( string, "%d %d", &x, &y ); - } - else if ( max == 0 ) { - sscanf( string, "%d", &max ); - } - } - } while ( max == 0 ); - - - im->xdim = x; - im->ydim = y; - im->zdim = 1; - im->vdim = 1; - - im->wordKind = WK_FIXED; - im->sign = SGN_UNSIGNED; - - if ( max < 256 ) im->wdim = 1; - else if ( max < 65536 ) { - im->wdim = 2; - fprintf( stderr, "readPgmImage: Warning, data of \'%s\' may have to be swapped\n", name ); - } - else { - fprintf( stderr, "readPgmImage: max value too large (%d) in \'%s\'\n", max, name ); - return( -1 ); - } - im->data = ImageIO_alloc( x*y ); - - ImageIO_read( im, im->data, x*y ); - - return 1; -} - - -int writePgmImage(char *name,_image *im ) -{ - char string[256]; - int max; - unsigned int i; - - if ( im->xdim <= 0 || im->ydim <= 0 || im->zdim != 1 || im->vdim != 1 ) { - fprintf( stderr, "writePgmImage: bad dimensions, unable to write '%s'\n", name ); - return -1; - } - if ( im->wordKind != WK_FIXED || im->sign != SGN_UNSIGNED - || ( im->wdim != 1 && im->wdim != 2 ) ) { - fprintf( stderr, "writePgmImage: bad type, unable to write '%s'\n", name ); - return -1; - } - - if ( 0 ) - im->dataMode = DM_ASCII; - - _openWriteImage( im, name ); - - if(!im->fd) { - fprintf(stderr, "writePgmImage: error: unable to open file \'%s\'\n", name ); - return ImageIO_OPENING; - } - - if ( im->dataMode == DM_ASCII ) - sprintf( string, "%s\n", PGM_ASCII_MAGIC ); - else - sprintf( string, "%s\n", PGM_MAGIC ); - - ImageIO_write( im, string, strlen( string ) ); - sprintf( string, "# CREATOR: pnm.c $Revision$ $Date$\n" ); - ImageIO_write( im, string, strlen( string ) ); - sprintf( string, "%zu %zu\n", im->xdim, im->ydim ); - ImageIO_write( im, string, strlen( string ) ); - max = 0; - switch ( im->wdim ) { - case 1 : - { - unsigned char *buf = (unsigned char *)im->data; - for ( i=0; ixdim*im->ydim; i++, buf++ ) - if ( max < *buf ) max = *buf; - } - break; - case 2 : - { - unsigned short *buf = (unsigned short *)im->data; - for ( i=0; ixdim*im->ydim; i++, buf++ ) - if ( max < *buf ) max = *buf; - } - break; - } - /* max == 0 causes problems for xv */ - if ( max == 0 ) max = 1; - sprintf( string, "%d\n", max ); - ImageIO_write( im, string, strlen( string ) ); - - if ( im->dataMode == DM_ASCII ) { - int i, j, n, size; - char *str = (char*)ImageIO_alloc( _LGTH_STRING_+1 ); - size = im->xdim * im->ydim * im->zdim * im->vdim; - n = ( im->xdim < 16 ) ? im->xdim : 16; - i = 0; - switch( im->wdim ) { - default : - /* can not occur */ - fprintf( stderr, "writePgmImage: bad type, unable to write '%s'\n", name ); - ImageIO_close( im ); - im->openMode = OM_CLOSE; - return -1; - case 1 : - { - unsigned char *theBuf = ( unsigned char * )im->data; - do { - memset( str, 0, _LGTH_STRING_ ); - for ( j=0; jdata; - do { - memset( str, 0, _LGTH_STRING_ ); - for ( j=0; jwdim == 1 || ( im->wdim == 2 && max > 255 ) ) { - ImageIO_write( im, im->data, im->xdim*im->ydim*im->wdim ); - } - else { - /* 2 octets, but max <= 255 - has to be converted on one octet - */ - unsigned short *buf = (unsigned short *)im->data; - unsigned char *tmp = (unsigned char *)ImageIO_alloc( im->xdim*im->ydim ); - if ( tmp == NULL ) { - fprintf( stderr, "writePgmImage: unable to allocate auxiliary buffer\n" ); - return -1; - } - for ( i=0; ixdim*im->ydim; i++, buf++ ) - tmp[i] = (unsigned char)*buf; - ImageIO_write( im, tmp, im->xdim*im->ydim ); - ImageIO_free( tmp ); - } - } - - ImageIO_close( im ); - im->openMode = OM_CLOSE; - return 1; -} - - +#include "pnm_impl.h" +#endif // CGAL_HEADER_ONLY diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/pnm.h b/CGAL_ImageIO/src/CGAL_ImageIO/pnm.h index 55ee237f439..6a5d379dd4a 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/pnm.h +++ b/CGAL_ImageIO/src/CGAL_ImageIO/pnm.h @@ -39,5 +39,8 @@ PTRIMAGE_FORMAT createPgmFormat(); PTRIMAGE_FORMAT createPgmAscIIFormat(); PTRIMAGE_FORMAT createPpmFormat(); +#ifdef CGAL_HEADER_ONLY +#include "pnm_impl.h" +#endif // CGAL_HEADER_ONLY #endif diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/pnm_impl.h b/CGAL_ImageIO/src/CGAL_ImageIO/pnm_impl.h new file mode 100644 index 00000000000..58c5a98ca34 --- /dev/null +++ b/CGAL_ImageIO/src/CGAL_ImageIO/pnm_impl.h @@ -0,0 +1,643 @@ +// Copyright (c) 2005-2008 ASCLEPIOS Project, INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of the ImageIO Library, and as been adapted for +// CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the +// GNU Lesser General Public License as published by the Free Software Foundation; +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#ifdef _MSC_VER +#pragma warning ( disable : 4068 4786 4081 ) +#endif + +#include +#include + +#include "fgetns.h" + + + + +/** pnm - portable anymap file format */ +/** Magic header for pgm - portable graymap file format */ +#define PGM_ASCII_MAGIC "P2" +#define PGM_MAGIC "P5" + +/** Magic header for ppm - portable pixmap file format */ +#define PPM_MAGIC "P6" + + + +#define _LGTH_STRING_ 1024 + + +CGAL_INLINE_FUNCTION +int testPpmHeader(char *magic,const char *) { + if( !strncmp(magic, PPM_MAGIC, strlen(PPM_MAGIC))) + return 0; + else + return -1; +} +CGAL_INLINE_FUNCTION +int testPgmHeader(char *magic,const char *) { + if (( !strncmp(magic, PGM_MAGIC, strlen(PGM_MAGIC)))) + return 0; + else + return -1; +} +CGAL_INLINE_FUNCTION +int testPgmAsciiHeader(char *magic,const char *) { + if ( !strncmp(magic, PGM_ASCII_MAGIC, strlen(PGM_ASCII_MAGIC))) + return 0; + else + return -1; +} + +CGAL_INLINE_FUNCTION +PTRIMAGE_FORMAT createPgmFormat() { + PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); + + f->testImageFormat=&testPgmHeader; + f->readImageHeader=&readPgmImage; + f->writeImage=&writePgmImage; + strcpy(f->fileExtension,".pgm,.pgm.gz"); + strcpy(f->realName,"Pgm"); + return f; +} + +CGAL_INLINE_FUNCTION +PTRIMAGE_FORMAT createPgmAscIIFormat() { + PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); + + f->testImageFormat=&testPgmAsciiHeader; + f->readImageHeader=&readPgmAsciiImage; + f->writeImage=&writePgmImage; + strcpy(f->fileExtension,".pgm,.pgm.gz"); + strcpy(f->realName,"Pgm-ASCII"); + return f; +} + +CGAL_INLINE_FUNCTION +PTRIMAGE_FORMAT createPpmFormat() { + PTRIMAGE_FORMAT f=(PTRIMAGE_FORMAT) ImageIO_alloc(sizeof(IMAGE_FORMAT)); + + f->testImageFormat=&testPpmHeader; + f->readImageHeader=&readPpmImage; + f->writeImage=&writePpmImage; + strcpy(f->fileExtension,".ppm,.ppm.gz"); + strcpy(f->realName,"Ppm"); + return f; +} + + +/* + The portable pixmap format is a lowest common denominator + color image file format. + + The definition is as follows: + + - A "magic number" for identifying the file type. A pgm + file's magic number is the two characters "P6". + + - Whitespace (blanks, TABs, CRs, LFs). + + - A width, formatted as ASCII characters in decimal. + + - Whitespace. + + - A height, again in ASCII decimal. + - Whitespace. + + - The maximum color value (Maxval), again in ASCII deci- + mal. Must be less than 65536. + + - Newline or other single whitespace character. + + - A raster of Width * Height pixels, proceeding through + the image in normal English reading order. Each pixel + is a triplet of red, green, and blue samples, in that + order. Each sample is represented in pure binary by + either 1 or 2 bytes. If the Maxval is less than 256, it + is 1 byte. Otherwise, it is 2 bytes. The most signifi- + cant byte is first. + + - In the raster, the sample values are proportional to the + intensity of the CIE Rec. 709 red, green, and blue in + the pixel. A value of Maxval for all three samples rep- + resents CIE D65 white and the most intense color in the + color universe of which the image is part (the color + universe is all the colors in all images to which this + image might be compared). + + - Characters from a "#" to the next end-of-line, before + the maxval line, are comments and are ignored. + +*/ +CGAL_INLINE_FUNCTION +int readPpmImage(const char *name,_image *im) +{ + char string[256]; + int x=0, y=0; + int max=0; + + fgetns( string, 255, im ); + if ( strncmp(string, PPM_MAGIC, strlen(PPM_MAGIC) ) ) { + fprintf( stderr, "readPpmImage: bad magic string in \'%s\'\n", name ); + return( -1 ); + } + + do { + fgetns( string, 255, im ); + + if ( string[0] != '#' ) { + if ( x == 0 && y == 0 ) { + sscanf( string, "%d %d", &x, &y ); + } + else if ( max == 0 ) { + sscanf( string, "%d", &max ); + } + } + } while ( max == 0 ); + + + im->xdim = static_cast(x); + im->ydim = static_cast(y); + im->zdim = 1; + im->vdim = 3; + + im->wordKind = WK_FIXED; + im->sign = SGN_UNSIGNED; + + if ( max < 256 ) im->wdim = 1; + else if ( max < 65536 ) { + im->wdim = 2; + fprintf( stderr, "readPpmImage: Warning, data of \'%s\' may have to be swapped\n", name ); + } + else { + fprintf( stderr, "readPpmImage: max value too large (%d) in \'%s\'\n", max, name ); + return( -1 ); + } + im->data = ImageIO_alloc( x*y*3 ); + + ImageIO_read( im, im->data, x*y*3 ); + + return 1; +} + +CGAL_INLINE_FUNCTION +int writePpmImage( char *name,_image *im ) +{ + std::ostringstream string; + int max; + unsigned int i; + + if ( im->xdim <= 0 || im->ydim <= 0 || im->zdim != 1 || im->vdim != 3 ) { + fprintf( stderr, "writePpmImage: bad dimensions, unable to write '%s'\n", name ); + return -1; + } + if ( im->wordKind != WK_FIXED || im->sign != SGN_UNSIGNED + || ( im->wdim != 1 && im->wdim != 2 ) ) { + fprintf( stderr, "writePpmImage: bad type, unable to write '%s'\n", name ); + return -1; + } + + _openWriteImage( im, name ); + + if(!im->fd) { + fprintf(stderr, "writeInrimage: error: unable to open file \'%s\'\n", name ); + return ImageIO_OPENING; + } + + string << PPM_MAGIC << "\n"; + string << "# CREATOR: pnm.c $Revision$ $Date$\n"; + string << im->xdim << " " << im->ydim << "\n"; + + max = 0; + switch ( im->wdim ) { + case 1 : + { + unsigned char *buf = (unsigned char *)im->data; + for ( i=0; ixdim*im->ydim*3; i++, buf++ ) + if ( max < *buf ) max = *buf; + } + break; + case 2 : + { + unsigned short *buf = (unsigned short *)im->data; + for ( i=0; ixdim*im->ydim*3; i++, buf++ ) + if ( max < *buf ) max = *buf; + } + break; + } + + if ( max == 0 ) max = 1; + string << max << "\n"; + ImageIO_write(im, string.str().data(), string.str().length()); + + if ( im->wdim == 1 || ( im->wdim == 2 && max > 255 ) ) { + ImageIO_write( im, im->data, im->xdim*im->ydim*3*im->wdim ); + } + else { + /* 2 octets, but max <= 255 + has to be converted on one octet + */ + unsigned short *buf = (unsigned short *)im->data; + unsigned char *tmp = (unsigned char *)ImageIO_alloc( im->xdim*im->ydim*3 ); + if ( tmp == NULL ) { + fprintf( stderr, "writePpmImage: unable to allocate auxiliary buffer\n" ); + return -1; + } + for ( i=0; ixdim*im->ydim*3; i++, buf++ ) + tmp[i] = (unsigned char)*buf; + ImageIO_write( im, tmp, im->xdim*im->ydim*3 ); + ImageIO_free( tmp ); + } + ImageIO_close( im ); + im->openMode = OM_CLOSE; + return 1; +} + + + +/* + The portable graymap format is a lowest common denominator + grayscale file format. The definition is as follows: + + - A "magic number" for identifying the file type. A pgm + file's magic number is the two characters "P2". + + - Whitespace (blanks, TABs, CRs, LFs). + + - A width, formatted as ASCII characters in decimal. + + - Whitespace. + - A height, again in ASCII decimal. + + - Whitespace. + + - The maximum gray value (Maxval), again in ASCII decimal. + Must be less than 65536. + + - Newline or other single whitespace character. + + - A raster of Width * Height gray values, proceeding + through the image in normal English reading order. Each + gray value is a number from 0 through Maxval, with 0 + being black and Maxval being white. Each gray value is + represented in pure binary by either 1 or 2 bytes. If + the Maxval is less than 256, it is 1 byte. Otherwise, + it is 2 bytes. The most significant byte is first. + + - Characters from a "#" to the next end-of-line, before + the maxval line, are comments and are ignored. +*/ +CGAL_INLINE_FUNCTION +int readPgmAsciiImage(const char *name,_image *im) +{ + char string[256]; + int x=0, y=0; + int max=0; + + int n; + char *tmp; + int iv; + + fgetns( string, 255, im ); + if ( strncmp(string, PGM_ASCII_MAGIC, strlen(PGM_ASCII_MAGIC) ) ) { + fprintf( stderr, "readAsciiPgmImage: bad magic string in \'%s\'\n", name ); + return( -1 ); + } + + do { + fgetns( string, 255, im ); + + if ( string[0] != '#' ) { + if ( x == 0 && y == 0 ) { + sscanf( string, "%d %d", &x, &y ); + } + else if ( max == 0 ) { + sscanf( string, "%d", &max ); + } + } + } while ( max == 0 ); + + im->xdim = x; + im->ydim = y; + im->zdim = 1; + im->vdim = 1; + + im->wordKind = WK_FIXED; + im->sign = SGN_UNSIGNED; + + if ( max < 256 ) im->wdim = 1; + else if ( max < 65536 ) { + im->wdim = 2; + } + else { + fprintf( stderr, "readAsciiPgmImage: max value too large (%d) in \'%s\'\n", max, name ); + return( -1 ); + } + im->data = ImageIO_alloc( x*y ); + + n=0; + + while( fgetns( string, 255, im ) != 0 && n < x*y ) { + tmp = string; + while ( *tmp != '\n' && *tmp != '\0' && *tmp != EOF && n < x*y ) { + /* skip trailing whitespace + */ + while ( *tmp == ' ' || *tmp == '\t' ) + tmp++; + if ( *tmp == '\0' || *tmp == '\n' || *tmp == EOF ) + continue; + + /* read a number + */ + switch ( im->wordKind ) { + case WK_FIXED : + if ( sscanf( tmp, "%d", &iv ) != 1 ) { + fprintf( stderr, "readAsciiPgmImage: error in reading ascii data\n" ); + ImageIO_free( im->data ); im->data = NULL; + return 0; + } + break; + default : + ImageIO_free( im->data ); im->data = NULL; + return 0; + } + + if ( im->wdim == 1 ) { + unsigned char *buf = (unsigned char *)im->data; + buf += n; + if ( iv < 0 ) *buf = (unsigned char)0; + else if ( iv > 255 ) *buf = (unsigned char)255; + else *buf = (unsigned char)iv; + n ++; + } + else if ( im->wdim == 2 ) { + unsigned short int *buf = (unsigned short int *)im->data; + buf += n; + if ( iv < 0 ) *buf = (unsigned short int)0; + else if ( iv > 65535 ) *buf = (unsigned short int)65535; + else *buf = (unsigned short int)iv; + n ++; + } + else { + fprintf( stderr, "readAsciiPgmImage: word im not handled\n" ); + ImageIO_free( im->data ); im->data = NULL; + return 0; + } + + /* skip a number + */ + while ( (*tmp >= '0' && *tmp <= '9') || *tmp == '.' || *tmp == '-' ) + tmp++; + } + } + + + return 1; +} + + + + +/* + The portable graymap format is a lowest common denominator + grayscale file format. The definition is as follows: + + - A "magic number" for identifying the file type. A pgm + file's magic number is the two characters "P5". + + - Whitespace (blanks, TABs, CRs, LFs). + + - A width, formatted as ASCII characters in decimal. + + - Whitespace. + - A height, again in ASCII decimal. + + - Whitespace. + + - The maximum gray value (Maxval), again in ASCII decimal. + Must be less than 65536. + + - Newline or other single whitespace character. + + - A raster of Width * Height gray values, proceeding + through the image in normal English reading order. Each + gray value is a number from 0 through Maxval, with 0 + being black and Maxval being white. Each gray value is + represented in pure binary by either 1 or 2 bytes. If + the Maxval is less than 256, it is 1 byte. Otherwise, + it is 2 bytes. The most significant byte is first. + + - Characters from a "#" to the next end-of-line, before + the maxval line, are comments and are ignored. +*/ +CGAL_INLINE_FUNCTION +int readPgmImage(const char *name,_image *im) +{ + + char string[256]; + int x=0, y=0; + int max=0; + + fgetns( string, 255, im ); + if ( strncmp(string, PGM_MAGIC, strlen(PGM_MAGIC) ) ) { + fprintf( stderr, "readPgmImage: bad magic string in \'%s\'\n", name ); + return( -1 ); + } + + do { + fgetns( string, 255, im ); + + if ( string[0] != '#' ) { + if ( x == 0 && y == 0 ) { + sscanf( string, "%d %d", &x, &y ); + } + else if ( max == 0 ) { + sscanf( string, "%d", &max ); + } + } + } while ( max == 0 ); + + + im->xdim = x; + im->ydim = y; + im->zdim = 1; + im->vdim = 1; + + im->wordKind = WK_FIXED; + im->sign = SGN_UNSIGNED; + + if ( max < 256 ) im->wdim = 1; + else if ( max < 65536 ) { + im->wdim = 2; + fprintf( stderr, "readPgmImage: Warning, data of \'%s\' may have to be swapped\n", name ); + } + else { + fprintf( stderr, "readPgmImage: max value too large (%d) in \'%s\'\n", max, name ); + return( -1 ); + } + im->data = ImageIO_alloc( x*y ); + + ImageIO_read( im, im->data, x*y ); + + return 1; +} + +CGAL_INLINE_FUNCTION +int writePgmImage(char *name,_image *im ) +{ + char string[256]; + int max; + unsigned int i; + + if ( im->xdim <= 0 || im->ydim <= 0 || im->zdim != 1 || im->vdim != 1 ) { + fprintf( stderr, "writePgmImage: bad dimensions, unable to write '%s'\n", name ); + return -1; + } + if ( im->wordKind != WK_FIXED || im->sign != SGN_UNSIGNED + || ( im->wdim != 1 && im->wdim != 2 ) ) { + fprintf( stderr, "writePgmImage: bad type, unable to write '%s'\n", name ); + return -1; + } + + if ( 0 ) + im->dataMode = DM_ASCII; + + _openWriteImage( im, name ); + + if(!im->fd) { + fprintf(stderr, "writePgmImage: error: unable to open file \'%s\'\n", name ); + return ImageIO_OPENING; + } + + if ( im->dataMode == DM_ASCII ) + sprintf( string, "%s\n", PGM_ASCII_MAGIC ); + else + sprintf( string, "%s\n", PGM_MAGIC ); + + ImageIO_write( im, string, strlen( string ) ); + sprintf( string, "# CREATOR: pnm.c $Revision$ $Date$\n" ); + ImageIO_write( im, string, strlen( string ) ); + sprintf( string, "%zu %zu\n", im->xdim, im->ydim ); + ImageIO_write( im, string, strlen( string ) ); + max = 0; + switch ( im->wdim ) { + case 1 : + { + unsigned char *buf = (unsigned char *)im->data; + for ( i=0; ixdim*im->ydim; i++, buf++ ) + if ( max < *buf ) max = *buf; + } + break; + case 2 : + { + unsigned short *buf = (unsigned short *)im->data; + for ( i=0; ixdim*im->ydim; i++, buf++ ) + if ( max < *buf ) max = *buf; + } + break; + } + /* max == 0 causes problems for xv */ + if ( max == 0 ) max = 1; + sprintf( string, "%d\n", max ); + ImageIO_write( im, string, strlen( string ) ); + + if ( im->dataMode == DM_ASCII ) { + int i, j, n, size; + char *str = (char*)ImageIO_alloc( _LGTH_STRING_+1 ); + size = im->xdim * im->ydim * im->zdim * im->vdim; + n = ( im->xdim < 16 ) ? im->xdim : 16; + i = 0; + switch( im->wdim ) { + default : + /* can not occur */ + fprintf( stderr, "writePgmImage: bad type, unable to write '%s'\n", name ); + ImageIO_close( im ); + im->openMode = OM_CLOSE; + return -1; + case 1 : + { + unsigned char *theBuf = ( unsigned char * )im->data; + do { + memset( str, 0, _LGTH_STRING_ ); + for ( j=0; jdata; + do { + memset( str, 0, _LGTH_STRING_ ); + for ( j=0; jwdim == 1 || ( im->wdim == 2 && max > 255 ) ) { + ImageIO_write( im, im->data, im->xdim*im->ydim*im->wdim ); + } + else { + /* 2 octets, but max <= 255 + has to be converted on one octet + */ + unsigned short *buf = (unsigned short *)im->data; + unsigned char *tmp = (unsigned char *)ImageIO_alloc( im->xdim*im->ydim ); + if ( tmp == NULL ) { + fprintf( stderr, "writePgmImage: unable to allocate auxiliary buffer\n" ); + return -1; + } + for ( i=0; ixdim*im->ydim; i++, buf++ ) + tmp[i] = (unsigned char)*buf; + ImageIO_write( im, tmp, im->xdim*im->ydim ); + ImageIO_free( tmp ); + } + } + + ImageIO_close( im ); + im->openMode = OM_CLOSE; + return 1; +} + + + diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/recbuffer.cpp b/CGAL_ImageIO/src/CGAL_ImageIO/recbuffer.cpp index 64f5f5edf9f..e5d6f002a90 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/recbuffer.cpp +++ b/CGAL_ImageIO/src/CGAL_ImageIO/recbuffer.cpp @@ -19,1719 +19,9 @@ // // Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau -/************************************************************************* - * recbuffer.c - tools for recursive filtering of 3D and 2D image buffers - * - * $Id$ - * - * Copyright©INRIA 1999 - * - * DESCRIPTION: - * - * recursive filtering of a buffer (a [1,2,3]D array) - * according that the filtering is separable - * - * - * - * AUTHOR: - * Gregoire Malandain (greg@sophia.inria.fr) - * - * CREATION DATE: - * June, 9 1998 - * - * Copyright Gregoire Malandain, INRIA - * - * ADDITIONS, CHANGES - * - * * Jul 6 1999 (Gregoire Malandain) - * a bug in RecursiveFilterOnBuffer (*&%^@$^ cut and paste) - * - */ -#include -#include -#include +#ifndef CGAL_HEADER_ONLY - - -#include "convert.h" #include "recbuffer.h" +#include "recbuffer_impl.h" -static int _VERBOSE_ = 0; - -#define EXIT_ON_FAILURE 0 -#define EXIT_ON_SUCCESS 1 - - - - - - - - - - -/* - * - * Gradient modulus - * - * - */ - -int GradientModulus( void *bufferIn, - bufferType typeIn, - void *bufferOut, - bufferType typeOut, - int *bufferDims, - int *borderLengths, - float *filterCoefs, - recursiveFilterType filterType ) -{ - const char *proc = "GradientModulus"; - float *auxBuf = NULL; - float *tmpBuf = NULL, *grdBuf = NULL; - int sizeAuxBuf = 0; - derivativeOrder derivatives[3]; - int i; - - - sizeAuxBuf = bufferDims[0] * bufferDims[1] * bufferDims[2]; - if ( typeOut != CGAL_FLOAT || bufferIn == bufferOut ) - sizeAuxBuf *= 2; - - - /* allocation des buffers de calcul - */ - auxBuf = (float*)malloc( sizeAuxBuf * sizeof(float) ); - if ( auxBuf == NULL ) { - if ( _VERBOSE_ > 0 ) - fprintf( stderr, "%s: unable to allocate auxiliary buffer\n", proc ); - return( EXIT_ON_FAILURE ); - } - tmpBuf = auxBuf; - if ( typeOut != CGAL_FLOAT || bufferIn == bufferOut ) { - grdBuf = tmpBuf; - grdBuf += bufferDims[0] * bufferDims[1] * bufferDims[2]; - } else { - grdBuf = (float*)bufferOut; - } - - /* cas 2D - */ - if ( bufferDims[2] == 1 ) { - - derivatives[0] = DERIVATIVE_1; - derivatives[1] = DERIVATIVE_0; - derivatives[2] = NODERIVATIVE; - if ( RecursiveFilterOnBuffer( bufferIn, typeIn, (void*)grdBuf, CGAL_FLOAT, - bufferDims, borderLengths, derivatives, - filterCoefs, filterType ) != EXIT_ON_SUCCESS ) { - if ( _VERBOSE_ ) - fprintf( stderr, "%s: unable to compute X derivative (2D)\n", proc ); - free( auxBuf ); - return( EXIT_ON_FAILURE ); - } - - derivatives[0] = DERIVATIVE_0; - derivatives[1] = DERIVATIVE_1; - derivatives[2] = NODERIVATIVE; - if ( RecursiveFilterOnBuffer( bufferIn, typeIn, (void*)tmpBuf, CGAL_FLOAT, - bufferDims, borderLengths, derivatives, - filterCoefs, filterType ) != EXIT_ON_SUCCESS ) { - if ( _VERBOSE_ ) - fprintf( stderr, "%s: unable to compute Y derivative (2D)\n", proc ); - free( auxBuf ); - return( EXIT_ON_FAILURE ); - } - - sizeAuxBuf = bufferDims[0] * bufferDims[1] * bufferDims[2]; - for ( i = 0; i < sizeAuxBuf; i++ ) - grdBuf[i] = (float)sqrt( grdBuf[i]*grdBuf[i] + tmpBuf[i]*tmpBuf[i] ); - - } else { - - derivatives[0] = NODERIVATIVE; - derivatives[1] = NODERIVATIVE; - derivatives[2] = DERIVATIVE_0; - if ( RecursiveFilterOnBuffer( bufferIn, typeIn, (void*)tmpBuf, CGAL_FLOAT, - bufferDims, borderLengths, derivatives, - filterCoefs, filterType ) != EXIT_ON_SUCCESS ) { - if ( _VERBOSE_ ) - fprintf( stderr, "%s: unable to compute Z smoothing (3D)\n", proc ); - free( auxBuf ); - return( EXIT_ON_FAILURE ); - } - - derivatives[0] = DERIVATIVE_1; - derivatives[1] = DERIVATIVE_0; - derivatives[2] = NODERIVATIVE; - if ( RecursiveFilterOnBuffer( (void*)tmpBuf, CGAL_FLOAT, (void*)grdBuf, CGAL_FLOAT, - bufferDims, borderLengths, derivatives, - filterCoefs, filterType ) != EXIT_ON_SUCCESS ) { - if ( _VERBOSE_ ) - fprintf( stderr, "%s: unable to compute X derivative (3D)\n", proc ); - free( auxBuf ); - return( EXIT_ON_FAILURE ); - } - - derivatives[0] = DERIVATIVE_0; - derivatives[1] = DERIVATIVE_1; - derivatives[2] = NODERIVATIVE; - if ( RecursiveFilterOnBuffer( (void*)tmpBuf, CGAL_FLOAT, (void*)tmpBuf, CGAL_FLOAT, - bufferDims, borderLengths, derivatives, - filterCoefs, filterType ) != EXIT_ON_SUCCESS ) { - if ( _VERBOSE_ ) - fprintf( stderr, "%s: unable to compute Y derivative (3D)\n", proc ); - free( auxBuf ); - return( EXIT_ON_FAILURE ); - } - - sizeAuxBuf = bufferDims[0] * bufferDims[1] * bufferDims[2]; - for ( i = 0; i < sizeAuxBuf; i++ ) - grdBuf[i] = grdBuf[i]*grdBuf[i] + tmpBuf[i]*tmpBuf[i]; - - derivatives[0] = DERIVATIVE_0; - derivatives[1] = DERIVATIVE_0; - derivatives[2] = DERIVATIVE_1; - if ( RecursiveFilterOnBuffer( bufferIn, typeIn, (void*)tmpBuf, CGAL_FLOAT, - bufferDims, borderLengths, derivatives, - filterCoefs, filterType ) != EXIT_ON_SUCCESS ) { - if ( _VERBOSE_ ) - fprintf( stderr, "%s: unable to compute Z derivative (3D)\n", proc ); - free( auxBuf ); - return( EXIT_ON_FAILURE ); - } - - for ( i = 0; i < sizeAuxBuf; i++ ) - grdBuf[i] = (float)sqrt( grdBuf[i] + tmpBuf[i]*tmpBuf[i] ); - - } - - if ( grdBuf != bufferOut ) - ConvertBuffer( grdBuf, CGAL_FLOAT, bufferOut, typeOut, - bufferDims[0]*bufferDims[1]*bufferDims[2] ); - free( auxBuf ); - return( EXIT_ON_SUCCESS ); -} - - - - - - - - - - - - - - - - - - - - - - - - -/* - * - * Laplacian - * - * - */ -int Laplacian_2D ( void *bufferIn, - bufferType typeIn, - void *bufferOut, - bufferType typeOut, - int *bufferDims, - int *borderLengths, - float *filterCoefs, - recursiveFilterType filterType ) -{ - const char *proc = "Laplacian_2D"; - float *theXX = NULL; - float *theYY = NULL; - - derivativeOrder XXderiv[3] = { DERIVATIVE_2, SMOOTHING, NODERIVATIVE }; - derivativeOrder YYderiv[3] = { SMOOTHING, DERIVATIVE_2, NODERIVATIVE }; - int sliceDims[3]; - int z, i, dimxXdimy; - - void *sliceOut = NULL; - - - - /* - * We check the buffers' dimensions. - */ - if ( (bufferDims[0] <= 0) || (bufferDims[1] <= 0) || (bufferDims[2] <= 0) ) { - if ( _VERBOSE_ > 0 ) - fprintf( stderr, " Fatal error in %s: improper buffer's dimension.\n", proc ); - return( EXIT_ON_FAILURE ); - } - - /* - * test of the coefficients - */ - if ( (filterCoefs[0] < 0.0) || (filterCoefs[1] < 0.0) || - (filterCoefs[2] < 0.0) ) { - if ( _VERBOSE_ > 0 ) - fprintf( stderr, " Error in %s: negative coefficient's value.\n", proc ); - return( EXIT_ON_FAILURE ); - } - - - /* - * - */ - dimxXdimy = bufferDims[0] * bufferDims[1]; - sliceDims[0] = bufferDims[0]; - sliceDims[1] = bufferDims[1]; - sliceDims[2] = 1; - - - if ( typeOut == CGAL_FLOAT ) { - theXX = (float*)malloc( dimxXdimy * sizeof( float ) ); - } else { - theXX = (float*)malloc( 2 * dimxXdimy * sizeof( float ) ); - } - - if ( theXX == NULL ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to allocate auxiliary buffer.\n" ); - } - return( EXIT_ON_FAILURE ); - } - - if ( typeOut != CGAL_FLOAT ) { - theYY = theXX; - theYY += dimxXdimy; - } - - - - for ( z=0; z 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute X^2 derivative.\n" ); - } - free( theXX ); - return( EXIT_ON_FAILURE ); - } - - if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theYY, CGAL_FLOAT, - sliceDims, borderLengths, - YYderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Y^2 derivative.\n" ); - } - free( theXX ); - return( EXIT_ON_FAILURE ); - } - - - for ( i=0; i 0 ) - fprintf( stderr, " Error in %s: such output type not handled.\n", proc ); - free( theXX ); - return( EXIT_ON_FAILURE ); - } - ConvertBuffer( theYY, CGAL_FLOAT, sliceOut, typeOut, dimxXdimy ); - } - } - - return( EXIT_ON_SUCCESS ); -} - - - - - - - - - - - - - - -int Laplacian ( void *bufferIn, - bufferType typeIn, - void *bufferOut, - bufferType typeOut, - int *bufferDims, - int *borderLengths, - float *filterCoefs, - recursiveFilterType filterType ) -{ - const char *proc = "Laplacian"; - float *theSL = NULL; - float *theZZ = NULL; - float *theZ0 = NULL; - - - derivativeOrder XXderiv[3] = { DERIVATIVE_2, SMOOTHING, NODERIVATIVE }; - derivativeOrder YYderiv[3] = { SMOOTHING, DERIVATIVE_2, NODERIVATIVE }; - derivativeOrder Zsmooth[3] = { NODERIVATIVE, NODERIVATIVE, SMOOTHING }; - derivativeOrder ZZderiv[3] = { SMOOTHING, SMOOTHING, DERIVATIVE_2 }; - - int sliceDims[3]; - int z, i, j, dimxXdimy; - - - - - /* - * We check the buffers' dimensions. - */ - if ( bufferDims[2] == 1 ) { - return( Laplacian_2D ( bufferIn, typeIn, bufferOut, typeOut, - bufferDims, borderLengths, filterCoefs, filterType ) ); - } - - if ( (bufferDims[0] <= 0) || (bufferDims[1] <= 0) || (bufferDims[2] <= 0) ) { - if ( _VERBOSE_ > 0 ) - fprintf( stderr, " Fatal error in %s: improper buffer's dimension.\n", proc ); - return( EXIT_ON_FAILURE ); - } - - /* - * test of the coefficients - */ - if ( (filterCoefs[0] < 0.0) || (filterCoefs[1] < 0.0) || - (filterCoefs[2] < 0.0) ) { - if ( _VERBOSE_ > 0 ) - fprintf( stderr, " Error in %s: negative coefficient's value.\n", proc ); - return( EXIT_ON_FAILURE ); - } - - - /* - * - */ - dimxXdimy = bufferDims[0] * bufferDims[1]; - sliceDims[0] = bufferDims[0]; - sliceDims[1] = bufferDims[1]; - sliceDims[2] = 1; - - - - if ( typeOut == CGAL_FLOAT ) { - theSL = (float*)malloc( (1+bufferDims[2]) * dimxXdimy * sizeof( float ) ); - } else { - theSL = (float*)malloc( (1+2*bufferDims[2]) * dimxXdimy * sizeof( float ) ); - } - - - - if ( theSL == NULL ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to allocate auxiliary buffer.\n" ); - } - return( EXIT_ON_FAILURE ); - } - - - - theZ0 = theSL; - theZ0 += dimxXdimy; - - - - if ( typeOut == CGAL_FLOAT ) { - theZZ = (float*) bufferOut; - } else { - theZZ = theZ0; - theZZ += dimxXdimy * bufferDims[2]; - } - - - - /* - * - * 3D filtering / filtering along Z - * - */ - - if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theZ0, CGAL_FLOAT, - bufferDims, borderLengths, - Zsmooth, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Z^0 derivative.\n" ); - } - free( theSL ); - return( EXIT_ON_FAILURE ); - } - if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theZZ, CGAL_FLOAT, - bufferDims, borderLengths, - ZZderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Z^2 derivative.\n" ); - } - free( theSL ); - return( EXIT_ON_FAILURE ); - } - - - - - - - for ( z=0; z 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute X^2 derivative.\n" ); - } - free( theSL ); - return( EXIT_ON_FAILURE ); - } - - for ( j=z*dimxXdimy, i=0; i 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Y^2 derivative.\n" ); - } - free( theSL ); - return( EXIT_ON_FAILURE ); - } - - for ( j=z*dimxXdimy, i=0; i 0 ) - fprintf( stderr, " Fatal error in %s: improper buffer's dimension.\n", proc ); - return( EXIT_ON_FAILURE ); - } - - /* - * test of the coefficients - */ - if ( (filterCoefs[0] < 0.0) || (filterCoefs[1] < 0.0) || - (filterCoefs[2] < 0.0) ) { - if ( _VERBOSE_ > 0 ) - fprintf( stderr, " Error in %s: negative coefficient's value.\n", proc ); - return( EXIT_ON_FAILURE ); - } - - - /* - * - */ - dimxXdimy = bufferDims[0] * bufferDims[1]; - sliceDims[0] = bufferDims[0]; - sliceDims[1] = bufferDims[1]; - sliceDims[2] = 1; - - - if ( typeOut == CGAL_FLOAT ) { - theXX = (float*)malloc( 4 * dimxXdimy * sizeof( float ) ); - } else { - theXX = (float*)malloc( 5 * dimxXdimy * sizeof( float ) ); - } - - if ( theXX == NULL ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to allocate auxiliary buffer.\n" ); - } - return( EXIT_ON_FAILURE ); - } - - - - theX = theY = theYY = theXX; - theYY += dimxXdimy; - theX += 2*dimxXdimy; - theY += 3*dimxXdimy; - - - - if ( typeOut != CGAL_FLOAT ) { - theXY = theXX; - theXY += 4*dimxXdimy; - } - - - - for ( z=0; z 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Y^0 derivative.\n" ); - } - free( theXX ); - return( EXIT_ON_FAILURE ); - } - - if ( RecursiveFilterOnBuffer( sliceIn, typeIn, theY, CGAL_FLOAT, - sliceDims, borderLengths, - Xsmooth, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute X^0 derivative.\n" ); - } - free( theXX ); - return( EXIT_ON_FAILURE ); - } - - - - - if ( RecursiveFilterOnBuffer( sliceIn, typeIn, theXY, CGAL_FLOAT, - sliceDims, borderLengths, - XYderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute X^1Y^1 derivative.\n" ); - } - free( theXX ); - return( EXIT_ON_FAILURE ); - } - - - - - if ( RecursiveFilterOnBuffer( theX, CGAL_FLOAT, theXX, CGAL_FLOAT, - sliceDims, borderLengths, - XXderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute X^2 derivative.\n" ); - } - free( theXX ); - return( EXIT_ON_FAILURE ); - } - - if ( RecursiveFilterOnBuffer( theY, CGAL_FLOAT, theYY, CGAL_FLOAT, - sliceDims, borderLengths, - YYderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Y^2 derivative.\n" ); - } - free( theXX ); - return( EXIT_ON_FAILURE ); - } - - - - - if ( RecursiveFilterOnBuffer( theX, CGAL_FLOAT, theX, CGAL_FLOAT, - sliceDims, borderLengths, - Xderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute X^1 derivative.\n" ); - } - free( theXX ); - return( EXIT_ON_FAILURE ); - } - - if ( RecursiveFilterOnBuffer( theY, CGAL_FLOAT, theY, CGAL_FLOAT, - sliceDims, borderLengths, - Yderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Y^1 derivative.\n" ); - } - free( theXX ); - return( EXIT_ON_FAILURE ); - } - - - - - for ( i=0; i 1e-10 ) theXY[i] = (float)(theXY[i] / g); - } - - if ( typeOut != CGAL_FLOAT ) { - switch ( typeOut ) { - case CGAL_UCHAR : - sliceOut = (((u8*)bufferOut) + z * dimxXdimy); - break; - case CGAL_SCHAR : - sliceOut = (((s8*)bufferOut) + z * dimxXdimy); - break; - case CGAL_SSHORT : - sliceOut = (((s16*)bufferOut) + z * dimxXdimy); - break; - case CGAL_DOUBLE : - sliceOut = (((r64*)bufferOut) + z * dimxXdimy); - break; - default : - if ( _VERBOSE_ > 0 ) - fprintf( stderr, " Error in %s: such output type not handled.\n", proc ); - free( theXX ); - return( EXIT_ON_FAILURE ); - } - ConvertBuffer( theXY, CGAL_FLOAT, sliceOut, typeOut, dimxXdimy ); - } - } - - return( EXIT_ON_SUCCESS ); -} - - - - - - - - - - - - - - - - - - - - - - -int GradientHessianGradient ( void *bufferIn, - bufferType typeIn, - void *bufferOut, - bufferType typeOut, - int *bufferDims, - int *borderLengths, - float *filterCoefs, - recursiveFilterType filterType ) -{ - const char *proc = "GradientHessianGradient"; - - - - float *theZZ = NULL; - float *theZ = NULL; - float *theZ1 = NULL; - float *theZ0 = NULL; - - float *theXZ = NULL; - float *theYZ = NULL; - - float *theXX = NULL; - float *theYY = NULL; - float *theXY = NULL; - - float *theX = NULL; - float *theY = NULL; - - - derivativeOrder ZZderiv[3] = { SMOOTHING, SMOOTHING, DERIVATIVE_2 }; - derivativeOrder Zderiv[3] = { SMOOTHING, SMOOTHING, DERIVATIVE_1 }; - derivativeOrder Z1deriv[3] = { NODERIVATIVE, NODERIVATIVE, DERIVATIVE_1 }; - derivativeOrder Z0deriv[3] = { NODERIVATIVE, NODERIVATIVE, SMOOTHING }; - - derivativeOrder XZderiv[3] = { DERIVATIVE_1, SMOOTHING, NODERIVATIVE }; - derivativeOrder YZderiv[3] = { SMOOTHING, DERIVATIVE_1, NODERIVATIVE }; - - derivativeOrder XXderiv[3] = { DERIVATIVE_2, SMOOTHING, NODERIVATIVE }; - derivativeOrder YYderiv[3] = { SMOOTHING, DERIVATIVE_2, NODERIVATIVE }; - derivativeOrder XYderiv[3] = { DERIVATIVE_1, DERIVATIVE_1, NODERIVATIVE }; - - derivativeOrder Xderiv[3] = { DERIVATIVE_1, SMOOTHING, NODERIVATIVE }; - derivativeOrder Yderiv[3] = { SMOOTHING, DERIVATIVE_1, NODERIVATIVE }; - - int sliceDims[3]; - int z, i, j, dimxXdimy; - - double gx, gy, gz, g; - - /* - * We check the buffers' dimensions. - */ - if ( bufferDims[2] == 1 ) { - return( GradientHessianGradient_2D ( bufferIn, typeIn, bufferOut, typeOut, - bufferDims, borderLengths, filterCoefs, filterType ) ); - } - - if ( (bufferDims[0] <= 0) || (bufferDims[1] <= 0) || (bufferDims[2] <= 0) ) { - if ( _VERBOSE_ > 0 ) - fprintf( stderr, " Fatal error in %s: improper buffer's dimension.\n", proc ); - return( EXIT_ON_FAILURE ); - } - - /* - * test of the coefficients - */ - if ( (filterCoefs[0] < 0.0) || (filterCoefs[1] < 0.0) || - (filterCoefs[2] < 0.0) ) { - if ( _VERBOSE_ > 0 ) - fprintf( stderr, " Error in %s: negative coefficient's value.\n", proc ); - return( EXIT_ON_FAILURE ); - } - - - /* - * - */ - dimxXdimy = bufferDims[0] * bufferDims[1]; - sliceDims[0] = bufferDims[0]; - sliceDims[1] = bufferDims[1]; - sliceDims[2] = 1; - - - if ( typeOut == CGAL_FLOAT ) { - theX = (float*)malloc( (7+3*bufferDims[2]) * dimxXdimy * sizeof( float ) ); - } else { - theX = (float*)malloc( (7+4*bufferDims[2]) * dimxXdimy * sizeof( float ) ); - } - - - if ( theX == NULL ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to allocate auxiliary buffer.\n" ); - } - return( EXIT_ON_FAILURE ); - } - - /* - * BUFFERS - * - * slices : theX theY theXY theYY theXX theYZ theXZ - * - * volumes : theZ0 theZ1 theZ theZZ - * - */ - - theY = theXX = theXY = theYY = theYZ = theXZ = theX; - theZ0 = theZ1 = theZ = theX; - - theY += dimxXdimy; - theXY += 2*dimxXdimy; - theYY += 3*dimxXdimy; - theXX += 4*dimxXdimy; - theYZ += 5*dimxXdimy; - theXZ += 6*dimxXdimy; - - theZ0 += 7*dimxXdimy; - theZ1 += 7*dimxXdimy + bufferDims[2]*dimxXdimy; - theZ += 7*dimxXdimy + 2*bufferDims[2]*dimxXdimy; - - if ( typeOut == CGAL_FLOAT ) { - theZZ = (float*)bufferOut; - } else { - theZZ = theX; - theZZ += 7*dimxXdimy + 3*bufferDims[2]*dimxXdimy; - } - - - - /* - * - * 3D filtering / filtering along Z - * - */ - - if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theZ0, CGAL_FLOAT, - bufferDims, borderLengths, - Z0deriv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Z^0 derivative.\n" ); - } - free( theX ); - return( EXIT_ON_FAILURE ); - } - - if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theZ1, CGAL_FLOAT, - bufferDims, borderLengths, - Z1deriv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Z^1 derivative.\n" ); - } - free( theX ); - return( EXIT_ON_FAILURE ); - } - - if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theZ, CGAL_FLOAT, - bufferDims, borderLengths, - Zderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Z^1 derivative (edge).\n" ); - } - free( theX ); - return( EXIT_ON_FAILURE ); - } - - if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theZZ, CGAL_FLOAT, - bufferDims, borderLengths, - ZZderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Z^2 derivative.\n" ); - } - free( theX ); - return( EXIT_ON_FAILURE ); - } - - - /* - * theZ0 : smoothed along Z - * theZ1 : first derivative along Z - * theZ : first derivative along Z, smoothed along X and Y - * theZZ : second derivative along Z, smoothed along X and Y - */ - - - - for ( z=0; z 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute X^1Z^1 derivative.\n" ); - } - free( theX ); - return( EXIT_ON_FAILURE ); - } - - if ( RecursiveFilterOnBuffer( theZ1+z*dimxXdimy, CGAL_FLOAT, theYZ, CGAL_FLOAT, - sliceDims, borderLengths, - YZderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Y^1Z^1 derivative.\n" ); - } - free( theX ); - return( EXIT_ON_FAILURE ); - } - - - - - if ( RecursiveFilterOnBuffer( theZ0+z*dimxXdimy, CGAL_FLOAT, theXX, CGAL_FLOAT, - sliceDims, borderLengths, - XXderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute X^2 derivative.\n" ); - } - free( theX ); - return( EXIT_ON_FAILURE ); - } - - if ( RecursiveFilterOnBuffer( theZ0+z*dimxXdimy, CGAL_FLOAT, theYY, CGAL_FLOAT, - sliceDims, borderLengths, - YYderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Y^2 derivative.\n" ); - } - free( theX ); - return( EXIT_ON_FAILURE ); - } - - if ( RecursiveFilterOnBuffer( theZ0+z*dimxXdimy, CGAL_FLOAT, theXY, CGAL_FLOAT, - sliceDims, borderLengths, - XYderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute X^1Y^1 derivative.\n" ); - } - free( theX ); - return( EXIT_ON_FAILURE ); - } - - - - if ( RecursiveFilterOnBuffer( theZ0+z*dimxXdimy, CGAL_FLOAT, theX, CGAL_FLOAT, - sliceDims, borderLengths, - Xderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute X^1 derivative (edge).\n" ); - } - free( theX ); - return( EXIT_ON_FAILURE ); - } - - if ( RecursiveFilterOnBuffer( theZ0+z*dimxXdimy, CGAL_FLOAT, theY, CGAL_FLOAT, - sliceDims, borderLengths, - Yderiv, filterCoefs, filterType ) == 0 ) { - if ( _VERBOSE_ > 0 ) { - fprintf( stderr, " Fatal error in %s:", proc ); - fprintf( stderr, " unable to compute Y^1 derivative (edge).\n" ); - } - free( theX ); - return( EXIT_ON_FAILURE ); - } - - - - for ( j=z*dimxXdimy, i=0; i 1e-10 ) theZZ[j] = (float)(theZZ[j] / g); - - } - - } - - if ( typeOut != CGAL_FLOAT ) { - ConvertBuffer( theZZ, CGAL_FLOAT, bufferOut, typeOut, bufferDims[2]*dimxXdimy ); - } - - free( theX ); - - return( EXIT_ON_SUCCESS ); -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* - * - * - * - * - */ - -int RecursiveFilterOnBuffer( void *bufferIn, - bufferType typeIn, - void *bufferOut, - bufferType typeOut, - int *bufferDims, - int *borderLengths, - derivativeOrder *derivatives, - float *filterCoefs, - recursiveFilterType filterType ) -{ - const char *proc = "RecursiveFilterOnBuffer"; - register int dimx, dimxXdimy; - int dimy, dimz; - register int x, y, z; - /* - *obviously, we need to perform the computation - * with float or double values. For this reason, - * we allocate an auxiliary buffer if the output buffer - * is not of type float or double. - */ - void *bufferToBeProcessed = (void*)NULL; - bufferType typeToBeProcessed = TYPE_UNKNOWN; - void *bufferResult = (void*)NULL; - bufferType typeResult = TYPE_UNKNOWN; - /* - * lines' lengths - */ - int lengthX = 0; - int lengthY = 0; - int lengthZ = 0; - int maxLengthline = 0; - int borderXlength = 0; - int borderYlength = 0; - int borderZlength = 0; - /* - * 1D arrays for computations. - */ - double *theLine = (double*)NULL; - double *resLine = (double*)NULL; - double *tmpLine = (double*)NULL; - /* - * pointers for computations; - */ - register r32 *r32firstPoint = (r32*)NULL; - register r64 *r64firstPoint = (r64*)NULL; - register r32 *r32_pt = (r32*)NULL; - register r64 *r64_pt = (r64*)NULL; - register double *dbl_pt1 = (double*)NULL; - register double *dbl_pt2 = (double*)NULL; - register double dbl_first = 0.0; - register double dbl_last = 0.0; - int offsetLastPoint = 0; - int offsetNextFirstPoint = 0; - register r32 *r32firstPointResult = (r32*)NULL; - register r64 *r64firstPointResult = (r64*)NULL; - double *theLinePlusBorder = (double*)NULL; - double *resLinePlusBorder = (double*)NULL; - - RFcoefficientType *RFC = NULL; - - /* - * We check the buffers' dimensions. - */ - dimx = bufferDims[0]; dimy = bufferDims[1]; dimz = bufferDims[2]; - dimxXdimy = dimx * dimy; - if ( (dimx <= 0) || (dimy <= 0) || (dimz <= 0) ) { - if ( _VERBOSE_ > 0 ) - fprintf( stderr, " Fatal error in %s: improper buffer's dimension.\n", proc ); - return( EXIT_ON_FAILURE ); - } - /* - * We check the pointers. - */ - if ( (bufferIn == (void*)NULL) || (bufferOut == (void*)NULL) ) { - if ( _VERBOSE_ > 0 ) - fprintf( stderr, " Fatal error in %s: NULL pointer on buffer.\n", proc ); - return( EXIT_ON_FAILURE ); - } - - /* - * May we use the buffer bufferOut as the bufferResult? - * If its type is CGAL_FLOAT or CGAL_DOUBLE, then yes. - * If not, we have to allocate an auxiliary buffer. - */ - if ( (typeOut == CGAL_FLOAT) || (typeOut == CGAL_DOUBLE) ) { - bufferResult = bufferOut; - typeResult = typeOut; - } else { - bufferResult = (void*)malloc( (dimx*dimy*dimz) * sizeof(r32) ); - if ( bufferResult == (void*)NULL ) { - if ( _VERBOSE_ > 0 ) - fprintf( stderr, " Fatal error in %s: unable to allocate auxiliary buffer.\n", proc ); - return( EXIT_ON_FAILURE ); - } - typeResult = CGAL_FLOAT; - } - - /* - * May we consider the buffer bufferIn as the bufferToBeProcessed? - * If its type is CGAL_FLOAT or CGAL_DOUBLE, then yes. - * If not, we convert it into the buffer bufferResult, and this - * last buffer is the bufferToBeProcessed. - */ - if ( (typeIn == CGAL_FLOAT) || (typeIn == CGAL_DOUBLE) ) { - bufferToBeProcessed = bufferIn; - typeToBeProcessed = typeIn; - } else { - ConvertBuffer( bufferIn, typeIn, bufferResult, typeResult, (dimx*dimy*dimz) ); - bufferToBeProcessed = bufferResult; - typeToBeProcessed = typeResult; - } - - /* - * Estimation of the lines' length along each direction. - */ - if ( borderLengths != NULL ) { - borderXlength = borderLengths[0]; - borderYlength = borderLengths[1]; - borderZlength = borderLengths[2]; - if ( borderXlength < 0 ) borderXlength = 0; - if ( borderYlength < 0 ) borderYlength = 0; - if ( borderZlength < 0 ) borderZlength = 0; - } - - /* - * Tue Jul 6 19:15:15 MET DST 1999 (gregoire Malandain) - * changes 3 x dimx -> dimx, dimy, dimz - */ - lengthX = dimx + 2 * borderXlength; - lengthY = dimy + 2 * borderYlength; - lengthZ = dimz + 2 * borderZlength; - maxLengthline = lengthX; - if ( maxLengthline < lengthY ) maxLengthline = lengthY; - if ( maxLengthline < lengthZ ) maxLengthline = lengthZ; - if ( maxLengthline <= 0 ) { - if ( _VERBOSE_ > 0 ) - fprintf( stderr, " Error in %s: unable to deal with dimensions = 0.\n", proc ); - if ( (typeOut != CGAL_FLOAT) && (typeOut != CGAL_DOUBLE) ) - free( bufferResult ); - return( EXIT_ON_FAILURE ); - } - /* - * Allocations of work arrays. - * We will use them to process each line. - */ - theLine = (double*)malloc( 3 * maxLengthline * sizeof(double) ); - if ( theLine == (double*)NULL ) { - if ( _VERBOSE_ > 0 ) - fprintf( stderr, " Fatal error in %s: unable to allocate auxiliary work arrays.\n", proc ); - if ( (typeOut != CGAL_FLOAT) && (typeOut != CGAL_DOUBLE) ) - free( bufferResult ); - return( EXIT_ON_FAILURE ); - } - resLine = theLine + maxLengthline; - tmpLine = resLine + maxLengthline; - - /* - * From now, - * typeToBeProcessed is either CGAL_FLOAT or CGAL_DOUBLE - * so is typeResult. - */ - - - /* - * Processing along X. - */ - if ( dimx > 4 ) - if (derivatives[0] != NODERIVATIVE) - if (filterCoefs[0] > 0.0) { - - if ( _VERBOSE_ != 0 ) - fprintf( stderr, " %s: processing along X.\n", proc ); - - RFC = InitRecursiveCoefficients( (double)filterCoefs[0], filterType, derivatives[0] ); - - if ( RFC == NULL ) { - if ( _VERBOSE_ != 0 ) - fprintf( stderr, " %s: unable to allocate coefficients\n", proc ); - if ( (typeOut != CGAL_FLOAT) && (typeOut != CGAL_DOUBLE) ) - free( bufferResult ); - return( EXIT_ON_FAILURE ); - } - - r64firstPoint = (r64*)bufferToBeProcessed; - r32firstPoint = (r32*)bufferToBeProcessed; - - r64firstPointResult = (r64*)bufferResult; - r32firstPointResult = (r32*)bufferResult; - - offsetLastPoint = borderXlength + dimx - 1; - - theLinePlusBorder = theLine + borderXlength; - resLinePlusBorder = resLine + borderXlength; - - /* - * There are dimz*dimy X lines to be processed. - */ - for ( z=0; z 0 ) { - dbl_pt1 = theLine + borderXlength; dbl_first = *dbl_pt1; - dbl_pt2 = theLine + offsetLastPoint; dbl_last = *dbl_pt2; - for ( x=0; x 4 ) - if (derivatives[1] != NODERIVATIVE) - if (filterCoefs[1] > 0.0) { - - if ( _VERBOSE_ != 0 ) - fprintf( stderr, " %s: processing along Y.\n", proc ); - - RFC = InitRecursiveCoefficients( (double)filterCoefs[1], filterType, derivatives[1] ); - - if ( RFC == NULL ) { - if ( _VERBOSE_ != 0 ) - fprintf( stderr, " %s: unable to allocate coefficients\n", proc ); - if ( (typeOut != CGAL_FLOAT) && (typeOut != CGAL_DOUBLE) ) - free( bufferResult ); - return( EXIT_ON_FAILURE ); - } - - r64firstPoint = (r64*)bufferToBeProcessed; - r32firstPoint = (r32*)bufferToBeProcessed; - - r64firstPointResult = (r64*)bufferResult; - r32firstPointResult = (r32*)bufferResult; - - offsetLastPoint = borderYlength + dimy - 1; - offsetNextFirstPoint = dimx * dimy - dimx; - - theLinePlusBorder = theLine + borderYlength; - resLinePlusBorder = resLine + borderYlength; - - /* - * There are dimz*dimx Y lines to be processed. - */ - for ( z=0; z 0 ) { - dbl_pt1 = theLine + borderYlength; dbl_first = *dbl_pt1; - dbl_pt2 = theLine + offsetLastPoint; dbl_last = *dbl_pt2; - for ( y=0; y 4 ) - if (derivatives[2] != NODERIVATIVE) - if (filterCoefs[2] > 0.0) { - - if ( _VERBOSE_ != 0 ) - fprintf( stderr, " %s: processing along Z.\n", proc ); - - RFC = InitRecursiveCoefficients( (double)filterCoefs[2], filterType, derivatives[2] ); - - if ( RFC == NULL ) { - if ( _VERBOSE_ != 0 ) - fprintf( stderr, " %s: unable to allocate coefficients\n", proc ); - if ( (typeOut != CGAL_FLOAT) && (typeOut != CGAL_DOUBLE) ) - free( bufferResult ); - return( EXIT_ON_FAILURE ); - } - - r64firstPoint = (r64*)bufferToBeProcessed; - r32firstPoint = (r32*)bufferToBeProcessed; - - offsetLastPoint = borderZlength + dimz - 1; - - r64firstPointResult = (r64*)bufferResult; - r32firstPointResult = (r32*)bufferResult; - - offsetLastPoint = borderZlength + dimz - 1; - - theLinePlusBorder = theLine + borderYlength; - resLinePlusBorder = resLine + borderYlength; - - /* - * There are dimy*dimx Z lines to be processed. - */ - for ( y=0; y 0 ) { - dbl_pt1 = theLine + borderZlength; dbl_first = *dbl_pt1; - dbl_pt2 = theLine + offsetLastPoint; dbl_last = *dbl_pt2; - for ( z=0; z +#include +#include + +#include "convert.h" + +#ifdef CGAL_HEADER_ONLY + +inline int& get_static_verbose_recbuffer() +{ + static int _VERBOSE_ = 0; + return _VERBOSE_; +} + +#else // CGAL_HEADER_ONLY + +static int _VERBOSE_ = 0; + +inline int& get_static_verbose_recbuffer() +{ return _VERBOSE_; } + +#endif // CGAL_HEADER_ONLY + + +#define EXIT_ON_FAILURE 0 +#define EXIT_ON_SUCCESS 1 + +/* + * + * Gradient modulus + * + * + */ +CGAL_INLINE_FUNCTION +int GradientModulus( void *bufferIn, + bufferType typeIn, + void *bufferOut, + bufferType typeOut, + int *bufferDims, + int *borderLengths, + float *filterCoefs, + recursiveFilterType filterType ) +{ + const char *proc = "GradientModulus"; + float *auxBuf = NULL; + float *tmpBuf = NULL, *grdBuf = NULL; + int sizeAuxBuf = 0; + derivativeOrder derivatives[3]; + int i; + + + sizeAuxBuf = bufferDims[0] * bufferDims[1] * bufferDims[2]; + if ( typeOut != CGAL_FLOAT || bufferIn == bufferOut ) + sizeAuxBuf *= 2; + + + /* allocation des buffers de calcul + */ + auxBuf = (float*)malloc( sizeAuxBuf * sizeof(float) ); + if ( auxBuf == NULL ) { + if ( _VERBOSE_ > 0 ) + fprintf( stderr, "%s: unable to allocate auxiliary buffer\n", proc ); + return( EXIT_ON_FAILURE ); + } + tmpBuf = auxBuf; + if ( typeOut != CGAL_FLOAT || bufferIn == bufferOut ) { + grdBuf = tmpBuf; + grdBuf += bufferDims[0] * bufferDims[1] * bufferDims[2]; + } else { + grdBuf = (float*)bufferOut; + } + + /* cas 2D + */ + if ( bufferDims[2] == 1 ) { + + derivatives[0] = DERIVATIVE_1; + derivatives[1] = DERIVATIVE_0; + derivatives[2] = NODERIVATIVE; + if ( RecursiveFilterOnBuffer( bufferIn, typeIn, (void*)grdBuf, CGAL_FLOAT, + bufferDims, borderLengths, derivatives, + filterCoefs, filterType ) != EXIT_ON_SUCCESS ) { + if ( _VERBOSE_ ) + fprintf( stderr, "%s: unable to compute X derivative (2D)\n", proc ); + free( auxBuf ); + return( EXIT_ON_FAILURE ); + } + + derivatives[0] = DERIVATIVE_0; + derivatives[1] = DERIVATIVE_1; + derivatives[2] = NODERIVATIVE; + if ( RecursiveFilterOnBuffer( bufferIn, typeIn, (void*)tmpBuf, CGAL_FLOAT, + bufferDims, borderLengths, derivatives, + filterCoefs, filterType ) != EXIT_ON_SUCCESS ) { + if ( _VERBOSE_ ) + fprintf( stderr, "%s: unable to compute Y derivative (2D)\n", proc ); + free( auxBuf ); + return( EXIT_ON_FAILURE ); + } + + sizeAuxBuf = bufferDims[0] * bufferDims[1] * bufferDims[2]; + for ( i = 0; i < sizeAuxBuf; i++ ) + grdBuf[i] = (float)sqrt( grdBuf[i]*grdBuf[i] + tmpBuf[i]*tmpBuf[i] ); + + } else { + + derivatives[0] = NODERIVATIVE; + derivatives[1] = NODERIVATIVE; + derivatives[2] = DERIVATIVE_0; + if ( RecursiveFilterOnBuffer( bufferIn, typeIn, (void*)tmpBuf, CGAL_FLOAT, + bufferDims, borderLengths, derivatives, + filterCoefs, filterType ) != EXIT_ON_SUCCESS ) { + if ( _VERBOSE_ ) + fprintf( stderr, "%s: unable to compute Z smoothing (3D)\n", proc ); + free( auxBuf ); + return( EXIT_ON_FAILURE ); + } + + derivatives[0] = DERIVATIVE_1; + derivatives[1] = DERIVATIVE_0; + derivatives[2] = NODERIVATIVE; + if ( RecursiveFilterOnBuffer( (void*)tmpBuf, CGAL_FLOAT, (void*)grdBuf, CGAL_FLOAT, + bufferDims, borderLengths, derivatives, + filterCoefs, filterType ) != EXIT_ON_SUCCESS ) { + if ( _VERBOSE_ ) + fprintf( stderr, "%s: unable to compute X derivative (3D)\n", proc ); + free( auxBuf ); + return( EXIT_ON_FAILURE ); + } + + derivatives[0] = DERIVATIVE_0; + derivatives[1] = DERIVATIVE_1; + derivatives[2] = NODERIVATIVE; + if ( RecursiveFilterOnBuffer( (void*)tmpBuf, CGAL_FLOAT, (void*)tmpBuf, CGAL_FLOAT, + bufferDims, borderLengths, derivatives, + filterCoefs, filterType ) != EXIT_ON_SUCCESS ) { + if ( _VERBOSE_ ) + fprintf( stderr, "%s: unable to compute Y derivative (3D)\n", proc ); + free( auxBuf ); + return( EXIT_ON_FAILURE ); + } + + sizeAuxBuf = bufferDims[0] * bufferDims[1] * bufferDims[2]; + for ( i = 0; i < sizeAuxBuf; i++ ) + grdBuf[i] = grdBuf[i]*grdBuf[i] + tmpBuf[i]*tmpBuf[i]; + + derivatives[0] = DERIVATIVE_0; + derivatives[1] = DERIVATIVE_0; + derivatives[2] = DERIVATIVE_1; + if ( RecursiveFilterOnBuffer( bufferIn, typeIn, (void*)tmpBuf, CGAL_FLOAT, + bufferDims, borderLengths, derivatives, + filterCoefs, filterType ) != EXIT_ON_SUCCESS ) { + if ( _VERBOSE_ ) + fprintf( stderr, "%s: unable to compute Z derivative (3D)\n", proc ); + free( auxBuf ); + return( EXIT_ON_FAILURE ); + } + + for ( i = 0; i < sizeAuxBuf; i++ ) + grdBuf[i] = (float)sqrt( grdBuf[i] + tmpBuf[i]*tmpBuf[i] ); + + } + + if ( grdBuf != bufferOut ) + ConvertBuffer( grdBuf, CGAL_FLOAT, bufferOut, typeOut, + bufferDims[0]*bufferDims[1]*bufferDims[2] ); + free( auxBuf ); + return( EXIT_ON_SUCCESS ); +} + + + + + + + + + + + + + + + + + + + + + + + + +/* + * + * Laplacian + * + * + */ +CGAL_INLINE_FUNCTION +int Laplacian_2D ( void *bufferIn, + bufferType typeIn, + void *bufferOut, + bufferType typeOut, + int *bufferDims, + int *borderLengths, + float *filterCoefs, + recursiveFilterType filterType ) +{ + const char *proc = "Laplacian_2D"; + float *theXX = NULL; + float *theYY = NULL; + + derivativeOrder XXderiv[3] = { DERIVATIVE_2, SMOOTHING, NODERIVATIVE }; + derivativeOrder YYderiv[3] = { SMOOTHING, DERIVATIVE_2, NODERIVATIVE }; + int sliceDims[3]; + int z, i, dimxXdimy; + + void *sliceOut = NULL; + + + + /* + * We check the buffers' dimensions. + */ + if ( (bufferDims[0] <= 0) || (bufferDims[1] <= 0) || (bufferDims[2] <= 0) ) { + if ( _VERBOSE_ > 0 ) + fprintf( stderr, " Fatal error in %s: improper buffer's dimension.\n", proc ); + return( EXIT_ON_FAILURE ); + } + + /* + * test of the coefficients + */ + if ( (filterCoefs[0] < 0.0) || (filterCoefs[1] < 0.0) || + (filterCoefs[2] < 0.0) ) { + if ( _VERBOSE_ > 0 ) + fprintf( stderr, " Error in %s: negative coefficient's value.\n", proc ); + return( EXIT_ON_FAILURE ); + } + + + /* + * + */ + dimxXdimy = bufferDims[0] * bufferDims[1]; + sliceDims[0] = bufferDims[0]; + sliceDims[1] = bufferDims[1]; + sliceDims[2] = 1; + + + if ( typeOut == CGAL_FLOAT ) { + theXX = (float*)malloc( dimxXdimy * sizeof( float ) ); + } else { + theXX = (float*)malloc( 2 * dimxXdimy * sizeof( float ) ); + } + + if ( theXX == NULL ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to allocate auxiliary buffer.\n" ); + } + return( EXIT_ON_FAILURE ); + } + + if ( typeOut != CGAL_FLOAT ) { + theYY = theXX; + theYY += dimxXdimy; + } + + + + for ( z=0; z 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute X^2 derivative.\n" ); + } + free( theXX ); + return( EXIT_ON_FAILURE ); + } + + if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theYY, CGAL_FLOAT, + sliceDims, borderLengths, + YYderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Y^2 derivative.\n" ); + } + free( theXX ); + return( EXIT_ON_FAILURE ); + } + + + for ( i=0; i 0 ) + fprintf( stderr, " Error in %s: such output type not handled.\n", proc ); + free( theXX ); + return( EXIT_ON_FAILURE ); + } + ConvertBuffer( theYY, CGAL_FLOAT, sliceOut, typeOut, dimxXdimy ); + } + } + + return( EXIT_ON_SUCCESS ); +} + + + + + + + + + + + + + +CGAL_INLINE_FUNCTION +int Laplacian ( void *bufferIn, + bufferType typeIn, + void *bufferOut, + bufferType typeOut, + int *bufferDims, + int *borderLengths, + float *filterCoefs, + recursiveFilterType filterType ) +{ + const char *proc = "Laplacian"; + float *theSL = NULL; + float *theZZ = NULL; + float *theZ0 = NULL; + + + derivativeOrder XXderiv[3] = { DERIVATIVE_2, SMOOTHING, NODERIVATIVE }; + derivativeOrder YYderiv[3] = { SMOOTHING, DERIVATIVE_2, NODERIVATIVE }; + derivativeOrder Zsmooth[3] = { NODERIVATIVE, NODERIVATIVE, SMOOTHING }; + derivativeOrder ZZderiv[3] = { SMOOTHING, SMOOTHING, DERIVATIVE_2 }; + + int sliceDims[3]; + int z, i, j, dimxXdimy; + + + + + /* + * We check the buffers' dimensions. + */ + if ( bufferDims[2] == 1 ) { + return( Laplacian_2D ( bufferIn, typeIn, bufferOut, typeOut, + bufferDims, borderLengths, filterCoefs, filterType ) ); + } + + if ( (bufferDims[0] <= 0) || (bufferDims[1] <= 0) || (bufferDims[2] <= 0) ) { + if ( _VERBOSE_ > 0 ) + fprintf( stderr, " Fatal error in %s: improper buffer's dimension.\n", proc ); + return( EXIT_ON_FAILURE ); + } + + /* + * test of the coefficients + */ + if ( (filterCoefs[0] < 0.0) || (filterCoefs[1] < 0.0) || + (filterCoefs[2] < 0.0) ) { + if ( _VERBOSE_ > 0 ) + fprintf( stderr, " Error in %s: negative coefficient's value.\n", proc ); + return( EXIT_ON_FAILURE ); + } + + + /* + * + */ + dimxXdimy = bufferDims[0] * bufferDims[1]; + sliceDims[0] = bufferDims[0]; + sliceDims[1] = bufferDims[1]; + sliceDims[2] = 1; + + + + if ( typeOut == CGAL_FLOAT ) { + theSL = (float*)malloc( (1+bufferDims[2]) * dimxXdimy * sizeof( float ) ); + } else { + theSL = (float*)malloc( (1+2*bufferDims[2]) * dimxXdimy * sizeof( float ) ); + } + + + + if ( theSL == NULL ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to allocate auxiliary buffer.\n" ); + } + return( EXIT_ON_FAILURE ); + } + + + + theZ0 = theSL; + theZ0 += dimxXdimy; + + + + if ( typeOut == CGAL_FLOAT ) { + theZZ = (float*) bufferOut; + } else { + theZZ = theZ0; + theZZ += dimxXdimy * bufferDims[2]; + } + + + + /* + * + * 3D filtering / filtering along Z + * + */ + + if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theZ0, CGAL_FLOAT, + bufferDims, borderLengths, + Zsmooth, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Z^0 derivative.\n" ); + } + free( theSL ); + return( EXIT_ON_FAILURE ); + } + if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theZZ, CGAL_FLOAT, + bufferDims, borderLengths, + ZZderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Z^2 derivative.\n" ); + } + free( theSL ); + return( EXIT_ON_FAILURE ); + } + + + + + + + for ( z=0; z 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute X^2 derivative.\n" ); + } + free( theSL ); + return( EXIT_ON_FAILURE ); + } + + for ( j=z*dimxXdimy, i=0; i 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Y^2 derivative.\n" ); + } + free( theSL ); + return( EXIT_ON_FAILURE ); + } + + for ( j=z*dimxXdimy, i=0; i 0 ) + fprintf( stderr, " Fatal error in %s: improper buffer's dimension.\n", proc ); + return( EXIT_ON_FAILURE ); + } + + /* + * test of the coefficients + */ + if ( (filterCoefs[0] < 0.0) || (filterCoefs[1] < 0.0) || + (filterCoefs[2] < 0.0) ) { + if ( _VERBOSE_ > 0 ) + fprintf( stderr, " Error in %s: negative coefficient's value.\n", proc ); + return( EXIT_ON_FAILURE ); + } + + + /* + * + */ + dimxXdimy = bufferDims[0] * bufferDims[1]; + sliceDims[0] = bufferDims[0]; + sliceDims[1] = bufferDims[1]; + sliceDims[2] = 1; + + + if ( typeOut == CGAL_FLOAT ) { + theXX = (float*)malloc( 4 * dimxXdimy * sizeof( float ) ); + } else { + theXX = (float*)malloc( 5 * dimxXdimy * sizeof( float ) ); + } + + if ( theXX == NULL ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to allocate auxiliary buffer.\n" ); + } + return( EXIT_ON_FAILURE ); + } + + + + theX = theY = theYY = theXX; + theYY += dimxXdimy; + theX += 2*dimxXdimy; + theY += 3*dimxXdimy; + + + + if ( typeOut != CGAL_FLOAT ) { + theXY = theXX; + theXY += 4*dimxXdimy; + } + + + + for ( z=0; z 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Y^0 derivative.\n" ); + } + free( theXX ); + return( EXIT_ON_FAILURE ); + } + + if ( RecursiveFilterOnBuffer( sliceIn, typeIn, theY, CGAL_FLOAT, + sliceDims, borderLengths, + Xsmooth, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute X^0 derivative.\n" ); + } + free( theXX ); + return( EXIT_ON_FAILURE ); + } + + + + + if ( RecursiveFilterOnBuffer( sliceIn, typeIn, theXY, CGAL_FLOAT, + sliceDims, borderLengths, + XYderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute X^1Y^1 derivative.\n" ); + } + free( theXX ); + return( EXIT_ON_FAILURE ); + } + + + + + if ( RecursiveFilterOnBuffer( theX, CGAL_FLOAT, theXX, CGAL_FLOAT, + sliceDims, borderLengths, + XXderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute X^2 derivative.\n" ); + } + free( theXX ); + return( EXIT_ON_FAILURE ); + } + + if ( RecursiveFilterOnBuffer( theY, CGAL_FLOAT, theYY, CGAL_FLOAT, + sliceDims, borderLengths, + YYderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Y^2 derivative.\n" ); + } + free( theXX ); + return( EXIT_ON_FAILURE ); + } + + + + + if ( RecursiveFilterOnBuffer( theX, CGAL_FLOAT, theX, CGAL_FLOAT, + sliceDims, borderLengths, + Xderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute X^1 derivative.\n" ); + } + free( theXX ); + return( EXIT_ON_FAILURE ); + } + + if ( RecursiveFilterOnBuffer( theY, CGAL_FLOAT, theY, CGAL_FLOAT, + sliceDims, borderLengths, + Yderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Y^1 derivative.\n" ); + } + free( theXX ); + return( EXIT_ON_FAILURE ); + } + + + + + for ( i=0; i 1e-10 ) theXY[i] = (float)(theXY[i] / g); + } + + if ( typeOut != CGAL_FLOAT ) { + switch ( typeOut ) { + case CGAL_UCHAR : + sliceOut = (((u8*)bufferOut) + z * dimxXdimy); + break; + case CGAL_SCHAR : + sliceOut = (((s8*)bufferOut) + z * dimxXdimy); + break; + case CGAL_SSHORT : + sliceOut = (((s16*)bufferOut) + z * dimxXdimy); + break; + case CGAL_DOUBLE : + sliceOut = (((r64*)bufferOut) + z * dimxXdimy); + break; + default : + if ( _VERBOSE_ > 0 ) + fprintf( stderr, " Error in %s: such output type not handled.\n", proc ); + free( theXX ); + return( EXIT_ON_FAILURE ); + } + ConvertBuffer( theXY, CGAL_FLOAT, sliceOut, typeOut, dimxXdimy ); + } + } + + return( EXIT_ON_SUCCESS ); +} + + + + + + + + + + + + + + + + + + + + + +CGAL_INLINE_FUNCTION +int GradientHessianGradient ( void *bufferIn, + bufferType typeIn, + void *bufferOut, + bufferType typeOut, + int *bufferDims, + int *borderLengths, + float *filterCoefs, + recursiveFilterType filterType ) +{ + const char *proc = "GradientHessianGradient"; + + + + float *theZZ = NULL; + float *theZ = NULL; + float *theZ1 = NULL; + float *theZ0 = NULL; + + float *theXZ = NULL; + float *theYZ = NULL; + + float *theXX = NULL; + float *theYY = NULL; + float *theXY = NULL; + + float *theX = NULL; + float *theY = NULL; + + + derivativeOrder ZZderiv[3] = { SMOOTHING, SMOOTHING, DERIVATIVE_2 }; + derivativeOrder Zderiv[3] = { SMOOTHING, SMOOTHING, DERIVATIVE_1 }; + derivativeOrder Z1deriv[3] = { NODERIVATIVE, NODERIVATIVE, DERIVATIVE_1 }; + derivativeOrder Z0deriv[3] = { NODERIVATIVE, NODERIVATIVE, SMOOTHING }; + + derivativeOrder XZderiv[3] = { DERIVATIVE_1, SMOOTHING, NODERIVATIVE }; + derivativeOrder YZderiv[3] = { SMOOTHING, DERIVATIVE_1, NODERIVATIVE }; + + derivativeOrder XXderiv[3] = { DERIVATIVE_2, SMOOTHING, NODERIVATIVE }; + derivativeOrder YYderiv[3] = { SMOOTHING, DERIVATIVE_2, NODERIVATIVE }; + derivativeOrder XYderiv[3] = { DERIVATIVE_1, DERIVATIVE_1, NODERIVATIVE }; + + derivativeOrder Xderiv[3] = { DERIVATIVE_1, SMOOTHING, NODERIVATIVE }; + derivativeOrder Yderiv[3] = { SMOOTHING, DERIVATIVE_1, NODERIVATIVE }; + + int sliceDims[3]; + int z, i, j, dimxXdimy; + + double gx, gy, gz, g; + + /* + * We check the buffers' dimensions. + */ + if ( bufferDims[2] == 1 ) { + return( GradientHessianGradient_2D ( bufferIn, typeIn, bufferOut, typeOut, + bufferDims, borderLengths, filterCoefs, filterType ) ); + } + + if ( (bufferDims[0] <= 0) || (bufferDims[1] <= 0) || (bufferDims[2] <= 0) ) { + if ( _VERBOSE_ > 0 ) + fprintf( stderr, " Fatal error in %s: improper buffer's dimension.\n", proc ); + return( EXIT_ON_FAILURE ); + } + + /* + * test of the coefficients + */ + if ( (filterCoefs[0] < 0.0) || (filterCoefs[1] < 0.0) || + (filterCoefs[2] < 0.0) ) { + if ( _VERBOSE_ > 0 ) + fprintf( stderr, " Error in %s: negative coefficient's value.\n", proc ); + return( EXIT_ON_FAILURE ); + } + + + /* + * + */ + dimxXdimy = bufferDims[0] * bufferDims[1]; + sliceDims[0] = bufferDims[0]; + sliceDims[1] = bufferDims[1]; + sliceDims[2] = 1; + + + if ( typeOut == CGAL_FLOAT ) { + theX = (float*)malloc( (7+3*bufferDims[2]) * dimxXdimy * sizeof( float ) ); + } else { + theX = (float*)malloc( (7+4*bufferDims[2]) * dimxXdimy * sizeof( float ) ); + } + + + if ( theX == NULL ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to allocate auxiliary buffer.\n" ); + } + return( EXIT_ON_FAILURE ); + } + + /* + * BUFFERS + * + * slices : theX theY theXY theYY theXX theYZ theXZ + * + * volumes : theZ0 theZ1 theZ theZZ + * + */ + + theY = theXX = theXY = theYY = theYZ = theXZ = theX; + theZ0 = theZ1 = theZ = theX; + + theY += dimxXdimy; + theXY += 2*dimxXdimy; + theYY += 3*dimxXdimy; + theXX += 4*dimxXdimy; + theYZ += 5*dimxXdimy; + theXZ += 6*dimxXdimy; + + theZ0 += 7*dimxXdimy; + theZ1 += 7*dimxXdimy + bufferDims[2]*dimxXdimy; + theZ += 7*dimxXdimy + 2*bufferDims[2]*dimxXdimy; + + if ( typeOut == CGAL_FLOAT ) { + theZZ = (float*)bufferOut; + } else { + theZZ = theX; + theZZ += 7*dimxXdimy + 3*bufferDims[2]*dimxXdimy; + } + + + + /* + * + * 3D filtering / filtering along Z + * + */ + + if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theZ0, CGAL_FLOAT, + bufferDims, borderLengths, + Z0deriv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Z^0 derivative.\n" ); + } + free( theX ); + return( EXIT_ON_FAILURE ); + } + + if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theZ1, CGAL_FLOAT, + bufferDims, borderLengths, + Z1deriv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Z^1 derivative.\n" ); + } + free( theX ); + return( EXIT_ON_FAILURE ); + } + + if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theZ, CGAL_FLOAT, + bufferDims, borderLengths, + Zderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Z^1 derivative (edge).\n" ); + } + free( theX ); + return( EXIT_ON_FAILURE ); + } + + if ( RecursiveFilterOnBuffer( bufferIn, typeIn, theZZ, CGAL_FLOAT, + bufferDims, borderLengths, + ZZderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Z^2 derivative.\n" ); + } + free( theX ); + return( EXIT_ON_FAILURE ); + } + + + /* + * theZ0 : smoothed along Z + * theZ1 : first derivative along Z + * theZ : first derivative along Z, smoothed along X and Y + * theZZ : second derivative along Z, smoothed along X and Y + */ + + + + for ( z=0; z 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute X^1Z^1 derivative.\n" ); + } + free( theX ); + return( EXIT_ON_FAILURE ); + } + + if ( RecursiveFilterOnBuffer( theZ1+z*dimxXdimy, CGAL_FLOAT, theYZ, CGAL_FLOAT, + sliceDims, borderLengths, + YZderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Y^1Z^1 derivative.\n" ); + } + free( theX ); + return( EXIT_ON_FAILURE ); + } + + + + + if ( RecursiveFilterOnBuffer( theZ0+z*dimxXdimy, CGAL_FLOAT, theXX, CGAL_FLOAT, + sliceDims, borderLengths, + XXderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute X^2 derivative.\n" ); + } + free( theX ); + return( EXIT_ON_FAILURE ); + } + + if ( RecursiveFilterOnBuffer( theZ0+z*dimxXdimy, CGAL_FLOAT, theYY, CGAL_FLOAT, + sliceDims, borderLengths, + YYderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Y^2 derivative.\n" ); + } + free( theX ); + return( EXIT_ON_FAILURE ); + } + + if ( RecursiveFilterOnBuffer( theZ0+z*dimxXdimy, CGAL_FLOAT, theXY, CGAL_FLOAT, + sliceDims, borderLengths, + XYderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute X^1Y^1 derivative.\n" ); + } + free( theX ); + return( EXIT_ON_FAILURE ); + } + + + + if ( RecursiveFilterOnBuffer( theZ0+z*dimxXdimy, CGAL_FLOAT, theX, CGAL_FLOAT, + sliceDims, borderLengths, + Xderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute X^1 derivative (edge).\n" ); + } + free( theX ); + return( EXIT_ON_FAILURE ); + } + + if ( RecursiveFilterOnBuffer( theZ0+z*dimxXdimy, CGAL_FLOAT, theY, CGAL_FLOAT, + sliceDims, borderLengths, + Yderiv, filterCoefs, filterType ) == 0 ) { + if ( _VERBOSE_ > 0 ) { + fprintf( stderr, " Fatal error in %s:", proc ); + fprintf( stderr, " unable to compute Y^1 derivative (edge).\n" ); + } + free( theX ); + return( EXIT_ON_FAILURE ); + } + + + + for ( j=z*dimxXdimy, i=0; i 1e-10 ) theZZ[j] = (float)(theZZ[j] / g); + + } + + } + + if ( typeOut != CGAL_FLOAT ) { + ConvertBuffer( theZZ, CGAL_FLOAT, bufferOut, typeOut, bufferDims[2]*dimxXdimy ); + } + + free( theX ); + + return( EXIT_ON_SUCCESS ); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* + * + * + * + * + */ +CGAL_INLINE_FUNCTION +int RecursiveFilterOnBuffer( void *bufferIn, + bufferType typeIn, + void *bufferOut, + bufferType typeOut, + int *bufferDims, + int *borderLengths, + derivativeOrder *derivatives, + float *filterCoefs, + recursiveFilterType filterType ) +{ + const char *proc = "RecursiveFilterOnBuffer"; + register int dimx, dimxXdimy; + int dimy, dimz; + register int x, y, z; + /* + *obviously, we need to perform the computation + * with float or double values. For this reason, + * we allocate an auxiliary buffer if the output buffer + * is not of type float or double. + */ + void *bufferToBeProcessed = (void*)NULL; + bufferType typeToBeProcessed = TYPE_UNKNOWN; + void *bufferResult = (void*)NULL; + bufferType typeResult = TYPE_UNKNOWN; + /* + * lines' lengths + */ + int lengthX = 0; + int lengthY = 0; + int lengthZ = 0; + int maxLengthline = 0; + int borderXlength = 0; + int borderYlength = 0; + int borderZlength = 0; + /* + * 1D arrays for computations. + */ + double *theLine = (double*)NULL; + double *resLine = (double*)NULL; + double *tmpLine = (double*)NULL; + /* + * pointers for computations; + */ + register r32 *r32firstPoint = (r32*)NULL; + register r64 *r64firstPoint = (r64*)NULL; + register r32 *r32_pt = (r32*)NULL; + register r64 *r64_pt = (r64*)NULL; + register double *dbl_pt1 = (double*)NULL; + register double *dbl_pt2 = (double*)NULL; + register double dbl_first = 0.0; + register double dbl_last = 0.0; + int offsetLastPoint = 0; + int offsetNextFirstPoint = 0; + register r32 *r32firstPointResult = (r32*)NULL; + register r64 *r64firstPointResult = (r64*)NULL; + double *theLinePlusBorder = (double*)NULL; + double *resLinePlusBorder = (double*)NULL; + + RFcoefficientType *RFC = NULL; + + /* + * We check the buffers' dimensions. + */ + dimx = bufferDims[0]; dimy = bufferDims[1]; dimz = bufferDims[2]; + dimxXdimy = dimx * dimy; + if ( (dimx <= 0) || (dimy <= 0) || (dimz <= 0) ) { + if ( _VERBOSE_ > 0 ) + fprintf( stderr, " Fatal error in %s: improper buffer's dimension.\n", proc ); + return( EXIT_ON_FAILURE ); + } + /* + * We check the pointers. + */ + if ( (bufferIn == (void*)NULL) || (bufferOut == (void*)NULL) ) { + if ( _VERBOSE_ > 0 ) + fprintf( stderr, " Fatal error in %s: NULL pointer on buffer.\n", proc ); + return( EXIT_ON_FAILURE ); + } + + /* + * May we use the buffer bufferOut as the bufferResult? + * If its type is CGAL_FLOAT or CGAL_DOUBLE, then yes. + * If not, we have to allocate an auxiliary buffer. + */ + if ( (typeOut == CGAL_FLOAT) || (typeOut == CGAL_DOUBLE) ) { + bufferResult = bufferOut; + typeResult = typeOut; + } else { + bufferResult = (void*)malloc( (dimx*dimy*dimz) * sizeof(r32) ); + if ( bufferResult == (void*)NULL ) { + if ( _VERBOSE_ > 0 ) + fprintf( stderr, " Fatal error in %s: unable to allocate auxiliary buffer.\n", proc ); + return( EXIT_ON_FAILURE ); + } + typeResult = CGAL_FLOAT; + } + + /* + * May we consider the buffer bufferIn as the bufferToBeProcessed? + * If its type is CGAL_FLOAT or CGAL_DOUBLE, then yes. + * If not, we convert it into the buffer bufferResult, and this + * last buffer is the bufferToBeProcessed. + */ + if ( (typeIn == CGAL_FLOAT) || (typeIn == CGAL_DOUBLE) ) { + bufferToBeProcessed = bufferIn; + typeToBeProcessed = typeIn; + } else { + ConvertBuffer( bufferIn, typeIn, bufferResult, typeResult, (dimx*dimy*dimz) ); + bufferToBeProcessed = bufferResult; + typeToBeProcessed = typeResult; + } + + /* + * Estimation of the lines' length along each direction. + */ + if ( borderLengths != NULL ) { + borderXlength = borderLengths[0]; + borderYlength = borderLengths[1]; + borderZlength = borderLengths[2]; + if ( borderXlength < 0 ) borderXlength = 0; + if ( borderYlength < 0 ) borderYlength = 0; + if ( borderZlength < 0 ) borderZlength = 0; + } + + /* + * Tue Jul 6 19:15:15 MET DST 1999 (gregoire Malandain) + * changes 3 x dimx -> dimx, dimy, dimz + */ + lengthX = dimx + 2 * borderXlength; + lengthY = dimy + 2 * borderYlength; + lengthZ = dimz + 2 * borderZlength; + maxLengthline = lengthX; + if ( maxLengthline < lengthY ) maxLengthline = lengthY; + if ( maxLengthline < lengthZ ) maxLengthline = lengthZ; + if ( maxLengthline <= 0 ) { + if ( _VERBOSE_ > 0 ) + fprintf( stderr, " Error in %s: unable to deal with dimensions = 0.\n", proc ); + if ( (typeOut != CGAL_FLOAT) && (typeOut != CGAL_DOUBLE) ) + free( bufferResult ); + return( EXIT_ON_FAILURE ); + } + /* + * Allocations of work arrays. + * We will use them to process each line. + */ + theLine = (double*)malloc( 3 * maxLengthline * sizeof(double) ); + if ( theLine == (double*)NULL ) { + if ( _VERBOSE_ > 0 ) + fprintf( stderr, " Fatal error in %s: unable to allocate auxiliary work arrays.\n", proc ); + if ( (typeOut != CGAL_FLOAT) && (typeOut != CGAL_DOUBLE) ) + free( bufferResult ); + return( EXIT_ON_FAILURE ); + } + resLine = theLine + maxLengthline; + tmpLine = resLine + maxLengthline; + + /* + * From now, + * typeToBeProcessed is either CGAL_FLOAT or CGAL_DOUBLE + * so is typeResult. + */ + + + /* + * Processing along X. + */ + if ( dimx > 4 ) + if (derivatives[0] != NODERIVATIVE) + if (filterCoefs[0] > 0.0) { + + if ( _VERBOSE_ != 0 ) + fprintf( stderr, " %s: processing along X.\n", proc ); + + RFC = InitRecursiveCoefficients( (double)filterCoefs[0], filterType, derivatives[0] ); + + if ( RFC == NULL ) { + if ( _VERBOSE_ != 0 ) + fprintf( stderr, " %s: unable to allocate coefficients\n", proc ); + if ( (typeOut != CGAL_FLOAT) && (typeOut != CGAL_DOUBLE) ) + free( bufferResult ); + return( EXIT_ON_FAILURE ); + } + + r64firstPoint = (r64*)bufferToBeProcessed; + r32firstPoint = (r32*)bufferToBeProcessed; + + r64firstPointResult = (r64*)bufferResult; + r32firstPointResult = (r32*)bufferResult; + + offsetLastPoint = borderXlength + dimx - 1; + + theLinePlusBorder = theLine + borderXlength; + resLinePlusBorder = resLine + borderXlength; + + /* + * There are dimz*dimy X lines to be processed. + */ + for ( z=0; z 0 ) { + dbl_pt1 = theLine + borderXlength; dbl_first = *dbl_pt1; + dbl_pt2 = theLine + offsetLastPoint; dbl_last = *dbl_pt2; + for ( x=0; x 4 ) + if (derivatives[1] != NODERIVATIVE) + if (filterCoefs[1] > 0.0) { + + if ( _VERBOSE_ != 0 ) + fprintf( stderr, " %s: processing along Y.\n", proc ); + + RFC = InitRecursiveCoefficients( (double)filterCoefs[1], filterType, derivatives[1] ); + + if ( RFC == NULL ) { + if ( _VERBOSE_ != 0 ) + fprintf( stderr, " %s: unable to allocate coefficients\n", proc ); + if ( (typeOut != CGAL_FLOAT) && (typeOut != CGAL_DOUBLE) ) + free( bufferResult ); + return( EXIT_ON_FAILURE ); + } + + r64firstPoint = (r64*)bufferToBeProcessed; + r32firstPoint = (r32*)bufferToBeProcessed; + + r64firstPointResult = (r64*)bufferResult; + r32firstPointResult = (r32*)bufferResult; + + offsetLastPoint = borderYlength + dimy - 1; + offsetNextFirstPoint = dimx * dimy - dimx; + + theLinePlusBorder = theLine + borderYlength; + resLinePlusBorder = resLine + borderYlength; + + /* + * There are dimz*dimx Y lines to be processed. + */ + for ( z=0; z 0 ) { + dbl_pt1 = theLine + borderYlength; dbl_first = *dbl_pt1; + dbl_pt2 = theLine + offsetLastPoint; dbl_last = *dbl_pt2; + for ( y=0; y 4 ) + if (derivatives[2] != NODERIVATIVE) + if (filterCoefs[2] > 0.0) { + + if ( _VERBOSE_ != 0 ) + fprintf( stderr, " %s: processing along Z.\n", proc ); + + RFC = InitRecursiveCoefficients( (double)filterCoefs[2], filterType, derivatives[2] ); + + if ( RFC == NULL ) { + if ( _VERBOSE_ != 0 ) + fprintf( stderr, " %s: unable to allocate coefficients\n", proc ); + if ( (typeOut != CGAL_FLOAT) && (typeOut != CGAL_DOUBLE) ) + free( bufferResult ); + return( EXIT_ON_FAILURE ); + } + + r64firstPoint = (r64*)bufferToBeProcessed; + r32firstPoint = (r32*)bufferToBeProcessed; + + offsetLastPoint = borderZlength + dimz - 1; + + r64firstPointResult = (r64*)bufferResult; + r32firstPointResult = (r32*)bufferResult; + + offsetLastPoint = borderZlength + dimz - 1; + + theLinePlusBorder = theLine + borderYlength; + resLinePlusBorder = resLine + borderYlength; + + /* + * There are dimy*dimx Z lines to be processed. + */ + for ( y=0; y 0 ) { + dbl_pt1 = theLine + borderZlength; dbl_first = *dbl_pt1; + dbl_pt2 = theLine + offsetLastPoint; dbl_last = *dbl_pt2; + for ( z=0; z -#include -#include - - +#ifndef CGAL_HEADER_ONLY #include "recline.h" +#include "recline_impl.h" -static int _VERBOSE_RECLINE_ = 0; - -#define EXIT_ON_FAILURE 0 -#define EXIT_ON_SUCCESS 1 - - - -void printRecursiveCoefficients( RFcoefficientType *RFC ) -{ - printf( "denominator:\n" ); - printf( "%f %f %f %f\n", RFC->sd1, RFC->sd2, RFC->sd3, RFC->sd4 ); - printf( "positive numerator:\n" ); - printf( "%f %f %f %f\n", RFC->sp0, RFC->sp1, RFC->sp2, RFC->sp3 ); - printf( "negative numerator:\n" ); - printf( "%f %f %f %f %f\n", RFC->sn0, RFC->sn1, RFC->sn2, RFC->sn3, RFC->sn4 ); - printf( "\n" ); -} - - -RFcoefficientType * InitRecursiveCoefficients( double x, - recursiveFilterType type_filter, - derivativeOrder derivative ) -{ - const char *proc="InitRecursiveCoefficients"; - double ex, k1, k2; - double a0, a1, c0, c1, omega0, omega1, b0, b1; - double cos0, sin0, cos1, sin1; - double sumA=0.0, sumC=0.0, aux; - - RFcoefficientType *RFC = NULL; - RFC = (RFcoefficientType *)malloc( sizeof(RFcoefficientType) ); - if ( RFC == NULL ) { - if ( _VERBOSE_RECLINE_ != 0 ) - fprintf( stderr, "%s: allocation failed\n", proc ); - return( NULL ); - } - - RFC->sd1 = RFC->sd2 = RFC->sd3 = RFC->sd4 = 0.0; - RFC->sp0 = RFC->sp1 = RFC->sp2 = RFC->sp3 = 0.0; - RFC->sn0 = RFC->sn1 = RFC->sn2 = RFC->sn3 = RFC->sn4 = 0.0; - - RFC->type_filter = UNKNOWN_FILTER; - RFC->derivative = NODERIVATIVE; - - ex = k1 = k2 = 0.0; - a0 = a1 = c0 = c1 = 0.0; - b0 = b1 = omega0 = omega1 = 0.0; - - /*--- Selon le type de filtrage (filtres de Deriche, - ou approximation de la gaussienne), x designe - soit alpha, soit sigma ---*/ - - switch ( type_filter ) { - - case GAUSSIAN_FIDRICH : - - if ( x < 0.1 ) { - if ( _VERBOSE_RECLINE_ != 0 ) { - fprintf( stderr, "%s: improper value of coefficient (should be >= 0.1).\n", proc ); - } - free( RFC ); - return( NULL ); - } - - switch ( derivative ) { - default : - if ( _VERBOSE_RECLINE_ != 0 ) { - fprintf( stderr, "%s: improper value of derivative order.\n", proc ); - } - free( RFC ); - return( NULL ); - case DERIVATIVE_0 : - a0 = 0.6570033214 / x; - a1 = 1.978946687 / x; - c0 = -0.2580640608 / x; - c1 = -0.2391206463 / x; - omega0 = 0.6512453378; - omega1 = 2.05339943; - b0 = 1.906154352; - b1 = 1.881305409; - break; - case DERIVATIVE_1 : - case DERIVATIVE_1_CONTOURS : - a0 = -0.1726729496 / x; - a1 = -2.003565572 / x; - c0 = 0.1726730777 / x; - c1 = 0.4440126835 / x; - b0 = 1.560644213; - b1 = 1.594202256; - omega0 = 0.6995461735; - omega1 = 2.144671764; - break; - case DERIVATIVE_2 : - a0 = -0.7241334169 / x; - a1 = 1.688628765 / x; - c0 = 0.3251949838 / x; - c1 = -0.7211796018 / x; - b0 = 1.294951143; - b1 = 1.427007123; - omega0 = 0.7789803775; - omega1 = 2.233566862; - break; - case DERIVATIVE_3 : - a0 = 1.285774106 / x; - a1 = -0.2896378408 / x; - c0 = -1.28577129 / x; - c1 = 0.26249833 / x; - b0 = 1.01162886; - b1 = 1.273344739; - omega0 = 0.9474270928; - omega1 = 2.337607006; - break; - } - - omega0 /= x; sin0 = sin( omega0 ); cos0 = cos( omega0 ); - omega1 /= x; sin1 = sin( omega1 ); cos1 = cos( omega1 ); - b0 /= x; - b1 /= x; - - RFC->sp0 = a0 + c0; - RFC->sp1 = exp( -b1 ) * (c1 * sin1 - (c0 + 2 * a0) * cos1); - RFC->sp1 += exp( -b0 ) * (a1 * sin0 - (2 * c0 + a0) * cos0); - RFC->sp2 = 2.0 * exp( -b0 - b1 ) - * ((a0 + c0) * cos1 * cos0 - cos1 * a1 * sin0 - cos0 * c1 * sin1); - RFC->sp2 += c0 * exp( -2.0 * b0 ) + a0 * exp( -2.0 * b1 ); - RFC->sp3 = exp( -b1 - 2.0 * b0 ) * (c1 * sin1 - c0 * cos1); - RFC->sp3 += exp( -b0 - 2.0 * b1 ) * (a1 * sin0 - a0 * cos0); - - RFC->sd1 = -2.0 * exp( -b1 ) * cos1 - 2.0 * exp( -b0 ) * cos0; - RFC->sd2 = 4.0 * cos1 * cos0 * exp( -b0 - b1 ) - + exp( -2.0 * b1 ) + exp( -2.0 * b0 ); - RFC->sd3 = -2.0 * cos0 * exp( -b0 - 2.0 * b1 ) - - 2.0 * cos1 * exp( -b1 - 2.0 * b0 ); - RFC->sd4 = exp( -2.0 * b0 - 2.0 * b1 ); - - switch ( derivative ) { - default : - if ( _VERBOSE_RECLINE_ != 0 ) { - fprintf( stderr, "%s: improper value of derivative order.\n", proc ); - } - free( RFC ); - return( NULL ); - case DERIVATIVE_0 : - case DERIVATIVE_2 : - RFC->sn1 = RFC->sp1 - RFC->sd1 * RFC->sp0; - RFC->sn2 = RFC->sp2 - RFC->sd2 * RFC->sp0; - RFC->sn3 = RFC->sp3 - RFC->sd3 * RFC->sp0; - RFC->sn4 = - RFC->sd4 * RFC->sp0; - break; - case DERIVATIVE_1 : - case DERIVATIVE_1_CONTOURS : - case DERIVATIVE_3 : - RFC->sn1 = - RFC->sp1 + RFC->sd1 * RFC->sp0; - RFC->sn2 = - RFC->sp2 + RFC->sd2 * RFC->sp0; - RFC->sn3 = - RFC->sp3 + RFC->sd3 * RFC->sp0; - RFC->sn4 = RFC->sd4 * RFC->sp0; - } - - RFC->type_filter = type_filter; - RFC->derivative = derivative; - break; - - case GAUSSIAN_DERICHE : - - if ( x < 0.1 ) { - if ( _VERBOSE_RECLINE_ != 0 ) { - fprintf( stderr, "%s: improper value of coefficient (should be >= 0.1).\n", proc ); - } - free( RFC ); - return( NULL ); - } - - switch ( derivative ) { - default : - if ( _VERBOSE_RECLINE_ != 0 ) { - fprintf( stderr, "%s: switch to default coefficients (smoothing).\n", proc ); - } - derivative = DERIVATIVE_0; - case DERIVATIVE_0 : - a0 = 1.68; - omega0 = 0.6318; - a1 = 3.735; - b0 = 1.783; - c0 = -0.6803; - omega1 = 1.997; - c1 = -0.2598; - b1 = 1.723; - break; - case DERIVATIVE_1 : - case DERIVATIVE_1_CONTOURS : - a0 = -0.6472; - omega0 = 0.6719; - a1 = -4.531; - b0 = 1.527; - c0 = 0.6494; - omega1 = 2.072; - c1 = 0.9557; - b1 = 1.516; - break; - case DERIVATIVE_2 : - a0 = -1.331; - omega0 = 0.748; - a1 = 3.661; - b0 = 1.24; - c0 = 0.3225; - omega1 = 2.166; - c1 = -1.738; - b1 = 1.314; - } - - omega0 /= x; sin0 = sin( omega0 ); cos0 = cos( omega0 ); - omega1 /= x; sin1 = sin( omega1 ); cos1 = cos( omega1 ); - b0 /= x; - b1 /= x; - - /*--- normalisation ---*/ - switch ( derivative ) { - default : - case DERIVATIVE_0 : - sumA = 2.0 * a1 * exp( b0 ) * cos0 * cos0 - a0 * sin0 * exp( 2.0 * b0 ); - sumA += a0 * sin0 - 2.0 * a1 * exp( b0 ); - sumA /= ( 2.0 * cos0 * exp( b0 ) - exp( 2.0 * b0 ) - 1 ) * sin0; - sumC = 2.0 * c1 * exp( b1 ) * cos1 * cos1 - c0 * sin1 * exp( 2.0 * b1 ); - sumC += c0 * sin1 - 2.0 * c1 * exp( b1 ); - sumC /= ( 2.0 * cos1 * exp( b1 ) - exp( 2.0 * b1 ) - 1 ) * sin1; - break; - case DERIVATIVE_1 : - aux = exp( 4.0 * b0 ) - 4.0 * cos0 * exp( 3.0 * b0 ); - aux += 2.0 * exp( 2.0 * b0 ) + 4.0 * cos0 * cos0 * exp( 2.0 * b0 ); - aux += 1.0 - 4.0 * cos0 * exp( b0 ); - sumA = a0 * cos0 - a1 * sin0 + a1 * sin0 * exp( 2.0 * b0 ); - sumA += a0 * cos0 * exp( 2.0 * b0 ) - 2.0 * a0 * exp( b0 ); - sumA *= exp( b0 ) / aux; - aux = exp( 4.0 * b1 ) - 4.0 * cos1 * exp( 3.0 * b1 ); - aux += 2.0 * exp( 2.0 * b1 ) + 4.0 * cos1 * cos1 * exp( 2.0 * b1 ); - aux += 1.0 - 4.0 * cos1 * exp( b1 ); - sumC = c0 * cos1 - c1 * sin1 + c1 * sin1 * exp( 2.0 * b1 ); - sumC += c0 * cos1 * exp( 2.0 * b1 ) - 2.0 * c0 * exp( b1 ); - sumC *= exp( b1 ) / aux; - /*--- on multiplie les sommes par 2 car on n'a calcule que des demi-sommes - et on change le signe car la somme doit etre egale a -1 ---*/ - sumA *= (-2.0); - sumC *= (-2.0); - break; - case DERIVATIVE_1_CONTOURS : - /*--- la somme de 1 a l'infini est egale a 1 : cela introduit - un petit biais (reponse un rien superieur a la hauteur du step). - Avec une somme de 0 a l'infini, c'est pire ---*/ - sumA = a1 * exp( b0 ) - a1 * cos0 * cos0 * exp( b0 ); - sumA += a0 * cos0 * sin0 * exp( b0 ) - a0 * sin0; - sumA /= sin0 * ( 2.0 * cos0 * exp( b0 ) - exp( 2.0 * b0 ) - 1 ); - sumC = c1 * exp( b1 ) - c1 * cos1 * cos1 * exp( b1 ); - sumC += c0 * cos1 * sin1 * exp( b1 ) - c0 * sin1; - sumC /= sin1 * ( 2.0 * cos1 * exp( b1 ) - exp( 2.0 * b1 ) - 1 ); - break; - case DERIVATIVE_2 : - aux = 12.0 * cos0 * exp( 3.0 * b0 ) - 3.0 * exp( 2.0 * b0 ); - aux += 8.0 * cos0 * cos0 * cos0 * exp( 3.0 * b0 ) - - 12.0 * cos0 * cos0 * exp( 4.0 * b0 ); - aux -= 3.0 * exp( 4.0 * b0 ); - aux += 6.0 * cos0 * exp( 5.0 * b0 ) - exp( 6.0 * b0 ) - + 6.0 * cos0 * exp( b0 ); - aux -= ( 1.0 + 12.0 * cos0 * cos0 * exp( 2.0 * b0 ) ); - sumA = 4.0 * a0 * sin0 * exp( 3.0 * b0 ) - + a1 * cos0 * cos0 * exp( 4.0 * b0 ); - sumA -= ( 4.0 * a0 * sin0 * exp( b0 ) - + 6.0 * a1 * cos0 * cos0 * exp( 2.0 * b0 ) ); - sumA += 2.0 * a1 * cos0 * cos0 * cos0 * exp( b0 ) - - 2.0 * a1 * cos0 * exp( b0 ); - sumA += 2.0 * a1 * cos0 * cos0 * cos0 * exp( 3.0 * b0 ) - - 2.0 * a1 * cos0 * exp( 3.0 * b0 ); - sumA += a1 * cos0 * cos0 - a1 * exp( 4.0 * b0 ); - sumA += 2.0 * a0 * sin0 * cos0 * cos0 * exp( b0 ) - - 2.0 * a0 * sin0 * cos0 * cos0 * exp( 3.0 * b0 ); - sumA -= ( a0 * sin0 * cos0 * exp( 4.0 * b0 ) + a1 ); - sumA += 6.0 * a1 * exp( 2.0 * b0 ) + a0 * cos0 * sin0; - sumA *= 2.0 * exp( b0 ) / ( aux * sin0 ); - aux = 12.0 * cos1 * exp( 3.0 * b1 ) - 3.0 * exp( 2.0 * b1 ); - aux += 8.0 * cos1 * cos1 * cos1 * exp( 3.0 * b1 ) - - 12.0 * cos1 * cos1 * exp( 4.0 * b1 ); - aux -= 3.0 * exp( 4.0 * b1 ); - aux += 6.0 * cos1 * exp( 5.0 * b1 ) - exp( 6.0 * b1 ) - + 6.0 * cos1 * exp( b1 ); - aux -= ( 1.0 + 12.0 * cos1 * cos1 * exp( 2.0 * b1 ) ); - sumC = 4.0 * c0 * sin1 * exp( 3.0 * b1 ) - + c1 * cos1 * cos1 * exp( 4.0 * b1 ); - sumC -= ( 4.0 * c0 * sin1 * exp( b1 ) - + 6.0 * c1 * cos1 * cos1 * exp( 2.0 * b1 ) ); - sumC += 2.0 * c1 * cos1 * cos1 * cos1 * exp( b1 ) - - 2.0 * c1 * cos1 * exp( b1 ); - sumC += 2.0 * c1 * cos1 * cos1 * cos1 * exp( 3.0 * b1 ) - - 2.0 * c1 * cos1 * exp( 3.0 * b1 ); - sumC += c1 * cos1 * cos1 - c1 * exp( 4.0 * b1 ); - sumC += 2.0 * c0 * sin1 * cos1 * cos1 * exp( b1 ) - - 2.0 * c0 * sin1 * cos1 * cos1 * exp( 3.0 * b1 ); - sumC -= ( c0 * sin1 * cos1 * exp( 4.0 * b1 ) + c1 ); - sumC += 6.0 * c1 * exp( 2.0 * b1 ) + c0 * cos1 * sin1; - sumC *= 2.0 * exp( b1 ) / ( aux * sin1 ); - /*--- on divise les sommes par 2 (la somme doit etre egale a 2) ---*/ - sumA /= 2; - sumC /= 2; - } - a0 /= ( sumA + sumC ); - a1 /= ( sumA + sumC ); - c0 /= ( sumA + sumC ); - c1 /= ( sumA + sumC ); - - /*--- coefficients du calcul recursif ---*/ - RFC->sp0 = a0 + c0; - RFC->sp1 = exp( -b1 ) * (c1 * sin1 - (c0 + 2 * a0) * cos1); - RFC->sp1 += exp( -b0 ) * (a1 * sin0 - (2 * c0 + a0) * cos0); - RFC->sp2 = 2.0 * exp( -b0 - b1 ) - * ((a0 + c0) * cos1 * cos0 - cos1 * a1 * sin0 - cos0 * c1 * sin1); - RFC->sp2 += c0 * exp( -2.0 * b0 ) + a0 * exp( -2.0 * b1 ); - RFC->sp3 = exp( -b1 - 2.0 * b0 ) * (c1 * sin1 - c0 * cos1); - RFC->sp3 += exp( -b0 - 2.0 * b1 ) * (a1 * sin0 - a0 * cos0); - - RFC->sd1 = -2.0 * exp( -b1 ) * cos1 - 2.0 * exp( -b0 ) * cos0; - RFC->sd2 = 4.0 * cos1 * cos0 * exp( -b0 - b1 ) - + exp( -2.0 * b1 ) + exp( -2.0 * b0 ); - RFC->sd3 = -2.0 * cos0 * exp( -b0 - 2.0 * b1 ) - - 2.0 * cos1 * exp( -b1 - 2.0 * b0 ); - RFC->sd4 = exp( -2.0 * b0 - 2.0 * b1 ); - - switch ( derivative ) { - default : - case DERIVATIVE_0 : - case DERIVATIVE_2 : - RFC->sn1 = RFC->sp1 - RFC->sd1 * RFC->sp0; - RFC->sn2 = RFC->sp2 - RFC->sd2 * RFC->sp0; - RFC->sn3 = RFC->sp3 - RFC->sd3 * RFC->sp0; - RFC->sn4 = - RFC->sd4 * RFC->sp0; - break; - case DERIVATIVE_1 : - case DERIVATIVE_1_CONTOURS : - case DERIVATIVE_3 : - RFC->sn1 = - RFC->sp1 + RFC->sd1 * RFC->sp0; - RFC->sn2 = - RFC->sp2 + RFC->sd2 * RFC->sp0; - RFC->sn3 = - RFC->sp3 + RFC->sd3 * RFC->sp0; - RFC->sn4 = RFC->sd4 * RFC->sp0; - } - - RFC->type_filter = type_filter; - RFC->derivative = derivative; - break; - - - - default : - if ( _VERBOSE_RECLINE_ != 0 ) { - fprintf( stderr, "%s: switch to default recursive filter (Deriche's filters).\n", proc ); - } - type_filter = ALPHA_DERICHE; - case ALPHA_DERICHE : - - if ( (x < 0.1) || (x > 1.9) ) { - if ( _VERBOSE_RECLINE_ != 0 ) { - fprintf( stderr, "%s: improper value of coefficient (should be >= 0.1 and <= 1.9).\n", proc ); - } - free( RFC ); - return( NULL ); - } - ex = exp( (-x) ); - - switch ( derivative ) { - default : - if ( _VERBOSE_RECLINE_ != 0 ) { - fprintf( stderr, "%s: switch to default coefficients (smoothing).\n", proc ); - } - derivative = DERIVATIVE_0; - case DERIVATIVE_0 : - RFC->sp0 = (1.0 - ex) * (1.0 - ex) / (1.0 + 2.0 * x * ex - ex * ex); - RFC->sp1 = RFC->sp0 * (x - 1.0) * ex; - RFC->sn1 = RFC->sp0 * (x + 1.0) * ex; - RFC->sn2 = (- RFC->sp0) * ex * ex; - RFC->sd1 = (- 2.0) * ex; - RFC->sd2 = ex * ex; - break; - case DERIVATIVE_1 : - RFC->sp1 = - (1.0 - ex) * (1.0 - ex) * (1.0 - ex) / (2.0 * (1.0 + ex)); - RFC->sn1 = (- RFC->sp1); - RFC->sd1 = (- 2.0) * ex; - RFC->sd2 = ex * ex; - break; - case DERIVATIVE_1_CONTOURS : - RFC->sp1 = - (1.0 - ex) * (1.0 - ex); - RFC->sn1 = (- RFC->sp1); - RFC->sd1 = (- 2.0) * ex; - RFC->sd2 = ex * ex; - break; - case DERIVATIVE_2 : - k1 = (- 2.0) * (1.0 - ex) * (1.0 - ex) * (1.0 - ex); - k1 /= (1.0 + ex) * (1.0 + ex) * (1.0 + ex); - k2 = (1.0 - ex * ex) / (2.0 * ex); - RFC->sp0 = k1; - RFC->sp1 = (- k1) * (1.0 + k2) * ex; - RFC->sn1 = k1 * (1.0 - k2) * ex; - RFC->sn2 = (- k1) * ex * ex; - RFC->sd1 = (- 2.0) * ex; - RFC->sd2 = ex * ex; - break; - case DERIVATIVE_3 : - k1 = (1.0 + x) * ex + (x - 1.0); - k2 = (1.0 - ex) / k1; - k1 *= (1.0 - ex) * (1.0 - ex) * (1.0 - ex) * (1.0 - ex); - k1 /= 2.0 * x * x * ex * ex; - k1 /= ex + 1.0; - RFC->sp0 = k1 * x * (k2 + 1.0); - RFC->sp1 = (- k1) * x * (1.0 + k2 + k2*x) * ex; - RFC->sn0 = (- RFC->sp0); - RFC->sn1 = (- RFC->sp1); - RFC->sd1 = (- 2.0) * ex; - RFC->sd2 = ex * ex; - } - RFC->type_filter = type_filter; - RFC->derivative = derivative; - } - - return( RFC ); -} - - - -int RecursiveFilter1D( RFcoefficientType *RFC, - double *in, - double *out, - double *work1, - double *work2, - int dim ) -{ - const char *proc="RecursiveFilter1D"; - register double rp0, rp1, rp2, rp3; - register double rd1, rd2, rd3, rd4; - register double rn0, rn1, rn2, rn3, rn4; - register int i; - register double *w0, *w1, *w2, *w3, *w4; - register double *d0, *d1, *d2, *d3, *d4; - - if ( RFC->type_filter == UNKNOWN_FILTER ) { - if ( _VERBOSE_RECLINE_ != 0 ) - fprintf( stderr, "%s: unknown type of recursive filter.\n", proc ); - return( EXIT_ON_FAILURE ); - } - if ( RFC->derivative == NODERIVATIVE ) { - if ( _VERBOSE_RECLINE_ != 0 ) - fprintf( stderr, "%s: unknown type of derivative.\n", proc ); - return( EXIT_ON_FAILURE ); - } - - rd1 = rd2 = rd3 = rd4 = 0.0; - rp0 = rp1 = rp2 = rp3 = 0.0; - rn0 = rn1 = rn2 = rn3 = rn4 = 0.0; - - switch( RFC->type_filter ) { - default : - if ( _VERBOSE_RECLINE_ != 0 ) - fprintf( stderr, "%s: unknown type of recursive filter.\n", proc ); - return( EXIT_ON_FAILURE ); - case GAUSSIAN_FIDRICH : - case GAUSSIAN_DERICHE : - /*--- filtrage generique d'ordre 4 ---*/ - rp0 = RFC->sp0; rp1 = RFC->sp1; rp2 = RFC->sp2; rp3 = RFC->sp3; - rd1 = RFC->sd1; rd2 = RFC->sd2; rd3 = RFC->sd3; rd4 = RFC->sd4; - rn1 = RFC->sn1; rn2 = RFC->sn2; rn3 = RFC->sn3; rn4 = RFC->sn4; - - /* on positionne les pointeurs - */ - w4 = work1; w3 = w4+1; w2 = w3+1; w1 = w2+1; w0 = w1+1; - d3 = in+1; d2 = d3+1; d1 = d2+1; d0 = d1+1; - /*--- calcul de y+ ---*/ - *(w4) = rp0 * *(in); - *(w3) = rp0 * *(d3) + rp1 * *(in) - - rd1 * *(w4); - *(w2) = rp0 * *(d2) + rp1 * *(d3) + rp2 * *(in) - - rd1 * *(w3) - rd2 * *(w4); - *(w1) = rp0 * *(d1) + rp1 * *(d2) + rp2 * *(d3) + rp3 * *(in) - - rd1 * *(w2) - rd2 * *(w3) - rd3 * *(w4); - for (i=4; i=0; i--,w0--,w1--,w2--,w3--,w4--,d1--,d2--,d3--,d4--) - *(w0) = rn1 * *(d1) + rn2 * *(d2) + rn3 * *(d3) + rn4 * *(d4) - - rd1 * *(w1) - rd2 * *(w2) - rd3 * *(w3) - rd4 * *(w4); - - /*--- calcul final ---*/ - w1 = work1; w2 = work2; d0 = out; - for (i=0 ; iderivative ) { - default : - case DERIVATIVE_0 : - case DERIVATIVE_2 : - - rp0 = RFC->sp0; rp1 = RFC->sp1; - rd1 = RFC->sd1; rd2 = RFC->sd2; - rn1 = RFC->sn1; rn2 = RFC->sn2; - - /* on positionne les pointeurs - */ - w2 = work1; w1 = w2+1; w0 = w1+1; - d1 = in+1; d0 = d1+1; - /*--- calcul de y+ ---*/ - *(w2) = rp0 * *(in); - *(w1) = rp0 * *(d1) + rp1 * *(in) - - rd1 * *(w2); - for (i=2; i=0; i--,w0--,w1--,w2--,d1--,d2--) - *(w0) = rn1 * *(d1) + rn2 * *(d2) - - rd1 * *(w1) - rd2 * *(w2); - - /*--- calcul final ---*/ - w1 = work1; w2 = work2; d0 = out; - for (i=0 ; isp1; - rn1 = RFC->sn1; - rd1 = RFC->sd1; rd2 = RFC->sd2; - - /* on positionne les pointeurs - */ - w2 = work1; w1 = w2+1; w0 = w1+1; - d1 = in+1; - /*--- calcul de y+ ---*/ - *(w2) = 0.0; - *(w1) = rp1 * *(in); - for (i=2; i=0; i--,w0--,w1--,w2--,d1--) - *(w0) = rn1 * *(d1) - - rd1 * *(w1) - rd2 * *(w2); - - /*--- calcul final ---*/ - w1 = work1; w2 = work2; d0 = out; - for (i=0 ; isp0; rp1 = RFC->sp1; - rd1 = RFC->sd1; rd2 = RFC->sd2; - rn0 = RFC->sn0; rn1 = RFC->sn1; - - w2 = work1; w1 = w2+1; w0 = w1+1; - d1 = in+1; d0 = d1+1; - /*--- calcul de y+ ---*/ - *(w2) = rp0 * *(in); - *(w1) = rp0 * *(d1) + rp1 * *(in) - - rd1 * *(w2); - for (i=2; i=0; i--,w0--,w1--,w2--,d0--,d1--) - *(w0) = rn0 * *(d0) + rn1 * *(d1) - - rd1 * *(w1) - rd2 * *(w2); - - /*--- calcul final ---*/ - w1 = work1; w2 = work2; d0 = out; - for (i=0 ; i +#include +#include + + + +#ifdef CGAL_HEADER_ONLY + +inline int& get_static_verbose_recline() +{ + static int _VERBOSE_RECLINE_ = 0; + return _VERBOSE_RECLINE_; +} + +#else // CGAL_HEADER_ONLY + +static int _VERBOSE_RECLINE_ = 0; + +inline int& get_static_verbose_recline() +{ return _VERBOSE_RECLINE_; } + +#endif // CGAL_HEADER_ONLY + + +#define EXIT_ON_FAILURE 0 +#define EXIT_ON_SUCCESS 1 + + + +CGAL_INLINE_FUNCTION +void printRecursiveCoefficients( RFcoefficientType *RFC ) +{ + printf( "denominator:\n" ); + printf( "%f %f %f %f\n", RFC->sd1, RFC->sd2, RFC->sd3, RFC->sd4 ); + printf( "positive numerator:\n" ); + printf( "%f %f %f %f\n", RFC->sp0, RFC->sp1, RFC->sp2, RFC->sp3 ); + printf( "negative numerator:\n" ); + printf( "%f %f %f %f %f\n", RFC->sn0, RFC->sn1, RFC->sn2, RFC->sn3, RFC->sn4 ); + printf( "\n" ); +} + + +CGAL_INLINE_FUNCTION +RFcoefficientType * InitRecursiveCoefficients( double x, + recursiveFilterType type_filter, + derivativeOrder derivative ) +{ + const char *proc="InitRecursiveCoefficients"; + double ex, k1, k2; + double a0, a1, c0, c1, omega0, omega1, b0, b1; + double cos0, sin0, cos1, sin1; + double sumA=0.0, sumC=0.0, aux; + + RFcoefficientType *RFC = NULL; + RFC = (RFcoefficientType *)malloc( sizeof(RFcoefficientType) ); + if ( RFC == NULL ) { + if ( get_static_verbose_recline() != 0 ) + fprintf( stderr, "%s: allocation failed\n", proc ); + return( NULL ); + } + + RFC->sd1 = RFC->sd2 = RFC->sd3 = RFC->sd4 = 0.0; + RFC->sp0 = RFC->sp1 = RFC->sp2 = RFC->sp3 = 0.0; + RFC->sn0 = RFC->sn1 = RFC->sn2 = RFC->sn3 = RFC->sn4 = 0.0; + + RFC->type_filter = UNKNOWN_FILTER; + RFC->derivative = NODERIVATIVE; + + ex = k1 = k2 = 0.0; + a0 = a1 = c0 = c1 = 0.0; + b0 = b1 = omega0 = omega1 = 0.0; + + /*--- Selon le type de filtrage (filtres de Deriche, + ou approximation de la gaussienne), x designe + soit alpha, soit sigma ---*/ + + switch ( type_filter ) { + + case GAUSSIAN_FIDRICH : + + if ( x < 0.1 ) { + if ( get_static_verbose_recline() != 0 ) { + fprintf( stderr, "%s: improper value of coefficient (should be >= 0.1).\n", proc ); + } + free( RFC ); + return( NULL ); + } + + switch ( derivative ) { + default : + if ( get_static_verbose_recline() != 0 ) { + fprintf( stderr, "%s: improper value of derivative order.\n", proc ); + } + free( RFC ); + return( NULL ); + case DERIVATIVE_0 : + a0 = 0.6570033214 / x; + a1 = 1.978946687 / x; + c0 = -0.2580640608 / x; + c1 = -0.2391206463 / x; + omega0 = 0.6512453378; + omega1 = 2.05339943; + b0 = 1.906154352; + b1 = 1.881305409; + break; + case DERIVATIVE_1 : + case DERIVATIVE_1_CONTOURS : + a0 = -0.1726729496 / x; + a1 = -2.003565572 / x; + c0 = 0.1726730777 / x; + c1 = 0.4440126835 / x; + b0 = 1.560644213; + b1 = 1.594202256; + omega0 = 0.6995461735; + omega1 = 2.144671764; + break; + case DERIVATIVE_2 : + a0 = -0.7241334169 / x; + a1 = 1.688628765 / x; + c0 = 0.3251949838 / x; + c1 = -0.7211796018 / x; + b0 = 1.294951143; + b1 = 1.427007123; + omega0 = 0.7789803775; + omega1 = 2.233566862; + break; + case DERIVATIVE_3 : + a0 = 1.285774106 / x; + a1 = -0.2896378408 / x; + c0 = -1.28577129 / x; + c1 = 0.26249833 / x; + b0 = 1.01162886; + b1 = 1.273344739; + omega0 = 0.9474270928; + omega1 = 2.337607006; + break; + } + + omega0 /= x; sin0 = sin( omega0 ); cos0 = cos( omega0 ); + omega1 /= x; sin1 = sin( omega1 ); cos1 = cos( omega1 ); + b0 /= x; + b1 /= x; + + RFC->sp0 = a0 + c0; + RFC->sp1 = exp( -b1 ) * (c1 * sin1 - (c0 + 2 * a0) * cos1); + RFC->sp1 += exp( -b0 ) * (a1 * sin0 - (2 * c0 + a0) * cos0); + RFC->sp2 = 2.0 * exp( -b0 - b1 ) + * ((a0 + c0) * cos1 * cos0 - cos1 * a1 * sin0 - cos0 * c1 * sin1); + RFC->sp2 += c0 * exp( -2.0 * b0 ) + a0 * exp( -2.0 * b1 ); + RFC->sp3 = exp( -b1 - 2.0 * b0 ) * (c1 * sin1 - c0 * cos1); + RFC->sp3 += exp( -b0 - 2.0 * b1 ) * (a1 * sin0 - a0 * cos0); + + RFC->sd1 = -2.0 * exp( -b1 ) * cos1 - 2.0 * exp( -b0 ) * cos0; + RFC->sd2 = 4.0 * cos1 * cos0 * exp( -b0 - b1 ) + + exp( -2.0 * b1 ) + exp( -2.0 * b0 ); + RFC->sd3 = -2.0 * cos0 * exp( -b0 - 2.0 * b1 ) + - 2.0 * cos1 * exp( -b1 - 2.0 * b0 ); + RFC->sd4 = exp( -2.0 * b0 - 2.0 * b1 ); + + switch ( derivative ) { + default : + if ( get_static_verbose_recline() != 0 ) { + fprintf( stderr, "%s: improper value of derivative order.\n", proc ); + } + free( RFC ); + return( NULL ); + case DERIVATIVE_0 : + case DERIVATIVE_2 : + RFC->sn1 = RFC->sp1 - RFC->sd1 * RFC->sp0; + RFC->sn2 = RFC->sp2 - RFC->sd2 * RFC->sp0; + RFC->sn3 = RFC->sp3 - RFC->sd3 * RFC->sp0; + RFC->sn4 = - RFC->sd4 * RFC->sp0; + break; + case DERIVATIVE_1 : + case DERIVATIVE_1_CONTOURS : + case DERIVATIVE_3 : + RFC->sn1 = - RFC->sp1 + RFC->sd1 * RFC->sp0; + RFC->sn2 = - RFC->sp2 + RFC->sd2 * RFC->sp0; + RFC->sn3 = - RFC->sp3 + RFC->sd3 * RFC->sp0; + RFC->sn4 = RFC->sd4 * RFC->sp0; + } + + RFC->type_filter = type_filter; + RFC->derivative = derivative; + break; + + case GAUSSIAN_DERICHE : + + if ( x < 0.1 ) { + if ( get_static_verbose_recline() != 0 ) { + fprintf( stderr, "%s: improper value of coefficient (should be >= 0.1).\n", proc ); + } + free( RFC ); + return( NULL ); + } + + switch ( derivative ) { + default : + if ( get_static_verbose_recline() != 0 ) { + fprintf( stderr, "%s: switch to default coefficients (smoothing).\n", proc ); + } + derivative = DERIVATIVE_0; + case DERIVATIVE_0 : + a0 = 1.68; + omega0 = 0.6318; + a1 = 3.735; + b0 = 1.783; + c0 = -0.6803; + omega1 = 1.997; + c1 = -0.2598; + b1 = 1.723; + break; + case DERIVATIVE_1 : + case DERIVATIVE_1_CONTOURS : + a0 = -0.6472; + omega0 = 0.6719; + a1 = -4.531; + b0 = 1.527; + c0 = 0.6494; + omega1 = 2.072; + c1 = 0.9557; + b1 = 1.516; + break; + case DERIVATIVE_2 : + a0 = -1.331; + omega0 = 0.748; + a1 = 3.661; + b0 = 1.24; + c0 = 0.3225; + omega1 = 2.166; + c1 = -1.738; + b1 = 1.314; + } + + omega0 /= x; sin0 = sin( omega0 ); cos0 = cos( omega0 ); + omega1 /= x; sin1 = sin( omega1 ); cos1 = cos( omega1 ); + b0 /= x; + b1 /= x; + + /*--- normalisation ---*/ + switch ( derivative ) { + default : + case DERIVATIVE_0 : + sumA = 2.0 * a1 * exp( b0 ) * cos0 * cos0 - a0 * sin0 * exp( 2.0 * b0 ); + sumA += a0 * sin0 - 2.0 * a1 * exp( b0 ); + sumA /= ( 2.0 * cos0 * exp( b0 ) - exp( 2.0 * b0 ) - 1 ) * sin0; + sumC = 2.0 * c1 * exp( b1 ) * cos1 * cos1 - c0 * sin1 * exp( 2.0 * b1 ); + sumC += c0 * sin1 - 2.0 * c1 * exp( b1 ); + sumC /= ( 2.0 * cos1 * exp( b1 ) - exp( 2.0 * b1 ) - 1 ) * sin1; + break; + case DERIVATIVE_1 : + aux = exp( 4.0 * b0 ) - 4.0 * cos0 * exp( 3.0 * b0 ); + aux += 2.0 * exp( 2.0 * b0 ) + 4.0 * cos0 * cos0 * exp( 2.0 * b0 ); + aux += 1.0 - 4.0 * cos0 * exp( b0 ); + sumA = a0 * cos0 - a1 * sin0 + a1 * sin0 * exp( 2.0 * b0 ); + sumA += a0 * cos0 * exp( 2.0 * b0 ) - 2.0 * a0 * exp( b0 ); + sumA *= exp( b0 ) / aux; + aux = exp( 4.0 * b1 ) - 4.0 * cos1 * exp( 3.0 * b1 ); + aux += 2.0 * exp( 2.0 * b1 ) + 4.0 * cos1 * cos1 * exp( 2.0 * b1 ); + aux += 1.0 - 4.0 * cos1 * exp( b1 ); + sumC = c0 * cos1 - c1 * sin1 + c1 * sin1 * exp( 2.0 * b1 ); + sumC += c0 * cos1 * exp( 2.0 * b1 ) - 2.0 * c0 * exp( b1 ); + sumC *= exp( b1 ) / aux; + /*--- on multiplie les sommes par 2 car on n'a calcule que des demi-sommes + et on change le signe car la somme doit etre egale a -1 ---*/ + sumA *= (-2.0); + sumC *= (-2.0); + break; + case DERIVATIVE_1_CONTOURS : + /*--- la somme de 1 a l'infini est egale a 1 : cela introduit + un petit biais (reponse un rien superieur a la hauteur du step). + Avec une somme de 0 a l'infini, c'est pire ---*/ + sumA = a1 * exp( b0 ) - a1 * cos0 * cos0 * exp( b0 ); + sumA += a0 * cos0 * sin0 * exp( b0 ) - a0 * sin0; + sumA /= sin0 * ( 2.0 * cos0 * exp( b0 ) - exp( 2.0 * b0 ) - 1 ); + sumC = c1 * exp( b1 ) - c1 * cos1 * cos1 * exp( b1 ); + sumC += c0 * cos1 * sin1 * exp( b1 ) - c0 * sin1; + sumC /= sin1 * ( 2.0 * cos1 * exp( b1 ) - exp( 2.0 * b1 ) - 1 ); + break; + case DERIVATIVE_2 : + aux = 12.0 * cos0 * exp( 3.0 * b0 ) - 3.0 * exp( 2.0 * b0 ); + aux += 8.0 * cos0 * cos0 * cos0 * exp( 3.0 * b0 ) + - 12.0 * cos0 * cos0 * exp( 4.0 * b0 ); + aux -= 3.0 * exp( 4.0 * b0 ); + aux += 6.0 * cos0 * exp( 5.0 * b0 ) - exp( 6.0 * b0 ) + + 6.0 * cos0 * exp( b0 ); + aux -= ( 1.0 + 12.0 * cos0 * cos0 * exp( 2.0 * b0 ) ); + sumA = 4.0 * a0 * sin0 * exp( 3.0 * b0 ) + + a1 * cos0 * cos0 * exp( 4.0 * b0 ); + sumA -= ( 4.0 * a0 * sin0 * exp( b0 ) + + 6.0 * a1 * cos0 * cos0 * exp( 2.0 * b0 ) ); + sumA += 2.0 * a1 * cos0 * cos0 * cos0 * exp( b0 ) + - 2.0 * a1 * cos0 * exp( b0 ); + sumA += 2.0 * a1 * cos0 * cos0 * cos0 * exp( 3.0 * b0 ) + - 2.0 * a1 * cos0 * exp( 3.0 * b0 ); + sumA += a1 * cos0 * cos0 - a1 * exp( 4.0 * b0 ); + sumA += 2.0 * a0 * sin0 * cos0 * cos0 * exp( b0 ) + - 2.0 * a0 * sin0 * cos0 * cos0 * exp( 3.0 * b0 ); + sumA -= ( a0 * sin0 * cos0 * exp( 4.0 * b0 ) + a1 ); + sumA += 6.0 * a1 * exp( 2.0 * b0 ) + a0 * cos0 * sin0; + sumA *= 2.0 * exp( b0 ) / ( aux * sin0 ); + aux = 12.0 * cos1 * exp( 3.0 * b1 ) - 3.0 * exp( 2.0 * b1 ); + aux += 8.0 * cos1 * cos1 * cos1 * exp( 3.0 * b1 ) + - 12.0 * cos1 * cos1 * exp( 4.0 * b1 ); + aux -= 3.0 * exp( 4.0 * b1 ); + aux += 6.0 * cos1 * exp( 5.0 * b1 ) - exp( 6.0 * b1 ) + + 6.0 * cos1 * exp( b1 ); + aux -= ( 1.0 + 12.0 * cos1 * cos1 * exp( 2.0 * b1 ) ); + sumC = 4.0 * c0 * sin1 * exp( 3.0 * b1 ) + + c1 * cos1 * cos1 * exp( 4.0 * b1 ); + sumC -= ( 4.0 * c0 * sin1 * exp( b1 ) + + 6.0 * c1 * cos1 * cos1 * exp( 2.0 * b1 ) ); + sumC += 2.0 * c1 * cos1 * cos1 * cos1 * exp( b1 ) + - 2.0 * c1 * cos1 * exp( b1 ); + sumC += 2.0 * c1 * cos1 * cos1 * cos1 * exp( 3.0 * b1 ) + - 2.0 * c1 * cos1 * exp( 3.0 * b1 ); + sumC += c1 * cos1 * cos1 - c1 * exp( 4.0 * b1 ); + sumC += 2.0 * c0 * sin1 * cos1 * cos1 * exp( b1 ) + - 2.0 * c0 * sin1 * cos1 * cos1 * exp( 3.0 * b1 ); + sumC -= ( c0 * sin1 * cos1 * exp( 4.0 * b1 ) + c1 ); + sumC += 6.0 * c1 * exp( 2.0 * b1 ) + c0 * cos1 * sin1; + sumC *= 2.0 * exp( b1 ) / ( aux * sin1 ); + /*--- on divise les sommes par 2 (la somme doit etre egale a 2) ---*/ + sumA /= 2; + sumC /= 2; + } + a0 /= ( sumA + sumC ); + a1 /= ( sumA + sumC ); + c0 /= ( sumA + sumC ); + c1 /= ( sumA + sumC ); + + /*--- coefficients du calcul recursif ---*/ + RFC->sp0 = a0 + c0; + RFC->sp1 = exp( -b1 ) * (c1 * sin1 - (c0 + 2 * a0) * cos1); + RFC->sp1 += exp( -b0 ) * (a1 * sin0 - (2 * c0 + a0) * cos0); + RFC->sp2 = 2.0 * exp( -b0 - b1 ) + * ((a0 + c0) * cos1 * cos0 - cos1 * a1 * sin0 - cos0 * c1 * sin1); + RFC->sp2 += c0 * exp( -2.0 * b0 ) + a0 * exp( -2.0 * b1 ); + RFC->sp3 = exp( -b1 - 2.0 * b0 ) * (c1 * sin1 - c0 * cos1); + RFC->sp3 += exp( -b0 - 2.0 * b1 ) * (a1 * sin0 - a0 * cos0); + + RFC->sd1 = -2.0 * exp( -b1 ) * cos1 - 2.0 * exp( -b0 ) * cos0; + RFC->sd2 = 4.0 * cos1 * cos0 * exp( -b0 - b1 ) + + exp( -2.0 * b1 ) + exp( -2.0 * b0 ); + RFC->sd3 = -2.0 * cos0 * exp( -b0 - 2.0 * b1 ) + - 2.0 * cos1 * exp( -b1 - 2.0 * b0 ); + RFC->sd4 = exp( -2.0 * b0 - 2.0 * b1 ); + + switch ( derivative ) { + default : + case DERIVATIVE_0 : + case DERIVATIVE_2 : + RFC->sn1 = RFC->sp1 - RFC->sd1 * RFC->sp0; + RFC->sn2 = RFC->sp2 - RFC->sd2 * RFC->sp0; + RFC->sn3 = RFC->sp3 - RFC->sd3 * RFC->sp0; + RFC->sn4 = - RFC->sd4 * RFC->sp0; + break; + case DERIVATIVE_1 : + case DERIVATIVE_1_CONTOURS : + case DERIVATIVE_3 : + RFC->sn1 = - RFC->sp1 + RFC->sd1 * RFC->sp0; + RFC->sn2 = - RFC->sp2 + RFC->sd2 * RFC->sp0; + RFC->sn3 = - RFC->sp3 + RFC->sd3 * RFC->sp0; + RFC->sn4 = RFC->sd4 * RFC->sp0; + } + + RFC->type_filter = type_filter; + RFC->derivative = derivative; + break; + + + + default : + if ( get_static_verbose_recline() != 0 ) { + fprintf( stderr, "%s: switch to default recursive filter (Deriche's filters).\n", proc ); + } + type_filter = ALPHA_DERICHE; + case ALPHA_DERICHE : + + if ( (x < 0.1) || (x > 1.9) ) { + if ( get_static_verbose_recline() != 0 ) { + fprintf( stderr, "%s: improper value of coefficient (should be >= 0.1 and <= 1.9).\n", proc ); + } + free( RFC ); + return( NULL ); + } + ex = exp( (-x) ); + + switch ( derivative ) { + default : + if ( get_static_verbose_recline() != 0 ) { + fprintf( stderr, "%s: switch to default coefficients (smoothing).\n", proc ); + } + derivative = DERIVATIVE_0; + case DERIVATIVE_0 : + RFC->sp0 = (1.0 - ex) * (1.0 - ex) / (1.0 + 2.0 * x * ex - ex * ex); + RFC->sp1 = RFC->sp0 * (x - 1.0) * ex; + RFC->sn1 = RFC->sp0 * (x + 1.0) * ex; + RFC->sn2 = (- RFC->sp0) * ex * ex; + RFC->sd1 = (- 2.0) * ex; + RFC->sd2 = ex * ex; + break; + case DERIVATIVE_1 : + RFC->sp1 = - (1.0 - ex) * (1.0 - ex) * (1.0 - ex) / (2.0 * (1.0 + ex)); + RFC->sn1 = (- RFC->sp1); + RFC->sd1 = (- 2.0) * ex; + RFC->sd2 = ex * ex; + break; + case DERIVATIVE_1_CONTOURS : + RFC->sp1 = - (1.0 - ex) * (1.0 - ex); + RFC->sn1 = (- RFC->sp1); + RFC->sd1 = (- 2.0) * ex; + RFC->sd2 = ex * ex; + break; + case DERIVATIVE_2 : + k1 = (- 2.0) * (1.0 - ex) * (1.0 - ex) * (1.0 - ex); + k1 /= (1.0 + ex) * (1.0 + ex) * (1.0 + ex); + k2 = (1.0 - ex * ex) / (2.0 * ex); + RFC->sp0 = k1; + RFC->sp1 = (- k1) * (1.0 + k2) * ex; + RFC->sn1 = k1 * (1.0 - k2) * ex; + RFC->sn2 = (- k1) * ex * ex; + RFC->sd1 = (- 2.0) * ex; + RFC->sd2 = ex * ex; + break; + case DERIVATIVE_3 : + k1 = (1.0 + x) * ex + (x - 1.0); + k2 = (1.0 - ex) / k1; + k1 *= (1.0 - ex) * (1.0 - ex) * (1.0 - ex) * (1.0 - ex); + k1 /= 2.0 * x * x * ex * ex; + k1 /= ex + 1.0; + RFC->sp0 = k1 * x * (k2 + 1.0); + RFC->sp1 = (- k1) * x * (1.0 + k2 + k2*x) * ex; + RFC->sn0 = (- RFC->sp0); + RFC->sn1 = (- RFC->sp1); + RFC->sd1 = (- 2.0) * ex; + RFC->sd2 = ex * ex; + } + RFC->type_filter = type_filter; + RFC->derivative = derivative; + } + + return( RFC ); +} + + + +CGAL_INLINE_FUNCTION +int RecursiveFilter1D( RFcoefficientType *RFC, + double *in, + double *out, + double *work1, + double *work2, + int dim ) +{ + const char *proc="RecursiveFilter1D"; + register double rp0, rp1, rp2, rp3; + register double rd1, rd2, rd3, rd4; + register double rn0, rn1, rn2, rn3, rn4; + register int i; + register double *w0, *w1, *w2, *w3, *w4; + register double *d0, *d1, *d2, *d3, *d4; + + if ( RFC->type_filter == UNKNOWN_FILTER ) { + if ( get_static_verbose_recline() != 0 ) + fprintf( stderr, "%s: unknown type of recursive filter.\n", proc ); + return( EXIT_ON_FAILURE ); + } + if ( RFC->derivative == NODERIVATIVE ) { + if ( get_static_verbose_recline() != 0 ) + fprintf( stderr, "%s: unknown type of derivative.\n", proc ); + return( EXIT_ON_FAILURE ); + } + + rd1 = rd2 = rd3 = rd4 = 0.0; + rp0 = rp1 = rp2 = rp3 = 0.0; + rn0 = rn1 = rn2 = rn3 = rn4 = 0.0; + + switch( RFC->type_filter ) { + default : + if ( get_static_verbose_recline() != 0 ) + fprintf( stderr, "%s: unknown type of recursive filter.\n", proc ); + return( EXIT_ON_FAILURE ); + case GAUSSIAN_FIDRICH : + case GAUSSIAN_DERICHE : + /*--- filtrage generique d'ordre 4 ---*/ + rp0 = RFC->sp0; rp1 = RFC->sp1; rp2 = RFC->sp2; rp3 = RFC->sp3; + rd1 = RFC->sd1; rd2 = RFC->sd2; rd3 = RFC->sd3; rd4 = RFC->sd4; + rn1 = RFC->sn1; rn2 = RFC->sn2; rn3 = RFC->sn3; rn4 = RFC->sn4; + + /* on positionne les pointeurs + */ + w4 = work1; w3 = w4+1; w2 = w3+1; w1 = w2+1; w0 = w1+1; + d3 = in+1; d2 = d3+1; d1 = d2+1; d0 = d1+1; + /*--- calcul de y+ ---*/ + *(w4) = rp0 * *(in); + *(w3) = rp0 * *(d3) + rp1 * *(in) + - rd1 * *(w4); + *(w2) = rp0 * *(d2) + rp1 * *(d3) + rp2 * *(in) + - rd1 * *(w3) - rd2 * *(w4); + *(w1) = rp0 * *(d1) + rp1 * *(d2) + rp2 * *(d3) + rp3 * *(in) + - rd1 * *(w2) - rd2 * *(w3) - rd3 * *(w4); + for (i=4; i=0; i--,w0--,w1--,w2--,w3--,w4--,d1--,d2--,d3--,d4--) + *(w0) = rn1 * *(d1) + rn2 * *(d2) + rn3 * *(d3) + rn4 * *(d4) + - rd1 * *(w1) - rd2 * *(w2) - rd3 * *(w3) - rd4 * *(w4); + + /*--- calcul final ---*/ + w1 = work1; w2 = work2; d0 = out; + for (i=0 ; iderivative ) { + default : + case DERIVATIVE_0 : + case DERIVATIVE_2 : + + rp0 = RFC->sp0; rp1 = RFC->sp1; + rd1 = RFC->sd1; rd2 = RFC->sd2; + rn1 = RFC->sn1; rn2 = RFC->sn2; + + /* on positionne les pointeurs + */ + w2 = work1; w1 = w2+1; w0 = w1+1; + d1 = in+1; d0 = d1+1; + /*--- calcul de y+ ---*/ + *(w2) = rp0 * *(in); + *(w1) = rp0 * *(d1) + rp1 * *(in) + - rd1 * *(w2); + for (i=2; i=0; i--,w0--,w1--,w2--,d1--,d2--) + *(w0) = rn1 * *(d1) + rn2 * *(d2) + - rd1 * *(w1) - rd2 * *(w2); + + /*--- calcul final ---*/ + w1 = work1; w2 = work2; d0 = out; + for (i=0 ; isp1; + rn1 = RFC->sn1; + rd1 = RFC->sd1; rd2 = RFC->sd2; + + /* on positionne les pointeurs + */ + w2 = work1; w1 = w2+1; w0 = w1+1; + d1 = in+1; + /*--- calcul de y+ ---*/ + *(w2) = 0.0; + *(w1) = rp1 * *(in); + for (i=2; i=0; i--,w0--,w1--,w2--,d1--) + *(w0) = rn1 * *(d1) + - rd1 * *(w1) - rd2 * *(w2); + + /*--- calcul final ---*/ + w1 = work1; w2 = work2; d0 = out; + for (i=0 ; isp0; rp1 = RFC->sp1; + rd1 = RFC->sd1; rd2 = RFC->sd2; + rn0 = RFC->sn0; rn1 = RFC->sn1; + + w2 = work1; w1 = w2+1; w0 = w1+1; + d1 = in+1; d0 = d1+1; + /*--- calcul de y+ ---*/ + *(w2) = rp0 * *(in); + *(w1) = rp0 * *(d1) + rp1 * *(in) + - rd1 * *(w2); + for (i=2; i=0; i--,w0--,w1--,w2--,d0--,d1--) + *(w0) = rn0 * *(d0) + rn1 * *(d1) + - rd1 * *(w1) - rd2 * *(w2); + + /*--- calcul final ---*/ + w1 = work1; w2 = work2; d0 = out; + for (i=0 ; i -#include "typedefs.h" - -#define _CONVERTR_(R) ( R ) -#define _CONVERTI_(R) ( (R) >= 0.0 ? ((int)((R)+0.5)) : ((int)((R)-0.5)) ) -static int _VERBOSE_REECH_ = 0; - - - - - - - -/* Resampling procedure. - - Work for 3D images, not for vectorial ones. - - (double* mat) is the matrix which permits to get - from resBuf into theBuf. - If one only have the matrix from theBuf into resBuf, - it must be inverted first. - - Soit x le point transforme et ix=(int)x; - nous allons distinguer les cas suivants : - x < -0.5 => resultat = 0 - -0.5 <= x < 0.0 => ix=0, on n'interpole pas selon X - 0.0 < x && ix < dimx-1 => on interpole selon X - x < dimx-0.5 => ix=dimx-1, on n'interpole pas selon X - x >= dimx-0.5 => resultat = 0 - -*/ - -void Reech3DTriLin4x4_u8 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; - register double res; - double v6, v5, v4; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register double ddimz = (double)tdimz-0.5; - register u8 *tbuf = (u8*)theBuf; - register u8 *tpt; - register u8 *rbuf = (u8*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - iz = (int)z; - tpt = (u8 *)tbuf; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) && - (z > 0.0) && (iz < t1dimz) ) { - /* the corresponding point is in the box defined - by (ix[+1],iy[+1],iz[+1]) */ - dx = x - ix; - dy = y - iy; - dz = z - iz; - dxdy = dx*dy; - dxdz = dx*dz; - dydz = dy*dz; - dxdydz = dxdy*dz; - - /* we have - v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) - v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) - v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) - v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) - v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) - v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) - v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) - v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) - */ - tpt += ix + iy * tdimx + iz * tdimxy + toffset1; - v6 = dxdz-dxdydz; - v5 = dxdy-dxdydz; - v4 = dx-dxdy-v6; - - res = 0; - res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ - tpt --; - res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ - tpt -= t1dimx; - res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ - tpt --; - res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ - tpt -= toffset2; - res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ - tpt --; - res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ - tpt -= t1dimx; - res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ - tpt --; - res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - /* here, we are sure we are on some border */ - tpt += ix + iy * tdimx + iz * tdimxy; - if ( (x < 0.0) || (ix == t1dimx) ) { - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - *rbuf = *tpt; - continue; - } - dz = z - iz; - res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ - tpt += tdimxy; - res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - dy = y - iy; - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt += toffset2+1; - res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt += tdimx; - res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is either - along the Y or the Z axis */ - dx = x - ix; - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += tdimxy-1; - res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt ++; - res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is along the Z axis */ - dy = y - iy; - res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += t1dimx; - res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt ++; - res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ - *rbuf = (u8)_CONVERTI_( res ); - } - } -} - -void Reech3DTriLin4x4gb_u8 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat, /* transformation matrix */ - float gain, - float bias ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; - register double res; - double v6, v5, v4; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register double ddimz = (double)tdimz-0.5; - register u8 *tbuf = (u8*)theBuf; - register u8 *tpt; - register u8 *rbuf = (u8*)resBuf; - register double b=bias; - register double g=gain; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - iz = (int)z; - tpt = (u8 *)tbuf; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) && - (z > 0.0) && (iz < t1dimz) ) { - /* the corresponding point is in the box defined - by (ix[+1],iy[+1],iz[+1]) */ - dx = x - ix; - dy = y - iy; - dz = z - iz; - dxdy = dx*dy; - dxdz = dx*dz; - dydz = dy*dz; - dxdydz = dxdy*dz; - - /* we have - v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) - v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) - v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) - v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) - v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) - v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) - v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) - v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) - */ - tpt += ix + iy * tdimx + iz * tdimxy + toffset1; - v6 = dxdz-dxdydz; - v5 = dxdy-dxdydz; - v4 = dx-dxdy-v6; - - res = 0; - res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ - tpt --; - res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ - tpt -= t1dimx; - res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ - tpt --; - res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ - tpt -= toffset2; - res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ - tpt --; - res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ - tpt -= t1dimx; - res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ - tpt --; - res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ - res = res * g + b; - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - /* here, we are sure we are on some border */ - tpt += ix + iy * tdimx + iz * tdimxy; - if ( (x < 0.0) || (ix == t1dimx) ) { - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (double)(*tpt) * g + b; - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ - tpt += tdimxy; - res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ - res = res * g + b; - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - dy = y - iy; - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ - res = res * g + b; - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt += toffset2+1; - res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt += tdimx; - res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ - res = res * g + b; - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is either - along the Y or the Z axis */ - dx = x - ix; - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ - res = res * g + b; - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += tdimxy-1; - res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt ++; - res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ - res = res * g + b; - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is along the Z axis */ - dy = y - iy; - res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += t1dimx; - res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt ++; - res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ - res = res * g + b; - *rbuf = (u8)_CONVERTI_( res ); - } - } -} - -void Reech3DNearest4x4_u8 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register u8 *tbuf = (u8*)theBuf; - register u8 *rbuf = (u8*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - ix = (int)(x+0.5); - if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - iy = (int)(y+0.5); - if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - iz = (int)(z+0.5); - if (( z < -0.5 ) || ( iz > t1dimz)) { *rbuf = 0; continue; } - - *rbuf = tbuf[ ix + iy * tdimx + iz * tdimxy ]; - } - } -} - -void Reech2DTriLin4x4_u8 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy; - register double x, y, dx, dy, dxdy; - register double res, v; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - int toffset=tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register u8 *tbuf = (u8*)theBuf; - register u8 *tpt; - register u8 *rbuf = (u8*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (u8*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - tpt = (u8 *)tbuf; - tpt += ix + iy * tdimx; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) ) { - dx = x - ix; - dy = y - iy; - dxdy = dx*dy; - /* we have - v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) - v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) - v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) - v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) - */ - v = dy-dxdy; - res = 0; - res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ - tpt ++; - res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ - tpt += toffset; - res += v * (*tpt); /* tbuf(ix,iy+1 ) */ - tpt ++; - res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - - /* here, we are sure we are on some border */ - if ( (x < 0.0) || (ix == t1dimx) ) { - /* we just look at y */ - if ( (y < 0.0) || (iy == t1dimy) ) { - *rbuf = *tpt; - continue; - } - dy = y - iy; - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - dx = x - ix; - res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ - tpt ++; - res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ - *rbuf = (u8)_CONVERTI_( res ); - } - } -} - -void Reech2DTriLin4x4gb_u8 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat, /* transformation matrix */ - float gain, - float bias ) -{ - register int i, j, k, ix, iy; - register double x, y, dx, dy, dxdy; - register double res, v; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - int toffset=tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register u8 *tbuf = (u8*)theBuf; - register u8 *tpt; - register u8 *rbuf = (u8*)resBuf; - register double b=bias; - register double g=gain; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (u8*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - tpt = (u8 *)tbuf; - tpt += ix + iy * tdimx; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) ) { - dx = x - ix; - dy = y - iy; - dxdy = dx*dy; - /* we have - v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) - v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) - v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) - v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) - */ - v = dy-dxdy; - res = 0; - res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ - tpt ++; - res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ - tpt += toffset; - res += v * (*tpt); /* tbuf(ix,iy+1 ) */ - tpt ++; - res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ - res = res * g + b; - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - - /* here, we are sure we are on some border */ - if ( (x < 0.0) || (ix == t1dimx) ) { - /* we just look at y */ - if ( (y < 0.0) || (iy == t1dimy) ) { - res = (double)(*tpt) * g + b; - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - dy = y - iy; - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ - res = (double)(*tpt) * g + b; - *rbuf = (u8)_CONVERTI_( res ); - continue; - } - dx = x - ix; - res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ - tpt ++; - res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ - res = res * g + b; - *rbuf = (u8)_CONVERTI_( res ); - } - } -} - -void Reech2DNearest4x4_u8 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy; - register double x, y; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register u8 *tbuf = (u8*)theBuf; - register u8 *rbuf = (u8*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (u8*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - ix = (int)(x+0.5); - if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - iy = (int)(y+0.5); - if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } - - *rbuf = tbuf[ ix + iy * tdimx ]; - } - } -} - - - - - - -/* Resampling procedure. - - Work for 3D images, not for vectorial ones. - - (double* mat) is the matrix which permits to get - from resBuf into theBuf. - If one only have the matrix from theBuf into resBuf, - it must be inverted first. - - Soit x le point transforme et ix=(int)x; - nous allons distinguer les cas suivants : - x < -0.5 => resultat = 0 - -0.5 <= x < 0.0 => ix=0, on n'interpole pas selon X - 0.0 < x && ix < dimx-1 => on interpole selon X - x < dimx-0.5 => ix=dimx-1, on n'interpole pas selon X - x >= dimx-0.5 => resultat = 0 - -*/ - -void Reech3DTriLin4x4_s8 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; - register double res; - double v6, v5, v4; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register double ddimz = (double)tdimz-0.5; - register s8 *tbuf = (s8*)theBuf; - register s8 *tpt; - register s8 *rbuf = (s8*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - iz = (int)z; - tpt = (s8 *)tbuf; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) && - (z > 0.0) && (iz < t1dimz) ) { - /* the corresponding point is in the box defined - by (ix[+1],iy[+1],iz[+1]) */ - dx = x - ix; - dy = y - iy; - dz = z - iz; - dxdy = dx*dy; - dxdz = dx*dz; - dydz = dy*dz; - dxdydz = dxdy*dz; - - /* we have - v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) - v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) - v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) - v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) - v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) - v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) - v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) - v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) - */ - tpt += ix + iy * tdimx + iz * tdimxy + toffset1; - v6 = dxdz-dxdydz; - v5 = dxdy-dxdydz; - v4 = dx-dxdy-v6; - - res = 0; - res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ - tpt --; - res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ - tpt -= t1dimx; - res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ - tpt --; - res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ - tpt -= toffset2; - res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ - tpt --; - res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ - tpt -= t1dimx; - res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ - tpt --; - res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - /* here, we are sure we are on some border */ - tpt += ix + iy * tdimx + iz * tdimxy; - if ( (x < 0.0) || (ix == t1dimx) ) { - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - *rbuf = *tpt; - continue; - } - dz = z - iz; - res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ - tpt += tdimxy; - res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - dy = y - iy; - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt += toffset2+1; - res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt += tdimx; - res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is either - along the Y or the Z axis */ - dx = x - ix; - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += tdimxy-1; - res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt ++; - res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is along the Z axis */ - dy = y - iy; - res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += t1dimx; - res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt ++; - res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ - *rbuf = (s8)_CONVERTI_( res ); - } - } -} - -void Reech3DTriLin4x4gb_s8 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat, /* transformation matrix */ - float gain, - float bias ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; - register double res; - double v6, v5, v4; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register double ddimz = (double)tdimz-0.5; - register s8 *tbuf = (s8*)theBuf; - register s8 *tpt; - register s8 *rbuf = (s8*)resBuf; - register double b=bias; - register double g=gain; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - iz = (int)z; - tpt = (s8 *)tbuf; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) && - (z > 0.0) && (iz < t1dimz) ) { - /* the corresponding point is in the box defined - by (ix[+1],iy[+1],iz[+1]) */ - dx = x - ix; - dy = y - iy; - dz = z - iz; - dxdy = dx*dy; - dxdz = dx*dz; - dydz = dy*dz; - dxdydz = dxdy*dz; - - /* we have - v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) - v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) - v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) - v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) - v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) - v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) - v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) - v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) - */ - tpt += ix + iy * tdimx + iz * tdimxy + toffset1; - v6 = dxdz-dxdydz; - v5 = dxdy-dxdydz; - v4 = dx-dxdy-v6; - - res = 0; - res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ - tpt --; - res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ - tpt -= t1dimx; - res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ - tpt --; - res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ - tpt -= toffset2; - res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ - tpt --; - res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ - tpt -= t1dimx; - res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ - tpt --; - res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ - res = res * g + b; - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - /* here, we are sure we are on some border */ - tpt += ix + iy * tdimx + iz * tdimxy; - if ( (x < 0.0) || (ix == t1dimx) ) { - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (double)(*tpt) * g + b; - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ - tpt += tdimxy; - res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ - res = res * g + b; - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - dy = y - iy; - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ - res = res * g + b; - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt += toffset2+1; - res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt += tdimx; - res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ - res = res * g + b; - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is either - along the Y or the Z axis */ - dx = x - ix; - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ - res = res * g + b; - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += tdimxy-1; - res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt ++; - res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ - res = res * g + b; - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is along the Z axis */ - dy = y - iy; - res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += t1dimx; - res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt ++; - res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ - res = res * g + b; - *rbuf = (s8)_CONVERTI_( res ); - } - } -} - -void Reech3DNearest4x4_s8 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register s8 *tbuf = (s8*)theBuf; - register s8 *rbuf = (s8*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - ix = (int)(x+0.5); - if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - iy = (int)(y+0.5); - if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - iz = (int)(z+0.5); - if (( z < -0.5 ) || ( iz > t1dimz)) { *rbuf = 0; continue; } - - *rbuf = tbuf[ ix + iy * tdimx + iz * tdimxy ]; - } - } -} - -void Reech2DTriLin4x4_s8 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy; - register double x, y, dx, dy, dxdy; - register double res, v; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - int toffset=tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register s8 *tbuf = (s8*)theBuf; - register s8 *tpt; - register s8 *rbuf = (s8*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (s8*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - tpt = (s8 *)tbuf; - tpt += ix + iy * tdimx; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) ) { - dx = x - ix; - dy = y - iy; - dxdy = dx*dy; - /* we have - v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) - v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) - v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) - v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) - */ - v = dy-dxdy; - res = 0; - res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ - tpt ++; - res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ - tpt += toffset; - res += v * (*tpt); /* tbuf(ix,iy+1 ) */ - tpt ++; - res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - - /* here, we are sure we are on some border */ - if ( (x < 0.0) || (ix == t1dimx) ) { - /* we just look at y */ - if ( (y < 0.0) || (iy == t1dimy) ) { - *rbuf = *tpt; - continue; - } - dy = y - iy; - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - dx = x - ix; - res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ - tpt ++; - res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ - *rbuf = (s8)_CONVERTI_( res ); - } - } -} - -void Reech2DTriLin4x4gb_s8 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat, /* transformation matrix */ - float gain, - float bias ) -{ - register int i, j, k, ix, iy; - register double x, y, dx, dy, dxdy; - register double res, v; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - int toffset=tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register s8 *tbuf = (s8*)theBuf; - register s8 *tpt; - register s8 *rbuf = (s8*)resBuf; - register double b=bias; - register double g=gain; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (s8*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - tpt = (s8 *)tbuf; - tpt += ix + iy * tdimx; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) ) { - dx = x - ix; - dy = y - iy; - dxdy = dx*dy; - /* we have - v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) - v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) - v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) - v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) - */ - v = dy-dxdy; - res = 0; - res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ - tpt ++; - res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ - tpt += toffset; - res += v * (*tpt); /* tbuf(ix,iy+1 ) */ - tpt ++; - res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ - res = res * g + b; - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - - /* here, we are sure we are on some border */ - if ( (x < 0.0) || (ix == t1dimx) ) { - /* we just look at y */ - if ( (y < 0.0) || (iy == t1dimy) ) { - res = (double)(*tpt) * g + b; - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - dy = y - iy; - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ - res = (double)(*tpt) * g + b; - *rbuf = (s8)_CONVERTI_( res ); - continue; - } - dx = x - ix; - res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ - tpt ++; - res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ - res = res * g + b; - *rbuf = (s8)_CONVERTI_( res ); - } - } -} - -void Reech2DNearest4x4_s8 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy; - register double x, y; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register s8 *tbuf = (s8*)theBuf; - register s8 *rbuf = (s8*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (s8*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - ix = (int)(x+0.5); - if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - iy = (int)(y+0.5); - if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } - - *rbuf = tbuf[ ix + iy * tdimx ]; - } - } -} - - - - - - -/* Resampling procedure. - - Work for 3D images, not for vectorial ones. - - (double* mat) is the matrix which permits to get - from resBuf into theBuf. - If one only have the matrix from theBuf into resBuf, - it must be inverted first. - - Soit x le point transforme et ix=(int)x; - nous allons distinguer les cas suivants : - x < -0.5 => resultat = 0 - -0.5 <= x < 0.0 => ix=0, on n'interpole pas selon X - 0.0 < x && ix < dimx-1 => on interpole selon X - x < dimx-0.5 => ix=dimx-1, on n'interpole pas selon X - x >= dimx-0.5 => resultat = 0 - -*/ - -void Reech3DTriLin4x4_u16 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; - register double res; - double v6, v5, v4; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register double ddimz = (double)tdimz-0.5; - register u16 *tbuf = (u16*)theBuf; - register u16 *tpt; - register u16 *rbuf = (u16*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - iz = (int)z; - tpt = (u16 *)tbuf; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) && - (z > 0.0) && (iz < t1dimz) ) { - /* the corresponding point is in the box defined - by (ix[+1],iy[+1],iz[+1]) */ - dx = x - ix; - dy = y - iy; - dz = z - iz; - dxdy = dx*dy; - dxdz = dx*dz; - dydz = dy*dz; - dxdydz = dxdy*dz; - - /* we have - v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) - v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) - v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) - v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) - v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) - v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) - v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) - v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) - */ - tpt += ix + iy * tdimx + iz * tdimxy + toffset1; - v6 = dxdz-dxdydz; - v5 = dxdy-dxdydz; - v4 = dx-dxdy-v6; - - res = 0; - res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ - tpt --; - res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ - tpt -= t1dimx; - res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ - tpt --; - res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ - tpt -= toffset2; - res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ - tpt --; - res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ - tpt -= t1dimx; - res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ - tpt --; - res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - /* here, we are sure we are on some border */ - tpt += ix + iy * tdimx + iz * tdimxy; - if ( (x < 0.0) || (ix == t1dimx) ) { - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - *rbuf = *tpt; - continue; - } - dz = z - iz; - res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ - tpt += tdimxy; - res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - dy = y - iy; - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt += toffset2+1; - res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt += tdimx; - res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is either - along the Y or the Z axis */ - dx = x - ix; - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += tdimxy-1; - res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt ++; - res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is along the Z axis */ - dy = y - iy; - res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += t1dimx; - res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt ++; - res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ - *rbuf = (u16)_CONVERTI_( res ); - } - } -} - -void Reech3DTriLin4x4gb_u16 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat, /* transformation matrix */ - float gain, - float bias ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; - register double res; - double v6, v5, v4; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register double ddimz = (double)tdimz-0.5; - register u16 *tbuf = (u16*)theBuf; - register u16 *tpt; - register u16 *rbuf = (u16*)resBuf; - register double b=bias; - register double g=gain; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - iz = (int)z; - tpt = (u16 *)tbuf; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) && - (z > 0.0) && (iz < t1dimz) ) { - /* the corresponding point is in the box defined - by (ix[+1],iy[+1],iz[+1]) */ - dx = x - ix; - dy = y - iy; - dz = z - iz; - dxdy = dx*dy; - dxdz = dx*dz; - dydz = dy*dz; - dxdydz = dxdy*dz; - - /* we have - v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) - v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) - v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) - v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) - v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) - v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) - v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) - v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) - */ - tpt += ix + iy * tdimx + iz * tdimxy + toffset1; - v6 = dxdz-dxdydz; - v5 = dxdy-dxdydz; - v4 = dx-dxdy-v6; - - res = 0; - res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ - tpt --; - res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ - tpt -= t1dimx; - res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ - tpt --; - res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ - tpt -= toffset2; - res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ - tpt --; - res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ - tpt -= t1dimx; - res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ - tpt --; - res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ - res = res * g + b; - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - /* here, we are sure we are on some border */ - tpt += ix + iy * tdimx + iz * tdimxy; - if ( (x < 0.0) || (ix == t1dimx) ) { - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (double)(*tpt) * g + b; - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ - tpt += tdimxy; - res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ - res = res * g + b; - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - dy = y - iy; - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ - res = res * g + b; - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt += toffset2+1; - res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt += tdimx; - res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ - res = res * g + b; - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is either - along the Y or the Z axis */ - dx = x - ix; - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ - res = res * g + b; - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += tdimxy-1; - res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt ++; - res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ - res = res * g + b; - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is along the Z axis */ - dy = y - iy; - res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += t1dimx; - res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt ++; - res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ - res = res * g + b; - *rbuf = (u16)_CONVERTI_( res ); - } - } -} - -void Reech3DNearest4x4_u16 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register u16 *tbuf = (u16*)theBuf; - register u16 *rbuf = (u16*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - ix = (int)(x+0.5); - if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - iy = (int)(y+0.5); - if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - iz = (int)(z+0.5); - if (( z < -0.5 ) || ( iz > t1dimz)) { *rbuf = 0; continue; } - - *rbuf = tbuf[ ix + iy * tdimx + iz * tdimxy ]; - } - } -} - -void Reech2DTriLin4x4_u16 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy; - register double x, y, dx, dy, dxdy; - register double res, v; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - int toffset=tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register u16 *tbuf = (u16*)theBuf; - register u16 *tpt; - register u16 *rbuf = (u16*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (u16*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - tpt = (u16 *)tbuf; - tpt += ix + iy * tdimx; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) ) { - dx = x - ix; - dy = y - iy; - dxdy = dx*dy; - /* we have - v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) - v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) - v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) - v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) - */ - v = dy-dxdy; - res = 0; - res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ - tpt ++; - res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ - tpt += toffset; - res += v * (*tpt); /* tbuf(ix,iy+1 ) */ - tpt ++; - res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - - /* here, we are sure we are on some border */ - if ( (x < 0.0) || (ix == t1dimx) ) { - /* we just look at y */ - if ( (y < 0.0) || (iy == t1dimy) ) { - *rbuf = *tpt; - continue; - } - dy = y - iy; - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - dx = x - ix; - res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ - tpt ++; - res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ - *rbuf = (u16)_CONVERTI_( res ); - } - } -} - -void Reech2DTriLin4x4gb_u16 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat, /* transformation matrix */ - float gain, - float bias ) -{ - register int i, j, k, ix, iy; - register double x, y, dx, dy, dxdy; - register double res, v; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - int toffset=tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register u16 *tbuf = (u16*)theBuf; - register u16 *tpt; - register u16 *rbuf = (u16*)resBuf; - register double b=bias; - register double g=gain; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (u16*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - tpt = (u16 *)tbuf; - tpt += ix + iy * tdimx; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) ) { - dx = x - ix; - dy = y - iy; - dxdy = dx*dy; - /* we have - v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) - v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) - v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) - v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) - */ - v = dy-dxdy; - res = 0; - res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ - tpt ++; - res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ - tpt += toffset; - res += v * (*tpt); /* tbuf(ix,iy+1 ) */ - tpt ++; - res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ - res = res * g + b; - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - - /* here, we are sure we are on some border */ - if ( (x < 0.0) || (ix == t1dimx) ) { - /* we just look at y */ - if ( (y < 0.0) || (iy == t1dimy) ) { - res = (double)(*tpt) * g + b; - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - dy = y - iy; - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ - res = (double)(*tpt) * g + b; - *rbuf = (u16)_CONVERTI_( res ); - continue; - } - dx = x - ix; - res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ - tpt ++; - res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ - res = res * g + b; - *rbuf = (u16)_CONVERTI_( res ); - } - } -} - -void Reech2DNearest4x4_u16 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy; - register double x, y; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register u16 *tbuf = (u16*)theBuf; - register u16 *rbuf = (u16*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (u16*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - ix = (int)(x+0.5); - if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - iy = (int)(y+0.5); - if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } - - *rbuf = tbuf[ ix + iy * tdimx ]; - } - } -} - - - - - - -/* Resampling procedure. - - Work for 3D images, not for vectorial ones. - - (double* mat) is the matrix which permits to get - from resBuf into theBuf. - If one only have the matrix from theBuf into resBuf, - it must be inverted first. - - Soit x le point transforme et ix=(int)x; - nous allons distinguer les cas suivants : - x < -0.5 => resultat = 0 - -0.5 <= x < 0.0 => ix=0, on n'interpole pas selon X - 0.0 < x && ix < dimx-1 => on interpole selon X - x < dimx-0.5 => ix=dimx-1, on n'interpole pas selon X - x >= dimx-0.5 => resultat = 0 - -*/ - -void Reech3DTriLin4x4_s16 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; - register double res; - double v6, v5, v4; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register double ddimz = (double)tdimz-0.5; - register s16 *tbuf = (s16*)theBuf; - register s16 *tpt; - register s16 *rbuf = (s16*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - iz = (int)z; - tpt = (s16 *)tbuf; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) && - (z > 0.0) && (iz < t1dimz) ) { - /* the corresponding point is in the box defined - by (ix[+1],iy[+1],iz[+1]) */ - dx = x - ix; - dy = y - iy; - dz = z - iz; - dxdy = dx*dy; - dxdz = dx*dz; - dydz = dy*dz; - dxdydz = dxdy*dz; - - /* we have - v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) - v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) - v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) - v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) - v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) - v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) - v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) - v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) - */ - tpt += ix + iy * tdimx + iz * tdimxy + toffset1; - v6 = dxdz-dxdydz; - v5 = dxdy-dxdydz; - v4 = dx-dxdy-v6; - - res = 0; - res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ - tpt --; - res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ - tpt -= t1dimx; - res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ - tpt --; - res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ - tpt -= toffset2; - res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ - tpt --; - res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ - tpt -= t1dimx; - res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ - tpt --; - res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - /* here, we are sure we are on some border */ - tpt += ix + iy * tdimx + iz * tdimxy; - if ( (x < 0.0) || (ix == t1dimx) ) { - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - *rbuf = *tpt; - continue; - } - dz = z - iz; - res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ - tpt += tdimxy; - res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - dy = y - iy; - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt += toffset2+1; - res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt += tdimx; - res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is either - along the Y or the Z axis */ - dx = x - ix; - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += tdimxy-1; - res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt ++; - res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is along the Z axis */ - dy = y - iy; - res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += t1dimx; - res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt ++; - res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ - *rbuf = (s16)_CONVERTI_( res ); - } - } -} - -void Reech3DTriLin4x4gb_s16 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat, /* transformation matrix */ - float gain, - float bias ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; - register double res; - double v6, v5, v4; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register double ddimz = (double)tdimz-0.5; - register s16 *tbuf = (s16*)theBuf; - register s16 *tpt; - register s16 *rbuf = (s16*)resBuf; - register double b=bias; - register double g=gain; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - iz = (int)z; - tpt = (s16 *)tbuf; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) && - (z > 0.0) && (iz < t1dimz) ) { - /* the corresponding point is in the box defined - by (ix[+1],iy[+1],iz[+1]) */ - dx = x - ix; - dy = y - iy; - dz = z - iz; - dxdy = dx*dy; - dxdz = dx*dz; - dydz = dy*dz; - dxdydz = dxdy*dz; - - /* we have - v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) - v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) - v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) - v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) - v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) - v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) - v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) - v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) - */ - tpt += ix + iy * tdimx + iz * tdimxy + toffset1; - v6 = dxdz-dxdydz; - v5 = dxdy-dxdydz; - v4 = dx-dxdy-v6; - - res = 0; - res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ - tpt --; - res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ - tpt -= t1dimx; - res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ - tpt --; - res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ - tpt -= toffset2; - res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ - tpt --; - res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ - tpt -= t1dimx; - res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ - tpt --; - res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ - res = res * g + b; - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - /* here, we are sure we are on some border */ - tpt += ix + iy * tdimx + iz * tdimxy; - if ( (x < 0.0) || (ix == t1dimx) ) { - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (double)(*tpt) * g + b; - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ - tpt += tdimxy; - res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ - res = res * g + b; - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - dy = y - iy; - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ - res = res * g + b; - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt += toffset2+1; - res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt += tdimx; - res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ - res = res * g + b; - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is either - along the Y or the Z axis */ - dx = x - ix; - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ - res = res * g + b; - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - dz = z - iz; - res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += tdimxy-1; - res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt ++; - res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ - res = res * g + b; - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - /* here we are sure that the border is along the Z axis */ - dy = y - iy; - res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += t1dimx; - res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt ++; - res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ - res = res * g + b; - *rbuf = (s16)_CONVERTI_( res ); - } - } -} - -void Reech3DNearest4x4_s16 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register s16 *tbuf = (s16*)theBuf; - register s16 *rbuf = (s16*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - ix = (int)(x+0.5); - if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - iy = (int)(y+0.5); - if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - iz = (int)(z+0.5); - if (( z < -0.5 ) || ( iz > t1dimz)) { *rbuf = 0; continue; } - - *rbuf = tbuf[ ix + iy * tdimx + iz * tdimxy ]; - } - } -} - -void Reech2DTriLin4x4_s16 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy; - register double x, y, dx, dy, dxdy; - register double res, v; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - int toffset=tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register s16 *tbuf = (s16*)theBuf; - register s16 *tpt; - register s16 *rbuf = (s16*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (s16*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - tpt = (s16 *)tbuf; - tpt += ix + iy * tdimx; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) ) { - dx = x - ix; - dy = y - iy; - dxdy = dx*dy; - /* we have - v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) - v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) - v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) - v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) - */ - v = dy-dxdy; - res = 0; - res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ - tpt ++; - res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ - tpt += toffset; - res += v * (*tpt); /* tbuf(ix,iy+1 ) */ - tpt ++; - res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - - /* here, we are sure we are on some border */ - if ( (x < 0.0) || (ix == t1dimx) ) { - /* we just look at y */ - if ( (y < 0.0) || (iy == t1dimy) ) { - *rbuf = *tpt; - continue; - } - dy = y - iy; - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - dx = x - ix; - res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ - tpt ++; - res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ - *rbuf = (s16)_CONVERTI_( res ); - } - } -} - -void Reech2DTriLin4x4gb_s16 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat, /* transformation matrix */ - float gain, - float bias ) -{ - register int i, j, k, ix, iy; - register double x, y, dx, dy, dxdy; - register double res, v; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - int toffset=tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register s16 *tbuf = (s16*)theBuf; - register s16 *tpt; - register s16 *rbuf = (s16*)resBuf; - register double b=bias; - register double g=gain; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (s16*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - tpt = (s16 *)tbuf; - tpt += ix + iy * tdimx; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) ) { - dx = x - ix; - dy = y - iy; - dxdy = dx*dy; - /* we have - v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) - v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) - v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) - v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) - */ - v = dy-dxdy; - res = 0; - res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ - tpt ++; - res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ - tpt += toffset; - res += v * (*tpt); /* tbuf(ix,iy+1 ) */ - tpt ++; - res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ - res = res * g + b; - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - - /* here, we are sure we are on some border */ - if ( (x < 0.0) || (ix == t1dimx) ) { - /* we just look at y */ - if ( (y < 0.0) || (iy == t1dimy) ) { - res = (double)(*tpt) * g + b; - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - dy = y - iy; - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ - res = (double)(*tpt) * g + b; - *rbuf = (s16)_CONVERTI_( res ); - continue; - } - dx = x - ix; - res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ - tpt ++; - res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ - res = res * g + b; - *rbuf = (s16)_CONVERTI_( res ); - } - } -} - -void Reech2DNearest4x4_s16 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy; - register double x, y; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register s16 *tbuf = (s16*)theBuf; - register s16 *rbuf = (s16*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (s16*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - ix = (int)(x+0.5); - if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - iy = (int)(y+0.5); - if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } - - *rbuf = tbuf[ ix + iy * tdimx ]; - } - } -} - - - - - - -/* Resampling procedure. - - Work for 3D images, not for vectorial ones. - - (double* mat) is the matrix which permits to get - from resBuf into theBuf. - If one only have the matrix from theBuf into resBuf, - it must be inverted first. - - Soit x le point transforme et ix=(int)x; - nous allons distinguer les cas suivants : - x < -0.5 => resultat = 0 - -0.5 <= x < 0.0 => ix=0, on n'interpole pas selon X - 0.0 < x && ix < dimx-1 => on interpole selon X - x < dimx-0.5 => ix=dimx-1, on n'interpole pas selon X - x >= dimx-0.5 => resultat = 0 - -*/ - -void Reech3DTriLin4x4_r32 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; - register double res; - double v6, v5, v4; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register double ddimz = (double)tdimz-0.5; - register r32 *tbuf = (r32*)theBuf; - register r32 *tpt; - register r32 *rbuf = (r32*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - iz = (int)z; - tpt = (r32 *)tbuf; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) && - (z > 0.0) && (iz < t1dimz) ) { - /* the corresponding point is in the box defined - by (ix[+1],iy[+1],iz[+1]) */ - dx = x - ix; - dy = y - iy; - dz = z - iz; - dxdy = dx*dy; - dxdz = dx*dz; - dydz = dy*dz; - dxdydz = dxdy*dz; - - /* we have - v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) - v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) - v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) - v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) - v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) - v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) - v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) - v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) - */ - tpt += ix + iy * tdimx + iz * tdimxy + toffset1; - v6 = dxdz-dxdydz; - v5 = dxdy-dxdydz; - v4 = dx-dxdy-v6; - - res = 0; - res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ - tpt --; - res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ - tpt -= t1dimx; - res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ - tpt --; - res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ - tpt -= toffset2; - res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ - tpt --; - res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ - tpt -= t1dimx; - res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ - tpt --; - res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - /* here, we are sure we are on some border */ - tpt += ix + iy * tdimx + iz * tdimxy; - if ( (x < 0.0) || (ix == t1dimx) ) { - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - *rbuf = *tpt; - continue; - } - dz = z - iz; - res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ - tpt += tdimxy; - res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - dy = y - iy; - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - dz = z - iz; - res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt += toffset2+1; - res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt += tdimx; - res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - /* here we are sure that the border is either - along the Y or the Z axis */ - dx = x - ix; - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - dz = z - iz; - res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += tdimxy-1; - res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt ++; - res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - /* here we are sure that the border is along the Z axis */ - dy = y - iy; - res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += t1dimx; - res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt ++; - res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ - *rbuf = (r32)_CONVERTR_( res ); - } - } -} - -void Reech3DTriLin4x4gb_r32 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat, /* transformation matrix */ - float gain, - float bias ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; - register double res; - double v6, v5, v4; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register double ddimz = (double)tdimz-0.5; - register r32 *tbuf = (r32*)theBuf; - register r32 *tpt; - register r32 *rbuf = (r32*)resBuf; - register double b=bias; - register double g=gain; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - iz = (int)z; - tpt = (r32 *)tbuf; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) && - (z > 0.0) && (iz < t1dimz) ) { - /* the corresponding point is in the box defined - by (ix[+1],iy[+1],iz[+1]) */ - dx = x - ix; - dy = y - iy; - dz = z - iz; - dxdy = dx*dy; - dxdz = dx*dz; - dydz = dy*dz; - dxdydz = dxdy*dz; - - /* we have - v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) - v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) - v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) - v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) - v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) - v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) - v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) - v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) - */ - tpt += ix + iy * tdimx + iz * tdimxy + toffset1; - v6 = dxdz-dxdydz; - v5 = dxdy-dxdydz; - v4 = dx-dxdy-v6; - - res = 0; - res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ - tpt --; - res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ - tpt -= t1dimx; - res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ - tpt --; - res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ - tpt -= toffset2; - res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ - tpt --; - res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ - tpt -= t1dimx; - res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ - tpt --; - res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ - res = res * g + b; - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - /* here, we are sure we are on some border */ - tpt += ix + iy * tdimx + iz * tdimxy; - if ( (x < 0.0) || (ix == t1dimx) ) { - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (double)(*tpt) * g + b; - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - dz = z - iz; - res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ - tpt += tdimxy; - res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ - res = res * g + b; - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - dy = y - iy; - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ - res = res * g + b; - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - dz = z - iz; - res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt += tdimx; - res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt += toffset2+1; - res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt += tdimx; - res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ - res = res * g + b; - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - /* here we are sure that the border is either - along the Y or the Z axis */ - dx = x - ix; - if ( (y < 0.0) || (iy == t1dimy) ) { - if ( (z < 0.0) || (iz == t1dimz) ) { - res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ - res = res * g + b; - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - dz = z - iz; - res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += tdimxy-1; - res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ - tpt ++; - res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ - res = res * g + b; - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - /* here we are sure that the border is along the Z axis */ - dy = y - iy; - res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ - tpt ++; - res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ - tpt += t1dimx; - res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ - tpt ++; - res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ - res = res * g + b; - *rbuf = (r32)_CONVERTR_( res ); - } - } -} - -void Reech3DNearest4x4_r32 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy, iz; - register double x, y, z; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; - int tdimxy=tdimx*tdimy; - register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; - register r32 *tbuf = (r32*)theBuf; - register r32 *rbuf = (r32*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; - ix = (int)(x+0.5); - if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; - iy = (int)(y+0.5); - if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } - z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; - iz = (int)(z+0.5); - if (( z < -0.5 ) || ( iz > t1dimz)) { *rbuf = 0; continue; } - - *rbuf = tbuf[ ix + iy * tdimx + iz * tdimxy ]; - } - } -} - -void Reech2DTriLin4x4_r32 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy; - register double x, y, dx, dy, dxdy; - register double res, v; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - int toffset=tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register r32 *tbuf = (r32*)theBuf; - register r32 *tpt; - register r32 *rbuf = (r32*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (r32*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - tpt = (r32 *)tbuf; - tpt += ix + iy * tdimx; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) ) { - dx = x - ix; - dy = y - iy; - dxdy = dx*dy; - /* we have - v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) - v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) - v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) - v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) - */ - v = dy-dxdy; - res = 0; - res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ - tpt ++; - res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ - tpt += toffset; - res += v * (*tpt); /* tbuf(ix,iy+1 ) */ - tpt ++; - res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - - /* here, we are sure we are on some border */ - if ( (x < 0.0) || (ix == t1dimx) ) { - /* we just look at y */ - if ( (y < 0.0) || (iy == t1dimy) ) { - *rbuf = *tpt; - continue; - } - dy = y - iy; - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - dx = x - ix; - res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ - tpt ++; - res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ - *rbuf = (r32)_CONVERTR_( res ); - } - } -} - -void Reech2DTriLin4x4gb_r32 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat, /* transformation matrix */ - float gain, - float bias ) -{ - register int i, j, k, ix, iy; - register double x, y, dx, dy, dxdy; - register double res, v; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - int toffset=tdimx-1; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; - register r32 *tbuf = (r32*)theBuf; - register r32 *tpt; - register r32 *rbuf = (r32*)resBuf; - register double b=bias; - register double g=gain; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (r32*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } - - /* here, the point lies on the borders or completely inside - the image */ - ix = (int)x; - iy = (int)y; - tpt = (r32 *)tbuf; - tpt += ix + iy * tdimx; - - /* are we on the border or not ? */ - if ( (x > 0.0) && (ix < t1dimx) && - (y > 0.0) && (iy < t1dimy) ) { - dx = x - ix; - dy = y - iy; - dxdy = dx*dy; - /* we have - v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) - v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) - v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) - v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) - */ - v = dy-dxdy; - res = 0; - res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ - tpt ++; - res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ - tpt += toffset; - res += v * (*tpt); /* tbuf(ix,iy+1 ) */ - tpt ++; - res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ - res = res * g + b; - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - - /* here, we are sure we are on some border */ - if ( (x < 0.0) || (ix == t1dimx) ) { - /* we just look at y */ - if ( (y < 0.0) || (iy == t1dimy) ) { - res = (double)(*tpt) * g + b; - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - dy = y - iy; - res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ - tpt += tdimx; - res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ - res = (double)(*tpt) * g + b; - *rbuf = (r32)_CONVERTR_( res ); - continue; - } - dx = x - ix; - res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ - tpt ++; - res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ - res = res * g + b; - *rbuf = (r32)_CONVERTR_( res ); - } - } -} - -void Reech2DNearest4x4_r32 ( void* theBuf, /* buffer to be resampled */ - int *theDim, /* dimensions of this buffer */ - void* resBuf, /* result buffer */ - int *resDim, /* dimensions of this buffer */ - double* mat /* transformation matrix */ - ) -{ - register int i, j, k, ix, iy; - register double x, y; - int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; - int tdimx=theDim[0], tdimy=theDim[1]; - register int t1dimx=tdimx-1, t1dimy=tdimy-1; - register r32 *tbuf = (r32*)theBuf; - register r32 *rbuf = (r32*)resBuf; - - for ( k = 0; k < rdimz; k ++ ) { - if ( _VERBOSE_REECH_ != 0 ) - fprintf( stderr, "Processing slice %d\r", k ); - /* tbuf represente le premier point du plan */ - tbuf = (r32*)theBuf; - tbuf += k*(tdimx * tdimy); - for ( j = 0; j < rdimy; j ++ ) - for ( i = 0; i < rdimx; i ++, rbuf ++ ) { - /* computation of the corresponding point coordinates in theBuf */ - x = mat[0] * i + mat[1] * j + mat[3]; - ix = (int)(x+0.5); - if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } - y = mat[4] * i + mat[5] * j + mat[7]; - iy = (int)(y+0.5); - if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } - - *rbuf = tbuf[ ix + iy * tdimx ]; - } - } -} - - - - - - -void Reech4x4_verbose ( ) -{ - _VERBOSE_REECH_ = 1; -} - -void Reech4x4_noverbose ( ) -{ - _VERBOSE_REECH_ = 0; -} +#include "reech4x4_impl.h" +#endif // CGAL_HEADER_ONLY diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/reech4x4.h b/CGAL_ImageIO/src/CGAL_ImageIO/reech4x4.h index 78b465f9bd8..11f84f794b8 100644 --- a/CGAL_ImageIO/src/CGAL_ImageIO/reech4x4.h +++ b/CGAL_ImageIO/src/CGAL_ImageIO/reech4x4.h @@ -280,5 +280,9 @@ extern void Reech2DNearest4x4_r32 ( void* theBuf, /* buffer to be resampled */ extern void Reech4x4_verbose ( ); extern void Reech4x4_noverbose ( ); +#ifdef CGAL_HEADER_ONLY +#include "reech4x4_impl.h" +#endif // CGAL_HEADER_ONLY + #endif diff --git a/CGAL_ImageIO/src/CGAL_ImageIO/reech4x4_impl.h b/CGAL_ImageIO/src/CGAL_ImageIO/reech4x4_impl.h new file mode 100644 index 00000000000..a09c9e363c4 --- /dev/null +++ b/CGAL_ImageIO/src/CGAL_ImageIO/reech4x4_impl.h @@ -0,0 +1,3176 @@ +// Copyright (c) 2005-2008 ASCLEPIOS Project, INRIA Sophia-Antipolis (France) +// All rights reserved. +// +// This file is part of the ImageIO Library, and as been adapted for +// CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the +// GNU Lesser General Public License as published by the Free Software Foundation; +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau + +/************************************************************************* + * reech4x4.c - + * + * $Id$ + * + * Copyright©INRIA 1999 + * + * AUTHOR: + * Gregoire Malandain (greg@sophia.inria.fr) + * + * CREATION DATE: + * + * + * ADDITIONS, CHANGES + * + * + * + * + */ + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +/* CAUTION + DO NOT EDIT THIS FILE, + UNLESS YOU HAVE A VERY GOOD REASON + */ + +#include +#include "typedefs.h" + +#define _CONVERTR_(R) ( R ) +#define _CONVERTI_(R) ( (R) >= 0.0 ? ((int)((R)+0.5)) : ((int)((R)-0.5)) ) + + +#ifdef CGAL_HEADER_ONLY + +inline int& get_static_verbose_reech4x4() +{ + static int _VERBOSE_REECH_ = 0; + return _VERBOSE_REECH_; +} + +#else // CGAL_HEADER_ONLY + +static int _VERBOSE_REECH_ = 0; + +inline int& get_static_verbose_reech4x4() +{ return _VERBOSE_REECH_; } + +#endif // CGAL_HEADER_ONLY + + + + + + +/* Resampling procedure. + + Work for 3D images, not for vectorial ones. + + (double* mat) is the matrix which permits to get + from resBuf into theBuf. + If one only have the matrix from theBuf into resBuf, + it must be inverted first. + + Soit x le point transforme et ix=(int)x; + nous allons distinguer les cas suivants : + x < -0.5 => resultat = 0 + -0.5 <= x < 0.0 => ix=0, on n'interpole pas selon X + 0.0 < x && ix < dimx-1 => on interpole selon X + x < dimx-0.5 => ix=dimx-1, on n'interpole pas selon X + x >= dimx-0.5 => resultat = 0 + +*/ + +CGAL_INLINE_FUNCTION +void Reech3DTriLin4x4_u8 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; + register double res; + double v6, v5, v4; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register double ddimz = (double)tdimz-0.5; + register u8 *tbuf = (u8*)theBuf; + register u8 *tpt; + register u8 *rbuf = (u8*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + iz = (int)z; + tpt = (u8 *)tbuf; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) && + (z > 0.0) && (iz < t1dimz) ) { + /* the corresponding point is in the box defined + by (ix[+1],iy[+1],iz[+1]) */ + dx = x - ix; + dy = y - iy; + dz = z - iz; + dxdy = dx*dy; + dxdz = dx*dz; + dydz = dy*dz; + dxdydz = dxdy*dz; + + /* we have + v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) + v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) + v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) + v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) + v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) + v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) + v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) + v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) + */ + tpt += ix + iy * tdimx + iz * tdimxy + toffset1; + v6 = dxdz-dxdydz; + v5 = dxdy-dxdydz; + v4 = dx-dxdy-v6; + + res = 0; + res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ + tpt --; + res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ + tpt -= t1dimx; + res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ + tpt --; + res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ + tpt -= toffset2; + res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ + tpt --; + res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ + tpt -= t1dimx; + res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ + tpt --; + res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + /* here, we are sure we are on some border */ + tpt += ix + iy * tdimx + iz * tdimxy; + if ( (x < 0.0) || (ix == t1dimx) ) { + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + *rbuf = *tpt; + continue; + } + dz = z - iz; + res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ + tpt += tdimxy; + res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + dy = y - iy; + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt += toffset2+1; + res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt += tdimx; + res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is either + along the Y or the Z axis */ + dx = x - ix; + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += tdimxy-1; + res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt ++; + res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is along the Z axis */ + dy = y - iy; + res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += t1dimx; + res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt ++; + res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ + *rbuf = (u8)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech3DTriLin4x4gb_u8 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat, /* transformation matrix */ + float gain, + float bias ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; + register double res; + double v6, v5, v4; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register double ddimz = (double)tdimz-0.5; + register u8 *tbuf = (u8*)theBuf; + register u8 *tpt; + register u8 *rbuf = (u8*)resBuf; + register double b=bias; + register double g=gain; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + iz = (int)z; + tpt = (u8 *)tbuf; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) && + (z > 0.0) && (iz < t1dimz) ) { + /* the corresponding point is in the box defined + by (ix[+1],iy[+1],iz[+1]) */ + dx = x - ix; + dy = y - iy; + dz = z - iz; + dxdy = dx*dy; + dxdz = dx*dz; + dydz = dy*dz; + dxdydz = dxdy*dz; + + /* we have + v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) + v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) + v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) + v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) + v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) + v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) + v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) + v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) + */ + tpt += ix + iy * tdimx + iz * tdimxy + toffset1; + v6 = dxdz-dxdydz; + v5 = dxdy-dxdydz; + v4 = dx-dxdy-v6; + + res = 0; + res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ + tpt --; + res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ + tpt -= t1dimx; + res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ + tpt --; + res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ + tpt -= toffset2; + res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ + tpt --; + res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ + tpt -= t1dimx; + res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ + tpt --; + res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ + res = res * g + b; + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + /* here, we are sure we are on some border */ + tpt += ix + iy * tdimx + iz * tdimxy; + if ( (x < 0.0) || (ix == t1dimx) ) { + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (double)(*tpt) * g + b; + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ + tpt += tdimxy; + res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ + res = res * g + b; + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + dy = y - iy; + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ + res = res * g + b; + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt += toffset2+1; + res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt += tdimx; + res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ + res = res * g + b; + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is either + along the Y or the Z axis */ + dx = x - ix; + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ + res = res * g + b; + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += tdimxy-1; + res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt ++; + res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ + res = res * g + b; + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is along the Z axis */ + dy = y - iy; + res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += t1dimx; + res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt ++; + res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ + res = res * g + b; + *rbuf = (u8)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech3DNearest4x4_u8 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register u8 *tbuf = (u8*)theBuf; + register u8 *rbuf = (u8*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + ix = (int)(x+0.5); + if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + iy = (int)(y+0.5); + if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + iz = (int)(z+0.5); + if (( z < -0.5 ) || ( iz > t1dimz)) { *rbuf = 0; continue; } + + *rbuf = tbuf[ ix + iy * tdimx + iz * tdimxy ]; + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DTriLin4x4_u8 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy; + register double x, y, dx, dy, dxdy; + register double res, v; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + int toffset=tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register u8 *tbuf = (u8*)theBuf; + register u8 *tpt; + register u8 *rbuf = (u8*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (u8*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + tpt = (u8 *)tbuf; + tpt += ix + iy * tdimx; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) ) { + dx = x - ix; + dy = y - iy; + dxdy = dx*dy; + /* we have + v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) + v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) + v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) + v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) + */ + v = dy-dxdy; + res = 0; + res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ + tpt ++; + res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ + tpt += toffset; + res += v * (*tpt); /* tbuf(ix,iy+1 ) */ + tpt ++; + res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + + /* here, we are sure we are on some border */ + if ( (x < 0.0) || (ix == t1dimx) ) { + /* we just look at y */ + if ( (y < 0.0) || (iy == t1dimy) ) { + *rbuf = *tpt; + continue; + } + dy = y - iy; + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + dx = x - ix; + res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ + tpt ++; + res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ + *rbuf = (u8)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DTriLin4x4gb_u8 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat, /* transformation matrix */ + float gain, + float bias ) +{ + register int i, j, k, ix, iy; + register double x, y, dx, dy, dxdy; + register double res, v; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + int toffset=tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register u8 *tbuf = (u8*)theBuf; + register u8 *tpt; + register u8 *rbuf = (u8*)resBuf; + register double b=bias; + register double g=gain; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (u8*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + tpt = (u8 *)tbuf; + tpt += ix + iy * tdimx; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) ) { + dx = x - ix; + dy = y - iy; + dxdy = dx*dy; + /* we have + v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) + v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) + v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) + v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) + */ + v = dy-dxdy; + res = 0; + res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ + tpt ++; + res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ + tpt += toffset; + res += v * (*tpt); /* tbuf(ix,iy+1 ) */ + tpt ++; + res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ + res = res * g + b; + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + + /* here, we are sure we are on some border */ + if ( (x < 0.0) || (ix == t1dimx) ) { + /* we just look at y */ + if ( (y < 0.0) || (iy == t1dimy) ) { + res = (double)(*tpt) * g + b; + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + dy = y - iy; + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ + res = (double)(*tpt) * g + b; + *rbuf = (u8)_CONVERTI_( res ); + continue; + } + dx = x - ix; + res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ + tpt ++; + res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ + res = res * g + b; + *rbuf = (u8)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DNearest4x4_u8 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy; + register double x, y; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register u8 *tbuf = (u8*)theBuf; + register u8 *rbuf = (u8*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (u8*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + ix = (int)(x+0.5); + if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + iy = (int)(y+0.5); + if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } + + *rbuf = tbuf[ ix + iy * tdimx ]; + } + } +} + + + + + + +/* Resampling procedure. + + Work for 3D images, not for vectorial ones. + + (double* mat) is the matrix which permits to get + from resBuf into theBuf. + If one only have the matrix from theBuf into resBuf, + it must be inverted first. + + Soit x le point transforme et ix=(int)x; + nous allons distinguer les cas suivants : + x < -0.5 => resultat = 0 + -0.5 <= x < 0.0 => ix=0, on n'interpole pas selon X + 0.0 < x && ix < dimx-1 => on interpole selon X + x < dimx-0.5 => ix=dimx-1, on n'interpole pas selon X + x >= dimx-0.5 => resultat = 0 + +*/ +CGAL_INLINE_FUNCTION +void Reech3DTriLin4x4_s8 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; + register double res; + double v6, v5, v4; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register double ddimz = (double)tdimz-0.5; + register s8 *tbuf = (s8*)theBuf; + register s8 *tpt; + register s8 *rbuf = (s8*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + iz = (int)z; + tpt = (s8 *)tbuf; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) && + (z > 0.0) && (iz < t1dimz) ) { + /* the corresponding point is in the box defined + by (ix[+1],iy[+1],iz[+1]) */ + dx = x - ix; + dy = y - iy; + dz = z - iz; + dxdy = dx*dy; + dxdz = dx*dz; + dydz = dy*dz; + dxdydz = dxdy*dz; + + /* we have + v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) + v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) + v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) + v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) + v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) + v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) + v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) + v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) + */ + tpt += ix + iy * tdimx + iz * tdimxy + toffset1; + v6 = dxdz-dxdydz; + v5 = dxdy-dxdydz; + v4 = dx-dxdy-v6; + + res = 0; + res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ + tpt --; + res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ + tpt -= t1dimx; + res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ + tpt --; + res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ + tpt -= toffset2; + res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ + tpt --; + res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ + tpt -= t1dimx; + res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ + tpt --; + res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + /* here, we are sure we are on some border */ + tpt += ix + iy * tdimx + iz * tdimxy; + if ( (x < 0.0) || (ix == t1dimx) ) { + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + *rbuf = *tpt; + continue; + } + dz = z - iz; + res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ + tpt += tdimxy; + res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + dy = y - iy; + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt += toffset2+1; + res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt += tdimx; + res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is either + along the Y or the Z axis */ + dx = x - ix; + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += tdimxy-1; + res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt ++; + res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is along the Z axis */ + dy = y - iy; + res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += t1dimx; + res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt ++; + res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ + *rbuf = (s8)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech3DTriLin4x4gb_s8 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat, /* transformation matrix */ + float gain, + float bias ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; + register double res; + double v6, v5, v4; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register double ddimz = (double)tdimz-0.5; + register s8 *tbuf = (s8*)theBuf; + register s8 *tpt; + register s8 *rbuf = (s8*)resBuf; + register double b=bias; + register double g=gain; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + iz = (int)z; + tpt = (s8 *)tbuf; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) && + (z > 0.0) && (iz < t1dimz) ) { + /* the corresponding point is in the box defined + by (ix[+1],iy[+1],iz[+1]) */ + dx = x - ix; + dy = y - iy; + dz = z - iz; + dxdy = dx*dy; + dxdz = dx*dz; + dydz = dy*dz; + dxdydz = dxdy*dz; + + /* we have + v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) + v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) + v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) + v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) + v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) + v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) + v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) + v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) + */ + tpt += ix + iy * tdimx + iz * tdimxy + toffset1; + v6 = dxdz-dxdydz; + v5 = dxdy-dxdydz; + v4 = dx-dxdy-v6; + + res = 0; + res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ + tpt --; + res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ + tpt -= t1dimx; + res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ + tpt --; + res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ + tpt -= toffset2; + res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ + tpt --; + res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ + tpt -= t1dimx; + res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ + tpt --; + res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ + res = res * g + b; + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + /* here, we are sure we are on some border */ + tpt += ix + iy * tdimx + iz * tdimxy; + if ( (x < 0.0) || (ix == t1dimx) ) { + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (double)(*tpt) * g + b; + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ + tpt += tdimxy; + res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ + res = res * g + b; + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + dy = y - iy; + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ + res = res * g + b; + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt += toffset2+1; + res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt += tdimx; + res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ + res = res * g + b; + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is either + along the Y or the Z axis */ + dx = x - ix; + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ + res = res * g + b; + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += tdimxy-1; + res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt ++; + res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ + res = res * g + b; + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is along the Z axis */ + dy = y - iy; + res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += t1dimx; + res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt ++; + res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ + res = res * g + b; + *rbuf = (s8)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech3DNearest4x4_s8 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register s8 *tbuf = (s8*)theBuf; + register s8 *rbuf = (s8*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + ix = (int)(x+0.5); + if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + iy = (int)(y+0.5); + if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + iz = (int)(z+0.5); + if (( z < -0.5 ) || ( iz > t1dimz)) { *rbuf = 0; continue; } + + *rbuf = tbuf[ ix + iy * tdimx + iz * tdimxy ]; + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DTriLin4x4_s8 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy; + register double x, y, dx, dy, dxdy; + register double res, v; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + int toffset=tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register s8 *tbuf = (s8*)theBuf; + register s8 *tpt; + register s8 *rbuf = (s8*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (s8*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + tpt = (s8 *)tbuf; + tpt += ix + iy * tdimx; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) ) { + dx = x - ix; + dy = y - iy; + dxdy = dx*dy; + /* we have + v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) + v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) + v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) + v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) + */ + v = dy-dxdy; + res = 0; + res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ + tpt ++; + res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ + tpt += toffset; + res += v * (*tpt); /* tbuf(ix,iy+1 ) */ + tpt ++; + res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + + /* here, we are sure we are on some border */ + if ( (x < 0.0) || (ix == t1dimx) ) { + /* we just look at y */ + if ( (y < 0.0) || (iy == t1dimy) ) { + *rbuf = *tpt; + continue; + } + dy = y - iy; + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + dx = x - ix; + res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ + tpt ++; + res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ + *rbuf = (s8)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DTriLin4x4gb_s8 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat, /* transformation matrix */ + float gain, + float bias ) +{ + register int i, j, k, ix, iy; + register double x, y, dx, dy, dxdy; + register double res, v; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + int toffset=tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register s8 *tbuf = (s8*)theBuf; + register s8 *tpt; + register s8 *rbuf = (s8*)resBuf; + register double b=bias; + register double g=gain; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (s8*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + tpt = (s8 *)tbuf; + tpt += ix + iy * tdimx; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) ) { + dx = x - ix; + dy = y - iy; + dxdy = dx*dy; + /* we have + v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) + v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) + v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) + v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) + */ + v = dy-dxdy; + res = 0; + res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ + tpt ++; + res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ + tpt += toffset; + res += v * (*tpt); /* tbuf(ix,iy+1 ) */ + tpt ++; + res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ + res = res * g + b; + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + + /* here, we are sure we are on some border */ + if ( (x < 0.0) || (ix == t1dimx) ) { + /* we just look at y */ + if ( (y < 0.0) || (iy == t1dimy) ) { + res = (double)(*tpt) * g + b; + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + dy = y - iy; + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ + res = (double)(*tpt) * g + b; + *rbuf = (s8)_CONVERTI_( res ); + continue; + } + dx = x - ix; + res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ + tpt ++; + res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ + res = res * g + b; + *rbuf = (s8)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DNearest4x4_s8 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy; + register double x, y; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register s8 *tbuf = (s8*)theBuf; + register s8 *rbuf = (s8*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (s8*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + ix = (int)(x+0.5); + if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + iy = (int)(y+0.5); + if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } + + *rbuf = tbuf[ ix + iy * tdimx ]; + } + } +} + + + + + + +/* Resampling procedure. + + Work for 3D images, not for vectorial ones. + + (double* mat) is the matrix which permits to get + from resBuf into theBuf. + If one only have the matrix from theBuf into resBuf, + it must be inverted first. + + Soit x le point transforme et ix=(int)x; + nous allons distinguer les cas suivants : + x < -0.5 => resultat = 0 + -0.5 <= x < 0.0 => ix=0, on n'interpole pas selon X + 0.0 < x && ix < dimx-1 => on interpole selon X + x < dimx-0.5 => ix=dimx-1, on n'interpole pas selon X + x >= dimx-0.5 => resultat = 0 + +*/ + +CGAL_INLINE_FUNCTION +void Reech3DTriLin4x4_u16 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; + register double res; + double v6, v5, v4; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register double ddimz = (double)tdimz-0.5; + register u16 *tbuf = (u16*)theBuf; + register u16 *tpt; + register u16 *rbuf = (u16*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + iz = (int)z; + tpt = (u16 *)tbuf; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) && + (z > 0.0) && (iz < t1dimz) ) { + /* the corresponding point is in the box defined + by (ix[+1],iy[+1],iz[+1]) */ + dx = x - ix; + dy = y - iy; + dz = z - iz; + dxdy = dx*dy; + dxdz = dx*dz; + dydz = dy*dz; + dxdydz = dxdy*dz; + + /* we have + v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) + v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) + v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) + v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) + v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) + v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) + v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) + v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) + */ + tpt += ix + iy * tdimx + iz * tdimxy + toffset1; + v6 = dxdz-dxdydz; + v5 = dxdy-dxdydz; + v4 = dx-dxdy-v6; + + res = 0; + res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ + tpt --; + res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ + tpt -= t1dimx; + res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ + tpt --; + res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ + tpt -= toffset2; + res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ + tpt --; + res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ + tpt -= t1dimx; + res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ + tpt --; + res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + /* here, we are sure we are on some border */ + tpt += ix + iy * tdimx + iz * tdimxy; + if ( (x < 0.0) || (ix == t1dimx) ) { + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + *rbuf = *tpt; + continue; + } + dz = z - iz; + res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ + tpt += tdimxy; + res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + dy = y - iy; + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt += toffset2+1; + res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt += tdimx; + res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is either + along the Y or the Z axis */ + dx = x - ix; + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += tdimxy-1; + res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt ++; + res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is along the Z axis */ + dy = y - iy; + res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += t1dimx; + res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt ++; + res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ + *rbuf = (u16)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech3DTriLin4x4gb_u16 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat, /* transformation matrix */ + float gain, + float bias ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; + register double res; + double v6, v5, v4; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register double ddimz = (double)tdimz-0.5; + register u16 *tbuf = (u16*)theBuf; + register u16 *tpt; + register u16 *rbuf = (u16*)resBuf; + register double b=bias; + register double g=gain; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + iz = (int)z; + tpt = (u16 *)tbuf; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) && + (z > 0.0) && (iz < t1dimz) ) { + /* the corresponding point is in the box defined + by (ix[+1],iy[+1],iz[+1]) */ + dx = x - ix; + dy = y - iy; + dz = z - iz; + dxdy = dx*dy; + dxdz = dx*dz; + dydz = dy*dz; + dxdydz = dxdy*dz; + + /* we have + v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) + v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) + v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) + v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) + v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) + v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) + v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) + v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) + */ + tpt += ix + iy * tdimx + iz * tdimxy + toffset1; + v6 = dxdz-dxdydz; + v5 = dxdy-dxdydz; + v4 = dx-dxdy-v6; + + res = 0; + res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ + tpt --; + res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ + tpt -= t1dimx; + res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ + tpt --; + res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ + tpt -= toffset2; + res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ + tpt --; + res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ + tpt -= t1dimx; + res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ + tpt --; + res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ + res = res * g + b; + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + /* here, we are sure we are on some border */ + tpt += ix + iy * tdimx + iz * tdimxy; + if ( (x < 0.0) || (ix == t1dimx) ) { + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (double)(*tpt) * g + b; + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ + tpt += tdimxy; + res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ + res = res * g + b; + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + dy = y - iy; + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ + res = res * g + b; + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt += toffset2+1; + res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt += tdimx; + res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ + res = res * g + b; + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is either + along the Y or the Z axis */ + dx = x - ix; + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ + res = res * g + b; + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += tdimxy-1; + res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt ++; + res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ + res = res * g + b; + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is along the Z axis */ + dy = y - iy; + res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += t1dimx; + res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt ++; + res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ + res = res * g + b; + *rbuf = (u16)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech3DNearest4x4_u16 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register u16 *tbuf = (u16*)theBuf; + register u16 *rbuf = (u16*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + ix = (int)(x+0.5); + if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + iy = (int)(y+0.5); + if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + iz = (int)(z+0.5); + if (( z < -0.5 ) || ( iz > t1dimz)) { *rbuf = 0; continue; } + + *rbuf = tbuf[ ix + iy * tdimx + iz * tdimxy ]; + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DTriLin4x4_u16 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy; + register double x, y, dx, dy, dxdy; + register double res, v; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + int toffset=tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register u16 *tbuf = (u16*)theBuf; + register u16 *tpt; + register u16 *rbuf = (u16*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (u16*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + tpt = (u16 *)tbuf; + tpt += ix + iy * tdimx; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) ) { + dx = x - ix; + dy = y - iy; + dxdy = dx*dy; + /* we have + v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) + v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) + v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) + v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) + */ + v = dy-dxdy; + res = 0; + res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ + tpt ++; + res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ + tpt += toffset; + res += v * (*tpt); /* tbuf(ix,iy+1 ) */ + tpt ++; + res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + + /* here, we are sure we are on some border */ + if ( (x < 0.0) || (ix == t1dimx) ) { + /* we just look at y */ + if ( (y < 0.0) || (iy == t1dimy) ) { + *rbuf = *tpt; + continue; + } + dy = y - iy; + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + dx = x - ix; + res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ + tpt ++; + res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ + *rbuf = (u16)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DTriLin4x4gb_u16 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat, /* transformation matrix */ + float gain, + float bias ) +{ + register int i, j, k, ix, iy; + register double x, y, dx, dy, dxdy; + register double res, v; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + int toffset=tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register u16 *tbuf = (u16*)theBuf; + register u16 *tpt; + register u16 *rbuf = (u16*)resBuf; + register double b=bias; + register double g=gain; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (u16*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + tpt = (u16 *)tbuf; + tpt += ix + iy * tdimx; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) ) { + dx = x - ix; + dy = y - iy; + dxdy = dx*dy; + /* we have + v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) + v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) + v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) + v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) + */ + v = dy-dxdy; + res = 0; + res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ + tpt ++; + res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ + tpt += toffset; + res += v * (*tpt); /* tbuf(ix,iy+1 ) */ + tpt ++; + res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ + res = res * g + b; + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + + /* here, we are sure we are on some border */ + if ( (x < 0.0) || (ix == t1dimx) ) { + /* we just look at y */ + if ( (y < 0.0) || (iy == t1dimy) ) { + res = (double)(*tpt) * g + b; + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + dy = y - iy; + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ + res = (double)(*tpt) * g + b; + *rbuf = (u16)_CONVERTI_( res ); + continue; + } + dx = x - ix; + res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ + tpt ++; + res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ + res = res * g + b; + *rbuf = (u16)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DNearest4x4_u16 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy; + register double x, y; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register u16 *tbuf = (u16*)theBuf; + register u16 *rbuf = (u16*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (u16*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + ix = (int)(x+0.5); + if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + iy = (int)(y+0.5); + if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } + + *rbuf = tbuf[ ix + iy * tdimx ]; + } + } +} + + + + + + +/* Resampling procedure. + + Work for 3D images, not for vectorial ones. + + (double* mat) is the matrix which permits to get + from resBuf into theBuf. + If one only have the matrix from theBuf into resBuf, + it must be inverted first. + + Soit x le point transforme et ix=(int)x; + nous allons distinguer les cas suivants : + x < -0.5 => resultat = 0 + -0.5 <= x < 0.0 => ix=0, on n'interpole pas selon X + 0.0 < x && ix < dimx-1 => on interpole selon X + x < dimx-0.5 => ix=dimx-1, on n'interpole pas selon X + x >= dimx-0.5 => resultat = 0 + +*/ + +CGAL_INLINE_FUNCTION +void Reech3DTriLin4x4_s16 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; + register double res; + double v6, v5, v4; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register double ddimz = (double)tdimz-0.5; + register s16 *tbuf = (s16*)theBuf; + register s16 *tpt; + register s16 *rbuf = (s16*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + iz = (int)z; + tpt = (s16 *)tbuf; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) && + (z > 0.0) && (iz < t1dimz) ) { + /* the corresponding point is in the box defined + by (ix[+1],iy[+1],iz[+1]) */ + dx = x - ix; + dy = y - iy; + dz = z - iz; + dxdy = dx*dy; + dxdz = dx*dz; + dydz = dy*dz; + dxdydz = dxdy*dz; + + /* we have + v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) + v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) + v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) + v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) + v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) + v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) + v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) + v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) + */ + tpt += ix + iy * tdimx + iz * tdimxy + toffset1; + v6 = dxdz-dxdydz; + v5 = dxdy-dxdydz; + v4 = dx-dxdy-v6; + + res = 0; + res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ + tpt --; + res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ + tpt -= t1dimx; + res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ + tpt --; + res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ + tpt -= toffset2; + res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ + tpt --; + res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ + tpt -= t1dimx; + res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ + tpt --; + res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + /* here, we are sure we are on some border */ + tpt += ix + iy * tdimx + iz * tdimxy; + if ( (x < 0.0) || (ix == t1dimx) ) { + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + *rbuf = *tpt; + continue; + } + dz = z - iz; + res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ + tpt += tdimxy; + res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + dy = y - iy; + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt += toffset2+1; + res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt += tdimx; + res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is either + along the Y or the Z axis */ + dx = x - ix; + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += tdimxy-1; + res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt ++; + res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is along the Z axis */ + dy = y - iy; + res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += t1dimx; + res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt ++; + res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ + *rbuf = (s16)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech3DTriLin4x4gb_s16 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat, /* transformation matrix */ + float gain, + float bias ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; + register double res; + double v6, v5, v4; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register double ddimz = (double)tdimz-0.5; + register s16 *tbuf = (s16*)theBuf; + register s16 *tpt; + register s16 *rbuf = (s16*)resBuf; + register double b=bias; + register double g=gain; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + iz = (int)z; + tpt = (s16 *)tbuf; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) && + (z > 0.0) && (iz < t1dimz) ) { + /* the corresponding point is in the box defined + by (ix[+1],iy[+1],iz[+1]) */ + dx = x - ix; + dy = y - iy; + dz = z - iz; + dxdy = dx*dy; + dxdz = dx*dz; + dydz = dy*dz; + dxdydz = dxdy*dz; + + /* we have + v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) + v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) + v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) + v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) + v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) + v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) + v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) + v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) + */ + tpt += ix + iy * tdimx + iz * tdimxy + toffset1; + v6 = dxdz-dxdydz; + v5 = dxdy-dxdydz; + v4 = dx-dxdy-v6; + + res = 0; + res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ + tpt --; + res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ + tpt -= t1dimx; + res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ + tpt --; + res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ + tpt -= toffset2; + res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ + tpt --; + res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ + tpt -= t1dimx; + res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ + tpt --; + res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ + res = res * g + b; + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + /* here, we are sure we are on some border */ + tpt += ix + iy * tdimx + iz * tdimxy; + if ( (x < 0.0) || (ix == t1dimx) ) { + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (double)(*tpt) * g + b; + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ + tpt += tdimxy; + res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ + res = res * g + b; + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + dy = y - iy; + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ + res = res * g + b; + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt += toffset2+1; + res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt += tdimx; + res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ + res = res * g + b; + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is either + along the Y or the Z axis */ + dx = x - ix; + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ + res = res * g + b; + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + dz = z - iz; + res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += tdimxy-1; + res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt ++; + res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ + res = res * g + b; + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + /* here we are sure that the border is along the Z axis */ + dy = y - iy; + res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += t1dimx; + res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt ++; + res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ + res = res * g + b; + *rbuf = (s16)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech3DNearest4x4_s16 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register s16 *tbuf = (s16*)theBuf; + register s16 *rbuf = (s16*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + ix = (int)(x+0.5); + if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + iy = (int)(y+0.5); + if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + iz = (int)(z+0.5); + if (( z < -0.5 ) || ( iz > t1dimz)) { *rbuf = 0; continue; } + + *rbuf = tbuf[ ix + iy * tdimx + iz * tdimxy ]; + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DTriLin4x4_s16 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy; + register double x, y, dx, dy, dxdy; + register double res, v; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + int toffset=tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register s16 *tbuf = (s16*)theBuf; + register s16 *tpt; + register s16 *rbuf = (s16*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (s16*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + tpt = (s16 *)tbuf; + tpt += ix + iy * tdimx; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) ) { + dx = x - ix; + dy = y - iy; + dxdy = dx*dy; + /* we have + v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) + v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) + v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) + v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) + */ + v = dy-dxdy; + res = 0; + res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ + tpt ++; + res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ + tpt += toffset; + res += v * (*tpt); /* tbuf(ix,iy+1 ) */ + tpt ++; + res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + + /* here, we are sure we are on some border */ + if ( (x < 0.0) || (ix == t1dimx) ) { + /* we just look at y */ + if ( (y < 0.0) || (iy == t1dimy) ) { + *rbuf = *tpt; + continue; + } + dy = y - iy; + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + dx = x - ix; + res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ + tpt ++; + res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ + *rbuf = (s16)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DTriLin4x4gb_s16 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat, /* transformation matrix */ + float gain, + float bias ) +{ + register int i, j, k, ix, iy; + register double x, y, dx, dy, dxdy; + register double res, v; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + int toffset=tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register s16 *tbuf = (s16*)theBuf; + register s16 *tpt; + register s16 *rbuf = (s16*)resBuf; + register double b=bias; + register double g=gain; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (s16*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + tpt = (s16 *)tbuf; + tpt += ix + iy * tdimx; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) ) { + dx = x - ix; + dy = y - iy; + dxdy = dx*dy; + /* we have + v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) + v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) + v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) + v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) + */ + v = dy-dxdy; + res = 0; + res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ + tpt ++; + res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ + tpt += toffset; + res += v * (*tpt); /* tbuf(ix,iy+1 ) */ + tpt ++; + res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ + res = res * g + b; + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + + /* here, we are sure we are on some border */ + if ( (x < 0.0) || (ix == t1dimx) ) { + /* we just look at y */ + if ( (y < 0.0) || (iy == t1dimy) ) { + res = (double)(*tpt) * g + b; + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + dy = y - iy; + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ + res = (double)(*tpt) * g + b; + *rbuf = (s16)_CONVERTI_( res ); + continue; + } + dx = x - ix; + res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ + tpt ++; + res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ + res = res * g + b; + *rbuf = (s16)_CONVERTI_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DNearest4x4_s16 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy; + register double x, y; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register s16 *tbuf = (s16*)theBuf; + register s16 *rbuf = (s16*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (s16*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + ix = (int)(x+0.5); + if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + iy = (int)(y+0.5); + if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } + + *rbuf = tbuf[ ix + iy * tdimx ]; + } + } +} + + + + + + +/* Resampling procedure. + + Work for 3D images, not for vectorial ones. + + (double* mat) is the matrix which permits to get + from resBuf into theBuf. + If one only have the matrix from theBuf into resBuf, + it must be inverted first. + + Soit x le point transforme et ix=(int)x; + nous allons distinguer les cas suivants : + x < -0.5 => resultat = 0 + -0.5 <= x < 0.0 => ix=0, on n'interpole pas selon X + 0.0 < x && ix < dimx-1 => on interpole selon X + x < dimx-0.5 => ix=dimx-1, on n'interpole pas selon X + x >= dimx-0.5 => resultat = 0 + +*/ + +CGAL_INLINE_FUNCTION +void Reech3DTriLin4x4_r32 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; + register double res; + double v6, v5, v4; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register double ddimz = (double)tdimz-0.5; + register r32 *tbuf = (r32*)theBuf; + register r32 *tpt; + register r32 *rbuf = (r32*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + iz = (int)z; + tpt = (r32 *)tbuf; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) && + (z > 0.0) && (iz < t1dimz) ) { + /* the corresponding point is in the box defined + by (ix[+1],iy[+1],iz[+1]) */ + dx = x - ix; + dy = y - iy; + dz = z - iz; + dxdy = dx*dy; + dxdz = dx*dz; + dydz = dy*dz; + dxdydz = dxdy*dz; + + /* we have + v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) + v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) + v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) + v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) + v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) + v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) + v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) + v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) + */ + tpt += ix + iy * tdimx + iz * tdimxy + toffset1; + v6 = dxdz-dxdydz; + v5 = dxdy-dxdydz; + v4 = dx-dxdy-v6; + + res = 0; + res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ + tpt --; + res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ + tpt -= t1dimx; + res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ + tpt --; + res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ + tpt -= toffset2; + res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ + tpt --; + res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ + tpt -= t1dimx; + res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ + tpt --; + res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + /* here, we are sure we are on some border */ + tpt += ix + iy * tdimx + iz * tdimxy; + if ( (x < 0.0) || (ix == t1dimx) ) { + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + *rbuf = *tpt; + continue; + } + dz = z - iz; + res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ + tpt += tdimxy; + res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + dy = y - iy; + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + dz = z - iz; + res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt += toffset2+1; + res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt += tdimx; + res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + /* here we are sure that the border is either + along the Y or the Z axis */ + dx = x - ix; + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + dz = z - iz; + res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += tdimxy-1; + res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt ++; + res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + /* here we are sure that the border is along the Z axis */ + dy = y - iy; + res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += t1dimx; + res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt ++; + res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ + *rbuf = (r32)_CONVERTR_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech3DTriLin4x4gb_r32 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat, /* transformation matrix */ + float gain, + float bias ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z, dx, dy, dz, dxdy,dxdz,dydz,dxdydz; + register double res; + double v6, v5, v4; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + int toffset1=tdimxy+tdimx+1, toffset2=tdimxy-tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register double ddimz = (double)tdimz-0.5; + register r32 *tbuf = (r32*)theBuf; + register r32 *tpt; + register r32 *rbuf = (r32*)resBuf; + register double b=bias; + register double g=gain; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + if ((z < -0.5) || ( z > ddimz)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + iz = (int)z; + tpt = (r32 *)tbuf; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) && + (z > 0.0) && (iz < t1dimz) ) { + /* the corresponding point is in the box defined + by (ix[+1],iy[+1],iz[+1]) */ + dx = x - ix; + dy = y - iy; + dz = z - iz; + dxdy = dx*dy; + dxdz = dx*dz; + dydz = dy*dz; + dxdydz = dxdy*dz; + + /* we have + v[7]=dxdydz; coefficient of tbuf(ix+1,iy+1,iz+1) + v[6]=dxdz-dxdydz; coefficient of tbuf(ix+1,iy, iz+1) + v[5]=dxdy-dxdydz; coefficient of tbuf(ix+1,iy+1,iz ) + v[4]=dx-dxdy-v[6]; coefficient of tbuf(ix+1,iy ,iz ) + v[3]=dydz-dxdydz; coefficient of tbuf(ix ,iy+1,iz+1) + v[2]=dz-dydz-v[6]; coefficient of tbuf(ix ,iy ,iz+1) + v[1]=dy-dydz-v[5]; coefficient of tbuf(ix ,iy+1,iz ) + v[0]=1-dy-dz+dydz-v[4]; coefficient of tbuf(ix ,iy ,iz ) + */ + tpt += ix + iy * tdimx + iz * tdimxy + toffset1; + v6 = dxdz-dxdydz; + v5 = dxdy-dxdydz; + v4 = dx-dxdy-v6; + + res = 0; + res += dxdydz * (*tpt); /* tbuf(ix+1,iy+1,iz+1) */ + tpt --; + res += (dydz-dxdydz) * (*tpt); /* tbuf(ix ,iy+1,iz+1) */ + tpt -= t1dimx; + res += v6 * (*tpt); /* tbuf(ix+1 ,iy, iz+1) */ + tpt --; + res += (dz-dydz-v6) * (*tpt); /* tbuf(ix ,iy ,iz+1) */ + tpt -= toffset2; + res += v5 * (*tpt); /* tbuf(ix+1,iy+1,iz ) */ + tpt --; + res += (dy-dydz-v5) * (*tpt); /* tbuf(ix ,iy+1,iz ) */ + tpt -= t1dimx; + res += v4 * (*tpt); /* tbuf(ix+1,iy ,iz ) */ + tpt --; + res += (1-dy-dz+dydz-v4) * (*tpt); /* tbuf(ix ,iy ,iz ) */ + res = res * g + b; + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + /* here, we are sure we are on some border */ + tpt += ix + iy * tdimx + iz * tdimxy; + if ( (x < 0.0) || (ix == t1dimx) ) { + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (double)(*tpt) * g + b; + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + dz = z - iz; + res = (1-dz) * (*tpt); /* (1-dz)* tbuf(ix,iy,iz) */ + tpt += tdimxy; + res += dz * (*tpt); /* dz * tbuf(ix,iy,iz+1) */ + res = res * g + b; + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + dy = y - iy; + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1,iz) */ + res = res * g + b; + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + dz = z - iz; + res = (1-dy)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt += tdimx; + res += dy*(1-dz) * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt += toffset2+1; + res += (1-dy)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt += tdimx; + res += dy*dz * (*tpt); /* tbuf(ix,iy+1,iz+1) */ + res = res * g + b; + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + /* here we are sure that the border is either + along the Y or the Z axis */ + dx = x - ix; + if ( (y < 0.0) || (iy == t1dimy) ) { + if ( (z < 0.0) || (iz == t1dimz) ) { + res = (1-dx) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx * (*tpt); /* tbuf(ix+1,iy,iz) */ + res = res * g + b; + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + dz = z - iz; + res = (1-dx)*(1-dz) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dz) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += tdimxy-1; + res += (1-dx)*dz * (*tpt); /* tbuf(ix,iy,iz+1) */ + tpt ++; + res += dx*dz * (*tpt); /* tbuf(ix+1,iy,iz+1) */ + res = res * g + b; + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + /* here we are sure that the border is along the Z axis */ + dy = y - iy; + res = (1-dx)*(1-dy) * (*tpt); /* tbuf(ix,iy,iz) */ + tpt ++; + res += dx*(1-dy) * (*tpt); /* tbuf(ix+1,iy,iz) */ + tpt += t1dimx; + res += (1-dx)*dy * (*tpt); /* tbuf(ix,iy+1,iz) */ + tpt ++; + res += dx*dy * (*tpt); /* tbuf(ix+1,iy+1,iz) */ + res = res * g + b; + *rbuf = (r32)_CONVERTR_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech3DNearest4x4_r32 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy, iz; + register double x, y, z; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1], tdimz=theDim[2]; + int tdimxy=tdimx*tdimy; + register int t1dimx=tdimx-1, t1dimy=tdimy-1, t1dimz=tdimz-1; + register r32 *tbuf = (r32*)theBuf; + register r32 *rbuf = (r32*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[2] * k + mat[3]; + ix = (int)(x+0.5); + if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[6] * k + mat[7]; + iy = (int)(y+0.5); + if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } + z = mat[8] * i + mat[9] * j + mat[10] * k + mat[11]; + iz = (int)(z+0.5); + if (( z < -0.5 ) || ( iz > t1dimz)) { *rbuf = 0; continue; } + + *rbuf = tbuf[ ix + iy * tdimx + iz * tdimxy ]; + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DTriLin4x4_r32 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy; + register double x, y, dx, dy, dxdy; + register double res, v; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + int toffset=tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register r32 *tbuf = (r32*)theBuf; + register r32 *tpt; + register r32 *rbuf = (r32*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (r32*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + tpt = (r32 *)tbuf; + tpt += ix + iy * tdimx; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) ) { + dx = x - ix; + dy = y - iy; + dxdy = dx*dy; + /* we have + v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) + v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) + v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) + v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) + */ + v = dy-dxdy; + res = 0; + res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ + tpt ++; + res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ + tpt += toffset; + res += v * (*tpt); /* tbuf(ix,iy+1 ) */ + tpt ++; + res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + + /* here, we are sure we are on some border */ + if ( (x < 0.0) || (ix == t1dimx) ) { + /* we just look at y */ + if ( (y < 0.0) || (iy == t1dimy) ) { + *rbuf = *tpt; + continue; + } + dy = y - iy; + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + dx = x - ix; + res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ + tpt ++; + res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ + *rbuf = (r32)_CONVERTR_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DTriLin4x4gb_r32 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat, /* transformation matrix */ + float gain, + float bias ) +{ + register int i, j, k, ix, iy; + register double x, y, dx, dy, dxdy; + register double res, v; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + int toffset=tdimx-1; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register double ddimx = (double)tdimx-0.5, ddimy = (double)tdimy-0.5; + register r32 *tbuf = (r32*)theBuf; + register r32 *tpt; + register r32 *rbuf = (r32*)resBuf; + register double b=bias; + register double g=gain; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (r32*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + if ((x < -0.5) || ( x > ddimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + if ((y < -0.5) || ( y > ddimy)) { *rbuf = 0; continue; } + + /* here, the point lies on the borders or completely inside + the image */ + ix = (int)x; + iy = (int)y; + tpt = (r32 *)tbuf; + tpt += ix + iy * tdimx; + + /* are we on the border or not ? */ + if ( (x > 0.0) && (ix < t1dimx) && + (y > 0.0) && (iy < t1dimy) ) { + dx = x - ix; + dy = y - iy; + dxdy = dx*dy; + /* we have + v[5]=dxdy; coefficient of tbuf(ix+1,iy+1) + v[4]=dx-dxdy; coefficient of tbuf(ix+1,iy ) + v[1]=dy-dxdy; coefficient of tbuf(ix ,iy+1) + v[0]=1-dx-dy+dxdy; coefficient of tbuf(ix ,iy ) + */ + v = dy-dxdy; + res = 0; + res += (1-dx-v) * (*tpt); /* tbuf(ix ,iy ) */ + tpt ++; + res += (dx-dxdy) * (*tpt); /* tbuf(ix+1,iy ) */ + tpt += toffset; + res += v * (*tpt); /* tbuf(ix,iy+1 ) */ + tpt ++; + res += dxdy * (*tpt); /* tbuf(ix+1,iy+1) */ + res = res * g + b; + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + + /* here, we are sure we are on some border */ + if ( (x < 0.0) || (ix == t1dimx) ) { + /* we just look at y */ + if ( (y < 0.0) || (iy == t1dimy) ) { + res = (double)(*tpt) * g + b; + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + dy = y - iy; + res = (1-dy) * (*tpt); /* (1-dy)* tbuf(ix,iy) */ + tpt += tdimx; + res += dy * (*tpt); /* dy * tbuf(ix,iy+1) */ + res = (double)(*tpt) * g + b; + *rbuf = (r32)_CONVERTR_( res ); + continue; + } + dx = x - ix; + res = (1-dx) * (*tpt); /* (1-dx)* tbuf(ix,iy) */ + tpt ++; + res += dx * (*tpt); /* dx * tbuf(ix+1,iy) */ + res = res * g + b; + *rbuf = (r32)_CONVERTR_( res ); + } + } +} + +CGAL_INLINE_FUNCTION +void Reech2DNearest4x4_r32 ( void* theBuf, /* buffer to be resampled */ + int *theDim, /* dimensions of this buffer */ + void* resBuf, /* result buffer */ + int *resDim, /* dimensions of this buffer */ + double* mat /* transformation matrix */ + ) +{ + register int i, j, k, ix, iy; + register double x, y; + int rdimx=resDim[0], rdimy=resDim[1], rdimz=resDim[2]; + int tdimx=theDim[0], tdimy=theDim[1]; + register int t1dimx=tdimx-1, t1dimy=tdimy-1; + register r32 *tbuf = (r32*)theBuf; + register r32 *rbuf = (r32*)resBuf; + + for ( k = 0; k < rdimz; k ++ ) { + if ( get_static_verbose_reech4x4() != 0 ) + fprintf( stderr, "Processing slice %d\r", k ); + /* tbuf represente le premier point du plan */ + tbuf = (r32*)theBuf; + tbuf += k*(tdimx * tdimy); + for ( j = 0; j < rdimy; j ++ ) + for ( i = 0; i < rdimx; i ++, rbuf ++ ) { + /* computation of the corresponding point coordinates in theBuf */ + x = mat[0] * i + mat[1] * j + mat[3]; + ix = (int)(x+0.5); + if (( x < -0.5 ) || ( ix > t1dimx)) { *rbuf = 0; continue; } + y = mat[4] * i + mat[5] * j + mat[7]; + iy = (int)(y+0.5); + if (( y < -0.5 ) || ( iy > t1dimy)) { *rbuf = 0; continue; } + + *rbuf = tbuf[ ix + iy * tdimx ]; + } + } +} + + + + + + +CGAL_INLINE_FUNCTION +void Reech4x4_verbose ( ) +{ + get_static_verbose_reech4x4() = 1; +} + +CGAL_INLINE_FUNCTION +void Reech4x4_noverbose ( ) +{ + get_static_verbose_reech4x4() = 0; +} diff --git a/CGAL_ImageIO/test/CGAL_ImageIO/test_trilinear_interpolation.cpp b/CGAL_ImageIO/test/CGAL_ImageIO/test_trilinear_interpolation.cpp index 2e73b6d1b3f..10222b3f24e 100644 --- a/CGAL_ImageIO/test/CGAL_ImageIO/test_trilinear_interpolation.cpp +++ b/CGAL_ImageIO/test/CGAL_ImageIO/test_trilinear_interpolation.cpp @@ -124,7 +124,7 @@ int main() { { // fill the 2x2x2 image for(int i = 0; i < 8; ++i) { - data[i] = CGAL::default_random.get_int(0,255); + data[i] = CGAL::get_default_random().get_int(0,255); } // test the difference between the two implementations diff --git a/CMakeLists.txt b/CMakeLists.txt index 22994ec982c..55120ee0cff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,10 @@ project(CGAL CXX C) # Minimal version of CMake: cmake_minimum_required(VERSION 2.8.11) +# add_definitions(-DCGAL_HEADER_ONLY) +# message("CGAL WITH HEADER ONLY") +# message("CGAL with libraries") + # option for branch build option( CGAL_BRANCH_BUILD "Create CGAL from branch" ON) diff --git a/Generator/examples/Generator/random_degenerate_point_set.cpp b/Generator/examples/Generator/random_degenerate_point_set.cpp index b9e32d1f952..d1bc4325cf9 100644 --- a/Generator/examples/Generator/random_degenerate_point_set.cpp +++ b/Generator/examples/Generator/random_degenerate_point_set.cpp @@ -40,7 +40,7 @@ int main() { // Use a random permutation to hide the creation history // of the point set. - std::random_shuffle( points.begin(), points.end(), default_random); + std::random_shuffle( points.begin(), points.end(), get_default_random()); // Check range of values. for ( Vector::iterator i = points.begin(); i != points.end(); i++){ diff --git a/Generator/include/CGAL/generators.h b/Generator/include/CGAL/generators.h index 3e38f593bc8..0bdc224b7ed 100644 --- a/Generator/include/CGAL/generators.h +++ b/Generator/include/CGAL/generators.h @@ -68,7 +68,7 @@ protected: public: typedef Random_generator_base This; - Random_generator_base() : _rnd( default_random) {} + Random_generator_base() : _rnd( CGAL::get_default_random() ) {} Random_generator_base( double range, Random& rnd) : Generator_base( range), _rnd( rnd) {} Random_generator_base( const T& item, double range, Random& rnd) @@ -83,7 +83,7 @@ class Random_double_in_interval : public Random_generator_base { public: typedef Random_double_in_interval This; - Random_double_in_interval(double a = 1, Random& rnd = default_random) + Random_double_in_interval(double a = 1, Random& rnd = CGAL::get_default_random()) // g is an input iterator creating points of type `P' uniformly // distributed in the half-open square with side length a, // centered around the origin, i.e. \forall p = `*g': -\frac{a}{2} diff --git a/Generator/include/CGAL/point_generators_2.h b/Generator/include/CGAL/point_generators_2.h index 801baad7015..48101f05bbd 100644 --- a/Generator/include/CGAL/point_generators_2.h +++ b/Generator/include/CGAL/point_generators_2.h @@ -38,7 +38,7 @@ class Random_points_in_disc_2 : public Random_generator_base

{ void generate_point(); public: typedef Random_points_in_disc_2 This; - Random_points_in_disc_2( double r = 1, Random& rnd = default_random) + Random_points_in_disc_2( double r = 1, Random& rnd = CGAL::get_default_random()) // g is an input iterator creating points of type `P' uniformly // distributed in the open disc with radius r, i.e. |`*g'| < r . // Two random numbers are needed from `rnd' for each point. @@ -73,7 +73,7 @@ class Random_points_on_circle_2 : public Random_generator_base

{ void generate_point(); public: typedef Random_points_on_circle_2 This; - Random_points_on_circle_2( double r = 1, Random& rnd = default_random) + Random_points_on_circle_2( double r = 1, Random& rnd = CGAL::get_default_random()) // g is an input iterator creating points of type `P' uniformly // distributed on the circle with radius r, i.e. |`*g'| == r . A // single random number is needed from `rnd' for each point. @@ -107,7 +107,7 @@ class Random_points_in_square_2 : public Random_generator_base

{ void generate_point(); public: typedef Random_points_in_square_2 This; - Random_points_in_square_2( double a = 1, Random& rnd = default_random) + Random_points_in_square_2( double a = 1, Random& rnd = CGAL::get_default_random()) // g is an input iterator creating points of type `P' uniformly // distributed in the half-open square with side length a, // centered around the origin, i.e. \forall p = `*g': -\frac{a}{2} @@ -143,7 +143,7 @@ class Random_points_on_square_2 : public Random_generator_base

{ void generate_point(); public: typedef Random_points_on_square_2 This; - Random_points_on_square_2( double a = 1, Random& rnd = default_random) + Random_points_on_square_2( double a = 1, Random& rnd = CGAL::get_default_random()) // g is an input iterator creating points of type `P' uniformly // distributed on the boundary of the square with side length a, // centered around the origin, i.e. \forall p = `*g': one @@ -196,7 +196,7 @@ class Random_points_in_iso_rectangle_2 : public Random_generator_base

{ void generate_point(); public: typedef Random_points_in_iso_rectangle_2 This; - Random_points_in_iso_rectangle_2( const P&p, const P& q, Random& rnd = default_random) + Random_points_in_iso_rectangle_2( const P&p, const P& q, Random& rnd = CGAL::get_default_random()) : Random_generator_base

( 1.0 , rnd) { left = (std::min)(to_double(p.x()), to_double(q.x())); @@ -240,7 +240,7 @@ public: typedef Random_points_on_segment_2 This; Random_points_on_segment_2( const P& p = P( -1, 0), const P& q = P( 1, 0), - Random& rnd = default_random) + Random& rnd = CGAL::get_default_random()) // g is an input iterator creating points of type `P' uniformly // distributed on the segment from p to q except q, i.e. `*g' == // \lambda p + (1-\lambda)\, q where 0 <= \lambda < 1 . A single @@ -425,7 +425,7 @@ void perturb_points_2( ForwardIterator first, double xeps, double yeps) { - perturb_points_2( first, last, xeps, yeps, default_random); + perturb_points_2( first, last, xeps, yeps, CGAL::get_default_random()); } template @@ -433,7 +433,7 @@ void perturb_points_2( ForwardIterator first, ForwardIterator last, double xeps) { - perturb_points_2( first, last, xeps, xeps, default_random); + perturb_points_2( first, last, xeps, xeps, CGAL::get_default_random()); } template OutputIterator random_collinear_points_2( @@ -491,7 +491,7 @@ OutputIterator random_collinear_points_2( OutputIterator first2) { return random_collinear_points_2( first, last, n, first2, - default_random); + CGAL::get_default_random()); } template < class P, class Creator = diff --git a/Generator/include/CGAL/point_generators_3.h b/Generator/include/CGAL/point_generators_3.h index afad4b0231d..5b9670c63a0 100644 --- a/Generator/include/CGAL/point_generators_3.h +++ b/Generator/include/CGAL/point_generators_3.h @@ -38,7 +38,7 @@ class Random_points_in_sphere_3 : public Random_generator_base

{ void generate_point(); public: typedef Random_points_in_sphere_3 This; - Random_points_in_sphere_3( double r = 1, Random& rnd = default_random) + Random_points_in_sphere_3( double r = 1, Random& rnd = CGAL::get_default_random()) // g is an input iterator creating points of type `P' uniformly // distributed in the open sphere with radius r, i.e. |`*g'| < r . // Three random numbers are needed from `rnd' for each point @@ -77,7 +77,7 @@ class Random_points_on_sphere_3 : public Random_generator_base

{ void generate_point(); public: typedef Random_points_on_sphere_3 This; - Random_points_on_sphere_3( double r = 1, Random& rnd = default_random) + Random_points_on_sphere_3( double r = 1, Random& rnd = CGAL::get_default_random()) // g is an input iterator creating points of type `P' uniformly // distributed on the sphere with radius r, i.e. |`*g'| == r . A // two random numbers are needed from `rnd' for each point. @@ -115,7 +115,7 @@ class Random_points_in_cube_3 : public Random_generator_base

{ void generate_point(); public: typedef Random_points_in_cube_3 This; - Random_points_in_cube_3( double a = 1, Random& rnd = default_random) + Random_points_in_cube_3( double a = 1, Random& rnd = CGAL::get_default_random()) : Random_generator_base

( a, rnd) { generate_point(); } This& operator++() { generate_point(); diff --git a/Generator/include/CGAL/point_generators_d.h b/Generator/include/CGAL/point_generators_d.h index f946ea126d0..59d11fd6bc3 100644 --- a/Generator/include/CGAL/point_generators_d.h +++ b/Generator/include/CGAL/point_generators_d.h @@ -35,7 +35,7 @@ class Random_points_in_ball_d : public Random_generator_base

{ public: typedef Random_points_in_ball_d

This; Random_points_in_ball_d( int dim, double a = 1, - Random& rnd = default_random) + Random& rnd = get_default_random()) // g is an input iterator creating points of type `P' uniformly // distributed in the open sphere with radius r, i.e. |`*g'| < r . : Random_generator_base

( a, rnd), dimension(dim) { generate_point(); } @@ -84,7 +84,7 @@ class Random_points_on_sphere_d : public Random_generator_base

{ public: typedef Random_points_on_sphere_d

This; Random_points_on_sphere_d( int dim, double a = 1, - Random& rnd = default_random) + Random& rnd = get_default_random()) // g is an input iterator creating points of type `P' uniformly // distributed on the sphere with radius r, i.e. |`*g'| == r . : Random_generator_base

( a, rnd), dimension(dim) { generate_point(); } @@ -129,7 +129,7 @@ class Random_points_in_cube_d : public Random_generator_base

{ public: typedef Random_points_in_cube_d

This; Random_points_in_cube_d( int dim, double a = 1, - Random& rnd = default_random) + Random& rnd = get_default_random()) : Random_generator_base

( a, rnd), dimension(dim) { generate_point(); } This& operator++() { generate_point(); diff --git a/Generator/include/CGAL/random_selection.h b/Generator/include/CGAL/random_selection.h index 0a4283b1279..b671b19e910 100644 --- a/Generator/include/CGAL/random_selection.h +++ b/Generator/include/CGAL/random_selection.h @@ -57,7 +57,7 @@ OutputIterator random_selection( RandomAccessIterator first, Size n, OutputIterator result) { - return random_selection( first, last, n, result, default_random); + return random_selection( first, last, n, result, get_default_random()); } } //namespace CGAL diff --git a/Generator/test/Generator/test_generators.cpp b/Generator/test/Generator/test_generators.cpp index addc06c7eea..9c4788ee9e3 100644 --- a/Generator/test/Generator/test_generators.cpp +++ b/Generator/test/Generator/test_generators.cpp @@ -97,7 +97,7 @@ void test_point_generators_2() { perturb_points_2( i1, i2, 10.0); // Create a random permutation. - std::random_shuffle( points.begin(), points.end(), default_random); + std::random_shuffle( points.begin(), points.end(), get_default_random()); assert( points.size() == 1000); for ( std::vector::iterator i = points.begin(); diff --git a/Geomview/include/CGAL/IO/Geomview_stream.h b/Geomview/include/CGAL/IO/Geomview_stream.h index e3b3f222fe1..daaa728c5c0 100644 --- a/Geomview/include/CGAL/IO/Geomview_stream.h +++ b/Geomview/include/CGAL/IO/Geomview_stream.h @@ -26,6 +26,9 @@ #define CGAL_GEOMVIEW_STREAM_H #include + +#ifdef CGAL_USE_GEOMVIEW + #include #include #include @@ -593,4 +596,10 @@ operator>>(Geomview_stream &gv, Point_3 &point) } //namespace CGAL +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + +#endif // CGAL_USE_GEOMVIEW + #endif // CGAL_GEOMVIEW_STREAM_H diff --git a/Geomview/include/CGAL/IO/Geomview_stream_impl.h b/Geomview/include/CGAL/IO/Geomview_stream_impl.h new file mode 100644 index 00000000000..7eb8dd2fb36 --- /dev/null +++ b/Geomview/include/CGAL/IO/Geomview_stream_impl.h @@ -0,0 +1,612 @@ +// Copyright (c) 1999-2004 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Andreas Fabri, Herve Bronnimann, Sylvain Pion + +#ifdef CGAL_USE_GEOMVIEW + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include +#include +#include +#include + +#include // kill() on SunPro requires these 2 #includes. +#include + +#include + +namespace CGAL { + +CGAL_INLINE_FUNCTION +Geomview_stream::Geomview_stream(const Bbox_3 &bbox, + const char *machine, + const char *login) + : bb(bbox), vertex_color(BLACK), edge_color(BLACK), face_color(BLACK), + wired_flag(false), echo_flag(true), raw_flag(false), + trace_flag(false), binary_flag(false), + line_width(1) +{ + setup_geomview(machine, login); + frame(bbox); + pickplane(bbox); + set_vertex_radius((bbox.xmax() - bbox.xmin())/100.0); +} + +CGAL_INLINE_FUNCTION +Geomview_stream::~Geomview_stream() +{ + kill(pid, SIGKILL); // kills geomview +} + +CGAL_INLINE_FUNCTION +void Geomview_stream::setup_geomview(const char *machine, const char *login) +{ + int pipe_out[2], pipe_in[2]; + + // Communication between CGAL and geomview should be possible + // in two directions. To achieve this we open two pipes + + std::cout << "Starting Geomview..." << std::flush; + if (pipe(pipe_out) < 0) { + CGAL_error_msg( "out pipe failed" ); + } + + if (pipe(pipe_in) < 0) { + CGAL_error_msg( "in pipe failed" ); + } + + switch (pid = fork()){ + case -1: + CGAL_error_msg( "fork failed" ); + case 0: // The child process + close(pipe_out[1]); // does not write to the out pipe, + close(pipe_in[0]); // does not read from the in pipe. + + if (dup2(pipe_out[0], 0) != 0) + std::cerr << "Connect pipe to stdin failed." << std::endl; + if (dup2(pipe_in[1], 1) != 1) + std::cerr << "Connect pipe to stdout failed." << std::endl; + + if (machine && (std::strlen(machine)>0)) { + std::string s (" rgeomview "); + s += machine; + s += ":0.0"; + execlp("rsh", "rsh", machine, "-l", login, s.data(), + static_cast(NULL)); // cast to stop gcc warning + } else { + execlp("geomview", "geomview", "-c", "-", + static_cast(NULL)); // cast to stop gcc warning + } + + // if we get to this point something went wrong. + std::cerr << "execl geomview failed" << std::endl; + switch(errno) { + case EACCES: + std::cerr << "please check your environment variable PATH" + << std::endl; + std::cerr << "make sure the file `geomview' is contained in it" + << std::endl; + std::cerr << "and is executable" << std::endl; + break; + case ELOOP: + std::cerr << "too many links for filename `geomview'" << std::endl; + break; + default: + std::cerr << "error number " << errno << " (check `man execlp')" + << std::endl; + }; + CGAL_error(); + default: // The parent process + close(pipe_out[0]); // does not read from the out pipe, + close(pipe_in[1]); // does not write to the in pipe. + + in = pipe_in[0]; + out = pipe_out[1]; + + // Necessary to wait a little bit for Geomview, + // otherwise you won't be able to ask for points... + sleep(1); + +#if 1 + // We want to get rid of the requirement in the CGAL doc about + // (echo "started"). But we want to be backward compatible, that is, + // people who have this echo in their .geomview must still have CGAL + // working, at least for a few public releases. + // So the plan is to send, from CGAL, the command : (echo "CGAL-3D") + // It's the same length as "started", 7. + // Then we read 7 chars from Geomview, and test which string it is. + // If it's "CGAL-3D", then fine, the user doesn't have .geomview with + // the back-compatible echo command. + // In the very long run, we'll be able to get rid of all this code as + // well. + // Maybe we should simply read the pipe, till we find "CGAL-3D" ? + + *this << "(echo \"CGAL-3D\")"; + + char inbuf[10]; + std::size_t retread=::read(in, inbuf, 7); + (void)retread; + + if (std::strncmp(inbuf, "started", 7) == 0) + { + // std::cerr << "You still have a .geomview file with the\n" + // << "(echo \"started\") command. Note that this is not\n" + // << "compulsory anymore, since CGAL 2.3" << std::endl; + + // Then the next one is supposed to be CGAL-3D. + retread=::read(in, inbuf, 7); + (void)retread; + if (std::strncmp(inbuf, "CGAL-3D", 7) != 0) + std::cerr << "Unexpected string from Geomview !" << std::endl; + } + else if (std::strncmp(inbuf, "CGAL-3D", 7) == 0) + { + // std::cerr << "Good, you don't have a .geomview file with the\n" + // << "(echo \"started\") command" << std::endl; + } + else + { + std::cerr << "Unexcepted string from Geomview at initialization!\n" + << "Going on nevertheless !" << std::endl; + } +#else + // Old original version + char inbuf[10]; + // Waits for "started" from the .geomview file. + retread=::read(in, inbuf, 7); + (void)retread; +#endif + + std::cout << "done." << std::endl; + + (*this) << "(normalization g* none)(bbox-draw g* no)"; + } +} + +CGAL_INLINE_FUNCTION +void +Geomview_stream::pickplane(const Bbox_3 &bbox) +{ + bool bin_bak = set_binary_mode(); + (*this) << "(geometry pickplane {QUAD BINARY\n" + << 1 + // here are the four corners + << bbox.xmin() << bbox.ymin() << bbox.zmin() + << bbox.xmin() << bbox.ymax() << bbox.zmin() + << bbox.xmax() << bbox.ymax() << bbox.zmin() + << bbox.xmax() << bbox.ymin() << bbox.zmin() + + // close the text bracket + << "}) (pickable pickplane no)"; + set_ascii_mode(bin_bak); +} + +CGAL_INLINE_FUNCTION +void +Geomview_stream::clear() +{ + (*this) << "(delete World)"; + id.clear(); +} + +CGAL_INLINE_FUNCTION +void +Geomview_stream::look_recenter() +{ + (*this) << "(look-recenter World)"; +} + +CGAL_INLINE_FUNCTION +Geomview_stream& +Geomview_stream::operator<<(const std::string & s) +{ + if ((int)s.length() != ::write(out, s.data(), s.length())) { + CGAL_error_msg( "write problem in the pipe while sending data to geomview" ); + } + trace(s); + + return *this; +} + +CGAL_INLINE_FUNCTION +Geomview_stream& +Geomview_stream::operator<<(int i) +{ + // Depending on the mode chosen + if (get_binary_mode()) { + // we write raw binary data to the stream. + int num = i; + I_swap_to_big_endian(num); + std::size_t retwrite=::write(out, (char*)&num, sizeof(num)); + (void)retwrite; + trace(i); + } else { + // transform the int in a character sequence and put whitespace around + std::ostringstream str; + str << i << ' ' << std::ends; + *this << str.str().c_str(); + } + + return *this; +} + +CGAL_INLINE_FUNCTION +Geomview_stream& +Geomview_stream::operator<<(unsigned int i) +{ + // Depending on the mode chosen + if (get_binary_mode()) { + // we write raw binary data to the stream. + unsigned int num = i; + I_swap_to_big_endian(num); + std::size_t retwrite=::write(out, (char*)&num, sizeof(num)); + (void)retwrite; + trace(i); + } else { + // transform the int in a character sequence and put whitespace around + std::ostringstream str; + str << i << ' ' << std::ends; + *this << str.str().c_str(); + } + + return *this; +} + +CGAL_INLINE_FUNCTION +Geomview_stream& +Geomview_stream::operator<<(long i) +{ + return operator<<((int) i); +} + +CGAL_INLINE_FUNCTION +Geomview_stream& +Geomview_stream::operator<<(unsigned long i) +{ + return operator<<((unsigned int) i); +} + +CGAL_INLINE_FUNCTION +Geomview_stream& +Geomview_stream::operator<<(double d) +{ + float f = d; + if (get_binary_mode()) { + float num = d; + I_swap_to_big_endian(num); + std::size_t retwrite= ::write(out, (char*)&num, sizeof(num)); + (void)retwrite; + trace(f); + } else { + // 'copy' the float in a string and append a blank + std::ostringstream str; + str << f << ' ' << std::ends; + *this << str.str().c_str(); + } + return *this; +} + +CGAL_INLINE_FUNCTION +Geomview_stream& +operator<<(Geomview_stream &gv, const Bbox_2 &bbox) +{ + bool ascii_bak = gv.set_ascii_mode(); + gv << "(geometry " << gv.get_new_id("Bbox") + << " {VECT 1 5 0 5 0 "; + // here are the four corners + + gv << bbox.xmin() << bbox.ymin() << 0.0 + << bbox.xmin() << bbox.ymax() << 0.0 + << bbox.xmax() << bbox.ymax() << 0.0 + << bbox.xmax() << bbox.ymin() << 0.0 + << bbox.xmin() << bbox.ymin() << 0.0; + + // close the text bracket + gv << "})"; + gv.set_ascii_mode(ascii_bak); + + return gv; +} + +CGAL_INLINE_FUNCTION +Geomview_stream& +operator<<(Geomview_stream &gv, const Bbox_3 &bbox) +{ + bool ascii_bak = gv.set_ascii_mode(); + gv << "(geometry " << gv.get_new_id("Bbox") + << " {appearance {material {edgecolor " + << gv.ecr() << gv.ecg() << gv.ecb() << "}}{SKEL 8 4 " + // here are the corners + << bbox.xmin() << bbox.ymin() << bbox.zmin() + << bbox.xmin() << bbox.ymax() << bbox.zmin() + << bbox.xmax() << bbox.ymax() << bbox.zmin() + << bbox.xmax() << bbox.ymin() << bbox.zmin() + << bbox.xmax() << bbox.ymin() << bbox.zmax() + << bbox.xmax() << bbox.ymax() << bbox.zmax() + << bbox.xmin() << bbox.ymax() << bbox.zmax() + << bbox.xmin() << bbox.ymin() << bbox.zmax() + + << "10 0 1 2 3 4 5 6 7 0 3\n" + << "2 1 6\n" + << "2 2 5\n" + << "2 4 7\n" + + // close the text bracket + << "}})"; + gv.set_ascii_mode(ascii_bak); + + return gv; +} + +CGAL_INLINE_FUNCTION +void +Geomview_stream::set_bg_color(const Color &c) +{ + bool ascii_bak = set_ascii_mode(); + *this << "(backcolor \"Camera\" " + << double(c.r())/255.0 + << double(c.g())/255.0 + << double(c.b())/255.0 + << ")"; + set_ascii_mode(ascii_bak); +} + +CGAL_INLINE_FUNCTION +Geomview_stream& +Geomview_stream::operator<<(const Color &c) +{ + vertex_color = edge_color = face_color = c; + return (*this); +} + +CGAL_INLINE_FUNCTION +Color +Geomview_stream::get_vertex_color() const +{ + return vertex_color; +} + +CGAL_INLINE_FUNCTION +Color +Geomview_stream::get_edge_color() const +{ + return edge_color; +} + +CGAL_INLINE_FUNCTION +Color +Geomview_stream::get_face_color() const +{ + return face_color; +} + +CGAL_INLINE_FUNCTION +Color +Geomview_stream::set_vertex_color(const Color &c) +{ + Color old = vertex_color; + vertex_color = c; + return old; +} + +CGAL_INLINE_FUNCTION +Color +Geomview_stream::set_edge_color(const Color &c) +{ + Color old = edge_color; + edge_color = c; + return old; +} + +CGAL_INLINE_FUNCTION +Color +Geomview_stream::set_face_color(const Color &c) +{ + Color old = face_color; + face_color = c; + return old; +} + +CGAL_INLINE_FUNCTION +double +Geomview_stream::vcr() const +{ + return double(vertex_color.r())/255.0; +} + +CGAL_INLINE_FUNCTION +double +Geomview_stream::vcg() const +{ + return double(vertex_color.g())/255.0; +} + +CGAL_INLINE_FUNCTION +double +Geomview_stream::vcb() const +{ + return double(vertex_color.b())/255.0; +} + +CGAL_INLINE_FUNCTION +double +Geomview_stream::ecr() const +{ + return double(edge_color.r())/255.0; +} + +CGAL_INLINE_FUNCTION +double +Geomview_stream::ecg() const +{ + return double(edge_color.g())/255.0; +} + +CGAL_INLINE_FUNCTION +double +Geomview_stream::ecb() const +{ + return double(edge_color.b())/255.0; +} + +CGAL_INLINE_FUNCTION +double +Geomview_stream::fcr() const +{ + return double(face_color.r())/255.0; +} + +CGAL_INLINE_FUNCTION +double +Geomview_stream::fcg() const +{ + return double(face_color.g())/255.0; +} + +CGAL_INLINE_FUNCTION +double +Geomview_stream::fcb() const +{ + return double(face_color.b())/255.0; +} + +CGAL_INLINE_FUNCTION +void +Geomview_stream::frame(const Bbox_3 &bbox) +{ + (*this) << bbox << "(look-recenter g0 c0)"; +} + +CGAL_INLINE_FUNCTION +Geomview_stream& +Geomview_stream::operator>>(char *expr) +{ + // Skip whitespaces + do { + std::size_t retread=::read(in, expr, 1); + (void)retread; + } while (expr[0] != '('); + + int pcount = 1; + int i = 1; + while (1) { + std::size_t retread=::read(in, &expr[i], 1); + (void)retread; + if (expr[i] == ')'){ + pcount--; + } else if (expr[i] == '('){ + pcount++; + } + if (pcount == 0){ + expr[i+1]='\0'; + break; // we encountered a balanced number of parantheses + } + i++; + } + return *this; +} + +// Parse a Lisp expression, return a pointer to the beginning of the +// nth subexpression, and terminate it by '\0'. +// It's either a word terminated by ' ' or ')', or a well parenthesed +// expression, or a quoted "string". +CGAL_INLINE_FUNCTION +char* +Geomview_stream::nth(char* s, int count) +{ + s++; // skip first character (always a parenthesis) + + // Skip "count" words. + for(; count != 0; count--) { + while (*s == ' ') // skip whitespaces + s++; + s++; + while (*s != ' ') // skip a word + s++; + } + while (*s == ' ') // skip whitespaces + s++; + + // Now we have the beginning of the searched sub-expression. + int j = 1; + if (*s == '(') // Case of a well-parenthesed expression. + for (int pcount = 1; pcount != 0;) { + if (s[j] == ')') pcount--; + if (s[j] == '(') pcount++; + j++; + } + else if (*s == '"') { // Case of a quoted "string". + while (s[j] != '"') + j++; + j++; + } + else // Case of a word terminated by ' ' or ')'. + while (s[j] != ' ' && s[j] != ')') + j++; + + s[j] = '\0'; + return s; +} + +CGAL_INLINE_FUNCTION +void +Geomview_stream::parse_point(const char* pickpoint, + double &x, double &y, double &z, double &w) +{ + std::stringstream ss; + ss << pickpoint << std::ends; + + char parenthesis; + ss >> parenthesis >> x >> y >> z >> w; +} + +CGAL_INLINE_FUNCTION +std::string +Geomview_stream::get_new_id(const std::string & s) +{ + std::ostringstream str; + str << s << id[s]++ << std::ends; + return str.str(); +} + +} //namespace CGAL + +#else + +#ifndef CGAL_HEADER_ONLY +// Add a dummy symbol to prevent warnings of empty translation unit. +namespace CGAL { +namespace { +int dummy; +} +} //namespace CGAL +#endif + +#endif // CGAL_USE_GEOMVIEW diff --git a/Geomview/src/CGAL/Geomview_stream.cpp b/Geomview/src/CGAL/Geomview_stream.cpp index a34af8ceabc..927d518f8d0 100644 --- a/Geomview/src/CGAL/Geomview_stream.cpp +++ b/Geomview/src/CGAL/Geomview_stream.cpp @@ -22,550 +22,9 @@ // // Author(s) : Andreas Fabri, Herve Bronnimann, Sylvain Pion -#include - -#ifdef CGAL_USE_GEOMVIEW - -#include -#include -#include -#include -#include -#include - -#include // kill() on SunPro requires these 2 #includes. -#include +#ifndef CGAL_HEADER_ONLY #include -#include +#include -namespace CGAL { - -Geomview_stream::Geomview_stream(const Bbox_3 &bbox, - const char *machine, - const char *login) - : bb(bbox), vertex_color(BLACK), edge_color(BLACK), face_color(BLACK), - wired_flag(false), echo_flag(true), raw_flag(false), - trace_flag(false), binary_flag(false), - line_width(1) -{ - setup_geomview(machine, login); - frame(bbox); - pickplane(bbox); - set_vertex_radius((bbox.xmax() - bbox.xmin())/100.0); -} - -Geomview_stream::~Geomview_stream() -{ - kill(pid, SIGKILL); // kills geomview -} - -void Geomview_stream::setup_geomview(const char *machine, const char *login) -{ - int pipe_out[2], pipe_in[2]; - - // Communication between CGAL and geomview should be possible - // in two directions. To achieve this we open two pipes - - std::cout << "Starting Geomview..." << std::flush; - if (pipe(pipe_out) < 0) { - CGAL_error_msg( "out pipe failed" ); - } - - if (pipe(pipe_in) < 0) { - CGAL_error_msg( "in pipe failed" ); - } - - switch (pid = fork()){ - case -1: - CGAL_error_msg( "fork failed" ); - case 0: // The child process - close(pipe_out[1]); // does not write to the out pipe, - close(pipe_in[0]); // does not read from the in pipe. - - if (dup2(pipe_out[0], 0) != 0) - std::cerr << "Connect pipe to stdin failed." << std::endl; - if (dup2(pipe_in[1], 1) != 1) - std::cerr << "Connect pipe to stdout failed." << std::endl; - - if (machine && (std::strlen(machine)>0)) { - std::string s (" rgeomview "); - s += machine; - s += ":0.0"; - execlp("rsh", "rsh", machine, "-l", login, s.data(), - static_cast(NULL)); // cast to stop gcc warning - } else { - execlp("geomview", "geomview", "-c", "-", - static_cast(NULL)); // cast to stop gcc warning - } - - // if we get to this point something went wrong. - std::cerr << "execl geomview failed" << std::endl; - switch(errno) { - case EACCES: - std::cerr << "please check your environment variable PATH" - << std::endl; - std::cerr << "make sure the file `geomview' is contained in it" - << std::endl; - std::cerr << "and is executable" << std::endl; - break; - case ELOOP: - std::cerr << "too many links for filename `geomview'" << std::endl; - break; - default: - std::cerr << "error number " << errno << " (check `man execlp')" - << std::endl; - }; - CGAL_error(); - default: // The parent process - close(pipe_out[0]); // does not read from the out pipe, - close(pipe_in[1]); // does not write to the in pipe. - - in = pipe_in[0]; - out = pipe_out[1]; - - // Necessary to wait a little bit for Geomview, - // otherwise you won't be able to ask for points... - sleep(1); - -#if 1 - // We want to get rid of the requirement in the CGAL doc about - // (echo "started"). But we want to be backward compatible, that is, - // people who have this echo in their .geomview must still have CGAL - // working, at least for a few public releases. - // So the plan is to send, from CGAL, the command : (echo "CGAL-3D") - // It's the same length as "started", 7. - // Then we read 7 chars from Geomview, and test which string it is. - // If it's "CGAL-3D", then fine, the user doesn't have .geomview with - // the back-compatible echo command. - // In the very long run, we'll be able to get rid of all this code as - // well. - // Maybe we should simply read the pipe, till we find "CGAL-3D" ? - - *this << "(echo \"CGAL-3D\")"; - - char inbuf[10]; - std::size_t retread=::read(in, inbuf, 7); - (void)retread; - - if (std::strncmp(inbuf, "started", 7) == 0) - { - // std::cerr << "You still have a .geomview file with the\n" - // << "(echo \"started\") command. Note that this is not\n" - // << "compulsory anymore, since CGAL 2.3" << std::endl; - - // Then the next one is supposed to be CGAL-3D. - retread=::read(in, inbuf, 7); - (void)retread; - if (std::strncmp(inbuf, "CGAL-3D", 7) != 0) - std::cerr << "Unexpected string from Geomview !" << std::endl; - } - else if (std::strncmp(inbuf, "CGAL-3D", 7) == 0) - { - // std::cerr << "Good, you don't have a .geomview file with the\n" - // << "(echo \"started\") command" << std::endl; - } - else - { - std::cerr << "Unexcepted string from Geomview at initialization!\n" - << "Going on nevertheless !" << std::endl; - } -#else - // Old original version - char inbuf[10]; - // Waits for "started" from the .geomview file. - retread=::read(in, inbuf, 7); - (void)retread; #endif - - std::cout << "done." << std::endl; - - (*this) << "(normalization g* none)(bbox-draw g* no)"; - } -} - -void -Geomview_stream::pickplane(const Bbox_3 &bbox) -{ - bool bin_bak = set_binary_mode(); - (*this) << "(geometry pickplane {QUAD BINARY\n" - << 1 - // here are the four corners - << bbox.xmin() << bbox.ymin() << bbox.zmin() - << bbox.xmin() << bbox.ymax() << bbox.zmin() - << bbox.xmax() << bbox.ymax() << bbox.zmin() - << bbox.xmax() << bbox.ymin() << bbox.zmin() - - // close the text bracket - << "}) (pickable pickplane no)"; - set_ascii_mode(bin_bak); -} - -void -Geomview_stream::clear() -{ - (*this) << "(delete World)"; - id.clear(); -} - -void -Geomview_stream::look_recenter() -{ - (*this) << "(look-recenter World)"; -} - -Geomview_stream& -Geomview_stream::operator<<(const std::string & s) -{ - if ((int)s.length() != ::write(out, s.data(), s.length())) { - CGAL_error_msg( "write problem in the pipe while sending data to geomview" ); - } - trace(s); - - return *this; -} - -Geomview_stream& -Geomview_stream::operator<<(int i) -{ - // Depending on the mode chosen - if (get_binary_mode()) { - // we write raw binary data to the stream. - int num = i; - I_swap_to_big_endian(num); - std::size_t retwrite=::write(out, (char*)&num, sizeof(num)); - (void)retwrite; - trace(i); - } else { - // transform the int in a character sequence and put whitespace around - std::ostringstream str; - str << i << ' ' << std::ends; - *this << str.str().c_str(); - } - - return *this; -} - -Geomview_stream& -Geomview_stream::operator<<(unsigned int i) -{ - // Depending on the mode chosen - if (get_binary_mode()) { - // we write raw binary data to the stream. - unsigned int num = i; - I_swap_to_big_endian(num); - std::size_t retwrite=::write(out, (char*)&num, sizeof(num)); - (void)retwrite; - trace(i); - } else { - // transform the int in a character sequence and put whitespace around - std::ostringstream str; - str << i << ' ' << std::ends; - *this << str.str().c_str(); - } - - return *this; -} - -Geomview_stream& -Geomview_stream::operator<<(long i) -{ - return operator<<((int) i); -} - -Geomview_stream& -Geomview_stream::operator<<(unsigned long i) -{ - return operator<<((unsigned int) i); -} - -Geomview_stream& -Geomview_stream::operator<<(double d) -{ - float f = d; - if (get_binary_mode()) { - float num = d; - I_swap_to_big_endian(num); - std::size_t retwrite= ::write(out, (char*)&num, sizeof(num)); - (void)retwrite; - trace(f); - } else { - // 'copy' the float in a string and append a blank - std::ostringstream str; - str << f << ' ' << std::ends; - *this << str.str().c_str(); - } - return *this; -} - -Geomview_stream& -operator<<(Geomview_stream &gv, const Bbox_2 &bbox) -{ - bool ascii_bak = gv.set_ascii_mode(); - gv << "(geometry " << gv.get_new_id("Bbox") - << " {VECT 1 5 0 5 0 "; - // here are the four corners - - gv << bbox.xmin() << bbox.ymin() << 0.0 - << bbox.xmin() << bbox.ymax() << 0.0 - << bbox.xmax() << bbox.ymax() << 0.0 - << bbox.xmax() << bbox.ymin() << 0.0 - << bbox.xmin() << bbox.ymin() << 0.0; - - // close the text bracket - gv << "})"; - gv.set_ascii_mode(ascii_bak); - - return gv; -} - -Geomview_stream& -operator<<(Geomview_stream &gv, const Bbox_3 &bbox) -{ - bool ascii_bak = gv.set_ascii_mode(); - gv << "(geometry " << gv.get_new_id("Bbox") - << " {appearance {material {edgecolor " - << gv.ecr() << gv.ecg() << gv.ecb() << "}}{SKEL 8 4 " - // here are the corners - << bbox.xmin() << bbox.ymin() << bbox.zmin() - << bbox.xmin() << bbox.ymax() << bbox.zmin() - << bbox.xmax() << bbox.ymax() << bbox.zmin() - << bbox.xmax() << bbox.ymin() << bbox.zmin() - << bbox.xmax() << bbox.ymin() << bbox.zmax() - << bbox.xmax() << bbox.ymax() << bbox.zmax() - << bbox.xmin() << bbox.ymax() << bbox.zmax() - << bbox.xmin() << bbox.ymin() << bbox.zmax() - - << "10 0 1 2 3 4 5 6 7 0 3\n" - << "2 1 6\n" - << "2 2 5\n" - << "2 4 7\n" - - // close the text bracket - << "}})"; - gv.set_ascii_mode(ascii_bak); - - return gv; -} - -void -Geomview_stream::set_bg_color(const Color &c) -{ - bool ascii_bak = set_ascii_mode(); - *this << "(backcolor \"Camera\" " - << double(c.r())/255.0 - << double(c.g())/255.0 - << double(c.b())/255.0 - << ")"; - set_ascii_mode(ascii_bak); -} - -Geomview_stream& -Geomview_stream::operator<<(const Color &c) -{ - vertex_color = edge_color = face_color = c; - return (*this); -} - -Color -Geomview_stream::get_vertex_color() const -{ - return vertex_color; -} - -Color -Geomview_stream::get_edge_color() const -{ - return edge_color; -} - -Color -Geomview_stream::get_face_color() const -{ - return face_color; -} - -Color -Geomview_stream::set_vertex_color(const Color &c) -{ - Color old = vertex_color; - vertex_color = c; - return old; -} - -Color -Geomview_stream::set_edge_color(const Color &c) -{ - Color old = edge_color; - edge_color = c; - return old; -} - -Color -Geomview_stream::set_face_color(const Color &c) -{ - Color old = face_color; - face_color = c; - return old; -} - -double -Geomview_stream::vcr() const -{ - return double(vertex_color.r())/255.0; -} - -double -Geomview_stream::vcg() const -{ - return double(vertex_color.g())/255.0; -} - -double -Geomview_stream::vcb() const -{ - return double(vertex_color.b())/255.0; -} - -double -Geomview_stream::ecr() const -{ - return double(edge_color.r())/255.0; -} - -double -Geomview_stream::ecg() const -{ - return double(edge_color.g())/255.0; -} - -double -Geomview_stream::ecb() const -{ - return double(edge_color.b())/255.0; -} - -double -Geomview_stream::fcr() const -{ - return double(face_color.r())/255.0; -} - -double -Geomview_stream::fcg() const -{ - return double(face_color.g())/255.0; -} - -double -Geomview_stream::fcb() const -{ - return double(face_color.b())/255.0; -} - -void -Geomview_stream::frame(const Bbox_3 &bbox) -{ - (*this) << bbox << "(look-recenter g0 c0)"; -} - -Geomview_stream& -Geomview_stream::operator>>(char *expr) -{ - // Skip whitespaces - do { - std::size_t retread=::read(in, expr, 1); - (void)retread; - } while (expr[0] != '('); - - int pcount = 1; - int i = 1; - while (1) { - std::size_t retread=::read(in, &expr[i], 1); - (void)retread; - if (expr[i] == ')'){ - pcount--; - } else if (expr[i] == '('){ - pcount++; - } - if (pcount == 0){ - expr[i+1]='\0'; - break; // we encountered a balanced number of parantheses - } - i++; - } - return *this; -} - -// Parse a Lisp expression, return a pointer to the beginning of the -// nth subexpression, and terminate it by '\0'. -// It's either a word terminated by ' ' or ')', or a well parenthesed -// expression, or a quoted "string". -char* -Geomview_stream::nth(char* s, int count) -{ - s++; // skip first character (always a parenthesis) - - // Skip "count" words. - for(; count != 0; count--) { - while (*s == ' ') // skip whitespaces - s++; - s++; - while (*s != ' ') // skip a word - s++; - } - while (*s == ' ') // skip whitespaces - s++; - - // Now we have the beginning of the searched sub-expression. - int j = 1; - if (*s == '(') // Case of a well-parenthesed expression. - for (int pcount = 1; pcount != 0;) { - if (s[j] == ')') pcount--; - if (s[j] == '(') pcount++; - j++; - } - else if (*s == '"') { // Case of a quoted "string". - while (s[j] != '"') - j++; - j++; - } - else // Case of a word terminated by ' ' or ')'. - while (s[j] != ' ' && s[j] != ')') - j++; - - s[j] = '\0'; - return s; -} - -void -Geomview_stream::parse_point(const char* pickpoint, - double &x, double &y, double &z, double &w) -{ - std::stringstream ss; - ss << pickpoint << std::ends; - - char parenthesis; - ss >> parenthesis >> x >> y >> z >> w; -} - -std::string -Geomview_stream::get_new_id(const std::string & s) -{ - std::ostringstream str; - str << s << id[s]++ << std::ends; - return str.str(); -} - -} //namespace CGAL - -#else - -// Add a dummy symbol to prevent warnings of empty translation unit. -namespace CGAL { -namespace { -int dummy; -} -} //namespace CGAL - -#endif // CGAL_USE_GEOMVIEW diff --git a/GraphicsView/include/CGAL/Qt/DemosMainWindow.h b/GraphicsView/include/CGAL/Qt/DemosMainWindow.h index ef5f0e8ee10..6339c812a6a 100644 --- a/GraphicsView/include/CGAL/Qt/DemosMainWindow.h +++ b/GraphicsView/include/CGAL/Qt/DemosMainWindow.h @@ -21,6 +21,7 @@ #ifndef CGAL_QT_DEMOS_MAIN_WINDOW_H #define CGAL_QT_DEMOS_MAIN_WINDOW_H + #include #include #include @@ -127,4 +128,8 @@ protected: Q_DECLARE_OPERATORS_FOR_FLAGS(CGAL::Qt::DemosMainWindow::Options) +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_QT_DEMOS_MAIN_WINDOW_H diff --git a/GraphicsView/include/CGAL/Qt/DemosMainWindow_impl.h b/GraphicsView/include/CGAL/Qt/DemosMainWindow_impl.h new file mode 100644 index 00000000000..32fa8676be3 --- /dev/null +++ b/GraphicsView/include/CGAL/Qt/DemosMainWindow_impl.h @@ -0,0 +1,474 @@ +// Copyright (c) 2008 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Andreas Fabri +// Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // needed to get CGAL_VERSION_STR +#include +#include + +namespace CGAL { +namespace Qt { + +CGAL_INLINE_FUNCTION +DemosMainWindow::DemosMainWindow(QWidget * parent, ::Qt::WindowFlags flags) + : QMainWindow(parent, flags), + maxNumRecentFiles(10), + recentFileActs(maxNumRecentFiles) +{ + // prepare the QLabel xycoord for inclusion in the statusBar() + xycoord = new QLabel(" -0.00000 , -0.00000 ", this); + xycoord->setAlignment(::Qt::AlignHCenter); + xycoord->setMinimumSize(xycoord->sizeHint()); + xycoord->clear(); + + actionUse_OpenGL = new QAction(this); + actionUse_OpenGL->setObjectName("actionUse_OpenGL"); + actionUse_OpenGL->setCheckable(true); + actionUse_OpenGL->setText(tr("Use &OpenGL")); + actionUse_OpenGL->setStatusTip(tr("Make Qt use OpenGL to display the graphical items, instead of its native painting system.")); + actionUse_OpenGL->setShortcut(tr("Ctrl+G")); + + actionUse_Antialiasing = new QAction(this); + actionUse_Antialiasing->setObjectName("actionUse_Antialiasing"); + actionUse_Antialiasing->setCheckable(true); + actionUse_Antialiasing->setText(tr("Use &anti-aliasing")); + actionUse_Antialiasing->setStatusTip(tr("Make Qt use anti-aliasing when displaying the graphical items.")); + actionUse_Antialiasing->setShortcut(tr("Ctrl+A")); + + actionAboutCGAL = new QAction(this); + actionAboutCGAL->setObjectName("actionAboutCGAL"); + actionAboutCGAL->setText(tr("About &CGAL...")); + + actionAbout = new QAction(this); + actionAbout->setObjectName("actionAbout"); + actionAbout->setText(tr("&About...")); + + setAcceptDrops(true); +} + +CGAL_INLINE_FUNCTION +DemosMainWindow::~DemosMainWindow() +{ +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::dragEnterEvent(QDragEnterEvent *event) +{ + if (event->mimeData()->hasFormat("text/uri-list")) + event->acceptProposedAction(); +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::dropEvent(QDropEvent *event) +{ + Q_FOREACH(QUrl url, event->mimeData()->urls()) { + QString filename = url.toLocalFile(); + this->open(filename); + } + event->acceptProposedAction(); +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::addNavigation(QGraphicsView* graphicsView) +{ + navigation = new CGAL::Qt::GraphicsViewNavigation(); + graphicsView->viewport()->installEventFilter(navigation); + graphicsView->installEventFilter(navigation); + QObject::connect(navigation, SIGNAL(mouseCoordinates(QString)), + xycoord, SLOT(setText(QString))); + view = graphicsView; +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::setupStatusBar() +{ + this->statusBar()->addWidget(new QLabel(this), 1); + this->statusBar()->addWidget(xycoord, 0); +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::setupOptionsMenu(QMenu* menuOptions) +{ + // search for the Options menu + if(!menuOptions) { + menuOptions = getMenu("menuOptions", tr("&Options")); + } + + // if not found, then create it + if(!menuOptions) { + menuOptions = new QMenu(this->menuBar()); + menuOptions->setTitle(tr("&Options")); + this->menuBar()->addAction(menuOptions->menuAction()); + menuOptions->setObjectName("menuOptions"); + } + + if(!menuOptions->isEmpty()) { + menuOptions->addSeparator(); + } + menuOptions->addAction(actionUse_OpenGL); + menuOptions->addAction(actionUse_Antialiasing); + connect(actionUse_Antialiasing, SIGNAL(toggled(bool)), + this, SLOT(setUseAntialiasing(bool))); + connect(actionUse_OpenGL, SIGNAL(toggled(bool)), + this, SLOT(setUseOpenGL(bool))); + actionUse_Antialiasing->setChecked(true); +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::setupExportSVG(QAction* action, QGraphicsView* view) +{ + this->view = view; + connect(action, SIGNAL(triggered(bool)), + this, SLOT(exportSVG())); +} + +CGAL_INLINE_FUNCTION +void DemosMainWindow::exportSVG() +{ + QString fileName = QFileDialog::getSaveFileName(this, + tr("Export to SVG"), + ".", + tr("SVG (*.svg)\n")); + + QSvgGenerator svg; + svg.setFileName(fileName); + + svg.setSize(this->view->size()); + svg.setViewBox(this->view->sceneRect()); + svg.setTitle(tr("%1 drawing").arg(qApp->applicationName())); + svg.setDescription(tr("Generated using %1").arg(qApp->applicationName())); + + QPainter painter; + painter.begin(&svg); + this->view->render(&painter); + painter.end(); +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::setUseAntialiasing(bool checked) +{ + view->setRenderHint(QPainter::Antialiasing, checked); + view->setRenderHint(QPainter::HighQualityAntialiasing, checked); + + statusBar()->showMessage(tr("Antialiasing %1activated").arg(checked?"":"de-"), + 1000); +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::setUseOpenGL(bool checked) +{ + if(checked) { + QGLWidget* new_viewport = new QGLWidget; + + // Setup the format to allow antialiasing with OpenGL: + // one need to activate the SampleBuffers, if the graphic driver allows + // this. + QGLFormat glformat = new_viewport->format(); + glformat.setOption(QGL::SampleBuffers); + new_viewport->setFormat(glformat); + + view->setViewport(new_viewport); + } + else { + view->setViewport(new QWidget); + } + statusBar()->showMessage(tr("OpenGL %1activated").arg(checked?"":"de-"), + 1000); + view->viewport()->installEventFilter(navigation); + view->setFocus(); +} + +CGAL_INLINE_FUNCTION +QMenu* +DemosMainWindow::getMenu(QString objectName, QString title) +{ + QMenu* menu = NULL; + + QString title2 = title; + title2.remove('&'); + // search if a menu has objectName()==objectName + menu = this->findChild(objectName); + + // then search if a menu has title()==title + if(menu) { + return menu; + } else { + Q_FOREACH(menu, this->findChildren()) { + if(menu->title() == title || + menu->title() == title2) { + return menu; + } + } + } + return NULL; +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::popupAboutBox(QString title, QString html_resource_name) +{ + QFile about_CGAL(html_resource_name); + about_CGAL.open(QIODevice::ReadOnly); + QString about_CGAL_txt = QTextStream(&about_CGAL).readAll(); +#ifdef CGAL_VERSION_STR + QString cgal_version(CGAL_VERSION_STR); +# ifdef CGAL_FAKE_PUBLIC_RELEASE + cgal_version.replace(QRegExp("-Ic?.*"), ""); +# endif + about_CGAL_txt.replace("", + QString(" (version %1)") + .arg(cgal_version)); +#endif + QMessageBox mb(QMessageBox::NoIcon, + title, + about_CGAL_txt, + QMessageBox::Ok, + this); + + QLabel* mb_label = mb.findChild("qt_msgbox_label"); + if(mb_label) { + mb_label->setTextInteractionFlags(mb_label->textInteractionFlags() | + ::Qt::LinksAccessibleByMouse | + ::Qt::LinksAccessibleByKeyboard); + } + else { + std::cerr << "Cannot find child \"qt_msgbox_label\" in QMessageBox\n" + << " with Qt version " << QT_VERSION_STR << "!\n"; + } + mb.exec(); +} + +CGAL_INLINE_FUNCTION +QMenu* DemosMainWindow::getHelpMenu() +{ + QMenu* menuHelp = getMenu("menuHelp", tr("&Help")); + if(!menuHelp) { + menuHelp = new QMenu(this->menuBar()); + menuHelp->setTitle(tr("&Help")); + this->menuBar()->addAction(menuHelp->menuAction()); + menuHelp->setObjectName("menuHelp"); + } + return menuHelp; +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::addAboutCGAL(QMenu* menuHelp) +{ + if(!menuHelp) { + menuHelp = getHelpMenu(); + } + menuHelp->addAction(actionAboutCGAL); + + connect(actionAboutCGAL, SIGNAL(triggered()), + this, SLOT(popupAboutCGAL())); +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::addAboutDemo(QString htmlResourceName, QMenu* menuHelp) +{ + if(!menuHelp) { + menuHelp = getHelpMenu(); + } + menuHelp->addAction(actionAbout); + aboutHtmlResource = htmlResourceName; + + connect(actionAbout, SIGNAL(triggered()), + this, SLOT(popupAboutDemo())); +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::popupAboutCGAL() +{ + popupAboutBox(tr("About CGAL..."), + ":/cgal/help/about_CGAL.html"); +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::popupAboutDemo() +{ + popupAboutBox(tr("About the demo..."), + aboutHtmlResource); +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::setMaxNumberOfRecentFiles(const unsigned int i) +{ + maxNumRecentFiles = i; + recentFileActs.resize(maxNumRecentFiles); +} + +CGAL_INLINE_FUNCTION +unsigned int +DemosMainWindow::maxNumberOfRecentFiles() const +{ + return maxNumRecentFiles; +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::openRecentFile_aux() +{ + QAction *action = qobject_cast(sender()); + if (action) + emit openRecentFile(action->data().toString()); +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::addToRecentFiles(QString fileName) +{ + QSettings settings; + QStringList files = settings.value("recentFileList").toStringList(); + files.removeAll(fileName); + files.prepend(fileName); + while (files.size() > (int)maxNumberOfRecentFiles()) + files.removeLast(); + + settings.setValue("recentFileList", files); + + updateRecentFileActions(); +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::addRecentFiles(QMenu* menu, QAction* insertBeforeAction) +{ + if(!insertBeforeAction) { + recentFilesSeparator = menu->addSeparator(); + } + + for (unsigned int i = 0; i < maxNumberOfRecentFiles(); ++i) { + recentFileActs[i] = new QAction(this); + recentFileActs[i]->setVisible(false); + connect(recentFileActs[i], SIGNAL(triggered()), + this, SLOT(openRecentFile_aux())); + if(insertBeforeAction) + menu->insertAction(insertBeforeAction, recentFileActs[i]); + else + menu->addAction(recentFileActs[i]); + } + + if(insertBeforeAction) { + recentFilesSeparator = menu->insertSeparator(insertBeforeAction); + } + + recentFilesSeparator->setVisible(false); + + updateRecentFileActions(); +} + +CGAL_INLINE_FUNCTION +void +DemosMainWindow::updateRecentFileActions() +{ + QSettings settings; + QStringList files = settings.value("recentFileList").toStringList(); + + int numRecentFiles = qMin(files.size(), (int)this->maxNumberOfRecentFiles()); + + for (int i = 0; i < numRecentFiles; ++i) { + QString strippedName = QFileInfo(files[i]).fileName(); + QString text = tr("&%1 %2").arg(i).arg(strippedName); + recentFileActs[i]->setText(text); + recentFileActs[i]->setData(files[i]); + recentFileActs[i]->setVisible(true); + } + for (unsigned int j = numRecentFiles; j < maxNumberOfRecentFiles(); ++j) + recentFileActs[j]->setVisible(false); + + recentFilesSeparator->setVisible(numRecentFiles > 0); +} + +CGAL_INLINE_FUNCTION +void DemosMainWindow::writeState(QString groupname) +{ + QSettings settings; + + settings.beginGroup(groupname); + settings.setValue("size", size()); + settings.setValue("pos", pos()); + settings.setValue("state", saveState()); + settings.endGroup(); +} + +CGAL_INLINE_FUNCTION +void DemosMainWindow::readState(QString groupname, Options /*what_to_save*/) +{ + QSettings settings; + + settings.beginGroup(groupname); + resize(settings.value("size", this->size()).toSize()); + + QDesktopWidget* desktop = qApp->desktop(); + QPoint pos = settings.value("pos", this->pos()).toPoint(); + if(desktop->availableGeometry(pos).contains(pos)) { + move(pos); + } + QByteArray mainWindowState = settings.value("state").toByteArray(); + if(!mainWindowState.isNull()) { + this->restoreState(mainWindowState); + } + settings.endGroup(); +} + + +} // namespace Qt +} // namespace CGAL diff --git a/GraphicsView/include/CGAL/Qt/GraphicsViewNavigation.h b/GraphicsView/include/CGAL/Qt/GraphicsViewNavigation.h index 3e212431381..f5314a9f41d 100644 --- a/GraphicsView/include/CGAL/Qt/GraphicsViewNavigation.h +++ b/GraphicsView/include/CGAL/Qt/GraphicsViewNavigation.h @@ -70,4 +70,8 @@ private: } // namespace Qt } // namespace CGAL +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_QT_GRAPHICS_VIEW_NAVIGATION_H diff --git a/GraphicsView/include/CGAL/Qt/GraphicsViewNavigation_impl.h b/GraphicsView/include/CGAL/Qt/GraphicsViewNavigation_impl.h new file mode 100644 index 00000000000..0570920869f --- /dev/null +++ b/GraphicsView/include/CGAL/Qt/GraphicsViewNavigation_impl.h @@ -0,0 +1,351 @@ +// Copyright (c) 2008 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Andreas Fabri +// Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include // for mapToScene(QGraphicsView*, QRect) +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace CGAL { +namespace Qt { + + CGAL_INLINE_FUNCTION + GraphicsViewNavigation::GraphicsViewNavigation() + : rectItem(new QGraphicsRectItem), + dragging(false) + { + QColor rect_color(250, 221, 0); + rect_color.setAlpha(50); + rectItem->setBrush(rect_color); + rect_color.setAlpha(255); + rectItem->setPen(QPen(rect_color, 0, ::Qt::DashLine)); + rectItem->hide(); + rectItem->setZValue(10000); + } + + CGAL_INLINE_FUNCTION + GraphicsViewNavigation::~GraphicsViewNavigation() + { + delete rectItem; + } + + CGAL_INLINE_FUNCTION + bool + GraphicsViewNavigation::eventFilter(QObject *obj, QEvent *event) + { + QGraphicsView* v = qobject_cast(obj); + if(v == NULL) { + QWidget* viewport = qobject_cast(obj); + if(viewport == NULL) { + return false; + } + v = qobject_cast(viewport->parent()); + if(v == NULL) { + return false; + } + } + switch(event->type()) + { + case QEvent::KeyPress: { + QKeyEvent *keyEvent = static_cast(event); + int offset = 10; + if( (keyEvent->modifiers() & ::Qt::ShiftModifier) + || (keyEvent->modifiers() & ::Qt::ControlModifier) ) { + offset = 20; + } + switch (keyEvent->key()) { + case ::Qt::Key_Up: + translateView(v, 0, -offset); + break; + case ::Qt::Key_Down: + translateView(v, 0, offset); + break; + case ::Qt::Key_Left: + translateView(v, -offset, 0); + break; + case ::Qt::Key_Right: + translateView(v, offset, 0); + break; + case ::Qt::Key_PageUp: + v->rotate(-6); + break; + case ::Qt::Key_PageDown: + v->rotate(6); + break; + case ::Qt::Key_Plus: + scaleView(v, 1.2); + break; + case ::Qt::Key_Minus: + scaleView(v, 1 / 1.2); + break; + case ::Qt::Key_Control: + cursor_backup = v->cursor(); + v->setCursor(::Qt::CrossCursor); + default: + return false; + } + // display_parameters(); + return true; + break; + } // end case KeyPress + case QEvent::KeyRelease: { + QKeyEvent *keyEvent = static_cast(event); + if(keyEvent->key() == ::Qt::Key_Control) { + if(rectItem->isVisible() ) { + dragging = false; + v->scene()->removeItem(rectItem); + rectItem->hide(); + } + v->setCursor(cursor_backup); + return true; + } + return false; + break; + } // end case KeyRelease + case QEvent::Wheel: { + QWheelEvent *wheelEvent = static_cast(event); + if(wheelEvent->orientation() != ::Qt::Vertical) { + return false; + } + double zoom_ratio = 240.0; + if( (wheelEvent->modifiers() & ::Qt::ShiftModifier) + || (wheelEvent->modifiers() & ::Qt::ControlModifier) ) { + zoom_ratio = 120.0; + } + scaleView(v, pow((double)2, -wheelEvent->delta() / zoom_ratio)); + + // display_parameters(); + return true; + break; + } // end case Wheel + case QEvent::MouseButtonPress: { + QMouseEvent* mouseEvent = static_cast(event); + if( (mouseEvent->modifiers() == (::Qt::ControlModifier | ::Qt::ShiftModifier)) + && mouseEvent->button() == ::Qt::RightButton ) + { + QPoint offset = mouseEvent->pos() - v->viewport()->rect().center(); + translateView(v, offset.x(), offset.y()); + return true; + } + else if( mouseEvent->modifiers() == ::Qt::ControlModifier ) { + if(mouseEvent->button() == ::Qt::LeftButton) { + rect_first_point = v->mapToScene(mouseEvent->pos()); + rectItem->setRect(QRectF(rect_first_point, QSizeF(0.,0.))); + rectItem->show(); + v->scene()->addItem(rectItem); + return true; + } + else if( mouseEvent->button() == ::Qt::RightButton) { + dragging = true; + dragging_start = v->mapToScene(mouseEvent->pos()); + v->setCursor(::Qt::ClosedHandCursor); + return true; + } + } + return false; + break; + } // end case MouseRelease + case QEvent::MouseMove: { + QMouseEvent* mouseEvent = static_cast(event); + QPointF pos = v->mapToScene(mouseEvent->pos()); + QString xy = QString(" ") + QString::number(pos.x(),'g', 6) + " , " + QString::number(pos.y(),'g', 6) + " "; + emit mouseCoordinates(xy); + if(rectItem->isVisible()) { + QPointF size = v->mapToScene(mouseEvent->pos()); + size = size - rect_first_point; + rectItem->setRect(rect_first_point.x(), + rect_first_point.y(), + size.x(), + size.y()); + } + if( dragging ) + { +// std::cerr << boost::format("mouseMove: globalpos=(%1%, %2%)\n" +// " pos=(%3%, %4%)\n" +// " sender=%5% (class %6%), parent class %7%\n") +// % mouseEvent->globalPos().x() +// % mouseEvent->globalPos().y() +// % mouseEvent->pos().x() +// % mouseEvent->pos().y() +// % (&*obj) +// % obj->metaObject()->className() +// % obj->parent()->metaObject()->className(); + +// drag_to(mouseEvent->pos()); + } + break; + } // end MouseMove + case QEvent::MouseButtonRelease: { + QMouseEvent* mouseEvent = static_cast(event); + if(rectItem->isVisible() && mouseEvent->button() == ::Qt::LeftButton){ + v->setSceneRect(v->sceneRect() | rectItem->rect()); + v->fitInView(rectItem->rect(), ::Qt::KeepAspectRatio); + v->scene()->removeItem(rectItem); + rectItem->hide(); + return true; + } + else if( mouseEvent->button() == ::Qt::RightButton ) { + if(dragging) { + dragging = false; + drag_to(v, mouseEvent->pos()); + v->setCursor(cursor_backup); + return true; + } + } + return false; + break; + } // end MouseRelease + default: + return false; + } // end switch + return false; + } + + + CGAL_INLINE_FUNCTION + void + GraphicsViewNavigation::scaleView(QGraphicsView* v, qreal scaleFactor) + { + QPointF center = v->mapToScene(v->viewport()->rect().center()); +// qreal factor = v->matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width(); + //if (factor < 0.001 || factor > 2000) + // return; + + v->scale(scaleFactor, scaleFactor); + QPoint offset = v->mapFromScene(center) - v->viewport()->rect().center(); + translateView(v, offset.x(), offset.y()); + } + + CGAL_INLINE_FUNCTION + void GraphicsViewNavigation::drag_to(QGraphicsView* v, QPoint new_pos) + { + QPoint dragging_start_in_view = v->mapFromScene(dragging_start); + QPoint offset = new_pos - dragging_start_in_view; +// std::cerr << boost::format("drag_to: origin=(%1%, %2%)\n" +// " offset=(%3%, %4%)\n") +// % dragging_start_in_view.x() % dragging_start_in_view.y() +// % offset.x() % offset.y(); + translateView(v, -offset.x(), -offset.y()); + dragging_start_in_view = v->mapFromScene(dragging_start); +// std::cerr << boost::format(" after=(%1%, %2%)\n") +// % dragging_start_in_view.x() % dragging_start_in_view.y(); + } + + CGAL_INLINE_FUNCTION + void GraphicsViewNavigation::translateView(QGraphicsView* v, int dx, int dy) + { + if( dx == 0 && dy == 0 ) { + return; + } + + int horizontalScrollBarValue = v->horizontalScrollBar()->value(); + int verticalScrollBarValue = v->verticalScrollBar()->value(); + + if( (horizontalScrollBarValue + dx <= + v->horizontalScrollBar()->maximum()) && + (horizontalScrollBarValue + dx >= + v->horizontalScrollBar()->minimum()) && + (verticalScrollBarValue + dy <= + v->verticalScrollBar()->maximum()) && + (verticalScrollBarValue + dy >= + v->verticalScrollBar()->minimum()) ) + { + v->horizontalScrollBar()->setValue(horizontalScrollBarValue + dx); + v->verticalScrollBar()->setValue(verticalScrollBarValue + dy); + } + else + { + QRect vp_rect = v->viewport()->rect(); + QPointF new_center = v->mapToScene(vp_rect.center() + QPoint(dx, dy)); + vp_rect |= vp_rect.translated(dx, dy); + QRectF rect = mapToScene(v, vp_rect); + v->setSceneRect(v->sceneRect() | rect); + v->centerOn(new_center); + + // QGraphicsView::centerOn makes rounding errors. + // The following two "if" make them unnoticable when dx==0 or dy==0. + if(dx == 0) { + v->horizontalScrollBar()->setValue(horizontalScrollBarValue); + } + if(dy == 0) { + v->verticalScrollBar()->setValue(verticalScrollBarValue); + } + } +// display_parameters(); + } + + CGAL_INLINE_FUNCTION + void GraphicsViewNavigation::display_parameters(QGraphicsView* v) + { + std::cerr << + boost::format("matrix translation=(%1%, %2%)\n" + " rotation=(%3% - %4% )\n" + " (%5% - %6% )\n") + % v->matrix().dx() + % v->matrix().dy() + % v->matrix().m11() + % v->matrix().m12() + % v->matrix().m21() + % v->matrix().m22(); + + QRect vp_rect = v->viewport()->rect(); + QPoint vp_top_left = vp_rect.topLeft(); + QPoint vp_bottom_right = vp_rect.bottomRight(); + QPointF top_left = v->mapToScene(vp_top_left); + QPointF bottom_right = v->mapToScene(vp_bottom_right); + + std::cerr << + boost::format("view=(%1% - %2%) x (%3% - %4%)\n") + % top_left.x() % bottom_right.x() + % top_left.y() % bottom_right.y(); + std::cerr << + boost::format("viewport=(%1% - %2%) x (%3% - %4%)\n") + % vp_top_left.x() % vp_bottom_right.x() + % vp_top_left.y() % vp_bottom_right.y(); + std::cerr << + boost::format("scrollbars=(%1% <= %2% <= %3%) x (%4% <= %5% <= %6%)\n") + % v->horizontalScrollBar()->minimum() + % v->horizontalScrollBar()->value() + % v->horizontalScrollBar()->maximum() + % v->verticalScrollBar()->minimum() + % v->verticalScrollBar()->value() + % v->verticalScrollBar()->maximum(); + } + +} // namespace Qt +} // namespace CGAL + diff --git a/GraphicsView/include/CGAL/Qt/GraphicsViewPolylineInput.h b/GraphicsView/include/CGAL/Qt/GraphicsViewPolylineInput.h index 0b48d7bd5b2..918cc7015d7 100644 --- a/GraphicsView/include/CGAL/Qt/GraphicsViewPolylineInput.h +++ b/GraphicsView/include/CGAL/Qt/GraphicsViewPolylineInput.h @@ -36,6 +36,7 @@ class QGraphicsScene; class QGraphicsSceneMouseEvent; class QGraphicsItem; class QGraphicsPathItem; +class QGraphicsLineItem; class QKeyEvent; class QEvent; class QObject; @@ -109,4 +110,8 @@ protected: } // namespace Qt } // namespace CGAL +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_QT_GRAPHICS_VIEW_POLYLINE_INPUT_H diff --git a/GraphicsView/include/CGAL/Qt/GraphicsViewPolylineInput_impl.h b/GraphicsView/include/CGAL/Qt/GraphicsViewPolylineInput_impl.h new file mode 100644 index 00000000000..5932a1b51a0 --- /dev/null +++ b/GraphicsView/include/CGAL/Qt/GraphicsViewPolylineInput_impl.h @@ -0,0 +1,206 @@ +// Copyright (c) 2008 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Andreas Fabri +// Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace CGAL { +namespace Qt { + +CGAL_INLINE_FUNCTION +GraphicsViewPolylineInput_non_templated_base:: +GraphicsViewPolylineInput_non_templated_base(QObject* parent, + QGraphicsScene* s, + int n, + bool closed) + : GraphicsViewInput(parent), closed_(closed), path_item(NULL), b(NULL), e(NULL), n_(n), scene_(s) +{} + + +CGAL_INLINE_FUNCTION +bool +GraphicsViewPolylineInput_non_templated_base::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + if( event->modifiers() ){ + return false; + } + if( event->button() != ::Qt::RightButton + && event->button() != ::Qt::LeftButton ){ + return false; + } + polygon.push_back(event->scenePos()); + if(path_item){ + scene_->removeItem(path_item); + delete path_item; + path_item = NULL; + } + if( (event->button() == ::Qt::RightButton) || (polygon.size() == n_) ){ + // call the virtual function generate_polygon(), that emit a + // CGAL::Object containing a list of points + generate_polygon(); + polygon.clear(); + if(b){ + scene_->removeItem(b); + delete b; + b = NULL; + } + if(e){ + scene_->removeItem(e); + delete e; + e = NULL; + } + return true; + } + if(event->button() == ::Qt::LeftButton){ + QPainterPath qpp; + qpp.addPolygon(polygon); + path_item = new QGraphicsPathItem(qpp); + path_item->setPen(QPen(::Qt::red, 0, ::Qt::SolidLine, ::Qt::RoundCap, ::Qt::RoundJoin)); + scene_->addItem(path_item); + return true; + } + return false; +} + + +CGAL_INLINE_FUNCTION +void +GraphicsViewPolylineInput_non_templated_base::rubberbands(const QPointF& p) +{ + if(polygon.empty()){ + return; + } + if(!b && closed_ ){ + b = new QGraphicsLineItem(); + b->setPen(QPen(::Qt::red, 0, ::Qt::SolidLine, ::Qt::RoundCap, ::Qt::RoundJoin)); + scene_->addItem(b); + } + if( !e){ + e = new QGraphicsLineItem(); + e->setPen(QPen(::Qt::red, 0, ::Qt::SolidLine, ::Qt::RoundCap, ::Qt::RoundJoin)); + scene_->addItem(e); + } + if(closed_){ + QLineF bLine(polygon.front(), p); + b->setLine(bLine); + } + QLineF eLine(polygon.back(), p); + e->setLine(eLine); +} + + +CGAL_INLINE_FUNCTION +void +GraphicsViewPolylineInput_non_templated_base::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + sp = event->scenePos(); + rubberbands(sp); +} + + +CGAL_INLINE_FUNCTION +bool +GraphicsViewPolylineInput_non_templated_base::keyPressEvent ( QKeyEvent * event ) +{ + if( event->modifiers() ) + return false; + + switch(event->key()) + { + case ::Qt::Key_Delete: + case ::Qt::Key_Escape: + case ::Qt::Key_Backspace: + break; + default: + return false; + } + if(polygon.empty()){ + return true; + } + polygon.pop_back(); + if(polygon.empty()){ + if(b){ + scene_->removeItem(b); + delete b; + b = NULL; + } + if(e){ + scene_->removeItem(e); + delete e; + e = NULL; + } + return true; + } + if(path_item){ + scene_->removeItem(path_item); + delete path_item; + path_item = NULL; + } + QPainterPath qpp; + qpp.addPolygon(polygon); + path_item = new QGraphicsPathItem(qpp); + path_item->setPen(QPen(::Qt::red, 0, ::Qt::SolidLine, ::Qt::RoundCap, ::Qt::RoundJoin)); + scene_->addItem(path_item); + rubberbands(sp); + return true; +} + + + +CGAL_INLINE_FUNCTION +bool +GraphicsViewPolylineInput_non_templated_base::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::GraphicsSceneMousePress) { + QGraphicsSceneMouseEvent *mouseEvent = static_cast(event); + if(!mousePressEvent(mouseEvent)) { + // standard event processing if mousePressEvent has returned false + return QObject::eventFilter(obj, event); + } + } else if (event->type() == QEvent::GraphicsSceneMouseMove) { + QGraphicsSceneMouseEvent *mouseEvent = static_cast(event); + mouseMoveEvent(mouseEvent); + return QObject::eventFilter(obj, event); + } else if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if(!keyPressEvent(keyEvent)) { + return QObject::eventFilter(obj, event); + } + } + // standard event processing if keyPressEvent has returned false + return QObject::eventFilter(obj, event); +} + +} // namespace Qt +} // namespace CGAL diff --git a/GraphicsView/include/CGAL/Qt/debug.h b/GraphicsView/include/CGAL/Qt/debug.h index 47b7c68329c..8ff5f1d44f6 100644 --- a/GraphicsView/include/CGAL/Qt/debug.h +++ b/GraphicsView/include/CGAL/Qt/debug.h @@ -44,5 +44,8 @@ CGAL_QT_EXPORT void traverse_resources(const QString& name, } // namespace Qt } // namespace CGAL +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY #endif // CGAL_QT_DEBUG_H diff --git a/GraphicsView/include/CGAL/Qt/debug_impl.h b/GraphicsView/include/CGAL/Qt/debug_impl.h new file mode 100644 index 00000000000..e7bf2904420 --- /dev/null +++ b/GraphicsView/include/CGAL/Qt/debug_impl.h @@ -0,0 +1,60 @@ +// Copyright (c) 2008 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Andreas Fabri +// Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include + +#include + +namespace CGAL { +namespace Qt { + + +CGAL_INLINE_FUNCTION +void traverse_resources(const QString& name, const QString& dirname, int indent) +{ + std::cerr << qPrintable(QString(indent, ' ')) + << qPrintable(name); + QString fullname = + dirname.isEmpty() ? + name : + dirname + "/" + name; + QDir dir(fullname); + if(dir.exists()) { + std::cerr << "/\n"; + Q_FOREACH(QString path, dir.entryList()) + { + traverse_resources(path, fullname, indent + 2); + } + } + else { + std::cerr << "\n"; + } +} + +} // namesapce Qt +} // namespace CGAL diff --git a/GraphicsView/include/CGAL/Qt/resources.h b/GraphicsView/include/CGAL/Qt/resources.h index f36d040681a..70910184887 100644 --- a/GraphicsView/include/CGAL/Qt/resources.h +++ b/GraphicsView/include/CGAL/Qt/resources.h @@ -30,4 +30,8 @@ CGAL_QT_EXPORT void CGAL_Qt_init_resources(); // The do{}while(0) trick is used to make that macro value a regular // statement and not a compound statement. +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_QT_RESOURCES_H diff --git a/GraphicsView/include/CGAL/Qt/resources_impl.h b/GraphicsView/include/CGAL/Qt/resources_impl.h new file mode 100644 index 00000000000..85508db27f8 --- /dev/null +++ b/GraphicsView/include/CGAL/Qt/resources_impl.h @@ -0,0 +1,37 @@ +// Copyright (c) 2011 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include + +// cannot use namespaces because of the Q_INIT_RESOURCE macro +CGAL_INLINE_FUNCTION +void CGAL_Qt_init_resources() { + Q_INIT_RESOURCE(File); + Q_INIT_RESOURCE(Triangulation_2); + Q_INIT_RESOURCE(Input); + Q_INIT_RESOURCE(CGAL); +} diff --git a/GraphicsView/include/CGAL/Qt/utility.h b/GraphicsView/include/CGAL/Qt/utility.h index f1e7fbf874d..83d03aca4fd 100644 --- a/GraphicsView/include/CGAL/Qt/utility.h +++ b/GraphicsView/include/CGAL/Qt/utility.h @@ -40,4 +40,8 @@ CGAL_QT_EXPORT QRectF viewportsBbox(const QGraphicsScene*); } // namespace Qt } // namespace CGAL +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_QT_UTILITY_H diff --git a/GraphicsView/include/CGAL/Qt/utility_impl.h b/GraphicsView/include/CGAL/Qt/utility_impl.h new file mode 100644 index 00000000000..4fea3451f07 --- /dev/null +++ b/GraphicsView/include/CGAL/Qt/utility_impl.h @@ -0,0 +1,62 @@ +// Copyright (c) 2008 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Andreas Fabri +// Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include +#include +#include +#include + +namespace CGAL { +namespace Qt { + +CGAL_INLINE_FUNCTION +QRectF mapToScene(const QGraphicsView* v, const QRect rect) +{ + QPointF top_left = v->mapToScene(rect.topLeft()); + QPointF size = v->mapToScene(rect.bottomRight()); + size -= top_left; + return QRectF(top_left.x(), + top_left.y(), + size.x(), + size.y()); +} + +CGAL_INLINE_FUNCTION +QRectF viewportsBbox(const QGraphicsScene* scene) { + QRectF rect; + Q_FOREACH(QGraphicsView* view, scene->views()) + { + rect |= mapToScene(view, view->viewport()->rect()); + } + rect = rect.normalized(); + return rect; +} + +} // namespace Qt +} // namespace CGAL diff --git a/GraphicsView/src/CGAL_Qt5/DemosMainWindow.cpp b/GraphicsView/src/CGAL_Qt5/DemosMainWindow.cpp index 528f91d5a2f..0e3c0f5462d 100644 --- a/GraphicsView/src/CGAL_Qt5/DemosMainWindow.cpp +++ b/GraphicsView/src/CGAL_Qt5/DemosMainWindow.cpp @@ -19,425 +19,9 @@ // Author(s) : Andreas Fabri // Laurent Rineau -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#ifndef CGAL_HEADER_ONLY - -#include // needed to get CGAL_VERSION_STR #include -#include +#include -namespace CGAL { -namespace Qt { - -DemosMainWindow::DemosMainWindow(QWidget * parent, ::Qt::WindowFlags flags) - : QMainWindow(parent, flags), - maxNumRecentFiles(10), - recentFileActs(maxNumRecentFiles) -{ - // prepare the QLabel xycoord for inclusion in the statusBar() - xycoord = new QLabel(" -0.00000 , -0.00000 ", this); - xycoord->setAlignment(::Qt::AlignHCenter); - xycoord->setMinimumSize(xycoord->sizeHint()); - xycoord->clear(); - - actionUse_OpenGL = new QAction(this); - actionUse_OpenGL->setObjectName("actionUse_OpenGL"); - actionUse_OpenGL->setCheckable(true); - actionUse_OpenGL->setText(tr("Use &OpenGL")); - actionUse_OpenGL->setStatusTip(tr("Make Qt use OpenGL to display the graphical items, instead of its native painting system.")); - actionUse_OpenGL->setShortcut(tr("Ctrl+G")); - - actionUse_Antialiasing = new QAction(this); - actionUse_Antialiasing->setObjectName("actionUse_Antialiasing"); - actionUse_Antialiasing->setCheckable(true); - actionUse_Antialiasing->setText(tr("Use &anti-aliasing")); - actionUse_Antialiasing->setStatusTip(tr("Make Qt use anti-aliasing when displaying the graphical items.")); - actionUse_Antialiasing->setShortcut(tr("Ctrl+A")); - - actionAboutCGAL = new QAction(this); - actionAboutCGAL->setObjectName("actionAboutCGAL"); - actionAboutCGAL->setText(tr("About &CGAL...")); - - actionAbout = new QAction(this); - actionAbout->setObjectName("actionAbout"); - actionAbout->setText(tr("&About...")); - - setAcceptDrops(true); -} - -DemosMainWindow::~DemosMainWindow() -{ -} - -void -DemosMainWindow::dragEnterEvent(QDragEnterEvent *event) -{ - if (event->mimeData()->hasFormat("text/uri-list")) - event->acceptProposedAction(); -} - -void -DemosMainWindow::dropEvent(QDropEvent *event) -{ - Q_FOREACH(QUrl url, event->mimeData()->urls()) { - QString filename = url.toLocalFile(); - this->open(filename); - } - event->acceptProposedAction(); -} - -void -DemosMainWindow::addNavigation(QGraphicsView* graphicsView) -{ - navigation = new CGAL::Qt::GraphicsViewNavigation(); - graphicsView->viewport()->installEventFilter(navigation); - graphicsView->installEventFilter(navigation); - QObject::connect(navigation, SIGNAL(mouseCoordinates(QString)), - xycoord, SLOT(setText(QString))); - view = graphicsView; -} - -void -DemosMainWindow::setupStatusBar() -{ - this->statusBar()->addWidget(new QLabel(this), 1); - this->statusBar()->addWidget(xycoord, 0); -} - -void -DemosMainWindow::setupOptionsMenu(QMenu* menuOptions) -{ - // search for the Options menu - if(!menuOptions) { - menuOptions = getMenu("menuOptions", tr("&Options")); - } - - // if not found, then create it - if(!menuOptions) { - menuOptions = new QMenu(this->menuBar()); - menuOptions->setTitle(tr("&Options")); - this->menuBar()->addAction(menuOptions->menuAction()); - menuOptions->setObjectName("menuOptions"); - } - - if(!menuOptions->isEmpty()) { - menuOptions->addSeparator(); - } - menuOptions->addAction(actionUse_OpenGL); - menuOptions->addAction(actionUse_Antialiasing); - connect(actionUse_Antialiasing, SIGNAL(toggled(bool)), - this, SLOT(setUseAntialiasing(bool))); - connect(actionUse_OpenGL, SIGNAL(toggled(bool)), - this, SLOT(setUseOpenGL(bool))); - actionUse_Antialiasing->setChecked(true); -} - -void -DemosMainWindow::setupExportSVG(QAction* action, QGraphicsView* view) -{ - this->view = view; - connect(action, SIGNAL(triggered(bool)), - this, SLOT(exportSVG())); -} - -void DemosMainWindow::exportSVG() -{ - QString fileName = QFileDialog::getSaveFileName(this, - tr("Export to SVG"), - ".", - tr("SVG (*.svg)\n")); - - QSvgGenerator svg; - svg.setFileName(fileName); - - svg.setSize(this->view->size()); - svg.setViewBox(this->view->sceneRect()); - svg.setTitle(tr("%1 drawing").arg(qApp->applicationName())); - svg.setDescription(tr("Generated using %1").arg(qApp->applicationName())); - - QPainter painter; - painter.begin(&svg); - this->view->render(&painter); - painter.end(); -} - -void -DemosMainWindow::setUseAntialiasing(bool checked) -{ - view->setRenderHint(QPainter::Antialiasing, checked); - view->setRenderHint(QPainter::HighQualityAntialiasing, checked); - - statusBar()->showMessage(tr("Antialiasing %1activated").arg(checked?"":"de-"), - 1000); -} - -void -DemosMainWindow::setUseOpenGL(bool checked) -{ - if(checked) { - QGLWidget* new_viewport = new QGLWidget; - - // Setup the format to allow antialiasing with OpenGL: - // one need to activate the SampleBuffers, if the graphic driver allows - // this. - QGLFormat glformat = new_viewport->format(); - glformat.setOption(QGL::SampleBuffers); - new_viewport->setFormat(glformat); - - view->setViewport(new_viewport); - } - else { - view->setViewport(new QWidget); - } - statusBar()->showMessage(tr("OpenGL %1activated").arg(checked?"":"de-"), - 1000); - view->viewport()->installEventFilter(navigation); - view->setFocus(); -} - -QMenu* -DemosMainWindow::getMenu(QString objectName, QString title) -{ - QMenu* menu = NULL; - - QString title2 = title; - title2.remove('&'); - // search if a menu has objectName()==objectName - menu = this->findChild(objectName); - - // then search if a menu has title()==title - if(menu) { - return menu; - } else { - Q_FOREACH(menu, this->findChildren()) { - if(menu->title() == title || - menu->title() == title2) { - return menu; - } - } - } - return NULL; -} - -void -DemosMainWindow::popupAboutBox(QString title, QString html_resource_name) -{ - QFile about_CGAL(html_resource_name); - about_CGAL.open(QIODevice::ReadOnly); - QString about_CGAL_txt = QTextStream(&about_CGAL).readAll(); -#ifdef CGAL_VERSION_STR - QString cgal_version(CGAL_VERSION_STR); -# ifdef CGAL_FAKE_PUBLIC_RELEASE - cgal_version.replace(QRegExp("-Ic?.*"), ""); -# endif - about_CGAL_txt.replace("", - QString(" (version %1)") - .arg(cgal_version)); -#endif - QMessageBox mb(QMessageBox::NoIcon, - title, - about_CGAL_txt, - QMessageBox::Ok, - this); - - QLabel* mb_label = mb.findChild("qt_msgbox_label"); - if(mb_label) { - mb_label->setTextInteractionFlags(mb_label->textInteractionFlags() | - ::Qt::LinksAccessibleByMouse | - ::Qt::LinksAccessibleByKeyboard); - } - else { - std::cerr << "Cannot find child \"qt_msgbox_label\" in QMessageBox\n" - << " with Qt version " << QT_VERSION_STR << "!\n"; - } - mb.exec(); -} - -QMenu* DemosMainWindow::getHelpMenu() -{ - QMenu* menuHelp = getMenu("menuHelp", tr("&Help")); - if(!menuHelp) { - menuHelp = new QMenu(this->menuBar()); - menuHelp->setTitle(tr("&Help")); - this->menuBar()->addAction(menuHelp->menuAction()); - menuHelp->setObjectName("menuHelp"); - } - return menuHelp; -} - -void -DemosMainWindow::addAboutCGAL(QMenu* menuHelp) -{ - if(!menuHelp) { - menuHelp = getHelpMenu(); - } - menuHelp->addAction(actionAboutCGAL); - - connect(actionAboutCGAL, SIGNAL(triggered()), - this, SLOT(popupAboutCGAL())); -} - -void -DemosMainWindow::addAboutDemo(QString htmlResourceName, QMenu* menuHelp) -{ - if(!menuHelp) { - menuHelp = getHelpMenu(); - } - menuHelp->addAction(actionAbout); - aboutHtmlResource = htmlResourceName; - - connect(actionAbout, SIGNAL(triggered()), - this, SLOT(popupAboutDemo())); -} - -void -DemosMainWindow::popupAboutCGAL() -{ - popupAboutBox(tr("About CGAL..."), - ":/cgal/help/about_CGAL.html"); -} - -void -DemosMainWindow::popupAboutDemo() -{ - popupAboutBox(tr("About the demo..."), - aboutHtmlResource); -} - -void -DemosMainWindow::setMaxNumberOfRecentFiles(const unsigned int i) -{ - maxNumRecentFiles = i; - recentFileActs.resize(maxNumRecentFiles); -} - -unsigned int -DemosMainWindow::maxNumberOfRecentFiles() const -{ - return maxNumRecentFiles; -} - -void -DemosMainWindow::openRecentFile_aux() -{ - QAction *action = qobject_cast(sender()); - if (action) - emit openRecentFile(action->data().toString()); -} - -void -DemosMainWindow::addToRecentFiles(QString fileName) -{ - QSettings settings; - QStringList files = settings.value("recentFileList").toStringList(); - files.removeAll(fileName); - files.prepend(fileName); - while (files.size() > (int)maxNumberOfRecentFiles()) - files.removeLast(); - - settings.setValue("recentFileList", files); - - updateRecentFileActions(); -} - -void -DemosMainWindow::addRecentFiles(QMenu* menu, QAction* insertBeforeAction) -{ - if(!insertBeforeAction) { - recentFilesSeparator = menu->addSeparator(); - } - - for (unsigned int i = 0; i < maxNumberOfRecentFiles(); ++i) { - recentFileActs[i] = new QAction(this); - recentFileActs[i]->setVisible(false); - connect(recentFileActs[i], SIGNAL(triggered()), - this, SLOT(openRecentFile_aux())); - if(insertBeforeAction) - menu->insertAction(insertBeforeAction, recentFileActs[i]); - else - menu->addAction(recentFileActs[i]); - } - - if(insertBeforeAction) { - recentFilesSeparator = menu->insertSeparator(insertBeforeAction); - } - - recentFilesSeparator->setVisible(false); - - updateRecentFileActions(); -} - -void -DemosMainWindow::updateRecentFileActions() -{ - QSettings settings; - QStringList files = settings.value("recentFileList").toStringList(); - - int numRecentFiles = qMin(files.size(), (int)this->maxNumberOfRecentFiles()); - - for (int i = 0; i < numRecentFiles; ++i) { - QString strippedName = QFileInfo(files[i]).fileName(); - QString text = tr("&%1 %2").arg(i).arg(strippedName); - recentFileActs[i]->setText(text); - recentFileActs[i]->setData(files[i]); - recentFileActs[i]->setVisible(true); - } - for (unsigned int j = numRecentFiles; j < maxNumberOfRecentFiles(); ++j) - recentFileActs[j]->setVisible(false); - - recentFilesSeparator->setVisible(numRecentFiles > 0); -} - -void DemosMainWindow::writeState(QString groupname) -{ - QSettings settings; - - settings.beginGroup(groupname); - settings.setValue("size", size()); - settings.setValue("pos", pos()); - settings.setValue("state", saveState()); - settings.endGroup(); -} - -void DemosMainWindow::readState(QString groupname, Options /*what_to_save*/) -{ - QSettings settings; - - settings.beginGroup(groupname); - resize(settings.value("size", this->size()).toSize()); - - QDesktopWidget* desktop = qApp->desktop(); - QPoint pos = settings.value("pos", this->pos()).toPoint(); - if(desktop->availableGeometry(pos).contains(pos)) { - move(pos); - } - QByteArray mainWindowState = settings.value("state").toByteArray(); - if(!mainWindowState.isNull()) { - this->restoreState(mainWindowState); - } - settings.endGroup(); -} - - -} // namespace Qt -} // namespace CGAL +#endif // CGAL_HEADER_ONLY diff --git a/GraphicsView/src/CGAL_Qt5/GraphicsViewNavigation.cpp b/GraphicsView/src/CGAL_Qt5/GraphicsViewNavigation.cpp index 712c4bb9a66..66fd8c0f887 100644 --- a/GraphicsView/src/CGAL_Qt5/GraphicsViewNavigation.cpp +++ b/GraphicsView/src/CGAL_Qt5/GraphicsViewNavigation.cpp @@ -19,320 +19,9 @@ // Author(s) : Andreas Fabri // Laurent Rineau +#ifndef CGAL_HEADER_ONLY + #include -#include // for mapToScene(QGraphicsView*, QRect) -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace CGAL { -namespace Qt { - - GraphicsViewNavigation::GraphicsViewNavigation() - : rectItem(new QGraphicsRectItem), - dragging(false) - { - QColor rect_color(250, 221, 0); - rect_color.setAlpha(50); - rectItem->setBrush(rect_color); - rect_color.setAlpha(255); - rectItem->setPen(QPen(rect_color, 0, ::Qt::DashLine)); - rectItem->hide(); - rectItem->setZValue(10000); - } - - GraphicsViewNavigation::~GraphicsViewNavigation() - { - delete rectItem; - } - - bool - GraphicsViewNavigation::eventFilter(QObject *obj, QEvent *event) - { - QGraphicsView* v = qobject_cast(obj); - if(v == NULL) { - QWidget* viewport = qobject_cast(obj); - if(viewport == NULL) { - return false; - } - v = qobject_cast(viewport->parent()); - if(v == NULL) { - return false; - } - } - switch(event->type()) - { - case QEvent::KeyPress: { - QKeyEvent *keyEvent = static_cast(event); - int offset = 10; - if( (keyEvent->modifiers() & ::Qt::ShiftModifier) - || (keyEvent->modifiers() & ::Qt::ControlModifier) ) { - offset = 20; - } - switch (keyEvent->key()) { - case ::Qt::Key_Up: - translateView(v, 0, -offset); - break; - case ::Qt::Key_Down: - translateView(v, 0, offset); - break; - case ::Qt::Key_Left: - translateView(v, -offset, 0); - break; - case ::Qt::Key_Right: - translateView(v, offset, 0); - break; - case ::Qt::Key_PageUp: - v->rotate(-6); - break; - case ::Qt::Key_PageDown: - v->rotate(6); - break; - case ::Qt::Key_Plus: - scaleView(v, 1.2); - break; - case ::Qt::Key_Minus: - scaleView(v, 1 / 1.2); - break; - case ::Qt::Key_Control: - cursor_backup = v->cursor(); - v->setCursor(::Qt::CrossCursor); - default: - return false; - } - // display_parameters(); - return true; - break; - } // end case KeyPress - case QEvent::KeyRelease: { - QKeyEvent *keyEvent = static_cast(event); - if(keyEvent->key() == ::Qt::Key_Control) { - if(rectItem->isVisible() ) { - dragging = false; - v->scene()->removeItem(rectItem); - rectItem->hide(); - } - v->setCursor(cursor_backup); - return true; - } - return false; - break; - } // end case KeyRelease - case QEvent::Wheel: { - QWheelEvent *wheelEvent = static_cast(event); - if(wheelEvent->orientation() != ::Qt::Vertical) { - return false; - } - double zoom_ratio = 240.0; - if( (wheelEvent->modifiers() & ::Qt::ShiftModifier) - || (wheelEvent->modifiers() & ::Qt::ControlModifier) ) { - zoom_ratio = 120.0; - } - scaleView(v, pow((double)2, -wheelEvent->delta() / zoom_ratio)); - - // display_parameters(); - return true; - break; - } // end case Wheel - case QEvent::MouseButtonPress: { - QMouseEvent* mouseEvent = static_cast(event); - if( (mouseEvent->modifiers() == (::Qt::ControlModifier | ::Qt::ShiftModifier)) - && mouseEvent->button() == ::Qt::RightButton ) - { - QPoint offset = mouseEvent->pos() - v->viewport()->rect().center(); - translateView(v, offset.x(), offset.y()); - return true; - } - else if( mouseEvent->modifiers() == ::Qt::ControlModifier ) { - if(mouseEvent->button() == ::Qt::LeftButton) { - rect_first_point = v->mapToScene(mouseEvent->pos()); - rectItem->setRect(QRectF(rect_first_point, QSizeF(0.,0.))); - rectItem->show(); - v->scene()->addItem(rectItem); - return true; - } - else if( mouseEvent->button() == ::Qt::RightButton) { - dragging = true; - dragging_start = v->mapToScene(mouseEvent->pos()); - v->setCursor(::Qt::ClosedHandCursor); - return true; - } - } - return false; - break; - } // end case MouseRelease - case QEvent::MouseMove: { - QMouseEvent* mouseEvent = static_cast(event); - QPointF pos = v->mapToScene(mouseEvent->pos()); - QString xy = QString(" ") + QString::number(pos.x(),'g', 6) + " , " + QString::number(pos.y(),'g', 6) + " "; - emit mouseCoordinates(xy); - if(rectItem->isVisible()) { - QPointF size = v->mapToScene(mouseEvent->pos()); - size = size - rect_first_point; - rectItem->setRect(rect_first_point.x(), - rect_first_point.y(), - size.x(), - size.y()); - } - if( dragging ) - { -// std::cerr << boost::format("mouseMove: globalpos=(%1%, %2%)\n" -// " pos=(%3%, %4%)\n" -// " sender=%5% (class %6%), parent class %7%\n") -// % mouseEvent->globalPos().x() -// % mouseEvent->globalPos().y() -// % mouseEvent->pos().x() -// % mouseEvent->pos().y() -// % (&*obj) -// % obj->metaObject()->className() -// % obj->parent()->metaObject()->className(); - -// drag_to(mouseEvent->pos()); - } - break; - } // end MouseMove - case QEvent::MouseButtonRelease: { - QMouseEvent* mouseEvent = static_cast(event); - if(rectItem->isVisible() && mouseEvent->button() == ::Qt::LeftButton){ - v->setSceneRect(v->sceneRect() | rectItem->rect()); - v->fitInView(rectItem->rect(), ::Qt::KeepAspectRatio); - v->scene()->removeItem(rectItem); - rectItem->hide(); - return true; - } - else if( mouseEvent->button() == ::Qt::RightButton ) { - if(dragging) { - dragging = false; - drag_to(v, mouseEvent->pos()); - v->setCursor(cursor_backup); - return true; - } - } - return false; - break; - } // end MouseRelease - default: - return false; - } // end switch - return false; - } - - - void - GraphicsViewNavigation::scaleView(QGraphicsView* v, qreal scaleFactor) - { - QPointF center = v->mapToScene(v->viewport()->rect().center()); -// qreal factor = v->matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width(); - //if (factor < 0.001 || factor > 2000) - // return; - - v->scale(scaleFactor, scaleFactor); - QPoint offset = v->mapFromScene(center) - v->viewport()->rect().center(); - translateView(v, offset.x(), offset.y()); - } - - void GraphicsViewNavigation::drag_to(QGraphicsView* v, QPoint new_pos) - { - QPoint dragging_start_in_view = v->mapFromScene(dragging_start); - QPoint offset = new_pos - dragging_start_in_view; -// std::cerr << boost::format("drag_to: origin=(%1%, %2%)\n" -// " offset=(%3%, %4%)\n") -// % dragging_start_in_view.x() % dragging_start_in_view.y() -// % offset.x() % offset.y(); - translateView(v, -offset.x(), -offset.y()); - dragging_start_in_view = v->mapFromScene(dragging_start); -// std::cerr << boost::format(" after=(%1%, %2%)\n") -// % dragging_start_in_view.x() % dragging_start_in_view.y(); - } - - void GraphicsViewNavigation::translateView(QGraphicsView* v, int dx, int dy) - { - if( dx == 0 && dy == 0 ) { - return; - } - - int horizontalScrollBarValue = v->horizontalScrollBar()->value(); - int verticalScrollBarValue = v->verticalScrollBar()->value(); - - if( (horizontalScrollBarValue + dx <= - v->horizontalScrollBar()->maximum()) && - (horizontalScrollBarValue + dx >= - v->horizontalScrollBar()->minimum()) && - (verticalScrollBarValue + dy <= - v->verticalScrollBar()->maximum()) && - (verticalScrollBarValue + dy >= - v->verticalScrollBar()->minimum()) ) - { - v->horizontalScrollBar()->setValue(horizontalScrollBarValue + dx); - v->verticalScrollBar()->setValue(verticalScrollBarValue + dy); - } - else - { - QRect vp_rect = v->viewport()->rect(); - QPointF new_center = v->mapToScene(vp_rect.center() + QPoint(dx, dy)); - vp_rect |= vp_rect.translated(dx, dy); - QRectF rect = mapToScene(v, vp_rect); - v->setSceneRect(v->sceneRect() | rect); - v->centerOn(new_center); - - // QGraphicsView::centerOn makes rounding errors. - // The following two "if" make them unnoticable when dx==0 or dy==0. - if(dx == 0) { - v->horizontalScrollBar()->setValue(horizontalScrollBarValue); - } - if(dy == 0) { - v->verticalScrollBar()->setValue(verticalScrollBarValue); - } - } -// display_parameters(); - } - - void GraphicsViewNavigation::display_parameters(QGraphicsView* v) - { - std::cerr << - boost::format("matrix translation=(%1%, %2%)\n" - " rotation=(%3% - %4% )\n" - " (%5% - %6% )\n") - % v->matrix().dx() - % v->matrix().dy() - % v->matrix().m11() - % v->matrix().m12() - % v->matrix().m21() - % v->matrix().m22(); - - QRect vp_rect = v->viewport()->rect(); - QPoint vp_top_left = vp_rect.topLeft(); - QPoint vp_bottom_right = vp_rect.bottomRight(); - QPointF top_left = v->mapToScene(vp_top_left); - QPointF bottom_right = v->mapToScene(vp_bottom_right); - - std::cerr << - boost::format("view=(%1% - %2%) x (%3% - %4%)\n") - % top_left.x() % bottom_right.x() - % top_left.y() % bottom_right.y(); - std::cerr << - boost::format("viewport=(%1% - %2%) x (%3% - %4%)\n") - % vp_top_left.x() % vp_bottom_right.x() - % vp_top_left.y() % vp_bottom_right.y(); - std::cerr << - boost::format("scrollbars=(%1% <= %2% <= %3%) x (%4% <= %5% <= %6%)\n") - % v->horizontalScrollBar()->minimum() - % v->horizontalScrollBar()->value() - % v->horizontalScrollBar()->maximum() - % v->verticalScrollBar()->minimum() - % v->verticalScrollBar()->value() - % v->verticalScrollBar()->maximum(); - } - -} // namespace Qt -} // namespace CGAL +#include +#endif // CGAL_HEADER_ONLY diff --git a/GraphicsView/src/CGAL_Qt5/GraphicsViewPolylineInput.cpp b/GraphicsView/src/CGAL_Qt5/GraphicsViewPolylineInput.cpp index 7780ef0aa7b..c08bdeaa84b 100644 --- a/GraphicsView/src/CGAL_Qt5/GraphicsViewPolylineInput.cpp +++ b/GraphicsView/src/CGAL_Qt5/GraphicsViewPolylineInput.cpp @@ -19,178 +19,9 @@ // Author(s) : Andreas Fabri // Laurent Rineau -#include -#include -#include -#include -#include -#include -#include -#include -#include +#ifndef CGAL_HEADER_ONLY #include +#include -namespace CGAL { -namespace Qt { - -GraphicsViewPolylineInput_non_templated_base:: -GraphicsViewPolylineInput_non_templated_base(QObject* parent, - QGraphicsScene* s, - int n, - bool closed) - : GraphicsViewInput(parent), closed_(closed), path_item(NULL), b(NULL), e(NULL), n_(n), scene_(s) -{} - - -bool -GraphicsViewPolylineInput_non_templated_base::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - if( event->modifiers() ){ - return false; - } - if( event->button() != ::Qt::RightButton - && event->button() != ::Qt::LeftButton ){ - return false; - } - polygon.push_back(event->scenePos()); - if(path_item){ - scene_->removeItem(path_item); - delete path_item; - path_item = NULL; - } - if( (event->button() == ::Qt::RightButton) || (polygon.size() == n_) ){ - // call the virtual function generate_polygon(), that emit a - // CGAL::Object containing a list of points - generate_polygon(); - polygon.clear(); - if(b){ - scene_->removeItem(b); - delete b; - b = NULL; - } - if(e){ - scene_->removeItem(e); - delete e; - e = NULL; - } - return true; - } - if(event->button() == ::Qt::LeftButton){ - QPainterPath qpp; - qpp.addPolygon(polygon); - path_item = new QGraphicsPathItem(qpp); - path_item->setPen(QPen(::Qt::red, 0, ::Qt::SolidLine, ::Qt::RoundCap, ::Qt::RoundJoin)); - scene_->addItem(path_item); - return true; - } - return false; -} - - -void -GraphicsViewPolylineInput_non_templated_base::rubberbands(const QPointF& p) -{ - if(polygon.empty()){ - return; - } - if(!b && closed_ ){ - b = new QGraphicsLineItem(); - b->setPen(QPen(::Qt::red, 0, ::Qt::SolidLine, ::Qt::RoundCap, ::Qt::RoundJoin)); - scene_->addItem(b); - } - if( !e){ - e = new QGraphicsLineItem(); - e->setPen(QPen(::Qt::red, 0, ::Qt::SolidLine, ::Qt::RoundCap, ::Qt::RoundJoin)); - scene_->addItem(e); - } - if(closed_){ - QLineF bLine(polygon.front(), p); - b->setLine(bLine); - } - QLineF eLine(polygon.back(), p); - e->setLine(eLine); -} - - -void -GraphicsViewPolylineInput_non_templated_base::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - sp = event->scenePos(); - rubberbands(sp); -} - - -bool -GraphicsViewPolylineInput_non_templated_base::keyPressEvent ( QKeyEvent * event ) -{ - if( event->modifiers() ) - return false; - - switch(event->key()) - { - case ::Qt::Key_Delete: - case ::Qt::Key_Escape: - case ::Qt::Key_Backspace: - break; - default: - return false; - } - if(polygon.empty()){ - return true; - } - polygon.pop_back(); - if(polygon.empty()){ - if(b){ - scene_->removeItem(b); - delete b; - b = NULL; - } - if(e){ - scene_->removeItem(e); - delete e; - e = NULL; - } - return true; - } - if(path_item){ - scene_->removeItem(path_item); - delete path_item; - path_item = NULL; - } - QPainterPath qpp; - qpp.addPolygon(polygon); - path_item = new QGraphicsPathItem(qpp); - path_item->setPen(QPen(::Qt::red, 0, ::Qt::SolidLine, ::Qt::RoundCap, ::Qt::RoundJoin)); - scene_->addItem(path_item); - rubberbands(sp); - return true; -} - - - -bool -GraphicsViewPolylineInput_non_templated_base::eventFilter(QObject *obj, QEvent *event) -{ - if (event->type() == QEvent::GraphicsSceneMousePress) { - QGraphicsSceneMouseEvent *mouseEvent = static_cast(event); - if(!mousePressEvent(mouseEvent)) { - // standard event processing if mousePressEvent has returned false - return QObject::eventFilter(obj, event); - } - } else if (event->type() == QEvent::GraphicsSceneMouseMove) { - QGraphicsSceneMouseEvent *mouseEvent = static_cast(event); - mouseMoveEvent(mouseEvent); - return QObject::eventFilter(obj, event); - } else if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); - if(!keyPressEvent(keyEvent)) { - return QObject::eventFilter(obj, event); - } - } - // standard event processing if keyPressEvent has returned false - return QObject::eventFilter(obj, event); -} - -} // namespace Qt -} // namespace CGAL +#endif // CGAL_HEADER_ONLY diff --git a/GraphicsView/src/CGAL_Qt5/debug.cpp b/GraphicsView/src/CGAL_Qt5/debug.cpp index 6d7712ac73b..a75a5c27ff2 100644 --- a/GraphicsView/src/CGAL_Qt5/debug.cpp +++ b/GraphicsView/src/CGAL_Qt5/debug.cpp @@ -19,35 +19,9 @@ // Author(s) : Andreas Fabri // Laurent Rineau +#ifndef CGAL_HEADER_ONLY + #include -#include +#include -#include - -namespace CGAL { -namespace Qt { - - -void traverse_resources(const QString& name, const QString& dirname, int indent) -{ - std::cerr << qPrintable(QString(indent, ' ')) - << qPrintable(name); - QString fullname = - dirname.isEmpty() ? - name : - dirname + "/" + name; - QDir dir(fullname); - if(dir.exists()) { - std::cerr << "/\n"; - Q_FOREACH(QString path, dir.entryList()) - { - traverse_resources(path, fullname, indent + 2); - } - } - else { - std::cerr << "\n"; - } -} - -} // namesapce Qt -} // namespace CGAL +#endif // CGAL_HEADER_ONLY diff --git a/GraphicsView/src/CGAL_Qt5/resources.cpp b/GraphicsView/src/CGAL_Qt5/resources.cpp index 99ec21e6d2b..f38ef67d1fd 100644 --- a/GraphicsView/src/CGAL_Qt5/resources.cpp +++ b/GraphicsView/src/CGAL_Qt5/resources.cpp @@ -18,13 +18,9 @@ // // Author(s) : Laurent Rineau -#include -#include +#ifndef CGAL_HEADER_ONLY -// cannot use namespaces because of the Q_INIT_RESOURCE macro -void CGAL_Qt_init_resources() { - Q_INIT_RESOURCE(File); - Q_INIT_RESOURCE(Triangulation_2); - Q_INIT_RESOURCE(Input); - Q_INIT_RESOURCE(CGAL); -} +#include +#include + +#endif // CGAL_HEADER_ONLY diff --git a/GraphicsView/src/CGAL_Qt5/utility.cpp b/GraphicsView/src/CGAL_Qt5/utility.cpp index caa1ea353bd..756ef452770 100644 --- a/GraphicsView/src/CGAL_Qt5/utility.cpp +++ b/GraphicsView/src/CGAL_Qt5/utility.cpp @@ -19,36 +19,9 @@ // Author(s) : Andreas Fabri // Laurent Rineau +#ifndef CGAL_HEADER_ONLY + #include -#include -#include -#include -#include -#include +#include -namespace CGAL { -namespace Qt { - -QRectF mapToScene(const QGraphicsView* v, const QRect rect) -{ - QPointF top_left = v->mapToScene(rect.topLeft()); - QPointF size = v->mapToScene(rect.bottomRight()); - size -= top_left; - return QRectF(top_left.x(), - top_left.y(), - size.x(), - size.y()); -} - -QRectF viewportsBbox(const QGraphicsScene* scene) { - QRectF rect; - Q_FOREACH(QGraphicsView* view, scene->views()) - { - rect |= mapToScene(view, view->viewport()->rect()); - } - rect = rect.normalized(); - return rect; -} - -} // namespace Qt -} // namespace CGAL +#endif // CGAL_HEADER_ONLY diff --git a/Installation/include/CGAL/export/helpers.h b/Installation/include/CGAL/export/helpers.h index 0c6bd9e5a90..cb6cecd2830 100644 --- a/Installation/include/CGAL/export/helpers.h +++ b/Installation/include/CGAL/export/helpers.h @@ -20,20 +20,28 @@ #ifndef CGAL_EXPORT_HELPERS_H #define CGAL_EXPORT_HELPERS_H -#if defined(_WIN32) || defined(__CYGWIN__) -# define CGAL_DLL_IMPORT __declspec(dllimport) -# define CGAL_DLL_EXPORT __declspec(dllexport) +#ifdef CGAL_HEADER_ONLY +# define CGAL_DLL_IMPORT +# define CGAL_DLL_EXPORT # define CGAL_DLL_LOCAL -#else - #if __GNUC__ >= 4 - #define CGAL_DLL_IMPORT __attribute__ ((visibility ("default"))) - #define CGAL_DLL_EXPORT __attribute__ ((visibility ("default"))) - #define CGAL_DLL_LOCAL __attribute__ ((visibility ("hidden"))) - #else - #define CGAL_DLL_IMPORT - #define CGAL_DLL_EXPORT - #define CGAL_DLL_LOCAL - #endif -#endif + +#else // !CGAL_HEADER_ONLY +# if defined(_WIN32) || defined(__CYGWIN__) +# define CGAL_DLL_IMPORT __declspec(dllimport) +# define CGAL_DLL_EXPORT __declspec(dllexport) +# define CGAL_DLL_LOCAL +# else + #if __GNUC__ >= 4 + #define CGAL_DLL_IMPORT __attribute__ ((visibility ("default"))) + #define CGAL_DLL_EXPORT __attribute__ ((visibility ("default"))) + #define CGAL_DLL_LOCAL __attribute__ ((visibility ("hidden"))) + #else + #define CGAL_DLL_IMPORT + #define CGAL_DLL_EXPORT + #define CGAL_DLL_LOCAL + #endif +# endif + +#endif // CGAL_HEADER_ONLY #endif // CGAL_EXPORT_HELPERS_H diff --git a/Intersections_2/include/CGAL/Bbox_2_Line_2_intersection.h b/Intersections_2/include/CGAL/Bbox_2_Line_2_intersection.h index 02503f3c08d..f9f15e76094 100644 --- a/Intersections_2/include/CGAL/Bbox_2_Line_2_intersection.h +++ b/Intersections_2/include/CGAL/Bbox_2_Line_2_intersection.h @@ -96,4 +96,8 @@ inline bool do_intersect( } //namespace CGAL +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif diff --git a/Intersections_2/include/CGAL/Bbox_2_Line_2_intersection_impl.h b/Intersections_2/include/CGAL/Bbox_2_Line_2_intersection_impl.h new file mode 100644 index 00000000000..241ca508898 --- /dev/null +++ b/Intersections_2/include/CGAL/Bbox_2_Line_2_intersection_impl.h @@ -0,0 +1,210 @@ +// Copyright (c) 2000 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Geert-Jan Giezeman + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +typedef CGAL::Simple_cartesian Lcart; + + +namespace CGAL { + +class Bbox_2_Line_2_pair_impl +{ +public: + Bbox_2_Line_2_pair_impl() {} + Bbox_2_Line_2_pair_impl(Bbox_2 const &bb, Lcart::Line_2 const &line) + : _bbox(bb), _line(line), _known(false) {} + Bbox_2 _bbox; + Lcart::Line_2 _line; + mutable bool _known; + mutable Bbox_2_Line_2_pair::Intersection_results _result; + mutable double _min, _max; +}; + +CGAL_INLINE_FUNCTION +Bbox_2_Line_2_pair::~Bbox_2_Line_2_pair() +{ + delete pimpl; +} + +CGAL_INLINE_FUNCTION +Bbox_2_Line_2_pair::Bbox_2_Line_2_pair() +{ + pimpl = new Bbox_2_Line_2_pair_impl; + pimpl->_known = false; +} + +CGAL_INLINE_FUNCTION +Bbox_2_Line_2_pair::Bbox_2_Line_2_pair(Bbox_2_Line_2_pair const &o) +{ + pimpl = new Bbox_2_Line_2_pair_impl(*o.pimpl); +} + +CGAL_INLINE_FUNCTION +Bbox_2_Line_2_pair::Bbox_2_Line_2_pair( + Bbox_2 const &bbox, double line_a, double line_b, double line_c) +{ + pimpl = new Bbox_2_Line_2_pair_impl(bbox, + Lcart::Line_2(line_a, line_b, line_c)); +} + +CGAL_INLINE_FUNCTION +Bbox_2_Line_2_pair & +Bbox_2_Line_2_pair::operator=(Bbox_2_Line_2_pair const &o) +{ + *pimpl = *o.pimpl; + return *this; +} + +CGAL_INLINE_FUNCTION +Bbox_2_Line_2_pair::Intersection_results +Bbox_2_Line_2_pair::intersection_type() const +{ + if (pimpl->_known) + return pimpl->_result; + // The non const this pointer is used to cast away const. + pimpl->_known = true; + const Lcart::Point_2 &ref_point = pimpl->_line.point(); + const Lcart::Vector_2 &dir = + pimpl->_line.direction().to_vector(); + bool to_infinity = true; +// first on x value + if (dir.x() == 0.0) { + if (ref_point.x() < pimpl->_bbox.xmin()) { + pimpl->_result = NO_INTERSECTION; + return pimpl->_result; + } + if (ref_point.x() > pimpl->_bbox.xmax()) { + pimpl->_result = NO_INTERSECTION; + return pimpl->_result; + } + } else { + double newmin, newmax; + if (dir.x() > 0.0) { + newmin = (pimpl->_bbox.xmin()-ref_point.x())/dir.x(); + newmax = (pimpl->_bbox.xmax()-ref_point.x())/dir.x(); + } else { + newmin = (pimpl->_bbox.xmax()-ref_point.x())/dir.x(); + newmax = (pimpl->_bbox.xmin()-ref_point.x())/dir.x(); + } + if (to_infinity) { + pimpl->_min = newmin; + pimpl->_max = newmax; + } else { + if (newmin > pimpl->_min) + pimpl->_min = newmin; + if (newmax < pimpl->_max) + pimpl->_max = newmax; + if (pimpl->_max < pimpl->_min) { + pimpl->_result = NO_INTERSECTION; + return pimpl->_result; + } + } + to_infinity = false; + } +// now on y value + if (dir.y() == 0.0) { + if (ref_point.y() < pimpl->_bbox.ymin()) { + pimpl->_result = NO_INTERSECTION; + return pimpl->_result; + } + if (ref_point.y() > pimpl->_bbox.ymax()) { + pimpl->_result = NO_INTERSECTION; + return pimpl->_result; + } + } else { + double newmin, newmax; + if (dir.y() > 0.0) { + newmin = (pimpl->_bbox.ymin()-ref_point.y())/dir.y(); + newmax = (pimpl->_bbox.ymax()-ref_point.y())/dir.y(); + } else { + newmin = (pimpl->_bbox.ymax()-ref_point.y())/dir.y(); + newmax = (pimpl->_bbox.ymin()-ref_point.y())/dir.y(); + } + if (to_infinity) { + pimpl->_min = newmin; + pimpl->_max = newmax; + } else { + if (newmin > pimpl->_min) + pimpl->_min = newmin; + if (newmax < pimpl->_max) + pimpl->_max = newmax; + if (pimpl->_max < pimpl->_min) { + pimpl->_result = NO_INTERSECTION; + return pimpl->_result; + } + } + to_infinity = false; + } + CGAL_kernel_assertion(!to_infinity); + if (pimpl->_max == pimpl->_min) { + pimpl->_result = POINT; + return pimpl->_result; + } + pimpl->_result = SEGMENT; + return pimpl->_result; +} + +CGAL_INLINE_FUNCTION +bool +Bbox_2_Line_2_pair::intersection( + double &x1, double &y1, double &x2, double &y2) const +{ + if (!pimpl->_known) + intersection_type(); + if (pimpl->_result != SEGMENT) + return false; + Lcart::Point_2 p1(pimpl->_line.point() + + pimpl->_min*pimpl->_line.direction().to_vector()); + Lcart::Point_2 p2(pimpl->_line.point() + + pimpl->_max*pimpl->_line.direction().to_vector()); + x1 = p1.x(); + y1 = p1.y(); + x2 = p2.x(); + y2 = p2.y(); + return true; +} + +CGAL_INLINE_FUNCTION +bool +Bbox_2_Line_2_pair::intersection( + double &x, double &y) const +{ + if (!pimpl->_known) + intersection_type(); + if (pimpl->_result != POINT) + return false; + Lcart::Point_2 pt(pimpl->_line.point() + + pimpl->_min*pimpl->_line.direction().to_vector()); + x = pt.x(); + y = pt.y(); + return true; +} + +} //namespace CGAL diff --git a/Intersections_2/include/CGAL/Ray_2_Bbox_2_intersection.h b/Intersections_2/include/CGAL/Ray_2_Bbox_2_intersection.h index 13323e874ba..1c4dc287c9b 100644 --- a/Intersections_2/include/CGAL/Ray_2_Bbox_2_intersection.h +++ b/Intersections_2/include/CGAL/Ray_2_Bbox_2_intersection.h @@ -75,6 +75,8 @@ inline bool do_intersect_ray_2( } } //namespace CGAL - +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY #endif diff --git a/Intersections_2/include/CGAL/Ray_2_Bbox_2_intersection_impl.h b/Intersections_2/include/CGAL/Ray_2_Bbox_2_intersection_impl.h new file mode 100644 index 00000000000..3f0943baf7b --- /dev/null +++ b/Intersections_2/include/CGAL/Ray_2_Bbox_2_intersection_impl.h @@ -0,0 +1,208 @@ +// Copyright (c) 2000 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Geert-Jan Giezeman + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +typedef CGAL::Simple_cartesian Rcart; + + +namespace CGAL { + +class Bbox_2_Ray_2_pair_impl +{ +public: + Bbox_2_Ray_2_pair_impl():_known(false) {} + Bbox_2_Ray_2_pair_impl(Bbox_2 const &bbox, Rcart::Point_2 const &pt, + Rcart::Vector_2 const &dir) + :_box(bbox), _known(false), _ref_point(pt), _dir(dir), _min(0.0) {} + Ray_2< Rcart > _ray; + Bbox_2 _box; + bool _known; + Bbox_2_Ray_2_pair::Intersection_results _result; + Rcart::Point_2 _ref_point; + Rcart::Vector_2 _dir; + double _min, _max; +}; + +CGAL_INLINE_FUNCTION +Bbox_2_Ray_2_pair::~Bbox_2_Ray_2_pair() +{ + delete pimpl; +} + +CGAL_INLINE_FUNCTION +Bbox_2_Ray_2_pair::Bbox_2_Ray_2_pair() +{ + pimpl = new Bbox_2_Ray_2_pair_impl; +} + +CGAL_INLINE_FUNCTION +Bbox_2_Ray_2_pair::Bbox_2_Ray_2_pair(Bbox_2_Ray_2_pair const &o) +{ + pimpl = new Bbox_2_Ray_2_pair_impl(*o.pimpl); +} + +CGAL_INLINE_FUNCTION +Bbox_2_Ray_2_pair::Bbox_2_Ray_2_pair( + Bbox_2 const &bbox, double x, double y, double dx, double dy) +{ + pimpl = new Bbox_2_Ray_2_pair_impl(bbox, + Rcart::Point_2(x,y), Rcart::Vector_2(dx,dy)); +} + +CGAL_INLINE_FUNCTION +Bbox_2_Ray_2_pair & +Bbox_2_Ray_2_pair::operator=(Bbox_2_Ray_2_pair const &o) +{ + *pimpl = *o.pimpl; + return *this; +} + +CGAL_INLINE_FUNCTION +Bbox_2_Ray_2_pair::Intersection_results +Bbox_2_Ray_2_pair::intersection_type() const +{ + if (pimpl->_known) + return pimpl->_result; + pimpl->_known = true; + bool to_infinity = true; +// first on x value + if (pimpl->_dir.x() == 0.0) { + if (pimpl->_ref_point.x() < pimpl->_box.xmin()) { + pimpl->_result = NO_INTERSECTION; + return pimpl->_result; + } + if (pimpl->_ref_point.x() > pimpl->_box.xmax()) { + pimpl->_result = NO_INTERSECTION; + return pimpl->_result; + } + } else { + double newmin, newmax; + if (pimpl->_dir.x() > 0.0) { + newmin =(pimpl->_box.xmin()-pimpl->_ref_point.x())/pimpl->_dir.x(); + newmax =(pimpl->_box.xmax()-pimpl->_ref_point.x())/pimpl->_dir.x(); + } else { + newmin =(pimpl->_box.xmax()-pimpl->_ref_point.x())/pimpl->_dir.x(); + newmax =(pimpl->_box.xmin()-pimpl->_ref_point.x())/pimpl->_dir.x(); + } + if (newmin > pimpl->_min) + pimpl->_min = newmin; + if (to_infinity) { + pimpl->_max = newmax; + } else { + if (newmax < pimpl->_max) + pimpl->_max = newmax; + } + if (pimpl->_max < pimpl->_min){ + pimpl->_result = NO_INTERSECTION; + return pimpl->_result; + } + to_infinity = false; + } +// now on y value + if (pimpl->_dir.y() == 0.0) { + if (pimpl->_ref_point.y() < pimpl->_box.ymin()) { + pimpl->_result = NO_INTERSECTION; + return pimpl->_result; + } + if (pimpl->_ref_point.y() > pimpl->_box.ymax()) { + pimpl->_result = NO_INTERSECTION; + return pimpl->_result; + } + } else { + double newmin, newmax; + if (pimpl->_dir.y() > 0.0) { + newmin =(pimpl->_box.ymin()-pimpl->_ref_point.y())/pimpl->_dir.y(); + newmax =(pimpl->_box.ymax()-pimpl->_ref_point.y())/pimpl->_dir.y(); + } else { + newmin =(pimpl->_box.ymax()-pimpl->_ref_point.y())/pimpl->_dir.y(); + newmax =(pimpl->_box.ymin()-pimpl->_ref_point.y())/pimpl->_dir.y(); + } + if (newmin > pimpl->_min) + pimpl->_min = newmin; + if (to_infinity) { + pimpl->_max = newmax; + } else { + if (newmax < pimpl->_max) + pimpl->_max = newmax; + } + if (pimpl->_max < pimpl->_min) { + pimpl->_result = NO_INTERSECTION; + return pimpl->_result; + } + to_infinity = false; + } + CGAL_kernel_assertion(!to_infinity); + if (pimpl->_max == pimpl->_min) { + pimpl->_result = POINT; + return pimpl->_result; + } + pimpl->_result = SEGMENT; + return pimpl->_result; +} + +CGAL_INLINE_FUNCTION +bool Bbox_2_Ray_2_pair:: +intersection(double &x1, double &y1, double &x2, double &y2) const +{ + if (!pimpl->_known) + intersection_type(); + if (pimpl->_result != SEGMENT) + return false; + Rcart::Point_2 p1(pimpl->_ref_point + pimpl->_min*pimpl->_dir); + Rcart::Point_2 p2(pimpl->_ref_point + pimpl->_max*pimpl->_dir); + x1 = p1.x(); + y1 = p1.y(); + x2 = p2.x(); + y2 = p2.y(); + return true; +} + +CGAL_INLINE_FUNCTION +bool Bbox_2_Ray_2_pair::intersection(double &x, double &y) const +{ + if (!pimpl->_known) + intersection_type(); + if (pimpl->_result != POINT) + return false; + Rcart::Point_2 pt = pimpl->_ref_point + pimpl->_min*pimpl->_dir; + x = pt.x(); + y = pt.y(); + return true; +} + +CGAL_INLINE_FUNCTION +bool do_intersect_ray_2( + const Bbox_2 &box, double x, double y, double dx, double dy) +{ + Bbox_2_Ray_2_pair pair(box, x, y, dx, dy); + return pair.intersection_type() != Bbox_2_Ray_2_pair::NO_INTERSECTION; +} + +} //namespace CGAL diff --git a/Intersections_2/src/CGAL/Bbox_2_intersections.cpp b/Intersections_2/src/CGAL/Bbox_2_intersections.cpp index baa4bf5b4ac..c8cc5e01466 100644 --- a/Intersections_2/src/CGAL/Bbox_2_intersections.cpp +++ b/Intersections_2/src/CGAL/Bbox_2_intersections.cpp @@ -22,346 +22,12 @@ // // Author(s) : Geert-Jan Giezeman +#ifndef CGAL_HEADER_ONLY -#include #include +#include + #include -typedef CGAL::Simple_cartesian Rcart; +#include - -namespace CGAL { - -class Bbox_2_Line_2_pair_impl -{ -public: - Bbox_2_Line_2_pair_impl() {} - Bbox_2_Line_2_pair_impl(Bbox_2 const &bb, Rcart::Line_2 const &line) - : _bbox(bb), _line(line), _known(false) {} - Bbox_2 _bbox; - Rcart::Line_2 _line; - mutable bool _known; - mutable Bbox_2_Line_2_pair::Intersection_results _result; - mutable double _min, _max; -}; - -Bbox_2_Line_2_pair::~Bbox_2_Line_2_pair() -{ - delete pimpl; -} - -Bbox_2_Line_2_pair::Bbox_2_Line_2_pair() -{ - pimpl = new Bbox_2_Line_2_pair_impl; - pimpl->_known = false; -} - -Bbox_2_Line_2_pair::Bbox_2_Line_2_pair(Bbox_2_Line_2_pair const &o) -{ - pimpl = new Bbox_2_Line_2_pair_impl(*o.pimpl); -} - -Bbox_2_Line_2_pair::Bbox_2_Line_2_pair( - Bbox_2 const &bbox, double line_a, double line_b, double line_c) -{ - pimpl = new Bbox_2_Line_2_pair_impl(bbox, - Rcart::Line_2(line_a, line_b, line_c)); -} - -Bbox_2_Line_2_pair & -Bbox_2_Line_2_pair::operator=(Bbox_2_Line_2_pair const &o) -{ - *pimpl = *o.pimpl; - return *this; -} - - -Bbox_2_Line_2_pair::Intersection_results -Bbox_2_Line_2_pair::intersection_type() const -{ - if (pimpl->_known) - return pimpl->_result; - // The non const this pointer is used to cast away const. - pimpl->_known = true; - const Rcart::Point_2 &ref_point = pimpl->_line.point(); - const Rcart::Vector_2 &dir = - pimpl->_line.direction().to_vector(); - bool to_infinity = true; -// first on x value - if (dir.x() == 0.0) { - if (ref_point.x() < pimpl->_bbox.xmin()) { - pimpl->_result = NO_INTERSECTION; - return pimpl->_result; - } - if (ref_point.x() > pimpl->_bbox.xmax()) { - pimpl->_result = NO_INTERSECTION; - return pimpl->_result; - } - } else { - double newmin, newmax; - if (dir.x() > 0.0) { - newmin = (pimpl->_bbox.xmin()-ref_point.x())/dir.x(); - newmax = (pimpl->_bbox.xmax()-ref_point.x())/dir.x(); - } else { - newmin = (pimpl->_bbox.xmax()-ref_point.x())/dir.x(); - newmax = (pimpl->_bbox.xmin()-ref_point.x())/dir.x(); - } - if (to_infinity) { - pimpl->_min = newmin; - pimpl->_max = newmax; - } else { - if (newmin > pimpl->_min) - pimpl->_min = newmin; - if (newmax < pimpl->_max) - pimpl->_max = newmax; - if (pimpl->_max < pimpl->_min) { - pimpl->_result = NO_INTERSECTION; - return pimpl->_result; - } - } - to_infinity = false; - } -// now on y value - if (dir.y() == 0.0) { - if (ref_point.y() < pimpl->_bbox.ymin()) { - pimpl->_result = NO_INTERSECTION; - return pimpl->_result; - } - if (ref_point.y() > pimpl->_bbox.ymax()) { - pimpl->_result = NO_INTERSECTION; - return pimpl->_result; - } - } else { - double newmin, newmax; - if (dir.y() > 0.0) { - newmin = (pimpl->_bbox.ymin()-ref_point.y())/dir.y(); - newmax = (pimpl->_bbox.ymax()-ref_point.y())/dir.y(); - } else { - newmin = (pimpl->_bbox.ymax()-ref_point.y())/dir.y(); - newmax = (pimpl->_bbox.ymin()-ref_point.y())/dir.y(); - } - if (to_infinity) { - pimpl->_min = newmin; - pimpl->_max = newmax; - } else { - if (newmin > pimpl->_min) - pimpl->_min = newmin; - if (newmax < pimpl->_max) - pimpl->_max = newmax; - if (pimpl->_max < pimpl->_min) { - pimpl->_result = NO_INTERSECTION; - return pimpl->_result; - } - } - to_infinity = false; - } - CGAL_kernel_assertion(!to_infinity); - if (pimpl->_max == pimpl->_min) { - pimpl->_result = POINT; - return pimpl->_result; - } - pimpl->_result = SEGMENT; - return pimpl->_result; -} - - -bool -Bbox_2_Line_2_pair::intersection( - double &x1, double &y1, double &x2, double &y2) const -{ - if (!pimpl->_known) - intersection_type(); - if (pimpl->_result != SEGMENT) - return false; - Rcart::Point_2 p1(pimpl->_line.point() - + pimpl->_min*pimpl->_line.direction().to_vector()); - Rcart::Point_2 p2(pimpl->_line.point() - + pimpl->_max*pimpl->_line.direction().to_vector()); - x1 = p1.x(); - y1 = p1.y(); - x2 = p2.x(); - y2 = p2.y(); - return true; -} - -bool -Bbox_2_Line_2_pair::intersection( - double &x, double &y) const -{ - if (!pimpl->_known) - intersection_type(); - if (pimpl->_result != POINT) - return false; - Rcart::Point_2 pt(pimpl->_line.point() - + pimpl->_min*pimpl->_line.direction().to_vector()); - x = pt.x(); - y = pt.y(); - return true; -} - - -class Bbox_2_Ray_2_pair_impl -{ -public: - Bbox_2_Ray_2_pair_impl():_known(false) {} - Bbox_2_Ray_2_pair_impl(Bbox_2 const &bbox, Rcart::Point_2 const &pt, - Rcart::Vector_2 const &dir) - :_box(bbox), _known(false), _ref_point(pt), _dir(dir), _min(0.0) {} - Ray_2< Rcart > _ray; - Bbox_2 _box; - bool _known; - Bbox_2_Ray_2_pair::Intersection_results _result; - Rcart::Point_2 _ref_point; - Rcart::Vector_2 _dir; - double _min, _max; -}; - -Bbox_2_Ray_2_pair::~Bbox_2_Ray_2_pair() -{ - delete pimpl; -} - -Bbox_2_Ray_2_pair::Bbox_2_Ray_2_pair() -{ - pimpl = new Bbox_2_Ray_2_pair_impl; -} - -Bbox_2_Ray_2_pair::Bbox_2_Ray_2_pair(Bbox_2_Ray_2_pair const &o) -{ - pimpl = new Bbox_2_Ray_2_pair_impl(*o.pimpl); -} - -Bbox_2_Ray_2_pair::Bbox_2_Ray_2_pair( - Bbox_2 const &bbox, double x, double y, double dx, double dy) -{ - pimpl = new Bbox_2_Ray_2_pair_impl(bbox, - Rcart::Point_2(x,y), Rcart::Vector_2(dx,dy)); -} - -Bbox_2_Ray_2_pair & -Bbox_2_Ray_2_pair::operator=(Bbox_2_Ray_2_pair const &o) -{ - *pimpl = *o.pimpl; - return *this; -} - - -Bbox_2_Ray_2_pair::Intersection_results -Bbox_2_Ray_2_pair::intersection_type() const -{ - if (pimpl->_known) - return pimpl->_result; - pimpl->_known = true; - bool to_infinity = true; -// first on x value - if (pimpl->_dir.x() == 0.0) { - if (pimpl->_ref_point.x() < pimpl->_box.xmin()) { - pimpl->_result = NO_INTERSECTION; - return pimpl->_result; - } - if (pimpl->_ref_point.x() > pimpl->_box.xmax()) { - pimpl->_result = NO_INTERSECTION; - return pimpl->_result; - } - } else { - double newmin, newmax; - if (pimpl->_dir.x() > 0.0) { - newmin =(pimpl->_box.xmin()-pimpl->_ref_point.x())/pimpl->_dir.x(); - newmax =(pimpl->_box.xmax()-pimpl->_ref_point.x())/pimpl->_dir.x(); - } else { - newmin =(pimpl->_box.xmax()-pimpl->_ref_point.x())/pimpl->_dir.x(); - newmax =(pimpl->_box.xmin()-pimpl->_ref_point.x())/pimpl->_dir.x(); - } - if (newmin > pimpl->_min) - pimpl->_min = newmin; - if (to_infinity) { - pimpl->_max = newmax; - } else { - if (newmax < pimpl->_max) - pimpl->_max = newmax; - } - if (pimpl->_max < pimpl->_min){ - pimpl->_result = NO_INTERSECTION; - return pimpl->_result; - } - to_infinity = false; - } -// now on y value - if (pimpl->_dir.y() == 0.0) { - if (pimpl->_ref_point.y() < pimpl->_box.ymin()) { - pimpl->_result = NO_INTERSECTION; - return pimpl->_result; - } - if (pimpl->_ref_point.y() > pimpl->_box.ymax()) { - pimpl->_result = NO_INTERSECTION; - return pimpl->_result; - } - } else { - double newmin, newmax; - if (pimpl->_dir.y() > 0.0) { - newmin =(pimpl->_box.ymin()-pimpl->_ref_point.y())/pimpl->_dir.y(); - newmax =(pimpl->_box.ymax()-pimpl->_ref_point.y())/pimpl->_dir.y(); - } else { - newmin =(pimpl->_box.ymax()-pimpl->_ref_point.y())/pimpl->_dir.y(); - newmax =(pimpl->_box.ymin()-pimpl->_ref_point.y())/pimpl->_dir.y(); - } - if (newmin > pimpl->_min) - pimpl->_min = newmin; - if (to_infinity) { - pimpl->_max = newmax; - } else { - if (newmax < pimpl->_max) - pimpl->_max = newmax; - } - if (pimpl->_max < pimpl->_min) { - pimpl->_result = NO_INTERSECTION; - return pimpl->_result; - } - to_infinity = false; - } - CGAL_kernel_assertion(!to_infinity); - if (pimpl->_max == pimpl->_min) { - pimpl->_result = POINT; - return pimpl->_result; - } - pimpl->_result = SEGMENT; - return pimpl->_result; -} - - -bool Bbox_2_Ray_2_pair:: -intersection(double &x1, double &y1, double &x2, double &y2) const -{ - if (!pimpl->_known) - intersection_type(); - if (pimpl->_result != SEGMENT) - return false; - Rcart::Point_2 p1(pimpl->_ref_point + pimpl->_min*pimpl->_dir); - Rcart::Point_2 p2(pimpl->_ref_point + pimpl->_max*pimpl->_dir); - x1 = p1.x(); - y1 = p1.y(); - x2 = p2.x(); - y2 = p2.y(); - return true; -} - -bool Bbox_2_Ray_2_pair::intersection(double &x, double &y) const -{ - if (!pimpl->_known) - intersection_type(); - if (pimpl->_result != POINT) - return false; - Rcart::Point_2 pt = pimpl->_ref_point + pimpl->_min*pimpl->_dir; - x = pt.x(); - y = pt.y(); - return true; -} - - -bool do_intersect_ray_2( - const Bbox_2 &box, double x, double y, double dx, double dy) -{ - Bbox_2_Ray_2_pair pair(box, x, y, dx, dy); - return pair.intersection_type() != Bbox_2_Ray_2_pair::NO_INTERSECTION; -} - -} //namespace CGAL +#endif // CGAL_HEADER_ONLY diff --git a/Kernel_23/include/CGAL/Bbox_2.h b/Kernel_23/include/CGAL/Bbox_2.h index e90bcf00e07..3e7131334da 100644 --- a/Kernel_23/include/CGAL/Bbox_2.h +++ b/Kernel_23/include/CGAL/Bbox_2.h @@ -166,7 +166,7 @@ inline std::ostream& operator<<(std::ostream &os, const Bbox_2 &b) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : os << b.xmin() << ' ' << b.ymin() << ' ' << b.xmax() << ' ' << b.ymax(); @@ -191,7 +191,7 @@ operator>>(std::istream &is, Bbox_2 &b) { double xmin, ymin, xmax, ymax; - switch(is.iword(IO::mode)) { + switch(get_mode(is)) { case IO::ASCII : is >> iformat(xmin) >> iformat(ymin) >> iformat(xmax) >> iformat(ymax); break; diff --git a/Kernel_23/include/CGAL/Bbox_3.h b/Kernel_23/include/CGAL/Bbox_3.h index 8be250baa2e..a3e99270953 100644 --- a/Kernel_23/include/CGAL/Bbox_3.h +++ b/Kernel_23/include/CGAL/Bbox_3.h @@ -184,7 +184,7 @@ inline std::ostream& operator<<(std::ostream &os, const Bbox_3& b) { - switch(os.iword(IO::mode)) + switch(get_mode(os)) { case IO::ASCII : return os << b.xmin() << ' ' << b.ymin() << ' ' << b.zmin() @@ -214,7 +214,7 @@ operator>>(std::istream &is, Bbox_3& b) { double xmin, ymin, zmin, xmax, ymax, zmax; - switch(is.iword(IO::mode)) + switch(get_mode(is)) { case IO::ASCII : is >> iformat(xmin) >> iformat(ymin) >> iformat(zmin) diff --git a/Kernel_23/include/CGAL/Circle_2.h b/Kernel_23/include/CGAL/Circle_2.h index f31db794fbb..b12ccb6feef 100644 --- a/Kernel_23/include/CGAL/Circle_2.h +++ b/Kernel_23/include/CGAL/Circle_2.h @@ -228,7 +228,7 @@ template std::ostream& insert(std::ostream& os, const Circle_2& c) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : os << c.center() << ' ' << c.squared_radius() << ' ' << static_cast(c.orientation()); @@ -271,7 +271,7 @@ extract(std::istream& is, Circle_2& c) typename R::Point_2 center; typename R::FT squared_radius; int o; - switch(is.iword(IO::mode)) { + switch(get_mode(is)) { case IO::ASCII : is >> center >> iformat(squared_radius) >> o; break; diff --git a/Kernel_23/include/CGAL/Direction_2.h b/Kernel_23/include/CGAL/Direction_2.h index 08b9e53e32e..bca7fa567d2 100644 --- a/Kernel_23/include/CGAL/Direction_2.h +++ b/Kernel_23/include/CGAL/Direction_2.h @@ -186,7 +186,7 @@ std::ostream& insert(std::ostream& os, const Direction_2& d, const Cartesian_tag&) { typename R::Vector_2 v = d.to_vector(); - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << v.x() << ' ' << v.y(); case IO::BINARY : @@ -202,7 +202,7 @@ template std::ostream& insert(std::ostream& os, const Direction_2& d, const Homogeneous_tag&) { - switch(os.iword(IO::mode)) + switch(get_mode(os)) { case IO::ASCII : return os << d.dx() << ' ' << d.dy(); @@ -229,7 +229,7 @@ std::istream& extract(std::istream& is, Direction_2& d, const Cartesian_tag&) { typename R::FT x, y; - switch(is.iword(IO::mode)) { + switch(get_mode(is)) { case IO::ASCII : is >> iformat(x) >> iformat(y); break; @@ -252,7 +252,7 @@ std::istream& extract(std::istream& is, Direction_2& d, const Homogeneous_tag&) { typename R::RT x, y; - switch(is.iword(IO::mode)) + switch(get_mode(is)) { case IO::ASCII : is >> iformat(x) >> iformat(y); diff --git a/Kernel_23/include/CGAL/Direction_3.h b/Kernel_23/include/CGAL/Direction_3.h index 5abeeb55e63..eff1991b9b4 100644 --- a/Kernel_23/include/CGAL/Direction_3.h +++ b/Kernel_23/include/CGAL/Direction_3.h @@ -139,7 +139,7 @@ std::ostream& insert(std::ostream& os, const Direction_3& d, const Cartesian_tag&) { typename R::Vector_3 v = d.to_vector(); - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << v.x() << ' ' << v.y() << ' ' << v.z(); case IO::BINARY : @@ -157,7 +157,7 @@ template std::ostream& insert(std::ostream& os, const Direction_3& d, const Homogeneous_tag&) { - switch(os.iword(IO::mode)) + switch(get_mode(os)) { case IO::ASCII : return os << d.dx() << ' ' << d.dy() << ' ' << d.dz(); @@ -186,7 +186,7 @@ std::istream& extract(std::istream& is, Direction_3& d, const Cartesian_tag&) { typename R::FT x, y, z; - switch(is.iword(IO::mode)) { + switch(get_mode(is)) { case IO::ASCII : is >> iformat(x) >> iformat(y) >> iformat(z); break; @@ -210,7 +210,7 @@ std::istream& extract(std::istream& is, Direction_3& d, const Homogeneous_tag&) { typename R::RT x, y, z; - switch(is.iword(IO::mode)) + switch(get_mode(is)) { case IO::ASCII : is >> iformat(x) >> iformat(y) >> iformat(z); diff --git a/Kernel_23/include/CGAL/Iso_cuboid_3.h b/Kernel_23/include/CGAL/Iso_cuboid_3.h index 72706efa2ff..184a30f574b 100644 --- a/Kernel_23/include/CGAL/Iso_cuboid_3.h +++ b/Kernel_23/include/CGAL/Iso_cuboid_3.h @@ -239,7 +239,7 @@ template < class R > std::ostream & operator<<(std::ostream& os, const Iso_cuboid_3& r) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << (r.min)() << ' ' << (r.max)(); case IO::BINARY : diff --git a/Kernel_23/include/CGAL/Iso_rectangle_2.h b/Kernel_23/include/CGAL/Iso_rectangle_2.h index e18c132f908..9df885f0a3a 100644 --- a/Kernel_23/include/CGAL/Iso_rectangle_2.h +++ b/Kernel_23/include/CGAL/Iso_rectangle_2.h @@ -230,7 +230,7 @@ template < class R > std::ostream & operator<<(std::ostream &os, const Iso_rectangle_2 &r) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << (r.min)() << ' ' << (r.max)(); case IO::BINARY : diff --git a/Kernel_23/include/CGAL/Line_2.h b/Kernel_23/include/CGAL/Line_2.h index 239dfd6dfbc..8f83060b6a7 100644 --- a/Kernel_23/include/CGAL/Line_2.h +++ b/Kernel_23/include/CGAL/Line_2.h @@ -233,7 +233,7 @@ template std::ostream& insert(std::ostream& os, const Line_2& l) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << l.a() << ' ' << l.b() << ' ' << l.c(); case IO::BINARY : @@ -260,7 +260,7 @@ std::istream& extract(std::istream& is, Line_2& l) { typename R::RT a, b, c; - switch(is.iword(IO::mode)) { + switch(get_mode(is)) { case IO::ASCII : is >> iformat(a) >> iformat(b) >> iformat(c); break; diff --git a/Kernel_23/include/CGAL/Line_3.h b/Kernel_23/include/CGAL/Line_3.h index 4429b11c06e..47696e5a9ab 100644 --- a/Kernel_23/include/CGAL/Line_3.h +++ b/Kernel_23/include/CGAL/Line_3.h @@ -145,7 +145,7 @@ template < class R > std::ostream & operator<<(std::ostream &os, const Line_3 &l) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << l.point(0) << ' ' << l.point(1); case IO::BINARY : diff --git a/Kernel_23/include/CGAL/Origin.h b/Kernel_23/include/CGAL/Origin.h index 70b3f949531..78ec935776b 100644 --- a/Kernel_23/include/CGAL/Origin.h +++ b/Kernel_23/include/CGAL/Origin.h @@ -33,13 +33,20 @@ namespace CGAL { class Origin {}; -CGAL_EXPORT extern const Origin ORIGIN; - class Null_vector {}; +#ifndef CGAL_HEADER_ONLY + +CGAL_EXPORT extern const Origin ORIGIN; CGAL_EXPORT extern const Null_vector NULL_VECTOR; +#endif + } //namespace CGAL +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_ORIGIN_H diff --git a/Kernel_23/include/CGAL/Origin_impl.h b/Kernel_23/include/CGAL/Origin_impl.h new file mode 100644 index 00000000000..38a00c486b3 --- /dev/null +++ b/Kernel_23/include/CGAL/Origin_impl.h @@ -0,0 +1,30 @@ +// Copyright (c) 1999 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Andreas Fabri, Stefan Schirra + +namespace CGAL { + +const Origin ORIGIN = Origin(); +const Null_vector NULL_VECTOR = Null_vector(); + +} //namespace CGAL diff --git a/Kernel_23/include/CGAL/Plane_3.h b/Kernel_23/include/CGAL/Plane_3.h index 79acd6cb991..448474c5cdf 100644 --- a/Kernel_23/include/CGAL/Plane_3.h +++ b/Kernel_23/include/CGAL/Plane_3.h @@ -235,7 +235,7 @@ template < class R > std::ostream & operator<<(std::ostream &os, const Plane_3 &p) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << p.a() << ' ' << p.b() << ' ' << p.c() << ' ' << p.d(); case IO::BINARY : @@ -256,7 +256,7 @@ std::istream & operator>>(std::istream &is, Plane_3 &p) { typename R::RT a, b, c, d; - switch(is.iword(IO::mode)) { + switch(get_mode(is)) { case IO::ASCII : is >> iformat(a) >> iformat(b) >> iformat(c) >> iformat(d); break; diff --git a/Kernel_23/include/CGAL/Point_2.h b/Kernel_23/include/CGAL/Point_2.h index 83c6f1d2bae..6c1ac87105b 100644 --- a/Kernel_23/include/CGAL/Point_2.h +++ b/Kernel_23/include/CGAL/Point_2.h @@ -169,7 +169,7 @@ template std::ostream& insert(std::ostream& os, const Point_2& p,const Cartesian_tag&) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << p.x() << ' ' << p.y(); case IO::BINARY : @@ -185,7 +185,7 @@ template std::ostream& insert(std::ostream& os, const Point_2& p,const Homogeneous_tag&) { - switch(os.iword(IO::mode)) + switch(get_mode(os)) { case IO::ASCII : return os << p.hx() << ' ' << p.hy() << ' ' << p.hw(); @@ -214,7 +214,7 @@ std::istream& extract(std::istream& is, Point_2& p, const Cartesian_tag&) { typename R::FT x, y; - switch(is.iword(IO::mode)) { + switch(get_mode(is)) { case IO::ASCII : is >> iformat(x) >> iformat(y); break; @@ -238,7 +238,7 @@ std::istream& extract(std::istream& is, Point_2& p, const Homogeneous_tag&) { typename R::RT hx, hy, hw; - switch(is.iword(IO::mode)) + switch(get_mode(is)) { case IO::ASCII : is >> hx >> hy >> hw; diff --git a/Kernel_23/include/CGAL/Point_3.h b/Kernel_23/include/CGAL/Point_3.h index 2cf563afaba..7c7e88de0af 100644 --- a/Kernel_23/include/CGAL/Point_3.h +++ b/Kernel_23/include/CGAL/Point_3.h @@ -194,7 +194,7 @@ template std::ostream& insert(std::ostream& os, const Point_3& p,const Cartesian_tag&) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << p.x() << ' ' << p.y() << ' ' << p.z(); case IO::BINARY : @@ -212,7 +212,7 @@ template std::ostream& insert(std::ostream& os, const Point_3& p,const Homogeneous_tag&) { - switch(os.iword(IO::mode)) + switch(get_mode(os)) { case IO::ASCII : return os << p.hx() << ' ' << p.hy() << ' ' << p.hz() << ' ' << p.hw(); @@ -243,7 +243,7 @@ std::istream& extract(std::istream& is, Point_3& p, const Cartesian_tag&) { typename R::FT x, y, z; - switch(is.iword(IO::mode)) { + switch(get_mode(is)) { case IO::ASCII : is >> iformat(x) >> iformat(y) >> iformat(z); break; @@ -268,7 +268,7 @@ std::istream& extract(std::istream& is, Point_3& p, const Homogeneous_tag&) { typename R::RT hx, hy, hz, hw; - switch(is.iword(IO::mode)) + switch(get_mode(is)) { case IO::ASCII : is >> hx >> hy >> hz >> hw; diff --git a/Kernel_23/include/CGAL/Ray_2.h b/Kernel_23/include/CGAL/Ray_2.h index f01f6feb4d6..b5bb85fd726 100644 --- a/Kernel_23/include/CGAL/Ray_2.h +++ b/Kernel_23/include/CGAL/Ray_2.h @@ -207,7 +207,7 @@ template std::ostream& insert(std::ostream& os, const Ray_2& r, const Cartesian_tag&) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << r.source() << ' ' << r.second_point(); case IO::BINARY : @@ -221,7 +221,7 @@ template std::ostream& insert(std::ostream& os, const Ray_2& r, const Homogeneous_tag&) { - switch(os.iword(IO::mode)) + switch(get_mode(os)) { case IO::ASCII : return os << r.source() << ' ' << r.second_point(); diff --git a/Kernel_23/include/CGAL/Ray_3.h b/Kernel_23/include/CGAL/Ray_3.h index 0be3ade7977..d63d3ec07b7 100644 --- a/Kernel_23/include/CGAL/Ray_3.h +++ b/Kernel_23/include/CGAL/Ray_3.h @@ -173,7 +173,7 @@ template std::ostream& insert(std::ostream& os, const Ray_3& r, const Cartesian_tag&) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << r.start() << ' ' << r.direction(); case IO::BINARY : @@ -187,7 +187,7 @@ template std::ostream& insert(std::ostream& os, const Ray_3& r, const Homogeneous_tag&) { - switch(os.iword(IO::mode)) + switch(get_mode(os)) { case IO::ASCII : return os << r.start() << ' ' << r.direction(); diff --git a/Kernel_23/include/CGAL/Segment_2.h b/Kernel_23/include/CGAL/Segment_2.h index 8da500cbc00..92f6c2a8b58 100644 --- a/Kernel_23/include/CGAL/Segment_2.h +++ b/Kernel_23/include/CGAL/Segment_2.h @@ -282,7 +282,7 @@ template < class R > std::ostream & operator<<(std::ostream &os, const Segment_2 &s) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << s.source() << ' ' << s.target(); case IO::BINARY : diff --git a/Kernel_23/include/CGAL/Segment_3.h b/Kernel_23/include/CGAL/Segment_3.h index daf26dbadd4..11c3a76cbce 100644 --- a/Kernel_23/include/CGAL/Segment_3.h +++ b/Kernel_23/include/CGAL/Segment_3.h @@ -198,7 +198,7 @@ template < class R > std::ostream & operator<<(std::ostream &os, const Segment_3 &s) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << s.source() << ' ' << s.target(); case IO::BINARY : diff --git a/Kernel_23/include/CGAL/Sphere_3.h b/Kernel_23/include/CGAL/Sphere_3.h index d708093abd3..0fc542033fd 100644 --- a/Kernel_23/include/CGAL/Sphere_3.h +++ b/Kernel_23/include/CGAL/Sphere_3.h @@ -216,7 +216,7 @@ template std::ostream& insert(std::ostream& os, const Sphere_3& c,const Cartesian_tag&) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : os << c.center() << ' ' << c.squared_radius() << ' ' << static_cast(c.orientation()); @@ -248,7 +248,7 @@ template std::ostream& insert(std::ostream& os, const Sphere_3& c, const Homogeneous_tag&) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : os << c.center() << ' ' << c.squared_radius() << ' ' << static_cast(c.orientation()); @@ -291,7 +291,7 @@ extract(std::istream& is, Sphere_3& c, const Cartesian_tag&) typename R::Point_3 center; typename R::FT squared_radius; int o=0; - switch(is.iword(IO::mode)) { + switch(get_mode(is)) { case IO::ASCII : is >> center >> squared_radius >> o; break; @@ -318,7 +318,7 @@ extract(std::istream& is, Sphere_3& c, const Homogeneous_tag&) typename R::Point_3 center; typename R::FT squared_radius; int o; - switch(is.iword(IO::mode)) { + switch(get_mode(is)) { case IO::ASCII : is >> center >> squared_radius >> o; break; diff --git a/Kernel_23/include/CGAL/Tetrahedron_3.h b/Kernel_23/include/CGAL/Tetrahedron_3.h index 625421b28c6..c58882b3bc6 100644 --- a/Kernel_23/include/CGAL/Tetrahedron_3.h +++ b/Kernel_23/include/CGAL/Tetrahedron_3.h @@ -155,7 +155,7 @@ template < class R > std::ostream & operator<<(std::ostream &os, const Tetrahedron_3 &t) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << t[0] << ' ' << t[1] << ' ' << t[2] << ' ' << t[3]; case IO::BINARY : diff --git a/Kernel_23/include/CGAL/Triangle_2.h b/Kernel_23/include/CGAL/Triangle_2.h index f89aa93fd85..75bcedaaa26 100644 --- a/Kernel_23/include/CGAL/Triangle_2.h +++ b/Kernel_23/include/CGAL/Triangle_2.h @@ -182,7 +182,7 @@ template < class R > std::ostream & operator<<(std::ostream &os, const Triangle_2 &t) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << t[0] << ' ' << t[1] << ' ' << t[2]; case IO::BINARY : diff --git a/Kernel_23/include/CGAL/Triangle_3.h b/Kernel_23/include/CGAL/Triangle_3.h index b1d04a16c1d..211a8b59820 100644 --- a/Kernel_23/include/CGAL/Triangle_3.h +++ b/Kernel_23/include/CGAL/Triangle_3.h @@ -125,7 +125,7 @@ template < class R > std::ostream & operator<<(std::ostream &os, const Triangle_3 &t) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << t[0] << ' ' << t[1] << ' ' << t[2]; case IO::BINARY : diff --git a/Kernel_23/include/CGAL/Vector_2.h b/Kernel_23/include/CGAL/Vector_2.h index 539030b7def..23e3b6edae5 100644 --- a/Kernel_23/include/CGAL/Vector_2.h +++ b/Kernel_23/include/CGAL/Vector_2.h @@ -251,7 +251,7 @@ template std::ostream& insert(std::ostream& os, const Vector_2& v, const Cartesian_tag&) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << v.x() << ' ' << v.y(); case IO::BINARY : @@ -267,7 +267,7 @@ template std::ostream& insert(std::ostream& os, const Vector_2& v, const Homogeneous_tag&) { - switch(os.iword(IO::mode)) + switch(get_mode(os)) { case IO::ASCII : return os << v.hx() << ' ' << v.hy() << ' ' << v.hw(); @@ -297,7 +297,7 @@ std::istream& extract(std::istream& is, Vector_2& v, const Cartesian_tag&) { typename R::FT x, y; - switch(is.iword(IO::mode)) { + switch(get_mode(is)) { case IO::ASCII : is >> iformat(x) >> iformat(y); break; @@ -321,7 +321,7 @@ std::istream& extract(std::istream& is, Vector_2& v, const Homogeneous_tag&) { typename R::RT hx, hy, hw; - switch(is.iword(IO::mode)) + switch(get_mode(is)) { case IO::ASCII : is >> hx >> hy >> hw; diff --git a/Kernel_23/include/CGAL/Vector_3.h b/Kernel_23/include/CGAL/Vector_3.h index 973dcdbd213..5f18d0493af 100644 --- a/Kernel_23/include/CGAL/Vector_3.h +++ b/Kernel_23/include/CGAL/Vector_3.h @@ -228,7 +228,7 @@ template std::ostream& insert(std::ostream& os, const Vector_3& v, const Cartesian_tag&) { - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : return os << v.x() << ' ' << v.y() << ' ' << v.z(); case IO::BINARY : @@ -246,7 +246,7 @@ template std::ostream& insert(std::ostream& os, const Vector_3& v, const Homogeneous_tag&) { - switch(os.iword(IO::mode)) + switch(get_mode(os)) { case IO::ASCII : return os << v.hx() << ' ' << v.hy() << ' ' << v.hz() << ' ' << v.hw(); @@ -277,7 +277,7 @@ std::istream& extract(std::istream& is, Vector_3& v, const Cartesian_tag&) { typename R::FT x, y, z; - switch(is.iword(IO::mode)) { + switch(get_mode(is)) { case IO::ASCII : is >> iformat(x) >> iformat(y) >> iformat(z); break; @@ -301,7 +301,7 @@ std::istream& extract(std::istream& is, Vector_3& v, const Homogeneous_tag&) { typename R::RT hx, hy, hz, hw; - switch(is.iword(IO::mode)) + switch(get_mode(is)) { case IO::ASCII : is >> hx >> hy >> hz >> hw; diff --git a/Kernel_23/include/CGAL/aff_transformation_tags.h b/Kernel_23/include/CGAL/aff_transformation_tags.h index 7e6b833bc7d..96a0041699a 100644 --- a/Kernel_23/include/CGAL/aff_transformation_tags.h +++ b/Kernel_23/include/CGAL/aff_transformation_tags.h @@ -36,12 +36,19 @@ class Scaling {}; class Reflection {}; class Identity_transformation {}; -CGAL_EXPORT extern const Translation TRANSLATION; -CGAL_EXPORT extern const Rotation ROTATION; -CGAL_EXPORT extern const Scaling SCALING; -CGAL_EXPORT extern const Reflection REFLECTION; -CGAL_EXPORT extern const Identity_transformation IDENTITY; +#ifndef CGAL_HEADER_ONLY + +CGAL_EXPORT extern const Translation TRANSLATION; +CGAL_EXPORT extern const Rotation ROTATION; +CGAL_EXPORT extern const Scaling SCALING; +CGAL_EXPORT extern const Reflection REFLECTION; +CGAL_EXPORT extern const Identity_transformation IDENTITY; + +#endif } //namespace CGAL +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY #endif // CGAL_AFF_TRANSFORMATION_TAGS_H diff --git a/Kernel_23/include/CGAL/aff_transformation_tags_impl.h b/Kernel_23/include/CGAL/aff_transformation_tags_impl.h new file mode 100644 index 00000000000..d454b445653 --- /dev/null +++ b/Kernel_23/include/CGAL/aff_transformation_tags_impl.h @@ -0,0 +1,33 @@ +// Copyright (c) 1999 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Andreas Fabri, Stefan Schirra + +namespace CGAL { + +const Translation TRANSLATION = Translation(); +const Rotation ROTATION = Rotation(); +const Scaling SCALING = Scaling(); +const Reflection REFLECTION = Reflection(); +const Identity_transformation IDENTITY = Identity_transformation(); + +} //namespace CGAL diff --git a/Kernel_23/src/CGAL/kernel.cpp b/Kernel_23/src/CGAL/kernel.cpp index 27d0dfa90ed..d5660472aed 100644 --- a/Kernel_23/src/CGAL/kernel.cpp +++ b/Kernel_23/src/CGAL/kernel.cpp @@ -22,18 +22,10 @@ // // Author(s) : Andreas Fabri, Stefan Schirra +#ifndef CGAL_HEADER_ONLY #include +#include #include +#include -namespace CGAL { - -const Translation TRANSLATION = Translation(); -const Rotation ROTATION = Rotation(); -const Scaling SCALING = Scaling(); -const Reflection REFLECTION = Reflection(); -const Identity_transformation IDENTITY = Identity_transformation(); - -const Origin ORIGIN = Origin(); -const Null_vector NULL_VECTOR = Null_vector(); - -} //namespace CGAL +#endif // CGAL_HEADER_ONLY diff --git a/Kernel_23/test/Kernel_23/Kernel_checker.cpp b/Kernel_23/test/Kernel_23/Kernel_checker.cpp index 4c7c34a790d..001cda3219f 100644 --- a/Kernel_23/test/Kernel_23/Kernel_checker.cpp +++ b/Kernel_23/test/Kernel_23/Kernel_checker.cpp @@ -24,7 +24,7 @@ typedef CGAL::Delaunay_triangulation_3 Delaunay3d; int my_rand() { - return int(CGAL::default_random.get_double()*(1<<31)); + return int(CGAL::get_default_random().get_double()*(1<<31)); } int main() diff --git a/Kernel_d/include/CGAL/Kernel_d/Matrix__.h b/Kernel_d/include/CGAL/Kernel_d/Matrix__.h index d6f3fb9db05..24aefedb80c 100644 --- a/Kernel_d/include/CGAL/Kernel_d/Matrix__.h +++ b/Kernel_d/include/CGAL/Kernel_d/Matrix__.h @@ -749,7 +749,7 @@ std::ostream& operator<<(std::ostream& os, const Matrix_& M) int d = M.row_dimension(); int k = M.column_dimension(); - switch (os.iword(CGAL::IO::mode)) { + switch (get_mode(os)) { case CGAL::IO::BINARY: CGAL::write( os, d); CGAL::write( os, k); @@ -793,7 +793,7 @@ std::istream& operator>>(std::istream& is, Matrix_& M) x_d2,0 ... x_d2,d1-1 */ int cdim, rdim, i; - switch(is.iword(CGAL::IO::mode)) { + switch(get_mode(is)) { case CGAL::IO::BINARY : CGAL::read(is,rdim); CGAL::read(is,cdim); diff --git a/Kernel_d/include/CGAL/Kernel_d/Pair_d.h b/Kernel_d/include/CGAL/Kernel_d/Pair_d.h index 564e143b658..e91abb3ac02 100644 --- a/Kernel_d/include/CGAL/Kernel_d/Pair_d.h +++ b/Kernel_d/include/CGAL/Kernel_d/Pair_d.h @@ -69,7 +69,7 @@ Direction_d direction() const void read(std::istream& is) { - switch( is.iword(CGAL::IO::mode) ) { + switch( get_mode(is) ) { case CGAL::IO::ASCII : is >> _p[0] >> _p[1]; break; case CGAL::IO::BINARY : @@ -81,7 +81,7 @@ void read(std::istream& is) void print(std::ostream& os, const char* _name) const { - switch( os.iword(CGAL::IO::mode) ) { + switch( get_mode(os) ) { case CGAL::IO::ASCII : os << _p[0] << " " << _p[1]; break; case CGAL::IO::BINARY : diff --git a/Kernel_d/include/CGAL/Kernel_d/Tuple_d.h b/Kernel_d/include/CGAL/Kernel_d/Tuple_d.h index 425a82a968f..6f07dbe1886 100644 --- a/Kernel_d/include/CGAL/Kernel_d/Tuple_d.h +++ b/Kernel_d/include/CGAL/Kernel_d/Tuple_d.h @@ -220,7 +220,7 @@ Comparison_result operator()( template void Tuple_d::print(std::ostream& os, const char* l) const { int i; - switch( os.iword(CGAL::IO::mode) ) { + switch( get_mode(os) ) { case CGAL::IO::ASCII : os << size() << " "; for (i = 0; i < size(); ++i) @@ -241,7 +241,7 @@ void Tuple_d::print(std::ostream& os, const char* l) const template void Tuple_d::read(std::istream& is) { int i = 0, d; - switch( is.iword(CGAL::IO::mode) ) { + switch( get_mode(is) ) { case CGAL::IO::ASCII : is >> d; v = Vector(d); while (i < d && is >> v[i] ) ++i; diff --git a/Kernel_d/include/CGAL/Kernel_d/Vector__.h b/Kernel_d/include/CGAL/Kernel_d/Vector__.h index b4ba1085334..f45c4265c1c 100644 --- a/Kernel_d/include/CGAL/Kernel_d/Vector__.h +++ b/Kernel_d/include/CGAL/Kernel_d/Vector__.h @@ -405,7 +405,7 @@ std::ostream& operator<<(std::ostream& os, const Vector_& v) /*{\Xbinopfunc writes |\Mvar| componentwise to the output stream $O$.}*/ { /* syntax: d x_0 x_1 ... x_d-1 */ int d = v.dimension(); - switch (os.iword(CGAL::IO::mode)) { + switch (get_mode(os)) { case CGAL::IO::BINARY: CGAL::write( os, d); for ( int i = 0; i < d; ++i) @@ -434,7 +434,7 @@ std::istream& operator>>(std::istream& is, Vector_& v) /*{\Xbinopfunc reads |\Mvar| componentwise from the input stream $I$.}*/ { /* syntax: d x_0 x_1 ... x_d-1 */ int d; - switch (is.iword(CGAL::IO::mode)) { + switch (get_mode(is)) { case CGAL::IO::ASCII : case CGAL::IO::BINARY : is >> d; diff --git a/Kernel_d/test/Kernel_d/Linear_algebra-test.cpp b/Kernel_d/test/Kernel_d/Linear_algebra-test.cpp index eefecd03070..af5a3cad1be 100644 --- a/Kernel_d/test/Kernel_d/Linear_algebra-test.cpp +++ b/Kernel_d/test/Kernel_d/Linear_algebra-test.cpp @@ -39,7 +39,7 @@ int main(int argc, char* argv[]) typedef LA::Matrix Matrix; typedef LA::Vector Vector; bool IOTEST = true; - { + { int vec_dim; if (argc == 2) vec_dim = std::atoi(argv[1]); else vec_dim = VEC_DIM; @@ -48,7 +48,7 @@ int main(int argc, char* argv[]) Vector v0(vec_dim), v1(vec_dim), v2(vec_dim); int F[] = { 1,2,3,4,5 }; Vector v11(F,F+2), v12(F,F+3), v13(F,F+4), v14(F,F+5), - v15(v13.begin(),v13.end()), + v15(v13.begin(),v13.end()), v16(vec_dim,NT(1)); CGAL_TEST(v13==v15){} CGAL_TEST(v0==v1){} @@ -64,7 +64,7 @@ int main(int argc, char* argv[]) v1 -= v2; v1 = -v1; CGAL_TEST((v1*v1 == NT(vec_dim*vec_dim*vec_dim))){} - /* squared length of (v1 + v2) = v1*v1 + /* squared length of (v1 + v2) = v1*v1 should be equal to dim*dim*dim */ NT res1 = (v1*v1 - v2*v2); NT res2 = ((v1-v2)*(v1+v2)); @@ -78,7 +78,7 @@ int main(int argc, char* argv[]) if (IOTEST) CGAL_IO_TEST(v1,v2,CGAL::IO::ASCII); } - { + { int mat_dim; if (argc == 2) mat_dim = std::atoi(argv[1]); else mat_dim = MAT_DIM; @@ -86,16 +86,16 @@ int main(int argc, char* argv[]) /* some construction and access ops */ Matrix::Identity ID; Matrix A(mat_dim,mat_dim), B(mat_dim), - I(mat_dim,ID), One(mat_dim,mat_dim,NT(2)); + I(mat_dim,ID), One(mat_dim,mat_dim,NT(2)); CGAL_TEST(A==B){} CGAL_TEST(One*I==One){} std::vector F(mat_dim); - int i,j; + int i,j; for (i = 0; i < mat_dim; i++) { Vector v(mat_dim); - for (j = 0; j < mat_dim; j++) { - A(i,j) = i; + for (j = 0; j < mat_dim; j++) { + A(i,j) = i; B(i,j) = j; v[j] = j; } @@ -115,7 +115,7 @@ int main(int argc, char* argv[]) (0,1,2,3...) (0,1,2,3...) ... - C = A = D = E; + C = A = D = E; */ Matrix::iterator it; @@ -130,15 +130,15 @@ int main(int argc, char* argv[]) CGAL_TEST(A.row(1)*B.column(1)==NT(mat_dim)){} /* some basic arithmetic testing */ - C = A; C += A; - C -= NT(3)*A; - C = -C; + C = A; C += A; + C -= NT(3)*A; + C = -C; CGAL_TEST(C==A){} /* row sum test: */ - Vector ones(mat_dim), row_sum_vec(mat_dim); + Vector ones(mat_dim), row_sum_vec(mat_dim); for (i = 0; i < mat_dim; i++) { - ones[i] = 1; + ones[i] = 1; row_sum_vec[i] = i*mat_dim; } CGAL_TEST(A*ones==row_sum_vec){} @@ -147,16 +147,16 @@ int main(int argc, char* argv[]) /* matrix operations + ,* and |transpose|, |rank| */ CGAL_TEST(C==LA::transpose(C)){} C = C-B; - CGAL_TEST(C==A){} + CGAL_TEST(C==A){} C = I+A; CGAL_TEST(LA::rank(C)==mat_dim){} - + /* matrix operations 2* , |determinant| */ C = NT(2) * I; C = C * NT(2); - Matrix L,U; - Vector c; - std::vector q; + Matrix L,U; + Vector c; + std::vector q; NT det = LA::determinant(C, L, U, q, c); // det must be 2^{2*mat_dim} NT pot = 1; for (i=0; i 0.0; f-=0.1) { Matrix E = C; for (i = 0; i< mat_dim; ++i) for (j = 0; j < mat_dim; ++j) - if ( CGAL::default_random.get_double() > f ) E(i,j)=0; + if ( CGAL::get_default_random().get_double() > f ) E(i,j)=0; if (LA::linear_solver(E, b, x, denom, A, e)) { CGAL_TEST(E*x == b*denom){} @@ -212,10 +212,10 @@ int main(int argc, char* argv[]) if (mat_dim > 1) { // ueberbestimmt: Matrix N(mat_dim,mat_dim-1); - for (i = 0; i < mat_dim; i++) { - for (j = 0; j < mat_dim-1; j++) - N(i,j) = CGAL::default_random.get_int(-mat_dim,mat_dim); - b[i] = CGAL::default_random.get_int(-mat_dim,mat_dim); + for (i = 0; i < mat_dim; i++) { + for (j = 0; j < mat_dim-1; j++) + N(i,j) = CGAL::get_default_random().get_int(-mat_dim,mat_dim); + b[i] = CGAL::get_default_random().get_int(-mat_dim,mat_dim); } if (LA::linear_solver(N,b,x,denom,e)) { CGAL_TEST(N*x == b*denom){} @@ -235,7 +235,7 @@ int main(int argc, char* argv[]) typedef LA::Matrix Matrix; typedef LA::Vector Vector; bool IOTEST = false; - { + { int vec_dim; if (argc == 2) vec_dim = std::atoi(argv[1]); else vec_dim = VEC_DIM; @@ -245,7 +245,7 @@ int main(int argc, char* argv[]) Vector v0(vec_dim), v1(vec_dim), v2(vec_dim); int F[] = { 1,2,3,4,5 }; Vector v11(F,F+2), v12(F,F+3), v13(F,F+4), v14(F,F+5), - v15(v13.begin(),v13.end()), + v15(v13.begin(),v13.end()), v16(vec_dim,NT(1)); CGAL_TEST(v13==v15){} CGAL_TEST(v0==v1){} @@ -261,7 +261,7 @@ int main(int argc, char* argv[]) v1 -= v2; v1 = -v1; CGAL_TEST((v1*v1 == NT(vec_dim*vec_dim*vec_dim))){} - /* squared length of (v1 + v2) = v1*v1 + /* squared length of (v1 + v2) = v1*v1 should be equal to dim*dim*dim */ NT res1 = (v1*v1 - v2*v2); NT res2 = ((v1-v2)*(v1+v2)); @@ -276,7 +276,7 @@ int main(int argc, char* argv[]) if (IOTEST) CGAL_IO_TEST(v1,v2,CGAL::IO::ASCII); } - { + { int mat_dim; if (argc == 2) mat_dim = std::atoi(argv[1]); else mat_dim = MAT_DIM; @@ -284,16 +284,16 @@ int main(int argc, char* argv[]) /* some construction and access ops */ Matrix::Identity ID; Matrix A(mat_dim,mat_dim), B(mat_dim), - I(mat_dim,ID), One(mat_dim,mat_dim,NT(2)); + I(mat_dim,ID), One(mat_dim,mat_dim,NT(2)); CGAL_TEST(A==B){} CGAL_TEST(One*I==One){} std::vector F(mat_dim); - int i,j; + int i,j; for (i = 0; i < mat_dim; i++) { Vector v(mat_dim); - for (j = 0; j < mat_dim; j++) { - A(i,j) = i; + for (j = 0; j < mat_dim; j++) { + A(i,j) = i; B(i,j) = j; v[j] = j; } @@ -313,7 +313,7 @@ int main(int argc, char* argv[]) (0,1,2,3...) (0,1,2,3...) ... - C = A = D = E; + C = A = D = E; */ Matrix::iterator it; @@ -328,15 +328,15 @@ int main(int argc, char* argv[]) CGAL_TEST(A.row(1)*B.column(1)==NT(mat_dim)){} /* some basic arithmetic testing */ - C = A; C += A; - C -= NT(3)*A; - C = -C; + C = A; C += A; + C -= NT(3)*A; + C = -C; CGAL_TEST(C==A){} /* row sum test: */ - Vector ones(mat_dim), row_sum_vec(mat_dim); + Vector ones(mat_dim), row_sum_vec(mat_dim); for (i = 0; i < mat_dim; i++) { - ones[i] = 1; + ones[i] = 1; row_sum_vec[i] = i*mat_dim; } CGAL_TEST(A*ones==row_sum_vec){} @@ -345,16 +345,16 @@ int main(int argc, char* argv[]) /* matrix operations + ,* and |transpose|, |rank| */ CGAL_TEST(C==LA::transpose(C)){} C = C-B; - CGAL_TEST(C==A){} + CGAL_TEST(C==A){} C = I+A; CGAL_TEST(LA::rank(C)==mat_dim){} - + /* matrix operations 2* , |determinant| */ C = NT(2) * I; C = C * NT(2); - Matrix L,U; - Vector c; - std::vector q; + Matrix L,U; + Vector c; + std::vector q; NT det = LA::determinant(C, L, U, q, c); // det must be 2^{2*mat_dim} NT pot = 1; for (i=0; i 0.0; f-=0.1) { Matrix E = C; for (i = 0; i< mat_dim; ++i) for (j = 0; j < mat_dim; ++j) - if ( CGAL::default_random.get_double() > f ) E(i,j)=0; + if ( CGAL::get_default_random().get_double() > f ) E(i,j)=0; if (LA::linear_solver(E, b, x, denom, A, e)) { CGAL_TEST(E*x == b*denom){} @@ -409,10 +409,10 @@ int main(int argc, char* argv[]) if (mat_dim > 1) { // ueberbestimmt: Matrix N(mat_dim,mat_dim-1); - for (i = 0; i < mat_dim; i++) { - for (j = 0; j < mat_dim-1; j++) - N(i,j) = CGAL::default_random.get_int(-mat_dim,mat_dim); - b[i] = CGAL::default_random.get_int(-mat_dim,mat_dim); + for (i = 0; i < mat_dim; i++) { + for (j = 0; j < mat_dim-1; j++) + N(i,j) = CGAL::get_default_random().get_int(-mat_dim,mat_dim); + b[i] = CGAL::get_default_random().get_int(-mat_dim,mat_dim); } if (LA::linear_solver(N,b,x,denom,e)) { CGAL_TEST(N*x == b*denom){} diff --git a/Kinetic_data_structures/include/CGAL/Kinetic/Active_objects_vector.h b/Kinetic_data_structures/include/CGAL/Kinetic/Active_objects_vector.h index 22de44f98b1..7659c695a95 100644 --- a/Kinetic_data_structures/include/CGAL/Kinetic/Active_objects_vector.h +++ b/Kinetic_data_structures/include/CGAL/Kinetic/Active_objects_vector.h @@ -313,7 +313,7 @@ CGAL_expensive_assertion_code(if ( storage_[i].second == storage_.back().second) iss >> d; if (!iss) { CGAL_ERROR("ERROR reading object from line " << buf); - ++internal::io_errors__; + ++internal::get_static_io_errors(); } else { //CGAL_LOG(Log::LOTS, "Read " << d << std::endl); insert(d); diff --git a/Kinetic_data_structures/include/CGAL/Kinetic/Handle_degeneracy_function_kernel.h b/Kinetic_data_structures/include/CGAL/Kinetic/Handle_degeneracy_function_kernel.h index 3e1dc8da996..a8b91ca941b 100644 --- a/Kinetic_data_structures/include/CGAL/Kinetic/Handle_degeneracy_function_kernel.h +++ b/Kinetic_data_structures/include/CGAL/Kinetic/Handle_degeneracy_function_kernel.h @@ -45,7 +45,7 @@ class HDRS{ CGAL_expensive_precondition(solver_.empty() || solver_.top() >= lb); if (uf.degree() == -1) { CGAL_LOG(Log::SOME, "Zero function found at time " << lb << std::endl); - ++ internal::zero_certificates__; + ++ internal::get_static_zero_certificates(); } #ifndef NDEBUG if (!SLOPPY && k.sign_at_object()(uf, lb) == CGAL::NEGATIVE) { @@ -61,7 +61,7 @@ class HDRS{ CGAL_LOG(Log::LOTS, "Degeneracy at " << solver_.top() << std::endl); CGAL::Sign sn = k.sign_after_object()(uf, lb); if (sn == CGAL::NEGATIVE) { - ++internal::function_degeneracies__; + ++internal::get_static_function_degeneracies(); CGAL_LOG(Log::LOTS, "Extra root at lower bound of " << lb << std::endl); } else { CGAL_LOG(Log::LOTS, "Popping extra root at lower bound of " << lb << std::endl); diff --git a/Kinetic_data_structures/include/CGAL/Kinetic/Sort.h b/Kinetic_data_structures/include/CGAL/Kinetic/Sort.h index d5e0a34ad57..11940198b55 100644 --- a/Kinetic_data_structures/include/CGAL/Kinetic/Sort.h +++ b/Kinetic_data_structures/include/CGAL/Kinetic/Sort.h @@ -277,7 +277,7 @@ public: #endif write(std::cerr); std::cerr << std::endl; - ++internal::audit_failures__; + ++internal::get_static_audit_failures(); if (!wrote_objects_) { wrote_objects_=true; @@ -311,7 +311,7 @@ public: #endif write(std::cerr); std::cerr << std::endl; - ++internal::audit_failures__; + ++internal::get_static_audit_failures(); if (!wrote_objects_) { wrote_objects_=true; diff --git a/Kinetic_data_structures/include/CGAL/Kinetic/Two_list_pointer_event_queue.h b/Kinetic_data_structures/include/CGAL/Kinetic/Two_list_pointer_event_queue.h index 7b49224b297..f3f834d3df8 100644 --- a/Kinetic_data_structures/include/CGAL/Kinetic/Two_list_pointer_event_queue.h +++ b/Kinetic_data_structures/include/CGAL/Kinetic/Two_list_pointer_event_queue.h @@ -717,7 +717,7 @@ protected: #ifndef NDEBUG if (CGAL::compare(tc, tp) == CGAL::SMALLER) { std::cout << "ERROR: Out of order " << tc << std::endl << tp << std::endl << std::endl; - ++internal::audit_failures__; + ++internal::get_static_audit_failures(); } #endif //CGAL_assertion(tc >= tp); diff --git a/Kinetic_data_structures/include/CGAL/Kinetic/internal/debug_counters.h b/Kinetic_data_structures/include/CGAL/Kinetic/internal/debug_counters.h index d03f1e0a9a2..5e4862f159b 100644 --- a/Kinetic_data_structures/include/CGAL/Kinetic/internal/debug_counters.h +++ b/Kinetic_data_structures/include/CGAL/Kinetic/internal/debug_counters.h @@ -18,15 +18,62 @@ // // Author(s) : Daniel Russel +#ifndef CGAL_DEBUG_COUNTERS_H_ +#define CGAL_DEBUG_COUNTERS_H_ + #include namespace CGAL { namespace Kinetic { namespace internal { - CGAL_EXPORT extern unsigned int zero_certificates__; + +#ifdef CGAL_HEADER_ONLY + + inline unsigned int& get_static_function_degeneracies() + { + static unsigned int function_degeneracies__ = 0; + return function_degeneracies__; + } + inline unsigned int& get_static_zero_certificates() + { + static unsigned int zero_certificates__ = 0; + return zero_certificates__; + } + inline unsigned int& get_static_io_errors() + { + static unsigned int io_errors__ = 0; + return io_errors__; + } + inline unsigned int& get_static_audit_failures() + { + static unsigned int audit_failures__ = 0; + return audit_failures__; + } + +#else // CGAL_HEADER_ONLY + CGAL_EXPORT extern unsigned int function_degeneracies__; + CGAL_EXPORT extern unsigned int zero_certificates__; CGAL_EXPORT extern unsigned int io_errors__; CGAL_EXPORT extern unsigned int audit_failures__; + inline unsigned int& get_static_function_degeneracies() + { return function_degeneracies__; } + inline unsigned int& get_static_zero_certificates() + { return zero_certificates__; } + inline unsigned int& get_static_io_errors() + { return io_errors__; } + inline unsigned int& get_static_audit_failures() + { return audit_failures__; } + +#endif // CGAL_HEADER_ONLY + + CGAL_EXPORT void write_debug_counters(std::ostream &out); } } } //namespace CGAL::Kinetic + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + +#endif // CGAL_DEBUG_COUNTERS_H_ \ No newline at end of file diff --git a/Kinetic_data_structures/include/CGAL/Kinetic/internal/debug_counters_impl.h b/Kinetic_data_structures/include/CGAL/Kinetic/internal/debug_counters_impl.h new file mode 100644 index 00000000000..f939334deed --- /dev/null +++ b/Kinetic_data_structures/include/CGAL/Kinetic/internal/debug_counters_impl.h @@ -0,0 +1,36 @@ +// Copyright (c) 2005 Stanford University (USA). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Daniel Russel + +#if defined(BOOST_MSVC) +# pragma warning(disable:4251) +#endif +#include + +namespace CGAL { namespace Kinetic { namespace internal { + + CGAL_INLINE_FUNCTION + void write_debug_counters(std::ostream &out) { + out << "Degeneracies " << get_static_function_degeneracies() << std::endl; + out << "Zero functions " << get_static_zero_certificates() << std::endl; + if (get_static_io_errors() != 0) out << "I/O errors " << get_static_io_errors() << std::endl; + if (get_static_audit_failures() != 0) out << "Audit failures " << get_static_audit_failures() << std::endl; + } + +} } } //namespace CGAL::Kinetic::internal diff --git a/Kinetic_data_structures/include/CGAL/Polynomial/internal/JAMA_numeric_solvers_impl.h b/Kinetic_data_structures/include/CGAL/Polynomial/internal/JAMA_numeric_solvers_impl.h new file mode 100644 index 00000000000..c9153c85667 --- /dev/null +++ b/Kinetic_data_structures/include/CGAL/Polynomial/internal/JAMA_numeric_solvers_impl.h @@ -0,0 +1,135 @@ +// Copyright (c) 2005 Stanford University (USA). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Daniel Russel + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include + +#ifdef CGAL_HAVE_TNT +#include +#include +#include +#endif + +#include +#include +#include + +//#include + +namespace CGAL { namespace POLYNOMIAL { namespace internal { +#if CGAL_HAVE_TNT +//static const double max_error_value =0.00005; + +template +static void jama_compute_roots(const NT *begin, const NT *end, NT lb, +NT ub, std::vector &roots) +{ + int degree= end-begin-1; + TNT::Array2D arr(degree, degree, 0.0); + for (int i=0; i< degree; ++i) { + arr[0][i]=-begin[degree-i-1]/begin[degree]; + } + for (int i=0; i+1< degree; ++i) { + arr[i+1][i]=1; + } + + JAMA::Eigenvalue ev(arr); + TNT::Array1D real, imag; + ev.getImagEigenvalues(imag); + ev.getRealEigenvalues(real); + CGAL_Polynomial_assertion(imag.dim1()== real.dim1()); + + /*NT tol; + if (CLEAN) tol=.00005; + else tol=0;*/ + + for (int i=0; i< real.dim1(); ++i) { + if (root_is_good(real[i], imag[i], lb-tol, ub)) { + roots.push_back(real[i]/*polish_root(begin, end, real[i])*/); + } else { + } + } + std::sort(roots.begin(), roots.end(), std::greater()); + if (CLEAN) filter_roots(begin, end, lb, roots); +} + +#endif + + +CGAL_INLINE_FUNCTION +void jama_polynomial_compute_roots(const double *begin, const double *end, +double lb, double ub, +std::vector &roots) +{ + std::ptrdiff_t degree= end-begin-1; + switch( degree) { + case -1: + case 0: + break; + case 1: + compute_linear_roots(begin,end, lb, ub, roots); + break; + case 2: + compute_quadratic_roots(begin, end, lb, ub, roots); + break; + default: +#ifdef CGAL_HAVE_TNT + jama_compute_roots(begin, end, lb, ub, roots); +#else + CGAL_error(); +#endif + //jama_compute_roots(begin, end, lb, ub, roots); + } +} + + +CGAL_INLINE_FUNCTION +void jama_polynomial_compute_cleaned_roots(const double *begin, const double *end, +double lb, double ub, +std::vector &roots) +{ + std::ptrdiff_t degree= end-begin-1; + switch( degree) { + case -1: + case 0: + break; + case 1: + compute_linear_cleaned_roots(begin,end, lb, ub, roots); + break; + case 2: + compute_quadratic_cleaned_roots(begin, end, lb, ub, roots); + break; + default: +#ifdef CGAL_HAVE_TNT + jama_compute_roots(begin, end, lb, ub, roots); +#else + CGAL_error(); +#endif + } +} + + +} } } //namespace CGAL::POLYNOMIAL::internal diff --git a/Kinetic_data_structures/include/CGAL/Polynomial/internal/Turkowski_numeric_solvers_impl.h b/Kinetic_data_structures/include/CGAL/Polynomial/internal/Turkowski_numeric_solvers_impl.h new file mode 100644 index 00000000000..d79a15f981f --- /dev/null +++ b/Kinetic_data_structures/include/CGAL/Polynomial/internal/Turkowski_numeric_solvers_impl.h @@ -0,0 +1,467 @@ +// Copyright (c) 2005 Stanford University (USA). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Daniel Russel + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include + +/*#ifdef _MSC_VER +#pragma warning(disable:1572) +#endif*/ + + +//#include "numeric_solvers_support.C" + +// Taken from http://www.worldserver.com/turk/opensource/ + +/* Copyright (C) 1978-1999 Ken Turkowski. + * + * All rights reserved. + * + * Warranty Information + * Even though I have reviewed this software, I make no warranty + * or representation, either express or implied, with respect to this + * software, its quality, accuracy, merchantability, or fitness for a + * particular purpose. As a result, this software is provided "as is," + * and you, its user, are assuming the entire risk as to its quality + * and accuracy. + * + * This code may be used and freely distributed as long as it includes + * this copyright notice and the above warranty information. + */ + +#include +#include + +namespace CGAL { namespace POLYNOMIAL { namespace internal { + +# define FLOAT double + +static const unsigned int MAXN= 55; +//# define PARAMFLOAT double_t + +/******************************************************************************* + * FindCubicRoots + * + * Solve: + * coeff[3] * x^3 + coeff[2] * x^2 + coeff[1] * x + coeff[0] = 0 + * + * returns: + * 3 - 3 real roots + * 1 - 1 real root (2 complex conjugate) + *******************************************************************************/ + +static long +FindCubicRoots(const FLOAT coeff[4], FLOAT x[3]) +{ + FLOAT a1 = coeff[2] / coeff[3]; + FLOAT a2 = coeff[1] / coeff[3]; + FLOAT a3 = coeff[0] / coeff[3]; + + double Q = (a1 * a1 - 3 * a2) / 9; + double R = (2 * a1 * a1 * a1 - 9 * a1 * a2 + 27 * a3) / 54; + double Qcubed = Q * Q * Q; + double d = Qcubed - R * R; + + /* Three real roots */ + if (d >= 0) { + double theta = std::acos(R / std::sqrt(Qcubed)); + double sqrtQ = std::sqrt(Q); + x[0] = -2 * sqrtQ * std::cos( theta / 3) - a1 / 3; + x[1] = -2 * sqrtQ * std::cos((theta + 2 * CGAL_PI) / 3) - a1 / 3; + x[2] = -2 * sqrtQ * std::cos((theta + 4 * CGAL_PI) / 3) - a1 / 3; + return (3); + } + + /* One real root */ + else { + double e = std::pow(std::sqrt(-d) + ::CGAL::abs(R), 1. / 3.); + if (R > 0) + e = -e; + x[0] = (e + Q / e) - a1 / 3.; + return (1); + } +} + + +/******************************************************************************* + * FindPolynomialRoots + * + * The Bairstow and Newton correction formulae are used for a simultaneous + * linear and quadratic iterated synthetic division. The coefficients of + * a polynomial of degree n are given as a[i] (i=0,i,..., n) where a[0] is + * the constant term. The coefficients are scaled by dividing them by + * their geometric mean. The Bairstow or Newton iteration method will + * nearly always converge to the number of figures carried, fig, either to + * root values or to their reciprocals. If the simultaneous Newton and + * Bairstow iteration fails to converge on root values or their + * reciprocals in maxiter iterations, the convergence requirement will be + * successively reduced by one decimal figure. This program anticipates + * and protects against loss of significance in the quadratic synthetic + * division. (Refer to "On Programming the Numerical Solution of + * Polynomial Equations," by K. W. Ellenberger, Commun. ACM 3 (Dec. 1960), + * 644-647.) The real and imaginary part of each root is stated as u[i] + * and v[i], respectively, together with the corresponding constant, + * conv[i], used in the convergence test. This program has been used + * successfully for over a year on the Bendix G15-D (Intercard System) and + * has recently been coded for the IBM 709 (Fortran system). + * + * ACM algorithm #30 - Numerical Solution of the Polynomial Equation + * K. W. Ellenberger + * Missle Division, North American Aviation, Downey, California + * Converted to C, modified, optimized, and structured by + * Ken Turkowski + * CADLINC, Inc., Palo Alto, California + *******************************************************************************/ + +static void +FindPolynomialRoots( + const FLOAT *a, /* Coefficients */ + FLOAT *u, /* Real component of each root */ + FLOAT *v, /* Imaginary component of each root */ + FLOAT *conv, /* Convergence constant associated with each root */ + register long n, /* Degree of polynomial (order-1) */ + long maxiter, /* Maximum number of iterations */ + long fig /* The number of decimal figures to be computed */ + ) +{ + int number_of_ITERATE=0; + int number_of_INIT=0; + CGAL_precondition(static_cast(fig) < MAXN); + int i; + register int j; + FLOAT h[MAXN + 3], b[MAXN + 3], c[MAXN + 3], d[MAXN + 3], e[MAXN + 3]; + /* [-2 : n] */ + FLOAT K, ps, qs, pt, qt, s, rev, r= std::numeric_limits::infinity(); + int t; + FLOAT p=std::numeric_limits::infinity(), q=std::numeric_limits::infinity(); + + /* Zero elements with negative indices */ + b[2 + -1] = b[2 + -2] = + c[2 + -1] = c[2 + -2] = + d[2 + -1] = d[2 + -2] = + e[2 + -1] = e[2 + -2] = + h[2 + -1] = h[2 + -2] = 0.0; + + /* Copy polynomial coefficients to working storage */ + for (j = n; j >= 0; j--) + h[2 + j] = *a++; /* Note reversal of coefficients */ + + t = 1; + K = std::pow(10.0, (double)(fig)); /* Relative accuracy */ + + for (; h[2 + n] == 0.0; n--) { /* Look for zero high-order coeff. */ + *u++ = 0.0; + *v++ = 0.0; + *conv++ = K; + } + + INIT: + ++number_of_INIT; + if (number_of_INIT > 1000) { + std::cerr << "Too many INITs" << std::flush; + return; + } + + if (n == 0) + return; + + ps = qs = pt = qt = s = 0.0; + rev = 1.0; + K = std::pow(10.0, (double)(fig)); + + if (n == 1) { + r = -h[2 + 1] / h[2 + 0]; + goto LINEAR; + } + + for (j = n; j >= 0; j--) /* Find geometric mean of coeff's */ + if (h[2 + j] != 0.0) + s += std::log( ::CGAL::abs(h[2 + j])); + s = std::exp(s / (n + 1)); + + for (j = n; j >= 0; j--) /* Normalize coeff's by mean */ + h[2 + j] /= s; + + if ( ::CGAL::abs(h[2 + 1] / h[2 + 0]) < ::CGAL::abs(h[2 + n - 1] / h[2 + n])) { + REVERSE: + t = -t; + for (j = (n - 1) / 2; j >= 0; j--) { + s = h[2 + j]; + h[2 + j] = h[2 + n - j]; + h[2 + n - j] = s; + } + } + if (qs != 0.0) { + p = ps; + q = qs; + } + else { + if (h[2 + n - 2] == 0.0) { + q = 1.0; + p = -2.0; + } + else { + q = h[2 + n] / h[2 + n - 2]; + p = (h[2 + n - 1] - q * h[2 + n - 3]) / h[2 + n - 2]; + } + if (n == 2) + goto QADRTIC; + r = 0.0; + } + ITERATE: + ++number_of_ITERATE; + if (number_of_ITERATE > 1000) { + std::cerr << "Too many ITERATEs" << std::flush; + return; + } + for (i = maxiter; i > 0; i--) { + + for (j = 0; j <= n; j++) { /* BAIRSTOW */ + b[2 + j] = h[2 + j] - p * b[2 + j - 1] - q * b[2 + j - 2]; + c[2 + j] = b[2 + j] - p * c[2 + j - 1] - q * c[2 + j - 2]; + } + if ((h[2 + n - 1] != 0.0) && (b[2 + n - 1] != 0.0)) { + if ( ::CGAL::abs(h[2 + n - 1] / b[2 + n - 1]) >= K) { + b[2 + n] = h[2 + n] - q * b[2 + n - 2]; + } + if (b[2 + n] == 0.0) + goto QADRTIC; + if (K < ::CGAL::abs(h[2 + n] / b[2 + n])) + goto QADRTIC; + } + + for (j = 0; j <= n; j++) { /* NEWTON */ + /* Calculate polynomial at r */ + d[2 + j] = h[2 + j] + r * d[2 + j - 1]; + /* Calculate derivative at r */ + e[2 + j] = d[2 + j] + r * e[2 + j - 1]; + } + if (d[2 + n] == 0.0) + goto LINEAR; + if (K < ::CGAL::abs(h[2 + n] / d[2 + n])) + goto LINEAR; + + c[2 + n - 1] = -p * c[2 + n - 2] - q * c[2 + n - 3]; + s = c[2 + n - 2] * c[2 + n - 2] - c[2 + n - 1] * c[2 + n - 3]; + if (s == 0.0) { + p -= 2.0; + q *= (q + 1.0); + } + else { + p += (b[2 + n - 1] * c[2 + n - 2] - b[2 + n] * c[2 + n - 3]) / s; + q += (-b[2 + n - 1] * c[2 + n - 1] + b[2 + n] * c[2 + n - 2]) / s; + } + if (e[2 + n - 1] == 0.0) + r -= 1.0; /* Minimum step */ + else + r -= d[2 + n] / e[2 + n - 1]; /* Newton's iteration */ + } + ps = pt; + qs = qt; + pt = p; + qt = q; + if (rev < 0.0) + K /= 10.0; + rev = -rev; + goto REVERSE; + + LINEAR: + if (t < 0) + r = 1.0 / r; + n--; + *u++ = r; + *v++ = 0.0; + *conv++ = K; + + for (j = n; j >= 0; j--) { /* Polynomial deflation by lin-nomial */ + if ((d[2 + j] != 0.0) && ( ::CGAL::abs(h[2 + j] / d[2 + j]) < K)) + h[2 + j] = d[2 + j]; + else + h[2 + j] = 0.0; + } + + if (n == 0) + return; + goto ITERATE; + + QADRTIC: + if (t < 0) { + p /= q; + q = 1.0 / q; + } + n -= 2; + + if (0.0 < (q - (p * p / 4.0))) { /* Two complex roots */ + *(u + 1) = *u = -p / 2.0; + u += 2; + s = sqrt(q - (p * p / 4.0)); + *v++ = s; + *v++ = -s; + } /* Two real roots */ + else { + s = std::sqrt(((p * p / 4.0)) - q); + if (p < 0.0) + *u++ = -p / 2.0 + s; + else + *u++ = -p / 2.0 - s; + *u = q / u[-1]; + ++u; // moved from lhs of before + *v++ = 0.0; + *v++ = 0.0; + } + *conv++ = K; + *conv++ = K; + + for (j = n; j >= 0; j--) { /* Polynomial deflation by quadratic */ + if ((b[2 + j] != 0.0) && ( ::CGAL::abs(h[2 + j] / b[2 + j]) < K)) + h[2 + j] = b[2 + j]; + else + h[2 + j] = 0.0; + } + goto INIT; +} + + +#undef MAXN + +template +static void Turkowski_polynomial_compute_roots_t(const double *begin, + const double *end, + double lb, double ub, + std::vector &roots) +{ + std::size_t numc= end-begin; + double rp[MAXN]; + double cp[MAXN]; + double cc[MAXN]; + + /*for (unsigned int i=0; i< numc; ++i){ + rp[i]= std::numeric_limits::infinity(); + }*/ + + for (unsigned int i=0; i< MAXN; ++i){ + cc[i]=std::numeric_limits::infinity(); + rp[i]=std::numeric_limits::infinity(); + cc[i]=std::numeric_limits::infinity(); + } + + FindPolynomialRoots(begin, rp, cp, cc, static_cast(numc)-1, 10*static_cast(numc), 40); + + /*if (CLEAN) { + lb-= .000005; + }*/ + double last= -std::numeric_limits::infinity(); + for (std::size_t i=0; i< numc-1; ++i) { + /* std::cout << "Trying " << rp[i] << "+" << std::setprecision(10) << cp[i] << "i " + << cc[i] << "\n";*/ + if (cc[i] > 10000 && root_is_good(rp[i], cp[i], lb, ub)) { + roots.push_back(rp[i]); + /*std::cout << "Good was " << rp[i] << "+" <()); + + if (CLEAN) filter_solver_roots(begin, end, lb, ub, last, roots); +} + +CGAL_INLINE_FUNCTION +void Turkowski_polynomial_compute_roots(const double *begin, const double *end, + double lb, double ub, + std::vector &roots) +{ + + std::ptrdiff_t degree= end-begin-1; + switch( degree) { + case -1: + case 0: + break; + case 1: + compute_linear_roots(begin,end, lb, ub, roots); + break; + case 2: + compute_quadratic_roots(begin, end, lb, ub, roots); + break; + case 3: + { + double rd[3]; + int numr= FindCubicRoots(begin, rd); + for (int i=numr-1; i>=0; --i) { + if (rd[i] >= lb && rd[i] < ub) roots.push_back(rd[i]); + } + std::sort(roots.begin(), roots.end(), std::greater()); + break; + } + default: + Turkowski_polynomial_compute_roots_t(begin, end, lb, ub, roots); + + } + +} + +CGAL_INLINE_FUNCTION +void Turkowski_polynomial_compute_cleaned_roots(const double *begin, const double *end, + double lb, double ub, + std::vector &roots) +{ + std::ptrdiff_t degree= end-begin-1; + switch( degree) { + case -1: + case 0: + break; + case 1: + compute_linear_cleaned_roots(begin,end, lb, ub, roots); + break; + case 2: + compute_quadratic_cleaned_roots(begin, end, lb, ub, roots); + break; + case 3: + { + double rd[3]; + int numr= FindCubicRoots(begin, rd); + double last=-std::numeric_limits::infinity(); + for (int i=numr-1; i>=0; --i) { + if (rd[i]< ub && rd[i] >= lb) roots.push_back(rd[i]); + if (rd[i] < lb && rd[i] > last){ + last=rd[i]; + } + } + std::sort(roots.begin(), roots.end(), std::greater()); + filter_solver_roots(begin, end, lb, ub, last, roots); + break; + } + default: + Turkowski_polynomial_compute_roots_t(begin, end, lb, ub, roots); + } +} + + +} } } //namespace CGAL::POLYNOMIAL::internal diff --git a/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers.h b/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers.h index 6c805fd42a5..8c02d9585ff 100644 --- a/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers.h +++ b/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers.h @@ -109,4 +109,10 @@ struct Turkowski_cleaned_numeric_solver }; } } } //namespace CGAL::POLYNOMIAL::internal + +#ifdef CGAL_HEADER_ONLY +#include +#include +#endif // CGAL_HEADER_ONLY + #endif diff --git a/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers_impl.h b/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers_impl.h new file mode 100644 index 00000000000..198843140db --- /dev/null +++ b/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers_impl.h @@ -0,0 +1,138 @@ +// Copyright (c) 2005 Stanford University (USA). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Daniel Russel + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include + +#ifdef CGAL_HAVE_TNT +#include +#include +#include +#endif + +#include +#include +#include + +//#include + +namespace CGAL { namespace POLYNOMIAL { namespace internal { +#if CGAL_HAVE_TNT +//static const double max_error_value =0.00005; + +template +static void jama_compute_roots(const NT *begin, const NT *end, NT lb, +NT ub, std::vector &roots) +{ + int degree= end-begin-1; + TNT::Array2D arr(degree, degree, 0.0); + for (int i=0; i< degree; ++i) { + arr[0][i]=-begin[degree-i-1]/begin[degree]; + } + for (int i=0; i+1< degree; ++i) { + arr[i+1][i]=1; + } + + JAMA::Eigenvalue ev(arr); + TNT::Array1D real, imag; + ev.getImagEigenvalues(imag); + ev.getRealEigenvalues(real); + CGAL_Polynomial_assertion(imag.dim1()== real.dim1()); + + /*NT tol; + if (CLEAN) tol=.00005; + else tol=0;*/ + + for (int i=0; i< real.dim1(); ++i) { + if (root_is_good(real[i], imag[i], lb-tol, ub)) { + roots.push_back(real[i]/*polish_root(begin, end, real[i])*/); + } else { + } + } + std::sort(roots.begin(), roots.end(), std::greater()); + if (CLEAN) filter_roots(begin, end, lb, roots); +} + +#endif + + +CGAL_INLINE_FUNCTION +void jama_polynomial_compute_roots(const double *begin, const double *end, +double lb, double ub, +std::vector &roots) +{ +#ifdef CGAL_HEADER_ONLY + int i = 0; +#endif + std::ptrdiff_t degree= endss-begin-1; + switch( degree) { + case -1: + case 0: + break; + case 1: + compute_linear_roots(begin,end, lb, ub, roots); + break; + case 2: + compute_quadratic_roots(begin, end, lb, ub, roots); + break; + default: +#ifdef CGAL_HAVE_TNT + jama_compute_roots(begin, end, lb, ub, roots); +#else + CGAL_error(); +#endif + //jama_compute_roots(begin, end, lb, ub, roots); + } +} + + +CGAL_INLINE_FUNCTION +void jama_polynomial_compute_cleaned_roots(const double *begin, const double *end, +double lb, double ub, +std::vector &roots) +{ + std::ptrdiff_t degree= end-begin-1; + switch( degree) { + case -1: + case 0: + break; + case 1: + compute_linear_cleaned_roots(begin,end, lb, ub, roots); + break; + case 2: + compute_quadratic_cleaned_roots(begin, end, lb, ub, roots); + break; + default: +#ifdef CGAL_HAVE_TNT + jama_compute_roots(begin, end, lb, ub, roots); +#else + CGAL_error(); +#endif + } +} + + +} } } //namespace CGAL::POLYNOMIAL::internal diff --git a/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers_support.h b/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers_support.h index b5e4e03e049..61de4d6da1a 100644 --- a/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers_support.h +++ b/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers_support.h @@ -57,4 +57,9 @@ void filter_solver_roots(const double *begin, const double *end, std::vector &roots); } } } //namespace CGAL::POLYNOMIAL::internal + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif diff --git a/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers_support_impl.h b/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers_support_impl.h new file mode 100644 index 00000000000..516bd529e47 --- /dev/null +++ b/Kinetic_data_structures/include/CGAL/Polynomial/internal/numeric_solvers_support_impl.h @@ -0,0 +1,276 @@ +// Copyright (c) 2005 Stanford University (USA). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Daniel Russel + + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include + +#include +#include +#include + +/*#ifdef _MSC_VER +#pragma warning(disable:1572) +#endif*/ + +namespace CGAL { namespace POLYNOMIAL { namespace internal { + +static double max_error_value=.00005; + +namespace { +template +inline void compute_quadratic_roots_t(const NT *begin, const NT * /*end*/, NT lb, NT ub, +std::vector &roots) +{ + NT max_error=0; + if (CLEAN) max_error=max_error_value; + CGAL_Polynomial_assertion(begin[2] != 0); + + NT desc= begin[1]*begin[1]-4*begin[0]*begin[2]; + if (desc <= 0) return; + + NT ur= (-begin[1]+sqrt(desc))/(2*begin[2]); + NT lr= (-begin[1]-sqrt(desc))/(2*begin[2]); + if (begin[2]< 0) std::swap(lr, ur); + if (lr > lb-max_error && lr < ub) { + roots.push_back(ur); + if (lr > lb-max_error && lr < ub && (!CLEAN || /*lr > lb+max_error ||*/ begin[2] >0)){ + roots.push_back(lr); + } + } else { + // only upper + if (ur > lb-max_error && ur < ub && (!CLEAN || /*ur > lb+max_error ||*/ begin[2] <0)){ + roots.push_back(ur); + } + + + } + + // drop even roots + /*if (ur >lb-max_error && ur < ub){ + if (!CLEAN || sign(begin[2]) != POSITIVE){ + roots.push_back(ur); + if (lr >lb-max_error && lr < ub){ + roots.push_back(lr); + } + } + } else { + if (lr > lb-max_error && lr &roots) +{ + return compute_quadratic_roots_t(begin, end, lb, ub, roots); +} + +CGAL_INLINE_FUNCTION +void compute_quadratic_cleaned_roots(const double *begin, const double *end, +double lb, double ub, std::vector &roots) +{ + return compute_quadratic_roots_t(begin, end, lb, ub, roots); +} + +namespace { +template +inline void compute_linear_roots_t(const NT *begin, const NT *, + NT lb, NT ub, + std::vector &roots) +{ + if (CLEAN && begin[1]>0 ) return; + //NT max_error=0; + //if (CLEAN) max_error=max_error_value; + NT r= -CGAL::to_double(begin[0]/begin[1]); + if ((CLEAN || r > lb) && r < ub) { + roots.push_back(r); + } +} +} + +CGAL_INLINE_FUNCTION +void compute_linear_roots(const double *begin, const double *end, +double lb, double ub, std::vector &roots) +{ + return compute_linear_roots_t(begin, end, lb, ub, roots); +} + +CGAL_INLINE_FUNCTION +void compute_linear_cleaned_roots(const double *begin, const double *end, + double lb, double ub, std::vector &roots) +{ + return compute_linear_roots_t(begin, end, lb, ub, roots); +} + + +namespace { +template + inline void filter_roots_t(const NT *begin, const NT *end, + NT lb, NT ub, NT last_root, std::vector &roots) +{ +// if we are not close to the current time, then we are fine + if (roots.empty()) return; + //if (roots.back() > lb+ .0005) return; + + //double eps= .0005; + /*double last_root=-std::numeric_limits::infinity(); + + while (roots.back() < lb) { + last_root= roots.back(); + roots.pop_back(); + }*/ + //if (roots.back() > lb+eps) return; + + //typedef CGAL_POLYNOMIAL_NS::Polynomial Fn; + + typedef CGAL_POLYNOMIAL_NS::Interval_polynomial IFn; + typedef CGAL_POLYNOMIAL_NS::internal::Derivative Diff; + typedef typename IFn::NT INT; + + + /*bool popped=false;*/ + // if the last valid root is closer than last, consider it as doubtful instead + if (lb-last_root > roots.back()-lb) { + last_root= roots.back(); + roots.pop_back(); + /*popped=true;*/ + } /*else { + last_root=lb; + }*/ + + INT vi; + if (last_root== -std::numeric_limits::infinity()){ + if ((end-begin)%2==1) { + vi= std::numeric_limits::infinity(); + } else { + vi = -*(end-1); + } + } else { + IFn fi(begin, end); + if (roots.empty()) { + Interval_arithmetic_guard guard; + if (ub== std::numeric_limits::infinity()) { + vi = 10*lb + 1000; + } else { + vi = fi((INT(lb)+INT(ub))/2.0); + } + } else { + Interval_arithmetic_guard guard; + vi = fi((INT(last_root)+INT(roots.back()))/2.0); + } + } + + if (vi.inf() > 0) { + return; + } else if (vi.sup() < 0){ + roots.push_back(last_root); + + /*if (!popped) { + IFn f(begin, end); + std::cout << "Adding last due to sign of " << vi << std::endl; + std::cout << "last " << last_root << " lb " << lb << " poly " << f << std::endl; + }*/ + return; + } + Interval_arithmetic_guard guard; + Diff dx; + IFn f(begin, end); + IFn d= dx(f); + + INT dv= d(roots.back()); + // switch + //while (sign(d(roots.back().representation()))== ZERO) d= dx_(d); + while (dv.inf() <= 0 && dv.sup() >= 0) { + d= dx(d); + dv= d(roots.back()); + } + // switch + //if (sign(d(roots.back().representation()))==POSITIVE){ + if (dv.sup() < 0) { + roots.push_back(last_root); + /*if (!popped) { + IFn f(begin, end); + std::cout << "Adding last due to deriv of " << vi << std::endl; + std::cout << "last " << last_root << " lb " << lb << " poly " << f << std::endl; + }*/ + } +} +} + +CGAL_INLINE_FUNCTION +void filter_solver_roots(const double *begin, const double *end, + double lb, double ub, double last, + std::vector &roots) +{ + filter_roots_t(begin, end, lb, ub, last, roots); +} + + +/*void polynomial_compute_roots(const double *begin, const double *end, double lb, + double ub, std::vector &roots){ +#ifdef POLYNOMIAL_USE_GSL + gsl_polynomial_compute_roots(begin, end, lb, ub, roots); +#else + jama_polynomial_compute_roots(begin, end, lb, ub, roots); +#endif +} + +void polynomial_compute_cleaned_roots(const double *begin, const double *end, double lb, + double ub, std::vector &roots){ +#ifdef POLYNOMIAL_USE_GSL +gsl_polynomial_compute_cleaned_roots(begin, end, lb, ub, roots); +#else +jama_polynomial_compute_cleaned_roots(begin, end, lb, ub, roots); +#endif +}*/ + +CGAL_INLINE_FUNCTION +double evaluate_polynomial(const double *b, const double *e, double t) +{ +#ifdef POLYNOMIAL_USE_GSL + return gsl_evaluate_polynomial(b, e, t); +#else + if (b==e) return 0.0; + + const double *rit=e-1; + double result = *rit; + --rit; + for (; rit != b-1; --rit) { + result *= t; + result += (*rit); + } + return result; +#endif +} + + +} } } //namespace CGAL::POLYNOMIAL::internal diff --git a/Kinetic_data_structures/include/CGAL/Tools/Log.h b/Kinetic_data_structures/include/CGAL/Tools/Log.h index 60bbb8e8028..78aaef503e4 100644 --- a/Kinetic_data_structures/include/CGAL/Tools/Log.h +++ b/Kinetic_data_structures/include/CGAL/Tools/Log.h @@ -59,7 +59,25 @@ private: output_maple_=true; } }; + +#ifdef CGAL_HEADER_ONLY + + static State& get_static_state() + { + static State state_; + return state_; + } + +#else // CGAL_HEADER_ONLY + CGAL_EXPORT static State state_; + static State& get_static_state() + { + return state_; + } + +#endif // CGAL_HEADER_ONLY + public: // The different types of logs supported /* MAPLE is a log which should be able to be fed directly in to @@ -67,42 +85,42 @@ public: when evaluated. */ - static Level level() {return state_.level_;} - static void set_level(Level l) {state_.level_=l;} + static Level level() {return get_static_state().level_;} + static void set_level(Level l) {get_static_state().level_=l;} static std::ostream &stream(Level l) { if (is_output(l)) { - if (state_.target_== COUT) { + if (get_static_state().target_== COUT) { return std::cout; } else { - return state_.fstream_; + return get_static_state().fstream_; } } else { - return state_.null_; + return get_static_state().null_; } } static bool is_output(Level l) { return l <= level(); } - static Target target() {return state_.target_;} - static CGAL_SET(Target, target, state_.target_=k); - static CGAL_SET(std::string, filename, state_.fstream_.open(k.c_str())); + static Target target() {return get_static_state().target_;} + static CGAL_SET(Target, target, get_static_state().target_=k); + static CGAL_SET(std::string, filename, get_static_state().fstream_.open(k.c_str())); - static bool is_output_maple(){return state_.output_maple_;} + static bool is_output_maple(){return get_static_state().output_maple_;} static void set_output_maple(bool b) { - state_.output_maple_=b; + get_static_state().output_maple_=b; } std::ofstream &maple_stream() { - if (!state_.maple_is_open_) { - state_.maple_is_open_=true; - state_.maple_.open("maple.log"); + if (!get_static_state().maple_is_open_) { + get_static_state().maple_is_open_=true; + get_static_state().maple_.open("maple.log"); } - return state_.maple_; + return get_static_state().maple_; } private: Log() { @@ -163,6 +181,8 @@ struct Set_log_state{ # pragma warning(pop) #endif +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif - - diff --git a/Kinetic_data_structures/include/CGAL/Tools/Log_impl.h b/Kinetic_data_structures/include/CGAL/Tools/Log_impl.h new file mode 100644 index 00000000000..566694f1c15 --- /dev/null +++ b/Kinetic_data_structures/include/CGAL/Tools/Log_impl.h @@ -0,0 +1,32 @@ +// Copyright (c) 2005 Stanford University (USA). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Daniel Russel + +#ifndef CGAL_HEADER_ONLY + +#if defined(BOOST_MSVC) +# pragma warning(disable:4251) +#endif + +namespace CGAL { + +Log::State Log::state_; +} //namespace CGAL + +#endif // CGAL_HEADER_ONLY diff --git a/Kinetic_data_structures/src/CGAL/JAMA_numeric_solver.cpp b/Kinetic_data_structures/src/CGAL/JAMA_numeric_solver.cpp index f602104eb31..a22ab9b0cc5 100644 --- a/Kinetic_data_structures/src/CGAL/JAMA_numeric_solver.cpp +++ b/Kinetic_data_structures/src/CGAL/JAMA_numeric_solver.cpp @@ -18,111 +18,9 @@ // // Author(s) : Daniel Russel -#include +#ifndef CGAL_HEADER_ONLY + #include +#include -#ifdef CGAL_HAVE_TNT -#include -#include -#include -#endif - -#include -#include -#include - -//#include - -namespace CGAL { namespace POLYNOMIAL { namespace internal { -#if CGAL_HAVE_TNT -//static const double max_error_value =0.00005; - -template -static void jama_compute_roots(const NT *begin, const NT *end, NT lb, -NT ub, std::vector &roots) -{ - int degree= end-begin-1; - TNT::Array2D arr(degree, degree, 0.0); - for (int i=0; i< degree; ++i) { - arr[0][i]=-begin[degree-i-1]/begin[degree]; - } - for (int i=0; i+1< degree; ++i) { - arr[i+1][i]=1; - } - - JAMA::Eigenvalue ev(arr); - TNT::Array1D real, imag; - ev.getImagEigenvalues(imag); - ev.getRealEigenvalues(real); - CGAL_Polynomial_assertion(imag.dim1()== real.dim1()); - - /*NT tol; - if (CLEAN) tol=.00005; - else tol=0;*/ - - for (int i=0; i< real.dim1(); ++i) { - if (root_is_good(real[i], imag[i], lb-tol, ub)) { - roots.push_back(real[i]/*polish_root(begin, end, real[i])*/); - } else { - } - } - std::sort(roots.begin(), roots.end(), std::greater()); - if (CLEAN) filter_roots(begin, end, lb, roots); -} - -#endif - - - -void jama_polynomial_compute_roots(const double *begin, const double *end, -double lb, double ub, -std::vector &roots) -{ - std::ptrdiff_t degree= end-begin-1; - switch( degree) { - case -1: - case 0: - break; - case 1: - compute_linear_roots(begin,end, lb, ub, roots); - break; - case 2: - compute_quadratic_roots(begin, end, lb, ub, roots); - break; - default: -#ifdef CGAL_HAVE_TNT - jama_compute_roots(begin, end, lb, ub, roots); -#else - CGAL_error(); -#endif - //jama_compute_roots(begin, end, lb, ub, roots); - } -} - - -void jama_polynomial_compute_cleaned_roots(const double *begin, const double *end, -double lb, double ub, -std::vector &roots) -{ - std::ptrdiff_t degree= end-begin-1; - switch( degree) { - case -1: - case 0: - break; - case 1: - compute_linear_cleaned_roots(begin,end, lb, ub, roots); - break; - case 2: - compute_quadratic_cleaned_roots(begin, end, lb, ub, roots); - break; - default: -#ifdef CGAL_HAVE_TNT - jama_compute_roots(begin, end, lb, ub, roots); -#else - CGAL_error(); -#endif - } -} - - -} } } //namespace CGAL::POLYNOMIAL::internal +#endif \ No newline at end of file diff --git a/Kinetic_data_structures/src/CGAL/KDS_Log.cpp b/Kinetic_data_structures/src/CGAL/KDS_Log.cpp index a2d296c7320..96ebc4338fe 100644 --- a/Kinetic_data_structures/src/CGAL/KDS_Log.cpp +++ b/Kinetic_data_structures/src/CGAL/KDS_Log.cpp @@ -18,30 +18,17 @@ // // Author(s) : Daniel Russel -#include +#ifndef CGAL_HEADER_ONLY -#if defined(BOOST_MSVC) -# pragma warning(disable:4251) -#endif - -#include #include -#include -namespace CGAL { -Log::State Log::state_; -} //namespace CGAL -namespace CGAL { namespace Kinetic { namespace internal { +#include +#include +#include +namespace CGAL { namespace Kinetic { namespace internal { unsigned int function_degeneracies__=0; unsigned int zero_certificates__=0; unsigned int io_errors__=0; unsigned int audit_failures__=0; - - void write_debug_counters(std::ostream &out) { - out << "Degeneracies " << function_degeneracies__ << std::endl; - out << "Zero functions " << zero_certificates__ << std::endl; - if (io_errors__ != 0) out << "I/O errors " << io_errors__ << std::endl; - if (audit_failures__ != 0) out << "Audit failures " << audit_failures__ << std::endl; - } - } } } //namespace CGAL::Kinetic::internal +#endif diff --git a/Kinetic_data_structures/src/CGAL/Turkowski_numeric_solver.cpp b/Kinetic_data_structures/src/CGAL/Turkowski_numeric_solver.cpp index 419aa40bb5e..7c444f6f2ce 100644 --- a/Kinetic_data_structures/src/CGAL/Turkowski_numeric_solver.cpp +++ b/Kinetic_data_structures/src/CGAL/Turkowski_numeric_solver.cpp @@ -18,444 +18,9 @@ // // Author(s) : Daniel Russel -#include +#ifndef CGAL_HEADER_ONLY + #include +#include -/*#ifdef _MSC_VER -#pragma warning(disable:1572) -#endif*/ - - -//#include "numeric_solvers_support.C" - -// Taken from http://www.worldserver.com/turk/opensource/ - -/* Copyright (C) 1978-1999 Ken Turkowski. - * - * All rights reserved. - * - * Warranty Information - * Even though I have reviewed this software, I make no warranty - * or representation, either express or implied, with respect to this - * software, its quality, accuracy, merchantability, or fitness for a - * particular purpose. As a result, this software is provided "as is," - * and you, its user, are assuming the entire risk as to its quality - * and accuracy. - * - * This code may be used and freely distributed as long as it includes - * this copyright notice and the above warranty information. - */ - -#include -#include - -namespace CGAL { namespace POLYNOMIAL { namespace internal { - -# define FLOAT double - -static const unsigned int MAXN= 55; -//# define PARAMFLOAT double_t - -/******************************************************************************* - * FindCubicRoots - * - * Solve: - * coeff[3] * x^3 + coeff[2] * x^2 + coeff[1] * x + coeff[0] = 0 - * - * returns: - * 3 - 3 real roots - * 1 - 1 real root (2 complex conjugate) - *******************************************************************************/ - -static long -FindCubicRoots(const FLOAT coeff[4], FLOAT x[3]) -{ - FLOAT a1 = coeff[2] / coeff[3]; - FLOAT a2 = coeff[1] / coeff[3]; - FLOAT a3 = coeff[0] / coeff[3]; - - double Q = (a1 * a1 - 3 * a2) / 9; - double R = (2 * a1 * a1 * a1 - 9 * a1 * a2 + 27 * a3) / 54; - double Qcubed = Q * Q * Q; - double d = Qcubed - R * R; - - /* Three real roots */ - if (d >= 0) { - double theta = std::acos(R / std::sqrt(Qcubed)); - double sqrtQ = std::sqrt(Q); - x[0] = -2 * sqrtQ * std::cos( theta / 3) - a1 / 3; - x[1] = -2 * sqrtQ * std::cos((theta + 2 * CGAL_PI) / 3) - a1 / 3; - x[2] = -2 * sqrtQ * std::cos((theta + 4 * CGAL_PI) / 3) - a1 / 3; - return (3); - } - - /* One real root */ - else { - double e = std::pow(std::sqrt(-d) + ::CGAL::abs(R), 1. / 3.); - if (R > 0) - e = -e; - x[0] = (e + Q / e) - a1 / 3.; - return (1); - } -} - - -/******************************************************************************* - * FindPolynomialRoots - * - * The Bairstow and Newton correction formulae are used for a simultaneous - * linear and quadratic iterated synthetic division. The coefficients of - * a polynomial of degree n are given as a[i] (i=0,i,..., n) where a[0] is - * the constant term. The coefficients are scaled by dividing them by - * their geometric mean. The Bairstow or Newton iteration method will - * nearly always converge to the number of figures carried, fig, either to - * root values or to their reciprocals. If the simultaneous Newton and - * Bairstow iteration fails to converge on root values or their - * reciprocals in maxiter iterations, the convergence requirement will be - * successively reduced by one decimal figure. This program anticipates - * and protects against loss of significance in the quadratic synthetic - * division. (Refer to "On Programming the Numerical Solution of - * Polynomial Equations," by K. W. Ellenberger, Commun. ACM 3 (Dec. 1960), - * 644-647.) The real and imaginary part of each root is stated as u[i] - * and v[i], respectively, together with the corresponding constant, - * conv[i], used in the convergence test. This program has been used - * successfully for over a year on the Bendix G15-D (Intercard System) and - * has recently been coded for the IBM 709 (Fortran system). - * - * ACM algorithm #30 - Numerical Solution of the Polynomial Equation - * K. W. Ellenberger - * Missle Division, North American Aviation, Downey, California - * Converted to C, modified, optimized, and structured by - * Ken Turkowski - * CADLINC, Inc., Palo Alto, California - *******************************************************************************/ - -static void -FindPolynomialRoots( - const FLOAT *a, /* Coefficients */ - FLOAT *u, /* Real component of each root */ - FLOAT *v, /* Imaginary component of each root */ - FLOAT *conv, /* Convergence constant associated with each root */ - register long n, /* Degree of polynomial (order-1) */ - long maxiter, /* Maximum number of iterations */ - long fig /* The number of decimal figures to be computed */ - ) -{ - int number_of_ITERATE=0; - int number_of_INIT=0; - CGAL_precondition(static_cast(fig) < MAXN); - int i; - register int j; - FLOAT h[MAXN + 3], b[MAXN + 3], c[MAXN + 3], d[MAXN + 3], e[MAXN + 3]; - /* [-2 : n] */ - FLOAT K, ps, qs, pt, qt, s, rev, r= std::numeric_limits::infinity(); - int t; - FLOAT p=std::numeric_limits::infinity(), q=std::numeric_limits::infinity(); - - /* Zero elements with negative indices */ - b[2 + -1] = b[2 + -2] = - c[2 + -1] = c[2 + -2] = - d[2 + -1] = d[2 + -2] = - e[2 + -1] = e[2 + -2] = - h[2 + -1] = h[2 + -2] = 0.0; - - /* Copy polynomial coefficients to working storage */ - for (j = n; j >= 0; j--) - h[2 + j] = *a++; /* Note reversal of coefficients */ - - t = 1; - K = std::pow(10.0, (double)(fig)); /* Relative accuracy */ - - for (; h[2 + n] == 0.0; n--) { /* Look for zero high-order coeff. */ - *u++ = 0.0; - *v++ = 0.0; - *conv++ = K; - } - - INIT: - ++number_of_INIT; - if (number_of_INIT > 1000) { - std::cerr << "Too many INITs" << std::flush; - return; - } - - if (n == 0) - return; - - ps = qs = pt = qt = s = 0.0; - rev = 1.0; - K = std::pow(10.0, (double)(fig)); - - if (n == 1) { - r = -h[2 + 1] / h[2 + 0]; - goto LINEAR; - } - - for (j = n; j >= 0; j--) /* Find geometric mean of coeff's */ - if (h[2 + j] != 0.0) - s += std::log( ::CGAL::abs(h[2 + j])); - s = std::exp(s / (n + 1)); - - for (j = n; j >= 0; j--) /* Normalize coeff's by mean */ - h[2 + j] /= s; - - if ( ::CGAL::abs(h[2 + 1] / h[2 + 0]) < ::CGAL::abs(h[2 + n - 1] / h[2 + n])) { - REVERSE: - t = -t; - for (j = (n - 1) / 2; j >= 0; j--) { - s = h[2 + j]; - h[2 + j] = h[2 + n - j]; - h[2 + n - j] = s; - } - } - if (qs != 0.0) { - p = ps; - q = qs; - } - else { - if (h[2 + n - 2] == 0.0) { - q = 1.0; - p = -2.0; - } - else { - q = h[2 + n] / h[2 + n - 2]; - p = (h[2 + n - 1] - q * h[2 + n - 3]) / h[2 + n - 2]; - } - if (n == 2) - goto QADRTIC; - r = 0.0; - } - ITERATE: - ++number_of_ITERATE; - if (number_of_ITERATE > 1000) { - std::cerr << "Too many ITERATEs" << std::flush; - return; - } - for (i = maxiter; i > 0; i--) { - - for (j = 0; j <= n; j++) { /* BAIRSTOW */ - b[2 + j] = h[2 + j] - p * b[2 + j - 1] - q * b[2 + j - 2]; - c[2 + j] = b[2 + j] - p * c[2 + j - 1] - q * c[2 + j - 2]; - } - if ((h[2 + n - 1] != 0.0) && (b[2 + n - 1] != 0.0)) { - if ( ::CGAL::abs(h[2 + n - 1] / b[2 + n - 1]) >= K) { - b[2 + n] = h[2 + n] - q * b[2 + n - 2]; - } - if (b[2 + n] == 0.0) - goto QADRTIC; - if (K < ::CGAL::abs(h[2 + n] / b[2 + n])) - goto QADRTIC; - } - - for (j = 0; j <= n; j++) { /* NEWTON */ - /* Calculate polynomial at r */ - d[2 + j] = h[2 + j] + r * d[2 + j - 1]; - /* Calculate derivative at r */ - e[2 + j] = d[2 + j] + r * e[2 + j - 1]; - } - if (d[2 + n] == 0.0) - goto LINEAR; - if (K < ::CGAL::abs(h[2 + n] / d[2 + n])) - goto LINEAR; - - c[2 + n - 1] = -p * c[2 + n - 2] - q * c[2 + n - 3]; - s = c[2 + n - 2] * c[2 + n - 2] - c[2 + n - 1] * c[2 + n - 3]; - if (s == 0.0) { - p -= 2.0; - q *= (q + 1.0); - } - else { - p += (b[2 + n - 1] * c[2 + n - 2] - b[2 + n] * c[2 + n - 3]) / s; - q += (-b[2 + n - 1] * c[2 + n - 1] + b[2 + n] * c[2 + n - 2]) / s; - } - if (e[2 + n - 1] == 0.0) - r -= 1.0; /* Minimum step */ - else - r -= d[2 + n] / e[2 + n - 1]; /* Newton's iteration */ - } - ps = pt; - qs = qt; - pt = p; - qt = q; - if (rev < 0.0) - K /= 10.0; - rev = -rev; - goto REVERSE; - - LINEAR: - if (t < 0) - r = 1.0 / r; - n--; - *u++ = r; - *v++ = 0.0; - *conv++ = K; - - for (j = n; j >= 0; j--) { /* Polynomial deflation by lin-nomial */ - if ((d[2 + j] != 0.0) && ( ::CGAL::abs(h[2 + j] / d[2 + j]) < K)) - h[2 + j] = d[2 + j]; - else - h[2 + j] = 0.0; - } - - if (n == 0) - return; - goto ITERATE; - - QADRTIC: - if (t < 0) { - p /= q; - q = 1.0 / q; - } - n -= 2; - - if (0.0 < (q - (p * p / 4.0))) { /* Two complex roots */ - *(u + 1) = *u = -p / 2.0; - u += 2; - s = sqrt(q - (p * p / 4.0)); - *v++ = s; - *v++ = -s; - } /* Two real roots */ - else { - s = std::sqrt(((p * p / 4.0)) - q); - if (p < 0.0) - *u++ = -p / 2.0 + s; - else - *u++ = -p / 2.0 - s; - *u = q / u[-1]; - ++u; // moved from lhs of before - *v++ = 0.0; - *v++ = 0.0; - } - *conv++ = K; - *conv++ = K; - - for (j = n; j >= 0; j--) { /* Polynomial deflation by quadratic */ - if ((b[2 + j] != 0.0) && ( ::CGAL::abs(h[2 + j] / b[2 + j]) < K)) - h[2 + j] = b[2 + j]; - else - h[2 + j] = 0.0; - } - goto INIT; -} - - -#undef MAXN - -template -static void Turkowski_polynomial_compute_roots_t(const double *begin, - const double *end, - double lb, double ub, - std::vector &roots) -{ - std::size_t numc= end-begin; - double rp[MAXN]; - double cp[MAXN]; - double cc[MAXN]; - - /*for (unsigned int i=0; i< numc; ++i){ - rp[i]= std::numeric_limits::infinity(); - }*/ - - for (unsigned int i=0; i< MAXN; ++i){ - cc[i]=std::numeric_limits::infinity(); - rp[i]=std::numeric_limits::infinity(); - cc[i]=std::numeric_limits::infinity(); - } - - FindPolynomialRoots(begin, rp, cp, cc, static_cast(numc)-1, 10*static_cast(numc), 40); - - /*if (CLEAN) { - lb-= .000005; - }*/ - double last= -std::numeric_limits::infinity(); - for (std::size_t i=0; i< numc-1; ++i) { - /* std::cout << "Trying " << rp[i] << "+" << std::setprecision(10) << cp[i] << "i " - << cc[i] << "\n";*/ - if (cc[i] > 10000 && root_is_good(rp[i], cp[i], lb, ub)) { - roots.push_back(rp[i]); - /*std::cout << "Good was " << rp[i] << "+" <()); - - if (CLEAN) filter_solver_roots(begin, end, lb, ub, last, roots); -} - - -void Turkowski_polynomial_compute_roots(const double *begin, const double *end, - double lb, double ub, - std::vector &roots) -{ - - std::ptrdiff_t degree= end-begin-1; - switch( degree) { - case -1: - case 0: - break; - case 1: - compute_linear_roots(begin,end, lb, ub, roots); - break; - case 2: - compute_quadratic_roots(begin, end, lb, ub, roots); - break; - case 3: - { - double rd[3]; - int numr= FindCubicRoots(begin, rd); - for (int i=numr-1; i>=0; --i) { - if (rd[i] >= lb && rd[i] < ub) roots.push_back(rd[i]); - } - std::sort(roots.begin(), roots.end(), std::greater()); - break; - } - default: - Turkowski_polynomial_compute_roots_t(begin, end, lb, ub, roots); - - } - -} - - -void Turkowski_polynomial_compute_cleaned_roots(const double *begin, const double *end, - double lb, double ub, - std::vector &roots) -{ - std::ptrdiff_t degree= end-begin-1; - switch( degree) { - case -1: - case 0: - break; - case 1: - compute_linear_cleaned_roots(begin,end, lb, ub, roots); - break; - case 2: - compute_quadratic_cleaned_roots(begin, end, lb, ub, roots); - break; - case 3: - { - double rd[3]; - int numr= FindCubicRoots(begin, rd); - double last=-std::numeric_limits::infinity(); - for (int i=numr-1; i>=0; --i) { - if (rd[i]< ub && rd[i] >= lb) roots.push_back(rd[i]); - if (rd[i] < lb && rd[i] > last){ - last=rd[i]; - } - } - std::sort(roots.begin(), roots.end(), std::greater()); - filter_solver_roots(begin, end, lb, ub, last, roots); - break; - } - default: - Turkowski_polynomial_compute_roots_t(begin, end, lb, ub, roots); - } -} - - -} } } //namespace CGAL::POLYNOMIAL::internal +#endif \ No newline at end of file diff --git a/Kinetic_data_structures/src/CGAL/numeric_solvers_support.cpp b/Kinetic_data_structures/src/CGAL/numeric_solvers_support.cpp index 1616cb6ee52..5f853cb4eee 100644 --- a/Kinetic_data_structures/src/CGAL/numeric_solvers_support.cpp +++ b/Kinetic_data_structures/src/CGAL/numeric_solvers_support.cpp @@ -19,249 +19,9 @@ // Author(s) : Daniel Russel +#ifndef CGAL_HEADER_ONLY + #include -#include +#include -#include -#include -#include - -/*#ifdef _MSC_VER -#pragma warning(disable:1572) -#endif*/ - -namespace CGAL { namespace POLYNOMIAL { namespace internal { - -static double max_error_value=.00005; - -namespace { -template -inline void compute_quadratic_roots_t(const NT *begin, const NT * /*end*/, NT lb, NT ub, -std::vector &roots) -{ - NT max_error=0; - if (CLEAN) max_error=max_error_value; - CGAL_Polynomial_assertion(begin[2] != 0); - - NT desc= begin[1]*begin[1]-4*begin[0]*begin[2]; - if (desc <= 0) return; - - NT ur= (-begin[1]+sqrt(desc))/(2*begin[2]); - NT lr= (-begin[1]-sqrt(desc))/(2*begin[2]); - if (begin[2]< 0) std::swap(lr, ur); - if (lr > lb-max_error && lr < ub) { - roots.push_back(ur); - if (lr > lb-max_error && lr < ub && (!CLEAN || /*lr > lb+max_error ||*/ begin[2] >0)){ - roots.push_back(lr); - } - } else { - // only upper - if (ur > lb-max_error && ur < ub && (!CLEAN || /*ur > lb+max_error ||*/ begin[2] <0)){ - roots.push_back(ur); - } - - - } - - // drop even roots - /*if (ur >lb-max_error && ur < ub){ - if (!CLEAN || sign(begin[2]) != POSITIVE){ - roots.push_back(ur); - if (lr >lb-max_error && lr < ub){ - roots.push_back(lr); - } - } - } else { - if (lr > lb-max_error && lr &roots) -{ - return compute_quadratic_roots_t(begin, end, lb, ub, roots); -} - - -void compute_quadratic_cleaned_roots(const double *begin, const double *end, -double lb, double ub, std::vector &roots) -{ - return compute_quadratic_roots_t(begin, end, lb, ub, roots); -} - -namespace { -template -inline void compute_linear_roots_t(const NT *begin, const NT *, - NT lb, NT ub, - std::vector &roots) -{ - if (CLEAN && begin[1]>0 ) return; - //NT max_error=0; - //if (CLEAN) max_error=max_error_value; - NT r= -to_double(begin[0]/begin[1]); - if ((CLEAN || r > lb) && r < ub) { - roots.push_back(r); - } -} -} - -void compute_linear_roots(const double *begin, const double *end, -double lb, double ub, std::vector &roots) -{ - return compute_linear_roots_t(begin, end, lb, ub, roots); -} - - -void compute_linear_cleaned_roots(const double *begin, const double *end, - double lb, double ub, std::vector &roots) -{ - return compute_linear_roots_t(begin, end, lb, ub, roots); -} - - -namespace { -template - inline void filter_roots_t(const NT *begin, const NT *end, - NT lb, NT ub, NT last_root, std::vector &roots) -{ -// if we are not close to the current time, then we are fine - if (roots.empty()) return; - //if (roots.back() > lb+ .0005) return; - - //double eps= .0005; - /*double last_root=-std::numeric_limits::infinity(); - - while (roots.back() < lb) { - last_root= roots.back(); - roots.pop_back(); - }*/ - //if (roots.back() > lb+eps) return; - - //typedef CGAL_POLYNOMIAL_NS::Polynomial Fn; - - typedef CGAL_POLYNOMIAL_NS::Interval_polynomial IFn; - typedef CGAL_POLYNOMIAL_NS::internal::Derivative Diff; - typedef typename IFn::NT INT; - - - /*bool popped=false;*/ - // if the last valid root is closer than last, consider it as doubtful instead - if (lb-last_root > roots.back()-lb) { - last_root= roots.back(); - roots.pop_back(); - /*popped=true;*/ - } /*else { - last_root=lb; - }*/ - - INT vi; - if (last_root== -std::numeric_limits::infinity()){ - if ((end-begin)%2==1) { - vi= std::numeric_limits::infinity(); - } else { - vi = -*(end-1); - } - } else { - IFn fi(begin, end); - if (roots.empty()) { - Interval_arithmetic_guard guard; - if (ub== std::numeric_limits::infinity()) { - vi = 10*lb + 1000; - } else { - vi = fi((INT(lb)+INT(ub))/2.0); - } - } else { - Interval_arithmetic_guard guard; - vi = fi((INT(last_root)+INT(roots.back()))/2.0); - } - } - - if (vi.inf() > 0) { - return; - } else if (vi.sup() < 0){ - roots.push_back(last_root); - - /*if (!popped) { - IFn f(begin, end); - std::cout << "Adding last due to sign of " << vi << std::endl; - std::cout << "last " << last_root << " lb " << lb << " poly " << f << std::endl; - }*/ - return; - } - Interval_arithmetic_guard guard; - Diff dx; - IFn f(begin, end); - IFn d= dx(f); - - INT dv= d(roots.back()); - // switch - //while (sign(d(roots.back().representation()))== ZERO) d= dx_(d); - while (dv.inf() <= 0 && dv.sup() >= 0) { - d= dx(d); - dv= d(roots.back()); - } - // switch - //if (sign(d(roots.back().representation()))==POSITIVE){ - if (dv.sup() < 0) { - roots.push_back(last_root); - /*if (!popped) { - IFn f(begin, end); - std::cout << "Adding last due to deriv of " << vi << std::endl; - std::cout << "last " << last_root << " lb " << lb << " poly " << f << std::endl; - }*/ - } -} -} - -void filter_solver_roots(const double *begin, const double *end, - double lb, double ub, double last, - std::vector &roots) -{ - filter_roots_t(begin, end, lb, ub, last, roots); -} - - -/*void polynomial_compute_roots(const double *begin, const double *end, double lb, - double ub, std::vector &roots){ -#ifdef POLYNOMIAL_USE_GSL - gsl_polynomial_compute_roots(begin, end, lb, ub, roots); -#else - jama_polynomial_compute_roots(begin, end, lb, ub, roots); -#endif -} - -void polynomial_compute_cleaned_roots(const double *begin, const double *end, double lb, - double ub, std::vector &roots){ -#ifdef POLYNOMIAL_USE_GSL -gsl_polynomial_compute_cleaned_roots(begin, end, lb, ub, roots); -#else -jama_polynomial_compute_cleaned_roots(begin, end, lb, ub, roots); -#endif -}*/ - -double evaluate_polynomial(const double *b, const double *e, double t) -{ -#ifdef POLYNOMIAL_USE_GSL - return gsl_evaluate_polynomial(b, e, t); -#else - if (b==e) return 0.0; - - const double *rit=e-1; - double result = *rit; - --rit; - for (; rit != b-1; --rit) { - result *= t; - result += (*rit); - } - return result; -#endif -} - - -} } } //namespace CGAL::POLYNOMIAL::internal +#endif \ No newline at end of file diff --git a/Kinetic_data_structures/test/Kinetic_data_structures/Delaunay_triangulation_3.cpp b/Kinetic_data_structures/test/Kinetic_data_structures/Delaunay_triangulation_3.cpp index e4373973c7f..1464fbe1446 100644 --- a/Kinetic_data_structures/test/Kinetic_data_structures/Delaunay_triangulation_3.cpp +++ b/Kinetic_data_structures/test/Kinetic_data_structures/Delaunay_triangulation_3.cpp @@ -111,6 +111,6 @@ int main(int argc, char *argv[]) //std::cout << "Insert " << queue_insertions__ << " and front " << queue_front_insertions__ << std::endl; //std::cout << "Sturm created " << sturm_created__ << " and shrink " << sturm_refined__ << std::endl; - if (CGAL::Kinetic::internal::audit_failures__ != 0 ) return EXIT_FAILURE; + if (CGAL::Kinetic::internal::get_static_audit_failures() != 0 ) return EXIT_FAILURE; else return EXIT_SUCCESS; } diff --git a/Kinetic_data_structures/test/Kinetic_data_structures/exact_kds.cpp b/Kinetic_data_structures/test/Kinetic_data_structures/exact_kds.cpp index 50a99d9cd10..0595ef92dd2 100644 --- a/Kinetic_data_structures/test/Kinetic_data_structures/exact_kds.cpp +++ b/Kinetic_data_structures/test/Kinetic_data_structures/exact_kds.cpp @@ -66,7 +66,7 @@ int main(int argc, char *argv[]) { #endif - if (error || CGAL::Kinetic::internal::audit_failures__ != 0) { + if (error || CGAL::Kinetic::internal::get_static_audit_failures() != 0) { return EXIT_FAILURE; } else { diff --git a/Kinetic_data_structures/test/Kinetic_data_structures/include/sort_test.h b/Kinetic_data_structures/test/Kinetic_data_structures/include/sort_test.h index b373ef99b77..bed6b15515b 100644 --- a/Kinetic_data_structures/test/Kinetic_data_structures/include/sort_test.h +++ b/Kinetic_data_structures/test/Kinetic_data_structures/include/sort_test.h @@ -40,7 +40,7 @@ bool sort_test(Traits &tr, double max_events=std::numeric_limits::infini #ifndef NDEBUG if (tr.simulator_handle()->current_event_number() > max_events){ std::cerr << "ERROR too many events" << std::endl; - ++CGAL::Kinetic::internal::audit_failures__; + ++CGAL::Kinetic::internal::get_static_audit_failures(); std::cerr << *tr.active_points_1_table_handle() << std::endl; } #endif @@ -85,7 +85,7 @@ bool sort_test(Traits &tr, double max_events=std::numeric_limits::infini std::cerr << etag << "Objects " << c->object() << " = " << tr.active_points_1_table_handle()->at(*c).x() << " and " << b->object() << " = " << tr.active_points_1_table_handle()->at(*b).x() << " out of order at end of time " < ("Upper bound"); - if (CGAL::Kinetic::internal::audit_failures__ != 0) return EXIT_FAILURE; + if (CGAL::Kinetic::internal::get_static_audit_failures() != 0) return EXIT_FAILURE; else return EXIT_SUCCESS; //test_sort < CGAL::Kinetic::Exact_simulation_traits_1 > ("Upper bound"); diff --git a/Mesh_2/test/Mesh_2/test_double_map.cpp b/Mesh_2/test/Mesh_2/test_double_map.cpp index 465160ec548..a8e1597cf75 100644 --- a/Mesh_2/test/Mesh_2/test_double_map.cpp +++ b/Mesh_2/test/Mesh_2/test_double_map.cpp @@ -61,7 +61,7 @@ int main(int argc, char** argv) std::cerr << "Filling f with " << number_of_elements << " random integers...\n"; for(unsigned int n=0; n #include "Volume_plane.h" +#include #include "Scene_segmented_image_item.h" diff --git a/Mesh_3/demo/Mesh_3/Volume_planes_plugin.cpp b/Mesh_3/demo/Mesh_3/Volume_planes_plugin.cpp index 37b9a8c1951..f8566061f10 100644 --- a/Mesh_3/demo/Mesh_3/Volume_planes_plugin.cpp +++ b/Mesh_3/demo/Mesh_3/Volume_planes_plugin.cpp @@ -1,8 +1,8 @@ #include "config.h" +#include "Volume_plane.h" #include -#include "Volume_plane.h" #include "Volume_plane_thread.h" #include "Volume_plane_intersection.h" diff --git a/Modular_arithmetic/include/CGAL/Modular_arithmetic/Residue_type.h b/Modular_arithmetic/include/CGAL/Modular_arithmetic/Residue_type.h index 18f05e7a6fd..ed1848cbd0b 100644 --- a/Modular_arithmetic/include/CGAL/Modular_arithmetic/Residue_type.h +++ b/Modular_arithmetic/include/CGAL/Modular_arithmetic/Residue_type.h @@ -60,46 +60,106 @@ public: typedef Residue NT; private: +#ifdef CGAL_HEADER_ONLY + static const double& get_static_CST_CUT() + { + static const double CST_CUT = std::ldexp( 3., 51 ); + return CST_CUT; + } +#else // CGAL_HEADER_ONLY CGAL_EXPORT static const double CST_CUT; + static const double& get_static_CST_CUT() + { return Residue::CST_CUT; } +#endif // CGAL_HEADER_ONLY #ifdef CGAL_HAS_THREADS +#ifdef CGAL_HEADER_ONLY + static boost::thread_specific_ptr& get_static_prime_int_() + { + static boost::thread_specific_ptr prime_int_; + return prime_int_; + } + static boost::thread_specific_ptr& get_static_prime_() + { + static boost::thread_specific_ptr prime_; + return prime_; + } + static boost::thread_specific_ptr& get_static_prime_inv_() + { + static boost::thread_specific_ptr prime_inv_; + return prime_inv_; + } +#else // CGAL_HEADER_ONLY CGAL_EXPORT static boost::thread_specific_ptr prime_int_; CGAL_EXPORT static boost::thread_specific_ptr prime_; CGAL_EXPORT static boost::thread_specific_ptr prime_inv_; + static boost::thread_specific_ptr& get_static_prime_int_() + { return Residue::prime_int_; } + static boost::thread_specific_ptr& get_static_prime_() + { return Residue::prime_; } + static boost::thread_specific_ptr& get_static_prime_inv_() + { return Residue::prime_inv_; } +#endif // CGAL_HEADER_ONLY static void init_class_for_thread(){ - CGAL_precondition(prime_int_.get() == NULL); - CGAL_precondition(prime_.get() == NULL); - CGAL_precondition(prime_inv_.get() == NULL); - prime_int_.reset(new int(67111067)); - prime_.reset(new double(67111067.0)); - prime_inv_.reset(new double(1.0/67111067.0)); + CGAL_precondition(get_static_prime_int_().get() == NULL); + CGAL_precondition(get_static_prime_().get() == NULL); + CGAL_precondition(get_static_prime_inv_().get() == NULL); + get_static_prime_int_().reset(new int(67111067)); + get_static_prime_().reset(new double(67111067.0)); + get_static_prime_inv_().reset(new double(1.0/67111067.0)); } static inline int get_prime_int(){ - if (prime_int_.get() == NULL) + if (get_static_prime_int_().get() == NULL) init_class_for_thread(); - return *prime_int_.get(); + return *get_static_prime_int_().get(); } static inline double get_prime(){ - if (prime_.get() == NULL) + if (get_static_prime_().get() == NULL) init_class_for_thread(); - return *prime_.get(); + return *get_static_prime_().get(); } static inline double get_prime_inv(){ - if (prime_inv_.get() == NULL) + if (get_static_prime_inv_().get() == NULL) init_class_for_thread(); - return *prime_inv_.get(); + return *get_static_prime_inv_().get(); } -#else +#else // CGAL_HAS_THREADS + +#ifdef CGAL_HEADER_ONLY + static int& get_static_prime_int() + { + static int prime_int = 67111067; + return prime_int; + } + static double& get_static_prime() + { + static double prime = 67111067.0; + return prime; + } + static double& get_static_prime_inv() + { + static double prime_inv = 1/67111067.0; + return prime_inv; + } + +#else // CGAL_EXPORT static int prime_int; CGAL_EXPORT static double prime; CGAL_EXPORT static double prime_inv; - static int get_prime_int(){ return prime_int;} - static double get_prime() { return prime;} - static double get_prime_inv(){ return prime_inv;} + static int& get_static_prime_int() + { return Residue::prime_int; } + static double& get_static_prime() + { return Residue::prime; } + static double& get_static_prime_inv() + { return Residue::prime_inv; } +#endif // CGAL_HEADER_ONLY + static int get_prime_int(){ return get_static_prime_int();} + static double get_prime() { return get_static_prime();} + static double get_prime_inv(){ return get_static_prime_inv();} #endif /* Quick integer rounding, valid if a<2^51. for double */ @@ -108,7 +168,7 @@ private: // call CGAL::Protect_FPU_rounding pfr(CGAL_FE_TONEAREST) // before using modular arithmetic CGAL_assertion(FPU_get_cw() == CGAL_FE_TONEAREST); - return ( (a + CST_CUT) - CST_CUT); + return ( (a + get_static_CST_CUT()) - get_static_CST_CUT()); } /* Big modular reduction (e.g. after multiplication) */ @@ -156,8 +216,6 @@ private: /* a^-1, using Bezout (extended Euclidian algorithm). */ static inline double RES_inv (double ri1){ - CGAL_precondition (ri1 != 0.0); - double bi = 0.0; double bi1 = 1.0; double ri = get_prime(); @@ -196,13 +254,13 @@ public: set_current_prime(int p){ int old_prime = get_prime_int(); #ifdef CGAL_HAS_THREADS - *prime_int_.get() = p; - *prime_.get() = double(p); - *prime_inv_.get() = 1.0/double(p); + *get_static_prime_int_().get() = p; + *get_static_prime_().get() = double(p); + *get_static_prime_inv_().get() = 1.0/double(p); #else - prime_int = p; - prime = double(p); - prime_inv = 1.0 / prime; + get_static_prime_int() = p; + get_static_prime() = double(p); + get_static_prime_inv() = 1.0 / prime; #endif return old_prime; } @@ -229,13 +287,8 @@ public: } //! constructor of Residue, from long - Residue (long n) { - x_= RES_soft_reduce (static_cast< double > (n % get_prime_int())); - } - - //! constructor of Residue, from long long - Residue (long long n) { - x_= RES_soft_reduce (static_cast< double > (n % get_prime_int())); + Residue(long n){ + x_= RES_reduce((double)n); } //! Access operator for x, \c const diff --git a/Modular_arithmetic/include/CGAL/primes.h b/Modular_arithmetic/include/CGAL/primes.h index c79c4c08682..e1cf782d907 100644 --- a/Modular_arithmetic/include/CGAL/primes.h +++ b/Modular_arithmetic/include/CGAL/primes.h @@ -63,4 +63,8 @@ int get_next_lower_prime(int current_prime){ } } +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_PRIMES_H diff --git a/Modular_arithmetic/include/CGAL/primes_impl.h b/Modular_arithmetic/include/CGAL/primes_impl.h new file mode 100644 index 00000000000..340b50bb1e4 --- /dev/null +++ b/Modular_arithmetic/include/CGAL/primes_impl.h @@ -0,0 +1,293 @@ +// Copyright (c) Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Michael Hemmer, Alexander Kobel + +#include + +namespace CGAL { +namespace internal { + +const int primes [2000] = { + /* + * Generated in SAGE with: + * + * N = 2000 + * p = 2^26 + * L = [] + * while len(L) < N: + * p = previous_prime(p) + * if GF(p)(2).is_primitive_root(): + * L.append(p) + * k = 8 + * for i in range(N/k): + * print ' ' + ', '.join (str(p) for p in L[k*i:k*(i+1)]) + ',' + */ + 67108859, 67108819, 67108763, 67108757, 67108747, 67108739, 67108709, 67108693, + 67108669, 67108667, 67108661, 67108597, 67108579, 67108507, 67108493, 67108453, + 67108387, 67108373, 67108331, 67108219, 67108187, 67108109, 67108037, 67108003, + 67107941, 67107797, 67107787, 67107773, 67107757, 67107749, 67107707, 67107643, + 67107541, 67107539, 67107533, 67107461, 67107427, 67107389, 67107323, 67107317, + 67107301, 67107253, 67107203, 67107149, 67107043, 67106987, 67106821, 67106813, + 67106797, 67106749, 67106717, 67106693, 67106483, 67106477, 67106357, 67106339, + 67106323, 67106243, 67106213, 67106189, 67106107, 67106099, 67106093, 67106059, + 67105963, 67105933, 67105877, 67105867, 67105811, 67105771, 67105763, 67105699, + 67105691, 67105517, 67105459, 67105453, 67105373, 67105349, 67105267, 67105187, + 67105141, 67105133, 67105061, 67104997, 67104931, 67104923, 67104893, 67104883, + 67104859, 67104803, 67104757, 67104707, 67104691, 67104589, 67104581, 67104571, + 67104563, 67104539, 67104517, 67104437, 67104419, 67104379, 67104341, 67104293, + 67104277, 67104251, 67104227, 67104139, 67104061, 67104053, 67103963, 67103909, + 67103867, 67103851, 67103837, 67103821, 67103731, 67103669, 67103653, 67103587, + 67103579, 67103549, 67103507, 67103483, 67103219, 67103173, 67103149, 67103147, + 67103107, 67103083, 67103051, 67103027, 67103021, 67102963, 67102949, 67102901, + 67102843, 67102733, 67102627, 67102613, 67102531, 67102499, 67102459, 67102397, + 67102333, 67102331, 67102283, 67102237, 67102181, 67102163, 67102099, 67102093, + 67102069, 67102067, 67102019, 67101997, 67101989, 67101899, 67101883, 67101877, + 67101779, 67101739, 67101691, 67101637, 67101613, 67101509, 67101493, 67101491, + 67101469, 67101443, 67101413, 67101341, 67101323, 67101299, 67101187, 67101173, + 67101053, 67100987, 67100981, 67100963, 67100947, 67100939, 67100909, 67100899, + 67100861, 67100851, 67100827, 67100773, 67100731, 67100699, 67100669, 67100659, + 67100653, 67100587, 67100459, 67100357, 67100347, 67100179, 67100141, 67100123, + 67100101, 67099987, 67099957, 67099931, 67099861, 67099853, 67099829, 67099819, + 67099699, 67099589, 67099547, 67099541, 67099517, 67099499, 67099397, 67099387, + 67099363, 67099339, 67099267, 67099213, 67099141, 67099133, 67099037, 67098931, + 67098923, 67098917, 67098907, 67098827, 67098821, 67098739, 67098653, 67098589, + 67098419, 67098389, 67098347, 67098341, 67098323, 67098299, 67098277, 67098259, + 67098203, 67098197, 67098179, 67098149, 67098067, 67098029, 67097917, 67097819, + 67097813, 67097803, 67097747, 67097699, 67097669, 67097659, 67097579, 67097413, + 67097363, 67097339, 67097333, 67097291, 67097269, 67097123, 67097053, 67096987, + 67096979, 67096973, 67096907, 67096867, 67096837, 67096693, 67096669, 67096507, + 67096499, 67096483, 67096411, 67096387, 67096373, 67096301, 67096109, 67096067, + 67096021, 67096013, 67095989, 67095971, 67095893, 67095869, 67095797, 67095731, + 67095701, 67095683, 67095667, 67095659, 67095629, 67095499, 67095421, 67095419, + 67095349, 67095317, 67095173, 67095139, 67095131, 67095101, 67095037, 67095011, + 67094987, 67094981, 67094917, 67094899, 67094891, 67094837, 67094827, 67094723, + 67094717, 67094707, 67094701, 67094581, 67094557, 67094507, 67094501, 67094459, + 67094437, 67094411, 67094389, 67094309, 67094299, 67094267, 67094141, 67094123, + 67094099, 67093979, 67093933, 67093931, 67093861, 67093853, 67093757, 67093723, + 67093699, 67093627, 67093619, 67093613, 67093603, 67093597, 67093547, 67093349, + 67093307, 67093181, 67093171, 67093163, 67093157, 67093109, 67093069, 67093043, + 67093003, 67092997, 67092947, 67092869, 67092821, 67092787, 67092757, 67092749, + 67092709, 67092691, 67092643, 67092611, 67092563, 67092539, 67092491, 67092461, + 67092419, 67092331, 67092323, 67092301, 67092227, 67092203, 67092197, 67092107, + 67091987, 67091939, 67091933, 67091923, 67091797, 67091779, 67091771, 67091669, + 67091611, 67091491, 67091477, 67091443, 67091357, 67091341, 67091243, 67091203, + 67091149, 67091107, 67091029, 67090979, 67090973, 67090939, 67090861, 67090763, + 67090627, 67090613, 67090589, 67090579, 67090549, 67090547, 67090523, 67090459, + 67090451, 67090411, 67090403, 67090307, 67090259, 67090229, 67090189, 67090117, + 67090099, 67090091, 67090043, 67090027, 67090013, 67089949, 67089829, 67089739, + 67089733, 67089707, 67089683, 67089587, 67089541, 67089461, 67089299, 67089283, + 67089277, 67089221, 67089059, 67088963, 67088821, 67088797, 67088779, 67088717, + 67088683, 67088653, 67088627, 67088621, 67088603, 67088597, 67088573, 67088509, + 67088501, 67088453, 67088429, 67088381, 67088347, 67088267, 67088117, 67088093, + 67088059, 67087973, 67087957, 67087901, 67087883, 67087859, 67087723, 67087717, + 67087637, 67087571, 67087547, 67087459, 67087451, 67087421, 67087277, 67087259, + 67087243, 67087187, 67087123, 67087019, 67086949, 67086931, 67086917, 67086893, + 67086869, 67086827, 67086757, 67086667, 67086637, 67086629, 67086611, 67086589, + 67086421, 67086347, 67086323, 67086317, 67086307, 67086293, 67086259, 67086109, + 67086067, 67086053, 67086043, 67086013, 67085939, 67085933, 67085899, 67085869, + 67085867, 67085861, 67085819, 67085813, 67085803, 67085771, 67085741, 67085677, + 67085531, 67085443, 67085437, 67085429, 67085357, 67085341, 67085267, 67085189, + 67085173, 67085171, 67085099, 67085093, 67085003, 67084981, 67084973, 67084931, + 67084861, 67084789, 67084757, 67084709, 67084643, 67084637, 67084603, 67084547, + 67084517, 67084483, 67084427, 67084349, 67084333, 67084331, 67084309, 67084189, + 67084187, 67084139, 67084013, 67083883, 67083859, 67083811, 67083803, 67083787, + 67083739, 67083707, 67083629, 67083619, 67083613, 67083539, 67083517, 67083461, + 67083437, 67083371, 67083323, 67083221, 67083197, 67083067, 67082989, 67082987, + 67082963, 67082933, 67082909, 67082891, 67082861, 67082843, 67082779, 67082707, + 67082699, 67082579, 67082549, 67082531, 67082453, 67082363, 67082339, 67082227, + 67082189, 67082131, 67082123, 67082101, 67082003, 67081957, 67081829, 67081811, + 67081787, 67081741, 67081733, 67081709, 67081691, 67081661, 67081579, 67081499, + 67081477, 67081429, 67081283, 67081237, 67081213, 67081211, 67081139, 67081123, + 67081051, 67080971, 67080947, 67080917, 67080859, 67080821, 67080803, 67080763, + 67080701, 67080653, 67080557, 67080491, 67080437, 67080413, 67080323, 67080179, + 67080173, 67080131, 67080107, 67080061, 67079981, 67079963, 67079941, 67079933, + 67079917, 67079693, 67079587, 67079491, 67079459, 67079429, 67079347, 67079333, + 67079323, 67079317, 67079267, 67079237, 67079219, 67079213, 67079203, 67079149, + 67079141, 67079123, 67079083, 67079027, 67078981, 67078931, 67078877, 67078819, + 67078813, 67078789, 67078763, 67078643, 67078573, 67078469, 67078387, 67078331, + 67078309, 67078301, 67078283, 67078213, 67078181, 67078139, 67078133, 67078069, + 67078061, 67078013, 67077947, 67077917, 67077851, 67077827, 67077797, 67077757, + 67077643, 67077611, 67077541, 67077539, 67077419, 67077403, 67077379, 67077349, + 67077341, 67077299, 67077293, 67077259, 67077181, 67077173, 67077133, 67076899, + 67076869, 67076851, 67076843, 67076803, 67076773, 67076741, 67076693, 67076683, + 67076677, 67076651, 67076629, 67076627, 67076573, 67076539, 67076413, 67076411, + 67076357, 67076341, 67076291, 67076189, 67076147, 67076117, 67076077, 67076069, + 67076029, 67075973, 67075949, 67075933, 67075907, 67075867, 67075787, 67075691, + 67075669, 67075573, 67075493, 67075373, 67075363, 67075277, 67075243, 67075147, + 67075109, 67075091, 67075069, 67075067, 67075037, 67074947, 67074901, 67074859, + 67074853, 67074851, 67074829, 67074691, 67074619, 67074613, 67074611, 67074587, + 67074523, 67074467, 67074317, 67074307, 67074277, 67074269, 67074179, 67073947, + 67073917, 67073899, 67073803, 67073731, 67073707, 67073701, 67073683, 67073651, + 67073603, 67073597, 67073579, 67073533, 67073459, 67073387, 67073339, 67073333, + 67073323, 67073309, 67073261, 67073197, 67073189, 67073107, 67073051, 67073003, + 67072997, 67072979, 67072909, 67072877, 67072781, 67072757, 67072739, 67072693, + 67072541, 67072373, 67072363, 67072339, 67072309, 67072283, 67072277, 67072253, + 67072139, 67072037, 67071997, 67071989, 67071947, 67071923, 67071899, 67071883, + 67071877, 67071821, 67071707, 67071637, 67071547, 67071419, 67071413, 67071317, + 67071299, 67071293, 67071157, 67071149, 67071139, 67071061, 67070989, 67070981, + 67070909, 67070869, 67070837, 67070827, 67070813, 67070803, 67070749, 67070699, + 67070621, 67070573, 67070539, 67070459, 67070357, 67070317, 67070291, 67070261, + 67070251, 67070203, 67070053, 67070027, 67069979, 67069819, 67069813, 67069787, + 67069781, 67069763, 67069669, 67069661, 67069549, 67069531, 67069469, 67069427, + 67069397, 67069339, 67069157, 67069133, 67069109, 67069099, 67069043, 67069021, + 67068971, 67068931, 67068787, 67068653, 67068643, 67068629, 67068571, 67068557, + 67068539, 67068509, 67068493, 67068371, 67068301, 67068269, 67068259, 67068227, + 67068203, 67068187, 67068181, 67068173, 67068163, 67068101, 67067971, 67067933, + 67067909, 67067789, 67067779, 67067773, 67067723, 67067629, 67067597, 67067501, + 67067453, 67067437, 67067389, 67067387, 67067339, 67067293, 67067269, 67067213, + 67067173, 67067171, 67067069, 67067059, 67067029, 67066907, 67066861, 67066859, + 67066771, 67066757, 67066723, 67066709, 67066667, 67066619, 67066613, 67066379, + 67066277, 67066243, 67066211, 67066157, 67066093, 67066061, 67066019, 67065979, + 67065931, 67065917, 67065883, 67065827, 67065787, 67065667, 67065659, 67065653, + 67065643, 67065619, 67065563, 67065461, 67065437, 67065389, 67065373, 67065293, + 67065283, 67065227, 67065211, 67065157, 67065091, 67064843, 67064827, 67064819, + 67064773, 67064771, 67064741, 67064717, 67064693, 67064611, 67064597, 67064587, + 67064579, 67064549, 67064467, 67064299, 67064267, 67064237, 67064213, 67064197, + 67064171, 67064147, 67064131, 67064093, 67064059, 67063853, 67063813, 67063723, + 67063643, 67063637, 67063523, 67063517, 67063397, 67063349, 67063307, 67063189, + 67063163, 67063133, 67063123, 67063099, 67063093, 67063069, 67063043, 67063037, + 67063019, 67062923, 67062893, 67062883, 67062859, 67062659, 67062629, 67062613, + 67062539, 67062509, 67062469, 67062461, 67062379, 67062349, 67062299, 67062221, + 67062179, 67062157, 67062067, 67062029, 67062011, 67061987, 67061947, 67061933, + 67061909, 67061867, 67061861, 67061789, 67061747, 67061693, 67061627, 67061597, + 67061563, 67061531, 67061333, 67061299, 67061227, 67061219, 67061179, 67061173, + 67061147, 67061003, 67060997, 67060957, 67060949, 67060933, 67060837, 67060813, + 67060627, 67060549, 67060523, 67060517, 67060507, 67060451, 67060421, 67060373, + 67060333, 67060307, 67060277, 67060261, 67060229, 67060187, 67060171, 67060141, + 67060109, 67060067, 67060043, 67060027, 67060013, 67059989, 67059907, 67059899, + 67059869, 67059779, 67059757, 67059749, 67059731, 67059709, 67059701, 67059637, + 67059613, 67059581, 67059547, 67059533, 67059523, 67059437, 67059427, 67059259, + 67059173, 67059061, 67058963, 67058941, 67058909, 67058899, 67058891, 67058867, + 67058843, 67058723, 67058699, 67058669, 67058627, 67058531, 67058389, 67058347, + 67058339, 67058323, 67058309, 67058269, 67058227, 67058213, 67058141, 67058003, + 67057883, 67057853, 67057819, 67057813, 67057763, 67057733, 67057723, 67057717, + 67057709, 67057643, 67057499, 67057493, 67057387, 67057381, 67057379, 67057363, + 67057307, 67057147, 67057141, 67056989, 67056971, 67056917, 67056877, 67056763, + 67056677, 67056667, 67056659, 67056637, 67056611, 67056581, 67056461, 67056419, + 67056371, 67056259, 67056251, 67056179, 67056107, 67056083, 67056053, 67056043, + 67056013, 67055957, 67055909, 67055843, 67055789, 67055771, 67055629, 67055539, + 67055491, 67055477, 67055467, 67055347, 67055309, 67055299, 67055291, 67055267, + 67055243, 67055203, 67055179, 67055147, 67054997, 67054979, 67054907, 67054877, + 67054859, 67054763, 67054733, 67054717, 67054541, 67054523, 67054483, 67054411, + 67054387, 67054301, 67054213, 67054051, 67054037, 67053997, 67053971, 67053941, + 67053893, 67053787, 67053733, 67053659, 67053653, 67053643, 67053629, 67053619, + 67053563, 67053557, 67053523, 67053517, 67053419, 67053397, 67053373, 67053317, + 67053251, 67053229, 67053197, 67053179, 67053149, 67053037, 67053029, 67052963, + 67052939, 67052933, 67052819, 67052813, 67052779, 67052723, 67052677, 67052509, + 67052477, 67052467, 67052243, 67052021, 67051979, 67051949, 67051909, 67051883, + 67051861, 67051813, 67051811, 67051781, 67051709, 67051651, 67051643, 67051573, + 67051571, 67051547, 67051493, 67051379, 67051373, 67051331, 67051253, 67051189, + 67051181, 67051099, 67051069, 67051021, 67050979, 67050931, 67050917, 67050869, + 67050827, 67050749, 67050707, 67050701, 67050619, 67050611, 67050541, 67050509, + 67050443, 67050421, 67050419, 67050371, 67050301, 67050299, 67050251, 67050187, + 67050101, 67050077, 67049987, 67049981, 67049963, 67049909, 67049891, 67049867, + 67049837, 67049813, 67049747, 67049707, 67049693, 67049629, 67049627, 67049603, + 67049573, 67049539, 67049453, 67049413, 67049267, 67049261, 67049251, 67049179, + 67049149, 67049141, 67049093, 67049027, 67048963, 67048859, 67048819, 67048757, + 67048733, 67048693, 67048627, 67048621, 67048523, 67048469, 67048411, 67048349, + 67048277, 67048259, 67048141, 67048123, 67048109, 67047989, 67047859, 67047787, + 67047763, 67047749, 67047733, 67047731, 67047683, 67047619, 67047613, 67047611, + 67047581, 67047517, 67047509, 67047413, 67047397, 67047283, 67047131, 67047077, + 67047061, 67047059, 67047053, 67047037, 67047011, 67046989, 67046939, 67046899, + 67046797, 67046779, 67046731, 67046549, 67046531, 67046477, 67046467, 67046437, + 67046429, 67046411, 67046387, 67046363, 67046341, 67046333, 67046261, 67046197, + 67046107, 67046069, 67046059, 67046051, 67045973, 67045949, 67045907, 67045877, + 67045723, 67045613, 67045579, 67045571, 67045549, 67045541, 67045507, 67045403, + 67045339, 67045301, 67045267, 67045261, 67045211, 67045189, 67045133, 67045117, + 67045109, 67045061, 67045037, 67045019, 67044973, 67044907, 67044829, 67044797, + 67044779, 67044773, 67044763, 67044739, 67044541, 67044427, 67044371, 67044347, + 67044301, 67044283, 67044203, 67044157, 67044083, 67044077, 67044067, 67044053, + 67043981, 67043939, 67043909, 67043813, 67043797, 67043707, 67043507, 67043477, + 67043443, 67043243, 67043147, 67043107, 67043083, 67043069, 67043059, 67043051, + 67043027, 67042979, 67042973, 67042949, 67042931, 67042709, 67042643, 67042637, + 67042589, 67042571, 67042541, 67042523, 67042501, 67042453, 67042427, 67042363, + 67042307, 67042301, 67042259, 67042211, 67042091, 67042043, 67041907, 67041893, + 67041869, 67041797, 67041749, 67041731, 67041701, 67041613, 67041581, 67041563, + 67041547, 67041539, 67041509, 67041467, 67041461, 67041419, 67041371, 67041307, + 67041283, 67041269, 67041203, 67041187, 67041179, 67041043, 67040917, 67040893, + 67040789, 67040773, 67040723, 67040629, 67040627, 67040621, 67040587, 67040549, + 67040509, 67040443, 67040387, 67040381, 67040317, 67040291, 67040261, 67040243, + 67040219, 67040203, 67040069, 67040021, 67039997, 67039957, 67039883, 67039877, + 67039867, 67039853, 67039811, 67039757, 67039723, 67039699, 67039669, 67039627, + 67039613, 67039571, 67039547, 67039501, 67039499, 67039309, 67039307, 67039253, + 67039187, 67039139, 67039051, 67039003, 67038947, 67038941, 67038877, 67038869, + 67038827, 67038787, 67038739, 67038637, 67038589, 67038557, 67038539, 67038533, + 67038427, 67038371, 67038341, 67038299, 67038277, 67038221, 67038197, 67038173, + 67038149, 67038133, 67038131, 67038067, 67038029, 67038011, 67037843, 67037837, + 67037819, 67037797, 67037771, 67037723, 67037683, 67037627, 67037603, 67037563, + 67037483, 67037459, 67037429, 67037389, 67037261, 67037227, 67037213, 67037107, + 67037101, 67037053, 67036979, 67036909, 67036901, 67036877, 67036867, 67036843, + 67036819, 67036811, 67036747, 67036643, 67036589, 67036547, 67036507, 67036469, + 67036397, 67036379, 67036357, 67036259, 67036243, 67036187, 67036181, 67036157, + 67036093, 67036027, 67036019, 67035989, 67035949, 67035931, 67035901, 67035803, + 67035707, 67035659, 67035653, 67035643, 67035589, 67035499, 67035491, 67035469, + 67035413, 67035349, 67035347, 67035307, 67035277, 67035149, 67035107, 67035077, + 67034987, 67034819, 67034699, 67034683, 67034677, 67034477, 67034419, 67034381, + 67034339, 67034309, 67034293, 67034171, 67034117, 67034069, 67034021, 67033859, + 67033763, 67033741, 67033709, 67033699, 67033667, 67033619, 67033613, 67033597, + 67033541, 67033507, 67033469, 67033429, 67033403, 67033357, 67033331, 67033283, + 67033277, 67033229, 67033157, 67033117, 67033061, 67032997, 67032941, 67032811, + 67032803, 67032701, 67032661, 67032653, 67032613, 67032587, 67032541, 67032523, + 67032517, 67032491, 67032461, 67032451, 67032443, 67032421, 67032389, 67032349, + 67032347, 67032299, 67032221, 67032179, 67032101, 67031941, 67031933, 67031893, + 67031851, 67031819, 67031813, 67031749, 67031693, 67031509, 67031483, 67031443, + 67031429, 67031387, 67031243, 67031219, 67031203, 67031189, 67031149, 67031147, + 67031123, 67031101, 67031059, 67030963, 67030933, 67030907, 67030867, 67030853, + 67030757, 67030741, 67030739, 67030693, 67030669, 67030597, 67030517, 67030451, + 67030427, 67030333, 67030331, 67030181, 67030069, 67030013, 67029947, 67029931, + 67029923, 67029917, 67029901, 67029811, 67029779, 67029763, 67029749, 67029709, + 67029707, 67029581, 67029541, 67029509, 67029491, 67029451, 67029437, 67029427, + 67029421, 67029373, 67029341, 67029323, 67029293, 67029269, 67029253, 67029229, + 67029077, 67029059, 67029043, 67029013, 67028981, 67028917, 67028771, 67028669, + 67028653, 67028651, 67028597, 67028557, 67028539, 67028477, 67028413, 67028387, + 67028243, 67028197, 67028083, 67028069, 67028021, 67027997, 67027963, 67027949, + 67027931, 67027867, 67027861, 67027811, 67027693, 67027627, 67027619, 67027547, + 67027507, 67027453, 67027427, 67027339, 67027283, 67027237, 67027189, 67027187, + 67027069, 67027027, 67027019, 67027013, 67026979, 67026907, 67026829, 67026811, + 67026803, 67026787, 67026643, 67026613, 67026539, 67026469, 67026467, 67026451, + 67026437, 67026403, 67026307, 67026299, 67026227, 67026187, 67026139, 67026131, + 67026109, 67026107, 67026083, 67026067, 67025971, 67025963, 67025957, 67025843, + 67025779, 67025773, 67025723, 67025701, 67025683, 67025669, 67025579, 67025573, + 67025531, 67025501, 67025459, 67025411, 67025363, 67025219, 67025213, 67025173, + 67025107, 67025051, 67025029, 67024987, 67024957, 67024901, 67024891, 67024733, + 67024637, 67024621, 67024613, 67024499, 67024483, 67024429, 67024411, 67024339, + 67024157, 67024141, 67024003, 67023989, 67023899, 67023893, 67023779, 67023763, + 67023667, 67023653, 67023493, 67023443, 67023421, 67023419, 67023371, 67023349, + 67023347, 67023331, 67023293, 67023259, 67023227, 67023211, 67023179, 67023157, + 67023139, 67023133, 67023091, 67023059, 67023053, 67023043, 67023037, 67023029, + 67022869, 67022819, 67022797, 67022723, 67022707, 67022701, 67022699, 67022693, + 67022539, 67022507, 67022477, 67022467, 67022387, 67022261, 67022243, 67022237, + 67022213, 67022147, 67022077, 67022027, 67021979, 67021963, 67021901, 67021861, + 67021741, 67021739, 67021723, 67021637, 67021621, 67021613, 67021499, 67021469, + 67021459, 67021363, 67021301, 67021237, 67021147, 67021139, 67021099, 67021067, + 67021043, 67020979, 67020973, 67020917, 67020893, 67020869, 67020797, 67020763, + 67020683, 67020589, 67020587, 67020557, 67020491, 67020397, 67020323, 67020299, + 67020251, 67020179, 67020077, 67020053, 67020013, 67019963, 67019867, 67019837, + 67019819, 67019747, 67019741, 67019653, 67019587, 67019549, 67019483, 67019437, + 67019371, 67019299, 67019123, 67019077, 67019027, 67019003, 67018997, 67018843, + 67018837, 67018771, 67018733, 67018717, 67018667, 67018613, 67018499, 67018493, + 67018429, 67018397, 67018387, 67018309, 67018181, 67018163, 67018141, 67018139, + 67018069, 67018051, 67017971, 67017931, 67017803, 67017763, 67017733, 67017707, + 67017677, 67017661, 67017659, 67017571, 67017563, 67017547, 67017413, 67017371, + 67017299, 67017277, 67017227, 67017211, 67017163, 67017157, 67017107, 67017059, + 67016869, 67016821, 67016813, 67016723, 67016717, 67016707, 67016693, 67016627, + 67016611, 67016483, 67016437, 67016387, 67016269, 67016197, 67016189, 67016179, +}; + +} // namespace internal +} // namespace CGAL diff --git a/Modular_arithmetic/src/CGAL/Residue_type.cpp b/Modular_arithmetic/src/CGAL/Residue_type.cpp index e221b51dc3e..e41a63a907b 100644 --- a/Modular_arithmetic/src/CGAL/Residue_type.cpp +++ b/Modular_arithmetic/src/CGAL/Residue_type.cpp @@ -17,8 +17,10 @@ // // Author(s) : Michael Hemmer +#ifndef CGAL_HEADER_ONLY #include +#include namespace CGAL{ #ifdef CGAL_HAS_THREADS @@ -35,3 +37,5 @@ double Residue::prime_inv =1/67111067.0; const double Residue::CST_CUT = std::ldexp( 3., 51 ); } + +#endif diff --git a/Modular_arithmetic/src/CGAL/primes.cpp b/Modular_arithmetic/src/CGAL/primes.cpp index bc2cff74c85..63b8b4d2800 100644 --- a/Modular_arithmetic/src/CGAL/primes.cpp +++ b/Modular_arithmetic/src/CGAL/primes.cpp @@ -15,280 +15,11 @@ // $URL$ // $Id$ // -// Author(s) : Michael Hemmer, Alexander Kobel +// Author(s) : Michael Hemmer + +#ifndef CGAL_HEADER_ONLY -#include #include +#include -namespace CGAL { -namespace internal { - -const int primes [2000] = { - /* - * Generated in SAGE with: - * - * N = 2000 - * p = 2^26 - * L = [] - * while len(L) < N: - * p = previous_prime(p) - * if GF(p)(2).is_primitive_root(): - * L.append(p) - * k = 8 - * for i in range(N/k): - * print ' ' + ', '.join (str(p) for p in L[k*i:k*(i+1)]) + ',' - */ - 67108859, 67108819, 67108763, 67108757, 67108747, 67108739, 67108709, 67108693, - 67108669, 67108667, 67108661, 67108597, 67108579, 67108507, 67108493, 67108453, - 67108387, 67108373, 67108331, 67108219, 67108187, 67108109, 67108037, 67108003, - 67107941, 67107797, 67107787, 67107773, 67107757, 67107749, 67107707, 67107643, - 67107541, 67107539, 67107533, 67107461, 67107427, 67107389, 67107323, 67107317, - 67107301, 67107253, 67107203, 67107149, 67107043, 67106987, 67106821, 67106813, - 67106797, 67106749, 67106717, 67106693, 67106483, 67106477, 67106357, 67106339, - 67106323, 67106243, 67106213, 67106189, 67106107, 67106099, 67106093, 67106059, - 67105963, 67105933, 67105877, 67105867, 67105811, 67105771, 67105763, 67105699, - 67105691, 67105517, 67105459, 67105453, 67105373, 67105349, 67105267, 67105187, - 67105141, 67105133, 67105061, 67104997, 67104931, 67104923, 67104893, 67104883, - 67104859, 67104803, 67104757, 67104707, 67104691, 67104589, 67104581, 67104571, - 67104563, 67104539, 67104517, 67104437, 67104419, 67104379, 67104341, 67104293, - 67104277, 67104251, 67104227, 67104139, 67104061, 67104053, 67103963, 67103909, - 67103867, 67103851, 67103837, 67103821, 67103731, 67103669, 67103653, 67103587, - 67103579, 67103549, 67103507, 67103483, 67103219, 67103173, 67103149, 67103147, - 67103107, 67103083, 67103051, 67103027, 67103021, 67102963, 67102949, 67102901, - 67102843, 67102733, 67102627, 67102613, 67102531, 67102499, 67102459, 67102397, - 67102333, 67102331, 67102283, 67102237, 67102181, 67102163, 67102099, 67102093, - 67102069, 67102067, 67102019, 67101997, 67101989, 67101899, 67101883, 67101877, - 67101779, 67101739, 67101691, 67101637, 67101613, 67101509, 67101493, 67101491, - 67101469, 67101443, 67101413, 67101341, 67101323, 67101299, 67101187, 67101173, - 67101053, 67100987, 67100981, 67100963, 67100947, 67100939, 67100909, 67100899, - 67100861, 67100851, 67100827, 67100773, 67100731, 67100699, 67100669, 67100659, - 67100653, 67100587, 67100459, 67100357, 67100347, 67100179, 67100141, 67100123, - 67100101, 67099987, 67099957, 67099931, 67099861, 67099853, 67099829, 67099819, - 67099699, 67099589, 67099547, 67099541, 67099517, 67099499, 67099397, 67099387, - 67099363, 67099339, 67099267, 67099213, 67099141, 67099133, 67099037, 67098931, - 67098923, 67098917, 67098907, 67098827, 67098821, 67098739, 67098653, 67098589, - 67098419, 67098389, 67098347, 67098341, 67098323, 67098299, 67098277, 67098259, - 67098203, 67098197, 67098179, 67098149, 67098067, 67098029, 67097917, 67097819, - 67097813, 67097803, 67097747, 67097699, 67097669, 67097659, 67097579, 67097413, - 67097363, 67097339, 67097333, 67097291, 67097269, 67097123, 67097053, 67096987, - 67096979, 67096973, 67096907, 67096867, 67096837, 67096693, 67096669, 67096507, - 67096499, 67096483, 67096411, 67096387, 67096373, 67096301, 67096109, 67096067, - 67096021, 67096013, 67095989, 67095971, 67095893, 67095869, 67095797, 67095731, - 67095701, 67095683, 67095667, 67095659, 67095629, 67095499, 67095421, 67095419, - 67095349, 67095317, 67095173, 67095139, 67095131, 67095101, 67095037, 67095011, - 67094987, 67094981, 67094917, 67094899, 67094891, 67094837, 67094827, 67094723, - 67094717, 67094707, 67094701, 67094581, 67094557, 67094507, 67094501, 67094459, - 67094437, 67094411, 67094389, 67094309, 67094299, 67094267, 67094141, 67094123, - 67094099, 67093979, 67093933, 67093931, 67093861, 67093853, 67093757, 67093723, - 67093699, 67093627, 67093619, 67093613, 67093603, 67093597, 67093547, 67093349, - 67093307, 67093181, 67093171, 67093163, 67093157, 67093109, 67093069, 67093043, - 67093003, 67092997, 67092947, 67092869, 67092821, 67092787, 67092757, 67092749, - 67092709, 67092691, 67092643, 67092611, 67092563, 67092539, 67092491, 67092461, - 67092419, 67092331, 67092323, 67092301, 67092227, 67092203, 67092197, 67092107, - 67091987, 67091939, 67091933, 67091923, 67091797, 67091779, 67091771, 67091669, - 67091611, 67091491, 67091477, 67091443, 67091357, 67091341, 67091243, 67091203, - 67091149, 67091107, 67091029, 67090979, 67090973, 67090939, 67090861, 67090763, - 67090627, 67090613, 67090589, 67090579, 67090549, 67090547, 67090523, 67090459, - 67090451, 67090411, 67090403, 67090307, 67090259, 67090229, 67090189, 67090117, - 67090099, 67090091, 67090043, 67090027, 67090013, 67089949, 67089829, 67089739, - 67089733, 67089707, 67089683, 67089587, 67089541, 67089461, 67089299, 67089283, - 67089277, 67089221, 67089059, 67088963, 67088821, 67088797, 67088779, 67088717, - 67088683, 67088653, 67088627, 67088621, 67088603, 67088597, 67088573, 67088509, - 67088501, 67088453, 67088429, 67088381, 67088347, 67088267, 67088117, 67088093, - 67088059, 67087973, 67087957, 67087901, 67087883, 67087859, 67087723, 67087717, - 67087637, 67087571, 67087547, 67087459, 67087451, 67087421, 67087277, 67087259, - 67087243, 67087187, 67087123, 67087019, 67086949, 67086931, 67086917, 67086893, - 67086869, 67086827, 67086757, 67086667, 67086637, 67086629, 67086611, 67086589, - 67086421, 67086347, 67086323, 67086317, 67086307, 67086293, 67086259, 67086109, - 67086067, 67086053, 67086043, 67086013, 67085939, 67085933, 67085899, 67085869, - 67085867, 67085861, 67085819, 67085813, 67085803, 67085771, 67085741, 67085677, - 67085531, 67085443, 67085437, 67085429, 67085357, 67085341, 67085267, 67085189, - 67085173, 67085171, 67085099, 67085093, 67085003, 67084981, 67084973, 67084931, - 67084861, 67084789, 67084757, 67084709, 67084643, 67084637, 67084603, 67084547, - 67084517, 67084483, 67084427, 67084349, 67084333, 67084331, 67084309, 67084189, - 67084187, 67084139, 67084013, 67083883, 67083859, 67083811, 67083803, 67083787, - 67083739, 67083707, 67083629, 67083619, 67083613, 67083539, 67083517, 67083461, - 67083437, 67083371, 67083323, 67083221, 67083197, 67083067, 67082989, 67082987, - 67082963, 67082933, 67082909, 67082891, 67082861, 67082843, 67082779, 67082707, - 67082699, 67082579, 67082549, 67082531, 67082453, 67082363, 67082339, 67082227, - 67082189, 67082131, 67082123, 67082101, 67082003, 67081957, 67081829, 67081811, - 67081787, 67081741, 67081733, 67081709, 67081691, 67081661, 67081579, 67081499, - 67081477, 67081429, 67081283, 67081237, 67081213, 67081211, 67081139, 67081123, - 67081051, 67080971, 67080947, 67080917, 67080859, 67080821, 67080803, 67080763, - 67080701, 67080653, 67080557, 67080491, 67080437, 67080413, 67080323, 67080179, - 67080173, 67080131, 67080107, 67080061, 67079981, 67079963, 67079941, 67079933, - 67079917, 67079693, 67079587, 67079491, 67079459, 67079429, 67079347, 67079333, - 67079323, 67079317, 67079267, 67079237, 67079219, 67079213, 67079203, 67079149, - 67079141, 67079123, 67079083, 67079027, 67078981, 67078931, 67078877, 67078819, - 67078813, 67078789, 67078763, 67078643, 67078573, 67078469, 67078387, 67078331, - 67078309, 67078301, 67078283, 67078213, 67078181, 67078139, 67078133, 67078069, - 67078061, 67078013, 67077947, 67077917, 67077851, 67077827, 67077797, 67077757, - 67077643, 67077611, 67077541, 67077539, 67077419, 67077403, 67077379, 67077349, - 67077341, 67077299, 67077293, 67077259, 67077181, 67077173, 67077133, 67076899, - 67076869, 67076851, 67076843, 67076803, 67076773, 67076741, 67076693, 67076683, - 67076677, 67076651, 67076629, 67076627, 67076573, 67076539, 67076413, 67076411, - 67076357, 67076341, 67076291, 67076189, 67076147, 67076117, 67076077, 67076069, - 67076029, 67075973, 67075949, 67075933, 67075907, 67075867, 67075787, 67075691, - 67075669, 67075573, 67075493, 67075373, 67075363, 67075277, 67075243, 67075147, - 67075109, 67075091, 67075069, 67075067, 67075037, 67074947, 67074901, 67074859, - 67074853, 67074851, 67074829, 67074691, 67074619, 67074613, 67074611, 67074587, - 67074523, 67074467, 67074317, 67074307, 67074277, 67074269, 67074179, 67073947, - 67073917, 67073899, 67073803, 67073731, 67073707, 67073701, 67073683, 67073651, - 67073603, 67073597, 67073579, 67073533, 67073459, 67073387, 67073339, 67073333, - 67073323, 67073309, 67073261, 67073197, 67073189, 67073107, 67073051, 67073003, - 67072997, 67072979, 67072909, 67072877, 67072781, 67072757, 67072739, 67072693, - 67072541, 67072373, 67072363, 67072339, 67072309, 67072283, 67072277, 67072253, - 67072139, 67072037, 67071997, 67071989, 67071947, 67071923, 67071899, 67071883, - 67071877, 67071821, 67071707, 67071637, 67071547, 67071419, 67071413, 67071317, - 67071299, 67071293, 67071157, 67071149, 67071139, 67071061, 67070989, 67070981, - 67070909, 67070869, 67070837, 67070827, 67070813, 67070803, 67070749, 67070699, - 67070621, 67070573, 67070539, 67070459, 67070357, 67070317, 67070291, 67070261, - 67070251, 67070203, 67070053, 67070027, 67069979, 67069819, 67069813, 67069787, - 67069781, 67069763, 67069669, 67069661, 67069549, 67069531, 67069469, 67069427, - 67069397, 67069339, 67069157, 67069133, 67069109, 67069099, 67069043, 67069021, - 67068971, 67068931, 67068787, 67068653, 67068643, 67068629, 67068571, 67068557, - 67068539, 67068509, 67068493, 67068371, 67068301, 67068269, 67068259, 67068227, - 67068203, 67068187, 67068181, 67068173, 67068163, 67068101, 67067971, 67067933, - 67067909, 67067789, 67067779, 67067773, 67067723, 67067629, 67067597, 67067501, - 67067453, 67067437, 67067389, 67067387, 67067339, 67067293, 67067269, 67067213, - 67067173, 67067171, 67067069, 67067059, 67067029, 67066907, 67066861, 67066859, - 67066771, 67066757, 67066723, 67066709, 67066667, 67066619, 67066613, 67066379, - 67066277, 67066243, 67066211, 67066157, 67066093, 67066061, 67066019, 67065979, - 67065931, 67065917, 67065883, 67065827, 67065787, 67065667, 67065659, 67065653, - 67065643, 67065619, 67065563, 67065461, 67065437, 67065389, 67065373, 67065293, - 67065283, 67065227, 67065211, 67065157, 67065091, 67064843, 67064827, 67064819, - 67064773, 67064771, 67064741, 67064717, 67064693, 67064611, 67064597, 67064587, - 67064579, 67064549, 67064467, 67064299, 67064267, 67064237, 67064213, 67064197, - 67064171, 67064147, 67064131, 67064093, 67064059, 67063853, 67063813, 67063723, - 67063643, 67063637, 67063523, 67063517, 67063397, 67063349, 67063307, 67063189, - 67063163, 67063133, 67063123, 67063099, 67063093, 67063069, 67063043, 67063037, - 67063019, 67062923, 67062893, 67062883, 67062859, 67062659, 67062629, 67062613, - 67062539, 67062509, 67062469, 67062461, 67062379, 67062349, 67062299, 67062221, - 67062179, 67062157, 67062067, 67062029, 67062011, 67061987, 67061947, 67061933, - 67061909, 67061867, 67061861, 67061789, 67061747, 67061693, 67061627, 67061597, - 67061563, 67061531, 67061333, 67061299, 67061227, 67061219, 67061179, 67061173, - 67061147, 67061003, 67060997, 67060957, 67060949, 67060933, 67060837, 67060813, - 67060627, 67060549, 67060523, 67060517, 67060507, 67060451, 67060421, 67060373, - 67060333, 67060307, 67060277, 67060261, 67060229, 67060187, 67060171, 67060141, - 67060109, 67060067, 67060043, 67060027, 67060013, 67059989, 67059907, 67059899, - 67059869, 67059779, 67059757, 67059749, 67059731, 67059709, 67059701, 67059637, - 67059613, 67059581, 67059547, 67059533, 67059523, 67059437, 67059427, 67059259, - 67059173, 67059061, 67058963, 67058941, 67058909, 67058899, 67058891, 67058867, - 67058843, 67058723, 67058699, 67058669, 67058627, 67058531, 67058389, 67058347, - 67058339, 67058323, 67058309, 67058269, 67058227, 67058213, 67058141, 67058003, - 67057883, 67057853, 67057819, 67057813, 67057763, 67057733, 67057723, 67057717, - 67057709, 67057643, 67057499, 67057493, 67057387, 67057381, 67057379, 67057363, - 67057307, 67057147, 67057141, 67056989, 67056971, 67056917, 67056877, 67056763, - 67056677, 67056667, 67056659, 67056637, 67056611, 67056581, 67056461, 67056419, - 67056371, 67056259, 67056251, 67056179, 67056107, 67056083, 67056053, 67056043, - 67056013, 67055957, 67055909, 67055843, 67055789, 67055771, 67055629, 67055539, - 67055491, 67055477, 67055467, 67055347, 67055309, 67055299, 67055291, 67055267, - 67055243, 67055203, 67055179, 67055147, 67054997, 67054979, 67054907, 67054877, - 67054859, 67054763, 67054733, 67054717, 67054541, 67054523, 67054483, 67054411, - 67054387, 67054301, 67054213, 67054051, 67054037, 67053997, 67053971, 67053941, - 67053893, 67053787, 67053733, 67053659, 67053653, 67053643, 67053629, 67053619, - 67053563, 67053557, 67053523, 67053517, 67053419, 67053397, 67053373, 67053317, - 67053251, 67053229, 67053197, 67053179, 67053149, 67053037, 67053029, 67052963, - 67052939, 67052933, 67052819, 67052813, 67052779, 67052723, 67052677, 67052509, - 67052477, 67052467, 67052243, 67052021, 67051979, 67051949, 67051909, 67051883, - 67051861, 67051813, 67051811, 67051781, 67051709, 67051651, 67051643, 67051573, - 67051571, 67051547, 67051493, 67051379, 67051373, 67051331, 67051253, 67051189, - 67051181, 67051099, 67051069, 67051021, 67050979, 67050931, 67050917, 67050869, - 67050827, 67050749, 67050707, 67050701, 67050619, 67050611, 67050541, 67050509, - 67050443, 67050421, 67050419, 67050371, 67050301, 67050299, 67050251, 67050187, - 67050101, 67050077, 67049987, 67049981, 67049963, 67049909, 67049891, 67049867, - 67049837, 67049813, 67049747, 67049707, 67049693, 67049629, 67049627, 67049603, - 67049573, 67049539, 67049453, 67049413, 67049267, 67049261, 67049251, 67049179, - 67049149, 67049141, 67049093, 67049027, 67048963, 67048859, 67048819, 67048757, - 67048733, 67048693, 67048627, 67048621, 67048523, 67048469, 67048411, 67048349, - 67048277, 67048259, 67048141, 67048123, 67048109, 67047989, 67047859, 67047787, - 67047763, 67047749, 67047733, 67047731, 67047683, 67047619, 67047613, 67047611, - 67047581, 67047517, 67047509, 67047413, 67047397, 67047283, 67047131, 67047077, - 67047061, 67047059, 67047053, 67047037, 67047011, 67046989, 67046939, 67046899, - 67046797, 67046779, 67046731, 67046549, 67046531, 67046477, 67046467, 67046437, - 67046429, 67046411, 67046387, 67046363, 67046341, 67046333, 67046261, 67046197, - 67046107, 67046069, 67046059, 67046051, 67045973, 67045949, 67045907, 67045877, - 67045723, 67045613, 67045579, 67045571, 67045549, 67045541, 67045507, 67045403, - 67045339, 67045301, 67045267, 67045261, 67045211, 67045189, 67045133, 67045117, - 67045109, 67045061, 67045037, 67045019, 67044973, 67044907, 67044829, 67044797, - 67044779, 67044773, 67044763, 67044739, 67044541, 67044427, 67044371, 67044347, - 67044301, 67044283, 67044203, 67044157, 67044083, 67044077, 67044067, 67044053, - 67043981, 67043939, 67043909, 67043813, 67043797, 67043707, 67043507, 67043477, - 67043443, 67043243, 67043147, 67043107, 67043083, 67043069, 67043059, 67043051, - 67043027, 67042979, 67042973, 67042949, 67042931, 67042709, 67042643, 67042637, - 67042589, 67042571, 67042541, 67042523, 67042501, 67042453, 67042427, 67042363, - 67042307, 67042301, 67042259, 67042211, 67042091, 67042043, 67041907, 67041893, - 67041869, 67041797, 67041749, 67041731, 67041701, 67041613, 67041581, 67041563, - 67041547, 67041539, 67041509, 67041467, 67041461, 67041419, 67041371, 67041307, - 67041283, 67041269, 67041203, 67041187, 67041179, 67041043, 67040917, 67040893, - 67040789, 67040773, 67040723, 67040629, 67040627, 67040621, 67040587, 67040549, - 67040509, 67040443, 67040387, 67040381, 67040317, 67040291, 67040261, 67040243, - 67040219, 67040203, 67040069, 67040021, 67039997, 67039957, 67039883, 67039877, - 67039867, 67039853, 67039811, 67039757, 67039723, 67039699, 67039669, 67039627, - 67039613, 67039571, 67039547, 67039501, 67039499, 67039309, 67039307, 67039253, - 67039187, 67039139, 67039051, 67039003, 67038947, 67038941, 67038877, 67038869, - 67038827, 67038787, 67038739, 67038637, 67038589, 67038557, 67038539, 67038533, - 67038427, 67038371, 67038341, 67038299, 67038277, 67038221, 67038197, 67038173, - 67038149, 67038133, 67038131, 67038067, 67038029, 67038011, 67037843, 67037837, - 67037819, 67037797, 67037771, 67037723, 67037683, 67037627, 67037603, 67037563, - 67037483, 67037459, 67037429, 67037389, 67037261, 67037227, 67037213, 67037107, - 67037101, 67037053, 67036979, 67036909, 67036901, 67036877, 67036867, 67036843, - 67036819, 67036811, 67036747, 67036643, 67036589, 67036547, 67036507, 67036469, - 67036397, 67036379, 67036357, 67036259, 67036243, 67036187, 67036181, 67036157, - 67036093, 67036027, 67036019, 67035989, 67035949, 67035931, 67035901, 67035803, - 67035707, 67035659, 67035653, 67035643, 67035589, 67035499, 67035491, 67035469, - 67035413, 67035349, 67035347, 67035307, 67035277, 67035149, 67035107, 67035077, - 67034987, 67034819, 67034699, 67034683, 67034677, 67034477, 67034419, 67034381, - 67034339, 67034309, 67034293, 67034171, 67034117, 67034069, 67034021, 67033859, - 67033763, 67033741, 67033709, 67033699, 67033667, 67033619, 67033613, 67033597, - 67033541, 67033507, 67033469, 67033429, 67033403, 67033357, 67033331, 67033283, - 67033277, 67033229, 67033157, 67033117, 67033061, 67032997, 67032941, 67032811, - 67032803, 67032701, 67032661, 67032653, 67032613, 67032587, 67032541, 67032523, - 67032517, 67032491, 67032461, 67032451, 67032443, 67032421, 67032389, 67032349, - 67032347, 67032299, 67032221, 67032179, 67032101, 67031941, 67031933, 67031893, - 67031851, 67031819, 67031813, 67031749, 67031693, 67031509, 67031483, 67031443, - 67031429, 67031387, 67031243, 67031219, 67031203, 67031189, 67031149, 67031147, - 67031123, 67031101, 67031059, 67030963, 67030933, 67030907, 67030867, 67030853, - 67030757, 67030741, 67030739, 67030693, 67030669, 67030597, 67030517, 67030451, - 67030427, 67030333, 67030331, 67030181, 67030069, 67030013, 67029947, 67029931, - 67029923, 67029917, 67029901, 67029811, 67029779, 67029763, 67029749, 67029709, - 67029707, 67029581, 67029541, 67029509, 67029491, 67029451, 67029437, 67029427, - 67029421, 67029373, 67029341, 67029323, 67029293, 67029269, 67029253, 67029229, - 67029077, 67029059, 67029043, 67029013, 67028981, 67028917, 67028771, 67028669, - 67028653, 67028651, 67028597, 67028557, 67028539, 67028477, 67028413, 67028387, - 67028243, 67028197, 67028083, 67028069, 67028021, 67027997, 67027963, 67027949, - 67027931, 67027867, 67027861, 67027811, 67027693, 67027627, 67027619, 67027547, - 67027507, 67027453, 67027427, 67027339, 67027283, 67027237, 67027189, 67027187, - 67027069, 67027027, 67027019, 67027013, 67026979, 67026907, 67026829, 67026811, - 67026803, 67026787, 67026643, 67026613, 67026539, 67026469, 67026467, 67026451, - 67026437, 67026403, 67026307, 67026299, 67026227, 67026187, 67026139, 67026131, - 67026109, 67026107, 67026083, 67026067, 67025971, 67025963, 67025957, 67025843, - 67025779, 67025773, 67025723, 67025701, 67025683, 67025669, 67025579, 67025573, - 67025531, 67025501, 67025459, 67025411, 67025363, 67025219, 67025213, 67025173, - 67025107, 67025051, 67025029, 67024987, 67024957, 67024901, 67024891, 67024733, - 67024637, 67024621, 67024613, 67024499, 67024483, 67024429, 67024411, 67024339, - 67024157, 67024141, 67024003, 67023989, 67023899, 67023893, 67023779, 67023763, - 67023667, 67023653, 67023493, 67023443, 67023421, 67023419, 67023371, 67023349, - 67023347, 67023331, 67023293, 67023259, 67023227, 67023211, 67023179, 67023157, - 67023139, 67023133, 67023091, 67023059, 67023053, 67023043, 67023037, 67023029, - 67022869, 67022819, 67022797, 67022723, 67022707, 67022701, 67022699, 67022693, - 67022539, 67022507, 67022477, 67022467, 67022387, 67022261, 67022243, 67022237, - 67022213, 67022147, 67022077, 67022027, 67021979, 67021963, 67021901, 67021861, - 67021741, 67021739, 67021723, 67021637, 67021621, 67021613, 67021499, 67021469, - 67021459, 67021363, 67021301, 67021237, 67021147, 67021139, 67021099, 67021067, - 67021043, 67020979, 67020973, 67020917, 67020893, 67020869, 67020797, 67020763, - 67020683, 67020589, 67020587, 67020557, 67020491, 67020397, 67020323, 67020299, - 67020251, 67020179, 67020077, 67020053, 67020013, 67019963, 67019867, 67019837, - 67019819, 67019747, 67019741, 67019653, 67019587, 67019549, 67019483, 67019437, - 67019371, 67019299, 67019123, 67019077, 67019027, 67019003, 67018997, 67018843, - 67018837, 67018771, 67018733, 67018717, 67018667, 67018613, 67018499, 67018493, - 67018429, 67018397, 67018387, 67018309, 67018181, 67018163, 67018141, 67018139, - 67018069, 67018051, 67017971, 67017931, 67017803, 67017763, 67017733, 67017707, - 67017677, 67017661, 67017659, 67017571, 67017563, 67017547, 67017413, 67017371, - 67017299, 67017277, 67017227, 67017211, 67017163, 67017157, 67017107, 67017059, - 67016869, 67016821, 67016813, 67016723, 67016717, 67016707, 67016693, 67016627, - 67016611, 67016483, 67016437, 67016387, 67016269, 67016197, 67016189, 67016179, -}; - -} // namespace internal -} // namespace CGAL +#endif diff --git a/Nef_2/include/CGAL/Nef_2/Polynomial.h b/Nef_2/include/CGAL/Nef_2/Polynomial.h index 95272055865..ed1745e15c8 100644 --- a/Nef_2/include/CGAL/Nef_2/Polynomial.h +++ b/Nef_2/include/CGAL/Nef_2/Polynomial.h @@ -1751,7 +1751,7 @@ template std::ostream& operator << (std::ostream& os, const Polynomial& p) { int i; - switch( os.iword(CGAL::IO::mode) ) + switch( get_mode(os) ) { case CGAL::IO::ASCII : os << p.degree() << ' '; @@ -1787,7 +1787,7 @@ std::istream& operator >> (std::istream& is, Polynomial& p) { char ch; NT c; bool pretty = false; - switch( is.iword(CGAL::IO::mode) ) { + switch( get_mode(is) ) { case CGAL::IO::ASCII : case CGAL::IO::PRETTY : is >> ch; @@ -1972,12 +1972,8 @@ using Nef::gcd; } //namespace CGAL - - - - - - - +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY #endif // CGAL_NEF_2_POLYNOMIAL_H diff --git a/Nef_2/include/CGAL/Nef_2/Polynomial_impl.h b/Nef_2/include/CGAL/Nef_2/Polynomial_impl.h new file mode 100644 index 00000000000..af23caf540b --- /dev/null +++ b/Nef_2/include/CGAL/Nef_2/Polynomial_impl.h @@ -0,0 +1,204 @@ +// Copyright (c) 2000 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Michael Seel +// Andreas Fabri + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +namespace CGAL{ + + namespace Nef { + +CGAL_INLINE_FUNCTION +void Polynomial::euclidean_div( + const Polynomial& f, const Polynomial& g, + Polynomial& q, Polynomial& r) +{ + r = f; r.copy_on_write(); + int rd=r.degree(), gd=g.degree(), qd; + if ( rd < gd ) { q = Polynomial(int(0)); } + else { qd = rd-gd+1; q = Polynomial(std::size_t(qd)); } + while ( rd >= gd && !(r.is_zero())) { + int S = r[rd] / g[gd]; + qd = rd-gd; + q.coeff(qd) += S; + r.minus_offsetmult(g,S,qd); + rd = r.degree(); + } + CGAL_postcondition( f==q*g+r ); +} + + + +CGAL_INLINE_FUNCTION +void Polynomial::pseudo_div( + const Polynomial& f, const Polynomial& g, + Polynomial& q, Polynomial& r, int& D) +{ + CGAL_NEF_TRACEN("pseudo_div "<(0); r = f; D = 1; + CGAL_postcondition(Polynomial(D)*f==q*g+r); return; + } + // now we know fd >= gd and f>=g + int qd=fd-gd, delta=qd+1, rd=fd; + { q = Polynomial( std::size_t(delta) ); }; // workaround for SUNPRO + int G = g[gd]; // highest order coeff of g + D = G; while (--delta) D*=G; // D = G^delta + Polynomial res = Polynomial(D)*f; + CGAL_NEF_TRACEN(" pseudo_div start "<= 0) { + int F = res[rd]; // highest order coeff of res + int t = F/G; // ensured to be integer by multiplication of D + q.coeff(qd) = t; // store q coeff + res.minus_offsetmult(g,t,qd); + if (res.is_zero()) break; + rd = res.degree(); + qd = rd - gd; + } + r = res; + CGAL_postcondition(Polynomial(D)*f==q*g+r); + CGAL_NEF_TRACEN(" returning "< Polynomial::gcd( + const Polynomial& p1, const Polynomial& p2) +{ CGAL_NEF_TRACEN("gcd("<(int(1)); + else return p2.abs(); + } + if ( p2.is_zero() ) + return p1.abs(); + + Polynomial f1 = p1.abs(); + Polynomial f2 = p2.abs(); + int f1c = f1.content(), f2c = f2.content(); + f1 /= f1c; f2 /= f2c; + int F = CGAL::gcd(f1c,f2c); + Polynomial q,r; int M=1,D; + bool first = true; + while ( ! f2.is_zero() ) { + Polynomial::pseudo_div(f1,f2,q,r,D); + if (!first) M*=D; + CGAL_NEF_TRACEV(f1);CGAL_NEF_TRACEV(f2);CGAL_NEF_TRACEV(q);CGAL_NEF_TRACEV(r);CGAL_NEF_TRACEV(M); + r /= r.content(); + f1=f2; f2=r; + first=false; + } + CGAL_NEF_TRACEV(f1.content()); + return Polynomial(F)*f1.abs(); +} + + + + +CGAL_INLINE_FUNCTION +void Polynomial::euclidean_div( + const Polynomial& f, const Polynomial& g, + Polynomial& q, Polynomial& r) +{ + r = f; r.copy_on_write(); + int rd=r.degree(), gd=g.degree(), qd; + if ( rd < gd ) { q = Polynomial(double(0)); } + else { qd = rd-gd+1; q = Polynomial(std::size_t(qd)); } + while ( rd >= gd && !(r.is_zero())) { + double S = r[rd] / g[gd]; + qd = rd-gd; + q.coeff(qd) += S; + r.minus_offsetmult(g,S,qd); + rd = r.degree(); + } + CGAL_postcondition( f==q*g+r ); +} + + + +CGAL_INLINE_FUNCTION +void Polynomial::pseudo_div( + const Polynomial& f, const Polynomial& g, + Polynomial& q, Polynomial& r, double& D) +{ + CGAL_NEF_TRACEN("pseudo_div "<(0); r = f; D = 1; + CGAL_postcondition(Polynomial(D)*f==q*g+r); return; + } + // now we know fd >= gd and f>=g + int qd=fd-gd, delta=qd+1, rd=fd; + q = Polynomial( std::size_t(delta) ); + double G = g[gd]; // highest order coeff of g + D = G; while (--delta) D*=G; // D = G^delta + Polynomial res = Polynomial(D)*f; + CGAL_NEF_TRACEN(" pseudo_div start "<= 0) { + double F = res[rd]; // highest order coeff of res + double t = F/G; // ensured to be integer by multiplication of D + q.coeff(qd) = t; // store q coeff + res.minus_offsetmult(g,t,qd); + if (res.is_zero()) break; + rd = res.degree(); + qd = rd - gd; + } + r = res; + CGAL_postcondition(Polynomial(D)*f==q*g+r); + CGAL_NEF_TRACEN(" returning "< Polynomial::gcd( + const Polynomial& p1, const Polynomial& p2) +{ CGAL_NEF_TRACEN("gcd("<(double(1)); + else return p2.abs(); + } + if ( p2.is_zero() ) + return p1.abs(); + + Polynomial f1 = p1.abs(); + Polynomial f2 = p2.abs(); + double f1c = f1.content(), f2c = f2.content(); + f1 /= f1c; f2 /= f2c; + Polynomial q,r; double M=1,D; + bool first = true; + while ( ! f2.is_zero() ) { + Polynomial::pseudo_div(f1,f2,q,r,D); + if (!first) M*=D; + CGAL_NEF_TRACEV(f1);CGAL_NEF_TRACEV(f2);CGAL_NEF_TRACEV(q);CGAL_NEF_TRACEV(r);CGAL_NEF_TRACEV(M); + r /= r.content(); + f1=f2; f2=r; + first=false; + } + CGAL_NEF_TRACEV(f1.content()); + return Polynomial(1)*f1.abs(); +} + + +} // end namespace Nef +}//end namespace CGAL diff --git a/Nef_2/src/CGAL/NefPolynomial.cpp b/Nef_2/src/CGAL/NefPolynomial.cpp index 261074845cf..aa717ca140c 100644 --- a/Nef_2/src/CGAL/NefPolynomial.cpp +++ b/Nef_2/src/CGAL/NefPolynomial.cpp @@ -19,176 +19,9 @@ // Author(s) : Michael Seel // Andreas Fabri +#ifndef CGAL_HEADER_ONLY + #include +#include -namespace CGAL{ - - namespace Nef { - -void Polynomial::euclidean_div( - const Polynomial& f, const Polynomial& g, - Polynomial& q, Polynomial& r) -{ - r = f; r.copy_on_write(); - int rd=r.degree(), gd=g.degree(), qd; - if ( rd < gd ) { q = Polynomial(int(0)); } - else { qd = rd-gd+1; q = Polynomial(std::size_t(qd)); } - while ( rd >= gd && !(r.is_zero())) { - int S = r[rd] / g[gd]; - qd = rd-gd; - q.coeff(qd) += S; - r.minus_offsetmult(g,S,qd); - rd = r.degree(); - } - CGAL_postcondition( f==q*g+r ); -} - - - -void Polynomial::pseudo_div( - const Polynomial& f, const Polynomial& g, - Polynomial& q, Polynomial& r, int& D) -{ - CGAL_NEF_TRACEN("pseudo_div "<(0); r = f; D = 1; - CGAL_postcondition(Polynomial(D)*f==q*g+r); return; - } - // now we know fd >= gd and f>=g - int qd=fd-gd, delta=qd+1, rd=fd; - { q = Polynomial( std::size_t(delta) ); }; // workaround for SUNPRO - int G = g[gd]; // highest order coeff of g - D = G; while (--delta) D*=G; // D = G^delta - Polynomial res = Polynomial(D)*f; - CGAL_NEF_TRACEN(" pseudo_div start "<= 0) { - int F = res[rd]; // highest order coeff of res - int t = F/G; // ensured to be integer by multiplication of D - q.coeff(qd) = t; // store q coeff - res.minus_offsetmult(g,t,qd); - if (res.is_zero()) break; - rd = res.degree(); - qd = rd - gd; - } - r = res; - CGAL_postcondition(Polynomial(D)*f==q*g+r); - CGAL_NEF_TRACEN(" returning "< Polynomial::gcd( - const Polynomial& p1, const Polynomial& p2) -{ CGAL_NEF_TRACEN("gcd("<(int(1)); - else return p2.abs(); - } - if ( p2.is_zero() ) - return p1.abs(); - - Polynomial f1 = p1.abs(); - Polynomial f2 = p2.abs(); - int f1c = f1.content(), f2c = f2.content(); - f1 /= f1c; f2 /= f2c; - int F = CGAL::gcd(f1c,f2c); - Polynomial q,r; int M=1,D; - bool first = true; - while ( ! f2.is_zero() ) { - Polynomial::pseudo_div(f1,f2,q,r,D); - if (!first) M*=D; - CGAL_NEF_TRACEV(f1);CGAL_NEF_TRACEV(f2);CGAL_NEF_TRACEV(q);CGAL_NEF_TRACEV(r);CGAL_NEF_TRACEV(M); - r /= r.content(); - f1=f2; f2=r; - first=false; - } - CGAL_NEF_TRACEV(f1.content()); - return Polynomial(F)*f1.abs(); -} - - - - -void Polynomial::euclidean_div( - const Polynomial& f, const Polynomial& g, - Polynomial& q, Polynomial& r) -{ - r = f; r.copy_on_write(); - int rd=r.degree(), gd=g.degree(), qd; - if ( rd < gd ) { q = Polynomial(double(0)); } - else { qd = rd-gd+1; q = Polynomial(std::size_t(qd)); } - while ( rd >= gd && !(r.is_zero())) { - double S = r[rd] / g[gd]; - qd = rd-gd; - q.coeff(qd) += S; - r.minus_offsetmult(g,S,qd); - rd = r.degree(); - } - CGAL_postcondition( f==q*g+r ); -} - - - -void Polynomial::pseudo_div( - const Polynomial& f, const Polynomial& g, - Polynomial& q, Polynomial& r, double& D) -{ - CGAL_NEF_TRACEN("pseudo_div "<(0); r = f; D = 1; - CGAL_postcondition(Polynomial(D)*f==q*g+r); return; - } - // now we know fd >= gd and f>=g - int qd=fd-gd, delta=qd+1, rd=fd; - q = Polynomial( std::size_t(delta) ); - double G = g[gd]; // highest order coeff of g - D = G; while (--delta) D*=G; // D = G^delta - Polynomial res = Polynomial(D)*f; - CGAL_NEF_TRACEN(" pseudo_div start "<= 0) { - double F = res[rd]; // highest order coeff of res - double t = F/G; // ensured to be integer by multiplication of D - q.coeff(qd) = t; // store q coeff - res.minus_offsetmult(g,t,qd); - if (res.is_zero()) break; - rd = res.degree(); - qd = rd - gd; - } - r = res; - CGAL_postcondition(Polynomial(D)*f==q*g+r); - CGAL_NEF_TRACEN(" returning "< Polynomial::gcd( - const Polynomial& p1, const Polynomial& p2) -{ CGAL_NEF_TRACEN("gcd("<(double(1)); - else return p2.abs(); - } - if ( p2.is_zero() ) - return p1.abs(); - - Polynomial f1 = p1.abs(); - Polynomial f2 = p2.abs(); - double f1c = f1.content(), f2c = f2.content(); - f1 /= f1c; f2 /= f2c; - Polynomial q,r; double M=1,D; - bool first = true; - while ( ! f2.is_zero() ) { - Polynomial::pseudo_div(f1,f2,q,r,D); - if (!first) M*=D; - CGAL_NEF_TRACEV(f1);CGAL_NEF_TRACEV(f2);CGAL_NEF_TRACEV(q);CGAL_NEF_TRACEV(r);CGAL_NEF_TRACEV(M); - r /= r.content(); - f1=f2; f2=r; - first=false; - } - CGAL_NEF_TRACEV(f1.content()); - return Polynomial(1)*f1.abs(); -} - - -} // end namespace Nef -}//end namespace CGAL +#endif // CGAL_HEADER_ONLY diff --git a/Nef_3/include/CGAL/Nef_3/Pluecker_line_3.h b/Nef_3/include/CGAL/Nef_3/Pluecker_line_3.h index b80beff7301..193d3c2543e 100644 --- a/Nef_3/include/CGAL/Nef_3/Pluecker_line_3.h +++ b/Nef_3/include/CGAL/Nef_3/Pluecker_line_3.h @@ -321,7 +321,7 @@ on their Pluecker coefficient tuples.}*/ template std::ostream& operator<<(std::ostream& os, const Pluecker_line_3& l) { - switch( os.iword(CGAL::IO::mode) ) { + switch( get_mode(os) ) { case CGAL::IO::ASCII : for (unsigned i=0; i<6; ++i) os << l[i] << " "; return os; diff --git a/Nef_3/include/CGAL/Nef_3/SNC_io_parser.h b/Nef_3/include/CGAL/Nef_3/SNC_io_parser.h index b15d1d8e985..6bea47f058e 100644 --- a/Nef_3/include/CGAL/Nef_3/SNC_io_parser.h +++ b/Nef_3/include/CGAL/Nef_3/SNC_io_parser.h @@ -14,7 +14,7 @@ // // $URL$ // $Id$ -// +// // // Author(s) : Michael Seel // Miguel Granados @@ -123,16 +123,16 @@ typename Type_converter::Vector_3 get_vector(const CGAL::Vector_3& v){ ret template class moreLeft : public T { - + typedef typename T::SM_decorator SM_decorator; typedef typename T::SHalfedge_handle SHalfedge_handle; typedef typename T::Vector_3 Vector_3; typedef typename T::FT FT; typedef typename T::RT RT; - + public: moreLeft(T D) : T(D) {} - + int operator()(SHalfedge_handle se1, SHalfedge_handle se2) { CGAL_assertion(se1 != SHalfedge_handle()); @@ -145,12 +145,12 @@ class moreLeft : public T { if(vec1 == vec2) return 0; - + if(vec1.x() == RT(0) && vec2.x() == RT(0)) { if(vec1.y() != vec2.y()) { if(vec1.y() < vec2.y()) return -1; - else + else return 1; } if(vec1.z() < vec2.z()) @@ -158,7 +158,7 @@ class moreLeft : public T { else return 1; } - + Vector_3 minus(-1,0,0); FT sk1(minus*vec1), sk2(minus*vec2); if((sk1 >= FT(0) && sk2 <= FT(0)) || @@ -172,11 +172,11 @@ class moreLeft : public T { FT len1 = vec1.x()*vec1.x()+vec1.y()*vec1.y()+vec1.z()*vec1.z(); FT len2 = vec2.x()*vec2.x()+vec2.y()*vec2.y()+vec2.z()*vec2.z(); FT diff = len1*sk2*sk2 - len2*sk1*sk1; - + if(diff != FT(0)) { if((sk1>FT(0) && diffFT(0))) return -1; - else + else return 1; } @@ -186,30 +186,30 @@ class moreLeft : public T { template class sort_vertices : public SNC_decorator { - + typedef T SNC_structure; typedef CGAL::SNC_decorator Base; typedef typename T::Vertex_handle Vertex_handle; typedef typename T::Point_3 Point_3; - + public: sort_vertices(T& D) : Base(D) {} - + bool operator() (Vertex_handle v1, Vertex_handle v2) const { return lexicographically_xyz_smaller(v1->point(), v2->point()); } }; - + template class sort_edges : public SNC_decorator { - - typedef T SNC_structure; + + typedef T SNC_structure; typedef CGAL::SNC_decorator Base; typedef typename T::Halfedge_handle Halfedge_handle; - + public: sort_edges(T& D) : Base(D) {} - + bool operator() (Halfedge_handle e1, Halfedge_handle e2) const { sort_vertices SORT(*this->sncp()); if(e1->source() != e2->source()) @@ -220,8 +220,8 @@ class sort_edges : public SNC_decorator { template class sort_facets : public SNC_decorator { - - typedef T SNC_structure; + + typedef T SNC_structure; typedef SNC_decorator Base; typedef typename T::Halffacet_handle Halffacet_handle; typedef typename T::SHalfedge_handle SHalfedge_handle; @@ -230,25 +230,25 @@ class sort_facets : public SNC_decorator { public: sort_facets(T& D) : Base(D) {} - + bool operator() (Halffacet_handle f1, Halffacet_handle f2) const { - + Plane_3 p1(f1->plane()); Plane_3 p2(f2->plane()); - + if(p1.d() != p2.d()) return p1.d() < p2.d(); else if(p1.a() != p2.a()) return p1.a() < p2.a(); else if(p1.b() != p2.b()) - return p1.b() < p2.b(); + return p1.b() < p2.b(); else if(p1.c() != p2.c()) - return p1.c() < p2.c(); + return p1.c() < p2.c(); SHalfedge_handle se1 = SHalfedge_handle(f1->facet_cycles_begin()); SHalfedge_handle se2 = SHalfedge_handle(f2->facet_cycles_begin()); - + sort_vertices SORT(*this->sncp()); if(se1->source()->source() != se2->source()->source()) return SORT(se1->source()->source(), se2->source()->source()); @@ -258,14 +258,14 @@ class sort_facets : public SNC_decorator { CGAL_assertion(se1->source()->source() != se2->source()->source()); return SORT(se1->source()->source(), se2->source()->source()); - + } }; template class sort_sedges : public SNC_decorator { - - typedef T SNC_structure; + + typedef T SNC_structure; typedef CGAL::SNC_decorator Base; typedef CGAL::SM_decorator SM_decorator; typedef typename T::Vertex_handle Vertex_handle; @@ -274,12 +274,12 @@ class sort_sedges : public SNC_decorator { public: sort_sedges(T& D) : Base(D) {} - + bool operator() (SHalfedge_handle se1, SHalfedge_handle se2) const { CGAL_NEF_TRACEN("sort sedges"); if(se1 == se2) return false; sort_vertices SORT(*this->sncp()); - CGAL_NEF_TRACEN(" center verices: " << se1->source()->source()->point() << + CGAL_NEF_TRACEN(" center verices: " << se1->source()->source()->point() << " , " << se2->source()->source()->point()); if(se1->source()->source() != se2->source()->source()) return SORT(se1->source()->source(),se2->source()->source()); @@ -291,23 +291,23 @@ class sort_sedges : public SNC_decorator { return vec1.a() < vec2.a(); else if(vec1.b() != vec2.b()) return vec1.b() < vec2.b(); - return vec1.c() < vec2.c(); + return vec1.c() < vec2.c(); } else return SORT(se1->source()->twin()->source(), se2->source()->twin()->source()); } - if(SORT(se1->twin()->source()->twin()->source(), + if(SORT(se1->twin()->source()->twin()->source(), se1->source()->twin()->source())) se1 = se1->twin(); - if(SORT(se2->twin()->source()->twin()->source(), + if(SORT(se2->twin()->source()->twin()->source(), se2->source()->twin()->source())) se2 = se2->twin(); - CGAL_NEF_TRACEN(" ssources " << se1->source()->twin()->source()->point() + CGAL_NEF_TRACEN(" ssources " << se1->source()->twin()->source()->point() << " , " << se2->source()->twin()->source()->point()); if(se1->source() != se2->source()) return SORT(se1->source()->twin()->source(), se2->source()->twin()->source()); - CGAL_NEF_TRACEN(" starget " << se1->twin()->source()->twin()->source()->point() << + CGAL_NEF_TRACEN(" starget " << se1->twin()->source()->twin()->source()->point() << " , " << se2->twin()->source()->twin()->source()->point()); if(se1->twin()->source()->twin()->source() != se2->twin()->source()->twin()->source()) return SORT(se1->twin()->source()->twin()->source(), se2->twin()->source()->twin()->source()); @@ -315,26 +315,26 @@ class sort_sedges : public SNC_decorator { CGAL_assertion(se1->circle() != se2->circle()); Sphere_circle vec1 = se1->circle(); Sphere_circle vec2 = se2->circle(); - + if(vec1.a() != vec2.a()) return vec1.a() < vec2.a(); else if(vec1.b() != vec2.b()) return vec1.b() < vec2.b(); - return vec1.c() < vec2.c(); + return vec1.c() < vec2.c(); } }; template class sort_sloops : public SNC_decorator { - - typedef T SNC_structure; + + typedef T SNC_structure; typedef CGAL::SNC_decorator Base; typedef typename T::SHalfloop_handle SHalfloop_handle; - + public: sort_sloops(T& D) : Base(D) {} - + bool operator() (SHalfloop_handle sl1, SHalfloop_handle sl2) const { if(sl1 == sl2) return false; sort_vertices SORTV(*this->sncp()); @@ -347,8 +347,8 @@ class sort_sloops : public SNC_decorator { template class sort_sface_cycle_entries : public SNC_decorator { - - typedef T SNC_structure; + + typedef T SNC_structure; typedef CGAL::SNC_decorator Base; typedef typename T::SM_decorator SM_decorator; typedef typename T::Object_handle Object_handle; @@ -358,10 +358,10 @@ class sort_sface_cycle_entries : public SNC_decorator { typedef typename T::SFace_handle SFace_handle; typedef typename T::Point_3 Point_3; typedef typename T::Vector_3 Vector_3; - + public: sort_sface_cycle_entries(T D) : Base(D) {} - + bool operator() (Object_handle o1, Object_handle o2) const { CGAL_NEF_TRACEN("sort sface cycles "); SVertex_handle sv1, sv2; @@ -370,10 +370,10 @@ class sort_sface_cycle_entries : public SNC_decorator { if(!CGAL::assign(se1,o1) && !CGAL::assign(sl1,o1) && !CGAL::assign(sv1,o1)) CGAL_error_msg("wrong handle"); - + if(!CGAL::assign(se2,o2) && !CGAL::assign(sl2,o2) && !CGAL::assign(sv2,o2)) - CGAL_error_msg("wrong handle"); - + CGAL_error_msg("wrong handle"); + if(se1 != SHalfedge_handle() && se2 == SHalfedge_handle()) return true; @@ -408,7 +408,7 @@ class sort_sface_cycle_entries : public SNC_decorator { else if(vec1.y() != vec2.y()) return vec1.y() < vec2.y(); else if(vec1.z() != vec2.z()) - return vec1.z() < vec2.z(); + return vec1.z() < vec2.z(); } CGAL_assertion(sv1 != SVertex_handle() && sv2 != SVertex_handle()); @@ -419,7 +419,7 @@ class sort_sface_cycle_entries : public SNC_decorator { template class sort_sfaces : public SNC_decorator { - + typedef T SNC_structure; typedef CGAL::SNC_decorator Base; typedef typename T::SM_decorator SM_decorator; @@ -432,16 +432,16 @@ class sort_sfaces : public SNC_decorator { typedef typename T::SFace_cycle_iterator SFace_cycle_iterator; typedef typename T::SHalfedge_around_sface_circulator SHalfedge_around_sface_circulator; - + public: sort_sfaces(T& D) : Base(D) {} bool operator() (SFace_handle sf1, SFace_handle sf2) const { CGAL_NEF_TRACEN("sort sfaces"); if(&*sf1 == &*sf2) return false; - + sort_vertices SORT(*this->sncp()); - + CGAL_NEF_TRACEN(" vertices " << sf1->center_vertex()->point() << " , " << sf2->center_vertex()->point()); if(sf1->center_vertex() != sf2->center_vertex()) return SORT(sf1->center_vertex(), sf2->center_vertex()); @@ -454,7 +454,7 @@ class sort_sfaces : public SNC_decorator { Vector_3 plus(1,0,0); SFace_cycle_iterator fc; - + CGAL_NEF_TRACEN(" sface 1"); SHalfedge_handle se1; @@ -464,7 +464,7 @@ class sort_sfaces : public SNC_decorator { SHalfedge_handle se(fc); SHalfedge_around_sface_circulator ec(se),ee(se); CGAL_For_all(ec,ee) { - CGAL_NEF_TRACEN(" " << ec->source()->point() << + CGAL_NEF_TRACEN(" " << ec->source()->point() << " | " << ec->circle().orthogonal_vector()); if(ml(ec, se1) == -1) se1 = ec; @@ -477,15 +477,15 @@ class sort_sfaces : public SNC_decorator { } CGAL_NEF_TRACEN(" sface 2"); - + SHalfedge_handle se2; SHalfloop_handle sl2; CGAL_forall_sface_cycles_of(fc,sf2) { if(fc.is_shalfedge()) { SHalfedge_handle se(fc); SHalfedge_around_sface_circulator ec(se),ee(se); - CGAL_For_all(ec,ee) { - CGAL_NEF_TRACEN(" " << ec->source()->point() << + CGAL_For_all(ec,ee) { + CGAL_NEF_TRACEN(" " << ec->source()->point() << " | " << ec->circle().orthogonal_vector()); if(ml(ec, se2) == -1) se2 = ec; @@ -496,15 +496,15 @@ class sort_sfaces : public SNC_decorator { else CGAL_assertion(fc.is_svertex()); } - - CGAL_NEF_TRACEN(" sedge cycles existing? " << (se1 != SHalfedge_handle()) + + CGAL_NEF_TRACEN(" sedge cycles existing? " << (se1 != SHalfedge_handle()) << " , " << (se2 != SHalfedge_handle())); if(se1 != SHalfedge_handle() && se2 == SHalfedge_handle()) return true; if(se1 == SHalfedge_handle() && se2 != SHalfedge_handle()) - return false; - + return false; + if(se1 == SHalfedge_handle() && se2 == SHalfedge_handle()) { Vector_3 vec1 = sl1->circle().orthogonal_vector(); Vector_3 vec2 = sl2->circle().orthogonal_vector(); @@ -514,14 +514,14 @@ class sort_sfaces : public SNC_decorator { else if(vec1.y() != vec2.y()) return vec1.y() < vec2.y(); else if(vec1.z() != vec2.z()) - return vec1.z() < vec2.z(); + return vec1.z() < vec2.z(); } - + CGAL_assertion(se1 != SHalfedge_handle() && se2 != SHalfedge_handle()); - CGAL_NEF_TRACEN(" minimal sedge in sface 1:" << se1->source()->point() << + CGAL_NEF_TRACEN(" minimal sedge in sface 1:" << se1->source()->point() << " , " << se1->circle().orthogonal_vector()); - CGAL_NEF_TRACEN(" minimal sedge in sface 2:" << se2->source()->point() << + CGAL_NEF_TRACEN(" minimal sedge in sface 2:" << se2->source()->point() << " , " << se2->circle().orthogonal_vector()); CGAL_NEF_TRACEN("result " << ml(se1,se2)); switch(ml(se1, se2)) { @@ -535,19 +535,19 @@ class sort_sfaces : public SNC_decorator { template class sort_volumes : public SNC_decorator { - + typedef T SNC_structure; typedef CGAL::SNC_decorator Base; typedef typename T::Volume_handle Volume_handle; typedef typename T::SFace_handle SFace_handle; - + public: sort_volumes(T& D) : Base(D) {} - + bool operator() (Volume_handle c1, Volume_handle c2) const { CGAL_NEF_TRACEN("sort volumes"); - SFace_handle sf1 = SFace_handle(c1->shells_begin()); - SFace_handle sf2 = SFace_handle(c2->shells_begin()); + SFace_handle sf1 = SFace_handle(c1->shells_begin()); + SFace_handle sf2 = SFace_handle(c2->shells_begin()); sort_sfaces SORT(*this->sncp()); return SORT(sf1, sf2); @@ -556,7 +556,7 @@ class sort_volumes : public SNC_decorator { template class sort_facet_cycle_entries : public T { - + typedef typename T::SNC_structure SNC_structure; typedef typename T::SM_decorator SM_decorator; typedef typename T::Object_handle Object_handle; @@ -565,21 +565,21 @@ class sort_facet_cycle_entries : public T { typedef typename T::SFace_handle SFace_handle; typedef typename T::Point_3 Point_3; typedef typename T::Vector_3 Vector_3; - + public: sort_facet_cycle_entries(T D) : T(D) {} - + bool operator() (Object_handle o1, Object_handle o2) const { - + SHalfedge_handle se1, se2; SHalfloop_handle sl1, sl2; - + if(!CGAL::assign(se1,o1) && !CGAL::assign(sl1,o1)) CGAL_error_msg("wrong handle"); - + if(!CGAL::assign(se2,o2) && !CGAL::assign(sl2,o2)) - CGAL_error_msg("wrong handle"); - + CGAL_error_msg("wrong handle"); + if(se1 != SHalfedge_handle() && se2 != SHalfedge_handle()) { sort_vertices SORT(*this->sncp()); return SORT(se1->source()->source(), se2->source()->source()); @@ -590,7 +590,7 @@ class sort_facet_cycle_entries : public T { if(se2 != SHalfedge_handle()) return false; - CGAL_assertion(sl1 != SHalfloop_handle() && + CGAL_assertion(sl1 != SHalfloop_handle() && sl2 != SHalfloop_handle()); SM_decorator SD(&*sl1->incident_sface()->center_vertex()); @@ -602,21 +602,21 @@ class sort_facet_cycle_entries : public T { else if(vec1.y() != vec2.y()) return vec1.y() < vec2.y(); else - return vec1.z() < vec2.z(); + return vec1.z() < vec2.z(); } }; template class sort_shell_entries : public T { - + typedef typename T::Object_handle Object_handle; typedef typename T::Shell_entry_iterator Shell_entry_iterator; typedef typename T::SFace_handle SFace_handle; typedef typename T::Point_3 Point_3; - + public: sort_shell_entries(T D) : T(D) {} - + bool operator() (Object_handle o1, Object_handle o2) const { SFace_handle sf1, sf2; CGAL::assign(sf1, o1); @@ -632,7 +632,7 @@ class sort_shell_entries : public T { template struct find_minimal_sface_of_shell : public SNC_decorator { - + typedef T SNC_structure; typedef CGAL::SNC_decorator Base; typedef typename T::Vertex_handle Vertex_handle; @@ -646,11 +646,11 @@ struct find_minimal_sface_of_shell : public SNC_decorator { SFace_visited_hash& Done; SFace_handle sf_min; sort_sfaces SORT; - - find_minimal_sface_of_shell(T& D, SFace_visited_hash& Vi) + + find_minimal_sface_of_shell(T& D, SFace_visited_hash& Vi) : Base(D), Done(Vi), SORT(D) {} - - void visit(SFace_handle h) { + + void visit(SFace_handle h) { Done[h]=true; if(sf_min == SFace_handle()) sf_min = h; @@ -659,7 +659,7 @@ struct find_minimal_sface_of_shell : public SNC_decorator { sf_min = h; } } - + void visit(Vertex_handle ) {} void visit(Halfedge_handle ) {} void visit(Halffacet_handle ) {} @@ -884,32 +884,32 @@ class SNC_io_parser : public SNC_decorator typedef typename SNC_structure::Infi_box Infi_box; typedef typename Infi_box::Standard_kernel Standard_kernel; public: - typedef typename SNC_structure::Vertex_iterator Vertex_iterator; + typedef typename SNC_structure::Vertex_iterator Vertex_iterator; typedef typename SNC_structure::Vertex_handle Vertex_handle; - typedef typename SNC_structure::Halfedge_iterator Halfedge_iterator; + typedef typename SNC_structure::Halfedge_iterator Halfedge_iterator; typedef typename SNC_structure::Halfedge_handle Halfedge_handle; - typedef typename SNC_structure::Halffacet_iterator Halffacet_iterator; + typedef typename SNC_structure::Halffacet_iterator Halffacet_iterator; typedef typename SNC_structure::Halffacet_handle Halffacet_handle; - typedef typename SNC_structure::Volume_iterator Volume_iterator; + typedef typename SNC_structure::Volume_iterator Volume_iterator; typedef typename SNC_structure::Volume_handle Volume_handle; - typedef typename SNC_structure::SVertex_iterator SVertex_iterator; + typedef typename SNC_structure::SVertex_iterator SVertex_iterator; typedef typename SNC_structure::SVertex_handle SVertex_handle; - typedef typename SNC_structure::SHalfedge_iterator SHalfedge_iterator; + typedef typename SNC_structure::SHalfedge_iterator SHalfedge_iterator; typedef typename SNC_structure::SHalfedge_handle SHalfedge_handle; - typedef typename SNC_structure::SFace_iterator SFace_iterator; + typedef typename SNC_structure::SFace_iterator SFace_iterator; typedef typename SNC_structure::SFace_handle SFace_handle; - typedef typename SNC_structure::SHalfloop_iterator SHalfloop_iterator; + typedef typename SNC_structure::SHalfloop_iterator SHalfloop_iterator; typedef typename SNC_structure::SHalfloop_handle SHalfloop_handle; - typedef typename SNC_structure::Object_iterator Object_iterator; + typedef typename SNC_structure::Object_iterator Object_iterator; typedef typename SNC_structure::Object_handle Object_handle; typedef typename SNC_structure::SFace_cycle_iterator SFace_cycle_iterator; typedef typename SNC_structure::Halffacet_cycle_iterator Halffacet_cycle_iterator; typedef typename SNC_structure::Shell_entry_iterator Shell_entry_iterator; - typedef typename SNC_structure::SHalfedge_around_svertex_circulator + typedef typename SNC_structure::SHalfedge_around_svertex_circulator SHalfedge_around_svertex_circulator; - typedef typename SNC_structure::SHalfedge_around_sface_circulator + typedef typename SNC_structure::SHalfedge_around_sface_circulator SHalfedge_around_sface_circulator; - typedef typename SNC_structure::SHalfedge_around_facet_circulator + typedef typename SNC_structure::SHalfedge_around_facet_circulator SHalfedge_around_facet_circulator; typedef typename SNC_structure::Point_3 Point_3; typedef typename SNC_structure::Plane_3 Plane_3; @@ -939,7 +939,7 @@ public: bool sorted; bool addInfiBox; - CGAL::Object_index VI; + CGAL::Object_index VI; CGAL::Object_index EI; CGAL::Object_index FI; CGAL::Object_index CI; @@ -957,7 +957,7 @@ public: std::vector Edge_of; std::vector Halffacet_of; std::vector Volume_of; - std::vector SVertex_of; + std::vector SVertex_of; std::vector SEdge_of; std::vector SLoop_of; std::vector SFace_of; @@ -965,22 +965,22 @@ public: public: SNC_io_parser(std::istream& is, SNC_structure& W); - SNC_io_parser(std::ostream& os, SNC_structure& W, + SNC_io_parser(std::ostream& os, SNC_structure& W, bool sort=false, bool reduce_ = false); std::string index(Vertex_iterator v) const - { return VI(v,verbose); } - std::string index(Halfedge_iterator e) const + { return VI(v,verbose); } + std::string index(Halfedge_iterator e) const { return EI(e,verbose); } - std::string index(Halffacet_iterator f) const + std::string index(Halffacet_iterator f) const { return FI(f,verbose); } - std::string index(Volume_iterator c) const + std::string index(Volume_iterator c) const { return CI(c,verbose); } - std::string index(SHalfedge_iterator e) const + std::string index(SHalfedge_iterator e) const { return SEI(e,verbose); } - std::string index(SHalfloop_iterator l) const + std::string index(SHalfloop_iterator l) const { return SLI(l,verbose); } - std::string index(SFace_iterator f) const + std::string index(SFace_iterator f) const { return SFI(f,verbose); } std::string index(Object_iterator o) const { if( o == 0 ) @@ -1050,44 +1050,44 @@ public: }; template -SNC_io_parser::SNC_io_parser(std::istream& is, SNC_structure& W) : - Base(W), in(is), out(std::cout) { +SNC_io_parser::SNC_io_parser(std::istream& is, SNC_structure& W) : + Base(W), in(is), out(std::cout) { W.clear(); CGAL_assertion(W.is_empty()); - verbose = false; + verbose = false; } template -SNC_io_parser::SNC_io_parser(std::ostream& os, SNC_structure& W, - bool sort, bool reduce_) : +SNC_io_parser::SNC_io_parser(std::ostream& os, SNC_structure& W, + bool sort, bool reduce_) : Base(W), in(std::cin), out(os), FI(W.halffacets_begin(),W.halffacets_end(),'F'), CI(W.volumes_begin(),W.volumes_end(),'C'), SEI(W.shalfedges_begin(),W.shalfedges_end(),'e'), SLI(W.shalfloops_begin(),W.shalfloops_end(),'l'), SFI(W.sfaces_begin(),W.sfaces_end(),'f'), - vn(W.number_of_vertices()), - en(W.number_of_halfedges()), + vn(W.number_of_vertices()), + en(W.number_of_halfedges()), fn(W.number_of_halffacets()), cn(W.number_of_volumes()), sen(W.number_of_shalfedges()), sln(W.number_of_shalfloops()), sfn(W.number_of_sfaces()) -{ - verbose = (out.iword(CGAL::IO::mode) != CGAL::IO::ASCII && - out.iword(CGAL::IO::mode) != CGAL::IO::BINARY); +{ + verbose = (get_mode(out) != CGAL::IO::ASCII && + get_mode(out) != CGAL::IO::BINARY); sorted = sort; reduce = reduce_; reduce = reduce && this->is_extended_kernel() && this->is_bounded(); sorted = sorted || reduce; - Vertex_iterator vi; + Vertex_iterator vi; CGAL_forall_vertices(vi, *this->sncp()) { VL.push_back(vi); if(sorted) { vi->point() = normalized(vi->point()); - if(vi->has_shalfloop() && + if(vi->has_shalfloop() && sort_sloops(*this->sncp())(vi->shalfloop()->twin(), vi->shalfloop())) vi->shalfloop() = vi->shalfloop()->twin(); @@ -1095,7 +1095,7 @@ SNC_io_parser::SNC_io_parser(std::ostream& os, SNC_structure& W, } if(sorted) { VL.sort(sort_vertices(*this->sncp())); - } + } if(reduce) for(int k=0; k<4; k++){ VL.pop_front(); VL.pop_back(); @@ -1104,9 +1104,9 @@ SNC_io_parser::SNC_io_parser(std::ostream& os, SNC_structure& W, typename std::list::iterator vl; for(vl = VL.begin(); vl != VL.end(); vl++) VI[*vl] = i++; - + SM_decorator SD; - Halfedge_iterator ei; + Halfedge_iterator ei; CGAL_forall_halfedges(ei, *this->sncp()) { EL.push_back(ei); if(sorted) { @@ -1133,12 +1133,12 @@ SNC_io_parser::SNC_io_parser(std::ostream& os, SNC_structure& W, for(el = EL.begin(); el != EL.end(); el++) EI[*el] = i++; - Halffacet_iterator fi; + Halffacet_iterator fi; CGAL_forall_halffacets(fi, *this->sncp()){ if(sorted) { sort_sedges sortSE(*this->sncp()); Halffacet_cycle_iterator fc; - for(fc = fi->facet_cycles_begin(); + for(fc = fi->facet_cycles_begin(); fc != fi->facet_cycles_end(); ++fc) { if(fc.is_shalfedge()) { SHalfedge_handle se(fc); @@ -1170,7 +1170,7 @@ SNC_io_parser::SNC_io_parser(std::ostream& os, SNC_structure& W, for(fl = FL.begin(); fl != FL.end(); fl++) FI[*fl] = i++; - SHalfedge_iterator sei; + SHalfedge_iterator sei; CGAL_forall_shalfedges(sei, *this->sncp()) { SEL.push_back(sei); if(sorted) @@ -1186,7 +1186,7 @@ SNC_io_parser::SNC_io_parser(std::ostream& os, SNC_structure& W, for(sel = SEL.begin(); sel != SEL.end(); sel++) SEI[*sel] = i++; - SHalfloop_iterator sli; + SHalfloop_iterator sli; CGAL_forall_shalfloops(sli, *this->sncp()) { SLL.push_back(sli); if(sorted) @@ -1198,7 +1198,7 @@ SNC_io_parser::SNC_io_parser(std::ostream& os, SNC_structure& W, for(sll = SLL.begin(); sll != SLL.end(); sll++) SLI[*sll] = i++; - SFace_iterator sfi; + SFace_iterator sfi; CGAL_forall_sfaces(sfi, *this->sncp()) { if(sorted) { SFace_cycle_iterator fc; @@ -1214,7 +1214,7 @@ SNC_io_parser::SNC_io_parser(std::ostream& os, SNC_structure& W, se->source()->twin()->source()->point())) se = cb; } - else + else if(lexicographically_xyz_smaller(cb->twin()->source()->twin()->source()->point(), se->twin()->source()->twin()->source()->point())) se = cb; @@ -1237,7 +1237,7 @@ SNC_io_parser::SNC_io_parser(std::ostream& os, SNC_structure& W, for(sfl = SFL.begin(); sfl != SFL.end(); sfl++) SFI[*sfl] = i++; - Volume_iterator ci; + Volume_iterator ci; CGAL::Unique_hash_map Done(false); find_minimal_sface_of_shell findMinSF(*this->sncp(),Done); CGAL_forall_volumes(ci, *this->sncp()) { @@ -1249,10 +1249,10 @@ SNC_io_parser::SNC_io_parser(std::ostream& os, SNC_structure& W, *it = make_object(findMinSF.minimal_sface()); } ci->shell_entry_objects().sort(sort_shell_entries((Base)*this)); - } + } CL.push_back(ci); } - + if(sorted) CL.sort(sort_volumes(*this->sncp())); if(reduce) CL.pop_front(); @@ -1273,9 +1273,9 @@ SNC_io_parser::SNC_io_parser(std::ostream& os, SNC_structure& W, template bool SNC_io_parser::check_sep(const char* sep) const { - char c; + char c; do in.get(c); while (isspace(c)); - while (*sep != '\0') { + while (*sep != '\0') { if (*sep != c) { in.putback(c); return false; @@ -1283,7 +1283,7 @@ bool SNC_io_parser::check_sep(const char* sep) const ++sep; in.get(c); } in.putback(c); - return true; + return true; } template @@ -1295,7 +1295,7 @@ bool SNC_io_parser::test_string(std::string s) const { template void SNC_io_parser::print() const -{ +{ out << "Selective Nef Complex" << std::endl; if(this->is_extended_kernel() && (!reduce || !this->is_bounded())) out << "extended" << std::endl; @@ -1309,46 +1309,46 @@ void SNC_io_parser::print() const out << "shalfloops " << SLL.size() << std::endl; out << "sfaces " << SFL.size() << std::endl; - if (verbose) + if (verbose) out << "/* Vertex: index { svs sve ses see sfs sfe sl," << " mark, point } */\n"; typename std::list::const_iterator v; for(v=VL.begin();v!=VL.end();v++) print_vertex(*v); - if (verbose) + if (verbose) out << "/* Edge: index { twin, source, isolated incident_object," << " mark } */\n"; typename std::list::const_iterator e; for(e=EL.begin();e!=EL.end();e++) print_edge(*e); - if (verbose) + if (verbose) out << "/* Facet: index { twin, fclist, ivlist, volume | plane } mark */\n"; typename std::list::const_iterator f; for(f=FL.begin();f!=FL.end();f++) print_facet(*f); - if (verbose) + if (verbose) out << "/* Volume: index { shlist } mark */\n"; typename std::list::const_iterator c; for(c=CL.begin();c!=CL.end();c++) print_volume(*c); - if (verbose) + if (verbose) out << "/* SEdge: index { twin, sprev, snext, source, sface," << " prev, next, facet } */\n"; typename std::list::const_iterator se; for(se=SEL.begin();se!=SEL.end();se++) print_sedge(*se); - if (verbose) + if (verbose) out << "/* SLoop: index { twin, sface, facet } */" << std::endl; typename std::list::const_iterator sl; for(sl=SLL.begin();sl!=SLL.end();sl++) print_sloop(*sl); - if (verbose) + if (verbose) out << "/* SFace: index { fclist, ivlist, sloop, volume } */" << std::endl; typename std::list::const_iterator sf; for(sf=SFL.begin();sf!=SFL.end();sf++) @@ -1359,13 +1359,13 @@ void SNC_io_parser::print() const template void SNC_io_parser::read() -{ - if ( !check_sep("Selective Nef Complex") ) +{ + if ( !check_sep("Selective Nef Complex") ) CGAL_error_msg("SNC_io_parser::read: no SNC header."); std::string kernel_type; in >> kernel_type; CGAL_assertion(kernel_type == "standard" || kernel_type == "extended"); - if ( !(check_sep("vertices") && (in >> vn)) ) + if ( !(check_sep("vertices") && (in >> vn)) ) CGAL_error_msg("SNC_io_parser::read: wrong vertex line."); if ( !(check_sep("halfedges") && (in >> en) && (en%2==0)) ) CGAL_error_msg("SNC_io_parser::read: wrong edge line."); @@ -1407,13 +1407,13 @@ void SNC_io_parser::read_items(int plus01) { if (!read_vertex(*vi)) CGAL_error_msg("SNC_io_parser::read: error in node line"); } - + typename std::vector::iterator ei; for(ei=Edge_of.begin(); ei!=Edge_of.end(); ++ei) { if (!read_edge(*ei)) CGAL_error_msg("SNC_io_parser::read: error in edge line"); } - + typedef typename std::vector::iterator vhf_iterator; vhf_iterator fi; for(fi=Halffacet_of.begin(); fi!=Halffacet_of.end(); ++fi) { @@ -1442,7 +1442,7 @@ void SNC_io_parser::read_items(int plus01) { } SNC_constructor C(*this->sncp()); - C.assign_indices(); + C.assign_indices(); } @@ -1452,17 +1452,17 @@ void SNC_io_parser::print_vertex(Vertex_handle v) const SM_decorator SD(&*v); out << index(v) << " { "; if(sorted) { - - output_sorted_indexes(v->svertices_begin(), + + output_sorted_indexes(v->svertices_begin(), v->svertices_end(), EI); - output_sorted_indexes(v->shalfedges_begin(), + output_sorted_indexes(v->shalfedges_begin(), v->shalfedges_end(), SEI); - output_sorted_indexes(v->sfaces_begin(), + output_sorted_indexes(v->sfaces_begin(), v->sfaces_end(), SFI); out << index(SD.shalfloop()) << " | "; } else { - out + out << index(v->svertices_begin()) << " " << index(v->svertices_last()) << ", " << index(v->shalfedges_begin()) << " " @@ -1473,7 +1473,7 @@ void SNC_io_parser::print_vertex(Vertex_handle v) const } if(reduce) { Geometry_io:: - print_point(out, Infi_box::standard_point(v->point())); + print_point(out, Infi_box::standard_point(v->point())); } else Geometry_io::print_point(out, v->point()); @@ -1492,7 +1492,7 @@ read_vertex(Vertex_handle vh) { in >> index; OK = OK && test_string("{"); vh->sncp() = this->sncp(); - + in >> index; vh->svertices_begin() = (index >= 0 ? Edge_of[index] : this->svertices_end()); in >> index; @@ -1515,12 +1515,12 @@ read_vertex(Vertex_handle vh) { in >> hx >> hy >> hz >> hw; vh->point() = Point_3(hx,hy,hz,hw); #else - vh->point() = + vh->point() = Geometry_io::template read_point(in); #endif OK = OK && test_string("}"); in >> vh->mark(); - + return OK; } @@ -1536,7 +1536,7 @@ void SNC_io_parser::print_edge(Halfedge_handle e) const if(reduce) { Standard_point sp = Infi_box::standard_point(e->point()); Geometry_io:: - print_vector(out, sp-CGAL::ORIGIN); + print_vector(out, sp-CGAL::ORIGIN); } else Geometry_io:: @@ -1557,10 +1557,10 @@ read_edge(Halfedge_handle eh) { bool OK = true; int index; typename K::RT hx,hy,hz,hw; - + in >> index; OK = OK && test_string("{"); - + in >> index; eh->twin() = Edge_of[index]; OK = OK && test_string(","); @@ -1571,7 +1571,7 @@ read_edge(Halfedge_handle eh) { if(index == 0) { in >> index; eh->out_sedge() = SEdge_of[index]; - } else { + } else { in >> index; eh->incident_sface() = SFace_of[index]; } @@ -1580,7 +1580,7 @@ read_edge(Halfedge_handle eh) { in >> hx >> hy >> hz >> hw; eh->point() = Sphere_point(hx,hy,hz); #else - eh->point() = + eh->point() = Geometry_io::template read_point(in); #endif OK = OK && test_string("}"); @@ -1592,9 +1592,9 @@ read_edge(Halfedge_handle eh) { template void SNC_io_parser::print_facet(Halffacet_handle f) const { // syntax: index { twin, fclist, ivlist, volume | plane } mark - out << index(f) << " { "; + out << index(f) << " { "; out << index(f->twin()) << ", "; - Halffacet_cycle_iterator it; + Halffacet_cycle_iterator it; CGAL_forall_facet_cycles_of(it,f) if ( it.is_shalfedge() ) out << index(SHalfedge_handle(it)) << ' '; out << ", "; @@ -1623,11 +1623,11 @@ read_facet(Halffacet_handle fh) { in >> index; OK = OK && test_string("{"); - + in >> index; fh->twin() = Halffacet_of[index]; OK = OK && test_string(","); - + in >> cc; while(isdigit(cc)) { in.putback(cc); @@ -1635,7 +1635,7 @@ read_facet(Halffacet_handle fh) { fh->boundary_entry_objects().push_back(make_object(SEdge_of[index])); in >> cc; } - + in >> cc; while(isdigit(cc)) { in.putback(cc); @@ -1643,7 +1643,7 @@ read_facet(Halffacet_handle fh) { fh->boundary_entry_objects().push_back(make_object(SLoop_of[index])); in >> cc; } - + in >> index; fh->incident_volume() = Volume_of[index+addInfiBox]; OK = OK && test_string("|"); @@ -1651,7 +1651,7 @@ read_facet(Halffacet_handle fh) { in >> a >> b >> c >> d; fh->plane() = Plane_3(a,b,c,d); #else - fh->plane() = + fh->plane() = Geometry_io:: template read_plane(in); #endif @@ -1664,9 +1664,9 @@ read_facet(Halffacet_handle fh) { template void SNC_io_parser::print_volume(Volume_handle c) const { // syntax: index { shlist } mark - out << index(c) << " { "; + out << index(c) << " { "; Shell_entry_iterator it; - CGAL_forall_shells_of(it,c) + CGAL_forall_shells_of(it,c) if(!reduce || Infi_box::is_standard(SFace_handle(it)->center_vertex()->point())) out << index(SFace_handle(it)) << ' '; out << "} " << c->mark() << std::endl; @@ -1679,10 +1679,10 @@ read_volume(Volume_handle ch) { bool OK = true; int index; char cc; - + in >> index; OK = OK && test_string("{"); - + in >> cc; while(isdigit(cc)) { in.putback(cc); @@ -1697,14 +1697,14 @@ read_volume(Volume_handle ch) { template void SNC_io_parser:: -print_sedge(SHalfedge_handle e) const { +print_sedge(SHalfedge_handle e) const { //index { twin, sprev, snext, source, sface, prev, next, facet | circle } mark out << index(e) << " { " - << index(e->twin()) << ", " + << index(e->twin()) << ", " << index(e->sprev()) << ", " << index(e->snext()) << ", " << index(e->source()) << ", " << index(e->incident_sface()) << ", " << index(e->prev()) << ", " << index(e->next()) << ", " - << index(e->facet()) + << index(e->facet()) << " | "; if(reduce) { Geometry_io:: @@ -1716,9 +1716,9 @@ print_sedge(SHalfedge_handle e) const { out << " } " << e->mark(); #ifdef CGAL_NEF_OUTPUT_INDEXES - out << " " << e->get_forward_index() + out << " " << e->get_forward_index() << " " << e->get_backward_index(); -#endif +#endif out << std::endl; } @@ -1730,10 +1730,10 @@ read_sedge(SHalfedge_handle seh) { bool OK = true; int index; typename K::RT a,b,c,d; - + in >> index; OK = OK && test_string("{"); - + in >> index; seh->twin() = SEdge_of[index]; OK = OK && test_string(","); @@ -1762,7 +1762,7 @@ read_sedge(SHalfedge_handle seh) { in >> a >> b >> c >> d; seh->circle() = Sphere_circle(Plane_3(a,b,c,d)); #else - seh->circle() = + seh->circle() = Geometry_io:: template read_plane(in); #endif @@ -1778,8 +1778,8 @@ print_sloop(SHalfloop_handle l) const { // syntax: index { twin, sface, facet | circle } mark out << index(l) << " { " << index(l->twin()) << ", " << index(l->incident_sface()) << ", " - << index(l->facet()) - << " | "; + << index(l->facet()) + << " | "; if(reduce) { Geometry_io:: print_plane(out, Infi_box::standard_plane(l->circle())); @@ -1802,7 +1802,7 @@ read_sloop(SHalfloop_handle slh) { in >> index; OK = OK && test_string("{"); - + in >> index; slh->twin() = SLoop_of[index]; OK = OK && test_string(","); @@ -1811,18 +1811,18 @@ read_sloop(SHalfloop_handle slh) { OK = OK && test_string(","); in >> index; slh->facet() = Halffacet_of[index]; - OK = OK && test_string("|"); + OK = OK && test_string("|"); #ifdef CGAL_NEF_NATURAL_COORDINATE_INPUT in >> a >> b >> c >> d; slh->circle() = Sphere_circle(Plane_3(a,b,c,d)); #else slh->circle() = Geometry_io:: - template read_plane(in); + template read_plane(in); #endif - OK = OK && test_string("}"); + OK = OK && test_string("}"); in >> slh->mark(); - + return OK; } @@ -1831,7 +1831,7 @@ void SNC_io_parser:: print_sface(SFace_handle f) const { // syntax: index { vertex, fclist, ivlist, sloop, volume } SM_decorator D(&*f->center_vertex()); - out << index(f) << " { " << index(f->center_vertex()) << ", "; + out << index(f) << " { " << index(f->center_vertex()) << ", "; SFace_cycle_iterator it; CGAL_forall_sface_cycles_of(it,f) if ( it.is_shalfedge() ) out << index(SHalfedge_handle(it)) << ' '; @@ -1854,11 +1854,11 @@ read_sface(SFace_handle sfh) { in >> index; OK = OK && test_string("{"); - + in >> index; sfh->center_vertex() = Vertex_of[index]; OK = OK && test_string(","); - + in >> cc; while(isdigit(cc)) { in.putback(cc); @@ -1868,7 +1868,7 @@ read_sface(SFace_handle sfh) { SD.link_as_face_cycle(SEdge_of[index],sfh); in >> cc; } - + in >> cc; while(isdigit(cc)) { in.putback(cc); @@ -1886,36 +1886,36 @@ read_sface(SFace_handle sfh) { this->sncp()->store_sm_boundary_item(SLoop_of[index], --(sfh->sface_cycles_end())); in >> cc; } - + in >> index; sfh->volume() = Volume_of[index+addInfiBox]; - OK = OK && test_string("}"); + OK = OK && test_string("}"); in >> sfh->mark(); - + return OK; } template void SNC_io_parser::print_local_graph(Vertex_handle v) const { SM_decorator D(&*v); - out << "Local Graph " + out << "Local Graph " << D.number_of_vertices() << " " << D.number_of_edges() << " " << D.number_of_loops() << " " << D.number_of_faces() << " " << std::endl; - if (verbose) + if (verbose) out << "/* index { twin, source, isolated incident_object, mark } */\n"; SVertex_iterator vit; CGAL_forall_svertices_of(vit,v) print_edge(vit); - if (verbose) + if (verbose) out << "/* index { twin, sprev, snext, source, sface," << " prev, next, facet } */\n"; SHalfedge_iterator eit; CGAL_forall_shalfedges_of(eit,v) print_sedge(eit); - if (verbose) + if (verbose) out << "/* index { twin, sface, facet } */" << std::endl; - if ( D.has_sloop() ) + if ( D.has_sloop() ) { print_sloop(D.loop()); print_sloop(twin(D.loop())); } - if (verbose) + if (verbose) out << "/* index { fclist, ivlist, sloop, volume } */" << std::endl; SFace_iterator fit; CGAL_forall_sfaces_of(fit,v) print_sface(fit); @@ -1945,10 +1945,10 @@ void SNC_io_parser::add_infi_box() { hy = i % 4 > 1 ? -1 : 1; hz = i > 3 ? -1 : 1; vh->point() = Infi_box::create_extended_point(hx, hy, hz); - vh->mark() = 1; + vh->mark() = 1; vh->sncp() = this->sncp(); } - + int seOff[3] = {0, 1, 3}; int twinIdx[24] = { 3, 7,14, 0,10,17, @@ -1958,14 +1958,14 @@ void SNC_io_parser::add_infi_box() { 12,22, 5, 21,13, 8, 18,16,11}; - + for(int i = 0; i < 24; ++i) { Halfedge_handle eh = Edge_of[en+i]; eh->twin() = Edge_of[en+twinIdx[i]]; eh->center_vertex() = Vertex_of[vn+(i/3)]; eh->out_sedge() = SEdge_of[sen+(i/3*6)+seOff[i%3]]; switch(i%3) { - case 0 : + case 0 : hx = i % 6 ? 1 : -1; hy = hz = 0; break; @@ -1981,7 +1981,7 @@ void SNC_io_parser::add_infi_box() { eh->point() = Sphere_point(hx,hy,hz); eh->mark() = 1; } - + int bnd[12] = {19, 18, 43, 42, 35, 34, 47, 46, 39, 38, 45, 44}; for(int i = 0; i < 12; ++i) { @@ -2005,11 +2005,11 @@ void SNC_io_parser::add_infi_box() { fh->plane() = Infi_box::create_extended_plane(hx,hy,hz,hw); fh->mark() = 1; } - + Volume_of[0]->shell_entry_objects().push_back(make_object(SFace_of[sfn])); Volume_of[0]->mark() = 0; Volume_of[1]->shell_entry_objects().push_front(make_object(SFace_of[sfn+1])); - + int sprevOff[6] = {4,3,0,5,2,1}; int snextOff[6] = {2,5,4,1,0,3}; int prevIdx[48] = {7,12,15,26,29,10, @@ -2040,10 +2040,10 @@ void SNC_io_parser::add_infi_box() { -1,-1,1,1,-1,-1, 1,-1,-1,-1,-1,1, -1,1,-1,1,1,1}; - + for(int i = 0; i < 48; ++i) { SHalfedge_handle seh = SEdge_of[sen+i]; - + seh->twin() = SEdge_of[sen+(i/2*2)+((i+1)%2)]; seh->sprev() = SEdge_of[sen+sprevOff[i%6]+(i/6*6)]; seh->snext() = SEdge_of[sen+snextOff[i%6]+(i/6*6)]; @@ -2067,14 +2067,14 @@ void SNC_io_parser::add_infi_box() { seh->circle() = Sphere_circle(Plane_3(RT(hx),RT(hy),RT(hz),RT(0))); seh->mark() = 1; } - + int volIdx[8] = {0,1,1,0,1,0,0,1}; - + for(int i = 0; i < 16; ++i) { SFace_handle sfh = SFace_of[sfn+i]; sfh->center_vertex() = Vertex_of[vn+(i/2)]; sfh->boundary_entry_objects().push_back(make_object(SEdge_of[sen+(i/2*6)+(i%2)])); - this->sncp()->store_sm_boundary_item(SEdge_of[sen+(i/2*6)+(i%2)], + this->sncp()->store_sm_boundary_item(SEdge_of[sen+(i/2*6)+(i%2)], --(sfh->sface_cycles_end())); int cIdx = i%2 ? 1-volIdx[i/2] : volIdx[i/2]; sfh->volume() = Volume_of[cIdx]; diff --git a/Nef_S2/include/CGAL/Nef_S2/SM_io_parser.h b/Nef_S2/include/CGAL/Nef_S2/SM_io_parser.h index a47380fa3e5..059cc498b30 100644 --- a/Nef_S2/include/CGAL/Nef_S2/SM_io_parser.h +++ b/Nef_S2/include/CGAL/Nef_S2/SM_io_parser.h @@ -157,8 +157,8 @@ SM_io_parser(std::ostream& iout, const Base& D) en(this->number_of_shalfedges()), ln(this->number_of_shalfloops()), fn(this->number_of_sfaces()) -{ verbose = (out.iword(CGAL::IO::mode) != CGAL::IO::ASCII && - out.iword(CGAL::IO::mode) != CGAL::IO::BINARY); +{ verbose = (get_mode(out) != CGAL::IO::ASCII && + get_mode(out) != CGAL::IO::BINARY); } diff --git a/Number_types/include/CGAL/CORE_BigFloat.h b/Number_types/include/CGAL/CORE_BigFloat.h index 48e2dffabd7..2488af7d00d 100644 --- a/Number_types/include/CGAL/CORE_BigFloat.h +++ b/Number_types/include/CGAL/CORE_BigFloat.h @@ -251,7 +251,7 @@ namespace internal{ CORE::BigFloat inline -round(const CORE::BigFloat& x, long rel_prec = CORE::defRelPrec.toLong() ){ +round(const CORE::BigFloat& x, long rel_prec = CORE::get_static_defRelPrec().toLong() ){ CGAL_postcondition(rel_prec >= 0); // since there is not rel prec defined if Zero_in(x) @@ -344,9 +344,9 @@ public: typedef long result_type; long operator() ( long prec ) const { - long result = ::CORE::defRelPrec.toLong(); - ::CORE::defRelPrec = prec; - ::CORE::defBFdivRelPrec = prec; + long result = ::CORE::get_static_defRelPrec().toLong(); + ::CORE::get_static_defRelPrec() = prec; + ::CORE::get_static_defBFdivRelPrec() = prec; return result; } }; @@ -356,7 +356,7 @@ public: typedef long result_type; long operator() () const { - return ::CORE::defRelPrec.toLong(); + return ::CORE::get_static_defRelPrec().toLong(); } }; }; @@ -378,17 +378,19 @@ template <> class Algebraic_structure_traits< CORE::BigFloat > : public std::unary_function< Type, Type > { public: Type operator()( const Type& x ) const { - // What I want is a sqrt computed with ::CORE::defRelPrec bits. + // What I want is a sqrt computed with + // ::CORE::get_static_defRelPrec() bits. // And not ::CORE::defBFsqrtAbsPrec as CORE does. - CGAL_precondition(::CORE::defRelPrec.toLong() > 0); + CGAL_precondition(::CORE::get_static_defRelPrec().toLong() > 0); CGAL_precondition(x > 0); - Type a = CGAL::internal::round(x, ::CORE::defRelPrec.toLong()*2); + Type a = CGAL::internal::round( + x, ::CORE::get_static_defRelPrec().toLong()*2); CGAL_postcondition(a > 0); - Type tmp1 = - CORE::BigFloat(a.m(),0,0).sqrt(::CORE::defRelPrec.toLong()); + Type tmp1 = CORE::BigFloat( + a.m(),0,0).sqrt(::CORE::get_static_defRelPrec().toLong()); Type err = Type(0,long(std::sqrt(double(a.err()))),0) * CORE::BigFloat::exp2(a.exp()*7); diff --git a/Number_types/include/CGAL/CORE_coercion_traits.h b/Number_types/include/CGAL/CORE_coercion_traits.h index d097ffcc6f1..d1ebbc69b72 100644 --- a/Number_types/include/CGAL/CORE_coercion_traits.h +++ b/Number_types/include/CGAL/CORE_coercion_traits.h @@ -84,7 +84,7 @@ struct Coercion_traits{ Type operator()(const CORE::BigFloat& x) const { return x;} Type operator()(const ::CORE::BigInt x) const { CORE::BigFloat result; - result.approx(x,CORE::defRelPrec.toLong(),LONG_MAX); + result.approx(x,CORE::get_static_defRelPrec().toLong(),LONG_MAX); // Do not use MakeFloorExact as it changes the Bigfloat CGAL_postcondition( ::CORE::BigRat(::CORE::BigFloat(result.m()-result.err(),0,result.exp())) <= x ); CGAL_postcondition( ::CORE::BigRat(::CORE::BigFloat(result.m()+result.err(),0,result.exp())) >= x ); @@ -104,7 +104,7 @@ struct Coercion_traits{ Type operator()(const CORE::BigFloat& x) const { return x;} Type operator()(const ::CORE::BigRat x) const { - CORE::BigFloat result(x,CORE::defRelPrec.toLong(),LONG_MAX); + CORE::BigFloat result(x,CORE::get_static_defRelPrec().toLong(),LONG_MAX); // Do not use MakeFloorExact as it changes the Bigfloat CGAL_postcondition( ::CORE::BigRat(::CORE::BigFloat(result.m()-result.err(),0,result.exp())) <= x ); CGAL_postcondition( ::CORE::BigRat(::CORE::BigFloat(result.m()+result.err(),0,result.exp())) >= x ); @@ -123,7 +123,7 @@ struct Coercion_traits{ typedef Type result_type; Type operator()(const CORE::BigFloat& x) const { return x;} Type operator()(const ::CORE::Expr x) const { - CORE::BigFloat result(x, CORE::defRelPrec.toLong(),LONG_MAX); + CORE::BigFloat result(x, CORE::get_static_defRelPrec().toLong(),LONG_MAX); // Do not use MakeFloorExact as it changes the Bigfloat CGAL_postcondition( ::CORE::BigRat(::CORE::BigFloat(result.m()-result.err(),0,result.exp())) <= x ); CGAL_postcondition( ::CORE::BigRat(::CORE::BigFloat(result.m()+result.err(),0,result.exp())) >= x ); diff --git a/Number_types/include/CGAL/FPU.h b/Number_types/include/CGAL/FPU.h index 1880d51533a..94bedba4765 100644 --- a/Number_types/include/CGAL/FPU.h +++ b/Number_types/include/CGAL/FPU.h @@ -1,9 +1,9 @@ -// Copyright (c) 1998-2008 +// Copyright (c) 1998-2008 // Utrecht University (The Netherlands), // ETH Zurich (Switzerland), // INRIA Sophia-Antipolis (France), // Max-Planck-Institute Saarbruecken (Germany), -// and Tel-Aviv University (Israel). All rights reserved. +// and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as @@ -66,7 +66,11 @@ extern "C" { # if defined CGAL_CFG_DENORMALS_COMPILE_BUG // For compilers crashing when dealing with denormalized values. // So we have to generate it at run time instead. +#ifdef CGAL_HEADER_ONLY +# define CGAL_IA_MIN_DOUBLE (CGAL::internal::get_static_minimin()) +#else # define CGAL_IA_MIN_DOUBLE (CGAL::internal::minimin) +#endif // CGAL_HEADER_ONLY # else # define CGAL_IA_MIN_DOUBLE (5e-324) # endif @@ -115,14 +119,22 @@ extern "C" { # define CGAL_USE_SSE2 1 #endif -namespace CGAL { - -namespace internal { - #ifdef CGAL_CFG_DENORMALS_COMPILE_BUG + +#ifdef CGAL_HEADER_ONLY +#include // To define get_static_minimin(); +#else // CGAL_HEADER_ONLY +namespace CGAL { +namespace internal { CGAL_EXPORT extern double minimin; +} +} +#endif // CGAL_HEADER_ONLY + #endif +namespace CGAL { +namespace internal { #ifdef __INTEL_COMPILER const double infinity = std::numeric_limits::infinity(); #else @@ -410,11 +422,27 @@ FPU_get_cw (void) return cw; } +} // namespace CGAL + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + +namespace CGAL { + +// User interface (cont): + inline void FPU_set_cw (FPU_CW_t cw) { - CGAL_IA_SETFPCW(cw); +#ifndef CGAL_NDEBUG +#ifdef CGAL_HEADER_ONLY + const Check_FPU_rounding_mode_is_restored & tmp = get_static_check_fpu_rounding_mode_is_restored(); +#endif +#endif + + CGAL_IA_SETFPCW(cw); } inline diff --git a/Number_types/include/CGAL/Interval_arithmetic_impl.h b/Number_types/include/CGAL/Interval_arithmetic_impl.h new file mode 100644 index 00000000000..1d0ed4710f1 --- /dev/null +++ b/Number_types/include/CGAL/Interval_arithmetic_impl.h @@ -0,0 +1,72 @@ +// Copyright (c) 1999-2004 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Sylvain Pion + +namespace CGAL { + +#ifdef CGAL_CFG_DENORMALS_COMPILE_BUG +// For compilers which bug on denormalized values at compile time. +// We generate CGAL_IA_MIN_DOUBLE at run time. +namespace { +double init_min_double() +{ + double d = 1; + double e = 1; + do { + d = e; + e = CGAL_IA_FORCE_TO_DOUBLE(e/2); + } while (e != 0); + return d; +} +} // anonymous namespace + +#ifndef CGAL_HEADER_ONLY + +namespace internal { +double minimin = init_min_double(); +} + +#else // CGAL_HEADER_ONLY + +namespace internal { + double& get_static_minimin() + { + static double minimin = init_min_double(); + return minimin; + } +} +#endif // CGAL_HEADER_ONLY + +#endif // CGAL_CFG_DENORMALS_COMPILE_BUG + +#ifndef CGAL_HEADER_ONLY + +#ifdef _MSC_VER +namespace { +int dummy_symbol_for_stopping_VC_linker_warning; +} // namespace +#endif + +#endif // CGAL_HEADER_ONLY + +} //namespace CGAL diff --git a/Number_types/include/CGAL/number_type_basic.h b/Number_types/include/CGAL/number_type_basic.h index bc71689703d..886ba274858 100644 --- a/Number_types/include/CGAL/number_type_basic.h +++ b/Number_types/include/CGAL/number_type_basic.h @@ -55,7 +55,6 @@ #include #include #include - #include #include #include diff --git a/Number_types/include/CGAL/test_FPU_rounding_mode_impl.h b/Number_types/include/CGAL/test_FPU_rounding_mode_impl.h new file mode 100644 index 00000000000..306330bd7dd --- /dev/null +++ b/Number_types/include/CGAL/test_FPU_rounding_mode_impl.h @@ -0,0 +1,70 @@ +// Copyright (c) 2008 GeometryFactory (France) +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Laurent Rineau + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#ifndef CGAL_NDEBUG + +#include +#include + +namespace CGAL { + +struct Check_FPU_rounding_mode_is_restored { + FPU_CW_t mode; + + Check_FPU_rounding_mode_is_restored() + : mode( FPU_get_cw()) {} + + ~Check_FPU_rounding_mode_is_restored() + { + CGAL_assertion_msg( FPU_get_cw() == mode, + "The default FPU rounding mode has not been restored " + " before the exit of the program. " + "That may be a bug in some CGAL kernel code."); + } +}; + +#ifdef CGAL_HEADER_ONLY + +inline const Check_FPU_rounding_mode_is_restored& get_static_check_fpu_rounding_mode_is_restored() +{ + static const Check_FPU_rounding_mode_is_restored check_fpu_rounding_mode_is_restored; + return check_fpu_rounding_mode_is_restored; +} + +#else + +// A global object that emits a warning if the rounding mode at the +// beginning and the end of the program are not the same. +static const Check_FPU_rounding_mode_is_restored check_fpu_rounding_mode_is_restored; + +inline const Check_FPU_rounding_mode_is_restored& get_static_check_fpu_rounding_mode_is_restored() +{ return check_fpu_rounding_mode_is_restored; } + +#endif // CGAL_HEADER_ONLY + +} // end namespace CGAL + +#endif // #ifnedef CGAL_NDEBUG diff --git a/Number_types/src/CGAL/Interval_arithmetic.cpp b/Number_types/src/CGAL/Interval_arithmetic.cpp index 50f643cdc7e..943b2f94cf2 100644 --- a/Number_types/src/CGAL/Interval_arithmetic.cpp +++ b/Number_types/src/CGAL/Interval_arithmetic.cpp @@ -22,36 +22,10 @@ // // Author(s) : Sylvain Pion +#ifndef CGAL_HEADER_ONLY + #include #include +#include -namespace CGAL { - -#ifdef CGAL_CFG_DENORMALS_COMPILE_BUG -// For compilers which bug on denormalized values at compile time. -// We generate CGAL_IA_MIN_DOUBLE at run time. -namespace { -double init_min_double() -{ - double d = 1; - double e = 1; - do { - d = e; - e = CGAL_IA_FORCE_TO_DOUBLE(e/2); - } while (e != 0); - return d; -} -} // anonymous namespace - -namespace internal { -double minimin = init_min_double(); -} #endif - -#ifdef _MSC_VER -namespace { -int dummy_symbol_for_stopping_VC_linker_warning; -} // namespace -#endif - -} //namespace CGAL diff --git a/Number_types/src/CGAL/test_FPU_rounding_mode.cpp b/Number_types/src/CGAL/test_FPU_rounding_mode.cpp index 8f347794db3..9821a5cadf5 100644 --- a/Number_types/src/CGAL/test_FPU_rounding_mode.cpp +++ b/Number_types/src/CGAL/test_FPU_rounding_mode.cpp @@ -18,34 +18,9 @@ // // Author(s) : Laurent Rineau -#ifndef CGAL_NDEBUG +#ifndef CGAL_HEADER_ONLY -#include #include -#include +#include -namespace CGAL { - - -struct Check_FPU_rounding_mode_is_restored { - FPU_CW_t mode; - - Check_FPU_rounding_mode_is_restored() - : mode( FPU_get_cw()) {} - - ~Check_FPU_rounding_mode_is_restored() - { - CGAL_assertion_msg( FPU_get_cw() == mode, - "The default FPU rounding mode has not been restored " - " before the exit of the program. " - "That may be a bug in some CGAL kernel code."); - } -}; - -// A global object that emits a warning if the rounding mode at the -// beginning and the end of the program are not the same. -static const Check_FPU_rounding_mode_is_restored check_fpu_rounding_mode_is_restored; - -} // end namespace CGAL - -#endif // #ifnedef CGAL_NDEBUG +#endif diff --git a/Number_types/test/Number_types/MP_Float.cpp b/Number_types/test/Number_types/MP_Float.cpp index 7705a86b451..a32503e5e48 100644 --- a/Number_types/test/Number_types/MP_Float.cpp +++ b/Number_types/test/Number_types/MP_Float.cpp @@ -19,7 +19,7 @@ typedef CGAL::Quotient QMPF; double non_zero_double(){ double d; do { - d = CGAL::default_random.get_double(); + d = CGAL::get_default_random().get_double(); if(d ==0) { std::cout << "generated zero" << std::endl; } @@ -130,7 +130,7 @@ void square_test() { for (int i = 0; i<1000; ++i) { - double d = CGAL::default_random.get_double(); + double d = CGAL::get_default_random().get_double(); MPF D(d); assert(D*D == CGAL_NTS square(D)); } @@ -274,8 +274,8 @@ int main(int argc, char **argv) std::cout << "Checking MP_Float(float) constructor." << std::endl; for (int i = 0; i < loops; ++i) { - float d = (float)CGAL::default_random.get_double(); - int exp = int((CGAL::default_random.get_double()-.5)*256); + float d = (float)CGAL::get_default_random().get_double(); + int exp = int((CGAL::get_default_random().get_double()-.5)*256); d = std::ldexp(d, exp); // std::cout << d << std::endl; // std::cout << MPF(d) << std::endl; @@ -289,8 +289,8 @@ int main(int argc, char **argv) std::cout << "Checking MP_Float(double) constructor." << std::endl; MPF y = 0.5000000000000001; // see bug-report on cgal-discuss (2006-06-23). for (int i = 0; i < loops; ++i) { - double d = CGAL::default_random.get_double(); - int exp = int((CGAL::default_random.get_double()-.5)*1024); + double d = CGAL::get_default_random().get_double(); + int exp = int((CGAL::get_default_random().get_double()-.5)*1024); d = std::ldexp(d, exp); // std::cout << d << std::endl; // std::cout << MPF(d) << std::endl; @@ -303,9 +303,9 @@ int main(int argc, char **argv) std::cout << "Checking MP_Float(long double) constructor." << std::endl; for (int i = 0; i < loops; ++i) { - long double d = CGAL::default_random.get_double(); + long double d = CGAL::get_default_random().get_double(); d = d*d; // to get more bits - int exp = int((CGAL::default_random.get_double()-.5)*1024); + int exp = int((CGAL::get_default_random().get_double()-.5)*1024); d = d * std::ldexp(1.0, exp); //std::cout << d << std::endl; //std::cout << MPF(d) << std::endl; diff --git a/Polygon/include/CGAL/Polygon_2/Polygon_2_impl.h b/Polygon/include/CGAL/Polygon_2/Polygon_2_impl.h index add348aad03..be890c5720e 100644 --- a/Polygon/include/CGAL/Polygon_2/Polygon_2_impl.h +++ b/Polygon/include/CGAL/Polygon_2/Polygon_2_impl.h @@ -116,7 +116,7 @@ operator<<(std::ostream &os, const Polygon_2& p) { typename Polygon_2::Vertex_const_iterator i; - switch(os.iword(IO::mode)) { + switch(get_mode(os)) { case IO::ASCII : os << p.size() << ' '; for (i = p.vertices_begin(); i != p.vertices_end(); ++i) { diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_remeshing_plugin_cgal_code.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_remeshing_plugin_cgal_code.cpp index 3d2397fa784..900cab6fbd9 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_remeshing_plugin_cgal_code.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_remeshing_plugin_cgal_code.cpp @@ -285,7 +285,7 @@ Scene_item* cgal_code_remesh(QWidget* parent, triangulation.dimension() < 3 ); n = triangulation.number_of_vertices()) { - const int pos = CGAL::default_random.get_int(0, (int)polyhedron_points.size()); + const int pos = CGAL::get_default_random().get_int(0, (int)polyhedron_points.size()); triangulation.insert(polyhedron_points[pos]); } } diff --git a/Polytope_distance_d/test/Polytope_distance_d/test_Polytope_distance_d_2.cpp b/Polytope_distance_d/test/Polytope_distance_d/test_Polytope_distance_d_2.cpp index 4f7e0714fee..d90c48ac530 100644 --- a/Polytope_distance_d/test/Polytope_distance_d/test_Polytope_distance_d_2.cpp +++ b/Polytope_distance_d/test/Polytope_distance_d/test_Polytope_distance_d_2.cpp @@ -55,7 +55,7 @@ typedef CGAL::Polytope_distance_d_traits_2 HTraits1; #include "test_Polytope_distance_d.h" template -void process () +void process () { // generate point set std::vector p_points, q_points; @@ -67,26 +67,26 @@ void process () for ( i = 0; i < 50; ++i) { p_points.push_back (typename K::Point_2( - CGAL::default_random( 0x100000), - CGAL::default_random( 0x100000), + CGAL::get_default_random()( 0x100000), + CGAL::get_default_random()( 0x100000), hom)); } hom = 3.0; for ( i = 0; i < 50; ++i) { q_points.push_back (typename K::Point_2( - -CGAL::default_random( 0x100000), - -CGAL::default_random( 0x100000), + -CGAL::get_default_random()( 0x100000), + -CGAL::get_default_random()( 0x100000), hom)); } } - + // call test function CGAL::test_Polytope_distance_d( p_points.begin(), p_points.end(), q_points.begin(), q_points.end(), Traits(), 1); } - + // main // ---- int @@ -95,5 +95,5 @@ main() process(); process(); } - + // ===== EOF ================================================================== diff --git a/Polytope_distance_d/test/Polytope_distance_d/test_Polytope_distance_d_3.cpp b/Polytope_distance_d/test/Polytope_distance_d/test_Polytope_distance_d_3.cpp index 769b3a60c68..0e19f181359 100644 --- a/Polytope_distance_d/test/Polytope_distance_d/test_Polytope_distance_d_3.cpp +++ b/Polytope_distance_d/test/Polytope_distance_d/test_Polytope_distance_d_3.cpp @@ -55,7 +55,7 @@ typedef CGAL::Polytope_distance_d_traits_3 HTraits1; #include "test_Polytope_distance_d.h" template -void process () +void process () { // generate point set std::vector p_points, q_points; @@ -67,28 +67,28 @@ void process () for ( i = 0; i < 50; ++i) { p_points.push_back (typename K::Point_3( - CGAL::default_random( 0x100000), - CGAL::default_random( 0x100000), - CGAL::default_random( 0x100000), + CGAL::get_default_random()( 0x100000), + CGAL::get_default_random()( 0x100000), + CGAL::get_default_random()( 0x100000), hom)); } hom = 3.0; for ( i = 0; i < 50; ++i) { q_points.push_back (typename K::Point_3( - -CGAL::default_random( 0x100000), - -CGAL::default_random( 0x100000), - -CGAL::default_random( 0x100000), + -CGAL::get_default_random()( 0x100000), + -CGAL::get_default_random()( 0x100000), + -CGAL::get_default_random()( 0x100000), hom)); } } - + // call test function CGAL::test_Polytope_distance_d( p_points.begin(), p_points.end(), q_points.begin(), q_points.end(), Traits(), 1); } - + // main // ---- int @@ -97,5 +97,5 @@ main() process(); process(); } - + // ===== EOF ================================================================== diff --git a/Polytope_distance_d/test/Polytope_distance_d/test_Polytope_distance_d_d.cpp b/Polytope_distance_d/test/Polytope_distance_d/test_Polytope_distance_d_d.cpp index bdc760d965e..3c1e66de7a5 100644 --- a/Polytope_distance_d/test/Polytope_distance_d/test_Polytope_distance_d_d.cpp +++ b/Polytope_distance_d/test/Polytope_distance_d/test_Polytope_distance_d_d.cpp @@ -68,7 +68,7 @@ void process () double hom = 2.0; for ( i = 0; i < 50; ++i) { for (j=0; j +#endif // CGAL_HEADER_ONLY + #endif // CGAL_REAL_TIMER_H // // EOF // diff --git a/Profiling_tools/include/CGAL/Real_timer_impl.h b/Profiling_tools/include/CGAL/Real_timer_impl.h new file mode 100644 index 00000000000..d986d308888 --- /dev/null +++ b/Profiling_tools/include/CGAL/Real_timer_impl.h @@ -0,0 +1,112 @@ +// Copyright (c) 1997 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Lutz Kettner +// Matthias Baesken + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#if defined (_MSC_VER) +# include +# include + +#elif defined (__MINGW32__) +# include +# include + +#else +// If none of the above PC compilers, use POSIX fct. gettimeofday() +# include +#endif + +namespace CGAL { + +// Member functions for Real_timer +// ===================================== + +CGAL_INLINE_FUNCTION +double Real_timer::get_real_time() const { + // Depends on the operating system. + // Returns a (weakly ;-) monotone increasing time in seconds (with + // possible wrap-around in case of overflow, see max()), or 0.0 + // if the system call for the time failed. If the system call + // failed the static flag 'm_failed' is set and can be used + // by the caller. +#if defined(_MSC_VER) + struct _timeb t; + _ftime(&t); + return double(t.time) + double(t.millitm) / 1000.0; +#elif defined (__MINGW32__) + struct timeb t; + ftime(&t); + return double(t.time) + double(t.millitm) / 1000.0; +#else // ! _MSC_VER && ! __MINGW32__// + struct timeval t; + int ret = gettimeofday( &t, NULL); + CGAL_warning_msg( ret == 0, "Call to gettimeofday() in class " + "CGAL::Real_timer failed - timings will be 0."); + if ( ret == 0) { + return double(t.tv_sec) + double(t.tv_usec) / 1000000; + } + get_static_realtimer_m_failed() = true; + return 0.0; +#endif // ! _MSC_VER && ! __MINGW32__// +} + +CGAL_INLINE_FUNCTION +double Real_timer::compute_precision() const { + // Computes timer precision in seconds dynamically. Note that + // the timer system call is probably non-trivial and will show + // up in this time here (probably for one call). But that is just + // fine that the call to the timer itself if reported as noise + // in the precision. + double min_res = DBL_MAX; + for ( int i = 0; i < 5; ++i) { + double current = get_real_time(); + if ( get_static_realtimer_m_failed() ) + return -1.0; + double next = get_real_time(); + while ( current >= next) { // wait until timer increases + next = get_real_time(); + if ( get_static_realtimer_m_failed() ) + return -1.0; + } + // Get the minimum timing difference of all runs. + if ( min_res > next - current) + min_res = next - current; + } + return min_res; +} + +CGAL_INLINE_FUNCTION +double Real_timer::precision() const { + // computes precision upon first call + // returns -1.0 if timer system call fails. + static double prec = compute_precision(); + return prec; +} + +} //namespace CGAL diff --git a/Profiling_tools/include/CGAL/Timer.h b/Profiling_tools/include/CGAL/Timer.h index 4e63563c202..ae111466c3f 100644 --- a/Profiling_tools/include/CGAL/Timer.h +++ b/Profiling_tools/include/CGAL/Timer.h @@ -48,7 +48,17 @@ private: int interv; bool running; +#ifdef CGAL_HEADER_ONLY + static bool& get_static_timer_m_failed() + { + static bool m_failed = false; + return m_failed; + } +#else // CGAL_HEADER_ONLY static bool m_failed; + static bool& get_static_timer_m_failed() + { return CGAL::Timer::m_failed; } +#endif // CGAL_HEADER_ONLY double user_process_time() const; // in seconds double compute_precision() const; // in seconds @@ -112,5 +122,9 @@ inline double Timer::time() const { } //namespace CGAL +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_TIMER_H // // EOF // diff --git a/Profiling_tools/include/CGAL/Timer_impl.h b/Profiling_tools/include/CGAL/Timer_impl.h new file mode 100644 index 00000000000..e655a457ffb --- /dev/null +++ b/Profiling_tools/include/CGAL/Timer_impl.h @@ -0,0 +1,139 @@ +// Copyright (c) 1997 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Lutz Kettner +// Matthias Baesken + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +// Determine if the POSIX function getrusage is available, otherwise +// use the previous solution based on std::clock(). +// First, detect POSIX. We cannot reliably use "unistd.h", +// but limits.h is part of the C standard. +#include +#ifdef _POSIX_ARG_MAX // now that should be POSIX +#include +#ifdef _POSIX_VERSION +#ifdef _XOPEN_UNIX // XSI: X/Open System Interfaces Extension +#define CGAL__GETRUSAGE 1 +#endif +#endif +#endif + + +#ifdef CGAL__GETRUSAGE +// types, function prototype and constants for the POSIX function +// int getrusage (int who, struct rusage *usage); +#include +// For the numerical limits +#else // CGAL__GETRUSAGE // +// used for clock() +#include +#endif // CGAL__GETRUSAGE // + +// For the numerical limits +#include + +namespace CGAL { + +// Member functions for Timer +// ===================================== + +CGAL_INLINE_FUNCTION +double Timer::user_process_time() const { + // Depends on the operating system. + // Returns a (weakly ;-) monotone increasing time in seconds (with + // possible wrap-around in case of overflow, see max()), or 0.0 + // if the system call for the time failed. If the system call + // failed the static flag 'm_failed' is set and can be used + // by the caller. +#ifdef CGAL__GETRUSAGE + struct rusage usage; + int ret = getrusage( RUSAGE_SELF, &usage); + CGAL_warning_msg( ret == 0, "Call to getrusage() in class CGAL::Timer " + "failed - timings will be 0."); + if ( ret == 0) { + return double( usage.ru_utime.tv_sec) // seconds + + double( usage.ru_utime.tv_usec) / 1000000.0; // microseconds + } +#else // CGAL__GETRUSAGE // + std::clock_t clk = std::clock(); + CGAL_warning_msg( clk != (std::clock_t)-1, + "Call to clock() in class CGAL::Timer failed - timings will be 0."); + if ( clk != (std::clock_t)-1) { + return double(clk) / CLOCKS_PER_SEC; + } +#endif // CGAL__GETRUSAGE // + get_static_timer_m_failed() = true; + return 0.0; +} + +CGAL_INLINE_FUNCTION +double Timer::compute_precision() const { + // Computes timer precision in seconds dynamically. Note that + // the timer system call is probably non-trivial and will show + // up in this time here (probably for one call). But that is just + // fine that the call to the timer itself if reported as noise + // in the precision. + double min_res = DBL_MAX; + for ( int i = 0; i < 5; ++i) { + double current = user_process_time(); + if ( get_static_timer_m_failed() ) + return -1.0; + double next = user_process_time(); + while ( current >= next) { // wait until timer increases + next = user_process_time(); + if ( get_static_timer_m_failed() ) + return -1.0; + } + // Get the minimum timing difference of all runs. + if ( min_res > next - current) + min_res = next - current; + } + return min_res; +} + +CGAL_INLINE_FUNCTION +double Timer::precision() const { + // computes precision upon first call + // returns -1.0 if timer system call fails. + static double prec = compute_precision(); + return prec; +} + +CGAL_INLINE_FUNCTION +double Timer::max BOOST_PREVENT_MACRO_SUBSTITUTION () const { + // Depends on the operating system. +#ifdef CGAL__GETRUSAGE + return DBL_MAX; +#else // CGAL__GETRUSAGE // + return 2146.0; +#endif // CGAL__GETRUSAGE // +} + +} //namespace CGAL + +// EOF // diff --git a/Profiling_tools/src/CGAL/Real_timer.cpp b/Profiling_tools/src/CGAL/Real_timer.cpp index e0a258b42bc..2a13b9be599 100644 --- a/Profiling_tools/src/CGAL/Real_timer.cpp +++ b/Profiling_tools/src/CGAL/Real_timer.cpp @@ -23,88 +23,15 @@ // Author(s) : Lutz Kettner // Matthias Baesken +#ifndef CGAL_HEADER_ONLY + #include - -#if defined (_MSC_VER) -# include -# include - -#elif defined (__MINGW32__) -# include -# include - -#else -// If none of the above PC compilers, use POSIX fct. gettimeofday() -# include -#endif +#include namespace CGAL { -// Static member variable for Real_timer -// ===================================== - bool Real_timer::m_failed = false; -// Member functions for Real_timer -// ===================================== - -double Real_timer::get_real_time() const { - // Depends on the operating system. - // Returns a (weakly ;-) monotone increasing time in seconds (with - // possible wrap-around in case of overflow, see max()), or 0.0 - // if the system call for the time failed. If the system call - // failed the static flag 'm_failed' is set and can be used - // by the caller. -#if defined(_MSC_VER) - struct _timeb t; - _ftime(&t); - return double(t.time) + double(t.millitm) / 1000.0; -#elif defined (__MINGW32__) - struct timeb t; - ftime(&t); - return double(t.time) + double(t.millitm) / 1000.0; -#else // ! _MSC_VER && ! __MINGW32__// - struct timeval t; - int ret = gettimeofday( &t, NULL); - CGAL_warning_msg( ret == 0, "Call to gettimeofday() in class " - "CGAL::Real_timer failed - timings will be 0."); - if ( ret == 0) { - return double(t.tv_sec) + double(t.tv_usec) / 1000000; - } - m_failed = true; - return 0.0; -#endif // ! _MSC_VER && ! __MINGW32__// -} - -double Real_timer::compute_precision() const { - // Computes timer precision in seconds dynamically. Note that - // the timer system call is probably non-trivial and will show - // up in this time here (probably for one call). But that is just - // fine that the call to the timer itself if reported as noise - // in the precision. - double min_res = DBL_MAX; - for ( int i = 0; i < 5; ++i) { - double current = get_real_time(); - if ( m_failed) - return -1.0; - double next = get_real_time(); - while ( current >= next) { // wait until timer increases - next = get_real_time(); - if ( m_failed) - return -1.0; - } - // Get the minimum timing difference of all runs. - if ( min_res > next - current) - min_res = next - current; - } - return min_res; -} - -double Real_timer::precision() const { - // computes precision upon first call - // returns -1.0 if timer system call fails. - static double prec = compute_precision(); - return prec; -} - } //namespace CGAL + +#endif // CGAL_HEADER_ONLY diff --git a/Profiling_tools/src/CGAL/Timer.cpp b/Profiling_tools/src/CGAL/Timer.cpp index 290d4f13cdf..3e45e00229a 100644 --- a/Profiling_tools/src/CGAL/Timer.cpp +++ b/Profiling_tools/src/CGAL/Timer.cpp @@ -23,116 +23,15 @@ // Author(s) : Lutz Kettner // Matthias Baesken +#ifndef CGAL_HEADER_ONLY + #include - -// Determine if the POSIX function getrusage is available, otherwise -// use the previous solution based on std::clock(). -// First, detect POSIX. We cannot reliably use "unistd.h", -// but limits.h is part of the C standard. -#include -#ifdef _POSIX_ARG_MAX // now that should be POSIX -#include -#ifdef _POSIX_VERSION -#ifdef _XOPEN_UNIX // XSI: X/Open System Interfaces Extension -#define CGAL__GETRUSAGE 1 -#endif -#endif -#endif - - -#ifdef CGAL__GETRUSAGE -// types, function prototype and constants for the POSIX function -// int getrusage (int who, struct rusage *usage); -#include -// For the numerical limits -#else // CGAL__GETRUSAGE // -// used for clock() -#include -#endif // CGAL__GETRUSAGE // - -// For the numerical limits -#include - +#include namespace CGAL { - -// Static member variable for Timer -// ===================================== - bool Timer::m_failed = false; -// Member functions for Timer -// ===================================== - -double Timer::user_process_time() const { - // Depends on the operating system. - // Returns a (weakly ;-) monotone increasing time in seconds (with - // possible wrap-around in case of overflow, see max()), or 0.0 - // if the system call for the time failed. If the system call - // failed the static flag 'm_failed' is set and can be used - // by the caller. -#ifdef CGAL__GETRUSAGE - struct rusage usage; - int ret = getrusage( RUSAGE_SELF, &usage); - CGAL_warning_msg( ret == 0, "Call to getrusage() in class CGAL::Timer " - "failed - timings will be 0."); - if ( ret == 0) { - return double( usage.ru_utime.tv_sec) // seconds - + double( usage.ru_utime.tv_usec) / 1000000.0; // microseconds - } -#else // CGAL__GETRUSAGE // - std::clock_t clk = std::clock(); - CGAL_warning_msg( clk != (std::clock_t)-1, - "Call to clock() in class CGAL::Timer failed - timings will be 0."); - if ( clk != (std::clock_t)-1) { - return double(clk) / CLOCKS_PER_SEC; - } -#endif // CGAL__GETRUSAGE // - m_failed = true; - return 0.0; -} - -double Timer::compute_precision() const { - // Computes timer precision in seconds dynamically. Note that - // the timer system call is probably non-trivial and will show - // up in this time here (probably for one call). But that is just - // fine that the call to the timer itself if reported as noise - // in the precision. - double min_res = DBL_MAX; - for ( int i = 0; i < 5; ++i) { - double current = user_process_time(); - if ( m_failed) - return -1.0; - double next = user_process_time(); - while ( current >= next) { // wait until timer increases - next = user_process_time(); - if ( m_failed) - return -1.0; - } - // Get the minimum timing difference of all runs. - if ( min_res > next - current) - min_res = next - current; - } - return min_res; -} - -double Timer::precision() const { - // computes precision upon first call - // returns -1.0 if timer system call fails. - static double prec = compute_precision(); - return prec; -} - -double Timer::max BOOST_PREVENT_MACRO_SUBSTITUTION () const { - // Depends on the operating system. -#ifdef CGAL__GETRUSAGE - return DBL_MAX; -#else // CGAL__GETRUSAGE // - return 2146.0; -#endif // CGAL__GETRUSAGE // -} - } //namespace CGAL -// EOF // +#endif // CGAL_HEADER_ONLY diff --git a/QP_solver/include/CGAL/QP_solver/QP_partial_exact_pricing.h b/QP_solver/include/CGAL/QP_solver/QP_partial_exact_pricing.h index 9d870894e25..aac1842e5be 100644 --- a/QP_solver/include/CGAL/QP_solver/QP_partial_exact_pricing.h +++ b/QP_solver/include/CGAL/QP_solver/QP_partial_exact_pricing.h @@ -55,7 +55,7 @@ class QP_partial_exact_pricing : public QP__partial_base { // creation QP_partial_exact_pricing( bool randomize = false, - Random& random = default_random); + Random& random = get_default_random()); // operations int pricing(int& direction ); diff --git a/QP_solver/include/CGAL/QP_solver/QP_partial_filtered_pricing.h b/QP_solver/include/CGAL/QP_solver/QP_partial_filtered_pricing.h index 5395e6ace14..e1c13cd6158 100644 --- a/QP_solver/include/CGAL/QP_solver/QP_partial_filtered_pricing.h +++ b/QP_solver/include/CGAL/QP_solver/QP_partial_filtered_pricing.h @@ -78,7 +78,7 @@ class QP_partial_filtered_pricing // creation QP_partial_filtered_pricing( bool randomize = false, - Random& random = default_random, + Random& random = get_default_random(), ET2NT et2nt = ET2NT()); // operations diff --git a/Random_numbers/include/CGAL/Random.h b/Random_numbers/include/CGAL/Random.h index 3433ccfb865..665dd78cb23 100644 --- a/Random_numbers/include/CGAL/Random.h +++ b/Random_numbers/include/CGAL/Random.h @@ -43,7 +43,6 @@ #include #include - namespace CGAL { class Random { @@ -229,12 +228,27 @@ public: boost::rand48 rng; }; +#ifndef CGAL_HEADER_ONLY // Global variables // ================ CGAL_EXPORT extern Random default_random; +#endif // CGAL_HEADER_ONLY + +#ifdef CGAL_HEADER_ONLY +inline Random& get_default_random() +{ + static Random default_random; + return default_random; +} +#else // CGAL_HEADER_ONLY +inline Random& get_default_random() +{ return default_random; } +#endif // CGAL_HEADER_ONLY } //namespace CGAL +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_RANDOM_H - - diff --git a/Random_numbers/include/CGAL/Random_impl.h b/Random_numbers/include/CGAL/Random_impl.h new file mode 100644 index 00000000000..16cb9e0cbd3 --- /dev/null +++ b/Random_numbers/include/CGAL/Random_impl.h @@ -0,0 +1,94 @@ +// Copyright (c) 1997-2001 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Sven Schönherr + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include + +namespace CGAL { + +// Class implementation (continued) +// ================================ + +// constructors +CGAL_INLINE_FUNCTION +Random:: +Random( ) + : val(0) +{ + // get system's time + std::time_t s; + std::time( &s); + seed = (unsigned int)s; + + // initialize random numbers generator + rng.seed(static_cast(seed)); + random_value = get_int(0, 1<<15); +} + +CGAL_INLINE_FUNCTION +Random:: +Random( unsigned int seed) + : val(0), seed(seed) +{ + // initialize random numbers generator + rng.seed(static_cast(seed)); + random_value = get_int(0, 1<<15); +} + +// seed +CGAL_INLINE_FUNCTION +unsigned int +Random::get_seed () const +{ + return seed; +} + +// state +CGAL_INLINE_FUNCTION +void +Random::save_state( Random::State& state) const +{ + std::ostringstream os; + os << rng; + state = Random::State(os.str(),random_value, val, seed); +} + +CGAL_INLINE_FUNCTION +void +Random::restore_state( const Random::State& state) +{ + std::istringstream is(state.rng); + is >> rng; + random_value = state.random_value; + val = state.val; + seed = state.seed; +} + +} //namespace CGAL diff --git a/Random_numbers/src/CGAL/Random.cpp b/Random_numbers/src/CGAL/Random.cpp index 9a5887a1b15..471accc5128 100644 --- a/Random_numbers/src/CGAL/Random.cpp +++ b/Random_numbers/src/CGAL/Random.cpp @@ -22,67 +22,15 @@ // // Author(s) : Sven Schönherr +#ifndef CGAL_HEADER_ONLY + #include -#include -#include +#include namespace CGAL { -// Class implementation (continued) -// ================================ - -// constructors -Random:: -Random( ) - : val(0) -{ - // get system's time - std::time_t s; - std::time( &s); - seed = (unsigned int)s; - - // initialize random numbers generator - rng.seed(static_cast(seed)); - random_value = get_int(0, 1<<15); -} - -Random:: -Random( unsigned int seed) - : val(0), seed(seed) -{ - // initialize random numbers generator - rng.seed(static_cast(seed)); - random_value = get_int(0, 1<<15); -} - -// seed -unsigned int -Random::get_seed () const -{ - return seed; -} - -// state -void -Random::save_state( Random::State& state) const -{ - std::ostringstream os; - os << rng; - state = Random::State(os.str(),random_value, val, seed); -} - -void -Random::restore_state( const Random::State& state) -{ - std::istringstream is(state.rng); - is >> rng; - random_value = state.random_value; - val = state.val; - seed = state.seed; -} - -// Global variables -// ================ Random default_random; } //namespace CGAL + +#endif diff --git a/Random_numbers/test/Random_numbers/test_Random.cpp b/Random_numbers/test/Random_numbers/test_Random.cpp index c09a960a4d3..ae46b8ee517 100644 --- a/Random_numbers/test/Random_numbers/test_Random.cpp +++ b/Random_numbers/test/Random_numbers/test_Random.cpp @@ -32,33 +32,33 @@ main() { // test get_bool { - bool b = CGAL::default_random.get_bool(); + bool b = CGAL::get_default_random().get_bool(); assert( ! b || b); } // test get_int { - int l = CGAL::default_random.get_int( -100, 0); - int u = CGAL::default_random.get_int( 0, 1000); - int i = CGAL::default_random.get_int( l, u); + int l = CGAL::get_default_random().get_int( -100, 0); + int u = CGAL::get_default_random().get_int( 0, 1000); + int i = CGAL::get_default_random().get_int( l, u); assert( ( l <= i) && ( i < u)); { std::size_t l = 0, u = 10; - std::size_t i = CGAL::default_random.uniform_int(l,u); + std::size_t i = CGAL::get_default_random().uniform_int(l,u); assert( ( l <= i) && ( i <= u)); } { std::ptrdiff_t l = 0, u = 10; - std::ptrdiff_t i = CGAL::default_random.uniform_int(l,u); + std::ptrdiff_t i = CGAL::get_default_random().uniform_int(l,u); assert( ( l <= i) && ( i <= u)); } { std::ptrdiff_t l = 0, u = 10; - std::ptrdiff_t i = CGAL::default_random.uniform_smallint(l,u); + std::ptrdiff_t i = CGAL::get_default_random().uniform_smallint(l,u); assert( ( l <= i) && ( i <= u)); } @@ -67,39 +67,39 @@ main() // test get_double { - double l = CGAL::default_random.get_double( -123.45, -0.99); - double u = CGAL::default_random.get_double( 22.0/7.0, 33.3); - double d = CGAL::default_random.get_double( l, u); + double l = CGAL::get_default_random().get_double( -123.45, -0.99); + double u = CGAL::get_default_random().get_double( 22.0/7.0, 33.3); + double d = CGAL::get_default_random().get_double( l, u); assert( ( l <= d) && ( d < u)); - double ho = CGAL::default_random.get_double(0.5); + double ho = CGAL::get_default_random().get_double(0.5); assert( (0.5 <= ho) && (ho < 1.0)); - double zo = CGAL::default_random.get_double(); + double zo = CGAL::get_default_random().get_double(); assert( (0 <= zo) && (zo < 1.0)); } // test uniform_real { - double d = CGAL::default_random.uniform_real(-10.0, 10.0); + double d = CGAL::get_default_random().uniform_real(-10.0, 10.0); assert( (d >= -10.0) && (d < 10.0) ); - d = CGAL::default_random.uniform_real(0.2); + d = CGAL::get_default_random().uniform_real(0.2); assert( (d >= 0.2) && (d < 1.0) ); - d = CGAL::default_random.uniform_real(); + d = CGAL::get_default_random().uniform_real(); assert( (d >= 0) && (d < 1) ); - d = CGAL::default_random.uniform_01(); + d = CGAL::get_default_random().uniform_01(); assert( (d >= 0) && (d < 1) ); } { - float d = CGAL::default_random.uniform_real(-10.0f, 10.0f); + float d = CGAL::get_default_random().uniform_real(-10.0f, 10.0f); assert( (d >= -10.0f) && (d < 10.0f) ); - d = CGAL::default_random.uniform_real(0.2f); + d = CGAL::get_default_random().uniform_real(0.2f); assert( (d >= 0.2) && (d < 1.0) ); - d = CGAL::default_random.uniform_real(); + d = CGAL::get_default_random().uniform_real(); assert( (d >= 0) && (d < 1) ); - d = CGAL::default_random.uniform_01(); + d = CGAL::get_default_random().uniform_01(); assert( (d >= 0) && (d < 1) ); } @@ -110,10 +110,10 @@ main() int p3[8] = {0,}; int p4[16] = {0,}; for (int loops=0; loops < (1<<16); ++loops) { - unsigned int l1 = CGAL::default_random.get_bits<1>(); - unsigned int l2 = CGAL::default_random.get_bits<2>(); - unsigned int l3 = CGAL::default_random.get_bits<3>(); - unsigned int l4 = CGAL::default_random.get_bits<4>(); + unsigned int l1 = CGAL::get_default_random().get_bits<1>(); + unsigned int l2 = CGAL::get_default_random().get_bits<2>(); + unsigned int l3 = CGAL::get_default_random().get_bits<3>(); + unsigned int l4 = CGAL::get_default_random().get_bits<4>(); assert(l1 < 2); assert(l2 < 4); assert(l3 < 8); @@ -138,7 +138,7 @@ main() // test operator() { - int i = CGAL::default_random( 5555); + int i = CGAL::get_default_random()( 5555); assert( ( 0 <= i) && ( i < 5555)); } @@ -160,7 +160,7 @@ main() std::vector numbers; numbers.push_back(1); - std::random_shuffle(numbers.begin(), numbers.end(), CGAL::default_random); + std::random_shuffle(numbers.begin(), numbers.end(), CGAL::get_default_random()); return( 0); } diff --git a/STL_Extension/include/CGAL/assertions.h b/STL_Extension/include/CGAL/assertions.h index 63144c96a3d..c9dd318cf71 100644 --- a/STL_Extension/include/CGAL/assertions.h +++ b/STL_Extension/include/CGAL/assertions.h @@ -343,4 +343,8 @@ inline bool possibly(Uncertain c); // But the macros need CGAL::possibly(). #include +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_ASSERTIONS_H diff --git a/STL_Extension/include/CGAL/assertions_impl.h b/STL_Extension/include/CGAL/assertions_impl.h new file mode 100644 index 00000000000..340fab72aa1 --- /dev/null +++ b/STL_Extension/include/CGAL/assertions_impl.h @@ -0,0 +1,281 @@ +// Copyright (c) 1997 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Geert-Jan Giezeman and Sven Schönherr + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include +#include + +#include +#include + +namespace CGAL { + +namespace { + +#ifdef CGAL_HEADER_ONLY + +inline Failure_behaviour& get_static_error_behaviour() +{ + static Failure_behaviour _error_behaviour = THROW_EXCEPTION; + return _error_behaviour; +} +inline Failure_behaviour& get_static_warning_behaviour() +{ + static Failure_behaviour _warning_behaviour = CONTINUE; + return _warning_behaviour; +} + +#else // CGAL_HEADER_ONLY + +// behaviour variables +// ------------------- + +Failure_behaviour _error_behaviour = THROW_EXCEPTION; +Failure_behaviour _warning_behaviour = CONTINUE; + +inline Failure_behaviour& get_static_error_behaviour() +{ return _error_behaviour; } +inline Failure_behaviour& get_static_warning_behaviour() +{ return _warning_behaviour; } + +#endif // CGAL_HEADER_ONLY + +// standard error handlers +// ----------------------- +CGAL_INLINE_FUNCTION +void +_standard_error_handler( + const char* what, + const char* expr, + const char* file, + int line, + const char* msg ) +{ +#if defined(__GNUG__) && !defined(__llvm__) + // After g++ 3.4, std::terminate defaults to printing to std::cerr itself. + if (get_static_error_behaviour() == THROW_EXCEPTION) + return; +#endif + std::cerr << "CGAL error: " << what << " violation!" << std::endl + << "Expression : " << expr << std::endl + << "File : " << file << std::endl + << "Line : " << line << std::endl + << "Explanation: " << msg << std::endl + << "Refer to the bug-reporting instructions at http://www.cgal.org/bug_report.html" + << std::endl; +} + + +// standard warning handler +// ------------------------ +CGAL_INLINE_FUNCTION +void +_standard_warning_handler( const char *, + const char* expr, + const char* file, + int line, + const char* msg ) +{ +#if defined(__GNUG__) && !defined(__llvm__) + // After g++ 3.4, std::terminate defaults to printing to std::cerr itself. + if (get_static_warning_behaviour() == THROW_EXCEPTION) + return; +#endif + std::cerr << "CGAL warning: check violation!" << std::endl + << "Expression : " << expr << std::endl + << "File : " << file << std::endl + << "Line : " << line << std::endl + << "Explanation: " << msg << std::endl + << "Refer to the bug-reporting instructions at http://www.cgal.org/bug_report.html" + << std::endl; +} + +#ifdef CGAL_HEADER_ONLY + +inline Failure_function& get_static_error_handler() +{ + static Failure_function _error_handler = _standard_error_handler; + return _error_handler; +} +inline Failure_function& get_static_warning_handler() +{ + static Failure_function _warning_handler = _standard_warning_handler; + return _warning_handler; +} + +#else // CGAL_HEADER_ONLY +// default handler settings +// ------------------------ +Failure_function _error_handler = _standard_error_handler; +Failure_function _warning_handler = _standard_warning_handler; + +inline Failure_function& get_static_error_handler() +{ return _error_handler; } +inline Failure_function& get_static_warning_handler() +{ return _warning_handler; } + +#endif // CGAL_HEADER_ONLY + +} // anonymous namespace + +// failure functions +// ----------------- +CGAL_INLINE_FUNCTION +void +assertion_fail( const char* expr, + const char* file, + int line, + const char* msg) +{ + get_static_error_handler()("assertion", expr, file, line, msg); + switch (get_static_error_behaviour()) { + case ABORT: + std::abort(); + case EXIT: + std::exit(1); // EXIT_FAILURE + case EXIT_WITH_SUCCESS: + std::exit(0); // EXIT_SUCCESS + case CONTINUE: // The CONTINUE case should not be used anymore. + case THROW_EXCEPTION: + default: + throw Assertion_exception("CGAL", expr, file, line, msg); + } +} + +CGAL_INLINE_FUNCTION +void +precondition_fail( const char* expr, + const char* file, + int line, + const char* msg) +{ + get_static_error_handler()("precondition", expr, file, line, msg); + switch (get_static_error_behaviour()) { + case ABORT: + std::abort(); + case EXIT: + std::exit(1); // EXIT_FAILURE + case EXIT_WITH_SUCCESS: + std::exit(0); // EXIT_SUCCESS + case CONTINUE: + case THROW_EXCEPTION: + default: + throw Precondition_exception("CGAL", expr, file, line, msg); + } +} + +CGAL_INLINE_FUNCTION +void +postcondition_fail(const char* expr, + const char* file, + int line, + const char* msg) +{ + get_static_error_handler()("postcondition", expr, file, line, msg); + switch (get_static_error_behaviour()) { + case ABORT: + std::abort(); + case EXIT: + std::exit(1); // EXIT_FAILURE + case EXIT_WITH_SUCCESS: + std::exit(0); // EXIT_SUCCESS + case CONTINUE: + case THROW_EXCEPTION: + default: + throw Postcondition_exception("CGAL", expr, file, line, msg); + } +} + + +// warning function +// ---------------- +CGAL_INLINE_FUNCTION +void +warning_fail( const char* expr, + const char* file, + int line, + const char* msg) +{ + get_static_warning_handler()("warning", expr, file, line, msg); + switch (get_static_warning_behaviour()) { + case ABORT: + std::abort(); + case EXIT: + std::exit(1); // EXIT_FAILURE + case EXIT_WITH_SUCCESS: + std::exit(0); // EXIT_SUCCESS + case THROW_EXCEPTION: + throw Warning_exception("CGAL", expr, file, line, msg); + case CONTINUE: + ; + } +} + + +// error handler set functions +// --------------------------- +CGAL_INLINE_FUNCTION +Failure_function +set_error_handler( Failure_function handler) +{ + Failure_function result = get_static_error_handler(); + get_static_error_handler() = handler; + return result; +} + +CGAL_INLINE_FUNCTION +Failure_function +set_warning_handler( Failure_function handler) +{ + Failure_function result = get_static_warning_handler(); + get_static_warning_handler() = handler; + return result; +} + +CGAL_INLINE_FUNCTION +Failure_behaviour +set_error_behaviour(Failure_behaviour eb) +{ + Failure_behaviour result = get_static_error_behaviour(); + get_static_error_behaviour() = eb; + return result; +} + +CGAL_INLINE_FUNCTION +Failure_behaviour +set_warning_behaviour(Failure_behaviour eb) +{ + Failure_behaviour result = get_static_warning_behaviour(); + get_static_warning_behaviour() = eb; + return result; +} + +} //namespace CGAL diff --git a/STL_Extension/src/CGAL/assertions.cpp b/STL_Extension/src/CGAL/assertions.cpp index 44e187df0a6..9df3b1ac79c 100644 --- a/STL_Extension/src/CGAL/assertions.cpp +++ b/STL_Extension/src/CGAL/assertions.cpp @@ -22,201 +22,9 @@ // // Author(s) : Geert-Jan Giezeman and Sven Schönherr -#include +#ifndef CGAL_HEADER_ONLY + #include -#include -#include +#include -#include -#include - -namespace CGAL { - -namespace { - -// behaviour variables -// ------------------- - -Failure_behaviour _error_behaviour = THROW_EXCEPTION; -Failure_behaviour _warning_behaviour = CONTINUE; - -// standard error handlers -// ----------------------- -void -_standard_error_handler( - const char* what, - const char* expr, - const char* file, - int line, - const char* msg ) -{ -#if defined(__GNUG__) && !defined(__llvm__) - // After g++ 3.4, std::terminate defaults to printing to std::cerr itself. - if (_error_behaviour == THROW_EXCEPTION) - return; -#endif - std::cerr << "CGAL error: " << what << " violation!" << std::endl - << "Expression : " << expr << std::endl - << "File : " << file << std::endl - << "Line : " << line << std::endl - << "Explanation: " << msg << std::endl - << "Refer to the bug-reporting instructions at http://www.cgal.org/bug_report.html" - << std::endl; -} - - -// standard warning handler -// ------------------------ -void -_standard_warning_handler( const char *, - const char* expr, - const char* file, - int line, - const char* msg ) -{ -#if defined(__GNUG__) && !defined(__llvm__) - // After g++ 3.4, std::terminate defaults to printing to std::cerr itself. - if (_warning_behaviour == THROW_EXCEPTION) - return; -#endif - std::cerr << "CGAL warning: check violation!" << std::endl - << "Expression : " << expr << std::endl - << "File : " << file << std::endl - << "Line : " << line << std::endl - << "Explanation: " << msg << std::endl - << "Refer to the bug-reporting instructions at http://www.cgal.org/bug_report.html" - << std::endl; -} - -// default handler settings -// ------------------------ -Failure_function _error_handler = _standard_error_handler; -Failure_function _warning_handler = _standard_warning_handler; - -} // anonymous namespace - -// failure functions -// ----------------- -void -assertion_fail( const char* expr, - const char* file, - int line, - const char* msg) -{ - _error_handler("assertion", expr, file, line, msg); - switch (_error_behaviour) { - case ABORT: - std::abort(); - case EXIT: - std::exit(1); // EXIT_FAILURE - case EXIT_WITH_SUCCESS: - std::exit(0); // EXIT_SUCCESS - case CONTINUE: // The CONTINUE case should not be used anymore. - case THROW_EXCEPTION: - default: - throw Assertion_exception("CGAL", expr, file, line, msg); - } -} - -void -precondition_fail( const char* expr, - const char* file, - int line, - const char* msg) -{ - _error_handler("precondition", expr, file, line, msg); - switch (_error_behaviour) { - case ABORT: - std::abort(); - case EXIT: - std::exit(1); // EXIT_FAILURE - case EXIT_WITH_SUCCESS: - std::exit(0); // EXIT_SUCCESS - case CONTINUE: - case THROW_EXCEPTION: - default: - throw Precondition_exception("CGAL", expr, file, line, msg); - } -} - -void -postcondition_fail(const char* expr, - const char* file, - int line, - const char* msg) -{ - _error_handler("postcondition", expr, file, line, msg); - switch (_error_behaviour) { - case ABORT: - std::abort(); - case EXIT: - std::exit(1); // EXIT_FAILURE - case EXIT_WITH_SUCCESS: - std::exit(0); // EXIT_SUCCESS - case CONTINUE: - case THROW_EXCEPTION: - default: - throw Postcondition_exception("CGAL", expr, file, line, msg); - } -} - - -// warning function -// ---------------- -void -warning_fail( const char* expr, - const char* file, - int line, - const char* msg) -{ - _warning_handler("warning", expr, file, line, msg); - switch (_warning_behaviour) { - case ABORT: - std::abort(); - case EXIT: - std::exit(1); // EXIT_FAILURE - case EXIT_WITH_SUCCESS: - std::exit(0); // EXIT_SUCCESS - case THROW_EXCEPTION: - throw Warning_exception("CGAL", expr, file, line, msg); - case CONTINUE: - ; - } -} - - -// error handler set functions -// --------------------------- -Failure_function -set_error_handler( Failure_function handler) -{ - Failure_function result = _error_handler; - _error_handler = handler; - return result; -} - -Failure_function -set_warning_handler( Failure_function handler) -{ - Failure_function result = _warning_handler; - _warning_handler = handler; - return result; -} - -Failure_behaviour -set_error_behaviour(Failure_behaviour eb) -{ - Failure_behaviour result = _error_behaviour; - _error_behaviour = eb; - return result; -} - -Failure_behaviour -set_warning_behaviour(Failure_behaviour eb) -{ - Failure_behaviour result = _warning_behaviour; - _warning_behaviour = eb; - return result; -} - -} //namespace CGAL +#endif // CGAL_HEADER_ONLY diff --git a/STL_Extension/test/STL_Extension/test_Compact_container.cpp b/STL_Extension/test/STL_Extension/test_Compact_container.cpp index 04e365e2a0e..567e78c872f 100644 --- a/STL_Extension/test/STL_Extension/test_Compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Compact_container.cpp @@ -63,7 +63,7 @@ class Node_2 public: Node_2() - : p(NULL), rnd(CGAL::default_random.get_int(0, 100)) {} + : p(NULL), rnd(CGAL::get_default_random().get_int(0, 100)) {} bool operator==(const Node_2 &n) const { return rnd == n.rnd; } bool operator!=(const Node_2 &n) const { return rnd != n.rnd; } diff --git a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp index 5794411d442..b4f6ede8654 100644 --- a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp @@ -47,7 +47,7 @@ public: int rnd; Node_2() - : p(NULL), rnd(CGAL::default_random.get_int(0, 100)) {} + : p(NULL), rnd(CGAL::get_default_random().get_int(0, 100)) {} bool operator==(const Node_2 &n) const { return rnd == n.rnd; } bool operator!=(const Node_2 &n) const { return rnd != n.rnd; } diff --git a/Stream_support/include/CGAL/IO/Color.h b/Stream_support/include/CGAL/IO/Color.h index 9a8e02bcf15..2696ce8dcee 100644 --- a/Stream_support/include/CGAL/IO/Color.h +++ b/Stream_support/include/CGAL/IO/Color.h @@ -1,9 +1,9 @@ -// Copyright (c) 1997 +// Copyright (c) 1997 // Utrecht University (The Netherlands), // ETH Zurich (Switzerland), // INRIA Sophia-Antipolis (France), // Max-Planck-Institute Saarbruecken (Germany), -// and Tel-Aviv University (Israel). All rights reserved. +// and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as @@ -18,7 +18,7 @@ // // $URL$ // $Id$ -// +// // // Author(s) : Andreas Fabri @@ -32,9 +32,9 @@ namespace CGAL { class Color { public: Color() {} - Color(unsigned char red, - unsigned char green, - unsigned char blue, + Color(unsigned char red, + unsigned char green, + unsigned char blue, unsigned char alpha = 120) : _red(red), _green(green), _blue(blue), _alpha(alpha) {} @@ -76,15 +76,16 @@ private: unsigned char _alpha; }; +#ifndef CGAL_HEADER_ONLY CGAL_EXPORT extern const Color BLACK ; CGAL_EXPORT extern const Color WHITE ; -CGAL_EXPORT extern const Color GRAY ; +CGAL_EXPORT extern const Color GRAY ; CGAL_EXPORT extern const Color RED ; CGAL_EXPORT extern const Color GREEN ; -CGAL_EXPORT extern const Color DEEPBLUE ; +CGAL_EXPORT extern const Color DEEPBLUE; CGAL_EXPORT extern const Color BLUE ; CGAL_EXPORT extern const Color PURPLE ; CGAL_EXPORT extern const Color VIOLET ; @@ -92,7 +93,12 @@ CGAL_EXPORT extern const Color VIOLET ; CGAL_EXPORT extern const Color ORANGE ; CGAL_EXPORT extern const Color YELLOW ; +#endif // CGAL_HEADER_ONLY } //namespace CGAL +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_COLOR_H diff --git a/Stream_support/include/CGAL/IO/Color_impl.h b/Stream_support/include/CGAL/IO/Color_impl.h new file mode 100644 index 00000000000..cfca8dea9bb --- /dev/null +++ b/Stream_support/include/CGAL/IO/Color_impl.h @@ -0,0 +1,42 @@ +// Copyright (c) 1997 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Andreas Fabri, Hervé Brönnimann + +namespace CGAL { + +const Color BLACK = Color(0, 0, 0); +const Color WHITE = Color(255, 255, 255); +const Color GRAY = Color(100,100,100); + +const Color GREEN = Color(0, 255, 0); + +const Color DEEPBLUE = Color(10, 0, 100); +const Color BLUE = Color(0, 0, 255); +const Color VIOLET = Color(255, 0, 255); +const Color PURPLE = Color(100, 0, 70); + +const Color RED = Color(255, 0, 0); +const Color ORANGE = Color(235, 150, 0); +const Color YELLOW = Color(255, 255, 0); + +} //namespace CGAL diff --git a/Stream_support/include/CGAL/IO/File_header_OFF.h b/Stream_support/include/CGAL/IO/File_header_OFF.h index 726e3aa3b9a..15a56771390 100644 --- a/Stream_support/include/CGAL/IO/File_header_OFF.h +++ b/Stream_support/include/CGAL/IO/File_header_OFF.h @@ -116,5 +116,10 @@ CGAL_EXPORT std::ostream& operator<<( std::ostream& out, const File_header_OFF& CGAL_EXPORT std::istream& operator>>( std::istream& in, File_header_OFF& h); } //namespace CGAL + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_IO_FILE_HEADER_OFF_H // // EOF // diff --git a/Stream_support/include/CGAL/IO/File_header_OFF_impl.h b/Stream_support/include/CGAL/IO/File_header_OFF_impl.h new file mode 100644 index 00000000000..9ac3e1fc83d --- /dev/null +++ b/Stream_support/include/CGAL/IO/File_header_OFF_impl.h @@ -0,0 +1,409 @@ +// Copyright (c) 1997 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Lutz Kettner + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace CGAL { + +CGAL_INLINE_FUNCTION +File_header_OFF::File_header_OFF( bool verbose) +: File_header_extended_OFF( verbose), + n_vertices(0), + n_facets(0), + m_skel(false), + m_binary(false), + m_no_comments(false), + m_offset(0), + m_colors(false), + m_normals(false), + m_tag4(false), + m_tagDim(false), + m_dim(3) +{} +CGAL_INLINE_FUNCTION +File_header_OFF::File_header_OFF( + bool binary, bool noc, bool skel, bool verbose) +: File_header_extended_OFF( verbose), + n_vertices(0), + n_facets(0), + m_skel(skel), + m_binary(binary), + m_no_comments(noc), + m_offset(0), + m_colors(false), + m_normals(false), + m_tag4(false), + m_tagDim(false), + m_dim(3) +{} +//CGAL_INLINE_FUNCTION +//File_header_OFF::File_header_OFF( int v, int h, int f, +// bool verbose) +//: File_header_extended_OFF( verbose), +// n_vertices(v), +// n_facets(f), +// m_skel(false), +// m_binary(false), +// m_no_comments(false), +// m_offset(0), +// m_colors(false), +// m_normals(false), +// m_tag4(false), +// m_tagDim(false), +// m_dim(3) +//{ +// set_halfedges(h); +//} +CGAL_INLINE_FUNCTION +File_header_OFF::File_header_OFF( std::size_t v, std::size_t h, std::size_t f, + bool binary, bool noc, bool skel, bool verbose) +: File_header_extended_OFF( verbose), + n_vertices(v), + n_facets(f), + m_skel(skel), + m_binary(binary), + m_no_comments(noc), + m_offset(0), + m_colors(false), + m_normals(false), + m_tag4(false), + m_tagDim(false), + m_dim(3) +{ + set_halfedges(h); +} +CGAL_INLINE_FUNCTION +File_header_OFF::File_header_OFF( + const File_header_extended_OFF& ext_header) +: File_header_extended_OFF( ext_header), + n_vertices(0), + n_facets(0), + m_skel(false), + m_binary(false), + m_no_comments(false), + m_offset(0), + m_colors(false), + m_normals(false), + m_tag4(false), + m_tagDim(false), + m_dim(3) +{} +CGAL_INLINE_FUNCTION +File_header_OFF::File_header_OFF( + const File_header_extended_OFF& ext_header, + bool binary, bool noc, bool skel) +: File_header_extended_OFF( ext_header), + n_vertices(0), + n_facets(0), + m_skel(skel), + m_binary(binary), + m_no_comments(noc), + m_offset(0), + m_colors(false), + m_normals(false), + m_tag4(false), + m_tagDim(false), + m_dim(3) +{} +CGAL_INLINE_FUNCTION +File_header_OFF::File_header_OFF( + std::size_t v, std::size_t h, std::size_t f, + const File_header_extended_OFF& ext_header) +: File_header_extended_OFF( ext_header), + n_vertices(v), + n_facets(f), + m_skel(false), + m_binary(false), + m_no_comments(false), + m_offset(0), + m_colors(false), + m_normals(false), + m_tag4(false), + m_tagDim(false), + m_dim(3) +{ + set_halfedges(h); +} +CGAL_INLINE_FUNCTION +File_header_OFF::File_header_OFF( + std::size_t v, std::size_t h, std::size_t f, + const File_header_extended_OFF& ext_header, + bool binary, bool noc, bool skel) +: File_header_extended_OFF( ext_header), + n_vertices(v), + n_facets(f), + m_skel(skel), + m_binary(binary), + m_no_comments(noc), + m_offset(0), + m_colors(false), + m_normals(false), + m_tag4(false), + m_tagDim(false), + m_dim(3) +{ + set_halfedges(h); +} + +CGAL_INLINE_FUNCTION +File_header_OFF& File_header_OFF:: +operator+=( const File_header_OFF& header) { + (File_header_extended_OFF&)(*this) = header; + n_vertices += header.n_vertices; + n_facets += header.n_facets; + return *this; +} + +// Write header. +CGAL_INLINE_FUNCTION +std::ostream& operator<<( std::ostream& out, const File_header_OFF& h) { + if ( h.comments()) { + out << "# Output of a CGAL tool\n"; + out << static_cast( h); + } + if ( h.has_normals()) + out << 'N'; + if ( h.skel()) + out << "SKEL"; + else + out << "OFF"; + if ( h.binary()) { + out << " BINARY\n"; + I_Binary_write_big_endian_integer32( out, static_cast(h.size_of_vertices())); + I_Binary_write_big_endian_integer32( out, static_cast(h.size_of_facets())); + if ( h.off()) + I_Binary_write_big_endian_integer32( out, 0); + } else { + out << '\n'; + out << h.size_of_vertices() << ' '<< h.size_of_facets(); + if ( h.off()) + out << " 0"; + if ( h.comments()) { + out << "\n\n# " << h.size_of_vertices() << " vertices\n"; + out << "# ------------------------------------------\n"; + } + out << std::endl; + } + return out; +} + +// Scan header. Marks streams badbit if not in SKEL format nor in OFF. +CGAL_INLINE_FUNCTION +std::istream& operator>>( std::istream& in, File_header_OFF& h) { + // read in the first character and scan for comments, `OFF', or `NOFF', + // or `SKEL', or `4SKEL'. + h.set_off_header( false); + char c; + while ( (in >> c) && c == '#') { + if ( in.get(c) && c == 'C' && + in.get(c) && c == 'B' && + in.get(c) && c == 'P') { + in >> static_cast( h); + } else if ( c != '\n') + in >> skip_until_EOL; + } + if ( ! in) + return in; + h.set_skel( false); + h.set_binary( false); + h.set_index_offset( 1); + h.set_colors( false); + h.set_normals( false); + h.set_homogeneous( false); + h.set_dimensional( false); + h.set_dimension( 3); + + const int max_keyword = 42; + char keyword[max_keyword] = ""; + int i = 0; + keyword[i++] = c; + while( i < max_keyword - 1 && in.get(c) && std::isalnum(c)) + keyword[i++] = c; + keyword[i] = '\0'; + if ( i < 2 || (std::isdigit(keyword[0]) && keyword[0] != '4') + || std::isdigit(keyword[1])) { + h.set_vertices( std::atoi( keyword)); + } else { + h.set_index_offset( 0); + int j = 0; + if ( j < i && keyword[j] == 'C') { + h.set_colors( true); + j++; + } + if ( j < i && keyword[j] == 'N') { + h.set_normals( true); + j++; + } + if ( j < i && keyword[j] == '4') { + h.set_homogeneous( true); + j++; + } + if ( j < i && keyword[j] == 'n') { + h.set_dimensional( true); + j++; + } + if ( i-j != 3 || keyword[j] != 'O' + || keyword[j+1] != 'F' + || keyword[j+2] != 'F') { + if ( i-j != 4 || keyword[j] != 'S' + || keyword[j+1] != 'K' + || keyword[j+2] != 'E' + || keyword[j+3] != 'L') { + in.clear( std::ios::badbit); + if ( h.verbose()) { + std::cerr << " " << std::endl; + std::cerr << "error: File_header_OFF: " + "wrong format: neither OFF nor SKEL." + << std::endl; + } + return in; + } else { + h.set_skel( true); + } + } + in >> skip_comment_OFF >> c; + if ( std::isdigit(c)) { + in.putback(c); + int n; + in >> n; + h.set_vertices(n); + } else { + i = 0; + keyword[i++] = c; + while( i < max_keyword - 1 && in.get(c) && + std::isalnum(c)) + keyword[i++] = c; + keyword[i] = '\0'; + if ( std::strcmp( keyword, "BINARY") == 0) { + h.set_binary( true); + if ( c != '\n') + in >> skip_until_EOL; + } else { + in.clear( std::ios::badbit); + if ( h.verbose()) { + std::cerr << " " << std::endl; + std::cerr << "error: File_header_OFF(): " + "wrong format: neither OFF nor SKEL." + << std::endl; + } + return in; + } + } + } + // Read remaining size value(s). + int n_h; + if ( h.binary()) { + boost::int32_t a, b, c; + I_Binary_read_big_endian_integer32( in, a); + if ( h.n_dimensional()) { + h.set_dimension( a); + I_Binary_read_big_endian_integer32( in, a); + } + I_Binary_read_big_endian_integer32( in, b); + if ( h.off()) + I_Binary_read_big_endian_integer32( in, c); + else + c = 0; + h.set_vertices( a); + if (b<0){ + in.clear( std::ios::badbit ); + if ( h.verbose()) { + std::cerr << " " << std::endl; + std::cerr << "error: File_header_OFF(): File contains < 0 facets." + << std::endl; + } + return in; + } + h.set_facets( b); + n_h = c; + } else { + int n; + if ( h.n_dimensional()) { + h.set_dimension( static_cast(h.size_of_vertices())); + in >> n; + h.set_vertices(n); + } + in >> n; + if (n < 0){ + in.clear( std::ios::badbit ); + if ( h.verbose()) { + std::cerr << " " << std::endl; + std::cerr << "error: File_header_OFF(): File contains < 0 facets." + << std::endl; + } + return in; + } + h.set_facets(n); + if ( h.off()) + in >> n_h; + else + n_h = 0; + } + if ( n_h == 0) + h.set_index_offset( 0); + if ( ! in || h.size_of_vertices() <= 0 ) { + in.clear( std::ios::badbit); + if ( h.verbose()) { + std::cerr << " " << std::endl; + std::cerr << "error: File_header_OFF(): File contains <= 0 vertices." + << std::endl; + } + return in; + } + if ( h.size_of_halfedges() == 0) { + // be careful, because border edges count twice + h.set_halfedges( 2 * n_h); + // check against the Eulerian equation for connected planar graphs. + // We do not know the number of holes we must represent as dummy + // facets and we do not know the genus of the surface. + // So we add 12 and a factor of 5 percent. + if ( h.size_of_halfedges() == 0 + || h.size_of_halfedges() > (h.size_of_vertices() + + h.size_of_facets() - 2 + 12) * 2.1 + || h.size_of_halfedges() < (h.size_of_vertices() + + h.size_of_facets() - 2) * 2 + ) + h.set_halfedges( int((h.size_of_vertices() + + h.size_of_facets() - 2 + 12) * 2.1)); + } + h.set_off_header( h.off()); + return in; +} + +} //namespace CGAL +// EOF // diff --git a/Stream_support/include/CGAL/IO/File_header_extended_OFF.h b/Stream_support/include/CGAL/IO/File_header_extended_OFF.h index 75679a488b2..8317be5b3bd 100644 --- a/Stream_support/include/CGAL/IO/File_header_extended_OFF.h +++ b/Stream_support/include/CGAL/IO/File_header_extended_OFF.h @@ -124,5 +124,10 @@ inline std::istream& skip_comment_OFF( std::istream& in) { } } //namespace CGAL + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_IO_FILE_HEADER_EXTENDED_OFF_H // // EOF // diff --git a/Stream_support/include/CGAL/IO/File_header_extended_OFF_impl.h b/Stream_support/include/CGAL/IO/File_header_extended_OFF_impl.h new file mode 100644 index 00000000000..0fad299f811 --- /dev/null +++ b/Stream_support/include/CGAL/IO/File_header_extended_OFF_impl.h @@ -0,0 +1,212 @@ +// Copyright (c) 1997 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Lutz Kettner + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + + +namespace CGAL { + +CGAL_INLINE_FUNCTION +bool File_header_extended_OFF:: +is_POL() const { + return is_OFF() && polyhedral_surface(); +} + +CGAL_INLINE_FUNCTION +bool File_header_extended_OFF:: +is_CBP() const { + return is_POL() && triangulated() && non_empty_facets() && + normalized_to_sphere() && radius() <= 1.0; +} + +CGAL_INLINE_FUNCTION +bool File_header_extended_OFF:: +is_TRN() const { return is_CBP() && terrain(); } + +CGAL_INLINE_FUNCTION +int File_header_extended_OFF:: +is_CBPn() const { + if ( is_POL() && triangulated() && non_empty_facets() && + normalized_to_sphere() && rounded() && + (radius() <= ( 1l << rounded_bits()))) + return rounded_bits(); + else + return 0; +} + +CGAL_INLINE_FUNCTION +int File_header_extended_OFF:: +is_TRNn() const { return ( terrain() ? is_CBPn() : 0); } + + +// The proper file suffix with respect to file format. +CGAL_INLINE_FUNCTION +std::string File_header_extended_OFF:: +suffix() const { + if ( is_TRNn()) { + std::ostringstream out; + out << "trn" << m_rounded_bits << '\0'; + return out.str(); + } + if ( is_TRN()) + return std::string("trn"); + if ( is_CBPn()) { + std::ostringstream out; + out << "cbp" << m_rounded_bits << '\0'; + return out.str(); + } + if ( is_CBP()) + return std::string("cbp"); + if ( is_POL()) + return std::string("pol"); + return std::string("off"); +} + +// The proper format name. +CGAL_INLINE_FUNCTION +std::string File_header_extended_OFF:: +format_name() const { + if ( is_TRNn()) { + std::ostringstream out; + out << "TRN" << m_rounded_bits << '\0'; + return out.str(); + } + if ( is_TRN()) + return std::string("TRN"); + if ( is_CBPn()) { + std::ostringstream out; + out << "CBP" << m_rounded_bits << '\0'; + return out.str(); + } + if ( is_CBP()) + return std::string("CBP"); + if ( is_POL()) + return std::string("POL"); + return std::string("OFF"); +} + +CGAL_INLINE_FUNCTION +File_header_extended_OFF& File_header_extended_OFF:: +operator+=( const File_header_extended_OFF& header) { + m_verbose = m_verbose || header.m_verbose; + m_polyhedral_surface = m_polyhedral_surface && + header.m_polyhedral_surface; + m_halfedges += header.m_halfedges; + m_triangulated = m_triangulated && header.m_triangulated; + m_non_empty_facets = m_non_empty_facets && + header.m_non_empty_facets; + m_terrain = m_terrain && header.m_terrain; + m_normalized_to_sphere = m_normalized_to_sphere && + header.m_normalized_to_sphere; + m_radius = (std::max)(m_radius, header.m_radius); + m_rounded = m_rounded && header.m_rounded; + m_rounded_bits = (std::max)( m_rounded_bits, + header.m_rounded_bits); + m_off_header = m_off_header && header.m_off_header; + return *this; +} + +#define CGAL_OUT(item) out << "# " #item " " << h.item() << '\n' +#define CGAL_OUTBOOL(item) out << "# " #item " " <<(h.item() ? '1':'0') << '\n' + +// Write extended header incl. CGAL/ENDCBP keywords. +CGAL_INLINE_FUNCTION +std::ostream& operator<<( std::ostream& out, + const File_header_extended_OFF& h) { + out << "#CBP\n"; + CGAL_OUTBOOL( polyhedral_surface); + CGAL_OUT( halfedges); + CGAL_OUTBOOL( triangulated); + CGAL_OUTBOOL( non_empty_facets); + CGAL_OUTBOOL( terrain); + CGAL_OUTBOOL( normalized_to_sphere); + CGAL_OUT( radius); + CGAL_OUTBOOL( rounded); + CGAL_OUT( rounded_bits); + out << "# ENDCBP\n" << std::endl; + return out; +} +#undef CGAL_OUT +#undef OUTBOOL + +#define CGAL_IN(item,type) \ + else if ( std::strcmp( keyword, #item) == 0) { \ + type t; \ + in >> t; \ + h.set_##item( t); \ + } + +#define CGAL_INBOOL(item) \ + else if ( std::strcmp( keyword, #item) == 0) { \ + in >> c; \ + h.set_##item( c == '1'); \ + } + +// Scan extended header. The CBP keyword must be read already. +CGAL_INLINE_FUNCTION +std::istream& operator>>( std::istream& in, File_header_extended_OFF& h) { + const int max_keyword = 42; + char c; + char keyword[max_keyword] = ""; + in >> keyword; + while ( in && std::strcmp( keyword, "ENDCBP") != 0) { + if ( std::strcmp( keyword, "#") == 0) + ; + CGAL_INBOOL( polyhedral_surface) + CGAL_IN( halfedges, int) + CGAL_INBOOL( triangulated) + CGAL_INBOOL( non_empty_facets) + CGAL_INBOOL( terrain) + CGAL_INBOOL( normalized_to_sphere) + CGAL_IN( radius, double) + CGAL_INBOOL( rounded) + CGAL_IN( rounded_bits, int) + else if ( h.verbose()) { + std::cerr << "warning: File_header_extended_OFF: unknown key '" + << keyword << "'." << std::endl; + } + in >> keyword; + } + in >> skip_until_EOL >> skip_comment_OFF; + return in; +} +#undef CGAL_IN +#undef CGAL_INBOOL + +} //namespace CGAL +// EOF // diff --git a/Stream_support/include/CGAL/IO/File_scanner_OFF.h b/Stream_support/include/CGAL/IO/File_scanner_OFF.h index 00227a0f943..a8a6dc9e950 100644 --- a/Stream_support/include/CGAL/IO/File_scanner_OFF.h +++ b/Stream_support/include/CGAL/IO/File_scanner_OFF.h @@ -462,5 +462,9 @@ file_scan_normal( File_scanner_OFF& scanner, Vector& v) { } //namespace CGAL +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_IO_FILE_SCANNER_OFF_H // // EOF // diff --git a/Stream_support/include/CGAL/IO/File_scanner_OFF_impl.h b/Stream_support/include/CGAL/IO/File_scanner_OFF_impl.h new file mode 100644 index 00000000000..36e2e8d393e --- /dev/null +++ b/Stream_support/include/CGAL/IO/File_scanner_OFF_impl.h @@ -0,0 +1,133 @@ +// Copyright (c) 1997 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Lutz Kettner + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include +#include +#include + +namespace CGAL { + +CGAL_INLINE_FUNCTION +void +File_scanner_OFF:: +skip_to_next_vertex( std::size_t current_vertex) { + CGAL_assertion( current_vertex < size_of_vertices()); + if ( binary()) { + float f; + if ( has_normals() && ! normals_read) { + I_Binary_read_big_endian_float32( m_in, f); + I_Binary_read_big_endian_float32( m_in, f); + I_Binary_read_big_endian_float32( m_in, f); + if ( is_homogeneous()) + I_Binary_read_big_endian_float32( m_in, f); + } + if ( has_colors()) { + // It is not well stated in the Geomview manual + // how color is coded following a vertex. It is + // parsed similar to the optional color for facets. + boost::int32_t k; + I_Binary_read_big_endian_integer32( m_in, k); + if (k<0 || k>4) { + m_in.clear( std::ios::badbit); + if ( verbose()) { + std::cerr << " " << std::endl; + std::cerr << "File_scanner_OFF::" << std::endl; + std::cerr << "skip_to_next_vertex(): input error: bad " + " number of color indices at vertex " + << current_vertex << "." << std::endl; + } + set_off_header( false); + return; + } + while (k--) { + float dummy; + I_Binary_read_big_endian_float32( m_in, dummy); + } + } + } else { + if ( has_normals() && ! normals_read) { + double dummy; + if ( is_homogeneous()) { + m_in >> dummy >> dummy >> dummy >> dummy; + } else { + m_in >> dummy >> dummy >> dummy; + } + } + if ( has_colors()) { // skip color entries (1 to 4) + m_in >> skip_until_EOL; + } + } + if( ! m_in) { + if ( verbose()) { + std::cerr << " " << std::endl; + std::cerr << "File_scanner_OFF::" << std::endl; + std::cerr << "skip_to_next_vertex(): input error: cannot read " + "OFF file beyond vertex " << current_vertex << "." + << std::endl; + } + set_off_header( false); + return; + } + normals_read = false; +} + +CGAL_INLINE_FUNCTION +void +File_scanner_OFF:: +skip_to_next_facet( std::size_t current_facet) { + // Take care of trailing informations like color triples. + if ( binary()) { + boost::int32_t k; + I_Binary_read_big_endian_integer32( m_in, k); + if (k<0 || k>4) { + m_in.clear( std::ios::badbit); + if ( verbose()) { + std::cerr << " " << std::endl; + std::cerr << "File_scanner_OFF::" << std::endl; + std::cerr << "skip_to_next_facet(): input error: bad " + "number of color indices at vertex " + << current_facet << "." << std::endl; + } + set_off_header( false); + return; + } + while (k--) { + float dummy; + I_Binary_read_big_endian_float32( m_in, dummy); + } + } else { + m_in >> skip_until_EOL; + } +} + +} //namespace CGAL +// EOF // diff --git a/Stream_support/include/CGAL/IO/File_writer_OFF.h b/Stream_support/include/CGAL/IO/File_writer_OFF.h index ae1d35b568f..12555671468 100644 --- a/Stream_support/include/CGAL/IO/File_writer_OFF.h +++ b/Stream_support/include/CGAL/IO/File_writer_OFF.h @@ -104,5 +104,10 @@ public: }; } //namespace CGAL + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_IO_FILE_WRITER_OFF_H // // EOF // diff --git a/Stream_support/include/CGAL/IO/File_writer_OFF_impl.h b/Stream_support/include/CGAL/IO/File_writer_OFF_impl.h new file mode 100644 index 00000000000..936e8d5b36b --- /dev/null +++ b/Stream_support/include/CGAL/IO/File_writer_OFF_impl.h @@ -0,0 +1,56 @@ +// Copyright (c) 1997 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Lutz Kettner + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include + +namespace CGAL { + +CGAL_INLINE_FUNCTION +void +File_writer_OFF:: +write_header( std::ostream& o, + std::size_t vertices, + std::size_t halfedges, + std::size_t facets, + bool normals) { + m_out = &o; + m_header.set_vertices( vertices); + // Don't. This halfdges aren't trusted: + // m_header.set_halfedges( halfedges); + (void)halfedges; + m_header.set_facets( facets); + m_header.set_normals( normals); + // Print header. + out() << m_header; +} +} //namespace CGAL +// EOF // diff --git a/Stream_support/include/CGAL/IO/File_writer_VRML_2.h b/Stream_support/include/CGAL/IO/File_writer_VRML_2.h index 174f8ad307a..69b7c0ffa95 100644 --- a/Stream_support/include/CGAL/IO/File_writer_VRML_2.h +++ b/Stream_support/include/CGAL/IO/File_writer_VRML_2.h @@ -55,5 +55,10 @@ public: }; } //namespace CGAL + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_IO_FILE_WRITER_VRML_2_H // // EOF // diff --git a/Stream_support/include/CGAL/IO/File_writer_VRML_2_impl.h b/Stream_support/include/CGAL/IO/File_writer_VRML_2_impl.h new file mode 100644 index 00000000000..7e807711f88 --- /dev/null +++ b/Stream_support/include/CGAL/IO/File_writer_VRML_2_impl.h @@ -0,0 +1,82 @@ +// Copyright (c) 1997 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Lutz Kettner + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include + +namespace CGAL { + +CGAL_INLINE_FUNCTION +void +File_writer_VRML_2:: +write_header( std::ostream& o, + std::size_t vertices, + std::size_t halfedges, + std::size_t facets) { + m_out = &o; + m_facets = facets; + + out() << " #-- Begin of Polyhedron_3\n"; + out() << " # " << vertices << " vertices\n"; + out() << " # " << halfedges << " halfedges\n"; + out() << " # " << facets << " facets\n"; + out() << " Group {\n" + " children [\n" + " Shape {\n" + " appearance Appearance { material " + "USE Material }\n" + " geometry IndexedFaceSet {\n" + " convex FALSE\n" + " solid FALSE\n" + " coord Coordinate {\n" + " point [" << std::endl; +} + +void +File_writer_VRML_2:: +write_facet_header() const { + out() << " ] #point\n" + " } #coord Coordinate\n" + " coordIndex [" << std::endl; +} + +void +File_writer_VRML_2:: +write_footer() const { + out() << " ] #coordIndex\n" + " } #geometry\n" + " } #Shape\n" + " ] #children\n" + " } #Group" << std::endl; +} + +} //namespace CGAL +// EOF // diff --git a/Stream_support/include/CGAL/IO/File_writer_inventor.h b/Stream_support/include/CGAL/IO/File_writer_inventor.h index b6948d06d81..4b49bee0750 100644 --- a/Stream_support/include/CGAL/IO/File_writer_inventor.h +++ b/Stream_support/include/CGAL/IO/File_writer_inventor.h @@ -52,5 +52,10 @@ public: }; } //namespace CGAL + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_IO_FILE_WRITER_INVENTOR_H // // EOF // diff --git a/Stream_support/include/CGAL/IO/File_writer_inventor_impl.h b/Stream_support/include/CGAL/IO/File_writer_inventor_impl.h new file mode 100644 index 00000000000..3cfda77aacf --- /dev/null +++ b/Stream_support/include/CGAL/IO/File_writer_inventor_impl.h @@ -0,0 +1,73 @@ +// Copyright (c) 1997 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Lutz Kettner + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include + +namespace CGAL { + +CGAL_INLINE_FUNCTION +void +File_writer_inventor:: +write_header( std::ostream& o, + std::size_t vertices, + std::size_t halfedges, + std::size_t facets){ + m_out = &o; + m_facets = facets; + out() << "# " << vertices << " vertices\n"; + out() << "# " << halfedges << " halfedges\n"; + out() << "# " << facets << " facets\n\n"; + out() << "Separator {\n" + " Coordinate3 {\n" + " point [" << std::endl; +} + +CGAL_INLINE_FUNCTION +void +File_writer_inventor:: +write_facet_header() const { + out() << " ] #point\n" + " } #Coordinate3\n" + " # " << m_facets << " facets\n" + " IndexedFaceSet {\n" + " coordIndex [\n"; +} + +CGAL_INLINE_FUNCTION +void +File_writer_inventor:: +write_footer() const { + out() << " ] #coordIndex\n" + " } #IndexedFaceSet\n" + "} #Separator" << std::endl; +} + +} //namespace CGAL +// EOF // diff --git a/Stream_support/include/CGAL/IO/File_writer_wavefront.h b/Stream_support/include/CGAL/IO/File_writer_wavefront.h index d3ee8cbf05e..bd4fee51eaa 100644 --- a/Stream_support/include/CGAL/IO/File_writer_wavefront.h +++ b/Stream_support/include/CGAL/IO/File_writer_wavefront.h @@ -56,5 +56,10 @@ public: }; } //namespace CGAL + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_IO_FILE_WRITER_WAVEFRONT_H // // EOF // diff --git a/Stream_support/include/CGAL/IO/File_writer_wavefront_impl.h b/Stream_support/include/CGAL/IO/File_writer_wavefront_impl.h new file mode 100644 index 00000000000..82691d5ec07 --- /dev/null +++ b/Stream_support/include/CGAL/IO/File_writer_wavefront_impl.h @@ -0,0 +1,57 @@ +// Copyright (c) 1997 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Lutz Kettner + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include +#include + +namespace CGAL { + +CGAL_INLINE_FUNCTION +void +File_writer_wavefront:: +write_header( std::ostream& o, + std::size_t vertices, + std::size_t halfedges, + std::size_t facets){ + m_out = &o; + m_facets = facets; + // Print header. + out() << "# file written from a CGAL tool in Wavefront obj format\n"; + out() << "# " << vertices << " vertices\n"; + out() << "# " << halfedges << " halfedges\n"; + out() << "# " << facets << " facets\n\n"; + + out() << "\n# " << vertices << " vertices\n"; + out() << "# ------------------------------------------\n\n"; +} + +} //namespace CGAL +// EOF // diff --git a/Stream_support/include/CGAL/IO/io.h b/Stream_support/include/CGAL/IO/io.h index 949f2253539..4b5b2ea36c2 100644 --- a/Stream_support/include/CGAL/IO/io.h +++ b/Stream_support/include/CGAL/IO/io.h @@ -40,7 +40,17 @@ namespace CGAL { class IO { public: - CGAL_EXPORT static int mode; +#ifndef CGAL_HEADER_ONLY + CGAL_EXPORT static int mode; + static int& get_static_mode() + { return IO::mode; } +#else // CGAL_HEADER_ONLY + static int& get_static_mode() + { + static int mode = std::ios::xalloc(); + return mode; + } +#endif // CGAL_HEADER_ONLY enum Mode {ASCII = 0, PRETTY, BINARY}; }; @@ -92,7 +102,6 @@ public: std::istream& operator()( std::istream& in) const { return (in >> t); } }; - #if CGAL_FORCE_IFORMAT_DOUBLE || \ ( ( _MSC_VER > 1600 ) && (! defined( CGAL_NO_IFORMAT_DOUBLE )) ) template <> @@ -226,7 +235,6 @@ bool is_binary(std::ios& i); - template < class T > inline void @@ -302,7 +310,7 @@ read(std::istream& is, T& t) inline std::ostream& operator<<( std::ostream& out, const Color& col) { - switch(out.iword(IO::mode)) { + switch(get_mode(out)) { case IO::ASCII : return out << static_cast(col.red()) << ' ' << static_cast(col.green()) << ' ' @@ -323,7 +331,7 @@ inline std::istream &operator>>(std::istream &is, Color& col) { int r = 0, g = 0, b = 0; - switch(is.iword(IO::mode)) { + switch(get_mode(is)) { case IO::ASCII : is >> r >> g >> b; break; @@ -351,8 +359,11 @@ void swallow(std::istream &is, char d); CGAL_EXPORT void swallow(std::istream &is, const std::string& s ); - - } //namespace CGAL + +#ifdef CGAL_HEADER_ONLY +#include +#endif // CGAL_HEADER_ONLY + #endif // CGAL_IO_H diff --git a/Stream_support/include/CGAL/IO/io_impl.h b/Stream_support/include/CGAL/IO/io_impl.h new file mode 100644 index 00000000000..ee84373d5a4 --- /dev/null +++ b/Stream_support/include/CGAL/IO/io_impl.h @@ -0,0 +1,136 @@ +// Copyright (c) 1997 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Andreas Fabri + +#ifdef CGAL_HEADER_ONLY +#define CGAL_INLINE_FUNCTION inline +#else +#define CGAL_INLINE_FUNCTION +#endif + +#include +#include + +#include +#include + +namespace CGAL { + +CGAL_INLINE_FUNCTION +IO::Mode +get_mode(std::ios& i) +{ + return static_cast(i.iword(IO::get_static_mode())); +} + +CGAL_INLINE_FUNCTION +IO::Mode +set_ascii_mode(std::ios& i) +{ + IO::Mode m = get_mode(i); + i.iword(IO::get_static_mode()) = IO::ASCII; + return m; +} + +CGAL_INLINE_FUNCTION +IO::Mode +set_binary_mode(std::ios& i) +{ + IO::Mode m = get_mode(i); + i.iword(IO::get_static_mode()) = IO::BINARY; + return m; +} + + +CGAL_INLINE_FUNCTION +IO::Mode +set_pretty_mode(std::ios& i) +{ + IO::Mode m = get_mode(i); + i.iword(IO::get_static_mode()) = IO::PRETTY; + return m; +} + +CGAL_INLINE_FUNCTION +IO::Mode +set_mode(std::ios& i, IO::Mode m) +{ + IO::Mode old = get_mode(i); + i.iword(IO::get_static_mode()) = m; + return old; +} + +CGAL_INLINE_FUNCTION +bool +is_pretty(std::ios& i) +{ + return i.iword(IO::get_static_mode()) == IO::PRETTY; +} + +CGAL_INLINE_FUNCTION +bool +is_ascii(std::ios& i) +{ + return i.iword(IO::get_static_mode()) == IO::ASCII; +} + +CGAL_INLINE_FUNCTION +bool +is_binary(std::ios& i) +{ + return i.iword(IO::get_static_mode()) == IO::BINARY; +} + +CGAL_INLINE_FUNCTION +const char* +mode_name( IO::Mode m) { + static const char* const names[] = {"ASCII", "PRETTY", "BINARY" }; + CGAL_assertion( IO::ASCII <= m && m <= IO::BINARY ); + return names[m]; +} + +CGAL_INLINE_FUNCTION +void +swallow(std::istream &is, char d) { + char c; + do is.get(c); while (isspace(c)); + if (c != d) { + std::stringstream msg; + msg << "input error: expected '" << d << "' but got '" << c << "'"; + CGAL_error_msg( msg.str().c_str() ); + } +} + +CGAL_INLINE_FUNCTION +void +swallow(std::istream &is, const std::string& s ) { + std::string t; + is >> t; + if (s != t) { + std::stringstream msg; + msg << "input error: expected '" << s << "' but got '" << t << "'"; + CGAL_error_msg( msg.str().c_str() ); + } +} + +} //namespace CGAL diff --git a/Stream_support/src/CGAL/Color.cpp b/Stream_support/src/CGAL/Color.cpp index 55bc10aff7d..3d4e3bf882d 100644 --- a/Stream_support/src/CGAL/Color.cpp +++ b/Stream_support/src/CGAL/Color.cpp @@ -22,25 +22,9 @@ // // Author(s) : Andreas Fabri, Hervé Brönnimann +#ifndef CGAL_HEADER_ONLY + #include +#include - -namespace CGAL { - -const Color BLACK = Color(0, 0, 0); -const Color WHITE = Color(255, 255, 255); -const Color GRAY = Color(100,100,100); - -const Color GREEN = Color(0, 255, 0); - -const Color DEEPBLUE = Color(10, 0, 100); -const Color BLUE = Color(0, 0, 255); -const Color VIOLET = Color(255, 0, 255); -const Color PURPLE = Color(100, 0, 70); - -const Color RED = Color(255, 0, 0); -const Color ORANGE = Color(235, 150, 0); -const Color YELLOW = Color(255, 255, 0); - -} //namespace CGAL - +#endif // CGAL_HEADER_ONLY diff --git a/Stream_support/src/CGAL/File_header_OFF.cpp b/Stream_support/src/CGAL/File_header_OFF.cpp index 71112bbca18..c70a2c3a0bf 100644 --- a/Stream_support/src/CGAL/File_header_OFF.cpp +++ b/Stream_support/src/CGAL/File_header_OFF.cpp @@ -22,371 +22,11 @@ // // Author(s) : Lutz Kettner -#include -#include -#include -#include -#include -#include +#ifndef CGAL_HEADER_ONLY + #include -#include -#include +#include -namespace CGAL { +#endif // CGAL_HEADER_ONLY -File_header_OFF::File_header_OFF( bool verbose) -: File_header_extended_OFF( verbose), - n_vertices(0), - n_facets(0), - m_skel(false), - m_binary(false), - m_no_comments(false), - m_offset(0), - m_colors(false), - m_normals(false), - m_tag4(false), - m_tagDim(false), - m_dim(3) -{} -File_header_OFF::File_header_OFF( - bool binary, bool noc, bool skel, bool verbose) -: File_header_extended_OFF( verbose), - n_vertices(0), - n_facets(0), - m_skel(skel), - m_binary(binary), - m_no_comments(noc), - m_offset(0), - m_colors(false), - m_normals(false), - m_tag4(false), - m_tagDim(false), - m_dim(3) -{} -//File_header_OFF::File_header_OFF( int v, int h, int f, -// bool verbose) -//: File_header_extended_OFF( verbose), -// n_vertices(v), -// n_facets(f), -// m_skel(false), -// m_binary(false), -// m_no_comments(false), -// m_offset(0), -// m_colors(false), -// m_normals(false), -// m_tag4(false), -// m_tagDim(false), -// m_dim(3) -//{ -// set_halfedges(h); -//} -File_header_OFF::File_header_OFF( std::size_t v, std::size_t h, std::size_t f, - bool binary, bool noc, bool skel, bool verbose) -: File_header_extended_OFF( verbose), - n_vertices(v), - n_facets(f), - m_skel(skel), - m_binary(binary), - m_no_comments(noc), - m_offset(0), - m_colors(false), - m_normals(false), - m_tag4(false), - m_tagDim(false), - m_dim(3) -{ - set_halfedges(h); -} -File_header_OFF::File_header_OFF( - const File_header_extended_OFF& ext_header) -: File_header_extended_OFF( ext_header), - n_vertices(0), - n_facets(0), - m_skel(false), - m_binary(false), - m_no_comments(false), - m_offset(0), - m_colors(false), - m_normals(false), - m_tag4(false), - m_tagDim(false), - m_dim(3) -{} -File_header_OFF::File_header_OFF( - const File_header_extended_OFF& ext_header, - bool binary, bool noc, bool skel) -: File_header_extended_OFF( ext_header), - n_vertices(0), - n_facets(0), - m_skel(skel), - m_binary(binary), - m_no_comments(noc), - m_offset(0), - m_colors(false), - m_normals(false), - m_tag4(false), - m_tagDim(false), - m_dim(3) -{} -File_header_OFF::File_header_OFF( - std::size_t v, std::size_t h, std::size_t f, - const File_header_extended_OFF& ext_header) -: File_header_extended_OFF( ext_header), - n_vertices(v), - n_facets(f), - m_skel(false), - m_binary(false), - m_no_comments(false), - m_offset(0), - m_colors(false), - m_normals(false), - m_tag4(false), - m_tagDim(false), - m_dim(3) -{ - set_halfedges(h); -} -File_header_OFF::File_header_OFF( - std::size_t v, std::size_t h, std::size_t f, - const File_header_extended_OFF& ext_header, - bool binary, bool noc, bool skel) -: File_header_extended_OFF( ext_header), - n_vertices(v), - n_facets(f), - m_skel(skel), - m_binary(binary), - m_no_comments(noc), - m_offset(0), - m_colors(false), - m_normals(false), - m_tag4(false), - m_tagDim(false), - m_dim(3) -{ - set_halfedges(h); -} - -File_header_OFF& File_header_OFF:: -operator+=( const File_header_OFF& header) { - (File_header_extended_OFF&)(*this) = header; - n_vertices += header.n_vertices; - n_facets += header.n_facets; - return *this; -} - -// Write header. -std::ostream& operator<<( std::ostream& out, const File_header_OFF& h) { - if ( h.comments()) { - out << "# Output of a CGAL tool\n"; - out << static_cast( h); - } - if ( h.has_normals()) - out << 'N'; - if ( h.skel()) - out << "SKEL"; - else - out << "OFF"; - if ( h.binary()) { - out << " BINARY\n"; - I_Binary_write_big_endian_integer32( out, static_cast(h.size_of_vertices())); - I_Binary_write_big_endian_integer32( out, static_cast(h.size_of_facets())); - if ( h.off()) - I_Binary_write_big_endian_integer32( out, 0); - } else { - out << '\n'; - out << h.size_of_vertices() << ' '<< h.size_of_facets(); - if ( h.off()) - out << " 0"; - if ( h.comments()) { - out << "\n\n# " << h.size_of_vertices() << " vertices\n"; - out << "# ------------------------------------------\n"; - } - out << std::endl; - } - return out; -} - -// Scan header. Marks streams badbit if not in SKEL format nor in OFF. -std::istream& operator>>( std::istream& in, File_header_OFF& h) { - // read in the first character and scan for comments, `OFF', or `NOFF', - // or `SKEL', or `4SKEL'. - h.set_off_header( false); - char c; - while ( (in >> c) && c == '#') { - if ( in.get(c) && c == 'C' && - in.get(c) && c == 'B' && - in.get(c) && c == 'P') { - in >> static_cast( h); - } else if ( c != '\n') - in >> skip_until_EOL; - } - if ( ! in) - return in; - h.set_skel( false); - h.set_binary( false); - h.set_index_offset( 1); - h.set_colors( false); - h.set_normals( false); - h.set_homogeneous( false); - h.set_dimensional( false); - h.set_dimension( 3); - - const int max_keyword = 42; - char keyword[max_keyword] = ""; - int i = 0; - keyword[i++] = c; - while( i < max_keyword - 1 && in.get(c) && std::isalnum(c)) - keyword[i++] = c; - keyword[i] = '\0'; - if ( i < 2 || (std::isdigit(keyword[0]) && keyword[0] != '4') - || std::isdigit(keyword[1])) { - h.set_vertices( std::atoi( keyword)); - } else { - h.set_index_offset( 0); - int j = 0; - if ( j < i && keyword[j] == 'C') { - h.set_colors( true); - j++; - } - if ( j < i && keyword[j] == 'N') { - h.set_normals( true); - j++; - } - if ( j < i && keyword[j] == '4') { - h.set_homogeneous( true); - j++; - } - if ( j < i && keyword[j] == 'n') { - h.set_dimensional( true); - j++; - } - if ( i-j != 3 || keyword[j] != 'O' - || keyword[j+1] != 'F' - || keyword[j+2] != 'F') { - if ( i-j != 4 || keyword[j] != 'S' - || keyword[j+1] != 'K' - || keyword[j+2] != 'E' - || keyword[j+3] != 'L') { - in.clear( std::ios::badbit); - if ( h.verbose()) { - std::cerr << " " << std::endl; - std::cerr << "error: File_header_OFF: " - "wrong format: neither OFF nor SKEL." - << std::endl; - } - return in; - } else { - h.set_skel( true); - } - } - in >> skip_comment_OFF >> c; - if ( std::isdigit(c)) { - in.putback(c); - int n; - in >> n; - h.set_vertices(n); - } else { - i = 0; - keyword[i++] = c; - while( i < max_keyword - 1 && in.get(c) && - std::isalnum(c)) - keyword[i++] = c; - keyword[i] = '\0'; - if ( std::strcmp( keyword, "BINARY") == 0) { - h.set_binary( true); - if ( c != '\n') - in >> skip_until_EOL; - } else { - in.clear( std::ios::badbit); - if ( h.verbose()) { - std::cerr << " " << std::endl; - std::cerr << "error: File_header_OFF(): " - "wrong format: neither OFF nor SKEL." - << std::endl; - } - return in; - } - } - } - // Read remaining size value(s). - int n_h; - if ( h.binary()) { - boost::int32_t a, b, c; - I_Binary_read_big_endian_integer32( in, a); - if ( h.n_dimensional()) { - h.set_dimension( a); - I_Binary_read_big_endian_integer32( in, a); - } - I_Binary_read_big_endian_integer32( in, b); - if ( h.off()) - I_Binary_read_big_endian_integer32( in, c); - else - c = 0; - h.set_vertices( a); - if (b<0){ - in.clear( std::ios::badbit ); - if ( h.verbose()) { - std::cerr << " " << std::endl; - std::cerr << "error: File_header_OFF(): File contains < 0 facets." - << std::endl; - } - return in; - } - h.set_facets( b); - n_h = c; - } else { - int n; - if ( h.n_dimensional()) { - h.set_dimension( static_cast(h.size_of_vertices())); - in >> n; - h.set_vertices(n); - } - in >> n; - if (n < 0){ - in.clear( std::ios::badbit ); - if ( h.verbose()) { - std::cerr << " " << std::endl; - std::cerr << "error: File_header_OFF(): File contains < 0 facets." - << std::endl; - } - return in; - } - h.set_facets(n); - if ( h.off()) - in >> n_h; - else - n_h = 0; - } - if ( n_h == 0) - h.set_index_offset( 0); - if ( ! in || h.size_of_vertices() <= 0 ) { - in.clear( std::ios::badbit); - if ( h.verbose()) { - std::cerr << " " << std::endl; - std::cerr << "error: File_header_OFF(): File contains <= 0 vertices." - << std::endl; - } - return in; - } - if ( h.size_of_halfedges() == 0) { - // be careful, because border edges count twice - h.set_halfedges( 2 * n_h); - // check against the Eulerian equation for connected planar graphs. - // We do not know the number of holes we must represent as dummy - // facets and we do not know the genus of the surface. - // So we add 12 and a factor of 5 percent. - if ( h.size_of_halfedges() == 0 - || h.size_of_halfedges() > (h.size_of_vertices() - + h.size_of_facets() - 2 + 12) * 2.1 - || h.size_of_halfedges() < (h.size_of_vertices() - + h.size_of_facets() - 2) * 2 - ) - h.set_halfedges( int((h.size_of_vertices() + - h.size_of_facets() - 2 + 12) * 2.1)); - } - h.set_off_header( h.off()); - return in; -} - -} //namespace CGAL // EOF // diff --git a/Stream_support/src/CGAL/File_header_extended_OFF.cpp b/Stream_support/src/CGAL/File_header_extended_OFF.cpp index 3f709ff65fa..735fe404387 100644 --- a/Stream_support/src/CGAL/File_header_extended_OFF.cpp +++ b/Stream_support/src/CGAL/File_header_extended_OFF.cpp @@ -22,175 +22,11 @@ // // Author(s) : Lutz Kettner +#ifndef CGAL_HEADER_ONLY + #include -#include +#include -#include -#include -#include -#include -#include -#include +#endif // CGAL_HEADER_ONLY - -namespace CGAL { - -bool File_header_extended_OFF:: -is_POL() const { - return is_OFF() && polyhedral_surface(); -} - -bool File_header_extended_OFF:: -is_CBP() const { - return is_POL() && triangulated() && non_empty_facets() && - normalized_to_sphere() && radius() <= 1.0; -} - -bool File_header_extended_OFF:: -is_TRN() const { return is_CBP() && terrain(); } - -int File_header_extended_OFF:: -is_CBPn() const { - if ( is_POL() && triangulated() && non_empty_facets() && - normalized_to_sphere() && rounded() && - (radius() <= ( 1l << rounded_bits()))) - return rounded_bits(); - else - return 0; -} - -int File_header_extended_OFF:: -is_TRNn() const { return ( terrain() ? is_CBPn() : 0); } - - -// The proper file suffix with respect to file format. -std::string File_header_extended_OFF:: -suffix() const { - if ( is_TRNn()) { - std::ostringstream out; - out << "trn" << m_rounded_bits << '\0'; - return out.str(); - } - if ( is_TRN()) - return std::string("trn"); - if ( is_CBPn()) { - std::ostringstream out; - out << "cbp" << m_rounded_bits << '\0'; - return out.str(); - } - if ( is_CBP()) - return std::string("cbp"); - if ( is_POL()) - return std::string("pol"); - return std::string("off"); -} - -// The proper format name. -std::string File_header_extended_OFF:: -format_name() const { - if ( is_TRNn()) { - std::ostringstream out; - out << "TRN" << m_rounded_bits << '\0'; - return out.str(); - } - if ( is_TRN()) - return std::string("TRN"); - if ( is_CBPn()) { - std::ostringstream out; - out << "CBP" << m_rounded_bits << '\0'; - return out.str(); - } - if ( is_CBP()) - return std::string("CBP"); - if ( is_POL()) - return std::string("POL"); - return std::string("OFF"); -} - -File_header_extended_OFF& File_header_extended_OFF:: -operator+=( const File_header_extended_OFF& header) { - m_verbose = m_verbose || header.m_verbose; - m_polyhedral_surface = m_polyhedral_surface && - header.m_polyhedral_surface; - m_halfedges += header.m_halfedges; - m_triangulated = m_triangulated && header.m_triangulated; - m_non_empty_facets = m_non_empty_facets && - header.m_non_empty_facets; - m_terrain = m_terrain && header.m_terrain; - m_normalized_to_sphere = m_normalized_to_sphere && - header.m_normalized_to_sphere; - m_radius = (std::max)(m_radius, header.m_radius); - m_rounded = m_rounded && header.m_rounded; - m_rounded_bits = (std::max)( m_rounded_bits, - header.m_rounded_bits); - m_off_header = m_off_header && header.m_off_header; - return *this; -} - -#define CGAL_OUT(item) out << "# " #item " " << h.item() << '\n' -#define CGAL_OUTBOOL(item) out << "# " #item " " <<(h.item() ? '1':'0') << '\n' - -// Write extended header incl. CGAL/ENDCBP keywords. -std::ostream& operator<<( std::ostream& out, - const File_header_extended_OFF& h) { - out << "#CBP\n"; - CGAL_OUTBOOL( polyhedral_surface); - CGAL_OUT( halfedges); - CGAL_OUTBOOL( triangulated); - CGAL_OUTBOOL( non_empty_facets); - CGAL_OUTBOOL( terrain); - CGAL_OUTBOOL( normalized_to_sphere); - CGAL_OUT( radius); - CGAL_OUTBOOL( rounded); - CGAL_OUT( rounded_bits); - out << "# ENDCBP\n" << std::endl; - return out; -} -#undef CGAL_OUT -#undef OUTBOOL - -#define CGAL_IN(item,type) \ - else if ( std::strcmp( keyword, #item) == 0) { \ - type t; \ - in >> t; \ - h.set_##item( t); \ - } - -#define CGAL_INBOOL(item) \ - else if ( std::strcmp( keyword, #item) == 0) { \ - in >> c; \ - h.set_##item( c == '1'); \ - } - -// Scan extended header. The CBP keyword must be read already. -std::istream& operator>>( std::istream& in, File_header_extended_OFF& h) { - const int max_keyword = 42; - char c; - char keyword[max_keyword] = ""; - in >> keyword; - while ( in && std::strcmp( keyword, "ENDCBP") != 0) { - if ( std::strcmp( keyword, "#") == 0) - ; - CGAL_INBOOL( polyhedral_surface) - CGAL_IN( halfedges, int) - CGAL_INBOOL( triangulated) - CGAL_INBOOL( non_empty_facets) - CGAL_INBOOL( terrain) - CGAL_INBOOL( normalized_to_sphere) - CGAL_IN( radius, double) - CGAL_INBOOL( rounded) - CGAL_IN( rounded_bits, int) - else if ( h.verbose()) { - std::cerr << "warning: File_header_extended_OFF: unknown key '" - << keyword << "'." << std::endl; - } - in >> keyword; - } - in >> skip_until_EOL >> skip_comment_OFF; - return in; -} -#undef CGAL_IN -#undef CGAL_INBOOL - -} //namespace CGAL // EOF // diff --git a/Stream_support/src/CGAL/File_scanner_OFF.cpp b/Stream_support/src/CGAL/File_scanner_OFF.cpp index 3361a458680..b7e1ed08838 100644 --- a/Stream_support/src/CGAL/File_scanner_OFF.cpp +++ b/Stream_support/src/CGAL/File_scanner_OFF.cpp @@ -22,104 +22,11 @@ // // Author(s) : Lutz Kettner -#include -#include -#include -#include +#ifndef CGAL_HEADER_ONLY + #include +#include -namespace CGAL { +#endif // CGAL_HEADER_ONLY -void -File_scanner_OFF:: -skip_to_next_vertex( std::size_t current_vertex) { - CGAL_assertion( current_vertex < size_of_vertices()); - if ( binary()) { - float f; - if ( has_normals() && ! normals_read) { - I_Binary_read_big_endian_float32( m_in, f); - I_Binary_read_big_endian_float32( m_in, f); - I_Binary_read_big_endian_float32( m_in, f); - if ( is_homogeneous()) - I_Binary_read_big_endian_float32( m_in, f); - } - if ( has_colors()) { - // It is not well stated in the Geomview manual - // how color is coded following a vertex. It is - // parsed similar to the optional color for facets. - boost::int32_t k; - I_Binary_read_big_endian_integer32( m_in, k); - if (k<0 || k>4) { - m_in.clear( std::ios::badbit); - if ( verbose()) { - std::cerr << " " << std::endl; - std::cerr << "File_scanner_OFF::" << std::endl; - std::cerr << "skip_to_next_vertex(): input error: bad " - " number of color indices at vertex " - << current_vertex << "." << std::endl; - } - set_off_header( false); - return; - } - while (k--) { - float dummy; - I_Binary_read_big_endian_float32( m_in, dummy); - } - } - } else { - if ( has_normals() && ! normals_read) { - double dummy; - if ( is_homogeneous()) { - m_in >> dummy >> dummy >> dummy >> dummy; - } else { - m_in >> dummy >> dummy >> dummy; - } - } - if ( has_colors()) { // skip color entries (1 to 4) - m_in >> skip_until_EOL; - } - } - if( ! m_in) { - if ( verbose()) { - std::cerr << " " << std::endl; - std::cerr << "File_scanner_OFF::" << std::endl; - std::cerr << "skip_to_next_vertex(): input error: cannot read " - "OFF file beyond vertex " << current_vertex << "." - << std::endl; - } - set_off_header( false); - return; - } - normals_read = false; -} - -void -File_scanner_OFF:: -skip_to_next_facet( std::size_t current_facet) { - // Take care of trailing informations like color triples. - if ( binary()) { - boost::int32_t k; - I_Binary_read_big_endian_integer32( m_in, k); - if (k<0 || k>4) { - m_in.clear( std::ios::badbit); - if ( verbose()) { - std::cerr << " " << std::endl; - std::cerr << "File_scanner_OFF::" << std::endl; - std::cerr << "skip_to_next_facet(): input error: bad " - "number of color indices at vertex " - << current_facet << "." << std::endl; - } - set_off_header( false); - return; - } - while (k--) { - float dummy; - I_Binary_read_big_endian_float32( m_in, dummy); - } - } else { - m_in >> skip_until_EOL; - } -} - -} //namespace CGAL // EOF // diff --git a/Stream_support/src/CGAL/File_writer_OFF.cpp b/Stream_support/src/CGAL/File_writer_OFF.cpp index cb288f2d6b4..6162f9ad34e 100644 --- a/Stream_support/src/CGAL/File_writer_OFF.cpp +++ b/Stream_support/src/CGAL/File_writer_OFF.cpp @@ -22,28 +22,11 @@ // // Author(s) : Lutz Kettner -#include -#include +#ifndef CGAL_HEADER_ONLY + #include +#include -namespace CGAL { +#endif // CGAL_HEADER_ONLY -void -File_writer_OFF:: -write_header( std::ostream& o, - std::size_t vertices, - std::size_t halfedges, - std::size_t facets, - bool normals) { - m_out = &o; - m_header.set_vertices( vertices); - // Don't. This halfdges aren't trusted: - // m_header.set_halfedges( halfedges); - (void)halfedges; - m_header.set_facets( facets); - m_header.set_normals( normals); - // Print header. - out() << m_header; -} -} //namespace CGAL // EOF // diff --git a/Stream_support/src/CGAL/File_writer_VRML_2.cpp b/Stream_support/src/CGAL/File_writer_VRML_2.cpp index ecec30c2535..a595f0f3b48 100644 --- a/Stream_support/src/CGAL/File_writer_VRML_2.cpp +++ b/Stream_support/src/CGAL/File_writer_VRML_2.cpp @@ -22,54 +22,11 @@ // // Author(s) : Lutz Kettner -#include -#include +#ifndef CGAL_HEADER_ONLY + #include +#include -namespace CGAL { +#endif // CGAL_HEADER_ONLY -void -File_writer_VRML_2:: -write_header( std::ostream& o, - std::size_t vertices, - std::size_t halfedges, - std::size_t facets) { - m_out = &o; - m_facets = facets; - - out() << " #-- Begin of Polyhedron_3\n"; - out() << " # " << vertices << " vertices\n"; - out() << " # " << halfedges << " halfedges\n"; - out() << " # " << facets << " facets\n"; - out() << " Group {\n" - " children [\n" - " Shape {\n" - " appearance Appearance { material " - "USE Material }\n" - " geometry IndexedFaceSet {\n" - " convex FALSE\n" - " solid FALSE\n" - " coord Coordinate {\n" - " point [" << std::endl; -} - -void -File_writer_VRML_2:: -write_facet_header() const { - out() << " ] #point\n" - " } #coord Coordinate\n" - " coordIndex [" << std::endl; -} - -void -File_writer_VRML_2:: -write_footer() const { - out() << " ] #coordIndex\n" - " } #geometry\n" - " } #Shape\n" - " ] #children\n" - " } #Group" << std::endl; -} - -} //namespace CGAL // EOF // diff --git a/Stream_support/src/CGAL/File_writer_inventor.cpp b/Stream_support/src/CGAL/File_writer_inventor.cpp index e40a1d0dd65..7c669692802 100644 --- a/Stream_support/src/CGAL/File_writer_inventor.cpp +++ b/Stream_support/src/CGAL/File_writer_inventor.cpp @@ -22,43 +22,11 @@ // // Author(s) : Lutz Kettner +#ifndef CGAL_HEADER_ONLY + #include +#include -namespace CGAL { +#endif // CGAL_HEADER_ONLY -void -File_writer_inventor:: -write_header( std::ostream& o, - std::size_t vertices, - std::size_t halfedges, - std::size_t facets){ - m_out = &o; - m_facets = facets; - out() << "# " << vertices << " vertices\n"; - out() << "# " << halfedges << " halfedges\n"; - out() << "# " << facets << " facets\n\n"; - out() << "Separator {\n" - " Coordinate3 {\n" - " point [" << std::endl; -} - -void -File_writer_inventor:: -write_facet_header() const { - out() << " ] #point\n" - " } #Coordinate3\n" - " # " << m_facets << " facets\n" - " IndexedFaceSet {\n" - " coordIndex [\n"; -} - -void -File_writer_inventor:: -write_footer() const { - out() << " ] #coordIndex\n" - " } #IndexedFaceSet\n" - "} #Separator" << std::endl; -} - -} //namespace CGAL // EOF // diff --git a/Stream_support/src/CGAL/File_writer_wavefront.cpp b/Stream_support/src/CGAL/File_writer_wavefront.cpp index 2fee7344ad6..d7c4ec4845c 100644 --- a/Stream_support/src/CGAL/File_writer_wavefront.cpp +++ b/Stream_support/src/CGAL/File_writer_wavefront.cpp @@ -22,29 +22,11 @@ // // Author(s) : Lutz Kettner -#include -#include +#ifndef CGAL_HEADER_ONLY + #include +#include -namespace CGAL { +#endif // CGAL_HEADER_ONLY -void -File_writer_wavefront:: -write_header( std::ostream& o, - std::size_t vertices, - std::size_t halfedges, - std::size_t facets){ - m_out = &o; - m_facets = facets; - // Print header. - out() << "# file written from a CGAL tool in Wavefront obj format\n"; - out() << "# " << vertices << " vertices\n"; - out() << "# " << halfedges << " halfedges\n"; - out() << "# " << facets << " facets\n\n"; - - out() << "\n# " << vertices << " vertices\n"; - out() << "# ------------------------------------------\n\n"; -} - -} //namespace CGAL // EOF // diff --git a/Stream_support/src/CGAL/io.cpp b/Stream_support/src/CGAL/io.cpp index 955ed6a2e2a..6514769ace3 100644 --- a/Stream_support/src/CGAL/io.cpp +++ b/Stream_support/src/CGAL/io.cpp @@ -22,104 +22,15 @@ // // Author(s) : Andreas Fabri -#include -#include -#include +#ifndef CGAL_HEADER_ONLY -#include -#include +#include +#include namespace CGAL { int IO::mode = std::ios::xalloc(); - -IO::Mode -get_mode(std::ios& i) -{ - return static_cast(i.iword(IO::mode)); -} - -IO::Mode -set_ascii_mode(std::ios& i) -{ - IO::Mode m = get_mode(i); - i.iword(IO::mode) = IO::ASCII; - return m; -} - - -IO::Mode -set_binary_mode(std::ios& i) -{ - IO::Mode m = get_mode(i); - i.iword(IO::mode) = IO::BINARY; - return m; -} - - -IO::Mode -set_pretty_mode(std::ios& i) -{ - IO::Mode m = get_mode(i); - i.iword(IO::mode) = IO::PRETTY; - return m; -} - -IO::Mode -set_mode(std::ios& i, IO::Mode m) -{ - IO::Mode old = get_mode(i); - i.iword(IO::mode) = m; - return old; -} - -bool -is_pretty(std::ios& i) -{ - return i.iword(IO::mode) == IO::PRETTY; -} - -bool -is_ascii(std::ios& i) -{ - return i.iword(IO::mode) == IO::ASCII; -} - - -bool -is_binary(std::ios& i) -{ - return i.iword(IO::mode) == IO::BINARY; -} - -const char* -mode_name( IO::Mode m) { - static const char* const names[] = {"ASCII", "PRETTY", "BINARY" }; - CGAL_assertion( IO::ASCII <= m && m <= IO::BINARY ); - return names[m]; -} - -void -swallow(std::istream &is, char d) { - char c; - do is.get(c); while (isspace(c)); - if (c != d) { - std::stringstream msg; - msg << "input error: expected '" << d << "' but got '" << c << "'"; - CGAL_error_msg( msg.str().c_str() ); - } -} - -void -swallow(std::istream &is, const std::string& s ) { - std::string t; - is >> t; - if (s != t) { - std::stringstream msg; - msg << "input error: expected '" << s << "' but got '" << t << "'"; - CGAL_error_msg( msg.str().c_str() ); - } -} - } //namespace CGAL + +#endif diff --git a/Triangulation_2/include/CGAL/Weighted_point.h b/Triangulation_2/include/CGAL/Weighted_point.h index 4aed838327e..200b374a0aa 100644 --- a/Triangulation_2/include/CGAL/Weighted_point.h +++ b/Triangulation_2/include/CGAL/Weighted_point.h @@ -109,7 +109,7 @@ template < class Point, class Weight > std::ostream & operator<<(std::ostream &os, const Weighted_point &p) { - switch(os.iword(IO::mode)) + switch(get_mode(os)) { case IO::ASCII : return os << p.point() << " " << p.weight(); diff --git a/Triangulation_3/benchmark/Triangulation_3/Triangulation_benchmark_3.cpp b/Triangulation_3/benchmark/Triangulation_3/Triangulation_benchmark_3.cpp index 8c13a3e8833..11e435125d4 100644 --- a/Triangulation_3/benchmark/Triangulation_3/Triangulation_benchmark_3.cpp +++ b/Triangulation_3/benchmark/Triangulation_3/Triangulation_benchmark_3.cpp @@ -153,7 +153,7 @@ public: ~Time_accumulator() { timer.stop(); accumulator += timer.time(); } }; -#define drand48 CGAL::default_random.get_double +#define drand48 CGAL::get_default_random().get_double Point rnd_point() { diff --git a/Triangulation_3/examples/Triangulation_3/fast_location_3.cpp b/Triangulation_3/examples/Triangulation_3/fast_location_3.cpp index 1d2ce0ccc77..b6a86304ba5 100644 --- a/Triangulation_3/examples/Triangulation_3/fast_location_3.cpp +++ b/Triangulation_3/examples/Triangulation_3/fast_location_3.cpp @@ -27,9 +27,9 @@ int main() // performing nearest vertex queries to a series of random points, // which is a case where the Fast_location policy is beneficial. for (int i=0; i<10000; ++i) - T.nearest_vertex(Point(CGAL::default_random.get_double(0, 20), - CGAL::default_random.get_double(0, 20), - CGAL::default_random.get_double(0, 20))); + T.nearest_vertex(Point(CGAL::get_default_random().get_double(0, 20), + CGAL::get_default_random().get_double(0, 20), + CGAL::get_default_random().get_double(0, 20))); return 0; } diff --git a/Triangulation_3/test/Triangulation_3/test_static_filters.cpp b/Triangulation_3/test/Triangulation_3/test_static_filters.cpp index 80a325054fd..c1c657f29dd 100644 --- a/Triangulation_3/test/Triangulation_3/test_static_filters.cpp +++ b/Triangulation_3/test/Triangulation_3/test_static_filters.cpp @@ -218,7 +218,7 @@ int main(int argc, char **argv) int loops = (argc < 2) ? 2000 : std::atoi(argv[1]); - int seed = (argc < 3) ? CGAL::default_random.get_int(0, 1<<30) + int seed = (argc < 3) ? CGAL::get_default_random().get_int(0, 1<<30) : std::atoi(argv[2]); std::cout << "Initializing random generator with seed = " << seed diff --git a/cppfiles.txt b/cppfiles.txt new file mode 100644 index 00000000000..979f936aad3 --- /dev/null +++ b/cppfiles.txt @@ -0,0 +1,76 @@ +Guillaume + +CGAL: + +DONE #include "/home/gdamiand/sources/CGAL/STL_Extension/src/CGAL/assertions.cpp" // variables globales +DONE #include "/home/gdamiand/sources/CGAL/Stream_support/src/CGAL/io.cpp" // variable statique de classe +DONE #include "/home/gdamiand/sources/CGAL/Stream_support/src/CGAL/Color.cpp" // constantes globales +DONE #include "/home/gdamiand/sources/CGAL/Kernel_23/src/CGAL/kernel.cpp" // constantes globales +DONE #include "/home/gdamiand/sources/CGAL/Number_types/src/CGAL/Interval_arithmetic.cpp" // constante globale +DONE #include "/home/gdamiand/sources/CGAL/Number_types/src/CGAL/test_FPU_rounding_mode.cpp" // variable static de classe const +DONE #include "/home/gdamiand/sources/CGAL/Profiling_tools/src/CGAL/Timer.cpp" // variable statique de classe +DONE #include "/home/gdamiand/sources/CGAL/Profiling_tools/src/CGAL/Real_timer.cpp" // variable statique de classe +DONE #include "/home/gdamiand/sources/CGAL/Random_numbers/src/CGAL/Random.cpp" // variable globale; utilisée directement (donc pb pour header only) -> we need to replace the use of CGAL::default_random by CGAL::get_default_random(). +DONE #include "/home/gdamiand/sources/CGAL/Modular_arithmetic/src/CGAL/primes.cpp" // constante globale +DONE #include "/home/gdamiand/sources/CGAL/Modular_arithmetic/src/CGAL/Residue_type.cpp" // variables globales (! version multi-thread !) + +DONE #include "/home/gdamiand/sources/CGAL/Geomview/src/CGAL/Geomview_stream.cpp" +DONE #include "/home/gdamiand/sources/CGAL/Intersections_2/src/CGAL/Bbox_2_intersections.cpp" +DONE #include "/home/gdamiand/sources/CGAL/Stream_support/src/CGAL/File_header_extended_OFF.cpp" +DONE #include "/home/gdamiand/sources/CGAL/Stream_support/src/CGAL/File_writer_inventor.cpp" +DONE #include "/home/gdamiand/sources/CGAL/Stream_support/src/CGAL/File_header_OFF.cpp" +DONE #include "/home/gdamiand/sources/CGAL/Stream_support/src/CGAL/File_scanner_OFF.cpp" +DONE #include "/home/gdamiand/sources/CGAL/Stream_support/src/CGAL/File_writer_OFF.cpp" +DONE #include "/home/gdamiand/sources/CGAL/Stream_support/src/CGAL/File_writer_VRML_2.cpp" +DONE #include "/home/gdamiand/sources/CGAL/Stream_support/src/CGAL/File_writer_wavefront.cpp" +DONE #include "/home/gdamiand/sources/CGAL/Nef_2/src/CGAL/NefPolynomial.cpp" + +CGAL_Qt4: + +DONE #include "/home/gdamiand/sources/CGAL/GraphicsView/src/CGAL_Qt4/utility.cpp" +DONE #include "/home/gdamiand/sources/CGAL/GraphicsView/src/CGAL_Qt4/resources.cpp" +DONE #include "/home/gdamiand/sources/CGAL/GraphicsView/src/CGAL_Qt4/debug.cpp" +DONE #include "/home/gdamiand/sources/CGAL/GraphicsView/src/CGAL_Qt4/GraphicsViewPolylineInput.cpp" +DONE #include "/home/gdamiand/sources/CGAL/GraphicsView/src/CGAL_Qt4/DemosMainWindow.cpp" +DONE #include "/home/gdamiand/sources/CGAL/GraphicsView/src/CGAL_Qt4/GraphicsViewNavigation.cpp" + +Clement: + +CGAL: + +DONE #include "/home/gdamiand/sources/CGAL/Kinetic_data_structures/src/CGAL/JAMA_numeric_solver.cpp" +DONE #include "/home/gdamiand/sources/CGAL/Kinetic_data_structures/src/CGAL/KDS_Log.cpp" +DONE #include "/home/gdamiand/sources/CGAL/Kinetic_data_structures/src/CGAL/numeric_solvers_support.cpp" +DONE #include "/home/gdamiand/sources/CGAL/Kinetic_data_structures/src/CGAL/Turkowski_numeric_solver.cpp" + +CGAL_Core: + +DONE #include "/home/gdamiand/sources/CGAL/CGAL_Core/src/CGAL_Core/CoreIO.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_Core/src/CGAL_Core/CoreAux.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_Core/src/CGAL_Core/CoreDefs.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_Core/src/CGAL_Core/Expr.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_Core/src/CGAL_Core/GmpIO.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_Core/src/CGAL_Core/BigFloat.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_Core/src/CGAL_Core/Real.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_Core/src/CGAL_Core/extLong.cpp" + +CGAL_ImageIO: + +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/analyze.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/bmpread.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/recline.cpp" // 1 global variable +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/mincio.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/convert.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/recbuffer.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/gif.cpp" // several global variables +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/gis.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/bmp.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/reech4x4.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/bmpendian.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/fgetns.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/Image_3.cpp" +DONE #include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/iris.cpp" +#include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/ImageIO.cpp" + +#include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/pnm.cpp" +#include "/home/gdamiand/sources/CGAL/CGAL_ImageIO/src/CGAL_ImageIO/inr.cpp"