| /************************************************************** |
| * |
| * 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 "testtools.hxx" |
| |
| #include <basegfx/point/b2dpoint.hxx> |
| #include <basegfx/vector/b2dvector.hxx> |
| #include <basegfx/range/b2drange.hxx> |
| #include <basegfx/curve/b2dcubicbezier.hxx> |
| #include <basegfx/polygon/b2dpolygon.hxx> |
| #include <basegfx/polygon/b2dpolypolygon.hxx> |
| |
| #include <algorithm> |
| |
| |
| namespace basegfx |
| { |
| namespace testtools |
| { |
| Plotter::Plotter( ::std::ostream& rOutputStream ) : |
| mrOutputStream(rOutputStream), |
| maPoints(), |
| mbFirstElement( true ) |
| { |
| // output gnuplot setup. We switch gnuplot to parametric |
| // mode, therefore every plot has at least _two_ |
| // functions: one for the x and one for the y value, both |
| // depending on t. |
| mrOutputStream << "#!/usr/bin/gnuplot -persist" << ::std::endl |
| << "#" << ::std::endl |
| << "# automatically generated by basegfx::testtools::Plotter, don't change!" << ::std::endl |
| << "#" << ::std::endl |
| << "set parametric" << ::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 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 |
| |
| // 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(a,b,t) = a*(1-t) + b*t" << ::std::endl << ::std::endl |
| << "# end of setup" << ::std::endl << ::std::endl |
| |
| // Start the actual plot line |
| << "plot [t=0:1] "; |
| } |
| |
| namespace |
| { |
| class PointWriter |
| { |
| public: |
| PointWriter( ::std::ostream& rOutputStream ) : |
| mrOutputStream( rOutputStream ) |
| { |
| } |
| |
| void operator()( const B2DPoint& rPoint ) const |
| { |
| mrOutputStream << rPoint.getX() << "\t" << rPoint.getY() << ::std::endl; |
| mrOutputStream << "e" << ::std::endl; |
| } |
| |
| private: |
| ::std::ostream& mrOutputStream; |
| }; |
| } |
| |
| Plotter::~Plotter() |
| { |
| // End the plot line |
| mrOutputStream << ::std::endl; |
| |
| // write stored data points. Cannot write before, since |
| // this is an inline dataset, which must be after the plot <...> |
| // line |
| ::std::for_each( maPoints.begin(), maPoints.end(), PointWriter(mrOutputStream) ); |
| } |
| |
| void Plotter::plot( const B2DPolygon& rPoly ) |
| { |
| const sal_uInt32 pointCount( rPoly.count() ); |
| |
| if( pointCount < 1 ) |
| return; |
| |
| if( pointCount == 1 ) |
| { |
| plot( rPoly.getB2DPoint(0) ); |
| return; |
| } |
| |
| sal_uInt32 i; |
| for( i=0; i<pointCount-1; ++i ) |
| { |
| if(rPoly.isNextControlPointUsed(i) || rPoly.isPrevControlPointUsed(i + 1)) |
| { |
| const B2DCubicBezier aBezierPlot( |
| rPoly.getB2DPoint(i), rPoly.getNextControlPoint(i), |
| rPoly.getPrevControlPoint(i + 1), rPoly.getB2DPoint(i + 1)); |
| |
| plot(aBezierPlot); |
| } |
| else |
| { |
| plot( rPoly.getB2DPoint(i), rPoly.getB2DPoint(i+1) ); |
| } |
| } |
| } |
| |
| void Plotter::plot( const B2DPolyPolygon& rPolyPoly ) |
| { |
| const sal_uInt32 nPolyCount( rPolyPoly.count() ); |
| |
| sal_uInt32 i; |
| for( i=0; i<nPolyCount; ++i ) |
| { |
| plot( rPolyPoly.getB2DPolygon(i) ); |
| } |
| } |
| |
| void Plotter::plot( const B2DPoint& rPoint ) |
| { |
| maPoints.push_back( rPoint ); |
| writeSeparator(); |
| mrOutputStream << "'-' using ($1):($2) title \"Point " << maPoints.size() << "\" with points"; |
| } |
| |
| void Plotter::plot( const B2DRange& rRect ) |
| { |
| // TODO: do that also as a data file plot. maPoints must |
| // then become polymorph, but WTF. |
| |
| // decompose into four lines |
| plot( B2DPoint(rRect.getMinX(), |
| rRect.getMinY()), |
| B2DPoint(rRect.getMaxX(), |
| rRect.getMinY()) ); |
| plot( B2DPoint(rRect.getMaxX(), |
| rRect.getMinY()), |
| B2DPoint(rRect.getMaxX(), |
| rRect.getMaxY()) ); |
| plot( B2DPoint(rRect.getMaxX(), |
| rRect.getMaxY()), |
| B2DPoint(rRect.getMinX(), |
| rRect.getMaxY()) ); |
| plot( B2DPoint(rRect.getMinX(), |
| rRect.getMaxY()), |
| B2DPoint(rRect.getMinX(), |
| rRect.getMinY()) ); |
| } |
| |
| void Plotter::plot( const B2DPoint& rStartPoint, const B2DPoint& rEndPoint ) |
| { |
| writeSeparator(); |
| mrOutputStream << "line(" << rStartPoint.getX() |
| << "," << rEndPoint.getX() |
| << ",t), " |
| << "line(" << rStartPoint.getY() |
| << "," << rEndPoint.getY() |
| << ",t)"; |
| } |
| |
| void Plotter::plot( const B2DCubicBezier& rCurve ) |
| { |
| writeSeparator(); |
| mrOutputStream << "cubicBezier(" << rCurve.getStartPoint().getX() |
| << "," << rCurve.getControlPointA().getX() |
| << "," << rCurve.getControlPointB().getX() |
| << "," << rCurve.getEndPoint().getX() |
| << ",t), " |
| << "cubicBezier(" << rCurve.getStartPoint().getY() |
| << "," << rCurve.getControlPointA().getY() |
| << "," << rCurve.getControlPointB().getY() |
| << "," << rCurve.getEndPoint().getY() |
| << ",t)"; |
| } |
| |
| void Plotter::writeSeparator() |
| { |
| if( mbFirstElement ) |
| { |
| mbFirstElement = false; |
| } |
| else |
| { |
| mrOutputStream << ", "; |
| } |
| } |
| |
| } |
| } |