Get intersection point of line and CIE chromaticity curve

First, let me lay out what I’ve done so far and what I’m trying to do with this partially completed program.
I’m attempting to convert the RGB pixel values to their corresponding wavelength by:

Converting RGB to XYZ [check],
Converting XYZ to Yxy [check], and
Defining the dominant wavelength of xy [in progress].

The process of calculating the dominant wavelength of xy is laid out in [1,2]
and summarized as follows for my purposes:

'Construct a line between the chromaticity coordinates of the reference white point on the diagram [CIE-D65 --> x = 0.3127 , y = 0.3291] and the chromaticity coordinates [x1,y1 - in code below], and then extrapolate the line [via slopes] from the end that terminates at the filter point [graphed chromaticity curve].

The wavelength associated with the point on the horseshoe-shaped curve at which the extrapolated line intersects is the dominant wavelength.’

Essentially, the starting point x = 0.3127, y = 0.3291 is drawn to the RGB-converted x1, y1 point.
Then the slope, rise and run [slopeY, slopeX respectively] are calculated and followed until it intersects the horseshoe graph of the CIE 1931 2-deg, x,y chromaticity coordinates.

Here is where I’m having trouble. The horseshoe graph [picture above] of the “CIE x,y chromaticity coordinates, CIE 1931 2-deg chromaticity coordinates” which describe each corresponding wavelength are made up of many different points x,y and is listed here in CSV files [3].
[This annotated version I’m using is here, for clarity as to the x, y axis’]:

nm x y
360 0.17556 0.005294
365 0.175161 0.005256
370 0.174821 0.005221
375 0.17451 0.005182
380 0.174112 0.004964
385 0.174008 0.004981
390 0.173801 0.004915
395 0.17356 0.004923
400 0.173337 0.004797
405 0.173021 0.004775
410 0.172577 0.004799
415 0.172087 0.004833
420 0.171407 0.005102
425 0.170301 0.005789
430 0.168878 0.0069
435 0.166895 0.008556
440 0.164412 0.010858
445 0.161105 0.013793
450 0.156641 0.017705
455 0.150985 0.02274
460 0.14396 0.029703
465 0.135503 0.039879
470 0.124118 0.057803
475 0.109594 0.086843
480 0.091294 0.132702
485 0.068706 0.200723
490 0.045391 0.294976
495 0.02346 0.412703
500 0.008168 0.538423
505 0.003859 0.654823
510 0.01387 0.750186
515 0.038852 0.812016
520 0.074302 0.833803
525 0.114161 0.826207
530 0.154722 0.805864
535 0.192876 0.781629
540 0.22962 0.754329
545 0.265775 0.724324
550 0.301604 0.692308
555 0.337363 0.658848
560 0.373102 0.624451
565 0.408736 0.589607
570 0.444062 0.554714
575 0.478775 0.520202
580 0.512486 0.486591
585 0.544787 0.454434
590 0.575151 0.424232
595 0.602933 0.396497
600 0.627037 0.372491
605 0.648233 0.351395
610 0.665764 0.334011
615 0.680079 0.319747
620 0.691504 0.308342
625 0.700606 0.299301
630 0.707918 0.292027
635 0.714032 0.285929
640 0.719033 0.280935
645 0.723032 0.276948
650 0.725992 0.274008
655 0.728272 0.271728
660 0.729969 0.270031
665 0.731089 0.268911
670 0.731993 0.268007
675 0.732719 0.267281
680 0.733417 0.266583
685 0.734047 0.265953
690 0.73439 0.26561
695 0.734592 0.265408
700 0.73469 0.26531
705 0.73469 0.26531
710 0.73469 0.26531
715 0.734548 0.265452
720 0.73469 0.26531
725 0.73469 0.26531
730 0.73469 0.26531
735 0.73469 0.26531
740 0.73469 0.26531
745 0.73469 0.26531
750 0.73469 0.26531
755 0.73469 0.26531
760 0.73469 0.26531
765 0.73469 0.26531
770 0.73469 0.26531
775 0.73469 0.26531
780 0.73469 0.26531
785 0.73469 0.26531
790 0.73469 0.26531
795 0.73469 0.26531
800 0.73469 0.26531
805 0.73469 0.26531
810 0.73469 0.26531
815 0.73469 0.26531
820 0.73469 0.26531
825 0.73469 0.26531
830 0.73469 0.26531

