source: src/Line.cpp@ 3839e5

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 3839e5 was f932b7, checked in by Tillmann Crueger <crueger@…>, 15 years ago

Added a method to calculate the intersection of a line with the unit sphere

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/*
2 * Line.cpp
3 *
4 * Created on: Apr 30, 2010
5 * Author: crueger
6 */
7
8#include "Helpers/MemDebug.hpp"
9
10#include "Line.hpp"
11
12#include <cmath>
13
14#include "vector.hpp"
15#include "log.hpp"
16#include "verbose.hpp"
17#include "gslmatrix.hpp"
18#include "info.hpp"
19#include "Exceptions/LinearDependenceException.hpp"
20#include "Exceptions/SkewException.hpp"
21#include "Plane.hpp"
22
23using namespace std;
24
25Line::Line(const Vector &_origin, const Vector &_direction) :
26 direction(new Vector(_direction))
27{
28 direction->Normalize();
29 origin.reset(new Vector(_origin.partition(*direction).second));
30}
31
32Line::Line(const Line &src) :
33 origin(new Vector(*src.origin)),
34 direction(new Vector(*src.direction))
35{}
36
37Line::~Line()
38{}
39
40
41double Line::distance(const Vector &point) const{
42 // get any vector from line to point
43 Vector helper = point - *origin;
44 // partition this vector along direction
45 // the residue points from the line to the point
46 return helper.partition(*direction).second.Norm();
47}
48
49Vector Line::getClosestPoint(const Vector &point) const{
50 // get any vector from line to point
51 Vector helper = point - *origin;
52 // partition this vector along direction
53 // add only the part along the direction
54 return *origin + helper.partition(*direction).first;
55}
56
57Vector Line::getDirection() const{
58 return *direction;
59}
60
61Vector Line::getOrigin() const{
62 return *origin;
63}
64
65vector<Vector> Line::getPointsOnLine() const{
66 vector<Vector> res;
67 res.reserve(2);
68 res.push_back(*origin);
69 res.push_back(*origin+*direction);
70 return res;
71}
72
73/** Calculates the intersection of the two lines that are both on the same plane.
74 * This is taken from Weisstein, Eric W. "Line-Line Intersection." From MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/Line-LineIntersection.html
75 * \param *out output stream for debugging
76 * \param *Line1a first vector of first line
77 * \param *Line1b second vector of first line
78 * \param *Line2a first vector of second line
79 * \param *Line2b second vector of second line
80 * \return true - \a this will contain the intersection on return, false - lines are parallel
81 */
82Vector Line::getIntersection(const Line& otherLine) const{
83 Info FunctionInfo(__func__);
84
85 pointset line1Points = getPointsOnLine();
86
87 Vector Line1a = line1Points[0];
88 Vector Line1b = line1Points[1];
89
90 pointset line2Points = otherLine.getPointsOnLine();
91
92 Vector Line2a = line2Points[0];
93 Vector Line2b = line2Points[1];
94
95 Vector res;
96
97 auto_ptr<GSLMatrix> M = auto_ptr<GSLMatrix>(new GSLMatrix(4,4));
98
99 M->SetAll(1.);
100 for (int i=0;i<3;i++) {
101 M->Set(0, i, Line1a[i]);
102 M->Set(1, i, Line1b[i]);
103 M->Set(2, i, Line2a[i]);
104 M->Set(3, i, Line2b[i]);
105 }
106
107 //Log() << Verbose(1) << "Coefficent matrix is:" << endl;
108 //for (int i=0;i<4;i++) {
109 // for (int j=0;j<4;j++)
110 // cout << "\t" << M->Get(i,j);
111 // cout << endl;
112 //}
113 if (fabs(M->Determinant()) > MYEPSILON) {
114 Log() << Verbose(1) << "Determinant of coefficient matrix is NOT zero." << endl;
115 throw SkewException(__FILE__,__LINE__);
116 }
117
118 Log() << Verbose(1) << "INFO: Line1a = " << Line1a << ", Line1b = " << Line1b << ", Line2a = " << Line2a << ", Line2b = " << Line2b << "." << endl;
119
120
121 // constuct a,b,c
122 Vector a = Line1b - Line1a;
123 Vector b = Line2b - Line2a;
124 Vector c = Line2a - Line1a;
125 Vector d = Line2b - Line1b;
126 Log() << Verbose(1) << "INFO: a = " << a << ", b = " << b << ", c = " << c << "." << endl;
127 if ((a.NormSquared() < MYEPSILON) || (b.NormSquared() < MYEPSILON)) {
128 res.Zero();
129 Log() << Verbose(1) << "At least one of the lines is ill-defined, i.e. offset equals second vector." << endl;
130 throw LinearDependenceException(__FILE__,__LINE__);
131 }
132
133 // check for parallelity
134 Vector parallel;
135 double factor = 0.;
136 if (fabs(a.ScalarProduct(b)*a.ScalarProduct(b)/a.NormSquared()/b.NormSquared() - 1.) < MYEPSILON) {
137 parallel = Line1a - Line2a;
138 factor = parallel.ScalarProduct(a)/a.Norm();
139 if ((factor >= -MYEPSILON) && (factor - 1. < MYEPSILON)) {
140 res = Line2a;
141 Log() << Verbose(1) << "Lines conincide." << endl;
142 return res;
143 } else {
144 parallel = Line1a - Line2b;
145 factor = parallel.ScalarProduct(a)/a.Norm();
146 if ((factor >= -MYEPSILON) && (factor - 1. < MYEPSILON)) {
147 res = Line2b;
148 Log() << Verbose(1) << "Lines conincide." << endl;
149 return res;
150 }
151 }
152 Log() << Verbose(1) << "Lines are parallel." << endl;
153 res.Zero();
154 throw LinearDependenceException(__FILE__,__LINE__);
155 }
156
157 // obtain s
158 double s;
159 Vector temp1, temp2;
160 temp1 = c;
161 temp1.VectorProduct(b);
162 temp2 = a;
163 temp2.VectorProduct(b);
164 Log() << Verbose(1) << "INFO: temp1 = " << temp1 << ", temp2 = " << temp2 << "." << endl;
165 if (fabs(temp2.NormSquared()) > MYEPSILON)
166 s = temp1.ScalarProduct(temp2)/temp2.NormSquared();
167 else
168 s = 0.;
169 Log() << Verbose(1) << "Factor s is " << temp1.ScalarProduct(temp2) << "/" << temp2.NormSquared() << " = " << s << "." << endl;
170
171 // construct intersection
172 res = a;
173 res.Scale(s);
174 res += Line1a;
175 Log() << Verbose(1) << "Intersection is at " << res << "." << endl;
176
177 return res;
178}
179
180/** Rotates the vector by an angle of \a alpha around this line.
181 * \param rhs Vector to rotate
182 * \param alpha rotation angle in radian
183 */
184Vector Line::rotateVector(const Vector &rhs, double alpha) const{
185 Vector helper = rhs;
186
187 // translate the coordinate system so that the line goes through (0,0,0)
188 helper -= *origin;
189
190 // partition the vector into a part that gets rotated and a part that lies along the line
191 pair<Vector,Vector> parts = helper.partition(*direction);
192
193 // we just keep anything that is along the axis
194 Vector res = parts.first;
195
196 // the rest has to be rotated
197 Vector a = parts.second;
198 // we only have to do the rest, if we actually could partition the vector
199 if(!a.IsZero()){
200 // construct a vector that is orthogonal to a and direction and has length |a|
201 Vector y = a;
202 // direction is normalized, so the result has length |a|
203 y.VectorProduct(*direction);
204
205 res += cos(alpha) * a + sin(alpha) * y;
206 }
207
208 // translate the coordinate system back
209 res += *origin;
210 return res;
211}
212
213Plane Line::getOrthogonalPlane(const Vector &origin) const{
214 return Plane(getDirection(),origin);
215}
216
217std::vector<Vector> Line::getSphereIntersections() const{
218 std::vector<Vector> res;
219
220 // line is kept in normalized form, so we can skip a lot of calculations
221 double discriminant = 1-origin->NormSquared();
222 // we might have 2, 1 or 0 solutions, depending on discriminant
223 if(discriminant>=0){
224 if(discriminant==0){
225 res.push_back(*origin);
226 }
227 else{
228 Vector helper = sqrt(discriminant)*(*direction);
229 res.push_back(*origin+helper);
230 res.push_back(*origin-helper);
231 }
232 }
233 return res;
234}
235
236Line makeLineThrough(const Vector &x1, const Vector &x2){
237 if(x1==x2){
238 throw LinearDependenceException(__FILE__,__LINE__);
239 }
240 return Line(x1,x1-x2);
241}
Note: See TracBrowser for help on using the repository browser.