/** @file ConvexHull.java * * @author marco corvi * @date nov 2014 * * @brief TopoDroid main 3d convex hull * -------------------------------------------------------- * Copyright This sowftare is distributed under GPL-3.0 or later * See the file COPYING. * -------------------------------------------------------- */ package com.topodroid.DistoX; import java.lang.Math; import java.util.ArrayList; // import java.util.Iterator; import android.util.Log; public class ConvexHull { private Vector mV1; // first base point private Vector mV2; // second base point private Vector mX; // X unit vector (mV2-mV1).normalized() private Vector mY; private Vector mZ; ArrayList< Vector > mPts; // other points ArrayList< Triangle > mTri; private class VectorPair { boolean valid; Vector mV1; Vector mV2; VectorPair( Vector v1, Vector v2 ) { valid = true; mV1 = v1; mV2 = v2; } } ConvexHull( Vector v1, Vector v2, ArrayList<Vector> pts ) { mV1 = v1; mV2 = v2; mPts = pts; mX = mV2.minus( mV1 ); mX.normalize(); if ( Math.abs( mX.z ) > Math.abs( mX.y ) ) { if ( Math.abs( mX.y ) > Math.abs( mX.x ) ) { mZ = new Vector( 1, 0, 0 ); } else { mZ = new Vector( 0, 1, 0 ); } } else { if ( Math.abs( mX.z ) > Math.abs( mX.x ) ) { mZ = new Vector( 1, 0, 0 ); } else { mZ = new Vector( 0, 0, 1 ); } } mY = mX.cross( mZ ); mY.normalize(); mZ = mX.cross( mY ); mZ.normalize(); // not really needed: should be normalized // first two triangles mV1-mV2-pmax mV2-mV1-p[0] // use temporary triangle array ArrayList<Triangle> tri = new ArrayList< Triangle >(); Vector p = (Vector) mPts.get(0); tri.add( new Triangle( mV1, mV2, p ) ); tri.add( new Triangle( mV2, mV1, p ) ); ArrayList< VectorPair > vp_to_add = new ArrayList< VectorPair >(); for ( int h = 1; h<mPts.size(); ++h ) { p = (Vector) mPts.get(h); vp_to_add.clear(); for ( Triangle t : tri ) { if ( ! t.valid ) continue; if ( t.signedDistance( p ) > 0 ) { vp_to_add.add( new VectorPair(t.mA, t.mB ) ); vp_to_add.add( new VectorPair(t.mB, t.mC ) ); vp_to_add.add( new VectorPair(t.mC, t.mA ) ); t.valid = false; } } // mark mirror vector-pairs invalid for ( int n1 = 0; n1 < vp_to_add.size(); ++n1 ) { VectorPair vp1 = (VectorPair) vp_to_add.get( n1 ); for ( int n2 = n1+1; n2 < vp_to_add.size(); ++n2 ) { VectorPair vp2 = (VectorPair) vp_to_add.get( n2 ); if ( vp1.mV1 == vp2.mV2 && vp1.mV2 == vp2.mV1 ) { vp1.valid = false; vp2.valid = false; break; } } } for ( VectorPair vp : vp_to_add ) { // ***** add new triangles if ( vp.valid ) { tri.add( new Triangle( vp.mV1, vp.mV2, p ) ); } } } mTri = new ArrayList<Triangle>(); // definitive triangle array list for ( Triangle t : tri ) { if ( t.valid ) mTri.add( t ) ; } } }