// // (C) Copyright 2003-2019 by Autodesk, Inc. // // Permission to use, copy, modify, and distribute this software in // object code form for any purpose and without fee is hereby granted, // provided that the above copyright notice appears in all copies and // that both that copyright notice and the limited warranty and // restricted rights notice below appear in all supporting // documentation. // // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE // UNINTERRUPTED OR ERROR FREE. // // Use, duplication, or disclosure by the U.S. Government is subject to // restrictions set forth in FAR 52.227-19 (Commercial Computer // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. // using System; using System.Collections.Generic; using System.Globalization; namespace Revit.SDK.Samples.SharedCoordinateSystem.CS { /// /// define type of value /// public enum ValueType { /// /// general value /// General = 0, /// /// angle value /// Angle } /// /// a class used to deal with converting operation /// public class UnitConversion { private static readonly int DefaultPrecision = 3; //default precision private static readonly double AngleRatio = 0.0174532925199433; //ratio of Angle /// /// convert CityInfo into CityInfoString /// /// CityInfo need to convert /// conversion result public static CityInfoString ConvertFrom(CityInfo cityInfo) { CityInfoString cityInfoString = new CityInfoString(); cityInfoString.Latitude = DoubleToString(cityInfo.Latitude, ValueType.Angle); cityInfoString.Longitude = DoubleToString(cityInfo.Longitude, ValueType.Angle); return cityInfoString; } /// /// convert CityInfoString into CityInfo /// /// CityInfoString need to convert /// conversion result public static CityInfo ConvertTo(CityInfoString cityInfoString) { CityInfo cityInfo = new CityInfo(); double temp; //convert Latitude if (StringToDouble(cityInfoString.Latitude, ValueType.Angle, out temp)) { cityInfo.Latitude = temp; } else { cityInfo.Latitude = Double.NaN; } //convert Longitude if (StringToDouble(cityInfoString.Longitude, ValueType.Angle, out temp)) { cityInfo.Longitude = temp; } else { cityInfo.Longitude = Double.NaN; } return cityInfo; } /// /// deal with value according to precision /// /// original value will be dealed /// precision wanted to be set /// return the dealed value public static double DealPrecision(double value, int precision) { //first make sure 0 =< precision <= 15 if (precision < 0 && precision > 15) { return value; } //if >1 or < -1,just use Math.Round to deal with double newValue; if (value >= 1 || value <= -1 || 0 == value) { //Math.Round: returns the number with the specified precision //nearest the specified value. newValue = Math.Round(value, precision); return newValue; } //if -1 < value < 1, //find first number which is not "0" //compare it with precision, then select //min of them as final precision int firstNumberPos = 0; double temp = Math.Abs(value); for (firstNumberPos = 1; ; firstNumberPos++) { temp *= 10; if (temp >= 1) { break; } } //make sure firstNumberPos <= 15 if (firstNumberPos > 15) { firstNumberPos = 15; } //Math.Round: returns the number with the specified precision //nearest the specified value. newValue = Math.Round(value, firstNumberPos > precision ? firstNumberPos : precision); return newValue; } /// /// convert double into string /// /// double value need to convert /// value type /// conversion result public static string DoubleToString(double value, ValueType valueType) { string displayText = null; // string included value and unit of parameter double newValue; ValueConversion(value, ValueType.Angle, true, out newValue); value = newValue; newValue = DealPrecision(value, DefaultPrecision); //calculate the number after ".",if less than DecimalNumber // add some "0" after it displayText = DealDecimalNumber(newValue.ToString(), DefaultPrecision); if(ValueType.Angle == valueType) { char degree = (char)0xb0; displayText += degree; } return displayText; } /// /// deal with decimal number /// /// string wanted to deal with /// number of decimal /// result dealing with public static string DealDecimalNumber(string value, int number) { string newValue = value; int dist; if (newValue.Contains(".")) { int index = newValue.IndexOf("."); dist = newValue.Length - (index + 1); } else { dist = 0; newValue += "."; } if (dist < number) { for (int i = 0; i < number - dist; i++) { newValue += "0"; } } return newValue; } /// /// convert string into double /// /// string value need to convert /// value type /// conversion result /// if success, return true; otherwise, return false public static bool StringToDouble(string value, ValueType valueType, out double newValue) { newValue = 0; if (null == value) { return false; } //try to Parse double from string double result; if (ParseFromString(value, valueType, out result)) { //deal with ratio ValueConversion(result, valueType, false, out newValue); return true; } return false; } /// /// Parse double from string /// /// string value /// value type /// conversion result /// if success, return true; otherwise, return false private static bool ParseFromString(string value, ValueType valueType, out double result) { string newValue = null; string degree = ((char)0xb0).ToString(); //if nothing, set result = 0; if (value.Length == 0) { result = 0; return true; } else if (ValueType.General == valueType) { } //check if contain degree symbol else if (value.Contains(degree)) { int index = value.IndexOf(degree); newValue = value.Substring(0, index); } //check if have string" " ,for there is string" " //between value and unit when show in PropertyGrid else if (value.Contains(" ")) { int index = value.IndexOf(" "); newValue = value.Substring(0, index); } //finally if don't have unit name in it //other situation, set newValue = value else { newValue = value; } //double.TryParse's return value: //true if s is converted successfully; otherwise, false. if (double.TryParse(newValue, out result)) { return true; } return false; } /// /// deal with ratio /// /// value need to deal with /// value type /// /// figure out whether be called by function "DoubleToString" /// /// private static void ValueConversion(double value, ValueType valueType, bool isDoubleToString, out double newValue) { //ValueType.General == valueType,do nothing and return if (ValueType.General == valueType) { newValue = value; return; } //otherwise,check whether be called by function "DoubleToString" if (isDoubleToString) { newValue = value / AngleRatio; } else { newValue = value * AngleRatio; } } } }