1 #ifndef _global_h
2 # include "global.h"
3 #endif
4
5 #ifndef _pcon_h
6 # include "pcon.h"
7 #endif
8 #ifndef _pocket_h
9 # include "pocket.h"
10 #endif
11 #ifndef _wall_h
12 # include "wall.h"
13 #endif
14 #ifndef _graph_h
15 # include "graph.h"
16 #endif
17
18
~PocketConnector()19 PocketConnector::~PocketConnector() {
20 if (w1) delete w1;
21 if (b1) delete b1;
22 if (w2) delete w2;
23 if (b2) delete b2;
24 if (w3) delete w3;
25 }
26
27 //
28 // RoundedSegment berechnet eine Wand und den n�chsten Bogen eines zigzag's.
29 // Der Startpunkt ist dabei Eingabe-Parameter f�r den ersten Punkt und
30 // gleichzeitig Ausgabe-Parameter f�r den genauen Endpunkt des Bogens.
31 //
32 // e1, e2 - Punkt 1&2
33 // st - Punkt 3 ein/aus
34 // r - Radius der Rundung
35 // w - erzeugtes Wandobjekt
36 // a - erzeugtes Bogenobjekt
37 //
RoundedSegment(const Vec2 & e1,const Vec2 & e2,Vec2 * st,const Real & r,Wall ** w,StaticArc ** a)38 void PocketConnector::RoundedSegment( const Vec2 &e1, const Vec2 &e2,
39 Vec2 *st, const Real &r,
40 Wall **w, StaticArc **a )
41 {
42 const Real off=RealZero;
43 Vec2 para; // Hilfsvektoren
44 Vec2 d1 = (e1-(*st)).Norm1(); // Vektor parallel zur Start-Wand;
45 Vec2 d2 = (e2-e1).Norm1(); // Vektor parallel zur Zielwand
46
47 Vec2 o1 = d1.TurnLeft() * r; // Abstandsvektor 1
48 Vec2 o2; // Abstandsvektor 2
49
50 Real off_r; // tats�chlicher Radius (nach Verschiebung)
51
52 o1.Split( d2, ¶ ); // Anteil in Richtung d2
53
54 if ( (para.X()*d2.X()<RealZero) || (para.Y()*d2.Y()<RealZero) ) {
55 // n�chster Bogen nach rechts ...
56 o1 *= -1.0; // entgegen, dann umkehren
57 o2 = d2.TurnRight() * r;
58 off_r = r-off;
59 }
60 else {
61 // n�chster Bogen nach links ...
62 o2 = d2.TurnLeft() * r;
63 off_r = r+off;
64 }
65
66 Real l; // Faktor f�r: p = e1 + l*d2 - o2;
67
68 if (Vec2::Solve( e1+o2, d2, (*st)+o1, d1, &l )) return;
69
70 if (l<RealZero) {
71 printf( "ZigZag: Ecke: (%f,%f), Radius: %f zu gross (<%f)",
72 (double)e1.X(), (double)e1.Y(), (double)r, (double)(l+r) );
73 }
74
75 Vec2 p = (*st)+o1 + l*d1; // Mitte des Kreises
76 Vec2 p1 = p-o1; // Endpunkt erstes Segment
77 Vec2 p2 = p-o2; // Startpunkt zweites Segment
78 double a1, a2; // Winkel zu den beiden Segmentpunkten
79 double ang; // Winkel-Differenz
80
81 Vec2 from = (*st)-d1.TurnLeft()*off;
82 Vec2 to = p1-d1.TurnLeft()*off;
83 *w = new Wall( from.X(), from.Y(), to.X(), to.Y() );
84
85 if (off_r>RealZero) {
86 a1 = p.AngleDeg( p-o1 );
87 a2 = p.AngleDeg( p-o2 );
88 ang = a2-a1;
89 if (ang<0) ang+=360.;
90 if (ang>180) *a = new OuterArc( p.X(), p.Y(), off_r, a2, 360-ang );
91 else *a = new OuterArc( p.X(), p.Y(), off_r, a1, ang );
92 }
93 else *a = new StaticBall( p.X(), p.Y(), 0.0 );
94
95 *st = p2; // Startpunkt zurueckgeben
96 }
97
98 //
99 // Analog zur pocket_connect-Routine aus creator.C wurde die Init-Methode
100 // des PocketConnector's aufgebaut. Allerdings werden keine gerundeten
101 // Ecken erzeugt.
102 //
103 // start end
104 // /.\ /
105 // s_ang/ \ /
106 // / \ /
107 // p1---> --\----------------------/---- p2
108 // | dir \angle /
109 // off| \ /
110 // v ----------------
111 // egde1 edge2
112 //
113
114 #define TANGENTIAL
115
116
Init(const Pocket & p1,const Real & angle1,const Pocket & p2,const Real & angle2,const Real & cushion,const Real & rad)117 int PocketConnector::Init( const Pocket &p1, const Real &angle1,
118 const Pocket &p2, const Real &angle2,
119 const Real &cushion, const Real &rad )
120 {
121 Real ls; // Ergebnis des Gleichungssystems
122 Vec2 dir =(p2.P()-p1.P()).Norm1(); // Richtungsvektor
123 Vec2 off = dir.TurnLeft()*cushion; // Abstand der Wand
124
125 Vec2 s_ang = dir.TurnAngleDeg(angle1); // Richtungsvektor zum Startpunkt
126
127 #ifdef TANGENTIAL
128 Vec2 start = p1.P()+s_ang*p1.R(); // Startpunkt
129 #else
130 Vec2 start = p1.P() + dir*p1.R();
131 #endif
132
133 if (Vec2::Solve( start, s_ang.TurnRight(), p1.P()+off, dir, &ls )) return 1;
134 Vec2 edge1 = p1.P()+off+dir*ls;
135
136
137 Vec2 s_end = Vec2(-dir).TurnAngleDeg(-angle2);// Richtungsvektor zum Endpunkt
138
139 #ifdef TANGENTIAL
140 Vec2 end = p2.P()+s_end*p2.R(); // Endpunkt
141 #else
142 Vec2 end = p2.P() - dir*p2.R();
143 #endif
144
145 if (Vec2::Solve( end, s_end.TurnLeft(), p2.P()+off, dir, &ls )) return 1;
146 Vec2 edge2 = p2.P()+off+dir*ls;
147
148 RoundedSegment( edge1, edge2, &start, rad, &w1, &b1 );
149 RoundedSegment( edge2, end, &start, rad, &w2, &b2 );
150 w3 = new Wall( start, end );
151
152 return 0;
153 }
154
155