I’m unsure of how to take all the x,y points in the CSV table [above] and algorithmically create the curve through which my line will intersect and output a specific wavelength.

How could I go about mapping the x,y chromaticity coordinates so that my slope-based line values [x_val, y_val] will intersect it and output the value?

float R2;
float G2;
float B2;

float X;
float Y;
float Z;

float x1;
float y1;
float z1;

float slopeY;
float slopeX;
float slope;

float lineX;
float lineY;
float x_val;
float y_val;

void setup() {
  size(1024,768);
}

void draw() {
  loadPixels();
  for (int x = 0; x < width; x++) {
   for (int y = 0; y < height; y++) {
    // Total X-Y Pixel Array Scan
    int loc = x+y*width;
    float r = 0;
    float g = 255;
    float b = 162;
    
    //Convert from RGB to XYZ
    R2 = r/255;
    G2 = g/255;
    B2 = b/255;
    
    if ( R2 > 0.04045 ) {
      R2 = pow(( ( R2 + 0.055 ) / 1.055 ), 2.4);
    }else{                   
      R2 = R2 / 12.92;
    }
    if ( G2 > 0.04045 ) {
      G2 = pow(( ( G2 + 0.055 ) / 1.055 ), 2.4);
    }else{
      G2 = G2 / 12.92;
    }
    if ( B2 > 0.04045 ){ 
      B2 = pow(( ( B2 + 0.055 ) / 1.055 ), 2.4);
    }else{                   
    B2 = B2 / 12.92;
    }
    
    R2 = R2 * 100;
    G2 = G2 * 100;
    B2 = B2 * 100;
    
    //Observer. = 2°, Illuminant = D65 [reference white]
    X = R2 * 0.4124 + G2 * 0.3576 + B2 * 0.1805;
    Y = R2 * 0.2126 + G2 * 0.7152 + B2 * 0.0722;
    Z = R2 * 0.0193 + G2 * 0.1192 + B2 * 0.9505;
    
        //println(X,Y,Z);
    
    //Convert from XYZ to Yxy [chromaticity coordinates]
    x1 = X / (X+Y+Z);
    y1 = Y / (X+Y+Z);
    z1 = 1 - (x1+y1); // thus, chromaticity coordinates are usually given as just x and y
    
        //println(x1,y1);
        //0.25991857, 0.45569262

    //Calculate the dominant wavelength of xy
    // construct a line between the chromaticity coordinates of the reference 
    // white point on the diagram (for instance, CIE-D65, CIE-E, CIEC, etc.) 
    // and the chromaticity coordinates [x1,y1], and then
    // extrapolate the line from the end that terminates at the filter point
    
    // The wavelength associated with the point on the horseshoe-shaped curve 
    // at which the extrapolated line intersects is the dominant wavelength.
    
    // Reference White [Illuminant]
    // CIE-D65 --> x = 0.3127 , y = 0.3291
      lineX = 0.3127;
      lineY = 0.3291;
    // Chromaticity coordinates of filter [x1,y1],
      x_val = x1; //0.25991857;
      y_val = y1; //0.45569262;
    
        // slopeY = [YA - YB]  
        // slopeX = [XA - XB]
        slopeY = (lineY - y_val); // YB = Current xy point 0.45569262
        slopeX = (lineX - x_val); // XB = Current xy point 0.25991857
        
        slope = slopeY/slopeX; // -2.3984306
        
        if (slope < 0){
          
          while (x_val>0 && y_val>0){
          x_val = x_val - slopeX; 
          y_val = y_val - slopeY;
          }
            if (x_val<0 || y_val<0){
            x_val = x_val + slopeX; 
            y_val = y_val + slopeY;
            }
          
        } else {
 
        }
       
        //println(slope);
        //println(x_val, y_val);

    

    //float d = dist(width/2, height/2, x, y);
    pixels[loc] = color(r, g, b);
   }
  }  
  updatePixels();
}

