home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
pmos2002.zip
/
SRC
/
SCREENGE.MOD
< prev
next >
Wrap
Text File
|
1996-11-05
|
7KB
|
190 lines
IMPLEMENTATION MODULE ScreenGeometry;
(********************************************************)
(* *)
(* Support module for screen graphics *)
(* *)
(* Programmer: P. Moylan *)
(* Last edited: 5 November 1996 *)
(* Status: Working *)
(* *)
(* Might be worth looking for a better algorithm *)
(* for SolveForX and SolveForY - see module *)
(* RawGraphics, where I think I've done it better. *)
(* *)
(********************************************************)
(************************************************************************)
PROCEDURE Inside (x, y: INTEGER; R: Rectangle): BOOLEAN;
(* Returns TRUE iff point (x,y) is in (or on the border of) R. *)
BEGIN
WITH R DO
RETURN (x >= left) AND (x <= right)
AND (y >= bottom) AND (y <= top);
END (*WITH*);
END Inside;
(************************************************************************)
PROCEDURE Adjacent (R1, R2: Rectangle;
VAR (*OUT*) union: Rectangle): BOOLEAN;
(* If the union of R1 and R2 is itself a rectangle, returns TRUE *)
(* and sets "union" to be the combined rectangle. Otherwise *)
(* returns FALSE, and the "union" result is meaningless. *)
BEGIN
union := R1;
IF R1.top = R2.top THEN
(* Possible left/right adjacency *)
IF R1.bottom = R2.bottom THEN
IF R2.left = R1.right + 1 THEN
union.right := R2.right;
RETURN TRUE;
ELSIF R1.left = R2.right + 1 THEN
union.left := R2.left;
RETURN TRUE;
ELSE
RETURN FALSE;
END (*IF*);
ELSE
RETURN FALSE;
END (*IF*);
ELSIF R1.left = R2.left THEN
(* Possible above/below adjacency *)
IF R1.right = R2.right THEN
IF R2.bottom = R1.top + 1 THEN
union.top := R2.top;
RETURN TRUE;
ELSIF R1.bottom = R2.top + 1 THEN
union.bottom := R2.bottom;
RETURN TRUE;
ELSE
RETURN FALSE;
END (*IF*);
ELSE
RETURN FALSE;
END (*IF*);
ELSE
RETURN FALSE;
END (*IF*);
END Adjacent;
(************************************************************************)
PROCEDURE SolveForX (end1, end2: Point; y: INTEGER): INTEGER;
(* Returns the x value for which the line with endpoints end1 and *)
(* end2 passes through the point (x,y). *)
VAR x1, x2, y1, y2, temp: INTEGER;
BEGIN
x1 := end1.x; y1 := end1.y;
x2 := end2.x; y2 := end2.y;
IF y1 > y2 THEN
temp := x1; x1 := x2; x2 := temp;
temp := y1; y1 := y2; y2 := temp;
END (*IF*);
RETURN (y*(x2-x1) - x2*y1 + x1*y2 + (y2-y1) DIV 2 + 1) DIV (y2-y1);
END SolveForX;
(************************************************************************)
PROCEDURE SolveForY (end1, end2: Point; x: INTEGER): INTEGER;
(* Returns the y value for which the line with endpoints end1 and *)
(* end2 passes through the point (x,y). *)
VAR x1, x2, y1, y2, temp: INTEGER;
BEGIN
x1 := end1.x; y1 := end1.y;
x2 := end2.x; y2 := end2.y;
IF x1 > x2 THEN
temp := x1; x1 := x2; x2 := temp;
temp := y1; y1 := y2; y2 := temp;
END (*IF*);
RETURN (x*(y2-y1) - y2*x1 + y1*x2 + (x2-x1) DIV 2 + 1) DIV (x2-x1);
END SolveForY;
(************************************************************************)
PROCEDURE TrimLine (VAR (*INOUT*) end1, end2: Point; R: Rectangle): BOOLEAN;
(* Modifies end1 and end2, if necessary, to cut off the ends of *)
(* the line from end1 to end2 which do not fit in R. *)
(* Returns FALSE if none of the line passes through the rectangle. *)
VAR temp: Point; result: INTEGER;
BEGIN
(* Check the bottom and top of the rectangle. *)
IF end1.y > end2.y THEN
temp := end1; end1 := end2; end2 := temp;
END (*IF*);
(* Exclude some special cases, to avoid overflow problems. *)
IF (end2.y < R.bottom) OR (end1.y > R.top) THEN
RETURN FALSE;
END (*IF*);
IF end1.y < R.bottom THEN
result := SolveForX (end1, end2, R.bottom);
IF (result < R.left) OR (result > R.right) THEN
RETURN FALSE;
END (*IF*);
end1.x := result;
end1.y := R.bottom;
END (*IF*);
IF end2.y > R.top THEN
result := SolveForX (end1, end2, R.top);
IF (result < R.left) OR (result > R.right) THEN
RETURN FALSE;
END (*IF*);
end2.x := result;
end2.y := R.top;
END (*IF*);
(* Check the left and right of the rectangle. *)
IF end1.x > end2.x THEN
temp := end1; end1 := end2; end2 := temp;
END (*IF*);
(* Exclude some special cases, to avoid overflow problems. *)
IF (end2.x < R.left) OR (end1.x > R.right) THEN
RETURN FALSE;
END (*IF*);
IF end1.x < R.left THEN
result := SolveForY (end1, end2, R.left);
IF (result < R.bottom) OR (result > R.top) THEN
RETURN FALSE;
END (*IF*);
end1.y := result;
end1.x := R.left;
END (*IF*);
IF end2.x > R.right THEN
result := SolveForY (end1, end2, R.right);
IF (result < R.bottom) OR (result > R.top) THEN
RETURN FALSE;
END (*IF*);
end2.y := result;
end2.x := R.right;
END (*IF*);
RETURN TRUE;
END TrimLine;
END ScreenGeometry.