Skip to content

Commit 8f4888e

Browse files
committed
Fixing vector plots not working for mercator and robinson projection
1 parent e1e4f40 commit 8f4888e

3 files changed

Lines changed: 94 additions & 20 deletions

File tree

Packages/vcs/Lib/VTKPlots.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,10 @@ def plotContinents(self, x1, x2, y1, y2, projection, wrap, tmpl):
645645
else:
646646
geo = None
647647

648+
writer = vtk.vtkXMLPolyDataWriter()
649+
writer.SetFileName("poly.vtk")
650+
writer.SetInputData(contData)
651+
writer.Write()
648652
self.fitToViewport(contActor,
649653
[tmpl.data.x1, tmpl.data.x2,
650654
tmpl.data.y1, tmpl.data.y2],
@@ -1137,6 +1141,7 @@ def fitToViewport(self, Actor, vp, wc=None, geo=None, priority=None,
11371141
else:
11381142
flipX = False
11391143

1144+
11401145
if geo is not None:
11411146
pt = vtk.vtkPoints()
11421147
Xrg2 = [1.e20, -1.e20]
@@ -1155,7 +1160,7 @@ def fitToViewport(self, Actor, vp, wc=None, geo=None, priority=None,
11551160
pt.InsertPoint(NGridCover, x, y, 0)
11561161
NGridCover += 1
11571162
pts = vtk.vtkPoints()
1158-
# pts.SetNumberOfPoints(Npts*Npts)
1163+
#pts.SetNumberOfPoints(Npts*Npts)
11591164
geo.TransformPoints(pt, pts)
11601165
b = pts.GetBounds()
11611166
xm, xM, ym, yM = b[:4]
@@ -1169,6 +1174,7 @@ def fitToViewport(self, Actor, vp, wc=None, geo=None, priority=None,
11691174
Yrg2[1] = max(Yrg2[1], yM)
11701175
Xrg = Xrg2
11711176
Yrg = Yrg2
1177+
11721178
wRatio = float(sc[0]) / float(sc[1])
11731179
dRatio = (Xrg[1] - Xrg[0]) / (Yrg[1] - Yrg[0])
11741180
vRatio = float(vp[1] - vp[0]) / float(vp[3] - vp[2])

Packages/vcs/Lib/vcs2vtk.py

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
for i in range(len(projNames)):
5454
projDict[i] = projNames[i]
5555

56-
5756
def applyAttributesFromVCStmpl(tmpl, tmplattribute, txtobj=None):
5857
tatt = getattr(tmpl, tmplattribute)
5958
if txtobj is None:
@@ -93,10 +92,6 @@ def putMaskOnVTKGrid(data, grid, actorColor=None, cellData=True, deep=True):
9392
grid2.GetPointData().RemoveArray(
9493
vtk.vtkDataSetAttributes.GhostArrayName())
9594
grid2.GetPointData().SetScalars(imsk)
96-
# grid2.SetCellVisibilityArray(imsk)
97-
# p2c = vtk.vtkPointDataToCellData()
98-
# p2c.SetInputData(grid2)
99-
# geoFilter.SetInputConnection(p2c.GetOutputPort())
10095
geoFilter.SetInputData(grid2)
10196
lut.SetTableValue(0, r / 100., g / 100., b / 100., 1.)
10297
lut.SetTableValue(1, r / 100., g / 100., b / 100., 1.)
@@ -137,9 +132,7 @@ def handleProjectionEdgeCases(projection, data):
137132
# For mercator projection, latitude values of -90 or 90
138133
# transformation result in infinity values. We chose -85, 85
139134
# as that's the typical limit used by the community.
140-
141135
pname = projDict.get(projection._type, projection.type)
142-
143136
if (pname.lower() == "merc"):
144137
lat = data.getLatitude()[:]
145138
# Reverse the latitudes incase the starting latitude is greater
@@ -149,14 +142,16 @@ def handleProjectionEdgeCases(projection, data):
149142
data = data(latitude=(max(-85, lat.min()), min(85, lat.max())))
150143
return data
151144

152-
153-
def genGridOnPoints(data1, gm, deep=True, grid=None, geo=None):
145+
def genGridOnPoints(data1, gm, deep=True, grid=None, geo=None,
146+
skipReprojection=False, data2=None):
154147
continents = False
155148
projection = vcs.elements["projection"][gm.projection]
156149
xm, xM, ym, yM = None, None, None, None
157150
useStructuredGrid = True
158151

159152
data1 = handleProjectionEdgeCases(projection, data1)
153+
if data2 is not None:
154+
data2 = handleProjectionEdgeCases(projection, data2)
160155

161156
try:
162157
g = data1.getGrid()
@@ -207,23 +202,25 @@ def genGridOnPoints(data1, gm, deep=True, grid=None, geo=None):
207202
m3 = numpy.concatenate((m3, z), axis=1)
208203
deep = True
209204
pts = vtk.vtkPoints()
205+
pts.SetDataTypeToDouble()
210206
# Convert nupmy array to vtk ones
211207
ppV = numpy_to_vtk_wrapper(m3, deep=deep)
212208
pts.SetData(ppV)
213209
else:
214210
xm, xM, ym, yM, tmp, tmp2 = grid.GetPoints().GetBounds()
215211
vg = grid
216212
xm, xM, ym, yM = getRange(gm, xm, xM, ym, yM)
217-
if geo is None:
213+
if geo is None and not skipReprojection:
218214
geo, geopts = project(pts, projection, [xm, xM, ym, yM])
215+
pts = geopts
219216
# Sets the vertices into the grid
220217
if grid is None:
221218
if useStructuredGrid:
222219
vg = vtk.vtkStructuredGrid()
223220
vg.SetDimensions(data1.shape[1], data1.shape[0], 1)
224221
else:
225222
vg = vtk.vtkUnstructuredGrid()
226-
vg.SetPoints(geopts)
223+
vg.SetPoints(pts)
227224
else:
228225
vg = grid
229226
out = {"vtk_backend_grid": vg,
@@ -234,7 +231,8 @@ def genGridOnPoints(data1, gm, deep=True, grid=None, geo=None):
234231
"continents": continents,
235232
"wrap": wrap,
236233
"geo": geo,
237-
"data": data1
234+
"data": data1,
235+
"data2": data2
238236
}
239237
return out
240238

@@ -545,6 +543,38 @@ def prepContinents(fnm):
545543
vcsContinents[fnm] = poly
546544
return poly
547545

546+
def projectArray(w, projection, geo=None):
547+
if isinstance(projection, (str, unicode)):
548+
projection = vcs.elements["projection"][projection]
549+
if projection.type == "linear":
550+
return None, pts
551+
552+
if geo is None:
553+
geo = vtk.vtkGeoTransform()
554+
ps = vtk.vtkGeoProjection()
555+
pd = vtk.vtkGeoProjection()
556+
557+
pname = projDict.get(projection._type, projection.type)
558+
projName = pname
559+
pd.SetName(projName)
560+
561+
if projection.type == "polar (non gctp)":
562+
if ym < yM:
563+
pd.SetOptionalParameter("lat_0", "-90.")
564+
pd.SetCentralMeridian(xm)
565+
else:
566+
pd.SetOptionalParameter("lat_0", "90.")
567+
pd.SetCentralMeridian(xm + 180.)
568+
else:
569+
setProjectionParameters(pd, projection)
570+
geo.SetSourceProjection(ps)
571+
geo.SetDestinationProjection(pd)
572+
573+
for i in range(0, w.GetNumberOfTuples()):
574+
tuple = [0, 0, 0]
575+
w.GetTupleValue(i, tuple)
576+
geo.TransformPoint(tuple, tuple)
577+
w.SetTupleValue(i, tuple)
548578

549579
# Geo projection
550580
def project(pts, projection, wc, geo=None):
@@ -573,6 +603,7 @@ def project(pts, projection, wc, geo=None):
573603
geo.SetSourceProjection(ps)
574604
geo.SetDestinationProjection(pd)
575605
geopts = vtk.vtkPoints()
606+
geopts.SetDataTypeToDouble()
576607
geo.TransformPoints(pts, geopts)
577608
return geo, geopts
578609

Packages/vcs/Lib/vcsvtk/vectorpipeline.py

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from vcs import vcs2vtk
55
import vtk
66

7+
import math
78

89
class VectorPipeline(Pipeline):
910

@@ -16,6 +17,7 @@ def plot(self, data1, data2, tmpl, grid, transform):
1617
"""Overrides baseclass implementation."""
1718
# Preserve time and z axis for plotting these inof in rendertemplate
1819
geo = None # to make flake8 happy
20+
projection = vcs.elements["projection"][self._gm.projection]
1921
returned = {}
2022
taxis = data1.getTime()
2123
if data1.ndim > 2:
@@ -27,14 +29,44 @@ def plot(self, data1, data2, tmpl, grid, transform):
2729
data1 = self._context().trimData2D(data1)
2830
data2 = self._context().trimData2D(data2)
2931

32+
scale = 1.0
33+
34+
lat = data1.getLatitude()[:]
35+
lon = data1.getLongitude()[:]
36+
37+
if projection is not None:
38+
scale = (lat.max() - lat.min()) * (lon.max() - lon.min())
39+
3040
gridGenDict = vcs2vtk.genGridOnPoints(data1, self._gm, deep=False, grid=grid,
31-
geo=transform)
41+
geo=transform, skipReprojection=False,
42+
data2=data2)
43+
44+
45+
data1 = gridGenDict["data"]
46+
data2 = gridGenDict["data2"]
47+
geo = gridGenDict["geo"]
48+
3249
for k in ['vtk_backend_grid', 'xm', 'xM', 'ym', 'yM', 'continents',
3350
'wrap', 'geo']:
3451
exec("%s = gridGenDict['%s']" % (k, k))
3552
grid = gridGenDict['vtk_backend_grid']
3653
self._dataWrapModulo = gridGenDict['wrap']
3754

55+
if geo is not None:
56+
newv = vtk.vtkDoubleArray()
57+
newv.SetNumberOfComponents(3)
58+
newv.InsertTupleValue(0, [lon.min(), lat.min(), 0])
59+
newv.InsertTupleValue(1, [lon.max(), lat.max(), 0])
60+
61+
vcs2vtk.projectArray(newv, projection=projection)
62+
dimMin = [0, 0, 0]
63+
dimMax = [0, 0, 0]
64+
newv.GetTupleValue(0, dimMin)
65+
newv.GetTupleValue(1, dimMax)
66+
scale = (dimMax[1] - dimMin[1]) * (dimMax[0] - dimMin[0])/scale
67+
else:
68+
scale = 1.0
69+
3870
returned["vtk_backend_grid"] = grid
3971
returned["vtk_backend_geo"] = geo
4072
missingMapper = vcs2vtk.putMaskOnVTKGrid(data1, grid, None, False,
@@ -68,6 +100,7 @@ def plot(self, data1, data2, tmpl, grid, transform):
68100

69101
arrow = vtk.vtkGlyphSource2D()
70102
arrow.SetGlyphTypeToArrow()
103+
arrow.SetOutputPointsPrecision(vtk.vtkAlgorithm.DOUBLE_PRECISION)
71104
arrow.FilledOff()
72105

73106
glyphFilter = vtk.vtkGlyph2D()
@@ -81,7 +114,7 @@ def plot(self, data1, data2, tmpl, grid, transform):
81114

82115
# Scale to vector magnitude:
83116
glyphFilter.SetScaleModeToScaleByVector()
84-
glyphFilter.SetScaleFactor(2. * self._gm.scale)
117+
glyphFilter.SetScaleFactor(math.sqrt(scale) * 2.0 * self._gm.scale)
85118

86119
# These are some unfortunately named methods. It does *not* clamp the
87120
# scale range to [min, max], but rather remaps the range
@@ -90,7 +123,12 @@ def plot(self, data1, data2, tmpl, grid, transform):
90123
glyphFilter.SetRange(0.01, 1.0)
91124

92125
mapper = vtk.vtkPolyDataMapper()
93-
mapper.SetInputConnection(glyphFilter.GetOutputPort())
126+
writer = vtk.vtkXMLPolyDataWriter()
127+
128+
glyphFilter.Update()
129+
data = glyphFilter.GetOutput()
130+
131+
mapper.SetInputData(data)
94132
act = vtk.vtkActor()
95133
act.SetMapper(mapper)
96134

@@ -100,21 +138,20 @@ def plot(self, data1, data2, tmpl, grid, transform):
100138

101139
x1, x2, y1, y2 = vcs.utils.getworldcoordinates(self._gm, data1.getAxis(-1),
102140
data1.getAxis(-2))
103-
104-
act = vcs2vtk.doWrap(act, [x1, x2, y1, y2], self._dataWrapModulo)
141+
# act = vcs2vtk.doWrap(act, [x1, x2, y1, y2], self._dataWrapModulo)
105142
self._context().fitToViewport(act, [tmpl.data.x1, tmpl.data.x2,
106143
tmpl.data.y1, tmpl.data.y2],
107-
[x1, x2, y1, y2],
144+
wc=None,
108145
priority=tmpl.data.priority,
109146
create_renderer=True)
110147

148+
111149
returned.update(
112150
self._context().renderTemplate(tmpl, data1, self._gm, taxis, zaxis))
113151

114152
if self._context().canvas._continents is None:
115153
continents = False
116154
if continents:
117-
projection = vcs.elements["projection"][self._gm.projection]
118155
self._context().plotContinents(x1, x2, y1, y2, projection,
119156
self._dataWrapModulo, tmpl)
120157

0 commit comments

Comments
 (0)