1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_basegfx.hxx" 26 27 #include "testtools.hxx" 28 29 #include <basegfx/point/b2dpoint.hxx> 30 #include <basegfx/vector/b2dvector.hxx> 31 #include <basegfx/range/b2drange.hxx> 32 #include <basegfx/curve/b2dcubicbezier.hxx> 33 #include <basegfx/polygon/b2dpolygon.hxx> 34 #include <basegfx/polygon/b2dpolypolygon.hxx> 35 36 #include <algorithm> 37 38 39 namespace basegfx 40 { 41 namespace testtools 42 { Plotter(::std::ostream & rOutputStream)43 Plotter::Plotter( ::std::ostream& rOutputStream ) : 44 mrOutputStream(rOutputStream), 45 maPoints(), 46 mbFirstElement( true ) 47 { 48 // output gnuplot setup. We switch gnuplot to parametric 49 // mode, therefore every plot has at least _two_ 50 // functions: one for the x and one for the y value, both 51 // depending on t. 52 mrOutputStream << "#!/usr/bin/gnuplot -persist" << ::std::endl 53 << "#" << ::std::endl 54 << "# automatically generated by basegfx::testtools::Plotter, don't change!" << ::std::endl 55 << "#" << ::std::endl 56 << "set parametric" << ::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 63 // This function plots the derivative of a cubic 64 // bezier curve. P,q,r,s are the control point 65 // components of the _original_ curve 66 << "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 67 68 // Plot a line's x component of a line in implicit 69 // form ax + by + c = 0 70 << "implicitLineX(a,b,c,t) = a*-c + t*-b" << ::std::endl 71 72 // Plot a line's y component of a line in implicit 73 // form ax + by + c = 0 74 << "implicitLineY(a,b,c,t) = b*-c + t*a" << ::std::endl 75 76 // Plot a line's component of a line between a and b 77 // (where a and b should be the corresponding 78 // components of the line's start and end point, 79 // respectively) 80 << "line(a,b,t) = a*(1-t) + b*t" << ::std::endl << ::std::endl 81 << "# end of setup" << ::std::endl << ::std::endl 82 83 // Start the actual plot line 84 << "plot [t=0:1] "; 85 } 86 87 namespace 88 { 89 class PointWriter 90 { 91 public: PointWriter(::std::ostream & rOutputStream)92 PointWriter( ::std::ostream& rOutputStream ) : 93 mrOutputStream( rOutputStream ) 94 { 95 } 96 operator ()(const B2DPoint & rPoint) const97 void operator()( const B2DPoint& rPoint ) const 98 { 99 mrOutputStream << rPoint.getX() << "\t" << rPoint.getY() << ::std::endl; 100 mrOutputStream << "e" << ::std::endl; 101 } 102 103 private: 104 ::std::ostream& mrOutputStream; 105 }; 106 } 107 ~Plotter()108 Plotter::~Plotter() 109 { 110 // End the plot line 111 mrOutputStream << ::std::endl; 112 113 // write stored data points. Cannot write before, since 114 // this is an inline dataset, which must be after the plot <...> 115 // line 116 ::std::for_each( maPoints.begin(), maPoints.end(), PointWriter(mrOutputStream) ); 117 } 118 plot(const B2DPolygon & rPoly)119 void Plotter::plot( const B2DPolygon& rPoly ) 120 { 121 const sal_uInt32 pointCount( rPoly.count() ); 122 123 if( pointCount < 1 ) 124 return; 125 126 if( pointCount == 1 ) 127 { 128 plot( rPoly.getB2DPoint(0) ); 129 return; 130 } 131 132 sal_uInt32 i; 133 for( i=0; i<pointCount-1; ++i ) 134 { 135 if(rPoly.isNextControlPointUsed(i) || rPoly.isPrevControlPointUsed(i + 1)) 136 { 137 const B2DCubicBezier aBezierPlot( 138 rPoly.getB2DPoint(i), rPoly.getNextControlPoint(i), 139 rPoly.getPrevControlPoint(i + 1), rPoly.getB2DPoint(i + 1)); 140 141 plot(aBezierPlot); 142 } 143 else 144 { 145 plot( rPoly.getB2DPoint(i), rPoly.getB2DPoint(i+1) ); 146 } 147 } 148 } 149 plot(const B2DPolyPolygon & rPolyPoly)150 void Plotter::plot( const B2DPolyPolygon& rPolyPoly ) 151 { 152 const sal_uInt32 nPolyCount( rPolyPoly.count() ); 153 154 sal_uInt32 i; 155 for( i=0; i<nPolyCount; ++i ) 156 { 157 plot( rPolyPoly.getB2DPolygon(i) ); 158 } 159 } 160 plot(const B2DPoint & rPoint)161 void Plotter::plot( const B2DPoint& rPoint ) 162 { 163 maPoints.push_back( rPoint ); 164 writeSeparator(); 165 mrOutputStream << "'-' using ($1):($2) title \"Point " << maPoints.size() << "\" with points"; 166 } 167 plot(const B2DRange & rRect)168 void Plotter::plot( const B2DRange& rRect ) 169 { 170 // TODO: do that also as a data file plot. maPoints must 171 // then become polymorph, but WTF. 172 173 // decompose into four lines 174 plot( B2DPoint(rRect.getMinX(), 175 rRect.getMinY()), 176 B2DPoint(rRect.getMaxX(), 177 rRect.getMinY()) ); 178 plot( B2DPoint(rRect.getMaxX(), 179 rRect.getMinY()), 180 B2DPoint(rRect.getMaxX(), 181 rRect.getMaxY()) ); 182 plot( B2DPoint(rRect.getMaxX(), 183 rRect.getMaxY()), 184 B2DPoint(rRect.getMinX(), 185 rRect.getMaxY()) ); 186 plot( B2DPoint(rRect.getMinX(), 187 rRect.getMaxY()), 188 B2DPoint(rRect.getMinX(), 189 rRect.getMinY()) ); 190 } 191 plot(const B2DPoint & rStartPoint,const B2DPoint & rEndPoint)192 void Plotter::plot( const B2DPoint& rStartPoint, const B2DPoint& rEndPoint ) 193 { 194 writeSeparator(); 195 mrOutputStream << "line(" << rStartPoint.getX() 196 << "," << rEndPoint.getX() 197 << ",t), " 198 << "line(" << rStartPoint.getY() 199 << "," << rEndPoint.getY() 200 << ",t)"; 201 } 202 plot(const B2DCubicBezier & rCurve)203 void Plotter::plot( const B2DCubicBezier& rCurve ) 204 { 205 writeSeparator(); 206 mrOutputStream << "cubicBezier(" << rCurve.getStartPoint().getX() 207 << "," << rCurve.getControlPointA().getX() 208 << "," << rCurve.getControlPointB().getX() 209 << "," << rCurve.getEndPoint().getX() 210 << ",t), " 211 << "cubicBezier(" << rCurve.getStartPoint().getY() 212 << "," << rCurve.getControlPointA().getY() 213 << "," << rCurve.getControlPointB().getY() 214 << "," << rCurve.getEndPoint().getY() 215 << ",t)"; 216 } 217 writeSeparator()218 void Plotter::writeSeparator() 219 { 220 if( mbFirstElement ) 221 { 222 mbFirstElement = false; 223 } 224 else 225 { 226 mrOutputStream << ", "; 227 } 228 } 229 230 } 231 } 232