Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // script.name = fitCircleToCorner,jsx
- // script.description = it moves a circle to the tightest fit in a selected corner point
- // script.required = One circle and one Straight Lines Corner Anchor Point selected.
- // script.parent = CarlosCanto // 10/20/12;
- // script.elegant = false;
- // USAGE select a circle and a single coner point on a polygone to fit the circle tangent to that corner.
- // for easy selection, use the white arrow and click on the center of the circle and then on a single point on a polygone
- #target "illustrator"
- var doc = app.activeDocument;
- var sel = doc.selection;
- if (sel.length==2) { // need two selected paths, the circle and the polygone
- var circle = null;
- var polygone = null;
- var polyPoints = null;
- for (j=0; j<sel.length; j++) { //
- var pat = sel[j];
- // check each selected path for a corner point, if one is not then the path is the circle
- var obj = isCornerPoint(pat); // the obj returned holds wether there is a corner point selected and wich points of the 3 are p1, p0, p2
- if (obj.selected=='true') { // then this is the polygon
- polygone = pat;
- polyPoints = obj;
- }
- else {
- // NOT the corner point, now check if it is a "true" circle
- if (pat.pathPoints.length == 4) {
- if (isItAcircle (pat)) {
- circle = pat;
- }
- else
- alert('the path is not a circle');
- }
- }
- }
- // if either circle or polygone are null, abort
- if (circle==null || polygone ==null) { // circle = null, both the circle and the polygone have 3 selected pathPoints,
- if (polygone == null) alert('a single corner point needs to be selected')
- alert('Select ONE single Corner Point on a Polygone and ONE Fully selected Circle'); // polygone = null, it needs to have only on anchor point selected
- }
- else {
- //alert ('good, continue');
- fitCircle (polyPoints, circle);
- }
- }
- else {
- alert('select a circle and a single coner point on a polygon');
- }
- //---------------------------------------------------------------------------
- // check if pathItem passed is a "corner" point, meaning the path has1 anchor point selected
- // return if it is a corner + the acutal anchor (p0) + p1 and p2, which makes the angle p1-p0-p2
- function isCornerPoint(pi /*pathItem*/) {
- var anchorsSelected = 0;
- var cornerCount = 0;
- var p0 = [];
- var p12 = [];
- var idx = null;
- var sPP = pi.selectedPathPoints;
- if (sPP.length != 3) { // if other than 3 points are selected, exit, this path has not a corner point selected
- return {selected:'false', idx:idx, p0:p0, p12:p12}
- }
- // continue if 3 pathPoints are selected (1 anchor + 2 handles)
- var selRt = PathPointSelection.RIGHTDIRECTION;
- var selAn = PathPointSelection.ANCHORPOINT;
- var selLt = PathPointSelection.LEFTDIRECTION;
- // loop thru all 3 points to get only 1 anchor selected
- for (i=0; i<sPP.length; i++) {
- if (sPP[i].selected == selAn) {
- cornerCount ++;
- idx = i; // if idx = 0, then it is the path's first anchor, idx=2, then is the path's last anchor, idx =1, then it is any other anchor
- anchorsSelected++; // count them, if more than 1, it can't be used as a "corner"
- p0.push(sPP[i]); // this will hold p0, if more than one, then it can't be used as a "corner" point
- }
- else {
- // check if point is not "smooth", handles towards corner must be at the same x,y as point.Anchor
- if (sPP[i].selected == selRt && sPP[i].anchor.toString() == sPP[i].rightDirection.toString()) {
- cornerCount ++;
- }
- else if (sPP[i].selected == selLt && sPP[i].anchor.toString() == sPP[i].leftDirection.toString()) {
- cornerCount ++;
- }
- p12.push(sPP[i]); // push the pathPoints that are not selected, it will hold p1 and p2
- }
- }
- if (p0.length==1 && cornerCount==3) {
- return {selected:'true', idx:idx, p0:p0, p12:p12}
- }
- return {selected:'false', idx:idx, p0:p0, p12:p12}
- }
- // --------------------------------------------------------------------------------------------------------
- // --------------------------------------------------------------------------------------------------------
- function fitCircle (cornerPathPoints, circle) {
- var pat = cornerPathPoints;
- var circle = circle;
- var r = circle.width/2;
- var angRad = get3pointAngle(pat); // this is the angle info object
- var h = r/Math.sin(angRad.ang1o2/2); // hypotenuse, distance from selected point to center of circle at half the agnle between points
- var x1 = h*Math.cos(angRad.angHalf)+angRad.Po[0]; // center of circle pos x
- var y1 = h*Math.sin(angRad.angHalf)+angRad.Po[1]; // center of circle pos y
- reposition(circle, x1, y1, r);
- function reposition (obj, x, y, r) {
- obj.position = [x-r, y+r];
- }
- function get3pointAngle(pi /*pathPoints object*/) {
- var p1 = pi.p12[0].anchor;
- var o = pi.p0[0].anchor;
- var p2 = pi.p12[1].anchor;
- // get both angles individually
- var ang1 = get2pointAngle(o,p1);
- var ang2 = get2pointAngle(o,p2);
- // who's the bigger
- var angbig = Math.max (ang1, ang2);
- var angsmall = Math.min (ang1, ang2);
- ang1 = angsmall; // make 1 the smaller
- ang2 = angbig; // make 2 the bigger
- var ang1o2 = ang2-ang1; // this is the p1-o-p2 angle (ie 60)
- var halfangle = ((ang2 - ang1) /2)+ang1; // this is half the p1-o-p2 angle (ie 30) but from the horizon (ie 135)
- // if angle 1o2 is over 180 deg then inside corner should be on the other side (add 180 deg or Pi)
- if (Math.abs(ang1o2)>Math.PI) {
- halfangle = halfangle + Math.PI;
- }
- var angle = {ang1o2:ang1o2, angHalf:halfangle, Po:o}; // angle info object
- return angle;
- }
- // return the angle from p1 to p2 in Radians. p1 is the origin, p2 rotates around p1
- function get2pointAngle(p1, p2) {
- var angl = Math.atan2(p2[1] - p1[1], p2[0] - p1[0]);
- if (angl<0) { // atan2 returns angles from 0 to Pi, if angle is negative it means is over 180 deg or over Pi, add 360 deg or 2Pi, to get the an absolute Positive angle from 0-360 deg
- angl = angl + 2*Math.PI;
- }
- return angl; //
- }
- }
- // ---------------------------------------------------------------------------------------------------------------------
- // ---------------------------------------------------------------------------------------------------------------------
- // based on Area and Perimeter Circle formulas, solving for Pi, both should be equal, or close but they're not. Bezier approx may it be?
- // if both are equal to the hard coded Pi, then tha path is a circle. 2 pt circles result as "not circles" with 3 digit precision
- function isItAcircle (path) {
- var sel = path;
- var areaPi = sel.area/Math.pow(sel.width/2,2);
- var periPi = sel.length/sel.width;
- var decimals = 2; // two decimal gives us some distortion tolerance, we don't want to be too precise and rule all shapes as 'not circles'
- var bezierPi = 3.14;
- areaPi = roundnumber (areaPi, decimals);
- periPi = roundnumber (periPi, decimals);
- if (areaPi==bezierPi && periPi==bezierPi)
- return true; //x = 'circle';
- else
- return false; //x = 'not a circle';
- }
- // ---------------------------------------------------------------------------------------------------------------------
- // ---------------------------------------------------------------------------------------------------------------------
- // round a number by x decimals
- function roundnumber(number, decimals) {
- rounded = (Math.round(number*Math.pow(10,decimals))/Math.pow(10,decimals));//.toFixed(decimals); // to pad with zeros if necessary
- return rounded;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement