3
// Copyright (C) 2004 Navel Ltd.
5
// This library is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU Lesser General Public
7
// License as published by the Free Software Foundation; either
8
// version 2.1 of the License, or (at your option) any later version.
10
// This library is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
// Lesser General Public License for more details.
15
// You should have received a copy of the GNU Lesser General Public
16
// License along with this library; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26
Tools::Geometry::LineSegment::LineSegment()
27
: m_dimension( 0 ), m_pStartPoint( 0 ), m_pEndPoint( 0 )
31
Tools::Geometry::LineSegment::LineSegment( const double* pStartPoint, const double* pEndPoint, unsigned long dimension )
32
: m_dimension( dimension )
34
// no need to initialize arrays to 0 since if a bad_alloc is raised the destructor will not be called.
36
m_pStartPoint = new double[m_dimension];
37
m_pEndPoint = new double[m_dimension];
38
memcpy( m_pStartPoint, pStartPoint, m_dimension * sizeof( double ) );
39
memcpy( m_pEndPoint, pEndPoint, m_dimension * sizeof( double ) );
42
Tools::Geometry::LineSegment::LineSegment( const Point& startPoint, const Point& endPoint )
43
: m_dimension( startPoint.m_dimension )
45
if ( startPoint.m_dimension != endPoint.m_dimension )
46
throw Tools::IllegalArgumentException(
47
"Tools::Geometry::LineSegment::LineSegment: Points have different dimensionalities."
50
// no need to initialize arrays to 0 since if a bad_alloc is raised the destructor will not be called.
52
m_pStartPoint = new double[m_dimension];
53
m_pEndPoint = new double[m_dimension];
54
memcpy( m_pStartPoint, startPoint.m_pCoords, m_dimension * sizeof( double ) );
55
memcpy( m_pEndPoint, endPoint.m_pCoords, m_dimension * sizeof( double ) );
58
Tools::Geometry::LineSegment::LineSegment( const LineSegment& l )
59
: m_dimension( l.m_dimension )
61
// no need to initialize arrays to 0 since if a bad_alloc is raised the destructor will not be called.
63
m_pStartPoint = new double[m_dimension];
64
m_pEndPoint = new double[m_dimension];
65
memcpy( m_pStartPoint, l.m_pStartPoint, m_dimension * sizeof( double ) );
66
memcpy( m_pEndPoint, l.m_pEndPoint, m_dimension * sizeof( double ) );
69
Tools::Geometry::LineSegment::~LineSegment()
71
delete[] m_pStartPoint;
75
Tools::Geometry::LineSegment& Tools::Geometry::LineSegment::operator=( const LineSegment & l )
79
makeDimension( l.m_dimension );
80
memcpy( m_pStartPoint, l.m_pStartPoint, m_dimension * sizeof( double ) );
81
memcpy( m_pEndPoint, l.m_pEndPoint, m_dimension * sizeof( double ) );
87
bool Tools::Geometry::LineSegment::operator==( const LineSegment& l ) const
89
if ( m_dimension != l.m_dimension )
90
throw IllegalArgumentException(
91
"Tools::Geometry::LineSegment::operator==: LineSegments have different number of dimensions."
94
for ( unsigned long i = 0; i < m_dimension; i++ )
97
m_pStartPoint[i] < l.m_pStartPoint[i] - std::numeric_limits<double>::epsilon() ||
98
m_pStartPoint[i] > l.m_pStartPoint[i] + std::numeric_limits<double>::epsilon() ) return false;
101
m_pEndPoint[i] < l.m_pEndPoint[i] - std::numeric_limits<double>::epsilon() ||
102
m_pEndPoint[i] > l.m_pEndPoint[i] + std::numeric_limits<double>::epsilon() ) return false;
111
Tools::Geometry::LineSegment* Tools::Geometry::LineSegment::clone()
113
return new LineSegment( *this );
117
// ISerializable interface
119
unsigned long Tools::Geometry::LineSegment::getByteArraySize()
121
return ( sizeof( unsigned long ) + m_dimension * sizeof( double ) * 2 );
124
void Tools::Geometry::LineSegment::loadFromByteArray( const byte* ptr )
126
unsigned long dimension;
127
memcpy( &dimension, ptr, sizeof( unsigned long ) );
128
ptr += sizeof( unsigned long );
130
makeDimension( dimension );
131
memcpy( m_pStartPoint, ptr, m_dimension * sizeof( double ) );
132
ptr += m_dimension * sizeof( double );
133
memcpy( m_pEndPoint, ptr, m_dimension * sizeof( double ) );
134
//ptr += m_dimension * sizeof(double);
137
void Tools::Geometry::LineSegment::storeToByteArray( byte** data, unsigned long& len )
139
len = getByteArraySize();
140
*data = new byte[len];
143
memcpy( ptr, &m_dimension, sizeof( unsigned long ) );
144
ptr += sizeof( unsigned long );
145
memcpy( ptr, m_pStartPoint, m_dimension * sizeof( double ) );
146
ptr += m_dimension * sizeof( double );
147
memcpy( ptr, m_pEndPoint, m_dimension * sizeof( double ) );
148
//ptr += m_dimension * sizeof(double);
154
bool Tools::Geometry::LineSegment::intersectsShape( const IShape& s ) const
156
throw IllegalStateException(
157
"Tools::Geometry::LineSegment::intersectsShape: Not implemented yet!"
161
bool Tools::Geometry::LineSegment::containsShape( const IShape& s ) const
166
bool Tools::Geometry::LineSegment::touchesShape( const IShape& s ) const
168
throw IllegalStateException(
169
"Tools::Geometry::LineSegment::touchesShape: Not implemented yet!"
173
void Tools::Geometry::LineSegment::getCenter( Point& out ) const
175
double* coords = new double[m_dimension];
177
for ( unsigned long cDim = 0; cDim < m_dimension; cDim++ )
180
( std::abs( m_pStartPoint[cDim] - m_pEndPoint[cDim] ) / 2.0 ) +
181
std::min( m_pStartPoint[cDim], m_pEndPoint[cDim] );
184
out = Point( coords, m_dimension );
189
unsigned long Tools::Geometry::LineSegment::getDimension() const
194
void Tools::Geometry::LineSegment::getMBR( Region& out ) const
196
double* low = new double[m_dimension];
197
double* high = new double[m_dimension];
199
for ( unsigned long cDim = 0; cDim < m_dimension; cDim++ )
201
low[cDim] = std::min( m_pStartPoint[cDim], m_pEndPoint[cDim] );
202
high[cDim] = std::max( m_pStartPoint[cDim], m_pEndPoint[cDim] );
205
out = Region( low, high, m_dimension );
211
double Tools::Geometry::LineSegment::getArea() const
216
double Tools::Geometry::LineSegment::getMinimumDistance( const IShape& s ) const
218
const Point* ppt = dynamic_cast<const Point*>( &s );
221
return getMinimumDistance( *ppt );
225
const Region* pr = dynamic_cast<const Region*>(&s);
228
return pr->getMinimumDistance(*this);
232
throw IllegalStateException(
233
"Tools::Geometry::LineSegment::getMinimumDistance: Not implemented yet!"
237
double Tools::Geometry::LineSegment::getMinimumDistance( const Point& p ) const
239
if ( m_dimension == 1 )
240
throw Tools::NotSupportedException(
241
"Tools::Geometry::LineSegment::getMinimumDistance: Use an Interval instead."
244
if ( m_dimension != 2 )
245
throw Tools::NotSupportedException(
246
"Tools::Geometry::LineSegment::getMinimumDistance: Distance for high dimensional spaces not supported!"
249
if ( m_pEndPoint[0] >= m_pStartPoint[0] - std::numeric_limits<double>::epsilon() &&
250
m_pEndPoint[0] <= m_pStartPoint[0] + std::numeric_limits<double>::epsilon() ) return std::abs( p.m_pCoords[0] - m_pStartPoint[0] );
252
if ( m_pEndPoint[1] >= m_pStartPoint[1] - std::numeric_limits<double>::epsilon() &&
253
m_pEndPoint[1] <= m_pStartPoint[1] + std::numeric_limits<double>::epsilon() ) return std::abs( p.m_pCoords[1] - m_pStartPoint[1] );
255
double x1 = m_pStartPoint[0];
256
double x2 = m_pEndPoint[0];
257
double x0 = p.m_pCoords[0];
258
double y1 = m_pStartPoint[1];
259
double y2 = m_pEndPoint[1];
260
double y0 = p.m_pCoords[1];
262
return std::abs(( x2 - x1 ) *( y1 - y0 ) - ( x1 - x0 ) *( y2 - y1 ) ) / ( std::sqrt(( x2 - x1 ) *( x2 - x1 ) + ( y2 - y1 ) *( y2 - y1 ) ) );
265
// assuming moving from start to end, positive distance is from right hand side.
266
double Tools::Geometry::LineSegment::getRelativeMinimumDistance( const Point& p ) const
268
if ( m_dimension == 1 )
269
throw Tools::NotSupportedException(
270
"Tools::Geometry::LineSegment::getRelativeMinimumDistance: Use an Interval instead."
273
if ( m_dimension != 2 )
274
throw Tools::NotSupportedException(
275
"Tools::Geometry::LineSegment::getRelativeMinimumDistance: Distance for high dimensional spaces not supported!"
278
if ( m_pEndPoint[0] >= m_pStartPoint[0] - std::numeric_limits<double>::epsilon() &&
279
m_pEndPoint[0] <= m_pStartPoint[0] + std::numeric_limits<double>::epsilon() )
281
if ( m_pStartPoint[1] < m_pEndPoint[1] ) return m_pStartPoint[0] - p.m_pCoords[0];
282
if ( m_pStartPoint[1] >= m_pEndPoint[1] ) return p.m_pCoords[0] - m_pStartPoint[0];
285
if ( m_pEndPoint[1] >= m_pStartPoint[1] - std::numeric_limits<double>::epsilon() &&
286
m_pEndPoint[1] <= m_pStartPoint[1] + std::numeric_limits<double>::epsilon() )
288
if ( m_pStartPoint[0] < m_pEndPoint[0] ) return p.m_pCoords[1] - m_pStartPoint[1];
289
if ( m_pStartPoint[0] >= m_pEndPoint[0] ) return m_pStartPoint[1] - p.m_pCoords[1];
292
double x1 = m_pStartPoint[0];
293
double x2 = m_pEndPoint[0];
294
double x0 = p.m_pCoords[0];
295
double y1 = m_pStartPoint[1];
296
double y2 = m_pEndPoint[1];
297
double y0 = p.m_pCoords[1];
299
return (( x1 - x0 ) *( y2 - y1 ) - ( x2 - x1 ) *( y1 - y0 ) ) / ( std::sqrt(( x2 - x1 ) *( x2 - x1 ) + ( y2 - y1 ) *( y2 - y1 ) ) );
302
double Tools::Geometry::LineSegment::getRelativeMaximumDistance( const Tools::Geometry::Region& r ) const
304
if ( m_dimension == 1 )
305
throw Tools::NotSupportedException(
306
"Tools::Geometry::LineSegment::getRelativeMaximumDistance: Use an Interval instead."
309
if ( m_dimension != 2 )
310
throw Tools::NotSupportedException(
311
"Tools::Geometry::LineSegment::getRelativeMaximumDistance: Distance for high dimensional spaces not supported!"
315
double d1 = getRelativeMinimumDistance( Point( r.m_pLow, 2 ) );
318
coords[0] = r.m_pLow[0];
319
coords[1] = r.m_pHigh[1];
320
double d2 = getRelativeMinimumDistance( Point( coords, 2 ) );
322
double d3 = getRelativeMinimumDistance( Point( r.m_pHigh, 2 ) );
324
coords[0] = r.m_pHigh[0];
325
coords[1] = r.m_pLow[1];
326
double d4 = getRelativeMinimumDistance( Point( coords, 2 ) );
328
return std::max( d1, std::max( d2, std::max( d3, d4 ) ) );
331
double Tools::Geometry::LineSegment::getAngleOfPerpendicularRay()
333
if ( m_dimension == 1 )
334
throw Tools::NotSupportedException(
335
"Tools::Geometry::LineSegment::getAngleOfPerpendicularRay: Use an Interval instead."
338
if ( m_dimension != 2 )
339
throw Tools::NotSupportedException(
340
"Tools::Geometry::LineSegment::getAngleOfPerpendicularRay: Distance for high dimensional spaces not supported!"
343
if ( m_pStartPoint[0] >= m_pEndPoint[0] - std::numeric_limits<double>::epsilon() &&
344
m_pStartPoint[0] <= m_pEndPoint[0] + std::numeric_limits<double>::epsilon() ) return 0.0;
346
if ( m_pStartPoint[1] >= m_pEndPoint[1] - std::numeric_limits<double>::epsilon() &&
347
m_pStartPoint[1] <= m_pEndPoint[1] + std::numeric_limits<double>::epsilon() ) return M_PI_2;
349
return std::atan( -( m_pStartPoint[0] - m_pEndPoint[0] ) / ( m_pStartPoint[1] - m_pEndPoint[1] ) );
352
void Tools::Geometry::LineSegment::makeInfinite( unsigned long dimension )
354
makeDimension( dimension );
355
for ( unsigned long cIndex = 0; cIndex < m_dimension; cIndex++ )
357
m_pStartPoint[cIndex] = std::numeric_limits<double>::max();
358
m_pEndPoint[cIndex] = std::numeric_limits<double>::max();
362
void Tools::Geometry::LineSegment::makeDimension( unsigned long dimension )
364
if ( m_dimension != dimension )
366
delete[] m_pStartPoint;
367
delete[] m_pEndPoint;
369
// remember that this is not a constructor. The object will be destructed normally if
370
// something goes wrong (bad_alloc), so we must take care not to leave the object at an intermediate state.
374
m_dimension = dimension;
375
m_pStartPoint = new double[m_dimension];
376
m_pEndPoint = new double[m_dimension];
380
std::ostream& Tools::Geometry::operator<<( std::ostream& os, const LineSegment& l )
382
for ( unsigned long cDim = 0; cDim < l.m_dimension; cDim++ )
384
os << l.m_pStartPoint[cDim] << ", " << l.m_pEndPoint[cDim] << " ";