dgBigVector LineTriangleIntersection (const dgBigVector& p0, const dgBigVector& p1, const dgBigVector& A, const dgBigVector& B, const dgBigVector& C)
{
	dgHugeVector ph0 (p0);
	dgHugeVector ph1 (p1);
	dgHugeVector Ah (A);
	dgHugeVector Bh (B);
	dgHugeVector Ch (C);

	dgHugeVector p1p0 (ph1 - ph0);
	dgHugeVector Ap0 (Ah - ph0);
	dgHugeVector Bp0 (Bh - ph0);
	dgHugeVector Cp0 (Ch - ph0);

	dgGoogol t0 ((Bp0 * Cp0) % p1p0);
	//hacd::HaF64 val0 = t0.GetAproximateValue();	
	//if (val0 < hacd::HaF64 (0.0f)) {
	if (hacd::HaF64(t0) < hacd::HaF64(0.0f)) {
		return dgBigVector (hacd::HaF32 (0.0f), hacd::HaF32 (0.0f), hacd::HaF32 (0.0f), hacd::HaF32 (-1.0f));
	}

	dgGoogol t1 ((Cp0 * Ap0) % p1p0);
//	hacd::HaF64 val1 = t1.GetAproximateValue();	
//	if (val1 < hacd::HaF64 (0.0f)) {
	if (hacd::HaF64 (t1) < hacd::HaF64 (0.0f)) {
		return dgBigVector (hacd::HaF32 (0.0f), hacd::HaF32 (0.0f), hacd::HaF32 (0.0f), hacd::HaF32 (-1.0f));
	}

	dgGoogol t2 ((Ap0 * Bp0) % p1p0);
	//hacd::HaF64 val2 = t2.GetAproximateValue();	
	//if (val2 < hacd::HaF64 (0.0f)) {
	if (hacd::HaF64 (t2) < hacd::HaF64 (0.0f)) {
		return dgBigVector (hacd::HaF32 (0.0f), hacd::HaF32 (0.0f), hacd::HaF32 (0.0f), hacd::HaF32 (-1.0f));
	}

	dgGoogol sum = t0 + t1 + t2;
	//hacd::HaF64 den = sum.GetAproximateValue();

#ifdef _DEBUG
	//dgBigVector testpoint (A.Scale (val0 / den) + B.Scale (val1 / den) + C.Scale(val2 / den));
	dgBigVector testpoint (A.Scale (t0 / sum) + B.Scale (t1 / sum) + C.Scale(t2 / sum));
	hacd::HaF64 volume = ((B - A) * (C - A)) % (testpoint - A);
	HACD_ASSERT (fabs (volume) < hacd::HaF64 (1.0e-12f));
#endif
//	return dgBigVector (val0 / den, val1 / den, val2 / den, hacd::HaF32 (0.0f));
	return dgBigVector (t0 / sum, t1 / sum, t2 / sum, hacd::HaF32 (0.0f));
}
dgBigVector LineTriangleIntersection (const dgBigVector& p0, const dgBigVector& p1, const dgBigVector& A, const dgBigVector& B, const dgBigVector& C)
{
	dgHugeVector ph0 (p0);
	dgHugeVector ph1 (p1);
	dgHugeVector Ah (A);
	dgHugeVector Bh (B);
	dgHugeVector Ch (C);

	dgHugeVector p1p0 (ph1 - ph0);
	dgHugeVector Ap0 (Ah - ph0);
	dgHugeVector Bp0 (Bh - ph0);
	dgHugeVector Cp0 (Ch - ph0);

	dgGoogol t0 ((Bp0 * Cp0) % p1p0);
	dgFloat64 val0 = t0.GetAproximateValue();	
	if (val0 < dgFloat64 (0.0f)) {
		return dgBigVector (dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (-1.0f));
	}

	dgGoogol t1 ((Cp0 * Ap0) % p1p0);
	dgFloat64 val1 = t1.GetAproximateValue();	
	if (val1 < dgFloat64 (0.0f)) {
		return dgBigVector (dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (-1.0f));
	}

	dgGoogol t2 ((Ap0 * Bp0) % p1p0);
	dgFloat64 val2 = t2.GetAproximateValue();	
	if (val2 < dgFloat64 (0.0f)) {
		return dgBigVector (dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (-1.0f));
	}

	dgGoogol sum = t0 + t1 + t2;
	dgFloat64 den = sum.GetAproximateValue();

#ifdef _DEBUG
	dgBigVector testpoint (A.Scale (val0 / den) + B.Scale (val1 / den) + C.Scale(val2 / den));
	dgFloat64 volume = ((B - A) * (C - A)) % (testpoint - A);
	_ASSERTE (fabs (volume) < dgFloat64 (1.0e-12f));
#endif


	return dgBigVector (val0 / den, val1 / den, val2 / den, dgFloat32 (0.0f));
}
dgBigVector LineTriangleIntersection (const dgBigVector& p0, const dgBigVector& p1, const dgBigVector& A, const dgBigVector& B, const dgBigVector& C)
{
	dgHugeVector ph0 (p0);
	dgHugeVector ph1 (p1);
	dgHugeVector Ah (A);
	dgHugeVector Bh (B);
	dgHugeVector Ch (C);

	dgHugeVector p1p0 (ph1 - ph0);
	dgHugeVector Ap0 (Ah - ph0);
	dgHugeVector Bp0 (Bh - ph0);
	dgHugeVector Cp0 (Ch - ph0);

	dgGoogol t0 ((Bp0 * Cp0) % p1p0);
	double val0 = t0.GetAproximateValue();	
	if (val0 < double (0.0f)) {
		return dgBigVector (float (0.0f), float (0.0f), float (0.0f), float (-1.0f));
	}

	dgGoogol t1 ((Cp0 * Ap0) % p1p0);
	double val1 = t1.GetAproximateValue();	
	if (val1 < double (0.0f)) {
		return dgBigVector (float (0.0f), float (0.0f), float (0.0f), float (-1.0f));
	}

	dgGoogol t2 ((Ap0 * Bp0) % p1p0);
	double val2 = t2.GetAproximateValue();	
	if (val2 < double (0.0f)) {
		return dgBigVector (float (0.0f), float (0.0f), float (0.0f), float (-1.0f));
	}

	dgGoogol sum = t0 + t1 + t2;
	double den = sum.GetAproximateValue();

	return dgBigVector (val0 / den, val1 / den, val2 / den, float (0.0f));
}
void LineSurfaceTension :: computeTangent(FloatMatrix &answer, TimeStep *tStep)
{
#if 1
    ///@todo Not sure if it's a good idea to use this tangent.
    answer.resize(4,4);
    answer.zero();
#else
    domainType dt = this->giveDomain()->giveDomainType();
    int ndofs = this->computeNumberOfDofs(EID_MomentumBalance);
    Node *node1, *node2;
    double x1, x2, y1, y2, dx, dy, vx, vy, length, width, gamma_s;

    gamma_s = this->giveMaterial()->give('g',NULL);

    node1 = giveNode(1);
    node2 = giveNode(2);

    x1 = node1->giveCoordinate(1);
    x2 = node2->giveCoordinate(1);

    y1 = node1->giveCoordinate(2);
    y2 = node2->giveCoordinate(2);

    dx = x2-x1;
    dy = y2-y1;

    length = sqrt(dx*dx + dy*dy);

    vx = dx/length;
    vy = dy/length;

    FloatArray Ah(4);
    Ah.at(1) = -vx;
    Ah.at(2) = -vy;
    Ah.at(3) = vx;
    Ah.at(4) = vy;

    FloatMatrix NpTNp(4,4);
    NpTNp.zero();
    NpTNp.at(1,1) = 1;
    NpTNp.at(2,2) = 1;
    NpTNp.at(3,3) = 1;
    NpTNp.at(4,4) = 1;
    NpTNp.at(1,3) = -1;
    NpTNp.at(2,4) = -1;
    NpTNp.at(3,1) = -1;
    NpTNp.at(4,2) = -1;

    answer.resize(ndofs,ndofs);
    answer.zero();
    if (dt == _3dAxisymmMode) {
        OOFEM_WARNING("Not tested");
        FloatArray Bh(4);
        Bh.zero();
        Bh.at(1) = 1;
        Bh.at(3) = 1;

        // It was simpler to write this in index notation.
        // Also using 0-based, to reduce typing
        double rJinv = (x1+x2)/length;
        answer.zero();
        for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) {
            answer(i,j) = M_PI*(Ah(i)*Bh(j) + Bh(i)*Ah(j)+ rJinv*(NpTNp(i,j) - Ah(i)*Ah(j)));
        }
    }
    else {
        width = 1;
        answer.beDyadicProductOf(Ah,Ah);
        answer.add(NpTNp);
        answer.times(width/length);
    }

    answer.times(gamma_s);
#endif
}