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