27#include <com/sun/star/chart/DataLabelPlacement.hpp>
29#include <osl/diagnose.h>
39 , sal_Int32 nDimensionCount )
40 : VSeriesPlotter( xChartTypeModel, nDimensionCount, false )
41 , m_fMaxLogicBubbleSize( 0.0 )
42 , m_fBubbleSizeFactorToScreen( 1.0 )
45 assert(nDimensionCount == 2);
47 if( !m_pMainPosHelper )
48 m_pMainPosHelper =
new PlottingPositionHelper();
49 PlotterBase::m_pPosHelper = m_pMainPosHelper;
52BubbleChart::~BubbleChart()
54 delete m_pMainPosHelper;
57void BubbleChart::calculateMaximumLogicBubbleSize()
59 double fMaxSize = 0.0;
61 sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
64 for(
auto const& rZSlot : m_aZSlots )
66 for(
auto const& rXSlot : rZSlot )
68 for( std::unique_ptr<VDataSeries>
const & pSeries : rXSlot.m_aSeriesVector )
73 double fSize = pSeries->getBubble_Size(
nIndex );
74 if( fSize > fMaxSize )
81 m_fMaxLogicBubbleSize = fMaxSize;
84void BubbleChart::calculateBubbleSizeScalingFactor()
87 drawing::Position3D aSceneMinPos( m_pMainPosHelper->transformLogicToScene( m_pMainPosHelper->getLogicMinX(),m_pMainPosHelper->getLogicMinY(),fLogicZ,
false ) );
88 drawing::Position3D aSceneMaxPos( m_pMainPosHelper->transformLogicToScene( m_pMainPosHelper->getLogicMaxX(),m_pMainPosHelper->getLogicMaxY(),fLogicZ,
false ) );
90 awt::Point aScreenMinPos(
LabelPositionHelper(m_nDimension,m_xLogicTarget).transformSceneToScreenPosition( aSceneMinPos ) );
91 awt::Point aScreenMaxPos(
LabelPositionHelper(m_nDimension,m_xLogicTarget).transformSceneToScreenPosition( aSceneMaxPos ) );
93 sal_Int32 nWidth =
abs( aScreenMaxPos.X - aScreenMinPos.X );
94 sal_Int32 nHeight =
abs( aScreenMaxPos.Y - aScreenMinPos.Y );
96 sal_Int32 nMinExtend = std::min( nWidth, nHeight );
97 m_fBubbleSizeFactorToScreen = nMinExtend * 0.25;
100drawing::Direction3D BubbleChart::transformToScreenBubbleSize(
double fLogicSize )
102 drawing::Direction3D aRet(0,0,0);
104 if( std::isnan(fLogicSize) || std::isinf(fLogicSize) )
107 double fMaxSize = m_fMaxLogicBubbleSize;
109 double fMaxRadius = sqrt( fMaxSize / M_PI );
110 double fRadius = sqrt( fLogicSize / M_PI );
112 aRet.DirectionX = m_fBubbleSizeFactorToScreen * fRadius / fMaxRadius;
113 aRet.DirectionY = aRet.DirectionX;
118bool BubbleChart::isExpandIfValuesCloseToBorder( sal_Int32 )
123bool BubbleChart::isSeparateStackingForDifferentSigns( sal_Int32 )
130 return LegendSymbolStyle::Circle;
133drawing::Direction3D BubbleChart::getPreferredDiagramAspectRatio()
const
135 return drawing::Direction3D(-1,-1,-1);
143 FormerPoint(
double fX,
double fY,
double fZ )
147 :
m_fX(
std::numeric_limits<double>::quiet_NaN())
148 ,
m_fY(
std::numeric_limits<double>::quiet_NaN())
149 ,
m_fZ(
std::numeric_limits<double>::quiet_NaN())
160void BubbleChart::createShapes()
162 if( m_aZSlots.empty() )
165 OSL_ENSURE(m_xLogicTarget.is()&&m_xFinalTarget.is(),
"BubbleChart is not proper initialized");
166 if(!(m_xLogicTarget.is()&&m_xFinalTarget.is()))
175 double fLogicZ = 1.0;
177 sal_Int32
const nStartIndex = 0;
178 sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
183 std::map< VDataSeries*, FormerPoint > aSeriesFormerPointMap;
184 m_bPointsWereSkipped =
false;
185 sal_Int32 nSkippedPoints = 0;
186 sal_Int32 nCreatedPoints = 0;
188 calculateMaximumLogicBubbleSize();
189 calculateBubbleSizeScalingFactor();
190 if( m_fMaxLogicBubbleSize <= 0 || m_fBubbleSizeFactorToScreen <= 0 )
196 for(
auto const& rZSlot : m_aZSlots )
198 for(
auto const& rXSlot : rZSlot )
201 for( std::unique_ptr<VDataSeries>
const & pSeries : rXSlot.m_aSeriesVector )
206 bool bHasFillColorMapping = pSeries->hasPropertyMapping(
"FillColor");
207 bool bHasBorderColorMapping = pSeries->hasPropertyMapping(
"LineColor");
211 sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex();
213 = getPlottingPositionHelper(nAttachedAxisIndex);
214 m_pPosHelper = &rPosHelper;
217 double fLogicX = pSeries->getXValue(
nIndex);
218 double fLogicY = pSeries->getYValue(
nIndex);
219 double fBubbleSize = pSeries->getBubble_Size(
nIndex );
221 if( fBubbleSize<0.0 )
224 if( fBubbleSize == 0.0 || std::isnan(fBubbleSize) )
227 if( std::isnan(fLogicX) || std::isinf(fLogicX)
228 || std::isnan(fLogicY) || std::isinf(fLogicY) )
231 bool bIsVisible = rPosHelper.
isLogicVisible(fLogicX, fLogicY, fLogicZ);
233 drawing::Position3D aUnscaledLogicPosition( fLogicX, fLogicY, fLogicZ );
234 drawing::Position3D aScaledLogicPosition(aUnscaledLogicPosition);
238 drawing::Position3D aScenePosition(
242 FormerPoint aFormerPoint( aSeriesFormerPointMap[pSeries.get()] );
244 if (!pSeries->isAttributedDataPoint(
nIndex)
246 aFormerPoint.m_fX, aFormerPoint.m_fY, aFormerPoint.m_fZ,
247 aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY,
248 aScaledLogicPosition.PositionZ))
251 m_bPointsWereSkipped =
true;
254 aSeriesFormerPointMap[pSeries.get()] = FormerPoint(aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ);
261 OUString aPointCID = ObjectIdentifier::createPointCID(
262 pSeries->getPointCID_Stub(),
nIndex );
264 createGroupShape(xSeriesGroupShape_Shapes,aPointCID) );
270 drawing::Direction3D aSymbolSize = transformToScreenBubbleSize( fBubbleSize );
272 , aScenePosition, aSymbolSize );
274 PropertyMapper::setMappedProperties( *xShape
275 , pSeries->getPropertiesOfPoint(
nIndex )
276 , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
278 if(bHasFillColorMapping)
280 double nPropVal = pSeries->getValueByProperty(
nIndex,
"FillColor");
281 if(!std::isnan(nPropVal))
283 xShape->SvxShape::setPropertyValue(
"FillColor",
uno::Any(
static_cast<sal_Int32
>(nPropVal)));
286 if(bHasBorderColorMapping)
288 double nPropVal = pSeries->getValueByProperty(
nIndex,
"LineColor");
289 if(!std::isnan(nPropVal))
291 xShape->SvxShape::setPropertyValue(
"LineColor",
uno::Any(
static_cast<sal_Int32
>(nPropVal)));
298 if( pSeries->getDataPointLabelIfLabel(
nIndex) )
301 drawing::Position3D aScenePosition3D( aScenePosition.PositionX
302 , aScenePosition.PositionY
303 , aScenePosition.PositionZ+getTransformedDepth() );
305 sal_Int32 nLabelPlacement = pSeries->getLabelPlacement(
308 switch(nLabelPlacement)
310 case css::chart::DataLabelPlacement::TOP:
311 aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
314 case css::chart::DataLabelPlacement::BOTTOM:
315 aScenePosition3D.PositionY += (aSymbolSize.DirectionY/2+1);
318 case css::chart::DataLabelPlacement::LEFT:
319 aScenePosition3D.PositionX -= (aSymbolSize.DirectionX/2+1);
322 case css::chart::DataLabelPlacement::RIGHT:
323 aScenePosition3D.PositionX += (aSymbolSize.DirectionX/2+1);
326 case css::chart::DataLabelPlacement::CENTER:
330 OSL_FAIL(
"this label alignment is not implemented yet");
331 aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
337 .transformSceneToScreenPosition( aScenePosition3D ) );
338 sal_Int32 nOffset = 0;
341 createDataLabel( xTextTarget, *pSeries,
nIndex
342 , fBubbleSize, fBubbleSize, aScreenPosition2D, eAlignment, nOffset );
347 if(!xPointGroupShape_Shapes->getCount())
348 xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shapes);
356 "skipped points: " << nSkippedPoints <<
" created points: "
bool isSameForGivenResolution(double fX, double fY, double fZ, double fX2, double fY2, double fZ2)
void setCoordinateSystemResolution(const css::uno::Sequence< sal_Int32 > &rCoordinateSystemResolution)
bool isLogicVisible(double fX, double fY, double fZ) const
virtual css::drawing::Position3D transformLogicToScene(double fX, double fY, double fZ, bool bClip) const
void doLogicScaling(double *pX, double *pY, double *pZ) const
static void setShapeName(const rtl::Reference< SvxShape > &xShape, const OUString &rName)
#define SAL_INFO(area, stream)
SwNodeOffset abs(const SwNodeOffset &a)