0ad/source/dcdt/se/Location.cpp
janwas 5bf9bca9ef fix/disable warnings.
there are too many W4 and "potentially uninitialized", so those are
disabled by 0ad_warning_disable.h.

the silly "int x = strlen" and very dangerous "int x = (void*)p" (and
vice versa) problems are fixed.

This was SVN commit r5526.
2007-12-23 12:18:57 +00:00

161 lines
5.0 KiB
C++

//Location.cpp
#include "precompiled.h"
#include "0ad_warning_disable.h"
#include <cstdlib>
#include <math.h>
#include "se_dcdt.h"
#include <fstream>
//the list of unprocessed triangles
template <class T>
SrArray<SeLinkFace<T> *> SeLinkFace<T>::processing;
//DJD: Point location function definitions {
//initializes each sector midpoint to point to the triangle in which it is contained
void SeDcdt::InitializeSectors()
{
#if defined EXPERIMENT
//count the number of triangles
int num = 0;
#endif
//calculate the width and height of the triangulation
float width = _xmax - _xmin;
float height = _ymax - _ymin;
//calculate the width and height of each sector
sectorWidth = width / (float)xSectors;
sectorHeight = height / (float)ySectors;
//initialize all sectors to null
for (int i = 0; i < ySectors; i++)
{
for (int j = 0; j < xSectors; j++)
{
sectors[i][j] = NULL;
}
}
float x, y;
float x1, y1, x2, y2, x3, y3;
//go through the unprocessed triangles
for (int k = 0; k < SeDcdtFace::Faces(); k++)
{
//retrieve the next valid triangle
SeDcdtFace *currentFace = SeDcdtFace::Face(k);
if (currentFace == NULL)
{
continue;
}
#if defined EXPERIMENT
//keep track of the number of triangles
num++;
#endif
//get the minimum and maximum x and y values
TriangleVertices(currentFace, x1, y1, x2, y2, x3, y3);
float left = Min(x1, x2, x3);
float right = Max(x1, x2, x3);
float top = Min(y1, y2, y3);
float bottom = Max(y1, y2, y3);
//calculate the minimum and maximum x and y sector indices covered
int xIndexMin = (int)((left - _xmin + 0.5f * sectorWidth) / sectorWidth);
int xIndexMax = (int)((right - _xmin - 0.5f * sectorWidth) / sectorWidth);
int yIndexMin = (int)((top - _ymin + 0.5f * sectorHeight) / sectorHeight);
int yIndexMax = (int)((bottom - _ymin - 0.5f * sectorHeight) / sectorHeight);
//go through the covered sector midpoints
for (int i = yIndexMin; i <= yIndexMax; i++)
{
for (int j = xIndexMin; j <= xIndexMax; j++)
{
//calculate the location of the midpoint
x = ((float)j + 0.5f) * sectorWidth + _xmin;
y = ((float)i + 0.5f) * sectorHeight + _ymin;
//if the midpoint is in the current triangle,
if (InTriangle(currentFace, x, y))
{
//point the sector to that triangle
sectors[i][j] = currentFace;
}
}
}
}
#if defined EXPERIMENT
//if we are running an experiment, output the number of triangles to a data file
std::ofstream outFile("Data.txt", std::ios_base::app);
outFile << "Triangles: " << num << "\t";
outFile.close();
#endif
}
//check if the given point is within a given triangle
bool SeDcdt::InTriangle(SeDcdtFace *face, float x, float y)
{
//get the triangle's vertices
float x1, y1, x2, y2, x3, y3;
TriangleVertices(face, x1, y1, x2, y2, x3, y3);
//check that the point is counterclockwise of all edges
return ((Orientation(x1, y1, x2, y2, x, y) >= 0)
&& (Orientation(x2, y2, x3, y3, x, y) >= 0)
&& (Orientation(x3, y3, x1, y1, x, y) >= 0));
}
//uses the sectors to locate in which triangle the given point lies
SeTriangulator::LocateResult SeDcdt::LocatePoint(float x, float y, SeBase* &result)
{
//calculates the indices of the sector in which the point lies
int xIndex = (int)((x - _xmin) / sectorWidth);
int yIndex = (int)((y - _ymin) / sectorHeight);
//makes sure the indices are within the proper bounds
xIndex = (xIndex < 0) ? 0 : (xIndex >= xSectors) ? xSectors - 1 : xIndex;
yIndex = (yIndex < 0) ? 0 : (yIndex >= ySectors) ? ySectors - 1 : yIndex;
//retrieve the triangle in which that sector midpoint is located
SeFace *iniface = sectors[yIndex][xIndex];
//if it was invalid, start at the usual place
if (iniface == NULL)
{
iniface = _search_face();
}
//use this starting triangle to start point location
return _triangulator->locate_point(iniface, x, y, result);
}
//locate the given point starting at the usual place
SeTriangulator::LocateResult SeDcdt::LocatePointOld(float x, float y, SeBase* &result)
{
return _triangulator->locate_point(_search_face(), x, y, result);
}
//returns the maximum of the 3 values passed
float SeDcdt::Max(float a, float b, float c)
{
return ((a >= b) && (a >= c)) ? a :
((b >= a) && (b >= c)) ? b : c;
}
//returns the minimum of the 3 values passed
float SeDcdt::Min(float a, float b, float c)
{
return ((a <= b) && (a <= c)) ? a :
((b <= a) && (b <= c)) ? b : c;
}
//return a random value in the range of x values (used for testing)
float SeDcdt::RandomX()
{
return RandomBetween(_xmin, _xmax);
}
//return a random value in the range of y values (used for testing)
float SeDcdt::RandomY()
{
return RandomBetween(_ymin, _ymax);
}
//returns a random number between the values given
float SeDcdt::RandomBetween(float min, float max)
{
float base = (float)rand() / (float)RAND_MAX; // TODO: Make net-safe
return (base * (max - min) + min);
}
//Point location function definitions }