File: pcon.C

package info (click to toggle)
flying 6.20-2
  • links: PTS
  • area: main
  • in suites: hamm, potato, slink
  • size: 688 kB
  • ctags: 1,875
  • sloc: cpp: 10,966; makefile: 223
file content (154 lines) | stat: -rw-r--r-- 4,225 bytes parent folder | download | duplicates (4)
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
#ifndef _global_h
#	include "global.h"
#endif

#ifndef _pcon_h
#	include "pcon.h"
#endif
#ifndef _pocket_h
#	include "pocket.h"
#endif
#ifndef _wall_h
#	include "wall.h"
#endif
#ifndef _graph_h
#	include "graph.h"
#endif


PocketConnector::~PocketConnector() {
	if (w1)	delete w1;
	if (b1)	delete b1;
	if (w2)	delete w2;
	if (b2)	delete b2;
	if (w3)	delete w3;
}

//
// RoundedSegment berechnet eine Wand und den nchsten Bogen eines zigzag's.
// Der Startpunkt ist dabei Eingabe-Parameter fr den ersten Punkt und
// gleichzeitig Ausgabe-Parameter fr den genauen Endpunkt des Bogens.
//
// e1, e2	- Punkt 1&2
// st			- Punkt 3 ein/aus
// r			- Radius der Rundung
// w			- erzeugtes Wandobjekt
// a			- erzeugtes Bogenobjekt
//
void PocketConnector::RoundedSegment( const Vec2 &e1, const Vec2 &e2,
		Vec2 *st,	const Real &r,
		Wall **w, StaticArc **a )
{
const Real off=RealZero;
Vec2	para;								// Hilfsvektoren
Vec2	d1 = (e1-(*st)).Norm1();	// Vektor parallel zur Start-Wand;
Vec2	d2 = (e2-e1).Norm1();		// Vektor parallel zur Zielwand

Vec2	o1 = d1.TurnLeft() * r;		// Abstandsvektor 1
Vec2	o2;								// Abstandsvektor 2

Real		off_r;							// tatschlicher Radius (nach Verschiebung)

			o1.Split( d2, &para );	  	// Anteil in Richtung d2

			if ( (para.X()*d2.X()<RealZero) || (para.Y()*d2.Y()<RealZero) ) {
				// nchster Bogen nach rechts ...
						o1   *= -1.0;	// entgegen, dann umkehren
						o2    = d2.TurnRight() * r;
						off_r = r-off;
			}
			else {
				// nchster Bogen nach links ...
						o2    = d2.TurnLeft() * r;
						off_r = r+off;
			}

Real l;		// Faktor fr: p = e1 + l*d2 - o2;

		if (Vec2::Solve( e1+o2, d2, (*st)+o1, d1, &l ))		return;

		if (l<RealZero) {
			printf( "ZigZag: Ecke: (%f,%f), Radius: %f zu gross (<%f)",
							(double)e1.X(), (double)e1.Y(), (double)r, (double)(l+r) );
		}

Vec2 p  = (*st)+o1 + l*d1;				// Mitte des Kreises
Vec2 p1 = p-o1;								// Endpunkt erstes Segment
Vec2 p2 = p-o2;								// Startpunkt zweites Segment
double a1, a2;									// Winkel zu den beiden Segmentpunkten
double ang;										// Winkel-Differenz

Vec2	from = (*st)-d1.TurnLeft()*off;
Vec2	to   = p1-d1.TurnLeft()*off;
		*w = new Wall( from.X(), from.Y(), to.X(), to.Y() );

		if (off_r>RealZero) {
			a1 = p.AngleDeg( p-o1 );
			a2 = p.AngleDeg( p-o2 );
			ang = a2-a1;
			if (ang<0)	ang+=360.;
			if (ang>180)	*a = new OuterArc( p.X(), p.Y(), off_r, a2, 360-ang );
			else				*a = new OuterArc( p.X(), p.Y(), off_r, a1, ang );
		}
		else					*a = new StaticBall( p.X(), p.Y(), 0.0 );

		*st = p2;								// Startpunkt zurueckgeben
}

//
// Analog zur pocket_connect-Routine aus creator.C wurde die Init-Methode
// des PocketConnector's aufgebaut. Allerdings werden keine gerundeten
// Ecken erzeugt.
//
//			  start                          end
//          /.\                            /
//		s_ang/   \                          /
//			 /     \                        /
//		  p1---> --\----------------------/----  p2
//			|  dir   \angle               /
//		off|			 \                  /
//			v	 		   ----------------
//				 		 egde1           edge2
//

#define	TANGENTIAL


int PocketConnector::Init( const Pocket &p1, const Real &angle1,
							 const Pocket &p2, const Real &angle2,
							 const Real &cushion, const Real &rad )
{
Real		ls;                                 // Ergebnis des Gleichungssystems
Vec2	dir	=(p2.P()-p1.P()).Norm1();		// Richtungsvektor
Vec2	off	= dir.TurnLeft()*cushion;		// Abstand der Wand

Vec2	s_ang = dir.TurnAngleDeg(angle1);	// Richtungsvektor zum Startpunkt

#ifdef TANGENTIAL
Vec2	start = p1.P()+s_ang*p1.R();			// Startpunkt
#else
Vec2	start = p1.P() + dir*p1.R();
#endif

		if (Vec2::Solve( start, s_ang.TurnRight(), p1.P()+off, dir, &ls ))	return 1;
Vec2	edge1 = p1.P()+off+dir*ls;


Vec2	s_end = Vec2(-dir).TurnAngleDeg(-angle2);// Richtungsvektor zum Endpunkt

#ifdef TANGENTIAL
Vec2	end   = p2.P()+s_end*p2.R();			// Endpunkt
#else
Vec2	end	= p2.P() - dir*p2.R();
#endif

		if (Vec2::Solve( end, s_end.TurnLeft(), p2.P()+off, dir, &ls ))	return 1;
Vec2	edge2 = p2.P()+off+dir*ls;

	RoundedSegment( edge1, edge2, &start, rad, &w1, &b1 );
	RoundedSegment( edge2,   end, &start, rad, &w2, &b2 );
	w3 = new Wall( start, end );

	return 0;
}