Création d'un compte pour un collaborateur extérieur au laboratoire depuis l'intranet ICube : https://intranet.icube.unistra.fr/fr/labs/member/profile

mapSVGRender.cpp 8.78 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
{

Sylvain Thery's avatar
Sylvain Thery committed
46
void SvgObj::addVertex(const Geom::Vec3f& v)
47
48
49
50
{
	m_vertices.push_back(v);
}

51
52
53
54
55
56
void SvgObj::addVertex3D(const Geom::Vec3f& v)
{
	m_vertices3D.push_back(v);
}


Sylvain Thery's avatar
Sylvain Thery committed
57
58
59
60
61
62
63
64

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


void SvgObj::close()
65
66
67
68
{
	m_vertices.push_back(m_vertices.front());
}

Sylvain Thery's avatar
Sylvain Thery committed
69
70
71
72
73
74
75
76
77

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);
	}

78
79
	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
80
81
82
83
84
85
86
87
88

	Geom::Vec3f N = U^V;

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

	return N;
}


Sylvain Thery's avatar
Sylvain Thery committed
89
90
91
92
93
94
95
96
void SvgPoints::save(std::ofstream& out)
{
	std::stringstream ss;

	for (std::vector<Geom::Vec3f>::iterator it =m_vertices.begin(); it != m_vertices.end(); ++it)
	{
		out << "<circle cx=\""<< (*it)[0];
		out << "\" cy=\""<< (*it)[1];
Sylvain Thery's avatar
Sylvain Thery committed
97
		out << "\" r=\""<< m_width;
Sylvain Thery's avatar
Sylvain Thery committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
		out << "\" style=\"stroke: none; fill: #";

		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.fill(prev);
		out.width(wp);

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

}

116

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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;

}

Sylvain Thery's avatar
Sylvain Thery committed
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
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;

}

181
182
183
184
185
186
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
227
228
229
230
231
232
233
234
235
236
237




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
238
239
//	compNormObj cmp;
//	std::sort(m_objs.begin(),m_objs.end(),cmp);
Sylvain Thery's avatar
Sylvain Thery committed
240

Sylvain Thery's avatar
Sylvain Thery committed
241
242
	std::cout << "CLOSE"<< std::endl;
//	std::list<SvgObj*> primitives;
243

Sylvain Thery's avatar
Sylvain Thery committed
244
	for (std::vector<SvgObj*>::iterator it = m_objs.begin(); it != m_objs.end(); ++it)
245
246
247
248
249
250
251
252
253
254
255
	{
		(*it)->save(*m_out);
	}

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



256
257
// all points behind the plane +1
// all points before the plane -1
Sylvain Thery's avatar
Sylvain Thery committed
258
// all points colinear to the plane 0
259
260
// undefined 999
int compSvgObj::points_plane (SvgPolygon* pol_points, SvgPolygon* pol_plane, float& averageZ)
Sylvain Thery's avatar
Sylvain Thery committed
261
262
263
264
265
266
267
268
269
270
{
	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;
271
	averageZ=0.0f;
Sylvain Thery's avatar
Sylvain Thery committed
272
273
	for (unsigned int i=0; i< nb; ++i)
	{
274
275
276
277
		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
278
279
280
281
282
283
284
285
286
287
288
289
290
		float ps = U*N;

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

291
292
	averageZ /= float(nb);

Sylvain Thery's avatar
Sylvain Thery committed
293
294
295
296
297
298
	if (nbfront==0)
		return 1;

	if (nbback==0)
		return -1;

299
300
301
302
	if (nb_col==nb)
		return 0;

	return 999;
Sylvain Thery's avatar
Sylvain Thery committed
303
304
}

305

Sylvain Thery's avatar
Sylvain Thery committed
306
307
308
309
310
311
312
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
	{
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
		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
328
			return true;
329
330
331

		// all point of b infront of a
		if ((t2 == -1) && (t1==999))
Sylvain Thery's avatar
Sylvain Thery committed
332
			return true;
333
334
335
336
337
338
339

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

		// all other cases ??
Sylvain Thery's avatar
Sylvain Thery committed
340
341
342
343
344
345
346
347
		return false;
	}

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


348
349

bool compNormObj::operator() (SvgObj* a, SvgObj*b)
Sylvain Thery's avatar
Sylvain Thery committed
350
{
351
352
353
354
355
	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
356
	{
357
358
359
		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
360
361
	}

362
363
364
365
	if ((p_a!= NULL)) // second case polygon/other
	{
		return true;	// all polygon before segments.
	}
Sylvain Thery's avatar
Sylvain Thery committed
366

367
368
	std::cout << "Cas non traite !!"<< std::endl;
	return false;
Sylvain Thery's avatar
Sylvain Thery committed
369
370
}

371
372
373



374
375
376
377
378
379
} // namespace SVG
} // namespace Render
} // namespace Algo
} // namespace CGoGN