How to get coordinates between two anchors - illustrator, script - adobe-illustrator

Is there any way to get coordinates on the line in my script for Adobe Illustrator?
I have line (or any rounded curve) with anchors [X, Y]: [10, 20] and [50, 100] and I want to get coordinates on the line between the anchors. I want coordinates for X = 30, but is there any way how to get Y value?

This should be your solution for a line:
var calc_distance = function(x1,x2){
return (x1 > x2) ? x1 - x2 : x2 - x1;
}
var p1 = {x:10,y:20};
var p2 = {x:50,y:100};
var p3 = {x:30,y:null};
var d = calc_distance(p1.x, p2.x); // calc whole distance
var d1 = calc_distance(p1.x, p3.x); // calc distance to p3
var blend = ((100/d) * d1) / 100;// percentual value between p1 and p2
var y = p1.y + blend * (p2.y - p1.y);
p3.y = y;

Related

I'm trying to project 4D lines to 3D to 2D and clip them at z=p and w=p, but I'm not sure if it's rendering correctly

I've been trying to write a program that can render 4D lines, the specific function doing this gets the lines already rotated, and the function attempts to clip the lines at planes z = p and w = p if needed, and then draw the line to the screen.
I think that I am doing at least most of this properly, however I am unsure, and not having much experience viewing the fourth dimension I cannot tell what might be a visual bug, or what is actually how it should be rendered.
The function first loads a line into two variables, each is one of the two endpoints of the line. If both points are beyond clippl (the clipping plane variable) for z = clippl and w = clippl, it then applies perspective transformation to them, and subsequently renders a line on the screen correspondingly.
If certain logic is met for the points, the function goes through a process of clipping them, and then continues the same as it would outside the clipping planes.
The location of the camera is held in the variables Ox, Oy, Oz, Ow at the beginning of the full program.
I can't tell if I've done this properly, can anyone tell me if this works right as a 4D perspective projection from a first person camera?
EDIT: I've added points to the rendering list that are at the corners of the cube I'm rendering, and it seems to show that there is in fact some problem with the line clipping, as I am fairly certain that the points are rendering properly, and there is not always a line showing up at it. Could the problem have to do with the w = p clip?
Here's the function, the program uses p5.js:
function drawPLines(P){
var lA,lB;
for(var i=0;i<P.length;i++){
lA = [P[i][0],P[i][1],P[i][2],P[i][3]];
lB = [P[i][4],P[i][5],P[i][6],P[i][7]];
//X: ( x*VS+(width*0.5)+(ox*VS) )
//Y: ( y*VS+(height*0.5)+(oy*VS) )
//x: (XV[0]*P[i][0])+(YV[0]*P[i][1])+(ZV[0]*P[i][2])+(WV[0]*P[i][3])
//y: (XV[1]*P[i][0])+(YV[1]*P[i][1])+(ZV[1]*P[i][2])+(WV[1]*P[i][3])
var x0,y0,x1,y1;
//x0 = (XV[0]*lA[0])+(YV[0]*lA[1])+(ZV[0]*lA[2])+(WV[0]*lA[3]);
//y0 = (XV[1]*lA[0])+(YV[1]*lA[1])+(ZV[1]*lA[2])+(WV[1]*lA[3]);
//new rendering pipeline
//old rendering pipeline
if(lA[2]>clippl&&lB[2]>clippl&&lA[3]>clippl&&lB[3]>clippl){
x0 = XV[0]*lA[0];
y0 = YV[1]*lA[1];
x0 = (x0/lA[3])/(lA[2]/lA[3]);
y0 = (y0/lA[3])/(lA[2]/lA[3]);
//console.log(y);
x0 = ( x0*VS+(width*0.5)+(ox*VS) );
y0 = ( y0*VS+(height*0.5)+(oy*VS) );
//x1 = (XV[0]*lB[0])+(YV[0]*lB[1])+(ZV[0]*lB[2])+(WV[0]*lB[3]);
//y1 = (XV[1]*lB[0])+(YV[1]*lB[1])+(ZV[1]*lB[2])+(WV[1]*lB[3]);
x1 = XV[0]*lB[0];
y1 = YV[1]*lB[1];
x1 = (x1/lB[3])/(lB[2]/lB[3]);
y1 = (y1/lB[3])/(lB[2]/lB[3]);
//console.log(y);
x1 = ( x1*VS+(width*0.5)+(ox*VS) );
y1 = ( y1*VS+(height*0.5)+(oy*VS) );
stroke([P[i][8],P[i][9],P[i][10],P[i][11]]);
line(x0,y0,x1,y1);
}else if((lA[2]>clippl||lA[3]>clippl||lB[2]>clippl||lB[3]>clippl)){
var V = 0;
var zV = 0;
var wV = 0;
//var oV = 0;
if(lA[2]>clippl&&lA[3]>clippl){
V++;
}else if(lA[2]>clippl&&lA[3]<=clippl){
zV++;
}else if(lA[2]<=clippl&&lA[3]>clippl){
wV++;
}/*else{
oV++;
}*/
if(lB[2]>clippl&&lB[3]>clippl){
V++;
}else if(lB[2]>clippl&&lB[3]<=clippl){
zV++;
}else if(lB[2]<=clippl&&lB[3]>clippl){
wV++;
}/*else{
oV++;
}*/
if((V==1)||(wV==1&&(V==1||zV==1))||(zV==1&&(V==1||wV==1))){
var lin = lB;
var out = lA;
if(lA[2]<=clippl){
out = lB;
lin = lA;
}
if(lin[2]<=clippl){
lin = [((((lA[0]-lB[0])*clippl)-((lA[0]-lB[0])*lB[2]))/(lA[2]-lB[2]))+lB[0],((((lA[1]-lB[1])*clippl)-((lA[1]-lB[1])*lB[2]))/(lA[2]-lB[2]))+lB[1],clippl,((((lA[3]-lB[3])*clippl)-((lA[3]-lB[3])*lB[2]))/(lA[2]-lB[2]))+lB[3]];
}
if((lA[2]-lB[2])!==0){
lA = lin;
lB = out;
}
lin = lA;
out = lB;
if(lB[3]<=clippl){
out = lA;
lin = lB;
}
if(lin[3]<=clippl){
lin = [((((lA[0]-lB[0])*clippl)-((lA[0]-lB[0])*lB[3]))/(lA[3]-lB[3]))+lB[0],((((lA[1]-lB[1])*clippl)-((lA[1]-lB[1])*lB[3]))/(lA[3]-lB[3]))+lB[1],((((lA[2]-lB[2])*clippl)-((lA[2]-lB[2])*lB[3]))/(lA[3]-lB[3]))+lB[2],clippl];
//alert(lin);
//alert(out);
}
if((lA[3]-lB[3])!==0){
lA = lin;
lB = out;
}
if(lA[2]>clippl||lB[2]>clippl||lA[3]>clippl||lB[3]>clippl){
x0 = XV[0]*lA[0];
y0 = YV[1]*lA[1];
x0 = (x0/lA[3])/(lA[2]/lA[3]);
y0 = (y0/lA[3])/(lA[2]/lA[3]);
//console.log(y);
x0 = ( x0*VS+(width*0.5)+(ox*VS) );
y0 = ( y0*VS+(height*0.5)+(oy*VS) );
//x1 = (XV[0]*lB[0])+(YV[0]*lB[1])+(ZV[0]*lB[2])+(WV[0]*lB[3]);
//y1 = (XV[1]*lB[0])+(YV[1]*lB[1])+(ZV[1]*lB[2])+(WV[1]*lB[3]);
x1 = XV[0]*lB[0];
y1 = YV[1]*lB[1];
x1 = (x1/lB[3])/(lB[2]/lB[3]);
y1 = (y1/lB[3])/(lB[2]/lB[3]);
//console.log(y);
x1 = ( x1*VS+(width*0.5)+(ox*VS) );
y1 = ( y1*VS+(height*0.5)+(oy*VS) );
stroke([P[i][8],P[i][9],P[i][10],P[i][11]]);
line(x0,y0,x1,y1);
}
}
}
}
}
You can see the full program at https://editor.p5js.org/hpestock/sketches/Yfagz4Bz3

