From a0ad212a43c647f681ace945d14021d5880e1bd0 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 10:48:30 +0200 Subject: [PATCH 001/241] Disable tutorial --- docs/make.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 2042645c8..c4aa99058 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -16,12 +16,12 @@ function fix_literate_output(content) return content end -gen_content_dir = joinpath(@__DIR__, "src") -tutorial_src = joinpath(@__DIR__, "src", "tutorial_lit.jl") -Literate.markdown(tutorial_src, gen_content_dir, name = "tutorial", documenter = true, credit = true, postprocess = fix_literate_output) -#Literate.markdown(tutorial_src, gen_content_dir, name = "tutorial", codefence = "```@repl tutorial" => "```", documenter = true, credit = true) -Literate.notebook(tutorial_src, gen_content_dir, execute = false, name = "ssd_tutorial", documenter = true, credit = true) -Literate.script(tutorial_src, gen_content_dir, keep_comments = false, name = "ssd_tutorial", documenter = true, credit = false) +# gen_content_dir = joinpath(@__DIR__, "src") +# tutorial_src = joinpath(@__DIR__, "src", "tutorial_lit.jl") +# Literate.markdown(tutorial_src, gen_content_dir, name = "tutorial", documenter = true, credit = true, postprocess = fix_literate_output) +# #Literate.markdown(tutorial_src, gen_content_dir, name = "tutorial", codefence = "```@repl tutorial" => "```", documenter = true, credit = true) +# Literate.notebook(tutorial_src, gen_content_dir, execute = false, name = "ssd_tutorial", documenter = true, credit = true) +# Literate.script(tutorial_src, gen_content_dir, keep_comments = false, name = "ssd_tutorial", documenter = true, credit = false) makedocs( @@ -44,7 +44,7 @@ makedocs( "Drift Fields" => "man/drift_fields.md", "IO" => "man/IO.md", ], - "Tutorial" => "tutorial.md", + # "Tutorial" => "tutorial.md", "API" => "api.md", "LICENSE" => "LICENSE.md", ], From e2bab45baf66fd0ca21fbd2676bd0b44f6aa2ea3 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 10:49:08 +0200 Subject: [PATCH 002/241] Disable all tests --- test/runtests.jl | 230 +++++++++++++++++++++++------------------------ 1 file changed, 115 insertions(+), 115 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index e6b4f8091..965b37f9e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,121 +8,121 @@ using Unitful T = Float32 -@testset "Comparison to analytic solutions" begin - include("comparison_to_analytic_solutions.jl") -end +# @testset "Comparison to analytic solutions" begin +# include("comparison_to_analytic_solutions.jl") +# end -@testset "Test real detectors" begin - @testset "Simulate example detector: Inverted Coax" begin - sim = Simulation{T}(SSD_examples[:InvertedCoax]) - simulate!(sim, max_refinements = 1, verbose = true) - evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 40e-3 )])) - simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) - signalsum = T(0) - for i in 1:length(evt.waveforms) - signalsum += abs(evt.waveforms[i].value[end]) - end - @test isapprox( signalsum, T(2), atol = 5e-4 ) - end - @testset "Simulate example detector: Inverted Coax (in cryostat)" begin - sim = Simulation{T}(SSD_examples[:InvertedCoaxInCryostat]) - simulate!(sim, max_refinements = 1, verbose = true) - evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 10e-3 )])) - simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) - signalsum = T(0) - for i in 1:length(evt.waveforms) - signalsum += abs(evt.waveforms[i].value[end]) - end - @test isapprox( signalsum, T(2), atol = 5e-4 ) - end - @testset "Simulate example detector: Coax" begin - sim = Simulation{T}(SSD_examples[:Coax]) - simulate!(sim, max_refinements = 0, verbose = true) - evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(30), 12e-3 )])) - simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) - signalsum = T(0) - for i in 1:length(evt.waveforms) - signalsum += abs(evt.waveforms[i].value[end]) - end - @test isapprox( signalsum, T(2), atol = 4e-3 ) - end - @testset "Simulate example detector: BEGe" begin - sim = Simulation{T}(SSD_examples[:BEGe]) - simulate!(sim, max_refinements = 0, verbose = true) - evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 20e-3 )])) - simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) - signalsum = T(0) - for i in 1:length(evt.waveforms) - signalsum += abs(evt.waveforms[i].value[end]) - end - @test isapprox( signalsum, T(2), atol = 3e-3 ) - end - @testset "Simulate example detector: HexagonalPrism" begin - sim = Simulation{T}(SSD_examples[:Hexagon]) - simulate!(sim, max_refinements = 0, verbose = true) - evt = Event([CartesianPoint{T}(0, 5e-4, 1e-3)]) - simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) - signalsum = T(0) - for i in 1:length(evt.waveforms) - signalsum += abs(evt.waveforms[i].value[end]) - end - @test isapprox( signalsum, T(2), atol = 5e-4 ) - end - @testset "Simulate example detector: CGD" begin - sim = Simulation{T}(SSD_examples[:CGD]) - SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) - simulate!(sim, max_refinements = 0, verbose = true) - evt = Event([CartesianPoint{T}(5e-3, 5e-3, 5e-3)]) - simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) - signalsum = T(0) - for i in 1:length(evt.waveforms) - signalsum += abs(evt.waveforms[i].value[end]) - end - @test isapprox( signalsum, T(2), atol = 5e-4 ) - end - #= - @testset "Simulate example detector: Spherical" begin - sim = Simulation{T}(SSD_examples[:Spherical]) - SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) - # simulate!(sim, max_refinements = 1, verbose = true) - # evt = Event([CartesianPoint{T}(0,0,0)]) - # simulate!(evt, sim) - # signalsum = T(0) - # for i in 1:length(evt.waveforms) - # signalsum += abs(evt.waveforms[i].value[end]) - # end - # @test isapprox( signalsum, T(2), atol = 5e-4 ) - end - @testset "Simulate example detector: Toroidal" begin - sim = Simulation{T}(SSD_examples[:CoaxialTorus]) - SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) - simulate!(sim, max_refinements = 1, verbose = true) - evt = Event([CartesianPoint{T}(0.01,0,0.003)]) - simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) - signalsum = T(0) - for i in 1:length(evt.waveforms) - signalsum += abs(evt.waveforms[i].value[end]) - end - @test isapprox( signalsum, T(2), atol = 5e-4 ) - end - =# - @testset "Simulate example detector: SigGen PPC" begin - sim = Simulation{T}(SSD_examples[:SigGen]) - simulate!(sim, max_refinements = 0, verbose = true) - evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 40e-3 )])) - simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) - signalsum = T(0) - for i in 1:length(evt.waveforms) - signalsum += abs(evt.waveforms[i].value[end]) - end - @test isapprox( signalsum, T(2), atol = 5e-4 ) - end -end +# @testset "Test real detectors" begin +# @testset "Simulate example detector: Inverted Coax" begin +# sim = Simulation{T}(SSD_examples[:InvertedCoax]) +# simulate!(sim, max_refinements = 1, verbose = true) +# evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 40e-3 )])) +# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) +# signalsum = T(0) +# for i in 1:length(evt.waveforms) +# signalsum += abs(evt.waveforms[i].value[end]) +# end +# @test isapprox( signalsum, T(2), atol = 5e-4 ) +# end +# @testset "Simulate example detector: Inverted Coax (in cryostat)" begin +# sim = Simulation{T}(SSD_examples[:InvertedCoaxInCryostat]) +# simulate!(sim, max_refinements = 1, verbose = true) +# evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 10e-3 )])) +# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) +# signalsum = T(0) +# for i in 1:length(evt.waveforms) +# signalsum += abs(evt.waveforms[i].value[end]) +# end +# @test isapprox( signalsum, T(2), atol = 5e-4 ) +# end +# @testset "Simulate example detector: Coax" begin +# sim = Simulation{T}(SSD_examples[:Coax]) +# simulate!(sim, max_refinements = 0, verbose = true) +# evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(30), 12e-3 )])) +# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) +# signalsum = T(0) +# for i in 1:length(evt.waveforms) +# signalsum += abs(evt.waveforms[i].value[end]) +# end +# @test isapprox( signalsum, T(2), atol = 4e-3 ) +# end +# @testset "Simulate example detector: BEGe" begin +# sim = Simulation{T}(SSD_examples[:BEGe]) +# simulate!(sim, max_refinements = 0, verbose = true) +# evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 20e-3 )])) +# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) +# signalsum = T(0) +# for i in 1:length(evt.waveforms) +# signalsum += abs(evt.waveforms[i].value[end]) +# end +# @test isapprox( signalsum, T(2), atol = 3e-3 ) +# end +# @testset "Simulate example detector: HexagonalPrism" begin +# sim = Simulation{T}(SSD_examples[:Hexagon]) +# simulate!(sim, max_refinements = 0, verbose = true) +# evt = Event([CartesianPoint{T}(0, 5e-4, 1e-3)]) +# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) +# signalsum = T(0) +# for i in 1:length(evt.waveforms) +# signalsum += abs(evt.waveforms[i].value[end]) +# end +# @test isapprox( signalsum, T(2), atol = 5e-4 ) +# end +# @testset "Simulate example detector: CGD" begin +# sim = Simulation{T}(SSD_examples[:CGD]) +# SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) +# simulate!(sim, max_refinements = 0, verbose = true) +# evt = Event([CartesianPoint{T}(5e-3, 5e-3, 5e-3)]) +# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) +# signalsum = T(0) +# for i in 1:length(evt.waveforms) +# signalsum += abs(evt.waveforms[i].value[end]) +# end +# @test isapprox( signalsum, T(2), atol = 5e-4 ) +# end +# #= +# @testset "Simulate example detector: Spherical" begin +# sim = Simulation{T}(SSD_examples[:Spherical]) +# SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) +# # simulate!(sim, max_refinements = 1, verbose = true) +# # evt = Event([CartesianPoint{T}(0,0,0)]) +# # simulate!(evt, sim) +# # signalsum = T(0) +# # for i in 1:length(evt.waveforms) +# # signalsum += abs(evt.waveforms[i].value[end]) +# # end +# # @test isapprox( signalsum, T(2), atol = 5e-4 ) +# end +# @testset "Simulate example detector: Toroidal" begin +# sim = Simulation{T}(SSD_examples[:CoaxialTorus]) +# SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) +# simulate!(sim, max_refinements = 1, verbose = true) +# evt = Event([CartesianPoint{T}(0.01,0,0.003)]) +# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) +# signalsum = T(0) +# for i in 1:length(evt.waveforms) +# signalsum += abs(evt.waveforms[i].value[end]) +# end +# @test isapprox( signalsum, T(2), atol = 5e-4 ) +# end +# =# +# @testset "Simulate example detector: SigGen PPC" begin +# sim = Simulation{T}(SSD_examples[:SigGen]) +# simulate!(sim, max_refinements = 0, verbose = true) +# evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 40e-3 )])) +# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) +# signalsum = T(0) +# for i in 1:length(evt.waveforms) +# signalsum += abs(evt.waveforms[i].value[end]) +# end +# @test isapprox( signalsum, T(2), atol = 5e-4 ) +# end +# end -@testset "ADLChargeDriftModel" begin - include("ADLChargeDriftModel.jl") -end +# @testset "ADLChargeDriftModel" begin +# include("ADLChargeDriftModel.jl") +# end -include("ConstructiveSolidGeometry/CSG_test.jl") -include("ConstructiveSolidGeometry/CSG_IO.jl") -include("ConstructiveSolidGeometry/CSG_decomposition.jl") \ No newline at end of file +# include("ConstructiveSolidGeometry/CSG_test.jl") +# include("ConstructiveSolidGeometry/CSG_IO.jl") +# include("ConstructiveSolidGeometry/CSG_decomposition.jl") \ No newline at end of file From d736137e30e7f4b4cbbabde852dbe5409406d9a3 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 10:58:53 +0200 Subject: [PATCH 003/241] Remove pos+neg-geometry and decomposed surf. fields from `Contact`, `Passive` and `Semiconductor` --- src/SolidStateDetector/Contacts.jl | 7 +------ src/SolidStateDetector/Passive.jl | 7 +------ src/SolidStateDetector/Semiconductor.jl | 5 ----- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/SolidStateDetector/Contacts.jl b/src/SolidStateDetector/Contacts.jl index 60cdf95a2..7f24c232b 100644 --- a/src/SolidStateDetector/Contacts.jl +++ b/src/SolidStateDetector/Contacts.jl @@ -12,9 +12,6 @@ mutable struct Contact{T} <: AbstractContact{T} id::Int name::String geometry::AbstractGeometry{T} - geometry_positive::Vector{AbstractGeometry{T}} - geometry_negative::Vector{AbstractGeometry{T}} - decomposed_surfaces::Vector{AbstractGeometry{T}} end @@ -23,9 +20,7 @@ function Contact{T}(dict::Union{Dict{String,Any}, Dict{Any, Any}}, input_units:: haskey(dict, "material") ? material = material_properties[materials[dict["material"]]] : material = material_properties[materials["HPGe"]] haskey(dict,"name") ? name = dict["name"] : name = "" geometry = transform(Geometry(T, dict["geometry"], input_units), transformations) - geometry_positive, geometry_negative = get_decomposed_volumes(geometry) - decomposed_surfaces = vcat(get_decomposed_surfaces.(geometry_positive)...) - return Contact{T}( dict["potential"], material, channel, name, geometry, geometry_positive, geometry_negative, decomposed_surfaces ) + return Contact{T}( dict["potential"], material, channel, name, geometry ) end function println(io::IO, d::Contact) diff --git a/src/SolidStateDetector/Passive.jl b/src/SolidStateDetector/Passive.jl index 6969fa772..51e94885f 100644 --- a/src/SolidStateDetector/Passive.jl +++ b/src/SolidStateDetector/Passive.jl @@ -8,10 +8,7 @@ mutable struct Passive{T} <: AbstractPassive{T} material::NamedTuple charge_density_model::AbstractChargeDensity{T} geometry::AbstractGeometry{T} - geometry_positive::Vector{AbstractGeometry{T}} - geometry_negative::Vector{AbstractGeometry{T}} - decomposed_surfaces::Vector{AbstractGeometry{T}} - + Passive{T}() where T <: SSDFloat = new{T}() end @@ -36,8 +33,6 @@ function Passive{T}(dict::Dict, input_units::NamedTuple, transformations::Vector ConstantChargeDensity{T}(0) end pass.geometry = transform(Geometry(T, dict["geometry"], input_units), transformations) - pass.geometry_positive, pass.geometry_negative = get_decomposed_volumes(pass.geometry) - pass.decomposed_surfaces = vcat(get_decomposed_surfaces.(pass.geometry_positive)...) return pass end diff --git a/src/SolidStateDetector/Semiconductor.jl b/src/SolidStateDetector/Semiconductor.jl index c8741b2a6..f019d96ae 100644 --- a/src/SolidStateDetector/Semiconductor.jl +++ b/src/SolidStateDetector/Semiconductor.jl @@ -8,9 +8,6 @@ mutable struct Semiconductor{T} <: AbstractSemiconductor{T} impurity_density_model::AbstractImpurityDensity{T} charge_drift_model::AbstractChargeDriftModel{T} geometry::AbstractGeometry{T} - geometry_positive::Vector{AbstractGeometry{T}} - geometry_negative::Vector{AbstractGeometry{T}} - decomposed_surfaces::Vector{AbstractGeometry{T}} Semiconductor{T}() where T <: SSDFloat = new{T}() end @@ -35,8 +32,6 @@ function Semiconductor{T}(dict::Dict, input_units::NamedTuple, transformations:: end sc.material = material_properties[materials[dict["material"]]] sc.geometry = transform(Geometry(T, dict["geometry"], input_units), transformations) - sc.geometry_positive, sc.geometry_negative = get_decomposed_volumes(sc.geometry) - sc.decomposed_surfaces = vcat(get_decomposed_surfaces.(sc.geometry_positive)...) return sc end From 8edaa4d3c2e74891b41cc0c24eba8936aaa67c4f Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 11:02:25 +0200 Subject: [PATCH 004/241] Make `Contact` immutable --- src/SolidStateDetector/Contacts.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/SolidStateDetector/Contacts.jl b/src/SolidStateDetector/Contacts.jl index 7f24c232b..e07c2195f 100644 --- a/src/SolidStateDetector/Contacts.jl +++ b/src/SolidStateDetector/Contacts.jl @@ -6,21 +6,21 @@ abstract type AbstractContact{T} <: AbstractObject{T} end T: Type of precision. """ -mutable struct Contact{T} <: AbstractContact{T} +struct Contact{T,G,MT} <: AbstractContact{T} potential::T - material::NamedTuple + material::MT id::Int name::String - geometry::AbstractGeometry{T} + geometry::G end function Contact{T}(dict::Union{Dict{String,Any}, Dict{Any, Any}}, input_units::NamedTuple, transformations::Vector{CSGTransformation})::Contact{T} where {T <: SSDFloat} - haskey(dict, "channel") ? channel = dict["channel"] : channel = -1 - haskey(dict, "material") ? material = material_properties[materials[dict["material"]]] : material = material_properties[materials["HPGe"]] - haskey(dict,"name") ? name = dict["name"] : name = "" + id::Int = haskey(dict, "channel") ? dict["channel"] : -1 + material = haskey(dict, "material") ? material_properties[materials[dict["material"]]] : material_properties[materials["HPGe"]] + name = haskey(dict,"name") ? dict["name"] : "" geometry = transform(Geometry(T, dict["geometry"], input_units), transformations) - return Contact{T}( dict["potential"], material, channel, name, geometry ) + return Contact( T(dict["potential"]), material, id, name, geometry ) end function println(io::IO, d::Contact) From 86ba7adcbe97e80134ef1426bee09ad19eb46489 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 11:25:07 +0200 Subject: [PATCH 005/241] Add a surronding object (a base plate) for testing of `Passive` --- .../public_CGD_config.json | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/examples/example_config_files/public_CGD_config.json b/examples/example_config_files/public_CGD_config.json index 2bb297063..2d03b73ee 100644 --- a/examples/example_config_files/public_CGD_config.json +++ b/examples/example_config_files/public_CGD_config.json @@ -114,5 +114,28 @@ } ] } + ], + "surroundings": [ + { + "name": "Base", + "material": "Copper", + "potential": 1000, + "geometry": { + "box": { + "x": { + "from": -5, + "to": 15 + }, + "y": { + "from": -5, + "to": 15.0 + }, + "z": { + "from": -2, + "to": -1 + } + } + } + } ] } From 6712d35f8d04a4d2ccf4f0088f070dc3ba75db03 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 11:26:07 +0200 Subject: [PATCH 006/241] Disable painting (through sampling) of contacts --- src/SolidStateDetector/DetectorGeometries.jl | 48 ++++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/SolidStateDetector/DetectorGeometries.jl b/src/SolidStateDetector/DetectorGeometries.jl index 035157563..438a8d8be 100644 --- a/src/SolidStateDetector/DetectorGeometries.jl +++ b/src/SolidStateDetector/DetectorGeometries.jl @@ -337,18 +337,18 @@ function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, p end end - for contact in ssd.contacts - pot::T = if ismissing(weighting_potential_contact_id) - contact.potential - else - contact.id == weighting_potential_contact_id ? 1 : 0 - end - contact_gridpoints = paint_object(contact, grid) - for gridpoint in contact_gridpoints - potential[ gridpoint... ] = pot - pointtypes[ gridpoint... ] = zero(PointType) - end - end + # for contact in ssd.contacts + # pot::T = if ismissing(weighting_potential_contact_id) + # contact.potential + # else + # contact.id == weighting_potential_contact_id ? 1 : 0 + # end + # contact_gridpoints = paint_object(contact, grid) + # for gridpoint in contact_gridpoints + # potential[ gridpoint... ] = pot + # pointtypes[ gridpoint... ] = zero(PointType) + # end + # end nothing end @@ -401,18 +401,18 @@ function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, p end end end - for contact in ssd.contacts - pot::T = if ismissing(weighting_potential_contact_id) - contact.potential - else - contact.id == weighting_potential_contact_id ? 1 : 0 - end - contact_gridpoints = paint_object(contact, grid) - for gridpoint in contact_gridpoints - potential[ gridpoint... ] = pot - pointtypes[ gridpoint... ] = zero(PointType) - end - end + # for contact in ssd.contacts + # pot::T = if ismissing(weighting_potential_contact_id) + # contact.potential + # else + # contact.id == weighting_potential_contact_id ? 1 : 0 + # end + # contact_gridpoints = paint_object(contact, grid) + # for gridpoint in contact_gridpoints + # potential[ gridpoint... ] = pot + # pointtypes[ gridpoint... ] = zero(PointType) + # end + # end nothing end From b0bb166b957fa2316599f32363832c7f8e72f413 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 11:26:26 +0200 Subject: [PATCH 007/241] Make `Passive` immutable --- src/SolidStateDetector/Passive.jl | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/SolidStateDetector/Passive.jl b/src/SolidStateDetector/Passive.jl index 51e94885f..8183d7b48 100644 --- a/src/SolidStateDetector/Passive.jl +++ b/src/SolidStateDetector/Passive.jl @@ -1,25 +1,22 @@ abstract type AbstractPassive{T} <: AbstractObject{T} end -mutable struct Passive{T} <: AbstractPassive{T} +mutable struct Passive{T,G,MT,CDM} <: AbstractPassive{T} name::String id::Int - potential::Union{Symbol,T} - temperature::Union{T,Missing} - material::NamedTuple - charge_density_model::AbstractChargeDensity{T} - geometry::AbstractGeometry{T} - - Passive{T}() where T <: SSDFloat = new{T}() + potential::T + temperature::T + material::MT + charge_density_model::CDM + geometry::G end function Passive{T}(dict::Dict, input_units::NamedTuple, transformations::Vector{CSGTransformation}) where T <: SSDFloat - pass = Passive{T}() - haskey(dict, "name") ? pass.name = dict["name"] : pass.name = "external part" - haskey(dict, "id") ? pass.id = dict["id"] : pass.id = -1 - haskey(dict, "potential") ? pass.potential = T(dict["potential"]) : pass.potential = :floating - haskey(dict, "temperature") ? pass.temperature = T(dict["temperature"]) : pass.temperature = missing - pass.material = material_properties[materials[dict["material"]]] - pass.charge_density_model = if haskey(dict, "charge_density") + name = haskey(dict, "name") ? dict["name"] : "external part" + id::Int = haskey(dict, "id") ? dict["id"] : -1 + potential = haskey(dict, "potential") ? T(dict["potential"]) : :floating + temperature = haskey(dict, "temperature") ? T(dict["temperature"]) : T(80) + material = material_properties[materials[dict["material"]]] + charge_density_model = if haskey(dict, "charge_density") ChargeDensity(T, dict["charge_density"], input_units) elseif haskey(dict, "charge_density_model") @warn "Config file deprication: There was an internal change from v0.5.1 to v0.6.0 regarding the @@ -32,8 +29,8 @@ function Passive{T}(dict::Dict, input_units::NamedTuple, transformations::Vector else ConstantChargeDensity{T}(0) end - pass.geometry = transform(Geometry(T, dict["geometry"], input_units), transformations) - return pass + geometry = transform(Geometry(T, dict["geometry"], input_units), transformations) + return Passive(name, id, potential, temperature, material, charge_density_model, geometry) end function println(io::IO, d::Passive{T}) where {T} From 11860c3652ced249079b93c9256a00b51c4d4bed Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 11:27:05 +0200 Subject: [PATCH 008/241] Look for `Passive`s under the dict-field `surroundings` --- src/SolidStateDetector/SolidStateDetector.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SolidStateDetector/SolidStateDetector.jl b/src/SolidStateDetector/SolidStateDetector.jl index 147893f70..a7f43bb68 100644 --- a/src/SolidStateDetector/SolidStateDetector.jl +++ b/src/SolidStateDetector/SolidStateDetector.jl @@ -136,13 +136,13 @@ function SolidStateDetector{T}(config_file::Dict, input_units::NamedTuple)::Soli if haskey(config_detector, "contacts") contacts = broadcast(c -> construct_contact(T, c, input_units, transformations), config_detector["contacts"]) end - if haskey(config_detector, "passives") - passives = broadcast(p -> construct_passive(T, p, input_units, transformations), config_detector["passives"]) - end if haskey(config_detector, "virtual_drift_volumes") virtual_drift_volumes = broadcast(v -> construct_virtual_volume(T, v, input_units, transformations), config_detector["virtual_drift_volumes"]) end end + if haskey(config_file, "surroundings") + passives = broadcast(p -> construct_passive(T, p, input_units, transformations), config_file["surroundings"]) + end c = SolidStateDetector{T}() c.name = haskey(config_file, "name") ? config_file["name"] : "NoNameDetector" From 3595ac70c03fd23f236bcb517d409424462d6cb2 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 11:42:31 +0200 Subject: [PATCH 009/241] Make `Semiconductor` immutable --- src/SolidStateDetector/Semiconductor.jl | 26 +++++++++----------- src/SolidStateDetector/SolidStateDetector.jl | 4 +-- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/SolidStateDetector/Semiconductor.jl b/src/SolidStateDetector/Semiconductor.jl index f019d96ae..de3cc827e 100644 --- a/src/SolidStateDetector/Semiconductor.jl +++ b/src/SolidStateDetector/Semiconductor.jl @@ -1,20 +1,15 @@ abstract type AbstractSemiconductor{T} <: AbstractObject{T} end -mutable struct Semiconductor{T} <: AbstractSemiconductor{T} - name::String - id::Int +struct Semiconductor{T,G,MT,CDM,IDM} <: AbstractSemiconductor{T} temperature::T - material::NamedTuple - impurity_density_model::AbstractImpurityDensity{T} - charge_drift_model::AbstractChargeDriftModel{T} - geometry::AbstractGeometry{T} - - Semiconductor{T}() where T <: SSDFloat = new{T}() + material::MT + impurity_density_model::IDM + charge_drift_model::CDM + geometry::G end function Semiconductor{T}(dict::Dict, input_units::NamedTuple, transformations::Vector{CSGTransformation} = []) where T <: SSDFloat - sc = Semiconductor{T}() - sc.impurity_density_model = if haskey(dict, "impurity_density") + impurity_density_model = if haskey(dict, "impurity_density") ImpurityDensity(T, dict["impurity_density"], input_units) elseif haskey(dict, "charge_density_model") @warn "Config file deprication: The field \"charge_density_model\" under semiconductor is deprecated. @@ -24,15 +19,16 @@ function Semiconductor{T}(dict::Dict, input_units::NamedTuple, transformations:: else ConstantImpurityDensity{T}(0) end - sc.charge_drift_model = if haskey(dict, "charge_drift_model") && haskey(dict["charge_drift_model"], "model") + charge_drift_model = if haskey(dict, "charge_drift_model") && haskey(dict["charge_drift_model"], "model") cdm = getfield(Main, Symbol(dict["charge_drift_model"]["model"])){T} cdm <: AbstractChargeDriftModel{T} ? cdm() : ElectricFieldChargeDriftModel{T}() else ElectricFieldChargeDriftModel{T}() end - sc.material = material_properties[materials[dict["material"]]] - sc.geometry = transform(Geometry(T, dict["geometry"], input_units), transformations) - return sc + temperature = haskey(dict, "temperature") ? T(dict["temperature"]) : T(80) + material = material_properties[materials[dict["material"]]] + geometry = transform(Geometry(T, dict["geometry"], input_units), transformations) + return Semiconductor(temperature, material, impurity_density_model, charge_drift_model, geometry) end diff --git a/src/SolidStateDetector/SolidStateDetector.jl b/src/SolidStateDetector/SolidStateDetector.jl index a7f43bb68..f607a4876 100644 --- a/src/SolidStateDetector/SolidStateDetector.jl +++ b/src/SolidStateDetector/SolidStateDetector.jl @@ -4,7 +4,7 @@ """ mutable struct SolidStateDetector{T <: SSDFloat} <: AbstractConfig{T} name::String # optional - semiconductor::Semiconductor{T} + semiconductor::Any contacts::Vector{Contact{T}} passives::Vector{Passive{T}} virtual_drift_volumes::Vector{AbstractVirtualVolume{T}} @@ -13,7 +13,7 @@ end get_precision_type(::SolidStateDetector{T}) where {T} = T function SolidStateDetector{T}()::SolidStateDetector{T} where {T <: SSDFloat} - semiconductor::Semiconductor{T} = Semiconductor{T}() + semiconductor = missing contacts::Vector{Contact{T}}, passives::Vector{Passive{T}} = [], [] virtual_drift_volumes::Vector{AbstractVirtualVolume{T}} = [] From fc25adf94025d928a353de112c500e72edc26830 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 11:57:38 +0200 Subject: [PATCH 010/241] Make `SolidStateDetector` immutable --- src/Simulation/Simulation.jl | 2 +- src/SolidStateDetector/SolidStateDetector.jl | 59 ++++++++------------ 2 files changed, 23 insertions(+), 38 deletions(-) diff --git a/src/Simulation/Simulation.jl b/src/Simulation/Simulation.jl index 815ad284f..4f9934bee 100644 --- a/src/Simulation/Simulation.jl +++ b/src/Simulation/Simulation.jl @@ -27,7 +27,7 @@ function Simulation{T,CS}() where {T <: SSDFloat, CS <: AbstractCoordinateSystem Dict(), default_unit_tuple(), material_properties[materials["vacuum"]], - SolidStateDetector{T}(), + missing, World(CS,(T(0),T(1),T(0),T(1),T(0),T(1))), missing, missing, diff --git a/src/SolidStateDetector/SolidStateDetector.jl b/src/SolidStateDetector/SolidStateDetector.jl index f607a4876..bebc9f882 100644 --- a/src/SolidStateDetector/SolidStateDetector.jl +++ b/src/SolidStateDetector/SolidStateDetector.jl @@ -2,29 +2,18 @@ mutable struct SolidStateDetector{T <: SSDFloat} <: AbstractConfig{T} """ -mutable struct SolidStateDetector{T <: SSDFloat} <: AbstractConfig{T} +struct SolidStateDetector{T,SC,CT,PT,VDM} <: AbstractConfig{T} name::String # optional - semiconductor::Any - contacts::Vector{Contact{T}} - passives::Vector{Passive{T}} - virtual_drift_volumes::Vector{AbstractVirtualVolume{T}} + semiconductor::SC + contacts::CT + passives::PT + virtual_drift_volumes::VDM + + SolidStateDetector{T}(n::AbstractString,s::SC,c::C,p::P,v::VDM) where {T,SC,C,P,VDM}= new{T,SC,C,P,VDM}(n,s,c,p,v) end -get_precision_type(::SolidStateDetector{T}) where {T} = T -function SolidStateDetector{T}()::SolidStateDetector{T} where {T <: SSDFloat} - semiconductor = missing - contacts::Vector{Contact{T}}, passives::Vector{Passive{T}} = [], [] - virtual_drift_volumes::Vector{AbstractVirtualVolume{T}} = [] - - return SolidStateDetector{T}( - "EmptyDetector", - semiconductor, - contacts, - passives, - virtual_drift_volumes - ) -end +get_precision_type(::SolidStateDetector{T}) where {T} = T function construct_semiconductor(T, sc::Dict, input_units::NamedTuple, transformations::Vector{CSGTransformation}= []) Semiconductor{T}(sc, input_units, transformations) @@ -120,10 +109,7 @@ function get_world_limits_from_objects(::Type{Cartesian}, s::Semiconductor{T}, c return ax1l, ax1r, ax2l, ax2r, ax3l, ax3r end -function SolidStateDetector{T}(config_file::Dict, input_units::NamedTuple)::SolidStateDetector{T} where {T <: SSDFloat} - contacts::Vector{Contact{T}}, passives::Vector{Passive{T}} = [], [] - virtual_drift_volumes::Vector{AbstractVirtualVolume{T}} = [] - +function SolidStateDetector{T}(config_file::Dict, input_units::NamedTuple) where {T <: SSDFloat} if haskey(config_file, "detectors") config_detector = config_file["detectors"][1] # still only one detector @@ -133,24 +119,23 @@ function SolidStateDetector{T}(config_file::Dict, input_units::NamedTuple)::Soli @assert haskey(config_detector, "bulk") "Each detector needs an entry `bulk`. Please define the bulk." semiconductor = construct_semiconductor(T, config_detector["bulk"], input_units, transformations) - if haskey(config_detector, "contacts") - contacts = broadcast(c -> construct_contact(T, c, input_units, transformations), config_detector["contacts"]) - end - if haskey(config_detector, "virtual_drift_volumes") - virtual_drift_volumes = broadcast(v -> construct_virtual_volume(T, v, input_units, transformations), config_detector["virtual_drift_volumes"]) + @assert haskey(config_detector, "contacts") "Each detector needs at least two contacts. Please define the them in the configuration file." + contacts = broadcast(c -> construct_contact(T, c, input_units, transformations), config_detector["contacts"]) + + virtual_drift_volumes = if haskey(config_detector, "virtual_drift_volumes") + broadcast(v -> construct_virtual_volume(T, v, input_units, transformations), config_detector["virtual_drift_volumes"]) + else + missing end end - if haskey(config_file, "surroundings") - passives = broadcast(p -> construct_passive(T, p, input_units, transformations), config_file["surroundings"]) + passives = if haskey(config_file, "surroundings") + broadcast(p -> construct_passive(T, p, input_units, transformations), config_file["surroundings"]) + else + missing end - c = SolidStateDetector{T}() - c.name = haskey(config_file, "name") ? config_file["name"] : "NoNameDetector" - c.semiconductor = semiconductor - c.contacts = contacts - c.passives = passives - c.virtual_drift_volumes = virtual_drift_volumes - return c + name = haskey(config_file, "name") ? config_file["name"] : "NoNameDetector" + SolidStateDetector{T}( name, semiconductor, contacts, passives, virtual_drift_volumes ) end function SolidStateDetector(parsed_dict::Dict) From e857dc013b71ca20357b0bdd4d61c7d2833428b4 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 12:03:33 +0200 Subject: [PATCH 011/241] Fix the issue of parsing of certain values, e.g. 0.01 -> 0.0100001, from config files. --- src/ConstructiveSolidGeometry/IO.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 5d29e9270..f6f350fa4 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -33,8 +33,8 @@ end #### INTERNAL PARSE FUNCTIONS # parses dictionary entries of type Real or String to their value in internal units -@inline _parse_value(::Type{T}, x::Real, unit::Unitful.Units) where {T} = to_internal_units(T(x) * unit) -@inline _parse_value(::Type{T}, s::String, ::Unitful.Units) where {T} = to_internal_units(T(uparse(s))) +@inline _parse_value(::Type{T}, x::Real, unit::Unitful.Units) where {T} = T(to_internal_units(x * unit)) +@inline _parse_value(::Type{T}, s::String, ::Unitful.Units) where {T} = T(to_internal_units(uparse(s))) @inline _parse_value(::Type{T}, a::Vector, unit::Unitful.Units) where {T} = _parse_value.(T, a, unit) # parses dictionary entries of type {"from": ..., "to": ... } to a Tuple of the interval boundaries From b7ce8cf17c0975f65d0ad65d456d76472249d198 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 12:12:12 +0200 Subject: [PATCH 012/241] Convert example CGD config file to `.yaml` --- .../public_CGD_config.json | 141 ------------------ .../public_CGD_config.yaml | 96 ++++++++++++ src/examples.jl | 2 +- 3 files changed, 97 insertions(+), 142 deletions(-) delete mode 100644 examples/example_config_files/public_CGD_config.json create mode 100644 examples/example_config_files/public_CGD_config.yaml diff --git a/examples/example_config_files/public_CGD_config.json b/examples/example_config_files/public_CGD_config.json deleted file mode 100644 index 2d03b73ee..000000000 --- a/examples/example_config_files/public_CGD_config.json +++ /dev/null @@ -1,141 +0,0 @@ -{ - "name": "ExampleCuboid", - "units": { - "length": "mm", - "angle": "deg", - "potential": "V", - "temperature": "K" - }, - "grid": { - "coordinates": "cartesian", - "axes": { - "x": { - "from": -5, - "to": 15, - "boundaries": "inf" - }, - "y": { - "from": -5, - "to": 15, - "boundaries": "inf" - }, - "z": { - "from": -5, - "to": 15, - "boundaries": "inf" - } - } - }, - "medium": "vacuum", - "detectors": [ - { - "bulk": { - "material": "HPGe", - "temperature": 78, - "impurity_density": { - "name": "linear", - "x": { - "init": 0.0, - "gradient": 0.0 - }, - "y": { - "init": 0.0, - "gradient": 0.0 - }, - "z": { - "init": 1.0e7, - "gradient": 50000.0 - } - }, - "charge_drift_model": { - "include": "ADLChargeDriftModel/drift_velocity_config.json" - }, - "geometry": { - "box": { - "x": { - "from": 0.0, - "to": 10.0 - }, - "y": { - "from": 0.0, - "to": 10.0 - }, - "z": { - "from": 0.0, - "to": 10.0 - } - } - } - }, - "contacts": [ - { - "material": "HPGe", - "name": "n+ contact", - "potential": 2000.0, - "channel": 1, - "geometry": { - "box": { - "x": { - "from": 0.0, - "to": 0.1 - }, - "y": { - "from": 0.0, - "to": 10.0 - }, - "z": { - "from": 0.0, - "to": 10.0 - } - } - } - }, - { - "material": "HPGe", - "name": "p+ contact", - "potential": 0.0, - "channel": 2, - "geometry": { - "box": { - "x": { - "from": 9.9, - "to": 10.0 - }, - "y": { - "from": 0.0, - "to": 10.0 - }, - "z": { - "from": 0.0, - "to": 10.0 - } - } - } - } - ] - } - ], - "surroundings": [ - { - "name": "Base", - "material": "Copper", - "potential": 1000, - "geometry": { - "box": { - "x": { - "from": -5, - "to": 15 - }, - "y": { - "from": -5, - "to": 15.0 - }, - "z": { - "from": -2, - "to": -1 - } - } - } - } - ] -} diff --git a/examples/example_config_files/public_CGD_config.yaml b/examples/example_config_files/public_CGD_config.yaml new file mode 100644 index 000000000..2f5e1186f --- /dev/null +++ b/examples/example_config_files/public_CGD_config.yaml @@ -0,0 +1,96 @@ +name: ExampleCuboid +units: + length: mm + angle: deg + potential: V + temperature: K +grid: + coordinates: cartesian + axes: + x: + from: -5 + to: 15 + boundaries: inf + y: + from: -5 + to: 15 + boundaries: inf + z: + from: -5 + to: 15 + boundaries: inf +medium: vacuum +detectors: +- bulk: + material: HPGe + temperature: 78 + impurity_density: + name: linear + x: + init: 0 + gradient: 0 + y: + init: 0 + gradient: 0 + z: + init: 10000000 + gradient: 50000 + charge_drift_model: + include: ADLChargeDriftModel/drift_velocity_config.json + geometry: + box: + x: + from: 0 + to: 10 + y: + from: 0 + to: 10 + z: + from: 0 + to: 10 + contacts: + - material: HPGe + name: n+ contact + potential: 2000 + channel: 1 + geometry: + box: + x: + from: 0 + to: 0.1 + y: + from: 0 + to: 10 + z: + from: 0 + to: 10 + - material: HPGe + name: p+ contact + potential: 0 + channel: 2 + geometry: + box: + x: + from: 9.9 + to: 10 + y: + from: 0 + to: 10 + z: + from: 0 + to: 10 +surroundings: +- name: Base + material: Copper + potential: 1000 + geometry: + box: + x: + from: -5 + to: 15 + y: + from: -5 + to: 15 + z: + from: -2 + to: -1 \ No newline at end of file diff --git a/src/examples.jl b/src/examples.jl index e6887c940..1bff85d26 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -22,7 +22,7 @@ SSD_examples[:BEGe] = ( joinpath(@__DIR__, "../examples/example_config_files/public_SegBEGe_config.json") ) SSD_examples[:CGD] = ( - joinpath(@__DIR__, "../examples/example_config_files/public_CGD_config.json") + joinpath(@__DIR__, "../examples/example_config_files/public_CGD_config.yaml") ) SSD_examples[:Spherical] = ( joinpath(@__DIR__, "../examples/example_config_files/public_spherical_detector_config.json") From 0ca5cb6c4ec8a654e5e63aa9eb82aa3fae16acf6 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 12:45:31 +0200 Subject: [PATCH 013/241] Run YAML formatter --- .../public_CGD_config.yaml | 134 +++++++++--------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/examples/example_config_files/public_CGD_config.yaml b/examples/example_config_files/public_CGD_config.yaml index 2f5e1186f..7fa4b44ac 100644 --- a/examples/example_config_files/public_CGD_config.yaml +++ b/examples/example_config_files/public_CGD_config.yaml @@ -9,11 +9,11 @@ grid: axes: x: from: -5 - to: 15 + to: 15 boundaries: inf y: from: -5 - to: 15 + to: 15 boundaries: inf z: from: -5 @@ -21,76 +21,76 @@ grid: boundaries: inf medium: vacuum detectors: -- bulk: - material: HPGe - temperature: 78 - impurity_density: - name: linear - x: - init: 0 - gradient: 0 - y: - init: 0 - gradient: 0 - z: - init: 10000000 - gradient: 50000 - charge_drift_model: - include: ADLChargeDriftModel/drift_velocity_config.json - geometry: - box: + - bulk: + material: HPGe + temperature: 78 + impurity_density: + name: linear x: - from: 0 - to: 10 + init: 0 + gradient: 0 y: - from: 0 - to: 10 + init: 0 + gradient: 0 z: - from: 0 - to: 10 - contacts: - - material: HPGe - name: n+ contact - potential: 2000 - channel: 1 - geometry: - box: - x: - from: 0 - to: 0.1 - y: - from: 0 - to: 10 - z: - from: 0 - to: 10 - - material: HPGe - name: p+ contact - potential: 0 - channel: 2 + init: 10000000 + gradient: 50000 + charge_drift_model: + include: ADLChargeDriftModel/drift_velocity_config.json + geometry: + box: + x: + from: 0 + to: 10 + y: + from: 0 + to: 10 + z: + from: 0 + to: 10 + contacts: + - material: HPGe + name: n+ contact + potential: 2000 + channel: 1 + geometry: + box: + x: + from: 0 + to: 0.1 + y: + from: 0 + to: 10 + z: + from: 0 + to: 10 + - material: HPGe + name: p+ contact + potential: 0 + channel: 2 + geometry: + box: + x: + from: 9.9 + to: 10 + y: + from: 0 + to: 10 + z: + from: 0 + to: 10 +surroundings: + - name: Base + material: Copper + potential: 1000 geometry: box: x: - from: 9.9 - to: 10 + from: -5 + to: 15 y: - from: 0 - to: 10 + from: -5 + to: 15 z: - from: 0 - to: 10 -surroundings: -- name: Base - material: Copper - potential: 1000 - geometry: - box: - x: - from: -5 - to: 15 - y: - from: -5 - to: 15 - z: - from: -2 - to: -1 \ No newline at end of file + from: -2 + to: -1 From 522090a9511a046032c4c38312b24653c8993f61 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 10 Jun 2021 14:24:17 +0200 Subject: [PATCH 014/241] Disable all primitives and geometry plot recipes --- src/ConstructiveSolidGeometry/IO.jl | 30 ++-- .../LinePrimitives/LinePrimitives.jl | 2 - .../PointsAndVectors/PointsAndVectors.jl | 24 +++ .../SurfacePrimitives/SurfacePrimitives.jl | 10 -- .../VolumePrimitives/VolumePrimitives.jl | 5 - .../plotting/PointsAndVectors/Points.jl | 0 .../PointsAndVectors/PointsAndVectors.jl | 2 + .../plotting/PointsAndVectors/Vectors.jl | 0 .../SurfacePrimitives/SurfacePrimitives.jl | 39 ++--- .../VolumePrimitives/VolumePrimitives.jl | 4 - .../plotting/plotting.jl | 154 +++++++++--------- 11 files changed, 134 insertions(+), 136 deletions(-) create mode 100644 src/ConstructiveSolidGeometry/PointsAndVectors/PointsAndVectors.jl create mode 100644 src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Points.jl create mode 100644 src/ConstructiveSolidGeometry/plotting/PointsAndVectors/PointsAndVectors.jl create mode 100644 src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index f6f350fa4..7b7990077 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -1,19 +1,19 @@ const CSG_dict = Dict{String, Any}( - "tube" => Cone, - "cone" => Cone, - "sphere" => Sphere, - "box" => Box, - "torus" => Torus, - "TriangularPrism" => TriangularPrism, - "SquarePrism" => SquarePrism, - "PentagonalPrism" => PentagonalPrism, - "HexagonalPrism" => HexagonalPrism, - "union" => CSGUnion, - "difference" => CSGDifference, - "intersection" => CSGIntersection, - "translate" => TranslatedGeometry, - "rotate" => RotatedGeometry, - "scale" => ScaledGeometry + # "tube" => Cone, + # "cone" => Cone, + # "sphere" => Sphere, + # "box" => Box, + # "torus" => Torus, + # "TriangularPrism" => TriangularPrism, + # "SquarePrism" => SquarePrism, + # "PentagonalPrism" => PentagonalPrism, + # "HexagonalPrism" => HexagonalPrism, + # "union" => CSGUnion, + # "difference" => CSGDifference, + # "intersection" => CSGIntersection, + # "translate" => TranslatedGeometry, + # "rotate" => RotatedGeometry, + # "scale" => ScaledGeometry ) function get_geometry_key(::Type{T}, dict::AbstractDict, input_units::NamedTuple)::Tuple{String, Vector{CSGTransformation}} where {T} diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl b/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl index 09b6e5dcc..e69de29bb 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl @@ -1,2 +0,0 @@ -include("Line.jl") -include("Arc.jl") diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors/PointsAndVectors.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/PointsAndVectors.jl new file mode 100644 index 000000000..941a85be1 --- /dev/null +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/PointsAndVectors.jl @@ -0,0 +1,24 @@ +@recipe function f(p::CylindricalPoint) + @series begin + CartesianPoint(p) + end +end +@recipe function f(p::CartesianPoint) + # st -> :scatter + @series begin + [p.x], [p.y], [p.z] + end +end +@recipe function f(v::AbstractVector{<:CartesianPoint}) + st -> :scatter + @series begin + [v[i].x for i in eachindex(v)], [v[i].y for i in eachindex(v)], [v[i].z for i in eachindex(v)] + end +end + +@recipe function f(v::AbstractVector{<:CylindricalPoint}) + st -> :scatter + @series begin + map(x->CartesianPoint(x),v) + end +end \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl index ed0e62c89..e69de29bb 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl @@ -1,10 +0,0 @@ -include("ConalPlane.jl") -include("ConeMantle.jl") -include("CylindricalAnnulus.jl") -include("Rectangle.jl") -include("RegularPolygon.jl") -include("RegularPrismMantle.jl") -include("SphereMantle.jl") -include("ToroidalAnnulus.jl") -include("TorusMantle.jl") -#include("Plane.jl") diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index 178ded751..e69de29bb 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -1,5 +0,0 @@ -include("Cone.jl") -include("Box.jl") -include("RegularPrism.jl") -include("Sphere.jl") -include("Torus.jl") diff --git a/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Points.jl b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Points.jl new file mode 100644 index 000000000..e69de29bb diff --git a/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/PointsAndVectors.jl b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/PointsAndVectors.jl new file mode 100644 index 000000000..fb40e1d59 --- /dev/null +++ b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/PointsAndVectors.jl @@ -0,0 +1,2 @@ +include("Points.jl") +include("Vectors.jl") \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl new file mode 100644 index 000000000..e69de29bb diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl index 5222142c2..36a98ec74 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl @@ -1,25 +1,16 @@ -include("ConalPlane.jl") -include("ConeMantle.jl") -include("CylindricalAnnulus.jl") -include("Rectangle.jl") -include("RegularPolygon.jl") -include("RegularPrismMantle.jl") -include("SphereMantle.jl") -include("ToroidalAnnulus.jl") -include("TorusMantle.jl") -#include("Plane.jl") -@recipe function f(g::AbstractSurfacePrimitive; SSD_style = :wireframe, n = 30) - if SSD_style == :wireframe #update to only plot real surfaces - linewidth --> 2 - for points in get_plot_points(g, n = n) - @series begin - label := "" - points - end - end - elseif SSD_style == :surface - linewidth --> 0.2 - mesh(g) - end -end + +# @recipe function f(g::AbstractSurfacePrimitive; SSD_style = :wireframe, n = 30) +# if SSD_style == :wireframe #update to only plot real surfaces +# linewidth --> 2 +# for points in get_plot_points(g, n = n) +# @series begin +# label := "" +# points +# end +# end +# elseif SSD_style == :surface +# linewidth --> 0.2 +# mesh(g) +# end +# end diff --git a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl index 0718d0e8e..e69de29bb 100644 --- a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl @@ -1,4 +0,0 @@ -include("Box.jl") -include("Cone.jl") -include("RegularPrism.jl") -include("Sphere.jl") diff --git a/src/ConstructiveSolidGeometry/plotting/plotting.jl b/src/ConstructiveSolidGeometry/plotting/plotting.jl index 00a8a94a3..3f5a70719 100644 --- a/src/ConstructiveSolidGeometry/plotting/plotting.jl +++ b/src/ConstructiveSolidGeometry/plotting/plotting.jl @@ -1,90 +1,92 @@ -include("PointsAndVectors.jl") +include("PointsAndVectors/PointsAndVectors.jl") +include("LinePrimitives/LinePrimitives.jl") +include("SurfacePrimitives/SurfacePrimitives.jl") +include("VolumePrimitives/VolumePrimitives.jl") -include("Meshing.jl") +# include("Meshing.jl") -include("Wireframe.jl") +# include("Wireframe.jl") -include("SurfacePrimitives/SurfacePrimitives.jl") -@recipe function f(g::AbstractGeometry{T}; SSD_style = :wireframe, n = 30) where {T} +# @recipe function f(g::AbstractGeometry{T}; SSD_style = :wireframe, n = 30) where {T} - seriescolor --> :orange +# seriescolor --> :orange - @series begin - label --> "Geometry" - [] - end +# @series begin +# label --> "Geometry" +# [] +# end - pos, _ = get_decomposed_volumes(g) +# pos, _ = get_decomposed_volumes(g) - for p in pos - if SSD_style == :wireframe - linewidth --> 2 - for points in get_plot_points(p, n = n) - @series begin - label := "" - points - end - end - elseif SSD_style == :surface - linewidth --> 0.2 - for mesh in get_plot_meshes(p, n = n) - @series begin - label := "" - mesh - end - end - end - end -end +# for p in pos +# if SSD_style == :wireframe +# linewidth --> 2 +# for points in get_plot_points(p, n = n) +# @series begin +# label := "" +# points +# end +# end +# elseif SSD_style == :surface +# linewidth --> 0.2 +# for mesh in get_plot_meshes(p, n = n) +# @series begin +# label := "" +# mesh +# end +# end +# end +# end +# end -@recipe function f(g::AbstractConstructiveGeometry{T}; SSD_style = :wireframe, n = 30) where {T} - seriescolor --> :orange +# @recipe function f(g::AbstractConstructiveGeometry{T}; SSD_style = :wireframe, n = 30) where {T} +# seriescolor --> :orange - @series begin - label --> "Geometry" - [] - end +# @series begin +# label --> "Geometry" +# [] +# end - if SSD_style == :wireframe #update to only plot real surfaces - pos, _ = get_decomposed_volumes(g) - for p in pos - linewidth --> 2 - for points in get_plot_points(p, n = n) - @series begin - label := "" - points - end - end - end - elseif SSD_style == :surface - linewidth --> 0.2 - for mesh in get_plot_meshes(g, n = n) - @series begin - label := "" - mesh - end - end - end -end +# if SSD_style == :wireframe #update to only plot real surfaces +# pos, _ = get_decomposed_volumes(g) +# for p in pos +# linewidth --> 2 +# for points in get_plot_points(p, n = n) +# @series begin +# label := "" +# points +# end +# end +# end +# elseif SSD_style == :surface +# linewidth --> 0.2 +# for mesh in get_plot_meshes(g, n = n) +# @series begin +# label := "" +# mesh +# end +# end +# end +# end -@recipe function f(ga::Array{<:AbstractSurfacePrimitive}; n = 30, seriescolor = missing) - ccolor = ismissing(seriescolor) ? [:blue] : seriescolor - if !(typeof(ccolor) <: AbstractArray) ccolor = [ccolor] end - for (cn,g) in enumerate(ga) - @series begin - seriescolor := ccolor[(cn-1)%length(ccolor)+1] - label := "" - mesh(g, n = n) - end - end -end +# @recipe function f(ga::Array{<:AbstractSurfacePrimitive}; n = 30, seriescolor = missing) +# ccolor = ismissing(seriescolor) ? [:blue] : seriescolor +# if !(typeof(ccolor) <: AbstractArray) ccolor = [ccolor] end +# for (cn,g) in enumerate(ga) +# @series begin +# seriescolor := ccolor[(cn-1)%length(ccolor)+1] +# label := "" +# mesh(g, n = n) +# end +# end +# end -@recipe function f(points::Vector{CartesianPoint{T}}) where {T} - map(p -> p.x, points), map(p -> p.y, points), map(p -> p.z, points) -end +# @recipe function f(points::Vector{CartesianPoint{T}}) where {T} +# map(p -> p.x, points), map(p -> p.y, points), map(p -> p.z, points) +# end -@recipe function f(points::Vector{CylindricalPoint{T}}) where {T} - points = CartesianPoint.(points) - map(p -> p.x, points), map(p -> p.y, points), map(p -> p.z, points) -end +# @recipe function f(points::Vector{CylindricalPoint{T}}) where {T} +# points = CartesianPoint.(points) +# map(p -> p.x, points), map(p -> p.y, points), map(p -> p.z, points) +# end From 3cfc543fc93ca8ed11a70d4a192da3def4763088 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 13:08:55 +0200 Subject: [PATCH 015/241] Restructure files of points and vectors --- .../ConstructiveSolidGeometry.jl | 2 +- .../Points.jl} | 50 ------------------- .../PointsAndVectors/PointsAndVectors.jl | 28 ++--------- .../PointsAndVectors/Vectors.jl | 48 ++++++++++++++++++ .../plotting/PointsAndVectors/Points.jl | 25 ++++++++++ .../PointsAndVectors/PointsAndVectors.jl | 4 +- 6 files changed, 82 insertions(+), 75 deletions(-) rename src/ConstructiveSolidGeometry/{PointsAndVectors.jl => PointsAndVectors/Points.jl} (73%) create mode 100644 src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index eb069d282..c302e43d7 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -43,7 +43,7 @@ module ConstructiveSolidGeometry abstract type AbstractTransformedGeometry{T} <: AbstractGeometry{T} end include("Units.jl") - include("PointsAndVectors.jl") + include("PointsAndVectors/PointsAndVectors.jl") include("GeometryRounding.jl") include("VolumePrimitives/VolumePrimitives.jl") include("LinePrimitives/LinePrimitives.jl") diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl similarity index 73% rename from src/ConstructiveSolidGeometry/PointsAndVectors.jl rename to src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl index 7e8740629..96871420f 100644 --- a/src/ConstructiveSolidGeometry/PointsAndVectors.jl +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl @@ -1,5 +1,3 @@ -abstract type AbstractCoordinatePoint{T, S} <: StaticArrays.FieldVector{3, T} end -abstract type AbstractCoordinateVector{T, S} <: StaticArrays.FieldVector{3, T} end abstract type AbstractPlanarPoint{T} <: StaticArrays.FieldVector{2, T} end abstract type AbstractPlanarVector{T} <: StaticArrays.FieldVector{2, T} end @@ -138,51 +136,3 @@ function _Δφ(φ1::T, φ2::T)::T where {T} end _φNear(φ::Real, φMin::T, φMax::T) where {T} = _Δφ(T(φ),φMin) ≤ _Δφ(T(φ),φMax) ? φMin : φMax - -struct PlanarVector{T} <: AbstractPlanarVector{T} - u::T - v::T -end - -""" - struct CartesianVector{T} <: AbstractCoordinateVector{T, Cartesian} - -* `x`: x-component in meter -* `y`: y-component in meter -* `z`: z-component in meter -""" -struct CartesianVector{T} <: AbstractCoordinateVector{T, Cartesian} - x::T - y::T - z::T -end - - -@inline rotate(p::CartesianPoint{T}, r::RotMatrix{3,T,TT}) where {T, TT} = r.mat * p -@inline rotate(p::CylindricalPoint{T}, r::RotMatrix{3,T,TT}) where {T, TT} = CylindricalPoint(rotate(CartesianPoint(p), r)) -@inline rotate!(vp::Vector{<:AbstractCoordinatePoint{T}}, r::RotMatrix{3,T,TT}) where {T, TT} = begin for i in eachindex(vp) vp[i] = rotate(vp[i], r) end; vp end -@inline rotate!(vvp::Vector{<:Vector{<:AbstractCoordinatePoint{T}}}, r::RotMatrix{3,T,TT}) where {T, TT} = begin for i in eachindex(vvp) rotate!(vvp[i], r) end; vvp end - -@inline scale(p::CartesianPoint{T}, v::SVector{3,T}) where {T} = p .* v -@inline scale(p::CylindricalPoint{T}, v::SVector{3,T}) where {T} = CylindricalPoint(scale(CartesianPoint(p),v)) -@inline scale!(vp::Vector{<:AbstractCoordinatePoint{T}}, v::SVector{3,T}) where {T} = begin for i in eachindex(vp) vp[i] = scale(vp[i], v) end; vp end -@inline scale!(vvp::Vector{<:Vector{<:AbstractCoordinatePoint{T}}}, v::SVector{3,T}) where {T} = begin for i in eachindex(vvp) scale!(vvp[i], v) end; vvp end - -@inline translate(p::CartesianPoint{T}, v::CartesianVector{T}) where {T} = p + v -@inline translate(p::CylindricalPoint{T}, v::CartesianVector{T}) where {T} = CylindricalPoint(translate(CartesianPoint(p), v)) -@inline translate!(vp::Vector{<:AbstractCoordinatePoint{T}}, v::CartesianVector{T}) where {T} = begin for i in eachindex(vp) vp[i] = translate(vp[i], v) end; vp end -@inline translate!(vvp::Vector{<:Vector{<:AbstractCoordinatePoint{T}}}, v::CartesianVector{T}) where {T} = begin for i in eachindex(vvp) translate!(vvp[i], v) end; vvp end - - -""" - struct CylindricalVector{T} <: AbstractCoordinateVector{T, Cylindrical} - -* `r`: Radius in meter -* `φ`: Polar angle in radians. φ == 0 <=> Parallel to x-axis of cartesian coordinate system." -* `z`: z-coordinate in meter -""" -struct CylindricalVector{T} <: AbstractCoordinateVector{T, Cylindrical} - r::T - φ::T - z::T -end diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors/PointsAndVectors.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/PointsAndVectors.jl index 941a85be1..a3ffde94d 100644 --- a/src/ConstructiveSolidGeometry/PointsAndVectors/PointsAndVectors.jl +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/PointsAndVectors.jl @@ -1,24 +1,6 @@ -@recipe function f(p::CylindricalPoint) - @series begin - CartesianPoint(p) - end -end -@recipe function f(p::CartesianPoint) - # st -> :scatter - @series begin - [p.x], [p.y], [p.z] - end -end -@recipe function f(v::AbstractVector{<:CartesianPoint}) - st -> :scatter - @series begin - [v[i].x for i in eachindex(v)], [v[i].y for i in eachindex(v)], [v[i].z for i in eachindex(v)] - end -end +abstract type AbstractCoordinatePoint{T, S} <: StaticArrays.FieldVector{3, T} end +abstract type AbstractCoordinateVector{T, S} <: StaticArrays.FieldVector{3, T} end -@recipe function f(v::AbstractVector{<:CylindricalPoint}) - st -> :scatter - @series begin - map(x->CartesianPoint(x),v) - end -end \ No newline at end of file + +include("Points.jl") +include("Vectors.jl") diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl new file mode 100644 index 000000000..89093b9ea --- /dev/null +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl @@ -0,0 +1,48 @@ + +struct PlanarVector{T} <: AbstractPlanarVector{T} + u::T + v::T +end + +""" + struct CartesianVector{T} <: AbstractCoordinateVector{T, Cartesian} + +* `x`: x-component in meter +* `y`: y-component in meter +* `z`: z-component in meter +""" +struct CartesianVector{T} <: AbstractCoordinateVector{T, Cartesian} + x::T + y::T + z::T +end + + +@inline rotate(p::CartesianPoint{T}, r::RotMatrix{3,T,TT}) where {T, TT} = r.mat * p +@inline rotate(p::CylindricalPoint{T}, r::RotMatrix{3,T,TT}) where {T, TT} = CylindricalPoint(rotate(CartesianPoint(p), r)) +@inline rotate!(vp::Vector{<:AbstractCoordinatePoint{T}}, r::RotMatrix{3,T,TT}) where {T, TT} = begin for i in eachindex(vp) vp[i] = rotate(vp[i], r) end; vp end +@inline rotate!(vvp::Vector{<:Vector{<:AbstractCoordinatePoint{T}}}, r::RotMatrix{3,T,TT}) where {T, TT} = begin for i in eachindex(vvp) rotate!(vvp[i], r) end; vvp end + +@inline scale(p::CartesianPoint{T}, v::SVector{3,T}) where {T} = p .* v +@inline scale(p::CylindricalPoint{T}, v::SVector{3,T}) where {T} = CylindricalPoint(scale(CartesianPoint(p),v)) +@inline scale!(vp::Vector{<:AbstractCoordinatePoint{T}}, v::SVector{3,T}) where {T} = begin for i in eachindex(vp) vp[i] = scale(vp[i], v) end; vp end +@inline scale!(vvp::Vector{<:Vector{<:AbstractCoordinatePoint{T}}}, v::SVector{3,T}) where {T} = begin for i in eachindex(vvp) scale!(vvp[i], v) end; vvp end + +@inline translate(p::CartesianPoint{T}, v::CartesianVector{T}) where {T} = p + v +@inline translate(p::CylindricalPoint{T}, v::CartesianVector{T}) where {T} = CylindricalPoint(translate(CartesianPoint(p), v)) +@inline translate!(vp::Vector{<:AbstractCoordinatePoint{T}}, v::CartesianVector{T}) where {T} = begin for i in eachindex(vp) vp[i] = translate(vp[i], v) end; vp end +@inline translate!(vvp::Vector{<:Vector{<:AbstractCoordinatePoint{T}}}, v::CartesianVector{T}) where {T} = begin for i in eachindex(vvp) translate!(vvp[i], v) end; vvp end + + +""" + struct CylindricalVector{T} <: AbstractCoordinateVector{T, Cylindrical} + +* `r`: Radius in meter +* `φ`: Polar angle in radians. φ == 0 <=> Parallel to x-axis of cartesian coordinate system." +* `z`: z-coordinate in meter +""" +struct CylindricalVector{T} <: AbstractCoordinateVector{T, Cylindrical} + r::T + φ::T + z::T +end diff --git a/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Points.jl b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Points.jl index e69de29bb..527e16f4c 100644 --- a/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Points.jl +++ b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Points.jl @@ -0,0 +1,25 @@ +@recipe function f(p::CartesianPoint) + @series begin + seriesstyle --> :scatter + [p.x], [p.y], [p.z] + end +end + +@recipe function f(p::CylindricalPoint) + @series begin + CartesianPoint(p) + end +end + +@recipe function f(v::AbstractVector{<:CartesianPoint}) + @series begin + seriesstyle --> :scatter + [v[i].x for i in eachindex(v)], [v[i].y for i in eachindex(v)], [v[i].z for i in eachindex(v)] + end +end + +@recipe function f(v::AbstractVector{<:CylindricalPoint}) + @series begin + map(x -> CartesianPoint(x), v) + end +end \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/PointsAndVectors.jl b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/PointsAndVectors.jl index fb40e1d59..798b8900a 100644 --- a/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/PointsAndVectors.jl +++ b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/PointsAndVectors.jl @@ -1,2 +1,4 @@ include("Points.jl") -include("Vectors.jl") \ No newline at end of file +include("Vectors.jl") + + From 8c80b794d538d4aae278ddc226ff6376f11b2886 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 13:16:18 +0200 Subject: [PATCH 016/241] Add plot seriesstyle `vector` and plot recipe for `CartesianVector` --- .../plotting/PointsAndVectors/Vectors.jl | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl index e69de29bb..846e515b0 100644 --- a/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl +++ b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl @@ -0,0 +1,31 @@ +@recipe function f(::Type{Val{:vector}}, x, y, z; + headlength = 0.05, headwidth = 0.02 ) + origin = x + vector = y + target = origin + vector + al = headlength + aw = headwidth + T = eltype(origin) + eX = CartesianVector{T}(1,0,0) + eY = CartesianVector{T}(0,1,0) + eZ = CartesianVector{T}(0,0,1) + apxl = target - al*vector - aw * normalize(vector × eX) + apxr = target - al*vector + aw * normalize(vector × eX) + apyl = target - al*vector - aw * normalize(vector × eY) + apyr = target - al*vector + aw * normalize(vector × eY) + apzl = target - al*vector - aw * normalize(vector × eZ) + apzr = target - al*vector + aw * normalize(vector × eZ) + + x := [origin[1], target[1], apxl[1], target[1], apxr[1], target[1], apyl[1], target[1], apyr[1], target[1], apzl[1], target[1], apzr[1]] + y := [origin[2], target[2], apxl[2], target[2], apxr[2], target[2], apyl[2], target[2], apyr[2], target[2], apzl[2], target[2], apzr[2]] + z := [origin[3], target[3], apxl[3], target[3], apxr[3], target[3], apyl[3], target[3], apyr[3], target[3], apzl[3], target[3], apzr[3]] + seriestype := :path3d + () +end + +@recipe function f(v::CartesianVector{T}) where {T} + @series begin + seriestype --> :vector + CartesianPoint{T}(0,0,0), v + end +end \ No newline at end of file From 2a9a17f6a2d736c10878fde76de8908ca9db954e Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 13:52:09 +0200 Subject: [PATCH 017/241] Add abstract types `ClosedPrimitive` and `OpenPrimitive` --- src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index c302e43d7..8251ba258 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -35,7 +35,10 @@ module ConstructiveSolidGeometry abstract type AbstractGeometry{T <: AbstractFloat} end abstract type AbstractPrimitive{T} <: AbstractGeometry{T} end - abstract type AbstractVolumePrimitive{T} <: AbstractPrimitive{T} end + abstract type ClosedPrimitive end + abstract type OpenPrimitive end + + abstract type AbstractVolumePrimitive{T, CO} <: AbstractPrimitive{T} end abstract type AbstractSurfacePrimitive{T} <: AbstractPrimitive{T} end abstract type AbstractLinePrimitive{T} <: AbstractPrimitive{T} end From 263fce53aa86aa647dd6c2daf79484b6d908bfb2 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 13:53:58 +0200 Subject: [PATCH 018/241] Add transformation of a point into the coordinate system of an object --- src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index 8251ba258..f898d7982 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -47,6 +47,12 @@ module ConstructiveSolidGeometry include("Units.jl") include("PointsAndVectors/PointsAndVectors.jl") + + _transform_into_object_coordinate_system(pt::CartesianPoint, p::AbstractVolumePrimitive) = inv(rotation(p)) * (pt - origin(p)) + in(pt::CartesianPoint, p::AbstractVolumePrimitive) = _in(_transform_into_object_coordinate_system(pt, p), p) + # Do we want to store the rotation matrix permanently in the primitive? + # We should do tests regarding the performance. It can be easily added later. + include("GeometryRounding.jl") include("VolumePrimitives/VolumePrimitives.jl") include("LinePrimitives/LinePrimitives.jl") From cf328b30709072d675dd6b8fa236481735157ea3 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 13:57:33 +0200 Subject: [PATCH 019/241] Add volume primitive `Box` --- .../VolumePrimitives/Box.jl | 108 ++++++------------ .../VolumePrimitives/VolumePrimitives.jl | 1 + 2 files changed, 33 insertions(+), 76 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 379f5432f..ae26dc40b 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -1,84 +1,40 @@ -struct Box{T,TX,TY,TZ} <: AbstractVolumePrimitive{T} - x::TX - y::TY - z::TZ - - function Box( ::Type{T}, - x::Union{T, <:AbstractInterval{T}}, - y::Union{T, <:AbstractInterval{T}}, - z::Union{T, <:AbstractInterval{T}}) where {T} - new{T,typeof(x),typeof(y),typeof(z)}(x, y, z) - end -end +""" + Box{T, CO} <: AbstractVolumePrimitive{T} -#Constructors -function Box(;xMin = -1, xMax = 1, yMin = -1, yMax = 1, zMin = -1, zMax = 1) - T = float(promote_type(typeof.((xMin, xMax, yMin, yMax, zMin, zMax))...)) - x = xMax == -xMin ? T(xMax) : T(xMin)..T(xMax) - y = yMax == -yMin ? T(yMax) : T(yMin)..T(yMax) - z = zMax == -zMin ? T(zMax) : T(zMin)..T(zMax) - Box( T, x, y, z) +T: Type of values, e.g. Float64 +CO: ClosedPrimitive or OpenPrimitive <-> whether surface belongs to it or not +""" +struct Box{T, CO} <: AbstractVolumePrimitive{T, CO} + hX::T + hY::T + hZ::T + origin::CartesianPoint{T} + rotation::SMatrix{3,3,T,9} end -Box(xMin, xMax, yMin, yMax, zMin, zMax) = Box(; xMin = xMin, xMax = xMax, yMin = yMin, yMax = yMax, zMin = zMin, zMax = zMax) -function Box(x::X, y::Y, z::Z) where {X<:Real, Y<:Real, Z<:Real} - T = float(promote_type(X,Y,Z)) - Box( T, T(x/2), T(y/2), T(z/2)) -end +Box{T, CO}(hX::Real, hY::Real, hZ::Real) where {T, CO<:Union{ClosedPrimitive, OpenPrimitive}} = + Box{T, CO}(T(hX), T(hY), T(hZ), CartesianPoint{T}(0,0,0), one(SMatrix{3, 3, T, 9})) +Box{T, CO}(hX::Real, hY::Real, hZ::Real, origin::CartesianPoint{T}) where {T, CO} = + Box{T, CO}(T(hX), T(hY), T(hZ), origin, one(SMatrix{3, 3, T, 9})) + +ClosedPrimitive(b::Box{T}) where {T} = Box{T, ClosedPrimitive}(b.hX, b.hY, b.hZ, b.origin, b.rotation) +OpenPrimitive(b::Box{T}) where {T} = Box{T, OpenPrimitive}(b.hX, b.hY, b.hZ, b.origin, b.rotation) -in(p::AbstractCoordinatePoint, b::Box) = - _in_x(p, b.x) && _in_y(p, b.y) && _in_z(p, b.z) - - -# read-in -function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::NamedTuple) where {T} - length_unit = input_units.length - x = parse_interval_of_primitive(T, "x", dict, length_unit) - y = parse_interval_of_primitive(T, "y", dict, length_unit) - z = parse_interval_of_primitive(T, "z", dict, length_unit) - return Box(T, x, y, z) -end +extremum(b::Box{T}) where {T} = norm(CartesianPoint{T}(b.hX, b.hY, b.hZ)) +rotation(p::AbstractVolumePrimitive) = p.rotation +origin(p::AbstractVolumePrimitive) = p.origin -function Dictionary(b::Box{T}) where {T} - dict = OrderedDict{String,Any}() - dict["x"] = typeof(b.x) == T ? b.x * 2 : OrderedDict{String,Any}("from" => b.x.left, "to" => b.x.right) - dict["y"] = typeof(b.y) == T ? b.y * 2 : OrderedDict{String,Any}("from" => b.y.left, "to" => b.y.right) - dict["z"] = typeof(b.z) == T ? b.z * 2 : OrderedDict{String,Any}("from" => b.z.left, "to" => b.z.right) - OrderedDict{String,Any}("box" => dict) -end +scale(b::Box{T, CO}, s::SVector{3, <:Any}) where {T, CO} = Box{T, CO}( b.hX * s[1], b.hY * s[2], b.hZ * s[3], b.origin, b.rotation ) +(*)(s::SVector{3, <:Any}, b::Box) = scale(b, s) -get_x_limits(b::Box{T}) where {T} = (_left_linear_interval(b.x), _right_linear_interval(b.x)) -get_y_limits(b::Box{T}) where {T} = (_left_linear_interval(b.y), _right_linear_interval(b.y)) -get_z_limits(b::Box{T}) where {T} = (_left_linear_interval(b.z), _right_linear_interval(b.z)) +translate(b::Box{T, CO}, v::CartesianVector) where {T, CO} = Box{T, CO}(b.hX, b.hY, b.hZ, b.origin + v, b.rotation) +(+)(b::Box, v::CartesianVector) = translate(b, v) -function get_decomposed_surfaces(b::Box{T}) where {T} - xMin::T, xMax::T = get_x_limits(b) - yMin::T, yMax::T = get_y_limits(b) - zMin::T, zMax::T = get_z_limits(b) - tol = geom_atol_zero(T) - if isapprox(xMin, xMax, atol = tol) - return AbstractSurfacePrimitive[RectangleX(b, xMin)] - elseif isapprox(yMin, yMax, atol = tol) - return AbstractSurfacePrimitive[RectangleY(b, yMin)] - elseif isapprox(zMin, zMax, atol = tol) - return AbstractSurfacePrimitive[RectangleZ(b, zMin)] - else - return AbstractSurfacePrimitive[ - RectangleX(b, xMin), RectangleX(b, xMax), - RectangleY(b, yMin), RectangleY(b, yMax), - RectangleZ(b, zMin), RectangleZ(b, zMax) - ] - end -end +rotate(b::Box{T, CO}, r::AbstractMatrix{T}) where {T, CO} = Box{T, CO}(b.hX, b.hY, b.hZ, r * b.origin, r * b.rotation) +# rotate_aroud_own_center(b::Box{T, CO}, r::AbstractMatrix{T}) where {T, CO} = Box{T, CO}(b.hX, b.hY, b.hZ, b.origin, r * b.rotation) +(*)(r::AbstractMatrix, b::Box) = rotate(b, r) -function sample(b::Box{T}, Nsamps::NTuple{3,Int} = (2,2,2)) where {T} - xMin::T, xMax::T = get_x_limits(b) - yMin::T, yMax::T = get_y_limits(b) - zMin::T, zMax::T = get_z_limits(b) - samples = [ - CartesianPoint{T}(x,y,z) - for x in (Nsamps[1] ≤ 1 ? xMin : range(xMin, xMax, length = Nsamps[1])) - for y in (Nsamps[2] ≤ 1 ? yMin : range(yMin, yMax, length = Nsamps[2])) - for z in (Nsamps[3] ≤ 1 ? zMin : range(zMin, zMax, length = Nsamps[3])) - ] -end +_in(pt::CartesianPoint, b::Box{<:Any, ClosedPrimitive}) = + abs(pt.x) <= b.hX && abs(pt.y) <= b.hY && abs(pt.z) <= b.hZ +_in(pt::CartesianPoint, b::Box{<:Any, :OpenPrimitive}) = + abs(pt.x) < b.hX && abs(pt.y) < b.hY && abs(pt.z) < b.hZ diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index e69de29bb..379ce3996 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -0,0 +1 @@ +include("Box.jl") \ No newline at end of file From 60731a1776850aabec1e5780709faece11fc8e0a Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 14:23:44 +0200 Subject: [PATCH 020/241] Add package Statistics.jl to the CSG submodule --- src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index f898d7982..1fa947300 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -12,7 +12,8 @@ module ConstructiveSolidGeometry using Rotations using StaticArrays using Unitful - + using Statistics + using DataStructures: OrderedDict import Base: in, *, +, -, &, size From 243f331a90cd51b0aee45a4bc2f204d9be5cacdd Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 14:24:24 +0200 Subject: [PATCH 021/241] Add from-Dict constructor for `Box` --- src/ConstructiveSolidGeometry/IO.jl | 2 +- .../VolumePrimitives/Box.jl | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 7b7990077..2ac910095 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -2,7 +2,7 @@ const CSG_dict = Dict{String, Any}( # "tube" => Cone, # "cone" => Cone, # "sphere" => Sphere, - # "box" => Box, + "box" => Box, # "torus" => Torus, # "TriangularPrism" => TriangularPrism, # "SquarePrism" => SquarePrism, diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index ae26dc40b..b76db6297 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -38,3 +38,38 @@ _in(pt::CartesianPoint, b::Box{<:Any, ClosedPrimitive}) = abs(pt.x) <= b.hX && abs(pt.y) <= b.hY && abs(pt.z) <= b.hZ _in(pt::CartesianPoint, b::Box{<:Any, :OpenPrimitive}) = abs(pt.x) < b.hX && abs(pt.y) < b.hY && abs(pt.z) < b.hZ + + + +function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::NamedTuple) where {T} + length_unit = input_units.length + x = parse_interval_of_primitive(T, "x", dict, length_unit) + y = parse_interval_of_primitive(T, "y", dict, length_unit) + z = parse_interval_of_primitive(T, "z", dict, length_unit) + μx = typeof(x) <: Real ? zero(T) : mean(x) + μy = typeof(y) <: Real ? zero(T) : mean(y) + μz = typeof(z) <: Real ? zero(T) : mean(z) + origin = CartesianPoint{T}(μx, μy, μz) + if haskey(dict, "translate") + origin += parse_translate_vector(T, dict["translate"], length_unit) + end + scale = SVector{3, T}(1, 1, 1) + if haskey(dict, "scale") + # scale = parse_translate_vector(T, dict["translate"], length_unit) + @info "Scale not yet implemented" + end + rot = if haskey(dict, "rotation") + parse_rotation_matrix(T, dict["rotate"], length_unit) + else + one(SMatrix{3, 3, T, 9}) + end + hX = typeof(x) <: Real ? x : width(x)/2 + hY = typeof(y) <: Real ? y : width(y)/2 + hZ = typeof(z) <: Real ? z : width(z)/2 + return Box{T, ClosedPrimitive}( + scale[1] * hX, + scale[2] * hY, + scale[3] * hZ, + origin, rot + ) +end From 1b53fe4901a3b39162367cc14ae464d91166a0b4 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 14:33:31 +0200 Subject: [PATCH 022/241] Add line primitive `Line` --- .../LinePrimitives/Line.jl | 65 ++----------------- .../LinePrimitives/LinePrimitives.jl | 1 + 2 files changed, 8 insertions(+), 58 deletions(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl index 3d6af5940..3cc9d1546 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl @@ -1,61 +1,10 @@ -struct Line{T,TP,TL} <: AbstractLinePrimitive{T} - p1::TP - p2::TP - linetype::TL - function Line( ::Type{T}, - p1::PT, - p2::PT, - linetype::Union{Val{:inf}, Val{:ray}, Val{:seg}} - ) where {T, PT <: Union{CartesianPoint{T}, PlanarPoint{T}}} - new{T,typeof(p1),typeof(linetype)}(p1, p2) - end +struct Line{T} <: AbstractLinePrimitive{T} + origin::CartesianPoint{T} + normal::CartesianVector{T} end -function LineSegment( ::Type{T}, - p1::PT, - p2::PT) where {T, PT <: Union{CartesianPoint{T}, PlanarPoint{T}}} #if LineSegment endpoints are p1, and p2 - Line(T, p1, p2, Val(:seg)) -end - -get_line_vector(l::Line{T,PlanarPoint{T}}) where {T} = normalize(PlanarVector{T}(l.p2 - l.p1)) -get_line_vector(l::Line{T,CartesianPoint{T}}) where {T} = normalize(CartesianVector{T}(l.p2 - l.p1)) - -function _distance_to_line(point::TP, l::Line{T, TP}) where {T, TP <: Union{PlanarPoint{T}, CartesianPoint{T}}} - v12 = get_line_vector(l) - v_point_1 = point - l.p1 - proj_on_v12 = dot(v12,v_point_1) - return v12, v_point_1, proj_on_v12 -end - -function distance_to_line(point::TP, l::Line{T, TP, Val{:inf}})::T where {T, TP <: Union{PlanarPoint{T}, CartesianPoint{T}}} - v12, v_point_1, proj_on_v12 = _distance_to_line(point, l) - return sqrt(abs(dot(v_point_1,v_point_1) - proj_on_v12^2)) -end - -function distance_to_line(point::TP, l::Line{T, TP, Val{:ray}})::T where {T, TP <: Union{PlanarPoint{T}, CartesianPoint{T}}} - v12, v_point_1, proj_on_v12 = _distance_to_line(point, l) - if proj_on_v12 ≤ T(0) - return norm(l.p1 - point) - else - v_point_2 = point - l.p2 - if dot(v12,v_point_2) ≥ T(0) - return norm(l.p2 - point) - else - return sqrt(abs(dot(v_point_1,v_point_1) - proj_on_v12^2)) - end - end -end - -function distance_to_line(point::TP, l::Line{T, TP, Val{:seg}})::T where {T, TP <: Union{PlanarPoint{T}, CartesianPoint{T}}} - v12, v_point_1, proj_on_v12 = _distance_to_line(point, l) - if proj_on_v12 ≤ T(0) - return norm(l.p1 - point) - else - v_point_2 = point - l.p2 - if dot(v12,v_point_2) ≥ T(0) - return norm(l.p2 - point) - else - return sqrt(abs(dot(v_point_1,v_point_1) - proj_on_v12^2)) - end - end +function distance(A::CartesianPoint, l::Line) + B = l.origin + C = B + l.normal + return norm((A - B) × (C - B)) / norm(C - B) end diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl b/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl index e69de29bb..8b3de045c 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl @@ -0,0 +1 @@ +include("Line.jl") \ No newline at end of file From 431ae1cc7e6a2347894718719513aadd9337a5af Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 14:34:32 +0200 Subject: [PATCH 023/241] Add Line primitive: Edge --- .../LinePrimitives/Edge.jl | 18 ++++++++++++++++++ .../LinePrimitives/LinePrimitives.jl | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl new file mode 100644 index 000000000..a4731e29b --- /dev/null +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl @@ -0,0 +1,18 @@ +struct Edge{T} <: AbstractLinePrimitive{T} + a::CartesianPoint{T} + b::CartesianPoint{T} +end + +direction(e::Edge) = e.b - e.a + +Line(e::Edge) = Line(e.a, direction(e)) + +function distance(pt::CartesianPoint{T}, e::Edge{T}) where {T} + return if (pt - e.b) ⋅ direction(e) >= 0 + norm(pt - e.b) + elseif (pt - e.a) ⋅ direction(e) <= 0 + norm(pt - e.a) + else + distance(pt, Line(e)) + end +end \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl b/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl index 8b3de045c..4130cb2a0 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl @@ -1 +1,2 @@ -include("Line.jl") \ No newline at end of file +include("Line.jl") +include("Edge.jl") \ No newline at end of file From 165a066616a3dcb04a52822a4e50fc2e0f761468 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 14:36:23 +0200 Subject: [PATCH 024/241] Add surface primitive: `Plane` --- .../SurfacePrimitives/Plane.jl | 184 +++--------------- .../SurfacePrimitives/SurfacePrimitives.jl | 1 + 2 files changed, 29 insertions(+), 156 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl index 98fe5aff5..fd7717604 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl @@ -1,168 +1,40 @@ -struct Plane{T,TP,TA} <: AbstractSurfacePrimitive{T} - p1::TP - p2::TP - p3::TP - p4::TA - function Plane( ::Type{T}, - p1::CartesianPoint{T}, - p2::CartesianPoint{T}, - p3::CartesianPoint{T}, - p4:: Union{Nothing, CartesianPoint{T}}) where {T} - new{T, CartesianPoint{T}, typeof(p4)}(p1, p2, p3, p4) - end -end +abstract type AbstractPlane{T} <: AbstractSurfacePrimitive{T} end -#Constructors -function Triangle(;p1 = CartesianPoint{Float32}(0,0,0), p2 = CartesianPoint{Float32}(1,0,0), p3 = CartesianPoint{Float32}(0,1,0)) - T = float(promote_type(eltype.((p1, p2, p3))...)) - Plane(T, p1, p2, p3, nothing) +struct Plane{T} <: AbstractPlane{T} + origin::CartesianPoint{T} + normal::CartesianVector{T} + Plane{T}(o, n) where {T} = new{T}(o, normalize(n)) end +Plane(origin::CartesianPoint{T}, normal::CartesianVector{T}) where {T} = Plane{T}(origin, normal) -Triangle(p1, p2, p3) = Triangle(;p1 = p1, p2 = p2, p3 = p3) - -get_vertices(tri::Plane{T, CartesianPoint{T}, Nothing}) where {T} = [tri.p1, tri.p2, tri.p3] +normal(p::Plane) = p.normal +origin(p::Plane) = p.origin -get_spanning_vectors(plane::Plane{T}) where {T} = (CartesianVector{T}(plane.p2 - plane.p1), CartesianVector{T}(plane.p3 - plane.p1)) - -function get_surface_vector(plane::Plane{T})::CartesianVector{T} where {T} - normalize(cross(get_spanning_vectors(plane)...)) -end +isinfront(pt::AbstractCoordinatePoint, p::Plane) = (pt - origin(p)) ⋅ normal(p) > 0 +isbehind(pt::AbstractCoordinatePoint, p::Plane) = (pt - origin(p)) ⋅ normal(p) < 0 +in(pt::AbstractCoordinatePoint, p::Plane) = (pt - origin(p)) ⋅ normal(p) == 0 -function get_surface_vector_nonunitary(plane::Plane{T})::CartesianVector{T} where {T} - cross(get_spanning_vectors(plane)...) -end +_distance(pt::AbstractCoordinatePoint, p::Plane) = (pt - origin(p)) ⋅ normal(p) +distance(pt::AbstractCoordinatePoint, p::Plane) = abs(_distance(pt, p)) -function distance_to_infinite_plane(point::CartesianPoint{T}, plane::Plane{T})::T where {T} - n::CartesianVector{T} = get_surface_vector(plane) - v = CartesianVector{T}(point - plane.p1) - geom_round(abs(dot(n,v))) -end -function on_infinite_plane(point::CartesianPoint{T}, plane::Plane{T})::Bool where {T} - distance_to_infinite_plane(point, plane) == T(0) +function evaluate(p::Plane{T}, x, y, ::Val{:xy}) where {T} + # plane.normal may not be perpendicular to the z-axis + line = Line{T}(CartesianPoint{T}(x, y, zero(T)), CartesianVector{T}(zero(T), zero(T), one(T))) + z = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ line.normal) + CartesianPoint{T}(x, y, z) end - -function get_planar_coordinates(point::CartesianPoint{T}, tri::Plane{T, CartesianPoint{T}, Nothing})::Tuple{T,T} where {T} - v1, v2 = get_spanning_vectors(tri) - v = CartesianVector{T}(point - tri.p1) - #equation to solve Ax = v where x is new 2D representation of plane. We solve by hitting it with A^T from right - A = hcat(v1,v2) - A_T = transpose(A) - x = inv(A_T*A)*(A_T*v) - x[1], x[2] +function evaluate(p::Plane{T}, x, z, ::Val{:xz}) where {T} + # plane.normal may not be perpendicular to the y-axis + line = Line{T}(CartesianPoint{T}(x, zero(T), z), CartesianVector{T}(zero(T), one(T), zero(T))) + y = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ line.normal) + CartesianPoint{T}(x, y, z) end - -function projection_in_triangle(point::CartesianPoint{T}, tri::Plane{T, CartesianPoint{T}, Nothing})::Bool where {T} - u, v = get_planar_coordinates(point, tri) - geom_round(u) ≥ T(0) && geom_round(v) ≥ T(0) && geom_round(u+v) ≤ T(1) +function evaluate(p::Plane{T}, y, z, ::Val{:yz}) where {T} + # plane.normal may not be perpendicular to the x-axis + line = Line{T}(CartesianPoint{T}(zero(T), y, z), CartesianVector{T}(one(T), zero(T), zero(T))) + x = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ line.normal) + CartesianPoint{T}(x, y, z) end -in(point::CartesianPoint{T}, tri::Plane{T, CartesianPoint{T}, Nothing}) where {T} = projection_in_triangle(point, tri) && on_infinite_plane(point, tri) -#Order of checks makes no difference in performance in all tested cases -function _distance_to_line_segment(point::CartesianPoint{T}, seg::Tuple{CartesianPoint{T},CartesianPoint{T}})::T where {T} - v12 = normalize(CartesianVector{T}(seg[2] - seg[1])) - v_point_1 = CartesianVector{T}(point - seg[1]) - proj_on_v12 = dot(v12,v_point_1) - if geom_round(proj_on_v12) ≤ T(0) - return norm(seg[1] - point) - else - v_point_2 = CartesianVector{T}(point - seg[2]) - if geom_round(dot(v12,v_point_2)) ≥ T(0) - return norm(seg[2] - point) - else - return sqrt(dot(v_point_1,v_point_1) - proj_on_v12^2) - end - end -end - -function distance_to_surface(point::CartesianPoint{T}, tri::Plane{T, CartesianPoint{T}, Nothing})::T where {T} - u, v = get_planar_coordinates(point, tri) - if geom_round(u) ≥ T(0) && geom_round(v) ≥ T(0) #++ quadrant. Origin is tri.p1 - if geom_round(u+v) ≤ T(1) #in triangle - return distance_to_infinite_plane(point, tri) - else # on side 2_3 of tri - return _distance_to_line_segment(point, (tri.p2,tri.p3)) - end - elseif geom_round(u) ≤ T(0) && geom_round(v) ≤ T(0) #-- quadrant - return norm(tri.p1 - point) - elseif geom_round(u) > T(0) && geom_round(v) < T(0) #+- quadrant, on side 1_2 of tri - return _distance_to_line_segment(point, (tri.p1,tri.p2)) - elseif geom_round(u) < T(0) && geom_round(v) > T(0) #-+ quadrant, on side 3_1 of tri - return _distance_to_line_segment(point, (tri.p3,tri.p1)) - end -end - -function sample(tri::Plane{T, CartesianPoint{T}, Nothing}, step::Real) where {T} - v1, v2 = get_spanning_vectors(tri) - step_u = step/norm(v1) - step_v = step/norm(v2) - samples = [ - CartesianPoint{T}(tri.p1 + u*v1 + v*v2) - for u in 0:step_u:1 - for v in 0:step_v:1-u - ] -end - -function sample(tri::Plane{T, CartesianPoint{T}, Nothing}, Nsamps::NTuple{3,Int}) where {T} - v1, v2 = get_spanning_vectors(tri) - samples = [ - CartesianPoint{T}(tri.p1 + u*v1 + v*v2) - for u in (Nsamps[1] ≤ 1 ? 0 : range(0, 1, length = Nsamps[1])) - for v in (Nsamps[2] ≤ 1 ? 0 : range(0, 1-u, length = Nsamps[2])) - ] -end - -function Quadrilateral(;p1 = CartesianPoint{Float32}(0,0,0), p2 = CartesianPoint{Float32}(1,0,0), p3 = CartesianPoint{Float32}(1,1,0), p4 = CartesianPoint{Float32}(0,1,0)) - T = float(promote_type(eltype.((p1, p2, p3))...)) - tri = Triangle(p1, p2, p3) - #will return triangle if conditions are not met - if geom_round(p4) in [geom_round(p1), geom_round(p2), geom_round(p3)] - return tri - else - if on_infinite_plane(p4, tri) - if !projection_in_triangle(p4, tri) - v = CartesianVector{T}(p4 - p1) - v2 = CartesianVector{T}(p3 - p1) - n = get_surface_vector_nonunitary(tri) - if geom_round(dot(n,cross(v2,v))) ≥ 0 - return Plane(T, p1, p2, p3, p4) - else - return tri - end - else - return Plane(T, p1, p2, p3, p4) - end - else - return tri - end - end -end - -Quadrilateral(p1, p2, p3, p4) = Quadrilateral(;p1 = p1, p2 = p2, p3 = p3, p4 = p4) -Plane(p1, p2, p3, p4) = Quadrilateral(;p1 = p1, p2 = p2, p3 = p3, p4 = p4) -Plane(p1, p2, p3) = Triangle(;p1 = p1, p2 = p2, p3 = p3) - -get_vertices(quad::Plane{T, CartesianPoint{T}, CartesianPoint{T}}) where {T} = [quad.p1, quad.p2, quad.p3, quad.p4] - - -function decompose_into_tiangles(quad::Plane{T, CartesianPoint{T}, CartesianPoint{T}})::Tuple{Plane{T, CartesianPoint{T}, Nothing},Plane{T, CartesianPoint{T}, Nothing}} where {T} - quad.p4 in Triangle(quad.p2,quad.p1,quad.p3) || quad.p2 in Triangle(quad.p4,quad.p1,quad.p3) ? (Triangle(quad.p1,quad.p2,quad.p4), Triangle(quad.p3,quad.p2,quad.p4)) : (Triangle(quad.p2,quad.p1,quad.p3), Triangle(quad.p4,quad.p1,quad.p3)) -end - - -function in(point::CartesianPoint{T}, quad::Plane{T, CartesianPoint{T}, CartesianPoint{T}})::Bool where {T} - tri1, tri2 = decompose_into_tiangles(quad) - point in tri1 || point in tri2 -end - -function distance_to_surface(point::CartesianPoint{T}, quad::Plane{T, CartesianPoint{T}, CartesianPoint{T}})::T where {T} - tri1, tri2 = decompose_into_tiangles(quad) - min(distance_to_surface(point, tri1), distance_to_surface(point, tri2)) -end - -function sample(quad::Plane{T, CartesianPoint{T}, CartesianPoint{T}}, sampling::Union{Real, NTuple{3,Int}}) where {T} - tri1, tri2 = decompose_into_tiangles(quad) - samples = sample(tri1, sampling) - append!(samples, sample(tri2, sampling)) -end diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl index e69de29bb..766f764e3 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl @@ -0,0 +1 @@ +include("Plane.jl") \ No newline at end of file From 7c06faafb6715bbb9c3a706f543e7ad71b316d0e Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 14:44:34 +0200 Subject: [PATCH 025/241] Add surface primitive `Polygon` --- .../SurfacePrimitives/Polygon.jl | 157 ++++++++++++++++++ .../SurfacePrimitives/SurfacePrimitives.jl | 3 +- 2 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl new file mode 100644 index 000000000..3773430cd --- /dev/null +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl @@ -0,0 +1,157 @@ + +struct Polygon{N,T} <: AbstractPlane{T} + points::SVector{N, CartesianPoint{T}} +end +const Triangle{T} = Polygon{3, T} +const Quadrangle{T} = Polygon{4, T} + +normal(p::Polygon) = normalize((p.points[2] - p.points[1]) × (p.points[3] - p.points[1])) + +vertices(p::Polygon) = p.points + + +function edges(p::Triangle{T}) where {T} + vs = vertices(p) + return SVector{3,Edge{T}}( + Edge(vs[1], vs[2]), + Edge(vs[2], vs[3]), + Edge(vs[3], vs[1]) + ) +end +function edges(p::Quadrangle{T}) where {T} + vs = vertices(p) + return SVector{4,Edge{T}}( + Edge(vs[1], vs[2]), + Edge(vs[2], vs[3]), + Edge(vs[3], vs[4]), + Edge(vs[4], vs[1]) + ) +end + +Plane(p::Polygon{N, T}) where {N, T} = Plane{T}(p.points[1], (p.points[2] - p.points[1]) × (p.points[3] - p.points[1])) + +function _get_rot_for_rotation_on_xy_plane(p::Polygon{<:Any, T}) where {T} + n = normal(p) + rot_angle_rad = CartesianVector{T}(0,0,1) ⋅ n + return if abs(rot_angle_rad) == 1 + RotationVec(zero(T), zero(T), zero(T)) + else + rot_angle = -acos(rot_angle_rad) + rot_axis = rot_angle * normalize(CartesianVector{T}(0,0,1) × n) + RotationVec(rot_axis[1], rot_axis[2], rot_axis[3]) + end +end + +function _rotate_on_xy_plane(p::Polygon{<:Any, T}) where {T} + rot = _get_rot_for_rotation_on_xy_plane(p) + map(pt -> rot * pt, p.points) +end + + +function in(pt::CartesianPoint{T}, p::Quadrangle{T}) where {T} + b::Bool = in(pt, Plane(p)) + if b + rot = _get_rot_for_rotation_on_xy_plane(p) + vs = vertices(p) + pts2d = SVector{5, SVector{2, T}}( + view(rot * vs[1], 1:2), + view(rot * vs[2], 1:2), + view(rot * vs[3], 1:2), + view(rot * vs[4], 1:2), + view(rot * vs[1], 1:2), + ) + # PolygonOps.inpolygon -> in = 1, on = -1, out = 0) + b = PolygonOps.inpolygon(view(rot * pt, 1:2), pts2d) != 0 + end + return b +end + +function _above_or_below_polygon(pt::AbstractCoordinatePoint, p::Quadrangle{T}) where {T} + rot = _get_rot_for_rotation_on_xy_plane(p) + vs = vertices(p) + pts2d = SVector{5, SVector{2, T}}( + view(rot * vs[1], 1:2), + view(rot * vs[2], 1:2), + view(rot * vs[3], 1:2), + view(rot * vs[4], 1:2), + view(rot * vs[1], 1:2), + ) + # PolygonOps.inpolygon -> in = 1, on = -1, out = 0) + return PolygonOps.inpolygon(view(rot * pt, 1:2), pts2d) != 0 +end + +function distance(pt::CartesianPoint, p::Polygon) + return if _above_or_below_polygon(pt, p) + distance(pt, Plane(p)) + else + es = edges(p) + ds = map(e -> distance(pt, e), es) + minimum(ds) + end +end + +function _filter_points(pts::AbstractArray, p::Quadrangle{T}) where {T} + # this functions assume that the points, pts, all lie in the plane of the Quadrangle, p + rot = _get_rot_for_rotation_on_xy_plane(p) + vs = vertices(p) + pts2d = SVector{5, SVector{2, T}}( + view(rot * vs[1], 1:2), + view(rot * vs[2], 1:2), + view(rot * vs[3], 1:2), + view(rot * vs[4], 1:2), + view(rot * vs[1], 1:2), + ) + # PolygonOps.inpolygon -> in = 1, on = -1, out = 0) + filter(pt -> PolygonOps.inpolygon(view(rot * pt, 1:2), pts2d) != 0, pts) +end + +function get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CartesianTicksTuple{T}) where {N, T} + # This method would actually work for any flat surface, e.g. elipse + xs, ys, zs = getindex.(p.points, 1), getindex.(p.points, 2), getindex.(p.points, 3) + xmin_idx = searchsortedfirst(t[1], minimum(xs)) + ymin_idx = searchsortedfirst(t[2], minimum(ys)) + zmin_idx = searchsortedfirst(t[3], minimum(zs)) + xmax_idx = searchsortedfirst(t[1], maximum(xs)) + ymax_idx = searchsortedfirst(t[2], maximum(ys)) + zmax_idx = searchsortedfirst(t[3], maximum(zs)) + ls = (length(t[1]), length(t[2]), length(t[3])) + if xmax_idx > ls[1] zmax_idx = ls[1] end + if ymax_idx > ls[2] zmax_idx = ls[2] end + if zmax_idx > ls[3] zmax_idx = ls[3] end + t_idx_range_x = xmin_idx:xmax_idx + t_idx_range_y = ymin_idx:ymax_idx + t_idx_range_z = zmin_idx:zmax_idx + ls = (length(t_idx_range_x), length(t_idx_range_y), length(t_idx_range_z)) + ls = ( + ls[1] == 1 ? typemax(eltype(ls)) : ls[1], + ls[2] == 1 ? typemax(eltype(ls)) : ls[2], + ls[3] == 1 ? typemax(eltype(ls)) : ls[3] + ) + n = normal(p) + proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && + (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) + Val{:xy}(), t_idx_range_x, t_idx_range_y + elseif ls[1] < ls[2] && ls[3] < ls[2] && + (n ⋅ CartesianVector{T}(zero(T),one(T),zero(T)) != 0) + Val{:xz}(), t_idx_range_x, t_idx_range_z + elseif n ⋅ CartesianVector{T}(one(T),zero(T), zero(T)) != 0 + Val{:yz}(), t_idx_range_y, t_idx_range_z + else + error("Sampling Error. Have to extend cases") + end + return t1, t2, proj +end + + +function sample(p::Polygon{N, T}, t::CartesianTicksTuple{T}) where {N, T} + plane = Plane(p) + t1, t2, proj = get_2d_grid_ticks_and_proj(p, t) + samples = Array{CartesianPoint{T}}(undef, length(t1), length(t2)) + for j in eachindex(t2) + for i in eachindex(t1) + samples[i, j] = evaluate(plane, t1[i], t2[j], proj) + end + end + _filter_points(Base.ReshapedArray(samples, (length(samples),), ()), p) +end + diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl index 766f764e3..f64e7a6a5 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl @@ -1 +1,2 @@ -include("Plane.jl") \ No newline at end of file +include("Plane.jl") +include("Polygon.jl") \ No newline at end of file From d1a0340e5cc7d62351a6dd89ba71319c85df0252 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 14:46:31 +0200 Subject: [PATCH 026/241] Add `vertices` function for `Box` # Conflicts: # src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl --- .../VolumePrimitives/Box.jl | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index b76db6297..ed6131abd 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -38,9 +38,7 @@ _in(pt::CartesianPoint, b::Box{<:Any, ClosedPrimitive}) = abs(pt.x) <= b.hX && abs(pt.y) <= b.hY && abs(pt.z) <= b.hZ _in(pt::CartesianPoint, b::Box{<:Any, :OpenPrimitive}) = abs(pt.x) < b.hX && abs(pt.y) < b.hY && abs(pt.z) < b.hZ - - - + function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::NamedTuple) where {T} length_unit = input_units.length x = parse_interval_of_primitive(T, "x", dict, length_unit) @@ -73,3 +71,18 @@ function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::Named origin, rot ) end + +function vertices(b::Box{T}) where {T} + return SVector{8, CartesianPoint{T}}( + b.rotation * SVector{3,T}(-b.hX, -b.hY, -b.hZ) .+ b.origin, + b.rotation * SVector{3,T}(+b.hX, -b.hY, -b.hZ) .+ b.origin, + b.rotation * SVector{3,T}(+b.hX, +b.hY, -b.hZ) .+ b.origin, + b.rotation * SVector{3,T}(-b.hX, +b.hY, -b.hZ) .+ b.origin, + b.rotation * SVector{3,T}(-b.hX, -b.hY, +b.hZ) .+ b.origin, + b.rotation * SVector{3,T}(+b.hX, -b.hY, +b.hZ) .+ b.origin, + b.rotation * SVector{3,T}(+b.hX, +b.hY, +b.hZ) .+ b.origin, + b.rotation * SVector{3,T}(-b.hX, +b.hY, +b.hZ) .+ b.origin, + ) +end + +sample(b::Box) = vertices(b) From eec274657f1b7378b01c5c68c97d074e28856918 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 15:06:22 +0200 Subject: [PATCH 027/241] Remove file `Decompose.jl` --- .../ConstructiveSolidGeometry.jl | 1 - src/ConstructiveSolidGeometry/Decompose.jl | 56 ------------------- src/SolidStateDetectors.jl | 3 +- 3 files changed, 1 insertion(+), 59 deletions(-) delete mode 100644 src/ConstructiveSolidGeometry/Decompose.jl diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index 1fa947300..4fcb47373 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -62,7 +62,6 @@ module ConstructiveSolidGeometry include("Intervals.jl") include("CSG.jl") include("IO.jl") - include("Decompose.jl") include("Sampling.jl") # Plotting diff --git a/src/ConstructiveSolidGeometry/Decompose.jl b/src/ConstructiveSolidGeometry/Decompose.jl deleted file mode 100644 index fc6c2eddf..000000000 --- a/src/ConstructiveSolidGeometry/Decompose.jl +++ /dev/null @@ -1,56 +0,0 @@ -function get_decomposed_volumes(vol::AbstractGeometry{T})::Tuple{Vector{<:AbstractGeometry},Vector{<:AbstractGeometry}} where {T} - positive_volumes = AbstractGeometry[] - negative_volumes = AbstractGeometry[] - transformation = CSGTransformation[] - decompose!(positive_volumes, negative_volumes, vol, transformation, Val{:PositiveVolume}, AbstractVolumePrimitive) - positive_volumes, negative_volumes -end - -function get_decomposed_surfaces(vol::AbstractGeometry{T})::Vector{<:AbstractGeometry} where {T} - positive_surfaces = AbstractGeometry[] - negative_surfaces = AbstractGeometry[] - transformation = CSGTransformation[] - decompose!(positive_surfaces, negative_surfaces, vol, transformation, Val{:PositiveVolume}, AbstractSurfacePrimitive) - positive_surfaces -end - -@inline invert_volume_type(::Type{Val{:PositiveVolume}}) = Val{:NegativeVolume} -@inline invert_volume_type(::Type{Val{:NegativeVolume}}) = Val{:PositiveVolume} - -function decompose!(pos, neg, vol::CSGDifference, transformation, ::Type{VT}, ::Type{P})::Nothing where {VT <:Union{Val{:PositiveVolume}, Val{:NegativeVolume}}, P <: Union{AbstractVolumePrimitive, AbstractSurfacePrimitive}} - decompose!(pos, neg, vol.a, transformation, VT, P) - decompose!(pos, neg, vol.b, transformation, invert_volume_type(VT), P) - nothing -end - -function decompose!(pos, neg, vol::Union{CSGUnion, CSGIntersection}, transformation, ::Type{VT}, ::Type{P})::Nothing where {VT <:Union{Val{:PositiveVolume}, Val{:NegativeVolume}}, P <: Union{AbstractVolumePrimitive, AbstractSurfacePrimitive}} - decompose!(pos, neg, vol.a, transformation, VT, P) - decompose!(pos, neg, vol.b, transformation, VT, P) - nothing -end - -function decompose!(pos, neg, vol::TranslatedGeometry, transformation, ::Type{VT}, ::Type{P})::Nothing where {VT <:Union{Val{:PositiveVolume}, Val{:NegativeVolume}}, P <: Union{AbstractVolumePrimitive, AbstractSurfacePrimitive}} - push!(transformation, vol.t) - decompose!(pos, neg, vol.p, transformation, VT, P) - pop!(transformation) - nothing -end - -function decompose!(pos, neg, vol::RotatedGeometry, transformation, ::Type{VT}, ::Type{P})::Nothing where {VT <:Union{Val{:PositiveVolume}, Val{:NegativeVolume}}, P <: Union{AbstractVolumePrimitive, AbstractSurfacePrimitive}} - push!(transformation, inv(vol.inv_r)) - decompose!(pos, neg, vol.p, transformation, VT, P) - pop!(transformation) - nothing -end - -function decompose!(pos, neg, vol::ScaledGeometry, transformation, ::Type{VT}, ::Type{P})::Nothing where {VT <:Union{Val{:PositiveVolume}, Val{:NegativeVolume}}, P <: Union{AbstractVolumePrimitive, AbstractSurfacePrimitive}} - push!(transformation, inv.(vol.inv_s)) - decompose!(pos, neg, vol.p, transformation, VT, P) - pop!(transformation) - nothing -end - -decompose!(pos, neg, vol::AbstractVolumePrimitive, transformation, ::Type{Val{:PositiveVolume}}, ::Type{AbstractVolumePrimitive}) = push!(pos, transform(vol, transformation)) -decompose!(pos, neg, vol::AbstractVolumePrimitive, transformation, ::Type{Val{:NegativeVolume}}, ::Type{AbstractVolumePrimitive}) = push!(neg, transform(vol, transformation)) -decompose!(pos, neg, vol::AbstractVolumePrimitive, transformation, ::Type{Val{:PositiveVolume}}, ::Type{AbstractSurfacePrimitive}) = append!(pos, broadcast(surf -> transform(surf, transformation), get_decomposed_surfaces(vol))) -#decompose!(pos, neg, surf::AbstractSurfacePrimitive, transformation, ::Type{Val{:PositiveVolume}}) = push!(pos, surf) diff --git a/src/SolidStateDetectors.jl b/src/SolidStateDetectors.jl index 2431a9a76..a1c6d6298 100644 --- a/src/SolidStateDetectors.jl +++ b/src/SolidStateDetectors.jl @@ -34,8 +34,7 @@ using .ConstructiveSolidGeometry: Cartesian, Cylindrical, AbstractCoordinateSystem, CoordinateSystemType, CartesianTicksTuple, CylindricalTicksTuple, Geometry, AbstractGeometry, - get_decomposed_volumes, - get_decomposed_surfaces, AbstractSurfacePrimitive, + AbstractSurfacePrimitive, geom_round, geom_sigdigits, geom_atol_zero, parse_rotation_matrix, parse_translate_vector, parse_CSG_transformation, CSGTransformation, transform, CSG_dict From c95c8fba47e6ceaf5cbacaaf2f353b013c0daa89 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 15:07:43 +0200 Subject: [PATCH 028/241] Add `faces` function for `Box` --- .../VolumePrimitives/Box.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index ed6131abd..14f874e8d 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -86,3 +86,15 @@ function vertices(b::Box{T}) where {T} end sample(b::Box) = vertices(b) + +function faces(b::Box{T}) where {T} + vs = vertices(b) + return SVector{6, Quadrangle{T}}( + Quadrangle{T}((vs[1], vs[2], vs[3], vs[4])), + Quadrangle{T}((vs[5], vs[6], vs[2], vs[1])), + Quadrangle{T}((vs[8], vs[7], vs[6], vs[5])), + Quadrangle{T}((vs[6], vs[7], vs[3], vs[2])), + Quadrangle{T}((vs[7], vs[8], vs[4], vs[3])), + Quadrangle{T}((vs[8], vs[5], vs[1], vs[4])), + ) +end From 5c961ed945ddb70c893d8eb18cd8e6846e62432f Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 15:08:21 +0200 Subject: [PATCH 029/241] Add `distance` function for `Box` --- src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 14f874e8d..07c554bf0 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -98,3 +98,8 @@ function faces(b::Box{T}) where {T} Quadrangle{T}((vs[8], vs[5], vs[1], vs[4])), ) end + +function distance(b::Box{T}, pt::CartesianPoint{T}) where {T} + planes = Plane.(faces(b)) + minimum(map(p -> distance(p, pt), planes)) +end From f5cad4390db0e7823792bcb0b95c4d113d04c249 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 15:09:54 +0200 Subject: [PATCH 030/241] Add constructor for `CartesianTicksTuple` --- src/Grids/Grids.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Grids/Grids.jl b/src/Grids/Grids.jl index ba29ccc1a..9c963f4c7 100644 --- a/src/Grids/Grids.jl +++ b/src/Grids/Grids.jl @@ -113,6 +113,7 @@ function get_boundary_types(grid::Grid{T, N, S}) where {T, N, S} return get_boundary_types.(grid.axes) end +CartesianTicksTuple(g::Grid{T, 3, Cartesian}) where {T} = (x = g.axes[1].ticks, y = g.axes[2].ticks, z = g.axes[3].ticks) function Grid(nt::NamedTuple) if nt.coordtype == "cylindrical" From 3f5c8d86301926424fe67a326f0505ceb76abfb2 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 15:11:24 +0200 Subject: [PATCH 031/241] Add paint function for `Polygon` --- src/SolidStateDetector/DetectorGeometries.jl | 34 ++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/SolidStateDetector/DetectorGeometries.jl b/src/SolidStateDetector/DetectorGeometries.jl index 438a8d8be..a82647852 100644 --- a/src/SolidStateDetector/DetectorGeometries.jl +++ b/src/SolidStateDetector/DetectorGeometries.jl @@ -416,6 +416,40 @@ function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, p nothing end +function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, geometry, pot_value, grid) + ticks = CartesianTicksTuple(grid) + t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) + t1, t2 = if proj == Val{:xy}() + ticks[1], ticks[2] + elseif proj == Val{:xz}() + ticks[1], ticks[3] + else + ticks[2], ticks[3] + end + plane = ConstructiveSolidGeometry.Plane(face) + for i2 in t_idx_r2 + for i1 in t_idx_r1 + pt = ConstructiveSolidGeometry.evaluate(plane, t1[i1], t2[i2], proj) + if pt in geometry + if proj == Val{:xy}() + i3 = searchsortednearest(ticks[3], pt[3]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value + elseif proj == Val{:xz}() + i3 = searchsortednearest(ticks[2], pt[2]) + pointtypes[i1, i3, i2] = zero(PointType) + potential[i1, i3, i2] = pot_value + else + i3 = searchsortednearest(ticks[1], pt[1]) + pointtypes[i3, i1, i2] = zero(PointType) + potential[i3, i1, i2] = pot_value + end + end + end + end + nothing +end + function json_to_dict(inputfile::String)::Dict parsed_json_file = Dict() open(inputfile,"r") do f From df7902867aee5fb4f92d88f61bee558032154a8d Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 15:12:23 +0200 Subject: [PATCH 032/241] Enable painting of contacts again. Now, without sampling. --- src/SolidStateDetector/DetectorGeometries.jl | 56 +++++++++++--------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/src/SolidStateDetector/DetectorGeometries.jl b/src/SolidStateDetector/DetectorGeometries.jl index a82647852..ab84b9b5f 100644 --- a/src/SolidStateDetector/DetectorGeometries.jl +++ b/src/SolidStateDetector/DetectorGeometries.jl @@ -337,18 +337,22 @@ function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, p end end - # for contact in ssd.contacts - # pot::T = if ismissing(weighting_potential_contact_id) - # contact.potential - # else - # contact.id == weighting_potential_contact_id ? 1 : 0 - # end - # contact_gridpoints = paint_object(contact, grid) - # for gridpoint in contact_gridpoints - # potential[ gridpoint... ] = pot - # pointtypes[ gridpoint... ] = zero(PointType) - # end - # end + for contact in ssd.contacts + pot::T = if ismissing(weighting_potential_contact_id) + contact.potential + else + contact.id == weighting_potential_contact_id ? 1 : 0 + end + # contact_gridpoints = paint_object(contact, grid) + # for gridpoint in contact_gridpoints + # potential[ gridpoint... ] = pot + # pointtypes[ gridpoint... ] = zero(PointType) + # end + fs = ConstructiveSolidGeometry.faces(contact.geometry) + for face in fs + paint!(pointtypes, potential, face, contact.geometry, pot, grid) + end + end nothing end @@ -401,18 +405,22 @@ function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, p end end end - # for contact in ssd.contacts - # pot::T = if ismissing(weighting_potential_contact_id) - # contact.potential - # else - # contact.id == weighting_potential_contact_id ? 1 : 0 - # end - # contact_gridpoints = paint_object(contact, grid) - # for gridpoint in contact_gridpoints - # potential[ gridpoint... ] = pot - # pointtypes[ gridpoint... ] = zero(PointType) - # end - # end + for contact in ssd.contacts + pot::T = if ismissing(weighting_potential_contact_id) + contact.potential + else + contact.id == weighting_potential_contact_id ? 1 : 0 + end + # contact_gridpoints = paint_object(contact, grid) + # for gridpoint in contact_gridpoints + # potential[ gridpoint... ] = pot + # pointtypes[ gridpoint... ] = zero(PointType) + # end + fs = ConstructiveSolidGeometry.faces(contact.geometry) + for face in fs + paint!(pointtypes, potential, face, contact.geometry, pot, grid) + end + end nothing end From 272bce9c320ba23a1293b6a7b34bea3848926a3a Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 15:46:25 +0200 Subject: [PATCH 033/241] Fix scaling of `Box` --- src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl | 2 ++ src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl index 96871420f..8dc4e7209 100644 --- a/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl @@ -20,6 +20,8 @@ struct CartesianPoint{T} <: AbstractCoordinatePoint{T, Cartesian} z::T end +scale(pt::CartesianPoint{T}, s::SVector{3}) where {T} = CartesianPoint{T}(pt.x * s[1], pt.y * s[2], pt.z * s[3]) + @inline _eq_cyl_r(p::CartesianPoint{T}, r::Real) where {T} = hypot(p.x, p.y) == T(r) @inline _in_planar_r(p::PlanarPoint, r::Real) = hypot(p.u, p.v) <= r diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 07c554bf0..d947e4641 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -24,7 +24,7 @@ extremum(b::Box{T}) where {T} = norm(CartesianPoint{T}(b.hX, b.hY, b.hZ)) rotation(p::AbstractVolumePrimitive) = p.rotation origin(p::AbstractVolumePrimitive) = p.origin -scale(b::Box{T, CO}, s::SVector{3, <:Any}) where {T, CO} = Box{T, CO}( b.hX * s[1], b.hY * s[2], b.hZ * s[3], b.origin, b.rotation ) +scale(b::Box{T, CO}, s::SVector{3, <:Any}) where {T, CO} = Box{T, CO}( b.hX * s[1], b.hY * s[2], b.hZ * s[3], scale(b.origin, s), b.rotation ) (*)(s::SVector{3, <:Any}, b::Box) = scale(b, s) translate(b::Box{T, CO}, v::CartesianVector) where {T, CO} = Box{T, CO}(b.hX, b.hY, b.hZ, b.origin + v, b.rotation) From e59c3248179c4801a8663d112ebec7d890703b8a Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 15:47:13 +0200 Subject: [PATCH 034/241] Refactor transformations: only enable translation --- src/ConstructiveSolidGeometry/CSG.jl | 10 +++ .../ConstructiveSolidGeometry.jl | 1 - src/ConstructiveSolidGeometry/IO.jl | 63 ++++++++-------- .../Transformations.jl | 75 ++----------------- src/SolidStateDetector/Contacts.jl | 2 +- src/SolidStateDetector/Passive.jl | 2 +- src/SolidStateDetector/Semiconductor.jl | 2 +- src/SolidStateDetector/SolidStateDetector.jl | 19 ++--- src/SolidStateDetector/TransitionLayer.jl | 4 +- src/SolidStateDetectors.jl | 2 +- 10 files changed, 66 insertions(+), 114 deletions(-) diff --git a/src/ConstructiveSolidGeometry/CSG.jl b/src/ConstructiveSolidGeometry/CSG.jl index 3cfe94992..8ae386bd0 100644 --- a/src/ConstructiveSolidGeometry/CSG.jl +++ b/src/ConstructiveSolidGeometry/CSG.jl @@ -64,3 +64,13 @@ end Dictionary(g::CSGDifference{T}) where {T} = OrderedDict{String,Any}("difference" => OrderedDict[Dictionary(g.a), Dictionary(g.b)]) Geometry(::Type{T}, CSG::Type{<:AbstractConstructiveGeometry}, v::Vector{Any}, input_units::NamedTuple) where {T} = Geometry(T, CSG, [g for g in v], input_units) + +(+)(csg::A, v::CartesianVector) where {A <: AbstractConstructiveGeometry} = A(csg.a + v, csg.b + v) + +(*)(r::AbstractMatrix, csg::A) where {A <: AbstractConstructiveGeometry} = A(r * csg.a, r * csg.b) + +scale(csg::A, s::SVector{3}) where {A <: AbstractConstructiveGeometry} = A(scale(csg.a, s), scale(csg.b, s)) +(*)(s::SVector{3}, csg::A) where {A <: AbstractConstructiveGeometry} = A(scale(csg.a, s), scale(csg.b, s)) +(*)(csg::A, s::SVector{3}) where {A <: AbstractConstructiveGeometry} = A(scale(csg.a, s), scale(csg.b, s)) + +faces(csg::AbstractConstructiveGeometry) = vcat(faces(csg.a)..., faces(csg.b)...) \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index 4fcb47373..7308eb15f 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -44,7 +44,6 @@ module ConstructiveSolidGeometry abstract type AbstractLinePrimitive{T} <: AbstractPrimitive{T} end abstract type AbstractConstructiveGeometry{T} <: AbstractGeometry{T} end - abstract type AbstractTransformedGeometry{T} <: AbstractGeometry{T} end include("Units.jl") include("PointsAndVectors/PointsAndVectors.jl") diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 2ac910095..8703fdc4e 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -11,12 +11,12 @@ const CSG_dict = Dict{String, Any}( # "union" => CSGUnion, # "difference" => CSGDifference, # "intersection" => CSGIntersection, - # "translate" => TranslatedGeometry, + "translate" => CartesianVector, # "rotate" => RotatedGeometry, # "scale" => ScaledGeometry ) -function get_geometry_key(::Type{T}, dict::AbstractDict, input_units::NamedTuple)::Tuple{String, Vector{CSGTransformation}} where {T} +function get_geometry_key(::Type{T}, dict::AbstractDict, input_units::NamedTuple) where {T} dict_keys = filter(k -> k in keys(CSG_dict), keys(dict)) transformations = sort!(filter(k -> (k == "translate" && !any(broadcast(key -> key in keys(CSG_dict), keys(dict["translate"])))) || @@ -26,7 +26,8 @@ function get_geometry_key(::Type{T}, dict::AbstractDict, input_units::NamedTuple primitives = setdiff(dict_keys, transformations) @assert length(primitives) <= 1 "Too many geometry entries in dictionary: $(length(dict_keys))." @assert length(primitives) >= 1 "None of the entries $(keys(dict)) describes a Geometry." - first(primitives), broadcast(t -> parse_CSG_transformation(T, dict, CSG_dict[t], input_units), transformations) + transformations = broadcast(t -> parse_CSG_transformation(T, dict, CSG_dict[t], input_units), transformations) + first(primitives), isempty(transformations) ? missing : transformations end @@ -134,16 +135,16 @@ function parse_translate_vector(::Type{T}, dict::AbstractDict, unit::Unitful.Uni CartesianVector{T}(x,y,z) end -function parse_CSG_transformation(::Type{T}, dict::AbstractDict, ::Type{TranslatedGeometry}, input_units::NamedTuple)::CSGTransformation where {T} +function parse_CSG_transformation(::Type{T}, dict::AbstractDict, ::Type{CartesianVector}, input_units::NamedTuple) where {T} parse_translate_vector(T, dict["translate"], input_units.length) end -function Geometry(::Type{T}, ::Type{TranslatedGeometry}, dict::AbstractDict, input_units::NamedTuple) where {T} - length_unit = input_units.length - translate_vector::CartesianVector{T} = parse_translate_vector(T, dict, length_unit) - key::String, transformations::Vector{CSGTransformation} = get_geometry_key(T, dict, input_units) - translate(transform(Geometry(T, CSG_dict[key], dict[key], input_units), transformations), translate_vector) -end +# function Geometry(::Type{T}, ::Type{CartesianVector}, dict::AbstractDict, input_units::NamedTuple) where {T} +# length_unit = input_units.length +# translate_vector::CartesianVector{T} = parse_translate_vector(T, dict, length_unit) +# key::String, transformations = get_geometry_key(T, dict, input_units) +# translate(transform(Geometry(T, CSG_dict[key], dict[key], input_units), transformations), translate_vector) +# end function parse_scale_vector(::Type{T}, dict::AbstractDict, unit::Unitful.Units)::SVector{3,T} where {T} x::T = haskey(dict, "x") ? _parse_value(T, dict["x"], unit) : T(1) @@ -152,12 +153,12 @@ function parse_scale_vector(::Type{T}, dict::AbstractDict, unit::Unitful.Units): SVector{3,T}(x,y,z) end -function Geometry(::Type{T}, ::Type{ScaledGeometry}, dict::AbstractDict, input_units::NamedTuple) where {T} - length_unit = input_units.length - scale_vector::SVector{3,T} = parse_scale_vector(T, dict, length_unit) - key::String, transformations::Vector{CSGTransformation} = get_geometry_key(T, dict, input_units) - scale(transform(Geometry(T, CSG_dict[key], dict[key], input_units), transformations), scale_vector) -end +# function Geometry(::Type{T}, ::Type{ScaledGeometry}, dict::AbstractDict, input_units::NamedTuple) where {T} +# length_unit = input_units.length +# scale_vector::SVector{3,T} = parse_scale_vector(T, dict, length_unit) +# key::String, transformations = get_geometry_key(T, dict, input_units) +# scale(transform(Geometry(T, CSG_dict[key], dict[key], input_units), transformations), scale_vector) +# end _rot_keys = ["X","Y","Z","XY","XZ","YX","YZ","ZX","ZY","XYX","XYZ","XZX","XZY","YXY","YXZ","YZX","YZY","ZXY","ZXZ","ZYX","ZYZ"] function parse_rotation_matrix(::Type{T}, dict::AbstractDict, unit::Unitful.Units)::RotMatrix3{T} where {T} @@ -175,20 +176,20 @@ function parse_rotation_matrix(::Type{T}, dict::AbstractDict, unit::Unitful.Unit end end -function parse_CSG_transformation(::Type{T}, dict::AbstractDict, ::Type{RotatedGeometry}, input_units::NamedTuple)::CSGTransformation where {T} - parse_rotation_matrix(T, dict["rotate"], input_units.angle) -end +# function parse_CSG_transformation(::Type{T}, dict::AbstractDict, ::Type{RotatedGeometry}, input_units::NamedTuple) where {T} +# parse_rotation_matrix(T, dict["rotate"], input_units.angle) +# end -function Geometry(::Type{T}, ::Type{RotatedGeometry}, dict::AbstractDict, input_units::NamedTuple) where {T} - angle_unit = input_units.angle - rotation_matrix = parse_rotation_matrix(T, dict, angle_unit) - key::String, transformations::Vector{CSGTransformation} = get_geometry_key(T, dict, input_units) - rotate(transform(Geometry(T, CSG_dict[key], dict[key], input_units), transformations), rotation_matrix) -end +# function Geometry(::Type{T}, ::Type{RotatedGeometry}, dict::AbstractDict, input_units::NamedTuple) where {T} +# angle_unit = input_units.angle +# rotation_matrix = parse_rotation_matrix(T, dict, angle_unit) +# key::String, transformations = get_geometry_key(T, dict, input_units) +# rotate(transform(Geometry(T, CSG_dict[key], dict[key], input_units), transformations), rotation_matrix) +# end function Geometry(::Type{T}, dict::AbstractDict, input_units::NamedTuple) where {T} - key::String, transformations::Vector{CSGTransformation} = get_geometry_key(T, dict, input_units) + key::String, transformations = get_geometry_key(T, dict, input_units) transform(Geometry(T, CSG_dict[key], dict[key], input_units), transformations) end @@ -204,11 +205,11 @@ function show_CSG_tree(csgtree; start = "", tab = "", CSG = false) show_CSG_tree(csgtree.a, start = tab*"├"*(CT <: CSGDifference ? " +" : "──"), tab = tab*(next_CSG ? "" : "│"), CSG = next_CSG) show_CSG_tree(csgtree.b, start = tab*(CSG ? "├" : "└")*(CT <: CSGDifference ? " ─" : "──"), tab = tab*(CSG ? "│" : " ")) end - if CT <: AbstractTransformedGeometry - println(start*" $(CT.name.name){$(CT.parameters[1])}") - tab *= "\t" - show_CSG_tree(csgtree.p, start = tab*"└──", tab = tab) - end + # if CT <: AbstractTransformedGeometry + # println(start*" $(CT.name.name){$(CT.parameters[1])}") + # tab *= "\t" + # show_CSG_tree(csgtree.p, start = tab*"└──", tab = tab) + # end if CT <: AbstractPrimitive println(start*" $(CT.name.name){$(CT.parameters[1])}") end diff --git a/src/ConstructiveSolidGeometry/Transformations.jl b/src/ConstructiveSolidGeometry/Transformations.jl index 0718ff422..165d7f33f 100644 --- a/src/ConstructiveSolidGeometry/Transformations.jl +++ b/src/ConstructiveSolidGeometry/Transformations.jl @@ -1,69 +1,10 @@ -struct ScaledGeometry{T,P<:AbstractGeometry{T}} <: AbstractTransformedGeometry{T} - p::P - inv_s::SVector{3,T} - ScaledGeometry(p::P, s::SVector{3,T}) where {T,P} = new{T,P}(p, inv.(s)) -end -in(p::CartesianPoint, g::ScaledGeometry) = in(CartesianPoint(p .* g.inv_s), g.p) -in(p::CylindricalPoint, g::ScaledGeometry) = in(CartesianPoint(p), g) -scale(g::AbstractGeometry{T}, s::SVector{3,T}) where {T} = (s == SVector{3,T}(1,1,1) ? g : ScaledGeometry(g, s)) -scale(g::ScaledGeometry{T}, s::SVector{3,T}) where {T} = (inv.(g.inv_s) .* s == SVector{3,T}(1,1,1) ? g.p : ScaledGeometry(g.p, inv.(g.inv_s) .* s)) -#(*)(g::AbstractGeometry{T}, s::SVector{3,T}) where {T} = scale(g, s) -get_plot_points(sg::ScaledGeometry{T}; n = 30) where {T} = scale!(get_plot_points(sg.p, n = n), inv.(sg.inv_s)) +transform(csg::G, t) where {G <: AbstractConstructiveGeometry} = G(transform(csg.a, t), transform(csg.b, t)) +transform(csg::G, t::Missing) where {G <: AbstractConstructiveGeometry} = csg -function Dictionary(g::ScaledGeometry{T}) where {T} - dict = Dictionary(g.p) - s = inv.(g.inv_s) - if s[1] != 1 dict["x"] = s[1] end - if s[2] != 1 dict["y"] = s[2] end - if s[3] != 1 dict["z"] = s[3] end - OrderedDict{String,Any}("scale" => dict) -end +transform(g::AbstractPrimitive, v::AbstractVector) = + length(v) > 1 ? transform(transform(g, v[end]), v[1:end-1]) : transform(g, v[1]) - -struct RotatedGeometry{T,P<:AbstractGeometry{T},RT} <: AbstractTransformedGeometry{T} - p::P - inv_r::RotMatrix3{RT} - RotatedGeometry(p::AbstractGeometry{T}, r::RotMatrix3{RT}) where {T,RT} = new{T,typeof(p),RT}(p, inv(r)) -end -in(p::CartesianPoint, g::RotatedGeometry) = in(g.inv_r * p, g.p) -in(p::CylindricalPoint, g::RotatedGeometry) = in(CartesianPoint(p), g) -rotate(g::AbstractGeometry{T}, r::RotMatrix3{RT}) where {T,RT} = (tr(r) == 3 ? g : RotatedGeometry(g, r)) -rotate(g::RotatedGeometry{T,<:Any,RT}, r::RotMatrix3{RT}) where {T,RT} = ( tr(r * inv(g.inv_r)) == 3 ? g.p : RotatedGeometry(g.p, r * inv(g.inv_r)) ) -(*)(r::RotMatrix3{RT}, g::AbstractGeometry{T}) where {T,RT} = rotate(g, r) -get_plot_points(rg::RotatedGeometry{T}; n = 30) where {T} = rotate!(get_plot_points(rg.p, n = n), inv(rg.inv_r)) - -function Dictionary(g::RotatedGeometry{T}) where {T} - dict = Dictionary(g.p) - dict["M"] = inv(g.inv_r)[:] - OrderedDict{String,Any}("rotate" => dict) -end - - - -struct TranslatedGeometry{T,P<:AbstractGeometry{T}} <: AbstractTransformedGeometry{T} - p::P - t::CartesianVector{T} -end -in(p::CartesianPoint, g::TranslatedGeometry) = in(p - g.t, g.p) -in(p::CylindricalPoint, g::TranslatedGeometry) = (g.t[1] == 0 && g.t[2] == 0) ? in(p -g.t, g.p) : in(CartesianPoint(p), g) -translate(g::AbstractGeometry{T}, t::CartesianVector{T}) where {T} = (t == CartesianVector{T}(0,0,0) ? g : TranslatedGeometry(g, t)) -translate(g::TranslatedGeometry{T}, t::CartesianVector{T}) where {T} = (g.t + t == CartesianVector{T}(0,0,0) ? g.p : TranslatedGeometry(g.p, g.t + t)) -(+)(g::AbstractGeometry{T}, t::CartesianVector{T}) where {T} = translate(g, t) -get_plot_points(tg::TranslatedGeometry{T}; n = 30) where {T} = translate!(get_plot_points(tg.p, n = n), tg.t) - -function Dictionary(g::TranslatedGeometry{T}) where {T} - dict = Dictionary(g.p) - t = g.t - if t.x != 0 dict["x"] = t.x end - if t.y != 0 dict["y"] = t.y end - if t.z != 0 dict["z"] = t.z end - OrderedDict{String,Any}("translate" => dict) -end - - - -const CSGTransformation = Union{SVector{3}, RotMatrix3, CartesianVector} -transform(g::AbstractGeometry, s::SVector{3}) = scale(g, s) -transform(g::AbstractGeometry, r::RotMatrix3) = rotate(g, r) -transform(g::AbstractGeometry, t::CartesianVector) = translate(g, t) -transform(g::AbstractGeometry, t::Vector{CSGTransformation}) = reduce(transform, reverse(t), init = g) +transform(p::AbstractVolumePrimitive, v::CartesianVector) = p + v +transform(p::AbstractVolumePrimitive, r::AbstractMatrix) = r * p +transform(p::AbstractVolumePrimitive, s::SVector{3}) = s * p +transform(p::AbstractVolumePrimitive, ::Missing) = p \ No newline at end of file diff --git a/src/SolidStateDetector/Contacts.jl b/src/SolidStateDetector/Contacts.jl index e07c2195f..532140d6c 100644 --- a/src/SolidStateDetector/Contacts.jl +++ b/src/SolidStateDetector/Contacts.jl @@ -15,7 +15,7 @@ struct Contact{T,G,MT} <: AbstractContact{T} end -function Contact{T}(dict::Union{Dict{String,Any}, Dict{Any, Any}}, input_units::NamedTuple, transformations::Vector{CSGTransformation})::Contact{T} where {T <: SSDFloat} +function Contact{T}(dict::Union{Dict{String,Any}, Dict{Any, Any}}, input_units::NamedTuple, transformations = missing)::Contact{T} where {T <: SSDFloat} id::Int = haskey(dict, "channel") ? dict["channel"] : -1 material = haskey(dict, "material") ? material_properties[materials[dict["material"]]] : material_properties[materials["HPGe"]] name = haskey(dict,"name") ? dict["name"] : "" diff --git a/src/SolidStateDetector/Passive.jl b/src/SolidStateDetector/Passive.jl index 8183d7b48..ce856217c 100644 --- a/src/SolidStateDetector/Passive.jl +++ b/src/SolidStateDetector/Passive.jl @@ -10,7 +10,7 @@ mutable struct Passive{T,G,MT,CDM} <: AbstractPassive{T} geometry::G end -function Passive{T}(dict::Dict, input_units::NamedTuple, transformations::Vector{CSGTransformation}) where T <: SSDFloat +function Passive{T}(dict::Dict, input_units::NamedTuple, transformations = missing) where T <: SSDFloat name = haskey(dict, "name") ? dict["name"] : "external part" id::Int = haskey(dict, "id") ? dict["id"] : -1 potential = haskey(dict, "potential") ? T(dict["potential"]) : :floating diff --git a/src/SolidStateDetector/Semiconductor.jl b/src/SolidStateDetector/Semiconductor.jl index de3cc827e..570b028a7 100644 --- a/src/SolidStateDetector/Semiconductor.jl +++ b/src/SolidStateDetector/Semiconductor.jl @@ -8,7 +8,7 @@ struct Semiconductor{T,G,MT,CDM,IDM} <: AbstractSemiconductor{T} geometry::G end -function Semiconductor{T}(dict::Dict, input_units::NamedTuple, transformations::Vector{CSGTransformation} = []) where T <: SSDFloat +function Semiconductor{T}(dict::Dict, input_units::NamedTuple, transformations = missing) where T <: SSDFloat impurity_density_model = if haskey(dict, "impurity_density") ImpurityDensity(T, dict["impurity_density"], input_units) elseif haskey(dict, "charge_density_model") diff --git a/src/SolidStateDetector/SolidStateDetector.jl b/src/SolidStateDetector/SolidStateDetector.jl index bebc9f882..855d73d86 100644 --- a/src/SolidStateDetector/SolidStateDetector.jl +++ b/src/SolidStateDetector/SolidStateDetector.jl @@ -15,25 +15,25 @@ end get_precision_type(::SolidStateDetector{T}) where {T} = T -function construct_semiconductor(T, sc::Dict, input_units::NamedTuple, transformations::Vector{CSGTransformation}= []) +function construct_semiconductor(T, sc::Dict, input_units::NamedTuple, transformations = missing) Semiconductor{T}(sc, input_units, transformations) end -function construct_passive(T, pass::Dict, input_units::NamedTuple, transformations::Vector{CSGTransformation}= []) +function construct_passive(T, pass::Dict, input_units::NamedTuple, transformations = missing) Passive{T}(pass, input_units, transformations) end -function construct_contact(T, contact::Dict, input_units::NamedTuple, transformations::Vector{CSGTransformation}= []) +function construct_contact(T, contact::Dict, input_units::NamedTuple, transformations = missing) Contact{T}(contact, input_units, transformations) end -function construct_virtual_volume(T, pass::Dict, input_units::NamedTuple, transformations::Vector{CSGTransformation}= []) +function construct_virtual_volume(T, pass::Dict, input_units::NamedTuple, transformations = missing) construct_virtual_volume(T, pass, input_units, Val{Symbol(pass["model"])}, transformations) end -function construct_virtual_volume(T, pass::Dict, input_units::NamedTuple, ::Type{Val{:dead}}, transformations::Vector{CSGTransformation}= []) +function construct_virtual_volume(T, pass::Dict, input_units::NamedTuple, ::Type{Val{:dead}}, transformations = missing) DeadVolume{T}(pass, input_units, transformations) end -function construct_virtual_volume(T, pass::Dict, input_units::NamedTuple, ::Type{Val{:arbitrary}}, transformations::Vector{CSGTransformation}= []) +function construct_virtual_volume(T, pass::Dict, input_units::NamedTuple, ::Type{Val{:arbitrary}}, transformations = missing) ArbitraryDriftModificationVolume{T}(pass, input_units, transformations) end @@ -114,9 +114,10 @@ function SolidStateDetector{T}(config_file::Dict, input_units::NamedTuple) where config_detector = config_file["detectors"][1] # still only one detector transformation_keys = filter(k -> k in ("translate", "rotate"), keys(config_detector)) - transformations::Vector{CSGTransformation} = broadcast(t -> parse_CSG_transformation(T, config_detector, CSG_dict[t], input_units), transformation_keys) - - @assert haskey(config_detector, "bulk") "Each detector needs an entry `bulk`. Please define the bulk." + transformations = broadcast(t -> parse_CSG_transformation(T, config_detector, CSG_dict[t], input_units), transformation_keys) + if isempty(transformations) transformations = missing end + + @assert haskey(config_detector, "bulk") "Each detector needs an entry `bulk`. Please define the bulk." semiconductor = construct_semiconductor(T, config_detector["bulk"], input_units, transformations) @assert haskey(config_detector, "contacts") "Each detector needs at least two contacts. Please define the them in the configuration file." diff --git a/src/SolidStateDetector/TransitionLayer.jl b/src/SolidStateDetector/TransitionLayer.jl index 71ca4ca3e..31551c131 100644 --- a/src/SolidStateDetector/TransitionLayer.jl +++ b/src/SolidStateDetector/TransitionLayer.jl @@ -7,7 +7,7 @@ function modulate_driftvector(sv::CartesianVector{T}, cp::CartesianPoint{T}, tl: return CartesianVector{T}(0,0,0) end -function DeadVolume{T}(dict::Dict, input_units::NamedTuple, transformations::Vector{CSGTransformation}) where T <: SSDFloat +function DeadVolume{T}(dict::Dict, input_units::NamedTuple, transformations = missing) where T <: SSDFloat n = haskey(dict, "name") ? dict["name"] : "external part" g = transform(Geometry(T, dict["geometry"], input_units), transformations) return DeadVolume{T}(n, g) @@ -32,7 +32,7 @@ function modulate_driftvector(sv::CartesianVector{T}, cp::CartesianPoint{T}, tl: end -function ArbitraryDriftModificationVolume{T}(dict::Dict, input_units::NamedTuple, transformations::Vector{CSGTransformation}) where T <: SSDFloat +function ArbitraryDriftModificationVolume{T}(dict::Dict, input_units::NamedTuple, transformations = missing) where T <: SSDFloat n = haskey(dict, "name") ? dict["name"] : "external part" g = transform(Geometry(T, dict["geometry"], input_units), transformations) id = Int(dict["id"]) diff --git a/src/SolidStateDetectors.jl b/src/SolidStateDetectors.jl index a1c6d6298..b4fabd965 100644 --- a/src/SolidStateDetectors.jl +++ b/src/SolidStateDetectors.jl @@ -37,7 +37,7 @@ using .ConstructiveSolidGeometry: AbstractSurfacePrimitive, geom_round, geom_sigdigits, geom_atol_zero, parse_rotation_matrix, parse_translate_vector, parse_CSG_transformation, - CSGTransformation, transform, CSG_dict + transform, CSG_dict import .ConstructiveSolidGeometry: sample, sample_surface From 713e94bcca9d8b5682240c557a2882239d69b141 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 16:25:03 +0200 Subject: [PATCH 035/241] Remove obsolete sample methods --- src/ConstructiveSolidGeometry/Sampling.jl | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/ConstructiveSolidGeometry/Sampling.jl b/src/ConstructiveSolidGeometry/Sampling.jl index e5969496d..2319ebc06 100644 --- a/src/ConstructiveSolidGeometry/Sampling.jl +++ b/src/ConstructiveSolidGeometry/Sampling.jl @@ -1,19 +1,6 @@ -sample_surface(c::AbstractVolumePrimitive{T}, sampling...) where {T} = [ point for surf in get_decomposed_surfaces(c) for point in sample(surf, sampling...) ] -sample_surface(c::AbstractSurfacePrimitive{T}, sampling...) where {T} = sample(c, sampling...) - -sample(sg::ScaledGeometry{T}, sampling...) where {T} = scale!(sample(sg.p, sampling...), inv.(sg.inv_s)) -sample(rg::RotatedGeometry{T}, sampling...) where {T} = rotate!(sample(rg.p, sampling...), inv(rg.inv_r)) -sample(tg::TranslatedGeometry{T}, sampling...) where {T} = translate!(sample(tg.p, sampling...), tg.t) sample(csg::AbstractConstructiveGeometry{T}, sampling...) where {T} = vcat(sample(csg.a, sampling...), sample(csg.b, sampling...)) -sample(tg::TranslatedGeometry{T}, g::CartesianTicksTuple{T}) where {T} = translate!(sample(tg.p, (x = g.x .- tg.t[1], y = g.y .- tg.t[2], z = g.z .- tg.t[3])), tg.t) -sample(tg::TranslatedGeometry{T}, g::CylindricalTicksTuple{T}) where {T} = sample(tg.p, (r = g.r, φ = g.φ, z = g.z .- tg.t[3])) .+ (CartesianVector{T}(0,0,tg.t[3]),) -sample_surface(sg::ScaledGeometry{T}, sampling...) where {T} = scale!(sample_surface(sg.p, sampling...), inv.(sg.inv_s)) -sample_surface(rg::RotatedGeometry{T}, sampling...) where {T} = rotate!(sample_surface(rg.p, sampling...), inv(rg.inv_r)) -sample_surface(tg::TranslatedGeometry{T}, sampling...) where {T} = translate!(sample_surface(tg.p, sampling...), tg.t) sample_surface(csg::AbstractConstructiveGeometry{T}, sampling...) where {T} = vcat(sample_surface(csg.a, sampling...), sample_surface(csg.b, sampling...)) -sample_surface(tg::TranslatedGeometry{T}, g::CartesianTicksTuple{T}) where {T} = translate!(sample_surface(tg.p, (g[1] .- tg.t[1], g[2] .- tg.t[2], g[3] .- tg.t[3])), tg.t) -sample_surface(tg::TranslatedGeometry{T}, g::CylindricalTicksTuple{T}) where {T} = sample_surface(tg.p, (g[1], g[2], g[3] .- tg.t[3])) .+ (CartesianVector{T}(0,0,tg.t[3]),) # for sampling surfaces with predefined ticks get_r_ticks(a::AbstractSurfacePrimitive{T}, g::CylindricalTicksTuple{T}) where {T} = _get_ticks(g.r, get_r_limits(a)...) From 1c0083900df3ad9cb3660a099efeef1591ed3f89 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 16:32:46 +0200 Subject: [PATCH 036/241] Enable rotation --- src/ConstructiveSolidGeometry/IO.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 8703fdc4e..84d484749 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -12,7 +12,7 @@ const CSG_dict = Dict{String, Any}( # "difference" => CSGDifference, # "intersection" => CSGIntersection, "translate" => CartesianVector, - # "rotate" => RotatedGeometry, + "rotate" => Rotation, # type from Rotations.jl: Rotation.Rotation # "scale" => ScaledGeometry ) @@ -176,9 +176,9 @@ function parse_rotation_matrix(::Type{T}, dict::AbstractDict, unit::Unitful.Unit end end -# function parse_CSG_transformation(::Type{T}, dict::AbstractDict, ::Type{RotatedGeometry}, input_units::NamedTuple) where {T} -# parse_rotation_matrix(T, dict["rotate"], input_units.angle) -# end +function parse_CSG_transformation(::Type{T}, dict::AbstractDict, ::Type{Rotation}, input_units::NamedTuple) where {T} + parse_rotation_matrix(T, dict["rotate"], input_units.angle) +end # function Geometry(::Type{T}, ::Type{RotatedGeometry}, dict::AbstractDict, input_units::NamedTuple) where {T} # angle_unit = input_units.angle From 08b0dcb280c2a0985730f10053c6e7f9b1a72748 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 17:43:33 +0200 Subject: [PATCH 037/241] Modify example config file: add translations and rotation --- .../public_CGD_config.yaml | 63 ++++++++----------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/examples/example_config_files/public_CGD_config.yaml b/examples/example_config_files/public_CGD_config.yaml index 7fa4b44ac..4488bb4c0 100644 --- a/examples/example_config_files/public_CGD_config.yaml +++ b/examples/example_config_files/public_CGD_config.yaml @@ -8,20 +8,24 @@ grid: coordinates: cartesian axes: x: - from: -5 + from: -15 to: 15 boundaries: inf y: - from: -5 + from: -15 to: 15 boundaries: inf z: - from: -5 + from: -15 to: 15 boundaries: inf medium: vacuum detectors: - - bulk: + - translate: + x: 0 + rotate: + Z: 45 + bulk: material: HPGe temperature: 78 impurity_density: @@ -39,15 +43,9 @@ detectors: include: ADLChargeDriftModel/drift_velocity_config.json geometry: box: - x: - from: 0 - to: 10 - y: - from: 0 - to: 10 - z: - from: 0 - to: 10 + x: 10 # width in x + y: 10 # width in y + z: 10 # width in z contacts: - material: HPGe name: n+ contact @@ -55,42 +53,35 @@ detectors: channel: 1 geometry: box: - x: - from: 0 - to: 0.1 - y: - from: 0 - to: 10 - z: - from: 0 - to: 10 + x: + from: -5 + to: -4.9 + y: 10 + z: 10 - material: HPGe name: p+ contact potential: 0 channel: 2 geometry: box: - x: - from: 9.9 - to: 10 - y: - from: 0 - to: 10 - z: - from: 0 - to: 10 + x: + from: 4.9 + to: 5 + y: 10 + z: 10 + surroundings: - name: Base material: Copper - potential: 1000 + potential: 0 geometry: box: x: - from: -5 + from: -15 to: 15 y: - from: -5 + from: -15 to: 15 z: - from: -2 - to: -1 + from: -7 + to: -6 From 368d41aa19a4d35ff4db1e1cad7127623835545a Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 17:44:22 +0200 Subject: [PATCH 038/241] Bugfix in read-in of transformations from config file --- src/SolidStateDetector/SolidStateDetector.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/SolidStateDetector/SolidStateDetector.jl b/src/SolidStateDetector/SolidStateDetector.jl index 855d73d86..0c1827166 100644 --- a/src/SolidStateDetector/SolidStateDetector.jl +++ b/src/SolidStateDetector/SolidStateDetector.jl @@ -130,6 +130,11 @@ function SolidStateDetector{T}(config_file::Dict, input_units::NamedTuple) where end end passives = if haskey(config_file, "surroundings") + config_surroundings = config_file["surroundings"] + transformation_keys = filter(k -> k in ("translate", "rotate"), keys(config_surroundings)) + transformations = broadcast(t -> parse_CSG_transformation(T, config_surroundings, CSG_dict[t], input_units), transformation_keys) + if isempty(transformations) transformations = missing end + broadcast(p -> construct_passive(T, p, input_units, transformations), config_file["surroundings"]) else missing From 66ce0a007a643fbd8fc9a4703583239a4add5c4e Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 18:10:07 +0200 Subject: [PATCH 039/241] Enable test for the CGD test detector --- .../public_CGD_config.yaml | 26 ++++++++--------- src/ChargeDrift/ChargeDrift.jl | 1 + test/runtests.jl | 29 ++++++++++--------- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/examples/example_config_files/public_CGD_config.yaml b/examples/example_config_files/public_CGD_config.yaml index 4488bb4c0..803249b5e 100644 --- a/examples/example_config_files/public_CGD_config.yaml +++ b/examples/example_config_files/public_CGD_config.yaml @@ -8,16 +8,16 @@ grid: coordinates: cartesian axes: x: - from: -15 - to: 15 + from: -7 + to: 7 boundaries: inf y: - from: -15 - to: 15 + from: -7 + to: 7 boundaries: inf z: - from: -15 - to: 15 + from: -7 + to: 7 boundaries: inf medium: vacuum detectors: @@ -55,7 +55,7 @@ detectors: box: x: from: -5 - to: -4.9 + to: -4.5 y: 10 z: 10 - material: HPGe @@ -65,8 +65,8 @@ detectors: geometry: box: x: - from: 4.9 - to: 5 + from: 4 + to: 4.5 y: 10 z: 10 @@ -77,11 +77,11 @@ surroundings: geometry: box: x: - from: -15 - to: 15 + from: -7 + to: 7 y: - from: -15 - to: 15 + from: -7 + to: 7 z: from: -7 to: -6 diff --git a/src/ChargeDrift/ChargeDrift.jl b/src/ChargeDrift/ChargeDrift.jl index 8daf0ac60..6445f3f78 100644 --- a/src/ChargeDrift/ChargeDrift.jl +++ b/src/ChargeDrift/ChargeDrift.jl @@ -77,6 +77,7 @@ function modulate_driftvector(sv::CartesianVector{T}, cp::CartesianPoint{T}, vdv end return sv end +modulate_driftvector(sv::CartesianVector{T}, cp::CartesianPoint{T}, vdv::Missing) where {T} = sv @inline function _is_next_point_in_det(pt_car::CartesianPoint{T}, pt_cyl::CylindricalPoint{T}, det::SolidStateDetector{T}, point_types::PointTypes{T, 3, Cylindrical})::Bool where {T <: SSDFloat} pt_cyl in point_types || pt_cyl in det diff --git a/test/runtests.jl b/test/runtests.jl index 965b37f9e..b21f145b8 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -12,7 +12,7 @@ T = Float32 # include("comparison_to_analytic_solutions.jl") # end -# @testset "Test real detectors" begin +@testset "Test real detectors" begin # @testset "Simulate example detector: Inverted Coax" begin # sim = Simulation{T}(SSD_examples[:InvertedCoax]) # simulate!(sim, max_refinements = 1, verbose = true) @@ -68,18 +68,19 @@ T = Float32 # end # @test isapprox( signalsum, T(2), atol = 5e-4 ) # end -# @testset "Simulate example detector: CGD" begin -# sim = Simulation{T}(SSD_examples[:CGD]) -# SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) -# simulate!(sim, max_refinements = 0, verbose = true) -# evt = Event([CartesianPoint{T}(5e-3, 5e-3, 5e-3)]) -# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) -# signalsum = T(0) -# for i in 1:length(evt.waveforms) -# signalsum += abs(evt.waveforms[i].value[end]) -# end -# @test isapprox( signalsum, T(2), atol = 5e-4 ) -# end + @testset "Simulate example detector: CGD" begin + sim = Simulation{T}(SSD_examples[:CGD]) + SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) + simulate!(sim, max_refinements = 1, verbose = true) + evt = Event([CartesianPoint{T}(0,0,0)]) + simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) + signalsum = T(0) + for i in 1:length(evt.waveforms) + signalsum += abs(evt.waveforms[i].value[end]) + end + signalsum + @test isapprox( signalsum, T(2), atol = 5e-3 ) + end # #= # @testset "Simulate example detector: Spherical" begin # sim = Simulation{T}(SSD_examples[:Spherical]) @@ -117,7 +118,7 @@ T = Float32 # end # @test isapprox( signalsum, T(2), atol = 5e-4 ) # end -# end +end # @testset "ADLChargeDriftModel" begin # include("ADLChargeDriftModel.jl") From f65d9c7c8102a29255dbc61edf279bc6fe136221 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 18:11:27 +0200 Subject: [PATCH 040/241] Add plotting recipe for `Polygon` --- .../plotting/SurfacePrimitives/Polygon.jl | 27 +++++++++++++++++++ .../SurfacePrimitives/SurfacePrimitives.jl | 17 +----------- 2 files changed, 28 insertions(+), 16 deletions(-) create mode 100644 src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/Polygon.jl diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/Polygon.jl new file mode 100644 index 000000000..f41aee2b1 --- /dev/null +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/Polygon.jl @@ -0,0 +1,27 @@ +@recipe function f(p::Polygon; show_normal = false, normallength = 0, normalcolor = missing) + @series begin + x = map(p -> p[1], [p.points..., p.points[1]]) + y = map(p -> p[2], [p.points..., p.points[1]]) + z = map(p -> p[3], [p.points..., p.points[1]]) + x, y, z + end + if show_normal + @series begin + seriestype := :vector + if !ismissing(normalcolor) + linecolor := normalcolor + end + mean(p.points), Plane(p).normal * normallength + end + end +end + +@recipe function f(vp::AbstractVector{<:Polygon}) + for p in vp + @series begin + show_normal := true + p + end + end +end + diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl index 36a98ec74..6802f2afe 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl @@ -1,16 +1 @@ - - -# @recipe function f(g::AbstractSurfacePrimitive; SSD_style = :wireframe, n = 30) -# if SSD_style == :wireframe #update to only plot real surfaces -# linewidth --> 2 -# for points in get_plot_points(g, n = n) -# @series begin -# label := "" -# points -# end -# end -# elseif SSD_style == :surface -# linewidth --> 0.2 -# mesh(g) -# end -# end +include("Polygon.jl") From d8511cac1a28cf00e04e66c378e458939d2c9397 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 9 Jun 2021 18:11:38 +0200 Subject: [PATCH 041/241] Add plotting recipe for `Box` --- .../plotting/VolumePrimitives/Box.jl | 39 ++----------------- .../VolumePrimitives/VolumePrimitives.jl | 1 + 2 files changed, 5 insertions(+), 35 deletions(-) diff --git a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/Box.jl index 6ef2ce104..446594645 100644 --- a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/Box.jl @@ -1,37 +1,6 @@ -function get_plot_points(b::Box{T}; kwargs...) where {T <: AbstractFloat} - - plot_points = Vector{CartesianPoint{T}}[] - - xMin::T = _left_linear_interval(b.x) - xMax::T = _right_linear_interval(b.x) - yMin::T = _left_linear_interval(b.y) - yMax::T = _right_linear_interval(b.y) - zMin::T = _left_linear_interval(b.z) - zMax::T = _right_linear_interval(b.z) - - #horizontal squares - for z in [zMin, zMax] - push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(xMin, yMin, z), CartesianPoint{T}(xMin, yMax, z), - CartesianPoint{T}(xMax, yMax, z), CartesianPoint{T}(xMax, yMin, z), - CartesianPoint{T}(xMin, yMin, z)])) +@recipe function f(b::Box) + fs = faces(b) + @series begin + fs end - - #vertical lines - for x in [xMin, xMax] - for y in [yMin, yMax] - push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(x,y,zMin), CartesianPoint{T}(x,y,zMax)])) - end - end - - plot_points end - - -# Old CSG -# @recipe function f(cb::Box{T}) where {T <: SSDFloat} -# label-->"Box" -# ls = LineSegments(cb) -# @series begin -# ls -# end -# end \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl index e69de29bb..379ce3996 100644 --- a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl @@ -0,0 +1 @@ +include("Box.jl") \ No newline at end of file From babc354124fd8806660bc52d6d6d6fc484886bb0 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 10 Jun 2021 09:44:31 +0200 Subject: [PATCH 042/241] Improve line-, surface- and volume-primitives plot recipes --- .../plotting/LinePrimitives/Edge.jl | 9 ++++ .../plotting/LinePrimitives/LinePrimitives.jl | 53 ++++++------------- .../plotting/PointsAndVectors/Vectors.jl | 18 ++++--- .../plotting/SurfacePrimitives/Polygon.jl | 19 +++---- .../SurfacePrimitives/SurfacePrimitives.jl | 18 +++++++ .../VolumePrimitives/VolumePrimitives.jl | 37 ++++++++++++- 6 files changed, 95 insertions(+), 59 deletions(-) create mode 100644 src/ConstructiveSolidGeometry/plotting/LinePrimitives/Edge.jl diff --git a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Edge.jl b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Edge.jl new file mode 100644 index 000000000..67ed2f4e9 --- /dev/null +++ b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Edge.jl @@ -0,0 +1,9 @@ +@recipe function f(e::Edge) + linecolor --> :black + @series begin + seriestype --> :path3d + [e.a[1], e.b[1]], [e.a[2], e.b[2]], [e.a[3], e.b[3]] + end +end + + diff --git a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/LinePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/LinePrimitives.jl index 2ec50e936..213ef2635 100644 --- a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/LinePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/LinePrimitives.jl @@ -1,38 +1,17 @@ +include("Edge.jl") - -# Old -# @recipe function f(l::AbstractLine{T, 3, :cartesian}) where {T} -# x::Vector{T} = [l.org.x, l.org.x + l.dir.x] -# y::Vector{T} = [l.org.y, l.org.y + l.dir.y] -# z::Vector{T} = [l.org.z, l.org.z + l.dir.z] -# x, y, z -# end - -# @recipe function f(l::AbstractLine{T, 2, :cartesian}) where {T} -# x::Vector{T} = [l.org.x, l.org.x + l.dir.x] -# y::Vector{T} = [l.org.y, l.org.y + l.dir.y] -# x, y -# end - -# @recipe function f(pc::PartialCircle{T, 3, :cartesian}; n = 30) where {T} -# phirange = range(pc.phiStart, pc.phiStop, length = round(Int, n + 1)) -# x::Vector{T} = pc.r .* cos.(phirange) -# y::Vector{T} = pc.r .* sin.(phirange) -# z::Vector{T} = map(phi -> 0.0, phirange) -# points = map(p -> pc.Rotate*p + pc.Translate, CartesianPoint{T}.(x,y,z)) -# points -# end - -# @recipe function f(ls::Array{<:AbstractLine{T, 3, :cartesian}, 1}) where {T} -# seriescolor --> 1 -# for l in ls -# @series begin -# label := "" -# l -# end -# end -# @series begin -# label --> "" -# [], [] -# end -# end +@recipe function f(ls::AbstractVector{<:AbstractLinePrimitive}) + linecolor --> :black + @series begin + label --> "Edges" + ls[1] + end + if length(ls) > 1 + for l in ls[2:end] + @series begin + label := nothing + l + end + end + end +end diff --git a/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl index 846e515b0..a1bcf8b19 100644 --- a/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl +++ b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl @@ -3,19 +3,21 @@ origin = x vector = y target = origin + vector - al = headlength - aw = headwidth + length = norm(vector) + hl = length * headlength + hw = length * headwidth T = eltype(origin) eX = CartesianVector{T}(1,0,0) eY = CartesianVector{T}(0,1,0) eZ = CartesianVector{T}(0,0,1) - apxl = target - al*vector - aw * normalize(vector × eX) - apxr = target - al*vector + aw * normalize(vector × eX) - apyl = target - al*vector - aw * normalize(vector × eY) - apyr = target - al*vector + aw * normalize(vector × eY) - apzl = target - al*vector - aw * normalize(vector × eZ) - apzr = target - al*vector + aw * normalize(vector × eZ) + apxl = target - hl*vector - hw * normalize(vector × eX) + apxr = target - hl*vector + hw * normalize(vector × eX) + apyl = target - hl*vector - hw * normalize(vector × eY) + apyr = target - hl*vector + hw * normalize(vector × eY) + apzl = target - hl*vector - hw * normalize(vector × eZ) + apzr = target - hl*vector + hw * normalize(vector × eZ) + linecolor --> :black x := [origin[1], target[1], apxl[1], target[1], apxr[1], target[1], apyl[1], target[1], apyr[1], target[1], apzl[1], target[1], apzr[1]] y := [origin[2], target[2], apxl[2], target[2], apxr[2], target[2], apyl[2], target[2], apyr[2], target[2], apzl[2], target[2], apzr[2]] z := [origin[3], target[3], apxl[3], target[3], apxr[3], target[3], apyl[3], target[3], apyr[3], target[3], apzl[3], target[3], apzr[3]] diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/Polygon.jl index f41aee2b1..f926bf259 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/Polygon.jl @@ -1,27 +1,20 @@ -@recipe function f(p::Polygon; show_normal = false, normallength = 0, normalcolor = missing) +@recipe function f(p::Polygon; normallength = 0) + linecolor --> :black @series begin + label --> "Polygon" x = map(p -> p[1], [p.points..., p.points[1]]) y = map(p -> p[2], [p.points..., p.points[1]]) z = map(p -> p[3], [p.points..., p.points[1]]) x, y, z end - if show_normal + if normallength > 0 @series begin + label --> "Normal" seriestype := :vector - if !ismissing(normalcolor) - linecolor := normalcolor - end mean(p.points), Plane(p).normal * normallength end end end -@recipe function f(vp::AbstractVector{<:Polygon}) - for p in vp - @series begin - show_normal := true - p - end - end -end + diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl index 6802f2afe..0d5dd1f54 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl @@ -1 +1,19 @@ include("Polygon.jl") + +@recipe function f(vp::AbstractVector{<:AbstractSurfacePrimitive}) + linecolor --> :black + @series begin + label --> "Faces" + show_normal --> false + vp[1] + end + if length(vp) > 1 + for p in vp[2:end] + @series begin + show_normal --> false + label := nothing + p + end + end + end +end diff --git a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl index 379ce3996..f9c25f08b 100644 --- a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl @@ -1 +1,36 @@ -include("Box.jl") \ No newline at end of file +@recipe function f(p::AbstractVolumePrimitive) + fs = faces(p) + # In principle it would be better to directly get the edges of the primitive + # Can be improved later... + linecolor --> :black + @series begin + label --> "$(nameof(typeof(p)))" + fs + end +end + +@recipe function f(p1::AbstractVolumePrimitive, p2::AbstractVolumePrimitive) + fs1 = faces(p1) + fs2 = faces(p2) + # In principle it would be better to directly get the edges of the primitive + # Can be improved later... + linecolor --> :black + @series begin + if plotattributes[:csguniontype] == :intersection + linestyle := :dot + else + linestyle := :solid + end + fs1 + end + @series begin + if plotattributes[:csguniontype] == :intersection + linestyle := :dot + elseif plotattributes[:csguniontype] == :difference + linestyle := :dash + else + linestyle := :solid + end + fs2 + end +end \ No newline at end of file From b6dae4cb8abd5ebb9f919f111fc2c6d684f23e4f Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 10 Jun 2021 09:45:21 +0200 Subject: [PATCH 043/241] Add primitive plot recipes for CSG's --- src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl | 15 +++++++++++++++ .../plotting/plotting.jl | 1 + 2 files changed, 16 insertions(+) create mode 100644 src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl diff --git a/src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl b/src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl new file mode 100644 index 000000000..38f3432d0 --- /dev/null +++ b/src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl @@ -0,0 +1,15 @@ +@recipe function f(csg::ConstructiveSolidGeometry.CSGUnion) + linecolor --> :black + csguniontype --> :union + csg.a, csg.b +end +@recipe function f(csg::ConstructiveSolidGeometry.CSGDifference) + linecolor --> :black + csguniontype --> :difference + csg.a, csg.b +end +@recipe function f(csg::ConstructiveSolidGeometry.CSGIntersection) + linecolor --> :black + csguniontype --> :intersection + csg.a, csg.b +end \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/plotting/plotting.jl b/src/ConstructiveSolidGeometry/plotting/plotting.jl index 3f5a70719..949a39fef 100644 --- a/src/ConstructiveSolidGeometry/plotting/plotting.jl +++ b/src/ConstructiveSolidGeometry/plotting/plotting.jl @@ -90,3 +90,4 @@ include("VolumePrimitives/VolumePrimitives.jl") # points = CartesianPoint.(points) # map(p -> p.x, points), map(p -> p.y, points), map(p -> p.z, points) # end +include("CSG/CSG.jl") From 71c5afbf32e29836b75254bd1ae8bbc76a99ebfd Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 10 Jun 2021 09:45:57 +0200 Subject: [PATCH 044/241] Add simple plot recipes for SolidStateDetector, Semiconductor, Contacts and Passives --- src/PlotRecipes/SolidStateDetector.jl | 96 ++++++++++----------------- 1 file changed, 35 insertions(+), 61 deletions(-) diff --git a/src/PlotRecipes/SolidStateDetector.jl b/src/PlotRecipes/SolidStateDetector.jl index 2a21c9785..d58b48e05 100644 --- a/src/PlotRecipes/SolidStateDetector.jl +++ b/src/PlotRecipes/SolidStateDetector.jl @@ -1,71 +1,45 @@ -@recipe function f(det::SolidStateDetector{T}; SSD_style = :wireframe, n = 30, φ = missing, seriescolor = missing, label = missing, alpha_factor = 1) where {T} - if !(SSD_style in [:wireframe])#, :samplesurface]) - #@warn "Chose SSD_style from [:wireframe, :samplesurface]. Defaulting to :wireframe" - SSD_style = :wireframe - end - clabel = (ismissing(label) ? map(c -> (c.name == "" ? c.id : c.name), det.contacts) : label) - if !(typeof(clabel) <: AbstractArray) clabel = [clabel] end - ccolor = (ismissing(seriescolor) ? map(c -> c.id, det.contacts) : seriescolor) - if !(typeof(ccolor) <: AbstractArray) ccolor = [ccolor] end - world_size = missing - #= - if SSD_style == :samplesurface - grid = Grid(det) # DOES NOT WORK ANYMORE - CS = get_coordinate_system(det) # DOES NOT WORK ANYMORE - if CS == Cylindrical - world_size = CylindricalVector{T}(width(grid.r.interval), π, width(grid.z.interval)) - elseif CS == Cartesian - world_size = CartesianVector{T}(width(grid.x.interval), width(grid.y.interval), width(grid.z.interval)) - else - @error "Could not determine the world size, try SSD_style = :wireframe" - end - end - =# - if ismissing(φ) - xguide --> "x / m" - yguide --> "y / m" - zguide --> "z / m" +@recipe function f(p::Passive) + linecolor --> :grey + l = p.name != "" ? p.name : "Passive $(p.id)" + label --> l + p.geometry +end +@recipe function f(sc::Semiconductor) + linecolor --> :black + label --> "Semiconductor" + sc.geometry +end - for (cn,contact) in enumerate(det.contacts) - linewidth --> 2 - seriescolor := ccolor[(cn-1)%length(ccolor)+1] - @series begin - label := "" - n --> n - SSD_style --> SSD_style - world_size --> world_size - alpha_factor --> alpha_factor - contact - end - @series begin - label := clabel[(cn-1)%length(clabel)+1] - seriescolor := ccolor[(cn-1)%length(ccolor)+1] - [] - end - end - else - @info "2D plotting of the detector not yet implemented." - end +@recipe function f(contact::Contact) + linecolor --> contact.id + l = contact.name != "" ? contact.name : "Contact $(contact.id)" + label --> l + contact.geometry end +@recipe function f(contact::Contact) + linecolor --> contact.id + l = contact.name != "" ? contact.name : "Contact $(contact.id)" + label --> l + contact.geometry +end + +@recipe function f(det::SolidStateDetector) + xguide --> "x / m" + yguide --> "y / m" + zguide --> "z / m" -@recipe function f(contact::Contact{T}; SSD_style = :wireframe, n = 30, seriescolor = missing, world_size = missing, alpha_factor = 1) where {T} - ccolor = (ismissing(seriescolor) ? contact.id : seriescolor) @series begin - seriescolor := ccolor - label --> (contact.name == "" ? contact.id : contact.name) - [] + det.semiconductor end - for (cn,c) in enumerate(contact.geometry_positive) + for c in det.contacts @series begin - seriescolor := ccolor - label := "" - n --> n - SSD_style --> SSD_style - world_size --> world_size - geometry_negative --> contact.geometry_negative - alpha_factor --> alpha_factor c end end -end \ No newline at end of file + for p in det.passives + @series begin + p + end + end +end From ffe878c20122fb29264d675cd17db36e55c01f0e Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 10 Jun 2021 09:49:06 +0200 Subject: [PATCH 045/241] Fix CSG config file --- .../public_CGD_config.yaml | 28 +++++++++---------- test/runtests.jl | 4 +-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/example_config_files/public_CGD_config.yaml b/examples/example_config_files/public_CGD_config.yaml index 803249b5e..c78d4de89 100644 --- a/examples/example_config_files/public_CGD_config.yaml +++ b/examples/example_config_files/public_CGD_config.yaml @@ -8,16 +8,16 @@ grid: coordinates: cartesian axes: x: - from: -7 - to: 7 + from: -9 + to: 9 boundaries: inf y: - from: -7 - to: 7 + from: -9 + to: 9 boundaries: inf z: - from: -7 - to: 7 + from: -9 + to: 9 boundaries: inf medium: vacuum detectors: @@ -65,8 +65,8 @@ detectors: geometry: box: x: - from: 4 - to: 4.5 + from: 4.5 + to: 5 y: 10 z: 10 @@ -77,11 +77,11 @@ surroundings: geometry: box: x: - from: -7 - to: 7 + from: -9 + to: 9 y: - from: -7 - to: 7 + from: -9 + to: 9 z: - from: -7 - to: -6 + from: -9 + to: -7 \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index b21f145b8..753116467 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -71,7 +71,7 @@ T = Float32 @testset "Simulate example detector: CGD" begin sim = Simulation{T}(SSD_examples[:CGD]) SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) - simulate!(sim, max_refinements = 1, verbose = true) + simulate!(sim, max_refinements = 2, verbose = true) evt = Event([CartesianPoint{T}(0,0,0)]) simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) signalsum = T(0) @@ -79,7 +79,7 @@ T = Float32 signalsum += abs(evt.waveforms[i].value[end]) end signalsum - @test isapprox( signalsum, T(2), atol = 5e-3 ) + @test isapprox( signalsum, T(2), atol = 5e-2 ) end # #= # @testset "Simulate example detector: Spherical" begin From 9df43459ad4d62bf10a7f809fd4e5e83f28efceb Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 10 Jun 2021 12:02:29 +0200 Subject: [PATCH 046/241] Make the CGD detector working on a cylindrical grid. --- .../ConstructiveSolidGeometry.jl | 1 + .../PointsAndVectors/Vectors.jl | 3 ++ .../SurfacePrimitives/Plane.jl | 22 +++++++++++ .../SurfacePrimitives/Polygon.jl | 36 ++++++++++++++++++ src/Grids/Grids.jl | 3 +- src/SolidStateDetector/DetectorGeometries.jl | 37 ++++++++++++++++++- 6 files changed, 99 insertions(+), 3 deletions(-) diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index 7308eb15f..4f6a933d1 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -50,6 +50,7 @@ module ConstructiveSolidGeometry _transform_into_object_coordinate_system(pt::CartesianPoint, p::AbstractVolumePrimitive) = inv(rotation(p)) * (pt - origin(p)) in(pt::CartesianPoint, p::AbstractVolumePrimitive) = _in(_transform_into_object_coordinate_system(pt, p), p) + in(pt::CylindricalPoint, p::AbstractVolumePrimitive) = in(CartesianPoint(pt), p) # Do we want to store the rotation matrix permanently in the primitive? # We should do tests regarding the performance. It can be easily added later. diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl index 89093b9ea..60505191c 100644 --- a/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl @@ -46,3 +46,6 @@ struct CylindricalVector{T} <: AbstractCoordinateVector{T, Cylindrical} φ::T z::T end + +CartesianVector(v::CylindricalVector{T}) where {T} = + CartesianVector{T}(CartesianPoint(CylindricalPoint{T}(v))) \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl index fd7717604..5b3fe4e64 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl @@ -38,3 +38,25 @@ function evaluate(p::Plane{T}, y, z, ::Val{:yz}) where {T} end +function evaluate(p::Plane{T}, r, φ, ::Val{:rφ}) where {T} + # plane.normal may not be perpendicular to the z-axis + car_pt = CartesianPoint(CylindricalPoint{T}(r, φ, zero(T))) + line = Line{T}(CartesianPoint{T}(car_pt.x, car_pt.y, zero(T)), CartesianVector{T}(zero(T), zero(T), one(T))) + z = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ line.normal) + CylindricalPoint(CartesianPoint{T}(car_pt.x, car_pt.y, z)) +end +function evaluate(p::Plane{T}, r, z, ::Val{:rz}) where {T} + #= + We need a function to calculate the crosssection + of a CylindricalVector{T}(0, 1, 0) with a polygon + =# + φ = 0 + CylindricalPoint{T}(r, φ, z) +end +function evaluate(p::Plane{T}, φ, z, ::Val{:φz}) where {T} + # plane.normal may not be perpendicular to the z-axis + car_pt = CartesianPoint(CylindricalPoint{T}(zero(T), φ, z)) + line = Line{T}(CartesianPoint{T}(zero(T), car_pt.y, car_pt.z), CartesianVector(CylindricalVector{T}(one(T), zero(T), zero(T)))) + r = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ line.normal) + CylindricalPoint{T}(r, φ, z) +end \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl index 3773430cd..feb0e13ec 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl @@ -141,6 +141,42 @@ function get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CartesianTicksTuple{T}) end return t1, t2, proj end +function get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CylindricalTicksTuple{T}) where {N, T} + # This method would actually work for any flat surface, e.g. elipse + cyls = CylindricalPoint.(p.points) + rs, φs, zs = getindex.(cyls, 1), getindex.(cyls, 2), getindex.(cyls, 3) + rmin_idx = searchsortedfirst(t[1], minimum(rs)) + φmin_idx = searchsortedfirst(t[2], minimum(φs)) + zmin_idx = searchsortedfirst(t[3], minimum(zs)) + rmax_idx = searchsortedfirst(t[1], maximum(rs)) + φmax_idx = searchsortedfirst(t[2], maximum(φs)) + zmax_idx = searchsortedfirst(t[3], maximum(zs)) + ls = (length(t[1]), length(t[2]), length(t[3])) + if rmax_idx > ls[1] rmax_idx = ls[1] end + if φmax_idx > ls[2] φmax_idx = ls[2] end + if zmax_idx > ls[3] zmax_idx = ls[3] end + t_idx_range_r = rmin_idx:rmax_idx + t_idx_range_φ = φmin_idx:φmax_idx + t_idx_range_z = zmin_idx:zmax_idx + ls = (length(t_idx_range_r), length(t_idx_range_φ), length(t_idx_range_z)) + ls = ( + ls[1] == 1 ? typemax(eltype(ls)) : ls[1], + ls[2] == 1 ? typemax(eltype(ls)) : ls[2], + ls[3] == 1 ? typemax(eltype(ls)) : ls[3] + ) + n = normal(p) + proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && + (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) + Val{:rφ}(), t_idx_range_r, t_idx_range_φ + # elseif ls[1] < ls[2] && ls[3] < ls[2] # for a polygon we do not need Val{:rz} + # Val{:rz}(), t_idx_range_r, t_idx_range_z + else + Val{:φz}(), t_idx_range_φ, t_idx_range_z + end + return t1, t2, proj +end + + function sample(p::Polygon{N, T}, t::CartesianTicksTuple{T}) where {N, T} diff --git a/src/Grids/Grids.jl b/src/Grids/Grids.jl index 9c963f4c7..6c5b3df64 100644 --- a/src/Grids/Grids.jl +++ b/src/Grids/Grids.jl @@ -113,7 +113,8 @@ function get_boundary_types(grid::Grid{T, N, S}) where {T, N, S} return get_boundary_types.(grid.axes) end -CartesianTicksTuple(g::Grid{T, 3, Cartesian}) where {T} = (x = g.axes[1].ticks, y = g.axes[2].ticks, z = g.axes[3].ticks) +TicksTuple(g::Grid{T, 3, Cartesian}) where {T} = (x = g.axes[1].ticks, y = g.axes[2].ticks, z = g.axes[3].ticks) +TicksTuple(g::Grid{T, 3, Cylindrical}) where {T} = (r = g.axes[1].ticks, φ = g.axes[2].ticks, z = g.axes[3].ticks) function Grid(nt::NamedTuple) if nt.coordtype == "cylindrical" diff --git a/src/SolidStateDetector/DetectorGeometries.jl b/src/SolidStateDetector/DetectorGeometries.jl index ab84b9b5f..88b88ab5e 100644 --- a/src/SolidStateDetector/DetectorGeometries.jl +++ b/src/SolidStateDetector/DetectorGeometries.jl @@ -424,8 +424,8 @@ function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, p nothing end -function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, geometry, pot_value, grid) - ticks = CartesianTicksTuple(grid) +function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, geometry, pot_value, grid::CartesianGrid) + ticks = TicksTuple(grid) t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) t1, t2 = if proj == Val{:xy}() ticks[1], ticks[2] @@ -457,6 +457,39 @@ function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, end nothing end +function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, geometry, pot_value, grid::CylindricalGrid) + ticks = TicksTuple(grid) + t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) + t1, t2 = if proj == Val{:rφ}() + ticks[1], ticks[2] + elseif proj == Val{:φz}() + ticks[2], ticks[3] + else + ticks[1], ticks[3] + end + plane = ConstructiveSolidGeometry.Plane(face) + for i2 in t_idx_r2 + for i1 in t_idx_r1 + pt = ConstructiveSolidGeometry.evaluate(plane, t1[i1], t2[i2], proj) + if pt in geometry + if proj == Val{:rφ}() + i3 = searchsortednearest(ticks[3], pt[3]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value + elseif proj == Val{:φz}() + i3 = searchsortednearest(ticks[2], pt[2]) + pointtypes[i1, i3, i2] = zero(PointType) + potential[i1, i3, i2] = pot_value + else + i3 = searchsortednearest(ticks[1], pt[1]) + pointtypes[i3, i1, i2] = zero(PointType) + potential[i3, i1, i2] = pot_value + end + end + end + end + nothing +end function json_to_dict(inputfile::String)::Dict parsed_json_file = Dict() From 01f7dd5c8250643ec0e6784257759c3ca522d29a Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 10 Jun 2021 12:03:24 +0200 Subject: [PATCH 047/241] Add config file of CGD detector on a cylindrical grid --- .../public_CGD_config_cyl_grid.yaml | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 examples/example_config_files/public_CGD_config_cyl_grid.yaml diff --git a/examples/example_config_files/public_CGD_config_cyl_grid.yaml b/examples/example_config_files/public_CGD_config_cyl_grid.yaml new file mode 100644 index 000000000..c206523c3 --- /dev/null +++ b/examples/example_config_files/public_CGD_config_cyl_grid.yaml @@ -0,0 +1,86 @@ +name: ExampleCuboid +units: + length: mm + angle: deg + potential: V + temperature: K +grid: + coordinates: cylindrical + axes: + r: + to: 9 + boundaries: inf + y: + from: 0 + to: 0 + boundaries: periodic + z: + from: -9 + to: 9 + boundaries: inf +medium: vacuum +detectors: + - translate: + x: 0 + rotate: + Z: 45 + bulk: + material: HPGe + temperature: 78 + impurity_density: + name: linear + x: + init: 0 + gradient: 0 + y: + init: 0 + gradient: 0 + z: + init: 10000000 + gradient: 50000 + charge_drift_model: + include: ADLChargeDriftModel/drift_velocity_config.json + geometry: + box: + x: 10 # width in x + y: 10 # width in y + z: 10 # width in z + contacts: + - material: HPGe + name: n+ contact + potential: 2000 + channel: 1 + geometry: + box: + x: + from: -5 + to: -4.5 + y: 10 + z: 10 + - material: HPGe + name: p+ contact + potential: 0 + channel: 2 + geometry: + box: + x: + from: 4.5 + to: 5 + y: 10 + z: 10 + +surroundings: + - name: Base + material: Copper + potential: 0 + geometry: + box: + x: + from: -9 + to: 9 + y: + from: -9 + to: 9 + z: + from: -9 + to: -7 \ No newline at end of file From 88929c85240d3d6bf3e3d94ff4b8ac2102d7592c Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 10 Jun 2021 13:42:14 +0200 Subject: [PATCH 048/241] Rename function `faces` to `surfaces` --- src/ConstructiveSolidGeometry/CSG.jl | 2 +- src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl | 4 ++-- .../plotting/VolumePrimitives/VolumePrimitives.jl | 6 +++--- src/SolidStateDetector/DetectorGeometries.jl | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ConstructiveSolidGeometry/CSG.jl b/src/ConstructiveSolidGeometry/CSG.jl index 8ae386bd0..78faab1fe 100644 --- a/src/ConstructiveSolidGeometry/CSG.jl +++ b/src/ConstructiveSolidGeometry/CSG.jl @@ -73,4 +73,4 @@ scale(csg::A, s::SVector{3}) where {A <: AbstractConstructiveGeometry} = A(scale (*)(s::SVector{3}, csg::A) where {A <: AbstractConstructiveGeometry} = A(scale(csg.a, s), scale(csg.b, s)) (*)(csg::A, s::SVector{3}) where {A <: AbstractConstructiveGeometry} = A(scale(csg.a, s), scale(csg.b, s)) -faces(csg::AbstractConstructiveGeometry) = vcat(faces(csg.a)..., faces(csg.b)...) \ No newline at end of file +surfaces(csg::AbstractConstructiveGeometry) = vcat(surfaces(csg.a)..., surfaces(csg.b)...) \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index d947e4641..0ddb5a37a 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -87,7 +87,7 @@ end sample(b::Box) = vertices(b) -function faces(b::Box{T}) where {T} +function surfaces(b::Box{T}) where {T} vs = vertices(b) return SVector{6, Quadrangle{T}}( Quadrangle{T}((vs[1], vs[2], vs[3], vs[4])), @@ -100,6 +100,6 @@ function faces(b::Box{T}) where {T} end function distance(b::Box{T}, pt::CartesianPoint{T}) where {T} - planes = Plane.(faces(b)) + planes = Plane.(surfaces(b)) minimum(map(p -> distance(p, pt), planes)) end diff --git a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl index f9c25f08b..a524d0e02 100644 --- a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl @@ -1,5 +1,5 @@ @recipe function f(p::AbstractVolumePrimitive) - fs = faces(p) + fs = surfaces(p) # In principle it would be better to directly get the edges of the primitive # Can be improved later... linecolor --> :black @@ -10,8 +10,8 @@ end @recipe function f(p1::AbstractVolumePrimitive, p2::AbstractVolumePrimitive) - fs1 = faces(p1) - fs2 = faces(p2) + fs1 = surfaces(p1) + fs2 = surfaces(p2) # In principle it would be better to directly get the edges of the primitive # Can be improved later... linecolor --> :black diff --git a/src/SolidStateDetector/DetectorGeometries.jl b/src/SolidStateDetector/DetectorGeometries.jl index 88b88ab5e..fdc7d605c 100644 --- a/src/SolidStateDetector/DetectorGeometries.jl +++ b/src/SolidStateDetector/DetectorGeometries.jl @@ -348,7 +348,7 @@ function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, p # potential[ gridpoint... ] = pot # pointtypes[ gridpoint... ] = zero(PointType) # end - fs = ConstructiveSolidGeometry.faces(contact.geometry) + fs = ConstructiveSolidGeometry.surfaces(contact.geometry) for face in fs paint!(pointtypes, potential, face, contact.geometry, pot, grid) end @@ -416,7 +416,7 @@ function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, p # potential[ gridpoint... ] = pot # pointtypes[ gridpoint... ] = zero(PointType) # end - fs = ConstructiveSolidGeometry.faces(contact.geometry) + fs = ConstructiveSolidGeometry.surfaces(contact.geometry) for face in fs paint!(pointtypes, potential, face, contact.geometry, pot, grid) end From 915400af0b852dc503b85f417b957b5626410a84 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 11 Jun 2021 15:32:04 +0200 Subject: [PATCH 049/241] complexify config file: add translation --- examples/example_config_files/public_CGD_config.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/example_config_files/public_CGD_config.yaml b/examples/example_config_files/public_CGD_config.yaml index c78d4de89..8974fe807 100644 --- a/examples/example_config_files/public_CGD_config.yaml +++ b/examples/example_config_files/public_CGD_config.yaml @@ -67,8 +67,12 @@ detectors: x: from: 4.5 to: 5 - y: 10 + y: + from: 0 + to: 10 z: 10 + translate: + y: -5 surroundings: - name: Base From 78b6038113267fbbd66f3c1462b8daf157ed4054 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 11 Jun 2021 15:33:54 +0200 Subject: [PATCH 050/241] Add `zero` and `scale` methods for points and vectors --- src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl | 2 +- src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl | 4 +++- src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index 4f6a933d1..0f01aaf66 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -16,7 +16,7 @@ module ConstructiveSolidGeometry using DataStructures: OrderedDict - import Base: in, *, +, -, &, size + import Base: in, *, +, -, &, size, zero abstract type AbstractCoordinateSystem end abstract type Cartesian <: AbstractCoordinateSystem end diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl index 8dc4e7209..3fad1c1ef 100644 --- a/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl @@ -20,7 +20,9 @@ struct CartesianPoint{T} <: AbstractCoordinatePoint{T, Cartesian} z::T end -scale(pt::CartesianPoint{T}, s::SVector{3}) where {T} = CartesianPoint{T}(pt.x * s[1], pt.y * s[2], pt.z * s[3]) +zero(PT::AbstractCoordinatePoint{T}) where {T} = PT(zero(T),zero(T),zero(T)) + +scale(pt::CartesianPoint{T}, s::SVector{3}) where {T} = CartesianPoint{T}(pt .* s) @inline _eq_cyl_r(p::CartesianPoint{T}, r::Real) where {T} = hypot(p.x, p.y) == T(r) diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl index 60505191c..f014a61be 100644 --- a/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl @@ -17,6 +17,9 @@ struct CartesianVector{T} <: AbstractCoordinateVector{T, Cartesian} z::T end +zero(VT::AbstractCoordinateVector{T}) where {T} = VT(zero(T),zero(T),zero(T)) + +scale(v::CartesianVector{T}, s::SVector{3}) where {T} = CartesianVector{T}(v .* s) @inline rotate(p::CartesianPoint{T}, r::RotMatrix{3,T,TT}) where {T, TT} = r.mat * p @inline rotate(p::CylindricalPoint{T}, r::RotMatrix{3,T,TT}) where {T, TT} = CylindricalPoint(rotate(CartesianPoint(p), r)) From d884d87ba336aed60b0179470dc745d49f7975a3 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 11 Jun 2021 15:34:47 +0200 Subject: [PATCH 051/241] Change default label in `Contact` plot recipe --- src/PlotRecipes/SolidStateDetector.jl | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/PlotRecipes/SolidStateDetector.jl b/src/PlotRecipes/SolidStateDetector.jl index d58b48e05..c602c5d85 100644 --- a/src/PlotRecipes/SolidStateDetector.jl +++ b/src/PlotRecipes/SolidStateDetector.jl @@ -12,14 +12,7 @@ end @recipe function f(contact::Contact) linecolor --> contact.id - l = contact.name != "" ? contact.name : "Contact $(contact.id)" - label --> l - contact.geometry -end - -@recipe function f(contact::Contact) - linecolor --> contact.id - l = contact.name != "" ? contact.name : "Contact $(contact.id)" + l = contact.name != "" ? "$(contact.name) (id: $(contact.id))" : "Contact - id: $(contact.id)" label --> l contact.geometry end From 8005bc0967fcd3021224e709e8fc65db0b8a1e0b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 11 Jun 2021 15:36:21 +0200 Subject: [PATCH 052/241] Refactor parsing and passing of transformations --- src/ConstructiveSolidGeometry/IO.jl | 45 ++++++++++++------- .../Transformations.jl | 27 ++++++++--- .../VolumePrimitives/Box.jl | 21 +++------ src/SolidStateDetector/Contacts.jl | 6 ++- src/SolidStateDetector/Passive.jl | 6 ++- src/SolidStateDetector/Semiconductor.jl | 7 ++- src/SolidStateDetector/SolidStateDetector.jl | 34 ++++---------- src/SolidStateDetectors.jl | 2 +- 8 files changed, 77 insertions(+), 71 deletions(-) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 84d484749..28433c9d0 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -11,26 +11,35 @@ const CSG_dict = Dict{String, Any}( # "union" => CSGUnion, # "difference" => CSGDifference, # "intersection" => CSGIntersection, - "translate" => CartesianVector, - "rotate" => Rotation, # type from Rotations.jl: Rotation.Rotation - # "scale" => ScaledGeometry ) function get_geometry_key(::Type{T}, dict::AbstractDict, input_units::NamedTuple) where {T} - dict_keys = filter(k -> k in keys(CSG_dict), keys(dict)) - transformations = sort!(filter(k -> - (k == "translate" && !any(broadcast(key -> key in keys(CSG_dict), keys(dict["translate"])))) || - (k == "rotate" && !any(broadcast(key -> key in keys(CSG_dict), keys(dict["rotate"])))), - collect(dict_keys)), - rev = true) #this will ensure that the rotation is parsed first and the translation is parsed second - primitives = setdiff(dict_keys, transformations) - @assert length(primitives) <= 1 "Too many geometry entries in dictionary: $(length(dict_keys))." - @assert length(primitives) >= 1 "None of the entries $(keys(dict)) describes a Geometry." - transformations = broadcast(t -> parse_CSG_transformation(T, dict, CSG_dict[t], input_units), transformations) - first(primitives), isempty(transformations) ? missing : transformations + g = collect(filter(k -> k in keys(CSG_dict), keys(dict))) + @assert !(length(g) > 1) "Too many geometry entries in dictionary: $(length(g))." + @assert !(length(g) == 0) "None of the entries $(keys(dict)) describes a Geometry." + g[1] end +function parse_CSG_transformation(::Type{T}, dict::AbstractDict, input_units::NamedTuple) where {T} + r = if haskey(dict, "rotation") + parse_rotation_vector(T, dict["rotation"], input_units.length) + else + one(SMatrix{3, 3, T, 9}) + end + s = if haskey(dict, "scale") + parse_translate_vector(T, dict["scale"], input_units.length) + else + ones(SVector{3,T}) + end + t = if haskey(dict, "translate") + parse_translate_vector(T, dict["translate"], input_units.length) + else + zero(CartesianVector{T}) + end + (scale = s, rotation = r, translation = t) +end + #### INTERNAL PARSE FUNCTIONS # parses dictionary entries of type Real or String to their value in internal units @@ -188,9 +197,11 @@ end # end -function Geometry(::Type{T}, dict::AbstractDict, input_units::NamedTuple) where {T} - key::String, transformations = get_geometry_key(T, dict, input_units) - transform(Geometry(T, CSG_dict[key], dict[key], input_units), transformations) +function Geometry(::Type{T}, dict::AbstractDict, input_units::NamedTuple, outer_transformations) where {T} + key = get_geometry_key(T, dict, input_units) + inner_transformations = parse_CSG_transformation(T, dict, input_units) + transformations = combine_transformations(inner_transformations, outer_transformations) + Geometry(T, CSG_dict[key], dict[key], input_units, transformations) end diff --git a/src/ConstructiveSolidGeometry/Transformations.jl b/src/ConstructiveSolidGeometry/Transformations.jl index 165d7f33f..e0d35a8a8 100644 --- a/src/ConstructiveSolidGeometry/Transformations.jl +++ b/src/ConstructiveSolidGeometry/Transformations.jl @@ -1,10 +1,27 @@ -transform(csg::G, t) where {G <: AbstractConstructiveGeometry} = G(transform(csg.a, t), transform(csg.b, t)) -transform(csg::G, t::Missing) where {G <: AbstractConstructiveGeometry} = csg +const Transformations{T} = NamedTuple{(:scale, :rotation, :translation), + Tuple{SVector{3, T}, SMatrix{3, 3, T, 9}, CartesianVector{T}}} +# Transformation rule: +# 1. Scale +# 2. Rotate +# 3. Translate -transform(g::AbstractPrimitive, v::AbstractVector) = - length(v) > 1 ? transform(transform(g, v[end]), v[1:end-1]) : transform(g, v[1]) +transform(g::AbstractPrimitive, t::Transformations) = + transform(transform(transform(g, t.scale), t.rotation), t.translation) transform(p::AbstractVolumePrimitive, v::CartesianVector) = p + v transform(p::AbstractVolumePrimitive, r::AbstractMatrix) = r * p transform(p::AbstractVolumePrimitive, s::SVector{3}) = s * p -transform(p::AbstractVolumePrimitive, ::Missing) = p \ No newline at end of file + +transform(csg::G, t::Transformations) where {G <: AbstractConstructiveGeometry} = G(transform(csg.a, t), transform(csg.b, t)) + +# Not sure yet if Rotations will always be of type SMatrix{3, 3, T, 9} -> Any + +function combine_transformations(current::Transformations, new::Transformations) + s = current.scale .* new.scale + t = scale(current.translation, new.scale) + r = new.rotation * current.rotation + t = new.rotation * t + t = t + new.translation + (scale = s, rotation = r, translation = t) +end + diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 0ddb5a37a..ca0d9931b 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -39,7 +39,7 @@ _in(pt::CartesianPoint, b::Box{<:Any, ClosedPrimitive}) = _in(pt::CartesianPoint, b::Box{<:Any, :OpenPrimitive}) = abs(pt.x) < b.hX && abs(pt.y) < b.hY && abs(pt.z) < b.hZ -function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::NamedTuple) where {T} +function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::NamedTuple, transformations) where {T} length_unit = input_units.length x = parse_interval_of_primitive(T, "x", dict, length_unit) y = parse_interval_of_primitive(T, "y", dict, length_unit) @@ -48,28 +48,17 @@ function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::Named μy = typeof(y) <: Real ? zero(T) : mean(y) μz = typeof(z) <: Real ? zero(T) : mean(z) origin = CartesianPoint{T}(μx, μy, μz) - if haskey(dict, "translate") - origin += parse_translate_vector(T, dict["translate"], length_unit) - end - scale = SVector{3, T}(1, 1, 1) - if haskey(dict, "scale") - # scale = parse_translate_vector(T, dict["translate"], length_unit) - @info "Scale not yet implemented" - end - rot = if haskey(dict, "rotation") - parse_rotation_matrix(T, dict["rotate"], length_unit) - else - one(SMatrix{3, 3, T, 9}) - end + scale = ones(SVector{3,T}) hX = typeof(x) <: Real ? x : width(x)/2 hY = typeof(y) <: Real ? y : width(y)/2 hZ = typeof(z) <: Real ? z : width(z)/2 - return Box{T, ClosedPrimitive}( + box = Box{T, ClosedPrimitive}( scale[1] * hX, scale[2] * hY, scale[3] * hZ, - origin, rot + origin ) + transform(box, transformations) end function vertices(b::Box{T}) where {T} diff --git a/src/SolidStateDetector/Contacts.jl b/src/SolidStateDetector/Contacts.jl index 532140d6c..e15354e62 100644 --- a/src/SolidStateDetector/Contacts.jl +++ b/src/SolidStateDetector/Contacts.jl @@ -15,11 +15,13 @@ struct Contact{T,G,MT} <: AbstractContact{T} end -function Contact{T}(dict::Union{Dict{String,Any}, Dict{Any, Any}}, input_units::NamedTuple, transformations = missing)::Contact{T} where {T <: SSDFloat} +function Contact{T}(dict::Union{Dict{String,Any}, Dict{Any, Any}}, input_units::NamedTuple, outer_transformations)::Contact{T} where {T <: SSDFloat} id::Int = haskey(dict, "channel") ? dict["channel"] : -1 material = haskey(dict, "material") ? material_properties[materials[dict["material"]]] : material_properties[materials["HPGe"]] name = haskey(dict,"name") ? dict["name"] : "" - geometry = transform(Geometry(T, dict["geometry"], input_units), transformations) + inner_transformations = parse_CSG_transformation(T, dict, input_units) + transformations = combine_transformations(inner_transformations, outer_transformations) + geometry = Geometry(T, dict["geometry"], input_units, transformations) return Contact( T(dict["potential"]), material, id, name, geometry ) end diff --git a/src/SolidStateDetector/Passive.jl b/src/SolidStateDetector/Passive.jl index ce856217c..f335c1ac5 100644 --- a/src/SolidStateDetector/Passive.jl +++ b/src/SolidStateDetector/Passive.jl @@ -10,7 +10,7 @@ mutable struct Passive{T,G,MT,CDM} <: AbstractPassive{T} geometry::G end -function Passive{T}(dict::Dict, input_units::NamedTuple, transformations = missing) where T <: SSDFloat +function Passive{T}(dict::Dict, input_units::NamedTuple, outer_transformations) where T <: SSDFloat name = haskey(dict, "name") ? dict["name"] : "external part" id::Int = haskey(dict, "id") ? dict["id"] : -1 potential = haskey(dict, "potential") ? T(dict["potential"]) : :floating @@ -29,7 +29,9 @@ function Passive{T}(dict::Dict, input_units::NamedTuple, transformations = missi else ConstantChargeDensity{T}(0) end - geometry = transform(Geometry(T, dict["geometry"], input_units), transformations) + inner_transformations = parse_CSG_transformation(T, dict, input_units) + transformations = combine_transformations(inner_transformations, outer_transformations) + geometry = Geometry(T, dict["geometry"], input_units, transformations) return Passive(name, id, potential, temperature, material, charge_density_model, geometry) end diff --git a/src/SolidStateDetector/Semiconductor.jl b/src/SolidStateDetector/Semiconductor.jl index 570b028a7..4888046d8 100644 --- a/src/SolidStateDetector/Semiconductor.jl +++ b/src/SolidStateDetector/Semiconductor.jl @@ -8,7 +8,7 @@ struct Semiconductor{T,G,MT,CDM,IDM} <: AbstractSemiconductor{T} geometry::G end -function Semiconductor{T}(dict::Dict, input_units::NamedTuple, transformations = missing) where T <: SSDFloat +function Semiconductor{T}(dict::Dict, input_units::NamedTuple, outer_transformations) where T <: SSDFloat impurity_density_model = if haskey(dict, "impurity_density") ImpurityDensity(T, dict["impurity_density"], input_units) elseif haskey(dict, "charge_density_model") @@ -27,7 +27,10 @@ function Semiconductor{T}(dict::Dict, input_units::NamedTuple, transformations = end temperature = haskey(dict, "temperature") ? T(dict["temperature"]) : T(80) material = material_properties[materials[dict["material"]]] - geometry = transform(Geometry(T, dict["geometry"], input_units), transformations) + + inner_transformations = parse_CSG_transformation(T, dict, input_units) + transformations = combine_transformations(inner_transformations, outer_transformations) + geometry = Geometry(T, dict["geometry"], input_units, transformations) return Semiconductor(temperature, material, impurity_density_model, charge_drift_model, geometry) end diff --git a/src/SolidStateDetector/SolidStateDetector.jl b/src/SolidStateDetector/SolidStateDetector.jl index 0c1827166..04e9cd337 100644 --- a/src/SolidStateDetector/SolidStateDetector.jl +++ b/src/SolidStateDetector/SolidStateDetector.jl @@ -15,25 +15,13 @@ end get_precision_type(::SolidStateDetector{T}) where {T} = T -function construct_semiconductor(T, sc::Dict, input_units::NamedTuple, transformations = missing) - Semiconductor{T}(sc, input_units, transformations) -end - -function construct_passive(T, pass::Dict, input_units::NamedTuple, transformations = missing) - Passive{T}(pass, input_units, transformations) -end - -function construct_contact(T, contact::Dict, input_units::NamedTuple, transformations = missing) - Contact{T}(contact, input_units, transformations) -end - -function construct_virtual_volume(T, pass::Dict, input_units::NamedTuple, transformations = missing) +function construct_virtual_volume(T, pass::Dict, input_units::NamedTuple, transformations::Transformations) construct_virtual_volume(T, pass, input_units, Val{Symbol(pass["model"])}, transformations) end -function construct_virtual_volume(T, pass::Dict, input_units::NamedTuple, ::Type{Val{:dead}}, transformations = missing) +function construct_virtual_volume(T, pass::Dict, input_units::NamedTuple, ::Type{Val{:dead}}, transformations::Transformations) DeadVolume{T}(pass, input_units, transformations) end -function construct_virtual_volume(T, pass::Dict, input_units::NamedTuple, ::Type{Val{:arbitrary}}, transformations = missing) +function construct_virtual_volume(T, pass::Dict, input_units::NamedTuple, ::Type{Val{:arbitrary}}, transformations::Transformations) ArbitraryDriftModificationVolume{T}(pass, input_units, transformations) end @@ -112,16 +100,14 @@ end function SolidStateDetector{T}(config_file::Dict, input_units::NamedTuple) where {T <: SSDFloat} if haskey(config_file, "detectors") config_detector = config_file["detectors"][1] # still only one detector - - transformation_keys = filter(k -> k in ("translate", "rotate"), keys(config_detector)) - transformations = broadcast(t -> parse_CSG_transformation(T, config_detector, CSG_dict[t], input_units), transformation_keys) - if isempty(transformations) transformations = missing end + transformations = parse_CSG_transformation(T, config_detector, input_units) + @assert haskey(config_detector, "bulk") "Each detector needs an entry `bulk`. Please define the bulk." - semiconductor = construct_semiconductor(T, config_detector["bulk"], input_units, transformations) + semiconductor = Semiconductor{T}(config_detector["bulk"], input_units, transformations) @assert haskey(config_detector, "contacts") "Each detector needs at least two contacts. Please define the them in the configuration file." - contacts = broadcast(c -> construct_contact(T, c, input_units, transformations), config_detector["contacts"]) + contacts = broadcast(c -> Contact{T}(c, input_units, transformations), config_detector["contacts"]) virtual_drift_volumes = if haskey(config_detector, "virtual_drift_volumes") broadcast(v -> construct_virtual_volume(T, v, input_units, transformations), config_detector["virtual_drift_volumes"]) @@ -131,11 +117,7 @@ function SolidStateDetector{T}(config_file::Dict, input_units::NamedTuple) where end passives = if haskey(config_file, "surroundings") config_surroundings = config_file["surroundings"] - transformation_keys = filter(k -> k in ("translate", "rotate"), keys(config_surroundings)) - transformations = broadcast(t -> parse_CSG_transformation(T, config_surroundings, CSG_dict[t], input_units), transformation_keys) - if isempty(transformations) transformations = missing end - - broadcast(p -> construct_passive(T, p, input_units, transformations), config_file["surroundings"]) + broadcast(p -> Passive{T}(p, input_units, parse_CSG_transformation(T, p, input_units)), config_file["surroundings"]) else missing end diff --git a/src/SolidStateDetectors.jl b/src/SolidStateDetectors.jl index b4fabd965..6810d15ff 100644 --- a/src/SolidStateDetectors.jl +++ b/src/SolidStateDetectors.jl @@ -37,7 +37,7 @@ using .ConstructiveSolidGeometry: AbstractSurfacePrimitive, geom_round, geom_sigdigits, geom_atol_zero, parse_rotation_matrix, parse_translate_vector, parse_CSG_transformation, - transform, CSG_dict + transform, CSG_dict, Transformations, combine_transformations import .ConstructiveSolidGeometry: sample, sample_surface From ad4eebd7f8f17ea01127c5c0d932bcd109a91f99 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 11 Jun 2021 16:14:22 +0200 Subject: [PATCH 053/241] Fix `zero` method definition for points and vectors --- src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl | 2 +- src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl index 3fad1c1ef..bad273774 100644 --- a/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl @@ -20,7 +20,7 @@ struct CartesianPoint{T} <: AbstractCoordinatePoint{T, Cartesian} z::T end -zero(PT::AbstractCoordinatePoint{T}) where {T} = PT(zero(T),zero(T),zero(T)) +zero(PT::Type{<:AbstractCoordinatePoint{T}}) where {T} = PT(zero(T),zero(T),zero(T)) scale(pt::CartesianPoint{T}, s::SVector{3}) where {T} = CartesianPoint{T}(pt .* s) diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl index f014a61be..bcf226066 100644 --- a/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl @@ -17,7 +17,7 @@ struct CartesianVector{T} <: AbstractCoordinateVector{T, Cartesian} z::T end -zero(VT::AbstractCoordinateVector{T}) where {T} = VT(zero(T),zero(T),zero(T)) +zero(VT::Type{<:AbstractCoordinateVector{T}}) where {T} = VT(zero(T),zero(T),zero(T)) scale(v::CartesianVector{T}, s::SVector{3}) where {T} = CartesianVector{T}(v .* s) From 5465ebdc99837ff8464a08df1c72aec90da2f85d Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 11 Jun 2021 16:21:55 +0200 Subject: [PATCH 054/241] Fix read-in of rotations --- src/ConstructiveSolidGeometry/IO.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 28433c9d0..4bdefb177 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -22,13 +22,15 @@ end function parse_CSG_transformation(::Type{T}, dict::AbstractDict, input_units::NamedTuple) where {T} - r = if haskey(dict, "rotation") - parse_rotation_vector(T, dict["rotation"], input_units.length) + r = if haskey(dict, "rotate") + SMatrix{3, 3, T, 9}(parse_rotation_matrix(T, dict["rotate"], input_units.angle)) + # We might want to improve this to avoid numerical precision errors. + # For now this is fine. else one(SMatrix{3, 3, T, 9}) end s = if haskey(dict, "scale") - parse_translate_vector(T, dict["scale"], input_units.length) + error("Not yet implemented") else ones(SVector{3,T}) end From 8395942a9cfe201768f0294398dfeea489189bbb Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 11 Jun 2021 20:04:20 +0200 Subject: [PATCH 055/241] Improve `distance(A::CartesianPoint, l::Line)` --- src/ConstructiveSolidGeometry/LinePrimitives/Line.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl index 3cc9d1546..804bdcccf 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl @@ -6,5 +6,5 @@ end function distance(A::CartesianPoint, l::Line) B = l.origin C = B + l.normal - return norm((A - B) × (C - B)) / norm(C - B) + return norm((A - B) × l.normal) / norm(l.normal) end From b7be5e8f4d0046956b9e94f50d614bfe3dc08a65 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 11 Jun 2021 20:09:00 +0200 Subject: [PATCH 056/241] Rename field `normal` to `direction` in struct `Line` --- src/ConstructiveSolidGeometry/LinePrimitives/Line.jl | 6 +++--- .../SurfacePrimitives/Plane.jl | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl index 804bdcccf..fb20ecb86 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl @@ -1,10 +1,10 @@ struct Line{T} <: AbstractLinePrimitive{T} origin::CartesianPoint{T} - normal::CartesianVector{T} + direction::CartesianVector{T} end function distance(A::CartesianPoint, l::Line) B = l.origin - C = B + l.normal - return norm((A - B) × l.normal) / norm(l.normal) + C = B + l.direction + return norm((A - B) × l.direction) / norm(l.direction) end diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl index 5b3fe4e64..fe7984c02 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl @@ -21,19 +21,19 @@ distance(pt::AbstractCoordinatePoint, p::Plane) = abs(_distance(pt, p)) function evaluate(p::Plane{T}, x, y, ::Val{:xy}) where {T} # plane.normal may not be perpendicular to the z-axis line = Line{T}(CartesianPoint{T}(x, y, zero(T)), CartesianVector{T}(zero(T), zero(T), one(T))) - z = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ line.normal) + z = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ normalize(line.direction)) CartesianPoint{T}(x, y, z) end function evaluate(p::Plane{T}, x, z, ::Val{:xz}) where {T} # plane.normal may not be perpendicular to the y-axis line = Line{T}(CartesianPoint{T}(x, zero(T), z), CartesianVector{T}(zero(T), one(T), zero(T))) - y = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ line.normal) + y = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ normalize(line.direction)) CartesianPoint{T}(x, y, z) end function evaluate(p::Plane{T}, y, z, ::Val{:yz}) where {T} # plane.normal may not be perpendicular to the x-axis line = Line{T}(CartesianPoint{T}(zero(T), y, z), CartesianVector{T}(one(T), zero(T), zero(T))) - x = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ line.normal) + x = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ normalize(line.direction)) CartesianPoint{T}(x, y, z) end @@ -42,7 +42,7 @@ function evaluate(p::Plane{T}, r, φ, ::Val{:rφ}) where {T} # plane.normal may not be perpendicular to the z-axis car_pt = CartesianPoint(CylindricalPoint{T}(r, φ, zero(T))) line = Line{T}(CartesianPoint{T}(car_pt.x, car_pt.y, zero(T)), CartesianVector{T}(zero(T), zero(T), one(T))) - z = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ line.normal) + z = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ normalize(line.direction)) CylindricalPoint(CartesianPoint{T}(car_pt.x, car_pt.y, z)) end function evaluate(p::Plane{T}, r, z, ::Val{:rz}) where {T} @@ -57,6 +57,6 @@ function evaluate(p::Plane{T}, φ, z, ::Val{:φz}) where {T} # plane.normal may not be perpendicular to the z-axis car_pt = CartesianPoint(CylindricalPoint{T}(zero(T), φ, z)) line = Line{T}(CartesianPoint{T}(zero(T), car_pt.y, car_pt.z), CartesianVector(CylindricalVector{T}(one(T), zero(T), zero(T)))) - r = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ line.normal) + r = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ normalize(line.direction)) CylindricalPoint{T}(r, φ, z) end \ No newline at end of file From b3156f80aef64924891b5bbea9aecc4238a3e667 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 12 Jun 2021 10:45:58 +0200 Subject: [PATCH 057/241] Change to a generic implementation for `distance` for volume primitives --- src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl | 4 ---- .../VolumePrimitives/VolumePrimitives.jl | 5 ++++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index ca0d9931b..897729da2 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -88,7 +88,3 @@ function surfaces(b::Box{T}) where {T} ) end -function distance(b::Box{T}, pt::CartesianPoint{T}) where {T} - planes = Plane.(surfaces(b)) - minimum(map(p -> distance(p, pt), planes)) -end diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index 379ce3996..8a6e2f7cb 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -1 +1,4 @@ -include("Box.jl") \ No newline at end of file +include("Box.jl") + +distance(pt::CartesianPoint, b::AbstractVolumePrimitive) = + minimum(map(p -> distance(pt, p), surfaces(b))) From 525563c767763b6776bf6a32b27e1486fa6ef59a Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 12 Jun 2021 11:08:45 +0200 Subject: [PATCH 058/241] Fix cunstructor `Line(e::Edge)` --- src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl index a4731e29b..cbc160df8 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl @@ -5,7 +5,7 @@ end direction(e::Edge) = e.b - e.a -Line(e::Edge) = Line(e.a, direction(e)) +Line(e::Edge{T}) where {T} = Line{T}(e.a, direction(e)) function distance(pt::CartesianPoint{T}, e::Edge{T}) where {T} return if (pt - e.b) ⋅ direction(e) >= 0 From 5fa6a45863a2ff21213c7b6e76b2d45e834a0521 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 12 Jun 2021 11:11:01 +0200 Subject: [PATCH 059/241] Add package PolygonOps --- Project.toml | 2 ++ src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index f0ed11b56..70eb8cf39 100644 --- a/Project.toml +++ b/Project.toml @@ -15,6 +15,7 @@ JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" ParallelProcessingTools = "8e8a01fc-6193-5ca1-a2f1-20776dae4199" +PolygonOps = "647866c9-e3ac-4575-94e7-e3d426903924" ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca" RadiationDetectorSignals = "bf2c0563-65cf-5db2-a620-ceb7de82658c" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" @@ -41,6 +42,7 @@ IntervalSets = "0.3, 0.4, 0.5" JSON = "0.21" LaTeXStrings = "1" ParallelProcessingTools = "0.4" +PolygonOps = "0.1" ProgressMeter = "1.2" RadiationDetectorSignals = "0.1" RecipesBase = "0.7, 0.8, 1.0" diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index 0f01aaf66..80195d6b6 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -8,11 +8,12 @@ module ConstructiveSolidGeometry # # Other Packages using IntervalSets + using PolygonOps using RecipesBase using Rotations using StaticArrays - using Unitful using Statistics + using Unitful using DataStructures: OrderedDict From e710bbd909b8a426696f785a553dbd2155c2e2ad Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 13 Jun 2021 11:14:54 +0200 Subject: [PATCH 060/241] Add example config file for the CGD detector on a cylindrical grid. --- src/examples.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/examples.jl b/src/examples.jl index 1bff85d26..32d262d5c 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -24,6 +24,9 @@ SSD_examples[:BEGe] = ( SSD_examples[:CGD] = ( joinpath(@__DIR__, "../examples/example_config_files/public_CGD_config.yaml") ) +SSD_examples[:CGD_CylGrid] = ( + joinpath(@__DIR__, "../examples/example_config_files/public_CGD_config_cyl_grid.yaml") +) SSD_examples[:Spherical] = ( joinpath(@__DIR__, "../examples/example_config_files/public_spherical_detector_config.json") ) From aa49d367ae8649c5b8e4159a5a739a06dcca33c0 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 13 Jun 2021 11:16:23 +0200 Subject: [PATCH 061/241] Remove code duplication and add docstrings --- .../SurfacePrimitives/Polygon.jl | 99 ++++++++++++------- 1 file changed, 61 insertions(+), 38 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl index feb0e13ec..4f495d28e 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl @@ -105,22 +105,41 @@ function _filter_points(pts::AbstractArray, p::Quadrangle{T}) where {T} filter(pt -> PolygonOps.inpolygon(view(rot * pt, 1:2), pts2d) != 0, pts) end +function get_min_max_index_ranges(a::Union{ + <:Tuple{AbstractVector{<:CartesianPoint{T}}, CartesianTicksTuple{T}}, + <:Tuple{AbstractVector{<:CylindricalPoint{T}}, CylindricalTicksTuple{T}} + }) where {T} + pts, t = a[1], a[2] + ax1, ax2, ax3 = getindex.(pts, 1), getindex.(pts, 2), getindex.(pts, 3) + ax1_min_idx = searchsortedfirst(t[1], minimum(ax1)) + ax2_min_idx = searchsortedfirst(t[2], minimum(ax2)) + ax3_min_idx = searchsortedfirst(t[3], minimum(ax3)) + ax1_max_idx = searchsortedfirst(t[1], maximum(ax1)) + ax2_max_idx = searchsortedfirst(t[2], maximum(ax2)) + ax3_max_idx = searchsortedfirst(t[3], maximum(ax3)) + ls = (length(t[1]), length(t[2]), length(t[3])) + if ax1_max_idx > ls[1] ax1_max_idx = ls[1] end + if ax2_max_idx > ls[2] ax2_max_idx = ls[2] end + if ax3_max_idx > ls[3] ax3_max_idx = ls[3] end + t_idx_range_ax1 = ax1_min_idx:ax1_max_idx + t_idx_range_ax2 = ax2_min_idx:ax2_max_idx + t_idx_range_ax3 = ax3_min_idx:ax3_max_idx + t_idx_range_ax1, t_idx_range_ax2, t_idx_range_ax3 +end + +""" + get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CartesianTicksTuple{T}) where {N, T} + +This function determines the two best dimensions to sample/paint the surface. +E.g. `x` & `y` -> `proj = Val{:xy}()`. +The dimensions are picked such that the number of points to evaluate is minimal. +However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, +because, than, there would not be a single value, but infinite ones, +for `z` in the evalution. +""" function get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CartesianTicksTuple{T}) where {N, T} # This method would actually work for any flat surface, e.g. elipse - xs, ys, zs = getindex.(p.points, 1), getindex.(p.points, 2), getindex.(p.points, 3) - xmin_idx = searchsortedfirst(t[1], minimum(xs)) - ymin_idx = searchsortedfirst(t[2], minimum(ys)) - zmin_idx = searchsortedfirst(t[3], minimum(zs)) - xmax_idx = searchsortedfirst(t[1], maximum(xs)) - ymax_idx = searchsortedfirst(t[2], maximum(ys)) - zmax_idx = searchsortedfirst(t[3], maximum(zs)) - ls = (length(t[1]), length(t[2]), length(t[3])) - if xmax_idx > ls[1] zmax_idx = ls[1] end - if ymax_idx > ls[2] zmax_idx = ls[2] end - if zmax_idx > ls[3] zmax_idx = ls[3] end - t_idx_range_x = xmin_idx:xmax_idx - t_idx_range_y = ymin_idx:ymax_idx - t_idx_range_z = zmin_idx:zmax_idx + t_idx_range_x, t_idx_range_y, t_idx_range_z = get_min_max_index_ranges((p.points, t)) ls = (length(t_idx_range_x), length(t_idx_range_y), length(t_idx_range_z)) ls = ( ls[1] == 1 ? typemax(eltype(ls)) : ls[1], @@ -128,36 +147,33 @@ function get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CartesianTicksTuple{T}) ls[3] == 1 ? typemax(eltype(ls)) : ls[3] ) n = normal(p) - proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && - (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) + proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) Val{:xy}(), t_idx_range_x, t_idx_range_y - elseif ls[1] < ls[2] && ls[3] < ls[2] && - (n ⋅ CartesianVector{T}(zero(T),one(T),zero(T)) != 0) + elseif ls[1] < ls[2] && ls[3] < ls[2] && (n ⋅ CartesianVector{T}(zero(T),one(T),zero(T)) != 0) Val{:xz}(), t_idx_range_x, t_idx_range_z elseif n ⋅ CartesianVector{T}(one(T),zero(T), zero(T)) != 0 Val{:yz}(), t_idx_range_y, t_idx_range_z else error("Sampling Error. Have to extend cases") + # Should never happen. This else case can be removed after testing. end return t1, t2, proj end + + +""" + get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CylindricalTicksTuple{T}) where {N, T} + +This function determines the two best dimensions to sample/paint the surface. +E.g. `r` & `φ` -> `proj = Val{:rφ}()`. +The dimensions are picked such that the number of points to evaluate is minimal. +However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, +because, than, there would not be a single value, but infinite ones, for `z` in the evalution. +The Val{:rz}-case is excluded as there are two crossections with the arc-line and the polygon. +""" function get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CylindricalTicksTuple{T}) where {N, T} # This method would actually work for any flat surface, e.g. elipse - cyls = CylindricalPoint.(p.points) - rs, φs, zs = getindex.(cyls, 1), getindex.(cyls, 2), getindex.(cyls, 3) - rmin_idx = searchsortedfirst(t[1], minimum(rs)) - φmin_idx = searchsortedfirst(t[2], minimum(φs)) - zmin_idx = searchsortedfirst(t[3], minimum(zs)) - rmax_idx = searchsortedfirst(t[1], maximum(rs)) - φmax_idx = searchsortedfirst(t[2], maximum(φs)) - zmax_idx = searchsortedfirst(t[3], maximum(zs)) - ls = (length(t[1]), length(t[2]), length(t[3])) - if rmax_idx > ls[1] rmax_idx = ls[1] end - if φmax_idx > ls[2] φmax_idx = ls[2] end - if zmax_idx > ls[3] zmax_idx = ls[3] end - t_idx_range_r = rmin_idx:rmax_idx - t_idx_range_φ = φmin_idx:φmax_idx - t_idx_range_z = zmin_idx:zmax_idx + t_idx_range_r, t_idx_range_φ, t_idx_range_z = get_min_max_index_ranges((CylindricalPoint.(p.points), t)) ls = (length(t_idx_range_r), length(t_idx_range_φ), length(t_idx_range_z)) ls = ( ls[1] == 1 ? typemax(eltype(ls)) : ls[1], @@ -165,13 +181,20 @@ function get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CylindricalTicksTuple{T ls[3] == 1 ? typemax(eltype(ls)) : ls[3] ) n = normal(p) - proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && - (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) + n_cyl = CylindricalVector{T}(CylindricalPoint(CartesianPoint{T}(n))) + proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) + # evaluate the z value -> same as for the cartesian case Val{:rφ}(), t_idx_range_r, t_idx_range_φ - # elseif ls[1] < ls[2] && ls[3] < ls[2] # for a polygon we do not need Val{:rz} - # Val{:rz}(), t_idx_range_r, t_idx_range_z - else + elseif n_cyl ⋅ CylindricalVector{T}(one(T),zero(T),zero(T)) != 0 + # evaluate the r value Val{:φz}(), t_idx_range_φ, t_idx_range_z + else#if ls[1] < ls[2] && ls[3] < ls[2] && (n ⋅ CylindricalVector{T}(zero(T),one(T),zero(T)) != 0) + # evaluate the φ value -> Issue, there are two solution for φ + # Thus, evaluate(p, r, z, Val{:rz}()) will (or might?) return two points. + # Therefore we try so skip this by not demanding that + # ls[2] < ls[1] && ls[3] < ls[1] for the Val{:φz}()-case. + error("Sampling Error. Have to extend cases") + Val{:rz}(), t_idx_range_r, t_idx_range_z end return t1, t2, proj end From e92e734b328319f2370d244b5d077c90783f41d8 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 13 Jun 2021 11:17:05 +0200 Subject: [PATCH 062/241] Remove obsolete `sample` function --- .../SurfacePrimitives/Polygon.jl | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl index 4f495d28e..d5277970b 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl @@ -198,19 +198,3 @@ function get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CylindricalTicksTuple{T end return t1, t2, proj end - - - - -function sample(p::Polygon{N, T}, t::CartesianTicksTuple{T}) where {N, T} - plane = Plane(p) - t1, t2, proj = get_2d_grid_ticks_and_proj(p, t) - samples = Array{CartesianPoint{T}}(undef, length(t1), length(t2)) - for j in eachindex(t2) - for i in eachindex(t1) - samples[i, j] = evaluate(plane, t1[i], t2[j], proj) - end - end - _filter_points(Base.ReshapedArray(samples, (length(samples),), ()), p) -end - From 4e07dcc6d20362511eb8c3ee78fb9e14c1f41884 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 13 Jun 2021 11:37:03 +0200 Subject: [PATCH 063/241] Bugfix in `paint!`-method for cylindrical coordinates --- src/SolidStateDetector/DetectorGeometries.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/SolidStateDetector/DetectorGeometries.jl b/src/SolidStateDetector/DetectorGeometries.jl index fdc7d605c..392262463 100644 --- a/src/SolidStateDetector/DetectorGeometries.jl +++ b/src/SolidStateDetector/DetectorGeometries.jl @@ -477,13 +477,13 @@ function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, pointtypes[i1, i2, i3] = zero(PointType) potential[i1, i2, i3] = pot_value elseif proj == Val{:φz}() - i3 = searchsortednearest(ticks[2], pt[2]) - pointtypes[i1, i3, i2] = zero(PointType) - potential[i1, i3, i2] = pot_value - else i3 = searchsortednearest(ticks[1], pt[1]) pointtypes[i3, i1, i2] = zero(PointType) potential[i3, i1, i2] = pot_value + else # proj == Val{:rz}() # Do we need this case? I will leave it for now. + i3 = searchsortednearest(ticks[2], pt[2]) + pointtypes[i1, i3, i2] = zero(PointType) + potential[i1, i3, i2] = pot_value end end end From 7a2fc16664d7e8151f74659cd79e4c6e976f9059 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 13 Jun 2021 11:38:41 +0200 Subject: [PATCH 064/241] Clean up comments --- .../SurfacePrimitives/Polygon.jl | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl index d5277970b..8c8770f81 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl @@ -169,7 +169,7 @@ E.g. `r` & `φ` -> `proj = Val{:rφ}()`. The dimensions are picked such that the number of points to evaluate is minimal. However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, because, than, there would not be a single value, but infinite ones, for `z` in the evalution. -The Val{:rz}-case is excluded as there are two crossections with the arc-line and the polygon. +The Val{:rz}-case is excluded as there are two intersections with the arc-line and the polygon. """ function get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CylindricalTicksTuple{T}) where {N, T} # This method would actually work for any flat surface, e.g. elipse @@ -181,20 +181,12 @@ function get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CylindricalTicksTuple{T ls[3] == 1 ? typemax(eltype(ls)) : ls[3] ) n = normal(p) - n_cyl = CylindricalVector{T}(CylindricalPoint(CartesianPoint{T}(n))) - proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) + # We skip the `:rz`-case as there could be two intersections with the arc and the polygon. + proj, t1, t2 = if ls[1] < ls[3] && (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) # evaluate the z value -> same as for the cartesian case Val{:rφ}(), t_idx_range_r, t_idx_range_φ - elseif n_cyl ⋅ CylindricalVector{T}(one(T),zero(T),zero(T)) != 0 - # evaluate the r value + else # evaluate the r value Val{:φz}(), t_idx_range_φ, t_idx_range_z - else#if ls[1] < ls[2] && ls[3] < ls[2] && (n ⋅ CylindricalVector{T}(zero(T),one(T),zero(T)) != 0) - # evaluate the φ value -> Issue, there are two solution for φ - # Thus, evaluate(p, r, z, Val{:rz}()) will (or might?) return two points. - # Therefore we try so skip this by not demanding that - # ls[2] < ls[1] && ls[3] < ls[1] for the Val{:φz}()-case. - error("Sampling Error. Have to extend cases") - Val{:rz}(), t_idx_range_r, t_idx_range_z end return t1, t2, proj end From d0a837831f192cf64eeadcd99acce119ca4317f9 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 13 Jun 2021 13:43:08 +0200 Subject: [PATCH 065/241] Add package Parameters.jl --- Project.toml | 1 + src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl | 1 + 2 files changed, 2 insertions(+) diff --git a/Project.toml b/Project.toml index 70eb8cf39..f1de78ad8 100644 --- a/Project.toml +++ b/Project.toml @@ -15,6 +15,7 @@ JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" ParallelProcessingTools = "8e8a01fc-6193-5ca1-a2f1-20776dae4199" +Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a" PolygonOps = "647866c9-e3ac-4575-94e7-e3d426903924" ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca" RadiationDetectorSignals = "bf2c0563-65cf-5db2-a620-ceb7de82658c" diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index 80195d6b6..8d9aaeedb 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -8,6 +8,7 @@ module ConstructiveSolidGeometry # # Other Packages using IntervalSets + using Parameters using PolygonOps using RecipesBase using Rotations From 8a31ec4d4a01dc5c470339e7dbac6c3ed4c16006 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 13 Jun 2021 13:43:36 +0200 Subject: [PATCH 066/241] Remove obsolete function --- src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl index bcf226066..0a4221bcb 100644 --- a/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl @@ -50,5 +50,4 @@ struct CylindricalVector{T} <: AbstractCoordinateVector{T, Cylindrical} z::T end -CartesianVector(v::CylindricalVector{T}) where {T} = - CartesianVector{T}(CartesianPoint(CylindricalPoint{T}(v))) \ No newline at end of file + From 492b55a83b340faa009bdf2bf0b63e31758fe27a Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 13 Jun 2021 13:44:01 +0200 Subject: [PATCH 067/241] Reduce (future) code duplication --- .../ConstructiveSolidGeometry.jl | 6 --- .../VolumePrimitives/Box.jl | 45 +++++++------------ .../VolumePrimitives/VolumePrimitives.jl | 27 +++++++++-- 3 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index 8d9aaeedb..9d048b6d7 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -50,12 +50,6 @@ module ConstructiveSolidGeometry include("Units.jl") include("PointsAndVectors/PointsAndVectors.jl") - _transform_into_object_coordinate_system(pt::CartesianPoint, p::AbstractVolumePrimitive) = inv(rotation(p)) * (pt - origin(p)) - in(pt::CartesianPoint, p::AbstractVolumePrimitive) = _in(_transform_into_object_coordinate_system(pt, p), p) - in(pt::CylindricalPoint, p::AbstractVolumePrimitive) = in(CartesianPoint(pt), p) - # Do we want to store the rotation matrix permanently in the primitive? - # We should do tests regarding the performance. It can be easily added later. - include("GeometryRounding.jl") include("VolumePrimitives/VolumePrimitives.jl") include("LinePrimitives/LinePrimitives.jl") diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 897729da2..bc0fef59d 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -4,35 +4,22 @@ T: Type of values, e.g. Float64 CO: ClosedPrimitive or OpenPrimitive <-> whether surface belongs to it or not """ -struct Box{T, CO} <: AbstractVolumePrimitive{T, CO} - hX::T - hY::T - hZ::T - origin::CartesianPoint{T} - rotation::SMatrix{3,3,T,9} +@with_kw struct Box{T, CO} <: AbstractVolumePrimitive{T, CO} + hX::T = 1 + hY::T = 1 + hZ::T = 1 + origin::CartesianPoint{T} = zero(CartesianPoint{T}) + rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -Box{T, CO}(hX::Real, hY::Real, hZ::Real) where {T, CO<:Union{ClosedPrimitive, OpenPrimitive}} = - Box{T, CO}(T(hX), T(hY), T(hZ), CartesianPoint{T}(0,0,0), one(SMatrix{3, 3, T, 9})) -Box{T, CO}(hX::Real, hY::Real, hZ::Real, origin::CartesianPoint{T}) where {T, CO} = - Box{T, CO}(T(hX), T(hY), T(hZ), origin, one(SMatrix{3, 3, T, 9})) - -ClosedPrimitive(b::Box{T}) where {T} = Box{T, ClosedPrimitive}(b.hX, b.hY, b.hZ, b.origin, b.rotation) -OpenPrimitive(b::Box{T}) where {T} = Box{T, OpenPrimitive}(b.hX, b.hY, b.hZ, b.origin, b.rotation) +Box{T, CO}( b::Box{T, CO}; + COT = CO, + scale::SVector{3,T} = ones(SVector{3,T}), + origin::CartesianPoint{T} = zero(CartesianPoint{T}), + rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9})) where {T, CO<:Union{ClosedPrimitive, OpenPrimitive}} = + Box{T, COT}(b.hX * scale[1], b.hY * scale[2], b.hZ * scale[3], origin, rotation) extremum(b::Box{T}) where {T} = norm(CartesianPoint{T}(b.hX, b.hY, b.hZ)) -rotation(p::AbstractVolumePrimitive) = p.rotation -origin(p::AbstractVolumePrimitive) = p.origin - -scale(b::Box{T, CO}, s::SVector{3, <:Any}) where {T, CO} = Box{T, CO}( b.hX * s[1], b.hY * s[2], b.hZ * s[3], scale(b.origin, s), b.rotation ) -(*)(s::SVector{3, <:Any}, b::Box) = scale(b, s) - -translate(b::Box{T, CO}, v::CartesianVector) where {T, CO} = Box{T, CO}(b.hX, b.hY, b.hZ, b.origin + v, b.rotation) -(+)(b::Box, v::CartesianVector) = translate(b, v) - -rotate(b::Box{T, CO}, r::AbstractMatrix{T}) where {T, CO} = Box{T, CO}(b.hX, b.hY, b.hZ, r * b.origin, r * b.rotation) -# rotate_aroud_own_center(b::Box{T, CO}, r::AbstractMatrix{T}) where {T, CO} = Box{T, CO}(b.hX, b.hY, b.hZ, b.origin, r * b.rotation) -(*)(r::AbstractMatrix, b::Box) = rotate(b, r) _in(pt::CartesianPoint, b::Box{<:Any, ClosedPrimitive}) = abs(pt.x) <= b.hX && abs(pt.y) <= b.hY && abs(pt.z) <= b.hZ @@ -53,10 +40,10 @@ function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::Named hY = typeof(y) <: Real ? y : width(y)/2 hZ = typeof(z) <: Real ? z : width(z)/2 box = Box{T, ClosedPrimitive}( - scale[1] * hX, - scale[2] * hY, - scale[3] * hZ, - origin + hX = scale[1] * hX, + hY = scale[2] * hY, + hZ = scale[3] * hZ, + origin = origin ) transform(box, transformations) end diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index 8a6e2f7cb..d2af3b20c 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -1,4 +1,25 @@ -include("Box.jl") +ClosedPrimitive(p::VP) where {VP <:AbstractVolumePrimitive} = VP(p, COT = ClosedPrimitive, origin = p.origin, rotation = p.rotation) +OpenPrimitive(p::VP) where {VP <: AbstractVolumePrimitive} = VP(p, COT = OpenPrimitive, origin = p.origin, rotation = p.rotation) -distance(pt::CartesianPoint, b::AbstractVolumePrimitive) = - minimum(map(p -> distance(pt, p), surfaces(b))) +rotation(p::AbstractVolumePrimitive) = p.rotation +origin(p::AbstractVolumePrimitive) = p.origin + +scale(p::VP, s::SVector{3, <:Any}) where {VP <: AbstractVolumePrimitive} = VP(p, scale = s, origin = scale(p.origin, s), rotation = p.rotation) +(*)(s::SVector{3, <:Any}, p::AbstractVolumePrimitive) = scale(p, s) + +rotate(p::VP, r::AbstractMatrix) where {VP <: AbstractVolumePrimitive} = VP(p, origin = r * p.origin, rotation = r * p.rotation) +(*)(r::AbstractMatrix, p::AbstractVolumePrimitive) = rotate(p, r) + +translate(p::VP, v::CartesianVector) where {VP <: AbstractVolumePrimitive} = VP(p, origin = p.origin + v, rotation = p.rotation) +(+)(p::AbstractVolumePrimitive, v::CartesianVector) = translate(p, v) + +distance(pt::CartesianPoint, vp::AbstractVolumePrimitive) = + minimum(map(p -> distance(pt, p), surfaces(vp))) + +_transform_into_object_coordinate_system(pt::CartesianPoint, p::AbstractVolumePrimitive) = inv(rotation(p)) * (pt - origin(p)) +in(pt::CartesianPoint, p::AbstractVolumePrimitive) = _in(_transform_into_object_coordinate_system(pt, p), p) +in(pt::CylindricalPoint, p::AbstractVolumePrimitive) = in(CartesianPoint(pt), p) +# Do we want to store the rotation matrix permanently in the primitive? +# We should do tests regarding the performance. It can be easily added later. + +include("Box.jl") \ No newline at end of file From 7ed19ef71b0eeafda8a56ed556835daccd12fa10 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 13 Jun 2021 13:46:46 +0200 Subject: [PATCH 068/241] Remove obsolete function --- .../SurfacePrimitives/Polygon.jl | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl index 8c8770f81..94625356f 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl @@ -90,21 +90,6 @@ function distance(pt::CartesianPoint, p::Polygon) end end -function _filter_points(pts::AbstractArray, p::Quadrangle{T}) where {T} - # this functions assume that the points, pts, all lie in the plane of the Quadrangle, p - rot = _get_rot_for_rotation_on_xy_plane(p) - vs = vertices(p) - pts2d = SVector{5, SVector{2, T}}( - view(rot * vs[1], 1:2), - view(rot * vs[2], 1:2), - view(rot * vs[3], 1:2), - view(rot * vs[4], 1:2), - view(rot * vs[1], 1:2), - ) - # PolygonOps.inpolygon -> in = 1, on = -1, out = 0) - filter(pt -> PolygonOps.inpolygon(view(rot * pt, 1:2), pts2d) != 0, pts) -end - function get_min_max_index_ranges(a::Union{ <:Tuple{AbstractVector{<:CartesianPoint{T}}, CartesianTicksTuple{T}}, <:Tuple{AbstractVector{<:CylindricalPoint{T}}, CylindricalTicksTuple{T}} From 54ec98a6360e40fb47a3bfcd9a078e70099c011b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 13 Jun 2021 14:22:44 +0200 Subject: [PATCH 069/241] Move application of scaling completely to the constructor. --- src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl | 4 ++-- .../VolumePrimitives/VolumePrimitives.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index bc0fef59d..b5bf6c401 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -14,10 +14,10 @@ end Box{T, CO}( b::Box{T, CO}; COT = CO, - scale::SVector{3,T} = ones(SVector{3,T}), + scaling::SVector{3,T} = ones(SVector{3,T}), origin::CartesianPoint{T} = zero(CartesianPoint{T}), rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9})) where {T, CO<:Union{ClosedPrimitive, OpenPrimitive}} = - Box{T, COT}(b.hX * scale[1], b.hY * scale[2], b.hZ * scale[3], origin, rotation) + Box{T, COT}(b.hX * scaling[1], b.hY * scaling[2], b.hZ * scaling[3], scale(origin, scaling), rotation) extremum(b::Box{T}) where {T} = norm(CartesianPoint{T}(b.hX, b.hY, b.hZ)) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index d2af3b20c..f5f3f398e 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -4,7 +4,7 @@ OpenPrimitive(p::VP) where {VP <: AbstractVolumePrimitive} = VP(p, COT = OpenPri rotation(p::AbstractVolumePrimitive) = p.rotation origin(p::AbstractVolumePrimitive) = p.origin -scale(p::VP, s::SVector{3, <:Any}) where {VP <: AbstractVolumePrimitive} = VP(p, scale = s, origin = scale(p.origin, s), rotation = p.rotation) +scale(p::VP, s::SVector{3, <:Any}) where {VP <: AbstractVolumePrimitive} = VP(p, scaling = s, origin = p.origin, rotation = p.rotation) (*)(s::SVector{3, <:Any}, p::AbstractVolumePrimitive) = scale(p, s) rotate(p::VP, r::AbstractMatrix) where {VP <: AbstractVolumePrimitive} = VP(p, origin = r * p.origin, rotation = r * p.rotation) From f471cc85684d82d9f917952368b22744b43ff7f8 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 14 Jun 2021 09:18:12 +0200 Subject: [PATCH 070/241] Simplify code --- src/ConstructiveSolidGeometry/LinePrimitives/Line.jl | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl index fb20ecb86..1be712b50 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl @@ -3,8 +3,4 @@ struct Line{T} <: AbstractLinePrimitive{T} direction::CartesianVector{T} end -function distance(A::CartesianPoint, l::Line) - B = l.origin - C = B + l.direction - return norm((A - B) × l.direction) / norm(l.direction) -end +distance(pt::CartesianPoint, l::Line) = norm((pt - l.origin) × l.direction) / norm(l.direction) From acac41cf706182d709fefa164dee93f7f555a033 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 14 Jun 2021 10:39:18 +0200 Subject: [PATCH 071/241] Remove `transform` methods and use `translate`, `scale`, `rotate` instead --- src/ConstructiveSolidGeometry/Transformations.jl | 15 ++++++++++----- .../VolumePrimitives/VolumePrimitives.jl | 9 --------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/ConstructiveSolidGeometry/Transformations.jl b/src/ConstructiveSolidGeometry/Transformations.jl index e0d35a8a8..b5b1016e7 100644 --- a/src/ConstructiveSolidGeometry/Transformations.jl +++ b/src/ConstructiveSolidGeometry/Transformations.jl @@ -5,12 +5,17 @@ const Transformations{T} = NamedTuple{(:scale, :rotation, :translation), # 2. Rotate # 3. Translate -transform(g::AbstractPrimitive, t::Transformations) = - transform(transform(transform(g, t.scale), t.rotation), t.translation) +scale(p::VP, s::SVector{3, <:Any}) where {VP <: AbstractVolumePrimitive} = VP(p, scaling = s, origin = p.origin, rotation = p.rotation) +(*)(s::SVector{3, <:Any}, p::AbstractVolumePrimitive) = scale(p, s) + +rotate(p::VP, r::AbstractMatrix) where {VP <: AbstractVolumePrimitive} = VP(p, origin = r * p.origin, rotation = r * p.rotation) +(*)(r::AbstractMatrix, p::AbstractVolumePrimitive) = rotate(p, r) -transform(p::AbstractVolumePrimitive, v::CartesianVector) = p + v -transform(p::AbstractVolumePrimitive, r::AbstractMatrix) = r * p -transform(p::AbstractVolumePrimitive, s::SVector{3}) = s * p +translate(p::VP, v::CartesianVector) where {VP <: AbstractVolumePrimitive} = VP(p, origin = p.origin + v, rotation = p.rotation) +(+)(p::AbstractVolumePrimitive, v::CartesianVector) = translate(p, v) + +transform(g::AbstractPrimitive, t::Transformations) = + translate(rotate(scale(g, t.scale), t.rotation), t.translation) transform(csg::G, t::Transformations) where {G <: AbstractConstructiveGeometry} = G(transform(csg.a, t), transform(csg.b, t)) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index f5f3f398e..3761c2fb3 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -4,15 +4,6 @@ OpenPrimitive(p::VP) where {VP <: AbstractVolumePrimitive} = VP(p, COT = OpenPri rotation(p::AbstractVolumePrimitive) = p.rotation origin(p::AbstractVolumePrimitive) = p.origin -scale(p::VP, s::SVector{3, <:Any}) where {VP <: AbstractVolumePrimitive} = VP(p, scaling = s, origin = p.origin, rotation = p.rotation) -(*)(s::SVector{3, <:Any}, p::AbstractVolumePrimitive) = scale(p, s) - -rotate(p::VP, r::AbstractMatrix) where {VP <: AbstractVolumePrimitive} = VP(p, origin = r * p.origin, rotation = r * p.rotation) -(*)(r::AbstractMatrix, p::AbstractVolumePrimitive) = rotate(p, r) - -translate(p::VP, v::CartesianVector) where {VP <: AbstractVolumePrimitive} = VP(p, origin = p.origin + v, rotation = p.rotation) -(+)(p::AbstractVolumePrimitive, v::CartesianVector) = translate(p, v) - distance(pt::CartesianPoint, vp::AbstractVolumePrimitive) = minimum(map(p -> distance(pt, p), surfaces(vp))) From 122e79c65eb785b7e15606ac251c3fea23e07980 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 14 Jun 2021 11:41:28 +0200 Subject: [PATCH 072/241] Remove `scale`. For proper scaling we would have to add shear modulus to the primitives. Maybe in the future. --- src/ConstructiveSolidGeometry/CSG.jl | 4 --- src/ConstructiveSolidGeometry/IO.jl | 20 ++++++------- .../PointsAndVectors/Points.jl | 2 -- .../PointsAndVectors/Vectors.jl | 30 +++++++++---------- .../Transformations.jl | 21 +++++-------- .../VolumePrimitives/Box.jl | 17 +++++------ .../VolumePrimitives/VolumePrimitives.jl | 4 +-- 7 files changed, 40 insertions(+), 58 deletions(-) diff --git a/src/ConstructiveSolidGeometry/CSG.jl b/src/ConstructiveSolidGeometry/CSG.jl index 78faab1fe..4f86a1776 100644 --- a/src/ConstructiveSolidGeometry/CSG.jl +++ b/src/ConstructiveSolidGeometry/CSG.jl @@ -69,8 +69,4 @@ Geometry(::Type{T}, CSG::Type{<:AbstractConstructiveGeometry}, v::Vector{Any}, i (*)(r::AbstractMatrix, csg::A) where {A <: AbstractConstructiveGeometry} = A(r * csg.a, r * csg.b) -scale(csg::A, s::SVector{3}) where {A <: AbstractConstructiveGeometry} = A(scale(csg.a, s), scale(csg.b, s)) -(*)(s::SVector{3}, csg::A) where {A <: AbstractConstructiveGeometry} = A(scale(csg.a, s), scale(csg.b, s)) -(*)(csg::A, s::SVector{3}) where {A <: AbstractConstructiveGeometry} = A(scale(csg.a, s), scale(csg.b, s)) - surfaces(csg::AbstractConstructiveGeometry) = vcat(surfaces(csg.a)..., surfaces(csg.b)...) \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 4bdefb177..707e5a543 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -29,17 +29,17 @@ function parse_CSG_transformation(::Type{T}, dict::AbstractDict, input_units::Na else one(SMatrix{3, 3, T, 9}) end - s = if haskey(dict, "scale") - error("Not yet implemented") - else - ones(SVector{3,T}) - end + # s = if haskey(dict, "scale") + # _s = parse_scale_vector(T, dict["scale"]) + # else + # ones(SVector{3,T}) + # end t = if haskey(dict, "translate") parse_translate_vector(T, dict["translate"], input_units.length) else zero(CartesianVector{T}) end - (scale = s, rotation = r, translation = t) + (rotation = r, translation = t) end #### INTERNAL PARSE FUNCTIONS @@ -157,10 +157,10 @@ end # translate(transform(Geometry(T, CSG_dict[key], dict[key], input_units), transformations), translate_vector) # end -function parse_scale_vector(::Type{T}, dict::AbstractDict, unit::Unitful.Units)::SVector{3,T} where {T} - x::T = haskey(dict, "x") ? _parse_value(T, dict["x"], unit) : T(1) - y::T = haskey(dict, "y") ? _parse_value(T, dict["y"], unit) : T(1) - z::T = haskey(dict, "z") ? _parse_value(T, dict["z"], unit) : T(1) +function parse_scale_vector(::Type{T}, dict::AbstractDict)::SVector{3,T} where {T} + x::T = haskey(dict, "x") ? _parse_value(T, dict["x"], Unitful.FreeUnits{(), NoDims, nothing}()) : T(1) + y::T = haskey(dict, "y") ? _parse_value(T, dict["y"], Unitful.FreeUnits{(), NoDims, nothing}()) : T(1) + z::T = haskey(dict, "z") ? _parse_value(T, dict["z"], Unitful.FreeUnits{(), NoDims, nothing}()) : T(1) SVector{3,T}(x,y,z) end diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl index bad273774..af6985311 100644 --- a/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/Points.jl @@ -22,8 +22,6 @@ end zero(PT::Type{<:AbstractCoordinatePoint{T}}) where {T} = PT(zero(T),zero(T),zero(T)) -scale(pt::CartesianPoint{T}, s::SVector{3}) where {T} = CartesianPoint{T}(pt .* s) - @inline _eq_cyl_r(p::CartesianPoint{T}, r::Real) where {T} = hypot(p.x, p.y) == T(r) @inline _in_planar_r(p::PlanarPoint, r::Real) = hypot(p.u, p.v) <= r diff --git a/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl b/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl index 0a4221bcb..55c12ad3c 100644 --- a/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl +++ b/src/ConstructiveSolidGeometry/PointsAndVectors/Vectors.jl @@ -19,22 +19,20 @@ end zero(VT::Type{<:AbstractCoordinateVector{T}}) where {T} = VT(zero(T),zero(T),zero(T)) -scale(v::CartesianVector{T}, s::SVector{3}) where {T} = CartesianVector{T}(v .* s) - -@inline rotate(p::CartesianPoint{T}, r::RotMatrix{3,T,TT}) where {T, TT} = r.mat * p -@inline rotate(p::CylindricalPoint{T}, r::RotMatrix{3,T,TT}) where {T, TT} = CylindricalPoint(rotate(CartesianPoint(p), r)) -@inline rotate!(vp::Vector{<:AbstractCoordinatePoint{T}}, r::RotMatrix{3,T,TT}) where {T, TT} = begin for i in eachindex(vp) vp[i] = rotate(vp[i], r) end; vp end -@inline rotate!(vvp::Vector{<:Vector{<:AbstractCoordinatePoint{T}}}, r::RotMatrix{3,T,TT}) where {T, TT} = begin for i in eachindex(vvp) rotate!(vvp[i], r) end; vvp end - -@inline scale(p::CartesianPoint{T}, v::SVector{3,T}) where {T} = p .* v -@inline scale(p::CylindricalPoint{T}, v::SVector{3,T}) where {T} = CylindricalPoint(scale(CartesianPoint(p),v)) -@inline scale!(vp::Vector{<:AbstractCoordinatePoint{T}}, v::SVector{3,T}) where {T} = begin for i in eachindex(vp) vp[i] = scale(vp[i], v) end; vp end -@inline scale!(vvp::Vector{<:Vector{<:AbstractCoordinatePoint{T}}}, v::SVector{3,T}) where {T} = begin for i in eachindex(vvp) scale!(vvp[i], v) end; vvp end - -@inline translate(p::CartesianPoint{T}, v::CartesianVector{T}) where {T} = p + v -@inline translate(p::CylindricalPoint{T}, v::CartesianVector{T}) where {T} = CylindricalPoint(translate(CartesianPoint(p), v)) -@inline translate!(vp::Vector{<:AbstractCoordinatePoint{T}}, v::CartesianVector{T}) where {T} = begin for i in eachindex(vp) vp[i] = translate(vp[i], v) end; vp end -@inline translate!(vvp::Vector{<:Vector{<:AbstractCoordinatePoint{T}}}, v::CartesianVector{T}) where {T} = begin for i in eachindex(vvp) translate!(vvp[i], v) end; vvp end +# @inline rotate(p::CartesianPoint{T}, r::RotMatrix{3,T,TT}) where {T, TT} = r.mat * p +# @inline rotate(p::CylindricalPoint{T}, r::RotMatrix{3,T,TT}) where {T, TT} = CylindricalPoint(rotate(CartesianPoint(p), r)) +# @inline rotate!(vp::Vector{<:AbstractCoordinatePoint{T}}, r::RotMatrix{3,T,TT}) where {T, TT} = begin for i in eachindex(vp) vp[i] = rotate(vp[i], r) end; vp end +# @inline rotate!(vvp::Vector{<:Vector{<:AbstractCoordinatePoint{T}}}, r::RotMatrix{3,T,TT}) where {T, TT} = begin for i in eachindex(vvp) rotate!(vvp[i], r) end; vvp end + +# @inline scale(p::CartesianPoint{T}, v::SVector{3,T}) where {T} = p .* v +# @inline scale(p::CylindricalPoint{T}, v::SVector{3,T}) where {T} = CylindricalPoint(scale(CartesianPoint(p),v)) +# @inline scale!(vp::Vector{<:AbstractCoordinatePoint{T}}, v::SVector{3,T}) where {T} = begin for i in eachindex(vp) vp[i] = scale(vp[i], v) end; vp end +# @inline scale!(vvp::Vector{<:Vector{<:AbstractCoordinatePoint{T}}}, v::SVector{3,T}) where {T} = begin for i in eachindex(vvp) scale!(vvp[i], v) end; vvp end + +# @inline translate(p::CartesianPoint{T}, v::CartesianVector{T}) where {T} = p + v +# @inline translate(p::CylindricalPoint{T}, v::CartesianVector{T}) where {T} = CylindricalPoint(translate(CartesianPoint(p), v)) +# @inline translate!(vp::Vector{<:AbstractCoordinatePoint{T}}, v::CartesianVector{T}) where {T} = begin for i in eachindex(vp) vp[i] = translate(vp[i], v) end; vp end +# @inline translate!(vvp::Vector{<:Vector{<:AbstractCoordinatePoint{T}}}, v::CartesianVector{T}) where {T} = begin for i in eachindex(vvp) translate!(vvp[i], v) end; vvp end """ diff --git a/src/ConstructiveSolidGeometry/Transformations.jl b/src/ConstructiveSolidGeometry/Transformations.jl index b5b1016e7..6000e527b 100644 --- a/src/ConstructiveSolidGeometry/Transformations.jl +++ b/src/ConstructiveSolidGeometry/Transformations.jl @@ -1,12 +1,8 @@ -const Transformations{T} = NamedTuple{(:scale, :rotation, :translation), - Tuple{SVector{3, T}, SMatrix{3, 3, T, 9}, CartesianVector{T}}} +const Transformations{T} = NamedTuple{(:rotation, :translation), Tuple{SMatrix{3, 3, T, 9}, CartesianVector{T}}} # Transformation rule: -# 1. Scale -# 2. Rotate -# 3. Translate - -scale(p::VP, s::SVector{3, <:Any}) where {VP <: AbstractVolumePrimitive} = VP(p, scaling = s, origin = p.origin, rotation = p.rotation) -(*)(s::SVector{3, <:Any}, p::AbstractVolumePrimitive) = scale(p, s) +# 1. Rotate +# 2. Translate +# Not sure yet if Rotations will always be of type SMatrix{3, 3, T, 9} -> Any rotate(p::VP, r::AbstractMatrix) where {VP <: AbstractVolumePrimitive} = VP(p, origin = r * p.origin, rotation = r * p.rotation) (*)(r::AbstractMatrix, p::AbstractVolumePrimitive) = rotate(p, r) @@ -15,18 +11,15 @@ translate(p::VP, v::CartesianVector) where {VP <: AbstractVolumePrimitive} = VP( (+)(p::AbstractVolumePrimitive, v::CartesianVector) = translate(p, v) transform(g::AbstractPrimitive, t::Transformations) = - translate(rotate(scale(g, t.scale), t.rotation), t.translation) + translate(rotate(g, t.rotation), t.translation) transform(csg::G, t::Transformations) where {G <: AbstractConstructiveGeometry} = G(transform(csg.a, t), transform(csg.b, t)) -# Not sure yet if Rotations will always be of type SMatrix{3, 3, T, 9} -> Any function combine_transformations(current::Transformations, new::Transformations) - s = current.scale .* new.scale - t = scale(current.translation, new.scale) r = new.rotation * current.rotation - t = new.rotation * t + t = new.rotation * current.translation t = t + new.translation - (scale = s, rotation = r, translation = t) + (rotation = r, translation = t) end diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index b5bf6c401..77f3f415e 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -12,12 +12,10 @@ CO: ClosedPrimitive or OpenPrimitive <-> whether surface belongs to it or not rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -Box{T, CO}( b::Box{T, CO}; - COT = CO, - scaling::SVector{3,T} = ones(SVector{3,T}), - origin::CartesianPoint{T} = zero(CartesianPoint{T}), - rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9})) where {T, CO<:Union{ClosedPrimitive, OpenPrimitive}} = - Box{T, COT}(b.hX * scaling[1], b.hY * scaling[2], b.hZ * scaling[3], scale(origin, scaling), rotation) +Box{T, CO}( b::Box{T, CO}; COT = CO, + origin::CartesianPoint{T} = b.origin, + rotation::SMatrix{3,3,T,9} = b.rotation) where {T, CO<:Union{ClosedPrimitive, OpenPrimitive}} = + Box{T, COT}(b.hX, b.hY, b.hZ, origin, rotation) extremum(b::Box{T}) where {T} = norm(CartesianPoint{T}(b.hX, b.hY, b.hZ)) @@ -35,14 +33,13 @@ function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::Named μy = typeof(y) <: Real ? zero(T) : mean(y) μz = typeof(z) <: Real ? zero(T) : mean(z) origin = CartesianPoint{T}(μx, μy, μz) - scale = ones(SVector{3,T}) hX = typeof(x) <: Real ? x : width(x)/2 hY = typeof(y) <: Real ? y : width(y)/2 hZ = typeof(z) <: Real ? z : width(z)/2 box = Box{T, ClosedPrimitive}( - hX = scale[1] * hX, - hY = scale[2] * hY, - hZ = scale[3] * hZ, + hX = hX, + hY = hY, + hZ = hZ, origin = origin ) transform(box, transformations) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index 3761c2fb3..fa319eb4a 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -1,5 +1,5 @@ -ClosedPrimitive(p::VP) where {VP <:AbstractVolumePrimitive} = VP(p, COT = ClosedPrimitive, origin = p.origin, rotation = p.rotation) -OpenPrimitive(p::VP) where {VP <: AbstractVolumePrimitive} = VP(p, COT = OpenPrimitive, origin = p.origin, rotation = p.rotation) +ClosedPrimitive(p::VP) where {VP <:AbstractVolumePrimitive} = VP(p, COT = ClosedPrimitive) +OpenPrimitive(p::VP) where {VP <: AbstractVolumePrimitive} = VP(p, COT = OpenPrimitive) rotation(p::AbstractVolumePrimitive) = p.rotation origin(p::AbstractVolumePrimitive) = p.origin From 562369ce5c4aab580b718dd7186dc86d8a404741 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 14 Jun 2021 12:14:13 +0200 Subject: [PATCH 073/241] Enable nested read-in of transformation inside "geometry"-sections of configuration files again. --- .../public_CGD_config.yaml | 16 ++++++------- src/ConstructiveSolidGeometry/IO.jl | 23 ++++++++++++++----- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/examples/example_config_files/public_CGD_config.yaml b/examples/example_config_files/public_CGD_config.yaml index 8974fe807..2d260964e 100644 --- a/examples/example_config_files/public_CGD_config.yaml +++ b/examples/example_config_files/public_CGD_config.yaml @@ -63,16 +63,16 @@ detectors: potential: 0 channel: 2 geometry: - box: - x: - from: 4.5 - to: 5 - y: - from: 0 - to: 10 - z: 10 translate: y: -5 + box: + x: + from: 4.5 + to: 5 + y: + from: 0 + to: 10 + z: 10 surroundings: - name: Base diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 707e5a543..7bebc939a 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -11,6 +11,8 @@ const CSG_dict = Dict{String, Any}( # "union" => CSGUnion, # "difference" => CSGDifference, # "intersection" => CSGIntersection, + "translate" => CartesianVector, # we just ne some type to dispatch on + "rotate" => Rotations.Rotation # we just ne some type to dispatch on ) function get_geometry_key(::Type{T}, dict::AbstractDict, input_units::NamedTuple) where {T} @@ -150,12 +152,13 @@ function parse_CSG_transformation(::Type{T}, dict::AbstractDict, ::Type{Cartesia parse_translate_vector(T, dict["translate"], input_units.length) end -# function Geometry(::Type{T}, ::Type{CartesianVector}, dict::AbstractDict, input_units::NamedTuple) where {T} -# length_unit = input_units.length -# translate_vector::CartesianVector{T} = parse_translate_vector(T, dict, length_unit) -# key::String, transformations = get_geometry_key(T, dict, input_units) -# translate(transform(Geometry(T, CSG_dict[key], dict[key], input_units), transformations), translate_vector) -# end +function Geometry(::Type{T}, ::Type{CartesianVector}, dict::AbstractDict, input_units::NamedTuple, outer_transformations) where {T} + translate_vector = parse_translate_vector(T, dict, input_units.length) + key = get_geometry_key(T, dict, input_units) + inner_transformations = (rotation = one(SMatrix{3, 3, T, 9}), translation = translate_vector) + transformations = combine_transformations(inner_transformations, outer_transformations) + Geometry(T, CSG_dict[key], dict[key], input_units, transformations) +end function parse_scale_vector(::Type{T}, dict::AbstractDict)::SVector{3,T} where {T} x::T = haskey(dict, "x") ? _parse_value(T, dict["x"], Unitful.FreeUnits{(), NoDims, nothing}()) : T(1) @@ -198,6 +201,14 @@ end # rotate(transform(Geometry(T, CSG_dict[key], dict[key], input_units), transformations), rotation_matrix) # end +function Geometry(::Type{T}, ::Type{Rotations.Rotation}, dict::AbstractDict, input_units::NamedTuple, outer_transformations) where {T} + rotation_matrix = SMatrix{3, 3, T, 9}(parse_rotation_matrix(T, dict["rotate"], input_units.angle)) + key = get_geometry_key(T, dict, input_units) + inner_transformations = (rotation = rotation_matrix, translation = zero(CartesianVector{T})) + transformations = combine_transformations(inner_transformations, outer_transformations) + Geometry(T, CSG_dict[key], dict[key], input_units, transformations) +end + function Geometry(::Type{T}, dict::AbstractDict, input_units::NamedTuple, outer_transformations) where {T} key = get_geometry_key(T, dict, input_units) From 9e6f55a215cc912f8b2e9ee953ba5379db246599 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 14 Jun 2021 12:34:21 +0200 Subject: [PATCH 074/241] Change default temperature --- src/SolidStateDetector/Passive.jl | 2 +- src/SolidStateDetector/Semiconductor.jl | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/SolidStateDetector/Passive.jl b/src/SolidStateDetector/Passive.jl index f335c1ac5..6d51d09b0 100644 --- a/src/SolidStateDetector/Passive.jl +++ b/src/SolidStateDetector/Passive.jl @@ -14,8 +14,8 @@ function Passive{T}(dict::Dict, input_units::NamedTuple, outer_transformations) name = haskey(dict, "name") ? dict["name"] : "external part" id::Int = haskey(dict, "id") ? dict["id"] : -1 potential = haskey(dict, "potential") ? T(dict["potential"]) : :floating - temperature = haskey(dict, "temperature") ? T(dict["temperature"]) : T(80) material = material_properties[materials[dict["material"]]] + temperature = haskey(dict, "temperature") ? T(dict["temperature"]) : T(293) charge_density_model = if haskey(dict, "charge_density") ChargeDensity(T, dict["charge_density"], input_units) elseif haskey(dict, "charge_density_model") diff --git a/src/SolidStateDetector/Semiconductor.jl b/src/SolidStateDetector/Semiconductor.jl index 4888046d8..27b32ce79 100644 --- a/src/SolidStateDetector/Semiconductor.jl +++ b/src/SolidStateDetector/Semiconductor.jl @@ -25,9 +25,14 @@ function Semiconductor{T}(dict::Dict, input_units::NamedTuple, outer_transformat else ElectricFieldChargeDriftModel{T}() end - temperature = haskey(dict, "temperature") ? T(dict["temperature"]) : T(80) material = material_properties[materials[dict["material"]]] - + temperature = if haskey(dict, "temperature") + T(dict["temperature"]) + elseif material.name == "High Purity Germanium" + T(78) + else + T(293) + end inner_transformations = parse_CSG_transformation(T, dict, input_units) transformations = combine_transformations(inner_transformations, outer_transformations) geometry = Geometry(T, dict["geometry"], input_units, transformations) From 1936f61559cc34eb3d036d4e5721437dd498adc0 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 14 Jun 2021 13:32:25 +0200 Subject: [PATCH 075/241] Bugfix in parsing of Transformations + Enable CSGDifference in read-in --- .../public_CGD_config.yaml | 25 +++++++++++-------- src/ConstructiveSolidGeometry/CSG.jl | 4 +-- src/ConstructiveSolidGeometry/IO.jl | 19 ++++++++------ .../Transformations.jl | 2 ++ .../VolumePrimitives/Box.jl | 1 + 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/examples/example_config_files/public_CGD_config.yaml b/examples/example_config_files/public_CGD_config.yaml index 2d260964e..3fa795abf 100644 --- a/examples/example_config_files/public_CGD_config.yaml +++ b/examples/example_config_files/public_CGD_config.yaml @@ -24,7 +24,7 @@ detectors: - translate: x: 0 rotate: - Z: 45 + Z: 0 bulk: material: HPGe temperature: 78 @@ -64,15 +64,20 @@ detectors: channel: 2 geometry: translate: - y: -5 - box: - x: - from: 4.5 - to: 5 - y: - from: 0 - to: 10 - z: 10 + y: 0 + difference: + - box: + x: + from: 4.5 + to: 5 + y: 10 + z: 10 + - box: + x: + from: 4 + to: 5.5 + y: 4 + z: 4 surroundings: - name: Base diff --git a/src/ConstructiveSolidGeometry/CSG.jl b/src/ConstructiveSolidGeometry/CSG.jl index 4f86a1776..c6cab420d 100644 --- a/src/ConstructiveSolidGeometry/CSG.jl +++ b/src/ConstructiveSolidGeometry/CSG.jl @@ -57,8 +57,8 @@ in(p::AbstractCoordinatePoint, csg::CSGDifference) = in(p, csg.a) && !in(p, csg. (-)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} = CSGDifference{T,A,B}(a, b) # read-in -function Geometry(::Type{T}, ::Type{CSGDifference}, v::Vector{<:AbstractDict}, input_units::NamedTuple) where {T} - Geometry(T, v[1], input_units) - sum( broadcast(x-> Geometry(T, x, input_units), v[2:end]) ) +function Geometry(::Type{T}, ::Type{CSGDifference}, v::Vector{<:AbstractDict}, input_units::NamedTuple, transformations) where {T} + transform(Geometry(T, v[1], input_units, Transformations{T}()) - sum(broadcast(x-> Geometry(T, x, input_units, Transformations{T}()), v[2:end])), transformations) end Dictionary(g::CSGDifference{T}) where {T} = OrderedDict{String,Any}("difference" => OrderedDict[Dictionary(g.a), Dictionary(g.b)]) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 7bebc939a..bc9cbfb18 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -9,7 +9,7 @@ const CSG_dict = Dict{String, Any}( # "PentagonalPrism" => PentagonalPrism, # "HexagonalPrism" => HexagonalPrism, # "union" => CSGUnion, - # "difference" => CSGDifference, + "difference" => CSGDifference, # "intersection" => CSGIntersection, "translate" => CartesianVector, # we just ne some type to dispatch on "rotate" => Rotations.Rotation # we just ne some type to dispatch on @@ -155,9 +155,9 @@ end function Geometry(::Type{T}, ::Type{CartesianVector}, dict::AbstractDict, input_units::NamedTuple, outer_transformations) where {T} translate_vector = parse_translate_vector(T, dict, input_units.length) key = get_geometry_key(T, dict, input_units) - inner_transformations = (rotation = one(SMatrix{3, 3, T, 9}), translation = translate_vector) - transformations = combine_transformations(inner_transformations, outer_transformations) - Geometry(T, CSG_dict[key], dict[key], input_units, transformations) + # inner_transformations = (rotation = one(SMatrix{3, 3, T, 9}), translation = translate_vector) + # transformations = combine_transformations(inner_transformations, outer_transformations) + Geometry(T, CSG_dict[key], dict[key], input_units, outer_transformations) end function parse_scale_vector(::Type{T}, dict::AbstractDict)::SVector{3,T} where {T} @@ -204,9 +204,7 @@ end function Geometry(::Type{T}, ::Type{Rotations.Rotation}, dict::AbstractDict, input_units::NamedTuple, outer_transformations) where {T} rotation_matrix = SMatrix{3, 3, T, 9}(parse_rotation_matrix(T, dict["rotate"], input_units.angle)) key = get_geometry_key(T, dict, input_units) - inner_transformations = (rotation = rotation_matrix, translation = zero(CartesianVector{T})) - transformations = combine_transformations(inner_transformations, outer_transformations) - Geometry(T, CSG_dict[key], dict[key], input_units, transformations) + Geometry(T, CSG_dict[key], dict[key], input_units, outer_transformations) end @@ -214,6 +212,13 @@ function Geometry(::Type{T}, dict::AbstractDict, input_units::NamedTuple, outer_ key = get_geometry_key(T, dict, input_units) inner_transformations = parse_CSG_transformation(T, dict, input_units) transformations = combine_transformations(inner_transformations, outer_transformations) + if key == "translate" + @show key + @show inner_transformations.translation + @show transformations.translation + @show CSG_dict[key] + println("-...") + end Geometry(T, CSG_dict[key], dict[key], input_units, transformations) end diff --git a/src/ConstructiveSolidGeometry/Transformations.jl b/src/ConstructiveSolidGeometry/Transformations.jl index 6000e527b..4b414b5b1 100644 --- a/src/ConstructiveSolidGeometry/Transformations.jl +++ b/src/ConstructiveSolidGeometry/Transformations.jl @@ -4,6 +4,8 @@ const Transformations{T} = NamedTuple{(:rotation, :translation), Tuple{SMatrix{3 # 2. Translate # Not sure yet if Rotations will always be of type SMatrix{3, 3, T, 9} -> Any +Transformations{T}() where {T} = (rotation = one(SMatrix{3, 3, T, 9}), translation = zero(CartesianVector{T})) + rotate(p::VP, r::AbstractMatrix) where {VP <: AbstractVolumePrimitive} = VP(p, origin = r * p.origin, rotation = r * p.rotation) (*)(r::AbstractMatrix, p::AbstractVolumePrimitive) = rotate(p, r) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 77f3f415e..09c4f94ae 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -36,6 +36,7 @@ function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::Named hX = typeof(x) <: Real ? x : width(x)/2 hY = typeof(y) <: Real ? y : width(y)/2 hZ = typeof(z) <: Real ? z : width(z)/2 + @show origin[2] box = Box{T, ClosedPrimitive}( hX = hX, hY = hY, From 5d09eabc5ee4e02dcd3dccc74118be1729c43c1f Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 14 Jun 2021 13:41:21 +0200 Subject: [PATCH 076/241] Enable CSGUnion & CSGIntersection again and clean up --- .../public_CGD_config.yaml | 21 +++++++++++++------ src/ConstructiveSolidGeometry/CSG.jl | 10 ++++----- src/ConstructiveSolidGeometry/IO.jl | 11 ++-------- .../Transformations.jl | 2 +- .../VolumePrimitives/Box.jl | 1 - 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/examples/example_config_files/public_CGD_config.yaml b/examples/example_config_files/public_CGD_config.yaml index 3fa795abf..0324c15fc 100644 --- a/examples/example_config_files/public_CGD_config.yaml +++ b/examples/example_config_files/public_CGD_config.yaml @@ -52,12 +52,21 @@ detectors: potential: 2000 channel: 1 geometry: - box: - x: - from: -5 - to: -4.5 - y: 10 - z: 10 + union: + - box: + x: + from: -5 + to: -4.5 + y: 10 + z: 10 + - translate: + z: 4.5 + box: + x: + from: -4.5 + to: -4 + y: 10 + z: 1 - material: HPGe name: p+ contact potential: 0 diff --git a/src/ConstructiveSolidGeometry/CSG.jl b/src/ConstructiveSolidGeometry/CSG.jl index c6cab420d..9d212504f 100644 --- a/src/ConstructiveSolidGeometry/CSG.jl +++ b/src/ConstructiveSolidGeometry/CSG.jl @@ -12,8 +12,8 @@ in(p::AbstractCoordinatePoint, csg::CSGUnion) = in(p, csg.a) || in(p, csg.b) (+)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} = CSGUnion{T,A,B}(a, b) # read-in -function Geometry(::Type{T}, t::Type{CSGUnion}, v::Vector{<:AbstractDict}, input_units::NamedTuple) where {T} - sum( broadcast(x-> Geometry(T, x, input_units), v) ) +function Geometry(::Type{T}, t::Type{CSGUnion}, v::Vector{<:AbstractDict}, input_units::NamedTuple, transformations) where {T} + sum( broadcast(x-> Geometry(T, x, input_units, transformations), v) ) end Dictionary(g::CSGUnion{T}) where {T} = OrderedDict{String,Any}("union" => vcat(UnionDictionary(g.a), UnionDictionary(g.b))) @@ -34,8 +34,8 @@ in(p::AbstractCoordinatePoint, csg::CSGIntersection) = in(p, csg.a) && in(p, csg (&)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} = CSGIntersection{T,A,B}(a, b) # read-in -function Geometry(::Type{T}, ::Type{CSGIntersection}, v::Vector{<:AbstractDict}, input_units::NamedTuple) where {T} - parts = broadcast(x-> Geometry(T, x, input_units), v) +function Geometry(::Type{T}, ::Type{CSGIntersection}, v::Vector{<:AbstractDict}, input_units::NamedTuple, transformation) where {T} + parts = broadcast(x-> Geometry(T, x, input_units, transformation), v) reduce(&, parts) end @@ -58,7 +58,7 @@ in(p::AbstractCoordinatePoint, csg::CSGDifference) = in(p, csg.a) && !in(p, csg. # read-in function Geometry(::Type{T}, ::Type{CSGDifference}, v::Vector{<:AbstractDict}, input_units::NamedTuple, transformations) where {T} - transform(Geometry(T, v[1], input_units, Transformations{T}()) - sum(broadcast(x-> Geometry(T, x, input_units, Transformations{T}()), v[2:end])), transformations) + Geometry(T, v[1], input_units, transformations) - sum(broadcast(x-> Geometry(T, x, input_units, transformations), v[2:end])) end Dictionary(g::CSGDifference{T}) where {T} = OrderedDict{String,Any}("difference" => OrderedDict[Dictionary(g.a), Dictionary(g.b)]) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index bc9cbfb18..76b58d135 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -8,9 +8,9 @@ const CSG_dict = Dict{String, Any}( # "SquarePrism" => SquarePrism, # "PentagonalPrism" => PentagonalPrism, # "HexagonalPrism" => HexagonalPrism, - # "union" => CSGUnion, + "union" => CSGUnion, "difference" => CSGDifference, - # "intersection" => CSGIntersection, + "intersection" => CSGIntersection, "translate" => CartesianVector, # we just ne some type to dispatch on "rotate" => Rotations.Rotation # we just ne some type to dispatch on ) @@ -212,13 +212,6 @@ function Geometry(::Type{T}, dict::AbstractDict, input_units::NamedTuple, outer_ key = get_geometry_key(T, dict, input_units) inner_transformations = parse_CSG_transformation(T, dict, input_units) transformations = combine_transformations(inner_transformations, outer_transformations) - if key == "translate" - @show key - @show inner_transformations.translation - @show transformations.translation - @show CSG_dict[key] - println("-...") - end Geometry(T, CSG_dict[key], dict[key], input_units, transformations) end diff --git a/src/ConstructiveSolidGeometry/Transformations.jl b/src/ConstructiveSolidGeometry/Transformations.jl index 4b414b5b1..f7089cb20 100644 --- a/src/ConstructiveSolidGeometry/Transformations.jl +++ b/src/ConstructiveSolidGeometry/Transformations.jl @@ -4,7 +4,7 @@ const Transformations{T} = NamedTuple{(:rotation, :translation), Tuple{SMatrix{3 # 2. Translate # Not sure yet if Rotations will always be of type SMatrix{3, 3, T, 9} -> Any -Transformations{T}() where {T} = (rotation = one(SMatrix{3, 3, T, 9}), translation = zero(CartesianVector{T})) +# Transformations{T}() where {T} = (rotation = one(SMatrix{3, 3, T, 9}), translation = zero(CartesianVector{T})) rotate(p::VP, r::AbstractMatrix) where {VP <: AbstractVolumePrimitive} = VP(p, origin = r * p.origin, rotation = r * p.rotation) (*)(r::AbstractMatrix, p::AbstractVolumePrimitive) = rotate(p, r) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 09c4f94ae..77f3f415e 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -36,7 +36,6 @@ function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::Named hX = typeof(x) <: Real ? x : width(x)/2 hY = typeof(y) <: Real ? y : width(y)/2 hZ = typeof(z) <: Real ? z : width(z)/2 - @show origin[2] box = Box{T, ClosedPrimitive}( hX = hX, hY = hY, From 03d708fb70a65ca2229e763696bcd6a067bab4f3 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 14 Jun 2021 13:46:00 +0200 Subject: [PATCH 077/241] Add rotation of detector again --- examples/example_config_files/public_CGD_config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_config_files/public_CGD_config.yaml b/examples/example_config_files/public_CGD_config.yaml index 0324c15fc..f4821b274 100644 --- a/examples/example_config_files/public_CGD_config.yaml +++ b/examples/example_config_files/public_CGD_config.yaml @@ -24,7 +24,7 @@ detectors: - translate: x: 0 rotate: - Z: 0 + Z: 45 bulk: material: HPGe temperature: 78 From 4481afa87be4be9848901b43961acd3cbd38cbe8 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 14 Jun 2021 13:54:03 +0200 Subject: [PATCH 078/241] Update CGD config file for cylindrical coordinates --- .../public_CGD_config_cyl_grid.yaml | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/examples/example_config_files/public_CGD_config_cyl_grid.yaml b/examples/example_config_files/public_CGD_config_cyl_grid.yaml index c206523c3..42f8d3eaf 100644 --- a/examples/example_config_files/public_CGD_config_cyl_grid.yaml +++ b/examples/example_config_files/public_CGD_config_cyl_grid.yaml @@ -51,23 +51,41 @@ detectors: potential: 2000 channel: 1 geometry: - box: - x: - from: -5 - to: -4.5 - y: 10 - z: 10 + union: + - box: + x: + from: -5 + to: -4.5 + y: 10 + z: 10 + - translate: + z: 4.5 + box: + x: + from: -4.5 + to: -4 + y: 10 + z: 1 - material: HPGe name: p+ contact potential: 0 channel: 2 geometry: - box: - x: - from: 4.5 - to: 5 - y: 10 - z: 10 + translate: + y: 0 + difference: + - box: + x: + from: 4.5 + to: 5 + y: 10 + z: 10 + - box: + x: + from: 4 + to: 5.5 + y: 4 + z: 4 surroundings: - name: Base From c239be2900ead68e85aaf42d45e58aaa3905b610 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 14 Jun 2021 14:05:23 +0200 Subject: [PATCH 079/241] Fix tests --- test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index 753116467..d88cc7ce6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -72,7 +72,7 @@ T = Float32 sim = Simulation{T}(SSD_examples[:CGD]) SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) simulate!(sim, max_refinements = 2, verbose = true) - evt = Event([CartesianPoint{T}(0,0,0)]) + evt = Event([CartesianPoint{T}(5e-3,0,0)]) simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) signalsum = T(0) for i in 1:length(evt.waveforms) From 2379adf9c2c634f7161908288d79f6a5263feb15 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 14 Jun 2021 14:32:50 +0200 Subject: [PATCH 080/241] Move functions --- src/PotentialSimulation/Painting/Painting.jl | 1 + src/PotentialSimulation/Painting/Polygon.jl | 67 ++++++ .../PotentialSimulation.jl | 1 + .../PotentialSimulationSetupRBCartesian3D.jl | 69 ++++++ .../PotentialSimulationSetupRBCylindrical.jl | 70 ++++++ src/SolidStateDetector/DetectorGeometries.jl | 203 ------------------ 6 files changed, 208 insertions(+), 203 deletions(-) create mode 100644 src/PotentialSimulation/Painting/Painting.jl create mode 100644 src/PotentialSimulation/Painting/Polygon.jl diff --git a/src/PotentialSimulation/Painting/Painting.jl b/src/PotentialSimulation/Painting/Painting.jl new file mode 100644 index 000000000..0ab42c88a --- /dev/null +++ b/src/PotentialSimulation/Painting/Painting.jl @@ -0,0 +1 @@ +include("Polygon.jl") \ No newline at end of file diff --git a/src/PotentialSimulation/Painting/Polygon.jl b/src/PotentialSimulation/Painting/Polygon.jl new file mode 100644 index 000000000..a740e0773 --- /dev/null +++ b/src/PotentialSimulation/Painting/Polygon.jl @@ -0,0 +1,67 @@ + +function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, geometry, pot_value, grid::CartesianGrid) + ticks = TicksTuple(grid) + t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) + t1, t2 = if proj == Val{:xy}() + ticks[1], ticks[2] + elseif proj == Val{:xz}() + ticks[1], ticks[3] + else + ticks[2], ticks[3] + end + plane = ConstructiveSolidGeometry.Plane(face) + for i2 in t_idx_r2 + for i1 in t_idx_r1 + pt = ConstructiveSolidGeometry.evaluate(plane, t1[i1], t2[i2], proj) + if pt in geometry + if proj == Val{:xy}() + i3 = searchsortednearest(ticks[3], pt[3]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value + elseif proj == Val{:xz}() + i3 = searchsortednearest(ticks[2], pt[2]) + pointtypes[i1, i3, i2] = zero(PointType) + potential[i1, i3, i2] = pot_value + else + i3 = searchsortednearest(ticks[1], pt[1]) + pointtypes[i3, i1, i2] = zero(PointType) + potential[i3, i1, i2] = pot_value + end + end + end + end + nothing +end +function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, geometry, pot_value, grid::CylindricalGrid) + ticks = TicksTuple(grid) + t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) + t1, t2 = if proj == Val{:rφ}() + ticks[1], ticks[2] + elseif proj == Val{:φz}() + ticks[2], ticks[3] + else + ticks[1], ticks[3] + end + plane = ConstructiveSolidGeometry.Plane(face) + for i2 in t_idx_r2 + for i1 in t_idx_r1 + pt = ConstructiveSolidGeometry.evaluate(plane, t1[i1], t2[i2], proj) + if pt in geometry + if proj == Val{:rφ}() + i3 = searchsortednearest(ticks[3], pt[3]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value + elseif proj == Val{:φz}() + i3 = searchsortednearest(ticks[1], pt[1]) + pointtypes[i3, i1, i2] = zero(PointType) + potential[i3, i1, i2] = pot_value + else # proj == Val{:rz}() # Do we need this case? I will leave it for now. + i3 = searchsortednearest(ticks[2], pt[2]) + pointtypes[i1, i3, i2] = zero(PointType) + potential[i1, i3, i2] = pot_value + end + end + end + end + nothing +end diff --git a/src/PotentialSimulation/PotentialSimulation.jl b/src/PotentialSimulation/PotentialSimulation.jl index 39d96a0af..044ea7d8a 100644 --- a/src/PotentialSimulation/PotentialSimulation.jl +++ b/src/PotentialSimulation/PotentialSimulation.jl @@ -4,6 +4,7 @@ end include("RedBlack/RedBlack.jl") include("GeometricalWeights/GeometricalWeights.jl") +include("Painting/Painting.jl") include("PotentialSimulationSetups/PotentialSimulationSetups.jl") include("EffectiveChargeDensity.jl") diff --git a/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCartesian3D.jl b/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCartesian3D.jl index 52908da5d..5a31f2b7a 100644 --- a/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCartesian3D.jl +++ b/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCartesian3D.jl @@ -1,3 +1,72 @@ +function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, potential::Array{T, N}, + grid::Grid{T, N, Cartesian}, ssd::SolidStateDetector{T}; weighting_potential_contact_id::Union{Missing, Int} = missing)::Nothing where {T <: SSDFloat, N} + + channels::Array{Int, 1} = if !ismissing(weighting_potential_contact_id) + [weighting_potential_contact_id] + else + Int[] + end + + axx::Vector{T} = grid.axes[1].ticks + axy::Vector{T} = grid.axes[2].ticks + axz::Vector{T} = grid.axes[3].ticks + + for iz in axes(potential, 3) + z::T = axz[iz] + for iy in axes(potential, 2) + y::T = axy[iy] + for ix in axes(potential, 1) + x::T = axx[ix] + pt::CartesianPoint{T} = CartesianPoint{T}( x, y, z ) + + for passive in ssd.passives + if passive.potential != :floating + if pt in passive + potential[ ix, iy, iz ] = if ismissing(weighting_potential_contact_id) + passive.potential + else + 0 + end + pointtypes[ ix, iy, iz ] = zero(PointType) + end + end + end + if in(pt, ssd) + pointtypes[ ix, iy, iz ] += pn_junction_bit + end + for contact in ssd.contacts + if pt in contact + potential[ ix, iy, iz ] = if ismissing(weighting_potential_contact_id) + contact.potential + else + contact.id == weighting_potential_contact_id ? 1 : 0 + end + pointtypes[ ix, iy, iz ] = zero(PointType) + end + end + end + end + end + for contact in ssd.contacts + pot::T = if ismissing(weighting_potential_contact_id) + contact.potential + else + contact.id == weighting_potential_contact_id ? 1 : 0 + end + # contact_gridpoints = paint_object(contact, grid) + # for gridpoint in contact_gridpoints + # potential[ gridpoint... ] = pot + # pointtypes[ gridpoint... ] = zero(PointType) + # end + fs = ConstructiveSolidGeometry.surfaces(contact.geometry) + for face in fs + paint!(pointtypes, potential, face, contact.geometry, pot, grid) + end + end + nothing +end + + function PotentialSimulationSetupRB(ssd::SolidStateDetector{T}, grid::Grid{T, 3, Cartesian}, medium::NamedTuple = material_properties[materials["vacuum"]], potential_array::Union{Missing, Array{T, 3}} = missing; weighting_potential_contact_id::Union{Missing, Int} = missing, sor_consts::T = T(1)) where {T}#::PotentialSimulationSetupRB{T} where {T} diff --git a/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCylindrical.jl b/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCylindrical.jl index bb7166c73..66fb018d0 100644 --- a/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCylindrical.jl +++ b/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCylindrical.jl @@ -1,3 +1,73 @@ +function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, potential::Array{T, N}, + grid::Grid{T, N, Cylindrical}, ssd::SolidStateDetector{T}; weighting_potential_contact_id::Union{Missing, Int} = missing)::Nothing where {T <: SSDFloat, N} + + channels::Array{Int, 1} = if !ismissing(weighting_potential_contact_id) + [weighting_potential_contact_id] + else + Int[] + end + + axr::Vector{T} = grid.axes[1].ticks + axφ::Vector{T} = grid.axes[2].ticks + axz::Vector{T} = grid.axes[3].ticks + + for iz in axes(potential, 3) + z::T = axz[iz] + for iφ in axes(potential, 2) + φ::T = axφ[iφ] + for ir in axes(potential, 1) + r::T = axr[ir] + pt::CylindricalPoint{T} = CylindricalPoint{T}( r, φ, z ) + + for passive in ssd.passives + if passive.potential != :floating + if pt in passive + potential[ ir, iφ, iz ] = if ismissing(weighting_potential_contact_id) + passive.potential + else + 0 + end + pointtypes[ ir, iφ, iz ] = zero(PointType) + end + end + end + if in(pt, ssd) + pointtypes[ ir, iφ, iz ] += pn_junction_bit + end + for contact in ssd.contacts + if pt in contact + potential[ ir, iφ, iz ] = if ismissing(weighting_potential_contact_id) + contact.potential + else + contact.id == weighting_potential_contact_id ? 1 : 0 + end + pointtypes[ ir, iφ, iz ] = zero(PointType) + end + end + end + end + end + + for contact in ssd.contacts + pot::T = if ismissing(weighting_potential_contact_id) + contact.potential + else + contact.id == weighting_potential_contact_id ? 1 : 0 + end + # contact_gridpoints = paint_object(contact, grid) + # for gridpoint in contact_gridpoints + # potential[ gridpoint... ] = pot + # pointtypes[ gridpoint... ] = zero(PointType) + # end + fs = ConstructiveSolidGeometry.surfaces(contact.geometry) + for face in fs + paint!(pointtypes, potential, face, contact.geometry, pot, grid) + end + end + nothing +end + + function PotentialSimulationSetupRB(ssd::SolidStateDetector{T}, grid::Grid{T, 3, Cylindrical}, medium::NamedTuple = material_properties[materials["vacuum"]], potential_array::Union{Missing, Array{T, 3}} = missing; sor_consts = (1.0, 1.0), weighting_potential_contact_id::Union{Missing, Int} = missing diff --git a/src/SolidStateDetector/DetectorGeometries.jl b/src/SolidStateDetector/DetectorGeometries.jl index 392262463..04c69e31f 100644 --- a/src/SolidStateDetector/DetectorGeometries.jl +++ b/src/SolidStateDetector/DetectorGeometries.jl @@ -287,209 +287,6 @@ function get_ρ_and_ϵ(pt::AbstractCoordinatePoint{T}, ssd::SolidStateDetector{T return ρ_semiconductor, ϵ, q_eff_fix end -function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, potential::Array{T, N}, - grid::Grid{T, N, Cylindrical}, ssd::SolidStateDetector{T}; weighting_potential_contact_id::Union{Missing, Int} = missing)::Nothing where {T <: SSDFloat, N} - - channels::Array{Int, 1} = if !ismissing(weighting_potential_contact_id) - [weighting_potential_contact_id] - else - Int[] - end - - axr::Vector{T} = grid.axes[1].ticks - axφ::Vector{T} = grid.axes[2].ticks - axz::Vector{T} = grid.axes[3].ticks - - for iz in axes(potential, 3) - z::T = axz[iz] - for iφ in axes(potential, 2) - φ::T = axφ[iφ] - for ir in axes(potential, 1) - r::T = axr[ir] - pt::CylindricalPoint{T} = CylindricalPoint{T}( r, φ, z ) - - for passive in ssd.passives - if passive.potential != :floating - if pt in passive - potential[ ir, iφ, iz ] = if ismissing(weighting_potential_contact_id) - passive.potential - else - 0 - end - pointtypes[ ir, iφ, iz ] = zero(PointType) - end - end - end - if in(pt, ssd) - pointtypes[ ir, iφ, iz ] += pn_junction_bit - end - for contact in ssd.contacts - if pt in contact - potential[ ir, iφ, iz ] = if ismissing(weighting_potential_contact_id) - contact.potential - else - contact.id == weighting_potential_contact_id ? 1 : 0 - end - pointtypes[ ir, iφ, iz ] = zero(PointType) - end - end - end - end - end - - for contact in ssd.contacts - pot::T = if ismissing(weighting_potential_contact_id) - contact.potential - else - contact.id == weighting_potential_contact_id ? 1 : 0 - end - # contact_gridpoints = paint_object(contact, grid) - # for gridpoint in contact_gridpoints - # potential[ gridpoint... ] = pot - # pointtypes[ gridpoint... ] = zero(PointType) - # end - fs = ConstructiveSolidGeometry.surfaces(contact.geometry) - for face in fs - paint!(pointtypes, potential, face, contact.geometry, pot, grid) - end - end - nothing -end - -function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, potential::Array{T, N}, - grid::Grid{T, N, Cartesian}, ssd::SolidStateDetector{T}; weighting_potential_contact_id::Union{Missing, Int} = missing)::Nothing where {T <: SSDFloat, N} - - channels::Array{Int, 1} = if !ismissing(weighting_potential_contact_id) - [weighting_potential_contact_id] - else - Int[] - end - - axx::Vector{T} = grid.axes[1].ticks - axy::Vector{T} = grid.axes[2].ticks - axz::Vector{T} = grid.axes[3].ticks - - for iz in axes(potential, 3) - z::T = axz[iz] - for iy in axes(potential, 2) - y::T = axy[iy] - for ix in axes(potential, 1) - x::T = axx[ix] - pt::CartesianPoint{T} = CartesianPoint{T}( x, y, z ) - - for passive in ssd.passives - if passive.potential != :floating - if pt in passive - potential[ ix, iy, iz ] = if ismissing(weighting_potential_contact_id) - passive.potential - else - 0 - end - pointtypes[ ix, iy, iz ] = zero(PointType) - end - end - end - if in(pt, ssd) - pointtypes[ ix, iy, iz ] += pn_junction_bit - end - for contact in ssd.contacts - if pt in contact - potential[ ix, iy, iz ] = if ismissing(weighting_potential_contact_id) - contact.potential - else - contact.id == weighting_potential_contact_id ? 1 : 0 - end - pointtypes[ ix, iy, iz ] = zero(PointType) - end - end - end - end - end - for contact in ssd.contacts - pot::T = if ismissing(weighting_potential_contact_id) - contact.potential - else - contact.id == weighting_potential_contact_id ? 1 : 0 - end - # contact_gridpoints = paint_object(contact, grid) - # for gridpoint in contact_gridpoints - # potential[ gridpoint... ] = pot - # pointtypes[ gridpoint... ] = zero(PointType) - # end - fs = ConstructiveSolidGeometry.surfaces(contact.geometry) - for face in fs - paint!(pointtypes, potential, face, contact.geometry, pot, grid) - end - end - nothing -end - -function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, geometry, pot_value, grid::CartesianGrid) - ticks = TicksTuple(grid) - t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) - t1, t2 = if proj == Val{:xy}() - ticks[1], ticks[2] - elseif proj == Val{:xz}() - ticks[1], ticks[3] - else - ticks[2], ticks[3] - end - plane = ConstructiveSolidGeometry.Plane(face) - for i2 in t_idx_r2 - for i1 in t_idx_r1 - pt = ConstructiveSolidGeometry.evaluate(plane, t1[i1], t2[i2], proj) - if pt in geometry - if proj == Val{:xy}() - i3 = searchsortednearest(ticks[3], pt[3]) - pointtypes[i1, i2, i3] = zero(PointType) - potential[i1, i2, i3] = pot_value - elseif proj == Val{:xz}() - i3 = searchsortednearest(ticks[2], pt[2]) - pointtypes[i1, i3, i2] = zero(PointType) - potential[i1, i3, i2] = pot_value - else - i3 = searchsortednearest(ticks[1], pt[1]) - pointtypes[i3, i1, i2] = zero(PointType) - potential[i3, i1, i2] = pot_value - end - end - end - end - nothing -end -function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, geometry, pot_value, grid::CylindricalGrid) - ticks = TicksTuple(grid) - t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) - t1, t2 = if proj == Val{:rφ}() - ticks[1], ticks[2] - elseif proj == Val{:φz}() - ticks[2], ticks[3] - else - ticks[1], ticks[3] - end - plane = ConstructiveSolidGeometry.Plane(face) - for i2 in t_idx_r2 - for i1 in t_idx_r1 - pt = ConstructiveSolidGeometry.evaluate(plane, t1[i1], t2[i2], proj) - if pt in geometry - if proj == Val{:rφ}() - i3 = searchsortednearest(ticks[3], pt[3]) - pointtypes[i1, i2, i3] = zero(PointType) - potential[i1, i2, i3] = pot_value - elseif proj == Val{:φz}() - i3 = searchsortednearest(ticks[1], pt[1]) - pointtypes[i3, i1, i2] = zero(PointType) - potential[i3, i1, i2] = pot_value - else # proj == Val{:rz}() # Do we need this case? I will leave it for now. - i3 = searchsortednearest(ticks[2], pt[2]) - pointtypes[i1, i3, i2] = zero(PointType) - potential[i1, i3, i2] = pot_value - end - end - end - end - nothing -end function json_to_dict(inputfile::String)::Dict parsed_json_file = Dict() From 68b2a8898878c8f9fcd9e698dddababbe8ab2ff1 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 08:00:21 +0200 Subject: [PATCH 081/241] Add type annotations `::Transformations{T}` --- src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl | 3 +-- src/ConstructiveSolidGeometry/IO.jl | 6 +++--- src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index 9d048b6d7..7851e47c5 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -49,12 +49,11 @@ module ConstructiveSolidGeometry include("Units.jl") include("PointsAndVectors/PointsAndVectors.jl") - + include("Transformations.jl") include("GeometryRounding.jl") include("VolumePrimitives/VolumePrimitives.jl") include("LinePrimitives/LinePrimitives.jl") include("SurfacePrimitives/SurfacePrimitives.jl") - include("Transformations.jl") include("Intervals.jl") include("CSG.jl") include("IO.jl") diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 76b58d135..651323d7a 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -152,7 +152,7 @@ function parse_CSG_transformation(::Type{T}, dict::AbstractDict, ::Type{Cartesia parse_translate_vector(T, dict["translate"], input_units.length) end -function Geometry(::Type{T}, ::Type{CartesianVector}, dict::AbstractDict, input_units::NamedTuple, outer_transformations) where {T} +function Geometry(::Type{T}, ::Type{CartesianVector}, dict::AbstractDict, input_units::NamedTuple, outer_transformations::Transformations{T}) where {T} translate_vector = parse_translate_vector(T, dict, input_units.length) key = get_geometry_key(T, dict, input_units) # inner_transformations = (rotation = one(SMatrix{3, 3, T, 9}), translation = translate_vector) @@ -201,14 +201,14 @@ end # rotate(transform(Geometry(T, CSG_dict[key], dict[key], input_units), transformations), rotation_matrix) # end -function Geometry(::Type{T}, ::Type{Rotations.Rotation}, dict::AbstractDict, input_units::NamedTuple, outer_transformations) where {T} +function Geometry(::Type{T}, ::Type{Rotations.Rotation}, dict::AbstractDict, input_units::NamedTuple, outer_transformations::Transformations{T}) where {T} rotation_matrix = SMatrix{3, 3, T, 9}(parse_rotation_matrix(T, dict["rotate"], input_units.angle)) key = get_geometry_key(T, dict, input_units) Geometry(T, CSG_dict[key], dict[key], input_units, outer_transformations) end -function Geometry(::Type{T}, dict::AbstractDict, input_units::NamedTuple, outer_transformations) where {T} +function Geometry(::Type{T}, dict::AbstractDict, input_units::NamedTuple, outer_transformations::Transformations{T}) where {T} key = get_geometry_key(T, dict, input_units) inner_transformations = parse_CSG_transformation(T, dict, input_units) transformations = combine_transformations(inner_transformations, outer_transformations) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 77f3f415e..993091d49 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -24,7 +24,7 @@ _in(pt::CartesianPoint, b::Box{<:Any, ClosedPrimitive}) = _in(pt::CartesianPoint, b::Box{<:Any, :OpenPrimitive}) = abs(pt.x) < b.hX && abs(pt.y) < b.hY && abs(pt.z) < b.hZ -function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::NamedTuple, transformations) where {T} +function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::NamedTuple, transformations::Transformations{T}) where {T} length_unit = input_units.length x = parse_interval_of_primitive(T, "x", dict, length_unit) y = parse_interval_of_primitive(T, "y", dict, length_unit) From 52d0f97d330b8f1cc9851f7665560593c94ccf2b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 12:18:56 +0200 Subject: [PATCH 082/241] Add `:rz`-case for painting of a `Polygon` on a cylindrical grid --- .../SurfacePrimitives/Plane.jl | 17 ++---- .../SurfacePrimitives/Polygon.jl | 7 ++- src/PotentialSimulation/Painting/Polygon.jl | 52 ++++++++++++------- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl index fe7984c02..94c1b023c 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl @@ -45,18 +45,9 @@ function evaluate(p::Plane{T}, r, φ, ::Val{:rφ}) where {T} z = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ normalize(line.direction)) CylindricalPoint(CartesianPoint{T}(car_pt.x, car_pt.y, z)) end -function evaluate(p::Plane{T}, r, z, ::Val{:rz}) where {T} - #= - We need a function to calculate the crosssection - of a CylindricalVector{T}(0, 1, 0) with a polygon - =# - φ = 0 - CylindricalPoint{T}(r, φ, z) -end +# function evaluate(p::Plane{T}, r, z, ::Val{:rz}) where {T} +# We don't need this +# end function evaluate(p::Plane{T}, φ, z, ::Val{:φz}) where {T} - # plane.normal may not be perpendicular to the z-axis - car_pt = CartesianPoint(CylindricalPoint{T}(zero(T), φ, z)) - line = Line{T}(CartesianPoint{T}(zero(T), car_pt.y, car_pt.z), CartesianVector(CylindricalVector{T}(one(T), zero(T), zero(T)))) - r = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ normalize(line.direction)) - CylindricalPoint{T}(r, φ, z) + zero(CylindricalPoint{T}) end \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl index 94625356f..739a5d520 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl @@ -166,12 +166,15 @@ function get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CylindricalTicksTuple{T ls[3] == 1 ? typemax(eltype(ls)) : ls[3] ) n = normal(p) + p_r = p.points[findmax(broadcast(p -> abs(p[1]), p.points))[2]] # We skip the `:rz`-case as there could be two intersections with the arc and the polygon. - proj, t1, t2 = if ls[1] < ls[3] && (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) + proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) # evaluate the z value -> same as for the cartesian case Val{:rφ}(), t_idx_range_r, t_idx_range_φ - else # evaluate the r value + elseif ls[2] < ls[1] && ls[3] < ls[1] && (n ⋅ p_r != 0) Val{:φz}(), t_idx_range_φ, t_idx_range_z + else + Val{:rz}(), t_idx_range_r, t_idx_range_z end return t1, t2, proj end diff --git a/src/PotentialSimulation/Painting/Polygon.jl b/src/PotentialSimulation/Painting/Polygon.jl index a740e0773..b4d3097e8 100644 --- a/src/PotentialSimulation/Painting/Polygon.jl +++ b/src/PotentialSimulation/Painting/Polygon.jl @@ -32,7 +32,7 @@ function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, end nothing end -function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, geometry, pot_value, grid::CylindricalGrid) +function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon{<:Any, T}, geometry, pot_value, grid::CylindricalGrid) where {T} ticks = TicksTuple(grid) t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) t1, t2 = if proj == Val{:rφ}() @@ -43,25 +43,41 @@ function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, ticks[1], ticks[3] end plane = ConstructiveSolidGeometry.Plane(face) - for i2 in t_idx_r2 - for i1 in t_idx_r1 - pt = ConstructiveSolidGeometry.evaluate(plane, t1[i1], t2[i2], proj) - if pt in geometry - if proj == Val{:rφ}() - i3 = searchsortednearest(ticks[3], pt[3]) - pointtypes[i1, i2, i3] = zero(PointType) - potential[i1, i2, i3] = pot_value - elseif proj == Val{:φz}() - i3 = searchsortednearest(ticks[1], pt[1]) - pointtypes[i3, i1, i2] = zero(PointType) - potential[i3, i1, i2] = pot_value - else # proj == Val{:rz}() # Do we need this case? I will leave it for now. - i3 = searchsortednearest(ticks[2], pt[2]) - pointtypes[i1, i3, i2] = zero(PointType) - potential[i1, i3, i2] = pot_value + if proj == Val{:rz}() + p_temp = face.points[findmax(broadcast(p -> abs(p[1]), face.points))[2]] + φ1 = CylindricalPoint(p_temp)[2] + φ2 = φ1 < π ? φ1+π : φ1-π + # Here we have to might have to do some modiciation of φ1 and φ2 + # due to the possible periodicity of the grid. + for i2 in t_idx_r2 + for i1 in t_idx_r1 + for φ in (φ1, φ2) + pt = CylindricalPoint{T}(t1[i1], φ, t2[i2]) + if pt in geometry + i3 = searchsortednearest(ticks[2], φ) + pointtypes[i1, i3, i2] = zero(PointType) + potential[i1, i3, i2] = pot_value + end end end end - end + else + for i2 in t_idx_r2 + for i1 in t_idx_r1 + pt = ConstructiveSolidGeometry.evaluate(plane, t1[i1], t2[i2], proj) + if pt in geometry + if proj == Val{:rφ}() + i3 = searchsortednearest(ticks[3], pt[3]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value + elseif proj == Val{:φz}() + i3 = searchsortednearest(ticks[1], pt[1]) + pointtypes[i3, i1, i2] = zero(PointType) + potential[i3, i1, i2] = pot_value + end + end + end + end + end nothing end From 23a52a1a1c99123528cd49ae893970fbf6633c37 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 12:26:00 +0200 Subject: [PATCH 083/241] Rename file: `Arc.jl` -> `Ellipse.jl` --- .../LinePrimitives/{Arc.jl => Ellipse.jl} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/ConstructiveSolidGeometry/LinePrimitives/{Arc.jl => Ellipse.jl} (100%) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Arc.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl similarity index 100% rename from src/ConstructiveSolidGeometry/LinePrimitives/Arc.jl rename to src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl From e4ab532250019ac06437455a8bd8e1f5959022ee Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 14:02:56 +0200 Subject: [PATCH 084/241] Add file `Ellipse.jl` for respective plot recipes and functionalities. --- .../plotting/LinePrimitives/Ellipse.jl | 0 .../plotting/LinePrimitives/LinePrimitives.jl | 5 +++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl diff --git a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl new file mode 100644 index 000000000..e69de29bb diff --git a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/LinePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/LinePrimitives.jl index 213ef2635..ce1070994 100644 --- a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/LinePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/LinePrimitives.jl @@ -1,5 +1,3 @@ -include("Edge.jl") - @recipe function f(ls::AbstractVector{<:AbstractLinePrimitive}) linecolor --> :black @series begin @@ -15,3 +13,6 @@ include("Edge.jl") end end end + +include("Edge.jl") +include("Ellipse.jl") \ No newline at end of file From e40ce8085590f6a76916a4eb556aa35d9c6389ba Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 14:14:45 +0200 Subject: [PATCH 085/241] Generalize transformation between object and global coordinates --- .../ConstructiveSolidGeometry.jl | 10 ++++++++++ src/ConstructiveSolidGeometry/Transformations.jl | 8 ++++---- .../VolumePrimitives/VolumePrimitives.jl | 10 +--------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index 7851e47c5..e0f1a7ab7 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -49,6 +49,16 @@ module ConstructiveSolidGeometry include("Units.jl") include("PointsAndVectors/PointsAndVectors.jl") + + rotation(p::AbstractPrimitive) = p.rotation + origin(p::AbstractPrimitive) = p.origin + _transform_into_global_coordinate_system(pt::CartesianPoint, p::AbstractPrimitive) = (rotation(p) * pt) + origin(p) + _transform_into_object_coordinate_system(pt::CartesianPoint, p::AbstractPrimitive) = inv(rotation(p)) * (pt - origin(p)) + in(pt::CartesianPoint, p::AbstractPrimitive) = _in(_transform_into_object_coordinate_system(pt, p), p) + in(pt::CylindricalPoint, p::AbstractPrimitive) = in(CartesianPoint(pt), p) + # Do we want to store the rotation matrix permanently in the primitive? + # We should do tests regarding the performance. It can be easily added later. + include("Transformations.jl") include("GeometryRounding.jl") include("VolumePrimitives/VolumePrimitives.jl") diff --git a/src/ConstructiveSolidGeometry/Transformations.jl b/src/ConstructiveSolidGeometry/Transformations.jl index f7089cb20..ee3c59c59 100644 --- a/src/ConstructiveSolidGeometry/Transformations.jl +++ b/src/ConstructiveSolidGeometry/Transformations.jl @@ -6,11 +6,11 @@ const Transformations{T} = NamedTuple{(:rotation, :translation), Tuple{SMatrix{3 # Transformations{T}() where {T} = (rotation = one(SMatrix{3, 3, T, 9}), translation = zero(CartesianVector{T})) -rotate(p::VP, r::AbstractMatrix) where {VP <: AbstractVolumePrimitive} = VP(p, origin = r * p.origin, rotation = r * p.rotation) -(*)(r::AbstractMatrix, p::AbstractVolumePrimitive) = rotate(p, r) +rotate(p::P, r::AbstractMatrix) where {P <: AbstractPrimitive} = P(p, origin = r * p.origin, rotation = r * p.rotation) +(*)(r::AbstractMatrix, p::AbstractPrimitive) = rotate(p, r) -translate(p::VP, v::CartesianVector) where {VP <: AbstractVolumePrimitive} = VP(p, origin = p.origin + v, rotation = p.rotation) -(+)(p::AbstractVolumePrimitive, v::CartesianVector) = translate(p, v) +translate(p::P, v::CartesianVector) where {P <: AbstractPrimitive} = P(p, origin = p.origin + v, rotation = p.rotation) +(+)(p::AbstractPrimitive, v::CartesianVector) = translate(p, v) transform(g::AbstractPrimitive, t::Transformations) = translate(rotate(g, t.rotation), t.translation) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index fa319eb4a..cd4d60c97 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -1,16 +1,8 @@ ClosedPrimitive(p::VP) where {VP <:AbstractVolumePrimitive} = VP(p, COT = ClosedPrimitive) OpenPrimitive(p::VP) where {VP <: AbstractVolumePrimitive} = VP(p, COT = OpenPrimitive) -rotation(p::AbstractVolumePrimitive) = p.rotation -origin(p::AbstractVolumePrimitive) = p.origin distance(pt::CartesianPoint, vp::AbstractVolumePrimitive) = - minimum(map(p -> distance(pt, p), surfaces(vp))) - -_transform_into_object_coordinate_system(pt::CartesianPoint, p::AbstractVolumePrimitive) = inv(rotation(p)) * (pt - origin(p)) -in(pt::CartesianPoint, p::AbstractVolumePrimitive) = _in(_transform_into_object_coordinate_system(pt, p), p) -in(pt::CylindricalPoint, p::AbstractVolumePrimitive) = in(CartesianPoint(pt), p) -# Do we want to store the rotation matrix permanently in the primitive? -# We should do tests regarding the performance. It can be easily added later. +minimum(map(p -> distance(pt, p), surfaces(vp))) include("Box.jl") \ No newline at end of file From af8aab050d342b0cb0b3dc0383d05a7d5154bb2f Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 12:31:06 +0200 Subject: [PATCH 086/241] Refactor struct `Arc` to `Ellipse` and include it again --- .../LinePrimitives/Ellipse.jl | 77 +++++++++++-------- .../LinePrimitives/LinePrimitives.jl | 3 +- .../plotting/LinePrimitives/Ellipse.jl | 6 ++ 3 files changed, 52 insertions(+), 34 deletions(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl index 5985fa8bd..f880224b3 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl @@ -1,41 +1,52 @@ -struct Arc{T,TH} <: AbstractLinePrimitive{T} - r::T - center::PlanarPoint{T} - α::TH - function Arc( ::Type{T}, - r::T, - center::PlanarPoint{T}, - α::Union{Nothing, <:AbstractInterval{T}}) where {T} - new{T,typeof(α)}(r, center, α) - end -end +""" + struct Ellipse{T,TR} <: AbstractLinePrimitive{T} + +* `r::TR`: + * TR = Real -> Circle (a = b = r) + * TR = (Real, Real) -> Ellipse (a = r[1], b = r[2]) -function Arc(; r = 0, center = PlanarPoint(0,0), αMin = 0, αMax = 2π) - T = float(promote_type(typeof.((r, αMin, αMax))..., eltype(center))) - α = mod(T(αMax) - T(αMin), T(2π)) == 0 ? nothing : T(αMin)..T(αMax) - Arc(T, T(r), PlanarPoint{T}(center), α) +* `φ::TP`: nothing <-> Full in φ +""" +@with_kw struct Ellipse{T,TR,TP} <: AbstractLinePrimitive{T} + r::TR = 1 + φ::TP = nothing + + origin::CartesianPoint{T} = zero(CartesianPoint{T}) + rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -Arc(r, center, αMin, αMax) = Arc(; r = r, center = center, αMin = αMin, αMax = αMax) +Ellipse{T,TR,TP}( e::Ellipse{T,TR,TP}; + origin::CartesianPoint{T} = b.origin, + rotation::SMatrix{3,3,T,9} = b.rotation) where {T,TR,TP} = + Ellipse{T,TR,TP}(e.r, e.φ, origin, rotation) -Circle(r::T, center::PlanarPoint{T}) where {T} = Arc(T, r, center, nothing) -Circle(a::Arc{T}) where {T} = Arc(T, a.r, a.center, nothing) -get_α_at_u_v(a::Arc{T}, u::Real, v::Real) where {T} = mod(atan(v - a.center.v, u - a.center.u), 2π) #u,v are planar coordinates +# function Arc(; r = 0, center = PlanarPoint(0,0), αMin = 0, αMax = 2π) +# T = float(promote_type(typeof.((r, αMin, αMax))..., eltype(center))) +# α = mod(T(αMax) - T(αMin), T(2π)) == 0 ? nothing : T(αMin)..T(αMax) +# Arc(T, T(r), PlanarPoint{T}(center), α) +# end -get_α_limits(a::Arc{T, Nothing}) where {T} = (T(0), T(2π), true) -get_α_limits(a::Arc{T, <:AbstractInterval}) where {T} = (a.α.left, a.α.right, false) +# Arc(r, center, αMin, αMax) = Arc(; r = r, center = center, αMin = αMin, αMax = αMax) -distance_to_line(point::PlanarPoint{T}, a::Arc{T, Nothing}) where {T} = abs(norm(point - a.center) - a.r) +# Circle(r::T, center::PlanarPoint{T}) where {T} = Arc(T, r, center, nothing) +# Circle(a::Arc{T}) where {T} = Arc(T, a.r, a.center, nothing) -function distance_to_line(point::PlanarPoint{T}, a::Arc{T, <:AbstractInterval})::T where {T} - αMin::T, αMax::T, _ = get_α_limits(a) - p_t = point - a.center - α = atan(p_t.v, p_t.u) - if _in_angular_interval_closed(α, a.α) - return abs(norm(p_t) - a.r) - else - sαNear, cαNear = sincos(_φNear(α, αMin, αMax)) - return norm(p_t - PlanarPoint{T}(a.r*cαNear, a.r*sαNear)) - end -end +# get_α_at_u_v(a::Arc{T}, u::Real, v::Real) where {T} = mod(atan(v - a.center.v, u - a.center.u), 2π) #u,v are planar coordinates + +# get_α_limits(a::Arc{T, Nothing}) where {T} = (T(0), T(2π), true) +# get_α_limits(a::Arc{T, <:AbstractInterval}) where {T} = (a.α.left, a.α.right, false) + +# distance_to_line(point::PlanarPoint{T}, a::Arc{T, Nothing}) where {T} = abs(norm(point - a.center) - a.r) + +# function distance_to_line(point::PlanarPoint{T}, a::Arc{T, <:AbstractInterval})::T where {T} +# αMin::T, αMax::T, _ = get_α_limits(a) +# p_t = point - a.center +# α = atan(p_t.v, p_t.u) +# if _in_angular_interval_closed(α, a.α) +# return abs(norm(p_t) - a.r) +# else +# sαNear, cαNear = sincos(_φNear(α, αMin, αMax)) +# return norm(p_t - PlanarPoint{T}(a.r*cαNear, a.r*sαNear)) +# end +# end diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl b/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl index 4130cb2a0..6bca7ecc2 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/LinePrimitives.jl @@ -1,2 +1,3 @@ include("Line.jl") -include("Edge.jl") \ No newline at end of file +include("Edge.jl") +include("Ellipse.jl") \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl index e69de29bb..151b64363 100644 --- a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl @@ -0,0 +1,6 @@ +function edges(e::Ellipse{T,T,Nothing}; n = 4) where {T} + φs = range(0, stop = 2π, length = n + 1) + pts = [CartesianPoint(CylindricalPoint{T}(e.r, φ, zero(T))) for φ in φs] + pts = map(p -> _transform_into_global_coordinate_system(p, e), pts) + edges = [Edge(pts[i], pts[i+1]) for i in 1:n] +end From c60d39f611551cfd5bdddfe11e993e050e79f9dc Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 14:43:30 +0200 Subject: [PATCH 087/241] Include file `Cone.jl` again --- .../VolumePrimitives/Cone.jl | 414 +++++++++--------- .../VolumePrimitives/VolumePrimitives.jl | 3 +- 2 files changed, 209 insertions(+), 208 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index f751a0f1e..87ae45cde 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -1,207 +1,207 @@ -struct Cone{T,TR,TP,TZ} <: AbstractVolumePrimitive{T} - r::TR #if not a Tuple, then Cone is a Tube - φ::TP - z::TZ - #if r is a Tuple, the first entry refers to the r-interval at the bottom, the second one to the r-interval at the top - function Cone( ::Type{T}, - r::Union{T, <:AbstractInterval{T}, Tuple{T,T}, Tuple{I,I}}, - φ::Union{Nothing, <:AbstractInterval{T}}, - z::Union{T, <:AbstractInterval{T}}) where {T, I<:AbstractInterval{T}} - new{T,typeof(r),typeof(φ),typeof(z)}(r, φ, z) - end -end - -#Constructors -function Cone(;rbotMin = 0, rbotMax = 1, rtopMin = 0, rtopMax = 1, φMin = 0, φMax = 2π, zMin = -1/2, zMax = 1/2) - T = float(promote_type(typeof.((rtopMin, rtopMax, rbotMin, rbotMax, φMin, φMax, zMin, zMax))...)) - rMin_is_equal::Bool = rbotMin == rtopMin - rMax_is_equal::Bool = rbotMax == rtopMax - rMin_is_zero::Bool = rMin_is_equal && rbotMin == 0 - r = if rMax_is_equal - if rMin_is_zero # Tube with rMin = 0 - T(rbotMax) - elseif rMin_is_equal # Tube - T(rbotMin)..T(rbotMax) - else # Cone - (T(rbotMin)..T(rbotMax), T(rtopMin)..T(rtopMax)) - end - elseif rMin_is_zero #Cone with rMin = 0 - (T(rbotMax), T(rtopMax)) - else # Cone - (T(rbotMin)..T(rbotMax), T(rtopMin)..T(rtopMax)) - end - φ = mod(T(φMax) - T(φMin), T(2π)) == 0 ? nothing : T(φMin)..T(φMax) - z = zMax == -zMin ? T(zMax) : T(zMin)..T(zMax) - Cone( T, r, φ, z) -end -Cone(rbotMin, rbotMax, rtopMin, rtopMax, φMin, φMax, zMin, zMax) = Cone(; rbotMin = rbotMin, rbotMax = rbotMax, rtopMin = rtopMin, rtopMax = rtopMax, φMin = φMin, φMax = φMax, zMin = zMin, zMax = zMax) - -function Cone(rbot::R1, rtop::R2, height::H) where {R1<:Real, R2<:Real, H<:Real} - T = float(promote_type(R1, R2, H)) - Cone( T, (T(rbot), T(rtop)), nothing, T(height)/2) -end - - -#Constructors for Tubes -Tube(;rMin = 0, rMax = 1, φMin = 0, φMax = 2π, zMin = -1/2, zMax = 1/2) = Cone(rMin, rMax, rMin, rMax, φMin, φMax, zMin, zMax) -Tube(rMin, rMax, φMin, φMax, zMin, zMax) = Tube(; rMin = rMin, rMax = rMax, φMin = φMin, φMax = φMax, zMin = zMin, zMax = zMax) - -function Tube(r::R, height::H) where {R<:Real, H<:Real} - T = float(promote_type(R,H)) - Cone(T, T(r), nothing, T(height)/2) -end - -function Tube(rMin::R1, rMax::R2, height::H) where {R1<:Real, R2<:Real, H<:Real} - T = float(promote_type(R1,R2,H)) - Cone(T, rMin == 0 ? T(rMax) : T(rMin)..T(rMax), nothing, T(height)/2) -end - -# for Tubes -get_r_at_z(c::Cone{T, <:Union{T, AbstractInterval{T}}, <:Any, <:Any}, z::Real) where {T} = c.r - -# for Cones -get_r_at_z(c::Cone{T, Tuple{T,T}, <:Any, <:Any}, z::Real) where {T} = _get_r_at_z(c.r[1], c.r[2], c.z, z) - -function get_r_at_z(c::Cone{T, Tuple{I,I}, <:Any, <:Any}, z::Real) where {T, I<:AbstractInterval{T}} - r1::T = _get_r_at_z(c.r[1].left, c.r[2].left, c.z, z) - r2::T = _get_r_at_z(c.r[1].right, c.r[2].right, c.z, z) - r1..r2 -end - -function _get_r_at_z(rbot::TR, rtop::TR, cz::TZ, z::Real)::TR where {TR<:Real, TZ} - (rtop - rbot) * (z - _left_linear_interval(cz)) / _width_linear_interval(cz) + rbot -end - - -in(p::AbstractCoordinatePoint, c::Cone{<:Any, <:Any, Nothing, <:Any}) = - _in_z(p, c.z) && _in_cyl_r(p, get_r_at_z(c, p.z)) - -in(p::AbstractCoordinatePoint, c::Cone{<:Any, <:Any, <:AbstractInterval, <:Any}) = - _in_z(p, c.z) && _in_φ(p, c.φ) && _in_cyl_r(p, get_r_at_z(c, p.z)) - -# read-in -function Geometry(::Type{T}, t::Union{Type{Cone}, Type{Tube}}, dict::AbstractDict, input_units::NamedTuple) where {T} - length_unit = input_units.length - angle_unit = input_units.angle - r = parse_r_of_primitive(T, dict, length_unit) - φ = parse_φ_of_primitive(T, dict, angle_unit) - z = parse_height_of_primitive(T, dict, length_unit) - return Cone(T, r, φ, z) -end - -function Dictionary(g::Cone{T,<:Union{T, AbstractInterval}}) where {T} - dict = OrderedDict{String,Any}() - dict["r"] = typeof(g.r) == T ? g.r : OrderedDict{String,Any}("from" => g.r.left, "to" => g.r.right) - if !isnothing(g.φ) dict["phi"] = OrderedDict{String,Any}("from" => g.φ.left, "to" => g.φ.right) end - typeof(g.z) == T ? dict["h"] = g.z * 2 : dict["z"] = OrderedDict{String,Any}("from" => g.z.left, "to" => g.z.right) - OrderedDict{String,Any}("tube" => dict) -end - -function Dictionary(g::Cone{T,<:Tuple}) where {T} - dict = OrderedDict{String,Any}() - dict["r"] = OrderedDict{String,Any}() - dict["r"]["bottom"] = typeof(g.r[1]) == T ? g.r[1] : OrderedDict{String,Any}("from" => g.r[1].left, "to" => g.r[1].right) - dict["r"]["top"] = typeof(g.r[2]) == T ? g.r[2] : OrderedDict{String,Any}("from" => g.r[2].left, "to" => g.r[2].right) - if !isnothing(g.φ) dict["phi"] = OrderedDict{String,Any}("from" => g.φ.left, "to" => g.φ.right) end - typeof(g.z) == T ? dict["h"] = g.z * 2 : dict["z"] = OrderedDict{String,Any}("from" => g.z.left, "to" => g.z.right) - OrderedDict{String,Any}("cone" => dict) -end - - -get_r_limits(c::Cone{T, <:Union{T, AbstractInterval{T}}, <:Any, <:Any}) where {T} = - (_left_radial_interval(c.r),_right_radial_interval(c.r),_left_radial_interval(c.r),_right_radial_interval(c.r)) -get_r_limits(c::Cone{T, <:Tuple, <:Any, <:Any}) where {T} = - (_left_radial_interval(c.r[1]),_right_radial_interval(c.r[1]),_left_radial_interval(c.r[2]),_right_radial_interval(c.r[2])) - -get_φ_limits(c::Cone{T, <:Any, Nothing, <:Any}) where {T} = (T(0), T(2π), true) -get_φ_limits(c::Cone{T, <:Any, <:AbstractInterval, <:Any}) where {T} = (c.φ.left, c.φ.right, false) - -get_z_limits(c::Cone{T}) where {T} = (_left_linear_interval(c.z), _right_linear_interval(c.z)) - -function _is_cone_collapsed(rbotMin::T, rbotMax::T, rtopMin::T, rtopMax::T, zMin::T, zMax::T) where {T} - tol = geom_atol_zero(T) - (isapprox(rbotMin, rbotMax, atol = tol) && isapprox(rtopMin, rtopMax, atol = tol)) || isapprox(zMin, zMax, atol = tol) -end - -function _get_decomposed_surfaces_cone(c::Cone{T}, rbotMin::T, rbotMax::T, rtopMin::T, rtopMax::T, zMin::T, zMax::T) where {T} - surfaces = AbstractSurfacePrimitive[] - #top and bottom annulus - tol = geom_atol_zero(T) - if !isapprox(rbotMin, rbotMax, atol = tol) - push!(surfaces, CylindricalAnnulus(c, z = zMin)) - end - if !isapprox(zMin, zMax, atol = tol) - if !isapprox(rtopMin, rtopMax, atol = tol) - push!(surfaces, CylindricalAnnulus(c, z = zMax)) - end - #outer conemantle - push!(surfaces, ConeMantle(c, rbot = rbotMax, rtop = rtopMax)) - end - surfaces -end - -#2π Cones -function get_decomposed_surfaces(c::Cone{T, <:Union{T, Tuple{T,T}}, Nothing, <:Any}) where {T} - rbotMin::T, rbotMax::T, rtopMin::T, rtopMax::T = get_r_limits(c) - zMin::T, zMax::T = get_z_limits(c) - _get_decomposed_surfaces_cone(c, rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) -end - -function get_decomposed_surfaces(c::Cone{T, <:Union{<:AbstractInterval{T}, Tuple{I,I}}, Nothing, <:Any}) where {T, I<:AbstractInterval{T}} - rbotMin::T, rbotMax::T, rtopMin::T, rtopMax::T = get_r_limits(c) - zMin::T, zMax::T = get_z_limits(c) - surfaces = _get_decomposed_surfaces_cone(c, rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) - if !_is_cone_collapsed(rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) - push!(surfaces, ConeMantle(c, rbot = rbotMin, rtop = rtopMin)) - end - surfaces -end - -#non 2π Cones -function get_decomposed_surfaces(c::Cone{T, <:Union{T, Tuple{T,T}}, <:AbstractInterval{T}, <:Any}) where {T} - rbotMin::T, rbotMax::T, rtopMin::T, rtopMax::T = get_r_limits(c) - zMin::T, zMax::T = get_z_limits(c) - φMin::T, φMax::T, _ = get_φ_limits(c) - surfaces = _get_decomposed_surfaces_cone(c, rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) - if !_is_cone_collapsed(rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) - push!(surfaces, ConalPlane(c, φ = φMin), ConalPlane(c, φ = φMax)) - end - surfaces -end - -function get_decomposed_surfaces(c::Cone{T, <:Union{<:AbstractInterval{T}, Tuple{I,I}}, <:AbstractInterval{T}, <:Any}) where {T, I<:AbstractInterval{T}} - rbotMin::T, rbotMax::T, rtopMin::T, rtopMax::T = get_r_limits(c) - zMin::T, zMax::T = get_z_limits(c) - φMin::T, φMax::T, _ = get_φ_limits(c) - surfaces = _get_decomposed_surfaces_cone(c, rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) - if !_is_cone_collapsed(rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) - push!(surfaces, ConalPlane(c, φ = φMin), ConalPlane(c, φ = φMax)) - push!(surfaces, ConeMantle(c, rbot = rbotMin, rtop = rtopMin)) - end - surfaces -end - -function sample(c::Cone{T}, step::Real)::Vector{CylindricalPoint{T}} where {T} - zMin::T, zMax::T = get_z_limits(c) - φMin::T, φMax::T, _ = get_φ_limits(c) - samples = [ - CylindricalPoint{T}(r,φ,z) - for z in zMin:step:zMax - for r in _left_radial_interval(get_r_at_z(c, z)):step:_right_radial_interval(get_r_at_z(c, z)) - for φ in (r == 0 ? φMin : φMin:step/r:φMax) - ] -end - -function sample(c::Cone{T}, Nsamps::NTuple{3,Int})::Vector{CylindricalPoint{T}} where {T} - zMin::T, zMax::T = get_z_limits(c) - φMin::T, φMax::T, _ = get_φ_limits(c) - samples = [ - CylindricalPoint{T}(r,φ,z) - for z in (Nsamps[3] ≤ 1 ? zMin : range(zMin, zMax, length = Nsamps[3])) - for r in (Nsamps[1] ≤ 1 ? _left_radial_interval(get_r_at_z(c, z)) : range(_left_radial_interval(get_r_at_z(c, z)), _right_radial_interval(get_r_at_z(c, z)), length = Nsamps[1])) - for φ in (Nsamps[2] ≤ 1 ? φMin : range(φMin, φMax, length = Nsamps[2])) - ] -end - -@inline sample(c::Cone{T}) where {T} = sample(c, (2,3,3)) -@inline sample(c::Cone{T, <:Any, Nothing}) where {T} = sample(c, (2,5,3)) +# struct Cone{T,TR,TP,TZ} <: AbstractVolumePrimitive{T} +# r::TR #if not a Tuple, then Cone is a Tube +# φ::TP +# z::TZ +# #if r is a Tuple, the first entry refers to the r-interval at the bottom, the second one to the r-interval at the top +# function Cone( ::Type{T}, +# r::Union{T, <:AbstractInterval{T}, Tuple{T,T}, Tuple{I,I}}, +# φ::Union{Nothing, <:AbstractInterval{T}}, +# z::Union{T, <:AbstractInterval{T}}) where {T, I<:AbstractInterval{T}} +# new{T,typeof(r),typeof(φ),typeof(z)}(r, φ, z) +# end +# end + +# #Constructors +# function Cone(;rbotMin = 0, rbotMax = 1, rtopMin = 0, rtopMax = 1, φMin = 0, φMax = 2π, zMin = -1/2, zMax = 1/2) +# T = float(promote_type(typeof.((rtopMin, rtopMax, rbotMin, rbotMax, φMin, φMax, zMin, zMax))...)) +# rMin_is_equal::Bool = rbotMin == rtopMin +# rMax_is_equal::Bool = rbotMax == rtopMax +# rMin_is_zero::Bool = rMin_is_equal && rbotMin == 0 +# r = if rMax_is_equal +# if rMin_is_zero # Tube with rMin = 0 +# T(rbotMax) +# elseif rMin_is_equal # Tube +# T(rbotMin)..T(rbotMax) +# else # Cone +# (T(rbotMin)..T(rbotMax), T(rtopMin)..T(rtopMax)) +# end +# elseif rMin_is_zero #Cone with rMin = 0 +# (T(rbotMax), T(rtopMax)) +# else # Cone +# (T(rbotMin)..T(rbotMax), T(rtopMin)..T(rtopMax)) +# end +# φ = mod(T(φMax) - T(φMin), T(2π)) == 0 ? nothing : T(φMin)..T(φMax) +# z = zMax == -zMin ? T(zMax) : T(zMin)..T(zMax) +# Cone( T, r, φ, z) +# end +# Cone(rbotMin, rbotMax, rtopMin, rtopMax, φMin, φMax, zMin, zMax) = Cone(; rbotMin = rbotMin, rbotMax = rbotMax, rtopMin = rtopMin, rtopMax = rtopMax, φMin = φMin, φMax = φMax, zMin = zMin, zMax = zMax) + +# function Cone(rbot::R1, rtop::R2, height::H) where {R1<:Real, R2<:Real, H<:Real} +# T = float(promote_type(R1, R2, H)) +# Cone( T, (T(rbot), T(rtop)), nothing, T(height)/2) +# end + + +# #Constructors for Tubes +# Tube(;rMin = 0, rMax = 1, φMin = 0, φMax = 2π, zMin = -1/2, zMax = 1/2) = Cone(rMin, rMax, rMin, rMax, φMin, φMax, zMin, zMax) +# Tube(rMin, rMax, φMin, φMax, zMin, zMax) = Tube(; rMin = rMin, rMax = rMax, φMin = φMin, φMax = φMax, zMin = zMin, zMax = zMax) + +# function Tube(r::R, height::H) where {R<:Real, H<:Real} +# T = float(promote_type(R,H)) +# Cone(T, T(r), nothing, T(height)/2) +# end + +# function Tube(rMin::R1, rMax::R2, height::H) where {R1<:Real, R2<:Real, H<:Real} +# T = float(promote_type(R1,R2,H)) +# Cone(T, rMin == 0 ? T(rMax) : T(rMin)..T(rMax), nothing, T(height)/2) +# end + +# # for Tubes +# get_r_at_z(c::Cone{T, <:Union{T, AbstractInterval{T}}, <:Any, <:Any}, z::Real) where {T} = c.r + +# # for Cones +# get_r_at_z(c::Cone{T, Tuple{T,T}, <:Any, <:Any}, z::Real) where {T} = _get_r_at_z(c.r[1], c.r[2], c.z, z) + +# function get_r_at_z(c::Cone{T, Tuple{I,I}, <:Any, <:Any}, z::Real) where {T, I<:AbstractInterval{T}} +# r1::T = _get_r_at_z(c.r[1].left, c.r[2].left, c.z, z) +# r2::T = _get_r_at_z(c.r[1].right, c.r[2].right, c.z, z) +# r1..r2 +# end + +# function _get_r_at_z(rbot::TR, rtop::TR, cz::TZ, z::Real)::TR where {TR<:Real, TZ} +# (rtop - rbot) * (z - _left_linear_interval(cz)) / _width_linear_interval(cz) + rbot +# end + + +# in(p::AbstractCoordinatePoint, c::Cone{<:Any, <:Any, Nothing, <:Any}) = +# _in_z(p, c.z) && _in_cyl_r(p, get_r_at_z(c, p.z)) + +# in(p::AbstractCoordinatePoint, c::Cone{<:Any, <:Any, <:AbstractInterval, <:Any}) = +# _in_z(p, c.z) && _in_φ(p, c.φ) && _in_cyl_r(p, get_r_at_z(c, p.z)) + +# # read-in +# function Geometry(::Type{T}, t::Union{Type{Cone}, Type{Tube}}, dict::AbstractDict, input_units::NamedTuple) where {T} +# length_unit = input_units.length +# angle_unit = input_units.angle +# r = parse_r_of_primitive(T, dict, length_unit) +# φ = parse_φ_of_primitive(T, dict, angle_unit) +# z = parse_height_of_primitive(T, dict, length_unit) +# return Cone(T, r, φ, z) +# end + +# function Dictionary(g::Cone{T,<:Union{T, AbstractInterval}}) where {T} +# dict = OrderedDict{String,Any}() +# dict["r"] = typeof(g.r) == T ? g.r : OrderedDict{String,Any}("from" => g.r.left, "to" => g.r.right) +# if !isnothing(g.φ) dict["phi"] = OrderedDict{String,Any}("from" => g.φ.left, "to" => g.φ.right) end +# typeof(g.z) == T ? dict["h"] = g.z * 2 : dict["z"] = OrderedDict{String,Any}("from" => g.z.left, "to" => g.z.right) +# OrderedDict{String,Any}("tube" => dict) +# end + +# function Dictionary(g::Cone{T,<:Tuple}) where {T} +# dict = OrderedDict{String,Any}() +# dict["r"] = OrderedDict{String,Any}() +# dict["r"]["bottom"] = typeof(g.r[1]) == T ? g.r[1] : OrderedDict{String,Any}("from" => g.r[1].left, "to" => g.r[1].right) +# dict["r"]["top"] = typeof(g.r[2]) == T ? g.r[2] : OrderedDict{String,Any}("from" => g.r[2].left, "to" => g.r[2].right) +# if !isnothing(g.φ) dict["phi"] = OrderedDict{String,Any}("from" => g.φ.left, "to" => g.φ.right) end +# typeof(g.z) == T ? dict["h"] = g.z * 2 : dict["z"] = OrderedDict{String,Any}("from" => g.z.left, "to" => g.z.right) +# OrderedDict{String,Any}("cone" => dict) +# end + + +# get_r_limits(c::Cone{T, <:Union{T, AbstractInterval{T}}, <:Any, <:Any}) where {T} = +# (_left_radial_interval(c.r),_right_radial_interval(c.r),_left_radial_interval(c.r),_right_radial_interval(c.r)) +# get_r_limits(c::Cone{T, <:Tuple, <:Any, <:Any}) where {T} = +# (_left_radial_interval(c.r[1]),_right_radial_interval(c.r[1]),_left_radial_interval(c.r[2]),_right_radial_interval(c.r[2])) + +# get_φ_limits(c::Cone{T, <:Any, Nothing, <:Any}) where {T} = (T(0), T(2π), true) +# get_φ_limits(c::Cone{T, <:Any, <:AbstractInterval, <:Any}) where {T} = (c.φ.left, c.φ.right, false) + +# get_z_limits(c::Cone{T}) where {T} = (_left_linear_interval(c.z), _right_linear_interval(c.z)) + +# function _is_cone_collapsed(rbotMin::T, rbotMax::T, rtopMin::T, rtopMax::T, zMin::T, zMax::T) where {T} +# tol = geom_atol_zero(T) +# (isapprox(rbotMin, rbotMax, atol = tol) && isapprox(rtopMin, rtopMax, atol = tol)) || isapprox(zMin, zMax, atol = tol) +# end + +# function _get_decomposed_surfaces_cone(c::Cone{T}, rbotMin::T, rbotMax::T, rtopMin::T, rtopMax::T, zMin::T, zMax::T) where {T} +# surfaces = AbstractSurfacePrimitive[] +# #top and bottom annulus +# tol = geom_atol_zero(T) +# if !isapprox(rbotMin, rbotMax, atol = tol) +# push!(surfaces, CylindricalAnnulus(c, z = zMin)) +# end +# if !isapprox(zMin, zMax, atol = tol) +# if !isapprox(rtopMin, rtopMax, atol = tol) +# push!(surfaces, CylindricalAnnulus(c, z = zMax)) +# end +# #outer conemantle +# push!(surfaces, ConeMantle(c, rbot = rbotMax, rtop = rtopMax)) +# end +# surfaces +# end + +# #2π Cones +# function get_decomposed_surfaces(c::Cone{T, <:Union{T, Tuple{T,T}}, Nothing, <:Any}) where {T} +# rbotMin::T, rbotMax::T, rtopMin::T, rtopMax::T = get_r_limits(c) +# zMin::T, zMax::T = get_z_limits(c) +# _get_decomposed_surfaces_cone(c, rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) +# end + +# function get_decomposed_surfaces(c::Cone{T, <:Union{<:AbstractInterval{T}, Tuple{I,I}}, Nothing, <:Any}) where {T, I<:AbstractInterval{T}} +# rbotMin::T, rbotMax::T, rtopMin::T, rtopMax::T = get_r_limits(c) +# zMin::T, zMax::T = get_z_limits(c) +# surfaces = _get_decomposed_surfaces_cone(c, rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) +# if !_is_cone_collapsed(rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) +# push!(surfaces, ConeMantle(c, rbot = rbotMin, rtop = rtopMin)) +# end +# surfaces +# end + +# #non 2π Cones +# function get_decomposed_surfaces(c::Cone{T, <:Union{T, Tuple{T,T}}, <:AbstractInterval{T}, <:Any}) where {T} +# rbotMin::T, rbotMax::T, rtopMin::T, rtopMax::T = get_r_limits(c) +# zMin::T, zMax::T = get_z_limits(c) +# φMin::T, φMax::T, _ = get_φ_limits(c) +# surfaces = _get_decomposed_surfaces_cone(c, rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) +# if !_is_cone_collapsed(rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) +# push!(surfaces, ConalPlane(c, φ = φMin), ConalPlane(c, φ = φMax)) +# end +# surfaces +# end + +# function get_decomposed_surfaces(c::Cone{T, <:Union{<:AbstractInterval{T}, Tuple{I,I}}, <:AbstractInterval{T}, <:Any}) where {T, I<:AbstractInterval{T}} +# rbotMin::T, rbotMax::T, rtopMin::T, rtopMax::T = get_r_limits(c) +# zMin::T, zMax::T = get_z_limits(c) +# φMin::T, φMax::T, _ = get_φ_limits(c) +# surfaces = _get_decomposed_surfaces_cone(c, rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) +# if !_is_cone_collapsed(rbotMin, rbotMax, rtopMin, rtopMax, zMin, zMax) +# push!(surfaces, ConalPlane(c, φ = φMin), ConalPlane(c, φ = φMax)) +# push!(surfaces, ConeMantle(c, rbot = rbotMin, rtop = rtopMin)) +# end +# surfaces +# end + +# function sample(c::Cone{T}, step::Real)::Vector{CylindricalPoint{T}} where {T} +# zMin::T, zMax::T = get_z_limits(c) +# φMin::T, φMax::T, _ = get_φ_limits(c) +# samples = [ +# CylindricalPoint{T}(r,φ,z) +# for z in zMin:step:zMax +# for r in _left_radial_interval(get_r_at_z(c, z)):step:_right_radial_interval(get_r_at_z(c, z)) +# for φ in (r == 0 ? φMin : φMin:step/r:φMax) +# ] +# end + +# function sample(c::Cone{T}, Nsamps::NTuple{3,Int})::Vector{CylindricalPoint{T}} where {T} +# zMin::T, zMax::T = get_z_limits(c) +# φMin::T, φMax::T, _ = get_φ_limits(c) +# samples = [ +# CylindricalPoint{T}(r,φ,z) +# for z in (Nsamps[3] ≤ 1 ? zMin : range(zMin, zMax, length = Nsamps[3])) +# for r in (Nsamps[1] ≤ 1 ? _left_radial_interval(get_r_at_z(c, z)) : range(_left_radial_interval(get_r_at_z(c, z)), _right_radial_interval(get_r_at_z(c, z)), length = Nsamps[1])) +# for φ in (Nsamps[2] ≤ 1 ? φMin : range(φMin, φMax, length = Nsamps[2])) +# ] +# end + +# @inline sample(c::Cone{T}) where {T} = sample(c, (2,3,3)) +# @inline sample(c::Cone{T, <:Any, Nothing}) where {T} = sample(c, (2,5,3)) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index cd4d60c97..2013bc4c3 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -5,4 +5,5 @@ OpenPrimitive(p::VP) where {VP <: AbstractVolumePrimitive} = VP(p, COT = OpenPri distance(pt::CartesianPoint, vp::AbstractVolumePrimitive) = minimum(map(p -> distance(pt, p), surfaces(vp))) -include("Box.jl") \ No newline at end of file +include("Box.jl") +include("Cone.jl") \ No newline at end of file From 55be2e156e404c72e19cae973deb133e81fa5466 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 14:44:15 +0200 Subject: [PATCH 088/241] Include file `ConeMantle.jl` again --- .../SurfacePrimitives/ConeMantle.jl | 300 +++++++++--------- .../SurfacePrimitives/SurfacePrimitives.jl | 3 +- 2 files changed, 152 insertions(+), 151 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index bd3271133..bb5e4658e 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -1,150 +1,150 @@ -struct ConeMantle{T,TR,TP,TZ} <: AbstractSurfacePrimitive{T} - r::TR #if not a Tuple, then ConeMantle is a Tube - φ::TP - z::TZ - #if r is a Tuple, the first entry refers to the r at the bottom, the second one to the r at the top - function ConeMantle( ::Type{T}, - r::Union{T, Tuple{T,T}}, - φ::Union{Nothing, <:AbstractInterval{T}}, - z::Union{T, <:AbstractInterval{T}}) where {T, I<:AbstractInterval{T}} - new{T,typeof(r),typeof(φ),typeof(z)}(r, φ, z) - end -end - -function ConeMantle(c::Cone{T}; rbot = 1, rtop = 1) where {T} - r = rbot == rtop ? T(rbot) : (T(rbot), T(rtop)) - ConeMantle( T, r, c.φ, c.z) -end - -function ConeMantle(t::Torus{T}; θ = π/2) where {T} - r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) - θ = T(mod(θ,2π)) - sθ, cθ = sincos(θ) - if θ > T(0) && θ < T(π) - rbot = geom_round(t.r_torus + r_tubeMin*cθ) - rtop = geom_round(t.r_torus + r_tubeMax*cθ) - zMin = geom_round(t.z + r_tubeMin*sθ) - zMax = geom_round(t.z + r_tubeMax*sθ) - elseif θ > T(π) && θ < T(2π) - rtop = geom_round(t.r_torus + r_tubeMin*cθ) - rbot = geom_round(t.r_torus + r_tubeMax*cθ) - zMax = geom_round(t.z + r_tubeMin*sθ) - zMin = geom_round(t.z + r_tubeMax*sθ) - else - @error "Cone Mantle not defined for torroidal cordinate θ = 0 or θ = π. Use Annulus" - end - r = rbot == rtop ? T(rbot) : (T(rbot), T(rtop)) - z = zMax == -zMin ? T(zMax) : T(zMin)..T(zMax) - ConeMantle( T, r, t.φ, z) -end - -function ConeMantle(;rbot = 1, rtop = 0, φMin = 0, φMax = 2π, zMin = -1/2, zMax = 1/2) - T = float(promote_type(typeof.((rbot, rtop, φMin, φMax, zMin, zMax))...)) - r = rbot == rtop ? T(rbot) : (T(rbot), T(rtop)) - φ = mod(T(φMax) - T(φMin), T(2π)) == 0 ? nothing : T(φMin)..T(φMax) - z = zMax == -zMin ? T(zMax) : T(zMin)..T(zMax) - ConeMantle(T, r, φ, z) -end -ConeMantle(rbot, rtop, φMin, φMax, zMin, zMax) = ConeMantle(;rbot = rbot, rtop = rtop, φMin = φMin, φMax = φMax, zMin = zMin, zMax = zMax) - -function ConeMantle(rbot::R1, rtop::R2, height::H) where {R1<:Real, R2<:Real, H<:Real} - T = float(promote_type(R1, R2, H)) - ConeMantle( T, (T(rbot), T(rtop)), nothing, T(height)/2) -end - - -get_r_at_z(c::ConeMantle{T, T}, z::Real) where {T} = c.r -get_r_at_z(c::ConeMantle{T, Tuple{T,T}}, z::Real) where {T} = _get_r_at_z(c.r[1], c.r[2], c.z, z) - -get_r_limits(c::ConeMantle{T, T, <:Any, <:Any}) where {T} = (T(c.r), T(c.r)) -get_r_limits(c::ConeMantle{T, <:Tuple, <:Any, <:Any}) where {T} = c.r - -get_φ_limits(c::ConeMantle{T, <:Any, Nothing, <:Any}) where {T} = (T(0), T(2π), true) -get_φ_limits(c::ConeMantle{T, <:Any, <:AbstractInterval, <:Any}) where {T} = (c.φ.left, c.φ.right, false) - -get_z_limits(c::ConeMantle{T}) where {T} = (_left_linear_interval(c.z), _right_linear_interval(c.z)) - -in(p::AbstractCoordinatePoint, c::ConeMantle{<:Any, <:Any, Nothing, <:Any}) = - _in_z(p, c.z) && _eq_cyl_r(p, get_r_at_z(c, p.z)) - -in(p::AbstractCoordinatePoint, c::ConeMantle{<:Any, <:Any, <:AbstractInterval, <:Any}) = - _in_z(p, c.z) && _in_φ(p, c.φ) && _eq_cyl_r(p, get_r_at_z(c, p.z)) - -#= -function sample(c::ConeMantle{T}, step::Real)::Vector{CylindricalPoint{T}} where {T} - φMin::T, φMax::T, _ = get_φ_limits(c) - zMin::T, zMax::T = get_z_limits(c) - samples = [ - CylindricalPoint{T}(get_r_at_z(c, z),φ,z) - for z in zMin:step:zMax - for φ in (get_r_at_z(c, z) == 0 ? φMin : φMin:step/get_r_at_z(c, z):φMax) - ] -end -=# - -function sample(c::ConeMantle{T}, Nsamps::NTuple{3,Int})::Vector{CylindricalPoint{T}} where {T} - φMin::T, φMax::T, _ = get_φ_limits(c) - zMin::T, zMax::T = get_z_limits(c) - samples = [ - CylindricalPoint{T}(get_r_at_z(c, z),φ,z) - for z in (Nsamps[3] ≤ 1 ? zMin : range(zMin, zMax, length = Nsamps[3])) - for φ in (Nsamps[2] ≤ 1 ? φMin : range(φMin, φMax, length = Nsamps[2])) - ] -end - -function sample(c::ConeMantle{T}, g::CylindricalTicksTuple{T})::Vector{CylindricalPoint{T}} where {T} - samples = [ - CylindricalPoint{T}(get_r_at_z(c, z),φ,z) - for z in get_z_ticks(c, g) - for φ in get_φ_ticks(c, g) - ] -end - -function _get_x_at_z(c::ConeMantle{T}, g::CartesianTicksTuple, z::T) where {T} - R::T = get_r_at_z(c, z) - x_from_y::Vector{T} = sqrt.(R^2 .- filter(y -> abs(y) <= R, g.y).^2) - _get_ticks(sort!(vcat(g.x, x_from_y, -x_from_y)), -R, R) -end - -function _get_y_at_z(c::ConeMantle{T}, x::T, z::T) where {T} - R::T = get_r_at_z(c, z) - (-sqrt(R^2-x^2),sqrt(R^2-x^2)) -end - -function sample(c::ConeMantle{T}, g::CartesianTicksTuple{T})::Vector{CartesianPoint{T}} where {T} - samples = [ - CartesianPoint{T}(x,y,z) - for z in _get_ticks(g.z, _left_linear_interval(c.z), _right_linear_interval(c.z)) - for x in _get_x_at_z(c, g, z) - for y in _get_y_at_z(c, x, z) - if c.φ === nothing || mod(atan(y, x), T(2π)) in c.φ - ] -end - -function LineSegment(c::ConeMantle{T}) where {T} - rbot::T, rtop::T = get_r_limits(c) - zMin::T, zMax::T = get_z_limits(c) - LineSegment(T, PlanarPoint{T}(rbot,zMin), PlanarPoint{T}(rtop,zMax)) -end - -function LineSegment(c::ConeMantle{T}, φ::Real) where {T} - rbot::T, rtop::T = get_r_limits(c) - zMin::T, zMax::T = get_z_limits(c) - sφ::T, cφ::T = sincos(φ) - LineSegment(T, CartesianPoint{T}(rbot*cφ,rbot*sφ,zMin), CartesianPoint{T}(rtop*cφ,rtop*sφ,zMax)) -end - -function distance_to_surface(point::AbstractCoordinatePoint{T}, c::ConeMantle{T, <:Any, Nothing, <:Any})::T where {T} - pcy = CylindricalPoint(point) - distance_to_line(PlanarPoint{T}(pcy.r,pcy.z), LineSegment(c)) -end - -function distance_to_surface(point::AbstractCoordinatePoint{T}, c::ConeMantle{T, <:Any, <:AbstractInterval, <:Any})::T where {T} - pcy = CylindricalPoint(point) - φMin::T, φMax::T, _ = get_φ_limits(c) - if _in_φ(pcy, c.φ) - return distance_to_line(PlanarPoint{T}(pcy.r,pcy.z), LineSegment(c)) - else - return distance_to_line(CartesianPoint(point), LineSegment(c, _φNear(pcy.φ, φMin, φMax))) - end -end +# struct ConeMantle{T,TR,TP,TZ} <: AbstractSurfacePrimitive{T} +# r::TR #if not a Tuple, then ConeMantle is a Tube +# φ::TP +# z::TZ +# #if r is a Tuple, the first entry refers to the r at the bottom, the second one to the r at the top +# function ConeMantle( ::Type{T}, +# r::Union{T, Tuple{T,T}}, +# φ::Union{Nothing, <:AbstractInterval{T}}, +# z::Union{T, <:AbstractInterval{T}}) where {T, I<:AbstractInterval{T}} +# new{T,typeof(r),typeof(φ),typeof(z)}(r, φ, z) +# end +# end + +# function ConeMantle(c::Cone{T}; rbot = 1, rtop = 1) where {T} +# r = rbot == rtop ? T(rbot) : (T(rbot), T(rtop)) +# ConeMantle( T, r, c.φ, c.z) +# end + +# function ConeMantle(t::Torus{T}; θ = π/2) where {T} +# r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) +# θ = T(mod(θ,2π)) +# sθ, cθ = sincos(θ) +# if θ > T(0) && θ < T(π) +# rbot = geom_round(t.r_torus + r_tubeMin*cθ) +# rtop = geom_round(t.r_torus + r_tubeMax*cθ) +# zMin = geom_round(t.z + r_tubeMin*sθ) +# zMax = geom_round(t.z + r_tubeMax*sθ) +# elseif θ > T(π) && θ < T(2π) +# rtop = geom_round(t.r_torus + r_tubeMin*cθ) +# rbot = geom_round(t.r_torus + r_tubeMax*cθ) +# zMax = geom_round(t.z + r_tubeMin*sθ) +# zMin = geom_round(t.z + r_tubeMax*sθ) +# else +# @error "Cone Mantle not defined for torroidal cordinate θ = 0 or θ = π. Use Annulus" +# end +# r = rbot == rtop ? T(rbot) : (T(rbot), T(rtop)) +# z = zMax == -zMin ? T(zMax) : T(zMin)..T(zMax) +# ConeMantle( T, r, t.φ, z) +# end + +# function ConeMantle(;rbot = 1, rtop = 0, φMin = 0, φMax = 2π, zMin = -1/2, zMax = 1/2) +# T = float(promote_type(typeof.((rbot, rtop, φMin, φMax, zMin, zMax))...)) +# r = rbot == rtop ? T(rbot) : (T(rbot), T(rtop)) +# φ = mod(T(φMax) - T(φMin), T(2π)) == 0 ? nothing : T(φMin)..T(φMax) +# z = zMax == -zMin ? T(zMax) : T(zMin)..T(zMax) +# ConeMantle(T, r, φ, z) +# end +# ConeMantle(rbot, rtop, φMin, φMax, zMin, zMax) = ConeMantle(;rbot = rbot, rtop = rtop, φMin = φMin, φMax = φMax, zMin = zMin, zMax = zMax) + +# function ConeMantle(rbot::R1, rtop::R2, height::H) where {R1<:Real, R2<:Real, H<:Real} +# T = float(promote_type(R1, R2, H)) +# ConeMantle( T, (T(rbot), T(rtop)), nothing, T(height)/2) +# end + + +# get_r_at_z(c::ConeMantle{T, T}, z::Real) where {T} = c.r +# get_r_at_z(c::ConeMantle{T, Tuple{T,T}}, z::Real) where {T} = _get_r_at_z(c.r[1], c.r[2], c.z, z) + +# get_r_limits(c::ConeMantle{T, T, <:Any, <:Any}) where {T} = (T(c.r), T(c.r)) +# get_r_limits(c::ConeMantle{T, <:Tuple, <:Any, <:Any}) where {T} = c.r + +# get_φ_limits(c::ConeMantle{T, <:Any, Nothing, <:Any}) where {T} = (T(0), T(2π), true) +# get_φ_limits(c::ConeMantle{T, <:Any, <:AbstractInterval, <:Any}) where {T} = (c.φ.left, c.φ.right, false) + +# get_z_limits(c::ConeMantle{T}) where {T} = (_left_linear_interval(c.z), _right_linear_interval(c.z)) + +# in(p::AbstractCoordinatePoint, c::ConeMantle{<:Any, <:Any, Nothing, <:Any}) = +# _in_z(p, c.z) && _eq_cyl_r(p, get_r_at_z(c, p.z)) + +# in(p::AbstractCoordinatePoint, c::ConeMantle{<:Any, <:Any, <:AbstractInterval, <:Any}) = +# _in_z(p, c.z) && _in_φ(p, c.φ) && _eq_cyl_r(p, get_r_at_z(c, p.z)) + +# #= +# function sample(c::ConeMantle{T}, step::Real)::Vector{CylindricalPoint{T}} where {T} +# φMin::T, φMax::T, _ = get_φ_limits(c) +# zMin::T, zMax::T = get_z_limits(c) +# samples = [ +# CylindricalPoint{T}(get_r_at_z(c, z),φ,z) +# for z in zMin:step:zMax +# for φ in (get_r_at_z(c, z) == 0 ? φMin : φMin:step/get_r_at_z(c, z):φMax) +# ] +# end +# =# + +# function sample(c::ConeMantle{T}, Nsamps::NTuple{3,Int})::Vector{CylindricalPoint{T}} where {T} +# φMin::T, φMax::T, _ = get_φ_limits(c) +# zMin::T, zMax::T = get_z_limits(c) +# samples = [ +# CylindricalPoint{T}(get_r_at_z(c, z),φ,z) +# for z in (Nsamps[3] ≤ 1 ? zMin : range(zMin, zMax, length = Nsamps[3])) +# for φ in (Nsamps[2] ≤ 1 ? φMin : range(φMin, φMax, length = Nsamps[2])) +# ] +# end + +# function sample(c::ConeMantle{T}, g::CylindricalTicksTuple{T})::Vector{CylindricalPoint{T}} where {T} +# samples = [ +# CylindricalPoint{T}(get_r_at_z(c, z),φ,z) +# for z in get_z_ticks(c, g) +# for φ in get_φ_ticks(c, g) +# ] +# end + +# function _get_x_at_z(c::ConeMantle{T}, g::CartesianTicksTuple, z::T) where {T} +# R::T = get_r_at_z(c, z) +# x_from_y::Vector{T} = sqrt.(R^2 .- filter(y -> abs(y) <= R, g.y).^2) +# _get_ticks(sort!(vcat(g.x, x_from_y, -x_from_y)), -R, R) +# end + +# function _get_y_at_z(c::ConeMantle{T}, x::T, z::T) where {T} +# R::T = get_r_at_z(c, z) +# (-sqrt(R^2-x^2),sqrt(R^2-x^2)) +# end + +# function sample(c::ConeMantle{T}, g::CartesianTicksTuple{T})::Vector{CartesianPoint{T}} where {T} +# samples = [ +# CartesianPoint{T}(x,y,z) +# for z in _get_ticks(g.z, _left_linear_interval(c.z), _right_linear_interval(c.z)) +# for x in _get_x_at_z(c, g, z) +# for y in _get_y_at_z(c, x, z) +# if c.φ === nothing || mod(atan(y, x), T(2π)) in c.φ +# ] +# end + +# function LineSegment(c::ConeMantle{T}) where {T} +# rbot::T, rtop::T = get_r_limits(c) +# zMin::T, zMax::T = get_z_limits(c) +# LineSegment(T, PlanarPoint{T}(rbot,zMin), PlanarPoint{T}(rtop,zMax)) +# end + +# function LineSegment(c::ConeMantle{T}, φ::Real) where {T} +# rbot::T, rtop::T = get_r_limits(c) +# zMin::T, zMax::T = get_z_limits(c) +# sφ::T, cφ::T = sincos(φ) +# LineSegment(T, CartesianPoint{T}(rbot*cφ,rbot*sφ,zMin), CartesianPoint{T}(rtop*cφ,rtop*sφ,zMax)) +# end + +# function distance_to_surface(point::AbstractCoordinatePoint{T}, c::ConeMantle{T, <:Any, Nothing, <:Any})::T where {T} +# pcy = CylindricalPoint(point) +# distance_to_line(PlanarPoint{T}(pcy.r,pcy.z), LineSegment(c)) +# end + +# function distance_to_surface(point::AbstractCoordinatePoint{T}, c::ConeMantle{T, <:Any, <:AbstractInterval, <:Any})::T where {T} +# pcy = CylindricalPoint(point) +# φMin::T, φMax::T, _ = get_φ_limits(c) +# if _in_φ(pcy, c.φ) +# return distance_to_line(PlanarPoint{T}(pcy.r,pcy.z), LineSegment(c)) +# else +# return distance_to_line(CartesianPoint(point), LineSegment(c, _φNear(pcy.φ, φMin, φMax))) +# end +# end diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl index f64e7a6a5..8f175632d 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl @@ -1,2 +1,3 @@ include("Plane.jl") -include("Polygon.jl") \ No newline at end of file +include("Polygon.jl") +include("ConeMantle.jl") \ No newline at end of file From d3471a628fe8f3fbb39e887966bf0f42c8268543 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 16:39:51 +0200 Subject: [PATCH 089/241] Extend docstring of `Ellipse` --- .../LinePrimitives/Ellipse.jl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl index f880224b3..09eb7d385 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl @@ -3,9 +3,14 @@ * `r::TR`: * TR = Real -> Circle (a = b = r) - * TR = (Real, Real) -> Ellipse (a = r[1], b = r[2]) - -* `φ::TP`: nothing <-> Full in φ + * TR = (Real, Real) -> Circular Annulus (r_in = r[1], r_out = r[2]) + * TR = ((Real,), (Real,)) -> Ellipse (a = r[1][1], b = r[2][1]) + * TR = ((Real, Real),(Real, Real)) -> Elliptical Annulus \n(a_in = r[1][1], a_out = r[1][2], b_in = r[2][1], b_out = r[2][2]) + * Not all are implemented yet + +* `φ::TP`: + * TP = Nothing <-> Full in φ + * ... """ @with_kw struct Ellipse{T,TR,TP} <: AbstractLinePrimitive{T} r::TR = 1 From 27079370ea02908b4ba719ae5fdd479ef7b96732 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 16:40:12 +0200 Subject: [PATCH 090/241] Refactor `Cone` --- .../VolumePrimitives/Cone.jl | 81 +++++++++---------- 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 87ae45cde..78fee5537 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -1,45 +1,42 @@ -# struct Cone{T,TR,TP,TZ} <: AbstractVolumePrimitive{T} -# r::TR #if not a Tuple, then Cone is a Tube -# φ::TP -# z::TZ -# #if r is a Tuple, the first entry refers to the r-interval at the bottom, the second one to the r-interval at the top -# function Cone( ::Type{T}, -# r::Union{T, <:AbstractInterval{T}, Tuple{T,T}, Tuple{I,I}}, -# φ::Union{Nothing, <:AbstractInterval{T}}, -# z::Union{T, <:AbstractInterval{T}}) where {T, I<:AbstractInterval{T}} -# new{T,typeof(r),typeof(φ),typeof(z)}(r, φ, z) -# end -# end - -# #Constructors -# function Cone(;rbotMin = 0, rbotMax = 1, rtopMin = 0, rtopMax = 1, φMin = 0, φMax = 2π, zMin = -1/2, zMax = 1/2) -# T = float(promote_type(typeof.((rtopMin, rtopMax, rbotMin, rbotMax, φMin, φMax, zMin, zMax))...)) -# rMin_is_equal::Bool = rbotMin == rtopMin -# rMax_is_equal::Bool = rbotMax == rtopMax -# rMin_is_zero::Bool = rMin_is_equal && rbotMin == 0 -# r = if rMax_is_equal -# if rMin_is_zero # Tube with rMin = 0 -# T(rbotMax) -# elseif rMin_is_equal # Tube -# T(rbotMin)..T(rbotMax) -# else # Cone -# (T(rbotMin)..T(rbotMax), T(rtopMin)..T(rtopMax)) -# end -# elseif rMin_is_zero #Cone with rMin = 0 -# (T(rbotMax), T(rtopMax)) -# else # Cone -# (T(rbotMin)..T(rbotMax), T(rtopMin)..T(rtopMax)) -# end -# φ = mod(T(φMax) - T(φMin), T(2π)) == 0 ? nothing : T(φMin)..T(φMax) -# z = zMax == -zMin ? T(zMax) : T(zMin)..T(zMax) -# Cone( T, r, φ, z) -# end -# Cone(rbotMin, rbotMax, rtopMin, rtopMax, φMin, φMax, zMin, zMax) = Cone(; rbotMin = rbotMin, rbotMax = rbotMax, rtopMin = rtopMin, rtopMax = rtopMax, φMin = φMin, φMax = φMax, zMin = zMin, zMax = zMax) - -# function Cone(rbot::R1, rtop::R2, height::H) where {R1<:Real, R2<:Real, H<:Real} -# T = float(promote_type(R1, R2, H)) -# Cone( T, (T(rbot), T(rtop)), nothing, T(height)/2) -# end +""" + struct Cone{T,CO,RT,TP} <: AbstractVolumePrimitive{T, CO} + +T: Type of values, e.g. Float64 +CO: ClosedPrimitive or OpenPrimitive <-> whether surface belongs to it or not + +* `r::TR`: + * TR = Real -> Solid Tube + * TR = (Real, Real) -> Pipe (r_in = r[1], r_out = r[2]) + * TR = ((Real,), (Real,)) Solid widening Tube -> (r_bot = r[1][1], r_top = r[1][2]) + * TR = ((Real,Real), (Real,Real)) Solid widening Pipe ->\n(r_bot_in = r[1][1], r_bot_out = r[1][2], r_top_in = r[2][1], r_top_out = r[2][2]) + * TR = (Nothing, (Real,Real)) Cone ->\n(r_bot_in = r_bot_out = 0, r_top_in = r[2][1], r_top_out = r[2][2]) + * TR = ((Real,Real), Nothing) Cone ->\n(r_bot_in = r[1][1], r_bot_out = r[1][2], r_top_in = r_top_out = 0) + * ... (+ elliptical cases -> (a, b)) + * Not all are implemented yet + +* `φ::TP`: + * TP = Nothing <-> Full in φ + * ... +* `zH::T`: half hight/length of the cone +""" +@with_kw struct Cone{T,CO,RT,TP} <: AbstractVolumePrimitive{T, CO} + r::RT = 1 + φ::TP = nothing + hZ::T = 1 + + origin::CartesianPoint{T} = zero(CartesianPoint{T}) + rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) +end + +Cone{T,CO,RT,TP}( c::Cone{T,CO,RT,TP}; COT = CO, + origin::CartesianPoint{T} = b.origin, + rotation::SMatrix{3,3,T,9} = b.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},RT,TP} = + Cone{T,CO,RT,TP}(c.r, c.φ, c.hZ, origin, rotation) + +const Tube{T,CO} = Cone{T,CO,T,Nothing} + +_in(pt::CartesianPoint, c::Tube{<:Real, ClosedPrimitive}) = abs(pt.z) <= c.hZ && hypot(pt.x, pt.y) <= c.r +_in(pt::CartesianPoint, c::Tube{<:Real, OpenPrimitive}) = abs(pt.z) < c.hZ && hypot(pt.x, pt.y) < c.r # #Constructors for Tubes From 7ea72a2fc60b729cc646d9b398cc1f7bbf6acd48 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 16:40:36 +0200 Subject: [PATCH 091/241] Enable "tube" and "cone" in the read-in again --- src/ConstructiveSolidGeometry/IO.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 651323d7a..e99b54ace 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -1,6 +1,6 @@ const CSG_dict = Dict{String, Any}( - # "tube" => Cone, - # "cone" => Cone, + "tube" => Cone, + "cone" => Cone, # "sphere" => Sphere, "box" => Box, # "torus" => Torus, From 96dc9bd353b8a2fb168bae8c51d60aad57a82288 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 16:47:56 +0200 Subject: [PATCH 092/241] Enable read-in for Tubes/Cones again --- .../VolumePrimitives/Cone.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 78fee5537..0292bea7f 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -77,14 +77,14 @@ _in(pt::CartesianPoint, c::Tube{<:Real, OpenPrimitive}) = abs(pt.z) < c.hZ && # _in_z(p, c.z) && _in_φ(p, c.φ) && _in_cyl_r(p, get_r_at_z(c, p.z)) # # read-in -# function Geometry(::Type{T}, t::Union{Type{Cone}, Type{Tube}}, dict::AbstractDict, input_units::NamedTuple) where {T} -# length_unit = input_units.length -# angle_unit = input_units.angle -# r = parse_r_of_primitive(T, dict, length_unit) -# φ = parse_φ_of_primitive(T, dict, angle_unit) -# z = parse_height_of_primitive(T, dict, length_unit) -# return Cone(T, r, φ, z) -# end +function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::NamedTuple, transformations::Transformations{T}) where {T} + length_unit = input_units.length + angle_unit = input_units.angle + r = parse_r_of_primitive(T, dict, length_unit) + φ = parse_φ_of_primitive(T, dict, angle_unit) + h = parse_height_of_primitive(T, dict, length_unit) + return Cone{T, ClosedPrimitive, typeof(r), typeof(φ)}(r = r, φ = φ, hZ = h/2) +end # function Dictionary(g::Cone{T,<:Union{T, AbstractInterval}}) where {T} # dict = OrderedDict{String,Any}() From 0f48dd5e7c24488bf73c7ba9dcee230ae241deaa Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 17:30:29 +0200 Subject: [PATCH 093/241] Integrate `ConeMantle` again. --- .../SurfacePrimitives/ConeMantle.jl | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index bb5e4658e..265c7c3f8 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -1,15 +1,35 @@ -# struct ConeMantle{T,TR,TP,TZ} <: AbstractSurfacePrimitive{T} -# r::TR #if not a Tuple, then ConeMantle is a Tube -# φ::TP -# z::TZ -# #if r is a Tuple, the first entry refers to the r at the bottom, the second one to the r at the top -# function ConeMantle( ::Type{T}, -# r::Union{T, Tuple{T,T}}, -# φ::Union{Nothing, <:AbstractInterval{T}}, -# z::Union{T, <:AbstractInterval{T}}) where {T, I<:AbstractInterval{T}} -# new{T,typeof(r),typeof(φ),typeof(z)}(r, φ, z) -# end -# end +""" + struct ConeMantle{T,RT,TP} <: AbstractSurfacePrimitive{T} + +T: Type of values, e.g. Float64 + +* `r::TR`: + * TR = Real -> Tube Mantle (a = b = r) + * TR = (Real, Real) -> Cone Mantle (r_bot = r[1], r_top = r[2]) + * TR = ((Real,), (Real,)) -> Elliptical Tube Mantle (a = r[1][1], b = r[2][1]) + * TR = ((Real, Real),(Real, Real)) -> Elliptical Cone Mantle \n(a_in = r[1][1], a_out = r[1][2], b_in = r[2][1], b_out = r[2][2]) + * Not all are implemented yet + +* `φ::TP`: + * TP = Nothing <-> Full in φ + * ... +* `zH::T`: half hight/length of the cone mantle + +* `axis::Line{T}`: The axis of the Cone mantle. Going from the bottom center point to the top center point. +""" +@with_kw struct ConeMantle{T,RT,TP} <: AbstractSurfacePrimitive{T} + r::RT = 1 + φ::TP = nothing + hZ::T = 1 # maybe we don't need this. I will leave it for now... + + axis::Line{T} = Line{T}(CartesianPoint{T}(zero(T), zero(T), -hZ), CartesianVector{T}(zero(T), zero(T), 2hZ)) +end + +function ConeMantle(t::Tube{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + ConeMantle{T,T,Nothing}(t.r, t.φ, t.hZ, Line{T}(bot_center_pt, top_center_pt - bot_center_pt)) +end # function ConeMantle(c::Cone{T}; rbot = 1, rtop = 1) where {T} # r = rbot == rtop ? T(rbot) : (T(rbot), T(rtop)) From 21c6b5079e8d7d384a083c98e8ad6c8e32d0d8b7 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 17:30:46 +0200 Subject: [PATCH 094/241] Add `surface` method for `Tube` --- src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 0292bea7f..e78111fcb 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -86,6 +86,13 @@ function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::Nam return Cone{T, ClosedPrimitive, typeof(r), typeof(φ)}(r = r, φ = φ, hZ = h/2) end +function surfaces(t::Tube{T}) where {T} + mantle = ConeMantle(t) + e_bot = Ellipse{T,T,Nothing}(r = t.r, φ = nothing, origin = mantle.axis.origin, rotation = t.rotation) + e_top = Ellipse{T,T,Nothing}(r = t.r, φ = nothing, origin = mantle.axis.origin + mantle.axis.direction, rotation = t.rotation) + e_top, e_bot, mantle +end + # function Dictionary(g::Cone{T,<:Union{T, AbstractInterval}}) where {T} # dict = OrderedDict{String,Any}() # dict["r"] = typeof(g.r) == T ? g.r : OrderedDict{String,Any}("from" => g.r.left, "to" => g.r.right) From 709cf8560f0ec9f42787b1da5394d5e4fca6452b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 17:48:57 +0200 Subject: [PATCH 095/241] Add plot recipe for `Ellipse` --- .../plotting/LinePrimitives/Ellipse.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl index 151b64363..aa0fd8e75 100644 --- a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl @@ -4,3 +4,13 @@ function edges(e::Ellipse{T,T,Nothing}; n = 4) where {T} pts = map(p -> _transform_into_global_coordinate_system(p, e), pts) edges = [Edge(pts[i], pts[i+1]) for i in 1:n] end + +@recipe function f(e::Ellipse; n = 40) + @series begin + label --> "Ellipse" + @info n + edges(e, n = n) + end +end + + From 4429950284251cb5572a165f81d8bb12d6801b34 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 17:53:42 +0200 Subject: [PATCH 096/241] Function `surfaces` now returns a tuple of surface primitives, not a static vector anymore because different volume primitives return different types of surfaces primitives. --- src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl | 2 +- .../plotting/VolumePrimitives/VolumePrimitives.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 993091d49..074968f88 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -62,7 +62,7 @@ sample(b::Box) = vertices(b) function surfaces(b::Box{T}) where {T} vs = vertices(b) - return SVector{6, Quadrangle{T}}( + return ( Quadrangle{T}((vs[1], vs[2], vs[3], vs[4])), Quadrangle{T}((vs[5], vs[6], vs[2], vs[1])), Quadrangle{T}((vs[8], vs[7], vs[6], vs[5])), diff --git a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl index a524d0e02..10046b19c 100644 --- a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl @@ -5,7 +5,7 @@ linecolor --> :black @series begin label --> "$(nameof(typeof(p)))" - fs + [fs...] end end From da7f0cec4eae6e014bbfc5e269b93bd5fb03fc0b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 16 Jun 2021 17:58:15 +0200 Subject: [PATCH 097/241] Rename file `CylindricalAnnulus.jl` to `EllipticalSurface.jl` --- .../{CylindricalAnnulus.jl => EllipticalSurface.jl} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/ConstructiveSolidGeometry/SurfacePrimitives/{CylindricalAnnulus.jl => EllipticalSurface.jl} (98%) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/CylindricalAnnulus.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl similarity index 98% rename from src/ConstructiveSolidGeometry/SurfacePrimitives/CylindricalAnnulus.jl rename to src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl index 127cd69ed..71ee83235 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/CylindricalAnnulus.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl @@ -1,4 +1,4 @@ -struct CylindricalAnnulus{T,TR,TP} <: AbstractSurfacePrimitive{T} +struct EllipticalSurface{T,TR,TP} <: AbstractSurfacePrimitive{T} r::TR φ::TP z::T From 551311c236e21c2758db5f2bf8d961d27d71e838 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 08:57:24 +0200 Subject: [PATCH 098/241] Rename plotting file `CylindricalAnnulus.jl` -> `EllipticalSurface.jl` and include it again --- .../SurfacePrimitives/CylindricalAnnulus.jl | 41 ------------------- .../SurfacePrimitives/EllipticalSurface.jl | 41 +++++++++++++++++++ 2 files changed, 41 insertions(+), 41 deletions(-) delete mode 100644 src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/CylindricalAnnulus.jl create mode 100644 src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/CylindricalAnnulus.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/CylindricalAnnulus.jl deleted file mode 100644 index c829e11e2..000000000 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/CylindricalAnnulus.jl +++ /dev/null @@ -1,41 +0,0 @@ -function get_plot_points(a::CylindricalAnnulus{T}; n = 30) where {T <: AbstractFloat} - - plot_points = Vector{CartesianPoint{T}}[] - - rMin::T, rMax::T = get_r_limits(a) - φMin::T, φMax::T, φ_is_full_2π::Bool = get_φ_limits(a) - φrange = range(φMin, φMax, length = n + 1) - - #circle(s) - for r in [rMin, rMax] - if r == 0 continue end - push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(r * cos(φ), r * sin(φ), a.z) for φ in φrange])) - end - - #for incomplete φ: lines of cross-sections - if !φ_is_full_2π - for φ in [φMin, φMax] - push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(rMin * cos(φ), rMin * sin(φ), a.z), CartesianPoint{T}(rMax * cos(φ), rMax * sin(φ), a.z)])) - end - end - plot_points -end - -function mesh(a::CylindricalAnnulus{T}; n = 30) where {T <: AbstractFloat} - - rMin::T, rMax::T = get_r_limits(a) - φMin::T, φMax::T, _ = get_φ_limits(a) - f = (φMax - φMin)/(2π) - n = Int(ceil(n*f)) - φrange = range(φMin, φMax, length = n+1) - sφrange = sin.(φrange) - cφrange = cos.(φrange) - r = range(rMin, rMax, length = 2) - z = fill(a.z, length(r)) - - X::Array{T,2} = [r_j*cφ for cφ in cφrange, r_j in r] - Y::Array{T,2} = [r_j*sφ for sφ in sφrange, r_j in r] - Z::Array{T,2} = [z_j for i in 1:n+1, z_j in z] - - Mesh(X, Y, Z) -end diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl new file mode 100644 index 000000000..e4e127568 --- /dev/null +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl @@ -0,0 +1,41 @@ +# function get_plot_points(a::CylindricalAnnulus{T}; n = 30) where {T <: AbstractFloat} + +# plot_points = Vector{CartesianPoint{T}}[] + +# rMin::T, rMax::T = get_r_limits(a) +# φMin::T, φMax::T, φ_is_full_2π::Bool = get_φ_limits(a) +# φrange = range(φMin, φMax, length = n + 1) + +# #circle(s) +# for r in [rMin, rMax] +# if r == 0 continue end +# push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(r * cos(φ), r * sin(φ), a.z) for φ in φrange])) +# end + +# #for incomplete φ: lines of cross-sections +# if !φ_is_full_2π +# for φ in [φMin, φMax] +# push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(rMin * cos(φ), rMin * sin(φ), a.z), CartesianPoint{T}(rMax * cos(φ), rMax * sin(φ), a.z)])) +# end +# end +# plot_points +# end + +# function mesh(a::CylindricalAnnulus{T}; n = 30) where {T <: AbstractFloat} + +# rMin::T, rMax::T = get_r_limits(a) +# φMin::T, φMax::T, _ = get_φ_limits(a) +# f = (φMax - φMin)/(2π) +# n = Int(ceil(n*f)) +# φrange = range(φMin, φMax, length = n+1) +# sφrange = sin.(φrange) +# cφrange = cos.(φrange) +# r = range(rMin, rMax, length = 2) +# z = fill(a.z, length(r)) + +# X::Array{T,2} = [r_j*cφ for cφ in cφrange, r_j in r] +# Y::Array{T,2} = [r_j*sφ for sφ in sφrange, r_j in r] +# Z::Array{T,2} = [z_j for i in 1:n+1, z_j in z] + +# Mesh(X, Y, Z) +# end From 441d98ddfd3f498ca49f352b3ed8d25314da00ec Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 09:02:31 +0200 Subject: [PATCH 099/241] Add plot recipe for `EllipticalSurface` --- .../plotting/SurfacePrimitives/EllipticalSurface.jl | 7 +++++++ .../plotting/SurfacePrimitives/SurfacePrimitives.jl | 1 + 2 files changed, 8 insertions(+) diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl index e4e127568..632b34457 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl @@ -1,3 +1,10 @@ +@recipe function f(es::EllipticalSurface) + @series begin + Ellipse(es) + end +end + + # function get_plot_points(a::CylindricalAnnulus{T}; n = 30) where {T <: AbstractFloat} # plot_points = Vector{CartesianPoint{T}}[] diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl index 0d5dd1f54..9fb710d31 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl @@ -1,4 +1,5 @@ include("Polygon.jl") +include("EllipticalSurface.jl") @recipe function f(vp::AbstractVector{<:AbstractSurfacePrimitive}) linecolor --> :black From 7621f333a6639fa417293e93853ba7c05843c628 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 09:04:41 +0200 Subject: [PATCH 100/241] Add plotting-file `ConeMantle.jl` again --- .../plotting/SurfacePrimitives/ConeMantle.jl | 82 +++++++++---------- .../SurfacePrimitives/SurfacePrimitives.jl | 1 + 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl index 33d47fefd..c3dbaccc0 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl @@ -1,41 +1,41 @@ -function get_plot_points(c::ConeMantle{T}; n = 30) where {T <: AbstractFloat} - - plot_points = Vector{CartesianPoint{T}}[] - - rbot::T, rtop::T = get_r_limits(c) - φMin::T, φMax::T, φ_is_full_2π::Bool = get_φ_limits(c) - zMin::T, zMax::T = get_z_limits(c) - - φrange = range(φMin, φMax, length = n + 1) - - #top and bottom circles - rbot != 0 ? push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(rbot * cos(φ), rbot * sin(φ), zMin) for φ in φrange])) : nothing - rtop != 0 ? push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(rtop * cos(φ), rtop * sin(φ), zMax) for φ in φrange])) : nothing - - #side line(s) - for φ in (φ_is_full_2π ? T(0) : [φMin, φMax]) - if rbot != 0 || rtop != 0 - push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(rbot * cos(φ), rbot * sin(φ), zMin), CartesianPoint{T}(rtop * cos(φ), rtop * sin(φ), zMax)])) - end - end - plot_points -end - -function mesh(c::ConeMantle{T}; n = 30) where {T <: AbstractFloat} - - rbot::T, rtop::T = get_r_limits(c) - φMin::T, φMax::T, _ = get_φ_limits(c) - zMin::T, zMax::T = get_z_limits(c) - f = (φMax - φMin)/(2π) - n = Int(ceil(n*f)) - m = (rtop-rbot)/(zMax-zMin) - φrange = range(φMin, φMax, length = n+1) - scφrange = sincos.(φrange) - z = (zMin, zMax) - - X::Array{T,2} = [(m*(z_i-zMin)+rbot)*cφ for (_,cφ) in scφrange, z_i in z] - Y::Array{T,2} = [(m*(z_i-zMin)+rbot)*sφ for (sφ,_) in scφrange, z_i in z] - Z::Array{T,2} = [j for i in φrange, j in z] - - Mesh(X, Y, Z) -end +# function get_plot_points(c::ConeMantle{T}; n = 30) where {T <: AbstractFloat} + +# plot_points = Vector{CartesianPoint{T}}[] + +# rbot::T, rtop::T = get_r_limits(c) +# φMin::T, φMax::T, φ_is_full_2π::Bool = get_φ_limits(c) +# zMin::T, zMax::T = get_z_limits(c) + +# φrange = range(φMin, φMax, length = n + 1) + +# #top and bottom circles +# rbot != 0 ? push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(rbot * cos(φ), rbot * sin(φ), zMin) for φ in φrange])) : nothing +# rtop != 0 ? push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(rtop * cos(φ), rtop * sin(φ), zMax) for φ in φrange])) : nothing + +# #side line(s) +# for φ in (φ_is_full_2π ? T(0) : [φMin, φMax]) +# if rbot != 0 || rtop != 0 +# push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(rbot * cos(φ), rbot * sin(φ), zMin), CartesianPoint{T}(rtop * cos(φ), rtop * sin(φ), zMax)])) +# end +# end +# plot_points +# end + +# function mesh(c::ConeMantle{T}; n = 30) where {T <: AbstractFloat} + +# rbot::T, rtop::T = get_r_limits(c) +# φMin::T, φMax::T, _ = get_φ_limits(c) +# zMin::T, zMax::T = get_z_limits(c) +# f = (φMax - φMin)/(2π) +# n = Int(ceil(n*f)) +# m = (rtop-rbot)/(zMax-zMin) +# φrange = range(φMin, φMax, length = n+1) +# scφrange = sincos.(φrange) +# z = (zMin, zMax) + +# X::Array{T,2} = [(m*(z_i-zMin)+rbot)*cφ for (_,cφ) in scφrange, z_i in z] +# Y::Array{T,2} = [(m*(z_i-zMin)+rbot)*sφ for (sφ,_) in scφrange, z_i in z] +# Z::Array{T,2} = [j for i in φrange, j in z] + +# Mesh(X, Y, Z) +# end diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl index 9fb710d31..a6f18d7da 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl @@ -1,5 +1,6 @@ include("Polygon.jl") include("EllipticalSurface.jl") +include("ConeMantle.jl") @recipe function f(vp::AbstractVector{<:AbstractSurfacePrimitive}) linecolor --> :black From df15042723d6984ec59a017ef88fc610be5de1e6 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 09:28:36 +0200 Subject: [PATCH 101/241] Remove `@info` output --- src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl index aa0fd8e75..ac1105010 100644 --- a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl @@ -8,7 +8,6 @@ end @recipe function f(e::Ellipse; n = 40) @series begin label --> "Ellipse" - @info n edges(e, n = n) end end From abbbbd6ff9f25f033d9834688a554df43185ea63 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 09:28:53 +0200 Subject: [PATCH 102/241] Add simple plot recipe for `ConeMantle` --- .../plotting/SurfacePrimitives/ConeMantle.jl | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl index c3dbaccc0..d839d2dde 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl @@ -1,3 +1,26 @@ +@recipe function f(cm::ConeMantle, n = 40; subn = 10) + T = typeof(cm.hZ) + ehZ = CartesianPoint(zero(T), zero(T), cm.hZ) + e_top = Ellipse(cm.r, cm.φ, cm.origin + cm.rotation * ehZ, cm.rotation) + e_bot = Ellipse(cm.r, cm.φ, cm.origin - cm.rotation * ehZ, cm.rotation) + e_top_edges = edges(e_top, n = n) + e_bot_edges = edges(e_bot, n = n) + linecolor --> :black + @series begin + label --> "Cone Mantle" + e_top_edges + end + @series begin + label := nothing + e_bot_edges + end + @series begin + label := nothing + map(i -> Edge(e_top_edges[i].a, e_bot_edges[i].a), 1:subn:length(e_top_edges)) + end +end + + # function get_plot_points(c::ConeMantle{T}; n = 30) where {T <: AbstractFloat} # plot_points = Vector{CartesianPoint{T}}[] From 1c20f11c6e26bd352f88d9b80bc996ed4a65083d Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 09:39:35 +0200 Subject: [PATCH 103/241] Change structure `ConeMantle`. Add origin and rotation again. --- .../SurfacePrimitives/ConeMantle.jl | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index 265c7c3f8..c362ee023 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -22,14 +22,11 @@ T: Type of values, e.g. Float64 φ::TP = nothing hZ::T = 1 # maybe we don't need this. I will leave it for now... - axis::Line{T} = Line{T}(CartesianPoint{T}(zero(T), zero(T), -hZ), CartesianVector{T}(zero(T), zero(T), 2hZ)) + # axis::Line{T} = Line{T}(CartesianPoint{T}(zero(T), zero(T), -hZ), CartesianVector{T}(zero(T), zero(T), 2hZ)) + origin::CartesianPoint{T} = zero(CartesianPoint{T}) + rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -function ConeMantle(t::Tube{T}) where {T} - bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) - top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - ConeMantle{T,T,Nothing}(t.r, t.φ, t.hZ, Line{T}(bot_center_pt, top_center_pt - bot_center_pt)) -end # function ConeMantle(c::Cone{T}; rbot = 1, rtop = 1) where {T} # r = rbot == rtop ? T(rbot) : (T(rbot), T(rtop)) From eb18b75f09be95e951ad4f2a85e6f0a53e67c6fd Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 09:40:06 +0200 Subject: [PATCH 104/241] Add `EllipticalSurface` primitive --- .../SurfacePrimitives/EllipticalSurface.jl | 254 +++++++++--------- .../SurfacePrimitives/SurfacePrimitives.jl | 3 +- 2 files changed, 135 insertions(+), 122 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl index 71ee83235..663e80ec9 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl @@ -1,123 +1,135 @@ -struct EllipticalSurface{T,TR,TP} <: AbstractSurfacePrimitive{T} - r::TR - φ::TP - z::T - function CylindricalAnnulus( ::Type{T}, - r::Union{T, <:AbstractInterval{T}}, - φ::Union{Nothing, <:AbstractInterval{T}}, - z::T) where {T} - new{T,typeof(r),typeof(φ)}(r, φ, z) - end +""" + EllipticalSurface{T,TR,TP} <: AbstractSurfacePrimitive{T} + +* `r::TR`: + * TR = Real -> Full Circle (a = b = r) + * TR = (Real, Real) -> Circular Annulus (r_in = r[1], r_out = r[2]) + * TR = ((Real,), (Real,)) -> Full Ellipse (a = r[1][1], b = r[2][1]) + * TR = ((Real, Real),(Real, Real)) -> Elliptical Annulus \n(a_in = r[1][1], a_out = r[1][2], b_in = r[2][1], b_out = r[2][2]) + * Not all are implemented yet + +* `φ::TP`: + * TP = Nothing <-> Full in φ + * ... +""" +@with_kw struct EllipticalSurface{T,TR,TP} <: AbstractSurfacePrimitive{T} + r::TR = 1 + φ::TP = nothing + + origin::CartesianPoint{T} = zero(CartesianPoint{T}) + rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -#Constructors -CylindricalAnnulus(c::Cone{T}; z = 0) where {T} = CylindricalAnnulus(T, get_r_at_z(c,z), c.φ, T(z)) - -function CylindricalAnnulus(t::Torus{T}; θ = 0) where {T} - r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) - θ = T(mod(θ,2π)) - if θ == T(0) - rMin = t.r_torus + r_tubeMin - rMax = t.r_torus + r_tubeMax - elseif θ == T(π) - rMin = t.r_torus - r_tubeMax - rMax = t.r_torus - r_tubeMin - else - @error "CylindricalAnnulus not defined for torroidal cordinate θ ≠ 0 and θ ≠ π. Use ConeMantle" - end - r = rMin == 0 ? T(rMax) : T(rMin)..T(rMax) - CylindricalAnnulus( T, r, t.φ, t.z) -end - - -function CylindricalAnnulus(; rMin = 0, rMax = 1, φMin = 0, φMax = 2π, z = 0) - T = float(promote_type(typeof.((rMin, rMax, φMin, φMax, z))...)) - r = rMin == 0 ? T(rMax) : T(rMin)..T(rMax) - φ = mod(T(φMax) - T(φMin), T(2π)) == 0 ? nothing : T(φMin)..T(φMax) - CylindricalAnnulus(T, r, φ, T(z)) -end - -CylindricalAnnulus(rMin, rMax, φMin, φMax, z) = CylindricalAnnulus(;rMin = rMin, rMax = rMax, φMin = φMin, φMax = φMax, z = z) - -function CylindricalAnnulus(r::Real, z::Real) - T = float(promote_type(typeof.((r, z))...)) - CylindricalAnnulus(T, T(r), nothing, T(z)) -end - -get_r_limits(a::CylindricalAnnulus{T, <:Union{T, AbstractInterval{T}}, <:Any}) where {T} = - (_left_radial_interval(a.r), _right_radial_interval(a.r)) - -get_φ_limits(a::CylindricalAnnulus{T, <:Any, Nothing}) where {T} = (T(0), T(2π), true) -get_φ_limits(a::CylindricalAnnulus{T, <:Any, <:AbstractInterval}) where {T} = (a.φ.left, a.φ.right, false) - -in(p::AbstractCoordinatePoint, a::CylindricalAnnulus{T, <:Any, Nothing}) where {T} = _isapprox_z(p, a.z) && _in_cyl_r(p, a.r) - -in(p::AbstractCoordinatePoint, a::CylindricalAnnulus{T, <:Any, <:AbstractInterval}) where {T} = _isapprox_z(p, a.z) && _in_φ(p, a.φ) && _in_cyl_r(p, a.r) - -#= -function sample(a::CylindricalAnnulus{T}, step::Real)::Vector{CylindricalPoint{T}} where {T} - rMin::T, rMax::T = get_r_limits(a) - φMin::T, φMax::T, _ = get_φ_limits(a) - samples = [ - CylindricalPoint{T}(r,φ,a.z) - for r in rMin:step:rMax - for φ in (r == 0 ? φMin : φMin:step/r:φMax) - ] -end -=# - -function sample(a::CylindricalAnnulus{T}, Nsamps::NTuple{3,Int})::Vector{CylindricalPoint{T}} where {T} - rMin::T, rMax::T = get_r_limits(a) - φMin::T, φMax::T, _ = get_φ_limits(a) - samples = [ - CylindricalPoint{T}(r,φ,a.z) - for r in (Nsamps[1] ≤ 1 ? rMin : range(rMin, rMax, length = Nsamps[1])) - for φ in (Nsamps[2] ≤ 1 ? φMin : range(φMin, φMax, length = Nsamps[2])) - ] -end - -function sample(a::CylindricalAnnulus{T}, g::CylindricalTicksTuple{T})::Vector{CylindricalPoint{T}} where {T} - samples = [ - CylindricalPoint{T}(r,φ,a.z) - for r in get_r_ticks(a, g) - for φ in get_φ_ticks(a, g) - ] -end - -function sample(a::CylindricalAnnulus{T}, g::CartesianTicksTuple{T})::Vector{CartesianPoint{T}} where {T} - L::T = _left_radial_interval(a.r) - R::T = _right_radial_interval(a.r) - samples = [ - CartesianPoint{T}(x,y,a.z) - for x in _get_ticks(g.x, -R, R) - for y in (abs(x) > L ? _get_ticks(g.y, -sqrt(R^2 - x^2), sqrt(R^2 - x^2)) : vcat(_get_ticks(g.y, -sqrt(R^2 - x^2), -sqrt(L^2 - x^2)), _get_ticks(g.y, sqrt(L^2 - x^2), sqrt(R^2 - x^2)))) - if a.φ === nothing || mod(atan(y, x), T(2π)) in a.φ - ] -end - -function distance_to_surface(point::AbstractCoordinatePoint{T}, a::CylindricalAnnulus{T, <:Any, Nothing})::T where {T} - point = CylindricalPoint(point) - rMin::T, rMax::T = get_r_limits(a) - _in_cyl_r(point, a.r) ? abs(point.z - a.z) : hypot(point.z - a.z, min(abs(point.r - rMin), abs(point.r - rMax))) -end - -function distance_to_surface(point::AbstractCoordinatePoint{T}, a::CylindricalAnnulus{T, <:Any, <:AbstractInterval})::T where {T} - pcy = CylindricalPoint(point) - rMin::T, rMax::T = get_r_limits(a) - φMin::T, φMax::T, _ = get_φ_limits(a) - if _in_φ(pcy, a.φ) - Δz = abs(pcy.z - a.z) - return _in_cyl_r(pcy, a.r) ? Δz : hypot(Δz, min(abs(pcy.r - rMin), abs(pcy.r - rMax))) - else - φNear = _φNear(pcy.φ, φMin, φMax) - if rMin == rMax - return norm(CartesianPoint(point)-CartesianPoint(CylindricalPoint{T}(rMin,φNear,a.z))) - else - return distance_to_line(CartesianPoint(point), - LineSegment(T,CartesianPoint(CylindricalPoint{T}(rMin,φNear,a.z)), - CartesianPoint(CylindricalPoint{T}(rMax,φNear,a.z)) - ) - ) - end - end -end +Ellipse(es::EllipticalSurface) = Ellipse(r = es.r, φ = es.φ, origin = es.origin, rotation = es.rotation) + +# #Constructors +# CylindricalAnnulus(c::Cone{T}; z = 0) where {T} = CylindricalAnnulus(T, get_r_at_z(c,z), c.φ, T(z)) + +# function CylindricalAnnulus(t::Torus{T}; θ = 0) where {T} +# r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) +# θ = T(mod(θ,2π)) +# if θ == T(0) +# rMin = t.r_torus + r_tubeMin +# rMax = t.r_torus + r_tubeMax +# elseif θ == T(π) +# rMin = t.r_torus - r_tubeMax +# rMax = t.r_torus - r_tubeMin +# else +# @error "CylindricalAnnulus not defined for torroidal cordinate θ ≠ 0 and θ ≠ π. Use ConeMantle" +# end +# r = rMin == 0 ? T(rMax) : T(rMin)..T(rMax) +# CylindricalAnnulus( T, r, t.φ, t.z) +# end + + +# function CylindricalAnnulus(; rMin = 0, rMax = 1, φMin = 0, φMax = 2π, z = 0) +# T = float(promote_type(typeof.((rMin, rMax, φMin, φMax, z))...)) +# r = rMin == 0 ? T(rMax) : T(rMin)..T(rMax) +# φ = mod(T(φMax) - T(φMin), T(2π)) == 0 ? nothing : T(φMin)..T(φMax) +# CylindricalAnnulus(T, r, φ, T(z)) +# end + +# CylindricalAnnulus(rMin, rMax, φMin, φMax, z) = CylindricalAnnulus(;rMin = rMin, rMax = rMax, φMin = φMin, φMax = φMax, z = z) + +# function CylindricalAnnulus(r::Real, z::Real) +# T = float(promote_type(typeof.((r, z))...)) +# CylindricalAnnulus(T, T(r), nothing, T(z)) +# end + +# get_r_limits(a::CylindricalAnnulus{T, <:Union{T, AbstractInterval{T}}, <:Any}) where {T} = +# (_left_radial_interval(a.r), _right_radial_interval(a.r)) + +# get_φ_limits(a::CylindricalAnnulus{T, <:Any, Nothing}) where {T} = (T(0), T(2π), true) +# get_φ_limits(a::CylindricalAnnulus{T, <:Any, <:AbstractInterval}) where {T} = (a.φ.left, a.φ.right, false) + +# in(p::AbstractCoordinatePoint, a::CylindricalAnnulus{T, <:Any, Nothing}) where {T} = _isapprox_z(p, a.z) && _in_cyl_r(p, a.r) + +# in(p::AbstractCoordinatePoint, a::CylindricalAnnulus{T, <:Any, <:AbstractInterval}) where {T} = _isapprox_z(p, a.z) && _in_φ(p, a.φ) && _in_cyl_r(p, a.r) + +# #= +# function sample(a::CylindricalAnnulus{T}, step::Real)::Vector{CylindricalPoint{T}} where {T} +# rMin::T, rMax::T = get_r_limits(a) +# φMin::T, φMax::T, _ = get_φ_limits(a) +# samples = [ +# CylindricalPoint{T}(r,φ,a.z) +# for r in rMin:step:rMax +# for φ in (r == 0 ? φMin : φMin:step/r:φMax) +# ] +# end +# =# + +# function sample(a::CylindricalAnnulus{T}, Nsamps::NTuple{3,Int})::Vector{CylindricalPoint{T}} where {T} +# rMin::T, rMax::T = get_r_limits(a) +# φMin::T, φMax::T, _ = get_φ_limits(a) +# samples = [ +# CylindricalPoint{T}(r,φ,a.z) +# for r in (Nsamps[1] ≤ 1 ? rMin : range(rMin, rMax, length = Nsamps[1])) +# for φ in (Nsamps[2] ≤ 1 ? φMin : range(φMin, φMax, length = Nsamps[2])) +# ] +# end + +# function sample(a::CylindricalAnnulus{T}, g::CylindricalTicksTuple{T})::Vector{CylindricalPoint{T}} where {T} +# samples = [ +# CylindricalPoint{T}(r,φ,a.z) +# for r in get_r_ticks(a, g) +# for φ in get_φ_ticks(a, g) +# ] +# end + +# function sample(a::CylindricalAnnulus{T}, g::CartesianTicksTuple{T})::Vector{CartesianPoint{T}} where {T} +# L::T = _left_radial_interval(a.r) +# R::T = _right_radial_interval(a.r) +# samples = [ +# CartesianPoint{T}(x,y,a.z) +# for x in _get_ticks(g.x, -R, R) +# for y in (abs(x) > L ? _get_ticks(g.y, -sqrt(R^2 - x^2), sqrt(R^2 - x^2)) : vcat(_get_ticks(g.y, -sqrt(R^2 - x^2), -sqrt(L^2 - x^2)), _get_ticks(g.y, sqrt(L^2 - x^2), sqrt(R^2 - x^2)))) +# if a.φ === nothing || mod(atan(y, x), T(2π)) in a.φ +# ] +# end + +# function distance_to_surface(point::AbstractCoordinatePoint{T}, a::CylindricalAnnulus{T, <:Any, Nothing})::T where {T} +# point = CylindricalPoint(point) +# rMin::T, rMax::T = get_r_limits(a) +# _in_cyl_r(point, a.r) ? abs(point.z - a.z) : hypot(point.z - a.z, min(abs(point.r - rMin), abs(point.r - rMax))) +# end + +# function distance_to_surface(point::AbstractCoordinatePoint{T}, a::CylindricalAnnulus{T, <:Any, <:AbstractInterval})::T where {T} +# pcy = CylindricalPoint(point) +# rMin::T, rMax::T = get_r_limits(a) +# φMin::T, φMax::T, _ = get_φ_limits(a) +# if _in_φ(pcy, a.φ) +# Δz = abs(pcy.z - a.z) +# return _in_cyl_r(pcy, a.r) ? Δz : hypot(Δz, min(abs(pcy.r - rMin), abs(pcy.r - rMax))) +# else +# φNear = _φNear(pcy.φ, φMin, φMax) +# if rMin == rMax +# return norm(CartesianPoint(point)-CartesianPoint(CylindricalPoint{T}(rMin,φNear,a.z))) +# else +# return distance_to_line(CartesianPoint(point), +# LineSegment(T,CartesianPoint(CylindricalPoint{T}(rMin,φNear,a.z)), +# CartesianPoint(CylindricalPoint{T}(rMax,φNear,a.z)) +# ) +# ) +# end +# end +# end diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl index 8f175632d..e373104d5 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl @@ -1,3 +1,4 @@ include("Plane.jl") include("Polygon.jl") -include("ConeMantle.jl") \ No newline at end of file +include("ConeMantle.jl") +include("EllipticalSurface.jl") \ No newline at end of file From eaa59858e5146025e813190e10ec1ecbfb213263 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 09:40:34 +0200 Subject: [PATCH 105/241] Fix read-in for `Cone` and `surfaces(t::Tube)` --- .../VolumePrimitives/Cone.jl | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index e78111fcb..80cc8d2d3 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -82,14 +82,19 @@ function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::Nam angle_unit = input_units.angle r = parse_r_of_primitive(T, dict, length_unit) φ = parse_φ_of_primitive(T, dict, angle_unit) - h = parse_height_of_primitive(T, dict, length_unit) - return Cone{T, ClosedPrimitive, typeof(r), typeof(φ)}(r = r, φ = φ, hZ = h/2) + hZ = parse_height_of_primitive(T, dict, length_unit) + cone = Cone{T, ClosedPrimitive, typeof(r), typeof(φ)}(r = r, φ = φ, hZ = hZ) + return transform(cone, transformations) end function surfaces(t::Tube{T}) where {T} - mantle = ConeMantle(t) - e_bot = Ellipse{T,T,Nothing}(r = t.r, φ = nothing, origin = mantle.axis.origin, rotation = t.rotation) - e_top = Ellipse{T,T,Nothing}(r = t.r, φ = nothing, origin = mantle.axis.origin + mantle.axis.direction, rotation = t.rotation) + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + mantle = ConeMantle{T,T,Nothing}(t.r, t.φ, t.hZ, t.origin, t.rotation) + bot_normal = top_center_pt - bot_center_pt + e_bot = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = bot_center_pt, rotation = t.rotation) + e_top = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = top_center_pt, rotation = t.rotation) + # normals of the surfaces show inside the volume primitives. e_top, e_bot, mantle end From ed84ac2ff81c267fc0943aa4f4f6d66bc4fc70a0 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 09:41:26 +0200 Subject: [PATCH 106/241] Add `test_detector.yaml` --- .../example_config_files/test_detector.yaml | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 examples/example_config_files/test_detector.yaml diff --git a/examples/example_config_files/test_detector.yaml b/examples/example_config_files/test_detector.yaml new file mode 100644 index 000000000..f9ca4d8a2 --- /dev/null +++ b/examples/example_config_files/test_detector.yaml @@ -0,0 +1,84 @@ +name: TestDetector +units: + length: mm + angle: deg + potential: V + temperature: K +grid: + coordinates: cartesian + axes: + x: + from: -9 + to: 9 + boundaries: inf + y: + from: -9 + to: 9 + boundaries: inf + z: + from: -9 + to: 9 + boundaries: inf +medium: vacuum +detectors: + - translate: + x: 0 + rotate: + Z: 0 + bulk: + material: HPGe + temperature: 78 + impurity_density: + name: linear + x: + init: 0 + gradient: 0 + y: + init: 0 + gradient: 0 + z: + init: 10000000 + gradient: 50000 + charge_drift_model: + include: ADLChargeDriftModel/drift_velocity_config.json + geometry: + tube: + r: 5 # width in x + h: 8 # width in z + contacts: + - material: HPGe + name: n+ contact + potential: 2000 + channel: 1 + geometry: + translate: + z: -3.9 + tube: + r: 1 + h: 0.2 + - material: HPGe + name: p+ contact + potential: 0 + channel: 2 + geometry: + translate: + z: 3.9 + tube: + r: 3 + h: 0.2 + +surroundings: + - name: Base + material: Copper + potential: 0 + geometry: + box: + x: + from: -9 + to: 9 + y: + from: -9 + to: 9 + z: + from: -9 + to: -7 \ No newline at end of file From 494ab125d0d6eea1b3ab74aa8af26ccc6cfd1b43 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 09:51:05 +0200 Subject: [PATCH 107/241] Add `sample` method for `Tube` --- .../VolumePrimitives/Cone.jl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 80cc8d2d3..7148d39db 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -212,5 +212,20 @@ end # ] # end +function sample(t::Tube{T}; n = 4) where {T} + # this could be improved performance-vise, + # but not that important right now as it is only called + # in the initzialiaton of the grid. + ehZ = CartesianPoint(zero(T), zero(T), t.hZ) + e_top = Ellipse(t.r, t.φ, t.origin + t.rotation * ehZ, t.rotation) + e_bot = Ellipse(t.r, t.φ, t.origin - t.rotation * ehZ, t.rotation) + φs = range(0, step = 2π / n, length = n) + pts_top = [CartesianPoint(CylindricalPoint{T}(e_top.r, φ, zero(T))) for φ in φs] + pts_top = map(p -> _transform_into_global_coordinate_system(p, e_top), pts_top) + pts_bot = [CartesianPoint(CylindricalPoint{T}(e_bot.r, φ, zero(T))) for φ in φs] + pts_bot = map(p -> _transform_into_global_coordinate_system(p, e_bot), pts_bot) + vcat(pts_bot, pts_top) +end + # @inline sample(c::Cone{T}) where {T} = sample(c, (2,3,3)) # @inline sample(c::Cone{T, <:Any, Nothing}) where {T} = sample(c, (2,5,3)) From 54dfa9d2264f54d9f951086f9fe842377adb4b82 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 10:04:29 +0200 Subject: [PATCH 108/241] Add abstract types `AbstractFlatSurfacePrimitive` & `AbstractBentSurfacePrimitive` --- src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl | 2 +- .../SurfacePrimitives/EllipticalSurface.jl | 4 +++- src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl | 4 +--- src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl | 2 +- .../SurfacePrimitives/SurfacePrimitives.jl | 3 +++ src/SolidStateDetectors.jl | 2 +- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index c362ee023..a916d0ade 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -17,7 +17,7 @@ T: Type of values, e.g. Float64 * `axis::Line{T}`: The axis of the Cone mantle. Going from the bottom center point to the top center point. """ -@with_kw struct ConeMantle{T,RT,TP} <: AbstractSurfacePrimitive{T} +@with_kw struct ConeMantle{T,RT,TP} <: AbstractBentSurfacePrimitive{T} r::RT = 1 φ::TP = nothing hZ::T = 1 # maybe we don't need this. I will leave it for now... diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl index 663e80ec9..d61005acc 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl @@ -12,7 +12,7 @@ * TP = Nothing <-> Full in φ * ... """ -@with_kw struct EllipticalSurface{T,TR,TP} <: AbstractSurfacePrimitive{T} +@with_kw struct EllipticalSurface{T,TR,TP} <: AbstractFlatSurfacePrimitive{T} r::TR = 1 φ::TP = nothing @@ -22,6 +22,8 @@ end Ellipse(es::EllipticalSurface) = Ellipse(r = es.r, φ = es.φ, origin = es.origin, rotation = es.rotation) +Plane(es::EllipticalSurface{T}) where {T} = Plane{T}(es.origin, es.rotation * CartesianVector{T}(zero(T),zero(T),one(T))) + # #Constructors # CylindricalAnnulus(c::Cone{T}; z = 0) where {T} = CylindricalAnnulus(T, get_r_at_z(c,z), c.φ, T(z)) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl index 94c1b023c..fedca9061 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl @@ -1,6 +1,4 @@ -abstract type AbstractPlane{T} <: AbstractSurfacePrimitive{T} end - -struct Plane{T} <: AbstractPlane{T} +struct Plane{T} <: AbstractFlatSurfacePrimitive{T} origin::CartesianPoint{T} normal::CartesianVector{T} Plane{T}(o, n) where {T} = new{T}(o, normalize(n)) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl index 739a5d520..ec25e7fa9 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl @@ -1,5 +1,5 @@ -struct Polygon{N,T} <: AbstractPlane{T} +struct Polygon{N,T} <: AbstractFlatSurfacePrimitive{T} points::SVector{N, CartesianPoint{T}} end const Triangle{T} = Polygon{3, T} diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl index e373104d5..ce23e66c9 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl @@ -1,3 +1,6 @@ +abstract type AbstractFlatSurfacePrimitive{T} <: AbstractSurfacePrimitive{T} end +abstract type AbstractBentSurfacePrimitive{T} <: AbstractSurfacePrimitive{T} end + include("Plane.jl") include("Polygon.jl") include("ConeMantle.jl") diff --git a/src/SolidStateDetectors.jl b/src/SolidStateDetectors.jl index 6810d15ff..95fc08557 100644 --- a/src/SolidStateDetectors.jl +++ b/src/SolidStateDetectors.jl @@ -34,7 +34,7 @@ using .ConstructiveSolidGeometry: Cartesian, Cylindrical, AbstractCoordinateSystem, CoordinateSystemType, CartesianTicksTuple, CylindricalTicksTuple, Geometry, AbstractGeometry, - AbstractSurfacePrimitive, + AbstractSurfacePrimitive, AbstractFlatSurfacePrimitive, AbstractBentSurfacePrimitive, geom_round, geom_sigdigits, geom_atol_zero, parse_rotation_matrix, parse_translate_vector, parse_CSG_transformation, transform, CSG_dict, Transformations, combine_transformations From fcb1ff20babd837aff8dd803eb82092c15ef55fa Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 10:30:58 +0200 Subject: [PATCH 109/241] Fix config file --- examples/example_config_files/test_detector.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/example_config_files/test_detector.yaml b/examples/example_config_files/test_detector.yaml index f9ca4d8a2..482c0025b 100644 --- a/examples/example_config_files/test_detector.yaml +++ b/examples/example_config_files/test_detector.yaml @@ -52,7 +52,7 @@ detectors: channel: 1 geometry: translate: - z: -3.9 + z: -3.95 tube: r: 1 h: 0.2 @@ -62,7 +62,7 @@ detectors: channel: 2 geometry: translate: - z: 3.9 + z: 3.95 tube: r: 3 h: 0.2 From cb6117b3baca4bda10bd38c857c051028c3704fd Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 10:31:50 +0200 Subject: [PATCH 110/241] Make polygon-`paint!` method general for all flat-surface types --- src/PotentialSimulation/Painting/Polygon.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PotentialSimulation/Painting/Polygon.jl b/src/PotentialSimulation/Painting/Polygon.jl index b4d3097e8..9d47a945e 100644 --- a/src/PotentialSimulation/Painting/Polygon.jl +++ b/src/PotentialSimulation/Painting/Polygon.jl @@ -1,5 +1,5 @@ -function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, geometry, pot_value, grid::CartesianGrid) +function paint!(pointtypes, potential, face::AbstractFlatSurfacePrimitive, geometry, pot_value, grid::CartesianGrid) ticks = TicksTuple(grid) t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) t1, t2 = if proj == Val{:xy}() @@ -32,7 +32,7 @@ function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon, end nothing end -function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.Polygon{<:Any, T}, geometry, pot_value, grid::CylindricalGrid) where {T} +function paint!(pointtypes, potential, face::AbstractFlatSurfacePrimitive, geometry, pot_value, grid::CylindricalGrid) where {T} ticks = TicksTuple(grid) t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) t1, t2 = if proj == Val{:rφ}() From 3c0a1ca5a1910d7d95414e89dfb93ea19c01d83b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 10:33:09 +0200 Subject: [PATCH 111/241] Add function `extreme_points` needed for each surface in the painting --- .../SurfacePrimitives/EllipticalSurface.jl | 10 ++++++++++ .../SurfacePrimitives/Polygon.jl | 20 ++++++++++--------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl index d61005acc..ebb05ce5e 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl @@ -24,6 +24,16 @@ Ellipse(es::EllipticalSurface) = Ellipse(r = es.r, φ = es.φ, origin = es.origi Plane(es::EllipticalSurface{T}) where {T} = Plane{T}(es.origin, es.rotation * CartesianVector{T}(zero(T),zero(T),one(T))) +normal(es::EllipticalSurface{T}) where {T} = es.rotation * CartesianVector{T}(zero(T), zero(T), one(T)) + +function extreme_points(es::EllipticalSurface{T,TR,Nothing}; n = 4) where {T,TR<:Real} + # this is probably not entirly correct. We need the extreme points of the ellipse + # in the global coordinate system. Not the ones in the object coordinate system. + φs = range(0, step = 2π / n, length = n) + pts = [CartesianPoint(CylindricalPoint{T}(es.r, φ, zero(T))) for φ in φs] + map(p -> _transform_into_global_coordinate_system(p, es), pts) +end + # #Constructors # CylindricalAnnulus(c::Cone{T}; z = 0) where {T} = CylindricalAnnulus(T, get_r_at_z(c,z), c.φ, T(z)) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl index ec25e7fa9..ae7316d8a 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl @@ -9,6 +9,7 @@ normal(p::Polygon) = normalize((p.points[2] - p.points[1]) × (p.points[3] - p.p vertices(p::Polygon) = p.points +extreme_points(p::Polygon) = p.points function edges(p::Triangle{T}) where {T} vs = vertices(p) @@ -113,18 +114,19 @@ function get_min_max_index_ranges(a::Union{ end """ - get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CartesianTicksTuple{T}) where {N, T} + get_2d_grid_ticks_and_proj(pts::AbstractVector{CartesianPoint{T}}, t::CartesianTicksTuple{T}) where {N, T} -This function determines the two best dimensions to sample/paint the surface. +This function determines the two best dimensions to sample/paint a surface to which the points `pts` belong. E.g. `x` & `y` -> `proj = Val{:xy}()`. The dimensions are picked such that the number of points to evaluate is minimal. However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, because, than, there would not be a single value, but infinite ones, for `z` in the evalution. """ -function get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CartesianTicksTuple{T}) where {N, T} +function get_2d_grid_ticks_and_proj(p::AbstractFlatSurfacePrimitive, t::CartesianTicksTuple{T}) where {N, T} # This method would actually work for any flat surface, e.g. elipse - t_idx_range_x, t_idx_range_y, t_idx_range_z = get_min_max_index_ranges((p.points, t)) + pts = extreme_points(p) + t_idx_range_x, t_idx_range_y, t_idx_range_z = get_min_max_index_ranges((pts, t)) ls = (length(t_idx_range_x), length(t_idx_range_y), length(t_idx_range_z)) ls = ( ls[1] == 1 ? typemax(eltype(ls)) : ls[1], @@ -147,18 +149,18 @@ end """ - get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CylindricalTicksTuple{T}) where {N, T} + get_2d_grid_ticks_and_proj(pts::AbstractVector{CartesianPoint{T}}, t::CylindricalTicksTuple{T}) where {N, T} -This function determines the two best dimensions to sample/paint the surface. +This function determines the two best dimensions to sample/paint a surface to which the points `pts` belong. E.g. `r` & `φ` -> `proj = Val{:rφ}()`. The dimensions are picked such that the number of points to evaluate is minimal. However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, because, than, there would not be a single value, but infinite ones, for `z` in the evalution. -The Val{:rz}-case is excluded as there are two intersections with the arc-line and the polygon. """ -function get_2d_grid_ticks_and_proj(p::Polygon{N, T}, t::CylindricalTicksTuple{T}) where {N, T} +function get_2d_grid_ticks_and_proj(p::AbstractFlatSurfacePrimitive, t::CylindricalTicksTuple{T}) where {N, T} # This method would actually work for any flat surface, e.g. elipse - t_idx_range_r, t_idx_range_φ, t_idx_range_z = get_min_max_index_ranges((CylindricalPoint.(p.points), t)) + pts = extreme_points(p) + t_idx_range_r, t_idx_range_φ, t_idx_range_z = get_min_max_index_ranges((CylindricalPoint.(pts), t)) ls = (length(t_idx_range_r), length(t_idx_range_φ), length(t_idx_range_z)) ls = ( ls[1] == 1 ? typemax(eltype(ls)) : ls[1], From 0e531e6dcd4a569d21c6a4f0c5bf945276d22e9e Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 10:48:31 +0200 Subject: [PATCH 112/241] Convention: Normal vectors of surfaces of volumes should direct inside. --- src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 7148d39db..de9ceb226 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -92,8 +92,8 @@ function surfaces(t::Tube{T}) where {T} top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) mantle = ConeMantle{T,T,Nothing}(t.r, t.φ, t.hZ, t.origin, t.rotation) bot_normal = top_center_pt - bot_center_pt - e_bot = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = bot_center_pt, rotation = t.rotation) - e_top = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = top_center_pt, rotation = t.rotation) + e_bot = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = bot_center_pt, rotation = t.rotation) + e_top = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = top_center_pt, rotation = -t.rotation) # normals of the surfaces show inside the volume primitives. e_top, e_bot, mantle end From 86ed307bad64e2a090cfb056047a1a0bc6c7fba7 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 14:43:05 +0200 Subject: [PATCH 113/241] Add a method `_transform_into_object_coordinate_system` for `Line` --- src/ConstructiveSolidGeometry/LinePrimitives/Line.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl index 1be712b50..67cd8c50a 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl @@ -4,3 +4,9 @@ struct Line{T} <: AbstractLinePrimitive{T} end distance(pt::CartesianPoint, l::Line) = norm((pt - l.origin) × l.direction) / norm(l.direction) + +function _transform_into_object_coordinate_system(l::Line{T}, p::AbstractPrimitive) where {T} + origin = _transform_into_object_coordinate_system(l.origin, p) + direction = _transform_into_object_coordinate_system(CartesianPoint{T}(l.direction), p) + Line{T}( origin, direction ) +end \ No newline at end of file From 4982d1f3e91bcad8d29431eece4d4b0d9622a999 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 14:44:31 +0200 Subject: [PATCH 114/241] Move generalized functions `get_2d_grid_ticks_and_proj` --- .../SurfacePrimitives/Polygon.jl | 90 ------------------ .../SurfacePrimitives/SurfacePrimitives.jl | 93 ++++++++++++++++++- 2 files changed, 92 insertions(+), 91 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl index ae7316d8a..b1959d191 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl @@ -90,93 +90,3 @@ function distance(pt::CartesianPoint, p::Polygon) minimum(ds) end end - -function get_min_max_index_ranges(a::Union{ - <:Tuple{AbstractVector{<:CartesianPoint{T}}, CartesianTicksTuple{T}}, - <:Tuple{AbstractVector{<:CylindricalPoint{T}}, CylindricalTicksTuple{T}} - }) where {T} - pts, t = a[1], a[2] - ax1, ax2, ax3 = getindex.(pts, 1), getindex.(pts, 2), getindex.(pts, 3) - ax1_min_idx = searchsortedfirst(t[1], minimum(ax1)) - ax2_min_idx = searchsortedfirst(t[2], minimum(ax2)) - ax3_min_idx = searchsortedfirst(t[3], minimum(ax3)) - ax1_max_idx = searchsortedfirst(t[1], maximum(ax1)) - ax2_max_idx = searchsortedfirst(t[2], maximum(ax2)) - ax3_max_idx = searchsortedfirst(t[3], maximum(ax3)) - ls = (length(t[1]), length(t[2]), length(t[3])) - if ax1_max_idx > ls[1] ax1_max_idx = ls[1] end - if ax2_max_idx > ls[2] ax2_max_idx = ls[2] end - if ax3_max_idx > ls[3] ax3_max_idx = ls[3] end - t_idx_range_ax1 = ax1_min_idx:ax1_max_idx - t_idx_range_ax2 = ax2_min_idx:ax2_max_idx - t_idx_range_ax3 = ax3_min_idx:ax3_max_idx - t_idx_range_ax1, t_idx_range_ax2, t_idx_range_ax3 -end - -""" - get_2d_grid_ticks_and_proj(pts::AbstractVector{CartesianPoint{T}}, t::CartesianTicksTuple{T}) where {N, T} - -This function determines the two best dimensions to sample/paint a surface to which the points `pts` belong. -E.g. `x` & `y` -> `proj = Val{:xy}()`. -The dimensions are picked such that the number of points to evaluate is minimal. -However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, -because, than, there would not be a single value, but infinite ones, -for `z` in the evalution. -""" -function get_2d_grid_ticks_and_proj(p::AbstractFlatSurfacePrimitive, t::CartesianTicksTuple{T}) where {N, T} - # This method would actually work for any flat surface, e.g. elipse - pts = extreme_points(p) - t_idx_range_x, t_idx_range_y, t_idx_range_z = get_min_max_index_ranges((pts, t)) - ls = (length(t_idx_range_x), length(t_idx_range_y), length(t_idx_range_z)) - ls = ( - ls[1] == 1 ? typemax(eltype(ls)) : ls[1], - ls[2] == 1 ? typemax(eltype(ls)) : ls[2], - ls[3] == 1 ? typemax(eltype(ls)) : ls[3] - ) - n = normal(p) - proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) - Val{:xy}(), t_idx_range_x, t_idx_range_y - elseif ls[1] < ls[2] && ls[3] < ls[2] && (n ⋅ CartesianVector{T}(zero(T),one(T),zero(T)) != 0) - Val{:xz}(), t_idx_range_x, t_idx_range_z - elseif n ⋅ CartesianVector{T}(one(T),zero(T), zero(T)) != 0 - Val{:yz}(), t_idx_range_y, t_idx_range_z - else - error("Sampling Error. Have to extend cases") - # Should never happen. This else case can be removed after testing. - end - return t1, t2, proj -end - - -""" - get_2d_grid_ticks_and_proj(pts::AbstractVector{CartesianPoint{T}}, t::CylindricalTicksTuple{T}) where {N, T} - -This function determines the two best dimensions to sample/paint a surface to which the points `pts` belong. -E.g. `r` & `φ` -> `proj = Val{:rφ}()`. -The dimensions are picked such that the number of points to evaluate is minimal. -However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, -because, than, there would not be a single value, but infinite ones, for `z` in the evalution. -""" -function get_2d_grid_ticks_and_proj(p::AbstractFlatSurfacePrimitive, t::CylindricalTicksTuple{T}) where {N, T} - # This method would actually work for any flat surface, e.g. elipse - pts = extreme_points(p) - t_idx_range_r, t_idx_range_φ, t_idx_range_z = get_min_max_index_ranges((CylindricalPoint.(pts), t)) - ls = (length(t_idx_range_r), length(t_idx_range_φ), length(t_idx_range_z)) - ls = ( - ls[1] == 1 ? typemax(eltype(ls)) : ls[1], - ls[2] == 1 ? typemax(eltype(ls)) : ls[2], - ls[3] == 1 ? typemax(eltype(ls)) : ls[3] - ) - n = normal(p) - p_r = p.points[findmax(broadcast(p -> abs(p[1]), p.points))[2]] - # We skip the `:rz`-case as there could be two intersections with the arc and the polygon. - proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) - # evaluate the z value -> same as for the cartesian case - Val{:rφ}(), t_idx_range_r, t_idx_range_φ - elseif ls[2] < ls[1] && ls[3] < ls[1] && (n ⋅ p_r != 0) - Val{:φz}(), t_idx_range_φ, t_idx_range_z - else - Val{:rz}(), t_idx_range_r, t_idx_range_z - end - return t1, t2, proj -end diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl index ce23e66c9..c608c8bc0 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl @@ -4,4 +4,95 @@ abstract type AbstractBentSurfacePrimitive{T} <: AbstractSurfacePrimitive{T} end include("Plane.jl") include("Polygon.jl") include("ConeMantle.jl") -include("EllipticalSurface.jl") \ No newline at end of file +include("EllipticalSurface.jl") + + +function get_min_max_index_ranges(a::Union{ + <:Tuple{AbstractVector{<:CartesianPoint{T}}, CartesianTicksTuple{T}}, + <:Tuple{AbstractVector{<:CylindricalPoint{T}}, CylindricalTicksTuple{T}} + }) where {T} + pts, t = a[1], a[2] + ax1, ax2, ax3 = getindex.(pts, 1), getindex.(pts, 2), getindex.(pts, 3) + ax1_min_idx = searchsortedfirst(t[1], minimum(ax1)) + ax2_min_idx = searchsortedfirst(t[2], minimum(ax2)) + ax3_min_idx = searchsortedfirst(t[3], minimum(ax3)) + ax1_max_idx = searchsortedfirst(t[1], maximum(ax1)) + ax2_max_idx = searchsortedfirst(t[2], maximum(ax2)) + ax3_max_idx = searchsortedfirst(t[3], maximum(ax3)) + ls = (length(t[1]), length(t[2]), length(t[3])) + if ax1_max_idx > ls[1] ax1_max_idx = ls[1] end + if ax2_max_idx > ls[2] ax2_max_idx = ls[2] end + if ax3_max_idx > ls[3] ax3_max_idx = ls[3] end + t_idx_range_ax1 = ax1_min_idx:ax1_max_idx + t_idx_range_ax2 = ax2_min_idx:ax2_max_idx + t_idx_range_ax3 = ax3_min_idx:ax3_max_idx + t_idx_range_ax1, t_idx_range_ax2, t_idx_range_ax3 +end + +""" + get_2d_grid_ticks_and_proj(pts::AbstractVector{CartesianPoint{T}}, t::CartesianTicksTuple{T}) where {N, T} + +This function determines the two best dimensions to sample/paint a surface to which the points `pts` belong. +E.g. `x` & `y` -> `proj = Val{:xy}()`. +The dimensions are picked such that the number of points to evaluate is minimal. +However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, +because, than, there would not be a single value, but infinite ones, +for `z` in the evalution. +""" +function get_2d_grid_ticks_and_proj(p::AbstractFlatSurfacePrimitive, t::CartesianTicksTuple{T}) where {N, T} + # This method would actually work for any flat surface, e.g. elipse + pts = extreme_points(p) + t_idx_range_x, t_idx_range_y, t_idx_range_z = get_min_max_index_ranges((pts, t)) + ls = (length(t_idx_range_x), length(t_idx_range_y), length(t_idx_range_z)) + ls = ( + ls[1] == 1 ? typemax(eltype(ls)) : ls[1], + ls[2] == 1 ? typemax(eltype(ls)) : ls[2], + ls[3] == 1 ? typemax(eltype(ls)) : ls[3] + ) + n = normal(p) + proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) + Val{:xy}(), t_idx_range_x, t_idx_range_y + elseif ls[1] < ls[2] && ls[3] < ls[2] && (n ⋅ CartesianVector{T}(zero(T),one(T),zero(T)) != 0) + Val{:xz}(), t_idx_range_x, t_idx_range_z + elseif n ⋅ CartesianVector{T}(one(T),zero(T), zero(T)) != 0 + Val{:yz}(), t_idx_range_y, t_idx_range_z + else + error("Sampling Error. Have to extend cases") + # Should never happen. This else case can be removed after testing. + end + return t1, t2, proj +end + + +""" + get_2d_grid_ticks_and_proj(pts::AbstractVector{CartesianPoint{T}}, t::CylindricalTicksTuple{T}) where {N, T} + +This function determines the two best dimensions to sample/paint a surface to which the points `pts` belong. +E.g. `r` & `φ` -> `proj = Val{:rφ}()`. +The dimensions are picked such that the number of points to evaluate is minimal. +However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, +because, than, there would not be a single value, but infinite ones, for `z` in the evalution. +""" +function get_2d_grid_ticks_and_proj(p::AbstractFlatSurfacePrimitive, t::CylindricalTicksTuple{T}) where {N, T} + # This method would actually work for any flat surface, e.g. elipse + pts = extreme_points(p) + t_idx_range_r, t_idx_range_φ, t_idx_range_z = get_min_max_index_ranges((CylindricalPoint.(pts), t)) + ls = (length(t_idx_range_r), length(t_idx_range_φ), length(t_idx_range_z)) + ls = ( + ls[1] == 1 ? typemax(eltype(ls)) : ls[1], + ls[2] == 1 ? typemax(eltype(ls)) : ls[2], + ls[3] == 1 ? typemax(eltype(ls)) : ls[3] + ) + n = normal(p) + p_r = p.points[findmax(broadcast(p -> abs(p[1]), p.points))[2]] + # We skip the `:rz`-case as there could be two intersections with the arc and the polygon. + proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) + # evaluate the z value -> same as for the cartesian case + Val{:rφ}(), t_idx_range_r, t_idx_range_φ + elseif ls[2] < ls[1] && ls[3] < ls[1] && (n ⋅ p_r != 0) + Val{:φz}(), t_idx_range_φ, t_idx_range_z + else + Val{:rz}(), t_idx_range_r, t_idx_range_z + end + return t1, t2, proj +end From d27e4b37b659f81d6ca922acfd74beffade95187 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 14:44:52 +0200 Subject: [PATCH 115/241] Add default label to plot recipe of `Edge` --- src/ConstructiveSolidGeometry/plotting/LinePrimitives/Edge.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Edge.jl b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Edge.jl index 67ed2f4e9..82dde9c77 100644 --- a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Edge.jl +++ b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Edge.jl @@ -1,5 +1,6 @@ @recipe function f(e::Edge) linecolor --> :black + label --> "Edge" @series begin seriestype --> :path3d [e.a[1], e.b[1]], [e.a[2], e.b[2]], [e.a[3], e.b[3]] From 7be709be962f08efd06d36aef9ca078b7121c3c4 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 14:45:32 +0200 Subject: [PATCH 116/241] Add methods for widening tube: `Cone{T,CO,Tuple{T,T},Nothing})` --- .../VolumePrimitives/Cone.jl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index de9ceb226..bda8c2337 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -38,6 +38,12 @@ const Tube{T,CO} = Cone{T,CO,T,Nothing} _in(pt::CartesianPoint, c::Tube{<:Real, ClosedPrimitive}) = abs(pt.z) <= c.hZ && hypot(pt.x, pt.y) <= c.r _in(pt::CartesianPoint, c::Tube{<:Real, OpenPrimitive}) = abs(pt.z) < c.hZ && hypot(pt.x, pt.y) < c.r +function radius_at_z(c::Cone{T,CO,Tuple{T,T}}, z::T) where {T,CO} + rslope = (c.r[2] - c.r[1]) / 2c.hZ + return c.r[1] + rslope * (z + c.hZ) +end +_in(pt::CartesianPoint, c::Cone{T,ClosedPrimitive,Tuple{T,T},Nothing}) where {T} = abs(pt.z) <= c.hZ && hypot(pt.x, pt.y) <= radius_at_z(c, pt.z) +_in(pt::CartesianPoint, c::Cone{T,OpenPrimitive,Tuple{T,T},Nothing}) where {T} = abs(pt.z) < c.hZ && hypot(pt.x, pt.y) < radius_at_z(c, pt.z) # #Constructors for Tubes # Tube(;rMin = 0, rMax = 1, φMin = 0, φMax = 2π, zMin = -1/2, zMax = 1/2) = Cone(rMin, rMax, rMin, rMax, φMin, φMax, zMin, zMax) @@ -97,6 +103,16 @@ function surfaces(t::Tube{T}) where {T} # normals of the surfaces show inside the volume primitives. e_top, e_bot, mantle end +function surfaces(t::Cone{T,CO,Tuple{T,T},Nothing}) where {T,CO} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + mantle = ConeMantle{T,Tuple{T,T},Nothing}(t.r, t.φ, t.hZ, t.origin, t.rotation) + bot_normal = top_center_pt - bot_center_pt + e_bot = EllipticalSurface{T,T,Nothing}(r = t.r[1], φ = nothing, origin = bot_center_pt, rotation = t.rotation) + e_top = EllipticalSurface{T,T,Nothing}(r = t.r[2], φ = nothing, origin = top_center_pt, rotation = -t.rotation) + # normals of the surfaces show inside the volume primitives. + e_top, e_bot, mantle +end # function Dictionary(g::Cone{T,<:Union{T, AbstractInterval}}) where {T} # dict = OrderedDict{String,Any}() From 5c583e3941dbfc90507aeab5121f4828e7f2285b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 14:46:34 +0200 Subject: [PATCH 117/241] Generalize plot recipe for `ConeMantle` --- .../plotting/SurfacePrimitives/ConeMantle.jl | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl index d839d2dde..b1b129ddb 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl @@ -1,8 +1,6 @@ @recipe function f(cm::ConeMantle, n = 40; subn = 10) - T = typeof(cm.hZ) - ehZ = CartesianPoint(zero(T), zero(T), cm.hZ) - e_top = Ellipse(cm.r, cm.φ, cm.origin + cm.rotation * ehZ, cm.rotation) - e_bot = Ellipse(cm.r, cm.φ, cm.origin - cm.rotation * ehZ, cm.rotation) + e_top = get_top_ellipse(cm) + e_bot = get_bot_ellipse(cm) e_top_edges = edges(e_top, n = n) e_bot_edges = edges(e_bot, n = n) linecolor --> :black @@ -20,6 +18,16 @@ end end +get_top_ellipse(cm::ConeMantle{T,T,Nothing}) where {T} = + Ellipse(cm.r, cm.φ, cm.origin + cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), cm.rotation) +get_bot_ellipse(cm::ConeMantle{T,T,Nothing}) where {T} = + Ellipse(cm.r, cm.φ, cm.origin - cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), -cm.rotation) +get_top_ellipse(cm::ConeMantle{T,Tuple{T,T},Nothing}) where {T} = + Ellipse(cm.r[2], cm.φ, cm.origin + cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), cm.rotation) +get_bot_ellipse(cm::ConeMantle{T,Tuple{T,T},Nothing}) where {T} = + Ellipse(cm.r[1], cm.φ, cm.origin - cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), RotZ(π) * -cm.rotation) + # RotZ(π) * -cm.rotation such that the normal vector points inside the cone (Convention) + # function get_plot_points(c::ConeMantle{T}; n = 30) where {T <: AbstractFloat} From 543b5c0244627033654d5d85561d1e847e36c367 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 14:46:54 +0200 Subject: [PATCH 118/241] Update doc-strings --- .../SurfacePrimitives/SurfacePrimitives.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl index c608c8bc0..380b87ac7 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl @@ -30,9 +30,9 @@ function get_min_max_index_ranges(a::Union{ end """ - get_2d_grid_ticks_and_proj(pts::AbstractVector{CartesianPoint{T}}, t::CartesianTicksTuple{T}) where {N, T} + get_2d_grid_ticks_and_proj(p::AbstractFlatSurfacePrimitive, t::CartesianTicksTuple{T}) where {N, T} -This function determines the two best dimensions to sample/paint a surface to which the points `pts` belong. +This function determines the two best dimensions to sample/paint the surface p. E.g. `x` & `y` -> `proj = Val{:xy}()`. The dimensions are picked such that the number of points to evaluate is minimal. However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, @@ -65,9 +65,9 @@ end """ - get_2d_grid_ticks_and_proj(pts::AbstractVector{CartesianPoint{T}}, t::CylindricalTicksTuple{T}) where {N, T} + get_2d_grid_ticks_and_proj(p::AbstractFlatSurfacePrimitive, t::CylindricalTicksTuple{T}) where {N, T} -This function determines the two best dimensions to sample/paint a surface to which the points `pts` belong. +This function determines the two best dimensions to sample/paint the surface p. E.g. `r` & `φ` -> `proj = Val{:rφ}()`. The dimensions are picked such that the number of points to evaluate is minimal. However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, From e6d5b9dad01dd4020b5e3d2f6d267c93ec98b0d4 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 14:58:33 +0200 Subject: [PATCH 119/241] Add intersection function of `Line` & `ConeMantle{T,Tuple{T,T}}` --- .../SurfacePrimitives/ConeMantle.jl | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index a916d0ade..d470cabe1 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -27,6 +27,55 @@ T: Type of values, e.g. Float64 rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end +radius_at_z(cm::ConeMantle{T,T}, z::T) where {T} = cm.r +function radius_at_z(cm::ConeMantle{T,Tuple{T,T}}, z::T) where {T} + rslope = (cm.r[2] - cm.r[1]) / 2cm.hZ + return cm.r[1] + rslope * (z + cm.hZ) +end + +""" + intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} + +The function will always return 2 CartesianPoint's. +If the line just touches the mantle, the two points will be the same. +If the line does not touch the mantle at all, the two points will have NaN's as there coordinates. +""" +function intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} + obj_l = _transform_into_object_coordinate_system(l, cm) # direction is not normalized + + L1 = obj_l.origin.x + L2 = obj_l.origin.y + L3 = obj_l.origin.z + D1 = obj_l.direction.x + D2 = obj_l.direction.y + D3 = obj_l.direction.z + + S = (cm.r[2] - cm.r[1]) / 2cm.hZ # r slope + + f1 = D1^2 + D2^2 - D3^2*S^2 + λ = inv(f1) # f1 is only 0 if obj_l is parallel to the axis of the cone + # (here eZ -> D1 = D2 = 0) + # and the cone is actually a tupe (S = 0). + # We assume here that this is not the case -> + # We check this this in choosing the sample / evaluating diensions in `paint!` + hZ = cm.hZ + R0 = cm.r[1] + + term1 = (2D1*L1 + 2D2*L2 - 2D3*hZ*S^2 - 2D3*L3*S^2 - 2D3*R0*S)^2 + term2 = -hZ^2*S^2 - 2hZ*L3*S^2 - 2hZ*R0*S + L1^2 + L2^2 - L3^2*S^2 - 2L3*R0*S - R0^2 + term3 = -D1*L1 - D2*L2 + D3*hZ*S^2 + D3*L3*S^2 + D3*R0*S + term4 = term1 - 4*f1*term2 + sq::T = term4 < 0 ? T(NaN) : sqrt(term1 - 4*f1*term2) # if this + + λ1 = λ * (-sq/2 + term3) + λ2 = λ * (+sq/2 + term3) + + ints1 = obj_l.origin + λ1 * obj_l.direction + ints2 = obj_l.origin + λ2 * obj_l.direction + return _transform_into_global_coordinate_system(ints1, cm), + _transform_into_global_coordinate_system(ints2, cm) +end + # function ConeMantle(c::Cone{T}; rbot = 1, rtop = 1) where {T} # r = rbot == rtop ? T(rbot) : (T(rbot), T(rtop)) From 2278d4c9a0893883ace03b28cb44d1289671146f Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 15:08:15 +0200 Subject: [PATCH 120/241] Add method `intersection(cm::ConeMantle{T,T}, l::Line{T})` --- .../SurfacePrimitives/ConeMantle.jl | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index d470cabe1..36d24bccb 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -76,6 +76,46 @@ function intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} _transform_into_global_coordinate_system(ints2, cm) end +""" + intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} + +The function will always return 2 CartesianPoint's. +If the line just touches the mantle, the two points will be the same. +If the line does not touch the mantle at all, the two points will have NaN's as there coordinates. +""" +function intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} + obj_l = _transform_into_object_coordinate_system(l, cm) # direction is not normalized + + L1 = obj_l.origin.x + L2 = obj_l.origin.y + L3 = obj_l.origin.z + D1 = obj_l.direction.x + D2 = obj_l.direction.y + D3 = obj_l.direction.z + + f1 = D1^2 + D2^2 + λ = inv(f1) # f1 is only 0 if obj_l is parallel to the axis of the cone + # (here eZ -> D1 = D2 = 0) + # We assume here that this is not the case -> + # We check this this in choosing the sample / evaluating diensions in `paint!` + hZ = cm.hZ + R0 = cm.r + + term1 = (2D1*L1 + 2D2*L2)^2 + term2 = L1^2 + L2^2 - R0^2 + term3 = -D1*L1 - D2*L2 + term4 = term1 - 4*f1*term2 + sq::T = term4 < 0 ? T(NaN) : sqrt(term1 - 4*f1*term2) # if this + + λ1 = λ * (-sq/2 + term3) + λ2 = λ * (+sq/2 + term3) + + ints1 = obj_l.origin + λ1 * obj_l.direction + ints2 = obj_l.origin + λ2 * obj_l.direction + return _transform_into_global_coordinate_system(ints1, cm), + _transform_into_global_coordinate_system(ints2, cm) +end + # function ConeMantle(c::Cone{T}; rbot = 1, rtop = 1) where {T} # r = rbot == rtop ? T(rbot) : (T(rbot), T(rtop)) From f7749eea9c569b3292dddb95ee47bae0141890d4 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 15:22:03 +0200 Subject: [PATCH 121/241] Remove `extremum(b::Box{T})` as we don't need it yet --- src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 074968f88..9773ef45c 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -17,8 +17,6 @@ Box{T, CO}( b::Box{T, CO}; COT = CO, rotation::SMatrix{3,3,T,9} = b.rotation) where {T, CO<:Union{ClosedPrimitive, OpenPrimitive}} = Box{T, COT}(b.hX, b.hY, b.hZ, origin, rotation) -extremum(b::Box{T}) where {T} = norm(CartesianPoint{T}(b.hX, b.hY, b.hZ)) - _in(pt::CartesianPoint, b::Box{<:Any, ClosedPrimitive}) = abs(pt.x) <= b.hX && abs(pt.y) <= b.hY && abs(pt.z) <= b.hZ _in(pt::CartesianPoint, b::Box{<:Any, :OpenPrimitive}) = From 678f8168ed16da2576037276b2628c03e61f025b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 15:59:16 +0200 Subject: [PATCH 122/241] Move functions --- .../plotting/SurfacePrimitives/ConeMantle.jl | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl index b1b129ddb..9d5315619 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl @@ -18,14 +18,6 @@ end end -get_top_ellipse(cm::ConeMantle{T,T,Nothing}) where {T} = - Ellipse(cm.r, cm.φ, cm.origin + cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), cm.rotation) -get_bot_ellipse(cm::ConeMantle{T,T,Nothing}) where {T} = - Ellipse(cm.r, cm.φ, cm.origin - cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), -cm.rotation) -get_top_ellipse(cm::ConeMantle{T,Tuple{T,T},Nothing}) where {T} = - Ellipse(cm.r[2], cm.φ, cm.origin + cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), cm.rotation) -get_bot_ellipse(cm::ConeMantle{T,Tuple{T,T},Nothing}) where {T} = - Ellipse(cm.r[1], cm.φ, cm.origin - cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), RotZ(π) * -cm.rotation) # RotZ(π) * -cm.rotation such that the normal vector points inside the cone (Convention) From 4f5e77ae996835afddc90c224f525956d7c88581 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 15:59:35 +0200 Subject: [PATCH 123/241] Add method `extreme_points(es::Ellipse{T,T}; n = 4)` --- .../LinePrimitives/Ellipse.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl index 09eb7d385..0c1b2c2bc 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl @@ -26,6 +26,17 @@ Ellipse{T,TR,TP}( e::Ellipse{T,TR,TP}; Ellipse{T,TR,TP}(e.r, e.φ, origin, rotation) + +function extreme_points(es::Ellipse{T,T}; n = 4) where {T} + # this is probably not entirly correct. We need the extreme points of the ellipse + # in the global coordinate system. Not the ones in the object coordinate system. + φs = range(0, step = 2π / n, length = n) + pts = [CartesianPoint(CylindricalPoint{T}(es.r, φ, zero(T))) for φ in φs] + map(p -> _transform_into_global_coordinate_system(p, es), pts) +end + + + # function Arc(; r = 0, center = PlanarPoint(0,0), αMin = 0, αMax = 2π) # T = float(promote_type(typeof.((r, αMin, αMax))..., eltype(center))) # α = mod(T(αMax) - T(αMin), T(2π)) == 0 ? nothing : T(αMin)..T(αMax) From 5f701ba7dd0c4105ddcec46b402a1133e2786196 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 16:00:14 +0200 Subject: [PATCH 124/241] Add painting of `ConeMantle` on a cartesian grid --- .../SurfacePrimitives/ConeMantle.jl | 58 +++++++++++++++++++ .../Painting/ConeMantle.jl | 35 +++++++++++ src/PotentialSimulation/Painting/Painting.jl | 3 +- 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 src/PotentialSimulation/Painting/ConeMantle.jl diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index 36d24bccb..f81d73bda 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -117,6 +117,64 @@ function intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} end +get_top_ellipse(cm::ConeMantle{T,T,Nothing}) where {T} = + Ellipse(cm.r, cm.φ, cm.origin + cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), cm.rotation) +get_bot_ellipse(cm::ConeMantle{T,T,Nothing}) where {T} = + Ellipse(cm.r, cm.φ, cm.origin - cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), RotZ(π) * -cm.rotation) +get_top_ellipse(cm::ConeMantle{T,Tuple{T,T},Nothing}) where {T} = + Ellipse(cm.r[2], cm.φ, cm.origin + cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), cm.rotation) +get_bot_ellipse(cm::ConeMantle{T,Tuple{T,T},Nothing}) where {T} = + Ellipse(cm.r[1], cm.φ, cm.origin - cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), RotZ(π) * -cm.rotation) + + + +function get_2d_grid_ticks_and_proj(cm::ConeMantle{T}, t) where {T} + et = get_top_ellipse(cm) + eb = get_bot_ellipse(cm) + pts = [extreme_points(et)..., extreme_points(eb)...] + + t_idx_range_x, t_idx_range_y, t_idx_range_z = get_min_max_index_ranges((pts, t)) + ls = (length(t_idx_range_x), length(t_idx_range_y), length(t_idx_range_z)) + ls = ( + ls[1] == 1 ? typemax(eltype(ls)) : ls[1], + ls[2] == 1 ? typemax(eltype(ls)) : ls[2], + ls[3] == 1 ? typemax(eltype(ls)) : ls[3] + ) + eX = CartesianVector{T}(one(T),zero(T),zero(T)) + eY = CartesianVector{T}(zero(T),one(T),zero(T)) + eZ = CartesianVector{T}(zero(T),zero(T),one(T)) + axis = cm.rotation * CartesianVector{T}(zero(T), zero(T), one(T)) + + proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && (axis × eZ != zero(CartesianVector{T})) + Val{:xy}(), t_idx_range_x, t_idx_range_y + elseif ls[1] < ls[2] && ls[3] < ls[2] && (axis × eY != zero(CartesianVector{T})) + Val{:xz}(), t_idx_range_x, t_idx_range_z + elseif (axis × eX != zero(CartesianVector{T})) + Val{:yz}(), t_idx_range_y, t_idx_range_z + else + error("Sampling Error. Have to extend cases") + # Should never happen. This else case can be removed after testing. + end + + return t1, t2, proj +end + + +function evaluate(cm::ConeMantle{T}, x, y, ::Val{:xy}) where {T} + # plane.normal may not be perpendicular to the z-axis + line = Line{T}(CartesianPoint{T}(x, y, zero(T)), CartesianVector{T}(zero(T), zero(T), one(T))) + intersection(cm, line) +end +function evaluate(cm::ConeMantle{T}, x, z, ::Val{:xz}) where {T} + # plane.normal may not be perpendicular to the y-axis + line = Line{T}(CartesianPoint{T}(x, zero(T), z), CartesianVector{T}(zero(T), one(T), zero(T))) + intersection(cm, line) +end +function evaluate(cm::ConeMantle{T}, y, z, ::Val{:yz}) where {T} + # plane.normal may not be perpendicular to the x-axis + line = Line{T}(CartesianPoint{T}(zero(T), y, z), CartesianVector{T}(one(T), zero(T), zero(T))) + intersection(cm, line) +end # function ConeMantle(c::Cone{T}; rbot = 1, rtop = 1) where {T} # r = rbot == rtop ? T(rbot) : (T(rbot), T(rtop)) # ConeMantle( T, r, c.φ, c.z) diff --git a/src/PotentialSimulation/Painting/ConeMantle.jl b/src/PotentialSimulation/Painting/ConeMantle.jl new file mode 100644 index 000000000..06aacabec --- /dev/null +++ b/src/PotentialSimulation/Painting/ConeMantle.jl @@ -0,0 +1,35 @@ + +function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.ConeMantle, geometry, pot_value, grid::CartesianGrid) + ticks = TicksTuple(grid) + t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) + t1, t2 = if proj == Val{:xy}() + ticks[1], ticks[2] + elseif proj == Val{:xz}() + ticks[1], ticks[3] + else + ticks[2], ticks[3] + end + for i2 in t_idx_r2 + for i1 in t_idx_r1 + pt1, pt2 = ConstructiveSolidGeometry.evaluate(face, t1[i1], t2[i2], proj) + for pt in (pt1, pt2) + if pt in geometry + if proj == Val{:xy}() + i3 = searchsortednearest(ticks[3], pt[3]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value + elseif proj == Val{:xz}() + i3 = searchsortednearest(ticks[2], pt[2]) + pointtypes[i1, i3, i2] = zero(PointType) + potential[i1, i3, i2] = pot_value + else + i3 = searchsortednearest(ticks[1], pt[1]) + pointtypes[i3, i1, i2] = zero(PointType) + potential[i3, i1, i2] = pot_value + end + end + end + end + end + nothing +end \ No newline at end of file diff --git a/src/PotentialSimulation/Painting/Painting.jl b/src/PotentialSimulation/Painting/Painting.jl index 0ab42c88a..691337ba2 100644 --- a/src/PotentialSimulation/Painting/Painting.jl +++ b/src/PotentialSimulation/Painting/Painting.jl @@ -1 +1,2 @@ -include("Polygon.jl") \ No newline at end of file +include("Polygon.jl") +include("ConeMantle.jl") \ No newline at end of file From 9b2a22b0b40a68c5bc759196b548199570446af9 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 17:18:01 +0200 Subject: [PATCH 125/241] Add case for only one intersection. --- .../SurfacePrimitives/ConeMantle.jl | 52 ++++++++++++------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index f81d73bda..4a3fe3acf 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -39,6 +39,7 @@ end The function will always return 2 CartesianPoint's. If the line just touches the mantle, the two points will be the same. If the line does not touch the mantle at all, the two points will have NaN's as there coordinates. +If the line crosses the mantle only once, two points will be returned. The two points will be the same point (the intersection). """ function intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} obj_l = _transform_into_object_coordinate_system(l, cm) # direction is not normalized @@ -49,33 +50,48 @@ function intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} D1 = obj_l.direction.x D2 = obj_l.direction.y D3 = obj_l.direction.z - - S = (cm.r[2] - cm.r[1]) / 2cm.hZ # r slope - - f1 = D1^2 + D2^2 - D3^2*S^2 - λ = inv(f1) # f1 is only 0 if obj_l is parallel to the axis of the cone - # (here eZ -> D1 = D2 = 0) - # and the cone is actually a tupe (S = 0). - # We assume here that this is not the case -> - # We check this this in choosing the sample / evaluating diensions in `paint!` + hZ = cm.hZ R0 = cm.r[1] - term1 = (2D1*L1 + 2D2*L2 - 2D3*hZ*S^2 - 2D3*L3*S^2 - 2D3*R0*S)^2 - term2 = -hZ^2*S^2 - 2hZ*L3*S^2 - 2hZ*R0*S + L1^2 + L2^2 - L3^2*S^2 - 2L3*R0*S - R0^2 - term3 = -D1*L1 - D2*L2 + D3*hZ*S^2 + D3*L3*S^2 + D3*R0*S - term4 = term1 - 4*f1*term2 - sq::T = term4 < 0 ? T(NaN) : sqrt(term1 - 4*f1*term2) # if this - - λ1 = λ * (-sq/2 + term3) - λ2 = λ * (+sq/2 + term3) + S = (cm.r[2] - cm.r[1]) / 2hZ # r slope + + f1 = D1^2 + D2^2 - D3^2*S^2 + # f1 is 0 if obj_l is parallel to the axis of the cone (here eZ -> D1 = D2 = 0) + # or the cone is actually a tupe (S = 0). + # We assume here that this is not the case: + # -> We check this in choosing the sample / evaluating dimensions in `paint!` + # Thus, f1 only zero if there is only one intersection. + + λ1, λ2 = if f1 == 0 # one intersection + term1 = -hZ^2*S^2 - 2hZ*L3*S^2 - 2*hZ*R0*S + L1^2 + L2^2 - L3^2*S^2 - 2L3*R0*S - R0^2 + term2 = L1*sqrt(D3^2*S^2 - D2^2) - D2*L2 + D3*hZ*S^2 + D3*L3*S^2 + D3*R0*S + λ = term1/(2*term2) + λ, λ + else # two or no intersections + λ = inv(f1) + term1 = (2D1*L1 + 2D2*L2 - 2D3*hZ*S^2 - 2D3*L3*S^2 - 2D3*R0*S)^2 + term2 = -hZ^2*S^2 - 2hZ*L3*S^2 - 2hZ*R0*S + L1^2 + L2^2 - L3^2*S^2 - 2L3*R0*S - R0^2 + term3 = -D1*L1 - D2*L2 + D3*hZ*S^2 + D3*L3*S^2 + D3*R0*S + term4 = term1 - 4*f1*term2 + sq::T = term4 < 0 ? T(NaN) : sqrt(term4) + λ1 = λ * (-sq/2 + term3) + λ2 = λ * (+sq/2 + term3) + λ1, λ2 + end ints1 = obj_l.origin + λ1 * obj_l.direction ints2 = obj_l.origin + λ2 * obj_l.direction return _transform_into_global_coordinate_system(ints1, cm), _transform_into_global_coordinate_system(ints2, cm) end + +# x = term1/(2 term2) + +# and D1 = -sqrt(D3^2 S^2 - D2^2) +# and -L1 sqrt(D3^2 S^2 - D2^2) + D2 L2 - D3 hZ S^2 - D3 L3 S^2 - D3 R0 S!=0 + """ intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} @@ -97,7 +113,7 @@ function intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} λ = inv(f1) # f1 is only 0 if obj_l is parallel to the axis of the cone # (here eZ -> D1 = D2 = 0) # We assume here that this is not the case -> - # We check this this in choosing the sample / evaluating diensions in `paint!` + # We check this in choosing the sample / evaluating dimensions in `paint!` hZ = cm.hZ R0 = cm.r From 61984e0f1f13bc2205d2b421c49ecf91b37f6bcf Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 17:21:47 +0200 Subject: [PATCH 126/241] Rename `AbstractFlatSurfacePrimitive` & `AbstractBentSurfacePrimitive` to `AbstractPlanarSurfacePrimitive` & `AbstractCurvedSurfacePrimitive` --- .../SurfacePrimitives/ConeMantle.jl | 2 +- .../SurfacePrimitives/EllipticalSurface.jl | 2 +- .../SurfacePrimitives/Plane.jl | 2 +- .../SurfacePrimitives/Polygon.jl | 2 +- .../SurfacePrimitives/SurfacePrimitives.jl | 12 ++++++------ src/PotentialSimulation/Painting/Polygon.jl | 4 ++-- src/SolidStateDetectors.jl | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index 4a3fe3acf..6a38a9e3c 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -17,7 +17,7 @@ T: Type of values, e.g. Float64 * `axis::Line{T}`: The axis of the Cone mantle. Going from the bottom center point to the top center point. """ -@with_kw struct ConeMantle{T,RT,TP} <: AbstractBentSurfacePrimitive{T} +@with_kw struct ConeMantle{T,RT,TP} <: AbstractCurvedSurfacePrimitive{T} r::RT = 1 φ::TP = nothing hZ::T = 1 # maybe we don't need this. I will leave it for now... diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl index ebb05ce5e..edef1d0d6 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl @@ -12,7 +12,7 @@ * TP = Nothing <-> Full in φ * ... """ -@with_kw struct EllipticalSurface{T,TR,TP} <: AbstractFlatSurfacePrimitive{T} +@with_kw struct EllipticalSurface{T,TR,TP} <: AbstractPlanarSurfacePrimitive{T} r::TR = 1 φ::TP = nothing diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl index fedca9061..3a34d49f0 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl @@ -1,4 +1,4 @@ -struct Plane{T} <: AbstractFlatSurfacePrimitive{T} +struct Plane{T} <: AbstractPlanarSurfacePrimitive{T} origin::CartesianPoint{T} normal::CartesianVector{T} Plane{T}(o, n) where {T} = new{T}(o, normalize(n)) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl index b1959d191..f51073be9 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl @@ -1,5 +1,5 @@ -struct Polygon{N,T} <: AbstractFlatSurfacePrimitive{T} +struct Polygon{N,T} <: AbstractPlanarSurfacePrimitive{T} points::SVector{N, CartesianPoint{T}} end const Triangle{T} = Polygon{3, T} diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl index 380b87ac7..e74854fdc 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl @@ -1,5 +1,5 @@ -abstract type AbstractFlatSurfacePrimitive{T} <: AbstractSurfacePrimitive{T} end -abstract type AbstractBentSurfacePrimitive{T} <: AbstractSurfacePrimitive{T} end +abstract type AbstractPlanarSurfacePrimitive{T} <: AbstractSurfacePrimitive{T} end +abstract type AbstractCurvedSurfacePrimitive{T} <: AbstractSurfacePrimitive{T} end include("Plane.jl") include("Polygon.jl") @@ -30,7 +30,7 @@ function get_min_max_index_ranges(a::Union{ end """ - get_2d_grid_ticks_and_proj(p::AbstractFlatSurfacePrimitive, t::CartesianTicksTuple{T}) where {N, T} + get_2d_grid_ticks_and_proj(p::AbstractPlanarSurfacePrimitive, t::CartesianTicksTuple{T}) where {N, T} This function determines the two best dimensions to sample/paint the surface p. E.g. `x` & `y` -> `proj = Val{:xy}()`. @@ -39,7 +39,7 @@ However, the polygon is not allowed to be parallel to the remaining dimension, e because, than, there would not be a single value, but infinite ones, for `z` in the evalution. """ -function get_2d_grid_ticks_and_proj(p::AbstractFlatSurfacePrimitive, t::CartesianTicksTuple{T}) where {N, T} +function get_2d_grid_ticks_and_proj(p::AbstractPlanarSurfacePrimitive, t::CartesianTicksTuple{T}) where {N, T} # This method would actually work for any flat surface, e.g. elipse pts = extreme_points(p) t_idx_range_x, t_idx_range_y, t_idx_range_z = get_min_max_index_ranges((pts, t)) @@ -65,7 +65,7 @@ end """ - get_2d_grid_ticks_and_proj(p::AbstractFlatSurfacePrimitive, t::CylindricalTicksTuple{T}) where {N, T} + get_2d_grid_ticks_and_proj(p::AbstractPlanarSurfacePrimitive, t::CylindricalTicksTuple{T}) where {N, T} This function determines the two best dimensions to sample/paint the surface p. E.g. `r` & `φ` -> `proj = Val{:rφ}()`. @@ -73,7 +73,7 @@ The dimensions are picked such that the number of points to evaluate is minimal. However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, because, than, there would not be a single value, but infinite ones, for `z` in the evalution. """ -function get_2d_grid_ticks_and_proj(p::AbstractFlatSurfacePrimitive, t::CylindricalTicksTuple{T}) where {N, T} +function get_2d_grid_ticks_and_proj(p::AbstractPlanarSurfacePrimitive, t::CylindricalTicksTuple{T}) where {N, T} # This method would actually work for any flat surface, e.g. elipse pts = extreme_points(p) t_idx_range_r, t_idx_range_φ, t_idx_range_z = get_min_max_index_ranges((CylindricalPoint.(pts), t)) diff --git a/src/PotentialSimulation/Painting/Polygon.jl b/src/PotentialSimulation/Painting/Polygon.jl index 9d47a945e..e6d6b0a26 100644 --- a/src/PotentialSimulation/Painting/Polygon.jl +++ b/src/PotentialSimulation/Painting/Polygon.jl @@ -1,5 +1,5 @@ -function paint!(pointtypes, potential, face::AbstractFlatSurfacePrimitive, geometry, pot_value, grid::CartesianGrid) +function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive, geometry, pot_value, grid::CartesianGrid) ticks = TicksTuple(grid) t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) t1, t2 = if proj == Val{:xy}() @@ -32,7 +32,7 @@ function paint!(pointtypes, potential, face::AbstractFlatSurfacePrimitive, geome end nothing end -function paint!(pointtypes, potential, face::AbstractFlatSurfacePrimitive, geometry, pot_value, grid::CylindricalGrid) where {T} +function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive, geometry, pot_value, grid::CylindricalGrid) where {T} ticks = TicksTuple(grid) t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) t1, t2 = if proj == Val{:rφ}() diff --git a/src/SolidStateDetectors.jl b/src/SolidStateDetectors.jl index 95fc08557..3373117c0 100644 --- a/src/SolidStateDetectors.jl +++ b/src/SolidStateDetectors.jl @@ -34,7 +34,7 @@ using .ConstructiveSolidGeometry: Cartesian, Cylindrical, AbstractCoordinateSystem, CoordinateSystemType, CartesianTicksTuple, CylindricalTicksTuple, Geometry, AbstractGeometry, - AbstractSurfacePrimitive, AbstractFlatSurfacePrimitive, AbstractBentSurfacePrimitive, + AbstractSurfacePrimitive, AbstractPlanarSurfacePrimitive, AbstractCurvedSurfacePrimitive, geom_round, geom_sigdigits, geom_atol_zero, parse_rotation_matrix, parse_translate_vector, parse_CSG_transformation, transform, CSG_dict, Transformations, combine_transformations From 805afbf6172aed5e0d558d05c8103a7141193410 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 17 Jun 2021 17:25:24 +0200 Subject: [PATCH 127/241] Clean-up --- .../SurfacePrimitives/ConeMantle.jl | 29 ++++--------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index 6a38a9e3c..dd14c47db 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -27,11 +27,6 @@ T: Type of values, e.g. Float64 rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -radius_at_z(cm::ConeMantle{T,T}, z::T) where {T} = cm.r -function radius_at_z(cm::ConeMantle{T,Tuple{T,T}}, z::T) where {T} - rslope = (cm.r[2] - cm.r[1]) / 2cm.hZ - return cm.r[1] + rslope * (z + cm.hZ) -end """ intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} @@ -57,11 +52,7 @@ function intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} S = (cm.r[2] - cm.r[1]) / 2hZ # r slope f1 = D1^2 + D2^2 - D3^2*S^2 - # f1 is 0 if obj_l is parallel to the axis of the cone (here eZ -> D1 = D2 = 0) - # or the cone is actually a tupe (S = 0). - # We assume here that this is not the case: - # -> We check this in choosing the sample / evaluating dimensions in `paint!` - # Thus, f1 only zero if there is only one intersection. + # f1 is zero if there is only one intersection. λ1, λ2 = if f1 == 0 # one intersection term1 = -hZ^2*S^2 - 2hZ*L3*S^2 - 2*hZ*R0*S + L1^2 + L2^2 - L3^2*S^2 - 2L3*R0*S - R0^2 @@ -86,12 +77,6 @@ function intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} _transform_into_global_coordinate_system(ints2, cm) end - -# x = term1/(2 term2) - -# and D1 = -sqrt(D3^2 S^2 - D2^2) -# and -L1 sqrt(D3^2 S^2 - D2^2) + D2 L2 - D3 hZ S^2 - D3 L3 S^2 - D3 R0 S!=0 - """ intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} @@ -136,11 +121,11 @@ end get_top_ellipse(cm::ConeMantle{T,T,Nothing}) where {T} = Ellipse(cm.r, cm.φ, cm.origin + cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), cm.rotation) get_bot_ellipse(cm::ConeMantle{T,T,Nothing}) where {T} = - Ellipse(cm.r, cm.φ, cm.origin - cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), RotZ(π) * -cm.rotation) + Ellipse(cm.r, cm.φ, cm.origin - cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), RotZ{T}(π) * -cm.rotation) get_top_ellipse(cm::ConeMantle{T,Tuple{T,T},Nothing}) where {T} = Ellipse(cm.r[2], cm.φ, cm.origin + cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), cm.rotation) get_bot_ellipse(cm::ConeMantle{T,Tuple{T,T},Nothing}) where {T} = - Ellipse(cm.r[1], cm.φ, cm.origin - cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), RotZ(π) * -cm.rotation) + Ellipse(cm.r[1], cm.φ, cm.origin - cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), RotZ{T}(π) * -cm.rotation) @@ -161,9 +146,9 @@ function get_2d_grid_ticks_and_proj(cm::ConeMantle{T}, t) where {T} eZ = CartesianVector{T}(zero(T),zero(T),one(T)) axis = cm.rotation * CartesianVector{T}(zero(T), zero(T), one(T)) - proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && (axis × eZ != zero(CartesianVector{T})) + proj, t1, t2 = if (axis × eZ != zero(CartesianVector{T})) Val{:xy}(), t_idx_range_x, t_idx_range_y - elseif ls[1] < ls[2] && ls[3] < ls[2] && (axis × eY != zero(CartesianVector{T})) + elseif (axis × eY != zero(CartesianVector{T})) Val{:xz}(), t_idx_range_x, t_idx_range_z elseif (axis × eX != zero(CartesianVector{T})) Val{:yz}(), t_idx_range_y, t_idx_range_z @@ -177,20 +162,18 @@ end function evaluate(cm::ConeMantle{T}, x, y, ::Val{:xy}) where {T} - # plane.normal may not be perpendicular to the z-axis line = Line{T}(CartesianPoint{T}(x, y, zero(T)), CartesianVector{T}(zero(T), zero(T), one(T))) intersection(cm, line) end function evaluate(cm::ConeMantle{T}, x, z, ::Val{:xz}) where {T} - # plane.normal may not be perpendicular to the y-axis line = Line{T}(CartesianPoint{T}(x, zero(T), z), CartesianVector{T}(zero(T), one(T), zero(T))) intersection(cm, line) end function evaluate(cm::ConeMantle{T}, y, z, ::Val{:yz}) where {T} - # plane.normal may not be perpendicular to the x-axis line = Line{T}(CartesianPoint{T}(zero(T), y, z), CartesianVector{T}(one(T), zero(T), zero(T))) intersection(cm, line) end + # function ConeMantle(c::Cone{T}; rbot = 1, rtop = 1) where {T} # r = rbot == rtop ? T(rbot) : (T(rbot), T(rtop)) # ConeMantle( T, r, c.φ, c.z) From b3bbc24d83aab63e9378121b953a7c27fddb5a6f Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 07:59:59 +0200 Subject: [PATCH 128/241] Extend docstring. --- src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index dd14c47db..0dc06b7f5 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -35,6 +35,7 @@ The function will always return 2 CartesianPoint's. If the line just touches the mantle, the two points will be the same. If the line does not touch the mantle at all, the two points will have NaN's as there coordinates. If the line crosses the mantle only once, two points will be returned. The two points will be the same point (the intersection). +If the line lies inside the mantle and is parallel to it. The same point will be returned which is the origin of the line. """ function intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} obj_l = _transform_into_object_coordinate_system(l, cm) # direction is not normalized @@ -57,7 +58,7 @@ function intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} λ1, λ2 = if f1 == 0 # one intersection term1 = -hZ^2*S^2 - 2hZ*L3*S^2 - 2*hZ*R0*S + L1^2 + L2^2 - L3^2*S^2 - 2L3*R0*S - R0^2 term2 = L1*sqrt(D3^2*S^2 - D2^2) - D2*L2 + D3*hZ*S^2 + D3*L3*S^2 + D3*R0*S - λ = term1/(2*term2) + λ = term1 / (2term2) λ, λ else # two or no intersections λ = inv(f1) From 347fcfe435ba9e5d5a5c7a5e68f1aca78aca3f8f Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 08:05:12 +0200 Subject: [PATCH 129/241] Add type annotations --- src/ConstructiveSolidGeometry/CSG.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ConstructiveSolidGeometry/CSG.jl b/src/ConstructiveSolidGeometry/CSG.jl index 9d212504f..67ce05046 100644 --- a/src/ConstructiveSolidGeometry/CSG.jl +++ b/src/ConstructiveSolidGeometry/CSG.jl @@ -12,7 +12,7 @@ in(p::AbstractCoordinatePoint, csg::CSGUnion) = in(p, csg.a) || in(p, csg.b) (+)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} = CSGUnion{T,A,B}(a, b) # read-in -function Geometry(::Type{T}, t::Type{CSGUnion}, v::Vector{<:AbstractDict}, input_units::NamedTuple, transformations) where {T} +function Geometry(::Type{T}, t::Type{CSGUnion}, v::Vector{<:AbstractDict}, input_units::NamedTuple, transformations::Transformations{T}) where {T} sum( broadcast(x-> Geometry(T, x, input_units, transformations), v) ) end @@ -34,7 +34,7 @@ in(p::AbstractCoordinatePoint, csg::CSGIntersection) = in(p, csg.a) && in(p, csg (&)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} = CSGIntersection{T,A,B}(a, b) # read-in -function Geometry(::Type{T}, ::Type{CSGIntersection}, v::Vector{<:AbstractDict}, input_units::NamedTuple, transformation) where {T} +function Geometry(::Type{T}, ::Type{CSGIntersection}, v::Vector{<:AbstractDict}, input_units::NamedTuple, transformation::Transformations{T}) where {T} parts = broadcast(x-> Geometry(T, x, input_units, transformation), v) reduce(&, parts) end @@ -57,7 +57,7 @@ in(p::AbstractCoordinatePoint, csg::CSGDifference) = in(p, csg.a) && !in(p, csg. (-)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} = CSGDifference{T,A,B}(a, b) # read-in -function Geometry(::Type{T}, ::Type{CSGDifference}, v::Vector{<:AbstractDict}, input_units::NamedTuple, transformations) where {T} +function Geometry(::Type{T}, ::Type{CSGDifference}, v::Vector{<:AbstractDict}, input_units::NamedTuple, transformations::Transformations{T}) where {T} Geometry(T, v[1], input_units, transformations) - sum(broadcast(x-> Geometry(T, x, input_units, transformations), v[2:end])) end From 42e2807fe3df8cd4bbbf68c7b7546ea486daac8a Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 08:07:22 +0200 Subject: [PATCH 130/241] Fix in read-in --- src/ConstructiveSolidGeometry/CSG.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/CSG.jl b/src/ConstructiveSolidGeometry/CSG.jl index 67ce05046..4bd2b1d35 100644 --- a/src/ConstructiveSolidGeometry/CSG.jl +++ b/src/ConstructiveSolidGeometry/CSG.jl @@ -63,7 +63,8 @@ end Dictionary(g::CSGDifference{T}) where {T} = OrderedDict{String,Any}("difference" => OrderedDict[Dictionary(g.a), Dictionary(g.b)]) -Geometry(::Type{T}, CSG::Type{<:AbstractConstructiveGeometry}, v::Vector{Any}, input_units::NamedTuple) where {T} = Geometry(T, CSG, [g for g in v], input_units) +Geometry(::Type{T}, CSG::Type{<:AbstractConstructiveGeometry}, v::Vector{Any}, input_units::NamedTuple, transformations::Transformations{T}) where {T} = + Geometry(T, CSG, [g for g in v], input_units, transformations) (+)(csg::A, v::CartesianVector) where {A <: AbstractConstructiveGeometry} = A(csg.a + v, csg.b + v) From 6319151ba7446a2fb118c14571cdd28253f92413 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 09:22:21 +0200 Subject: [PATCH 131/241] Bugfix if there are no `Passive`'s --- .../PotentialSimulationSetupRBCartesian3D.jl | 18 ++++++++++-------- .../PotentialSimulationSetupRBCylindrical.jl | 18 ++++++++++-------- src/SolidStateDetector/DetectorGeometries.jl | 6 +++--- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCartesian3D.jl b/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCartesian3D.jl index 5a31f2b7a..9705f272a 100644 --- a/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCartesian3D.jl +++ b/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCartesian3D.jl @@ -19,15 +19,17 @@ function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, p x::T = axx[ix] pt::CartesianPoint{T} = CartesianPoint{T}( x, y, z ) - for passive in ssd.passives - if passive.potential != :floating - if pt in passive - potential[ ix, iy, iz ] = if ismissing(weighting_potential_contact_id) - passive.potential - else - 0 + if !ismissing(ssd.passives) + for passive in ssd.passives + if passive.potential != :floating + if pt in passive + potential[ ix, iy, iz ] = if ismissing(weighting_potential_contact_id) + passive.potential + else + 0 + end + pointtypes[ ix, iy, iz ] = zero(PointType) end - pointtypes[ ix, iy, iz ] = zero(PointType) end end end diff --git a/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCylindrical.jl b/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCylindrical.jl index 66fb018d0..0fe630648 100644 --- a/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCylindrical.jl +++ b/src/PotentialSimulation/PotentialSimulationSetups/PotentialSimulationSetupRBCylindrical.jl @@ -19,15 +19,17 @@ function set_pointtypes_and_fixed_potentials!(pointtypes::Array{PointType, N}, p r::T = axr[ir] pt::CylindricalPoint{T} = CylindricalPoint{T}( r, φ, z ) - for passive in ssd.passives - if passive.potential != :floating - if pt in passive - potential[ ir, iφ, iz ] = if ismissing(weighting_potential_contact_id) - passive.potential - else - 0 + if !ismissing(ssd.passives) + for passive in ssd.passives + if passive.potential != :floating + if pt in passive + potential[ ir, iφ, iz ] = if ismissing(weighting_potential_contact_id) + passive.potential + else + 0 + end + pointtypes[ ir, iφ, iz ] = zero(PointType) end - pointtypes[ ir, iφ, iz ] = zero(PointType) end end end diff --git a/src/SolidStateDetector/DetectorGeometries.jl b/src/SolidStateDetector/DetectorGeometries.jl index 04c69e31f..af43ff7a8 100644 --- a/src/SolidStateDetector/DetectorGeometries.jl +++ b/src/SolidStateDetector/DetectorGeometries.jl @@ -108,14 +108,14 @@ end function sample(c::SolidStateDetector{T}, ::Type{Cartesian}, sampling...)::Vector{CartesianPoint{T}} where {T <: SSDFloat} imp::Vector{CartesianPoint{T}} = vcat( CartesianPoint.(sample(c.semiconductor.geometry, sampling...)), - [CartesianPoint.(sample(g.geometry, sampling...)) for object in (c.contacts, c.passives) for g in object]...) + [CartesianPoint.(sample(g.geometry, sampling...)) for object in skipmissing((c.contacts, c.passives)) for g in object]...) unique!(imp) end function sample(c::SolidStateDetector{T}, ::Type{Cylindrical}, sampling...)::Vector{CylindricalPoint{T}} where {T <: SSDFloat} imp::Vector{CylindricalPoint{T}} = vcat( CylindricalPoint.(sample(c.semiconductor.geometry, sampling...)), - [CylindricalPoint.(sample(g.geometry, sampling...)) for object in (c.contacts, c.passives) for g in object]...) + [CylindricalPoint.(sample(g.geometry, sampling...)) for object in skipmissing((c.contacts, c.passives)) for g in object]...) unique!(imp) end @@ -275,7 +275,7 @@ function get_ρ_and_ϵ(pt::AbstractCoordinatePoint{T}, ssd::SolidStateDetector{T if pt in ssd.semiconductor ρ_semiconductor = get_charge_density(ssd.semiconductor, pt) ϵ = ssd.semiconductor.material.ϵ_r - elseif in(pt, ssd.passives) + elseif !ismissing(ssd.passives) && in(pt, ssd.passives) for ep in ssd.passives if pt in ep q_eff_fix = get_charge_density(ep, pt) From 8caabd5dc9894a28a2352cf5fba81d910bbbc23a Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 09:22:39 +0200 Subject: [PATCH 132/241] Fix simple plot recipes for CSG's --- .../plotting/CSG/CSG.jl | 31 ++++++++++++++++--- .../VolumePrimitives/VolumePrimitives.jl | 25 --------------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl b/src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl index 38f3432d0..b977121e0 100644 --- a/src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl +++ b/src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl @@ -1,15 +1,38 @@ @recipe function f(csg::ConstructiveSolidGeometry.CSGUnion) linecolor --> :black csguniontype --> :union - csg.a, csg.b + @series begin + linestyle := :solid + csg.a + end + @series begin + linestyle := :solid + csg.b + end end @recipe function f(csg::ConstructiveSolidGeometry.CSGDifference) linecolor --> :black - csguniontype --> :difference - csg.a, csg.b + @series begin + linestyle := :solid + csguniontype --> :difference + csg.a + end + @series begin + linestyle := :dash + csg.b + end end @recipe function f(csg::ConstructiveSolidGeometry.CSGIntersection) linecolor --> :black csguniontype --> :intersection - csg.a, csg.b + @series begin + linestyle := :dot + csguniontype --> :difference + csg.a + end + @series begin + linestyle := :dot + linestyle := :dash + csg.b + end end \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl index 10046b19c..a4e2246bf 100644 --- a/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/VolumePrimitives/VolumePrimitives.jl @@ -9,28 +9,3 @@ end end -@recipe function f(p1::AbstractVolumePrimitive, p2::AbstractVolumePrimitive) - fs1 = surfaces(p1) - fs2 = surfaces(p2) - # In principle it would be better to directly get the edges of the primitive - # Can be improved later... - linecolor --> :black - @series begin - if plotattributes[:csguniontype] == :intersection - linestyle := :dot - else - linestyle := :solid - end - fs1 - end - @series begin - if plotattributes[:csguniontype] == :intersection - linestyle := :dot - elseif plotattributes[:csguniontype] == :difference - linestyle := :dash - else - linestyle := :solid - end - fs2 - end -end \ No newline at end of file From 2b410597f792e488dcce34a50befbedeb3fe6796 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 09:24:42 +0200 Subject: [PATCH 133/241] Add generalized method for `extreme_points(es::AbstractPrimitive{T})` --- .../ConstructiveSolidGeometry.jl | 16 ++++++++++++++++ .../LinePrimitives/Ellipse.jl | 9 ++------- .../SurfacePrimitives/EllipticalSurface.jl | 10 +++------- .../SurfacePrimitives/SurfacePrimitives.jl | 10 +++++----- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index e0f1a7ab7..c3251402c 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -59,6 +59,22 @@ module ConstructiveSolidGeometry # Do we want to store the rotation matrix permanently in the primitive? # We should do tests regarding the performance. It can be easily added later. + """ + extreme_points(es::AbstractPrimitive{T}) where {T} + + General implementation for all primitives. + """ + function extreme_points(es::AbstractPrimitive{T}) where {T} + o = origin(es) + r = extremum(es) + vX = r * CartesianVector{T}(one(T), zero(T), zero(T)) + vY = r * CartesianVector{T}(zero(T), one(T), zero(T)) + vZ = r * CartesianVector{T}(zero(T), zero(T), one(T)) + SVector{6,CartesianPoint{T}}( + o - vX, o + vX, o - vY, o + vY, o - vZ, o + vZ, + ) + end + include("Transformations.jl") include("GeometryRounding.jl") include("VolumePrimitives/VolumePrimitives.jl") diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl index 0c1b2c2bc..1c77524c3 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl @@ -26,14 +26,9 @@ Ellipse{T,TR,TP}( e::Ellipse{T,TR,TP}; Ellipse{T,TR,TP}(e.r, e.φ, origin, rotation) +extremum(e::Ellipse{T,T}) where {T} = e.r + -function extreme_points(es::Ellipse{T,T}; n = 4) where {T} - # this is probably not entirly correct. We need the extreme points of the ellipse - # in the global coordinate system. Not the ones in the object coordinate system. - φs = range(0, step = 2π / n, length = n) - pts = [CartesianPoint(CylindricalPoint{T}(es.r, φ, zero(T))) for φ in φs] - map(p -> _transform_into_global_coordinate_system(p, es), pts) -end diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl index edef1d0d6..947c39ef9 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl @@ -26,13 +26,9 @@ Plane(es::EllipticalSurface{T}) where {T} = Plane{T}(es.origin, es.rotation * Ca normal(es::EllipticalSurface{T}) where {T} = es.rotation * CartesianVector{T}(zero(T), zero(T), one(T)) -function extreme_points(es::EllipticalSurface{T,TR,Nothing}; n = 4) where {T,TR<:Real} - # this is probably not entirly correct. We need the extreme points of the ellipse - # in the global coordinate system. Not the ones in the object coordinate system. - φs = range(0, step = 2π / n, length = n) - pts = [CartesianPoint(CylindricalPoint{T}(es.r, φ, zero(T))) for φ in φs] - map(p -> _transform_into_global_coordinate_system(p, es), pts) -end +extremum(es::EllipticalSurface{T,T}) where {T} = es.r +extremum(es::EllipticalSurface{T,Tuple{T,T}}) where {T} = max(es.r[1], es.r[2]) + # #Constructors # CylindricalAnnulus(c::Cone{T}; z = 0) where {T} = CylindricalAnnulus(T, get_r_at_z(c,z), c.φ, T(z)) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl index e74854fdc..b7fd788e3 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl @@ -50,9 +50,9 @@ function get_2d_grid_ticks_and_proj(p::AbstractPlanarSurfacePrimitive, t::Cartes ls[3] == 1 ? typemax(eltype(ls)) : ls[3] ) n = normal(p) - proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) + proj, t1, t2 = if (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) Val{:xy}(), t_idx_range_x, t_idx_range_y - elseif ls[1] < ls[2] && ls[3] < ls[2] && (n ⋅ CartesianVector{T}(zero(T),one(T),zero(T)) != 0) + elseif (n ⋅ CartesianVector{T}(zero(T),one(T),zero(T)) != 0) Val{:xz}(), t_idx_range_x, t_idx_range_z elseif n ⋅ CartesianVector{T}(one(T),zero(T), zero(T)) != 0 Val{:yz}(), t_idx_range_y, t_idx_range_z @@ -84,12 +84,12 @@ function get_2d_grid_ticks_and_proj(p::AbstractPlanarSurfacePrimitive, t::Cylind ls[3] == 1 ? typemax(eltype(ls)) : ls[3] ) n = normal(p) - p_r = p.points[findmax(broadcast(p -> abs(p[1]), p.points))[2]] + p_r = pts[findmax(broadcast(p -> abs(p[1]), pts))[2]] # We skip the `:rz`-case as there could be two intersections with the arc and the polygon. - proj, t1, t2 = if ls[1] < ls[3] && ls[2] < ls[3] && (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) + proj, t1, t2 = if (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) # evaluate the z value -> same as for the cartesian case Val{:rφ}(), t_idx_range_r, t_idx_range_φ - elseif ls[2] < ls[1] && ls[3] < ls[1] && (n ⋅ p_r != 0) + elseif (n ⋅ p_r != 0) Val{:φz}(), t_idx_range_φ, t_idx_range_z else Val{:rz}(), t_idx_range_r, t_idx_range_z From 2dc94579abddc2eb61bb610c40151904b97ea8a4 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 09:25:05 +0200 Subject: [PATCH 134/241] Extend plotting recipe for `EllipticalSurface` --- .../SurfacePrimitives/EllipticalSurface.jl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl index 632b34457..57646bb88 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl @@ -1,9 +1,21 @@ @recipe function f(es::EllipticalSurface) + ess = ellpises(es) + linecolor --> black @series begin - Ellipse(es) + label --> "Elliptical Surface" + ess[1] + end + if length(ess) == 2 + label := nothing + ess[2] end end +ellpises(es::EllipticalSurface{T,T}) where {T} = (Ellipse(es),) +function ellpises(es::EllipticalSurface{T,Tuple{T,T}}) where {T} + Ellipse(r = es.r[1], φ = es.φ, origin = es.origin, rotation = es.rotation), + Ellipse(r = es.r[2], φ = es.φ, origin = es.origin, rotation = es.rotation) +end # function get_plot_points(a::CylindricalAnnulus{T}; n = 30) where {T <: AbstractFloat} From 8463dd6f0c0cbdff4a60fffa62afb581fce7d6b8 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 09:26:18 +0200 Subject: [PATCH 135/241] Change parsing of intervals -> use `Tuple` instead of `Intervals` To keep the types as short as possible. --- src/ConstructiveSolidGeometry/IO.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index e99b54ace..8522c20d1 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -64,8 +64,8 @@ end function _parse_radial_interval(::Type{T}, dict::AbstractDict, unit::Unitful.Units) where {T} @assert haskey(dict, "from") && haskey(dict, "to") "Please specify 'from' and 'to' in $(dict)." From::T, To::T = _parse_interval_from_to(T, dict, unit) - @assert From >= 0 && To >= 0 "Entries 'from' and 'to' of radial $(dict) should be non-zero." - From == 0 ? To : From..To + @assert From >= 0 && To >= 0 "Entries 'from' and 'to' of radial $(dict) should `>= 0`." + (From, To) end # parses dictionary entries of type Real, String or {"from": ..., "to": ... } to respective AbstractFloat/Interval @@ -95,14 +95,14 @@ end function parse_r_of_primitive(::Type{T}, dict::AbstractDict, unit::Unitful.Units) where {T} @assert haskey(dict, "r") "Please specify 'r'." dictr = dict["r"] - # "r" : {"bottom": {"from": ..., "to": ...}, "top": {"from": ..., "to": ...}} if haskey(dictr, "bottom") && haskey(dictr, "top") + # "r" : {"bottom": {"from": ..., "to": ...}, "top": {"from": ..., "to": ...}} bottom = _parse_radial_interval(T, dictr["bottom"], unit) top = _parse_radial_interval(T, dictr["top"], unit) # bottom and top need to be same type for Cone typeof(bottom) == typeof(top) ? (bottom, top) : _extend_number_to_zero_interval.((bottom, top)) - # "r" : {"from": ..., "to": ...} else + # "r" : {"from": ..., "to": ...} _parse_radial_interval(T, dictr, unit) end end From 3641c795a8d461f88dbeff7ce45c3a0d406425ec Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 09:34:06 +0200 Subject: [PATCH 136/241] Change `Tube` to `Cylinder` --- .../SurfacePrimitives/ConeMantle.jl | 6 +- .../VolumePrimitives/Cone.jl | 116 +++++++++++++----- 2 files changed, 88 insertions(+), 34 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index 0dc06b7f5..d019099ea 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -4,9 +4,9 @@ T: Type of values, e.g. Float64 * `r::TR`: - * TR = Real -> Tube Mantle (a = b = r) - * TR = (Real, Real) -> Cone Mantle (r_bot = r[1], r_top = r[2]) - * TR = ((Real,), (Real,)) -> Elliptical Tube Mantle (a = r[1][1], b = r[2][1]) + * TR = Real -> Cylinder Mantle (a = b = r) + * TR = (Real, Real) -> Cone Mantle (r_bot = r[1], r_top = r[2]) + * TR = ((Real,), (Real,)) -> Elliptical Cylinder Mantle (a = r[1][1], b = r[2][1]) * TR = ((Real, Real),(Real, Real)) -> Elliptical Cone Mantle \n(a_in = r[1][1], a_out = r[1][2], b_in = r[2][1], b_out = r[2][2]) * Not all are implemented yet diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index bda8c2337..61a606dc5 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -5,10 +5,10 @@ T: Type of values, e.g. Float64 CO: ClosedPrimitive or OpenPrimitive <-> whether surface belongs to it or not * `r::TR`: - * TR = Real -> Solid Tube - * TR = (Real, Real) -> Pipe (r_in = r[1], r_out = r[2]) - * TR = ((Real,), (Real,)) Solid widening Tube -> (r_bot = r[1][1], r_top = r[1][2]) - * TR = ((Real,Real), (Real,Real)) Solid widening Pipe ->\n(r_bot_in = r[1][1], r_bot_out = r[1][2], r_top_in = r[2][1], r_top_out = r[2][2]) + * TR = Real -> Cylinder + * TR = (Real, Real) -> Tube (r_in = r[1], r_out = r[2]) + * TR = ((Real,), (Real,)) Solid widening Cylinder -> (r_bot = r[1][1], r_top = r[1][2]) + * TR = ((Real,Real), (Real,Real)) Solid widening Tube ->\n(r_bot_in = r[1][1], r_bot_out = r[1][2], r_top_in = r[2][1], r_top_out = r[2][2]) * TR = (Nothing, (Real,Real)) Cone ->\n(r_bot_in = r_bot_out = 0, r_top_in = r[2][1], r_top_out = r[2][2]) * TR = ((Real,Real), Nothing) Cone ->\n(r_bot_in = r[1][1], r_bot_out = r[1][2], r_top_in = r_top_out = 0) * ... (+ elliptical cases -> (a, b)) @@ -33,17 +33,28 @@ Cone{T,CO,RT,TP}( c::Cone{T,CO,RT,TP}; COT = CO, rotation::SMatrix{3,3,T,9} = b.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},RT,TP} = Cone{T,CO,RT,TP}(c.r, c.φ, c.hZ, origin, rotation) -const Tube{T,CO} = Cone{T,CO,T,Nothing} +const Cylinder{T,CO} = Cone{T,CO,T,Nothing} +# const Tube{T,CO} = Cone{T,CO,Tuple{T,T},Nothing} -_in(pt::CartesianPoint, c::Tube{<:Real, ClosedPrimitive}) = abs(pt.z) <= c.hZ && hypot(pt.x, pt.y) <= c.r -_in(pt::CartesianPoint, c::Tube{<:Real, OpenPrimitive}) = abs(pt.z) < c.hZ && hypot(pt.x, pt.y) < c.r - -function radius_at_z(c::Cone{T,CO,Tuple{T,T}}, z::T) where {T,CO} - rslope = (c.r[2] - c.r[1]) / 2c.hZ - return c.r[1] + rslope * (z + c.hZ) +function _in(pt::CartesianPoint, c::Cylinder{<:Real, ClosedPrimitive}) + z = abs(pt.z) + r = hypot(pt.x, pt.y) + # return z < c.hZ || z ≈ c.hZ && r < c.r || r ≈ c.r # This solves numerical issues but costs performance... + return z <= c.hZ && r <= c.r +end +_in(pt::CartesianPoint, c::Cylinder{<:Real, OpenPrimitive}) = abs(pt.z) < c.hZ && hypot(pt.x, pt.y) < c.r + + +function _in(pt::CartesianPoint, c::Cone{T,ClosedPrimitive,Tuple{Tuple{T,T},Tuple{T,T}},Nothing}) where {T} + z = abs(pt.z) + if abs(pt.z) <= c.hZ + r = hypot(pt.x, pt.y) + r_in, r_out = radii_at_z(c, z) + r_in <= r <= r_out + else + false + end end -_in(pt::CartesianPoint, c::Cone{T,ClosedPrimitive,Tuple{T,T},Nothing}) where {T} = abs(pt.z) <= c.hZ && hypot(pt.x, pt.y) <= radius_at_z(c, pt.z) -_in(pt::CartesianPoint, c::Cone{T,OpenPrimitive,Tuple{T,T},Nothing}) where {T} = abs(pt.z) < c.hZ && hypot(pt.x, pt.y) < radius_at_z(c, pt.z) # #Constructors for Tubes # Tube(;rMin = 0, rMax = 1, φMin = 0, φMax = 2π, zMin = -1/2, zMax = 1/2) = Cone(rMin, rMax, rMin, rMax, φMin, φMax, zMin, zMax) @@ -87,32 +98,41 @@ function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::Nam length_unit = input_units.length angle_unit = input_units.angle r = parse_r_of_primitive(T, dict, length_unit) + @info r φ = parse_φ_of_primitive(T, dict, angle_unit) hZ = parse_height_of_primitive(T, dict, length_unit) cone = Cone{T, ClosedPrimitive, typeof(r), typeof(φ)}(r = r, φ = φ, hZ = hZ) return transform(cone, transformations) end -function surfaces(t::Tube{T}) where {T} +function surfaces(t::Cylinder{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) mantle = ConeMantle{T,T,Nothing}(t.r, t.φ, t.hZ, t.origin, t.rotation) - bot_normal = top_center_pt - bot_center_pt - e_bot = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = bot_center_pt, rotation = t.rotation) - e_top = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = top_center_pt, rotation = -t.rotation) - # normals of the surfaces show inside the volume primitives. - e_top, e_bot, mantle -end -function surfaces(t::Cone{T,CO,Tuple{T,T},Nothing}) where {T,CO} - bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) - top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - mantle = ConeMantle{T,Tuple{T,T},Nothing}(t.r, t.φ, t.hZ, t.origin, t.rotation) - bot_normal = top_center_pt - bot_center_pt - e_bot = EllipticalSurface{T,T,Nothing}(r = t.r[1], φ = nothing, origin = bot_center_pt, rotation = t.rotation) - e_top = EllipticalSurface{T,T,Nothing}(r = t.r[2], φ = nothing, origin = top_center_pt, rotation = -t.rotation) + e_bot = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = bot_center_pt, rotation = t.rotation) + e_top = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) # normals of the surfaces show inside the volume primitives. e_top, e_bot, mantle end +# function surfaces(t::Cone{T,CO,Tuple{T,T},Nothing}) where {T,CO} +# bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) +# top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) +# mantle = ConeMantle{T,Tuple{T,T},Nothing}(t.r, t.φ, t.hZ, t.origin, t.rotation) +# e_bot = EllipticalSurface{T,T,Nothing}(r = t.r[1], φ = nothing, origin = bot_center_pt, rotation = t.rotation) +# e_top = EllipticalSurface{T,T,Nothing}(r = t.r[2], φ = nothing, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) +# # normals of the surfaces show inside the volume primitives. +# e_top, e_bot, mantle +# end +# function surfaces(t::Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Nothing}) where {T,CO} +# bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) +# top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) +# in_mantle = ConeMantle{T,Tuple{T,T},Nothing}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) +# out_mantle = ConeMantle{T,Tuple{T,T},Nothing}((t.r[1][2], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) +# e_bot = EllipticalSurface{T,Tuple{T,T},Nothing}(r = t.r[1], φ = nothing, origin = bot_center_pt, rotation = t.rotation) +# e_top = EllipticalSurface{T,Tuple{T,T},Nothing}(r = t.r[2], φ = nothing, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) +# # normals of the surfaces show inside the volume primitives. +# e_top, e_bot, in_mantle, out_mantle +# end # function Dictionary(g::Cone{T,<:Union{T, AbstractInterval}}) where {T} # dict = OrderedDict{String,Any}() @@ -228,20 +248,54 @@ end # ] # end -function sample(t::Tube{T}; n = 4) where {T} + +#= + This sampling might be better to be done more general: + kinda like: sample.(lines.(surfaces.(p::VolumePrimitive)) + So we only have to right a set of sample methods for certain line types +=# +function sample(t::Cylinder{T}; n = 4) where {T} # this could be improved performance-vise, # but not that important right now as it is only called # in the initzialiaton of the grid. ehZ = CartesianPoint(zero(T), zero(T), t.hZ) - e_top = Ellipse(t.r, t.φ, t.origin + t.rotation * ehZ, t.rotation) e_bot = Ellipse(t.r, t.φ, t.origin - t.rotation * ehZ, t.rotation) + e_top = Ellipse(t.r, t.φ, t.origin + t.rotation * ehZ, t.rotation) φs = range(0, step = 2π / n, length = n) - pts_top = [CartesianPoint(CylindricalPoint{T}(e_top.r, φ, zero(T))) for φ in φs] - pts_top = map(p -> _transform_into_global_coordinate_system(p, e_top), pts_top) pts_bot = [CartesianPoint(CylindricalPoint{T}(e_bot.r, φ, zero(T))) for φ in φs] pts_bot = map(p -> _transform_into_global_coordinate_system(p, e_bot), pts_bot) + pts_top = [CartesianPoint(CylindricalPoint{T}(e_top.r, φ, zero(T))) for φ in φs] + pts_top = map(p -> _transform_into_global_coordinate_system(p, e_top), pts_top) vcat(pts_bot, pts_top) end +# function sample(t::Cone{T,CO,Tuple{T,T}}; n = 4) where {T,CO} +# ehZ = CartesianPoint(zero(T), zero(T), t.hZ) +# e_bot = Ellipse(t.r[1], t.φ, t.origin - t.rotation * ehZ, t.rotation) +# e_top = Ellipse(t.r[2], t.φ, t.origin + t.rotation * ehZ, t.rotation) +# φs = range(0, step = 2π / n, length = n) +# pts_top = [CartesianPoint(CylindricalPoint{T}(e_top.r, φ, zero(T))) for φ in φs] +# pts_top = map(p -> _transform_into_global_coordinate_system(p, e_top), pts_top) +# pts_bot = [CartesianPoint(CylindricalPoint{T}(e_bot.r, φ, zero(T))) for φ in φs] +# pts_bot = map(p -> _transform_into_global_coordinate_system(p, e_bot), pts_bot) +# vcat(pts_bot, pts_top) +# end +# function sample(t::Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}}}; n = 4) where {T,CO} +# ehZ = CartesianPoint(zero(T), zero(T), t.hZ) +# e_in_bot = Ellipse(t.r[1][1], t.φ, t.origin - t.rotation * ehZ, t.rotation) +# e_out_bot = Ellipse(t.r[1][2], t.φ, t.origin - t.rotation * ehZ, t.rotation) +# e_in_top = Ellipse(t.r[2][1], t.φ, t.origin + t.rotation * ehZ, t.rotation) +# e_out_top = Ellipse(t.r[2][2], t.φ, t.origin + t.rotation * ehZ, t.rotation) +# φs = range(0, step = 2π / n, length = n) +# pts_in_bot = [CartesianPoint(CylindricalPoint{T}(e_in_bot.r, φ, zero(T))) for φ in φs] +# pts_in_bot = map(p -> _transform_into_global_coordinate_system(p, e_in_bot), pts_in_bot) +# pts_out_bot = [CartesianPoint(CylindricalPoint{T}(e_out_bot.r, φ, zero(T))) for φ in φs] +# pts_out_bot = map(p -> _transform_into_global_coordinate_system(p, e_out_bot), pts_out_bot) +# pts_in_top = [CartesianPoint(CylindricalPoint{T}(e_in_top.r, φ, zero(T))) for φ in φs] +# pts_in_top = map(p -> _transform_into_global_coordinate_system(p, e_in_top), pts_in_top) +# pts_out_top = [CartesianPoint(CylindricalPoint{T}(e_out_top.r, φ, zero(T))) for φ in φs] +# pts_out_top = map(p -> _transform_into_global_coordinate_system(p, e_out_top), pts_out_top) +# vcat(pts_in_bot, pts_out_bot, pts_in_top, pts_out_top) +# end # @inline sample(c::Cone{T}) where {T} = sample(c, (2,3,3)) # @inline sample(c::Cone{T, <:Any, Nothing}) where {T} = sample(c, (2,5,3)) From 797759772788fa27c5c71dee7b04299a7b6a6d65 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 09:34:32 +0200 Subject: [PATCH 137/241] Add `const Tube` --- src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 61a606dc5..a317b7d7a 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -34,7 +34,7 @@ Cone{T,CO,RT,TP}( c::Cone{T,CO,RT,TP}; COT = CO, Cone{T,CO,RT,TP}(c.r, c.φ, c.hZ, origin, rotation) const Cylinder{T,CO} = Cone{T,CO,T,Nothing} -# const Tube{T,CO} = Cone{T,CO,Tuple{T,T},Nothing} +const Tube{T,CO} = Cone{T,CO,Tuple{T,T},Nothing} function _in(pt::CartesianPoint, c::Cylinder{<:Real, ClosedPrimitive}) z = abs(pt.z) From 35b0469df3a531c39ba3302a44407562dfa19e04 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 09:37:45 +0200 Subject: [PATCH 138/241] Add `surface` method for `Tube` --- .../example_config_files/test_detector.yaml | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/examples/example_config_files/test_detector.yaml b/examples/example_config_files/test_detector.yaml index 482c0025b..37f49b80f 100644 --- a/examples/example_config_files/test_detector.yaml +++ b/examples/example_config_files/test_detector.yaml @@ -42,30 +42,34 @@ detectors: charge_drift_model: include: ADLChargeDriftModel/drift_velocity_config.json geometry: - tube: - r: 5 # width in x - h: 8 # width in z + difference: + - tube: + r: 4 # width in x + h: 6 # width in z + - tube: + r: 1 # width in x + h: 6 # width in z contacts: - material: HPGe name: n+ contact potential: 2000 channel: 1 geometry: - translate: - z: -3.95 - tube: - r: 1 - h: 0.2 + tube: + r: + from: 3.8 + to: 4 + h: 6 - material: HPGe name: p+ contact potential: 0 channel: 2 geometry: - translate: - z: 3.95 - tube: - r: 3 - h: 0.2 + tube: + r: + from: 1 + to: 1.2 + h: 6 surroundings: - name: Base From 165dd324bb15b37a9cbd1cadce7d235d1a992543 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 09:49:15 +0200 Subject: [PATCH 139/241] Add `sample`, `surfaces`and `_in` methods for Tube --- .../VolumePrimitives/Cone.jl | 73 +++++++++++-------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index a317b7d7a..ab08e31b1 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -36,21 +36,25 @@ Cone{T,CO,RT,TP}( c::Cone{T,CO,RT,TP}; COT = CO, const Cylinder{T,CO} = Cone{T,CO,T,Nothing} const Tube{T,CO} = Cone{T,CO,Tuple{T,T},Nothing} -function _in(pt::CartesianPoint, c::Cylinder{<:Real, ClosedPrimitive}) - z = abs(pt.z) - r = hypot(pt.x, pt.y) - # return z < c.hZ || z ≈ c.hZ && r < c.r || r ≈ c.r # This solves numerical issues but costs performance... - return z <= c.hZ && r <= c.r +function _in(pt::CartesianPoint, c::Cylinder{T,ClosedPrimitive}) where {T} + if abs(pt.z) <= c.hZ + hypot(pt.x, pt.y) <= c.r + else + false + end +end +function _in(pt::CartesianPoint, c::Cylinder{T,OpenPrimitive}) where {T} + if abs(pt.z) < c.hZ + hypot(pt.x, pt.y) < c.r + else + false + end end -_in(pt::CartesianPoint, c::Cylinder{<:Real, OpenPrimitive}) = abs(pt.z) < c.hZ && hypot(pt.x, pt.y) < c.r -function _in(pt::CartesianPoint, c::Cone{T,ClosedPrimitive,Tuple{Tuple{T,T},Tuple{T,T}},Nothing}) where {T} - z = abs(pt.z) +function _in(pt::CartesianPoint, c::Tube{T,ClosedPrimitive}) where {T} if abs(pt.z) <= c.hZ - r = hypot(pt.x, pt.y) - r_in, r_out = radii_at_z(c, z) - r_in <= r <= r_out + c.r[1] <= hypot(pt.x, pt.y) <= c.r[2] else false end @@ -114,15 +118,16 @@ function surfaces(t::Cylinder{T}) where {T} # normals of the surfaces show inside the volume primitives. e_top, e_bot, mantle end -# function surfaces(t::Cone{T,CO,Tuple{T,T},Nothing}) where {T,CO} -# bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) -# top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) -# mantle = ConeMantle{T,Tuple{T,T},Nothing}(t.r, t.φ, t.hZ, t.origin, t.rotation) -# e_bot = EllipticalSurface{T,T,Nothing}(r = t.r[1], φ = nothing, origin = bot_center_pt, rotation = t.rotation) -# e_top = EllipticalSurface{T,T,Nothing}(r = t.r[2], φ = nothing, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) -# # normals of the surfaces show inside the volume primitives. -# e_top, e_bot, mantle -# end +function surfaces(t::Tube{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + inner_mantle = ConeMantle{T,T,Nothing}(t.r[1], t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = ConeMantle{T,T,Nothing}(t.r[2], t.φ, t.hZ, t.origin, t.rotation) + e_bot = EllipticalSurface{T,Tuple{T,T},Nothing}(r = t.r, φ = nothing, origin = bot_center_pt, rotation = t.rotation) + e_top = EllipticalSurface{T,Tuple{T,T},Nothing}(r = t.r, φ = nothing, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + # normals of the surfaces show inside the volume primitives. + e_top, e_bot, inner_mantle, outer_mantle +end # function surfaces(t::Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Nothing}) where {T,CO} # bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) # top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) @@ -268,17 +273,23 @@ function sample(t::Cylinder{T}; n = 4) where {T} pts_top = map(p -> _transform_into_global_coordinate_system(p, e_top), pts_top) vcat(pts_bot, pts_top) end -# function sample(t::Cone{T,CO,Tuple{T,T}}; n = 4) where {T,CO} -# ehZ = CartesianPoint(zero(T), zero(T), t.hZ) -# e_bot = Ellipse(t.r[1], t.φ, t.origin - t.rotation * ehZ, t.rotation) -# e_top = Ellipse(t.r[2], t.φ, t.origin + t.rotation * ehZ, t.rotation) -# φs = range(0, step = 2π / n, length = n) -# pts_top = [CartesianPoint(CylindricalPoint{T}(e_top.r, φ, zero(T))) for φ in φs] -# pts_top = map(p -> _transform_into_global_coordinate_system(p, e_top), pts_top) -# pts_bot = [CartesianPoint(CylindricalPoint{T}(e_bot.r, φ, zero(T))) for φ in φs] -# pts_bot = map(p -> _transform_into_global_coordinate_system(p, e_bot), pts_bot) -# vcat(pts_bot, pts_top) -# end +function sample(t::Tube{T}; n = 4) where {T} + ehZ = CartesianPoint(zero(T), zero(T), t.hZ) + φs = range(0, step = 2π / n, length = n) + in_e_bot = Ellipse(t.r[1], t.φ, t.origin - t.rotation * ehZ, t.rotation) + out_e_bot = Ellipse(t.r[2], t.φ, t.origin - t.rotation * ehZ, t.rotation) + in_e_top = Ellipse(t.r[1], t.φ, t.origin + t.rotation * ehZ, t.rotation) + out_e_top = Ellipse(t.r[2], t.φ, t.origin + t.rotation * ehZ, t.rotation) + pts_in_bot = [CartesianPoint(CylindricalPoint{T}(in_e_bot.r, φ, zero(T))) for φ in φs] + pts_out_bot = [CartesianPoint(CylindricalPoint{T}(out_e_bot.r, φ, zero(T))) for φ in φs] + pts_in_top = [CartesianPoint(CylindricalPoint{T}(in_e_top.r, φ, zero(T))) for φ in φs] + pts_out_top = [CartesianPoint(CylindricalPoint{T}(out_e_top.r, φ, zero(T))) for φ in φs] + pts_in_bot = map(p -> _transform_into_global_coordinate_system(p, in_e_bot), pts_in_bot) + pts_out_bot = map(p -> _transform_into_global_coordinate_system(p, out_e_bot), pts_out_bot) + pts_in_top = map(p -> _transform_into_global_coordinate_system(p, in_e_top), pts_in_top) + pts_out_top = map(p -> _transform_into_global_coordinate_system(p, out_e_top), pts_out_top) + vcat(pts_in_bot, pts_out_bot, pts_in_top, pts_out_top) +end # function sample(t::Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}}}; n = 4) where {T,CO} # ehZ = CartesianPoint(zero(T), zero(T), t.hZ) # e_in_bot = Ellipse(t.r[1][1], t.φ, t.origin - t.rotation * ehZ, t.rotation) From dec690d71679cb807e3d39b011968d193d41bb9b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 17:45:32 +0200 Subject: [PATCH 140/241] Add alias `Circle` and `Annulus` for certain `Ellipse` --- src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl index 1c77524c3..5c74147de 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl @@ -20,6 +20,9 @@ rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end +const Circle{T} = Ellipse{T,T} +const Annulus{T} = Ellipse{T,Tuple{T,T}} + Ellipse{T,TR,TP}( e::Ellipse{T,TR,TP}; origin::CartesianPoint{T} = b.origin, rotation::SMatrix{3,3,T,9} = b.rotation) where {T,TR,TP} = From fcc287245f9f11a8c23d75cd186acdc8dd24c7bc Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 17:46:02 +0200 Subject: [PATCH 141/241] Add alias `CylinderMantle` for certain `ConeMantle`'s --- .../SurfacePrimitives/ConeMantle.jl | 9 +++++---- src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl | 2 +- src/PotentialSimulation/Painting/ConeMantle.jl | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index d019099ea..f575feefb 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -27,6 +27,7 @@ T: Type of values, e.g. Float64 rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end +const CylinderMantle{T} = ConeMantle{T,T} """ intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} @@ -79,13 +80,13 @@ function intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} end """ - intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} + intersection(cm::CylinderMantle{T}, l::Line{T}) where {T} The function will always return 2 CartesianPoint's. If the line just touches the mantle, the two points will be the same. If the line does not touch the mantle at all, the two points will have NaN's as there coordinates. """ -function intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} +function intersection(cm::CylinderMantle{T}, l::Line{T}) where {T} obj_l = _transform_into_object_coordinate_system(l, cm) # direction is not normalized L1 = obj_l.origin.x @@ -119,9 +120,9 @@ function intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} end -get_top_ellipse(cm::ConeMantle{T,T,Nothing}) where {T} = +get_top_ellipse(cm::CylinderMantle{T}) where {T} = Ellipse(cm.r, cm.φ, cm.origin + cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), cm.rotation) -get_bot_ellipse(cm::ConeMantle{T,T,Nothing}) where {T} = +get_bot_ellipse(cm::CylinderMantle{T}) where {T} = Ellipse(cm.r, cm.φ, cm.origin - cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), RotZ{T}(π) * -cm.rotation) get_top_ellipse(cm::ConeMantle{T,Tuple{T,T},Nothing}) where {T} = Ellipse(cm.r[2], cm.φ, cm.origin + cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), cm.rotation) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index ab08e31b1..7db10b49f 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -112,7 +112,7 @@ end function surfaces(t::Cylinder{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - mantle = ConeMantle{T,T,Nothing}(t.r, t.φ, t.hZ, t.origin, t.rotation) + mantle = CylinderMantle{T,T,Nothing}(t.r, t.φ, t.hZ, t.origin, t.rotation) e_bot = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = bot_center_pt, rotation = t.rotation) e_top = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) # normals of the surfaces show inside the volume primitives. diff --git a/src/PotentialSimulation/Painting/ConeMantle.jl b/src/PotentialSimulation/Painting/ConeMantle.jl index 06aacabec..494e7e3ff 100644 --- a/src/PotentialSimulation/Painting/ConeMantle.jl +++ b/src/PotentialSimulation/Painting/ConeMantle.jl @@ -1,5 +1,5 @@ -function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.ConeMantle, geometry, pot_value, grid::CartesianGrid) +function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.CylinderMantle, geometry, pot_value, grid::CartesianGrid) ticks = TicksTuple(grid) t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) t1, t2 = if proj == Val{:xy}() From 1a8b07013e14cae9087ee2dbe19f03879a7a7d99 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 18:38:15 +0200 Subject: [PATCH 142/241] Define type aliases for readabilityreadb --- .../LinePrimitives/Ellipse.jl | 10 +- .../SurfacePrimitives/ConeMantle.jl | 6 +- .../VolumePrimitives/Cone.jl | 192 +++++++++--------- 3 files changed, 112 insertions(+), 96 deletions(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl index 5c74147de..473eb5a3b 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl @@ -20,8 +20,10 @@ rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -const Circle{T} = Ellipse{T,T} -const Annulus{T} = Ellipse{T,Tuple{T,T}} +const Circle{T} = Ellipse{T,T,Nothing} +const PartialCircle{T} = Ellipse{T,T,Tuple{T,T}} +const Annulus{T} = Ellipse{T,Tuple{T,T},Nothing} +const PartialAnnulus{T} = Ellipse{T,Tuple{T,T},Tuple{T,T}} Ellipse{T,TR,TP}( e::Ellipse{T,TR,TP}; origin::CartesianPoint{T} = b.origin, @@ -31,7 +33,9 @@ Ellipse{T,TR,TP}( e::Ellipse{T,TR,TP}; extremum(e::Ellipse{T,T}) where {T} = e.r - +# function sample(e::Ellipse{T,TP}) where {T,TP} +# rand(2) +# end diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index f575feefb..dc4be6bc1 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -27,7 +27,11 @@ T: Type of values, e.g. Float64 rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -const CylinderMantle{T} = ConeMantle{T,T} +const CylinderMantle{T} = ConeMantle{T,T,Nothing} +const PartialCylinderMantle{T} = ConeMantle{T,T,Tuple{T,T}} + +const FullConeMantle{T} = ConeMantle{T,T,Tuple{T,T}} # ugly name but works for now +const PartialConeMantle{T} = ConeMantle{T,Tuple{T,T},Tuple{T,T}} """ intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 7db10b49f..cb04830e2 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -33,71 +33,33 @@ Cone{T,CO,RT,TP}( c::Cone{T,CO,RT,TP}; COT = CO, rotation::SMatrix{3,3,T,9} = b.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},RT,TP} = Cone{T,CO,RT,TP}(c.r, c.φ, c.hZ, origin, rotation) -const Cylinder{T,CO} = Cone{T,CO,T,Nothing} -const Tube{T,CO} = Cone{T,CO,Tuple{T,T},Nothing} +# Aliases for certain types of Cones: +# We can change these names, but for now they do their job -function _in(pt::CartesianPoint, c::Cylinder{T,ClosedPrimitive}) where {T} - if abs(pt.z) <= c.hZ - hypot(pt.x, pt.y) <= c.r - else - false - end -end -function _in(pt::CartesianPoint, c::Cylinder{T,OpenPrimitive}) where {T} - if abs(pt.z) < c.hZ - hypot(pt.x, pt.y) < c.r - else - false - end -end - - -function _in(pt::CartesianPoint, c::Tube{T,ClosedPrimitive}) where {T} - if abs(pt.z) <= c.hZ - c.r[1] <= hypot(pt.x, pt.y) <= c.r[2] - else - false - end -end - -# #Constructors for Tubes -# Tube(;rMin = 0, rMax = 1, φMin = 0, φMax = 2π, zMin = -1/2, zMax = 1/2) = Cone(rMin, rMax, rMin, rMax, φMin, φMax, zMin, zMax) -# Tube(rMin, rMax, φMin, φMax, zMin, zMax) = Tube(; rMin = rMin, rMax = rMax, φMin = φMin, φMax = φMax, zMin = zMin, zMax = zMax) - -# function Tube(r::R, height::H) where {R<:Real, H<:Real} -# T = float(promote_type(R,H)) -# Cone(T, T(r), nothing, T(height)/2) -# end - -# function Tube(rMin::R1, rMax::R2, height::H) where {R1<:Real, R2<:Real, H<:Real} -# T = float(promote_type(R1,R2,H)) -# Cone(T, rMin == 0 ? T(rMax) : T(rMin)..T(rMax), nothing, T(height)/2) -# end - -# # for Tubes -# get_r_at_z(c::Cone{T, <:Union{T, AbstractInterval{T}}, <:Any, <:Any}, z::Real) where {T} = c.r - -# # for Cones -# get_r_at_z(c::Cone{T, Tuple{T,T}, <:Any, <:Any}, z::Real) where {T} = _get_r_at_z(c.r[1], c.r[2], c.z, z) +# r_in_top = r_in_bot = 0 && r_out_top = r_out_bot > 0 +const Cylinder{T,CO} = Cone{T,CO,T,Nothing} # Full in φ +const PartialCylinder{T,CO} = Cone{T,CO,T,Tuple{T,T}} -# function get_r_at_z(c::Cone{T, Tuple{I,I}, <:Any, <:Any}, z::Real) where {T, I<:AbstractInterval{T}} -# r1::T = _get_r_at_z(c.r[1].left, c.r[2].left, c.z, z) -# r2::T = _get_r_at_z(c.r[1].right, c.r[2].right, c.z, z) -# r1..r2 -# end - -# function _get_r_at_z(rbot::TR, rtop::TR, cz::TZ, z::Real)::TR where {TR<:Real, TZ} -# (rtop - rbot) * (z - _left_linear_interval(cz)) / _width_linear_interval(cz) + rbot -# end +# r_in_top = r_in_bot = 0 && r_out_top != r_out_bot > 0 +const VaryingCylinder{T,CO} = Cone{T,CO,Tuple{Tuple{T},Tuple{T}},Nothing} # Full in φ +const PartialVaryingCylinder{T,CO} = Cone{T,CO,Tuple{Tuple{T},Tuple{T}},Tuple{T,T}} +# r_in_top = r_in_bot > 0 && r_out_top == r_out_bot > 0 +const Tube{T,CO} = Cone{T,CO,Tuple{T,T},Nothing} # Full in φ +const PartialTube{T,CO} = Cone{T,CO,T,Tuple{T,T}} -# in(p::AbstractCoordinatePoint, c::Cone{<:Any, <:Any, Nothing, <:Any}) = -# _in_z(p, c.z) && _in_cyl_r(p, get_r_at_z(c, p.z)) +# r_in_top != r_in_bot > 0 && r_out_top != r_out_bot > 0 +const VaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}}, Nothing} # Full in φ +const PartialVaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Tuple{T,T}} -# in(p::AbstractCoordinatePoint, c::Cone{<:Any, <:Any, <:AbstractInterval, <:Any}) = -# _in_z(p, c.z) && _in_φ(p, c.φ) && _in_cyl_r(p, get_r_at_z(c, p.z)) + # Future... More cases: + # r_top_in = r_top_in = 0 +# const ClosedCone{T} = Cone{T,CO,Tuple{Tuple{T,T}, Nothing},Nothing} +# const PartialClosedCone{T} = Cone{T,CO,Tuple{Tuple{T,T},Nothing},Tuple{T,T}} + # r_bot_in = r_bot_in = 0 +# const FlippedClosedCone{T} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Nothing} +# const PartialFlippedClosedCone{T} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Tuple{T,T}} -# # read-in function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::NamedTuple, transformations::Transformations{T}) where {T} length_unit = input_units.length angle_unit = input_units.angle @@ -109,15 +71,45 @@ function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::Nam return transform(cone, transformations) end +# Cylinder + +function _in(pt::CartesianPoint, c::Cylinder{T,ClosedPrimitive}) where {T} + if abs(pt.z) <= c.hZ + hypot(pt.x, pt.y) <= c.r + else + false + end +end +function _in(pt::CartesianPoint, c::Cylinder{T,OpenPrimitive}) where {T} + if abs(pt.z) < c.hZ + hypot(pt.x, pt.y) < c.r + else + false + end +end + function surfaces(t::Cylinder{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - mantle = CylinderMantle{T,T,Nothing}(t.r, t.φ, t.hZ, t.origin, t.rotation) + mantle = CylinderMantle{T}(t.r, t.φ, t.hZ, t.origin, t.rotation) e_bot = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = bot_center_pt, rotation = t.rotation) e_top = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) # normals of the surfaces show inside the volume primitives. e_top, e_bot, mantle end + +# PartialCylinder + +# Tube + +function _in(pt::CartesianPoint, c::Tube{T,ClosedPrimitive}) where {T} + if abs(pt.z) <= c.hZ + c.r[1] <= hypot(pt.x, pt.y) <= c.r[2] + else + false + end +end + function surfaces(t::Tube{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) @@ -128,7 +120,12 @@ function surfaces(t::Tube{T}) where {T} # normals of the surfaces show inside the volume primitives. e_top, e_bot, inner_mantle, outer_mantle end -# function surfaces(t::Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Nothing}) where {T,CO} + +# PartialTube + +# VaryingTube + +# function surfaces(t::VaryingTube{T,CO}) where {T,CO} # bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) # top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) # in_mantle = ConeMantle{T,Tuple{T,T},Nothing}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) @@ -139,6 +136,17 @@ end # e_top, e_bot, in_mantle, out_mantle # end +# PartialVaryingTube + + + + + +################################ +################################ +################################ + + # function Dictionary(g::Cone{T,<:Union{T, AbstractInterval}}) where {T} # dict = OrderedDict{String,Any}() # dict["r"] = typeof(g.r) == T ? g.r : OrderedDict{String,Any}("from" => g.r.left, "to" => g.r.right) @@ -259,37 +267,37 @@ end kinda like: sample.(lines.(surfaces.(p::VolumePrimitive)) So we only have to right a set of sample methods for certain line types =# -function sample(t::Cylinder{T}; n = 4) where {T} - # this could be improved performance-vise, - # but not that important right now as it is only called - # in the initzialiaton of the grid. - ehZ = CartesianPoint(zero(T), zero(T), t.hZ) - e_bot = Ellipse(t.r, t.φ, t.origin - t.rotation * ehZ, t.rotation) - e_top = Ellipse(t.r, t.φ, t.origin + t.rotation * ehZ, t.rotation) - φs = range(0, step = 2π / n, length = n) - pts_bot = [CartesianPoint(CylindricalPoint{T}(e_bot.r, φ, zero(T))) for φ in φs] - pts_bot = map(p -> _transform_into_global_coordinate_system(p, e_bot), pts_bot) - pts_top = [CartesianPoint(CylindricalPoint{T}(e_top.r, φ, zero(T))) for φ in φs] - pts_top = map(p -> _transform_into_global_coordinate_system(p, e_top), pts_top) - vcat(pts_bot, pts_top) -end -function sample(t::Tube{T}; n = 4) where {T} - ehZ = CartesianPoint(zero(T), zero(T), t.hZ) - φs = range(0, step = 2π / n, length = n) - in_e_bot = Ellipse(t.r[1], t.φ, t.origin - t.rotation * ehZ, t.rotation) - out_e_bot = Ellipse(t.r[2], t.φ, t.origin - t.rotation * ehZ, t.rotation) - in_e_top = Ellipse(t.r[1], t.φ, t.origin + t.rotation * ehZ, t.rotation) - out_e_top = Ellipse(t.r[2], t.φ, t.origin + t.rotation * ehZ, t.rotation) - pts_in_bot = [CartesianPoint(CylindricalPoint{T}(in_e_bot.r, φ, zero(T))) for φ in φs] - pts_out_bot = [CartesianPoint(CylindricalPoint{T}(out_e_bot.r, φ, zero(T))) for φ in φs] - pts_in_top = [CartesianPoint(CylindricalPoint{T}(in_e_top.r, φ, zero(T))) for φ in φs] - pts_out_top = [CartesianPoint(CylindricalPoint{T}(out_e_top.r, φ, zero(T))) for φ in φs] - pts_in_bot = map(p -> _transform_into_global_coordinate_system(p, in_e_bot), pts_in_bot) - pts_out_bot = map(p -> _transform_into_global_coordinate_system(p, out_e_bot), pts_out_bot) - pts_in_top = map(p -> _transform_into_global_coordinate_system(p, in_e_top), pts_in_top) - pts_out_top = map(p -> _transform_into_global_coordinate_system(p, out_e_top), pts_out_top) - vcat(pts_in_bot, pts_out_bot, pts_in_top, pts_out_top) -end +# function sample(t::Cylinder{T}; n = 4) where {T} +# # this could be improved performance-vise, +# # but not that important right now as it is only called +# # in the initzialiaton of the grid. +# ehZ = CartesianPoint(zero(T), zero(T), t.hZ) +# e_bot = Ellipse(t.r, t.φ, t.origin - t.rotation * ehZ, t.rotation) +# e_top = Ellipse(t.r, t.φ, t.origin + t.rotation * ehZ, t.rotation) +# φs = range(0, step = 2π / n, length = n) +# pts_bot = [CartesianPoint(CylindricalPoint{T}(e_bot.r, φ, zero(T))) for φ in φs] +# pts_bot = map(p -> _transform_into_global_coordinate_system(p, e_bot), pts_bot) +# pts_top = [CartesianPoint(CylindricalPoint{T}(e_top.r, φ, zero(T))) for φ in φs] +# pts_top = map(p -> _transform_into_global_coordinate_system(p, e_top), pts_top) +# vcat(pts_bot, pts_top) +# end +# function sample(t::Tube{T}; n = 4) where {T} +# ehZ = CartesianPoint(zero(T), zero(T), t.hZ) +# φs = range(0, step = 2π / n, length = n) +# in_e_bot = Ellipse(t.r[1], t.φ, t.origin - t.rotation * ehZ, t.rotation) +# out_e_bot = Ellipse(t.r[2], t.φ, t.origin - t.rotation * ehZ, t.rotation) +# in_e_top = Ellipse(t.r[1], t.φ, t.origin + t.rotation * ehZ, t.rotation) +# out_e_top = Ellipse(t.r[2], t.φ, t.origin + t.rotation * ehZ, t.rotation) +# pts_in_bot = [CartesianPoint(CylindricalPoint{T}(in_e_bot.r, φ, zero(T))) for φ in φs] +# pts_out_bot = [CartesianPoint(CylindricalPoint{T}(out_e_bot.r, φ, zero(T))) for φ in φs] +# pts_in_top = [CartesianPoint(CylindricalPoint{T}(in_e_top.r, φ, zero(T))) for φ in φs] +# pts_out_top = [CartesianPoint(CylindricalPoint{T}(out_e_top.r, φ, zero(T))) for φ in φs] +# pts_in_bot = map(p -> _transform_into_global_coordinate_system(p, in_e_bot), pts_in_bot) +# pts_out_bot = map(p -> _transform_into_global_coordinate_system(p, out_e_bot), pts_out_bot) +# pts_in_top = map(p -> _transform_into_global_coordinate_system(p, in_e_top), pts_in_top) +# pts_out_top = map(p -> _transform_into_global_coordinate_system(p, out_e_top), pts_out_top) +# vcat(pts_in_bot, pts_out_bot, pts_in_top, pts_out_top) +# end # function sample(t::Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}}}; n = 4) where {T,CO} # ehZ = CartesianPoint(zero(T), zero(T), t.hZ) # e_in_bot = Ellipse(t.r[1][1], t.φ, t.origin - t.rotation * ehZ, t.rotation) From 2c26979958844494634942d4fcbd80021139e67b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 19:31:41 +0200 Subject: [PATCH 143/241] Add sample method for `Edge` --- src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl index cbc160df8..b52ec1322 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl @@ -15,4 +15,14 @@ function distance(pt::CartesianPoint{T}, e::Edge{T}) where {T} else distance(pt, Line(e)) end +end + +function sample(e::Edge{T}; n = 2) where {T} + xs = range(zero(T), stop = one(T), length = n) + pts = Vector{CartesianPoint{T}}(undef, n) + dir = direction(e) + for i in eachindex(pts) + pts[i] = e.a + xs[i] .* dir + end + pts end \ No newline at end of file From 5f0bceb02b833cd4fac977b0c0bdc15e86b65e1c Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 19:32:51 +0200 Subject: [PATCH 144/241] Remove wrong aliases again & add `sample` methods for `Ellipse` --- .../LinePrimitives/Ellipse.jl | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl index 473eb5a3b..8ae173ca4 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl @@ -22,8 +22,6 @@ end const Circle{T} = Ellipse{T,T,Nothing} const PartialCircle{T} = Ellipse{T,T,Tuple{T,T}} -const Annulus{T} = Ellipse{T,Tuple{T,T},Nothing} -const PartialAnnulus{T} = Ellipse{T,Tuple{T,T},Tuple{T,T}} Ellipse{T,TR,TP}( e::Ellipse{T,TR,TP}; origin::CartesianPoint{T} = b.origin, @@ -32,16 +30,30 @@ Ellipse{T,TR,TP}( e::Ellipse{T,TR,TP}; extremum(e::Ellipse{T,T}) where {T} = e.r - -# function sample(e::Ellipse{T,TP}) where {T,TP} -# rand(2) -# end +extremum(e::Ellipse{T,Tuple{T,T}}) where {T} = max(e.r[1], e.r[1]) + +function sample(e::Circle{T}; n = 4) where {T} + φs = range(T(0), step = T(2π) / n, length = n) + pts = Vector{CartesianPoint{T}}(undef, n) + for i in eachindex(pts) + pts[i] = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(e.r, φs[i], zero(T))), e) + end + pts +end +function sample(e::PartialCircle{T}; n = 2) where {T} + φs = range(e.φ[1], stop = e.φ[1], length = n) + pts = Vector{CartesianPoint{T}}(undef, n) + for i in eachindex(pts) + pts[i] = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(e.r, φs[i], zero(T))), e) + end + pts +end # function Arc(; r = 0, center = PlanarPoint(0,0), αMin = 0, αMax = 2π) # T = float(promote_type(typeof.((r, αMin, αMax))..., eltype(center))) -# α = mod(T(αMax) - T(αMin), T(2π)) == 0 ? nothing : T(αMin)..T(αMax) +# α = mod(T(αMax ) - T(αMin), T(2π)) == 0 ? nothing : T(αMin)..T(αMax) # Arc(T, T(r), PlanarPoint{T}(center), α) # end From f67b0f6e7977573e387ee90d5acc4dc5db1bf1d5 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 19:33:20 +0200 Subject: [PATCH 145/241] Add `lines` methods for `ConeMantle` --- .../SurfacePrimitives/ConeMantle.jl | 55 +++++++++++++++---- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index dc4be6bc1..224d422cb 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -30,9 +30,51 @@ end const CylinderMantle{T} = ConeMantle{T,T,Nothing} const PartialCylinderMantle{T} = ConeMantle{T,T,Tuple{T,T}} -const FullConeMantle{T} = ConeMantle{T,T,Tuple{T,T}} # ugly name but works for now +const FullConeMantle{T} = ConeMantle{T,Tuple{T,T},Nothing} # ugly name but works for now const PartialConeMantle{T} = ConeMantle{T,Tuple{T,T},Tuple{T,T}} +function lines(sp::CylinderMantle{T}) where {T} + bot_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), sp.hZ), sp) + bot_ellipse = Circle{T}(r = sp.r, φ = sp.φ, origin = bot_origin, rotation = sp.rotation) + top_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -sp.hZ), sp) + top_ellipse = Circle{T}(r = sp.r, φ = sp.φ, origin = top_origin, rotation = sp.rotation) + bot_ellipse, top_ellipse +end +function lines(sp::PartialCylinderMantle{T}) where {T} + bot_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), sp.hZ), sp) + bot_ellipse = PartialCircle{T}(r = sp.r, φ = sp.φ, origin = bot_origin, rotation = sp.rotation) + top_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -sp.hZ), sp) + top_ellipse = PartialCircle{T}(r = sp.r, φ = sp.φ, origin = top_origin, rotation = sp.rotation) + p_bot_l = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r, sp.φ[1], -sp.hZ), sp) + p_bot_r = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r, sp.φ[2], -sp.hZ), sp) + p_top_l = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r, sp.φ[1], sp.hZ), sp) + p_top_r = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r, sp.φ[2], sp.hZ), sp) + edge_l = Edge{T}(p_bot_l, p_top_l) + edge_r = Edge{T}(p_bot_r, p_top_r) + bot_ellipse, top_ellipse, edge_l, edge_r +end +function lines(sp::FullConeMantle{T}) where {T} + bot_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T),zero(T), sp.hZ), sp) + bot_ellipse = Circle{T}(r = sp.r[1], φ = sp.φ, origin = bot_origin, rotation = sp.rotation) + top_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T),zero(T),-sp.hZ), sp) + top_ellipse = Circle{T}(r = sp.r[2], φ = sp.φ, origin = top_origin, rotation = sp.rotation) + bot_ellipse, top_ellipse +end +function lines(sp::PartialConeMantle{T}) where {T} + bot_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), sp.hZ), sp) + bot_ellipse = PartialCircle{T}(r = sp.r[1], φ = sp.φ, origin = bot_origin, rotation = sp.rotation) + top_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -sp.hZ), sp) + top_ellipse = PartialCircle{T}(r = sp.r[2], φ = sp.φ, origin = top_origin, rotation = sp.rotation) + p_bot_l = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r[1], sp.φ[1], -sp.hZ), sp) + p_bot_r = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r[1], sp.φ[2], -sp.hZ), sp) + p_top_l = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r[2], sp.φ[1], sp.hZ), sp) + p_top_r = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r[2], sp.φ[2], sp.hZ), sp) + edge_l = Edge{T}(p_bot_l, p_top_l) + edge_r = Edge{T}(p_bot_r, p_top_r) + bot_ellipse, top_ellipse, edge_l, edge_r +end + + """ intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} @@ -124,17 +166,6 @@ function intersection(cm::CylinderMantle{T}, l::Line{T}) where {T} end -get_top_ellipse(cm::CylinderMantle{T}) where {T} = - Ellipse(cm.r, cm.φ, cm.origin + cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), cm.rotation) -get_bot_ellipse(cm::CylinderMantle{T}) where {T} = - Ellipse(cm.r, cm.φ, cm.origin - cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), RotZ{T}(π) * -cm.rotation) -get_top_ellipse(cm::ConeMantle{T,Tuple{T,T},Nothing}) where {T} = - Ellipse(cm.r[2], cm.φ, cm.origin + cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), cm.rotation) -get_bot_ellipse(cm::ConeMantle{T,Tuple{T,T},Nothing}) where {T} = - Ellipse(cm.r[1], cm.φ, cm.origin - cm.rotation * CartesianPoint(zero(T), zero(T), cm.hZ), RotZ{T}(π) * -cm.rotation) - - - function get_2d_grid_ticks_and_proj(cm::ConeMantle{T}, t) where {T} et = get_top_ellipse(cm) eb = get_bot_ellipse(cm) From c9a37f1cc25f3755e9b67c5b2e0d89f7f719ac55 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 19:34:47 +0200 Subject: [PATCH 146/241] Add `lines` method for `Polygon` --- src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl index f51073be9..1b931d461 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl @@ -13,7 +13,7 @@ extreme_points(p::Polygon) = p.points function edges(p::Triangle{T}) where {T} vs = vertices(p) - return SVector{3,Edge{T}}( + return ( Edge(vs[1], vs[2]), Edge(vs[2], vs[3]), Edge(vs[3], vs[1]) @@ -21,7 +21,7 @@ function edges(p::Triangle{T}) where {T} end function edges(p::Quadrangle{T}) where {T} vs = vertices(p) - return SVector{4,Edge{T}}( + return ( Edge(vs[1], vs[2]), Edge(vs[2], vs[3]), Edge(vs[3], vs[4]), @@ -29,6 +29,8 @@ function edges(p::Quadrangle{T}) where {T} ) end +lines(p::Polygon) = edges(p) + Plane(p::Polygon{N, T}) where {N, T} = Plane{T}(p.points[1], (p.points[2] - p.points[1]) × (p.points[3] - p.points[1])) function _get_rot_for_rotation_on_xy_plane(p::Polygon{<:Any, T}) where {T} From 0c2956a048d1c032de9195325b4a551c8dcee588 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 19:40:53 +0200 Subject: [PATCH 147/241] Add aliases for `EllipticalSurface` --- .../SurfacePrimitives/EllipticalSurface.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl index 947c39ef9..a20cfeceb 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl @@ -20,6 +20,13 @@ rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end +const CircularArea{T} = EllipticalSurface{T,T,Nothing} +const PartialCircularArea{T} = EllipticalSurface{T,T,Tuple{T,T}} + +const Annulus{T} = EllipticalSurface{T,Tuple{T,T},Nothing} +const PartialAnnulus{T} = EllipticalSurface{T,Tuple{T,T},Tuple{T,T}} + + Ellipse(es::EllipticalSurface) = Ellipse(r = es.r, φ = es.φ, origin = es.origin, rotation = es.rotation) Plane(es::EllipticalSurface{T}) where {T} = Plane{T}(es.origin, es.rotation * CartesianVector{T}(zero(T),zero(T),one(T))) From 66a712972241b3cce664ba53333bec5c0fe35aec Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 20:42:14 +0200 Subject: [PATCH 148/241] Add `lines` methods for `EllipticalSurface` --- .../SurfacePrimitives/EllipticalSurface.jl | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl index a20cfeceb..ed7553876 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl @@ -26,9 +26,6 @@ const PartialCircularArea{T} = EllipticalSurface{T,T,Tuple{T,T}} const Annulus{T} = EllipticalSurface{T,Tuple{T,T},Nothing} const PartialAnnulus{T} = EllipticalSurface{T,Tuple{T,T},Tuple{T,T}} - -Ellipse(es::EllipticalSurface) = Ellipse(r = es.r, φ = es.φ, origin = es.origin, rotation = es.rotation) - Plane(es::EllipticalSurface{T}) where {T} = Plane{T}(es.origin, es.rotation * CartesianVector{T}(zero(T),zero(T),one(T))) normal(es::EllipticalSurface{T}) where {T} = es.rotation * CartesianVector{T}(zero(T), zero(T), one(T)) @@ -36,6 +33,37 @@ normal(es::EllipticalSurface{T}) where {T} = es.rotation * CartesianVector{T}(ze extremum(es::EllipticalSurface{T,T}) where {T} = es.r extremum(es::EllipticalSurface{T,Tuple{T,T}}) where {T} = max(es.r[1], es.r[2]) +function lines(sp::CircularArea{T}) where {T} + circ = Circle{T}(r = sp.r, φ = sp.φ, origin = sp.origin, rotation = sp.rotation) + return (circ,) +end +function lines(sp::PartialCircularArea{T}) where {T} + circ = PartialCircle{T}(r = sp.r, φ = sp.φ, origin = sp.origin, rotation = sp.rotation) + p_l = CartesianPoint{T}(sp.r, sp.φ[1], zero(T)) + p_r = CartesianPoint{T}(sp.r, sp.φ[2], zero(T)) + edge_l = Edge(sp.origin, _transform_into_global_coordinate_system(p_l, sp)) + edge_r = Edge(sp.origin, _transform_into_global_coordinate_system(p_r, sp)) + return (circ, edge_l, edge_r) +end + +function lines(sp::Annulus{T}) where {T} + circ_in = Circle{T}(r = sp.r[1], φ = sp.φ, origin = sp.origin, rotation = sp.rotation) + circ_out = Circle{T}(r = sp.r[2], φ = sp.φ, origin = sp.origin, rotation = sp.rotation) + return (circ_in, circ_out) +end +function lines(sp::PartialAnnulus{T}) where {T} + circ_in = PartialCircle{T}(r = sp.r[1], φ = sp.φ, origin = sp.origin, rotation = sp.rotation) + circ_out = PartialCircle{T}(r = sp.r[2], φ = sp.φ, origin = sp.origin, rotation = sp.rotation) + p_l_in = CartesianPoint{T}(sp.r[1], sp.φ[1], zero(T)) + p_l_out = CartesianPoint{T}(sp.r[2], sp.φ[1], zero(T)) + p_r_in = CartesianPoint{T}(sp.r[1], sp.φ[2], zero(T)) + p_r_out = CartesianPoint{T}(sp.r[2], sp.φ[2], zero(T)) + edge_l = Edge(_transform_into_global_coordinate_system(p_l_in, sp), + _transform_into_global_coordinate_system(p_l_out, sp)) + edge_r = Edge(_transform_into_global_coordinate_system(p_r_in, sp), + _transform_into_global_coordinate_system(p_r_out, sp)) + return (circ_in, circ_out, edge_l, edge_r) +end # #Constructors # CylindricalAnnulus(c::Cone{T}; z = 0) where {T} = CylindricalAnnulus(T, get_r_at_z(c,z), c.φ, T(z)) From 2344a433918142ac96834a0dec0e1f421881de09 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 20:42:33 +0200 Subject: [PATCH 149/241] Add type annotations --- src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl | 2 +- src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl | 4 ++-- src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl index b52ec1322..0cfa6e035 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Edge.jl @@ -17,7 +17,7 @@ function distance(pt::CartesianPoint{T}, e::Edge{T}) where {T} end end -function sample(e::Edge{T}; n = 2) where {T} +function sample(e::Edge{T}; n = 2)::Vector{CartesianPoint{T}} where {T} xs = range(zero(T), stop = one(T), length = n) pts = Vector{CartesianPoint{T}}(undef, n) dir = direction(e) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl index 8ae173ca4..678008f9f 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl @@ -32,7 +32,7 @@ Ellipse{T,TR,TP}( e::Ellipse{T,TR,TP}; extremum(e::Ellipse{T,T}) where {T} = e.r extremum(e::Ellipse{T,Tuple{T,T}}) where {T} = max(e.r[1], e.r[1]) -function sample(e::Circle{T}; n = 4) where {T} +function sample(e::Circle{T}; n = 4)::Vector{CartesianPoint{T}} where {T} φs = range(T(0), step = T(2π) / n, length = n) pts = Vector{CartesianPoint{T}}(undef, n) for i in eachindex(pts) @@ -40,7 +40,7 @@ function sample(e::Circle{T}; n = 4) where {T} end pts end -function sample(e::PartialCircle{T}; n = 2) where {T} +function sample(e::PartialCircle{T}; n = 2)::Vector{CartesianPoint{T}} where {T} φs = range(e.φ[1], stop = e.φ[1], length = n) pts = Vector{CartesianPoint{T}}(undef, n) for i in eachindex(pts) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 9773ef45c..24fb48dc2 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -44,7 +44,7 @@ function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::Named end function vertices(b::Box{T}) where {T} - return SVector{8, CartesianPoint{T}}( + return ( b.rotation * SVector{3,T}(-b.hX, -b.hY, -b.hZ) .+ b.origin, b.rotation * SVector{3,T}(+b.hX, -b.hY, -b.hZ) .+ b.origin, b.rotation * SVector{3,T}(+b.hX, +b.hY, -b.hZ) .+ b.origin, @@ -56,7 +56,7 @@ function vertices(b::Box{T}) where {T} ) end -sample(b::Box) = vertices(b) +sample(b::Box)::Vector{CartesianPoint{T}} = [vertices(b)...] function surfaces(b::Box{T}) where {T} vs = vertices(b) From 80d77a10d0b1b5a7d74a353d951835b21c9a20fa Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 20:43:34 +0200 Subject: [PATCH 150/241] Add generic method: `sample(vp::AbstractVolumePrimitive)` --- src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl | 4 +++- .../VolumePrimitives/VolumePrimitives.jl | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 24fb48dc2..305584f4d 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -56,7 +56,9 @@ function vertices(b::Box{T}) where {T} ) end -sample(b::Box)::Vector{CartesianPoint{T}} = [vertices(b)...] +function sample(b::Box{T})::Vector{CartesianPoint{T}} where {T} + [vertices(b)...] +end function surfaces(b::Box{T}) where {T} vs = vertices(b) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index 2013bc4c3..763177144 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -5,5 +5,11 @@ OpenPrimitive(p::VP) where {VP <: AbstractVolumePrimitive} = VP(p, COT = OpenPri distance(pt::CartesianPoint, vp::AbstractVolumePrimitive) = minimum(map(p -> distance(pt, p), surfaces(vp))) +function sample(vp::AbstractVolumePrimitive) + surfs = surfaces(vp) + ls = unique!(collect(Base.Iterators.flatten(lines.(surfs)))) + unique!(mapreduce(sample, vcat, ls)) +end + include("Box.jl") include("Cone.jl") \ No newline at end of file From 596ca14ad723b3e58e09f4f93f0eec8f75307de2 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 18 Jun 2021 20:46:50 +0200 Subject: [PATCH 151/241] Remove `@info` --- src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index cb04830e2..d8920527c 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -64,7 +64,6 @@ function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::Nam length_unit = input_units.length angle_unit = input_units.angle r = parse_r_of_primitive(T, dict, length_unit) - @info r φ = parse_φ_of_primitive(T, dict, angle_unit) hZ = parse_height_of_primitive(T, dict, length_unit) cone = Cone{T, ClosedPrimitive, typeof(r), typeof(φ)}(r = r, φ = φ, hZ = hZ) From 1a217c78b9e480b993bfebecd97f829f371ad2e3 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 19 Jun 2021 09:50:33 +0200 Subject: [PATCH 152/241] Remove obsolete constructor --- src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl index 678008f9f..573fb7b76 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl @@ -23,12 +23,6 @@ end const Circle{T} = Ellipse{T,T,Nothing} const PartialCircle{T} = Ellipse{T,T,Tuple{T,T}} -Ellipse{T,TR,TP}( e::Ellipse{T,TR,TP}; - origin::CartesianPoint{T} = b.origin, - rotation::SMatrix{3,3,T,9} = b.rotation) where {T,TR,TP} = - Ellipse{T,TR,TP}(e.r, e.φ, origin, rotation) - - extremum(e::Ellipse{T,T}) where {T} = e.r extremum(e::Ellipse{T,Tuple{T,T}}) where {T} = max(e.r[1], e.r[1]) From 1730dd2098fed5a438794576bc8c6d198b60543c Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 19 Jun 2021 09:50:51 +0200 Subject: [PATCH 153/241] Improve readability --- src/ConstructiveSolidGeometry/LinePrimitives/Line.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl index 67cd8c50a..be25afdf9 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl @@ -7,6 +7,6 @@ distance(pt::CartesianPoint, l::Line) = norm((pt - l.origin) × l.direction) / n function _transform_into_object_coordinate_system(l::Line{T}, p::AbstractPrimitive) where {T} origin = _transform_into_object_coordinate_system(l.origin, p) - direction = _transform_into_object_coordinate_system(CartesianPoint{T}(l.direction), p) - Line{T}( origin, direction ) + direction = _transform_into_object_coordinate_system(CartesianPoint(l.direction), p) + Line( origin, CartesianVector(direction) ) end \ No newline at end of file From 91ef74b265bf7524a178067cc53a43689031b8ba Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 19 Jun 2021 09:51:30 +0200 Subject: [PATCH 154/241] Add `intersection` method for `Plane` and `Line` --- src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl index 3a34d49f0..570fb5aa0 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl @@ -16,6 +16,15 @@ _distance(pt::AbstractCoordinatePoint, p::Plane) = (pt - origin(p)) ⋅ normal(p distance(pt::AbstractCoordinatePoint, p::Plane) = abs(_distance(pt, p)) +""" + We assume l.direction is normalized +""" +function intersection(p::Plane{T}, line::Line{T}) where {T} + ndir = normalize(line.direction) + λ = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ ndir) + line.origin + λ * ndir +end + function evaluate(p::Plane{T}, x, y, ::Val{:xy}) where {T} # plane.normal may not be perpendicular to the z-axis line = Line{T}(CartesianPoint{T}(x, y, zero(T)), CartesianVector{T}(zero(T), zero(T), one(T))) From 4cc146ca13a1cc159ed4445a000d951206078a08 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 19 Jun 2021 09:51:47 +0200 Subject: [PATCH 155/241] Bugfix --- src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index d8920527c..ef97bbe3c 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -29,9 +29,9 @@ CO: ClosedPrimitive or OpenPrimitive <-> whether surface belongs to it or not end Cone{T,CO,RT,TP}( c::Cone{T,CO,RT,TP}; COT = CO, - origin::CartesianPoint{T} = b.origin, - rotation::SMatrix{3,3,T,9} = b.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},RT,TP} = - Cone{T,CO,RT,TP}(c.r, c.φ, c.hZ, origin, rotation) + origin::CartesianPoint{T} = c.origin, + rotation::SMatrix{3,3,T,9} = c.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},RT,TP} = + Cone{T,COT,RT,TP}(c.r, c.φ, c.hZ, origin, rotation) # Aliases for certain types of Cones: # We can change these names, but for now they do their job From bf799a27df3b0af156387df1b4873771009f69a2 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 19 Jun 2021 09:53:10 +0200 Subject: [PATCH 156/241] Add proper change of volume types (closed <-> open) in `CSGDifference` --- src/ConstructiveSolidGeometry/CSG.jl | 13 ++++++++++++- .../VolumePrimitives/VolumePrimitives.jl | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/CSG.jl b/src/ConstructiveSolidGeometry/CSG.jl index 4bd2b1d35..99810b7ea 100644 --- a/src/ConstructiveSolidGeometry/CSG.jl +++ b/src/ConstructiveSolidGeometry/CSG.jl @@ -54,7 +54,18 @@ struct CSGDifference{T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} <: A end in(p::AbstractCoordinatePoint, csg::CSGDifference) = in(p, csg.a) && !in(p, csg.b) -(-)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} = CSGDifference{T,A,B}(a, b) + +function (-)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractConstructiveGeometry{T}} + ob = switchClosedOpen(b) + CSGDifference{T,A,typeof(ob)}(a, ob) +end +function switchClosedOpen(csg::CSGDifference) + CSGDifference(switchClosedOpen(csg.a), switchClosedOpen(csg.b)) +end +function (-)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractVolumePrimitive{T}} + ob = OpenPrimitive(b) + CSGDifference{T,A,typeof(ob)}(a, ob) +end # read-in function Geometry(::Type{T}, ::Type{CSGDifference}, v::Vector{<:AbstractDict}, input_units::NamedTuple, transformations::Transformations{T}) where {T} diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index 763177144..8dedc7806 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -1,6 +1,7 @@ ClosedPrimitive(p::VP) where {VP <:AbstractVolumePrimitive} = VP(p, COT = ClosedPrimitive) OpenPrimitive(p::VP) where {VP <: AbstractVolumePrimitive} = VP(p, COT = OpenPrimitive) - +switchClosedOpen(p::AbstractVolumePrimitive{<:Any,ClosedPrimitive}) = OpenPrimitive(p) +switchClosedOpen(p::AbstractVolumePrimitive{<:Any,OpenPrimitive}) = ClosedPrimitive(p) distance(pt::CartesianPoint, vp::AbstractVolumePrimitive) = minimum(map(p -> distance(pt, p), surfaces(vp))) From b4c8507c06674e027a0e800f02cd2a45d21f448a Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 19 Jun 2021 09:58:17 +0200 Subject: [PATCH 157/241] Use `approx` in `_in` method for `Box` --- src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 305584f4d..22e7fa527 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -18,8 +18,11 @@ Box{T, CO}( b::Box{T, CO}; COT = CO, Box{T, COT}(b.hX, b.hY, b.hZ, origin, rotation) _in(pt::CartesianPoint, b::Box{<:Any, ClosedPrimitive}) = - abs(pt.x) <= b.hX && abs(pt.y) <= b.hY && abs(pt.z) <= b.hZ -_in(pt::CartesianPoint, b::Box{<:Any, :OpenPrimitive}) = + (abs(pt.x) <= b.hX || abs(pt.x) ≈ b.hX) && + (abs(pt.y) <= b.hY || abs(pt.y) ≈ b.hY) && + (abs(pt.z) <= b.hZ || abs(pt.z) ≈ b.hZ) + +_in(pt::CartesianPoint, b::Box{<:Any, OpenPrimitive}) = abs(pt.x) < b.hX && abs(pt.y) < b.hY && abs(pt.z) < b.hZ function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::NamedTuple, transformations::Transformations{T}) where {T} From fd70698643960e2281d8a4ec7f23fca08c90206a Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 19 Jun 2021 10:54:10 +0200 Subject: [PATCH 158/241] Refactor `paint!`: Each surfaces is now always painted in each dimension, because, than, there are no gaps anymore (point type maps plots). In `paint!`, `intersections`-methods are now used directly instead of the `evaluate`-methods which are now removed. --- .../SurfacePrimitives/ConeMantle.jl | 67 ++++----- .../SurfacePrimitives/Plane.jl | 34 ----- .../SurfacePrimitives/SurfacePrimitives.jl | 90 ------------ src/PotentialSimulation/Painting/Painting.jl | 32 ++++ src/PotentialSimulation/Painting/Polygon.jl | 138 +++++++++--------- 5 files changed, 129 insertions(+), 232 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index 224d422cb..c3377307a 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -166,50 +166,35 @@ function intersection(cm::CylinderMantle{T}, l::Line{T}) where {T} end -function get_2d_grid_ticks_and_proj(cm::ConeMantle{T}, t) where {T} - et = get_top_ellipse(cm) - eb = get_bot_ellipse(cm) - pts = [extreme_points(et)..., extreme_points(eb)...] +# function get_2d_grid_ticks_and_proj(cm::ConeMantle{T}, t) where {T} +# pts = extreme_points(cm) - t_idx_range_x, t_idx_range_y, t_idx_range_z = get_min_max_index_ranges((pts, t)) - ls = (length(t_idx_range_x), length(t_idx_range_y), length(t_idx_range_z)) - ls = ( - ls[1] == 1 ? typemax(eltype(ls)) : ls[1], - ls[2] == 1 ? typemax(eltype(ls)) : ls[2], - ls[3] == 1 ? typemax(eltype(ls)) : ls[3] - ) - eX = CartesianVector{T}(one(T),zero(T),zero(T)) - eY = CartesianVector{T}(zero(T),one(T),zero(T)) - eZ = CartesianVector{T}(zero(T),zero(T),one(T)) - axis = cm.rotation * CartesianVector{T}(zero(T), zero(T), one(T)) - - proj, t1, t2 = if (axis × eZ != zero(CartesianVector{T})) - Val{:xy}(), t_idx_range_x, t_idx_range_y - elseif (axis × eY != zero(CartesianVector{T})) - Val{:xz}(), t_idx_range_x, t_idx_range_z - elseif (axis × eX != zero(CartesianVector{T})) - Val{:yz}(), t_idx_range_y, t_idx_range_z - else - error("Sampling Error. Have to extend cases") - # Should never happen. This else case can be removed after testing. - end - - return t1, t2, proj -end +# t_idx_range_x, t_idx_range_y, t_idx_range_z = get_min_max_index_ranges((pts, t)) +# ls = (length(t_idx_range_x), length(t_idx_range_y), length(t_idx_range_z)) +# ls = ( +# ls[1] == 1 ? typemax(eltype(ls)) : ls[1], +# ls[2] == 1 ? typemax(eltype(ls)) : ls[2], +# ls[3] == 1 ? typemax(eltype(ls)) : ls[3] +# ) +# eX = CartesianVector{T}(one(T),zero(T),zero(T)) +# eY = CartesianVector{T}(zero(T),one(T),zero(T)) +# eZ = CartesianVector{T}(zero(T),zero(T),one(T)) +# axis = cm.rotation * CartesianVector{T}(zero(T), zero(T), one(T)) + +# proj, t1, t2 = if (axis × eZ != zero(CartesianVector{T})) +# Val{:xy}(), t_idx_range_x, t_idx_range_y +# elseif (axis × eY != zero(CartesianVector{T})) +# Val{:xz}(), t_idx_range_x, t_idx_range_z +# elseif (axis × eX != zero(CartesianVector{T})) +# Val{:yz}(), t_idx_range_y, t_idx_range_z +# else +# error("Sampling Error. Have to extend cases") +# # Should never happen. This else case can be removed after testing. +# end +# return t1, t2, proj +# end -function evaluate(cm::ConeMantle{T}, x, y, ::Val{:xy}) where {T} - line = Line{T}(CartesianPoint{T}(x, y, zero(T)), CartesianVector{T}(zero(T), zero(T), one(T))) - intersection(cm, line) -end -function evaluate(cm::ConeMantle{T}, x, z, ::Val{:xz}) where {T} - line = Line{T}(CartesianPoint{T}(x, zero(T), z), CartesianVector{T}(zero(T), one(T), zero(T))) - intersection(cm, line) -end -function evaluate(cm::ConeMantle{T}, y, z, ::Val{:yz}) where {T} - line = Line{T}(CartesianPoint{T}(zero(T), y, z), CartesianVector{T}(one(T), zero(T), zero(T))) - intersection(cm, line) -end # function ConeMantle(c::Cone{T}; rbot = 1, rtop = 1) where {T} # r = rbot == rtop ? T(rbot) : (T(rbot), T(rtop)) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl index 570fb5aa0..f4187d0b2 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl @@ -24,37 +24,3 @@ function intersection(p::Plane{T}, line::Line{T}) where {T} λ = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ ndir) line.origin + λ * ndir end - -function evaluate(p::Plane{T}, x, y, ::Val{:xy}) where {T} - # plane.normal may not be perpendicular to the z-axis - line = Line{T}(CartesianPoint{T}(x, y, zero(T)), CartesianVector{T}(zero(T), zero(T), one(T))) - z = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ normalize(line.direction)) - CartesianPoint{T}(x, y, z) -end -function evaluate(p::Plane{T}, x, z, ::Val{:xz}) where {T} - # plane.normal may not be perpendicular to the y-axis - line = Line{T}(CartesianPoint{T}(x, zero(T), z), CartesianVector{T}(zero(T), one(T), zero(T))) - y = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ normalize(line.direction)) - CartesianPoint{T}(x, y, z) -end -function evaluate(p::Plane{T}, y, z, ::Val{:yz}) where {T} - # plane.normal may not be perpendicular to the x-axis - line = Line{T}(CartesianPoint{T}(zero(T), y, z), CartesianVector{T}(one(T), zero(T), zero(T))) - x = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ normalize(line.direction)) - CartesianPoint{T}(x, y, z) -end - - -function evaluate(p::Plane{T}, r, φ, ::Val{:rφ}) where {T} - # plane.normal may not be perpendicular to the z-axis - car_pt = CartesianPoint(CylindricalPoint{T}(r, φ, zero(T))) - line = Line{T}(CartesianPoint{T}(car_pt.x, car_pt.y, zero(T)), CartesianVector{T}(zero(T), zero(T), one(T))) - z = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ normalize(line.direction)) - CylindricalPoint(CartesianPoint{T}(car_pt.x, car_pt.y, z)) -end -# function evaluate(p::Plane{T}, r, z, ::Val{:rz}) where {T} -# We don't need this -# end -function evaluate(p::Plane{T}, φ, z, ::Val{:φz}) where {T} - zero(CylindricalPoint{T}) -end \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl index b7fd788e3..9b03ae570 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl @@ -6,93 +6,3 @@ include("Polygon.jl") include("ConeMantle.jl") include("EllipticalSurface.jl") - -function get_min_max_index_ranges(a::Union{ - <:Tuple{AbstractVector{<:CartesianPoint{T}}, CartesianTicksTuple{T}}, - <:Tuple{AbstractVector{<:CylindricalPoint{T}}, CylindricalTicksTuple{T}} - }) where {T} - pts, t = a[1], a[2] - ax1, ax2, ax3 = getindex.(pts, 1), getindex.(pts, 2), getindex.(pts, 3) - ax1_min_idx = searchsortedfirst(t[1], minimum(ax1)) - ax2_min_idx = searchsortedfirst(t[2], minimum(ax2)) - ax3_min_idx = searchsortedfirst(t[3], minimum(ax3)) - ax1_max_idx = searchsortedfirst(t[1], maximum(ax1)) - ax2_max_idx = searchsortedfirst(t[2], maximum(ax2)) - ax3_max_idx = searchsortedfirst(t[3], maximum(ax3)) - ls = (length(t[1]), length(t[2]), length(t[3])) - if ax1_max_idx > ls[1] ax1_max_idx = ls[1] end - if ax2_max_idx > ls[2] ax2_max_idx = ls[2] end - if ax3_max_idx > ls[3] ax3_max_idx = ls[3] end - t_idx_range_ax1 = ax1_min_idx:ax1_max_idx - t_idx_range_ax2 = ax2_min_idx:ax2_max_idx - t_idx_range_ax3 = ax3_min_idx:ax3_max_idx - t_idx_range_ax1, t_idx_range_ax2, t_idx_range_ax3 -end - -""" - get_2d_grid_ticks_and_proj(p::AbstractPlanarSurfacePrimitive, t::CartesianTicksTuple{T}) where {N, T} - -This function determines the two best dimensions to sample/paint the surface p. -E.g. `x` & `y` -> `proj = Val{:xy}()`. -The dimensions are picked such that the number of points to evaluate is minimal. -However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, -because, than, there would not be a single value, but infinite ones, -for `z` in the evalution. -""" -function get_2d_grid_ticks_and_proj(p::AbstractPlanarSurfacePrimitive, t::CartesianTicksTuple{T}) where {N, T} - # This method would actually work for any flat surface, e.g. elipse - pts = extreme_points(p) - t_idx_range_x, t_idx_range_y, t_idx_range_z = get_min_max_index_ranges((pts, t)) - ls = (length(t_idx_range_x), length(t_idx_range_y), length(t_idx_range_z)) - ls = ( - ls[1] == 1 ? typemax(eltype(ls)) : ls[1], - ls[2] == 1 ? typemax(eltype(ls)) : ls[2], - ls[3] == 1 ? typemax(eltype(ls)) : ls[3] - ) - n = normal(p) - proj, t1, t2 = if (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) - Val{:xy}(), t_idx_range_x, t_idx_range_y - elseif (n ⋅ CartesianVector{T}(zero(T),one(T),zero(T)) != 0) - Val{:xz}(), t_idx_range_x, t_idx_range_z - elseif n ⋅ CartesianVector{T}(one(T),zero(T), zero(T)) != 0 - Val{:yz}(), t_idx_range_y, t_idx_range_z - else - error("Sampling Error. Have to extend cases") - # Should never happen. This else case can be removed after testing. - end - return t1, t2, proj -end - - -""" - get_2d_grid_ticks_and_proj(p::AbstractPlanarSurfacePrimitive, t::CylindricalTicksTuple{T}) where {N, T} - -This function determines the two best dimensions to sample/paint the surface p. -E.g. `r` & `φ` -> `proj = Val{:rφ}()`. -The dimensions are picked such that the number of points to evaluate is minimal. -However, the polygon is not allowed to be parallel to the remaining dimension, e.g. `z`, -because, than, there would not be a single value, but infinite ones, for `z` in the evalution. -""" -function get_2d_grid_ticks_and_proj(p::AbstractPlanarSurfacePrimitive, t::CylindricalTicksTuple{T}) where {N, T} - # This method would actually work for any flat surface, e.g. elipse - pts = extreme_points(p) - t_idx_range_r, t_idx_range_φ, t_idx_range_z = get_min_max_index_ranges((CylindricalPoint.(pts), t)) - ls = (length(t_idx_range_r), length(t_idx_range_φ), length(t_idx_range_z)) - ls = ( - ls[1] == 1 ? typemax(eltype(ls)) : ls[1], - ls[2] == 1 ? typemax(eltype(ls)) : ls[2], - ls[3] == 1 ? typemax(eltype(ls)) : ls[3] - ) - n = normal(p) - p_r = pts[findmax(broadcast(p -> abs(p[1]), pts))[2]] - # We skip the `:rz`-case as there could be two intersections with the arc and the polygon. - proj, t1, t2 = if (n ⋅ CartesianVector{T}(zero(T),zero(T),one(T)) != 0) - # evaluate the z value -> same as for the cartesian case - Val{:rφ}(), t_idx_range_r, t_idx_range_φ - elseif (n ⋅ p_r != 0) - Val{:φz}(), t_idx_range_φ, t_idx_range_z - else - Val{:rz}(), t_idx_range_r, t_idx_range_z - end - return t1, t2, proj -end diff --git a/src/PotentialSimulation/Painting/Painting.jl b/src/PotentialSimulation/Painting/Painting.jl index 691337ba2..8a2907359 100644 --- a/src/PotentialSimulation/Painting/Painting.jl +++ b/src/PotentialSimulation/Painting/Painting.jl @@ -1,2 +1,34 @@ +function get_sub_ind_ranges(a::Union{ + <:Tuple{AbstractVector{<:CartesianPoint{T}}, CartesianTicksTuple{T}}, + <:Tuple{AbstractVector{<:CylindricalPoint{T}}, CylindricalTicksTuple{T}} + }) where {T} + # For Cylindrical Coordinates this only works for z right now + # There, we will only use t_idx_range_ax3 in the painting (for now...) + pts, t = a[1], a[2] + ax1, ax2, ax3 = getindex.(pts, 1), getindex.(pts, 2), getindex.(pts, 3) + ax1_min_idx = searchsortedfirst(t[1], minimum(ax1)) - 1 + ax2_min_idx = searchsortedfirst(t[2], minimum(ax2)) - 1 + ax3_min_idx = searchsortedfirst(t[3], minimum(ax3)) - 1 + ax1_max_idx = searchsortedfirst(t[1], maximum(ax1)) + 1 + ax2_max_idx = searchsortedfirst(t[2], maximum(ax2)) + 1 + ax3_max_idx = searchsortedfirst(t[3], maximum(ax3)) + 1 + ls = (length(t[1]), length(t[2]), length(t[3])) + if ax1_min_idx < 1 ax1_min_idx = 1 end + if ax2_min_idx < 1 ax2_min_idx = 1 end + if ax3_min_idx < 1 ax3_min_idx = 1 end + if ax1_max_idx > ls[1] ax1_max_idx = ls[1] end + if ax2_max_idx > ls[2] ax2_max_idx = ls[2] end + if ax3_max_idx > ls[3] ax3_max_idx = ls[3] end + t_idx_range_ax1 = ax1_min_idx:ax1_max_idx + t_idx_range_ax2 = ax2_min_idx:ax2_max_idx + t_idx_range_ax3 = ax3_min_idx:ax3_max_idx + t_idx_range_ax1, t_idx_range_ax2, t_idx_range_ax3 +end + +get_sub_ind_ranges(p::ConstructiveSolidGeometry.Polygon{N,T}, grid::CartesianGrid{T}) where {N,T} = + get_sub_ind_ranges((ConstructiveSolidGeometry.extreme_points(p), TicksTuple(grid))) +get_sub_ind_ranges(p::ConstructiveSolidGeometry.Polygon{N,T}, grid::CylindricalGrid{T}) where {N,T} = + get_sub_ind_ranges((CylindricalPoint.(ConstructiveSolidGeometry.extreme_points(p)), TicksTuple(grid))) + include("Polygon.jl") include("ConeMantle.jl") \ No newline at end of file diff --git a/src/PotentialSimulation/Painting/Polygon.jl b/src/PotentialSimulation/Painting/Polygon.jl index e6d6b0a26..1cff868a2 100644 --- a/src/PotentialSimulation/Painting/Polygon.jl +++ b/src/PotentialSimulation/Painting/Polygon.jl @@ -1,83 +1,87 @@ -function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive, geometry, pot_value, grid::CartesianGrid) - ticks = TicksTuple(grid) - t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) - t1, t2 = if proj == Val{:xy}() - ticks[1], ticks[2] - elseif proj == Val{:xz}() - ticks[1], ticks[3] - else - ticks[2], ticks[3] - end +function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive{T}, geometry, pot_value, grid::CartesianGrid) where {T} + t_idx_r1, t_idx_r2, t_idx_r3 = get_sub_ind_ranges(face, grid) + ticks = (grid.axes[1].ticks, grid.axes[2].ticks, grid.axes[3].ticks) plane = ConstructiveSolidGeometry.Plane(face) + eX = CartesianVector{T}(1,0,0); + eY = CartesianVector{T}(0,1,0); + eZ = CartesianVector{T}(0,0,1); for i2 in t_idx_r2 for i1 in t_idx_r1 - pt = ConstructiveSolidGeometry.evaluate(plane, t1[i1], t2[i2], proj) + l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], ticks[2][i2], zero(T)), eZ) + pt = ConstructiveSolidGeometry.intersection(plane, l) if pt in geometry - if proj == Val{:xy}() - i3 = searchsortednearest(ticks[3], pt[3]) - pointtypes[i1, i2, i3] = zero(PointType) - potential[i1, i2, i3] = pot_value - elseif proj == Val{:xz}() - i3 = searchsortednearest(ticks[2], pt[2]) - pointtypes[i1, i3, i2] = zero(PointType) - potential[i1, i3, i2] = pot_value - else - i3 = searchsortednearest(ticks[1], pt[1]) - pointtypes[i3, i1, i2] = zero(PointType) - potential[i3, i1, i2] = pot_value - end + i3 = searchsortednearest(ticks[3], pt[3]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value + end + end + end + for i3 in t_idx_r3 + for i1 in t_idx_r1 + l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], zero(T), ticks[3][i3]), eY) + pt = ConstructiveSolidGeometry.intersection(plane, l) + if pt in geometry + i2 = searchsortednearest(ticks[2], pt[2]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value + end + end + end + for i3 in t_idx_r3 + for i2 in t_idx_r2 + l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(zero(T), ticks[2][i2], ticks[3][i3]), eX) + pt = ConstructiveSolidGeometry.intersection(plane, l) + if pt in geometry + i1 = searchsortednearest(ticks[1], pt[1]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value end end end nothing end -function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive, geometry, pot_value, grid::CylindricalGrid) where {T} - ticks = TicksTuple(grid) - t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) - t1, t2 = if proj == Val{:rφ}() - ticks[1], ticks[2] - elseif proj == Val{:φz}() - ticks[2], ticks[3] - else - ticks[1], ticks[3] - end + + +function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive{T}, geometry, pot_value, grid::CylindricalGrid) where {T} + t_idx_r1, t_idx_r2, t_idx_r3 = get_sub_ind_ranges(face, grid) + ticks = (grid.axes[1].ticks, grid.axes[2].ticks, grid.axes[3].ticks) plane = ConstructiveSolidGeometry.Plane(face) - if proj == Val{:rz}() - p_temp = face.points[findmax(broadcast(p -> abs(p[1]), face.points))[2]] - φ1 = CylindricalPoint(p_temp)[2] - φ2 = φ1 < π ? φ1+π : φ1-π - # Here we have to might have to do some modiciation of φ1 and φ2 - # due to the possible periodicity of the grid. - for i2 in t_idx_r2 - for i1 in t_idx_r1 - for φ in (φ1, φ2) - pt = CylindricalPoint{T}(t1[i1], φ, t2[i2]) - if pt in geometry - i3 = searchsortednearest(ticks[2], φ) - pointtypes[i1, i3, i2] = zero(PointType) - potential[i1, i3, i2] = pot_value - end - end + eZ = CartesianVector{T}(0,0,1); + for i2 in eachindex(ticks[2]) + for i1 in eachindex(ticks[1]) + l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], ticks[2][i2], zero(T)), eZ) + pt = ConstructiveSolidGeometry.intersection(plane, l) + if pt in geometry + i3 = searchsortednearest(ticks[3], pt[3]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value end end - else - for i2 in t_idx_r2 - for i1 in t_idx_r1 - pt = ConstructiveSolidGeometry.evaluate(plane, t1[i1], t2[i2], proj) - if pt in geometry - if proj == Val{:rφ}() - i3 = searchsortednearest(ticks[3], pt[3]) - pointtypes[i1, i2, i3] = zero(PointType) - potential[i1, i2, i3] = pot_value - elseif proj == Val{:φz}() - i3 = searchsortednearest(ticks[1], pt[1]) - pointtypes[i3, i1, i2] = zero(PointType) - potential[i3, i1, i2] = pot_value - end - end + end + # for i3 in t_idx_r3 # z + # for i1 in t_idx_r1 # r + # For this we need a new method for `intersection(plane, Circle)` + # l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], zero(T), ticks[3][i3]), eY) + # pt = ConstructiveSolidGeometry.intersection(plane, l) + # if pt in geometry + # i2 = searchsortednearest(ticks[2], pt[2]) + # pointtypes[i1, i2, i3] = zero(PointType) + # potential[i1, i2, i3] = pot_value + # end + # end + # end + for i3 in t_idx_r3 # z; Maybe switch loops so that the direction of `l` has to be calculated less times.. + o = CartesianPoint{T}(zero(T), zero(T), ticks[3][i3]) + for i2 in eachindex(ticks[2]) # φ + l = ConstructiveSolidGeometry.Line(o, CartesianVector(CartesianPoint(CylindricalPoint{T}(one(T), ticks[2][i2], zero(T))))) + pt = CylindricalPoint(ConstructiveSolidGeometry.intersection(plane, l)) + if pt in geometry + i1 = searchsortednearest(ticks[1], pt[1]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value end - end - end + end + end nothing end From a084cc4e54d1a9c93d20c1d62a3ca65cadca859a Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 19 Jun 2021 11:33:11 +0200 Subject: [PATCH 159/241] Bugfix in `paint!` for Polygon on Cylindrical Grid --- src/PotentialSimulation/Painting/Polygon.jl | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/PotentialSimulation/Painting/Polygon.jl b/src/PotentialSimulation/Painting/Polygon.jl index 1cff868a2..2bda85b68 100644 --- a/src/PotentialSimulation/Painting/Polygon.jl +++ b/src/PotentialSimulation/Painting/Polygon.jl @@ -50,7 +50,7 @@ function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive{T}, eZ = CartesianVector{T}(0,0,1); for i2 in eachindex(ticks[2]) for i1 in eachindex(ticks[1]) - l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], ticks[2][i2], zero(T)), eZ) + l = ConstructiveSolidGeometry.Line(CartesianPoint(CylindricalPoint{T}(ticks[1][i1], ticks[2][i2], zero(T))), eZ) pt = ConstructiveSolidGeometry.intersection(plane, l) if pt in geometry i3 = searchsortednearest(ticks[3], pt[3]) @@ -74,10 +74,15 @@ function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive{T}, for i3 in t_idx_r3 # z; Maybe switch loops so that the direction of `l` has to be calculated less times.. o = CartesianPoint{T}(zero(T), zero(T), ticks[3][i3]) for i2 in eachindex(ticks[2]) # φ - l = ConstructiveSolidGeometry.Line(o, CartesianVector(CartesianPoint(CylindricalPoint{T}(one(T), ticks[2][i2], zero(T))))) - pt = CylindricalPoint(ConstructiveSolidGeometry.intersection(plane, l)) - if pt in geometry - i1 = searchsortednearest(ticks[1], pt[1]) + dir = CartesianVector(CartesianPoint(CylindricalPoint{T}(one(T), ticks[2][i2], zero(T)))) + l = ConstructiveSolidGeometry.Line(o, dir) # dir should be normalized + pt_car = ConstructiveSolidGeometry.intersection(plane, l) + pt_cyl = CylindricalPoint(pt_car) + # Intersection must be in positive r direction of dir: pt_cyl[2] == ticks[2][i2] + # Use `abs(pt_cyl[2] - ticks[2][i2]) < 0.1` to avoid rounding issues + # if it differs, it would always differ by π = 3.141... -> 0.1 is fine + if abs(pt_cyl[2] - ticks[2][i2]) < 0.1 && pt_car in geometry + i1 = searchsortednearest(ticks[1], pt_cyl[1]) pointtypes[i1, i2, i3] = zero(PointType) potential[i1, i2, i3] = pot_value end From 2eb03edbfbf635cc1c77fd0b1246441c51f75902 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 19 Jun 2021 13:15:36 +0200 Subject: [PATCH 160/241] =?UTF-8?q?Start=20and=20stoped=20implementing=20`?= =?UTF-8?q?intersection=5Fwith=5F=CF=86=5Faxis`=20for=20Polygon.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cylindrical coordinates... --- .../SurfacePrimitives/Plane.jl | 11 +++++++++++ src/PotentialSimulation/Painting/Polygon.jl | 5 ++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl index f4187d0b2..5bbe9ded7 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl @@ -24,3 +24,14 @@ function intersection(p::Plane{T}, line::Line{T}) where {T} λ = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ ndir) line.origin + λ * ndir end + +function intersection_with_φ_axis(p::Plane{T}, r::T, z::T) where {T} + n = normal(p) + o = origin(p) + u = n × CartesianVector{T}(-n[3], n[1], n[2]) + v = n × u + + error("This will be fun...") + + n ⋅ u, n ⋅ v +end diff --git a/src/PotentialSimulation/Painting/Polygon.jl b/src/PotentialSimulation/Painting/Polygon.jl index 2bda85b68..d23b5651e 100644 --- a/src/PotentialSimulation/Painting/Polygon.jl +++ b/src/PotentialSimulation/Painting/Polygon.jl @@ -59,9 +59,11 @@ function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive{T}, end end end + # For this we need a the function `intersection_with_φ_axis`... + # This will be fun... I skip this for now. + # for i3 in t_idx_r3 # z # for i1 in t_idx_r1 # r - # For this we need a new method for `intersection(plane, Circle)` # l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], zero(T), ticks[3][i3]), eY) # pt = ConstructiveSolidGeometry.intersection(plane, l) # if pt in geometry @@ -71,6 +73,7 @@ function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive{T}, # end # end # end + for i3 in t_idx_r3 # z; Maybe switch loops so that the direction of `l` has to be calculated less times.. o = CartesianPoint{T}(zero(T), zero(T), ticks[3][i3]) for i2 in eachindex(ticks[2]) # φ From 28c219303b6715426317c91330eb81351edd27aa Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 19 Jun 2021 13:34:01 +0200 Subject: [PATCH 161/241] Add `extremum` method for `CylinderMantle` --- src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index c3377307a..f4b900671 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -27,12 +27,15 @@ T: Type of values, e.g. Float64 rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end + const CylinderMantle{T} = ConeMantle{T,T,Nothing} const PartialCylinderMantle{T} = ConeMantle{T,T,Tuple{T,T}} const FullConeMantle{T} = ConeMantle{T,Tuple{T,T},Nothing} # ugly name but works for now const PartialConeMantle{T} = ConeMantle{T,Tuple{T,T},Tuple{T,T}} +extremum(cm::CylinderMantle{T}) where {T} = sqrt(cm.hZ^2 + cm.r^2) + function lines(sp::CylinderMantle{T}) where {T} bot_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), sp.hZ), sp) bot_ellipse = Circle{T}(r = sp.r, φ = sp.φ, origin = bot_origin, rotation = sp.rotation) From 6aa1e6c8e97637635040a1b524652a672c58b2a0 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 19 Jun 2021 13:34:43 +0200 Subject: [PATCH 162/241] Adjust paining for `CurvedSurfaces` on a cartesian grid --- .../Painting/ConeMantle.jl | 35 -------- src/PotentialSimulation/Painting/Curved.jl | 84 +++++++++++++++++++ src/PotentialSimulation/Painting/Painting.jl | 8 +- .../Painting/{Polygon.jl => Planar.jl} | 0 4 files changed, 88 insertions(+), 39 deletions(-) delete mode 100644 src/PotentialSimulation/Painting/ConeMantle.jl create mode 100644 src/PotentialSimulation/Painting/Curved.jl rename src/PotentialSimulation/Painting/{Polygon.jl => Planar.jl} (100%) diff --git a/src/PotentialSimulation/Painting/ConeMantle.jl b/src/PotentialSimulation/Painting/ConeMantle.jl deleted file mode 100644 index 494e7e3ff..000000000 --- a/src/PotentialSimulation/Painting/ConeMantle.jl +++ /dev/null @@ -1,35 +0,0 @@ - -function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.CylinderMantle, geometry, pot_value, grid::CartesianGrid) - ticks = TicksTuple(grid) - t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) - t1, t2 = if proj == Val{:xy}() - ticks[1], ticks[2] - elseif proj == Val{:xz}() - ticks[1], ticks[3] - else - ticks[2], ticks[3] - end - for i2 in t_idx_r2 - for i1 in t_idx_r1 - pt1, pt2 = ConstructiveSolidGeometry.evaluate(face, t1[i1], t2[i2], proj) - for pt in (pt1, pt2) - if pt in geometry - if proj == Val{:xy}() - i3 = searchsortednearest(ticks[3], pt[3]) - pointtypes[i1, i2, i3] = zero(PointType) - potential[i1, i2, i3] = pot_value - elseif proj == Val{:xz}() - i3 = searchsortednearest(ticks[2], pt[2]) - pointtypes[i1, i3, i2] = zero(PointType) - potential[i1, i3, i2] = pot_value - else - i3 = searchsortednearest(ticks[1], pt[1]) - pointtypes[i3, i1, i2] = zero(PointType) - potential[i3, i1, i2] = pot_value - end - end - end - end - end - nothing -end \ No newline at end of file diff --git a/src/PotentialSimulation/Painting/Curved.jl b/src/PotentialSimulation/Painting/Curved.jl new file mode 100644 index 000000000..871b8571b --- /dev/null +++ b/src/PotentialSimulation/Painting/Curved.jl @@ -0,0 +1,84 @@ + +function paint!(pointtypes, potential, face::AbstractCurvedSurfacePrimitive{T}, geometry, pot_value, grid::CartesianGrid) where {T} + t_idx_r1, t_idx_r2, t_idx_r3 = get_sub_ind_ranges(face, grid) + ticks = (grid.axes[1].ticks, grid.axes[2].ticks, grid.axes[3].ticks) + eX = CartesianVector{T}(1,0,0); + eY = CartesianVector{T}(0,1,0); + eZ = CartesianVector{T}(0,0,1); + for i2 in t_idx_r2 + for i1 in t_idx_r1 + l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], ticks[2][i2], zero(T)), eZ) + pts = ConstructiveSolidGeometry.intersection(face, l) + for pt in pts + if pt in geometry + i3 = searchsortednearest(ticks[3], pt[3]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value + end + end + end + end + for i3 in t_idx_r3 + for i1 in t_idx_r1 + l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], zero(T), ticks[3][i3]), eY) + pts = ConstructiveSolidGeometry.intersection(face, l) + for pt in pts + if pt in geometry + i2 = searchsortednearest(ticks[2], pt[2]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value + end + end + end + end + for i3 in t_idx_r3 + for i2 in t_idx_r2 + l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(zero(T), ticks[2][i2], ticks[3][i3]), eX) + pts = ConstructiveSolidGeometry.intersection(face, l) + for pt in pts + if pt in geometry + i1 = searchsortednearest(ticks[1], pt[1]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value + end + end + end + end + nothing +end + + +# function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.CylinderMantle, geometry, pot_value, grid::CartesianGrid) +# ticks = TicksTuple(grid) +# t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) +# t1, t2 = if proj == Val{:xy}() +# ticks[1], ticks[2] +# elseif proj == Val{:xz}() +# ticks[1], ticks[3] +# else +# ticks[2], ticks[3] +# end +# for i2 in t_idx_r2 +# for i1 in t_idx_r1 +# pt1, pt2 = ConstructiveSolidGeometry.evaluate(face, t1[i1], t2[i2], proj) +# for pt in (pt1, pt2) +# if pt in geometry +# if proj == Val{:xy}() +# i3 = searchsortednearest(ticks[3], pt[3]) +# pointtypes[i1, i2, i3] = zero(PointType) +# potential[i1, i2, i3] = pot_value +# elseif proj == Val{:xz}() +# i3 = searchsortednearest(ticks[2], pt[2]) +# pointtypes[i1, i3, i2] = zero(PointType) +# potential[i1, i3, i2] = pot_value +# else +# i3 = searchsortednearest(ticks[1], pt[1]) +# pointtypes[i3, i1, i2] = zero(PointType) +# potential[i3, i1, i2] = pot_value +# end +# end +# end +# end +# end +# nothing +# end \ No newline at end of file diff --git a/src/PotentialSimulation/Painting/Painting.jl b/src/PotentialSimulation/Painting/Painting.jl index 8a2907359..e8554bece 100644 --- a/src/PotentialSimulation/Painting/Painting.jl +++ b/src/PotentialSimulation/Painting/Painting.jl @@ -25,10 +25,10 @@ function get_sub_ind_ranges(a::Union{ t_idx_range_ax1, t_idx_range_ax2, t_idx_range_ax3 end -get_sub_ind_ranges(p::ConstructiveSolidGeometry.Polygon{N,T}, grid::CartesianGrid{T}) where {N,T} = +get_sub_ind_ranges(p::ConstructiveSolidGeometry.AbstractSurfacePrimitive{T}, grid::CartesianGrid{T}) where {N,T} = get_sub_ind_ranges((ConstructiveSolidGeometry.extreme_points(p), TicksTuple(grid))) -get_sub_ind_ranges(p::ConstructiveSolidGeometry.Polygon{N,T}, grid::CylindricalGrid{T}) where {N,T} = +get_sub_ind_ranges(p::ConstructiveSolidGeometry.AbstractSurfacePrimitive{T}, grid::CylindricalGrid{T}) where {N,T} = get_sub_ind_ranges((CylindricalPoint.(ConstructiveSolidGeometry.extreme_points(p)), TicksTuple(grid))) -include("Polygon.jl") -include("ConeMantle.jl") \ No newline at end of file +include("Planar.jl") +include("Curved.jl") \ No newline at end of file diff --git a/src/PotentialSimulation/Painting/Polygon.jl b/src/PotentialSimulation/Painting/Planar.jl similarity index 100% rename from src/PotentialSimulation/Painting/Polygon.jl rename to src/PotentialSimulation/Painting/Planar.jl From 9663a5e0bea472345ef831bb3d7dab9d092267e0 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sat, 19 Jun 2021 13:34:55 +0200 Subject: [PATCH 163/241] Fix config file --- examples/example_config_files/test_detector.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_config_files/test_detector.yaml b/examples/example_config_files/test_detector.yaml index 37f49b80f..144b81ee4 100644 --- a/examples/example_config_files/test_detector.yaml +++ b/examples/example_config_files/test_detector.yaml @@ -48,7 +48,7 @@ detectors: h: 6 # width in z - tube: r: 1 # width in x - h: 6 # width in z + h: 6.5 # width in z contacts: - material: HPGe name: n+ contact From 7026964d4c28bc16e8c6829e954c13cb4c1fe126 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 20 Jun 2021 10:07:09 +0200 Subject: [PATCH 164/241] Add `paint!` method for `Curved` surfaces on a cylindrical grid --- src/PotentialSimulation/Painting/Curved.jl | 88 +++++++++++++--------- 1 file changed, 54 insertions(+), 34 deletions(-) diff --git a/src/PotentialSimulation/Painting/Curved.jl b/src/PotentialSimulation/Painting/Curved.jl index 871b8571b..e6dbc1e26 100644 --- a/src/PotentialSimulation/Painting/Curved.jl +++ b/src/PotentialSimulation/Painting/Curved.jl @@ -48,37 +48,57 @@ function paint!(pointtypes, potential, face::AbstractCurvedSurfacePrimitive{T}, end -# function paint!(pointtypes, potential, face::ConstructiveSolidGeometry.CylinderMantle, geometry, pot_value, grid::CartesianGrid) -# ticks = TicksTuple(grid) -# t_idx_r1, t_idx_r2, proj = ConstructiveSolidGeometry.get_2d_grid_ticks_and_proj(face, ticks) -# t1, t2 = if proj == Val{:xy}() -# ticks[1], ticks[2] -# elseif proj == Val{:xz}() -# ticks[1], ticks[3] -# else -# ticks[2], ticks[3] -# end -# for i2 in t_idx_r2 -# for i1 in t_idx_r1 -# pt1, pt2 = ConstructiveSolidGeometry.evaluate(face, t1[i1], t2[i2], proj) -# for pt in (pt1, pt2) -# if pt in geometry -# if proj == Val{:xy}() -# i3 = searchsortednearest(ticks[3], pt[3]) -# pointtypes[i1, i2, i3] = zero(PointType) -# potential[i1, i2, i3] = pot_value -# elseif proj == Val{:xz}() -# i3 = searchsortednearest(ticks[2], pt[2]) -# pointtypes[i1, i3, i2] = zero(PointType) -# potential[i1, i3, i2] = pot_value -# else -# i3 = searchsortednearest(ticks[1], pt[1]) -# pointtypes[i3, i1, i2] = zero(PointType) -# potential[i3, i1, i2] = pot_value -# end -# end -# end -# end -# end -# nothing -# end \ No newline at end of file +function paint!(pointtypes, potential, face::AbstractCurvedSurfacePrimitive{T}, geometry, pot_value, grid::CylindricalGrid) where {T} + t_idx_r1, t_idx_r2, t_idx_r3 = get_sub_ind_ranges(face, grid) + ticks = (grid.axes[1].ticks, grid.axes[2].ticks, grid.axes[3].ticks) + eZ = CartesianVector{T}(0,0,1); + + for i2 in eachindex(ticks[2]) + for i1 in eachindex(ticks[1]) + l = ConstructiveSolidGeometry.Line(CartesianPoint(CylindricalPoint{T}(ticks[1][i1], ticks[2][i2], zero(T))), eZ) + pts = ConstructiveSolidGeometry.intersection(face, l) + for pt in pts + if pt in geometry + i3 = searchsortednearest(ticks[3], pt[3]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value + end + end + end + end + # For this we need a the function `intersection_with_φ_axis`... + # This will be fun... I skip this for now. + + # for i3 in t_idx_r3 # z + # for i1 in t_idx_r1 # r + # l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], zero(T), ticks[3][i3]), eY) + # pt = ConstructiveSolidGeometry.intersection(plane, l) + # if pt in geometry + # i2 = searchsortednearest(ticks[2], pt[2]) + # pointtypes[i1, i2, i3] = zero(PointType) + # potential[i1, i2, i3] = pot_value + # end + # end + # end + + for i3 in t_idx_r3 # z; Maybe switch loops so that the direction of `l` has to be calculated less times.. + o = CartesianPoint{T}(zero(T), zero(T), ticks[3][i3]) + for i2 in eachindex(ticks[2]) # φ + dir = CartesianVector(CartesianPoint(CylindricalPoint{T}(one(T), ticks[2][i2], zero(T)))) + l = ConstructiveSolidGeometry.Line(o, dir) # dir should be normalized + pts_car = ConstructiveSolidGeometry.intersection(face, l) + for pt_car in pts_car + pt_cyl = CylindricalPoint(pt_car) + # Intersection must be in positive r direction of dir: pt_cyl[2] == ticks[2][i2] + # Use `abs(pt_cyl[2] - ticks[2][i2]) < 0.1` to avoid rounding issues + # if it differs, it would always differ by π = 3.141... -> 0.1 is fine + if abs(pt_cyl[2] - ticks[2][i2]) < 0.1 && pt_car in geometry + i1 = searchsortednearest(ticks[1], pt_cyl[1]) + pointtypes[i1, i2, i3] = zero(PointType) + potential[i1, i2, i3] = pot_value + end + end + end + end + nothing +end From f15c3b9da10d2542d89ce7b79d4f77be02de613c Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 20 Jun 2021 10:12:19 +0200 Subject: [PATCH 165/241] Add `extremum` methods for `ConeMantle` --- .../SurfacePrimitives/ConeMantle.jl | 6 +++++- .../SurfacePrimitives/EllipticalSurface.jl | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index f4b900671..57f757704 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -31,10 +31,14 @@ end const CylinderMantle{T} = ConeMantle{T,T,Nothing} const PartialCylinderMantle{T} = ConeMantle{T,T,Tuple{T,T}} -const FullConeMantle{T} = ConeMantle{T,Tuple{T,T},Nothing} # ugly name but works for now +const FullConeMantle{T} = ConeMantle{T,Tuple{T,T},Nothing} # ugly name but works for now, should just be `ConeMantle`... const PartialConeMantle{T} = ConeMantle{T,Tuple{T,T},Tuple{T,T}} extremum(cm::CylinderMantle{T}) where {T} = sqrt(cm.hZ^2 + cm.r^2) +extremum(cm::PartialCylinderMantle{T}) where {T} = sqrt(cm.hZ^2 + cm.r^2) + +extremum(cm::FullConeMantle{T}) where {T} = sqrt(cm.hZ^2 + max(es.r[1], es.r[2])^2) +extremum(cm::PartialConeMantle{T}) where {T} = sqrt(cm.hZ^2 + max(es.r[1], es.r[2])^2) function lines(sp::CylinderMantle{T}) where {T} bot_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), sp.hZ), sp) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl index ed7553876..fa0e49cb7 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl @@ -31,7 +31,7 @@ Plane(es::EllipticalSurface{T}) where {T} = Plane{T}(es.origin, es.rotation * Ca normal(es::EllipticalSurface{T}) where {T} = es.rotation * CartesianVector{T}(zero(T), zero(T), one(T)) extremum(es::EllipticalSurface{T,T}) where {T} = es.r -extremum(es::EllipticalSurface{T,Tuple{T,T}}) where {T} = max(es.r[1], es.r[2]) +extremum(es::EllipticalSurface{T,Tuple{T,T}}) where {T} = es.r[2] # r_out always larger r_in: es.r[2] > es.r[2] function lines(sp::CircularArea{T}) where {T} circ = Circle{T}(r = sp.r, φ = sp.φ, origin = sp.origin, rotation = sp.rotation) From 57f94500984635e703b35cf99fcbcbc92d332256 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 20 Jun 2021 10:20:25 +0200 Subject: [PATCH 166/241] Change to cylindrical grid --- .../example_config_files/test_detector.yaml | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/examples/example_config_files/test_detector.yaml b/examples/example_config_files/test_detector.yaml index 144b81ee4..880e08fb8 100644 --- a/examples/example_config_files/test_detector.yaml +++ b/examples/example_config_files/test_detector.yaml @@ -5,20 +5,33 @@ units: potential: V temperature: K grid: - coordinates: cartesian + coordinates: cylindrical axes: - x: - from: -9 + r: to: 9 boundaries: inf y: - from: -9 - to: 9 - boundaries: inf + from: 0 + to: 180 + boundaries: periodic z: from: -9 to: 9 boundaries: inf + # coordinates: cartesian + # axes: + # x: + # from: -9 + # to: 9 + # boundaries: inf + # y: + # from: -9 + # to: 9 + # boundaries: inf + # z: + # from: -9 + # to: 9 + # boundaries: inf medium: vacuum detectors: - translate: From 6567cd12e9320866cc642306e9765161ad07575d Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 20 Jun 2021 11:47:11 +0200 Subject: [PATCH 167/241] Add support for `PartialCylinder` --- src/ConstructiveSolidGeometry/IO.jl | 2 +- src/ConstructiveSolidGeometry/Intervals.jl | 6 ++- .../SurfacePrimitives/ConeMantle.jl | 20 ++++---- .../SurfacePrimitives/EllipticalSurface.jl | 12 ++--- .../SurfacePrimitives/Polygon.jl | 5 ++ .../VolumePrimitives/Cone.jl | 49 ++++++++++++++++--- .../plotting/LinePrimitives/Ellipse.jl | 6 +++ .../plotting/SurfacePrimitives/ConeMantle.jl | 19 +++---- .../SurfacePrimitives/EllipticalSurface.jl | 26 +++++----- 9 files changed, 96 insertions(+), 49 deletions(-) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 8522c20d1..72ff7f09a 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -82,7 +82,7 @@ function _parse_angular_interval(::Type{T}, dict::AbstractDict, unit::Unitful.Un φTo::T = _parse_value(T, dict["to"], unit) φFrom::T = _parse_value(T, dict["from"], unit) if abs(rem2pi(φFrom - φTo, RoundNearest)) > 2*eps(T) - φFrom..φTo + φFrom, φTo #else nothing end end diff --git a/src/ConstructiveSolidGeometry/Intervals.jl b/src/ConstructiveSolidGeometry/Intervals.jl index 6d4f79c0f..85dd71c18 100644 --- a/src/ConstructiveSolidGeometry/Intervals.jl +++ b/src/ConstructiveSolidGeometry/Intervals.jl @@ -23,11 +23,15 @@ @inline _in_angular_interval_closed(α::Real, α_int::Nothing, tol::Real = 0) = true @inline _in_angular_interval_closed(α::Real, α_int::AbstractInterval{T}, tol::Real = 0) where {T} = mod(α - (α_int.left-tol), T(2π)) ≤ (α_int.right+tol) - (α_int.left-tol) +@inline _in_angular_interval_closed(α::T, α_int::Tuple{T,T}) where {T} = mod(α - α_int[1], T(2π)) ≤ (α_int[2] - α_int[1]) +@inline _in_angular_interval_open(α::T, α_int::Tuple{T,T}) where {T} = 0 < mod(α - α_int[1], T(2π)) < (α_int[2] - α_int[1]) + + @inline _in_angular_interval_open(α::T, α_int::Nothing) where {T<:Real} = 0 < mod(α, T(2π)) < T(2π) @inline _in_angular_interval_open(α::Real, α_int::AbstractInterval{T}) where {T} = 0 < mod(α - α_int.left, T(2π)) < α_int.right - α_int.left _in_angular_interval_union(val::T, α::AbstractInterval, β::AbstractInterval) where {T<:AbstractFloat} = - _in_angular_interval_closed(val, α) || _in_angular_interval_closed(val, β) +_in_angular_interval_closed(val, α) || _in_angular_interval_closed(val, β) function _is_edge_of_angular_interval_union(val::T, α::AbstractInterval, β::AbstractInterval) where {T<:AbstractFloat} tol = 10*geom_atol_zero(T) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index 57f757704..b9db44611 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -52,10 +52,10 @@ function lines(sp::PartialCylinderMantle{T}) where {T} bot_ellipse = PartialCircle{T}(r = sp.r, φ = sp.φ, origin = bot_origin, rotation = sp.rotation) top_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -sp.hZ), sp) top_ellipse = PartialCircle{T}(r = sp.r, φ = sp.φ, origin = top_origin, rotation = sp.rotation) - p_bot_l = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r, sp.φ[1], -sp.hZ), sp) - p_bot_r = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r, sp.φ[2], -sp.hZ), sp) - p_top_l = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r, sp.φ[1], sp.hZ), sp) - p_top_r = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r, sp.φ[2], sp.hZ), sp) + p_bot_l = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r, sp.φ[1], -sp.hZ)), sp) + p_bot_r = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r, sp.φ[2], -sp.hZ)), sp) + p_top_l = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r, sp.φ[1], sp.hZ)), sp) + p_top_r = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r, sp.φ[2], sp.hZ)), sp) edge_l = Edge{T}(p_bot_l, p_top_l) edge_r = Edge{T}(p_bot_r, p_top_r) bot_ellipse, top_ellipse, edge_l, edge_r @@ -72,10 +72,10 @@ function lines(sp::PartialConeMantle{T}) where {T} bot_ellipse = PartialCircle{T}(r = sp.r[1], φ = sp.φ, origin = bot_origin, rotation = sp.rotation) top_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -sp.hZ), sp) top_ellipse = PartialCircle{T}(r = sp.r[2], φ = sp.φ, origin = top_origin, rotation = sp.rotation) - p_bot_l = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r[1], sp.φ[1], -sp.hZ), sp) - p_bot_r = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r[1], sp.φ[2], -sp.hZ), sp) - p_top_l = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r[2], sp.φ[1], sp.hZ), sp) - p_top_r = _transform_into_global_coordinate_system(CartesianPoint{T}(sp.r[2], sp.φ[2], sp.hZ), sp) + p_bot_l = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r[1], sp.φ[1], -sp.hZ)), sp) + p_bot_r = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r[1], sp.φ[2], -sp.hZ)), sp) + p_top_l = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r[2], sp.φ[1], sp.hZ)), sp) + p_top_r = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r[2], sp.φ[2], sp.hZ)), sp) edge_l = Edge{T}(p_bot_l, p_top_l) edge_r = Edge{T}(p_bot_r, p_top_r) bot_ellipse, top_ellipse, edge_l, edge_r @@ -133,13 +133,13 @@ function intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} end """ - intersection(cm::CylinderMantle{T}, l::Line{T}) where {T} + intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} The function will always return 2 CartesianPoint's. If the line just touches the mantle, the two points will be the same. If the line does not touch the mantle at all, the two points will have NaN's as there coordinates. """ -function intersection(cm::CylinderMantle{T}, l::Line{T}) where {T} +function intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} obj_l = _transform_into_object_coordinate_system(l, cm) # direction is not normalized L1 = obj_l.origin.x diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl index fa0e49cb7..ac80aa77a 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipticalSurface.jl @@ -39,8 +39,8 @@ function lines(sp::CircularArea{T}) where {T} end function lines(sp::PartialCircularArea{T}) where {T} circ = PartialCircle{T}(r = sp.r, φ = sp.φ, origin = sp.origin, rotation = sp.rotation) - p_l = CartesianPoint{T}(sp.r, sp.φ[1], zero(T)) - p_r = CartesianPoint{T}(sp.r, sp.φ[2], zero(T)) + p_l = CartesianPoint(CylindricalPoint{T}(sp.r, sp.φ[1], zero(T))) + p_r = CartesianPoint(CylindricalPoint{T}(sp.r, sp.φ[2], zero(T))) edge_l = Edge(sp.origin, _transform_into_global_coordinate_system(p_l, sp)) edge_r = Edge(sp.origin, _transform_into_global_coordinate_system(p_r, sp)) return (circ, edge_l, edge_r) @@ -54,10 +54,10 @@ end function lines(sp::PartialAnnulus{T}) where {T} circ_in = PartialCircle{T}(r = sp.r[1], φ = sp.φ, origin = sp.origin, rotation = sp.rotation) circ_out = PartialCircle{T}(r = sp.r[2], φ = sp.φ, origin = sp.origin, rotation = sp.rotation) - p_l_in = CartesianPoint{T}(sp.r[1], sp.φ[1], zero(T)) - p_l_out = CartesianPoint{T}(sp.r[2], sp.φ[1], zero(T)) - p_r_in = CartesianPoint{T}(sp.r[1], sp.φ[2], zero(T)) - p_r_out = CartesianPoint{T}(sp.r[2], sp.φ[2], zero(T)) + p_l_in = CartesianPoint(CylindricalPoint{T}(sp.r[1], sp.φ[1], zero(T))) + p_l_out = CartesianPoint(CylindricalPoint{T}(sp.r[2], sp.φ[1], zero(T))) + p_r_in = CartesianPoint(CylindricalPoint{T}(sp.r[1], sp.φ[2], zero(T))) + p_r_out = CartesianPoint(CylindricalPoint{T}(sp.r[2], sp.φ[2], zero(T))) edge_l = Edge(_transform_into_global_coordinate_system(p_l_in, sp), _transform_into_global_coordinate_system(p_l_out, sp)) edge_r = Edge(_transform_into_global_coordinate_system(p_r_in, sp), diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl index 1b931d461..94cbd1912 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Polygon.jl @@ -83,6 +83,11 @@ function _above_or_below_polygon(pt::AbstractCoordinatePoint, p::Quadrangle{T}) return PolygonOps.inpolygon(view(rot * pt, 1:2), pts2d) != 0 end +function _transform_into_global_coordinate_system(poly::Polygon{N, T}, p::AbstractPrimitive{T}) where {N, T} + Polygon{N,T}(broadcast(pt -> _transform_into_global_coordinate_system(pt, p), poly.points)) +end + + function distance(pt::CartesianPoint, p::Polygon) return if _above_or_below_polygon(pt, p) distance(pt, Plane(p)) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index ef97bbe3c..034633575 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -91,13 +91,43 @@ function surfaces(t::Cylinder{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) mantle = CylinderMantle{T}(t.r, t.φ, t.hZ, t.origin, t.rotation) - e_bot = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = bot_center_pt, rotation = t.rotation) - e_top = EllipticalSurface{T,T,Nothing}(r = t.r, φ = nothing, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + e_bot = CircularArea{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + e_top = CircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) # normals of the surfaces show inside the volume primitives. e_top, e_bot, mantle end # PartialCylinder +function _in(pt::CartesianPoint, c::PartialCylinder{T,ClosedPrimitive}) where {T} + abs(pt.z) <= c.hZ && + hypot(pt.x, pt.y) <= c.r && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) +end +function _in(pt::CartesianPoint, c::PartialCylinder{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + hypot(pt.x, pt.y) < c.r && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +end + +function surfaces(t::PartialCylinder{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + mantle = PartialCylinderMantle{T}(t.r, t.φ, t.hZ, t.origin, t.rotation) + e_bot = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + e_top = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = t.rotation) #RotZ{T}(π) * -t.rotation) + poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( + CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r, t.φ[1], -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r, t.φ[1], +t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), +t.hZ)) )), t) + poly_r = _transform_into_global_coordinate_system(Quadrangle{T}(( + CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), -t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r, t.φ[2], +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r, t.φ[2], -t.hZ)) )), t) + # normals of the surfaces show inside the volume primitives. + (e_top, e_bot, mantle, poly_l, poly_r) +end # Tube @@ -108,14 +138,21 @@ function _in(pt::CartesianPoint, c::Tube{T,ClosedPrimitive}) where {T} false end end +function _in(pt::CartesianPoint, c::Tube{T,OpenPrimitive}) where {T} + if abs(pt.z) < c.hZ + c.r[1] < hypot(pt.x, pt.y) < c.r[2] + else + false + end +end function surfaces(t::Tube{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - inner_mantle = ConeMantle{T,T,Nothing}(t.r[1], t.φ, t.hZ, t.origin, t.rotation) - outer_mantle = ConeMantle{T,T,Nothing}(t.r[2], t.φ, t.hZ, t.origin, t.rotation) - e_bot = EllipticalSurface{T,Tuple{T,T},Nothing}(r = t.r, φ = nothing, origin = bot_center_pt, rotation = t.rotation) - e_top = EllipticalSurface{T,Tuple{T,T},Nothing}(r = t.r, φ = nothing, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + inner_mantle = CylinderMantle{T}(t.r[1], t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = CylinderMantle{T}(t.r[2], t.φ, t.hZ, t.origin, t.rotation) + e_bot = Annulus{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + e_top = Annulus{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) # normals of the surfaces show inside the volume primitives. e_top, e_bot, inner_mantle, outer_mantle end diff --git a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl index ac1105010..b9d99916d 100644 --- a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl @@ -4,6 +4,12 @@ function edges(e::Ellipse{T,T,Nothing}; n = 4) where {T} pts = map(p -> _transform_into_global_coordinate_system(p, e), pts) edges = [Edge(pts[i], pts[i+1]) for i in 1:n] end +function edges(e::Ellipse{T,T,Tuple{T,T}}; n = 4) where {T} + φs = range(e.φ[1], stop = e.φ[2], length = n + 1) + pts = [CartesianPoint(CylindricalPoint{T}(e.r, φ, zero(T))) for φ in φs] + pts = map(p -> _transform_into_global_coordinate_system(p, e), pts) + edges = [Edge(pts[i], pts[i+1]) for i in 1:n] +end @recipe function f(e::Ellipse; n = 40) @series begin diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl index 9d5315619..8845bc621 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl @@ -1,20 +1,15 @@ @recipe function f(cm::ConeMantle, n = 40; subn = 10) - e_top = get_top_ellipse(cm) - e_bot = get_bot_ellipse(cm) - e_top_edges = edges(e_top, n = n) - e_bot_edges = edges(e_bot, n = n) + ls = lines(cm) linecolor --> :black @series begin label --> "Cone Mantle" - e_top_edges + ls[1] end - @series begin - label := nothing - e_bot_edges - end - @series begin - label := nothing - map(i -> Edge(e_top_edges[i].a, e_bot_edges[i].a), 1:subn:length(e_top_edges)) + for i in 2:length(ls) + @series begin + label := nothing + ls[i] + end end end diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl index 57646bb88..65b982695 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl @@ -1,22 +1,22 @@ -@recipe function f(es::EllipticalSurface) - ess = ellpises(es) - linecolor --> black +@recipe function f(es::EllipticalSurface; n = 40) + ls = lines(es) + linecolor --> :black @series begin label --> "Elliptical Surface" - ess[1] + n := n + ls[1] end - if length(ess) == 2 - label := nothing - ess[2] + if length(ls) > 1 + for i in 2:length(ls) + @series begin + label := nothing + n := n + ls[i] + end + end end end -ellpises(es::EllipticalSurface{T,T}) where {T} = (Ellipse(es),) -function ellpises(es::EllipticalSurface{T,Tuple{T,T}}) where {T} - Ellipse(r = es.r[1], φ = es.φ, origin = es.origin, rotation = es.rotation), - Ellipse(r = es.r[2], φ = es.φ, origin = es.origin, rotation = es.rotation) -end - # function get_plot_points(a::CylindricalAnnulus{T}; n = 30) where {T <: AbstractFloat} # plot_points = Vector{CartesianPoint{T}}[] From 8d796e59831c5882d2d245ac8aae1f7299d0eb75 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 20 Jun 2021 11:59:55 +0200 Subject: [PATCH 168/241] Code style --- .../VolumePrimitives/Cone.jl | 30 +++++-------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 034633575..62a6ea661 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -71,20 +71,13 @@ function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::Nam end # Cylinder - function _in(pt::CartesianPoint, c::Cylinder{T,ClosedPrimitive}) where {T} - if abs(pt.z) <= c.hZ - hypot(pt.x, pt.y) <= c.r - else - false - end + abs(pt.z) <= c.hZ && + hypot(pt.x, pt.y) <= c.r end function _in(pt::CartesianPoint, c::Cylinder{T,OpenPrimitive}) where {T} - if abs(pt.z) < c.hZ - hypot(pt.x, pt.y) < c.r - else - false - end + abs(pt.z) < c.hZ && + hypot(pt.x, pt.y) < c.r end function surfaces(t::Cylinder{T}) where {T} @@ -130,20 +123,13 @@ function surfaces(t::PartialCylinder{T}) where {T} end # Tube - function _in(pt::CartesianPoint, c::Tube{T,ClosedPrimitive}) where {T} - if abs(pt.z) <= c.hZ - c.r[1] <= hypot(pt.x, pt.y) <= c.r[2] - else - false - end + abs(pt.z) <= c.hZ && + c.r[1] <= hypot(pt.x, pt.y) <= c.r[2] end function _in(pt::CartesianPoint, c::Tube{T,OpenPrimitive}) where {T} - if abs(pt.z) < c.hZ - c.r[1] < hypot(pt.x, pt.y) < c.r[2] - else - false - end + abs(pt.z) < c.hZ && + c.r[1] < hypot(pt.x, pt.y) < c.r[2] end function surfaces(t::Tube{T}) where {T} From 003f0ff7d7e442ab45d9efddb2b225ae1df0f23b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Sun, 20 Jun 2021 13:53:42 +0200 Subject: [PATCH 169/241] Clearify aliases for `Cone` --- .../VolumePrimitives/Cone.jl | 275 +++++++++++++----- 1 file changed, 208 insertions(+), 67 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 62a6ea661..e4dc8b753 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -33,32 +33,98 @@ Cone{T,CO,RT,TP}( c::Cone{T,CO,RT,TP}; COT = CO, rotation::SMatrix{3,3,T,9} = c.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},RT,TP} = Cone{T,COT,RT,TP}(c.r, c.φ, c.hZ, origin, rotation) -# Aliases for certain types of Cones: -# We can change these names, but for now they do their job +#################################################################### +#################################################################### -# r_in_top = r_in_bot = 0 && r_out_top = r_out_bot > 0 + +#= +___ + | + | + | +___| + +=# const Cylinder{T,CO} = Cone{T,CO,T,Nothing} # Full in φ const PartialCylinder{T,CO} = Cone{T,CO,T,Tuple{T,T}} -# r_in_top = r_in_bot = 0 && r_out_top != r_out_bot > 0 -const VaryingCylinder{T,CO} = Cone{T,CO,Tuple{Tuple{T},Tuple{T}},Nothing} # Full in φ -const PartialVaryingCylinder{T,CO} = Cone{T,CO,Tuple{Tuple{T},Tuple{T}},Tuple{T,T}} -# r_in_top = r_in_bot > 0 && r_out_top == r_out_bot > 0 -const Tube{T,CO} = Cone{T,CO,Tuple{T,T},Nothing} # Full in φ -const PartialTube{T,CO} = Cone{T,CO,T,Tuple{T,T}} -# r_in_top != r_in_bot > 0 && r_out_top != r_out_bot > 0 -const VaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}}, Nothing} # Full in φ -const PartialVaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Tuple{T,T}} +#= +___ + \ + \ +_____\ + +=# +const VaryingCylinder{T,CO} = Cone{T,CO,Tuple{T,T},Nothing} # Full in φ +const PartialVaryingCylinder{T,CO} = Cone{T,CO,Tuple{T,T},Tuple{T,T}} + + + +#= + ___ + / \ +/_____\ + +=# +const VaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Nothing} # Full in φ +const PartialVaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Tuple{T,T}} + + + +#= + +\ + \ +__\ + +=# +const UpwardCone{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Nothing},Nothing} # Full in φ +const PartialUpwardCone{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Nothing},Tuple{T,T}} + + + +#= +___ + / + / +/ + +=# +const DownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Nothing} # Full in φ +const PartialDownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Tuple{T,T}} + + + +#= + + /\ + / \ +/____\ + +=# +const TopClosedTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},T},Nothing} # Full in φ +const PartialTopClosedTube{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Tuple{T,T}} + + + +#= + +______ +\ / + \ / + \/ + +=# +const BottomClosedTube{T,CO} = Cone{T,CO,Tuple{T, Tuple{T,T}},Nothing} # Full in φ +const PartialBottomClosedTube{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Tuple{T,T}} + + + +#################################################################### +#################################################################### - # Future... More cases: - # r_top_in = r_top_in = 0 -# const ClosedCone{T} = Cone{T,CO,Tuple{Tuple{T,T}, Nothing},Nothing} -# const PartialClosedCone{T} = Cone{T,CO,Tuple{Tuple{T,T},Nothing},Tuple{T,T}} - # r_bot_in = r_bot_in = 0 -# const FlippedClosedCone{T} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Nothing} -# const PartialFlippedClosedCone{T} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Tuple{T,T}} function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::NamedTuple, transformations::Transformations{T}) where {T} length_unit = input_units.length @@ -83,7 +149,7 @@ end function surfaces(t::Cylinder{T}) where {T} bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - mantle = CylinderMantle{T}(t.r, t.φ, t.hZ, t.origin, t.rotation) + mantle = ConeMantle{T,Tuple{T,T},Nothing}((t.r, t.r), t.φ, t.hZ, t.origin, t.rotation) e_bot = CircularArea{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) e_top = CircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) # normals of the surfaces show inside the volume primitives. @@ -91,61 +157,136 @@ function surfaces(t::Cylinder{T}) where {T} end # PartialCylinder -function _in(pt::CartesianPoint, c::PartialCylinder{T,ClosedPrimitive}) where {T} - abs(pt.z) <= c.hZ && - hypot(pt.x, pt.y) <= c.r && - _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) -end -function _in(pt::CartesianPoint, c::PartialCylinder{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - hypot(pt.x, pt.y) < c.r && - _in_angular_interval_open(atan(pt.y, pt.x), c.φ) -end +# function _in(pt::CartesianPoint, c::PartialCylinder{T,ClosedPrimitive}) where {T} +# abs(pt.z) <= c.hZ && +# hypot(pt.x, pt.y) <= c.r && +# _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) +# end +# function _in(pt::CartesianPoint, c::PartialCylinder{T,OpenPrimitive}) where {T} +# abs(pt.z) < c.hZ && +# hypot(pt.x, pt.y) < c.r && +# _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +# end + +# function surfaces(t::PartialCylinder{T}) where {T} +# bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) +# top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) +# mantle = PartialConeMantle{T}((t.r, t.r), t.φ, t.hZ, t.origin, t.rotation) +# e_bot = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) +# e_top = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) +# poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( +# CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), -t.hZ)), +# CartesianPoint(CylindricalPoint{T}( t.r, t.φ[1], -t.hZ)), +# CartesianPoint(CylindricalPoint{T}( t.r, t.φ[1], +t.hZ)), +# CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), +t.hZ)) )), t) +# poly_r = _transform_into_global_coordinate_system(Quadrangle{T}(( +# CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), -t.hZ)), +# CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), +t.hZ)), +# CartesianPoint(CylindricalPoint{T}( t.r, t.φ[2], +t.hZ)), +# CartesianPoint(CylindricalPoint{T}( t.r, t.φ[2], -t.hZ)) )), t) +# # normals of the surfaces show inside the volume primitives. +# (e_top, e_bot, mantle, poly_l, poly_r) +# end + +# VaryingCylinder +# radius_at_z(hZ::T, rBot::T, rTop::T, z::T) where {T} = rBot + (rTop - rBot) * z / 2hZ + +# function _in(pt::CartesianPoint, c::VaryingCylinder{T,ClosedPrimitive}) where {T} +# abs(pt.z) <= c.hZ && +# hypot(pt.x, pt.y) <= radius_at_z(c.hZ, c.r[2][1], c.r[2][2], pt.z) +# end +# function _in(pt::CartesianPoint, c::VaryingCylinder{T,OpenPrimitive}) where {T} +# abs(pt.z) < c.hZ && +# hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[2][1], c.r[2][2], pt.z) +# end + +# function surfaces(t::VaryingCylinder{T}) where {T} +# bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) +# top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) +# mantle = ConeMantle{T,Tuple{T,T},Nothing}((t.r[2][1], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) +# e_bot = CircularArea{T}(r = t.r[2][1], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) +# e_top = CircularArea{T}(r = t.r[2][2], φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) +# # normals of the surfaces show inside the volume primitives. +# e_top, e_bot, mantle +# end + -function surfaces(t::PartialCylinder{T}) where {T} - bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) - top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - mantle = PartialCylinderMantle{T}(t.r, t.φ, t.hZ, t.origin, t.rotation) - e_bot = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) - e_top = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = t.rotation) #RotZ{T}(π) * -t.rotation) - poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( - CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), -t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r, t.φ[1], -t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r, t.φ[1], +t.hZ)), - CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), +t.hZ)) )), t) - poly_r = _transform_into_global_coordinate_system(Quadrangle{T}(( - CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), -t.hZ)), - CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), +t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r, t.φ[2], +t.hZ)), - CartesianPoint(CylindricalPoint{T}( t.r, t.φ[2], -t.hZ)) )), t) - # normals of the surfaces show inside the volume primitives. - (e_top, e_bot, mantle, poly_l, poly_r) -end # Tube -function _in(pt::CartesianPoint, c::Tube{T,ClosedPrimitive}) where {T} - abs(pt.z) <= c.hZ && - c.r[1] <= hypot(pt.x, pt.y) <= c.r[2] -end -function _in(pt::CartesianPoint, c::Tube{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - c.r[1] < hypot(pt.x, pt.y) < c.r[2] -end +# function _in(pt::CartesianPoint, c::Tube{T,ClosedPrimitive}) where {T} +# abs(pt.z) <= c.hZ && +# c.r[1] <= hypot(pt.x, pt.y) <= c.r[2] +# end +# function _in(pt::CartesianPoint, c::Tube{T,OpenPrimitive}) where {T} +# abs(pt.z) < c.hZ && +# c.r[1] < hypot(pt.x, pt.y) < c.r[2] +# end -function surfaces(t::Tube{T}) where {T} - bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) - top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - inner_mantle = CylinderMantle{T}(t.r[1], t.φ, t.hZ, t.origin, t.rotation) - outer_mantle = CylinderMantle{T}(t.r[2], t.φ, t.hZ, t.origin, t.rotation) - e_bot = Annulus{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) - e_top = Annulus{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) - # normals of the surfaces show inside the volume primitives. - e_top, e_bot, inner_mantle, outer_mantle -end +# function surfaces(t::Tube{T}) where {T} +# bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) +# top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) +# inner_mantle = ConeMantle{T}((t.r[1], t.r[1]), t.φ, t.hZ, t.origin, t.rotation) +# outer_mantle = ConeMantle{T}((t.r[2], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) +# e_bot = Annulus{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) +# e_top = Annulus{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) +# # normals of the surfaces show inside the volume primitives. +# e_top, e_bot, inner_mantle, outer_mantle +# end # PartialTube +# function _in(pt::CartesianPoint, c::PartialTube{T,ClosedPrimitive}) where {T} +# abs(pt.z) <= c.hZ && +# c.r[1] <= hypot(pt.x, pt.y) <= c.r[2] && +# _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) +# end +# function _in(pt::CartesianPoint, c::PartialTube{T,OpenPrimitive}) where {T} +# abs(pt.z) < c.hZ && +# c.r[1] < hypot(pt.x, pt.y) < c.r && +# _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +# end + +# function surfaces(t::PartialTube{T}) where {T} +# bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) +# top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) +# inner_mantle = PartialConeMantle{T}((t.r[1], t.r[1]), t.φ, t.hZ, t.origin, t.rotation) +# outer_mantle = PartialConeMantle{T}((t.r[2], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) +# e_bot = PartialAnnulus{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) +# e_top = PartialAnnulus{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) +# poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( +# CartesianPoint(CylindricalPoint{T}( t.r[1], t.φ[1], -t.hZ)), +# CartesianPoint(CylindricalPoint{T}( t.r[2], t.φ[1], -t.hZ)), +# CartesianPoint(CylindricalPoint{T}( t.r[2], t.φ[1], +t.hZ)), +# CartesianPoint(CylindricalPoint{T}( t.r[1], t.φ[1], +t.hZ)) )), t) +# poly_r = _transform_into_global_coordinate_system(Quadrangle{T}(( +# CartesianPoint(CylindricalPoint{T}( t.r[2], t.φ[2], -t.hZ)), +# CartesianPoint(CylindricalPoint{T}( t.r[2], t.φ[2], +t.hZ)), +# CartesianPoint(CylindricalPoint{T}( t.r[1], t.φ[2], +t.hZ)), +# CartesianPoint(CylindricalPoint{T}( t.r[1], t.φ[2], -t.hZ)) )), t) +# # normals of the surfaces show inside the volume primitives. +# e_top, e_bot, inner_mantle, outer_mantle, poly_l, poly_r +# end # VaryingTube +# function _in(pt::CartesianPoint, c::VaryingTube{T,ClosedPrimitive}) where {T} +# abs(pt.z) <= c.hZ && +# c.r[1] <= hypot(pt.x, pt.y) <= c.r[2] +# end +# function _in(pt::CartesianPoint, c::VaryingTube{T,OpenPrimitive}) where {T} +# abs(pt.z) < c.hZ && +# c.r[1] < hypot(pt.x, pt.y) < c.r[2] +# end + +# function surfaces(t::VaryingTube{T}) where {T} +# bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) +# top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) +# inner_mantle = CylinderMantle{T}(t.r[1], t.φ, t.hZ, t.origin, t.rotation) +# outer_mantle = CylinderMantle{T}(t.r[2], t.φ, t.hZ, t.origin, t.rotation) +# e_bot = Annulus{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) +# e_top = Annulus{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) +# # normals of the surfaces show inside the volume primitives. +# e_top, e_bot, inner_mantle, outer_mantle +# end + # function surfaces(t::VaryingTube{T,CO}) where {T,CO} # bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) From d5a38cb0c8b248881d6b49faf1be39dc3b266a0b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 21 Jun 2021 11:21:14 +0200 Subject: [PATCH 170/241] Change test detector file due to tests --- .../example_config_files/test_detector.yaml | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/examples/example_config_files/test_detector.yaml b/examples/example_config_files/test_detector.yaml index 880e08fb8..2513fe296 100644 --- a/examples/example_config_files/test_detector.yaml +++ b/examples/example_config_files/test_detector.yaml @@ -55,13 +55,15 @@ detectors: charge_drift_model: include: ADLChargeDriftModel/drift_velocity_config.json geometry: - difference: - - tube: - r: 4 # width in x - h: 6 # width in z - - tube: - r: 1 # width in x - h: 6.5 # width in z + tube: + r: + bottom: 4 + top: 6 + h: 6 # width in z + # difference: + # - tube: + # r: 1 # width in x + # h: 6.5 # width in z contacts: - material: HPGe name: n+ contact @@ -69,9 +71,10 @@ detectors: channel: 1 geometry: tube: - r: - from: 3.8 - to: 4 + r: 2 + # top: + # from: 3.8 + # to: 4 h: 6 - material: HPGe name: p+ contact @@ -80,8 +83,12 @@ detectors: geometry: tube: r: - from: 1 - to: 1.2 + bottom: + from: 4 + to: 6 + top: + from: 3.5 + to: 4 h: 6 surroundings: From 8f5e7cb9ec198fe11ab6fc7075f69632ea1c0068 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 21 Jun 2021 11:22:51 +0200 Subject: [PATCH 171/241] Add `yaml`-version of the IVC config file --- .../public_ivc_config.yaml | 169 ++++++++++++++++++ src/examples.jl | 2 +- 2 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 examples/example_config_files/public_ivc_config.yaml diff --git a/examples/example_config_files/public_ivc_config.yaml b/examples/example_config_files/public_ivc_config.yaml new file mode 100644 index 000000000..5d0d3661b --- /dev/null +++ b/examples/example_config_files/public_ivc_config.yaml @@ -0,0 +1,169 @@ +name: Public Inverted Coax +units: + length: mm + angle: deg + potential: V + temperature: K +grid: + coordinates: cylindrical + axes: + r: + to: 40 + boundaries: inf + phi: + from: 0 + to: 0 + boundaries: periodic + z: + from: -10 + to: 90 + boundaries: + left: inf + right: inf +# grid: +# coordinates: cartesian +# axes: +# x: +# from: -40 +# to: 40 +# boundaries: +# left: inf +# right: inf +# y: +# from: -40 +# to: 40 +# boundaries: +# left: inf +# right: inf +# z: +# from: -10 +# to: 90 +# boundaries: +# left: inf +# right: inf +medium: vacuum +detectors: + - bulk: + material: HPGe + temperature: 78 + impurity_density: + name: cylindrical + r: + init: 0 + gradient: 0 + z: + init: -10000000 + gradient: -100000 + charge_drift_model: + include: ADLChargeDriftModel/drift_velocity_config.json + geometry: + difference: + - difference: + - translate: + tube: + r: 35 + phi: + from: 0 + to: 360 + h: 80 + z: 40 + - translate: + cone: + r: + bottom: + from: 35 + to: 36 + top: + from: 23.71 + to: 36 + phi: + from: 0 + to: 360 + h: 64 + z: 52 + - translate: + tube: + r: 5 + phi: + from: 0 + to: 360 + h: 80 + z: 65 + contacts: + - material: HPGe + channel: 1 + potential: 0 + geometry: + translate: + tube: + r: 3 + phi: + from: 0 + to: 360 + h: 2 + z: 1 + - material: HPGe + channel: 2 + potential: 3500 + geometry: + union: + - tube: + r: + from: 15 + to: 35 + phi: + from: 0 + to: 360 + h: 0 + - translate: + tube: + r: + from: 35 + to: 35 + phi: + from: 0 + to: 360 + h: 20 + z: 10 + - translate: + cone: + r: + bottom: + from: 35 + to: 35 + top: + from: 24.42 + to: 24.42 + phi: + from: 0 + to: 360 + h: 60 + z: 50 + - translate: + tube: + r: + from: 5 + to: 24.42 + phi: + from: 0 + to: 360 + h: 0 + z: 80 + - translate: + tube: + r: + from: 5 + to: 5 + phi: + from: 0 + to: 360 + h: 55 + z: 52.5 + - translate: + tube: + r: 5 + phi: + from: 0 + to: 360 + h: 0 + z: 25 diff --git a/src/examples.jl b/src/examples.jl index 32d262d5c..a36650adb 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -13,7 +13,7 @@ SSD_examples[:Coax] = ( joinpath(@__DIR__, "../examples/example_config_files/public_Coax_config.json") ) SSD_examples[:InvertedCoax] = ( - joinpath(@__DIR__, "../examples/example_config_files/public_ivc_config.json") + joinpath(@__DIR__, "../examples/example_config_files/public_ivc_config.yaml") ) SSD_examples[:InvertedCoaxInCryostat] = ( joinpath(@__DIR__, "../examples/example_config_files/ivc_splitted_config/public_ivc_cryostat_config.json") From 6d5e5da25b7a14fcdc6c819675b6c29dd7839bc5 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 21 Jun 2021 11:23:40 +0200 Subject: [PATCH 172/241] Fix detector plot recipe for detectors with no passive objects --- src/PlotRecipes/SolidStateDetector.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/PlotRecipes/SolidStateDetector.jl b/src/PlotRecipes/SolidStateDetector.jl index c602c5d85..6890dd039 100644 --- a/src/PlotRecipes/SolidStateDetector.jl +++ b/src/PlotRecipes/SolidStateDetector.jl @@ -30,9 +30,11 @@ end c end end - for p in det.passives - @series begin - p + if !ismissing(det.passives) + for p in det.passives + @series begin + p + end end end end From da24c35fe684933d6fa377512204316a2ff6bcc9 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 21 Jun 2021 11:24:39 +0200 Subject: [PATCH 173/241] Improve plot recipes: Add normal-option for surfaces --- .../plotting/PointsAndVectors/Vectors.jl | 21 +++++++------ .../plotting/SurfacePrimitives/ConeMantle.jl | 11 +++++++ .../SurfacePrimitives/EllipticalSurface.jl | 31 +++++++++++++++++++ .../plotting/SurfacePrimitives/Polygon.jl | 9 +++--- .../SurfacePrimitives/SurfacePrimitives.jl | 4 +-- 5 files changed, 60 insertions(+), 16 deletions(-) diff --git a/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl index a1bcf8b19..89143ecea 100644 --- a/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl +++ b/src/ConstructiveSolidGeometry/plotting/PointsAndVectors/Vectors.jl @@ -1,22 +1,22 @@ @recipe function f(::Type{Val{:vector}}, x, y, z; - headlength = 0.05, headwidth = 0.02 ) + headlength = 0.1, headwidth = 0.05 ) origin = x vector = y target = origin + vector - length = norm(vector) - hl = length * headlength - hw = length * headwidth + hl = headlength + hw = headwidth T = eltype(origin) eX = CartesianVector{T}(1,0,0) eY = CartesianVector{T}(0,1,0) eZ = CartesianVector{T}(0,0,1) - apxl = target - hl*vector - hw * normalize(vector × eX) - apxr = target - hl*vector + hw * normalize(vector × eX) - apyl = target - hl*vector - hw * normalize(vector × eY) - apyr = target - hl*vector + hw * normalize(vector × eY) - apzl = target - hl*vector - hw * normalize(vector × eZ) - apzr = target - hl*vector + hw * normalize(vector × eZ) + apxl = target - hl*vector - hw * normalize(vector × eX) * norm(vector) + apxr = target - hl*vector + hw * normalize(vector × eX) * norm(vector) + apyl = target - hl*vector - hw * normalize(vector × eY) * norm(vector) + apyr = target - hl*vector + hw * normalize(vector × eY) * norm(vector) + apzl = target - hl*vector - hw * normalize(vector × eZ) * norm(vector) + apzr = target - hl*vector + hw * normalize(vector × eZ) * norm(vector) + label --> nothing linecolor --> :black x := [origin[1], target[1], apxl[1], target[1], apxr[1], target[1], apyl[1], target[1], apyr[1], target[1], apzl[1], target[1], apzr[1]] y := [origin[2], target[2], apxl[2], target[2], apxr[2], target[2], apyl[2], target[2], apyr[2], target[2], apzl[2], target[2], apzr[2]] @@ -28,6 +28,7 @@ end @recipe function f(v::CartesianVector{T}) where {T} @series begin seriestype --> :vector + label --> nothing CartesianPoint{T}(0,0,0), v end end \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl index 8845bc621..5d68bbee6 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/ConeMantle.jl @@ -11,6 +11,17 @@ ls[i] end end + if !haskey(plotattributes, :show_normal) || plotattributes[:show_normal] + @series begin + label := nothing + seriestype := :vector + nφ = cm.φ == nothing ? 0 : (cm.φ[2] + cm.φ[1])/2 + T = typeof(cm.hZ) + npt_obj = CartesianPoint(CylindricalPoint{T}(radius_at_z(cm, zero(T)), nφ, zero(T))) + npt = _transform_into_global_coordinate_system(npt_obj, cm) + npt, normalize(normal(cm, npt))/10 + end + end end # RotZ(π) * -cm.rotation such that the normal vector points inside the cone (Convention) diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl index 65b982695..3f54f903c 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipticalSurface.jl @@ -6,6 +6,13 @@ n := n ls[1] end + if !haskey(plotattributes, :show_normal) || plotattributes[:show_normal] + @series begin + label := nothing + seriestype := :vector + _plt_get_start_point_for_normal(es), normalize(Plane(es).normal) * _plt_area(es) / 20 + end + end if length(ls) > 1 for i in 2:length(ls) @series begin @@ -13,10 +20,34 @@ n := n ls[i] end + @series begin + label := nothing + seriestype := :vector + _plt_get_start_point_for_normal(es), normalize(Plane(es).normal) * _plt_area(es) / 20 + end end end end +_plt_area(es::CircularArea{T}) where {T} = π*es.r^2 +_plt_area(es::PartialCircularArea{T}) where {T} = π*es.r^2 / ((es.φ[2]-es.φ[1])/2π) +_plt_area(es::Annulus{T}) where {T} = π*(es.r[2]^2 - es.r[1]^2) +_plt_area(es::PartialAnnulus{T}) where {T} = π*(es.r[2]^2 - es.r[1]^2) / ((es.φ[2]-es.φ[1])/2π) + +_plt_get_start_point_for_normal(es::CircularArea{T}) where {T} = es.origin +function _plt_get_start_point_for_normal(es::PartialCircularArea{T}) where {T} + cyl = CylindricalPoint{T}(es.r/2, (es.φ[2]+es.φ[1])/2, zero(T)) + _transform_into_global_coordinate_system(CartesianPoint(cyl), es) +end +function _plt_get_start_point_for_normal(es::Annulus{T}) where {T} + cyl = CylindricalPoint{T}((es.r[2]+es.r[1])/2, zero(T), zero(T)) + _transform_into_global_coordinate_system(CartesianPoint(cyl), es) +end +function _plt_get_start_point_for_normal(es::PartialAnnulus{T}) where {T} + cyl = CylindricalPoint{T}((es.r[2]+es.r[1])/2, (es.φ[2]+es.φ[1])/2, zero(T)) + _transform_into_global_coordinate_system(CartesianPoint(cyl), es) +end + # function get_plot_points(a::CylindricalAnnulus{T}; n = 30) where {T <: AbstractFloat} # plot_points = Vector{CartesianPoint{T}}[] diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/Polygon.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/Polygon.jl index f926bf259..54d7494ad 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/Polygon.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/Polygon.jl @@ -1,4 +1,4 @@ -@recipe function f(p::Polygon; normallength = 0) +@recipe function f(p::Polygon) linecolor --> :black @series begin label --> "Polygon" @@ -7,14 +7,15 @@ z = map(p -> p[3], [p.points..., p.points[1]]) x, y, z end - if normallength > 0 + if !haskey(plotattributes, :show_normal) || plotattributes[:show_normal] @series begin - label --> "Normal" + label := nothing seriestype := :vector - mean(p.points), Plane(p).normal * normallength + mean(p.points), Plane(p).normal / 5 end end end +! \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl index a6f18d7da..b71edd290 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl @@ -6,13 +6,13 @@ include("ConeMantle.jl") linecolor --> :black @series begin label --> "Faces" - show_normal --> false + show_normal --> true vp[1] end if length(vp) > 1 for p in vp[2:end] @series begin - show_normal --> false + show_normal --> true label := nothing p end From 4538d174f5689de540e3c8b1e4bf5d6ca926227e Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 21 Jun 2021 11:25:04 +0200 Subject: [PATCH 174/241] Bugfix in coordinate transformation of `Line` --- src/ConstructiveSolidGeometry/LinePrimitives/Line.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl index be25afdf9..c6b3679e6 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl @@ -7,6 +7,6 @@ distance(pt::CartesianPoint, l::Line) = norm((pt - l.origin) × l.direction) / n function _transform_into_object_coordinate_system(l::Line{T}, p::AbstractPrimitive) where {T} origin = _transform_into_object_coordinate_system(l.origin, p) - direction = _transform_into_object_coordinate_system(CartesianPoint(l.direction), p) + direction = rotation(p) * l.direction Line( origin, CartesianVector(direction) ) end \ No newline at end of file From 4d1d7cfcdc079edb99164628addd0dda68ce5674 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 21 Jun 2021 11:26:13 +0200 Subject: [PATCH 175/241] Add full support for certain `Cone`-versions IVC test detectors works now on cartesian & cylindrical grid again. --- src/ConstructiveSolidGeometry/IO.jl | 34 ++- src/ConstructiveSolidGeometry/Intervals.jl | 6 +- .../SurfacePrimitives/ConeMantle.jl | 142 +++++----- .../VolumePrimitives/Cone.jl | 268 +++++++++++++----- 4 files changed, 309 insertions(+), 141 deletions(-) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 72ff7f09a..bc1a20d94 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -73,7 +73,7 @@ end function _parse_linear_interval(::Type{T}, dict::AbstractDict, unit::Unitful.Units) where {T} @assert haskey(dict, "from") && haskey(dict, "to") "Please specify 'from' and 'to' in $(dict)." From::T, To::T = _parse_interval_from_to(T, dict, unit) - To == -From ? To : From..To + To == -From == zero(T) ? To : From..To # if != 0 is influences the origin end @@ -100,12 +100,40 @@ function parse_r_of_primitive(::Type{T}, dict::AbstractDict, unit::Unitful.Units bottom = _parse_radial_interval(T, dictr["bottom"], unit) top = _parse_radial_interval(T, dictr["top"], unit) # bottom and top need to be same type for Cone - typeof(bottom) == typeof(top) ? (bottom, top) : _extend_number_to_zero_interval.((bottom, top)) + # typeof(bottom) == typeof(top) ? (bottom, top) : _extend_number_to_zero_interval.((bottom, top)) + bottom, top else - # "r" : {"from": ..., "to": ...} + # "r" : {"from": ... , "to": ...} _parse_radial_interval(T, dictr, unit) end end +# converts "r" to the respective AbstractFloat/Interval/Tuple for Cone +function parse_r_of_primitive(::Type{T}, dict::AbstractDict, unit::Unitful.Units, ::Type{Cone}) where {T} + @assert haskey(dict, "r") "Please specify 'r'." + dictr = dict["r"] + r_bot, r_top = if haskey(dictr, "bottom") && haskey(dictr, "top") + # "r" : {"bottom": {"from": ..., "to": ...}, "top": {"from": ..., "to": ...}} + bottom = _parse_radial_interval(T, dictr["bottom"], unit) + top = _parse_radial_interval(T, dictr["top"], unit) + # bottom and top need to be same type for Cone + # typeof(bottom) == typeof(top) ? (bottom, top) : _extend_number_to_zero_interval.((bottom, top)) + bottom, top + else + # "r" : {"from": ... , "to": ...} + r = _parse_radial_interval(T, dictr, unit) + (r, r) + end + # Not all cases implemented yet + if r_bot[1] == r_top[1] == zero(T) + if r_bot[2] == r_bot[1] + r_bot[2] + else + r_bot[2], r_top[2] + end + else + r_bot, r_top + end +end # converts "phi" : {...} to the respective Nothing/Interval # if no φ is given, then a full 360° interval (i.e. φ = nothing) is assumed diff --git a/src/ConstructiveSolidGeometry/Intervals.jl b/src/ConstructiveSolidGeometry/Intervals.jl index 85dd71c18..7d239368f 100644 --- a/src/ConstructiveSolidGeometry/Intervals.jl +++ b/src/ConstructiveSolidGeometry/Intervals.jl @@ -23,7 +23,11 @@ @inline _in_angular_interval_closed(α::Real, α_int::Nothing, tol::Real = 0) = true @inline _in_angular_interval_closed(α::Real, α_int::AbstractInterval{T}, tol::Real = 0) where {T} = mod(α - (α_int.left-tol), T(2π)) ≤ (α_int.right+tol) - (α_int.left-tol) -@inline _in_angular_interval_closed(α::T, α_int::Tuple{T,T}) where {T} = mod(α - α_int[1], T(2π)) ≤ (α_int[2] - α_int[1]) +@inline function _in_angular_interval_closed(α::T, α_int::Tuple{T,T}) where {T} + m = mod(α - α_int[1], T(2π)) + d = (α_int[2] - α_int[1]) + m ≤ d || m ≈ d +end @inline _in_angular_interval_open(α::T, α_int::Tuple{T,T}) where {T} = 0 < mod(α - α_int[1], T(2π)) < (α_int[2] - α_int[1]) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index b9db44611..5c53b11cf 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -1,5 +1,5 @@ """ - struct ConeMantle{T,RT,TP} <: AbstractSurfacePrimitive{T} + struct ConeMantle{T,RT,TP,D} <: AbstractSurfacePrimitive{T} T: Type of values, e.g. Float64 @@ -15,9 +15,9 @@ T: Type of values, e.g. Float64 * ... * `zH::T`: half hight/length of the cone mantle -* `axis::Line{T}`: The axis of the Cone mantle. Going from the bottom center point to the top center point. +* `D`: `:inwards` or `:outwards`: Whethe the normal points inside or outside """ -@with_kw struct ConeMantle{T,RT,TP} <: AbstractCurvedSurfacePrimitive{T} +@with_kw struct ConeMantle{T,RT,TP,D} <: AbstractCurvedSurfacePrimitive{T} r::RT = 1 φ::TP = nothing hZ::T = 1 # maybe we don't need this. I will leave it for now... @@ -27,50 +27,52 @@ T: Type of values, e.g. Float64 rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end +radius_at_z(hZ::T, rBot::T, rTop::T, z::T) where {T} = iszero(hZ) ? rBot : rBot + (hZ+z)*(rTop - rBot)/(2hZ) +radius_at_z(cm::ConeMantle{T,T}, z::T) where {T} = cm.r +radius_at_z(cm::ConeMantle{T,Tuple{T,T}}, z::T) where {T} = radius_at_z(cm.hZ, cm.r[1], cm.r[2], z) -const CylinderMantle{T} = ConeMantle{T,T,Nothing} -const PartialCylinderMantle{T} = ConeMantle{T,T,Tuple{T,T}} +function normal(cm::ConeMantle{T,T}, pt::CartesianPoint{T}) where {T} + pto = _transform_into_object_coordinate_system(pt, cm) + cyl = CylindricalPoint(pto) + return CartesianVector(_transform_into_global_coordinate_system( + CartesianPoint(CylindricalPoint{T}(cyl.r, cyl.φ, zero(T))), cm)) +end +function normal(cm::ConeMantle{T,Tuple{T,T},<:Any,:inwards}, pt::CartesianPoint{T}) where {T} + pto = _transform_into_object_coordinate_system(pt, cm) + cyl = CylindricalPoint(pto) + Δr = cm.r[2] - cm.r[1] + z = cyl.r * Δr / 2cm.hZ + return CartesianVector(_transform_into_global_coordinate_system( + CartesianPoint(CylindricalPoint{T}(-cyl.r, cyl.φ, z)), cm)) +end +function normal(cm::ConeMantle{T,Tuple{T,T},<:Any,:outwards}, pt::CartesianPoint{T}) where {T} + pto = _transform_into_object_coordinate_system(pt, cm) + cyl = CylindricalPoint(pto) + Δr = -(cm.r[2] - cm.r[1]) + z = cyl.r * Δr / 2cm.hZ + return CartesianVector(_transform_into_global_coordinate_system( + CartesianPoint(CylindricalPoint{T}( cyl.r, cyl.φ, z)), cm)) +end -const FullConeMantle{T} = ConeMantle{T,Tuple{T,T},Nothing} # ugly name but works for now, should just be `ConeMantle`... -const PartialConeMantle{T} = ConeMantle{T,Tuple{T,T},Tuple{T,T}} +const FullConeMantle{T,D} = ConeMantle{T,Tuple{T,T},Nothing,D} # ugly name but works for now, should just be `ConeMantle`... +const PartialConeMantle{T,D} = ConeMantle{T,Tuple{T,T},Tuple{T,T},D} -extremum(cm::CylinderMantle{T}) where {T} = sqrt(cm.hZ^2 + cm.r^2) -extremum(cm::PartialCylinderMantle{T}) where {T} = sqrt(cm.hZ^2 + cm.r^2) -extremum(cm::FullConeMantle{T}) where {T} = sqrt(cm.hZ^2 + max(es.r[1], es.r[2])^2) -extremum(cm::PartialConeMantle{T}) where {T} = sqrt(cm.hZ^2 + max(es.r[1], es.r[2])^2) +extremum(cm::FullConeMantle{T}) where {T} = sqrt(cm.hZ^2 + max(cm.r[1], cm.r[2])^2) +extremum(cm::PartialConeMantle{T}) where {T} = sqrt(cm.hZ^2 + max(cm.r[1], cm.r[2])^2) + -function lines(sp::CylinderMantle{T}) where {T} - bot_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), sp.hZ), sp) - bot_ellipse = Circle{T}(r = sp.r, φ = sp.φ, origin = bot_origin, rotation = sp.rotation) - top_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -sp.hZ), sp) - top_ellipse = Circle{T}(r = sp.r, φ = sp.φ, origin = top_origin, rotation = sp.rotation) - bot_ellipse, top_ellipse -end -function lines(sp::PartialCylinderMantle{T}) where {T} - bot_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), sp.hZ), sp) - bot_ellipse = PartialCircle{T}(r = sp.r, φ = sp.φ, origin = bot_origin, rotation = sp.rotation) - top_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -sp.hZ), sp) - top_ellipse = PartialCircle{T}(r = sp.r, φ = sp.φ, origin = top_origin, rotation = sp.rotation) - p_bot_l = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r, sp.φ[1], -sp.hZ)), sp) - p_bot_r = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r, sp.φ[2], -sp.hZ)), sp) - p_top_l = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r, sp.φ[1], sp.hZ)), sp) - p_top_r = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r, sp.φ[2], sp.hZ)), sp) - edge_l = Edge{T}(p_bot_l, p_top_l) - edge_r = Edge{T}(p_bot_r, p_top_r) - bot_ellipse, top_ellipse, edge_l, edge_r -end function lines(sp::FullConeMantle{T}) where {T} - bot_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T),zero(T), sp.hZ), sp) + bot_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T),zero(T), -sp.hZ), sp) bot_ellipse = Circle{T}(r = sp.r[1], φ = sp.φ, origin = bot_origin, rotation = sp.rotation) - top_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T),zero(T),-sp.hZ), sp) + top_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T),zero(T), +sp.hZ), sp) top_ellipse = Circle{T}(r = sp.r[2], φ = sp.φ, origin = top_origin, rotation = sp.rotation) bot_ellipse, top_ellipse end function lines(sp::PartialConeMantle{T}) where {T} - bot_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), sp.hZ), sp) + bot_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -sp.hZ), sp) bot_ellipse = PartialCircle{T}(r = sp.r[1], φ = sp.φ, origin = bot_origin, rotation = sp.rotation) - top_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -sp.hZ), sp) + top_origin = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +sp.hZ), sp) top_ellipse = PartialCircle{T}(r = sp.r[2], φ = sp.φ, origin = top_origin, rotation = sp.rotation) p_bot_l = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r[1], sp.φ[1], -sp.hZ)), sp) p_bot_r = _transform_into_global_coordinate_system(CartesianPoint(CylindricalPoint{T}(sp.r[1], sp.φ[2], -sp.hZ)), sp) @@ -132,45 +134,45 @@ function intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} _transform_into_global_coordinate_system(ints2, cm) end -""" - intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} +# """ +# intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} -The function will always return 2 CartesianPoint's. -If the line just touches the mantle, the two points will be the same. -If the line does not touch the mantle at all, the two points will have NaN's as there coordinates. -""" -function intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} - obj_l = _transform_into_object_coordinate_system(l, cm) # direction is not normalized +# The function will always return 2 CartesianPoint's. +# If the line just touches the mantle, the two points will be the same. +# If the line does not touch the mantle at all, the two points will have NaN's as there coordinates. +# """ +# function intersection(cm::ConeMantle{T,T}, l::Line{T}) where {T} +# obj_l = _transform_into_object_coordinate_system(l, cm) # direction is not normalized - L1 = obj_l.origin.x - L2 = obj_l.origin.y - L3 = obj_l.origin.z - D1 = obj_l.direction.x - D2 = obj_l.direction.y - D3 = obj_l.direction.z - - f1 = D1^2 + D2^2 - λ = inv(f1) # f1 is only 0 if obj_l is parallel to the axis of the cone - # (here eZ -> D1 = D2 = 0) - # We assume here that this is not the case -> - # We check this in choosing the sample / evaluating dimensions in `paint!` - hZ = cm.hZ - R0 = cm.r - - term1 = (2D1*L1 + 2D2*L2)^2 - term2 = L1^2 + L2^2 - R0^2 - term3 = -D1*L1 - D2*L2 - term4 = term1 - 4*f1*term2 - sq::T = term4 < 0 ? T(NaN) : sqrt(term1 - 4*f1*term2) # if this +# L1 = obj_l.origin.x +# L2 = obj_l.origin.y +# L3 = obj_l.origin.z +# D1 = obj_l.direction.x +# D2 = obj_l.direction.y +# D3 = obj_l.direction.z + +# f1 = D1^2 + D2^2 +# λ = inv(f1) # f1 is only 0 if obj_l is parallel to the axis of the cone +# # (here eZ -> D1 = D2 = 0) +# # We assume here that this is not the case -> +# # We check this in choosing the sample / evaluating dimensions in `paint!` +# hZ = cm.hZ +# R0 = cm.r + +# term1 = (2D1*L1 + 2D2*L2)^2 +# term2 = L1^2 + L2^2 - R0^2 +# term3 = -D1*L1 - D2*L2 +# term4 = term1 - 4*f1*term2 +# sq::T = term4 < 0 ? T(NaN) : sqrt(term1 - 4*f1*term2) # if this - λ1 = λ * (-sq/2 + term3) - λ2 = λ * (+sq/2 + term3) +# λ1 = λ * (-sq/2 + term3) +# λ2 = λ * (+sq/2 + term3) - ints1 = obj_l.origin + λ1 * obj_l.direction - ints2 = obj_l.origin + λ2 * obj_l.direction - return _transform_into_global_coordinate_system(ints1, cm), - _transform_into_global_coordinate_system(ints2, cm) -end +# ints1 = obj_l.origin + λ1 * obj_l.direction +# ints2 = obj_l.origin + λ2 * obj_l.direction +# return _transform_into_global_coordinate_system(ints1, cm), +# _transform_into_global_coordinate_system(ints2, cm) +# end # function get_2d_grid_ticks_and_proj(cm::ConeMantle{T}, t) where {T} diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index e4dc8b753..b9cb4d533 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -48,7 +48,68 @@ ___| const Cylinder{T,CO} = Cone{T,CO,T,Nothing} # Full in φ const PartialCylinder{T,CO} = Cone{T,CO,T,Tuple{T,T}} +### Cylinder +function _in(pt::CartesianPoint, c::Cylinder{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || az ≈ c.hZ) && begin + r = hypot(pt.x, pt.y) + r <= c.r || r ≈ c.r + end +end +function _in(pt::CartesianPoint, c::Cylinder{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + hypot(pt.x, pt.y) < c.r +end + +function surfaces(t::Cylinder{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}((t.r, t.r), t.φ, t.hZ, t.origin, t.rotation) + e_bot = CircularArea{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + e_top = CircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + # normals of the surfaces show inside the volume primitives. + e_top, e_bot, mantle +end + +### PartialCylinder + +function _in(pt::CartesianPoint, c::PartialCylinder{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || az ≈ c.hZ) && begin + r = hypot(pt.x, pt.y) + r <= c.r || r ≈ c.r + end && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) +end +function _in(pt::CartesianPoint, c::PartialCylinder{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + hypot(pt.x, pt.y) < c.r && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +end + +function surfaces(t::PartialCylinder{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + mantle = PartialConeMantle{T,:inwards}((t.r, t.r), t.φ, t.hZ, t.origin, t.rotation) + e_bot = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + e_top = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], -t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r, t.φ[1], +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r, t.φ[1], -t.hZ)) )), t) + poly_r = _transform_into_global_coordinate_system(Quadrangle{T}(( + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r, t.φ[2], -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r, t.φ[2], +t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], +t.hZ)) )), t) + # normals of the surfaces show inside the volume primitives. + (e_top, e_bot, mantle, poly_l, poly_r) +end + +#################################################################### +#################################################################### #= ___ @@ -60,7 +121,68 @@ _____\ const VaryingCylinder{T,CO} = Cone{T,CO,Tuple{T,T},Nothing} # Full in φ const PartialVaryingCylinder{T,CO} = Cone{T,CO,Tuple{T,T},Tuple{T,T}} +function _in(pt::CartesianPoint, c::VaryingCylinder{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || az ≈ c.hZ) && begin + r = hypot(pt.x, pt.y) + rz = radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) + r <= rz || r ≈ rz + end +end +function _in(pt::CartesianPoint, c::VaryingCylinder{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) +end + +function surfaces(t::VaryingCylinder{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}((t.r[1], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) + e_bot = CircularArea{T}(r = t.r[1], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + e_top = CircularArea{T}(r = t.r[2], φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + # normals of the surfaces show inside the volume primitives. + e_top, e_bot, mantle +end +function _in(pt::CartesianPoint, c::PartialVaryingCylinder{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || az ≈ c.hZ) && begin + r = hypot(pt.x, pt.y) + rz = radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) + r <= rz || r ≈ rz + end && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) +end +function _in(pt::CartesianPoint, c::PartialVaryingCylinder{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +end + +function surfaces(t::PartialVaryingCylinder{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}((t.r[1], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) + e_bot = PartialCircularArea{T}(r = t.r[1], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + e_top = PartialCircularArea{T}(r = t.r[2], φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], -t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[2], t.φ[1], +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[1], t.φ[1], -t.hZ)) )), t) + poly_r = _transform_into_global_coordinate_system(Quadrangle{T}(( + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[1], t.φ[2], -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[2], t.φ[2], +t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], +t.hZ)) )), t) + # normals of the surfaces show inside the volume primitives. + e_top, e_bot, mantle, poly_l, poly_r +end + + + +#################################################################### +#################################################################### #= ___ @@ -71,7 +193,74 @@ const PartialVaryingCylinder{T,CO} = Cone{T,CO,Tuple{T,T},Tuple{T,T}} const VaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Nothing} # Full in φ const PartialVaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Tuple{T,T}} +#(r_bot_in = r[1][1], r_bot_out = r[1][2], r_top_in = r[2][1], r_top_out = r[2][2]) + +function _in(pt::CartesianPoint, c::VaryingTube{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || az ≈ c.hZ) && begin + r = hypot(pt.x, pt.y) + r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) + r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) + (r_in <= r || r_in ≈ r) && + (r <= r_out || r ≈ r_out) + end +end +function _in(pt::CartesianPoint, c::VaryingTube{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) +end +function surfaces(t::VaryingTube{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + inner_mantle = ConeMantle{T,Tuple{T,T},Nothing,:outwards}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}( (t.r[1][2], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) + e_bot = Annulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + e_top = Annulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + # normals of the surfaces show inside the volume primitives. + e_top, e_bot, inner_mantle, outer_mantle +end + +function _in(pt::CartesianPoint, c::PartialVaryingTube{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || az ≈ c.hZ) && begin + r = hypot(pt.x, pt.y) + r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) + r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) + (r_in <= r || r_in ≈ r) && + (r <= r_out || r ≈ r_out) + end && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +end +function _in(pt::CartesianPoint, c::PartialVaryingTube{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +end + +function surfaces(t::PartialVaryingTube{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + inner_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:outwards}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}( (t.r[1][2], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) + e_bot = PartialAnnulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + e_top = PartialAnnulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( + CartesianPoint(CylindricalPoint{T}(t.r[1][1], t.φ[1], -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][1], t.φ[1], +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ[1], +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ[1], -t.hZ)) )), t) + poly_r = _transform_into_global_coordinate_system(Quadrangle{T}(( + CartesianPoint(CylindricalPoint{T}(t.r[1][1], t.φ[2], -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ[2], -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ[2], +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][1], t.φ[2], +t.hZ)) )), t) + # normals of the surfaces show inside the volume primitives. + e_top, e_bot, inner_mantle, outer_mantle, poly_l, poly_r +end + +#################################################################### +#################################################################### #= @@ -85,6 +274,9 @@ const PartialUpwardCone{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Nothing},Tuple{T,T}} +#################################################################### +#################################################################### + #= ___ / @@ -97,6 +289,10 @@ const PartialDownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Tuple{T,T} + +#################################################################### +#################################################################### + #= /\ @@ -109,6 +305,10 @@ const PartialTopClosedTube{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Tuple{T,T + +#################################################################### +#################################################################### + #= ______ @@ -129,7 +329,7 @@ const PartialBottomClosedTube{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Tuple{ function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::NamedTuple, transformations::Transformations{T}) where {T} length_unit = input_units.length angle_unit = input_units.angle - r = parse_r_of_primitive(T, dict, length_unit) + r = parse_r_of_primitive(T, dict, length_unit, Cone) φ = parse_φ_of_primitive(T, dict, angle_unit) hZ = parse_height_of_primitive(T, dict, length_unit) cone = Cone{T, ClosedPrimitive, typeof(r), typeof(φ)}(r = r, φ = φ, hZ = hZ) @@ -137,78 +337,12 @@ function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::Nam end # Cylinder -function _in(pt::CartesianPoint, c::Cylinder{T,ClosedPrimitive}) where {T} - abs(pt.z) <= c.hZ && - hypot(pt.x, pt.y) <= c.r -end -function _in(pt::CartesianPoint, c::Cylinder{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - hypot(pt.x, pt.y) < c.r -end -function surfaces(t::Cylinder{T}) where {T} - bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) - top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) - mantle = ConeMantle{T,Tuple{T,T},Nothing}((t.r, t.r), t.φ, t.hZ, t.origin, t.rotation) - e_bot = CircularArea{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) - e_top = CircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) - # normals of the surfaces show inside the volume primitives. - e_top, e_bot, mantle -end # PartialCylinder -# function _in(pt::CartesianPoint, c::PartialCylinder{T,ClosedPrimitive}) where {T} -# abs(pt.z) <= c.hZ && -# hypot(pt.x, pt.y) <= c.r && -# _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) -# end -# function _in(pt::CartesianPoint, c::PartialCylinder{T,OpenPrimitive}) where {T} -# abs(pt.z) < c.hZ && -# hypot(pt.x, pt.y) < c.r && -# _in_angular_interval_open(atan(pt.y, pt.x), c.φ) -# end - -# function surfaces(t::PartialCylinder{T}) where {T} -# bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) -# top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) -# mantle = PartialConeMantle{T}((t.r, t.r), t.φ, t.hZ, t.origin, t.rotation) -# e_bot = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) -# e_top = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) -# poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( -# CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), -t.hZ)), -# CartesianPoint(CylindricalPoint{T}( t.r, t.φ[1], -t.hZ)), -# CartesianPoint(CylindricalPoint{T}( t.r, t.φ[1], +t.hZ)), -# CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), +t.hZ)) )), t) -# poly_r = _transform_into_global_coordinate_system(Quadrangle{T}(( -# CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), -t.hZ)), -# CartesianPoint(CylindricalPoint{T}(zero(T), zero(T), +t.hZ)), -# CartesianPoint(CylindricalPoint{T}( t.r, t.φ[2], +t.hZ)), -# CartesianPoint(CylindricalPoint{T}( t.r, t.φ[2], -t.hZ)) )), t) -# # normals of the surfaces show inside the volume primitives. -# (e_top, e_bot, mantle, poly_l, poly_r) -# end -# VaryingCylinder -# radius_at_z(hZ::T, rBot::T, rTop::T, z::T) where {T} = rBot + (rTop - rBot) * z / 2hZ -# function _in(pt::CartesianPoint, c::VaryingCylinder{T,ClosedPrimitive}) where {T} -# abs(pt.z) <= c.hZ && -# hypot(pt.x, pt.y) <= radius_at_z(c.hZ, c.r[2][1], c.r[2][2], pt.z) -# end -# function _in(pt::CartesianPoint, c::VaryingCylinder{T,OpenPrimitive}) where {T} -# abs(pt.z) < c.hZ && -# hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[2][1], c.r[2][2], pt.z) -# end -# function surfaces(t::VaryingCylinder{T}) where {T} -# bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) -# top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) -# mantle = ConeMantle{T,Tuple{T,T},Nothing}((t.r[2][1], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) -# e_bot = CircularArea{T}(r = t.r[2][1], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) -# e_top = CircularArea{T}(r = t.r[2][2], φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) -# # normals of the surfaces show inside the volume primitives. -# e_top, e_bot, mantle -# end From 49deddb87863bc5d5f18d94feb086daafd2e4ee0 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 21 Jun 2021 11:33:58 +0200 Subject: [PATCH 176/241] Use IVC detector in tests again --- test/runtests.jl | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index d88cc7ce6..9491d055b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -13,17 +13,17 @@ T = Float32 # end @testset "Test real detectors" begin -# @testset "Simulate example detector: Inverted Coax" begin -# sim = Simulation{T}(SSD_examples[:InvertedCoax]) -# simulate!(sim, max_refinements = 1, verbose = true) -# evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 40e-3 )])) -# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) -# signalsum = T(0) -# for i in 1:length(evt.waveforms) -# signalsum += abs(evt.waveforms[i].value[end]) -# end -# @test isapprox( signalsum, T(2), atol = 5e-4 ) -# end + @testset "Simulate example detector: Inverted Coax" begin + sim = Simulation{T}(SSD_examples[:InvertedCoax]) + simulate!(sim, max_refinements = 1, verbose = true) + evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 40e-3 )])) + simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) + signalsum = T(0) + for i in 1:length(evt.waveforms) + signalsum += abs(evt.waveforms[i].value[end]) + end + @test isapprox( signalsum, T(2), atol = 1e-3 ) + end # @testset "Simulate example detector: Inverted Coax (in cryostat)" begin # sim = Simulation{T}(SSD_examples[:InvertedCoaxInCryostat]) # simulate!(sim, max_refinements = 1, verbose = true) @@ -78,7 +78,6 @@ T = Float32 for i in 1:length(evt.waveforms) signalsum += abs(evt.waveforms[i].value[end]) end - signalsum @test isapprox( signalsum, T(2), atol = 5e-2 ) end # #= From d2590ef64fab0e8043b4c35721a23f52802f6802 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 21 Jun 2021 13:13:08 +0200 Subject: [PATCH 177/241] Add function `csg_isapprox` for precision settings (1nm) in the CSG. We can play with this setting. --- src/ConstructiveSolidGeometry/GeometryRounding.jl | 2 ++ src/ConstructiveSolidGeometry/LinePrimitives/Line.jl | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/GeometryRounding.jl b/src/ConstructiveSolidGeometry/GeometryRounding.jl index 0964470e6..7a618d60c 100644 --- a/src/ConstructiveSolidGeometry/GeometryRounding.jl +++ b/src/ConstructiveSolidGeometry/GeometryRounding.jl @@ -20,3 +20,5 @@ end function geom_round(pt::CartesianPoint{T})::CartesianPoint{T} where {T <: Real} return CartesianPoint{T}( geom_round(pt.x), geom_round(pt.y), geom_round(pt.z) ) end + +csg_isapprox(x::T, y::T) where {T} = abs(x - y) < T(1e-9) # nm resolution \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl index c6b3679e6..eecfb4369 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Line.jl @@ -7,6 +7,6 @@ distance(pt::CartesianPoint, l::Line) = norm((pt - l.origin) × l.direction) / n function _transform_into_object_coordinate_system(l::Line{T}, p::AbstractPrimitive) where {T} origin = _transform_into_object_coordinate_system(l.origin, p) - direction = rotation(p) * l.direction + direction = inv(rotation(p)) * l.direction Line( origin, CartesianVector(direction) ) end \ No newline at end of file From 93e52456caa94e7a912f568692a4cbb5168f9444 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 21 Jun 2021 13:14:07 +0200 Subject: [PATCH 178/241] Fix in `intersection` of `ConeMantle` and `Line` for rotated objects --- src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index 5c53b11cf..a0f1c5ef3 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -122,8 +122,10 @@ function intersection(cm::ConeMantle{T,Tuple{T,T}}, l::Line{T}) where {T} term2 = -hZ^2*S^2 - 2hZ*L3*S^2 - 2hZ*R0*S + L1^2 + L2^2 - L3^2*S^2 - 2L3*R0*S - R0^2 term3 = -D1*L1 - D2*L2 + D3*hZ*S^2 + D3*L3*S^2 + D3*R0*S term4 = term1 - 4*f1*term2 - sq::T = term4 < 0 ? T(NaN) : sqrt(term4) + # sq::T = term4 < 0 ? T(NaN) : sqrt(term4) + sq::T = sqrt(abs(term4)) + # @show term4 λ1 = λ * (-sq/2 + term3) λ2 = λ * (+sq/2 + term3) λ1, λ2 From 629b363bf273607cde3508a649000b400a7acffa Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 21 Jun 2021 13:15:17 +0200 Subject: [PATCH 179/241] Use `csg_isapprox` in `_in`-methods --- src/ConstructiveSolidGeometry/Intervals.jl | 2 +- .../VolumePrimitives/Box.jl | 6 +-- .../VolumePrimitives/Cone.jl | 48 +++++++++---------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/ConstructiveSolidGeometry/Intervals.jl b/src/ConstructiveSolidGeometry/Intervals.jl index 7d239368f..ba15f3423 100644 --- a/src/ConstructiveSolidGeometry/Intervals.jl +++ b/src/ConstructiveSolidGeometry/Intervals.jl @@ -26,7 +26,7 @@ @inline function _in_angular_interval_closed(α::T, α_int::Tuple{T,T}) where {T} m = mod(α - α_int[1], T(2π)) d = (α_int[2] - α_int[1]) - m ≤ d || m ≈ d + m ≤ d || csg_isapprox(m, d) # we might want to add r into this here. end @inline _in_angular_interval_open(α::T, α_int::Tuple{T,T}) where {T} = 0 < mod(α - α_int[1], T(2π)) < (α_int[2] - α_int[1]) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 22e7fa527..094663cff 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -18,9 +18,9 @@ Box{T, CO}( b::Box{T, CO}; COT = CO, Box{T, COT}(b.hX, b.hY, b.hZ, origin, rotation) _in(pt::CartesianPoint, b::Box{<:Any, ClosedPrimitive}) = - (abs(pt.x) <= b.hX || abs(pt.x) ≈ b.hX) && - (abs(pt.y) <= b.hY || abs(pt.y) ≈ b.hY) && - (abs(pt.z) <= b.hZ || abs(pt.z) ≈ b.hZ) + (abs(pt.x) <= b.hX || csg_isapprox(pt.x, b.hX)) && + (abs(pt.y) <= b.hY || csg_isapprox(pt.y, b.hY)) && + (abs(pt.z) <= b.hZ || csg_isapprox(pt.z, b.hZ)) _in(pt::CartesianPoint, b::Box{<:Any, OpenPrimitive}) = abs(pt.x) < b.hX && abs(pt.y) < b.hY && abs(pt.z) < b.hZ diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index b9cb4d533..15e7ca9af 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -52,9 +52,9 @@ const PartialCylinder{T,CO} = Cone{T,CO,T,Tuple{T,T}} function _in(pt::CartesianPoint, c::Cylinder{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || az ≈ c.hZ) && begin + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin r = hypot(pt.x, pt.y) - r <= c.r || r ≈ c.r + r <= c.r || csg_isapprox(r, c.r) end end function _in(pt::CartesianPoint, c::Cylinder{T,OpenPrimitive}) where {T} @@ -67,7 +67,7 @@ function surfaces(t::Cylinder{T}) where {T} top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}((t.r, t.r), t.φ, t.hZ, t.origin, t.rotation) e_bot = CircularArea{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) - e_top = CircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + e_top = CircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) # normals of the surfaces show inside the volume primitives. e_top, e_bot, mantle end @@ -76,9 +76,9 @@ end function _in(pt::CartesianPoint, c::PartialCylinder{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || az ≈ c.hZ) && begin + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin r = hypot(pt.x, pt.y) - r <= c.r || r ≈ c.r + r <= c.r || csg_isapprox(r, c.r) end && _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) end @@ -93,7 +93,7 @@ function surfaces(t::PartialCylinder{T}) where {T} top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) mantle = PartialConeMantle{T,:inwards}((t.r, t.r), t.φ, t.hZ, t.origin, t.rotation) e_bot = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) - e_top = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + e_top = PartialCircularArea{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], -t.hZ)), CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], +t.hZ)), @@ -123,10 +123,10 @@ const PartialVaryingCylinder{T,CO} = Cone{T,CO,Tuple{T,T},Tuple{T,T}} function _in(pt::CartesianPoint, c::VaryingCylinder{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || az ≈ c.hZ) && begin + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin r = hypot(pt.x, pt.y) rz = radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) - r <= rz || r ≈ rz + r <= rz || csg_isapprox(r, rz) end end function _in(pt::CartesianPoint, c::VaryingCylinder{T,OpenPrimitive}) where {T} @@ -139,17 +139,17 @@ function surfaces(t::VaryingCylinder{T}) where {T} top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}((t.r[1], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) e_bot = CircularArea{T}(r = t.r[1], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) - e_top = CircularArea{T}(r = t.r[2], φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + e_top = CircularArea{T}(r = t.r[2], φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) # normals of the surfaces show inside the volume primitives. e_top, e_bot, mantle end function _in(pt::CartesianPoint, c::PartialVaryingCylinder{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || az ≈ c.hZ) && begin + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin r = hypot(pt.x, pt.y) rz = radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) - r <= rz || r ≈ rz + r <= rz || csg_isapprox(r, rz) end && _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) end @@ -164,7 +164,7 @@ function surfaces(t::PartialVaryingCylinder{T}) where {T} top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}((t.r[1], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) e_bot = PartialCircularArea{T}(r = t.r[1], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) - e_top = PartialCircularArea{T}(r = t.r[2], φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + e_top = PartialCircularArea{T}(r = t.r[2], φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], -t.hZ)), CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], +t.hZ)), @@ -197,12 +197,12 @@ const PartialVaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Tuple{T, function _in(pt::CartesianPoint, c::VaryingTube{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || az ≈ c.hZ) && begin + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) - (r_in <= r || r_in ≈ r) && - (r <= r_out || r ≈ r_out) + (r_in <= r || csg_isapprox(r_in, r)) && + (r <= r_out || csg_isapprox(r, r_out)) end end function _in(pt::CartesianPoint, c::VaryingTube{T,OpenPrimitive}) where {T} @@ -216,19 +216,19 @@ function surfaces(t::VaryingTube{T}) where {T} inner_mantle = ConeMantle{T,Tuple{T,T},Nothing,:outwards}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) outer_mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}( (t.r[1][2], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) e_bot = Annulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) - e_top = Annulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + e_top = Annulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) # normals of the surfaces show inside the volume primitives. e_top, e_bot, inner_mantle, outer_mantle end function _in(pt::CartesianPoint, c::PartialVaryingTube{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || az ≈ c.hZ) && begin + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) - (r_in <= r || r_in ≈ r) && - (r <= r_out || r ≈ r_out) + (r_in <= r || csg_isapprox(r_in, r)) && + (r <= r_out || csg_isapprox(r, r_out)) end && _in_angular_interval_open(atan(pt.y, pt.x), c.φ) end @@ -244,7 +244,7 @@ function surfaces(t::PartialVaryingTube{T}) where {T} inner_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:outwards}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) outer_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}( (t.r[1][2], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) e_bot = PartialAnnulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) - e_top = PartialAnnulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) + e_top = PartialAnnulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( CartesianPoint(CylindricalPoint{T}(t.r[1][1], t.φ[1], -t.hZ)), CartesianPoint(CylindricalPoint{T}(t.r[2][1], t.φ[1], +t.hZ)), @@ -362,7 +362,7 @@ end # inner_mantle = ConeMantle{T}((t.r[1], t.r[1]), t.φ, t.hZ, t.origin, t.rotation) # outer_mantle = ConeMantle{T}((t.r[2], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) # e_bot = Annulus{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) -# e_top = Annulus{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) +# e_top = Annulus{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) # # normals of the surfaces show inside the volume primitives. # e_top, e_bot, inner_mantle, outer_mantle # end @@ -385,7 +385,7 @@ end # inner_mantle = PartialConeMantle{T}((t.r[1], t.r[1]), t.φ, t.hZ, t.origin, t.rotation) # outer_mantle = PartialConeMantle{T}((t.r[2], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) # e_bot = PartialAnnulus{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) -# e_top = PartialAnnulus{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) +# e_top = PartialAnnulus{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) # poly_l = _transform_into_global_coordinate_system(Quadrangle{T}(( # CartesianPoint(CylindricalPoint{T}( t.r[1], t.φ[1], -t.hZ)), # CartesianPoint(CylindricalPoint{T}( t.r[2], t.φ[1], -t.hZ)), @@ -416,7 +416,7 @@ end # inner_mantle = CylinderMantle{T}(t.r[1], t.φ, t.hZ, t.origin, t.rotation) # outer_mantle = CylinderMantle{T}(t.r[2], t.φ, t.hZ, t.origin, t.rotation) # e_bot = Annulus{T}(r = t.r, φ = t.φ, origin = bot_center_pt, rotation = t.rotation) -# e_top = Annulus{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) +# e_top = Annulus{T}(r = t.r, φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) # # normals of the surfaces show inside the volume primitives. # e_top, e_bot, inner_mantle, outer_mantle # end @@ -428,7 +428,7 @@ end # in_mantle = ConeMantle{T,Tuple{T,T},Nothing}((t.r[1][1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) # out_mantle = ConeMantle{T,Tuple{T,T},Nothing}((t.r[1][2], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) # e_bot = EllipticalSurface{T,Tuple{T,T},Nothing}(r = t.r[1], φ = nothing, origin = bot_center_pt, rotation = t.rotation) -# e_top = EllipticalSurface{T,Tuple{T,T},Nothing}(r = t.r[2], φ = nothing, origin = top_center_pt, rotation = RotZ{T}(π) * -t.rotation) +# e_top = EllipticalSurface{T,Tuple{T,T},Nothing}(r = t.r[2], φ = nothing, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) # # normals of the surfaces show inside the volume primitives. # e_top, e_bot, in_mantle, out_mantle # end From cc0206ffc30d85ed54b415bdca80d7b03f961347 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 21 Jun 2021 14:27:59 +0200 Subject: [PATCH 180/241] Improve read in of Cone --- src/ConstructiveSolidGeometry/IO.jl | 35 ++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index bc1a20d94..6a82ca376 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -111,27 +111,46 @@ end function parse_r_of_primitive(::Type{T}, dict::AbstractDict, unit::Unitful.Units, ::Type{Cone}) where {T} @assert haskey(dict, "r") "Please specify 'r'." dictr = dict["r"] - r_bot, r_top = if haskey(dictr, "bottom") && haskey(dictr, "top") + r = if haskey(dictr, "bottom") && haskey(dictr, "top") # "r" : {"bottom": {"from": ..., "to": ...}, "top": {"from": ..., "to": ...}} bottom = _parse_radial_interval(T, dictr["bottom"], unit) top = _parse_radial_interval(T, dictr["top"], unit) # bottom and top need to be same type for Cone # typeof(bottom) == typeof(top) ? (bottom, top) : _extend_number_to_zero_interval.((bottom, top)) - bottom, top - else + if bottom isa Real bottom = (zero(T), bottom) end + if top isa Real top = (zero(T), top) end + (bottom, top) + elseif haskey(dictr, "from") && haskey(dictr, "to") # "r" : {"from": ... , "to": ...} r = _parse_radial_interval(T, dictr, unit) + if r isa Real r = (zero(T), r) end (r, r) + else + r = _parse_radial_interval(T, dictr, unit) + ((zero(T),r),(zero(T),r)) end # Not all cases implemented yet - if r_bot[1] == r_top[1] == zero(T) - if r_bot[2] == r_bot[1] - r_bot[2] + r_bot_in, r_bot_out, r_top_in, r_top_out = r[1][1], r[1][2], r[2][1], r[2][2] + if r_bot_in == r_top_in == zero(T) + if r_bot_out == r_top_out + return r_bot_out # Cylinder + else + return (r_bot_out, r_top_out) # VaryingCylinder + end + elseif r_top_in == r_top_out && r_bot_in != r_bot_out + if r_top_in == 0 + return ((r_bot_in, r_bot_out), nothing) + else + return ((r_bot_in, r_bot_out), r_top_in) + end + elseif r_top_in != r_top_out && r_bot_in == r_bot_out + if r_bot_in == 0 + return (nothing, (r_top_in, r_top_out)) else - r_bot[2], r_top[2] + return (r_bot_in, (r_top_in, r_top_out)) end else - r_bot, r_top + r # VaryingTube end end From c69ac16b606261e09863d8b224d07b59da3b4b9c Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 21 Jun 2021 17:44:59 +0200 Subject: [PATCH 181/241] Add `_in` & `surfaces` methods for remaining `Cone` types --- .../VolumePrimitives/Cone.jl | 243 +++++++++++++++++- 1 file changed, 235 insertions(+), 8 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 15e7ca9af..f7854f39f 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -230,7 +230,7 @@ function _in(pt::CartesianPoint, c::PartialVaryingTube{T,ClosedPrimitive}) where (r_in <= r || csg_isapprox(r_in, r)) && (r <= r_out || csg_isapprox(r, r_out)) end && - _in_angular_interval_open(atan(pt.y, pt.x), c.φ) + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) end function _in(pt::CartesianPoint, c::PartialVaryingTube{T,OpenPrimitive}) where {T} abs(pt.z) < c.hZ && @@ -269,9 +269,60 @@ end __\ =# -const UpwardCone{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Nothing},Nothing} # Full in φ -const PartialUpwardCone{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Nothing},Tuple{T,T}} +const UpwardCone{T,CO} = Cone{T,CO,Tuple{Tuple{Nothing,T},Nothing},Nothing} # Full in φ +const PartialUpwardCone{T,CO} = Cone{T,CO,Tuple{Tuple{Nothing,T},Nothing},Tuple{T,T}} +function _in(pt::CartesianPoint, c::UpwardCone{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + r = hypot(pt.x, pt.y) + r_out = radius_at_z(c.hZ, c.r[1][2], zero(T), pt.z) + (r <= r_out || csg_isapprox(r_out, r)) + end +end +function _in(pt::CartesianPoint, c::UpwardCone{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], zero(T), pt.z) +end + +function surfaces(t::UpwardCone{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + outer_mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}( (t.r[1][2], zero(T)), t.φ, t.hZ, t.origin, t.rotation) + e_bot = CircularArea{T}(r = t.r[1][2], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + # normals of the surfaces show inside the volume primitives. + e_bot, outer_mantle +end + +function _in(pt::CartesianPoint, c::PartialUpwardCone{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + r = hypot(pt.x, pt.y) + r_out = radius_at_z(c.hZ, c.r[1][2], zero(T), pt.z) + (r <= r_out || csg_isapprox(r_out, r)) + end && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) +end +function _in(pt::CartesianPoint, c::PartialUpwardCone{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], zero(T), pt.z) && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +end + +function surfaces(t::PartialUpwardCone{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + outer_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}( (t.r[1][2], zero(T)), t.φ, t.hZ, t.origin, t.rotation) + e_bot = PartialCircularArea{T}(r = t.r[1][2], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + poly_l = _transform_into_global_coordinate_system(Triangle{T}(( + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], -t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ[1], -t.hZ)) )), t) + poly_r = _transform_into_global_coordinate_system(Triangle{T}(( + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ[2], -t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], +t.hZ)) )), t) + # normals of the surfaces show inside the volume primitives. + e_bot, outer_mantle, poly_l, poly_r +end #################################################################### @@ -284,9 +335,61 @@ ___ / =# -const DownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Nothing} # Full in φ -const PartialDownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Tuple{T,T}} +const DownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{Nothing,T}},Nothing} # Full in φ +const PartialDownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{Nothing,T}},Tuple{T,T}} + +function _in(pt::CartesianPoint, c::DownwardCone{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + r = hypot(pt.x, pt.y) + r_out = radius_at_z(c.hZ, zero(T), c.r[2][2], pt.z) + (r <= r_out || csg_isapprox(r_out, r)) + end +end +function _in(pt::CartesianPoint, c::DownwardCone{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + hypot(pt.x, pt.y) < radius_at_z(c.hZ, zero(T), c.r[2][2], pt.z) +end + +function surfaces(t::DownwardCone{T}) where {T} + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + outer_mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}( (zero(T), t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) + e_top = CircularArea{T}(r = t.r[2][2], φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) + # normals of the surfaces show inside the volume primitives. + e_top, outer_mantle +end + +function _in(pt::CartesianPoint, c::PartialDownwardCone{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + r = hypot(pt.x, pt.y) + r_out = radius_at_z(c.hZ, zero(T), c.r[2][2], pt.z) + (r <= r_out || csg_isapprox(r_out, r)) + end && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) +end +function _in(pt::CartesianPoint, c::PartialDownwardCone{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + hypot(pt.x, pt.y) < radius_at_z(c.hZ, zero(T), c.r[2][2], pt.z) && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +end + +function surfaces(t::PartialDownwardCone{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + outer_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}( (t.r[2][2], zero(T)), t.φ, t.hZ, t.origin, t.rotation) + e_bot = PartialCircularArea{T}(r = t.r[2][2], φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + poly_l = _transform_into_global_coordinate_system(Triangle{T}(( + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], -t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[1], +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ[1], -t.hZ)) )), t) + poly_r = _transform_into_global_coordinate_system(Triangle{T}(( + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ[2], -t.hZ)), + CartesianPoint(CylindricalPoint{T}(zero(T), t.φ[2], +t.hZ)) )), t) + # normals of the surfaces show inside the volume primitives. + e_bot, outer_mantle, poly_l, poly_r +end @@ -301,9 +404,71 @@ const PartialDownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Tuple{T,T} =# const TopClosedTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},T},Nothing} # Full in φ -const PartialTopClosedTube{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Tuple{T,T}} +const PartialTopClosedTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},T},Tuple{T,T}} +function _in(pt::CartesianPoint, c::TopClosedTube{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + r = hypot(pt.x, pt.y) + r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2], pt.z) + r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2], pt.z) + (r_in <= r || csg_isapprox(r_in, r)) && + (r <= r_out || csg_isapprox(r, r_out)) + end +end +function _in(pt::CartesianPoint, c::TopClosedTube{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + radius_at_z(c.hZ, c.r[1][1], c.r[2], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], c.r[2], pt.z) +end + +function surfaces(t::TopClosedTube{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + # top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + inner_mantle = ConeMantle{T,Tuple{T,T},Nothing,:outwards}((t.r[1][1], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}( (t.r[1][2], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) + e_bot = Annulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + # e_top = Annulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) + # normals of the surfaces show inside the volume primitives. + e_bot, inner_mantle, outer_mantle +end + +function _in(pt::CartesianPoint, c::PartialTopClosedTube{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + r = hypot(pt.x, pt.y) + r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2], pt.z) + r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2], pt.z) + (r_in <= r || csg_isapprox(r_in, r)) && + (r <= r_out || csg_isapprox(r, r_out)) + end && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) +end +function _in(pt::CartesianPoint, c::PartialTopClosedTube{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + radius_at_z(c.hZ, c.r[1][1], c.r[2], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], c.r[2], pt.z) && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +end + +function surfaces(t::PartialTopClosedTube{T}) where {T} + bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + # top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + inner_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:outwards}((t.r[1][1], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}( (t.r[1][2], t.r[2]), t.φ, t.hZ, t.origin, t.rotation) + e_bot = PartialAnnulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + # e_top = Annulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) + poly_l = _transform_into_global_coordinate_system(Triangle{T}(( + CartesianPoint(CylindricalPoint{T}(t.r[1][1], t.φ[1], -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[2], t.φ[1], +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ[1], -t.hZ)) )), t) + poly_r = _transform_into_global_coordinate_system(Triangle{T}(( + CartesianPoint(CylindricalPoint{T}(t.r[1][1], t.φ[2], -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[1][2], t.φ[2], -t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[2], t.φ[2], +t.hZ)) )), t) + # normals of the surfaces show inside the volume primitives. + e_bot, inner_mantle, outer_mantle, poly_l, poly_r +end + #################################################################### @@ -317,10 +482,72 @@ ______ \/ =# -const BottomClosedTube{T,CO} = Cone{T,CO,Tuple{T, Tuple{T,T}},Nothing} # Full in φ -const PartialBottomClosedTube{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{T,T}},Tuple{T,T}} +const BottomClosedTube{T,CO} = Cone{T,CO,Tuple{T,Tuple{T,T}},Nothing} # Full in φ +const PartialBottomClosedTube{T,CO} = Cone{T,CO,Tuple{T,Tuple{T,T}},Tuple{T,T}} +function _in(pt::CartesianPoint, c::BottomClosedTube{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + r = hypot(pt.x, pt.y) + r_in = radius_at_z(c.hZ, c.r[1], c.r[2][1], pt.z) + r_out = radius_at_z(c.hZ, c.r[1], c.r[2][2], pt.z) + (r_in <= r || csg_isapprox(r_in, r)) && + (r <= r_out || csg_isapprox(r, r_out)) + end +end +function _in(pt::CartesianPoint, c::BottomClosedTube{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + radius_at_z(c.hZ, c.r[1], c.r[2][1], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1], c.r[2][2], pt.z) +end + +function surfaces(t::BottomClosedTube{T}) where {T} + # bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + inner_mantle = ConeMantle{T,Tuple{T,T},Nothing,:outwards}((t.r[1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = ConeMantle{T,Tuple{T,T},Nothing,:inwards}( (t.r[1], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) + # e_bot = Annulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + e_top = Annulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) + # normals of the surfaces show inside the volume primitives. + e_top, inner_mantle, outer_mantle +end + +function _in(pt::CartesianPoint, c::PartialBottomClosedTube{T,ClosedPrimitive}) where {T} + az = abs(pt.z) + (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + r = hypot(pt.x, pt.y) + r_in = radius_at_z(c.hZ, c.r[1], c.r[2][1], pt.z) + r_out = radius_at_z(c.hZ, c.r[1], c.r[2][2], pt.z) + (r_in <= r || csg_isapprox(r_in, r)) && + (r <= r_out || csg_isapprox(r, r_out)) + end && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) +end +function _in(pt::CartesianPoint, c::PartialBottomClosedTube{T,OpenPrimitive}) where {T} + abs(pt.z) < c.hZ && + radius_at_z(c.hZ, c.r[1], c.r[2][1], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1], c.r[2][2], pt.z) && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +end + +function surfaces(t::PartialBottomClosedTube{T}) where {T} + # bot_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), -t.hZ), t) + top_center_pt = _transform_into_global_coordinate_system(CartesianPoint{T}(zero(T), zero(T), +t.hZ), t) + inner_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:outwards}((t.r[1], t.r[2][1]), t.φ, t.hZ, t.origin, t.rotation) + outer_mantle = ConeMantle{T,Tuple{T,T},Tuple{T,T},:inwards}( (t.r[1], t.r[2][2]), t.φ, t.hZ, t.origin, t.rotation) + # e_bot = PartialAnnulus{T}(r = (t.r[1][1], t.r[1][2]), φ = t.φ, origin = bot_center_pt, rotation = t.rotation) + e_top = PartialAnnulus{T}(r = (t.r[2][1], t.r[2][2]), φ = t.φ, origin = top_center_pt, rotation = -t.rotation * RotZ{T}(π)) + poly_l = _transform_into_global_coordinate_system(Triangle{T}(( + CartesianPoint(CylindricalPoint{T}(t.r[2][1], t.φ[1], +t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ[1], +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[1], t.φ[1], -t.hZ)) )), t) + poly_r = _transform_into_global_coordinate_system(Triangle{T}(( + CartesianPoint(CylindricalPoint{T}(t.r[2][1], t.φ[2], +t.hZ)), + CartesianPoint(CylindricalPoint{T}( t.r[1], t.φ[2], -t.hZ)), + CartesianPoint(CylindricalPoint{T}(t.r[2][2], t.φ[2], +t.hZ)) )), t) + # normals of the surfaces show inside the volume primitives. + e_top, inner_mantle, outer_mantle, poly_l, poly_r +end + #################################################################### #################################################################### From 0f9484b40220714a6a050a364a520774acf635af Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Tue, 22 Jun 2021 10:42:41 +0200 Subject: [PATCH 182/241] Improve `csg_isapprox` --- src/ConstructiveSolidGeometry/GeometryRounding.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/GeometryRounding.jl b/src/ConstructiveSolidGeometry/GeometryRounding.jl index 7a618d60c..13ca6f1f4 100644 --- a/src/ConstructiveSolidGeometry/GeometryRounding.jl +++ b/src/ConstructiveSolidGeometry/GeometryRounding.jl @@ -21,4 +21,5 @@ function geom_round(pt::CartesianPoint{T})::CartesianPoint{T} where {T <: Real} return CartesianPoint{T}( geom_round(pt.x), geom_round(pt.y), geom_round(pt.z) ) end -csg_isapprox(x::T, y::T) where {T} = abs(x - y) < T(1e-9) # nm resolution \ No newline at end of file +csg_isapprox(x::T, y::T) where {T} = abs(x - y)/((x+y)/2) < T(1e-9) +csg_isapprox(x::Float32, y::Float32) = abs(x - y)/((x+y)/2) < 1f-7 \ No newline at end of file From 036050617b2dea453ce071b6e612f996dd0f66d2 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Tue, 22 Jun 2021 10:43:37 +0200 Subject: [PATCH 183/241] Activate both IVC detectors in tests again --- test/runtests.jl | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 9491d055b..7076cb96e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -22,30 +22,30 @@ T = Float32 for i in 1:length(evt.waveforms) signalsum += abs(evt.waveforms[i].value[end]) end - @test isapprox( signalsum, T(2), atol = 1e-3 ) + @test isapprox( signalsum, T(2), atol = 5e-4 ) end -# @testset "Simulate example detector: Inverted Coax (in cryostat)" begin -# sim = Simulation{T}(SSD_examples[:InvertedCoaxInCryostat]) -# simulate!(sim, max_refinements = 1, verbose = true) -# evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 10e-3 )])) -# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) -# signalsum = T(0) -# for i in 1:length(evt.waveforms) -# signalsum += abs(evt.waveforms[i].value[end]) -# end -# @test isapprox( signalsum, T(2), atol = 5e-4 ) -# end -# @testset "Simulate example detector: Coax" begin -# sim = Simulation{T}(SSD_examples[:Coax]) -# simulate!(sim, max_refinements = 0, verbose = true) -# evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(30), 12e-3 )])) -# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) -# signalsum = T(0) -# for i in 1:length(evt.waveforms) -# signalsum += abs(evt.waveforms[i].value[end]) -# end -# @test isapprox( signalsum, T(2), atol = 4e-3 ) -# end + @testset "Simulate example detector: Inverted Coax (in cryostat)" begin + sim = Simulation{T}(SSD_examples[:InvertedCoaxInCryostat]) + simulate!(sim, max_refinements = 1, verbose = true) + evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 10e-3 )])) + simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) + signalsum = T(0) + for i in 1:length(evt.waveforms) + signalsum += abs(evt.waveforms[i].value[end]) + end + @test isapprox( signalsum, T(2), atol = 5e-4 ) + end + # @testset "Simulate example detector: Coax" begin + # sim = Simulation{T}(SSD_examples[:Coax]) + # simulate!(sim, max_refinements = 0, verbose = true) + # evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(30), 12e-3 )])) + # simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) + # signalsum = T(0) + # for i in 1:length(evt.waveforms) + # signalsum += abs(evt.waveforms[i].value[end]) + # end + # @test isapprox( signalsum, T(2), atol = 4e-3 ) + # end # @testset "Simulate example detector: BEGe" begin # sim = Simulation{T}(SSD_examples[:BEGe]) # simulate!(sim, max_refinements = 0, verbose = true) From 21c5be87b65773f6a63aa14a142979db000f05db Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Tue, 22 Jun 2021 10:44:45 +0200 Subject: [PATCH 184/241] Disable plotting normal vectors for detectors --- src/PlotRecipes/SolidStateDetector.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PlotRecipes/SolidStateDetector.jl b/src/PlotRecipes/SolidStateDetector.jl index 6890dd039..a06209500 100644 --- a/src/PlotRecipes/SolidStateDetector.jl +++ b/src/PlotRecipes/SolidStateDetector.jl @@ -21,6 +21,7 @@ end xguide --> "x / m" yguide --> "y / m" zguide --> "z / m" + show_normal --> false @series begin det.semiconductor From de2d9ddbead55ce3324e069093699d2b597122f4 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Tue, 22 Jun 2021 10:45:26 +0200 Subject: [PATCH 185/241] Add methods for `switchClosedOpen` --- src/ConstructiveSolidGeometry/CSG.jl | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/ConstructiveSolidGeometry/CSG.jl b/src/ConstructiveSolidGeometry/CSG.jl index 99810b7ea..03a0e03b6 100644 --- a/src/ConstructiveSolidGeometry/CSG.jl +++ b/src/ConstructiveSolidGeometry/CSG.jl @@ -59,9 +59,7 @@ function (-)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractConstr ob = switchClosedOpen(b) CSGDifference{T,A,typeof(ob)}(a, ob) end -function switchClosedOpen(csg::CSGDifference) - CSGDifference(switchClosedOpen(csg.a), switchClosedOpen(csg.b)) -end + function (-)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractVolumePrimitive{T}} ob = OpenPrimitive(b) CSGDifference{T,A,typeof(ob)}(a, ob) @@ -81,4 +79,14 @@ Geometry(::Type{T}, CSG::Type{<:AbstractConstructiveGeometry}, v::Vector{Any}, i (*)(r::AbstractMatrix, csg::A) where {A <: AbstractConstructiveGeometry} = A(r * csg.a, r * csg.b) -surfaces(csg::AbstractConstructiveGeometry) = vcat(surfaces(csg.a)..., surfaces(csg.b)...) \ No newline at end of file +surfaces(csg::AbstractConstructiveGeometry) = vcat(surfaces(csg.a)..., surfaces(csg.b)...) + +function switchClosedOpen(csg::CSGDifference) + CSGDifference(switchClosedOpen(csg.a), switchClosedOpen(csg.b)) +end +function switchClosedOpen(csg::CSGUnion) + CSGDifference(switchClosedOpen(csg.a), switchClosedOpen(csg.b)) +end +function switchClosedOpen(csg::CSGIntersection) + CSGDifference(switchClosedOpen(csg.a), switchClosedOpen(csg.b)) +end \ No newline at end of file From 75210385ff64ccb57b0c6b5e02d839384e01e10a Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Tue, 22 Jun 2021 11:30:13 +0200 Subject: [PATCH 186/241] Bugfix in IO --- src/ConstructiveSolidGeometry/CSG.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ConstructiveSolidGeometry/CSG.jl b/src/ConstructiveSolidGeometry/CSG.jl index 03a0e03b6..f1877324c 100644 --- a/src/ConstructiveSolidGeometry/CSG.jl +++ b/src/ConstructiveSolidGeometry/CSG.jl @@ -72,8 +72,9 @@ end Dictionary(g::CSGDifference{T}) where {T} = OrderedDict{String,Any}("difference" => OrderedDict[Dictionary(g.a), Dictionary(g.b)]) -Geometry(::Type{T}, CSG::Type{<:AbstractConstructiveGeometry}, v::Vector{Any}, input_units::NamedTuple, transformations::Transformations{T}) where {T} = +function Geometry(::Type{T}, CSG::Type{<:AbstractConstructiveGeometry}, v::Vector{Any}, input_units::NamedTuple, transformations::Transformations{T}) where {T} Geometry(T, CSG, [g for g in v], input_units, transformations) +end (+)(csg::A, v::CartesianVector) where {A <: AbstractConstructiveGeometry} = A(csg.a + v, csg.b + v) @@ -85,8 +86,8 @@ function switchClosedOpen(csg::CSGDifference) CSGDifference(switchClosedOpen(csg.a), switchClosedOpen(csg.b)) end function switchClosedOpen(csg::CSGUnion) - CSGDifference(switchClosedOpen(csg.a), switchClosedOpen(csg.b)) + CSGUnion(switchClosedOpen(csg.a), switchClosedOpen(csg.b)) end function switchClosedOpen(csg::CSGIntersection) - CSGDifference(switchClosedOpen(csg.a), switchClosedOpen(csg.b)) + CSGIntersection(switchClosedOpen(csg.a), switchClosedOpen(csg.b)) end \ No newline at end of file From ab9fb227b039cc7d2f970568272962e64bbf4cb4 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Tue, 22 Jun 2021 14:52:58 +0200 Subject: [PATCH 187/241] Deactivate rounding of initial grid ticks --- src/Axes/DiscreteAxis.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Axes/DiscreteAxis.jl b/src/Axes/DiscreteAxis.jl index 4cb219373..14526002c 100644 --- a/src/Axes/DiscreteAxis.jl +++ b/src/Axes/DiscreteAxis.jl @@ -153,14 +153,14 @@ end function DiscreteAxis{BL, BR}(interval::Interval{L, R, T}; step::Union{Missing, T} = missing, length::Union{Missing, Int} = missing)::DiscreteAxis{T, BL, BR} where {L, R, T, BL, BR} ticks::Vector{T} = collect(range(interval, step=step, length=length)) - if T == Float32 || T == Float64 - ticks = round.(ticks, sigdigits = geom_sigdigits(T)) - for iv in eachindex(ticks) - if isapprox(ticks[iv], 0, atol = geom_atol_zero(T)) - ticks[iv] = zero(T) - end - end - end + # if T == Float32 || T == Float64 + # ticks = round.(ticks, sigdigits = geom_sigdigits(T)) + # for iv in eachindex(ticks) + # if isapprox(ticks[iv], 0, atol = geom_atol_zero(T)) + # ticks[iv] = zero(T) + # end + # end + # end DiscreteAxis{T, BL, BR}(interval, ticks) end From c56324adba397ddd0f80eaaaf0e068381bfb949f Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Tue, 22 Jun 2021 14:56:53 +0200 Subject: [PATCH 188/241] Hotfix regarding `geom_round` There occured an issue with the initial grid. This will be anyhow improved soon, after the new CSG is finished. --- src/ConstructiveSolidGeometry/GeometryRounding.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/GeometryRounding.jl b/src/ConstructiveSolidGeometry/GeometryRounding.jl index 13ca6f1f4..1be1b8c5e 100644 --- a/src/ConstructiveSolidGeometry/GeometryRounding.jl +++ b/src/ConstructiveSolidGeometry/GeometryRounding.jl @@ -1,5 +1,5 @@ geom_sigdigits(::Type{Int64})::Int = 12 -geom_sigdigits(::Type{Float32})::Int = 6 +geom_sigdigits(::Type{Float32})::Int = 5 geom_sigdigits(::Type{Float64})::Int = 12 geom_atol_zero(::Type{Int64})::Float64 = 1e-12 From 24896a18548bdd8f69e5d9a7ab9ef72d6efc5d80 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Tue, 22 Jun 2021 14:57:21 +0200 Subject: [PATCH 189/241] Adjust values to new CSG due to `OpenPrimitive` --- examples/example_config_files/public_Coax_config.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/example_config_files/public_Coax_config.json b/examples/example_config_files/public_Coax_config.json index 7aae0f8b3..b6453b137 100644 --- a/examples/example_config_files/public_Coax_config.json +++ b/examples/example_config_files/public_Coax_config.json @@ -76,7 +76,7 @@ "from": 0.0, "to": 360.0 }, - "h": 70.0 + "h": 72.0 }, "z": 35.0 } @@ -92,7 +92,7 @@ "from": 0.0, "to": 360.0 }, - "h": 5.0 + "h": 6.0 }, "z": 2.5 } @@ -108,7 +108,7 @@ "from": 0.0, "to": 360.0 }, - "h": 5.0 + "h": 6.0 }, "z": 67.5 } From 83573f985652978c333b36d0e026b95ee7ea6c34 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Tue, 22 Jun 2021 16:04:34 +0200 Subject: [PATCH 190/241] Fix in `_in` for `Box` regarding `csg_isapprox` --- src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 094663cff..9b4e2a547 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -17,10 +17,11 @@ Box{T, CO}( b::Box{T, CO}; COT = CO, rotation::SMatrix{3,3,T,9} = b.rotation) where {T, CO<:Union{ClosedPrimitive, OpenPrimitive}} = Box{T, COT}(b.hX, b.hY, b.hZ, origin, rotation) -_in(pt::CartesianPoint, b::Box{<:Any, ClosedPrimitive}) = - (abs(pt.x) <= b.hX || csg_isapprox(pt.x, b.hX)) && - (abs(pt.y) <= b.hY || csg_isapprox(pt.y, b.hY)) && - (abs(pt.z) <= b.hZ || csg_isapprox(pt.z, b.hZ)) +function _in(pt::CartesianPoint, b::Box{<:Any, ClosedPrimitive}) + (abs(pt.x) <= b.hX || csg_isapprox(abs(pt.x), b.hX)) && + (abs(pt.y) <= b.hY || csg_isapprox(abs(pt.y), b.hY)) && + (abs(pt.z) <= b.hZ || csg_isapprox(abs(pt.z), b.hZ)) +end _in(pt::CartesianPoint, b::Box{<:Any, OpenPrimitive}) = abs(pt.x) < b.hX && abs(pt.y) < b.hY && abs(pt.z) < b.hZ From 8e47c9bfb82479fadfc1024185779158638097dd Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Tue, 22 Jun 2021 16:05:20 +0200 Subject: [PATCH 191/241] Change relative tolerance to `1f-6` for `Float32` in `csg_isapprox` --- src/ConstructiveSolidGeometry/GeometryRounding.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/GeometryRounding.jl b/src/ConstructiveSolidGeometry/GeometryRounding.jl index 1be1b8c5e..6418f836d 100644 --- a/src/ConstructiveSolidGeometry/GeometryRounding.jl +++ b/src/ConstructiveSolidGeometry/GeometryRounding.jl @@ -22,4 +22,4 @@ function geom_round(pt::CartesianPoint{T})::CartesianPoint{T} where {T <: Real} end csg_isapprox(x::T, y::T) where {T} = abs(x - y)/((x+y)/2) < T(1e-9) -csg_isapprox(x::Float32, y::Float32) = abs(x - y)/((x+y)/2) < 1f-7 \ No newline at end of file +csg_isapprox(x::Float32, y::Float32) = abs(x - y)/((x+y)/2) < 1f-6 \ No newline at end of file From 964db340724fb78c5bc08f594fbe5b51c988326d Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Tue, 22 Jun 2021 16:05:42 +0200 Subject: [PATCH 192/241] Activate `Coax` detector in tests again --- test/runtests.jl | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 7076cb96e..63919a86e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -22,6 +22,7 @@ T = Float32 for i in 1:length(evt.waveforms) signalsum += abs(evt.waveforms[i].value[end]) end + @info signalsum @test isapprox( signalsum, T(2), atol = 5e-4 ) end @testset "Simulate example detector: Inverted Coax (in cryostat)" begin @@ -33,19 +34,21 @@ T = Float32 for i in 1:length(evt.waveforms) signalsum += abs(evt.waveforms[i].value[end]) end + @info signalsum @test isapprox( signalsum, T(2), atol = 5e-4 ) end - # @testset "Simulate example detector: Coax" begin - # sim = Simulation{T}(SSD_examples[:Coax]) - # simulate!(sim, max_refinements = 0, verbose = true) - # evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(30), 12e-3 )])) - # simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) - # signalsum = T(0) - # for i in 1:length(evt.waveforms) - # signalsum += abs(evt.waveforms[i].value[end]) - # end - # @test isapprox( signalsum, T(2), atol = 4e-3 ) - # end + @testset "Simulate example detector: Coax" begin + sim = Simulation{T}(SSD_examples[:Coax]) + simulate!(sim, max_refinements = 0, verbose = true) + evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(30), 12e-3 )])) + simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) + signalsum = T(0) + for i in 1:length(evt.waveforms) + signalsum += abs(evt.waveforms[i].value[end]) + end + @info signalsum + @test isapprox( signalsum, T(2), atol = 4e-3 ) + end # @testset "Simulate example detector: BEGe" begin # sim = Simulation{T}(SSD_examples[:BEGe]) # simulate!(sim, max_refinements = 0, verbose = true) @@ -55,6 +58,7 @@ T = Float32 # for i in 1:length(evt.waveforms) # signalsum += abs(evt.waveforms[i].value[end]) # end +# @info signalsum # @test isapprox( signalsum, T(2), atol = 3e-3 ) # end # @testset "Simulate example detector: HexagonalPrism" begin @@ -66,6 +70,7 @@ T = Float32 # for i in 1:length(evt.waveforms) # signalsum += abs(evt.waveforms[i].value[end]) # end +# @info signalsum # @test isapprox( signalsum, T(2), atol = 5e-4 ) # end @testset "Simulate example detector: CGD" begin @@ -78,6 +83,7 @@ T = Float32 for i in 1:length(evt.waveforms) signalsum += abs(evt.waveforms[i].value[end]) end + @info signalsum @test isapprox( signalsum, T(2), atol = 5e-2 ) end # #= @@ -91,6 +97,7 @@ T = Float32 # # for i in 1:length(evt.waveforms) # # signalsum += abs(evt.waveforms[i].value[end]) # # end +# @info signalsum # # @test isapprox( signalsum, T(2), atol = 5e-4 ) # end # @testset "Simulate example detector: Toroidal" begin @@ -103,6 +110,7 @@ T = Float32 # for i in 1:length(evt.waveforms) # signalsum += abs(evt.waveforms[i].value[end]) # end +# @info signalsum # @test isapprox( signalsum, T(2), atol = 5e-4 ) # end # =# @@ -115,6 +123,7 @@ T = Float32 # for i in 1:length(evt.waveforms) # signalsum += abs(evt.waveforms[i].value[end]) # end +# @info signalsum # @test isapprox( signalsum, T(2), atol = 5e-4 ) # end end From 8a230ab1da3dc557a3ee7558205f179f69de25ae Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 10:54:51 +0200 Subject: [PATCH 193/241] Remove `geom_round` and adept rounding issues to new CSG. Also, split `csg_isapprox` into `csg_isapprox_lin` & `csg_isaprox_rad` Also, split `csg_round` into `csg_round_lin` & `csg_isaprox_rad` --- src/Axes/DiscreteAxis.jl | 3 +- src/ChargeDensities/ConstantChargeDensity.jl | 3 +- .../CylindricalChargeDensity.jl | 6 +- src/ChargeDensities/LinearChargeDensity.jl | 9 ++- src/ChargeDrift/ChargeDrift.jl | 6 +- .../GeometryRounding.jl | 29 ++------ src/ConstructiveSolidGeometry/Intervals.jl | 2 +- .../VolumePrimitives/Box.jl | 6 +- .../VolumePrimitives/Cone.jl | 68 +++++++++---------- src/GeometryRounding.jl | 22 ------ .../ConstantImpurityDensity.jl | 3 +- .../CylindricalImpurityDensity.jl | 6 +- .../LinearImpurityDensity.jl | 9 ++- src/PlotRecipes/ElectricField.jl | 6 +- src/PotentialSimulation/Painting/Painting.jl | 17 +++-- src/Simulation/Simulation.jl | 68 +++++++++++++++---- src/SolidStateDetector/DetectorGeometries.jl | 2 +- src/SolidStateDetectors.jl | 8 +-- src/World/World.jl | 15 ++-- 19 files changed, 158 insertions(+), 130 deletions(-) delete mode 100644 src/GeometryRounding.jl diff --git a/src/Axes/DiscreteAxis.jl b/src/Axes/DiscreteAxis.jl index 14526002c..7c88e9ace 100644 --- a/src/Axes/DiscreteAxis.jl +++ b/src/Axes/DiscreteAxis.jl @@ -111,7 +111,8 @@ function range(interval::Interval{:closed, :open, T}; step::Union{Missing, T} = range(interval.left, stop = stop, length=length) elseif ismissing(length) # stop = interval.right - interval.right % step - stop = geom_round(interval.right - step) + # stop = geom_round(interval.right - step) + stop = interval.right - step range(interval.left, stop = stop, step=step) else error(KeyError, ": Both keywords `step` and `length` were given. But only one is allowed.") diff --git a/src/ChargeDensities/ConstantChargeDensity.jl b/src/ChargeDensities/ConstantChargeDensity.jl index 2819aedc4..0e7fb0276 100644 --- a/src/ChargeDensities/ConstantChargeDensity.jl +++ b/src/ChargeDensities/ConstantChargeDensity.jl @@ -24,7 +24,8 @@ end function ConstantChargeDensity{T}(dict::Union{Dict{String, Any}, Dict{Any, Any}}, unit_factor::T)::ConstantChargeDensity{T} where {T <: SSDFloat} ρ::T = if haskey(dict, "charge_density") - geom_round(unit_factor * T(dict["charge_density"])) + # geom_round(unit_factor * T(dict["charge_density"])) + unit_factor * T(dict["charge_density"]) else T(0) end diff --git a/src/ChargeDensities/CylindricalChargeDensity.jl b/src/ChargeDensities/CylindricalChargeDensity.jl index 070a1e482..37ef7543a 100644 --- a/src/ChargeDensities/CylindricalChargeDensity.jl +++ b/src/ChargeDensities/CylindricalChargeDensity.jl @@ -24,8 +24,10 @@ end function CylindricalChargeDensity{T}(dict::Union{Dict{String, Any}, Dict{Any, Any}}, unit_factor::T, gradient_unit_factor::T)::CylindricalChargeDensity{T} where {T <: SSDFloat} offsets, gradients = zeros(T,3), zeros(T,3) if prod(map(k -> k in ["r","z"], collect(keys(dict)))) @warn "Only r and z are supported in the cylindrical charge density model.\nChange the charge density model in the config file or remove all other entries." end - if haskey(dict, "r") offsets[1] = geom_round(unit_factor * T(dict["r"]["init"])); gradients[1] = geom_round(gradient_unit_factor * T(dict["r"]["gradient"])) end - if haskey(dict, "z") offsets[3] = geom_round(unit_factor * T(dict["z"]["init"])); gradients[3] = geom_round(gradient_unit_factor * T(dict["z"]["gradient"])) end + # if haskey(dict, "r") offsets[1] = geom_round(unit_factor * T(dict["r"]["init"])); gradients[1] = geom_round(gradient_unit_factor * T(dict["r"]["gradient"])) end + # if haskey(dict, "z") offsets[3] = geom_round(unit_factor * T(dict["z"]["init"])); gradients[3] = geom_round(gradient_unit_factor * T(dict["z"]["gradient"])) end + if haskey(dict, "r") offsets[1] = unit_factor * T(dict["r"]["init"]); gradients[1] = gradient_unit_factor * T(dict["r"]["gradient"]) end + if haskey(dict, "z") offsets[3] = unit_factor * T(dict["z"]["init"]); gradients[3] = gradient_unit_factor * T(dict["z"]["gradient"]) end CylindricalChargeDensity{T}( NTuple{3, T}(offsets), NTuple{3, T}(gradients) ) end diff --git a/src/ChargeDensities/LinearChargeDensity.jl b/src/ChargeDensities/LinearChargeDensity.jl index b118065f2..57927306a 100644 --- a/src/ChargeDensities/LinearChargeDensity.jl +++ b/src/ChargeDensities/LinearChargeDensity.jl @@ -24,9 +24,12 @@ end function LinearChargeDensity{T}(dict::Union{Dict{String, Any}, Dict{Any, Any}}, unit_factor::T, gradient_unit_factor::T)::LinearChargeDensity{T} where {T <: SSDFloat} offsets, gradients = zeros(T,3), zeros(T,3) if prod(map(k -> k in ["x","y","z"], collect(keys(dict)))) @warn "Only x, y and z are supported in the linear charge density model.\nChange the charge density model in the config file or remove all other entries." end - if haskey(dict, "x") offsets[1] = geom_round(unit_factor * T(dict["x"]["init"])); gradients[1] = geom_round(gradient_unit_factor * T(dict["x"]["gradient"])) end - if haskey(dict, "y") offsets[2] = geom_round(unit_factor * T(dict["y"]["init"])); gradients[2] = geom_round(gradient_unit_factor * T(dict["y"]["gradient"])) end - if haskey(dict, "z") offsets[3] = geom_round(unit_factor * T(dict["z"]["init"])); gradients[3] = geom_round(gradient_unit_factor * T(dict["z"]["gradient"])) end + # if haskey(dict, "x") offsets[1] = geom_round(unit_factor * T(dict["x"]["init"])); gradients[1] = geom_round(gradient_unit_factor * T(dict["x"]["gradient"])) end + # if haskey(dict, "y") offsets[2] = geom_round(unit_factor * T(dict["y"]["init"])); gradients[2] = geom_round(gradient_unit_factor * T(dict["y"]["gradient"])) end + # if haskey(dict, "z") offsets[3] = geom_round(unit_factor * T(dict["z"]["init"])); gradients[3] = geom_round(gradient_unit_factor * T(dict["z"]["gradient"])) end + if haskey(dict, "x") offsets[1] = unit_factor * T(dict["x"]["init"]); gradients[1] = gradient_unit_factor * T(dict["x"]["gradient"]) end + if haskey(dict, "y") offsets[2] = unit_factor * T(dict["y"]["init"]); gradients[2] = gradient_unit_factor * T(dict["y"]["gradient"]) end + if haskey(dict, "z") offsets[3] = unit_factor * T(dict["z"]["init"]); gradients[3] = gradient_unit_factor * T(dict["z"]["gradient"]) end LinearChargeDensity{T}( NTuple{3, T}(offsets), NTuple{3, T}(gradients) ) end diff --git a/src/ChargeDrift/ChargeDrift.jl b/src/ChargeDrift/ChargeDrift.jl index 6445f3f78..5d55d0151 100644 --- a/src/ChargeDrift/ChargeDrift.jl +++ b/src/ChargeDrift/ChargeDrift.jl @@ -121,7 +121,8 @@ function _drift_charge!( current_pos::CartesianPoint{T} = drift_path[istep - 1] stepvector::CartesianVector{T} = get_velocity_vector(velocity_field, _convert_point(current_pos, S)) * Δt stepvector = modulate_driftvector(stepvector, current_pos, det.virtual_drift_volumes) - if geom_round.(stepvector) == null_step + # if geom_round.(stepvector) == null_step + if stepvector == null_step done = true end next_pos::CartesianPoint{T} = current_pos + stepvector @@ -159,7 +160,8 @@ function _drift_charge!( drifttime += Δt * (1 - i * T(0.001)) timestamps[istep] = drifttime last_real_step_index += 1 - if geom_round.(next_pos - current_pos) == null_step + # if geom_round.(next_pos - current_pos) == null_step + if next_pos - current_pos == null_step done = true end else # elseif cd_point_type == CD_BULK -- or -- cd_point_type == CD_OUTSIDE diff --git a/src/ConstructiveSolidGeometry/GeometryRounding.jl b/src/ConstructiveSolidGeometry/GeometryRounding.jl index 6418f836d..fb712a4b7 100644 --- a/src/ConstructiveSolidGeometry/GeometryRounding.jl +++ b/src/ConstructiveSolidGeometry/GeometryRounding.jl @@ -1,25 +1,6 @@ -geom_sigdigits(::Type{Int64})::Int = 12 -geom_sigdigits(::Type{Float32})::Int = 5 -geom_sigdigits(::Type{Float64})::Int = 12 +csg_round_lin(x::T) where {T} = round(x, sigdigits = 9) # min. Δx = 1 nm +csg_round_lin(x::Float32) where {T} = round(x, sigdigits = 5) # min. Δx = 10 μm +csg_round_rad(φ::T) where {T} = round(φ, digits = 4) # min. Δφ ≈ 0.011 ° -geom_atol_zero(::Type{Int64})::Float64 = 1e-12 -geom_atol_zero(::Type{Float32})::Float32 = 1e-6 -geom_atol_zero(::Type{Float64})::Float64 = 1e-12 - -function geom_round(v::T)::T where {T} - return isapprox(v, 0, atol = geom_atol_zero(T)) ? T(0) : round(v, sigdigits = geom_sigdigits(T)) -end -# function geom_round(cyl::CylindricalPoint{T})::CylindricalPoint{T} where T -# return Cylindrical{T}(geom_round(cyl.r),geom_round(cyl.φ),geom_round(cyl.z)) -# end - -function geom_round(pt::CylindricalPoint{T})::CylindricalPoint{T} where {T <: Real} - return CylindricalPoint{T}( geom_round(pt.r), geom_round(pt.φ), geom_round(pt.z) ) -end - -function geom_round(pt::CartesianPoint{T})::CartesianPoint{T} where {T <: Real} - return CartesianPoint{T}( geom_round(pt.x), geom_round(pt.y), geom_round(pt.z) ) -end - -csg_isapprox(x::T, y::T) where {T} = abs(x - y)/((x+y)/2) < T(1e-9) -csg_isapprox(x::Float32, y::Float32) = abs(x - y)/((x+y)/2) < 1f-6 \ No newline at end of file +csg_isapprox_lin(x::T, y::T) where {T} = csg_round_lin(x) == csg_round_lin(y) #abs(x - y) < T(1e-9) +csg_isapprox_rad(α::T, β::T) where {T} = csg_round_rad(α) == csg_round_rad(β) #abs(x - y) < T(1e-4) \ No newline at end of file diff --git a/src/ConstructiveSolidGeometry/Intervals.jl b/src/ConstructiveSolidGeometry/Intervals.jl index ba15f3423..ee70e15e7 100644 --- a/src/ConstructiveSolidGeometry/Intervals.jl +++ b/src/ConstructiveSolidGeometry/Intervals.jl @@ -26,7 +26,7 @@ @inline function _in_angular_interval_closed(α::T, α_int::Tuple{T,T}) where {T} m = mod(α - α_int[1], T(2π)) d = (α_int[2] - α_int[1]) - m ≤ d || csg_isapprox(m, d) # we might want to add r into this here. + m ≤ d || csg_isapprox_rad(m, d) # we might want to add r into this here. end @inline _in_angular_interval_open(α::T, α_int::Tuple{T,T}) where {T} = 0 < mod(α - α_int[1], T(2π)) < (α_int[2] - α_int[1]) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 9b4e2a547..74a0e0a93 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -18,9 +18,9 @@ Box{T, CO}( b::Box{T, CO}; COT = CO, Box{T, COT}(b.hX, b.hY, b.hZ, origin, rotation) function _in(pt::CartesianPoint, b::Box{<:Any, ClosedPrimitive}) - (abs(pt.x) <= b.hX || csg_isapprox(abs(pt.x), b.hX)) && - (abs(pt.y) <= b.hY || csg_isapprox(abs(pt.y), b.hY)) && - (abs(pt.z) <= b.hZ || csg_isapprox(abs(pt.z), b.hZ)) + (abs(pt.x) <= b.hX || csg_isapprox_lin(abs(pt.x), b.hX)) && + (abs(pt.y) <= b.hY || csg_isapprox_lin(abs(pt.y), b.hY)) && + (abs(pt.z) <= b.hZ || csg_isapprox_lin(abs(pt.z), b.hZ)) end _in(pt::CartesianPoint, b::Box{<:Any, OpenPrimitive}) = diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index f7854f39f..338f0c5b1 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -52,9 +52,9 @@ const PartialCylinder{T,CO} = Cone{T,CO,T,Tuple{T,T}} function _in(pt::CartesianPoint, c::Cylinder{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) - r <= c.r || csg_isapprox(r, c.r) + r <= c.r || csg_isapprox_lin(r, c.r) end end function _in(pt::CartesianPoint, c::Cylinder{T,OpenPrimitive}) where {T} @@ -76,9 +76,9 @@ end function _in(pt::CartesianPoint, c::PartialCylinder{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) - r <= c.r || csg_isapprox(r, c.r) + r <= c.r || csg_isapprox_lin(r, c.r) end && _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) end @@ -123,10 +123,10 @@ const PartialVaryingCylinder{T,CO} = Cone{T,CO,Tuple{T,T},Tuple{T,T}} function _in(pt::CartesianPoint, c::VaryingCylinder{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) rz = radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) - r <= rz || csg_isapprox(r, rz) + r <= rz || csg_isapprox_lin(r, rz) end end function _in(pt::CartesianPoint, c::VaryingCylinder{T,OpenPrimitive}) where {T} @@ -146,10 +146,10 @@ end function _in(pt::CartesianPoint, c::PartialVaryingCylinder{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) rz = radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) - r <= rz || csg_isapprox(r, rz) + r <= rz || csg_isapprox_lin(r, rz) end && _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) end @@ -197,12 +197,12 @@ const PartialVaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Tuple{T, function _in(pt::CartesianPoint, c::VaryingTube{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) - (r_in <= r || csg_isapprox(r_in, r)) && - (r <= r_out || csg_isapprox(r, r_out)) + (r_in <= r || csg_isapprox_lin(r_in, r)) && + (r <= r_out || csg_isapprox_lin(r, r_out)) end end function _in(pt::CartesianPoint, c::VaryingTube{T,OpenPrimitive}) where {T} @@ -223,12 +223,12 @@ end function _in(pt::CartesianPoint, c::PartialVaryingTube{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) - (r_in <= r || csg_isapprox(r_in, r)) && - (r <= r_out || csg_isapprox(r, r_out)) + (r_in <= r || csg_isapprox_lin(r_in, r)) && + (r <= r_out || csg_isapprox_lin(r, r_out)) end && _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) end @@ -274,10 +274,10 @@ const PartialUpwardCone{T,CO} = Cone{T,CO,Tuple{Tuple{Nothing,T},Nothing},Tuple{ function _in(pt::CartesianPoint, c::UpwardCone{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) r_out = radius_at_z(c.hZ, c.r[1][2], zero(T), pt.z) - (r <= r_out || csg_isapprox(r_out, r)) + (r <= r_out || csg_isapprox_lin(r_out, r)) end end function _in(pt::CartesianPoint, c::UpwardCone{T,OpenPrimitive}) where {T} @@ -295,10 +295,10 @@ end function _in(pt::CartesianPoint, c::PartialUpwardCone{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) r_out = radius_at_z(c.hZ, c.r[1][2], zero(T), pt.z) - (r <= r_out || csg_isapprox(r_out, r)) + (r <= r_out || csg_isapprox_lin(r_out, r)) end && _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) end @@ -341,10 +341,10 @@ const PartialDownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{Nothing,T}},Tupl function _in(pt::CartesianPoint, c::DownwardCone{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) r_out = radius_at_z(c.hZ, zero(T), c.r[2][2], pt.z) - (r <= r_out || csg_isapprox(r_out, r)) + (r <= r_out || csg_isapprox_lin(r_out, r)) end end function _in(pt::CartesianPoint, c::DownwardCone{T,OpenPrimitive}) where {T} @@ -362,10 +362,10 @@ end function _in(pt::CartesianPoint, c::PartialDownwardCone{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) r_out = radius_at_z(c.hZ, zero(T), c.r[2][2], pt.z) - (r <= r_out || csg_isapprox(r_out, r)) + (r <= r_out || csg_isapprox_lin(r_out, r)) end && _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) end @@ -409,12 +409,12 @@ const PartialTopClosedTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},T},Tuple{T,T}} function _in(pt::CartesianPoint, c::TopClosedTube{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2], pt.z) r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2], pt.z) - (r_in <= r || csg_isapprox(r_in, r)) && - (r <= r_out || csg_isapprox(r, r_out)) + (r_in <= r || csg_isapprox_lin(r_in, r)) && + (r <= r_out || csg_isapprox_lin(r, r_out)) end end function _in(pt::CartesianPoint, c::TopClosedTube{T,OpenPrimitive}) where {T} @@ -435,12 +435,12 @@ end function _in(pt::CartesianPoint, c::PartialTopClosedTube{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2], pt.z) r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2], pt.z) - (r_in <= r || csg_isapprox(r_in, r)) && - (r <= r_out || csg_isapprox(r, r_out)) + (r_in <= r || csg_isapprox_lin(r_in, r)) && + (r <= r_out || csg_isapprox_lin(r, r_out)) end && _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) end @@ -488,12 +488,12 @@ const PartialBottomClosedTube{T,CO} = Cone{T,CO,Tuple{T,Tuple{T,T}},Tuple{T,T}} function _in(pt::CartesianPoint, c::BottomClosedTube{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1], c.r[2][1], pt.z) r_out = radius_at_z(c.hZ, c.r[1], c.r[2][2], pt.z) - (r_in <= r || csg_isapprox(r_in, r)) && - (r <= r_out || csg_isapprox(r, r_out)) + (r_in <= r || csg_isapprox_lin(r_in, r)) && + (r <= r_out || csg_isapprox_lin(r, r_out)) end end function _in(pt::CartesianPoint, c::BottomClosedTube{T,OpenPrimitive}) where {T} @@ -514,12 +514,12 @@ end function _in(pt::CartesianPoint, c::PartialBottomClosedTube{T,ClosedPrimitive}) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox(az, c.hZ)) && begin + (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1], c.r[2][1], pt.z) r_out = radius_at_z(c.hZ, c.r[1], c.r[2][2], pt.z) - (r_in <= r || csg_isapprox(r_in, r)) && - (r <= r_out || csg_isapprox(r, r_out)) + (r_in <= r || csg_isapprox_lin(r_in, r)) && + (r <= r_out || csg_isapprox_lin(r, r_out)) end && _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) end diff --git a/src/GeometryRounding.jl b/src/GeometryRounding.jl deleted file mode 100644 index 8c3ba3bfc..000000000 --- a/src/GeometryRounding.jl +++ /dev/null @@ -1,22 +0,0 @@ -geom_sigdigits(::Type{Int64})::Int = 12 -geom_sigdigits(::Type{Float32})::Int = 6 -geom_sigdigits(::Type{Float64})::Int = 12 - -geom_atol_zero(::Type{Int64})::Float64 = 1e-12 -geom_atol_zero(::Type{Float32})::Float32 = 1e-9 -geom_atol_zero(::Type{Float64})::Float64 = 1e-12 - -function geom_round(v::T)::T where {T} - return isapprox(v, 0, atol = geom_atol_zero(T)) ? T(0) : round(v, sigdigits = geom_sigdigits(T)) -end -# function geom_round(cyl::CylindricalPoint{T})::CylindricalPoint{T} where T -# return Cylindrical{T}(geom_round(cyl.r),geom_round(cyl.φ),geom_round(cyl.z)) -# end - -function geom_round(pt::CylindricalPoint{T})::CylindricalPoint{T} where {T <: SSDFloat} - return CylindricalPoint{T}( geom_round(pt.r), geom_round(pt.φ), geom_round(pt.z) ) -end - -function geom_round(pt::CartesianPoint{T})::CartesianPoint{T} where {T <: SSDFloat} - return CartesianPoint{T}( geom_round(pt.x), geom_round(pt.y), geom_round(pt.z) ) -end diff --git a/src/ImpurityDensities/ConstantImpurityDensity.jl b/src/ImpurityDensities/ConstantImpurityDensity.jl index 14be9d7fb..a1997f80f 100644 --- a/src/ImpurityDensities/ConstantImpurityDensity.jl +++ b/src/ImpurityDensities/ConstantImpurityDensity.jl @@ -24,7 +24,8 @@ end function ConstantImpurityDensity{T}(dict::Union{Dict{String, Any}, Dict{Any, Any}}, unit_factor::T)::ConstantImpurityDensity{T} where {T <: SSDFloat} ρ::T = if haskey(dict, "Impurity_density") - geom_round(unit_factor * T(dict["Impurity_density"])) + # geom_round(unit_factor * T(dict["Impurity_density"])) + unit_factor * T(dict["Impurity_density"]) else T(0) end diff --git a/src/ImpurityDensities/CylindricalImpurityDensity.jl b/src/ImpurityDensities/CylindricalImpurityDensity.jl index 6938b953d..636f012a9 100644 --- a/src/ImpurityDensities/CylindricalImpurityDensity.jl +++ b/src/ImpurityDensities/CylindricalImpurityDensity.jl @@ -24,8 +24,10 @@ end function CylindricalImpurityDensity{T}(dict::Union{Dict{String, Any}, Dict{Any, Any}}, unit_factor::T, gradient_unit_factor::T)::CylindricalImpurityDensity{T} where {T <: SSDFloat} offsets, gradients = zeros(T,3), zeros(T,3) if prod(map(k -> k in ["r","z"], collect(keys(dict)))) @warn "Only r and z are supported in the cylindrical Impurity density model.\nChange the Impurity density model in the config file or remove all other entries." end - if haskey(dict, "r") offsets[1] = geom_round(unit_factor * T(dict["r"]["init"])); gradients[1] = geom_round(gradient_unit_factor * T(dict["r"]["gradient"])) end - if haskey(dict, "z") offsets[3] = geom_round(unit_factor * T(dict["z"]["init"])); gradients[3] = geom_round(gradient_unit_factor * T(dict["z"]["gradient"])) end + # if haskey(dict, "r") offsets[1] = geom_round(unit_factor * T(dict["r"]["init"])); gradients[1] = geom_round(gradient_unit_factor * T(dict["r"]["gradient"])) end + # if haskey(dict, "z") offsets[3] = geom_round(unit_factor * T(dict["z"]["init"])); gradients[3] = geom_round(gradient_unit_factor * T(dict["z"]["gradient"])) end + if haskey(dict, "r") offsets[1] = unit_factor * T(dict["r"]["init"]); gradients[1] = gradient_unit_factor * T(dict["r"]["gradient"]) end + if haskey(dict, "z") offsets[3] = unit_factor * T(dict["z"]["init"]); gradients[3] = gradient_unit_factor * T(dict["z"]["gradient"]) end CylindricalImpurityDensity{T}( NTuple{3, T}(offsets), NTuple{3, T}(gradients) ) end diff --git a/src/ImpurityDensities/LinearImpurityDensity.jl b/src/ImpurityDensities/LinearImpurityDensity.jl index 1d9bf0744..2e0c03391 100644 --- a/src/ImpurityDensities/LinearImpurityDensity.jl +++ b/src/ImpurityDensities/LinearImpurityDensity.jl @@ -24,9 +24,12 @@ end function LinearImpurityDensity{T}(dict::Union{Dict{String, Any}, Dict{Any, Any}}, unit_factor::T, gradient_unit_factor::T)::LinearImpurityDensity{T} where {T <: SSDFloat} offsets, gradients = zeros(T,3), zeros(T,3) if prod(map(k -> k in ["x","y","z"], collect(keys(dict)))) @warn "Only x, y and z are supported in the linear Impurity density model.\nChange the Impurity density model in the config file or remove all other entries." end - if haskey(dict, "x") offsets[1] = geom_round(unit_factor * T(dict["x"]["init"])); gradients[1] = geom_round(gradient_unit_factor * T(dict["x"]["gradient"])) end - if haskey(dict, "y") offsets[2] = geom_round(unit_factor * T(dict["y"]["init"])); gradients[2] = geom_round(gradient_unit_factor * T(dict["y"]["gradient"])) end - if haskey(dict, "z") offsets[3] = geom_round(unit_factor * T(dict["z"]["init"])); gradients[3] = geom_round(gradient_unit_factor * T(dict["z"]["gradient"])) end + # if haskey(dict, "x") offsets[1] = geom_round(unit_factor * T(dict["x"]["init"])); gradients[1] = geom_round(gradient_unit_factor * T(dict["x"]["gradient"])) end + # if haskey(dict, "y") offsets[2] = geom_round(unit_factor * T(dict["y"]["init"])); gradients[2] = geom_round(gradient_unit_factor * T(dict["y"]["gradient"])) end + # if haskey(dict, "z") offsets[3] = geom_round(unit_factor * T(dict["z"]["init"])); gradients[3] = geom_round(gradient_unit_factor * T(dict["z"]["gradient"])) end + if haskey(dict, "x") offsets[1] = unit_factor * T(dict["x"]["init"]); gradients[1] = gradient_unit_factor * T(dict["x"]["gradient"]) end + if haskey(dict, "y") offsets[2] = unit_factor * T(dict["y"]["init"]); gradients[2] = gradient_unit_factor * T(dict["y"]["gradient"]) end + if haskey(dict, "z") offsets[3] = unit_factor * T(dict["z"]["init"]); gradients[3] = gradient_unit_factor * T(dict["z"]["gradient"]) end LinearImpurityDensity{T}( NTuple{3, T}(offsets), NTuple{3, T}(gradients) ) end diff --git a/src/PlotRecipes/ElectricField.jl b/src/PlotRecipes/ElectricField.jl index 7fa9b0a00..04428d891 100644 --- a/src/PlotRecipes/ElectricField.jl +++ b/src/PlotRecipes/ElectricField.jl @@ -134,8 +134,10 @@ end @info("Scaling down sampling steps by a factor of $(2^exponent). Now using sampling steps of $(sampling_vector_pool./2^exponent) m. Also scaling down offset by a factor $(2^exponent).") offset /= 2^exponent end - sample_pool = S == Cylindrical ? geom_round.(CylindricalPoint.(sample_pool)) : geom_round.(sample_pool) - sample_pool = S == Cartesian ? geom_round.(CartesianPoint.(sample_pool)) : geom_round.(sample_pool) + # sample_pool = S == Cylindrical ? geom_round.(CylindricalPoint.(sample_pool)) : geom_round.(sample_pool) + # sample_pool = S == Cartesian ? geom_round.(CartesianPoint.(sample_pool)) : geom_round.(sample_pool) + sample_pool = S == Cylindrical ? CylindricalPoint.(sample_pool) : sample_pool + sample_pool = S == Cartesian ? CartesianPoint.(sample_pool) : sample_pool sampled_planes = unique!(map(x->x[dim_number],sample_pool)) v_Xsec_plane = sampled_planes[searchsortednearest(sampled_planes,v)] if abs(v-v_Xsec_plane) > sampling_vector_pool[dim_number] continue; end diff --git a/src/PotentialSimulation/Painting/Painting.jl b/src/PotentialSimulation/Painting/Painting.jl index e8554bece..979bef3b5 100644 --- a/src/PotentialSimulation/Painting/Painting.jl +++ b/src/PotentialSimulation/Painting/Painting.jl @@ -6,12 +6,17 @@ function get_sub_ind_ranges(a::Union{ # There, we will only use t_idx_range_ax3 in the painting (for now...) pts, t = a[1], a[2] ax1, ax2, ax3 = getindex.(pts, 1), getindex.(pts, 2), getindex.(pts, 3) - ax1_min_idx = searchsortedfirst(t[1], minimum(ax1)) - 1 - ax2_min_idx = searchsortedfirst(t[2], minimum(ax2)) - 1 - ax3_min_idx = searchsortedfirst(t[3], minimum(ax3)) - 1 - ax1_max_idx = searchsortedfirst(t[1], maximum(ax1)) + 1 - ax2_max_idx = searchsortedfirst(t[2], maximum(ax2)) + 1 - ax3_max_idx = searchsortedfirst(t[3], maximum(ax3)) + 1 + # ± 2 because due to merging close ticks of an axis of a grid, + # the grid points which should "belong" to corners of a primitive + # might be a bit outside of the intervals defined by the points + # of the `extreme_points`-method. + # ± 1 might also be enough -> testing... + ax1_min_idx = searchsortedfirst(t[1], minimum(ax1)) - 2 + ax2_min_idx = searchsortedfirst(t[2], minimum(ax2)) - 2 + ax3_min_idx = searchsortedfirst(t[3], minimum(ax3)) - 2 + ax1_max_idx = searchsortedfirst(t[1], maximum(ax1)) + 2 + ax2_max_idx = searchsortedfirst(t[2], maximum(ax2)) + 2 + ax3_max_idx = searchsortedfirst(t[3], maximum(ax3)) + 2 ls = (length(t[1]), length(t[2]), length(t[3])) if ax1_min_idx < 1 ax1_min_idx = 1 end if ax2_min_idx < 1 ax2_min_idx = 1 end diff --git a/src/Simulation/Simulation.jl b/src/Simulation/Simulation.jl index 4f9934bee..9df97f6c1 100644 --- a/src/Simulation/Simulation.jl +++ b/src/Simulation/Simulation.jl @@ -214,13 +214,17 @@ function Grid( sim::Simulation{T, Cylindrical}; push!(important_r_points, sim.world.intervals[1].left) push!(important_r_points, sim.world.intervals[1].right) - important_r_points = unique!(sort!(geom_round.(important_r_points))) + important_r_points = unique!(sort!(csg_round_lin.(important_r_points))) push!(important_z_points, sim.world.intervals[3].left) push!(important_z_points, sim.world.intervals[3].right) - important_z_points = unique!(sort!(geom_round.(important_z_points))) + important_z_points = unique!(sort!(csg_round_lin.(important_z_points))) push!(important_φ_points, sim.world.intervals[2].left) push!(important_φ_points, sim.world.intervals[2].right) - important_φ_points = unique!(sort!(geom_round.(important_φ_points))) + important_φ_points = unique!(sort!(csg_round_rad.(important_φ_points))) + + important_r_points = merge_close_ticks(important_r_points) + important_φ_points = merge_close_ticks(important_φ_points, max_diff = T(1e-4)) + important_z_points = merge_close_ticks(important_z_points) # r L, R, BL, BR = get_boundary_types(sim.world.intervals[1]) @@ -231,6 +235,7 @@ function Grid( sim::Simulation{T, Cylindrical}; DiscreteAxis{BL, BR}(int_r, length = init_grid_size[1]) end rticks::Vector{T} = merge_axis_ticks_with_important_ticks(ax_r, important_r_points, atol = minimum(diff(ax_r.ticks))/4) + rticks = merge_close_ticks(rticks) ax_r = DiscreteAxis{T, BL, BR}(int_r, rticks) @@ -252,12 +257,14 @@ function Grid( sim::Simulation{T, Cylindrical}; end if length(ax_φ) > 1 φticks::Vector{T} = merge_axis_ticks_with_important_ticks(ax_φ, important_φ_points, atol = minimum(diff(ax_φ.ticks))/4) + φticks = merge_close_ticks(φticks) ax_φ = typeof(ax_φ)(int_φ, φticks) end + int_φ = ax_φ.interval + φticks = merge_close_ticks(ax_φ.ticks) if isodd(length(ax_φ)) && length(ax_φ) > 1 # must be even - int_φ = ax_φ.interval - φticks = ax_φ.ticks - push!(φticks, geom_round((φticks[end] + φticks[end-1]) * 0.5)) + imax = findmax(diff(φticks))[2] + push!(φticks, (φticks[imax] + φticks[imax+1]) / 2) sort!(φticks) ax_φ = typeof(ax_φ)(int_φ, φticks) # must be even end @@ -274,11 +281,13 @@ function Grid( sim::Simulation{T, Cylindrical}; DiscreteAxis{BL, BR}(int_z, length = init_grid_size[3]) end zticks::Vector{T} = merge_axis_ticks_with_important_ticks(ax_z, important_z_points, atol=minimum(diff(ax_z.ticks))/2) + zticks = merge_close_ticks(zticks) ax_z = typeof(ax_z)(int_z, zticks) if isodd(length(ax_z)) # must be even int_z = ax_z.interval zticks = ax_z.ticks - push!(zticks, geom_round((zticks[end] + zticks[end-1]) * 0.5)) + imax = findmax(diff(zticks))[2] + push!(zticks, (zticks[imax] + zticks[imax+1]) / 2) sort!(zticks) ax_z = typeof(ax_z)(int_z, zticks) # must be even end @@ -287,6 +296,35 @@ function Grid( sim::Simulation{T, Cylindrical}; return CylindricalGrid{T}( (ax_r, ax_φ, ax_z) ) end +function merge_closest_ticks!(v::AbstractVector{T}, n::Int = length(v); max_diff::T = T(1e-6)) where {T} + Δv = diff(v[1:n]) + Δ_min, Δv_min_indx = findmin(Δv) + vFirst = v[1] + vLast = v[n] + if Δ_min < max_diff + v[Δv_min_indx] = (v[Δv_min_indx]+v[Δv_min_indx+1]) / 2 + v[Δv_min_indx+1:end-1] = v[Δv_min_indx+2:end] + v[1] = vFirst + n -= 1 + v[n] = vLast + n + else + n + end +end +function merge_close_ticks(v::AbstractVector{T}; max_diff::T = T(1e-6)) where {T} + l = length(v) + if l == 1 return v end + n = merge_closest_ticks!(v, max_diff = max_diff) + reduced = n < l + l = n + while reduced + n = merge_closest_ticks!(v, n, max_diff = max_diff) + reduced = n < l + l = n + end + v[1:n] +end function Grid( sim::Simulation{T, Cartesian}; init_grid_size::Union{Missing, NTuple{3, Int}} = missing, @@ -314,9 +352,10 @@ function Grid( sim::Simulation{T, Cartesian}; samples::Vector{CartesianPoint{T}} = sample(sim.detector, Cartesian) - important_x_points::Vector{T} = geom_round.(map(p -> p.x, samples)) - important_y_points::Vector{T} = geom_round.(map(p -> p.y, samples)) - important_z_points::Vector{T} = geom_round.(map(p -> p.z, samples)) + important_x_points::Vector{T} = merge_close_ticks(sort(unique(map(p -> p.x, samples)))) + important_y_points::Vector{T} = merge_close_ticks(sort(unique(map(p -> p.y, samples)))) + important_z_points::Vector{T} = merge_close_ticks(sort(unique(map(p -> p.z, samples)))) + init_grid_spacing, use_spacing::Bool = if !ismissing(init_grid_spacing) T.(init_grid_spacing), true @@ -333,10 +372,11 @@ function Grid( sim::Simulation{T, Cartesian}; DiscreteAxis{BL, BR}(int_x, length = init_grid_size[1]) end xticks::Vector{T} = merge_axis_ticks_with_important_ticks(ax_x, important_x_points, atol = minimum(diff(ax_x.ticks)) / 2) + xticks = merge_close_ticks(xticks) ax_x = typeof(ax_x)(int_x, xticks) if isodd(length(ax_x)) # RedBlack dimension must be of even length xticks = ax_x.ticks - push!(xticks, geom_round((xticks[end] + xticks[end-1]) * 0.5)) + push!(xticks, csg_round_lin((xticks[end] + xticks[end-1]) * 0.5)) sort!(xticks) ax_x = DiscreteAxis{T, BL, BR}(int_x, xticks) # must be even end @@ -351,6 +391,7 @@ function Grid( sim::Simulation{T, Cartesian}; DiscreteAxis{BL, BR}(int_y, length = init_grid_size[2]) end yticks::Vector{T} = merge_axis_ticks_with_important_ticks(ax_y, important_y_points, atol = minimum(diff(ax_y.ticks)) / 2) + yticks = merge_close_ticks(yticks) ax_y = typeof(ax_y)(int_y, yticks) # z @@ -362,6 +403,7 @@ function Grid( sim::Simulation{T, Cartesian}; DiscreteAxis{BL, BR}(int_z, length = init_grid_size[3]) end zticks::Vector{T} = merge_axis_ticks_with_important_ticks(ax_z, important_z_points, atol = minimum(diff(ax_z.ticks)) / 2) + zticks = merge_close_ticks(zticks) ax_z = typeof(ax_z)(int_z, zticks) return CartesianGrid3D{T}( (ax_x, ax_y, ax_z) ) @@ -897,12 +939,12 @@ function simulate!(sim::Simulation{T}; max_refinements::Int = 1, verbose::Bool calculate_electric_potential!( sim, max_refinements = max_refinements, verbose = verbose, - init_grid_size = (10,10,10), + init_grid_size = (20,20,20), depletion_handling = depletion_handling, convergence_limit = convergence_limit ) for contact in sim.detector.contacts calculate_weighting_potential!(sim, contact.id, max_refinements = max_refinements, - init_grid_size = (10,10,10), + init_grid_size = (20,20,20), verbose = verbose, convergence_limit = convergence_limit) end calculate_electric_field!(sim) diff --git a/src/SolidStateDetector/DetectorGeometries.jl b/src/SolidStateDetector/DetectorGeometries.jl index af43ff7a8..6adb15873 100644 --- a/src/SolidStateDetector/DetectorGeometries.jl +++ b/src/SolidStateDetector/DetectorGeometries.jl @@ -142,7 +142,7 @@ end function point_type(c::SolidStateDetector{T}, grid::Grid{T, 3}, p::CylindricalPoint{T})::Tuple{UInt8, Int, CartesianVector{T}} where {T <: SSDFloat} surface_normal::CartesianVector{T} = CartesianVector{T}(0, 0, 0) # need undef version for this for contact in c.contacts - if in(searchsortednearest(grid, geom_round(p)), contact) || in(searchsortednearest(grid, p), contact) || geom_round(p) in contact || p in contact + if in(searchsortednearest(grid, p), contact) || in(searchsortednearest(grid, p), contact) || p in contact || p in contact return CD_ELECTRODE::UInt8, contact.id, surface_normal end end diff --git a/src/SolidStateDetectors.jl b/src/SolidStateDetectors.jl index 3373117c0..d78335bba 100644 --- a/src/SolidStateDetectors.jl +++ b/src/SolidStateDetectors.jl @@ -35,11 +35,10 @@ using .ConstructiveSolidGeometry: CartesianTicksTuple, CylindricalTicksTuple, Geometry, AbstractGeometry, AbstractSurfacePrimitive, AbstractPlanarSurfacePrimitive, AbstractCurvedSurfacePrimitive, - geom_round, geom_sigdigits, geom_atol_zero, + csg_round_lin, csg_round_rad, csg_isapprox_lin, csg_isapprox_rad, parse_rotation_matrix, parse_translate_vector, parse_CSG_transformation, transform, CSG_dict, Transformations, combine_transformations - - + import .ConstructiveSolidGeometry: sample, sample_surface export CartesianPoint, CartesianVector, CylindricalPoint @@ -78,6 +77,8 @@ Base.showerror(io::IO, e::ConfigFileError) = print(io, "ConfigFileError: ", e.ms include("Units.jl") +isunique(v::AbstractVector) = length(v) == length(unique(v)) + include("Axes/DiscreteAxis.jl") include("World/World.jl") include("Grids/Grids.jl") @@ -90,7 +91,6 @@ include("ChargeDensities/ChargeDensities.jl") include("ImpurityDensities/ImpurityDensities.jl") include("ChargeDriftModels/ChargeDriftModels.jl") include("SolidStateDetector/DetectorGeometries.jl") -# include("GeometryRounding.jl") include("PotentialSimulation/PotentialSimulation.jl") diff --git a/src/World/World.jl b/src/World/World.jl index b484485d0..e3e9f586c 100644 --- a/src/World/World.jl +++ b/src/World/World.jl @@ -72,7 +72,8 @@ function get_r_SSDInterval(T, dict, input_units::NamedTuple) if isa(dict, Dict) from::T = 0 if "from" in keys(dict) @warn "ConfigFileWarning: \"from\" is not used in r-axis. It is fixed to 0." end - to::T = "to" in keys(dict) ? geom_round(ustrip(uconvert(internal_length_unit, T(dict["to"]) * input_units.length))) : throw(ConfigFileError("No \"to\" given for r-axis.")) + # to::T = "to" in keys(dict) ? geom_round(ustrip(uconvert(internal_length_unit, T(dict["to"]) * input_units.length))) : throw(ConfigFileError("No \"to\" given for r-axis.")) + to::T = "to" in keys(dict) ? ustrip(uconvert(internal_length_unit, T(dict["to"]) * input_units.length)) : throw(ConfigFileError("No \"to\" given for r-axis.")) if from < 0 throw(ConfigFileError("left boundary of r-axis cannot be negative.")) end if to < 0 throw(ConfigFileError("right boundary of r-axis cannot be negative.")) end L = :closed @@ -89,8 +90,10 @@ end function get_φ_SSDInterval(T, dict::Dict, input_units::NamedTuple) if haskey(dict, "phi") dp = dict["phi"] - from::T = "from" in keys(dp) ? geom_round(ustrip(uconvert(internal_angle_unit, T(dp["from"]) * input_units.angle))) : T(0) - to::T = "to" in keys(dp) ? geom_round(ustrip(uconvert(internal_angle_unit, T(dp["to"]) * input_units.angle))) : T(2π) + # from::T = "from" in keys(dp) ? geom_round(ustrip(uconvert(internal_angle_unit, T(dp["from"]) * input_units.angle))) : T(0) + # to::T = "to" in keys(dp) ? geom_round(ustrip(uconvert(internal_angle_unit, T(dp["to"]) * input_units.angle))) : T(2π) + from::T = "from" in keys(dp) ? ustrip(uconvert(internal_angle_unit, T(dp["from"]) * input_units.angle)) : T(0) + to::T = "to" in keys(dp) ? ustrip(uconvert(internal_angle_unit, T(dp["to"]) * input_units.angle)) : T(2π) L = :closed R = :open BL = :periodic @@ -112,8 +115,10 @@ function get_φ_SSDInterval(T, dict::Dict, input_units::NamedTuple) end function get_cartesian_SSDInterval(T, dict::Dict, input_units::NamedTuple) - from::T = "from" in keys(dict) ? geom_round(ustrip(uconvert(internal_length_unit, T(dict["from"]) * input_units.length))) : 0 - to = "to" in keys(dict) ? geom_round(ustrip(uconvert(internal_length_unit, T(dict["to"]) * input_units.length))) : throw(ConfigFileError("No \"to\" given for z-axis.")) + # from::T = "from" in keys(dict) ? geom_round(ustrip(uconvert(internal_length_unit, T(dict["from"]) * input_units.length))) : 0 + # to = "to" in keys(dict) ? geom_round(ustrip(uconvert(internal_length_unit, T(dict["to"]) * input_units.length))) : throw(ConfigFileError("No \"to\" given for z-axis.")) + from::T = "from" in keys(dict) ? ustrip(uconvert(internal_length_unit, T(dict["from"]) * input_units.length)) : 0 + to = "to" in keys(dict) ? ustrip(uconvert(internal_length_unit, T(dict["to"]) * input_units.length)) : throw(ConfigFileError("No \"to\" given for z-axis.")) L = :closed R = :closed BL, BR = :infinite, :infinite From 1dded7ffdf9b8020afcf8ca23fe6ae464db0fee2 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 10:55:21 +0200 Subject: [PATCH 194/241] Activate the `BEGe` detector in tests again --- test/runtests.jl | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 63919a86e..068ba2c88 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -49,18 +49,18 @@ T = Float32 @info signalsum @test isapprox( signalsum, T(2), atol = 4e-3 ) end -# @testset "Simulate example detector: BEGe" begin -# sim = Simulation{T}(SSD_examples[:BEGe]) -# simulate!(sim, max_refinements = 0, verbose = true) -# evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 20e-3 )])) -# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) -# signalsum = T(0) -# for i in 1:length(evt.waveforms) -# signalsum += abs(evt.waveforms[i].value[end]) -# end -# @info signalsum -# @test isapprox( signalsum, T(2), atol = 3e-3 ) -# end + @testset "Simulate example detector: BEGe" begin + sim = Simulation{T}(SSD_examples[:BEGe]) + simulate!(sim, max_refinements = 1, verbose = true) + evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 20e-3 )])) + simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) + signalsum = T(0) + for i in 1:length(evt.waveforms) + signalsum += abs(evt.waveforms[i].value[end]) + end + @info signalsum + @test isapprox( signalsum, T(2), atol = 3e-3 ) + end # @testset "Simulate example detector: HexagonalPrism" begin # sim = Simulation{T}(SSD_examples[:Hexagon]) # simulate!(sim, max_refinements = 0, verbose = true) @@ -75,7 +75,6 @@ T = Float32 # end @testset "Simulate example detector: CGD" begin sim = Simulation{T}(SSD_examples[:CGD]) - SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) simulate!(sim, max_refinements = 2, verbose = true) evt = Event([CartesianPoint{T}(5e-3,0,0)]) simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) From 0b8ef259085cdaef50ee4785f31ac3a4dbd367fc Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 11:33:08 +0200 Subject: [PATCH 195/241] Add constructors to change the impurity density of a detector --- src/SolidStateDetector/Semiconductor.jl | 6 +++++- src/SolidStateDetector/SolidStateDetector.jl | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/SolidStateDetector/Semiconductor.jl b/src/SolidStateDetector/Semiconductor.jl index 27b32ce79..a2a1b1d68 100644 --- a/src/SolidStateDetector/Semiconductor.jl +++ b/src/SolidStateDetector/Semiconductor.jl @@ -39,7 +39,6 @@ function Semiconductor{T}(dict::Dict, input_units::NamedTuple, outer_transformat return Semiconductor(temperature, material, impurity_density_model, charge_drift_model, geometry) end - function println(io::IO, d::Semiconductor{T}) where {T <: SSDFloat} println("\t---General Properties---") println("\t-Detector Material: \t $(d.material.name)") @@ -50,3 +49,8 @@ print(io::IO, d::Semiconductor{T}) where {T} = print(io, "Semiconductor{$T} - $( show(io::IO, d::Semiconductor) = print(io, d) show(io::IO,::MIME"text/plain", d::Semiconductor) = show(io, d) + + +function Semiconductor(sc::Semiconductor{T,G,MT,CDM,IDM}, cdm::AbstractImpurityDensity{T}) where {T,G,MT,CDM,IDM} + Semiconductor(sc.temperature, sc.material, cdm, sc.charge_drift_model, sc.geometry) +end \ No newline at end of file diff --git a/src/SolidStateDetector/SolidStateDetector.jl b/src/SolidStateDetector/SolidStateDetector.jl index 04e9cd337..010df111d 100644 --- a/src/SolidStateDetector/SolidStateDetector.jl +++ b/src/SolidStateDetector/SolidStateDetector.jl @@ -12,6 +12,12 @@ struct SolidStateDetector{T,SC,CT,PT,VDM} <: AbstractConfig{T} SolidStateDetector{T}(n::AbstractString,s::SC,c::C,p::P,v::VDM) where {T,SC,C,P,VDM}= new{T,SC,C,P,VDM}(n,s,c,p,v) end +function SolidStateDetector(det::SolidStateDetector{T,SC,CT,PT,VDM}, cdm::AbstractImpurityDensity{T}) where {T,SC,CT,PT,VDM} + sc = Semiconductor(det.semiconductor, cdm) + SolidStateDetector{T}( + det.name, sc, det.contacts, det.passives, det.virtual_drift_volumes + ) +end get_precision_type(::SolidStateDetector{T}) where {T} = T From f7cd6f2bdf782f05157d64e7ba32eef44d05dc62 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 11:33:45 +0200 Subject: [PATCH 196/241] Fix IO of `Cone` in case `z` is defined via `from` & `to` --- src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 338f0c5b1..9fa3d6978 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -558,8 +558,14 @@ function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::Nam angle_unit = input_units.angle r = parse_r_of_primitive(T, dict, length_unit, Cone) φ = parse_φ_of_primitive(T, dict, angle_unit) - hZ = parse_height_of_primitive(T, dict, length_unit) - cone = Cone{T, ClosedPrimitive, typeof(r), typeof(φ)}(r = r, φ = φ, hZ = hZ) + z = parse_height_of_primitive(T, dict, length_unit) + hZ = typeof(z) <: Real ? z : width(z)/2 + origin = if typeof(z) <: Real + CartesianPoint{T}(zero(T), zero(T), zero(T)) + else + CartesianPoint{T}(zero(T), zero(T), mean(z)) + end + cone = Cone{T, ClosedPrimitive, typeof(r), typeof(φ)}(r = r, φ = φ, hZ = hZ, origin = origin) return transform(cone, transformations) end From 9b351a168aa8af56a45f4f7c2a7c1ac6fac343ca Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 11:39:46 +0200 Subject: [PATCH 197/241] Activate comparison to analytic solutions in tests again --- test/comparison_to_analytic_solutions.jl | 11 ++++++----- test/runtests.jl | 6 +++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/test/comparison_to_analytic_solutions.jl b/test/comparison_to_analytic_solutions.jl index e7aba713b..8295578f5 100644 --- a/test/comparison_to_analytic_solutions.jl +++ b/test/comparison_to_analytic_solutions.jl @@ -10,7 +10,8 @@ e = SolidStateDetectors.elementary_charge * u"C" ) calculate_electric_field!(sim) BV_true = SolidStateDetectors._get_abs_bias_voltage(sim.detector) - Δd = (sim.detector.contacts[2].decomposed_surfaces[1].loc - sim.detector.contacts[1].decomposed_surfaces[1].loc) * u"m" + # Δd = (sim.detector.contacts[2].decomposed_surfaces[1].loc - sim.detector.contacts[1].decomposed_surfaces[1].loc) * u"m" + Δd = (sim.detector.contacts[2].geometry.origin[1] - sim.detector.contacts[1].geometry.origin[1]) * u"m" Δx = (sim.world.intervals[2].right - sim.world.intervals[2].left) * u"m" A = Δx * Δx V = A * Δd @@ -34,8 +35,8 @@ struct DummyImpurityDensity{T} <: SolidStateDetectors.AbstractImpurityDensity{T} sim_car = Simulation{T}(SSD_examples[:InfiniteCoaxialCapacitorCartesianCoords]) BV_true = SolidStateDetectors._get_abs_bias_voltage(sim_cyl.detector) ϵr = sim_cyl.detector.semiconductor.material.ϵ_r - R1 = sim_cyl.detector.contacts[1].geometry.r.right * u"m" - R2 = sim_cyl.detector.contacts[2].geometry.r.left * u"m" + R1 = sim_cyl.detector.contacts[1].geometry.r[1][1] * u"m" + R2 = sim_cyl.detector.contacts[2].geometry.r[1][1] * u"m" V1 = sim_cyl.detector.contacts[1].potential * u"V" V2 = sim_cyl.detector.contacts[2].potential * u"V" L = (sim_cyl.world.intervals[3].right - sim_cyl.world.intervals[3].left) * u"m" @@ -95,8 +96,8 @@ struct DummyImpurityDensity{T} <: SolidStateDetectors.AbstractImpurityDensity{T} SolidStateDetectors.get_impurity_density(cdm, CylindricalPoint(pt)) end - sim_cyl.detector.semiconductor.impurity_density_model = DummyImpurityDensity{T}() - sim_car.detector.semiconductor.impurity_density_model = DummyImpurityDensity{T}() + sim_cyl.detector = SolidStateDetector(sim_cyl.detector, DummyImpurityDensity{T}()); + sim_car.detector = SolidStateDetector(sim_car.detector, DummyImpurityDensity{T}()); calculate_electric_potential!(sim_cyl, init_grid_size = (40, 2, 2), diff --git a/test/runtests.jl b/test/runtests.jl index 068ba2c88..b5791d2fc 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,9 +8,9 @@ using Unitful T = Float32 -# @testset "Comparison to analytic solutions" begin -# include("comparison_to_analytic_solutions.jl") -# end +@testset "Comparison to analytic solutions" begin + include("comparison_to_analytic_solutions.jl") +end @testset "Test real detectors" begin @testset "Simulate example detector: Inverted Coax" begin From 2e4f7770f8cf42995017a24588c90a065f2a1597 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 13:24:46 +0200 Subject: [PATCH 198/241] Adjust RegularPrism to new CSG --- .../VolumePrimitives/RegularPrism.jl | 242 +++++++++--------- .../VolumePrimitives/VolumePrimitives.jl | 3 +- 2 files changed, 123 insertions(+), 122 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl index b21b33ddf..c5612c949 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl @@ -1,124 +1,124 @@ -struct RegularPrism{N,T,TR,TZ} <: AbstractVolumePrimitive{T} - r::TR - z::TZ - - function RegularPrism( N::Integer, - ::Type{T}, - r::Union{T, <:AbstractInterval{T}}, - z::Union{T, <:AbstractInterval{T}}) where {T} - @assert typeof(N) <: Integer && N >= 3 "Failed constructing RegularPrism with $(N) points in the polygon base (needs at least 3 points)." - new{N, T,typeof(r),typeof(z)}(r,z) - end -end - -const PrismAliases = Dict{Int, String}( - 3 => "TriangularPrism", - 4 => "SquarePrism", - 5 => "PentagonalPrism", - 6 => "HexagonalPrism" -) - -# Convenience functions -const TriangularPrism{T,TR,TZ} = RegularPrism{3,T,TR,TZ} -const SquarePrism{T,TR,TZ} = RegularPrism{4,T,TR,TZ} -const PentagonalPrism{T,TR,TZ} = RegularPrism{5,T,TR,TZ} -const HexagonalPrism{T,TR,TZ} = RegularPrism{6,T,TR,TZ} - -TriangularPrism(args...) = RegularPrism(3, args...) -SquarePrism(args...) = RegularPrism(4, args...) -PentagonalPrism(args...) = RegularPrism(5, args...) -HexagonalPrism(args...) = RegularPrism(6, args...) - -print(io::IO, rp::TriangularPrism{T, TR, TZ}) where {T,TR,TZ} = print(io, "TriangularPrism{$(T), $(TR), $(TZ)}($(rp.r), $(rp.z))") -print(io::IO, rp::SquarePrism{T, TR, TZ}) where {T,TR,TZ} = print(io, "SquarePrism{$(T), $(TR), $(TZ)}($(rp.r), $(rp.z))") -print(io::IO, rp::PentagonalPrism{T, TR, TZ}) where {T,TR,TZ} = print(io, "PentagonalPrism{$(T), $(TR), $(TZ)}($(rp.r), $(rp.z))") -print(io::IO, rp::HexagonalPrism{T, TR, TZ}) where {T,TR,TZ} = print(io, "HexagonalPrism{$(T), $(TR), $(TZ)}($(rp.r), $(rp.z))") - - -# Constructors -function RegularPrism(N::Integer; rInner = 0, rOuter = 1, zMin = -1, zMax = 1) - T = float(promote_type(typeof.((rInner, rOuter, zMin, zMax))...)) - r = rInner == 0 ? T(rOuter) : T(rInner)..T(rOuter) - z = zMax == -zMin ? T(zMax) : T(zMin)..T(zMax) - RegularPrism(N, T, r, z) -end -RegularPrism(N::Integer, rInner, rOuter, zMin, zMax) = RegularPrism(N; rInner = rInner, rOuter = rOuter, zMin = zMin, zMax = zMax) +@with_kw struct RegularPrism{T,CO,N,TR} <: AbstractVolumePrimitive{T, CO} + r::TR = 1 + hZ::T = 1 -function RegularPrism(N::Integer, rOuter::R, height::H) where {R<:Real, H<:Real} - T = float(promote_type(R,H)) - RegularPrism( N, T, T(rOuter), T(height/2)) + origin::CartesianPoint{T} = zero(CartesianPoint{T}) + rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end - -@inline in(p::CylindricalPoint, hp::RegularPrism{N, T, <:Real}) where {N,T} = begin - _in_z(p, hp.z) && p.r * cos(T(π/N) - mod(p.φ, T(2π/N))) / cos(T(π/N)) <= hp.r -end - -@inline in(p::CylindricalPoint, hp::RegularPrism{N, T, <:AbstractInterval}) where {N,T} = begin - _in_z(p, hp.z) && p.r * cos(T(π/N) - mod(p.φ, T(2π/N))) / cos(T(π/N)) in hp.r -end - -@inline in(p::CartesianPoint, hp::RegularPrism) = in(CylindricalPoint(p), hp) - -# Special case: CartesianPoint in HexagonalPrism: use analytical formulas -@inline in(p::CartesianPoint, hp::HexagonalPrism{T, <:Real}) where {T} = - _in_z(p, hp.z) && _in_y(p, hp.r * sqrt(T(3))/2) && _in_x(p, hp.r - abs(p.y)/sqrt(T(3))) - -@inline in(p::CartesianPoint, hp::HexagonalPrism{T, <:AbstractInterval{T}}) where {T} = - _in_z(p, hp.z) && abs(p.y) <= hp.r.right * sqrt(T(3))/2 && - ( - abs(p.y) >= hp.r.left * sqrt(T(3))/2 && _in_x(p, hp.r.right * T(0.5)) || - abs(p.x) in (hp.r.left - abs(p.y) /sqrt(T(3)))..(hp.r.right - abs(p.y)/sqrt(T(3))) - ) - -# read-in -function Geometry(::Type{T}, ::Type{P}, dict::AbstractDict, input_units::NamedTuple - ) where {T, P <: Union{TriangularPrism, SquarePrism, PentagonalPrism, HexagonalPrism}} - length_unit = input_units.length - r = parse_r_of_primitive(T, dict, length_unit) - z = parse_height_of_primitive(T, dict, length_unit) - return P(T, r, z) -end - -function Dictionary(rp::RegularPrism{N,T}) where {N,T} - dict = OrderedDict{String,Any}() - dict["r"] = typeof(rp.r) == T ? rp.r : OrderedDict{String,Any}("from" => rp.r.left, "to" => rp.r.right) - typeof(rp.z) == T ? dict["h"] = rp.z * 2 : dict["z"] = OrderedDict{String,Any}("from" => rp.z.left, "to" => rp.z.right) - OrderedDict{String,Any}(PrismAliases[N] => dict) -end - - - -get_r_limits(rp::RegularPrism) = (_left_radial_interval(rp.r), _right_radial_interval(rp.r)) -get_z_limits(rp::RegularPrism) = (_left_linear_interval(rp.z), _right_linear_interval(rp.z)) - -function get_decomposed_surfaces(rp::RegularPrism{N,T}) where {N, T} - rMin::T, rMax::T = get_r_limits(rp) - zMin::T, zMax::T = get_z_limits(rp) - surfaces = AbstractSurfacePrimitive[] - tol = geom_atol_zero(T) - if !isapprox(zMin, zMax, atol = tol) - if !isapprox(rMin, rMax, atol = tol) - if rMin == 0 - return AbstractSurfacePrimitive[RegularPolygon(rp, z = zMin), RegularPolygon(rp, z = zMax), RegularPrismMantle(rp, r = rMax)] - else - return AbstractSurfacePrimitive[RegularPolygon(rp, z = zMin), RegularPolygon(rp, z = zMax), RegularPrismMantle(rp, r = rMin), RegularPrismMantle(rp, r = rMax)] - end - else - return AbstractSurfacePrimitive[RegularPrismMantle(rp, r = rMin)] - end - else - return AbstractSurfacePrimitive[RegularPolygon(rp, z = zMin)] - end -end - -function sample(rp::RegularPrism{N,T}, Nsamps::NTuple{3,Int} = (2,N+1,2))::Vector{CylindricalPoint{T}} where {N,T} - rMin::T, rMax::T = get_r_limits(rp) - zMin::T, zMax::T = get_z_limits(rp) - samples = [ - CylindricalPoint{T}(r*cos(π/N)/cos(π/N - mod(φ, 2π/N)),φ,z) - for z in (Nsamps[3] ≤ 1 ? zMin : range(zMin, zMax, length = Nsamps[3])) - for φ in (Nsamps[2] ≤ 1 ? 0 : range(0, 2π, length = Nsamps[2])) - for r in (Nsamps[1] ≤ 1 ? rMax : range(rMin, rMax, length = Nsamps[1])) - ] -end +RegularPrism{T, CO, N, TR}( rp::RegularPrism{T, CO, N, TR}; COT = CO, + origin::CartesianPoint{T} = rp.origin, + rotation::SMatrix{3,3,T,9} = rp.rotation) where {T, CO<:Union{ClosedPrimitive, OpenPrimitive}, N, TR} = + RegularPrism{T, COT, N, TR}(rp.r, rp.hZ, origin, rotation) + +# const PrismAliases = Dict{Int, String}( +# 3 => "TriangularPrism", +# 4 => "SquarePrism", +# 5 => "PentagonalPrism", +# 6 => "HexagonalPrism" +# ) + +# # Convenience functions +# const TriangularPrism{T,TR,TZ} = RegularPrism{3,T,TR,TZ} +# const SquarePrism{T,TR,TZ} = RegularPrism{4,T,TR,TZ} +# const PentagonalPrism{T,TR,TZ} = RegularPrism{5,T,TR,TZ} +# const HexagonalPrism{T,TR,TZ} = RegularPrism{6,T,TR,TZ} + +# TriangularPrism(args...) = RegularPrism(3, args...) +# SquarePrism(args...) = RegularPrism(4, args...) +# PentagonalPrism(args...) = RegularPrism(5, args...) +# HexagonalPrism(args...) = RegularPrism(6, args...) + +# print(io::IO, rp::TriangularPrism{T, TR, TZ}) where {T,TR,TZ} = print(io, "TriangularPrism{$(T), $(TR), $(TZ)}($(rp.r), $(rp.z))") +# print(io::IO, rp::SquarePrism{T, TR, TZ}) where {T,TR,TZ} = print(io, "SquarePrism{$(T), $(TR), $(TZ)}($(rp.r), $(rp.z))") +# print(io::IO, rp::PentagonalPrism{T, TR, TZ}) where {T,TR,TZ} = print(io, "PentagonalPrism{$(T), $(TR), $(TZ)}($(rp.r), $(rp.z))") +# print(io::IO, rp::HexagonalPrism{T, TR, TZ}) where {T,TR,TZ} = print(io, "HexagonalPrism{$(T), $(TR), $(TZ)}($(rp.r), $(rp.z))") + + +# # Constructors +# function RegularPrism(N::Integer; rInner = 0, rOuter = 1, zMin = -1, zMax = 1) +# T = float(promote_type(typeof.((rInner, rOuter, zMin, zMax))...)) +# r = rInner == 0 ? T(rOuter) : T(rInner)..T(rOuter) +# z = zMax == -zMin ? T(zMax) : T(zMin)..T(zMax) +# RegularPrism(N, T, r, z) +# end +# RegularPrism(N::Integer, rInner, rOuter, zMin, zMax) = RegularPrism(N; rInner = rInner, rOuter = rOuter, zMin = zMin, zMax = zMax) + +# function RegularPrism(N::Integer, rOuter::R, height::H) where {R<:Real, H<:Real} +# T = float(promote_type(R,H)) +# RegularPrism( N, T, T(rOuter), T(height/2)) +# end + + +# @inline in(p::CylindricalPoint, hp::RegularPrism{N, T, <:Real}) where {N,T} = begin +# _in_z(p, hp.z) && p.r * cos(T(π/N) - mod(p.φ, T(2π/N))) / cos(T(π/N)) <= hp.r +# end + +# @inline in(p::CylindricalPoint, hp::RegularPrism{N, T, <:AbstractInterval}) where {N,T} = begin +# _in_z(p, hp.z) && p.r * cos(T(π/N) - mod(p.φ, T(2π/N))) / cos(T(π/N)) in hp.r +# end + +# @inline in(p::CartesianPoint, hp::RegularPrism) = in(CylindricalPoint(p), hp) + +# # Special case: CartesianPoint in HexagonalPrism: use analytical formulas +# @inline in(p::CartesianPoint, hp::HexagonalPrism{T, <:Real}) where {T} = +# _in_z(p, hp.z) && _in_y(p, hp.r * sqrt(T(3))/2) && _in_x(p, hp.r - abs(p.y)/sqrt(T(3))) + +# @inline in(p::CartesianPoint, hp::HexagonalPrism{T, <:AbstractInterval{T}}) where {T} = +# _in_z(p, hp.z) && abs(p.y) <= hp.r.right * sqrt(T(3))/2 && +# ( +# abs(p.y) >= hp.r.left * sqrt(T(3))/2 && _in_x(p, hp.r.right * T(0.5)) || +# abs(p.x) in (hp.r.left - abs(p.y) /sqrt(T(3)))..(hp.r.right - abs(p.y)/sqrt(T(3))) +# ) + +# # read-in +# function Geometry(::Type{T}, ::Type{P}, dict::AbstractDict, input_units::NamedTuple +# ) where {T, P <: Union{TriangularPrism, SquarePrism, PentagonalPrism, HexagonalPrism}} +# length_unit = input_units.length +# r = parse_r_of_primitive(T, dict, length_unit) +# z = parse_height_of_primitive(T, dict, length_unit) +# return P(T, r, z) +# end + +# function Dictionary(rp::RegularPrism{N,T}) where {N,T} +# dict = OrderedDict{String,Any}() +# dict["r"] = typeof(rp.r) == T ? rp.r : OrderedDict{String,Any}("from" => rp.r.left, "to" => rp.r.right) +# typeof(rp.z) == T ? dict["h"] = rp.z * 2 : dict["z"] = OrderedDict{String,Any}("from" => rp.z.left, "to" => rp.z.right) +# OrderedDict{String,Any}(PrismAliases[N] => dict) +# end + + + +# get_r_limits(rp::RegularPrism) = (_left_radial_interval(rp.r), _right_radial_interval(rp.r)) +# get_z_limits(rp::RegularPrism) = (_left_linear_interval(rp.z), _right_linear_interval(rp.z)) + +# function get_decomposed_surfaces(rp::RegularPrism{N,T}) where {N, T} +# rMin::T, rMax::T = get_r_limits(rp) +# zMin::T, zMax::T = get_z_limits(rp) +# surfaces = AbstractSurfacePrimitive[] +# tol = geom_atol_zero(T) +# if !isapprox(zMin, zMax, atol = tol) +# if !isapprox(rMin, rMax, atol = tol) +# if rMin == 0 +# return AbstractSurfacePrimitive[RegularPolygon(rp, z = zMin), RegularPolygon(rp, z = zMax), RegularPrismMantle(rp, r = rMax)] +# else +# return AbstractSurfacePrimitive[RegularPolygon(rp, z = zMin), RegularPolygon(rp, z = zMax), RegularPrismMantle(rp, r = rMin), RegularPrismMantle(rp, r = rMax)] +# end +# else +# return AbstractSurfacePrimitive[RegularPrismMantle(rp, r = rMin)] +# end +# else +# return AbstractSurfacePrimitive[RegularPolygon(rp, z = zMin)] +# end +# end + +# function sample(rp::RegularPrism{N,T}, Nsamps::NTuple{3,Int} = (2,N+1,2))::Vector{CylindricalPoint{T}} where {N,T} +# rMin::T, rMax::T = get_r_limits(rp) +# zMin::T, zMax::T = get_z_limits(rp) +# samples = [ +# CylindricalPoint{T}(r*cos(π/N)/cos(π/N - mod(φ, 2π/N)),φ,z) +# for z in (Nsamps[3] ≤ 1 ? zMin : range(zMin, zMax, length = Nsamps[3])) +# for φ in (Nsamps[2] ≤ 1 ? 0 : range(0, 2π, length = Nsamps[2])) +# for r in (Nsamps[1] ≤ 1 ? rMax : range(rMin, rMax, length = Nsamps[1])) +# ] +# end diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index 8dedc7806..a4b1ceef6 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -13,4 +13,5 @@ function sample(vp::AbstractVolumePrimitive) end include("Box.jl") -include("Cone.jl") \ No newline at end of file +include("Cone.jl") +include("RegularPrism.jl") \ No newline at end of file From 96d92788199b6d6a270a7ecdbdbe03fc2a747cbe Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 13:41:58 +0200 Subject: [PATCH 199/241] Adjust IO for RegularPrism --- src/ConstructiveSolidGeometry/IO.jl | 8 ++--- .../VolumePrimitives/RegularPrism.jl | 30 ++++++++++++++----- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 6a82ca376..eedab4c4b 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -4,10 +4,10 @@ const CSG_dict = Dict{String, Any}( # "sphere" => Sphere, "box" => Box, # "torus" => Torus, - # "TriangularPrism" => TriangularPrism, - # "SquarePrism" => SquarePrism, - # "PentagonalPrism" => PentagonalPrism, - # "HexagonalPrism" => HexagonalPrism, + "TriangularPrism" => TriangularPrism, + "QuadranglePrism" => QuadranglePrism, + "PentagonalPrism" => PentagonalPrism, + "HexagonalPrism" => HexagonalPrism, "union" => CSGUnion, "difference" => CSGDifference, "intersection" => CSGIntersection, diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl index c5612c949..87e13c576 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl @@ -10,7 +10,27 @@ RegularPrism{T, CO, N, TR}( rp::RegularPrism{T, CO, N, TR}; COT = CO, origin::CartesianPoint{T} = rp.origin, rotation::SMatrix{3,3,T,9} = rp.rotation) where {T, CO<:Union{ClosedPrimitive, OpenPrimitive}, N, TR} = RegularPrism{T, COT, N, TR}(rp.r, rp.hZ, origin, rotation) - + +const TriangularPrism{T,CO,TR} = RegularPrism{T,CO,3,TR} +const QuadranglePrism{T,CO,TR} = RegularPrism{T,CO,4,TR} +const PentagonalPrism{T,CO,TR} = RegularPrism{T,CO,5,TR} +const HexagonalPrism{T,CO,TR} = RegularPrism{T,CO,6,TR} + +function Geometry(::Type{T}, ::Type{P}, dict::AbstractDict, input_units::NamedTuple, transformations::Transformations{T} + ) where {T, P <: Union{TriangularPrism, QuadranglePrism, PentagonalPrism, HexagonalPrism}} + length_unit = input_units.length + r = parse_r_of_primitive(T, dict, length_unit) + z = parse_height_of_primitive(T, dict, length_unit) + hZ = typeof(z) <: Real ? z : width(z)/2 + origin = if typeof(z) <: Real + CartesianPoint{T}(zero(T), zero(T), zero(T)) + else + CartesianPoint{T}(zero(T), zero(T), mean(z)) + end + return P{T,ClosedPrimitive,typeof(r)}(r = r, hZ = hZ, origin = origin) +end + + # const PrismAliases = Dict{Int, String}( # 3 => "TriangularPrism", # 4 => "SquarePrism", @@ -72,13 +92,7 @@ RegularPrism{T, CO, N, TR}( rp::RegularPrism{T, CO, N, TR}; COT = CO, # ) # # read-in -# function Geometry(::Type{T}, ::Type{P}, dict::AbstractDict, input_units::NamedTuple -# ) where {T, P <: Union{TriangularPrism, SquarePrism, PentagonalPrism, HexagonalPrism}} -# length_unit = input_units.length -# r = parse_r_of_primitive(T, dict, length_unit) -# z = parse_height_of_primitive(T, dict, length_unit) -# return P(T, r, z) -# end + # function Dictionary(rp::RegularPrism{N,T}) where {N,T} # dict = OrderedDict{String,Any}() From 86edf183356a4a0357abf9a9337393ca120e0356 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 14:29:49 +0200 Subject: [PATCH 200/241] Add `vertices` and `surfaces` methods for `RegularPrism` --- .../VolumePrimitives/RegularPrism.jl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl index 87e13c576..cb44dd01e 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl @@ -30,6 +30,22 @@ function Geometry(::Type{T}, ::Type{P}, dict::AbstractDict, input_units::NamedTu return P{T,ClosedPrimitive,typeof(r)}(r = r, hZ = hZ, origin = origin) end +function vertices(rp::RegularPrism{T,<:Any,N,T}) where {T,N} + xys = SVector{6,Tuple{T,T}}([sincos(T(2π)*(n-1)/N) for n in 1:N]) + SVector{2N,CartesianPoint{T}}([CartesianPoint{T}(xy[2], xy[1], z) for z in (-rp.hZ, rp.hZ) for xy in xys]) +end + +function surfaces(rp::RegularPrism{T,<:Any,N,T}) where {T,N} + vs = vertices(rp) + p_bot = Polygon{N,T}(vs[1:N]) + p_top = Polygon{N,T}(reverse(vs[N+1:end])) + quads = Vector{Quadrangle{T}}(undef, N) + for i in 1:N-1 + quads[i] = Quadrangle{T}((vs[i], vs[N+i], vs[N+i+1], vs[i+1])) + end + quads[N] = Quadrangle{T}((vs[N], vs[2N], vs[N+1], vs[1])) + p_bot, p_top, quads... +end # const PrismAliases = Dict{Int, String}( # 3 => "TriangularPrism", From f0128b3ba4e4abe45336f3af5e78d8acd8e9fdd0 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 14:35:49 +0200 Subject: [PATCH 201/241] Add sample method for `RegularPrism` and add lazy workaround for `RegularPrism` with a "borehole" --- .../VolumePrimitives/RegularPrism.jl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl index cb44dd01e..ac942d5f1 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl @@ -27,7 +27,12 @@ function Geometry(::Type{T}, ::Type{P}, dict::AbstractDict, input_units::NamedTu else CartesianPoint{T}(zero(T), zero(T), mean(z)) end - return P{T,ClosedPrimitive,typeof(r)}(r = r, hZ = hZ, origin = origin) + if r isa Tuple # lazy workaround for now + return P{T,ClosedPrimitive,T}(r = r[2], hZ = hZ, origin = origin) - + P{T,ClosedPrimitive,T}(r = r[1], hZ = hZ, origin = origin) + else + return P{T,ClosedPrimitive,T}(r = r, hZ = hZ, origin = origin) + end end function vertices(rp::RegularPrism{T,<:Any,N,T}) where {T,N} @@ -36,7 +41,7 @@ function vertices(rp::RegularPrism{T,<:Any,N,T}) where {T,N} end function surfaces(rp::RegularPrism{T,<:Any,N,T}) where {T,N} - vs = vertices(rp) + vs = (vertices(rp)) p_bot = Polygon{N,T}(vs[1:N]) p_top = Polygon{N,T}(reverse(vs[N+1:end])) quads = Vector{Quadrangle{T}}(undef, N) @@ -47,6 +52,11 @@ function surfaces(rp::RegularPrism{T,<:Any,N,T}) where {T,N} p_bot, p_top, quads... end + +function sample(rp::RegularPrism{T,<:Any,N,T})::Vector{CartesianPoint{T}} where {T,N} + [vertices(rp)...] +end + # const PrismAliases = Dict{Int, String}( # 3 => "TriangularPrism", # 4 => "SquarePrism", From f457398924457e5412edf6b393e761a3fc385576 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 15:04:48 +0200 Subject: [PATCH 202/241] Add method for `_transform_into_global_coordinate_system` --- src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index c3251402c..2d4f337b7 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -53,6 +53,8 @@ module ConstructiveSolidGeometry rotation(p::AbstractPrimitive) = p.rotation origin(p::AbstractPrimitive) = p.origin _transform_into_global_coordinate_system(pt::CartesianPoint, p::AbstractPrimitive) = (rotation(p) * pt) + origin(p) + _transform_into_global_coordinate_system(pts::AbstractVector{<:CartesianPoint}, p::AbstractPrimitive) = + broadcast(pt -> _transform_into_global_coordinate_system(pt, p), pts) _transform_into_object_coordinate_system(pt::CartesianPoint, p::AbstractPrimitive) = inv(rotation(p)) * (pt - origin(p)) in(pt::CartesianPoint, p::AbstractPrimitive) = _in(_transform_into_object_coordinate_system(pt, p), p) in(pt::CylindricalPoint, p::AbstractPrimitive) = in(CartesianPoint(pt), p) From 7856e10d2555bce394b790351190542f84622974 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 15:05:45 +0200 Subject: [PATCH 203/241] Add `_in` methods for `RegularPrism` again + bugfixes of `RegularPrism` --- .../VolumePrimitives/RegularPrism.jl | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl index ac942d5f1..7472f0c26 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl @@ -27,17 +27,19 @@ function Geometry(::Type{T}, ::Type{P}, dict::AbstractDict, input_units::NamedTu else CartesianPoint{T}(zero(T), zero(T), mean(z)) end - if r isa Tuple # lazy workaround for now - return P{T,ClosedPrimitive,T}(r = r[2], hZ = hZ, origin = origin) - - P{T,ClosedPrimitive,T}(r = r[1], hZ = hZ, origin = origin) + g = if r isa Tuple # lazy workaround for now + P{T,ClosedPrimitive,T}(r = r[2], hZ = hZ, origin = origin) - + P{T,ClosedPrimitive,T}(r = r[1], hZ = T(1.1)*hZ, origin = origin) else - return P{T,ClosedPrimitive,T}(r = r, hZ = hZ, origin = origin) + P{T,ClosedPrimitive,T}(r = r, hZ = hZ, origin = origin) end + transform(g, transformations) end function vertices(rp::RegularPrism{T,<:Any,N,T}) where {T,N} - xys = SVector{6,Tuple{T,T}}([sincos(T(2π)*(n-1)/N) for n in 1:N]) - SVector{2N,CartesianPoint{T}}([CartesianPoint{T}(xy[2], xy[1], z) for z in (-rp.hZ, rp.hZ) for xy in xys]) + xys = [sincos(T(2π)*(n-1)/N) for n in 1:N] + pts = [CartesianPoint{T}(xy[2], xy[1], z) for z in (-rp.hZ, rp.hZ) for xy in xys] + _transform_into_global_coordinate_system(pts, rp) end function surfaces(rp::RegularPrism{T,<:Any,N,T}) where {T,N} @@ -57,6 +59,23 @@ function sample(rp::RegularPrism{T,<:Any,N,T})::Vector{CartesianPoint{T}} where [vertices(rp)...] end +function _in(pt::CartesianPoint{T}, rp::RegularPrism{T,ClosedPrimitive,N,T}) where {T,N} + (abs(pt.z) <= rp.hZ || csg_isapprox_lin(abs(pt.z), rp.hZ)) && begin + r, φ = hypot(pt.x, pt.y), atan(pt.y, pt.x) + α = T(π/N) + _r = r * cos(α - mod(φ, 2α)) / cos(α) + _r <= rp.r || csg_isapprox_lin(_r, rp.r) + end +end +function _in(pt::CartesianPoint{T}, rp::RegularPrism{T,OpenPrimitive,N,T}) where {T,N} + abs(pt.z) < rp.hZ && begin + r, φ = hypot(pt.x, pt.y), atan(pt.y, pt.x) + α = T(π/N) + _r = r * cos(α - mod(φ, 2α)) / cos(α) + _r < rp.r + end +end + # const PrismAliases = Dict{Int, String}( # 3 => "TriangularPrism", # 4 => "SquarePrism", From fb118c63c62b38de11d23688927853efd5380bde Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 15:06:01 +0200 Subject: [PATCH 204/241] Activate `HexagonalPrism` detector in tests again --- test/runtests.jl | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index b5791d2fc..e5f3fc2e3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -61,18 +61,18 @@ end @info signalsum @test isapprox( signalsum, T(2), atol = 3e-3 ) end -# @testset "Simulate example detector: HexagonalPrism" begin -# sim = Simulation{T}(SSD_examples[:Hexagon]) -# simulate!(sim, max_refinements = 0, verbose = true) -# evt = Event([CartesianPoint{T}(0, 5e-4, 1e-3)]) -# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) -# signalsum = T(0) -# for i in 1:length(evt.waveforms) -# signalsum += abs(evt.waveforms[i].value[end]) -# end -# @info signalsum -# @test isapprox( signalsum, T(2), atol = 5e-4 ) -# end + @testset "Simulate example detector: HexagonalPrism" begin + sim = Simulation{T}(SSD_examples[:Hexagon]) + simulate!(sim, max_refinements = 0, verbose = true) + evt = Event([CartesianPoint{T}(0, 5e-4, 1e-3)]) + simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) + signalsum = T(0) + for i in 1:length(evt.waveforms) + signalsum += abs(evt.waveforms[i].value[end]) + end + @info signalsum + @test isapprox( signalsum, T(2), atol = 5e-4 ) + end @testset "Simulate example detector: CGD" begin sim = Simulation{T}(SSD_examples[:CGD]) simulate!(sim, max_refinements = 2, verbose = true) From f71d080c81e45ec17c128e30089f273cb0317cd5 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 15:25:47 +0200 Subject: [PATCH 205/241] Add struct `Ellipsoid` + IO for it --- src/ConstructiveSolidGeometry/IO.jl | 2 +- .../VolumePrimitives/Ellipsoid.jl | 72 +++++++++++++++++++ .../VolumePrimitives/Sphere.jl | 54 -------------- .../VolumePrimitives/VolumePrimitives.jl | 1 + 4 files changed, 74 insertions(+), 55 deletions(-) create mode 100644 src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl delete mode 100644 src/ConstructiveSolidGeometry/VolumePrimitives/Sphere.jl diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index eedab4c4b..7a93f39d9 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -1,7 +1,7 @@ const CSG_dict = Dict{String, Any}( "tube" => Cone, "cone" => Cone, - # "sphere" => Sphere, + "sphere" => Ellipsoid, "box" => Box, # "torus" => Torus, "TriangularPrism" => TriangularPrism, diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl new file mode 100644 index 000000000..cfc830a15 --- /dev/null +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl @@ -0,0 +1,72 @@ +@with_kw struct Ellipsoid{T,CO,RT,PT,TT} <: AbstractVolumePrimitive{T, CO} + r::RT = 1 + φ::PT = nothing + θ::TT = nothing + + origin::CartesianPoint{T} = zero(CartesianPoint{T}) + rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) +end + +Ellipsoid{T,CO,RT,PT,TT}( e::Ellipsoid{T,CO,RT,PT,TT}; COT = CO, + origin::CartesianPoint{T} = e.origin, + rotation::SMatrix{3,3,T,9} = e.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},RT,PT,TT} = + Ellipsoid{T,COT,RT,PT,TT}(e.r, e.φ, e.θ, origin, rotation) + +function Geometry(::Type{T}, ::Type{Ellipsoid}, dict::AbstractDict, input_units::NamedTuple, transformations::Transformations{T}) where {T} + r = parse_r_of_primitive(T, dict, input_units.length) + φ = nothing + θ = nothing + e = Ellipsoid{T,ClosedPrimitive,typeof(r),typeof(φ),typeof(θ)}( + r = r, + φ = φ, + θ = θ + ) + transform(e, transformations) +end + +# #Constructors +# function Sphere(; rMin = 0, rMax = 1) +# T = float(promote_type(typeof.((rMin, rMax))...)) +# r = rMin == 0 ? T(rMax) : T(rMin)..T(rMax) +# Sphere(T, r) +# end + +# Sphere(rMin, rMax) = Sphere(; rMin = rMin, rMax = rMax) +# function Sphere(r::R) where {R <: Real} +# T = float(R) +# Sphere(T, T(r)) +# end + +# in(p::AbstractCoordinatePoint, s::Sphere) = _in_sph_r(p, s.r) + +# # read-in +# function Geometry(::Type{T}, ::Type{Sphere}, dict::AbstractDict, input_units::NamedTuple) where {T} +# length_unit = input_units.length +# r = parse_r_of_primitive(T, dict, length_unit) +# return Sphere(T, r) +# end + +# function Dictionary(s::Sphere{T}) where {T} +# dict = OrderedDict{String,Any}() +# dict["r"] = typeof(s.r) == T ? s.r : OrderedDict{String,Any}("from" => s.r.left, "to" => s.r.right) +# OrderedDict{String,Any}("sphere" => dict) +# end + +# get_r_limits(s::Sphere{T}) where {T} = (_left_radial_interval(s.r), _right_radial_interval(s.r)) + +# get_decomposed_surfaces(s::Sphere{T, T}) where {T} = AbstractSurfacePrimitive[SphereMantle{T}(s.r)] + +# function get_decomposed_surfaces(s::Sphere{T, <:AbstractInterval{T}}) where {T} +# rMin::T, rMax::T = get_r_limits(s) +# AbstractSurfacePrimitive[SphereMantle{T}(rMin), SphereMantle{T}(rMax)] +# end + +# function sample(s::Sphere{T}, Nsamps::NTuple{3,Int} = (2,5,3))::Vector{CylindricalPoint{T}} where {T} +# rMin::T, rMax::T = get_r_limits(s) +# samples = [ +# CylindricalPoint{T}(r,φ,z) +# for z in (Nsamps[3] ≤ 1 ? rMax : range(-rMax, rMax, length = Nsamps[3])) +# for r in (Nsamps[1] ≤ 1 ? rMax : range((abs(z) > rMin ? 0 : sqrt(rMin^2 - z^2)), sqrt(rMax^2 - z^2), length = Nsamps[1])) +# for φ in (Nsamps[2] ≤ 1 ? 0 : range(0, 2π, length = Nsamps[2])) +# ] +# end diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Sphere.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Sphere.jl deleted file mode 100644 index e0fc2b009..000000000 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Sphere.jl +++ /dev/null @@ -1,54 +0,0 @@ -struct Sphere{T,TR} <: AbstractVolumePrimitive{T} - r::TR - - function Sphere( ::Type{T}, r::Union{T, <:AbstractInterval{T}}) where {T} - new{T, typeof(r)}(r) - end -end - -#Constructors -function Sphere(; rMin = 0, rMax = 1) - T = float(promote_type(typeof.((rMin, rMax))...)) - r = rMin == 0 ? T(rMax) : T(rMin)..T(rMax) - Sphere(T, r) -end - -Sphere(rMin, rMax) = Sphere(; rMin = rMin, rMax = rMax) -function Sphere(r::R) where {R <: Real} - T = float(R) - Sphere(T, T(r)) -end - -in(p::AbstractCoordinatePoint, s::Sphere) = _in_sph_r(p, s.r) - -# read-in -function Geometry(::Type{T}, ::Type{Sphere}, dict::AbstractDict, input_units::NamedTuple) where {T} - length_unit = input_units.length - r = parse_r_of_primitive(T, dict, length_unit) - return Sphere(T, r) -end - -function Dictionary(s::Sphere{T}) where {T} - dict = OrderedDict{String,Any}() - dict["r"] = typeof(s.r) == T ? s.r : OrderedDict{String,Any}("from" => s.r.left, "to" => s.r.right) - OrderedDict{String,Any}("sphere" => dict) -end - -get_r_limits(s::Sphere{T}) where {T} = (_left_radial_interval(s.r), _right_radial_interval(s.r)) - -get_decomposed_surfaces(s::Sphere{T, T}) where {T} = AbstractSurfacePrimitive[SphereMantle{T}(s.r)] - -function get_decomposed_surfaces(s::Sphere{T, <:AbstractInterval{T}}) where {T} - rMin::T, rMax::T = get_r_limits(s) - AbstractSurfacePrimitive[SphereMantle{T}(rMin), SphereMantle{T}(rMax)] -end - -function sample(s::Sphere{T}, Nsamps::NTuple{3,Int} = (2,5,3))::Vector{CylindricalPoint{T}} where {T} - rMin::T, rMax::T = get_r_limits(s) - samples = [ - CylindricalPoint{T}(r,φ,z) - for z in (Nsamps[3] ≤ 1 ? rMax : range(-rMax, rMax, length = Nsamps[3])) - for r in (Nsamps[1] ≤ 1 ? rMax : range((abs(z) > rMin ? 0 : sqrt(rMin^2 - z^2)), sqrt(rMax^2 - z^2), length = Nsamps[1])) - for φ in (Nsamps[2] ≤ 1 ? 0 : range(0, 2π, length = Nsamps[2])) - ] -end diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index a4b1ceef6..2530f6ad4 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -14,4 +14,5 @@ end include("Box.jl") include("Cone.jl") +include("Ellipsoid.jl") include("RegularPrism.jl") \ No newline at end of file From 70f33b0c44084fadd3c7d1cbc841e54eedb65815 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 15:28:32 +0200 Subject: [PATCH 206/241] Add aliases for different `Ellipsoid` types --- src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl index cfc830a15..352feeb2b 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl @@ -12,6 +12,10 @@ Ellipsoid{T,CO,RT,PT,TT}( e::Ellipsoid{T,CO,RT,PT,TT}; COT = CO, rotation::SMatrix{3,3,T,9} = e.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},RT,PT,TT} = Ellipsoid{T,COT,RT,PT,TT}(e.r, e.φ, e.θ, origin, rotation) +const Sphere{T,CO,PT,TT} = Ellipsoid{T,CO,T,PT,TT} +const FullSphere{T,CO} = Ellipsoid{T,CO,T,Nothing,Nothing} +const FullEllipsoid{T,CO} = Ellipsoid{T,CO,NTuple{3,T},Nothing,Nothing} + function Geometry(::Type{T}, ::Type{Ellipsoid}, dict::AbstractDict, input_units::NamedTuple, transformations::Transformations{T}) where {T} r = parse_r_of_primitive(T, dict, input_units.length) φ = nothing From 25e6d28b3b5d85cc9480dc3f3add9f651767c275 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 15:34:53 +0200 Subject: [PATCH 207/241] Add `_in` methods for `FullSphere` --- .../VolumePrimitives/Ellipsoid.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl index 352feeb2b..0107fdba4 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl @@ -28,6 +28,16 @@ function Geometry(::Type{T}, ::Type{Ellipsoid}, dict::AbstractDict, input_units: transform(e, transformations) end +function _in(pt::CartesianPoint, s::FullSphere{<:Any, ClosedPrimitive}) + r = hypot(pt.x, pt.y, pt.z) + r <= s.r || csg_isapprox_lin(r, s.r) +end +function _in(pt::CartesianPoint, s::FullSphere{<:Any, OpenPrimitive}) + r = hypot(pt.x, pt.y, pt.z) + r < s.r +end + + # #Constructors # function Sphere(; rMin = 0, rMax = 1) # T = float(promote_type(typeof.((rMin, rMax))...)) From a839ada53a5caf998cdd95f46ffaac0ba48a7603 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 15:40:32 +0200 Subject: [PATCH 208/241] Add struct for surface primitive `EllipsoidMantle` --- .../SurfacePrimitives/EllipsoidMantle.jl | 69 +++++++++++++++++++ .../SurfacePrimitives/SphereMantle.jl | 61 ---------------- .../SurfacePrimitives/SurfacePrimitives.jl | 1 + 3 files changed, 70 insertions(+), 61 deletions(-) create mode 100644 src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl delete mode 100644 src/ConstructiveSolidGeometry/SurfacePrimitives/SphereMantle.jl diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl new file mode 100644 index 000000000..833f6df20 --- /dev/null +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl @@ -0,0 +1,69 @@ +@with_kw struct EllipsoidMantle{T,RT,PT,TT} <: AbstractCurvedSurfacePrimitive{T} + r::RT = 1 + φ::PT = nothing + θ::TT = nothing + + origin::CartesianPoint{T} = zero(CartesianPoint{T}) + rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) +end + +const FullSphereMantle{T} = EllipsoidMantle{T,T,Nothing,Nothing} +const FullEllipsoidMantle{T} = EllipsoidMantle{T,NTuple{3,T},Nothing,Nothing} + +# get_r_limits(s::SphereMantle{T}) where {T} = (_left_radial_interval(s.r), _right_radial_interval(s.r)) +# get_φ_limits(s::SphereMantle{T}) where {T} = (T(0), T(2π), true) +# get_z_limits(s::SphereMantle{T}) where {T} = (-_right_linear_interval(s.r), _right_linear_interval(s.r)) + +# in(p::AbstractCoordinatePoint, s::SphereMantle) = _isapprox_sph_r(p, s.r) + +# #= +# function sample(s::SphereMantle{T}, step::Real)::Vector{CylindricalPoint{T}} where {T} +# samples = [ +# CylindricalPoint{T}(sqrt(s.r^2 - z^2),φ,z) +# for z in in -s.r:step:s.r +# for φ in 0:step/s.r:2π +# ] +# end +# =# + +# function sample(s::SphereMantle{T}, Nsamps::NTuple{3,Int})::Vector{CylindricalPoint{T}} where {T} +# samples = [ +# CylindricalPoint{T}(sqrt(s.r^2 - z^2),φ,z) +# for z in (Nsamps[3] ≤ 1 ? s.r : range(-s.r, s.r, length = Nsamps[3])) +# for φ in (Nsamps[2] ≤ 1 ? 0 : range(0, 2π, length = Nsamps[2])) +# ] +# end + +# function sample(s::SphereMantle{T}, g::CylindricalTicksTuple{T})::Vector{CylindricalPoint{T}} where {T} +# samples = [ +# CylindricalPoint{T}((s.r^2 - z^2 < 0 ? 0 : sqrt(s.r^2 - z^2)),φ,z) +# for z in get_z_ticks(s, g) +# for φ in get_φ_ticks(s, g) +# ] +# end + +# function _get_x_at_z(s::SphereMantle{T}, g::CartesianTicksTuple{T}, z::T) where {T} +# if s.r < abs(z) return [0] end +# R::T = sqrt(s.r^2 - z^2) +# x_from_y::Vector{T} = sqrt.(R^2 .- filter(y -> abs(y) <= R, g.y).^2) +# _get_ticks(sort!(vcat(g.x, x_from_y, -x_from_y)), -R, R) +# end + +# function _get_y_at_z(s::SphereMantle{T}, z::T, x::T) where {T} +# tmp::T = s.r^2 - hypot(x,z)^2 +# if tmp < 0 return (0,) end +# (-sqrt(tmp), sqrt(tmp)) +# end + +# function sample(s::SphereMantle{T}, g::CartesianTicksTuple{T})::Vector{CartesianPoint{T}} where {T} +# samples = [ +# CartesianPoint{T}(x,y,z) +# for z in get_z_ticks(s, g) +# for x in _get_x_at_z(s, g, z) +# for y in _get_y_at_z(s, z, x) +# ] +# end + +# distance_to_surface(point::CylindricalPoint{T}, s::SphereMantle{T}) where {T} = abs(hypot(point.r, point.z) - s.r) + +# distance_to_surface(point::CartesianPoint{T}, s::SphereMantle{T}) where {T} = abs(norm(point) - s.r) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SphereMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SphereMantle.jl deleted file mode 100644 index f672d392c..000000000 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SphereMantle.jl +++ /dev/null @@ -1,61 +0,0 @@ -struct SphereMantle{T} <: AbstractSurfacePrimitive{T} - r::T -end - -get_r_limits(s::SphereMantle{T}) where {T} = (_left_radial_interval(s.r), _right_radial_interval(s.r)) -get_φ_limits(s::SphereMantle{T}) where {T} = (T(0), T(2π), true) -get_z_limits(s::SphereMantle{T}) where {T} = (-_right_linear_interval(s.r), _right_linear_interval(s.r)) - -in(p::AbstractCoordinatePoint, s::SphereMantle) = _isapprox_sph_r(p, s.r) - -#= -function sample(s::SphereMantle{T}, step::Real)::Vector{CylindricalPoint{T}} where {T} - samples = [ - CylindricalPoint{T}(sqrt(s.r^2 - z^2),φ,z) - for z in in -s.r:step:s.r - for φ in 0:step/s.r:2π - ] -end -=# - -function sample(s::SphereMantle{T}, Nsamps::NTuple{3,Int})::Vector{CylindricalPoint{T}} where {T} - samples = [ - CylindricalPoint{T}(sqrt(s.r^2 - z^2),φ,z) - for z in (Nsamps[3] ≤ 1 ? s.r : range(-s.r, s.r, length = Nsamps[3])) - for φ in (Nsamps[2] ≤ 1 ? 0 : range(0, 2π, length = Nsamps[2])) - ] -end - -function sample(s::SphereMantle{T}, g::CylindricalTicksTuple{T})::Vector{CylindricalPoint{T}} where {T} - samples = [ - CylindricalPoint{T}((s.r^2 - z^2 < 0 ? 0 : sqrt(s.r^2 - z^2)),φ,z) - for z in get_z_ticks(s, g) - for φ in get_φ_ticks(s, g) - ] -end - -function _get_x_at_z(s::SphereMantle{T}, g::CartesianTicksTuple{T}, z::T) where {T} - if s.r < abs(z) return [0] end - R::T = sqrt(s.r^2 - z^2) - x_from_y::Vector{T} = sqrt.(R^2 .- filter(y -> abs(y) <= R, g.y).^2) - _get_ticks(sort!(vcat(g.x, x_from_y, -x_from_y)), -R, R) -end - -function _get_y_at_z(s::SphereMantle{T}, z::T, x::T) where {T} - tmp::T = s.r^2 - hypot(x,z)^2 - if tmp < 0 return (0,) end - (-sqrt(tmp), sqrt(tmp)) -end - -function sample(s::SphereMantle{T}, g::CartesianTicksTuple{T})::Vector{CartesianPoint{T}} where {T} - samples = [ - CartesianPoint{T}(x,y,z) - for z in get_z_ticks(s, g) - for x in _get_x_at_z(s, g, z) - for y in _get_y_at_z(s, z, x) - ] -end - -distance_to_surface(point::CylindricalPoint{T}, s::SphereMantle{T}) where {T} = abs(hypot(point.r, point.z) - s.r) - -distance_to_surface(point::CartesianPoint{T}, s::SphereMantle{T}) where {T} = abs(norm(point) - s.r) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl index 9b03ae570..8ee3de223 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl @@ -5,4 +5,5 @@ include("Plane.jl") include("Polygon.jl") include("ConeMantle.jl") include("EllipticalSurface.jl") +include("EllipsoidMantle.jl") From 7a75a08bfc934e7cc34e5b906f0d53713f5674a4 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 17:03:29 +0200 Subject: [PATCH 209/241] Add basic functions for `Ellipsoid` and `EllipsoidMantle` --- .../SurfacePrimitives/EllipsoidMantle.jl | 95 +++++++++++++++++++ .../VolumePrimitives/Ellipsoid.jl | 6 ++ .../plotting/LinePrimitives/Ellipse.jl | 6 ++ .../SurfacePrimitives/EllipsoidMantle.jl | 53 +++++++++++ .../SurfacePrimitives/SphereMantle.jl | 27 ------ .../SurfacePrimitives/SurfacePrimitives.jl | 1 + 6 files changed, 161 insertions(+), 27 deletions(-) create mode 100644 src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipsoidMantle.jl delete mode 100644 src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SphereMantle.jl diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl index 833f6df20..8f4336c56 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl @@ -10,6 +10,101 @@ end const FullSphereMantle{T} = EllipsoidMantle{T,T,Nothing,Nothing} const FullEllipsoidMantle{T} = EllipsoidMantle{T,NTuple{3,T},Nothing,Nothing} +function lines(em::FullSphereMantle{T}) where {T} + ellipse_xy = Ellipse{T,T,Nothing}(r = em.r[1], φ = em.φ, origin = em.origin, rotation = em.rotation) + ellipse_xz = Ellipse{T,T,Nothing}(r = em.r[1], φ = em.φ, origin = em.origin, rotation = em.rotation * RotX(T(π)/2)) + ellipse_yz = Ellipse{T,T,Nothing}(r = em.r[1], φ = em.φ, origin = em.origin, rotation = em.rotation * RotX(T(π)/2) * RotY(T(π)/2)) + (ellipse_xy, ellipse_xz, ellipse_yz) +end +function lines(em::FullEllipsoidMantle{T}) where {T} + ellipse_xy = Ellipse{T,NTuple{2, Tuple{T}},Nothing}(r = ((em.r[1],), (em.r[2],)), φ = em.φ, origin = em.origin, rotation = em.rotation) + ellipse_xz = Ellipse{T,NTuple{2, Tuple{T}},Nothing}(r = ((em.r[1],), (em.r[3],)), φ = em.φ, origin = em.origin, rotation = em.rotation * RotX(T(π)/2)) + ellipse_yz = Ellipse{T,NTuple{2, Tuple{T}},Nothing}(r = ((em.r[2],), (em.r[3],)), φ = em.φ, origin = em.origin, rotation = em.rotation * RotX(T(π)/2) * RotY(T(π)/2)) + (ellipse_xy, ellipse_xz, ellipse_yz) +end + +extremum(e::EllipsoidMantle{T,T}) where {T} = e.r +extremum(e::EllipsoidMantle{T,NTuple{3,T}}) where {T} = max(e.r) + +""" + intersection(cm::EllipsoidMantle{T,NTuple{3,T}}, l::Line{T}) where {T} + +The function will always return 2 CartesianPoint's. +If the line just touches the mantle, the two points will be the same. +If the line does not touch the mantle at all, the two points will have NaN's as there coordinates. +""" +function intersection(em::EllipsoidMantle{T,NTuple{3,T}}, l::Line{T}) where {T} + obj_l = _transform_into_object_coordinate_system(l, em) # direction is not normalized + + L1 = obj_l.origin.x + L2 = obj_l.origin.y + L3 = obj_l.origin.z + D1 = obj_l.direction.x + D2 = obj_l.direction.y + D3 = obj_l.direction.z + + R1 = em.r[1] + R2 = em.r[2] + R3 = em.r[3] + + term3 = D1^2/R1^2 + D2^2/R2^2 + D3^2/R3^2 + term1 = ((2D1*L1)/R1^2 + (2D2*L2)/R2^2 + (2D3*L3)/R3^2)^2 - 4*term3*(L1^2/R1^2 + L2^2/R2^2 + L3^2/R3^2 - 1) + term2 = -(2D1*L1)/R1^2 - (2D2*L2)/R2^2 - (2D3*L3)/R3^2 + + term1 = term1 < 0 ? sqrt(abs(term1)) : sqrt(term1) + + λ1 = (term2 - term1) / 2term3 + λ2 = (term2 + term1) / 2term3 + + ints1 = obj_l.origin + λ1 * obj_l.direction + ints2 = obj_l.origin + λ2 * obj_l.direction + return _transform_into_global_coordinate_system(ints1, em), + _transform_into_global_coordinate_system(ints2, em) +end +""" + intersection(cm::EllipsoidMantle{T,T}, l::Line{T}) where {T} + +The function will always return 2 CartesianPoint's. +If the line just touches the mantle, the two points will be the same. +If the line does not touch the mantle at all, the two points will have NaN's as there coordinates. +""" +function intersection(em::EllipsoidMantle{T,T}, l::Line{T}) where {T} + obj_l = _transform_into_object_coordinate_system(l, em) # direction is not normalized + + L1 = obj_l.origin.x + L2 = obj_l.origin.y + L3 = obj_l.origin.z + D1 = obj_l.direction.x + D2 = obj_l.direction.y + D3 = obj_l.direction.z + + R = em.r + + term3 = D1^2 + D2^2 + D3^2 + term1 = (2D1*L1 + 2D2*L2 + 2D3*L3)^2 - 4*term3*(L1^2 + L2^2 + L3^2 - R^2) + term2 = -D1*L1 - D2*L2 - D3*L3 + + if term1 < 0 term1 = abs(term1) end + + λ1 = (term2 - sqrt(term1)/2) / term3 + λ2 = (term2 + sqrt(term1)/2) / term3 + + ints1 = obj_l.origin + λ1 * obj_l.direction + ints2 = obj_l.origin + λ2 * obj_l.direction + return _transform_into_global_coordinate_system(ints1, em), + _transform_into_global_coordinate_system(ints2, em) +end + +# x = (-1/2 sqrt((2 D1 L1 + 2 D2 L2 + 2 D3 L3)^2 - 4 (D1^2 + D2^2 + D3^2) (L1^2 + L2^2 + L3^2 - R^2)) +# - D1 L1 - D2 L2 - D3 L3)/(D1^2 + D2^2 + D3^2) +# #and D1^2 + D2^2 + D3^2!=0 and R!=0 + +# y = (+1/2 sqrt((2 D1 L1 + 2 D2 L2 + 2 D3 L3)^2 - 4 (D1^2 + D2^2 + D3^2) (L1^2 + L2^2 + L3^2 - R^2)) +# - D1 L1 - D2 L2 - D3 L3)/(D1^2 + D2^2 + D3^2) + #and D1^2 + D2^2 + D3^2!=0 and R!=0 + + + # get_r_limits(s::SphereMantle{T}) where {T} = (_left_radial_interval(s.r), _right_radial_interval(s.r)) # get_φ_limits(s::SphereMantle{T}) where {T} = (T(0), T(2π), true) # get_z_limits(s::SphereMantle{T}) where {T} = (-_right_linear_interval(s.r), _right_linear_interval(s.r)) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl index 0107fdba4..e0e1c0e72 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl @@ -37,6 +37,12 @@ function _in(pt::CartesianPoint, s::FullSphere{<:Any, OpenPrimitive}) r < s.r end +function surfaces(e::Ellipsoid{T}) where {T} + em = EllipsoidMantle(e.r, e.φ, e.θ, e.origin, e.rotation) + (em,) +end + + # #Constructors # function Sphere(; rMin = 0, rMax = 1) diff --git a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl index b9d99916d..6757c1096 100644 --- a/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/plotting/LinePrimitives/Ellipse.jl @@ -10,6 +10,12 @@ function edges(e::Ellipse{T,T,Tuple{T,T}}; n = 4) where {T} pts = map(p -> _transform_into_global_coordinate_system(p, e), pts) edges = [Edge(pts[i], pts[i+1]) for i in 1:n] end +function edges(e::Ellipse{T,NTuple{2,Tuple{T}},Nothing}; n = 4) where {T} + φs = range(0, stop = 2π, length = n + 1) + pts = [CartesianPoint{T}(e.r[1][1] * cos(φ), e.r[2][1] * sin(φ), zero(T)) for φ in φs] + pts = map(p -> _transform_into_global_coordinate_system(p, e), pts) + edges = [Edge(pts[i], pts[i+1]) for i in 1:n] +end @recipe function f(e::Ellipse; n = 40) @series begin diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipsoidMantle.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipsoidMantle.jl new file mode 100644 index 000000000..0aec51560 --- /dev/null +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipsoidMantle.jl @@ -0,0 +1,53 @@ +@recipe function f(em::EllipsoidMantle, n = 40; subn = 10) + ls = lines(em) + linecolor --> :black + @series begin + label --> "Ellipsoid Mantle" + ls[1] + end + for i in 2:length(ls) + @series begin + label := nothing + ls[i] + end + end + # if !haskey(plotattributes, :show_normal) || plotattributes[:show_normal] + # @series begin + # label := nothing + # seriestype := :vector + # nφ = cm.φ == nothing ? 0 : (cm.φ[2] + cm.φ[1])/2 + # T = typeof(cm.hZ) + # npt_obj = CartesianPoint(CylindricalPoint{T}(radius_at_z(cm, zero(T)), nφ, zero(T))) + # npt = _transform_into_global_coordinate_system(npt_obj, cm) + # npt, normalize(normal(cm, npt))/10 + # end + # end +end + +# function get_plot_points(s::SphereMantle{T}; n = 30) where {T <: AbstractFloat} +# plot_points = Vector{CartesianPoint{T}}[] + +# φrange = range(0, 2π, length = n) + +# for φ in φrange +# push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(s.r * sin(θ) * cos(φ), s.r * sin(θ) * sin(φ), s.r * cos(θ)) for θ in φrange])) +# end +# push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(s.r * cos(φ), s.r * sin(φ), 0) for φ in φrange])) + +# plot_points +# end + +# function mesh(s::SphereMantle{T}; n = 30) where {T <: AbstractFloat} + +# θrange = range(-π/2, π/2, length = n) +# sθrange = sin.(θrange) +# cθrange = cos.(θrange) +# φrange = range(0, 2π, length = n) +# sφrange = sin.(φrange) +# cφrange = cos.(φrange) + +# X = [s.r*cθ*cφ for cφ in cφrange, cθ in cθrange] +# Y = [s.r*cθ*sφ for sφ in sφrange, cθ in cθrange] +# Z = [s.r*sθ for i in 1:n, sθ in sθrange] +# Mesh(X, Y, Z) +# end diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SphereMantle.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SphereMantle.jl deleted file mode 100644 index 471f2a6c1..000000000 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SphereMantle.jl +++ /dev/null @@ -1,27 +0,0 @@ -function get_plot_points(s::SphereMantle{T}; n = 30) where {T <: AbstractFloat} - plot_points = Vector{CartesianPoint{T}}[] - - φrange = range(0, 2π, length = n) - - for φ in φrange - push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(s.r * sin(θ) * cos(φ), s.r * sin(θ) * sin(φ), s.r * cos(θ)) for θ in φrange])) - end - push!(plot_points, Vector{CartesianPoint{T}}([CartesianPoint{T}(s.r * cos(φ), s.r * sin(φ), 0) for φ in φrange])) - - plot_points -end - -function mesh(s::SphereMantle{T}; n = 30) where {T <: AbstractFloat} - - θrange = range(-π/2, π/2, length = n) - sθrange = sin.(θrange) - cθrange = cos.(θrange) - φrange = range(0, 2π, length = n) - sφrange = sin.(φrange) - cφrange = cos.(φrange) - - X = [s.r*cθ*cφ for cφ in cφrange, cθ in cθrange] - Y = [s.r*cθ*sφ for sφ in sφrange, cθ in cθrange] - Z = [s.r*sθ for i in 1:n, sθ in sθrange] - Mesh(X, Y, Z) -end diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl index b71edd290..d7804b67f 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl @@ -1,6 +1,7 @@ include("Polygon.jl") include("EllipticalSurface.jl") include("ConeMantle.jl") +include("EllipsoidMantle.jl") @recipe function f(vp::AbstractVector{<:AbstractSurfacePrimitive}) linecolor --> :black From 6d72e3d18af1e2bc186055a3e96e3de43b4c8c18 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Wed, 23 Jun 2021 17:03:46 +0200 Subject: [PATCH 210/241] Activate `Spherical` detector in tests again --- test/runtests.jl | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index e5f3fc2e3..84647f65b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -85,20 +85,19 @@ end @info signalsum @test isapprox( signalsum, T(2), atol = 5e-2 ) end -# #= -# @testset "Simulate example detector: Spherical" begin -# sim = Simulation{T}(SSD_examples[:Spherical]) -# SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) -# # simulate!(sim, max_refinements = 1, verbose = true) -# # evt = Event([CartesianPoint{T}(0,0,0)]) -# # simulate!(evt, sim) -# # signalsum = T(0) -# # for i in 1:length(evt.waveforms) -# # signalsum += abs(evt.waveforms[i].value[end]) -# # end -# @info signalsum -# # @test isapprox( signalsum, T(2), atol = 5e-4 ) -# end + @testset "Simulate example detector: Spherical" begin + sim = Simulation{T}(SSD_examples[:Spherical]) + SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) + simulate!(sim, max_refinements = 1, verbose = true) + evt = Event([CartesianPoint{T}(0,0,0)]) + simulate!(evt, sim) + signalsum = T(0) + for i in 1:length(evt.waveforms) + signalsum += abs(evt.waveforms[i].value[end]) + end + @info signalsum + @test isapprox( signalsum, T(2), atol = 5e-4 ) + end # @testset "Simulate example detector: Toroidal" begin # sim = Simulation{T}(SSD_examples[:CoaxialTorus]) # SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) From 868d726cf59a05620a0727869b0b59027e49dded Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 24 Jun 2021 10:16:25 +0200 Subject: [PATCH 211/241] Add type field for direction of EllipsoidMantle and `normal`-method --- .../SurfacePrimitives/EllipsoidMantle.jl | 26 +++++++++++-------- .../VolumePrimitives/Ellipsoid.jl | 8 ++++-- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl index 8f4336c56..2e5c61aee 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl @@ -1,4 +1,4 @@ -@with_kw struct EllipsoidMantle{T,RT,PT,TT} <: AbstractCurvedSurfacePrimitive{T} +@with_kw struct EllipsoidMantle{T,RT,PT,TT,D} <: AbstractCurvedSurfacePrimitive{T} r::RT = 1 φ::PT = nothing θ::TT = nothing @@ -7,8 +7,11 @@ rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -const FullSphereMantle{T} = EllipsoidMantle{T,T,Nothing,Nothing} -const FullEllipsoidMantle{T} = EllipsoidMantle{T,NTuple{3,T},Nothing,Nothing} +flip(em::EllipsoidMantle{T,RT,PT,TT,:inwards}) where {T,RT,PT,TT} = + EllipsoidMantle{T,RT,PT,TT,:outwards}(em.r, em.φ, em.θ, em.origin, em.rotation ) + +const FullSphereMantle{T,D} = EllipsoidMantle{T,T,Nothing,Nothing,D} +const FullEllipsoidMantle{T,D} = EllipsoidMantle{T,NTuple{3,T},Nothing,Nothing,D} function lines(em::FullSphereMantle{T}) where {T} ellipse_xy = Ellipse{T,T,Nothing}(r = em.r[1], φ = em.φ, origin = em.origin, rotation = em.rotation) @@ -26,6 +29,15 @@ end extremum(e::EllipsoidMantle{T,T}) where {T} = e.r extremum(e::EllipsoidMantle{T,NTuple{3,T}}) where {T} = max(e.r) +function normal(em::EllipsoidMantle{T,NTuple{3,T},PT,TT,:outwards}, pt::CartesianPoint{T}) where {T,PT,TT} + # not normalized, do we want this? + # Or wrap this into somehting like `normal(em, pt) = normalize(direction(em, pt))` ? + p = _transform_into_object_coordinate_system(pt, em) + obj_normal = CartesianPoint{T}((p.x/em.r[1])^2, (p.y/em.r[2])^2, (p.z/em.r[3])^2) # We might want to store the inv(em.r) in the struct? + CartesianVector(_transform_into_global_coordinate_system(obj_normal, em)) +end +normal(em::EllipsoidMantle{T,RT,PT,TT,:inwards}, pt::CartesianPoint{T}) where {T,RT,PT,TT} = -normal(flip(em), pt) + """ intersection(cm::EllipsoidMantle{T,NTuple{3,T}}, l::Line{T}) where {T} @@ -95,14 +107,6 @@ function intersection(em::EllipsoidMantle{T,T}, l::Line{T}) where {T} _transform_into_global_coordinate_system(ints2, em) end -# x = (-1/2 sqrt((2 D1 L1 + 2 D2 L2 + 2 D3 L3)^2 - 4 (D1^2 + D2^2 + D3^2) (L1^2 + L2^2 + L3^2 - R^2)) -# - D1 L1 - D2 L2 - D3 L3)/(D1^2 + D2^2 + D3^2) -# #and D1^2 + D2^2 + D3^2!=0 and R!=0 - -# y = (+1/2 sqrt((2 D1 L1 + 2 D2 L2 + 2 D3 L3)^2 - 4 (D1^2 + D2^2 + D3^2) (L1^2 + L2^2 + L3^2 - R^2)) -# - D1 L1 - D2 L2 - D3 L3)/(D1^2 + D2^2 + D3^2) - #and D1^2 + D2^2 + D3^2!=0 and R!=0 - # get_r_limits(s::SphereMantle{T}) where {T} = (_left_radial_interval(s.r), _right_radial_interval(s.r)) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl index e0e1c0e72..5ad8a873b 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl @@ -37,8 +37,12 @@ function _in(pt::CartesianPoint, s::FullSphere{<:Any, OpenPrimitive}) r < s.r end -function surfaces(e::Ellipsoid{T}) where {T} - em = EllipsoidMantle(e.r, e.φ, e.θ, e.origin, e.rotation) +function surfaces(e::Ellipsoid{T,ClosedPrimitive}) where {T} + em = EllipsoidMantle{T,typeof(e.r),typeof(e.φ),typeof(e.θ),:inwards}(e.r, e.φ, e.θ, e.origin, e.rotation) + (em,) +end +function surfaces(e::Ellipsoid{T,OpenPrimitive}) where {T} + em = EllipsoidMantle{T,typeof(e.r),typeof(e.φ),typeof(e.θ),:outwards}(e.r, e.φ, e.θ, e.origin, e.rotation) (em,) end From fa250925a9a4da272fb7fd41132c90b6d88451b7 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 24 Jun 2021 10:40:27 +0200 Subject: [PATCH 212/241] Fix direction of `normal` for `EllipsoidMantle` --- .../SurfacePrimitives/EllipsoidMantle.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl index 2e5c61aee..3b0010525 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl @@ -33,7 +33,7 @@ function normal(em::EllipsoidMantle{T,NTuple{3,T},PT,TT,:outwards}, pt::Cartesia # not normalized, do we want this? # Or wrap this into somehting like `normal(em, pt) = normalize(direction(em, pt))` ? p = _transform_into_object_coordinate_system(pt, em) - obj_normal = CartesianPoint{T}((p.x/em.r[1])^2, (p.y/em.r[2])^2, (p.z/em.r[3])^2) # We might want to store the inv(em.r) in the struct? + obj_normal = CartesianPoint{T}(sign(p.x)*(p.x/em.r[1])^2, sign(p.y)*(p.y/em.r[2])^2, sign(p.z)*(p.z/em.r[3])^2) # We might want to store the inv(em.r) in the struct? CartesianVector(_transform_into_global_coordinate_system(obj_normal, em)) end normal(em::EllipsoidMantle{T,RT,PT,TT,:inwards}, pt::CartesianPoint{T}) where {T,RT,PT,TT} = -normal(flip(em), pt) From 600441e9c5354a44a80b91bf5c9545d7fb4e6900 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 24 Jun 2021 10:40:49 +0200 Subject: [PATCH 213/241] Add plotting of normals for `EllipsoidMantle` --- .../SurfacePrimitives/EllipsoidMantle.jl | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipsoidMantle.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipsoidMantle.jl index 0aec51560..da8cd13ad 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipsoidMantle.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/EllipsoidMantle.jl @@ -11,19 +11,36 @@ ls[i] end end - # if !haskey(plotattributes, :show_normal) || plotattributes[:show_normal] - # @series begin - # label := nothing - # seriestype := :vector - # nφ = cm.φ == nothing ? 0 : (cm.φ[2] + cm.φ[1])/2 - # T = typeof(cm.hZ) - # npt_obj = CartesianPoint(CylindricalPoint{T}(radius_at_z(cm, zero(T)), nφ, zero(T))) - # npt = _transform_into_global_coordinate_system(npt_obj, cm) - # npt, normalize(normal(cm, npt))/10 - # end - # end + if (!haskey(plotattributes, :show_normal) || plotattributes[:show_normal]) && + em.φ === nothing && em.θ === nothing + @series begin + label := nothing + seriestype := :vector + pts = _plt_points_for_normals(em) + ns = broadcast(p -> normal(em, p) / 5, pts) + [(pts[i], ns[i]) for i in eachindex(pts)] + end + end end +function _plt_points_for_normals(em::EllipsoidMantle{T,NTuple{3,T}}) where {T} + pts = [ CartesianPoint{T}( em.r[1], zero(T), zero(T)), + CartesianPoint{T}(-em.r[1], zero(T), zero(T)), + CartesianPoint{T}(zero(T), em.r[2], zero(T)), + CartesianPoint{T}(zero(T), -em.r[2], zero(T)), + CartesianPoint{T}(zero(T), zero(T), em.r[3]), + CartesianPoint{T}(zero(T), zero(T), -em.r[3]) ] + _transform_into_global_coordinate_system(pts, em) +end +function _plt_points_for_normals(em::EllipsoidMantle{T,T}) where {T} + pts = [ CartesianPoint{T}( em.r, zero(T), zero(T)), + CartesianPoint{T}(-em.r, zero(T), zero(T)), + CartesianPoint{T}(zero(T), em.r, zero(T)), + CartesianPoint{T}(zero(T), -em.r, zero(T)), + CartesianPoint{T}(zero(T), zero(T), em.r), + CartesianPoint{T}(zero(T), zero(T), -em.r) ] + _transform_into_global_coordinate_system(pts, em) +end # function get_plot_points(s::SphereMantle{T}; n = 30) where {T <: AbstractFloat} # plot_points = Vector{CartesianPoint{T}}[] From 4c7e2052aab2a74e2bc9f436d10401ace8e72aa2 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 24 Jun 2021 12:56:14 +0200 Subject: [PATCH 214/241] Adjust and add `Torus` again --- .../VolumePrimitives/Torus.jl | 329 +++++++++--------- .../VolumePrimitives/VolumePrimitives.jl | 3 +- 2 files changed, 167 insertions(+), 165 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl index c1a643b90..f9d2b985a 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl @@ -1,176 +1,177 @@ -struct Torus{T,TB,TP,TT} <: AbstractVolumePrimitive{T} - r_torus::T - r_tube::TB - φ::TP - θ::TT - z::T - function Torus( ::Type{T}, - r_torus::T, - r_tube::Union{T, <:AbstractInterval{T}}, - φ::Union{Nothing, <:AbstractInterval{T}}, - θ::Union{Nothing, <:AbstractInterval{T}}, - z::T) where {T} - new{T,typeof(r_tube),typeof(φ),typeof(θ)}(r_torus, r_tube, φ, θ, z) - end +@with_kw struct Torus{T,CO,TR,TP,TT} <: AbstractVolumePrimitive{T,CO} + r_torus::T = 1 + r_tube::TR = 1 + φ::TP = nothing + θ::TT = nothing + + origin::CartesianPoint{T} = zero(CartesianPoint{T}) + rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -#Constructors -function Torus(;r_torus = 1, r_tubeMin = 0, r_tubeMax = 1, φMin = 0, φMax = 2π, θMin = 0, θMax = 2π, z = 0) - T = float(promote_type(typeof.((r_torus, r_tubeMin, r_tubeMax, φMin, φMax, θMin, θMax, z))...)) - r_tube = r_tubeMin == 0 ? T(r_tubeMax) : T(r_tubeMin)..T(r_tubeMax) - φ = mod(T(φMax) - T(φMin), T(2π)) == 0 ? nothing : T(φMin)..T(φMax) - θ = mod(T(θMax) - T(θMin), T(2π)) == 0 ? nothing : T(θMin)..T(θMax) - Torus( T, T(r_torus), r_tube, φ, θ, T(z)) -end - -Torus(r_torus, r_tubeMin, r_tubeMax, φMin, φMax, θMin, θMax, z) = Torus(;r_torus = r_torus, r_tubeMin = r_tubeMin, r_tubeMax = r_tubeMax, φMin = φMin, φMax = φMax, θMin = θMin, θMax = θMax, z = z) - -function Torus(r_torus::R1, r_tube::R2, z::TZ) where {R1<:Real, R2<:Real, TZ<:Real} - T = float(promote_type(R1, R2, TZ)) - Torus( T, T(r_torus), T(r_tube), nothing, nothing, T(z)) -end - -function RoundChamfer(r_torus::R1, r_tube::R2, z::TZ) where {R1<:Real, R2<:Real, TZ<:Real} - T = float(promote_type(R1, R2, TZ)) - Torus( T, T(r_torus), T(r_tube), nothing, T(0)..T(π/2), T(z)) -end - -in(p::AbstractCoordinatePoint, t::Torus{<:Any, <:Any, Nothing, Nothing}) = - _in_torr_r_tube(p, t.r_torus, t.r_tube, t.z) +Torus{T,CO,TR,TP,TT}( t::Torus{T,CO,TR,TP,TT}; COT = CO, + origin::CartesianPoint{T} = t.origin, + rotation::SMatrix{3,3,T,9} = t.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},TR,TP,TT} = + Torus{T,COT,TR,TP,TT}(t.r_torus, t.r_tube, t.φ, t.θ, origin, rotation) -in(p::AbstractCoordinatePoint, t::Torus{<:Any, <:Any, <:AbstractInterval, Nothing}) = - _in_torr_r_tube(p, t.r_torus, t.r_tube, t.z) && _in_φ(p, t.φ) +const FullTorus{T,CO} = Torus{T,CO,T,Nothing,Nothing} -in(p::AbstractCoordinatePoint, t::Torus{<:Any, <:Any, Nothing, <:AbstractInterval}) = - _in_torr_r_tube(p, t.r_torus, t.r_tube, t.z) && _in_torr_θ(p, t.r_torus, t.θ, t.z) +# #Constructors +# function Torus(;r_torus = 1, r_tubeMin = 0, r_tubeMax = 1, φMin = 0, φMax = 2π, θMin = 0, θMax = 2π, z = 0) +# T = float(promote_type(typeof.((r_torus, r_tubeMin, r_tubeMax, φMin, φMax, θMin, θMax, z))...)) +# r_tube = r_tubeMin == 0 ? T(r_tubeMax) : T(r_tubeMin)..T(r_tubeMax) +# φ = mod(T(φMax) - T(φMin), T(2π)) == 0 ? nothing : T(φMin)..T(φMax) +# θ = mod(T(θMax) - T(θMin), T(2π)) == 0 ? nothing : T(θMin)..T(θMax) +# Torus( T, T(r_torus), r_tube, φ, θ, T(z)) +# end -in(p::AbstractCoordinatePoint, t::Torus{<:Any, <:Any, <:AbstractInterval, <:AbstractInterval}) = - _in_torr_r_tube(p, t.r_torus, t.r_tube, t.z) && _in_φ(p, t.φ) && _in_torr_θ(p, t.r_torus, t.θ, t.z) - - -# read-in -function Geometry(T::DataType, ::Type{Torus}, dict::AbstractDict, input_units::NamedTuple) - length_unit = input_units.length - angle_unit = input_units.angle - r_torus::T = _parse_value(T, dict["r_torus"], length_unit) - r_tube = _parse_radial_interval(T, dict["r_tube"], length_unit) - φ = parse_φ_of_primitive(T, dict, angle_unit) - θ = parse_θ_of_primitive(T, dict, angle_unit) - z::T = ("z" in keys(dict) ? _parse_value(T, dict["z"], length_unit) : T(0)) - Torus(T, r_torus, r_tube, φ, θ, z) -end +# Torus(r_torus, r_tubeMin, r_tubeMax, φMin, φMax, θMin, θMax, z) = Torus(;r_torus = r_torus, r_tubeMin = r_tubeMin, r_tubeMax = r_tubeMax, φMin = φMin, φMax = φMax, θMin = θMin, θMax = θMax, z = z) -function Dictionary(t::Torus{T}) where {T} - dict = OrderedDict{String,Any}() - dict["r_torus"] = t.r_torus - dict["r_tube"] = typeof(t.r_tube) == T ? t.r_tube : OrderedDict{String,Any}("from" => t.r_tube.left, "to" => t.r_tube.right) - if !isnothing(t.φ) dict["phi"] = OrderedDict{String,Any}("from" => t.φ.left, "to" => t.φ.right) end - if !isnothing(t.θ) dict["theta"] = OrderedDict{String,Any}("from" => t.θ.left, "to" => t.θ.right) end - if t.z != 0 dict["z"] = t.z end - OrderedDict{String,Any}("torus" => dict) -end +# function Torus(r_torus::R1, r_tube::R2, z::TZ) where {R1<:Real, R2<:Real, TZ<:Real} +# T = float(promote_type(R1, R2, TZ)) +# Torus( T, T(r_torus), T(r_tube), nothing, nothing, T(z)) +# end +# function RoundChamfer(r_torus::R1, r_tube::R2, z::TZ) where {R1<:Real, R2<:Real, TZ<:Real} +# T = float(promote_type(R1, R2, TZ)) +# Torus( T, T(r_torus), T(r_tube), nothing, T(0)..T(π/2), T(z)) +# end -get_r_tube_limits(t::Torus{T}) where {T} = (_left_radial_interval(t.r_tube),_right_radial_interval(t.r_tube)) +# in(p::AbstractCoordinatePoint, t::Torus{<:Any, <:Any, Nothing, Nothing}) = +# _in_torr_r_tube(p, t.r_torus, t.r_tube, t.z) -get_φ_limits(t::Torus{T, <:Any, Nothing, <:Any}) where {T} = (T(0), T(2π), true) -get_φ_limits(t::Torus{T, <:Any, <:AbstractInterval, <:Any}) where {T} = (t.φ.left, t.φ.right, false) +# in(p::AbstractCoordinatePoint, t::Torus{<:Any, <:Any, <:AbstractInterval, Nothing}) = +# _in_torr_r_tube(p, t.r_torus, t.r_tube, t.z) && _in_φ(p, t.φ) -get_θ_limits(t::Torus{T, <:Any, <:Any, Nothing}) where {T} = (T(0), T(2π), true) -get_θ_limits(t::Torus{T, <:Any, <:Any, <:AbstractInterval}) where {T} = (t.θ.left, t.θ.right, false) +# in(p::AbstractCoordinatePoint, t::Torus{<:Any, <:Any, Nothing, <:AbstractInterval}) = +# _in_torr_r_tube(p, t.r_torus, t.r_tube, t.z) && _in_torr_θ(p, t.r_torus, t.θ, t.z) -function _is_torus_collapsed(t::Torus{T}) where {T} - r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) - isapprox(r_tubeMin, r_tubeMax, atol = geom_atol_zero(T)) -end - -function _get_decomposed_surfaces_torus(t::Torus{T, T}) where {T} - r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) - AbstractSurfacePrimitive[TorusMantle(t, r_tube = r_tubeMax)] -end - -function _get_decomposed_surfaces_torus(t::Torus{T, <:AbstractInterval{T}}) where {T} - surfaces = AbstractSurfacePrimitive[] - r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) - if isapprox(r_tubeMin, r_tubeMax, atol = geom_atol_zero(T)) - push!(surfaces, TorusMantle(t, r_tube = r_tubeMax)) - else - push!(surfaces, TorusMantle(t, r_tube = r_tubeMin), TorusMantle(t, r_tube = r_tubeMax)) - end - surfaces -end - -get_decomposed_surfaces(t::Torus{T, <:Any, Nothing, Nothing}) where {T} = _get_decomposed_surfaces_torus(t) - -function get_decomposed_surfaces(t::Torus{T, <:Any, <:AbstractInterval, Nothing}) where {T} - φMin::T, φMax::T, _ = get_φ_limits(t) - surfaces = _get_decomposed_surfaces_torus(t) - if !_is_torus_collapsed(t) - push!(surfaces, ToroidalAnnulus(t, φ = φMin), ToroidalAnnulus(t, φ = φMax)) - end - surfaces -end - -function get_decomposed_surfaces(t::Torus{T, <:Any, Nothing, <:AbstractInterval}) where {T} - r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) - θMin::T, θMax::T, _ = get_θ_limits(t) - surfaces = _get_decomposed_surfaces_torus(t) - if !_is_torus_collapsed(t) - if r_tubeMin == T(0) && minmax(mod.((θMin, θMax), T(2π))...) == (T(0),T(π)) - rMin = t.r_torus - r_tubeMax - rMax = t.r_torus + r_tubeMax - r = rMin == T(0) ? T(rMax) : T(rMin)..T(rMax) - push!(surfaces, CylindricalAnnulus(T, r, t.φ, t.z)) - else - for θ in [θMin, θMax] - mod(θ, T(2π)) in [T(0),T(π)] ? push!(surfaces, CylindricalAnnulus(t, θ = θ)) : push!(surfaces, ConeMantle(t, θ = θ)) - end - end - end - surfaces -end - -function get_decomposed_surfaces(t::Torus{T, <:Any, <:AbstractInterval, <:AbstractInterval}) where {T} - r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) - θMin::T, θMax::T, _ = get_θ_limits(t) - φMin::T, φMax::T, _ = get_φ_limits(t) - surfaces = _get_decomposed_surfaces_torus(t) - if !_is_torus_collapsed(t) - if r_tubeMin == T(0) && minmax(mod.((θMin, θMax), T(2π))...) == (T(0),T(π)) - rMin = t.r_torus - r_tubeMax - rMax = t.r_torus + r_tubeMax - r = rMin == T(0) ? T(rMax) : T(rMin)..T(rMax) - push!(surfaces, CylindricalAnnulus(T, r, t.φ, t.z)) - else - for θ in [θMin, θMax] - mod(θ, T(2π)) in [T(0),T(π)] ? push!(surfaces, CylindricalAnnulus(t, θ = θ)) : push!(surfaces, ConeMantle(t, θ = θ)) - end - end - push!(surfaces, ToroidalAnnulus(t, φ = φMin), ToroidalAnnulus(t, φ = φMax)) - end - surfaces -end - -function sample(t::Torus{T}, step::Real) where {T} - r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) - θMin::T, θMax::T, _ = get_θ_limits(t) - φMin::T, φMax::T, _ = get_φ_limits(t) - samples = [ - CylindricalPoint{T}(t.r_torus+r_tube*cos(θ),φ,r_tube*sin(θ)) - for r_tube in r_tubeMin:step:r_tubeMax - for θ in (r_tube == 0 ? θMin : θMin:step/r_tube:θMax) - for φ in (r_tube == 0 ? φMin : φMin:step/r_tube:φMax) - ] -end +# in(p::AbstractCoordinatePoint, t::Torus{<:Any, <:Any, <:AbstractInterval, <:AbstractInterval}) = +# _in_torr_r_tube(p, t.r_torus, t.r_tube, t.z) && _in_φ(p, t.φ) && _in_torr_θ(p, t.r_torus, t.θ, t.z) + -function sample(t::Torus{T}, Nsamps::NTuple{3,Int} = (2,5,3)) where {T} - r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) - θMin::T, θMax::T, _ = get_θ_limits(t) - φMin::T, φMax::T, _ = get_φ_limits(t) - samples = [ - CylindricalPoint{T}(t.r_torus+r_tube*cos(θ),φ,r_tube*sin(θ)) - for r_tube in (Nsamps[1] ≤ 1 ? r_tubeMin : range(r_tubeMin, r_tubeMax, length = Nsamps[1])) - for θ in (Nsamps[3] ≤ 1 ? θMin : range(θMin, θMax, length = Nsamps[3])) - for φ in (Nsamps[2] ≤ 1 ? φMin : range(φMin, φMax, length = Nsamps[2])) - ] -end +# # read-in +# function Geometry(T::DataType, ::Type{Torus}, dict::AbstractDict, input_units::NamedTuple) +# length_unit = input_units.length +# angle_unit = input_units.angle +# r_torus::T = _parse_value(T, dict["r_torus"], length_unit) +# r_tube = _parse_radial_interval(T, dict["r_tube"], length_unit) +# φ = parse_φ_of_primitive(T, dict, angle_unit) +# θ = parse_θ_of_primitive(T, dict, angle_unit) +# z::T = ("z" in keys(dict) ? _parse_value(T, dict["z"], length_unit) : T(0)) +# Torus(T, r_torus, r_tube, φ, θ, z) +# end + +# function Dictionary(t::Torus{T}) where {T} +# dict = OrderedDict{String,Any}() +# dict["r_torus"] = t.r_torus +# dict["r_tube"] = typeof(t.r_tube) == T ? t.r_tube : OrderedDict{String,Any}("from" => t.r_tube.left, "to" => t.r_tube.right) +# if !isnothing(t.φ) dict["phi"] = OrderedDict{String,Any}("from" => t.φ.left, "to" => t.φ.right) end +# if !isnothing(t.θ) dict["theta"] = OrderedDict{String,Any}("from" => t.θ.left, "to" => t.θ.right) end +# if t.z != 0 dict["z"] = t.z end +# OrderedDict{String,Any}("torus" => dict) +# end + + +# get_r_tube_limits(t::Torus{T}) where {T} = (_left_radial_interval(t.r_tube),_right_radial_interval(t.r_tube)) + +# get_φ_limits(t::Torus{T, <:Any, Nothing, <:Any}) where {T} = (T(0), T(2π), true) +# get_φ_limits(t::Torus{T, <:Any, <:AbstractInterval, <:Any}) where {T} = (t.φ.left, t.φ.right, false) + +# get_θ_limits(t::Torus{T, <:Any, <:Any, Nothing}) where {T} = (T(0), T(2π), true) +# get_θ_limits(t::Torus{T, <:Any, <:Any, <:AbstractInterval}) where {T} = (t.θ.left, t.θ.right, false) + +# function _is_torus_collapsed(t::Torus{T}) where {T} +# r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) +# isapprox(r_tubeMin, r_tubeMax, atol = geom_atol_zero(T)) +# end + +# function _get_decomposed_surfaces_torus(t::Torus{T, T}) where {T} +# r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) +# AbstractSurfacePrimitive[TorusMantle(t, r_tube = r_tubeMax)] +# end + +# function _get_decomposed_surfaces_torus(t::Torus{T, <:AbstractInterval{T}}) where {T} +# surfaces = AbstractSurfacePrimitive[] +# r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) +# if isapprox(r_tubeMin, r_tubeMax, atol = geom_atol_zero(T)) +# push!(surfaces, TorusMantle(t, r_tube = r_tubeMax)) +# else +# push!(surfaces, TorusMantle(t, r_tube = r_tubeMin), TorusMantle(t, r_tube = r_tubeMax)) +# end +# surfaces +# end + +# get_decomposed_surfaces(t::Torus{T, <:Any, Nothing, Nothing}) where {T} = _get_decomposed_surfaces_torus(t) + +# function get_decomposed_surfaces(t::Torus{T, <:Any, <:AbstractInterval, Nothing}) where {T} +# φMin::T, φMax::T, _ = get_φ_limits(t) +# surfaces = _get_decomposed_surfaces_torus(t) +# if !_is_torus_collapsed(t) +# push!(surfaces, ToroidalAnnulus(t, φ = φMin), ToroidalAnnulus(t, φ = φMax)) +# end +# surfaces +# end + +# function get_decomposed_surfaces(t::Torus{T, <:Any, Nothing, <:AbstractInterval}) where {T} +# r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) +# θMin::T, θMax::T, _ = get_θ_limits(t) +# surfaces = _get_decomposed_surfaces_torus(t) +# if !_is_torus_collapsed(t) +# if r_tubeMin == T(0) && minmax(mod.((θMin, θMax), T(2π))...) == (T(0),T(π)) +# rMin = t.r_torus - r_tubeMax +# rMax = t.r_torus + r_tubeMax +# r = rMin == T(0) ? T(rMax) : T(rMin)..T(rMax) +# push!(surfaces, CylindricalAnnulus(T, r, t.φ, t.z)) +# else +# for θ in [θMin, θMax] +# mod(θ, T(2π)) in [T(0),T(π)] ? push!(surfaces, CylindricalAnnulus(t, θ = θ)) : push!(surfaces, ConeMantle(t, θ = θ)) +# end +# end +# end +# surfaces +# end + +# function get_decomposed_surfaces(t::Torus{T, <:Any, <:AbstractInterval, <:AbstractInterval}) where {T} +# r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) +# θMin::T, θMax::T, _ = get_θ_limits(t) +# φMin::T, φMax::T, _ = get_φ_limits(t) +# surfaces = _get_decomposed_surfaces_torus(t) +# if !_is_torus_collapsed(t) +# if r_tubeMin == T(0) && minmax(mod.((θMin, θMax), T(2π))...) == (T(0),T(π)) +# rMin = t.r_torus - r_tubeMax +# rMax = t.r_torus + r_tubeMax +# r = rMin == T(0) ? T(rMax) : T(rMin)..T(rMax) +# push!(surfaces, CylindricalAnnulus(T, r, t.φ, t.z)) +# else +# for θ in [θMin, θMax] +# mod(θ, T(2π)) in [T(0),T(π)] ? push!(surfaces, CylindricalAnnulus(t, θ = θ)) : push!(surfaces, ConeMantle(t, θ = θ)) +# end +# end +# push!(surfaces, ToroidalAnnulus(t, φ = φMin), ToroidalAnnulus(t, φ = φMax)) +# end +# surfaces +# end + +# function sample(t::Torus{T}, step::Real) where {T} +# r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) +# θMin::T, θMax::T, _ = get_θ_limits(t) +# φMin::T, φMax::T, _ = get_φ_limits(t) +# samples = [ +# CylindricalPoint{T}(t.r_torus+r_tube*cos(θ),φ,r_tube*sin(θ)) +# for r_tube in r_tubeMin:step:r_tubeMax +# for θ in (r_tube == 0 ? θMin : θMin:step/r_tube:θMax) +# for φ in (r_tube == 0 ? φMin : φMin:step/r_tube:φMax) +# ] +# end + +# function sample(t::Torus{T}, Nsamps::NTuple{3,Int} = (2,5,3)) where {T} +# r_tubeMin::T, r_tubeMax::T = get_r_tube_limits(t) +# θMin::T, θMax::T, _ = get_θ_limits(t) +# φMin::T, φMax::T, _ = get_φ_limits(t) +# samples = [ +# CylindricalPoint{T}(t.r_torus+r_tube*cos(θ),φ,r_tube*sin(θ)) +# for r_tube in (Nsamps[1] ≤ 1 ? r_tubeMin : range(r_tubeMin, r_tubeMax, length = Nsamps[1])) +# for θ in (Nsamps[3] ≤ 1 ? θMin : range(θMin, θMax, length = Nsamps[3])) +# for φ in (Nsamps[2] ≤ 1 ? φMin : range(φMin, φMax, length = Nsamps[2])) +# ] +# end diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl index 2530f6ad4..1c050abd3 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/VolumePrimitives.jl @@ -15,4 +15,5 @@ end include("Box.jl") include("Cone.jl") include("Ellipsoid.jl") -include("RegularPrism.jl") \ No newline at end of file +include("RegularPrism.jl") +include("Torus.jl") \ No newline at end of file From e574a1e829325a654a8a554faa9e098523d501dd Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 24 Jun 2021 13:10:49 +0200 Subject: [PATCH 215/241] Adjust IO for `Torus` --- src/ConstructiveSolidGeometry/IO.jl | 2 +- .../VolumePrimitives/Torus.jl | 34 +++++++++++++------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 7a93f39d9..45c98b305 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -3,7 +3,7 @@ const CSG_dict = Dict{String, Any}( "cone" => Cone, "sphere" => Ellipsoid, "box" => Box, - # "torus" => Torus, + "torus" => Torus, "TriangularPrism" => TriangularPrism, "QuadranglePrism" => QuadranglePrism, "PentagonalPrism" => PentagonalPrism, diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl index f9d2b985a..ae16b8e7f 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl @@ -1,6 +1,6 @@ @with_kw struct Torus{T,CO,TR,TP,TT} <: AbstractVolumePrimitive{T,CO} r_torus::T = 1 - r_tube::TR = 1 + r_tube::TR = 1 φ::TP = nothing θ::TT = nothing @@ -15,6 +15,18 @@ Torus{T,CO,TR,TP,TT}( t::Torus{T,CO,TR,TP,TT}; COT = CO, const FullTorus{T,CO} = Torus{T,CO,T,Nothing,Nothing} +function Geometry(::Type{T}, ::Type{Torus}, dict::AbstractDict, input_units::NamedTuple, transformations::Transformations{T}) where {T} + length_unit = input_units.length + angle_unit = input_units.angle + r_torus = _parse_value(T, dict["r_torus"], length_unit) + r_tube = _parse_radial_interval(T, dict["r_tube"], length_unit) + φ = parse_φ_of_primitive(T, dict, angle_unit) + θ = parse_θ_of_primitive(T, dict, angle_unit) + t = Torus{T,ClosedPrimitive,typeof(r_tube),typeof(φ),typeof(θ)}( + r_torus = r_torus, r_tube = r_tube, φ =φ, θ = θ) + transform(t, transformations) +end + # #Constructors # function Torus(;r_torus = 1, r_tubeMin = 0, r_tubeMax = 1, φMin = 0, φMax = 2π, θMin = 0, θMax = 2π, z = 0) # T = float(promote_type(typeof.((r_torus, r_tubeMin, r_tubeMax, φMin, φMax, θMin, θMax, z))...)) @@ -50,16 +62,16 @@ const FullTorus{T,CO} = Torus{T,CO,T,Nothing,Nothing} # # read-in -# function Geometry(T::DataType, ::Type{Torus}, dict::AbstractDict, input_units::NamedTuple) -# length_unit = input_units.length -# angle_unit = input_units.angle -# r_torus::T = _parse_value(T, dict["r_torus"], length_unit) -# r_tube = _parse_radial_interval(T, dict["r_tube"], length_unit) -# φ = parse_φ_of_primitive(T, dict, angle_unit) -# θ = parse_θ_of_primitive(T, dict, angle_unit) -# z::T = ("z" in keys(dict) ? _parse_value(T, dict["z"], length_unit) : T(0)) -# Torus(T, r_torus, r_tube, φ, θ, z) -# end +function Geometry(T::DataType, ::Type{Torus}, dict::AbstractDict, input_units::NamedTuple) + length_unit = input_units.length + angle_unit = input_units.angle + r_torus::T = _parse_value(T, dict["r_torus"], length_unit) + r_tube = _parse_radial_interval(T, dict["r_tube"], length_unit) + φ = parse_φ_of_primitive(T, dict, angle_unit) + θ = parse_θ_of_primitive(T, dict, angle_unit) + z::T = ("z" in keys(dict) ? _parse_value(T, dict["z"], length_unit) : T(0)) + Torus(T, r_torus, r_tube, φ, θ, z) +end # function Dictionary(t::Torus{T}) where {T} # dict = OrderedDict{String,Any}() From 7122bd927631e71483e9abf02dc5239ab1a62e1e Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 24 Jun 2021 13:18:57 +0200 Subject: [PATCH 216/241] Adjust and add `TorusMantle` again --- .../SurfacePrimitives/SurfacePrimitives.jl | 1 + .../SurfacePrimitives/TorusMantle.jl | 285 +++++++++--------- 2 files changed, 143 insertions(+), 143 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl index 8ee3de223..7c3728087 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/SurfacePrimitives.jl @@ -6,4 +6,5 @@ include("Polygon.jl") include("ConeMantle.jl") include("EllipticalSurface.jl") include("EllipsoidMantle.jl") +include("TorusMantle.jl") diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl index 6be07d40a..51e12bc77 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl @@ -1,145 +1,144 @@ -struct TorusMantle{T,TP,TT} <: AbstractSurfacePrimitive{T} - r_torus::T - r_tube::T - φ::TP - θ::TT - z::T - function TorusMantle( ::Type{T}, - r_torus::T, - r_tube::T, - φ::Union{Nothing, <:AbstractInterval{T}}, - θ::Union{Nothing, <:AbstractInterval{T}}, - z::T) where {T} - new{T,typeof(φ),typeof(θ)}(r_torus, r_tube, φ, θ, z) - end +@with_kw struct TorusMantle{T,TP,TT,D} <: AbstractCurvedSurfacePrimitive{T} + r_torus::T = 1 + r_tube::T = 1 + φ::TP = nothing + θ::TT = nothing + + origin::CartesianPoint{T} = zero(CartesianPoint{T}) + rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -#Constructors -TorusMantle(t::Torus{T}; r_tube = 1) where {T} = TorusMantle( T, t.r_torus, T(r_tube), t.φ, t.θ, t.z) - -function TorusMantle(;r_torus = 1, r_tube = 1, φMin = 0, φMax = 2π, θMin = 0, θMax = 2π, z = 0) - T = float(promote_type(typeof.((r_torus, r_tube, φMin, φMax, θMin, θMax, z))...)) - φ = mod(T(φMax) - T(φMin), T(2π)) == 0 ? nothing : T(φMin)..T(φMax) - θ = mod(T(θMax) - T(θMin), T(2π)) == 0 ? nothing : T(θMin)..T(θMax) - TorusMantle( T, T(r_torus), T(r_tube), φ, θ, T(z)) -end -TorusMantle(r_torus, r_tube, φMin, φMax, θMin, θMax, z) = TorusMantle(;r_torus = r_torus, r_tube = r_tube, φMin = φMin, φMax = φMax, θMin = θMin, θMax = θMax, z = z) - -function get_surface_vector(t::TorusMantle{T}, point::AbstractCoordinatePoint)::CartesianVector{T} where {T} - pcy = CylindricalPoint(point) - r = pcy.r - t.r_torus - sφ::T, cφ::T = sincos(pcy.φ) - CartesianVector{T}(r*cφ, r*sφ, pcy.z - t.z) -end - -in(p::AbstractCoordinatePoint, t::TorusMantle{<:Any, Nothing, Nothing}) = - _isapprox_torr_r_tube(p, t.r_torus, t.r_tube, t.z) - -in(p::AbstractCoordinatePoint, t::TorusMantle{<:Any, <:AbstractInterval, Nothing}) = - _isapprox_torr_r_tube(p, t.r_torus, t.r_tube, t.z) && _in_φ(p, t.φ) - -in(p::AbstractCoordinatePoint, t::TorusMantle{<:Any, Nothing, <:AbstractInterval}) = - _isapprox_torr_r_tube(p, t.r_torus, t.r_tube, t.z) && _in_torr_θ(p, t.r_torus, t.θ, t.z) - -in(p::AbstractCoordinatePoint, t::TorusMantle{<:Any, <:AbstractInterval, <:AbstractInterval}) = - _isapprox_torr_r_tube(p, t.r_torus, t.r_tube, t.z) && _in_φ(p, t.φ) && _in_torr_θ(p, t.r_torus, t.θ, t.z) - -get_φ_limits(t::TorusMantle{T, Nothing}) where {T} = (T(0), T(2π), true) -get_φ_limits(t::TorusMantle{T, <:AbstractInterval}) where {T} = (t.φ.left, t.φ.right, false) - -get_θ_limits(t::TorusMantle{T, <:Any, Nothing}) where {T} = (T(0), T(2π), true) -get_θ_limits(t::TorusMantle{T, <:Any, <:AbstractInterval}) where {T} = (t.θ.left, t.θ.right, false) - - -function sample(t::TorusMantle{T}, step::Real) where {T} - φMin::T, φMax::T, _ = get_φ_limits(t) - θMin::T, θMax::T, _ = get_θ_limits(t) - samples = [ - CylindricalPoint{T}(get_r_at_θ(t,θ),φ,t.r_tube*sin(θ)+t.z) - for φ in (t.r_tube == 0 ? φMin : φMin:step/t.r_tube:φMax) - for θ in (t.r_tube == 0 ? θMin : θMin:step/t.r_tube:θMax) - ] -end - -function sample(t::TorusMantle{T}, Nsamps::NTuple{3,Int}) where {T} - φMin::T, φMax::T, _ = get_φ_limits(t) - θMin::T, θMax::T, _ = get_θ_limits(t) - samples = [ - CylindricalPoint{T}(get_r_at_θ(t,θ),φ,t.r_tube*sin(θ)+t.z) - for φ in (Nsamps[2] ≤ 1 ? φMin : range(φMin, φMax, length = Nsamps[2])) - for θ in (Nsamps[3] ≤ 1 ? θMin : range(θMin, θMax, length = Nsamps[3])) - ] -end - - -function _get_z_ticks(t::TorusMantle{T}, g::CylindricalTicksTuple{T}) where {T} - z_from_r::Vector{T} = sqrt.(t.r_tube.^2 .- (filter(r -> abs(r - t.r_torus) < t.r_tube, g.r).- t.r_torus).^2) - filter!(z -> t.r_tube^2 - (z - t.z)^2 >= 0,_get_ticks(sort!(vcat(g.z, t.z .- z_from_r, t.z .+ z_from_r)), t.z - t.r_tube, t.z + t.r_tube)) -end - -function sample(t::TorusMantle{T}, g::CylindricalTicksTuple{T})::Vector{CylindricalPoint{T}} where {T} - samples::Vector{CylindricalPoint{T}} = [ - CylindricalPoint{T}(r,φ,z) - for z in _get_z_ticks(t, g) - for φ in get_φ_ticks(t, g) - for r in (t.r_torus - sqrt(t.r_tube^2 - (z - t.z)^2), t.r_torus + sqrt(t.r_tube^2 - (z - t.z)^2)) - if t.θ === nothing || _in_angular_interval_closed(mod(atan(z - t.z, r - t.r_torus), T(2π)), t.θ) - ] -end - - -function _get_z_ticks(t::TorusMantle{T}, g::CartesianTicksTuple{T}) where {T} - z_from_x::Vector{T} = t.z .+ sqrt.(t.r_tube.^2 .- (filter(x -> abs(x - t.r_torus) < t.r_tube, g.x).- t.r_torus).^2) - z_from_y::Vector{T} = t.z .+ sqrt.(t.r_tube.^2 .- (filter(y -> abs(y - t.r_torus) < t.r_tube, g.y).- t.r_torus).^2) - filter!(z -> t.r_tube^2 - (z - t.z)^2 >= 0,_get_ticks(unique!(sort!(vcat(g.z, t.z .- z_from_x, t.z .+ z_from_x, t.z .- z_from_y, t.z .+ z_from_y))), t.z - t.r_tube, t.z + t.r_tube)) -end - -function _get_x_at_z(t::TorusMantle{T}, g::CartesianTicksTuple{T}, z::T) where {T} - R::T = sqrt(t.r_tube^2 - (z - t.z)^2) - xMax_from_y::Vector{T} = sqrt.((t.r_torus + R)^2 .- filter(y -> abs(y) <= t.r_torus + R, g.y).^2) - xMin_from_y::Vector{T} = sqrt.((t.r_torus - R)^2 .- filter(y -> abs(y) <= t.r_torus - R, g.y).^2) - _get_ticks(sort!(vcat(-xMax_from_y, -xMin_from_y, g.x, xMin_from_y, xMax_from_y)), -t.r_torus - t.r_tube, t.r_torus + t.r_tube) -end - -function _get_y_at_z(t::TorusMantle{T}, x::T, z::T) where {T} - R::T = sqrt(t.r_tube^2 - (z - t.z)^2) - tmp::T = (t.r_torus + R)^2 - x^2 - tmp2::T = (t.r_torus - R)^2 - x^2 - if tmp < 0 - () - elseif tmp2 < 0 - (-sqrt(tmp), sqrt(tmp)) - else - (-sqrt(tmp), -sqrt(tmp2), sqrt(tmp2), sqrt(tmp)) - end -end - -function sample(t::TorusMantle{T}, g::CartesianTicksTuple{T})::Vector{CartesianPoint{T}} where {T} - samples::Vector{CartesianPoint{T}} = [ - CartesianPoint{T}(x,y,z) - for z in _get_z_ticks(t, g) - for x in _get_x_at_z(t, g, z) - for y in _get_y_at_z(t, x, z) - if (t.φ === nothing || mod(atan(y, x), T(2π)) in t.φ) && - (t.θ === nothing || _in_angular_interval_closed(mod(atan(z - t.z, hypot(x, y) - t.r_torus), T(2π)), t.θ)) - ] -end - -Arc(t::TorusMantle{T}) where {T} = Arc(T, t.r_tube, PlanarPoint{T}(t.r_torus,t.z), t.θ) - -function distance_to_surface(point::AbstractCoordinatePoint{T}, t::TorusMantle{T, Nothing})::T where {T} - pcy = CylindricalPoint(point) - return distance_to_line(PlanarPoint{T}(pcy.r,pcy.z), Arc(t)) -end - -function distance_to_surface(point::AbstractCoordinatePoint{T}, t::TorusMantle{T, <:AbstractInterval})::T where {T} - pcy = CylindricalPoint(point) - if _in_φ(point, t.φ) - return distance_to_line(PlanarPoint{T}(pcy.r,pcy.z), Arc(t)) - else - φMin::T, φMax::T, _ = get_φ_limits(t) - Δφ = pcy.φ - _φNear(pcy.φ, φMin, φMax) - d, r_on_plane = pcy.r .* sincos(Δφ) - return hypot(d, distance_to_line(PlanarPoint{T}(r_on_plane, pcy.z), Arc(t))) - end -end +flip(t::TorusMantle{T,TP,TT,:inwards}) where {T,TP,TT} = + TorusMantle{T,TP,TT,:outwards}(t.r_torus, t.r_tube, t.φ, t.θ, t.origin, t.rotation ) + +const FullTorusMantle{T,D} = TorusMantle{T,Nothing,Nothing,D} + +# #Constructors +# TorusMantle(t::Torus{T}; r_tube = 1) where {T} = TorusMantle( T, t.r_torus, T(r_tube), t.φ, t.θ, t.z) + +# function TorusMantle(;r_torus = 1, r_tube = 1, φMin = 0, φMax = 2π, θMin = 0, θMax = 2π, z = 0) +# T = float(promote_type(typeof.((r_torus, r_tube, φMin, φMax, θMin, θMax, z))...)) +# φ = mod(T(φMax) - T(φMin), T(2π)) == 0 ? nothing : T(φMin)..T(φMax) +# θ = mod(T(θMax) - T(θMin), T(2π)) == 0 ? nothing : T(θMin)..T(θMax) +# TorusMantle( T, T(r_torus), T(r_tube), φ, θ, T(z)) +# end +# TorusMantle(r_torus, r_tube, φMin, φMax, θMin, θMax, z) = TorusMantle(;r_torus = r_torus, r_tube = r_tube, φMin = φMin, φMax = φMax, θMin = θMin, θMax = θMax, z = z) + +# function get_surface_vector(t::TorusMantle{T}, point::AbstractCoordinatePoint)::CartesianVector{T} where {T} +# pcy = CylindricalPoint(point) +# r = pcy.r - t.r_torus +# sφ::T, cφ::T = sincos(pcy.φ) +# CartesianVector{T}(r*cφ, r*sφ, pcy.z - t.z) +# end + +# in(p::AbstractCoordinatePoint, t::TorusMantle{<:Any, Nothing, Nothing}) = +# _isapprox_torr_r_tube(p, t.r_torus, t.r_tube, t.z) + +# in(p::AbstractCoordinatePoint, t::TorusMantle{<:Any, <:AbstractInterval, Nothing}) = +# _isapprox_torr_r_tube(p, t.r_torus, t.r_tube, t.z) && _in_φ(p, t.φ) + +# in(p::AbstractCoordinatePoint, t::TorusMantle{<:Any, Nothing, <:AbstractInterval}) = +# _isapprox_torr_r_tube(p, t.r_torus, t.r_tube, t.z) && _in_torr_θ(p, t.r_torus, t.θ, t.z) + +# in(p::AbstractCoordinatePoint, t::TorusMantle{<:Any, <:AbstractInterval, <:AbstractInterval}) = +# _isapprox_torr_r_tube(p, t.r_torus, t.r_tube, t.z) && _in_φ(p, t.φ) && _in_torr_θ(p, t.r_torus, t.θ, t.z) + +# get_φ_limits(t::TorusMantle{T, Nothing}) where {T} = (T(0), T(2π), true) +# get_φ_limits(t::TorusMantle{T, <:AbstractInterval}) where {T} = (t.φ.left, t.φ.right, false) + +# get_θ_limits(t::TorusMantle{T, <:Any, Nothing}) where {T} = (T(0), T(2π), true) +# get_θ_limits(t::TorusMantle{T, <:Any, <:AbstractInterval}) where {T} = (t.θ.left, t.θ.right, false) + + +# function sample(t::TorusMantle{T}, step::Real) where {T} +# φMin::T, φMax::T, _ = get_φ_limits(t) +# θMin::T, θMax::T, _ = get_θ_limits(t) +# samples = [ +# CylindricalPoint{T}(get_r_at_θ(t,θ),φ,t.r_tube*sin(θ)+t.z) +# for φ in (t.r_tube == 0 ? φMin : φMin:step/t.r_tube:φMax) +# for θ in (t.r_tube == 0 ? θMin : θMin:step/t.r_tube:θMax) +# ] +# end + +# function sample(t::TorusMantle{T}, Nsamps::NTuple{3,Int}) where {T} +# φMin::T, φMax::T, _ = get_φ_limits(t) +# θMin::T, θMax::T, _ = get_θ_limits(t) +# samples = [ +# CylindricalPoint{T}(get_r_at_θ(t,θ),φ,t.r_tube*sin(θ)+t.z) +# for φ in (Nsamps[2] ≤ 1 ? φMin : range(φMin, φMax, length = Nsamps[2])) +# for θ in (Nsamps[3] ≤ 1 ? θMin : range(θMin, θMax, length = Nsamps[3])) +# ] +# end + + +# function _get_z_ticks(t::TorusMantle{T}, g::CylindricalTicksTuple{T}) where {T} +# z_from_r::Vector{T} = sqrt.(t.r_tube.^2 .- (filter(r -> abs(r - t.r_torus) < t.r_tube, g.r).- t.r_torus).^2) +# filter!(z -> t.r_tube^2 - (z - t.z)^2 >= 0,_get_ticks(sort!(vcat(g.z, t.z .- z_from_r, t.z .+ z_from_r)), t.z - t.r_tube, t.z + t.r_tube)) +# end + +# function sample(t::TorusMantle{T}, g::CylindricalTicksTuple{T})::Vector{CylindricalPoint{T}} where {T} +# samples::Vector{CylindricalPoint{T}} = [ +# CylindricalPoint{T}(r,φ,z) +# for z in _get_z_ticks(t, g) +# for φ in get_φ_ticks(t, g) +# for r in (t.r_torus - sqrt(t.r_tube^2 - (z - t.z)^2), t.r_torus + sqrt(t.r_tube^2 - (z - t.z)^2)) +# if t.θ === nothing || _in_angular_interval_closed(mod(atan(z - t.z, r - t.r_torus), T(2π)), t.θ) +# ] +# end + + +# function _get_z_ticks(t::TorusMantle{T}, g::CartesianTicksTuple{T}) where {T} +# z_from_x::Vector{T} = t.z .+ sqrt.(t.r_tube.^2 .- (filter(x -> abs(x - t.r_torus) < t.r_tube, g.x).- t.r_torus).^2) +# z_from_y::Vector{T} = t.z .+ sqrt.(t.r_tube.^2 .- (filter(y -> abs(y - t.r_torus) < t.r_tube, g.y).- t.r_torus).^2) +# filter!(z -> t.r_tube^2 - (z - t.z)^2 >= 0,_get_ticks(unique!(sort!(vcat(g.z, t.z .- z_from_x, t.z .+ z_from_x, t.z .- z_from_y, t.z .+ z_from_y))), t.z - t.r_tube, t.z + t.r_tube)) +# end + +# function _get_x_at_z(t::TorusMantle{T}, g::CartesianTicksTuple{T}, z::T) where {T} +# R::T = sqrt(t.r_tube^2 - (z - t.z)^2) +# xMax_from_y::Vector{T} = sqrt.((t.r_torus + R)^2 .- filter(y -> abs(y) <= t.r_torus + R, g.y).^2) +# xMin_from_y::Vector{T} = sqrt.((t.r_torus - R)^2 .- filter(y -> abs(y) <= t.r_torus - R, g.y).^2) +# _get_ticks(sort!(vcat(-xMax_from_y, -xMin_from_y, g.x, xMin_from_y, xMax_from_y)), -t.r_torus - t.r_tube, t.r_torus + t.r_tube) +# end + +# function _get_y_at_z(t::TorusMantle{T}, x::T, z::T) where {T} +# R::T = sqrt(t.r_tube^2 - (z - t.z)^2) +# tmp::T = (t.r_torus + R)^2 - x^2 +# tmp2::T = (t.r_torus - R)^2 - x^2 +# if tmp < 0 +# () +# elseif tmp2 < 0 +# (-sqrt(tmp), sqrt(tmp)) +# else +# (-sqrt(tmp), -sqrt(tmp2), sqrt(tmp2), sqrt(tmp)) +# end +# end + +# function sample(t::TorusMantle{T}, g::CartesianTicksTuple{T})::Vector{CartesianPoint{T}} where {T} +# samples::Vector{CartesianPoint{T}} = [ +# CartesianPoint{T}(x,y,z) +# for z in _get_z_ticks(t, g) +# for x in _get_x_at_z(t, g, z) +# for y in _get_y_at_z(t, x, z) +# if (t.φ === nothing || mod(atan(y, x), T(2π)) in t.φ) && +# (t.θ === nothing || _in_angular_interval_closed(mod(atan(z - t.z, hypot(x, y) - t.r_torus), T(2π)), t.θ)) +# ] +# end + +# Arc(t::TorusMantle{T}) where {T} = Arc(T, t.r_tube, PlanarPoint{T}(t.r_torus,t.z), t.θ) + +# function distance_to_surface(point::AbstractCoordinatePoint{T}, t::TorusMantle{T, Nothing})::T where {T} +# pcy = CylindricalPoint(point) +# return distance_to_line(PlanarPoint{T}(pcy.r,pcy.z), Arc(t)) +# end + +# function distance_to_surface(point::AbstractCoordinatePoint{T}, t::TorusMantle{T, <:AbstractInterval})::T where {T} +# pcy = CylindricalPoint(point) +# if _in_φ(point, t.φ) +# return distance_to_line(PlanarPoint{T}(pcy.r,pcy.z), Arc(t)) +# else +# φMin::T, φMax::T, _ = get_φ_limits(t) +# Δφ = pcy.φ - _φNear(pcy.φ, φMin, φMax) +# d, r_on_plane = pcy.r .* sincos(Δφ) +# return hypot(d, distance_to_line(PlanarPoint{T}(r_on_plane, pcy.z), Arc(t))) +# end +# end From bd24d5e64c2303b32c18a496f74972adf41220cf Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 24 Jun 2021 13:19:51 +0200 Subject: [PATCH 217/241] Code style --- .../SurfacePrimitives/EllipsoidMantle.jl | 12 ++++++------ .../VolumePrimitives/Ellipsoid.jl | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl index 3b0010525..9560eba3f 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl @@ -1,14 +1,14 @@ -@with_kw struct EllipsoidMantle{T,RT,PT,TT,D} <: AbstractCurvedSurfacePrimitive{T} +@with_kw struct EllipsoidMantle{T,RT,TP,TT,D} <: AbstractCurvedSurfacePrimitive{T} r::RT = 1 - φ::PT = nothing + φ::TP = nothing θ::TT = nothing origin::CartesianPoint{T} = zero(CartesianPoint{T}) rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -flip(em::EllipsoidMantle{T,RT,PT,TT,:inwards}) where {T,RT,PT,TT} = - EllipsoidMantle{T,RT,PT,TT,:outwards}(em.r, em.φ, em.θ, em.origin, em.rotation ) +flip(em::EllipsoidMantle{T,RT,TP,TT,:inwards}) where {T,RT,TP,TT} = + EllipsoidMantle{T,RT,TP,TT,:outwards}(em.r, em.φ, em.θ, em.origin, em.rotation ) const FullSphereMantle{T,D} = EllipsoidMantle{T,T,Nothing,Nothing,D} const FullEllipsoidMantle{T,D} = EllipsoidMantle{T,NTuple{3,T},Nothing,Nothing,D} @@ -29,14 +29,14 @@ end extremum(e::EllipsoidMantle{T,T}) where {T} = e.r extremum(e::EllipsoidMantle{T,NTuple{3,T}}) where {T} = max(e.r) -function normal(em::EllipsoidMantle{T,NTuple{3,T},PT,TT,:outwards}, pt::CartesianPoint{T}) where {T,PT,TT} +function normal(em::EllipsoidMantle{T,NTuple{3,T},TP,TT,:outwards}, pt::CartesianPoint{T}) where {T,TP,TT} # not normalized, do we want this? # Or wrap this into somehting like `normal(em, pt) = normalize(direction(em, pt))` ? p = _transform_into_object_coordinate_system(pt, em) obj_normal = CartesianPoint{T}(sign(p.x)*(p.x/em.r[1])^2, sign(p.y)*(p.y/em.r[2])^2, sign(p.z)*(p.z/em.r[3])^2) # We might want to store the inv(em.r) in the struct? CartesianVector(_transform_into_global_coordinate_system(obj_normal, em)) end -normal(em::EllipsoidMantle{T,RT,PT,TT,:inwards}, pt::CartesianPoint{T}) where {T,RT,PT,TT} = -normal(flip(em), pt) +normal(em::EllipsoidMantle{T,RT,TP,TT,:inwards}, pt::CartesianPoint{T}) where {T,RT,TP,TT} = -normal(flip(em), pt) """ intersection(cm::EllipsoidMantle{T,NTuple{3,T}}, l::Line{T}) where {T} diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl index 5ad8a873b..5d9ab7504 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl @@ -1,18 +1,18 @@ -@with_kw struct Ellipsoid{T,CO,RT,PT,TT} <: AbstractVolumePrimitive{T, CO} +@with_kw struct Ellipsoid{T,CO,RT,TP,TT} <: AbstractVolumePrimitive{T, CO} r::RT = 1 - φ::PT = nothing + φ::TP = nothing θ::TT = nothing origin::CartesianPoint{T} = zero(CartesianPoint{T}) rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -Ellipsoid{T,CO,RT,PT,TT}( e::Ellipsoid{T,CO,RT,PT,TT}; COT = CO, +Ellipsoid{T,CO,RT,TP,TT}( e::Ellipsoid{T,CO,RT,TP,TT}; COT = CO, origin::CartesianPoint{T} = e.origin, - rotation::SMatrix{3,3,T,9} = e.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},RT,PT,TT} = - Ellipsoid{T,COT,RT,PT,TT}(e.r, e.φ, e.θ, origin, rotation) + rotation::SMatrix{3,3,T,9} = e.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},RT,TP,TT} = + Ellipsoid{T,COT,RT,TP,TT}(e.r, e.φ, e.θ, origin, rotation) -const Sphere{T,CO,PT,TT} = Ellipsoid{T,CO,T,PT,TT} +const Sphere{T,CO,TP,TT} = Ellipsoid{T,CO,T,TP,TT} const FullSphere{T,CO} = Ellipsoid{T,CO,T,Nothing,Nothing} const FullEllipsoid{T,CO} = Ellipsoid{T,CO,NTuple{3,T},Nothing,Nothing} From b7f888c4f10ab502e9c87032acf2971e420a77aa Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 24 Jun 2021 13:44:46 +0200 Subject: [PATCH 218/241] Add `surfaces` methods for `FullTorus` --- src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl index ae16b8e7f..783e25898 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl @@ -27,6 +27,15 @@ function Geometry(::Type{T}, ::Type{Torus}, dict::AbstractDict, input_units::Nam transform(t, transformations) end +function surfaces(t::FullTorus{T,ClosedPrimitive}) where {T} + tm = FullTorusMantle{T,:inwards}(t.r_torus, t.r_tube, t.φ, t.θ, t.origin, t.rotation) + (tm, ) +end +function surfaces(t::FullTorus{T,OpenPrimitive}) where {T} + tm = FullTorusMantle{T,:outwards}(t.r_torus, t.r_tube, t.φ, t.θ, t.origin, t.rotation) + (tm, ) +end + # #Constructors # function Torus(;r_torus = 1, r_tubeMin = 0, r_tubeMax = 1, φMin = 0, φMax = 2π, θMin = 0, θMax = 2π, z = 0) # T = float(promote_type(typeof.((r_torus, r_tubeMin, r_tubeMax, φMin, φMax, θMin, θMax, z))...)) From c9e3eecc6f372ca62fe0546a0b011582a5809058 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 24 Jun 2021 13:45:03 +0200 Subject: [PATCH 219/241] Add `lines` method for `FullTorusMantle` --- .../SurfacePrimitives/TorusMantle.jl | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl index 51e12bc77..75b07a0e2 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl @@ -9,10 +9,28 @@ end flip(t::TorusMantle{T,TP,TT,:inwards}) where {T,TP,TT} = - TorusMantle{T,TP,TT,:outwards}(t.r_torus, t.r_tube, t.φ, t.θ, t.origin, t.rotation ) +TorusMantle{T,TP,TT,:outwards}(t.r_torus, t.r_tube, t.φ, t.θ, t.origin, t.rotation ) const FullTorusMantle{T,D} = TorusMantle{T,Nothing,Nothing,D} +function lines(tm::FullTorusMantle{T}) where {T} + top_circ_origin = CartesianPoint{T}(zero(T), zero(T), tm.r_tube) + top_circ_origin = _transform_into_global_coordinate_system(top_circ_origin, tm) + top_circ = Circle{T}(r = tm.r_torus, origin = top_circ_origin, rotation = tm.rotation) + bot_circ_origin = CartesianPoint{T}(zero(T), zero(T), -tm.r_tube) + bot_circ_origin = _transform_into_global_coordinate_system(bot_circ_origin, tm) + bot_circ = Circle{T}(r = tm.r_torus, origin = bot_circ_origin, rotation = tm.rotation) + inner_circ = Circle{T}(r = tm.r_torus - tm.r_tube, origin = tm.origin, rotation = tm.rotation) + outer_circ = Circle{T}(r = tm.r_torus + tm.r_tube, origin = tm.origin, rotation = tm.rotation) + tube_circ_1_origin = CartesianPoint{T}(tm.r_torus, zero(T), zero(T)) + tube_circ_1_origin = _transform_into_global_coordinate_system(tube_circ_1_origin, tm) + tube_circ_1 = Circle{T}(r = tm.r_tube, origin = tube_circ_1_origin, rotation = tm.rotation * RotX(T(π)/2)) + tube_circ_2_origin = CartesianPoint{T}(-tm.r_torus, zero(T), zero(T)) + tube_circ_2_origin = _transform_into_global_coordinate_system(tube_circ_2_origin, tm) + tube_circ_2 = Circle{T}(r = tm.r_tube, origin = tube_circ_2_origin, rotation = tm.rotation * RotX(T(π)/2)) + (bot_circ, outer_circ, top_circ, inner_circ, tube_circ_1, tube_circ_2) +end + # #Constructors # TorusMantle(t::Torus{T}; r_tube = 1) where {T} = TorusMantle( T, t.r_torus, T(r_tube), t.φ, t.θ, t.z) From c855b8e08d13d3ece9c830be8ca432f94ba8cc89 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 24 Jun 2021 13:46:58 +0200 Subject: [PATCH 220/241] Add simple plotting of `FullTorus` --- .../SurfacePrimitives/SurfacePrimitives.jl | 1 + .../plotting/SurfacePrimitives/TorusMantle.jl | 116 ++++++++++++------ 2 files changed, 81 insertions(+), 36 deletions(-) diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl index d7804b67f..404f8b5e6 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/SurfacePrimitives.jl @@ -2,6 +2,7 @@ include("Polygon.jl") include("EllipticalSurface.jl") include("ConeMantle.jl") include("EllipsoidMantle.jl") +include("TorusMantle.jl") @recipe function f(vp::AbstractVector{<:AbstractSurfacePrimitive}) linecolor --> :black diff --git a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/TorusMantle.jl b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/TorusMantle.jl index f5cda393e..a8b633009 100644 --- a/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/TorusMantle.jl +++ b/src/ConstructiveSolidGeometry/plotting/SurfacePrimitives/TorusMantle.jl @@ -1,43 +1,87 @@ -function get_plot_points(t::TorusMantle{T}; n = 30) where {T <: AbstractFloat} - plot_points = Vector{CartesianPoint{T}}[] - φMin::T, φMax::T, φ_is_full_2π::Bool = get_φ_limits(t) - θMin::T, θMax::T, θ_is_full_2π::Bool = get_θ_limits(t) - sθMin, cθMin = sincos(θMin) - - r1 = T(t.r_torus + t.r_tube*cθMin) - z1 = T(t.r_tube*sθMin) + t.z - θ2 = θ_is_full_2π ? π : θMax - sθ2, cθ2 = sincos(θ2) - r2 = T(t.r_torus + t.r_tube*cθ2) - z2 = T(t.r_tube*sθ2) + t.z - - append!(plot_points, get_plot_points(CylindricalAnnulus(T,r1..r1,t.φ,z1), n = n)) - append!(plot_points, get_plot_points(CylindricalAnnulus(T,r2..r2,t.φ,z2), n = n)) - for φ in (φ_is_full_2π ? [φMin] : [φMin, φMax]) - append!(plot_points, get_plot_points(ToroidalAnnulus(T,t.r_torus,t.r_tube..t.r_tube,φ,t.θ,t.z), n = n)) +@recipe function f(tm::TorusMantle, n = 40; subn = 10) + ls = lines(tm) + linecolor --> :black + @series begin + label --> "Ellipsoid Mantle" + ls[1] end - plot_points + for i in 2:length(ls) + @series begin + label := nothing + ls[i] + end + end + # if (!haskey(plotattributes, :show_normal) || plotattributes[:show_normal]) && + # em.φ === nothing && em.θ === nothing + # @series begin + # label := nothing + # seriestype := :vector + # pts = _plt_points_for_normals(em) + # ns = broadcast(p -> normal(em, p) / 5, pts) + # [(pts[i], ns[i]) for i in eachindex(pts)] + # end + # end end -function mesh(t::TorusMantle{T}; n = 30) where {T <: AbstractFloat} - φMin::T, φMax::T, _ = get_φ_limits(t) - θMin::T, θMax::T, _ = get_θ_limits(t) +# function _plt_points_for_normals(em::EllipsoidMantle{T,NTuple{3,T}}) where {T} +# pts = [ CartesianPoint{T}( em.r[1], zero(T), zero(T)), +# CartesianPoint{T}(-em.r[1], zero(T), zero(T)), +# CartesianPoint{T}(zero(T), em.r[2], zero(T)), +# CartesianPoint{T}(zero(T), -em.r[2], zero(T)), +# CartesianPoint{T}(zero(T), zero(T), em.r[3]), +# CartesianPoint{T}(zero(T), zero(T), -em.r[3]) ] +# _transform_into_global_coordinate_system(pts, em) +# end +# function _plt_points_for_normals(em::EllipsoidMantle{T,T}) where {T} +# pts = [ CartesianPoint{T}( em.r, zero(T), zero(T)), +# CartesianPoint{T}(-em.r, zero(T), zero(T)), +# CartesianPoint{T}(zero(T), em.r, zero(T)), +# CartesianPoint{T}(zero(T), -em.r, zero(T)), +# CartesianPoint{T}(zero(T), zero(T), em.r), +# CartesianPoint{T}(zero(T), zero(T), -em.r) ] +# _transform_into_global_coordinate_system(pts, em) +# end - fφ = (φMax - φMin)/(2π) - nφ = Int(ceil(n*fφ)) +# function get_plot_points(t::TorusMantle{T}; n = 30) where {T <: AbstractFloat} +# plot_points = Vector{CartesianPoint{T}}[] +# φMin::T, φMax::T, φ_is_full_2π::Bool = get_φ_limits(t) +# θMin::T, θMax::T, θ_is_full_2π::Bool = get_θ_limits(t) +# sθMin, cθMin = sincos(θMin) - fθ = (θMax - θMin)/(2π) - nθ = Int(ceil(n*fθ)) +# r1 = T(t.r_torus + t.r_tube*cθMin) +# z1 = T(t.r_tube*sθMin) + t.z +# θ2 = θ_is_full_2π ? π : θMax +# sθ2, cθ2 = sincos(θ2) +# r2 = T(t.r_torus + t.r_tube*cθ2) +# z2 = T(t.r_tube*sθ2) + t.z - θrange = range(θMin, θMax, length = nθ + 1) - sθrange = sin.(θrange) - cθrange = cos.(θrange) - φrange = range(φMin, φMax, length = nφ + 1) - sφrange = sin.(φrange) - cφrange = cos.(φrange) +# append!(plot_points, get_plot_points(CylindricalAnnulus(T,r1..r1,t.φ,z1), n = n)) +# append!(plot_points, get_plot_points(CylindricalAnnulus(T,r2..r2,t.φ,z2), n = n)) +# for φ in (φ_is_full_2π ? [φMin] : [φMin, φMax]) +# append!(plot_points, get_plot_points(ToroidalAnnulus(T,t.r_torus,t.r_tube..t.r_tube,φ,t.θ,t.z), n = n)) +# end +# plot_points +# end - X = [(t.r_torus + t.r_tube*cθ)*cφ for cφ in cφrange, cθ in cθrange] - Y = [(t.r_torus + t.r_tube*cθ)*sφ for sφ in sφrange, cθ in cθrange] - Z = [t.r_tube*sθ + t.z for i in 1:nφ+1, sθ in sθrange] - Mesh(X, Y, Z) -end +# function mesh(t::TorusMantle{T}; n = 30) where {T <: AbstractFloat} +# φMin::T, φMax::T, _ = get_φ_limits(t) +# θMin::T, θMax::T, _ = get_θ_limits(t) + +# fφ = (φMax - φMin)/(2π) +# nφ = Int(ceil(n*fφ)) + +# fθ = (θMax - θMin)/(2π) +# nθ = Int(ceil(n*fθ)) + +# θrange = range(θMin, θMax, length = nθ + 1) +# sθrange = sin.(θrange) +# cθrange = cos.(θrange) +# φrange = range(φMin, φMax, length = nφ + 1) +# sφrange = sin.(φrange) +# cφrange = cos.(φrange) + +# X = [(t.r_torus + t.r_tube*cθ)*cφ for cφ in cφrange, cθ in cθrange] +# Y = [(t.r_torus + t.r_tube*cθ)*sφ for sφ in sφrange, cθ in cθrange] +# Z = [t.r_tube*sθ + t.z for i in 1:nφ+1, sθ in sθrange] +# Mesh(X, Y, Z) +# end From 279e35076e1da48971bce143f23f84f4b36790cc Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Thu, 24 Jun 2021 13:53:00 +0200 Subject: [PATCH 221/241] Lazy workaround for hollow `Torus` --- .../VolumePrimitives/Torus.jl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl index 783e25898..fce27d394 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl @@ -22,8 +22,15 @@ function Geometry(::Type{T}, ::Type{Torus}, dict::AbstractDict, input_units::Nam r_tube = _parse_radial_interval(T, dict["r_tube"], length_unit) φ = parse_φ_of_primitive(T, dict, angle_unit) θ = parse_θ_of_primitive(T, dict, angle_unit) - t = Torus{T,ClosedPrimitive,typeof(r_tube),typeof(φ),typeof(θ)}( - r_torus = r_torus, r_tube = r_tube, φ =φ, θ = θ) + t = if r_tube isa Real + Torus{T,ClosedPrimitive,typeof(r_tube),typeof(φ),typeof(θ)}( + r_torus = r_torus, r_tube = r_tube, φ =φ, θ = θ) + else + Torus{T,ClosedPrimitive,typeof(r_tube[2]),typeof(φ),typeof(θ)}( + r_torus = r_torus, r_tube = r_tube[2], φ =φ, θ = θ) - + Torus{T,ClosedPrimitive,typeof(r_tube[1]),typeof(φ),typeof(θ)}( + r_torus = r_torus, r_tube = r_tube[1], φ =φ, θ = θ) + end transform(t, transformations) end From f62455bb1ee6a2bd60cd2153d76d5d0cde2f08a5 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 25 Jun 2021 14:21:49 +0200 Subject: [PATCH 222/241] Add Package `Polynomials.jl` --- Project.toml | 1 + src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl | 1 + 2 files changed, 2 insertions(+) diff --git a/Project.toml b/Project.toml index f1de78ad8..11b7f5f32 100644 --- a/Project.toml +++ b/Project.toml @@ -17,6 +17,7 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" ParallelProcessingTools = "8e8a01fc-6193-5ca1-a2f1-20776dae4199" Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a" PolygonOps = "647866c9-e3ac-4575-94e7-e3d426903924" +Polynomials = "f27b6e38-b328-58d1-80ce-0feddd5e7a45" ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca" RadiationDetectorSignals = "bf2c0563-65cf-5db2-a620-ceb7de82658c" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index 2d4f337b7..04cdac9b8 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -10,6 +10,7 @@ module ConstructiveSolidGeometry using IntervalSets using Parameters using PolygonOps + using Polynomials using RecipesBase using Rotations using StaticArrays From a9d4025888e942f73c51a9efebdaad259da0a821 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 25 Jun 2021 14:22:31 +0200 Subject: [PATCH 223/241] Add `_in` method for `FullTorus` --- .../VolumePrimitives/Torus.jl | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl index fce27d394..06fcd1f59 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl @@ -1,6 +1,6 @@ @with_kw struct Torus{T,CO,TR,TP,TT} <: AbstractVolumePrimitive{T,CO} r_torus::T = 1 - r_tube::TR = 1 + r_tube::TR = 1 # (r_tube_in, r_tube_out) φ::TP = nothing θ::TT = nothing @@ -43,6 +43,15 @@ function surfaces(t::FullTorus{T,OpenPrimitive}) where {T} (tm, ) end +function _in(pt::CartesianPoint{T}, t::FullTorus{T,ClosedPrimitive}) where {T} + _r = hypot(hypot(pt.x, pt.y) - t.r_torus, pt.z) + return _r <= t.r_tube || csg_isapprox_lin(_r, t.r_tube) +end +function _in(pt::CartesianPoint{T}, t::FullTorus{T,OpenPrimitive}) where {T} + _r = hypot(hypot(pt.x, pt.y) - t.r_torus, pt.z) + return _r < t.r_tube +end + # #Constructors # function Torus(;r_torus = 1, r_tubeMin = 0, r_tubeMax = 1, φMin = 0, φMax = 2π, θMin = 0, θMax = 2π, z = 0) # T = float(promote_type(typeof.((r_torus, r_tubeMin, r_tubeMax, φMin, φMax, θMin, θMax, z))...)) From 1987f1d81a687b4ebba1dd0057d594e8187d48a1 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 25 Jun 2021 14:23:27 +0200 Subject: [PATCH 224/241] Add method `intersection` for `TorusMantle` and `Line` --- .../SurfacePrimitives/TorusMantle.jl | 127 ++++++++++++++++-- 1 file changed, 117 insertions(+), 10 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl index 75b07a0e2..f78e8b4cc 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/TorusMantle.jl @@ -31,6 +31,113 @@ function lines(tm::FullTorusMantle{T}) where {T} (bot_circ, outer_circ, top_circ, inner_circ, tube_circ_1, tube_circ_2) end +extremum(tm::TorusMantle{T}) where {T} = tm.r_torus + tm.r_tube + +""" + intersection(tm::TorusMantle{T}, l::Line{T}) where {T} + +The function will always return 4 CartesianPoint's. +If the line just touches the mantle, the points will be the same. +If the line does not touch the mantle at all, the points will have NaN's as there coordinates. + +Solve: `solve (sqrt((L1 + λ*D1)^2 + (L2 + λ*D2)^2)-R)^2 + (L3 + λ*D3)^2 = r^2 for λ` +""" +function intersection(tm::TorusMantle{T}, l::Line{T}) where {T} + obj_l = _transform_into_object_coordinate_system(l, tm) # direction is not normalized + + L1 = obj_l.origin.x + L2 = obj_l.origin.y + L3 = obj_l.origin.z + D1 = obj_l.direction.x + D2 = obj_l.direction.y + D3 = obj_l.direction.z + + R = tm.r_torus + r = tm.r_tube + + A = L1^2 + L2^2 + L3^2 + R^2 - r^2 + B = 2*(L1*D1 + L2*D2 + L3*D3) + C = D1^2 + D2^2 + D3^2 + + a = (2*B*C) / C^2 + b = (2*A*C + B^2 - 4*R^2*(D1^2 + D2^2)) / C^2 + c = (2*A*B - 8*R^2*(L1*D1 + L2*D2)) / C^2 + d = (A^2 - 4*R^2*(L1^2 + L2^2)) / C^2 + + # λ1, λ2, λ3, λ4 = roots_of_4th_order_polynomial(a, b, c, d) # That does not work for all combinations of a, b, c, d... + # fallback to Polynomials.jl, which is slower... We should improve `roots_of_4th_order_polynomial`... + λ1, λ2, λ3, λ4 = real.(Polynomials.roots(Polynomial((d, c, b, a, one(T))))) + + ints1 = obj_l.origin + λ1 * obj_l.direction + ints2 = obj_l.origin + λ2 * obj_l.direction + ints3 = obj_l.origin + λ3 * obj_l.direction + ints4 = obj_l.origin + λ4 * obj_l.direction + return _transform_into_global_coordinate_system(ints1, tm), + _transform_into_global_coordinate_system(ints2, tm), + _transform_into_global_coordinate_system(ints3, tm), + _transform_into_global_coordinate_system(ints4, tm) +end + + +""" + roots_of_4th_order_polynomial(a::T, b::T, c::T, d::T, e::T) + +Calculate the 4 (possible) roots of `x^4 + ax^3 + bx^2 + cx + d = 0` +""" +function roots_of_4th_order_polynomial(a::T, b::T, c::T, d::T) where {T} + #= + using Polynomials + A, a, b, c, d = 1.0, 0.2, -5.0, -0.1, 2.5 + p = Polynomial(SVector{5,T}([d, c, b, a, A])) + xs = -2.5:0.01:2.5; plot(xs, map(x -> p(x), xs)) + roots(p) + + rs = CSG.roots_of_4th_order_polynomial(a, b, c, d) + vline!([rs...]) + @btime CSG.roots_of_4th_order_polynomial($a, $b, $c, $d) + =# + + # There are some issues for certain combinations of a, b, c, d, ... + + term_1_1_1_1 = 2*b^3 - 9*a*b*c + 27*c^2 + 27*a^2*d - 72*b*d + term_1_1_1_2 = b^2 - 3*a*c + 12*d + + comp_term = -4 * term_1_1_1_2^3 + term_1_1_1_1^2 + + term_1_1_1_3 = term_1_1_1_1 + sqrt(Complex(comp_term)) + term_1_1_1 = 3*(term_1_1_1_3^(1/3)) + + term_1_1 = 2^(1/3) * term_1_1_1_2 / term_1_1_1 + term_1_2 = (term_1_1_1_3 / 54)^(1/3) + term_1 = a^2/4 - 2b/3 + term_1_1 + term_1_2 + + if term_1 == 0 + term_6 = sqrt(Complex(b^2 - 4d)) + λ1 = sqrt(-term_6 - b)/sqrt(2) + λ2 = -λ1 + λ3 = sqrt( term_6 - b)/sqrt(2) + λ4 = -λ3 + else + term_2_1 = (-a^3 + 4a*b - 8c) / (4*sqrt(term_1)) + term_2a = a^2/2 - 4b/3 - term_1_2 - term_1_2 - term_2_1 + term_2b = a^2/2 - 4b/3 - term_1_1 - term_1_2 + term_2_1 + + term3 = sqrt(term_1)/2 + term4a = sqrt(term_2a)/2 + term4b = sqrt(term_2b)/2 + term5 = -a/4 + + λ1 = term5 - term3 - term4a + λ2 = term5 - term3 + term4a + λ3 = term5 + term3 - term4b + λ4 = term5 + term3 + term4b + end + real(λ1), real(λ2), real(λ3), real(λ4) +end + + + + # #Constructors # TorusMantle(t::Torus{T}; r_tube = 1) where {T} = TorusMantle( T, t.r_torus, T(r_tube), t.φ, t.θ, t.z) @@ -71,21 +178,21 @@ end # function sample(t::TorusMantle{T}, step::Real) where {T} # φMin::T, φMax::T, _ = get_φ_limits(t) # θMin::T, θMax::T, _ = get_θ_limits(t) -# samples = [ +# samples = ( # CylindricalPoint{T}(get_r_at_θ(t,θ),φ,t.r_tube*sin(θ)+t.z) # for φ in (t.r_tube == 0 ? φMin : φMin:step/t.r_tube:φMax) # for θ in (t.r_tube == 0 ? θMin : θMin:step/t.r_tube:θMax) -# ] +# ) # end # function sample(t::TorusMantle{T}, Nsamps::NTuple{3,Int}) where {T} # φMin::T, φMax::T, _ = get_φ_limits(t) # θMin::T, θMax::T, _ = get_θ_limits(t) -# samples = [ +# samples = ( # CylindricalPoint{T}(get_r_at_θ(t,θ),φ,t.r_tube*sin(θ)+t.z) -# for φ in (Nsamps[2] ≤ 1 ? φMin : range(φMin, φMax, length = Nsamps[2])) -# for θ in (Nsamps[3] ≤ 1 ? θMin : range(θMin, θMax, length = Nsamps[3])) -# ] +# for φ in (Nsamps(2) ≤ 1 ? φMin : range(φMin, φMax, length = Nsamps(2))) +# for θ in (Nsamps(3) ≤ 1 ? θMin : range(θMin, θMax, length = Nsamps(3))) +# ) # end @@ -95,13 +202,13 @@ end # end # function sample(t::TorusMantle{T}, g::CylindricalTicksTuple{T})::Vector{CylindricalPoint{T}} where {T} -# samples::Vector{CylindricalPoint{T}} = [ +# samples::Vector{CylindricalPoint{T}} = ( # CylindricalPoint{T}(r,φ,z) # for z in _get_z_ticks(t, g) # for φ in get_φ_ticks(t, g) # for r in (t.r_torus - sqrt(t.r_tube^2 - (z - t.z)^2), t.r_torus + sqrt(t.r_tube^2 - (z - t.z)^2)) # if t.θ === nothing || _in_angular_interval_closed(mod(atan(z - t.z, r - t.r_torus), T(2π)), t.θ) -# ] +# ) # end @@ -132,14 +239,14 @@ end # end # function sample(t::TorusMantle{T}, g::CartesianTicksTuple{T})::Vector{CartesianPoint{T}} where {T} -# samples::Vector{CartesianPoint{T}} = [ +# samples::Vector{CartesianPoint{T}} = ( # CartesianPoint{T}(x,y,z) # for z in _get_z_ticks(t, g) # for x in _get_x_at_z(t, g, z) # for y in _get_y_at_z(t, x, z) # if (t.φ === nothing || mod(atan(y, x), T(2π)) in t.φ) && # (t.θ === nothing || _in_angular_interval_closed(mod(atan(z - t.z, hypot(x, y) - t.r_torus), T(2π)), t.θ)) -# ] +# ) # end # Arc(t::TorusMantle{T}) where {T} = Arc(T, t.r_tube, PlanarPoint{T}(t.r_torus,t.z), t.θ) From 84058b5cf9fde56e811fc72fe0789120fd0c5963 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 25 Jun 2021 14:24:15 +0200 Subject: [PATCH 225/241] Add keywords to `csg_round_` and `csg_isapprox_` --- src/ConstructiveSolidGeometry/GeometryRounding.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ConstructiveSolidGeometry/GeometryRounding.jl b/src/ConstructiveSolidGeometry/GeometryRounding.jl index fb712a4b7..7d0f30d71 100644 --- a/src/ConstructiveSolidGeometry/GeometryRounding.jl +++ b/src/ConstructiveSolidGeometry/GeometryRounding.jl @@ -1,6 +1,6 @@ -csg_round_lin(x::T) where {T} = round(x, sigdigits = 9) # min. Δx = 1 nm -csg_round_lin(x::Float32) where {T} = round(x, sigdigits = 5) # min. Δx = 10 μm -csg_round_rad(φ::T) where {T} = round(φ, digits = 4) # min. Δφ ≈ 0.011 ° +csg_round_lin(x::T; sigdigits::Int = 9) where {T} = round(x, sigdigits = sigdigits) # min. Δx = 1 nm +csg_round_lin(x::Float32; sigdigits::Int = 5) where {T} = round(x, sigdigits = sigdigits) # min. Δx = 10 μm +csg_round_rad(φ::T; digits::Int = 4) where {T} = round(φ, digits = digits) # min. Δφ ≈ 0.011 ° -csg_isapprox_lin(x::T, y::T) where {T} = csg_round_lin(x) == csg_round_lin(y) #abs(x - y) < T(1e-9) -csg_isapprox_rad(α::T, β::T) where {T} = csg_round_rad(α) == csg_round_rad(β) #abs(x - y) < T(1e-4) \ No newline at end of file +csg_isapprox_lin(x::T, y::T; Δ::T = T(1e-9)) where {T} = abs(x - y) < Δ +csg_isapprox_rad(α::T, β::T; Δ::T = T(1e-4)) where {T} = abs(α - β) < Δ \ No newline at end of file From 96cc3c30ee550aa4edd0a053491df468c557917d Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 25 Jun 2021 14:41:31 +0200 Subject: [PATCH 226/241] Activate `CoaxialTorus` detector in tests again --- test/runtests.jl | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 84647f65b..fd230e6a7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -98,19 +98,19 @@ end @info signalsum @test isapprox( signalsum, T(2), atol = 5e-4 ) end -# @testset "Simulate example detector: Toroidal" begin -# sim = Simulation{T}(SSD_examples[:CoaxialTorus]) -# SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) -# simulate!(sim, max_refinements = 1, verbose = true) -# evt = Event([CartesianPoint{T}(0.01,0,0.003)]) -# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) -# signalsum = T(0) -# for i in 1:length(evt.waveforms) -# signalsum += abs(evt.waveforms[i].value[end]) -# end -# @info signalsum -# @test isapprox( signalsum, T(2), atol = 5e-4 ) -# end + @testset "Simulate example detector: Toroidal" begin + sim = Simulation{T}(SSD_examples[:CoaxialTorus]) + SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) + simulate!(sim, max_refinements = 1, verbose = true) + evt = Event([CartesianPoint{T}(0.01,0,0.003)]) + simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) + signalsum = T(0) + for i in 1:length(evt.waveforms) + signalsum += abs(evt.waveforms[i].value[end]) + end + @info signalsum + @test isapprox( signalsum, T(2), atol = 5e-3 ) + end # =# # @testset "Simulate example detector: SigGen PPC" begin # sim = Simulation{T}(SSD_examples[:SigGen]) From 7aa2d3d69ec4fcd5096223ae172d251c883aa677 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 25 Jun 2021 14:54:55 +0200 Subject: [PATCH 227/241] Activate `SigGen` detector in tests again --- test/runtests.jl | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index fd230e6a7..7b7e58252 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -111,19 +111,18 @@ end @info signalsum @test isapprox( signalsum, T(2), atol = 5e-3 ) end -# =# -# @testset "Simulate example detector: SigGen PPC" begin -# sim = Simulation{T}(SSD_examples[:SigGen]) -# simulate!(sim, max_refinements = 0, verbose = true) -# evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 40e-3 )])) -# simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) -# signalsum = T(0) -# for i in 1:length(evt.waveforms) -# signalsum += abs(evt.waveforms[i].value[end]) -# end -# @info signalsum -# @test isapprox( signalsum, T(2), atol = 5e-4 ) -# end + @testset "Simulate example detector: SigGen PPC" begin + sim = Simulation{T}(SSD_examples[:SigGen]) + simulate!(sim, max_refinements = 0, verbose = true) + evt = Event(CartesianPoint.([CylindricalPoint{T}(20e-3, deg2rad(10), 40e-3 )])) + simulate!(evt, sim, Δt = 1e-9, max_nsteps = 10000) + signalsum = T(0) + for i in 1:length(evt.waveforms) + signalsum += abs(evt.waveforms[i].value[end]) + end + @info signalsum + @test isapprox( signalsum, T(2), atol = 2e-3 ) + end end # @testset "ADLChargeDriftModel" begin From dfe43acdf56b4861e6683f752493f96d584c673b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 25 Jun 2021 14:57:18 +0200 Subject: [PATCH 228/241] Activate `ADLChargeDriftModel` tests again --- test/ADLChargeDriftModel.jl | 6 +++++- test/runtests.jl | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/ADLChargeDriftModel.jl b/test/ADLChargeDriftModel.jl index 4d9bcd0e2..53234f510 100644 --- a/test/ADLChargeDriftModel.jl +++ b/test/ADLChargeDriftModel.jl @@ -1,4 +1,4 @@ -using SolidStateDetectors: getVe, getVh, Vl, geom_sigdigits +using SolidStateDetectors: getVe, getVh, Vl using StaticArrays using LinearAlgebra @@ -7,6 +7,10 @@ config_dict = Dict( "Silicon" => joinpath(@__DIR__,"../examples/example_config_files/ADLChargeDriftModel/drift_velocity_Si_300K_config.json") ) +geom_sigdigits(::Type{Int64})::Int = 12 +geom_sigdigits(::Type{Float32})::Int = 6 +geom_sigdigits(::Type{Float64})::Int = 12 + for T in (Float32, Float64) @testset "Precision type: $(T)" begin diff --git a/test/runtests.jl b/test/runtests.jl index 7b7e58252..ffa58d91e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -125,9 +125,9 @@ end end end -# @testset "ADLChargeDriftModel" begin -# include("ADLChargeDriftModel.jl") -# end +@testset "ADLChargeDriftModel" begin + include("ADLChargeDriftModel.jl") +end # include("ConstructiveSolidGeometry/CSG_test.jl") # include("ConstructiveSolidGeometry/CSG_IO.jl") From 36fac446be80854efcbe5856c70708b8d6fdd945 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 25 Jun 2021 15:10:40 +0200 Subject: [PATCH 229/241] Adjust CSG IO tests and activate them again --- test/ConstructiveSolidGeometry/CSG_IO.jl | 16 +++++++++------- test/runtests.jl | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/test/ConstructiveSolidGeometry/CSG_IO.jl b/test/ConstructiveSolidGeometry/CSG_IO.jl index b0c862563..aa6ec3f5d 100644 --- a/test/ConstructiveSolidGeometry/CSG_IO.jl +++ b/test/ConstructiveSolidGeometry/CSG_IO.jl @@ -4,11 +4,12 @@ using IntervalSets using LinearAlgebra using JSON using YAML +using StaticArrays import SolidStateDetectors.ConstructiveSolidGeometry: Geometry using SolidStateDetectors.ConstructiveSolidGeometry: internal_unit_length, internal_unit_angle, - Box, Cone, HexagonalPrism, Sphere, Torus, Tube + Box, Cone, HexagonalPrism, Ellipsoid, Torus T = Float64 @@ -21,16 +22,17 @@ function Geometry(::Type{T}, filename::String, input_units::NamedTuple = (length else @error "Only JSON and YAML formats are supported at the moment." end - Geometry(T, dict, input_units) + transformation = (rotation = one(SMatrix{3, 3, T, 9}), translation = zero(CartesianVector{T})) + Geometry(T, dict, input_units, transformation) end example_primitive_dir = joinpath(@__DIR__, "../../examples/example_primitive_files") @testset "Test primitive read-in" begin @test typeof(Geometry(T, joinpath(example_primitive_dir, "Box.yaml"))) <: Box{T} - @test typeof(Geometry(T, joinpath(example_primitive_dir, "Cone.yaml"))) <: Cone{T, <:Tuple} - @test typeof(Geometry(T, joinpath(example_primitive_dir, "HexagonalPrism.yaml"))) <: HexagonalPrism{T} - @test typeof(Geometry(T, joinpath(example_primitive_dir, "Sphere.yaml"))) <: Sphere{T} - @test typeof(Geometry(T, joinpath(example_primitive_dir, "Torus.yaml"))) <: Torus{T} - @test typeof(Geometry(T, joinpath(example_primitive_dir, "Tube.yaml"))) <: Cone{T, <:Union{T, AbstractInterval{T}}} + @test typeof(Geometry(T, joinpath(example_primitive_dir, "Cone.yaml"))) <: Cone{T, <:Any, <:Tuple} + @test typeof(Geometry(T, joinpath(example_primitive_dir, "HexagonalPrism.yaml")).a) <: HexagonalPrism{T} + @test typeof(Geometry(T, joinpath(example_primitive_dir, "Sphere.yaml"))) <: Ellipsoid{T} + @test typeof(Geometry(T, joinpath(example_primitive_dir, "Torus.yaml")).a) <: Torus{T} + @test typeof(Geometry(T, joinpath(example_primitive_dir, "Tube.yaml"))) <: Cone{T, <:Any, <:Tuple} end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index ffa58d91e..ea1cd7b89 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -130,5 +130,5 @@ end end # include("ConstructiveSolidGeometry/CSG_test.jl") -# include("ConstructiveSolidGeometry/CSG_IO.jl") +include("ConstructiveSolidGeometry/CSG_IO.jl") # include("ConstructiveSolidGeometry/CSG_decomposition.jl") \ No newline at end of file From 1f61e6c14c140b4f46b3690d9982bc36115301c0 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Fri, 25 Jun 2021 16:47:24 +0200 Subject: [PATCH 230/241] Update test limit --- test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index ea1cd7b89..7a3fa4426 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -109,7 +109,7 @@ end signalsum += abs(evt.waveforms[i].value[end]) end @info signalsum - @test isapprox( signalsum, T(2), atol = 5e-3 ) + @test isapprox( signalsum, T(2), atol = 2e-2 ) end @testset "Simulate example detector: SigGen PPC" begin sim = Simulation{T}(SSD_examples[:SigGen]) From 68cef363586f980c00c35196e7d26cf531987736 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 28 Jun 2021 15:08:20 +0200 Subject: [PATCH 231/241] Adjust to `OpenPrimitives` in `CSGDifference`s --- .../example_config_files/public_spherical_detector_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_config_files/public_spherical_detector_config.json b/examples/example_config_files/public_spherical_detector_config.json index 3705b1b0f..91a8494f3 100644 --- a/examples/example_config_files/public_spherical_detector_config.json +++ b/examples/example_config_files/public_spherical_detector_config.json @@ -114,7 +114,7 @@ }, "z": { "from": 0.0, - "to": 30.0 + "to": 35.0 } } } From 29d73bc1a607af060c2ade0650060e9a125e389e Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 28 Jun 2021 15:08:37 +0200 Subject: [PATCH 232/241] Remove obsolete line --- test/runtests.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index 7a3fa4426..472339825 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -87,7 +87,6 @@ end end @testset "Simulate example detector: Spherical" begin sim = Simulation{T}(SSD_examples[:Spherical]) - SolidStateDetectors.apply_initial_state!(sim, ElectricPotential) simulate!(sim, max_refinements = 1, verbose = true) evt = Event([CartesianPoint{T}(0,0,0)]) simulate!(evt, sim) From 8a1c8e377b5a18d7aab349df648e7bd19972b5b6 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 28 Jun 2021 15:09:28 +0200 Subject: [PATCH 233/241] Add `csgtol` keyword to `_in` --- src/ConstructiveSolidGeometry/CSG.jl | 9 +- .../ConstructiveSolidGeometry.jl | 6 +- .../GeometryRounding.jl | 6 +- src/ConstructiveSolidGeometry/Intervals.jl | 8 +- .../VolumePrimitives/Box.jl | 12 +- .../VolumePrimitives/Cone.jl | 238 +++++++++--------- .../VolumePrimitives/Ellipsoid.jl | 13 +- .../VolumePrimitives/RegularPrism.jl | 12 +- .../VolumePrimitives/Torus.jl | 8 +- src/PotentialSimulation/Painting/Curved.jl | 76 +++++- src/PotentialSimulation/Painting/Planar.jl | 75 +++++- src/SolidStateDetectors.jl | 2 +- 12 files changed, 293 insertions(+), 172 deletions(-) diff --git a/src/ConstructiveSolidGeometry/CSG.jl b/src/ConstructiveSolidGeometry/CSG.jl index f1877324c..b4705fb92 100644 --- a/src/ConstructiveSolidGeometry/CSG.jl +++ b/src/ConstructiveSolidGeometry/CSG.jl @@ -8,7 +8,8 @@ struct CSGUnion{T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} <: Abstra b::B end -in(p::AbstractCoordinatePoint, csg::CSGUnion) = in(p, csg.a) || in(p, csg.b) +in(p::AbstractCoordinatePoint{T}, csg::CSGUnion; csgtol::T = csg_default_tol(T)) where {T} = + in(p, csg.a; csgtol = csgtol) || in(p, csg.b; csgtol = csgtol) (+)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} = CSGUnion{T,A,B}(a, b) # read-in @@ -30,7 +31,8 @@ struct CSGIntersection{T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} <: b::B end -in(p::AbstractCoordinatePoint, csg::CSGIntersection) = in(p, csg.a) && in(p, csg.b) +in(p::AbstractCoordinatePoint{T}, csg::CSGIntersection; csgtol::T = csg_default_tol(T)) where {T} = + in(p, csg.a; csgtol = csgtol) && in(p, csg.b; csgtol = csgtol) (&)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} = CSGIntersection{T,A,B}(a, b) # read-in @@ -53,7 +55,8 @@ struct CSGDifference{T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} <: A b::B end -in(p::AbstractCoordinatePoint, csg::CSGDifference) = in(p, csg.a) && !in(p, csg.b) +in(p::AbstractCoordinatePoint{T}, csg::CSGDifference; csgtol::T = csg_default_tol(T)) where {T} = + in(p, csg.a; csgtol = csgtol) && !in(p, csg.b; csgtol = csgtol) function (-)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractConstructiveGeometry{T}} ob = switchClosedOpen(b) diff --git a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl index 04cdac9b8..6f39804bb 100644 --- a/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl +++ b/src/ConstructiveSolidGeometry/ConstructiveSolidGeometry.jl @@ -57,8 +57,10 @@ module ConstructiveSolidGeometry _transform_into_global_coordinate_system(pts::AbstractVector{<:CartesianPoint}, p::AbstractPrimitive) = broadcast(pt -> _transform_into_global_coordinate_system(pt, p), pts) _transform_into_object_coordinate_system(pt::CartesianPoint, p::AbstractPrimitive) = inv(rotation(p)) * (pt - origin(p)) - in(pt::CartesianPoint, p::AbstractPrimitive) = _in(_transform_into_object_coordinate_system(pt, p), p) - in(pt::CylindricalPoint, p::AbstractPrimitive) = in(CartesianPoint(pt), p) + in(pt::CartesianPoint{T}, p::AbstractPrimitive{T}; csgtol::T = csg_default_tol(T)) where {T} = + _in(_transform_into_object_coordinate_system(pt, p), p; csgtol = csgtol) + in(pt::CylindricalPoint{T}, p::AbstractPrimitive{T}; csgtol::T = csg_default_tol(T)) where {T} = + in(CartesianPoint(pt), p; csgtol = csgtol) # Do we want to store the rotation matrix permanently in the primitive? # We should do tests regarding the performance. It can be easily added later. diff --git a/src/ConstructiveSolidGeometry/GeometryRounding.jl b/src/ConstructiveSolidGeometry/GeometryRounding.jl index 7d0f30d71..d1c5a4c41 100644 --- a/src/ConstructiveSolidGeometry/GeometryRounding.jl +++ b/src/ConstructiveSolidGeometry/GeometryRounding.jl @@ -2,5 +2,7 @@ csg_round_lin(x::T; sigdigits::Int = 9) where {T} = round(x, sigdigits = sigdigi csg_round_lin(x::Float32; sigdigits::Int = 5) where {T} = round(x, sigdigits = sigdigits) # min. Δx = 10 μm csg_round_rad(φ::T; digits::Int = 4) where {T} = round(φ, digits = digits) # min. Δφ ≈ 0.011 ° -csg_isapprox_lin(x::T, y::T; Δ::T = T(1e-9)) where {T} = abs(x - y) < Δ -csg_isapprox_rad(α::T, β::T; Δ::T = T(1e-4)) where {T} = abs(α - β) < Δ \ No newline at end of file +csg_default_tol(::Type{T}) where {T} = T(1e-12) + +csg_isapprox(x::T, y::T; csgtol::T = T(1e-9)) where {T} = abs(x - y) < csgtol + diff --git a/src/ConstructiveSolidGeometry/Intervals.jl b/src/ConstructiveSolidGeometry/Intervals.jl index ee70e15e7..b94f8c060 100644 --- a/src/ConstructiveSolidGeometry/Intervals.jl +++ b/src/ConstructiveSolidGeometry/Intervals.jl @@ -23,12 +23,14 @@ @inline _in_angular_interval_closed(α::Real, α_int::Nothing, tol::Real = 0) = true @inline _in_angular_interval_closed(α::Real, α_int::AbstractInterval{T}, tol::Real = 0) where {T} = mod(α - (α_int.left-tol), T(2π)) ≤ (α_int.right+tol) - (α_int.left-tol) -@inline function _in_angular_interval_closed(α::T, α_int::Tuple{T,T}) where {T} +@inline function _in_angular_interval_closed(α::T, α_int::Tuple{T,T}; csgtol::T = csg_default_tol(T)) where {T} m = mod(α - α_int[1], T(2π)) d = (α_int[2] - α_int[1]) - m ≤ d || csg_isapprox_rad(m, d) # we might want to add r into this here. + m ≤ d + csgtol +end +@inline function _in_angular_interval_open(α::T, α_int::Tuple{T,T}; csgtol::T = csg_default_tol(T)) where {T} + csgtol < mod(α - α_int[1], T(2π)) < (α_int[2] - α_int[1]) - csgtol end -@inline _in_angular_interval_open(α::T, α_int::Tuple{T,T}) where {T} = 0 < mod(α - α_int[1], T(2π)) < (α_int[2] - α_int[1]) @inline _in_angular_interval_open(α::T, α_int::Nothing) where {T<:Real} = 0 < mod(α, T(2π)) < T(2π) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 74a0e0a93..47e44f7f9 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -17,14 +17,14 @@ Box{T, CO}( b::Box{T, CO}; COT = CO, rotation::SMatrix{3,3,T,9} = b.rotation) where {T, CO<:Union{ClosedPrimitive, OpenPrimitive}} = Box{T, COT}(b.hX, b.hY, b.hZ, origin, rotation) -function _in(pt::CartesianPoint, b::Box{<:Any, ClosedPrimitive}) - (abs(pt.x) <= b.hX || csg_isapprox_lin(abs(pt.x), b.hX)) && - (abs(pt.y) <= b.hY || csg_isapprox_lin(abs(pt.y), b.hY)) && - (abs(pt.z) <= b.hZ || csg_isapprox_lin(abs(pt.z), b.hZ)) +function _in(pt::CartesianPoint{T}, b::Box{<:Any, ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.x) <= b.hX + csgtol && + abs(pt.y) <= b.hY + csgtol && + abs(pt.z) <= b.hZ + csgtol end -_in(pt::CartesianPoint, b::Box{<:Any, OpenPrimitive}) = - abs(pt.x) < b.hX && abs(pt.y) < b.hY && abs(pt.z) < b.hZ +_in(pt::CartesianPoint{T}, b::Box{<:Any, OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} = + abs(pt.x) < b.hX - csgtol && abs(pt.y) < b.hY - csgtol && abs(pt.z) < b.hZ - csgtol function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::NamedTuple, transformations::Transformations{T}) where {T} length_unit = input_units.length diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 9fa3d6978..425123a80 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -50,16 +50,16 @@ const PartialCylinder{T,CO} = Cone{T,CO,T,Tuple{T,T}} ### Cylinder -function _in(pt::CartesianPoint, c::Cylinder{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::Cylinder{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) - r <= c.r || csg_isapprox_lin(r, c.r) + r <= c.r + csgtol end end -function _in(pt::CartesianPoint, c::Cylinder{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - hypot(pt.x, pt.y) < c.r +function _in(pt::CartesianPoint, c::Cylinder{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) < c.hZ - csgtol && + hypot(pt.x, pt.y) < c.r - csgtol end function surfaces(t::Cylinder{T}) where {T} @@ -74,18 +74,20 @@ end ### PartialCylinder -function _in(pt::CartesianPoint, c::PartialCylinder{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::PartialCylinder{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) - r <= c.r || csg_isapprox_lin(r, c.r) - end && - _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) + r <= c.r + csgtol && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end end -function _in(pt::CartesianPoint, c::PartialCylinder{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - hypot(pt.x, pt.y) < c.r && - _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +function _in(pt::CartesianPoint, c::PartialCylinder{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) + csgtol < c.hZ && begin + r = hypot(pt.x, pt.y) + csgtol + r < c.r && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end end function surfaces(t::PartialCylinder{T}) where {T} @@ -121,17 +123,17 @@ _____\ const VaryingCylinder{T,CO} = Cone{T,CO,Tuple{T,T},Nothing} # Full in φ const PartialVaryingCylinder{T,CO} = Cone{T,CO,Tuple{T,T},Tuple{T,T}} -function _in(pt::CartesianPoint, c::VaryingCylinder{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::VaryingCylinder{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) rz = radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) - r <= rz || csg_isapprox_lin(r, rz) + r <= rz + csgtol end end -function _in(pt::CartesianPoint, c::VaryingCylinder{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) +function _in(pt::CartesianPoint, c::VaryingCylinder{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) + csgtol < c.hZ && + csgtol + hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) end function surfaces(t::VaryingCylinder{T}) where {T} @@ -144,19 +146,21 @@ function surfaces(t::VaryingCylinder{T}) where {T} e_top, e_bot, mantle end -function _in(pt::CartesianPoint, c::PartialVaryingCylinder{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::PartialVaryingCylinder{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) rz = radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) - r <= rz || csg_isapprox_lin(r, rz) - end && - _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) + r <= rz + csgtol && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end end -function _in(pt::CartesianPoint, c::PartialVaryingCylinder{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) && - _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +function _in(pt::CartesianPoint, c::PartialVaryingCylinder{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) + csgtol < c.hZ && begin + r = hypot(pt.x, pt.y) + csgtol + r < radius_at_z(c.hZ, c.r[1], c.r[2], pt.z) && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end end function surfaces(t::PartialVaryingCylinder{T}) where {T} @@ -195,19 +199,19 @@ const PartialVaryingTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},Tuple{T,T}},Tuple{T, #(r_bot_in = r[1][1], r_bot_out = r[1][2], r_top_in = r[2][1], r_top_out = r[2][2]) -function _in(pt::CartesianPoint, c::VaryingTube{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::VaryingTube{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) - (r_in <= r || csg_isapprox_lin(r_in, r)) && - (r <= r_out || csg_isapprox_lin(r, r_out)) + r_in - csgtol <= r && + r <= r_out + csgtol end end -function _in(pt::CartesianPoint, c::VaryingTube{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) +function _in(pt::CartesianPoint, c::VaryingTube{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) + csgtol < c.hZ && + csgtol + radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) - csgtol end function surfaces(t::VaryingTube{T}) where {T} @@ -221,21 +225,23 @@ function surfaces(t::VaryingTube{T}) where {T} e_top, e_bot, inner_mantle, outer_mantle end -function _in(pt::CartesianPoint, c::PartialVaryingTube{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::PartialVaryingTube{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) - (r_in <= r || csg_isapprox_lin(r_in, r)) && - (r <= r_out || csg_isapprox_lin(r, r_out)) - end && - _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) + r_in - csgtol <= r && + r <= r_out + csgtol && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end end -function _in(pt::CartesianPoint, c::PartialVaryingTube{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) && - _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +function _in(pt::CartesianPoint, c::PartialVaryingTube{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) + csgtol < c.hZ && begin + r = hypot(pt.x, pt.y) + csgtol + radius_at_z(c.hZ, c.r[1][1], c.r[2][1], pt.z) < r < radius_at_z(c.hZ, c.r[1][2], c.r[2][2], pt.z) - csgtol && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end end function surfaces(t::PartialVaryingTube{T}) where {T} @@ -272,17 +278,17 @@ __\ const UpwardCone{T,CO} = Cone{T,CO,Tuple{Tuple{Nothing,T},Nothing},Nothing} # Full in φ const PartialUpwardCone{T,CO} = Cone{T,CO,Tuple{Tuple{Nothing,T},Nothing},Tuple{T,T}} -function _in(pt::CartesianPoint, c::UpwardCone{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::UpwardCone{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) r_out = radius_at_z(c.hZ, c.r[1][2], zero(T), pt.z) - (r <= r_out || csg_isapprox_lin(r_out, r)) + r <= r_out + csgtol end end -function _in(pt::CartesianPoint, c::UpwardCone{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], zero(T), pt.z) +function _in(pt::CartesianPoint, c::UpwardCone{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) + csgtol < c.hZ && + hypot(pt.x, pt.y) + csgtol < radius_at_z(c.hZ, c.r[1][2], zero(T), pt.z) end function surfaces(t::UpwardCone{T}) where {T} @@ -293,19 +299,21 @@ function surfaces(t::UpwardCone{T}) where {T} e_bot, outer_mantle end -function _in(pt::CartesianPoint, c::PartialUpwardCone{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::PartialUpwardCone{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) r_out = radius_at_z(c.hZ, c.r[1][2], zero(T), pt.z) - (r <= r_out || csg_isapprox_lin(r_out, r)) - end && - _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) + r <= r_out + csgtol && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end end -function _in(pt::CartesianPoint, c::PartialUpwardCone{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], zero(T), pt.z) && - _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +function _in(pt::CartesianPoint, c::PartialUpwardCone{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) + csgtol < c.hZ && begin + r = hypot(pt.x, pt.y) + csgtol + r < radius_at_z(c.hZ, c.r[1][2], zero(T), pt.z) && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end end function surfaces(t::PartialUpwardCone{T}) where {T} @@ -339,17 +347,17 @@ const DownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{Nothing,T}},Nothing} # const PartialDownwardCone{T,CO} = Cone{T,CO,Tuple{Nothing,Tuple{Nothing,T}},Tuple{T,T}} -function _in(pt::CartesianPoint, c::DownwardCone{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::DownwardCone{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) r_out = radius_at_z(c.hZ, zero(T), c.r[2][2], pt.z) - (r <= r_out || csg_isapprox_lin(r_out, r)) + r <= r_out + csgtol end end -function _in(pt::CartesianPoint, c::DownwardCone{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - hypot(pt.x, pt.y) < radius_at_z(c.hZ, zero(T), c.r[2][2], pt.z) +function _in(pt::CartesianPoint, c::DownwardCone{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) + csgtol < c.hZ && + hypot(pt.x, pt.y) + csgtol < radius_at_z(c.hZ, zero(T), c.r[2][2], pt.z) end function surfaces(t::DownwardCone{T}) where {T} @@ -360,19 +368,21 @@ function surfaces(t::DownwardCone{T}) where {T} e_top, outer_mantle end -function _in(pt::CartesianPoint, c::PartialDownwardCone{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::PartialDownwardCone{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) r_out = radius_at_z(c.hZ, zero(T), c.r[2][2], pt.z) - (r <= r_out || csg_isapprox_lin(r_out, r)) - end && - _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) + r <= r_out + csgtol && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end end -function _in(pt::CartesianPoint, c::PartialDownwardCone{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - hypot(pt.x, pt.y) < radius_at_z(c.hZ, zero(T), c.r[2][2], pt.z) && - _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +function _in(pt::CartesianPoint, c::PartialDownwardCone{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) + csgtol < c.hZ && begin + r = hypot(pt.x, pt.y) + csgtol + r < radius_at_z(c.hZ, zero(T), c.r[2][2], pt.z) && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end end function surfaces(t::PartialDownwardCone{T}) where {T} @@ -407,19 +417,19 @@ const TopClosedTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},T},Nothing} # Full in φ const PartialTopClosedTube{T,CO} = Cone{T,CO,Tuple{Tuple{T,T},T},Tuple{T,T}} -function _in(pt::CartesianPoint, c::TopClosedTube{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::TopClosedTube{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2], pt.z) r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2], pt.z) - (r_in <= r || csg_isapprox_lin(r_in, r)) && - (r <= r_out || csg_isapprox_lin(r, r_out)) + r_in - csgtol <= r && + r <= r_out + csgtol end end -function _in(pt::CartesianPoint, c::TopClosedTube{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - radius_at_z(c.hZ, c.r[1][1], c.r[2], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], c.r[2], pt.z) +function _in(pt::CartesianPoint, c::TopClosedTube{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) + csgtol < c.hZ && + csgtol + radius_at_z(c.hZ, c.r[1][1], c.r[2], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], c.r[2], pt.z) - csgtol end function surfaces(t::TopClosedTube{T}) where {T} @@ -433,21 +443,23 @@ function surfaces(t::TopClosedTube{T}) where {T} e_bot, inner_mantle, outer_mantle end -function _in(pt::CartesianPoint, c::PartialTopClosedTube{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::PartialTopClosedTube{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1][1], c.r[2], pt.z) r_out = radius_at_z(c.hZ, c.r[1][2], c.r[2], pt.z) - (r_in <= r || csg_isapprox_lin(r_in, r)) && - (r <= r_out || csg_isapprox_lin(r, r_out)) - end && - _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) + r_in - csgtol <= r && + r <= r_out + csgtol && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end end -function _in(pt::CartesianPoint, c::PartialTopClosedTube{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - radius_at_z(c.hZ, c.r[1][1], c.r[2], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1][2], c.r[2], pt.z) && - _in_angular_interval_open(atan(pt.y, pt.x), c.φ) +function _in(pt::CartesianPoint, c::PartialTopClosedTube{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) + csgtol < c.hZ && begin + r = hypot(pt.x, pt.y) + csgtol + radius_at_z(c.hZ, c.r[1][1], c.r[2], pt.z) < r < radius_at_z(c.hZ, c.r[1][2], c.r[2], pt.z) - csgtol && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end end function surfaces(t::PartialTopClosedTube{T}) where {T} @@ -486,19 +498,19 @@ const BottomClosedTube{T,CO} = Cone{T,CO,Tuple{T,Tuple{T,T}},Nothing} # Full in const PartialBottomClosedTube{T,CO} = Cone{T,CO,Tuple{T,Tuple{T,T}},Tuple{T,T}} -function _in(pt::CartesianPoint, c::BottomClosedTube{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::BottomClosedTube{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1], c.r[2][1], pt.z) r_out = radius_at_z(c.hZ, c.r[1], c.r[2][2], pt.z) - (r_in <= r || csg_isapprox_lin(r_in, r)) && - (r <= r_out || csg_isapprox_lin(r, r_out)) + r_in - csgtol <= r && + r <= r_out + csgtol end end -function _in(pt::CartesianPoint, c::BottomClosedTube{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - radius_at_z(c.hZ, c.r[1], c.r[2][1], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1], c.r[2][2], pt.z) +function _in(pt::CartesianPoint, c::BottomClosedTube{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) + csgtol < c.hZ && + csgtol + radius_at_z(c.hZ, c.r[1], c.r[2][1], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1], c.r[2][2], pt.z) - csgtol end function surfaces(t::BottomClosedTube{T}) where {T} @@ -512,21 +524,23 @@ function surfaces(t::BottomClosedTube{T}) where {T} e_top, inner_mantle, outer_mantle end -function _in(pt::CartesianPoint, c::PartialBottomClosedTube{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint, c::PartialBottomClosedTube{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} az = abs(pt.z) - (az <= c.hZ || csg_isapprox_lin(az, c.hZ)) && begin + az <= c.hZ + csgtol && begin r = hypot(pt.x, pt.y) r_in = radius_at_z(c.hZ, c.r[1], c.r[2][1], pt.z) r_out = radius_at_z(c.hZ, c.r[1], c.r[2][2], pt.z) - (r_in <= r || csg_isapprox_lin(r_in, r)) && - (r <= r_out || csg_isapprox_lin(r, r_out)) - end && - _in_angular_interval_closed(atan(pt.y, pt.x), c.φ) -end -function _in(pt::CartesianPoint, c::PartialBottomClosedTube{T,OpenPrimitive}) where {T} - abs(pt.z) < c.hZ && - radius_at_z(c.hZ, c.r[1], c.r[2][1], pt.z) < hypot(pt.x, pt.y) < radius_at_z(c.hZ, c.r[1], c.r[2][2], pt.z) && - _in_angular_interval_open(atan(pt.y, pt.x), c.φ) + r_in - csgtol <= r && + r <= r_out + csgtol && + _in_angular_interval_closed(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end +end +function _in(pt::CartesianPoint, c::PartialBottomClosedTube{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} + abs(pt.z) + csgtol < c.hZ && begin + r = hypot(pt.x, pt.y) + csgtol + radius_at_z(c.hZ, c.r[1], c.r[2][1], pt.z) < r < radius_at_z(c.hZ, c.r[1], c.r[2][2], pt.z) - csgtol && + _in_angular_interval_open(atan(pt.y, pt.x), c.φ, csgtol = csgtol / r) + end end function surfaces(t::PartialBottomClosedTube{T}) where {T} diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl index 5d9ab7504..ab9b9facf 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl @@ -28,14 +28,11 @@ function Geometry(::Type{T}, ::Type{Ellipsoid}, dict::AbstractDict, input_units: transform(e, transformations) end -function _in(pt::CartesianPoint, s::FullSphere{<:Any, ClosedPrimitive}) - r = hypot(pt.x, pt.y, pt.z) - r <= s.r || csg_isapprox_lin(r, s.r) -end -function _in(pt::CartesianPoint, s::FullSphere{<:Any, OpenPrimitive}) - r = hypot(pt.x, pt.y, pt.z) - r < s.r -end +_in(pt::CartesianPoint{T}, s::FullSphere{<:Any, ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} = + hypot(pt.x, pt.y, pt.z) <= s.r + csgtol + +_in(pt::CartesianPoint{T}, s::FullSphere{<:Any, OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} = + hypot(pt.x, pt.y, pt.z) < s.r - csgtol function surfaces(e::Ellipsoid{T,ClosedPrimitive}) where {T} em = EllipsoidMantle{T,typeof(e.r),typeof(e.φ),typeof(e.θ),:inwards}(e.r, e.φ, e.θ, e.origin, e.rotation) diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl index 7472f0c26..913406944 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/RegularPrism.jl @@ -59,20 +59,20 @@ function sample(rp::RegularPrism{T,<:Any,N,T})::Vector{CartesianPoint{T}} where [vertices(rp)...] end -function _in(pt::CartesianPoint{T}, rp::RegularPrism{T,ClosedPrimitive,N,T}) where {T,N} - (abs(pt.z) <= rp.hZ || csg_isapprox_lin(abs(pt.z), rp.hZ)) && begin +function _in(pt::CartesianPoint{T}, rp::RegularPrism{T,ClosedPrimitive,N,T}; csgtol::T = csg_default_tol(T)) where {T,N} + abs(pt.z) <= rp.hZ + csgtol && begin r, φ = hypot(pt.x, pt.y), atan(pt.y, pt.x) α = T(π/N) _r = r * cos(α - mod(φ, 2α)) / cos(α) - _r <= rp.r || csg_isapprox_lin(_r, rp.r) + _r <= rp.r + csgtol end end -function _in(pt::CartesianPoint{T}, rp::RegularPrism{T,OpenPrimitive,N,T}) where {T,N} - abs(pt.z) < rp.hZ && begin +function _in(pt::CartesianPoint{T}, rp::RegularPrism{T,OpenPrimitive,N,T}; csgtol::T = csg_default_tol(T)) where {T,N} + abs(pt.z) < rp.hZ - csgtol && begin r, φ = hypot(pt.x, pt.y), atan(pt.y, pt.x) α = T(π/N) _r = r * cos(α - mod(φ, 2α)) / cos(α) - _r < rp.r + _r < rp.r - csgtol end end diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl index 06fcd1f59..a1fbf256d 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Torus.jl @@ -43,13 +43,13 @@ function surfaces(t::FullTorus{T,OpenPrimitive}) where {T} (tm, ) end -function _in(pt::CartesianPoint{T}, t::FullTorus{T,ClosedPrimitive}) where {T} +function _in(pt::CartesianPoint{T}, t::FullTorus{T,ClosedPrimitive}; csgtol::T = csg_default_tol(T)) where {T} _r = hypot(hypot(pt.x, pt.y) - t.r_torus, pt.z) - return _r <= t.r_tube || csg_isapprox_lin(_r, t.r_tube) + return _r <= t.r_tube + csgtol end -function _in(pt::CartesianPoint{T}, t::FullTorus{T,OpenPrimitive}) where {T} +function _in(pt::CartesianPoint{T}, t::FullTorus{T,OpenPrimitive}; csgtol::T = csg_default_tol(T)) where {T} _r = hypot(hypot(pt.x, pt.y) - t.r_torus, pt.z) - return _r < t.r_tube + return _r < t.r_tube - csgtol end # #Constructors diff --git a/src/PotentialSimulation/Painting/Curved.jl b/src/PotentialSimulation/Painting/Curved.jl index e6dbc1e26..98a86f05e 100644 --- a/src/PotentialSimulation/Painting/Curved.jl +++ b/src/PotentialSimulation/Painting/Curved.jl @@ -5,13 +5,25 @@ function paint!(pointtypes, potential, face::AbstractCurvedSurfacePrimitive{T}, eX = CartesianVector{T}(1,0,0); eY = CartesianVector{T}(0,1,0); eZ = CartesianVector{T}(0,0,1); + widths_ax1 = diff(get_extended_ticks(grid[1])) + widths_ax2 = diff(get_extended_ticks(grid[2])) + widths_ax3 = diff(get_extended_ticks(grid[3])) for i2 in t_idx_r2 for i1 in t_idx_r1 l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], ticks[2][i2], zero(T)), eZ) pts = ConstructiveSolidGeometry.intersection(face, l) for pt in pts - if pt in geometry - i3 = searchsortednearest(ticks[3], pt[3]) + i3 = searchsortednearest(ticks[3], pt[3]) + csgtol = abs(ticks[3][i3] - pt[3]) + Δw_max = max( + widths_ax1[i1], widths_ax1[i1+1], + widths_ax2[i2], widths_ax1[i2+1], + # widths_ax3[i3], widths_ax3[i3+1] + )/2 + if csgtol > Δw_max + # csgtol = Δw_max + end + if in(pt, geometry, csgtol = csgtol) pointtypes[i1, i2, i3] = zero(PointType) potential[i1, i2, i3] = pot_value end @@ -23,8 +35,17 @@ function paint!(pointtypes, potential, face::AbstractCurvedSurfacePrimitive{T}, l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], zero(T), ticks[3][i3]), eY) pts = ConstructiveSolidGeometry.intersection(face, l) for pt in pts - if pt in geometry - i2 = searchsortednearest(ticks[2], pt[2]) + i2 = searchsortednearest(ticks[2], pt[2]) + csgtol = abs(ticks[2][i2] - pt[2]) + Δw_max = max( + widths_ax1[i1], widths_ax1[i1+1], + # widths_ax2[i2], widths_ax1[i2+1], + widths_ax3[i3], widths_ax3[i3+1] + )/2 + if csgtol > Δw_max + # csgtol = Δw_max + end + if in(pt, geometry, csgtol = csgtol) pointtypes[i1, i2, i3] = zero(PointType) potential[i1, i2, i3] = pot_value end @@ -36,8 +57,17 @@ function paint!(pointtypes, potential, face::AbstractCurvedSurfacePrimitive{T}, l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(zero(T), ticks[2][i2], ticks[3][i3]), eX) pts = ConstructiveSolidGeometry.intersection(face, l) for pt in pts - if pt in geometry - i1 = searchsortednearest(ticks[1], pt[1]) + i1 = searchsortednearest(ticks[1], pt[1]) + csgtol = abs(ticks[1][i1] - pt[1]) + Δw_max = max( + # widths_ax1[i1], widths_ax1[i1+1], + widths_ax2[i2], widths_ax1[i2+1], + widths_ax3[i3], widths_ax3[i3+1] + )/2 + if csgtol > Δw_max + # csgtol = Δw_max + end + if in(pt, geometry, csgtol = csgtol) pointtypes[i1, i2, i3] = zero(PointType) potential[i1, i2, i3] = pot_value end @@ -53,13 +83,25 @@ function paint!(pointtypes, potential, face::AbstractCurvedSurfacePrimitive{T}, ticks = (grid.axes[1].ticks, grid.axes[2].ticks, grid.axes[3].ticks) eZ = CartesianVector{T}(0,0,1); + widths_ax1 = diff(get_extended_ticks(grid[1])) + widths_ax2 = diff(get_extended_ticks(grid[2])) + widths_ax3 = diff(get_extended_ticks(grid[3])) + for i2 in eachindex(ticks[2]) for i1 in eachindex(ticks[1]) l = ConstructiveSolidGeometry.Line(CartesianPoint(CylindricalPoint{T}(ticks[1][i1], ticks[2][i2], zero(T))), eZ) pts = ConstructiveSolidGeometry.intersection(face, l) for pt in pts - if pt in geometry - i3 = searchsortednearest(ticks[3], pt[3]) + i3 = searchsortednearest(ticks[3], pt[3]) + csgtol = abs(ticks[3][i3] - pt[3]) + Δw_max = max( + widths_ax1[i1], widths_ax1[i1+1], + # widths_ax2[i2], widths_ax2[i2+1], + )/4 + if csgtol > Δw_max + csgtol = Δw_max + end + if in(pt, geometry, csgtol = csgtol) pointtypes[i1, i2, i3] = zero(PointType) potential[i1, i2, i3] = pot_value end @@ -73,14 +115,14 @@ function paint!(pointtypes, potential, face::AbstractCurvedSurfacePrimitive{T}, # for i1 in t_idx_r1 # r # l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], zero(T), ticks[3][i3]), eY) # pt = ConstructiveSolidGeometry.intersection(plane, l) - # if pt in geometry - # i2 = searchsortednearest(ticks[2], pt[2]) +# i2 = searchsortednearest(ticks[2], pt[2]) + # if in(pt, geometry, csgtol = abs(ticks[2][i2] - pt[2])) # pointtypes[i1, i2, i3] = zero(PointType) # potential[i1, i2, i3] = pot_value # end # end # end - + for i3 in t_idx_r3 # z; Maybe switch loops so that the direction of `l` has to be calculated less times.. o = CartesianPoint{T}(zero(T), zero(T), ticks[3][i3]) for i2 in eachindex(ticks[2]) # φ @@ -92,8 +134,16 @@ function paint!(pointtypes, potential, face::AbstractCurvedSurfacePrimitive{T}, # Intersection must be in positive r direction of dir: pt_cyl[2] == ticks[2][i2] # Use `abs(pt_cyl[2] - ticks[2][i2]) < 0.1` to avoid rounding issues # if it differs, it would always differ by π = 3.141... -> 0.1 is fine - if abs(pt_cyl[2] - ticks[2][i2]) < 0.1 && pt_car in geometry - i1 = searchsortednearest(ticks[1], pt_cyl[1]) + i1 = searchsortednearest(ticks[1], pt_cyl[1]) + csgtol = abs(ticks[1][i1] - pt_cyl[1]) + Δw_max = max( + widths_ax3[i3], widths_ax3[i3+1], + # widths_ax2[i2], widths_ax2[i2+1], + )/4 + if csgtol > Δw_max + csgtol = Δw_max + end + if abs(pt_cyl[2] - ticks[2][i2]) < 0.1 && in(pt_car, geometry, csgtol = csgtol) pointtypes[i1, i2, i3] = zero(PointType) potential[i1, i2, i3] = pot_value end diff --git a/src/PotentialSimulation/Painting/Planar.jl b/src/PotentialSimulation/Painting/Planar.jl index d23b5651e..d73ffabc8 100644 --- a/src/PotentialSimulation/Painting/Planar.jl +++ b/src/PotentialSimulation/Painting/Planar.jl @@ -6,12 +6,24 @@ function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive{T}, eX = CartesianVector{T}(1,0,0); eY = CartesianVector{T}(0,1,0); eZ = CartesianVector{T}(0,0,1); + widths_ax1 = diff(get_extended_ticks(grid[1])) + widths_ax2 = diff(get_extended_ticks(grid[2])) + widths_ax3 = diff(get_extended_ticks(grid[3])) for i2 in t_idx_r2 for i1 in t_idx_r1 l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], ticks[2][i2], zero(T)), eZ) pt = ConstructiveSolidGeometry.intersection(plane, l) - if pt in geometry - i3 = searchsortednearest(ticks[3], pt[3]) + i3 = searchsortednearest(ticks[3], pt[3]) + csgtol = abs(ticks[3][i3] - pt[3]) + Δw_max = max( + widths_ax1[i1], widths_ax1[i1+1], + widths_ax2[i2], widths_ax1[i2+1], + # widths_ax3[i3], widths_ax3[i3+1] + )/4 + if csgtol > Δw_max + csgtol = Δw_max + end + if in(pt, geometry, csgtol = csgtol) pointtypes[i1, i2, i3] = zero(PointType) potential[i1, i2, i3] = pot_value end @@ -21,8 +33,17 @@ function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive{T}, for i1 in t_idx_r1 l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], zero(T), ticks[3][i3]), eY) pt = ConstructiveSolidGeometry.intersection(plane, l) - if pt in geometry - i2 = searchsortednearest(ticks[2], pt[2]) + i2 = searchsortednearest(ticks[2], pt[2]) + csgtol = abs(ticks[2][i2] - pt[2]) + Δw_max = max( + widths_ax1[i1], widths_ax1[i1+1], + # widths_ax2[i2], widths_ax1[i2+1], + widths_ax3[i3], widths_ax3[i3+1] + )/4 + if csgtol > Δw_max + csgtol = Δw_max + end + if in(pt, geometry, csgtol = csgtol) pointtypes[i1, i2, i3] = zero(PointType) potential[i1, i2, i3] = pot_value end @@ -32,8 +53,17 @@ function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive{T}, for i2 in t_idx_r2 l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(zero(T), ticks[2][i2], ticks[3][i3]), eX) pt = ConstructiveSolidGeometry.intersection(plane, l) - if pt in geometry - i1 = searchsortednearest(ticks[1], pt[1]) + i1 = searchsortednearest(ticks[1], pt[1]) + csgtol = abs(ticks[1][i1] - pt[1]) + Δw_max = max( + # widths_ax1[i1], widths_ax1[i1+1], + widths_ax2[i2], widths_ax1[i2+1], + widths_ax3[i3], widths_ax3[i3+1] + )/4 + if csgtol > Δw_max + csgtol = Δw_max + end + if in(pt, geometry, csgtol = csgtol) pointtypes[i1, i2, i3] = zero(PointType) potential[i1, i2, i3] = pot_value end @@ -48,12 +78,24 @@ function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive{T}, ticks = (grid.axes[1].ticks, grid.axes[2].ticks, grid.axes[3].ticks) plane = ConstructiveSolidGeometry.Plane(face) eZ = CartesianVector{T}(0,0,1); + widths_ax1 = diff(get_extended_ticks(grid[1])) + widths_ax2 = diff(get_extended_ticks(grid[2])) + widths_ax3 = diff(get_extended_ticks(grid[3])) + for i2 in eachindex(ticks[2]) for i1 in eachindex(ticks[1]) l = ConstructiveSolidGeometry.Line(CartesianPoint(CylindricalPoint{T}(ticks[1][i1], ticks[2][i2], zero(T))), eZ) pt = ConstructiveSolidGeometry.intersection(plane, l) - if pt in geometry - i3 = searchsortednearest(ticks[3], pt[3]) + i3 = searchsortednearest(ticks[3], pt[3]) + csgtol = abs(ticks[3][i3] - pt[3]) + Δw_max = max( + widths_ax1[i1], widths_ax1[i1+1], + # widths_ax2[i2], widths_ax2[i2+1], + )/4 + if csgtol > Δw_max + csgtol = Δw_max + end + if in(pt, geometry, csgtol = csgtol) pointtypes[i1, i2, i3] = zero(PointType) potential[i1, i2, i3] = pot_value end @@ -66,8 +108,8 @@ function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive{T}, # for i1 in t_idx_r1 # r # l = ConstructiveSolidGeometry.Line(CartesianPoint{T}(ticks[1][i1], zero(T), ticks[3][i3]), eY) # pt = ConstructiveSolidGeometry.intersection(plane, l) - # if pt in geometry - # i2 = searchsortednearest(ticks[2], pt[2]) +# i2 = searchsortednearest(ticks[2], pt[2]) + # if in(pt, geometry, csgtol = abs(ticks[2][i2] - pt[2])) # pointtypes[i1, i2, i3] = zero(PointType) # potential[i1, i2, i3] = pot_value # end @@ -84,8 +126,17 @@ function paint!(pointtypes, potential, face::AbstractPlanarSurfacePrimitive{T}, # Intersection must be in positive r direction of dir: pt_cyl[2] == ticks[2][i2] # Use `abs(pt_cyl[2] - ticks[2][i2]) < 0.1` to avoid rounding issues # if it differs, it would always differ by π = 3.141... -> 0.1 is fine - if abs(pt_cyl[2] - ticks[2][i2]) < 0.1 && pt_car in geometry - i1 = searchsortednearest(ticks[1], pt_cyl[1]) + i1 = searchsortednearest(ticks[1], pt_cyl[1]) + csgtol = abs(ticks[1][i1] - pt_cyl[1]) + Δw_max = max( + # widths_ax2[i2], widths_ax2[i2+1], + widths_ax3[i3], widths_ax3[i3+1] + )/4 + if csgtol > Δw_max + csgtol = Δw_max + end + if abs(pt_cyl[2] - ticks[2][i2]) < 0.1 && + in(pt_car, geometry, csgtol = csgtol) pointtypes[i1, i2, i3] = zero(PointType) potential[i1, i2, i3] = pot_value end diff --git a/src/SolidStateDetectors.jl b/src/SolidStateDetectors.jl index d78335bba..ad6cf8b7d 100644 --- a/src/SolidStateDetectors.jl +++ b/src/SolidStateDetectors.jl @@ -35,7 +35,7 @@ using .ConstructiveSolidGeometry: CartesianTicksTuple, CylindricalTicksTuple, Geometry, AbstractGeometry, AbstractSurfacePrimitive, AbstractPlanarSurfacePrimitive, AbstractCurvedSurfacePrimitive, - csg_round_lin, csg_round_rad, csg_isapprox_lin, csg_isapprox_rad, + csg_round_lin, csg_round_rad, csg_isapprox, parse_rotation_matrix, parse_translate_vector, parse_CSG_transformation, transform, CSG_dict, Transformations, combine_transformations From f8fad59b9cea4aab799d02d774c11651dd5b1122 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 28 Jun 2021 15:28:47 +0200 Subject: [PATCH 234/241] Code style --- src/ConstructiveSolidGeometry/CSG.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ConstructiveSolidGeometry/CSG.jl b/src/ConstructiveSolidGeometry/CSG.jl index b4705fb92..4763688a2 100644 --- a/src/ConstructiveSolidGeometry/CSG.jl +++ b/src/ConstructiveSolidGeometry/CSG.jl @@ -36,8 +36,8 @@ in(p::AbstractCoordinatePoint{T}, csg::CSGIntersection; csgtol::T = csg_default_ (&)(a::A, b::B) where {T, A <: AbstractGeometry{T}, B <: AbstractGeometry{T}} = CSGIntersection{T,A,B}(a, b) # read-in -function Geometry(::Type{T}, ::Type{CSGIntersection}, v::Vector{<:AbstractDict}, input_units::NamedTuple, transformation::Transformations{T}) where {T} - parts = broadcast(x-> Geometry(T, x, input_units, transformation), v) +function Geometry(::Type{T}, ::Type{CSGIntersection}, v::Vector{<:AbstractDict}, input_units::NamedTuple, transformations::Transformations{T}) where {T} + parts = broadcast(x-> Geometry(T, x, input_units, transformations), v) reduce(&, parts) end From 3ab44dca55648acbf5cec0e861625600f73f522f Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 28 Jun 2021 16:39:42 +0200 Subject: [PATCH 235/241] Clean up --- src/ConstructiveSolidGeometry/GeometryRounding.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/GeometryRounding.jl b/src/ConstructiveSolidGeometry/GeometryRounding.jl index d1c5a4c41..8ac0158ad 100644 --- a/src/ConstructiveSolidGeometry/GeometryRounding.jl +++ b/src/ConstructiveSolidGeometry/GeometryRounding.jl @@ -1,5 +1,5 @@ csg_round_lin(x::T; sigdigits::Int = 9) where {T} = round(x, sigdigits = sigdigits) # min. Δx = 1 nm -csg_round_lin(x::Float32; sigdigits::Int = 5) where {T} = round(x, sigdigits = sigdigits) # min. Δx = 10 μm +csg_round_lin(x::Float32; sigdigits::Int = 5) = round(x, sigdigits = sigdigits) # min. Δx = 10 μm csg_round_rad(φ::T; digits::Int = 4) where {T} = round(φ, digits = digits) # min. Δφ ≈ 0.011 ° csg_default_tol(::Type{T}) where {T} = T(1e-12) From 85b7a5ec585546991aca577db28baae58f497d92 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 28 Jun 2021 16:40:10 +0200 Subject: [PATCH 236/241] Use `-->` instead of `:=` --- src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl b/src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl index b977121e0..262ec0dbd 100644 --- a/src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl +++ b/src/ConstructiveSolidGeometry/plotting/CSG/CSG.jl @@ -2,23 +2,23 @@ linecolor --> :black csguniontype --> :union @series begin - linestyle := :solid + linestyle --> :solid csg.a end @series begin - linestyle := :solid + linestyle --> :solid csg.b end end @recipe function f(csg::ConstructiveSolidGeometry.CSGDifference) linecolor --> :black @series begin - linestyle := :solid + linestyle --> :solid csguniontype --> :difference csg.a end @series begin - linestyle := :dash + linestyle --> :dash csg.b end end @@ -26,13 +26,12 @@ end linecolor --> :black csguniontype --> :intersection @series begin - linestyle := :dot + linestyle --> :dot csguniontype --> :difference csg.a end @series begin - linestyle := :dot - linestyle := :dash + linestyle --> :dot csg.b end end \ No newline at end of file From 293397027b13616066d96285850faef96bfb3d44 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 28 Jun 2021 16:51:56 +0200 Subject: [PATCH 237/241] Bugfix in `extremum`-method for `Ellipse` --- src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl index 573fb7b76..5feaaac84 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl @@ -24,7 +24,7 @@ const Circle{T} = Ellipse{T,T,Nothing} const PartialCircle{T} = Ellipse{T,T,Tuple{T,T}} extremum(e::Ellipse{T,T}) where {T} = e.r -extremum(e::Ellipse{T,Tuple{T,T}}) where {T} = max(e.r[1], e.r[1]) +extremum(e::Ellipse{T,Tuple{T,T}}) where {T} = max(e.r[1], e.r[2]) function sample(e::Circle{T}; n = 4)::Vector{CartesianPoint{T}} where {T} φs = range(T(0), step = T(2π) / n, length = n) From 898e03f89374d9615de05926108fdf211cc5f36b Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 28 Jun 2021 16:57:28 +0200 Subject: [PATCH 238/241] Code style --- .../SurfacePrimitives/ConeMantle.jl | 10 +++++----- .../SurfacePrimitives/EllipsoidMantle.jl | 10 +++++----- .../VolumePrimitives/Cone.jl | 12 ++++++------ .../VolumePrimitives/Ellipsoid.jl | 10 +++++----- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index a0f1c5ef3..bded14cb7 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -1,5 +1,5 @@ """ - struct ConeMantle{T,RT,TP,D} <: AbstractSurfacePrimitive{T} + struct ConeMantle{T,TR,TP,D} <: AbstractSurfacePrimitive{T} T: Type of values, e.g. Float64 @@ -13,14 +13,14 @@ T: Type of values, e.g. Float64 * `φ::TP`: * TP = Nothing <-> Full in φ * ... -* `zH::T`: half hight/length of the cone mantle +* `hZ::T`: half hight/length of the cone mantle * `D`: `:inwards` or `:outwards`: Whethe the normal points inside or outside """ -@with_kw struct ConeMantle{T,RT,TP,D} <: AbstractCurvedSurfacePrimitive{T} - r::RT = 1 +@with_kw struct ConeMantle{T,TR,TP,D} <: AbstractCurvedSurfacePrimitive{T} + r::TR = 1 φ::TP = nothing - hZ::T = 1 # maybe we don't need this. I will leave it for now... + hZ::T = 1 # axis::Line{T} = Line{T}(CartesianPoint{T}(zero(T), zero(T), -hZ), CartesianVector{T}(zero(T), zero(T), 2hZ)) origin::CartesianPoint{T} = zero(CartesianPoint{T}) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl index 9560eba3f..f42325645 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl @@ -1,5 +1,5 @@ -@with_kw struct EllipsoidMantle{T,RT,TP,TT,D} <: AbstractCurvedSurfacePrimitive{T} - r::RT = 1 +@with_kw struct EllipsoidMantle{T,TR,TP,TT,D} <: AbstractCurvedSurfacePrimitive{T} + r::TR = 1 φ::TP = nothing θ::TT = nothing @@ -7,8 +7,8 @@ rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -flip(em::EllipsoidMantle{T,RT,TP,TT,:inwards}) where {T,RT,TP,TT} = - EllipsoidMantle{T,RT,TP,TT,:outwards}(em.r, em.φ, em.θ, em.origin, em.rotation ) +flip(em::EllipsoidMantle{T,TR,TP,TT,:inwards}) where {T,TR,TP,TT} = + EllipsoidMantle{T,TR,TP,TT,:outwards}(em.r, em.φ, em.θ, em.origin, em.rotation ) const FullSphereMantle{T,D} = EllipsoidMantle{T,T,Nothing,Nothing,D} const FullEllipsoidMantle{T,D} = EllipsoidMantle{T,NTuple{3,T},Nothing,Nothing,D} @@ -36,7 +36,7 @@ function normal(em::EllipsoidMantle{T,NTuple{3,T},TP,TT,:outwards}, pt::Cartesia obj_normal = CartesianPoint{T}(sign(p.x)*(p.x/em.r[1])^2, sign(p.y)*(p.y/em.r[2])^2, sign(p.z)*(p.z/em.r[3])^2) # We might want to store the inv(em.r) in the struct? CartesianVector(_transform_into_global_coordinate_system(obj_normal, em)) end -normal(em::EllipsoidMantle{T,RT,TP,TT,:inwards}, pt::CartesianPoint{T}) where {T,RT,TP,TT} = -normal(flip(em), pt) +normal(em::EllipsoidMantle{T,TR,TP,TT,:inwards}, pt::CartesianPoint{T}) where {T,TR,TP,TT} = -normal(flip(em), pt) """ intersection(cm::EllipsoidMantle{T,NTuple{3,T}}, l::Line{T}) where {T} diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index 425123a80..f05911d9c 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -1,5 +1,5 @@ """ - struct Cone{T,CO,RT,TP} <: AbstractVolumePrimitive{T, CO} + struct Cone{T,CO,TR,TP} <: AbstractVolumePrimitive{T, CO} T: Type of values, e.g. Float64 CO: ClosedPrimitive or OpenPrimitive <-> whether surface belongs to it or not @@ -19,8 +19,8 @@ CO: ClosedPrimitive or OpenPrimitive <-> whether surface belongs to it or not * ... * `zH::T`: half hight/length of the cone """ -@with_kw struct Cone{T,CO,RT,TP} <: AbstractVolumePrimitive{T, CO} - r::RT = 1 +@with_kw struct Cone{T,CO,TR,TP} <: AbstractVolumePrimitive{T, CO} + r::TR = 1 φ::TP = nothing hZ::T = 1 @@ -28,10 +28,10 @@ CO: ClosedPrimitive or OpenPrimitive <-> whether surface belongs to it or not rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -Cone{T,CO,RT,TP}( c::Cone{T,CO,RT,TP}; COT = CO, +Cone{T,CO,TR,TP}( c::Cone{T,CO,TR,TP}; COT = CO, origin::CartesianPoint{T} = c.origin, - rotation::SMatrix{3,3,T,9} = c.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},RT,TP} = - Cone{T,COT,RT,TP}(c.r, c.φ, c.hZ, origin, rotation) + rotation::SMatrix{3,3,T,9} = c.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},TR,TP} = + Cone{T,COT,TR,TP}(c.r, c.φ, c.hZ, origin, rotation) #################################################################### #################################################################### diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl index ab9b9facf..14f11ced6 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Ellipsoid.jl @@ -1,5 +1,5 @@ -@with_kw struct Ellipsoid{T,CO,RT,TP,TT} <: AbstractVolumePrimitive{T, CO} - r::RT = 1 +@with_kw struct Ellipsoid{T,CO,TR,TP,TT} <: AbstractVolumePrimitive{T, CO} + r::TR = 1 φ::TP = nothing θ::TT = nothing @@ -7,10 +7,10 @@ rotation::SMatrix{3,3,T,9} = one(SMatrix{3, 3, T, 9}) end -Ellipsoid{T,CO,RT,TP,TT}( e::Ellipsoid{T,CO,RT,TP,TT}; COT = CO, +Ellipsoid{T,CO,TR,TP,TT}( e::Ellipsoid{T,CO,TR,TP,TT}; COT = CO, origin::CartesianPoint{T} = e.origin, - rotation::SMatrix{3,3,T,9} = e.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},RT,TP,TT} = - Ellipsoid{T,COT,RT,TP,TT}(e.r, e.φ, e.θ, origin, rotation) + rotation::SMatrix{3,3,T,9} = e.rotation) where {T,CO<:Union{ClosedPrimitive, OpenPrimitive},TR,TP,TT} = + Ellipsoid{T,COT,TR,TP,TT}(e.r, e.φ, e.θ, origin, rotation) const Sphere{T,CO,TP,TT} = Ellipsoid{T,CO,T,TP,TT} const FullSphere{T,CO} = Ellipsoid{T,CO,T,Nothing,Nothing} From dffb7bfd1ef1e0e487a10e7261bfcb7cb6ff427c Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 28 Jun 2021 17:08:49 +0200 Subject: [PATCH 239/241] Bugfix in `extremum` and code style --- src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl | 2 +- src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl | 4 ++-- .../SurfacePrimitives/EllipsoidMantle.jl | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl index 5feaaac84..f9096b5f8 100644 --- a/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl +++ b/src/ConstructiveSolidGeometry/LinePrimitives/Ellipse.jl @@ -24,7 +24,7 @@ const Circle{T} = Ellipse{T,T,Nothing} const PartialCircle{T} = Ellipse{T,T,Tuple{T,T}} extremum(e::Ellipse{T,T}) where {T} = e.r -extremum(e::Ellipse{T,Tuple{T,T}}) where {T} = max(e.r[1], e.r[2]) +extremum(e::Ellipse{T,Tuple{T,T}}) where {T} = max(e.r...) function sample(e::Circle{T}; n = 4)::Vector{CartesianPoint{T}} where {T} φs = range(T(0), step = T(2π) / n, length = n) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl index bded14cb7..33dbbfae4 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/ConeMantle.jl @@ -58,8 +58,8 @@ const FullConeMantle{T,D} = ConeMantle{T,Tuple{T,T},Nothing,D} # ugly name but w const PartialConeMantle{T,D} = ConeMantle{T,Tuple{T,T},Tuple{T,T},D} -extremum(cm::FullConeMantle{T}) where {T} = sqrt(cm.hZ^2 + max(cm.r[1], cm.r[2])^2) -extremum(cm::PartialConeMantle{T}) where {T} = sqrt(cm.hZ^2 + max(cm.r[1], cm.r[2])^2) +extremum(cm::FullConeMantle{T}) where {T} = sqrt(cm.hZ^2 + max(cm.r...)^2) +extremum(cm::PartialConeMantle{T}) where {T} = sqrt(cm.hZ^2 + max(cm.r...)^2) function lines(sp::FullConeMantle{T}) where {T} diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl index f42325645..b7d5a0311 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/EllipsoidMantle.jl @@ -27,7 +27,7 @@ function lines(em::FullEllipsoidMantle{T}) where {T} end extremum(e::EllipsoidMantle{T,T}) where {T} = e.r -extremum(e::EllipsoidMantle{T,NTuple{3,T}}) where {T} = max(e.r) +extremum(e::EllipsoidMantle{T,NTuple{3,T}}) where {T} = max(e.r...) function normal(em::EllipsoidMantle{T,NTuple{3,T},TP,TT,:outwards}, pt::CartesianPoint{T}) where {T,TP,TT} # not normalized, do we want this? From 5466111dd577395caab85d267385cb3deeb8c550 Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Mon, 28 Jun 2021 18:09:55 +0200 Subject: [PATCH 240/241] =?UTF-8?q?Remove=20unfinished=20implementation=20?= =?UTF-8?q?of=20`intersection=5Fwith=5F=CF=86=5Faxis`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SurfacePrimitives/Plane.jl | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl index 5bbe9ded7..0a0538c9e 100644 --- a/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl +++ b/src/ConstructiveSolidGeometry/SurfacePrimitives/Plane.jl @@ -16,22 +16,8 @@ _distance(pt::AbstractCoordinatePoint, p::Plane) = (pt - origin(p)) ⋅ normal(p distance(pt::AbstractCoordinatePoint, p::Plane) = abs(_distance(pt, p)) -""" - We assume l.direction is normalized -""" function intersection(p::Plane{T}, line::Line{T}) where {T} ndir = normalize(line.direction) λ = (p.normal ⋅ p.origin - p.normal ⋅ line.origin) / (p.normal ⋅ ndir) line.origin + λ * ndir end - -function intersection_with_φ_axis(p::Plane{T}, r::T, z::T) where {T} - n = normal(p) - o = origin(p) - u = n × CartesianVector{T}(-n[3], n[1], n[2]) - v = n × u - - error("This will be fun...") - - n ⋅ u, n ⋅ v -end From 325f0e89e7a44f49d6a398017ece18c7f894f9dd Mon Sep 17 00:00:00 2001 From: Lukas Hauertmann Date: Tue, 29 Jun 2021 10:49:16 +0200 Subject: [PATCH 241/241] Change `Interval` to `Tuple` --- src/ConstructiveSolidGeometry/IO.jl | 2 +- src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl | 6 +++--- src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ConstructiveSolidGeometry/IO.jl b/src/ConstructiveSolidGeometry/IO.jl index 45c98b305..768b0868b 100644 --- a/src/ConstructiveSolidGeometry/IO.jl +++ b/src/ConstructiveSolidGeometry/IO.jl @@ -73,7 +73,7 @@ end function _parse_linear_interval(::Type{T}, dict::AbstractDict, unit::Unitful.Units) where {T} @assert haskey(dict, "from") && haskey(dict, "to") "Please specify 'from' and 'to' in $(dict)." From::T, To::T = _parse_interval_from_to(T, dict, unit) - To == -From == zero(T) ? To : From..To # if != 0 is influences the origin + To == -From == zero(T) ? To : (From, To) # if != 0 is influences the origin end diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl index 47e44f7f9..22ff8e744 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Box.jl @@ -35,9 +35,9 @@ function Geometry(::Type{T}, ::Type{Box}, dict::AbstractDict, input_units::Named μy = typeof(y) <: Real ? zero(T) : mean(y) μz = typeof(z) <: Real ? zero(T) : mean(z) origin = CartesianPoint{T}(μx, μy, μz) - hX = typeof(x) <: Real ? x : width(x)/2 - hY = typeof(y) <: Real ? y : width(y)/2 - hZ = typeof(z) <: Real ? z : width(z)/2 + hX = typeof(x) <: Real ? x : (x[2] - x[1])/2 + hY = typeof(y) <: Real ? y : (y[2] - y[1])/2 + hZ = typeof(z) <: Real ? z : (z[2] - z[1])/2 box = Box{T, ClosedPrimitive}( hX = hX, hY = hY, diff --git a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl index f05911d9c..505802fa3 100644 --- a/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl +++ b/src/ConstructiveSolidGeometry/VolumePrimitives/Cone.jl @@ -573,7 +573,7 @@ function Geometry(::Type{T}, t::Type{Cone}, dict::AbstractDict, input_units::Nam r = parse_r_of_primitive(T, dict, length_unit, Cone) φ = parse_φ_of_primitive(T, dict, angle_unit) z = parse_height_of_primitive(T, dict, length_unit) - hZ = typeof(z) <: Real ? z : width(z)/2 + hZ = typeof(z) <: Real ? z : (z[2] - z[1])/2 origin = if typeof(z) <: Real CartesianPoint{T}(zero(T), zero(T), zero(T)) else