Jump to content

Recommended Posts

Posted

N2VDrax.png?1

Is there a way to provide coordinates such that the arc length between two lines, red and purple for instance, can be said to remain at a fixed value for where they intersect both circles?

Posted

N2VDrax.png?1

Is there a way to provide coordinates such that the arc length between two lines, red and purple for instance, can be said to remain at a fixed value for where they intersect both circles?

That's kind of regular polar coordinates - you just need to ignore the fact that theta is in degrees or radians

Posted

I have one too. How do I find coordinates for points on the circle dividing a circle into areas representative of their size in %? I know when doing a normal piechart but I want to divide like this.

 

VmIFkE6.png?1

Posted (edited)

I have one too. How do I find coordinates for points on the circle dividing a circle into areas representative of their size in %? I know when doing a normal piechart but I want to divide like this.

 

VmIFkE6.png?1

 

If you have center at cx,cy

which typically is

radius=diameter/2

cx=radius

cy=radius

 

point on circle will be given by

x=cx+sin(angle*2*PI/360)*radius

y=cy+cos(angle*2*PI/360)*radius

with angle in degrees between 0...360

 

Please notice that you have right triangle (with lines a,b and the longest c) with coords:

cx,cy

cx+sin(angle)*radius,cy+cos(angle)*radius

cx,cy+cos(angle)*radius

a/c=sin(angle)

b/c=cos(angle)

c^2=a^2+b^2

 

Area of circle is PI*radius^2

So, area A in your image has PI*radius^2 * percentage of A/ 100 pixels

area B, has PI*radius^2 * percentage of B/100 pixels

 

You can make for-loop going from i=0 to diameter, convert it to b=i-cy, and convert it to angle (cos(angle)=b/c)

calculating left circle pixel (cx-sin(angle)*radius), right circle pixel (cx+sin(angle)*radius),

(c is known, and b is known, so you can use Pythagoras formula to learn a, instead)

difference between them will be quantity of pixels (area of single row).

And sum them together.

After that variable exceeds area of A (given above formula),

then you draw horizontal line.

And subtract from variable area of A (or clear variable, but more precise will be subtract).

And then you continue loop.

 

That would be probably not bad algorithm, even though it's going row by row, pixel by pixel. It's called scanline algorithm. But you would like to fill areas with different colors, right? Then difference between drawing line inside of circle, is what color is used: if it's separation between one area A and B etc, choose black color, otherwise pick color from array of colors for regions (Index increased after drawing separation line between them)

Edited by Sensei
Posted

Thanks I'll test that out tomorrow. What I found was the formula

 

Area of Segment = ½ × ( (θ × π/180) - sin θ) × r2

 

I could also see from looking at the formula that it

(A) Won't work over 50% of the area without some tweaking

(B) I have to find θ which is going to be a pain because I need an exact value which wolfram gives multiple values for http://www.wolframalpha.com/input/?i=200%3D%28%CE%B8+%C3%97+%CF%80%2F180%29+-+sin+%CE%B8

 

If I work out how to find θ I can find the height of the triangle the segment makes with the circle centre. Given h I can draw the line at h.

Posted (edited)

If I work out how to find θ I can find the height of the triangle the segment makes with the circle centre.

 

Like I showed earlier, it's not needed at all to search for angle.

sin(angle)=a/c

sin(angle)*c=a

But actually, you are interested to know a, not angle, not sinus of angle.

and you can simply do Pythagoras formula to find a (b is from for-loop counter, c is radius of circle).

2*abs(a) = area of single row in pixels.

Sum rows area together in loop, unit it exceeds threshold area of region, and you know when to draw separation line.

Edited by Sensei
Posted

You could do it just based on pixels

 

Get total pixels in a solid circle. Use that to find your individual segment pixel counts. Then itterate on through the pixels in the solid circle creating the segments as you go.

Posted

OK - to do this mathematically takes a bit of effort.

 

1. Inscribe a diameter O (ie longest chord) parallel to your other chords A,B,C,D.

2. The radius of the circle is r.

3. The perpendicular distance from O to A is a, O to B is b etc

 

The size of Area A and D is fairly easy

[latex]

Area_A=r^2 \cdot \cos^{-1}\left ( \frac{a}{r}\right )- a \cdot \sqrt{r^2-a^2}

[/latex]

 

And Similarly for D - just replace a with d

 

B and C the work is slightly more involved.

 

For B you need to work out the area of A+B ie replace a in above equation with a+b, and then deduct the area of A.

For C which includes the diameter you need to take area of Circle and deduct every thing else ie Pi.r^2 - (Areas of a + b + d)

Posted (edited)

OK - to do this mathematically takes a bit of effort.

imatfaal, actually he wants to know x0,y and x1,y, coordinates of separating lines, between regions. To be able to draw there lines.

Edited by Sensei
Posted (edited)
You could do it just based on pixels

 

Get total pixels in a solid circle. Use that to find your individual segment pixel counts. Then itterate on through the pixels in the solid circle creating the segments as you go.

 

Well you could but I am using svg or scalable vector graphics which doesn't use pixels.

 

450px-Bitmap_VS_SVG.svg.png

Edited by fiveworlds
Posted

When you guys have fully conquered 2D how about tackling 3D?

 

Same problem but on a sphere not a circle.

 

If you paint parallel stripes on a football so that in fiveworlds' post#4 each of A, B C etc represent a painted stripe on the football.

 

How do you relate the area of paint to width / height of the stripes ?

Posted

When you guys have fully conquered 2D how about tackling 3D?

 

Same problem but on a sphere not a circle.

 

If you paint parallel stripes on a football so that in fiveworlds' post#4 each of A, B C etc represent a painted stripe on the football.

 

How do you relate the area of paint to width / height of the stripes ?

 

Surface Area? Tricky - needs some thinking time

LaTex fest to follow

 

the area of a surface of rotation is

[latex]

S_x= 2 \pi \cdot \int^b_a y \cdot \sqrt{1+\left ( \frac{dy}{dx}\right )^2} dx

[/latex]

 

If we take the y-axis as the axis of rotation then we can say that

[latex]R^2=x^2+z^2

[/latex]

 

[latex]x= \left ( R^2-z^2\right )^{1/2}[/latex]

 

[latex]

\frac{dx}{dz}=\frac{dx}{du} \cdot \frac{du}{dz}= 1/2\left ( R^2-z^2\right )^{-1/2} \cdot (-2z)=-z\left ( R^2-z^2\right )^{-1/2}=\frac{-z}{\sqrt{R^2-z^2}}

[/latex]

 

[latex]\left (\frac{dx}{dz} \right )^2=\frac{z^2}{{R^2-z^2}}[/latex]

 

[latex]S= 2 \pi \cdot \int^b_a \left ( R^2-z^2\right )^{1/2} \cdot \sqrt{1+\frac{z^2}{{R^2-z^2}}} \cdot dz[/latex]

 

If you then integrate (and my latex has run out) substituting in for a and b the pythagorean result of [latex]a = sqrt(R^2- r_a^2) [/latex] ie the r_a is the radius at height a and similarly for b

 

then it all cancels out to give

 

[latex]S= 2 \pi R (b-a) = 2 \pi R h [/latex] where h is the height of the band. Which is a ridiculously simple result - if you set h to R (ie hemisphere) then you get the right answer of 2piR^2 which is nice.

 

The Area only depends of the height of the band (and the radius obviously) - not on its position on the sphere

Posted

The Ancient Greeks didn't do much 3D geometry but this particular result was due to Archimedes, though his approach and proof was rather different.

 

The area is the same on an equivalent cylinder.

 

Pity you didn't put that working into a spoiler, but well done for working it out.

Posted

[latex]2 \pi \left [ z*\sqrt{(r - z)*(r +z})*\sqrt{\frac{r^2}{(r^2 - z^2)}} \right ][/latex]

 

from z = Sqrt(R^2-b^2) to z = Sqrt(R^2-a^2)

 

if we sub in the first we get (sorry I have slipped to lower case r)

 

[latex]\sqrt{\frac{r^2}{a^2}} \sqrt{(r^2-a^2)} \sqrt{((r-\sqrt(r^2-a^2)) (\sqrt({r^2-a^2)+r)})}[/latex]

 

The third root collapses to sqrt(a^2) which cancels with the bottom of the first root giving

 

[latex]r \cdot \sqrt{r^2-a^2}[/latex]

 

so the difference is

 

[latex]r \cdot \sqrt{r^2-b^2}-r \cdot \sqrt{r^2-a^2}[/latex]

 

so we get

[latex]

 

S = 2 \pi R (\sqrt{r^2-b^2}- \sqrt{r^2-a^2}

[/latex]

 

[latex]

 

S = 2 \pi R h

[/latex]

Posted (edited)

I was able to get it working. The coding for the colors was off creating that static effect instead of solid colors. Actually thought it was interesting if entirely unanticipated. Reminded me of watching static on the TV back in the day.

 

Uses the pixel method. I'm not sure if you could apply it mathematically to an ideal circle. Food for thought. At any rate telling your teacher you can construct segments if she gives you enough little squares is probably not going to fly.

aYV00H3.png

 

https://jsfiddle.net/v2co4cns/

 

 

 

<!DOCTYPE html>

<html>

<head>
    <title></title>
</head>

<body>
    <canvas height="400" id="canvas" width="400"></canvas>
    <script>
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        var radius = canvas.height / 2;
        ctx.translate(radius, radius);
        radius = radius * 0.90;
        drawCirc();

        function drawCirc() {
            ctx.arc(0, 0, radius, 0, 2 * Math.PI);
            ctx.fillStyle = "White";
            ctx.fill();
        }


        var imgData = ctx.getImageData(0, 0, 400, 400);

        //count colored pixels
        var x = 0;
        for (var i = 0; i < imgData.data.length; i++) {
            if (imgData.data[i] != 0) {
                x++;
            }
        }


        var percents = [25, 25, 25, 25];


        for (var a = 0; a = percents.length; a++) {

            var sumPer = 0;
            for (var i = 0; i < percents.length; i++) {

                sumPer += percents[i];
            }
            percents.shift();

            var segArea = x * sumPer / 100;
            var alpha = 3;

            var color = [Math.floor(Math.random() * 255), Math.floor(Math.random() * 255), Math.floor(Math.random() * 255)];

            var b = 0;
            for (var i = 0; i < segArea; i++) {


                if (imgData.data[i] == 0) {
                    segArea++;
                }


                if (imgData.data[i] != 0 && i != alpha) {

                    imgData.data[i] = color[b];
                    b++;
                    if (b == 3) {
                        b = 0;
                    }
                }

                if (i == alpha) {
                    alpha += 4;
                }

            }

            ctx.putImageData(imgData, 0, 0);
        }
    </script>
</body>

</html>

 

 

Edited by Endy0816
Posted (edited)

endy, +1 for tenacity

TY. Thought it was a fun concept fiveworlds came up with and that it might be cool/useful in terms of converting irregular shapes into charts(logos, maps).

Edited by Endy0816
Posted
TY. Thought it was a fun concept fiveworlds came up with and that it might be cool/useful in terms of converting irregular shapes into charts(logos, maps).

 

It was a very cool solution to it too. This is how far I am at the moment.

 

pi/100 * percentage * 360 = angle;

cos(angle)*radius = y;

sin(angle)*radius = x;

points of first line = (x,y) (-x,y);

 

It is every other line i need to work out now.

Posted

It was a very cool solution to it too. This is how far I am at the moment.

 

 

It is every other line i need to work out now.

 

Thank you.

 

Maybe try clipping in conjunction with the y co-ords?

 

something like:

<svg height="100" width="100">
  
    <defs>
        <clipPath id="cirClip">
            <circle cx="50" cy="50" r="30"/>
        </clipPath>
    </defs>
    
    <rect x="0" y="20" width="109" height="100" fill="blue"
          clip-path="url(#cirClip)"/>
    <rect x="0" y="40" width="100" height="100" fill="red"
          clip-path="url(#cirClip)"/>
    
</svg>

Might be other, better ways out there though.

Posted (edited)
Might be other, better ways out there though.

 

 

I explained what I am doing badly here. I am generating an array of values for area from 0 to pi and the angle associated with it. Using the array (lookup table) I can find the angle to a certain precision. Since it is an svg online I don't need it to be 100% correct so I just get the closest value I generated and use that for my angle.

<script>
function toFixed(x) {
  if (Math.abs(x) < 1.0) {
    var e = parseInt(x.toString().split('e-')[1]);
    if (e) {
        x *= Math.pow(10,e-1);
        x = '0.' + (new Array(e)).join('0') + x.toString().substring(2);
    }
  } else {
    var e = parseInt(x.toString().split('+')[1]);
    if (e > 20) {
        e -= 20;
        x /= Math.pow(10,e);
        x += (new Array(e+1)).join('0');
    }
  }
  return x;
}

function closest (num, arr) {
    var curr = arr[0];
    var diff = Math.abs (num - curr);
    for (var val = 0; val < arr.length; val++) {
        var newdiff = Math.abs (num - arr[val]);
        if (newdiff < diff) {
            diff = newdiff;
            curr = val;
            
        }
    }
    return curr;
}

var lookuparea= [];
var angles = [];
for(i = 1; i < 5001; i+=1){
    angle= (i*360)/10000;
    percentage=i/100;
    radseg = angle * (Math.PI / 180);
    r=1;
    area=((1/2)*r*r)*(radseg-Math.sin(radseg));
    document.write("percentage: "+percentage+" area: "+toFixed(area)+" angle: "+angle+"</br>");
    lookuparea.push(toFixed(area));
    angles.push(angle);
}

startx=0;
starty=10;
percentages=[25,25,25];
lastpercentage=0;
for (i = 0; i < percentages.length; i += 1) {
    percentage=percentages[i]+lastpercentage;    
    if(percentage < 50){
        area = Math.PI*percentage/100;
        test = closest (area, lookuparea)
        document.write(test+"</br></br>");
        document.write(angles[test]+"</br></br>");
        radseg = angles[test] * (Math.PI / 180);
        y=Math.cos(radseg)-starty;
        x=Math.sin(radseg)+startx;
        document.write("x: "+x+" y: "+y+"</br>x: "+-x+" y: "+y+"</br>");
        lastpercentage=percentage;
    }
    
    else if(percentage==50){
        x=0;
        y=0;
        document.write("x: "+x+" y: "+y+"</br>x: "+-x+" y: "+y+"</br>");
        lastpercentage=percentage;    
    }
    
    else if(percentage < 100){
        lastpercentage=percentage;
        percentage=100-percentage;
        area = Math.PI*percentage/100;
        test = closest (area, lookuparea)
        document.write(test+"</br></br>");
        document.write(angles[test]+"</br></br>");
        radseg = angles[test] * (Math.PI / 180);
        y=(Math.cos(radseg)*-1)+starty;
        x=Math.sin(radseg);
        //points
        document.write("x: "+x+" y: "+y+"</br>x: "+-x+" y: "+y+"</br>");    
    }    
}

</script>

So for this I know trig doesn't work for 180 degrees because there is no right angled triangle. Also greater than 50% i need to change things around.

Edited by fiveworlds
Posted (edited)

Think I'm going to have to see it used in drawing to really understand it. Looks decently complex though. :)

Edited by Endy0816

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.