版本:Unity 6 (6000.0)
语言英语
  • C#

LineUtility.Simplify

建议更改

成功!

感谢您帮助我们改进 Unity 文档的质量。虽然我们无法接受所有提交的内容,但我们会阅读用户提出的每一项建议,并根据情况进行更新。

关闭

提交失败

由于某些原因,您的建议更改无法提交。请在几分钟后<a>重试</a>。感谢您花时间帮助我们改进 Unity 文档的质量。

关闭

取消

声明

public static void Simplify(List<Vector3> points, float tolerance, List<int> pointsToKeep);

声明

public static void Simplify(List<Vector3> points, float tolerance, List<Vector3> simplifiedPoints);

声明

public static void Simplify(List<Vector2> points, float tolerance, List<int> pointsToKeep);

声明

public static void Simplify(List<Vector2> points, float tolerance, List<Vector2> simplifiedPoints);

参数

points 组成原始线条的点。
tolerance 此值用于评估应从线条中删除哪些点。较高的值将导致更简单的线条(更少的点)。接近零的正值将导致线条几乎或完全不减少。值为零或负值没有任何效果。
pointsToKeep 由该函数填充。包含应生成简化版本的点的索引。
simplifiedPoints 由该函数填充。包含构成简化线条的点。

描述

通过删除位于指定容差范围内的点,生成原始线条的简化版本。

例如,你可以使用此函数缩减由数千个点构成的复杂线条。可以将该线条缩减至数百个甚至更少的点,同时仍然保持与原始线条非常接近的形状。你可以通过调整容差(较高的容差值会导致生成线条中的点较少)来生成同一线条的多个不同细节级别的版本。然后,可以使用 LODGroup 系统显示生成的线条。

Simplify 算法基于Ramer Douglas Peucker 算法;它创建一条非常接近所提供线条但点较少的线条(由容差值确定)。

注释:该函数能够处理大量的点,因为它是非递归的。此函数的 2D 版本比此函数的性能要好,因为它使用了一种更简单的点评估方式。

其他资源:LineRenderer.Simplify

以下示例演示如何将线简化应用到现有的线中。

using System.Collections.Generic;
using System.Linq;
using UnityEngine;

// This example shows how to apply line simplification to a line that already contains points. [RequireComponent(typeof(LineRenderer))] public class SimpleExampleLineUtility : MonoBehaviour { public float tolerance = 1; void Start() { // Get the points. var lineRenderer = GetComponent<LineRenderer>(); int pointsBefore = lineRenderer.positionCount; var points = new Vector3[pointsBefore]; lineRenderer.GetPositions(points);

// Simplify. var simplifiedPoints = new List<Vector3>(); LineUtility.Simplify(points.ToList(), tolerance, simplifiedPoints);

// Assign back to the line renderer. lineRenderer.positionCount = simplifiedPoints.Count; lineRenderer.SetPositions(simplifiedPoints.ToArray());

Debug.Log("Line reduced from " + pointsBefore + " to " + lineRenderer.positionCount); } }

以下示例演示如何使用 pointsToKeep 参数返回索引列表。该列表随后可用于简化保留该列表中点的线段。仍可向所得简化线段中添加其他点。

using System.Collections.Generic;
using System.Linq;
using UnityEngine;

// This example shows how to use the pointsToKeep parameter to generate a new simplified version of the line. [RequireComponent(typeof(LineRenderer))] public class SimpleExampleLineUtilityPointsToKeep : MonoBehaviour { public float tolerance = 1; void Start() { // Get the points. var lineRenderer = GetComponent<LineRenderer>(); int pointsBefore = lineRenderer.positionCount; var points = new Vector3[pointsBefore]; lineRenderer.GetPositions(points);

// Simplify. var pointsToKeep = new List<int>(); LineUtility.Simplify(points.ToList(), tolerance, pointsToKeep);

var simplifiedPoints = new Vector3[pointsToKeep.Count]; for (int i = 0; i < simplifiedPoints.Length; ++i) { simplifiedPoints[i] = points[pointsToKeep[i]]; }

// Assign back to the line renderer. lineRenderer.positionCount = simplifiedPoints.Length; lineRenderer.SetPositions(simplifiedPoints);

Debug.Log("Line reduced from " + pointsBefore + " to " + lineRenderer.positionCount); } }

本示例生成一条正弦波形状的线段,并提供一个 GUI 来自定义线段生成和简化参数。

using System.Collections.Generic;
using UnityEngine;

// This example creates a sine wave and then simplifies it using the LineUtility. // The parameters can be adjusted through an in game GUI to allow for experimentation. [RequireComponent(typeof(LineRenderer))] public class LineUtilityExample : MonoBehaviour { public int numberOfPoints = 1000; public float length = 50; public float waveHeight = 10; public float tolerance = 0.1f;

private LineRenderer lineRenderer; private List<Vector3> points = new List<Vector3>(); // Generated points before LineOptimizer is used. private List<Vector3> simplifiedPoints = new List<Vector3>(); // Simplified points after LineOptimizer is used.

public void Start() { lineRenderer = GetComponent<LineRenderer>(); }

// Generates the sine wave points. public void GeneratePoints() { points.Clear(); float halfWaveHeight = waveHeight * 0.5f; float step = length / numberOfPoints; for (int i = 0; i < numberOfPoints; ++i) { points.Add(new Vector3(i * step, Mathf.Sin(i * step) * halfWaveHeight, 0)); } }

// Simplify the line using the LineOptimizer. public void SimplifyLine() { simplifiedPoints.Clear(); LineUtility.Simplify(points, tolerance, simplifiedPoints); lineRenderer.positionCount = simplifiedPoints.Count; lineRenderer.SetPositions(simplifiedPoints.ToArray()); }

// Draw a simple GUI slider with a label. private static float GUISlider(string label, float value, float min, float max) { GUILayout.BeginHorizontal(GUILayout.Width(Screen.width / 2.0f)); GUILayout.Label(label + "(" + value + ") :", GUILayout.Width(150)); var val = GUILayout.HorizontalSlider(value, min, max); GUILayout.EndHorizontal(); return val; }

public void OnGUI() { GUILayout.Label("LineUtility.Simplify", GUI.skin.box);

// We use GUI.changed to detect if a value was changed via the GUI, if it has we can then re-generate the points and simplify the line again. GUI.changed = false;

numberOfPoints = (int)GUISlider("Number of Points", numberOfPoints, 0, 1000); length = GUISlider("Length", length, 0, 100); waveHeight = GUISlider("Wave Height", waveHeight, 0, 100); if (GUI.changed) GeneratePoints();

tolerance = GUISlider("Simplify Tolerance", tolerance, 0, 2); if (GUI.changed) SimplifyLine();

float percentRemoved = 100.0f - ((float)lineRenderer.positionCount / numberOfPoints) * 100.0f; if (tolerance > 0.0f) GUILayout.Label("Points after simplification: " + lineRenderer.positionCount + "(Removed " + percentRemoved.ToString("##.##") + "%)"); } }