File: geometry.h

package info (click to toggle)
bandage 0.9.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 15,684 kB
  • sloc: cpp: 45,359; sh: 491; makefile: 12
file content (794 lines) | stat: -rw-r--r-- 22,118 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
/*
 * $Revision: 2564 $
 *
 * last checkin:
 *   $Author: gutwenger $
 *   $Date: 2012-07-07 00:03:48 +0200 (Sa, 07. Jul 2012) $
 ***************************************************************/

/** \file
 * \brief Declaration of classes DPoint, DPolyline, DLine, DRect, DScaler.
 *
 * \author Joachim Kupke
 *
 * \par License:
 * This file is part of the Open Graph Drawing Framework (OGDF).
 *
 * \par
 * Copyright (C)<br>
 * See README.txt in the root directory of the OGDF installation for details.
 *
 * \par
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * Version 2 or 3 as published by the Free Software Foundation;
 * see the file LICENSE.txt included in the packaging of this file
 * for details.
 *
 * \par
 * This program 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 General Public License for more details.
 *
 * \par
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 * \see  http://www.gnu.org/copyleft/gpl.html
 ***************************************************************/




#ifdef _MSC_VER
#pragma once
#endif

#ifndef OGDF_GEOMETRY_H
#define OGDF_GEOMETRY_H

#include "List.h"
#include "Hashing.h"
#include <float.h>
#include <math.h>

#define OGDF_GEOM_EPS  1e-06


namespace ogdf {

//! Determines the orientation in hierarchical layouts.
enum Orientation {
	topToBottom, //!< Edges are oriented from top to bottom.
	bottomToTop, //!< Edges are oriented from bottom to top.
	leftToRight, //!< Edges are oriented from left to right.
	rightToLeft  //!< Edges are oriented from right to left.
};


// Important: be careful, if compared values are (+/-)DBL_MAX !!!
inline
	bool DIsEqual(const double &a, const double &b, const double eps = OGDF_GEOM_EPS)
{
	return (a < (b + eps) && a > (b - eps));
}

inline
	bool DIsGreaterEqual(const double &a, const double &b, const double eps = OGDF_GEOM_EPS)
{
	return (a > (b - eps));
}

inline
	bool DIsGreater(const double &a, const double &b, const double eps = OGDF_GEOM_EPS)
{
	return (a > (b + eps));
}

inline
	bool DIsLessEqual(const double &a, const double &b, const double eps = OGDF_GEOM_EPS)
{
	return (a < (b + eps));
}

inline
	bool DIsLess(const double &a, const double &b, const double eps = OGDF_GEOM_EPS)
{
	return (a < (b - eps));
}

inline
	double DRound(const double &d, int prec = 0)
{
	if (prec == 0)
		return floor(d + 0.5);
	double factor = pow(10.0, ((double) prec));
	return DRound(d * factor, 0) / factor;
}

/**
 * \brief Parameterized base class for points.
 *
 * This class serves as base class for two-dimensional points with specific
 * coordinate types like integer points (IPoint) and real points (DPoint).
 * The template parameter NUMBER is the type for the coordinates of the point
 * and has to support assignment and equality/inequality operators.
 */
template <class NUMBER>
class GenericPoint
{
public:
	//! The type for coordinates of the point.
	typedef NUMBER numberType;

	NUMBER m_x; //!< The x-coordinate.
	NUMBER m_y; //!< The y-coordinate.

	//! Creates a generic point.
	/**
	 * \warning Does not assign something like zero to the coordinates,
	 *          since we do not require that 0 can be casted to a NUMBER.
	 */
	GenericPoint() { }

	//! Creates a generic point (\a x,\a y).
	GenericPoint(NUMBER x, NUMBER y) : m_x(x), m_y(y) { }

	//! Copy constructor.
	GenericPoint(const GenericPoint &ip) : m_x(ip.m_x), m_y(ip.m_y) { }

	//! Assignment operator.
	GenericPoint operator=(const GenericPoint &ip) {
		m_x = ip.m_x;
		m_y = ip.m_y;
		return *this;
	}

