001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.units;
006
007import edu.wpi.first.units.measure.Force;
008
009/** A unit of force like {@link Units#Newtons}. */
010public final class ForceUnit extends MultUnit<MassUnit, LinearAccelerationUnit> {
011  private static final CombinatoryUnitCache<MassUnit, LinearAccelerationUnit, ForceUnit> cache =
012      new CombinatoryUnitCache<>(ForceUnit::new);
013
014  ForceUnit(MassUnit mass, LinearAccelerationUnit acceleration) {
015    super(
016        mass.isBaseUnit() && acceleration.isBaseUnit()
017            ? null
018            : combine(mass.getBaseUnit(), acceleration.getBaseUnit()),
019        mass,
020        acceleration);
021  }
022
023  ForceUnit(
024      ForceUnit baseUnit,
025      UnaryFunction toBaseConverter,
026      UnaryFunction fromBaseConverter,
027      String name,
028      String symbol) {
029    super(baseUnit, toBaseConverter, fromBaseConverter, name, symbol);
030  }
031
032  /**
033   * Combines a mass and (linear) acceleration to form a unit of force.
034   *
035   * @param mass the unit of mass
036   * @param acceleration the unit of acceleration
037   * @return the combined unit of force
038   */
039  public static ForceUnit combine(MassUnit mass, LinearAccelerationUnit acceleration) {
040    return cache.combine(mass, acceleration);
041  }
042
043  @Override
044  public ForceUnit getBaseUnit() {
045    return (ForceUnit) super.getBaseUnit();
046  }
047
048  /**
049   * Multiplies this force unit by a unit of distance to create a unit of torque.
050   *
051   * @param distance the unit of distance
052   * @return the combined torque unit
053   */
054  public TorqueUnit multAsTorque(DistanceUnit distance) {
055    return TorqueUnit.combine(distance, this);
056  }
057
058  // TODO: Add a multAsEnergy equivalent
059
060  @Override
061  public Force of(double magnitude) {
062    return new Force(magnitude, toBaseUnits(magnitude), this);
063  }
064
065  @Override
066  public Force ofBaseUnits(double baseUnitMagnitude) {
067    return new Force(toBaseUnits(baseUnitMagnitude), baseUnitMagnitude, this);
068  }
069
070  @Override
071  public Force zero() {
072    return (Force) super.zero();
073  }
074
075  @Override
076  public Force one() {
077    return (Force) super.one();
078  }
079
080  @Override
081  public VelocityUnit<ForceUnit> per(TimeUnit time) {
082    return VelocityUnit.combine(this, time);
083  }
084
085  /**
086   * Creates a ratio unit between this unit and an arbitrary other unit.
087   *
088   * @param other the other unit
089   * @param <U> the type of the other unit
090   * @return the ratio unit
091   */
092  public <U extends Unit> PerUnit<ForceUnit, U> per(U other) {
093    return PerUnit.combine(this, other);
094  }
095
096  /**
097   * Converts a measurement value in terms of another unit to this unit.
098   *
099   * @param magnitude the magnitude of the measurement in terms of the other unit
100   * @param otherUnit the other unit
101   * @return the value of the measurement in terms of this unit
102   */
103  public double convertFrom(double magnitude, ForceUnit otherUnit) {
104    return fromBaseUnits(otherUnit.toBaseUnits(magnitude));
105  }
106}