Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

PALADIN / PROGRAM

.DOC
Скачиваний:
6
Добавлен:
16.04.2013
Размер:
66.05 Кб
Скачать

Приложение.

Текст основных процедур, реализующих алгоритм.

// file topology.h

// Cодержит определения основных классов

#include <graphics.h>

#include <stdio.h>

#include <iostream.h>

#include <fstream.h>

//

// topology.h

//

typedef unsigned int IntType;

enum TypeOfRibbon {Vertical, Gorizontical};

enum bool {false, true};

//

extern IntType SizeXLambda, SizeYLambda, WidthRibbon;

extern TypeOfRibbon RibbonType;

extern IntType XView, YView;

extern IntType MaxXLambda, MaxYLambda;

// Forward declaration for ArrayOfRibbons

class Topology;

//

class Ribbon {

public:

bool Corrected;

IntType X, Y, Len; // Start position of ribbon and length

friend ofstream& operator<<(ofstream& ofs, Ribbon& ribb);

friend ifstream& operator>>(ifstream& ifs, Ribbon& ribb);

void WriteToFile(FILE* fp);

void LoadFromFile(FILE* fp);

void ShowRibbon();

};

//

class ArrayOfRibbons {

//

friend class Topology;

class FragmentOfArray {

public:

FragmentOfArray* Next; // Point to next fragment of array

Ribbon* *Array; // Point to array of ribbons

};

protected:

IntType MaxF; // Size of first fragment of array

IntType MaxO; // Size of others fragments

IntType Total; // Current number of elements

FragmentOfArray* FirstFragment; // Point to first fragment

FragmentOfArray* CurrentFragment; // Point to current fragment

//

public:

IntType CurrentIndex; // Current index inside fragment

TypeOfRibbon RibbonsType;

ArrayOfRibbons() :

MaxF(500), MaxO(10), Total(0), CurrentIndex(0),

CurrentFragment(0), FirstFragment(0) {}

ArrayOfRibbons(IntType mF, IntType mO) :

MaxF(mF), MaxO(mO), Total(0), CurrentIndex(0),

CurrentFragment(0), FirstFragment(0) {}

~ArrayOfRibbons();

void EraseAll();

IntType NumberOfRibbons() { return Total; }

void Add(Ribbon* ribb);

Ribbon& operator[](IntType Index);

//

void ShowArray();

friend ostream& operator<<(ostream& os, ArrayOfRibbons& array);

};

//

//

class Topology {

protected:

IntType StepX, StepY;

IntType SpaceAtBottom;

IntType CurrentPage;

bool Passed;

long XScan, YScan;

void SortVert(); // Sort array of vertical ribbons

void SortGoriz(); // Sort array of gorizontal ribbons

public:

ArrayOfRibbons VertRibbons, GorizRibbons;

IntType MaxX, MaxY; //

IntType MinX, MinY; // Minimum distance bitween ribbons

Topology()

{

VertRibbons.RibbonsType = Vertical;

GorizRibbons.RibbonsType = Gorizontical;

MaxX = MaxY = 0;

MinX = MinY = 3;

CurrentPage = 0;

StepX = MinX;

StepY = MinY;

SpaceAtBottom = 16;

}

void AddVertRibbon(Ribbon* ribb);

void AddGorizRibbon(Ribbon* ribb);

bool IsEmpty(long XR, long YR, long XL, long YL);

bool IsPlaced(long XR, long YR, long XL, long YL);

void FillVert();

void FillGoriz();

void Correct();

bool ChangeScanGoriz();

bool ChangeScanVert();

void Optimize();

//

void ShowTopology();

void ChangeView(int dx, int dy);

void ChangeStep(int stepx, int stepy);

void Left();

void Right();

void Up();

void Down();

void ShowGrid();

//

friend ostream& operator<<(ostream& os, Topology& top);

};

// Текст основных процедур

TypeOfRibbon RibbonType = Vertical;

IntType SizeXLambda = 1, SizeYLambda = 1, WidthRibbon = 3;

IntType XView = 0, YView = 0;

IntType MaxXLambda, MaxYLambda;

//

// ----------------------------------------------------------------------

// Define class Topology

//-----------------------------------------------------------------------

//

void Topology::SortGoriz()

