Kaydet (Commit) 093fa2a3 authored tarafından Markus Mohrhard's avatar Markus Mohrhard Kaydeden (comit) Markus Mohrhard

use a direct method for pie segment crastion

Change-Id: I4b42ebe994b4e498acd32d08a063e4626b3c97d8
üst 82ed9053
......@@ -324,168 +324,6 @@ DummyCone::DummyCone(const drawing::Position3D& rPos, const drawing::Direction3D
setPosition(Position3DToAWTPoint(rPos));
setSize(Direction3DToAWTSize(rSize));
}
void appendAndCloseBezierCoords( drawing::PolyPolygonBezierCoords& rReturn, const drawing::PolyPolygonBezierCoords& rAdd, sal_Bool bAppendInverse )
{
if(!rAdd.Coordinates.getLength())
return;
sal_Int32 nAddCount = rAdd.Coordinates[0].getLength();
if(!nAddCount)
return;
sal_Int32 nOldCount = rReturn.Coordinates[0].getLength();
rReturn.Coordinates[0].realloc(nOldCount+nAddCount+1);
rReturn.Flags[0].realloc(nOldCount+nAddCount+1);
for(sal_Int32 nN=0;nN<nAddCount; nN++ )
{
sal_Int32 nAdd = bAppendInverse ? (nAddCount-1-nN) : nN;
rReturn.Coordinates[0][nOldCount+nN] = rAdd.Coordinates[0][nAdd];
rReturn.Flags[0][nOldCount+nN] = rAdd.Flags[0][nAdd];
}
//close
rReturn.Coordinates[0][nOldCount+nAddCount] = rReturn.Coordinates[0][0];
rReturn.Flags[0][nOldCount+nAddCount] = rReturn.Flags[0][0];
}
drawing::PolyPolygonBezierCoords getCircularArcBezierCoords(
double fStartAngleRadian, double fWidthAngleRadian, double fUnitRadius
, const ::basegfx::B2DHomMatrix& rTransformationFromUnitCircle
, const double fAngleSubdivisionRadian )
{
//at least one polygon is created using two normal and two control points
//if the angle is larger it is separated into multiple sub angles
drawing::PolyPolygonBezierCoords aReturn = drawing::PolyPolygonBezierCoords();
sal_Int32 nSegmentCount = static_cast< sal_Int32 >( fWidthAngleRadian/fAngleSubdivisionRadian );
if( fWidthAngleRadian > fAngleSubdivisionRadian*nSegmentCount )
nSegmentCount++;
double fFirstSegmentAngle = fAngleSubdivisionRadian;
double fLastSegmentAngle = fAngleSubdivisionRadian;
if(nSegmentCount==1)
{
fFirstSegmentAngle = fWidthAngleRadian;
fLastSegmentAngle = 0.0;
}
else
{
double fFirstAngleOnSubDevision = (static_cast<sal_Int32>(fStartAngleRadian/fAngleSubdivisionRadian)+1)*fAngleSubdivisionRadian;
if( !::rtl::math::approxEqual( fStartAngleRadian, fFirstAngleOnSubDevision ) )
fFirstSegmentAngle = fFirstAngleOnSubDevision-fStartAngleRadian;
if(nSegmentCount>1)
{
fLastSegmentAngle = fWidthAngleRadian-fFirstSegmentAngle-fAngleSubdivisionRadian*(nSegmentCount-2);
if( fLastSegmentAngle<0 )
nSegmentCount--;
if( fLastSegmentAngle>fAngleSubdivisionRadian )
{
fLastSegmentAngle-=fAngleSubdivisionRadian;
nSegmentCount++;
}
}
}
sal_Int32 nPointCount = 1 + 3*nSegmentCount; //first point of next segment equals last point of former segment
aReturn.Coordinates = drawing::PointSequenceSequence(1);
aReturn.Flags = drawing::FlagSequenceSequence(1);
drawing::PointSequence aPoints(nPointCount);
drawing::FlagSequence aFlags(nPointCount);
//
//!! applying matrix to vector does ignore translation, so it is important to use a B2DPoint here instead of B2DVector
::basegfx::B2DPoint P0,P1,P2,P3;
sal_Int32 nPoint=0;
double fCurrentRotateAngle = fStartAngleRadian;
for(sal_Int32 nSegment=0; nSegment<nSegmentCount; nSegment++)
{
double fCurrentSegmentAngle = fAngleSubdivisionRadian;
if(nSegment==0)//first segment gets only a smaller peace until the next subdevision
fCurrentSegmentAngle = fFirstSegmentAngle;
else if(nSegment==(nSegmentCount-1)) //the last segment gets the rest angle that does not fit into equal pieces
fCurrentSegmentAngle = fLastSegmentAngle;
//first create untransformed points for a unit circle arc:
const double fCos = cos(fCurrentSegmentAngle/2.0);
const double fSin = sin(fCurrentSegmentAngle/2.0);
P0.setX(fCos);
P3.setX(fCos);
P0.setY(-fSin);
P3.setY(-P0.getY());
P1.setX((4.0-fCos)/3.0);
P2.setX(P1.getX());
P1.setY((1.0-fCos)*(fCos-3.0)/(3.0*fSin));
P2.setY(-P1.getY());
//transform thus startangle equals NULL
::basegfx::B2DHomMatrix aStart;
aStart.rotate(fCurrentSegmentAngle/2.0 + fCurrentRotateAngle );
fCurrentRotateAngle+=fCurrentSegmentAngle;
aStart.scale( fUnitRadius, fUnitRadius );
//apply given transformation to get final points
P0 = rTransformationFromUnitCircle*(aStart*P0);
P1 = rTransformationFromUnitCircle*(aStart*P1);
P2 = rTransformationFromUnitCircle*(aStart*P2);
P3 = rTransformationFromUnitCircle*(aStart*P3);
aPoints[nPoint].X = static_cast< sal_Int32 >( P0.getX());
aPoints[nPoint].Y = static_cast< sal_Int32 >( P0.getY());
aFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
aPoints[nPoint].X = static_cast< sal_Int32 >( P1.getX());
aPoints[nPoint].Y = static_cast< sal_Int32 >( P1.getY());
aFlags[nPoint++] = drawing::PolygonFlags_CONTROL;
aPoints[nPoint].X = static_cast< sal_Int32 >( P2.getX());
aPoints[nPoint].Y = static_cast< sal_Int32 >( P2.getY());
aFlags [nPoint++] = drawing::PolygonFlags_CONTROL;
if(nSegment==(nSegmentCount-1))
{
aPoints[nPoint].X = static_cast< sal_Int32 >( P3.getX());
aPoints[nPoint].Y = static_cast< sal_Int32 >( P3.getY());
aFlags [nPoint++] = drawing::PolygonFlags_NORMAL;
}
}
aReturn.Coordinates[0] = aPoints;
aReturn.Flags[0] = aFlags;
return aReturn;
}
drawing::PolyPolygonBezierCoords getRingBezierCoords(
double fUnitCircleInnerRadius
, double fUnitCircleOuterRadius
, double fStartAngleRadian, double fWidthAngleRadian
, ::basegfx::B2DHomMatrix aTransformationFromUnitCircle
, const double fAngleSubdivisionRadian )
{
drawing::PolyPolygonBezierCoords aReturn = drawing::PolyPolygonBezierCoords();
aReturn.Coordinates = drawing::PointSequenceSequence(1);
aReturn.Flags = drawing::FlagSequenceSequence(1);
drawing::PolyPolygonBezierCoords aOuterArc = getCircularArcBezierCoords(
fStartAngleRadian, fWidthAngleRadian, fUnitCircleOuterRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
aReturn.Coordinates[0] = aOuterArc.Coordinates[0];
aReturn.Flags[0] = aOuterArc.Flags[0];
drawing::PolyPolygonBezierCoords aInnerArc = getCircularArcBezierCoords(
fStartAngleRadian, fWidthAngleRadian, fUnitCircleInnerRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
appendAndCloseBezierCoords( aReturn, aInnerArc, sal_True );
return aReturn;
}
DummyPieSegment2D::DummyPieSegment2D(double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree,
double fUnitCircleInnerRadius, double fUnitCircleOuterRadius,
......@@ -506,21 +344,9 @@ void DummyPieSegment2D::render()
mfUnitCircleWidthAngleDegree -= 360.0;
while(mfUnitCircleWidthAngleDegree<0)
mfUnitCircleWidthAngleDegree += 360.0;
::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(maUnitCircleToScene) ) );
aTransformationFromUnitCircle.translate(maOffset.DirectionX,maOffset.DirectionY);
const double fAngleSubdivisionRadian = F_PI/30.0;
drawing::PolyPolygonBezierCoords aCoords = getRingBezierCoords(
mfUnitCircleInnerRadius, mfUnitCircleOuterRadius
, mfUnitCircleStartAngleDegree*F_PI/180.0, mfUnitCircleWidthAngleDegree*F_PI/180.0
, aTransformationFromUnitCircle, fAngleSubdivisionRadian );
sal_Int32 pointCount = aCoords.Coordinates[0].getLength();
for (sal_Int32 i = 0; i < pointCount; i++)
{
com::sun::star::awt::Point p = aCoords.Coordinates[0][i];
pChart->m_GLRender.SetPieSegment2DShapePoint((float)p.X, (float)p.Y, pointCount);
}
pChart->m_GLRender.GeneratePieSegment2D(mfUnitCircleInnerRadius, mfUnitCircleOuterRadius,
mfUnitCircleStartAngleDegree, mfUnitCircleWidthAngleDegree);
std::map<OUString, uno::Any>::const_iterator itr = maProperties.find(UNO_NAME_FILLCOLOR);
if(itr != maProperties.end())
......@@ -528,14 +354,17 @@ void DummyPieSegment2D::render()
sal_Int32 nColor = itr->second.get<sal_Int32>();
pChart->m_GLRender.SetColor(nColor);
}
/*
itr = maProperties.find(UNO_NAME_FILL_TRANSPARENCE);
if(itr != maProperties.end())
{
sal_Int32 transparency = itr->second.get<sal_Int32>();
pChart->m_GLRender.SetTransparency(transparency&(0xFF));
}
*/
pChart->m_GLRender.RenderPieSegment2DShape();
float nSize = std::max<float>(maUnitCircleToScene.Line1.Column1, maUnitCircleToScene.Line2.Column2);
pChart->m_GLRender.RenderPieSegment2DShape(nSize, maUnitCircleToScene.Line1.Column4, maUnitCircleToScene.Line2.Column4);
}
......
......@@ -1726,32 +1726,51 @@ void OpenGLRender::SetChartTransparencyGradient(long transparencyGradient)
m_BackgroundColor[15] = 0.0;
}
}
int OpenGLRender::SetPieSegment2DShapePoint(float x, float y, int listLength)
void OpenGLRender::GeneratePieSegment2D(double fInnerRadius, double fOutterRadius, double nAngleStart, double nAngleWidth)
{
if (m_PieSegment2DPointList.empty())
double nAngleStep = 1;
PieSegment2DPointList aPointList;
// TODO: moggi: GL_TRIANGLE_FAN seems not to work
bool bInnerRadiusNotZero = true; //!rtl::math::approxEqual(0.0, fInnerRadius);
size_t nVectorSize = 3*(nAngleWidth/nAngleStep);
if(bInnerRadiusNotZero)
nVectorSize *= 2;
aPointList.reserve(nVectorSize);
// if inner radius = 0 generate a normal pie segment (triangle fan)
// if inner radius != 0 generate a pie segment - inner pie (triangle strip)
if(!bInnerRadiusNotZero)
{
m_PieSegment2DPointList.reserve(listLength);
aPointList.push_back(0);
aPointList.push_back(0);
aPointList.push_back(m_fZStep);
}
float actualX = (x / OPENGL_SCALE_VALUE);
float actualY = (y / OPENGL_SCALE_VALUE);
m_PieSegment2DPointList.push_back(actualX);
m_PieSegment2DPointList.push_back(actualY);
m_PieSegment2DPointList.push_back(m_fZStep);
if (m_PieSegment2DPointList.size() == size_t(listLength * 3))
for(double nAngle = nAngleStart; nAngle <= nAngleStart + nAngleWidth; nAngle += nAngleStep)
{
m_PieSegment2DShapePointList.push_back(m_PieSegment2DPointList);
m_PieSegment2DPointList.clear();
float xVal = sin(nAngle/360*2*GL_PI);
float yVal = cos(nAngle/360*2*GL_PI);
aPointList.push_back(fOutterRadius * xVal);
aPointList.push_back(fOutterRadius * yVal);
aPointList.push_back(m_fZStep);
if(bInnerRadiusNotZero)
{
aPointList.push_back(fInnerRadius * xVal);
aPointList.push_back(fInnerRadius * yVal);
aPointList.push_back(m_fZStep);
}
}
return 0;
m_PieSegment2DShapePointList.push_back(aPointList);
}
int OpenGLRender::RenderPieSegment2DShape()
int OpenGLRender::RenderPieSegment2DShape(float fSize, float fPosX, float fPosY)
{
int listNum = m_PieSegment2DShapePointList.size();
PosVecf3 trans = {0.0f, 0.0f, 0.0f};
PosVecf3 trans = {fPosX/OPENGL_SCALE_VALUE, fPosY/OPENGL_SCALE_VALUE, 0.0f};
PosVecf3 angle = {0.0f, 0.0f, 0.0f};
PosVecf3 scale = {1.0f, 1.0f, 1.0f};
PosVecf3 scale = {fSize/OPENGL_SCALE_VALUE, fSize/OPENGL_SCALE_VALUE, 1.0f};
MoveModelf(trans, angle, scale);
m_MVP = m_Projection * m_View * m_Model;
......@@ -1779,10 +1798,11 @@ int OpenGLRender::RenderPieSegment2DShape()
0, // stride
(void*)0 // array buffer offset
);
glDrawArrays(GL_POLYGON, 0, pointList.size() / 3); // 12*3 indices starting at 0 -> 12 triangles
glDrawArrays(GL_TRIANGLE_STRIP, 0, pointList.size() / 3); // 12*3 indices starting at 0 -> 12 triangles
glDisableVertexAttribArray(m_2DVertexID);
glUseProgram(0);
m_PieSegment2DShapePointList.pop_back();
CHECK_GL_ERROR();
}
glEnable(GL_MULTISAMPLE);
......
......@@ -176,8 +176,8 @@ public:
int RenderArea2DShape();
void SetChartTransparencyGradient(long transparencyGradient);
int SetPieSegment2DShapePoint(float x, float y, int listLength);
int RenderPieSegment2DShape();
void GeneratePieSegment2D(double, double, double, double);
int RenderPieSegment2DShape(float, float, float);
#if DEBUG_POSITIONING
void renderDebug();
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment