Coupure prévue mardi 3 Août au matin pour maintenance du serveur. Nous faisons au mieux pour que celle-ci soit la plus brève possible.

mapSVGRender.cpp 12.7 KB
Newer Older
1
2
3
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
4
* Copyright (C) 2009-2011, IGG Team, LSIIT, University of Strasbourg           *
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library 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 Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
20
* Web site: http://cgogn.u-strasbg.fr/                                         *
21
22
23
24
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/
#include "Algo/Render/SVG/mapSVGRender.h"
Sylvain Thery's avatar
Sylvain Thery committed
25
26
#include <algorithm>
#include <typeinfo>
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

/**
* A set of functions that allow the creation of rendering
* object using Vertex-Buffer-Object.
* Function are made for dual-2-map and can be used on
* any subset of a dual-N-map which is a 2-map
*/
namespace CGoGN
{

namespace Algo
{

namespace Render
{

namespace SVG
{

46
47
48



Sylvain Thery's avatar
Sylvain Thery committed
49
void SvgObj::addVertex(const Geom::Vec3f& v)
50
51
{
	m_vertices.push_back(v);
52
	m_colors.push_back(m_color);
53
54
}

55
56
57
void SvgObj::addVertex3D(const Geom::Vec3f& v)
{
	m_vertices3D.push_back(v);
58
59
60
61
62
63
64
65
66
67
68
69
70
	m_colors.push_back(m_color);
}

void SvgObj::addVertex(const Geom::Vec3f& v, const Geom::Vec3f& c)
{
	m_vertices.push_back(v);
	m_colors.push_back(c);
}

void SvgObj::addVertex3D(const Geom::Vec3f& v, const Geom::Vec3f& c)
{
	m_vertices3D.push_back(v);
	m_colors.push_back(c);
71
72
73
}


Sylvain Thery's avatar
Sylvain Thery committed
74
75
76
77
78
79
80
81

void SvgObj::setColor(const Geom::Vec3f& c)
{
	m_color=c;
}


void SvgObj::close()
82
83
84
85
{
	m_vertices.push_back(m_vertices.front());
}

Sylvain Thery's avatar
Sylvain Thery committed
86
87
88
89
90
91
92
93
94

Geom::Vec3f SvgObj::normal()
{
	if (m_vertices.size()<3)
	{
		CGoGNerr << "Error SVG normal computing (not enough points)"<<CGoGNendl;
		return Geom::Vec3f(0.0f,0.0f,0.0f);
	}

95
96
	Geom::Vec3f U = m_vertices3D[2] - m_vertices3D[1];
	Geom::Vec3f V = m_vertices3D[0] - m_vertices3D[1];
Sylvain Thery's avatar
Sylvain Thery committed
97
98
99
100
101
102
103
104
105

	Geom::Vec3f N = U^V;

	N.normalize(); // TO DO verify that is necessary

	return N;
}


Sylvain Thery's avatar
Sylvain Thery committed
106
107
108
109
void SvgPoints::save(std::ofstream& out)
{
	std::stringstream ss;

110
111
112
//	for (std::vector<Geom::Vec3f>::iterator it =m_vertices.begin(); it != m_vertices.end(); ++it)
	unsigned int nb = m_vertices.size();
	for (unsigned int i=0; i<nb; ++i)
Sylvain Thery's avatar
Sylvain Thery committed
113
	{
114
115
		out << "<circle cx=\""<< m_vertices[i][0];
		out << "\" cy=\""<< m_vertices[i][1];
Sylvain Thery's avatar
Sylvain Thery committed
116
		out << "\" r=\""<< m_width;
Sylvain Thery's avatar
Sylvain Thery committed
117
118
119
120
121
		out << "\" style=\"stroke: none; fill: #";

		out << std::hex;
		unsigned int wp = out.width(2);
		char prev = out.fill('0');
122
		out << int(m_colors[i][0]*255);
Sylvain Thery's avatar
Sylvain Thery committed
123
		out.width(2); out.fill('0');
124
		out<< int(m_colors[i][1]*255);
Sylvain Thery's avatar
Sylvain Thery committed
125
		out.width(2); out.fill('0');
126
		out << int(m_colors[i][2]*255)<<std::dec;
Sylvain Thery's avatar
Sylvain Thery committed
127
128
129
130
131
132
133
134
		out.fill(prev);
		out.width(wp);

		out <<"\"/>"<< std::endl;
	}

}

135

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
void SvgPolyline::save(std::ofstream& out)
{
	std::stringstream ss;

	out << "<polyline fill=\"none\" stroke=\"#";
	out << std::hex;
	unsigned int wp = out.width(2);
	char prev = out.fill('0');
	out << int(m_color[0]*255);
	out.width(2); out.fill('0');
	out<< int(m_color[1]*255);
	out.width(2); out.fill('0');
	out << int(m_color[2]*255)<<std::dec;
	out <<"\" stroke-width=\""<<m_width<<"\" points=\"";
	out.fill(prev);
	out.width(wp);
	for (std::vector<Geom::Vec3f>::iterator it =m_vertices.begin(); it != m_vertices.end(); ++it)
	{
		out << (*it)[0] << ","<< (*it)[1]<< " ";
	}
	out <<"\"/>"<< std::endl;
157
}
158

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
void SvgLines::save(std::ofstream& out)
{
	std::stringstream ss;

//	for (std::vector<Geom::Vec3f>::iterator it =m_vertices.begin(); it != m_vertices.end(); ++it)
	unsigned int nb = m_vertices.size();
	for (unsigned int i=0; i<nb; ++i)
	{
		out << "<polyline fill=\"none\" stroke=\"#";
		out << std::hex;
		unsigned int wp = out.width(2);
		char prev = out.fill('0');
		out << int(m_colors[i][0]*255);
		out.width(2); out.fill('0');
		out<< int(m_colors[i][1]*255);
		out.width(2); out.fill('0');
		out << int(m_colors[i][2]*255)<<std::dec;
		out <<"\" stroke-width=\""<<m_width<<"\" points=\"";
		out.fill(prev);
		out.width(wp);
		out << m_vertices[i][0] << ","<< m_vertices[i][1]<< " ";
		i++;
		out << m_vertices[i][0] << ","<< m_vertices[i][1];
		out <<"\"/>"<< std::endl;
	}
184
185
}

186

Sylvain Thery's avatar
Sylvain Thery committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
void SvgPolygon::setColorFill(const Geom::Vec3f& c)
{
	m_colorFill=c;
}


void SvgPolygon::save(std::ofstream& out)
{
	std::stringstream ss;

	out << "<polyline fill=\"";
	out << std::hex;
	unsigned int wp = out.width(2);
	char prev = out.fill('0');
	out << int(m_colorFill[0]*255);
	out.width(2); out.fill('0');
	out<< int(m_colorFill[1]*255);
	out.width(2); out.fill('0');
	out << int(m_colorFill[2]*255);

	out << "none\" stroke=\"#";
	wp = out.width(2);
	prev = out.fill('0');
	out << int(m_color[0]*255);
	out.width(2); out.fill('0');
	out<< int(m_color[1]*255);
	out.width(2); out.fill('0');
	out << int(m_color[2]*255)<<std::dec;

	out <<"\" stroke-width=\""<<m_width<<"\" points=\"";
	out.fill(prev);
	out.width(wp);
	for (std::vector<Geom::Vec3f>::iterator it =m_vertices.begin(); it != m_vertices.end(); ++it)
	{
		out << (*it)[0] << ","<< (*it)[1]<< " ";
	}
	out <<"\"/>"<< std::endl;

}

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283




SVGOut::SVGOut(const std::string& filename, const glm::mat4& model, const glm::mat4& proj):
		m_model(model),m_proj(proj),global_color(Geom::Vec3f(0.0f,0.0f,0.0f)), global_width(2.0f)
{
	m_objs.reserve(1000);

	m_out = new std::ofstream(filename.c_str()) ;
	if (!m_out->good())
	{
		CGoGNerr << "Unable to open file " << CGoGNendl ;
		// ????
	}

	glGetIntegerv(GL_VIEWPORT, &(m_viewport[0]));

	*m_out << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"<< std::endl;
	*m_out << "<svg xmlns=\"http://www.w3.org/2000/svg\""<< std::endl;
	*m_out << " xmlns:xlink=\"http://www.w3.org/1999/xlink\""<< std::endl;
	*m_out << " width=\""<<m_viewport[2]<<"px\" height=\""<<m_viewport[3]<<"px\" viewBox=\"0 0 "<<m_viewport[2]<<" "<<m_viewport[3]<<"\">"<< std::endl;
	*m_out << "<title>test</title>"<< std::endl;
	*m_out << "<desc>"<< std::endl;
	*m_out << "Rendered from CGoGN"<< std::endl;

	*m_out << "</desc>"<< std::endl;
	*m_out << "<defs>"<< std::endl;
	*m_out << "</defs>"<< std::endl;
	*m_out << "<g shape-rendering=\"crispEdges\">" << std::endl;
}

SVGOut::~SVGOut()
{
	if (m_out->good())
	{
		closeFile();
	}
	delete m_out;

	for (std::vector<SvgObj*>::iterator it = m_objs.begin(); it != m_objs.end(); ++it)
		delete (*it);
}

void SVGOut::setColor(const Geom::Vec3f& col)
{
	global_color = col;
}

void SVGOut::setWidth(float w)
{
	global_width = w;
}

void SVGOut::closeFile()
{
	// here do the sort in necessary
Sylvain Thery's avatar
Sylvain Thery committed
284
285
//	compNormObj cmp;
//	std::sort(m_objs.begin(),m_objs.end(),cmp);
Sylvain Thery's avatar
Sylvain Thery committed
286

Sylvain Thery's avatar
Sylvain Thery committed
287
288
	std::cout << "CLOSE"<< std::endl;
//	std::list<SvgObj*> primitives;
289

Sylvain Thery's avatar
Sylvain Thery committed
290
	for (std::vector<SvgObj*>::iterator it = m_objs.begin(); it != m_objs.end(); ++it)
291
292
293
294
295
296
297
298
299
300
301
	{
		(*it)->save(*m_out);
	}

	*m_out << "</g>" << std::endl;
	*m_out << "</svg>" << std::endl;
	m_out->close();
}



302
303
// all points behind the plane +1
// all points before the plane -1
Sylvain Thery's avatar
Sylvain Thery committed
304
// all points colinear to the plane 0
305
306
// undefined 999
int compSvgObj::points_plane (SvgPolygon* pol_points, SvgPolygon* pol_plane, float& averageZ)
Sylvain Thery's avatar
Sylvain Thery committed
307
308
309
310
311
312
313
314
315
316
{
	Geom::Vec3f N = pol_plane->normal();

	if (N[2] > 0.0f)
		N = -1.0f*N;

	unsigned int nb = pol_points->nbv();
	unsigned int nbback=0;
	unsigned int nbfront=0;
	unsigned int nb_col=0;
317
	averageZ=0.0f;
Sylvain Thery's avatar
Sylvain Thery committed
318
319
	for (unsigned int i=0; i< nb; ++i)
	{
320
321
322
323
		const Geom::Vec3f& Q = pol_points->P(i);
		averageZ += Q[2];
		Geom::Vec3f U = Q - pol_plane->P(0);

Sylvain Thery's avatar
Sylvain Thery committed
324
325
326
327
328
329
330
331
332
333
334
335
336
		float ps = U*N;

		if (fabs(ps) < 0.0001f)
			nb_col++;
		else
		{
			if (ps <0)
				nbback++;
			else
				nbfront++;
		}
	}

337
338
	averageZ /= float(nb);

Sylvain Thery's avatar
Sylvain Thery committed
339
340
341
342
343
344
	if (nbfront==0)
		return 1;

	if (nbback==0)
		return -1;

345
346
347
348
	if (nb_col==nb)
		return 0;

	return 999;
Sylvain Thery's avatar
Sylvain Thery committed
349
350
}

351

Sylvain Thery's avatar
Sylvain Thery committed
352
353
354
355
356
357
358
bool compSvgObj::operator() (SvgObj* a, SvgObj*b)
{
	SvgPolygon* p_a = dynamic_cast<SvgPolygon*>(a);
	SvgPolygon* p_b = dynamic_cast<SvgPolygon*>(b);

	if ((p_a!= NULL) && (p_b!=NULL)) // first case polygon/polygon
	{
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
		float avz_a;
		int  t1 = points_plane(p_a,p_b,avz_a);

		if (t1==0) // colinear choose farthest
		{
			float za = p_a->P(0)[2];
			float zb = p_b->P(0)[2];
			return za > zb;
		}

		float avz_b;
		int  t2 = points_plane(p_b,p_a,avz_b);

		// all point of a behind b
		if ((t1 == 1)&&(t2==999))
Sylvain Thery's avatar
Sylvain Thery committed
374
			return true;
375
376
377

		// all point of b infront of a
		if ((t2 == -1) && (t1==999))
Sylvain Thery's avatar
Sylvain Thery committed
378
			return true;
379
380
381
382
383
384
385

		if ((t1 == t2 )&& (t2!=999))
		{
			return avz_a > avz_b;
		}

		// all other cases ??
Sylvain Thery's avatar
Sylvain Thery committed
386
387
388
389
390
391
392
393
		return false;
	}

	std::cout << "Cas non traite !!"<< std::endl;
	return false;
}


394
395

bool compNormObj::operator() (SvgObj* a, SvgObj*b)
Sylvain Thery's avatar
Sylvain Thery committed
396
{
397
398
399
400
401
	SvgPolygon* p_a = dynamic_cast<SvgPolygon*>(a);
	SvgPolygon* p_b = dynamic_cast<SvgPolygon*>(b);


	if ((p_a!= NULL) && (p_b!=NULL)) // first case polygon/polygon
Sylvain Thery's avatar
Sylvain Thery committed
402
	{
403
404
405
		Geom::Vec3f Na = p_a->normal();
		Geom::Vec3f Nb = p_b->normal();
		return fabs(Na[2]) > fabs(Nb[2]);
Sylvain Thery's avatar
Sylvain Thery committed
406
407
	}

408
409
410
411
	if ((p_a!= NULL)) // second case polygon/other
	{
		return true;	// all polygon before segments.
	}
Sylvain Thery's avatar
Sylvain Thery committed
412

413
414
	std::cout << "Cas non traite !!"<< std::endl;
	return false;
Sylvain Thery's avatar
Sylvain Thery committed
415
416
}

417
418


419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
void SVGOut::beginPoints()
{
	glm::i32vec4 viewport;
	glGetIntegerv(GL_VIEWPORT, &(viewport[0]));

	m_current = new SvgPoints();
	m_current->setColor(global_color);
	m_current->setWidth(global_width);
}

void SVGOut::endPoints()
{
	m_objs.push_back(m_current);
}

void SVGOut::addPoint(const Geom::Vec3f& P)
{
	glm::vec3 Q = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,m_proj,m_viewport);
	glm::vec3 R = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,glm::mat4(1.0),m_viewport);
	m_current->addVertex(Geom::Vec3f(Q[0],float(m_viewport[3])-Q[1],Q[2]));
	m_current->addVertex3D(Geom::Vec3f(Q[0],float(m_viewport[3])-Q[1],Q[2]));
}

void SVGOut::addPoint(const Geom::Vec3f& P, const Geom::Vec3f& C)
{
	glm::vec3 Q = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,m_proj,m_viewport);
	glm::vec3 R = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,glm::mat4(1.0),m_viewport);
	m_current->addVertex(Geom::Vec3f(Q[0],float(m_viewport[3])-Q[1],Q[2]),C);
	m_current->addVertex3D(Geom::Vec3f(Q[0],float(m_viewport[3])-Q[1],Q[2]),C);
}


void SVGOut::beginLines()
{
	glm::i32vec4 viewport;
	glGetIntegerv(GL_VIEWPORT, &(viewport[0]));

	m_current = new SvgLines();
	m_current->setColor(global_color);
	m_current->setWidth(global_width);
}


void SVGOut::endLines()
{
	m_objs.push_back(m_current);
}

void SVGOut::addLine(const Geom::Vec3f& P, const Geom::Vec3f& P2)
{
	glm::vec3 Q = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,m_proj,m_viewport);
	glm::vec3 R = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,glm::mat4(1.0),m_viewport);

	glm::vec3 Q2 = glm::project(glm::vec3(P2[0],P2[1],P2[2]),m_model,m_proj,m_viewport);
	glm::vec3 R2 = glm::project(glm::vec3(P2[0],P2[1],P2[2]),m_model,glm::mat4(1.0),m_viewport);

	m_current->addVertex(Geom::Vec3f(Q[0],float(m_viewport[3])-Q[1],Q[2]));
	m_current->addVertex(Geom::Vec3f(Q2[0],float(m_viewport[3])-Q2[1],Q2[2]));

	m_current->addVertex3D(Geom::Vec3f(R[0],float(m_viewport[3])-R[1],R[2]));
	m_current->addVertex3D(Geom::Vec3f(R2[0],float(m_viewport[3])-R2[1],R2[2]));
}



void SVGOut::addLine(const Geom::Vec3f& P, const Geom::Vec3f& P2, const Geom::Vec3f& C)
{
	glm::vec3 Q = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,m_proj,m_viewport);
	glm::vec3 R = glm::project(glm::vec3(P[0],P[1],P[2]),m_model,glm::mat4(1.0),m_viewport);

	glm::vec3 Q2 = glm::project(glm::vec3(P2[0],P2[1],P2[2]),m_model,m_proj,m_viewport);
	glm::vec3 R2 = glm::project(glm::vec3(P2[0],P2[1],P2[2]),m_model,glm::mat4(1.0),m_viewport);

	m_current->addVertex(Geom::Vec3f(Q[0],float(m_viewport[3])-Q[1],Q[2]),C);
	m_current->addVertex(Geom::Vec3f(Q2[0],float(m_viewport[3])-Q2[1],Q2[2]),C);

	m_current->addVertex3D(Geom::Vec3f(R[0],float(m_viewport[3])-R[1],R[2]),C);
	m_current->addVertex3D(Geom::Vec3f(R2[0],float(m_viewport[3])-R2[1],R2[2]),C);
}



501

502
503
504
505
506
507
} // namespace SVG
} // namespace Render
} // namespace Algo
} // namespace CGoGN