	//! Equality operator.
	bool operator==(const GenericPoint &ip) const {
		return m_x == ip.m_x && m_y == ip.m_y;
	}

	//! Inequality operator.
	bool operator!=(const GenericPoint &ip) const {
		return m_x != ip.m_x || m_y != ip.m_y;
	}

};//class GenericPoint


/**
 * \brief Integer points.
 *
 * This class represent a two-dimensional point with integer coordinates.
 */
class OGDF_EXPORT IPoint : public GenericPoint<int>
{
public:
	//! Creates an integer point (0,0).
	IPoint() : GenericPoint<int>(0,0) { }

	//! Creates an integer point (\a x,\a y).
	IPoint(int x, int y) : GenericPoint<int>(x,y) { }

	//! Copy constructor.
	IPoint(const IPoint &ip) : GenericPoint<int>(ip) { }

	//! Returns the euclidean distance between \a p and this point.
	double distance(const IPoint &p) const;
};//class IPoint


//! Output operator for integer points.
OGDF_EXPORT ostream &operator<<(ostream &os, const IPoint &ip);


template<> class DefHashFunc<IPoint>
{
public:
	int hash(const IPoint &ip) const {
		return 7*ip.m_x + 23*ip.m_y;
	}
};


/**
 * \brief Polylines with integer coordinates.
 *
 * This class represents integer polylines by a list of integer points.
 * Such polylines are, e.g., used in layouts for representing bend
 * point lists. Note that in this case, only the bend points are in the
 * list and neither the start nor the end point.
 */
class OGDF_EXPORT IPolyline : public List<IPoint> {
public:
	//! Creates an empty integer polyline.
	IPolyline() { }

	//! Copy constructor.
	IPolyline(const IPolyline &ipl) : List<IPoint>(ipl) { }

	//! Assignment operator.
	IPolyline &operator=(const IPolyline &ipl) {
		List<IPoint>::operator =(ipl);
		return *this;
	}

	//! Returns the euclidean length of the polyline.
	double length() const;
};



/**
 * \brief Real points.
 *
 * This class represent a two-dimensional point with real coordinates.
 */
class OGDF_EXPORT DPoint : public GenericPoint<double>
{
public:
	//! Creates a real point (0,0).
	DPoint() : GenericPoint<double>(0,0) { }

	//! Creates a real point (\a x,\a y).
	DPoint(double x, double y) : GenericPoint<double>(x,y) { }

	//! Copy constructor.
	DPoint(const DPoint &dp) : GenericPoint<double>(dp) { }

	//! Relaxed equality operator.
	bool operator==(const DPoint &dp) const {
		return DIsEqual(m_x, dp.m_x) && DIsEqual(m_y,dp.m_y);
	}

	//! Returns the norm of the point.
	double norm() const {
		return sqrt(m_x*m_x + m_y*m_y);
	}

	//! Addition of real points.
	DPoint operator+(const DPoint &p) const;

	//! Subtraction of real points.
	DPoint operator-(const DPoint &p) const;

	//! Returns the euclidean distance between \a p and this point.
	double distance(const DPoint &p) const;
};

//! Output operator for real points.
OGDF_EXPORT ostream &operator<<(ostream &os, const DPoint &dp);


/**
 * \brief Vectors with real coordinates.
 */
class OGDF_EXPORT DVector : public DPoint {
public:

	//! Creates a vector (0,0).
	DVector() : DPoint() { }

	//! Creates a vector (\a x,\a y).
	DVector(double x, double y) : DPoint(x, y) { }

	//! Copy constructor.
	DVector(const DVector &dv) : DPoint(dv) { }

	//! Assignment operator.
	DVector operator=(const DPoint &ip) {
		if (this != &ip)
		{
			m_x = ip.m_x;
			m_y = ip.m_y;
		}
		return *this;
	}

	//! Multiplies all coordinates with \a val.
	DVector operator*(const double val) const;

	//! Divides all coordinates by \a val.
	DVector operator/(const double val) const;

	//! Returns the length of the vector.
	double length() const;

	//! Returns the determinante of the vector.
	double operator^(const DVector &dv) const;

