nec2++ 2.1.1
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#pragma once
20
21#include <algorithm>
22#include <vector>
23#include "math_util.h"
24
28{
29public:
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
57 nec_float get_radius() const
58 {
59 return radius;
60 }
61
65std::vector<nec_wire> intersect(nec_wire& b)
66{
67 nec_float d2,sa,sb;
68 int_solve(x0,x1, b.x0, b.x1, d2,sa,sb);
69
70 nec_float epsa = b.radius / length(); // Set by the radius of the other wires
71 nec_float epsb = radius / b.length(); // Set by the radius of the other wires
72
73 std::vector<nec_wire> ret;
74
75 if (d2 > (radius + b.radius)) return ret;
76
77 if ((sa >= -epsa) && (sa <= 1.0 + epsa) && (sb >= -epsb) && (sb <= 1.0 + epsb))
78 {
79 nec_3vector a_pt = parametrize(sa);
80 nec_3vector b_pt = b.parametrize(sb);
81
82 if (sa > epsa) ret.push_back(nec_wire(x0, a_pt, radius,_tag_id));
83 if (sa < 1.0 - epsa) ret.push_back(nec_wire(a_pt, x1, radius,_tag_id));
84
85 if (sb > epsb) ret.push_back(nec_wire(b.x0, b_pt, b.radius,b._tag_id));
86 if (sb < 1.0 - epsb) ret.push_back(nec_wire(b_pt, b.x1, b.radius, b._tag_id));
87 }
88
89 return ret;
90}
91
92
96 bool intersect(nec_3vector& b0)
97 {
98 nec_float a0x = x0(0); nec_float a0y = x0(1); nec_float a0z = x0(2);
99 nec_float a1x = x1(0); nec_float a1y = x1(1); nec_float a1z = x1(2);
100
101 nec_float b0x = b0(0); nec_float b0y = b0(1); nec_float b0z = b0(2);
102 /*
103#
104# Do the expression for intersection of a cylinder and a point
105#
106# aptitude install python-sympy
107#
108#
109from sympy import *
110from sympy.matrices import Matrix
111
112a0x = Symbol('a0x')
113a1x = Symbol('a1x')
114a0y = Symbol('a0y')
115a1y = Symbol('a1y')
116a0z = Symbol('a0z')
117a1z = Symbol('a1z')
118
119b0x = Symbol('b0x')
120b0y = Symbol('b0y')
121b0z = Symbol('b0z')
122
123a0 = Matrix([a0x,a0y,a0z])
124b0 = Matrix([b0x,b0y,b0z])
125
126a1 = Matrix([a1x,a1y,a1z])
127
128# Each wire is parametrized by sa and sb
129sa = Symbol('sa')
130
131a = a0 + sa*(a1 - a0)
132b = b0
133
134# Distance between the two wires is d2
135delta = (b-a)
136d2 = delta.dot(delta)
137
138print "Distance ="
139print_python(d2)
140
141# Closest point is the set of parameters (sa,sb) that minimize d2
142# subject to the constraint that sa and sb are in the range [0,1]
143
144eqn1 = diff(d2, sa)
145
146equations = [Eq(eqn1,0)]
147print "diff(d2,sa) = "
148print eqn1
149
150
151solution = solve(equations,[sa])
152
153print solution
154*/
155 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)/
156 (-2.0*a0x*a1x - 2*a0y*a1y - 2.0*a0z*a1z + a0x*a0x + a0y*a0y + a0z*a0z + a1x*a1x + a1y*a1y + a1z*a1z);
157 if (sa < 0) sa = 0.0;
158 if (sa > 1.0) sa = 1.0;
159
160 nec_3vector a_pt = parametrize(sa);
161
162 if (distance(a_pt, b0) > radius) return false;
163 return true;
164
165}
166
167 bool similar(nec_wire& b)
168 {
169 // Check if the wires share two endpoints
170 nec_float d1 = distance(x0, b.x0);
171 nec_float d2 = distance(x0, b.x1);
172 nec_float da = std::min(d1,d2);
173
174 nec_float d3 = distance(x1, b.x1);
175 nec_float d4 = distance(x1, b.x0);
176 nec_float db = std::min(d3,d4);
177
178 if ((std::abs(da) < radius) && (std::abs(db) < radius))
179 return true;
180 else
181 return false;
182 }
183
220 static void int_solve(nec_3vector& a0, nec_3vector& a1,
221 nec_3vector& b0, nec_3vector& b1,
222 nec_float& distance, nec_float& sa, nec_float& sb)
223 {
224 nec_float a0x = a0(0); nec_float a0y = a0(1); nec_float a0z = a0(2);
225 nec_float b0x = b0(0); nec_float b0y = b0(1); nec_float b0z = b0(2);
226 nec_float a1x = a1(0); nec_float a1y = a1(1); nec_float a1z = a1(2);
227 nec_float b1x = b1(0); nec_float b1y = b1(1); nec_float b1z = b1(2);
228
229 nec_float a01x = (a0x - a1x);
230 nec_float a01y = (a0y - a1y);
231 nec_float a01z = (a0z - a1z);
232
233 nec_float b01x = (b0x - b1x);
234 nec_float b01y = (b0y - b1y);
235 nec_float b01z = (b0z - b1z);
236
237 nec_float moda = (a01x*a01x + a01y*a01y + a01z*a01z);
238 nec_float modb = (b01x*b01x + b01y*b01y + b01z*b01z);
239
240 nec_float tmp2 = (a01x*b01x + a01y*b01y + a01z*b01z);
241
242 nec_float den = (-4.0*tmp2*tmp2 + 4.0*moda*modb);
243
244 distance = 9.0e9; sa = 2.0; sb = 2.0;
245 if (0 == den) return;
246
247 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));
248
249 sa = (a0x*a01x + a0y*a01y + a0z*a01z - a01x*b0x - a01y*b0y - a01z*b0z - tmp3*tmp2/den)/moda;
250
251 sb = -(tmp3/den);
252
253 nec_float d2 = pow((a0x - b0x + sa*(a1x - a0x) - sb*(b1x - b0x)),2) +
254 pow((a0z - b0z + sa*(a1z - a0z) - sb*(b1z - b0z)),2) +
255 pow((a0y - b0y + sa*(a1y - a0y) - sb*(b1y - b0y)),2);
256
257 distance = std::sqrt(d2);
258 }
259
260private:
261 nec_3vector x0, x1;
262 nec_float radius;
263 int _tag_id;
264};
265
A class to handle properties of wires.
Definition nec_wire.h:28
std::vector< nec_wire > intersect(nec_wire &b)
Calculate whether two wires intersect.
Definition nec_wire.h:65
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:220
bool intersect(nec_3vector &b0)
Calculate whether the point is inside the wire.
Definition nec_wire.h:96