nec2++  1.7.0
nec_wire.h
1 /*
2  Copyright (C) 2008-2011 Timothy C.A. Molteno
3  tim@physics.otago.ac.nz
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 #ifndef __nec_wire__
20 #define __nec_wire__
21 
22 #include <algorithm>
23 #include "math_util.h"
24 
27 class nec_wire
28 {
29 public:
30  nec_wire(const nec_3vector& a, const nec_3vector& b, nec_float in_radius, int id)
31  : x0(a), x1(b), radius(in_radius), _tag_id(id)
32  {
33  }
34 
35  nec_3vector parametrize(nec_float s) const
36  {
37  nec_3vector ret = x0;
38  ret += (x1 - x0)*s;
39  return ret;
40  }
41 
42  nec_float distance(const nec_3vector& a, const nec_3vector& b) const
43  {
44  return (a - b).norm();
45  }
46 
47  nec_float length() const
48  {
49  return distance(x0, x1);
50  }
51 
52  int tag_id() const
53  {
54  return _tag_id;
55  }
56 
60 std::vector<nec_wire> intersect(nec_wire& b)
61 {
62  nec_float d2,sa,sb;
63  int_solve(x0,x1, b.x0, b.x1, d2,sa,sb);
64 
65  nec_float epsa = b.radius / length(); // Set by the radius of the other wires
66  nec_float epsb = radius / b.length(); // Set by the radius of the other wires
67 
68  std::vector<nec_wire> ret;
69 
70  if (d2 > (radius + b.radius)) return ret;
71 
72  if ((sa >= -epsa) && (sa <= 1.0 + epsa) && (sb >= -epsb) && (sb <= 1.0 + epsb))
73  {
74  nec_3vector a_pt = parametrize(sa);
75  nec_3vector b_pt = b.parametrize(sb);
76 
77  if (sa > epsa) ret.push_back(nec_wire(x0, a_pt, radius,_tag_id));
78  if (sa < 1.0 - epsa) ret.push_back(nec_wire(a_pt, x1, radius,_tag_id));
79 
80  if (sb > epsb) ret.push_back(nec_wire(b.x0, b_pt, b.radius,b._tag_id));
81  if (sb < 1.0 - epsb) ret.push_back(nec_wire(b_pt, b.x1, b.radius, b._tag_id));
82  }
83 
84  return ret;
85 }
86 
87 
92 {
93  nec_float a0x = x0.x(); nec_float a0y = x0.y(); nec_float a0z = x0.z();
94  nec_float a1x = x1.x(); nec_float a1y = x1.y(); nec_float a1z = x1.z();
95 
96  nec_float b0x = b0.x(); nec_float b0y = b0.y(); nec_float b0z = b0.z();
97  /*
98 #
99 # Do the expression for intersection of a cylinder and a point
100 #
101 # aptitude install python-sympy
102 #
103 #
104 from sympy import *
105 from sympy.matrices import Matrix
106 
107 a0x = Symbol('a0x')
108 a1x = Symbol('a1x')
109 a0y = Symbol('a0y')
110 a1y = Symbol('a1y')
111 a0z = Symbol('a0z')
112 a1z = Symbol('a1z')
113 
114 b0x = Symbol('b0x')
115 b0y = Symbol('b0y')
116 b0z = Symbol('b0z')
117 
118 a0 = Matrix([a0x,a0y,a0z])
119 b0 = Matrix([b0x,b0y,b0z])
120 
121 a1 = Matrix([a1x,a1y,a1z])
122 
123 # Each wire is parametrized by sa and sb
124 sa = Symbol('sa')
125 
126 a = a0 + sa*(a1 - a0)
127 b = b0
128 
129 # Distance between the two wires is d2
130 delta = (b-a)
131 d2 = delta.dot(delta)
132 
133 print "Distance ="
134 print_python(d2)
135 
136 # Closest point is the set of parameters (sa,sb) that minimize d2
137 # subject to the constraint that sa and sb are in the range [0,1]
138 
139 eqn1 = diff(d2, sa)
140 
141 equations = [Eq(eqn1,0)]
142 print "diff(d2,sa) = "
143 print eqn1
144 
145 
146 solution = solve(equations,[sa])
147 
148 print solution
149 */
150  nec_float sa = (a1x*b0x + a1y*b0y + a1z*b0z - a0x*a1x - a0x*b0x - a0y*a1y - a0y*b0y - a0z*a1z - a0z*b0z + a0x*a0x + a0y*a0y + a0z*a0z)/
151  (-2.0*a0x*a1x - 2*a0y*a1y - 2.0*a0z*a1z + a0x*a0x + a0y*a0y + a0z*a0z + a1x*a1x + a1y*a1y + a1z*a1z);
152  if (sa < 0) sa = 0.0;
153  if (sa > 1.0) sa = 1.0;
154 
155  nec_3vector a_pt = parametrize(sa);
156 
157  if (distance(a_pt, b0) > radius) return false;
158  return true;
159 
160 }
161 
162  bool similar(nec_wire& b)
163  {
164  // Check if the wires share two endpoints
165  nec_float d1 = distance(x0, b.x0);
166  nec_float d2 = distance(x0, b.x1);
167  nec_float da = std::min(d1,d2);
168 
169  nec_float d3 = distance(x1, b.x1);
170  nec_float d4 = distance(x1, b.x0);
171  nec_float db = std::min(d3,d4);
172 
173  if ((std::abs(da) < radius) && (std::abs(db) < radius))
174  return true;
175  else
176  return false;
177  }
178 
215  static void int_solve(nec_3vector& a0, nec_3vector& a1,
216  nec_3vector& b0, nec_3vector& b1,
217  nec_float& distance, nec_float& sa, nec_float& sb)
218  {
219  nec_float a0x = a0.x(); nec_float a0y = a0.y(); nec_float a0z = a0.z();
220  nec_float b0x = b0.x(); nec_float b0y = b0.y(); nec_float b0z = b0.z();
221  nec_float a1x = a1.x(); nec_float a1y = a1.y(); nec_float a1z = a1.z();
222  nec_float b1x = b1.x(); nec_float b1y = b1.y(); nec_float b1z = b1.z();
223 
224  nec_float a01x = (a0x - a1x);
225  nec_float a01y = (a0y - a1y);
226  nec_float a01z = (a0z - a1z);
227 
228  nec_float b01x = (b0x - b1x);
229  nec_float b01y = (b0y - b1y);
230  nec_float b01z = (b0z - b1z);
231 
232  nec_float moda = (a01x*a01x + a01y*a01y + a01z*a01z);
233  nec_float modb = (b01x*b01x + b01y*b01y + b01z*b01z);
234 
235  nec_float tmp2 = (a01x*b01x + a01y*b01y + a01z*b01z);
236 
237  nec_float den = (-4.0*tmp2*tmp2 + 4.0*moda*modb);
238 
239  distance = 9.0e9; sa = 2.0; sb = 2.0;
240  if (0 == den) return;
241 
242  nec_float tmp3 = (-4.0*(a0x*a0x + a0y*a0y + a1x*b0x - a0x*(a1x + b0x) + a1y*b0y - a0y*(a1y + b0y) + a01z*(a0z - b0z))*tmp2 + 4.0*moda*((a0x - b0x)*b01x + (a0y - b0y)*b01y + (a0z - b0z)*b01z));
243 
244  sa = (a0x*a01x + a0y*a01y + a0z*a01z - a01x*b0x - a01y*b0y - a01z*b0z - tmp3*tmp2/den)/moda;
245 
246  sb = -(tmp3/den);
247 
248  nec_float d2 = pow((a0x - b0x + sa*(a1x - a0x) - sb*(b1x - b0x)),2) +
249  pow((a0z - b0z + sa*(a1z - a0z) - sb*(b1z - b0z)),2) +
250  pow((a0y - b0y + sa*(a1y - a0y) - sb*(b1y - b0y)),2);
251 
252  distance = std::sqrt(d2);
253  }
254 
255 private:
256  nec_3vector x0, x1;
257  nec_float radius;
258  int _tag_id;
259 };
260 
261 #endif /*__nec_wire__*/
262 
A class to handle properties of wires.
Definition: nec_wire.h:27
bool intersect(nec_3vector &b0)
Calculate whether the point is inside the wire.
Definition: nec_wire.h:91
A Class for handling 3 dimensional vectors.
Definition: math_util.h:196
nec_float norm() const
The Euclidian norm.
Definition: math_util.h:207
static void int_solve(nec_3vector &a0, nec_3vector &a1, nec_3vector &b0, nec_3vector &b1, nec_float &distance, nec_float &sa, nec_float &sb)
Definition: nec_wire.h:215
std::vector< nec_wire > intersect(nec_wire &b)
Calculate whether two wires intersect.
Definition: nec_wire.h:60