Files
secondo/Algebras/TIN/Triangle.cpp
2026-01-23 17:03:45 +08:00

1370 lines
30 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2004-2007, University in Hagen, Department of 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
----
Class ~Triangle~ and nested class triangleWalker
*/
#include "Triangle.h"
#include <iostream>
#include <sstream>
#include <string>
#include "Edge.h"
#include "TinPart.h"
#ifdef TRIANGLE_NO_LOGGING
#define LOGGING_SWITCH_OFF
#endif
#include <TinLogging.h>
namespace tin {
const bool Triangle::edge_iterator::FORWARD = true;
const bool Triangle::edge_iterator::BACKWARD = false;
Triangle::Triangle(const Vertex* iv1, const Vertex* iv2, const Vertex* iv3,
TinPart * imyPart) {
LOGP
const Vertex * clockwise_second_vertex;
if (!iv1 || !iv2 || !iv3)
throw std::invalid_argument(
"Constructing triangle with null pointer.(Triangle::Triangle)");
if ((clockwise_second_vertex = Triangle::isTriangle_sec(iv1, iv2, iv3))) {
v1 = iv1;
v2 = clockwise_second_vertex;
v3 = (clockwise_second_vertex == iv2 ? iv3 : iv2);
n1 = 0;
n2 = 0;
n3 = 0;
myPart = imyPart;
LOG_EXP (print())
LOG("trianglecreate")
} else {
std::ostringstream str;
str << "Constructing triangle with invalid vertices."
<< "Three vertices on a line.(Triangle::Triangle)";
iv1->print(str);
iv2->print(str);
iv3->print(str);
throw std::invalid_argument(str.str().c_str());
}
LOGP
}
Triangle::Triangle(AbstractVertexContainer* vc, char * buff,
size_t & offset, TinPart * imyPart) {
LOGP
FILE_VERTEX_POINTER lv1, lv2, lv3;
FILE_TRIANGLE_POINTER lt1, lt2, lt3;
lv1 = *((FILE_VERTEX_POINTER*) (buff + offset));
offset += sizeof(FILE_VERTEX_POINTER);
lv2 = *((FILE_VERTEX_POINTER*) (buff + offset));
offset += sizeof(FILE_VERTEX_POINTER);
lv3 = *((FILE_VERTEX_POINTER*) (buff + offset));
offset += sizeof(FILE_VERTEX_POINTER);
v1 = vc->getVertexByYIndex(lv1);
v2 = vc->getVertexByYIndex(lv2);
v3 = vc->getVertexByYIndex(lv3);
LOG_EXP(v1->print())
LOG_EXP(v2->print())
LOG_EXP(v3->print())
myPart = imyPart;
lt1 = *((FILE_TRIANGLE_POINTER*) (buff + offset));
offset += sizeof(FILE_TRIANGLE_POINTER);
lt2 = *((FILE_TRIANGLE_POINTER*) (buff + offset));
offset += sizeof(FILE_TRIANGLE_POINTER);
lt3 = *((FILE_TRIANGLE_POINTER*) (buff + offset));
offset += sizeof(FILE_TRIANGLE_POINTER);
switch (lt1) {
case FILE_TRIANGLE_POINTER_BOUNDARY:
LOGP
n1 = VORONOI_OPEN_END;
break;
case FILE_TRIANGLE_POINTER_UNKNOWN:
LOGP
n1 = 0;
break;
default:
LOGP
n1 = myPart->getTriangleByIndex(lt1);
break;
}
switch (lt2) {
case FILE_TRIANGLE_POINTER_BOUNDARY:
n2 = VORONOI_OPEN_END;
break;
case FILE_TRIANGLE_POINTER_UNKNOWN:
n2 = 0;
break;
default:
n2 = myPart->getTriangleByIndex(lt2);
break;
}
switch (lt3) {
case FILE_TRIANGLE_POINTER_BOUNDARY:
n3 = VORONOI_OPEN_END;
break;
case FILE_TRIANGLE_POINTER_UNKNOWN:
n3 = 0;
break;
default:
n3 = myPart->getTriangleByIndex(lt3);
break;
}
}
Triangle::Triangle() {
n1 = 0;
n2 = 0;
n3 = 0;
v1 = 0;
v2 = 0;
v3 = 0;
myPart = 0;
}
Triangle::~Triangle() {
LOGP
LOG(myPart)
LOG(n1)
LOG(n2)
LOG(n3)
if (n1 && n1 != VORONOI_OPEN_END)
n1->removeNeighbor(this);
if (n2 && n2 != VORONOI_OPEN_END)
n2->removeNeighbor(this);
if (n3 && n3 != VORONOI_OPEN_END)
n3->removeNeighbor(this);
LOGP}
NeighborEdge Triangle::getEdgeWithVertex(const Vertex * iv) {
LOGP
if (*iv == *v1)
return NeighborEdge(v1, v2, this, n1);
if (*iv == *v2)
return NeighborEdge(v2, v3, this, n2);
if (*iv == *v3)
return NeighborEdge(v3, v1, this, n3);
LOGP
return NeighborEdge();
}
const Vertex * Triangle::getMaxYVertex() const {
if (*v1 < *v2) {
if (*v2 < *v3) {
return v3;
} else {
return v2;
}
} else {
if (*v3 < *v1) {
return v1;
} else {
return v3;
}
}
}
const Vertex * Triangle::getMaxYCWVertex() const {
if (*v1 < *v2) {
if (*v2 < *v3) {
return v1;
} else {
return v3;
}
} else {
if (*v3 < *v1) {
return v2;
} else {
return v1;
}
}
}
const Vertex * Triangle::getMaxYCCWVertex() const {
if (*v1 < *v2) {
if (*v2 < *v3) {
return v2;
} else {
return v1;
}
} else {
if (*v3 < *v1) {
return v3;
} else {
return v2;
}
}
}
const Vertex * Triangle::getMiddleYVertex() const {
if (*v1 < *v2) {
if (*v2 < *v3) {
return v2;
} else if (*v3 < *v1) {
return v1;
} else {
return v3;
}
} else {
if (*v1 < *v3) {
return v1;
} else if (*v3 < *v2) {
return v2;
} else
return v3;
}
}
const Vertex * Triangle::getMinYVertex() const {
if (*v1 < *v2) {
if (*v1 < *v3) {
return v1;
} else {
return v3;
}
} else {
if (*v3 < *v2) {
return v3;
} else {
return v2;
}
}
}
bool Triangle::hasEdge(const Edge& e) {
return (getEdge(1).equal3D(e) || getEdge(2).equal3D(e)
|| getEdge(3).equal3D(e));
}
NeighborEdge Triangle::getNextEdge(const NeighborEdge& currentEdge) {
LOGP
if (*(currentEdge.getV1()) == *v1) {
if (*(currentEdge.getV2()) == *v2)
return NeighborEdge(v1, v3, this, getNeighbor(3));
else
return NeighborEdge(v1, v2, this, getNeighbor(1));
}
if (*(currentEdge.getV1()) == *v2) {
if (*(currentEdge.getV2()) == *v1)
return NeighborEdge(v2, v3, this, getNeighbor(2));
else
return NeighborEdge(v2, v1, this, getNeighbor(1));
}
if (*(currentEdge.getV1()) == *v3) {
if (*(currentEdge.getV2()) == *v1)
return NeighborEdge(v3, v2, this, getNeighbor(2));
else
return NeighborEdge(v3, v1, this, getNeighbor(3));
}
LOGP
return NeighborEdge(0, 0, 0, 0);
}
NeighborEdge Triangle::getNextEdge_noload(
const NeighborEdge& currentEdge) {
LOGP
if (*(currentEdge.getV1()) == *v1) {
if (*(currentEdge.getV2()) == *v2)
return NeighborEdge(v1, v3, this, n3);
else
return NeighborEdge(v1, v2, this, n1);
}
if (*(currentEdge.getV1()) == *v2) {
if (*(currentEdge.getV2()) == *v1)
return NeighborEdge(v2, v3, this, n2);
else
return NeighborEdge(v2, v1, this, n1);
}
if (*(currentEdge.getV1()) == *v3) {
if (*(currentEdge.getV2()) == *v1)
return NeighborEdge(v3, v2, this, n2);
else
return NeighborEdge(v3, v1, this, n3);
}
LOGP
return NeighborEdge(0, 0, 0, 0);
}
Triangle* Triangle::getNeighbor(const int index) {
LOGP
Triangle * nt = 0;
switch (index) {
case 1:
if (n1)
return n1;
else {
if (myPart)
nt = myPart->getNeighbor(Edge(v1, v2), this);
if (nt)
addNeighbor(nt);
return n1;
}
break;
case 2:
if (n2)
return n2;
else {
if (myPart)
nt = myPart->getNeighbor(Edge(v2, v3), this);
if (nt)
addNeighbor(nt);
return n2;
}
break;
case 3:
if (n3)
return n3;
else {
if (myPart)
nt = myPart->getNeighbor(Edge(v3, v1), this);
if (nt)
addNeighbor(nt);
return n3;
}
break;
default:
LOGP
throw std::runtime_error("Index out of bounds.(Triangle::getNeighbor)");
}
}
bool Triangle::triangleWalker::heightWalk(
Triangle::triangleWalker * walker, Triangle* next) {
if (next == (Triangle*) END_OF_SEGMENT
|| next == (Triangle*) END_OF_WALK) {
heightWalkParameter * p =
(heightWalkParameter *) walker->getUserParameter1();
Triangle * c = walker->getCurrentTriangle();
p->values.push_back(c->getValue(walker->getCurrentDestination()));
}
return false;
}
bool Triangle::triangleWalker::stopAtEdgeWalk(
Triangle::triangleWalker * walker, Triangle* next) {
Edge * e = (Edge*) walker->getUserParameter1();
if (e) {
if (!walker->isTriangle(next))
return true;
if (walker->getCurrentTriangle()->hasEdge(*e) && next->hasEdge(*e))
return true;
}
return false;
}
Triangle * Triangle::walkToTriangle_sec(const Point_p & destination) {
LOGP
Point_p * arPoints = new Point_p[1];
arPoints[0] = destination;
Triangle::triangleWalker walker(this, arPoints, 1, false, false);
walker.walk_sec();
LOG(*myPart)
LOG("Part of result:")
LOG_EXP((walker.getCurrentTriangle())->print())
LOGP
if (walker.getCurrentTriangle()->isInside_sec(destination))
return walker.getCurrentTriangle();
else
return 0;
}
int Triangle::triangleWalker::walk_step_sec_return(Edge &edge) {
SecureOperator::startSecureCalc();
// cout << "current segment: (("
// << currentSegment.getV1()->getX() << ", "
// << currentSegment.getV1()->getY() << "), ("
// << currentSegment.getV2()->getX() << ", "
// << currentSegment.getV2()->getY() << "))" << "\r\n";
LOGP
Edge e = current->getEdge(1);
LOG("Walk a step in Triangle: ")
LOG_EXP(current->print())
//turn to neighbor n1
if (e.intersects_sec(&currentSegment)
&& e.getSide_sec((Point_p) *currentSegment.getV2()) < 0) {
edge = e;
// cout << "intersect edge 1" << "\r\n";
if (!current->n1 && !noload) {
current->getNeighbor(1);
}
if (!current->n1 || current->n1 == VORONOI_OPEN_END
|| (stayInSamePart && !current->n1->isInSamePart(current))) {
if (userExit && userExit(this, (Triangle*) END_OF_ACCESS))
return END_OF_WALK;
LOG("End of walk")
LOG(current->n1)
return END_OF_WALK;
} else {
if (current->n1 != last) {
if (userExit && userExit(this, current->n1))
return END_OF_WALK;
last = current;
current = current->n1;
LOGP
return TRIANGLE_ENTERED;
}
}
}
//turn to neighbor n2
e = current->getEdge(2);
if (e.intersects_sec(&currentSegment)
&& e.getSide_sec((Point_p) *currentSegment.getV2()) < 0) {
edge = e;
// cout << "intersect edge 2" << "\r\n";
if (!current->n2 && !noload) {
current->getNeighbor(2);
}
if (!current->n2 || current->n2 == VORONOI_OPEN_END
|| (stayInSamePart && !current->n2->isInSamePart(current))) {
if (userExit && userExit(this, (Triangle*) END_OF_ACCESS))
return END_OF_WALK;
LOG("End of walk")
LOG(current->n2)
return END_OF_WALK;
} else {
if (current->n2 != last) {
if (userExit && userExit(this, current->n2))
return END_OF_WALK;
last = current;
current = current->n2;
LOGP
return TRIANGLE_ENTERED;
}
}
}
//turn to neighbor n3
e = current->getEdge(3);
if (e.intersects_sec(&currentSegment)
&& e.getSide_sec((Point_p) *currentSegment.getV2()) < 0) {
edge = e;
// cout << "intersect edge 3" << "\r\n";
if (!current->n3 && !noload) {
current->getNeighbor(3);
}
if (!current->n3 || current->n3 == VORONOI_OPEN_END
|| (stayInSamePart && !current->n3->isInSamePart(current))) {
if (userExit && userExit(this, (Triangle*) END_OF_ACCESS))
return END_OF_WALK;
LOG(current->n3)
LOG("End of walk")
return END_OF_WALK;
} else {
if (current->n3 != last) {
if (userExit && userExit(this, current->n3))
return END_OF_WALK;
last = current;
current = current->n3;
LOGP
return TRIANGLE_ENTERED;
}
}
}
//currentPoint is in current Triangle -> reached end of current segment
if (currentPoint < noPoints - 1) {
// cout << "intersect none." << "\r\n";
if (userExit)
userExit(this, (Triangle*) END_OF_SEGMENT);
currentPoint++; //move to next segment
currentSegment = Segment(arPoints[currentPoint - 1],
arPoints[currentPoint]);
last = 0;
LOG("End of segment")
return END_OF_SEGMENT;
}
if (userExit)
userExit(this, (Triangle*) END_OF_WALK);
LOGP
LOG("No more segments -> end of walk")
// here no more segments are available so the walk ends
return END_OF_WALK;
}
int Triangle::triangleWalker::walk_step_sec() {
Edge edge;
return walk_step_sec_return(edge);
}
NeighborEdge Triangle::getEdge(const Edge & e) {
if (getEdge(1).equal3D(e))
return NeighborEdge(v1, v2, this, n1);
if (getEdge(2).equal3D(e))
return NeighborEdge(v2, v3, this, n2);
if (getEdge(3).equal3D(e))
return NeighborEdge(v3, v1, this, n3);
return NeighborEdge();
}
/*
Method matchNeighbors installs the neighborship
between this and all neighboring triangles in ~match~.
*/
void Triangle::matchNeighbors(std::deque<Triangle *>::iterator match,
const std::deque<Triangle *>::iterator& end) {
Edge e1 = getEdge(1);
Edge e2 = getEdge(2);
Edge e3 = getEdge(3);
while (match != end) {
if ((*match) != this && (*match) && (*match) != VORONOI_OPEN_END) {
if ((*match)->hasEdge(e1)) {
n1 = (*match);
(*match)->addNeighbor(this, false);
}
if ((*match)->hasEdge(e2)) {
n2 = (*match);
(*match)->addNeighbor(this, false);
}
if ((*match)->hasEdge(e3)) {
n3 = (*match);
(*match)->addNeighbor(this, false);
}
}
++match;
}
}
void Triangle::triangleWalker::walk_sec() {
LOG("Walking from ...")
LOG_EXP(this->currentSegment.getV1()->print())
LOG(" ...to... ")
LOG_EXP(this->currentSegment.getV2()->print())
while (this->walk_step_sec() != END_OF_WALK)
;
}
void Triangle::triangleWalker::walk_segment_sec() {
while (this->walk_step_sec() != END_OF_WALK
&& this->walk_step_sec() != END_OF_SEGMENT)
;
}
void Triangle::addReference() {
if (myPart)
myPart->addContentReference();
}
void Triangle::deleteReference() {
if (myPart)
myPart->deleteContentReference();
}
void Triangle::removeDifferentPartNeighbors() {
if (n1 && n1 != VORONOI_OPEN_END && !n1->isInSamePart(this))
removeNeighbor(n1);
if (n2 && n2 != VORONOI_OPEN_END && !n2->isInSamePart(this))
removeNeighbor(n2);
if (n3 && n3 != VORONOI_OPEN_END && !n3->isInSamePart(this))
removeNeighbor(n3);
}
void Triangle::removeNeighbor(Triangle * t) {
if (t == n1) {
n1 = 0;
}
if (t == n2) {
n2 = 0;
}
if (t == n3) {
n3 = 0;
}
}
bool Triangle::isInSamePart(const Triangle * t) const {
if (t && t != VORONOI_OPEN_END)
return t->myPart == myPart;
else
return false;
}
bool Triangle::isNeighbor(Triangle& iat) {
if (v1 == 0)
throw std::runtime_error(E_TRIANGLE_UNINITIALIZED);
Vertex *verticesMe[3] = { 0, 0, 0 };
Vertex *verticesIat[3] = { 0, 0, 0 };
SecureOperator::startSecureCalc();
//Vertex *cv[2] = { 0, 0 };
int commonVertexCnt = 0;
//int intersectCnt = 0;
if (iat.bbox().hasIntersection(this->bbox())) {
for (int i = 0; i < 3; i++) {
verticesMe[i] = const_cast<Vertex *>(getVertex(i + 1));
verticesIat[i] = const_cast<Vertex *>(iat.getVertex(i + 1));
}
//check for common vertices
for (int i2 = 0; i2 < 3; i2++) {
for (int i3 = 0; i3 < 3; i3++) {
if (verticesIat[i3] != 0 && *verticesMe[i2] == *verticesIat[i3]) {
if (commonVertexCnt < 2
&& verticesMe[i2]->equal3D(*verticesIat[i3])) {
// cv[commonVertexCnt++] = verticesMe[i2];
commonVertexCnt++;
verticesMe[i2] = 0;
verticesIat[i3] = 0;
break;
} else
return false;
}
}
}
if (commonVertexCnt == 2) //common Edge
return true;
}
return false;
}
bool Triangle::checkNeighbors() {
return (n1 && n1 != VORONOI_OPEN_END ? n1->isNeighbor(*this) : true)
&& (n2 && n2 != VORONOI_OPEN_END ? n2->isNeighbor(*this) : true)
&& (n3 && n3 != VORONOI_OPEN_END ? n3->isNeighbor(*this) : true);
}
void Triangle::addOpenEnd() {
if (!n1) {
n1 = VORONOI_OPEN_END;
return;
}
if (!n2) {
n2 = VORONOI_OPEN_END;
return;
}
if (!n3) {
n3 = VORONOI_OPEN_END;
return;
}
return; //TODO this is not a clean solution there must be an error
throw std::runtime_error(E_TRIANGLE_ADDNEIGHBOR);
}
void Triangle::addNeighbor(Triangle *t, bool bidirectional) {
if (!t)
throw std::runtime_error(
"Null pointer cannot be added as neighbor.(Triangle::addNeighbor)");
if (t == this)
throw std::runtime_error(
"Triangle cannot add itself as neighbor.(Triangle::addNeighbor)");
if (t == VORONOI_OPEN_END) {
addOpenEnd();
return;
}
if (t->hasVertices2D(*v1, *v2)) {
if (n1) {
if (n1 == VORONOI_OPEN_END) {
addOpenEnd();
} else if (n1 != t) {
throw std::runtime_error(
"The added neighbor already exists! (Triangle::addNeighbor)");
}
}
if (bidirectional && !t->hasNeighbor(this)) {
t->addNeighbor(this, false);
}
n1 = t;
return;
}
if (t->hasVertices2D(*v2, *v3)) {
if (n2) {
if (n2 == VORONOI_OPEN_END) {
addOpenEnd();
} else if (n2 != t) {
throw std::runtime_error(
"The added neighbor already exists! (Triangle::addNeighbor)");
}
}
if (bidirectional && !t->hasNeighbor(this)) {
t->addNeighbor(this, false);
}
n2 = t;
return;
}
if (t->hasVertices2D(*v3, *v1)) {
if (n3){
if (n3 == VORONOI_OPEN_END) {
addOpenEnd();
} else if (n3 != t) {
throw std::runtime_error(
"The added neighbor already exists! (Triangle::addNeighbor)");
}
}
if (bidirectional && !t->hasNeighbor(this)) {
t->addNeighbor(this, false);
}
n3 = t;
return;
}
throw std::runtime_error(E_TRIANGLE_ADDNEIGHBOR);
}
bool Triangle::hasNeighbor(Triangle * t) {
return n1 == t || n2 == t || n3 == t;
}
bool Triangle::hasVertices2D(const Vertex& iv1, const Vertex& iv2) {
if (*v1 == iv1) {
if (*v2 == iv2) {
return true;
} else if (*v3 == iv2) {
return true;
} else
return false;
}
if (*v2 == iv1) {
if (*v1 == iv2) {
return true;
} else if (*v3 == iv2) {
return true;
} else
return false;
}
if (*v3 == iv1) {
if (*v1 == iv2) {
return true;
} else if (*v2 == iv2) {
return true;
} else
return false;
}
return false;
}
Triangle* Triangle::clone() {
Triangle* nt = new Triangle(v1, v2, v3, myPart);
nt->n1 = n1;
nt->n2 = n2;
nt->n3 = n3;
return nt;
}
#ifndef UNIT_TEST
ListExpr Triangle::outTriangle() {
LOGP
if (v1 == 0 || v2 == 0 || v3 == 0)
return nl->SymbolAtom(Symbol::UNDEFINED());
return nl->ThreeElemList(v1->outVertex(), v2->outVertex(),
v3->outVertex());
}
#endif
TIN_SIZE Triangle::getSizeOnDisc() {
return sizeof(FILE_VERTEX_POINTER) * 3 + 3 * sizeof(FILE_TRIANGLE_POINTER);
}
int Triangle::getIndexInArray() const {
if (myPart)
return (this - myPart->getTriangleArrayBaseAdress());
else
return -1;
}
bool Triangle::putSecondoRepresentation(const AbstractVertexContainer * vc,
char * buff, size_t & offset) const {
FILE_VERTEX_POINTER lv1, lv2, lv3;
//first write the vertex indices to buffer
lv1 = vc->getYIndex(v1);
lv2 = vc->getYIndex(v2);
lv3 = vc->getYIndex(v3);
*((FILE_VERTEX_POINTER*) (buff + offset)) = lv1;
offset += sizeof(FILE_VERTEX_POINTER);
*((FILE_VERTEX_POINTER*) (buff + offset)) = lv2;
offset += sizeof(FILE_VERTEX_POINTER);
*((FILE_VERTEX_POINTER*) (buff + offset)) = lv3;
offset += sizeof(FILE_VERTEX_POINTER);
//then the indices of the neighbors
if (!n1)
*((FILE_TRIANGLE_POINTER*) (buff + offset)) =
FILE_TRIANGLE_POINTER_UNKNOWN;
else if (n1 == VORONOI_OPEN_END)
*((FILE_TRIANGLE_POINTER*) (buff + offset)) =
FILE_TRIANGLE_POINTER_BOUNDARY;
else {
if (n1->isInSamePart(this))
*((FILE_TRIANGLE_POINTER*) (buff + offset)) =
(FILE_TRIANGLE_POINTER) n1->getIndexInArray();
else
*((FILE_TRIANGLE_POINTER*) (buff + offset)) =
FILE_TRIANGLE_POINTER_UNKNOWN;
}
offset += sizeof(FILE_TRIANGLE_POINTER);
if (!n2)
*((FILE_TRIANGLE_POINTER*) (buff + offset)) =
FILE_TRIANGLE_POINTER_UNKNOWN;
else if (n2 == VORONOI_OPEN_END)
*((FILE_TRIANGLE_POINTER*) (buff + offset)) =
FILE_TRIANGLE_POINTER_BOUNDARY;
else {
if (n2->isInSamePart(this))
*((FILE_TRIANGLE_POINTER*) (buff + offset)) =
(FILE_TRIANGLE_POINTER) n2->getIndexInArray();
else
*((FILE_TRIANGLE_POINTER*) (buff + offset)) =
FILE_TRIANGLE_POINTER_UNKNOWN;
}
offset += sizeof(FILE_TRIANGLE_POINTER);
if (!n3)
*((FILE_TRIANGLE_POINTER*) (buff + offset)) =
FILE_TRIANGLE_POINTER_UNKNOWN;
else if (n3 == VORONOI_OPEN_END)
*((FILE_TRIANGLE_POINTER*) (buff + offset)) =
FILE_TRIANGLE_POINTER_BOUNDARY;
else {
if (n3->isInSamePart(this))
*((FILE_TRIANGLE_POINTER*) (buff + offset)) =
(FILE_TRIANGLE_POINTER) n3->getIndexInArray();
else
*((FILE_TRIANGLE_POINTER*) (buff + offset)) =
FILE_TRIANGLE_POINTER_UNKNOWN;
}
offset += sizeof(FILE_TRIANGLE_POINTER);
return true;
}
bool Triangle::putSTLbinaryRepresentation(char * buff,
uint32_t & offset) const {
//normal vector
Vertex normalv(0, 0, 0);
normalv.putSTLbinaryRepresentation(buff, offset);
//vertices
v1->putSTLbinaryRepresentation(buff, offset);
v2->putSTLbinaryRepresentation(buff, offset);
v3->putSTLbinaryRepresentation(buff, offset);
//attribute dummy
*((uint16_t*) (buff + offset)) = (uint16_t) 0;
offset += 2;
return true;
}
const Vertex* Triangle::isTriangle_sec(const Vertex* iv1,
const Vertex* iv2, const Vertex* iv3) {
if (iv1 == 0 || iv2 == 0 || iv3 == 0)
throw std::invalid_argument("isTriangle_sec called with null pointer");
//v1 and v2 etc. in the same place
if (*iv1 == *iv2 || *iv1 == *iv3 || *iv2 == *iv3) {
return 0; //always secure
}
SecureOperator::startSecureCalc();
Line l(*iv1, *iv2);
int side = l.getSide(Point(iv3));
if (!SecureOperator::isSecureResult())
return isTriangle_mp(iv1, iv2, iv3);
if (side == 0)
return 0;
if (side > 0)
return iv2;
else
return iv3;
}
const Vertex* Triangle::isTriangle_mp(const Vertex *iv1, const Vertex *iv2,
const Vertex *iv3) {
Line_mp lmp(*iv1, *iv2);
int side = lmp.getSide_mp(Point_mp(iv3));
if (side == 0)
return 0;
if (side > 0)
return iv2;
else
return iv3;
}
bool Triangle::isInside_sec(const Point_p& p) const {
if (v1 == 0)
throw std::runtime_error(E_TRIANGLE_UNINITIALIZED);
if (hasVertex(p))
return true;
Vector2D vector1, vector2, vectorTest;
//TODO possible overflow
vector1 = v3->minus2D(*v1);
vector2 = v2->minus2D(*v1);
vectorTest = p - (*v1);
SecureOperator::startSecureCalc();
if (vectorTest.isNull()) {
if (!SecureOperator::isSecureResult())
return isInside_mp(p);
return true; //on a vertex
}
if (vectorTest.isBetween(&vector1, &vector2)) {
vector1 = v1->minus2D(*v2);
vector2 = v3->minus2D(*v2);
vectorTest = p - *v2;
if (vectorTest.isNull()) {
if (!SecureOperator::isSecureResult())
return isInside_mp(p);
return true; //on a vertex
}
if (vectorTest.isBetween(&vector1, &vector2)) {
if (!SecureOperator::isSecureResult())
return isInside_mp(p);
return true; // inside or on an edge
} else {
if (!SecureOperator::isSecureResult())
return isInside_mp(p);
return false;
}
} else {
if (!SecureOperator::isSecureResult())
return isInside_mp(p);
return false;
}
}
bool Triangle::isInside_mp(const Point_p& p) const {
Vector2D_mp vector1, vector2, vectorTest;
//TODO possible overflow
vector1 = v3->minus2D_mp(*v1);
vector2 = v2->minus2D_mp(*v1);
vectorTest = p.minus2D_mp(*v1);
if (vectorTest.isNull())
return true; //on a vertex
if (vectorTest.isBetween(&vector1, &vector2)) {
vector1 = v1->minus2D_mp(*v2);
vector2 = v3->minus2D_mp(*v2);
vectorTest = p.minus2D_mp(*v2);
if (vectorTest.isNull())
return true; //on a vertex
if (vectorTest.isBetween(&vector1, &vector2)) {
return true; // inside or on an edge
} else
return false;
} else
return false;
}
bool Triangle::isEqual(Vertex& iv1, Vertex& iv2, Vertex& iv3) {
if ((v1->equal3D(iv1) || v1->equal3D(iv2) || v1->equal3D(iv3))
&& (v2->equal3D(iv1) || v2->equal3D(iv2) || v2->equal3D(iv3))
&& (v3->equal3D(iv1) || v3->equal3D(iv2) || v3->equal3D(iv3)))
return true;
return false;
}
bool Triangle::operator==(const Triangle & t) const {
if ((v1->equal3D(*t.v1) || v1->equal3D(*t.v2) || v1->equal3D(*t.v3))
&& (v2->equal3D(*t.v1) || v2->equal3D(*t.v2) || v2->equal3D(*t.v3))
&& (v3->equal3D(*t.v1) || v3->equal3D(*t.v2) || v3->equal3D(*t.v3)))
return true;
return false;
}
void Triangle::print(std::ostream & out) const {
if (v1 == 0)
throw std::runtime_error(E_TRIANGLE_UNINITIALIZED);
out << "\n" << "Triangle in Part: ";
if (myPart)
out << myPart << " index in array: " << getIndexInArray();
v1->print(out);
v2->print(out);
v3->print(out);
if (n1 && n1 != VORONOI_OPEN_END)
n1->printNeighbor(out);
if (n1 == VORONOI_OPEN_END)
out << "\n" << "OPEN_END", getEdge(1).getV1()->print(out),
getEdge(1).getV2()->print(
out);
if (n2 && n2 != VORONOI_OPEN_END)
n2->printNeighbor(out);
if (n2 == VORONOI_OPEN_END)
out << "\n" << "OPEN_END", getEdge(2).getV1()->print(out),
getEdge(2).getV2()->print(
out);
;
if (n3 && n3 != VORONOI_OPEN_END)
n3->printNeighbor(out);
if (n3 == VORONOI_OPEN_END)
out << "\n" << "OPEN_END", getEdge(3).getV1()->print(out),
getEdge(3).getV2()->print(
out);
;
}
void Triangle::printNeighbor(std::ostream & out) const {
if (v1 == 0)
throw std::runtime_error(E_TRIANGLE_UNINITIALIZED);
out << "\n" << "Neighbor: ";
v1->print(out);
v2->print(out);
v3->print(out);
}
VERTEX_Z Triangle::getValue(const Point_p& p) const {
if (v1 == 0)
throw std::runtime_error(E_TRIANGLE_UNINITIALIZED);
LOGP
Vector3D vc1 = v2->minus3D(*v1);
Vector3D vc2 = v3->minus3D(*v1);
VERTEX_COORDINATE xp, yp, x_0, y_0, x_1, y_1, x_2, y_2, f1, f2;
x_0 = v1->getX();
y_0 = v1->getY();
LOG(x_0)
LOG(y_0)
xp = p.x - x_0;
yp = p.y - y_0;
LOG(xp)
LOG(yp)
x_1 = vc1.getDx().l;
x_2 = vc2.getDx().l;
y_1 = vc1.getDy().l;
y_2 = vc2.getDy().l;
LOG(x_1)
LOG(y_1)
LOG(x_2)
LOG(y_2)
if (x_1 == 0) {
f2 = xp / x_2;
f1 = (yp - y_2 * f2) / y_1;
} else if (y_1 == 0) {
f2 = yp / y_2;
f1 = (xp - x_2 * f2) / x_1;
} else {
VERTEX_COORDINATE d = x_1 / y_1;
f2 = (xp - (yp * d)) / (x_2 - y_2 * d);
f1 = (xp - (x_2 * f2)) / x_1;
}
LOG(f1)
LOG(f2)
VERTEX_COORDINATE z = f1 * vc1.getDz().l + f2 * vc2.getDz().l
+ v1->getZ();
LOG("Value calculated:")
LOG(z)
return z;
}
const Vertex* Triangle::getVertex(const int n) const {
switch (n) {
case 1:
return v1;
break;
case 2:
return v2;
break;
case 3:
return v3;
break;
default:
throw std::invalid_argument(E_TRIANGLE_GETVERTEX);
}
}
bool Triangle::isCompatibleWith_sec(const Triangle& iat) const {
if (v1 == 0)
throw std::runtime_error(E_TRIANGLE_UNINITIALIZED);
Vertex *verticesMe[3] = { 0, 0, 0 };
Vertex *verticesIat[3] = { 0, 0, 0 };
SecureOperator::startSecureCalc();
Vertex *cv[2] = { 0, 0 };
int commonVertexCnt = 0;
if (iat.bbox().hasIntersection(this->bbox())) {
for (int i = 0; i < 3; i++) {
verticesMe[i] = const_cast<Vertex *>(getVertex(i + 1));
verticesIat[i] = const_cast<Vertex *>(iat.getVertex(i + 1));
}
//check for common vertices
for (int i2 = 0; i2 < 3; i2++) {
for (int i3 = 0; i3 < 3; i3++) {
if (verticesIat[i3] != 0 && *verticesMe[i2] == *verticesIat[i3]) {
if (commonVertexCnt < 2
&& verticesMe[i2]->equal3D(*verticesIat[i3])) {
cv[commonVertexCnt++] = verticesMe[i2];
verticesMe[i2] = 0;
verticesIat[i3] = 0;
break;
} else
return false;
}
}
}
if (commonVertexCnt == 2) //common Edge
{
Point p1(cv[0]);
Point checkpiat;
Point checkpme;
for (int i4 = 0; i4 < 3; i4++) {
if (verticesIat[i4] != 0)
checkpiat = Point(verticesIat[i4]);
if (verticesMe[i4] != 0)
checkpme = Point(verticesMe[i4]);
}
Edge commonEdge(cv[0], cv[1]);
Line commonEdgeLine(commonEdge.getVector2D(), p1);
int sideiat = commonEdgeLine.getSide(checkpiat);
if (!SecureOperator::isSecureResult()) {
Vector2D_mp vmp = commonEdge.getVector2D_mp();
Line_mp common_mp(vmp, (Point_mp) p1);
sideiat = common_mp.getSide_mp((Point_mp) checkpiat);
}
int sideme = commonEdgeLine.getSide(checkpme);
if (!SecureOperator::isSecureResult()) {
Vector2D_mp vmp = commonEdge.getVector2D_mp();
Line_mp common_mp(vmp, (Point_mp) p1);
sideme = common_mp.getSide_mp((Point_mp) checkpme);
}
if (sideme != sideiat) {
return true;
} else {
return false;
}
} else if (commonVertexCnt == 1) //common Vertex
{
int oppositeVertexCnt = 0;
int insideVertexCnt = 0;
Vertex * oVertices[2];
Vertex * verticesForInsideCheck[2];
for (int i4 = 0; i4 < 3; i4++) {
if (verticesIat[i4] != 0)
verticesForInsideCheck[insideVertexCnt++] = verticesIat[i4];
if (verticesMe[i4] != 0)
oVertices[oppositeVertexCnt++] = verticesMe[i4];
}
Edge oEdge(oVertices[0], oVertices[1]);
for (int i5 = 1; i5 < 4; i5++) {
Edge eiat = iat.getEdge(i5);
if (oEdge.intersects_sec(&eiat)) {
return false;
}
}
//still one could be contained in the other
Point_p checkinsideme(oEdge.getV1());
Point_p checkinsideiat0(verticesForInsideCheck[0]);
Point_p checkinsideiat1(verticesForInsideCheck[1]);
if (iat.isInside_sec(checkinsideme)
|| this->isInside_sec(checkinsideiat0)
|| this->isInside_sec(checkinsideiat1))
return false;
return true;
}
//nothing in common
Edge e1 = iat.getEdge(1);
Edge e2 = iat.getEdge(2);
Edge e3 = iat.getEdge(3);
for (int i6 = 1; i6 < 4; i6++) {
//TODO check again
if (getEdge(i6).intersects_sec(&e1))
return false;
if (getEdge(i6).intersects_sec(&e2))
return false;
if (getEdge(i6).intersects_sec(&e3))
return false;
}
//still possible that one is contained in the other
Point_p p(iat.v1->getX(), iat.v1->getY());
Point_p p2(v1->getX(), v1->getY());
if (isInside_sec(p) || iat.isInside_sec(p2))
return false;
return true;
} else
return true;
}
Rectangle Triangle::bbox() const {
if (v1 == 0)
throw std::runtime_error(E_TRIANGLE_UNINITIALIZED);
VERTEX_COORDINATE x2 = std::max(v1->getX(), v2->getX());
x2 = std::max(x2, v3->getX());
VERTEX_COORDINATE y2 = std::max(v1->getY(), v2->getY());
y2 = std::max(y2, v3->getY());
VERTEX_COORDINATE x1 = std::min(v1->getX(), v2->getX());
x1 = std::min(x1, v3->getX());
VERTEX_COORDINATE y1 = std::min(v1->getY(), v2->getY());
y1 = std::min(y1, v3->getY());
return Rectangle(x1, y1, x2, y2);
}
Edge Triangle::getEdge(const int n) const {
if (v1 == 0)
throw std::runtime_error(E_TRIANGLE_UNINITIALIZED);
switch (n) {
case 1:
return Edge(v1, v2);
case 2:
return Edge(v2, v3);
case 3:
return Edge(v3, v1);
default:
throw std::invalid_argument(E_TRIANGLE_GETEDGE);
}
}
}