	//! Returns the scalar product of this vecor and \a dv.
	double operator*(const DVector &dv) const;

	/**
	* \brief Returns a vector that is orthogonal to this vector.
	*
	* Returns the vector \f$(y/x,1)\f$ if \f$x\neq 0\f$, or \f$(1,0)\f$
	* otherwise, where \f$(x,y)\f$ is this vector.
	*/
	DVector operator++() const;

	/**
	* \brief Returns a vector that is orthogonal to this vector.
	*
	* Returns the vector \f$(-y/x,-1)\f$ if \f$x\neq 0\f$, or \f$(-1,0)\f$
	* otherwise, where \f$(x,y)\f$ is this vector.
	*/
	DVector operator--() const;
};



/**
 * \brief Polylines with real coordinates.
 *
 * This class represents real polylines by a list of real points.
 * Such polylines are, e.g., used in layouts for representing bend
 * point lists.
 */
class OGDF_EXPORT DPolyline : public List<DPoint> {
	static const double s_prec; //!< The conversion-precision.
public:
	//! Creates an empty integer polyline.
	DPolyline() { }

	//! Copy constructor.
	DPolyline(const DPolyline &dpl) : List<DPoint>(dpl) { }

	//! Assignment operator.
	DPolyline &operator=(const DPolyline &dpl) {
		List<DPoint>::operator =(dpl);
		return *this;
	}

	//! Returns the euclidean length of the polyline.
	double length() const;

	/**
	 * \brief Returns a point on the polyline which is \a fraction * \a len
	 *        away from the start point.
	 *
	 * @param fraction defines the fraction of \a lento be considered.
	 * @param len is the given length, or the length of the polyline if \a len < 0.
	 */
	DPoint position(const double fraction, double len = -1.0) const;

	//! Writes the polyline as graph in gml-format to file \a filename.
	void writeGML(const char* filename) const;

	//! Writes the polyline as graph in gml-format to output stream \a stream.
	void writeGML(ostream &stream) const;

	//! Deletes all successive points with equal coordinates.
	void unify();

	//! Deletes all redundant points on the polyline that lie on a straight line given by their adajcent points.
	void normalize();

	//! Deletes all redundant points on the polyline that lie on a straight line given by their adajcent points.
	void normalize(DPoint src, //start point of the edge
		DPoint tgt); //end point of the edge

	//! Converts all coordinates rounded to \a s_prec decimal digits.
	void convertToInt();

	//void reConvertToDouble();
};


/**
 * \brief Lines with real coordinates.
 */
class OGDF_EXPORT DLine {

protected:
	DPoint m_start; //!< The start point of the line.
	DPoint m_end;   //!< The end point of the line.

public:

	//! Creates an empty line.
	DLine() : m_start(), m_end() {}

	//! Creates a line with start point \a p1 and end point \a p2.
	DLine(const DPoint &p1, const DPoint &p2) : m_start(p1), m_end(p2) {}

	//! Copy constructor.
	DLine(const DLine &dl) : m_start(dl.m_start), m_end(dl.m_end) {}

	//! Creates a line with start point (\a x1,\a y1) and end point (\a x2,\a y2).
	DLine(double x1, double y1, double x2, double y2) {
		m_start.m_x = x1; m_start.m_y = y1; m_end.m_x = x2; m_end.m_y = y2;
	}

	//! Equality operator.
	bool operator==(const DLine &dl) const {
		return m_start == dl.m_start && m_end == dl.m_end;
	}

	//! Inequality operator.
	bool operator!=(const DLine &dl) const {
		return !(*this == dl);
	}

	//! Assignment operator.
	DLine &operator= (const DLine &dl) {
		if (this != &dl) { // don't assign myself
			m_start = dl.m_start;
			m_end   = dl.m_end;
		}
		return *this;
	}

	//! Returns the start point of the line.
	const DPoint &start() const { return m_start; }

	//! Returns the end point of the line.
	const DPoint &end() const { return m_end; }

	//! Returns the x-coordinate of the difference (end point - start point).
	double dx() const { return m_end.m_x - m_start.m_x; }

	//! Returns the y-coordinate of the difference (end point - start point).
	double dy() const { return m_end.m_y - m_start.m_y; }

