2

几个月前我发现了 JScience,它对我的​​项目有很大的帮助,尽管我正在为一件事而苦苦挣扎。

我正在尝试创建一个PressureHead(又名水柱)单元,可以直接使用给定值进行转换,也可以使用给定值Length间接进行转换。PressureVolumetricDensity

寻找压力:Density × Gravity × Head = Pressure

这是来自Wikipedia的示例转换:

1 cmH 2 O (4°C) = 999.9720 kg/m 3 × 9.80665 m/s 2 × 1 cm = 98.063754138 Pa

1 cmH 2 O 可以直接换算成1 cm。

假设我知道以 Pa 为单位的压力,并想找到以 mH 2 O 为单位的压头,这是我在项目中最常进行的转换。我还需要知道流体的密度。压力和密度是可变输入。重力也必须是已知的公式,但出于我的目的,它可以固定为标准重力。

查找压头:Pressure / (Density × Gravity) = Head

为简单起见,我只是重新利用了上述示例中的值,将压力乘以 100 得到 1 mH 2 O 而不是 1 cmH 2 O。

9806.3754138 Pa / (999.9720 kg/m 3 × 9.80665 m/s 2 ) = 1 mH 2 O

看起来 JScience 可能足够灵活以允许这样的单元,但我还没有看到任何示例来帮助我创建它。最坏的情况,我可能会满足于使用 util 方法在它们之间进行转换。

编辑

我希望看到的一些理想用法示例:

// Pressure to PressureHead
Amount<Pressure> pressure = Amount.valueOf(9806.3754138, PASCAL);
Amount<VolumetricDensity> density = Amount.valueOf(999.9720, KG_M3);
Amount<PressureHead> head = pressure.to(M_H2O, density);
System.out.println(pressure.doubleValue(M_H2O, density)); // 1.0

// PressureHead <-> Length
Amount<Length> length = head.to(METER);
System.out.println(head.doubleValue(METER)); // 1.0
head = length.to(M_H2O);
System.out.println(length.doubleValue(M_H2O)); // 1.0

// PressureHead to Pressure
pressure = head.to(PASCAL, density);
System.out.println(head.doubleValue(PASCAL, density)); // 9806.3754138

单位之间的转换PressureHead很容易。我可以像这样定义其他单位:

Unit<PressureHead> FT_H2O = M_H2O.transform(FOOT.getConverterTo(METER));

对于上面的理想用法,我需要子类化Amount和重载to()and doubleValue()。我怀疑是否有更合适的方式进行转换(尽管不是很漂亮),它涉及子类UnitConverter化和/或DerivedUnit基于 - 的类之一。

我的一部分想放弃,走捷径(和丑陋)的 util 方法,这样我就可以继续做更重要的事情,另一部分想找到一个让我更喜欢 JScience 的解决方案。

4

1 回答 1

0

虽然我现在不再需要进行这种转换,但在将大部分项目(除了 UI 代码)转换为 Kotlin 并找到喜欢 Kotlin 的理由后,我正在重新审视这个问题。我做出了转换,因为我认为这是在项目仍处于早期阶段时学习语言的好机会。因此,这并不能完全回答我过去想要 Java 答案的自我,但我现在的自我很高兴接受这个作为答案。

该解决方案利用了 Kotlin 的扩展功能

为了防止这两个方向发生冲突,它们必须使用不同的函数名或定义在不同的对象或包中。

object PressureToHead {
    fun Amount<Pressure>.to(unit: Unit<PressureHead>,
            fluidDensity: Amount<VolumetricDensity>): Amount<PressureHead> {
        return Amount.valueOf(doubleValue(PASCAL)
                / (fluidDensity.doubleValue(KG_M3)
                * SensorManager.GRAVITY_EARTH), M_H2O).to(unit)
    }

    fun Amount<Pressure>.doubleValue(unit: Unit<PressureHead>,
            fluidDensity: Amount<VolumetricDensity>): Double {
        return to(unit, fluidDensity).estimatedValue
    }
}

object HeadToPressure {
    fun Amount<PressureHead>.to(unit: Unit<Pressure>,
            fluidDensity: Amount<VolumetricDensity>): Amount<Pressure> {
        return Amount.valueOf(fluidDensity.doubleValue(KG_M3)
                * SensorManager.GRAVITY_EARTH
                * doubleValue(M_H2O), PASCAL).to(unit)
    }

    fun Amount<PressureHead>.doubleValue(unit: Unit<Pressure>,
            fluidDensity: Amount<VolumetricDensity>): Double {
        return to(unit, fluidDensity).estimatedValue
    }
}

PressureHead为了在and之间进行转换Length,我不能使用相同的函数名,因为它们会遮蔽现有的函数名。最好的解决方案似乎是给函数一个不同的名字,我可以接受。

object HeadToLength {
    fun Amount<PressureHead>.toLength(unit: Unit<Length>): Amount<Length> {
        return Amount.valueOf(doubleValue(M_H2O), METER).to(unit)
    }

    fun Amount<PressureHead>.doubleValueLength(unit: Unit<Length>): Double {
        return toLength(unit).estimatedValue
    }
}

object LengthToHead {
    fun Amount<Length>.toHead(unit: Unit<PressureHead>): Amount<PressureHead> {
        return Amount.valueOf(doubleValue(METER), M_H2O).to(unit)
    }

    fun Amount<Length>.doubleValueHead(unit: Unit<PressureHead>): Double {
        return toHead(unit).estimatedValue
    }
}

除了转换的微小差异之外,用法完全符合我的要求Length。这次是用 Kotlin 编写的。

// Pressure to PressureHead
val density = Amount.valueOf(999.9720, KG_M3)
var pressure = Amount.valueOf(9806.3754138, PASCAL)
var head = pressure.to(M_H2O, density)
println(pressure.doubleValue(M_H2O, density)) // 1.0

// PressureHead to Pressure
pressure = head.to(PASCAL, density)
println(head.doubleValue(PASCAL, density)) // 9806.3754138

// PressureHead <-> Length
Amount<Length> length = head.toLength(METER)
println(head.doubleValueLength(METER)) // 1.0
head = length.toHead(M_H2O)
println(length.doubleValueHead(M_H2O)) // 1.0
于 2019-12-12T18:03:20.397 回答