1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
/*
VeroRoute - Qt based Veroboard/Perfboard/PCB layout & routing application.
Copyright (C) 2017 Alex Lawrow ( dralx@users.sourceforge.net )
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CurveList.h"
Curve::Curve(const QPoint& p, GPEN ePen, int width) : m_ePen(ePen), m_width(width)
{
push_back(p);
}
Curve::Curve(const QPolygon& polygon, GPEN ePen, int width) : m_ePen(ePen), m_width(width)
{
for (const auto& p : polygon) push_back(p);
// DO NOT COMPRESS BY DEFAULT. That's only OK for open line segments
}
void Curve::Compress() // Removes redundant points
{
unique();
while ( size() > 2 )
{
bool bChanged(false);
auto A = begin();
auto B = A; ++B;
auto C = B; ++C;
for (; C != end(); ++A, ++B, ++C)
{
if ( A->x() == B->x() && B->x() == C->x() ) // Vertical
{
if ( ( B->y() >= A->y() && B->y() <= C->y() ) ||
( B->y() >= C->y() && B->y() <= A->y() ) )
{
(*B) = (*A); // .. make B == A so we can remove it as not unique
bChanged = true;
}
}
else if ( A->y() == B->y() && B->y() == C->y() ) // Horizontal
{
if ( ( B->x() >= A->x() && B->x() <= C->x() ) ||
( B->x() >= C->x() && B->x() <= A->x() ) )
{
(*B) = (*A); // .. make B == A so we can remove it as not unique
bChanged = true;
}
}
}
if ( !bChanged ) return;
unique();
}
}
bool Curve::Splice(Curve* pB) // Tries to splice curve B to this
{
if ( m_ePen != pB->m_ePen ) return false; // Pens must match
if ( m_width != pB->m_width ) return false; // Widths must match
if ( empty() || pB->empty() ) return false; // Curves must have points
// Try to get back of 'this' matching front of 'pB', then splice 'pB' to 'this'
if ( front() == pB->back() ) { reverse(); pB->reverse(); }
else if ( front() == pB->front() ) { reverse(); }
else if ( back() == pB->back() ) { pB->reverse(); }
if ( back() == pB->front() ) { splice(end(), *pB); Compress(); return true; }
return false;
}
void CurveList::Clear()
{
for (auto& p : *this) p->clear();
clear();
}
void CurveList::Sort()
{
sort( Curve::HasLargerPen() );
}
void CurveList::SpliceAll()
{
Sort(); // Sort list of curves by pen width and type
bool bDone(false); // Keep splicing curves together till no more splices are possible.
while ( !bDone )
{
bDone = true;
for (auto iterA = begin(); iterA != end(); ++iterA)
{
auto iterB = iterA; ++iterB;
for (; iterB != end(); ++iterB)
if ( (*iterA)->Splice(*iterB) ) bDone = false;
}
}
}
|