merged tag ooo/OOO330_m14
[LibreOffice.git] / basegfx / source / tools / debugplotter.cxx
blob2c68eb44a846b6822e0cba8e63e70c81ece0ae5e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basegfx.hxx"
30 #include <osl/diagnose.h>
32 #include <basegfx/curve/b2dcubicbezier.hxx>
34 #include <basegfx/tools/debugplotter.hxx>
35 #include <boost/bind.hpp>
38 namespace basegfx
40 namespace
42 void outputHeader( const ::rtl::OString& rTitle,
43 ::std::ostream* pStm )
45 // output gnuplot setup
46 if( pStm )
48 *pStm << "#!/usr/bin/gnuplot -persist" << ::std::endl <<
49 "#" << ::std::endl <<
50 "# automatically generated by basegfx, don't change!" << ::std::endl <<
51 "#" << ::std::endl <<
52 "# --- " << (const sal_Char*)rTitle << " ---" << ::std::endl <<
53 "#" << ::std::endl <<
54 "set parametric" << ::std::endl <<
55 "# set terminal postscript eps enhanced color " << ::std::endl <<
56 "# set output \"plot.eps\"" << ::std::endl <<
57 // This function plots a cubic bezier curve. P,q,r,s
58 // are the control point elements of the corresponding
59 // output coordinate component (i.e. x components for
60 // the x plot, and y components for the y plot)
61 "cubicBezier(p,q,r,s,t) = p*(1-t)**3+q*3*(1-t)**2*t+r*3*(1-t)*t**2+s*t**3" << ::std::endl <<
62 // This function plots the derivative of a cubic
63 // bezier curve. P,q,r,s are the control point
64 // components of the _original_ curve
65 "cubicBezDerivative(p,q,r,s,t) = 3*(q-p)*(1-t)**2+6*(r-q)*(1-t)*t+3*(s-r)*t**2" << ::std::endl <<
66 // Plot a line's component of a line between a and b
67 // (where a and b should be the corresponding
68 // components of the line's start and end point,
69 // respectively)
70 "line(p,q,r) = p*(1-t)+q*t" << ::std::endl <<
71 // Plot a line's x component of a line in implicit
72 // form ax + by + c = 0
73 "implicitLineX(a,b,c,t) = a*-c + t*-b" << ::std::endl <<
74 // Plot a line's y component of a line in implicit
75 // form ax + by + c = 0
76 "implicitLineY(a,b,c,t) = b*-c + t*a" << ::std::endl <<
77 "pointmarkx(c,t) = c-0.03*t" << ::std::endl << // hack for displaying single points in parametric form
78 "pointmarky(c,t) = c+0.03*t" << ::std::endl << // hack for displaying single points in parametric form
79 "# end of setup" << ::std::endl;
81 else
83 OSL_TRACE( "#!/usr/bin/gnuplot -persist\n",
84 "#\n",
85 "# automatically generated by basegfx, don't change!\n",
86 "#\n",
87 "# --- %s ---\n",
88 "#\n",
89 "set parametric\n",
90 // This function plots a cubic bezier curve. P,q,r,s
91 // are the control point elements of the corresponding
92 // output coordinate component (i.e. x components for
93 // the x plot, and y components for the y plot)
94 "cubicBezier(p,q,r,s,t) = p*(1-t)**3+q*3*(1-t)**2*t+r*3*(1-t)*t**2+s*t**3\n",
95 // This function plots the derivative of a cubic
96 // bezier curve. P,q,r,s are the control point
97 // components of the _original_ curve
98 "cubicBezDerivative(p,q,r,s,t) = 3*(q-p)*(1-t)**2+6*(r-q)*(1-t)*t+3*(s-r)*t**2\n",
99 // Plot a line's component of a line between a and b
100 // (where a and b should be the corresponding
101 // components of the line's start and end point,
102 // respectively)
103 "line(p,q,r) = p*(1-t)+q*t\n",
104 // Plot a line's x component of a line in implicit
105 // form ax + by + c = 0
106 "implicitLineX(a,b,c,t) = a*-c + t*-b\n",
107 // Plot a line's y component of a line in implicit
108 // form ax + by + c = 0
109 "implicitLineY(a,b,c,t) = b*-c + t*a\n",
110 "pointmarkx(c,t) = c-0.03*t\n", // hack for displaying single points in parametric form
111 "pointmarky(c,t) = c+0.03*t\n", // hack for displaying single points in parametric form
112 "# end of setup\n",
113 (const sal_Char*)rTitle );
117 class Writer
119 public:
120 Writer( ::std::ostream* pStm ) :
121 mpStream( pStm )
125 void outputPoint( const ::std::pair< B2DPoint, ::rtl::OString >& rElem )
127 if( mpStream )
128 *mpStream << " " << rElem.first.getX() << "\t" << rElem.first.getY() << ::std::endl;
129 else
130 OSL_TRACE( " %f\t%f\n", rElem.first.getX(), rElem.first.getY() );
133 void outputVector( const ::std::pair< B2DVector, ::rtl::OString >& rElem )
135 if( mpStream )
136 *mpStream << " " << rElem.first.getX() << "\t" << rElem.first.getY() << ::std::endl << ::std::endl;
137 else
138 OSL_TRACE( " %f\t%f\n\n", rElem.first.getX(), rElem.first.getY() );
141 void outputRect( const ::std::pair< B2DRange, ::rtl::OString >& rElem )
143 const double nX0( rElem.first.getMinX() );
144 const double nY0( rElem.first.getMinY() );
145 const double nX1( rElem.first.getMaxX() );
146 const double nY1( rElem.first.getMaxY() );
148 if( mpStream )
149 *mpStream << " "
150 << nX0 << "\t" << nY0 << "\t"
151 << nX1 << "\t" << nY0 << "\t"
152 << nX1 << "\t" << nY1 << "\t"
153 << nX0 << "\t" << nY1 << "\t"
154 << nX0 << "\t" << nY0 << ::std::endl << ::std::endl;
156 else
157 OSL_TRACE( " %f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n\n",
158 nX0, nY0,
159 nX1, nY0,
160 nX1, nY1,
161 nX0, nY1,
162 nX0, nY0 );
165 private:
166 ::std::ostream* mpStream;
170 DebugPlotter::DebugPlotter( const sal_Char* pTitle ) :
171 maTitle( pTitle ),
172 maPoints(),
173 maVectors(),
174 maRanges(),
175 maPolygons(),
176 mpOutputStream(NULL)
180 DebugPlotter::DebugPlotter( const sal_Char* pTitle,
181 ::std::ostream& rOutputStream ) :
182 maTitle( pTitle ),
183 maPoints(),
184 maVectors(),
185 maRanges(),
186 maPolygons(),
187 mpOutputStream(&rOutputStream)
191 DebugPlotter::~DebugPlotter()
193 const bool bHavePoints( !maPoints.empty() );
194 const bool bHaveVectors( !maVectors.empty() );
195 const bool bHaveRanges( !maRanges.empty() );
196 const bool bHavePolygons( !maPolygons.empty() );
198 if( bHavePoints ||
199 bHaveVectors ||
200 bHaveRanges ||
201 bHavePolygons )
203 outputHeader( maTitle, mpOutputStream );
205 print( "\n\n# parametric primitive output\n"
206 "plot [t=0:1] \\\n" );
208 // output plot declarations for used entities
209 bool bNeedColon( false );
210 if( bHavePoints )
212 print( " '-' using ($1):($2) title \"Points\" with points" );
213 bNeedColon = true;
215 if( bHaveVectors )
217 if( bNeedColon )
218 print( ", \\\n" );
220 print( " '-' using ($1):($2) title \"Vectors\" with lp" );
221 bNeedColon = true;
223 if( bHaveRanges )
225 if( bNeedColon )
226 print( ", \\\n" );
228 print( " '-' using ($1):($2) title \"Ranges\" with lines" );
229 bNeedColon = true;
231 if( bHavePolygons )
233 const ::std::size_t nSize( maPolygons.size() );
234 for( ::std::size_t i=0; i<nSize; ++i )
236 if( maPolygons.at(i).first.areControlPointsUsed() )
238 const B2DPolygon& rCurrPoly( maPolygons.at(i).first );
240 const sal_uInt32 nCount( rCurrPoly.count() );
241 for( sal_uInt32 k=0; k<nCount; ++k )
243 if( bNeedColon )
244 print( ", \\\n" );
246 const B2DPoint& rP0( rCurrPoly.getB2DPoint(k) );
247 const B2DPoint& rP1( rCurrPoly.getNextControlPoint(k) );
248 const B2DPoint& rP2( rCurrPoly.getPrevControlPoint((k + 1) % nCount) );
249 const B2DPoint& rP3( k+1<nCount ? rCurrPoly.getB2DPoint(k+1) : rCurrPoly.getB2DPoint(k) );
251 if( mpOutputStream )
252 *mpOutputStream << " cubicBezier("
253 << rP0.getX() << ","
254 << rP1.getX() << ","
255 << rP2.getX() << ","
256 << rP3.getX() << ",t), \\\n cubicBezier("
257 << rP0.getY() << ","
258 << rP1.getY() << ","
259 << rP2.getY() << ","
260 << rP3.getY() << ",t)";
261 else
262 OSL_TRACE( " cubicBezier(%f,%f,%f,%f,t), \\\n"
263 " cubicBezier(%f,%f,%f,%f,t)",
264 rP0.getX(),
265 rP1.getX(),
266 rP2.getX(),
267 rP3.getX(),
268 rP0.getY(),
269 rP1.getY(),
270 rP2.getY(),
271 rP3.getY() );
273 bNeedColon = true;
276 else
278 if( bNeedColon )
279 print( ", \\\n" );
281 if( mpOutputStream )
282 *mpOutputStream << " '-' using ($1):($2) title \"Polygon "
283 << (const sal_Char*)maPolygons.at(i).second << "\" with lp";
284 else
285 OSL_TRACE( " '-' using ($1):($2) title \"Polygon %s\" with lp",
286 (const sal_Char*)maPolygons.at(i).second );
288 bNeedColon = true;
293 if( bHavePoints )
295 Writer aWriter( mpOutputStream );
297 ::std::for_each( maPoints.begin(),
298 maPoints.end(),
299 ::boost::bind( &Writer::outputPoint,
300 ::boost::ref( aWriter ),
301 _1 ) );
302 print( "e\n" );
305 if( bHaveVectors )
307 Writer aWriter( mpOutputStream );
309 ::std::for_each( maVectors.begin(),
310 maVectors.end(),
311 ::boost::bind( &Writer::outputVector,
312 ::boost::ref( aWriter ),
313 _1 ) );
314 print( "e\n" );
317 if( bHaveRanges )
319 Writer aWriter( mpOutputStream );
321 ::std::for_each( maRanges.begin(),
322 maRanges.end(),
323 ::boost::bind( &Writer::outputRect,
324 ::boost::ref( aWriter ),
325 _1 ) );
326 print( "e\n" );
329 if( bHavePolygons )
331 const ::std::size_t nSize( maPolygons.size() );
332 for( ::std::size_t i=0; i<nSize; ++i )
334 if( !maPolygons.at(i).first.areControlPointsUsed() )
336 const B2DPolygon& rCurrPoly( maPolygons.at(i).first );
338 const sal_uInt32 nCount( rCurrPoly.count() );
339 for( sal_uInt32 k=0; k<nCount; ++k )
341 const B2DPoint& rP( rCurrPoly.getB2DPoint(k) );
343 if( mpOutputStream )
344 *mpOutputStream << " " << rP.getX() << "," << rP.getY();
345 else
346 OSL_TRACE( " %f,%f",
347 rP.getX(),
348 rP.getX() );
351 print( "\ne\n" );
358 void DebugPlotter::plot( const B2DPoint& rPoint,
359 const sal_Char* pTitle )
361 maPoints.push_back( ::std::make_pair( rPoint,
362 ::rtl::OString( pTitle ) ) );
365 void DebugPlotter::plot( const B2DVector& rVec,
366 const sal_Char* pTitle )
368 maVectors.push_back( ::std::make_pair( rVec,
369 ::rtl::OString( pTitle ) ) );
372 void DebugPlotter::plot( const B2DCubicBezier& rBezier,
373 const sal_Char* pTitle )
375 B2DPolygon aPoly;
376 aPoly.append(rBezier.getStartPoint());
377 aPoly.appendBezierSegment(rBezier.getControlPointA(), rBezier.getControlPointB(), rBezier.getEndPoint());
378 maPolygons.push_back( ::std::make_pair( aPoly,
379 ::rtl::OString( pTitle ) ) );
382 void DebugPlotter::plot( const B2DRange& rRange,
383 const sal_Char* pTitle )
385 maRanges.push_back( ::std::make_pair( rRange,
386 ::rtl::OString( pTitle ) ) );
389 void DebugPlotter::plot( const B2DPolygon& rPoly,
390 const sal_Char* pTitle )
392 maPolygons.push_back( ::std::make_pair( rPoly,
393 ::rtl::OString( pTitle ) ) );
396 void DebugPlotter::plot( const B2DPolyPolygon& rPoly,
397 const sal_Char* pTitle )
399 const ::rtl::OString aTitle( pTitle );
400 const sal_uInt32 nCount( rPoly.count() );
401 for( sal_uInt32 i=0; i<nCount; ++i )
402 maPolygons.push_back( ::std::make_pair( rPoly.getB2DPolygon( i ),
403 aTitle ) );
406 void DebugPlotter::print( const sal_Char* pStr )
408 if( mpOutputStream )
409 *mpOutputStream << pStr;
410 else
411 OSL_TRACE( pStr );