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_chart2.hxx"
30 #include "VCartesianGrid.hxx"
31 #include "Tickmarks.hxx"
32 #include "PlottingPositionHelper.hxx"
33 #include "ShapeFactory.hxx"
34 #include "ObjectIdentifier.hxx"
35 #include "macros.hxx"
36 #include "CommonConverters.hxx"
37 #include "AxisHelper.hxx"
38 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
39 #include <com/sun/star/drawing/LineStyle.hpp>
40 
41 #include <vector>
42 #include <memory>
43 
44 //.............................................................................
45 namespace chart
46 {
47 //.............................................................................
48 using namespace ::com::sun::star;
49 using namespace ::com::sun::star::chart2;
50 using ::com::sun::star::uno::Reference;
51 using ::com::sun::star::uno::Sequence;
52 
53 struct GridLinePoints
54 {
55     Sequence< double > P0;
56     Sequence< double > P1;
57     Sequence< double > P2;
58 
59     GridLinePoints( const PlottingPositionHelper* pPosHelper, sal_Int32 nDimensionIndex
60         , CuboidPlanePosition eLeftWallPos=CuboidPlanePosition_Left
61         , CuboidPlanePosition eBackWallPos=CuboidPlanePosition_Back
62         , CuboidPlanePosition eBottomPos=CuboidPlanePosition_Bottom );
63     void update( double fScaledTickValue );
64 
65     sal_Int32 m_nDimensionIndex;
66 };
67 
68 GridLinePoints::GridLinePoints( const PlottingPositionHelper* pPosHelper, sal_Int32 nDimensionIndex
69                 , CuboidPlanePosition eLeftWallPos
70                 , CuboidPlanePosition eBackWallPos
71                 , CuboidPlanePosition eBottomPos )
72                 : m_nDimensionIndex(nDimensionIndex)
73 {
74     double MinX = pPosHelper->getLogicMinX();
75     double MinY = pPosHelper->getLogicMinY();
76     double MinZ = pPosHelper->getLogicMinZ();
77     double MaxX = pPosHelper->getLogicMaxX();
78     double MaxY = pPosHelper->getLogicMaxY();
79     double MaxZ = pPosHelper->getLogicMaxZ();
80 
81     pPosHelper->doLogicScaling( &MinX,&MinY,&MinZ );
82     pPosHelper->doLogicScaling( &MaxX,&MaxY,&MaxZ );
83 
84     if(!pPosHelper->isMathematicalOrientationX())
85     {
86         double fHelp = MinX;
87         MinX = MaxX;
88         MaxX = fHelp;
89     }
90     if(!pPosHelper->isMathematicalOrientationY())
91     {
92         double fHelp = MinY;
93         MinY = MaxY;
94         MaxY = fHelp;
95     }
96     if(pPosHelper->isMathematicalOrientationZ())//z axis in draw is reverse to mathematical
97     {
98         double fHelp = MinZ;
99         MinZ = MaxZ;
100         MaxZ = fHelp;
101     }
102     bool bSwapXY = pPosHelper->isSwapXAndY();
103 
104     P0.realloc(3);
105     P1.realloc(3);
106     P2.realloc(3);
107 
108     //P0: point on 'back' wall, not on 'left' wall
109     //P1: point on both walls
110     //P2: point on 'left' wall not on 'back' wall
111 
112     P0[0]=P1[0]=P2[0]= (CuboidPlanePosition_Left == eLeftWallPos || bSwapXY) ? MinX : MaxX;
113     P0[1]=P1[1]=P2[1]= (CuboidPlanePosition_Left == eLeftWallPos || !bSwapXY) ? MinY : MaxY;
114     P0[2]=P1[2]=P2[2]= (CuboidPlanePosition_Back == eBackWallPos) ? MinZ : MaxZ;
115 
116     if(m_nDimensionIndex==0)
117     {
118         P0[1]= (CuboidPlanePosition_Left == eLeftWallPos || !bSwapXY) ? MaxY : MinY;
119         P2[2]= (CuboidPlanePosition_Back == eBackWallPos) ? MaxZ : MinZ;
120         if( CuboidPlanePosition_Bottom != eBottomPos && !bSwapXY )
121             P2=P1;
122     }
123     else if(m_nDimensionIndex==1)
124     {
125         P0[0]= (CuboidPlanePosition_Left == eLeftWallPos || bSwapXY) ? MaxX : MinX;
126         P2[2]= (CuboidPlanePosition_Back == eBackWallPos) ? MaxZ : MinZ;
127         if( CuboidPlanePosition_Bottom != eBottomPos && bSwapXY )
128             P2=P1;
129     }
130     else if(m_nDimensionIndex==2)
131     {
132         P0[0]= (CuboidPlanePosition_Left == eLeftWallPos || bSwapXY) ? MaxX : MinX;
133         P2[1]= (CuboidPlanePosition_Left == eLeftWallPos || !bSwapXY) ? MaxY : MinY;
134         if( CuboidPlanePosition_Bottom != eBottomPos )
135         {
136             if( !bSwapXY )
137                 P0=P1;
138             else
139                 P2=P1;
140         }
141     }
142 }
143 
144 void GridLinePoints::update( double fScaledTickValue )
145 {
146     P0[m_nDimensionIndex] = P1[m_nDimensionIndex] = P2[m_nDimensionIndex] = fScaledTickValue;
147 }
148 
149 void addLine2D( drawing::PointSequenceSequence& rPoints, sal_Int32 nIndex
150              , const GridLinePoints& rScaledLogicPoints
151              , const Reference< XTransformation > & xTransformation
152               )
153 {
154     drawing::Position3D aPA = SequenceToPosition3D( xTransformation->transform( rScaledLogicPoints.P0 ) );
155     drawing::Position3D aPB = SequenceToPosition3D( xTransformation->transform( rScaledLogicPoints.P1 ) );
156 
157     rPoints[nIndex].realloc(2);
158     rPoints[nIndex][0].X = static_cast<sal_Int32>(aPA.PositionX);
159     rPoints[nIndex][0].Y = static_cast<sal_Int32>(aPA.PositionY);
160     rPoints[nIndex][1].X = static_cast<sal_Int32>(aPB.PositionX);
161     rPoints[nIndex][1].Y = static_cast<sal_Int32>(aPB.PositionY);
162 }
163 
164 void addLine3D( drawing::PolyPolygonShape3D& rPoints, sal_Int32 nIndex
165             , const GridLinePoints& rBasePoints
166             , const Reference< XTransformation > & xTransformation )
167 {
168     drawing::Position3D aPoint = SequenceToPosition3D( xTransformation->transform( rBasePoints.P0 ) );
169     AddPointToPoly( rPoints, aPoint, nIndex );
170     aPoint = SequenceToPosition3D( xTransformation->transform( rBasePoints.P1 ) );
171     AddPointToPoly( rPoints, aPoint, nIndex );
172     aPoint = SequenceToPosition3D( xTransformation->transform( rBasePoints.P2 ) );
173     AddPointToPoly( rPoints, aPoint, nIndex );
174 }
175 
176 //---------------------------------------------------------------------------------
177 //---------------------------------------------------------------------------------
178 //---------------------------------------------------------------------------------
179 //---------------------------------------------------------------------------------
180 
181 VCartesianGrid::VCartesianGrid( sal_Int32 nDimensionIndex, sal_Int32 nDimensionCount
182                                , const Sequence< Reference< beans::XPropertySet > > & rGridPropertiesList )
183             : VAxisOrGridBase( nDimensionIndex, nDimensionCount )
184             , m_aGridPropertiesList( rGridPropertiesList )
185 {
186     m_pPosHelper = new PlottingPositionHelper();
187 }
188 
189 VCartesianGrid::~VCartesianGrid()
190 {
191     delete m_pPosHelper;
192     m_pPosHelper = NULL;
193 }
194 
195 void VCartesianGrid::fillLinePropertiesFromGridModel( ::std::vector<VLineProperties>& rLinePropertiesList
196                                      , const Sequence< Reference< beans::XPropertySet > > & rGridPropertiesList )
197 {
198     rLinePropertiesList.clear();
199     if( !rGridPropertiesList.getLength() )
200         return;
201 
202     VLineProperties aLineProperties;
203     for( sal_Int32 nN=0; nN < rGridPropertiesList.getLength(); nN++ )
204     {
205         if(!AxisHelper::isGridVisible( rGridPropertiesList[nN] ))
206             aLineProperties.LineStyle = uno::makeAny( drawing::LineStyle_NONE );
207         else
208             aLineProperties.initFromPropertySet( rGridPropertiesList[nN] );
209         rLinePropertiesList.push_back(aLineProperties);
210     }
211 };
212 
213 void VCartesianGrid::createShapes()
214 {
215     if(!m_aGridPropertiesList.getLength())
216         return;
217     //somehow equal to axis tickmarks
218 
219     //-----------------------------------------
220     //create named group shape
221     Reference< drawing::XShapes > xGroupShape_Shapes(
222         this->createGroupShape( m_xLogicTarget, m_aCID ) );
223 
224     if(!xGroupShape_Shapes.is())
225         return;
226     //-----------------------------------------
227 
228     ::std::vector<VLineProperties> aLinePropertiesList;
229     fillLinePropertiesFromGridModel( aLinePropertiesList, m_aGridPropertiesList );
230 
231     //-----------------------------------------
232     //create all scaled tickmark values
233     std::auto_ptr< TickFactory > apTickFactory( this->createTickFactory() );
234     TickFactory& aTickFactory = *apTickFactory.get();
235     ::std::vector< ::std::vector< TickInfo > > aAllTickInfos;
236     aTickFactory.getAllTicks( aAllTickInfos );
237 
238     //-----------------------------------------
239     //create tick mark line shapes
240     ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter             = aAllTickInfos.begin();
241     const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd  = aAllTickInfos.end();
242 
243     if(aDepthIter == aDepthEnd)//no tickmarks at all
244         return;
245 
246 
247     sal_Int32 nLinePropertiesCount = aLinePropertiesList.size();
248     for( sal_Int32 nDepth=0
249         ; aDepthIter != aDepthEnd && nDepth < nLinePropertiesCount
250         ; aDepthIter++, nDepth++ )
251     {
252         if( !aLinePropertiesList[nDepth].isLineVisible() )
253             continue;
254 
255         Reference< drawing::XShapes > xTarget( xGroupShape_Shapes );
256         if( nDepth > 0 )
257         {
258             xTarget.set( this->createGroupShape( m_xLogicTarget
259                 , ObjectIdentifier::addChildParticle( m_aCID, ObjectIdentifier::createChildParticleWithIndex( OBJECTTYPE_SUBGRID, nDepth-1 ) )
260                 ) );
261             if(!xTarget.is())
262                 xTarget.set( xGroupShape_Shapes );
263         }
264 
265         if(2==m_nDimension)
266         {
267 
268             GridLinePoints aGridLinePoints( m_pPosHelper, m_nDimensionIndex );
269 
270             sal_Int32 nPointCount = (*aDepthIter).size();
271             drawing::PointSequenceSequence aPoints(nPointCount);
272 
273             ::std::vector< TickInfo >::const_iterator       aTickIter = (*aDepthIter).begin();
274             const ::std::vector< TickInfo >::const_iterator aTickEnd  = (*aDepthIter).end();
275             sal_Int32 nRealPointCount = 0;
276             for( ; aTickIter != aTickEnd; aTickIter++ )
277             {
278                 if( !(*aTickIter).bPaintIt )
279                     continue;
280                 aGridLinePoints.update( (*aTickIter).fScaledTickValue );
281                 addLine2D( aPoints, nRealPointCount, aGridLinePoints, m_pPosHelper->getTransformationScaledLogicToScene() );
282                 nRealPointCount++;
283             }
284             aPoints.realloc(nRealPointCount);
285             m_pShapeFactory->createLine2D( xTarget, aPoints, &aLinePropertiesList[nDepth] );
286 
287             //prepare polygon for handle shape:
288             drawing::PointSequenceSequence aHandlesPoints(1);
289             sal_Int32 nOldHandleCount = aHandlesPoints[0].getLength();
290             aHandlesPoints[0].realloc(nOldHandleCount+nRealPointCount);
291             for( sal_Int32 nN = 0; nN<nRealPointCount; nN++)
292                 aHandlesPoints[0][nOldHandleCount+nN] = aPoints[nN][1];
293 
294             //create handle shape:
295             VLineProperties aHandleLineProperties;
296             aHandleLineProperties.LineStyle    = uno::makeAny( drawing::LineStyle_NONE );
297             Reference< drawing::XShape > xHandleShape =
298                 m_pShapeFactory->createLine2D( xTarget, aHandlesPoints, &aHandleLineProperties );
299             m_pShapeFactory->setShapeName( xHandleShape, C2U("HandlesOnly") );
300         }
301         //-----------------------------------------
302         else //if(2!=m_nDimension)
303         {
304             GridLinePoints aGridLinePoints( m_pPosHelper, m_nDimensionIndex, m_eLeftWallPos, m_eBackWallPos, m_eBottomPos );
305 
306             sal_Int32 nPointCount = (*aDepthIter).size();
307             drawing::PolyPolygonShape3D aPoints;
308             aPoints.SequenceX.realloc(nPointCount);
309             aPoints.SequenceY.realloc(nPointCount);
310             aPoints.SequenceZ.realloc(nPointCount);
311 
312             ::std::vector< TickInfo >::const_iterator       aTickIter = (*aDepthIter).begin();
313             const ::std::vector< TickInfo >::const_iterator aTickEnd  = (*aDepthIter).end();
314             sal_Int32 nRealPointCount = 0;
315             sal_Int32 nPolyIndex = 0;
316             for( ; aTickIter != aTickEnd; aTickIter++, nPolyIndex++ )
317             {
318                 if( !(*aTickIter).bPaintIt )
319                     continue;
320 
321                 aGridLinePoints.update( (*aTickIter).fScaledTickValue );
322                 addLine3D( aPoints, nPolyIndex, aGridLinePoints, m_pPosHelper->getTransformationScaledLogicToScene() );
323                 nRealPointCount+=3;
324             }
325             aPoints.SequenceX.realloc(nRealPointCount);
326             aPoints.SequenceY.realloc(nRealPointCount);
327             aPoints.SequenceZ.realloc(nRealPointCount);
328             m_pShapeFactory->createLine3D( xTarget, aPoints, aLinePropertiesList[nDepth] );
329         }
330     }
331 }
332 
333 //.............................................................................
334 } //namespace chart
335 //.............................................................................
336