OVERLAY PROCEDURE CONCAVE_HULL_MENU; { Generates a home range area about the minimum and maximum Y values along an X axis. The X axis is divided into n arbitrary points giving a delta X. A min and max value is saved for each range of delta X } VAR GRID_NUM : INTEGER; PROCEDURE CONCAVE_HULL; { This is a home grown procedure to connect the external points along a given home range area. A delta X is given to determine the resolution of the 'grid' width. The smaller the delta x, the slower the program runs. } VAR CURVE_HIGH : ARRAY[1..2,1..500] OF REAL; { X AND Y POINTS OF THE UPPER CURVE } CURVE_LOW : ARRAY[1..2,1..500] OF REAL; { X AND Y POINTS OF THE LOWER CURVE } XHPOINTS : ARRAY [1..500] OF REAL; { POINTS TO CALCULATE AREA } YHPOINTS : ARRAY [1..500] OF REAL; { POINTS TO CALCULATE AREA } XLPOINTS : ARRAY [1..500] OF REAL; YLPOINTS : ARRAY [1..500] OF REAL; I : INTEGER; { A WORK VARIABLE } JH : INTEGER; { A WORK VARIABLE } JL : INTEGER; { A WORK VARIABLE } MAXINDEX : INTEGER; { LARGES INDEX USED IN GETTING THE POINTS } NPOINTS : INTEGER; { NUMBER OF POINTS IN THE DATA FILE } NUM_EMPTY : INTEGER; { PARTIAL NUMBER OF SECTION WITH NO POINTS } SCREENCT : INTEGER; { NUMBER OF LINES PRINTED TO THE SCREEN } TOTAL_POINTS : INTEGER; { TOTAL NUMBER OF PLOTTED POINTS - VERTICIES } XINDEX : INTEGER; { INDEX INTO THE TWO CURVE ARRAYS } X1I : INTEGER; X2I : INTEGER; Y1I : INTEGER; Y2I : INTEGER; AREAI : REAL; { TOTAL AREA OF THE HOME RANGE BY INTEGRATION } AREAIK : REAL; { INTEGRATED AREA IN SQUARE KILOMETERS } AREAG : REAL; { TOTAL AREA OF THE HOME RANGE BY GRID COUNT } AREAGK : REAL; { GRID COUNT AREA IN SQUARE KILOMETERS } AREA1 : REAL; { INCREMENTAL AREA OF THE HOME RANGE } TOTAL_METERS : REAL; { TOTAL METERS OF ENTIRE X RANGE } XSECTIONS : REAL; { THE NUMBER OF X SECTIONS } XVALUE : REAL; { CURRENT X CO-ORDINATE } YSECTIONS : REAL; { NUMBER OF Y SECTIONS } YFIRST : REAL; { FIRST Y VALUE IN INTERPOLATION } YLAST : REAL; { LAST Y VALUE IN INTERPOLATION } YMEAN : REAL; { AVERAGE OF YLAST + YFIRST } BEGIN { CONCAVE_HULL } { OPEN THE FILES } ASSIGN (FILEVAR2,FILEOUT); RESET (FILEVAR2); { POSITION POINTER TO BEGIN OF INPUT FILE } STUDYOPEN := FALSE; REPLAYOPEN := FALSE; { FIRST , LOAD THE MIN AND MAX VALUES FROM THE DATA FILE } WRITELN (OUTPUT,' '); WRITELN (OUTPUT,'Loading extreme limits of the data file.'); SEEK (FILEVAR2,1); READ (FILEVAR2,FILE2REC); XLOW := FILE2REC.X; YLOW := FILE2REC.Y; ZLOW := FILE2REC.Z; NPOINTS := FILE2REC.RECORD_NO; READ (FILEVAR2,FILE2REC); XHIGH := FILE2REC.X; YHIGH := FILE2REC.Y; ZHIGH := FILE2REC.Z; { SET UP DIVISION POINTS } XDELTA := XHIGH - XLOW; YDELTA := YHIGH - YLOW; { SET UP USER REQUESTED GRID SQUARE SIZE } TOTAL_METERS := METER_VALUE * XDELTA; XSECTIONS := TOTAL_METERS / SECTION_VALUE; XGRID_NUM := ROUND(INT(XSECTIONS)); IF FRAC(XSECTIONS) > 0 THEN XGRID_NUM := XGRID_NUM + 1; XDELTA := XGRID_NUM * SECTION_VALUE / METER_VALUE; XHIGH := XDELTA + XLOW; { DO THE SAME FOR THE Y VALUES } TOTAL_METERS := METER_VALUE * YDELTA; YSECTIONS := TOTAL_METERS / SECTION_VALUE; YGRID_NUM := ROUND(INT(YSECTIONS)); IF FRAC(YSECTIONS) > 0 THEN YGRID_NUM := YGRID_NUM + 1; YDELTA := YGRID_NUM * SECTION_VALUE / METER_VALUE; YHIGH := YDELTA + YLOW; IF XDELTA > YDELTA THEN BEGIN GRID_NUM := XGRID_NUM; GRID_SPAN := XDELTA; GRIDLOW := XLOW; GRIDHIGH := XHIGH; END ELSE BEGIN GRID_NUM := YGRID_NUM; GRID_SPAN := YDELTA; GRIDLOW := YLOW; GRIDHIGH := YHIGH; END; { INITIALIZE THE CURVES ARRAYS } FOR I := 1 TO GRID_NUM DO BEGIN CURVE_HIGH[1,I] := XLOW -1; CURVE_HIGH[2,I] := YLOW -1; CURVE_LOW[1,I] := XHIGH + 1; CURVE_LOW[2,I] := YHIGH + 1; END; { FOR I = 1 TO GRID_NUM } MAXINDEX := 0; { SECOND PASS, GETTING THE MIN AND MAX Y VALUES FOR EACH X DIVISION } WRITELN (OUTPUT,' '); WRITELN (OUTPUT,'Second pass, creating the CONCAVE polygon.'); RESET (FILEVAR2); SEEK (FILEVAR2,3); { POSITION BEYOND FILE HEADERS } WHILE NOT EOF(FILEVAR2) DO BEGIN READ (FILEVAR2,FILE2REC); WITH FILE2REC DO BEGIN XVALUE := ( X - XLOW) * GRID_NUM / XDELTA; XINDEX := TRUNC(XVALUE) + 1; IF XINDEX > GRID_NUM THEN XINDEX := GRID_NUM; IF XINDEX < 1 THEN XINDEX := 1; IF XINDEX > MAXINDEX THEN MAXINDEX := XINDEX; { HAVE THE INDEX, NOW SEE IF Y IS A MIN OR MAX } IF Y > CURVE_HIGH[2,XINDEX] THEN BEGIN CURVE_HIGH[1,XINDEX] := X; CURVE_HIGH[2,XINDEX] := Y; END; IF Y < CURVE_LOW[2,XINDEX] THEN BEGIN CURVE_LOW[1,XINDEX] := X; CURVE_LOW[2,XINDEX] := Y; END; END; { WITH FILE2REC } END; { WHILE NOT EOF(FILEVAR2) } { THE TWO CURVE ARRAYS HAVE THE UPPER AND LOWER CURVE OF THE HOME RANGE CALCULATE THE AREA OF THE HOME RANGE } { ************************************************************************ } { *************** AREA BY INTEGRATION ************************************ } { This is always done as the graph is done with these values } AREAI := 0.0; METER_SQUARE := METER_VALUE * METER_VALUE; WRITELN; WRITELN('Isolating the polygon verticies.'); JH := 0; { SEE WHICH END POINT TO USE } IF CURVE_LOW[1,1] < CURVE_HIGH[1,1] THEN BEGIN JH := JH + 1; XHPOINTS[JH] := CURVE_LOW[1,1]; YHPOINTS[JH] := CURVE_LOW[2,1]; END; { GET MAX POINTS FROM ALL GRID SECTIONS. IF THE X VALUE IS STILL XLOW-1, THEN THAT GRID SECTION HAD NO POINT IN IT. } FOR I := 1 TO MAXINDEX DO IF CURVE_HIGH[1,I] > XLOW-1 THEN BEGIN JH := JH + 1; XHPOINTS[JH] := CURVE_HIGH[1,I]; YHPOINTS[JH] := CURVE_HIGH[2,I]; END; { IF CURVE_HIGH[1,I] > XLOW-1 } WRITELN; IF PRECISION = 'I' THEN WRITELN('Calculating the area of the polygon by integration.') ELSE WRITELN('Calculating the area of the polygon by grid cell count.'); { NOW GET THE HIGH END POINT } IF CURVE_LOW[1,MAXINDEX] > CURVE_HIGH[1,MAXINDEX] THEN BEGIN JH := JH + 1; XHPOINTS[JH] := CURVE_LOW[1,MAXINDEX]; YHPOINTS[JH] := CURVE_LOW[2,MAXINDEX]; END; { CALCULATE AREA UNDER THE HIGH CURVE } FOR I := 1 TO JH-1 DO BEGIN CURVE_AREA(XHPOINTS[I],YHPOINTS[I],XHPOINTS[I+1],YHPOINTS[I+1],AREA1); AREAI := AREAI + AREA1; END; { REPEAT THE PROCEDURE FOR THE LOWER CURVE } JL := 0; IF CURVE_HIGH[1,1] <= CURVE_LOW[1,1] THEN BEGIN JL := JL + 1; XLPOINTS[JL] := CURVE_HIGH[1,1]; YLPOINTS[JL] := CURVE_HIGH[2,1]; END; FOR I := 1 TO MAXINDEX DO IF CURVE_LOW[1,I] < XHIGH + 1 THEN BEGIN JL := JL + 1; XLPOINTS[JL] := CURVE_LOW[1,I]; YLPOINTS[JL] := CURVE_LOW[2,I]; END; { NOW GET THE HIGH END POINT } IF CURVE_HIGH[1,MAXINDEX] >= CURVE_LOW[1,MAXINDEX] THEN BEGIN JL := JL + 1; XLPOINTS[JL] := CURVE_HIGH[1,MAXINDEX]; YLPOINTS[JL] := CURVE_HIGH[2,MAXINDEX]; END; { SUBTRACT AREA UNDER THE LOW CURVE FROM THE AREA UNDER THE HIGH CURVE } FOR I := 1 TO JL -1 DO BEGIN CURVE_AREA(XLPOINTS[I],YLPOINTS[I],XLPOINTS[I+1],YLPOINTS[I+1],AREA1); AREAI := AREAI - AREA1; END; AREAI := AREAI * METER_SQUARE; AREAIK := AREAI / 1000; AREAIK := AREAIK / 1000; { ************************************************************************ } { *************** AREA BY GRID SQUARE ************************************ } AREAG := 0; YFIRST := -100; NUM_EMPTY := 0; XGRID_NUM := 0; { XGRID_NUM WILL HOLD THE AREA IN GRID SQUARE NUMBERS } YGRID_NUM := 0; { YGRID_NUM WILL BE A WORK VARIABLE } FOR I := 1 TO MAXINDEX DO IF CURVE_HIGH[1,I] > XLOW-1 THEN BEGIN IF NUM_EMPTY > 0 THEN BEGIN YLAST := CURVE_HIGH[2,I]; YMEAN := (YFIRST + YLAST) / 2; YGRID_NUM := ROUND(INT(YMEAN * METER_VALUE / SECTION_VALUE)); IF FRAC(YMEAN * METER_VALUE / SECTION_VALUE) > 0 THEN YGRID_NUM := YGRID_NUM + 1; XGRID_NUM := XGRID_NUM + YGRID_NUM * NUM_EMPTY; NUM_EMPTY := 0; END; YFIRST := CURVE_HIGH[2,I]; YGRID_NUM := ROUND(INT(CURVE_HIGH[2,I] * METER_VALUE / SECTION_VALUE)); IF FRAC(CURVE_HIGH[2,I] * METER_VALUE / SECTION_VALUE) > 0 THEN YGRID_NUM := YGRID_NUM +1; XGRID_NUM := XGRID_NUM + YGRID_NUM; END ELSE BEGIN { SETUP FOR INTERPOLATION } NUM_EMPTY := NUM_EMPTY + 1; END; { The lower curve is subtracted from the upper to give area } FOR I := 1 TO MAXINDEX DO IF CURVE_LOW[1,I] < XHIGH + 1 THEN BEGIN IF NUM_EMPTY > 0 THEN BEGIN YLAST := CURVE_LOW[2,I]; YMEAN := (YFIRST + YLAST) / 2; YGRID_NUM := ROUND(INT(YMEAN * METER_VALUE / SECTION_VALUE)); IF FRAC(YMEAN * METER_VALUE / SECTION_VALUE) > 0 THEN YGRID_NUM := YGRID_NUM - 1; XGRID_NUM := XGRID_NUM - YGRID_NUM * NUM_EMPTY; NUM_EMPTY := 0; END; YFIRST := CURVE_LOW[2,I]; YGRID_NUM := ROUND(INT(CURVE_LOW[2,I] * METER_VALUE / SECTION_VALUE)); IF FRAC(CURVE_LOW[2,I] * METER_VALUE / SECTION_VALUE) > 0 THEN YGRID_NUM := YGRID_NUM - 1; XGRID_NUM := XGRID_NUM - YGRID_NUM; END ELSE BEGIN { SETUP FOR INTERPOLATION } NUM_EMPTY := NUM_EMPTY + 1; END; AREAG := XGRID_NUM * SECTION_VALUE * SECTION_VALUE; AREAGK := AREAG / 1000; AREAGK := AREAGK / 1000; { ************************************************************************ } { ************************************************************************ } TOTAL_POINTS := JL + JH - 3; CLRSCR; WRITELN; WRITELN('The home range ploygon has ',TOTAL_POINTS,' verticies.'); WRITELN; IF PRECISION = 'I' THEN BEGIN IF AREAI > 10000 THEN WRITELN('The area of the polygon is ',AREAIK:12:7,' square kilometers.') ELSE WRITELN('The area of the polygon is ',AREAI:12:7,' square meters.'); WRITELN; WRITELN ('The area is calculated with High accuracy integration.'); END ELSE { GRID COUNT ACCURACY } BEGIN IF AREAG > 10000 THEN WRITELN('The area of the polygon is ',AREAGK:12:7,' square kilometers.') ELSE WRITELN ('The area of the polygon is ',AREAG:12:7,' square meters.'); WRITELN; WRITELN ('The area is calculated with Low accuracy grid cell counts.'); END; WRITELN; WRITELN ('A grid of ',grid_num,' cells wide is used to cover the home range.'); LINE_OUT(1,25,SPACE79); LINE_OUT(1,25,'Do you want the vertices displayed and/or printed? (Y|N) '); YES_NO(KEYVALUE); IF KEYVALUE = 'Y' THEN BEGIN CLRSCR; SCREENCT := 0; FOR I := 1 TO JH DO BEGIN IF ( PRINTCHAR IN ['D','B'] ) AND ( KEYVALUE <> 'Q' ) THEN BEGIN SCREENCT := SCREENCT + 1; WRITELN (XHPOINTS[I]:10:5,' ',YHPOINTS[I]:10:5); IF SCREENCT >= 22 THEN BEGIN LINE_OUT(1,25,'Press any key to continue, Q to Quit.'); READ (KBD,KEYVALUE); SCREENCT := 0; DELLINE; WRITELN; WRITELN; END; { IF SCREENCT >= 22 } END; { IF PRINTCHAR = D OR B AND KEYVALUE <> Q } IF ( PRINTCHAR IN ['P','B'] ) AND ( KEYVALUE <> 'Q' ) THEN WRITELN (LST,XHPOINTS[I]:10:5,' ',YHPOINTS[I]:10:5); IF KEYPRESSED THEN BEGIN WRITELN ('A key was entered, press any key to continue, Q to quit.'); READ (KBD,KEYVALUE); DELLINE; END; { IF KEYPRESSED } END; { FOR I = 1 TO JH } FOR I := 1 TO JL DO BEGIN IF ( PRINTCHAR IN ['D','B'] ) AND ( KEYVALUE <> 'Q' ) THEN BEGIN SCREENCT := SCREENCT + 1; WRITELN (XLPOINTS[I]:10:5,' ',YLPOINTS[I]:10:5); IF SCREENCT >= 22 THEN BEGIN LINE_OUT(1,25,'Press any key to continue, Q to Quit.'); READ (KBD,KEYVALUE); SCREENCT := 0; DELLINE; WRITELN; WRITELN; END; { IF SCREENCT >= 22 } END; { IF PRINTCHAR = D OR B AND KEYVALUE <> Q } IF ( PRINTCHAR IN ['P','B'] ) AND ( KEYVALUE <> 'Q' ) THEN WRITELN (LST,XLPOINTS[I]:10:5,' ',YLPOINTS[I]:10:5); IF KEYPRESSED THEN BEGIN WRITELN ('A key was entered, press any key to continue, Q to quit.'); READ (KBD,KEYVALUE); DELLINE; END; { IF KEYPRESSED } END; { FOR I = 1 TO JL } IF PRINTCHAR IN ['D','B'] THEN IF PRECISION = 'I' THEN BEGIN IF AREAI > 10000 THEN WRITELN('Number of verticies: ',TOTAL_POINTS,' Area: ', AREAIK:12:7,' Square kilometers.') ELSE WRITELN('Number of verticies: ',TOTAL_POINTS,' Area: ', AREAI:12:7,' Square meters.'); WRITELN; END ELSE BEGIN IF AREAG > 10000 THEN WRITELN('Number of verticies: ',TOTAL_POINTS,' Area: ', AREAGK:12:7,' Square kilometers.') ELSE WRITELN('Number of verticies: ',TOTAL_POINTS,' Area: ', AREAG:12:7,' Square meters.'); WRITELN; END; IF PRINTCHAR IN ['P','B'] THEN IF PRECISION = 'I' THEN BEGIN IF AREAI > 10000 THEN WRITELN(LST,'Number of verticies: ',TOTAL_POINTS,' Area: ', AREAIK:12:7,' Square kilometers.') ELSE WRITELN(LST,'Number of verticies: ',TOTAL_POINTS,' Area: ', AREAI:12:7,' Square meters.'); WRITELN; END ELSE IF AREAG > 10000 THEN WRITELN(LST,'Number of verticies: ',TOTAL_POINTS,' Area: ', AREAGK:12:7,' Square kilometers.') ELSE WRITELN(LST,'Number of verticies: ',TOTAL_POINTS,' Area: ', AREAG:12:7,' Square meters.'); KEYBOARD_PAUSE; END; { IF KEYVALUE = 'Y' } KEYVALUE := 'R'; IF DRAWCHAR = 'Y' THEN BEGIN { SAVE THE MIN AND MAX VALUES } SXLOW := XLOW; SYLOW := YLOW; SZLOW := ZLOW; SXHIGH := XHIGH; SYHIGH := YHIGH; SZHIGH := ZHIGH; { DRAW THE POINTS IN THE HIGH CURVE AND THE LOW CURVE } IF STUDYFILE <> '' THEN BEGIN ASSIGN(FILEVAR3,STUDYFILE); RESET(FILEVAR3); STUDYOPEN := TRUE; END; IF (REPLAYFILE <> '') AND (EXIST(REPLAYFILE)) THEN BEGIN ASSIGN(FILEVAR4,REPLAYFILE); RESET(FILEVAR4); REPLAYOPEN := TRUE; END; { MIN AND MAX VALUES WERE CALCULATED HIGHER IN THE PROGRAM } GRID_CALCULATIONS; HIRES; HIRESCOLOR(YELLOW); LINE_OUT(2,1,'Concave Polygon'); FOR I := 1 TO JH-1 DO HIRES_VECTOR(XHPOINTS[I],YHPOINTS[I],XHPOINTS[I+1],YHPOINTS[I+1], XOFFSET,YOFFSET,GRIDFACTOR); FOR I := 1 TO JL-1 DO HIRES_VECTOR(XLPOINTS[I],YLPOINTS[I],XLPOINTS[I+1],YLPOINTS[I+1], XOFFSET,YOFFSET,GRIDFACTOR); { WRITE OUT THE FILE INFORMATION } LINE_OUT(60,4,'Data file:'); LINE_OUT(64,5,FILEOUT); IF STUDYFILE <> '' THEN BEGIN LINE_OUT(60,7,'Map file:'); LINE_OUT(64,8,STUDYFILE); END; IF REPLAYFILE <> '' THEN BEGIN LINE_OUT(60,10,'Replay file:'); LINE_OUT(64,11,REPLAYFILE); END; LINE_OUT(62,13,'AREA:'); GOTOXY(62,14); IF PRECISION = 'I' THEN IF AREAI > 10000 THEN BEGIN WRITE(AREAIK:12:7); LINE_OUT(62,15,'Sq. kilometers.'); END ELSE BEGIN WRITE(AREAI:12:7); LINE_OUT(62,15,'Sq. meters.'); END ELSE IF AREAG > 10000 THEN BEGIN WRITE(AREAGK:12:7); LINE_OUT(62,15,'Sq. kilometers.'); END ELSE BEGIN WRITE(AREAG:12:7,' Square meters.'); LINE_OUT(62,15,'Sq. meters.'); END; IF STUDYFILE <> '' THEN BEGIN LINE_OUT(1,25,SPACE79); LINE_OUT(1,25,'Draw the study file area overlay? (Y|N) '); YES_NO(STUDYDRAWN); LINE_OUT(1,25,SPACE79); IF STUDYDRAWN = 'Y' THEN BEGIN { DRAW THE STUDY AREA } HIRES; HIRESCOLOR(YELLOW); SEEK (FILEVAR3,1); { MIN AND MAX FOR STUDY AREA } READ (FILEVAR3,FILE3REC); XLOW := MIN_VAL(FILE3REC.X1,XLOW); YLOW := MIN_VAL(FILE3REC.Y1,YLOW); ZLOW := MIN_VAL(FILE3REC.Z1,ZLOW); XHIGH := MAX_VAL(FILE3REC.X2,XHIGH); YHIGH := MAX_VAL(FILE3REC.Y2,YHIGH); ZHIGH := MAX_VAL(FILE3REC.X2,XHIGH); GRID_CALCULATIONS; LINE_OUT(2,1,'Concave Polygon'); SEEK (FILEVAR3,2); { DATA BEGINS AT THE THIRD RECORD } WHILE NOT EOF(FILEVAR3) DO BEGIN READ (FILEVAR3,FILE3REC); WITH FILE3REC DO HIRES_VECTOR(X1,Y1,X2,Y2,XOFFSET,YOFFSET,GRIDFACTOR); END; { REDRAW THE CONCAVE POLYGON } FOR I := 1 TO JH-1 DO HIRES_VECTOR(XHPOINTS[I],YHPOINTS[I],XHPOINTS[I+1],YHPOINTS[I+1], XOFFSET,YOFFSET,GRIDFACTOR); FOR I := 1 TO JL-1 DO HIRES_VECTOR(XLPOINTS[I],YLPOINTS[I],XLPOINTS[I+1],YLPOINTS[I+1], XOFFSET,YOFFSET,GRIDFACTOR); { WRITE OUT THE FILE INFORMATION } LINE_OUT(60,4,'Data file:'); LINE_OUT(64,5,FILEOUT); IF STUDYFILE <> '' THEN BEGIN LINE_OUT(60,7,'Map file:'); LINE_OUT(64,8,STUDYFILE); END; IF REPLAYFILE <> '' THEN BEGIN LINE_OUT(60,10,'Replay file:'); LINE_OUT(64,11,REPLAYFILE); END; LINE_OUT(62,13,'AREA:'); GOTOXY(62,14); IF PRECISION = 'I' THEN IF AREAI > 10000 THEN BEGIN WRITE(AREAIK:12:7); LINE_OUT(62,15,'Sq. kilometers.'); END ELSE BEGIN WRITE(AREAI:12:7); LINE_OUT(62,15,'Sq. meters.'); END ELSE IF AREAG > 10000 THEN BEGIN WRITE(AREAGK:12:7); LINE_OUT(62,15,'Sq. kilometers.'); END ELSE BEGIN WRITE(AREAG:12:7,' Square meters.'); LINE_OUT(62,15,'Sq. meters.'); END; END; { IF STUDYDRAWN = Y } END; { IF STUDYFILE <> '' } IF REPLAYFILE <> '' THEN BEGIN LINE_OUT(1,25,SPACE79); LINE_OUT(1,25,'Do you want to add this graph to the replay file? (Y|N) '); YES_NO(KEYVALUE); IF KEYVALUE = 'Y' THEN BEGIN IF NOT EXIST(REPLAYFILE) THEN BEGIN INIT_REPLAY_FILE; ASSIGN(FILEVAR4,REPLAYFILE); RESET (FILEVAR4); REPLAYOPEN := TRUE; END; { WRITE OUT THIS PLOT } IF STUDYDRAWN = 'Y' THEN IF NOT STUDY_IN_REPLAY THEN ADD_GRAPH('STUDYFILE'); SEEK (FILEVAR4,1); { WHOLE FILE MIN AND MAX } READ (FILEVAR4,FILE4REC); FILE4REC.X1 := MIN_VAL(FILE4REC.X1,SXLOW); FILE4REC.Y1 := MIN_VAL(FILE4REC.Y1,SYLOW); FILE4REC.Z1 := MIN_VAL(FILE4REC.Z1,SZLOW); FILE4REC.X2 := MIN_VAL(FILE4REC.X2,SXHIGH); FILE4REC.Y2 := MIN_VAL(FILE4REC.Y2,SYHIGH); FILE4REC.Z2 := MIN_VAL(FILE4REC.Z2,SZHIGH); FILE4REC.LINE_TYPE := FILE4REC.LINE_TYPE + TOTAL_POINTS; SEEK (FILEVAR4,1); WRITE(FILEVAR4,FILE4REC); READ (FILEVAR4,FILE4REC); FILE4REC.X2 := FILE4REC.X2 + 1; SEEK (FILEVAR4,2); WRITE(FILEVAR4,FILE4REC); SEEK (FILEVAR4,FILESIZE(FILEVAR4)-1); { LAST RECORD IN FILE } READ (FILEVAR4,FILE4REC); FILE4REC.X1 := -4; { BEGIN CONCAVE GRAPH } FILE4REC.Y1 := -10; FILE4REC.X2 := -10; FILE4REC.Y2 := -10; SEEK (FILEVAR4,FILESIZE(FILEVAR4)-1); WRITE(FILEVAR4,FILE4REC); FILE4REC.X1 := SXLOW; { BUILD SECOND HEADER } FILE4REC.Y1 := SYLOW; FILE4REC.Z1 := SZLOW; FILE4REC.X2 := SXHIGH; FILE4REC.Y2 := SYHIGH; FILE4REC.Z2 := SZHIGH; FILE4REC.LINE_TYPE := TOTAL_POINTS; WRITE(FILEVAR4,FILE4REC); { WRITE OUT THE CONCAVE POLYGON VECTORS } FILE4REC.Z1 := 0.0; FILE4REC.Z2 := 0.0; FILE4REC.LINE_TYPE := 1; FOR I := 1 TO JH-1 DO BEGIN FILE4REC.X1 := XHPOINTS[I]; FILE4REC.Y1 := YHPOINTS[I]; FILE4REC.X2 := XHPOINTS[I+1]; FILE4REC.Y2 := YHPOINTS[I+1]; WRITE(FILEVAR4,FILE4REC); END; FOR I := 1 TO JL-1 DO BEGIN FILE4REC.X1 := XLPOINTS[I]; FILE4REC.Y1 := YLPOINTS[I]; FILE4REC.X2 := XLPOINTS[I+1]; FILE4REC.Y2 := YLPOINTS[I+1]; WRITE(FILEVAR4,FILE4REC); END; { WRITE OUT THE TRAILING RECORD } FILE4REC.X1 := 0.0; FILE4REC.Y1 := 0.0; FILE4REC.X2 := 0.0; FILE4REC.Y2 := 0.0; FILE4REC.LINE_TYPE := 0; WRITE(FILEVAR4,FILE4REC); END; { IF KEYVALUE := Y } END; { IF REPLAYFILE <> '' }; KEYBOARD_PAUSE; KEYVALUE := 'R'; TEXTMODE; IF STUDYOPEN THEN CLOSE(FILEVAR3); IF REPLAYOPEN THEN CLOSE(FILEVAR4); END; { IF DRAWCHAR = Y } CLOSE (FILEVAR2); END; { CONCAVE_HULL PROCEDURE } BEGIN { CONCAVE_HULL_MENU PROCEDURE } { Display the options menu for the Concave Hull procedure } GRID_NUM := 20; KEYVALUE := 'R'; WHILE KEYVALUE = 'R' DO BEGIN CLRSCR; DISPLAY_COLOR(CYAN); LINE_OUT(28,2,'(7) Concave Polygon Algorithm'); LINE_OUT(10,4,'1 Data file:'); LINE_OUT(10,6,'2 Study area file:'); LINE_OUT(10,8,'3 Plot replay file:'); LINE_OUT(10,10,'4 Text output displayed on:'); LINE_OUT(10,12,'5 Graphics displayed on screen (Y|N):'); LINE_OUT(10,14,'6 Area accuracy method (I|G):'); LINE_OUT(10,16,'7 Width of a grid cell in meters:'); LINE_OUT(10,18,'8 Scale of your map as meters between adjacent coordinates: '); TEXTCOLOR(YELLOW); LINE_OUT(24,4,FILEOUT); LINE_OUT(30,6,STUDYFILE); LINE_OUT(31,8,REPLAYFILE); CASE UPCASE(PRINTCHAR) OF 'D' : PRINTSTR := 'DISPLAY ONLY'; 'P' : PRINTSTR := 'PRINTER ONLY'; 'B' : PRINTSTR := 'BOTH DISPLAY AND PRINTER'; END; LINE_OUT(39,10,PRINTSTR); IF DRAWCHAR = 'N' THEN DRAWSTR := 'NO' ELSE DRAWSTR := 'YES'; LINE_OUT(49,12,DRAWSTR); IF PRECISION = 'I' THEN LINE_OUT(41,14,'INTEGRATION') ELSE LINE_OUT(41,14,'GRID CELL COUNT'); GOTOXY(45,16); WRITE (SECTION_VALUE:8:4); GOTOXY(71,18); WRITE (METER_VALUE:8:4); DISPLAY_COLOR(RED); LINE_OUT(7,21,'P Process Data'); LINE_OUT(37,21,'E Exit to Main Menu'); TEXTCOLOR(YELLOW); GOTOXY(1,24); KEYVALUE := ' '; WHILE NOT (UPCASE(KEYVALUE) IN [ 'E','R']) DO BEGIN KEYVALUE := ' '; WHILE NOT (UPCASE(KEYVALUE) IN ['1'..'8','E','P']) DO READ (KBD,KEYVALUE); KEYVALUE := UPCASE(KEYVALUE); GOTOXY(1,23); DELLINE; DELLINE; CASE KEYVALUE OF '1': MENU_CALL(1); '2': MENU_CALL(2); '3': MENU_CALL(3); '4': MENU_CALL(4); '5': MENU_CALL(5); '6': MENU_CALL(6); '7': MENU_CALL(7); '8': MENU_CALL(8); 'P': BEGIN KEEP_GOING := TRUE; PROCESSING_VERIFY; IF (KEEP_GOING) AND (SECTION_VALUE <= 0) THEN BEGIN LINE_OUT(1,23,'A grid cell value greater than 0 must be given.'); KEEP_GOING := FALSE; END; IF (KEEP_GOING) AND (METER_VALUE <=0) THEN BEGIN LINE_OUT(1,23,'The distance from 1.0 to 2.0 must be given.'); KEEP_GOING := FALSE; END; IF KEEP_GOING THEN BEGIN CLRSCR; CONCAVE_HULL; END END; { CASE P } END; { CASE KEYVALUE OF } GOTOXY(1,25); END; { WHILE NOT (KEYVALUE IN ['E','R']) } END; { WHILE KEYVALUE = 'R' } KEYVALUE := ' ' END; { CONCAVE_HULL_MENU }