0

The problem scenario is defined as follows problem statement (Click here)

The information what happens in one single iteration is provided here in this link

I am supposed to get one small arc touching the circle at both ends (curve 1 rotates circle about point A and then rotates touching circle at point B so both ends of arc touch the circle). I am getting the result when I do this manually where I find intersection by using polyxpoly() , place the arc on intersection and keep rotating it till it touches the circle. But when I try to automate the process for many arcs by using a for loop I do not get desired result.

Since rotation of arc takes place , I have given small rotation step size but I get different results . Sometimes the for-loop works normally and gives desired result and sometimes gives abnormal results for certain iteration. I am unable to figure out the the problem with my approach.

Results are as follows click here to see the result

These are additional details which shows difference between desired result and undesired result Desired Result Vs Undesired Result for theta=500 & i=2 ,3 Desired Result Vs Undesired Result for theta=1800 & i=4

It can be seen for theta = 500 & i = 2 the arc does not rotate and since it dose not rotate it gives same result for theta = 500 & i = 3 but when theta = 1800 it gives different results but fails at iteration 4 (for theta = 1800 i = 1,2,3 gives desired result but fails at i = 4). Check the result image.

  • The parameter theta can be found in rotation()

The code I used is as follows but For-loop is giving abnormal results for certain iteration depending on theta

clc,clear
r = 10;                     % arc length
R = 55;                     % radius of a circle
aa = 60*pi/180;              % arc angle
ap = 0*pi/180;             % arc position angle
k=0;

t = linspace(0,pi/2);
[x,y] = pol2cart(t,R);      % circle data
t1 = linspace(0,aa)-aa/2+ap;
[x1,y1] = pol2cart(t1,r); % arc data
% Intersection of x axis (y=0) and quarter circle
x_axis_range=1:1000;
y_val_on_x_axis=zeros(1,length(x_axis_range));
[x1rc,y1rc]=polyxpoly(x_axis_range,y_val_on_x_axis,x,y);
xc_s(1)=x1rc;
yc_s(1)=y1rc;
% x1rc=55;
% y1rc=0;
for z=1:3
[x1_p,y1_p]= placement(x,y,x1,y1,x1rc,y1rc);
[x1_rotated,y1_rotated,xc,yc]=rotate(x,y,x1_p,y1_p,x1rc,y1rc);
%[x1_rotated,y1_rotated,xc,yc]=rotate(x,y,x1,y1,x1rc,y1rc);
x1rc=xc;
y1rc=yc;
end
% havent written the plot command

Placement()- The purpose of placement () is to shift the new arc to point of intersection of previous arc and the circle

function [x1_p,y1_p] = placement(x,y,x1,y1,x1rc,y1rc)

xcen=x1rc;
ycen=y1rc;

% shifting arc-lower-end to (t(1),0) or (
delx=xcen-x1(1); % Finding the x difference between arc-lower-end x-coordinate & x(1)[circle]
dely=ycen-y1(1); % Finding the y difference between arc-lower-end y-coordinate & y(1) [circle]

x1_p=x1+delx;
y1_p=y1+dely;
end

The rotation function():

 function [x1_rotated,y1_rotated,xc,yc] = rotate(x,y,x1_p,y1_p,x1rc,y1rc)
    % [x1_p,y1_p]= placement(x,y,x1,y1,x1rc,y1rc);
    theta =linspace(0,pi,500);
    i=1;
    xc=[];
    yc=[];
    xcen=x1rc;
    ycen=y1rc;
    while isempty(xc)||xc==xcen && isempty(yc)||yc==ycen
    % create a matrix of these points, which will be useful in future calculations
    v = [x1_p;y1_p];
    % choose a point which will be the center of rotation
    x_center = xcen;
    y_center = ycen;
    % create a matrix which will be used later in calculations
    center = repmat([x_center; y_center], 1, length(x1_p));
    % define a theta degree counter-clockwise rotation matrix
    R = [cos(theta(i)) -sin(theta(i)); sin(theta(i)) cos(theta(i))];
    % do the rotation...
    s = v - center;     % shift points in the plane so that the center of rotation is at the origin
    so = R*s;           % apply the rotation about the origin
    vo = so + center;   % shift again so the origin goes back to the desired center of rotation
    % this can be done in one line as:
    % vo = R*(v - center) + center
    % pick out the vectors of rotated x- and y-data
    x1_rotated = vo(1,:);
    y1_rotated = vo(2,:);
    [xc,yc] = polyxpoly(x1_rotated,y1_rotated,x,y);
    [xc1,yc1] = polyxpoly(x1_p,y1_p,x,y);
    if length(xc)==2
    xc=xc(2);
    yc=yc(2);
    end
    i=i+1;
    end
    end

I tried modifying the "if statement" as following but it seems after a certain iteration it dosen't work. The new modification in if statement are as follows

   if length(xc)==2
   ubx=xc(1); lbx=xc(2);
   uby=yc(2);lby=yc(1);
   xc=xc(2);
   yc=yc(2)
    
  ub=[ubx uby];
  lb=[lbx-4 lby];
  end

Then I was trying to return the ub and lb and got the following error message Output argument "ub" (and maybe others) not assigned during call to "rotate". after fifth iteration of for loop . The if statement worked fine for 1,2,3,4 iteation

  • 1
    How can we run this without `placement()`? Edit your post and and remove the first piece of code. Instead, only specify inputs that makes `rotate()` give unexpected results. Also, an image that shows expected results for the given inputs would be much better than images that you've already posted. – saastn Dec 14 '20 at 08:46
  • Thank you for the feedback. I have added two images which shows expected results vs unexpected result that I am getting. I even added the placement(). Basically I am unable to get the expected result. The purpose of placement() is to move the small arc from initial position to a new position. So basically x,y are coordinate of circle , (x1,y1 - coordinate of arc) (x1_p,y1_p are coordinate of arc after we move it to new position on the circle) . Once we place the arc on circle we rotate it using rotation matrix and rotation keeps occurring till arcs 2nd end touches the circle. – Praveen1891 Dec 14 '20 at 15:29
  • The new intersection acts as rotation point for next arc of similar dimension and the process continues as per iteration we mention in loop. When I do the process manually but feeding values it works but when I use for-loop I get unexpected result for certain iteration. – Praveen1891 Dec 14 '20 at 15:32

1 Answers1

2

It's a floating point comparison problem. Long story short, both 3*(4/3 -1) == 1 and sin(pi)==0 return false (Avoiding Common Problems with Floating-Point Arithmetic).

Change your while condition to something like this:

while (isempty(xc)||abs(xc-xcen)<=10*eps(xcen)) && (isempty(yc)||abs(yc-ycen)<=10*eps(ycen))

enter image description here

BTW, your assumption that when polyxpoly returns 2 point, the second point is your result, is not true. Try to find the furthest point from start point of the arc:

if length(xc)>1
    [~, i] = max((xc-xcen).^2+(yc-ycen).^2);
    xc=xc(i);
    yc=yc(i);
end
saastn
  • 5,717
  • 8
  • 47
  • 78
  • Thank you the code works now after modifying while loop statement but I still have some doubts as I am a beginner and my concepts are still not clear. I will be grateful if you clarify my doubts if you find it fit. 1) Why eps(xcen)??? I was thinking only eps will do . 2) xc is exact value that is passed to xcen , then why is floating problem arising?? Had it been two separate numbers I would have understood that the numbers are close by so floating point comparison arises. Thank you again. I learnt something new . – Praveen1891 Dec 17 '20 at 06:39
  • @Praveen1891 `eps` is equal to `eps(1.0)`. The precision of `double` type is varying and depends on the magnitude of the stored values. Therefore, the precision required to compare two numbers around `1.0` is different from the precision required around `100.0`. So this precision must be calculated each time for the values being compared, in your case `xc` or `xcen`. – saastn Dec 17 '20 at 08:31
  • @Praveen1891 What do you mean that `xc` is exact? `xc` is calculated and returned by `polyxpoly`. – saastn Dec 17 '20 at 08:32
  • Actually XC value is provided by polyxpoly() and this same XC value is stored inside Xcen for next iteration and then we have it used in while loop condition .For example Floating point comparison problem comes when we have numbers like 3.333333 vs 3.333334. But here since XC value is passed into Xcen so they are actually both same and I was unclear why the problem of floating point comparison arose in 1st place. Sorry for bothering you with minor questions. – Praveen1891 Dec 17 '20 at 11:07
  • Overall I am quite clear with the picture and reasoning you gave for above questions. Thank you for sparring your time. I am really grateful for your help. – Praveen1891 Dec 17 '20 at 11:07
  • @Praveen1891 No they are NOT the same. At each iteration, `xcen` is the intersection found in **previous** iteration, but `xc` is intersection found in **current** iteration. They are intersections of the circle with two different curves. This is exactly what called different sources of calculation which causes the fpc problem. – saastn Dec 17 '20 at 11:50
  • Well I dint see that coming. It was really subtle for me. So conclusion is that: both XC and Xcen are meant to have same values but since the values come from different source of calculation so we are having minor differences. Thank you for your time hope readers here get some help.I am really grateful. I did learn something new. – Praveen1891 Dec 18 '20 at 05:17
  • Actually I need both the intersection point to be used so for creating upper boundary and lower boundary for an optimization problem. So tried using if length(xc)==2 ubx=xc(1); lbx=xc(2); uby=yc(2);lby=yc(1); xc=xc(2); yc=yc(2); ub=[ubx uby]; lb=[lbx-4 lby]; end But after few loops again I am not getting ub and lb values. – Praveen1891 Dec 29 '20 at 07:27
  • Any method to save both xc(1) & xc(2) in both lb and ub using your method of using if statement. I have modified the question towards end for better clarity. – Praveen1891 Dec 29 '20 at 07:48