From 4d9a4ed30085312825d9430d93b1e7029914c821 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Mon, 6 Oct 2025 16:37:37 +0300 Subject: [PATCH] Fix bug 77268 --- PdfFile/PdfEditor.cpp | 15 ++-- PdfFile/PdfWriter.cpp | 123 ++++++++++++++------------ PdfFile/PdfWriter.h | 1 + PdfFile/SrcWriter/RedactOutputDev.cpp | 89 ++++++------------- PdfFile/SrcWriter/RedactOutputDev.h | 1 - PdfFile/SrcWriter/States.cpp | 36 +++++--- PdfFile/SrcWriter/States.h | 2 +- PdfFile/SrcWriter/Utils.cpp | 47 ++++++++++ PdfFile/SrcWriter/Utils.h | 3 + 9 files changed, 175 insertions(+), 142 deletions(-) diff --git a/PdfFile/PdfEditor.cpp b/PdfFile/PdfEditor.cpp index 7f2bfdbfe5..2a3f622a87 100644 --- a/PdfFile/PdfEditor.cpp +++ b/PdfFile/PdfEditor.cpp @@ -3296,8 +3296,8 @@ bool CPdfEditor::EditWidgets(IAdvancedCommand* pCommand) if (m_nMode == Mode::Unknown && !IncrementalUpdates()) return false; - WriteRedact({}); m_pWriter->AddRedact({}); + WriteRedact({}); m_arrRedact.clear(); CWidgetsInfo* pFieldInfo = (CWidgetsInfo*)pCommand; @@ -3605,7 +3605,6 @@ std::vector CPdfEditor::WriteRedact(const std::vector& arr if (oRedact.bDraw || !oRedact.pRender) continue; - m_pWriter->SetTransform(1, 0, 0, 1, 0, 0); LONG nLenRender = oRedact.nLenRender; BYTE* pRender = oRedact.pRender; @@ -3620,19 +3619,23 @@ std::vector CPdfEditor::WriteRedact(const std::vector& arr double B = ret / 100000.0; LONG lColor = (LONG)(((LONG)(R * 255)) | ((LONG)(G * 255) << 8) | ((LONG)(B * 255) << 16) | ((LONG)255 << 24)); + m_pWriter->SetTransform(1, 0, 0, 1, 0, 0); + m_pWriter->PathCommandEnd(); + m_pWriter->put_BrushType(c_BrushTypeSolid); + m_pWriter->put_BrushColor1(lColor); + for (int i = 0; i < oRedact.arrQuads.size(); i += 4) { - m_pWriter->PathCommandEnd(); - m_pWriter->put_BrushColor1(lColor); m_pWriter->PathCommandMoveTo(PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 0]), PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 1])); m_pWriter->PathCommandLineTo(PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 0]), PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 3])); m_pWriter->PathCommandLineTo(PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 2]), PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 3])); m_pWriter->PathCommandLineTo(PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 2]), PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 1])); m_pWriter->PathCommandClose(); - m_pWriter->DrawPath(NULL, L"", c_nWindingFillMode); - m_pWriter->PathCommandEnd(); } + m_pWriter->DrawPath(NULL, L"", c_nWindingFillMode); + m_pWriter->PathCommandEnd(); + // TODO рендер редакта должен быть пересечён со всеми последующими редактами // TODO на самом деле должен быть рендер команд редакта /* diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index d24af6e760..c9132f815f 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -2646,11 +2646,11 @@ HRESULT CPdfWriter::AddRedact(const std::vector& arrRedact) for (int i = 0; i < m_arrRedact.size(); i += 4) { - m_arrRedact[i * 4 + 0] += dPageX; - double dQ = m_arrRedact[i * 4 + 1]; - m_arrRedact[i * 4 + 1] = dPageH - m_arrRedact[i * 4 + 3]; - m_arrRedact[i * 4 + 2] += dPageX; - m_arrRedact[i * 4 + 3] = dPageH - dQ; + m_arrRedact[i + 0] += dPageX; + double dQ = m_arrRedact[i + 1]; + m_arrRedact[i + 1] = dPageH - m_arrRedact[i + 3]; + m_arrRedact[i + 2] += dPageX; + m_arrRedact[i + 3] = dPageH - dQ; } return S_OK; @@ -3176,8 +3176,52 @@ bool CPdfWriter::SkipRedact(const double& dX, const double& dY, const double& dW if (m_arrRedact.empty()) return false; double dXmin = MM_2_PT(dX), dYmin = MM_2_PT(m_dPageHeight - dY - dH), dXmax = MM_2_PT(dX + dW), dYmax = MM_2_PT(m_dPageHeight - dY); - m_oTransform.Transform(dXmin, dYmin, &dXmin, &dYmin); - m_oTransform.Transform(dXmax, dYmax, &dXmax, &dYmax); + CTransform& t = m_oTransform; + CTransform oT; + oT.Set(t.m11, -t.m12, -t.m21, t.m22, MM_2_PT(t.dx + t.m21 * m_dPageHeight), MM_2_PT(m_dPageHeight - m_dPageHeight * t.m22 - t.dy)); + + double dX1, dY1, dX2, dY2, dX3, dY3, dX4, dY4; + dX1 = dXmin, dY1 = dYmin; + dX2 = dXmin, dY2 = dYmax; + dX3 = dXmax, dY3 = dYmax; + dX4 = dXmax, dY4 = dYmin; + + oT.Transform(dX1, dY1, &dX1, &dY1); + oT.Transform(dX2, dY2, &dX2, &dY2); + oT.Transform(dX3, dY3, &dX3, &dY3); + oT.Transform(dX4, dY4, &dX4, &dY4); + + std::vector poly2 = + { + PdfWriter::CPoint(dX1, dY1), + PdfWriter::CPoint(dX2, dY2), + PdfWriter::CPoint(dX3, dY3), + PdfWriter::CPoint(dX4, dY4) + }; + for (int i = 0; i < m_arrRedact.size(); i += 4) + { + std::vector poly1 = + { + PdfWriter::CPoint(m_arrRedact[i + 0], m_arrRedact[i + 1]), + PdfWriter::CPoint(m_arrRedact[i + 2], m_arrRedact[i + 1]), + PdfWriter::CPoint(m_arrRedact[i + 2], m_arrRedact[i + 3]), + PdfWriter::CPoint(m_arrRedact[i + 0], m_arrRedact[i + 3]) + }; + + if (PdfWriter::SAT(poly1, poly2)) + return true; + } + return false; +} +bool CPdfWriter::SkipRedact(const double& dX, const double& dY) +{ + if (m_arrRedact.empty()) + return false; + double dXc = MM_2_PT(dX), dYc = MM_2_PT(m_dPageHeight - dY); + CTransform& t = m_oTransform; + CTransform oT; + oT.Set(t.m11, -t.m12, -t.m21, t.m22, MM_2_PT(t.dx + t.m21 * m_dPageHeight), MM_2_PT(m_dPageHeight - m_dPageHeight * t.m22 - t.dy)); + oT.Transform(dXc, dYc, &dXc, &dYc); for (int i = 0; i < m_arrRedact.size(); i += 4) { double xMin = m_arrRedact[i + 0]; @@ -3185,7 +3229,7 @@ bool CPdfWriter::SkipRedact(const double& dX, const double& dY, const double& dW double xMax = m_arrRedact[i + 2]; double yMax = m_arrRedact[i + 3]; - if (!(dXmax < xMin || dXmin > xMax || dYmax < yMin || dYmin > yMax)) + if (xMin < dXc && dXc < xMax && yMin < dYc && dYc < yMax) return true; } return false; @@ -3305,23 +3349,10 @@ bool CPdfWriter::DrawText(unsigned char* pCodes, const unsigned int& unLen, cons if (!pCodes || !unLen) return false; - if (!m_arrRedact.empty()) - { - double dXc = MM_2_PT(dX), dYc = MM_2_PT(m_dPageHeight - dY); - m_oTransform.Transform(dXc, dYc, &dXc, &dYc); - // TODO должна быть проверка центрального положения, а не точки начала - // TODO Сюда приходит много символов за раз, и нужно отрисовать только те, что вне областей редакта - for (int i = 0; i < m_arrRedact.size(); i += 4) - { - double xMin = m_arrRedact[i + 0]; - double yMin = m_arrRedact[i + 1]; - double xMax = m_arrRedact[i + 2]; - double yMax = m_arrRedact[i + 3]; - - if (xMin < dXc && dXc < xMax && yMin < dYc && dYc < yMax) - return true; - } - } + // TODO должна быть проверка центрального положения, а не точки начала + // TODO Сюда приходит много символов за раз, и нужно отрисовать только те, что вне областей редакта + if (SkipRedact(dX, dY)) + return true; CTransform& t = m_oTransform; m_oCommandManager.SetTransform(t.m11, -t.m12, -t.m21, t.m22, MM_2_PT(t.dx + t.m21 * m_dPageHeight), MM_2_PT(m_dPageHeight - m_dPageHeight * t.m22 - t.dy)); @@ -3345,23 +3376,10 @@ bool CPdfWriter::DrawTextToRenderer(const unsigned int* unGid, const unsigned in { if (m_bSplit) return false; - if (!m_arrRedact.empty()) - { - double dXc = MM_2_PT(dX), dYc = MM_2_PT(m_dPageHeight - dY); - m_oTransform.Transform(dXc, dYc, &dXc, &dYc); - // TODO должна быть проверка центрального положения, а не точки начала - // TODO Сюда приходит много символов за раз, и нужно отрисовать только те, что вне областей редакта - for (int i = 0; i < m_arrRedact.size(); i += 4) - { - double xMin = m_arrRedact[i + 0]; - double yMin = m_arrRedact[i + 1]; - double xMax = m_arrRedact[i + 2]; - double yMax = m_arrRedact[i + 3]; - - if (xMin < dXc && dXc < xMax && yMin < dYc && dYc < yMax) - return true; - } - } + // TODO должна быть проверка центрального положения, а не точки начала + // TODO Сюда приходит много символов за раз, и нужно отрисовать только те, что вне областей редакта + if (SkipRedact(dX, dY)) + return true; // TODO pdf позволяет создание своего шрифта, но не следует это использовать для воссоздания шрифта запрещенного для редактирования или встраивания Aggplus::CGraphicsPathSimpleConverter simplifier; simplifier.SetRenderer(m_pRenderer); @@ -3377,23 +3395,10 @@ bool CPdfWriter::DrawTextToRenderer(const unsigned int* unGid, const unsigned in } bool CPdfWriter::PathCommandDrawText(unsigned int* pUnicodes, unsigned int unLen, const double& dX, const double& dY, const unsigned int* pGids) { - if (!m_arrRedact.empty()) - { - double dXc = MM_2_PT(dX), dYc = MM_2_PT(m_dPageHeight - dY); - m_oTransform.Transform(dXc, dYc, &dXc, &dYc); - // TODO должна быть проверка центрального положения, а не точки начала - // TODO Сюда приходит много символов за раз, и нужно отрисовать только те, что вне областей редакта - for (int i = 0; i < m_arrRedact.size(); i += 4) - { - double xMin = m_arrRedact[i + 0]; - double yMin = m_arrRedact[i + 1]; - double xMax = m_arrRedact[i + 2]; - double yMax = m_arrRedact[i + 3]; - - if (xMin < dXc && dXc < xMax && yMin < dYc && dYc < yMax) - return true; - } - } + // TODO должна быть проверка центрального положения, а не точки начала + // TODO Сюда приходит много символов за раз, и нужно отрисовать только те, что вне областей редакта + if (SkipRedact(dX, dY)) + return true; unsigned char* pCodes = EncodeString(pUnicodes, unLen, pGids); if (!pCodes) diff --git a/PdfFile/PdfWriter.h b/PdfFile/PdfWriter.h index b6db52c232..12edd3f0bd 100644 --- a/PdfFile/PdfWriter.h +++ b/PdfFile/PdfWriter.h @@ -230,6 +230,7 @@ public: private: bool SkipRedact(const double& dX, const double& dY, const double& dW, const double& dH); + bool SkipRedact(const double& dX, const double& dY); PdfWriter::CImageDict* LoadImage(Aggplus::CImage* pImage, BYTE nAlpha); PdfWriter::CImageDict* DrawImage(Aggplus::CImage* pImage, const double& dX, const double& dY, const double& dW, const double& dH, const BYTE& nAlpha); bool DrawText(unsigned char* pCodes, const unsigned int& unLen, const double& dX, const double& dY, const std::string& sPUA); diff --git a/PdfFile/SrcWriter/RedactOutputDev.cpp b/PdfFile/SrcWriter/RedactOutputDev.cpp index 4d33f2237b..52a1becd88 100644 --- a/PdfFile/SrcWriter/RedactOutputDev.cpp +++ b/PdfFile/SrcWriter/RedactOutputDev.cpp @@ -33,6 +33,7 @@ #include "RedactOutputDev.h" #include "Types.h" #include "Streams.h" +#include "Utils.h" #include "../lib/xpdf/GfxFont.h" #include "../lib/xpdf/XRef.h" @@ -703,64 +704,6 @@ void RedactOutputDev::type3D1(GfxState *pGState, double wx, double wy, double ll } //----- form XObjects -void projectPolygon(const std::vector& polygon, const CPoint& axis, double& min, double& max) -{ - min = std::numeric_limits::max(); - max = std::numeric_limits::lowest(); - - for (const auto& point : polygon) - { - double projection = (point.x * axis.x + point.y * axis.y) / (axis.x * axis.x + axis.y * axis.y); - projection *= (axis.x * axis.x + axis.y * axis.y); - - if (projection < min) min = projection; - if (projection > max) max = projection; - } -} -bool RedactOutputDev::SAT(const std::vector& poly2) -{ - for (int j = 0; j < m_arrQuadPoints.size(); j += 4) - { - std::vector poly1 = - { - CPoint(m_arrQuadPoints[j + 0], m_arrQuadPoints[j + 1]), - CPoint(m_arrQuadPoints[j + 2], m_arrQuadPoints[j + 1]), - CPoint(m_arrQuadPoints[j + 2], m_arrQuadPoints[j + 3]), - CPoint(m_arrQuadPoints[j + 0], m_arrQuadPoints[j + 3]) - }; - - std::vector axes; - for (size_t i = 0; i < poly1.size(); i++) - { - CPoint p1 = poly1[i]; - CPoint p2 = poly1[(i + 1) % poly1.size()]; - CPoint edge(p2.x - p1.x, p2.y - p1.y); - CPoint normal(-edge.y, edge.x); // Перпендикуляр к ребру - axes.push_back(normal); - } - - for (size_t i = 0; i < poly2.size(); i++) - { - CPoint p1 = poly2[i]; - CPoint p2 = poly2[(i + 1) % poly2.size()]; - CPoint edge(p2.x - p1.x, p2.y - p1.y); - CPoint normal(-edge.y, edge.x); // Перпендикуляр к ребру - axes.push_back(normal); - } - - // Проверяем все оси на разделение - for (const auto& axis : axes) - { - double min1, max1, min2, max2; - projectPolygon(poly1, axis, min1, max1); - projectPolygon(poly2, axis, min2, max2); - - if (max1 < min2 || max2 < min1) - return false; // Найдена разделяющая ось - } - } - return true; // Пересекаются -} void RedactOutputDev::drawForm(GfxState *pGState, Ref id, const char* name) { m_pRenderer->m_oCommandManager.Flush(); @@ -831,8 +774,19 @@ void RedactOutputDev::drawForm(GfxState *pGState, Ref id, const char* name) CPoint(dX3, dY3), CPoint(dX4, dY4) }; - if (SAT(poly2)) - return; + for (int i = 0; i < m_arrQuadPoints.size(); i += 4) + { + std::vector poly1 = + { + CPoint(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 1]), + CPoint(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 1]), + CPoint(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 3]), + CPoint(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 3]) + }; + + if (PdfWriter::SAT(poly1, poly2)) + return; + } m_pPage->GrSave(); UpdateTransform(); @@ -862,8 +816,19 @@ void RedactOutputDev::drawImage(GfxState *pGState, Ref id, const char* name) CPoint(dX3, dY3), CPoint(dX4, dY4) }; - if (SAT(poly2)) - return; + for (int j = 0; j < m_arrQuadPoints.size(); j += 4) + { + std::vector poly1 = + { + CPoint(m_arrQuadPoints[j + 0], m_arrQuadPoints[j + 1]), + CPoint(m_arrQuadPoints[j + 2], m_arrQuadPoints[j + 1]), + CPoint(m_arrQuadPoints[j + 2], m_arrQuadPoints[j + 3]), + CPoint(m_arrQuadPoints[j + 0], m_arrQuadPoints[j + 3]) + }; + + if (PdfWriter::SAT(poly1, poly2)) + return; + } m_pPage->GrSave(); UpdateTransform(); diff --git a/PdfFile/SrcWriter/RedactOutputDev.h b/PdfFile/SrcWriter/RedactOutputDev.h index c7fe303aa6..23d371f3fd 100644 --- a/PdfFile/SrcWriter/RedactOutputDev.h +++ b/PdfFile/SrcWriter/RedactOutputDev.h @@ -204,7 +204,6 @@ namespace PdfWriter void UpdateTransform(); void AddClip(GfxState* pGState, GfxRedactState* pState, int nIndex); void DoStateOp(); - bool SAT(const std::vector& vXObject); XRef* m_pXref; std::vector m_arrQuadPoints; diff --git a/PdfFile/SrcWriter/States.cpp b/PdfFile/SrcWriter/States.cpp index 57b75a973d..e74ee898f2 100644 --- a/PdfFile/SrcWriter/States.cpp +++ b/PdfFile/SrcWriter/States.cpp @@ -297,12 +297,14 @@ bool SkipPath(const std::vector& arrForStroke, const PdfWri } return false; } -void CPath::DrawPathRedact(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath* oPath, bool bStroke, const std::vector& arrForStroke) +bool CPath::DrawPathRedact(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath* oPath, bool bStroke, const std::vector& arrForStroke) { PdfWriter::CMatrix oInverse = pMatrix->Inverse(); size_t length = oPath->GetPointCount(), compound = oPath->GetCloseCount(); std::vector points = oPath->GetPoints(0, length + compound); + if (length + compound == 0) + return false; double dXStart = -1, dYStart = -1, dXCur = -1, dYCur = -1; bool bBreak = false; @@ -388,6 +390,7 @@ void CPath::DrawPathRedact(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath* Close(); } } + return true; } void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRedact, PdfWriter::CPage* pPage, bool bStroke, bool bFill, bool bEoFill, PdfWriter::CShading* pShading, PdfWriter::CExtGrState* pShadingExtGrState) @@ -419,20 +422,23 @@ void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRe if (bFill || bEoFill) { oPathResult = Aggplus::CalcBooleanOperation(oPath, oPathRedact, Aggplus::BooleanOpType::Subtraction); - DrawPathRedact(pMatrix, &oPathResult, bStroke); + bool bPath = DrawPathRedact(pMatrix, &oPathResult, bStroke); - if (!pShading) - Draw(pPage, false, bFill, bEoFill); - else + if (bPath) { - pPage->GrSave(); - Clip(pPage, bEoFill); + if (!pShading) + Draw(pPage, false, bFill, bEoFill); + else + { + pPage->GrSave(); + Clip(pPage, bEoFill); - if (pShadingExtGrState) - pPage->SetExtGrState(pShadingExtGrState); + if (pShadingExtGrState) + pPage->SetExtGrState(pShadingExtGrState); - pPage->DrawShading(pShading); - pPage->GrRestore(); + pPage->DrawShading(pShading); + pPage->GrRestore(); + } } } @@ -440,6 +446,7 @@ void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRe if (bStroke) { + bool bPath = false; std::vector arrForStroke; std::vector rectangles; for (int i = 0; i < arrRedact.size(); i += 4) @@ -477,7 +484,7 @@ void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRe dXCur = dX3, dYCur = dY3; oPathResult = Aggplus::CalcBooleanOperation(_oPath, oPathRedact, Aggplus::BooleanOpType::Subtraction); - DrawPathRedact(pMatrix, &oPathResult, bStroke, arrForStroke); + bPath = bPath || DrawPathRedact(pMatrix, &oPathResult, bStroke, arrForStroke); oPathResult.Reset(); } else if (oPath.IsMovePoint(i)) @@ -494,6 +501,7 @@ void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRe dXCur = dX; dYCur = dY; auto visibleSegments = clipper.getVisibleSegments(line); + bPath = bPath || visibleSegments.size() != 0; for (int i = 0; i < visibleSegments.size(); ++i) { double dX1 = visibleSegments[i].start.x, dY1 = visibleSegments[i].start.y; @@ -509,6 +517,7 @@ void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRe PdfWriter::CLineClipper clipper(rectangles); PdfWriter::CSegment line(PdfWriter::CPoint(dXCur, dYCur), PdfWriter::CPoint(dXStart, dYStart)); auto visibleSegments = clipper.getVisibleSegments(line); + bPath = bPath || visibleSegments.size() != 0; for (int i = 0; i < visibleSegments.size(); ++i) { double dX1 = visibleSegments[i].start.x, dY1 = visibleSegments[i].start.y; @@ -521,7 +530,8 @@ void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRe } } - Draw(pPage, bStroke, false, false); + if (bPath) + Draw(pPage, bStroke, false, false); } m_vCommands = vCommands; diff --git a/PdfFile/SrcWriter/States.h b/PdfFile/SrcWriter/States.h index 7ed7463e66..de49508ba5 100644 --- a/PdfFile/SrcWriter/States.h +++ b/PdfFile/SrcWriter/States.h @@ -1594,7 +1594,7 @@ public: void GetBounds(double& dL, double& dT, double& dR, double& dB); void Redact(PdfWriter::CMatrix* oMatrix, const std::vector& arrRedact, PdfWriter::CPage* pPage, bool bStroke, bool bFill, bool bEoFill, PdfWriter::CShading* pShading, PdfWriter::CExtGrState* pShadingExtGrState); - void DrawPathRedact(PdfWriter::CMatrix* oMatrix, Aggplus::CGraphicsPath* oPath, bool bStroke, const std::vector& arrForStroke = {}); + bool DrawPathRedact(PdfWriter::CMatrix* oMatrix, Aggplus::CGraphicsPath* oPath, bool bStroke, const std::vector& arrForStroke = {}); private: diff --git a/PdfFile/SrcWriter/Utils.cpp b/PdfFile/SrcWriter/Utils.cpp index 9157d95983..73b0009b63 100644 --- a/PdfFile/SrcWriter/Utils.cpp +++ b/PdfFile/SrcWriter/Utils.cpp @@ -316,4 +316,51 @@ namespace PdfWriter return sRes; } + void projectPolygon(const std::vector& polygon, const CPoint& axis, double& min, double& max) + { + min = std::numeric_limits::max(); + max = std::numeric_limits::lowest(); + + for (const auto& point : polygon) + { + double projection = (point.x * axis.x + point.y * axis.y) / (axis.x * axis.x + axis.y * axis.y); + projection *= (axis.x * axis.x + axis.y * axis.y); + + if (projection < min) min = projection; + if (projection > max) max = projection; + } + } + bool SAT(const std::vector& poly1, const std::vector& poly2) + { + std::vector axes; + for (size_t i = 0; i < poly1.size(); i++) + { + CPoint p1 = poly1[i]; + CPoint p2 = poly1[(i + 1) % poly1.size()]; + CPoint edge(p2.x - p1.x, p2.y - p1.y); + CPoint normal(-edge.y, edge.x); // Перпендикуляр к ребру + axes.push_back(normal); + } + + for (size_t i = 0; i < poly2.size(); i++) + { + CPoint p1 = poly2[i]; + CPoint p2 = poly2[(i + 1) % poly2.size()]; + CPoint edge(p2.x - p1.x, p2.y - p1.y); + CPoint normal(-edge.y, edge.x); // Перпендикуляр к ребру + axes.push_back(normal); + } + + // Проверяем все оси на разделение + for (const auto& axis : axes) + { + double min1, max1, min2, max2; + projectPolygon(poly1, axis, min1, max1); + projectPolygon(poly2, axis, min2, max2); + + if (max1 < min2 || max2 < min1) + return false; // Найдена разделяющая ось + } + return true; // Пересекаются + } } diff --git a/PdfFile/SrcWriter/Utils.h b/PdfFile/SrcWriter/Utils.h index 776fffabe1..f15855957a 100644 --- a/PdfFile/SrcWriter/Utils.h +++ b/PdfFile/SrcWriter/Utils.h @@ -141,6 +141,9 @@ namespace PdfWriter std::string DateNow(); std::wstring NormalizeWhitespace(const std::wstring& s); + + // Пересечение по теореме о разделяющей оси + bool SAT(const std::vector& poly1, const std::vector& poly2); } #endif // _PDF_WRITER_SRC_UTILS_H