Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <OpenFOAM/IOstreams.H>
00027
00028
00029
00030 namespace Foam
00031 {
00032
00033
00034
00035 template<class Point, class PointRef>
00036 inline line<Point, PointRef>::line(const Point& start, const Point& end)
00037 :
00038 a_(start),
00039 b_(end)
00040 {}
00041
00042
00043 template<class Point, class PointRef>
00044 inline line<Point, PointRef>::line(Istream& is)
00045 {
00046
00047 is.readBegin("line");
00048
00049 is >> a_ >> b_;
00050
00051
00052 is.readEnd("line");
00053
00054
00055 is.check("line::line(Istream& is)");
00056 }
00057
00058
00059
00060
00061 template<class Point, class PointRef>
00062 inline PointRef line<Point, PointRef>::start() const
00063 {
00064 return a_;
00065 }
00066
00067 template<class Point, class PointRef>
00068 inline PointRef line<Point, PointRef>::end() const
00069 {
00070 return b_;
00071 }
00072
00073
00074 template<class Point, class PointRef>
00075 inline Point line<Point, PointRef>::centre() const
00076 {
00077 return 0.5*(a_ + b_);
00078 }
00079
00080
00081 template<class Point, class PointRef>
00082 inline scalar line<Point, PointRef>::mag() const
00083 {
00084 return ::Foam::mag(vec());
00085 }
00086
00087
00088 template<class Point, class PointRef>
00089 inline Point line<Point, PointRef>::vec() const
00090 {
00091 return b_ - a_;
00092 }
00093
00094
00095 template<class Point, class PointRef>
00096 PointHit<Point> line<Point, PointRef>::nearestDist(const Point& p) const
00097 {
00098 Point v = vec();
00099
00100 Point w(p - a_);
00101
00102 scalar c1 = v & w;
00103
00104 if (c1 <= 0)
00105 {
00106 return PointHit<Point>(false, a_, Foam::mag(p - a_), true);
00107 }
00108
00109 scalar c2 = v & v;
00110
00111 if (c2 <= c1)
00112 {
00113 return PointHit<Point>(false, b_, Foam::mag(p - b_), true);
00114 }
00115
00116 scalar b = c1/c2;
00117
00118 Point pb(a_ + b*v);
00119
00120 return PointHit<Point>(true, pb, Foam::mag(p - pb), false);
00121 }
00122
00123
00124 template<class Point, class PointRef>
00125 scalar line<Point, PointRef>::nearestDist
00126 (
00127 const line<Point, const Point&>& edge,
00128 Point& thisPt,
00129 Point& edgePt
00130 ) const
00131 {
00132
00133 Point a(end() - start());
00134 Point b(edge.end() - edge.start());
00135 Point c(edge.start() - start());
00136
00137 Point crossab = a ^ b;
00138 scalar magCrossSqr = magSqr(crossab);
00139
00140 if (magCrossSqr > VSMALL)
00141 {
00142 scalar s = ((c ^ b) & crossab)/magCrossSqr;
00143 scalar t = ((c ^ a) & crossab)/magCrossSqr;
00144
00145
00146 if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
00147 {
00148
00149 thisPt = start() + a*s;
00150 edgePt = edge.start() + b*t;
00151 }
00152 else
00153 {
00154
00155
00156
00157
00158 PointHit<Point> this0(nearestDist(edge.start()));
00159 PointHit<Point> this1(nearestDist(edge.end()));
00160 scalar thisDist = min(this0.distance(), this1.distance());
00161
00162
00163 PointHit<Point> edge0(edge.nearestDist(start()));
00164 PointHit<Point> edge1(edge.nearestDist(end()));
00165 scalar edgeDist = min(edge0.distance(), edge1.distance());
00166
00167 if (thisDist < edgeDist)
00168 {
00169 if (this0.distance() < this1.distance())
00170 {
00171 thisPt = this0.rawPoint();
00172 edgePt = edge.start();
00173 }
00174 else
00175 {
00176 thisPt = this1.rawPoint();
00177 edgePt = edge.end();
00178 }
00179 }
00180 else
00181 {
00182 if (edge0.distance() < edge1.distance())
00183 {
00184 thisPt = start();
00185 edgePt = edge0.rawPoint();
00186 }
00187 else
00188 {
00189 thisPt = end();
00190 edgePt = edge1.rawPoint();
00191 }
00192 }
00193 }
00194 }
00195 else
00196 {
00197
00198
00199
00200 scalar edge0 = edge.start() & a;
00201 scalar edge1 = edge.end() & a;
00202 bool edgeOrder = edge0 < edge1;
00203
00204 scalar minEdge = (edgeOrder ? edge0 : edge1);
00205 scalar maxEdge = (edgeOrder ? edge1 : edge0);
00206 const Point& minEdgePt = (edgeOrder ? edge.start() : edge.end());
00207 const Point& maxEdgePt = (edgeOrder ? edge.end() : edge.start());
00208
00209 scalar this0 = start() & a;
00210 scalar this1 = end() & a;
00211 bool thisOrder = this0 < this1;
00212
00213 scalar minThis = min(this0, this1);
00214 scalar maxThis = max(this1, this0);
00215 const Point& minThisPt = (thisOrder ? start() : end());
00216 const Point& maxThisPt = (thisOrder ? end() : start());
00217
00218 if (maxEdge < minThis)
00219 {
00220
00221 edgePt = maxEdgePt;
00222 thisPt = minThisPt;
00223 }
00224 else if (maxEdge < maxThis)
00225 {
00226
00227 edgePt = maxEdgePt;
00228 thisPt = nearestDist(edgePt).rawPoint();
00229 }
00230 else
00231 {
00232
00233 if (minEdge < minThis)
00234 {
00235
00236
00237 thisPt = minThisPt;
00238 edgePt = edge.nearestDist(thisPt).rawPoint();
00239 }
00240 else if (minEdge < maxThis)
00241 {
00242
00243 edgePt = minEdgePt;
00244 thisPt = nearestDist(edgePt).rawPoint();
00245 }
00246 else
00247 {
00248
00249 edgePt = minEdgePt;
00250 thisPt = maxThisPt;
00251 }
00252 }
00253 }
00254
00255 return Foam::mag(thisPt - edgePt);
00256 }
00257
00258
00259
00260
00261 template<class Point, class PointRef>
00262 inline Istream& operator>>(Istream& is, line<Point, PointRef>& l)
00263 {
00264
00265 is.readBegin("line");
00266
00267 is >> l.a_ >> l.b_;
00268
00269
00270 is.readEnd("line");
00271
00272
00273 is.check("Istream& operator>>(Istream&, line&)");
00274
00275 return is;
00276 }
00277
00278
00279 template<class Point, class PointRef>
00280 inline Ostream& operator<<(Ostream& os, const line<Point, PointRef>& l)
00281 {
00282 os << token::BEGIN_LIST << l.a_ << token::SPACE << l.b_ << token::END_LIST;
00283 return os;
00284 }
00285
00286
00287
00288
00289 }
00290
00291