import math

import pytest
import numpy as np
import matplotlib.pyplot as plt  # needed for visualization
import matplotlib.tri as mtri  # needed for visualization
import networkx as nx

from locan import AlphaShape, AlphaComplex, RoiRegion, EmptyRegion, Region2D


@pytest.mark.visual
def test_AlphaComplex_visual(locdata_2d):
    points = locdata_2d.coordinates
    alpha_complex = AlphaComplex(points)

    alpha = 1.6
    ac_simplices_all = alpha_complex.get_alpha_complex_lines(alpha, type='all')
    ac_simplices_exterior = alpha_complex.get_alpha_complex_lines(alpha, type='exterior')
    ac_simplices_interior = alpha_complex.get_alpha_complex_lines(alpha, type='interior')
    ac_simplices_regular = alpha_complex.get_alpha_complex_lines(alpha, type='regular')
    ac_simplices_singular = alpha_complex.get_alpha_complex_lines(alpha, type='singular')

    lengths = [len(sim) for sim in [
        ac_simplices_all, ac_simplices_exterior, ac_simplices_interior, ac_simplices_regular, ac_simplices_singular]]
    assert lengths == [8, 2, 0, 6, 2]

    locdata_2d.data.plot(*locdata_2d.coordinate_labels, kind='scatter')
    for simp in ac_simplices_all:
        plt.plot(points[simp, 0], points[simp, 1], '-b')
    for simp in ac_simplices_interior:
        plt.plot(points[simp, 0], points[simp, 1], '--g')
    for simp in ac_simplices_regular:
        plt.plot(points[simp, 0], points[simp, 1], '--r')
    for simp in ac_simplices_singular:
        plt.plot(points[simp, 0], points[simp, 1], '--y')
    plt.show()


@pytest.mark.visual
def test_AlphaComplex_1_visual():
    points = np.array([[10, 10], [10, 14], [11, 11], [12, 11], [13, 10], [13, 13], [15, 14], [17, 16],
                       [10, 24]])

    alpha_complex = AlphaComplex(points)

    alpha = 2.2
    ac_simplices_all = alpha_complex.get_alpha_complex_lines(alpha, type='all')
    ac_simplices_exterior = alpha_complex.get_alpha_complex_lines(alpha, type='exterior')
    ac_simplices_interior = alpha_complex.get_alpha_complex_lines(alpha, type='interior')
    ac_simplices_regular = alpha_complex.get_alpha_complex_lines(alpha, type='regular')
    ac_simplices_singular = alpha_complex.get_alpha_complex_lines(alpha, type='singular')

    H = alpha_complex.graph_from_lines(alpha, type='regular')

    fig, ax = plt.subplots(1, 3)
    nx.draw_networkx(H, points, with_labels=True, ax=ax[0])
    # plt.show()

    plt.scatter(*points.T)
    for simp in ac_simplices_all:
        ax[1].plot(points[simp, 0], points[simp, 1], '-b')
    for simp in ac_simplices_interior:
        ax[1].plot(points[simp, 0], points[simp, 1], '--g')
    for simp in ac_simplices_regular:
        ax[1].plot(points[simp, 0], points[simp, 1], '--r')
    for simp in ac_simplices_singular:
        ax[1].plot(points[simp, 0], points[simp, 1], '--y')
    # plt.show()

    triangles_all = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='all')]
    triangles_exterior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='exterior')]
    triangles_interior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='interior')]
    triangles_regular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='regular')]
    triangles_singular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='singular')]

    tri = mtri.Triangulation(*points.T, triangles=triangles_all)
    ax[2].triplot(tri, '-b')
    tri = mtri.Triangulation(*points.T, triangles=triangles_interior)
    ax[2].triplot(tri, '--g')
    tri = mtri.Triangulation(*points.T, triangles=triangles_regular)
    ax[2].triplot(tri, '--r')
    tri = mtri.Triangulation(*points.T, triangles=triangles_singular)
    ax[2].triplot(tri, '--y')
    plt.show()


