Esempio n. 1
0
bool ICHull::CleanVertices(unsigned int& addedPoints)
{
    // mark all vertices incident to some undeleted edge as on the hull
    CircularList<TMMEdge>& edges = m_mesh.GetEdges();
    CircularListElement<TMMEdge>* e = edges.GetHead();
    size_t nE = edges.GetSize();
    for (size_t i = 0; i < nE; i++) {
        e->GetData().m_vertices[0]->GetData().m_onHull = true;
        e->GetData().m_vertices[1]->GetData().m_onHull = true;
        e = e->GetNext();
    }
    // delete all the vertices that have been processed but are not on the hull
    CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
    CircularListElement<TMMVertex>* vHead = vertices.GetHead();
    CircularListElement<TMMVertex>* v = vHead;
    v = v->GetPrev();
    do {
        if (v->GetData().m_tag && !v->GetData().m_onHull) {
            CircularListElement<TMMVertex>* tmp = v->GetPrev();
            vertices.Delete(v);
            v = tmp;
            addedPoints--;
        }
        else {
            v->GetData().m_duplicate = 0;
            v->GetData().m_onHull = false;
            v = v->GetPrev();
        }
    } while (v->GetData().m_tag && v != vHead);
    return true;
}
Esempio n. 2
0
bool ICHull::ProcessPoint()
{
    double totalVolume = 0.0;
    if (!ComputePointVolume(totalVolume, true)) {
        return false;
    }
    // Mark edges in interior of visible region for deletion.
    // Create a new face based on each border edge
    CircularListElement<TMMVertex>* v0 = m_mesh.GetVertices().GetHead();
    CircularListElement<TMMEdge>* eHead = m_mesh.GetEdges().GetHead();
    CircularListElement<TMMEdge>* e = eHead;
    CircularListElement<TMMEdge>* tmp = 0;
    int nvisible = 0;
    m_edgesToDelete.Resize(0);
    m_edgesToUpdate.Resize(0);
    do {
        tmp = e->GetNext();
        nvisible = 0;
        for (int k = 0; k < 2; k++) {
            if (e->GetData().m_triangles[k]->GetData().m_visible) {
                nvisible++;
            }
        }
        if (nvisible == 2) {
            m_edgesToDelete.PushBack(e);
        }
        else if (nvisible == 1) {
            e->GetData().m_newFace = MakeConeFace(e, v0);
            m_edgesToUpdate.PushBack(e);
        }
        e = tmp;
    } while (e != eHead);
    return true;
}
Esempio n. 3
0
bool ICHull::FindMaxVolumePoint(const double minVolume)
{
    CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
    CircularListElement<TMMVertex>* vMaxVolume = 0;
    CircularListElement<TMMVertex>* vHeadPrev = vertices.GetHead()->GetPrev();

    double maxVolume = minVolume;
    double volume = 0.0;
    while (!vertices.GetData().m_tag) // not processed
    {
        if (ComputePointVolume(volume, false)) {
            if (maxVolume < volume) {
                maxVolume = volume;
                vMaxVolume = vertices.GetHead();
            }
            vertices.Next();
        }
    }
    CircularListElement<TMMVertex>* vHead = vHeadPrev->GetNext();
    vertices.GetHead() = vHead;
    if (!vMaxVolume) {
        return false;
    }
    if (vMaxVolume != vHead) {
        Vec3<double> pos = vHead->GetData().m_pos;
        int id = vHead->GetData().m_name;
        vHead->GetData().m_pos = vMaxVolume->GetData().m_pos;
        vHead->GetData().m_name = vMaxVolume->GetData().m_name;
        vMaxVolume->GetData().m_pos = pos;
        vHead->GetData().m_name = id;
    }
    return true;
}
Esempio n. 4
0
bool ICHull::ComputePointVolume(double& totalVolume, bool markVisibleFaces)
{
	// mark visible faces
	CircularListElement<TMMTriangle>* fHead = m_mesh.GetTriangles().GetHead();
	CircularListElement<TMMTriangle>* f = fHead;
	CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
	CircularListElement<TMMVertex>* vertex0 = vertices.GetHead();
	bool visible = false;
	Vec3<double> pos0 = Vec3<double>(vertex0->GetData().m_pos.X(),
									 vertex0->GetData().m_pos.Y(),
									 vertex0->GetData().m_pos.Z());
	double vol = 0.0;
	totalVolume = 0.0;
	Vec3<double> ver0, ver1, ver2;
	do
	{
		ver0.X() = f->GetData().m_vertices[0]->GetData().m_pos.X();
		ver0.Y() = f->GetData().m_vertices[0]->GetData().m_pos.Y();
		ver0.Z() = f->GetData().m_vertices[0]->GetData().m_pos.Z();
		ver1.X() = f->GetData().m_vertices[1]->GetData().m_pos.X();
		ver1.Y() = f->GetData().m_vertices[1]->GetData().m_pos.Y();
		ver1.Z() = f->GetData().m_vertices[1]->GetData().m_pos.Z();
		ver2.X() = f->GetData().m_vertices[2]->GetData().m_pos.X();
		ver2.Y() = f->GetData().m_vertices[2]->GetData().m_pos.Y();
		ver2.Z() = f->GetData().m_vertices[2]->GetData().m_pos.Z();
		vol = ComputeVolume4(ver0, ver1, ver2, pos0);
		if (vol < -sc_eps)
		{
			vol = fabs(vol);
			totalVolume += vol;
			if (markVisibleFaces)
			{
				f->GetData().m_visible = true;
				m_trianglesToDelete.PushBack(f);
			}
			visible = true;
		}
		f = f->GetNext();
	} while (f != fHead);

	if (m_trianglesToDelete.Size() == m_mesh.m_triangles.GetSize())
	{
		for (size_t i = 0; i < m_trianglesToDelete.Size(); i++)
		{
			m_trianglesToDelete[i]->GetData().m_visible = false;
		}
		visible = false;
	}
	// if no faces visible from p then p is inside the hull
	if (!visible && markVisibleFaces)
	{
		vertices.Delete();
		m_trianglesToDelete.Resize(0);
		return false;
	}
	return true;
}
Esempio n. 5
0
ICHullError ICHull::DoubleTriangle()
{
    // find three non colinear points
    m_isFlat = false;
    CircularList<TMMVertex>& vertices = m_mesh.GetVertices();
    CircularListElement<TMMVertex>* v0 = vertices.GetHead();
    while (Colinear(v0->GetData().m_pos,
        v0->GetNext()->GetData().m_pos,
        v0->GetNext()->GetNext()->GetData().m_pos)) {
        if ((v0 = v0->GetNext()) == vertices.GetHead()) {
            return ICHullErrorCoplanarPoints;
        }
    }
    CircularListElement<TMMVertex>* v1 = v0->GetNext();
    CircularListElement<TMMVertex>* v2 = v1->GetNext();
    // mark points as processed
    v0->GetData().m_tag = v1->GetData().m_tag = v2->GetData().m_tag = true;

    // create two triangles
    CircularListElement<TMMTriangle>* f0 = MakeFace(v0, v1, v2, 0);
    MakeFace(v2, v1, v0, f0);

    // find a fourth non-coplanar point to form tetrahedron
    CircularListElement<TMMVertex>* v3 = v2->GetNext();
    vertices.GetHead() = v3;

    double vol = ComputeVolume4(v0->GetData().m_pos, v1->GetData().m_pos, v2->GetData().m_pos, v3->GetData().m_pos);
    while (fabs(vol) < sc_eps && !v3->GetNext()->GetData().m_tag) {
        v3 = v3->GetNext();
        vol = ComputeVolume4(v0->GetData().m_pos, v1->GetData().m_pos, v2->GetData().m_pos, v3->GetData().m_pos);
    }
    if (fabs(vol) < sc_eps) {
        // compute the barycenter
        Vec3<double> bary(0.0, 0.0, 0.0);
        CircularListElement<TMMVertex>* vBary = v0;
        do {
            bary += vBary->GetData().m_pos;
        } while ((vBary = vBary->GetNext()) != v0);
        bary /= static_cast<double>(vertices.GetSize());

        // Compute the normal to the plane
        Vec3<double> p0 = v0->GetData().m_pos;
        Vec3<double> p1 = v1->GetData().m_pos;
        Vec3<double> p2 = v2->GetData().m_pos;
        m_normal = (p1 - p0) ^ (p2 - p0);
        m_normal.Normalize();
        // add dummy vertex placed at (bary + normal)
        vertices.GetHead() = v2;
        Vec3<double> newPt = bary + m_normal;
        AddPoint(newPt, sc_dummyIndex);
        m_isFlat = true;
        return ICHullErrorOK;
    }
    else if (v3 != vertices.GetHead()) {
        TMMVertex temp;
        temp.m_name = v3->GetData().m_name;
        temp.m_pos = v3->GetData().m_pos;
        v3->GetData().m_name = vertices.GetHead()->GetData().m_name;
        v3->GetData().m_pos = vertices.GetHead()->GetData().m_pos;
        vertices.GetHead()->GetData().m_name = temp.m_name;
        vertices.GetHead()->GetData().m_pos = temp.m_pos;
    }
    return ICHullErrorOK;
}