1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "IOstreams.H"
29 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
34 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
36 template<class Point, class PointRef>
37 inline line<Point, PointRef>::line(const Point& start, const Point& end)
44 template<class Point, class PointRef>
45 inline line<Point, PointRef>::line(Istream& is)
47 // Read beginning of line point pair
52 // Read end of line point pair
55 // Check state of Istream
56 is.check("line::line(Istream& is)");
60 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
62 template<class Point, class PointRef>
63 inline PointRef line<Point, PointRef>::start() const
68 template<class Point, class PointRef>
69 inline PointRef line<Point, PointRef>::end() const
75 template<class Point, class PointRef>
76 inline Point line<Point, PointRef>::centre() const
82 template<class Point, class PointRef>
83 inline scalar line<Point, PointRef>::mag() const
85 return ::Foam::mag(vec());
89 template<class Point, class PointRef>
90 inline Point line<Point, PointRef>::vec() const
96 template<class Point, class PointRef>
97 PointHit<Point> line<Point, PointRef>::nearestDist(const Point& p) const
107 return PointHit<Point>(false, a_, Foam::mag(p - a_), true);
114 return PointHit<Point>(false, b_, Foam::mag(p - b_), true);
121 return PointHit<Point>(true, pb, Foam::mag(p - pb), false);
125 template<class Point, class PointRef>
126 scalar line<Point, PointRef>::nearestDist
128 const line<Point, const Point&>& edge,
133 // From Mathworld Line-Line distance/(Gellert et al. 1989, p. 538).
134 Point a(end() - start());
135 Point b(edge.end() - edge.start());
136 Point c(edge.start() - start());
138 Point crossab = a ^ b;
139 scalar magCrossSqr = magSqr(crossab);
141 if (magCrossSqr > VSMALL)
143 scalar s = ((c ^ b) & crossab)/magCrossSqr;
144 scalar t = ((c ^ a) & crossab)/magCrossSqr;
146 // Check for end points outside of range 0..1
147 if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
149 // Both inside range 0..1
150 thisPt = start() + a*s;
151 edgePt = edge.start() + b*t;
155 // Do brute force. Distance of everything to everything.
156 // Can quite possibly be improved!
158 // From edge endpoints to *this
159 PointHit<Point> this0(nearestDist(edge.start()));
160 PointHit<Point> this1(nearestDist(edge.end()));
161 scalar thisDist = min(this0.distance(), this1.distance());
163 // From *this to edge
164 PointHit<Point> edge0(edge.nearestDist(start()));
165 PointHit<Point> edge1(edge.nearestDist(end()));
166 scalar edgeDist = min(edge0.distance(), edge1.distance());
168 if (thisDist < edgeDist)
170 if (this0.distance() < this1.distance())
172 thisPt = this0.rawPoint();
173 edgePt = edge.start();
177 thisPt = this1.rawPoint();
183 if (edge0.distance() < edge1.distance())
186 edgePt = edge0.rawPoint();
191 edgePt = edge1.rawPoint();
198 // Parallel lines. Find overlap of both lines by projecting onto
199 // direction vector (now equal for both lines).
201 scalar edge0 = edge.start() & a;
202 scalar edge1 = edge.end() & a;
203 bool edgeOrder = edge0 < edge1;
205 scalar minEdge = (edgeOrder ? edge0 : edge1);
206 scalar maxEdge = (edgeOrder ? edge1 : edge0);
207 const Point& minEdgePt = (edgeOrder ? edge.start() : edge.end());
208 const Point& maxEdgePt = (edgeOrder ? edge.end() : edge.start());
210 scalar this0 = start() & a;
211 scalar this1 = end() & a;
212 bool thisOrder = this0 < this1;
214 scalar minThis = min(this0, this1);
215 scalar maxThis = max(this1, this0);
216 const Point& minThisPt = (thisOrder ? start() : end());
217 const Point& maxThisPt = (thisOrder ? end() : start());
219 if (maxEdge < minThis)
221 // edge completely below *this
225 else if (maxEdge < maxThis)
227 // maxEdge inside interval of *this
229 thisPt = nearestDist(edgePt).rawPoint();
233 // maxEdge outside. Check if minEdge inside.
234 if (minEdge < minThis)
236 // Edge completely envelops this. Take any this point and
237 // determine nearest on edge.
239 edgePt = edge.nearestDist(thisPt).rawPoint();
241 else if (minEdge < maxThis)
243 // minEdge inside this interval.
245 thisPt = nearestDist(edgePt).rawPoint();
249 // minEdge outside this interval
256 return Foam::mag(thisPt - edgePt);
260 // * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * * //
262 template<class Point, class PointRef>
263 inline Istream& operator>>(Istream& is, line<Point, PointRef>& l)
265 // Read beginning of line point pair
266 is.readBegin("line");
270 // Read end of line point pair
273 // Check state of Ostream
274 is.check("Istream& operator>>(Istream&, line&)");
280 template<class Point, class PointRef>
281 inline Ostream& operator<<(Ostream& os, const line<Point, PointRef>& l)
283 os << token::BEGIN_LIST << l.a_ << token::SPACE << l.b_ << token::END_LIST;
288 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
290 } // End namespace Foam
292 // ************************************************************************* //