source: ThirdParty/LinearAlgebra/src/LinearAlgebra/Line.cpp@ 4ecb2d

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 4ecb2d was 4ecb2d, checked in by Frederik Heber <heber@…>, 8 years ago

Moved LinearAlgebra sub-package into ThirdParty folder.

  • needed to adapt location of libLinearAlgebra.la in all Makefile.am's.
  • relinked m4 subfolder, relinked am_doxygen_include.am. Both point to those present in molecuilder parent folder.
  • adapted configure.ac's:
  • Property mode set to 100644
File size: 10.3 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * Line.cpp
25 *
26 * Created on: Apr 30, 2010
27 * Author: crueger
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35#include "CodePatterns/MemDebug.hpp"
36
37#include "Line.hpp"
38
39#include <cmath>
40#include <iostream>
41#include <limits>
42
43#include "CodePatterns/Info.hpp"
44#include "CodePatterns/Log.hpp"
45#include "CodePatterns/Verbose.hpp"
46#include "defs.hpp"
47#include "Exceptions.hpp"
48#include "LinePoint.hpp"
49#include "MatrixContent.hpp"
50#include "Plane.hpp"
51#include "RealSpaceMatrix.hpp"
52#include "Vector.hpp"
53
54using namespace std;
55
56Line::Line(const Vector &_origin, const Vector &_direction) :
57 direction(new Vector(_direction))
58{
59 direction->Normalize();
60 origin.reset(new Vector(_origin.partition(*direction).second));
61}
62
63Line::Line(const Line &src) :
64 origin(new Vector(*src.origin)),
65 direction(new Vector(*src.direction))
66{}
67
68Line::~Line()
69{}
70
71Line &Line::operator=(const Line& rhs){
72 if(this!=&rhs){
73 origin.reset(new Vector(*rhs.origin));
74 direction.reset(new Vector(*rhs.direction));
75 }
76 return *this;
77}
78
79
80double Line::distance(const Vector &point) const{
81 // get any vector from line to point
82 Vector helper = point - *origin;
83 // partition this vector along direction
84 // the residue points from the line to the point
85 return helper.partition(*direction).second.Norm();
86}
87
88Vector Line::getClosestPoint(const Vector &point) const{
89 // get any vector from line to point
90 Vector helper = point - *origin;
91 // partition this vector along direction
92 // add only the part along the direction
93 return *origin + helper.partition(*direction).first;
94}
95
96Vector Line::getDirection() const{
97 return *direction;
98}
99
100Vector Line::getOrigin() const{
101 return *origin;
102}
103
104vector<Vector> Line::getPointsOnLine() const{
105 vector<Vector> res;
106 res.reserve(2);
107 res.push_back(*origin);
108 res.push_back(*origin+*direction);
109 return res;
110}
111
112/** Calculates the intersection of the two lines that are both on the same plane.
113 * This is taken from Weisstein, Eric W. "Line-Line Intersection." From MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/Line-LineIntersection.html
114 * \param *out output stream for debugging
115 * \param *Line1a first vector of first line
116 * \param *Line1b second vector of first line
117 * \param *Line2a first vector of second line
118 * \param *Line2b second vector of second line
119 * \return true - \a this will contain the intersection on return, false - lines are parallel
120 */
121Vector Line::getIntersection(const Line& otherLine) const{
122 pointset line1Points = getPointsOnLine();
123
124 Vector Line1a = line1Points[0];
125 Vector Line1b = line1Points[1];
126
127 pointset line2Points = otherLine.getPointsOnLine();
128
129 Vector Line2a = line2Points[0];
130 Vector Line2b = line2Points[1];
131
132 Vector res;
133
134 auto_ptr<MatrixContent> M = auto_ptr<MatrixContent>(new MatrixContent(4,4));
135
136 M->setValue(1.);
137 for (int i=0;i<3;i++) {
138 M->set(0, i, Line1a[i]);
139 M->set(1, i, Line1b[i]);
140 M->set(2, i, Line2a[i]);
141 M->set(3, i, Line2b[i]);
142 }
143
144 //Log() << Verbose(1) << "Coefficent matrix is:" << endl;
145 //for (int i=0;i<4;i++) {
146 // for (int j=0;j<4;j++)
147 // cout << "\t" << M->Get(i,j);
148 // cout << endl;
149 //}
150 if (fabs(M->Determinant()) > LINALG_MYEPSILON()) {
151 eLog() << Verbose(2) << "Determinant of coefficient matrix is NOT zero." << endl;
152 throw SkewException() << LinearAlgebraDeterminant(M->Determinant()) << LinearAlgebraMatrixContent(&(*M));
153 }
154
155 Log() << Verbose(6) << "INFO: Line1a = " << Line1a << ", Line1b = " << Line1b << ", Line2a = " << Line2a << ", Line2b = " << Line2b << "." << endl;
156
157
158 // constuct a,b,c
159 Vector a = Line1b - Line1a;
160 Vector b = Line2b - Line2a;
161 Vector c = Line2a - Line1a;
162 Vector d = Line2b - Line1b;
163 Log() << Verbose(7) << "INFO: a = " << a << ", b = " << b << ", c = " << c << "." << endl;
164 if ((a.NormSquared() <= LINALG_MYEPSILON()) || (b.NormSquared() <= LINALG_MYEPSILON())) {
165 res.Zero();
166 eLog() << Verbose(2) << "At least one of the lines is ill-defined, i.e. offset equals second vector." << endl;
167 throw LinearDependenceException() << LinearAlgebraVectorPair( make_pair(&a, &b) );
168 }
169
170 // check for parallelity
171 Vector parallel;
172 double factor = 0.;
173 if (fabs(a.ScalarProduct(b)*a.ScalarProduct(b)/a.NormSquared()/b.NormSquared() - 1.) <= LINALG_MYEPSILON()) {
174 parallel = Line1a - Line2a;
175 factor = parallel.ScalarProduct(a)/a.Norm();
176 if ((factor > -LINALG_MYEPSILON()) && (factor - 1. <= LINALG_MYEPSILON())) {
177 res = Line2a;
178 Log() << Verbose(5) << "Lines conincide." << endl;
179 return res;
180 } else {
181 parallel = Line1a - Line2b;
182 factor = parallel.ScalarProduct(a)/a.Norm();
183 if ((factor > -LINALG_MYEPSILON()) && (factor - 1. <= LINALG_MYEPSILON())) {
184 res = Line2b;
185 Log() << Verbose(5) << "Lines conincide." << endl;
186 return res;
187 }
188 }
189 eLog() << Verbose(2) << "Lines are parallel." << endl;
190 res.Zero();
191 throw LinearDependenceException() << LinearAlgebraVectorPair( make_pair(&a, &b) );
192 }
193
194 // obtain s
195 double s;
196 Vector temp1, temp2;
197 temp1 = c;
198 temp1.VectorProduct(b);
199 temp2 = a;
200 temp2.VectorProduct(b);
201 Log() << Verbose(7) << "INFO: temp1 = " << temp1 << ", temp2 = " << temp2 << "." << endl;
202 if (fabs(temp2.NormSquared()) > LINALG_MYEPSILON())
203 s = temp1.ScalarProduct(temp2)/temp2.NormSquared();
204 else
205 s = 0.;
206 Log() << Verbose(6) << "Factor s is " << temp1.ScalarProduct(temp2) << "/" << temp2.NormSquared() << " = " << s << "." << endl;
207
208 // construct intersection
209 res = a;
210 res.Scale(s);
211 res += Line1a;
212 Log() << Verbose(5) << "Intersection is at " << res << "." << endl;
213
214 return res;
215}
216
217/** Rotates the vector by an angle of \a alpha around this line.
218 * \param rhs Vector to rotate
219 * \param alpha rotation angle in radian
220 */
221Vector Line::rotateVector(const Vector &rhs, double alpha) const{
222 Vector helper = rhs;
223
224 // translate the coordinate system so that the line goes through (0,0,0)
225 helper -= *origin;
226
227 // partition the vector into a part that gets rotated and a part that lies along the line
228 pair<Vector,Vector> parts = helper.partition(*direction);
229
230 // we just keep anything that is along the axis
231 Vector res = parts.first;
232
233 // the rest has to be rotated
234 Vector a = parts.second;
235 // we only have to do the rest, if we actually could partition the vector
236 if(!a.IsZero()){
237 // construct a vector that is orthogonal to a and direction and has length |a|
238 Vector y = a;
239 // direction is normalized, so the result has length |a|
240 y.VectorProduct(*direction);
241
242 res += cos(alpha) * a + sin(alpha) * y;
243 }
244
245 // translate the coordinate system back
246 res += *origin;
247 return res;
248}
249
250Line Line::rotateLine(const Line &rhs, double alpha) const{
251 Vector lineOrigin = rotateVector(rhs.getOrigin(),alpha);
252 Vector helper = rhs.getDirection();
253 // rotate the direction without considering the ofset
254 pair<Vector,Vector> parts = helper.partition(*direction);
255 Vector lineDirection = parts.first;
256 Vector a = parts.second;
257 if(!a.IsZero()){
258 // construct a vector that is orthogonal to a and direction and has length |a|
259 Vector y = a;
260 // direction is normalized, so the result has length |a|
261 y.VectorProduct(*direction);
262
263 lineDirection += cos(alpha) * a + sin(alpha) * y;
264 }
265 return Line(lineOrigin,lineDirection);
266}
267
268Plane Line::rotatePlane(const Plane &rhs, double alpha) const{
269 vector<Vector> points = rhs.getPointsOnPlane();
270 transform(points.begin(),
271 points.end(),
272 points.begin(),
273 boost::bind(&Line::rotateVector,this,_1,alpha));
274 return Plane(points[0],points[1],points[2]);
275}
276
277RealSpaceMatrix Line::getRotationMatrix(double alpha) const
278{
279 RealSpaceMatrix M;
280 M.setRotation(getDirection(), alpha);
281
282 return M;
283}
284
285Plane Line::getOrthogonalPlane(const Vector &origin) const{
286 return Plane(getDirection(),origin);
287}
288
289std::vector<Vector> Line::getSphereIntersections() const{
290 std::vector<Vector> res;
291
292 // line is kept in normalized form, so we can skip a lot of calculations
293 double discriminant = 1-origin->NormSquared();
294 // we might have 2, 1 or 0 solutions, depending on discriminant
295 if(discriminant>=0){
296 if(discriminant==0){
297 res.push_back(*origin);
298 }
299 else{
300 Vector helper = sqrt(discriminant)*(*direction);
301 res.push_back(*origin+helper);
302 res.push_back(*origin-helper);
303 }
304 }
305 return res;
306}
307
308LinePoint Line::getLinePoint(const Vector &point) const{
309 ASSERT(isContained(point),"Line point queried for point not on line");
310 Vector helper = point - (*origin);
311 double param = helper.ScalarProduct(*direction);
312 return LinePoint(*this,param);
313}
314
315LinePoint Line::posEndpoint() const{
316 return LinePoint(*this, numeric_limits<double>::infinity());
317}
318LinePoint Line::negEndpoint() const{
319 return LinePoint(*this,-numeric_limits<double>::infinity());
320}
321
322bool operator==(const Line &x,const Line &y){
323 return *x.origin == *y.origin && *x.direction == *y.direction;
324}
325
326Line makeLineThrough(const Vector &x1, const Vector &x2){
327 if(x1==x2){
328 throw LinearDependenceException() << LinearAlgebraVectorPair( make_pair(&x1, &x2) );
329 }
330 return Line(x1,x1-x2);
331}
332
333std::ostream& operator<<(std::ostream& ost, const Line& m)
334{
335 const Vector origin = m.getOrigin();
336 const Vector direction = m.getDirection();
337 ost << "(";
338 for (int i=0;i<NDIM;i++) {
339 ost << origin[i];
340 if (i != 2)
341 ost << ",";
342 }
343 ost << ") -> (";
344 for (int i=0;i<NDIM;i++) {
345 ost << direction[i];
346 if (i != 2)
347 ost << ",";
348 }
349 ost << ")";
350 return ost;
351};
352
353
354/******************************** Points on the line ********************/
Note: See TracBrowser for help on using the repository browser.