References:

Yxy Equations -
[1] https://www.semrock.com/how-to-calculate-luminosity-dominant-wavelength-and-excitation-purity.aspx
[2] https://www.hunterlab.se/wp-content/uploads/2012/11/Yxy-CIE-Chromaticity-Coordinates.pdf.

CIE 1931 2-deg, x,y chromaticity coordinates / Filter Points -
[3] http://www.cvrl.org/ccs.htm

CIE Basics-
http://hyperphysics.phy-astr.gsu.edu/hbase/vision/cie.html#c4

1 Like

Thanks but I’m not converting LAB to XYZ to RGB. And I’ve already converted the RGB to XYZ and then XYZ to Yxy in the above code. I’m trying to find the intersect point of the x_val and y_val (of Yxy) and the entire chromaticity coordinates graph.

Edit [1]:
I was thinking maybe something like using PVectors and storing the x,y values of all the chromaticity coordinates graph, though how I’d define the intersect point of x_val and y_val and the graph boundary points is murky.

Edit [2]:
I’ve run with the PVectors idea and wrote a separate program to create the chromaticity coordinates curve with beginShape and then used the equations from the original program to draw the dominant wavelength line.

I’ve managed to cause the line to intersect the curve, but how can I define the new x,y intersect point?

float lineX;
float lineY;
float x_val;
float y_val;

float slopeY;
float slopeX;
float slope;

float cycle = 0;

