** We are experiencing a high volume of emails that may result in a delay in our response. We strive to provide you with the best possible service and we apologize for any inconvenience the delay might cause. The deadline to update accounts to the new backend has ended. For questions about what will happen with your current account, please see our FAQ. Thank you for your patience. ** Hello YOURNAME Thank you for contacting Bitcasa Technical Support! You have reached us outside of normal business hours. Business hours are Monday-Friday, 8:00AM - 6:00PM Pacific Time. Your support request (NNNNN) has been created and a Technical Support Specialist will be contacting you during regular business hours. If you wish to add additional comments or details, reply to this email or go to: http://support.bitcasa.com/hc/requests/NNNNN. While you're waiting, check out the Bitcasa Help Center! There you will find answers to common questions and issues, FAQs, our community forums, and more! Check us out at http://support.bitcasa.com. Thank you for contacting us and we look forward to helping you. Regards, Bitcasa Technical Support http://support.bitcasa.comメールに書かれてある、サポートサイトに発行されたリクエスト・チケットに従ってリプライをします。 Amazon S3 の価格から考えて容量無制限のストレージは無理。結局 BitCasa も財務が圧迫して容量無制限を打ち切らざるを得なかった。という事でしょうか。
2014年12月29日月曜日
Bitcasa 退会しました
年間プランで契約していたにも関わらず、突然の1Tに容量を制限しました宣言。それでも価格はGoogleDriveと同じなので、使い続けてみようかなぁと様子を見ていました。
ところが提供されている BitCasaドライブに接続するアプリの品質が一向に改善される気配が無く、エラーで使い物にならない始末。おまけにFAQに書かれている退会方法と実際の退会方法が一致していない状態で放置されたまま。バグがあっても、使い勝手が悪くても、改善される兆しが見えれば問題ないのですが、一向に変化なしで、この状態はサービスとしてはもう終了していると判断しました。
さて辞め方ですが、Bitcasaのアカウントを完全に削除する に書いてある通りです。
最後の肝となる返信先は、
2014年11月6日木曜日
GDAL-1.11.1 における ShapeDriver の日本語設定
前回「GDAL-1.10.1 の日本語環境ではまった」からの続きです。
うまく行ったり、行かなかったりは、文字コードが UTF-8 だったり SJIS だったりと、判別のしようが無い Shape が混在していたのが大きな原因でした。
それで、定説の 環境変数
コード中の解説ページhttp://www.autopark.ru/ASBProgrammerGuide/DBFSTRUC.HTMが詳しいです。
CP932 に相当するケース文の値は、0x7B でなければなりませんから、10進数にしますと、123になります。上記コードと照らしあわせても整合がとれていますよね? という事で、LDID/19 でもOKなのですが、
もしくは、最初から CP932 を指定していれば、LDID/の変換をパスして、上記関数を通った後の値が評価されるので
と、思ったら、-1 は CPACP 扱い? int は 32bit 以上で、65535 == 0xFFFF の解釈で考えればOKでしょうか? 同日追記: 実は SHAPE_ENCODING= を設定しない方が、うまく動く場合もあるようです。どうも、前回DBFファイルに設定があった場合は、SHAPE_ENCODINGは使用されないような事を書きましたが、その記述が間違いだったみたいです。そして、SHAPE_ENCODING=UTF-8 と設定してみましたが、挙動が違うような・・・。もうちょい、突っ込んで調べてみます・・・
set SHAPE_ENCODING=LDID/19ですが、そこを解釈するコードは、このようになっております。
CPLString OGRShapeLayer::ConvertCodePage( const char *pszCodePage ) { CPLString osEncoding; osEncoding.Clear(); if( pszCodePage == NULL ) return osEncoding; if( EQUALN(pszCodePage,"LDID/",5) ) { int nCP = -1; // windows code page. //http://www.autopark.ru/ASBProgrammerGuide/DBFSTRUC.HTM switch( atoi(pszCodePage+5) ) { case 1: nCP = 437; break; case 2: nCP = 850; break; case 3: nCP = 1252; break; case 4: nCP = 10000; break; case 8: nCP = 865; break; case 10: nCP = 850; break; case 11: nCP = 437; break; case 13: nCP = 437; break; case 14: nCP = 850; break; case 15: nCP = 437; break; case 16: nCP = 850; break; case 17: nCP = 437; break; case 18: nCP = 850; break; case 19: nCP = 932; break; case 20: nCP = 850; break; case 21: nCP = 437; break; case 22: nCP = 850; break; case 23: nCP = 865; break; case 24: nCP = 437; break; case 25: nCP = 437; break; case 26: nCP = 850; break; case 27: nCP = 437; break; case 28: nCP = 863; break; case 29: nCP = 850; break; case 31: nCP = 852; break; case 34: nCP = 852; break; case 35: nCP = 852; break; case 36: nCP = 860; break; case 37: nCP = 850; break; case 38: nCP = 866; break; case 55: nCP = 850; break; case 64: nCP = 852; break; case 77: nCP = 936; break; case 78: nCP = 949; break; case 79: nCP = 950; break; case 80: nCP = 874; break; case 87: return CPL_ENC_ISO8859_1; case 88: nCP = 1252; break; case 89: nCP = 1252; break; case 100: nCP = 852; break; case 101: nCP = 866; break; case 102: nCP = 865; break; case 103: nCP = 861; break; case 104: nCP = 895; break; case 105: nCP = 620; break; case 106: nCP = 737; break; case 107: nCP = 857; break; case 108: nCP = 863; break; case 120: nCP = 950; break; case 121: nCP = 949; break; case 122: nCP = 936; break; case 123: nCP = 932; break; case 124: nCP = 874; break; case 134: nCP = 737; break; case 135: nCP = 852; break; case 136: nCP = 857; break; case 150: nCP = 10007; break; case 151: nCP = 10029; break; case 200: nCP = 1250; break; case 201: nCP = 1251; break; case 202: nCP = 1254; break; case 203: nCP = 1253; break; case 204: nCP = 1257; break; default: break; } if( nCP != -1 ) { osEncoding.Printf( "CP%d", nCP ); return osEncoding; } } // From the CPG file // http://resources.arcgis.com/fr/content/kbase?fa=articleShow&d=21106 if( (atoi(pszCodePage) >= 437 && atoi(pszCodePage) <= 950) || (atoi(pszCodePage) >= 1250 && atoi(pszCodePage) <= 1258) ) { osEncoding.Printf( "CP%d", atoi(pszCodePage) ); return osEncoding; } if( EQUALN(pszCodePage,"8859",4) ) { if( pszCodePage[4] == '-' ) osEncoding.Printf( "ISO-8859-%s", pszCodePage + 5 ); else osEncoding.Printf( "ISO-8859-%s", pszCodePage + 4 ); return osEncoding; } if( EQUALN(pszCodePage,"UTF-8",5) ) return CPL_ENC_UTF8; // try just using the CPG value directly. Works for stuff like Big5. return pszCodePage; }これのディスカッションは、ESRI社のフォーラムで話題になっていました。
コード中の解説ページhttp://www.autopark.ru/ASBProgrammerGuide/DBFSTRUC.HTMが詳しいです。
CP932 に相当するケース文の値は、0x7B でなければなりませんから、10進数にしますと、123になります。上記コードと照らしあわせても整合がとれていますよね? という事で、LDID/19 でもOKなのですが、
set SHAPE_ENCODING=LDID/123を設定すると、CP932 に変換してくれる。
もしくは、最初から CP932 を指定していれば、LDID/の変換をパスして、上記関数を通った後の値が評価されるので
set SHAPE_ENCODING=CP932でもOKだったという事になるのでしょうか? 拡張子 DBF ファイルの 29バイト目に、case 文の値か、UTF-8なら -1 == 65535 == 0xFFFF を設定するように改善していけば良さそうですよね?
と、思ったら、-1 は CPACP 扱い? int は 32bit 以上で、65535 == 0xFFFF の解釈で考えればOKでしょうか? 同日追記: 実は SHAPE_ENCODING= を設定しない方が、うまく動く場合もあるようです。どうも、前回DBFファイルに設定があった場合は、SHAPE_ENCODINGは使用されないような事を書きましたが、その記述が間違いだったみたいです。そして、SHAPE_ENCODING=UTF-8 と設定してみましたが、挙動が違うような・・・。もうちょい、突っ込んで調べてみます・・・
2014年11月4日火曜日
近況2014/11/4
ご無沙汰してます。すっかりマネジメントの方に引っ張られてます。
この先どうなっていくかは、不透明な状態ではありますが、クラウドに関して一周した感があるので、それについて、つらつらと書いてみます。
勝者一人勝ちの世界、そこは揺るぎようがないとは思いますが、結局の所、企業というのは他社との差別化が無いと付加価値はありません。コストだけに価値があるわけではないので、クラウドに移行したからと言って、受託の領域が無くなるわけじゃないのかなぁと感じています。
クラウドのビジネスに乗り出して戦うには、体力が必要です。投資の得られたベンチャーならともかく、中小企業がそれをやるには、あまりにも厳しい。じゃあ、仕事はクラウドになって無くなるのか?と思ったら、クラウドのプラットフォームと関連づけられた付加価値という名のサブシステムは無くなりようがないんじゃないかと。受託の領域が無くならないと感じているのは、まさにここなんです。
以上、こんな事を考えてました。とは言え、自分自身、この先どう歩んでいくのか模索中です。
2014年7月25日金曜日
GDAL-1.10.1 の日本語環境ではまった
たまーに、お客さんから DBF ファイルにエンコーディング(文字コード)の設定をしていない Shape ファイルを貰うんですわ。
そしたら、ogr2ogr にかけると、文字化けするんです。
調査していると、1.10.1 のバージョンでは
set SHAPE_ENCODING=LDID/19って、やっても文字化けは直らないんで、調べました。 DBF をバイナリエディタで見ると、もらった Shape ファイルは、DBFファイル中のヘッダーパートの29バイト目の値(エンコーディング)が 0 のままで、データに使用されている文字コードはCP932(Shift_JIS)でした。 GDALのコード中の処理順序は、こんな感じです。
- DBF ファイルの codepage が設定されているかどうかで処理
- CPGファイルに codepage が設定されているかどうかで処理
- 環境変数 SHAPE_ENCODING の値が設定されているかどうかで処理
- プログラム・オプションに codepage が指定されているかどうかで処理
- 文字コードは変換しないで、そのまま利用する
調査していると、1.10.1 のバージョンでは
set SHAPE_ENCODING=CP932としないと、ちゃんとSJISとして扱ってくれないようでした。いつから LDID/19 じゃなくなった? こんな調査に半日以上費やしました・・・(`;ω;´) 2014/09/04 追記: 環境によって、SHAPE_ENCODING=LDID/19 にしないと変換してくれない場合があったりして混乱中。 ソースを修正しすぎた? なんと、UTF-8 コードで書かれた shape と、CP932 コードで書かれた shape が混在している事が判明しました。 エスパーじゃあるまいし、知るか!
2014年5月27日火曜日
Android の PopupWindow が dismiss できない備忘録
久しぶりです。
Android 開発、難しいですね。
知ってました?Android の PopupWindow 作るの難しいの。
Problems creating a Popup Window in Android Activity
タイミングが速すぎるんですよ。何このノウハウ?
でね、PopupWindow 破棄するのも、難しいの知ってました?
PopupWindow.dismiss() なんですがね、PopupWindow.isShowing() == true じゃないと、破棄できないんですよ。迅速にUIでポップアップの表示と破棄をボタン連打で繰り返してると、ゴーストウィンドウが溜まりまくるんですよwwww
何が起きてるかっていうと、PopupWindow が表示しきれる前に破棄をUIから指示できるんです。
そうすると
PopupWindow.isShowing() == false 時に破棄関数が呼ばれて、dismiss() できないから、PopupWindow のインスタンスは生きたまま破棄できない状態でスルーですわ。
どうすればいいか?
Android 開発、難しいですね。
知ってました?Android の PopupWindow 作るの難しいの。
Problems creating a Popup Window in Android Activity
タイミングが速すぎるんですよ。何このノウハウ?
でね、PopupWindow 破棄するのも、難しいの知ってました?
PopupWindow.dismiss() なんですがね、PopupWindow.isShowing() == true じゃないと、破棄できないんですよ。迅速にUIでポップアップの表示と破棄をボタン連打で繰り返してると、ゴーストウィンドウが溜まりまくるんですよwwww
何が起きてるかっていうと、PopupWindow が表示しきれる前に破棄をUIから指示できるんです。
そうすると
PopupWindow.isShowing() == false 時に破棄関数が呼ばれて、dismiss() できないから、PopupWindow のインスタンスは生きたまま破棄できない状態でスルーですわ。
どうすればいいか?
private void purgePopup( PopupWindow pw ) { if( pw == null ) return; if( pw.isShowing() ) { pw.dismiss(); } else { final PopupWindow oldWindow = pw; new Timer().schedule(new TimerTask(){ @Override public void run() { getActivity().runOnUiThread(new Runnable(){ public void run() { oldWindow.dismiss(); } }); } }, 100); } }こんな感じで対処したら、うまくいきました。ぼぇー
2014年3月13日木曜日
boost::filesystem v3 で windows 環境にて日本語ファイルを扱う備忘録
Default encoding under windows
を参考にやってみました。
コンパイラが VC8 だったので、最初、手を抜いてソースコードを UTF-8 でファイルに保存して実行してみたら
#include <boost/locale.hpp> #include <boost/filesystem/path.hpp> #include <boost/filesystem/fstream.hpp> #include <boost/format.hpp> int main() { // Create and install global locale std::locale::global(boost::locale::generator().generate("")); //std::locale::global(boost::locale::generator().generate("ja_JP.UTF-8")); // Make boost.filesystem use it boost::filesystem::path::imbue(std::locale()); // Now Works perfectly fine with UTF-8! boost::filesystem::ofstream hello("こんにちわ.txt"); return 0; }出力されたファイル名が
こんにちめEtxtなんじゃこれ??? あれこれ、試しているうちに、どうやら UTF-8 で保存したのがいけないみたいだという事で
#include <boost/locale.hpp> #include <boost/filesystem/path.hpp> #include <boost/filesystem/fstream.hpp> #include <boost/format.hpp> int main() { // Create and install global locale std::locale::global(boost::locale::generator().generate("")); //std::locale::global(boost::locale::generator().generate("ja_JP.UTF-8")); // Make boost.filesystem use it boost::filesystem::path::imbue(std::locale()); // Now Works perfectly fine with UTF-8! //boost::filesystem::ofstream hello("こんにちわ.txt"); // こ ん に ち わ boost::filesystem::ofstream hello("\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1\xE3\x82\x8F.txt"); return 0; }と正攻法で書きなおしたら、ちゃんと動作しました。 また、くだらない事に時間を費やしてしまった(´・ω・`)
2014年3月12日水曜日
boost::polygon self intersection problem 顛末
この前のポストの問題ですが、面白い事がわかったので、顛末を書きます。
OpenGLES では、描画が float 精度までで、データは double 精度で保持しておりました。
これを boost::polygon にて、trapezoid にかけて台形化処理するのですが、その時に double から float に static_cast で精度を落とします。そうすると、自己交差の無い simple な図形が精度変換の過程で自己交差を持つ図形に変身するケースがあると判明しました。
じゃあ事前に float 精度に落として 自己交差のある状態の図形は float 精度で自己交差を解消した simple な状態にしてから double に戻せば問題無いだろうと思って、やってみましたが、何故かうまく行かない。詳しく突っ込んで調べていないですが、もしかしたら CPU に依存する話なのかもしれません。
余計な事をすると遅くなるので、なんとかしたかったですが、アプリが落ちてしまっては、元も子もありません。もう少し無駄な計算は省こうという事で、こんな感じで落ち着きました。
void to_simple( Polygon& polygon ) { size_t len = polygon.self_.coords_.size(); Point ss = polygon.self_.coords_[len-1]; for( size_t i = 0; i < len-2; ++i ) { Point se = polygon.self_.coords_[i]; Point es = polygon.self_.coords_[i+1]; for( size_t j = i + 2; j < len; ++j ) { Point ee = polygon.self_.coords_[j]; if( i != j ) { if( (ss.x() == es.x() && ss.y() == es.y() ) || (ss.x() == ee.x() && ss.y() == ee.y() ) || (se.x() == es.x() && se.y() == es.y() ) || (se.x() == ee.x() && se.y() == ee.y() ) ) { } else { double xx, yy; if( k_4t_close( xx, yy, ss.x(), ss.y(), se.x(), se.y(), es.x(), es.y(), ee.x(), ee.y() ) ) { se = Point( xx, yy ); ee = Point( xx, yy ); //if( i < j ) { // i < j は自明でしたねorz polygon.self_.coords_.insert( polygon.self_.coords_.begin() + j, ee ); polygon.self_.coords_.insert( polygon.self_.coords_.begin() + i, se ); //} else { // polygon.self_.coords_.insert( polygon.self_.coords_.begin() + i, se ); // polygon.self_.coords_.insert( polygon.self_.coords_.begin() + j, ee ); //} len += 2; } } } es = ee; } ss = se; } }
2014年3月7日金曜日
boost::polygon self intersection problem
ここ2つ前からの投稿の問題は解決しました。この前に geos というライブラリでもテストコードを実行させてみたところ
TopologyException: side location conflict at -752.63088031450525 -148.60182192355231という例外が発生しました。boost::geometry はロバストに出来ていて、自分が例外キャッチするのを忘れていただけで、ちゃんと
Boost.Geometry Overlay invalid input exceptionという例外が送出されていました。 で、どういう問題が発生してたか boost::geometryのコードを読んでみたところ、図形が Simple でない=自己交差を起こしている場合に例外が送出されていました。 なので、自己交差を解消してやれば、問題をクリアできそうな感触を得ました。 残念ながら、自己交差を解消する関数は、見当たらなかったので自作。スタイルが古いですが、古いコンパイラを使っているので auto とか使えなかったんです。 list::insert してるあたりがダサいですが、古い環境なんで、このままです(>_<) 結局、自己交差を解消してやれば、boost::polygon のコードも通りました。
#include <boost/cstdint.hpp> #include <boost/polygon/polygon.hpp> #include <vector> #include <deque> #include <cmath> #include <iomanip> namespace bpl = boost::polygon; typedef double point_value_type; typedef bpl::segment_data<point_value_type> Segment; typedef bpl::polygon_with_holes_data<point_value_type> Polygon; typedef bpl::polygon_data<point_value_type> Ring; typedef bpl::polygon_traits<Polygon>::point_type Point; typedef std::vector<Point> PointSet; typedef std::vector<Polygon> PolygonSet; typedef std::list<Segment> SegmentSet; #define ACCY 1e-6 Polygon make_polygon( const point_value_type* pts, size_t count ) { Polygon polygon; polygon.self_.coords_.resize( count ); for( size_t i = 0; i < count; ++i ) { polygon.self_.coords_[i].x( *pts++ ); polygon.self_.coords_[i].y( *pts++ ); } return polygon; } void construct( PolygonSet& polygons, Polygon polygon ) { using namespace bpl::operators; polygons |= polygon; } void construct( SegmentSet& segments, const point_value_type* pts, size_t count ) { point_value_type ax = pts[count*2-2]; point_value_type ay = pts[count*2-1]; for( size_t i = 0; i < count; ++i ) { point_value_type bx = *pts++; point_value_type by = *pts++; segments.push_back( Segment( Point(ax, ay), Point(bx, by) ) ); ax = bx; ay = by; } } Polygon make_polygon(const SegmentSet& segments ) { Polygon polygon; size_t count = segments.size(); polygon.self_.coords_.resize( count ); size_t i = 0; SegmentSet::const_iterator s = segments.begin(); SegmentSet::const_iterator e = segments.end(); while( s != e ) { polygon.self_.coords_[i++] = bpl::low(*s++); } return polygon; } std::ostream& operator << (std::ostream& os, const Point& p) { os << std::setprecision(10); os << "{ " << bpl::x(p) << ", " << bpl::y(p) << " },\n"; return os; } std::ostream& operator << (std::ostream& os, const SegmentSet& segments) { SegmentSet::const_iterator s = segments.begin(); SegmentSet::const_iterator e = segments.end(); while( s != e ) { os << bpl::low( *s++ ); } return os; } //! 4点交点(線分による完全交差版)を取得する /*! @attention 交点が存在しない場合、x,y は未定義である @retval true 交点が存在 @retval false 交点は存在しない */ bool k_4t_close( double& x, //!< [out] 交点X座標値 double& y, //!< [out] 交点Y座標値 double xk, //!< [in] 線分KLの始点X座標値 double yk, //!< [in] 線分KLの始点Y座標値 double xl, //!< [in] 線分KLの終点X座標値 double yl, //!< [in] 線分KLの終点Y座標値 double xm, //!< [in] 線分MNの始点X座標値 double ym, //!< [in] 線分MNの始点Y座標値 double xn, //!< [in] 線分MNの終点X座標値 double yn //!< [in] 線分MNの終点Y座標値 ) { long double xlk = xl - xk; long double ylk = yl - yk; long double xnm = xn - xm; long double ynm = yn - ym; long double xmk = xm - xk; long double ymk = ym - yk; long double det = xnm * ylk - ynm * xlk; if( std::fabs( det ) < ACCY ) return false; long double s = (xnm * ymk - ynm * xmk ) / det; long double t = (xlk * ymk - ylk * xmk ) / det; if( s < 0.0 || 1.0 < s || t < 0.0 || 1.0 < t ) return false; x = xk + xlk * s; y = yk + ylk * s; return true; } void resolve_segment( SegmentSet& segments ) { SegmentSet::iterator is = segments.begin(); SegmentSet::iterator ie = segments.end(); while( is != ie ) { SegmentSet::iterator cs = segments.begin(); SegmentSet::iterator ce = segments.end(); while( cs != ce ) { if( cs != is ) { if( bpl::intersects( *cs, *is, false ) ) { //std::cout << "X" << std::endl; double xx, yy; Point a = bpl::low( *cs ); Point b = bpl::high( *cs ); Point c = bpl::low( *is ); Point d = bpl::high( *is ); k_4t_close( xx, yy, bpl::x( a ), bpl::y( a ), bpl::x( b ), bpl::y( b ), bpl::x( c ), bpl::y( c ), bpl::x( d ), bpl::y( d ) ); Point n( xx, yy ); //std::cout << a << n << b << std::endl; *cs = Segment( n, b ); cs = segments.insert( cs, Segment( a, n ) ); *is = Segment( n, d ); is = segments.insert( is, Segment( c, n ) ); } else { //std::cout << "o" << std::endl; } } ++cs; } ++is; } } int main() { point_value_type pts[] = { -162.277344, -684.941406, -154.300781, -684.707031, -147.291016, -768.253906, -148.601562, -752.630859, -156.675781, -753.292969, -155.425781, -768.546875, }; /* point_value_type pts2[] = { -155.425781, -768.546875 , -162.277344, -684.941406 , -154.300781, -684.707031 , -148.6018219, -752.6308803 , -147.291016, -768.253906 , -148.601562, -752.630859 , -148.6018219, -752.6308803 , -156.675781, -753.292969 , }; */ SegmentSet segments; construct( segments, pts, 6 ); std::cout << segments; resolve_segment( segments ); std::cout << "===== RESOLVE ====\n"; std::cout << segments; PolygonSet polygons; //construct( polygons, make_polygon( pts, 6 ) ); construct( polygons, make_polygon( segments ) ); return 0; }追記:あれ? insert のあたり、よく考えたら、まずいですかね・・・。
2014年3月6日木曜日
boost::geometry でもハマった
同じ図形を geometry でも処理してみたら、見事に落ちた。
ロバストへの道は険しいのであった(´・ω・`)
// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #include <algorithm> // for reverse, unique #include <iostream> #include <string> #include <boost/geometry/geometry.hpp> #include <boost/geometry/geometries/point_xy.hpp> #include <boost/geometry/geometries/polygon.hpp> #include <boost/geometry/geometries/adapted/c_array.hpp> #include <boost/geometry/multi/geometries/multi_polygon.hpp> BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian) int main(void) { using namespace boost::geometry; typedef model::d2::point_xy<double> point_2d; typedef model::polygon<point_2d> polygon_2d; typedef model::box<point_2d> box_2d; // Define a polygon and fill the outer ring. // In most cases you will read it from a file or database polygon_2d poly; { #ifndef SEGV const double coor[][2] = { {2.0, 1.3}, {2.4, 1.7}, {2.8, 1.8}, {3.4, 1.2}, {3.7, 1.6}, {3.4, 2.0}, {4.1, 3.0}, {5.3, 2.6}, {5.4, 1.2}, {4.9, 0.8}, {2.9, 0.7}, {2.0, 1.3} // closing point is opening point }; #else const double coor[][2] = { { -162.277344, -684.941406 }, { -154.300781, -684.707031 }, { -147.291016, -768.253906 }, { -148.601562, -752.630859 }, { -156.675781, -753.292969 }, { -155.425781, -768.546875 } }; #endif assign_points(poly, coor); } // Polygons should be closed, and directed clockwise. If you're not sure if that is the case, // call the correct algorithm correct(poly); // Polygons can be streamed as text // (or more precisely: as DSV (delimiter separated values)) std::cout << dsv(poly) << std::endl; typedef std::vector<polygon_2d> polygon_list; polygon_list v; try { intersection(poly, poly, v); } catch(const std::exception& e) { std::cerr << e.what() << std::endl; } std::cout << "Clipped output polygons" << std::endl; for (polygon_list::const_iterator it = v.begin(); it != v.end(); ++it) { std::cout << dsv(*it) << std::endl; } return 0; }今回は vc 2008 だったのだ… /D SEGV を付けないケースでは、落ちる事はない。
cl /EHsc /GR /MD test.cpp /D SEGV2014/03/07 追記: geos で selfIntersection にかけてみたが、やはりダメだった。
TopologyException: side location conflict at -752.63088031450525 -148.60182192355231追記:例外処理しないといけないですね。キャッチされない例外で落ちるのは、あたりまえですね。修正しました。
Boost.Geometry Overlay invalid input exceptionになりました。 追記:boost::geometry has_self_intersections.hpp でスローされる例外のようで、自己交差の無い Simple な Polygon が入力として必要なようである。用語が難しいのだが、一般に、図形の Simplify というと、複雑な点数を簡略化する(点を間引く)操作を言うので、自己交差のないポリゴンにばらす関数があれば良いのだろうか。
2014年3月5日水曜日
boost::polygon はまった
三角形分割するのに、boost::polygon を使ってたんですが、残念ながら実数版は実装されているもののサポート対象外みたいで、ロバスト性が保証されていないようです。
Android をはじめとする GLES では、Tesselation(三角形分割)がサポートされていないので、Trapezoid (台形)化してポリゴンを塗り潰してたんですけども、残念です。
以下、削ったコード。
#include <boost/cstdint.hpp> #include <boost/polygon/polygon.hpp> #include <vector> using boost::int32_t; using boost::uint8_t; namespace bpl = boost::polygon; typedef float point_value_type; typedef bpl::polygon_with_holes_data<point_value_type> Polygon; typedef bpl::polygon_data<point_value_type> Ring; typedef bpl::polygon_traits<Polygon>::point_type Point; typedef std::vector<Point> PointSet; typedef std::vector<Polygon> PolygonSet; void set_points( Polygon& polygon, const point_value_type* pts, int32_t count ) { polygon.self_.coords_.resize( count ); for( int32_t i = 0; i < count; ++i ) { polygon.self_.coords_[i].x( *pts++ ); polygon.self_.coords_[i].y( *pts++ ); } } void construct( PolygonSet& polygons, const point_value_type* pts, int32_t count ) { using namespace bpl::operators; Polygon polygon; set_points( polygon, pts, count ); polygons |= polygon; //// SIGSEGV } int main() { float pts[] = { -30162.277344, -21684.941406, -30154.300781, -21684.707031, -30147.291016, -21768.253906, -30148.601562, -21752.630859, -30156.675781, -21753.292969, -30155.425781, -21768.546875, }; PolygonSet polygons; construct( polygons, pts, 6 ); return 0; }追記:どんな図形か調べてみた。ま、往々にしてありがちな図形やね。平行な直線が折り返しているとダメなのであろうか?普通、平行な直線は交点の計算ができないので、交点を求めたりはしない。これをやろうとすると泥沼に陥る事が多い。 2014/03/06 追記: 整数の同じ構成にしてテストを行うと、ちゃんとパスする。
#ifndef SEGF typedef int32_t point_value_type; #else typedef float point_value_type; #endifにして
point_value_type pts[] = { #ifndef SEGF -22277344, -4941406, -14300781, -4707031, -7291016, -88253906, -8601562, -72630859, -16675781, -73292969, -15425781, -88546875, #else -22.277344, -4.941406, -14.300781, -4.707031, -7.291016, -88.253906, -8.601562, -72.630859, -16.675781, -73.292969, -15.425781, -88.546875, #endif };ここは、難しいようで、 polygon_arbitrary_format.hpp にもデバッグ用のコードがコメントアウトされる形で埋め込まれていた。 両者で実行して、違いを見比べてみたところ セーフバージョン
processEvent_ loop current Y -72630881 scanline size 2 ( -16675781, -73292969), ( -8601822, -72630881); ( -14300781, -4707031), ( -8601822, -72630881); found element in scanline 1 finding elements in tree first iter y is -7.26309e+007 loop2 loop2 counts_from_scanline size 2 aggregating loop3 loop3落ちるバージョン
processEvent_ loop current Y -72.6309 scanline size 2 ( -16.6758, -73.293), ( -8.60156, -72.6309); ( -14.3008, -4.70703), ( -7.29102, -88.2539); found element in scanline 1 finding elements in tree first iter y is -72.6309 loop2 counts_from_scanline size 1 aggregating loop3 loop3更に、loop2 の条件判定文のコメントを polygon_arbitrary_format.hpp に追加して追試してみたところ、
if(iter != scanData_.end()) std::cout << "first iter y is " << iter->first.evalAtX(x_) << "\n"; while(iter != scanData_.end() && ((iter->first.pt.x() == x_ && iter->first.pt.y() == currentY) || (iter->first.other_pt.x() == x_ && iter->first.other_pt.y() == currentY))) { //iter->first.evalAtX(x_) == (high_precision)currentY) { std::cout << "loop2\n"; elementIters.push_back(iter); counts_from_scanline.push_back(std::pair<std::pair<std::pair<Point, Point>, int>, active_tail_arbitrary*> (std::pair<std::pair<Point, Point>, int>(std::pair<Point, Point>(iter->first.pt, iter->first.other_pt), iter->first.count), iter->second)); ++iter; if( iter != scanData_.end() ) { std::cout << "CHK loop2 " << iter->first.pt.x() << " == " << x_ << " && " << iter->first.pt.y() << " == " << currentY << "\n"; std::cout << "CHK loop2 " << iter->first.other_pt.x() << " == " << x_ << " && " << iter->first.other_pt.y() << " == " << currentY << "\n"; } }セーフバージョンと落ちるバージョンでは、そもそもscanline の構成が異なっている事がわかった
processEvent_ loop current Y -72630881 scanline size 2 ( -16675781, -73292969), ( -8601822, -72630881); ( -14300781, -4707031), ( -8601822, -72630881); found element in scanline 1 finding elements in tree first iter y is -7.26309e+007 loop2 CHK loop2 -14300781 == -8601822 && -4707031 == -72630881 CHK loop2 -8601822 == -8601822 && -72630881 == -72630881 loop2 counts_from_scanline size 2 aggregating
processEvent_ loop current Y -72.6309 scanline size 2 ( -16.6758, -73.293), ( -8.60156, -72.6309); ( -14.3008, -4.70703), ( -7.29102, -88.2539); found element in scanline 1 finding elements in tree first iter y is -72.6309 loop2 CHK loop2 -14.3008 == -8.60156 && -4.70703 == -72.6309 CHK loop2 -7.29102 == -8.60156 && -88.2539 == -72.6309 counts_from_scanline size 1 aggregating loop3 loop3浮動小数点型の演算は、難しいものだ。やはり、ロバスト性を確保するのは並大抵のことではない感じだ。
2014年2月10日月曜日
2014年2月7日金曜日
Android の Intent が宝の持ち腐れ
ちょっ、Android の開発に関して、ぼやきます。
Intent を介してアプリケーションが連帯する仕組みが整っているのに、ファイル選択ダイアログといった単純なパーツさえ、自分でエクスプローラのアプリケーションを作成する勢いで書かないと、存在しない。
例えば、zip ファイルを選択させたいと思ったら、既存の枠組みでは、
そうすると無料の広告付きアプリを入れてくるか、android-file-dialog(広告付きのオープンソース:改造可)を用意するか、とにかくイケてない。
ま、検索すれば AlertDialog.Builder ベースのファイル選択ダイアログというパーツも見つかるのだが、アクセス権限のないディレクトリに触った瞬間落ちるし、なんか、いけてない。Google さんも、Android の UIガイドと啓蒙みたいな部分に力を入れるよりも、こういった連帯ベース部分に力を入れたほうが、よほどエコなんじゃないでしょうか?
private static final int REQUEST_CHOOSE_ZIP = 1; ... private void selectZip() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); // MIME/Type が微妙だが置いといて intent.setType("application/zip"); intent.addCategory(Intent.CATEGORY_OPENABLE); startActivityForResult(intent, REQUEST_CHOOSE_ZIP ); }と、呼び出してやれば済む話なのであるが、Androidに付属している標準のエクスプローラ・アプリは、得てして、この仕様に対応していない。
そうすると無料の広告付きアプリを入れてくるか、android-file-dialog(広告付きのオープンソース:改造可)を用意するか、とにかくイケてない。
ま、検索すれば AlertDialog.Builder ベースのファイル選択ダイアログというパーツも見つかるのだが、アクセス権限のないディレクトリに触った瞬間落ちるし、なんか、いけてない。Google さんも、Android の UIガイドと啓蒙みたいな部分に力を入れるよりも、こういった連帯ベース部分に力を入れたほうが、よほどエコなんじゃないでしょうか?
2014年1月6日月曜日
SD-1 merrill を買いました
皆さん、明けましておめでとうございます。
ファインダーのついてるカメラが欲しくなったのと、NEX-5Rのクオリティでは我慢できなくなってきたので、カメラを買い替えました。Sigma の SD-1 merrill で、foveon センサという、ちょっとユニークなカメラです。撮れる画像は、はまった時には超一流、だけど、その他の部分は、色々と酷評されている面から考えてもユニークなカメラです。
最近、目が肥えてきて、フルサイズのセンサーで撮影された写真が、なんとなくわかるようになってきました。なので、フルサイズにも惹かれてて、価格的にD610やEOS6Dも圏内でした。NIKON のカメラで撮影されたRAWデータを触らせてもらった事があるのですが、ダイナミック・レンジが半端なく広く感動していた事もあり、D610が有力だったんですが、レンズまで含めると、フルサイズのカメラは、価格的に、かなりしんどい。どうせD610行くならD800Eぐらいのが欲しいというのも頭をかすめました。
PENTAXのK-3も気になってはいたんですが、K-5IIsと比べて、画質は落ちるんじゃないかという部分と、APS-Cサイズな点で、結局SD-1 merrill を選択しちゃいました。
まだ少ししか触ってないんですが、早くも難しいカメラを選んでしまったというのが率直な感想です。ベイヤー方式と異なるカメラなので、RAWデータを弄る感覚が、今までと全く違う。実際どうなのかは、わかりませんが、ダイナミック・レンジは狭いんじゃないかな?という気がしてます。もしくは、現像ソフトで引き出せるダイナミック・レンジが狭いのか?12bit階調しかない NEX-5RのRAWデータでさえ、暗い部分を持ち上げて明るい部分を抑える芸当が、そこそこ効くのに、SD-1 merrill のRAWデータは、どれかを動かすと全体的に追従してきてしまう。しかも、白飛びした部分の潰れ方が極端で、ベタっとします。
手応えとしては、SD-1 merrill こそ HDR 向きなのではないかと感じている次第です。
rsync 備忘録
3台のマシンがあって、入り口のマシンは1台。いちいちコピーしてたら日が暮れるので、ファイル転送部分だけは定型化しておく事にした。
MenteMachine 上に
/home/foo/to_main
/home/foo/to_sub
MainMacihne 上に
/home/foo/to_mente
SubMacihne 上に
/home/foo/to_mente
と、こんな感じディレクトリを構築しておく
MenteMachine 上に、データを収集するためのシェル
- MenteMachine
- MainMachine
- SubMachine
MenteMachine 上に
/home/foo/to_main
/home/foo/to_sub
MainMacihne 上に
/home/foo/to_mente
SubMacihne 上に
/home/foo/to_mente
と、こんな感じディレクトリを構築しておく
MenteMachine 上に、データを収集するためのシェル
#!/bin/bash rsync -av --delete -e 'ssh -c arcfour' foo@MainMachine:/home/foo/to_mente/ /home/foo/to_main/ rsync -av --delete -e 'ssh -c arcfour' foo@SubMachine:/home/foo/to_mente/ /home/foo/to_sub/MenteMachine 上のデータを配送するためのシェル
#!/bin/bash rsync -av --delete -e 'ssh -c arcfour' /home/foo/to_main/ foo@MainMachine:/home/foo/to_mente/ rsync -av --delete -e 'ssh -c arcfour' /home/foo/to_sub/ foo@SubMachine:/home/foo/to_mente/
登録:
投稿 (Atom)