File: pt2d.h

package info (click to toggle)
battleball 2.0-13
  • links: PTS
  • area: main
  • in suites: woody
  • size: 1,016 kB
  • ctags: 3,097
  • sloc: cpp: 15,310; makefile: 48; csh: 34
file content (163 lines) | stat: -rw-r--r-- 5,326 bytes parent folder | download | duplicates (5)
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
// Copyright (c) 1997 Philip A. Hardin (pahardin@cs.utexas.edu)
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License v2 or later.


#ifndef PT2D_h
#define PT2D_h


#include <math.h>    // to get sqrt(), M_SQRT2, sin(), etc.
#include "general.h"
#include "ang2d.h"


/*======================================================================*/
struct pt2d {
  enum {numDims=2};
  typedef double coord;
  coord	x,y;

  	pt2d() {};
  	pt2d(coord nx, coord ny) : x(nx), y(ny) {}
  	pt2d(const coord* ptr) {x= *ptr++; y= *ptr++;}
  	pt2d(coord*& ptr)      {x= *ptr++; y= *ptr++;}
  	pt2d(const pt2d*& ptr) {*this= *ptr++;}
  	pt2d(pt2d*& ptr)       {*this= *ptr++;}

  // inline functions
  bool	operator==(const pt2d& p) const	{return (x==p.x and y==p.y);}
  bool	operator!=(const pt2d& p) const	{return (x!=p.x or y!=p.y);}
  void	operator+=(const pt2d& p)	{x+=p.x; y+=p.y;}
  void	operator-=(const pt2d& p)	{x-=p.x; y-=p.y;}
  pt2d	operator+ (const pt2d& p) const {return pt2d(x+p.x,y+p.y);}
  pt2d	operator- (const pt2d& p) const {return pt2d(x-p.x,y-p.y);}
  void	operator*=(const pt2d& sc)	{x*=sc.x; y*=sc.y;}
  void	operator*=(coord sc)		{x*=sc; y*=sc;}
  pt2d	operator* (coord sc) const	{return pt2d(x*sc, y*sc);}
  pt2d	operator* (const pt2d& p) const	{return pt2d(x*p.x, y*p.y);}
  coord	Dot       (const pt2d& p) const	{return x*p.x +y*p.y;}
  void	operator/=(coord dv)		{x/=dv; y/=dv;}
  pt2d	operator/ (coord sc) const	{return pt2d(x/sc, y/sc);}
  coord& operator[](int i)              {if (i==0) return x; else return y;}
  const
  coord& operator[](int i) const        {if (i==0) return x; else return y;}
  coord	Dist() const		{return sqrt((double)(sqr(x) +sqr(y)));}
  coord	FastDist() const;
  pt2d	operator>>(ang2d) const;
  void	operator>>=(ang2d);
  pt2d	Left90() const		{return pt2d(-y,x);}
  pt2d	Right90() const		{return pt2d(y,-x);}

  // non-inline functions
  ang2d	Ang2d() const;
  void	Interpolate(const pt2d&,const pt2d&,int,int);
  pt2d  Normalized(coord=1) const;
  void	Normalize(coord);
  void	FastNormalize(coord);
  pt2d	operator>>(double) const;
  void	operator>>=(double);
};


/*----------------------------------------------------------------------*/
inline pt2d::coord pt2d::FastDist() const
{ pt2d absPt;

  absPt.x= ABS(x);
  absPt.y= ABS(y);
  if (absPt.x >absPt.y)
    return absPt.x +(M_SQRT2-1)*absPt.y;
  else
    return absPt.y +(M_SQRT2-1)*absPt.x;
}


/*----------------------------------------------------------------------*/
inline pt2d pt2d::operator>>(ang2d ang) const
{ double sinAng= sinTbl[ang&(2*MA_PI-1)];
  double cosAng= cosTbl[ang&(2*MA_PI-1)];
  return pt2d((coord)(cosAng*x - sinAng*y),(coord)(cosAng*y + sinAng*x));
}


/*----------------------------------------------------------------------*/
inline void pt2d::operator>>=(ang2d ang)
{ double sinAng= sinTbl[ang&(2*MA_PI-1)];
  double cosAng= cosTbl[ang&(2*MA_PI-1)];
  coord	tempx= (coord)(cosAng*x - sinAng*y);
  y= (coord)(cosAng*y + sinAng*x);
  x= tempx;
}


/*======================================================================*/
// Destination point is pt1 for function below
inline void Get2dXCrossing(pt2d& pt1,const pt2d& pt2,pt2d::coord planex)
{ pt1.y= pt1.y +(planex - pt1.x) * (pt2.y - pt1.y) / (pt2.x - pt1.x);
  pt1.x= planex;
}


// Destination point is pt1 for function below
inline void Get2dYCrossing(pt2d& pt1,const pt2d& pt2,pt2d::coord planey)
{ pt1.x= pt1.x +(planey - pt1.y) * (pt2.x - pt1.x) / (pt2.y - pt1.y);
  pt1.y= planey;
}


/*----------------------------------------------------------------------*/
/* In:	numPts = number of pts in pts[] array
   Out:	numPts = number of pts in destPts[] array

   Clipping algorithm:
   for each point
     if coord & prev coord are not on the same side of x==planex, then 
       find intersection w/ the x==planex plane
       copy intersection to new points
     if coord.x >=planex, then
       copy coord to new points
   if the new points form an unclosed polygon,
     add an extra new point to close the polygon
   
   Presumably, the arguments for the parameters 'greaterPts' and 'axis'
   will usually be constants, in which case an optimizing compiler should
   be able to make this function small & fast.  (This is the
   reason for declaring this function 'inline'.)
*/

inline void ClipPts(const pt2d *srcPt, pt2d destPts[], int& numPts,
		    double plane, bool greaterPts, int axis) {
  const pt2d *srcPtsEnd= srcPt +numPts;
  pt2d *destPt= destPts;
#define axis2 (not axis)

  if (numPts==0) return;
  if (((*srcPt)[axis] >= plane and greaterPts) or 
      ((*srcPt)[axis] <= plane and not greaterPts))
    *(destPt++)= *srcPt;
    
  const pt2d *prevPt= srcPt;
  srcPt++;

  while (srcPt != srcPtsEnd) {
    if (((*srcPt)[axis] >=plane) != ((*prevPt)[axis] >=plane)) {
      (*destPt)[axis]= plane;
      (*destPt)[axis2]= (*prevPt)[axis2] + (plane - (*prevPt)[axis]) * 
	((*srcPt)[axis2] - (*prevPt)[axis2]) /
	((*srcPt)[axis]  - (*prevPt)[axis]);
      destPt++;
    }
    if (((*srcPt)[axis] >=plane and greaterPts) or 
        ((*srcPt)[axis] <=plane and not greaterPts))
      *(destPt++)= *srcPt;
    prevPt= srcPt++;
  }
  
  if (destPt != destPts and *(destPt-1) != *destPts)
    *(destPt++)= *destPts;
  
  numPts= destPt -destPts;
}

#endif