W
W
Wolko_dav2014-03-31 00:32:45
Python
Wolko_dav, 2014-03-31 00:32:45

Where did the error in the implementation of the Kirus-Beck algorithm crept in?

Dear time everyone. The second day I've been working on this algorithm.
It turned out to be implemented, but it does not work .... I don’t see the error at close range ... Help is required.

mult = lambda a, b: a.x * b.x + a.y * b.y


class Point(object):
    def __init__(self, x, y):
        self.x = float(x)
        self.y = float(y)


class Line(object):
    def __init__(self, begin, end):
        self.begin = begin
        self.end = end

    @property
    def direction(self):
        return Point(self.end.x - self.begin.x, self.end.y - self.begin.y)

    @property
    def normal(self):
        return Point(self.end.y - self.begin.y, self.begin.x - self.end.x)


class Polygon(object):
    def __init__(self, points):
        self.count = len(points)
        self.edges = []
        for i in xrange(self.count-1):
            self.edges.append(Line(points[i], points[i+1]))

        self.edges.append(Line(points[-1], points[1]))
    # Реализаця алгоритма!
    def cyruse_beck(self, l):
        t_begin = 0.0
        t_end = 1.0
        dirL = l.direction
        for edge in self.edges:
            dir_edg = edge.direction
            Q = Point(l.begin.x - dir_edg.x, l.begin.y - dir_edg.y)
            N = edge.normal
            Pn = mult(dirL, N)
            Qn = mult(Q, N)
            if Pn == 0:
                if Qn < 0:
                    return False
            else:
                t = -Qn / Pn
                if Pn < 0:
                    if t < t_begin:
                        return False
                    t_end = min(t_end, t)
                else:
                    if t > t_end:
                        return False
                    t_begin = max(t_begin, t)

        if t_end > t_begin:
            if t_begin > 0:
                l.begin = Point(l.begin.x + t_begin * dirL.x, l.begin.y + t_begin * dirL.y)
            if t_end < 1:
                l.end = Point(l.begin.x + t_end * dirL.x, l.begin.y + t_end * dirL.y)
        else:
            return False
        return True

Answer the question

In order to leave comments, you need to log in

3 answer(s)
J
jcmvbkbc, 2014-03-31
@jcmvbkbc

By code:
Probably still self.edges.append(Line(points[-1], points[0]))

if t_begin > 0:
    l.begin = Point(l.begin.x + t_begin * dirL.x, l.begin.y + t_begin * dirL.y)
if t_end < 1:
    l.end = Point(l.begin.x + t_end * dirL.x, l.begin.y + t_end * dirL.y)

You can arrive at this point with t_begin > 0 and t_end < 1, but t_begin and t_end will be in terms of the original segment. You will end up in the second if with an already changed segment.
I think it should be like this:
mult = lambda a, b: a.x * b.x + a.y * b.y


class Point(object):
    def __init__(self, x, y):
        self.x = float(x)
        self.y = float(y)

    def __str__(self):
        return "(%s, %s)" % (self.x, self.y)


class Line(object):
    def __init__(self, begin, end):
        self.begin = begin
        self.end = end

    def __str__(self):
        return "{%s - %s}" % (self.begin, self.end)

    @property
    def direction(self):
        return Point(self.end.x - self.begin.x, self.end.y - self.begin.y)

    @property
    def normal(self):
        return Point(self.end.y - self.begin.y, self.begin.x - self.end.x)


class Polygon(object):
    def __init__(self, points):
        self.count = len(points)
        self.edges = []
        for i in xrange(self.count-1):
            self.edges.append(Line(points[i], points[i+1]))

        self.edges.append(Line(points[-1], points[0]))
    def cyruse_beck(self, l):
        t_begin = 0.0
        t_end = 1.0
        dirL = l.direction
        for edge in self.edges:
            dir_edg = edge.direction
            Q = Point(l.begin.x - edge.begin.x, l.begin.y - edge.begin.y)
            N = edge.normal
            Pn = mult(dirL, N)
            Qn = mult(Q, N)
            if Pn == 0:
                if Qn < 0:
                    return False
            else:
                t = -Qn / Pn
                if Pn > 0:
                    if t < t_begin:
                        return False
                    t_end = min(t_end, t)
                else:
                    if t > t_end:
                        return False
                    t_begin = max(t_begin, t)

        if t_end > t_begin:
            if t_end < 1:
                l.end = Point(l.begin.x + t_end * dirL.x, l.begin.y + t_end * dirL.y)
            if t_begin > 0:
                l.begin = Point(l.begin.x + t_begin * dirL.x, l.begin.y + t_begin * dirL.y)
        else:
            return False
        return True

p = Polygon([Point(0, 0), Point(2, 0), Point(2, 2), Point(0, 2)]);
l = Line(Point(-0.5, -0.5), Point(2.5, 2.5))
print(p.cyruse_beck(l))
print("Line: %s" % l)
l = Line(Point(-0.5, -0.5), Point(2.5, -0.5))
print(p.cyruse_beck(l))
l = Line(Point(0, -1), Point(3, 2))
print(p.cyruse_beck(l))
print("Line: %s" % l)

X
xandox, 2014-03-31
@xandox

Do you have the normal turned exactly in the right direction?

W
Wolko_dav, 2014-03-31
@Wolko_dav

It's decided.

mult = lambda a, b: a.x * b.x + a.y * b.y


class Point(object):
    def __init__(self, x, y):
        self.x = float(x)
        self.y = float(y)


class Line(object):
    def __init__(self, begin, end):
        self.begin = begin
        self.end = end

    @property
    def direction(self):
        return Point(self.end.x - self.begin.x, self.end.y - self.begin.y)

    @property
    def normal(self):
        return Point(self.end.y - self.begin.y, self.begin.x - self.end.x)


class Polygon(object):
    def __init__(self, points):
        self.count = len(points)
        self.edges = []
        for i in xrange(self.count-1):
            self.edges.append(Line(points[i], points[i+1]))

        self.edges.append(Line(points[-1], points[0]))
    # Реализаця алгоритма!
    def cyruse_beck(self, l):
        t_begin = 0.0
        t_end = 1.0
        dirL = l.direction
        for edge in self.edges:
            dir_edg = edge.direction
            Q = Point(l.begin.x - dir_edg.x, l.begin.y - dir_edg.y)
            N = edge.normal
            Pn = mult(dirL, N)
            Qn = mult(Q, N)
            if Pn == 0:
                pass
            else:
                t = -Qn / Pn
                if Pn > 0:
                    if t < t_begin:
                        return False
                    t_end = min(t_end, t)
                else:
                    if t > t_end:
                        return False
                    t_begin = max(t_begin, t)

        if t_end > t_begin:
            if t_begin > 0:
                l.begin = Point(l.begin.x + t_begin * dirL.x, l.begin.y + t_begin * dirL.y)
            if t_end < 1:
                l.end = Point(l.begin.x + t_end * dirL.x, l.begin.y + t_end * dirL.y)
        else:
            return False
        return True

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question