public CIE1931Point NearestContainedPoint(CIE1931Point point) { if (Contains(point)) { // If this gamut already contains the point, then no adjustment is required. return(point); } // Find the closest point on each line in the triangle. CIE1931Point pAB = GetClosestPointOnLine(Red, Green, point); CIE1931Point pAC = GetClosestPointOnLine(Red, Blue, point); CIE1931Point pBC = GetClosestPointOnLine(Green, Blue, point); //Get the distances per point and see which point is closer to our Point. double dAB = GetDistanceBetweenTwoPoints(point, pAB); double dAC = GetDistanceBetweenTwoPoints(point, pAC); double dBC = GetDistanceBetweenTwoPoints(point, pBC); double lowest = dAB; CIE1931Point closestPoint = pAB; if (dAC < lowest) { lowest = dAC; closestPoint = pAC; } if (dBC < lowest) { lowest = dBC; closestPoint = pBC; } return(closestPoint); }
private static double GetDistanceBetweenTwoPoints(CIE1931Point one, CIE1931Point two) { double dx = one.x - two.x; // horizontal difference double dy = one.y - two.y; // vertical difference return(Math.Sqrt(dx * dx + dy * dy)); }
private static bool IsAbove(CIE1931Point blue, CIE1931Point red, CIE1931Point point) { double slope = (blue.y - red.y) / (blue.x - red.x); double intercept = blue.y - slope * blue.x; double minY = point.x * slope + intercept; return(point.y >= minY); }
private static bool IsBelow(CIE1931Point a, CIE1931Point b, CIE1931Point point) { double slope = (a.y - b.y) / (a.x - b.x); double intercept = a.y - slope * a.x; double maxY = point.x * slope + intercept; return(point.y <= maxY); }
public bool Contains(CIE1931Point point) { // Arrangement of points in color space: // // ^ G // y| // | R // | B // .-------------------> // x // return(IsBelow(Blue, Green, point) && IsBelow(Green, Red, point) && IsAbove(Red, Blue, point)); }
private static CIE1931Point GetClosestPointOnLine(CIE1931Point a, CIE1931Point b, CIE1931Point p) { CIE1931Point AP = new CIE1931Point(p.x - a.x, p.y - a.y); CIE1931Point AB = new CIE1931Point(b.x - a.x, b.y - a.y); double ab2 = AB.x * AB.x + AB.y * AB.y; double ap_ab = AP.x * AB.x + AP.y * AB.y; double t = ap_ab / ab2; // Bound to ends of line between A and B. if (t < 0.0f) { t = 0.0f; } else if (t > 1.0f) { t = 1.0f; } return(new CIE1931Point(a.x + AB.x * t, a.y + AB.y * t)); }
public CIE1931Gamut(CIE1931Point red, CIE1931Point green, CIE1931Point blue) { this.Red = red; this.Green = green; this.Blue = blue; }