	//! Returns the slope of the line.
	double slope() const { return (dx() == 0) ? DBL_MAX : dy()/dx(); }

	//! Returns the value y' such that (0,y') lies on the unlimited straight-line define dby this line.
	double yAbs() const { return (dx() == 0) ? DBL_MAX : m_start.m_y - (slope() * m_start.m_x); }

	//! Returns true iff this line runs vertically.
	bool isVertical()   const { return (DIsEqual(dx(), 0.0)); }

	//! Returns true iff this line runs horizontally.
	bool isHorizontal() const { return (DIsEqual(dy(), 0.0)); }

	/**
	 * \brief Returns true iff \a line and this line intersect.
	 *
	 * @param line is the second line.
	 * @param inter is assigned  the intersection point if true is returned.
	 * @param endpoints determines if common endpoints are treated as intersection.
	 */
	bool intersection(const DLine &line, DPoint &inter, bool endpoints = true) const;

	//! Returns true iff \a p lie on this line.
	bool contains(const DPoint &p) const;

	//! Returns the length (euclidean distance between start and edn point) of this line.
	double length() const {
		return m_start.distance(m_end);
	}

	/**
	 * \brief Computes the intersection between this line and the horizontal line through y = \a horAxis.
	 *
	 * @param horAxis defines the horizontal line.
	 * @param crossing is assigned the x-coordinate of the intersection point.
	 *
	 * \return the number of intersection points (0 = none, 1 = one, 2 = this
	 *         line lies on the horizontal line through y = \a horAxis).
	 */
	int horIntersection(const double horAxis, double &crossing) const;

	// gives the intersection with the vertical axis 'verAxis', returns the number of intersections
	// 0 = no, 1 = one, 2 = infinity or both end-points, e.g. parallel on this axis
	/**
	 * \brief Computes the intersection between this line and the vertical line through x = \a verAxis.
	 *
	 * @param verAxis defines the vertical line.
	 * @param crossing is assigned the y-coordinate of the intersection point.
	 *
	 * \return the number of intersection points (0 = none, 1 = one, 2 = this
	 *         line lies on the vertical line through x = \a verAxis).
	 */
	int verIntersection(const double verAxis, double &crossing) const;
};

//! Output operator for lines.
ostream &operator<<(ostream &os, const DLine &dl);


/**
 * \brief Rectangles with real coordinates.
 */
class OGDF_EXPORT DRect {

private:
	DPoint m_p1; //!< The lower left point of the rectangle.
	DPoint m_p2; //!< The upper right point of the rectangle.

public:
	//! Creates a rectangle with lower left and upper right point (0,0).
	DRect() : m_p1(), m_p2() {}

	//! Creates a rectangle with lower left point \a p1 and upper right point \a p2.
	DRect(const DPoint &p1, const DPoint &p2) : m_p1(p1), m_p2(p2)
	{ normalize(); }

	//! Creates a rectangle with lower left point (\a x1,\a y1) and upper right point (\a x1,\a y2).
	DRect(double x1, double y1, double x2, double y2) {
		m_p1.m_x = x1; m_p1.m_y = y1; m_p2.m_x = x2; m_p2.m_y = y2;
		normalize();
	}

	//! Creates a rectangle defined by the end points of line \a dl.
	DRect(const DLine &dl) : m_p1(dl.start()), m_p2(dl.end())
	{ normalize(); }

	//! Copy constructor.
	DRect(const DRect &dr) : m_p1(dr.m_p1), m_p2(dr.m_p2)
	{ normalize(); }

	//! Equality operator.
	bool operator==(const DRect &dr) const {
		return m_p1 == dr.m_p1 && m_p2 == dr.m_p2;
	}

	//! Inequality operator.
	bool operator!=(const DRect &dr) const {
		return !(*this == dr);
	}

	//! Assignment operator.
	DRect &operator= (const DRect &dr) {
		if (this != &dr) { // don't assign myself
			m_p1 = dr.m_p1;
			m_p2 = dr.m_p2;
		}
		return *this;
	}

