mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 14:00:32 +08:00
191 lines
5.5 KiB
C++
191 lines
5.5 KiB
C++
#include "stdafx.h"
|
|
|
|
#include <string.h>
|
|
#include "MemoryUtils.h"
|
|
#include "..\VectorGraphics\SErrorCodes.h"
|
|
#include "GraphicsPath.h"
|
|
#include "..\VectorGraphics\SMathExt.h"
|
|
|
|
|
|
CGraphicsPath::CGraphicsPath() : SPath()
|
|
{
|
|
m_bStartSubPath = false;
|
|
m_lMode = 0;
|
|
}
|
|
CGraphicsPath::CGraphicsPath(const CGraphicsPath &oSrc) : SPath((SPath*)&oSrc)
|
|
{
|
|
m_bStartSubPath = oSrc.m_bStartSubPath;
|
|
m_lMode = oSrc.m_lMode;
|
|
}
|
|
CGraphicsPath& CGraphicsPath::operator=(const CGraphicsPath& oSrc)
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
CGraphicsPath::~CGraphicsPath()
|
|
{
|
|
}
|
|
|
|
|
|
// ------------------------------------------------
|
|
int CGraphicsPath::EllipseArc(double fX, double fY, double fXRad, double fYRad, double fAngle1, double fAngle2, BOOL bClockDirection)
|
|
{
|
|
int nRet = 0;
|
|
|
|
while ( fAngle1 < 0 )
|
|
fAngle1 += 360;
|
|
|
|
while ( fAngle1 > 360 )
|
|
fAngle1 -= 360;
|
|
|
|
while ( fAngle2 < 0 )
|
|
fAngle2 += 360;
|
|
|
|
while ( fAngle2 >= 360 )
|
|
fAngle2 -= 360;
|
|
|
|
if ( !bClockDirection )
|
|
{
|
|
if ( fAngle1 <= fAngle2 )
|
|
nRet = EllipseArc2( fX, fY, fXRad, fYRad, fAngle1, fAngle2, FALSE );
|
|
else
|
|
{
|
|
nRet += EllipseArc2( fX, fY, fXRad, fYRad, fAngle1, 360, FALSE );
|
|
nRet += EllipseArc2( fX, fY, fXRad, fYRad, 0, fAngle2, FALSE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( fAngle1 >= fAngle2 )
|
|
nRet = EllipseArc2( fX, fY, fXRad, fYRad, fAngle1, fAngle2, TRUE );
|
|
else
|
|
{
|
|
nRet += EllipseArc2( fX, fY, fXRad, fYRad, fAngle1, 0, TRUE );
|
|
nRet += EllipseArc2( fX, fY, fXRad, fYRad, 360, fAngle2, TRUE );
|
|
}
|
|
}
|
|
return nRet;
|
|
}
|
|
|
|
double CGraphicsPath::AngToEllPrm(double fAngle, double fXRad, double fYRad)
|
|
{
|
|
// Ôóíêöèÿ äëÿ ïåðåâîäà ðåàëüíîãî óãëà â ïàðàìåòðè÷åñêîå çàäàíèå ýëëïèñà
|
|
// ò.å. x= a cos(t) y = b sin(t) - ïàðàìåòðè÷åñêîå çàäàíèå ýëëïèñà.
|
|
// x = r cos(p), y = r sin(p) => t = atan2( sin(p) / b, cos(p) / a );
|
|
return atan2( sin( fAngle ) / fYRad, cos( fAngle ) / fXRad );
|
|
}
|
|
|
|
int CGraphicsPath::EllipseArc2(double fX, double fY, double fXRad, double fYRad, double fAngle1, double fAngle2, BOOL bClockDirection)
|
|
{
|
|
// ïåðåâåäåì óãëû â ðàäèàíû
|
|
int nRet = 0;
|
|
|
|
double dAngle1 = fAngle1 * 3.141592 / 180;
|
|
double dAngle2 = fAngle2 * 3.141592 / 180;
|
|
|
|
// Âûÿñíèì â êàêèõ ÷åòâåðòÿõ íàõîäÿòñÿ íà÷àëüíàÿ è êîíå÷íàÿ òî÷êè
|
|
unsigned int nFirstPointQuard = int(fAngle1) / 90 + 1;
|
|
unsigned int nSecondPointQuard = int(fAngle2) / 90 + 1;
|
|
nSecondPointQuard = min( 4, max( 1, nSecondPointQuard ) );
|
|
nFirstPointQuard = min( 4, max( 1, nFirstPointQuard ) );
|
|
// Ïðîâåäåì ëèíèþ â íà÷àëüíóþ òî÷êó äóãè
|
|
double fStartX = 0.0, fStartY = 0.0, fEndX = 0.0, fEndY = 0.0;
|
|
|
|
fStartX = fX + fXRad * cos( AngToEllPrm( dAngle1, fXRad, fYRad ) );
|
|
fStartY = fY + fYRad * sin( AngToEllPrm( dAngle1, fXRad, fYRad ) );
|
|
|
|
LineTo(fStartX, fStartY);
|
|
|
|
// Äàëüøå ðèñóåì ïî ÷åòâåðÿì
|
|
|
|
double fCurX = fStartX, fCurY = fStartY;
|
|
double dStartAngle = dAngle1;
|
|
double dEndAngle = 0;
|
|
|
|
if ( !bClockDirection )
|
|
{
|
|
for( unsigned int nIndex = nFirstPointQuard; nIndex <= nSecondPointQuard; nIndex++ )
|
|
{
|
|
if ( nIndex == nSecondPointQuard )
|
|
dEndAngle = dAngle2;
|
|
else
|
|
dEndAngle = (90 * (nIndex ) ) * 3.141592f / 180;
|
|
if ( !( nIndex == nFirstPointQuard ) )
|
|
dStartAngle = (90 * (nIndex - 1 ) ) * 3.141592f / 180;
|
|
|
|
EllipseArc3(fX, fY, fXRad, fYRad, AngToEllPrm( dStartAngle, fXRad, fYRad ), AngToEllPrm( dEndAngle, fXRad, fYRad ), &fEndX, &fEndY, FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for( unsigned int nIndex = nFirstPointQuard; nIndex >= nSecondPointQuard; nIndex-- )
|
|
{
|
|
if ( nIndex == nFirstPointQuard )
|
|
dStartAngle = dAngle1;
|
|
else
|
|
dStartAngle = (90 * (nIndex ) ) * 3.141592f / 180;
|
|
if ( !( nIndex == nSecondPointQuard ) )
|
|
dEndAngle = (90 * (nIndex - 1 ) ) * 3.141592f / 180;
|
|
else
|
|
dEndAngle = dAngle2;
|
|
|
|
EllipseArc3(fX, fY, fXRad, fYRad, AngToEllPrm( dStartAngle, fXRad, fYRad ), AngToEllPrm( dEndAngle, fXRad, fYRad ), &fEndX, &fEndY, FALSE);
|
|
}
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
|
|
int CGraphicsPath::EllipseArc3(double fX, double fY, double fXRad, double fYRad, double dAngle1, double dAngle2, double *pfXCur, double *pfYCur, BOOL bClockDirection = FALSE)
|
|
{
|
|
// Ðàññ÷èòàåì íà÷àëüíóþ, êîíå÷íóþ è êîíòðîëüíûå òî÷êè
|
|
double fX1 = 0.0, fX2 = 0.0, fY1 = 0.0, fY2 = 0.0;
|
|
double fCX1 = 0.0, fCX2 = 0.0, fCY1 = 0.0, fCY2 = 0.0;
|
|
|
|
double fAlpha = sin( dAngle2 - dAngle1 ) * ( sqrt( 4.0 + 3.0 * tan( (dAngle2 - dAngle1) / 2.0 ) * tan( (dAngle2 - dAngle1) / 2.0 ) ) - 1.0 ) / 3.0;
|
|
|
|
double fKoef = 1;
|
|
|
|
fX1 = fX + fXRad * cos( dAngle1 );
|
|
fY1 = fY + fYRad * sin( dAngle1 );
|
|
|
|
fX2 = fX + fXRad * cos( dAngle2 );
|
|
fY2 = fY + fYRad * sin( dAngle2 );
|
|
|
|
fCX1 = fX1 - fAlpha * fXRad * sin ( dAngle1 );
|
|
fCY1 = fY1 + fAlpha * fYRad * cos ( dAngle1 );
|
|
|
|
fCX2 = fX2 + fAlpha * fXRad * sin ( dAngle2 );
|
|
fCY2 = fY2 - fAlpha * fYRad * cos ( dAngle2 );
|
|
|
|
if ( !bClockDirection )
|
|
{
|
|
CurveTo(fCX1, fCY1, fCX2, fCY2, fX2, fY2);
|
|
|
|
*pfXCur = fX2;
|
|
*pfYCur = fY2;
|
|
}
|
|
else
|
|
{
|
|
CurveTo(fCX2, fCY2, fCX1, fCY1, fX1, fY1);
|
|
|
|
*pfXCur = fX1;
|
|
*pfYCur = fY1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int CGraphicsPath::Ellipse(double fX, double fY, double fXRad, double fYRad)
|
|
{
|
|
MoveTo(fX - fXRad, fY);
|
|
|
|
double c_fKappa = 0.552;
|
|
CurveTo(fX - fXRad, fY + fYRad * c_fKappa, fX - fXRad * c_fKappa, fY + fYRad, fX, fY + fYRad);
|
|
CurveTo(fX + fXRad * c_fKappa, fY + fYRad, fX + fXRad, fY + fYRad * c_fKappa, fX + fXRad, fY);
|
|
CurveTo(fX + fXRad, fY - fYRad * c_fKappa, fX + fXRad * c_fKappa, fY - fYRad, fX, fY - fYRad);
|
|
CurveTo(fX - fXRad * c_fKappa, fY - fYRad, fX - fXRad, fY - fYRad * c_fKappa, fX - fXRad, fY);
|
|
|
|
return 0;
|
|
}
|
|
|