⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linesegment.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2003-2009 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.jme.math;

import java.io.IOException;
import java.io.Serializable;

import com.jme.util.export.InputCapsule;
import com.jme.util.export.JMEExporter;
import com.jme.util.export.JMEImporter;
import com.jme.util.export.OutputCapsule;
import com.jme.util.export.Savable;

/**
 * <p>LineSegment represents a segment in the space. This is a portion of a Line
 * that has a limited start and end points.</p>
 * <p>A LineSegment is defined by an origin, a direction and an extent (or length).
 * Direction should be a normalized vector. It is not internally normalized.</p>
 * <p>This class provides methods to calculate distances between LineSegments, Rays and Vectors.
 * It is also possible to retrieve both end points of the segment {@link LineSegment#getPositiveEnd(Vector3f)}
 * and {@link LineSegment#getNegativeEnd(Vector3f)}. There are also methods to check whether
 * a point is within the segment bounds.</p>
 *
 * @see Ray
 * @author Mark Powell
 * @author Joshua Slack
 */
public class LineSegment implements Serializable, Cloneable, Savable {

	private static final long serialVersionUID = 1L;

	private Vector3f origin;

	private Vector3f direction;

	private float extent;

	private static final Vector3f compVec1 = new Vector3f();

	public LineSegment() {
		origin = new Vector3f();
		direction = new Vector3f();
	}

	public LineSegment(LineSegment ls) {
		this.origin = new Vector3f(ls.getOrigin());
		this.direction = new Vector3f(ls.getDirection());
		this.extent = ls.getExtent();
	}

	/**
	 * <p>Creates a new LineSegment with the given origin, direction and extent.</p>
	 * <p>Note that the origin is not one of the ends of the LineSegment, but its center.</p>
	 */
	public LineSegment(Vector3f origin, Vector3f direction, float extent) {
		this.origin = origin;
		this.direction = direction;
		this.extent = extent;
	}

	/**
	 * <p>Creates a new LineSegment with a given origin and end. This constructor will calculate the
	 * center, the direction and the extent.</p>
	 */
	public LineSegment(Vector3f start, Vector3f end) {
		this.origin = new Vector3f(0.5f * (start.x + end.x), 0.5f * (start.y + end.y), 0.5f * (start.z + end.z));
		this.direction = end.subtract(start);
		this.extent = direction.length();
		direction.normalizeLocal();
	}

	public void set(LineSegment ls) {
		this.origin = new Vector3f(ls.getOrigin());
		this.direction = new Vector3f(ls.getDirection());
		this.extent = ls.getExtent();
	}

	public float distance(Vector3f point) {
		return FastMath.sqrt(distanceSquared(point));
	}

	public float distance(LineSegment ls) {
		return FastMath.sqrt(distanceSquared(ls));
	}

	public float distance(Ray r) {
		return FastMath.sqrt(distanceSquared(r));
	}

	public float distanceSquared(Vector3f point) {
		point.subtract(origin, compVec1);
		float segmentParameter = direction.dot(compVec1);

		if (-extent < segmentParameter) {
			if (segmentParameter < extent) {
				origin
						.add(direction.mult(segmentParameter, compVec1),
								compVec1);
			} else {
				origin.add(direction.mult(extent, compVec1), compVec1);
			}
		} else {
			origin.subtract(direction.mult(extent, compVec1), compVec1);
		}

		compVec1.subtractLocal(point);
		return compVec1.lengthSquared();
	}

	public float distanceSquared(LineSegment test) {
		origin.subtract(test.getOrigin(), compVec1);
		float negativeDirectionDot = -(direction.dot(test.getDirection()));
		float diffThisDot = compVec1.dot(direction);
		float diffTestDot = -(compVec1.dot(test.getDirection()));
		float lengthOfDiff = compVec1.lengthSquared();
		float determinant = FastMath.abs(1.0f - negativeDirectionDot
				* negativeDirectionDot);
		float s0, s1, squareDistance, extentDeterminant0, extentDeterminant1, tempS0, tempS1;

		if (determinant >= FastMath.FLT_EPSILON) {
			// segments are not parallel
			s0 = negativeDirectionDot * diffTestDot - diffThisDot;
			s1 = negativeDirectionDot * diffThisDot - diffTestDot;
			extentDeterminant0 = extent * determinant;
			extentDeterminant1 = test.getExtent() * determinant;

			if (s0 >= -extentDeterminant0) {
				if (s0 <= extentDeterminant0) {
					if (s1 >= -extentDeterminant1) {
						if (s1 <= extentDeterminant1) // region 0 (interior)
						{
							// minimum at two interior points of 3D lines
							float inverseDeterminant = ((float) 1.0)
									/ determinant;
							s0 *= inverseDeterminant;
							s1 *= inverseDeterminant;
							squareDistance = s0
									* (s0 + negativeDirectionDot * s1 + (2.0f) * diffThisDot)
									+ s1
									* (negativeDirectionDot * s0 + s1 + (2.0f) * diffTestDot)
									+ lengthOfDiff;
						} else // region 3 (side)
						{
							s1 = test.getExtent();
							tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
							if (tempS0 < -extent) {
								s0 = -extent;
								squareDistance = s0 * (s0 - (2.0f) * tempS0)
										+ s1 * (s1 + (2.0f) * diffTestDot)
										+ lengthOfDiff;
							} else if (tempS0 <= extent) {
								s0 = tempS0;
								squareDistance = -s0 * s0 + s1
										* (s1 + (2.0f) * diffTestDot)
										+ lengthOfDiff;
							} else {
								s0 = extent;
								squareDistance = s0 * (s0 - (2.0f) * tempS0)
										+ s1 * (s1 + (2.0f) * diffTestDot)
										+ lengthOfDiff;
							}
						}
					} else // region 7 (side)
					{
						s1 = -test.getExtent();
						tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
						if (tempS0 < -extent) {
							s0 = -extent;
							squareDistance = s0 * (s0 - (2.0f) * tempS0) + s1
									* (s1 + (2.0f) * diffTestDot)
									+ lengthOfDiff;
						} else if (tempS0 <= extent) {
							s0 = tempS0;
							squareDistance = -s0 * s0 + s1
									* (s1 + (2.0f) * diffTestDot)
									+ lengthOfDiff;
						} else {
							s0 = extent;
							squareDistance = s0 * (s0 - (2.0f) * tempS0) + s1
									* (s1 + (2.0f) * diffTestDot)
									+ lengthOfDiff;
						}
					}
				} else {
					if (s1 >= -extentDeterminant1) {
						if (s1 <= extentDeterminant1) // region 1 (side)
						{
							s0 = extent;
							tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
							if (tempS1 < -test.getExtent()) {
								s1 = -test.getExtent();
								squareDistance = s1 * (s1 - (2.0f) * tempS1)
										+ s0 * (s0 + (2.0f) * diffThisDot)
										+ lengthOfDiff;
							} else if (tempS1 <= test.getExtent()) {
								s1 = tempS1;
								squareDistance = -s1 * s1 + s0
										* (s0 + (2.0f) * diffThisDot)
										+ lengthOfDiff;
							} else {
								s1 = test.getExtent();
								squareDistance = s1 * (s1 - (2.0f) * tempS1)
										+ s0 * (s0 + (2.0f) * diffThisDot)
										+ lengthOfDiff;
							}
						} else // region 2 (corner)
						{
							s1 = test.getExtent();
							tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
							if (tempS0 < -extent) {
								s0 = -extent;
								squareDistance = s0 * (s0 - (2.0f) * tempS0)
										+ s1 * (s1 + (2.0f) * diffTestDot)
										+ lengthOfDiff;
							} else if (tempS0 <= extent) {
								s0 = tempS0;
								squareDistance = -s0 * s0 + s1
										* (s1 + (2.0f) * diffTestDot)
										+ lengthOfDiff;
							} else {
								s0 = extent;
								tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
								if (tempS1 < -test.getExtent()) {
									s1 = -test.getExtent();
									squareDistance = s1
											* (s1 - (2.0f) * tempS1) + s0
											* (s0 + (2.0f) * diffThisDot)
											+ lengthOfDiff;
								} else if (tempS1 <= test.getExtent()) {
									s1 = tempS1;
									squareDistance = -s1 * s1 + s0
											* (s0 + (2.0f) * diffThisDot)
											+ lengthOfDiff;
								} else {
									s1 = test.getExtent();
									squareDistance = s1
											* (s1 - (2.0f) * tempS1) + s0
											* (s0 + (2.0f) * diffThisDot)
											+ lengthOfDiff;
								}
							}
						}
					} else // region 8 (corner)
					{
						s1 = -test.getExtent();
						tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
						if (tempS0 < -extent) {
							s0 = -extent;
							squareDistance = s0 * (s0 - (2.0f) * tempS0) + s1
									* (s1 + (2.0f) * diffTestDot)
									+ lengthOfDiff;
						} else if (tempS0 <= extent) {
							s0 = tempS0;
							squareDistance = -s0 * s0 + s1
									* (s1 + (2.0f) * diffTestDot)
									+ lengthOfDiff;
						} else {
							s0 = extent;
							tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
							if (tempS1 > test.getExtent()) {
								s1 = test.getExtent();
								squareDistance = s1 * (s1 - (2.0f) * tempS1)
										+ s0 * (s0 + (2.0f) * diffThisDot)
										+ lengthOfDiff;
							} else if (tempS1 >= -test.getExtent()) {
								s1 = tempS1;
								squareDistance = -s1 * s1 + s0
										* (s0 + (2.0f) * diffThisDot)
										+ lengthOfDiff;
							} else {
								s1 = -test.getExtent();
								squareDistance = s1 * (s1 - (2.0f) * tempS1)
										+ s0 * (s0 + (2.0f) * diffThisDot)
										+ lengthOfDiff;
							}
						}
					}
				}
			} else {
				if (s1 >= -extentDeterminant1) {
					if (s1 <= extentDeterminant1) // region 5 (side)
					{
						s0 = -extent;
						tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
						if (tempS1 < -test.getExtent()) {
							s1 = -test.getExtent();
							squareDistance = s1 * (s1 - (2.0f) * tempS1) + s0

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -