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, ¶ ); // 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;
}
|