/// <summary>
        /// Insert a new node between every node segment of the area
        /// </summary>
        public static void Subdivide(VegetationMaskArea mask)
        {
            List <Node> originalNodes = new List <Node>();

            originalNodes.AddRange(mask.Nodes);

            for (var i = 0; i < originalNodes.Count; i++)
            {
                Node curr = originalNodes[i];
                Node next = mask.GetNextNode(curr);

                Vector3[] segment = new Vector3[] { curr.Position, next.Position };

                Vector3 meanVector = PolygonUtils.GetMeanVector(segment);

                int index = mask.GetNodeIndex(curr);

                Node newNode = new Node()
                {
                    Position = meanVector
                };

                mask.Nodes.Insert(index + 1, newNode);
            }

            UpdateMask(mask);
        }
        /// <summary>
        /// Force update on the mask in scene view
        /// </summary>
        /// <param name="mask"></param>
        public static void UpdateMask(VegetationMaskArea mask)
        {
            // TODO: that's just a quick hack to update the mask. mask.PositionNodes(); doesn't seem to work and mask.Update() has an optimization in it
            mask.transform.position = mask.transform.position + new Vector3(0, 1, 0);
            mask.transform.position = mask.transform.position + new Vector3(0, -1, 0);

            // apply the mask to the vegetation
            mask.UpdateVegetationMask();
        }
        public static void CreateHexagon(VegetationMaskArea mask)
        {
            float radius = GetRadius(mask);

            Vector3[] hexagon = ShapeCreator.CreateHexagon(mask.transform.position, radius);

            mask.Nodes.Clear();
            mask.AddNodesToEnd(hexagon);

            // center main handle, implicitly updates the mask
            CenterMainHandle(mask);
        }
        /// <summary>
        /// Resize the mask
        /// </summary>
        /// <param name="factor">Positive values for growing, negative for shrinking. 0.1 means grow by 10%, -0.1 means shrink by 10%</param>
        public static void ResizeMask(VegetationMaskArea mask, float factor)
        {
            Vector3 center = GetMaskCenter(mask);

            foreach (Node node in mask.Nodes)
            {
                Vector3 worldPos = mask.transform.TransformPoint(node.Position);

                Vector3 distance = worldPos - center;

                worldPos += distance * factor;

                node.Position = mask.transform.InverseTransformPoint(worldPos);
            }

            UpdateMask(mask);
        }
        /// <summary>
        /// Transform the mask and convert it into its convex hull.
        /// </summary>
        /// <param name="mask"></param>
        public static void ConvexHull(VegetationMaskArea mask)
        {
            Vector3 maskPosition = mask.transform.position;

            List <Vector2> positionsXY = mask.Nodes.ConvertAll <Vector2>(item => new Vector2(item.Position.x, item.Position.z));

            List <Vector2> convexHull = PolygonUtility.GetConvexHull(positionsXY);

            mask.Nodes.Clear();
            foreach (Vector2 nodePosition in convexHull)
            {
                mask.AddNodeToEnd(new Vector3(maskPosition.x + nodePosition.x, 0, maskPosition.z + nodePosition.y));
            }

            // center main handle, implicitly updates the mask
            CenterMainHandle(mask);
        }
        public static float GetRadius(VegetationMaskArea mask)
        {
            Vector3        maskCenter     = GetMaskCenter(mask);
            List <Vector3> worldPositions = mask.GetWorldSpaceNodePositions();

            // calculate the radius by using the average distance from the mask center
            float magnitudeSum = 0f;

            foreach (Vector3 worldPosition in worldPositions)
            {
                magnitudeSum += (worldPosition - maskCenter).magnitude;
            }

            float radius = magnitudeSum / mask.Nodes.Count;

            return(radius);
        }
        /// <summary>
        /// Move the main handle into the center of the maks polygon
        /// </summary>
        /// <param name="mask"></param>
        public static void CenterMainHandle(VegetationMaskArea mask)
        {
            Vector3 center = GetMaskCenter(mask);
            Vector3 offset = mask.transform.position - center;

            mask.transform.position = center;

            foreach (Node node in mask.Nodes)
            {
                Vector3 worldPos = mask.transform.TransformPoint(node.Position);

                worldPos += offset;

                node.Position = mask.transform.InverseTransformPoint(worldPos);
            }

            UpdateMask(mask);
        }
        /// <summary>
        /// Remove every 2nd node
        /// </summary>
        public static void Unsubdivide(VegetationMaskArea mask)
        {
            // ensure there is at least the specified number of nodes left
            int minimumNodeCount = 3;

            if (mask.Nodes.Count <= minimumNodeCount)
            {
                return;
            }

            int count = mask.Nodes.Count;

            for (var i = mask.Nodes.Count - 1; i >= 0; i -= 2)
            {
                mask.Nodes.RemoveAt(i);

                if (mask.Nodes.Count < minimumNodeCount)
                {
                    break;
                }
            }

            UpdateMask(mask);
        }
 /// <summary>
 /// Shrink the mask by the given factor
 /// </summary>
 /// <param name="mask"></param>
 /// <param name="factor"></param>
 public static void Shrink(VegetationMaskArea mask, float factor)
 {
     ResizeMask(mask, -Mathf.Abs(factor));
 }
 /// <summary>
 /// Grow the mask by the given factor
 /// </summary>
 /// <param name="mask"></param>
 /// <param name="factor"></param>
 public static void Grow(VegetationMaskArea mask, float factor)
 {
     ResizeMask(mask, Mathf.Abs(factor));
 }
        /// <summary>
        /// Get the center of the mask polygon
        /// </summary>
        /// <param name="mask"></param>
        /// <returns></returns>
        public static Vector3 GetMaskCenter(VegetationMaskArea mask)
        {
            List <Vector3> worldPositions = mask.GetWorldSpaceNodePositions();

            return(PolygonUtils.GetMeanVector(worldPositions.ToArray()));
        }
 /// <summary>
 /// Create a list of node positions.
 /// </summary>
 /// <param name="mask"></param>
 /// <returns></returns>
 public static List <Vector3> GetPositions(VegetationMaskArea mask)
 {
     return(mask.Nodes.ConvertAll <Vector3>(item => new Vector3(item.Position.x, item.Position.y, item.Position.z)));
 }
Exemple #13
0
 public void Awake()
 {
     extension = (VegetationMaskAreaExtension)target;
     mask      = extension.GetComponent <VegetationMaskArea>();
 }