home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1999 mARCH
/
PCWK3A99.iso
/
Linux
/
DDD331
/
DDD-3_1_.000
/
DDD-3_1_
/
ddd-3.1.1
/
ddd
/
GraphEdge.C
< prev
next >
Wrap
C/C++ Source or Header
|
1998-03-25
|
7KB
|
306 lines
// $Id: GraphEdge.C,v 1.7 1998/03/25 12:43:17 zeller Exp $
// GraphEdge class
// Copyright (C) 1995 Technische Universitaet Braunschweig, Germany.
// Written by Andreas Zeller <zeller@ips.cs.tu-bs.de>.
//
// This file is part of DDD.
//
// DDD is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// DDD is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with DDD -- see the file COPYING.
// If not, write to the Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// DDD is the data display debugger.
// For details, see the DDD World-Wide-Web page,
// `http://www.cs.tu-bs.de/softech/ddd/',
// or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
char GraphEdge_rcsid[] =
"$Id: GraphEdge.C,v 1.7 1998/03/25 12:43:17 zeller Exp $";
#ifdef __GNUG__
#pragma implementation
#endif
#include "GraphEdge.h"
#include "GraphNode.h"
#include "printBox.h"
#include <stdlib.h>
DEFINE_TYPE_INFO_0(GraphEdge)
void GraphEdge::enqueue()
{
assert (_nextFrom == 0);
assert (_nextTo == 0);
assert (_prevFrom == 0);
assert (_prevTo == 0);
if (from()->_firstFrom == 0)
{
_nextFrom = this;
_prevFrom = this;
from()->_firstFrom = this;
}
else
{
_nextFrom = from()->_firstFrom->_nextFrom;
_prevFrom = from()->_firstFrom;
_nextFrom->_prevFrom = this;
_prevFrom->_nextFrom = this;
}
if (to()->_firstTo == 0)
{
_nextTo = this;
_prevTo = this;
to()->_firstTo = this;
}
else
{
_nextTo = to()->_firstTo->_nextTo;
_prevTo = to()->_firstTo;
_nextTo->_prevTo = this;
_prevTo->_nextTo = this;
}
}
void GraphEdge::dequeue()
{
// dequeue from "from" chain
if (_nextFrom != 0 || _prevFrom != 0)
{
assert(_nextFrom != 0);
assert(_prevFrom != 0);
if (_from->_firstFrom == this)
_from->_firstFrom = _nextFrom;
if (_from->_firstFrom == this)
{
assert(_nextFrom == this);
assert(_prevFrom == this);
_from->_firstFrom = 0;
}
else
{
_nextFrom->_prevFrom = _prevFrom;
_prevFrom->_nextFrom = _nextFrom;
}
_nextFrom = 0;
_prevFrom = 0;
}
// dequeue from "to" chain
if (_nextTo != 0 || _prevTo != 0)
{
assert(_nextTo != 0);
assert(_prevTo != 0);
if (_to->_firstTo == this)
_to->_firstTo = _nextTo;
if (_to->_firstTo == this)
{
assert(_nextTo == this);
assert(_prevTo == this);
_to->_firstTo = 0;
}
else
{
_nextTo->_prevTo = _prevTo;
_prevTo->_nextTo = _nextTo;
}
_nextTo = 0;
_prevTo = 0;
}
}
ostream& operator << (ostream& s, GraphEdge& e)
{
return s << "( " << *(e.from()) << " -> " << *(e.to()) << " )";
}
// representation invariant
bool GraphEdge::OK() const
{
GraphEdge *e;
// assert that prev/next is okay
assert(_nextTo == 0 || _nextTo->_prevTo == this);
assert(_prevTo == 0 || _prevTo->_nextTo == this);
assert(_nextFrom == 0 || _nextFrom->_prevFrom == this);
assert(_prevFrom == 0 || _prevFrom->_nextFrom == this);
// assert that this is contained in from and to lists
if (_nextFrom || _prevFrom)
{
for (e = from()->firstFrom(); e != 0 && e != this;
e = from()->nextFrom(e))
;
assert(e == this);
}
if (_nextTo || _prevTo)
{
for (e = to()->firstTo(); e != 0 && e != this;
e = to()->nextTo(e))
;
assert(e == this);
}
return true;
}
// printing
// internal types
enum Side { North = 1 , South = 2 , East = 4 , West = 8 } ;
// prototypes for internal usage
static Side crosside (BoxRegion ®ion, BoxPoint &p) ;
static BoxPoint crosspoint (BoxRegion ®ion, BoxPoint &p);
//
// crossside
//
static Side crosside (BoxRegion ®ion, BoxPoint &p)
{
BoxPoint center = region.origin() + (region.space() / BoxPoint(2)) ;
BoxPoint delta = center - p ;
int side = North | South | East | West ;
// exclude opposite side
if (p[X] > center[X])
side &= ~West ;
else
side &= ~East ;
if (p[Y] > center[Y])
side &= ~North ;
else
side &= ~South ;
delta[X] = abs(delta[X]);
delta[Y] = abs(delta[Y]);
if (region.space(Y) * delta[X] > region.space(X) * delta[Y])
side &= ~(North | South);
else
side &= ~(East | West);
return Side(side);
}
//
// crosspoint
//
static BoxPoint crosspoint (BoxRegion ®ion, BoxPoint &p)
{
int side = crosside (region, p);
BoxDimension d1, d2;
BoxPoint center = region.origin() + (region.space() / BoxPoint(2)) ;
BoxPoint cross = center;
int offset;
offset = (side & (North | West)? -1 : 1) ;
if (side & (North | South)) {
d1 = X ;
d2 = Y ;
} else {
d1 = Y ;
d2 = X ;
}
if (center[d1] != p[d1] && center[d2] != p[d2]) {
cross[d1] += offset * (region.space(d2) / 2)
* ( center[d1] - p[d1]) / ( center[d2] - p[d2] ) ;
}
cross[d2] += offset * region.space(d2) / 2;
return cross ;
}
//
// drawEdge
//
void GraphEdge::_print(ostream& os, const GraphGC &gc) const
{
// Don't print if we're hidden
if (hidden())
return;
// Fetch the regions
BoxRegion start = from()->region(gc);
BoxRegion end = to()->region(gc);
// Don't print edges with zero length
if (start <= end)
return;
BoxPoint startc = start.origin() + (start.space() / BoxPoint(2));
BoxPoint endc = end.origin() + (end.space() / BoxPoint(2));
BoxPoint startp = crosspoint (start, endc);
BoxPoint endp = crosspoint (end, startc);
// This should come from gc.edgeGC
BoxCoordinate line_width = 1;
if (gc.printGC->isFig()) {
if (!gc.drawArrowHeads || to()->isHint()) {
os << EDGEHEAD1 << line_width;
os << EDGEHEAD2 ;
os << startp[X] << " " << startp[Y] << " " ;
os << endp[X] << " " << endp[Y] << " " ;
os << "9999 9999\n" ;
} else {
os << ARROWHEAD1 << line_width;
os << ARROWHEAD2 ;
os << startp[X] << " " << startp[Y] << " " ;
os << endp[X] << " " << endp[Y] << " " ;
os << "9999 9999\n" ;
}
} else if (gc.printGC->isPostScript()) {
if (!gc.drawArrowHeads || to()->isHint()) {
os << startp[X] << " " << startp[Y] << " " ;
os << endp[X] << " " << endp[Y] << " " ;
os << line_width << " line*\n";
} else {
os << gc.arrowAngle << " " << gc.arrowLength << " ";
os << startp[X] << " " << startp[Y] << " " ;
os << endp[X] << " " << endp[Y] << " " ;
os << line_width << " arrowline*\n";
}
}
}