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