Skip to content

Commit

Permalink
rework feature and tolerance storage
Browse files Browse the repository at this point in the history
  • Loading branch information
cserteGT3 committed Jan 24, 2024
1 parent 54fe9a6 commit b1ee3db
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 115 deletions.
29 changes: 14 additions & 15 deletions src/BlankLocalizationCore.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,25 @@ using Printf: @sprintf
export PartZero,
printpartzeropositions

export GeometryStyle,
PLANELIKE,
HOLELIKE,
isplanelike,
isholelike,
IsPrimitive,
IsFreeForm,
export RepresentationStyle,
FeatureStyle,
AbstractLocalizationGeometry,
SimpleHole,
MeshHole,
SimplePlane,
MeshPlane,
featurepoint,
surfacepoints,
filteredsurfacepoints,
featureradius,
RoughFeature,
MachinedFeature,
LocalizationFeature

export PlanePlaneDistance,
PlaneAxisDistance,
AxisAxisDistance,
AxisAxisConcentric,
LocalizationTolerance,
toleranceddistance
export PositionTolerance,
ConcentrictyTolerance,
ProjectedDimensionTolerance,
addtolerance2model!

export OptimizationResult,
MultiOperationProblem,
Expand Down Expand Up @@ -67,8 +66,8 @@ HV(v) = vcat(v, 1)

include("partzeros.jl")
include("geometries.jl")
#include("tolerances.jl")
#include("optimizationproblem.jl")
include("tolerances.jl")
include("optimizationproblem.jl")
#include("optimization.jl")
#include("resultevaluation.jl")
#include("visualization.jl")
Expand Down
171 changes: 99 additions & 72 deletions src/geometries.jl
Original file line number Diff line number Diff line change
@@ -1,107 +1,129 @@
"""
GeometryStyle
RepresentationStyle
Trait that describes the "style" of an [`AbstractLocalizationGeometry`](@ref).
If it can be described by a primitive, then it is [`IsPrimitive`](@ref) and
[`IsFreeForm`](@ref) otherwise.
If it can be described by a primitive, then it is [`Primitive`](@ref) and
[`FreeForm`](@ref) otherwise.
"""
abstract type GeometryStyle end
abstract type RepresentationStyle end

"""Primitive geometries can be explicitly described, e.g. a box or sphere."""
struct IsPrimitive <: GeometryStyle end
struct Primitive <: RepresentationStyle end

"""Free form geometries are discrete representations, e.g. a mesh or a point cloud."""
struct IsFreeForm <: GeometryStyle end
struct FreeForm <: RepresentationStyle end

nicestr(x::Primitive) = "primitive"
nicestr(x::FreeForm) = "free form"

abstract type FeatureStyle end
struct Planar <: FeatureStyle end
struct Cylindrical <: FeatureStyle end

nicestr(x::Planar) = "planar"
nicestr(x::Cylindrical) = "cylindrical"

abstract type AbstractLocalizationGeometry end

struct SimpleHole <: AbstractLocalizationGeometry
geom::Meshes.Disk
end

RepresentationStyle(g::SimpleHole) = Primitive()
FeatureStyle(g::SimpleHole) = Cylindrical()

featurepoint(g::SimpleHole) = plane(g.geom)(0,0)
featureradius(g::SimpleHole) = radius(g.geom)

struct MeshHole <: AbstractLocalizationGeometry
geom #::Meshes.Mesh, but that is abstract
chull # vector of points / vector of vectors - TBD
end

RepresentationStyle(g::MeshHole) = FreeForm()
FeatureStyle(g::MeshHole) = Cylindrical()

surfacepoints(g::MeshHole) = vertices(g.geom)
filteredsurfacepoints(g::MeshHole) = g.chull

struct SimplePlane <: AbstractLocalizationGeometry
geom::Meshes.Plane
end

RepresentationStyle(g::SimplePlane) = Primitive()
FeatureStyle(g::SimplePlane) = Planar()

featurepoint(g::SimplePlane) = g.geom(0,0)

struct MeshPlane <: AbstractLocalizationGeometry
geom #::Meshes.Mesh, but that is abstract
end

RepresentationStyle(g::MeshPlane) = FreeForm()
FeatureStyle(g::MeshPlane) = Planar()

surfacepoints(g::MeshPlane) = vertices(g.geom)
filteredsurfacepoints(g::MeshPlane) = vertices(g.geom)



"""Enum to store if a feature is hole or plane like."""
@enum GeometryType PLANELIKE HOLELIKE

"""Supertype for feature types."""
abstract type AbstractFeature{G} end
abstract type AbstractFeature end

GeometryStyle(f::AbstractFeature) = GeometryStyle(f.geometry)
RepresentationStyle(f::AbstractFeature) = RepresentationStyle(f.geometry)
FeatureStyle(f::AbstractFeature) = FeatureStyle(f.geometry)
featurename(f::AbstractFeature) = f.name
geometrytype(f::AbstractFeature) = f.gtype
geometry(f::AbstractFeature) = f.geometry

isplanelike(st::AbstractFeature) = geometrytype(st) == PLANELIKE
isholelike(st::AbstractFeature) = geometrytype(st) == HOLELIKE
isplanar(st::AbstractFeature) = FeatureStyle(st) === Planar()
iscylindrical(st::AbstractFeature) = FeatureStyle(st) === Cylindrical()

"""
featurepoint(f::AbstractFeature)
Return the feature point of an [`IsPrimitive`](@ref) geometry.
Return the feature point of an [`Primitive`](@ref) geometry.
"""
featurepoint(f::AbstractFeature) = featurepoint(GeometryStyle(f), f)
featurepoint(::IsPrimitive, f) = featurepoint(geometry(f))
function featurepoint(::IsFreeForm, f)
error("Function `featurepoint` is not defined for `IsFreeForm` features.")
featurepoint(f::AbstractFeature) = featurepoint(RepresentationStyle(f), f)
featurepoint(::Primitive, f) = featurepoint(geometry(f))
function featurepoint(::FreeForm, f)
error("Function `featurepoint` is not defined for `FreeForm` features.")
end

"""
surfacepoints(f::AbstractFeature)
Return the points of the surface of an [`IsFreeForm`](@ref) geometry.
Return the points of the surface of an [`FreeForm`](@ref) geometry.
"""
surfacepoints(f::AbstractFeature) = surfacepoints(GeometryStyle(f), f)
surfacepoints(f::AbstractFeature) = surfacepoints(RepresentationStyle(f), f)

surfacepoints(::IsFreeForm, f) = surfacepoints(geometry(f))
surfacepoints(::FreeForm, f) = surfacepoints(geometry(f))

function surfacepoints(::IsPrimitive, f)
error("Function `surfacepoints` is not defined for `IsPrimitive` features.")
function surfacepoints(::Primitive, f)
error("Function `surfacepoints` is not defined for `Primitive` features.")
end

"""
featureradius(f::AbstractFeature)
Return the radius of a [`IsPrimitive`](@ref) geometry, that is `HOLELIKE`.
Return the radius of a [`Primitive`](@ref) geometry, that is `HOLELIKE`.
"""
featureradius(f::AbstractFeature) = featureradius(GeometryStyle(f), f)
featureradius(f::AbstractFeature) = featureradius(RepresentationStyle(f), FeatureStyle(f), f)

function featureradius(::IsPrimitive, f)
if isholelike(f)
return featureradius(geometry(f))
else
error("Function `featureradius` is only defined for `HOLELIKE` features.")
end
end
featureradius(::Primitive, ::Cylindrical, f) = featureradius(geometry(f))

function featureradius(::IsFreeForm, f)
error("Function `featureradius` is not defined for `IsFreeForm` features.")
function featureradius(t1, t2, f)
error("Function `featureradius` is only defined for ::Primitive and ::Cylindrical features. Got $t1 and $t2")
end

## default functions for Cylinders, Planes and Meshes
featurepoint(g::Meshes.Plane) = g(0,0)

featurepoint(g::Meshes.Cylinder) = featurepoint(top(g))

surfacepoints(g::Meshes.Mesh) = vertices(g)

featureradius(g::Meshes.Cylinder) = radius(g)

struct RoughFeature{G} <: AbstractFeature{G}
struct RoughFeature <: AbstractFeature
name::String
gtype::GeometryType
geometry::G
geometry # <: AbstractLocalizationGeometry
end

GeometryStyle(f::Meshes.Primitive) = IsPrimitive()
GeometryStyle(f::Meshes.Domain) = IsFreeForm()
#GeometryStyle(f) = IsFreeForm()

#=
for ST = subtypes(Meshes.Primitive)
eval(quote
GeometryStyle(::Type{$ST}) = IsPrimitive()
end)
end
GeometryStyle(::Type) = IsFreeForm()
=#

struct MachinedFeature{G<:Meshes.Primitive} <: AbstractFeature{G}
struct MachinedFeature <: AbstractFeature
name::String
gtype::GeometryType
geometry::G
geometry # <: AbstractLocalizationGeometry
partzero::PartZero
end

