<Source Index
|
<PPA-L top page
plotarea.cpp
//////////////////////////////////////////////////
//
// This file is to be used for point process analysis
//
// Copyright October 2001 by TAKENAKA, A.
#include <iostream>
#include "plotarea.h"
#define M_PI 3.14159265358979323846
//////////////////////////////
//
// Constructor # Does nothing.
PlotArea::PlotArea(void)
{}
//////////////////////////////
//
bool PlotArea::loadPoints(const char* file1, const char* file2)
{
Points1.erase(Points1.begin(), Points1.end());
Points2.erase(Points2.begin(), Points2.end());
Points1.load(file1);
if (Points1.size() == 0) { // No data.
return false;
}
if (file2 != NULL) { // If two files are specified...
Points2.load(file2);
if (Points2.size() == 0) { // No data.
return false;
}
}
// The area of the first data set is stored.
AreaSize = Points1.getAreaSize();
Area = AreaSize.X * AreaSize.Y;
Perimeter = 2.0 * (AreaSize.X + AreaSize.Y);
Density1 = Points1.size() / Area;
if (Points2.size() > 0) {
Density2 = Points2.size() / Area;
}
if ((Points2.size()) > 0 && !(AreaSize == Points2.getAreaSize()) ) {
std::cerr << "! WARNING: Area of two data sets does not match."
<< std::endl;
}
return true;
}
//////////////////////////////
//
// Calculate L function.
//
// r_unit : increment of the distance, r.
// r_upto : the furthest distance to calculate L.
bool PlotArea::calc_L(double r_unit, double r_upto)
{
if (r_unit <= 0 || r_unit > r_upto) { // Invalid r specification.
std::cerr << "Invalid r specification." << std::endl;
return false;
}
R_Unit = r_unit;
R_Upto = r_upto;
// R is kept shorter than the width of the area.
double min_side = (AreaSize.X < AreaSize.Y) ? AreaSize.X : AreaSize.Y;
if (R_Upto > min_side) {
R_Upto = min_side;
}
// r = R_Unit, 2 * R_Unit, 3 * R_Unit, ...(MaxR_Index - 1) * R_Unit.
MaxR_Index = R_Upto / R_Unit;
initArray(); // Initialize array to store the results.
calc_K();
fromKtoL();
return true;
}
//////////////////////////////
//
// Calculate K function.
void PlotArea::calc_K(void)
{
PointList::iterator itr1, itr2;
PointList::iterator itr2_begin, itr2_end;
if (Points2.size() > 0) { // cross K between two sets of points.
itr2_begin = Points2.begin();
itr2_end = Points2.end();
}
else { // K within a set of points.
itr2_begin = Points1.begin();
itr2_end = Points1.end();
}
for (itr1 = Points1.begin(); itr1 != Points1.end(); ++itr1) {
for (itr2 = itr2_begin; itr2 != itr2_end; ++itr2) {
if (itr1 == itr2) { // Does not happen in case of cross K.
continue;
}
double r = (*itr1).distance(*itr2);
int r_index = r_to_index(r);
if (r_index < 0) {
continue; // r_to_index(r) returns -1 if points are too far.
}
// if the point (*itr2) is within a dinstance n *R_Unit from the
// point (*itr1), the point (*itr2) is also within a distance
// (n+1) * R_Unit, (n+2) * R_Unit ,... (MaxR_Index - 1) * R_Unit.
double s = get_s(r); // Ohser's edge correction factor.
for (int i = r_index; i < MaxR_Index; ++i) {
ResultsArray[i].second += 1.0 / s;
}
}
}
// Normalize for point density.
double dd = (Points2.size() == 0) ? (Density1 * Density1)
: (Density1 * Density2);
for (int i = 0; i < MaxR_Index; ++i) {
ResultsArray[i].second /= dd;
}
}
//////////////////////////////
//
const r_X_Array& PlotArea::getResults(void)
{
return ResultsArray;
}
//////////////////////////////
//
// Initialize the result array.
void PlotArea::initArray(void)
{
ResultsArray.erase(ResultsArray.begin(), ResultsArray.end());
for (int i = 0; i < MaxR_Index; ++i) {
double r = (i + 1) * R_Unit;
ResultsArray.push_back(r_X_Pair(r, 0.0));
}
}
//////////////////////////////
//
// Returns index of the element in the result array (ResultsArray)
// corresponding to the given distance, r.
//
// For too large r (index > MaxR_Index), -1 will be returned.
int PlotArea::r_to_index(double r)
{
int index = (r / R_Unit);
// If r = n * R_Unit (n is integer), the index should be n-1, not n.
if (index * R_Unit == r) {
index--;
}
if (index >= MaxR_Index) { // Too far.
return -1;
}
return index;
}
//////////////////////////////
//
// Ohser's edge correction
double PlotArea::get_s(double x)
{
return Area - x * (Perimeter - x) / M_PI;
}
//////////////////////////////
//
// Replace K function values in the result array by L values.
void PlotArea::fromKtoL(void)
{
double r, k, l;
for (int i = 0; i < MaxR_Index; ++i) {
r = ResultsArray[i].first;
k = ResultsArray[i].second;
l = sqrt(k / M_PI) - r;
ResultsArray[i].second = l; // replace K by L.
}
}