/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/hittest.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/Thuban/UI/hittest.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1589 - (hide annotations)
Fri Aug 15 12:49:08 2003 UTC (21 years, 6 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/hittest.py
File MIME type: text/x-python
File size: 2590 byte(s)
* Thuban/UI/viewport.py (ViewPort.find_shape_at)
(ViewPort._find_shape_in_layer, ViewPort._find_shape_in_layer)
(ViewPort._get_hit_tester, ViewPort.projected_points)
(ViewPort._hit_point, ViewPort._hit_arc, ViewPort._hit_polygon)
(ViewPort._find_label_at): Split the find_shape_at method into
several new methods and use the functions in the hit-test module.

* Thuban/UI/hittest.py: New module with Python-level hit-testing
functions

* test/test_hittest.py: New. Test for the new hittest module

1 bh 1589 # Copyright (C) 2003 by Intevation GmbH
2     # Authors:
3     # Martin Mueller <[email protected]>
4     # Bernhard Herzog <[email protected]>
5     #
6     # This program is free software under the GPL (>=v2)
7     # Read the file COPYING coming with the software for details.
8    
9     """Hit testing functions"""
10    
11     __version__ = "$Revision$"
12     # $Source$
13     # $Id$
14    
15     from math import hypot, sqrt
16    
17     def line_hit(sx, sy, ex, ey, px, py):
18     """Determine whether the line fom (SX, SY) to (EX, EY) is `hit' by a
19     click at (PX, PY), or whether a polygon containing this line is hit
20     in the interior at (PX, PY).
21    
22     Return -1 if the line it self his hit. Otherwise, return +1 if a
23     horizontal line from (PX, PY) to (-Infinity, PY) intersects the line
24     and 0 if it doesn't.
25    
26     The nonnegative return values can be used to determine whether (PX, PY)
27     is an interior point of a polygon according to the even-odd rule.
28     """
29    
30     if (ey < sy):
31     sx, ex = ex, sx
32     sy, ey = ey, sy
33    
34     not_horizontal = ey > sy + 2
35     if not_horizontal and (py >= ey or py < sy):
36     return 0
37    
38     vx = ex - sx
39     vy = ey - sy
40    
41     len = sqrt(vx * vx + vy * vy)
42     if not len:
43     # degenerate case of coincident end points. Assumes that some
44     # other part of the code has already determined whether the end
45     # point is hit.
46     return 0
47    
48     dx = px - sx
49     dy = py - sy
50     dist = vx * dy - vy * dx
51    
52     if ((not_horizontal or (px >= sx and px <= ex) or (px >= ex and px <= sx))
53     and abs(dist) <= (len * 2)):
54     return -1
55    
56     # horizontal lines (vy == 0) always return 0 here.
57     return vy and py < ey and py >= sy and dx * abs(vy) > vx * abs(dy)
58    
59    
60     def polygon_hit(points, x, y):
61     """Return whether x, y is in the polygon or on or near the boundary
62    
63     The return value is -1 if the point (x, y) is near the boundary, 1
64     if the point is inside and 0 if it's outside.
65    
66     The points argument should be a list of lists of coordinate pairs.
67     """
68     crossings = 0
69     for ring in points:
70     for i in range(len(ring) - 1):
71     sx, sy = ring[i]
72     ex, ey = ring[i + 1]
73     hit = line_hit(sx, sy, ex, ey, x, y)
74     if hit < 0:
75     return hit
76     crossings += hit
77     return crossings % 2
78    
79    
80     def arc_hit(points, x, y):
81     """Return whether x, y is on or near the arc's boundary
82    
83     The return value is -1 if the point (x, y) is near the boundary, 1
84     if the point is inside and 0 if it's outside.
85    
86     The points argument should be a list of lists of coordinate pairs.
87     """
88     return polygon_hit(points, x, y) < 0

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26