可能你已经了解到了一些要随ArcGIS 10.1版本发布的新产品ArcGIS Runtime的信息,比如它的跨平台,高便携,64位,可扩展等。
Esri刚刚结束的developer summit上,以WPF为例,演示了最新的prerelease版本中ArcGIS Runtime的性能。视频中prerelease版中同时加载了10,000个带动画的复杂渲染的graphic。
Web API中一直被偏执狂们诟病的graphic性能有了长足的提升,ArcGIS Runtime更加让人期待了。
ps:期待更多有社会价值的公交车,出租车,物流监控系统出现。
2012年3月31日星期六
ArcGIS Runtime性能
2012年3月15日星期四
弟子规-与鲶总、李总、法人共勉
总 叙
弟子规 圣人训 首孝悌 次谨信
泛爱众 而亲仁 有余力 则学文
入 则 孝
父母呼 应勿缓 父母命 行勿懒
父母教 须敬听 父母责 须顺承
冬则温 夏则凊 晨则省 昏则定
出必告 反必面 居有常 业无变
事虽小 勿擅为 苟擅为 子道亏
物虽小 勿私藏 苟私藏 亲心伤
亲所好 力为具 亲所恶 谨为去
身有伤 贻亲忧 德有伤 贻亲羞
亲爱我 孝何难 亲憎我 孝方贤
亲有过 谏使更 怡吾色 柔吾声
谏不入 悦复谏 号泣随 挞无怨
亲有疾 药先尝 昼夜侍 不离床
丧三年 常悲咽 居处变 酒肉绝
丧尽礼 祭尽诚 事死者 如事生
出 则 悌
兄道友 弟道恭 兄弟睦 孝在中
财物轻 怨何生 言语忍 忿自泯
或饮食 或坐走 长者先 幼者后
长呼人 即代叫 人不在 己即到
称尊长 勿呼名 对尊长 勿见能
路遇长 疾趋揖 长无言 退恭立
骑下马 乘下车 过犹待 百步余
长者立 幼勿坐 长者坐 命乃坐
尊长前 声要低 低不闻 却非宜
进必趋 退必迟 问起对 视勿移
事诸父 如事父 事诸兄 如事兄
谨
朝起早 夜眠迟 老易至 惜此时
晨必盥 兼漱口 便溺回 辄净手
冠必正 纽必结 袜与履 俱紧切
置冠服 有定位 勿乱顿 致污秽
衣贵洁 不贵华 上循分 下称家
对饮食 勿拣择 食适可 勿过则
年方少 勿饮酒 饮酒醉 最为丑
步从容 立端正 揖深圆 拜恭敬
勿践阈 勿跛倚 勿箕踞 勿摇髀
缓揭帘 勿有声 宽转弯 勿触棱
执虚器 如执盈 入虚室 如有人
事勿忙 忙多错 勿畏难 勿轻略
斗闹场 绝勿近 邪僻事 绝勿问
将入门 问孰存 将上堂 声必扬
人问谁 对以名 吾与我 不分明
用人物 须明求 倘不问 即为偷
借人物 及时还 后有急 借不难
信
凡出言 信为先 诈与妄 奚可焉
话说多 不如少 惟其是 勿佞巧
奸巧语 秽污词 市井气 切戒之
见未真 勿轻言 知未的 勿轻传
事非宜 勿轻诺 苟轻诺 进退错
凡道字 重且舒 勿急疾 勿模糊
彼说长 此说短 不关己 莫闲管
见人善 即思齐 纵去远 以渐跻
见人恶 即内省 有则改 无加警
唯德学 唯才艺 不如人 当自砺
若衣服 若饮食 不如人 勿生戚
闻过怒 闻誉乐 损友来 益友却
闻誉恐 闻过欣 直谅士 渐相亲
无心非 名为错 有心非 名为恶
过能改 归于无 倘掩饰 增一辜
泛 爱 众
凡是人 皆须爱 天同覆 地同载
行高者 名自高 人所重 非貌高
才大者 望自大 人所服 非言大
己有能 勿自私 人所能 勿轻訾
勿谄富 勿骄贫 勿厌故 勿喜新
人不闲 勿事搅 人不安 勿话扰
人有短 切莫揭 人有私 切莫说
道人善 即是善 人知之 愈思勉
扬人恶 即是恶 疾之甚 祸且作
善相劝 德皆建 过不规 道两亏
凡取与 贵分晓 与宜多 取宜少
将加人 先问己 己不欲 即速已
恩欲报 怨欲忘 报怨短 报恩长
待婢仆 身贵端 虽贵端 慈而宽
势服人 心不然 理服人 方无言
亲 仁
同是人 类不齐 流俗众 仁者希
果仁者 人多畏 言不讳 色不媚
能亲仁 无限好 德日进 过日少
不亲仁 无限害 小人进 百事坏
余 力 学 文
不力行 但学文 长浮华 成何人
但力行 不学文 任己见 昧理真
读书法 有三到 心眼口 信皆要
方读此 勿慕彼 此未终 彼勿起
宽为限 紧用功 工夫到 滞塞通
心有疑 随札记 就人问 求确义
房室清 墙壁净 几案洁 笔砚正
墨磨偏 心不端 字不敬 心先病
列典籍 有定处 读看毕 还原处
虽有急 卷束齐 有缺坏 就补之
非圣书 屏勿视 蔽聪明 坏心志
勿自暴 勿自弃 圣与贤 可驯致
命自我作 福自我求
心好命又好 富贵直到老
命好心不好 福变为祸兆
心好命不好 祸转为福报
心命俱不好 遭殃且贫夭
心可挽乎命 最要存仁道
命实造於心 吉凶惟人召
信命不修心 阴阳恐虚矫
修心一听命 天地自相保
2012年2月29日星期三
在新的Android工程中调用已经编译好的so库文件代码
照着ndk帮助的说明,运行<ndk>/samples目录下的hello-jni工程后,你一定想知道如何在自己的项目里调用别人已经编译好的.so库文件。于是新建一个Android工程,将hello-jni例子中ndk-build后的结果:libs文件夹(包括其下所有内容)拷贝到新建工程的根目录下,仿照hello-jni的代码,调用native方法:
1: package com.my.SoTest;
2:
3: import android.app.Activity;
4: import android.os.Bundle;
5: import android.widget.TextView;
6:
7: public class SoTestActivity extends Activity {
8: /** Called when the activity is first created. */
9: @Override
10: public void onCreate(Bundle savedInstanceState) {
11: super.onCreate(savedInstanceState);
12:
13: TextView tv=new TextView(this);
14: tv.setText(stringFromJNI());
15: setContentView(tv);
16: }
17: public native String stringFromJNI();
18: static {
19: System.loadLibrary("hello-jni");
20: }
21: }
运行后,logcat记录以下错误:
No implementation found for native Lcom/my/SoTest/SoTestActivity;.stringFromJNI ()Ljava/lang/String;
...
java.lang.UnsatisfiedLinkError: stringFromJNI
在hello-jni的代码注释里明确说明,UnsatisfiedLinkError错误是由于native代码中没有该方法的实现而引起的,但stringFromJNI这个方法,在c代码中是有的;前一个错误就比较明确了,是在Lcom/my/SoTest/SoTestActivity中去找这个方法实现的,打开hello-jni.c文件看看该函数头,其中有这样的字样:Java_com_example_hellojni_HelloJni_stringFromJNI,而com.example.hellojni恰好是例子工程的package name,HelloJni则是class的名称。也就是说,我们.so中函数声明涉及到的package name和class name与调用它的package name和class name不符。google一下印证了这个猜测,但提供现成解决办法的不多,总不能自己工程的package name必须和.so里的一样吧。
搜索看到了一篇NDK的教程,Using NDK to Call C code from Android Apps(需翻墙),里面写明了在一个普通Android工程中,如何从零开始组装自己的native代码。大致的步骤是,首先写一个java类,里面声明一些需要实现native方法(函数签名即可),然后用javah命令来生成对应的header文件,里面的内容是自动生成的native函数声明,然后照着这个声明实现各个函数,最后编译,用最初的java类调用。
受此启发,我们在拿到别人已经编译好的.so文件后,可首先新建一个java类,所在package的名称和class名称都与.so文件中函数签名提示的一致,在这个类中加入native方法的声明。这样在别处就可以用这个wrapper调用so库中的函数了。
2012年2月27日星期一
在Android上利用NDK编译并使用Spatialite库(Windows环境)
Sqlite数据库因其体积便携(基于单个文件,跨平台),功能完整(类似RDBMS)受到非常广泛的欢迎,在iOS,Android平台上都提供原生的支持。Spatialite是Sqlite的一个空间扩展,根据官方介绍,Spatialite之于Sqlite,相当于PostGIS之于PostgreSQL。
Spatialite扩展提供了一系列用于空间操作的SQL函数,例如基础的空间查询,缓冲区生成等,也有高级的类似ArcObjects中ITopologicalOperator,IRelationalOperator等接口的功能。
在Android平台上使用Spatialite资料比较少,主要是google上的Spatialite for Android和github上的android-spatialite两个工程。前者带有完整的编译步骤,我尝试了这个,其中遇到了些问题,记录下来,方便需要用到的朋友。后者工程似乎带有编译好的libjsqlite.so库,可直接使用。
我机器的环境是Windows 7 64bit,已经搭建好了Android Eclipse开发环境。由于Spatialite及Sqlite是C/C++的native语言编写,而Android的默认开发语言是Java,所以在Android上编译Spatialite必须用到google提供的NDK(Native Development Kit)环境。NDK环境的搭建比较简单,按照google的文档进行即可:
- 下载NDK压缩包(android-ndk-r7b-windows.zip)。我下载的是最新的android-ndk-r7b版本。将其解压到任意目录,下文以<ndk>指代。注意:由于后面cygwin中配置环境变量时不支持带空格的路径,所以建议将其解压到某个盘符的根目录下,比如d:\android-ndk-r7b\;
- 设置Windows的环境变量。主要是将NDK的路径添加到PATH中去,方便在任何位置调用ndk-build命令。详细操作不再赘述。此步骤只是为cmd提供了便利;
- 由于NDK需求中说明,必须用到GNU Make命令,所以在Windows环境上还需要提前安装Cygwin。这是在Windows上模拟Linux环境的工具。安装步骤参考此贴:Windows环境下Android NDK环境搭建。注意在cygwin的linux环境下,配置$NDK环境变量,方便在任何地方调用ndk-build编译命令。我在安装Cygwin时,只额外勾选了Devel库。
完成这个步骤后,可尝试编译运行NDK中自带的hello-jni例子,验证NDK编译环境已经搭好。具体步骤参见google的文档。可以发现,native代码需要放在与src同级的jni目录下,该目录下必须至少有Android.mk文件,向NDK系统描述源文件;编译时需要在工程的根目录下运<ndk>/ndk-build命令;利用NDK编译后,Android工程文件夹中会多出libs目录,里面会生成lib<something>.so共享库,这就是我们要用到类库,该文件也会一并打包到apk文件中去。更多的ndk知识请参考<ndk>/documentation.html文件,非常详尽。注:JNI相当于.net平台的p/invoke。
接下来就要按照Spatialite for Android上的提示,在cygwin环境中编译spatialite库了。
- 在windows下利用svn工具对整个project checkout(这次作者用的是Spatialite 3.0.1,PROJ 4.7.0,geos 3.2.2几个库)。会发现有两个工程spatialite-android和spatialite-android-test。我们主要对spatialite-android工程进行编译;
- 由于spatialite用到了geos和proj两个库,所以首先需要为该工程下载,配置两个库。具体步骤如下,在cygwin环境中执行:
1: $ cd jni2: $ wget http://download.osgeo.org/geos/geos-3.2.2.tar.bz2
3: $ tar xvjf geos-3.2.2.tar.bz24: $ cd geos-3.2.25: $ ./configure --build=x86_64-pc-linux-gnu --host=arm-linux-eabi6: $ cd ..7: $ wget ftp://ftp.remotesensing.org/proj/proj-4.7.0.tar.gz
8: $ tar xvzf proj-4.7.0.tar.gz9: $ cd proj-4.7.010: $ ./configure --build=x86_64-pc-linux-gnu --host=arm-linux-eabi11: $ touch src/empty.cpp12: $ cd .. - 按照作者的提示,下来就可以直接对工程进行ndk-build了(注:此时仍然在spatialite-android/jni目录下,而非spatialite-android目录)。如果你这么做了,会出现一个错误:
1: ...2: Compile thumb : proj <= rtodms.c3: Compile thumb : proj <= vector1.c4: StaticLibrary : libproj.a5: Compile++ thumb : geos <= geos_c.cpp6: In file included from D:/spatialite-android/jni/geos-3.2.2/source/headers/geos/geom/Coordinate.h:20,7: from D:/spatialite-android/jni/geos-3.2.2/source/headers/geos/g eom/Envelope.h:26,8: from D:/spatialite-android/jni/geos-3.2.2/source/headers/geos/i ndex/strtree/STRtree.h:27,9: from D:/spatialite-android/jni/geos-3.2.2/capi/geos_c.cpp:19:10: D:/spatialite-android/jni/geos-3.2.2/source/headers/geos/platform.h:29:20: error : ieeefp.h: No such file or directory11: /cygdrive/d/android-ndk-r7b/build/core/build-binary.mk:243: recipe for target `/ cygdrive/d/spatialite-android/obj/local/armeabi/objs-debug/geos/geos-3.2.2/capi/ geos_c.o' failed
12: make: *** [/cygdrive/d/spatialite-android/obj/local/armeabi/objs-debug/geos/geos -3.2.2/capi/geos_c.o] Error 1
提示ieeefp.h: No such file or directory。要修正这个错误,你需要在spatialite-android/jni/geos-3.2.2/source/headers/geos/platform.h文件中大约15行的位置,找到“#define HAVE_IEEEFP_H 1”这句话,并在其下面添加一行“#undef HAVE_IEEEFP_H”,取消对HAVE_IEEEFP_H的定义。保存该文件; - 再次ndk-build,这回发现上面的错误消失了。但又产生了新的错误:
1: ...2: Compile++ thumb : geos <= InteriorPointLine.cpp3: Compile++ thumb : geos <= InteriorPointPoint.cpp4: Compile++ thumb : geos <= LineIntersector.cpp5: D:/spatialite-android/jni/geos-3.2.2/source/algorithm/LineIntersector.cpp: In st atic member function 'static double geos::algorithm::LineIntersector::interpolat eZ(const geos::geom::Coordinate&, const geos::geom::Coordinate&, const geos::geo m::Coordinate&)':
6: D:/spatialite-android/jni/geos-3.2.2/source/algorithm/LineIntersector.cpp:224: e rror: expected unqualified-id before '(' token
7: D:/spatialite-android/jni/geos-3.2.2/source/algorithm/LineIntersector.cpp:232: e rror: expected unqualified-id before '(' token
8: D:/spatialite-android/jni/geos-3.2.2/source/algorithm/LineIntersector.cpp: In me mber function 'void geos::algorithm::LineIntersector::computeIntersection(const geos::geom::Coordinate&, const geos::geom::Coordinate&, const geos::geom::Coordi nate&)':
9: D:/spatialite-android/jni/geos-3.2.2/source/algorithm/LineIntersector.cpp:304: e rror: expected unqualified-id before '(' token
10: D:/spatialite-android/jni/geos-3.2.2/source/algorithm/LineIntersector.cpp:306: e rror: expected unqualified-id before '(' token
11: D:/spatialite-android/jni/geos-3.2.2/source/algorithm/LineIntersector.cpp: In me mber function 'int geos::algorithm::LineIntersector::computeIntersect(const geos ::geom::Coordinate&, const geos::geom::Coordinate&, const geos::geom::Coordinate &, const geos::geom::Coordinate&)':
12: D:/spatialite-android/jni/geos-3.2.2/source/algorithm/LineIntersector.cpp:426: e rror: expected unqualified-id before '(' token
在很多位置都提示 error: expected unqualified-id before '(' token,google一下这个错误,发现大概是由于在头文件中对某个函数重复声明冲突引起的。于是打开spatialite-android/jni/geos-3.2.2/source/algorithm/LineIntersector.cpp文件查看,发现基本都与一个名为“ISNAN”的函数有关。在Windows下搜索包含此字符串的文件,又来到了刚才修改过的platform.h文件中,发现这个文件中有与此函数相关的语句。为了解决此问题,尝试对此文件进行再次修改。在大约25行的位置,可以找到“/* #undef HAVE_ISNAN */”这句话,在这句话下面添加一句“#define HAVE_ISNAN 1”。这样做的目的是改变该文件后续的一些编译处理。
- 最后再次ndk-build,成功输出libjsqlite.so库。
现在我们在eclipse中运行spatialite-android这个工程(需要将test-2.3.sqlite数据库adb push到模拟器的sd卡上),就可以看到预期的结果了。 关于如何利用java语言调用spatialite的功能,可以详细参考这个工程中jsqlite包下的封装代码。至此我们就完成了在Android平台上使用spatialite库的准备工作。
此次编译中遇到的问题可参考:http://code.google.com/p/spatialite-android/issues/detail?id=3
2012年2月25日星期六
心力
心力,可以理解为和通常所讲的“体力”相对而言。是指一个人心理的力量,精神上的能量,或者意念。当然你不可能用意念杀死别人,但你可以用心力拯救你自己。
从前有一片茫茫大海,比地球上所有大陆都变成海洋后的海洋还要大。这片海面上漂浮着唯一一个木环,直径只有杯口大小;海里面有一只乌龟,双目失明,它一直在水中游动,一万年才浮到水面上呼吸一次。
我们每个人的生命是有限的,但内心是永恒的。今生今世只不过是内心灵魂的一段短暂旅程,现在的身体只是它寄存的一种形式。上辈子你有可能是只猪,是只考拉,甚至阿凡达,下辈子你有可能是格桑花,是面包树。这些表现形式都不真正属于你,生不带来死不带去,只有内心才是真正的你。但这辈子你能获得这个人身,几率和上面的盲龟浮出海面时,头恰好能钻进木环的几率是一样的。之所以能这么幸运,是前几百世修来的福气。
每做一件好事或者一件坏事,都是你自己的“业”,好的业力多了,就会有好报。不管你在哪一世,万般带不走,唯有业随身。我们活着,除了要积攒业力,最重要的就是锻炼心力,使自己变得正直,善良,坚韧不拔,温柔如水。
路上碰到瘸腿的乞丐了,不要鄙视,给些零钱,他们或许就能多吃一碗救命的米饭;拥挤的地铁上碰到不讲卫生的农民工了,不要移动脚步躲开,他们和你一样有父母有儿女,他们盖起的高楼能让你们安居乐业,而你们做出的价值千万的系统也许没有一点实用价值,只是在浪费纳税人的血汗钱,为腐败提供了温床。
锻炼心力是需要决心和勇气的,但可以从一点一滴做起,比如早晨不赖床,或者开始学一些对人生有意义的东西。最好的办法就是挫折和困难。菩萨和天使不总是带给你好处,还可能是挫折和困难,越是逆境,就越要珍惜。因为在你得到这个磨练机会的时候,别人可能还在把时间挥霍在享乐上。享乐的时间和心力的积累通常是成反比的。
有一些人等意识到,可能也就心有余,力不足了。与各位共勉。
