- Home /
How do you select 3d lines in Vectrosity by clicking?
i have created lines using the VectorLine.SetLine3D function and would like to be able to select a line by clicking on it.
I am using c# and would like to be able to do this on iOS and web platforms.
Thanks in advance and thanks for the answers to questions others have asked, for i have benefited as well.
What does 'select' mean? What do you want to do with the line after you select it? I see three possibilities:
Dynamically add a mesh collier to the mesh of the line
Create a collider that is scaled and rotated to match the line
Do the calculation mathematically
after selecting the line i would like to find the shortest distance between the curve (line) and a particular point on another curve. from the choices you proposed i think the mathematical solution would be best. could you explain further? thank you
Answer by robertbu · Aug 14, 2014 at 08:03 AM
Here is a bit of code that demonstrates how it can be done mathematically. What is needed is the minimum distance between a ray and a line segment, since you need to cast a ray into the scene for a perspective camera. This can be solved as single function mathematically. But I just went out and grabbed the Math3d class from the Unity Wiki, and did it in three function calls (per segment).
Find the closest point on the ray to the line defined by the two segment points
Find the closest point on the line segment to the point from step 1.
Find the distance between the points in step 1 and 2.
If the distance is below the selection threshold, and if it is closer than any other distance found, it becomes the best candidate.
Note the sample code uses a LineRender. It generates a number of points in 3D space. When a line is selected, the code places a marker sphere at both ends of the segment. Note since the lines are in 3D space, the spheres will be at different distance from the camera and therefore usually very different in size. You could make the code more efficient by combining and simplify the function calls, but with 10,000 segments I found no lag when selecting (on my desktop).
using UnityEngine;
using System.Collections;
[RequireComponent (typeof (LineRenderer))]
public class SelectSegment : MonoBehaviour {
public int ptCount = 25;
public float selectionThreshold = 0.05f;
private Vector3[] points;
private Transform marker1;
private Transform marker2;
void Start () {
LineRenderer lr = GetComponent<LineRenderer>();
lr.SetWidth(0.1f, 0.1f);
lr.SetVertexCount(ptCount);
points = new Vector3[ptCount];
for (int i = 0; i < ptCount; i++) {
points[i] = Random.insideUnitSphere * 6.0f;
lr.SetPosition(i, points[i]);
}
marker1 = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
marker1.localScale = new Vector3(.15f, .15f, .15f);
marker2 = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
marker1.localScale = new Vector3(.15f, .15f, .15f);
marker1.renderer.enabled = false;
marker2.renderer.enabled = false;
}
void Update () {
if (Input.GetMouseButtonDown (0)) {
int iSelect = AttemptSelect();
if (iSelect != -1) {
marker1.transform.position = points[iSelect];
marker1.renderer.enabled = true;
marker2.transform.position = points[iSelect +1];
marker2.renderer.enabled = true;
}
else {
marker1.renderer.enabled = false;
marker2.renderer.enabled = false;
}
}
}
// Returns -1 if it did not find any lines within the threshold,
// or it returns the index of the first point in the closest segment
int AttemptSelect() {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
int iSelect = -1;
float closestYet = Mathf.Infinity;
for (int i = 0; i < points.Length-1; i++) {
Vector3 closest1;
Vector3 closest2;
if (Math3d.ClosestPointsOnTwoLines(out closest1, out closest2, ray.origin, ray.direction, points[i], points[i+1] - points[i])) {
Vector3 v = Math3d.ProjectPointOnLineSegment(points[i], points[i+1], closest1);
float dist = (v - closest1).magnitude;
if (dist < closestYet && dist < selectionThreshold) {
iSelect = i;
closestYet = dist;
}
}
}
return iSelect;
}
}
thank you robertbu. i don't have enough reputation to thumbs up your answer. very clever code. thank you.
You can mark the question as answered by clicking on the checkmark to the left of the answer. When you accept an answer, it gives karma to both you and the person that answered your question.
Your answer
![](https://koobas.hobune.stream/wayback/20220613160519im_/https://answers.unity.com/themes/thub/images/avi.jpg)