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