SourceForge logo
SourceForge logo
Menu

matplotlib-checkins — Commit notification. DO NOT POST to this list, just subscribe to it.

You can subscribe to this list here.

2007 Jan
Feb
Mar
Apr
May
Jun
Jul
(115)
Aug
(120)
Sep
(137)
Oct
(170)
Nov
(461)
Dec
(263)
2008 Jan
(120)
Feb
(74)
Mar
(35)
Apr
(74)
May
(245)
Jun
(356)
Jul
(240)
Aug
(115)
Sep
(78)
Oct
(225)
Nov
(98)
Dec
(271)
2009 Jan
(132)
Feb
(84)
Mar
(74)
Apr
(56)
May
(90)
Jun
(79)
Jul
(83)
Aug
(296)
Sep
(214)
Oct
(76)
Nov
(82)
Dec
(66)
2010 Jan
(46)
Feb
(58)
Mar
(51)
Apr
(77)
May
(58)
Jun
(126)
Jul
(128)
Aug
(64)
Sep
(50)
Oct
(44)
Nov
(48)
Dec
(54)
2011 Jan
(68)
Feb
(52)
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
(1)
2018 Jan
Feb
Mar
Apr
May
(1)
Jun
Jul
Aug
Sep
Oct
Nov
Dec
S M T W T F S






1
2
3
(1)
4
(3)
5
6
7
8
9
(1)
10
(5)
11
(2)
12
(7)
13
(1)
14
15
16
17
(1)
18
(2)
19
(6)
20
(5)
21
(1)
22
23
(2)
24
(2)
25
26
(2)
27
(2)
28
(3)
29
30
(6)
31
(6)





Showing 1 results of 1

From: <ian...@us...> - 2010年05月13日 09:13:56
Revision: 8316
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8316&view=rev
Author: ianthomas23
Date: 2010年05月13日 09:13:49 +0000 (2010年5月13日)
Log Message:
-----------
Added triangular grid plotting and contouring functions.
Modified Paths:
--------------
 trunk/matplotlib/boilerplate.py
 trunk/matplotlib/lib/matplotlib/axes.py
 trunk/matplotlib/lib/matplotlib/pyplot.py
 trunk/matplotlib/setup.py
 trunk/matplotlib/setupext.py
Added Paths:
-----------
 trunk/matplotlib/examples/misc/contour_manual.py
 trunk/matplotlib/examples/pylab_examples/tricontour_demo.py
 trunk/matplotlib/examples/pylab_examples/tricontour_vs_griddata.py
 trunk/matplotlib/examples/pylab_examples/tripcolor_demo.py
 trunk/matplotlib/examples/pylab_examples/triplot_demo.py
 trunk/matplotlib/lib/matplotlib/tri/
 trunk/matplotlib/lib/matplotlib/tri/__init__.py
 trunk/matplotlib/lib/matplotlib/tri/_tri.cpp
 trunk/matplotlib/lib/matplotlib/tri/_tri.h
 trunk/matplotlib/lib/matplotlib/tri/triangulation.py
 trunk/matplotlib/lib/matplotlib/tri/tricontour.py
 trunk/matplotlib/lib/matplotlib/tri/tripcolor.py
 trunk/matplotlib/lib/matplotlib/tri/triplot.py
Modified: trunk/matplotlib/boilerplate.py
===================================================================
--- trunk/matplotlib/boilerplate.py	2010年05月12日 17:58:17 UTC (rev 8315)
+++ trunk/matplotlib/boilerplate.py	2010年05月13日 09:13:49 UTC (rev 8316)
@@ -89,6 +89,10 @@
 #'spy',
 'stem',
 'step',
+ 'tricontour',
+ 'tricontourf',
+ 'tripcolor',
+ 'triplot',
 'vlines',
 'xcorr',
 'barbs',
@@ -117,6 +121,9 @@
 #'spy' : 'sci(%(ret)s)', ### may return image or Line2D
 'quiver' : 'sci(%(ret)s)',
 'specgram' : 'sci(%(ret)s[-1])',
+ 'tricontour' : 'if %(ret)s._A is not None: sci(%(ret)s)',
+ 'tricontourf': 'if %(ret)s._A is not None: sci(%(ret)s)',
+ 'tripcolor' : 'sci(%(ret)s)',
 
 }
 
Added: trunk/matplotlib/examples/misc/contour_manual.py
===================================================================
--- trunk/matplotlib/examples/misc/contour_manual.py	 (rev 0)
+++ trunk/matplotlib/examples/misc/contour_manual.py	2010年05月13日 09:13:49 UTC (rev 8316)
@@ -0,0 +1,50 @@
+"""
+Example of displaying your own contour lines and polygons using ContourSet.
+"""
+import matplotlib.pyplot as plt
+from matplotlib.contour import ContourSet
+import matplotlib.cm as cm
+
+# Contour lines for each level are a list/tuple of polygons.
+lines0 = [ [[0,0],[0,4]] ]
+lines1 = [ [[2,0],[1,2],[1,3]] ]
+lines2 = [ [[3,0],[3,2]], [[3,3],[3,4]] ] # Note two lines.
+
+# Filled contours between two levels are also a list/tuple of polygons.
+# Points can be ordered clockwise or anticlockwise.
+filled01 = [ [[0,0],[0,4],[1,3],[1,2],[2,0]] ]
+filled12 = [ [[2,0],[3,0],[3,2],[1,3],[1,2]], # Note two polygons.
+ [[1,4],[3,4],[3,3]] ]
+
+
+plt.figure()
+
+# Filled contours using filled=True.
+cs = ContourSet(plt.gca(), [0,1,2], [filled01, filled12], filled=True, cmap=cm.bone)
+cbar = plt.colorbar(cs)
+
+# Contour lines (non-filled).
+lines = ContourSet(plt.gca(), [0,1,2], [lines0, lines1, lines2], cmap=cm.cool,
+ linewidths=3)
+cbar.add_lines(lines)
+
+plt.axis([-0.5, 3.5, -0.5, 4.5])
+plt.title('User-specified contours')
+
+
+
+# Multiple filled contour lines can be specified in a single list of polygon
+# vertices along with a list of vertex kinds (code types) as described in the
+# Path class. This is particularly useful for polygons with holes.
+# Here a code type of 1 is a MOVETO, and 2 is a LINETO.
+
+plt.figure()
+filled01 = [ [[0,0],[3,0],[3,3],[0,3],[1,1],[1,2],[2,2],[2,1]] ]
+kinds01 = [ [1,2,2,2,1,2,2,2] ]
+cs = ContourSet(plt.gca(), [0,1], [filled01], [kinds01], filled=True)
+cbar = plt.colorbar(cs)
+
+plt.axis([-0.5, 3.5, -0.5, 3.5])
+plt.title('User specified filled contours with holes')
+
+plt.show()
\ No newline at end of file
Property changes on: trunk/matplotlib/examples/misc/contour_manual.py
___________________________________________________________________
Added: svn:keywords
 + Id
Added: trunk/matplotlib/examples/pylab_examples/tricontour_demo.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/tricontour_demo.py	 (rev 0)
+++ trunk/matplotlib/examples/pylab_examples/tricontour_demo.py	2010年05月13日 09:13:49 UTC (rev 8316)
@@ -0,0 +1,98 @@
+"""
+Contour plots of unstructured triangular grids.
+"""
+import matplotlib.pyplot as plt
+import matplotlib.tri as tri
+import numpy as np
+import math
+
+# Creating a Triangulation without specifying the triangles results in the
+# Delaunay triangulation of the points.
+
+# First create the x and y coordinates of the points.
+n_angles = 48
+n_radii = 8
+min_radius = 0.25
+radii = np.linspace(min_radius, 0.95, n_radii)
+
+angles = np.linspace(0, 2*math.pi, n_angles, endpoint=False)
+angles = np.repeat(angles[...,np.newaxis], n_radii, axis=1)
+angles[:,1::2] += math.pi/n_angles
+
+x = (radii*np.cos(angles)).flatten()
+y = (radii*np.sin(angles)).flatten()
+z = (np.cos(radii)*np.cos(angles*3.0)).flatten()
+
+# Create the Triangulation; no triangles so Delaunay triangulation created.
+triang = tri.Triangulation(x, y)
+
+# Mask off unwanted triangles.
+xmid = x[triang.triangles].mean(axis=1)
+ymid = y[triang.triangles].mean(axis=1)
+mask = np.where(xmid*xmid + ymid*ymid < min_radius*min_radius, 1, 0)
+triang.set_mask(mask)
+
+# pcolor plot.
+plt.figure()
+plt.gca().set_aspect('equal')
+plt.tricontourf(triang, z)
+plt.colorbar()
+plt.tricontour(triang, z, colors='k')
+plt.title('Contour plot of Delaunay triangulation')
+
+# You can specify your own triangulation rather than perform a Delaunay
+# triangulation of the points, where each triangle is given by the indices of
+# the three points that make up the triangle, ordered in either a clockwise or
+# anticlockwise manner.
+
+xy = np.asarray([
+ [-0.101,0.872],[-0.080,0.883],[-0.069,0.888],[-0.054,0.890],[-0.045,0.897],
+ [-0.057,0.895],[-0.073,0.900],[-0.087,0.898],[-0.090,0.904],[-0.069,0.907],
+ [-0.069,0.921],[-0.080,0.919],[-0.073,0.928],[-0.052,0.930],[-0.048,0.942],
+ [-0.062,0.949],[-0.054,0.958],[-0.069,0.954],[-0.087,0.952],[-0.087,0.959],
+ [-0.080,0.966],[-0.085,0.973],[-0.087,0.965],[-0.097,0.965],[-0.097,0.975],
+ [-0.092,0.984],[-0.101,0.980],[-0.108,0.980],[-0.104,0.987],[-0.102,0.993],
+ [-0.115,1.001],[-0.099,0.996],[-0.101,1.007],[-0.090,1.010],[-0.087,1.021],
+ [-0.069,1.021],[-0.052,1.022],[-0.052,1.017],[-0.069,1.010],[-0.064,1.005],
+ [-0.048,1.005],[-0.031,1.005],[-0.031,0.996],[-0.040,0.987],[-0.045,0.980],
+ [-0.052,0.975],[-0.040,0.973],[-0.026,0.968],[-0.020,0.954],[-0.006,0.947],
+ [ 0.003,0.935],[ 0.006,0.926],[ 0.005,0.921],[ 0.022,0.923],[ 0.033,0.912],
+ [ 0.029,0.905],[ 0.017,0.900],[ 0.012,0.895],[ 0.027,0.893],[ 0.019,0.886],
+ [ 0.001,0.883],[-0.012,0.884],[-0.029,0.883],[-0.038,0.879],[-0.057,0.881],
+ [-0.062,0.876],[-0.078,0.876],[-0.087,0.872],[-0.030,0.907],[-0.007,0.905],
+ [-0.057,0.916],[-0.025,0.933],[-0.077,0.990],[-0.059,0.993] ])
+x = xy[:,0]*180/3.14159
+y = xy[:,1]*180/3.14159
+x0 = -5
+y0 = 52
+z = np.exp(-0.01*( (x-x0)*(x-x0) + (y-y0)*(y-y0) ))
+
+triangles = np.asarray([
+ [67,66, 1],[65, 2,66],[ 1,66, 2],[64, 2,65],[63, 3,64],[60,59,57],
+ [ 2,64, 3],[ 3,63, 4],[ 0,67, 1],[62, 4,63],[57,59,56],[59,58,56],
+ [61,60,69],[57,69,60],[ 4,62,68],[ 6, 5, 9],[61,68,62],[69,68,61],
+ [ 9, 5,70],[ 6, 8, 7],[ 4,70, 5],[ 8, 6, 9],[56,69,57],[69,56,52],
+ [70,10, 9],[54,53,55],[56,55,53],[68,70, 4],[52,56,53],[11,10,12],
+ [69,71,68],[68,13,70],[10,70,13],[51,50,52],[13,68,71],[52,71,69],
+ [12,10,13],[71,52,50],[71,14,13],[50,49,71],[49,48,71],[14,16,15],
+ [14,71,48],[17,19,18],[17,20,19],[48,16,14],[48,47,16],[47,46,16],
+ [16,46,45],[23,22,24],[21,24,22],[17,16,45],[20,17,45],[21,25,24],
+ [27,26,28],[20,72,21],[25,21,72],[45,72,20],[25,28,26],[44,73,45],
+ [72,45,73],[28,25,29],[29,25,31],[43,73,44],[73,43,40],[72,73,39],
+ [72,31,25],[42,40,43],[31,30,29],[39,73,40],[42,41,40],[72,33,31],
+ [32,31,33],[39,38,72],[33,72,38],[33,38,34],[37,35,38],[34,38,35],
+ [35,37,36] ])
+
+# Rather than create a Triangulation object, can simply pass x, y and triangles
+# arrays to tripcolor directly. It would be better to use a Triangulation object
+# if the same triangulation was to be used more than once to save duplicated
+# calculations.
+plt.figure()
+plt.gca().set_aspect('equal')
+plt.tricontourf(x, y, triangles, z)
+plt.colorbar()
+plt.title('Contour plot of user-specified triangulation')
+plt.xlabel('Longitude (degrees)')
+plt.ylabel('Latitude (degrees)')
+
+plt.show()
Property changes on: trunk/matplotlib/examples/pylab_examples/tricontour_demo.py
___________________________________________________________________
Added: svn:keywords
 + Id
Added: trunk/matplotlib/examples/pylab_examples/tricontour_vs_griddata.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/tricontour_vs_griddata.py	 (rev 0)
+++ trunk/matplotlib/examples/pylab_examples/tricontour_vs_griddata.py	2010年05月13日 09:13:49 UTC (rev 8316)
@@ -0,0 +1,47 @@
+"""
+Comparison of griddata and tricontour for an unstructured triangular grid.
+"""
+import matplotlib.pyplot as plt
+import matplotlib.tri as tri
+import numpy as np
+from numpy.random import uniform, seed
+from matplotlib.mlab import griddata
+import time
+
+seed(0)
+npts = 200
+ngridx = 100
+ngridy = 200
+x = uniform(-2,2,npts)
+y = uniform(-2,2,npts)
+z = x*np.exp(-x**2-y**2)
+
+# griddata and contour.
+start = time.clock()
+plt.subplot(211)
+xi = np.linspace(-2.1,2.1,ngridx)
+yi = np.linspace(-2.1,2.1,ngridy)
+zi = griddata(x,y,z,xi,yi,interp='linear')
+plt.contour(xi,yi,zi,15,linewidths=0.5,colors='k')
+plt.contourf(xi,yi,zi,15,cmap=plt.cm.jet)
+plt.colorbar() # draw colorbar
+plt.plot(x, y, 'ko', ms=3)
+plt.xlim(-2,2)
+plt.ylim(-2,2)
+plt.title('griddata and contour (%d points, %d grid points)' % (npts, ngridx*ngridy))
+print 'griddata and contour seconds:', time.clock() - start
+
+# tricontour.
+start = time.clock()
+plt.subplot(212)
+triang = tri.Triangulation(x, y)
+plt.tricontour(x, y, z, 15, linewidths=0.5, colors='k')
+plt.tricontourf(x, y, z, 15, cmap=plt.cm.jet)
+plt.colorbar()
+plt.plot(x, y, 'ko', ms=3)
+plt.xlim(-2,2)
+plt.ylim(-2,2)
+plt.title('tricontour (%d points)' % npts)
+print 'tricontour seconds:', time.clock() - start
+
+plt.show()
Property changes on: trunk/matplotlib/examples/pylab_examples/tricontour_vs_griddata.py
___________________________________________________________________
Added: svn:keywords
 + Id
