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, &para );	  	// 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