void setup(){  
size(640,360);
 background(0);
}
void draw(){  
  
// declaring the array (notice the brackets)
PVector[] nm;

// setting up the array (96 = 96 items)
nm = new PVector[96];

// filling the array :
nm[0] = new PVector(0.175560, 0.005294);
nm[1] = new PVector(0.175161, 0.005256);
nm[2] = new PVector(0.174821, 0.005221);
nm[3] = new PVector(0.174510, 0.005182);
nm[4] = new PVector(0.174112, 0.004964);
nm[5] = new PVector(0.174008, 0.004981);
nm[6] = new PVector(0.173801, 0.004915);
nm[7] = new PVector(0.173560, 0.004923);
nm[8] = new PVector(0.173337, 0.004797);
nm[9] = new PVector(0.173021, 0.004775);
nm[10] = new PVector(0.172577, 0.004799);
nm[11] = new PVector(0.172087, 0.004833);
nm[12] = new PVector(0.171407, 0.005102);
nm[13] = new PVector(0.170301, 0.005789);
nm[14] = new PVector(0.168878, 0.0069);
nm[15] = new PVector(0.166895, 0.008556);
nm[16] = new PVector(0.164412, 0.010858);
nm[17] = new PVector(0.161105, 0.013793);
nm[18] = new PVector(0.156641, 0.017705);
nm[19] = new PVector(0.150985, 0.02274);
nm[20] = new PVector(0.143960, 0.029703);
nm[21] = new PVector(0.135503, 0.039879);
nm[22] = new PVector(0.124118, 0.057803);
nm[23] = new PVector(0.109594, 0.086843);
nm[24] = new PVector(0.091294, 0.132702);
nm[25] = new PVector(0.068706, 0.200723);
nm[26] = new PVector(0.045391, 0.294976);
nm[27] = new PVector(0.023460, 0.412703);
nm[28] = new PVector(0.008168, 0.538423);
nm[29] = new PVector(0.003859, 0.654823);
nm[30] = new PVector(0.013870, 0.750186);
nm[31] = new PVector(0.038852, 0.812016);
nm[32] = new PVector(0.074302, 0.833803);
nm[33] = new PVector(0.114161, 0.826207);
nm[34] = new PVector(0.154722, 0.805864);
nm[35] = new PVector(0.192876, 0.781629);
nm[36] = new PVector(0.229620, 0.754329);
nm[37] = new PVector(0.265775, 0.724324);
nm[38] = new PVector(0.301604, 0.692308);
nm[39] = new PVector(0.337363, 0.658848);
nm[40] = new PVector(0.373102, 0.624451);
nm[41] = new PVector(0.408736, 0.589607);
nm[42] = new PVector(0.444062, 0.554714);
nm[43] = new PVector(0.478775, 0.520202);
nm[44] = new PVector(0.512486, 0.486591);
nm[45] = new PVector(0.544787, 0.454434);
nm[46] = new PVector(0.575151, 0.424232);
nm[47] = new PVector(0.602933, 0.396497);
nm[48] = new PVector(0.627037, 0.372491);
nm[49] = new PVector(0.648233, 0.351395);
nm[50] = new PVector(0.665764, 0.334011);
nm[51] = new PVector(0.680079, 0.319747);
nm[52] = new PVector(0.691504, 0.308342);
nm[53] = new PVector(0.700606, 0.299301);
nm[54] = new PVector(0.707918, 0.292027);
nm[55] = new PVector(0.714032, 0.285929);
nm[56] = new PVector(0.719033, 0.280935);
nm[57] = new PVector(0.723032, 0.276948);
nm[58] = new PVector(0.725992, 0.274008);
nm[59] = new PVector(0.728272, 0.271728);
nm[60] = new PVector(0.729969, 0.270031);
nm[61] = new PVector(0.731089, 0.268911);
nm[62] = new PVector(0.731993, 0.268007);
nm[63] = new PVector(0.732719, 0.267281);
nm[64] = new PVector(0.733417, 0.266583);
nm[65] = new PVector(0.734047, 0.265953);
nm[66] = new PVector(0.734390, 0.26561);
nm[67] = new PVector(0.734592, 0.265408);
nm[68] = new PVector(0.734690, 0.26531);
nm[69] = new PVector(0.734690, 0.26531);
nm[70] = new PVector(0.734690, 0.26531);
nm[71] = new PVector(0.734548, 0.265452);
nm[72] = new PVector(0.734690, 0.26531);
nm[73] = new PVector(0.734690, 0.26531);
nm[74] = new PVector(0.734690, 0.26531);
nm[75] = new PVector(0.734690, 0.26531);
nm[76] = new PVector(0.734690, 0.26531);
nm[77] = new PVector(0.734690, 0.26531);
nm[78] = new PVector(0.734690, 0.26531);
nm[79] = new PVector(0.734690, 0.26531);
nm[80] = new PVector(0.734690, 0.26531);
nm[81] = new PVector(0.734690, 0.26531);
nm[82] = new PVector(0.734690, 0.26531);
nm[83] = new PVector(0.734690, 0.26531);
nm[84] = new PVector(0.734690, 0.26531);
nm[85] = new PVector(0.734690, 0.26531);
nm[86] = new PVector(0.734690, 0.26531);
nm[87] = new PVector(0.734690, 0.26531);
nm[88] = new PVector(0.734690, 0.26531);
nm[89] = new PVector(0.734690, 0.26531);
nm[90] = new PVector(0.734690, 0.26531);
nm[91] = new PVector(0.734690, 0.26531);
nm[92] = new PVector(0.734690, 0.26531);
nm[93] = new PVector(0.734690, 0.26531);
nm[94] = new PVector(0.734690, 0.26531);
nm[95] = new PVector(0.734690, 0.26531);

while (cycle == 0){
  translate(260, 280);
  noFill();
  stroke(255);
  strokeWeight(1);
  beginShape();    

    int x1;  
    for (x1=0; x1<96; x1++){
    PVector v = nm[x1];
    float x = v.x;
    float y = v.y; 
    int nm_val = 360;
        nm_val = nm_val + (5*x1);
          println(nm_val+"nm = "+x,y);
      
    // Create chromasticity curve using beginShape
    vertex(x * pow(2,8),-y * pow(2,8)); //inverted y-ais for chromasticity graph
   }
   
  endShape(CLOSE);
  
  // lineX, lineY (starting point): lineX2, lineY2 (Endpoint) 
  //line(0.3127 * pow(2,8), -0.3291 * pow(2,8), 0.25991857 * pow(2,8), -0.45569262 * pow(2,8));

    lineX = 0.3127 * pow(2,8);
    lineY = 0.3291 * pow(2,8);
    x_val = 0.25991857 * pow(2,8);
    y_val = 0.45569262 * pow(2,8);
    
        slopeY = (lineY - y_val); // YB = Current xy point 0.45569262
        slopeX = (lineX - x_val); // XB = Current xy point 0.25991857
        
        slope = slopeY/slopeX; // -0.41693923389846896288267041159271
        
        if (slope < 0){
          
          while (x_val>0 && y_val>0){
          x_val = x_val - slopeX; 
          y_val = y_val - slopeY;
          }
            if (x_val<0 || y_val<0){
            x_val = x_val + slopeX; 
            y_val = y_val + slopeY;
            }
          
        } else {
 
        }
        
  line(lineX, -lineY, x_val, -y_val);
  
  cycle = 1;
  }
}
1 Like

