// WEdgeSlide 1.2 // Author: alexione/mindnever (alexione@mindnever.org) // Created on 22-29.09.2005. // USAGE: // 1. select points of edges // 2. call plugin in point selection mode // NOTES: // - plugin supports any percent and uniformness, not only -100..100 // GREETING: // to greent/mindnever (greent@mindnever.org) for idea and testing // HISTORY: // 1.1 - bugfixes // 1.2 - faster; please, report if not working! // - better undo // 1.3 - Uniformness slider @version 2.1 @script modeler @name WEdgeSlide npoints; pointchecked; pointpos; // original positions pointline1, pointline2; // (-100) pointline1[i] <- points[i] -> pointline2[i] (+100) pointstack; pointstacktop, pointstackbottom; firstundo; lastpercent = 0; maxdist; slide_percent; slide_uniformness; main { selmode(DIRECT); editbegin(); // ---------------------------------------------------- // check number of selected points // ---------------------------------------------------- npoints = pointcount(); if(npoints < 2) { error("You need at least 2 points selected."); return; } editend(); selmode(USER); editbegin(); // ---------------------------------------------------- // generate pointline1 and pointline2 // ---------------------------------------------------- for (i = 1; i <= npoints; i++) { pt = points[i]; pointchecked[pt] = false; pointpos[pt] = ; pointline1[pt] = 0; pointline2[pt] = 0; } for (i = 1; i <= npoints; i++) { pt = points[i]; if (!pointchecked[pt]) { pointstackbottom = 1; pointstacktop = 1; pointstack[pointstacktop] = pt; while (pointstackbottom <= pointstacktop) { pt = pointstack[pointstackbottom++]; if (!pointchecked[pt]) { pointchecked[pt] = true; //info("check_point " + pt); n = pt.polygon; ptpolygons = pt.polygon(); for (j = 1; j <= n; j++) check_polygon(ptpolygons[j], pt); } } } } // ---------------------------------------------------- // calculate maxdist // ---------------------------------------------------- maxdist = 0; for (i = 1; i <= npoints; i++) { pt = points[i]; pt2 = pointline1[pt]; if (pt2) { d = vmag(pointinfo(pt2) - pointinfo(pt)); if (!maxdist || (d < maxdist)) maxdist = d; } pt2 = pointline2[pt]; if (pt2) { d = vmag(pointinfo(pt2) - pointinfo(pt)); if (!maxdist || (d < maxdist)) maxdist = d; } } editend(); // ---------------------------------------------------- // create interface // ---------------------------------------------------- firstundo = true; reqbegin("WEdgeSlide"); reqsize(200, 85); slide_percent = 0; cPercent = ctlminislider("Percent", slide_percent, -100, 100); ctlposition(cPercent, 26, 5, 149); ctlrefresh(cPercent, "update_percent"); slide_uniformness = 0; cUniformness = ctlminislider("Uniformness", slide_uniformness, 0, 100); ctlposition(cUniformness, 5, 30, 170); ctlrefresh(cUniformness, "update_uniformness"); if (!reqpost()) { slide_points(0, 0); return; } } // ------------------------------------------------------------ // checks polygon edges which contain point pt // ------------------------------------------------------------ check_polygon: ipoly, pt { n = ipoly.pointCount; i = 1; while (ipoly.points[i] != pt) i++; a2 = ipoly.points[round_n(i - 2, n)]; a1 = ipoly.points[round_n(i - 1, n)]; b1 = ipoly.points[round_n(i + 1, n)]; b2 = ipoly.points[round_n(i + 2, n)]; //a2sel = pointselected(a2); //a1sel = pointselected(a1); //b1sel = pointselected(b1); //b2sel = pointselected(b2); //info("check_line " + a2 + " " + a1 + " " + pt + " " + b1 + " " + b2); // if (!a2sel && a1sel && !b1sel) if (!(a2 <= npoints) && (a1 <= npoints) && !(b1 <= npoints)) { check_edge(b1, pt, a1, a2); if (!pointchecked[a1]) pointstack[++pointstacktop] = a1; } //else if (!a1sel && b1sel && !b2sel) else if (!(a1 <= npoints) && (b1 <= npoints) && !(b2 <= npoints)) { check_edge(a1, pt, b1, b2); if (!pointchecked[b1]) pointstack[++pointstacktop] = b1; } } // ------------------------------------------------------------ // check edge i1 - j1 where i1 slides to i2 and j1 slides to j2 // ------------------------------------------------------------ check_edge: i2, i1, j1, j2 { i11 = pointline1[i1]; i12 = pointline2[i1]; j11 = pointline1[j1]; j12 = pointline2[j1]; if (i11) { if (i11 == i2) side = 1; else side = 2; } else if (i12) { if (i12 == i2) side = 2; else side = 1; } else if (j11) { if (j11 == j2) side = 1; else side = 2; } else if (j12) { if (j12 == j2) side = 2; else side = 1; } else side = 1; if (side == 1) { if (!i11 && (i12 != i2)) pointline1[i1] = i2; if (!j11 && (j12 != i2)) pointline1[j1] = j2; } else { if (!i12 && (i11 != i2)) pointline2[i1] = i2; if (!j12 && (j11 != i2)) pointline2[j1] = j2; } } // ------------------------------------------------------------ // update methods // ------------------------------------------------------------ update_percent: value { slide_percent = value; slide_points(slide_percent, slide_uniformness); } update_uniformness: value { slide_uniformness = value; slide_points(slide_percent, slide_uniformness); } // ------------------------------------------------------------ // slides all points // ------------------------------------------------------------ slide_points: percent, uniformness { if (firstundo) firstundo = false; else if (lastpercent) undo(); if (percent) { editbegin(); for (i = 1; i <= npoints; i++) { pt = points[i]; pointmove(pt, interpolate_point(pt, percent / 100, uniformness / 100)); } editend(); } lastpercent = percent; } // ------------------------------------------------------------ // iterpolate position of ipoint // ------------------------------------------------------------ interpolate_point: ipoint, percent, uniformness { if (percent >= 0) { pt2 = pointline1[ipoint]; if (!pt2) { pt2 = pointline2[ipoint]; percent = -percent; } } else { pt2 = pointline2[ipoint]; if (!pt2) pt2 = pointline1[ipoint]; else percent = -percent; } pt = pointpos[ipoint]; if (!pt2) return pt; else { delta = ; d = vmag(delta); if (d) percent2 = percent * maxdist / d; else percent2 = 0; return pt + ((1 - uniformness) * percent + uniformness * percent2) * delta; } } // ------------------------------------------------------------ // check if point is selected // ------------------------------------------------------------ pointselected: pt { for (i = 1; i <= npoints; i++) if (points[i] == pt) return true; return false; } // ------------------------------------------------------------ // round i to [1..n] // ------------------------------------------------------------ round_n: i, n { while (i < 1) i = i + n; while (i > n) i = i - n; return i; }