# -*- coding: iso-8859-7 -*-
##############################################################################
# ThanCad 0.0.9 "DoesSomething": 2dimensional CAD with raster support for engineers.
#
# Copyright (c) 2001-2009 Thanasis Stamos, August 23, 2009
# URL: http://thancad.sourceforge.net
# e-mail: cyberthanasis@excite.com
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details (www.gnu.org/licenses/gpl.html).
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
"""\
ThanCad 0.0.9 "DoesSomething": 2dimensional CAD with raster support for engineers.
This module computes intersection of 2 lines sgements (extending them if
necessary and joins them with circular arc.
"""
from math import pi,acos
from p_gmath import dpt
from p_gvec import Vector2
def thanFiletCalc(a, b, rr):
"""Extend and join 2 lines with circular arc of radius rr.
a.cp are the coordinates of the first line and b.cp are the
coordinates of the second line.
c---------------------------------------------------------------------------
c
c o K2 --->
c /|\ = (K2 C)
c / | \ ----> ---->
c / | \ t23 = (K2 K3) , t21 = (K2 K1)
c / o | o \ --> -->
c /o. | .o\ r = (C ) r = (C )
c / . | . \
c / .|. \ rr = radius
c K3 / o C \
c o \ ... = radiuses, = circular arc
c \
c o K1
c
c Let t21, t23 unit vectors.
c = t21+t23
c K2 C.
c r (K2 K1).
c
c t* r.
c r = rr*r = (C ). :
c
c + r = t21 => *(1) + r(1) = *t21(1)
c *(2) + r(2) = *t21(2) =>
c (1) * - t21(1) * = -r(1) (2x2 )
c (2) * - t21(2) * = -r(2)
c
C + r = t21 => - t21 = -r => - + t21 = r ( r t21)
c
c OK. Now I know K3 and t21 (or t12 - not sure which one) and
c K2 and t23 (or t32). How do I find K2?
c K1K2 + K2K3 = K1K3 => -K2K1 + K2K3 = K1K3 => -kapa t21 + lambda t23 = K1K3
c which is equvalent to analysis of K1K3 to t21 and t23
c Then: K2 = K1 + K1K2 = K1 + kapa t21
c---------------------------------------------------------------------------
"""
assert rr >= 0.0, "negative radius?!"
assert len(a.cp) == 2 and len(b.cp) == 2, "This routine can filet only single line segments"
K1v = Vector2(a.cp[0][0], a.cp[0][1])
K1 = Vector2(a.cp[1][0], a.cp[1][1])
d1v = abs(K1-K1v)
K3v = Vector2(b.cp[0][0], b.cp[0][1])
K3 = Vector2(b.cp[1][0], b.cp[1][1])
d3v = abs(K3-K3v)
t21 = -(K1-K1v).unit()
t23 = -(K3-K3v).unit()
th = dpt(acos(t21*t23))
if abs(th-pi) < 1e-6: return 1, None # angle almost 180 deg; no intesection
if abs(th) < 1e-6: return 1, None # angle almost 0 deg; no intersection
kapa, lamda = (K3-K1).anal(-t21, t23) # This must succeed, angle is nonzero
K2 = K1 - kapa * t21
ia = 1
if kapa < 0.0:
if abs(kapa) >= d1v:
# if len(a.cp) > 2: return 1, None # They do not intersect in this side
K1, K1v = K1, K1v
t21 = -t21
ia = 0
ib = 1
if lamda < 0.0:
if abs(lamda) >= d3v:
# if len(b.cp) > 2: return 1, None # They do not intersect in this side
K3, K3v = K3, K3v
t23 = -t23
ib = 0
if rr == 0.0:
a.cp[ia][:2] = K2.x, K2.y
b.cp[ib][:2] = K2.x, K2.y
return 0, None
d = t21+t23
r = t21.normal()
if d*r > 0.0: r = -r
r = r * rr
kapa, lamda = r.anal(d, t21)
kapa = -kapa
assert kapa > 0.0, 'filetCalc 1: impossible error'
assert lamda > 0.0, 'filetCalc 1: impossible error'
center = K2 + kapa*d
alpha = center + r
r = t23.normal()
if d*r > 0.0: r = -r
tau = center + rr*r
T = abs(K2-alpha)
if T > abs(K2-K1v): return 2, None # Circular arc is outside the first line
if T > abs(K2-K3v): return 2, None # Circular arc is outside the second line
a.cp[ia][:2] = alpha.x, alpha.y
b.cp[ib][:2] = tau.x, tau.y
theta1 = (alpha-center).atan2()
theta2 = (tau-center).atan2()
if dpt(theta2-theta1) > pi: theta1, theta2 = theta2, theta1 # We want the convex angle
cc = list(a.cp[ia])
cc[0] = center.x
cc[1] = center.y
return 0, (cc, rr, theta1, theta2)
|