Are you, in general, wanting a line/line intersection formula for this? If I’m understanding your code right, your “curve” is actually a series of line segments. If you iterated over those curve segments and checked each against your line, zero or more of them will return a solution for a line-line intersection point.

2 Likes

jeremydouglass:
Are you, in general, wanting a line/line intersection formula for this?

If the line/line intersection formula can also provide the x and y intersect coordinates then yes, because in order to calculate the exact dominant wavelength I need to know the coordinates in which the line intersects the graphed curve.

jeremydouglass:
If I’m understanding your code right, your “curve” is actually a series of line segments.

Yes exactly, though I used the beginShape() method in the second code, the same method could easily be applied with producing lines between each point.

jeremydouglass:
If you iterated over those curve segments and checked each against your line, zero or more of them will return a solution for a line-line intersection point.

Well actually the dominant wavelength line will always have a set starting point:

    lineX = 0.3127 * pow(2,8);
    lineY = 0.3291 * pow(2,8);

and have a fixed point defined by the RGB pixel–>XYZ–>xy conversion

    x_val = 0.25991857 * pow(2,8);
    y_val = 0.45569262 * pow(2,8);

which then sets the fixed slope and allows the calculation of the whole line, defining the [x,y] intersection point with the graphed curve. Given that, there should only be a single possible intersection point, as shown below.

Graphv3

Great! Sounds like you have a solution, then. Loop over your segments and test them against your line for intersection.

Here is Thompson’s tutorial method that I linked to earlier, modified to return the intersection point (or null if no intersection):

PVector lineLine(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
  // calculate the distance to intersection point
  float uA = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
  float uB = ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
  // if uA and uB are between 0-1, lines are colliding
  if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {
    // computer intersection point
    float intersectionX = x1 + (uA * (x2-x1));
    float intersectionY = y1 + (uA * (y2-y1));
    return new PVector(intersectionX, intersectionY);
  }
  return null;
}

So given a list of curve segments segments and a line line, you could use that method something like this:

// loop over segments and mark the point if intersection is not null
for (float[] seg : segments){
  PVector intersection = lineLine(seg[0], seg[1], seg[2], seg[3], line[0], line[1], line[2], line[3]);
  if(intersection != null){
    ellipse(intersection.x, intersection.y, 20, 20);
    break; 
  }
}
1 Like

That’s great thank you! However, I’m relatively new to the PVector() method could you perhaps demonstrate that mathematical method with PVector() in an example?

Sure. First, your draw coordinates and your data coordinates are not the same, and you switch back and forth a lot in your code – computing the line as draw coordinates, but storing nm as data coordinates. To simplify a demonstrated solution let’s create a second nm array for our draw coordinates:

PVector[] nmDraw;

…and store them like this:

  // Create chromasticity curve using beginShape
  PVector pt = new PVector(x * pow(2, 8), -y * pow(2, 8));
  nmDraw[x1] = pt;
  vertex(pt.x, pt.y); //inverted y-ais for chromasticity graph

Now, IF we had found the line first, we could find the intersection while in the loop to draw our curve. But instead of doing that, let’s add something to find the intersection as a separate stage, at the very end of draw:

  println(lineX, -lineY, x_val, -y_val);
  PVector resultPoint = colorPoint(nmDraw, lineX, -lineY, x_val, -y_val);
  println(resultPoint);
  ellipse(resultPoint.x, resultPoint.y, 20, 20);
}

We call colorPoint to solve for the intersection, which loops through the draw segments and compares them to the draw line. Notice that if we computed our line in data space then we could compare it to nm instead with the same function.

PVector colorPoint(PVector[] nm, float x1, float y1, float x2, float y2) {
  PVector resultPoint;
  for (int i=1; i<nm.length; i++) {
    PVector seg1 = nm[i-1];
    PVector seg2 = nm[i];
    //    println(seg1.x, seg1.y, seg2.x, seg2.y, x1, y1, x2, y2);
    resultPoint = lineLine(seg1.x, seg1.y, seg2.x, seg2.y, x1, y1, x2, y2);
    if (resultPoint != null) {
      return resultPoint;
    }
  }
  return null;
}

This function is built on many calls to lineLine, the line-line intersection detection which I showed you earlier, and looks like this:

PVector lineLine(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
  // calculate the distance to intersection point
  float uA = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
  float uB = ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
  // if uA and uB are between 0-1, lines are colliding
  if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {
    // computer intersection point
    float intersectionX = x1 + (uA * (x2-x1));
    float intersectionY = y1 + (uA * (y2-y1));
    return new PVector(intersectionX, intersectionY);
  }
  return null;
}

The result prints your line and your intersection point between the curve and the line

80.0512 -84.2496 12.490967 -246.28815
[ 26.798986, -211.97136, 0.0 ]

and draws a circle around that point.

Complete sketch code
float lineX;
float lineY;
float x_val;
float y_val;

float slopeY;
float slopeX;
float slope;

float cycle = 0;

PVector[] nm;
PVector[] nmDraw;

void setup() {  
  size(640, 360);

  // setting up the array (96 = 96 items)
  nm = new PVector[96];
  nmDraw = new PVector[96];
  // filling the array :
  nm[0] = new PVector(0.175560, 0.005294);
  nm[1] = new PVector(0.175161, 0.005256);
  nm[2] = new PVector(0.174821, 0.005221);
  nm[3] = new PVector(0.174510, 0.005182);
  nm[4] = new PVector(0.174112, 0.004964);
  nm[5] = new PVector(0.174008, 0.004981);
  nm[6] = new PVector(0.173801, 0.004915);
  nm[7] = new PVector(0.173560, 0.004923);
  nm[8] = new PVector(0.173337, 0.004797);
  nm[9] = new PVector(0.173021, 0.004775);
  nm[10] = new PVector(0.172577, 0.004799);
  nm[11] = new PVector(0.172087, 0.004833);
  nm[12] = new PVector(0.171407, 0.005102);
  nm[13] = new PVector(0.170301, 0.005789);
  nm[14] = new PVector(0.168878, 0.0069);
  nm[15] = new PVector(0.166895, 0.008556);
  nm[16] = new PVector(0.164412, 0.010858);
  nm[17] = new PVector(0.161105, 0.013793);
  nm[18] = new PVector(0.156641, 0.017705);
  nm[19] = new PVector(0.150985, 0.02274);
  nm[20] = new PVector(0.143960, 0.029703);
  nm[21] = new PVector(0.135503, 0.039879);
  nm[22] = new PVector(0.124118, 0.057803);
  nm[23] = new PVector(0.109594, 0.086843);
  nm[24] = new PVector(0.091294, 0.132702);
  nm[25] = new PVector(0.068706, 0.200723);
  nm[26] = new PVector(0.045391, 0.294976);
  nm[27] = new PVector(0.023460, 0.412703);
  nm[28] = new PVector(0.008168, 0.538423);
  nm[29] = new PVector(0.003859, 0.654823);
  nm[30] = new PVector(0.013870, 0.750186);
  nm[31] = new PVector(0.038852, 0.812016);
  nm[32] = new PVector(0.074302, 0.833803);
  nm[33] = new PVector(0.114161, 0.826207);
  nm[34] = new PVector(0.154722, 0.805864);
  nm[35] = new PVector(0.192876, 0.781629);
  nm[36] = new PVector(0.229620, 0.754329);
  nm[37] = new PVector(0.265775, 0.724324);
  nm[38] = new PVector(0.301604, 0.692308);
  nm[39] = new PVector(0.337363, 0.658848);
  nm[40] = new PVector(0.373102, 0.624451);
  nm[41] = new PVector(0.408736, 0.589607);
  nm[42] = new PVector(0.444062, 0.554714);
  nm[43] = new PVector(0.478775, 0.520202);
  nm[44] = new PVector(0.512486, 0.486591);
  nm[45] = new PVector(0.544787, 0.454434);
  nm[46] = new PVector(0.575151, 0.424232);
  nm[47] = new PVector(0.602933, 0.396497);
  nm[48] = new PVector(0.627037, 0.372491);
  nm[49] = new PVector(0.648233, 0.351395);
  nm[50] = new PVector(0.665764, 0.334011);
  nm[51] = new PVector(0.680079, 0.319747);
  nm[52] = new PVector(0.691504, 0.308342);
  nm[53] = new PVector(0.700606, 0.299301);
  nm[54] = new PVector(0.707918, 0.292027);
  nm[55] = new PVector(0.714032, 0.285929);
  nm[56] = new PVector(0.719033, 0.280935);
  nm[57] = new PVector(0.723032, 0.276948);
  nm[58] = new PVector(0.725992, 0.274008);
  nm[59] = new PVector(0.728272, 0.271728);
  nm[60] = new PVector(0.729969, 0.270031);
  nm[61] = new PVector(0.731089, 0.268911);
  nm[62] = new PVector(0.731993, 0.268007);
  nm[63] = new PVector(0.732719, 0.267281);
  nm[64] = new PVector(0.733417, 0.266583);
  nm[65] = new PVector(0.734047, 0.265953);
  nm[66] = new PVector(0.734390, 0.26561);
  nm[67] = new PVector(0.734592, 0.265408);
  nm[68] = new PVector(0.734690, 0.26531);
  nm[69] = new PVector(0.734690, 0.26531);
  nm[70] = new PVector(0.734690, 0.26531);
  nm[71] = new PVector(0.734548, 0.265452);
  nm[72] = new PVector(0.734690, 0.26531);
  nm[73] = new PVector(0.734690, 0.26531);
  nm[74] = new PVector(0.734690, 0.26531);
  nm[75] = new PVector(0.734690, 0.26531);
  nm[76] = new PVector(0.734690, 0.26531);
  nm[77] = new PVector(0.734690, 0.26531);
  nm[78] = new PVector(0.734690, 0.26531);
  nm[79] = new PVector(0.734690, 0.26531);
  nm[80] = new PVector(0.734690, 0.26531);
  nm[81] = new PVector(0.734690, 0.26531);
  nm[82] = new PVector(0.734690, 0.26531);
  nm[83] = new PVector(0.734690, 0.26531);
  nm[84] = new PVector(0.734690, 0.26531);
  nm[85] = new PVector(0.734690, 0.26531);
  nm[86] = new PVector(0.734690, 0.26531);
  nm[87] = new PVector(0.734690, 0.26531);
  nm[88] = new PVector(0.734690, 0.26531);
  nm[89] = new PVector(0.734690, 0.26531);
  nm[90] = new PVector(0.734690, 0.26531);
  nm[91] = new PVector(0.734690, 0.26531);
  nm[92] = new PVector(0.734690, 0.26531);
  nm[93] = new PVector(0.734690, 0.26531);
  nm[94] = new PVector(0.734690, 0.26531);
  nm[95] = new PVector(0.734690, 0.26531);

  noLoop();
}

