#include "StdAfx.h"
#include "CrossSectionConfig.h"



CrossSectionConfig::CrossSectionConfig(void)
{
	m_Enable = false;
	m_CutPosX = 0.5f;
	m_CutPosY = 0.5f;
	m_CutPosZ = 0.5f;

	m_Ribbon      = false;
	m_RibbonRange = 0.02f;

	m_LineCS = false;
	m_MultiColor = false;

	m_ShowCutplane = false;

	m_EnableConvexHull        = false;
	m_EnableShowLength        = false;
	m_EnableShowCHLength      = false;
	m_EnableCrossSectionGroup = true;

	m_Transparent = false;

	m_CutAngle = CutAngle::CUT_Y_FORE;
}

float CrossSectionConfig::GetCurrentAxisCutPos(void) const
{
	if (IsCutX())
		return m_CutPosX;
	if (IsCutY())
		return m_CutPosY;
	if (IsCutZ())
		return m_CutPosZ;

	assert(false);
	return 0.0f;
}

void CrossSectionConfig::ApplyClipPlaneAxis(float t, float b)
{
	GLdouble h = GetCutAxisHeightParam(t, b);

	if(m_Ribbon)
	{
		float r = t - b;
		GLdouble rr = (GLdouble)(r * 0.5 * m_RibbonRange);
		if (IsCutRev())
			rr *= -1.0f;

		glEnable(GL_CLIP_PLANE0);
		glEnable(GL_CLIP_PLANE1);
		SetAxisClipPlane(GL_CLIP_PLANE0, true, h + rr);
		SetAxisClipPlane(GL_CLIP_PLANE1, false, h - rr);
	}
	else
	{
		glEnable(GL_CLIP_PLANE0);
		SetAxisClipPlane(GL_CLIP_PLANE0, true, h);
	}
}

void CrossSectionConfig::ApplyCutPlaneAxis(float t, float b)
{
	GLdouble h = GetCutAxisHeightParam(t, b);

	glEnable(GL_CLIP_PLANE0);
	glEnable(GL_CLIP_PLANE1);
	SetAxisClipPlane(GL_CLIP_PLANE0, true, h);
	SetAxisClipPlane(GL_CLIP_PLANE1, false, h);
}

void CrossSectionConfig::ApplyClipPlane(const lm::vec3f& p, const lm::vec3f& n)
{
	lm::vec3f rn = n;
	if (IsCutRev())
		rn = -rn;

	float drn = dot(p, rn);
	glEnable(GL_CLIP_PLANE0);
	glClipPlaneFunc(GL_CLIP_PLANE0, rn.x, rn.y, rn.z, -drn);
}

void CrossSectionConfig::ApplyCutPlane(const lm::vec3f& p, const lm::vec3f& n)
{
	lm::vec3f rn = n;
	if (IsCutRev())
		rn = -rn;

	glEnable(GL_CLIP_PLANE0);
	glEnable(GL_CLIP_PLANE1);

	float drn = dot(p, rn);
	glClipPlaneFunc(GL_CLIP_PLANE0, rn.x, rn.y, rn.z, -drn);
	glClipPlaneFunc(GL_CLIP_PLANE1, -rn.x, -rn.y, -rn.z, drn);
}

float CrossSectionConfig::GetCutAxisHeightParam(float t, float b) const
{
	return (GLdouble)(b + (t - b) * GetCurrentAxisCutPos());
}

void CrossSectionConfig::DisableGLClipPlane(void)
{
	glDisable(GL_CLIP_PLANE0);
	glDisable(GL_CLIP_PLANE1);
}

void CrossSectionConfig::SetAxisClipPlane(GLenum plane, bool bFore, GLdouble height)
{
	bool CutFore = bFore;
	if (!IsCutFore())
		CutFore = !CutFore;
	
	if (IsCutX())
		return glClipPlaneFuncX(plane, CutFore, height);
	if (IsCutY())
		return glClipPlaneFuncY(plane, CutFore, height);
	if (IsCutZ())
		return glClipPlaneFuncZ(plane, CutFore, height);

	assert(false);
}

lm::vec3f CrossSectionConfig::GetCutAxis(void) const
{
	if (IsCutX())
		return lm::vec3f(1.0f, 0.0f, 0.0f);
	if (IsCutY())
		return lm::vec3f(0.0f, 1.0f, 0.0f);
	if (IsCutZ())
		return lm::vec3f(0.0f, 0.0f, 1.0f);

	assert(false);
	return lm::vec3f();
}


bool CrossSectionConfig::IsCutFore(void) const
{
	switch(m_CutAngle)
	{
	case CutAngle::CUT_X_FORE:
	case CutAngle::CUT_Y_FORE:
	case CutAngle::CUT_Z_FORE:
		return true;
	default:
		return false;
	}
}

bool CrossSectionConfig::IsCutRev(void) const
{
	switch(m_CutAngle)
	{
	case CutAngle::CUT_X_REV:
	case CutAngle::CUT_Y_REV:
	case CutAngle::CUT_Z_REV:
		return true;
	default:
		return false;
	}
}

bool CrossSectionConfig::IsCutX(void) const
{
	return (m_CutAngle == CutAngle::CUT_X_FORE || m_CutAngle == CutAngle::CUT_X_REV);
}

bool CrossSectionConfig::IsCutY(void) const
{
	return (m_CutAngle == CutAngle::CUT_Y_FORE || m_CutAngle == CutAngle::CUT_Y_REV);
}

bool CrossSectionConfig::IsCutZ(void) const
{
	return (m_CutAngle == CutAngle::CUT_Z_FORE || m_CutAngle == CutAngle::CUT_Z_REV);
}

bool CrossSectionConfig::IsFreeCut(void) const
{
	return (m_CutAngle == CutAngle::CUT_FREE);
}


bool CrossSectionConfig::IsRequireUpdateCS(void) const
{
	if (m_EnableShowLength)
		return true;

	if (m_EnableShowCHLength)
		return true;

	if (m_EnableConvexHull)
		return true;

	return false;
}

void CrossSectionConfig::GetCutPlane(const lm::range3f& tb, lib_geo::Plane& cutplane) const
{
	GetCutPlaneFromXYZParam(tb, cutplane);
}

void CrossSectionConfig::GetCutPlaneFromXYZParam(const lm::range3f& tb, lib_geo::Plane& cutplane) const
{
	lm::vec3f ax = GetCutAxis();

	const lm::vec3f& vt = tb.max_point();
	const lm::vec3f& vb = tb.min_point();

	float t = dot(vt, ax);
	float b = dot(vb, ax);

	float cutpos = GetCurrentAxisCutPos();
	float param = GetCurrentAxisCutPos();

	cutplane.normal = GetCutAxis();
	cutplane.origin = vb + (vt - vb) * param;
}
