关于SuperMap Objects .NET中计算沿线某个距离点方向的说明

我们可以通过查找指定距离点所在的前后两个线节点来计算线上某个距离点的方向:

// 定义要计算的线
GeoLine geoLine = new GeoLine();
// 定义沿线距离
double distance = 100;
// 定义要计算的剩余距离
double tempDistance = distance;
// 遍历线上所有点
for (int i = 0; i < geoLine.PartCount; i++)
{
    Point2Ds point2Ds = geoLine[i];
    for (int j = 1; j < point2Ds.Count; j++)
    {
        // 计算两个节点的距离并修正剩下需要沿线的距离
        Point2D point2D1 = point2Ds[j - 1];
        Point2D point2D2 = point2Ds[j];
        tempDistance -= Geometrist.Distance(new GeoPoint(point2D1), new GeoPoint(point2D2));
        // 判断是否到达指定的距离
        if (tempDistance <= 0)
        {
            // 根据当前所在前后节点计算并返回方向
            double dx = point2D2.X - point2D1.X;
            double dy = point2D2.Y - point2D1.Y;
            // 东北方向
            if (dx > 0 && dy > 0)
            {
                return Math.Atan(dx / dy) * 180d / Math.PI;
            }
            // 东南方向
            else if (dx > 0 && dy < 0)
            {
                return 180d - (Math.Atan(dx / -dy) * 180d / Math.PI);
            }
            // 西南方向
            else if (dx < 0 && dy < 0)
            {
                return 180d + (Math.Atan(-dx / -dy) * 180d / Math.PI);
            }
            // 西北方向
            else if (dx < 0 && dy > 0)
            {
                return 360d - (Math.Atan(-dx / dy) * 180d / Math.PI);
            }
            // 正北方向
            else if (dx == 0 && dy > 0)
            {
                return 0;
            }
            // 正南方向
            else if (dx == 0 && dy < 0)
            {
                return 180;
            }
            // 正东方向
            else if (dx > 0 && dy == 0)
            {
                return 90;
            }
            // 正西方向
            else if (dx < 0 && dy == 0)
            {
                return 270;
            }
            // 其他
            else
            {
                return 0;
            }
        }
    }
}
// 没有线则返回默认方向
return 0;

关于SuperMap Objects .NET中点串拟合飞行轨迹的说明

在三维GIS开发中,场景飞行是一种常用的展示手段,平滑的飞行轨迹能使三维展示更加流畅。下面介绍在SuperMap Objects .NET中如何将一系列的坐标点串拟合成平滑的飞行轨迹线:

// 定义轨迹点串,包括X、Y、Z三维坐标
double[][] coordinates = new double[99][];
// 定义相关点集
Point2Ds point2Ds = new Point2Ds();
Point2Ds heightItemPoint2Ds = new Point2Ds();
Point2Ds heightPoint2Ds = new Point2Ds();
// 定义曲线拟合段数
int cardinalSegment = 20;
// 遍历所有轨迹点
foreach (double[] coordinate in coordinates)
{
    // 根据X、Y坐标创建高度曲线
    Point2D point2D = new Point2D(coordinate[0], coordinate[1]);
    point2Ds.Add(point2D);
    heightItemPoint2Ds.Add(point2D);
    GeoCardinal heightItemGeoCardinal = new GeoCardinal(heightItemPoint2Ds);
    // 将高度曲线转换为几何线对象
    GeoLine heightItemGeoLine = heightItemGeoCardinal.ConvertToLine(cardinalSegment);
    // 将高度曲线长度和Z坐标定义为轨迹曲线的坐标
    point2D = new Point2D(heightItemGeoLine.Length, coordinate[2]);
    heightPoint2Ds.Add(point2D);
}
// 获取水平轨迹曲线
GeoCardinal geoCardinal = new GeoCardinal(point2Ds);
GeoLine geoLine = geoCardinal.ConvertToLine(cardinalSegment);
// 获取垂直轨迹曲线
GeoCardinal heightGeoCardinal = new GeoCardinal(heightPoint2Ds);
GeoLine heightGeoLine = heightGeoCardinal.ConvertToLine(cardinalSegment);
// 获取轨迹点集
Point2Ds allPoint2Ds = geoLine[0];
Point2Ds allHeightPoint2Ds = heightGeoLine[0];
// 拟合轨迹曲线
Point3Ds allPoint3Ds = new Point3Ds();
for (Int32 i = 0; i < allHeightPoint2Ds.Count; i++)
{
    allPoint3Ds.Add(new Point3D(allPoint2Ds[i].X, allPoint2Ds[i].Y, allHeightPoint2Ds[i].Y));
}
GeoLine3D geoLine3D = new GeoLine3D(allPoint3Ds);
// 返回轨迹曲线
return geoLine3D;

