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