Added: trunk/matplotlib/examples/pylab_examples/tripcolor_demo.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/tripcolor_demo.py	 (rev 0)
+++ trunk/matplotlib/examples/pylab_examples/tripcolor_demo.py	2010年05月13日 09:13:49 UTC (rev 8316)
@@ -0,0 +1,98 @@
+"""
+Pseudocolor plots of unstructured triangular grids.
+"""
+import matplotlib.pyplot as plt
+import matplotlib.tri as tri
+import numpy as np
+import math
+
+# Creating a Triangulation without specifying the triangles results in the
+# Delaunay triangulation of the points.
+
+# First create the x and y coordinates of the points.
+n_angles = 36
+n_radii = 8
+min_radius = 0.25
+radii = np.linspace(min_radius, 0.95, n_radii)
+
+angles = np.linspace(0, 2*math.pi, n_angles, endpoint=False)
+angles = np.repeat(angles[...,np.newaxis], n_radii, axis=1)
+angles[:,1::2] += math.pi/n_angles
+
+x = (radii*np.cos(angles)).flatten()
+y = (radii*np.sin(angles)).flatten()
+z = (np.cos(radii)*np.cos(angles*3.0)).flatten()
+
+# Create the Triangulation; no triangles so Delaunay triangulation created.
+triang = tri.Triangulation(x, y)
+
+# Mask off unwanted triangles.
+xmid = x[triang.triangles].mean(axis=1)
+ymid = y[triang.triangles].mean(axis=1)
+mask = np.where(xmid*xmid + ymid*ymid < min_radius*min_radius, 1, 0)
+triang.set_mask(mask)
+
+# pcolor plot.
+plt.figure()
+plt.gca().set_aspect('equal')
+plt.tripcolor(triang, z, shading='faceted')
+plt.colorbar()
+plt.title('tripcolor of Delaunay triangulation')
+
+
+# You can specify your own triangulation rather than perform a Delaunay
+# triangulation of the points, where each triangle is given by the indices of
+# the three points that make up the triangle, ordered in either a clockwise or
+# anticlockwise manner.
+
+xy = np.asarray([
+ [-0.101,0.872],[-0.080,0.883],[-0.069,0.888],[-0.054,0.890],[-0.045,0.897],
+ [-0.057,0.895],[-0.073,0.900],[-0.087,0.898],[-0.090,0.904],[-0.069,0.907],
+ [-0.069,0.921],[-0.080,0.919],[-0.073,0.928],[-0.052,0.930],[-0.048,0.942],
+ [-0.062,0.949],[-0.054,0.958],[-0.069,0.954],[-0.087,0.952],[-0.087,0.959],
+ [-0.080,0.966],[-0.085,0.973],[-0.087,0.965],[-0.097,0.965],[-0.097,0.975],
+ [-0.092,0.984],[-0.101,0.980],[-0.108,0.980],[-0.104,0.987],[-0.102,0.993],
+ [-0.115,1.001],[-0.099,0.996],[-0.101,1.007],[-0.090,1.010],[-0.087,1.021],
+ [-0.069,1.021],[-0.052,1.022],[-0.052,1.017],[-0.069,1.010],[-0.064,1.005],
+ [-0.048,1.005],[-0.031,1.005],[-0.031,0.996],[-0.040,0.987],[-0.045,0.980],
+ [-0.052,0.975],[-0.040,0.973],[-0.026,0.968],[-0.020,0.954],[-0.006,0.947],
+ [ 0.003,0.935],[ 0.006,0.926],[ 0.005,0.921],[ 0.022,0.923],[ 0.033,0.912],
+ [ 0.029,0.905],[ 0.017,0.900],[ 0.012,0.895],[ 0.027,0.893],[ 0.019,0.886],
+ [ 0.001,0.883],[-0.012,0.884],[-0.029,0.883],[-0.038,0.879],[-0.057,0.881],
+ [-0.062,0.876],[-0.078,0.876],[-0.087,0.872],[-0.030,0.907],[-0.007,0.905],
+ [-0.057,0.916],[-0.025,0.933],[-0.077,0.990],[-0.059,0.993] ])
+x = xy[:,0]*180/3.14159
+y = xy[:,1]*180/3.14159
+x0 = -5
+y0 = 52
+z = np.exp(-0.01*( (x-x0)*(x-x0) + (y-y0)*(y-y0) ))
+
+triangles = np.asarray([
+ [67,66, 1],[65, 2,66],[ 1,66, 2],[64, 2,65],[63, 3,64],[60,59,57],
+ [ 2,64, 3],[ 3,63, 4],[ 0,67, 1],[62, 4,63],[57,59,56],[59,58,56],
+ [61,60,69],[57,69,60],[ 4,62,68],[ 6, 5, 9],[61,68,62],[69,68,61],
+ [ 9, 5,70],[ 6, 8, 7],[ 4,70, 5],[ 8, 6, 9],[56,69,57],[69,56,52],
+ [70,10, 9],[54,53,55],[56,55,53],[68,70, 4],[52,56,53],[11,10,12],
+ [69,71,68],[68,13,70],[10,70,13],[51,50,52],[13,68,71],[52,71,69],
+ [12,10,13],[71,52,50],[71,14,13],[50,49,71],[49,48,71],[14,16,15],
+ [14,71,48],[17,19,18],[17,20,19],[48,16,14],[48,47,16],[47,46,16],
+ [16,46,45],[23,22,24],[21,24,22],[17,16,45],[20,17,45],[21,25,24],
+ [27,26,28],[20,72,21],[25,21,72],[45,72,20],[25,28,26],[44,73,45],
+ [72,45,73],[28,25,29],[29,25,31],[43,73,44],[73,43,40],[72,73,39],
+ [72,31,25],[42,40,43],[31,30,29],[39,73,40],[42,41,40],[72,33,31],
+ [32,31,33],[39,38,72],[33,72,38],[33,38,34],[37,35,38],[34,38,35],
+ [35,37,36] ])
+
+# Rather than create a Triangulation object, can simply pass x, y and triangles
+# arrays to tripcolor directly. It would be better to use a Triangulation object
+# if the same triangulation was to be used more than once to save duplicated
+# calculations.
+plt.figure()
+plt.gca().set_aspect('equal')
+plt.tripcolor(x, y, triangles, z, shading='faceted')
+plt.colorbar()
+plt.title('tripcolor of user-specified triangulation')
+plt.xlabel('Longitude (degrees)')
+plt.ylabel('Latitude (degrees)')
+
+plt.show()
Property changes on: trunk/matplotlib/examples/pylab_examples/tripcolor_demo.py
___________________________________________________________________
Added: svn:keywords
 + Id
Added: trunk/matplotlib/examples/pylab_examples/triplot_demo.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/triplot_demo.py	 (rev 0)
+++ trunk/matplotlib/examples/pylab_examples/triplot_demo.py	2010年05月13日 09:13:49 UTC (rev 8316)
@@ -0,0 +1,92 @@
+"""
+Creating and plotting unstructured triangular grids.
+"""
+import matplotlib.pyplot as plt
+import matplotlib.tri as tri
+import numpy as np
+import math
+
+# Creating a Triangulation without specifying the triangles results in the
+# Delaunay triangulation of the points.
+
+# First create the x and y coordinates of the points.
+n_angles = 36
+n_radii = 8
+min_radius = 0.25
+radii = np.linspace(min_radius, 0.95, n_radii)
+
+angles = np.linspace(0, 2*math.pi, n_angles, endpoint=False)
+angles = np.repeat(angles[...,np.newaxis], n_radii, axis=1)
+angles[:,1::2] += math.pi/n_angles
+
+x = (radii*np.cos(angles)).flatten()
+y = (radii*np.sin(angles)).flatten()
+
+# Create the Triangulation; no triangles so Delaunay triangulation created.
+triang = tri.Triangulation(x, y)
+
+# Mask off unwanted triangles.
+xmid = x[triang.triangles].mean(axis=1)
+ymid = y[triang.triangles].mean(axis=1)
+mask = np.where(xmid*xmid + ymid*ymid < min_radius*min_radius, 1, 0)
+triang.set_mask(mask)
+
+# Plot the triangulation.
+plt.figure()
+plt.gca().set_aspect('equal')
+plt.triplot(triang, 'bo-')
+plt.title('triplot of Delaunay triangulation')
+
+
+# You can specify your own triangulation rather than perform a Delaunay
+# triangulation of the points, where each triangle is given by the indices of
+# the three points that make up the triangle, ordered in either a clockwise or
+# anticlockwise manner.
+
+xy = np.asarray([
+ [-0.101,0.872],[-0.080,0.883],[-0.069,0.888],[-0.054,0.890],[-0.045,0.897],
+ [-0.057,0.895],[-0.073,0.900],[-0.087,0.898],[-0.090,0.904],[-0.069,0.907],
+ [-0.069,0.921],[-0.080,0.919],[-0.073,0.928],[-0.052,0.930],[-0.048,0.942],
+ [-0.062,0.949],[-0.054,0.958],[-0.069,0.954],[-0.087,0.952],[-0.087,0.959],
+ [-0.080,0.966],[-0.085,0.973],[-0.087,0.965],[-0.097,0.965],[-0.097,0.975],
+ [-0.092,0.984],[-0.101,0.980],[-0.108,0.980],[-0.104,0.987],[-0.102,0.993],
+ [-0.115,1.001],[-0.099,0.996],[-0.101,1.007],[-0.090,1.010],[-0.087,1.021],
+ [-0.069,1.021],[-0.052,1.022],[-0.052,1.017],[-0.069,1.010],[-0.064,1.005],
+ [-0.048,1.005],[-0.031,1.005],[-0.031,0.996],[-0.040,0.987],[-0.045,0.980],
+ [-0.052,0.975],[-0.040,0.973],[-0.026,0.968],[-0.020,0.954],[-0.006,0.947],
+ [ 0.003,0.935],[ 0.006,0.926],[ 0.005,0.921],[ 0.022,0.923],[ 0.033,0.912],
+ [ 0.029,0.905],[ 0.017,0.900],[ 0.012,0.895],[ 0.027,0.893],[ 0.019,0.886],
+ [ 0.001,0.883],[-0.012,0.884],[-0.029,0.883],[-0.038,0.879],[-0.057,0.881],
+ [-0.062,0.876],[-0.078,0.876],[-0.087,0.872],[-0.030,0.907],[-0.007,0.905],
+ [-0.057,0.916],[-0.025,0.933],[-0.077,0.990],[-0.059,0.993] ])
+x = xy[:,0]*180/3.14159
+y = xy[:,1]*180/3.14159
+
+triangles = np.asarray([
+ [67,66, 1],[65, 2,66],[ 1,66, 2],[64, 2,65],[63, 3,64],[60,59,57],
+ [ 2,64, 3],[ 3,63, 4],[ 0,67, 1],[62, 4,63],[57,59,56],[59,58,56],
+ [61,60,69],[57,69,60],[ 4,62,68],[ 6, 5, 9],[61,68,62],[69,68,61],
+ [ 9, 5,70],[ 6, 8, 7],[ 4,70, 5],[ 8, 6, 9],[56,69,57],[69,56,52],
+ [70,10, 9],[54,53,55],[56,55,53],[68,70, 4],[52,56,53],[11,10,12],
+ [69,71,68],[68,13,70],[10,70,13],[51,50,52],[13,68,71],[52,71,69],
+ [12,10,13],[71,52,50],[71,14,13],[50,49,71],[49,48,71],[14,16,15],
+ [14,71,48],[17,19,18],[17,20,19],[48,16,14],[48,47,16],[47,46,16],
+ [16,46,45],[23,22,24],[21,24,22],[17,16,45],[20,17,45],[21,25,24],
+ [27,26,28],[20,72,21],[25,21,72],[45,72,20],[25,28,26],[44,73,45],
+ [72,45,73],[28,25,29],[29,25,31],[43,73,44],[73,43,40],[72,73,39],
+ [72,31,25],[42,40,43],[31,30,29],[39,73,40],[42,41,40],[72,33,31],
+ [32,31,33],[39,38,72],[33,72,38],[33,38,34],[37,35,38],[34,38,35],
+ [35,37,36] ])
+
+# Rather than create a Triangulation object, can simply pass x, y and triangles
+# arrays to triplot directly. It would be better to use a Triangulation object
+# if the same triangulation was to be used more than once to save duplicated
+# calculations.
+plt.figure()
+plt.gca().set_aspect('equal')
+plt.triplot(x, y, triangles, 'go-')
+plt.title('triplot of user-specified triangulation')
+plt.xlabel('Longitude (degrees)')
+plt.ylabel('Latitude (degrees)')
+
+plt.show()
Property changes on: trunk/matplotlib/examples/pylab_examples/triplot_demo.py
___________________________________________________________________
Added: svn:keywords
 + Id
