-
Notifications
You must be signed in to change notification settings - Fork 11
/
Group Overlapping Objects.jsx
232 lines (202 loc) · 5.85 KB
/
Group Overlapping Objects.jsx
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/////////////////////////////////////////////////////////////////
//Group Overlapping (Beta) -- CS, CS2, CS3
//>=--------------------------------------
//
// Groups all overlapping objects in selection into discreet groups.
// The definition for 'overlaping' is based on objects bounding boxes, not their actual geometry.
// Each new groups zOrder is determined by the depth of the front-most object in each group.
// There is no limit to the number of groups created.
// Any non-overlapping objects are ignored.
//
// Note: Currently, this is not very efficient code. It works well on small groups (less than 120 objects)
// and works faster on smaller groupings. Running this on a huge number of objects will likely crash illustrator.
// It serves my purposes, but test it's limits on your machine, and use at your own risk.
// On a 2.53GHz P4, a group of 100 objects took 20 seconds with 2 groups.
//
//
//>=--------------------------------------
// JS code (c) copyright: John Wundes ( john@wundes.com ) www.wundes.com
//copyright full text here: http://www.wundes.com/js4ai/copyright.txt
//////////////////////////////////////////////////////////////////
//this little section is just for testing
//the number of times each function is called.
var testmode = 0;
var t1 = t2 = t3 = t4 = t5 = t6 = t7 = 0;
var testmsg = "";
//
//
//
var go = true;
if (selection.length > 120) {
go = confirm("You have selected " + selection.length + " objects. It is highly recommended that you select less than 120 objects at a time. Do you want to continue anyway?");
}
if (selection.length > 1 && go == true) {
var groups = 0;
var slen = selection.length;
var hitList = new Array(slen);
var groupArr = new Array(slen);
// for each element in selection
for (var sx = 0; sx < slen; sx++) {
//t6++; //---------------------------------------------loop tracker
var tArr = new Array(0);
// for each element in selection (again)
for (var si = 0; si < slen; si++) {
//t7++; //-------------------------------------loop tracker
groupArr[sx] = tArr;
//note each object hits itself once.
if (hitTest(selection[sx], selection[si])) {
groupArr[sx].push(selection[si]);
}
}
}
minimize(groupArr);
var zError = 0;
var gaLen = groupArr.length;
for (var each = 0; each < gaLen; each++) {
if (groupArr[each].length > 1) {
groupArr[each].sort(sortBy_zOrder);
}
if (zError == 1) {
alert("cannot read some objects zOrderPosition");
}
//alert("halftime");
for (var each = 0; each < gaLen; each++) {
t1++; //----------------------------------------------loop tracker
if (groupArr[each].length > 1) {
groups++;
groupAll(groupArr[each]);
}
}
//
//---all done with main code, now display statistics if you care...
//
testmsg = "\nObjects processed: " + t1 + "\nObjects grouped: " + t2 + "\nObjects ignored: " + (t1 - t2);
if (testmode == 1) {
testmsg += "\n\n---testmode data---\nhits compared: " + t5 + "\nfunction 'minimize' called: " + t3 + "\nitems tested within 'minimize': " + t4;
"\nelements: " + t6 + "\nelements*elements: " + t7;
}
var x = 0;
while (x < selection.length) {
if (selection[x].name == "wundes_GO_group") {
selection[x].name = "";
} else {
selection[x].selected = false;
x--;
}
x++;
}
redraw();
alert(groups + " groups created.\n----------------" + testmsg);
}
}
//----------------------------------------------------------->
//--------------------------------functions------------------<
//----------------------------------------------------------->
function sortBy_zOrder(a, b) {
if (a.zOrderPosition == undefined) {
alert(a.zOrderPosition);
zError = 1;
return 0;
}
var x = Number(a.zOrderPosition);
var y = Number(b.zOrderPosition);
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}
function groupAll(arr) {
var tempGroup = arr[0].parent.groupItems.add();
tempGroup.move(arr[0], ElementPlacement.PLACEBEFORE);
var max = arr.length;
for (var i = max - 1; i >= 0; i--) {
t2++; //-----------------------------------------loop tracker
arr[i].move(tempGroup, ElementPlacement.INSIDE);
}
//name the object for selection at end... (will be removed later)
tempGroup.name = "wundes_GO_group";
tempGroup.selected = true;
}
//---------------hitTest functions ---------------
function hitTest(a, b) {
var OK = 0;
if (isWithinX(a, b) || isWithinX(b, a)) {
OK++;
}
if (isWithinY(a, b) || isWithinY(b, a)) {
OK++;
}
if (OK < 2) {
//alert("miss.");
return false;
} else {
//alert("Hit!")
return true;
}
}
function isWithinX(a, b) {
var p1 = a.geometricBounds[0];
var p2 = b.geometricBounds[0];
if (p2 <= p1 && p1 <= p2 + b.width) {
return true;
} else {
return false;
}
}
function isWithinY(a, b) {
var p3 = a.geometricBounds[1];
var p4 = b.geometricBounds[1];
if (p3 >= p4 && p4 >= (p3 - a.height)) {
return true;
}
return false;
}
/*
//-----------------------------------OK, finding groups is done, now do the grouping---------------
*/
function itemize(a) {
var out = "";
return (a.join("\n"));
}
function minimize(arr) {
for (var e in arr) {
t3++; //-----------------------------------------loop tracker
for (ot in arr) {
t4++; //-------------------------------------loop tracker
if (arr[e] != arr[ot]) {
//if it's not THIS element,
//test for overlaps
if (overlaps(arr[e], arr[ot])) {
merge(arr[e], arr[ot]);
arr[e] = new Array(0);
minimize(arr);
break;
}
}
}
}
}
function merge(a, b) {
var alen = a.length;
for (var all = 0; all < alen; all++) {
if (contains(b, a[all])) {
//do nothing
} else {
b.push(a[all]);
}
}
}
function contains(ar, i) {
for (var all in ar) {
if (ar[all] == i) {
return true;
}
}
return false;
}
function overlaps(ar1, ar2) {
for (var each in ar1) {
t5++; //------------------------------------loop tracker
if (contains(ar2, ar1[each])) { //
return true;
}
}
return false;
}