1
/////////////////////////////////////////////////////////////////////////////
3
// Purpose: Rectangular selection storage classes for ints and doubles
4
// Author: John Labenski
6
// Copyright: (c) John Labenski 2004
8
/////////////////////////////////////////////////////////////////////////////
10
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
11
#pragma implementation "block.h"
14
// For compilers that support precompilation, includes "wx.h".
15
#include "wx/wxprec.h"
22
//#include "wx/object.h"
25
#include "wx/things/block.h"
27
// use this to check to see if there is any overlap after minimizing
28
//#define CHECK_BLOCK_OVERLAP 1
30
#define PRINT_BLOCK(msg, b) { wxPrintf(wxT("Block '%s' %lg %lg %lg %lg\n"), msg, (double)(b).m_x1, (double)(b).m_y1, (double)(b).m_x2, (double)(b).m_y2); }
32
wxBlockInt const wxEmptyBlockInt(0, 0, -1, -1);
33
wxBlockDouble const wxEmptyBlockDouble(0, 0, -1, -1);
35
#include "wx/arrimpl.cpp"
36
WX_DEFINE_OBJARRAY(wxArrayBlockInt);
37
WX_DEFINE_OBJARRAY(wxArrayBlockDouble);
38
WX_DEFINE_OBJARRAY(wxArrayBlockIntSelection);
39
WX_DEFINE_OBJARRAY(wxArrayBlockDoubleSelection);
41
// ----------------------------------------------------------------------------
42
// Sorting functions for wxBlockInt
43
// ----------------------------------------------------------------------------
45
static int wxCMPFUNC_CONV wxblockint_sort_topleft_bottomright( wxBlockInt **a, wxBlockInt **b)
47
register int y = ((*a)->m_y1 - (*b)->m_y1);
50
if (y == 0) return ((*a)->m_x1 - (*b)->m_x1);
53
static int wxCMPFUNC_CONV wxblockint_sort_topright_bottomleft( wxBlockInt **a, wxBlockInt **b)
55
register int y = ((*a)->m_y1 - (*b)->m_y1);
58
if (y == 0) return ((*a)->m_x2 - (*b)->m_x2);
62
static int wxCMPFUNC_CONV wxblockint_sort_bottomleft_topright( wxBlockInt **a, wxBlockInt **b)
64
register int y = ((*a)->m_y2 - (*b)->m_y2);
67
if (y == 0) return ((*a)->m_x1 - (*b)->m_x1);
70
static int wxCMPFUNC_CONV wxblockint_sort_bottomright_topleft( wxBlockInt **a, wxBlockInt **b)
72
register int y = ((*a)->m_y2 - (*b)->m_y2);
75
if (y == 0) return ((*a)->m_x2 - (*b)->m_x2);
78
static int wxCMPFUNC_CONV wxblockint_sort_largest_to_smallest( wxBlockInt **a, wxBlockInt **b)
80
return (*a)->IsLarger(**b);
82
static int wxCMPFUNC_CONV wxblockint_sort_smallest_to_largest( wxBlockInt **a, wxBlockInt **b)
84
return -(*a)->IsLarger(**b);
87
void wxArrayBlockIntSort(wxArrayBlockInt &blocks, wxBlockSort_Type type)
91
case wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT : blocks.Sort(wxblockint_sort_topleft_bottomright); break;
92
case wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT : blocks.Sort(wxblockint_sort_topright_bottomleft); break;
93
case wxBLOCKSORT_BOTTOMLEFT_TOPRIGHT : blocks.Sort(wxblockint_sort_bottomleft_topright); break;
94
case wxBLOCKSORT_BOTTOMRIGHT_TOPLEFT : blocks.Sort(wxblockint_sort_bottomright_topleft); break;
95
case wxBLOCKSORT_SMALLEST_TO_LARGEST : blocks.Sort(wxblockint_sort_smallest_to_largest); break;
96
case wxBLOCKSORT_LARGEST_TO_SMALLEST : blocks.Sort(wxblockint_sort_largest_to_smallest); break;
97
default : wxFAIL_MSG(wxT("unknown block sort type"));
101
// ----------------------------------------------------------------------------
102
// Sorting functions for wxBlockDouble
103
// ----------------------------------------------------------------------------
105
static int wxCMPFUNC_CONV wxblockdouble_sort_topleft_bottomright( wxBlockDouble **a, wxBlockDouble **b)
107
register wxDouble y = ((*a)->m_y1 - (*b)->m_y1);
109
if (y < 0) return -1;
110
if (y == 0) return int((*a)->m_x1 - (*b)->m_x1);
113
static int wxCMPFUNC_CONV wxblockdouble_sort_topright_bottomleft( wxBlockDouble **a, wxBlockDouble **b)
115
register wxDouble y = ((*a)->m_y1 - (*b)->m_y1);
117
if (y < 0) return -1;
118
if (y == 0) return int((*a)->m_x2 - (*b)->m_x2);
122
static int wxCMPFUNC_CONV wxblockdouble_sort_bottomleft_topright( wxBlockDouble **a, wxBlockDouble **b)
124
register wxDouble y = ((*a)->m_y2 - (*b)->m_y2);
126
if (y > 0) return -1;
127
if (y == 0) return int((*a)->m_x1 - (*b)->m_x1);
130
static int wxCMPFUNC_CONV wxblockdouble_sort_bottomright_topleft( wxBlockDouble **a, wxBlockDouble **b)
132
register wxDouble y = ((*a)->m_y2 - (*b)->m_y2);
134
if (y > 0) return -1;
135
if (y == 0) return int((*a)->m_x2 - (*b)->m_x2);
138
static int wxCMPFUNC_CONV wxblockdouble_sort_largest_to_smallest( wxBlockDouble **a, wxBlockDouble **b)
140
return (*a)->IsLarger(**b);
142
static int wxCMPFUNC_CONV wxblockdouble_sort_smallest_to_largest( wxBlockDouble **a, wxBlockDouble **b)
144
return -(*a)->IsLarger(**b);
147
void wxArrayBlockDoubleSort(wxArrayBlockDouble &blocks, wxBlockSort_Type type)
151
case wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT : blocks.Sort(wxblockdouble_sort_topleft_bottomright); break;
152
case wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT : blocks.Sort(wxblockdouble_sort_topright_bottomleft); break;
153
case wxBLOCKSORT_BOTTOMLEFT_TOPRIGHT : blocks.Sort(wxblockdouble_sort_bottomleft_topright); break;
154
case wxBLOCKSORT_BOTTOMRIGHT_TOPLEFT : blocks.Sort(wxblockdouble_sort_bottomright_topleft); break;
155
case wxBLOCKSORT_SMALLEST_TO_LARGEST : blocks.Sort(wxblockdouble_sort_smallest_to_largest); break;
156
case wxBLOCKSORT_LARGEST_TO_SMALLEST : blocks.Sort(wxblockdouble_sort_largest_to_smallest); break;
157
default : wxFAIL_MSG(wxT("unknown block sort type"));
161
//=============================================================================
163
//=============================================================================
170
printf("Start Testing blocks -----------------------------------------\n");
171
wxBlockInt b1(1,1,4,4);
172
wxBlockInt b2(5,4,10,11);
173
PRINT_BLOCK("b1", b1)
174
PRINT_BLOCK("b2", b2)
177
iB.Intersect(b1, b2, &iB);
178
PRINT_BLOCK("Intersect b1 b2", iB)
181
uB.Union(b1, b2, &uB);
182
PRINT_BLOCK("Union b1 b2", uB)
184
printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1));
186
b1 = wxBlockInt(2,3,7,9);
187
b2 = wxBlockInt(8,3,8,3);
188
printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1));
190
b1 = wxBlockInt(2,3,7,9);
191
b2 = wxBlockInt(1,3,1,3);
192
printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1));
193
iB.Intersect(b1, b2, &iB);
194
PRINT_BLOCK("Intersect b1 b2", iB)
196
b1 = wxBlockInt(2,3,7,9);
197
b2 = wxBlockInt(2,2,2,2);
198
printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1));
200
b1 = wxBlockInt(2,3,7,9);
201
b2 = wxBlockInt(7,10,7,10);
202
printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1));
204
printf("End Testing blocks -----------------------------------------\n");
209
bool wxBlockInt::Touches(const wxBlockInt &b) const // see Intersects
211
//if (((wxMax(m_x1, b.m_x1)) <= (wxMin(m_x2, b.m_x2))) &&
212
// ((wxMax(m_y1, b.m_y1)) <= (wxMin(m_y2, b.m_y2))))
215
return Intersects(wxBlockInt(b.m_x1-1, b.m_y1-1, b.m_x2+1, b.m_y2+1));
218
wxInt32 left = wxMax( m_x1, b.m_x1 );
219
wxInt32 right = wxMin( m_x2, b.m_x2 );
221
if (labs(left - right) <= 1)
223
wxInt32 top = wxMax( m_y1, b.m_y1 );
224
wxInt32 bottom = wxMin( m_y2, b.m_y2 );
225
if (labs(top - bottom) <= 1)
232
bool wxBlockInt::Combine(const wxBlockInt &b)
234
if (!Touches(b)) return false;
235
if (Contains(b)) return true;
236
if (b.Contains(*this))
242
wxBlockInt unionBlock;
243
Union( *this, b, &unionBlock );
245
if (unionBlock.IsEmpty()) return false;
247
// at least one of the two blocks has to be at each corner of the union
248
if (((unionBlock.GetLeftTop() == GetLeftTop()) || (unionBlock.GetLeftTop() == b.GetLeftTop())) &&
249
((unionBlock.GetRightTop() == GetRightTop()) || (unionBlock.GetRightTop() == b.GetRightTop())) &&
250
((unionBlock.GetLeftBottom() == GetLeftBottom()) || (unionBlock.GetLeftBottom() == b.GetLeftBottom())) &&
251
((unionBlock.GetRightBottom() == GetRightBottom()) || (unionBlock.GetRightBottom() == b.GetRightBottom())) )
260
bool wxBlockInt::Combine( const wxBlockInt &block,
261
wxBlockInt &top, wxBlockInt &bottom,
262
wxBlockInt &left, wxBlockInt &right) const
264
top = bottom = left = right = wxEmptyBlockInt;
267
Intersect(*this, block, &iBlock);
269
if (iBlock.IsEmpty()) return false; // nothing to combine
270
if (iBlock == *this) return true; // can combine all of this, no leftover
272
bool combined = false;
274
if ( block.m_y1 < m_y1 )
276
top = wxBlockInt( block.m_x1, block.m_y1, block.m_x2, m_y1-1 );
279
if ( block.m_y2 > m_y2 )
281
bottom = wxBlockInt( block.m_x1, m_y2+1, block.m_x2, block.m_y2 );
284
if ( block.m_x1 < m_x1 )
286
left = wxBlockInt( block.m_x1, iBlock.m_y1, m_x1-1, iBlock.m_y2 );
289
if ( block.m_x2 > m_x2 )
291
right = wxBlockInt( m_x2+1, iBlock.m_y1, block.m_x2, iBlock.m_y2 );
298
bool wxBlockInt::Delete( const wxBlockInt &block,
299
wxBlockInt &top, wxBlockInt &bottom,
300
wxBlockInt &left, wxBlockInt &right) const
302
top = bottom = left = right = wxEmptyBlockInt;
305
Intersect(*this, block, &iBlock);
307
if (iBlock.IsEmpty()) return false; // nothing to delete
308
if (iBlock == *this) return true; // can delete all of this, no leftover
310
bool deleted = false;
312
if ( m_y1 < iBlock.m_y1 )
314
top = wxBlockInt( m_x1, m_y1, m_x2, iBlock.m_y1-1 );
317
if ( GetBottom() > iBlock.GetBottom() )
319
bottom = wxBlockInt( m_x1, iBlock.m_y2+1, m_x2, m_y2 );
322
if ( m_x1 < iBlock.m_x1 )
324
left = wxBlockInt( m_x1, iBlock.m_y1, iBlock.m_x1-1, iBlock.m_y2 );
327
if ( GetRight() > iBlock.GetRight() )
329
right = wxBlockInt( iBlock.m_x2+1, iBlock.m_y1, m_x2, iBlock.m_y2 );
336
//=============================================================================
338
//=============================================================================
340
bool wxBlockDouble::Touches(const wxBlockDouble &b) const // see Intersects
342
if (((wxMax(m_x1, b.m_x1)) <= (wxMin(m_x2, b.m_x2))) &&
343
((wxMax(m_y1, b.m_y1)) <= (wxMin(m_y2, b.m_y2))))
349
bool wxBlockDouble::Combine(const wxBlockDouble &b)
351
if (!Touches(b)) return false;
352
if (Contains(b)) return true;
353
if (b.Contains(*this))
359
wxBlockDouble unionBlock;
360
Union( *this, b, &unionBlock );
362
if (unionBlock.IsEmpty()) return false;
364
// at least one of the two blocks has to be at each corner of the union
365
if (((unionBlock.GetLeftTop() == GetLeftTop()) || (unionBlock.GetLeftTop() == b.GetLeftTop())) &&
366
((unionBlock.GetRightTop() == GetRightTop()) || (unionBlock.GetRightTop() == b.GetRightTop())) &&
367
((unionBlock.GetLeftBottom() == GetLeftBottom()) || (unionBlock.GetLeftBottom() == b.GetLeftBottom())) &&
368
((unionBlock.GetRightBottom() == GetRightBottom()) || (unionBlock.GetRightBottom() == b.GetRightBottom())) )
377
bool wxBlockDouble::Combine( const wxBlockDouble &block,
378
wxBlockDouble &top, wxBlockDouble &bottom,
379
wxBlockDouble &left, wxBlockDouble &right) const
381
top = bottom = left = right = wxEmptyBlockDouble;
383
wxBlockDouble iBlock;
384
Intersect(*this, block, &iBlock);
386
if (iBlock.IsEmpty()) return false; // nothing to combine
387
if (iBlock == *this) return true; // can combine all of this, no leftover
389
bool combined = false;
391
if ( block.m_y1 < m_y1 )
393
top = wxBlockDouble( block.m_x1, block.m_y1, block.m_x2, m_y1 );
396
if ( block.m_y2 > m_y2 )
398
bottom = wxBlockDouble( block.m_x1, m_y2, block.m_x2, block.m_y2 );
401
if ( block.m_x1 < m_x1 )
403
left = wxBlockDouble( block.m_x1, iBlock.m_y1, m_x1, iBlock.m_y2 );
406
if ( block.m_x2 > m_x2 )
408
right = wxBlockDouble( m_x2, iBlock.m_y1, block.m_x2, iBlock.m_y2 );
415
bool wxBlockDouble::Delete( const wxBlockDouble &block,
416
wxBlockDouble &top, wxBlockDouble &bottom,
417
wxBlockDouble &left, wxBlockDouble &right) const
419
top = bottom = left = right = wxEmptyBlockDouble;
421
wxBlockDouble iBlock;
422
Intersect(*this, block, &iBlock);
424
if (iBlock.IsEmpty()) return false; // nothing to delete
425
if (iBlock == *this) return true; // can delete all of this, no leftover
427
bool deleted = false;
429
if ( m_y1 < iBlock.m_y1 )
431
top = wxBlockDouble( m_x1, m_y1, m_x2, iBlock.m_y1 );
434
if ( m_y2 > iBlock.m_y2 )
436
bottom = wxBlockDouble( m_x1, iBlock.m_y2, m_x2, m_y2 );
439
if ( m_x1 < iBlock.m_x1 )
441
left = wxBlockDouble( m_x1, iBlock.m_y1, iBlock.m_x1, iBlock.m_y2 );
444
if ( m_x2 > iBlock.m_x2 )
446
right = wxBlockDouble( iBlock.m_x2, iBlock.m_y1, m_x2, iBlock.m_y2 );
453
//=============================================================================
454
// wxBlockIntSelection
455
//=============================================================================
456
wxBlockInt wxBlockIntSelection::GetBlock( int index ) const
458
wxCHECK_MSG((index>=0) && (index<int(m_blocks.GetCount())), wxEmptyBlockInt, wxT("Invalid index"));
459
return m_blocks[index];
463
wxArrayRangeInt wxBlockIntSelection::GetBlockCol(int col) const
465
wxArrayRangeInt ranges;
466
register int n, count = m_blocks.GetCount();
467
for (n=0; n<count; n++)
469
if ((col >= m_blocks[n].m_x1) && (col <= m_blocks[n].m_x2))
471
wxRangeInt range(m_blocks[n].m_y1, m_blocks[n].m_y2);
478
wxArrayRangeInt wxBlockIntSelection::GetBlockRow(int row) const
480
wxArrayRangeInt ranges;
481
register int n, count = m_blocks.GetCount();
482
for (n=0; n<count; n++)
484
if ((row >= m_blocks[n].m_y1) && (row <= m_blocks[n].m_y2))
485
ranges.Add(wxRangeInt(m_blocks[n].m_x1, m_blocks[n].m_x2));
489
#endif // USE_wxRANGE
491
wxBlockInt wxBlockIntSelection::GetBoundingBlock() const
493
register int n, count = m_blocks.GetCount();
494
if (count == 0) return wxEmptyBlockInt;
495
wxBlockInt bound = m_blocks[0];
496
for (n=1; n<count; n++) bound.Union(m_blocks[n]);
500
int wxBlockIntSelection::Index( int x, int y ) const
502
register int n, count = m_blocks.GetCount();
503
for (n=0; n<count; n++)
505
if ( m_blocks[n].Contains(x, y) )
511
int wxBlockIntSelection::Index( const wxBlockInt &b ) const
513
register int n, count = m_blocks.GetCount();
514
for (n=0; n<count; n++)
516
if (m_blocks[n].Intersects(b))
522
void wxBlockIntSelection::Sort(wxBlockSort_Type type)
525
wxArrayBlockIntSort(m_blocks, type);
528
bool wxBlockIntSelection::DeselectBlock( const wxBlockInt &block, bool combineNow)
530
wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") );
534
wxBlockInt top, bottom, left, right;
535
for (int n=0; n<int(m_blocks.GetCount()); n++)
537
if (m_blocks[n].Delete(block, top, bottom, left, right))
540
m_blocks.RemoveAt(n);
541
n = (n > 0) ? n - 1 : -1;
543
if (!top.IsEmpty()) m_blocks.Add(top);
544
if (!bottom.IsEmpty()) m_blocks.Add(bottom);
545
if (!left.IsEmpty()) m_blocks.Add(left);
546
if (!right.IsEmpty()) m_blocks.Add(right);
556
bool wxBlockIntSelection::SelectBlock( const wxBlockInt &block, bool combineNow,
557
wxArrayBlockInt *addedBlocks )
559
wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") );
563
wxArrayBlockInt extraBlocks;
564
wxArrayBlockInt *extra = &extraBlocks;
566
if (addedBlocks != NULL)
568
addedBlocks->Clear();
574
int n, count = m_blocks.GetCount();
575
wxBlockInt top, bottom, left, right;
577
for (n=0; n<count; n++)
579
for (int k=0; k<int(extra->GetCount()); k++)
581
if (m_blocks[n].Combine(extra->Item(k), top, bottom, left, right))
584
if (!top.IsEmpty()) extra->Add(top);
585
if (!bottom.IsEmpty()) extra->Add(bottom);
586
if (!left.IsEmpty()) extra->Add(left);
587
if (!right.IsEmpty()) extra->Add(right);
588
//DoMinimize( *extra );
595
if (extra->GetCount() > 0u)
597
WX_APPEND_ARRAY(m_blocks, *extra);
607
bool wxBlockIntSelection::Minimize()
609
bool ret = DoMinimize(m_blocks);
614
bool wxBlockIntSelection::DoMinimize(wxArrayBlockInt &blocks)
617
for (n=0; n<1000; n++) // should probably just take a few
619
if (!DoDoMinimize(blocks)) break;
622
#ifdef CHECK_BLOCK_OVERLAP
623
for (size_t a=0; a<blocks.GetCount(); a++)
625
for (size_t b=a+1; b<blocks.GetCount(); b++)
627
if (blocks[a].Intersects(blocks[b]))
629
printf("Intersecting blocks in wxBlockIntSelection::DoMinimize"); fflush(stdout);
639
bool wxBlockIntSelection::DoDoMinimize(wxArrayBlockInt &blocks)
641
// wxBlockInt top, bottom, left, right;
643
for (int i=0; i<int(blocks.GetCount())-1; i++)
645
for (int j=i+1; j<int(blocks.GetCount()); j++)
647
if (blocks[i].Combine(blocks[j]))
655
else if (blocks[i].Combine(blocks[j], top, bottom, left, right))
657
printf("INTERSECTION!?---------------------------\n"); fflush(stdout);
659
if (!top.IsEmpty()) blocks.Add(top);
660
if (!bottom.IsEmpty()) blocks.Add(bottom);
661
if (!left.IsEmpty()) blocks.Add(left);
662
if (!right.IsEmpty()) blocks.Add(right);
671
//=============================================================================
672
// wxBlockDoubleSelection
673
//=============================================================================
674
wxBlockDouble wxBlockDoubleSelection::GetBlock( int index ) const
676
wxCHECK_MSG((index>=0) && (index<int(m_blocks.GetCount())), wxEmptyBlockDouble, wxT("Invalid index"));
677
return m_blocks[index];
681
wxArrayRangeDouble wxBlockDoubleSelection::GetBlockCol(wxDouble col) const
683
wxArrayRangeDouble ranges;
684
register int n, count = m_blocks.GetCount();
685
for (n=0; n<count; n++)
687
if ((col >= m_blocks[n].m_x1) && (col <= m_blocks[n].m_x2))
689
wxRangeDouble range(m_blocks[n].m_y1, m_blocks[n].m_y2);
696
wxArrayRangeDouble wxBlockDoubleSelection::GetBlockRow(wxDouble row) const
698
wxArrayRangeDouble ranges;
699
register int n, count = m_blocks.GetCount();
700
for (n=0; n<count; n++)
702
if ((row >= m_blocks[n].m_y1) && (row <= m_blocks[n].m_y2))
703
ranges.Add(wxRangeDouble(m_blocks[n].m_x1, m_blocks[n].m_x2));
707
#endif // USE_wxRANGE
709
wxBlockDouble wxBlockDoubleSelection::GetBoundingBlock() const
711
register int n, count = m_blocks.GetCount();
712
if (count == 0) return wxEmptyBlockDouble;
713
wxBlockDouble bound = m_blocks[0];
714
for (n=1; n<count; n++) bound.Union(m_blocks[n]);
718
int wxBlockDoubleSelection::Index( wxDouble x, wxDouble y ) const
720
register int n, count = m_blocks.GetCount();
721
for (n=0; n<count; n++)
723
if ( (x >= m_blocks[n].m_x1) && (y >= m_blocks[n].m_y1) &&
724
(x <= m_blocks[n].m_x2) && (y <= m_blocks[n].m_y2) )
730
int wxBlockDoubleSelection::Index( const wxBlockDouble &b ) const
732
register int n, count = m_blocks.GetCount();
733
for (n=0; n<count; n++)
735
if (m_blocks[n].Intersects(b))
741
void wxBlockDoubleSelection::Sort(wxBlockSort_Type type)
744
wxArrayBlockDoubleSort(m_blocks, type);
747
bool wxBlockDoubleSelection::DeselectBlock( const wxBlockDouble &block, bool combineNow)
749
//wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") );
753
wxBlockDouble top, bottom, left, right;
754
for (int n=0; n<int(m_blocks.GetCount()); n++)
756
if (m_blocks[n].Delete(block, top, bottom, left, right))
759
m_blocks.RemoveAt(n);
760
n = (n > 0) ? n - 1 : -1;
762
if (!top.IsEmpty()) m_blocks.Add(top);
763
if (!bottom.IsEmpty()) m_blocks.Add(bottom);
764
if (!left.IsEmpty()) m_blocks.Add(left);
765
if (!right.IsEmpty()) m_blocks.Add(right);
775
bool wxBlockDoubleSelection::SelectBlock( const wxBlockDouble &block, bool combineNow)
777
// It's valid to select a block with a width and height 0 since that means that point
778
//wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") );
780
wxArrayBlockDouble extra;
782
wxBlockDouble top, bottom, left, right;
784
for (int n=0; n<int(m_blocks.GetCount()); n++)
786
for (int k=0; k<int(extra.GetCount()); k++)
790
// Doubles are different than ints - roundoff error problems
791
// always use the bigger block to soak up the smaller blocks
792
// this reduces problems with tiny roundoff error produced blocks
793
if (m_blocks[n].Intersects(extra[k]))
795
if (m_blocks[n].Contains(extra[k]))
801
else if (extra[k].Contains(m_blocks[n]))
803
m_blocks.RemoveAt(n);
807
else if (m_blocks[n].IsLarger(extra[k]) > 0)
809
done = m_blocks[n].Combine(extra[k], top, bottom, left, right);
818
done = extra[k].Combine(m_blocks[n], top, bottom, left, right);
821
m_blocks.RemoveAt(n);
829
if (!top.IsEmpty()) extra.Add(top);
830
if (!bottom.IsEmpty()) extra.Add(bottom);
831
if (!left.IsEmpty()) extra.Add(left);
832
if (!right.IsEmpty()) extra.Add(right);
833
//DoMinimize( extra );
840
if (extra.GetCount() > 0u)
842
WX_APPEND_ARRAY(m_blocks, extra);
852
bool wxBlockDoubleSelection::Minimize()
854
bool ret = DoMinimize(m_blocks);
859
bool wxBlockDoubleSelection::DoMinimize(wxArrayBlockDouble &blocks)
862
for (n=0; n<1000; n++) // should probably just take < 10 at most
864
if (!DoDoMinimize(blocks)) break;
867
#ifdef CHECK_BLOCK_OVERLAP
868
for (size_t a=0; a<blocks.GetCount(); a++)
870
printf("Checking wxBlockDoubleSelection::DoMinimize %d =", a); PRINT_BLOCK("", blocks[a])
871
for (size_t b=a+1; b<blocks.GetCount(); b++)
873
if (blocks[a].Intersects(blocks[b]))
875
printf("Intersecting blocks in wxBlockDoubleSelection::DoMinimize\n"); fflush(stdout);
876
PRINT_BLOCK("",blocks[a])
877
PRINT_BLOCK("",blocks[b])
887
bool wxBlockDoubleSelection::DoDoMinimize(wxArrayBlockDouble &blocks)
889
//wxBlockDouble top, bottom, left, right;
892
for (int i=0; i<int(blocks.GetCount())-1; i++)
894
for (int j=i+1; j<int(blocks.GetCount()); j++)
896
if (blocks[i].Combine(blocks[j]))
903
else if (blocks[i].Combine(blocks[j], top, bottom, left, right))
906
if (!top.IsEmpty()) blocks.Add(top);
907
if (!bottom.IsEmpty()) blocks.Add(bottom);
908
if (!left.IsEmpty()) blocks.Add(left);
909
if (!right.IsEmpty()) blocks.Add(right);
918
//=============================================================================
919
// wxBlockIntSelectionIterator - iterates through a wxBlockIntSelection
920
//=============================================================================
922
wxBlockIntSelectionIterator::wxBlockIntSelectionIterator( const wxBlockIntSelection &sel,
926
WX_APPEND_ARRAY(m_blocks, sel.GetBlockArray());
927
m_blocks.Sort(wxblockint_sort_topleft_bottomright);
931
wxBlockIntSelectionIterator::wxBlockIntSelectionIterator( const wxArrayBlockInt &blocks,
935
WX_APPEND_ARRAY(m_blocks, blocks);
936
m_blocks.Sort(wxblockint_sort_topleft_bottomright);
940
void wxBlockIntSelectionIterator::Reset()
943
m_pt = wxPoint2DInt(0, 0);
946
bool wxBlockIntSelectionIterator::GetNext(wxBlockInt &block)
948
wxCHECK_MSG(m_type == wxBISI_BLOCK, false, wxT("wrong selection type"));
949
if (m_block_index+1 < int(m_blocks.GetCount()))
952
block = m_blocks[m_block_index];
959
bool wxBlockIntSelectionIterator::GetNext(wxPoint2DInt &pt)
961
wxCHECK_MSG(m_type == wxBISI_POINT, false, wxT("wrong selection type"));
962
if ((m_blocks.GetCount() < 1u) || (m_block_index >= int(m_blocks.GetCount())))
966
if (m_block_index < 0)
969
pt = m_pt = m_blocks[m_block_index].GetLeftTop();
973
// at end of block swap to new one
974
if (m_pt == m_blocks[m_block_index].GetRightBottom())
977
if (int(m_blocks.GetCount()) > m_block_index)
979
pt = m_pt = m_blocks[m_block_index].GetLeftTop();
982
else // past end nothing more to check
985
// at end of col, down to next row
986
if (m_pt.m_x == m_blocks[m_block_index].GetRight())
988
m_pt.m_x = m_blocks[m_block_index].m_x1;
1002
bool wxBlockIntSelectionIterator::IsInSelection(const wxPoint2DInt &pt) const
1004
register int n, count = m_blocks.GetCount();
1005
for (n=0; n<count; n++)
1007
if (m_blocks[n].Contains(pt))
1013
//=============================================================================
1014
// wxBlockDoubleSelectionIterator - iterates through a wxBlockDoubleSelection
1015
//=============================================================================
1017
wxBlockDoubleSelectionIterator::wxBlockDoubleSelectionIterator( const wxBlockDoubleSelection &sel )
1019
WX_APPEND_ARRAY(m_blocks, sel.GetBlockArray());
1020
m_blocks.Sort(wxblockdouble_sort_topleft_bottomright);
1024
wxBlockDoubleSelectionIterator::wxBlockDoubleSelectionIterator( const wxArrayBlockDouble &blocks )
1026
WX_APPEND_ARRAY(m_blocks, blocks);
1027
m_blocks.Sort(wxblockdouble_sort_topleft_bottomright);
1031
void wxBlockDoubleSelectionIterator::Reset()
1036
bool wxBlockDoubleSelectionIterator::GetNext(wxBlockDouble &block)
1038
if (m_block_index < m_blocks.GetCount())
1040
block = m_blocks[m_block_index];
1048
bool wxBlockDoubleSelectionIterator::IsInSelection(const wxPoint2DDouble &pt) const
1050
register int n, count = m_blocks.GetCount();
1051
for (n=0; n<count; n++)
1053
if (m_blocks[n].Contains(pt))
1059
// ============================================================================
1060
// ============================================================================
1061
// ============================================================================
1062
// ============================================================================
1063
// ============================================================================
1064
// Unit testing, sortof