void draw() {  
  background(0);
  while (cycle == 0) {
    translate(260, 280);
    noFill();
    stroke(255);
    strokeWeight(1);
    beginShape();    

    int x1;  
    for (x1=0; x1<96; x1++) {
      PVector v = nm[x1];
      float x = v.x;
      float y = v.y; 
      int nm_val = 360;
      nm_val = nm_val + (5*x1);
      // println(nm_val+"nm = "+x, y);

      // Create chromasticity curve using beginShape
      PVector pt = new PVector(x * pow(2, 8), -y * pow(2, 8));
      nmDraw[x1] = pt;
      vertex(pt.x, pt.y); //inverted y-ais for chromasticity graph
    }

    endShape(CLOSE);

    // lineX, lineY (starting point): lineX2, lineY2 (Endpoint) 
    //line(0.3127 * pow(2,8), -0.3291 * pow(2,8), 0.25991857 * pow(2,8), -0.45569262 * pow(2,8));

    lineX = 0.3127 * pow(2, 8);
    lineY = 0.3291 * pow(2, 8);
    x_val = 0.25991857 * pow(2, 8);
    y_val = 0.45569262 * pow(2, 8);

    slopeY = (lineY - y_val); // YB = Current xy point 0.45569262
    slopeX = (lineX - x_val); // XB = Current xy point 0.25991857
    slope = slopeY/slopeX; // -0.41693923389846896288267041159271

    if (slope < 0) {
      while (x_val>0 && y_val>0) {
        x_val = x_val - slopeX; 
        y_val = y_val - slopeY;
      }
      if (x_val<0 || y_val<0) {
        x_val = x_val + slopeX; 
        y_val = y_val + slopeY;
      }
    } else {
    }
    line(lineX, -lineY, x_val, -y_val);
    cycle = 1;
  }
  println(lineX, -lineY, x_val, -y_val);
  PVector resultPoint = colorPoint(nmDraw, lineX, -lineY, x_val, -y_val);
  println(resultPoint);
  ellipse(resultPoint.x, resultPoint.y, 20, 20);
}

PVector colorPoint(PVector[] nm, float x1, float y1, float x2, float y2) {
  PVector resultPoint;
  for (int i=1; i<nm.length; i++) {
    PVector seg1 = nm[i-1];
    PVector seg2 = nm[i];
    //    println(seg1.x, seg1.y, seg2.x, seg2.y, x1, y1, x2, y2);
    resultPoint = lineLine(seg1.x, seg1.y, seg2.x, seg2.y, x1, y1, x2, y2);
    if (resultPoint != null) {
      return resultPoint;
    }
  }
  return null;
}

PVector lineLine(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
  // calculate the distance to intersection point
  float uA = ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
  float uB = ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3)) / ((y4-y3)*(x2-x1) - (x4-x3)*(y2-y1));
  // if uA and uB are between 0-1, lines are colliding
  if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {
    // computer intersection point
    float intersectionX = x1 + (uA * (x2-x1));
    float intersectionY = y1 + (uA * (y2-y1));
    return new PVector(intersectionX, intersectionY);
  }
  return null;
}
1 Like