c – Calculate the sum of the interior angles of a polygon [Rev #2]

#include 
#include 
#include 


/* Keep string constants of the questions. */

const char* howManySides =
"How many sides does the shape have? ";

const char* askAnotherShape =
"Would you like to find interior angles for another polygon? (0 or 1) ";

/* Table of polygon names from 3 to 12 sides */
const char* names() = {
    "a triangle",
    "a quadrilateral",
    "a pentagon",
    "a hexagon",
    "a heptagon",
    "an octagon",
    "a nonagon",
    "a decagon",
    "a hendecagon",
    "a dodecagon"
};

enum errorType {noError, errNegSides, errZeroSides, errInsufSides};



static int getSumInteriorAngles(const unsigned int numSides)
{
    return 180 * (numSides - 2);
}



/* Print a specific type of error based on its enumeration.
   */
static void printError(const enum errorType eType)
{
    switch(eType) {
        case errNegSides:
        printf("The number of sides cannot be negative...n");
        break;

        case errZeroSides:
        printf("The number of sides cannot be zero...n");
        break;

        case errInsufSides:
        printf("The shape must have at least 3 sides...n");
        break;
    }
}



/* Takes a number of polygon sides and returns a type of error if the number
   of sides invalid or no error type if the number of sides is valid.
   */
static enum errorType isSidesValid(const int numSides)
{
    if(numSides < 0) return errNegSides;
    else if(numSides == 0) return errZeroSides;
    else if(numSides < 3) return errInsufSides;
    else return noError;
}



static int getUserInput(void)
{
    int userInput;
    bool isValidResponse = false;

    while(!isValidResponse) {
        /* Ask for the number of sides. */
        printf(howManySides);

        /* We're looking for exactly 1 argument, so if there's
           less than that, then something went wrong with the conversion. */
        if(scanf("%i", &userInput) < 1) {
            printf("Not a number...n");
            fflush(stdin);

            /* This check failed, so repeat the question. */
            continue;
        }
        isValidResponse = true;
    }
    return userInput;
}



static int getNumSides(void)
{
    int numSides;

    /* Initialize the checks flag to false and make it true only when
       all checks pass. */
    bool passedAllChecks = false;


    while(!passedAllChecks) {
        numSides = getUserInput();

        /* If the input was a valid number, then we have to check if the
           number of sides makes sense. */
        enum errorType returnError = isSidesValid(numSides);

        if(returnError != noError) {
            /* If the number doesn't make sense for a number of sides,
               then print the specific error and repeat the question. */
            printError(returnError);
            continue;
        }

        /* All checks passed. Exit the loop and return the number of sides. */
        passedAllChecks = true;
    }
    return numSides;
}



static int askAgain(void)
{
    int userResponse = 0;
    bool isValidResponse = false;

    while(!isValidResponse) {
        printf(askAnotherShape);

        /* Weed out non-integers and other weirdness. */
        if(scanf("%i", &userResponse) < 1) {
            printf("Not a valid response...n");
            fflush(stdin);
            continue;
        }

        /* Restrict valid input to 0 or 1. */
        if((userResponse != 0) && (userResponse != 1)) {
            printf("Please choose 0 or 1...n");
            continue;
        }
        isValidResponse = true;
    }
    return userResponse;
}



static void printResult(int numSides)
{
    /* Assume we're dealing with a polygon without a special name,
       in which case, we'll refer to it non-specifically. */
    const char *name = "this polygon";

    /* If we have a name for this polygon, then get it from the table. */
    if(numSides <= 12) {
        name = names(numSides - 3);
    }

    printf("The sum of the interior angles of %s is %in",
            name, getSumInteriorAngles(numSides));
}



int main(void)
{
    do {
        printResult(getNumSides());
    } while(askAgain());

    return 0;
}

This is another review of Calculate the sum of the interior angles of a polygon.

Using the helpful answers from the original post, I've integrated the suggestions in order from start to finish:

  • Add checks to scanf(),
  • Use main(void) instead of main(...),
  • Transfer of char * directly to printf(),
  • Conditions made easier.
  • main() is divided into several functions and subroutines.

I'm looking for a second peer review, as I also added changes that were not suggested in the original post:

  • Use bulleted lists to convey error information.
  • Heavier error checking in the function askAgain(),

Unit – set a 2D polygon collider to the camera size

I am trying to fit a polygonal 2D collider to the size of the camera. I have so far:

Vector3 position = Camera.main.ViewportToWorldPoint(new Vector3(0, 0, 0));
position.z = 0;
transform.position = position;

PolygonCollider2D collider = GetComponent();
Vector2() points = collider.points;
float cameraWidth = Camera.main.scaledPixelWidth / 2;
float cameraHeight = Camera.main.scaledPixelHeight / 2;
points(0) = new Vector2(0, 0);
points(1) = new Vector2(cameraWidth, 0);
points(2) = new Vector2(cameraWidth, cameraHeight);
points(3) = new Vector2(0, cameraHeight);
collider.points = points;

Unfortunately, this only covers most of the camera. For some reason, it is not big enough. Can someone explain that to me? Also why is scaledPixelWidth about twice as big as it should be?

Geometry – Determinant of Gauss (area of ​​a polygon of n vertices) how to implement

A very useful method for determining the area of ​​an irregular polygon is the Gaussian determinant.

The point is to draw the figure on a Cartesian plane and set the coordinates of each corner of the polygon.

Drawing of the selection and enumeration of the irregular pentagon points for the Gaussian determinant.

Each of them is randomly selected and the pairs are put into the following formula. The polygon must be counter-clockwise, bearing in mind that the first coordinate pair corresponds to the selected vertex, and after all vertices have been driven counterclockwise, the last pair must be the initial torque

https://www.universoformulas.com/imagenes/formulas/matematicas/geometria/area-poligono-irregular-determinante-gauss.jpg

The vertices of the polygon are: (x1, y1), (x2, y2), …, (xN, yN). The formula is as follows:

(FORMULA))

Formula of the irregular polygon surface with the Gaussian determinant

If you solve it with the known method, you have quickly found the area of ​​the irregular polygon.

This method applies to all polygons with any number of sides, both concave and convex polygons.

My question is how can I create a script that asks me
a) number of vertices
b) Ask me to enter the n points between these n vertices
This is
$$ (x_1, y_1) $$
$$ (x_2, y_2) $$
……………………
$$ (x_n, y_n) $$
c) Can calculate the area with the given formula

n = input ("number of vertices", n)
(Input (x1, y1), (x2, y2) ….. (xn, yn)) ?? ??
A = (1/2) det (x1, y1), (x2, y2) ….. (xn, yn) ???

can you help me ? I searched the forum, but I can not find an example that I can adapt

Arithmetic Geometry – Eigenform families mean a lower bound of the Newton polygon of $ U_p $

To let $ p $ be arbitrary and $ k in Z $, and $ f $ be a classic eigenform of the level $ Np $ and weight $ k $, then that's known $ f $ lie in one $ p $-adische family of eigen forms.

So the question is why the above result implies that there should be a lower bound on the Newtonian polygon $ U_p $ interact with the space of modular levels $ Np $ and weight $ k $and this barrier should be uniform in $ k $,

Thank you so much!

tilemap – Java creates a polygon for each island in the tile game

I'm doing a 2D top-down game that is randomly generated in each new world.

What I want to do is create a polygon (or some other suitable shape I do not know) for any landmass that is not intersected by land, basically any undivided landmass / island. I want to do this where my player should appear. The world wants me to have a better chance of spawning on the world's largest land mass than on a tiny island with multiple tiles. All I need to know is how I would create a shape system to detect different islands.

The reason why I propose a polygon is that the player would spawn in that area by accident, so it must be land accurate. It can not start by spawning in water nearby.

If a polygon is outdated for this idea and another system is better, let me know.

Select a polygon within an array of complex polygons

I have an array of polygons that are arrays of points. There are no gaps and none of them overlap like a Voronoi diagram.

Unlike a Voronoi diagram, I can not just find the nearest center of gravity to pick a polygon. This returns the correct polygon most of the time, but sometimes the point is within an adjacent polygon.

The developer tools in my Chrome browser seem to be able to do this with the selection tool, but I have no idea how it works.

