From 6634b3ff6bcdffbab38a049460ae6ea3cd68944f Mon Sep 17 00:00:00 2001 From: sam-anthony Date: Thu, 31 Mar 2022 20:27:39 -0230 Subject: refactor and compressor map image widget --- compressor/compressor.go | 45 +++++++++++++++ compressor/res/GarrettG25660.jpg | Bin 0 -> 833764 bytes main.go | 91 +++++++++++++++++++++--------- mass.go | 86 ----------------------------- mass/mass.go | 86 +++++++++++++++++++++++++++++ pressure.go | 58 -------------------- pressure/pressure.go | 58 ++++++++++++++++++++ temperature.go | 71 ------------------------ temperature/temperature.go | 71 ++++++++++++++++++++++++ ui.go | 116 ++++++++++++++++++++++++--------------- util.go | 27 --------- util/util.go | 31 +++++++++++ volume.go | 54 ------------------ volume/volume.go | 54 ++++++++++++++++++ 14 files changed, 482 insertions(+), 366 deletions(-) create mode 100644 compressor/compressor.go create mode 100644 compressor/res/GarrettG25660.jpg delete mode 100644 mass.go create mode 100644 mass/mass.go delete mode 100644 pressure.go create mode 100644 pressure/pressure.go delete mode 100644 temperature.go create mode 100644 temperature/temperature.go delete mode 100644 util.go create mode 100644 util/util.go delete mode 100644 volume.go create mode 100644 volume/volume.go diff --git a/compressor/compressor.go b/compressor/compressor.go new file mode 100644 index 0000000..a3ac4bf --- /dev/null +++ b/compressor/compressor.go @@ -0,0 +1,45 @@ +package compressor + +import ( + "time" + + "github.com/sam-anthony/volute/mass" + "github.com/sam-anthony/volute/util" +) + +type Compressor struct { + FileName string + // MinX is the distance of the y-axis from left of image in pixels. + MinX int + // MinY is the distance of the x-axis from the top of the image in + //pixels. + MinY int + // MaxX is the distance of the end of the graph from the left of the + // image in pixels. + MaxX int + // MaxY is the distance of the top of the graph from the top of the + // image in pixels. + MaxY int + // MaxFlow is the mass flow rate at MaxX. + MaxFlow mass.FlowRate + // MaxPressureRatio is the pressure ratio at MaxY. + MaxPressureRatio float32 +} + +func GarrettG25660() Compressor { + maxFlow, err := mass.NewFlowRate( + mass.Mass{70, mass.Pound}, + time.Minute, + mass.PoundsPerMinute, + ) + util.Check(err) + return Compressor{ + "compressor/res/GarrettG25660.jpg", + 204, + 1885, + 1665, + 25, + maxFlow, + 4.0, + } +} diff --git a/compressor/res/GarrettG25660.jpg b/compressor/res/GarrettG25660.jpg new file mode 100644 index 0000000..aa8d12a Binary files /dev/null and b/compressor/res/GarrettG25660.jpg differ diff --git a/main.go b/main.go index 4af9cbb..82847bd 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,18 @@ package main import ( g "github.com/AllenDang/giu" + "image" + "image/draw" + _ "image/jpeg" + "os" "time" + + "github.com/sam-anthony/volute/compressor" + "github.com/sam-anthony/volute/mass" + "github.com/sam-anthony/volute/pressure" + "github.com/sam-anthony/volute/temperature" + "github.com/sam-anthony/volute/util" + "github.com/sam-anthony/volute/volume" ) const ( @@ -14,29 +25,29 @@ const ( var numPoints = 1 var ( - displacement = volume{2000, cubicCentimetre} - // selectedVolumeUnit is used to index volumeUnitStrings. - selectedVolumeUnit = defaultVolumeUnitIndex + displacement = volume.Volume{2000, volume.CubicCentimetre} + // selectedVolumeUnit is used to index volume.UnitStrings(). + selectedVolumeUnit = volume.DefaultUnitIndex engineSpeed = []int32{2000} volumetricEfficiency = []int32{80} - intakeAirTemperature = []temperature{{25, celcius}} - // selectedTemperatureUnit is used to index temperatureUnitStrings. - selectedTemperatureUnit = defaultTemperatureUnitIndex + intakeAirTemperature = []temperature.Temperature{{25, temperature.Celcius}} + // selectedTemperatureUnit is used to index temperature.UnitStrings(). + selectedTemperatureUnit = temperature.DefaultUnitIndex - manifoldPressure = []pressure{{100, defaultPressureUnit}} - // selectedPressureUnit is used to index pressureUnitStrings. - selectedPressureUnit = defaultPressureUnitIndex + manifoldPressure = []pressure.Pressure{{100, pressure.DefaultUnit}} + // selectedPressureUnit is used to index pressure.UnitStrings(). + selectedPressureUnit = pressure.DefaultUnitIndex ) var pressureRatio []float32 func pressureRatioAt(point int) float32 { - u := pascal - m := manifoldPressure[point].asUnit(u) - a := atmosphericPressure().asUnit(u) + u := pressure.Pascal + m := manifoldPressure[point].AsUnit(u) + a := pressure.Atmospheric().AsUnit(u) return m / a } func init() { @@ -44,31 +55,31 @@ func init() { } var ( - engineMassFlowRate []massFlowRate - // selectedMassFlowRateUnit is used to index massFlowRateUnitStrings. - selectedMassFlowRateUnit = defaultMassFlowRateUnitIndex + engineMassFlowRate []mass.FlowRate + // selectedMassFlowRateUnit is used to index mass.FlowRateUnitStrings(). + selectedMassFlowRateUnit = mass.DefaultFlowRateUnitIndex ) -func massFlowRateAt(point int) massFlowRate { +func massFlowRateAt(point int) mass.FlowRate { rpm := float32(engineSpeed[point]) - disp := displacement.asUnit(cubicMetre) + disp := displacement.AsUnit(volume.CubicMetre) ve := float32(volumetricEfficiency[point]) / 100.0 cubicMetresPerMin := (rpm / 2.0) * disp * ve - iat, err := intakeAirTemperature[point].asUnit(kelvin) - check(err) - pres := manifoldPressure[point].asUnit(pascal) + iat, err := intakeAirTemperature[point].AsUnit(temperature.Kelvin) + util.Check(err) + pres := manifoldPressure[point].AsUnit(pressure.Pascal) molsPerMin := (pres * cubicMetresPerMin) / (gasConstant * iat) kgPerMin := molsPerMin * airMolarMass - massPerMin := mass{kgPerMin, kilogram} + massPerMin := mass.Mass{kgPerMin, mass.Kilogram} - u, err := massFlowRateUnitFromString(massFlowRateUnitStrings()[selectedMassFlowRateUnit]) - check(err) + u, err := mass.FlowRateUnitFromString(mass.FlowRateUnitStrings()[selectedMassFlowRateUnit]) + util.Check(err) - mfr, err := newMassFlowRate(massPerMin, time.Minute, u) - check(err) + mfr, err := mass.NewFlowRate(massPerMin, time.Minute, u) + util.Check(err) return mfr } func init() { @@ -79,6 +90,7 @@ func loop() { g.SingleWindow().Layout( engineDisplacementRow(), g.Table(). + Size(g.Auto, 190). Rows( engineSpeedRow(), volumetricEfficiencyRow(), @@ -91,10 +103,39 @@ func loop() { Columns( columns()..., ), + g.Custom(compressorWidget), ) } +var ( + compressorImage *image.RGBA + compressorTexture *g.Texture + selectedCompressor compressor.Compressor +) + +func init() { + selectedCompressor = compressor.GarrettG25660() + + f, err := os.Open(selectedCompressor.FileName) + util.Check(err) + defer f.Close() + + j, _, err := image.Decode(f) + util.Check(err) + + b := j.Bounds() + m := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy())) + draw.Draw(m, m.Bounds(), j, b.Min, draw.Src) + + compressorImage = m +} + func main() { wnd := g.NewMasterWindow("volute", 400, 200, 0) + + g.EnqueueNewTextureFromRgba(compressorImage, func(tex *g.Texture) { + compressorTexture = tex + }) + wnd.Run(loop) } diff --git a/mass.go b/mass.go deleted file mode 100644 index 0b97020..0000000 --- a/mass.go +++ /dev/null @@ -1,86 +0,0 @@ -package main - -import ( - "errors" - "fmt" - "time" -) - -type massUnit float32 - -const ( - gram massUnit = 1 - kilogram massUnit = 1_000 - pound massUnit = 453.5924 -) - -type mass struct { - val float32 - unit massUnit -} - -func (m mass) asUnit(u massUnit) float32 { - g := m.val * float32(m.unit) // Convert to grams. - return g / float32(u) // Convert to desired unit. -} - -type massFlowRateUnit float32 - -const ( - kilogramsPerSecond massFlowRateUnit = 1 - poundsPerMinute massFlowRateUnit = 0.007_559_872_833 -) - -// massFlowRateUnitStrings returns a slice of strings, each representing a -// massFlowRateUnit. -// This is necessary because giu.Combo only works with strings. -func massFlowRateUnitStrings() []string { - return []string{"kg/s", "lb/min"} -} - -const ( - defaultMassFlowRateUnit massFlowRateUnit = kilogramsPerSecond - //Used to index massFlowRateUnitStrings - defaultMassFlowRateUnitIndex int32 = 0 // kg/s -) - -func massFlowRateUnitFromString(s string) (massFlowRateUnit, error) { - // Each case corresponds to a value in massFlowRateUnitStrings. - switch s { - case "kg/s": - return kilogramsPerSecond, nil - case "lb/min": - return poundsPerMinute, nil - default: - return *new(massFlowRateUnit), errors.New( - fmt.Sprintf("invalid massFlowRateUnit: '%s'", s)) - } -} - -type massFlowRate struct { - val float32 - unit massFlowRateUnit -} - -func newMassFlowRate(m mass, t time.Duration, u massFlowRateUnit) (massFlowRate, error) { - switch u { - case kilogramsPerSecond: - return massFlowRate{ - m.asUnit(kilogram) / float32(t.Seconds()), - u, - }, nil - case poundsPerMinute: - return massFlowRate{ - m.asUnit(pound) / float32(t.Minutes()), - u, - }, nil - default: - return *new(massFlowRate), errors.New( - fmt.Sprintf("invalid massFlowRateUnit: '%v'", u)) - } -} - -func (fr massFlowRate) asUnit(u massFlowRateUnit) float32 { - kgps := fr.val * float32(fr.unit) // Convert to kilogramsPerSecond. - return kgps / float32(u) // Convert to desired unit. -} diff --git a/mass/mass.go b/mass/mass.go new file mode 100644 index 0000000..29ecbd5 --- /dev/null +++ b/mass/mass.go @@ -0,0 +1,86 @@ +package mass + +import ( + "errors" + "fmt" + "time" +) + +type unit float32 + +const ( + Gram unit = 1 + Kilogram unit = 1_000 + Pound unit = 453.5924 +) + +type Mass struct { + Val float32 + Unit unit +} + +func (m Mass) AsUnit(u unit) float32 { + g := m.Val * float32(m.Unit) // Convert to grams. + return g / float32(u) // Convert to desired unit. +} + +type flowRateUnit float32 + +const ( + KilogramsPerSecond flowRateUnit = 1 + PoundsPerMinute flowRateUnit = 0.007_559_872_833 +) + +// FlowRateUnitStrings returns a slice of strings, each representing a +// flowRateUnit. +// This is necessary because giu.Combo only works with strings. +func FlowRateUnitStrings() []string { + return []string{"kg/s", "lb/min"} +} + +const ( + DefaultFlowRateUnit flowRateUnit = KilogramsPerSecond + // DefaultFlowRateUnitIndex is used to index FlowRateUnitStrings() + DefaultFlowRateUnitIndex int32 = 0 // kg/s +) + +func FlowRateUnitFromString(s string) (flowRateUnit, error) { + // Each case corresponds to a value in FlowRateUnitStrings(). + switch s { + case "kg/s": + return KilogramsPerSecond, nil + case "lb/min": + return PoundsPerMinute, nil + default: + return *new(flowRateUnit), errors.New( + fmt.Sprintf("invalid massFlowRateUnit: '%s'", s)) + } +} + +type FlowRate struct { + Val float32 + Unit flowRateUnit +} + +func NewFlowRate(m Mass, t time.Duration, u flowRateUnit) (FlowRate, error) { + switch u { + case KilogramsPerSecond: + return FlowRate{ + m.AsUnit(Kilogram) / float32(t.Seconds()), + u, + }, nil + case PoundsPerMinute: + return FlowRate{ + m.AsUnit(Pound) / float32(t.Minutes()), + u, + }, nil + default: + return *new(FlowRate), errors.New( + fmt.Sprintf("invalid massFlowRateUnit: '%v'", u)) + } +} + +func (fr FlowRate) AsUnit(u flowRateUnit) float32 { + kgps := fr.Val * float32(fr.Unit) // Convert to kilogramsPerSecond. + return kgps / float32(u) // Convert to desired unit. +} diff --git a/pressure.go b/pressure.go deleted file mode 100644 index a6665dc..0000000 --- a/pressure.go +++ /dev/null @@ -1,58 +0,0 @@ -package main - -import ( - "errors" - "fmt" -) - -type pressureUnit float32 - -const ( - pascal pressureUnit = 1 - kilopascal pressureUnit = 1_000 - bar pressureUnit = 100_000 - poundsPerSquareInch pressureUnit = 6_894.757 -) - -// pressureUnitStrings returns a slice of strings, each representing a -// pressureUnit. -// This is necessary because giu.Combo only works with strings. -func pressureUnitStrings() []string { - return []string{"Pa", "kPa", "bar", "psi"} -} - -const ( - defaultPressureUnit pressureUnit = kilopascal - // Used to index pressureUnitStrings - defaultPressureUnitIndex int32 = 1 // kPa -) - -func pressureUnitFromString(s string) (pressureUnit, error) { - // Each case corresponds to a value in pressureUnitStrings - switch s { - case "Pa": - return pascal, nil - case "kPa": - return kilopascal, nil - case "bar": - return bar, nil - case "psi": - return poundsPerSquareInch, nil - default: - return *new(pressureUnit), errors.New(fmt.Sprintf("invalid pressureUnit: '%s'", s)) - } -} - -type pressure struct { - val float32 - unit pressureUnit -} - -func (p pressure) asUnit(u pressureUnit) float32 { - pa := p.val * float32(p.unit) // Convert to pascals. - return pa / float32(u) // Convert to desired unit. -} - -func atmosphericPressure() pressure { - return pressure{1, bar} -} diff --git a/pressure/pressure.go b/pressure/pressure.go new file mode 100644 index 0000000..2948c72 --- /dev/null +++ b/pressure/pressure.go @@ -0,0 +1,58 @@ +package pressure + +import ( + "errors" + "fmt" +) + +type unit float32 + +const ( + Pascal unit = 1 + Kilopascal unit = 1_000 + Bar unit = 100_000 + PoundsPerSquareInch unit = 6_894.757 +) + +// UnitStrings returns a slice of strings, each representing a +// unit. +// This is necessary because giu.Combo only works with strings. +func UnitStrings() []string { + return []string{"Pa", "kPa", "bar", "psi"} +} + +const ( + DefaultUnit unit = Kilopascal + // DefaultUnitIndex is used to index UnitStrings(). + DefaultUnitIndex int32 = 1 // kPa +) + +func UnitFromString(s string) (unit, error) { + // Each case corresponds to a value in UnitStrings(). + switch s { + case "Pa": + return Pascal, nil + case "kPa": + return Kilopascal, nil + case "bar": + return Bar, nil + case "psi": + return PoundsPerSquareInch, nil + default: + return *new(unit), errors.New(fmt.Sprintf("invalid unit: '%s'", s)) + } +} + +type Pressure struct { + Val float32 + Unit unit +} + +func (p Pressure) AsUnit(u unit) float32 { + pa := p.Val * float32(p.Unit) // Convert to pascals. + return pa / float32(u) // Convert to desired unit. +} + +func Atmospheric() Pressure { + return Pressure{1, Bar} +} diff --git a/temperature.go b/temperature.go deleted file mode 100644 index 7562ca7..0000000 --- a/temperature.go +++ /dev/null @@ -1,71 +0,0 @@ -package main - -import ( - "errors" - "fmt" -) - -type temperatureUnit int - -const ( - celcius temperatureUnit = iota - kelvin - fahrenheit -) - -// temperatureUnitStrings returns a slice of strings, each representing a -// temperatureUnit. -// This is necessary because giu.Combo only works with strings. -func temperatureUnitStrings() []string { - return []string{"°C", "°K", "°F"} -} - -const ( - defaultTemperatureUnit temperatureUnit = celcius - // Used to index temperatureUnitStrings - defaultTemperatureUnitIndex int32 = 0 // celcius -) - -func temperatureUnitFromString(s string) (temperatureUnit, error) { - // Each case corresponds to a value in volumeUnitStrings. - switch s { - case "°C": - return celcius, nil - case "°K": - return kelvin, nil - case "°F": - return fahrenheit, nil - default: - return *new(temperatureUnit), errors.New(fmt.Sprintf("invalid temperatureUnit: '%s'", s)) - } -} - -type temperature struct { - val float32 - unit temperatureUnit -} - -func (t temperature) asUnit(u temperatureUnit) (float32, error) { - // Convert to celcius - var c float32 - switch t.unit { - case celcius: - c = t.val - case kelvin: - c = t.val - 272.15 - case fahrenheit: - c = (t.val - 32.0) * (5.0 / 9.0) - } - - // Convert to desired unit - switch u { - case celcius: - return c, nil - case kelvin: - return c + 272.15, nil - case fahrenheit: - return c*(9.0/5.0) + 32.0, nil - default: - return 0, errors.New(fmt.Sprintf("invalid temperatureUnit: '%v'", u)) - } -} diff --git a/temperature/temperature.go b/temperature/temperature.go new file mode 100644 index 0000000..2a135df --- /dev/null +++ b/temperature/temperature.go @@ -0,0 +1,71 @@ +package temperature + +import ( + "errors" + "fmt" +) + +type unit int + +const ( + Celcius unit = iota + Kelvin + Fahrenheit +) + +// UnitStrings returns a slice of strings, each representing a +// unit. +// This is necessary because giu.Combo only works with strings. +func UnitStrings() []string { + return []string{"°C", "°K", "°F"} +} + +const ( + DefaultUnit unit = Celcius + // DefaultUnitIndex is used to index UnitStrings(). + DefaultUnitIndex int32 = 0 // celcius +) + +func UnitFromString(s string) (unit, error) { + // Each case corresponds to a value in UnitStrings(). + switch s { + case "°C": + return Celcius, nil + case "°K": + return Kelvin, nil + case "°F": + return Fahrenheit, nil + default: + return *new(unit), errors.New(fmt.Sprintf("invalid unit: '%s'", s)) + } +} + +type Temperature struct { + Val float32 + Unit unit +} + +func (t Temperature) AsUnit(u unit) (float32, error) { + // Convert to celcius + var c float32 + switch t.Unit { + case Celcius: + c = t.Val + case Kelvin: + c = t.Val - 272.15 + case Fahrenheit: + c = (t.Val - 32.0) * (5.0 / 9.0) + } + + // Convert to desired unit + switch u { + case Celcius: + return c, nil + case Kelvin: + return c + 272.15, nil + case Fahrenheit: + return c*(9.0/5.0) + 32.0, nil + default: + return 0, errors.New(fmt.Sprintf("invalid unit: '%v'", u)) + } +} diff --git a/ui.go b/ui.go index b12ff07..0515c46 100644 --- a/ui.go +++ b/ui.go @@ -3,28 +3,35 @@ package main import ( "fmt" g "github.com/AllenDang/giu" + "image" "strconv" + + "github.com/sam-anthony/volute/mass" + "github.com/sam-anthony/volute/pressure" + "github.com/sam-anthony/volute/temperature" + "github.com/sam-anthony/volute/util" + "github.com/sam-anthony/volute/volume" ) func engineDisplacementRow() *g.RowWidget { return g.Row( g.Label("Engine Displacement"), - g.InputFloat(&displacement.val).Format("%.2f").OnChange(func() { + g.InputFloat(&displacement.Val).Format("%.2f").OnChange(func() { for i := 0; i < numPoints; i++ { engineMassFlowRate[i] = massFlowRateAt(i) } }), g.Combo( "", - volumeUnitStrings()[selectedVolumeUnit], - volumeUnitStrings(), + volume.UnitStrings()[selectedVolumeUnit], + volume.UnitStrings(), &selectedVolumeUnit, ).OnChange(func() { - s := volumeUnitStrings()[selectedVolumeUnit] - u, err := volumeUnitFromString(s) - check(err) - displacement = volume{ - displacement.asUnit(u), + s := volume.UnitStrings()[selectedVolumeUnit] + u, err := volume.UnitFromString(s) + util.Check(err) + displacement = volume.Volume{ + displacement.AsUnit(u), u, } }), @@ -70,18 +77,18 @@ func intakeAirTemperatureRow() *g.TableRowWidget { g.Label("Intake Air Temperature"), g.Combo( "", - temperatureUnitStrings()[selectedTemperatureUnit], - temperatureUnitStrings(), + temperature.UnitStrings()[selectedTemperatureUnit], + temperature.UnitStrings(), &selectedTemperatureUnit, ).OnChange(func() { - s := temperatureUnitStrings()[selectedTemperatureUnit] - u, err := temperatureUnitFromString(s) - check(err) + s := temperature.UnitStrings()[selectedTemperatureUnit] + u, err := temperature.UnitFromString(s) + util.Check(err) for i := range intakeAirTemperature { - t, err := intakeAirTemperature[i].asUnit(u) - check(err) - intakeAirTemperature[i] = temperature{t, u} + t, err := intakeAirTemperature[i].AsUnit(u) + util.Check(err) + intakeAirTemperature[i] = temperature.Temperature{t, u} } }), } @@ -89,7 +96,7 @@ func intakeAirTemperatureRow() *g.TableRowWidget { i := i widgets = append( widgets, - g.InputFloat(&intakeAirTemperature[i].val). + g.InputFloat(&intakeAirTemperature[i].Val). Format("%.2f"). OnChange(func() { engineMassFlowRate[i] = massFlowRateAt(i) @@ -104,17 +111,17 @@ func manifoldPressureRow() *g.TableRowWidget { g.Label("Manifold Absolute Pressure"), g.Combo( "", - pressureUnitStrings()[selectedPressureUnit], - pressureUnitStrings(), + pressure.UnitStrings()[selectedPressureUnit], + pressure.UnitStrings(), &selectedPressureUnit, ).OnChange(func() { - s := pressureUnitStrings()[selectedPressureUnit] - u, err := pressureUnitFromString(s) - check(err) + s := pressure.UnitStrings()[selectedPressureUnit] + u, err := pressure.UnitFromString(s) + util.Check(err) for i := 0; i < numPoints; i++ { - manifoldPressure[i] = pressure{ - manifoldPressure[i].asUnit(u), + manifoldPressure[i] = pressure.Pressure{ + manifoldPressure[i].AsUnit(u), u, } } @@ -124,7 +131,7 @@ func manifoldPressureRow() *g.TableRowWidget { i := i widgets = append( widgets, - g.InputFloat(&manifoldPressure[i].val).Format("%.2f"). + g.InputFloat(&manifoldPressure[i].Val).Format("%.2f"). OnChange(func() { pressureRatio[i] = pressureRatioAt(i) engineMassFlowRate[i] = massFlowRateAt(i) @@ -154,17 +161,17 @@ func massFlowRateRow() *g.TableRowWidget { g.Label("Mass Flow Rate"), g.Combo( "", - massFlowRateUnitStrings()[selectedMassFlowRateUnit], - massFlowRateUnitStrings(), + mass.FlowRateUnitStrings()[selectedMassFlowRateUnit], + mass.FlowRateUnitStrings(), &selectedMassFlowRateUnit, ).OnChange(func() { - s := massFlowRateUnitStrings()[selectedMassFlowRateUnit] - u, err := massFlowRateUnitFromString(s) - check(err) + s := mass.FlowRateUnitStrings()[selectedMassFlowRateUnit] + u, err := mass.FlowRateUnitFromString(s) + util.Check(err) for i := 0; i < numPoints; i++ { - engineMassFlowRate[i] = massFlowRate{ - engineMassFlowRate[i].asUnit(u), + engineMassFlowRate[i] = mass.FlowRate{ + engineMassFlowRate[i].AsUnit(u), u, } } @@ -172,7 +179,7 @@ func massFlowRateRow() *g.TableRowWidget { } for i := 0; i < numPoints; i++ { mfr := strconv.FormatFloat( - float64(engineMassFlowRate[i].val), + float64(engineMassFlowRate[i].Val), 'f', 3, 32, @@ -192,32 +199,32 @@ func duplicateDeleteRow() *g.TableRowWidget { widgets = append(widgets, g.Row( g.Button("Duplicate").OnClick(func() { numPoints++ - engineSpeed = insert( + engineSpeed = util.Insert( engineSpeed, engineSpeed[i], i, ) - volumetricEfficiency = insert( + volumetricEfficiency = util.Insert( volumetricEfficiency, volumetricEfficiency[i], i, ) - intakeAirTemperature = insert( + intakeAirTemperature = util.Insert( intakeAirTemperature, intakeAirTemperature[i], i, ) - manifoldPressure = insert( + manifoldPressure = util.Insert( manifoldPressure, manifoldPressure[i], i, ) - pressureRatio = insert( + pressureRatio = util.Insert( pressureRatio, pressureRatio[i], i, ) - engineMassFlowRate = insert( + engineMassFlowRate = util.Insert( engineMassFlowRate, engineMassFlowRate[i], i, @@ -228,12 +235,12 @@ func duplicateDeleteRow() *g.TableRowWidget { return } numPoints-- - engineSpeed = remove(engineSpeed, i) - volumetricEfficiency = remove(volumetricEfficiency, i) - intakeAirTemperature = remove(intakeAirTemperature, i) - manifoldPressure = remove(manifoldPressure, i) - pressureRatio = remove(pressureRatio, i) - engineMassFlowRate = remove(engineMassFlowRate, i) + engineSpeed = util.Remove(engineSpeed, i) + volumetricEfficiency = util.Remove(volumetricEfficiency, i) + intakeAirTemperature = util.Remove(intakeAirTemperature, i) + manifoldPressure = util.Remove(manifoldPressure, i) + pressureRatio = util.Remove(pressureRatio, i) + engineMassFlowRate = util.Remove(engineMassFlowRate, i) }), )) } @@ -253,3 +260,22 @@ func columns() []*g.TableColumnWidget { } return widgets } + +func compressorWidget() { + m := compressorImage + // TODO: Apply points to compressor map. + + g.EnqueueNewTextureFromRgba(m, func(tex *g.Texture) { + compressorTexture = tex + }) + + canvas := g.GetCanvas() + if compressorTexture != nil { + winWidth, winHeight := g.GetAvailableRegion() + canvas.AddImage( + compressorTexture, + image.Pt(0, 225), + image.Pt(int(winWidth), int(winHeight)), + ) + } +} diff --git a/util.go b/util.go deleted file mode 100644 index c11ff40..0000000 --- a/util.go +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "fmt" - "os" -) - -func check(err error) { - if err != nil { - fmt.Println(err) - os.Exit(1) - } -} - -func insert[T int32 | float32 | temperature | pressure | massFlowRate](slice []T, elem T, i int) []T { - return append( - slice[:i], - append( - []T{elem}, - slice[i:]..., - )..., - ) -} - -func remove[T int32 | float32 | temperature | pressure | massFlowRate](slice []T, i int) []T { - return append(slice[:i], slice[i+1:]...) -} diff --git a/util/util.go b/util/util.go new file mode 100644 index 0000000..5812ee1 --- /dev/null +++ b/util/util.go @@ -0,0 +1,31 @@ +package util + +import ( + "fmt" + "os" + + "github.com/sam-anthony/volute/mass" + "github.com/sam-anthony/volute/pressure" + "github.com/sam-anthony/volute/temperature" +) + +func Check(err error) { + if err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func Insert[T int32 | float32 | temperature.Temperature | pressure.Pressure | mass.FlowRate](slice []T, elem T, i int) []T { + return append( + slice[:i], + append( + []T{elem}, + slice[i:]..., + )..., + ) +} + +func Remove[T int32 | float32 | temperature.Temperature | pressure.Pressure | mass.FlowRate](slice []T, i int) []T { + return append(slice[:i], slice[i+1:]...) +} diff --git a/volume.go b/volume.go deleted file mode 100644 index cb7098a..0000000 --- a/volume.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "errors" - "fmt" -) - -type volumeUnit float32 - -const ( - cubicCentimetre volumeUnit = 1 - litre volumeUnit = 1_000 - cubicMetre volumeUnit = 1_000_000 - cubicInch volumeUnit = 16.38706 -) - -// volumeUnitStrings returns a slice of strings, each representing a -// volumeUnit. -// This is necessary because giu.Combo only works with strings. -func volumeUnitStrings() []string { - return []string{"cc", "L", "m³", "in³"} -} - -const ( - defaultVolumeUnit volumeUnit = cubicCentimetre - // Used to index volumeUnitStrings - defaultVolumeUnitIndex int32 = 0 // cc -) - -func volumeUnitFromString(s string) (volumeUnit, error) { - // Each case corresponds to a value in volumeUnitStrings - switch s { - case "cc": - return cubicCentimetre, nil - case "L": - return litre, nil - case "m³": - return cubicMetre, nil - case "in³": - return cubicInch, nil - default: - return *new(volumeUnit), errors.New(fmt.Sprintf("invalid volumeUnit: '%s'", s)) - } -} - -type volume struct { - val float32 - unit volumeUnit -} - -func (v volume) asUnit(u volumeUnit) float32 { - cc := v.val * float32(v.unit) // Convert to cubic centimetres. - return cc / float32(u) // Convert to desired unit. -} diff --git a/volume/volume.go b/volume/volume.go new file mode 100644 index 0000000..020d1a6 --- /dev/null +++ b/volume/volume.go @@ -0,0 +1,54 @@ +package volume + +import ( + "errors" + "fmt" +) + +type unit float32 + +const ( + CubicCentimetre unit = 1 + Litre unit = 1_000 + CubicMetre unit = 1_000_000 + CubicInch unit = 16.38706 +) + +// UnitStrings returns a slice of strings, each representing a +// unit. +// This is necessary because giu.Combo only works with strings. +func UnitStrings() []string { + return []string{"cc", "L", "m³", "in³"} +} + +const ( + DefaultUnit unit = CubicCentimetre + // DefaulUnitIndex is used to index UnitStrings(). + DefaultUnitIndex int32 = 0 // cc +) + +func UnitFromString(s string) (unit, error) { + // Each case corresponds to a value in UnitStrings(). + switch s { + case "cc": + return CubicCentimetre, nil + case "L": + return Litre, nil + case "m³": + return CubicMetre, nil + case "in³": + return CubicInch, nil + default: + return *new(unit), errors.New(fmt.Sprintf("invalid volume unit: '%s'", s)) + } +} + +type Volume struct { + Val float32 + Unit unit +} + +func (v Volume) AsUnit(u unit) float32 { + cc := v.Val * float32(v.Unit) // Convert to cubic centimetres. + return cc / float32(u) // Convert to desired unit. +} -- cgit v1.2.3