aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
diff options
context:
space:
mode:
authorDavid Walter Seikel2016-11-03 21:44:39 +1000
committerDavid Walter Seikel2016-11-03 21:44:39 +1000
commit134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch)
tree216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
parentMore changing to production grid. Double oops. (diff)
downloadopensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs378
1 files changed, 378 insertions, 0 deletions
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
new file mode 100644
index 0000000..7ebd08e
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
@@ -0,0 +1,378 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Reflection;
29using log4net;
30
31using OpenSim.Region.Framework.Interfaces;
32
33namespace OpenSim.Region.CoreModules.World.Terrain
34{
35 public abstract class TerrainModifier : ITerrainModifier
36 {
37 protected ITerrainModule m_module;
38 protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39
40 protected TerrainModifier(ITerrainModule module)
41 {
42 m_module = module;
43 }
44
45 public abstract string ModifyTerrain(ITerrainChannel map, string[] args);
46
47 public abstract string GetUsage();
48
49 public abstract double operate(double[,] map, TerrainModifierData data, int x, int y);
50
51 protected String parseParameters(string[] args, out TerrainModifierData data)
52 {
53 string val;
54 string arg;
55 string result;
56 data = new TerrainModifierData();
57 data.shape = String.Empty;
58 data.bevel = String.Empty;
59 data.dx = 0;
60 data.dy = 0;
61 if (args.Length < 4)
62 {
63 result = "Usage: " + GetUsage();
64 }
65 else
66 {
67 result = this.parseFloat(args[3], out data.elevation);
68 }
69 if (result == String.Empty)
70 {
71 int index = 3;
72 while(++index < args.Length && result == String.Empty)
73 {
74 arg = args[index];
75 // check for shape
76 if (arg.StartsWith("-rec=") || arg.StartsWith("-ell="))
77 {
78 if (data.shape != String.Empty)
79 {
80 result = "Only 1 '-rec' or '-ell' parameter is permitted.";
81 }
82 else
83 {
84 data.shape = arg.StartsWith("-ell=") ? "ellipse" : "rectangle";
85 val = arg.Substring(arg.IndexOf("=") + 1);
86 string[] coords = val.Split(new char[] {','});
87 if ((coords.Length < 3) || (coords.Length > 4))
88 {
89 result = String.Format("Bad format for shape parameter {0}", arg);
90 }
91 else
92 {
93 result = this.parseInt(coords[0], out data.x0);
94 if (result == String.Empty)
95 {
96 result = this.parseInt(coords[1], out data.y0);
97 }
98 if (result == String.Empty)
99 {
100 result = this.parseInt(coords[2], out data.dx);
101 }
102 if (result == String.Empty)
103 {
104 if (coords.Length == 4)
105 {
106 result = this.parseInt(coords[3], out data.dy);
107 }
108 else
109 {
110 data.dy = data.dx;
111 }
112 }
113 if (result == String.Empty)
114 {
115 if ((data.dx <= 0) || (data.dy <= 0))
116 {
117 result = "Shape sizes must be positive integers";
118 }
119 }
120 else
121 {
122 result = String.Format("Bad value in shape parameters {0}", arg);
123 }
124 }
125 }
126 }
127 else if (arg.StartsWith("-taper="))
128 {
129 if (data.bevel != String.Empty)
130 {
131 result = "Only 1 '-taper' parameter is permitted.";
132 }
133 else
134 {
135 data.bevel = "taper";
136 val = arg.Substring(arg.IndexOf("=") + 1);
137 result = this.parseFloat(val, out data.bevelevation);
138 if (result != String.Empty)
139 {
140 result = String.Format("Bad format for taper parameter {0}", arg);
141 }
142 }
143 }
144 else
145 {
146 result = String.Format("Unrecognized parameter {0}", arg);
147 }
148 }
149 }
150 return result;
151 }
152
153 protected string parseFloat(String s, out float f)
154 {
155 string result;
156 double d;
157 if (Double.TryParse(s, out d))
158 {
159 try
160 {
161 f = (float)d;
162 result = String.Empty;
163 }
164 catch(InvalidCastException)
165 {
166 result = String.Format("{0} is invalid", s);
167 f = -1.0f;
168 }
169 }
170 else
171 {
172 f = -1.0f;
173 result = String.Format("{0} is invalid", s);
174 }
175 return result;
176 }
177
178 protected string parseInt(String s, out int i)
179 {
180 string result;
181 if (Int32.TryParse(s, out i))
182 {
183 result = String.Empty;
184 }
185 else
186 {
187 result = String.Format("{0} is invalid", s);
188 }
189 return result;
190 }
191
192 protected void applyModification(ITerrainChannel map, TerrainModifierData data)
193 {
194 bool[,] mask;
195 int xMax;
196 int yMax;
197 int xMid;
198 int yMid;
199 if (data.shape == "ellipse")
200 {
201 mask = this.ellipticalMask(data.dx, data.dy);
202 xMax = mask.GetLength(0);
203 yMax = mask.GetLength(1);
204 xMid = xMax / 2 + xMax % 2;
205 yMid = yMax / 2 + yMax % 2;
206 }
207 else
208 {
209 mask = this.rectangularMask(data.dx, data.dy);
210 xMax = mask.GetLength(0);
211 yMax = mask.GetLength(1);
212 xMid = 0;
213 yMid = 0;
214 }
215// m_log.DebugFormat("Apply {0} mask {1}x{2} @ {3},{4}", data.shape, xMax, yMax, xMid, yMid);
216 double[,] buffer = map.GetDoubles();
217 int yDim = yMax;
218 while(--yDim >= 0)
219 {
220 int yPos = data.y0 + yDim - yMid;
221 if ((yPos >= 0) && (yPos < map.Height))
222 {
223 int xDim = xMax;
224 while(--xDim >= 0)
225 {
226 int xPos = data.x0 + xDim - xMid;
227 if ((xPos >= 0) && (xPos < map.Width) && (mask[xDim, yDim]))
228 {
229 double endElevation = this.operate(buffer, data, xPos, yPos);
230 map[xPos, yPos] = endElevation;
231 }
232 }
233 }
234 }
235 }
236
237 protected double computeBevel(TerrainModifierData data, int x, int y)
238 {
239 int deltaX;
240 int deltaY;
241 int xMax;
242 int yMax;
243 double factor;
244 if (data.bevel == "taper")
245 {
246 if (data.shape == "ellipse")
247 {
248 deltaX = x - data.x0;
249 deltaY = y - data.y0;
250 xMax = data.dx;
251 yMax = data.dy;
252 factor = (double)((deltaX * deltaX) + (deltaY * deltaY));
253 factor /= ((xMax * xMax) + (yMax * yMax));
254 }
255 else
256 {
257 // pyramid
258 xMax = data.dx / 2 + data.dx % 2;
259 yMax = data.dy / 2 + data.dy % 2;
260 deltaX = Math.Abs(data.x0 + xMax - x);
261 deltaY = Math.Abs(data.y0 + yMax - y);
262 factor = Math.Max(((double)(deltaY) / yMax), ((double)(deltaX) / xMax));
263 }
264 }
265 else
266 {
267 factor = 0.0;
268 }
269 return factor;
270 }
271
272 private bool[,] rectangularMask(int xSize, int ySize)
273 {
274 bool[,] mask = new bool[xSize, ySize];
275 int yPos = ySize;
276 while(--yPos >= 0)
277 {
278 int xPos = xSize;
279 while(--xPos >= 0)
280 {
281 mask[xPos, yPos] = true;
282 }
283 }
284 return mask;
285 }
286
287 /*
288 * Fast ellipse-based derivative of Bresenham algorithm.
289 * https://web.archive.org/web/20120225095359/http://homepage.smc.edu/kennedy_john/belipse.pdf
290 */
291 private bool[,] ellipticalMask(int xRadius, int yRadius)
292 {
293 long twoASquared = 2L * xRadius * xRadius;
294 long twoBSquared = 2L * yRadius * yRadius;
295
296 bool[,] mask = new bool[2 * xRadius + 1, 2 * yRadius + 1];
297
298 long ellipseError = 0L;
299 long stoppingX = twoBSquared * xRadius;
300 long stoppingY = 0L;
301 long xChange = yRadius * yRadius * (1L - 2L * xRadius);
302 long yChange = xRadius * xRadius;
303
304 int xPos = xRadius;
305 int yPos = 0;
306
307 // first set of points
308 while(stoppingX >= stoppingY)
309 {
310 int yUpper = yRadius + yPos;
311 int yLower = yRadius - yPos;
312 // fill in the mask
313 int xNow = xPos;
314 while(xNow >= 0)
315 {
316 mask[xRadius + xNow, yUpper] = true;
317 mask[xRadius - xNow, yUpper] = true;
318 mask[xRadius + xNow, yLower] = true;
319 mask[xRadius - xNow, yLower] = true;
320 --xNow;
321 }
322 yPos++;
323 stoppingY += twoASquared;
324 ellipseError += yChange;
325 yChange += twoASquared;
326 if ((2L * ellipseError + xChange) > 0L)
327 {
328 xPos--;
329 stoppingX -= twoBSquared;
330 ellipseError += xChange;
331 xChange += twoBSquared;
332 }
333 }
334
335 // second set of points
336 xPos = 0;
337 yPos = yRadius;
338 xChange = yRadius * yRadius;
339 yChange = xRadius * xRadius * (1L - 2L * yRadius);
340
341 ellipseError = 0L;
342 stoppingX = 0L;
343 stoppingY = twoASquared * yRadius;
344
345 while(stoppingX <= stoppingY)
346 {
347 int xUpper = xRadius + xPos;
348 int xLower = xRadius - xPos;
349 // fill in the mask
350 int yNow = yPos;
351 while(yNow >= 0)
352 {
353 mask[xUpper, yRadius + yNow] = true;
354 mask[xUpper, yRadius - yNow] = true;
355 mask[xLower, yRadius + yNow] = true;
356 mask[xLower, yRadius - yNow] = true;
357 --yNow;
358 }
359 xPos++;
360 stoppingX += twoBSquared;
361 ellipseError += xChange;
362 xChange += twoBSquared;
363 if ((2L * ellipseError + yChange) > 0L)
364 {
365 yPos--;
366 stoppingY -= twoASquared;
367 ellipseError += yChange;
368 yChange += twoASquared;
369 }
370 }
371 return mask;
372 }
373
374
375 }
376
377}
378