Single Building EXTraction
In PHLBPCB.c, we record all runs from ixl -> ixr as also seen in nonovrl.dia.
We read (fo)=dyxlr.bh and write to (fr)=yxlrb.bh initially for each new building.
Since we fix the cell size(cs)=10' for more resolution, we show more missing data
as black holes as the 1000x1000 *.grf -> *.pcx. So, to fill these holes, we develop
a method to fill them in.
Also, we now want any adjacent vertical overlap of line yp with the consecutive ones below it.
For this, we display the possible combinations using 'b' for buildings.
CASE:1 ixll=12 ixrl=25
^ ^
iyt=0 ............bbbbbbbbbbbbb......bbbbbbb..............
iy =1 ........bbbbbbbbbb...........
^ ^
ixl=6 ixr=15
CASE:2 ixll=12 ixrl=25
^ ^
iyt=0 ............bbbbbbbbbbbbb......bbbbbbb..............
iy =1 ................bbbbbbbbbbb...........
^ ^
ixl=16 ixr=27
CASE:3 ixll=12 ixrl=25
^ ^
iyt=0 ............bbbbbbbbbbbbb......bbbbbbb..............
iy =1 ..bbbbbbbb...........
^ ^
ixl=2 ixr=9
CASE:4 ixll=12 ixrl=25
^ ^
iyt=0 ............bbbbbbbbbbbbb......bbbbbbb..............
iy =1 ............................bbbbbbbbbbbb...........
^ ^
ixl=29 ixr40
CASE:5 ixll=12 ixrl=24
^ ^
iyt=0 ............bbbbbbbbbbbbb......bbbbbbb..............
iy =1 .............bbbbbbbbbbb...........
^ ^
ixl=13 ixr=23
CASE:6 ixll=13 ixrl=23
^ ^
iyt=0 .............bbbbbbbbbbb...........
iy =1 ............bbbbbbbbbbbbb......bbbbbbb..............
^ ^
ixl=12 ixr=24
All cases overlap except 3 & 4. Just using the endpoint's in their respective positions,
we have the 5 cases again as:
Overlap Logical Exp
CASE:1 Y ixl ixll ixr ixrl ixll < ixr < ixrl
CASE:2 Y ixll ixl ixrl ixr ixl < ixrl < ixr
CASE:3 N ixl ixr ixll ixrl ixr < ixll
CASE:4 N ixll ixrl ixl ixr ixrl < ixl
CASE:5 Y ixll ixl ixr ixrl ixll < ixl < ixrl
CASE:6 Y ixl ixll ixrl ixr ixl < ixll < ixr
We could combine the 4 overlap (Y) cases Logical Exp's and accept overlaps.
However, a simpler method would be to use the 2 non-overlap (N) cases and reject
overlaps. That is if(ixr < ixll || ixrl < ixl) continue reading. This is our 1st
filter. Also, we could also have split that statement into 2 parts.
if(ixr < ixll) continue
if(ixrl < ixl) continue
Here, again either one will continue. However, notice that the 2nd line,
if(ixrl < ixl), this means that all consecutive buildings on that line ixl's
are even more > ixrl. So we should end reading that row by resetting to the next
row by file position (filp br record length recl but we don't know how many records
down the next line iy+1 is so we must continue reading iy's until it changes to the
next line. However, when we do reach it, we have to reset ixll to the new ixl &
ixrl to the new ixr because the building could be oriented ne<->sw, nw<->se as we
travel down (iy) the sloping sides of ixl & ixr. However, one structure may butt up
against the other structure below the iy line. So we modify to read
if(ixr <= ixll || ixrl <= ixl) continue.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Since we condensed the 10,000 x 10,000' down so that the total # of points (npr) should
reduce the no points, the cell size varied from about 24 to 40'/cell. This made the lines
yp too long even though the no points blackened have disappeared. Better is to use a lesser
cell size so we use 10'/cell or the 1000 x 1000 grid size (2 megabytes) seems reasonable.
Since building to building were hardly less that 30', let's fill in these gaps of say 20'
or 2 cell sizes or 2 black pixels in the horizontal ix. In the vertical, since the building
most building points should appear along the ix width, we can use this 2 cell size fo ix only,
not iy. We define mpa=2 consecutive Missing buildings Points allowed along the line ix. We
keep track of these by mbp, and cumulative mbp by mbpc. Each time we start picking up points
again, we in a sense fill in these 2 missing cells with the average height of the observed data.
Some examples are seen below:
0 2
8 9 mbp is set back to 0 each time we pick building points with mpa =3
ixl ixr cs cell size lengths however, mbpc still accumulates. For
^ ^ the 16 (nc) building points [b], say we have a running bhc along the
.......[bbb bbbb bbb bbbb bb] bbb iy line as bhcr=480'. So our average bh (abh) = bhc/nc = 480/16= 30'.
mbp 1 12 1 12 123 However, the ixr-ixl=29-8=21. Then +1=22 (nc). Since the 6 missing points
mbpc 1 23 4 56 789 are filled in with the average, we have higher total bhcr for the row,
bhcr=bhcr+bhcr/nc*mbpc = 480 + 30*6 = 660. So we would still have
660/(nc=22)=30'. That is, using real cell, count (nc=16), we obtain that
average to fill in the 6 missing cells (mbpc). Notice that we counted 3
mbp & mbpc before we ended the building. So with no more points, these last
3 mbp's were not missing points but ending points. So, we correct
mbpc=mbpc-mpb = 9-3=6 first before using it and write the new 'bhcr' at the
end of line in (fr)=yxlrb.bh.
ixl lx-1 Here, we end the line before mbp=3. So now we still adjust mbpc=mbpc-mpb
^ ^ as we did before but mpb=2 now.
..........bbbbbbbbbbbbbbbb..
mpc 12
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Another case exists where we may pick up smaller sheds, buildings or trees adjacent to a building. The problem is minor
if combining this with the building. However, its the rest of the building is ignored for the
rest of the row and by the rules for the next line, miss it. A diagram is giving below.
A The orientation of most buildings would be rectangular. The slope of the building
/\ face will be constant or either increase or decrease in width (ixr-ixl) but this
ixll/...\ixrl change in building width (bw) is proportional to the length down each cs (|) rows
ixl/......\ixr even though the ixr changes < ixl. So for some shrubs (*), its (IXL->IXR)
***/ | \ixr << (ixl->ixr) and should be easy to detect away from the upper & lower corners A & B.
**/IXR | \ Even if oriented NS EW, w by building remains constant but bw by shrubs may vary but
/ | \ usually much less than bw by building. See the expanded last diagram and explanation
/ | \ below.
/ | \
\ | \
\ | \
***\ | \
** \ | \
\ | /
\ | /
\ | /
\ | /
\ | /
\ /
\ /
\/
B
i The 1st ixll=ixrl is at apex A. Here, /
\ / Notice for this lower half of the building,
\ / as we round the corners, dxls & dxrs are
\<-------------- bw ------------------------->/ decreasing and lags behind the real lower wall
\ / projection because of averaging the upper wall slopes.
\ / However, we add another test. Only if bw/bw0 < .1,
\ / we reject it as a bush width as might be evident rounding
\ / the corners. These last 2 methods should also help depict
\ / rounded buildings better. This is the 4th filter.
\ / However, if bw0=0, we reject and continue reading.
\ / This is our 3rd filter.
\ /
\ /
\ /
\ /
\ /
\ /
\ /
\/
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
We have our initial filter of building heights bh by examining the string of consecutive building points, real & missing points until
mps > mpa. Here we now replace the consecutive missing points 'mps' by interpolation instead filling in these with average bh (abh).
So, we store an array of points that must include all the building points in a row. How many? Well that depends on the cell size but for PHL,
with cs=10, we have to use 750 whish is 7500'. Why so long? Because of marsh tall grass or trees along a river bang or bays, we don't know
it's real height above ground until we subtract off the terrain. In the main web page, you will see an example pic link of 3-4' tall grass.
However, for PHL, we set if bh < 20, probably tall grass, and trees will have breaks and more height variation. Also, most likely to Delaware
River basin. If not, if(ixr-ixl >= 750), we set flags and end the program. Using bh as the present grid building height (including terrain),
and bh0 as the last real building height, if(bh < .6*bh0 || bh > 1.4*bh0) { mbp++ and rbh[ix-ixl]=0 }. That is, the present bh must fall within
+,- 40% of the last bh (bh0). This is our initial filter (0). That is, we assume the 1 or 2 consecutive building heights are out of this range
for a continuous building and if this point is to be included, we interpolate by the adjacent points either side of mbp. A display of rbh's
(real building heights) array are seen below:
ix 47 48 49 50 51 52 53 54 55 56 57 58 59 60
i 0 1 2 3 4 5 6 7 8 9 10 11 12 13
bh 42.0 42.0 47.0 42.0 41.0 38.0 36.0 0.0 0.0 38.0 0.0 0.0 37.0 39.0
bh 42.0 42.0 47.0 42.0 41.0 38.0 36.0 36.7 37.3 38.0 37.7 37.3 37.0 39.0
Index i is rbh[i] and ix=ixl->ixr. Note i = 7 & 8 is interpolated to 36.666 & 37.333 as
well as i = 10,11.
ix107 108 109 110 111 112 113 114 115 116 117 118 119 120
i 0 1 2 3 4 5 6 7 8 9 10 11 12 13
bh 57.0 0.0 57.0 57.0 0.0 59.0 57.0 57.0 58.0 0.0 57.0 57.0 0.0 37.0
bh 57.0 57.0 57.0 57.0 58.0 59.0 57.0 57.0 58.0 57.5 57.0 57.0 47.0 37.0
Here, we simply match 57 @ i=1, 58 is interpolated @ i=4, 57.5 @ i=9 and 47.0 @ i=12.
Note, by filter # 0, .6 x 57(bh0) = 34.2. Since 37 > 34.2, i @ 12 can be interpolated to
47.0. This +- 40% works well instead of +- 2nf or 22' where tiered sky scrapers would likely
be segmented. For bh0=50', .6 x 50 = 30' or 20' less before we segment but at bh0=500', we
would have 300' or 200' less before we segmented. That is, we average taller building heights
with less tiering than with lower buildings.
By building row average heights, we have bhr=bhcr/ncr as building height Real by decimal.
With bh0=bhr, as the last real building height average in row, if(bhr <= .8*bh0 || bhr >= 1.2*bh0)
we reject this bhr. That is, the present bhr must fall within +,- 20% of the last bhr (bh0). This
is our 2nd filter - similar to 0 filter above.