关于JavaScript中自定义事件绑定对象方法的说明

基于JavaScript弱类型的特点,我们可以通过重构对象方法来实现绑定事件的机制(当调用某个对象方法时总是触发调用我们自定义的方法):

/**
* 定义事件绑定方法
* obj:要绑定事件的对象
* target:要绑定事件的对象方法名
* handler:要绑定的事件
* toTop:是否优先执行事件
*/
function addEvent(obj, target, handler, toTop) {
    // 判断参数是否有效
    if (obj && target && typeof (handler) == "function") {
        // 获取对象obj中名称为target的成员
        var fun = obj[target];
        // 重构对象obj的target成员
        obj[target] = function () {
            // 判断要绑定的方法是否优先执行
            if (toTop) {
                // 调用要绑定的方法
                var result = handler.apply(obj, arguments);
                // 返回false则终止事件冒泡
                if (result !== false) {
                    // 判断对象obj的target成员是否为方法
                    if (typeof (fun) == "function") {
                        // 调用对象obj的原始target方法
                        result = fun.apply(obj, arguments);
                    }
                }
                return result;
            } else {
                // 定义返回结果
                var result = undefined;
                // 判断对象obj的target成员是否为方法
                if (typeof (fun) == "function") {
                    // 调用对象obj的原始target方法
                    result = fun.apply(obj, arguments);
                }
                // 调用要绑定的方法,返回false则终止事件冒泡
                if (handler.apply(obj, arguments) === false) {
                    return false;
                } else {
                    // 返回原始结果
                    return result;
                }
            }
        }
    }
}

// 为window对象的encodeURIComponent方法绑定事件
addEvent(window, "encodeURIComponent", function (url) {
    alert(url);
}, true);
// 调用方法触发事件
encodeURIComponent("index.html");

关于C#中逗号分隔字符串转泛型数组的说明

在处理Web表单请求时,相同name值的数据会以逗号分隔的字符串形式提交到服务端,以下示例如何在C#中将此类字符串转换为实际需要的数据类型:

// 定义逗号分隔字符串
string value = "a,b,c,d";
// 获取泛型类型
Type type = typeof(T);
// 判断泛型是否为数组
if (type.IsArray)
{
    // 将字符串以逗号拆分
    string[] values = value.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
    // 创建泛型对应的数组实例
    Array array = (Array)Activator.CreateInstance(type, values.Length);
    // 获取泛型数组元素类型
    Type elementType = type.GetElementType();
    // 将字符串逐个转换为泛型数组元素类型,并添加到数组对应索引处
    for (int i = 0, length = values.Length; i < length; i++)
    {
        array.SetValue(Convert.ChangeType(values[i], elementType), i);
    }
    // 获取泛型数组
    return (T)(object)array;
}
else
{
    // 不是数组则直接尝试将字符串转换为泛型类型
    return (T)Convert.ChangeType(value, type);
}

关于Castle.Windsor中实现属性类注解自动注入的说明

Castle是.NET平台上的一个开源项目,为企业级开发和WEB应用程序开发提供完整的服务。Windsor是Castle下的一个项目,用于提供IOC的解决方案。IOC被称为控制反转或者依赖注入(Inversion of Control)
以下介绍如何通过Castle.Windsor实现对类的成员属性或字段进行自动注入:

一、自动注入核心代码:

using Castle.Core;
using Castle.Core.Resource;
using Castle.MicroKernel;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;
using System;
using System.Collections.Generic;
using System.Reflection;

// 成员注解自动注入属性类,可注解字段和属性
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class InstanceAttribute : Attribute
{
    // 获取或设置需要注入对象的ID值
    public string ID
    {
        get;
        set;
    }

    // 获取或设置需要注入对象的类型
    public Type Type
    {
        get;
        set;
    }
}

// 成员注解自动注入功能类,继承Castle.Windsor的WindsorContainer
public class InstanceProvider : WindsorContainer
{
    // 定义Castle.Windsor在程序配置文件中的节点
    private static readonly string ConfigRoot = "windsor";
    // 定义类的成员注解信息字典
    private static Dictionary<Type, Dictionary<MemberInfo, InstanceAttribute>> _InstanceMembers = new Dictionary<Type, Dictionary<MemberInfo, InstanceAttribute>>();

    // 构造函数初始化程序默认配置文件的Castle.Windsor配置信息(也可以指定其他配置文件)
    public InstanceProvider()
      : base(new XmlInterpreter(new ConfigResource(InstanceProvider.ConfigRoot)))
    {
        // 绑定IoC组件创建事件
        this.Kernel.ComponentCreated += this.Kernel_ComponentCreated;
    }

    // 获取类型的成员注解信息
    private Dictionary<MemberInfo, InstanceAttribute> GetInstanceMembers(Type type)
    {
        // 定义类型的成员注解信息
        Dictionary<MemberInfo, InstanceAttribute> instanceMembers;
        // 获取Castle.Windsor的IoC接口
        IKernel kernel = this.Kernel;
        // 线程安全锁,防止多线程对成员注解信息字典操作的冲突
        lock (InstanceProvider._InstanceMembers)
        {
            // 判断当前类型是否已存在成员注解信息
            if (InstanceProvider._InstanceMembers.ContainsKey(type))
            {
                // 根据类型获取所属的成员注解信息
                instanceMembers = InstanceProvider._InstanceMembers[type];
            }
            else
            {
                // 新建成员注解信息
                instanceMembers = new Dictionary<MemberInfo, InstanceAttribute>();
                // 获取成员注解的属性类类型
                Type instanceAttributeType = typeof(InstanceAttribute);
                // 获取类型的成员信息
                MemberInfo[] memberInfos = type.GetMembers();
                foreach (MemberInfo memberInfo in memberInfos)
                {
                    switch (memberInfo.MemberType)
                    {
                        case MemberTypes.Field:
                            // 获取字段成员
                            FieldInfo fieldInfo = memberInfo as FieldInfo;
                            // 获取成员注解对象
                            object[] fieldInstanceAttributes = memberInfo.GetCustomAttributes(instanceAttributeType, false);
                            // 查找有效的字段注解信息
                            foreach (InstanceAttribute instanceAttribute in fieldInstanceAttributes)
                            {
                                // 判断是否设置了需要注入对象的ID值
                                if (instanceAttribute.ID == null)
                                {
                                    // 定义IoC组件类型
                                    Type componentType;
                                    // 判断是否设置了需要注入对象的类型
                                    if (instanceAttribute.Type == null)
                                    {
                                        // 没有设置需要注入对象的类型则使用字段类型
                                        componentType = fieldInfo.FieldType;
                                    }
                                    else
                                    {
                                        // 设置IoC组件类型
                                        componentType = instanceAttribute.Type;
                                    }
                                    // 没有设置需要注入对象的ID值则根据组件类型判断是否存在对应的IoC组件
                                    if (kernel.HasComponent(componentType))
                                    {
                                        // 添加成员注解信息项
                                        instanceMembers.Add(memberInfo, instanceAttribute);
                                        break;
                                    }
                                }
                                else
                                {
                                    // 根据注入对象的ID值判断是否存在Ioc组件
                                    if (kernel.HasComponent(instanceAttribute.ID))
                                    {
                                        // 添加成员注解信息项
                                        instanceMembers.Add(memberInfo, instanceAttribute);
                                        break;
                                    }
                                }
                            }
                            break;
                        case MemberTypes.Property:
                            // 获取属性成员
                            PropertyInfo propertyInfo = memberInfo as PropertyInfo;
                            // 判断属性成员是否可读写,并且Get、Set访问器的静态性是否一致
                            MethodInfo getMethodInfo = propertyInfo.GetGetMethodInfo();
                            MethodInfo setMethodInfo = propertyInfo.GetSetMethodInfo();
                            if (getMethodInfo != null && setMethodInfo != null && getMethodInfo.IsStatic == setMethodInfo.IsStatic)
                            {
                                // 获取属性注解对象
                                object[] propertyInstanceAttributes = memberInfo.GetCustomAttributes(instanceAttributeType, false);
                                // 查找有效的属性注解信息
                                foreach (InstanceAttribute instanceAttribute in propertyInstanceAttributes)
                                {
                                    // 判断是否设置了需要注入对象的ID值
                                    if (instanceAttribute.ID == null)
                                    {
                                        // 定义IoC组件类型
                                        Type componentType;
                                        // 判断是否设置了需要注入对象的类型
                                        if (instanceAttribute.Type == null)
                                        {
                                            // 没有设置需要注入对象的类型则使用属性类型
                                            componentType = propertyInfo.PropertyType;
                                        }
                                        else
                                        {
                                            // 设置IoC组件类型
                                            componentType = instanceAttribute.Type;
                                        }
                                        // 没有设置需要注入对象的ID值则根据组件类型判断是否存在对应的IoC组件
                                        if (kernel.HasComponent(componentType))
                                        {
                                            // 添加属性注解信息项
                                            instanceMembers.Add(memberInfo, instanceAttribute);
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        // 根据注入对象的ID值判断是否存在Ioc组件
                                        if (kernel.HasComponent(instanceAttribute.ID))
                                        {
                                            // 添加属性注解信息项
                                            instanceMembers.Add(memberInfo, instanceAttribute);
                                            break;
                                        }
                                    }
                                }
                            }
                            break;
                        default:
                            break;
                    }
                }
                // 将获取到的成员注解信息保存到成员注解信息字典以备下次获取
                InstanceProvider._InstanceMembers.Add(type, instanceMembers);
            }
        }
        // 返回成员注解信息
        return instanceMembers;
    }

    // 为对象进行属性注入,静态类可通过传入Type对象进行注入
    public void Instance(object obj)
    {
        // 获取需要注入对象的类型
        Type type;
        // 判断对象是否是Type对象
        if (obj is Type)
        {
            // 直接强制转换为Type对象
            type = obj as Type;
        }
        else
        {
            // 获取对象的类型
            type = obj.GetType();
        }
        // 获取对象的成员注入信息
        Dictionary<MemberInfo, InstanceAttribute> instanceMembers = this.GetInstanceMembers(type);
        // 获取Castle.Windsor的IoC接口
        IKernel kernel = this.Kernel;
        // 开始进行成员注入
        foreach (KeyValuePair<MemberInfo, InstanceAttribute> item in instanceMembers)
        {
            switch (item.Key.MemberType)
            {
                case MemberTypes.Field:
                    // 获取字段注入信息
                    FieldInfo fieldInfo = item.Key as FieldInfo;
                    // 定义字段反射对象
                    object field;
                    // 根据字段是否是静态字段设置反射对象
                    if (fieldInfo.IsStatic)
                    {
                        field = null;
                    }
                    else
                    {
                        field = obj;
                    }
                    // 判断字段是否已经被赋值,只对未赋值字段进行注入
                    if (fieldInfo.GetValue(field) == null)
                    {
                        // 定义IoC组件类型
                        Type componentType;
                        // 判断是否设置了需要注入对象的类型
                        if (item.Value.Type == null)
                        {
                            // 没有设置需要注入对象的类型则使用字段类型
                            componentType = fieldInfo.FieldType;
                        }
                        else
                        {
                            // 设置IoC组件类型
                            componentType = item.Value.Type;
                        }
                        // 定义需要注入的字段值
                        object value;
                        // 判断是否设置了需要注入对象的ID值
                        if (item.Value.ID == null)
                        {
                            // 没有设置需要注入对象的ID值则根据类型获取对应的IoC组件
                            value = kernel.Resolve(componentType);
                        }
                        else
                        {
                            // 根据注入对象的ID值获取Ioc组件
                            value = kernel.Resolve(item.Value.ID, componentType);
                        }
                        // 通过反射为字段进行赋值
                        fieldInfo.SetValue(field, value);
                    }
                    break;
                case MemberTypes.Property:
                    // 获取属性注入信息
                    PropertyInfo propertyInfo = item.Key as PropertyInfo;
                    // 定义属性反射对象
                    object property;
                    // 根据属性是否是静态属性设置反射对象
                    MethodInfo getMethodInfo = propertyInfo.GetGetMethod();
                    MethodInfo setMethodInfo = propertyInfo.GetSetMethod();
                    if (getMethodInfo.IsStatic && setMethodInfo.IsStatic)
                    {
                        property = null;
                    }
                    else
                    {
                        property = obj;
                    }
                    // 判断属性是否已经被赋值,只对未赋值属性进行注入
                    if (propertyInfo.GetValue(property, null) == null)
                    {
                        // 定义IoC组件类型
                        Type componentType;
                        // 判断是否设置了需要注入对象的类型
                        if (item.Value.Type == null)
                        {
                            // 没有设置需要注入对象的类型则使用属性类型
                            componentType = propertyInfo.PropertyType;
                        }
                        else
                        {
                            // 设置IoC组件类型
                            componentType = item.Value.Type;
                        }
                        // 定义需要注入的属性值
                        object value;
                        // 判断是否设置了需要注入对象的ID值
                        if (item.Value.ID == null)
                        {
                            // 没有设置需要注入对象的ID值则根据类型获取对应的IoC组件
                            value = kernel.Resolve(componentType);
                        }
                        else
                        {
                            // 根据注入对象的ID值获取Ioc组件
                            value = kernel.Resolve(item.Value.ID, componentType);
                        }
                        // 通过反射为属性进行赋值
                        propertyInfo.SetValue(property, value, null);
                    }
                    break;
                default:
                    break;
            }
        }
    }

    // 订阅IoC组件创建事件
    private void Kernel_ComponentCreated(ComponentModel model, object instance)
    {
        // 在每次创建IoC组件时进行成员注入
        this.Instance(instance);
    }
}

二、调用说明:
定义类,并对需要进行注入的属性或字段标记InstanceAttribute注解属性类。创建InstanceProvider对象,通过调用Instance方法将传入的类实例对象进行属性或字段的注入。如果是静态类可通过传入其Type对象进行注入。

更多信息请参阅:Windsor | Castle Project