Vector – motion point (as line) – polygon collision detection

I have reached a good point with my engine, with static / instant collision detection and recalls in collisions.
With immediate collision detection I mean:

  • Object A moves from x1y1 to x2y2
  • Check if A (at x2y2) collides with B

Ideal for slow-moving objects that need to be destroyed in a collision. Terrible for "Stop on Touch", "Bounce" or "Slide" interactions.

So I'm expanding my engine to support collisions in motion, and now only support points as moving objects. The collision is the collision from line to polygon, where the starting point of the line is the starting coordinates of the point object and the end point of the line is the point where the object is after the movement, if there is no collision.

The collision should not only return a true / false value, but also information such as the distance to the collision, the unit normal vector of the surface with which it collides, and the collision point. This information should enable me to implement the 3 mentioned interactions. (For the tags, I'm not sure if this is a collision detection or prediction.)

Although I should have done most things right, but the "jumping" calculations on inclined lines do not get the angle right. I'm really bad at math and just used a few formulas from stackexchange.


Here is the code for the collision detection and the returned information. After the next horizontal separator, the code stands for the calculation of the "bounce" line.

Collision between two lines:

Collision_info Line::collide(Line& l)
    {
    sf::Vector2f p0 = vertices(va).position;
    sf::Vector2f p1 = vertices(vb).position;
    sf::Vector2f p2 = l.vertices(va).position;
    sf::Vector2f p3 = l.vertices(vb).position;

    sf::Vector2f s1, s2;
    s1.x = p1.x - p0.x; 
    s1.y = p1.y - p0.y; 
    s2.x = p3.x - p2.x; 
    s2.y = p3.y - p2.y; 

    float s, t; 

    s = (-s1.y * (p0.x - p2.x) + s1.x * (p0.y - p2.y)) / (-s2.x * s1.y + s1.x * s2.y); 
    t = (s2.x * (p0.y - p2.y) - s2.y * (p0.x - p2.x)) / (-s2.x * s1.y + s1.x * s2.y);

    if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
        { // Collision detected 
        sf::Vector2f c = p0 + (t * s1);
        return { c, l.normal, linelength(p0, c)};
        }
    return Collision_info(); // No collision 
    }

Collision between line and polygon:

    Collision_info Line::collide(Polygon& p)
    {
    bool collided = false;
    Collision_info ret;

    for (size_t i = 0; i < p.lines.size(); i++)
        {
        Collision_info tmp = collide(p.lines(i));

        if (tmp)
            {
            if (collided) { if (tmp.distance < ret.distance) { ret = tmp; } }
            else { ret = tmp; collided = true; }
            }
        }
    if (collided) { return ret; }
    return Collision_info();
    }

Collision information:

    class Collision_info
    {
    private:
        bool collision;
    public:
        operator bool() const; //returns collision
        sf::Vector2f collider_normal;
        sf::Vector2f collision_point;
        float distance;
        Collision_info(); //sets collision to false
        Collision_info(sf::Vector2f collision_point, sf::Vector2f collider_normal, float distance);
    };

collision_line.move_p1(collide.collision_point);
        //collision_line.move_p2(collide.collision_point + (collide.collider_normal * (line.length() - collide.distance)));

        //https://gamedev.stackexchange.com/questions/23672/determine-resulting-angle-of-wall-collision
        sf::Vector2f full_line_reflection = -(2.f * (collide.collider_normal * line.unit) * collide.collider_normal - line.unit);
        sf::Vector2f unit_reflection = full_line_reflection / line.length();
        sf::Vector2f remaining_reflection = unit_reflection * (line.length() - collide.distance);
        collision_line.move_p2(collide.collision_point + remaining_reflection);

It feels alright if the polygon has axis-aligned lines, but the angle is completely wrong, if not.
GitHub link for a short little project to test all this math (sfml for graphics):
collisions

Algorithm – Calculation of the outer polygon

I need to compute an outer polygon from a self-intersecting polygon. I've found that Mathematica has recently implemented the following feature that could solve this problem. Does anyone know how it could be implemented?

https://reference.wolfram.com/language/ref/OuterPolygon.html

Any book or article dealing with this topic would also be helpful.

To illustrate my problem, I have a self-cutting polygon (blue) and want to get the outer polygon (red):

Auto-cutting polygon and outer polygon

If it helps, this polygon is created by "displacing" * a previous polygon that did not overlap itself:

Polygon-term development

Could there be a way to increase the polygon that considers self-overlapping?

Thanks a lot!

* not technically balancing, as only some parts of the polygon move in the normal direction.

Rotation – The polygon does not return in a collision between edge and ground

I'm doing a (basic) physics engine in Python, where a polygon should bounce off the ground ( $ y = 0 $).

When a vertex hits the ground, I apply the (linear) impulse $$ overrightarrow {P} left (0, ; frac {- (1+ epsilon) overrightarrow {n} cdot overrightarrow {v}} { frac {1} {m} + overrightarrow { n} cdot left (I ^ {- 1} ( overrightarrow {r} times overrightarrow {n}) right) times overrightarrow {r}} right) $$
(from where $ overrightarrow {n} (0,1) $ is the normal on the ground, $ overrightarrow {r} $ is a vector from the center of mass to the point of contact and $ epsilon in (0,1) $ is a constant of elasticity)

In my code:

class POLYGON:
    def bounce(self):
        #Checks whether the polygon is under the ground and rebounces it if necessary

        #Finds the nodes with y <= 0
        low_nodes = ()
        for node in self.nodes:
            if node(1) < 0:
                low_nodes.append(node)

        if len(low_nodes) > 0:
            #Translates the polygon above the ground
            lowest_node = low_nodes(np.argmax(low_nodes,axis=0)(1))
            self.translate((0, (1+restituence_constant)*(-lowest_node(1))))

            #Makes a list of the (linear) velocities of all low nodes
            speed = ()
            for node in low_nodes:
                speed.append(self.getLinearVelocity(node))

            for (i,node) in enumerate(low_nodes):
                r = node - self.pos

                ut = -(1+restituence_constant) * speed(i)(1)
                lt = 1/self.mass + 1/self.rot_inertia * cross(r(0), r)(1)
                j = ut/lt
                impulse = (0, j/len(low_nodes))
                self.applyLinearImpulse(impulse, node)

As a side note: I create the list of linear velocities of the nodes in advance, since these are influenced by applying impulses.
It is also necessary to divide the length of the size of the pulse by the number of "low nodes".

If only one vertex hits the ground, everything works fine.
But in a collision between edge and ground I find the impulses too small.

If I drop the square with knots $ ( pm100, pm100) $it does not even jump!
But if I drop the polygon with knots $ ( pm10, -100) $ and $ ( pm100,100) $ On the "small side" the impulse is big enough to bounce back.
Therefore, I come to the conclusion that the problem is caused by the vertices being too far from the center of mass $ x $-Direction.

My question is: how can I fix this?
My first idea was to replace the impulses at the vertices with a linear impulse in the middle of the edge. However, this seems a bit "hacky" and mathematically incorrect.
Could you please help me?

Rotation – polygon jumps off the ground

NOTE: You may want to read the calculations here (on the Physics Stack Exchange website) because I can insert LaTeX equations inline there.

I'm doing a physics simulator right now, but I'm having some trouble bouncing a polygon off the ground.

What I'm trying to do:
When the polygon touches the ground, I want to apply a linear pulse Enter image description here at the point of contact, so that the energy E & # 39; of the polygon after the rebound is a certain elasticity constant (!) Enter image description here (2)) (2) times the energy E of the polygon before the rebound.
$$ E & # 39; = epsilon E $$

My calculations:
Imagine a Cartesian coordinate system in which the ground is y = 0. Then (! (Insert image description here) (3)) (3) where we expect p to be positive.
m, I, $ overrightarrow {v} $, $ overrightarrow { omega} $ and $ overrightarrow {r} $ are given, and we want to calculate the size p of the impulse $ overrightarrow {P} $.
$$ frac {1} {2} m cdot overrightarrow {v & # 39;} ^ 2 + frac {1} {2} cdot overrightarrow { omega & # 39;} ^ 2 = E & # 39; = epsilon E = epsilon cdot left ( frac {1} {2} m cdot overrightarrow {v} ^ 2 + frac {1} {2} I cdot overrightarrow { omega } ^ 2 right) $$
$$ Leftrightarrow m cdot left ( overrightarrow {v} + frac { overrightarrow {P}} {m} right) ^ 2 + I cdot left ( overrightarrow { omega} + frac { overrightarrow {r} times overrightarrow {P}} {I} right) ^ 2 = epsilon cdot left (m cdot overrightarrow {v} ^ 2 + I cdot overrightarrow { omega} ^ 2 right) $$
$$ Leftrightarrow m cdot overrightarrow {v} ^ 2 + 2 overrightarrow {v} cdot overrightarrow {P} + frac { overrightarrow {P} ^ 2} {m} + I cdot overrightarrow { omega} ^ 2 + 2 overrightarrow { omega} cdot ( overrightarrow {r} times overrightarrow {P}) + frac {( overrightarrow {r} times overrightarrow {P}) ^ 2} {I} = epsilon cdot left (m cdot overrightarrow {v} ^ 2 + I cdot overrightarrow { omega} ^ 2 right) $$

And now we can use the fact that $ overrightarrow {P} (0, p) $, to calculate the point and cross products:
$$ 0 = (1 epsilon) cdot left (m cdot overrightarrow {v} ^ 2 + I cdot overrightarrow { omega} ^ 2 right) + 2p cdot v (1) + frac {p ^ 2} {m} + 2p cdot r (0) cdot | overrightarrow { omega} | + frac {(p cdot r (0)) ^ 2} {I} $$
$$ Leftrightarrow left ( frac {1} {m} + frac {r (0) ^ 2} {I} right) cdot p ^ 2 + left (2v (1) + 2r (0) cdot | overrightarrow { omega} | right) cdot p + (1- epsilon) cdot left (m cdot overrightarrow {v} ^ 2 + I cdot overrightarrow { omega} ^ 2 right) $$

This is a quadratic equation in $ p $.
If we hire:

  • $$ A = frac {1} {m} + frac {r (0) ^ 2} {I} $$
  • $$ B = 2v (1) + 2r (0) cdot | overrightarrow { omega} | $$
  • $$ C = (1 epsilon) cdot left (m cdot overrightarrow {v} ^ 2 + I cdot overrightarrow { omega} ^ 2 right) $$
  • We can calculate the determinant $$ D = B ^ 2-4AC $$,

    Now it is clear that $$ p = frac {-B + sqrt {D}} {2A} $$

    When I do this in a simulation, it looks very natural.
    However, there are always problems when D <0.
    I've tried to solve this problem in countless ways (*)but it never worked out well.

    Can someone check if my method and calculations are correct?
    And if not, how can I model this collision instead?

    Here's a snippet of my code (in Python):

    class POLYGON:
        def bounce(self):
            #Checks whether the polygon touches the ground and makes it rebound if necessary
    
            low_nodes = ()    #makes a list of the nodes with y<0
            for node in self.nodes:
                if node(1) <= 0:
                    low_nodes.append(node)
    
            if len(low_nodes) >= 1:
                speed = self.speed
                self.translate((0, -2*lowest_node(1))    #lifts the lowest node above the ground
    
                for node in low_nodes:
                    r = node - self.pos    #calculates r
    
                    A = 1/self.mass + r(0)**2/self.rot_inertia
                    B = 2*self.speed(1) + 2*self.rot_speed*r(0)
                    C = (1-restituence_constant) * (self.mass*np.linalg.norm(self.speed)**2 + self.rot_inertia*self.rot_speed**2)
                    D = B**2 - 4*A*C
    
                    if D<0:
                        impulse = (0, -B/(2*A)
                    else:
                        impulse = (0, (-B-np.sqrt(D)) /(2*A) /len(low_nodes))
                    self.applyLinearImpulse(impulse, node)
    

    (*)
    For example:
    using the absolute value of D
    Consider $ p $ as a complex number and apply the impulse $ (Im (p), Re (p)) $
    Set $ ​​p = frac {-B} {2A} $ if $ D <0 $
    ...