3
* $Id: wpoligono.cpp 3535 2011-03-18 17:57:05Z carlos $
6
* Copyright 2008-10 MetaEmotion S.L. All rights reserved.
7
* http://ginkgo-cadx.com
9
* This file is licensed under LGPL v3 license.
10
* See License.txt for details
14
//#define _GINKGO_TRACE
15
#include <wx/xml/xml.h>
16
#include <api/globals.h>
17
#include <api/icontexto.h>
18
#include "wpoligono.h"
19
#include <api/iwidgetsrenderer.h>
20
#include <api/ievento.h>
21
#include <eventos/eventosginkgo.h>
22
#include "main/managers/widgetsmanager.h"
23
#include <api/internacionalizacion.h>
27
#include <api/westilo.h>
30
//region "Implementacion de WPoligonoBuilder"
32
GNC::GCS::Widgets::WPoligonoBuilder::WPoligonoBuilder(ModoPoligono modo, GNC::GCS::IWidgetsManager* pManager, GNC::GCS::Widgets::Observadores::IObservadorPoligono* pObservador) : GNC::GCS::Widgets::IWidgetBuilder(pManager), GNC::GCS::Widgets::Notificadores::INotificadorPoligono(pObservador)
36
m_Estado = WBS_Ninguno;
38
m_pPoligonoCreado = NULL;
42
GNC::GCS::Widgets::WPoligonoBuilder::~WPoligonoBuilder()
45
if (m_Modo == MP_Lazo) {
46
if (m_pPoligonoCreado) {
47
NotificarDestruccion(m_pPoligonoCreado);
48
m_pManager->EliminarWidget(m_pPoligonoCreado, false);
49
m_pPoligonoCreado = NULL;
54
void GNC::GCS::Widgets::WPoligonoBuilder::OnMouseEvents(GNC::GCS::Eventos::EventoRaton& evento)
59
if (m_MouseDown && evento.ButtonUp(GNC::GCS::Eventos::EventoRaton::EB_IZQUIERDO)) {
61
if (m_Estado != WBS_Creando) {
62
m_Estado = WBS_Ninguno;
65
m_Estado = WBS_Ninguno;
66
m_PosCursor= evento.iP;
68
if (m_Modo == MP_Lazo && m_pPoligonoCreado != NULL) {
69
NotificarDestruccion(m_pPoligonoCreado);
70
m_pManager->EliminarWidget(m_pPoligonoCreado, false);
71
m_pPoligonoCreado = NULL;
73
if(m_Vertices.size()>2){
74
m_pPoligonoCreado = new WPoligono(m_Modo, m_pManager, evento.c->GetRenderer()->GetVID(), m_Vertices, m_RadioNodo, "PolĆgono");
75
m_pManager->InsertarWidget(m_pPoligonoCreado);
76
NotificarCreacion(m_pPoligonoCreado);
77
m_pManager->LanzarEventoCreacion(m_pPoligonoCreado);
81
m_pManager->Modificado();
84
else if (evento.ButtonDown(GNC::GCS::Eventos::EventoRaton::EB_IZQUIERDO)) {
85
if (m_Estado != WBS_Ninguno) {
90
if (m_Modo == MP_Lazo && m_pPoligonoCreado != NULL) {
91
NotificarDestruccion(m_pPoligonoCreado);
92
m_pManager->EliminarWidget(m_pPoligonoCreado, false);
93
m_pPoligonoCreado = NULL;
96
//aviso que han soltado
97
m_pManager->Modificado();
98
m_Estado = WBS_Creando;
102
else if (evento.Dragging() && m_MouseDown) {
104
if (m_Estado != WBS_Creando) {
108
GTRACE(" ---->"<<(evento.iP - m_PosCursor).Norma2Cuadrado()<<" minimo= " << m_DistanciaMinimaCuadrado);
110
if (!m_Vertices.empty() && ((evento.iP - m_PosCursor)/evento.c->RelacionImagenPantalla()).Norma2Cuadrado() < m_DistanciaMinimaCuadrado) {
113
m_PosCursor = evento.iP;
114
m_Vertices.push_back(m_PosCursor);
115
m_pManager->Modificado();
118
else if( evento.Moving() ){
119
m_PosCursor= evento.iP;
120
m_Estado = WBS_Ninguno;
125
void GNC::GCS::Widgets::WPoligonoBuilder::OnKeyEvents(GNC::GCS::Eventos::EventoTeclado& /*evento*/)
127
GTRACE("GNC::GCS::Widgets::WPoligonoBuilder::OnKeyEvents(wxKeyEvent&)");
130
void GNC::GCS::Widgets::WPoligonoBuilder::Render(GNC::GCS::Contexto3D* /*c*/)
133
if (m_Estado != WBS_Creando) {
137
glLineWidth(WIDGET_GROSOR_LINEA);
138
wColorNormal.Aplicar();
140
VerticesPoligono::iterator prev = m_Vertices.begin();
141
if (prev != m_Vertices.end()) {
142
VerticesPoligono::iterator curr = prev;
144
for (; curr != m_Vertices.end(); curr++) {
146
glVertex2d((*prev).x, (*prev).y);
147
glVertex2d((*curr).x, (*curr).y);
154
if (m_Vertices.size() > 2) {
155
glEnable(GL_LINE_STIPPLE);
156
glColor4f(0.7f, 0.7f, 0.0f, 1.0);
157
glLineStipple(3, 0xAAAA);
159
glVertex2d(m_Vertices.front().x, m_Vertices.front().y);
160
glVertex2d(m_Vertices.back().x, m_Vertices.back().y);
162
glDisable(GL_LINE_STIPPLE);
166
glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
167
glPointSize(m_RadioNodo);
169
for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); it++) {
170
glVertex2d((*it).x, (*it).y);
176
GNC::GCS::Widgets::TipoCursor GNC::GCS::Widgets::WPoligonoBuilder::GetCursor()
178
return GNC::GCS::Widgets::CUR_CREAR_POLIGONO;
183
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
185
//region "Constructor y destructor"
187
GNC::GCS::Widgets::WPoligono::WPoligono(GNC::GCS::Widgets::ModoPoligono modo, IWidgetsManager* pManager, unsigned int vid, VerticesPoligono& vertices, float radioNodo, const char* nombre) : GNC::GCS::Widgets::IWidget(pManager, vid, nombre), GNC::GCS::Widgets::IWidgetSerializable()
189
m_Vertices = vertices;
191
m_RadioNodo = radioNodo;
195
m_PosCursor = m_Centro;
198
GNC::GCS::Widgets::WPoligono::~WPoligono()
200
if(m_Modo != GNC::GCS::Widgets::MP_Lazo){
201
LanzarEventoDestruccion();
207
//region "Serializado y desserializado"
208
GNC::GCS::Widgets::WPoligono::WPoligono(IWidgetsManager* pManager, long vid, wxXmlNode* nodo, float radioNodo): GNC::GCS::Widgets::IWidget(pManager, vid, "PolĆgono"), GNC::GCS::Widgets::IWidgetSerializable(nodo)
210
if(nodo->GetName() != wxT("poligono_widget")){
211
std::cerr<< "Ha ocurrido un error al desserializar el widget poligono"<<std::endl;
214
if(nodo->GetPropVal(wxT("mode"),wxT("normal")) == wxT("lazo")){
220
wxXmlNode *child = nodo->GetChildren();
221
GNC::GCS::Nodo nodoTmp;
223
nodoTmp = GNC::GCS::Nodo::Deserializar(child);
224
GNC::GCS::Vector v(nodoTmp);
225
m_Vertices.push_back(v);
226
child = child->GetNext();
229
m_RadioNodo = radioNodo;
232
m_PosCursor = m_Centro;
235
wxXmlNode* GNC::GCS::Widgets::WPoligono::Serializar(const std::string& nombreMedico)
237
wxXmlNode* resultado = new wxXmlNode(NULL,wxXML_ELEMENT_NODE,wxT("poligono_widget"));
238
if(m_Modo == MP_Lazo){
239
resultado->AddProperty(wxT("mode"),wxT("lazo"));
241
resultado->AddProperty(wxT("mode"),wxT("normal"));
245
for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); it++) {
246
wxXmlNode* nodo = new wxXmlNode(NULL,wxXML_ELEMENT_NODE,wxString::Format(wxT("nodo%d"),i));
247
nodo->AddProperty(new wxXmlProperty(wxT("x"),wxString::Format(wxT("%f"),(*it).x)));
248
nodo->AddProperty(new wxXmlProperty(wxT("y"),wxString::Format(wxT("%f"),(*it).y)));
249
resultado->AddChild(nodo);
253
SerializarMetadatos(resultado,nombreMedico);
258
void GNC::GCS::Widgets::WPoligono::OnMouseEvents(GNC::GCS::Eventos::EventoRaton& evento)
263
//------------------------------------------------------
265
if (evento.Leaving()){
268
//------------------------------------------------------
270
else if (evento.Entering() ) {
275
//------------------------------------------------------
277
else if (evento.Dragging() && m_MouseDown) {
278
Vector delta = evento.iP - m_PosCursor;
279
m_PosCursor = evento.iP;
281
if (EstaSeleccionado()) {
282
for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); it++) {
290
LanzarEventoModificacion();
297
//------------------------------------------------------
299
else if (evento.LeftDown()) {
301
if (EventoConsumido() && !evento.m_controlDown) {
308
if (evento.iP.DentroDePoligono2(m_Vertices)) {
310
if (evento.m_controlDown) { // Inversion de seleccion
318
if (!evento.m_controlDown) {
323
if (EstaSeleccionado()) {
325
m_PosCursor= evento.iP;
332
m_PosCursor= evento.iP;
339
//------------------------------------------------------
341
else if (evento.LeftUp()) {
343
ActualizarTimestampModificacion();
348
//------------------------------------------------------
350
else if (evento.Moving()) {
352
if (EventoConsumido()) {
359
m_PosCursor= evento.iP;
361
if (evento.iP.DentroDePoligono2(m_Vertices)) {
376
void GNC::GCS::Widgets::WPoligono::OnKeyEvents(GNC::GCS::Eventos::EventoTeclado& evento)
378
if (evento.GetKeyCode() == WXK_ESCAPE) {
383
bool GNC::GCS::Widgets::WPoligono::HitTest(float x, float y, float umbralCuadrado)
385
GNC::GCS::Vector punto(x, y);
387
bool hits = punto.DentroDePoligono2(m_Vertices);
390
punto.Asignar(x - umbralCuadrado, y - umbralCuadrado);
391
hits = punto.DentroDePoligono2(m_Vertices);
394
punto.Asignar(x, y - umbralCuadrado);
395
hits = punto.DentroDePoligono2(m_Vertices);
398
punto.Asignar(x + umbralCuadrado, y + umbralCuadrado);
399
hits = punto.DentroDePoligono2(m_Vertices);
402
punto.Asignar(x + umbralCuadrado, y);
403
hits = punto.DentroDePoligono2(m_Vertices);
406
punto.Asignar(x + umbralCuadrado, y - umbralCuadrado);
407
hits = punto.DentroDePoligono2(m_Vertices);
410
punto.Asignar(x , y - umbralCuadrado);
411
hits = punto.DentroDePoligono2(m_Vertices);
414
punto.Asignar(x - umbralCuadrado, y - umbralCuadrado);
415
hits = punto.DentroDePoligono2(m_Vertices);
418
punto.Asignar(x - umbralCuadrado, y);
419
hits = punto.DentroDePoligono2(m_Vertices);
424
bool GNC::GCS::Widgets::WPoligono::HitTest(GNC::GCS::Vector* vertices, int numVertices)
428
for (VerticesPoligono::iterator it = m_Vertices.begin(); hits && it != m_Vertices.end(); it++) {
429
if (!(*it).DentroDePoligono2(vertices, numVertices) ) {
437
void GNC::GCS::Widgets::WPoligono::Render(GNC::GCS::Contexto3D* c)
444
GNC::GCS::Vector escala = c->RelacionImagenPantalla();
445
glLineWidth(WIDGET_GROSOR_LINEA);
447
float fsombrax, fsombray;
449
if (m_Seleccionado && m_MouseDown)
451
fsombrax = WIDGET_OFFSET_X_SOMBRA_SELECCIONADO * escala.x;
452
fsombray = WIDGET_OFFSET_Y_SOMBRA_SELECCIONADO * escala.y;
456
fsombrax = WIDGET_OFFSET_X_SOMBRA * escala.x;
457
fsombray = WIDGET_OFFSET_Y_SOMBRA * escala.y;
460
wColorSombra.Aplicar();
461
glBegin(GL_LINE_LOOP);
462
for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); it++) {
463
glVertex2d((*it).x + fsombrax, (*it).y - fsombray);
468
for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); it++) {
469
glVertex2d((*it).x + fsombrax, (*it).y - fsombray);
473
// Dibujo el poligono
474
wAplicarColor(m_Iluminado, m_MouseDown, m_Seleccionado);
475
glBegin(GL_LINE_LOOP);
476
for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); it++) {
477
glVertex2d((*it).x, (*it).y);
483
glPointSize(WIDGET_SIZE_PUNTO);
484
for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); it++) {
486
glVertex2d((*it).x, (*it).y);
490
m_Modificado = false;
493
void GNC::GCS::Widgets::WPoligono::Seleccionar(bool seleccionado)
495
if (m_Seleccionado != seleccionado) {
496
m_Seleccionado = seleccionado;
501
void GNC::GCS::Widgets::WPoligono::Iluminar(bool iluminado)
503
if (m_Iluminado != iluminado) {
504
m_Iluminado = iluminado;
509
void GNC::GCS::Widgets::WPoligono::Ocultar(bool oculto){
510
if(oculto != m_Oculto){
516
void GNC::GCS::Widgets::WPoligono::Recalcular()
518
m_Centro = GNC::GCS::Vector::Centroide(m_Vertices);
519
m_Perimetro = GNC::GCS::Vector::PerimetroDePoligono(m_Vertices);
524
void GNC::GCS::Widgets::WPoligono::InsertarPropiedades(TListaMapasPropiedades &listaMapaPropiedades)
526
TMapaPropiedades& primerMapa = listaMapaPropiedades.front();
528
std::ostringstream ostr;
530
primerMapa[_Std("Center (I)")] = ostr.str();
534
std::stringstream out;
535
out << PuntoToStringMundo(m_Centro);
536
primerMapa[_Std("Center (M)")] = out.str();
540
std::ostringstream ostr;
541
ostr << m_Vertices.size();
542
primerMapa[_Std("Number of Vertex")] = ostr.str();
546
void GNC::GCS::Widgets::WPoligono::OffscreenRender(GNC::GCS::Contexto3D* c)
548
if(m_Vertices.size() < 2) {
552
//const GNC::GCS::Vector& escala = c->RefRelacionMundoPantallaOffscreen();
554
VerticesPoligono Vertices;
556
for (VerticesPoligono::iterator it = m_Vertices.begin(); it != m_Vertices.end(); it++)
558
Vertices.push_back( c->Reproyectar(*it) * c->factorReescalado );
561
cairo_set_line_width(c->cr, WIDGET_GROSOR_LINEA);
564
wColorNormal.AplicarCairo(c->cr);
566
// Dibujado del cuerpo
567
for (VerticesPoligono::iterator it = Vertices.begin(); it != Vertices.end(); it++) {
568
if(it == Vertices.begin()) {
569
cairo_move_to(c->cr, (*it).x, (*it).y);
571
cairo_line_to(c->cr, (*it).x, (*it).y);
573
cairo_line_to(c->cr, Vertices.front().x, Vertices.front().y);
577
float GNC::GCS::Widgets::WPoligono::GetAreaMetrica() const
581
const VerticesPoligono& lista = m_Vertices;
583
if (lista.size() > 3) {
585
std::list<GNC::GCS::Vector>::const_iterator i = lista.begin();
586
std::list<GNC::GCS::Vector>::const_iterator j = i; j++;
588
std::list<GNC::GCS::Vector>::const_iterator k;
589
std::list<GNC::GCS::Vector>::const_iterator l;
591
GNC::GCS::Vector inter;
592
GNC::GCS::Vector bbox[2][2];
596
glColor3f(1.0f, 0.0f, 0.0f);
597
glVertex2f( (*i).x, (*i).y );
599
glColor3f(0.0f, 0.0f, 1.0f);
600
glVertex2f( (*j).x, (*j).y );
604
const unsigned long nl = lista.size() - 1;
605
unsigned long ni = 0;
606
unsigned long nj = 0;
608
std::cout << "Poligono: numNodos = " << nl << std::endl;
610
for (ni = 0; simple && ni < nl; ni++, i++, j++) {
612
(*i).IniciarBoundingBox(bbox[0][0],bbox[0][1]);
613
(*j).ExtenderBoundingBox(bbox[0][0],bbox[0][1]);
619
while (k != lista.end()) {
623
if (l == lista.end()) {
630
(*k).IniciarBoundingBox(bbox[1][0], bbox[1][1]);
631
(*l).ExtenderBoundingBox(bbox[1][0], bbox[1][1]);
633
GNC::GCS::Vector::IntersectarBoundingBox(bbox[0], bbox[1], bbox[1]);
635
if ( GNC::GCS::Vector::BoundingBoxValido(bbox[1]) ) {
636
std::cout << "IntersecciĆ³n: [ " << ni << ", " << ni + 1 << " ] x [" << nj << ", ";
638
std::cout << "0 ]" << std::endl;
641
std::cout << nj + 1 << " ]" << std::endl;
644
inter = GNC::GCS::Vector::InterseccionEntreRectas(*i, *j, *k, *l);
646
//if ( inter.DistanciaARecta(*i, *j) < GNC::GCS::Vector::EpsilonDeComponentes() && inter.DistanciaARecta(*k, *l) < inter.DistanciaARecta(*k, *l) ) {
648
(inter.x + 1e-13) >= bbox[1][0].x &&
649
(inter.x - 1e-13) <= bbox[1][1].x &&
650
(inter.y + 1e-13) >= bbox[1][0].y &&
651
(inter.y - 1e-13) <= bbox[1][1].y
654
//if (inter.DentroDeBoundingBoxCerradoConUmbral(bbox[1][0], bbox[1][1]) ) {
657
glColor3f(0.0f, 0.0f, 1.0f);
659
glBegin(GL_LINE_LOOP);
660
glVertex2f(bbox[1][0].x, bbox[1][0].y);
661
glVertex2f(bbox[1][1].x, bbox[1][0].y);
662
glVertex2f(bbox[1][1].x, bbox[1][1].y);
663
glVertex2f(bbox[1][0].x, bbox[1][1].y);
666
glColor3f(1.0f, 1.0f, 1.0f);
668
glVertex2f((*i).x, (*i).y);
669
glVertex2f((*j).x, (*j).y);
674
glColor3f(1.0f, 0.0f, 1.0f);
675
glVertex2f(inter.x, inter.y);
680
GNC::GCS::Vector diff1 = inter - bbox[1][0];
681
GNC::GCS::Vector diff2 = bbox[1][1] - inter;
685
std::cout << "Diff1,2: " << diff1 << ", " << diff2 << std::endl;
687
double diff3 = inter.DistanciaARecta(*i, *j);
688
double diff4 = inter.DistanciaARecta(*k, *l);
690
std::cout << "Diff2,3" << diff3 << ", " << diff4 << std::endl;
692
GNC::GCS::Vector inter2 = GNC::GCS::Vector::InterseccionEntreRectas(*i, *j, *k, *l);
694
std::cout << inter2 << std::endl;
696
glColor3f(0.0f, 0.0f, 0.5f);
698
glBegin(GL_LINE_LOOP);
699
glVertex2f(bbox[1][0].x, bbox[1][0].y);
700
glVertex2f(bbox[1][1].x, bbox[1][0].y);
701
glVertex2f(bbox[1][1].x, bbox[1][1].y);
702
glVertex2f(bbox[1][0].x, bbox[1][1].y);
705
glColor3f(1.0f, 0.0f, 0.0f);
707
glVertex2f((*i).x, (*i).y);
708
glVertex2f((*j).x, (*j).y);
713
glColor3f(0.5f, 0.5f, 0.5f);
714
glVertex2f(inter.x, inter.y);
725
for (unsigned long nj = 2; simple && (ni + nj) < lista.size(); nj++, k++, l++) {
726
//inter = GNC::GCS::Vector::InterseccionEntreRectas((*i), (*j), (*k), (*l));
727
//if ( 1 || inter.DentroDeBoundingBoxCerrado(bbox[0][0], bbox[0][1])) {
728
(*k).IniciarBoundingBox(bbox[1][0],bbox[1][1]);
729
(*l).ExtenderBoundingBox(bbox[1][0],bbox[1][1]);
730
GNC::GCS::Vector::IntersectarBoundingBox(bbox[0], bbox[1], bbox[1]);
731
if ( GNC::GCS::Vector::BoundingBoxValido(bbox[1]) && GNC::GCS::Vector::InterseccionEntreRectas(*i, *j, *k, *l).DentroDeBoundingBoxCerrado(bbox[1][0], bbox[1][1]) ) {
733
GNC::GCS::Vector inter = GNC::GCS::Vector::InterseccionEntreRectas(*i, *j, *k, *l);
737
glColor3f(0.0f, 0.0f, 1.0f);
739
glBegin(GL_LINE_LOOP);
740
glVertex2f(bbox[1][0].x, bbox[1][0].y);
741
glVertex2f(bbox[1][1].x, bbox[1][0].y);
742
glVertex2f(bbox[1][1].x, bbox[1][1].y);
743
glVertex2f(bbox[1][0].x, bbox[1][1].y);
746
glColor3f(1.0f, 1.0f, 1.0f);
748
glVertex2f((*i).x, (*i).y);
749
glVertex2f((*j).x, (*j).y);
752
glVertex2f((*k).x, (*k).y);
753
glVertex2f((*l).x, (*l).y);
758
glColor3f(1.0f, 1.0f, 1.0f);
759
glVertex2f(inter.x, inter.y);
765
if ( (++i) == lista.end() ) {
769
glColor3f(1.0f, 0.0f, 1.0f);
770
glVertex2f( (*i).x, (*i).y );
781
if (GNC::GCS::Vector::EsPoligonoSimple(m_Vertices)) {
782
return GNC::GCS::Vector::AreaDePoligono(m_Vertices);
785
return std::numeric_limits<float>::quiet_NaN();