the test for two overlapping sectors is trivial, simply test if any point of either sector is inside the other. however, the manner in which they overlap matters for the two operations we need for the shadowcaster
// here are the possible overlap types:
enum SECTOR {
OVER_LEFT,
OVER_RIGHT,
OVER_LR,
COVERED,
COVERING,
NONE,
}
the union merges two overlapping sectors into one, this is useful for optimisation. less shadows to check against reduces the number of operations. when two sectors merge to cover all 360 degrees, there are no more cells in line of sight
the difference subtracts the range of one sector from another, and is ordered like a-b. a cell C is not in the field of vision if C.empty = true while iterating over the list
most of the overlap types are intuitive. OVER_LR is the case where all 4 points are inside the range of the other sector, the union of which is engulfed
here are the three functions added to Sector class, unhandled edge cases that (shouldnt) occur during shadowcasting are mentioned in comments
static sectorOverlaps = function(a) {
if (engulfed) return SECTOR.COVERING;
if (a.engulfed) return SECTOR.COVERED;
var sl = pointWithin(a.left);
var sr = pointWithin(a.right);
var al = a.pointWithin(left);
var ar = a.pointWithin(right);
if (!(sl || sr || al || ar)) {
return SECTOR.NONE;
}
var covering = sl && sr;
var covered = al && ar;
if (covering && covered) {
// unhandled edge case: both sectors are identical
// will not occur in this usecase
return SECTOR.OVER_LR;
}
if (covering) {
return SECTOR.COVERING;
}
if (covered) {
return SECTOR.COVERED;
}
if (sl) {
return SECTOR.OVER_LEFT;
}
if (sr) {
return SECTOR.OVER_RIGHT;
}
return undefined;
};
// combine two sectors into one and return self or a
// or undefined if no overlap
// this may modify the original as it is intended to be called
// from a loop that merges a list of sector
static sectorUnion = function(a) {
var type = sectorOverlaps(a);
switch (type) {
case SECTOR.OVER_LEFT:
right = a.right;
update();
return self;
case SECTOR.OVER_RIGHT:
left = a.left;
update();
return self;
case SECTOR.OVER_LR:
engulfed = true;
return self;
case SECTOR.COVERED:
return a;
case SECTOR.COVERING:
return self;
//case SECTOR.NONE:
// return undefined because the list of sectors does not change
// return [self, a]
}
return undefined;
};
// return a *new* sector C \ a, undefined if completely covered, self if no overlap
static sectorDifference = function(a) {
var type = sectorOverlaps(a);
switch (type) {
case SECTOR.OVER_LEFT:
return new Sector(left, a.left);
case SECTOR.OVER_RIGHT:
return new Sector(a.right, right);
case SECTOR.OVER_LR:
// flip a around
return new Sector(a.right, a.left);
//case SECTOR.COVERED:
// empty, undefined
// this wont occur in our usecase
case SECTOR.COVERING:
return [
new Sector(left, a.left),
new Sector(a.right, right)
];
case SECTOR.NONE:
return self;
}
return undefined;
};
Did you like this post? Tell us
Leave a comment
Log in with your itch.io account to leave a comment.