How to set starting and ending point for line projection in DM script

I am trying to draw line projection for an image . The line 4 in the code below sy/2 represents the length of projection (here is the half image range). But how to set the starting point or ending point with scripting? For example, I want to draw the line projection, from 1/4 image range to 3/4 image range. Any suggestions?
image src := getfrontimage()
number sx,sy
src.GetSize(sx,sy)
image line_projection := RealImage( "Vertical", 4, sy/2 )
line_projection[irow,0] += src
line_projection *= 1/sx
While using intrinsic variables (icol,irow,...) for iterative summing was the fasted method in GMS 1, this is no longer true for newer versions that utilize multi-threaded code, as demonstrated by the following example:
// various ways to sum a subsection of an image
number sx = 4096, sy = 4096
number startx = 0.2, starty = 0.2
number endx = 0.8, endy = 0.4
// Coordinates of cut
number t = trunc(starty*sy), l = trunc(startx*sx), b = trunc(endy*sy), r = trunc(endx*sx)
image test := realImage( "Test", 4, sx, sy )
test = sin( icol/iwidth * 20*Pi()) + cos( itheta * iradius/iwidth * 50)
test= sin( icol/iwidth * 20*Pi())
test.ShowImage()
ROI marker = NewROI()
marker.ROISetLabel( "Section" )
marker.ROISetRectangle( t, l, b, r )
marker.ROISetVolatile( 0 )
test.ImageGetImageDisplay(0).ImageDisplayAddRoi( marker )
//OKDialog( "Performing vertical sum with various methods now." )
number h = b - t
number w = r - l
ClearResults()
number ts, te, tps = GetHighResTicksPerSecond()
// using intrinsic variables
image sumImg1 := RealImage( "Sum intrinsic", 4, w )
ts = GetHighResTickcount()
sumImg1[icol, 0] += test[t,l,b,r];
te = GetHighResTickcount()
sumImg1.ShowImage()
result("\n Summing using intrinisic variables: " + (te-ts)/tps + " sec")
// using for-loop of slice
image sumImg2 := RealImage( "Sum with slice", 4, w )
ts = GetHighResTickcount()
for( number i=0; i<h; i++)
sumImg2 += test.slice1(0,i,0, 0,w,1)
te = GetHighResTickcount()
sumImg2.ShowImage()
result("\n Summing using for-loop with slice : " + (te-ts)/tps + " sec")
// using project of slice
image sumImg3 := RealImage( "Sum with project", 4, w )
ts = GetHighResTickcount()
sumImg3 = test[t,l,b,r].project( 1 )
te = GetHighResTickcount()
sumImg3.ShowImage()
result("\n Summing using project on section : " + (te-ts)/tps + " sec")
You can use slicing to only look at the image area you are interested in. For "clipping" the source to the interesting part use img[y1, x1, y2, x2].
image src := getFrontImage();
number width, height;
src.GetSize(width, height);
number start_y = 1/4 * height;
number end_y = 3/4 * height;
image line_projection := RealImage("Vertical", 4, width);
line_projection[icol, 0] += src[start_y, 0, end_y, width];
line_projection *= 1/(height/2);
line_projection.ShowImage();

RGB to HSV in numpy

I'm trying to implement RGB to HSV conversion from opencv in pure numpy using formula from here:
def rgb2hsv_opencv(img_rgb):
img_hsv = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HSV)
return img_hsv
def rgb2hsv_np(img_rgb):
assert img_rgb.dtype == np.float32
height, width, c = img_rgb.shape
r, g, b = img_rgb[:,:,0], img_rgb[:,:,1], img_rgb[:,:,2]
t = np.min(img_rgb, axis=-1)
v = np.max(img_rgb, axis=-1)
s = (v - t) / (v + 1e-6)
s[v==0] = 0
# v==r
hr = 60 * (g - b) / (v - t + 1e-6)
# v==g
hg = 120 + 60 * (b - r) / (v - t + 1e-6)
# v==b
hb = 240 + 60 * (r - g) / (v - t + 1e-6)
h = np.zeros((height, width), np.float32)
h = h.flatten()
hr = hr.flatten()
hg = hg.flatten()
hb = hb.flatten()
h[(v==r).flatten()] = hr[(v==r).flatten()]
h[(v==g).flatten()] = hg[(v==g).flatten()]
h[(v==b).flatten()] = hb[(v==b).flatten()]
h[h<0] += 360
h = h.reshape((height, width))
img_hsv = np.stack([h, s, v], axis=-1)
return img_hsv
img_bgr = cv2.imread('00000.png')
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
img_rgb = img_rgb / 255.0
img_rgb = img_rgb.astype(np.float32)
img_hsv1 = rgb2hsv_np(img_rgb)
img_hsv2 = rgb2hsv_opencv(img_rgb)
print('max diff:', np.max(np.fabs(img_hsv1 - img_hsv2)))
print('min diff:', np.min(np.fabs(img_hsv1 - img_hsv2)))
print('mean diff:', np.mean(np.fabs(img_hsv1 - img_hsv2)))
But I get big diff:
max diff: 240.0
min diff: 0.0
mean diff: 0.18085355
Do I missing something?
Also maybe it's possible to write numpy code more efficient, for example without flatten?
Also I have hard time finding original C++ code for cvtColor function, as I understand it should be actually function cvCvtColor from C code, but I can't find actual source code with formula.
From the fact that the max difference is exactly 240, I'm pretty sure that what's happening is in the case when both or either of v==r, v==g are simultaneously true alongside v==b, which gets executed last.
If you change the order from:
h[(v==r).flatten()] = hr[(v==r).flatten()]
h[(v==g).flatten()] = hg[(v==g).flatten()]
h[(v==b).flatten()] = hb[(v==b).flatten()]
To:
h[(v==r).flatten()] = hr[(v==r).flatten()]
h[(v==b).flatten()] = hb[(v==b).flatten()]
h[(v==g).flatten()] = hg[(v==g).flatten()]
The max difference may start showing up as 120, because of that added 120 in that equation. So ideally, you would want to execute these three lines in the order b->g->r. The difference should be negligible then (still noticing a max difference of 0.01~, chalking it up to some round off somewhere).
h[(v==b).flatten()] = hb[(v==b).flatten()]
h[(v==g).flatten()] = hg[(v==g).flatten()]
h[(v==r).flatten()] = hr[(v==r).flatten()]