	//! Returns the width of the rectangle.
	double width() const {
		return m_p2.m_x - m_p1.m_x;
	}

	//! Returns the height of the rectangle.
	double height() const {
		return m_p2.m_y - m_p1.m_y;
	}

	/**
	 * \brief Normalizes the rectangle.
	 *
	 * Makes sure that the lower left point lies below and left of the upper
	 * right point.
	 */
	void normalize() {
		if (width() < 0)  swap(m_p2.m_x, m_p1.m_x);
		if (height() < 0) swap(m_p2.m_y, m_p1.m_y);
	}

	//! Returns the lower left point of the rectangle.
	const DPoint &p1() const { return m_p1; }

	//! Returns the upper right point of the rectangle.
	const DPoint &p2() const { return m_p2; }

	//! Returns the top side of the rectangle.
	const DLine topLine() const {
		return DLine( DPoint(m_p1.m_x, m_p2.m_y), DPoint(m_p2.m_x, m_p2.m_y));
	}

	//! Returns the right side of the rectangle.
	const DLine rightLine() const {
		return DLine( DPoint(m_p2.m_x, m_p2.m_y), DPoint(m_p2.m_x, m_p1.m_y));
	}

	//! Returns the left side of the rectangle.
	const DLine leftLine() const {
		return DLine( DPoint(m_p1.m_x, m_p1.m_y), DPoint(m_p1.m_x, m_p2.m_y));
	}

	//! Returns the bottom side of the rectangle.
	const DLine bottomLine() const {
		return DLine( DPoint(m_p2.m_x, m_p1.m_y), DPoint(m_p1.m_x, m_p1.m_y));
	}

	//! Swaps the y-coordinates of the two points.
	void yInvert() { swap(m_p1.m_y, m_p2.m_y); }

	//! Swaps the x-coordinates of the two points.
	void xInvert() { swap(m_p1.m_x, m_p2.m_x); }

	//! Returns true iff \a p lies within this rectangle.
	bool contains(const DPoint &p) const {
		if (DIsLess   (p.m_x, m_p1.m_x) ||
			DIsGreater(p.m_x, m_p2.m_x) ||
			DIsLess   (p.m_y, m_p1.m_y) ||
			DIsGreater(p.m_y, m_p2.m_y))
			return false;
		return true;
	}
};

//! Output operator for rectangles.
OGDF_EXPORT ostream &operator<<(ostream &os, const DRect &dr);


/**
* \brief Scaling between coordinate systems.
*/
class OGDF_EXPORT DScaler {

private:

	const DRect *m_from; //!< Rectangluar area in source coordinate system.
	const DRect *m_to; //!< Rectangluar area in target coordinate system.

	double m_factorX; //!< The scaling factor for the x-coordinates.
	double m_factorY; //!< The scaling factor for the y-coordinates.
	double m_offsetX; //!< The offset for the x-coordinates.
	double m_offsetY; //!< The offset for the y-coordinates.

public:
	//! Creates a scaler for scaling from area \a from to area \a to.
	DScaler(const DRect &from, const DRect &to) :
		m_from(&from),
		m_to(&to),
		m_factorX(to.width()/from.width()),
		m_factorY(to.height()/from.height()),
		m_offsetX(to.p1().m_x - from.p1().m_x * m_factorX),
		m_offsetY(to.p1().m_y - from.p1().m_y * m_factorY) { }

	~DScaler() {}

	//! Returns the rectangle in the source coordinate system.
	const DRect &from() const { return *m_from; }

	//! Returns the rectangle in the target coordinate system.
	const DRect &to()   const { return *m_to;   }

	//! Transforms x-coordinates from source to target coordinate system.
	double scaleToX(double x) { return x * m_factorX + m_offsetX; }

	//! Transforms y-coordinates from source to target coordinate system.
	double scaleToY(double y) { return y * m_factorY + m_offsetY; }

	//! Scales a horizontal length from source to target coordinate system.
	double scaleWidth(double width)   { return width  * m_to->width() /m_from->width();  }

	//! Scales a vertical length from source to target coordinate system.
	double scaleHeight(double height) { return height * m_to->height()/m_from->height(); }
};


//! Output operator for scalers.
OGDF_EXPORT ostream &operator<<(ostream &os, const DScaler &ds);


/**
 * \brief Line segments with real coordinates.
 */
class OGDF_EXPORT DSegment : public DLine {

protected:

public:

	//! Creates an empty line segment.
	DSegment() : DLine() {}

	//! Creates a line segment from \a p1 to \a p2.
	DSegment(const DPoint &p1, const DPoint &p2) : DLine(p1, p2) {}

	//! Creates a line segment defined by the start and end point of line \a dl.
	DSegment(const DLine &dl) : DLine(dl) {}

	//! Creates a line segment from (\a x1,\a y1) to (\a x2,\a y2).
	DSegment(double x1, double y1, double x2, double y2) : DLine(x1, y1, x2, y2) {}

	//! Copy constructor.
	DSegment(const DSegment &ds) : DLine(ds) {}


	/**
	 * \brief Determines if \a segment is left or right of this segment.
	 *
	 * \return a positve number if \a segment is left of this segment, and a
	 *         a negative number if \a segment is right of this segment.
	 */
	double det(const DSegment &segment) const {
		return (dx() * segment.dy() - dy() * segment.dx());
	}
};


/**
 * \brief Polygons with real coordinates.
 */
class OGDF_EXPORT DPolygon : public DPolyline {

protected:

	bool m_counterclock; //!< If true points are given in conter-clockwise order.

public:
	/**
	 * \brief Creates an empty polygon.
	 *
	 * @param cc determines in which order the points will be given; true means
	 *        counter-clockwise, false means clockwise.
	 */
	DPolygon(bool cc = true) : m_counterclock(cc) { }

	//! Creates a polgon from a rectangle.
	DPolygon(const DRect &rect, bool cc = true) : m_counterclock(cc) {
		operator=(rect);
	}

	//! Copy constructor.
	DPolygon(const DPolygon  &dop) : DPolyline(dop), m_counterclock(dop.m_counterclock) { }

	//! Returns true iff points are given in counter-clockwise order.
	bool counterclock() { return m_counterclock; }

	//! Assignment operator.
	DPolygon &operator=(const DPolygon &dop) {
		List<DPoint>::operator =(dop);
		m_counterclock = dop.m_counterclock;
		return *this;
	}

	//! Assignment operator (for assigning from a rectangle).
	DPolygon &operator=(const DRect &rect);

	//! Returns the line segment that starts at position \a it.
	DSegment segment(ListConstIterator<DPoint> it) const;


	//! Inserts point \a p, that must lie on a polygon segment.
	ListIterator<DPoint> insertPoint(const DPoint &p) {
		return insertPoint(p, begin(), begin());
	}

	/**
	 * \brief Inserts point \a p, but just searching from point \a p1 to \a p2.
	 *
	 * That is, from the segment starting at \a p1 to the segment ending at \a p2.
	 */
	ListIterator<DPoint> insertPoint(const DPoint &p,
		ListIterator<DPoint> p1,
		ListIterator<DPoint> p2);

	//! Inserts point p on every segment (a,b) with \a p in the open range ]a, b[.
	void insertCrossPoint(const DPoint &p);

	//! Returns the list of intersection points of this polygon with \a p.
	int getCrossPoints(const DPolygon &p, List<DPoint> &crossPoints) const;

	//! Deletes all consecutive points that are equal.
	void unify();

	//! Deletes all points, which are not facets.
	void normalize();

	//! Writes the polygon as graph in gml-format to file \a filename.
	void writeGML(const char* filename) const;

	//! Writes the polygon as graph in gml-format to output stream \a stream.
	void writeGML(ostream &stream)      const;

	/**
	 * \brief Checks wether a Point /a p is inside the Poylgon or not.
	 * \note Polygons with crossings have inner areas that count as outside!
	 * \par p the Point to check.
	 * return true if Point is inside.
	 */
	bool containsPoint(DPoint &p) const;
};

//! Output operator for polygons.
OGDF_EXPORT ostream &operator<<(ostream &os, const DPolygon &dop);



} // end namespace ogdf

#endif