Archive for category 职业 Profession

DIY Google Earth

  SRTM(Shuttle Radar Topography Mission),由美国太空总署(NASA)和国防部国家测绘局(NIMA)联合测量。覆盖全球超过80%的地面,每5度经纬度方格划分一个文件。理论上SRTM数据的分辨率可以达到每90米一个数据点,每个文件共有6000*6000个采样点,这样的后果就是最终生成的一张OBJ格式的地形图大概是2.7G以上,仅包含顶点和面片。导入3DMax或者Unity都是等待许久以后崩溃。于是只有降低精度了,现在看到的是每360米一个数据点,只能大概的表示一下地形的起伏了,小范围内最高精度地形图倒是看起来比较平滑。
  在引擎中增加一个摄像头,并且添上控制移动的一段代码,就能够在地图上方“飞行”了。由于数据都在本地,比起google earth要流畅很多。比如可以看看某高原上最高的一座山峰,确实有点鹤立鸡群的感觉,而某岛东面的海岸平原也明显比起西部要狭窄。接下去需要做的事情是需要使用代码根据每个区域的选择合适的纹理贴图。

青藏高原边缘

青藏高原边缘


台湾岛东北岸

台湾岛东北岸

Advertisements

Leave a comment

Clustering for Dummys

 
  如果你此前认为传说中的Cluster需要很多背景知识需要很复杂的配置,那么恭喜了,其实有很多方法可以让java应用程序升级为可以运行在分布式环境下了,其中之一就是terracotta。
 
  借助它,我们不用太多地修改自己代码,更不会在代码中引用任何来自terracotta的类。我们需要做的是写一个或多个用于在多个JVM中共享数据的类,并且在配置文件中声明这些类及其字段和方法。然后通过使用terracotta提供的classloader来运行我们的程序,魔法就这样发生了:这些自定义的对象看似每个运行时的程序都拥有本地实例,但运行于不同机器的Java应用程序通过这些共享数据池或者说消息队列进行协作。我们的程序可以是运行于jboss、tomcat、glassfish上的java ee应用,也可以是一个本地的java se程序,比如说一个带有swing界面的聊天窗口……当然,terracotta不是万能灵药,它只是提供了一个快速搭建cluster的环境。有了“陶胚”,能不能烧制出瓷器,就看工匠的了。
 
  关于terracotta的更多,请看:http://www.terracotta.org/documentation/
  Terracotta 一个JVM级的开源群集框架,提供:HTTP Session复制,分布式缓存,POJO群集,跨越群集的JVM来实现分布式应用程序协调(采用代码注入的方式,所以你不需要修改任何代码……
 

6 Comments

Portal Charting:爱与恨交织

  圣诞前夕,刚好手头上的活告一个段落,趁着空闲总结一下最近几个月来的工作。
  RIA愈来愈成为人们讨论的热门话题,如果你还在告诉别人你的应用程序有一个功能和体积都非常彪悍的客户端,或者说你的Page还停留只是简单的使用AJAX通信然后展示一堆HTML结构的表格,那么对方一定会说你已经过时了。人们不希望继续部署桌面程序,同时又希望他们的浏览器里面运行着的玩意足够强大:丰富的窗口组件;可即时交互的图表;随心所欲的点击或者拖拉;……就像一个桌面程序,很矛盾不是吗?
  过去的几个月里,我参与了公司下一代Portal产品的开发,所希望达到的目标正是这样。高级用户在客户端中编写工作流并发布成服务,用户在页面里面打开服务导入数据配置参数……运行得到结果以图表的方式展示,然后选择放弃、保存或者导出。我所承担的部分任务主要是可即时交互的图表,包括图表之间的联动。
  公司的客户端产品里早已有了这些图表(IB),提供了非常丰富的功能,也可以选择其他第三方的图表引擎(比如很流行的JFreeChart),另外我们也在上海用比较短的时间重新实现了几种类型的图表。但是后来因为时间原因,绘图部分我们仍然首先重用了产品。回顾下来,我的感觉是JFreeChart的视觉效果较好,很干净很成熟,但是经过测试,在处理海量数据的时候,效率上没有什么优势,最关键的是需要编写大量代码将源数据根据参数重建模型提交给JFreeChart;IB的视觉效果比较简单,绘制大数据量的散点图时比较慢;重新实现的话视觉效果和效率都可以得到一定的提高,而且还可以学习JFreeChart,生成图像的同时生成AreaMap输出到页面,最大的问题是时间,要在短期内达到IB所具备的功能比较困难,加上后期IB做了一些优化提高了效率。因此最后还是选择IB作为默认的绘图引擎。
  光有ChartEnginee还只是第一步,我们需要在页面中定义各种Widget,它们有自己的窗口、工具按钮、右键菜单,还能够在页面中拖放,最大化最小化或者关闭,甚至用户能够在图上面拖拉选区或者缩放……我们选择Ext作为整个Portal的客户端框架,中间也混用了dojo。在客户端里面,用户更改了参数或者直接在图上面操作后直接重绘即可,但是在浏览器里面我们必须把这个流程改成异步的,先以JSON数组的方式提交参数到服务器端的某个AJAX end-point,创建一个新的chart实例并且序列化在容器中返回一个序列号给浏览器,浏览器用这个序列号通知DOM对象请求图片,另外一个end-point直接将图像绘制到BufferedImage并写入字节流。
  有了一个图还只是万里长征的第一步,然后是同一页面里多个图表之间的异步交互,各种事件的管理,选区里的数据保存在用户空间或者导出成各种格式的文档,还有服务器端的数据缓存以及对象的生存周期管理等等。另外一个重头戏是表格,可以说是最常用也是最难做好的控件,到了英国后我大部分时间都用在跟这里的同事一起开发表格控件上。Ext提供的表格还是比较让人满意的,在它的基础上,我们的表格控件已经具备非常好的交互性了,支持服务器端排序、分页、同步选中数据、自定义renderer……
  开始这个项目以前,我也经常写一些JavaScript代码,并且也常跟别人说作为一名开发者,应该掌握至少一种脚本语言,但是绝对没有像这次一样大规模的使用JavaScript来开发。虽然有JSEclipse插件和EditPlus来写代码,有FireBug来调试,但是遇到问题的频率和走过的弯路却感觉比以前从C++转向Java更加高,更加长。转载一下某同事的话说就是自从开始用JavaScript开发,感觉生活水平一下下降了好几个层次,大概这是每一个从桌面应用走向浏览器应用的开发者都要面临的问题吧。
  几个月的痛苦和快乐,迷茫和振奋,期间整个团队还经历了一次从Ext1.0到Ext2.0的升级煎熬,现在运行在我面前的Portal Charting已经慢慢稳定下来,用我们开玩笑的话说就是Movie已经满天飞了,接下去要做的就是漫长的测试与除BUG。每当看到邮件里面的褒奖之词或者老板把访问者拉到我的电脑前的时候,总是会感到骄傲。毕竟,我在这个项目里面贡献了一份力量。

4 Comments

ABC of OLAP/MDX

  做PPT做到午夜两点多,居然再也睡不着了。躺在床上翻来覆去一小时,干脆再次爬起来看看能干点什么。
  接受了一个研究OLAP/MDX的任务,给同事们作一个简单的报告。以前曾有读过SSAS的文档,但只是浅尝辄止,没有深入进去,这次也算是重新学习一下吧。
  OLAP(联机分析处理)的概念是在上世纪90年代被提出的,主要是因为传统的OLTP(联机事务处理)已不能满足终端用户对数据库查询分析的需要,SQL对大型数据库进行的简单查询也不能满足终端用户分析的要求。用户的决策分析需要对关系数据库进行大量计算才能得到结果,而查询的结果并不能满足决策者提出的需求。因此,提出了多维数据库和多维分析的概念,即OLAP。简单的说就是数据不再仅仅是像关系数据库中的二维平面表一样仅仅只有行和列两个维度,行和列的交点处只有一个数据元素,而是可以有任意多个维度,形成一个超立方体或者多立方体。一个简单的例子就是在MSDN中的Cube:{Route, Service, Time, Measures}。
  OLAP多维数据分析主要包括以下几种方法:切片/块、向上/下钻取、旋转/转轴。其目标就是从不同的角度在不同的细节程度上去观察数据,管理决策者以此为依据进行决策。 
  OLAP商业产品很多,微软主推的是它的Microsoft SQL Server 2005 Analysis Services (SSAS),IBM/Oracle/Informix/Sybase也都在自己的BI产品中集成了OLAP技术,和ETL、数据仓库、数据挖掘、前端工具等综合运用,形成一个完整的BI平台。
  如同传统的关系数据库中SQL(结构化查询语言)是它的体系结构的基本构成部分一样,MDX(多维表达式)则是OLAP分析功能的利器,是一种功能完备、基于语句的脚本语言,用于定义、使用以及从多维对象中检索数据。它的形式也有点类似SQL,同样也包括DDL、DML、DCL等,但MDX不是SQL语言的扩展。事实上,MDX所提供的一些功能也可由SQL提供,尽管不是那么有效或直观。
  一个典型的MDX查询语句如下:
  select [SET] on Columns,
  [SET] on Rows
  from [CUBE]
  where [TUPLE]
  看看,是不是跟SQL很有几分接近。这里的Tuple、Set、Cube以及Measure、Member都是MDX里面的元素,具体定义也都可以查阅MSDN或者其他文档。就像SQL语句可以有很复杂的变化,MDX非常复杂,语法很烦琐,要熟练掌握还是需要很花一番功夫的。
  在同事的推荐下,我在自己机器上安装了一个Tomcat+JPivot+Mondrian的环境用于测试学习MDX语法。JPivot是一个很好的前端展示工具,使用WCF (Web Component Framework) ,基于XML/XSLT来渲染Web UI组件,同时支持XMLA和Mondrian两种OLAP Server,而且JPivot和Mondrian都是开源项目。网上也能找到一些关于它们的介绍,不过中文的似乎就是一两篇文章被到处转来转去,如果希望有更加深入的了解,除了自己多摸索,还得去慢慢啃英文。

5 Comments

JNI ActiveX

  最近这些日子对JNI(Java Native Interface)作了一个简单的研究,起因是需要将几个第三方的Win32应用程序整合进我们用Java开发的软件框架里面。虽然这样Java的可移植性打了折扣,但是软件开发,客户的需求是第一位的。好在Java提供了JNI这么一个接口供开发者调用其他语言编写的代码,而大量的Win32应用程序也都能够以自动化服务器或者ActiveX控件的方式供其他程序调用,这样两者之间就能够建立一个桥梁。

  如果仅仅是为了针对某一个提供了COM接口的Win32应用程序与Java建立这么一个桥梁,事情就变得非常简单。只要获得Java窗口的Windows句柄,就可以利用这个句柄,在这个窗口上创建任何子窗口。将TypeLib导入到VC的工程中,可以获得ActiveX控件的C++包装类,然后直接调用类的方法就可以了。

  我遇到的问题跟这个又有点不一样,目标是提供一个通用的接口,能够根据CLSID创建任何一个已注册的ActiveX控件,并且根据名称直接访问控件的方法和属性。对于这个接口的使用者,可能的使用方式如下:

 AxWindow wnd = new AxWindow("CLSID");
 Object objProperty = wnd.getProperty("PROPERTY_NAME");
 wnd.putProperty("PROPERTY_NAME", objProperty);
 
 Object objParam1, objParam2;
 wnd.addParam(objParam1);
 wnd.addParam(objParam2);
 wnd.invokeMethod("METHOD_NAME");

  JNI方面的资料可以在J2SDK的文档中找到,生成C++头文件并且实现代码并编译得到DLL,在很多网站上都能找到简单的例子。但是MSDN上面对ActiveX控件的调用,大部分都是导入TypeLib得到C++包装类,可是如果仔细阅读代码,可以发现CComPtr类提供了这么几个成员函数:

 virtual HRESULT CComPtr<IDispatch>::GetIDsOfNames

 virtual HRESULT CComPtr<IDispatch>::Invoke;

 virtual HRESULT CComPtr<IDispatch>::GetPropertyByName

 virtual HRESULT CComPtr<IDispatch>::PutPropertyByName

 ……

  原来那些包装类最终也都是调用这些函数:即先调用GetIDofName,通过方法或者属性的名称得到接口ID,然后通过标志位来控制是调用方法还是对属性进行读写。典型的调用过程如下:

CComVariant varRet;

// 先得到控件的IUNKNOWN接口
IUnknown *pUnk = GetInterface();
if (pUnk != NULL)
{

  CComPtr<IDispatch> sp;

  pUnk->QueryInterface(IID_IDispatch, (void**)&sp);

  if (sp)

  {

    // 根据方法或者属性的名称得到DISPID

    DISPID dispid = 0;

    sp->GetIDsOfNames(IID_NULL, (LPOLESTR *)&lpszName, 1, 0, &dispid);

    // 预处理参数,参数均为VARIANT类型

    DISPPARAMS dispParams = {NULL, NULL, 1, 1};

    int nParams = m_ayParams.size();

    if (nParams > 0)

    {

      dispParams.cArgs = nParams;

      dispParams.rgvarg = new VARIANTARG[nParams];

      for (int n = 0; n < nParams; n++)

      {

        dispParams.rgvarg[n] = m_ayParams[n];

      }

    }

    // 调用方法或者访问属性 wFlag可以为以下值之一
    // DISPATCH_METHOD
    // DISPATCH_PROPERTYGET
    // DISPATCH_PROPERTYPUT
    // DISPATCH_PROPERTYPUTREF

    sp.p->Invoke(dispid, IID_NULL, 0, wFlag, &dispParams, &varRet, NULL, NULL);

    // 清理
    delete [] dispParams.rgvarg;
  }
}

m_ayParams.clear();

  还有需要解决的问题就是参数,首先是参数的个数和类型不确定,而且还需要首先将Java类型映射成C++类型或者反之。这个问题倒也不难,主要就是调用JNIEnv类的FindClass、GetMethodID、NewObject等函数,先获取类型,再得到该类型的构造函数id,最后通过构造函数在C++代码中创建一个对应的Java对象实例,或者是通过FindClass得到Java对象的类型,调用toString将对象的值统一转换成一个字符串,然后根据类型和值两个字符串创建一个C++对象。

  最后还有一个让我郁闷的事情就是,由于在代码中使用了ATL,因此需要在目标机器上也安装有ATL80.dll。按照老习惯,我先选择“静态链接到ATL”重新编译一次,奇怪的是结果文件的大小并没有发生变化,运行的时候仍然报错:“未找到ATL80.DLL……”。最后不得已,只有在另外一台安装Visual Studio 6.0的机器上面重新编译发布。希望有经验的朋友能够帮助我解决这个问题。

 

6 Comments

斧头C vs 锄头J

  除了中学时学了段BASIC,进入大学后一直都是学习C/C++的干活,大部分时间里也都是跟VC打交道,从最会利用向导写几个按钮触发函数,到后来深入到Win32应用程序的方方面面,积累了深厚的革命情谊。中间也有过一些类似为手机编写应用程序和实现该应用程序的Java Applet版本等的小插曲,可前者根本就是VC的另外一个版本,做那个Applet也是凭借一点基础概念一边学习一边实践。

  虽然很明白,要成为一个合格的IT外来务工青年,斧头或者锄头,都只是工具只是手段,但是拿惯了斧头的手挥舞起锄头来,难免会有点生涩。当然,理想状态是左青龙右白虎,斧头锄头内外双修左右互搏……咳咳,废话就不多说了,开始操练,坚信:转型是必要的,前途是光明的。

  的确很久没有更新了,一下子就到五一了,继续锄草。

2 Comments

梅林会说话了

  要让梅林说话很简单,只需要安装上合适的TTS引擎就可以了,比如微软AGENT主页上面提供的一个叫做L&H引擎,并且在代码中设置一下语种ID就好了。可惜的是这个引擎尚不支持中文(同样是东亚语言,日文和韩文倒是支持,郁闷),要让这个控件能够说中文,还是需要安装完整的SAPI和相关的资源,这就过分了。

  还有一个小进步就是支持脚本,要让梅林说更多的话做更多的动作不需要重新修改编译程序了,只需要编辑一个XML文档。而且如果想换一个角色,比如机器人、阿拉丁灯神、鹦鹉等也变得很方便了。

5 Comments