Code

1e363c7627a0855a55ba1aa37af37718105c3d13
[inkscape.git] / share / extensions / ffgeom.py
1 #!/usr/bin/env python
2 """
3     ffgeom.py
4     Copyright (C) 2005 Aaron Cyril Spike, aaron@ekips.org
6     This file is part of FretFind 2-D.
8     FretFind 2-D is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
13     FretFind 2-D is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
18     You should have received a copy of the GNU General Public License
19     along with FretFind 2-D; if not, write to the Free Software
20     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 """
22 import math
23 try:
24         NaN = float('NaN')
25 except ValueError:
26         PosInf = 1e300000
27         NaN = PosInf/PosInf
29 class Point:
30         precision = 5
31         def __init__(self, x, y):
32                 self.__coordinates = {'x' : float(x), 'y' : float(y)}
33         def __getitem__(self, key):
34                 return self.__coordinates[key]
35         def __setitem__(self, key, value):
36                 self.__coordinates[key] = float(value)
37         def __repr__(self):
38                 return '(%s, %s)' % (round(self['x'],self.precision),round(self['y'],self.precision))
39         def copy(self):
40                 return Point(self['x'],self['y'])
41         def translate(self, x, y):
42                 self['x'] += x
43                 self['y'] += y
44         def move(self, x, y):
45                 self['x'] = float(x)
46                 self['y'] = float(y)
48 class Segment:
49         def __init__(self, e0, e1):
50                 self.__endpoints = [e0, e1]
51         def __getitem__(self, key):
52                 return self.__endpoints[key]
53         def __setitem__(self, key, value):
54                 self.__endpoints[key] = value
55         def __repr__(self):
56                 return repr(self.__endpoints)
57         def copy(self):
58                 return Segment(self[0],self[1])
59         def translate(self, x, y):
60                 self[0].translate(x,y)
61                 self[1].translate(x,y)
62         def move(self,e0,e1):
63                 self[0] = e0
64                 self[1] = e1
65         def delta_x(self):
66                 return self[1]['x'] - self[0]['x']
67         def delta_y(self):
68                 return self[1]['y'] - self[0]['y']
69         #alias functions
70         run = delta_x
71         rise = delta_y
72         def slope(self):
73                 if self.delta_x() != 0:
74                         return self.delta_x() / self.delta_y()
75                 return NaN
76         def intercept(self):
77                 if self.delta_x() != 0:
78                         return self[1]['y'] - (self[0]['x'] * self.slope())
79                 return NaN
80         def distanceToPoint(self, p):
81                 len = self.length()
82                 if len == 0: return NaN
83                 return math.fabs(((self[1]['x'] - self[0]['x']) * (self[0]['y'] - p['y'])) - \
84                         ((self[0]['x'] - p['x']) * (self[1]['y'] - self[0]['y']))) / len
85         def angle(self):
86                 return math.pi * (math.atan2(self.delta_y(), self.delta_x())) / 180
87         def length(self):
88                 return math.sqrt((self.delta_x() ** 2) + (self.delta_y() ** 2))
89         def pointAtLength(self, len):
90                 if self.length() == 0: return Point(NaN, NaN)
91                 ratio = len / self.length()
92                 x = self[0]['x'] + (ratio * self.delta_x())
93                 y = self[0]['y'] + (ratio * self.delta_y())
94                 return Point(x, y)
95         def pointAtRatio(self, ratio):
96                 if self.length() == 0: return Point(NaN, NaN)
97                 x = self[0]['x'] + (ratio * self.delta_x())
98                 y = self[0]['y'] + (ratio * self.delta_y())
99                 return Point(x, y)
100         def createParallel(self, p):
101                 return Segment(Point(p['x'] + self.delta_x(), p['y'] + self.delta_y()), p)
102         def intersect(self, s):
103                 return intersectSegments(self, s)
105 def intersectSegments(s1, s2):
106         x1 = s1[0]['x']
107         x2 = s1[1]['x']
108         x3 = s2[0]['x']
109         x4 = s2[1]['x']
110         
111         y1 = s1[0]['y']
112         y2 = s1[1]['y']
113         y3 = s2[0]['y']
114         y4 = s2[1]['y']
115         
116         denom = ((y4 - y3) * (x2 - x1)) - ((x4 - x3) * (y2 - y1))
117         num1 = ((x4 - x3) * (y1 - y3)) - ((y4 - y3) * (x1 - x3))
118         num2 = ((x2 - x1) * (y1 - y3)) - ((y2 - y1) * (x1 - x3))
120         num = num1
122         if denom != 0: 
123                 x = x1 + ((num / denom) * (x2 - x1))
124                 y = y1 + ((num / denom) * (y2 - y1))
125                 return Point(x, y)
126         return Point(NaN, NaN)