Advertisement
EmeraldIT

Shape Detector

Sep 6th, 2024 (edited)
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.65 KB | None | 0 0
  1. local UserInputService = game:GetService("UserInputService")
  2. local RunService = game:GetService("RunService")
  3.  
  4. local isDrawing = false
  5. local points = {}
  6.  
  7. -- Accuracy tuning parameters (you can adjust these)
  8. local LINE_THRESHOLD = 20 -- Lower = more sensitive for detecting straight lines
  9. local CIRCLE_RADIUS_DEVIATION = 30 -- Lower = more sensitive for detecting perfect circles
  10. local RIGHT_ANGLE_THRESHOLD = 40 -- Tolerance for detecting right angles (in degrees)
  11. local MIN_TURN_ANGLE = 40 -- Minimum angle considered a "turn" for polygon detection
  12. local POLYGON_ANGLE_THRESHOLD = 30 -- Tolerance for angle deviation in polygons
  13.  
  14. -- Start drawing when mouse button is pressed
  15. UserInputService.InputBegan:Connect(function(input)
  16.     if input.UserInputType == Enum.UserInputType.MouseButton1 then
  17.         isDrawing = true
  18.         points = {} -- Reset points
  19.     end
  20. end)
  21.  
  22. -- Track mouse movement while drawing
  23. UserInputService.InputChanged:Connect(function(input)
  24.     if isDrawing and input.UserInputType == Enum.UserInputType.MouseMovement then
  25.         local mousePosition = input.Position
  26.         table.insert(points, Vector2.new(mousePosition.X, mousePosition.Y))
  27.     end
  28. end)
  29.  
  30. -- Stop drawing and analyze points when mouse button is released
  31. UserInputService.InputEnded:Connect(function(input)
  32.     if input.UserInputType == Enum.UserInputType.MouseButton1 then
  33.         isDrawing = false
  34.         detectShape(points)
  35.     end
  36. end)
  37.  
  38. -- Function to detect the shape
  39. function detectShape(points)
  40.     if #points < 10 then
  41.         print("Too few points to detect a shape.")
  42.         return
  43.     end
  44.    
  45.     local firstPoint = points[1]
  46.     local lastPoint = points[#points]
  47.    
  48.     -- Check if the first and last points are close (to form closed shapes)
  49.     local distance = (firstPoint - lastPoint).Magnitude
  50.    
  51.     if distance < 50 then
  52.         if isCircle(points) then
  53.             print("Circle detected!")
  54.         elseif isSquare(points) then
  55.             print("Square/Rectangle detected!")
  56.         elseif isTriangle(points) then
  57.             print("Triangle detected!")
  58.         elseif isPolygon(points) then
  59.             print("Polygon detected!")
  60.         else
  61.             print("Unknown closed shape")
  62.         end
  63.     else
  64.         if isLine(points) then
  65.             print("Line detected!")
  66.         else
  67.             print("Unknown open shape")
  68.         end
  69.     end
  70. end
  71.  
  72. -- Helper function to check if the points form a line
  73. function isLine(points)
  74.     local totalLength = 0
  75.     local directLineLength = (points[1] - points[#points]).Magnitude
  76.    
  77.     for i = 2, #points do
  78.         totalLength = totalLength + (points[i] - points[i - 1]).Magnitude
  79.     end
  80.    
  81.     -- If the total length of the segments is almost equal to the direct line distance, it's a line
  82.     return math.abs(totalLength - directLineLength) < LINE_THRESHOLD
  83. end
  84.  
  85. -- Helper function to check if the points form a circle
  86. function isCircle(points)
  87.     local center = (points[1] + points[#points]) / 2
  88.     local totalRadius = 0
  89.     local radiusDeviation = 0
  90.  
  91.     -- Calculate the average radius from the center
  92.     for _, point in ipairs(points) do
  93.         local radius = (point - center).Magnitude
  94.         totalRadius = totalRadius + radius
  95.     end
  96.    
  97.     local averageRadius = totalRadius / #points
  98.    
  99.     -- Calculate the deviation from the average radius
  100.     for _, point in ipairs(points) do
  101.         local radius = (point - center).Magnitude
  102.         radiusDeviation = radiusDeviation + math.abs(radius - averageRadius)
  103.     end
  104.    
  105.     -- If the deviation is small, it's a circle
  106.     return radiusDeviation / #points < CIRCLE_RADIUS_DEVIATION
  107. end
  108.  
  109. -- Helper function to check if the points form a square or rectangle
  110. function isSquare(points)
  111.     local function getAngle(v1, v2)
  112.         return math.acos(v1:Dot(v2) / (v1.Magnitude * v2.Magnitude))
  113.     end
  114.    
  115.     local rightAngleCount = 0
  116.     local turns = 0
  117.    
  118.     -- Check for 90-degree turns (right angles)
  119.     for i = 2, #points - 1 do
  120.         local v1 = (points[i] - points[i - 1]).Unit
  121.         local v2 = (points[i + 1] - points[i]).Unit
  122.         local angle = getAngle(v1, v2)
  123.        
  124.         -- 90-degree turns (right angle)
  125.         if math.abs(math.deg(angle) - 90) < RIGHT_ANGLE_THRESHOLD then
  126.             rightAngleCount = rightAngleCount + 1
  127.         end
  128.        
  129.         -- Track major turns
  130.         if math.deg(angle) > MIN_TURN_ANGLE then
  131.             turns = turns + 1
  132.         end
  133.     end
  134.    
  135.     -- A square/rectangle usually has 4 right angles and exactly 4 turns
  136.     return rightAngleCount >= 3 and turns == 4
  137. end
  138.  
  139. -- Helper function to check if the points form a triangle
  140. function isTriangle(points)
  141.     local function getAngle(v1, v2)
  142.         return math.acos(v1:Dot(v2) / (v1.Magnitude * v2.Magnitude))
  143.     end
  144.    
  145.     local turns = 0
  146.    
  147.     -- Check for 3 major turns to detect a triangle
  148.     for i = 2, #points - 1 do
  149.         local v1 = (points[i] - points[i - 1]).Unit
  150.         local v2 = (points[i + 1] - points[i]).Unit
  151.         local angle = getAngle(v1, v2)
  152.        
  153.         -- If the angle between segments indicates a sharp turn, increment
  154.         if math.deg(angle) > MIN_TURN_ANGLE then
  155.             turns = turns + 1
  156.         end
  157.     end
  158.    
  159.     -- A triangle has exactly 3 turns (corners)
  160.     return turns == 3
  161. end
  162.  
  163. -- Helper function to check if the points form a polygon (with more than 4 sides)
  164. function isPolygon(points)
  165.     local function getAngle(v1, v2)
  166.         return math.acos(v1:Dot(v2) / (v1.Magnitude * v2.Magnitude))
  167.     end
  168.    
  169.     local turns = 0
  170.     local angleSum = 0
  171.     local angles = {}
  172.  
  173.     -- Measure all angles between points
  174.     for i = 2, #points - 1 do
  175.         local v1 = (points[i] - points[i - 1]).Unit
  176.         local v2 = (points[i + 1] - points[i]).Unit
  177.         local angle = math.deg(getAngle(v1, v2))
  178.        
  179.         if angle > MIN_TURN_ANGLE then
  180.             table.insert(angles, angle)
  181.             turns = turns + 1
  182.         end
  183.     end
  184.    
  185.     -- Check if all angles are roughly the same for a regular polygon
  186.     if #angles >= 4 then
  187.         local averageAngle = 0
  188.         for _, angle in ipairs(angles) do
  189.             averageAngle = averageAngle + angle
  190.         end
  191.         averageAngle = averageAngle / #angles
  192.        
  193.         -- Check if the deviation from the average angle is small
  194.         local deviation = 0
  195.         for _, angle in ipairs(angles) do
  196.             deviation = deviation + math.abs(angle - averageAngle)
  197.         end
  198.        
  199.         -- If deviation is small, it's likely a regular polygon
  200.         return deviation / #angles < POLYGON_ANGLE_THRESHOLD
  201.     end
  202.    
  203.     return false
  204. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement