You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdemultimedia/arts/builder/autorouter.h

185 lines
4.4 KiB

/*
Copyright (C) 1998 Stefan Westerfeld <stefan@space.twc.de>,
2002 Hans Meine <hans_meine@gmx.net>
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __AUTOROUTER_H_
#define __AUTOROUTER_H_
// If you get into trouble with threading (random crashes), you can configure
// things with --disable-threading, which should fix everything by not using
// threads
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_LIBPTHREAD
#include <pthread.h>
#endif
#include <tqptrlist.h>
#include <tqvaluelist.h>
class PathInfo
{
public:
int x1, x2, y1, y2, cost, depth;
TQString history;
int operator<(const PathInfo& x) const { return cost < x.cost; }
int operator==(const PathInfo& x) const { return cost == x.cost; }
};
typedef TQValueList<PathInfo> PathQueue;
class ARCommand;
/**
* The AutoRouter uses threads, commands are passed as objects via
* AutoRouter::enqueue() to the routing thread.
*/
class AutoRouter
{
public:
enum { none=0,up=1,down=2,left=4,right=8,head=16,tail=32,solid=64 };
enum Direction { DIR_NONE=0, DIR_UP, DIR_DOWN, DIR_LEFT, DIR_RIGHT };
protected:
int width, height;
enum OwnerType { OWNER_UD=0, OWNER_LR=1 };
OwnerType ownerIndex[DIR_RIGHT + 1]; // index is of type Direction
long directionMask[DIR_RIGHT + 1]; // index is of type Direction
struct Field
{
long data;
long minCost;
long penalty;
long owner[2];
} **field, **completeField;
long newOwner; // next free owner ID
long currentOwner;
bool _needRedraw;
PathInfo bestGoalPath;
PathQueue pathlist[1024];
int numQueuedPaths;
// pseudo random table for fast "random" decisions
enum { PRSIZE = 16 };
long pseudoRandomDir[PRSIZE];
int nextPR;
void initPseudoRandom();
/****** thread stuff *****/
#ifdef HAVE_LIBPTHREAD
pthread_mutex_t mutex_sync;
pthread_mutex_t mutex_queue;
pthread_t route_thread;
#endif
TQPtrList<ARCommand> command_queue;
bool thread_terminate_now;
/*************************/
void queuePath(const PathInfo &path);
void examinePath(const PathInfo &path);
public:
AutoRouter(int width, int height);
~AutoRouter();
// queries _needRedraw flag and deletes it
// (assuming that the client is smart and redraws when getting true ;)
bool needRedraw();
long get(int x, int y);
void getowners(int x, int y, long& ud_owner, long& lr_owner);
void enqueue(ARCommand *command);
// marks the entire field as unused
void clear();
// sets the
void set(int x1, int y1, int x2, int y2, long lt);
long connect(int x1, int y1, int x2, int y2, long owner);
//
void sync();
// the following functions are not for direct use; they're used
// for threading only
void thread_clear();
void thread_set(int x1, int y1, int x2, int y2, long lt);
void thread_connect(int x1, int y1, int x2, int y2, long owner);
void thread_sync();
void thread_command_loop();
};
/**
* The ARCommand classes are used to communicate with the routing
* thread, see AutoRouter::enqueue()
*/
class ARCommand
{
public:
virtual void execute(AutoRouter *autorouter) = 0;
// if a command is destructive (default: false), the command queue
// will be emptied before queuing this one, assuming it'll destroy
// results of all other commands anyway.
virtual bool isDestructive();
};
class ARClearCommand :public ARCommand
{
public:
void execute(AutoRouter *autorouter);
bool isDestructive();
};
class ARSyncCommand :public ARCommand
{
public:
void execute(AutoRouter *autorouter);
};
class ARConnectCommand :public ARCommand
{
int _x1, _y1, _x2, _y2;
long _owner;
public:
ARConnectCommand(int x1, int y1, int x2, int y2, long owner);
void execute(AutoRouter *autorouter);
};
class ARSetCommand :public ARCommand
{
private:
int _x1, _y1, _x2, _y2;
long _lt;
public:
ARSetCommand(int x1, int y1, int x2, int y2, long lt);
void execute(AutoRouter *autorouter);
};
#endif