2007-03-08 04:03:40 +08:00
|
|
|
/**********************************************************************
|
|
|
|
* File: rect.h (Formerly box.h)
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
#ifndef RECT_H
|
|
|
|
#define RECT_H
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include "points.h"
|
|
|
|
#include "ndminx.h"
|
|
|
|
#include "tprintf.h"
|
2008-02-01 08:36:18 +08:00
|
|
|
#include "scrollview.h"
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
class DLLSYM TBOX //bounding box
|
2007-03-08 04:03:40 +08:00
|
|
|
{
|
|
|
|
public:
|
2008-04-22 08:41:37 +08:00
|
|
|
TBOX (): //empty constructor
|
2007-03-08 04:03:40 +08:00
|
|
|
bot_left (MAX_INT16, MAX_INT16), top_right (-MAX_INT16, -MAX_INT16) {
|
|
|
|
} //null box
|
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
TBOX( //constructor
|
2007-03-08 04:03:40 +08:00
|
|
|
const ICOORD pt1, //one corner
|
|
|
|
const ICOORD pt2); //the other corner
|
2008-04-22 08:41:37 +08:00
|
|
|
TBOX( //box around FCOORD
|
2007-03-08 04:03:40 +08:00
|
|
|
const FCOORD pt);
|
|
|
|
|
|
|
|
BOOL8 null_box() const { //Is box null
|
|
|
|
return ((left () > right ()) || (top () < bottom ()));
|
|
|
|
}
|
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
inT16 top() const { // coord of top
|
2007-03-08 04:03:40 +08:00
|
|
|
return top_right.y ();
|
|
|
|
}
|
2008-12-31 05:31:01 +08:00
|
|
|
void set_top(int y) {
|
|
|
|
top_right.set_y(y);
|
|
|
|
}
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
inT16 bottom() const { // coord of bottom
|
2007-03-08 04:03:40 +08:00
|
|
|
return bot_left.y ();
|
|
|
|
}
|
2008-12-31 05:31:01 +08:00
|
|
|
void set_bottom(int y) {
|
|
|
|
bot_left.set_y(y);
|
|
|
|
}
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
inT16 left() const { // coord of left
|
2007-03-08 04:03:40 +08:00
|
|
|
return bot_left.x ();
|
|
|
|
}
|
2008-12-31 05:31:01 +08:00
|
|
|
void set_left(int x) {
|
|
|
|
bot_left.set_x(x);
|
|
|
|
}
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
inT16 right() const { // coord of right
|
2007-03-08 04:03:40 +08:00
|
|
|
return top_right.x ();
|
|
|
|
}
|
2008-12-31 05:31:01 +08:00
|
|
|
void set_right(int x) {
|
|
|
|
top_right.set_x(x);
|
|
|
|
}
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
//access function
|
|
|
|
const ICOORD &botleft() const {
|
|
|
|
return bot_left;
|
|
|
|
}
|
|
|
|
|
|
|
|
ICOORD botright() const { // ~ access function
|
|
|
|
return ICOORD (top_right.x (), bot_left.y ());
|
|
|
|
}
|
|
|
|
|
|
|
|
ICOORD topleft() const { // ~ access function
|
|
|
|
return ICOORD (bot_left.x (), top_right.y ());
|
|
|
|
}
|
|
|
|
|
|
|
|
//access function
|
|
|
|
const ICOORD &topright() const {
|
|
|
|
return top_right;
|
|
|
|
}
|
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
inT16 height() const { //how high is it?
|
2007-03-08 04:03:40 +08:00
|
|
|
if (!null_box ())
|
|
|
|
return top_right.y () - bot_left.y ();
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
inT16 width() const { //how high is it?
|
2007-03-08 04:03:40 +08:00
|
|
|
if (!null_box ())
|
|
|
|
return top_right.x () - bot_left.x ();
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
inT32 area() const { //what is the area?
|
2007-03-08 04:03:40 +08:00
|
|
|
if (!null_box ())
|
|
|
|
return width () * height ();
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void move_bottom_edge( // move one edge
|
2008-04-22 08:41:37 +08:00
|
|
|
const inT16 y) { // by +/- y
|
2007-03-08 04:03:40 +08:00
|
|
|
bot_left += ICOORD (0, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
void move_left_edge( // move one edge
|
2008-04-22 08:41:37 +08:00
|
|
|
const inT16 x) { // by +/- x
|
2007-03-08 04:03:40 +08:00
|
|
|
bot_left += ICOORD (x, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void move_right_edge( // move one edge
|
2008-04-22 08:41:37 +08:00
|
|
|
const inT16 x) { // by +/- x
|
2007-03-08 04:03:40 +08:00
|
|
|
top_right += ICOORD (x, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void move_top_edge( // move one edge
|
2008-04-22 08:41:37 +08:00
|
|
|
const inT16 y) { // by +/- y
|
2007-03-08 04:03:40 +08:00
|
|
|
top_right += ICOORD (0, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
void move( // move box
|
|
|
|
const ICOORD vec) { // by vector
|
|
|
|
bot_left += vec;
|
|
|
|
top_right += vec;
|
|
|
|
}
|
|
|
|
|
|
|
|
void move( // move box
|
|
|
|
const FCOORD vec) { // by float vector
|
2008-04-22 08:41:37 +08:00
|
|
|
bot_left.set_x ((inT16) floor (bot_left.x () + vec.x ()));
|
2007-03-08 04:03:40 +08:00
|
|
|
//round left
|
2008-04-22 08:41:37 +08:00
|
|
|
bot_left.set_y ((inT16) floor (bot_left.y () + vec.y ()));
|
2007-03-08 04:03:40 +08:00
|
|
|
//round down
|
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
top_right.set_x ((inT16) ceil (top_right.x () + vec.x ()));
|
2007-03-08 04:03:40 +08:00
|
|
|
//round right
|
2008-04-22 08:41:37 +08:00
|
|
|
top_right.set_y ((inT16) ceil (top_right.y () + vec.y ()));
|
2007-03-08 04:03:40 +08:00
|
|
|
//round up
|
|
|
|
}
|
|
|
|
|
|
|
|
void scale( // scale box
|
|
|
|
const float f) { // by multiplier
|
|
|
|
//round left
|
2008-04-22 08:41:37 +08:00
|
|
|
bot_left.set_x ((inT16) floor (bot_left.x () * f));
|
2007-03-08 04:03:40 +08:00
|
|
|
//round down
|
2008-04-22 08:41:37 +08:00
|
|
|
bot_left.set_y ((inT16) floor (bot_left.y () * f));
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
top_right.set_x ((inT16) ceil (top_right.x () * f));
|
2007-03-08 04:03:40 +08:00
|
|
|
//round right
|
2008-04-22 08:41:37 +08:00
|
|
|
top_right.set_y ((inT16) ceil (top_right.y () * f));
|
2007-03-08 04:03:40 +08:00
|
|
|
//round up
|
|
|
|
}
|
|
|
|
void scale( // scale box
|
|
|
|
const FCOORD vec) { // by float vector
|
2008-04-22 08:41:37 +08:00
|
|
|
bot_left.set_x ((inT16) floor (bot_left.x () * vec.x ()));
|
|
|
|
bot_left.set_y ((inT16) floor (bot_left.y () * vec.y ()));
|
|
|
|
top_right.set_x ((inT16) ceil (top_right.x () * vec.x ()));
|
|
|
|
top_right.set_y ((inT16) ceil (top_right.y () * vec.y ()));
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void rotate( //rotate coords
|
|
|
|
const FCOORD vec) { //by vector
|
|
|
|
bot_left.rotate (vec);
|
|
|
|
top_right.rotate (vec);
|
2008-04-22 08:41:37 +08:00
|
|
|
*this = TBOX (bot_left, top_right);
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL8 contains( //is pt inside box
|
|
|
|
const FCOORD pt) const;
|
|
|
|
|
|
|
|
BOOL8 contains( //is box inside box
|
2008-04-22 08:41:37 +08:00
|
|
|
const TBOX &box) const;
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2008-12-31 05:31:01 +08:00
|
|
|
// Do boxes overlap on x axis.
|
|
|
|
BOOL8 x_overlap(const TBOX &box) const;
|
|
|
|
|
|
|
|
// Do boxes overlap on x axis by more than
|
|
|
|
// half of the width of the narrower box.
|
|
|
|
BOOL8 major_x_overlap(const TBOX &box) const;
|
|
|
|
|
2007-03-08 04:03:40 +08:00
|
|
|
BOOL8 overlap( //do boxes overlap
|
2008-04-22 08:41:37 +08:00
|
|
|
const TBOX &box) const;
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2008-12-31 05:31:01 +08:00
|
|
|
BOOL8 major_overlap( // do boxes overlap more than half
|
2008-04-22 08:41:37 +08:00
|
|
|
const TBOX &box) const;
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
TBOX intersection( //shared area box
|
|
|
|
const TBOX &box) const;
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
TBOX bounding_union( //box enclosing both
|
|
|
|
const TBOX &box) const;
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
void print() { //print
|
|
|
|
tprintf ("Bounding box=(%d,%d)->(%d,%d)\n",
|
|
|
|
left (), bottom (), right (), top ());
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef GRAPHICS_DISABLED
|
|
|
|
void plot( //use current settings
|
2008-02-01 08:36:18 +08:00
|
|
|
ScrollView* fd) const { //where to paint
|
|
|
|
fd->Rectangle(bot_left.x (), bot_left.y (), top_right.x (),
|
2007-03-08 04:03:40 +08:00
|
|
|
top_right.y ());
|
|
|
|
}
|
|
|
|
|
|
|
|
void plot( //paint box
|
2008-02-01 08:36:18 +08:00
|
|
|
ScrollView* fd, //where to paint
|
|
|
|
ScrollView::Color fill_colour, //colour for inside
|
|
|
|
ScrollView::Color border_colour) const; //colour for border
|
2007-03-08 04:03:40 +08:00
|
|
|
#endif
|
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
friend DLLSYM TBOX & operator+= (TBOX &, const TBOX &);
|
2007-03-08 04:03:40 +08:00
|
|
|
//in place union
|
2008-04-22 08:41:37 +08:00
|
|
|
friend DLLSYM TBOX & operator-= (TBOX &, const TBOX &);
|
2007-03-08 04:03:40 +08:00
|
|
|
//in place intrsection
|
|
|
|
|
|
|
|
void serialise_asc( //convert to ascii
|
|
|
|
FILE *f);
|
|
|
|
void de_serialise_asc( //convert from ascii
|
|
|
|
FILE *f);
|
|
|
|
|
|
|
|
private:
|
|
|
|
ICOORD bot_left; //bottom left corner
|
|
|
|
ICOORD top_right; //top right corner
|
|
|
|
};
|
|
|
|
|
|
|
|
/**********************************************************************
|
2008-04-22 08:41:37 +08:00
|
|
|
* TBOX::TBOX() Constructor from 1 FCOORD
|
2007-03-08 04:03:40 +08:00
|
|
|
*
|
|
|
|
**********************************************************************/
|
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
inline TBOX::TBOX( //construtor
|
2007-03-08 04:03:40 +08:00
|
|
|
const FCOORD pt //floating centre
|
|
|
|
) {
|
2008-04-22 08:41:37 +08:00
|
|
|
bot_left = ICOORD ((inT16) floor (pt.x ()), (inT16) floor (pt.y ()));
|
|
|
|
top_right = ICOORD ((inT16) ceil (pt.x ()), (inT16) ceil (pt.y ()));
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
2008-04-22 08:41:37 +08:00
|
|
|
* TBOX::contains() Is point within box
|
2007-03-08 04:03:40 +08:00
|
|
|
*
|
|
|
|
**********************************************************************/
|
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
inline BOOL8 TBOX::contains(const FCOORD pt) const {
|
2007-03-08 04:03:40 +08:00
|
|
|
return ((pt.x () >= bot_left.x ()) &&
|
|
|
|
(pt.x () <= top_right.x ()) &&
|
|
|
|
(pt.y () >= bot_left.y ()) && (pt.y () <= top_right.y ()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
2008-04-22 08:41:37 +08:00
|
|
|
* TBOX::contains() Is box within box
|
2007-03-08 04:03:40 +08:00
|
|
|
*
|
|
|
|
**********************************************************************/
|
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
inline BOOL8 TBOX::contains(const TBOX &box) const {
|
2007-03-08 04:03:40 +08:00
|
|
|
return (contains (box.bot_left) && contains (box.top_right));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
2008-04-22 08:41:37 +08:00
|
|
|
* TBOX::overlap() Do two boxes overlap?
|
2007-03-08 04:03:40 +08:00
|
|
|
*
|
|
|
|
**********************************************************************/
|
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
inline BOOL8 TBOX::overlap( //do boxes overlap
|
|
|
|
const TBOX &box) const {
|
2007-03-08 04:03:40 +08:00
|
|
|
return ((box.bot_left.x () <= top_right.x ()) &&
|
|
|
|
(box.top_right.x () >= bot_left.x ()) &&
|
|
|
|
(box.bot_left.y () <= top_right.y ()) &&
|
|
|
|
(box.top_right.y () >= bot_left.y ()));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************
|
2008-04-22 08:41:37 +08:00
|
|
|
* TBOX::major_overlap() Do two boxes overlap by at least half of the smallest?
|
2007-03-08 04:03:40 +08:00
|
|
|
*
|
|
|
|
**********************************************************************/
|
|
|
|
|
2008-04-22 08:41:37 +08:00
|
|
|
inline BOOL8 TBOX::major_overlap( // Do boxes overlap more that half.
|
|
|
|
const TBOX &box) const {
|
2007-03-08 04:03:40 +08:00
|
|
|
int overlap = MIN(box.top_right.x(), top_right.x());
|
|
|
|
overlap -= MAX(box.bot_left.x(), bot_left.x());
|
|
|
|
overlap += overlap;
|
|
|
|
if (overlap < MIN(box.width(), width()))
|
|
|
|
return false;
|
|
|
|
overlap = MIN(box.top_right.y(), top_right.y());
|
|
|
|
overlap -= MAX(box.bot_left.y(), bot_left.y());
|
|
|
|
overlap += overlap;
|
|
|
|
if (overlap < MIN(box.height(), height()))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
2008-12-31 05:31:01 +08:00
|
|
|
|
|
|
|
inline BOOL8 TBOX::x_overlap(const TBOX &box) const {
|
|
|
|
return ((box.bot_left.x() <= top_right.x()) &&
|
|
|
|
(box.top_right.x() >= bot_left.x()));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline BOOL8 TBOX::major_x_overlap(const TBOX &box) const {
|
|
|
|
inT16 overlap = box.width();
|
|
|
|
if (this->left() > box.left()) {
|
|
|
|
overlap -= this->left() - box.left();
|
|
|
|
}
|
|
|
|
if (this->right() < box.right()) {
|
|
|
|
overlap -= box.right() - this->right();
|
|
|
|
}
|
|
|
|
return (overlap >= box.width() / 2 || overlap >= this->width() / 2);
|
|
|
|
}
|
2007-03-08 04:03:40 +08:00
|
|
|
#endif
|