I keep getting an error saying there is no picture when there is. What am I doing wrong?

def blendPictures(pict1, pict2, overlapAmt):
width1 = getWidth(pict1)
height1 = getHeight(pict1)
width2 = getWidth(pict2)
height2 = getHeight(pict2)
newWidth = width1 + width2 - overlapAmt
newHeight = min(height1, height2)
newCanvas = makeEmptyPicture(newWidth, newHeight)
for x in range(width1 - overlapAmt):
for y in range(newHeight):
color = getColor(getPixel(pict1, x, y))
setColor(getPixel(newCanvas, x, y), color)
pict2_x = 0
for pict1_x in range(width1 - overlapAmt, width1):
for y in range(newHeight):
pixel1 = getPixel(pict1, pict1_x, y)
pixel2 = getPixel(pict2, pict2_x, y)
newRed = 0.50 * getRed(pixel1) + 0.50 * getRed(pixel2)
newGreen = 0.50 * getGreen(pixel1) + 0.50 * getGreen(pixel2)
newBlue = 0.50 * getBlue(pixel1) + 0.50 * getBlue(pixel2)
color = makeColor(newRed, newGreen, newBlue)
setColor(getPixel(newCanvas, pict1_x, y), color)
pict2_x = pict2_x + 1
targetX = width1
for x in range(overlapAmt, width2):
for y in range(newHeight):
color = getColor(getPixel(pict2, x, y))
setColor(getPixel(newCanvas, targetX, y), color)
targetX = targetX + 1
return newCanvas
def swapBackground( src, background, newBackground ):
# src, and background must be the same size
# newBackground must be at least as big as src and background
for x in range(1, getWidth( src ) + 1 ) :
for y in range(1, getHeight( src ) + 1 ) :
srcPxl = getPixel( src, x, y )
backgroundPxl = getPixel( background, x, y )
if (distance(getColor( srcPxl ), getColor( backgroundPxl )) < 15.0):
setColor( srcPxl, getColor( getPixel( newBackground, x, y ) ) )
return src
jackalope = blendPictures('rabbit.jpg', 'antelope.jpg', 50)
writePictureTo(jackalope, "./jackalope.jpg")
#here swap the background to place your photo on front
swapBackground( 'photograph.jpg', 'jackalope.jpg', newBackground )
writePictureTo(newBackground, "./nexttojackalope.jpg")
swapBackground( 'rabbit.jpg', 'campus.jpg', newBackground1 )
writePictureTo(newBackground1, "./campustemp.jpg")
swapBackground( 'antelope.jpg', 'campustemp.jpg', newBackground2 )
writePictureTo(newBackground1, "./campusfinal.jpg")
Where the .jpg's are I put where the files will go or where they are pulling from. I have a picture of a rabbit and an antelope with a jackalope wav file and a picture of myself and a picture to put as the background. But I still get an error on line 2 saying that getWidth(picture) isn't defined and I'm not sure what to do. Any ideas?
In order to use the getWidth() function you need to pass a picture object as it's argument. So you will need to first create a picture object using the makePicture() function. For example:
pict1 = makePicture('rabbit.jpg')
width1 = getWidth1(pict1)
Here's a good guide on working with pictures in JES. http://www.cs.bu.edu/courses/cs101b1/jes/#Pictures%20and%20Sound

