aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/OpenSim.RegionServer/world/ParcelManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/OpenSim.RegionServer/world/ParcelManager.cs')
-rw-r--r--OpenSim/OpenSim.RegionServer/world/ParcelManager.cs658
1 files changed, 658 insertions, 0 deletions
diff --git a/OpenSim/OpenSim.RegionServer/world/ParcelManager.cs b/OpenSim/OpenSim.RegionServer/world/ParcelManager.cs
new file mode 100644
index 0000000..7cc39ff
--- /dev/null
+++ b/OpenSim/OpenSim.RegionServer/world/ParcelManager.cs
@@ -0,0 +1,658 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using libsecondlife;
5using libsecondlife.Packets;
6
7namespace OpenSim.world
8{
9 public delegate void ParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, bool snap_selection, ClientView remote_client);
10
11 #region Enums
12 public enum ParcelFlags : uint
13 {
14 /// <summary>No flags set</summary>
15 None = 0,
16 /// <summary>Allow avatars to fly (a client-side only restriction)</summary>
17 AllowFly = 1 << 0,
18 /// <summary>Allow foreign scripts to run</summary>
19 AllowOtherScripts = 1 << 1,
20 /// <summary>This parcel is for sale</summary>
21 ForSale = 1 << 2,
22 /// <summary>Allow avatars to create a landmark on this parcel</summary>
23 AllowLandmark = 1 << 3,
24 /// <summary>Allows all avatars to edit the terrain on this parcel</summary>
25 AllowTerraform = 1 << 4,
26 /// <summary>Avatars have health and can take damage on this parcel.
27 /// If set, avatars can be killed and sent home here</summary>
28 AllowDamage = 1 << 5,
29 /// <summary>Foreign avatars can create objects here</summary>
30 CreateObjects = 1 << 6,
31 /// <summary>All objects on this parcel can be purchased</summary>
32 ForSaleObjects = 1 << 7,
33 /// <summary>Access is restricted to a group</summary>
34 UseAccessGroup = 1 << 8,
35 /// <summary>Access is restricted to a whitelist</summary>
36 UseAccessList = 1 << 9,
37 /// <summary>Ban blacklist is enabled</summary>
38 UseBanList = 1 << 10,
39 /// <summary>Unknown</summary>
40 UsePassList = 1 << 11,
41 /// <summary>List this parcel in the search directory</summary>
42 ShowDirectory = 1 << 12,
43 /// <summary>Unknown</summary>
44 AllowDeedToGroup = 1 << 13,
45 /// <summary>Unknown</summary>
46 ContributeWithDeed = 1 << 14,
47 /// <summary>Restrict sounds originating on this parcel to the
48 /// parcel boundaries</summary>
49 SoundLocal = 1 << 15,
50 /// <summary>Objects on this parcel are sold when the land is
51 /// purchsaed</summary>
52 SellParcelObjects = 1 << 16,
53 /// <summary>Allow this parcel to be published on the web</summary>
54 AllowPublish = 1 << 17,
55 /// <summary>The information for this parcel is mature content</summary>
56 MaturePublish = 1 << 18,
57 /// <summary>The media URL is an HTML page</summary>
58 UrlWebPage = 1 << 19,
59 /// <summary>The media URL is a raw HTML string</summary>
60 UrlRawHtml = 1 << 20,
61 /// <summary>Restrict foreign object pushes</summary>
62 RestrictPushObject = 1 << 21,
63 /// <summary>Ban all non identified/transacted avatars</summary>
64 DenyAnonymous = 1 << 22,
65 /// <summary>Ban all identified avatars</summary>
66 DenyIdentified = 1 << 23,
67 /// <summary>Ban all transacted avatars</summary>
68 DenyTransacted = 1 << 24,
69 /// <summary>Allow group-owned scripts to run</summary>
70 AllowGroupScripts = 1 << 25,
71 /// <summary>Allow object creation by group members or group
72 /// objects</summary>
73 CreateGroupObjects = 1 << 26,
74 /// <summary>Allow all objects to enter this parcel</summary>
75 AllowAllObjectEntry = 1 << 27,
76 /// <summary>Only allow group and owner objects to enter this parcel</summary>
77 AllowGroupObjectEntry = 1 << 28,
78 }
79
80 /// <summary>
81 /// Parcel ownership status
82 /// </summary>
83 public enum ParcelStatus : sbyte
84 {
85 /// <summary>Eh?</summary>
86 None = -1,
87 /// <summary>Land is owned</summary>
88 Leased = 0,
89 /// <summary>Land is for sale</summary>
90 LeasePending = 1,
91 /// <summary>Land is public</summary>
92 Abandoned = 2
93 }
94
95 public enum ParcelCategory : sbyte
96 {
97 /// <summary>No assigned category</summary>
98 None = 0,
99 /// <summary></summary>
100 Linden,
101 /// <summary></summary>
102 Adult,
103 /// <summary></summary>
104 Arts,
105 /// <summary></summary>
106 Business,
107 /// <summary></summary>
108 Educational,
109 /// <summary></summary>
110 Gaming,
111 /// <summary></summary>
112 Hangout,
113 /// <summary></summary>
114 Newcomer,
115 /// <summary></summary>
116 Park,
117 /// <summary></summary>
118 Residential,
119 /// <summary></summary>
120 Shopping,
121 /// <summary></summary>
122 Stage,
123 /// <summary></summary>
124 Other,
125 /// <summary>Not an actual category, only used for queries</summary>
126 Any = -1
127 }
128
129 #endregion
130
131 #region ParcelManager Class
132 public class ParcelManager
133 {
134
135 #region Constants
136 //Parcel types set with flags in ParcelOverlay.
137 //Only one of these can be used.
138 public static byte PARCEL_TYPE_PUBLIC = (byte)0; //Equals 00000000
139 public static byte PARCEL_TYPE_OWNED_BY_OTHER = (byte)1; //Equals 00000001
140 public static byte PARCEL_TYPE_OWNED_BY_GROUP = (byte)2; //Equals 00000010
141 public static byte PARCEL_TYPE_OWNED_BY_REQUESTER = (byte)3; //Equals 00000011
142 public static byte PARCEL_TYPE_IS_FOR_SALE = (byte)4; //Equals 00000100
143 public static byte PARCEL_TYPE_IS_BEING_AUCTIONED = (byte)5; //Equals 00000101
144
145
146 //Flags that when set, a border on the given side will be placed
147 //NOTE: North and East is assumable by the west and south sides (if parcel to east has a west border, then I have an east border; etc)
148 //This took forever to figure out -- jeesh. /blame LL for even having to send these
149 public static byte PARCEL_FLAG_PROPERTY_BORDER_WEST = (byte)64; //Equals 01000000
150 public static byte PARCEL_FLAG_PROPERTY_BORDER_SOUTH = (byte)128; //Equals 10000000
151
152 #endregion
153
154 #region Member Variables
155 private List<Parcel> parcelList;
156 private static World m_world;
157 #endregion
158
159 #region Constructors
160 public ParcelManager(World world)
161 {
162 parcelList = new List<Parcel>();
163 m_world = world;
164
165 //NOTE: This is temporary until I get to storing the parcels out of memory
166 //This should later only be for new simulators
167 resetSimParcels();
168 Console.WriteLine("Created ParcelManager Object");
169
170
171 }
172 #endregion
173
174 #region Member Functions
175
176 #region Parcel Add/Remove/Get
177 public void addParcel(Parcel new_parcel)
178 {
179 parcelList.Add(new_parcel);
180 }
181 public void removeParcel(Parcel old_parcel)
182 {
183 parcelList.Remove(old_parcel);
184 }
185 public Parcel getParcel(int x, int y)
186 {
187 int searchParcel;
188 for(searchParcel = 0; searchParcel < this.parcelList.Count; searchParcel++)
189 {
190 if(parcelList[searchParcel].containsPoint(x,y))
191 {
192 return this.parcelList[searchParcel];
193 }
194 }
195 throw new Exception("Error: Parcel not found at point " + x + ", " + y);
196
197 }
198 #endregion
199
200 #region Parcel Modification
201 public bool subdivide(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id)
202 {
203 //First, lets loop through the points and make sure they are all in the same parcel
204 //Get the parcel at start
205 Parcel startParcel = getParcel(start_x, start_y);
206 if(startParcel == null) return false; //No such parcel at the beginning
207
208 //Loop through the points
209 try
210 {
211 int totalX = end_x - start_x;
212 int totalY = end_y - start_y;
213 int x, y;
214 for (x = 0; x < totalX; x++)
215 {
216 for (y = 0; y < totalY; y++)
217 {
218 Parcel tempParcel = getParcel(start_x + x, start_y + y);
219 if (tempParcel == null) return false; //No such parcel at that point
220 if (tempParcel != startParcel) return false; //Subdividing over 2 parcels; no-no
221 }
222 }
223 }
224 catch (Exception e)
225 {
226 return false; //Exception. For now, lets skip subdivision
227 }
228
229 //If we are still here, then they are subdividing within one parcel
230 //Check owner
231 if (startParcel.ownerID != attempting_user_id)
232 {
233 return false; //They cant do this!
234 }
235
236 //Lets create a new parcel with bitmap activated at that point (keeping the old parcels info)
237 Parcel newParcel = startParcel;
238 newParcel.setParcelBitmap(Parcel.getSquareParcelBitmap(start_x, start_y, end_x, end_y));
239
240 //Now, lets set the subdivision area of the original to false
241 int startParcelIndex = parcelList.IndexOf(startParcel);
242 parcelList[startParcelIndex].setParcelBitmap(Parcel.modifyParcelBitmapSquare(parcelList[startParcelIndex].getParcelBitmap(),start_x,start_y,end_x, end_y,false));
243
244 //Now add the new parcel
245 addParcel(newParcel);
246
247 return true;
248 }
249
250 public bool join(int start_x, int start_y, int end_x, int end_y, LLUUID attempting_user_id)
251 {
252 //NOTE: The following only connects the parcels in each corner and not all the parcels that are within the selection box!
253 //This should be fixed later -- somewhat "incomplete code" --Ming
254 Parcel startParcel, endParcel;
255 try
256 {
257 startParcel = getParcel(start_x, start_y);
258 endParcel = getParcel(end_x, end_y);
259 }
260 catch (Exception e)
261 {
262 return false; //Error occured when trying to get the start and end parcels
263 }
264 //Check the parcel owners:
265 if (startParcel.ownerID != endParcel.ownerID)
266 {
267 return false;
268 }
269 if (startParcel.ownerID != attempting_user_id)
270 {
271 //TODO: Group editing stuff. Avatar owner support for now
272 return false;
273 }
274
275 //Same owners! Lets join them
276 //Merge them to startParcel
277 parcelList[parcelList.IndexOf(startParcel)].setParcelBitmap(Parcel.mergeParcelBitmaps(startParcel.getParcelBitmap(),endParcel.getParcelBitmap()));
278
279 //Remove the old parcel
280 parcelList.Remove(endParcel);
281
282 return true;
283
284
285
286 }
287 #endregion
288
289 #region Parcel Updating
290 /// <summary>
291 /// Where we send the ParcelOverlay packet to the client
292 /// </summary>
293 /// <param name="remote_client">The object representing the client</param>
294 public void sendParcelOverlay(ClientView remote_client)
295 {
296 const int PARCEL_BLOCKS_PER_PACKET = 1024;
297 int x, y = 0;
298 byte[] byteArray = new byte[PARCEL_BLOCKS_PER_PACKET];
299 int byteArrayCount = 0;
300 int sequenceID = 0;
301 ParcelOverlayPacket packet;
302
303 for (x = 0; x < 64; x++)
304 {
305 for (y = 0; y < 64; y++)
306 {
307 byte tempByte = (byte)0; //This represents the byte for the current 4x4
308 Parcel currentParcelBlock = getParcel(x * 4, y * 4);
309
310 if (currentParcelBlock.ownerID == remote_client.AgentID)
311 {
312 //Owner Flag
313 tempByte = Convert.ToByte(tempByte | PARCEL_TYPE_OWNED_BY_REQUESTER);
314 }
315 else if (currentParcelBlock.salePrice > 0 && (currentParcelBlock.authBuyerID == LLUUID.Zero || currentParcelBlock.authBuyerID == remote_client.AgentID))
316 {
317 //Sale Flag
318 tempByte = Convert.ToByte(tempByte | PARCEL_TYPE_IS_FOR_SALE);
319 }
320 else if (currentParcelBlock.ownerID == LLUUID.Zero)
321 {
322 //Public Flag
323 tempByte = Convert.ToByte(tempByte | PARCEL_TYPE_PUBLIC);
324 }
325 else
326 {
327 //Other Flag
328 tempByte = Convert.ToByte(tempByte | PARCEL_TYPE_OWNED_BY_OTHER);
329 }
330
331
332 //Now for border control
333 if (x == 0)
334 {
335 tempByte = Convert.ToByte(tempByte | PARCEL_FLAG_PROPERTY_BORDER_WEST);
336 }
337 else if (getParcel(x - 1, y) != currentParcelBlock)
338 {
339 tempByte = Convert.ToByte(tempByte | PARCEL_FLAG_PROPERTY_BORDER_WEST);
340 }
341
342 if (y == 0)
343 {
344 tempByte = Convert.ToByte(tempByte | PARCEL_FLAG_PROPERTY_BORDER_SOUTH);
345 }
346 else if (getParcel(x, y - 1) != currentParcelBlock)
347 {
348 tempByte = Convert.ToByte(tempByte | PARCEL_FLAG_PROPERTY_BORDER_SOUTH);
349 }
350
351 byteArray[byteArrayCount] = tempByte;
352 byteArrayCount++;
353 if (byteArrayCount >= PARCEL_BLOCKS_PER_PACKET)
354 {
355 byteArrayCount = 0;
356 packet = new ParcelOverlayPacket();
357 packet.ParcelData.Data = byteArray;
358 packet.ParcelData.SequenceID = sequenceID;
359 remote_client.OutPacket((Packet)packet);
360 sequenceID++;
361 byteArray = new byte[PARCEL_BLOCKS_PER_PACKET];
362 }
363 }
364 }
365
366 packet = new ParcelOverlayPacket();
367 packet.ParcelData.Data = byteArray;
368 packet.ParcelData.SequenceID = sequenceID; //Eh?
369 remote_client.OutPacket((Packet)packet);
370 }
371 #endregion
372 public void resetSimParcels()
373 {
374 //Remove all the parcels in the sim and add a blank, full sim parcel set to public
375 parcelList.Clear();
376 Parcel fullSimParcel = new Parcel(LLUUID.Zero, false,m_world);
377 fullSimParcel.setParcelBitmap(Parcel.basicFullRegionParcelBitmap());
378 fullSimParcel.parcelName = "Your Sim Parcel";
379 fullSimParcel.parcelDesc = "";
380 LLUUID Agent;
381 int AgentRand = OpenSim.Framework.Utilities.Util.RandomClass.Next(1, 9999);
382 Agent = new LLUUID("99998888-0100-" + AgentRand.ToString("0000") + "-8ec1-0b1d5cd6aead");
383
384 fullSimParcel.ownerID = Agent;
385 fullSimParcel.salePrice = 1;
386 fullSimParcel.parcelFlags = ParcelFlags.ForSale;
387
388 addParcel(fullSimParcel);
389
390
391 }
392 #endregion
393 }
394 #endregion
395
396
397 #region Parcel Class
398 public class Parcel
399 {
400 #region Member Variables
401 private bool[,] parcelBitmap = new bool[64,64];
402 public string parcelName = "";
403 public string parcelDesc = "";
404 public LLUUID ownerID = new LLUUID();
405 public bool isGroupOwned = false;
406 public LLVector3 AABBMin = new LLVector3();
407 public LLVector3 AABBMax = new LLVector3();
408 public int area = 0;
409 public uint auctionID = 0; //Unemplemented. If set to 0, not being auctioned
410 public LLUUID authBuyerID = new LLUUID(); //Unemplemented. Authorized Buyer's UUID
411 public ParcelCategory category = new ParcelCategory(); //Unemplemented. Parcel's chosen category
412 public int claimDate = 0; //Unemplemented
413 public int claimPrice = 0; //Unemplemented
414 public LLUUID groupID = new LLUUID(); //Unemplemented
415 public int groupPrims = 0; //Unemplemented
416 public int salePrice = 0; //Unemeplemented. Parcels price.
417 public ParcelStatus parcelStatus = ParcelStatus.None;
418 public ParcelFlags parcelFlags = ParcelFlags.None;
419
420 private int localID;
421 private static int localIDCount = 0;
422 private World m_world;
423 #endregion
424
425
426 #region Constructors
427 public Parcel(LLUUID owner_id, bool is_group_owned, World world)
428 {
429 m_world = world;
430 ownerID = owner_id;
431 isGroupOwned = is_group_owned;
432
433 localID = localIDCount;
434 localIDCount++;
435
436 }
437 #endregion
438
439
440 #region Member Functions
441
442 #region General Functions
443 public bool containsPoint(int x, int y)
444 {
445 if (x >= 0 && y >= 0 && x <= 256 && x <= 256)
446 {
447 return (this.parcelBitmap[x / 4, y / 4] == true);
448 }
449 else
450 {
451 return false;
452 }
453 }
454 #endregion
455
456
457 #region Packet Request Handling
458 public void sendParcelProperties(int sequence_id, bool snap_selection, ClientView remote_client)
459 {
460
461 ParcelPropertiesPacket updatePacket = new ParcelPropertiesPacket();
462 updatePacket.ParcelData.AABBMax = AABBMax;
463 updatePacket.ParcelData.AABBMin = AABBMin;
464 updatePacket.ParcelData.Area = this.area;
465 updatePacket.ParcelData.AuctionID = this.auctionID;
466 updatePacket.ParcelData.AuthBuyerID = this.authBuyerID; //unemplemented
467
468 updatePacket.ParcelData.Bitmap = this.convertParcelBitmapToBytes();
469
470 updatePacket.ParcelData.Desc = libsecondlife.Helpers.StringToField(this.parcelDesc);
471 updatePacket.ParcelData.Category = (byte)this.category;
472 updatePacket.ParcelData.ClaimDate = this.claimDate;
473 updatePacket.ParcelData.ClaimPrice = this.claimPrice;
474 updatePacket.ParcelData.GroupID = this.groupID;
475 updatePacket.ParcelData.GroupPrims = this.groupPrims;
476 updatePacket.ParcelData.IsGroupOwned = this.isGroupOwned;
477 updatePacket.ParcelData.LandingType = (byte)0; //unemplemented
478 updatePacket.ParcelData.LocalID = (byte)this.localID;
479 updatePacket.ParcelData.MaxPrims = 1000; //unemplemented
480 updatePacket.ParcelData.MediaAutoScale = (byte)0; //unemplemented
481 updatePacket.ParcelData.MediaID = LLUUID.Zero; //unemplemented
482 updatePacket.ParcelData.MediaURL = Helpers.StringToField(""); //unemplemented
483 updatePacket.ParcelData.MusicURL = Helpers.StringToField(""); //unemplemented
484 updatePacket.ParcelData.Name = Helpers.StringToField(this.parcelName);
485 updatePacket.ParcelData.OtherCleanTime = 0; //unemplemented
486 updatePacket.ParcelData.OtherCount = 0; //unemplemented
487 updatePacket.ParcelData.OtherPrims = 0; //unemplented
488 updatePacket.ParcelData.OwnerID = this.ownerID;
489 updatePacket.ParcelData.OwnerPrims = 0; //unemplemented
490 updatePacket.ParcelData.ParcelFlags = (uint)this.parcelFlags; //unemplemented
491 updatePacket.ParcelData.ParcelPrimBonus = (float)1.0; //unemplemented
492 updatePacket.ParcelData.PassHours = (float)0.0; //unemplemented
493 updatePacket.ParcelData.PassPrice = 0; //unemeplemented
494 updatePacket.ParcelData.PublicCount = 0; //unemplemented
495 updatePacket.ParcelData.RegionDenyAnonymous = false; //unemplemented
496 updatePacket.ParcelData.RegionDenyIdentified = false; //unemplemented
497 updatePacket.ParcelData.RegionDenyTransacted = false; //unemplemented
498 updatePacket.ParcelData.RegionPushOverride = true; //unemplemented
499 updatePacket.ParcelData.RentPrice = 0; //??
500 updatePacket.ParcelData.RequestResult = 0;//??
501 updatePacket.ParcelData.SalePrice = this.salePrice; //unemplemented
502 updatePacket.ParcelData.SelectedPrims = 0; //unemeplemented
503 updatePacket.ParcelData.SelfCount = 0;//unemplemented
504 updatePacket.ParcelData.SequenceID = sequence_id;
505 updatePacket.ParcelData.SimWideMaxPrims = 15000; //unemplemented
506 updatePacket.ParcelData.SimWideTotalPrims = 0; //unemplemented
507 updatePacket.ParcelData.SnapSelection = snap_selection; //Bleh - not important yet
508 updatePacket.ParcelData.SnapshotID = LLUUID.Zero; //Unemplemented
509 updatePacket.ParcelData.Status = (byte)this.parcelStatus; //??
510 updatePacket.ParcelData.TotalPrims = 0; //unemplemented
511 updatePacket.ParcelData.UserLocation = LLVector3.Zero; //unemplemented
512 updatePacket.ParcelData.UserLookAt = LLVector3.Zero; //unemeplemented
513
514 remote_client.OutPacket((Packet)updatePacket);
515 }
516 #endregion
517
518
519 #region Update Functions
520 private void updateAABBAndAreaValues()
521 {
522 int min_x = 64;
523 int min_y = 64;
524 int max_x = 0;
525 int max_y = 0;
526 int tempArea = 0;
527 int x, y;
528 for (x = 0; x < 64; x++)
529 {
530 for (y = 0; y < 64; y++)
531 {
532 if (parcelBitmap[x, y] == true)
533 {
534 if (min_x > x) min_x = x;
535 if (min_y > y) min_y = y;
536 if (max_x < x) max_x = x;
537 if (max_y < y) max_y = y;
538 tempArea += 16; //16sqm parcel
539 }
540 }
541 }
542 this.AABBMin = new LLVector3((float)(min_x * 4), (float)(min_y * 4), m_world.Terrain[(min_x * 4), (min_y * 4)]);
543 this.AABBMax = new LLVector3((float)(max_x * 4), (float)(max_y * 4), m_world.Terrain[(max_x * 4), (max_y * 4)]);
544 this.area = tempArea;
545 }
546 #endregion
547
548
549 #region Parcel Bitmap Functions
550 public void setParcelBitmap(bool[,] bitmap)
551 {
552 if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2)
553 {
554 //Throw an exception - The bitmap is not 64x64
555 throw new Exception("Error: Invalid Parcel Bitmap");
556 }
557 else
558 {
559 //Valid: Lets set it
560 this.parcelBitmap = bitmap;
561 updateAABBAndAreaValues();
562 }
563 }
564 public bool[,] getParcelBitmap()
565 {
566 return parcelBitmap;
567 }
568 private byte[] convertParcelBitmapToBytes()
569 {
570 byte[] tempConvertArr = new byte[64 * 64 / 8];
571 byte tempByte = 0;
572 int x, y,i, byteNum = 0;
573 i = 0;
574 for (x = 0; x < 64; x++)
575 {
576 for (y = 0; y < 64; y++)
577 {
578 tempByte = Convert.ToByte(tempByte | Convert.ToByte(parcelBitmap[x,y]) << (i++ % 8));
579 if (i % 8 == 0)
580 {
581 tempConvertArr[byteNum] = tempByte;
582 tempByte = (byte)0;
583 i = 0;
584 byteNum++;
585 }
586 }
587 }
588 tempByte.ToString();
589 return tempConvertArr;
590 }
591
592 public static bool[,] basicFullRegionParcelBitmap()
593 {
594 return getSquareParcelBitmap(0, 0, 256, 256);
595 }
596 public static bool[,] getSquareParcelBitmap(int start_x, int start_y, int end_x, int end_y)
597 {
598
599 bool[,] tempBitmap = new bool[64, 64];
600 tempBitmap.Initialize();
601
602 tempBitmap = modifyParcelBitmapSquare(tempBitmap, start_x, start_y, end_x, end_x, true);
603 return tempBitmap;
604 }
605 public static bool[,] modifyParcelBitmapSquare(bool[,] parcel_bitmap, int start_x, int start_y, int end_x, int end_y, bool set_value)
606 {
607 if (parcel_bitmap.GetLength(0) != 64 || parcel_bitmap.GetLength(1) != 64 || parcel_bitmap.Rank != 2)
608 {
609 //Throw an exception - The bitmap is not 64x64
610 throw new Exception("Error: Invalid Parcel Bitmap in modifyParcelBitmapSquare()");
611 }
612
613 int x, y;
614 for (x = 0; x < 64; x++)
615 {
616 for (y = 0; y < 64; y++)
617 {
618 if (x >= start_x / 4 && x <= end_x / 4
619 && y >= start_y / 4 && y <= end_y / 4)
620 {
621 parcel_bitmap[x, y] = true;
622 }
623 }
624 }
625 return parcel_bitmap;
626 }
627 public static bool[,] mergeParcelBitmaps(bool[,] bitmap_base, bool[,] bitmap_add)
628 {
629 if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2)
630 {
631 //Throw an exception - The bitmap is not 64x64
632 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeParcelBitmaps");
633 }
634 if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2)
635 {
636 //Throw an exception - The bitmap is not 64x64
637 throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeParcelBitmaps");
638 }
639
640 int x, y;
641 for (x = 0; x < 64; x++)
642 {
643 for (y = 0; y < 64; y++)
644 {
645 if (bitmap_add[x,y])
646 {
647 bitmap_base[x, y] = true;
648 }
649 }
650 }
651 return bitmap_base;
652 }
653 #endregion
654
655 #endregion
656 }
657 #endregion
658}