예제 #1
0
/*!
Compute a point on the line from a parameter in [0,1] interval, where 0 is the begin and 1 is the end
of the line

\param theSection
Line section to use for point computation

\return
Point on the line at the section theSectio, return an invalid point if the line is invalid or theSection is
out of range
*/
GM_3dPoint GM_3dLine::pointFromSection(double theSection) const {
	GM_3dPoint ret;
	if (!isValid() || theSection < -GM_DIFF_TOLERANCE || theSection > 1.0 + GM_DIFF_TOLERANCE) {
		return ret;
	}
	if (theSection < 0.0) {
		theSection = 0.0;
	}
	if (theSection > 1.0) {
		theSection = 1.0;
	}

	theSection *= length();

	GM_3dVector lineDir(dx(), dy(), dz());
	lineDir.normalize();
	ret = (GM_3dVector)mBegin + (lineDir * theSection);

	return ret;
}
예제 #2
0
/*!
From a point on the line compute the section on the line corrisponding to the specified point, the section
is in [0,1] interval, where 0 is the begin and 1 is the end of the line.

\param thePoint
Point on the line to use for section computation

\return
Section of the line computed from thePoint, 0 = begin 1 = end, return -DBL_MAX if the line or thePoinr are
not valid or if thePoint is not on the line
*/
double GM_3dLine::sectionFromPoint(GM_3dPoint thePoint) const {
	double ret = -DBL_MAX;
	if (!isValid() || !thePoint.isValid())
		return ret;

	GM_3dVector lineDir(dx(), dy(), dz());
	lineDir.normalize();
	GM_3dVector pointDir(thePoint.x() - mBegin.x(), thePoint.y() - mBegin.y(), thePoint.z() - mBegin.z());
	pointDir.normalize();

	if (fabs((lineDir * pointDir) - 1.0) < GM_DIFF_TOLERANCE) {
		double distFromBegin = thePoint.distFrom(mBegin);
		double distFromEnd = thePoint.distFrom(mEnd);
		double lineLen = length();
		if (fabs(distFromBegin + distFromEnd - lineLen) < GM_DIFF_TOLERANCE) {
			ret = distFromBegin / lineLen;
		}
	}

	return ret;
}
dgInt32 dgCollisionConvexPolygon::CalculatePlaneIntersection (const dgVector& normalIn, const dgVector& origin, dgVector* const contactsOut, dgFloat32 normalSign) const
{
    dgVector normal(normalIn);
    dgInt32 count = 0;
    dgFloat32 maxDist = dgFloat32 (1.0f);
    dgFloat32 projectFactor = m_normal % normal;
    if (projectFactor < dgFloat32 (0.0f)) {
        projectFactor *= dgFloat32 (-1.0f);
        normal = normal.Scale3 (dgFloat32 (-1.0f));
    }

    if (projectFactor > dgFloat32 (0.9999f)) {
        for (dgInt32 i = 0; i < m_count; i ++) {
            contactsOut[count] = m_localPoly[i];
            count ++;
        }

#ifdef _DEBUG
        dgInt32 j = count - 1;
        for (dgInt32 i = 0; i < count; i ++) {
            dgVector error (contactsOut[i] - contactsOut[j]);
            dgAssert ((error % error) > dgFloat32 (1.0e-20f));
            j = i;
        }
#endif

    } else if (projectFactor > dgFloat32 (0.1736f)) {
        maxDist = dgFloat32 (0.0f);
        dgPlane plane (normal, - (normal % origin));

        dgVector p0 (m_localPoly[m_count - 1]);
        dgFloat32 side0 = plane.Evalue (p0);
        for (dgInt32 i = 0; i < m_count; i ++) {
            dgVector p1 (m_localPoly[i]);
            dgFloat32 side1 = plane.Evalue (p1);

            if (side0 > dgFloat32 (0.0f)) {
                maxDist = dgMax (maxDist, side0);
                contactsOut[count] = p0 - plane.Scale3 (side0);
                count ++;
                if (count > 1) {
                    dgVector edgeSegment (contactsOut[count - 1] - contactsOut[count - 2]);
                    dgFloat32 error = edgeSegment % edgeSegment;
                    if (error < dgFloat32 (1.0e-8f)) {
                        count --;
                    }
                }

                if (side1 <= dgFloat32 (0.0f)) {
                    dgVector dp (p1 - p0);
                    dgFloat32 t = plane % dp;
                    dgAssert (dgAbsf (t) >= dgFloat32 (0.0f));
                    if (dgAbsf (t) < dgFloat32 (1.0e-8f)) {
                        t = dgSign(t) * dgFloat32 (1.0e-8f);
                    }
                    contactsOut[count] = p0 - dp.Scale3 (side0 / t);
                    count ++;
                    if (count > 1) {
                        dgVector edgeSegment (contactsOut[count - 1] - contactsOut[count - 2]);
                        dgFloat32 error = edgeSegment % edgeSegment;
                        if (error < dgFloat32 (1.0e-8f)) {
                            count --;
                        }
                    }
                }
            } else if (side1 > dgFloat32 (0.0f)) {
                dgVector dp (p1 - p0);
                dgFloat32 t = plane % dp;
                dgAssert (dgAbsf (t) >= dgFloat32 (0.0f));
                if (dgAbsf (t) < dgFloat32 (1.0e-8f)) {
                    t = dgSign(t) * dgFloat32 (1.0e-8f);
                }
                contactsOut[count] = p0 - dp.Scale3 (side0 / t);
                count ++;
                if (count > 1) {
                    dgVector edgeSegment (contactsOut[count - 1] - contactsOut[count - 2]);
                    dgFloat32 error = edgeSegment % edgeSegment;
                    if (error < dgFloat32 (1.0e-8f)) {
                        count --;
                    }
                }
            }

            side0 = side1;
            p0 = p1;
        }
    } else {
        maxDist = dgFloat32 (1.0e10f);
        dgPlane plane (normal, - (normal % origin));

        dgVector p0 (m_localPoly[m_count - 1]);
        dgFloat32 side0 = plane.Evalue (p0);
        for (dgInt32 i = 0; i < m_count; i ++) {
            dgVector p1 (m_localPoly[i]);
            dgFloat32 side1 = plane.Evalue (p1);

            if ((side0 * side1) < dgFloat32 (0.0f)) {
                dgVector dp (p1 - p0);
                dgFloat32 t = plane % dp;
                dgAssert (dgAbsf (t) >= dgFloat32 (0.0f));
                if (dgAbsf (t) < dgFloat32 (1.0e-8f)) {
                    t = dgSign(t) * dgFloat32 (1.0e-8f);
                }
                contactsOut[count] = p0 - dp.Scale3 (side0 / t);
                count ++;
                if (count > 1) {
                    dgVector edgeSegment (contactsOut[count - 1] - contactsOut[count - 2]);
                    dgFloat32 error = edgeSegment % edgeSegment;
                    if (error < dgFloat32 (1.0e-8f)) {
                        count --;
                    }
                }
            }
            side0 = side1;
            p0 = p1;
        }
    }


    if (count > 1) {
        if (maxDist < dgFloat32 (1.0e-3f)) {
            dgVector maxPoint (contactsOut[0]);
            dgVector minPoint (contactsOut[0]);
            dgVector lineDir (m_normal * normal);

            dgFloat32 proj = contactsOut[0] % lineDir;
            dgFloat32 maxProjection = proj;
            dgFloat32 minProjection = proj;
            for (dgInt32 i = 1; i < count; i ++) {
                proj = contactsOut[i] % lineDir;
                if (proj > maxProjection) {
                    maxProjection = proj;
                    maxPoint = contactsOut[i];
                }
                if (proj < minProjection) {
                    minProjection = proj;
                    minPoint = contactsOut[i];
                }
            }

            contactsOut[0] = maxPoint;
            contactsOut[1] = minPoint;
            count = 2;
        }


        dgVector error (contactsOut[count - 1] - contactsOut[0]);
        if ((error % error) < dgFloat32 (1.0e-8f)) {
            count --;
        }
    }

#ifdef _DEBUG
    if (count > 1) {
        dgInt32 j = count - 1;
        for (dgInt32 i = 0; i < count; i ++) {
            dgVector error (contactsOut[i] - contactsOut[j]);
            dgAssert ((error % error) > dgFloat32 (1.0e-20f));
            j = i;
        }

        if (count >= 3) {
            dgVector n (dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f));
            dgVector e0 (contactsOut[1] - contactsOut[0]);
            for (dgInt32 i = 2; i < count; i ++) {
                dgVector e1 (contactsOut[i] - contactsOut[0]);
                n += e0 * e1;
                e0 = e1;
            }
            n = n.Scale3 (dgRsqrt(n % n));
            dgFloat32 val = n % normal;
            dgAssert (val > dgFloat32 (0.9f));
        }
    }
#endif
    return count;
}