source: tags/ms_r18q1/WINDOW/AW_position.cxx

Last change on this file was 14197, checked in by westram, 9 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.6 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : AW_position.cxx                                   //
4//   Purpose   : Positions, Vectors and Angles                     //
5//                                                                 //
6//   Coded by Ralf Westram (coder@reallysoft.de) in July 2007      //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#include "aw_position.hxx"
13
14using namespace std;
15using namespace AW;
16
17const Position AW::Origin(0, 0);
18const Vector   AW::ZeroVector(0, 0, 0);
19
20const double AW::Angle::rad2deg = 180/M_PI;
21const double AW::Angle::deg2rad = M_PI/180;
22
23const Angle AW::Eastwards (  0*Angle::deg2rad);
24const Angle AW::Southwards( 90*Angle::deg2rad);
25const Angle AW::Westwards (180*Angle::deg2rad);
26const Angle AW::Northwards(270*Angle::deg2rad);
27
28void LineVector::standardize() {
29    // make diagonal positive (i.e. make it a Vector which contains width and height of a Rectangle)
30    // this changes the start position to the upper-left corner
31
32    double dx = ToEnd.x();
33    double dy = ToEnd.y();
34
35    if (dx<0) {
36        if (dy<0) {
37            Start += ToEnd; // lower-right to upper-left
38            ToEnd.rotate180deg();
39        }
40        else {
41            Start.movex(dx); // upper-right to upper-left
42            ToEnd.negx();
43        }
44    }
45    else if (dy<0) {
46        Start.movey(dy); // lower-left to upper-left
47        ToEnd.negy();
48    }
49}
50
51Vector& Vector::rotate45deg() {
52    static double inv_sqrt2 = 1/sqrt(2.0);
53
54    *this = (*this+Vector(*this).rotate90deg()) * inv_sqrt2;
55    return *this;
56}
57
58void Angle::recalcRadian() const {
59    Radian = atan2(Normal.y(), Normal.x());
60}
61
62void Angle::recalcNormal() const {
63    Normal = Vector(std::cos(Radian), std::sin(Radian));
64    aw_assert(Normal.is_normalized());
65}
66
67Position Rectangle::nearest_corner(const Position& topos) const {
68    Position nearest = get_corner(0);
69    double   mindist = Distance(nearest, topos);
70    for (int i = 1; i<4; ++i) {
71        Position c    = get_corner(i);
72        double   dist = Distance(c, topos);
73        if (dist<mindist) {
74            mindist = dist;
75            nearest = c;
76        }
77    }
78    return nearest;
79}
80
81// --------------------------------------------------------------------------------
82
83namespace AW {
84    Position crosspoint(const LineVector& l1, const LineVector& l2, double& factor_l1, double& factor_l2) {
85        // calculates the crossing point of the two straight lines defined by l1 and l2.
86        // sets two factors, so that
87        // crosspoint == l1.start()+factor_l1*l1.line_vector();
88        // crosspoint == l2.start()+factor_l2*l2.line_vector();
89
90        // Herleitung:
91        // x1+g*sx = x2+h*tx
92        // y1+g*sy = y2+h*ty
93        //
94        // h = -(x2-sx*g-x1)/tx
95        // h = (y1-y2+sy*g)/ty                                        (h is factor_l2)
96        //
97        // -(x2-sx*g-x1)/tx = (y1-y2+sy*g)/ty
98        //
99        // g = (tx*y1+ty*x2-tx*y2-ty*x1)/(sx*ty-sy*tx)
100        //
101        // g = (tx*(y1-y2)+ty*(x2-x1))/(sx*ty-sy*tx)                  (g is factor_l1)
102
103        const Position& p1 = l1.start();
104        const Position& p2 = l2.start();
105
106        const Vector& s = l1.line_vector();
107        const Vector& t = l2.line_vector();
108
109        aw_assert(s.has_length() && t.has_length());
110
111        factor_l1 = (t.x()*(p1.ypos()-p2.ypos()) + t.y()*(p2.xpos()-p1.xpos()))
112            / (s.x()*t.y() - s.y()*t.x());
113
114        factor_l2 = (p1.ypos()-p2.ypos()+s.y()*factor_l1) / t.y();
115
116        return p1 + factor_l1*s; 
117    }
118
119    Position nearest_linepoint(const Position& pos, const LineVector& line, double& factor) {
120        // returns the Position on 'line' with minimum distance to 'pos'
121        // factor is set to [0.0 .. 1.0],
122        //    where 0.0 means "at line.start()"
123        //    and   1.0 means "at line.head()"
124
125        if (!line.has_length()) {
126            factor = 0.5;
127            return line.start();
128        }
129
130        Vector upright(line.line_vector());
131        upright.rotate90deg();
132
133        LineVector pos2line(pos, upright);
134
135        double   unused;
136        Position nearest = crosspoint(line, pos2line, factor, unused);
137
138        if (factor<0) {
139            nearest = line.start();
140            factor  = 0;
141        }
142        else if (factor>1) {
143            nearest = line.head();
144            factor  = 1;
145        }
146        return nearest;
147    }
148};
149
Note: See TracBrowser for help on using the repository browser.