xref: /trunk/main/basegfx/test/testtools.cxx (revision 09dbbe93)
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