Exemplo n.º 1
0
//----------------------------------------------------------------------------
int BspTree2::CoPointLocation (const BspPolygon2& polygon,
    const Vector2d& vertex) const
{
    // For numerical round-off error handling.
    const double epsilon = 0.00001;

    const int numEdges = (int)mCoincident.size();
    for (int i = 0; i < numEdges; ++i)
    {
        Vector2d end0 = polygon.mVArray[mCoincident[i].I0];
        Vector2d end1 = polygon.mVArray[mCoincident[i].I1];
        Vector2d dir = end1 - end0;
        Vector2d diff = vertex - end0;
        double tmax = dir.Dot(dir);
        double t = dir.Dot(diff);

        if (-epsilon <= t && t <= tmax + epsilon)
        {
            return 0;
        }
    }

    // Does not matter which subtree you use.
    if (mPosChild)
    {
        return mPosChild->PointLocation(polygon, vertex);
    }

    if (mNegChild)
    {
        return mNegChild->PointLocation(polygon, vertex);
    }

    return 0;
}
Exemplo n.º 2
0
	IShape* CreateLine(Vector2d p1, Vector2d p2, int r, int g, int b, int size) {
		sf::RectangleShape* rect = new sf::RectangleShape(sf::Vector2f(p1.x, p1.y));
		rect->setPosition(sf::Vector2f(p1.x, p1.y));
		float len = (p1-p2).Len();
		rect->setSize(sf::Vector2f(len, size));

		Vector2d target = p2-p1;
		Vector2d orig = p1; orig.x = int(len); orig.y = 0;
		orig = orig.GetNormalized();
		target = target.GetNormalized();
		float dot = target.Dot(orig);
		//float angle = atan2f(target.y-orig.y, target.x-orig.x) * 57.2957795;
		float angle = acos(dot) * 57.2957795;
		if(p1.y > p2.y)
			angle = -angle;

		rect->rotate(angle);
		SFMLShape * shape = new SFMLShape(rect);
		rect->setFillColor(sf::Color(r,g,b));

		return shape;
	}
Exemplo n.º 3
0
//----------------------------------------------------------------------------
int BspTree2::Classify (const Vector2d& end0, const Vector2d& end1,
    const Vector2d& vertex) const
{
    // For numerical round-off error handling.
    const double epsilon = 0.00001;

    Vector2d dir = end1 - end0;
    Vector2d nor = dir.Perp();
    Vector2d diff = vertex - end0;
    double c = nor.Dot(diff);

    if (c > epsilon)
    {
        return ALL_POSITIVE;
    }

    if (c < -epsilon)
    {
        return ALL_NEGATIVE;
    }

    return COINCIDENT;
}
Exemplo n.º 4
0
//----------------------------------------------------------------------------
void BspTree2::GetCoPartition (const BspPolygon2& polygon, const Vector2d& v0,
    const Vector2d& v1, BspPolygon2& pos, BspPolygon2& neg,
    BspPolygon2& coSame, BspPolygon2& coDiff) const
{
    const double epsilon = 0.00001;

    // Segment the line containing V0 and V1 by the coincident intervals that
    // intersect <V0,V1>.
    Vector2d dir = v1 - v0;
    double tmax = dir.Dot(dir);

    Vector2d end0, end1;
    double t0, t1;
    bool sameDir;

    std::list<Interval> intervalList;
    std::list<Interval>::iterator iter;

    const int numEdges = (int)mCoincident.size();
    for (int i = 0; i < numEdges; ++i)
    {
        end0 = polygon.mVArray[mCoincident[i].I0];
        end1 = polygon.mVArray[mCoincident[i].I1];

        t0 = dir.Dot(end0 - v0);
        if (Mathd::FAbs(t0) <= epsilon)
        {
            t0 = 0.0;
        }
        else if (Mathd::FAbs(t0 - tmax) <= epsilon)
        {
            t0 = tmax;
        }

        t1 = dir.Dot(end1 - v0);
        if (Mathd::FAbs(t1) <= epsilon)
        {
            t1 = 0.0;
        }
        else if (Mathd::FAbs(t1 - tmax) <= epsilon)
        {
            t1 = tmax;
        }

        sameDir = (t1 > t0);
        if (!sameDir)
        {
            double save = t0;
            t0 = t1;
            t1 = save;
        }

        if (t1 > 0.0 && t0 < tmax)
        {
            if (intervalList.empty())
            {
                intervalList.push_front(Interval(t0, t1, sameDir, true));
            }
            else
            {
                iter = intervalList.begin();
                for (/**/; iter != intervalList.end(); ++iter)
                {
                    if (Mathd::FAbs(t1 - iter->T0) <= epsilon)
                    {
                        t1 = iter->T0;
                    }

                    if (t1 <= iter->T0)
                    {
                        // [t0,t1] is on the left of [I.t0,I.t1]
                        intervalList.insert(iter,
                            Interval(t0, t1, sameDir, true));
                        break;
                    }

                    // Theoretically, the intervals are disjoint or intersect
                    // only at an end point.  The assert makes sure that
                    // [t0,t1] is to the right of [I.t0,I.t1].
                    if (Mathd::FAbs(t0 - iter->T1) <= epsilon)
                    {
                        t0 = iter->T1;
                    }

                    assertion(t0 >= iter->T1, "Invalid ordering.\n");

                    std::list<Interval>::iterator last = intervalList.end();
                    --last;
                    if (iter == last)
                    {
                        intervalList.push_back(Interval(t0, t1, sameDir,
                            true));
                        break;
                    }
                }
            }
        }
    }

    if (intervalList.empty())
    {
        GetPosPartition(polygon, v0, v1, pos, neg, coSame, coDiff);
        GetNegPartition(polygon, v0, v1, pos, neg, coSame, coDiff);
        return;
    }

    // Insert outside intervals between the touching intervals.  It is
    // possible that two touching intervals are adjacent, so this is not just
    // a simple alternation of touching and outside intervals.
    Interval& front = intervalList.front();
    if (front.T0 > 0.0)
    {
        intervalList.push_front(Interval(0.0, front.T0, front.SameDir,
            false));
    }
    else
    {
        front.T0 = 0.0;
    }

    Interval& back = intervalList.back();
    if (back.T1 < tmax)
    {
        intervalList.push_back(Interval(back.T1, tmax, back.SameDir, false));
    }
    else
    {
        back.T1 = tmax;
    }

    std::list<Interval>::iterator iter0 = intervalList.begin();
    std::list<Interval>::iterator iter1 = intervalList.begin();
    for (++iter1; iter1 != intervalList.end(); ++iter0, ++iter1)
    {
        t0 = iter0->T1;
        t1 = iter1->T0;
        if (t1 - t0 > epsilon)
        {
            iter0 = intervalList.insert(iter1, Interval(t0, t1, true, false));
        }
    }

    // Process the segmentation.
    double invTMax = 1.0/tmax;
    t0 = intervalList.front().T0*invTMax;
    end1 = v0 + (intervalList.front().T0*invTMax)*dir;
    iter = intervalList.begin();
    for (/**/; iter != intervalList.end(); ++iter)
    {
        end0 = end1;
        t1 = iter->T1*invTMax;
        end1 = v0 + (iter->T1*invTMax)*dir;

        if (iter->Touching)
        {
            Edge2 edge;
            if (iter->SameDir)
            {
                edge.I0 = coSame.InsertVertex(end0);
                edge.I1 = coSame.InsertVertex(end1);
                if (edge.I0 != edge.I1)
                {
                    coSame.InsertEdge(edge);
                }
            }
            else
            {
                edge.I0 = coDiff.InsertVertex(end1);
                edge.I1 = coDiff.InsertVertex(end0);
                if (edge.I0 != edge.I1)
                {
                    coDiff.InsertEdge(edge);
                }
            }
        }
        else
        {
            GetPosPartition(polygon, end0, end1, pos, neg, coSame, coDiff);
            GetNegPartition(polygon, end0, end1, pos, neg, coSame, coDiff);
        }
    }
}
Exemplo n.º 5
0
//----------------------------------------------------------------------------
int BspTree2::Classify (const Vector2d& end0, const Vector2d& end1,
    const Vector2d& v0, const Vector2d& v1, Vector2d& intr) const
{
    // For numerical round-off error handling.
    const double epsilon0 = 0.00001;
    const double epsilon1 = 0.99999;

    Vector2d dir = end1 - end0;
    Vector2d nor = dir.Perp();
    Vector2d diff0 = v0 - end0;
    Vector2d diff1 = v1 - end0;

    double d0 = nor.Dot(diff0);
    double d1 = nor.Dot(diff1);

    if (d0*d1 < 0.0)
    {
        // Edge <V0,V1> transversely crosses line.  Compute point of
        // intersection I = V0 + t*(V1 - V0).
        double t = d0/(d0 - d1);
        if (t > epsilon0)
        {
            if (t < epsilon1)
            {
                intr = v0 + t*(v1 - v0);
                if (d1 > 0.0)
                {
                    return TRANSVERSE_POSITIVE;
                }
                else
                {
                    return TRANSVERSE_NEGATIVE;
                }
            }
            else
            {
                // T is effectively 1 (numerical round-off issue), so
                // set d1 = 0 and go on to other cases.
                d1 = 0.0;
            }
        }
        else
        {
            // T is effectively 0 (numerical round-off issue), so
            // set d0 = 0 and go on to other cases.
            d0 = 0.0;
        }
    }

    if (d0 > 0.0 || d1 > 0.0)
    {
        // edge on positive side of line
        return ALL_POSITIVE;
    }

    if (d0 < 0.0 || d1 < 0.0)
    {
        // edge on negative side of line
        return ALL_NEGATIVE;
    }

    return COINCIDENT;
}
Exemplo n.º 6
0
//----------------------------------------------------------------------------
int ExtractRidges::Main (int, char**)
{
    std::string imageName = Environment::GetPathR("Head.im");
    ImageDouble2D image(imageName.c_str());

    // Normalize the image values to be in [0,1].
    int quantity = image.GetQuantity();
    double minValue = image[0], maxValue = minValue;
    int i;
    for (i = 1; i < quantity; ++i)
    {
        if (image[i] < minValue)
        {
            minValue = image[i];
        }
        else if (image[i] > maxValue)
        {
            maxValue = image[i];
        }
    }
    double invRange = 1.0/(maxValue - minValue);
    for (i = 0; i < quantity; ++i)
    {
        image[i] = (image[i] - minValue)*invRange;
    }

    // Use first-order centered finite differences to estimate the image
    // derivatives.  The gradient is DF = (df/dx, df/dy) and the Hessian
    // is D^2F = {{d^2f/dx^2, d^2f/dxdy}, {d^2f/dydx, d^2f/dy^2}}.
    int xBound = image.GetBound(0);
    int yBound = image.GetBound(1);
    int xBoundM1 = xBound - 1;
    int yBoundM1 = yBound - 1;
    ImageDouble2D dx(xBound, yBound);
    ImageDouble2D dy(xBound, yBound);
    ImageDouble2D dxx(xBound, yBound);
    ImageDouble2D dxy(xBound, yBound);
    ImageDouble2D dyy(xBound, yBound);
    int x, y;
    for (y = 1; y < yBoundM1; ++y)
    {
        for (x = 1; x < xBoundM1; ++x)
        {
            dx(x, y) = 0.5*(image(x+1, y) - image(x-1, y));
            dy(x, y) = 0.5*(image(x, y+1) - image(x, y-1));
            dxx(x, y) = image(x+1, y) - 2.0*image(x, y) + image(x-1, y);
            dxy(x, y) = 0.25*(image(x+1, y+1) + image(x-1, y-1)
                - image(x+1, y-1) - image(x-1, y+1));
            dyy(x, y) = image(x, y+1) - 2.0*image(x, y) + image(x, y+1);
        }
    }
    dx.Save("dx.im");
    dy.Save("dy.im");
    dxx.Save("dxx.im");
    dxy.Save("dxy.im");
    dyy.Save("dyy.im");

    // The eigensolver produces eigenvalues a and b and corresponding
    // eigenvectors U and V:  D^2F*U = a*U, D^2F*V = b*V.  Define
    // P = Dot(U,DF) and Q = Dot(V,DF).  The classification is as follows.
    //   ridge:   P = 0 with a < 0
    //   valley:  Q = 0 with b > 0
    ImageDouble2D aImage(xBound, yBound);
    ImageDouble2D bImage(xBound, yBound);
    ImageDouble2D pImage(xBound, yBound);
    ImageDouble2D qImage(xBound, yBound);
    for (y = 1; y < yBoundM1; ++y)
    {
        for (x = 1; x < xBoundM1; ++x)
        {
            Vector2d gradient(dx(x, y), dy(x, y));
            Matrix2d hessian(dxx(x, y), dxy(x, y), dxy(x, y), dyy(x, y));
            EigenDecompositiond decomposer(hessian);
            decomposer.Solve(true);
            aImage(x,y) = decomposer.GetEigenvalue(0);
            bImage(x,y) = decomposer.GetEigenvalue(1);
            Vector2d u = decomposer.GetEigenvector2(0);
            Vector2d v = decomposer.GetEigenvector2(1);
            pImage(x,y) = u.Dot(gradient);
            qImage(x,y) = v.Dot(gradient);
        }
    }
    aImage.Save("a.im");
    bImage.Save("b.im");
    pImage.Save("p.im");
    qImage.Save("q.im");

    // Use a cheap classification of the pixels by testing for sign changes
    // between neighboring pixels.
    ImageRGB82D result(xBound, yBound);
    for (y = 1; y < yBoundM1; ++y)
    {
        for (x = 1; x < xBoundM1; ++x)
        {
            unsigned char gray = (unsigned char)(255.0f*image(x, y));

            double pValue = pImage(x, y);
            bool isRidge = false;
            if (pValue*pImage(x-1 ,y) < 0.0
            ||  pValue*pImage(x+1, y) < 0.0
            ||  pValue*pImage(x, y-1) < 0.0
            ||  pValue*pImage(x, y+1) < 0.0)
            {
                if (aImage(x, y) < 0.0)
                {
                    isRidge = true;
                }
            }

            double qValue = qImage(x,y);
            bool isValley = false;
            if (qValue*qImage(x-1, y) < 0.0
            ||  qValue*qImage(x+1, y) < 0.0
            ||  qValue*qImage(x, y-1) < 0.0
            ||  qValue*qImage(x, y+1) < 0.0)
            {
                if (bImage(x,y) > 0.0)
                {
                    isValley = true;
                }
            }

            if (isRidge)
            {
                if (isValley)
                {
                    result(x, y) = GetColor24(gray, 0, gray);
                }
                else
                {
                    result(x, y) = GetColor24(gray, 0, 0);
                }
            }
            else if (isValley)
            {
                result(x, y) = GetColor24(0, 0, gray);
            }
            else
            {
                result(x, y) = GetColor24(gray, gray, gray);
            }
        }
    }
    result.Save("result.im");

    return 0;
}