Package org.mt4j.components.bounds

Source Code of org.mt4j.components.bounds.BoundsArbitraryPlanarPolygon

/***********************************************************************
* mt4j Copyright (c) 2008 - 2009, C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
*   This program is free software: you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation, either version 3 of the License, or
*   (at your option) any later version.
*
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
***********************************************************************/
package org.mt4j.components.bounds;

import org.mt4j.components.MTComponent;
import org.mt4j.components.TransformSpace;
import org.mt4j.util.camera.IFrustum;
import org.mt4j.util.math.Matrix;
import org.mt4j.util.math.Ray;
import org.mt4j.util.math.ToolsGeometry;
import org.mt4j.util.math.Vector3D;

import processing.core.PGraphics;


/**
* The Class BoundsArbitraryPlanarPolygon.
* @author Christopher Ruff
*/
public class BoundsArbitraryPlanarPolygon implements IBoundingShape {
 
  /** The peer component. */
  private MTComponent peerComponent;
 
  /** The bounding points local. */
  private Vector3D[] boundingPointsLocal;
 
 
  /** The xy bounds rect. */
  private BoundsZPlaneRectangle xyBoundsRect;
 
 
  private Vector3D[] worldVecs;
  private boolean worldVecsDirty;
  private Vector3D centerPointWorld;
  private boolean centerWorldDirty;
 
 
  /**
   * A 2D bounding polygon that is defined by the specified vectors.
   * This bounding shape is only suitable for objects that lie entirely in the z=0 plane.
   *
   * @param peerComponent the peer component
   * @param boundingPoints the bounding points
   */
  public BoundsArbitraryPlanarPolygon(MTComponent peerComponent, Vector3D[] boundingPoints) {
    super();
    this.peerComponent         = peerComponent;
    this.boundingPointsLocal     = boundingPoints;
   
    if (boundingPointsLocal.length < 3){
      throw new RuntimeException("Bounds have to have at least 3 vertices!");
    }
   
    //Calc bounding rect in xy-plane for width/height
    this.xyBoundsRect = new BoundsZPlaneRectangle(peerComponent, boundingPoints);
   
    this.worldVecsDirty   = true;
    this.centerWorldDirty   = true;
//    this.worldVecs       = this.getVectorsGlobal();
//    this.centerPointWorld   = this.getCenterPointGlobal();
  }
 
 
  public void drawBounds(PGraphics g) {
    g.pushMatrix();
    g.fill(150,180);
    g.beginShape();
    Vector3D[] vectors = this.getVectorsLocal();
    for (int i = 0; i < vectors.length; i++) {
      g.vertex(vectors[i].x, vectors[i].y, vectors[i].z);
    }
    g.endShape();
    g.popMatrix();
  }
 
 
  public void setGlobalBoundsChanged(){
    this.worldVecsDirty = true;
    this.centerWorldDirty = true;
    xyBoundsRect.setGlobalBoundsChanged();
  }

 
  public Vector3D getCenterPointLocal() {
    //TODO check if entierely in x,y plane and use this, else create bounding box/sphere and get the center
    return  ToolsGeometry.getPolygonCenterOfMass2D(this.boundingPointsLocal);
  }
 
 
  public Vector3D getCenterPointGlobal() {
    if (centerWorldDirty){
      Vector3D tmp = this.getCenterPointLocal().getCopy();
      tmp.transform(this.peerComponent.getGlobalMatrix());
      this.centerPointWorld = tmp;
      this.centerWorldDirty = false;
      return this.centerPointWorld;
    }
    else{
      return this.centerPointWorld;
    }
  }

 
  public Vector3D getIntersectionLocal(Ray ray) {
    Vector3D[] verts   = this.boundingPointsLocal;
    Vector3D polyNormal = this.getNormalLocal();
    Vector3D testPoint   = ToolsGeometry.getRayPlaneIntersection(ray, polyNormal, verts[0]);
    if (testPoint == null)
      return null;
   
    return (ToolsGeometry.isPoint3DInPlanarPolygon(verts, testPoint, polyNormal)? testPoint : null);
  }

 
  /**
   * Gets the normal local.
   *
   * @return the normal local
   */
  private Vector3D getNormalLocal() {
    return ToolsGeometry.getNormal(this.boundingPointsLocal[0], this.boundingPointsLocal[1], this.boundingPointsLocal[2], true);
  }

 
  public Vector3D[] getVectorsLocal() {
    return this.boundingPointsLocal;
  }


  public Vector3D[] getVectorsGlobal() {
    if (this.worldVecsDirty){
      Vector3D[] vecs = Vector3D.getDeepVertexArrayCopy(this.boundingPointsLocal);
      Vector3D.transFormArrayLocal(this.peerComponent.getGlobalMatrix(), vecs);
      this.worldVecs = vecs;
      this.worldVecsDirty = false;
      return this.worldVecs;
    }else{
      return this.worldVecs;
    }
  }


  public boolean containsPointLocal(Vector3D testPoint) {
    return ToolsGeometry.isPolygonContainsPoint(this.getVectorsLocal(), testPoint);
  }


  public float getHeightXY(TransformSpace transformSpace) {
    switch (transformSpace) {
    case LOCAL:
      return this.getHeightXYObjSpace();
    case RELATIVE_TO_PARENT:
      return this.getHeightXYRelativeToParent();
    case GLOBAL:
      return this.getHeightXYGlobal();
    default:
      return -1;
    }
  }


  /**
   * Gets the height xy obj space.
   *
   * @return the height xy obj space
   */
  private float getHeightXYObjSpace() {
    return this.getHeightXYVectLocal().length();
  }

  /**
   * Gets the "height vector" and transforms it to parent relative space, then calculates
   * its length.
   *
   * @return the height xy relative to parent
   *
   * the height relative to its peer components parent frame of reference
   */
  private float getHeightXYRelativeToParent() {
    Vector3D p = this.getHeightXYVectLocal();
    Matrix m = new Matrix(this.peerComponent.getLocalMatrix());
    m.removeTranslationFromMatrix();
    p.transform(m);
    return p.length();
   
//    Vector3D[] v = xyBoundsRect.getVectorsRelativeToParent();
//    float[] minMax = ToolsGeometry.getMinXYMaxXY(v);
//    return minMax[3] - minMax[1];
  }


  /**
   * Gets the "height vector" and transforms it to world space, then calculates
   * its length.
   *
   * @return the height xy global
   *
   * the height relative to the world space
   */
  private float getHeightXYGlobal() {
    Vector3D p = this.getHeightXYVectLocal();
    Matrix m = new Matrix(this.peerComponent.getGlobalMatrix());
    m.removeTranslationFromMatrix();
    p.transform(m);
    return p.length();
   
//    Vector3D[] v = xyBoundsRect.getVectorsGlobal();
//    float[] minMax = ToolsGeometry.getMinXYMaxXY(v);
//    return minMax[3] - minMax[1];
  }

  /**
   * Gets the "height vector". The vector is calculated from the bounds vectors,
   * representing a vector with the height as its length in object space.
   *
   * @return the height xy vect obj space
   *
   * vector representing the height of the boundingshape of the shape
   */
  public Vector3D getHeightXYVectLocal() {
    return this.xyBoundsRect.getHeightXYVectLocal();
  }


  public float getWidthXY(TransformSpace transformSpace) {
    switch (transformSpace) {
    case LOCAL:
      return this.getWidthXYObjSpace();
    case RELATIVE_TO_PARENT:
      return this.getWidthXYRealtiveToParent();
    case GLOBAL:
      return this.getWidthXYGlobal();
    default:
      return -1;
    }
  }


  /**
   * Gets the width xy obj space.
   *
   * @return the width xy obj space
   */
  private float getWidthXYObjSpace() {
    return this.getWidthXYVectLocal().length();
  }


  /**
   * Calculates the width of this shape, by using the
   * bounding shapes vectors.
   * Uses the objects local transform. So the width will be
   * relative to the parent only - not the whole world
   *
   * @return the width xy realtive to parent
   *
   * the width
   */
  private float getWidthXYRealtiveToParent() {
    Vector3D p = this.getWidthXYVectLocal();
    Matrix m = new Matrix(this.peerComponent.getLocalMatrix());
    m.removeTranslationFromMatrix();
    p.transform(m);
    return p.length();
   
//    Vector3D[] v = xyBoundsRect.getVectorsRelativeToParent();
//    float[] minMax = ToolsGeometry.getMinXYMaxXY(v);
//    return minMax[2] - minMax[0];
  }
 

  /**
   * Gets the "Width vector" and transforms it to world space, then calculates
   * its length.
   *
   * @return the width xy global
   *
   * the Width relative to the world space
   */
  private float getWidthXYGlobal() {
    Vector3D p = this.getWidthXYVectLocal();
    Matrix m = new Matrix(this.peerComponent.getGlobalMatrix());
    m.removeTranslationFromMatrix();
    p.transform(m);
    return p.length();
   
//    Vector3D[] v = xyBoundsRect.getVectorsGlobal();
//    float[] minMax = ToolsGeometry.getMinXYMaxXY(v);
//    return minMax[2] - minMax[0];
  }

  /**
   * Gets the "Width vector". The vector is calculated from the bounds vectors,
   * representing a vector with the Width as its length in object space.
   *
   * @return the width xy vect obj space
   *
   * vector representing the Width of the boundingshape of the shape
   */
  public Vector3D getWidthXYVectLocal() {
    return this.xyBoundsRect.getWidthXYVectLocal();
  }


  //@Override
  public boolean isContainedInFrustum(IFrustum frustum) {
    Vector3D[] points = this.getVectorsGlobal();
    for (int i = 0; i < points.length; i++) {
      Vector3D vector3D = points[i];
      int test = frustum.isPointInFrustum(vector3D);
      if (   test == IFrustum.INSIDE
        || test == IFrustum.INTERSECT
      ){
        return true;
      }
    }
    return false;
  }

 

}
TOP

Related Classes of org.mt4j.components.bounds.BoundsArbitraryPlanarPolygon

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.