How to calculate coordinates of 6 point of intersection between a circle and a equilateral triangle? - geometry

I know of an equilateral triangle the center (cx,cy) and the radius (r) of a blue circle which circumscribed it.
If I draw a green circle of any radius (radius), assuming the circle is large enough to have this intersection, can I get the coordinates of the 6 intersection points (P1, P2, P3...)?
I'm looking for P5JS/processing but any other clue can help me...
Thank you in advance

Distance from the center to top point is r.
Distance from the center to the lowest triangle side is r/2 (median intersection point is center, they are divided in 1:2 ratio).
Horizontal distance from cx to p4 (and p5) is (Pythagoras' theorem)
dx = sqrt(radius^2 - r^2/4)
So coordinates of p4 and p5 are (relative to center)
p4x = dx
p4y = r/2
p5x = -dx
p5y = r/2
Other points might be calculated using rotation by 120 degrees
p2x = p4x*(-1/2) - p4y*(sqrt(3)/2)
p2y = p4x*(sqrt(3)/2) + p4y*(-1/2)
and so on.
And finally add cx,cy to get absolute coordinates

If you want to test... ;-)
function setup() {
createCanvas(500, 500);
const cx = width / 2;
const cy = height / 2;
const r = 250; // taille du triangle
const radius = 180; // externe
noFill();
strokeWeight(3);
stroke(0, 0, 0);
drawTriangle(cx, cy, r);
strokeWeight(1);
stroke(0, 0, 255);
circle(cx, cy, r * 2);
strokeWeight(2);
stroke(8, 115, 0);
circle(cx, cy, radius * 2);
noStroke();
fill(215, 0, 0);
// dx = sqrt(Math.pow(r / 2, 2) - Math.pow(r / 2, 2 / 4));
dx = sqrt(radius * radius - (r * r) / 4);
p4x = dx;
p4y = r / 2;
circle(cx + p4x, cy + p4y, 20);
text("p4", cx + p4x, cy + p4y + 30);
p5x = -dx;
p5y = r / 2;
circle(cx + p5x, cy + p5y, 20);
text("p5", cx + p5x - 10, cy + p5y + 30);
p6x = p4x * (-1 / 2) - p4y * (sqrt(3) / 2);
p6y = p4x * (sqrt(3) / 2) + p4y * (-1 / 2);
circle(cx + p6x, cy + p6y, 20);
text("p6", cx + p6x - 30, cy + p6y);
p2x = p6x * (-1 / 2) - p6y * (sqrt(3) / 2);
p2y = p6x * (sqrt(3) / 2) + p6y * (-1 / 2);
circle(cx + p2x, cy + p2y, 20);
text("p2", cx + p2x + 10, cy + p2y - 10);
p1x = p5x * (-1 / 2) - p5y * (sqrt(3) / 2);
p1y = p5x * (sqrt(3) / 2) + p5y * (-1 / 2);
circle(cx + p1x, cy + p1y, 20);
text("p1", cx + p1x - 20, cy + p1y - 10);
p3x = p1x * (-1 / 2) - p1y * (sqrt(3) / 2);
p3y = p1x * (sqrt(3) / 2) + p1y * (-1 / 2);
circle(cx + p3x, cy + p3y, 20);
text("p3", cx + p3x + 20, cy + p3y - 10);
noFill();
stroke(0, 255, 255);
triangle(cx + p2x, cx + p2y, cx + p4x, cx + p4y, cx + p6x, cx + p6y);
stroke(255, 0, 255);
// prettier-ignore
triangle(
cx + p1x, cx + p1y,
cx + p3x, cx + p3y,
cx + p5x, cx + p5y,
)
}
function drawTriangle(cx, cy, radius) {
noFill();
trianglePoints = [];
for (var i = 0; i < 3; i++) {
var x = cx + radius * cos((i * TWO_PI) / 3.0 - HALF_PI);
var y = cy + radius * sin((i * TWO_PI) / 3.0 - HALF_PI);
trianglePoints[i] = {
x,
y,
};
}
triangle(
trianglePoints[0].x,
trianglePoints[0].y,
trianglePoints[1].x,
trianglePoints[1].y,
trianglePoints[2].x,
trianglePoints[2].y
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.min.js"></script>

Related

SVG Text Not Aligning in Edge

I cannot find a solution to my issue here, so I am posting a new question. The text in my SVG here is not aligned properly in Edge. It works fine in Firefox, but when I open the page in Edge, the text is crooked and spaced unevenly. It looks great in Firefox though. I have tried numerous fixes, but nothing seems to be working. What is causing this and how can I fix it?
Javascript
const rad = Math.PI / 180;
let cx = 50, cy = 100, R = 50, r = 35, A = 40 , a = 5, o=4;
// o for offset
svgGroupC.setAttributeNS(null, "transform", `rotate(${-90 -(A / 2) - a} ${cx} ${cy})`);
// control points for the quadratic Bézier
let px1 = cx + R * Math.cos(0);
let py1 = cy + R * Math.sin(0);
let px2 = cx + R * Math.cos((2*a + A)*rad);
let py2 = cy + R * Math.sin((2*a + A)*rad);
let px3 = cx + r * Math.cos((2*a + A)*rad);
let py3 = cy + r * Math.sin((2*a + A)*rad);
let px4 = cx + r * Math.cos(0);
let py4 = cy + r * Math.sin(0);
// points used to draw the shape
let x11 = cx + (R-o) * Math.cos(0);
let y11 = cy + (R-o) * Math.sin(0);
let x1 = cx + R * Math.cos(a*rad);
let y1 = cy + R * Math.sin(a*rad);
let x2 = cx + R * Math.cos((a + A)*rad);
let y2 = cy + R * Math.sin((a + A)*rad);
let x21 = cx + (R-o) * Math.cos((2*a + A)*rad);
let y21 = cy + (R-o) * Math.sin((2*a + A)*rad);
let x31 = cx + (r+o) * Math.cos((2*a + A)*rad);
let y31 = cy + (r+o) * Math.sin((2*a + A)*rad);
let x3 = cx + r * Math.cos((a + A)*rad);
let y3 = cy + r * Math.sin((a + A)*rad);
let x4 = cx + r * Math.cos(a*rad);
let y4 = cy + r * Math.sin(a*rad);
let x41 = cx + (r+o) * Math.cos(0);
let y41 = cy + (r+o) * Math.sin(0);
// Rounded corners with quadratic Bézier curves
d = `M${x1},${y1}
A${R},${R},0 0,1 ${x2},${y2}
Q${px2},${py2} ${x21},${y21}
L${x31},${y31}
Q${px3},${py3} ${x3},${y3}
A${r},${r},0 0,0 ${x4},${y4}
Q${px4},${py4} ${x41},${y41}
L${x11},${y11}
Q${px1},${py1} ${x1},${y1}Z`;
svgPath.setAttributeNS(null,"d",d);
HTML
<svg viewBox="0 40 100 40">
<g id="svgGroupC" >
<style type="text/css">
#import url('https://fonts.googleapis.com/css?family=Raleway');
text{
font-size: 4pt;
fill: #ffffff;
text-anchor: middle;
font-family: 'Raleway';
z-index: 2;
}
</style>
<path id="svgPath"/>
<text>
<textpath xlink:href="#svgPath" startOffset="53%" >
<tspan dx="14" dy="9">CLIENTS</tspan>
</textpath>
</text>
</g>
</svg>
I find that SVGs often have poor alignment with small dimensions. Multiplying all values by 10 makes the text in Edge line up properly:
SVG
<svg viewBox="0 400 1000 400">
<g id="svgGroupC" >
<style type="text/css">
#import url('https://fonts.googleapis.com/css?family=Raleway');
text{
font-size: 40pt;
fill: #ffffff;
text-anchor: middle;
font-family: 'Raleway';
z-index: 2;
}
</style>
<path id="svgPath"/>
<text>
<textpath xlink:href="#svgPath" startOffset="53%" >
<tspan dx="140" dy="90">CLIENTS</tspan>
</textpath>
</text>
</g>
</svg>
JS
const rad = Math.PI / 180;
let cx = 500, cy = 1000, R = 500, r = 350, A = 40 , a = 5, o=4;
// o for offset
svgGroupC.setAttributeNS(null, "transform", `rotate(${-90 -(A / 2) - a} ${cx} ${cy})`);
// control points for the quadratic Bézier
let px1 = cx + R * Math.cos(0);
let py1 = cy + R * Math.sin(0);
let px2 = cx + R * Math.cos((2*a + A)*rad);
let py2 = cy + R * Math.sin((2*a + A)*rad);
let px3 = cx + r * Math.cos((2*a + A)*rad);
let py3 = cy + r * Math.sin((2*a + A)*rad);
let px4 = cx + r * Math.cos(0);
let py4 = cy + r * Math.sin(0);
// points used to draw the shape
let x11 = cx + (R-o) * Math.cos(0);
let y11 = cy + (R-o) * Math.sin(0);
let x1 = cx + R * Math.cos(a*rad);
let y1 = cy + R * Math.sin(a*rad);
let x2 = cx + R * Math.cos((a + A)*rad);
let y2 = cy + R * Math.sin((a + A)*rad);
let x21 = cx + (R-o) * Math.cos((2*a + A)*rad);
let y21 = cy + (R-o) * Math.sin((2*a + A)*rad);
let x31 = cx + (r+o) * Math.cos((2*a + A)*rad);
let y31 = cy + (r+o) * Math.sin((2*a + A)*rad);
let x3 = cx + r * Math.cos((a + A)*rad);
let y3 = cy + r * Math.sin((a + A)*rad);
let x4 = cx + r * Math.cos(a*rad);
let y4 = cy + r * Math.sin(a*rad);
let x41 = cx + (r+o) * Math.cos(0);
let y41 = cy + (r+o) * Math.sin(0);
// Rounded corners with quadratic Bézier curves
d = `M${x1},${y1}
A${R},${R},0 0,1 ${x2},${y2}
Q${px2},${py2} ${x21},${y21}
L${x31},${y31}
Q${px3},${py3} ${x3},${y3}
A${r},${r},0 0,0 ${x4},${y4}
Q${px4},${py4} ${x41},${y41}
L${x11},${y11}
Q${px1},${py1} ${x1},${y1}Z`;
svgPath.setAttributeNS(null,"d",d);
(Those rounded corners are now tighter because I didn't get into your curves, but I assume you know which values to update to fix them.)
CodePen for you: https://codepen.io/MSCAU/pen/VqeXxo

Converting SVG to Three.js path

Trying to use the sample SVG parsing code demonstrated at https://threejs.org/examples/#webgl_geometry_extrude_shapes2. It does not properly support the 'a' path command. I've made a few corrections found in https://gist.github.com/IkarosKappler/d3c39db08115085bcb18 and a few of my own referencing https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes, but still am coming up wrong.
Here's a sample with the original SVG shown.
https://codepen.io/matelich/pen/rKzXZV
Since stack wants code here, this is the code that incorrectly parses and interprets A and a paths:
// - elliptical arc
case "A":
case "a":
rx = eatNum();
ry = eatNum();
xar = eatNum() * DEGS_TO_RADS;
laf = eatNum(); //large arc flag
sf = eatNum(); //sweep flag
nx = eatNum();
ny = eatNum();
if (activeCmd == "a") {
// relative
nx += x;
ny += y;
}
if(rx != 0 && ry != 0) {
console.debug(
"Read arc params: rx=" + rx + ", ry=" + ry + ", xar=" + xar + ", laf=" + laf + ", sf=" + sf + ", nx=" + nx + ", ny=" + ny
);
//might need to bring this back if absellipse doesn't work
//if (rx !== ry)
// console.warn("Forcing elliptical arc to be a circular one :(", rx, ry);
// SVG implementation notes does all the math for us! woo!
// http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
// step1, using x1 as x1'
x1 = Math.cos(xar) * (x - nx) / 2 + Math.sin(xar) * (y - ny) / 2;
y1 = -Math.sin(xar) * (x - nx) / 2 + Math.cos(xar) * (y - ny) / 2;
// step 2, using x2 as cx'
console.debug( "TMP x1=" + x1 + ", y1=" + y1 + ", (rx*rx * y1*y1 + ry*ry * x1*x1)=" + (rx * rx * y1 * y1 + ry * ry * x1 * x1) + ", (rx*rx * ry*ry - rx*rx * y1*y1 - ry*ry * x1*x1)=" + (rx * rx * ry * ry - rx * rx * y1 * y1 - ry * ry * x1 * x1));
var norm = Math.sqrt(
Math.abs(
(rx * rx * ry * ry - rx * rx * y1 * y1 - ry * ry * x1 * x1) /
(rx * rx * y1 * y1 + ry * ry * x1 * x1)
)
);
if (laf === sf) norm = -norm;
x2 = norm * rx * y1 / ry;
y2 = norm * -ry * x1 / rx;
console.debug("TMP norm=" + norm + ", x2=" + x2 + ", y2=" + y2);
// step 3
cx = Math.cos(xar) * x2 - Math.sin(xar) * y2 + (x + nx) / 2;
cy = Math.sin(xar) * x2 + Math.cos(xar) * y2 + (y + ny) / 2;
console.debug("TMP cx=" + cx + ", cy=" + cy);
var u = new THREE.Vector2(1, 0),
v = new THREE.Vector2((x1 - x2) / rx, (y1 - y2) / ry);
var startAng = Math.acos(u.dot(v) / u.length() / v.length());
if (u.x * v.y - u.y * v.x < 0) startAng = -startAng;
// we can reuse 'v' from start angle as our 'u' for delta angle
u.x = (-x1 - x2) / rx;
u.y = (-y1 - y2) / ry;
var deltaAng = Math.acos(v.dot(u) / v.length() / u.length());
// This normalization ends up making our curves fail to triangulate...
if (u.x * v.y - u.y * v.x < 0) deltaAng = -deltaAng;
if (!sf && deltaAng > 0) deltaAng -= Math.PI * 2;
if (sf && deltaAng < 0) deltaAng += Math.PI * 2;
console.debug(
"Building arc from values: cx=" + cx + ", cy=" + cy + ", startAng=" + startAng + ", deltaAng=" + deltaAng + ", endAng=" + (startAng + deltaAng) + ", sweepFlag=" + sf );
// path.absarc(cx, cy, rx, startAng, startAng + deltaAng, sf);
path.absellipse(cx, cy, rx, ry, startAng, startAng + deltaAng, sf);
} else {
path.lineTo(nx, ny);
}
Or, perhaps its just my hack of ShapePath?
THREE.ShapePath.prototype.absarc = function( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
this.currentPath.absarc(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise);
};
THREE.ShapePath.prototype.absellipse = function( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise ) {
this.currentPath.absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise );
};
You can still use SVGLoader to load the SVG and retrieve an array of ShapePath objects. You can then use ShapePath.toShapes and use these shapes for creating ExtrudeBufferGeometry's. It's actually the same workflow like in webgl_loader_svg.html, just with ExtrudeBufferGeometry

Geometry Arc Algorithm

I searched all internet and didn't find any pseudo code that solved this problem,
I want to find an Arc between two points, A and B, using 5 arguments:
Start Point
End Point
Radius (Don't know if this is needed)
Angle
Quality
Example:
StartPoint = The green point on the left is the Start Point set on the arguments
EndPoint = The green point on the right is the End Point set on the arguments
Angle = Angle of the Arc(Semi Circle)
Quality = How many red circles to create
I would like to have a pseudo code to solve this problem
Thanks in advance :D
Let start point is P0, end point P1, angle Fi. R is not needed
At first find arc center. Get middle of P0-P1 segment.
M = (P0 + P1) / 2
// M.x = (P0.x + P1.x) / 2 , same for y
And direction vector
D = (P1 - P0) / 2
Get length of D
lenD = Math.Hypot(D.x, D.y) //Vector.Length, sqrt of sum of squares
Get unit vector
uD = D / lenD
Get (left) perpendicular vector
(P.x, P.y) = (-uD.y, ud.x)
Now circle center
if F = Pi then
C.x = M.x
C.y = M.y
else
C.x = M.x + P.x * Len / Tan(Fi/2)
C.y = M.y + P.y * Len / Tan(Fi/2)
Vector from center to start point:
CP0.x = P0.x - C.x
CP0.y = P0.y - C.y
Then you can calculate coordinates of N intermediate points at the arc using rotation of vector CP0 around center point
an = i * Fi / (NSeg + 1);
X[i] = C.x + CP0.x * Cos(an) - CP0.y * Sin(an)
Y[i] = C.y + CP0.x * Sin(an) + CP0.y * Cos(an)
Working Delphi code
procedure ArcByStartEndAngle(P0, P1: TPoint; Angle: Double; NSeg: Integer);
var
i: Integer;
len, dx, dy, mx, my, px, py, t, cx, cy, p0x, p0y, an: Double;
xx, yy: Integer;
begin
mx := (P0.x + P1.x) / 2;
my := (P0.y + P1.y) / 2;
dx := (P1.x - P0.x) / 2;
dy := (P1.y - P0.y) / 2;
len := Math.Hypot(dx, dy);
px := -dy / len;
py := dx / len;
if Angle = Pi then
t := 0
else
t := len / Math.Tan(Angle / 2);
cx := mx + px * t;
cy := my + py * t;
p0x := P0.x - cx;
p0y := P0.y - cy;
for i := 0 to NSeg + 1 do begin
an := i * Angle / (NSeg + 1);
xx := Round(cx + p0x * Cos(an) - p0y * Sin(an));
yy := Round(cy + p0x * Sin(an) + p0y * Cos(an));
Canvas.Ellipse(xx - 3, yy - 3, xx + 4, yy + 4);
end;
end;
Result for (Point(100, 0), Point(0, 100), Pi / 2, 8 (Y-axis down at the picture)

SVG - crescent shape in raphael

I have a circle with a half circle in it which I'm going to use to create a shine effect - what I'd really like to do is make it a crescent shape
Does anybody know how to make the half circle a crescent shape so it looks a bit more 3d?
This is what I have so far
http://jsfiddle.net/Hf79W/3/
var paper = Raphael("holder", 550, 550/1.5);
var rad = Math.PI / 180;
function sector(cx, cy, r, startAngle, endAngle, params) {
var x1 = cx + r * Math.cos(-startAngle * rad),
x2 = cx + r * Math.cos(-endAngle * rad),
y1 = cy + r * Math.sin(-startAngle * rad),
y2 = cy + r * Math.sin(-endAngle * rad);
return paper.path(["M", cx, cy, "L", x1, y1, "A", r, r, 0, +(endAngle - startAngle > 180), 0, x2, y2, "z"]).attr(params);
}
var circle = paper.circle(100, 100, 50).attr({"fill":"brown"});
var fifty = sector(100,100,50,0,180,{"fill":"white","opacity":"0.4"});
I have modified the main function a bit to achieve the same.
function sector(cx, cy, r, startAngle, endAngle, params) {
var x1 = cx + r * Math.cos(-startAngle * rad),
x2 = cx + r * Math.cos(-endAngle * rad),
y1 = cy + r * Math.sin(-startAngle * rad),
y2 = cy + r * Math.sin(-endAngle * rad);
return paper.path(["M", x1, y1,
"A", r, r, 0, +(endAngle - startAngle > 180), 0, x2, y2,
"A", r*1.1, r*1.1, 0, +(endAngle - startAngle > 180), 1, x1, y1,
"z"]).attr(params);
}
In drawing the second curve, reverse the sense of drawing and increase the radius a bit. Hope that helps.
I solved this by drawing the cresecent in inkscape and then saving as SVG

My "perlin" noise effect shader produces either all-white or all-black

I'm trying to code a "perlin" noise shader in NVidia FX Composer. However, no matter how I tweak the noise function, it returns either 100% white or 100% black. I have no clue how to solve this or even where the problem is.
Edit: If you've seen This page, you probably know where I got the code. Figured I'd start with a method I'd already gotten working on a CPU.
Help, please.
float Noise1(int x, int y)
{
int n = x + y * 57;
// int n = x + y * 1376312627;
// n = n * n;
// n = (int)pow(n * pow(2, 13), n);
// return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) + 0x7fffffff) / 1073741824.0);
// return abs( ( (n * (n * n * 15731 + 789221) + 1376312589) + 0x7fffffff) / 2147483647.0);
// return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) + 0x7fffffff) / 2147483647.0);
// return ( n / 2147483647.0);
return ( ((float)n) / 500.0 );
// return n = 2147483647.0;
}
float SmoothNoise_1(int x, int y)
{
float corners = ( Noise1(x-1, y-1) + Noise1(x+1, y-1) + Noise1(x-1, y+1) + Noise1(x+1, y+1) ) / 16.0;
float sides = ( Noise1(x-1, y) + Noise1(x+1, y) + Noise1(x, y-1) + Noise1(x, y+1) ) / 8.0;
float center = Noise1(x, y) / 4.0;
return corners + sides + center;
}
float Cosine_Interpolate(float a, float b, float x)
{
float ft = x * 3.1415927;
float f = (1 - cos(ft)) * 0.5;
return a*(1-f) + b*f;
}
float InterpolatedNoise_1(float x, float y)
{
int integer_X = (int)x;
float fractional_X = x - integer_X;
int integer_Y = (int)y;
float fractional_Y = y - integer_Y;
float v1 = SmoothNoise_1(integer_X, integer_Y);
float v2 = SmoothNoise_1(integer_X + 1, integer_Y);
float v3 = SmoothNoise_1(integer_X, integer_Y + 1);
float v4 = SmoothNoise_1(integer_X + 1, integer_Y + 1);
float i1 = Cosine_Interpolate(v1 , v2 , fractional_X);
float i2 = Cosine_Interpolate(v3 , v4 , fractional_X);
return Cosine_Interpolate(i1 , i2 , fractional_Y);
}
int width = 512;
int height = 512;
float4 PerlinNoise_2D(float2 xy : TEXCOORD0) : COLOR0
{
float4 total = 0;
// int p = persistence;
float p = 1.0;
// int n = Number_Of_Octaves - 1;
int n = 2;
for(int i = 0; i < n; ++i)
{
float frequency = pow(2, i);
float amplitude = pow(p, i);
/* total.a = InterpolatedNoise_1(xy.x * width * frequency, xy.y * height * frequency) * amplitude;
total.r = InterpolatedNoise_1(xy.x * width * frequency, xy.y * height * frequency) * amplitude;
total.g = InterpolatedNoise_1(xy.x * width * frequency, xy.y * height * frequency) * amplitude;
total.b = InterpolatedNoise_1(xy.x * width * frequency, xy.y * height * frequency) * amplitude; */
/* total.a = InterpolatedNoise_1(xy.x * frequency, xy.y * frequency) * amplitude;
total.r = InterpolatedNoise_1(xy.x * frequency, xy.y * frequency) * amplitude;
total.g = InterpolatedNoise_1(xy.x * frequency, xy.y * frequency) * amplitude;
total.b = InterpolatedNoise_1(xy.x * frequency, xy.y * frequency) * amplitude; */
total.a = InterpolatedNoise_1(xy.x * width, xy.y * height);
total.r = InterpolatedNoise_1(xy.x * width, xy.y * height);
total.g = InterpolatedNoise_1(xy.x * width, xy.y * height);
total.b = InterpolatedNoise_1(xy.x * width, xy.y * height);
}
return clamp(total, 0.0, 1.0);
// return (float)(int)(2147483647 + 2147483647 + 2147483647 / 2) / 2147483647.0;
}
technique Perlin
{
pass p0
{
VertexShader = null;
PixelShader = compile ps_3_0 PerlinNoise_2D();
}
}
Thanks.
In short form, because a GeForce 8800GT doesn't do Bitwise and pow() returns a float. So no spinning and wobbling integer bits. (Very technical explanation, that).

Resources