Modified: trunk/matplotlib/lib/matplotlib/axes.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/axes.py	2010年05月12日 17:58:17 UTC (rev 8315)
+++ trunk/matplotlib/lib/matplotlib/axes.py	2010年05月13日 09:13:49 UTC (rev 8316)
@@ -32,6 +32,7 @@
 import matplotlib.text as mtext
 import matplotlib.ticker as mticker
 import matplotlib.transforms as mtransforms
+import matplotlib.tri as mtri
 
 
 iterable = cbook.iterable
@@ -8021,7 +8022,23 @@
 self.xaxis.set_minor_locator(mticker.NullLocator())
 self.yaxis.set_minor_locator(mticker.NullLocator())
 
+ def tricontour(self, *args, **kwargs):
+ return mtri.tricontour(self, *args, **kwargs)
+ tricontour.__doc__ = mtri.TriContourSet.tricontour_doc
 
+ def tricontourf(self, *args, **kwargs):
+ return mtri.tricontourf(self, *args, **kwargs)
+ tricontourf.__doc__ = mtri.TriContourSet.tricontour_doc
+
+ def tripcolor(self, *args, **kwargs):
+ return mtri.tripcolor(self, *args, **kwargs)
+ tripcolor.__doc__ = mtri.tripcolor.__doc__
+
+ def triplot(self, *args, **kwargs):
+ mtri.triplot(self, *args, **kwargs)
+ triplot.__doc__ = mtri.triplot.__doc__
+
+
 class SubplotBase:
 """
 Base class for subplots, which are :class:`Axes` instances with
Modified: trunk/matplotlib/lib/matplotlib/pyplot.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/pyplot.py	2010年05月12日 17:58:17 UTC (rev 8315)
+++ trunk/matplotlib/lib/matplotlib/pyplot.py	2010年05月13日 09:13:49 UTC (rev 8316)
@@ -2427,6 +2427,78 @@
 
 # This function was autogenerated by boilerplate.py. Do not edit as
 # changes will be lost
+@autogen_docstring(Axes.tricontour)
+def tricontour(*args, **kwargs):
+ ax = gca()
+ # allow callers to override the hold state by passing hold=True|False
+ washold = ax.ishold()
+ hold = kwargs.pop('hold', None)
+ if hold is not None:
+ ax.hold(hold)
+ try:
+ ret = ax.tricontour(*args, **kwargs)
+ draw_if_interactive()
+ finally:
+ ax.hold(washold)
+ if ret._A is not None: sci(ret)
+ return ret
+
+# This function was autogenerated by boilerplate.py. Do not edit as
+# changes will be lost
+@autogen_docstring(Axes.tricontourf)
+def tricontourf(*args, **kwargs):
+ ax = gca()
+ # allow callers to override the hold state by passing hold=True|False
+ washold = ax.ishold()
+ hold = kwargs.pop('hold', None)
+ if hold is not None:
+ ax.hold(hold)
+ try:
+ ret = ax.tricontourf(*args, **kwargs)
+ draw_if_interactive()
+ finally:
+ ax.hold(washold)
+ if ret._A is not None: sci(ret)
+ return ret
+
+# This function was autogenerated by boilerplate.py. Do not edit as
+# changes will be lost
+@autogen_docstring(Axes.tripcolor)
+def tripcolor(*args, **kwargs):
+ ax = gca()
+ # allow callers to override the hold state by passing hold=True|False
+ washold = ax.ishold()
+ hold = kwargs.pop('hold', None)
+ if hold is not None:
+ ax.hold(hold)
+ try:
+ ret = ax.tripcolor(*args, **kwargs)
+ draw_if_interactive()
+ finally:
+ ax.hold(washold)
+ sci(ret)
+ return ret
+
+# This function was autogenerated by boilerplate.py. Do not edit as
+# changes will be lost
+@autogen_docstring(Axes.triplot)
+def triplot(*args, **kwargs):
+ ax = gca()
+ # allow callers to override the hold state by passing hold=True|False
+ washold = ax.ishold()
+ hold = kwargs.pop('hold', None)
+ if hold is not None:
+ ax.hold(hold)
+ try:
+ ret = ax.triplot(*args, **kwargs)
+ draw_if_interactive()
+ finally:
+ ax.hold(washold)
+
+ return ret
+
+# This function was autogenerated by boilerplate.py. Do not edit as
+# changes will be lost
 @autogen_docstring(Axes.vlines)
 def vlines(x, ymin, ymax, colors='k', linestyles='solid', label='', hold=None, **kwargs):
 ax = gca()
Added: trunk/matplotlib/lib/matplotlib/tri/__init__.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/tri/__init__.py	 (rev 0)
+++ trunk/matplotlib/lib/matplotlib/tri/__init__.py	2010年05月13日 09:13:49 UTC (rev 8316)
@@ -0,0 +1,8 @@
+"""
+Unstructured triangular grid functions.
+"""
+
+from triangulation import *
+from tricontour import *
+from tripcolor import *
+from triplot import *
Property changes on: trunk/matplotlib/lib/matplotlib/tri/__init__.py
___________________________________________________________________
Added: svn:keywords
 + Id
Added: trunk/matplotlib/lib/matplotlib/tri/_tri.cpp
===================================================================
--- trunk/matplotlib/lib/matplotlib/tri/_tri.cpp	 (rev 0)
+++ trunk/matplotlib/lib/matplotlib/tri/_tri.cpp	2010年05月13日 09:13:49 UTC (rev 8316)
@@ -0,0 +1,1112 @@
+#include "_tri.h"
+#include "src/mplutils.h"
+
+#include <algorithm>
+#include <iostream>
+#include <set>
+
+#define MOVETO 1
+#define LINETO 2
+
+
+
+TriEdge::TriEdge()
+ : tri(-1), edge(-1)
+{}
+
+TriEdge::TriEdge(int tri_, int edge_)
+ : tri(tri_), edge(edge_)
+{}
+
+bool TriEdge::operator<(const TriEdge& other) const
+{
+ if (tri != other.tri)
+ return tri < other.tri;
+ else
+ return edge < other.edge;
+}
+
+bool TriEdge::operator==(const TriEdge& other) const
+{
+ return tri == other.tri && edge == other.edge;
+}
+
+bool TriEdge::operator!=(const TriEdge& other) const
+{
+ return !operator==(other);
+}
+
+std::ostream& operator<<(std::ostream& os, const TriEdge& tri_edge)
+{
+ return os << tri_edge.tri << ' ' << tri_edge.edge;
+}
+
+
+
+XY::XY()
+{}
+
+XY::XY(const double& x_, const double& y_)
+ : x(x_), y(y_)
+{}
+
+double XY::angle() const
+{
+ return atan2(y, x);
+}
+
+double XY::cross_z(const XY& other) const
+{
+ return x*other.y - y*other.x;
+}
+
+bool XY::operator==(const XY& other) const
+{
+ return x == other.x && y == other.y;
+}
+
+bool XY::operator!=(const XY& other) const
+{
+ return x != other.x || y != other.y;
+}
+
+bool XY::operator<(const XY& other) const
+{
+ if (y == other.y)
+ return x < other.x;
+ else
+ return y < other.y;
+}
+
+XY XY::operator*(const double& multiplier) const
+{
+ return XY(x*multiplier, y*multiplier);
+}
+
+XY XY::operator+(const XY& other) const
+{
+ return XY(x + other.x, y + other.y);
+}
+
+XY XY::operator-(const XY& other) const
+{
+ return XY(x - other.x, y - other.y);
+}
+
+std::ostream& operator<<(std::ostream& os, const XY& xy)
+{
+ return os << '(' << xy.x << ' ' << xy.y << ')';
+}
+
+
+
+BoundingBox::BoundingBox()
+ : empty(true)
+{}
+
+void BoundingBox::add(const XY& point)
+{
+ if (empty) {
+ empty = false;
+ lower = upper = point;
+ } else {
+ if (point.x < lower.x) lower.x = point.x;
+ else if (point.x > upper.x) upper.x = point.x;
+
+ if (point.y < lower.y) lower.y = point.y;
+ else if (point.y > upper.y) upper.y = point.y;
+ }
+}
+
+bool BoundingBox::contains_x(const double& x) const
+{
+ return !empty && x >= lower.x && x <= upper.x;
+}
+
+std::ostream& operator<<(std::ostream& os, const BoundingBox& box)
+{
+ if (box.empty)
+ return os << "<empty>";
+ else
+ return os << box.lower << " -> " << box.upper;
+}
+
+
+
+ContourLine::ContourLine()
+ : std::vector<XY>()
+{}
+
+void ContourLine::insert_unique(iterator pos, const XY& point)
+{
+ if (empty() || pos == end() || point != *pos)
+ std::vector<XY>::insert(pos, point);
+}
+
+void ContourLine::push_back(const XY& point)
+{
+ if (empty() || point != back())
+ std::vector<XY>::push_back(point);
+}
+
+void ContourLine::write() const
+{
+ std::cout << "ContourLine of " << size() << " points:";
+ for (const_iterator it = begin(); it != end(); ++it)
+ std::cout << ' ' << *it;
+ std::cout << std::endl;
+}
+
+
+
+void write_contour(const Contour& contour)
+{
+ std::cout << "Contour of " << contour.size() << " lines." << std::endl;
+ for (Contour::const_iterator it = contour.begin(); it != contour.end(); ++it)
+ it->write();
+}
+
+
+
+
+Triangulation::Triangulation(PyArrayObject* x,
+ PyArrayObject* y,
+ PyArrayObject* triangles,
+ PyArrayObject* mask,
+ PyArrayObject* edges,
+ PyArrayObject* neighbors)
+ : _npoints(PyArray_DIM(x,0)),
+ _ntri(PyArray_DIM(triangles,0)),
+ _x(x),
+ _y(y),
+ _triangles(triangles),
+ _mask(mask),
+ _edges(edges),
+ _neighbors(neighbors)
+{
+ _VERBOSE("Triangulation::Triangulation");
+ correct_triangles();
+}
+
+Triangulation::~Triangulation()
+{
+ _VERBOSE("Triangulation::~Triangulation");
+ Py_XDECREF(_x);
+ Py_XDECREF(_y);
+ Py_XDECREF(_triangles);
+ Py_XDECREF(_mask);
+ Py_XDECREF(_edges);
+ Py_XDECREF(_neighbors);
+}
+
+void Triangulation::calculate_boundaries()
+{
+ _VERBOSE("Triangulation::calculate_boundaries");
+
+ get_neighbors(); // Ensure _neighbors has been created.
+
+ // Create set of all boundary TriEdges, which are those which do not
+ // have a neighbor triangle.
+ typedef std::set<TriEdge> BoundaryEdges;
+ BoundaryEdges boundary_edges;
+ for (int tri = 0; tri < _ntri; ++tri) {
+ if (!is_masked(tri)) {
+ for (int edge = 0; edge < 3; ++edge) {
+ if (get_neighbor(tri, edge) == -1) {
+ boundary_edges.insert(TriEdge(tri, edge));
+ }
+ }
+ }
+ }
+
+ // Take any boundary edge and follow the boundary until return to start
+ // point, removing edges from boundary_edges as they are used. At the same
+ // time, initialise the _tri_edge_to_boundary_map.
+ while (!boundary_edges.empty()) {
+ // Start of new boundary.
+ BoundaryEdges::iterator it = boundary_edges.begin();
+ int tri = it->tri;
+ int edge = it->edge;
+ _boundaries.push_back(Boundary());
+ Boundary& boundary = _boundaries.back();
+
+ while (true) {
+ boundary.push_back(TriEdge(tri, edge));
+ boundary_edges.erase(it);
+ _tri_edge_to_boundary_map[TriEdge(tri, edge)] =
+ BoundaryEdge(_boundaries.size()-1, boundary.size()-1);
+
+ // Move to next edge of current triangle.
+ edge = (edge+1) % 3;
+
+ // Find start point index of boundary edge.
+ int point = get_triangle_point(tri, edge);
+
+ // Find next TriEdge by traversing neighbors until find one
+ // without a neighbor.
+ while (get_neighbor(tri, edge) != -1) {
+ tri = get_neighbor(tri, edge);
+ edge = get_edge_in_triangle(tri, point);
+ }
+
+ if (TriEdge(tri,edge) == boundary.front())
+ break; // Reached beginning of this boundary, so finished it.
+ else
+ it = boundary_edges.find(TriEdge(tri, edge));
+ }
+ }
+}
+
+void Triangulation::calculate_edges()
+{
+ _VERBOSE("Triangulation::calculate_edges");
+ Py_XDECREF(_edges);
+
+ // Create set of all edges, storing them with start point index less than
+ // end point index.
+ typedef std::set<Edge> EdgeSet;
+ EdgeSet edge_set;
+ for (int tri = 0; tri < _ntri; ++tri) {
+ if (!is_masked(tri)) {
+ for (int edge = 0; edge < 3; edge++) {
+ int start = get_triangle_point(tri, edge);
+ int end = get_triangle_point(tri, (edge+1)%3);
+ edge_set.insert(start > end ? Edge(start,end) : Edge(end,start));
+ }
+ }
+ }
+
+ // Convert to python _edges array.
+ npy_intp dims[2] = {edge_set.size(), 2};
+ _edges = (PyArrayObject*)PyArray_SimpleNew(2, dims, PyArray_INT);
+ int* edges_ptr = (int*)PyArray_DATA(_edges);
+ for (EdgeSet::const_iterator it = edge_set.begin(); it != edge_set.end(); ++it) {
+ *edges_ptr++ = it->start;
+ *edges_ptr++ = it->end;
+ }
+}
+
+void Triangulation::calculate_neighbors()
+{
+ _VERBOSE("Triangulation::calculate_neighbors");
+ Py_XDECREF(_neighbors);
+
+ // Create _neighbors array with shape (ntri,3) and initialise all to -1.
+ npy_intp dims[2] = {_ntri,3};
+ _neighbors = (PyArrayObject*)PyArray_SimpleNew(2, dims, PyArray_INT);
+ int* neighbors_ptr = (int*)PyArray_DATA(_neighbors);
+ std::fill(neighbors_ptr, neighbors_ptr + 3*_ntri, -1);
+
+ // For each triangle edge (start to end point), find corresponding neighbor
+ // edge from end to start point. Do this by traversing all edges and
+ // storing them in a map from edge to TriEdge. If corresponding neighbor
+ // edge is already in the map, don't need to store new edge as neighbor
+ // already found.
+ typedef std::map<Edge, TriEdge> EdgeToTriEdgeMap;
+ EdgeToTriEdgeMap edge_to_tri_edge_map;
+ for (int tri = 0; tri < _ntri; ++tri) {
+ if (!is_masked(tri)) {
+ for (int edge = 0; edge < 3; ++edge) {
+ int start = get_triangle_point(tri, edge);
+ int end = get_triangle_point(tri, (edge+1)%3);
+ EdgeToTriEdgeMap::iterator it =
+ edge_to_tri_edge_map.find(Edge(end,start));
+ if (it == edge_to_tri_edge_map.end()) {
+ // No neighbor edge exists in the edge_to_tri_edge_map, so
+ // add this edge to it.
+ edge_to_tri_edge_map[Edge(start,end)] = TriEdge(tri,edge);
+ } else {
+ // Neighbor edge found, set the two elements of _neighbors
+ // and remove edge from edge_to_tri_edge_map.
+ neighbors_ptr[3*tri + edge] = it->second.tri;
+ neighbors_ptr[3*it->second.tri + it->second.edge] = tri;
+ edge_to_tri_edge_map.erase(it);
+ }
+ }
+ }
+ }
+
+ // Note that remaining edges in the edge_to_tri_edge_map correspond to
+ // boundary edges, but the boundaries are calculated separately elsewhere.
+}
+
+void Triangulation::correct_triangles()
+{
+ int* triangles_ptr = (int*)PyArray_DATA(_triangles);
+ int* neighbors_ptr = _neighbors != 0 ? (int*)PyArray_DATA(_neighbors) : 0;
+ for (int tri = 0; tri < _ntri; ++tri) {
+ XY point0 = get_point_coords(*triangles_ptr++);
+ XY point1 = get_point_coords(*triangles_ptr++);
+ XY point2 = get_point_coords(*triangles_ptr++);
+ if ( (point1 - point0).cross_z(point2 - point0) < 0.0) {
+ // Triangle points are clockwise, so change them to anticlockwise.
+ std::swap(*(triangles_ptr-2), *(triangles_ptr-1));
+ if (neighbors_ptr)
+ std::swap(*(neighbors_ptr+3*tri+1), *(neighbors_ptr+3*tri+2));
+ }
+ }
+}
+
+const Triangulation::Boundaries& Triangulation::get_boundaries() const
+{
+ _VERBOSE("Triangulation::get_boundaries");
+ if (_boundaries.empty())
+ const_cast<Triangulation*>(this)->calculate_boundaries();
+ return _boundaries;
+}
+
+void Triangulation::get_boundary_edge(const TriEdge& triEdge,
+ int& boundary,
+ int& edge) const
+{
+ get_boundaries(); // Ensure _tri_edge_to_boundary_map has been created.
+ TriEdgeToBoundaryMap::const_iterator it =
+ _tri_edge_to_boundary_map.find(triEdge);
+ assert(it != _tri_edge_to_boundary_map.end() &&
+ "TriEdge is not on a boundary");
+ boundary = it->second.boundary;
+ edge = it->second.edge;
+}
+
+int Triangulation::get_edge_in_triangle(int tri, int point) const
+{
+ assert(tri >= 0 && tri < _ntri && "Triangle index out of bounds");
+ assert(point >= 0 && point < _npoints && "Point index out of bounds.");
+ const int* triangles_ptr = get_triangles_ptr() + 3*tri;
+ for (int edge = 0; edge < 3; ++edge) {
+ if (*triangles_ptr++ == point) return edge;
+ }
+ return -1; // point is not in triangle.
+}
+
+Py::Object Triangulation::get_edges()
+{
+ _VERBOSE("Triangulation::get_edges");
+ if (_edges == 0)
+ calculate_edges();
+ return Py::asObject(Py::new_reference_to((PyObject*)_edges));
+}
+
+int Triangulation::get_neighbor(int tri, int edge) const
+{
+ assert(tri >= 0 && tri < _ntri && "Triangle index out of bounds");
+ assert(edge >= 0 && edge < 3 && "Edge index out of bounds");
+ return get_neighbors_ptr()[3*tri + edge];
+}
+
+TriEdge Triangulation::get_neighbor_edge(int tri, int edge) const
+{
+ int neighbor_tri = get_neighbor(tri, edge);
+ if (neighbor_tri == -1)
+ return TriEdge(-1,-1);
+ else
+ return TriEdge(neighbor_tri,
+ get_edge_in_triangle(neighbor_tri,
+ get_triangle_point(tri,
+ (edge+1)%3)));
+}
+
+Py::Object Triangulation::get_neighbors()
+{
+ _VERBOSE("Triangulation::get_neighbors");
+ if (_neighbors == 0) calculate_neighbors();
+ return Py::asObject(Py::new_reference_to((PyObject*)_neighbors));
+}
+
+const int* Triangulation::get_neighbors_ptr() const
+{
+ if (_neighbors == 0)
+ const_cast<Triangulation*>(this)->calculate_neighbors();
+ return (const int*)PyArray_DATA(_neighbors);
+}
+
+int Triangulation::get_npoints() const
+{
+ return _npoints;
+}
+
+int Triangulation::get_ntri() const
+{
+ return _ntri;
+}
+
+XY Triangulation::get_point_coords(int point) const
+{
+ assert(point >= 0 && point < _npoints && "Point index out of bounds.");
+ return XY( ((const double*)PyArray_DATA(_x))[point],
+ ((const double*)PyArray_DATA(_y))[point] );
+}
+
+int Triangulation::get_triangle_point(int tri, int edge) const
+{
+ assert(tri >= 0 && tri < _ntri && "Triangle index out of bounds");
+ assert(edge >= 0 && edge < 3 && "Edge index out of bounds");
+ return get_triangles_ptr()[3*tri + edge];
+}
+
+int Triangulation::get_triangle_point(const TriEdge& tri_edge) const
+{
+ return get_triangle_point(tri_edge.tri, tri_edge.edge);
+}
+
+const int* Triangulation::get_triangles_ptr() const
+{
+ return (const int*)PyArray_DATA(_triangles);
+}
+
+void Triangulation::init_type()
+{
+ _VERBOSE("Triangulation::init_type");
+
+ behaviors().name("Triangulation");
+ behaviors().doc("Triangulation");
+
+ add_noargs_method("get_edges", &Triangulation::get_edges,
+ "get_edges()");
+ add_noargs_method("get_neighbors", &Triangulation::get_neighbors,
+ "get_neighbors()");
+ add_varargs_method("set_mask", &Triangulation::set_mask,
+ "set_mask(mask)");
+}
+
+bool Triangulation::is_masked(int tri) const
+{
+ assert(tri >= 0 && tri < _ntri && "Triangle index out of bounds.");
+ return _mask && *((bool*)PyArray_DATA(_mask) + tri);
+}
+
+Py::Object Triangulation::set_mask(const Py::Tuple &args)
+{
+ _VERBOSE("Triangulation::set_mask");
+ args.verify_length(1);
+
+ Py_XDECREF(_mask);
+ _mask = 0;
+ if (args[0] != Py::None())
+ {
+ _mask = (PyArrayObject*)PyArray_ContiguousFromObject(
+ args[0].ptr(), PyArray_BOOL, 1, 1);
+ if (_mask == 0 || PyArray_DIM(_mask,0) != PyArray_DIM(_triangles,0)) {
+ Py_XDECREF(_mask);
+ throw Py::ValueError(
+ "mask must be a 1D array with the same length as the triangles array");
+ }
+ }
+
+ // Clear derived fields so they are recalculated when needed.
+ Py_XDECREF(_edges);
+ _edges = 0;
+ Py_XDECREF(_neighbors);
+ _neighbors = 0;
+ _boundaries.clear();
+
+ return Py::None();
+}
+
+void Triangulation::write_boundaries() const
+{
+ const Boundaries& bs = get_boundaries();
+ std::cout << "Number of boundaries: " << bs.size() << std::endl;
+ for (Boundaries::const_iterator it = bs.begin(); it != bs.end(); ++it) {
+ const Boundary& b = *it;
+ std::cout << " Boundary of " << b.size() << " points: ";
+ for (Boundary::const_iterator itb = b.begin(); itb != b.end(); ++itb) {
+ std::cout << *itb << ", ";
+ }
+ std::cout << std::endl;
+ }
+}
+
+
+
+
+TriContourGenerator::TriContourGenerator(Py::Object triangulation,
+ PyArrayObject* z)
+ : _triangulation(triangulation),
+ _z(z),
+ _interior_visited(2*get_triangulation().get_ntri()),
+ _boundaries_visited(0),
+ _boundaries_used(0)
+{
+ _VERBOSE("TriContourGenerator::TriContourGenerator");
+}
+
+TriContourGenerator::~TriContourGenerator()
+{
+ _VERBOSE("TriContourGenerator::~TriContourGenerator");
+ Py_XDECREF(_z);
+}
+
+void TriContourGenerator::clear_visited_flags(bool include_boundaries)
+{
+ // Clear _interiorVisited.
+ std::fill(_interior_visited.begin(), _interior_visited.end(), false);
+
+ if (include_boundaries) {
+ if (_boundaries_visited.empty()) {
+ const Boundaries& boundaries = get_boundaries();
+
+ // Initialise _boundaries_visited.
+ _boundaries_visited.reserve(boundaries.size());
+ for (Boundaries::const_iterator it = boundaries.begin();
+ it != boundaries.end(); ++it)
+ _boundaries_visited.push_back(BoundaryVisited(it->size()));
+
+ // Initialise _boundaries_used.
+ _boundaries_used = BoundariesUsed(boundaries.size());
+ }
+
+ // Clear _boundaries_visited.
+ for (BoundariesVisited::iterator it = _boundaries_visited.begin();
+ it != _boundaries_visited.end(); ++it)
+ fill(it->begin(), it->end(), false);
+
+ // Clear _boundaries_used.
+ fill(_boundaries_used.begin(), _boundaries_used.end(), false);
+ }
+}
+
+Py::Object TriContourGenerator::contour_to_segs(const Contour& contour)
+{
+ Py::List segs(contour.size());
+ for (Contour::size_type i = 0; i < contour.size(); ++i) {
+ const ContourLine& line = contour[i];
+ npy_intp dims[2] = {line.size(),2};
+ PyArrayObject* py_line = (PyArrayObject*)PyArray_SimpleNew(
+ 2, dims, PyArray_DOUBLE);
+ double* p = (double*)PyArray_DATA(py_line);
+ for (ContourLine::const_iterator it = line.begin(); it != line.end(); ++it) {
+ *p++ = it->x;
+ *p++ = it->y;
+ }
+ segs[i] = Py::asObject((PyObject*)py_line);
+ }
+ return segs;
+}
+
+Py::Object TriContourGenerator::contour_to_segs_and_kinds(const Contour& contour)
+{
+ Contour::const_iterator line;
+ ContourLine::const_iterator point;
+
+ // Find total number of points in all contour lines.
+ int n_points = 0;
+ for (line = contour.begin(); line != contour.end(); ++line)
+ n_points += line->size();
+
+ // Create segs array for point coordinates.
+ npy_intp segs_dims[2] = {n_points, 2};
+ PyArrayObject* segs = (PyArrayObject*)PyArray_SimpleNew(
+ 2, segs_dims, PyArray_DOUBLE);
+ double* segs_ptr = (double*)PyArray_DATA(segs);
+
+ // Create kinds array for code types.
+ npy_intp kinds_dims[1] = {n_points};
+ PyArrayObject* kinds = (PyArrayObject*)PyArray_SimpleNew(
+ 1, kinds_dims, PyArray_UBYTE);
+ unsigned char* kinds_ptr = (unsigned char*)PyArray_DATA(kinds);
+
+ for (line = contour.begin(); line != contour.end(); ++line) {
+ for (point = line->begin(); point != line->end(); point++) {
+ *segs_ptr++ = point->x;
+ *segs_ptr++ = point->y;
+ *kinds_ptr++ = (point == line->begin() ? MOVETO : LINETO);
+ }
+ }
+
+ Py::Tuple result(2);
+ result[0] = Py::asObject((PyObject*)segs);
+ result[1] = Py::asObject((PyObject*)kinds);
+ return result;
+}
+
+Py::Object TriContourGenerator::create_contour(const Py::Tuple &args)
+{
+ _VERBOSE("TriContourGenerator::create_contour");
+ args.verify_length(1);
+
+ double level = (Py::Float)args[0];
+
+ clear_visited_flags(false);
+ Contour contour;
+
+ find_boundary_lines(contour, level);
+ find_interior_lines(contour, level, false, false);
+
+ return contour_to_segs(contour);
+}
+
+Py::Object TriContourGenerator::create_filled_contour(const Py::Tuple &args)
+{
+ _VERBOSE("TriContourGenerator::create_filled_contour");
+ args.verify_length(2);
+
+ double lower_level = (Py::Float)args[0];
+ double upper_level = (Py::Float)args[1];
+
+ clear_visited_flags(true);
+ Contour contour;
+
+ find_boundary_lines_filled(contour, lower_level, upper_level);
+ find_interior_lines(contour, lower_level, false, true);
+ find_interior_lines(contour, upper_level, true, true);
+
+ return contour_to_segs_and_kinds(contour);
+}
+
+XY TriContourGenerator::edge_interp(int tri, int edge, const double& level)
+{
+ return interp(get_triangulation().get_triangle_point(tri, edge),
+ get_triangulation().get_triangle_point(tri, (edge+1)%3),
+ level);
+}
+
+void TriContourGenerator::find_boundary_lines(Contour& contour,
+ const double& level)
+{
+ // Traverse boundaries to find starting points for all contour lines that
+ // intersect the boundaries. For each starting point found, follow the
+ // line to its end before continuing.
+ const Triangulation& triang = get_triangulation();
+ const Boundaries& boundaries = get_boundaries();
+ for (Boundaries::const_iterator it = boundaries.begin();
+ it != boundaries.end(); ++it) {
+ const Boundary& boundary = *it;
+ bool startAbove, endAbove = false;
+ for (Boundary::const_iterator itb = boundary.begin();
+ itb != boundary.end(); ++itb) {
+ if (itb == boundary.begin())
+ startAbove = get_z(triang.get_triangle_point(*itb)) >= level;
+ else
+ startAbove = endAbove;
+ endAbove = get_z(triang.get_triangle_point(itb->tri,
+ (itb->edge+1)%3)) >= level;
+ if (startAbove && !endAbove) {
+ // This boundary edge is the start point for a contour line,
+ // so follow the line.
+ contour.push_back(ContourLine());
+ ContourLine& contour_line = contour.back();
+ TriEdge tri_edge = *itb;
+ follow_interior(contour_line, tri_edge, true, level, false);
+ }
+ }
+ }
+}
+
+void TriContourGenerator::find_boundary_lines_filled(Contour& contour,
+ const double& lower_level,
+ const double& upper_level)
+{
+ // Traverse boundaries to find starting points for all contour lines that
+ // intersect the boundaries. For each starting point found, follow the
+ // line to its end before continuing.
+ const Triangulation& triang = get_triangulation();
+ const Boundaries& boundaries = get_boundaries();
+ for (Boundaries::size_type i = 0; i < boundaries.size(); ++i) {
+ const Boundary& boundary = boundaries[i];
+ for (Boundary::size_type j = 0; j < boundary.size(); ++j) {
+ if (!_boundaries_visited[i][j]) {
+ // z values of start and end of this boundary edge.
+ double z_start = get_z(triang.get_triangle_point(boundary[j]));
+ double z_end = get_z(triang.get_triangle_point(
+ boundary[j].tri, (boundary[j].edge+1)%3));
+
+ // Does this boundary edge's z increase through upper level
+ // and/or decrease through lower level?
+ bool incr_upper = (z_start < upper_level && z_end >= upper_level);
+ bool decr_lower = (z_start >= lower_level && z_end < lower_level);
+
+ if (decr_lower || incr_upper) {
+ // Start point for contour line, so follow it.
+ contour.push_back(ContourLine());
+ ContourLine& contour_line = contour.back();
+ TriEdge start_tri_edge = boundary[j];
+ TriEdge tri_edge = start_tri_edge;
+
+ // Traverse interior and boundaries until return to start.
+ bool on_upper = incr_upper;
+ do {
+ follow_interior(contour_line, tri_edge, true,
+ on_upper ? upper_level : lower_level, on_upper);
+ on_upper = follow_boundary(contour_line, tri_edge,
+ lower_level, upper_level, on_upper);
+ } while (tri_edge != start_tri_edge);
+
+ // Filled contour lines must not have same first and last
+ // points.
+ if (contour_line.size() > 1 &&
+ contour_line.front() == contour_line.back())
+ contour_line.pop_back();
+ }
+ }
+ }
+ }
+
+ // Add full boundaries that lie between the lower and upper levels. These
+ // are boundaries that have not been touched by an internal contour line
+ // which are stored in _boundaries_used.
+ for (Boundaries::size_type i = 0; i < boundaries.size(); ++i) {
+ if (!_boundaries_used[i]) {
+ const Boundary& boundary = boundaries[i];
+ double z = get_z(triang.get_triangle_point(boundary[0]));
+ if (z >= lower_level && z < upper_level) {
+ contour.push_back(ContourLine());
+ ContourLine& contour_line = contour.back();
+ for (Boundary::size_type j = 0; j < boundary.size(); ++j)
+ contour_line.push_back(triang.get_point_coords(
+ triang.get_triangle_point(boundary[j])));
+ }
+ }
+ }
+}
+
+void TriContourGenerator::find_interior_lines(Contour& contour,
+ const double& level,
+ bool on_upper,
+ bool filled)
+{
+ const Triangulation& triang = get_triangulation();
+ int ntri = triang.get_ntri();
+ for (int tri = 0; tri < ntri; ++tri) {
+ int visited_index = (on_upper ? tri+ntri : tri);
+
+ if (_interior_visited[visited_index] || triang.is_masked(tri))
+ continue; // Triangle has already been visited or is masked.
+
+ _interior_visited[visited_index] = true;
+
+ // Determine edge via which to leave this triangle.
+ int edge = get_exit_edge(tri, level, on_upper);
+ assert(edge >= -1 && edge < 3 && "Invalid exit edge");
+ if (edge == -1)
+ continue; // Contour does not pass through this triangle.
+
+ // Found start of new contour line loop.
+ contour.push_back(ContourLine());
+ ContourLine& contour_line = contour.back();
+ TriEdge tri_edge = triang.get_neighbor_edge(tri, edge);
+ follow_interior(contour_line, tri_edge, false, level, on_upper);
+
+ if (!filled)
+ // Non-filled contour lines must be closed.
+ contour_line.push_back(contour_line.front());
+ else if (contour_line.size() > 1 &&
+ contour_line.front() == contour_line.back())
+ // Filled contour lines must not have same first and last points.
+ contour_line.pop_back();
+ }
+}
+
+bool TriContourGenerator::follow_boundary(ContourLine& contour_line,
+ TriEdge& tri_edge,
+ const double& lower_level,
+ const double& upper_level,
+ bool on_upper)
+{
+ const Triangulation& triang = get_triangulation();
+ const Boundaries& boundaries = get_boundaries();
+
+ // Have TriEdge to start at, need equivalent boundary edge.
+ int boundary, edge;
+ triang.get_boundary_edge(tri_edge, boundary, edge);
+ _boundaries_used[boundary] = true;
+
+ bool stop = false;
+ bool first_edge = true;
+ double z_start, z_end = 0;
+ while (!stop)
+ {
+ assert(!_boundaries_visited[boundary][edge] && "Boundary already visited");
+ _boundaries_visited[boundary][edge] = true;
+
+ // z values of start and end points of boundary edge.
+ if (first_edge)
+ z_start = get_z(triang.get_triangle_point(tri_edge));
+ else
+ z_start = z_end;
+ z_end = get_z(triang.get_triangle_point(tri_edge.tri,
+ (tri_edge.edge+1)%3));
+
+ if (z_end > z_start) { // z increasing.
+ if (!(!on_upper && first_edge) &&
+ z_end >= lower_level && z_start < lower_level) {
+ stop = true;
+ on_upper = false;
+ } else if (z_end >= upper_level && z_start < upper_level) {
+ stop = true;
+ on_upper = true;
+ }
+ } else { // z decreasing.
+ if (!(on_upper && first_edge) &&
+ z_start >= upper_level && z_end < upper_level) {
+ stop = true;
+ on_upper = true;
+ } else if (z_start >= lower_level && z_end < lower_level) {
+ stop = true;
+ on_upper = false;
+ }
+ }
+
+ first_edge = false;
+
+ if (!stop) {
+ // Move to next boundary edge, adding point to contour line.
+ edge = (edge+1) % (int)boundaries[boundary].size();
+ tri_edge = boundaries[boundary][edge];
+ contour_line.push_back(triang.get_point_coords(
+ triang.get_triangle_point(tri_edge)));
+ }
+ }
+
+ return on_upper;
+}
+
+void TriContourGenerator::follow_interior(ContourLine& contour_line,
+ TriEdge& tri_edge,
+ bool end_on_boundary,
+ const double& level,
+ bool on_upper)
+{
+ int& tri = tri_edge.tri;
+ int& edge = tri_edge.edge;
+
+ // Initial point.
+ contour_line.push_back(edge_interp(tri, edge, level));
+
+ while (true) {
+ int visited_index = tri;
+ if (on_upper)
+ visited_index += get_triangulation().get_ntri();
+
+ // Check for end not on boundary.
+ if (!end_on_boundary && _interior_visited[visited_index])
+ break; // Reached start point, so return.
+
+ // Determine edge by which to leave this triangle.
+ edge = get_exit_edge(tri, level, on_upper);
+ assert(edge >= 0 && edge < 3 && "Invalid exit edge");
+
+ _interior_visited[visited_index] = true;
+
+ // Append new point to point set.
+ assert(edge >= 0 && edge < 3 && "Invalid triangle edge");
+ contour_line.push_back(edge_interp(tri, edge, level));
+
+ // Move to next triangle.
+ TriEdge next_tri_edge = get_triangulation().get_neighbor_edge(tri,edge);
+
+ // Check if ending on a boundary.
+ if (end_on_boundary && next_tri_edge.tri == -1)
+ break;
+
+ tri_edge = next_tri_edge;
+ assert(tri_edge.tri != -1 && "Invalid triangle for internal loop");
+ }
+}
+
+const TriContourGenerator::Boundaries& TriContourGenerator::get_boundaries() const
+{
+ return get_triangulation().get_boundaries();
+}
+
+int TriContourGenerator::get_exit_edge(int tri,
+ const double& level,
+ bool on_upper) const
+{
+ assert(tri >= 0 && tri < get_triangulation().get_ntri() &&
+ "Triangle index out of bounds.");
+
+ unsigned int config =
+ (get_z(get_triangulation().get_triangle_point(tri, 0)) >= level) |
+ (get_z(get_triangulation().get_triangle_point(tri, 1)) >= level) << 1 |
+ (get_z(get_triangulation().get_triangle_point(tri, 2)) >= level) << 2;
+
+ if (on_upper) config = 7-config;
+
+ switch (config) {
+ case 0: return -1;
+ case 1: return 2;
+ case 2: return 0;
+ case 3: return 2;
+ case 4: return 1;
+ case 5: return 1;
+ case 6: return 0;
+ case 7: return -1;
+ default: assert(0 && "Invalid config value"); return -1;
+ }
+}
+
+const Triangulation& TriContourGenerator::get_triangulation() const
+{
+ return *(Triangulation*)_triangulation.ptr();
+}
+
+const double& TriContourGenerator::get_z(int point) const
+{
+ assert(point >= 0 && point < get_triangulation().get_npoints() &&
+ "Point index out of bounds.");
+ return ((const double*)PyArray_DATA(_z))[point];
+}
+
+void TriContourGenerator::init_type()
+{
+ _VERBOSE("TriContourGenerator::init_type");
+
+ behaviors().name("TriContourGenerator");
+ behaviors().doc("TriContourGenerator");
+
+ add_varargs_method("create_contour",
+ &TriContourGenerator::create_contour,
+ "create_contour(level)");
+ add_varargs_method("create_filled_contour",
+ &TriContourGenerator::create_filled_contour,
+ "create_filled_contour(lower_level, upper_level)");
+}
+
+XY TriContourGenerator::interp(int point1,
+ int point2,
+ const double& level) const
+{
+ assert(point1 >= 0 && point1 < get_triangulation().get_npoints() &&
+ "Point index 1 out of bounds.");
+ assert(point2 >= 0 && point2 < get_triangulation().get_npoints() &&
+ "Point index 2 out of bounds.");
+ assert(point1 != point2 && "Identical points");
+ double fraction = (get_z(point2) - level) / (get_z(point2) - get_z(point1));
+ return get_triangulation().get_point_coords(point1)*fraction +
+ get_triangulation().get_point_coords(point2)*(1.0 - fraction);
+}
+
+
+
+
+
+#if defined(_MSC_VER)
+DL_EXPORT(void)
+#elif defined(__cplusplus)
+extern "C" void
+#else
+void
+#endif
+init_tri()
+{
+ static TriModule* triModule = new TriModule;
+ import_array();
+}
+
+TriModule::TriModule()
+ : Py::ExtensionModule<TriModule>("tri")
+{
+ Triangulation::init_type();
+ TriContourGenerator::init_type();
+
+ add_varargs_method("Triangulation", &TriModule::new_triangulation,
+ "Create and return new C++ Triangulation object");
+ add_varargs_method("TriContourGenerator", &TriModule::new_tricontourgenerator,
+ "Create and return new C++ TriContourGenerator object");
+
+ initialize("Module for unstructured triangular grids");
+}
+
+Py::Object TriModule::new_triangulation(const Py::Tuple &args)
+{
+ _VERBOSE("TriModule::new_triangulation");
+ args.verify_length(6);
+
+ // x and y.
+ PyArrayObject* x = (PyArrayObject*)PyArray_ContiguousFromObject(
+ args[0].ptr(), PyArray_DOUBLE, 1, 1);
+ PyArrayObject* y = (PyArrayObject*)PyArray_ContiguousFromObject(
+ args[1].ptr(), PyArray_DOUBLE, 1, 1);
+ if (x == 0 || y == 0 || PyArray_DIM(x,0) != PyArray_DIM(y,0)) {
+ Py_XDECREF(x);
+ Py_XDECREF(y);
+ throw Py::ValueError("x and y must be 1D arrays of the same length");
+ }
+
+ // triangles.
+ PyArrayObject* triangles = (PyArrayObject*)PyArray_ContiguousFromObject(
+ args[2].ptr(), PyArray_INT, 2, 2);
+ if (triangles == 0 || PyArray_DIM(triangles,1) != 3) {
+ Py_XDECREF(x);
+ Py_XDECREF(y);
+ Py_XDECREF(triangles);
+ throw Py::ValueError("triangles must be a 2D array of shape (?,3)");
+ }
+
+ // Optiona...
 
[truncated message content]

Showing 1 results of 1

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.
Thanks for helping keep SourceForge clean.
X





Briefly describe the problem (required):
Upload screenshot of ad (required):
Select a file, or drag & drop file here.
Screenshot instructions:

Click URL instructions:
Right-click on the ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)

More information about our ad policies

Ad destination/click URL:

AltStyle によって変換されたページ (->オリジナル) /