Skip to content

Commit 9544bf1

Browse files
committed
Improve performance of path gradient brush on triangles.
1 parent 799d6af commit 9544bf1

3 files changed

Lines changed: 53 additions & 0 deletions

File tree

src/ImageSharp.Drawing/Processing/PathGradientBrush.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,25 @@ public PathGradientBrushApplicator(
257257
return this.centerPixel;
258258
}
259259

260+
if (this.edges.Count == 3)
261+
{
262+
if (!this.FindPointOnTriangle(
263+
this.edges[0].Start,
264+
this.edges[1].Start,
265+
this.edges[2].Start,
266+
point,
267+
out float u,
268+
out float v))
269+
{
270+
return this.transparentPixel;
271+
}
272+
273+
Vector4 pointColor = ((1 - u - v) * this.edges[0].StartColor) + (u * this.edges[0].EndColor) +
274+
(v * this.edges[2].StartColor);
275+
276+
return new Color(pointColor).ToPixel<TPixel>();
277+
}
278+
260279
var direction = Vector2.Normalize(point - this.center);
261280
PointF end = point + (PointF)(direction * this.maxDistance);
262281

@@ -301,6 +320,40 @@ public PathGradientBrushApplicator(
301320

302321
return closest;
303322
}
323+
324+
private bool FindPointOnTriangle(PointF v1, PointF v2, PointF v3, PointF point, out float u, out float v)
325+
{
326+
Vector2 e1 = v2 - v1;
327+
Vector2 e2 = v3 - v2;
328+
Vector2 e3 = v1 - v3;
329+
330+
Vector2 pv1 = point - v1;
331+
Vector2 pv2 = point - v2;
332+
Vector2 pv3 = point - v3;
333+
334+
var d1 = Vector3.Cross(new Vector3(e1.X, e1.Y, 0), new Vector3(pv1.X, pv1.Y, 0));
335+
var d2 = Vector3.Cross(new Vector3(e2.X, e2.Y, 0), new Vector3(pv2.X, pv2.Y, 0));
336+
var d3 = Vector3.Cross(new Vector3(e3.X, e3.Y, 0), new Vector3(pv3.X, pv3.Y, 0));
337+
338+
if (Math.Sign(Vector3.Dot(d1, d2)) != Math.Sign(Vector3.Dot(d1, d3)) || Math.Sign(Vector3.Dot(d1, d2)) != Math.Sign(Vector3.Dot(d2, d3)))
339+
{
340+
u = 0;
341+
v = 0;
342+
return false;
343+
}
344+
345+
// From Real-Time Collision Detection
346+
// https://gamedev.stackexchange.com/questions/23743/whats-the-most-efficient-way-to-find-barycentric-coordinates
347+
float d00 = Vector2.Dot(e1, e1);
348+
float d01 = Vector2.Dot(e1, -e3);
349+
float d11 = Vector2.Dot(-e3, -e3);
350+
float d20 = Vector2.Dot(pv1, e1);
351+
float d21 = Vector2.Dot(pv1, -e3);
352+
float denominator = (d00 * d11) - (d01 * d01);
353+
u = ((d11 * d20) - (d01 * d21)) / denominator;
354+
v = ((d00 * d21) - (d01 * d20)) / denominator;
355+
return true;
356+
}
304357
}
305358
}
306359
}
39 Bytes
Loading
Loading

0 commit comments

Comments
 (0)