mirror of https://github.com/CGAL/cgal
Merge branch 'CGAL_headers_only-gdamiand_cjamin-old' into CGAL_headers_only-gdamiand_cjamin
This commit is contained in:
commit
9c78897ba5
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ void process ()
|
|||
double hom = 2.0;
|
||||
for ( i = 0; i < 100; ++i) {
|
||||
for (j=0; j<d; ++j)
|
||||
coords[ j] = CGAL::default_random( 0x100000);
|
||||
coords[ j] = CGAL::get_default_random()( 0x100000);
|
||||
coords[d] = hom;
|
||||
points.push_back
|
||||
(typename K::Point_d(d, coords.begin(), coords.end()));
|
||||
|
|
|
|||
|
|
@ -37,6 +37,13 @@
|
|||
|
||||
#include <CGAL/CORE/BigFloatRep.h>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#undef CGAL_EXPORT // CJTODO: TEMPORARY
|
||||
#undef CGAL_CORE_EXPORT
|
||||
#define CGAL_EXPORT
|
||||
#define CGAL_CORE_EXPORT
|
||||
#endif
|
||||
|
||||
namespace CORE {
|
||||
|
||||
class Expr;
|
||||
|
|
@ -83,8 +90,8 @@ public:
|
|||
BigFloat(const BigInt& I)
|
||||
: RCBigFloat(new BigFloatRep(I)) {}
|
||||
/// constructor for <tt>BigRat</tt>
|
||||
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);
|
||||
}
|
||||
|
|
@ -93,8 +100,8 @@ public:
|
|||
// know about Expr, but BigFloat has a special role in our system!
|
||||
// ===============================
|
||||
/// constructor for <tt>Expr</tt>
|
||||
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& ,
|
||||
|
|
@ -161,7 +168,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;
|
||||
}
|
||||
|
|
@ -182,11 +189,11 @@ public:
|
|||
/// \name String Conversion Functions
|
||||
//@{
|
||||
/// set value from <tt>const char*</tt> (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 <tt>std::string</tt> (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 {
|
||||
|
|
@ -435,7 +442,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;
|
||||
}
|
||||
|
||||
|
|
@ -490,12 +497,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
|
||||
|
|
@ -625,4 +632,10 @@ inline BigRat::BigRat(const BigFloat& f) : RCBigRat(new BigRatRep()){
|
|||
*this = f.BigRatValue();
|
||||
}
|
||||
} //namespace CORE
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/CORE/BigFloat_impl.h>
|
||||
#include <CGAL/CORE/CoreIO_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // _CORE_BIGFLOAT_H_
|
||||
|
|
|
|||
|
|
@ -40,6 +40,13 @@
|
|||
#include <CGAL/CORE/CoreDefs.h>
|
||||
#include <CGAL/CORE/extLong.h>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#undef CGAL_EXPORT // CJTODO: TEMPORARY
|
||||
#undef CGAL_CORE_EXPORT
|
||||
#define CGAL_EXPORT
|
||||
#define CGAL_CORE_EXPORT
|
||||
#endif
|
||||
|
||||
namespace CORE {
|
||||
|
||||
// forward reference
|
||||
|
|
@ -144,11 +151,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;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -39,6 +39,13 @@
|
|||
#include <CGAL/CORE/MemoryPool.h>
|
||||
#include <string>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#undef CGAL_EXPORT // CJTODO: TEMPORARY
|
||||
#undef CGAL_CORE_EXPORT
|
||||
#define CGAL_EXPORT
|
||||
#define CGAL_CORE_EXPORT
|
||||
#endif
|
||||
|
||||
namespace CORE {
|
||||
|
||||
|
||||
|
|
@ -559,4 +566,9 @@ inline BigInt randomize(const BigInt& a) {
|
|||
//@}
|
||||
|
||||
} //namespace CORE
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
//#include <CGAL/CORE/CoreIO_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // _CORE_BIGINT_H_
|
||||
|
|
|
|||
|
|
@ -39,6 +39,13 @@
|
|||
#include <fstream>
|
||||
#include "CGAL/CORE/Impl.h"
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#undef CGAL_EXPORT // CJTODO: TEMPORARY
|
||||
#undef CGAL_CORE_EXPORT
|
||||
#define CGAL_EXPORT
|
||||
#define CGAL_CORE_EXPORT
|
||||
#endif
|
||||
|
||||
namespace CORE {
|
||||
|
||||
#ifndef LONG_BIT // such as in Linux
|
||||
|
|
@ -181,4 +188,9 @@ inline void core_debug(std::string msg){
|
|||
|
||||
|
||||
} //namespace CORE
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/CORE/CoreAux_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // _CORE_COREAUX_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 <yap@cs.nyu.edu>
|
||||
* Chen Li <chenli@cs.nyu.edu>
|
||||
* Zilin Du <zilin@cs.nyu.edu>
|
||||
*
|
||||
* 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 <CGAL/CORE/CoreAux.h>
|
||||
#include <gmp.h>
|
||||
|
||||
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 (p<q)
|
||||
core_swap(p, q);
|
||||
while (q>0) {
|
||||
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"<<std::endl;
|
||||
std::exit(1); //Note: do not call abort()
|
||||
}
|
||||
outFile << "CORE " << (err? "ERROR" : "WARNING")
|
||||
<< " (at " << file << ": " << lineno << "): "
|
||||
<< msg << std::endl;
|
||||
outFile.close();
|
||||
if (err) {
|
||||
char buf[65];
|
||||
// perror((std::string("CORE ERROR") + " (file " + file + ", line "
|
||||
// + core_itoa(lineno,buf) +"):" + msg + "\n").c_str());
|
||||
std::cerr << (std::string("CORE ERROR") + " (file " + file + ", line "
|
||||
+ core_itoa(lineno,buf) +"):" + msg + "\n").c_str();
|
||||
std::exit(1); //Note: do not call abort()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} //namespace CORE
|
||||
|
|
@ -40,6 +40,33 @@
|
|||
|
||||
#include <CGAL/CORE/extLong.h>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#undef CGAL_EXPORT // CJTODO: TEMPORARY
|
||||
#undef CGAL_CORE_EXPORT
|
||||
#define CGAL_EXPORT
|
||||
#define CGAL_CORE_EXPORT
|
||||
#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) \
|
||||
CGAL_EXPORT extern TYPE NAME; \
|
||||
inline TYPE& get_static_##NAME() \
|
||||
{ \
|
||||
return NAME; \
|
||||
}
|
||||
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
namespace CORE {
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
|
@ -60,34 +87,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 +124,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 +170,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 +261,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 +277,9 @@ inline void setPositionalFormat(std::ostream& o = std::cout) {
|
|||
}
|
||||
|
||||
} //namespace CORE
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/CORE/CoreDefs_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // _CORE_COREDEFS_H_
|
||||
|
|
|
|||
|
|
@ -0,0 +1,170 @@
|
|||
/****************************************************************************
|
||||
* 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 <yap@cs.nyu.edu>
|
||||
* Chen Li <chenli@cs.nyu.edu>
|
||||
* Zilin Du <zilin@cs.nyu.edu>
|
||||
*
|
||||
* WWW URL: http://cs.nyu.edu/exact/
|
||||
* Email: exact@cs.nyu.edu
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
#include "CGAL/CORE/CoreDefs.h"
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#undef CGAL_EXPORT // CJTODO: TEMPORARY
|
||||
#undef CGAL_CORE_EXPORT
|
||||
#define CGAL_EXPORT
|
||||
#define CGAL_CORE_EXPORT
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
|
|
@ -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 <zilin@cs.nyu.edu>
|
||||
* Chee Yap <yap@cs.nyu.edu>
|
||||
*
|
||||
* 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 <CGAL/CORE/BigFloatRep.h>
|
||||
#include <CGAL/CORE/BigFloat.h>
|
||||
#include <CGAL/CORE/BigInt.h>
|
||||
|
||||
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<size)&&((c=skip_backslash_new_line(in)) != EOF ); i++) {
|
||||
if (c != ' ' && c != '\t' && c != '\n')
|
||||
append_char(buffer, size, pos++, c);
|
||||
}
|
||||
if (base == 10) {
|
||||
for(int j=0; j<offset; j++)
|
||||
append_char(buffer, size, pos++, '0');
|
||||
}
|
||||
append_char(buffer, size, pos, '\0');
|
||||
|
||||
// convert string to bigint.
|
||||
if (m.set_str(buffer, base) < 0)
|
||||
core_io_error_handler("CoreIO::read_from_file()","bad big number format.");
|
||||
delete[] buffer;
|
||||
|
||||
// shift left if neccessary
|
||||
if (offset > 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; i += charsPerLine) {
|
||||
start = buffer + i;
|
||||
if (i + charsPerLine >= 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_
|
||||
|
|
@ -36,11 +36,22 @@
|
|||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
// We need to include BigFloat.h here because there is a circular dependency
|
||||
// between Expr and BigFloat.
|
||||
#include <CGAL/CORE/BigFloat.h>
|
||||
|
||||
#ifndef _CORE_EXPR_H_
|
||||
#define _CORE_EXPR_H_
|
||||
|
||||
#include <CGAL/CORE/ExprRep.h>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#undef CGAL_EXPORT // CJTODO: TEMPORARY
|
||||
#undef CGAL_CORE_EXPORT
|
||||
#define CGAL_EXPORT
|
||||
#define CGAL_CORE_EXPORT
|
||||
#endif
|
||||
|
||||
namespace CORE {
|
||||
|
||||
/// \class Expr Expr.h
|
||||
|
|
@ -78,9 +89,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);
|
||||
}
|
||||
|
|
@ -89,9 +100,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);
|
||||
}
|
||||
|
|
@ -111,11 +122,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 <tt>std::string</tt>
|
||||
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 <tt>Real</tt>
|
||||
|
|
@ -179,9 +190,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;
|
||||
|
|
@ -225,12 +236,12 @@ public:
|
|||
/// \name String Conversion Functions
|
||||
//@{
|
||||
/// set value from <tt>const char*</tt>
|
||||
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 <tt>std::string</tt>
|
||||
/** 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);
|
||||
}
|
||||
//@}
|
||||
|
|
@ -282,8 +293,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);
|
||||
}
|
||||
//@}
|
||||
|
|
@ -355,7 +366,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;
|
||||
|
|
@ -382,9 +393,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()));
|
||||
}
|
||||
|
|
@ -485,9 +496,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()));
|
||||
}
|
||||
|
|
@ -548,4 +559,9 @@ inline Expr radical(const NT& n, int m) {
|
|||
#include <CGAL/CORE/poly/Poly.tcc>
|
||||
|
||||
} //namespace CORE
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/CORE/Expr_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // _CORE_EXPR_H_
|
||||
|
|
|
|||
|
|
@ -43,9 +43,16 @@
|
|||
#include <CGAL/CORE/Filter.h>
|
||||
#include <CGAL/CORE/poly/Sturm.h>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#undef CGAL_EXPORT // CJTODO: TEMPORARY
|
||||
#undef CGAL_CORE_EXPORT
|
||||
#define CGAL_EXPORT
|
||||
#define CGAL_CORE_EXPORT
|
||||
#endif
|
||||
|
||||
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 +196,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 +396,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 +684,7 @@ protected:
|
|||
tc() = ceilLg(ss.seq[0].getTailCoeff());
|
||||
|
||||
// no rational reduction
|
||||
if (rationalReduceFlag)
|
||||
if (get_static_rationalReduceFlag())
|
||||
ratFlag() = -1;
|
||||
|
||||
flagsComputed() = true;
|
||||
|
|
@ -838,7 +845,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 <class T>
|
||||
|
|
@ -857,7 +869,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 <class T>
|
||||
|
|
@ -895,7 +912,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 +942,7 @@ void AddSubRep<Operator>::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 +950,7 @@ void AddSubRep<Operator>::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 +1063,7 @@ void AddSubRep<Operator>::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 +1102,7 @@ void AddSubRep<Operator>::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 +1113,7 @@ void AddSubRep<Operator>::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 +1168,22 @@ void AddSubRep<Operator>::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
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -42,6 +42,13 @@
|
|||
#include <CGAL/CORE/Real.h>
|
||||
#include <cmath>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#undef CGAL_EXPORT // CJTODO: TEMPORARY
|
||||
#undef CGAL_CORE_EXPORT
|
||||
#define CGAL_EXPORT
|
||||
#define CGAL_CORE_EXPORT
|
||||
#endif
|
||||
|
||||
#if !defined CGAL_CFG_NO_CPP0X_ISFINITE
|
||||
#define CGAL_CORE_finite(x) std::isfinite(x)
|
||||
#elif defined (_MSC_VER) || defined (__MINGW32__) // add support for MinGW
|
||||
|
|
@ -102,7 +109,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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,13 @@
|
|||
#include <CGAL/CORE/Impl.h>
|
||||
#include <gmp.h>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#undef CGAL_EXPORT // CJTODO: TEMPORARY
|
||||
#undef CGAL_CORE_EXPORT
|
||||
#define CGAL_EXPORT
|
||||
#define CGAL_CORE_EXPORT
|
||||
#endif
|
||||
|
||||
namespace CORE {
|
||||
|
||||
CGAL_CORE_EXPORT std::ostream& io_write (std::ostream &, mpz_srcptr);
|
||||
|
|
@ -39,4 +46,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 <CGAL/CORE/Gmp_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // _CORE_GMP_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 <CGAL/CORE/Gmp.h>
|
||||
#include <cctype>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
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
|
||||
|
|
@ -39,6 +39,13 @@
|
|||
#define _CORE_REAL_H_
|
||||
#include "RealRep.h"
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#undef CGAL_EXPORT // CJTODO: TEMPORARY
|
||||
#undef CGAL_CORE_EXPORT
|
||||
#define CGAL_EXPORT
|
||||
#define CGAL_CORE_EXPORT
|
||||
#endif
|
||||
|
||||
namespace CORE {
|
||||
// class Real
|
||||
typedef RCImpl<RealRep> RCReal;
|
||||
|
|
@ -57,10 +64,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 +141,12 @@ public:
|
|||
/// \name String Conversion Functions
|
||||
//@{
|
||||
/// set value from <tt>const char*</tt>
|
||||
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 <tt>std::string</tt>
|
||||
/** 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 +186,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 +403,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 +421,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 +486,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 +501,9 @@ inline Real RealLong::operator-() const {
|
|||
}
|
||||
|
||||
} //namespace CORE
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/CORE/Real_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // _CORE_REAL_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 <ouchi@simulation.nyu.edu>
|
||||
* Chee Yap <yap@cs.nyu.edu>
|
||||
* Chen Li <chenli@cs.nyu.edu>
|
||||
* Zilin Du <zilin@cs.nyu.edu>
|
||||
* Sylvain Pion <pion@cs.nyu.edu>
|
||||
*
|
||||
* 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 <ctype.h>
|
||||
#include <CGAL/CORE/Real.h>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/CORE/BigFloat.h> // 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<unsigned long>(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
|
||||
|
|
@ -41,6 +41,13 @@
|
|||
#include <CGAL/CORE/Impl.h>
|
||||
#include <CGAL/CORE/CoreAux.h>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#undef CGAL_EXPORT // CJTODO: TEMPORARY
|
||||
#undef CGAL_CORE_EXPORT
|
||||
#define CGAL_EXPORT
|
||||
#define CGAL_CORE_EXPORT
|
||||
#endif
|
||||
|
||||
namespace CORE {
|
||||
|
||||
#ifndef LONG_MAX
|
||||
|
|
@ -294,4 +301,9 @@ inline bool extLong::isNaN() const {
|
|||
}
|
||||
|
||||
} //namespace CORE
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/CORE/extLong_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // _CORE_EXTLONG_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 <yap@cs.nyu.edu>
|
||||
* Chen Li <chenli@cs.nyu.edu>
|
||||
* Zilin Du <zilin@cs.nyu.edu>
|
||||
* Sylvain Pion <pion@cs.nyu.edu>
|
||||
*
|
||||
* 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 <CGAL/CORE/extLong.h>
|
||||
|
||||
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
|
||||
|
|
@ -205,7 +205,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.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -33,181 +33,9 @@
|
|||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
#include "CGAL/CORE/CoreAux.h"
|
||||
#include <gmp.h>
|
||||
#ifndef CGAL_HEADER_ONLY
|
||||
|
||||
namespace CORE {
|
||||
#include <CGAL/CORE/CoreAux.h>
|
||||
#include <CGAL/CORE/CoreAux_impl.h>
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// 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 (p<q)
|
||||
core_swap(p, q);
|
||||
while (q>0) {
|
||||
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"<<std::endl;
|
||||
std::exit(1); //Note: do not call abort()
|
||||
}
|
||||
outFile << "CORE " << (err? "ERROR" : "WARNING")
|
||||
<< " (at " << file << ": " << lineno << "): "
|
||||
<< msg << std::endl;
|
||||
outFile.close();
|
||||
if (err) {
|
||||
char buf[65];
|
||||
// perror((std::string("CORE ERROR") + " (file " + file + ", line "
|
||||
// + core_itoa(lineno,buf) +"):" + msg + "\n").c_str());
|
||||
std::cerr << (std::string("CORE ERROR") + " (file " + file + ", line "
|
||||
+ core_itoa(lineno,buf) +"):" + msg + "\n").c_str();
|
||||
std::exit(1); //Note: do not call abort()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} //namespace CORE
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,124 +32,9 @@
|
|||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
#include "CGAL/CORE/CoreDefs.h"
|
||||
#ifndef CGAL_HEADER_ONLY
|
||||
|
||||
namespace CORE {
|
||||
|
||||
// Default Values
|
||||
|
||||
/* ************************************************************
|
||||
* ERROR FLAGS
|
||||
* ************************************************************ */
|
||||
|
||||
/** 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
|
||||
|
||||
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;
|
||||
|
||||
} //namespace CORE
|
||||
#include <CGAL/CORE/CoreDefs.h>
|
||||
#include <CGAL/CORE/CoreDefs_impl.h>
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,430 +29,6 @@
|
|||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
#include <CGAL/CORE/BigFloatRep.h>
|
||||
#include <CGAL/CORE/BigFloat.h>
|
||||
|
||||
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<size)&&((c=skip_backslash_new_line(in)) != EOF ); i++) {
|
||||
if (c != ' ' && c != '\t' && c != '\n')
|
||||
append_char(buffer, size, pos++, c);
|
||||
}
|
||||
if (base == 10) {
|
||||
for(int j=0; j<offset; j++)
|
||||
append_char(buffer, size, pos++, '0');
|
||||
}
|
||||
append_char(buffer, size, pos, '\0');
|
||||
|
||||
// convert string to bigint.
|
||||
if (m.set_str(buffer, base) < 0)
|
||||
core_io_error_handler("CoreIO::read_from_file()","bad big number format.");
|
||||
delete[] buffer;
|
||||
|
||||
// shift left if neccessary
|
||||
if (offset > 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; i += charsPerLine) {
|
||||
start = buffer + i;
|
||||
if (i + charsPerLine >= 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 <CGAL/CORE/CoreIO_impl.h>
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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 <CGAL/CORE/Gmp.h>
|
||||
#include <cctype>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <CGAL/CORE/Gmp_impl.h>
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -35,242 +35,9 @@
|
|||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
#include <ctype.h>
|
||||
#ifndef CGAL_HEADER_ONLY
|
||||
|
||||
#include <CGAL/CORE/Real.h>
|
||||
#include <CGAL/CORE/Real_impl.h>
|
||||
|
||||
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<unsigned long>(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
|
||||
|
|
|
|||
|
|
@ -39,157 +39,9 @@
|
|||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef CGAL_HEADER_ONLY
|
||||
|
||||
#include <CGAL/CORE/extLong.h>
|
||||
#include <CGAL/CORE/extLong_impl.h>
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -19,820 +19,9 @@
|
|||
//
|
||||
// Author(s) : ASCLEPIOS Project (INRIA Sophia-Antipolis), Laurent Rineau
|
||||
|
||||
#include <string.h>
|
||||
#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; i<im->nuser; 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<size; i++, buf++) {
|
||||
if ( imax < *buf ) imax = *buf;
|
||||
if ( imin > *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<size; i++, buf++) {
|
||||
if ( imax < *buf ) imax = *buf;
|
||||
if ( imin > *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<size; i++, buf++) {
|
||||
if ( imax < *buf ) imax = *buf;
|
||||
if ( imin > *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<size; i++, buf++) {
|
||||
if ( imax < *buf ) imax = *buf;
|
||||
if ( imin > *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
|
||||
|
|
|
|||
|
|
@ -67,5 +67,8 @@ int writeAnalyzeHeader( const _image* im ) ;
|
|||
*/
|
||||
int writeAnalyzeData( const _image* im ) ;
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include "analyse_impl.h"
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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; i<im->nuser; 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<size; i++, buf++) {
|
||||
if ( imax < *buf ) imax = *buf;
|
||||
if ( imin > *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<size; i++, buf++) {
|
||||
if ( imax < *buf ) imax = *buf;
|
||||
if ( imin > *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<size; i++, buf++) {
|
||||
if ( imax < *buf ) imax = *buf;
|
||||
if ( imin > *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<size; i++, buf++) {
|
||||
if ( imax < *buf ) imax = *buf;
|
||||
if ( imin > *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 );
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ else()
|
|||
cmake_minimum_required(VERSION 2.6.2)
|
||||
endif()
|
||||
|
||||
# add_definitions(-DCGAL_HEADER_ONLY)
|
||||
|
||||
# option for branch build
|
||||
|
||||
option( CGAL_BRANCH_BUILD "Create CGAL from branch" ON)
|
||||
|
|
|
|||
|
|
@ -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++){
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ protected:
|
|||
public:
|
||||
typedef Random_generator_base<T> This;
|
||||
|
||||
Random_generator_base() : _rnd( default_random) {}
|
||||
Random_generator_base() : _rnd( CGAL::get_default_random() ) {}
|
||||
Random_generator_base( double range, Random& rnd)
|
||||
: Generator_base<T>( 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<double> {
|
|||
|
||||
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}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class Random_points_in_disc_2 : public Random_generator_base<P>{
|
|||
void generate_point();
|
||||
public:
|
||||
typedef Random_points_in_disc_2<P,Creator> 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.
|
||||
|
|
@ -71,7 +71,7 @@ class Random_points_on_circle_2 : public Random_generator_base<P> {
|
|||
void generate_point();
|
||||
public:
|
||||
typedef Random_points_on_circle_2<P,Creator> 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.
|
||||
|
|
@ -105,7 +105,7 @@ class Random_points_in_square_2 : public Random_generator_base<P> {
|
|||
void generate_point();
|
||||
public:
|
||||
typedef Random_points_in_square_2<P,Creator> 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}
|
||||
|
|
@ -141,7 +141,7 @@ class Random_points_on_square_2 : public Random_generator_base<P> {
|
|||
void generate_point();
|
||||
public:
|
||||
typedef Random_points_on_square_2<P,Creator> 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
|
||||
|
|
@ -194,7 +194,7 @@ class Random_points_in_iso_rectangle_2 : public Random_generator_base<P> {
|
|||
void generate_point();
|
||||
public:
|
||||
typedef Random_points_in_iso_rectangle_2<P,Creator> 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<P>( 1.0 , rnd)
|
||||
{
|
||||
left = (std::min)(to_double(p.x()), to_double(q.x()));
|
||||
|
|
@ -238,7 +238,7 @@ public:
|
|||
typedef Random_points_on_segment_2<P,Creator> 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
|
||||
|
|
@ -423,7 +423,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 <class ForwardIterator>
|
||||
|
|
@ -431,7 +431,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 <class RandomAccessIterator, class OutputIterator, class Creator>
|
||||
OutputIterator random_collinear_points_2(
|
||||
|
|
@ -489,7 +489,7 @@ OutputIterator random_collinear_points_2(
|
|||
OutputIterator first2)
|
||||
{
|
||||
return random_collinear_points_2( first, last, n, first2,
|
||||
default_random);
|
||||
CGAL::get_default_random());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class Random_points_in_sphere_3 : public Random_generator_base<P> {
|
|||
void generate_point();
|
||||
public:
|
||||
typedef Random_points_in_sphere_3<P,Creator> 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
|
||||
|
|
@ -75,7 +75,7 @@ class Random_points_on_sphere_3 : public Random_generator_base<P> {
|
|||
void generate_point();
|
||||
public:
|
||||
typedef Random_points_on_sphere_3<P,Creator> 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.
|
||||
|
|
@ -113,7 +113,7 @@ class Random_points_in_cube_3 : public Random_generator_base<P>{
|
|||
void generate_point();
|
||||
public:
|
||||
typedef Random_points_in_cube_3<P,Creator> 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<P>( a, rnd) { generate_point(); }
|
||||
This& operator++() {
|
||||
generate_point();
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class Random_points_in_ball_d : public Random_generator_base<P>{
|
|||
public:
|
||||
typedef Random_points_in_ball_d<P> 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<P>( a, rnd), dimension(dim) { generate_point(); }
|
||||
|
|
@ -84,7 +84,7 @@ class Random_points_on_sphere_d : public Random_generator_base<P>{
|
|||
public:
|
||||
typedef Random_points_on_sphere_d<P> 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<P>( a, rnd), dimension(dim) { generate_point(); }
|
||||
|
|
@ -129,7 +129,7 @@ class Random_points_in_cube_d : public Random_generator_base<P>{
|
|||
public:
|
||||
typedef Random_points_in_cube_d<P> This;
|
||||
Random_points_in_cube_d( int dim, double a = 1,
|
||||
Random& rnd = default_random)
|
||||
Random& rnd = get_default_random())
|
||||
: Random_generator_base<P>( a, rnd), dimension(dim) { generate_point(); }
|
||||
This& operator++() {
|
||||
generate_point();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<Point_2>::iterator i = points.begin();
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#ifndef CGAL_GEOMVIEW_STREAM_H
|
||||
#define CGAL_GEOMVIEW_STREAM_H
|
||||
|
||||
#ifdef CGAL_USE_GEOMVIEW
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/Bbox_2.h>
|
||||
#include <CGAL/Bbox_3.h>
|
||||
|
|
@ -593,4 +595,10 @@ operator>>(Geomview_stream &gv, Point_3<R> &point)
|
|||
|
||||
} //namespace CGAL
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/IO/Geomview_stream_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // CGAL_USE_GEOMVIEW
|
||||
|
||||
#endif // CGAL_GEOMVIEW_STREAM_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,614 @@
|
|||
// 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 <CGAL/basic.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <csignal>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/types.h> // kill() on SunPro requires these 2 #includes.
|
||||
#include <signal.h>
|
||||
|
||||
#include <CGAL/IO/binary_file_io.h>
|
||||
|
||||
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<void *>(NULL)); // cast to stop gcc warning
|
||||
} else {
|
||||
execlp("geomview", "geomview", "-c", "-",
|
||||
static_cast<void *>(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
|
||||
|
|
@ -22,550 +22,9 @@
|
|||
//
|
||||
// Author(s) : Andreas Fabri, Herve Bronnimann, Sylvain Pion
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
|
||||
#ifdef CGAL_USE_GEOMVIEW
|
||||
|
||||
#include <sstream>
|
||||
#include <csignal>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/types.h> // kill() on SunPro requires these 2 #includes.
|
||||
#include <signal.h>
|
||||
#ifndef CGAL_HEADER_ONLY
|
||||
|
||||
#include <CGAL/IO/Geomview_stream.h>
|
||||
#include <CGAL/IO/binary_file_io.h>
|
||||
#include <CGAL/IO/Geomview_stream_impl.h>
|
||||
|
||||
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<void *>(NULL)); // cast to stop gcc warning
|
||||
} else {
|
||||
execlp("geomview", "geomview", "-c", "-",
|
||||
static_cast<void *>(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
|
||||
|
|
|
|||
|
|
@ -125,4 +125,8 @@ protected:
|
|||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(CGAL::Qt::DemosMainWindow::Options)
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/Qt/DemosMainWindow_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // CGAL_QT_DEMOS_MAIN_WINDOW_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,436 @@
|
|||
// 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 <Andreas.Fabri@geometryfactory.com>
|
||||
// Laurent Rineau <Laurent.Rineau@geometryfactory.com>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#define CGAL_INLINE_FUNCTION inline
|
||||
#else
|
||||
#define CGAL_INLINE_FUNCTION
|
||||
#endif
|
||||
|
||||
#include <CGAL/Qt/GraphicsViewNavigation.h>
|
||||
#include <QApplication>
|
||||
#include <QLabel>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <QAction>
|
||||
#include <QMessageBox>
|
||||
#include <QStatusBar>
|
||||
#include <QGraphicsView>
|
||||
#include <QGLWidget>
|
||||
#include <QTextStream>
|
||||
#include <QSettings>
|
||||
#include <QUrl>
|
||||
#include <QDesktopWidget>
|
||||
#include <QRegExp>
|
||||
|
||||
#include <CGAL/config.h> // needed to get CGAL_VERSION_STR
|
||||
#include <CGAL/Qt/DemosMainWindow.h>
|
||||
#include <iostream>
|
||||
|
||||
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
|
||||
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::setUseAntialiasing(bool checked)
|
||||
{
|
||||
view->setRenderHint(QPainter::Antialiasing, checked);
|
||||
#if QT_VERSION >= 0x040300
|
||||
view->setRenderHint(QPainter::HighQualityAntialiasing, checked);
|
||||
#endif
|
||||
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<QMenu*>(objectName);
|
||||
|
||||
// then search if a menu has title()==title
|
||||
if(menu) {
|
||||
return menu;
|
||||
} else {
|
||||
Q_FOREACH(menu, this->findChildren<QMenu*>()) {
|
||||
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("<!--CGAL_VERSION-->",
|
||||
QString(" (version %1)")
|
||||
.arg(cgal_version));
|
||||
#endif
|
||||
QMessageBox mb(QMessageBox::NoIcon,
|
||||
title,
|
||||
about_CGAL_txt,
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
|
||||
QLabel* mb_label = mb.findChild<QLabel*>("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<QAction *>(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
|
||||
|
|
@ -69,4 +69,8 @@ private:
|
|||
} // namespace Qt
|
||||
} // namespace CGAL
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/Qt/GraphicsViewNavigation_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // CGAL_QT_GRAPHICS_VIEW_NAVIGATION_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 <Andreas.Fabri@geometryfactory.com>
|
||||
// Laurent Rineau <Laurent.Rineau@geometryfactory.com>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#define CGAL_INLINE_FUNCTION inline
|
||||
#else
|
||||
#define CGAL_INLINE_FUNCTION
|
||||
#endif
|
||||
|
||||
#include <CGAL/Qt/GraphicsViewNavigation.h>
|
||||
#include <CGAL/Qt/utility.h> // for mapToScene(QGraphicsView*, QRect)
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <QEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
#include <QGraphicsView>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsRectItem>
|
||||
#include <QFlags>
|
||||
#include <QScrollBar>
|
||||
|
||||
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<QGraphicsView*>(obj);
|
||||
if(v == NULL) {
|
||||
QWidget* viewport = qobject_cast<QWidget*>(obj);
|
||||
if(viewport == NULL) {
|
||||
return false;
|
||||
}
|
||||
v = qobject_cast<QGraphicsView*>(viewport->parent());
|
||||
if(v == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch(event->type())
|
||||
{
|
||||
case QEvent::KeyPress: {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(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<QKeyEvent*>(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<QWheelEvent*>(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<QMouseEvent*>(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<QMouseEvent*>(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<QMouseEvent*>(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
|
||||
|
||||
|
|
@ -34,6 +34,7 @@ class QGraphicsScene;
|
|||
class QGraphicsSceneMouseEvent;
|
||||
class QGraphicsItem;
|
||||
class QGraphicsPathItem;
|
||||
class QGraphicsLineItem;
|
||||
class QKeyEvent;
|
||||
class QEvent;
|
||||
class QObject;
|
||||
|
|
@ -107,4 +108,8 @@ protected:
|
|||
} // namespace Qt
|
||||
} // namespace CGAL
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/Qt/GraphicsViewPolylineInput_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // CGAL_QT_GRAPHICS_VIEW_POLYLINE_INPUT_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 <Andreas.Fabri@geometryfactory.com>
|
||||
// Laurent Rineau <Laurent.Rineau@geometryfactory.com>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#define CGAL_INLINE_FUNCTION inline
|
||||
#else
|
||||
#define CGAL_INLINE_FUNCTION
|
||||
#endif
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <QGraphicsPathItem>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QPolygonF>
|
||||
#include <QPainterPath>
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
|
||||
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<QGraphicsSceneMouseEvent *>(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<QGraphicsSceneMouseEvent *>(event);
|
||||
mouseMoveEvent(mouseEvent);
|
||||
return QObject::eventFilter(obj, event);
|
||||
} else if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(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
|
||||
|
|
@ -43,5 +43,8 @@ CGAL_QT4_EXPORT void traverse_resources(const QString& name,
|
|||
} // namespace Qt
|
||||
} // namespace CGAL
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/Qt/debug_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // CGAL_QT_DEBUG_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 <Andreas.Fabri@geometryfactory.com>
|
||||
// Laurent Rineau <Laurent.Rineau@geometryfactory.com>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#define CGAL_INLINE_FUNCTION inline
|
||||
#else
|
||||
#define CGAL_INLINE_FUNCTION
|
||||
#endif
|
||||
|
||||
#include <CGAL/Qt/debug.h>
|
||||
#include <QDir>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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
|
||||
|
|
@ -30,4 +30,8 @@ CGAL_QT4_EXPORT void CGAL_Qt4_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 <CGAL/Qt/resources_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // CGAL_QT_RESOURCES_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 <Laurent.Rineau@geometryfactory.com>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#define CGAL_INLINE_FUNCTION inline
|
||||
#else
|
||||
#define CGAL_INLINE_FUNCTION
|
||||
#endif
|
||||
|
||||
#include <QDir>
|
||||
#include <CGAL/Qt/resources.h>
|
||||
|
||||
// cannot use namespaces because of the Q_INIT_RESOURCE macro
|
||||
CGAL_INLINE_FUNCTION
|
||||
void CGAL_Qt4_init_resources() {
|
||||
Q_INIT_RESOURCE(File);
|
||||
Q_INIT_RESOURCE(Triangulation_2);
|
||||
Q_INIT_RESOURCE(Input);
|
||||
Q_INIT_RESOURCE(CGAL);
|
||||
}
|
||||
|
|
@ -39,4 +39,8 @@ CGAL_QT4_EXPORT QRectF viewportsBbox(const QGraphicsScene*);
|
|||
} // namespace Qt
|
||||
} // namespace CGAL
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/Qt/utility_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // CGAL_QT_UTILITY_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 <Andreas.Fabri@geometryfactory.com>
|
||||
// Laurent Rineau <Laurent.Rineau@geometryfactory.com>
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#define CGAL_INLINE_FUNCTION inline
|
||||
#else
|
||||
#define CGAL_INLINE_FUNCTION
|
||||
#endif
|
||||
|
||||
#include <CGAL/Qt/utility.h>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsView>
|
||||
#include <QList>
|
||||
#include <QPoint>
|
||||
#include <QPointF>
|
||||
|
||||
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
|
||||
|
|
@ -19,420 +19,10 @@
|
|||
// Author(s) : Andreas Fabri <Andreas.Fabri@geometryfactory.com>
|
||||
// Laurent Rineau <Laurent.Rineau@geometryfactory.com>
|
||||
|
||||
#include <CGAL/Qt/GraphicsViewNavigation.h>
|
||||
#include <QApplication>
|
||||
#include <QLabel>
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <QAction>
|
||||
#include <QMessageBox>
|
||||
#include <QStatusBar>
|
||||
#include <QGraphicsView>
|
||||
#include <QGLWidget>
|
||||
#include <QTextStream>
|
||||
#include <QSettings>
|
||||
#include <QUrl>
|
||||
#include <QDesktopWidget>
|
||||
#include <QRegExp>
|
||||
#include <QSvgGenerator>
|
||||
#ifndef CGAL_HEADER_ONLY
|
||||
|
||||
#include <CGAL/config.h> // needed to get CGAL_VERSION_STR
|
||||
#include <CGAL/Qt/DemosMainWindow.h>
|
||||
#include <iostream>
|
||||
#include <CGAL/Qt/DemosMainWindow_impl.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
#if QT_VERSION >= 0x040300
|
||||
view->setRenderHint(QPainter::HighQualityAntialiasing, checked);
|
||||
#endif
|
||||
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<QMenu*>(objectName);
|
||||
|
||||
// then search if a menu has title()==title
|
||||
if(menu) {
|
||||
return menu;
|
||||
} else {
|
||||
Q_FOREACH(menu, this->findChildren<QMenu*>()) {
|
||||
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("<!--CGAL_VERSION-->",
|
||||
QString(" (version %1)")
|
||||
.arg(cgal_version));
|
||||
#endif
|
||||
QMessageBox mb(QMessageBox::NoIcon,
|
||||
title,
|
||||
about_CGAL_txt,
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
|
||||
QLabel* mb_label = mb.findChild<QLabel*>("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<QAction *>(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
|
||||
|
|
|
|||
|
|
@ -19,320 +19,9 @@
|
|||
// Author(s) : Andreas Fabri <Andreas.Fabri@geometryfactory.com>
|
||||
// Laurent Rineau <Laurent.Rineau@geometryfactory.com>
|
||||
|
||||
#ifndef CGAL_HEADER_ONLY
|
||||
|
||||
#include <CGAL/Qt/GraphicsViewNavigation.h>
|
||||
#include <CGAL/Qt/utility.h> // for mapToScene(QGraphicsView*, QRect)
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <QEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
#include <QGraphicsView>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsRectItem>
|
||||
#include <QFlags>
|
||||
#include <QScrollBar>
|
||||
|
||||
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<QGraphicsView*>(obj);
|
||||
if(v == NULL) {
|
||||
QWidget* viewport = qobject_cast<QWidget*>(obj);
|
||||
if(viewport == NULL) {
|
||||
return false;
|
||||
}
|
||||
v = qobject_cast<QGraphicsView*>(viewport->parent());
|
||||
if(v == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch(event->type())
|
||||
{
|
||||
case QEvent::KeyPress: {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(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<QKeyEvent*>(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<QWheelEvent*>(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<QMouseEvent*>(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<QMouseEvent*>(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<QMouseEvent*>(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 <CGAL/Qt/GraphicsViewNavigation_impl.h>
|
||||
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
|
|
|||
|
|
@ -19,178 +19,9 @@
|
|||
// Author(s) : Andreas Fabri <Andreas.Fabri@geometryfactory.com>
|
||||
// Laurent Rineau <Laurent.Rineau@geometryfactory.com>
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <QGraphicsPathItem>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QPolygonF>
|
||||
#include <QPainterPath>
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#ifndef CGAL_HEADER_ONLY
|
||||
|
||||
#include <CGAL/Qt/GraphicsViewPolylineInput.h>
|
||||
#include <CGAL/Qt/GraphicsViewPolylineInput_impl.h>
|
||||
|
||||
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<QGraphicsSceneMouseEvent *>(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<QGraphicsSceneMouseEvent *>(event);
|
||||
mouseMoveEvent(mouseEvent);
|
||||
return QObject::eventFilter(obj, event);
|
||||
} else if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(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
|
||||
|
|
|
|||
|
|
@ -19,35 +19,9 @@
|
|||
// Author(s) : Andreas Fabri <Andreas.Fabri@geometryfactory.com>
|
||||
// Laurent Rineau <Laurent.Rineau@geometryfactory.com>
|
||||
|
||||
#ifndef CGAL_HEADER_ONLY
|
||||
|
||||
#include <CGAL/Qt/debug.h>
|
||||
#include <QDir>
|
||||
#include <CGAL/Qt/debug_impl.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -18,13 +18,9 @@
|
|||
//
|
||||
// Author(s) : Laurent Rineau <Laurent.Rineau@geometryfactory.com>
|
||||
|
||||
#include <QDir>
|
||||
#include <CGAL/Qt/resources.h>
|
||||
#ifndef CGAL_HEADER_ONLY
|
||||
|
||||
// cannot use namespaces because of the Q_INIT_RESOURCE macro
|
||||
void CGAL_Qt4_init_resources() {
|
||||
Q_INIT_RESOURCE(File);
|
||||
Q_INIT_RESOURCE(Triangulation_2);
|
||||
Q_INIT_RESOURCE(Input);
|
||||
Q_INIT_RESOURCE(CGAL);
|
||||
}
|
||||
#include <CGAL/Qt/resources.h>
|
||||
#include <CGAL/Qt/resources_impl.h>
|
||||
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
|
|
|||
|
|
@ -19,36 +19,9 @@
|
|||
// Author(s) : Andreas Fabri <Andreas.Fabri@geometryfactory.com>
|
||||
// Laurent Rineau <Laurent.Rineau@geometryfactory.com>
|
||||
|
||||
#ifndef CGAL_HEADER_ONLY
|
||||
|
||||
#include <CGAL/Qt/utility.h>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsView>
|
||||
#include <QList>
|
||||
#include <QPoint>
|
||||
#include <QPointF>
|
||||
#include <CGAL/Qt/utility_impl.h>
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -20,20 +20,29 @@
|
|||
#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)
|
||||
# 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
|
||||
// CJTODO: uncomment this when everything is ready
|
||||
/*#ifdef CGAL_HEADER_ONLY
|
||||
# define CGAL_DLL_IMPORT
|
||||
# define CGAL_DLL_EXPORT
|
||||
# define CGAL_DLL_LOCA
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -96,4 +96,8 @@ inline bool do_intersect(
|
|||
|
||||
} //namespace CGAL
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/Bbox_2_Line_2_intersection_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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 <CGAL/Simple_cartesian.h>
|
||||
typedef CGAL::Simple_cartesian<double> 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
|
||||
|
|
@ -75,6 +75,8 @@ inline bool do_intersect_ray_2(
|
|||
}
|
||||
} //namespace CGAL
|
||||
|
||||
|
||||
#ifdef CGAL_HEADER_ONLY
|
||||
#include <CGAL/Ray_2_Bbox_2_intersection_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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 <CGAL/Simple_cartesian.h>
|
||||
typedef CGAL::Simple_cartesian<double> 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
|
||||
|
|
@ -22,346 +22,12 @@
|
|||
//
|
||||
// Author(s) : Geert-Jan Giezeman
|
||||
|
||||
#ifndef CGAL_HEADER_ONLY
|
||||
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Bbox_2_Line_2_intersection.h>
|
||||
#include <CGAL/Bbox_2_Line_2_intersection_impl.h>
|
||||
|
||||
#include <CGAL/Ray_2_Bbox_2_intersection.h>
|
||||
typedef CGAL::Simple_cartesian<double> Rcart;
|
||||
#include <CGAL/Ray_2_Bbox_2_intersection_impl.h>
|
||||
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ template <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Circle_2<R>& c)
|
||||
{
|
||||
switch(os.iword(IO::mode)) {
|
||||
switch(get_mode(os)) {
|
||||
case IO::ASCII :
|
||||
os << c.center() << ' ' << c.squared_radius() << ' '
|
||||
<< static_cast<int>(c.orientation());
|
||||
|
|
@ -271,7 +271,7 @@ extract(std::istream& is, Circle_2<R>& 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;
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ std::ostream&
|
|||
insert(std::ostream& os, const Direction_2<R>& 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 <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Direction_2<R>& 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<R>& 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<R>& 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);
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ std::ostream&
|
|||
insert(std::ostream& os, const Direction_3<R>& 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 <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Direction_3<R>& 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<R>& 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<R>& 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);
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ template < class R >
|
|||
std::ostream &
|
||||
operator<<(std::ostream& os, const Iso_cuboid_3<R>& r)
|
||||
{
|
||||
switch(os.iword(IO::mode)) {
|
||||
switch(get_mode(os)) {
|
||||
case IO::ASCII :
|
||||
return os << (r.min)() << ' ' << (r.max)();
|
||||
case IO::BINARY :
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ template < class R >
|
|||
std::ostream &
|
||||
operator<<(std::ostream &os, const Iso_rectangle_2<R> &r)
|
||||
{
|
||||
switch(os.iword(IO::mode)) {
|
||||
switch(get_mode(os)) {
|
||||
case IO::ASCII :
|
||||
return os << (r.min)() << ' ' << (r.max)();
|
||||
case IO::BINARY :
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ template <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Line_2<R>& 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<R>& 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;
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ template < class R >
|
|||
std::ostream &
|
||||
operator<<(std::ostream &os, const Line_3<R> &l)
|
||||
{
|
||||
switch(os.iword(IO::mode)) {
|
||||
switch(get_mode(os)) {
|
||||
case IO::ASCII :
|
||||
return os << l.point(0) << ' ' << l.point(1);
|
||||
case IO::BINARY :
|
||||
|
|
|
|||
|
|
@ -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 <CGAL/Origin_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // CGAL_ORIGIN_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
|
||||
|
|
@ -235,7 +235,7 @@ template < class R >
|
|||
std::ostream &
|
||||
operator<<(std::ostream &os, const Plane_3<R> &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<R> &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;
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ template <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Point_2<R>& 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 <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Point_2<R>& 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<R>& 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<R>& 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;
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ template <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Point_3<R>& 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 :
|
||||
|
|
@ -213,7 +213,7 @@ template <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Point_3<R>& 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();
|
||||
|
|
@ -244,7 +244,7 @@ std::istream&
|
|||
extract(std::istream& is, Point_3<R>& 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;
|
||||
|
|
@ -269,7 +269,7 @@ std::istream&
|
|||
extract(std::istream& is, Point_3<R>& 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;
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ template <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Ray_2<R>& 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 <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Ray_2<R>& r, const Homogeneous_tag&)
|
||||
{
|
||||
switch(os.iword(IO::mode))
|
||||
switch(get_mode(os))
|
||||
{
|
||||
case IO::ASCII :
|
||||
return os << r.source() << ' ' << r.second_point();
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ template <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Ray_3<R>& 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 <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Ray_3<R>& r, const Homogeneous_tag&)
|
||||
{
|
||||
switch(os.iword(IO::mode))
|
||||
switch(get_mode(os))
|
||||
{
|
||||
case IO::ASCII :
|
||||
return os << r.start() << ' ' << r.direction();
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ template < class R >
|
|||
std::ostream &
|
||||
operator<<(std::ostream &os, const Segment_2<R> &s)
|
||||
{
|
||||
switch(os.iword(IO::mode)) {
|
||||
switch(get_mode(os)) {
|
||||
case IO::ASCII :
|
||||
return os << s.source() << ' ' << s.target();
|
||||
case IO::BINARY :
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ template < class R >
|
|||
std::ostream &
|
||||
operator<<(std::ostream &os, const Segment_3<R> &s)
|
||||
{
|
||||
switch(os.iword(IO::mode)) {
|
||||
switch(get_mode(os)) {
|
||||
case IO::ASCII :
|
||||
return os << s.source() << ' ' << s.target();
|
||||
case IO::BINARY :
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ template <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Sphere_3<R>& c,const Cartesian_tag&)
|
||||
{
|
||||
switch(os.iword(IO::mode)) {
|
||||
switch(get_mode(os)) {
|
||||
case IO::ASCII :
|
||||
os << c.center() << ' ' << c.squared_radius() << ' '
|
||||
<< static_cast<int>(c.orientation());
|
||||
|
|
@ -248,7 +248,7 @@ template <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Sphere_3<R>& c, const Homogeneous_tag&)
|
||||
{
|
||||
switch(os.iword(IO::mode)) {
|
||||
switch(get_mode(os)) {
|
||||
case IO::ASCII :
|
||||
os << c.center() << ' ' << c.squared_radius() << ' '
|
||||
<< static_cast<int>(c.orientation());
|
||||
|
|
@ -291,7 +291,7 @@ extract(std::istream& is, Sphere_3<R>& 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<R>& 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;
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ template < class R >
|
|||
std::ostream &
|
||||
operator<<(std::ostream &os, const Tetrahedron_3<R> &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 :
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ template < class R >
|
|||
std::ostream &
|
||||
operator<<(std::ostream &os, const Triangle_2<R> &t)
|
||||
{
|
||||
switch(os.iword(IO::mode)) {
|
||||
switch(get_mode(os)) {
|
||||
case IO::ASCII :
|
||||
return os << t[0] << ' ' << t[1] << ' ' << t[2];
|
||||
case IO::BINARY :
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ template < class R >
|
|||
std::ostream &
|
||||
operator<<(std::ostream &os, const Triangle_3<R> &t)
|
||||
{
|
||||
switch(os.iword(IO::mode)) {
|
||||
switch(get_mode(os)) {
|
||||
case IO::ASCII :
|
||||
return os << t[0] << ' ' << t[1] << ' ' << t[2];
|
||||
case IO::BINARY :
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ template <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Vector_2<R>& 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 <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Vector_2<R>& 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<R>& 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<R>& 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;
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ template <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Vector_3<R>& 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 <class R >
|
|||
std::ostream&
|
||||
insert(std::ostream& os, const Vector_3<R>& 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<R>& 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<R>& 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;
|
||||
|
|
|
|||
|
|
@ -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 <CGAL/aff_transformation_tags_impl.h>
|
||||
#endif // CGAL_HEADER_ONLY
|
||||
|
||||
#endif // CGAL_AFF_TRANSFORMATION_TAGS_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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue