//============================================================================
//
// This file is part of the 'reorientmeshfaces' project.
//
// This software is covered by the following BSD license, except for portions
// derived from other works which are covered by their respective licenses.
// For full licensing information including reproduction of these external
// licenses, see the file LICENSE.txt provided in the documentation.
//
// Copyright (c) 2015, Evangelos Kalogerakis, UMass Amherst
//
// 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 the copyright holders nor the names of contributors
// to this software 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 HOLDERS 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.
//
//============================================================================

#ifndef __DEF_POINTFEATUREEXPORTER_H
#define __DEF_POINTFEATUREEXPORTER_H

#include "helper.h"


struct NamedPoint
{
  Vector3 position;
	size_t  id;

	NamedPoint() {}
  NamedPoint(float x, float y, float z) 
	{
		position = Vector3(x, y, z);
	}
  NamedPoint(float x, float y, float z, const size_t _id) 
	{
		id = _id;
		position = Vector3(x, y, z);
	}
};

namespace Thea {
	template <>
	struct PointTraits3<NamedPoint>
	{
		static Vector3 const & getPosition(NamedPoint const & np) { return np.position; }
	};

	template <>
	struct IsPoint3<NamedPoint>
	{
		static bool const value = true;
	};
}

struct MyCustomTriangleVertexTriple
{
	size_t id;
  Vector3 v[3];

  MyCustomTriangleVertexTriple() {}
  MyCustomTriangleVertexTriple(Vector3 const & v0_, Vector3 const & v1_, Vector3 const & v2_, size_t _id)
  {
    v[0] = v0_;
    v[1] = v1_;
    v[2] = v2_;
		id = _id;
  }
  MyCustomTriangleVertexTriple(MyCustomTriangleVertexTriple const & src)
  {
    v[0] = src.v[0];
    v[1] = src.v[1];
    v[2] = src.v[2];
		id = src.id;
  }

  // Get the i'th vertex. This is the operative function that a vertex triple needs to have.
  Vector3 const & getVertex(int i) const { return v[i]; }
};

typedef Triangle3<MyCustomTriangleVertexTriple> MyCustomTriangle;
typedef KDTree3<NamedPoint> PKDTree;
typedef KDTree3<MyCustomTriangle> TKDTree;

typedef boost::property<boost::edge_weight_t, float> EdgeProperty;
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, boost::no_property, EdgeProperty> ProximityGraph;



class Mesh
{
private:	
	vector<MyCustomTriangle> triangles;    // list of triangles for ray-triangle intersections	
	TKDTree* tree;												 // kdtree for ray-triangle intersection
  float rayShoot(vec& line, point& origin, float limdist);    // shoot a ray from origin (of face f) with direction line, returns ray segment length (-1 if no intersection)

public:
  TriMesh *mesh;
  Mesh(const string& filename, bool add_faces = true, bool do_nothing = false);
  bool valid() { return mesh != NULL;  }
	void write(const string& filename);
};



#endif