@pytest.mark.visual
def test_AlphaComplex_2_visual():
    points = np.array([[10, 10], [10, 14], [11, 11], [12, 11], [13, 10], [13, 13], [15, 14], [17, 16],
                       [20, 20], [20, 24], [21, 21], [22, 21], [23, 20], [23, 23], [25, 24],
                       [10, 24]])

    alpha_complex = AlphaComplex(points)

    alpha = 2.2
    ac_simplices_all = alpha_complex.get_alpha_complex_lines(alpha, type='all')
    ac_simplices_exterior = alpha_complex.get_alpha_complex_lines(alpha, type='exterior')
    ac_simplices_interior = alpha_complex.get_alpha_complex_lines(alpha, type='interior')
    ac_simplices_regular = alpha_complex.get_alpha_complex_lines(alpha, type='regular')
    ac_simplices_singular = alpha_complex.get_alpha_complex_lines(alpha, type='singular')

    H = alpha_complex.graph_from_lines(alpha, type='regular')

    fig, ax = plt.subplots(1, 3)
    nx.draw_networkx(H, points, with_labels=True, ax=ax[0])
    # plt.show()

    plt.scatter(*points.T)
    for simp in ac_simplices_all:
        ax[1].plot(points[simp, 0], points[simp, 1], '-b')
    for simp in ac_simplices_interior:
        ax[1].plot(points[simp, 0], points[simp, 1], '--g')
    for simp in ac_simplices_regular:
        ax[1].plot(points[simp, 0], points[simp, 1], '--r')
    for simp in ac_simplices_singular:
        ax[1].plot(points[simp, 0], points[simp, 1], '--y')
    # plt.show()

    triangles_all = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='all')]
    triangles_exterior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='exterior')]
    triangles_interior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='interior')]
    triangles_regular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='regular')]
    triangles_singular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='singular')]

    tri = mtri.Triangulation(*points.T, triangles=triangles_all)
    ax[2].triplot(tri, '-b')
    tri = mtri.Triangulation(*points.T, triangles=triangles_interior)
    ax[2].triplot(tri, '--g')
    tri = mtri.Triangulation(*points.T, triangles=triangles_regular)
    ax[2].triplot(tri, '--r')
    tri = mtri.Triangulation(*points.T, triangles=triangles_singular)
    ax[2].triplot(tri, '--y')
    plt.show()


@pytest.mark.visual
def test_AlphaComplex_3_visual():
    points = np.array([[10, 10], [10, 20], [20, 20], [20, 10], [10, 15], [15, 20], [20, 15], [15, 10],
                       [10, 12], [10, 18], [20, 18], [20, 12], [17, 20], [12, 10], [17, 10], [12, 20],
                       [11, 11], [11, 19], [19, 19], [19, 11], [11, 15], [15, 19], [19, 15], [15, 11],
                       [13, 11], [11.5, 12], [12, 18], [13, 19], [17, 19], [18, 18], [17, 11], [18, 12],
                       [15, 15]
                       ])

    alpha_complex = AlphaComplex(points)

    alpha = 2.2
    ac_simplices_all = alpha_complex.get_alpha_complex_lines(alpha, type='all')
    ac_simplices_exterior = alpha_complex.get_alpha_complex_lines(alpha, type='exterior')
    ac_simplices_interior = alpha_complex.get_alpha_complex_lines(alpha, type='interior')
    ac_simplices_regular = alpha_complex.get_alpha_complex_lines(alpha, type='regular')
    ac_simplices_singular = alpha_complex.get_alpha_complex_lines(alpha, type='singular')

    H = alpha_complex.graph_from_lines(alpha, type='regular')

    fig, ax = plt.subplots(1, 3)
    nx.draw_networkx(H, points, with_labels=True, ax=ax[0])
    # plt.show()

    plt.scatter(*points.T)
    for simp in ac_simplices_all:
        ax[1].plot(points[simp, 0], points[simp, 1], '-b')
    for simp in ac_simplices_interior:
        ax[1].plot(points[simp, 0], points[simp, 1], '--g')
    for simp in ac_simplices_regular:
        ax[1].plot(points[simp, 0], points[simp, 1], '--r')
    for simp in ac_simplices_singular:
        ax[1].plot(points[simp, 0], points[simp, 1], '--y')
    # plt.show()

    triangles_all = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='all')]
    triangles_exterior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='exterior')]
    triangles_interior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='interior')]
    triangles_regular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='regular')]
    triangles_singular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='singular')]

    tri = mtri.Triangulation(*points.T, triangles=triangles_all)
    ax[2].triplot(tri, '-b')
    tri = mtri.Triangulation(*points.T, triangles=triangles_interior)
    ax[2].triplot(tri, '--g')
    tri = mtri.Triangulation(*points.T, triangles=triangles_regular)
    ax[2].triplot(tri, '--r')
    tri = mtri.Triangulation(*points.T, triangles=triangles_singular)
    ax[2].triplot(tri, '--y')
    plt.show()


