Files
vroni/vroni_added_functions.cpp
T
SaraP 5f930bac07 Vroni :
- corretta gestione del bisettore nel caso in cui i siti non siano definiti.
2024-07-09 13:15:52 +02:00

553 lines
18 KiB
C++

/*****************************************************************************/
/* */
/* Funzioni aggiunte per integrare vroni con le nostre librerie */
/* Le funzioni modificate nel codice vengono individuate con il */
/* commento MODIF */
/*****************************************************************************/
#include "vroni_object.h"
#include "offset.h"
#include <fstream>
//----------------------------------------------------------------------------
void
vroniObject::GetPointFromCoord( coord ptCoord, double p[3])
{
// trasformo vroni::coord in un array compatibile con il nostro Point3d
p[0] = ptCoord.x ;
p[1] = ptCoord.y ;
p[2] = 0.0 ;
// scalo
if ( unscaleXYZ) {
p[0] = UnscaleX( p[0]) ;
p[1] = UnscaleY( p[1]) ;
}
}
//----------------------------------------------------------------------------
int
vroniObject::GetOffsetCurveCount( int i)
{
return GetOffsetListEnd(i) - GetOffsetListStart(i) + 1 ;
}
//----------------------------------------------------------------------------
vr_bool
vroniObject::GetOffsetCurve( int nOffs, int nCrv, int& nType, double ptS[3], double ptE[3], double ptC[3],
int& nOrigLoop, int& nOrigCrv, int& nOrigPnt)
{
// sito originale
nOrigLoop = -1 ;
nOrigCrv = -1 ;
nOrigPnt = -1 ;
if ( nOffs > num_offset_list)
return false ;
int k = GetOffsetListStart( nOffs) + nCrv ;
if ( k > GetOffsetListEnd( nOffs))
return false ;
assert( InOffsetData(k)) ;
// recupero il punto iniziale
coord start = GetOffsetPntCoords( k) ;
GetPointFromCoord( start, ptS) ;
// recupero punto finale
int m = k + 1 ;
if ( m > GetOffsetListEnd( nOffs))
m = GetOffsetListStart( nOffs) ;
coord end = GetOffsetPntCoords( m) ;
GetPointFromCoord( end, ptE) ;
if ( GetOffsetEleType( k) == PNT) {
int c = GetOffsetEleSite( k) ;
assert( InPntsList( c)) ;
coord center = GetPntCoords( c) ;
vr_bool ori = false ;
if ( ScrutinizeArc( start, end, center, &ori, ZERO_IO, HasIncidentSite( c))) {
nType = CW ;
// recupero le coordinate del centro
GetPointFromCoord( center, ptC) ;
}
else
nType = SEG ;
// recupero il sito
nOrigLoop = pnts[c].ext_appl.first ;
nOrigPnt = pnts[c].ext_appl.second ;
}
else if ( GetOffsetEleType( k) == SEG) {
nType = SEG ;
// recupero il sito
int c = GetOffsetEleSite( k) ;
nOrigLoop = segs[c].ext_appl.first ;
nOrigCrv = segs[c].ext_appl.second ;
}
else if ( GetOffsetEleType( k) == CCW || GetOffsetEleType( k) == CW) {
int c = GetOffsetEleSite( k) ;
assert( InArcsList( c)) ;
coord center = GetArcCenter( c) ;
vr_bool ori = ( GetOffsetEleType( k) == CCW ? true : false) ;
if ( ScrutinizeArc( start, end, center, &ori, ZERO_IO, true)) {
nType = ori ? CCW : CW ;
// recupero le coordinate del centro
GetPointFromCoord( center, ptC) ;
}
else
nType = SEG ;
// recupero il sito
nOrigLoop = arcs[c].ext_appl.first ;
nOrigCrv = arcs[c].ext_appl.second ;
}
return true ;
}
//----------------------------------------------------------------------------
void vroniObject::ResetVoronoiDiagram(void)
{
/* */
/* reset global and static data within individual files */
/* */
#ifdef GRAPHICS
if (graphics) {
#if defined (OGL_GRAPHICS)
ResetGraphicsData();
#else
ExtApplResetGraphicsData;
#endif
ResetBufferData();
}
#endif
// sistemo i 4 punti estremi
SetXCoord( 0, -DBL_MAX) ;
SetYCoord( 0, -DBL_MAX) ;
SetXCoord( 1, -DBL_MAX) ;
SetYCoord( 1, DBL_MAX) ;
int i = num_pnts - 2 ;
SetXCoord( i, DBL_MAX) ;
SetYCoord( i, -DBL_MAX) ;
i = num_pnts - 1 ;
SetXCoord( i, DBL_MAX) ;
SetYCoord( i, DBL_MAX) ;
ResetVDData();
ResetVDConstructionData();
ResetEdgeData();
ResetOffsetData();
#ifdef MAT
ResetWMATStatus();
#endif
ResetIntersectionData();
ResetIntersectionStatus();
ResetCleanStatus();
isolated_pnts = false;
/* */
/* let the user call some application-specific function */
/* */
ExtApplFuncReset;
return;
}
//----------------------------------------------------------------------------
BisectorType
vroniObject::GetBisectorType( int i)
{
int lft, rgt ;
t_site t_lft, t_rgt ;
GetLftSiteData(i, &lft, &t_lft) ;
GetRgtSiteData(i, &rgt, &t_rgt) ;
BisectorType conic = NONE ;
if ( t_lft == UNKNOWN || t_rgt == UNKNOWN || lft == NIL || rgt == NIL)
return NONE ;
// Questo caso nel calcolo dei bisettori viene identificato come HYPERBOLA che degenera come linea. Visto che
// nel calcolo delle approssimazioni viene identificato come linea indico il tipo direttamente come LINE
if (( t_lft == PNT) && ( t_rgt == PNT))
return LINE ;
else if (( t_lft == PNT) || ( t_lft == ARC)) {
if (( t_rgt == PNT) || ( t_rgt == ARC)) {
if ( t_lft == PNT) {
assert( t_rgt == ARC) ;
assert( InArcsList( rgt)) ;
if ( IsArcStartPnt( rgt, lft) || IsArcEndPnt( rgt, lft))
return LINE ;
}
if ( t_rgt == PNT) {
assert( t_lft == ARC) ;
assert( InArcsList( lft)) ;
if ( IsArcStartPnt( lft, rgt) || IsArcEndPnt( lft, rgt))
return LINE ;
}
// verifico se degenere
e_formula coeff ;
if ( ! ComputeHyperbolaEllipseData( i, &coeff)) {
double r1 = t_lft == PNT ? 0.0 : GetArcRadius( lft) ;
coord p1 = t_lft == PNT ? GetPntCoords( lft) : GetArcCenter(lft) ;
double r2 = t_rgt == PNT ? 0.0 : GetArcRadius( rgt) ;
coord p2 = t_rgt == PNT ? GetPntCoords( rgt) : GetArcCenter(rgt) ;
double dx = p2.x - p1.x ;
double dy = p2.y - p1.y ;
double dist = dx * dx + dy * dy ;
if ( eq( dist, ZERO_MAX)) {
dist = r1 - r2;
if ( eq( dist, ZERO_MAX))
return LINE ;
else
// degenerate elliptic edge
return DEGENERATE_HYPERELL ;
}
else
return LINE ;
}
return HYPERELL ;
}
else {
assert( t_rgt == SEG);
assert( InSegsList( rgt));
if (( t_lft == PNT) &&
( IsSegStartPnt( rgt, lft) || IsSegEndPnt( rgt, lft)))
return LINE ;
else {
// verifico se degenere
e_formula coeff ;
if ( ! ComputeParabolaData( i, &coeff))
return LINE ;
return PARABOLA ;
}
}
}
else {
if (( t_rgt == PNT) || ( t_rgt == ARC)) {
assert( t_lft == SEG) ;
assert( InSegsList( lft)) ;
if (( t_rgt == PNT) &&
( IsSegStartPnt( lft, rgt) || IsSegEndPnt( lft, rgt)))
return LINE ;
else {
// verifico se degenere
e_formula coeff ;
if ( ! ComputeParabolaData( i, &coeff))
return LINE ;
return PARABOLA ;
}
}
else {
return LINE ;
}
}
return conic ;
}
//----------------------------------------------------------------------------
vr_bool
vroniObject::GetBisectorParams( int nEdge, double& dParS, double& dParE)
{
GetEdgeParam( nEdge, &dParS, &dParE) ;
dParS = UnscaleV( dParS) ;
dParE = UnscaleV( dParE) ;
return true ;
}
//----------------------------------------------------------------------------
vr_bool
vroniObject::GetApproxedBisectorParams( int nEdge, double& dParS, double& dParE)
{
// restituisce i parametri del bisettore approssimato, che potrebbe essere invertito
// rispetto al bisettore originale salvato tra gli edges di vroni
// se il bisettore non è quello approssimato nel buffer devo calcolarlo
if ( nEdge != m_nBufferedVDEdge) {
ResetVDBuffer() ;
AddVDEdgeToBuffer( nEdge) ;
m_nBufferedVDEdge = nEdge ;
}
// recupero i parametri dagli estremi
dParS = UnscaleV( vde_buf[0].dPar1) ;
dParE = UnscaleV( vde_buf[num_vde_buf-1].dPar2) ;
return true ;
}
//----------------------------------------------------------------------------
int
vroniObject::GetApproxedBisectorPointsNbr( int nEdge)
{
// se il bisettore non è quello approssimato nel buffer devo calcolarlo
if ( nEdge != m_nBufferedVDEdge) {
ResetVDBuffer() ;
AddVDEdgeToBuffer( nEdge) ;
m_nBufferedVDEdge = nEdge ;
}
return num_vde_buf + 1;
}
//----------------------------------------------------------------------------
vr_bool
vroniObject::GetApproxedBisectorPoint( int nEdge, int nIdx, double pt[3], double& dPar)
{
// se il bisettore non è quello approssimato nel buffer devo calcolarlo
if ( nEdge != m_nBufferedVDEdge) {
ResetVDBuffer() ;
AddVDEdgeToBuffer( nEdge) ;
m_nBufferedVDEdge = nEdge ;
}
// verifico validità dell'indice passato
int nPoints = GetApproxedBisectorPointsNbr( nEdge) ;
if ( nIdx < 0 || nIdx >= nPoints)
return false ;
if ( nIdx == 0) {
GetPointFromCoord( vde_buf[0].p1, pt) ;
dPar = UnscaleV( vde_buf[0].dPar1) ;
}
else {
GetPointFromCoord( vde_buf[nIdx-1].p2, pt) ;
dPar = UnscaleV( vde_buf[nIdx-1].dPar2) ;
}
return true ;
}
//----------------------------------------------------------------------------
vr_bool
vroniObject::GetLinearBisectorData( int nEdge, double ptS[3], double ptE[3], double& dParS, double& dParE)
{
// verifico sia effettivamente bisettore lineare
if ( GetBisectorType( nEdge) != BisectorType::LINE)
return false ;
// calcolo i parametri
GetEdgeParam( nEdge, &dParS, &dParE) ;
dParS = UnscaleV( dParS) ;
dParE = UnscaleV( dParE) ;
// calcolo gli estremi
coord coordS = GetNodeCoord( edges[nEdge].n1) ;
GetPointFromCoord( coordS, ptS) ;
coord coordE = GetNodeCoord( edges[nEdge].n2) ;
GetPointFromCoord( coordE, ptE) ;
return true ;
}
//----------------------------------------------------------------------------
vr_bool
vroniObject::GetDegenerateHyperEllipticBisectorData( int nEdge, double ptS[3], double ptE[3], double ptC[3], double& dParS, double& dParE)
{
// verifico sia effettivamente del tipo corretto
if ( GetBisectorType( nEdge) != BisectorType::DEGENERATE_HYPERELL)
return false ;
// calcolo il centro
int i1, i2 ;
t_site ltype, rtype ;
GetLftSiteData( nEdge, &i1, &ltype) ;
GetRgtSiteData( nEdge, &i2, &rtype) ;
coord p1 = ( ltype == PNT ? GetPntCoords( i1) : GetArcCenter( i1)) ;
coord p2 = ( rtype == PNT ? GetPntCoords( i2) : GetArcCenter( i2)) ;
coord p = MidPoint( p1, p2) ;
GetPointFromCoord( p, ptC) ;
// calcolo gli estremi
coord coordS = GetNodeCoord( edges[nEdge].n1) ;
GetPointFromCoord( coordS, ptS) ;
coord coordE = GetNodeCoord( edges[nEdge].n2) ;
GetPointFromCoord( coordE, ptE) ;
// calcolo i parametri
GetEdgeParam( nEdge, &dParS, &dParE) ;
dParS = UnscaleV( dParS) ;
dParE = UnscaleV( dParE) ;
return true ;
}
//----------------------------------------------------------------------------
vr_bool
vroniObject::IsRelatedEdge( int nEdge, int nOrigSite, bool bLeft)
{
// verifico se l'edge è relativo alla curva nOrigSite
int nSiteL, nSiteR ;
t_site nSiteTypeL, nSiteTypeR ;
GetLftSiteData( nEdge, &nSiteL, &nSiteTypeL) ;
GetRgtSiteData( nEdge, &nSiteR, &nSiteTypeR) ;
if ( nSiteTypeL == UNKNOWN || nSiteTypeR == UNKNOWN || nSiteL == NIL || nSiteR == NIL)
return false ;
if ( ( nSiteTypeL == PNT && pnts[nSiteL].ext_appl.first == nOrigSite) ||
( nSiteTypeL == SEG && segs[nSiteL].ext_appl.first == nOrigSite) ||
( nSiteTypeL == ARC && arcs[nSiteL].ext_appl.first == nOrigSite) ||
( nSiteTypeR == PNT && pnts[nSiteR].ext_appl.first == nOrigSite) ||
( nSiteTypeR == SEG && segs[nSiteR].ext_appl.first == nOrigSite) ||
( nSiteTypeR == ARC && arcs[nSiteR].ext_appl.first == nOrigSite)) {
// verifico se è necessario calcolare active edges
if ( num_active_edges == 0) {
int nTmp ;
InitializeEdgeData( false, bLeft, false, &nTmp) ;
}
// verifico è active ( e quindi dal lato richiesto di nOrigSite)
for ( int j = 0 ; j < num_active_edges ; j ++)
if ( active_edges[j] == nEdge)
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
vr_bool
vroniObject::IsWMATEdge( int nEdge)
{
return edges[nEdge].w_mat.in_w_mat ;
}
//----------------------------------------------------------------------------
const char*
vroniObject::GetExceptionMessage()
{
try {
throw ;
}
catch ( const std::runtime_error& VRONIerror) {
return VRONIerror.what() ;
}
catch (const std::exception& VRONIerror) {
return VRONIerror.what() ;
}
catch ( ... ) {
return "VRONI error: unknown type of error" ;
}
return "" ;
}
//----------------------------------------------------------------------------
void
vroniObject::MyWriteVoronoiDiagram()
{
std::ofstream myfile ;
myfile.open( "C:\\EgtData\\Varie\\Test.lua") ; // percorso del file
// versione per scrivere i dati del diagramma su un file di testo
// myfile << " EDGES DATA" << std::endl ;
// for ( int i = 0 ; i < num_edges ; i ++) {
// myfile << "Voronoi edge " << i << std::endl ;
// myfile << " n1 = " << edges[i].n1 << std::endl ;
// myfile << " n2 = " << edges[i].n2 << std::endl ;
// myfile << " lft = " << edges[i].lft << std::endl ;
// myfile << " rgt = " << edges[i].rgt << std::endl ;
// myfile << " lft type = " << edges[i].ltype << std::endl ;
// myfile << " rgt type = " << edges[i].rtype << std::endl ;
// myfile << " s_ccw = " << edges[i].s_ccw << std::endl ;
// myfile << " s_cw = " << edges[i].s_cw << std::endl ;
// myfile << " e_ccw = " << edges[i].e_ccw << std::endl ;
// myfile << " e_cw = " << edges[i].e_cw << std::endl ;
// if (IsWmatEdge(i)) {
// myfile << " wmat =" << edges[i].w_mat.in_w_mat << std::endl ;
// // solo con Wmat
// // myfile << " wmat rmin = " << UnscaleV( edges[i].w_mat.r_min) ;
// // myfile << " wmat rmax = " << UnscaleV( edges[i].w_mat.r_max) ;
// }
// myfile.flush() ;
// }
//
// myfile << std::endl << std::endl ;
// myfile << "NODES DATA" << std::endl ;
// for ( int i = 0 ; i < num_nodes ; i ++) {
// myfile << "Voronoi node " << i << std::endl ;
// auto p = GetNodeCoord(i) ;
// myfile << " pt = " << UnscaleX(p.x) << ", " << UnscaleY(p.y) << std::endl ;
// myfile << " r2 = " << UnscaleV( nodes[i].r2) << std::endl ;
// myfile << " deg2 = " << nodes[i].deg2 << std::endl ;
// myfile << " edge = " << nodes[i].edge << std::endl ;
// myfile << " site = " << nodes[i].site << std::endl ;
// }
// versione per scrivere un file lua
// N.B. i lati vengono rappresentati tutti con delle linee solo per avere le relazioni tra i nodi, non sono
// rappresentativi dei veri lati del diagramma (parabole, ellissi, ...)
//
myfile << "-- Nodes " << num_nodes << std::endl ;
myfile << "-- Edges " << num_edges << std::endl ;
myfile << "local nId" << std::endl ;
myfile << "local nGrp1 = EgtGroup( GDB_ID.ROOT)" << std::endl ;
myfile << "local nGrp2 = EgtGroup( GDB_ID.ROOT)" << std::endl ;
for ( int i = 0 ; i < num_nodes ; i ++) {
double x1 = UnscaleX( nodes[i].p.x) ;
double y1 = UnscaleY( nodes[i].p.y) ;
myfile << "nId = EgtPoint( nGrp1, Point3d( " << x1 << ", " << y1 << ", 0))" << std::endl ;
myfile << "EgtSetName( nId or GDB_ID.NULL, 'Node" << i << "')" << std::endl ;
myfile.flush() ;
}
for ( int i = 0 ; i < num_edges ; i ++) {
double x1 = UnscaleX( nodes[edges[i].n1].p.x) ;
double y1 = UnscaleY( nodes[edges[i].n1].p.y) ;
double x2 = UnscaleX( nodes[edges[i].n2].p.x) ;
double y2 = UnscaleY( nodes[edges[i].n2].p.y) ;
myfile << "nId = EgtLine( nGrp2, Point3d( " << x1 << ", " << y1 << ", 0), Point3d( " << x2 << ", " << y2 << ", 0))" << std::endl ;
myfile << "EgtSetName( nId or GDB_ID.NULL, 'Edge" << i << "')" << std::endl ;
myfile.flush() ;
}
myfile.close() ;
return ;
}
//----------------------------------------------------------------------------
void
vroniObject::MyFreeVDConstructionData()
{
FreeVDConstructionData() ;
#ifdef RANDOM
m_rnd_sites.clear() ;
m_max_num_rnd_sites = 0;
m_num_rnd_sites = 0;
#endif
}
//----------------------------------------------------------------------------
void
vroniObject::apiFreeOffsetData(void)
{
// libera la memoria utilizzata ( ResetOffsetData azzera i contatori ma non dealloca memoria)
FreeOffsetData() ;
// libero i dati degli edge utilizzati per il calcolo dell'offset
FreeEdgeData() ;
}
//----------------------------------------------------------------------------
void
vroniObject::apiFreeBisectorBuffer(void)
{
// libera la memoria utilizzata per approssimare il bisettore
FreeDrawingBuffer() ;
// libero i dati degli edge utilizzati per i calcoli
FreeEdgeData() ;
}