mirror of
https://github.com/NGSolve/netgen.git
synced 2024-11-11 16:49:16 +05:00
modernize STL-meshing
This commit is contained in:
parent
ba620a5b41
commit
d7bf88e0cd
@ -229,6 +229,12 @@ namespace netgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Box (const Point<D> & p1, const Point<D> & p2, const Point<D> & p3)
|
||||||
|
: Box(p1,p2)
|
||||||
|
{
|
||||||
|
Add (p3);
|
||||||
|
}
|
||||||
|
|
||||||
enum EB_TYPE { EMPTY_BOX = 1 };
|
enum EB_TYPE { EMPTY_BOX = 1 };
|
||||||
Box ( EB_TYPE et )
|
Box ( EB_TYPE et )
|
||||||
{
|
{
|
||||||
|
@ -62,6 +62,7 @@ void STLMeshing (STLGeometry & geom,
|
|||||||
|
|
||||||
STLGeometry :: ~STLGeometry()
|
STLGeometry :: ~STLGeometry()
|
||||||
{
|
{
|
||||||
|
for (auto p : atlas) delete p;
|
||||||
delete edgedata;
|
delete edgedata;
|
||||||
delete ref;
|
delete ref;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
namespace netgen
|
namespace netgen
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
inline int IsInArray(int n, const Array<int>& ia)
|
inline int IsInArray(int n, const Array<int>& ia)
|
||||||
{
|
{
|
||||||
return ia.Contains(n);
|
return ia.Contains(n);
|
||||||
@ -37,6 +38,7 @@ namespace netgen
|
|||||||
list.Append(x);
|
list.Append(x);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
extern DLL_HEADER MeshingParameters mparam;
|
extern DLL_HEADER MeshingParameters mparam;
|
||||||
|
|
||||||
|
@ -818,7 +818,8 @@ void STLGeometry :: GetDirtyChartTrigs(int chartnum, STLChart& chart,
|
|||||||
|
|
||||||
if (GetChartNr(tn2) != chartnum && outercharttrigs.Get(tn2) != chartnum) {problem = 1;}
|
if (GetChartNr(tn2) != chartnum && outercharttrigs.Get(tn2) != chartnum) {problem = 1;}
|
||||||
}
|
}
|
||||||
if (problem && !IsInArray(j,dirtytrigs))
|
// if (problem && !IsInArray(j,dirtytrigs))
|
||||||
|
if (problem && !dirtytrigs.Contains(j))
|
||||||
{
|
{
|
||||||
dirtytrigs.Append(j);
|
dirtytrigs.Append(j);
|
||||||
cnt++;
|
cnt++;
|
||||||
|
@ -1174,14 +1174,18 @@ void STLGeometry :: RestrictHChartDistOneChart(int chartnum, Array<int>& acttrig
|
|||||||
{
|
{
|
||||||
Point3d p3p1 = GetPoint(np1);
|
Point3d p3p1 = GetPoint(np1);
|
||||||
Point3d p3p2 = GetPoint(np2);
|
Point3d p3p2 = GetPoint(np2);
|
||||||
if (AddIfNotExists(limes1,np1))
|
// if (AddIfNotExists(limes1,np1))
|
||||||
|
if (!limes1.Contains(np1))
|
||||||
{
|
{
|
||||||
|
limes1.Append(np1);
|
||||||
plimes1.Append(p3p1);
|
plimes1.Append(p3p1);
|
||||||
plimes1trigs.Append(t);
|
plimes1trigs.Append(t);
|
||||||
plimes1origin.Append(np1);
|
plimes1origin.Append(np1);
|
||||||
}
|
}
|
||||||
if (AddIfNotExists(limes1,np2))
|
// if (AddIfNotExists(limes1,np2))
|
||||||
|
if (!limes1.Contains(np2))
|
||||||
{
|
{
|
||||||
|
limes1.Append(np2);
|
||||||
plimes1.Append(p3p2);
|
plimes1.Append(p3p2);
|
||||||
plimes1trigs.Append(t);
|
plimes1trigs.Append(t);
|
||||||
plimes1origin.Append(np2);
|
plimes1origin.Append(np2);
|
||||||
@ -1226,8 +1230,20 @@ void STLGeometry :: RestrictHChartDistOneChart(int chartnum, Array<int>& acttrig
|
|||||||
Point3d p3p1 = GetPoint(np1);
|
Point3d p3p1 = GetPoint(np1);
|
||||||
Point3d p3p2 = GetPoint(np2);
|
Point3d p3p2 = GetPoint(np2);
|
||||||
|
|
||||||
if (AddIfNotExists(limes2,np1)) {plimes2.Append(p3p1); plimes2trigs.Append(t);}
|
// if (AddIfNotExists(limes2,np1)) {plimes2.Append(p3p1); plimes2trigs.Append(t);}
|
||||||
if (AddIfNotExists(limes2,np2)) {plimes2.Append(p3p2); plimes2trigs.Append(t);}
|
// if (AddIfNotExists(limes2,np2)) {plimes2.Append(p3p2); plimes2trigs.Append(t);}
|
||||||
|
if (!limes2.Contains(np1))
|
||||||
|
{
|
||||||
|
limes2.Append(np1);
|
||||||
|
plimes2.Append(p3p1);
|
||||||
|
plimes2trigs.Append(t);
|
||||||
|
}
|
||||||
|
if (!limes2.Contains(np2))
|
||||||
|
{
|
||||||
|
limes2.Append(np2);
|
||||||
|
plimes2.Append(p3p2);
|
||||||
|
plimes2trigs.Append(t);
|
||||||
|
}
|
||||||
chart.AddOLimit(twoint(np1,np2));
|
chart.AddOLimit(twoint(np1,np2));
|
||||||
|
|
||||||
for (int di = 1; di <= divisions; di++)
|
for (int di = 1; di <= divisions; di++)
|
||||||
|
@ -609,40 +609,62 @@ STLTopEdge :: STLTopEdge (int p1, int p2, int trig1, int trig2)
|
|||||||
|
|
||||||
STLChart :: STLChart(STLGeometry * ageometry)
|
STLChart :: STLChart(STLGeometry * ageometry)
|
||||||
{
|
{
|
||||||
charttrigs = new Array<int> (0,0);
|
// charttrigs = new Array<int> (0,0);
|
||||||
outertrigs = new Array<int> (0,0);
|
// outertrigs = new Array<int> (0,0);
|
||||||
ilimit = new Array<twoint> (0,0);
|
// ilimit = new Array<twoint> (0,0);
|
||||||
olimit = new Array<twoint> (0,0);
|
// olimit = new Array<twoint> (0,0);
|
||||||
|
|
||||||
geometry = ageometry;
|
geometry = ageometry;
|
||||||
|
|
||||||
if ( stlparam.usesearchtree == 1)
|
if ( stlparam.usesearchtree == 1)
|
||||||
searchtree = new BoxTree<3> (geometry->GetBoundingBox().PMin() - Vec3d(1,1,1),
|
{
|
||||||
geometry->GetBoundingBox().PMax() + Vec3d(1,1,1));
|
Box<3> box = geometry->GetBoundingBox();
|
||||||
|
box.Increase (0.2*box.Diam()+1e-12);
|
||||||
|
searchtree = new BoxTree<3> (box);
|
||||||
|
/*
|
||||||
|
searchtree = new BoxTree<3> (geometry->GetBoundingBox().PMin() - Vec3d(1,1,1),
|
||||||
|
geometry->GetBoundingBox().PMax() + Vec3d(1,1,1));
|
||||||
|
*/
|
||||||
|
}
|
||||||
else
|
else
|
||||||
searchtree = NULL;
|
searchtree = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STLChart :: ~STLChart()
|
||||||
|
{
|
||||||
|
delete searchtree;
|
||||||
|
}
|
||||||
|
|
||||||
void STLChart :: AddChartTrig(int i)
|
void STLChart :: AddChartTrig(int i)
|
||||||
{
|
{
|
||||||
// static int timer = NgProfiler::CreateTimer ("STLChart::AddChartTrig");
|
// static int timer = NgProfiler::CreateTimer ("STLChart::AddChartTrig");
|
||||||
// NgProfiler::RegionTimer reg(timer);
|
// NgProfiler::RegionTimer reg(timer);
|
||||||
|
|
||||||
charttrigs->Append(i);
|
charttrigs.Append(i);
|
||||||
|
|
||||||
const STLTriangle & trig = geometry->GetTriangle(i);
|
const STLTriangle & trig = geometry->GetTriangle(i);
|
||||||
const Point3d & p1 = geometry->GetPoint (trig.PNum(1));
|
const Point<3> & p1 = geometry->GetPoint (trig.PNum(1));
|
||||||
const Point3d & p2 = geometry->GetPoint (trig.PNum(2));
|
const Point<3> & p2 = geometry->GetPoint (trig.PNum(2));
|
||||||
const Point3d & p3 = geometry->GetPoint (trig.PNum(3));
|
const Point<3> & p3 = geometry->GetPoint (trig.PNum(3));
|
||||||
|
|
||||||
|
/*
|
||||||
Point3d pmin(p1), pmax(p1);
|
Point3d pmin(p1), pmax(p1);
|
||||||
pmin.SetToMin (p2);
|
pmin.SetToMin (p2);
|
||||||
pmin.SetToMin (p3);
|
pmin.SetToMin (p3);
|
||||||
pmax.SetToMax (p2);
|
pmax.SetToMax (p2);
|
||||||
pmax.SetToMax (p3);
|
pmax.SetToMax (p3);
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Box<3> box(p1);
|
||||||
|
box.Add(p2);
|
||||||
|
box.Add(p3);
|
||||||
|
*/
|
||||||
|
Box<3> box(p1,p2,p3);
|
||||||
if (!geomsearchtreeon && (stlparam.usesearchtree == 1))
|
if (!geomsearchtreeon && (stlparam.usesearchtree == 1))
|
||||||
{searchtree->Insert (pmin, pmax, i);}
|
// {searchtree->Insert (pmin, pmax, i);}
|
||||||
|
{
|
||||||
|
searchtree->Insert (box, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void STLChart :: AddOuterTrig(int i)
|
void STLChart :: AddOuterTrig(int i)
|
||||||
@ -650,7 +672,7 @@ void STLChart :: AddOuterTrig(int i)
|
|||||||
// static int timer = NgProfiler::CreateTimer ("STLChart::AddOuterTrig");
|
// static int timer = NgProfiler::CreateTimer ("STLChart::AddOuterTrig");
|
||||||
// NgProfiler::RegionTimer reg(timer);
|
// NgProfiler::RegionTimer reg(timer);
|
||||||
|
|
||||||
outertrigs->Append(i);
|
outertrigs.Append(i);
|
||||||
|
|
||||||
const STLTriangle & trig = geometry->GetTriangle(i);
|
const STLTriangle & trig = geometry->GetTriangle(i);
|
||||||
const Point3d & p1 = geometry->GetPoint (trig.PNum(1));
|
const Point3d & p1 = geometry->GetPoint (trig.PNum(1));
|
||||||
@ -669,11 +691,11 @@ void STLChart :: AddOuterTrig(int i)
|
|||||||
|
|
||||||
int STLChart :: IsInWholeChart(int nr) const
|
int STLChart :: IsInWholeChart(int nr) const
|
||||||
{
|
{
|
||||||
for (int i = 1; i <= charttrigs->Size(); i++)
|
for (int i = 1; i <= charttrigs.Size(); i++)
|
||||||
if (charttrigs->Get(i) == nr) return 1;
|
if (charttrigs.Get(i) == nr) return 1;
|
||||||
|
|
||||||
for (int i = 1; i <= outertrigs->Size(); i++)
|
for (int i = 1; i <= outertrigs.Size(); i++)
|
||||||
if (outertrigs->Get(i) == nr) return 1;
|
if (outertrigs.Get(i) == nr) return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -688,9 +710,8 @@ void STLChart :: GetTrianglesInBox (const Point3d & pmin,
|
|||||||
searchtree -> GetIntersecting (pmin, pmax, trias);
|
searchtree -> GetIntersecting (pmin, pmax, trias);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Box3d box1(pmin, pmax);
|
Box<3> box1(pmin, pmax);
|
||||||
box1.Increase (1e-4);
|
box1.Increase (1e-2*box1.Diam());
|
||||||
Box3d box2;
|
|
||||||
|
|
||||||
trias.SetSize(0);
|
trias.SetSize(0);
|
||||||
|
|
||||||
@ -699,9 +720,9 @@ void STLChart :: GetTrianglesInBox (const Point3d & pmin,
|
|||||||
{
|
{
|
||||||
int trignum = GetTrig(i);
|
int trignum = GetTrig(i);
|
||||||
const STLTriangle & trig = geometry->GetTriangle(trignum);
|
const STLTriangle & trig = geometry->GetTriangle(trignum);
|
||||||
box2.SetPoint (geometry->GetPoint (trig.PNum(1)));
|
Box<3> box2(geometry->GetPoint (trig.PNum(1)),
|
||||||
box2.AddPoint (geometry->GetPoint (trig.PNum(2)));
|
geometry->GetPoint (trig.PNum(2)),
|
||||||
box2.AddPoint (geometry->GetPoint (trig.PNum(3)));
|
geometry->GetPoint (trig.PNum(3)));
|
||||||
|
|
||||||
if (box1.Intersect (box2))
|
if (box1.Intersect (box2))
|
||||||
trias.Append (trignum);
|
trias.Append (trignum);
|
||||||
@ -712,12 +733,12 @@ void STLChart :: GetTrianglesInBox (const Point3d & pmin,
|
|||||||
//trigs may contain the same triangle double
|
//trigs may contain the same triangle double
|
||||||
void STLChart :: MoveToOuterChart(const Array<int>& trigs)
|
void STLChart :: MoveToOuterChart(const Array<int>& trigs)
|
||||||
{
|
{
|
||||||
if (!trigs.Size()) {return;}
|
if (!trigs.Size()) return;
|
||||||
for (int i = 1; i <= trigs.Size(); i++)
|
for (int i = 1; i <= trigs.Size(); i++)
|
||||||
{
|
{
|
||||||
if (charttrigs->Get(trigs.Get(i)) != -1)
|
if (charttrigs.Get(trigs.Get(i)) != -1)
|
||||||
{AddOuterTrig(charttrigs->Get(trigs.Get(i)));}
|
{AddOuterTrig(charttrigs.Get(trigs.Get(i)));}
|
||||||
charttrigs->Elem(trigs.Get(i)) = -1;
|
charttrigs.Elem(trigs.Get(i)) = -1;
|
||||||
}
|
}
|
||||||
DelChartTrigs(trigs);
|
DelChartTrigs(trigs);
|
||||||
}
|
}
|
||||||
@ -725,27 +746,22 @@ void STLChart :: MoveToOuterChart(const Array<int>& trigs)
|
|||||||
//trigs may contain the same triangle double
|
//trigs may contain the same triangle double
|
||||||
void STLChart :: DelChartTrigs(const Array<int>& trigs)
|
void STLChart :: DelChartTrigs(const Array<int>& trigs)
|
||||||
{
|
{
|
||||||
if (!trigs.Size()) {return;}
|
if (!trigs.Size()) return;
|
||||||
|
|
||||||
for (int i = 1; i <= trigs.Size(); i++)
|
for (int i = 1; i <= trigs.Size(); i++)
|
||||||
{
|
charttrigs.Elem(trigs.Get(i)) = -1;
|
||||||
charttrigs->Elem(trigs.Get(i)) = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
for (int i = 1; i <= charttrigs->Size(); i++)
|
for (int i = 1; i <= charttrigs.Size(); i++)
|
||||||
{
|
{
|
||||||
if (charttrigs->Elem(i) == -1)
|
if (charttrigs.Elem(i) == -1)
|
||||||
{
|
cnt++;
|
||||||
cnt++;
|
if (cnt != 0 && i < charttrigs.Size())
|
||||||
}
|
charttrigs.Elem(i-cnt+1) = charttrigs.Get(i+1);
|
||||||
if (cnt != 0 && i < charttrigs->Size())
|
|
||||||
{
|
|
||||||
charttrigs->Elem(i-cnt+1) = charttrigs->Get(i+1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
int i = charttrigs->Size() - trigs.Size();
|
|
||||||
charttrigs->SetSize(i);
|
int i = charttrigs.Size() - trigs.Size();
|
||||||
|
charttrigs.SetSize(i);
|
||||||
|
|
||||||
if (!geomsearchtreeon && stlparam.usesearchtree == 1)
|
if (!geomsearchtreeon && stlparam.usesearchtree == 1)
|
||||||
{
|
{
|
||||||
@ -754,7 +770,7 @@ void STLChart :: DelChartTrigs(const Array<int>& trigs)
|
|||||||
searchtree = new BoxTree<3> (geometry->GetBoundingBox().PMin() - Vec3d(1,1,1),
|
searchtree = new BoxTree<3> (geometry->GetBoundingBox().PMin() - Vec3d(1,1,1),
|
||||||
geometry->GetBoundingBox().PMax() + Vec3d(1,1,1));
|
geometry->GetBoundingBox().PMax() + Vec3d(1,1,1));
|
||||||
|
|
||||||
for (int i = 1; i <= charttrigs->Size(); i++)
|
for (int i = 1; i <= charttrigs.Size(); i++)
|
||||||
{
|
{
|
||||||
const STLTriangle & trig = geometry->GetTriangle(i);
|
const STLTriangle & trig = geometry->GetTriangle(i);
|
||||||
const Point3d & p1 = geometry->GetPoint (trig.PNum(1));
|
const Point3d & p1 = geometry->GetPoint (trig.PNum(1));
|
||||||
@ -767,7 +783,7 @@ void STLChart :: DelChartTrigs(const Array<int>& trigs)
|
|||||||
pmax.SetToMax (p2);
|
pmax.SetToMax (p2);
|
||||||
pmax.SetToMax (p3);
|
pmax.SetToMax (p3);
|
||||||
|
|
||||||
searchtree->Insert (pmin, pmax, i);
|
searchtree->Insert (pmin, pmax, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -831,21 +847,17 @@ void STLBoundarySeg :: Swap ()
|
|||||||
|
|
||||||
|
|
||||||
STLBoundary :: STLBoundary (STLGeometry * ageometry)
|
STLBoundary :: STLBoundary (STLGeometry * ageometry)
|
||||||
: // boundary(),
|
: geometry(ageometry)
|
||||||
geometry(ageometry)
|
{ ; }
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void STLBoundary :: AddOrDelSegment(const STLBoundarySeg & seg)
|
void STLBoundary :: AddOrDelSegment(const STLBoundarySeg & seg)
|
||||||
{
|
{
|
||||||
int i;
|
bool found = false;
|
||||||
int found = 0;
|
for (int i = 1; i <= boundary.Size(); i++)
|
||||||
for (i = 1; i <= boundary.Size(); i++)
|
|
||||||
{
|
{
|
||||||
if (found) {boundary.Elem(i-1) = boundary.Get(i);}
|
if (found) { boundary.Elem(i-1) = boundary.Get(i); }
|
||||||
if (boundary.Get(i) == seg) {found = 1;}
|
if (boundary.Get(i) == seg) { found = true; }
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
|
@ -43,49 +43,50 @@ class STLChart
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
STLGeometry * geometry;
|
STLGeometry * geometry;
|
||||||
Array<int>* charttrigs; // trigs which only belong to this chart
|
Array<int> charttrigs; // trigs which only belong to this chart
|
||||||
Array<int>* outertrigs; // trigs which belong to other charts
|
Array<int> outertrigs; // trigs which belong to other charts
|
||||||
BoxTree<3> * searchtree; // ADT containing outer trigs
|
BoxTree<3> * searchtree; // ADT containing outer trigs
|
||||||
|
|
||||||
Array<twoint>* olimit; //outer limit of outer chart
|
Array<twoint> olimit; //outer limit of outer chart
|
||||||
Array<twoint>* ilimit; //outer limit of inner chart
|
Array<twoint> ilimit; //outer limit of inner chart
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
STLChart(STLGeometry * ageometry);
|
STLChart(STLGeometry * ageometry);
|
||||||
|
~STLChart();
|
||||||
void AddChartTrig(int i);
|
void AddChartTrig(int i);
|
||||||
void AddOuterTrig(int i);
|
void AddOuterTrig(int i);
|
||||||
|
|
||||||
int IsInWholeChart(int nr) const;
|
int IsInWholeChart(int nr) const;
|
||||||
|
|
||||||
int GetChartTrig(int i) const {return charttrigs->Get(i);}
|
int GetChartTrig(int i) const {return charttrigs.Get(i);}
|
||||||
int GetOuterTrig(int i) const {return outertrigs->Get(i);}
|
int GetOuterTrig(int i) const {return outertrigs.Get(i);}
|
||||||
//get all trigs:
|
//get all trigs:
|
||||||
int GetTrig(int i) const
|
int GetTrig(int i) const
|
||||||
{
|
{
|
||||||
if (i <= charttrigs->Size()) {return charttrigs->Get(i);}
|
if (i <= charttrigs.Size()) {return charttrigs.Get(i);}
|
||||||
else {return outertrigs->Get(i-charttrigs->Size());}
|
else {return outertrigs.Get(i-charttrigs.Size());}
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetNChartT() const {return charttrigs->Size();}
|
int GetNChartT() const {return charttrigs.Size();}
|
||||||
int GetNOuterT() const {return outertrigs->Size();}
|
int GetNOuterT() const {return outertrigs.Size();}
|
||||||
int GetNT() const {return charttrigs->Size()+outertrigs->Size(); }
|
int GetNT() const {return charttrigs.Size()+outertrigs.Size(); }
|
||||||
|
|
||||||
void GetTrianglesInBox (const Point3d & pmin,
|
void GetTrianglesInBox (const Point3d & pmin,
|
||||||
const Point3d & pmax,
|
const Point3d & pmax,
|
||||||
Array<int> & trias) const;
|
Array<int> & trias) const;
|
||||||
void AddOLimit(twoint l) {olimit->Append(l);}
|
void AddOLimit(twoint l) {olimit.Append(l);}
|
||||||
void AddILimit(twoint l) {ilimit->Append(l);}
|
void AddILimit(twoint l) {ilimit.Append(l);}
|
||||||
|
|
||||||
void ClearOLimit() {olimit->SetSize(0);}
|
void ClearOLimit() {olimit.SetSize(0);}
|
||||||
void ClearILimit() {ilimit->SetSize(0);}
|
void ClearILimit() {ilimit.SetSize(0);}
|
||||||
|
|
||||||
int GetNOLimit() const {return olimit->Size();}
|
int GetNOLimit() const {return olimit.Size();}
|
||||||
int GetNILimit() const {return ilimit->Size();}
|
int GetNILimit() const {return ilimit.Size();}
|
||||||
|
|
||||||
twoint GetOLimit(int i) const {return olimit->Get(i);}
|
twoint GetOLimit(int i) const {return olimit.Get(i);}
|
||||||
twoint GetILimit(int i) const {return ilimit->Get(i);}
|
twoint GetILimit(int i) const {return ilimit.Get(i);}
|
||||||
|
|
||||||
//move triangles trigs (local chart-trig numbers) to outer chart
|
//move triangles trigs (local chart-trig numbers) to outer chart
|
||||||
void MoveToOuterChart(const Array<int>& trigs);
|
void MoveToOuterChart(const Array<int>& trigs);
|
||||||
|
Loading…
Reference in New Issue
Block a user