Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
tools
frackit
Commits
2d907608
Commit
2d907608
authored
Dec 10, 2020
by
Dennis Gläser
Browse files
[test] test new entity networks
parent
890a496f
Pipeline
#2763
passed with stages
in 12 minutes and 47 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
test/entitynetwork/CMakeLists.txt
View file @
2d907608
...
...
@@ -26,5 +26,9 @@ frackit_add_test(NAME test_generate_disk_network_cylinder
frackit_add_test
(
NAME test_generate_disk_network_shape
SOURCES test_generate_disk_network_shape.cc
LABELS entitynetwork sampling
COMPILE_DEFINITIONS BREPFILE=
"
${
CMAKE_SOURCE_DIR
}
/test/entitynetwork/layer.brep"
COMMAND ./test_generate_disk_network_shape
)
COMPILE_DEFINITIONS BREPFILE=
"
${
CMAKE_SOURCE_DIR
}
/test/entitynetwork/layer.brep"
)
# test entity network classes & corresponding I/O
frackit_add_test
(
NAME test_entity_network_3d
SOURCES test_entity_network_3d.cc
LABELS entitynetwork
)
test/entitynetwork/test_entity_network_3d.cc
0 → 100644
View file @
2d907608
#include
<iostream>
#include
<stdexcept>
#include
<algorithm>
#include
<unordered_map>
#include
<type_traits>
#include
<utility>
#include
<vector>
#include
<cmath>
#include
<BRepTools.hxx>
#include
<TopoDS.hxx>
#include
<TopoDS_Shape.hxx>
#include
<frackit/common/id.hh>
#include
<frackit/geometry/box.hh>
#include
<frackit/geometry/quadrilateral.hh>
#include
<frackit/magnitude/magnitude.hh>
#include
<frackit/occ/breputilities.hh>
#include
<frackit/entitynetwork/networkbuilder.hh>
#include
<frackit/io/brepwriter.hh>
// helper functions
template
<
class
List
,
class
Value
>
bool
contains
(
const
List
&
list
,
const
Value
&
v
);
void
testEquality
(
const
Frackit
::
Id
&
obtained
,
const
Frackit
::
Id
&
expected
);
void
testEquality
(
const
Frackit
::
IdPair
&
obtained
,
const
Frackit
::
IdPair
&
expected
);
template
<
class
ShapeType
>
bool
testShapeEquality
(
const
ShapeType
&
s1
,
const
ShapeType
&
s2
);
template
<
class
Network
>
void
testNetworkIds
(
const
Network
&
network
,
const
std
::
vector
<
std
::
size_t
>&
expDomainIds
,
const
std
::
vector
<
std
::
size_t
>&
expEntityIds
,
const
std
::
vector
<
std
::
size_t
>&
expIntersectionIds
,
const
std
::
vector
<
std
::
size_t
>&
expJunctionIds
)
{
using
namespace
Frackit
;
std
::
vector
<
std
::
size_t
>
foundIds
;
for
(
const
auto
&
domainFragment
:
subDomainFragments
(
network
))
{
foundIds
.
push_back
(
network
.
subDomainId
(
domainFragment
).
get
());
if
(
!
contains
(
expDomainIds
,
foundIds
.
back
()))
throw
std
::
runtime_error
(
"Unexpected subdomain id"
);
}
if
(
std
::
any_of
(
expDomainIds
.
begin
(),
expDomainIds
.
end
(),
[
&
]
(
auto
id
)
{
return
!
contains
(
foundIds
,
id
);
}))
throw
std
::
runtime_error
(
"Subdomain id not found"
);
for
(
auto
id
:
foundIds
)
for
(
const
auto
&
domainFragment
:
subDomainFragments
(
network
,
Id
(
id
)))
if
(
network
.
subDomainId
(
domainFragment
).
get
()
!=
id
)
throw
std
::
runtime_error
(
"Subdomain id mismatch"
);
foundIds
.
clear
();
for
(
const
auto
&
entityFragment
:
entityFragments
(
network
))
{
foundIds
.
push_back
(
network
.
entityId
(
entityFragment
).
get
());
if
(
!
contains
(
expEntityIds
,
foundIds
.
back
()))
throw
std
::
runtime_error
(
"Unexpected entity id"
);
}
if
(
std
::
any_of
(
expEntityIds
.
begin
(),
expEntityIds
.
end
(),
[
&
]
(
auto
id
)
{
return
!
contains
(
foundIds
,
id
);
}))
throw
std
::
runtime_error
(
"Entity id not found"
);
for
(
auto
id
:
foundIds
)
for
(
const
auto
&
entityFragment
:
entityFragments
(
network
,
Id
(
id
)))
if
(
network
.
entityId
(
entityFragment
).
get
()
!=
id
)
throw
std
::
runtime_error
(
"Entity id mismatch"
);
foundIds
.
clear
();
for
(
const
auto
&
intersectionFragment
:
intersectionFragments
(
network
))
{
foundIds
.
push_back
(
network
.
intersectionId
(
intersectionFragment
).
get
());
if
(
!
contains
(
expIntersectionIds
,
foundIds
.
back
()))
throw
std
::
runtime_error
(
"Unexpected intersection id"
);
}
if
(
std
::
any_of
(
expIntersectionIds
.
begin
(),
expIntersectionIds
.
end
(),
[
&
]
(
auto
id
)
{
return
!
contains
(
foundIds
,
id
);
}))
throw
std
::
runtime_error
(
"Intersection id not found"
);
for
(
auto
id
:
foundIds
)
for
(
const
auto
&
intersectionFragment
:
intersectionFragments
(
network
,
Id
(
id
)))
if
(
network
.
intersectionId
(
intersectionFragment
).
get
()
!=
id
)
throw
std
::
runtime_error
(
"Intersection id mismatch"
);
foundIds
.
clear
();
for
(
const
auto
&
junction
:
intersectionJunctions
(
network
))
{
foundIds
.
push_back
(
network
.
intersectionJunctionId
(
junction
).
get
());
if
(
!
contains
(
expJunctionIds
,
foundIds
.
back
()))
throw
std
::
runtime_error
(
"Unexpected junction id"
);
}
if
(
std
::
any_of
(
expJunctionIds
.
begin
(),
expJunctionIds
.
end
(),
[
&
]
(
auto
id
)
{
return
!
contains
(
foundIds
,
id
);
}))
throw
std
::
runtime_error
(
"Junction id not found"
);
}
template
<
class
Network
>
void
testNetworkSize
(
const
Network
&
network
,
const
std
::
array
<
std
::
size_t
,
8
>&
expCounts
)
{
// first check the result of the size query functions
if
(
network
.
numSubDomains
()
!=
expCounts
[
1
])
throw
std
::
runtime_error
(
"numSubDomains() failed"
);
if
(
network
.
numSubDomainFragments
()
!=
expCounts
[
0
])
throw
std
::
runtime_error
(
"numSubDomainFragments() failed"
);
if
(
network
.
numEntities
()
!=
expCounts
[
3
])
throw
std
::
runtime_error
(
"numEntities() failed"
);
if
(
network
.
numEntityFragments
()
!=
expCounts
[
2
])
throw
std
::
runtime_error
(
"numEntityFragments() failed"
);
if
(
network
.
numIntersections
()
!=
expCounts
[
5
])
throw
std
::
runtime_error
(
"numIntersections() failed"
);
if
(
network
.
numIntersectionFragments
()
!=
expCounts
[
4
])
throw
std
::
runtime_error
(
"numIntersectionFragments() failed"
);
if
(
network
.
numIntersectionJunctions
()
!=
expCounts
[
6
])
throw
std
::
runtime_error
(
"numIntersectionJunctions() failed"
);
if
(
network
.
numIntersectionJunctions
()
!=
expCounts
[
7
])
throw
std
::
runtime_error
(
"numIntersectionJunctions() failed"
);
std
::
array
<
std
::
size_t
,
8
>
counts
;
std
::
fill
(
counts
.
begin
(),
counts
.
end
(),
0
);
std
::
vector
<
std
::
size_t
>
found
;
for
(
const
auto
&
domainFragment
:
subDomainFragments
(
network
))
{
counts
[
0
]
++
;
const
auto
id
=
network
.
subDomainId
(
domainFragment
).
get
();
if
(
!
contains
(
found
,
id
))
{
found
.
push_back
(
id
);
counts
[
1
]
++
;
}
}
found
.
clear
();
for
(
const
auto
&
entityFragment
:
entityFragments
(
network
))
{
counts
[
2
]
++
;
const
auto
id
=
network
.
entityId
(
entityFragment
).
get
();
if
(
!
contains
(
found
,
id
))
{
found
.
push_back
(
id
);
counts
[
3
]
++
;
}
}
found
.
clear
();
for
(
const
auto
&
isFragment
:
intersectionFragments
(
network
))
{
counts
[
4
]
++
;
const
auto
id
=
network
.
intersectionId
(
isFragment
).
get
();
if
(
!
contains
(
found
,
id
))
{
found
.
push_back
(
id
);
counts
[
5
]
++
;
}
}
found
.
clear
();
for
(
const
auto
&
junction
:
intersectionJunctions
(
network
))
{
counts
[
6
]
++
;
const
auto
id
=
network
.
intersectionJunctionId
(
junction
).
get
();
if
(
!
contains
(
found
,
id
))
{
found
.
push_back
(
id
);
counts
[
7
]
++
;
}
}
auto
printArray
=
[]
(
const
std
::
string
&
pre
,
const
auto
&
a
)
{
std
::
cout
<<
pre
;
for
(
auto
v
:
a
)
std
::
cout
<<
v
<<
", "
;
std
::
cout
<<
std
::
endl
;
};
printArray
(
"Counts: "
,
counts
);
printArray
(
"Expected: "
,
expCounts
);
for
(
int
i
=
0
;
i
<
8
;
++
i
)
if
(
counts
[
i
]
!=
expCounts
[
i
])
throw
std
::
runtime_error
(
"Entity count mismatch"
);
}
template
<
class
Network
>
void
testNetworkMagnitudes
(
const
Network
&
network
,
const
std
::
vector
<
std
::
pair
<
double
,
int
>>&
volumes
,
const
std
::
vector
<
std
::
pair
<
double
,
int
>>&
areas
,
const
std
::
vector
<
std
::
pair
<
double
,
int
>>&
lengths
)
{
using
std
::
abs
;
auto
isEqual
=
[]
(
auto
a
,
auto
b
)
{
return
abs
(
a
-
b
)
<
1e-6
;
};
auto
matchesCount
=
[
&
isEqual
]
(
const
auto
&
v
,
auto
val
,
int
count
)
{
return
count
==
std
::
count_if
(
v
.
begin
(),
v
.
end
(),
[
&
]
(
auto
vVal
)
{
return
isEqual
(
val
,
vVal
);
});
};
auto
compare
=
[
&
]
(
const
std
::
string
&
magName
,
const
auto
&
found
,
const
auto
&
expected
)
{
std
::
cout
<<
"Found "
<<
magName
<<
": "
;
for
(
auto
m
:
found
)
{
std
::
cout
<<
m
<<
", "
;
}
std
::
cout
<<
std
::
endl
;
std
::
cout
<<
"Expected "
<<
magName
<<
": "
;
for
(
auto
[
m
,
count
]
:
expected
)
std
::
cout
<<
"{"
<<
m
<<
", "
<<
count
<<
"}, "
;
std
::
cout
<<
std
::
endl
;
for
(
auto
[
mag
,
count
]
:
expected
)
if
(
!
matchesCount
(
found
,
mag
,
count
))
throw
std
::
runtime_error
(
"Magnitude comparison failed"
);
};
std
::
vector
<
double
>
found
;
for
(
const
auto
&
domainFragment
:
subDomainFragments
(
network
))
found
.
push_back
(
Frackit
::
computeMagnitude
(
TopoDS
::
Solid
(
domainFragment
.
shape
())));
compare
(
"volumes"
,
found
,
volumes
);
found
.
clear
();
for
(
const
auto
&
entityFragment
:
entityFragments
(
network
))
found
.
push_back
(
Frackit
::
computeMagnitude
(
TopoDS
::
Face
(
entityFragment
.
shape
())));
compare
(
"areas"
,
found
,
areas
);
found
.
clear
();
for
(
const
auto
&
isFragment
:
intersectionFragments
(
network
))
found
.
push_back
(
Frackit
::
computeMagnitude
(
TopoDS
::
Edge
(
isFragment
.
shape
())));
compare
(
"lengths"
,
found
,
lengths
);
}
template
<
class
Network
>
void
testNetworkAdjacency
(
const
Network
&
network
)
{
for
(
const
auto
&
e
:
entityFragments
(
network
))
{
int
count
=
0
;
for
(
const
auto
&
i
:
embeddedFragments
(
network
,
e
))
{
count
++
;
bool
found
=
false
;
for
(
const
auto
&
ad
:
adjacentFragments
(
network
,
i
))
if
(
ad
.
index
()
==
e
.
index
())
found
=
true
;
if
(
!
found
)
throw
std
::
runtime_error
(
"Adjacency map not symmetric"
);
}
if
(
count
!=
2
)
throw
std
::
runtime_error
(
"Unexpected embedded isection count"
);
}
std
::
vector
<
std
::
size_t
>
counts
;
for
(
const
auto
&
i
:
intersectionFragments
(
network
))
{
int
count
=
0
;
for
(
const
auto
&
j
:
embeddedFragments
(
network
,
i
))
{
count
++
;
bool
found
=
false
;
for
(
const
auto
&
ad
:
adjacentFragments
(
network
,
j
))
if
(
ad
.
index
()
==
i
.
index
())
found
=
true
;
if
(
!
found
)
throw
std
::
runtime_error
(
"Adjacency map not symmetric"
);
}
counts
.
push_back
(
count
);
}
auto
throwErr
=
[]
()
{
throw
std
::
runtime_error
(
"Unexpected junction count"
);
};
const
auto
numZero
=
std
::
count
(
counts
.
begin
(),
counts
.
end
(),
0
);
const
auto
numOnes
=
std
::
count
(
counts
.
begin
(),
counts
.
end
(),
1
);
if
(
numOnes
!=
6
)
throwErr
();
if
(
numZero
!=
0
&&
numZero
!=
numOnes
)
throwErr
();
}
template
<
class
Network
>
void
testBRep
(
const
Network
&
network
)
{
using
namespace
Frackit
;
BRepWriter
writer
(
network
);
writer
.
write
(
"tmp"
);
using
namespace
OCCUtilities
;
const
auto
brepShape
=
readShape
(
"tmp.brep"
);
const
auto
brepVertices
=
getVertices
(
brepShape
);
const
auto
brepEdges
=
getEdges
(
brepShape
);
const
auto
brepFaces
=
getFaces
(
brepShape
);
const
auto
brepSolids
=
getSolids
(
brepShape
);
for
(
const
auto
&
domainFragment
:
subDomainFragments
(
network
))
{
const
auto
&
solid
=
TopoDS
::
Solid
(
domainFragment
.
shape
());
if
(
std
::
none_of
(
brepSolids
.
begin
(),
brepSolids
.
end
(),
[
&
]
(
const
auto
&
s
)
{
return
testShapeEquality
(
s
,
solid
);
}))
throw
std
::
runtime_error
(
"Solid not found in brep"
);
}
std
::
cout
<<
"All solids found in brep"
<<
std
::
endl
;
for
(
const
auto
&
entFragment
:
entityFragments
(
network
))
{
const
auto
&
face
=
TopoDS
::
Face
(
entFragment
.
shape
());
if
(
std
::
none_of
(
brepFaces
.
begin
(),
brepFaces
.
end
(),
[
&
]
(
const
auto
&
s
)
{
return
testShapeEquality
(
s
,
face
);
}))
throw
std
::
runtime_error
(
"Face not found in brep"
);
}
std
::
cout
<<
"All faces found in brep"
<<
std
::
endl
;
for
(
const
auto
&
isFragment
:
intersectionFragments
(
network
))
{
const
auto
&
edge
=
TopoDS
::
Edge
(
isFragment
.
shape
());
if
(
std
::
none_of
(
brepEdges
.
begin
(),
brepEdges
.
end
(),
[
&
]
(
const
auto
&
s
)
{
return
testShapeEquality
(
s
,
edge
);
}))
throw
std
::
runtime_error
(
"Edge not found in brep"
);
}
std
::
cout
<<
"All edges found in brep"
<<
std
::
endl
;
for
(
const
auto
&
junction
:
intersectionJunctions
(
network
))
{
const
auto
&
vertex
=
TopoDS
::
Vertex
(
junction
.
shape
());
if
(
std
::
none_of
(
brepVertices
.
begin
(),
brepVertices
.
end
(),
[
&
]
(
const
auto
&
s
)
{
return
testShapeEquality
(
s
,
vertex
);
}))
throw
std
::
runtime_error
(
"Vertex not found in brep"
);
}
std
::
cout
<<
"All vertices found in brep"
<<
std
::
endl
;
}
// test entity networks & builder
// this also tests the brepwriter for entity networks
int
main
()
{
using
namespace
Frackit
;
using
ctype
=
double
;
// test 2d entities in 3d domain
using
Point
=
Point
<
ctype
,
3
>
;
using
Quad
=
Quadrilateral
<
ctype
,
3
>
;
using
Box
=
Box
<
ctype
>
;
// quads split the domain into 8 blocks
Box
domain
(
Point
(
0.0
,
0.0
,
0.0
),
Point
(
1.0
,
1.0
,
1.0
));
Quad
quad1
(
Point
(
-
0.5
,
0.5
,
-
0.5
),
Point
(
1.5
,
0.5
,
-
0.5
),
Point
(
-
0.5
,
0.5
,
1.5
),
Point
(
1.5
,
0.5
,
1.5
));
Quad
quad2
(
Point
(
0.5
,
-
0.5
,
-
0.5
),
Point
(
0.5
,
1.5
,
-
0.5
),
Point
(
0.5
,
-
0.5
,
1.5
),
Point
(
0.5
,
1.5
,
1.5
));
Quad
quad3
(
Point
(
-
0.5
,
-
0.5
,
0.5
),
Point
(
1.5
,
-
0.5
,
0.5
),
Point
(
-
0.5
,
1.5
,
0.5
),
Point
(
1.5
,
1.5
,
0.5
));
std
::
vector
<
Quad
>
quadVec
{{
quad1
,
quad2
,
quad3
}};
auto
range
=
[]
(
std
::
size_t
start
,
std
::
size_t
end
)
{
std
::
vector
<
std
::
size_t
>
v
(
end
-
start
+
1
);
for
(
std
::
size_t
i
=
0
;
i
<
v
.
size
();
++
i
)
v
[
i
]
=
start
+
i
;
return
v
;
};
{
// test uncontained build
EntityNetworkBuilder
<
ctype
>
unconfinedBuilder
;
unconfinedBuilder
.
setConfineToSubDomainUnion
(
false
);
EntityNetworkBuilder
<
ctype
>
confinedBuilder
;
confinedBuilder
.
addSubDomain
(
domain
,
Id
(
1
));
////////////////////////////////////////////
// test expected result from add functions
testEquality
(
confinedBuilder
.
addSubDomainEntities
(
quadVec
,
Id
(
1
)),
IdPair
(
Id
(
1
),
Id
(
3
)));
testEquality
(
unconfinedBuilder
.
addEntity
(
quad1
),
Id
(
1
));
testEquality
(
unconfinedBuilder
.
addEntity
(
quad2
),
Id
(
2
));
testEquality
(
unconfinedBuilder
.
addEntity
(
quad3
),
Id
(
3
));
unconfinedBuilder
.
clear
();
testEquality
(
unconfinedBuilder
.
addEntities
(
quadVec
),
IdPair
(
Id
(
1
),
Id
(
3
)));
///////////////////////////////////////////
std
::
cout
<<
"Testing confined"
<<
std
::
endl
;
auto
n
=
confinedBuilder
.
build
();
testNetworkSize
(
n
,
{
0
,
0
,
12
,
3
,
6
,
6
,
1
,
1
});
testNetworkIds
(
n
,
{},
range
(
1
,
3
),
range
(
1
,
6
),
range
(
1
,
1
));
testNetworkMagnitudes
(
n
,
{{
0
,
0
}},
{{
0.25
,
12
}},
{{
0.5
,
6
}});
testNetworkAdjacency
(
n
);
testBRep
(
n
);
std
::
cout
<<
"
\n
Testing unconfined"
<<
std
::
endl
;
n
=
unconfinedBuilder
.
build
();
testNetworkIds
(
n
,
{},
range
(
1
,
3
),
range
(
1
,
6
),
range
(
1
,
1
));
testNetworkSize
(
n
,
{
0
,
0
,
12
,
3
,
6
,
6
,
1
,
1
});
testNetworkMagnitudes
(
n
,
{{
0
,
0
}},
{{
1.0
,
12
}},
{{
1.0
,
6
}});
testNetworkAdjacency
(
n
);
testBRep
(
n
);
}
{
// test contained build
ContainedEntityNetworkBuilder
<
ctype
>
confinedBuilder
;
confinedBuilder
.
addSubDomain
(
domain
,
Id
(
1
));
confinedBuilder
.
addSubDomainEntities
(
quadVec
,
Id
(
1
));
ContainedEntityNetworkBuilder
<
ctype
>
unconfinedBuilder
;
unconfinedBuilder
.
setConfineToSubDomainUnion
(
false
);
// test expected result from add functions
testEquality
(
unconfinedBuilder
.
addSubDomainEntity
(
quad1
,
Id
(
1
)),
Id
(
1
));
testEquality
(
unconfinedBuilder
.
addSubDomainEntity
(
quad2
,
Id
(
1
)),
Id
(
2
));
testEquality
(
unconfinedBuilder
.
addSubDomainEntity
(
quad3
,
Id
(
1
)),
Id
(
3
));
unconfinedBuilder
.
clear
();
unconfinedBuilder
.
addSubDomain
(
domain
,
Id
(
1
));
testEquality
(
unconfinedBuilder
.
addSubDomainEntities
(
quadVec
,
Id
(
1
)),
IdPair
(
Id
(
1
),
Id
(
3
)));
std
::
cout
<<
"
\n
Testing confined (contained)"
<<
std
::
endl
;
auto
n
=
confinedBuilder
.
build
();
testNetworkIds
(
n
,
range
(
1
,
1
),
range
(
1
,
3
),
range
(
1
,
6
),
range
(
1
,
1
));
testNetworkSize
(
n
,
{
8
,
1
,
12
,
3
,
6
,
6
,
1
,
1
});
testNetworkMagnitudes
(
n
,
{{
0.125
,
8
}},
{{
0.25
,
12
}},
{{
0.5
,
6
}});
testNetworkAdjacency
(
n
);
testBRep
(
n
);
std
::
cout
<<
"
\n
Testing unconfined (contained)"
<<
std
::
endl
;
n
=
unconfinedBuilder
.
build
();
testNetworkIds
(
n
,
range
(
1
,
1
),
range
(
1
,
3
),
range
(
1
,
6
),
range
(
1
,
1
));
testNetworkSize
(
n
,
{
8
,
1
,
24
,
3
,
12
,
6
,
1
,
1
});
testNetworkMagnitudes
(
n
,
{{
0.125
,
8
}},
{{
0.25
,
12
},
{
0.75
,
12
}},
{{
0.5
,
12
}});
testNetworkAdjacency
(
n
);
testBRep
(
n
);
}
std
::
cout
<<
"All tests passed"
<<
std
::
endl
;
return
0
;
}
////////////////////////////////////////////
// Implementations of some helper functions
template
<
class
List
,
class
Value
>
bool
contains
(
const
List
&
list
,
const
Value
&
v
)
{
return
std
::
count
(
list
.
begin
(),
list
.
end
(),
v
);
}
void
testEquality
(
const
Frackit
::
Id
&
obtained
,
const
Frackit
::
Id
&
expected
)
{
if
(
obtained
!=
expected
)
{
std
::
cout
<<
"Expected: "
<<
expected
.
get
()
<<
std
::
endl
;
std
::
cout
<<
"Found: "
<<
expected
.
get
()
<<
std
::
endl
;
throw
std
::
runtime_error
(
"Id does not match"
);
}
}
void
testEquality
(
const
Frackit
::
IdPair
&
obtained
,
const
Frackit
::
IdPair
&
expected
)
{
if
(
obtained
.
first
()
!=
expected
.
first
()
||
obtained
.
second
()
!=
expected
.
second
())
{
std
::
cout
<<
"Expected: "
<<
expected
.
first
().
get
()
<<
" - "
<<
expected
.
second
().
get
()
<<
std
::
endl
;
std
::
cout
<<
"Found: "
<<
obtained
.
first
().
get
()
<<
" - "
<<
obtained
.
second
().
get
()
<<
std
::
endl
;
throw
std
::
runtime_error
(
"Id pair does not match"
);
}
}
template
<
class
ShapeType
>
ShapeType
extractSingleShape
(
const
TopoDS_Shape
&
s
)
{
auto
checkLength
=
[]
(
auto
&
v
)
{
if
(
v
.
size
()
!=
1
)
throw
std
::
runtime_error
(
"Size"
);
};
using
namespace
Frackit
::
OCCUtilities
;
if
constexpr
(
std
::
is_same_v
<
ShapeType
,
TopoDS_Vertex
>
)
{
auto
v
=
getVertices
(
s
);
checkLength
(
v
);
return
TopoDS
::
Vertex
(
v
[
0
]);
}
if
constexpr
(
std
::
is_same_v
<
ShapeType
,
TopoDS_Edge
>
)
{
auto
v
=
getEdges
(
s
);
checkLength
(
v
);
return
TopoDS
::
Edge
(
v
[
0
]);
}
if
constexpr
(
std
::
is_same_v
<
ShapeType
,
TopoDS_Face
>
)
{
auto
v
=
getFaces
(
s
);
checkLength
(
v
);
return
TopoDS
::
Face
(
v
[
0
]);
}
if
constexpr
(
std
::
is_same_v
<
ShapeType
,
TopoDS_Solid
>
)
{
auto
v
=
getSolids
(
s
);
checkLength
(
v
);
return
TopoDS
::
Solid
(
v
[
0
]);
}
throw
std
::
runtime_error
(
"Unsupported shape type"
);
}
// we check equality based on the intersection and resulting magnitude
// rather than using the isEqual method. This is because we want to compare
// the shapes of a network to those that were read back in after writin it
// to a brep file. That seems to lead to IsEqual() to fail between a shape
// in the memory and one that was read back in from a file
template
<
class
ShapeType
>
bool
testShapeEquality
(
const
ShapeType
&
s1
,
const
ShapeType
&
s2
)
{
const
auto
m1
=
Frackit
::
computeMagnitude
(
s1
);
const
auto
m2
=
Frackit
::
computeMagnitude
(
s2
);
using
std
::
abs
;
if
(
abs
(
m2
-
m1
)
>
1e-6
)
return
false
;
const
auto
is
=
Frackit
::
OCCUtilities
::
intersect
(
s1
,
s2
,
1e-6
);
if
(
is
.
IsNull
())
return
false
;
ShapeType
isShape
;
try
{
isShape
=
extractSingleShape
<
ShapeType
>
(
is
);
}
catch
(...)
{
return
false
;
}
return
abs
(
Frackit
::
computeMagnitude
(
isShape
)
-
m1
)
<
1e-6
;
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment