mirror of https://github.com/CGAL/cgal
Remove free function and fix TDS3 test
This commit is contained in:
parent
a7a768cae9
commit
52cf9815e4
|
|
@ -15,21 +15,16 @@ see below). The class may offer some
|
|||
flexibility for the choice of container in the future, in the form of
|
||||
additional template parameters.
|
||||
|
||||
\cgalHeading{Parameters}
|
||||
\tparam VertexBase must be a model of `TriangulationDSVertexBase_3`. The default is `Triangulation_ds_vertex_base_3<TDS>`.
|
||||
|
||||
It is parameterized by base classes for vertices and cells which have to match
|
||||
the requirements for the concepts `TriangulationDSCellBase_3` and
|
||||
`TriangulationDSVertexBase_3` respectively.
|
||||
\tparam CellBase must be a model of `TriangulationDSCellBase_3`. The default is `Triangulation_ds_cell_base_3<TDS>`.
|
||||
|
||||
They have the default values `Triangulation_ds_vertex_base_3<TDS>` and
|
||||
`Triangulation_ds_cell_base_3<TDS>` respectively.
|
||||
|
||||
The `Concurrency_tag` parameter allows to enable the use of a concurrent
|
||||
\tparam ConcurrencyTag enables the use of a concurrent
|
||||
container to store vertices and cells. It can be `Sequential_tag` (use of a
|
||||
`Compact_container` to store vertices and cells) or `Parallel_tag`
|
||||
`Compact_container` to store vertices and cells) or `Parallel_tag`
|
||||
(use of a `Concurrent_compact_container`). If it is
|
||||
`Parallel_tag`, the following functions can be called concurrently:
|
||||
`create_vertex`, `create_cell`, `delete_vertex`, `delete_cell`.
|
||||
`create_vertex()`, `create_cell()`, `delete_vertex()`, and `delete_cell()`.
|
||||
`Sequential_tag` is the default value.
|
||||
|
||||
\cgalModels `TriangulationDataStructure_3`
|
||||
|
|
@ -37,37 +32,50 @@ container to store vertices and cells. It can be `Sequential_tag` (use of a
|
|||
The base class `Triangulation_utils_3` defines basic computations on
|
||||
indices of vertices and neighbors of cells.
|
||||
|
||||
\attention All members listed here are additional to the interface
|
||||
specified by the concept.
|
||||
|
||||
\sa `CGAL::Triangulation_ds_vertex_base_3`
|
||||
\sa `CGAL::Triangulation_ds_cell_base_3`
|
||||
\sa `CGAL::Triangulation_vertex_base_with_info_3`
|
||||
\sa `CGAL::Triangulation_cell_base_with_info_3`
|
||||
*/
|
||||
template< typename TriangulationDSVertexBase_3,
|
||||
typename TriangulationDSCellBase_3,
|
||||
typename Concurrency_tag >
|
||||
class Triangulation_data_structure_3 : public CGAL::Triangulation_utils_3 {
|
||||
template< typename VertexBase,
|
||||
typename CellBase,
|
||||
typename ConcurrencyTag >
|
||||
class Triangulation_data_structure_3
|
||||
: public CGAL::Triangulation_utils_3
|
||||
{
|
||||
public:
|
||||
|
||||
/// \name Types
|
||||
/// @{
|
||||
|
||||
typedef Triangulation_data_structure_2<VertexBase,FaceBase> Tds;
|
||||
|
||||
/// The vertex type.
|
||||
///
|
||||
/// \sa Section \ref tds3cyclic
|
||||
typedef typename VertexBase::template Rebind_TDS<Tds>::Other Vertex;
|
||||
|
||||
/// The face type.
|
||||
///
|
||||
/// \sa Section \ref tds3cyclic
|
||||
typedef typename CellBase::template Rebind_TDS<Tds>::Other Cell;
|
||||
|
||||
/*!
|
||||
Vertex container type. If Concurrency_tag is Parallel_tag, a
|
||||
Vertex container type. If `ConcurrencyTag` is `Parallel_tag`, a
|
||||
`Concurrent_compact_container` is used instead of a `Compact_container`.
|
||||
*/
|
||||
typedef Compact_container<Vertex, Default> Vertex_range;
|
||||
|
||||
/*!
|
||||
Cell container type. If Concurrency_tag is Parallel_tag, a
|
||||
Cell container type. If `ConcurrencyTag` is `Parallel_tag`, a
|
||||
`Concurrent_compact_container` is used instead of a `Compact_container`.
|
||||
*/
|
||||
typedef Compact_container<Cell, Default> Cell_range;
|
||||
/// @}
|
||||
|
||||
/// \name Operations
|
||||
///
|
||||
/// In addition to the interface documented in the concept,
|
||||
/// the class offers the following functions.
|
||||
///
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -10,9 +10,10 @@ The class `Triangulation_ds_cell_base_3<>` is a model for the concept
|
|||
|
||||
\cgalModels `TriangulationDSCellBase_3`
|
||||
|
||||
\tparam TDS should not be specified (see Section \ref tds3cyclic and examples)
|
||||
|
||||
\sa `CGAL::Triangulation_cell_base_3`
|
||||
\sa `CGAL::Triangulation_ds_vertex_base_3`
|
||||
\sa `CGAL::Triangulation_cell_base_with_info_3`
|
||||
|
||||
*/
|
||||
template< typename TDS = void >
|
||||
|
|
|
|||
|
|
@ -20,9 +20,10 @@ example) tuned for a specific application.
|
|||
|
||||
\cgalModels `TriangulationDSVertexBase_3`
|
||||
|
||||
\tparam TDS should not be specified (see Section \ref tds3cyclic and examples)
|
||||
|
||||
\sa `CGAL::Triangulation_vertex_base_3`
|
||||
\sa `CGAL::Triangulation_ds_cell_base_3`
|
||||
\sa `CGAL::Triangulation_vertex_base_with_info_3`
|
||||
|
||||
*/
|
||||
template< typename TDS = void >
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
#ifndef TDS_3_FILE_INPUT_H
|
||||
#define TDS_3_FILE_INPUT_H
|
||||
// Copyright (c) 1997-2010 INRIA Sophia-Antipolis (France).
|
||||
// Copyright (c) 2011, 2020 GeometryFactory Sarl (France)
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Laurent Rineau, Maxime Gimeno
|
||||
|
||||
// Adapted from operator>>(std::istream&, Triangulation_3&) from
|
||||
// <CGAL/Triangulation_3.h>
|
||||
|
||||
#include <CGAL/license/TDS_3.h>
|
||||
|
||||
|
||||
#include <CGAL/internal/Tr_or_tds_file_input.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename Tr_src,
|
||||
typename Tr_tgt,
|
||||
typename ConvertVertex,
|
||||
typename ConvertCell>
|
||||
std::istream& file_input(std::istream& is, Tr_tgt &tr,
|
||||
ConvertVertex convert_vertex = ConvertVertex(),
|
||||
ConvertCell convert_cell = ConvertCell())
|
||||
{
|
||||
return internal::file_input(is, tr, true, convert_vertex, convert_cell);
|
||||
}
|
||||
|
||||
} //end CGAL
|
||||
#endif // TDS_3_FILE_INPUT_H
|
||||
|
|
@ -51,8 +51,6 @@
|
|||
#include <CGAL/internal/Triangulation_ds_circulators_3.h>
|
||||
#include <CGAL/tss.h>
|
||||
|
||||
#include <CGAL/IO/TDS_3_file_input.h>
|
||||
|
||||
#ifdef CGAL_LINKED_WITH_TBB
|
||||
# include <tbb/scalable_allocator.h>
|
||||
#endif
|
||||
|
|
@ -1524,6 +1522,73 @@ public:
|
|||
return s <= maximal_nb_of_facets_of_small_hole;
|
||||
}
|
||||
|
||||
//IO
|
||||
template <typename TDS_src,
|
||||
typename ConvertVertex,
|
||||
typename ConvertCell>
|
||||
std::istream& file_input(std::istream& is,
|
||||
ConvertVertex convert_vertex = ConvertVertex(),
|
||||
ConvertCell convert_cell = ConvertCell())
|
||||
{
|
||||
// reads
|
||||
// the dimension
|
||||
// the number of finite vertices
|
||||
// the non combinatorial information on vertices (point, etc)
|
||||
// the number of cells
|
||||
// the cells by the indices of their vertices in the preceding list
|
||||
// of vertices, plus the non combinatorial information on each cell
|
||||
// the neighbors of each cell by their index in the preceding list of cells
|
||||
// when dimension < 3 : the same with faces of maximal dimension
|
||||
|
||||
// If this is used for a TDS, the vertices are processed from 0 to n.
|
||||
// Else, we make V[0] the infinite vertex and work from 1 to n+1.
|
||||
|
||||
typedef typename Tds::Vertex_handle Vertex_handle;
|
||||
typedef typename Tds::Cell_handle Cell_handle;
|
||||
|
||||
typedef typename TDS_src::Vertex Vertex1;
|
||||
typedef typename TDS_src::Cell Cell1;
|
||||
clear();
|
||||
cells().clear();
|
||||
|
||||
std::size_t n;
|
||||
int d;
|
||||
if(is_ascii(is))
|
||||
is >> d >> n;
|
||||
else {
|
||||
read(is, d);
|
||||
read(is, n);
|
||||
}
|
||||
if(!is) return is;
|
||||
set_dimension(d);
|
||||
|
||||
std::size_t V_size = n;
|
||||
std::vector< Vertex_handle > V(V_size);
|
||||
|
||||
// the infinite vertex is numbered 0
|
||||
for (std::size_t i=0 ; i < V_size; ++i) {
|
||||
Vertex1 v;
|
||||
if(!(is >> v)) return is;
|
||||
Vertex_handle vh=create_vertex( convert_vertex(v) );
|
||||
V[i] = vh;
|
||||
convert_vertex(v, *V[i]);
|
||||
}
|
||||
|
||||
std::vector< Cell_handle > C;
|
||||
|
||||
std::size_t m;
|
||||
read_cells(is, V, m, C);
|
||||
|
||||
for (std::size_t j=0 ; j < m; j++) {
|
||||
Cell1 c;
|
||||
if(!(is >> c)) return is;
|
||||
convert_cell(c, *C[j]);
|
||||
}
|
||||
|
||||
CGAL_triangulation_assertion(is_valid(false));
|
||||
return is;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Change the orientation of the cell by swapping indices 0 and 1.
|
||||
|
|
@ -1554,16 +1619,6 @@ private:
|
|||
bool count_cells(size_type &i, bool verbose = false, int level = 0) const;
|
||||
// counts AND checks the validity
|
||||
|
||||
//IO
|
||||
template <typename Tr_src,
|
||||
typename ConvertVertex,
|
||||
typename ConvertCell>
|
||||
std::istream& file_input(std::istream& is,
|
||||
ConvertVertex convert_vertex = ConvertVertex(),
|
||||
ConvertCell convert_cell = ConvertCell())
|
||||
{
|
||||
return CGAL::file_input<Tr_src, Tds, ConvertVertex, ConvertCell>(is, *this, convert_vertex, convert_cell);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef CGAL_TDS_USE_RECURSIVE_CREATE_STAR_3
|
||||
|
|
|
|||
|
|
@ -1,106 +0,0 @@
|
|||
// Copyright (c) 1997-2010 INRIA Sophia-Antipolis (France).
|
||||
// Copyright (c) 2011, 2020 GeometryFactory Sarl (France)
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Laurent Rineau, Maxime Gimeno
|
||||
|
||||
// Adapted from operator>>(std::istream&, Triangulation_3&) from
|
||||
// <CGAL/Triangulation_3.h>
|
||||
|
||||
|
||||
#ifndef CGAL_TR_OR_TDS_FILE_INPUT_H
|
||||
#define CGAL_TR_OR_TDS_FILE_INPUT_H
|
||||
|
||||
#include <CGAL/license/TDS_3.h>
|
||||
|
||||
#include <CGAL/license/Triangulation_3.h>
|
||||
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
|
||||
namespace CGAL {
|
||||
namespace internal{
|
||||
|
||||
template <typename Tr_src,
|
||||
typename Tr_tgt,
|
||||
typename ConvertVertex,
|
||||
typename ConvertCell>
|
||||
std::istream& file_input(std::istream& is, Tr_tgt &tr, bool is_tds,
|
||||
ConvertVertex convert_vertex = ConvertVertex(),
|
||||
ConvertCell convert_cell = ConvertCell())
|
||||
// reads
|
||||
// the dimension
|
||||
// the number of finite vertices
|
||||
// the non combinatorial information on vertices (point, etc)
|
||||
// the number of cells
|
||||
// the cells by the indices of their vertices in the preceding list
|
||||
// of vertices, plus the non combinatorial information on each cell
|
||||
// the neighbors of each cell by their index in the preceding list of cells
|
||||
// when dimension < 3 : the same with faces of maximal dimension
|
||||
|
||||
// If this is used for a TDS, the vertices are processed from 0 to n.
|
||||
// Else, we make V[0] the infinite vertex and work from 1 to n+1.
|
||||
{
|
||||
typedef Tr_tgt Triangulation;
|
||||
typedef typename Triangulation::Vertex_handle Vertex_handle;
|
||||
typedef typename Triangulation::Cell_handle Cell_handle;
|
||||
|
||||
typedef typename Tr_src::Vertex Vertex1;
|
||||
typedef typename Tr_src::Cell Cell1;
|
||||
|
||||
tr.clear();
|
||||
tr.tds().cells().clear();
|
||||
|
||||
std::size_t n;
|
||||
int d;
|
||||
if(is_ascii(is))
|
||||
is >> d >> n;
|
||||
else {
|
||||
read(is, d);
|
||||
read(is, n);
|
||||
}
|
||||
if(!is) return is;
|
||||
tr.tds().set_dimension(d);
|
||||
|
||||
std::size_t V_size = is_tds ? n : n+1;
|
||||
std::vector< Vertex_handle > V(V_size);
|
||||
|
||||
// the infinite vertex is numbered 0
|
||||
if(!is_tds)
|
||||
V[0] = tr.infinite_vertex();
|
||||
|
||||
for (std::size_t i=is_tds ? 0 : 1; i < V_size; ++i) {
|
||||
Vertex1 v;
|
||||
if(!(is >> v)) return is;
|
||||
Vertex_handle vh=tr.tds().create_vertex( convert_vertex(v) );
|
||||
V[i] = vh;
|
||||
convert_vertex(v, *V[i]);
|
||||
}
|
||||
|
||||
std::vector< Cell_handle > C;
|
||||
|
||||
std::size_t m;
|
||||
tr.tds().read_cells(is, V, m, C);
|
||||
|
||||
for (std::size_t j=0 ; j < m; j++) {
|
||||
Cell1 c;
|
||||
if(!(is >> c)) return is;
|
||||
convert_cell(c, *C[j]);
|
||||
}
|
||||
|
||||
CGAL_triangulation_assertion( tr.is_valid(false) );
|
||||
return is;
|
||||
}
|
||||
|
||||
} //end internal
|
||||
} // end namespace CGAL
|
||||
|
||||
|
||||
#endif // CGAL_TR_OR_TDS_FILE_INPUT_H
|
||||
|
|
@ -26,8 +26,28 @@ struct Update_vertex
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}; // end struct Update_vertex
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct Update_cell
|
||||
{
|
||||
typedef typename T1::Cell C1;
|
||||
typedef typename T2::Cell C2;
|
||||
|
||||
C2 operator()(const C1&)
|
||||
{
|
||||
return C2();
|
||||
}
|
||||
|
||||
void operator()(const C1&, C2&)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}; // end struct Update_vertex
|
||||
|
||||
int main()
|
||||
{
|
||||
|
|
@ -52,7 +72,7 @@ int main()
|
|||
out.close();
|
||||
Tds T2;
|
||||
std::ifstream in("tr");
|
||||
//T2.file_input<Tr1,Update_vertex<Tr1, Tr2>, Update_cell>(in);
|
||||
T2.file_input<Tds,Update_vertex<Tds, Tds>, Update_cell<Tds, Tds> >(in);
|
||||
in.close();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
namespace CGAL {
|
||||
|
||||
///@{
|
||||
/*!
|
||||
\ingroup PkgIOTriangulation3
|
||||
|
||||
The triangulation streamed in `is`, of original type `Tr_src`, is written into `tr`, of type `Tr_tgt`. As the vertex and cell
|
||||
types might be different and incompatible, the creation of new cells and vertices
|
||||
is made thanks to the functors `convert_vertex` and `convert_cell`, that convert
|
||||
vertex and cell types. For each vertex `v_src` in `is`, the corresponding
|
||||
vertex `v_tgt` in `tr` is a copy of the vertex returned by `convert_vertex(v_src)`.
|
||||
The same operations are done for cells with the functor convert_cell, except cells
|
||||
in `tr` are created using the default constructor, and then filled with the data
|
||||
contained in the stream.
|
||||
|
||||
|
||||
- A model of `ConvertVertex` must provide two `operator()`s that are responsible
|
||||
for converting the source vertex `v_src` into the target vertex:
|
||||
- `Tr_tgt::Vertex operator()(const Tr_src::Vertex& v_src) const;` This operator is
|
||||
used to create the vertex from `v_src`.
|
||||
- `void operator()(const Tr_src::Vertex& v_src, Tr_tgt::Vertex& v_tgt) const;` This
|
||||
operator is meant to be used in case heavy data should be transferred to `v_tgt`.
|
||||
- A model of ConvertCell must provide an `operator()` that is responsible for
|
||||
converting the source cell `c_src` into the target cell:
|
||||
- `void operator()(const Tr_src::Cell& c_src, Tr_tgt::Cell& c_tgt) const;` This operator
|
||||
is meant to be used in case data should be transferred to `c_tgt`.
|
||||
|
||||
\note The triangulation contained in `is` can be obtained with the `operator>>` of a `Triangulation_3`.
|
||||
*/
|
||||
template <typename Tr_src,
|
||||
typename Tr_tgt,
|
||||
typename ConvertVertex,
|
||||
typename ConvertCell>
|
||||
std::istream& file_input(std::istream& is, Tr_tgt &tr,
|
||||
ConvertVertex convert_vertex = ConvertVertex(),
|
||||
ConvertCell convert_cell = ConvertCell());
|
||||
///@}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (c) 1997-2010 INRIA Sophia-Antipolis (France).
|
||||
// Copyright (c) 2011, 2020 GeometryFactory Sarl (France)
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
//
|
||||
// Author(s) : Laurent Rineau, Maxime Gimeno
|
||||
|
||||
// Adapted from operator>>(std::istream&, Triangulation_3&) from
|
||||
// <CGAL/Triangulation_3.h>
|
||||
|
||||
|
||||
#ifndef CGAL_TRIANGULATION_FILE_INPUT_3_H
|
||||
#define CGAL_TRIANGULATION_FILE_INPUT_3_H
|
||||
|
||||
#include <CGAL/license/Triangulation_3.h>
|
||||
|
||||
#include <CGAL/internal/Tr_or_tds_file_input.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename Tr_src,
|
||||
typename Tr_tgt,
|
||||
typename ConvertVertex,
|
||||
typename ConvertCell>
|
||||
std::istream& file_input(std::istream& is, Tr_tgt &tr,
|
||||
ConvertVertex convert_vertex = ConvertVertex(),
|
||||
ConvertCell convert_cell = ConvertCell())
|
||||
{
|
||||
return internal::file_input<Tr_src>(is, tr, false, convert_vertex, convert_cell);
|
||||
}
|
||||
|
||||
} // end namespace CGAL
|
||||
|
||||
|
||||
#endif // TRIANGULATION_FILE_INPUT_H
|
||||
|
|
@ -60,7 +60,6 @@
|
|||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/utility/result_of.hpp>
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#include <CGAL/IO/Triangulation_file_input.h>
|
||||
|
||||
#ifndef CGAL_TRIANGULATION_3_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO
|
||||
#include <CGAL/internal/info_check.h>
|
||||
|
|
@ -2203,7 +2202,67 @@ public:
|
|||
ConvertVertex convert_vertex = ConvertVertex(),
|
||||
ConvertCell convert_cell = ConvertCell())
|
||||
{
|
||||
return CGAL::file_input<Tr_src, Self, ConvertVertex, ConvertCell>(is, *this, convert_vertex, convert_cell);
|
||||
// reads
|
||||
// the dimension
|
||||
// the number of finite vertices
|
||||
// the non combinatorial information on vertices (point, etc)
|
||||
// the number of cells
|
||||
// the cells by the indices of their vertices in the preceding list
|
||||
// of vertices, plus the non combinatorial information on each cell
|
||||
// the neighbors of each cell by their index in the preceding list of cells
|
||||
// when dimension < 3 : the same with faces of maximal dimension
|
||||
|
||||
// If this is used for a TDS, the vertices are processed from 0 to n.
|
||||
// Else, we make V[0] the infinite vertex and work from 1 to n+1.
|
||||
|
||||
typedef Self Triangulation;
|
||||
typedef typename Triangulation::Vertex_handle Vertex_handle;
|
||||
typedef typename Triangulation::Cell_handle Cell_handle;
|
||||
|
||||
typedef typename Tr_src::Vertex Vertex1;
|
||||
typedef typename Tr_src::Cell Cell1;
|
||||
|
||||
clear();
|
||||
tds().cells().clear();
|
||||
|
||||
std::size_t n;
|
||||
int d;
|
||||
if(is_ascii(is))
|
||||
is >> d >> n;
|
||||
else {
|
||||
read(is, d);
|
||||
read(is, n);
|
||||
}
|
||||
if(!is) return is;
|
||||
tds().set_dimension(d);
|
||||
|
||||
std::size_t V_size = n+1;
|
||||
std::vector< Vertex_handle > V(V_size);
|
||||
|
||||
// the infinite vertex is numbered 0
|
||||
V[0] = infinite_vertex();
|
||||
|
||||
for (std::size_t i = 1; i < V_size; ++i) {
|
||||
Vertex1 v;
|
||||
if(!(is >> v)) return is;
|
||||
Vertex_handle vh=tds().create_vertex( convert_vertex(v) );
|
||||
V[i] = vh;
|
||||
convert_vertex(v, *V[i]);
|
||||
}
|
||||
|
||||
std::vector< Cell_handle > C;
|
||||
|
||||
std::size_t m;
|
||||
tds().read_cells(is, V, m, C);
|
||||
|
||||
for (std::size_t j=0 ; j < m; j++) {
|
||||
Cell1 c;
|
||||
if(!(is >> c)) return is;
|
||||
convert_cell(c, *C[j]);
|
||||
}
|
||||
|
||||
CGAL_triangulation_assertion( is_valid(false) );
|
||||
return is;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue