
1. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Oct 12, 2015 1:25 AM (in response to ajaatshatru)I would think that the left control points go to the left (750,1234) which in your specific case is between 2 and 3 and that the right control points go to the right (757, 1238) which in your case is between 3 and 4.

2. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
ajaatshatru Oct 12, 2015 1:51 AM (in response to Trevorׅ)But I believe this is a quadratic Bezier curve and there need to be two control points to represent it accurately. How would that be satisfied if what you propose is true?

3. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Oct 12, 2015 1:56 AM (in response to ajaatshatru)I think it's cubic and not quadratic, I once looked into it and seem to remember that's what I found documented.
Time for some googling

4. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
pkahrel Oct 12, 2015 2:24 AM (in response to ajaatshatru)1 person found this helpfulIt's clearer if you present the path as an array of arrays (values rounded here):
[
[519,1135],
[613,1135],
[[647,1169],[750,1234],[757,1238]],
[782,1254],
[1536,2048]
]
The third line indicates that the anchor point is at [750,1234] and that the anchor has two handles. When you select an anchor with the direct selection tool you see any handles. The anchor point in line 3 has two handles: the incoming one ('leftDirection') is [647,1169], the outgoing one ('rightDirection') is [757, 1238]. The values are the coordinates of the handles. When you select a handle, the Transform panel shows the coordinates of the anchor, not the handle. (Only when you press a handle and you keep the mouse button down do you see the handle's coordinates, but very briefly.) But you can see a handle's coordinates in the Info panel, see the screenshot.
The selected anchor is at 186,400, the outgoing ('rightDirection') handle is at 220,400 (couldn't get the mouse pointer exactly on the spot). The path of this curve can be represented in several ways:
[
[[134, 500], [134, 457], [134, 420]],
[[150, 400], [186, 400], [220, 400]],
[[230, 420], [230, 436], [230, 457]],
]
or
[
[leftDirection = [134, 500],
anchor = [134, 457],
rightDirection = [134, 420]
],
[leftDirection = [150, 400],
anchor = [186, 400],
rightDirection = [220, 400]
],
[leftDirection = [230, 420],
anchor = [230, 436],
rightDirection = [230, 457]
],
];
Peter

5. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
pkahrel Oct 12, 2015 2:26 AM (in response to Trevorׅ)InDesign's curves and handles essentially work the same way as in FontLab, Fontographer, Illustrator, CorelDraw, etc.
P.

6. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
ajaatshatru Oct 12, 2015 2:42 AM (in response to pkahrel)Thanks a ton for this comprehensive explanation!

7. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
ajaatshatru Oct 12, 2015 2:49 AM (in response to pkahrel)I have one more question. So I understand, the Bezier between two anchor points a and b can be drawn using the leftControl of b and rightControl of a. But according to the screenshot I posted above, it is not possible as there is no other anchor point with controlPoints so how would I draw a Bezier then?

8. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
pkahrel Oct 12, 2015 3:05 AM (in response to ajaatshatru)Let's sort out some terminology: a Bézier curve is the whole curve. What you call 'control points' are usually called 'handles'. Those handles are used to change the shape of the curve. How exactly the shape is changed when you drag a handle depends on the type of anchor: smooth, symmetrical, etc.
If you have two anchors a and b, the shape of the curve connection a and b can be changed by dragging the outgoing handle of a and/or the incoming handle of b (assuming that you started at a).
To place an anchor with handles, choose the pen tool, click somewhere, keep the mouse button down, and drag somewhere. You'll see the handles appear. If you've not worked with Bézier before it can be a bit of a challenge but it's not really very difficult. Some practice will make things clear. Look into point conversion (Object > Convert point) and the Convert Direction Tool in the Tools menu. Doodle around and draw and change lots of curves!
P.

9. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
ajaatshatru Oct 12, 2015 3:35 AM (in response to pkahrel)I thought that every anchor point was connected by Bezier curves and using the control points I could draw a curve in HTML too. What do I do if I wish to do that?

10. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
pkahrel Oct 12, 2015 3:45 AM (in response to ajaatshatru)> I thought that every anchor point was connected by Bezier curves . . .
Yes, you're right about that.
> . . . and using the control points I could draw a curve in HTML too. What do I do if I wish to do that?
In HTML? I haven't a clue.

11. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
ajaatshatru Oct 12, 2015 3:49 AM (in response to pkahrel)So to draw a Bezier curve between two points we need the two points between which we wish to draw a curve and two control points. So considering I have the information supplied by InDesign, how would that translate into the the format I require, that is basically my query.

12. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Oct 12, 2015 3:49 AM (in response to pkahrel)Not so much an indesign question but you can mess around with HTML canvas bezierCurveTo() Method and google bezier curve html5 demo

13. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Oct 12, 2015 4:03 AM (in response to Trevorׅ)This is a nice link https://developer.mozilla.org/enUS/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes
The below is pasted from there
Cubic Bezier curves
This example draws a heart using cubic Bézier curves.
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
// Quadratric curves example
var path = new Path2D();
path.moveTo(75,40);
path.bezierCurveTo(75,37,70,25,50,25);
path.bezierCurveTo(20,25,20,62.5,20,62.5);
path.bezierCurveTo(20,80,40,102,75,120);
path.bezierCurveTo(110,102,130,80,130,62.5);
path.bezierCurveTo(130,62.5,130,25,100,25);
path.bezierCurveTo(85,25,75,37,75,40);
ctx.fill(path);
}
}

14. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
pkahrel Oct 12, 2015 4:32 AM (in response to Trevorׅ)Nice link, Trevor, thanks.
So in the earlier example, this shape:
ctx.moveTo(20,20);
ctx.bezierCurveTo(20,100,200,100,200,20);
corresponds with the shape you get in InDesign with this script:
g = app.documents[0].pages[0].graphicLines.add ({strokeWeight: 0.5});
g.paths[0].entirePath =
[
[[20, 20], [20, 20], [20, 100]],
[[200, 100], [200, 20], [200, 20]],
];
The curve has two anchors. First anchor at 20,20; no handle, i.e. the incoming handle is on the anchor. The second point has no outgoing handle.
To translate InDesign's path to HTML, do a moveTo to the path's first anchor (myCurve.paths[0].pathPoints[0].anchor).
From there you can work out how to proceed.
P.

15. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Marc Autret Oct 12, 2015 6:38 AM (in response to pkahrel)Hi all,
First, InDesign uses cubic Bezier curves.
And now, here is the best reference ever about dealing with Bezier curves:
@+,
Marc

16. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Harbs. Oct 12, 2015 7:14 AM (in response to Marc Autret)Marc Autret wrote:
And now, here is the best reference ever about dealing with Bezier curves:
Wow! Now that is comprehensive!
I've bookmarked that page to read when I have the mental capacity to digest some of it...
Thanks!
Harbs

17. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Harbs. Oct 12, 2015 7:16 AM (in response to Trevorׅ)The easiest way to draw this stuff in HTML is using EaselJS.

18. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Oct 12, 2015 11:29 AM (in response to Harbs.)HI Marc and all,
I made a script earlier in the year and read at least some that link then, it was a bit difficult to apply in practice in Illustrator or InDesign.
I needed to as per UI entry draw templates with arches at their ends using bezier curves. For the simple 1/4 circles rounded corners I used an approximation of something like .55 for the right handle and .45 for the left.
Below is a snippet of part of the script (it was for Illustrator but the principles are the same for ID)
const kLeft = r * 0.44771575927734444444, // constant for leftDirection handle for a 90 degree arc kRight = r * 0.55228508843315972222; // constant for rightDirection handle for a 90 degree arc var c, l, arcPaths, pathPoints; top = (top == true  top == "top") ? "top" : "bottom"; arcPaths = { top : { // top path starting from top right anchors: [[x, y], [x  r, y  r]], rightDirections: [[x, y], [x  r, y  kLeft]], leftDirections: [[x  kRight, y], [x  r, y  r]], pointTypes: [PointType.CORNER, PointType.CORNER] }, bottom: { // bottom path starting from top left anchors: [[x, y], [x + r, y  r]], rightDirections: [[x, y], [x + kLeft, y  r]], leftDirections: [[x, y  kRight], [x + r, y  r]], pointTypes: [PointType.CORNER, PointType.CORNER] } };
The above would produce the paths and handles which I pushed into arrays to produce the shapes.
That was the easy bit. The harder bit was that I needed to adds arches of a given radius and width / sagitta.
I wanted to do it mathematically but in the end took the path that I think the OP is taking of using ID or Ai as a crutch to do the math, so I got Ai to draw a circle and a correctly placed rectangle, excluded the rectangle from the circle copied the path of the resulting arc, removed the arc and added the path to the shapes entire path array.
To draw a circle one would use 4 1/4 circles that would be easy enough, to draw an ellipse presumably one would average out the handles in some form of proportion to the translation or the ellipses anchor points from the circle anchor points. I haven't experimented to get it to work.
What I wanted to do was to make a generic function for segments of ellipses, of height h and width w starting from and a and ending at b.
I know from you sin script tat you read up on the topic. Do you know how to go about it?
Regards
Trevor

19. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Marc Autret Oct 12, 2015 2:03 PM (in response to Trevorׅ)Hi Trevor,
I didn't work specifically on ellipses (so far) but I suppose all could be done by just scaling data from basic circle path points. So the main question is about managing circles (and circle arcs) in terms of cubic Bezier curves.
As we already know a Bezier curve cannot perfectly match an exact circle but there are decent approximations (InDesign native circle routine is not very good, by the way). A good read on this issue is: Approximate a circle with cubic Bézier curves (There are also technical details in Drawing Sine Waves in InDesign, although this is a subsidiary topic.)
There are great libraries to study Bezier art in depth. For JavaScript dev I specially recommand Paper.js (many interesting snippets here). And at a higher level (C++) we have of course Inkscape's source code: https://inkscape.org/en/download/source/
Using DOM commands (Pathfinder operations etc.) remains the easier solution anyway… as long as you do not question performances.
Now, going back to your question, give us more detail on what your routine is exactly supposed to do in terms of input/output, then maybe I could bring a starting point.
@+
Marc

20. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
[Jongware] Oct 12, 2015 2:15 PM (in response to pkahrel)pkahrel wrote:
InDesign's curves and handles essentially work the same way as in FontLab, Fontographer, Illustrator, CorelDraw, etc.
.. and inside Type 1 PostScript fonts! (But not TTF fonts. Now those are quadratic, not cubic.)

21. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
[Jongware] Oct 12, 2015 2:20 PM (in response to Trevorׅ)Trevor, there is a very nice PDF floating around on the web which explains in detail the differences between bezier curves and circle segments. But (looking at your magic values) perhaps you've already seen it?
(As a note to others: mathematically you can prove that you cannot draw circles  or ellipses  using bezier curves only, although you can approximate them. Technically, neither InDesign's nor Illustrator's circles are, in fact, actual circles.)

22. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Oct 12, 2015 2:42 PM (in response to [Jongware])Hi Marc and Jongware
Thanks for your reply.
I'll get back tomorrow afternoon.
Trevor

23. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
ajaatshatru Oct 12, 2015 11:57 PM (in response to Trevorׅ)This is exactly what I wanted! Thanks a lot!
Rishabh K

24. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Oct 13, 2015 2:23 PM (in response to Trevorׅ)Ok, the afternoon came and went.
I did see a lot of sources on the topic but didn't understand how to apply the theory and the terms used in them to practical ID, AI scripting terms.
I am using the terms circles, ellipses etc. as what the look like and what most "normal" people would call them even though I fully understand that they are approximations. I did see in one of the sources (no idea which) that a better value can be given instead of the standard .552... that is used. The numbers that I used I think I got by looking at the paths that Ai was producing. The numbers didn't produce a fixed constant a bigger "circle" produced a different number than a smaller one.
I only noticed now that I didn't need to use 2 numbers .522... and .447... as the .447... is 1  .52222
I looked today at the Paper.js in particular the function that starts at line 4474 of the papercore.js file. Which I shall paste below.
It helps a very lot in understanding things. Now that from this post we know the conversion from extended script to and from the html "ctx.bezierCurveTo()" it opens up the topic tremendously.
_draw: function(ctx, param, strokeMatrix) { var style = this._style, hasFill = style.hasFill(), hasStroke = style.hasStroke(), dontPaint = param.dontFinish  param.clip, untransformed = !strokeMatrix; if (hasFill  hasStroke  dontPaint) { var type = this._type, radius = this._radius, isCircle = type === 'circle'; if (!param.dontStart) ctx.beginPath(); if (untransformed && isCircle) { ctx.arc(0, 0, radius, 0, Math.PI * 2, true); } else { var rx = isCircle ? radius : radius.width, ry = isCircle ? radius : radius.height, size = this._size, width = size.width, height = size.height; if (untransformed && type === 'rectangle' && rx === 0 && ry === 0) { ctx.rect(width / 2, height / 2, width, height); } else { var x = width / 2, y = height / 2, kappa = 1  0.5522847498307936, cx = rx * kappa, cy = ry * kappa, c = [ x, y + ry, x, y + cy, x + cx, y, x + rx, y, x  rx, y, x  cx, y, x, y + cy, x, y + ry, x, y  ry, x, y  cy, x  cx, y, x  rx, y, x + rx, y, x + cx, y, x, y  cy, x, y  ry ]; if (strokeMatrix) strokeMatrix.transform(c, c, 32); ctx.moveTo(c[0], c[1]); ctx.bezierCurveTo(c[2], c[3], c[4], c[5], c[6], c[7]); if (x !== rx) ctx.lineTo(c[8], c[9]); ctx.bezierCurveTo(c[10], c[11], c[12], c[13], c[14], c[15]); if (y !== ry) ctx.lineTo(c[16], c[17]); ctx.bezierCurveTo(c[18], c[19], c[20], c[21], c[22], c[23]); if (x !== rx) ctx.lineTo(c[24], c[25]); ctx.bezierCurveTo(c[26], c[27], c[28], c[29], c[30], c[31]); } } ctx.closePath(); }
From this it should be pretty simple to parse in the jsx. With this we can draw an ellipse, or a 1/4, 1/2 and 3/4 ellipse using 1, 2, 3 or 4 bezier curves.
This is really all I need, but what I would like is to be able to start and end at any point in the ellipse.
Given H, W, and start and end angles S and E how would I calculate the black bezier curve on the right side of the screenshot?

25. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Marc Autret Oct 14, 2015 6:59 PM (in response to Trevorׅ)Okay Trevor let's go into this!
I won't use Paper.js in my example as I have already coded a similar routine in a workinprogress—Claquos v3—so I'll be more comfortable with my personal code.
My basic idea is, don't work with an ellipse when you can just rescale a circle (through a transformation matrix, etc.) So I'll start with a circular arc.
My main reference when I was implementing the below routine was Circular Arcs and Circles. You find there a clear explanation and method for computing the right Bézier weight for a specific arc in [0,pi/2]. Then, all we need to do is to create as many control points as needed to cover arcs over 90 degree. Here my approach is to divide the entire arc in equal subarcs so that I just have to deal with a single Bézier weight calculation and then apply a rotation to the successive control points. (Also, we want to manage a global rotation angle to support your S parameter, but it's not a big deal.)
//  // This is part of my Claquos v3 script (not released yet.) //  $.hasOwnProperty('Arc')(function(H/*OST*/,S/*ELF*/,I/*NNER*/) { H[S] = S; I.F_ROTATOR = function F(/*num[2][]&*/a) //  // A rotation utility. { if( !a ) { F.FACTOR = 1e3; F.COS = 1; F.SIN = 0; F.alphaDeg = 0; F.rotate  (F.rotate = function(dAlphaDeg) { var a = ((F.alphaDeg += dAlphaDeg)*Math.PI)/180; F.COS = Math.cos(a); F.SIN = Math.sin(a); }); return F; } var cos = F.COS, sin = F.SIN, factor = F.FACTOR, x, y, i = a.length; while( i ) { x = a[i][0]; y = a[i][1]; a[i][0] = (x*cos + y*sin)/factor; a[i][1] = (y*cos  x*sin)/factor; } }; I.F_TANGENT_FACTOR = function(/*]0...[*/radius,/*]0,90]*/angle,/*bool=false*/ANGLE_IN_RADIANS) //  // Get the perfect Bezier weight for that angle. { var a = ANGLE_IN_RADIANS ? angle : ((angle * Math.PI) / 180), x = radius * Math.cos(a), y = radius * Math.sin(a); return ( 4 * (Math.sqrt(radius*radius  2*x)  (x1)) ) / ( 3*y ); } I.F_ARC_PATH = function(/*]0...[*/radius,/*]0,360]*/arcDeg,/*[0,360[*/rotDeg) //  // Generate the entire path. { var FX = I.F_ROTATOR(), //  n = 2 + (arcDeg>90) + (arcDeg>180) + (arcDeg>210), r = radius*FX.FACTOR, //  alphaDeg = arcDeg / n, kAlpha = r * I.F_TANGENT_FACTOR(r, alphaDeg/2), //  path, i, z, t; FX.rotate(rotDeg); for( path=[], i=z=0 ; i <= n ; ++i ) { t = path[z++] = [ null, [r,0], null ]; t[0] = i > 0 ? [r, kAlpha] : t[1].concat(); t[2] = i < n ? [r, kAlpha] : t[1].concat(); FX(t); FX.rotate(alphaDeg); } return path; }; //  // API //  S.buildPath = I.F_ARC_PATH; })($,{toString:function(){return 'Arc'}},{}); //  // TEST  assuming the ruler space is OK, in pt, etc. //  var path = $.Arc.buildPath(/*radius*/100,/*arc*/270,/*rotation*/90); app.activeWindow.activeSpread.rectangles.add({ strokeColor:'Black', fillColor:'None', strokeWeight:'3pt' }).paths[0].properties = { entirePath: path, pathType: +PathType.OPEN_PATH, };
Which leads to:
From then the only question you have to deal with is to find the parameters (i.e. radius, rotation and arc angles) that fit your final ellipse, considering some scaling factor. I guess that will be the easy part ;)
Of course I strongly suggest that you implement the scaling transformation at the path computation level (rather than scaling the circle after its creation) since every DOM command has a cost. But you already knew that.
Hope that helps.
@+,
Marc

26. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Oct 15, 2015 7:28 AM (in response to Marc Autret)Very Nice Marc!
From then the only question you have to deal with is to find the parameters (i.e. radius, rotation and arc angles) that fit your final ellipse, considering some scaling factor. I guess that will be the easy part ;)
My only doubt is just how easy the "easy part" will be.
I shall give it a go.
Thanks hope the help and time you put into it,
Trevor

27. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Marc Autret Oct 15, 2015 2:19 PM (in response to Trevorׅ)Hi Trevor,
My only doubt is just how easy the "easy part" will be.
Sorry but we'll need a little bit of math here. Take R = W / 2 and k = W / H.
k is the yscaling factor that sends the ellipse to the circle (and inversely 1/k is the yscaling factor we shall apply to the circular arc.)
Since your parameters provide the start and end angles relative to the ellipse, the problem is to determine the corresponding angles in the circular area (that is, before stretching the circle).
Given an angle α relative to the ellipse, what is the corresponding angle α' relative to the circle? Let's solve this first in the usual trigonometric form:
Now we can write an adapter to convert ellipse parameters into circle parameters. The code below also takes care of the angular reference frame you used in your example.
// Original Trevor's parameters //  var W = 400, H = 144, S = 57, // in degree, origin +90, reversed E = 212; // in degree, origin +90, reversed // Adapter //  const DEG2RAD = Math.PI/180, RAD2DEG = 180/Math.PI; var radius = W/2, k = W/H, convertEllipseToCircleAngle = function(a) { return 180*(0>Math.cos(a*=DEG2RAD)) + RAD2DEG*Math.atan(k*Math.tan(a)); }, //  start = convertEllipseToCircleAngle(90E), end = convertEllipseToCircleAngle(90S), arc = endstart; while( arc <= 0 ) arc+=360; // Build the circular arc using $.Arc (see previous post.) //  var path = $.Arc.buildPath(radius,arc,start); var arc = app.activeWindow.activeSpread.rectangles.add({ strokeColor:'Black', fillColor:'None', strokeWeight:'2pt' }); arc.paths[0].properties = { entirePath: path, pathType: +PathType.OPEN_PATH, }; // Yrescale by 1/k (relative to the space origin.) // [This should be done at the coordinate level for better performance!] //  arc.resize( CoordinateSpaces.spreadCoordinates, [[0,0],AnchorPoint.centerAnchor], // this refers to the ruler origin ResizeMethods.MULTIPLYING_CURRENT_DIMENSIONS_BY, [1,1/k] );
That's it! Here is how the script behaves for decreasing values of H:
Note that the resulting angles S and E remains constant, as expected
@+
Marc

28. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
pkahrel Oct 15, 2015 2:25 PM (in response to Marc Autret)These are works of art. . .

29. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Oct 16, 2015 2:21 AM (in response to pkahrel)Excellent Marc!
Better still is.
// Original Trevor's parameters //  var W = 400, H = 144, S = 57, // in degree, origin +90, reversed E = 212; // in degree, origin +90, reversed // Adapter //  const DEG2RAD = Math.PI/180, RAD2DEG = 180/Math.PI; var radius = W/2, k = W/H, convertEllipseToCircleAngle = function(a) { return 180*(0>Math.cos(a*=DEG2RAD)) + RAD2DEG*Math.atan(k*Math.tan(a)); }, //  start = convertEllipseToCircleAngle(90E), end = convertEllipseToCircleAngle(90S), arc = endstart; while( arc <= 0 ) arc+=360; // Build the circular arc using $.Arc (see previous post.) //  var path = $.Arc.buildPath(radius,arc,start); // Yrescale by 1/k (relative to the space origin.) //  var l = path.length, p, ll, n, c; for (n = 0; n < l; n++) { // loop through the circle segments p = path[n] ll =p.length; for (c = 0; c < ll; c++) { // loop through Anchor, left and right points p[c][1] /= k; // fix up the vertical scales } } var arc = app.activeWindow.activeSpread.rectangles.add({ strokeColor:'Black', fillColor:'None', strokeWeight:'2pt' }); arc.paths[0].properties = { entirePath: path, pathType: +PathType.OPEN_PATH, };
This way we avoid using the DOM resize call. This is what I need to get all the points with no DOM calls and just at the end to make the one DOM call.
The idea is to make an API to easily draw shapes in the following sort of form.
// Very Very rough numbers to make the magenta colored inner shape of the screen shot // Aimed for Api var path = new Shape(); // Shape is the path factory path.start(40,500); // starting point of path path.right(300); // or path.east (300) path.down(300); // or path.right(300) or path.south(300) // continue the path at a 46 degree angle for 60 points path.right(46, 60); // continue with an arc of radius 1000 (for ellipse could use [1000, 700] starting from 230 degrees going to 290 degrees path.arc(500, 230, 290); // continue the end of the arc at the current angle of the end of the arc i.e. the tangent angle of 290 by 60 points path.continue(60); path.up(300); path.draw({strokeColor: 'Magenta', strokeWeight: '3pt'}); // will draw the shape with properties
The last stage of the arc function would be to allow for a rotation of the arc around the starting point.
That should be pretty basic trigonometry, I shall give it a go and hopefully post it on Sunday. (you can post it sooner if you like!)
Thanks for all you help, I'm sure this will be very useful particularly for Illustrator scripters who are doing more drawing stuff.
Regards
Trevor

30. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Oct 16, 2015 4:46 AM (in response to Trevorׅ)This would go after the resize part.
// Rotate Arc from the start point by r degrees //  var R = 35, // Trevor's random rotation angle; h = path[0][0][0], // horizontal start point v = path[0][0][1]; // vertical start point R *= DEG2RAD; for (n = 0; n < l; n++) { // loop through the circle segments p = path[n] ll =p.length; for (c = 0; c < ll; c++) { // loop through Anchor, left and right points Rotate(p[c], [h,v], R); } } function Rotate(point, origin, r) { var x = point[0], y = point[1], ox = origin[0], oy = origin[1]; point[0] = (x  ox) * Math.cos(r)  (y  oy) * Math.sin(r) + ox, point[1] = (x  ox) * Math.sin(r) + (y  oy) * Math.cos(r) + oy; }

31. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Oct 20, 2015 8:54 AM (in response to Trevorׅ)Hi All,
I think Jive's went a bit berserk and posted part of an earlier post of mine by itself, anyway I did not post it, and now I deleted it.
I did try to post another post which Jive's deleted. So here's the summary, this time typed on a text editor so it doesn't get trashed so easily.
In short; Marc has done an absolutely brilliant job in illustrating how to apply the Bezier mathematics in a practical way in InDesign and the like that makes it now easier to draw complex arcs using his functions than using the traditional path finder DOM methods. To convert the output to HTML has been illustrated in the early part of the thread opening all sorts of possibilities including producing live previews on HTML based extensions.
I have changed the structure of the functions to make it more simple for us mortals who are not yet familiar with hi unpublished Claquos v3.
I added a few functions including the ability to choose which end of the arc it the beginning.
The Screenshot below is the result of the below script.
Thanks Marc!
Regards,
Trevor.
// Taken from Marc https://forums.adobe.com/message/8072664#8072664 var ArcPath, F_ROTATOR, F_TANGENT_FACTOR, EllipseArc; var ArcPath = function(/*]0...[*/ radius,/*]0,360]*/ arcDeg ,/*[0,360[*/ rotDeg, reversePath /*[Bool]*/) // By Marc Autret //  // Generate the entire path. { var FX = F_ROTATOR(), //  n = 2 + (arcDeg>90) + (arcDeg>180) + (arcDeg>210), r = radius*FX.FACTOR, //  alphaDeg = arcDeg / n, kAlpha = r * F_TANGENT_FACTOR(r, alphaDeg/2), //  path, i, z, t; FX.rotate(rotDeg); if (!reversePath) { for( path=[], i=z=0 ; i <= n ; ++i ) { t = path[z++] = [ null, [r,0], null ]; t[0] = i > 0 ? [r, kAlpha] : t[1].concat(); t[2] = i < n ? [r, kAlpha] : t[1].concat(); FX(t); FX.rotate(alphaDeg); } } else { // this will make path[0][0] at the "other" end of the arc // else part by Trevor path=[]; i=z=n+1; while (i) { t = path[z] = [ null, [r,0], null ]; t[0] = i > 0 ? [r, kAlpha] : t[1].concat(); t[2] = i < n ? [r, kAlpha] : t[1].concat(); FX(t); FX.rotate(alphaDeg); } ; } return path; }; F_ROTATOR = function F(/*num[2][]&*/ a) // By Marc Autret //  // A rotation utility. { if( !a ) { F.FACTOR = 1e3; F.COS = 1; F.SIN = 0; F.alphaDeg = 0; F.rotate  (F.rotate = function(dAlphaDeg) { var a = ((F.alphaDeg += dAlphaDeg)*Math.PI)/180; F.COS = Math.cos(a); F.SIN = Math.sin(a); }); return F; } var cos = F.COS, sin = F.SIN, factor = F.FACTOR, x, y, i = a.length; while( i ) { x = a[i][0]; y = a[i][1]; a[i][0] = (x*cos + y*sin)/factor; a[i][1] = (y*cos  x*sin)/factor; } }; F_TANGENT_FACTOR = function (/*]0...[*/ radius , /*]0,90]*/ angle ,/*bool=false*/ ANGLE_IN_RADIANS) // By Marc Autret //  // Get the perfect Bezier weight for that angle. { var a = ANGLE_IN_RADIANS ? angle : ((angle * Math.PI) / 180), x = radius * Math.cos(a), y = radius * Math.sin(a); return ( 4 * (Math.sqrt(radius*radius  2*x)  (x1)) ) / ( 3*y ); } // This is the main function for drawing ellipse arcs //  EllipseArc = function (W, H, S, E, R, reversePath /*[Bool]*/) { // Width, Height, Start and End in degrees, origin +90, reversed Rotation in Degrees // By Marc Autret const DEG2RAD = Math.PI/180, RAD2DEG = 180/Math.PI; var radius = W/2, k = W/H, convertEllipseToCircleAngle = function(a) { return 180*(0>Math.cos(a*=DEG2RAD)) + RAD2DEG*Math.atan(k*Math.tan(a)); }, //  start = convertEllipseToCircleAngle(90E), end = convertEllipseToCircleAngle(90S), arc = endstart; while( arc <= 0 ) arc+=360; var path = ArcPath(radius, arc, start, reversePath); // Yrescale by 1/k (relative to the space origin.) //  var l = path.length, p, ll, n, c; for (n = 0; n < l; n++) { // loop through the circle segments p = path[n] ll =p.length; for (c = 0; c < ll; c++) { // loop through Anchor, left and right points p[c][1] /= k; // fix up the vertical scales } } if (R) { // Rotate Arc from the start point by r degrees //  Rotate(path, R); } return path; } Rotate = function (path /*object or array*/, R) { // Rotates all the points in the path around the starting point of the path // By Trevor R *= Math.PI / 180; // Convert to radians var h = path[0][1][0], // horizontal start point v = path[0][1][1], // vertical start point n, p, l, ll, c; l = path.length; for (n = 0; n < l; n++) { // loop through the circle segments p = path[n] ll =p.length; for (c = 0; c < ll; c++) { // loop through Anchor, left and right points RotatePoint(p[c], [h,v], R); } } } RotatePoint = function (point /*[Array x,y]*/, origin /*[Array x,y]*/, r /*num degrees from +90*/) { // Rotates any given point around any other given point // By Trevor var x = point[0], y = point[1], ox = origin[0], oy = origin[1]; point[0] = (x  ox) * Math.cos(r)  (y  oy) * Math.sin(r) + ox, point[1] = (x  ox) * Math.sin(r) + (y  oy) * Math.cos(r) + oy; } MoveTo = function (path /*object or array*/, x, y) { // translates the path to start at a give point // By Trevor var q = path.length  1; var h = x  path[0][1][0], // horizontal translation from start point v = y  path[0][1][1], // vertical translation from start point n, p, l, ll, c; ll = path.length; for (n = 0; n < ll; n++) { // loop through the circle segments p = path[n] l =p.length; for (c = 0; c < l; c++) { // loop through Anchor, left and right points p[c][0] += h; p[c][1] += v; } } } Scale = function (path, x, y /* number X scale i.e. 1.2 for 120% */) { // By Trevor var n, p, l, ll, c; ll = path.length; for (n = 0; n < ll; n++) { // loop through the circle segments p = path[n] l =p.length; for (c = 0; c < l; c++) { // loop through Anchor, left and right points p[c][0] *= x; p[c][1] *= y; } } } //  // TEST //  function drawSomething () { // By Trevor const DEG2RAD = Math.PI/180; var n, path, c, doc = app.documents.add({ viewPreferences: {horizontalMeasurementUnits: 'pt', verticalMeasurementUnits: 'pt'}, documentPreferences: {pagesPerDocument: 1, pageHeight: '1900pt', pageWidth: '1150pt'} }); cmyk = ['Cyan', 'Yellow', 'Magenta', 'Black']; for (c = 0; c < 2; c++) { path = EllipseArc(200, 70, 100, 300, 10, c % 2 /* Boolean to reverse starting point of path */); for (n = 0; n < 360; n++) { // change to 15 to get a better idea of what the path reversing does // Face and Trunk Scale(path, .99, .99); Rotate(path, n * 2); MoveTo (path, 200 + .5 * n, 150 + ((c) * 300) + 40 * Math.cos (n * 2 * DEG2RAD)); doc.spreads[0].graphicLines.add({ strokeColor: cmyk[n % 4], fillColor: cmyk[(n + 1) % 4], fillColor: cmyk[(n + 1) % 4], strokeWeight:'.5pt', name: "shape" }).paths[0].properties = { entirePath: path, pathType: +PathType.CLOSED_PATH, }; } } } app.doScript (drawSomething, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.FAST_ENTIRE_SCRIPT);

32. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Aug 1, 2016 3:02 PM (in response to Marc Autret)Hi Marc
I am doing some work on this now and was wondering why you have a factor F.FACTOR = 1e3 and why you set it to 1000?
You are multiplying the radius by the factor and then you divide by the factor so any non 0 number will produce the same result.
If it wasn't you I wouldn't ask the question but as it is you I'm sure you have good reason!
Regards
Trevor

33. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Marc Autret Aug 2, 2016 12:29 PM (in response to Trevorׅ)Hi Trevor,
Good question. My answer will be disappointing, I'm afraid. My original purpose was all about increasing the precision of the final coordinates, considering the fact that IEEE754 arithmetic (floatingpoint numbers) is an approximation of real number arithmetic, especially when additive operations are involved. My reasoning was as follows: we know IEEE754 is just a finite set of numbers (an infinite set of real numbers can't be described with that system). Then I was supposing that adding/subtracting high numbers rather than small numbers was a way of reducing rounding errors, because if the error density is the same at any scale then finally dividing by some factor will perhaps reduce the rounding error by that factor. But to be honest there are many points in my reasoning which I'm not sure at all. I made assumptions about error density which in fact I can't prove based on the mantissaexponent representation of floatingpoint numbers. Also, I'm not sure that multiplying (first) and dividing (last) does not introduce errors of the same amount that those I want to reduce (however, it is known that IEEE754 multiplication is safer than addition, so…) Finally, that 1e3 factor is purely empiric and arbitrary. Maybe a 2^n factor would be much more convenient. Etc.
Reconsidering my code after several months, I don't feel it that good and exemplary. The logic is OK but the implementation is highly questionable, indeed.
@+
Marc

34. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Aug 2, 2016 2:36 PM (in response to Marc Autret)Hi Marc,
Thanks for the detailed answer.
I think in truth that the even if one could get perfect coordinates the accuracy margin would be at a guess a 0.0000001 difference at most, this difference in our case is going to be irreverent as a 'perfect' bezier circle has an inaccuracy of about .02% of a true perfect circle at the max deviating points. So whether the accuracy is .02% or .0200001% is not important. In any case we'll never be able to see the difference even on the highest resolution printers.
The fact off the matter is that your code shows how to apply the bezier maths in a practical form and is a huge help to me.
I would like to improve on my implementation of the ellipse and rotation parts which I feel should be compressed into a single loop and not 1st draw a circle arc 2nd scale to ellipse and 3rd rotate to desired angle 4th translate the object to the desired coordinates.
Perhaps I am guilty of trying to make scripts that takes 2 seconds to execute take 1.999 seconds. Either way making the compressed form would be an interesting mathematical challenge.
Regards and thanks again,
Trevor

35. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Marc Autret Aug 2, 2016 4:50 PM (in response to Trevorׅ)You are definitely not guilty, since scaling and translation calculations are easy to prepend. That will remove two DOM commands and undoubtedly speed up the script in a noticeable way. Especially if it has to generate a bunch of ellipses.
Have fun!
@+
Marc

36. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Aug 2, 2016 11:19 PM (in response to Marc Autret)I think in the nearly a year since the scripts were posted you forgot that my version only calls the DOM command once after all the calculations have been made.

37. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Laubender Aug 2, 2016 11:29 PM (in response to Trevorׅ)Hi colleagues,
this is a very interesting discussion.
Recently I did some studies on the precission that the Pathfinder tools are doing.
I found that e.g. Adobe Illustrator is more precise than InDesign and searching for a way to do more accurate operations with the Pathfinder tools. Maybe by scaling the objects first before applying a Pathfinder action. I don't know, if this is the right place to discuss this here or maybe it's better to open another thread.I'm bussy right now, but can come back this evening with some samples, that show a few things.
Also related is the maximum zoom percentage one can zoom in and out with InDesign. Way better is the current Illustrator in this regards…Uwe

38. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Aug 2, 2016 11:45 PM (in response to Laubender)Hi Uwe,
1) Interesting, but the whole point of the exercise here is to not use any pathfinder tools. See 29 above.
2) The API I am working on is basically for Illustrator. (Actually a form of Illustrator server ) . As the API is so removed from DOM operations I would like it to work also on InDesign but it's a little bit complicated to cover them both as the vertical positions of the 2 applications are annoyingly opposite!
Regards
Trevor

39. Re: What is the direction of the curve points returned by entirePath()? [See description for details]
Trevorׅ Aug 2, 2016 11:50 PM (in response to Laubender)I wonder if the precision difference is because due to the bounding box that Illustrator draws is around the path points where as InDesign wraps the line thickness of the path in the bounding box?