Files
secondo/Algebras/Convex2/Convex2.cpp

8212 lines
198 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
----
This file is part of SECONDO.
Copyright (C) 2019,
University in Hagen,
Faculty of Mathematics and Computer Science,
Database Systems for New Applications.
SECONDO 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.
SECONDO 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 SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
*/
#include "Convex2.h"
#include "Attribute.h"
#include <set>
#include <iostream>
#include "NestedList.h"
#include "Algebras/Spatial/SpatialAlgebra.h"
#include <tuple>
#include <vector>
#include <algorithm>
#include "ListUtils.h"
#include "NList.h"
#include "StandardTypes.h"
#include "Stream.h"
#include "Algebras/FText/FTextAlgebra.h"
#include <cstdio>
#include "AlmostEqual.h"
#include <limits>
#include "math.h"
#include "Algebras/Collection/IntSet.h"
#include "predicates.c"
#include <boost/polygon/voronoi.hpp>
using boost::polygon::voronoi_builder;
using boost::polygon::voronoi_diagram;
using boost::polygon::x;
using boost::polygon::y;
using boost::polygon::low;
using boost::polygon::high;
using boost::polygon::construct_voronoi;
/*
1.1 boost definitions needed for constructing the voronoi diag
*/
namespace boost {
namespace polygon {
struct VoronoiPoint {
double a;
double b;
VoronoiPoint(double x, double y) : a(x), b(y) {}
};
template<>
struct geometry_concept<VoronoiPoint>{typedef point_concept type;};
template <>
struct point_traits<VoronoiPoint> {
typedef double coordinate_type;
static inline coordinate_type get(
const VoronoiPoint& point, orientation_2d orient) {
return (orient == HORIZONTAL) ? point.a : point.b;
}
};
}}
using namespace std;
extern NestedList* nl;
using boost::polygon::VoronoiPoint;
namespace convex {
/*
2.1 constructors
*/
Convex::Convex(const Convex& src):Attribute(src),value(0),
size(src.size),cellId(0){
if(size>0){
value = new Point[size];
memcpy((char*)value, src.value,size*sizeof(Point));
memcpy(&cellId, &src.cellId, sizeof(int));
}
}
Convex::Convex(Convex&& src): Attribute(src),
value(src.value), size(src.size), cellId(src.cellId) {
src.size = 0;
src.value = 0;
src.cellId = 0;
}
Convex::Convex(const std::vector<std::tuple
<double, double>>& src, int id_):Attribute(true), value(0){
setTo(src, id_);
}
Convex::Convex(const std::vector<std::tuple
<double, double>>& src):Attribute(true), value(0){
setTo(src, -1);
}
Convex& Convex::operator=(const Convex& src) {
Attribute::operator=(src);
if(this->size != src.size){
delete[] value;
value = 0;
cellId = 0;
this->size = src.size;
if(size > 0){
value = new Point[size];
}
}
if(size > 0){
memcpy((char*)value, src.value,size*sizeof(Point));
memcpy(&cellId, &src.cellId, sizeof(int));
}
return *this;
}
Convex& Convex::operator=(Convex&& src) {
Attribute::operator=(src);
size = src.size;
value = src.value;
cellId = src.cellId;
src.size = 0;
src.value = 0;
src.cellId = 0;
return *this;
}
void
Convex::setCellId(int cell_id) {
this->cellId = cell_id;
}
int
Convex::getCellId() {
return cellId;
}
void
Convex::setTo(const std::vector<std::tuple <double, double>>& src,
int id_){
clear();
SetDefined(true);
if(src.size()>0){
size = src.size();
value = new Point[size];
setCellId(id_);
auto it = src.begin();
size_t pos = 0;
std::tuple<double, double> temptup;
double tempxval;
double tempyval;
Point poi;
/*
converting the right tuple vector into point sequence
*/
while(it!=src.end()) {
temptup = *it;
tempxval = std::get<0>(temptup);
tempyval = std::get<1>(temptup);
poi.Set(true, tempxval, tempyval);
value[pos] = poi;
it++;
pos++;
}
}
}
/*
3.1 auxillary functions
*/
bool insideRect(Rectangle<2>* r, std::tuple<double,double> center) {
double x = get<0>(center);
double y = get<1>(center);
if (r->getMinX() <= x && r->getMaxX() >= x
&& r->getMinY() <= y && r->getMaxY() >= y)
{
return true;
}
return false;
}
Point getRectCentre(Rectangle<2>* r)
{
Point rc;
double a = (r->getMaxY() - r->getMinY()) / (double)2;
double b = (r->getMaxX() - r->getMinX()) / (double)2;
rc.Set(r->getMinX()+ b, r->getMinY() + a);
return rc;
}
/*
Returns bounding box of a convex polygon
*/
Rectangle<2> createBBox(Convex* convex) {
Rectangle<2> bbox;
double minx = convex->value[0].GetX();
double maxx = convex->value[0].GetX();
double miny = convex->value[0].GetY();
double maxy = convex->value[0].GetY();
for(int c=1; c < (int)convex->size; c++) {
double x_val = convex->value[c].GetX();
double y_val = convex->value[c].GetY();
if(x_val < minx) {
minx = x_val;
} else if (x_val > maxx) {
maxx = x_val;
}
if(y_val < miny) {
miny = y_val;
} else if(y_val > maxy) {
maxy = y_val;
}
}
double min[2], max[2];
min[0] = minx;
min[1] = miny;
max[0] = maxx;
max[1] = maxy;
bbox = Rectangle<2>(true, min, max);
return bbox;
}
/*
Returns true if point is inside of convex polygon
*/
bool PointInPolygon(Point point, Convex* conv)
{
std::vector<Point> poly;
for(int a = 0; a < (int)conv->size; a++) {
Point p1;
p1.Set(conv->value[a].GetX(), conv->value[a].GetY());
poly.insert(poly.begin() + a, p1);
}
Rectangle<2> bbox = createBBox(conv);
/*
Precheck: if point is not in bbox of polygon, then it is not in
polygon either
*/
if(!insideRect(&bbox, std::make_tuple(point.GetX(), point.GetY())))
{
return false;
}
/*
go through every segment and check
on which side point lies
*/
double detO;
Point a,b;
a = poly[0];
b = poly[1];
/*
P0 (x0,y0) and P1 (x1,y1), another point P (x,y)
(y - y0) (x1 - x0) - (x - x0) (y1 - y0)
*/
detO = (point.GetY() - a.GetY())*(b.GetX() - a.GetX())
- (point.GetX() - a.GetX())*(b.GetY() - a.GetY());
for(int e = 1; e < (int)poly.size()-1; e++) {
Point a,b;
a = poly[e];
b = poly[e+1];
double det = (point.GetY() - a.GetY())*(b.GetX() - a.GetX())
- (point.GetX() - a.GetX())*(b.GetY() - a.GetY());
if(signbit(detO) != signbit(det))
{
return false;
}
}
return true;
}
/*
Calculates point of intersection between two segments
*/
int getLineIntersection(Point p0, Point p1,
Point p2, Point p3, double *i_x, double *i_y)
{
// Points x and y values
double p0_x = p0.GetX();
double p0_y = p0.GetY();
double p1_x = p1.GetX();
double p1_y = p1.GetY();
double p2_x = p2.GetX();
double p2_y = p2.GetY();
double p3_x = p3.GetX();
double p3_y = p3.GetY();
double xp0p2, yp0p2, xp1p0, yp1p0, xp3p2,
yp3p2, u_numrator, t_numerator, denominator, t;
xp1p0 = p1_x - p0_x;
yp1p0 = p1_y - p0_y;
xp3p2 = p3_x - p2_x;
yp3p2 = p3_y - p2_y;
denominator = xp1p0 * yp3p2 - xp3p2 * yp1p0;
if (denominator == 0)
return 0; // parallel
bool denomPositive = denominator > 0;
xp0p2 = p0_x - p2_x;
yp0p2 = p0_y - p2_y;
u_numrator = xp1p0 * yp0p2 - yp1p0 * xp0p2;
if ((u_numrator < 0) == denomPositive)
return 0; // No intersection
t_numerator = xp3p2 * yp0p2 - yp3p2 * xp0p2;
if ((t_numerator < 0) == denomPositive)
return 0; // No intersection
if (((u_numrator > denominator) == denomPositive) ||
((t_numerator > denominator) == denomPositive))
return 0; // No intersection
// Intersection
t = t_numerator / denominator;
if (i_x != NULL)
*i_x = p0_x + (t * xp1p0);
if (i_y != NULL)
*i_y = p0_y + (t * yp1p0);
return 1;
}
/*
Calculates center of a given polygon
*/
std::tuple<double,double>
calcPolyCentroid(std::vector<std::tuple<double, double>> vertices,
int vertexNumb)
{
std::tuple<double,double> centroid = {0, 0};
double signedArea = 0.0;
double x0 = 0.0; // current x value
double y0 = 0.0; // current y value
double x1 = 0.0; // next x value
double y1 = 0.0; // next y value
double a = 0.0; // area
int i;
// Calculate area of polygon with Gaußsche Trapezformel
for(i=0; i<vertexNumb-1; ++i)
{
x0 = get<0>(vertices[i]);
y0 = get<1>(vertices[i]);
x1 = get<0>(vertices[i+1]);
y1 = get<1>(vertices[i+1]);
a = x0*y1 - x1*y0;
signedArea += a;
get<0>(centroid) += (x0 + x1)*a;
get<1>(centroid) += (y0 + y1)*a;
}
// last vertex
x0 = get<0>(vertices[i]);
y0 = get<1>(vertices[i]);
x1 = get<0>(vertices[0]);
y1 = get<1>(vertices[0]);
a = x0*y1 - x1*y0;
signedArea += a;
get<0>(centroid) += (x0 + x1)*a;
get<1>(centroid) += (y0 + y1)*a;
signedArea *= 0.5;
// calculate centroid with formula
get<0>(centroid) /= (6.0*signedArea);
get<1>(centroid) /= (6.0*signedArea);
return centroid;
}
/*
Returns true if two rectangles (l1, r1) and (l2, r2) overlap
*/
bool rectOverlap(Point tole1, Point bori1, Point tole2, Point bori2)
{
// If one rectangle is on left side of other
if (tole1.GetX() > bori2.GetX() || tole2.GetX() > bori1.GetX())
return false;
// If one rectangle is above other
if (tole1.GetY() < bori2.GetY() || tole2.GetY() < bori1.GetY())
return false;
return true;
}
/*
Returns true if two cuboids (l1, r1) and (l2, r2) overlap
*/
bool cuboidOverlap(Point3D tolefr1,
Point3D boriba1, Point3D tolefr2, Point3D boriba2)
{
// If one cuboid is on left side of other
if (tolefr1.x > boriba2.x || tolefr2.x > boriba1.x)
return false;
// If one cuboid is above other
if (tolefr1.y < boriba2.y || tolefr2.y < boriba1.y)
return false;
if(tolefr1.z > boriba2.z || tolefr2.z > boriba1.z)
return false;
return true;
}
/*
Returns bounding box of a convex polyhedron
*/
Rectangle<3> createBBox3D(Polyhedron* poly) {
Rectangle<3> bbox;
double minx = poly->faces.at(0).at(0).x;
double maxx = poly->faces.at(0).at(0).x;
double miny = poly->faces.at(0).at(0).y;
double maxy = poly->faces.at(0).at(0).y;
double minz = poly->faces.at(0).at(0).z;
double maxz = poly->faces.at(0).at(0).z;
for(size_t c=1; c < poly->faces.size(); c++) {
for(size_t v=0; v < poly->faces.at(c).size(); v++)
{
double x_val = poly->faces.at(c).at(v).x;
double y_val = poly->faces.at(c).at(v).y;
double z_val = poly->faces.at(c).at(v).z;
if(x_val < minx) {
minx = x_val;
} else if (x_val > maxx) {
maxx = x_val;
}
if(y_val < miny) {
miny = y_val;
} else if(y_val > maxy) {
maxy = y_val;
}
if(z_val < minz) {
minz = z_val;
} else if(z_val > maxz) {
maxz = z_val;
}
}
}
double min[3], max[3];
min[0] = minx;
min[1] = miny;
min[2] = minz;
max[0] = maxx;
max[1] = maxy;
max[2] = maxz;
bbox = Rectangle<3>(true, min, max);
return bbox;
}
/*
Returns all cellnumbers of cells which intersect with a given rectangle
Two modes are possible: intersections with the exact cell and intersection
with the bounding box of a cell
*/
void cellNum(Rectangle<2>* search_window_ptr,
int mode, std::set<int> *cell_ids) {
int bbox = 2;
int precise = 1;
// Rectangle points
Point lebo, ribo, leto, rito;
lebo.Set(search_window_ptr->getMinX(), search_window_ptr->getMinY());
ribo.Set(search_window_ptr->getMaxX(), search_window_ptr->getMinY());
leto.Set(search_window_ptr->getMinX(), search_window_ptr->getMaxY());
rito.Set(search_window_ptr->getMaxX(), search_window_ptr->getMaxY());
Point center = getRectCentre(search_window_ptr);
// intersection with exact cell
if(mode == precise) {
for(int i = 0; i < (int)voroVec.size(); i++)
{
Convex* tmp = &voroVec[i];
if(tmp->size > 0) {
/*
-1. Precheck if object has an intersection
with bbox of voronoi cell
- if yes: go on with further tests
- if not: go to next cell
*/
Rectangle<2> bbox = createBBox(tmp);
// see if bbox intersects with rectangle
// top left and bottom right of bbox
Point tole, bori;
tole.Set(bbox.getMinX(), bbox.getMaxY());
bori.Set(bbox.getMaxX(), bbox.getMinY());
if(rectOverlap(tole, bori, leto, ribo))
{
std::vector<std::tuple<double, double>> polygon {};
std::tuple<double, double> point;
/*
1. Check if middle of cell intersects with rectangle
(get middle of cell, check if it lies in rectangle)
- if yes: add cell\_id to cell\_ids
- if no: check if edges intersect with rectangle
- build edges from points (ordered clockwise), check intersection
- if one intersect: add cell\_id to cell\_ids
- if no edge intersects: check if rectangle is small and does
not intersects with edges or centroid at all, but lies in cell
- if no intersects: go to next cell, don't add cell\_id
*/
double firstX = tmp->value[0].GetX();
double firstY = tmp->value[0].GetY();
point = std::make_tuple(firstX, firstY);
polygon.insert(polygon.begin(), point);
for(int a = 1; a < (int)tmp->size; a++) {
point = std::make_tuple(tmp->value[a].GetX(), tmp->value[a].GetY());
polygon.insert(polygon.begin() + a, point);
}
std::tuple<double,double> centroid =
calcPolyCentroid(polygon, polygon.size());
if(insideRect(search_window_ptr, centroid)){
cell_ids->insert(tmp->getCellId());
} else if (PointInPolygon(center, tmp)) {
cell_ids->insert(tmp->getCellId());
} else {
for(int e = 0; e < (int)tmp->size; e++) {
Point a,b;
a.Set(tmp->value[e].GetX(), tmp->value[e].GetY());
if(e == (int)tmp->size-1) {
b.Set(firstX, firstY);
} else {
b.Set(tmp->value[e+1].GetX(), tmp->value[e+1].GetY());
}
// Point of intersection i\_x, i\_y w
double i_x = 0.0;
double i_y = 0.0;
/*
call to getlineintersection with 2 points of line
and two points of side of rectangle
(for each side of rectangle)
*/
if(getLineIntersection(a,b, lebo, ribo, &i_x, &i_y) == 1
|| getLineIntersection(a,b, lebo, leto, &i_x, &i_y) == 1
|| getLineIntersection(a,b, ribo, rito, &i_x, &i_y) == 1
|| getLineIntersection(a,b, leto, rito, &i_x, &i_y) == 1) {
cell_ids->insert(tmp->getCellId());
break;
}
}
}
if(polygon.size() > 0)
{
polygon.clear();
}
}
}
}
} else if (mode== bbox) {
for(int b = 0; b < (int)voroVec.size(); b++)
{
Convex* tmp = &voroVec[b];
if(tmp->size > 0) {
Rectangle<2> bbox = createBBox(tmp);
// see if bbox intersects with rectangle
// top left and bottom right of bbox
Point tole, bori;
tole.Set(bbox.getMinX(), bbox.getMaxY());
bori.Set(bbox.getMaxX(), bbox.getMinY());
if(rectOverlap(tole, bori, leto, ribo)) {
cell_ids->insert(tmp->getCellId());
}
}
}
} else {
cell_ids->insert(0);
}
return;
}
bool sortyupxup(const tuple<double, double>& a,
const tuple<double, double>& b)
{
if ( (get<1>(a) < get<1>(b)) ||
( ( get<1>(a) == get<1>(b)) && (get<0>(a) <= get<0>(b))) )
return true;
return false;
}
bool sortyupxdown(const tuple<double, double>& a,
const tuple<double, double>& b)
{
if ( (get<1>(a) < get<1>(b)) ||
( ( get<1>(a) == get<1>(b)) && (get<0>(a) >= get<0>(b))) )
return true;
return false;
}
bool sortxupyup(const tuple<double, double>& a,
const tuple<double, double>& b)
{
if ( (get<0>(a) < get<0>(b)) ||
( ( get<0>(a) == get<0>(b)) && (get<1>(a) <= get<1>(b))) )
return true;
return false;
}
bool sortxdownydown (const tuple<double, double>& a,
const tuple<double, double>& b)
{
if ( (get<0>(a) > get<0>(b)) ||
( ( get<0>(a) == get<0>(b)) && (get<1>(a) >= get<1>(b))) )
return true;
return false;
}
bool sortxdownyup (const tuple<double, double>& a,
const tuple<double, double>& b)
{
if ( (get<0>(a) > get<0>(b)) ||
( ( get<0>(a) == get<0>(b)) && (get<1>(a) <= get<1>(b))) )
return true;
return false;
}
bool sortxupydown (const tuple<double, double>& a,
const tuple<double, double>& b)
{
if ( (get<0>(a) < get<0>(b)) ||
( ( get<0>(a) == get<0>(b)) && (get<1>(a) >= get<1>(b))) )
return true;
return false;
}
void rmvredundpoints (std::vector<std::tuple<double, double>>& ppoi) {
std::set <std::tuple<double, double>> setme;
std::set <std::tuple<double, double>> tempvec;
for (unsigned int i = 0; i < ppoi.size(); i++)
{
setme.insert(ppoi[i]);
}
ppoi.assign(setme.begin(), setme.end());
sort(ppoi.begin(), ppoi.end(), sortxupyup);
}
/*
3.2 checkme function
*/
int checkme(std::vector<std::tuple <double, double>>& src, bool checkactive){
std::vector<std::tuple<double, double>> finalcheckedvec;
std::vector<std::tuple<double, double>> tmp;
std::vector<std::tuple <double, double>> xysortedvecasc;
std::vector<std::tuple <double, double>> yxsortedvecasc;
std::vector<std::tuple <double, double>> xysortedvecdesc;
std::vector<std::tuple <double, double>> ydownsortedvec;
std::tuple<double, double> leftpoint;
std::tuple<double, double> rightpoint;
std::tuple<double, double> downpoint;
std::tuple<double, double> uppoint;
std::tuple<double, double> actpoint;
std::tuple<double, double> intermpoint;
std::vector<std::tuple <double, double>> above;
std::vector<std::tuple <double, double>> below;
std::vector<std::tuple <double, double>> aboveleft;
std::vector<std::tuple <double, double>> belowleft;
std::vector<std::tuple <double, double>> aboveright;
std::vector<std::tuple <double, double>> belowright;
std::vector<std::tuple <double, double>> temp1, temp2;
unsigned int iter, sectorflag;
unsigned int aboveleftsize;
unsigned int aboverightsize;
unsigned int belowleftsize;
unsigned int belowrightsize;
unsigned int tmpsize;
bool okflag = true;
bool firstperpend = false;
bool secondperpend = false;
bool setfperflag = false;
bool firstmflag = false;
double m, b, mlast, mnew;
if (src.size() <= 2) {
return 0;
}
tmp = src;
xysortedvecasc = tmp;
yxsortedvecasc = tmp;
/*
sorting vecs by x resp. y coord
*/
sort(yxsortedvecasc.begin(), yxsortedvecasc.end(), sortyupxdown);
/*
eliminate redundant points
*/
rmvredundpoints(xysortedvecasc);
/*
get leftpoint and right point of polygon
*/
leftpoint = xysortedvecasc[0];
rightpoint = xysortedvecasc[xysortedvecasc.size() - 1];
downpoint = yxsortedvecasc[0];
uppoint = yxsortedvecasc[yxsortedvecasc.size() - 1];
/*
get points above and below the imagenary "line"
from leftpoint to rightpoint
*/
m = (get<1>(rightpoint) - get<1>(leftpoint)) /
(get<0>(rightpoint) - get<0>(leftpoint));
b = get<1>(rightpoint) - (m * get<0>(rightpoint));
below.clear();
above.clear();
for (unsigned int i = 0; i < xysortedvecasc.size(); i++) {
double fuval = (m * get<0>(xysortedvecasc[i])) + b;
if ( fuval > get<1>(xysortedvecasc[i]) &&
!(AlmostEqual (fuval, get<1>(xysortedvecasc[i])))) {
below.push_back (xysortedvecasc[i]);
}
else {
above.push_back (xysortedvecasc[i]);
}
}
/*
move points above and below to
aboveleft, aboveright, belowleft and belowright.
using the "line" from downpoint to uppoint
get points above and below the imagenary "line" from downpoint to uppoint
first: testing if point are perpendicular
*/
belowright.clear();
aboveright.clear();
belowleft.clear();
aboveleft.clear();
if (get<0>(uppoint) != get<0>(downpoint) ){
m = (get<1>(uppoint) - get<1>(downpoint)) /
(get<0>(uppoint) - get<0>(downpoint));
b = get<1>(uppoint) - (m * get<0>(uppoint));
}
if (get<0>(uppoint) != get<0>(downpoint)) {
for (unsigned int i = 0; i < above.size(); i++) {
double fval = (m * get<0>(above[i])) + b;
if ( (fval > get<1>(above[i])) &&
!(AlmostEqual (fval, get<1>(above[i]))))
{
aboveright.push_back (above[i]);
}
else {
aboveleft.push_back (above[i]);
}
}
for (unsigned int i = 0; i < below.size(); i++) {
if ( ((m * get<0>(below[i])) + b) > get<1>(below[i]) ) {
belowright.push_back (below[i]);
}
else {
belowleft.push_back (below[i]);
}
}
if (m < 0) {
temp1 = aboveright;
temp2 = belowright;
aboveright = aboveleft;
belowright = belowleft;
aboveleft = temp1;
belowleft = temp2;
}
}
/*
uppoint and downpoint are perpendicular
*/
if (get<0>(uppoint) == get<0>(downpoint) ) {
for (unsigned int i = 0; i < above.size(); i++) {
if ( (get<0>(above[i])) > get<0>(uppoint)) {
aboveright.push_back (above[i]);
}
else {
aboveleft.push_back (above[i]);
}
}
for (unsigned int i = 0; i < below.size(); i++) {
if ( (get<0>(below[i])) > get<0>(uppoint)) {
belowright.push_back (below[i]);
}
else {
belowleft.push_back (below[i]);
}
}
}
/*
sorting aboveleft, ab aboveright, belowright and belowleft...
*/
/*
aboveleft is already sorted: x up , y up
*/
sort(aboveleft.begin(), aboveleft.end(), sortxupyup);
/*
sorting aboveright: x up, y down
*/
sort(aboveright.begin(), aboveright.end(), sortxupydown);
/*
sorting belowright: x down, y down
*/
sort(belowright.begin(), belowright.end(), sortxdownydown);
/*
sorting belowleft: x down, y up
*/
sort(belowleft.begin(), belowleft.end(), sortxdownyup);
/*
constructing the final vector
*/
finalcheckedvec.clear();
aboveleftsize = aboveleft.size();
aboverightsize = aboveright.size();
belowleftsize = belowleft.size();
belowrightsize = belowright.size();
tmpsize = tmp.size();
for (unsigned int i = 0; i < aboveleftsize; i++) {
finalcheckedvec.push_back(aboveleft[i]);
}
for (unsigned int i = 0; i < aboverightsize; i++) {
finalcheckedvec.push_back(aboveright[i]);
}
for (unsigned int i = 0; i < belowrightsize; i++) {
finalcheckedvec.push_back(belowright[i]);
}
for (unsigned int i = 0; i < belowleftsize; i++) {
finalcheckedvec.push_back(belowleft[i]);
}
if (tmpsize == finalcheckedvec.size()) {
}
if (checkactive == false)
{
src = finalcheckedvec;
return 2;}
/*
put left point at the end of the final vec for testing purposes
*/
finalcheckedvec.push_back(leftpoint);
actpoint = leftpoint;
intermpoint = uppoint;
sectorflag = 1;
iter = 1;
if ((get<0>(leftpoint) == get<0>(finalcheckedvec[iter])) &&
(get<0>(leftpoint) == get<0>(finalcheckedvec[iter+1]))) {
ErrorReporter::ReportError(
"The coordinates do not form a convex polygon");
return 0;
}
if ((get<0>(leftpoint) == get<0>(finalcheckedvec[iter])) &&
(get<0>(leftpoint) != get<0>(finalcheckedvec[iter+1]))) {
firstperpend = true;
setfperflag = true;
/*
set mlast > mnew as start value
*/
mlast = 1;
mnew = 0;
}
else {
mlast = (get<1>(finalcheckedvec[iter] ) - get<1>(leftpoint)) /
(get<0>(finalcheckedvec[iter]) - get<0>(leftpoint));
firstmflag = true;
mnew = mlast - 1;
/*
just a dummy value
*/
}
while ( (iter < finalcheckedvec.size()) && (okflag == true)) {
/*
begin sector 2 case
*/
if (actpoint == uppoint) {
intermpoint = rightpoint;
sectorflag = 2;
firstperpend = false;
setfperflag = false;
}
if (sectorflag == 2) {
if ( (iter+1 < finalcheckedvec.size()) &&
(get<0>(actpoint) == get<0>(finalcheckedvec[iter])) &&
(get<0>(actpoint) == get<0>(finalcheckedvec[iter+1]))) {
ErrorReporter::ReportError(
"3The coordinates do not form a convex polygon");
return 0;
}
if (get<0>(actpoint) == get<0>(finalcheckedvec[iter]) &&
(actpoint != rightpoint) ) {
ErrorReporter::ReportError(
"4The coordinates do not form a convex polygon");
return 0;;
}
if (get<0>(actpoint) != get<0>(finalcheckedvec[iter]) &&
actpoint == uppoint)
{
mlast = (get<1>(finalcheckedvec[iter] ) - get<1>(uppoint)) /
(get<0>(finalcheckedvec[iter]) - get<0>(uppoint));
firstmflag = true;
mnew = mlast - 1;
/*
just a dummy value
*/
}
}
/*
end of sectorflag == 2 case
*/
/*
begin sector 3 case
*/
if (actpoint == rightpoint){
intermpoint = downpoint;
sectorflag = 3;
firstperpend = false;
setfperflag = false;
secondperpend = false;
firstmflag = false;
}
if (sectorflag == 3) {
if ( (iter+1 < finalcheckedvec.size()) &&
(get<0>(actpoint) == get<0>(finalcheckedvec[iter])) &&
(get<0>(actpoint) == get<0>(finalcheckedvec[iter+1])) &&
(actpoint == rightpoint) ) {
ErrorReporter::ReportError(
"4The coordinates do not form a convex polygon");
return 0;;
}
if ((iter+1 < finalcheckedvec.size()) &&
(get<0>(rightpoint) == get<0>(finalcheckedvec[iter])) &&
(get<0>(rightpoint) != get<0>(finalcheckedvec[iter+1])) &&
(actpoint == rightpoint) ) {
firstperpend = true;
setfperflag = true;
/*
set mlast > mnew as start value;
*/
mlast = 1;
mnew = 0;
}
else if (actpoint == rightpoint) {
mlast = (get<1>(finalcheckedvec[iter] ) - get<1>(rightpoint)) /
(get<0>(finalcheckedvec[iter]) - get<0>(rightpoint));
firstmflag = true;
mnew = mlast - 1;
/*
just a dummy value
*/
}
}
/*
end of sectorflag == 3 case
*/
/*
begin sector 4 case
*/
if ((actpoint == downpoint) && (downpoint != leftpoint)) {
intermpoint = leftpoint;
sectorflag = 4;
}
if ( (sectorflag == 4) && (actpoint != leftpoint) ) {
if ( (iter+1 < finalcheckedvec.size()) &&
(get<0>(actpoint) == get<0>(finalcheckedvec[iter])) &&
(get<0>(actpoint) == get<0>(finalcheckedvec[iter+1]))) {
ErrorReporter::ReportError(
"5The coordinates do not form a convex polygon");
return 0;;
}
if (get<0>(actpoint) == get<0>(finalcheckedvec[iter]) &&
(actpoint != uppoint) ) {
ErrorReporter::ReportError(
"6The coordinates do not form a convex polygon");
return 0;;
}
if (get<0>(actpoint) != get<0>(finalcheckedvec[iter]) &&
actpoint == downpoint)
{
mlast = (get<1>(finalcheckedvec[iter] ) - get<1>(downpoint)) /
(get<0>(finalcheckedvec[iter]) - get<0>(downpoint));
firstmflag = true;
mnew = mlast - 1;
/*
just a dummy value
*/
}
/*
end of sector 4 case
*/
}
switch (sectorflag) {
case 1: {
if (get<0>(actpoint) == get<0>(finalcheckedvec[iter])&&
(setfperflag == false) )
{secondperpend = true;
}
if (! ( (get<0>(actpoint) <= get<0>(finalcheckedvec[iter])) &&
(get<1>(actpoint) <= get<1>(finalcheckedvec[iter])) ) ||
(setfperflag == false && secondperpend == true) ||
mlast <= mnew)
{
okflag = false;
break; }
if ((iter+1 < finalcheckedvec.size()) &&
(firstperpend == true) && (setfperflag == true) &&
(get<0>(finalcheckedvec[iter+1]) !=
get<0>(finalcheckedvec[iter]))) {
actpoint = finalcheckedvec[iter];
mnew = (get<1>(finalcheckedvec[iter+1] ) -
get<1>(actpoint)) /
(get<0>(finalcheckedvec[iter+1]) -
get<0>(actpoint));
mlast = mnew + 1;
setfperflag = false;
}
else {
actpoint = finalcheckedvec[iter];
if ( (iter+1 < finalcheckedvec.size() ) &&
(get<0>(finalcheckedvec[iter+1]) != get<0>(actpoint))&&
(firstmflag == false) ) {
mlast = mnew;
mnew = (get<1>(finalcheckedvec[iter+1] ) -
get<1>(actpoint)) /
(get<0>(finalcheckedvec[iter+1]) -
get<0>(actpoint));
}
else {
/*
mlast ist the first m value
*/
mnew = (get<1>(finalcheckedvec[iter+1] ) -
get<1>(actpoint)) /
(get<0>(finalcheckedvec[iter+1]) -
get<0>(actpoint));
firstmflag = false;
}
}
break;}
case 2:{
if (! ((get<0>(actpoint) <= get<0>(finalcheckedvec[iter])) &&
(get<1>(actpoint) >= get<1>(finalcheckedvec[iter])) ) ||
mlast <= mnew ) {
okflag = false;
break; }
if ( (iter+1 < finalcheckedvec.size() ) &&
(get<0>(finalcheckedvec[iter+1]) != get<0>(actpoint)) &&
(firstmflag == true) ) {
actpoint = finalcheckedvec[iter];
mnew = (get<1>(finalcheckedvec[iter+1] ) -
get<1>(actpoint)) /
(get<0>(finalcheckedvec[iter+1]) -
get<0>(actpoint));
firstmflag = false;
}
else {
actpoint = finalcheckedvec[iter];
mlast = mnew;
mnew = (get<1>(finalcheckedvec[iter+1] ) -
get<1>(actpoint)) /
(get<0>(finalcheckedvec[iter+1]) -
get<0>(actpoint));
}
break;}
case 3:{
if (get<0>(actpoint) == get<0>(finalcheckedvec[iter])&&
(setfperflag == false) ) {
secondperpend = true;
}
if (! ( (get<0>(actpoint) >= get<0>(finalcheckedvec[iter])) &&
(get<1>(actpoint) >= get<1>(finalcheckedvec[iter])) ) ||
(setfperflag == false && secondperpend == true) ||
mlast <= mnew)
{
okflag = false;
break; }
if ((iter+1 < finalcheckedvec.size() ) &&
(firstperpend == true) &&
(setfperflag == true) &&
(get<0>(finalcheckedvec[iter+1]) !=
get<0>(finalcheckedvec[iter]))) {
actpoint = finalcheckedvec[iter];
mnew = (get<1>(finalcheckedvec[iter+1] ) -
get<1>(actpoint)) /
(get<0>(finalcheckedvec[iter+1]) -
get<0>(actpoint));
mlast = mnew + 1;
setfperflag = false;
}
else {
actpoint = finalcheckedvec[iter];
if ((iter+1 < finalcheckedvec.size()) &&
(get<0>(finalcheckedvec[iter+1]) !=
get<0>(actpoint)) &&
(firstmflag == false) ) {
mlast = mnew;
mnew = (get<1>(finalcheckedvec[iter+1] ) -
get<1>(actpoint)) /
(get<0>(finalcheckedvec[iter+1]) -
get<0>(actpoint));
}
else {
/*
mlast ist the first m value
*/
if (get<0>(finalcheckedvec[iter+1]) !=
get<0>(actpoint)) {
mnew = (get<1>(finalcheckedvec[iter+1] ) -
get<1>(actpoint)) /
(get<0>(finalcheckedvec[iter+1]) -
get<0>(actpoint));
}
firstmflag = false;
}
}
break;}
case 4: {
if (! ((get<0>(actpoint) >= get<0>(finalcheckedvec[iter])) &&
(get<1>(actpoint) <= get<1>(finalcheckedvec[iter])) ) ||
mlast <= mnew ) {
okflag = false;
break; }
if ( (iter+1 < finalcheckedvec.size() ) &&
(get<0>(finalcheckedvec[iter+1]) != get<0>(actpoint)) &&
(firstmflag == true) ) {
actpoint = finalcheckedvec[iter];
mnew = (get<1>(finalcheckedvec[iter+1] ) -
get<1>(actpoint)) /
(get<0>(finalcheckedvec[iter+1]) -
get<0>(actpoint));
firstmflag = false;
}
else if (iter+1 < finalcheckedvec.size())
{
actpoint = finalcheckedvec[iter];
mlast = mnew;
mnew = (get<1>(finalcheckedvec[iter+1] ) -
get<1>(actpoint)) /
(get<0>(finalcheckedvec[iter+1]) -
get<0>(actpoint));
}
break;}
}
/*
end of switch
*/
if (okflag == false) break;
iter++;
}
/*
end of while
*/
finalcheckedvec.pop_back();
src = finalcheckedvec;
if (okflag == true)
return 1;
else
return 0;;
}
/*
the end of checkme
*/
/*
4.1 Compare and HasValue
*/
int Convex::Compare(const Convex& arg) const {
if(!IsDefined()){
return arg.IsDefined()?-1:0;
}
if(!arg.IsDefined()){
return 1;
}
if(size != arg.size){
return size < arg.size ? -1 : 1;
}
for(size_t i=0;i<size;i++){
if(value[i].GetX() < arg.value[i].GetX()) return -1;
if(value[i].GetX() > arg.value[i].GetY()) return 1;
if(value[i].GetX() == arg.value[i].GetX()
&&
(value[i].GetY() < arg.value[i].GetY())) return -1;
}
return 0;
}
size_t Convex::HashValue() const {
if(!IsDefined() ) return 0;
if(value==nullptr) return 42;
unsigned int step = size / 2;
if(step<1) step = 1;
size_t pos = 0;
size_t res = 0;
while(pos < size){
res = res + value[pos].HashValue();
pos += step;
}
return res;
}
/*
5.1 In functions
*/
Word Convex::In(const ListExpr typeInfo, const ListExpr le1,
const int errorPos, ListExpr& errorInfo, bool& correct) {
ListExpr le = le1;
ListExpr f, fxpoi, fypoi;
std::vector<std::tuple<double, double>> tmpo;
int checkokflag;
string lexprstr;
Word res = SetWord(Address(0));
if(listutils::isSymbolUndefined(le)){
Convex* co = new Convex(false);
co->SetDefined(false);
res.addr = co;
correct = true;
return res;
}
if(nl->ListLength(le) <= 2){
Convex* co = new Convex(false);
correct = true;
co->SetDefined(false);
res.addr = co;
return res;
}
while(!nl->IsEmpty(le)){
f = nl->First(le);
le = nl->Rest(le);
if(nl->ListLength(f) != 2)
{
correct = true;
nl->WriteToString(lexprstr, f);
Convex* co = new Convex(false);
co->SetDefined(false);
res.addr = co;
return res;
}
fxpoi = nl->First(f);
fypoi = nl->Second(f);
if ( ( nl->IsAtom(fxpoi) && nl->IsAtom(fypoi))
== false)
{
Convex* co = new Convex(false);
correct = true;
co->SetDefined(false);
res.addr = co;
return res;
}
if ( ( (nl->IsAtom(fxpoi) && nl->IsAtom(fypoi)) &&
( (nl->AtomType(fxpoi) == RealType) &&
(nl->AtomType(fypoi) == RealType) )
== false))
{
Convex* co = new Convex(false);
correct = true;
co->SetDefined(false);
res.addr = co;
return res;
}
/*
contructing the vektor of tuples
*/
tmpo.push_back(std::make_tuple(nl->RealValue(fxpoi), nl->RealValue(fypoi)));
}
/*
end of while
*/
/*
CHECKME Call
*/
checkokflag = checkme(tmpo, true);
if (checkokflag == 0) {
ErrorReporter::ReportError(
"1The coordinates do not form a convex polygon");
correct = false;
return res;
}
else {
Convex* r = new Convex(tmpo);
res.addr = r;
correct = true;
//voroVec.push_back(r);
return res;
}
}
/*
5.1 Out function
*/
ListExpr Convex::Out(const ListExpr typeInfo, Word value) {
Convex* is = (Convex*) value.addr;
if(!is->IsDefined()){
return listutils::getUndefined();
}
if(is->size == 0){
return nl->TheEmptyList();
}
ListExpr res = nl->OneElemList(
nl->TwoElemList( nl->RealAtom(is->value[0].GetX()),
nl->RealAtom(is->value[0].GetY())));
ListExpr last = res;
for(unsigned int i=1;i<is->size;i++){
last = nl->Append( last,
nl->TwoElemList ( nl->RealAtom(is->value[i].GetX()),
nl->RealAtom(is->value[i].GetY()) ) );
}
last = nl->Append(last, nl->OneElemList(nl->RealAtom(is->getCellId())));
return res;
}
/*
6.1 Open and save function
*/
bool Convex::Open( SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value){
bool def;
if(!valueRecord.Read(&def, sizeof(bool), offset)){
return false;
}
offset += sizeof(bool);
if(!def){
value.addr = new Convex(false);
return true;
}
size_t size;
if(!valueRecord.Read(&size, sizeof(size_t), offset)){
return false;
}
offset+=sizeof(size_t);
if(size==0){
value.addr = new Convex(0,0,0);
return true;
}
Point* v = new Point[size];
if(!valueRecord.Read(v,size*sizeof(Point),offset)){
return false;
}
for(size_t i=0;i<size;i++){
void* v1 = (void*) &(v[i]);
new (v1) Point();
}
value.addr = new Convex(size,v,0);
return true;
}
bool Convex::Save(SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value) {
Convex* is = (Convex*) value.addr;
bool def = is->IsDefined();
if(!valueRecord.Write(&def, sizeof(bool), offset)){
return false;
}
offset += sizeof(bool);
if(!def){
return true;
}
size_t size = is->size;
if(!valueRecord.Write(&size, sizeof(size_t), offset)){
return false;
}
offset += sizeof(size_t);
if(is->size>0){
if(!valueRecord.Write(is->value, sizeof(Point) * is->size, offset)){
return false;
}
offset += sizeof(int) * is->size;
}
return true;
}
void Convex::Rebuild(char* buffer, size_t sz) {
if(value!=nullptr){
delete[] value;
value = nullptr;
}
size = 0;
bool def;
size_t offset = 0;
memcpy(&def,buffer + offset, sizeof(bool));
offset += sizeof(bool);
if(!def){
SetDefined(false);
return;
}
SetDefined(true);
memcpy(&size, buffer+offset, sizeof(size_t));
offset += sizeof(size_t);
if(size > 0){
value = new Point[size];
memcpy((char*)value, buffer+offset, size * sizeof(Point));
offset += size * sizeof(Point);
}
for(size_t i=0;i<size;i++){
void* v = (void*) &(value[i]);
new (v) Point();
}
memcpy(&cellId, buffer+offset, sizeof(int));
offset += sizeof(int);
}
/*
7.1 Auxillary print function
*/
std::ostream& Convex::Print( std::ostream& os ) const {
if(!IsDefined()){
os << "undefined";
return os;
}
os << "{";
for(size_t i=0;i<size;i++){
if(i>0) os << ", ";
os << value[i];
}
os << "}";
return os;
}
/*
8 Operator Definitions
*/
/*
8.1 TypeMapping Definitions
*/
/*
8.1.1 createconvextypemap
*/
ListExpr createconvextypemap( ListExpr args)
{
if(!nl->HasLength(args,2))
{
return listutils::typeError("two arguments expected");
}
ListExpr arg1 = nl->First(args);
ListExpr arg2 = nl->Second(args);
if(!Stream<Point>::checkType(arg1))
{
return listutils::typeError("first argument must be a stream of points");
}
if(!CcBool::checkType(arg2))
{
return listutils::typeError("second argument must be a Bool Value");
}
return nl->SymbolAtom(Convex::BasicType());
}
/*
8.1.2 voronoitypemap
*/
ListExpr voronoitypemap ( ListExpr args)
{
ListExpr extendconv, stream, namenewattr, attrtype;
ListExpr second, third, secondname, thirdname;
string secondnamestr, thirdnamestr;
int posit1, posit2;
if(nl->ListLength(args)!=5){
ErrorReporter::ReportError("five args expected");
return nl->TypeError();
}
if(nl->AtomType(nl->Second(args))!=SymbolType){
return listutils::typeError("second arg does not represent a valid "
"attribute name");
}
if(nl->AtomType(nl->Third(args))!=SymbolType){
return listutils::typeError("third arg does not represent a valid "
"attribute name");
}
if(!Rectangle<2>::checkType(nl->Fourth(args))){
return listutils::typeError("fourth arg is not a rectangle");
}
if(!CcBool::checkType(nl->Fifth(args))){
return listutils::typeError("fifth arg is not a Bool value");
}
second = nl->Second(args);
third = nl->Third(args);
if ((nl->ListLength(second) != -1 )
|| (nl->ListLength(third) != -1) ) {
ErrorReporter::ReportError("two attribute name arguments expected");
return nl->TypeError();
}
if(!IsStreamDescription(nl->First(args))){
ErrorReporter::ReportError("first argument is not a tuple stream");
return nl->TypeError();
}
stream = nl->First(args);
namenewattr = nl->Third(args);
/*
copy attrlist to newattrlist
*/
ListExpr attrList = nl->Second(nl->Second(stream));
ListExpr newAttrList = nl->OneElemList(nl->First(attrList));
ListExpr lastlistn = newAttrList;
attrList = nl->Rest(attrList);
while (!(nl->IsEmpty(attrList)))
{
lastlistn = nl->Append(lastlistn,nl->First(attrList));
attrList = nl->Rest(attrList);
}
/*
reset attrList
*/
attrList = nl->Second(nl->Second(stream));
secondname = second;
secondnamestr = nl->SymbolValue(secondname);
thirdname = third;
thirdnamestr = nl->SymbolValue(thirdname);
posit1 = FindAttribute(attrList,secondnamestr,attrtype);
if(posit1==0){
ErrorReporter::ReportError("Attribute "+ secondnamestr +
" must be a member of the tuple");
return nl->TypeError();
}
posit2 = FindAttribute(attrList,thirdnamestr,attrtype);
if(posit2!=0){
ErrorReporter::ReportError("Attribute "+ thirdnamestr +
" is already a member of the tuple");
return nl->TypeError();
}
extendconv = nl->SymbolAtom(Convex::BasicType());
lastlistn = nl->Append(lastlistn, (nl->TwoElemList(namenewattr, extendconv)));
return
nl->ThreeElemList(
nl->SymbolAtom(Symbol::APPEND()),
nl->OneElemList(nl->IntAtom(posit1)),
nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
nl->TwoElemList(nl->SymbolAtom(Tuple::BasicType()),
newAttrList)));
}
/*
8.1.3 cellNumber Typemapping
*/
ListExpr cellnumvoronoitypemap ( ListExpr args)
{
if(nl->HasLength(args, 3)) {
ListExpr first = nl->First(args);
ListExpr second = nl->Second(args);
ListExpr third = nl->Third(args);
if(Stream<Convex>::checkType(first) && CcInt::checkType(third)
&& Rectangle<2>::checkType(second)) {
return nl->SymbolAtom(collection::IntSet::BasicType());
}
}
const std::string errMsg = "The following three arguments are expected:"
" Stream<Convex> x rect x int";
return listutils::typeError(errMsg);
}
/*
8.1.4 smallest common cellnumber typemapping
*/
ListExpr sccvoronoitypemap (ListExpr args)
{
if(nl->HasLength(args, 4)) {
ListExpr first = nl->First(args);
ListExpr second = nl->Second(args);
ListExpr third = nl->Third(args);
ListExpr fourth = nl->Fourth(args);
if(Stream<Convex>::checkType(first) && Rectangle<2>::checkType(second)
&& Rectangle<2>::checkType(third)
&& CcInt::checkType(fourth)) {
return nl->SymbolAtom(CcBool::BasicType());
}
}
const std::string errMsg = "The following four arguments are expected:"
" Stream<Convex> x rect x rect x int";
return listutils::typeError(errMsg);
}
/*
8.1.5 getcell typemapping
*/
ListExpr getcellvoronoitypemap ( ListExpr args)
{
if(nl->HasLength(args, 2)) {
ListExpr first = nl->First(args);
ListExpr second = nl->Second(args);
if(Stream<Convex>::checkType(first)
&& CcInt::checkType(second)) {
return nl->SymbolAtom(Rectangle<2>::BasicType());
}
}
const std::string errMsg = "The following two arguments are expected:"
" Stream<Convex> x int";
return listutils::typeError(errMsg);
}
/*
8.1.6 voronoi3dtypemap
*/
ListExpr voronoi3dtypemap( ListExpr args )
{
if(nl->HasLength(args, 2)) {
ListExpr first = nl->First(args);
ListExpr second = nl->Second(args);
if (Stream<Rectangle<3>>::checkType(first)
&& Rectangle<3>::checkType(second)) {
return nl->SymbolAtom(Convex3D::BasicType());
}
}
const string errMsg = "The following two arguments are expected:"
" stream(rect3) x rect3";
return listutils::typeError(errMsg);
}
/*
8.1.7 cellnum 3d typemapping
*/
ListExpr cellnumvoronoi3dtypemap ( ListExpr args)
{
if(nl->HasLength(args, 3)) {
ListExpr first = nl->First(args);
ListExpr second = nl->Second(args);
ListExpr third = nl->Third(args);
if (Convex3D::checkType(first) && CcInt::checkType(third)
&& Rectangle<3>::checkType(second)) {
return nl->SymbolAtom(collection::IntSet::BasicType());
}
}
const std::string errMsg = "The following two arguments are expected:"
" Convex3D x rect3 x int";
return listutils::typeError(errMsg);
}
int voronoi3DCreateSelect( ListExpr args )
{
ListExpr first = nl->First(args);
ListExpr second = nl->Second(args);
if (Stream<Rectangle<3>>::checkType(first)
&& Rectangle<3>::checkType(second)) {
return 0;
}
return -1;
}
/*
8.1.8 smallest common cellnumber typemapping
*/
ListExpr sccvoronoi3dtypemap (ListExpr args)
{
if(nl->HasLength(args, 4)) {
ListExpr first = nl->First(args);
ListExpr second = nl->Second(args);
ListExpr third = nl->Third(args);
ListExpr fourth = nl->Fourth(args);
if(Convex3D::checkType(first)
&& Rectangle<3>::checkType(second)
&& Rectangle<3>::checkType(third)
&& CcInt::checkType(fourth)) {
return nl->SymbolAtom(CcBool::BasicType());
}
}
const std::string errMsg = "The following two arguments are expected:"
" Convex3D x rect3 x rect3 x int";
return listutils::typeError(errMsg);
}
/*
8.1.9 getcell 3d typemapping
*/
ListExpr getcellvoronoi3dtypemap ( ListExpr args)
{
if(nl->HasLength(args, 2)) {
ListExpr first = nl->First(args);
ListExpr second = nl->Second(args);
if(Convex3D::checkType(first) && CcInt::checkType(second)) {
return nl->SymbolAtom(Rectangle<3>::BasicType());
}
}
const std::string errMsg = "The following two arguments are expected:"
" Convex3D x int";
return listutils::typeError(errMsg);
}
/*
8.2 ValueMapping Definitions
*/
/*
8.2.1 cellNumVM
*/
int cellNumVM( Word* args, Word& result, int message,
Word& local, Supplier s )
{
if(voroVec.size() == 0) {
Stream<Convex> input_convex(args[0]);
input_convex.open();
Convex* next = input_convex.request();
while(next != 0){
voroVec.push_back(*next);
// free memory
delete next;
next = input_convex.request();
}
input_convex.close();
}
Rectangle<2> *search_window_ptr
= static_cast<Rectangle<2>*>( args[1].addr );
/*
mode == 1 => precise allocation;
mode == 2 => use Bboxes of convex cells
In case the user did not specify
the mode of allocation, use Bboxes
*/
int mode = ((CcInt*)args[2].addr)->GetIntval();
std::set<int> cell_ids;
int bbox = 2;
int precise = 1;
result = qp->ResultStorage(s);
collection::IntSet* res = (collection::IntSet*) result.addr;
if(search_window_ptr == nullptr) {
return 1;
}
if(mode > bbox || mode < precise) {
mode = bbox;
}
cellNum(search_window_ptr, mode, &cell_ids);
res->setTo(cell_ids);
if(voroVec.size() > 0) {
voroVec.clear();
}
return 0;
}
/*
8.2.2 smallestCommonCellnumVM
*/
int smallestCommonCellnumVM( Word* args, Word& result, int message,
Word& local, Supplier s )
{
Stream<Convex> input_convex(args[0]);
input_convex.open();
Convex* next = input_convex.request();
while(next != 0){
voroVec.push_back(*next);
delete next;
next = input_convex.request();
}
input_convex.close();
Rectangle<2> *search_window_ptr
= static_cast<Rectangle<2>*>( args[1].addr );
Rectangle<2> *search_window_ptr_2
= static_cast<Rectangle<2>*>( args[2].addr );
CcInt* cellno_ptr = static_cast<CcInt*>(args[3].addr);
int cellno = cellno_ptr->GetIntval();
if(search_window_ptr == nullptr
|| search_window_ptr_2 == nullptr) {
return -1;
}
result = qp->ResultStorage( s );
CcBool *res = (CcBool*) result.addr;
bool boolval = false;
std::set<int> intsetRect1;
std::set<int> intsetRect2;
cellNum(search_window_ptr, 1, &intsetRect1);
if (intsetRect1.find(cellno) != intsetRect1.end())
{
cellNum(search_window_ptr_2, 1, &intsetRect2);
std::vector<int> v(sizeof(intsetRect1)+ sizeof(intsetRect2));
std::vector<int>::iterator it;
it=std::set_intersection (intsetRect1.begin(), intsetRect1.end(),
intsetRect2.begin(), intsetRect2.end(), v.begin());
v.resize(it-v.begin());
if(v.empty()) {
//no intersection between rectangles
res->Set( true, boolval);
return 0;
}
if(v[0] == cellno)
{
boolval = true;
}
if(v.size() > 0)
{
v.clear();
}
}
if(intsetRect1.size() > 0)
{
intsetRect1.clear();
}
if(intsetRect2.size() > 0)
{
intsetRect2.clear();
}
if(voroVec.size() > 0)
{
voroVec.clear();
}
res->Set( true, boolval);
return 0;
}
/*
8.2.3 getCellVM
*/
int getcellvoronoiVM(Word* args, Word& result, int message,
Word& local, Supplier s)
{
Stream<Convex> input_convex(args[0]);
input_convex.open();
Convex* next = input_convex.request();
while(next != 0){
voroVec.push_back(*next);
delete next;
next = input_convex.request();
}
input_convex.close();
CcInt* cellno_ptr = static_cast<CcInt*>(args[1].addr);
int cellno = cellno_ptr->GetIntval();
if (voroVec.size() > 0 )
{
result = qp->ResultStorage( s );
Rectangle<2> *res = (Rectangle<2>*) result.addr;
for(size_t i = 0; i < voroVec.size(); i++)
{
if(voroVec[i].getCellId() == cellno)
{
double min[2], max[2];
Rectangle<2> bbox = createBBox(&voroVec[i]);
min[0] = bbox.getMinX();
min[1] = bbox.getMinY();
max[0] = bbox.getMaxX();
max[1] = bbox.getMaxY();
res->Set(true, min, max);
return 0;
}
}
}
return -1;
}
/*
8.2.4 createconvexVM
*/
int createconvexVM (Word* args, Word& result,
int message, Word& local, Supplier s)
{
qp->DeleteResultStorage(s);
qp->ReInitResultStorage(s);
result = qp->ResultStorage(s);
Stream<Point> stream(args[0]);
Convex* res = static_cast<Convex*>(result.addr);
Point* elem;
vector<Point> points;
std::vector<std::tuple<double, double>> temp;
int checkgood;
CcBool* checkonp = ((CcBool*)args[1].addr);
if (!checkonp->IsDefined()) {
res->SetDefined(false);
return 0;
}
bool checkon = checkonp->GetBoolval();
stream.open();
while ( (elem = stream.request() ) ){
if (!elem->IsDefined()) {
res->SetDefined(false);
return 0;
}
/*
contructing the vektor of tuples
*/
temp.push_back(std::make_tuple(elem->GetX(), elem->GetY()));
}
if (checkon == true) {
checkgood = checkme(temp, true);
}
else {
checkgood = checkme(temp, false);
}
if ((checkgood == 1) || (checkgood == 2)) {
res -> setTo(temp, -1);;
stream.close();
return 0;
}
else {
stream.close();
return 0;
}
}
/*
8.2.3 voronoiVM
*/
struct voronoiInfo {
map<std::tuple<double, double>,
std::vector<std::tuple<double, double>> > center2vorpoi;
TupleBuffer *rel;
GenericRelationIterator *reliter;
int attrcount;
int pointposition;
bool checkon;
int cellId;
};
int voronoiVM (Word* args, Word& result, int message, Word& local, Supplier s)
{
Word tee;
Tuple* tup;
voronoiInfo* localInfo = (voronoiInfo*) qp->GetLocal2(s).addr;
std::vector<VoronoiPoint> voropoints;
voronoi_diagram<double> vorodiag;
double xval, yval;
switch (message)
{
/*
voronoiVM-open
*/
case OPEN: {
localInfo = new voronoiInfo;
qp->GetLocal2(s).addr = localInfo;
ListExpr resultType = GetTupleResultType(s);
TupleType *tupleType = new TupleType(nl->Second(resultType));
local.addr = tupleType;
ListExpr attrsave = qp->GetType(qp->GetSon(s,0));
ListExpr attrsave2 = nl->Second(nl->Second(attrsave));
int counter = 0;
int counttup = 0;
localInfo->reliter = 0;
int pointpos = ((CcInt*)args[5].addr)->GetIntval();
Rectangle<2>* rectme = (Rectangle<2>*) args[3].addr;
double belowleftx,belowlefty, belowrightx, belowrighty, aboveleftx,
abovelefty, aboverightx, aboverighty, miny, minx, maxx, maxy;
double scale = 50;
double stretchx = 0;
double stretchy = 0;
double diaglenght;
double testpointstretch;
bool scalereset = false;
std::tuple<double, double> center;
std::tuple<double, double> testcenter;
std::vector<std::tuple<double, double>> voropoi;
std::vector<std::tuple<double, double>> allpoints;
std::vector<std::tuple<double, double>> infedgecenter;
std::vector<std::tuple<double, double>> voropoitemp;
std::vector<std::tuple<double, double>> infedgepoints;
std::vector<std::tuple<double, double>> normaledgepoints;
map<std::tuple<double, double>,
std::tuple<double, double>> infcenter2firstinfedgepoi;
map<std::tuple<double, double>,
std::tuple<double, double>> infcenter2secondinfedgepoi;
map<std::tuple<double, double>,
std::vector<std::tuple<double, double>> > infedgepoi2lineparam;
map<std::tuple<double, double>,
std::vector<std::tuple<double, double>> > infcenter2neighborcenters;
map<std::tuple<double, double>,
std::vector<std::tuple<double, double>>>
normaledgepoints2normalcenters;
map<std::tuple<double, double>,
std::vector<std::tuple<double, double>> > infedgepoints2centers;
std::tuple<double, double> aboveleft, aboveright, belowleft, belowright;
std::tuple<double, double> testpoint1, testpoint2;
std::tuple<double, double> newpoint1, newpoint2;
map<std::tuple<double, double>,
std::vector<std::tuple<double, double>>>::
iterator iterone = normaledgepoints2normalcenters.begin();
map<std::tuple<double, double>,
std::vector<std::tuple<double, double>>>::
iterator itedge = infedgepoints2centers.begin();
map<std::tuple<double, double>,
std::vector<std::tuple<double, double>>>::
iterator itlineparam = infedgepoi2lineparam.begin();
/*
storing pointpos in localInfo
*/
localInfo->pointposition = pointpos;
if (!((CcBool*)args[4].addr)->IsDefined()) {
localInfo->checkon = true;
}
else {
/*
storing bool in localInfo
*/
localInfo->checkon = ((CcBool*)args[4].addr)->GetBoolval();
}
while (!(nl->IsEmpty(attrsave2)))
{
attrsave2 = nl->Rest(attrsave2);
/*
counting the attributes
*/
counter++;
}
/*
Init localInfo
*/
localInfo->attrcount = counter;
qp->Open(args[0].addr);
qp->Request(args[0].addr, tee);
if(qp->Received(args[0].addr))
{
localInfo->rel = new TupleBuffer( );
}
else
{
localInfo->rel = 0;
}
while(qp->Received(args[0].addr))
{
/*
storing tuples in localInfo
*/
Tuple *tup2 = (Tuple*)tee.addr;
localInfo->rel->AppendTuple( tup2 );
counttup++;
/*
Setting up the VoroPoint vector
*/
Point* pointval = static_cast<Point*>(tup2->GetAttribute(pointpos-1));
if(pointval->IsDefined()) {
xval = pointval->GetX();
yval = pointval->GetY();
voropoints.push_back(VoronoiPoint(xval, yval));
allpoints.push_back(std::make_tuple(xval, yval));
}
tup2->DeleteIfAllowed();
qp->Request(args[0].addr, tee);
}
if( localInfo->rel)
{
localInfo->reliter = localInfo->rel->MakeScan();
}
else
{
localInfo->reliter = 0;
}
/*
constructing the voronoi diagramm using the boost library
*/
construct_voronoi(voropoints.begin(), voropoints.end(), &vorodiag);
int contzell = 0;
unsigned int cell_index = 0;
for (voronoi_diagram<double>::const_cell_iterator it =
vorodiag.cells().begin();
it != vorodiag.cells().end(); ++it) {
contzell++;
if (it->contains_point()) {
if (it->source_category() ==
boost::polygon::SOURCE_CATEGORY_SINGLE_POINT) {
std::size_t index = it->source_index();
VoronoiPoint p = voropoints[index];
center = std::make_tuple(x(p), y(p));
voropoitemp.push_back ( std::make_tuple(x(p), y(p)));
const voronoi_diagram<double>::cell_type& cell = *it;
const voronoi_diagram<double>::edge_type* edge = cell.incident_edge();
/*
iterate edges around voronoi cell
*/
do {
if (true) {
if( (edge->vertex0() != NULL) &&
(edge->vertex1() != NULL)) {
std::tuple<double, double>
edgepoitemp1 = std::make_tuple((edge->vertex0())->x(),
(edge->vertex0())->y());
std::tuple<double, double>
edgepoitemp2 = std::make_tuple((edge->vertex1())->x(),
(edge->vertex1())->y());
voropoi.push_back(edgepoitemp1);
voropoi.push_back(edgepoitemp2);
allpoints.push_back(edgepoitemp1);
allpoints.push_back(edgepoitemp2);
std::tuple<double, double> edgecentertemp = std::make_tuple(x(p), y(p));
std::vector<std::tuple<double, double>> vectemp;
vectemp.push_back (edgecentertemp);
normaledgepoints.push_back(edgepoitemp1);
normaledgepoints.push_back(edgepoitemp2);
iterone = normaledgepoints2normalcenters.find(edgepoitemp1);
/*
edgepoint not set yet
*/
if (iterone == normaledgepoints2normalcenters.end()) {
normaledgepoints2normalcenters.insert
(pair<std::tuple<double, double>,
std::vector<std::tuple<double, double>>>
(edgepoitemp1, vectemp));
}
/*
edgepoint entry exists already
*/
else {
normaledgepoints2normalcenters.at(edgepoitemp1).push_back(
edgecentertemp);
rmvredundpoints(normaledgepoints2normalcenters.at(edgepoitemp1));
}
iterone = normaledgepoints2normalcenters.find(edgepoitemp2);
/*
edgepoint not set yet
*/
if (iterone == normaledgepoints2normalcenters.end()) {
normaledgepoints2normalcenters.insert
(pair<std::tuple<double, double>,
std::vector<std::tuple<double, double>>>
(edgepoitemp2, vectemp));
}
/*
edgepoint entry exists already
*/
else {
normaledgepoints2normalcenters.at(edgepoitemp2).push_back
(edgecentertemp);
rmvredundpoints(normaledgepoints2normalcenters.at(edgepoitemp2));
}
}
if ( (edge->vertex0() != NULL) &&
(edge->vertex1() == NULL)) {
std::tuple<double, double>
edgepoitemp4 = std::make_tuple((edge->vertex0())->x(),
(edge->vertex0())->y());
std::vector<std::tuple<double, double>> vectemp3;
std::tuple<double, double> twincenter;
allpoints.push_back(edgepoitemp4);
infedgecenter.push_back(center);
infedgepoints.push_back(edgepoitemp4);
voropoi.push_back(edgepoitemp4);
if ( ((edge->twin())->cell())->contains_point()) {
if (((edge->twin())->cell())->source_category() ==
boost::polygon::SOURCE_CATEGORY_SINGLE_POINT) {
std::size_t index = ((edge->twin())->cell())->source_index();
VoronoiPoint q = voropoints[index];
twincenter = std::make_tuple(x(q), y(q));
}
}
itedge = infedgepoints2centers.find(edgepoitemp4);
/*
edgepoint not set yet
*/
if (itedge == infedgepoints2centers.end()) {
vectemp3.push_back(center);
vectemp3.push_back(twincenter);
infedgepoints2centers.insert
(pair<std::tuple<double, double>,
std::vector<std::tuple<double, double>>>
(edgepoitemp4, vectemp3));
}
/*
edgepoint entry exists already
*/
else {
infedgepoints2centers.at(edgepoitemp4).push_back(center);
infedgepoints2centers.at(edgepoitemp4).push_back(twincenter);
}
}
if( (edge->vertex1() != NULL) &&
(edge->vertex0() == NULL)) {
allpoints.push_back(
std::make_tuple((edge->vertex1())->x(),
(edge->vertex1())->y()));
infedgecenter.push_back(std::make_tuple(x(p), y(p)));
infedgepoints.push_back(
std::make_tuple((edge->vertex1())->x(),
(edge->vertex1())->y()));
voropoi.push_back(std::make_tuple((edge->vertex1())->x(),
(edge->vertex1())->y()));
}
}
edge = edge->next();
} while (edge != cell.incident_edge());
}
++cell_index;
}
rmvredundpoints(voropoi);
localInfo->center2vorpoi.insert
(pair<std::tuple<double, double>,
std::vector<std::tuple<double, double>>>
(center, voropoi));
voropoi.clear();
/*
cleared for the next cell
*/
}
/*
setting up border handling of the voronoi cells
*/
/*
remove redundant points
*/
rmvredundpoints(allpoints);
rmvredundpoints(infedgecenter);
rmvredundpoints(infedgepoints);
/*
compute minx, maxx, miny and maxy from allpoints
*/
sort(allpoints.begin(), allpoints.end(), sortyupxup);
miny = get<1>(allpoints[0]);
maxy = get<1>(allpoints[allpoints.size()-1]);
sort(allpoints.begin(), allpoints.end(), sortxupyup);
minx = get<0>(allpoints[0]);
maxx = get<0>(allpoints[allpoints.size()-1]);
/*
Voronoi Border handling
*/
/*
testing if box is fitting and rectangle value defined
*/
if ( (rectme->IsDefined()) &&
( (rectme->MinD(0) < minx) && (rectme->MaxD(0) > maxx) &&
(rectme->MinD(1) < miny) && (rectme->MaxD(1) > maxy) ) ) {
/*
receiving box points from rectangle
*/
belowleftx = rectme->MinD(0);
belowlefty = rectme->MinD(1);
belowrightx = rectme->MaxD(0);
belowrighty = rectme->MinD(1);
aboveleftx = rectme->MinD(0);
abovelefty = rectme->MaxD(1);
aboverightx = rectme->MaxD(0);
aboverighty = rectme->MaxD(1);
}
/*
use the dafault box if box is not fitting or
if rectangle value is undefined
*/
else {
stretchx = (abs(maxx - minx)) / 4;
stretchy = (abs(maxy - miny)) / 4;
belowleftx = minx - stretchx;
belowlefty = miny - stretchy;
belowrightx = maxx + stretchx;
belowrighty = miny - stretchy;
aboveleftx = minx - stretchx;
abovelefty = maxy + stretchy;
aboverightx = maxx + stretchx;
aboverighty = maxy + stretchy;
}
/*
construct box points
*/
aboveleft = std::make_tuple(aboveleftx, abovelefty);
aboveright = std::make_tuple(aboverightx, aboverighty);
belowright = std::make_tuple(belowrightx, belowrighty);
belowleft = std::make_tuple(belowleftx, belowlefty);
diaglenght = sqrt (pow (get<0>(belowleft) - get<0>(aboveright), 2) +
pow (get<1>(belowleft) - get<1>(aboveright), 2));
/*
constructing a point and the corresponding
straight line equation for infinite edges
*/
for (unsigned int i = 0; i < infedgepoints.size(); i++) {
itedge = infedgepoints2centers.find(infedgepoints[i]);
if (itedge != infedgepoints2centers.end()) {
std::vector<std::tuple<double, double>> pairvec =
infedgepoints2centers.at(infedgepoints[i]);
if ((pairvec.size() % 2) == 0) {
for (unsigned int j = 0; j < pairvec.size(); j=j+2) {
std::tuple<double, double> infovec5 = pairvec[j];
std::tuple<double, double> infovec6 = pairvec[j+1];
double xfirst = get<0>(infovec5);
double xsecond = get<0>(infovec6);
double yfirst = get<1>(infovec5);
double ysecond = get<1>(infovec6);
/*
The result point lies on the corresponding
straight line equation of the infinite edge
*/
double resultx = (xfirst + xsecond) / 2;
double resulty = (yfirst + ysecond) / 2;
if ( !(xfirst == xsecond) &&
!(AlmostEqual(xfirst, xsecond)) &&
!(yfirst == ysecond) &&
!(AlmostEqual(yfirst, ysecond)) ) {
/*
m and b are the straight line equation parameters for the line
that goes through the 2 center points.
We only need the gradient m here.
*/
double m = (ysecond - yfirst) / (xsecond - xfirst);
/*
mm and bb are the straight line equation parameters for the line
that goes through the infinte edge between the 2 centers
The two straight lines are always perpendicular to each other,
so you can determine mm from m.
*/
double mm = - 1/m;
double bb = resulty - (mm * resultx);
std::vector<std::tuple<double, double>> paramvec;
std::tuple<double, double> param = std::make_tuple(mm ,bb);
itlineparam = infedgepoi2lineparam.find(infedgepoints[i]);
/*
edgepointto param not set
*/
if (itlineparam == infedgepoi2lineparam.end()) {
paramvec.push_back(param);
infedgepoi2lineparam.insert
(pair<std::tuple<double, double>,
std::vector<std::tuple<double, double>>>
(infedgepoints[i], paramvec));
}
/*
edgepoint entry exists already
*/
else {
infedgepoi2lineparam.at(infedgepoints[i]).push_back(param);
}
}
/*
the 2 centers form a straight line with gradient 0
*/
else if ( (yfirst == ysecond) || (AlmostEqual(yfirst, ysecond)) ) {
double dummy = std::numeric_limits<double>::infinity();
std::tuple<double, double> dummytup = std::make_tuple(dummy ,dummy);
std::vector<std::tuple<double, double>> paramvec2;
/*
just pushing an infinty value for identification purposes
*/
itlineparam = infedgepoi2lineparam.find(infedgepoints[i]);
/*
edgepointto param not set
*/
if (itlineparam == infedgepoi2lineparam.end()) {
paramvec2.push_back(dummytup);
infedgepoi2lineparam.insert
(pair<std::tuple<double, double>,
std::vector<std::tuple<double, double>>>
(infedgepoints[i], paramvec2));
}
/*
edgepoint entry exists already
*/
else {
infedgepoi2lineparam.at(infedgepoints[i]).push_back(dummytup);
}
}
else {
/*
the two centers are perpendicular
*/
double mmm = 0;
double bbb = resulty - (mmm * resultx);
std::vector<std::tuple<double, double>> paramvec3;
std::tuple<double, double> para = std::make_tuple(mmm ,bbb);
itlineparam = infedgepoi2lineparam.find(infedgepoints[i]);
/*
edgepointto param not set
*/
if (itlineparam == infedgepoi2lineparam.end()) {
paramvec3.push_back(para);
infedgepoi2lineparam.insert
(pair<std::tuple<double, double>,
std::vector<std::tuple<double, double>>>
(infedgepoints[i], paramvec3));
}
/*
edgepoint entry exists already
*/
else {
infedgepoi2lineparam.at(infedgepoints[i]).push_back(para);
}
}
}
/*
end of second for
*/
}
/*
nothing has to be done here
*/
}
/*
no entry found, should not happen
*/
}
/*
end of first for
*/
/*
Calculating points on the border lines
and the correpondending cells
*/
for (unsigned int i = 0; i < infedgepoints.size(); i++) {
itlineparam = infedgepoi2lineparam.find(infedgepoints[i]);
if (itlineparam != infedgepoi2lineparam.end()) {
std::vector<std::tuple<double, double>> paramvector =
infedgepoi2lineparam.at(infedgepoints[i]);
for (unsigned int j = 0; j < paramvector.size(); j++) {
std::tuple<double, double> lineinfo =
paramvector[j];
double m = get<0>(lineinfo);
double t = get<1>(lineinfo);
std::vector<std::tuple<double, double>> vec =
infedgepoints2centers.at(infedgepoints[i]);
/*
get center coords
*/
std::tuple<double, double> center1 = vec[2*j];
std::tuple<double, double> center2 = vec[(2*j) + 1];
double xfirst = get<0>(center1);
double xsecond = get<0>(center2);
double yfirst = get<1>(center1);
double ysecond = get<1>(center2);
double resultx = (xfirst + xsecond) / 2;
double resulty = (yfirst + ysecond) / 2;
std::tuple<double, double> testp1 = std::make_tuple(resultx, resulty);
std::tuple<double, double> testp2 = infedgepoints[i];
std::tuple<double, double> testpfinal =
std::make_tuple ((resultx + get<0>(testp2)) / 2,
(resulty + get<1>(testp2)) / 2);
/*
normaledgepoints2normalcenters output
*/
iterone = normaledgepoints2normalcenters.find(infedgepoints[i]);
if (iterone != normaledgepoints2normalcenters.end()) {
std::vector<std::tuple<double, double>> centerinfovec =
normaledgepoints2normalcenters.at(infedgepoints[i]);
for (unsigned int j = 0; j < centerinfovec.size(); j++) {
if ((centerinfovec[j] != center1) && (centerinfovec[j] != center2)) {
std::tuple<double, double> testc = centerinfovec[j];
testcenter = testc;
}
}
}
bool cond1 = ( ((get<0>(testcenter) >= get<0>(testp1)) &&
(get<0>(testcenter) <= get<0>(testpfinal)) &&
(get<0>(testp1) <= get<0>(testpfinal))) ||
((get<0>(testcenter) <= get<0>(testp1)) &&
(get<0>(testcenter) >= get<0>(testpfinal)) &&
(get<0>(testp1) >= get<0>(testpfinal))) ||
((get<1>(testcenter) >= get<1>(testp1)) &&
(get<1>(testcenter) <= get<1>(testpfinal)) &&
(get<1>(testp1) <= get<1>(testpfinal))) ||
((get<1>(testcenter) <= get<1>(testp1)) &&
(get<1>(testcenter) >= get<1>(testpfinal)) &&
(get<1>(testp1) >= get<1>(testpfinal))) );
/*
change testpfinal if necessary
*/
if (cond1 == true) {
testpfinal = testp1;
scale = 200;
scalereset = true;
}
if ( ((cond1 != true) && (get<0>(testcenter) > get<0>(testp1)) &&
(get<1>(testcenter) > get<1>(testp1))) ||
((cond1 != true) && (get<0>(testcenter) < get<0>(testp1)) &&
(get<1>(testcenter) < get<1>(testp1))) ) {
testpfinal = testp1;
scale = 30;
scalereset = true;
}
testpointstretch = diaglenght/scale;
if (scalereset == true) scale = 50;
if (isinf(m) && isinf(t)) {
testpoint1 = std::make_tuple(get<0>( testpfinal),
get<1>( testpfinal) +
testpointstretch);
testpoint2 = std::make_tuple(get<0>( testpfinal),
get<1>( testpfinal) -
testpointstretch);
}
else if (m==0) {
testpoint1 = std::make_tuple(get<0>( testpfinal) +
testpointstretch, get<1>( testpfinal));
testpoint2 = std::make_tuple(get<0>( testpfinal) -
testpointstretch, get<1>( testpfinal));
}
else {
testpoint1 = std::make_tuple(get<0>( testpfinal) +
testpointstretch,
m * (get<0>( testpfinal) +
testpointstretch) + t);
testpoint2 = std::make_tuple(get<0>( testpfinal) -
testpointstretch,
m * (get<0>( testpfinal) -
testpointstretch) + t);
}
/*
Euklidien distance to testcenter
*/
double distinfedgpoitotestcenter = sqrt
(pow (get<0>(testpfinal) -
get<0>(testcenter), 2) +
pow (get<1>(testpfinal) -
get<1>(testcenter), 2));
double distinfedgpoitotestpoint1 = sqrt
(pow (get<0>(testpoint1) -
get<0>(testcenter), 2) +
pow (get<1>(testpoint1) -
get<1>(testcenter), 2));
double distinfedgpoitotestpoint2 = sqrt
(pow (get<0>(testpoint2) -
get<0>(testcenter), 2) +
pow (get<1>(testpoint2) -
get<1>(testcenter), 2));
/*
looking for points added to center voropoints
*/
if ( (distinfedgpoitotestpoint1 > distinfedgpoitotestcenter) &&
( (distinfedgpoitotestpoint2 <= distinfedgpoitotestcenter) ||
(distinfedgpoitotestpoint1 > distinfedgpoitotestpoint2))) {
if (isinf(m) && isinf(t)) {
newpoint1 = std::make_tuple(get<0>(infedgepoints[i]),
aboverighty);
}
else if (m==0) {
newpoint1 = std::make_tuple(belowrightx,
get<1>(infedgepoints[i]));
}
/*
case m<0
*/
else if (m<0) {
std::tuple<double, double> newpoint1cand1;
std::tuple<double, double> newpoint1cand2;
double newxval = (belowrighty - t) / m;
double newyval = (m * belowrightx) + t;
newpoint1cand1 = std::make_tuple(belowrightx, newyval);
newpoint1cand2 = std::make_tuple(newxval, belowrighty);
if ( ((belowrightx == newxval) &&
(belowrighty == newyval)) ||
(AlmostEqual (belowrightx, newxval) &&
AlmostEqual (belowrighty, newyval)) ) {
newpoint1 = std::make_tuple (belowrightx,
belowrighty);
}
if ((newxval > belowrightx) && (newyval > belowrighty) &&
(newyval < aboverighty) ) {
newpoint1 = newpoint1cand1;
}
else if ((newyval < belowrighty) &&
(newxval < belowrightx) &&
(newxval > belowleftx) ) {
newpoint1 = newpoint1cand2;
}
}
/*
case m>0
*/
else
{
std::tuple<double, double> newpoint1cand1;
std::tuple<double, double> newpoint1cand2;
double newxval = (aboverighty - t) / m;
double newyval = (m * aboverightx) + t;
newpoint1cand1 = std::make_tuple(aboverightx, newyval);
newpoint1cand2 = std::make_tuple(newxval, aboverighty);
if ( ((aboverightx == newxval) &&
(aboverighty == newyval)) ||
(AlmostEqual (aboverightx, newxval) &&
AlmostEqual (aboverighty, newyval)) ) {
newpoint1 = std::make_tuple (aboverightx,
aboverighty);
}
if ((newxval > aboverightx) &&
(newyval > belowrighty) &&
(newyval < aboverighty) ) {
newpoint1 = newpoint1cand1;
}
else if ((newyval > aboverighty) &&
(newxval < belowrightx) &&
(newxval > belowleftx) ) {
newpoint1 = newpoint1cand2;
}
}
localInfo->center2vorpoi.at(center1).push_back (newpoint1);
localInfo->center2vorpoi.at(center2).push_back (newpoint1);
}
/*
case m=0
*/
else if ( (distinfedgpoitotestpoint2 > distinfedgpoitotestcenter) &&
( (distinfedgpoitotestpoint1 <= distinfedgpoitotestcenter) ||
(distinfedgpoitotestpoint2 > distinfedgpoitotestpoint1))) {
if (isinf(m) && isinf(t)) {
newpoint2 = std::make_tuple(get<0>(infedgepoints[i]),
belowrighty);
}
else if (m==0) {
newpoint2 = std::make_tuple(belowleftx,
get<1>(infedgepoints[i]));
}
/*
case m<0
*/
else if (m<0) {
std::tuple<double, double> newpoint1cand1;
std::tuple<double, double> newpoint1cand2;
double newxval = (abovelefty - t) / m;
double newyval = (m * aboveleftx) + t;
newpoint1cand1 = std::make_tuple(aboveleftx, newyval);
newpoint1cand2 = std::make_tuple(newxval, abovelefty);
if ( ((aboveleftx == newxval) &&
(abovelefty == newyval)) ||
(AlmostEqual (aboveleftx, newxval) &&
AlmostEqual (abovelefty, newyval)) ) {
newpoint2 = std::make_tuple (aboveleftx, abovelefty);
}
if ((newxval < aboveleftx) && (newyval > belowlefty) &&
(newyval < abovelefty) ) {
newpoint2 = newpoint1cand1;
}
else if ((newyval > abovelefty) &&
(newxval < belowrightx) &&
(newxval > belowleftx) ) {
newpoint2 = newpoint1cand2;
}
}
/*
case m>0
*/
else {
std::tuple<double, double> newpoint1cand1;
std::tuple<double, double> newpoint1cand2;
double newxval = (belowlefty - t) / m;
double newyval = (m * belowleftx) + t;
newpoint1cand1 = std::make_tuple(belowleftx, newyval);
newpoint1cand2 = std::make_tuple(newxval, belowlefty);
if ( ((belowleftx == newxval) &&
(belowlefty == newyval)) ||
(AlmostEqual (belowleftx, newxval) &&
AlmostEqual (belowlefty, newyval)) ) {
newpoint2 = std::make_tuple (belowleftx, belowlefty);
}
if ((newxval < belowleftx) &&
(newyval > belowlefty) &&
(newyval < abovelefty) ) {
newpoint2 = newpoint1cand1;
}
else if ((newyval < belowlefty) &&
(newxval < belowrightx) &&
(newxval > belowleftx) ) {
newpoint2 = newpoint1cand2;
}
}
localInfo->center2vorpoi.at(center1).push_back (newpoint2);
localInfo->center2vorpoi.at(center2).push_back (newpoint2);
}
/*
nothing is done here
*/
}
/*
end of second for
*/
}
/*
end of first if
*/
}
/*
end of for
*/
/*
distribute the 4 box edge points to the right voronoicells
*/
for (unsigned int i = 0; i < infedgecenter.size(); i++) {
int countymaxvals = 0;
int countyminvals = 0;
int countxminvals = 0;
int countxmaxvals = 0;
std::vector<std::tuple<double, double>> infovec =
localInfo->center2vorpoi.at(infedgecenter[i]);
/*
counting the cases
*/
for (unsigned int j = 0; j < infovec.size(); j++) {
if (get<0>(infovec[j]) == belowleftx) countxminvals++;
if (get<0>(infovec[j]) == belowrightx) countxmaxvals++;
if (get<1>(infovec[j]) == belowlefty) countyminvals++;
if (get<1>(infovec[j]) == abovelefty) countymaxvals++;
}
/*
distribute the new points
*/
if ((countxminvals == 1) && (countyminvals == 1)) {
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(belowleft);
}
else if ((countxminvals == 1) && (countymaxvals == 1)) {
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(aboveleft);
}
else if ((countxmaxvals == 1) && (countymaxvals == 1)) {
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(aboveright);
}
else if ((countxmaxvals == 1) && (countyminvals == 1)) {
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(belowright);
}
else if ((countyminvals == 1) && (countymaxvals == 1)) {
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(belowright);
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(aboveright);
}
/*
special case
*/
else if ( (countyminvals == 1) && (countymaxvals == 1) &&
(get<0>(infedgecenter[i]) >
((belowleftx + belowrightx) / 2)) ) {
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(belowright);
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(aboveright);
}
/*
special case
*/
else if ( (countyminvals == 1) && (countymaxvals == 1) &&
(get<0>(infedgecenter[i]) <
((belowleftx + belowrightx) / 2)) ) {
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(belowleft);
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(aboveleft);
}
/*
special case
*/
else if ( (countxminvals == 1) && (countxmaxvals == 1) &&
(get<1>(infedgecenter[i]) <
((belowlefty + abovelefty) / 2)) ) {
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(belowleft);
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(belowright);
}
/*
special case
*/
else if ( (countxminvals == 1) && (countxmaxvals == 1) &&
(get<1>(infedgecenter[i]) >
((belowlefty + abovelefty) / 2)) ) {
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(aboveleft);
localInfo->center2vorpoi.at(infedgecenter[i]).push_back
(aboveright);
}
}
return 0;
}
/*
voronoiVM-request
*/
case REQUEST: {
TupleType *tupleType = (TupleType*)local.addr;
Tuple *newTuple = new Tuple( tupleType );
map<std::tuple<double, double>, std::vector<std::tuple<double, double>>>::
iterator iter=localInfo->center2vorpoi.begin();
int maxattrpos = 0;
std::vector<std::tuple<double, double>> tmpo;
std::vector<std::tuple<double, double>> dummy;
int checkokflag;
double xv, yv;
int pointposit = localInfo->pointposition;
std::tuple<double, double> search;
/*
calculate max attribute position
*/
maxattrpos = localInfo->attrcount - 1;
/*
get point coords
*/
if ((tup = localInfo->reliter->GetNextTuple()) != 0 ) {
Point* pointval = static_cast<Point*>(tup->GetAttribute(pointposit-1));
// Convex cell id corresponds to tupleId
int cell_Id = (int)tup->GetTupleId();
if(pointval->IsDefined()) {
xv = pointval->GetX();
yv = pointval->GetY();
}
search = std::make_tuple(xv, yv);
iter = localInfo->center2vorpoi.find(search);
if (iter !=localInfo->center2vorpoi.end()) {
/*
setting up the new tuple
*/
for( int i = 0; i < tup->GetNoAttributes(); i++ ) {
newTuple->CopyAttribute( i, tup, i );
}
tmpo = localInfo->center2vorpoi.at(search);
checkokflag = checkme(tmpo, localInfo->checkon);
if ((checkokflag == 1) || (checkokflag == 2)) {
Convex* conv = new Convex(tmpo, cell_Id);
voroVec.push_back(*conv);
newTuple->PutAttribute(maxattrpos+1, conv);
result = SetWord(newTuple);
}
else {
Convex* conv = new Convex(false);
newTuple->PutAttribute(maxattrpos+1, conv);
result = SetWord(newTuple);
}
return YIELD;
}
else {
/*
not possible
*/
Convex* conv2 = new Convex(false);
for( int i = 0; i < tup->GetNoAttributes(); i++ ) {
newTuple->CopyAttribute( i, tup, i );
}
newTuple->PutAttribute(maxattrpos+1, conv2);
result = SetWord(newTuple);
return YIELD;
}
return YIELD;
/*
never happens
*/
}
else {
delete newTuple;
return CANCEL;
}
return 0;
}
/*
voronoiVM-close
*/
case CLOSE : {
if(localInfo){
if( localInfo->reliter != 0 )
delete localInfo->reliter;
if( localInfo->rel ) {
localInfo->rel->Clear();
delete localInfo->rel;
}
delete localInfo;
qp->GetLocal2(s).addr=0;
}
qp->Close(args[0].addr);
if (local.addr)
{
((TupleType*)local.addr)->DeleteIfAllowed();
local.setAddr(0);
}
return 0;
}
}
return 0;
}
/*
3D Convex
*/
/*
Class Polyhedron for result of voronoi3d
*/
Polyhedron::Polyhedron() {}
void Polyhedron::setPolyId(int id_) {
this->polyhedronId = id_;
}
int Polyhedron::getPolyId() {
return polyhedronId;
}
Polyhedron::~Polyhedron() {}
/*
3D Convex constructor
*/
Convex3D::Convex3D() {
boundingBox = nullptr;
}
Convex3D::Convex3D(const Convex3D& g) {
boundingBox = g.boundingBox;
}
Convex3D::Convex3D(Rectangle<3> &bounding_box) {
boundingBox = &bounding_box;
}
Convex3D::Convex3D(std::vector<Polyhedron> &poly_vec) {
polyhedronvec = poly_vec;
}
void Convex3D::Set(Stream<Rectangle<3>> rStream) {
CreateVoronoi3D(rStream);
}
void Convex3D::CreateVoronoi3D(Stream<Rectangle<3>> rStream) {
// create voronoi diagram
buildVoronoi3D(rStream);
}
void
Convex3D::setTetrahedronVector(std::vector<Tetrahedron*> tetra_vec) {
this->tetravec = tetra_vec;
}
std::vector<Tetrahedron*>&
Convex3D::getTetrahedronVector() {
return this->tetravec;
}
void
Convex3D::setPolyhedronVector(std::vector<Polyhedron> poly_vec) {
this->polyhedronvec = poly_vec;
}
std::vector<Polyhedron>&
Convex3D::getPolyhedronVector() {
return this->polyhedronvec;
}
std::vector<Point3D>&
Convex3D::getPointsVector() {
return this->points;
}
void
Convex3D::setPointsVector(std::vector<Point3D> pointsvec) {
this->points = pointsvec;
}
std::vector<Point3D>&
Convex3D::getVerticeVector() {
return this->vertices;
}
void
Convex3D::setVerticeVector(std::vector<Point3D> verticevec) {
this->vertices = verticevec;
}
std::vector<std::vector<int>>&
Convex3D::getFacesVector() {
return this->faces;
}
void
Convex3D::setFacesVector(std::vector<std::vector<int>> facevec) {
this->faces = facevec;
}
std::vector<std::vector<int>>&
Convex3D::getV2TVector(){
return this->v2t;
}
void
Convex3D::setV2TVector(std::vector<std::vector<int>> v2tvec){
this->v2t = v2tvec;
}
std::vector<std::vector<int>>&
Convex3D::getF2TVector(){
return this->f2t;
}
void
Convex3D::setF2TVector(std::vector<std::vector<int>> f2tvec){
this->f2t = f2tvec;
}
void
Convex3D::setCellId(int cell_id) {
this->polyhedronId = cell_id;
}
int
Convex3D::getCellId() {
return polyhedronId;
}
Convex3D::~Convex3D() {}
/*
Calculates cross product of two vectors and returns vector
*/
std::vector<double> crossProduct(std::vector<double> va,
std::vector<double> vb)
{
std::vector<double> res {va[1]*vb[2] - va[2]*vb[1],
va[2]*vb[0] - va[0]*vb[2], va[0]*vb[1] - va[1]*vb[0]};
return res;
}
/*
Calculates dot product of two vectors and returns value
*/
double dotProduct(std::vector<double> va, std::vector<double> vb)
{
double product = va[0]*vb[0] + va[1]*vb[1] + va[2]*vb[2];
return product;
}
/*
Calculates centre of a cuboid
*/
Point3D getCentre(Rectangle<3>* r) {
double a = (r->getMaxY() - r->getMinY()) / (double)2;
double b = (r->getMaxX() - r->getMinX()) / (double)2;
double c = (r->getMaxZ() - r->getMinZ()) / (double)2;
Point3D r_c;
r_c.x = r->getMinX() + b;
r_c.y = r->getMinY() + a;
r_c.z = r->getMinZ() + c;
return r_c;
}
/*
Returns true if Point p is in given polyhedron
*/
bool isInPolyhedron(Point3D p, Polyhedron poly, Point3D pi)
{
for(size_t i = 1; i < poly.faces.size(); i++)
{
// calculate first orient3d to have a comparetive value
std::vector<Point3D> face = poly.faces[i];
if(face.size() > 2) {
double pa[3] = {face[0].x, face[0].y, face[0].z};
double pb[3] = {face[1].x, face[1].y, face[1].z};
double pc[3] = {face[2].x, face[2].y, face[2].z};
// take point pi (which lies definitly in cell) as a reference
double pd[3] = {pi.x, pi.y, pi.z};
double d0 = orient3d(pa, pb, pc, pd);
double paC[3] = {face[0].x, face[0].y, face[0].z};
double pbC[3] = {face[1].x, face[1].y, face[1].z};
double pcC[3] = {face[2].x, face[2].y, face[2].z};
double pp[3] = {p.x, p.y, p.z};
double d1 = orient3d(paC, pbC, pcC, pp);
/*
if values for determinants (d0,d1)
have different signs,
the points pi and p cannot be on the same side
of the checked face. In this case p cannot be
inside of the polyhedron
*/
if(signbit(d0) != signbit(d1))
{
return false;
}
}
}
return true;
}
/*
Returns true if point lies in cuboid
*/
bool insideCuboid(Rectangle<3>* r, Point3D center) {
double x = center.x;
double y = center.y;
double z = center.z;
if (r->getMinX() <= x && r->getMaxX() >= x
&& r->getMinY() <= y && r->getMaxY() >= y
&& r->getMinZ() <= z && r->getMaxZ() >= z) {
return true;
}
return false;
}
/*
Returns true if one of the points
of the given polyhedron lies in cuboid
*/
bool insideCuboid(Rectangle<3>* r, Polyhedron poly) {
for(size_t t = 0; t < poly.faces.size(); t++)
{
std::vector<Point3D> face = poly.faces[t];
for(size_t f = 0; f < face.size(); f++)
{
double x = face[f].x;
double y = face[f].y;
double z = face[f].z;
if (r->getMinX() <= x && r->getMaxX() >= x
&& r->getMinY() <= y && r->getMaxY() >= y
&& r->getMinZ() <= z && r->getMaxZ() >= z) {
return true;
}
}
}
return false;
}
bool sortbyX(Point3D a, Point3D b)
{
return a.x < b.x;
}
bool sortbyY(Point3D a, Point3D b)
{
return a.y < b.y;
}
bool sortbyZ(Point3D a, Point3D b)
{
return a.z < b.z;
}
ListExpr
Convex3D::PropertyConvex3D()
{
ListExpr desclst = nl->TextAtom();
nl->AppendText(desclst,
"A polyhedron id "
"followed by list of faces.\n"
"A face consists of a list of 3d points\n"
"(<x value> <y value> <z value>). ");
ListExpr formatlst = nl->TextAtom();
nl->AppendText(formatlst,
"(1 (((1.0 2.0 1.0)(1.0 3.0 1.0)(4.0 3.0 1.0)"
"(1.0 1.5 2.0)(2.0 1.5 2.0))))");
return (nl->TwoElemList(
nl->FourElemList(nl->StringAtom("Signature"),
nl->StringAtom("Example Type List"),
nl->StringAtom("List Rep"),
nl->StringAtom("Example List")),
nl->FourElemList(nl->StringAtom("-> DATA"),
nl->StringAtom(Convex3D::BasicType()),
desclst,
formatlst)));
}
/*
Out function
*/
ListExpr
Convex3D::OutConvex3D( ListExpr typeInfo, Word value ) {
Convex3D* conv = static_cast<Convex3D*>( value.addr );
if(conv != nullptr)
{
std::vector<Polyhedron> polyhedronvec = conv->getPolyhedronVector();
ListExpr polyExpr = nl->Empty();
ListExpr lastPolyLstExpr;
for(size_t test=0; test < polyhedronvec.size(); test++)
{
ListExpr facesLstExpr;
ListExpr lastFacesLstExpr;
Polyhedron poly = polyhedronvec.at(test);
if(test > 0) {
lastPolyLstExpr = nl->Append(lastPolyLstExpr,
nl->IntAtom(poly.getPolyId()));
} else {
polyExpr = nl->OneElemList(nl->IntAtom(poly.getPolyId()));
lastPolyLstExpr = polyExpr;
}
for(size_t fac = 0; fac < poly.faces.size(); fac++)
{
ListExpr faceLstExpr;
ListExpr lastFaceLstExpr;
if(fac > 0)
{
lastFacesLstExpr = nl->Append(lastFacesLstExpr, nl->Empty());
} else {
facesLstExpr = nl->OneElemList(nl->Empty());
lastFacesLstExpr = facesLstExpr;
}
std::vector<Point3D> facc = poly.faces.at(fac);
for(size_t poii=0; poii < facc.size(); poii++)
{
if(poii > 0)
{
lastFaceLstExpr = nl->Append(lastFaceLstExpr,
nl->ThreeElemList(nl->RealAtom(facc.at(poii).x),
nl->RealAtom(facc.at(poii).y),
nl->RealAtom(facc.at(poii).z)));
} else {
faceLstExpr = nl->OneElemList(nl->ThreeElemList(
nl->RealAtom(facc.at(poii).x),
nl->RealAtom(facc.at(poii).y),
nl->RealAtom(facc.at(poii).z)));
lastFaceLstExpr = faceLstExpr;
}
}
lastFacesLstExpr = nl->Append(lastFacesLstExpr,
faceLstExpr);
}
lastPolyLstExpr = nl->Append(lastPolyLstExpr, facesLstExpr);
}
return polyExpr;
} else {
return (nl->SymbolAtom(Symbol::UNDEFINED()));
}
}
/*
In function
*/
Word
Convex3D::InConvex3D( const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr& errorInfo, bool& correct ) {
Word w = SetWord(Address(0));
try {
Polyhedron polyhedron;
std::vector<Point3D> face;
std::vector<Polyhedron> poly_vec;
std::vector<std::vector<Point3D>> facesPoints;
ListExpr polyExpr = instance;
int polyId;
if (nl->ListLength( polyExpr ) > 0) {
while(nl->ListLength(polyExpr) > 1) {
ListExpr lstElem = nl->First(polyExpr);
if(nl->IsAtom(lstElem))
{
polyhedron = Polyhedron();
polyId = nl->IntValue(lstElem);
polyhedron.setPolyId(polyId);
}
ListExpr facesLst = nl->Second(polyExpr);
/*
list of faces
*/
if(nl->ListLength(facesLst) > 1) {
while(nl->ListLength(facesLst) > 1) {
if(nl->ListLength(facesLst) > 1) {
ListExpr faceElems = nl->Second(facesLst);
if(nl->ListLength(faceElems) > 0) {
face.clear();
while(!nl->IsEmpty(faceElems)) {
ListExpr vertex = nl->First(faceElems);
ListExpr first = nl->First(vertex);
ListExpr second = nl->Second(vertex);
ListExpr third = nl->Third(vertex);
if(nl->IsAtom(first) && nl->AtomType(first) == RealType
&& nl->IsAtom(second) && nl->AtomType(second) == RealType
&& nl->IsAtom(third) && nl->AtomType(third) == RealType)
{
double x = nl->RealValue(first);
double y = nl->RealValue(second);
double z = nl->RealValue(third);
Point3D p {x,y,z};
face.push_back(p);
}
faceElems = nl->Rest(faceElems);
}
}
polyhedron.faces.push_back(face);
facesLst = nl->Rest(facesLst);
facesLst = nl->Rest(facesLst);
}
}
}
poly_vec.push_back(polyhedron);
polyExpr = nl->Rest(polyExpr);
polyExpr = nl->Rest(polyExpr);
}
}
Convex3D* conv3d = new Convex3D();
conv3d->setPolyhedronVector(poly_vec);
w.addr = conv3d;
correct = true;
return w;
} catch (int e) {
correct = false;
cmsg.inFunError("Expecting a 3dvoronoi list representation. Exit code "
+ std::to_string(e));
return w;
}
}
// This function checks whether the type constructor is applied correctly.
bool
Convex3D::KindCheckConvex3D( ListExpr type, ListExpr& errorInfo )
{
return (nl->IsEqual( type, Convex3D::BasicType() ));
}
// Clone function
Word
Convex3D::CloneConvex3D( const ListExpr typeInfo, const Word& w )
{
Convex3D *g = new Convex3D( *((Convex3D *)w.addr) );
return SetWord( g );
}
// Create function
Word
Convex3D::CreateConvex3D( const ListExpr typeInfo )
{
return SetWord( new Convex3D() );
}
// Delete function
void
Convex3D::DeleteConvex3D( const ListExpr typeInfo, Word& w )
{
delete (Convex3D *)w.addr;
w.addr = 0;
}
// SizeOf function
int
Convex3D::SizeOfConvex3D()
{
return sizeof(Convex3D);
}
/*
Returns true if points are equal
*/
bool comparePoints3D(Point3D p1, Point3D p2)
{
bool res = (p1.x == p2.x && p1.y == p2.y && p1.z == p2.z);
return res;
}
/*
Normalizes a vector
*/
Point3D normalize(double x, double y, double z)
{
const float s = 1.0f / sqrtf(x*x + y*y + z*z);
Point3D p {x*s, y*s, z*s};
return p;
}
/*
Returns the index of a point in a vector of points
*/
int getIndex(Point3D t1, std::vector<Point3D> v2)
{
for(int i=0; i < (int)v2.size(); i++)
{
Point3D t2 = v2.at(i);
if(t1.x == t2.x && t1.y == t2.y && t1.z == t2.z) {
return i;
}
}
return -1;
}
/*
Returns the centre of the sphere around a tetrahedron
see
Weisstein, Eric W. 'Circumsphere.'
From MathWorld--A Wolfram Web Resource.
for explanation
*/
Point3D getCircumcenter(Point3D a, Point3D b, Point3D c, Point3D d)
{
// calculate middle of Tetrahedron with circumsphere
double fina[3] = {a.x, a.y, a.z};
double finb[3] = {b.x, b.y, b.z};
double finc[3] = {c.x, c.y, c.z};
double find[3] = {d.x, d.y, d.z};
float ax = orient3d(fina, finb, finc, find);
/*
build new points for Dx, Dy and Dz
by discarding column xi (or yi or zi)
*/
float square_1 = a.x*a.x + a.y*a.y + a.z*a.z;
float square_2 = b.x*b.x + b.y*b.y + b.z*b.z;
float square_3 = c.x*c.x + c.y*c.y + c.z*c.z;
float square_4 = d.x*d.x + d.y*d.y + d.z*d.z;
double dx_1[3] = {square_1, a.y, a.z};
double dx_2[3] = {square_2, b.y, b.z};
double dx_3[3] = {square_3, c.y, c.z};
double dx_4[3] = {square_4, d.y, d.z};
float dx = orient3d(dx_1, dx_2, dx_3, dx_4);
double dy_1[3] = {square_1, a.x, a.z};
double dy_2[3] = {square_2, b.x, b.z};
double dy_3[3] = {square_3, c.x, c.z};
double dy_4[3] = {square_4, d.x, d.z};
float dy = -orient3d(dy_1, dy_2, dy_3, dy_4);
double dz_1[3] = {square_1, a.x, a.y};
double dz_2[3] = {square_2, b.x, b.y};
double dz_3[3] = {square_3, c.x, c.y};
double dz_4[3] = {square_4, d.x, d.y};
float dz = orient3d(dz_1, dz_2, dz_3, dz_4);
if(ax < 0)
{
ax = orient3d(fina, finc, finb, find);
dx = orient3d(dx_1, dx_3, dx_2, dx_4);
dy = -orient3d(dy_1, dy_3, dy_2, dy_4);
dz = orient3d(dz_1, dz_3, dz_2, dz_4);
}
Point3D circumcenter;
circumcenter.x = (dx / (2*ax));
circumcenter.y = (dy / (2*ax));
circumcenter.z = (dz / (2*ax));
return circumcenter;
}
/*
Returns true if line p1 to p2 is a line in tet (two tetrahedrons share a line)
*/
bool sameline(Point3D p1, Point3D p2, Tetrahedron tet)
{
std::vector<Point3D> tmp {tet.a, tet.b, tet.c, tet.d};
bool p1in = false;
bool p2in = false;
for(int i = 0; i < (int)tmp.size(); i++)
{
p1in = comparePoints3D(p1, tmp.at(i));
if(p1in)
{
for(int z=0; z<(int)tmp.size(); z++)
{
if(z!=i)
{
p2in = comparePoints3D(p2,tmp.at(z));
if(p2in)
{
return true;
}
}
}
}
}
return false;
}
bool sameline(int p1, int p2, std::vector<int> tet)
{
bool p1in = false;
bool p2in = false;
for (const auto &value:tet)
{
if(value == p1)
p1in = true;
if(value == p2)
p2in = true;
if(p1in && p2in)
{
return true;
}
}
return false;
}
/*
Returns true if a pair of points is
in a vector of pairs of points
*/
bool insidevec(Point3D p1, Point3D p2,
std::vector<std::tuple<Point3D, Point3D>> pairs)
{
for(int o=0; o < (int)pairs.size(); o++)
{
Point3D t1 = std::get<0>(pairs.at(o));
Point3D t2 = std::get<1>(pairs.at(o));
if(comparePoints3D(t1, p1) && comparePoints3D(t2, p2))
{
return true;
}
}
return false;
}
/*
Returns true if a pair of points is
in a vector of pairs of points
using indices
*/
bool insidevec(int p1, int p2,
std::vector<std::tuple<int, int>> pairs)
{
for(int o=0; o < (int)pairs.size(); o++)
{
int t1 = std::get<0>(pairs.at(o));
int t2 = std::get<1>(pairs.at(o));
if((t1 == p1 && t2 == p2) || (t1 == p2 && t2 == p1))
{
return true;
}
}
return false;
}
/*
Returns true if a segment pd intersects with triangle abc
See Moeller-Trumbore intersection algorithm
for further explanation
Paper: Fast MinimumStorage RayTriangle Intersection
*/
bool segmentIntersectsArea(Point3D p, Point3D d, Point3D a,
Point3D b, Point3D c)
{
double epsilon = 0.000001f;
Point3D e0 {b.x-a.x, b.y-a.y, b.z-a.z};
Point3D e1 {c.x-a.x, c.y-a.y, c.z-a.z};
Point3D dir {d.x-p.x, d.y-p.y, d.z-p.z};
Point3D dir_norm = normalize(dir.x, dir.y, dir.z);
std::vector<double> dir_norm_vec {dir_norm.x, dir_norm.y, dir_norm.z};
std::vector<double> dir_vec{dir.x, dir.y, dir.z};
std::vector<double> e1_vec {e1.x, e1.y, e1.z};
std::vector<double> e0_vec {e0.x, e0.y, e0.z};
/*
The equation that needs to be solved is (6)
(page 3 from source above)
The first step is to check whether the part
(dir\_norm\_vec x e1\_vec) \* e0\_vec
(in the paper this would be (D x E2)\*E1) is non-zero.
If the equation is not solvable we can stop.
In the paper h is called P.
*/
std::vector<double> h = crossProduct(dir_norm_vec, e1_vec);
double dp = dotProduct(e0_vec, h);
if (dp > -epsilon && dp < epsilon) {
return false;
}
/*
The next step is to check the value of u
which is calculated as 1 / (P * E1) * (P * T)
In this notation:
h: P
dp: (P * E1)
s\_vec: T
So:
u = (1 / dp) * (s\_vec * h)
*/
Point3D s {p.x-a.x, p.y-a.y, p.z-a.z};
std::vector<double> s_vec {s.x, s.y, s.z};
const float f = 1.0f / dp;
const float u = f * dotProduct(s_vec, h);
/*
u has to be between 0 and 1 as we are
looking at a unit triangle in
y and z and a ray direction aligned with x.
If u is not between 0 and 1 we can stop.
*/
if (u < 0.0f || u > 1.0f) {
return false;
}
/*
Now we look at the v in equation (6) in the paper.
Here v = 1 / (P * E1) * ((T x E1) * D)
In this notation:
v = f * ((s\_vec x e0\_vec) * dir\_norm\_vec)
*/
std::vector<double> q = crossProduct(s_vec, e0_vec);
const float v = f * dotProduct(dir_norm_vec, q);
/*
v has to be positive and u + v cannot exceed 1 to lie
in the unit triangle
*/
if (v < 0.0f || u + v > 1.0f) {
return false;
}
/*
Now the last value t is calculated accordingly as
t = 1 / (P * E1) * ((T x E1) * E2)
In this notation:
t = f * (q * e1\_vec)
*/
const float t = f * dotProduct(e1_vec, q);
/*
segment intersection:
the distance variable t must be between 0 and the length
of the direction vector dir\_vec for the segment between the two
points p and d to intersect the triangle.
*/
if (t > epsilon && t < sqrtf(dotProduct(dir_vec, dir_vec))) {
return true;
}
return false;
}
/*
Returns all cellnumbers of cells which intersect with a given rectangle
Two modes are possible: intersections with the exact cell and intersection
with the bounding box of a cell
*/
void cellNum3D(Convex3D* convex3d, Rectangle<3>*
search_window_ptr, int mode, std::set<int> *cell_ids)
{
// get polyvec
std::vector<Polyhedron> polyvec = convex3d->getPolyhedronVector();
std::vector<Point3D> inputPoints = convex3d->getPointsVector();
if(inputPoints.size() < polyvec.size())
{
/*
calculate center of polyeder
1. calculate bbox of polyeder
2. calculate center of this bbox
*/
for(size_t p = 0; p < polyvec.size(); p++)
{
Rectangle<3> bboxP = createBBox3D(&polyvec[p]);
Point3D bc = getCentre(&bboxP);
inputPoints.push_back(bc);
}
}
int bbox = 2;
int precise = 1;
// Rectangle points
Point3D lebofr, ribofr, letofr, ritofr, leboba, riboba, letoba, ritoba;
lebofr = {search_window_ptr->getMinX(),
search_window_ptr->getMinY(), search_window_ptr->getMinZ()};
ribofr = {search_window_ptr->getMaxX(),
search_window_ptr->getMinY(), search_window_ptr->getMinZ()};
letofr = {search_window_ptr->getMinX(),
search_window_ptr->getMaxY(), search_window_ptr->getMinZ()};
ritofr = {search_window_ptr->getMaxX(),
search_window_ptr->getMaxY(), search_window_ptr->getMinZ()};
leboba = {search_window_ptr->getMinX(),
search_window_ptr->getMinY(), search_window_ptr->getMaxZ()};
riboba = {search_window_ptr->getMaxX(),
search_window_ptr->getMinY(), search_window_ptr->getMaxZ()};
letoba = {search_window_ptr->getMinX(),
search_window_ptr->getMaxY(), search_window_ptr->getMaxZ()};
ritoba = {search_window_ptr->getMaxX(),
search_window_ptr->getMaxY(), search_window_ptr->getMaxZ()};
Point3D center = getCentre(search_window_ptr);
// intersection with exact cell
if(mode == precise) {
for(size_t i = 0; i < polyvec.size(); i++)
{
Polyhedron tmp = polyvec[i];
if(!tmp.faces.empty()) {
/*
1. Check if any point (taken from points) of polyhedron
lies in cuboid: add cell id (easy, saves time)
2. Check if middle of cuboid intersects with polyhedron
cell (get middle of cuboid, check if it lies in cell)
- if yes: add cell\_id to cell\_ids
- if no: check if edges of cuboid intersect with faces of polyhedron
- get face and points of cuboid, check intersection
- if one intersect: add cell\_id to cell\_ids
- if no intersects: go to next cell, don't add cell\_id
*/
if(insideCuboid(search_window_ptr, inputPoints.at(i)))
{
cell_ids->insert(tmp.getPolyId());
}
else if(isInPolyhedron(center, tmp, inputPoints.at(i)))
{
cell_ids->insert(tmp.getPolyId());
}
else
{
// check intersection for each face
for(size_t f = 0; f < tmp.faces.size(); f++)
{
std::vector<Point3D> face = tmp.faces.at(f);
if(face.size() > 2) {
for(size_t n=0; n < face.size()-2; n++)
{
/*
polygon consists of x-2 (x number of vertices) triangles
triangle consists of vertex v[0], v[n+1], v[n+2]
n = number of triangles already formed
first triangle: v[0], v[1], v[2] with n = 0
*/
if(segmentIntersectsArea(lebofr, leboba, face[0], face[n+1], face[n+2])
|| segmentIntersectsArea(ribofr, riboba, face[0], face[n+1], face[n+2])
|| segmentIntersectsArea(lebofr, ribofr, face[0], face[n+1], face[n+2])
|| segmentIntersectsArea(leboba, riboba, face[0], face[n+1], face[n+2])
|| segmentIntersectsArea(lebofr, letofr, face[0], face[n+1], face[n+2])
|| segmentIntersectsArea(ribofr, ritofr, face[0], face[n+1], face[n+2])
|| segmentIntersectsArea(leboba, letoba, face[0], face[n+1], face[n+2])
|| segmentIntersectsArea(riboba, ritoba, face[0], face[n+1], face[n+2])
|| segmentIntersectsArea(letofr, letoba, face[0], face[n+1], face[n+2])
|| segmentIntersectsArea(ritofr, ritoba, face[0], face[n+1], face[n+2])
|| segmentIntersectsArea(letofr, ritofr, face[0], face[n+1], face[n+2])
|| segmentIntersectsArea(letoba, ritoba, face[0], face[n+1], face[n+2]))
{
cell_ids->insert(tmp.getPolyId());
break;
}
}
}
}
}
}
}
} else if (mode== bbox) {
for(size_t b = 0; b < polyvec.size(); b++)
{
Polyhedron pol = polyvec.at(b);
if(!pol.faces.empty()) {
Rectangle<3> bbox = createBBox3D(&pol);
/*
see if bbox intersects with rectangle
top left and bottom right of bbox
*/
Point3D tolefr, boriba;
tolefr = {bbox.getMinX(), bbox.getMaxY(), bbox.getMinZ()};
boriba = {bbox.getMaxX(), bbox.getMinY(), bbox.getMaxZ()};
if(cuboidOverlap(tolefr, boriba, letofr, riboba)) {
cell_ids->insert(pol.getPolyId());
}
}
}
} else {
cell_ids->insert(0);
}
return;
}
/*
checks if id of face is already in vector
if yes: returns position
*/
bool Convex3D::faceIn(std::vector<int> face, int* pos)
{
std::sort(face.begin(), face.end());
for(int a = 0; a < (int)faces.size(); a++)
{
std::sort(faces[a].begin(), faces[a].end());
if(faces[a] == face)
{
*pos = a;
return true;
}
}
return false;
}
/*
check if tetrahedron exists in vector v2t
*/
bool Convex3D::tetExists(int a, int b, int p, int d, int* pos)
{
std::vector<int> tetr {a, b, p, d};
sort(tetr.begin(), tetr.end());
for(int v=0; v < (int)v2t.size(); v++)
{
sort(v2t[v].begin(), v2t[v].end());
if(v2t[v] == tetr)
{
*pos = v;
return true;
}
}
return false;
}
/*
Create Delaunay diagram
Input: Set of points
Output: Delaunay diagram
Further explanation in paper of Hugo Ledoux
Computing the 3D Voronoi Diagram Robustly:
An Easy Explanation
*/
void
Convex3D::createDelaunay (std::vector<Point3D> points,
std::vector<Tetrahedron>* tetravec)
{
// 1. Get min and max x,y,z
std::vector<Point3D> pointsSortedbyX = points;
std::vector<Point3D> pointsSortedbyY = points;
std::vector<Point3D> pointsSortedbyZ = points;
// Sort Points by x-value
std::sort(pointsSortedbyX.begin(), pointsSortedbyX.end(), sortbyX);
double xmin = pointsSortedbyX.front().x;
double xmax = pointsSortedbyX[pointsSortedbyX.size() -1].x;
// Sort points by y-value
std::sort(pointsSortedbyY.begin(), pointsSortedbyY.end(), sortbyY);
double ymin = pointsSortedbyY.front().y;
double ymax = pointsSortedbyY[pointsSortedbyY.size()-1].y;
// Sort points by z-value - check if it works to get z-value
std::sort(pointsSortedbyZ.begin(), pointsSortedbyZ.end(), sortbyZ);
double zmin = pointsSortedbyZ.front().z;
double zmax = pointsSortedbyZ[pointsSortedbyZ.size()-1].z;
/*
2. Build tetrahedron with min and max values
2.1 Calculate bounding box of points with min and max values
2.2 Build triangle around upper rectangle of cuboid (bounding box)
2.3 Build tetrahedron with point above triangle
2.4 Extend sides from point to triangle until it reaches
height of lower rectangle of cuboid
2.5 result is the start tetrahedron
*/
double min[3], max[3];
min[0] = xmin;
min[1] = ymin;
max[0] = xmax;
max[1] = ymax;
min[2] = zmin;
max[2] = zmax;
Rectangle<3> bbox (true, min, max);
double x_len = (xmax-xmin);
double z_len = (zmax-zmin);
// triangle points:
Point3D t1 {xmin-x_len, ymax, zmin-1};
Point3D t2 {xmin+x_len, ymax, ((z_len+1)*2)};
Point3D t3 {xmax+x_len, ymax, zmin-1};
// upper tetrahedron:
double y_len = (ymax-ymin);
// upper point of tetrahedron
Point3D t4 {xmin+(x_len/2), ymax+y_len, zmin+(z_len/2)};
Point3D t5 {t1.x-y_len, ymin-1, zmin-1};
Point3D t6 {t2.x, ymin-1, t2.z+y_len};
Point3D t7 {t3.x+y_len, ymin-1, zmin-1};
// adding vertices t4-t7 to vertice vector
vertices.push_back(t4);
vertices.push_back(t5);
vertices.push_back(t6);
vertices.push_back(t7);
/*
adding faces to faces vector
use indices of vertice vector
*/
std::vector<int> face1 {0, 1, 2};
std::vector<int> face2 {0, 2, 3};
std::vector<int> face3 {0, 1, 3};
std::vector<int> face4 {1, 2, 3};
faces.push_back(face1);
faces.push_back(face2);
faces.push_back(face3);
faces.push_back(face4);
/*
adding indices to tetrahedron vectors
tetrahedron is build from four vertices
vertices2tetrahedron (v2t)
*/
double dz[3] {t4.x, t4.y, t4.z};
double dx[3] {t5.x, t5.y, t5.z};
double dy[3] {t6.x, t6.y, t6.z};
double dv[3] {t7.x, t7.y, t7.z};
if(orient3d(dz, dx, dy, dv) > 0)
{
std::vector<int> vert2tet {0,1,2,3};
v2t.push_back(vert2tet);
vert2tet.clear();
} else {
std::vector<int> vert2tet {0,2,1,3};
v2t.push_back(vert2tet);
vert2tet.clear();
}
/*
faces2tetrahedron (f2t)
vector which has indices to faces
of each tetrahedron that is inside
this vector
*/
std::vector<int> face2tet {0,1,2,3};
f2t.push_back(face2tet);
face2tet.clear();
std::vector<std::vector<int>> tetfaces;
std::vector<std::vector<int>> tetverts;
/*
push start tetrahedron in vector
Insert point by point in initial tetrahedron
*/
for(int i = 0; i < (int)points.size(); i++)
{
Point3D p = points.at(i);
/*
find tetrahedron T containing p
with visibility walk through diagram
*/
bool found_tet = false;
int n = 0;
int start = 0;
std::vector<int> tetStart =f2t[n];
std::vector<int> faceStart = faces[tetStart[start]];
std::vector<int> tStart = v2t[n];
double pit[3] = {p.x, p.y, p.z};
int a = 0;
/*
visited elements in v2t
*/
std::vector<int> visited {};
std::vector<int>::iterator it;
while(found_tet == false)
{
start = 0;
a++;
it = std::find(visited.begin(), visited.end(), n);
/*
to take another starting point
(and not to get stuck in visibility walk)
*/
if (it != visited.end())
{
// random start
n = std::rand() % v2t.size();
tStart = v2t[n];
}
// first points at position 0,1,2
double ait[3] = {vertices[tStart[0]].x,
vertices[tStart[0]].y, vertices[tStart[0]].z} ;
double bit[3] = {vertices[tStart[1]].x,
vertices[tStart[1]].y, vertices[tStart[1]].z};
double cit[3] = {vertices[tStart[2]].x,
vertices[tStart[2]].y, vertices[tStart[2]].z};
double dit[3] = {vertices[tStart[3]].x,
vertices[tStart[3]].y, vertices[tStart[3]].z};
double detTet = orient3d(ait, bit, cit, dit);
if(signbit(orient3d(ait, bit, cit, pit))
!= signbit(detTet))
{
visited.push_back(n);
// face
std::vector<int> fa {tStart[0], tStart[1], tStart[2]};
int index = -1;
std::vector<int>::iterator it;
if(faceIn(fa, &index))
{
/*
is index in another tet in f2t
*/
for(int ii=0; ii < (int)f2t.size(); ii++)
{
if(ii != n) {
it = find (f2t[ii].begin(), f2t[ii].end(), index);
if (it != f2t[ii].end())
{
n = ii;
tStart = v2t[n];
break;
}
}
}
}
} else {
if(signbit(orient3d(ait, bit, pit, dit))
!= signbit(detTet))
{
visited.push_back(n);
std::vector<int> fa {tStart[0], tStart[1], tStart[3]};
int index = -1;
std::vector<int>::iterator it;
if(faceIn(fa, &index))
{
/*
is index in another tet in f2t
*/
for(int ii=0; ii < (int)f2t.size(); ii++)
{
if(ii != n) {
it = find (f2t[ii].begin(), f2t[ii].end(), index);
if (it != f2t[ii].end())
{
n = ii;
tStart = v2t[n];
break;
}
}
}
}
} else {
if(signbit(orient3d(ait, pit, cit, dit))
!= signbit(detTet))
{
visited.push_back(n);
std::vector<int> fa {tStart[0], tStart[2], tStart[3]};
int index = -1;
std::vector<int>::iterator it;
if(faceIn(fa, &index))
{
/*
is index in another tet in f2t
*/
for(int ii=0; ii < (int)f2t.size(); ii++)
{
if(ii != n) {
it = find (f2t[ii].begin(), f2t[ii].end(), index);
if (it != f2t[ii].end())
{
n = ii;
tStart = v2t[n];
break;
}
}
}
}
} else {
if(signbit(orient3d(pit, bit, cit, dit))
!= signbit(detTet))
{
visited.push_back(n);
std::vector<int> fa {tStart[1], tStart[2], tStart[3]};
int index = -1;
std::vector<int>::iterator it;
if(faceIn(fa, &index))
{
/*
is index in another tet in f2t
*/
for(int ii=0; ii < (int)f2t.size(); ii++)
{
if(ii != n) {
it = find (f2t[ii].begin(), f2t[ii].end(), index);
if (it != f2t[ii].end())
{
n = ii;
tStart = v2t[n];
break;
}
}
}
}
} else {
/*
point is inside
*/
found_tet = true;
if(found_tet) {
a = (int)v2t.size();
}
}
}
}
}
if(a > ((int)v2t.size()*4))
{
/*
cannot find tetrahedron
remove point
*/
points.erase(points.begin()+i);
break;
}
} // end of while
if(visited.size() > 0){
visited.clear();
}
/*
check if new point lies directly on one of
the already existing vertices
*/
if(comparePoints3D(p, vertices[v2t[n][0]])
|| comparePoints3D(p, vertices[v2t[n][1]])
|| comparePoints3D(p, vertices[v2t[n][2]])
|| comparePoints3D(p, vertices[v2t[n][3]]))
{
/*
do not insert point at all
*/
} else {
// insert point p to vertices
vertices.push_back(p);
/*
add new v2t
get current tetrahedron and
remove it from vector to insert
4 new ones
*/
std::vector<int> tetcrr = v2t[n];
std::vector<int> facecrr = f2t[n];
v2t.erase(v2t.begin()+n);
// (0,1,3,4), (1,2,3,4), (0,1,2,4), (0,2,3,4)
double ux[3] ={vertices[tetcrr[0]].x,
vertices[tetcrr[0]].y, vertices[tetcrr[0]].z};
double uy[3] ={vertices[tetcrr[1]].x,
vertices[tetcrr[1]].y, vertices[tetcrr[1]].z};
double uv[3] ={vertices[tetcrr[2]].x,
vertices[tetcrr[2]].y, vertices[tetcrr[2]].z};
double uw[3] ={vertices[tetcrr[3]].x,
vertices[tetcrr[3]].y, vertices[tetcrr[3]].z};
double ur[3] ={vertices[vertices.size()-1].x,
vertices[vertices.size()-1].y, vertices[vertices.size()-1].z};
/*
check orientation of vertices
before inserting
*/
if(orient3d(ux, uy, uw, ur) > 0) {
std::vector<int> tetnew1 {tetcrr[0],
tetcrr[1], tetcrr[3], (int)vertices.size()-1};
v2t.push_back(tetnew1);
tetverts.push_back(tetnew1);
} else {
std::vector<int> tetnew1 {tetcrr[0],
tetcrr[3], tetcrr[1], (int)vertices.size()-1};
v2t.push_back(tetnew1);
tetverts.push_back(tetnew1);
}
if(orient3d(uy, uv, uw, ur) > 0) {
std::vector<int> tetnew2 {tetcrr[1],
tetcrr[2], tetcrr[3], (int)vertices.size()-1};
v2t.push_back(tetnew2);
tetverts.push_back(tetnew2);
} else {
std::vector<int> tetnew2 {tetcrr[1],
tetcrr[3], tetcrr[2], (int)vertices.size()-1};
v2t.push_back(tetnew2);
tetverts.push_back(tetnew2);
}
if(orient3d(ux, uy, uv, ur) > 0) {
std::vector<int> tetnew3 {tetcrr[0],
tetcrr[1], tetcrr[2], (int)vertices.size()-1};
v2t.push_back(tetnew3);
tetverts.push_back(tetnew3);
} else {
std::vector<int> tetnew3 {tetcrr[0],
tetcrr[2], tetcrr[1], (int)vertices.size()-1};
v2t.push_back(tetnew3);
tetverts.push_back(tetnew3);
}
if(orient3d(ux, uv, uw, ur) > 0) {
std::vector<int> tetnew4 {tetcrr[0],
tetcrr[2], tetcrr[3], (int)vertices.size()-1};
v2t.push_back(tetnew4);
tetverts.push_back(tetnew4);
} else {
std::vector<int> tetnew4 {tetcrr[0],
tetcrr[3], tetcrr[2], (int)vertices.size()-1};
v2t.push_back(tetnew4);
tetverts.push_back(tetnew4);
}
/*
add new faces
(numbers behind for orientation)
*/
std::vector<int> facenew1_1 {tetcrr[0],
tetcrr[1], tetcrr[3] }; //013
std::vector<int> facenew1_2 {tetcrr[0],
tetcrr[1], (int)vertices.size()-1 }; //014
std::vector<int> facenew1_3 {tetcrr[0],
tetcrr[3], (int)vertices.size()-1 }; //034
std::vector<int> facenew1_4 {tetcrr[1],
tetcrr[3], (int)vertices.size()-1 }; //134
std::vector<int> facenew2_1 {tetcrr[1],
tetcrr[2], (int)vertices.size()-1 }; //124
std::vector<int> facenew2_2 {tetcrr[1],
tetcrr[2], tetcrr[3] }; //123
// 134 s.o.: 1-4
std::vector<int> facenew2_4 {tetcrr[2],
tetcrr[3], (int)vertices.size()-1 }; //234
std::vector<int> facenew3_1 {tetcrr[0],
tetcrr[1], tetcrr[2] }; //012
//014 s.o.: 1-2
std::vector<int> facenew3_3 {tetcrr[0],
tetcrr[2], (int)vertices.size()-1 }; //024
std::vector<int> facenew3_4 {tetcrr[1],
tetcrr[2], (int)vertices.size()-1 }; //124
//024 s.o.: 3-3
//034 s.o.: 1-3
std::vector<int> facenew4_3 {tetcrr[0],
tetcrr[2], tetcrr[3] }; //023
std::vector<int> facenew4_4 {tetcrr[2],
tetcrr[3], (int)vertices.size()-1 }; //234
int pos1 = 0;
std::vector<int> tetfacenew1;
std::vector<int> tetfacenew2;
std::vector<int> tetfacenew3;
std::vector<int> tetfacenew4;
/*
create faces
- check if face exists
- take position if it does
*/
if(!faceIn(facenew1_1, &pos1)) {
faces.push_back(facenew1_1);
tetfacenew1.push_back(faces.size()-1);
} else {
tetfacenew1.push_back(pos1);
}
if(!faceIn(facenew1_2, &pos1)) {
faces.push_back(facenew1_2);
tetfacenew1.push_back(faces.size()-1);
} else {
tetfacenew1.push_back(pos1);
}
if(!faceIn(facenew1_3, &pos1)) {
faces.push_back(facenew1_3);
tetfacenew1.push_back(faces.size()-1);
} else {
tetfacenew1.push_back(pos1);
}
if(!faceIn(facenew1_4, &pos1)) {
faces.push_back(facenew1_4);
tetfacenew1.push_back(faces.size()-1);
} else {
tetfacenew1.push_back(pos1);
}
/*
faces for tetrahedron 2
*/
if(!faceIn(facenew2_1, &pos1)) {
faces.push_back(facenew2_1);
tetfacenew2.push_back(faces.size()-1);
} else {
tetfacenew2.push_back(pos1);
}
if(!faceIn(facenew2_2, &pos1)) {
faces.push_back(facenew2_2);
tetfacenew2.push_back(faces.size()-1);
} else {
tetfacenew2.push_back(pos1);
}
if(!faceIn(facenew1_4, &pos1)) {
faces.push_back(facenew1_4);
tetfacenew2.push_back(faces.size()-1);
} else {
tetfacenew2.push_back(pos1);
}
if(!faceIn(facenew2_4, &pos1)) {
faces.push_back(facenew2_4);
tetfacenew2.push_back(faces.size()-1);
} else {
tetfacenew2.push_back(pos1);
}
/*
faces for tetrahedron 3
*/
if(!faceIn(facenew3_1, &pos1)) {
faces.push_back(facenew3_1);
tetfacenew3.push_back(faces.size()-1);
} else {
tetfacenew3.push_back(pos1);
}
if(!faceIn(facenew1_2, &pos1)) {
faces.push_back(facenew1_2);
tetfacenew3.push_back(faces.size()-1);
} else {
tetfacenew3.push_back(pos1);
}
if(!faceIn(facenew3_3, &pos1)) {
faces.push_back(facenew3_3);
tetfacenew3.push_back(faces.size()-1);
} else {
tetfacenew3.push_back(pos1);
}
if(!faceIn(facenew3_4, &pos1)) {
faces.push_back(facenew3_4);
tetfacenew3.push_back(faces.size()-1);
} else {
tetfacenew3.push_back(pos1);
}
/*
faces for tetrahedron 4
*/
if(!faceIn(facenew3_3, &pos1)) {
faces.push_back(facenew3_3);
tetfacenew4.push_back(faces.size()-1);
} else {
tetfacenew4.push_back(pos1);
}
if(!faceIn(facenew1_3, &pos1)) {
faces.push_back(facenew1_3);
tetfacenew4.push_back(faces.size()-1);
} else {
tetfacenew4.push_back(pos1);
}
if(!faceIn(facenew4_3, &pos1)) {
faces.push_back(facenew4_3);
tetfacenew4.push_back(faces.size()-1);
} else {
tetfacenew4.push_back(pos1);
}
if(!faceIn(facenew4_4, &pos1)) {
faces.push_back(facenew4_4);
tetfacenew4.push_back(faces.size()-1);
} else {
tetfacenew4.push_back(pos1);
}
/*
push tetrahedrons in vector f2t
and same tetrahedrons in
temporary vector tetfaces
to check delaunay criteria
*/
f2t.erase(f2t.begin()+n);
f2t.push_back(tetfacenew1);
f2t.push_back(tetfacenew2);
f2t.push_back(tetfacenew3);
f2t.push_back(tetfacenew4);
tetfaces.push_back(tetfacenew1);
tetfaces.push_back(tetfacenew2);
tetfaces.push_back(tetfacenew3);
tetfaces.push_back(tetfacenew4);
}
int f2tsize = (int)f2t.size();
/*
check if the new tetrahedrons
meet delaunay critera
*/
while((int)tetverts.size() > 0) {
int siz = (int)tetverts.size();
std::vector<int> ttt = tetverts.at(siz-1);
tetverts.pop_back();
f2tsize--;
/*
get tetrahedron with same face opposite of p
*/
int index_p = getIndex(p, vertices);
int faceIndx;
for(int gf=0; gf < (int)tetfaces[siz-1].size(); gf++)
{
auto it = std::find(std::begin(faces[tetfaces[siz-1][gf]]),
std::end(faces[tetfaces[siz-1][gf]]), index_p);
if(it == std::end(faces[tetfaces[siz-1][gf]])) {
faceIndx = tetfaces[siz-1][gf];
break;
}
}
bool foundtet = false;
int ind_tet2;
int ind_d;
for(int ai=0; ai < (int)f2t.size(); ai++)
{
auto it = std::find(std::begin(f2t[ai]),
std::end(f2t[ai]), faceIndx);
if(it != std::end(f2t[ai])) {
if(ai != f2tsize) {
ind_tet2 = ai;
for(int zz=0; zz < (int)v2t[ai].size(); zz++)
{
if(faces[faceIndx][0] != v2t[ai][zz]
&& faces[faceIndx][1] != v2t[ai][zz]
&& faces[faceIndx][2] != v2t[ai][zz]) {
ind_d = zz;
foundtet = true;
break;
}
}
break;
}
}
}
tetfaces.pop_back();
/*
found tet with point d
*/
if(foundtet) {
std::vector<int> tettt = v2t[ind_tet2];
double pti[3] {vertices[ttt[3]].x,
vertices[ttt[3]].y, vertices[ttt[3]].z};
double ati[3] {vertices[ttt[0]].x,
vertices[ttt[0]].y, vertices[ttt[0]].z};
double bti[3] {vertices[ttt[1]].x,
vertices[ttt[1]].y, vertices[ttt[1]].z};
double cti[3] {vertices[ttt[2]].x,
vertices[ttt[2]].y, vertices[ttt[2]].z};
double dti[3] {vertices[tettt[ind_d]].x,
vertices[tettt[ind_d]].y, vertices[tettt[ind_d]].z};
/*
Before insphere check if orientation
of points is correct
*/
float orient_1 = orient3d(ati, bti, cti, pti);
float detInSphere;
if(orient_1 < 0.0)
{
detInSphere = insphere(ati, cti, bti, pti, dti);
} else {
detInSphere = insphere(ati, bti, cti, pti, dti);
}
/*
if point d lies inside sphere of tetrahedron abcp,
check if it fulfills one of four other cases.
If so, change ordering of points corresponding to
the face
*/
if(detInSphere > 0.0)
{
/*
case 1: pd intersects area abc
perform Flip23
*/
if(signbit(orient3d(ati, bti, cti, pti))
!= signbit(orient3d(ati,bti,cti, dti)))
{
/*
Flip23:
get 'old' tetrahedrons and push three new one in vector
find ttt and tettt
in v2t/f2t
*/
std::sort(tettt.begin(), tettt.end());
for(int comp1=0; comp1 < (int) v2t.size(); comp1++)
{
std::sort(v2t[comp1].begin(), v2t[comp1].end());
if(v2t[comp1] == tettt)
{
v2t.erase(v2t.begin()+comp1);
f2t.erase(f2t.begin()+comp1);
}
}
std::sort(ttt.begin(), ttt.end());
for(int comp=0; comp < (int)v2t.size(); comp++)
{
std::sort(v2t[comp].begin(), v2t[comp].end());
if(v2t[comp] == ttt) {
v2t.erase(v2t.begin()+comp);
f2t.erase(f2t.begin()+comp);
break;
}
}
/*
remove tettt from tetfaces and tetverts
*/
std::sort(tettt.begin(), tettt.end());
for(int au=0; au < (int)tetfaces.size(); au++)
{
std::sort(tetfaces[au].begin(), tetfaces[au].end());
if(tetfaces[au] == tettt) {
tetfaces.erase(tetfaces.begin()+au);
tetverts.erase(tetverts.begin()+au);
}
}
/*
build new ones
p = ttt[3], a = ttt[0], b = ttt[1],
c = ttt[2], d = tettt[3]
*/
double dx1[3] {vertices[ttt[0]].x,
vertices[ttt[0]].y, vertices[ttt[0]].z};
double dx2[3] {vertices[ttt[1]].x,
vertices[ttt[1]].y, vertices[ttt[1]].z};
double dx3[3] {vertices[ttt[2]].x,
vertices[ttt[2]].y, vertices[ttt[2]].z};
double dx4[3] {vertices[ttt[3]].x,
vertices[ttt[3]].y, vertices[ttt[3]].z};
double dx5[3] {vertices[tettt[ind_d]].x,
vertices[tettt[ind_d]].y, vertices[tettt[ind_d]].z};
/*
abdp
*/
if(orient3d(dx1, dx2, dx5, dx4) > 0) {
std::vector<int> pnew1 {ttt[0], ttt[1], tettt[ind_d], ttt[3]};
v2t.push_back(pnew1);
tetverts.push_back(pnew1);
pnew1.clear();
} else {
std::vector<int> pnew1 {ttt[0], tettt[ind_d], ttt[1], ttt[3]};
v2t.push_back(pnew1);
tetverts.push_back(pnew1);
pnew1.clear();
}
/*
acdp
*/
if(orient3d(dx1, dx3, dx5, dx4) > 0) {
std::vector<int> pnew2 {ttt[0], ttt[2], tettt[ind_d], ttt[3]};
v2t.push_back(pnew2);
tetverts.push_back(pnew2);
pnew2.clear();
} else {
std::vector<int> pnew2 {ttt[0], tettt[ind_d], ttt[2], ttt[3]};
v2t.push_back(pnew2);
tetverts.push_back(pnew2);
pnew2.clear();
}
/*
bcdp
*/
if(orient3d(dx2, dx3, dx5, dx4) > 0) {
std::vector<int> pnew3 {ttt[1], ttt[2], tettt[ind_d], ttt[3]};
v2t.push_back(pnew3);
tetverts.push_back(pnew3);
pnew3.clear();
} else {
std::vector<int> pnew3 {ttt[1], tettt[ind_d], ttt[2], ttt[3]};
v2t.push_back(pnew3);
tetverts.push_back(pnew3);
pnew3.clear();
}
/*
first tet with faces
pac, acd, pcd, pad
*/
std::vector<int> fnew1 {ttt[3], ttt[0], ttt[2]};
std::vector<int> fnew2 {ttt[0], ttt[2], tettt[ind_d]};
std::vector<int> fnew3 {ttt[3], ttt[2], tettt[ind_d]};
std::vector<int> fnew4 {ttt[3], ttt[0], tettt[ind_d]};
// pbc, bcd, pcd, pbd
std::vector<int> fnew5 {ttt[3], ttt[1], ttt[2]};
std::vector<int> fnew6 {ttt[1], ttt[2], tettt[ind_d]};
// pdc s.o.: fnew3
std::vector<int> fnew7 {ttt[3], ttt[1], tettt[ind_d]};
// pab, abd, pad, pbd
std::vector<int> fnew8 {ttt[3], ttt[0], ttt[1]};
std::vector<int> fnew9 {ttt[0], ttt[1], tettt[ind_d]};
// pad s.o.: fnew4
// pbd s.o.: fnew7
int pos1 = 0;
std::vector<int> ftet;
std::vector<int> ftet2;
std::vector<int> ftet3;
/*
build new faces
check if combination already
exists
1. faces for tet 1
*/
if(!faceIn(fnew1, &pos1)) {
faces.push_back(fnew1);
ftet.push_back(faces.size()-1);
} else {
ftet.push_back(pos1);
}
if(!faceIn(fnew2, &pos1)) {
faces.push_back(fnew2);
ftet.push_back(faces.size()-1);
} else {
ftet.push_back(pos1);
}
if(!faceIn(fnew3, &pos1)) {
faces.push_back(fnew3);
ftet.push_back(faces.size()-1);
} else {
ftet.push_back(pos1);
}
if(!faceIn(fnew4, &pos1)) {
faces.push_back(fnew4);
ftet.push_back(faces.size()-1);
} else {
ftet.push_back(pos1);
}
/*
faces for tet 2
*/
if(!faceIn(fnew5, &pos1)) {
faces.push_back(fnew5);
ftet2.push_back(faces.size()-1);
} else {
ftet2.push_back(pos1);
}
if(!faceIn(fnew6, &pos1)) {
faces.push_back(fnew6);
ftet2.push_back(faces.size()-1);
} else {
ftet2.push_back(pos1);
}
if(!faceIn(fnew3, &pos1)) {
faces.push_back(fnew3);
ftet2.push_back(faces.size()-1);
} else {
ftet2.push_back(pos1);
}
if(!faceIn(fnew7, &pos1)){
faces.push_back(fnew7);
ftet2.push_back(faces.size()-1);
} else {
ftet2.push_back(pos1);
}
/*
faces for tet 3
*/
if(!faceIn(fnew8, &pos1)){
faces.push_back(fnew8);
ftet3.push_back(faces.size()-1);
} else {
ftet3.push_back(pos1);
}
if(!faceIn(fnew9, &pos1)){
faces.push_back(fnew9);
ftet3.push_back(faces.size()-1);
} else {
ftet3.push_back(pos1);
}
if(!faceIn(fnew7, &pos1)){
faces.push_back(fnew7);
ftet3.push_back(faces.size()-1);
} else {
ftet3.push_back(pos1);
}
if(!faceIn(fnew4, &pos1)) {
faces.push_back(fnew4);
ftet3.push_back(faces.size()-1);
} else {
ftet3.push_back(pos1);
}
/*
push in vectors
and update f2tsize
*/
f2t.push_back(ftet3);
f2t.push_back(ftet);
f2t.push_back(ftet2);
f2tsize = (int)f2t.size();
tetfaces.push_back(ftet3);
tetfaces.push_back(ftet);
tetfaces.push_back(ftet2);
} else
{
/*
case 2: pd does not intersect area abc and there is
a third tetrahedron abpd,
so all tetrahedrons share edge ab: Flip32
*/
int pos;
if(tetExists(ttt[0], ttt[1], ttt[3], tettt[ind_d], &pos)) {
std::vector<int> tetabpd = v2t[pos];
v2t.erase(v2t.begin() + pos);
f2t.erase(f2t.begin() + pos);
/*
find ttt in v2t/f2t
*/
std::sort(ttt.begin(), ttt.end());
for(int comp=0; comp < (int)v2t.size(); comp++)
{
std::sort(v2t[comp].begin(), v2t[comp].end());
if(v2t[comp] == ttt) {
// position is comp
v2t.erase(v2t.begin()+comp);
f2t.erase(f2t.begin()+comp);
break;
}
}
/*
find tettt in v2t/f2t
*/
std::sort(tettt.begin(), tettt.end());
for(int comp=0; comp < (int)v2t.size(); comp++)
{
std::sort(v2t[comp].begin(), v2t[comp].end());
if(v2t[comp] == tettt) {
// position is comp
v2t.erase(v2t.begin()+comp);
f2t.erase(f2t.begin()+comp);
break;
}
}
/*
perform flip32
build two new tetrahedrons from
three old ones
*/
double dx1[3] {vertices[ttt[0]].x,
vertices[ttt[0]].y, vertices[ttt[0]].z};
double dx2[3] {vertices[ttt[1]].x,
vertices[ttt[1]].y, vertices[ttt[1]].z};
double dx3[3] {vertices[ttt[2]].x,
vertices[ttt[2]].y, vertices[ttt[2]].z};
double dx4[3] {vertices[ttt[3]].x,
vertices[ttt[3]].y, vertices[ttt[3]].z};
double dx5[3] {vertices[tettt[ind_d]].x,
vertices[tettt[ind_d]].y, vertices[tettt[ind_d]].z};
if(orient3d(dx1, dx2, dx3, dx4) > 0) {
std::vector<int> pnew1 {ttt[0], ttt[1], ttt[2], ttt[3]};
v2t.push_back(pnew1);
tetverts.push_back(pnew1);
pnew1.clear();
} else {
std::vector<int> pnew1 {ttt[0], ttt[2], ttt[1], ttt[3]};
v2t.push_back(pnew1);
tetverts.push_back(pnew1);
pnew1.clear();
}
if(orient3d(dx1, dx2, dx3, dx5) > 0) {
std::vector<int> pnew2 {ttt[0], ttt[1], ttt[2], tettt[ind_d]};
v2t.push_back(pnew2);
tetverts.push_back(pnew2);
pnew2.clear();
} else {
std::vector<int> pnew2 {ttt[0], ttt[2], ttt[1], tettt[ind_d]};
v2t.push_back(pnew2);
tetverts.push_back(pnew2);
pnew2.clear();
}
std::vector<int> newf1 {ttt[3], ttt[0], ttt[2]};
std::vector<int> newf2 {ttt[3], ttt[1], ttt[2]};
std::vector<int> newf3 {ttt[3], ttt[0], ttt[1]};
std::vector<int> newf4 {ttt[0], ttt[1], ttt[2]}; // in both
std::vector<int> newf5 {ttt[0], ttt[2], tettt[ind_d]};
std::vector<int> newf6 {ttt[1], ttt[2], tettt[ind_d]};
std::vector<int> newf7 {ttt[0], ttt[1], tettt[ind_d]};
int pos2;
/*
check if face already exists
if yes: take position of needed face
if no: create new one
*/
std::vector<int> ftet32_1;
std::vector<int> ftet32_2;
if(faceIn(newf1, &pos2)) {
ftet32_1.push_back(pos2);
} else {
faces.push_back(newf1);
ftet32_1.push_back(faces.size()-1);
}
if(faceIn(newf2, &pos2)) {
ftet32_1.push_back(pos2);
} else {
faces.push_back(newf2);
ftet32_1.push_back(faces.size()-1);
}
if(faceIn(newf3, &pos2)) {
ftet32_1.push_back(pos2);
} else {
faces.push_back(newf3);
ftet32_1.push_back(faces.size()-1);
}
if(faceIn(newf4, &pos2)) {
ftet32_1.push_back(pos2);
} else {
faces.push_back(newf4);
ftet32_1.push_back(faces.size()-1);
}
if(faceIn(newf4, &pos2)) {
ftet32_2.push_back(pos2);
} else {
faces.push_back(newf4);
ftet32_2.push_back(faces.size()-1);
}
if(faceIn(newf5, &pos2)) {
ftet32_2.push_back(pos2);
} else {
faces.push_back(newf5);
ftet32_2.push_back(faces.size()-1);
}
if(faceIn(newf6, &pos2)) {
ftet32_2.push_back(pos2);
} else {
faces.push_back(newf6);
ftet32_2.push_back(faces.size()-1);
}
if(faceIn(newf7, &pos2)) {
ftet32_2.push_back(pos2);
} else {
faces.push_back(newf7);
ftet32_2.push_back(faces.size()-1);
}
/*
push new builded tetrahedrons
from faces in vectors
*/
f2t.push_back(ftet32_1);
f2t.push_back(ftet32_2);
// update f2tsize
f2tsize = (int)f2t.size();
tetfaces.push_back(ftet32_1);
tetfaces.push_back(ftet32_2);
}
else if(orient3d(pti, ati, bti, dti) == 0.00
|| orient3d(pti, bti, cti, dti) == 0.00
|| orient3d(pti, ati, cti, dti) == 0.00)
{
/*
case 3: line pd intersects edge of abc and there exist
two other tetrahedrons which share edges: flip44
1. sorting the vectors
*/
sort(ttt.begin(), ttt.end());
sort(tettt.begin(), tettt.end());
/*
declaring result vector to
store the common elements
*/
vector<int> v3(ttt.size() + tettt.size());
/*
iterator to store return type
*/
vector<int>::iterator it, end;
end = set_intersection(
ttt.begin(), ttt.end(),
tettt.begin(), tettt.end(),
v3.begin());
std::vector<int> samep;
for (it = v3.begin(); it != end; it++)
{
if(*it != ttt[3] && *it != tettt[ind_d])
{
samep.push_back(*it);
}
}
if((int)samep.size() == 2)
{
sort(samep.begin(), samep.end());
std::vector<int> vv(4);
int first = -1;
int second = -1;
/*
find two other tetrahedrons
with same points
*/
for(int r=0; r < (int)v2t.size(); r++)
{
std::vector<int> v = v2t[r];
sort(v.begin(), v.end());
std::set_intersection(v.begin(), v.end(),
samep.begin(), samep.end(),
std::back_inserter(vv));
if(vv.size() == 2) {
first = r;
vv.clear();
for(int rr=r; rr < (int)v2t.size(); rr++)
{
std::vector<int> v = v2t[rr];
sort(v.begin(), v.end());
std::set_intersection(v.begin(), v.end(),
samep.begin(), samep.end(),
std::back_inserter(vv));
if(vv.size() == 2) {
second = rr;
break;
}
}
break;
}
}
/*
found two other tetrahedrons
*/
if(first >= 0 && second >= 0)
{
std::vector<int> thitet = v2t[first];
std::vector<int> foutet = v2t[second];
if(first > second) {
v2t.erase(v2t.begin() + first);
f2t.erase(f2t.begin() + first);
v2t.erase(v2t.begin() + second);
f2t.erase(f2t.begin() + second);
} else {
v2t.erase(v2t.begin() + second);
f2t.erase(f2t.begin() + second);
v2t.erase(v2t.begin() + first);
f2t.erase(f2t.begin() + first);
}
/*
find ttt in v2t/f2t
find tettt in v2t/f2t
*/
for(int comp=0; comp < (int)v2t.size(); comp++)
{
if(v2t[comp] == ttt) {
v2t.erase(v2t.begin()+comp);
f2t.erase(f2t.begin()+comp);
break;
}
}
for(int comp=0; comp < (int)v2t.size(); comp++)
{
if(v2t[comp] == tettt) {
v2t.erase(v2t.begin()+comp);
f2t.erase(f2t.begin()+comp);
break;
}
}
/*
build 4 new tetrahedrons
1 curr.a, curr.b, curr.c, t1.d
2 curr.a, curr.b, curr.d, t1.d
3 d, curr.b, curr.c, t1.d
4 d, curr.b, curr.d, t1.d
*/
double ux[3] ={vertices[ttt[0]].x,
vertices[ttt[0]].y, vertices[ttt[0]].z};
double uy[3] ={vertices[ttt[1]].x,
vertices[ttt[1]].y, vertices[ttt[1]].z};
double uv[3] ={vertices[ttt[2]].x,
vertices[ttt[2]].y, vertices[ttt[2]].z};
double uw[3] ={vertices[ttt[3]].x,
vertices[ttt[3]].y, vertices[ttt[3]].z};
double ur[3] ={vertices[tettt[ind_d]].x,
vertices[tettt[ind_d]].y, vertices[tettt[ind_d]].z};
double ut[3] ={vertices[thitet[0]].x,
vertices[thitet[0]].y, vertices[thitet[0]].z};
/*
build new tetrahedrons
check order of vertices before push to vector
*/
if(orient3d(ux, uy, ut, uw) > 0) {
std::vector<int> newt1 {ttt[0], ttt[1],
thitet[0], ttt[3]};
v2t.push_back(newt1);
tetverts.push_back(newt1);
newt1.clear();
} else {
std::vector<int> newt1 {ttt[0], thitet[0], ttt[1], ttt[3]};
v2t.push_back(newt1);
tetverts.push_back(newt1);
newt1.clear();
}
if(orient3d(ur, ux, uy, ut) > 0) {
std::vector<int> newt2 {tettt[ind_d], ttt[0],
ttt[1], thitet[0]};
v2t.push_back(newt2);
tetverts.push_back(newt2);
newt2.clear();
} else {
std::vector<int> newt2 {tettt[ind_d], ttt[1],
ttt[0], thitet[0]};
v2t.push_back(newt2);
tetverts.push_back(newt2);
newt2.clear();
}
if(orient3d(ux, uv, ut, uw) > 0) {
std::vector<int> newt3 {ttt[0],
ttt[2], thitet[0], ttt[3]};
v2t.push_back(newt3);
tetverts.push_back(newt3);
newt3.clear();
} else {
std::vector<int> newt3 {ttt[0],
thitet[0], ttt[2], ttt[3]};
v2t.push_back(newt3);
tetverts.push_back(newt3);
newt3.clear();
}
if(orient3d(ur, ux, uv, ut) > 0) {
std::vector<int> newt4 {tettt[ind_d],
ttt[0], ttt[2], thitet[0]};
v2t.push_back(newt4);
tetverts.push_back(newt4);
newt4.clear();
} else {
std::vector<int> newt4 {tettt[ind_d],
ttt[2], ttt[0], thitet[0]};
v2t.push_back(newt4);
tetverts.push_back(newt4);
newt4.clear();
}
/*
Build faces and push
to vector
*/
std::vector<int> newf1 {ttt[3], ttt[0], ttt[1]};
std::vector<int> newf2 {ttt[3], ttt[1], thitet[0]};
std::vector<int> newf3 {ttt[0], ttt[1], thitet[0]};
std::vector<int> newf4 {ttt[3], ttt[0], thitet[0]};
std::vector<int> newf5 {tettt[ind_d], ttt[0], ttt[1]};
std::vector<int> newf6 {tettt[ind_d], ttt[1], thitet[0]};
std::vector<int> newf7 {ttt[0], ttt[1], thitet[0]};
std::vector<int> newf8 {tettt[ind_d], ttt[0], thitet[0]};
std::vector<int> newf9 {ttt[3], ttt[0], ttt[2]};
std::vector<int> newf10 {ttt[3], ttt[2], thitet[0]};
std::vector<int> newf11 {ttt[0], ttt[3], thitet[0]};
std::vector<int> newf12 {ttt[0], ttt[2], thitet[0]};
std::vector<int> newf13 {tettt[ind_d], ttt[2], thitet[0]};
std::vector<int> newf14 {tettt[ind_d], ttt[0], ttt[2]};
std::vector<int> newf15 {tettt[ind_d], ttt[0], thitet[0]};
std::vector<int> newf16 {ttt[0], ttt[2], thitet[0]};
int pos2 = 0;
std::vector<int> ftet44_1;
std::vector<int> ftet44_2;
std::vector<int> ftet44_3;
std::vector<int> ftet44_4;
/*
faces for tetrahedron 44-1
*/
if(!faceIn(newf1, &pos2)) {
faces.push_back(newf1);
ftet44_1.push_back(faces.size()-1);
} else {
ftet44_1.push_back(pos2);
}
if(!faceIn(newf2, &pos2)) {
faces.push_back(newf2);
ftet44_1.push_back(faces.size()-1);
} else {
ftet44_1.push_back(pos2);
}
if(!faceIn(newf3, &pos2)) {
faces.push_back(newf3);
ftet44_1.push_back(faces.size()-1);
} else {
ftet44_1.push_back(pos2);
}
if(!faceIn(newf4, &pos2)) {
faces.push_back(newf4);
ftet44_1.push_back(faces.size()-1);
} else {
ftet44_1.push_back(pos2);
}
/*
faces for tetrahedron 44-2
*/
if(!faceIn(newf5, &pos2)) {
faces.push_back(newf5);
ftet44_2.push_back(faces.size()-1);
} else {
ftet44_2.push_back(pos2);
}
if(!faceIn(newf6, &pos2)) {
faces.push_back(newf6);
ftet44_2.push_back(faces.size()-1);
} else {
ftet44_2.push_back(pos2);
}
if(!faceIn(newf7, &pos2)) {
faces.push_back(newf7);
ftet44_2.push_back(faces.size()-1);
} else {
ftet44_2.push_back(pos2);
}
if(!faceIn(newf8, &pos2)) {
faces.push_back(newf8);
ftet44_2.push_back(faces.size()-1);
} else {
ftet44_2.push_back(pos2);
}
/*
faces for tetrahedron 44-3
*/
if(!faceIn(newf9, &pos2)) {
faces.push_back(newf8);
ftet44_3.push_back(faces.size()-1);
} else {
ftet44_3.push_back(pos2);
}
if(!faceIn(newf10, &pos2)) {
faces.push_back(newf10);
ftet44_3.push_back(faces.size()-1);
} else {
ftet44_3.push_back(pos2);
}
if(!faceIn(newf11, &pos2)) {
faces.push_back(newf11);
ftet44_3.push_back(faces.size()-1);
} else {
ftet44_3.push_back(pos2);
}
if(!faceIn(newf12, &pos2)) {
faces.push_back(newf12);
ftet44_3.push_back(faces.size()-1);
} else {
ftet44_3.push_back(pos2);
}
/*
faces for tetrahedron 44-4
*/
if(!faceIn(newf13, &pos2)) {
faces.push_back(newf13);
ftet44_4.push_back(faces.size()-1);
} else {
ftet44_4.push_back(pos2);
}
if(!faceIn(newf14, &pos2)) {
faces.push_back(newf14);
ftet44_4.push_back(faces.size()-1);
} else {
ftet44_4.push_back(pos2);
}
if(!faceIn(newf15, &pos2)) {
faces.push_back(newf15);
ftet44_4.push_back(faces.size()-1);
} else {
ftet44_4.push_back(pos2);
}
if(!faceIn(newf16, &pos2)) {
faces.push_back(newf16);
ftet44_4.push_back(faces.size()-1);
} else {
ftet44_4.push_back(pos2);
}
f2t.push_back(ftet44_1);
f2t.push_back(ftet44_2);
f2t.push_back(ftet44_3);
f2t.push_back(ftet44_4);
/*
update f2tsize
*/
f2tsize = (int)f2t.size();
tetfaces.push_back(ftet44_1);
tetfaces.push_back(ftet44_2);
tetfaces.push_back(ftet44_3);
tetfaces.push_back(ftet44_4);
}
}
} else if(orient3d(ati, bti, cti, dti) == 0.00)
{
/*
case 4: tetrahedron is flat
perform Flip23
get 'old' tetrahedrons and push three new one in vector
*/
std::sort(tettt.begin(), tettt.end());
for(int comp1=0; comp1 < (int) v2t.size(); comp1++)
{
std::sort(v2t[comp1].begin(), v2t[comp1].end());
if(v2t[comp1] == tettt)
{
v2t.erase(v2t.begin()+comp1);
f2t.erase(f2t.begin()+comp1);
}
}
// find ttt in v2t/f2t
std::sort(ttt.begin(), ttt.end());
for(int comp=0; comp < (int)v2t.size(); comp++)
{
std::sort(v2t[comp].begin(), v2t[comp].end());
if(v2t[comp] == ttt) {
v2t.erase(v2t.begin()+comp);
f2t.erase(f2t.begin()+comp);
break;
}
}
// remove tettt from tetfaces and tetverts
std::sort(tettt.begin(), tettt.end());
for(int au=0; au < (int)tetfaces.size(); au++)
{
std::sort(tetfaces[au].begin(), tetfaces[au].end());
if(tetfaces[au] == tettt) {
tetfaces.erase(tetfaces.begin()+au);
tetverts.erase(tetverts.begin()+au);
}
}
/*
build new ones
p = ttt[3], a = ttt[0], b = ttt[1], c = ttt[2], d = tettt[3]
*/
double dx1[3] {vertices[ttt[0]].x,
vertices[ttt[0]].y, vertices[ttt[0]].z};
double dx2[3] {vertices[ttt[1]].x,
vertices[ttt[1]].y, vertices[ttt[1]].z};
double dx3[3] {vertices[ttt[2]].x,
vertices[ttt[2]].y, vertices[ttt[2]].z};
double dx4[3] {vertices[ttt[3]].x,
vertices[ttt[3]].y, vertices[ttt[3]].z};
double dx5[3] {vertices[tettt[ind_d]].x,
vertices[tettt[ind_d]].y, vertices[tettt[ind_d]].z};
// abdp
if(orient3d(dx1, dx2, dx5, dx4) > 0) {
std::vector<int> pnew1 {ttt[0], ttt[1], tettt[ind_d], ttt[3]};
v2t.push_back(pnew1);
tetverts.push_back(pnew1);
pnew1.clear();
} else {
std::vector<int> pnew1 {ttt[0], tettt[ind_d], ttt[1], ttt[3]};
v2t.push_back(pnew1);
tetverts.push_back(pnew1);
pnew1.clear();
}
// acdp
if(orient3d(dx1, dx3, dx5, dx4) > 0) {
std::vector<int> pnew2 {ttt[0], ttt[2], tettt[ind_d], ttt[3]};
v2t.push_back(pnew2);
tetverts.push_back(pnew2);
pnew2.clear();
} else {
std::vector<int> pnew2 {ttt[0], tettt[ind_d], ttt[2], ttt[3]};
v2t.push_back(pnew2);
tetverts.push_back(pnew2);
pnew2.clear();
}
// bcdp
if(orient3d(dx2, dx3, dx5, dx4) > 0) {
std::vector<int> pnew3 {ttt[1], ttt[2], tettt[ind_d], ttt[3]};
v2t.push_back(pnew3);
tetverts.push_back(pnew3);
pnew3.clear();
} else {
std::vector<int> pnew3 {ttt[1], tettt[ind_d], ttt[2], ttt[3]};
v2t.push_back(pnew3);
tetverts.push_back(pnew3);
pnew3.clear();
}
/*
first tet with faces
pac, acd, pcd, pad
*/
std::vector<int> fnew1 {ttt[3], ttt[0], ttt[2]};
std::vector<int> fnew2 {ttt[0], ttt[2], tettt[ind_d]};
std::vector<int> fnew3 {ttt[3], ttt[2], tettt[ind_d]};
std::vector<int> fnew4 {ttt[3], ttt[0], tettt[ind_d]};
// pbc, bcd, pcd, pbd
std::vector<int> fnew5 {ttt[3], ttt[1], ttt[2]};
std::vector<int> fnew6 {ttt[1], ttt[2], tettt[ind_d]};
// pdc s.o.: fnew3
std::vector<int> fnew7 {ttt[3], ttt[1], tettt[ind_d]};
// pab, abd, pad, pbd
std::vector<int> fnew8 {ttt[3], ttt[0], ttt[1]};
std::vector<int> fnew9 {ttt[0], ttt[1], tettt[ind_d]};
// pad s.o.: fnew4
// pbd s.o.: fnew7
int pos1 = 0;
std::vector<int> ftet;
std::vector<int> ftet2;
std::vector<int> ftet3;
/*
build faces
*/
if(!faceIn(fnew1, &pos1)) {
faces.push_back(fnew1);
ftet.push_back(faces.size()-1);
} else {
ftet.push_back(pos1);
}
if(!faceIn(fnew2, &pos1)) {
faces.push_back(fnew2);
ftet.push_back(faces.size()-1);
} else {
ftet.push_back(pos1);
}
if(!faceIn(fnew3, &pos1)) {
faces.push_back(fnew3);
ftet.push_back(faces.size()-1);
} else {
ftet.push_back(pos1);
}
if(!faceIn(fnew4, &pos1)) {
faces.push_back(fnew4);
ftet.push_back(faces.size()-1);
} else {
ftet.push_back(pos1);
}
if(!faceIn(fnew5, &pos1)) {
faces.push_back(fnew5);
ftet2.push_back(faces.size()-1);
} else {
ftet2.push_back(pos1);
}
if(!faceIn(fnew6, &pos1)) {
faces.push_back(fnew6);
ftet2.push_back(faces.size()-1);
} else {
ftet2.push_back(pos1);
}
if(!faceIn(fnew3, &pos1)) {
faces.push_back(fnew3);
ftet2.push_back(faces.size()-1);
} else {
ftet2.push_back(pos1);
}
if(!faceIn(fnew7, &pos1)){
faces.push_back(fnew7);
ftet2.push_back(faces.size()-1);
} else {
ftet2.push_back(pos1);
}
if(!faceIn(fnew8, &pos1)){
faces.push_back(fnew8);
ftet3.push_back(faces.size()-1);
} else {
ftet3.push_back(pos1);
}
if(!faceIn(fnew9, &pos1)){
faces.push_back(fnew9);
ftet3.push_back(faces.size()-1);
} else {
ftet3.push_back(pos1);
}
if(!faceIn(fnew7, &pos1)){
faces.push_back(fnew7);
ftet3.push_back(faces.size()-1);
} else {
ftet3.push_back(pos1);
}
if(!faceIn(fnew4, &pos1)) {
faces.push_back(fnew4);
ftet3.push_back(faces.size()-1);
} else {
ftet3.push_back(pos1);
}
/*
push in vectors
*/
f2t.push_back(ftet3);
f2t.push_back(ftet);
f2t.push_back(ftet2);
// update f2tsize
f2tsize = (int)f2t.size();
tetfaces.push_back(ftet3);
tetfaces.push_back(ftet);
tetfaces.push_back(ftet2);
}
}
}
}
}
}
}
/*
check if point p is already
in vector points
*/
bool
Convex3D::duplicateP(Point3D p)
{
for(size_t dup = 0; dup < points.size(); dup++)
{
if(points[dup].x == p.x && points[dup].y == p.y
&& points[dup].z == p.z) {
return true;
}
}
return false;
}
/*
build voronoi diagramm 3d
*/
void
Convex3D::buildVoronoi3D(Stream<Rectangle<3>> rStream) {
// get all points from input cuboids
rStream.open();
Rectangle<3>* next = rStream.request();
while(next != 0){
Point3D p = getCentre(next);
// check for duplicates
if(!duplicateP(p)) {
points.push_back(getCentre(next));
}
// free memory
delete next;
next = rStream.request();
}
rStream.close();
if(points.size() < 2)
{
const string errmsg = "Expected at least two points";
return;
}
Convex3D* conv3d = new Convex3D();
std::vector<Tetrahedron> tetravec;
// create delaunay diagram with points
createDelaunay(points, &tetravec);
std::vector<std::vector<Point3D>> facesPoints;
std::vector<std::tuple<int, int>> lines;
std::vector<std::vector<int>> temp;
std::vector<std::vector<int>> tempF;
std::vector<Point3D> circumcenters;
/*
create voronoi diagram from delaunay diagram
find all lines including point p from points
*/
for(int t=0; t < (int)points.size(); t++)
{
int p_index;
for(size_t id=0; id < vertices.size(); id++)
{
if(comparePoints3D(vertices[id], points[t]))
{
p_index = id;
break;
}
}
lines.clear();
for(int z=0; z<(int)v2t.size(); z++)
{
std::vector<int> fin = v2t[z];
if(fin[0] == p_index)
{
if(!insidevec(fin[0], fin[1], lines)) {
lines.push_back(std::make_tuple(fin[0], fin[1])); }
if(!insidevec(fin[0], fin[2], lines)) {
lines.push_back(std::make_tuple(fin[0], fin[2])); }
if(!insidevec(fin[0], fin[3], lines)) {
lines.push_back(std::make_tuple(fin[0], fin[3]));
}
}
else if(fin[1] == p_index)
{
if(!insidevec(fin[1], fin[0], lines)) {
lines.push_back(std::make_tuple(fin[1], fin[0])); }
if(!insidevec(fin[1], fin[2], lines)) {
lines.push_back(std::make_tuple(fin[1], fin[2])); }
if(!insidevec(fin[1], fin[3], lines)) {
lines.push_back(std::make_tuple(fin[1], fin[3]));
}
}
else if(fin[2] == p_index)
{
if(!insidevec(fin[2], fin[0], lines)) {
lines.push_back(std::make_tuple(fin[2], fin[0])); }
if(!insidevec(fin[2], fin[1], lines)) {
lines.push_back(std::make_tuple(fin[2], fin[1])); }
if(!insidevec(fin[2], fin[3], lines)) {
lines.push_back(std::make_tuple(fin[2], fin[3]));
}
}
else if(fin[3] == p_index)
{
if(!insidevec(fin[3], fin[0], lines)) {
lines.push_back(std::make_tuple(fin[3], fin[0])); }
if(!insidevec(fin[3], fin[1], lines)) {
lines.push_back(std::make_tuple(fin[3], fin[1])); }
if(!insidevec(fin[3], fin[2], lines)) {
lines.push_back(std::make_tuple(fin[3], fin[2]));
}
}
}
// find tetrahedrons to lines
for(int n=0; n < (int)lines.size(); n++)
{
std::tuple<int, int> tup = lines.at(n);
int p1 = std::get<0>(tup);
int p2 = std::get<1>(tup);
for(int b=0; b < (int)v2t.size(); b++)
{
if(sameline(p1, p2, v2t[b]))
{
temp.push_back(v2t[b]);
tempF.push_back(f2t[b]);
}
}
// sort tetrahedrons of temp
// face to face
std::vector<std::vector<int>> tempSorted;
std::vector<int> faces = tempF[temp.size()-1];
tempSorted.push_back(temp[temp.size()-1]);
int x = temp.size()-1;
while(temp.size() > 0)
{
bool foundface = false;
faces = tempF[x];
temp.erase(temp.begin()+x);
tempF.erase(tempF.begin()+x);
for(size_t st=0; st < faces.size(); st++)
{
int face = faces[st];
for(int ai=0; ai < (int)tempF.size(); ai++)
{
auto it = std::find(std::begin(tempF[ai]),
std::end(tempF[ai]), face);
if(it != std::end(tempF[ai])) {
tempSorted.push_back(temp[ai]);
foundface = true;
x = ai;
break;
}
}
if(foundface) { break; }
}
}
/*
all tetrahedrons in vector which share line point\_tup[n]
get circumcenter which builds vertex of face of polyhedron
*/
for(int m=0; m< (int)tempSorted.size(); m++)
{
Point3D vertex = getCircumcenter(vertices[tempSorted[m][0]],
vertices[tempSorted[m][1]],
vertices[tempSorted[m][2]], vertices[tempSorted[m][3]]);
if(isfinite(vertex.x) && isfinite(vertex.y)
&& isfinite(vertex.z))
{
circumcenters.push_back(vertex);
}
}
facesPoints.push_back(circumcenters);
tempSorted.clear();
circumcenters.clear();
}
// create polyhedron
Polyhedron polyhedron = Polyhedron();
std::vector<Point3D> face;
polyhedron.setPolyId(t+1);
for(int s=0; s< (int)facesPoints.size(); s++)
{
face.clear();
for(int g=0; g<(int)facesPoints.at(s).size(); g++)
{
face.push_back(facesPoints.at(s).at(g));
}
if(!face.empty()) {
polyhedron.faces.push_back(face);
}
}
// save polyhedron in vector
polyhedronvec.push_back(polyhedron);
facesPoints.clear();
}
conv3d->setPolyhedronVector(polyhedronvec);
delete conv3d;
}
/*
8.2.1 cellNumVM
*/
int cellNum3DVM( Word* args, Word& result, int message,
Word& local, Supplier s )
{
Convex3D *convex3d = static_cast<Convex3D*>(args[0].addr);
Rectangle<3> *search_window_ptr
= static_cast<Rectangle<3>*>( args[1].addr );
/*
mode == 1 => precise allocation;
mode == 2 => use Bboxes of convex3d cells
In case the user did not specify the mode of
allocation, use Bboxes
*/
int mode = ((CcInt*)args[2].addr)->GetIntval();
std::set<int> cell_ids;
int bbox = 2;
int precise = 1;
result = qp->ResultStorage(s);
collection::IntSet* res = (collection::IntSet*) result.addr;
if(search_window_ptr == nullptr || convex3d == nullptr) {
return 0;
}
if(mode > bbox || mode < precise) {
mode = bbox;
}
cellNum3D(convex3d, search_window_ptr, mode, &cell_ids);
res->setTo(cell_ids);
return 0;
}
/*
8.2.2 smallestCommonCellnumVM
*/
int smallestCommonCellnum3DVM( Word* args, Word& result, int message,
Word& local, Supplier s )
{
Convex3D *convex3d = static_cast<Convex3D*>(args[0].addr);
Rectangle<3> *search_window_ptr
= static_cast<Rectangle<3>*>( args[1].addr );
Rectangle<3> *search_window_ptr_2
= static_cast<Rectangle<3>*>( args[2].addr );
CcInt* cellno_ptr = static_cast<CcInt*>(args[3].addr);
int cellno = cellno_ptr->GetIntval();
if(search_window_ptr == nullptr
|| search_window_ptr_2 == nullptr
|| convex3d == nullptr) {
return -1;
}
result = qp->ResultStorage( s );
CcBool *res = (CcBool*) result.addr;
bool boolval = false;
std::set<int> intsetRect1;
cellNum3D(convex3d, search_window_ptr, 1, &intsetRect1);
std::set<int> intsetRect2;
cellNum3D(convex3d, search_window_ptr_2, 1, &intsetRect2);
std::vector<int> v(sizeof(intsetRect1)+ sizeof(intsetRect2));
std::vector<int>::iterator it;
it=std::set_intersection (intsetRect1.begin(), intsetRect1.end(),
intsetRect2.begin(), intsetRect2.end(), v.begin());
v.resize(it-v.begin());
if(v.empty()) {
//no intersection between rectangles
res->Set( true, boolval);
return 0;
}
if(v[0] == cellno)
{
boolval = true;
res->Set( true, boolval);
return 0;
}
res->Set( true, boolval);
return 0;
}
/*
8.2.3 getcellvoronoi3DVM
*/
int getcellvoronoi3DVM(Word* args, Word& result, int message,
Word& local, Supplier s)
{
Convex3D *convex3d = static_cast<Convex3D*>(args[0].addr);
CcInt* cellno_ptr = static_cast<CcInt*>(args[1].addr);
int cellno = cellno_ptr->GetIntval();
result = qp->ResultStorage( s );
Rectangle<3> *res = (Rectangle<3>*) result.addr;
std::vector<Polyhedron> polyvec = convex3d->getPolyhedronVector();
for(size_t i = 0; i < polyvec.size(); i++)
{
if(polyvec[i].getPolyId() == cellno)
{
double min[3], max[3];
Rectangle<3> bbox = createBBox3D(&polyvec[i]);
min[0] = bbox.getMinX();
min[1] = bbox.getMinY();
min[2] = bbox.getMinZ();
max[0] = bbox.getMaxX();
max[1] = bbox.getMaxY();
max[2] = bbox.getMaxZ();
res->Set(true, min, max);
return 0;
}
}
return -1;
}
/*
Valuemapping function for create 3D-Tree
*/
int voronoi3dVM( Word* args, Word& result, int message,
Word& local, Supplier s ) {
Stream<Rectangle<3>> input_rect_ptr(args[0]);
result = qp->ResultStorage(s);
((Convex3D*)result.addr)->Set(
input_rect_ptr);
return 0;
}
/*
8.3 Specifications
*/
/*
createconvexSpec
*/
const string createconvexSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>stream(points) x bool -> convex </text--->"
"<text>_ createconvex </text--->"
"<text>Creates a convex polygon in form of a point sequence "
"starting from the left point in clockwise order."
"The input point sequence does not have to be ordered in that way. "
"Returns the polygon "
"if the input point sequence form a convex polygon. "
"Otherwise undef is returned either if the point stream "
"does not form a convex polygon or "
"any other error occurs. With the bool parameter, you can switch on/off "
" the convex test. Be sure that your data form convex polygons when "
"you switch it to FALSE. With TRUE the test is enabled </text--->"
"<text> query Kinos feed head [3] projecttransformstream[GeoData] "
"createconvex[TRUE] </text--->"
") )";
/*
voronoiSpec
*/
const string voronoiSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>((stream (tuple (..., (ak1 Tk1),...))) x"
" ak1 x ak2 x rect x bool"
"-> (stream (tuple (..., (ak1 Tk1),..., "
"(ak2 Tk2))))) </text--->"
"<text>_ voronoi [ list ] </text--->"
"<text>Expands each tuple of the relation with a convex polygon "
" representing the voronoi cell that belongs to the "
"centerpoint specified "
" with point value Tk1 of the attribute ak1. The complete voronoi "
" diagramm is set up with "
" all points of ak1 from all tuples, in other words with "
"all points of the "
" ak1 column of the relation. "
"The value of ak2 ist the type convex forming a convex polygon "
"representing the voronoi region "
"that is corresponding to the point value of ak1. "
"The rect paramater specifies a rectangle "
" forming the bounding box of the voronoi diagram. If the diagram fits "
"in the box the rectangle values are used. The sequence of parameters "
"for the rectangle values must be (minx, maxx, miny, maxy). "
" If the diagram do not fit in the rectangle box, a default box is used "
" derived from the expansion of the voronoi diagram."
" With the last parameter you can switch on/off the convex polygon test. "
" When TRUE is set the contructed polygons are explicit tested "
" if they are convex. Choose FALSE, when you are sure about "
"that property and "
" you want to leave out the test.</text--->"
"<text> query testrel feed voronoi [p, conv, "
"[const rect value (-10 9 2 )], TRUE] </text--->"
") )";
/*
cellNumSpec
*/
const string cellNumSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> Stream<Convex> x rect2 x int"
"-> intset </text--->"
"<text>_ cellnum[ list ] </text--->"
"<text> Returns all cellnumbers of the created voronoi"
" diagram which intersect with the given "
" rectangle. </text--->"
"<text> query cellnum((convtest feed voronoi "
" [Punkt, Conv, [const rect value (-10 10 -10 10)], "
" FALSE] project[Conv] consume) feed "
" projecttransformstream[Conv], "
" rectangle2(-1.0, 4.0, 0.0, 2.0), 1) </text--->"
") )";
const string smallestCommCellnumSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> Stream<Convex> x rect2 x rect2 x int"
"-> bool </text--->"
"<text>_ sccvoronoi [ list ] </text--->"
"<text> Returns true if int equals "
" the smallest common cellnumber "
" of two rectangles in a voronoi diagram. First "
" the voronoi diagram is created as in voronoi(). </text--->"
"<text> query sccvoronoi((convtest feed voronoi "
" [Punkt, Conv, [const rect value (-10 10 -10 10)], FALSE] "
" project[Conv] consume) feed projecttransformstream[Conv],"
" rectangle2(-1.0, 4.0, 0.0, 2.0), "
" rectangle2(5.0, 7.0, -0.5, 0.5), 5) </text--->"
") )";
const string getcellvoronoiSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> Stream<Convex> x int "
"-> rectangle<2> </text--->"
"<text>_ getcellvoro [ ] </text--->"
"<text>Returns the bbox of a cell to "
" the given cellid </text--->"
"<text> query getcellvoro((convtest feed voronoi "
" [Punkt, Conv, [const rect value (-10 10 -10 10)], FALSE] "
" project[Conv] consume) feed projecttransformstream[Conv],"
" 2 </text--->"
") )";
const string voronoi3dSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> stream(rect3) x rect3"
"-> (stream (convex3d) </text--->"
"<text>_ voronoi3d [] </text--->"
"<text> It calculates the centre of the cuboids "
" and builds the voronoi diagram to this set of points. "
" Returns a list of cell ids with the number of faces "
" belonging to this cell ids."
" </text--->"
"<text> query [const rect3 value(-1 2 -3 6 0 2)] feed voronoi3d [ "
"[const rect3 value (-10 10 9 20 2 10)]] </text--->"
") )";
const string cellNum3DSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>((stream (rect3) x rect3"
"-> intset </text--->"
"<text>_ cellnum3d[ list ] </text--->"
"<text> Returns all cellnumbers of the created voronoi"
" diagram which intersect with the given "
" cuboid. </text--->"
"<text> query cellnum3d([const rect3 value(-1 2 -3 6 0 2)]"
" feed voronoi3d "
" [const rect value (-10 10 -10 10 -10 10)], "
" rectangle3(-1.0, 4.0, 0.0, 2.0, 1.0, 2.0)) </text--->"
") )";
const string smallestCommCellnum3DSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text>((stream(rect3) x rect3 x rect3 x int"
"-> bool </text--->"
"<text>_ sccvoronoi3d [ list ] </text--->"
"<text> Returns true if int equals "
" the smallest common cellnumber "
" of two cuboids in a voronoi diagram. First "
" the voronoi diagram is created as in voronoi(). </text--->"
"<text> query ssc_voronoi3d([const rect3 value(-1 2 -3 6 0 2)]"
" feed voronoi3d "
" [const rect value (-10 10 -10 10 -10 10)], "
" rectangle3(-1.0, 4.0, 0.0, 2.0, 1.0, 2.0), "
" rectangle3(-1.0, 2.0, 1.0, 2.0, 1.0, 2.0), 5) </text--->"
") )";
const string getcellvoronoi3DSpec =
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" ) "
"( <text> Stream<Convex3D> x int "
"-> rectangle<3> </text--->"
"<text>_ getcellvoro3d [ ] </text--->"
"<text>Returns the bbox of a cell to "
" the given cellid </text--->"
"<text> query getcellvoro3d((convtest feed voronoi "
" [Punkt, Conv, [const rect value (-10 10 -10 10)], FALSE] "
" project[Conv] consume) feed projecttransformstream[Conv],"
" 2 </text--->"
") )";
/*
10 Registration an initialization
*/
/*
10.1 Registration of Types
*/
TypeConstructor Conv3DTC(
// name of the type in SECONDO
Convex3D:: BasicType(),
// property function describing signature
Convex3D::PropertyConvex3D,
// Out and In functions
Convex3D::OutConvex3D, Convex3D::InConvex3D,
// SaveToList, RestoreFromList functions
0,0,
// object creation and deletion
Convex3D::CreateConvex3D, Convex3D::DeleteConvex3D,
// object open, save
0, 0,
// object close and clone
Convex3D::Close, Convex3D::CloneConvex3D,
// cast function
0,
// sizeof function
Convex3D::SizeOfConvex3D,
// kind checking function
Convex3D::KindCheckConvex3D
);
TypeConstructor ConvexTC(
Convex::BasicType(),
Convex::Property, Convex::Out, Convex::In, 0,0,
Convex::Create, Convex::Delete,
Convex::Open, Convex::Save, Convex::Close, Convex::Clone,
Convex::Cast, Convex::Size, Convex::TypeCheck
);
/*
10.2 Operator instances
*/
Operator createconvex ( "createconvex",
createconvexSpec,
createconvexVM,
Operator::SimpleSelect,
createconvextypemap );
Operator voronoi ( "voronoi",
voronoiSpec,
voronoiVM,
Operator::SimpleSelect,
voronoitypemap );
Operator cellnum ("cellnum",
cellNumSpec,
cellNumVM,
Operator::SimpleSelect,
cellnumvoronoitypemap );
Operator sccvoronoi ("sccvoronoi",
smallestCommCellnumSpec,
smallestCommonCellnumVM,
Operator::SimpleSelect,
sccvoronoitypemap );
Operator getcellvoronoi ( "getcellvoronoi",
getcellvoronoiSpec,
getcellvoronoiVM,
Operator::SimpleSelect,
getcellvoronoitypemap);
Operator voronoi3d ( "voronoi3d",
voronoi3dSpec,
voronoi3dVM,
Operator::SimpleSelect,
voronoi3dtypemap );
Operator cellnum3d ("cellnum3d",
cellNum3DSpec,
cellNum3DVM,
Operator::SimpleSelect,
cellnumvoronoi3dtypemap );
Operator sccvoronoi3d ("sccvoronoi3d",
smallestCommCellnum3DSpec,
smallestCommonCellnum3DVM,
Operator::SimpleSelect,
sccvoronoi3dtypemap );
Operator getcellvoronoi3d ( "getcellvoronoi3d",
getcellvoronoi3DSpec,
getcellvoronoi3DVM,
Operator::SimpleSelect,
getcellvoronoi3dtypemap);
/*
10.3 Creating the Algebra
*/
class ConvexAlgebra : public Algebra
{
public:
ConvexAlgebra() : Algebra()
/*
Registration of Types
*/
{
AddTypeConstructor(&ConvexTC);
ConvexTC.AssociateKind(Kind::DATA() );
AddTypeConstructor ( &Conv3DTC );
Conv3DTC.AssociateKind(Kind::SIMPLE() );
/*
Registration of operators
*/
AddOperator( &createconvex);
AddOperator( &voronoi);
AddOperator( &cellnum);
AddOperator( &sccvoronoi);
AddOperator( &getcellvoronoi );
AddOperator( &voronoi3d );
AddOperator( &cellnum3d );
AddOperator( &sccvoronoi3d );
AddOperator( &getcellvoronoi3d );
}
~ConvexAlgebra() {};
};
}
/*
end of namespace
*/
/*
10.4 Initialization
*/
extern "C"
Algebra*
InitializeConvex2Algebra( NestedList* nlRef, QueryProcessor* qpRef )
{
nl = nlRef;
qp = qpRef;
return new convex::ConvexAlgebra;
}