{

IntType Last = GorizRibbons.Total - 1;

if ( (GorizRibbons[Last].X + GorizRibbons[Last].Len - 1) > MaxX)

MaxX = GorizRibbons[Last].X + GorizRibbons[Last].Len - 1;

if (GorizRibbons[Last].Y + WidthRibbon > MaxY)

MaxY = GorizRibbons[Last].Y + WidthRibbon;

for(int i=0; i< Last; i++)

if(GorizRibbons[Last].Y <= GorizRibbons[i].Y) {

Ribbon ribb = GorizRibbons[Last];

for(int j=Last; j>i; j--)

GorizRibbons[j] = GorizRibbons[j-1];

GorizRibbons[i] = ribb;

break;

}

}

//

void Topology::SortVert()

{

IntType Last = VertRibbons.Total - 1;

if ( (VertRibbons[Last].Y + VertRibbons[Last].Len - 1) > MaxY)

MaxY = VertRibbons[Last].Y + VertRibbons[Last].Len - 1;

if (VertRibbons[Last].X + WidthRibbon > MaxX)

MaxX = VertRibbons[Last].X + WidthRibbon;

for(int i=0; i< Last; i++)

if(VertRibbons[Last].X <= VertRibbons[i].X) {

Ribbon ribb = VertRibbons[Last];

for(int j=Last; j>i; j--)

VertRibbons[j] = VertRibbons[j-1];

VertRibbons[i] = ribb;

break;

}

}

//

void Topology::AddGorizRibbon(Ribbon* ribb)

{

GorizRibbons.Add(ribb);

SortGoriz();

}

//

void Topology::AddVertRibbon(Ribbon* ribb)

{

VertRibbons.Add(ribb);

SortVert();

}

// Return 'false' if region contains anything ribbon

// (XL, YL) - left top point

// (XR, YR) - rigth bottom point

bool Topology::IsEmpty(long XL, long YL, long XR, long YR)

{

bool empty = true;

IntType Index = 0;

if (XL < 0 || XR > MaxX || YL < 0 || YR > MaxY)

return false;

// Scanning gorizontal ribbons

while(GorizRibbons[Index].Y+WidthRibbon-1 < YL) Index++;

while( (GorizRibbons[Index].Y <= YR) && empty) {

if (GorizRibbons[Index].X <= XR)

if ( (GorizRibbons[Index].X+GorizRibbons[Index].Len-1) >= XL)

empty = false;

Index++;

}

// Scanning vertical ribbons

Index = 0;

if (empty) {

while(VertRibbons[Index].X+WidthRibbon-1 < XL) Index++;

while( (VertRibbons[Index].X <= XR) && empty) {

if (VertRibbons[Index].Y <= YR)

if ( (VertRibbons[Index].Y+VertRibbons[Index].Len-1) >= YL)

empty = false;

Index++;

}

}

return empty;

}

// Return 'false' if region contains anything ribbon

// (XL, YL) - left top point

// (XR, YR) - rigth bottom point

bool Topology::IsPlaced(long XL, long YL, long XR, long YR)

{

bool empty = true;

IntType Index = 0;

if (XL+MinX < 0)

XL = MinX;

if (XR+MinX > MaxX)

XR = MaxX-MinX;

if (YL-MinY < 0)

YL = MinY;

if (YR+MinY > MaxY)

YR = MaxY-MinY;

// Scanning gorizontal ribbons

while(GorizRibbons[Index].Y+WidthRibbon-1 < YL-MinY) Index++;

while( (GorizRibbons[Index].Y <= YR+MinY) && empty) {

if (GorizRibbons[Index].X <= XR+MinX)

if ( (GorizRibbons[Index].X+GorizRibbons[Index].Len-1) >= XL-MinX)

empty = false;

Index++;

}

// Scanning vertical ribbons

Index = 0;

if (empty) {

while(VertRibbons[Index].X+WidthRibbon-1 < XL-MinX) Index++;

while( (VertRibbons[Index].X <= XR+MinX) && empty) {

if (VertRibbons[Index].Y <= YR+MinY)

if ( (VertRibbons[Index].Y+VertRibbons[Index].Len-1) >= YL-MinY)

empty = false;

Index++;

}

}

return empty;

}

// ---------------------------------------------

// functions Correct(), FillVert(), FillGoriz(),

// ChangeScanGoriz(), ChangeScanVert()

// for correction of topology

// ---------------------------------------------

// select type of filling ribbons

void Topology::Correct()

{

Passed = false;

if (VertRibbons.Total < GorizRibbons.Total)

FillGoriz();

else

FillVert();

}

// fill topology by gorizontical ribbons

void Topology::FillGoriz()