Find control point on piecewise quadratic Bezier curve

I need to write a program to generate and display a piecewise quadratic Bezier curve that interpolates each set of data points (I have a txt file contains data points). The curve should have continuous tangent directions, the tangent direction at each data point being a convex combination of the two adjacent chord directions.
0.1 0,
0 0,
0 5,
0.25 5,
0.25 0,
5 0,
5 5,
10 5,
10 0,
9.5 0
The above are the data points I have, does anyone know what formula I can use to calculate control points?
You will need to go with a cubic Bezier to nicely handle multiple slope changes such as occurs in your data set. With quadratic Beziers there is only one control point between data points and so each curve segment much be all on one side of the connecting line segment.
Hard to explain, so here's a quick sketch of your data (black points) and quadratic control points (red) and the curve (blue). (Pretend the curve is smooth!)
Look into Cubic Hermite curves for a general solution.
From here: http://blog.mackerron.com/2011/01/01/javascript-cubic-splines/
To produce interpolated curves like these:
You can use this coffee-script class (which compiles to javascript)
class MonotonicCubicSpline
# by George MacKerron, mackerron.com
# adapted from:
# http://sourceforge.net/mailarchive/forum.php?thread_name=
# EC90C5C6-C982-4F49-8D46-A64F270C5247%40gmail.com&forum_name=matplotlib-users
# (easier to read at http://old.nabble.com/%22Piecewise-Cubic-Hermite-Interpolating-
# Polynomial%22-in-python-td25204843.html)
# with help from:
# F N Fritsch & R E Carlson (1980) 'Monotone Piecewise Cubic Interpolation',
# SIAM Journal of Numerical Analysis 17(2), 238 - 246.
# http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
# http://en.wikipedia.org/wiki/Cubic_Hermite_spline
constructor: (x, y) ->
n = x.length
delta = []; m = []; alpha = []; beta = []; dist = []; tau = []
for i in [0...(n - 1)]
delta[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i])
m[i] = (delta[i - 1] + delta[i]) / 2 if i > 0
m[0] = delta[0]
m[n - 1] = delta[n - 2]
to_fix = []
for i in [0...(n - 1)]
to_fix.push(i) if delta[i] == 0
for i in to_fix
m[i] = m[i + 1] = 0
for i in [0...(n - 1)]
alpha[i] = m[i] / delta[i]
beta[i] = m[i + 1] / delta[i]
dist[i] = Math.pow(alpha[i], 2) + Math.pow(beta[i], 2)
tau[i] = 3 / Math.sqrt(dist[i])
to_fix = []
for i in [0...(n - 1)]
to_fix.push(i) if dist[i] > 9
for i in to_fix
m[i] = tau[i] * alpha[i] * delta[i]
m[i + 1] = tau[i] * beta[i] * delta[i]
#x = x[0...n] # copy
#y = y[0...n] # copy
#m = m
interpolate: (x) ->
for i in [(#x.length - 2)..0]
break if #x[i] <= x
h = #x[i + 1] - #x[i]
t = (x - #x[i]) / h
t2 = Math.pow(t, 2)
t3 = Math.pow(t, 3)
h00 = 2 * t3 - 3 * t2 + 1
h10 = t3 - 2 * t2 + t
h01 = -2 * t3 + 3 * t2
h11 = t3 - t2
y = h00 * #y[i] +
h10 * h * #m[i] +
h01 * #y[i + 1] +
h11 * h * #m[i + 1]
y