{"id":21936372,"url":"https://github.com/tjstretchalot/sharpmath2","last_synced_at":"2025-04-22T12:03:40.853Z","repository":{"id":148118359,"uuid":"91968766","full_name":"Tjstretchalot/SharpMath2","owner":"Tjstretchalot","description":"2D math / geometry collision library for C#, compatable with monogame.","archived":false,"fork":false,"pushed_at":"2021-03-30T19:11:00.000Z","size":153,"stargazers_count":53,"open_issues_count":1,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-29T14:51:14.474Z","etag":null,"topics":["2d","collision","csharp","geometry","library","math","math2d","minimumtranslationvector","mtv","polygon","sat"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Tjstretchalot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-21T15:48:24.000Z","updated_at":"2024-09-20T01:02:11.000Z","dependencies_parsed_at":"2023-05-19T04:45:37.277Z","dependency_job_id":null,"html_url":"https://github.com/Tjstretchalot/SharpMath2","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tjstretchalot%2FSharpMath2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tjstretchalot%2FSharpMath2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tjstretchalot%2FSharpMath2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tjstretchalot%2FSharpMath2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Tjstretchalot","download_url":"https://codeload.github.com/Tjstretchalot/SharpMath2/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250237831,"owners_count":21397400,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["2d","collision","csharp","geometry","library","math","math2d","minimumtranslationvector","mtv","polygon","sat"],"created_at":"2024-11-29T01:14:17.018Z","updated_at":"2025-04-22T12:03:40.840Z","avatar_url":"https://github.com/Tjstretchalot.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SharpMath2\n\n![banner](imgs/banner.png)\n\nThis is a C# math library. It is built as the bare minimum to get up and running with a 2D game in C#. It\nis compatible with or without monogame. To compile with monogame, use the compiler directive \"NOT_MONOGAME\".\nThis will provide versions of Microsoft.XNA.Framework.Vector2 and Microsoft.XNA.Framework.Point that do not\nrequire any external libraries (with reduced functionality).\n\n## Examples\n\n### Import tags\n\n```cs\nusing SharpMath2;\nusing Microsoft.XNA.Framework;\n```\n\n### Polygon construction\n\n```cs\nvar triangle1 = new Polygon2(new[] { new Vector2(0, 0), new Vector2(1, 1), new Vector2(2, 0) });\nvar triangle2 = ShapeUtils.CreateCircle(1, segments=3); // this is not the same triangle as triangle1, this will be equilateral\nvar octogon = ShapeUtils.CreateCircle(1, segments=8);\n```\n\n### Polygon intersection\n\n```cs\n// Check intersection of two entities, both of which have the same triangle bounds but one is\n// rotated at rotation1 and located at position1, where the other is rotated at rotation2 and \n// located at position2\n\nvar triangle = new Polygon2(new[] { new Vector2(0, 0), new Vector2(1, 1), new Vector2(2, 0) });\n\n// Rotation2 caches Math.Sin and Math.Cos of the given angle, so if you know you are going to reuse\n// rotations often (like 0) they should be cached (Rotation2.Zero is provided)\nvar rotation1 = Rotation2.Zero;\nvar rotation2 = Rotation2.Zero; // new Rotation2((float)(Math.PI / 6)) would be 30degrees\nvar position1 = new Vector2(5, 3);\nvar position2 = new Vector2(6, 3);\n\n// Determine if the polygons overlap or touch: \nPolygon2.Intersects(triangle, triangle, position1, position2, rotation1, rotation2, false); // True\n\n// Determine if the polygons overlap\nPolygon2.Intersects(triangle, triangle, position1, position2, rotation1, rotation2, true); // False\n\n// Note that in the special case of no rotation (rotation1 == rotation2 == Rotation2.Zero) we can\n// use the shorter function definition by omitting the rotation parameters\nPolygon2.Intersects(triangle, triangle, position1, position2, true); // False\n```\n\n### Polygon collision detection + handling\n\n```cs\n// Suppose we have two entities, entity1 and entity2, both of which use the polygon \"triangle\" and are at position1, rotation1 and \n// position2, rotation2 respectively. If we are updating entity1 and we want to detect and handle collision with entity2 we would\n// do:\n\n// note we do not check for intersection first - while intersection is faster to check than intersection + MTV, it is not \n// faster to check intersection then intersection + MTV if you will need the MTV.\n\n// Note strict is not an option for MTV - if two triangles are touching but not overlapping then\n// it doesn't make sense to try and get an MTV\nTuple\u003cVector2, float\u003e mtv = Polygon2.IntersectMTV(triangle, triangle, position1, position2, rotation1, rotation2);\nif(mtv != null)\n{\n  // The two entites are colliding.\n  position1 += mtv.Item1 * mtv.Item2;\n  \n  // Polygon2.Intersects(triangle, triangle, position1, position2, rotation1, rotation2, true); -\u003e False\n  // Polygon2.Intersects(triangle, triangle, position1, position2, rotation1, rotation2, false); -\u003e True\n}\n```\n\n### Polygon -\u003e AABB collision\n\nIt is very common to need to check polygons against unrotated rectangles in square-grid systems. In this case \nthere are functions in Shape2 that provide these comparisons that is slightly faster than complete polygon to \npolygon collision that you would get from `ShapeUtils.CreateRectangle(width, height)` rather than `new Rect(minx, miny, maxx, maxy)`\n\n```cs\nvar triangle = ShapeUtils.CreateCircle(1, segments=3);\nvar tile = new Rect2(0, 0, 1, 1); // minX, minY, maxX, maxY NOT x, y, w, h.\n\nvar triPos = new Vector2(3.3, 4.1);\nvar triRot = new Rotation2((float)(Math.PI / 6));\n\nVector2 tmp = Vector2.Zero; // Vector2 is a struct so this is safe\nint xMin = (int)triPos.x;\nint xMax = (int)Math.Ceiling(triPos.x + triangle.LongestAxisLength);\nint yMin = (int)triPos.y;\nint yMax = (int)Math.Ceiling(triPos.y + triangle.LongestAxisLength);\nfor(int y = yMin; y \u003c= yMax; y++)\n{\n  tmp.Y = y;\n  for(int x = xMin; x \u003c= xMax; x++) \n  {\n     tmp.X = x;\n     var intersectsTileAtXY = Shape2.Intersects(triangle, tile, triPos, tmp, triRot, true);\n     Console.Write($\"({x},{y})={intersectsTileAtXY}\")\n     if(intersectsTileAtXY)\n       Console.Write(\"  \"); // true is 1 letter shorter than false\n     else\n       Console.Write(\" \");\n  }\n  Console.WriteLine();\n}\n```\n\n### Polygon AABB checking\n\nNote that this is only faster for fairly complicated polygons (theoretical breakeven at 6 unique normals each).\nFurther note that it's almost *never* faster for rotated polygons - finding the AABB for rotated polygons is not\nsupported (though not complicated).\n\nThe provided AABB is most often used in UI elements which do not anticipate rotation and can have somewhat complicated\npolygons but don't have rotation, which is where AABBs shine.\n\n```cs\nvar complicatedShape = ShapeUtils.CreateCircle(5); // radius 5, 32 segments\n\n// Note we are not providing rotation - rect2 does not support rotation \n// (use ShapeUtils.CreateRectangle for that, which returns a Polygon2)\nRect2.Intersects(complicatedShape.AABB, complicatedShape.AABB, Vector2.Zero, new Vector2(3, 0), true); // True\n````\n\n### Circles\n\nCircles have similiar functions to polygons. The only thing to note is that all API functions will use the top-left\nof the bounding box of the circle for the circles position, rather than the center of the circle. This makes switching\nthings between circles and polygons easier in return for a very small performance cost.\n\n```cs\nvar circle = new Circle2(3); // The only argument is the radius of the circle.\nvar anotherCircle = new Circle2(5); \nvar triangle = ShapeUtils.CreateCircle(2, segments=3); \n\n// Circle -\u003e Circle collision using the same underlying circle object\nCircle2.Intersects(circle, circle, Vector2.Zero, new Vector(1, 0), true); // True\n\n// Circle -\u003e Circle collision can be done using just the radius\nCircle2.Intersects(3.0f, 3.0f, Vector2.Zero, new Vector2(1, 0), true); // Identical to above\n\n// Circle -\u003e Polygon collision must pass in a circle, not the radius of the circle\nShape2.Intersects(circle, triangle, Vector2.Zero, new Vector2(1, 1), true); // True\n\n// Circle -\u003e AABB collision\nShape2.Intersects(circle, triangle.AABB, Vector2.Zero, new Vector2(10, 0), true); // False\n```\n\n## Performance notes\n\nThis library is designed for when:\n\n1. You have only a few different polygon types\n2. You need to check collision on those polygon types when they are in rapidly changing positions and rotations.\n\nFor example in a 2D game where everything is either a triangle or hexagon, in this library you would only need \nto construct two polygons, then reuse those two polygons everywhere else. This allows the library to cache certain\noperations.\n\nThe library is designed such that changing rotations or position is fast, but the downside is when rotation\nor position does *not* change there is only a minor improvement in performance.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftjstretchalot%2Fsharpmath2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftjstretchalot%2Fsharpmath2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftjstretchalot%2Fsharpmath2/lists"}