WIP (shielding, various bug fixes)

This commit is contained in:
Matthias Koefferlein
2021-01-17 14:38:44 +01:00
parent 9a55bdc687
commit fd90e66ee1
25 changed files with 247 additions and 143 deletions
+4 -4
View File
@@ -1601,11 +1601,11 @@ CompoundRegionCheckOperationNode::do_compute_local (db::Layout *layout, const sh
tl_assert (results.size () == 1);
if (results.front ().empty ()) {
op.compute_local (layout, interactions, results, max_vertex_count, area_ratio);
op.do_compute_local (layout, interactions, results, max_vertex_count, area_ratio);
} else {
std::vector<std::unordered_set<db::EdgePair> > r;
r.resize (1);
op.compute_local (layout, interactions, r, max_vertex_count, area_ratio);
op.do_compute_local (layout, interactions, r, max_vertex_count, area_ratio);
results.front ().insert (r.front ().begin (), r.front ().end ());
}
}
@@ -1617,11 +1617,11 @@ CompoundRegionCheckOperationNode::do_compute_local (db::Layout *layout, const sh
tl_assert (results.size () == 1);
if (results.front ().empty ()) {
op.compute_local (layout, interactions, results, max_vertex_count, area_ratio);
op.do_compute_local (layout, interactions, results, max_vertex_count, area_ratio);
} else {
std::vector<std::unordered_set<db::EdgePair> > r;
r.resize (1);
op.compute_local (layout, interactions, r, max_vertex_count, area_ratio);
op.do_compute_local (layout, interactions, r, max_vertex_count, area_ratio);
results.front ().insert (r.front ().begin (), r.front ().end ());
}
}
+5 -1
View File
@@ -680,7 +680,11 @@ public:
virtual ResultType result_type () const { return compound_operation_type_traits<TR>::type (); }
virtual const db::TransformationReducer *vars () const { return mp_vars; }
virtual bool wants_variants () const { return m_wants_variants; }
virtual db::Coord computed_dist () const { return m_op->dist (); }
virtual db::Coord computed_dist () const
{
return CompoundRegionMultiInputOperationNode::computed_dist () + m_op->dist ();
}
virtual std::vector<db::Region *> inputs () const
{
+64
View File
@@ -33,10 +33,74 @@
#include "tlLog.h"
#include "tlTimer.h"
#include "tlInternational.h"
#include "tlProgress.h"
namespace db
{
// ---------------------------------------------------------------------------------------------
// local_operations implementation
template <class TS, class TI, class TR>
void local_operation<TS, TI, TR>::compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t max_vertex_count, double area_ratio, bool report_progress, const std::string &progress_desc) const
{
if (interactions.num_subjects () <= 1 || ! requests_single_subjects ()) {
do_compute_local (layout, interactions, results, max_vertex_count, area_ratio);
} else {
std::auto_ptr<tl::RelativeProgress> progress;
if (report_progress) {
progress.reset (new tl::RelativeProgress (progress_desc, interactions.size ()));
}
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const TS &subject_shape = interactions.subject_shape (i->first);
shape_interactions<TS, TI> single_interactions;
if (on_empty_intruder_hint () == OnEmptyIntruderHint::Drop) {
single_interactions.add_subject_shape (i->first, subject_shape);
} else {
// this includes the subject-without-intruder "interaction"
single_interactions.add_subject (i->first, subject_shape);
}
const std::vector<unsigned int> &intruders = interactions.intruders_for (i->first);
for (typename std::vector<unsigned int>::const_iterator ii = intruders.begin (); ii != intruders.end (); ++ii) {
const std::pair<unsigned int, TI> &is = interactions.intruder_shape (*ii);
single_interactions.add_intruder_shape (*ii, is.first, is.second);
single_interactions.add_interaction (i->first, *ii);
}
do_compute_local (layout, single_interactions, results, max_vertex_count, area_ratio);
if (progress.get ()) {
++*progress;
}
}
}
}
// explicit instantiations
template class DB_PUBLIC local_operation<db::Polygon, db::Polygon, db::Polygon>;
template class DB_PUBLIC local_operation<db::Polygon, db::Text, db::Polygon>;
template class DB_PUBLIC local_operation<db::Polygon, db::Text, db::Text>;
template class DB_PUBLIC local_operation<db::Polygon, db::Edge, db::Polygon>;
template class DB_PUBLIC local_operation<db::Polygon, db::Edge, db::Edge>;
template class DB_PUBLIC local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>;
template class DB_PUBLIC local_operation<db::PolygonRef, db::Edge, db::PolygonRef>;
template class DB_PUBLIC local_operation<db::PolygonRef, db::PolygonRef, db::EdgePair>;
template class DB_PUBLIC local_operation<db::Polygon, db::Polygon, db::EdgePair>;
template class DB_PUBLIC local_operation<db::Edge, db::Edge, db::Edge>;
template class DB_PUBLIC local_operation<db::Edge, db::PolygonRef, db::Edge>;
template class DB_PUBLIC local_operation<db::Edge, db::Edge, db::EdgePair>;
// ---------------------------------------------------------------------------------------------
// BoolAndOrNotLocalOperation implementation
+1 -48
View File
@@ -29,8 +29,6 @@
#include "dbLayout.h"
#include "dbEdgeBoolean.h"
#include "tlProgress.h"
#include "tlInternational.h"
#include <unordered_map>
#include <unordered_set>
@@ -89,55 +87,10 @@ public:
/**
* @brief Computes the results from a given set of interacting shapes
* @param layout The layout to which the shapes belong
* @param interactions The interaction set
* @param result The container to which the results are written
*
* If the operation requests single subject mode, the interactions will be split into single subject/intruder clusters
*/
void compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t max_vertex_count, double area_ratio, bool report_progress = false, const std::string &progress_desc = std::string ()) const
{
if (interactions.num_subjects () <= 1 || ! requests_single_subjects ()) {
do_compute_local (layout, interactions, results, max_vertex_count, area_ratio);
} else {
std::auto_ptr<tl::RelativeProgress> progress;
if (report_progress) {
progress.reset (new tl::RelativeProgress (progress_desc, interactions.size ()));
}
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
const TS &subject_shape = interactions.subject_shape (i->first);
shape_interactions<TS, TI> single_interactions;
if (on_empty_intruder_hint () == OnEmptyIntruderHint::Drop) {
single_interactions.add_subject_shape (i->first, subject_shape);
} else {
// this includes the subject-without-intruder "interaction"
single_interactions.add_subject (i->first, subject_shape);
}
const std::vector<unsigned int> &intruders = interactions.intruders_for (i->first);
for (typename std::vector<unsigned int>::const_iterator ii = intruders.begin (); ii != intruders.end (); ++ii) {
const std::pair<unsigned int, TI> &is = interactions.intruder_shape (*ii);
single_interactions.add_intruder_shape (*ii, is.first, is.second);
single_interactions.add_interaction (i->first, *ii);
}
do_compute_local (layout, single_interactions, results, max_vertex_count, area_ratio);
if (progress.get ()) {
++*progress;
}
}
}
}
void compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<TR> > &results, size_t max_vertex_count, double area_ratio, bool report_progress = false, const std::string &progress_desc = std::string ()) const;
/**
* @brief Indicates the desired behaviour when a shape does not have an intruder
+5 -34
View File
@@ -200,9 +200,9 @@ void
check_local_operation<TS, TI>::do_compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
{
tl_assert (results.size () == 1);
std::unordered_set<db::EdgePair> result;
std::unordered_set<db::EdgePair> result, intra_polygon_result;
edge2edge_check_negative_or_positive<std::unordered_set<db::EdgePair> > edge_check (m_check, result, m_options.negative, true, true, m_options.shielded);
edge2edge_check_negative_or_positive<std::unordered_set<db::EdgePair> > edge_check (m_check, result, intra_polygon_result, m_options.negative, m_different_polygons, m_has_other, m_options.shielded);
poly2poly_check<TS> poly_check (edge_check);
std::list<TS> heap;
@@ -302,30 +302,6 @@ check_local_operation<TS, TI>::do_compute_local (db::Layout *layout, const shape
scanner.process (poly_check, m_check.distance (), db::box_convert<TS> ());
} while (edge_check.prepare_next_pass ());
// now also handle the intra-polygon interactions if required
std::unordered_set<db::EdgePair> intra_polygon_result;
if (! m_different_polygons && ! m_has_other) {
for (typename shape_interactions<TS, TI>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
std::list<TS> heap;
const TS &subject = interactions.subject_shape (i->first);
scanner.clear ();
scanner.insert (push_polygon_to_heap (layout, subject, heap), 0);
edge2edge_check_negative_or_positive<std::unordered_set<db::EdgePair> > edge_check_intra (m_check, intra_polygon_result, m_options.negative, false, false, m_options.shielded);
poly2poly_check<TS> poly_check_intra (edge_check_intra);
do {
scanner.process (poly_check_intra, m_check.distance (), db::box_convert<TS> ());
} while (edge_check_intra.prepare_next_pass ());
}
}
// detect and remove parts of the result which have or do not have results "opposite"
// ("opposite" is defined by the projection of edges "through" the subject shape)
@@ -497,18 +473,13 @@ check_local_operation<TS, TI>::do_compute_local (db::Layout *layout, const shape
for (std::unordered_set<db::EdgePair>::const_iterator i = result.begin (); i != result.end (); ++i) {
results.front ().insert (db::EdgePair (i->first (), i->first ().swapped_points ()));
}
} else {
results.front ().insert (result.begin (), result.end ());
result.clear ();
}
} else {
results.front ().insert (result.begin (), result.end ());
}
results.front ().insert (result.begin (), result.end ());
}
template <class TS, class TI>
+2 -2
View File
@@ -210,14 +210,14 @@ public:
virtual bool requests_single_subjects () const { return true; }
virtual std::string description () const;
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
private:
EdgeRelationFilter m_check;
bool m_different_polygons;
bool m_has_other;
bool m_other_is_merged;
db::RegionCheckOptions m_options;
virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions<TS, TI> &interactions, std::vector<std::unordered_set<db::EdgePair> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const;
};
typedef check_local_operation<db::PolygonRef, db::PolygonRef> CheckLocalOperation;
+14 -3
View File
@@ -67,6 +67,7 @@ Edge2EdgeCheckBase::prepare_next_pass ()
if (! m_ep.empty () && m_has_edge_pair_output) {
std::vector<bool>::const_iterator d = m_ep_discarded.begin ();
std::vector<bool>::const_iterator i = m_ep_intra_polygon.begin ();
std::vector<db::EdgePair>::const_iterator ep = m_ep.begin ();
while (ep != m_ep.end () && size_t (ep - m_ep.begin ()) < m_first_pseudo) {
bool use_result = true;
@@ -75,9 +76,10 @@ Edge2EdgeCheckBase::prepare_next_pass ()
++d;
}
if (use_result) {
put (*ep);
put (*ep, *i);
}
++ep;
++i;
}
}
@@ -182,7 +184,10 @@ Edge2EdgeCheckBase::add (const db::Edge *o1, size_t p1, const db::Edge *o2, size
// pass we will eliminate those which are shielded completely (with shielding)
// and/or compute the negative edges.
size_t n = m_ep.size ();
m_ep.push_back (ep);
m_ep_intra_polygon.push_back (p1 == p2);
m_e2ep.insert (std::make_pair (std::make_pair (*o1, p1), n * 2));
m_e2ep.insert (std::make_pair (std::make_pair (*o2, p2), n * 2 + 1));
@@ -253,9 +258,12 @@ Edge2EdgeCheckBase::add (const db::Edge *o1, size_t p1, const db::Edge *o2, size
}
// for negative output edges are cancelled by short interactions perpendicular to them
// For this we have generated "pseudo edges" running along the sides of the original violation. We now check a real
// edge vs. a pseudo edge with the same conditions as the normal interaction and add them to the results. In the
// negative case this means we cancel a real edge.
if (m_has_negative_edge_output &&
(m_pseudo_edges.find (std::make_pair (*o1, p1)) != m_pseudo_edges.end () || m_pseudo_edges.find (std::make_pair (*o2, p2)) != m_pseudo_edges.end ()) &&
! (m_pseudo_edges.find (std::make_pair (*o1, p1)) != m_pseudo_edges.end () && m_pseudo_edges.find (std::make_pair (*o2, p2)) != m_pseudo_edges.end ())) {
(m_pseudo_edges.find (std::make_pair (*o1, p1)) != m_pseudo_edges.end ()) != (m_pseudo_edges.find (std::make_pair (*o2, p2)) != m_pseudo_edges.end ())) {
// Overlap or inside checks require input from different layers
if ((! m_different_polygons || p1 != p2) && (! m_requires_different_layers || ((p1 ^ p2) & 1) != 0)) {
@@ -274,7 +282,10 @@ Edge2EdgeCheckBase::add (const db::Edge *o1, size_t p1, const db::Edge *o2, size
if (mp_check->check (*o1, *o2, &ep)) {
size_t n = m_ep.size ();
m_ep.push_back (ep);
m_ep_intra_polygon.push_back (p1 == p2); // not really required, but there for consistency
m_e2ep.insert (std::make_pair (std::make_pair (*o1, p1), n * 2));
m_e2ep.insert (std::make_pair (std::make_pair (*o2, p2), n * 2 + 1));
+41 -31
View File
@@ -612,7 +612,7 @@ protected:
/**
* @brief Normal edge pair output (violations)
*/
virtual void put (const db::EdgePair & /*edge*/) const { }
virtual void put (const db::EdgePair & /*edge*/, bool /*intra-polygon*/) const { }
/**
* @brief Negative edge output
@@ -628,7 +628,7 @@ private:
std::multimap<std::pair<db::Edge, size_t>, size_t> m_e2ep;
std::set<std::pair<db::Edge, size_t> > m_pseudo_edges;
size_t m_first_pseudo;
std::vector<bool> m_ep_discarded;
std::vector<bool> m_ep_discarded, m_ep_intra_polygon;
bool m_with_shielding;
bool m_has_edge_pair_output;
bool m_has_negative_edge_output;
@@ -646,19 +646,30 @@ class DB_PUBLIC_TEMPLATE edge2edge_check
{
public:
edge2edge_check (const EdgeRelationFilter &check, Output &output, bool different_polygons, bool requires_different_layers, bool with_shielding)
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding), mp_output (&output)
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding), mp_output_inter (&output), mp_output_intra (0)
{
// .. nothing yet ..
}
edge2edge_check (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool different_polygons, bool requires_different_layers, bool with_shielding)
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding), mp_output_inter (&output_inter), mp_output_intra (&output_intra)
{
// .. nothing yet ..
}
protected:
void put (const db::EdgePair &edge) const
void put (const db::EdgePair &edge, bool inter_polygon) const
{
mp_output->insert (edge);
if (! inter_polygon || ! mp_output_intra) {
mp_output_inter->insert (edge);
} else {
mp_output_intra->insert (edge);
}
}
private:
Output *mp_output;
Output *mp_output_inter;
Output *mp_output_intra;
};
/**
@@ -669,24 +680,26 @@ private:
*/
template <class Output, class NegativeEdgeOutput>
class DB_PUBLIC_TEMPLATE edge2edge_check_with_negative_output
: public Edge2EdgeCheckBase
: public edge2edge_check<Output>
{
public:
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding)
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding),
mp_output (&output),
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding),
mp_l1_negative_output (&l1_negative_output),
mp_l2_negative_output (&l2_negative_output)
{
set_has_negative_edge_output (true);
edge2edge_check<Output>::set_has_negative_edge_output (true);
}
edge2edge_check_with_negative_output (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, NegativeEdgeOutput &l1_negative_output, NegativeEdgeOutput &l2_negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding)
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding),
mp_l1_negative_output (&l1_negative_output),
mp_l2_negative_output (&l2_negative_output)
{
edge2edge_check<Output>::set_has_negative_edge_output (true);
}
protected:
void put (const db::EdgePair &ep) const
{
mp_output->insert (ep);
}
void put_negative (const db::Edge &edge, int layer) const
{
if (layer == 0) {
@@ -698,7 +711,6 @@ protected:
}
private:
Output *mp_output;
NegativeEdgeOutput *mp_l1_negative_output, *mp_l2_negative_output;
};
@@ -746,35 +758,33 @@ private:
*/
template <class Output>
class DB_PUBLIC_TEMPLATE edge2edge_check_negative_or_positive
: public Edge2EdgeCheckBase
: public edge2edge_check<Output>
{
public:
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding)
: Edge2EdgeCheckBase (check, different_polygons, requires_different_layers, with_shielding),
mp_output (&output)
: edge2edge_check<Output> (check, output, different_polygons, requires_different_layers, with_shielding)
{
set_has_negative_edge_output (negative_output);
set_has_edge_pair_output (! negative_output);
edge2edge_check<Output>::set_has_negative_edge_output (negative_output);
edge2edge_check<Output>::set_has_edge_pair_output (! negative_output);
}
edge2edge_check_negative_or_positive (const EdgeRelationFilter &check, Output &output_inter, Output &output_intra, bool negative_output, bool different_polygons, bool requires_different_layers, bool with_shielding)
: edge2edge_check<Output> (check, output_inter, output_intra, different_polygons, requires_different_layers, with_shielding)
{
edge2edge_check<Output>::set_has_negative_edge_output (negative_output);
edge2edge_check<Output>::set_has_edge_pair_output (! negative_output);
}
protected:
void put_negative (const db::Edge &edge, int layer) const
{
if (layer == 0) {
mp_output->insert (db::EdgePair (edge, edge.swapped_points ()));
edge2edge_check<Output>::put (db::EdgePair (edge, edge.swapped_points ()), false);
}
if (layer == 1) {
mp_output->insert (db::EdgePair (edge.swapped_points (), edge));
edge2edge_check<Output>::put (db::EdgePair (edge.swapped_points (), edge), false);
}
}
void put (const db::EdgePair &edge) const
{
mp_output->insert (edge);
}
private:
Output *mp_output;
};
/**
+4 -7
View File
@@ -426,13 +426,10 @@ static db::CompoundRegionOperationNode *new_width_check (db::Coord d, bool whole
static db::CompoundRegionOperationNode *new_space_or_isolated_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative, bool isolated)
{
if (opposite_filter != db::NoOppositeFilter || rect_filter != db::NoSideAllowed || shielded) {
// NOTE: we have to use the "foreign" scheme with a filter because only this scheme
// guarantees that all subject shapes are visited and receive all intruders.
return new_check_node (new_foreign (), db::SpaceRelation, isolated, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
} else {
return new_check_node (db::SpaceRelation, isolated, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
}
// NOTE: we have to use the "foreign" scheme with a filter because only this scheme
// guarantees that all subject shapes are visited and receive all intruders. Having all intruders is crucial for the
// semantics of the "drc" feature
return new_check_node (new_foreign (), db::SpaceRelation, isolated, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative);
}
static db::CompoundRegionOperationNode *new_space_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative)
+20
View File
@@ -218,3 +218,23 @@ TEST(15d)
{
run_test (_this, "15", true);
}
TEST(16)
{
run_test (_this, "16", false);
}
TEST(16d)
{
run_test (_this, "16", true);
}
TEST(17)
{
run_test (_this, "17", false);
}
TEST(17d)
{
run_test (_this, "17", true);
}
+10
View File
@@ -1137,3 +1137,13 @@ TEST(26d_attributes)
{
run_test (_this, "26", true);
}
TEST(27_advancedShielding)
{
run_test (_this, "27", false);
}
TEST(27d_advancedShielding)
{
run_test (_this, "27", true);
}
+19
View File
@@ -0,0 +1,19 @@
source $drc_test_source
target $drc_test_target
if $drc_test_deep
deep
end
l1 = input(1, 0)
l2 = input(2, 0)
l3 = input(3, 0)
l1.output(1, 0)
l2.output(2, 0)
l3.output(3, 0)
l1.drc(primary.interacting((space(shielded) < 1.0).polygons)).output(100, 0)
l1.drc(primary.interacting((space(transparent) < 1.0).polygons)).output(101, 0)
Binary file not shown.
+24
View File
@@ -0,0 +1,24 @@
source $drc_test_source
target $drc_test_target
if $drc_test_deep
deep
end
l1 = input(1, 0)
l2 = input(2, 0)
l3 = input(3, 0)
l1.output(1, 0)
l2.output(2, 0)
l3.output(3, 0)
# advanced shielding (self, symmetric space)
l1.drc(width(projection, shielded) < 1.0).output(100, 0)
l1.drc(width(projection, transparent) < 1.0).output(101, 0)
l1.drc(space(projection, shielded) < 1.0).output(110, 0)
l1.drc(space(projection, transparent) < 1.0).output(111, 0)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+24
View File
@@ -0,0 +1,24 @@
source $drc_test_source
target $drc_test_target
if $drc_test_deep
deep
end
l1 = input(1, 0)
l2 = input(2, 0)
l3 = input(3, 0)
l1.output(1, 0)
l2.output(2, 0)
l3.output(3, 0)
# advanced shielding (self, symmetric space)
l1.width(1.0, projection, shielded).output(100, 0)
l1.width(1.0, projection, transparent).output(101, 0)
l1.space(1.0, projection, shielded).output(110, 0)
l1.space(1.0, projection, transparent).output(111, 0)
Binary file not shown.
Binary file not shown.
Binary file not shown.
+10 -13
View File
@@ -321,19 +321,16 @@ def run_testsuite(dm, ic, tiled = false, hier = false)
lb += 10 #230
message "--- isolated #{lb}"
b.isolated(0.4).polygons.output(lb, dm)
b.isolated(0.4).polygons.xor(b.iso(0.4).polygons).is_empty? == true || raise("xor not empty")
b.isolated(0.4, euclidian).polygons.output(lb + 1, dm)
b.isolated(0.4, square).polygons.output(lb + 2, dm)
b.isolated(0.4, projection).polygons.output(lb + 3, dm)
b.isolated(0.4, euclidian, whole_edges).polygons.output(lb + 4, dm)
b.isolated(0.4, euclidian, projection_limits(0.4, nil)).polygons.output(lb + 5, dm)
b.isolated(0.4, euclidian, projection_limits(nil, 0.4)).polygons.output(lb + 6, dm)
if has_float_range
b.isolated(0.4, euclidian, projection_limits(0..0.4)).polygons.output(lb + 7, dm)
else
b.isolated(0.4, euclidian, projection_limits(0, 0.4)).polygons.output(lb + 7, dm)
end
b.isolated(0.4, shielded).polygons.output(lb, dm)
b.isolated(0.4, shielded).polygons.xor(b.iso(0.4, shielded).polygons).is_empty? == true || raise("xor not empty")
b.isolated(0.4, shielded, euclidian).polygons.output(lb + 1, dm)
b.isolated(0.4, shielded, square).polygons.output(lb + 2, dm)
b.isolated(0.4, shielded, projection).polygons.output(lb + 3, dm)
b.isolated(0.4, shielded, euclidian, whole_edges).polygons.output(lb + 4, dm)
b.isolated(0.4, shielded, euclidian, projection_limits(0.4, nil)).polygons.output(lb + 5, dm)
b.isolated(0.4, shielded, euclidian, projection_limits(nil, 0.4)).polygons.output(lb + 6, dm)
b.isolated(0.4, shielded, euclidian, projecting < 0.4).polygons.output(lb + 7, dm)
b.isolated(0.4, transparent).polygons.output(lb + 8, dm)
lb += 10 #240
message "--- notch #{lb}"
Binary file not shown.