LCOV - code coverage report
Current view: top level - maps/random/rmgen - math.js (source / functions) Hit Total Coverage
Test: lcov.info Lines: 13 59 22.0 %
Date: 2023-04-02 12:52:40 Functions: 2 10 20.0 %

          Line data    Source code
       1           6 : const g_TileVertices = deepfreeze([
       2             :         new Vector2D(0, 0),
       3             :         new Vector2D(0, 1),
       4             :         new Vector2D(1, 0),
       5             :         new Vector2D(1, 1)
       6             : ]);
       7             : 
       8           6 : const g_AdjacentCoordinates = deepfreeze([
       9             :         new Vector2D(1, 0),
      10             :         new Vector2D(1, 1),
      11             :         new Vector2D(0, 1),
      12             :         new Vector2D(-1, 1),
      13             :         new Vector2D(-1, 0),
      14             :         new Vector2D(-1, -1),
      15             :         new Vector2D(0, -1),
      16             :         new Vector2D(1, -1)
      17             : ]);
      18             : 
      19             : function diskArea(radius)
      20             : {
      21           0 :         return Math.PI * Math.square(radius);
      22             : }
      23             : 
      24             : /**
      25             :  * Returns the angle of the vector between point 1 and point 2.
      26             :  * The angle is counterclockwise from the positive x axis.
      27             :  */
      28             : function getAngle(x1, z1, x2, z2)
      29             : {
      30           0 :         return Math.atan2(z2 - z1, x2 - x1);
      31             : }
      32             : 
      33             : /**
      34             :  * Get pointCount points equidistantly located on a circle.
      35             :  * @param {Vector2D} center
      36             :  */
      37             : function distributePointsOnCircle(pointCount, startAngle, radius, center)
      38             : {
      39           0 :         return distributePointsOnCircularSegment(pointCount, 2 * Math.PI * (pointCount - 1) / pointCount, startAngle, radius, center);
      40             : }
      41             : 
      42             : /**
      43             :  * Get pointCount points equidistantly located on a circular segment, including both endpoints.
      44             :  */
      45             : function distributePointsOnCircularSegment(pointCount, maxAngle, startAngle, radius, center)
      46             : {
      47           0 :         let points = [];
      48           0 :         let angle = [];
      49           0 :         pointCount = Math.round(pointCount);
      50             : 
      51           0 :         for (let i = 0; i < pointCount; ++i)
      52             :         {
      53           0 :                 angle[i] = startAngle + maxAngle * i / Math.max(1, pointCount - 1);
      54           0 :                 points[i] = Vector2D.add(center, new Vector2D(radius, 0).rotate(-angle[i]));
      55             :         }
      56             : 
      57           0 :         return [points, angle];
      58             : }
      59             : 
      60             : /**
      61             :  * Returns the shortest distance from a point to a line.
      62             :  * The sign of the return value determines the direction!
      63             :  *
      64             :  * @param {Vector2D} - lineStart, lineEnd, point
      65             :  */
      66             : function distanceOfPointFromLine(lineStart, lineEnd, point)
      67             : {
      68             :         // Since the cross product is the area of the parallelogram with the vectors for sides and
      69             :         // one of the two vectors having length one, that area equals the distance between the points.
      70           0 :         return Vector2D.sub(lineStart, lineEnd).normalize().cross(Vector2D.sub(point, lineEnd));
      71             : }
      72             : 
      73             : /**
      74             :  * Returns whether the two lines of the given width going through the given Vector2D intersect.
      75             :  */
      76             : function testLineIntersection(start1, end1, start2, end2, width)
      77             : {
      78           0 :         let start1end1 = Vector2D.sub(start1, end1);
      79           0 :         let start2end2 = Vector2D.sub(start2, end2);
      80           0 :         let start1start2 = Vector2D.sub(start1, start2);
      81             : 
      82           0 :         return (
      83             :                 Math.abs(distanceOfPointFromLine(start1, end1, start2)) < width ||
      84             :                 Math.abs(distanceOfPointFromLine(start1, end1, end2)) < width ||
      85             :                 Math.abs(distanceOfPointFromLine(start2, end2, start1)) < width ||
      86             :                 Math.abs(distanceOfPointFromLine(start2, end2, end1)) < width ||
      87             :                 start1end1.cross(start1start2) * start1end1.cross(Vector2D.sub(start1, end2)) <= 0 &&
      88             :                 start2end2.cross(start1start2) * start2end2.cross(Vector2D.sub(start2, end1)) >= 0);
      89             : }
      90             : 
      91             : /**
      92             :  * Returns the topleft and bottomright coordinate of the given two points.
      93             :  */
      94             : function getBoundingBox(points)
      95             : {
      96           4 :         let min = points[0].clone();
      97           4 :         let max = points[0].clone();
      98             : 
      99           4 :         for (let point of points)
     100             :         {
     101           8 :                 min.set(Math.min(min.x, point.x), Math.min(min.y, point.y));
     102           8 :                 max.set(Math.max(max.x, point.x), Math.max(max.y, point.y));
     103             :         }
     104             : 
     105           4 :         return {
     106             :                 "min": min,
     107             :                 "max": max
     108             :         };
     109             : }
     110             : 
     111             : function getPointsInBoundingBox(boundingBox)
     112             : {
     113           4 :         let points = [];
     114           4 :         for (let x = boundingBox.min.x; x <= boundingBox.max.x; ++x)
     115          18 :                 for (let y = boundingBox.min.y; y <= boundingBox.max.y; ++y)
     116          92 :                         points.push(new Vector2D(x, y));
     117           4 :         return points;
     118             : }
     119             : 
     120             : /**
     121             :  * Get the order of the given points to get the shortest closed path (similar to the traveling salesman problem).
     122             :  * @param {Vectro2D[]} points - Points the path should go through
     123             :  * @returns {number[]} Ordered indices, same length as points
     124             :  */
     125             : function sortPointsShortestCycle(points)
     126             : {
     127           0 :         let order = [];
     128           0 :         let distances = [];
     129           0 :         if (points.length <= 3)
     130             :         {
     131           0 :                 for (let i = 0; i < points.length; ++i)
     132           0 :                         order.push(i);
     133             : 
     134           0 :                 return order;
     135             :         }
     136             : 
     137             :         // Just add the first 3 points
     138           0 :         let pointsToAdd = points.map(p => p.clone());
     139           0 :         for (let i = 0; i < 3; ++i)
     140             :         {
     141           0 :                 order.push(i);
     142           0 :                 pointsToAdd.shift();
     143           0 :                 if (i)
     144           0 :                         distances.push(points[order[i]].distanceTo(points[order[i - 1]]));
     145             :         }
     146             : 
     147           0 :         distances.push(points[order[0]].distanceTo(points[order[order.length - 1]]));
     148             : 
     149             :         // Add remaining points so the path lengthens the least
     150           0 :         let numPointsToAdd = pointsToAdd.length;
     151           0 :         for (let i = 0; i < numPointsToAdd; ++i)
     152             :         {
     153             :                 let indexToAddTo;
     154           0 :                 let minEnlengthen = Infinity;
     155           0 :                 let minDist1 = 0;
     156           0 :                 let minDist2 = 0;
     157           0 :                 for (let k = 0; k < order.length; ++k)
     158             :                 {
     159           0 :                         let dist1 = pointsToAdd[0].distanceTo(points[order[k]]);
     160           0 :                         let dist2 = pointsToAdd[0].distanceTo(points[order[(k + 1) % order.length]]);
     161             : 
     162           0 :                         let enlengthen = dist1 + dist2 - distances[k];
     163           0 :                         if (enlengthen < minEnlengthen)
     164             :                         {
     165           0 :                                 indexToAddTo = k;
     166           0 :                                 minEnlengthen = enlengthen;
     167           0 :                                 minDist1 = dist1;
     168           0 :                                 minDist2 = dist2;
     169             :                         }
     170             :                 }
     171           0 :                 order.splice(indexToAddTo + 1, 0, i + 3);
     172           0 :                 distances.splice(indexToAddTo, 1, minDist1, minDist2);
     173           0 :                 pointsToAdd.shift();
     174             :         }
     175             : 
     176           0 :         return order;
     177             : }

Generated by: LCOV version 1.14