blob: e22908e897b37d1bf4730ffaa5f44dc3419516a5 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_basegfx.hxx"
#include <osl/diagnose.h>
#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 <<
"# --- " << rTitle.getStr() << " ---" << ::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",
rTitle.getStr() );
}
}
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.areControlPointsUsed() )
{
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.getNextControlPoint(k) );
const B2DPoint& rP2( rCurrPoly.getPrevControlPoint((k + 1) % nCount) );
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 "
<< maPolygons.at(i).second.getStr() << "\" with lp";
else
OSL_TRACE( " '-' using ($1):($2) title \"Polygon %s\" with lp",
maPolygons.at(i).second.getStr() );
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.areControlPointsUsed() )
{
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.appendBezierSegment(rBezier.getControlPointA(), rBezier.getControlPointB(), 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 );
}
}