blob: 1c922928ee5ce79ca7472e735d952062eaea470f [file] [log] [blame]
/**********************************************************************
* File: rect.c (Formerly box.c)
* Description: Bounding box class definition.
* Author: Phil Cheatle
* Created: Wed Oct 16 15:18:45 BST 1991
*
* (C) Copyright 1991, Hewlett-Packard Ltd.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#include "mfcpch.h" //precompiled headers
#include "rect.h"
/**********************************************************************
* TBOX::TBOX() Constructor from 2 ICOORDS
*
**********************************************************************/
TBOX::TBOX( //construtor
const ICOORD pt1, //one corner
const ICOORD pt2 //the other corner
) {
if (pt1.x () <= pt2.x ()) {
if (pt1.y () <= pt2.y ()) {
bot_left = pt1;
top_right = pt2;
}
else {
bot_left = ICOORD (pt1.x (), pt2.y ());
top_right = ICOORD (pt2.x (), pt1.y ());
}
}
else {
if (pt1.y () <= pt2.y ()) {
bot_left = ICOORD (pt2.x (), pt1.y ());
top_right = ICOORD (pt1.x (), pt2.y ());
}
else {
bot_left = pt2;
top_right = pt1;
}
}
}
/**********************************************************************
* TBOX::TBOX() Constructor from 4 integer values.
* Note: It is caller's responsibility to provide values in the right
* order.
**********************************************************************/
TBOX::TBOX( //constructor
inT16 left, inT16 bottom, inT16 right, inT16 top)
: bot_left(left, bottom), top_right(right, top) {
}
// rotate_large constructs the containing bounding box of all 4
// corners after rotating them. It therefore guarantees that all
// original content is contained within, but also slightly enlarges the box.
void TBOX::rotate_large(const FCOORD& vec) {
ICOORD top_left(bot_left.x(), top_right.y());
ICOORD bottom_right(top_right.x(), bot_left.y());
top_left.rotate(vec);
bottom_right.rotate(vec);
rotate(vec);
TBOX box2(top_left, bottom_right);
*this += box2;
}
/**********************************************************************
* TBOX::intersection() Build the largest box contained in both boxes
*
**********************************************************************/
TBOX TBOX::intersection( //shared area box
const TBOX &box) const {
inT16 left;
inT16 bottom;
inT16 right;
inT16 top;
if (overlap (box)) {
if (box.bot_left.x () > bot_left.x ())
left = box.bot_left.x ();
else
left = bot_left.x ();
if (box.top_right.x () < top_right.x ())
right = box.top_right.x ();
else
right = top_right.x ();
if (box.bot_left.y () > bot_left.y ())
bottom = box.bot_left.y ();
else
bottom = bot_left.y ();
if (box.top_right.y () < top_right.y ())
top = box.top_right.y ();
else
top = top_right.y ();
}
else {
left = MAX_INT16;
bottom = MAX_INT16;
top = -MAX_INT16;
right = -MAX_INT16;
}
return TBOX (left, bottom, right, top);
}
/**********************************************************************
* TBOX::bounding_union() Build the smallest box containing both boxes
*
**********************************************************************/
TBOX TBOX::bounding_union( //box enclosing both
const TBOX &box) const {
ICOORD bl; //bottom left
ICOORD tr; //top right
if (box.bot_left.x () < bot_left.x ())
bl.set_x (box.bot_left.x ());
else
bl.set_x (bot_left.x ());
if (box.top_right.x () > top_right.x ())
tr.set_x (box.top_right.x ());
else
tr.set_x (top_right.x ());
if (box.bot_left.y () < bot_left.y ())
bl.set_y (box.bot_left.y ());
else
bl.set_y (bot_left.y ());
if (box.top_right.y () > top_right.y ())
tr.set_y (box.top_right.y ());
else
tr.set_y (top_right.y ());
return TBOX (bl, tr);
}
/**********************************************************************
* TBOX::plot() Paint a box using specified settings
*
**********************************************************************/
#ifndef GRAPHICS_DISABLED
void TBOX::plot( //paint box
ScrollView* fd, //where to paint
ScrollView::Color fill_colour, //colour for inside
ScrollView::Color border_colour //colour for border
) const {
fd->Brush(fill_colour);
fd->Pen(border_colour);
plot(fd);
}
#endif
/**********************************************************************
* operator+=
*
* Extend one box to include the other (In place union)
**********************************************************************/
DLLSYM TBOX &
operator+= ( //bounding bounding bx
TBOX & op1, //operands
const TBOX & op2) {
if (op2.bot_left.x () < op1.bot_left.x ())
op1.bot_left.set_x (op2.bot_left.x ());
if (op2.top_right.x () > op1.top_right.x ())
op1.top_right.set_x (op2.top_right.x ());
if (op2.bot_left.y () < op1.bot_left.y ())
op1.bot_left.set_y (op2.bot_left.y ());
if (op2.top_right.y () > op1.top_right.y ())
op1.top_right.set_y (op2.top_right.y ());
return op1;
}
/**********************************************************************
* operator-=
*
* Reduce one box to intersection with the other (In place intersection)
**********************************************************************/
DLLSYM TBOX &
operator-= ( //inplace intersection
TBOX & op1, //operands
const TBOX & op2) {
if (op1.overlap (op2)) {
if (op2.bot_left.x () > op1.bot_left.x ())
op1.bot_left.set_x (op2.bot_left.x ());
if (op2.top_right.x () < op1.top_right.x ())
op1.top_right.set_x (op2.top_right.x ());
if (op2.bot_left.y () > op1.bot_left.y ())
op1.bot_left.set_y (op2.bot_left.y ());
if (op2.top_right.y () < op1.top_right.y ())
op1.top_right.set_y (op2.top_right.y ());
}
else {
op1.bot_left.set_x (MAX_INT16);
op1.bot_left.set_y (MAX_INT16);
op1.top_right.set_x (-MAX_INT16);
op1.top_right.set_y (-MAX_INT16);
}
return op1;
}
/**********************************************************************
* TBOX::serialise_asc() Convert to ascii file.
*
**********************************************************************/
void TBOX::serialise_asc( //convert to ascii
FILE *f //file to use
) {
bot_left.serialise_asc (f);
top_right.serialise_asc (f);
}
/**********************************************************************
* TBOX::de_serialise_asc() Convert from ascii file.
*
**********************************************************************/
void TBOX::de_serialise_asc( //convert from ascii
FILE *f //file to use
) {
bot_left.de_serialise_asc (f);
top_right.de_serialise_asc (f);
}