Files
libreoffice/basegfx/source/tools/debugplotter.cxx
2006-12-14 23:31:23 +00:00

456 lines
19 KiB
C++
Executable File

/*************************************************************************
*
* $RCSfile: debugplotter.cxx,v $
*
* $Revision: 1.3 $
*
* last change: $Author: kz $ $Date: 2006-12-15 00:31:23 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_basegfx.hxx"
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif
#include <basegfx/curve/b2dcubicbezier.hxx>
#include <basegfx/tools/debugplotter.hxx>
#include <boost/bind.hpp>
namespace basegfx
{
namespace
{
void outputHeader( const ::rtl::OString& rTitle,
::std::ostream* pStm )
{
// output gnuplot setup
if( pStm )
{
*pStm << "#!/usr/bin/gnuplot -persist" << ::std::endl <<
"#" << ::std::endl <<
"# automatically generated by basegfx, don't change!" << ::std::endl <<
"#" << ::std::endl <<
"# --- " << (const sal_Char*)rTitle << " ---" << ::std::endl <<
"#" << ::std::endl <<
"set parametric" << ::std::endl <<
"# set terminal postscript eps enhanced color " << ::std::endl <<
"# set output \"plot.eps\"" << ::std::endl <<
// This function plots a cubic bezier curve. P,q,r,s
// are the control point elements of the corresponding
// output coordinate component (i.e. x components for
// the x plot, and y components for the y plot)
"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 <<
// This function plots the derivative of a cubic
// bezier curve. P,q,r,s are the control point
// components of the _original_ curve
"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 <<
// Plot a line's component of a line between a and b
// (where a and b should be the corresponding
// components of the line's start and end point,
// respectively)
"line(p,q,r) = p*(1-t)+q*t" << ::std::endl <<
// Plot a line's x component of a line in implicit
// form ax + by + c = 0
"implicitLineX(a,b,c,t) = a*-c + t*-b" << ::std::endl <<
// Plot a line's y component of a line in implicit
// form ax + by + c = 0
"implicitLineY(a,b,c,t) = b*-c + t*a" << ::std::endl <<
"pointmarkx(c,t) = c-0.03*t" << ::std::endl << // hack for displaying single points in parametric form
"pointmarky(c,t) = c+0.03*t" << ::std::endl << // hack for displaying single points in parametric form
"# end of setup" << ::std::endl;
}
else
{
OSL_TRACE( "#!/usr/bin/gnuplot -persist\n",
"#\n",
"# automatically generated by basegfx, don't change!\n",
"#\n",
"# --- %s ---\n",
"#\n",
"set parametric\n",
// This function plots a cubic bezier curve. P,q,r,s
// are the control point elements of the corresponding
// output coordinate component (i.e. x components for
// the x plot, and y components for the y plot)
"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",
// This function plots the derivative of a cubic
// bezier curve. P,q,r,s are the control point
// components of the _original_ curve
"cubicBezDerivative(p,q,r,s,t) = 3*(q-p)*(1-t)**2+6*(r-q)*(1-t)*t+3*(s-r)*t**2\n",
// Plot a line's component of a line between a and b
// (where a and b should be the corresponding
// components of the line's start and end point,
// respectively)
"line(p,q,r) = p*(1-t)+q*t\n",
// Plot a line's x component of a line in implicit
// form ax + by + c = 0
"implicitLineX(a,b,c,t) = a*-c + t*-b\n",
// Plot a line's y component of a line in implicit
// form ax + by + c = 0
"implicitLineY(a,b,c,t) = b*-c + t*a\n",
"pointmarkx(c,t) = c-0.03*t\n", // hack for displaying single points in parametric form
"pointmarky(c,t) = c+0.03*t\n", // hack for displaying single points in parametric form
"# end of setup\n",
(const sal_Char*)rTitle );
}
}
class Writer
{
public:
Writer( ::std::ostream* pStm ) :
mpStream( pStm )
{
}
void outputPoint( const ::std::pair< B2DPoint, ::rtl::OString >& rElem )
{
if( mpStream )
*mpStream << " " << rElem.first.getX() << "\t" << rElem.first.getY() << ::std::endl;
else
OSL_TRACE( " %f\t%f\n", rElem.first.getX(), rElem.first.getY() );
}
void outputVector( const ::std::pair< B2DVector, ::rtl::OString >& rElem )
{
if( mpStream )
*mpStream << " " << rElem.first.getX() << "\t" << rElem.first.getY() << ::std::endl << ::std::endl;
else
OSL_TRACE( " %f\t%f\n\n", rElem.first.getX(), rElem.first.getY() );
}
void outputRect( const ::std::pair< B2DRange, ::rtl::OString >& rElem )
{
const double nX0( rElem.first.getMinX() );
const double nY0( rElem.first.getMinY() );
const double nX1( rElem.first.getMaxX() );
const double nY1( rElem.first.getMaxY() );
if( mpStream )
*mpStream << " "
<< nX0 << "\t" << nY0 << "\t"
<< nX1 << "\t" << nY0 << "\t"
<< nX1 << "\t" << nY1 << "\t"
<< nX0 << "\t" << nY1 << "\t"
<< nX0 << "\t" << nY0 << ::std::endl << ::std::endl;
else
OSL_TRACE( " %f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n\n",
nX0, nY0,
nX1, nY0,
nX1, nY1,
nX0, nY1,
nX0, nY0 );
}
private:
::std::ostream* mpStream;
};
}
DebugPlotter::DebugPlotter( const sal_Char* pTitle ) :
maTitle( pTitle ),
maPoints(),
maVectors(),
maRanges(),
maPolygons(),
mpOutputStream(NULL)
{
}
DebugPlotter::DebugPlotter( const sal_Char* pTitle,
::std::ostream& rOutputStream ) :
maTitle( pTitle ),
maPoints(),
maVectors(),
maRanges(),
maPolygons(),
mpOutputStream(&rOutputStream)
{
}
DebugPlotter::~DebugPlotter()
{
const bool bHavePoints( !maPoints.empty() );
const bool bHaveVectors( !maVectors.empty() );
const bool bHaveRanges( !maRanges.empty() );
const bool bHavePolygons( !maPolygons.empty() );
if( bHavePoints ||
bHaveVectors ||
bHaveRanges ||
bHavePolygons )
{
outputHeader( maTitle, mpOutputStream );
print( "\n\n# parametric primitive output\n"
"plot [t=0:1] \\\n" );
// output plot declarations for used entities
bool bNeedColon( false );
if( bHavePoints )
{
print( " '-' using ($1):($2) title \"Points\" with points" );
bNeedColon = true;
}
if( bHaveVectors )
{
if( bNeedColon )
print( ", \\\n" );
print( " '-' using ($1):($2) title \"Vectors\" with lp" );
bNeedColon = true;
}
if( bHaveRanges )
{
if( bNeedColon )
print( ", \\\n" );
print( " '-' using ($1):($2) title \"Ranges\" with lines" );
bNeedColon = true;
}
if( bHavePolygons )
{
const ::std::size_t nSize( maPolygons.size() );
for( ::std::size_t i=0; i<nSize; ++i )
{
if( maPolygons.at(i).first.areControlVectorsUsed() )
{
const B2DPolygon& rCurrPoly( maPolygons.at(i).first );
const sal_uInt32 nCount( rCurrPoly.count() );
for( sal_uInt32 k=0; k<nCount; ++k )
{
if( bNeedColon )
print( ", \\\n" );
const B2DPoint& rP0( rCurrPoly.getB2DPoint(k) );
const B2DPoint& rP1( rCurrPoly.getControlPointA(k) );
const B2DPoint& rP2( rCurrPoly.getControlPointB(k) );
const B2DPoint& rP3( k+1<nCount ? rCurrPoly.getB2DPoint(k+1) : rCurrPoly.getB2DPoint(k) );
if( mpOutputStream )
*mpOutputStream << " cubicBezier("
<< rP0.getX() << ","
<< rP1.getX() << ","
<< rP2.getX() << ","
<< rP3.getX() << ",t), \\\n cubicBezier("
<< rP0.getY() << ","
<< rP1.getY() << ","
<< rP2.getY() << ","
<< rP3.getY() << ",t)";
else
OSL_TRACE( " cubicBezier(%f,%f,%f,%f,t), \\\n"
" cubicBezier(%f,%f,%f,%f,t)",
rP0.getX(),
rP1.getX(),
rP2.getX(),
rP3.getX(),
rP0.getY(),
rP1.getY(),
rP2.getY(),
rP3.getY() );
bNeedColon = true;
}
}
else
{
if( bNeedColon )
print( ", \\\n" );
if( mpOutputStream )
*mpOutputStream << " '-' using ($1):($2) title \"Polygon "
<< (const sal_Char*)maPolygons.at(i).second << "\" with lp";
else
OSL_TRACE( " '-' using ($1):($2) title \"Polygon %s\" with lp",
(const sal_Char*)maPolygons.at(i).second );
bNeedColon = true;
}
}
}
if( bHavePoints )
{
Writer aWriter( mpOutputStream );
::std::for_each( maPoints.begin(),
maPoints.end(),
::boost::bind( &Writer::outputPoint,
::boost::ref( aWriter ),
_1 ) );
print( "e\n" );
}
if( bHaveVectors )
{
Writer aWriter( mpOutputStream );
::std::for_each( maVectors.begin(),
maVectors.end(),
::boost::bind( &Writer::outputVector,
::boost::ref( aWriter ),
_1 ) );
print( "e\n" );
}
if( bHaveRanges )
{
Writer aWriter( mpOutputStream );
::std::for_each( maRanges.begin(),
maRanges.end(),
::boost::bind( &Writer::outputRect,
::boost::ref( aWriter ),
_1 ) );
print( "e\n" );
}
if( bHavePolygons )
{
const ::std::size_t nSize( maPolygons.size() );
for( ::std::size_t i=0; i<nSize; ++i )
{
if( !maPolygons.at(i).first.areControlVectorsUsed() )
{
const B2DPolygon& rCurrPoly( maPolygons.at(i).first );
const sal_uInt32 nCount( rCurrPoly.count() );
for( sal_uInt32 k=0; k<nCount; ++k )
{
const B2DPoint& rP( rCurrPoly.getB2DPoint(k) );
if( mpOutputStream )
*mpOutputStream << " " << rP.getX() << "," << rP.getY();
else
OSL_TRACE( " %f,%f",
rP.getX(),
rP.getX() );
}
print( "\ne\n" );
}
}
}
}
}
void DebugPlotter::plot( const B2DPoint& rPoint,
const sal_Char* pTitle )
{
maPoints.push_back( ::std::make_pair( rPoint,
::rtl::OString( pTitle ) ) );
}
void DebugPlotter::plot( const B2DVector& rVec,
const sal_Char* pTitle )
{
maVectors.push_back( ::std::make_pair( rVec,
::rtl::OString( pTitle ) ) );
}
void DebugPlotter::plot( const B2DCubicBezier& rBezier,
const sal_Char* pTitle )
{
B2DPolygon aPoly;
aPoly.append( rBezier.getStartPoint() );
aPoly.setControlPointA( 0,
rBezier.getControlPointA() );
aPoly.setControlPointB( 0,
rBezier.getControlPointB() );
aPoly.append( rBezier.getEndPoint() );
maPolygons.push_back( ::std::make_pair( aPoly,
::rtl::OString( pTitle ) ) );
}
void DebugPlotter::plot( const B2DRange& rRange,
const sal_Char* pTitle )
{
maRanges.push_back( ::std::make_pair( rRange,
::rtl::OString( pTitle ) ) );
}
void DebugPlotter::plot( const B2DPolygon& rPoly,
const sal_Char* pTitle )
{
maPolygons.push_back( ::std::make_pair( rPoly,
::rtl::OString( pTitle ) ) );
}
void DebugPlotter::plot( const B2DPolyPolygon& rPoly,
const sal_Char* pTitle )
{
const ::rtl::OString aTitle( pTitle );
const sal_uInt32 nCount( rPoly.count() );
for( sal_uInt32 i=0; i<nCount; ++i )
maPolygons.push_back( ::std::make_pair( rPoly.getB2DPolygon( i ),
aTitle ) );
}
void DebugPlotter::print( const sal_Char* pStr )
{
if( mpOutputStream )
*mpOutputStream << pStr;
else
OSL_TRACE( pStr );
}
}