Expand All @@ -117,35 +139,38 @@ It has a name, a [`RoughFeature`](@ref) and a [`MachinedFeature`](@ref).
The two geometries should be of same [`GeometryType`](@ref) (holelike or planelike),
the constructor enforces this property.
"""
struct LocalizationFeature{G}
struct LocalizationFeature
name::String
roughfeature::RoughFeature{G}
roughfeature::RoughFeature
machinedfeature::MachinedFeature
function LocalizationFeature(n, r::RoughFeature{T}, m) where {T}
if isplanelike(r) == isplanelike(m)
new{T}(n, r, m)
function LocalizationFeature(n, r, m)
if FeatureStyle(r) === FeatureStyle(m)
new(n, r, m)
else
error("GeometryType of rough and machined does not match!")
error("FeatureStyle of rough and machined features does not match!")
end
end
end

featurename(lf::LocalizationFeature) = lf.name
partzero(lf::LocalizationFeature) = partzero(lf.machinedfeature)
partzeroname(lf::LocalizationFeature) = partzeroname(lf.partzero)
isplanelike(lf::LocalizationFeature) = isplanelike(lf.roughfeature)
isholelike(lf::LocalizationFeature) = isholelike(lf.roughfeature)
GeometryStyle(lf::LocalizationFeature) = GeometryStyle(lf.roughfeature)
isplanar(lf::LocalizationFeature) = isplanar(lf.roughfeature)
iscylindrical(lf::LocalizationFeature) = iscylindrical(lf.roughfeature)
RepresentationStyle(lf::LocalizationFeature) = RepresentationStyle(lf.roughfeature)
FeatureStyle(lf::LocalizationFeature) = FeatureStyle(lf.roughfeature)

function Base.show(io::IO, lf::LocalizationFeature)
print(io, typeof(lf), ": ", featurename(lf))
print(io, "LocalizationFeature: ", featurename(lf),
" ", nicestr(RepresentationStyle(lf)), ", ", nicestr(FeatureStyle(lf)))
end

roughfeaturepoint(lf::LocalizationFeature) = featurepoint(lf.rough)
machinedfeaturepoint(lf::LocalizationFeature) = featurepoint(lf.machined)
roughradius(lf::LocalizationFeature) = featureradius(lf.rough)
machinedradius(lf::LocalizationFeature) = featureradius(lf.machined)

#=
function machinedfeaturepointindatum(f::LocalizationFeature)
v = machinedfeaturepoint(f)
pz = partzero(f)
Expand All @@ -166,3 +191,5 @@ function transformmachined2datum(feature, points)
resultpoints = [p[1:3] for p in newpoints]
return resultpoints
end
=#

44 changes: 28 additions & 16 deletions src/optimizationproblem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ The features in tolerances ([`LocalizationTolerance`](@ref)) can be `nothing`, i
mutable struct MultiOperationProblem
partzeros::Vector{PartZero}
features::Vector{LocalizationFeature} # features that have rough and machined -> allowanced
tolerances::Vector{LocalizationTolerance}
tolerances # Vector{AbstractTolerance}
parameters::Dict{String,Real}
opresult::OptimizationResult
end
Expand All @@ -46,26 +46,26 @@ function MultiOperationProblem(partzeros, features, tolerances, parameters)
end

function problemtype(mop::MultiOperationProblem)
# problem type is depending on the rough geometries: IsPrimitive or IsFreeForm
# if there is at least one IsFreeForm rough geometry -> hybrid problem
featuretypes = GeometryStyle.(typeof.(x.rough for x in mop.features))
# problem type is depending on the rough geometries: Primitive or FreeForm
# if there is at least one FreeForm rough geometry -> hybrid problem
featuretypes = RepresentationStyle.(mop.features)
for ft in featuretypes
ft === IsFreeForm() && return :HybridProblem
ft === FreeForm() && return :HybridProblem
end
return :PrimitiveProblem
end

function collectholefeatures(mop::MultiOperationProblem)
filter(x->x isa HoleLocalizationFeature, mop.features)
function cylindricalfeatures(mop::MultiOperationProblem)
filter(x->FeatureStyle(x) === Cylindrical(), mop.features)
end

function collectplanefeatures(mop::MultiOperationProblem)
filter(x->x isa PlaneLocalizationFeature, mop.features)
function planarfeatures(mop::MultiOperationProblem)
filter(x->FeatureStyle(x) === Planar(), mop.features)
end

function Base.show(io::IO, mop::MultiOperationProblem)
nh = size(collectholefeatures(mop), 1)
np = size(collectplanefeatures(mop), 1)
nh = size(cylindricalfeatures(mop), 1)
np = size(planarfeatures(mop), 1)
npz = size(mop.partzeros, 1)
nts = size(mop.tolerances, 1)
sn = string(problemtype(mop))
Expand Down Expand Up @@ -101,22 +101,34 @@ Tell if `mop`'s solution is in an optimal state, either: `OPTIMAL` or `LOCALLY_S
"""
isoptimum(mop::MultiOperationProblem) = isoptimum(mop.opresult)


"""
getfeaturebyname(mop::MultiOperationProblem, featurename)
getfeaturebyname(features, featuresname)
Get a hole or plane feature by its name.
It is assumed that all features have distinct names.
Return `nothing`, if no feature is found with `featurename`.
Return `nothing`, if no feature is found with `featuresname`.
"""
function getfeaturebyname(mop::MultiOperationProblem, featurename)
for f in mop.features
if getfeaturename(f) == featurename
function getfeaturebyname(features, featuresname)
for f in features
if featurename(f) == featuresname
return f
end
end
return nothing
end

"""
getfeaturebyname(mop::MultiOperationProblem, featurename)
Get a hole or plane feature by its name from a vector of features.
It is assumed that all features have distinct names.
Return `nothing`, if no feature is found with `featurename`.
"""
function getfeaturebyname(mop::MultiOperationProblem, featurename)
getfeaturebyname(mop.features, featurename)
end

"""
collectfeaturesbypartzero(mop::MultiOperationProblem, partzeroname)
Expand Down
Loading

0 comments on commit b1ee3db

Please sign in to comment.