def test_AlphaComplex_0():
    points = np.array([])
    assert np.size(points) == 0
    alpha_complex = AlphaComplex(points)
    assert len(alpha_complex.triangles) == 0
    assert len(alpha_complex.lines) == 0
    assert alpha_complex.dimension is None
    assert alpha_complex.get_alpha_complex_lines(alpha=alpha_complex.optimal_alpha(), type='exterior') == []
    assert alpha_complex.optimal_alpha() is None
    assert alpha_complex.alphas().size == 0
    # assert isinstance(alpha_complex.alpha_shape(alpha=2.2), AlphaShape)

    alpha = 2.2
    ac_simplices_all = alpha_complex.get_alpha_complex_lines(alpha, type='all')
    ac_simplices_exterior = alpha_complex.get_alpha_complex_lines(alpha, type='exterior')
    ac_simplices_interior = alpha_complex.get_alpha_complex_lines(alpha, type='interior')
    ac_simplices_regular = alpha_complex.get_alpha_complex_lines(alpha, type='regular')
    ac_simplices_singular = alpha_complex.get_alpha_complex_lines(alpha, type='singular')

    lengths = [len(sim) for sim in [
        ac_simplices_all, ac_simplices_exterior, ac_simplices_interior, ac_simplices_regular, ac_simplices_singular]]
    assert lengths == [0, 0, 0, 0, 0]

    triangles_all = alpha_complex.get_alpha_complex_triangles(alpha, type='all')
    assert len(triangles_all) == 0

    H = alpha_complex.graph_from_lines(alpha, type='regular')
    assert isinstance(H, nx.Graph)
    H = alpha_complex.graph_from_triangles(alpha, type='regular')
    assert isinstance(H, nx.Graph)


def test_AlphaComplex_1():
    points = np.array([[10, 10], [10, 14], [11, 11], [12, 11], [13, 10], [13, 13], [15, 14], [17, 16],
                       [10, 24]])
    assert len(points) == 9
    alpha_complex = AlphaComplex(points)
    assert len(alpha_complex.triangles) == 11
    assert len(alpha_complex.lines) == 19
    assert alpha_complex.dimension == 2
    assert alpha_complex.get_alpha_complex_lines(alpha=alpha_complex.optimal_alpha(), type='exterior') == []
    assert alpha_complex.optimal_alpha() in alpha_complex.alphas()
    assert np.max(alpha_complex.alphas()) == np.inf
    assert isinstance(alpha_complex.alpha_shape(alpha=2.2), AlphaShape)

    alpha = 2.2
    ac_simplices_all = alpha_complex.get_alpha_complex_lines(alpha, type='all')
    ac_simplices_exterior = alpha_complex.get_alpha_complex_lines(alpha, type='exterior')
    ac_simplices_interior = alpha_complex.get_alpha_complex_lines(alpha, type='interior')
    ac_simplices_regular = alpha_complex.get_alpha_complex_lines(alpha, type='regular')
    ac_simplices_singular = alpha_complex.get_alpha_complex_lines(alpha, type='singular')

    lengths = [len(sim) for sim in [
        ac_simplices_all, ac_simplices_exterior, ac_simplices_interior, ac_simplices_regular, ac_simplices_singular]]
    assert lengths == [13, 6, 5, 5, 3]

    triangles_all = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='all')]
    triangles_exterior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='exterior')]
    triangles_interior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='interior')]
    triangles_regular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='regular')]
    triangles_singular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='singular')]

    lengths = [len(sim) for sim in [
        triangles_all, triangles_exterior, triangles_interior, triangles_regular, triangles_singular]]
    assert lengths == [6, 5, 1, 4, 1]

    H = alpha_complex.graph_from_lines(alpha, type='regular')
    assert isinstance(H, nx.Graph)
    H = alpha_complex.graph_from_triangles(alpha, type='regular')
    assert isinstance(H, nx.Graph)

    alpha = 1
    ac_simplices_all = alpha_complex.get_alpha_complex_lines(alpha, type='all')
    ac_simplices_exterior = alpha_complex.get_alpha_complex_lines(alpha, type='exterior')
    ac_simplices_interior = alpha_complex.get_alpha_complex_lines(alpha, type='interior')
    ac_simplices_regular = alpha_complex.get_alpha_complex_lines(alpha, type='regular')
    ac_simplices_singular = alpha_complex.get_alpha_complex_lines(alpha, type='singular')

    lengths = [len(sim) for sim in [
        ac_simplices_all, ac_simplices_exterior, ac_simplices_interior, ac_simplices_regular, ac_simplices_singular]]
    assert lengths == [3, 16, 0, 0, 3]

    triangles_all = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='all')]
    triangles_exterior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='exterior')]
    triangles_interior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='interior')]
    triangles_regular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='regular')]
    triangles_singular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='singular')]

    lengths = [len(sim) for sim in [
        triangles_all, triangles_exterior, triangles_interior, triangles_regular, triangles_singular]]
    assert lengths == [0, 11, 0, 0, 0]

    H = alpha_complex.graph_from_lines(alpha, type='all')
    assert isinstance(H, nx.Graph)
    H = alpha_complex.graph_from_triangles(alpha, type='regular')
    assert isinstance(H, nx.Graph)


def test_AlphaComplex_2():
    points = np.array([[10, 10], [10, 14], [11, 11], [12, 11], [13, 10], [13, 13], [15, 14], [17, 16],
                       [20, 20], [20, 24], [21, 21], [22, 21], [23, 20], [23, 23], [25, 24],
                       [10, 24]])
    assert len(points) == 16
    alpha_complex = AlphaComplex(points)
    assert len(alpha_complex.lines) == 38
    assert alpha_complex.dimension == 2
    assert alpha_complex.get_alpha_complex_lines(alpha=alpha_complex.optimal_alpha(), type='exterior') == []
    assert alpha_complex.optimal_alpha() in alpha_complex.alphas()
    assert np.max(alpha_complex.alphas()) == np.inf
    assert isinstance(alpha_complex.alpha_shape(alpha=2.2), AlphaShape)

    alpha = 2.2
    ac_simplices_all = alpha_complex.get_alpha_complex_lines(alpha, type='all')
    ac_simplices_exterior = alpha_complex.get_alpha_complex_lines(alpha, type='exterior')
    ac_simplices_interior = alpha_complex.get_alpha_complex_lines(alpha, type='interior')
    ac_simplices_regular = alpha_complex.get_alpha_complex_lines(alpha, type='regular')
    ac_simplices_singular = alpha_complex.get_alpha_complex_lines(alpha, type='singular')

    lengths = [len(sim) for sim in [
        ac_simplices_all, ac_simplices_exterior, ac_simplices_interior, ac_simplices_regular, ac_simplices_singular]]
    assert lengths == [25, 13, 10, 10, 5]

    triangles_all = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='all')]
    triangles_exterior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='exterior')]
    triangles_interior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='interior')]
    triangles_regular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='regular')]
    triangles_singular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='singular')]

    lengths = [len(sim) for sim in [
        triangles_all, triangles_exterior, triangles_interior, triangles_regular, triangles_singular]]
    assert lengths == [12, 11, 3, 7, 2]

    H = alpha_complex.graph_from_lines(alpha, type='regular')
    assert isinstance(H, nx.Graph)
    H = alpha_complex.graph_from_triangles(alpha, type='regular')
    assert isinstance(H, nx.Graph)


def test_AlphaComplex_3():
    points = np.array([[10, 10], [10, 20], [20, 20], [20, 10], [10, 15], [15, 20], [20, 15], [15, 10],
                       [10, 12], [10, 18], [20, 18], [20, 12], [17, 20], [12, 10], [17, 10], [12, 20],
                       [11, 11], [11, 19], [19, 19], [19, 11], [11, 15], [15, 19], [19, 15], [15, 11],
                       [13, 11], [11.5, 12], [12, 18], [13, 19], [17, 19], [18, 18], [17, 11], [18, 12],
                       [15, 15]
                       ])
    assert len(points) == 33
    alpha_complex = AlphaComplex(points)
    assert len(alpha_complex.lines) == 80
    assert alpha_complex.dimension == 2
    assert alpha_complex.get_alpha_complex_lines(alpha=alpha_complex.optimal_alpha(), type='exterior') == []
    assert alpha_complex.optimal_alpha() in alpha_complex.alphas()
    assert np.max(alpha_complex.alphas()) == np.inf
    assert isinstance(alpha_complex.alpha_shape(alpha=2.2), AlphaShape)

    alpha = 2.2
    ac_simplices_all = alpha_complex.get_alpha_complex_lines(alpha, type='all')
    ac_simplices_exterior = alpha_complex.get_alpha_complex_lines(alpha, type='exterior')
    ac_simplices_interior = alpha_complex.get_alpha_complex_lines(alpha, type='interior')
    ac_simplices_regular = alpha_complex.get_alpha_complex_lines(alpha, type='regular')
    ac_simplices_singular = alpha_complex.get_alpha_complex_lines(alpha, type='singular')

    lengths = [len(sim) for sim in [
        ac_simplices_all, ac_simplices_exterior, ac_simplices_interior, ac_simplices_regular, ac_simplices_singular]]
    assert lengths == [75, 5, 40, 28, 7]

    triangles_all = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='all')]
    triangles_exterior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='exterior')]
    triangles_interior = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='interior')]
    triangles_regular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='regular')]
    triangles_singular = alpha_complex.delaunay_triangulation.simplices[
        alpha_complex.get_alpha_complex_triangles(alpha, type='singular')]

    lengths = [len(sim) for sim in [
        triangles_all, triangles_exterior, triangles_interior, triangles_regular, triangles_singular]]
    assert lengths == [39, 9, 8, 28, 3]

    H = alpha_complex.graph_from_lines(alpha=2.2, type='regular')
    assert isinstance(H, nx.Graph)
    H = alpha_complex.graph_from_triangles(alpha, type='regular')
    assert isinstance(H, nx.Graph)


def test_AlphaShape_0():
    points = np.array([])

    alpha = 2.2
    alpha_shape = AlphaShape(alpha, points=points)
    assert len(alpha_shape.alpha_shape) == 0
    assert isinstance(alpha_shape.alpha_shape, list)
    assert alpha_shape.dimension is None
    assert isinstance(alpha_shape.region, EmptyRegion)
    assert alpha_shape.region_measure == 0
    assert alpha_shape.subregion_measure == 0
    assert alpha_shape.n_points_alpha_shape == 0
    assert math.isnan(alpha_shape.n_points_alpha_shape_rel)
    assert alpha_shape.n_points_on_boundary == 0
    assert math.isnan(alpha_shape.n_points_on_boundary_rel)
    assert alpha_shape.vertex_indices == []
    assert np.size(alpha_shape.vertices) == 0
    assert np.size(alpha_shape.vertices_alpha_shape) == 0
    assert np.size(alpha_shape.vertex_alpha_shape_indices) == 0

    cc = alpha_shape.connected_components
    assert len(cc) == 0
    assert alpha_shape.vertices_connected_components_indices == []


def test_AlphaShape_1():
    points = np.array([[10, 10], [10, 14], [11, 11], [12, 11], [13, 10], [13, 13], [15, 14], [17, 16],
                       [10, 24]])
    assert len(points) == 9

    alpha = 2.2
    alpha_shape = AlphaShape(alpha, points=points)
    assert len(alpha_shape.alpha_shape) == 13
    assert isinstance(alpha_shape.alpha_shape, list)
    assert alpha_shape.dimension == 2
    assert isinstance(alpha_shape.region, Region2D)
    assert alpha_shape.region_measure == 10.5
    assert alpha_shape.subregion_measure == 13.16227766016838
    assert alpha_shape.n_points_alpha_shape == 8
    assert alpha_shape.n_points_alpha_shape_rel == 0.8888888888888888
    assert alpha_shape.n_points_on_boundary == 5
    assert alpha_shape.n_points_on_boundary_rel == 0.625
    assert np.array_equal(alpha_shape.vertex_indices, [0, 1, 2, 4, 5])
    assert alpha_shape.vertices.shape == (5, 2)
    assert alpha_shape.vertices_alpha_shape.shape == (8, 2)
    assert len(alpha_shape.vertex_alpha_shape_indices) == 8
    cc = alpha_shape.connected_components
    assert len(cc) == 1
    assert isinstance(cc[0], Region2D)
    assert alpha_shape.vertices_connected_components_indices == [[2, 1, 0, 5, 3, 4]]

    alpha = 1
    # alpha_shape = AlphaShape(alpha, points=points)
    alpha_shape.alpha = 1
    assert len(alpha_shape.alpha_shape) == 3
    assert isinstance(alpha_shape.alpha_shape, list)
    assert alpha_shape.dimension == 2
    assert isinstance(alpha_shape.region, EmptyRegion)
    assert alpha_shape.region_measure == 0
    assert alpha_shape.subregion_measure == 0
    assert alpha_shape.n_points_alpha_shape == 4
    assert alpha_shape.n_points_alpha_shape_rel == 0.4444444444444444
    assert alpha_shape.n_points_on_boundary == 0
    assert alpha_shape.n_points_on_boundary_rel == 0
    assert np.array_equal(alpha_shape.vertex_indices, [])
    assert alpha_shape.vertices.shape == (0, 2)
    assert alpha_shape.vertices_alpha_shape.shape == (4, 2)
    assert len(alpha_shape.vertex_alpha_shape_indices) == 4
    cc = alpha_shape.connected_components
    assert len(cc) == 0
    assert alpha_shape.vertices_connected_components_indices == []


@pytest.mark.visual
def test_AlphaShape_2_visual():
    points = np.array([[10, 10], [10, 14], [11, 11], [12, 11], [13, 10], [13, 13], [15, 14], [17, 16],
                       [20, 20], [20, 24], [21, 21], [22, 21], [23, 20], [23, 23], [25, 24],
                       [10, 24]])
    assert len(points) == 16

    alpha = 2.2
    alpha_shape = AlphaShape(alpha, points=points)
    H = alpha_shape.alpha_complex.graph_from_lines(alpha, type='regular')
    assert isinstance(H, nx.Graph)
    # visualization
    nx.draw_networkx(H, points, with_labels=True)
    plt.show()


def test_AlphaShape_2():
    points = np.array([[10, 10], [10, 14], [11, 11], [12, 11], [13, 10], [13, 13], [15, 14], [17, 16],
                       [20, 20], [20, 24], [21, 21], [22, 21], [23, 20], [23, 23], [25, 24],
                       [10, 24]])
    assert len(points) == 16

    alpha = 2.2
    alpha_shape = AlphaShape(alpha, points=points)
    H = alpha_shape.alpha_complex.graph_from_lines(alpha, type='regular')
    assert isinstance(H, nx.Graph)

    assert len(alpha_shape.alpha_shape) == 25
    assert isinstance(alpha_shape.alpha_shape, list)
    assert alpha_shape.dimension == 2
    assert isinstance(alpha_shape.region, Region2D)
    assert alpha_shape.region_measure == 21.0
    assert alpha_shape.subregion_measure == 26.32455532033676
    assert alpha_shape.n_points_alpha_shape == 15
    assert alpha_shape.n_points_alpha_shape_rel == 0.9375
    assert alpha_shape.n_points_on_boundary == 10
    assert alpha_shape.n_points_on_boundary_rel == 0.6666666666666666
    assert np.array_equal(alpha_shape.vertex_indices, [0, 1, 2, 4, 5, 8, 9, 10, 12, 13])
    assert alpha_shape.vertices.shape == (10, 2)
    assert alpha_shape.vertices_alpha_shape.shape == (15, 2)
    assert len(alpha_shape.vertex_alpha_shape_indices) == 15
    cc = alpha_shape.connected_components
    assert len(cc) == 2
    assert isinstance(cc[0], Region2D)
    assert alpha_shape.vertices_connected_components_indices == [[13, 11, 12, 8, 10, 9], [2, 1, 0, 5, 3, 4]]


def test_AlphaShape_3():
    points = np.array([[10, 10], [10, 20], [20, 20], [20, 10], [10, 15], [15, 20], [20, 15], [15, 10],
                       [10, 12], [10, 18], [20, 18], [20, 12], [17, 20], [12, 10], [17, 10], [12, 20],

                       [11, 11], [11, 19], [19, 19], [19, 11], [11, 15], [15, 19], [19, 15], [15, 11],
                       [13, 11], [11.5, 12], [12, 18], [13, 19], [17, 19], [18, 18], [17, 11], [18, 12],
                       [15, 15]
                       ])
    assert len(points) == 33

    alpha = 2.2
    alpha_shape = AlphaShape(alpha, points=points)
    H = alpha_shape.alpha_complex.graph_from_lines(alpha, type='regular')
    assert isinstance(H, nx.Graph)
    assert len(alpha_shape.alpha_shape) == 75
    assert isinstance(alpha_shape.alpha_shape, list)
    assert alpha_shape.dimension == 2
    assert isinstance(alpha_shape.region, Region2D)
    assert alpha_shape.region_measure == 65.0
    assert alpha_shape.subregion_measure == 73.81471965135825
    assert alpha_shape.n_points_alpha_shape == 33
    assert alpha_shape.n_points_alpha_shape_rel == 1.
    assert alpha_shape.n_points_on_boundary == 28
    assert alpha_shape.n_points_on_boundary_rel == 0.8484848484848485
    assert np.array_equal(alpha_shape.vertex_indices, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20,
                                                       21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31])
    assert alpha_shape.vertices.shape == (28, 2)
    assert alpha_shape.vertices_alpha_shape.shape == (33, 2)
    assert len(alpha_shape.vertex_alpha_shape_indices) == 33
    cc = alpha_shape.connected_components
    assert len(cc) == 1
    assert isinstance(cc[0], Region2D)
    assert sorted(alpha_shape.vertices_connected_components_indices[0]) == sorted(
           [26, 20, 32, 9, 4, 8, 25, 24, 13, 7, 23, 31, 22, 29, 10, 6, 11, 15, 27, 5, 21, 17, 1, 16, 0, 18, 2, 12,
            28, 19, 3, 14, 30])