{

bool completed = false;

XScan = YScan = 0;

// step2: seaching empty area

while(!completed) {

while(!IsPlaced(XScan, YScan, XScan, YScan+WidthRibbon-1)

&& !completed)

completed = ChangeScanGoriz();

// step3: select rectangle area

// define width of rectangle area

if (!completed) {

long XB = XScan, YB = YScan, Width = 0, Height = 0;

while (IsPlaced(XB, YScan,

XB, YScan+WidthRibbon-1)) {

Width++;

if (XB == MaxX)

break;

else

XB++;

}

// define Height of rectangle area

if (Width > WidthRibbon) {

while (

IsEmpty( (XScan-MinX) < 0 ? 0:(XScan-MinX), YB,

(XScan+MinX+Width-1) > MaxX ? MaxX:(XScan+MinX+Width-1),

(YB+MinY) > MaxY ? MaxY:(YB+MinY)) &&

!IsEmpty( XScan-MinX-1, YB,

(XScan+MinX+Width-1) > MaxX ? MaxX:(XScan+MinX+Width-1),

YB) &&

!IsEmpty( (XScan-MinX) < 0 ? 0:(XScan-MinX),

YB, XScan+MinX+Width, YB)

)

{

Height++;

if (YB == MaxY)

break;

else

YB++;

}

// step 4: compute number of ribbons in area

IntType THeight = Height+2*MinY;

IntType numRibbons =

(Height+MinY)/(WidthRibbon+MinY);

// step 5: compute spacing bitween ribbons

float Spacing = (THeight-numRibbons*WidthRibbon)/

(numRibbons+1);

for(int i=0; i< numRibbons; i++)

{

Ribbon* ribb = new Ribbon;

ribb->X = XScan;

ribb->Y = (YScan-MinY) +

floor((i+1)*Spacing+i*WidthRibbon);

ribb->Len = Width;

ribb->Corrected = true;

AddGorizRibbon(ribb);

// ShowTopology();

}

}

// continue process

XScan = XB;

completed = ChangeScanGoriz();

}

}

// step 6: Additional correction

if (Passed == true)

return;

else {

Passed = true;

FillVert();

}

}

// Fill topology by vertical ribbons

void Topology::FillVert()

{

bool completed = false;

XScan = YScan = 0;

while(!completed) {

while(!IsPlaced(XScan, YScan, XScan+WidthRibbon-1, YScan)

&& !completed)

completed = ChangeScanVert();

// end of while

if (!completed) {

long XB = XScan, YB = YScan, Width = 0, Height = 0;

while (IsPlaced(XScan, YB,

XScan+WidthRibbon-1, YB)) {

Height++;

if (YB == MaxY)

break;

else

YB++;

}

//

if (Height > WidthRibbon) {

while (

IsEmpty( XB, (YScan-MinY) < 0 ? 0:(YScan-MinY),

(XB+MinX) > MaxX ? MaxX:(XB+MinX),

(YScan+MinY+Height-1) > MaxY ? MaxY:(YScan+MinY+Height-1)) &&

!IsEmpty( XB, YScan-MinY-1, XB,

(YScan+MinY+Height-1) > MaxY ? MaxY:(YScan+MinY+Height-1)) &&

!IsEmpty( XB, (YScan-MinY) < 0 ? 0:(YScan-MinY),

XB, YScan+MinY+Height)

)

{

Width++;

if (XB == MaxX)

break;

else

XB++;

}

// end of while

// step 4: compute number of ribbons in area

IntType TWidth = Width+2*MinY;

IntType numRibbons =

(Width+MinY)/(WidthRibbon+MinX);

// step 5: compute spacing bitween ribbons

float Spacing = (TWidth-numRibbons*WidthRibbon)/

(numRibbons+1);

for(int i=0; i< numRibbons; i++)

{

Ribbon* ribb = new Ribbon;

ribb->X = (XScan-MinX) +

floor((i+1)*Spacing+i*WidthRibbon);

ribb->Y = YScan;

ribb->Len = Height;

ribb->Corrected = true;

AddVertRibbon(ribb);

// ShowTopology();

}

}

YScan = YB;

completed = ChangeScanVert();

}

}

if (Passed == true)

return;

else {

Passed = true;

FillGoriz();

}

}

//

bool Topology::ChangeScanGoriz()

{

if (XScan == MaxX) {

XScan = 0;

if (YScan == MaxY)

return true;

else

YScan++;

}

else

XScan++;

return false;

}

//

bool Topology::ChangeScanVert()

{

if (YScan == MaxY) {

YScan = 0;

if (XScan == MaxX)

return true;

else

XScan++;

}

else

YScan++;

return false;

}

Соседние файлы в папке PALADIN