mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-08-23 18:11:54 -06:00
Merge branch 'master' of https://github.com/prusa3d/Slic3r into svg_icons
This commit is contained in:
commit
fab87ff1d9
42 changed files with 314 additions and 203 deletions
|
@ -69,7 +69,9 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||
if (surface.is_solid() && (!surface.is_bridge() || layerm.layer()->id() == 0)) {
|
||||
group_attrib[i].is_solid = true;
|
||||
group_attrib[i].flow_width = (surface.surface_type == stTop) ? top_solid_infill_flow.width : solid_infill_flow.width;
|
||||
group_attrib[i].pattern = surface.is_external() ? layerm.region()->config().external_fill_pattern.value : ipRectilinear;
|
||||
group_attrib[i].pattern = surface.is_external() ?
|
||||
(surface.is_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().bottom_fill_pattern.value) :
|
||||
ipRectilinear;
|
||||
}
|
||||
}
|
||||
// Loop through solid groups, find compatible groups and append them to this one.
|
||||
|
@ -161,7 +163,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||
if (surface.is_solid()) {
|
||||
density = 100.;
|
||||
fill_pattern = (surface.is_external() && ! is_bridge) ?
|
||||
layerm.region()->config().external_fill_pattern.value :
|
||||
(surface.is_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().bottom_fill_pattern.value) :
|
||||
ipRectilinear;
|
||||
} else if (density <= 0)
|
||||
continue;
|
||||
|
|
|
@ -1506,7 +1506,7 @@ namespace Slic3r {
|
|||
if (metadata.key == NAME_KEY)
|
||||
volume->name = metadata.value;
|
||||
else if ((metadata.key == MODIFIER_KEY) && (metadata.value == "1"))
|
||||
volume->set_type(ModelVolume::PARAMETER_MODIFIER);
|
||||
volume->set_type(ModelVolumeType::PARAMETER_MODIFIER);
|
||||
else if (metadata.key == VOLUME_TYPE_KEY)
|
||||
volume->set_type(ModelVolume::type_from_string(metadata.value));
|
||||
else
|
||||
|
|
|
@ -604,7 +604,7 @@ void AMFParserContext::endElement(const char * /* name */)
|
|||
if (strcmp(opt_key, "modifier") == 0) {
|
||||
// Is this volume a modifier volume?
|
||||
// "modifier" flag comes first in the XML file, so it may be later overwritten by the "type" flag.
|
||||
m_volume->set_type((atoi(m_value[1].c_str()) == 1) ? ModelVolume::PARAMETER_MODIFIER : ModelVolume::MODEL_PART);
|
||||
m_volume->set_type((atoi(m_value[1].c_str()) == 1) ? ModelVolumeType::PARAMETER_MODIFIER : ModelVolumeType::MODEL_PART);
|
||||
} else if (strcmp(opt_key, "volume_type") == 0) {
|
||||
m_volume->set_type(ModelVolume::type_from_string(m_value[1]));
|
||||
}
|
||||
|
|
|
@ -1480,32 +1480,32 @@ const TriangleMesh& ModelVolume::get_convex_hull() const
|
|||
return m_convex_hull;
|
||||
}
|
||||
|
||||
ModelVolume::Type ModelVolume::type_from_string(const std::string &s)
|
||||
ModelVolumeType ModelVolume::type_from_string(const std::string &s)
|
||||
{
|
||||
// Legacy support
|
||||
if (s == "1")
|
||||
return PARAMETER_MODIFIER;
|
||||
return ModelVolumeType::PARAMETER_MODIFIER;
|
||||
// New type (supporting the support enforcers & blockers)
|
||||
if (s == "ModelPart")
|
||||
return MODEL_PART;
|
||||
return ModelVolumeType::MODEL_PART;
|
||||
if (s == "ParameterModifier")
|
||||
return PARAMETER_MODIFIER;
|
||||
return ModelVolumeType::PARAMETER_MODIFIER;
|
||||
if (s == "SupportEnforcer")
|
||||
return SUPPORT_ENFORCER;
|
||||
return ModelVolumeType::SUPPORT_ENFORCER;
|
||||
if (s == "SupportBlocker")
|
||||
return SUPPORT_BLOCKER;
|
||||
return ModelVolumeType::SUPPORT_BLOCKER;
|
||||
assert(s == "0");
|
||||
// Default value if invalud type string received.
|
||||
return MODEL_PART;
|
||||
return ModelVolumeType::MODEL_PART;
|
||||
}
|
||||
|
||||
std::string ModelVolume::type_to_string(const Type t)
|
||||
std::string ModelVolume::type_to_string(const ModelVolumeType t)
|
||||
{
|
||||
switch (t) {
|
||||
case MODEL_PART: return "ModelPart";
|
||||
case PARAMETER_MODIFIER: return "ParameterModifier";
|
||||
case SUPPORT_ENFORCER: return "SupportEnforcer";
|
||||
case SUPPORT_BLOCKER: return "SupportBlocker";
|
||||
case ModelVolumeType::MODEL_PART: return "ModelPart";
|
||||
case ModelVolumeType::PARAMETER_MODIFIER: return "ParameterModifier";
|
||||
case ModelVolumeType::SUPPORT_ENFORCER: return "SupportEnforcer";
|
||||
case ModelVolumeType::SUPPORT_BLOCKER: return "SupportBlocker";
|
||||
default:
|
||||
assert(false);
|
||||
return "ModelPart";
|
||||
|
@ -1671,7 +1671,7 @@ bool model_object_list_extended(const Model &model_old, const Model &model_new)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolume::Type type)
|
||||
bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolumeType type)
|
||||
{
|
||||
bool modifiers_differ = false;
|
||||
size_t i_old, i_new;
|
||||
|
|
|
@ -295,6 +295,15 @@ private:
|
|||
mutable bool m_raw_mesh_bounding_box_valid;
|
||||
};
|
||||
|
||||
// Declared outside of ModelVolume, so it could be forward declared.
|
||||
enum class ModelVolumeType : int {
|
||||
INVALID = -1,
|
||||
MODEL_PART = 0,
|
||||
PARAMETER_MODIFIER,
|
||||
SUPPORT_ENFORCER,
|
||||
SUPPORT_BLOCKER,
|
||||
};
|
||||
|
||||
// An object STL, or a modifier volume, over which a different set of parameters shall be applied.
|
||||
// ModelVolume instances are owned by a ModelObject.
|
||||
class ModelVolume : public ModelBase
|
||||
|
@ -307,23 +316,15 @@ public:
|
|||
// overriding the global Slic3r settings and the ModelObject settings.
|
||||
DynamicPrintConfig config;
|
||||
|
||||
enum Type {
|
||||
MODEL_TYPE_INVALID = -1,
|
||||
MODEL_PART = 0,
|
||||
PARAMETER_MODIFIER,
|
||||
SUPPORT_ENFORCER,
|
||||
SUPPORT_BLOCKER,
|
||||
};
|
||||
|
||||
// A parent object owning this modifier volume.
|
||||
ModelObject* get_object() const { return this->object; };
|
||||
Type type() const { return m_type; }
|
||||
void set_type(const Type t) { m_type = t; }
|
||||
bool is_model_part() const { return m_type == MODEL_PART; }
|
||||
bool is_modifier() const { return m_type == PARAMETER_MODIFIER; }
|
||||
bool is_support_enforcer() const { return m_type == SUPPORT_ENFORCER; }
|
||||
bool is_support_blocker() const { return m_type == SUPPORT_BLOCKER; }
|
||||
bool is_support_modifier() const { return m_type == SUPPORT_BLOCKER || m_type == SUPPORT_ENFORCER; }
|
||||
ModelVolumeType type() const { return m_type; }
|
||||
void set_type(const ModelVolumeType t) { m_type = t; }
|
||||
bool is_model_part() const { return m_type == ModelVolumeType::MODEL_PART; }
|
||||
bool is_modifier() const { return m_type == ModelVolumeType::PARAMETER_MODIFIER; }
|
||||
bool is_support_enforcer() const { return m_type == ModelVolumeType::SUPPORT_ENFORCER; }
|
||||
bool is_support_blocker() const { return m_type == ModelVolumeType::SUPPORT_BLOCKER; }
|
||||
bool is_support_modifier() const { return m_type == ModelVolumeType::SUPPORT_BLOCKER || m_type == ModelVolumeType::SUPPORT_ENFORCER; }
|
||||
t_model_material_id material_id() const { return m_material_id; }
|
||||
void set_material_id(t_model_material_id material_id);
|
||||
ModelMaterial* material() const;
|
||||
|
@ -357,8 +358,8 @@ public:
|
|||
const TriangleMesh& get_convex_hull() const;
|
||||
|
||||
// Helpers for loading / storing into AMF / 3MF files.
|
||||
static Type type_from_string(const std::string &s);
|
||||
static std::string type_to_string(const Type t);
|
||||
static ModelVolumeType type_from_string(const std::string &s);
|
||||
static std::string type_to_string(const ModelVolumeType t);
|
||||
|
||||
const Geometry::Transformation& get_transformation() const { return m_transformation; }
|
||||
void set_transformation(const Geometry::Transformation& transformation) { m_transformation = transformation; }
|
||||
|
@ -403,7 +404,7 @@ private:
|
|||
// Parent object owning this ModelVolume.
|
||||
ModelObject* object;
|
||||
// Is it an object to be printed, or a modifier volume?
|
||||
Type m_type;
|
||||
ModelVolumeType m_type;
|
||||
t_model_material_id m_material_id;
|
||||
// The convex hull of this model's mesh.
|
||||
TriangleMesh m_convex_hull;
|
||||
|
@ -415,13 +416,13 @@ private:
|
|||
// 1 -> is splittable
|
||||
int m_is_splittable {-1};
|
||||
|
||||
ModelVolume(ModelObject *object, const TriangleMesh &mesh) : mesh(mesh), m_type(MODEL_PART), object(object)
|
||||
ModelVolume(ModelObject *object, const TriangleMesh &mesh) : mesh(mesh), m_type(ModelVolumeType::MODEL_PART), object(object)
|
||||
{
|
||||
if (mesh.stl.stats.number_of_facets > 1)
|
||||
calculate_convex_hull();
|
||||
}
|
||||
ModelVolume(ModelObject *object, TriangleMesh &&mesh, TriangleMesh &&convex_hull) :
|
||||
mesh(std::move(mesh)), m_convex_hull(std::move(convex_hull)), m_type(MODEL_PART), object(object) {}
|
||||
mesh(std::move(mesh)), m_convex_hull(std::move(convex_hull)), m_type(ModelVolumeType::MODEL_PART), object(object) {}
|
||||
|
||||
// Copying an existing volume, therefore this volume will get a copy of the ID assigned.
|
||||
ModelVolume(ModelObject *object, const ModelVolume &other) :
|
||||
|
@ -633,7 +634,7 @@ extern bool model_object_list_extended(const Model &model_old, const Model &mode
|
|||
|
||||
// Test whether the new ModelObject contains a different set of volumes (or sorted in a different order)
|
||||
// than the old ModelObject.
|
||||
extern bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolume::Type type);
|
||||
extern bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolumeType type);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique.
|
||||
|
|
|
@ -571,7 +571,7 @@ void Print::model_volume_list_update_supports(ModelObject &model_object_dst, con
|
|||
delete mv_with_status.first;
|
||||
}
|
||||
|
||||
static inline void model_volume_list_copy_configs(ModelObject &model_object_dst, const ModelObject &model_object_src, const ModelVolume::Type type)
|
||||
static inline void model_volume_list_copy_configs(ModelObject &model_object_dst, const ModelObject &model_object_src, const ModelVolumeType type)
|
||||
{
|
||||
size_t i_src, i_dst;
|
||||
for (i_src = 0, i_dst = 0; i_src < model_object_src.volumes.size() && i_dst < model_object_dst.volumes.size();) {
|
||||
|
@ -841,10 +841,10 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
|||
assert(it_status->status == ModelObjectStatus::Old || it_status->status == ModelObjectStatus::Moved);
|
||||
const ModelObject &model_object_new = *model.objects[idx_model_object];
|
||||
// Check whether a model part volume was added or removed, their transformations or order changed.
|
||||
bool model_parts_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::MODEL_PART);
|
||||
bool modifiers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::PARAMETER_MODIFIER);
|
||||
bool support_blockers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::SUPPORT_BLOCKER);
|
||||
bool support_enforcers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::SUPPORT_ENFORCER);
|
||||
bool model_parts_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::MODEL_PART);
|
||||
bool modifiers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::PARAMETER_MODIFIER);
|
||||
bool support_blockers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_BLOCKER);
|
||||
bool support_enforcers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_ENFORCER);
|
||||
if (model_parts_differ || modifiers_differ ||
|
||||
model_object.origin_translation != model_object_new.origin_translation ||
|
||||
model_object.layer_height_ranges != model_object_new.layer_height_ranges ||
|
||||
|
@ -886,8 +886,8 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
|||
}
|
||||
// Synchronize (just copy) the remaining data of ModelVolumes (name, config).
|
||||
//FIXME What to do with m_material_id?
|
||||
model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolume::MODEL_PART);
|
||||
model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolume::PARAMETER_MODIFIER);
|
||||
model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::MODEL_PART);
|
||||
model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::PARAMETER_MODIFIER);
|
||||
// Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step.
|
||||
model_object.name = model_object_new.name;
|
||||
model_object.input_file = model_object_new.input_file;
|
||||
|
|
|
@ -362,12 +362,11 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->default_value = new ConfigOptionBool(false);
|
||||
|
||||
def = this->add("external_fill_pattern", coEnum);
|
||||
def->label = L("Top/bottom fill pattern");
|
||||
auto def_top_fill_pattern = def = this->add("top_fill_pattern", coEnum);
|
||||
def->label = L("Top fill pattern");
|
||||
def->category = L("Infill");
|
||||
def->tooltip = L("Fill pattern for top/bottom infill. This only affects the external visible layer, "
|
||||
"and not its adjacent solid shells.");
|
||||
def->cli = "external-fill-pattern|solid-fill-pattern=s";
|
||||
def->tooltip = L("Fill pattern for top infill. This only affects the top visible layer, and not its adjacent solid shells.");
|
||||
def->cli = "top-fill-pattern|external-fill-pattern|solid-fill-pattern=s";
|
||||
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values();
|
||||
def->enum_values.push_back("rectilinear");
|
||||
def->enum_values.push_back("concentric");
|
||||
|
@ -379,8 +378,15 @@ void PrintConfigDef::init_fff_params()
|
|||
def->enum_labels.push_back(L("Hilbert Curve"));
|
||||
def->enum_labels.push_back(L("Archimedean Chords"));
|
||||
def->enum_labels.push_back(L("Octagram Spiral"));
|
||||
// solid_fill_pattern is an obsolete equivalent to external_fill_pattern.
|
||||
def->aliases = { "solid_fill_pattern" };
|
||||
// solid_fill_pattern is an obsolete equivalent to top_fill_pattern/bottom_fill_pattern.
|
||||
def->aliases = { "solid_fill_pattern", "external_fill_pattern" };
|
||||
def->default_value = new ConfigOptionEnum<InfillPattern>(ipRectilinear);
|
||||
|
||||
def = this->add("bottom_fill_pattern", coEnum);
|
||||
*def = *def_top_fill_pattern;
|
||||
def->label = L("Bottom Pattern");
|
||||
def->tooltip = L("Fill pattern for bottom infill. This only affects the bottom external visible layer, and not its adjacent solid shells.");
|
||||
def->cli = "bottom-fill-pattern|external-fill-pattern|solid-fill-pattern=s";
|
||||
def->default_value = new ConfigOptionEnum<InfillPattern>(ipRectilinear);
|
||||
|
||||
def = this->add("external_perimeter_extrusion_width", coFloatOrPercent);
|
||||
|
@ -2939,13 +2945,17 @@ std::string FullPrintConfig::validate()
|
|||
if (! print_config_def.get("fill_pattern")->has_enum_value(this->fill_pattern.serialize()))
|
||||
return "Invalid value for --fill-pattern";
|
||||
|
||||
// --external-fill-pattern
|
||||
if (! print_config_def.get("external_fill_pattern")->has_enum_value(this->external_fill_pattern.serialize()))
|
||||
return "Invalid value for --external-fill-pattern";
|
||||
// --top-fill-pattern
|
||||
if (! print_config_def.get("top_fill_pattern")->has_enum_value(this->top_fill_pattern.serialize()))
|
||||
return "Invalid value for --top-fill-pattern";
|
||||
|
||||
// --bottom-fill-pattern
|
||||
if (! print_config_def.get("bottom_fill_pattern")->has_enum_value(this->bottom_fill_pattern.serialize()))
|
||||
return "Invalid value for --bottom-fill-pattern";
|
||||
|
||||
// --fill-density
|
||||
if (fabs(this->fill_density.value - 100.) < EPSILON &&
|
||||
! print_config_def.get("external_fill_pattern")->has_enum_value(this->fill_pattern.serialize()))
|
||||
! print_config_def.get("top_fill_pattern")->has_enum_value(this->fill_pattern.serialize()))
|
||||
return "The selected fill pattern is not supposed to work at 100% density";
|
||||
|
||||
// --infill-every-layers
|
||||
|
|
|
@ -462,7 +462,8 @@ public:
|
|||
ConfigOptionFloat bridge_flow_ratio;
|
||||
ConfigOptionFloat bridge_speed;
|
||||
ConfigOptionBool ensure_vertical_shell_thickness;
|
||||
ConfigOptionEnum<InfillPattern> external_fill_pattern;
|
||||
ConfigOptionEnum<InfillPattern> top_fill_pattern;
|
||||
ConfigOptionEnum<InfillPattern> bottom_fill_pattern;
|
||||
ConfigOptionFloatOrPercent external_perimeter_extrusion_width;
|
||||
ConfigOptionFloatOrPercent external_perimeter_speed;
|
||||
ConfigOptionBool external_perimeters_first;
|
||||
|
@ -504,7 +505,8 @@ protected:
|
|||
OPT_PTR(bridge_flow_ratio);
|
||||
OPT_PTR(bridge_speed);
|
||||
OPT_PTR(ensure_vertical_shell_thickness);
|
||||
OPT_PTR(external_fill_pattern);
|
||||
OPT_PTR(top_fill_pattern);
|
||||
OPT_PTR(bottom_fill_pattern);
|
||||
OPT_PTR(external_perimeter_extrusion_width);
|
||||
OPT_PTR(external_perimeter_speed);
|
||||
OPT_PTR(external_perimeters_first);
|
||||
|
|
|
@ -155,14 +155,8 @@ template<> class FilePrinter<FilePrinterFormat::SLA_PNGZIP>
|
|||
"jobDir = ") + projectname + "\n" +
|
||||
"expTime = " + expt_str + "\n"
|
||||
"expTimeFirst = " + expt_first_str + "\n"
|
||||
// "stepNum = " + stepnum_str + "\n"
|
||||
// "wifiOn = 1\n"
|
||||
// "tiltSlow = 60\n"
|
||||
// "tiltFast = 15\n"
|
||||
"numFade = " + cnt_fade_layers + "\n"
|
||||
// "startdelay = 0\n"
|
||||
"layerHeight = " + layerh_str + "\n"
|
||||
"noteInfo = "
|
||||
"expTime = "+expt_str+" + resinType = generic+layerHeight = "
|
||||
+layerh_str+" + printer = DWARF3\n"
|
||||
"usedMaterial = " + used_material + "\n"
|
||||
|
|
|
@ -498,7 +498,8 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
|||
|| opt_key == "bridge_angle") {
|
||||
steps.emplace_back(posPrepareInfill);
|
||||
} else if (
|
||||
opt_key == "external_fill_pattern"
|
||||
opt_key == "top_fill_pattern"
|
||||
|| opt_key == "bottom_fill_pattern"
|
||||
|| opt_key == "external_fill_link_max_length"
|
||||
|| opt_key == "fill_angle"
|
||||
|| opt_key == "fill_pattern"
|
||||
|
|
|
@ -310,7 +310,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
|||
if (it_print_object_status != print_object_status.end() && it_print_object_status->id != model_object.id())
|
||||
it_print_object_status = print_object_status.end();
|
||||
// Check whether a model part volume was added or removed, their transformations or order changed.
|
||||
bool model_parts_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::MODEL_PART);
|
||||
bool model_parts_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::MODEL_PART);
|
||||
bool sla_trafo_differs = model_object.instances.empty() != model_object_new.instances.empty() ||
|
||||
(! model_object.instances.empty() && ! sla_trafo(model_object).isApprox(sla_trafo(model_object_new)));
|
||||
if (model_parts_differ || sla_trafo_differs) {
|
||||
|
@ -975,7 +975,7 @@ void SLAPrint::process()
|
|||
this->fill_statistics();
|
||||
// Set statistics values to the printer
|
||||
m_printer->set_statistics({(m_print_statistics.objects_used_material + m_print_statistics.support_used_material)/1000,
|
||||
10.0,
|
||||
double(m_default_object_config.faded_layers.getInt()),
|
||||
double(m_print_statistics.slow_layers_count),
|
||||
double(m_print_statistics.fast_layers_count)
|
||||
});
|
||||
|
@ -1318,7 +1318,8 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
|||
std::vector<SLAPrintObjectStep> steps;
|
||||
bool invalidated = false;
|
||||
for (const t_config_option_key &opt_key : opt_keys) {
|
||||
if (opt_key == "layer_height") {
|
||||
if ( opt_key == "layer_height"
|
||||
|| opt_key == "faded_layers") {
|
||||
steps.emplace_back(slaposObjectSlice);
|
||||
} else if (
|
||||
opt_key == "supports_enable"
|
||||
|
|
|
@ -42,6 +42,12 @@ Surface::is_internal() const
|
|||
|| this->surface_type == stInternalVoid;
|
||||
}
|
||||
|
||||
bool
|
||||
Surface::is_top() const
|
||||
{
|
||||
return this->surface_type == stTop;
|
||||
}
|
||||
|
||||
bool
|
||||
Surface::is_bottom() const
|
||||
{
|
||||
|
|
|
@ -98,6 +98,7 @@ public:
|
|||
bool is_solid() const;
|
||||
bool is_external() const;
|
||||
bool is_internal() const;
|
||||
bool is_top() const;
|
||||
bool is_bottom() const;
|
||||
bool is_bridge() const;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue