(57)【特許請求の範囲】
【請求項１】
コンピュータ制御システムにおいて使用されるように作られたオブジェクト指向曲げモデルビューアにして、前記コンピュータ制御システムは、前記部品に関連する曲げモデルデータを格納するためのデータベースと、前記部品の画像を表示するための表示装置とを備え、
前記オブジェクト指向曲げモデルビューアは、曲げモデルビューア観察クラスを備え；
曲げモデルビューア観察クラスは、観察モデル属性と、前記曲げモデルビューア観察クラスのメンバー機能として実行される少なくとも一つの観察機能を有し；
前記部品の少なくとも一つの画像は、前記曲げモデルデータおよび前記観察モデル属性に基づいて前記コンピュータ制御システムの前記表示装置に表示される。
【請求項２】
請求項１のオブジェクト指向曲げモデルビューアにして、
前記観察モデル属性は、所定の観察モードに関連する表示情報を備え、前記所定の観察モードは、実線観察モード・ワイヤフレーム観察モード・２次元平面観察モード・正斜影観察モードの少なくとも一つを含む。
【請求項３】
請求項１のオブジェクト指向曲げモデルビューアにして、前記曲げモデルビューア観察クラスは、前記少なくとも一つの観察機能に応じて前記部品の前記画像を変形する情報を更に備える。
【請求項４】
請求項３オブジェクト指向曲げモデルビューアにして、前記少なくとも一つの観察機能は、ズーム機能、回転機能、パンニング機能、又は寸法機能の内の少なくとも一つを有する。
【請求項５】
請求項４によるオブジェクト指向曲げモデルビューアにして前記寸法機能は前記部品の画像を変形し前記部品の少なくとも１つの特徴に関連する寸法情報を追加的に表示する動作を含み、前記寸法情報は、前記部品の少なくとも１つの曲げ線の長さと前記各曲げ線の曲げ角度とを含む。
【請求項６】
請求項１のオブジェクト指向曲げモデルビューアにして、前記曲げモデルビューア観察クラスは、前記曲げモデルビューア観察クラスのメンバー機能として提供される複数の観察機能を備え、前記曲げモデルビューア観察クラスは更に、前記観察機能の各々に応じて前記部品の前記画像を変形するための情報を備える。
【請求項７】
請求項１のオブジェクト指向曲げモデルビューアにして、更に前記部品の前記画像の現在表示されている画面に基づいて、前記表示装置上で観察可能な前記部品の特徴に関連する観察可能情報を提供し維持するための観察可能機能を有するもの。
【請求項８】
請求項７によるオブジェクト指向曲げモデルビューアにして、前記曲げモデルビューア画像クラスは、前記少なくとも１つの撮影機能に応じて前記部品の画像を変更するための情報を含み、前記少なくとも１つの撮影機能は、寸法機能を含み、この寸法機能は前記可視性情報に基づき前記部品の画像を変形し前記部品の観察可能の特徴に関連する寸法情報を表示する操作を含む。
【請求項９】
コンピュータ制御システムにおいて使用されるように作られたオブジェクト指向曲げモデルビューアを格納したコンピュータ読取可能媒体にして、
前記コンピュータ制御システムは、前記部品に関連する曲げモデルデータを格納するためのデータベースと、前記部品の画像を表示するための表示装置とを備え、
前記オブジェクト指向曲げモデルビューアは、曲げモデルビューア観察クラスを備え；
曲げモデルビューア観察クラスは、観察モデル属性と、前記曲げモデルビューア観察クラスのメンバー機能として実行される少なくとも一つの観察機能を有し；
前記部品の少なくとも一つの画像は、前記曲げモデルデータおよび前記観察モデル属性に基づいて前記コンピュータ制御システムの前記表示装置に表示されるもの。
【発明の詳細な説明】
【０００１】
関連出願データ
本出願は1996年5月6日出願の「薄板金属製作設備全体に亘って設計製作情報を管理し分配する装置と方法」と題したU.S.仮出願No. 60/016,948に準拠し、その明細書を全般的に参照する事によって本明細書に明白にとりいれていることを主張する。
【０００２】
著作権についての注意書き
本特許文書の明細書の一部は、著作権保護の対象になっている。著作権保有者はU.S.特許・商標局の特許フアイルや記録に記載されている特許明細書の何人かによる複写には異議を申し立てないが、それ以外のものについては著作権保有者は著作権すべてを保留する。
【０００３】
発明の背景
発明の分野
本発明は一般的に、製造分野及び薄板金属部品のような部品の製作に関するものである。特に、本発明は曲げ薄板金属部品の製作を容易にするために設計・製作情報を工場全体にわたって管理・分配する装置と方法に関するものである。
【０００４】
背景情報
伝統的に、たとえば薄板金属の進歩的な製造設備での曲げ薄板金属の製作は、連続的な製作製造段階を含む。第一段階は設計段階で、そこでは顧客の仕様にもとづいて薄板金属部品の設計が行われる。通例顧客は特定の薄板金属部品の設備での製作を注文する。顧客の注文は通例、部品を工場で製造するのに必要な製品と設計の情報を含んでいる。この情報は、たとえば部品の幾何学的寸法、部品に必要な材料（たとえば鋼鉄、ステインレス鋼、またはアルミニウム）、特殊な成形の情報、分量、引き渡し年月日等を含むことがある。客先から要請された薄板金属部品は広範囲の種類の応用に設計・製作することが出来る。たとえば、製作された部品は最終的にはコンピュータのケース、配電盤、航空機の肘掛け、または自動車のドアのパネルに使われるかもしれない。
設計段階では、薄板金属部品の設計は、適当なコンピュータ支援設計（CAD）システムによって製造設備の設計部でなされる。顧客の仕様に応じて、プログラマーがCADシステムを用いて薄板金属部品の2次元（2ーD）モデルを作成することもできる。通例、客先は部品の重要な幾何学的寸法を含む青写真を提供する。この青写真は、部品に含まれる特別の成形や記号、または薄板金属部品の表面の孔や他の開口を示すこともある。設計プログラマーはCADシステムで2ーDモデルを作成するため、この青写真を度々用いる。この2ーDモデルはまた、薄板金属部品の曲げ線及び/または寸法情報を含む平面図と、一つまたは一つ以上の透視図を含むこともある。
【０００５】
実際に薄板金属部品の曲げ加工を開始する前に、先ず原材料から部品を打ち抜き切断するか/または切断しなければならない。在庫材料の処理に当たって、打ち抜きプレスやプラズマまたはレーザー切断機を制御作動するのに、普通コンピュータ数値制御（CNC）または数値制御（NC）が用いられる。この在庫材料の処理を容易にするため、設計プログラマーは、コンピュータ支援製造（CAM）システムまたはCAD/CAM システムを用いて2ーDモデルにもとづいた制御コードを作成することが出来る。この制御コードには、打ち抜きプレス及び/または切断機にとりいれて、在庫材料からの薄板金属部品の打ち抜き、または切断に利用できる部品プログラムが含められていることもある。
【０００６】
製造プロセスの次の段階は曲げ加工計画段階である．この段階で、曲げ加工計画が作業場で曲げ加工オペレータによって立てられる。オペレータには通常切断または打ち抜かれた一つまたは一つ以上の在庫材料とともに、部品の青写真または2ーD図面が渡される。これらの材料で曲げ加工オペレータは使用する工具と実施される曲げの手順を定める曲げ加工計画を立てる。曲げ作業場には、オペレータがデータを入力した曲げコード、または曲げ計画にもとづいたプログラムが作成できるCNCプレスブレーキのようなCNC金属曲げ機も含まれる。
【０００７】
曲げ加工計画が作成されると、オペレータは曲げ加工の順序の初期テストのための作業場を設置する。このテスト段階では、打ち抜きまたは切断された材料はプレスブレーキに手で組み込まれ、プレスブレーキはプログラムされた順序に従って製作品に曲げを加工するように操作される。オペレータは出来上がった曲げ薄板金属部品を分析して顧客の仕様に適合しているかどうかを検査する。このプレスブレーキの初期作業の結果によって、オペレータは曲げプログラムを編集し、曲げ順序を修正することもある。オペレータはまた、薄板金属部品の設計が適当に修正出来るように、設計部に結果をフイードバックすることもある。テストは通常曲げ薄板金属部品が要求されている設計仕様内におさまるまで続けて行われる。
【０００８】
製作プロセスの最後の段階の一つは曲げ段階である。曲げ計画が作成され、テストされた後、曲げオペレータは曲げ加工場に必要な工具を装備し、曲げ計画と記憶されている曲げプログラムまたはコードに従ってプレスブレーキを作動する。曲げ加工場に必要な量の打ち抜きまたは切断された材料が確保されるように、また他の作業が指定された引き渡し年月日までに完了しているように、作業日程も作成される。作業日程は製作過程の初期段階と/または全過程に平行して作業場監督によって作成または修正されることもある。最後の曲げ薄板金属部品の製作が完了すると、顧客への引き渡しのために部品は集められ、梱包される。
【０００９】
通常の製作、製造過程は幾つかの欠点や不利な点がある。たとえば、各々顧客の設計製造データは通常物理的に（たとえば紙によってフアイルキャビネットに）、電子的に（たとえばデイスクまたは磁気テープに）保管されるが、こうしたデータは普通別々に保管されていて検索するのが容易でない。さらに、多くの工場環境では、重要な仕事情報の分配は工場全体にわたって配布される仕事または企画用紙の形をとる。その結果、データがしばしば紛失または損傷し、以前または類似の仕事に関する設計製造データを検索するのが困難になる。加うるに、データの保管方法の不備によって、設計製造情報を全工場の作業場やその他の場所に配布するのに貴重な時間が失われる。また部品の設計や曲げ計画の作成は、主として設計プログラマーと曲げオペレータによって行われ、個人の知識、手腕と経験によるところが大きいので、薄板金属部品と曲げ計画の作成の間に製造時間がかなり失われる。
【００１０】
近年、慣習的な薄板金属製造過程を改善し、過程全体にわたる効率を改善するための開発と試みがなされてきた。たとえば、市販のCAD/CAMシステムにおける2次元（2-D）および3次元（3-D）モデル作成の使用と開発によって曲げ薄板金属の製作過程とモデル作成を促進され、改善された。今では設計プログラマーやオペレーターは2ーD及び3ーD表示を用いて、部品の形状をよりよく理解し、部品設計と曲げコードの順序をより効率的’に作成出来るようになっている。データを電子的に記憶し、トランスフアーする機能は、設計部から作業場への情報の流れを改善した。コンピュータとデータ通信ネットワークの進歩により、最早古い紙テープや磁気デイスクをキャビネットまたはフアイルから探し出すことが不要になった。
【００１１】
こうした進歩があるにもかかわらず、組織と工場環境全体にわたる設計と製造情報の組織化と流れを改善する必要がまだある。たとえば、在来の製造システムでは、各顧客の注文の重要な設計及び製造情報が、工場のどの場所でも容易にアクセスでき、検索できるような論理的関係づけがなされていない。今までのシステムはまた、薄板金属部品の特徴や特質のような、色々な特色にもとづいた仕事情報を探索する機能をもたない。たとえば同一または類似の部品の探索にもとづいた、以前の仕事情報が探索でき、検索出来ることは、全体的な製作プロセスを大幅に増強し、将来の仕事の必要製造時間を短縮する。
【００１２】
過去の試みはまた、設計プログラマーや作業場オペレータによる薄板金属部品の設計を容易にすることに欠けている。2ーDや3ーDモデリング・システムによって、設計者は部品の形状や幾何学をよりよく理解出来るようになったが、このシステムによって設計プログラマーや作業場オペレータに科せられた負担は軽減されていない。たとえば、これらのシステムによって設計プログラマーが現存の2ーD  CADモデルを簡単に3ーD表示に変換することはできない。また作業場オペレータに曲げ加工計画を立てる助けとなる部品の2ーD及び/また3-D図面が提供されても、オペレータは必要な工具や曲げ手順を手で/または試行によって決めなければならない。
【００１３】
発明の要約
上記に照らして、本発明は、発明の一つまたは一つ以上の見地、実施例及び/または特色あ、るいはサブコンポーネントを通して、以下にに特記する一つまたは一つ以上の目的と利点をもたらすために供するものである。
【００１４】
本発明の一般的な目的は、曲げ薄板金属部品のような部品の製作を促進するために、設計と製造情報を全工場に亘って管理し、分配する装置と方法の提供である。
【００１５】
さらに本発明の目的としては、たとえば進歩的な薄板金属製作設備における重要な仕事情報の紛失または破壊を防止し、専門的知識の蓄積の有効活用と整理を助長する装置と方法の提供がある。
【００１６】
もう一つの本発明の目的は、各顧客の注文の設計と製造情報の双方を、論理的に記憶する装置と方法を備えることによって、工場のどの場所でも容易にアクセスでき、検索できるようにすることにある。
【００１７】
さらにもう一つの本発明の目的は、仕事データが中央のデータベースまたはフアイルサーバーに、全工場のどの場所でも容易に探索し、検索できるよう論理的に記憶されている設計と製造情報を管理し、分配する装置と方法の提供にある。仕事データは仕事に関連した設計と製造情報ばかりでなく、必要な曲げ操作を遂行するための実際の曲げコードも提供できる。
【００１８】
またさらに本発明の目的は、色々な探索基準にもとづいた、設計と製造情報を含む以前の仕事情報を探索する装置と方法の提供である。探索基準は、たとえばこれから製造される薄板金属部品の特色や特徴を含むことができ、これによって同一または類似の部品に関連した以前の仕事情報を、将来の仕事の全体的な製造時間の短縮に利用できる。
【００１９】
本発明のもう一つの目的は、各顧客の注文に関連した従来の書類仕事または企画用紙を、工場の何処からでも瞬間的にアクセスできる電子的ジョッブシートに置き換えることである。電子的なジョッブシートはどの場所でも表示でき、部品の2ーD及び/または3-Dモデル像、工具の選択、最適曲げ手順、必要なステイジング情報やバーコードまたは認識番号を含む、仕事に関連した重要な設計と製造情報を含む。この電子的ジョッブシートには、曲げオペレータによって将来再び同じ、または類似の仕事を行うときに役立つと思われる、特別の指図または手順を録音録画したオーデイオ及び/またはビデオ部品も備えられる。
【００２０】
本発明のもう一つの目的は薄板金属部品の2ーDと3-Dコンピュータ画像を提供することによって部品図面の解析に要する時間を短縮する事にある。固体3ーD画像モード、3ーDワイヤフレーム画像モード、2-D平面画像モード及び正射画像モードを含む、色々な画像が提供できる。薄板金属部品の解析に役立つズーミング、パンニング、回転及び自動寸法入れを含む色々な異なる画像機能も備えられる。
【００２１】
さらに本発明は設計者の薄板金属部品の設計と曲げ計画の製作を容易にする装置と方法を提供する目的を持つ。たとえば、現存する部品の2ーDモデルから部品の3ーD表示を容易に製作することができるようにするのも本発明の目的である。さらにもう一つの本発明の目的として、曲げ計画とプログラムされた曲げコードを作成する時間を短縮するためのグラフィックスインターフエイスの提供がある。
【００２２】
上記に鑑みてこの発明は設備において製造されるべきパーツ（例えば板金パーツ）を表現するためにコンピュータ可読媒体に格納されたオブジェクト指向ベンドモデルに向けられる。このオブジェクト指向ベンドモデルは、前記パーツの特徴に関連するパーツ情報及びこのパーツになされる曲げ操作に関連する曲げ情報を有する複数のオブジェクトを含むパーツクラスを備える。前記パーツ情報は、パーツの設計及び製造情報を含む。前記パーツ設計情報は２次元及び３次元座標空間における前記パーツの表現に関連する。更に、前記曲げ情報は、前記パーツの曲げ線において曲げ操作を行なうための曲げデータ及び命令を備えた一群のオブジェクトを有する。曲げデータは、曲げ角度量及び曲げ半径量を含む。
【００２３】
この発明の１つの側面によれば、前記パーツクラスは前記曲げ操作が前記パーツになされるところの順番に関連する曲げシーケンス情報を備える属性を含む。前記属性はパーツ材質タイプ及びパーツ厚さを備える。更に上記複数のオブジェクトは、面オブジェクトを備え、この面オブジェクトは、前記パーツの各面の寸法に関連する設計データ及び少なくとも１つの座標空間内における前記パーツの各面の表現に関連する１データを含む。前記複数のオブジェクトは更に、曲げ線オブジェクトを含む。前記曲げ線オブジェクトは前記パーツの各曲げ線の寸法に関連する設計データ及び少なくとも１つの所定の座標空間内での前記パーツの各曲げ線の表現に関連する１データを含む。前記曲げ線オブジェクトは更に、前記パーツになされる曲げ操作に関連する曲げ製造データを含む。前記曲げ製造データは、前記パーツの各曲げ線についての部位幅データ及び曲げピッチ及び配向データを含む。
【００２４】
前記曲げモデルの複数のオブジェクトはまた穴オブジェクト及び成形オブジェクトを含む。この穴オブジェクトは、前記パーツにおける少なくとも１つの穴の寸法に関連する設計データ及び少なくとも１つの所定の座標空間内での前記パーツの各穴の表現に関連する１データとを含む。前記成形オブジェクトは、前記パーツの各々の成形部の寸法に関連する設計データ及び少なくとも１つの座標空間内における前記パーツの各成形部の表現に関連する１データとを含む。トポロジーオブジェクトと曲げ特性オブジェクトが更に設けてある。前記トポロジーオブジェクトは、前記パーツの特徴に関連するパーツトポロジーデータを含み、前記パーツの特徴は、前記パーツの面または穴または成形部または曲げ線の少なくとも１つを含む。更に前記曲げ特性オブジェクトは、前記パーツに関連する製造拘束データを含む。この発明はまた製造設備において製造されるべき板金パーツを表現するための、コンピュータ可読媒体に格納されたオブジェクト指向曲げモデルに向けられる。前記オブジェクト指向モデルは、複数のパーツ特性を有するパーツオブジェクトと２次元座標空間及び３次元座標空間において板金パーツを表現するための複数のオブジェクトを含むパーツクラスを備える。前記複数のオブジェクトは、前記板金パーツの特徴に関連する設計情報及び前記板金パーツに少なくとも１つの曲げ操作を行なうための曲げ情報を含む。前記パーツの特徴は、面及び穴及び成形部及びまたは曲げ線を含み、前記複数のオブジェクトは、面オブジェクト及び穴オブジェクト及び成形オブジェクト及びまたは曲げ線オブジェクトを備える。
【００２５】
前記曲げ情報は、前記板金パーツになされる複数の曲げ操作に関連する。前記曲げ情報は、前記板金パーツに少なくとも１つの曲げ操作を行なうための曲げデータ及び命令を備えた一群のオブジェクトを備える。前記曲げデータは、例えば、曲げ角度量及び曲げ半径量を含む。更に前記曲げ属性は、前記曲げ操作が前記板金パーツに対してなされる順番に関連する曲げシーケンス情報を備える。前記パーツ属性はまた、パーツ材料タイプ及びパーツ厚さを備える。
【００２６】
この発明の他の側面によれば、コンピュータ制御システムにおいて用いられるように構成されたオブジェクト指向曲げモデルビューアが提供される。前記コンピュータ制御システムは、前記パーツに関連する曲げモデルデータを格納するデータベースと前記パーツの画像を表示するための表示装置とを含む。前記オブジェクト指向曲げモデルビューアは、曲げモデルビューア観察クラスを備え、この曲げモデルビューア観察クラスは、観察モデル属性と前記ベンドモデルビューア観察クラスの要素機能として実行される少なくとも１つの観察機能とを含む。前記パーツの少なくとも１つの画像が、前記曲げモデルデータ及び観察モデル属性とに基づいて、前記コンピュータ制御システムの表示装置上に表示される。
【００２７】
種々の追加的特徴が、この発明のオブジェクト指向曲げモデルビューアに設けてある。例えば、前記観察モデル属性は所定の観察モード或いは複数のモードに関連する表示情報を備え、前記所定の観察モード或いは複数の観察モードは実線観察モードまたはワイヤフレーム観察モード、２次元平面図モード、及びまたは斜視図モードを含む。前記曲げモデルビューア観察クラスはまた、１つまたはそれ以上の観察機能に応じて前記パーツの画像を修正するための情報を含む。前記観察機能は、例えば、ズーミング機能または回転機能またはタンニング機能及びまたは寸法付け機能を含む。前記ズーミング機能は、表示装置上で前記パーツの画像をズームするための操作を含み、前記回転機能は前記パーツの画像を回転するための操作を含む。前記タンニング機能は、前記表示装置上で前記パーツの画像をタンニングする操作を含み、前記寸法機能は、前記パーツの少なくとも１つの特徴に関連する寸法情報を追加的に表示するために前記パーツの画像を修正する操作を含む。前記寸法情報は、前記パーツの少なくとも１つの曲げ線の長さまたは前記パーツの各曲げ線の曲げ角度及びまたは前記パーツの少なくとも１つのフランジ部の長さを含む。
【００２８】
前記オブジェクト指向曲げモデルビューアは、前記パーツの画像の現在表示されている姿に基づいて前記表示装置上において観察可能な前記パーツの特徴に関連する観察可能性情報を維持し提供するための観察可能性機能を有する。前記曲げモデルビューア観察クラスは、少なくとも１つの観察機能に応じてパーツの画像を修正するための情報を含む。前記観察機能は、観察可能性情報に基づいて前記パーツの画像を修正しパーツの観察可能な特徴に関連する寸法情報を表現するための操作を含む寸法機能を備える。更にオブジェクト指向曲げモデルビューアは、前記表示装置上のパーツの画像の現在表示されている姿のズーム係数に関連するズーム係数情報を含む。
【００２９】
本発明の更に他の側面によれば、パーツの表示されている画像を操作するためのシステムが提供される。前記パーツの表示されているイメージは３次元座標空間においてスクリーン上に表示される。このシステムは以下を含む。指令信号を生成するための入力装置（例えばジョイスティック装置或いはマウス装置）ここに前記指令信号は前記パーツの表示されている画像を修正するように構成された少なくとも１つの所定の観察機能に関連する。表示されている画像の現在の姿を決定するための現在姿決定システム。表示されているイメージの現在の姿に基づいて前記パーツの回転軸を動力学的に設定するための設定システム。前記観察機能に応じて、前記指令信号及び回転軸に基づいて前記パーツの表示されている画像を修正するための画像修正システム。
【００３０】
所定の観察機能は、回転機能を備え、前記画像修正システムは前記指令信号に基づいて前記回転軸を中心としてパーツの表示されている画像を回転するように構成されている。更に現在姿決定システムは、パーツの表示されている画像の現在の姿がパーツの全体の姿であるか或いはパーツの部分的姿であるかを決定するように構成されている。前記設定システムは、前記現在姿決定システムが前記パーツの表示されているイメージの現在の姿は全体の姿であると決定する時、前記パーツの幾何学的中心を前記パーツの回転軸が通るように設定するように構成されている。更に前記設定システムは、前記現在姿決定システムがパーツの表示されている現在の姿が部分的姿であると決定する時、前記パーツの回転軸が前記スクリーンのセンターを通るように設定するように構成されている。
【００３１】
前記システムには他の特徴が設けてある。例えばパーツ観察可能システムが設けてあり、それは現在の姿に基づいてパーツの一部がスクリーンの中心に観察可能であるか否かを決定する。その場合には、前記パーツ観察可能性システムが前記パーツの前記一部が観察可能であると決定する時前記回転軸が前記スクリーンの中心における前記パーツの前記一部を通るように設定するように構成されている。更に前記設定システムは、前記パーツ観察可能性システムが前記パーツの前記部分がスクリーンの中心において観察可能ではないと決定する時、前記パーツの幾何学的中心のＺ座標軸における前記スクリーンの中心を前記回転軸が通るように設定するように構成されている。
【００３２】
前記現在姿決定システムがパーツの表示されている画像の現在の姿は部分的姿であると決定する時、前記スクリーンの中心に位置し且つ前記スクリーンのカメラ視野に最も近い前記パーツの部分を特定するためのシステムが設けてある。前記パーツの特定された部分が前記パーツの開口部に対応するかどうかを決定するためのオブジェクト検出システムがまた設けてある。このオブジェクト検出システムが、パーツの特定された部分はパーツの開口部に関係しないと決定する時、前記計算システムは、前記回転軸が前記パーツの前記特定された部分を通るように設定するように構成されている。更に前記オブジェクト検出システムが前記パーツの特定された部分が当該パーツの開口部に関連すると決定する時、前記パーツの幾何学的中心のＺ座標に対応する深さにおいて前記スクリーンの中心を前記回転軸が設定されるように前記設定システムは構成されている。
【００３３】
前記入力装置はジョイスティック装置及びまたはマウス装置を備えている。前記ジョイスティック装置は、ジョイスティック仮想空間を含み、当該装置からの指令信号は前記ジョイスティック仮想空間内での前記ジョイスティック装置の移動に関連する情報を含む。前記画像修正システムは、前記ジョイスティック仮想空間内でのジョイスティック装置の移動をスクリーンのスクリーン空間内での仮想の移動に写像するための写像システムを有する。従って、前記画像修正システムはジョイスティック移動から写像されたカーソルの移動に基づいて前記パーツの表示された画像を修正する。前記写像システムは、前記ジョイスティック仮想空間の寸法に対する前記スクリーン空間の寸法の比率に基づいて、前記ジョイスティック装置の移動を前記スクリーン空間内でのカーソルの移動へ写像するように構成されている。例えば前記カーソルの移動は以下の式に基づいて前記写像システムにより写像される。
【００３４】
現在位置＝従前位置＋（スケール係数×Ｖ）
ここに現在位置はスクリーン空間内でのカーソルの現在の位置であり、従前位置は前記スクリーン空間内でのカーソルの従前の位置であり、スケール係数はジョイスティック仮想空間の寸法に対するスクリーン空間の寸法の比率であり、Ｖは前記ジョイスティック仮想空間内でのジョイスティック原点からジョイスティック現在位置へのジョイスティック装置の移動及び方向に関連するベクトルである。
【００３５】
この発明の他の特徴によれば、前記写像システムは、前記写像システムにより必要されるスケール係数を調整するためのスケール調整システムを備える。このスケール調整システムは、前記スクリーン空間の寸法の前記ジョイスティック仮想空間の寸法に対する比率に所定の調整係数を掛け合わせ調整されたスケール係数を提供するように構成されている。前記写像システムは前記ジョイスティック運動を写像する際にこの調整されたスケール係数を用いるように構成されている。非限定的な事例として、３という調整係数が使用される。
【００３６】
この発明はまたパーツの表示された画像を操作する方法を含む。ここに前記パーツの前記表示された画像は３次元座標空間においてスクリーン上に表示される。前記方法は以下の工程を含む。入力装置から生成された指令信号を受け取る工程。ここに前記指令信号は前記パーツの表示された画像を修正するように構成された少なくとも１つの所定の観察機能に関連する。スクリーン上においてパーツの表示された画像の現在の姿を決定する工程。前記パーツの現在の姿に基づいて前記パーツの回転軸を動力学的に設定する工程。前記観察機能に応じて、前記指令信号及び回転軸に基づいて前記パーツの表示された画像を修正する工程。
【００３７】
この発明の上記した方法によれば、前記所定の観察機能は、回転機能を備え、これにより前記パーツの表示された画像は指令信号に基づいて前記回転軸を中心として回転される。更に前記設定の工程は、前記パーツの表示された画像の現在の姿が全体の姿であると決定される時、前記パーツの幾何学的中心を前記パーツの回転軸が通るように設定する操作を含む。前記設定の工程はまた、前記パーツの表示された画像の現在の姿が部分的な姿であると決定される時、前記パーツの回転軸が前記スクリーンの中心を通るように設定する操作を含む。
【００３８】
この発明の他の側面によれば、パーツの画像と共に寸法情報をスクリーン上に表示するシステム及び方法が提供される。前記方法は以下の工程を含む。前記パーツの表示された画像の現在の姿を決定し且つ前記現在の姿に基づいてスクリーン上で複数の特徴のうちのいずれが観察可能であるかを決定する工程。前記パーツの表示された画像と共にスクリーン上に、スクリーン上で観察可能であると決定されたパーツの特徴の各々についてのみの寸法情報を選択的に表示する工程。前記方法は更に、前記パーツに関連する曲げモデルデータにアクセスし、この曲げモデルデータに基づいて前記パーツの特徴の各々についての寸法情報を表示するためのスクリーン上の全ての可能な位置を決定する。更に、前記選択的に表示する工程は所定のヒューリスティックを適用し、前記可能な位置に基づいて前記観察可能な特徴の寸法情報を表示する場所を決定する。前記ヒューリスティックは、前記パーツの表示された画像の外側に存在するスクリーン上の位置に前記寸法情報を表示する動作と観察者の観察点に近い方のスクリーン上の位置に前記寸法情報を表示する動作と及びまたはスクリーン上で寸法情報が重なり合わないように前記寸法情報を表示する動作を備える。
【００３９】
表示される前記寸法情報は、前記パーツの各曲げ線についての曲げ長さ及び曲げ角度を備える。前記寸法情報はまた、前記パーツの各曲げ線に関連する内側曲げ半径及び曲げ縮小量を含む。ここに前記表示の工程は、前記現在姿に基づいて観察可能であると決定される前記パーツの各曲げ線についての曲げ線長さ、曲げ角度、曲げ半径及びまたは曲げ縮小量を表示する。前記パーツの各フランジ部のフランジ長さのような他の寸法情報も表示される。追加の情報例えばパーツの幅及び深さ及び高さも表示される。
【００４０】
選択的に表示する工程は、パーツの所定の特徴のみの寸法情報を表示するための自動寸法付け操作を行なうことを含む。従って観察可能であると決定される所定の特徴のみについて寸法情報が表示される。更に前記選択的表示の工程は、パーツの特徴に関連するユーザにより選択された寸法情報を表示するためのマニュアル寸法付け操作を実行することを含む。従ってユーザに選択された寸法情報の各々は観察可能であると決定されるパーツの特徴についてのみ表示される。スクリーン上に表示されたパーツの画像と共に寸法情報を表示するシステムも提供される。このシステムはパーツの表示された画像の現在の姿を決定し且つ現在の姿に基づいて複数の特徴のうちのいずれがスクリーン上で観察可能であるかを決定するためのシステムと前記パーツの表示されたイメージと共にスクリーン上に、スクリーン上で観察可能であると決定されたパーツの特徴のみについて寸法情報を選択的に表示するシステムとを含む。
【００４１】
パーツに関連する曲げモデルデータにアクセスするためのアクセスシステムのみならずこの曲げモデルデータに基づいてパーツの複数の特徴の各々についての寸法情報を表示するためのスクリーン上の全ての可能な位置を決定するためのシステムが設けてある。前記選択的表示システムは、所定のヒューリスティックを適用し前記可能な位置に基づいて観察可能な特徴の寸法情報を表示すべき場所を決定するためのシステムを含む。表示される前記寸法情報は、前記現在姿に基づいて観察可能であると判断される前記パーツの各曲げ線についての曲げ線長さ、曲げ角度、曲げ半径及びまたは曲げ縮小量を含む。他の寸法情報、例えばパーツの各フランジ部のフランジ長さはまた表示される。追加の情報例えばパーツの幅及び深さ及び高さもこの発明によれば表示される。
【００４２】
上記の特徴に加えて、さらに特徴と/またはその変形を設けることができる、たとえば、発明を上述した特徴の色々な組み合わせ、または再組み合わせ及び/または下記の詳細な記述にある幾つかの特徴の組み合わせとの再組み合わせに適用させることができる。
【００４３】
上に列記したものや他の本発明の対象物、特徴及び利点については、この後により詳細に記述する。
【００４４】
付録の要約
本発明の詳細な記述をさらに促進するため、付記の限定されない本発明の望ましい実施例の例に沿っての発明の色々な特徴、操作及び機能に関するソースコードの例やコメントを記した、以下の多数の付録を参照する：
付録の要約
本発明の詳細な記述をさらに促進するため、付記の限定されない本発明の望ましい実施例の例に沿っての発明の色々な特徴、操作及び機能に関するソースコードの例やコメントを記した、以下の多数の付録を参照する：
付録Aはたとえば一つの類似部品を探索するときの特徴抽出演算実行の典型的なソースコードであり；
付録Bはたとえば本発明の幾つかの類似部品の探索時に類似指数演算を行使する典型的なソースコードであり；
付録Cはこの発明で曲げ線検出操作を行う典型的なソースコードであり；
付録Dは本発明の2-Dクリーンアップを実行するための典型的なソースコードであり、これによって薄板金属部品の3-Dモデルを元の3方向からの2-D図面にもとづいて作成するのに使用出来；
付録Eは本発明の曲げモデルビューアーに色々なビュー モードや機能を実行するための典型的ソースコードであり；
付録F,G,HとIは本発明の自動寸法入れ特性を実行するための典型的なソースコードとコメントであり；
付録Jは本発明の曲げモデルビューアーの、部品・エンテイテイの観察可能性機能を実行するための典型的なソースコードであり；
付録Kは曲げモデルの実施と部品構造の構成に関する、本発明の色々な教訓をふまえた一般的なコメントを含み、
付録Lは与えられた部品の回転軸の動的計算による3-D操作とナビゲーションシステムを実行する典型的なソースコードである。
【００４５】
本発明はこの後の詳細記述で限定されない本発明の望ましい実施例の例についての多数の図面を参照しながら記述されており、記述の中の同じ参照番号は全図面中の類似の部品を示す。
【００４６】
詳細な説明
本発明の見地に沿って、全工場に亘って設計製造情報を管理分配し、工場内での部品の製造を促進するための装置と方法が具備される。この本発明の特徴は広範囲の工場環境や装置に利用することができ、特にこの発明は一続きの製作製造段階が異なる場所で行われる工場環境の充足に利用できる。限定されない実施例や種々の例を通じて、本発明を、たとえば進歩的な薄板金属製造設備における曲げ薄板金属部品の製作を参照しながら記述する。
【００４７】
図1に、本発明の実施例に従って、進歩的な薄板金属製造設備38一般が、ブロック線図で図示されている。図1に示すように、薄板金属製造設備または工場38は全工場に分散している多数の場所10,12,14...20をもつ。
【００４８】
これらの場所には設計事務所10、出荷作業場14、打ち抜き作業場16、曲げ作業場18及び溶接作業場20が含まれる。図1に画かれている薄板金属工場38には分離した場所が六つしかないが、勿論工場は六つ以上の分離した場所をもちうるし、また図1に画かれている各タイプの事務所または作業場は一つ以上の場所を占めることもある。たとえば設備38の大きさと製産必要容量により、一つ以上の打ち抜き作業場16、曲げ作業場18と/または溶接作業場20を設けることができる。さらに工場38は一つ以上の設計事務所10、組立作業場12または出荷作業場14をもちうるし、曲げ薄板金属部品の製作製造を促進するための他のタイプの場所をもちうる。
【００４９】
工場38内の各場所10,12,14...20は部品の製作製造に伴う一つまたは一つ以上の別個の製作製造段階や処理に対応し、実行する用具を備えている。たとえば、設計事務所10は顧客の仕様にもとづいた薄板金属部品の設計を促進するために、適当なキャド／キャム（CAD/CAM）システムをもちうる。このCAD/CAMシステムには一つまたは一つ以上のパソコンとデイスプレイ、プリンター及び市販のCAD/CAMソフトウエアーを含みうる。限定されない例として、設計事務所10のCAD/CAMシステムはオートキャドまたはキャドキー、またはアマダ・アメリカ  社（以前はU.S.アマダ株式会社の社名で営業）ビユエナ  パーク、カリフオルニアから入手できる アマダAP40またはAP60 CAD/CAMシステムを含みうる。さらに、ベールムのようなアシュラー社から入手できるウインドウズにもとづいたCADシステムも使用できる。このCAD/CAMシステムを用いて設計プログラマーは客先の注文にある図面やデータにもとづいて薄板金属部品の2-Dモデルと/または3-Dモデルを作成できる。設計プログラマーはまた薄板金属部品の設計にもとづいた制御コードを作成し、これによってたとえば被加工材から薄板金属部品を打ち抜きまたは切断するための、CNC打ち抜きプレスと/または切断機を制御する部品プログラムが作成できる。
【００５０】
打ち抜き作業場16と曲げ作業場18は各々CNC及び/またはNC機械工具のどのような組み合わせでも備えられる。たとえば打ち抜き作業場16は、コマ・シリーズ及び/またはペガ・シリーズのアマダ・タレット打ち抜きプレス、あるいは他の市販されているCNC及び/またはNC打ち抜きプレス一つまたは一つ以上もつことができ、また曲げ作業場18は、RGシリーズ  アマダ・プレスブレーキまたは他の市販されている多軸ゲージング・プレスブレーキのようなCNC及び/またはNCプレスブレーキを一つまたは一つ以上もつことができる。さらに溶接作業場20は、薄板金属部品に対して必要な如何なる溶接をも果たすために適当な溶接機器を備えることができる。打ち抜き作業場16、曲げ作業場18と溶接作業場20は設備38の工場内のどの場所にも設置出来、熟練オペレータ（たとえば打ち抜きプレスオペレータ、曲げ機オペレータ等）によって手動で動かすことができる機械も備えている。アマダ  セルロボミニやアマダ  プロムキャムのような全自動またはロボット支援機械もこれらの場所に備えることができる。必要な打ち抜きと曲げの作業、あるいは必要な如何なる溶接作業もこれらの作業場で製作過程中に行うことができる。
【００５１】
さらに図1に示すように、進歩的な薄板金属設備38は組立作業場12と出荷作業場14も含む。組立作業場12と出荷作業場14には、顧客への製造部品の組立と出荷を促進するために必要な梱包、ルート割り当て及び/または輸送機器も含まれる。
部品の組立と出荷は工場職員によって手動で行使または管理されるが、機械自動化及び/または機械支援にすることもできる。さらに組立作業場12と出荷作業場14は、物理的に工場作業場（たとえば打ち抜き作業場16、曲げ作業場18及び/または‘溶接作業場20に近接した）に近い場所に置くか、または薄板金属工場38とは別の設備または区域に置くことができる。
本発明の見地に沿って、重要な設計と製造情報の管理と分配は、設計と製造情報を電子的に記憶し、分配することによって行われる。伝統的な紙上の仕事の段取りまたはワークシートを、工場のどの場所からでも瞬時的にアクセスできる電子的なジョッブシートに置き換え、または補足することによって、本発明は工場の全体的な効率を改善することができる。加えて、本発明の色々な側面や特徴によって、記憶された設計製造情報の編成とアクセスが改善される。さらに類似または同一の薄板金属部品に関する以前の仕事情報のアクセスや検索が、この発明の色々な特徴を通じて出来るようになっている。
【００５２】
この目的のため、本発明の色々な側面は、サーバーモジュール32とデータベース30を薄板金属設備38内の多数の場所10,12,14...20各々と結ぶ通信ネットワーク26を設けることによって実行される。このあと論ずるように、各場所10,12,14...20は通信ネットワーク26とデータベース30にインターフエイスするステーションモジュールをもつ。図1、２と３に発明のこれらの特色と実装の限定されない例を示す。
【００５３】
図1と２に示すように、通信ネットワーク26は設備38の色々な場所10,12,14...20の各々とサーバーモジュール32とデータベース30を結んでいる。通信ネットワーク26はデータや情報を場所10,12,14...20とサーバーモジュール32とデータベース30間で伝送できるものであれば、どのようなネットワークでもよい。伝送は電子的または光学的に、無線周波数伝送または遠赤外伝送によって行われる。限定されない例として、通信ネットワーク26は、ローカルエリアネットワーク（LAN）、エーテルネットまたは同様のネットワーク構造で構成出来る。後でさらに述べるように、場所10,12,14...20の各々はまた、通信ネットワーク26を通じて情報を伝送し、受信するためネットワーク終端接続装置（たとえばコンピュータ、ミニコンピュータまたはワークステイション）及び/または周辺機器（たとえばデイスプレイモニターまたは画面、プリンター、CD-ROM、及び/またはモデム）をもつことができる。ネットワーク終端接続装置と周辺機器は通信ネットワーク26とインターフエイスするためと、あとで詳しく論ずるよに、本発明の色々な特徴と側面を備えるためのハードウエアと適当なソフトウエアまたはプログラム論理を含む。工場内の場所にコンピュータを設置する場合のコンピュータは独立型、パソコンまたはその場所にある装備や機械類のインターフエイス装置の一部である汎用コンピュータであってもよい。たとえば、コンピュータはIBM互換性パソコンまたはアマダAMNCのような機械類のインターフエイス/制御システムの一部であるコンピュータであってもよい。
【００５４】
サーバーモジュール32とデータベース30も通信ネットワークにつながれている。
サーバーモジュール32は、通信ネットワーク26とインターフエイスするのに適したハードウエアとソフトウエアをもつパソコン、ミニコンまたはミニフレームを含む。 サーバーモジュール32はまた、あとで詳細に期述する、この発明の色々な特徴を満たすソフトウエアやフアームウエアも含められる。さらに本発明の見地に沿って、サーバーモジュール32は顧客の注文に関連する設計製造情報を記憶するためのデータベース30をもちうる。データベース30は十分な記憶容量をもつ市販のデータベースを備えることにより、工場の顧客の設計製造情報やその他のデータ、表、及び/またはプログラムを記憶しておくことができる。たとえば、データベース30に4GBまたはそれ以上の記憶容量をもつスカジー（SCSI）メモリー・デイスクを含めることができる。データベース30に記憶された設計製造情報をアクセスして、通信ネットワーク26を通じて薄板金属設備38の色々な場所10,12,14...20に分配することができる。構造的問い合わせ言語(SQL)のような、色々なデータフオーマットがデータベース30にデータをアクセスまたは記憶させるために使用されることができる。さらに、データベース30に記憶されている情報は色々な種類の記憶媒体、たとえば磁気テープ、光学デイスクあるいはフロッピーデでバックアップし、記憶しておくことができる。サーバーモジュール32とデータベース30の通信ネットワーク26との連結は、工場38内の別々の区域または場所で（たとえば図1参照）、あるいは予め定められたステイションの中で（たとえば設計事務所内）、またはこれに近接した場所で行うことができる。図1の実施例では、データベース30がサーバーモジュール32の一部で通信ネットワーク26とサーバーモジュールを通してインタフエースしているように画かれているが、データベース30は勿論サーバーモジュール32と物理的に離れた場所に置かれていて、図２に示すように通信ネットワーク26とネットワークデータベースモジュール34を介してつなぐことができる。
【００５５】
本発明の望ましい実施例に沿った限定されない例として、サーバーモジュール32と各場所10,12,14...20は100-200MHzの、ペンテイアムまたは同等のマイクロプロセッサーを含む中央処理装置(CPU)と、少なくとも32MBの記憶容量と市販の800×600分解能をもつSVGAモニターのような高分解能デイスプレースクリーンをもつ、IBM互換機のようなパソコンを含む。サーバーモジュール32と場所10,12,14...20にはまた、情報のデイスプレイとのインターフエスと制御のための、ジョイステイックまたはマウスとサウンド・ブラスターまたはそれに代わる音響とゲームポートアダプターカードが含まれる。通信を支援するための実行システムのソフトウエアも備えられる。たとえば、サーバーモジュール32はマイクロソフトウィンドウズニューテクノロジー（NT）またはウインドウズ95実行システムソフトウエア（両方ともマイクロソフト社、レッドモンド、ワシントン州から入手できる）を備え、また各場所10,12,14...20はマイクロソフトウインドウズ95実行システムソフトウエアを含められる。さらにサーバーモジュール32と場所10,12,14...20は多数の言語（たとえば英語、日本語等）の支援に対応でき、またOLE2サーバーのようなオブジェクトリンクと埋め込み（OLE）サーバーの全面的な支援を具備できる。
【００５６】
色々なデータベース言語と管理システムはまたデータベースに記憶された情報を創りだしたり、保持したり見たりすることに用いられる。構造的問い合わせ言語（SQL）のようなデータベース言語をデータベース30のデータを確定したり、操作したり、制御したりするのに用いることができる。たとえば、SQLサーバー（マイクロソフト社から入手できる小売り製品）は本発明の実施に利用できる。さらに、この発明は開放データベース連結オープン・データベース・コネクテイビテイー（ODBC）互換ドライバーを備えることによって通信ネットワーク26を通してのデータベース30からの情報のアクセスを促進できる。ODBCに関するより詳しい情報はマイクロソフトオープン・データベース。コネクテイビテイー・ソフトウエア開発キットプログラマー用レフアランス・マニュエルでえられる。
【００５７】
図２は本発明の別の実施例に従って建設された進歩的な薄板金属製造設備のブロック線図である。図２の実施例では、データベース30とサーバーモジュール32は別々に設置されており、データベース30はネットワークデータベースモジュール34を介して通信ネットワーク26につながれている。上記のように、本発明はこの構成に限定されたものではなく、データベース30とサーバーモジュール32は一緒に設置でき（たとえば図1に示すように）、ネットワークデータベースモジュール34のデータベースにアクセスする機能をサーバーモジュールに取り入れることができる。図２はまた、薄板金属製造設備38内の色々な場所10,12,14...20に設置できるステイションモジュール36の例を示す。図示の目的で、図２には曲げステイション18に設置されたステイションモジュール36が例示されている。図２の例には示されていないが、同様のステーションモジュール36を設備38内の他の場所にも設置できる。
【００５８】
図２に示すように、各モジュール（サーバーモジュール32、ネットワークデータベースモジュール34及びステイションモジュール36）はネットワークインターフエイスカードまたはポート42を介して通信ネットワーク26につなぐことができる。ネットワークインターフエイスカード26はベンダー専用で、選ばれた通信ネットワークの形式にもとづいて選択できる。 各モジュール32、34、36は通信ネットワーク26とインターフエイスするためのネットワークソフトウエアまたはプログラムされた論理を含むことができる。 通信ネットワーク26はイーサネット(Ethernet)で、10ベース/T（ツイスト対）、10ベース/2（同軸）、または10ベース/5（厚膜ケーブル）のような多くのタイプの市販ケーブルから設備38の大きさと必要なケーブル長さにもとづいて選んだタイプのケーブルを用いたものであってもよい。
【００５９】
図２でサーバモジュール32はデイスプレイモニターまたはCRT44とキーボード、マウス及び/またはジョイステイックを含む入力/出力デバイスをもつパソコンを含めうる。ネットワークインターフエスカード42は備えられている拡張スロットまたはパソコン40のポートに挿入できる。さらに、パソコン40は100-200MHzの処理速度とペンテイアムまたはペンテイアム・プロ  マイクロプロセッサーを含むことができる。パソコン40はまた、たとえば32MBまたはそれ以上の主記憶装置と1.2GBまたはそれ以上のランダムアクセス記憶装置（RAM）を含むことができる。
デイスプレイ44は高解像度の表示画面、たとえば800×600の解像度をもつ市販のSVGAモニターを含むことができる。デイスプレイ44に表示された色々なグラフ一クスや情報を支援するため、パソコン40はまた、PCIグラフイックス・カードのような市販のグラフイックスクス・カードを含むことができる。さらに、コンピュータ40はサウンド・ブラスター、または互換の音声及びゲームポートアダプターカードを含み、入力/出力装置46はキーボード、ジョイステイックと/またはマウスを含むことができる。
【００６０】
この発明の色々な特徴を実行するために、サーバーモジュール32にはソフトウエアや色々なパッケージソフトが備えられている。たとえば、サーバーモジュール32はマイクロソフト  ウインドウズ  NT（ワーク  ステーション型）またはウインドウズ95を備えている。さらに、サーバーモジュールにこの発明特有の機能と特徴（たとえば図４を見よ）を持たせるために、サーバーモジュール32はソフトウエアまたはプログラムされた論理を備えたルーチンを含ませることができる。後でより詳しく論ずるように、これらのルーチンは、C++のような高レベルのプログラム言語とオブジェクト指向プログラミングによって作成できる。サーバーモジュール32はまた、顧客の仕様にもとづいた2-D及び3-D図面を入力及び/または作成するために、ベルムまたはアマダAP40またはAP60ソフトウエアのようなCADまたはCAD/CAMソフトウエアを含むか、インタフエースできるようになっている。この理由で、サーバーモジュールは製造設備38の設計事務所10におくことができる。データベース30からデータをアクセスするために、サーバーモジュール32は、マイクロソフトODBドライバーのようなODBCドライバーをもち、またSQLをデータ  アクセスの標準に用いることができる。OLE2サーバーのようなOLEサーバーを、データをリンクするために備えることができる。
【００６１】
図２の実施例では、データベース30はサーバーモジュール32から分離して備えられており、ネットワーク  データベース  モジュール34を経由して通信ネットワーク26につなげられている。先に述べたように、データベース30は工場38の規模と、データベースに記憶させる部品情報の量にもとづいて選ばれた、適当な記憶スペースをもったSCSIデイスク（たとえば1-4 GB）を含むことができる。ネットワーク  データベース  モジュール34は、ペンテイウム  マイクロプロセッサーを備えたIBM互換機のようなパソコン40と、通信ネットワーク26とインターフェースするためのネットワーク  インターフエース カード42を備えた拡張スロットを含むことができる。データベース30はデータ母線を介してパソコン40に連結でき、パソコン40は標準的なデイスプレイやデイスプレイ  モニターまたはCRTとキーボードのような入力/出力デバイス（図２には示されていない）も含む。
【００６２】
SQLに基づいたデータベース30へのアクセスを容易にするため、ネットワークデータベース  モジュール   34のパソコン40は、 マイクロソフトSQLサーバーやオラクルSQLサーバーのような、市販のSQLサーバーと合わせて設置することができる。OLE2サーバーのようなOLEサーバーをデータをリンクするために備えておくことができる。パソコン40もDOSやマイクロソフト・ウインドウズNT（サーバー  バージョン）のような、色々なソフトウエアを備えておくことができる。
図２の実施例は一つのステーションモジュール36の典型的な実装例を含んでいる。この実施例では、ステーションモジュール36は、曲げステーション18に装備されている。図２に示すように、ステーションモジュール36はサーバーモジュール32と同様のハードウエアを含んでいる。つまり、各ステーションモジュール（たとえば図1に示す他のステーション）はデイスプレイ  モニターまたはCRT44と、ジョイステイックまたはマウスを含む入力/出力デバイス46をもつコンピュータ48を備えている。ネットワーク・インターフエイス・カード42はコンピュータ40に備えられている拡張スロットまたはポートに差し込むことができる。前に論じたように、ステーションモジュール36のコンピュータは 独立型、またはパソコン、またはその場所に備えられた装置または機械類のインターフエイス ・デバイスの一部である汎用コンピュータであってもよい。たとえば、コンピュータ48は、100-200  MHzの動作速度とペンテイウムまたはペンテイウム  プロマイクロプロセッサーをもつIBM互換機のような自立型パソコンであってもよいし、コンピュータ48はアマダAMNCシステムのような機械類のインターフエイス/制御システムの一部、あるいはシステムに組み込まれたコンピュータであってもよい。コンピュータ48はまた、たとえば32MBまたはそれ以上の主記憶と、1.2GBまたはすれ以上のランダム・アクセス記憶（RAM）を保有することができる。デイスプレイ44は高解像度デイスプレイ画面、市販のたとえば解像度800×600をもつSVGAモニターを含みうる。デイスプレイ44にデイスプレイされる色々なグラフイックスや情報を支援するために、コンピュータ48はPCIグラフイックス・カードのような市販のグラフイックス・カードを備えることができる。さらに、コンピュータ48はサウンド・ブラスター、または互換できる音響及びゲームポート・アダプターとそれを支援する入力/出力デバイス46のジョイステイックまたはマウスを含むことができる。
【００６３】
この発明の色々な特徴を実行するために、ステイション・モジュール36はソフトウエアといろいろな市販ソフトウエアが配置されている。たとえば、ステーション・モジュール36はマイクロソフト・ウインドウズ95またはウインドウズNT（ワークステーション版）のような基本ソフトが備えられている。さらに、ステーション・モジュールに、この発明固有の機能と特徴をもたせるために（たとえば図５を見よ）、ステーション・モジュール36にソフトウエアまたはプログラム化論理装備ルチーンが備えられる。後でより詳しく論ずるように、これらのルチーンは高レベルのプログラム言語、たとえばC++、及びオブジェクト指向プログラミング技術を用いることによって開発できる。データをアクセスし、リンクするために、ステーション・モジュール36はマイクロシフトOBCDドライバーとOLE2サーバーのようなOLEサーバーが含まれている。サーバー・モジュール32と同様、ステーション・モジュールもSQLをデータベース30からデータをアクセスする基準に用いることができる。
【００６４】
曲げステーション18のステーション・モジュール36が自立型パソコンとして備えられている場合、曲げコードデータを作成するためと曲げ機械類25（たとえばCNCまたはNC制御プレス・ブレーキ）とインターフエースするためのソフトウエアを装備できる。図２の実施例では、コンピュータ36はパソコンとして装備され、標準RS-232-C配線インターフエースを通じて曲げ機械25とインターフエースするソフトウエアを配備しているように画かれている。このインターフエースはステーション・モジュール36が、RS-232-Cインターフエースを通じて曲げ機械25と通信し、曲げコードを送受できるために装備されている。このインターフエースの実行はベンダー用であり、曲げ機械25に用いられるデータ書式と命令セットに依存する。ステーション・モジュール36から曲げ機械25に送られるすべてのデータは、機械に決められている機械命令セットにもとづいてフオーマットしたものでなければならない。ステーション・モジュール36のコンピュータ48は、曲げコード生成のため、市販で入手できるCNCまたはNCソフトウエアを備えることにより、このような機械類のためにCNCまたはNCシステム（たとえばアマダAMNC）の組み込みコンピュータに通常備わっている機能をシミュレートできる。
【００６５】
図３はデータのサーバー・モジュール32、データベース30と薄板金属製造設備38の間のそれぞれのデータの流れを示す実施例の典型である。図で表すためと実施例におけるそれぞれのデータの流れの記述を容易にするため、図３ではサーバー・モジュール32とデータベース30（ネットワーク・データベース・モジュール34に統合されている）は、各々別々に通信ネットワーク26と直接に接続されていて、これらの構成要素間のデータの流れは通信ネットワークを通して行われる。勿論、この技術に熟練した人なら分かるように、これら構成要素間には多種多様のデータの流れ方式を用いることができる；また、データベース30がサーバー・モジュール32に直接接続されている場合、データと情報はサーバー・モジュールからデータベースに直接に、通信ネットワーク26を用いることなく伝達できる。さらに、記述を容易にするため、図３の通信ネットワーク26は簡略化されており、図には打ち抜きステーション16と曲げステーション18しか示されていない。しかしながら、場所10,12,14...20（工場内の他のあらゆる場所や区域も含めて）からのデータのやりとりの流れは、打ち抜きステーション16と曲げステーション18について示したのと同様の方法で行うことができる。
【００６６】
各顧客の注文に関連した設計製造情報は、編成してデータベース30に記憶することができる。最初に顧客から注文を受けると、基本的な製品と設計情報がサーバー・モジュール32に入力され、それからデータベース30に伝送され、記憶される。前に論じたように、サーバー・モジュール32は、キーボードを備えたパソコン等のような、データを入力する適当な手段を備えている。サーバー・モジュール32でパソコンが用いられるとき、工場職員によるデータの入力を容易にするため、メニュー方式画面を生成するソフトウエアを備えることができる。データ入力プログラムは、たとえばマイクロソフト・ウインドウズをベースとしたアプリケーションで、ヘルプ及び/またはメニュー画面をもつものであってよい。限定されない例として、サーバー・モジュール32に入力され/または作成されて、データベース30に転送されたデータは、図３に一般的に示してあるように、部品情報、曲げモデル、特徴抽出データ及び曲げ線情報を含むことができる。
【００６７】
部品情報は、たとえば部品または注文参照番号、顧客の名前、部品の簡単な説明、バッチの大きさまたは量及び引き渡し予定日を含むことができる。曲げモデルデータは、たとえば部品の全体的な寸法（たとえば幅、高さ、深さ）と材料のタイプ（たとえば鋼鉄、ステインレス鋼またはアルミニウム）、厚さ及び引っ張り強さのような部品材料の情報を含むことができる。さらに、特徴抽出データは手動による入力と/または自動的に生成することによって、部品の主要な特徴を識別し、データベースの類似部品の探索やその他の探索を容易にする。特徴抽出データはデータベース30の別のフアイルに格納するか、曲げモデルデータや各部品の仕事情報と一緒に格納することができる。特徴抽出データは、たとえば表面や面の数、曲げタイプの数（たとえば二面間の正の折り曲げ、または二面間の負の折り曲げ）、面の間の関係及び/または部品にある孔や他のタイプの開口の数を含むことができる。後でより詳しく論ずるように、このようなデータは特徴ベース部品マトリクスと/または逐次探索キー（たとえば下記の図６-１０を見よ）によって表現し、編成できる。最後に、曲げ線情報はデータベース30に格納するため、サーバー・モジュール32に入力できる。曲げ線情報は、たとえば部品の各折り曲げの曲げ角度、曲げ長さ、曲げの内半径（IR）、縮小量及び曲げ方向（たとえば前方または後方）を含む主要な曲げ線情報を含む。
【００６８】
通信ネットワーク26を通じてデータベース30へデータを送受信するため、各場所10,12,14...20は通信ネットワークに接続されているステーション・モジュール（前に述べたステーション・モジュール36のような）を含めることができる。図３には、打ち抜きステーション16と曲げステーション18は一般的にステーション・モジュールと合わせたブロック線図で示されている。前に論じたように、ステーション・モジュールは、たとえばソフトウエア、または制御論理と独立型パソコン、またはその場所に備えられた装置または機械類の一部である汎用コンピュータを含む。各顧客の注文に応じて、設計製造情報（部品情報、曲げ線情報および曲げモデル・データを含む）が、所定参照番号またはコードを入力することによってアクセスでき、検索できる。参照番号またはコードは手動（たとえばキーボードまたはデジタル入力パッドによって）またはバー・コードを、ステーション・モジュールに備えられているバー・コード読みとり装置またはスキャナーでスキャンすることによって入力できる。さらに、本発明の見地に沿って、以前の仕事情報はデータベース30から、工場内のどの場所10,12,14...20からでも、同様の部品探索を行うことによってアクセスし、検索できる。引き続く詳しい記述で論ずるように、類似部品の探索は、特徴抽出データ、またはデータベース30に記憶されている探索キーにもとづいて行うことができ、これによって同一または類似の部品に関する以前の仕事情報が検索され、将来の仕事の全体的な製造時間の短縮に利用できる。
【００６９】
データベース30から検索された製造情報は、作業場オペレータが曲げ計画を作成し、テストするのに用いられる。たとえば、曲げステーション18の曲げオペレータは、薄板金属部品に必要な工具や最適な曲げ手順を決めるために、データベース30から部品情報、曲げ線情報や曲げモデル・データをアクセスし、検索することができる。本発明の見地に沿って、ODBCドライバーを備えることにより、各ステーション・モジュールがデータベース30とインターフエースし、データベースに記憶されている情報を表示できるようにすることができる。さらに、サーバー・モジュール32またはデータベース30のネットワーク・データベース・モジュールは、データベースに記憶されているデータのアクセスと検索を容易にするために、SQLサーバーを含むことができる。最終曲げ計画に基づいて曲げコードがプログラムされると、曲げコードは曲げ手順とともに、図３に一般的に示すように通信ネットワーク30を通じて、曲げステーションのステーション・モジュール18からデータベース30に送られる。この情報は、当該の仕事に関連する他の設計製造情報とともに記憶される。
【００７０】
他の情報もデータベース30に記憶することができる。たとえば、部品の2-D及び/または3-D画像表現は曲げモデルデータとともに記憶することができる。この2-Dまたは3-D画像表現は設計ステーション10または他の場所でCAD/CAMシステムを用いて作成し、設計ステーション（あるいは他の適当な場所）のステーション・モジュールを介して通信ネットワーク26を通じ、データベース30に転送できる。あるいはまた、2-Dまたは3-D画像はサーバー・モジュール32で、後でより詳しく述べるように、適当なCAD/CAMシステムまたはモデル化ソフトウエアを用いて、一連の機能または演算を実行することによって作成できる。
【００７１】
図４と５を参照しながら、サーバー・モジュール32と各場所10,12,14...20においてプログラムされ実行される処理や演算について詳述する。図４と５はサーバー・モジュール32と薄板金属製造設備38内の各場所10,12,14...20で実行される基本論理の流れの流れ図である。図５は、たとえば曲げステーション18で実行される典型的な処理や操作に対するものであるが、設備38内の特定な場所で実行される操作によっては、これ以外の処理やステップも実行できることは理解できよう。以下に述べる処理や操作はソフトウエア、または多種類のプログラム作成言語と技法の一つを利用することによって実施できる。たとえば、本発明の見地に沿って、関連図面を参照しながら記述する下記の処理や操作は、C++のような高レベルのプログラム作成言語とオブジェクト指向プログラミング技法を用いることによって実施できる。さらに、限定されない例として、ウインドウズ・ベースアプリケーション用にマイクロソフト社が作成した、プログラム作成言語のバージョンであるヴイジュアルC++を利用することができる。
【００７２】
図４は本発明の見地に沿って、サーバー・モジュール  32が行う基本的な処理と操作の流れ図である。図４はサーバー・モジュール32がソフトウエアまたはプログラム化論理によって実行する処理と操作の基本論理フローである。サーバー・モジュール32は、オペレータまたはユーザーがサーバー・モジュールの色々な処理や操作の選択と実行を支援するためにツール・バーやヘルプ及び/またはメニュー画面をもつウインドウズ・ベース  アプリケーションを含むことができる。処理は薄板金属製造設備38で顧客の注文を受けたステップS.1から開始される。顧客の注文は通常部品が工場で製造するのに必要な製品と設計の情報を含む。この情報は、たとえば部品の幾何学的寸法、部品に必要な材料や他の設計情報も含む。顧客から受けた情報をもとに、サーバー・モジュール32は、ステップS.3に画かれているように、データベース30に記憶されている以前の仕事情報の探索を実行する。データベース30に記憶されている仕事情報は多様な探索基準にもとづいて探索できる。たとえば、情報は事前定義参照または仕事番号にもとづいて探索でき、あるいは類似部品の探索は部品のある設計特徴にもとづいて実行でき、これによって同一または類似の部品に関する以前の仕事情報が現在の仕事のために検索でき、利用できる。利用できる類似部品探索のさらに詳しい記述は、図６-１０を参照しながら以下に記す。
【００７３】
ステップS.5では、データベースの検索結果が解析され、現在の顧客の注文が新しい部品か、以前の仕事に類似の部品か、あるいは以前の仕事の繰り返しかが決定される。同一の照合が見いだされる（たとえば同じ部品または参照番号が見いだされる）と、顧客の現在の注文は工場で行った以前の仕事の完全な繰り返しになり、仕事情報に対するこれ以上の修正は不必要で、以前の仕事情報をデータベース30からアクセスしてステップS.11に示すように現在の顧客の注文の遂行に利用できる。データベースの探索は以前の仕事の部品または参照番号及び/またはフアイル名を与え、それによってサーバー・モジュール32またはどのステーション・モジュールにいるオペレータでもデータベースから仕事情報をアクセスすることができる。部品または参照番号しかえられない場合、変換テーブルを備えることによって、オペレータが部品参照または仕事番号を入力することによって以前の仕事情報のフアイル名を決定し、アクセスできる。従って、たとえばサーバー・モジュール32にいるオペレータは、仕事情報と2-Dと3-Dモデル化情報をデータベース30からアクセスすることによって部品の幾何学を解析し、繰り返しの注文と類似であることを確認することができる。注文が繰り返しの注文であることが確認されると、曲げステーション18のステーション・モジュールにいる曲げオペレータは、さらに以前の仕事情報をアクセスし、曲げコードのデータと工具段取り情報を含む製造情報を曲げと部品の製作に利用することができる。かかる記憶された専門的知識を利用することによって、このようにして、繰り返しの注文をより効率的に、以前に入力され開発された仕事情報を必要とせずに製造することを可能にする。
【００７４】
しかしステップS.5で、もし現在の顧客の注文が以前の仕事と類似か、以前の仕事と同じであるが、たとえば仕事または参照番号またはバッチの大きさ等の修正が必要と決定されれば、ステップS.7での探索で捜し出した以前の仕事情報データはデータベース30から検索され、サーバー・モジュール32にいるオペレータによって編集し、修正される。編集機能を備えることによって、以前の仕事データを編集し、修正して新しい仕事データを作成し、現在の顧客の注文のためにデータベース30に格納できる。必要とする編集の量は、以前の仕事と現在の仕事間の類似性の程度による。編集の量は、参照または仕事番号またはバッチの大きさの単なる修正から/または、部品の寸法や定められた曲げ手順の編集のような、より広範囲な修正を含むものにわたる。以前の仕事情報の編集が終わると、修正された仕事情報はステップS.9でデータベース30に格納される。修正された仕事情報は新しい参照または仕事番号で格納できる。さらに、色々なデータベース管理機能（コーピー、削除、保管、再命名等）を備えることによって、特別なコマンドの入力でデータベース30の以前の仕事情報の保持、または以前の仕事情報の消去または上書きができる。
【００７５】
現在の仕事に適合する類似または同一のものが無く、従って現在の顧客の注文は新しい仕事に関係することが決定されると、論理フローは図４に示すステップS.15に進む。この場合、現在の仕事は新しい仕事に関するものになるので、設計製造情報を独立に作成し、入力しなければならない。サーバー・モジュール32からメニュー及び/またはヘルプ画面を提供することによって、オペレータが必要な仕事情報すべてを入力するのを支援することができる。本発明の見地に沿って、サーバー・モジュール32のオペレータは、最初に新しい仕事の基本的な部品情報を入力することによって新しいフアイルを作成できる。部品情報は、たとえば参照または仕事番号、顧客の名前、部品の簡単な記述、仕事に必要なバッチの大きさまたは量及び予定引き渡し年月日を含む。特徴抽出データまたは探索キーもステップS.15で入力できるし、また、以下に記すように、このデータを自動的に作成するか、曲げモデルデータの作成と同時に抽出することができる。他のデータや情報もステップS.15で入力するか、部品の各曲げ線の曲げ角度、半径や長さを含む曲げ線情報のような曲げモデルデータの入力後か入力中に入力できる。ステップS.15に引き続き、論理フローは図４に示すように、オペレータによって曲げモデルデータがサーバー・モジュール32で開発され、入力されるように進む。
【００７６】
曲げモデルの開発と入力は、顧客から提供された原図や情報に依存する。顧客の注文は、たとえば製造される部品の2-Dの一方向平面図及び/または部品の2-D、三方向図（たとえば上面、前面、側面図）を含むかも知れない。たまには顧客は、部品材の厚さが図に示されている、またはいない部品の3-Dワイヤーフレームを提供することもある。本発明の見地に沿って、曲げモデルデータは、製造される部品の展開（2-D平面表示）と折りたたみ(3-D表示)情報を双方とも含む。従って顧客が2-D平面図しか提供しない場合、たとえば2-D図面に対して折りたたみアルゴリズムまたは処理を適用することによって3-D図面を作成する必要がある。これにひきかえ、部品の3-D図面が提供された場合、3-D図面に対して展開アルゴリズムまたはプロセスを適用することによって2-D平面図を作成しなければならない。本発明の別の見地に沿って、曲げモデルに保管されている2-D及び3-Dモデルは、薄板材料厚さなし（つまり厚さなし）で作成し表現できる。これが可能なのはすべての薄板金属部品に特有の対称性による。厚さなしの2-Dと3-D図面の提供と表現は、設計プログラマー、曲げオペレータや他のユーザがより容易に解釈され理解される部品のモデリングとシミュレーションの図を与える。厚さ情報を省くことはまた、サーバー・モジュールやステーション・モジュールで、文中に記述の本発明の色々な特徴を実行し達成するのに要する処理時間を短縮し、改善する。このような特徴のより詳細な記述や、本発明で利用することができる折りたたみと展開アルゴりズムについては、以下に付図を参照しながら記述する。
【００７７】
図４は曲げモデルを開発するときに行われる一般的な処理と操作を示す。受理した、または顧客の注文にもとづいて開発され、曲げモデルデータを作成するために入力できる色々なタイプの図面は、一般的にステップS.19,S.23,S.27とS.31に示されている。 ツール・アイコン・バーとメニュー及び/またはヘルプ画面を、サーバー・モジュール32によって、これらの各ステップを選択し実施するオペレータを支援するために提供できる。これらの図面から曲げモデルのための部品の2-Dと3-Dモデルを作成する処理は、最初に提供された図面のタイプに依存する。これらの図面は、サーバー・モジュール32で手動で入力または作成するか、テープまたはデイスクからダウンロードできる。サーバー・モジュール32は、たとえば、設計事務所10にあるCAD/CAMシステムとインターフエイスするか、またはサーバー・モジュール32が独立型CAD/CAMシステムをもつことができる。さらに、2-Dと3-D図面は、DXFまたはIGESフアイルとして保管され、サーバー・モジュール32に取り入れられる。
【００７８】
一方向平面図が提供された場合は、曲げモデルを作成する処理は、図４に示すようにステップS.19から始められる。ステップS.19で、受理または作成された2-D平面図はサーバー・モジュール32に入力される。部品の全体的な寸法（幅、高さ、深さ）のような他の曲げモデルデータ及び部品材料情報もステップS.19で入力できる。その後、折りたたみアルゴリズムまたは処理を用いて、ステップS.21に一般的に示されているように、元の2-D一方向図面にもとづいて3-Dモデル（材料の厚さのない）を作成することができる。2-D平面図から3-Dモデルを作成するのに行われる処理や操作の例は、図１１-１８を参照しながら後で述べる。
【００７９】
部品の3-Dワイヤーフレーム図（材料厚さの無い）が受理または作成された場合、図の情報はステップS.27で入力される。さらに、他の曲げモデルデータ、たとえば部品の全体的な寸法（幅、高さ、深さ）及び部品材料情報もステップS.27で入力できる。この後に、ステップS.27に示すように、部品の2-Dモデルを作成するために、サーバー・モジュール32で展開のアルゴリズムまたは処理が実行される。2-Dモデルを3-D図面（厚さのない）から作成するために行われる処理と操作の例は、たとえば図１９を参照しながら後で述べる。
【００８０】
部品の2-Dと3-Dモデル表示は、その部品のための曲げモデルの一部として格納される。さらに、前に注記したように、2-Dと3-Dモデルの作成と格納の間に、他の曲げモデルデータ（部品材料情報やその他の製造情報のような）も入力し、曲げモデルデータとともにデータベース30に格納できる。曲げモデルデータを編成し、格納するために実施できる、いろいろな機能やデータ構造配列についてはあとでより詳しく記述する（たとえば図２６と２７を見よ）。
【００８１】
図４に示すように、簡単な3-D図面（材料厚さなしの）がもともと作成または受理されていない場合は、最終的な2-Dモデルを作成するのに必要な展開アルゴリズムまたは処理を行う前に、部品の3-Dモデル（厚さなし）を作成するための付加的な処理が必要となる。ステップS.23、S.25、S.31とS.33は、ステップS.29で展開アルゴリズムを実行し、2-Dモデルを作成する前に、サーバー・モジュール32で一般に実施される付加的な処理と操作を示す。
【００８２】
たとえば、部品の2-D、三方向図面（三面図）がはじめに提供または作成されている場合、ステップS.23で図面はサーバー・モジュール32に入力または取り入れることができる。さらに部品の全体的な寸法（幅、高さ、深さ）のような他の曲げモデルデータや部品材料情報もS.23で入力できる。引き続きステップS.25では、入力された2-D三方向図面にもとづいて、部品の簡単な3-D平面図が作成できる。作成された3-D図面は、図４に示すように、ステップS.29で2-Dモデルを作成するのに用いられる。3-Dモデルを2-D三方向図面から作成する処理と操作の例は、あとでたとえば図２０を参照しながら述べる。
【００８３】
しかしながら、もし材料厚さが入っている3-D図面がもともと受理または作成されている場合、展開アルゴリズムを適用する前に、さらに先の処理のため図面情報をステップS.31で入力する事ができる。他の曲げモデルデータ、部品の全体的な寸法（幅、高さ、深さ）と部品材料情報もステップS.31で入力できる。そのあとステップS.33で、3-D図面にある厚さを削除するための厚さ削除手順を行うことができる。本発明の見地に沿って、サーバー・モジュール32は、オペレータまたはユーザーが厚さ削除手順を実行するとき、図面に厚さを示し、どの表面（外側か内側か）を保存するかを示すように促すことがある。本発明で利用できる厚さ削除手順については、たとえば図２４（ａ）と２４（ｂ）を参照しながら下記に述べる。ステップS.33で3-D図面の厚さが削除された後、論理の流れはステップS.29に進み、そこでは最終的2-Dモデルを作成するために、改訂された厚さの無い3-Dモデルを利用して適当な展開アルゴリズムまたは処理が施される。3-D図面から2-Dモデル作成するための展開処理と色々な処理や操作は、たとえば図１９を参照しながら下記に述べる。
【００８４】
図４に示すように、すべての重要な情報が作成され、入力された後、顧客の注文に関連する部品情報、曲げモデル情報及びその他のデータは、ステップS.35でサーバー・モジュール32からデータベース30に移されて格納される。データベース30に格納されたデータは、データベース探索を行うときに利用できる特徴抽出または探索データも含む。下記に述べるように、特徴抽出または探索データは、各仕事に関連した部品の基本的または主要な特徴を指示するデータも含まれ、これによって仕事情報や格納されている同一または類似部品に関する専門的知識の探索が実施できる。サーバー・モジュール32に入力されたデータと情報は、たとえば図３に示すように、直接データベース30に、または通信ネットワーク26を介して転送することができる。上述のように、曲げモデルデータを作成するときに、色々な図面に対して実施できる各種の処理や操作についての詳しい記述は、下記に付図を参照しながら記す。
【００８５】
図５は薄板製造設備38の場所10,12,14...20に設けられ、各ステーション・モジュールで実施される基本的な処理や操作の流れ図を示す。例証のため、図５は、たとえば曲げステーション18に置かれたステーション・モジュールで実施される基本的な処理や操作の基本論理の流れの例を示す。本発明の教示にもとづく技術に熟練した者には理解できるように、図５に示す論理の流れは、各場所で実施される操作や処理の性格により、各ステーション・モジュールで修正できることは勿論である。さらに、サーバー・モジュール32と同様、下記に述べるステーション・モジュールでの処理や操作にはソフトウエアまたはプログラム化論理を装備できる。加うるに、ステーション・モジュールは、オペレータまたはユーザーによる色々な処理や操作の選択と実施を容易にするために、ツール・バー・アイコンまたはヘルプ及び/またはメニュー画面をもつウインドウズ・ベース・アプリケーションを含むことができる。このようなヘルプ及び/またはメニュー画面は、ステーション・モジュールにおいてデータの入力または転送を容易にするためにも設けることができる。
【００８６】
図５に示すように、ステップS.51でステーション・モジュールを初期設定した後、オペレータはステップS.53で一つまたは一つ以上のデータベース探索基準またはキー項目を入力することができる。探索基準は、データベース30に格納されている以前の仕事情報、または新しいまたは現在の仕事に関する仕事情報を捜し出すために入力できる。オペレータは、たとえばデータベース30から特定の仕事情報を検索するために、予め定められた番号またはコードを入力できる。たとえば、本発明の見地に沿って、バーコード をルーチングシートに付すか、せん孔された材料につけて、ステーション・モジュールでバーコード読みとり装置でスキャンすることによって情報をアクセスすることができる。あるいは、参照コードまたは番号を、ステーション・モジュールでキーボードまたはデイジタル入力パッドを介して手動で入力できる。変換テーブルを備えることによって、部品参照または仕事番号のオペレータによる入力によって、以前の仕事情報を定めることもできる。さらに、探索基準またはキーを入力することによって、以前に格納した仕事情報の類似部品探索を行うことも予想される。このような探索は、部品の色々な設計特性または特徴抽出データにもとづいて行うことができる。本発明の見地に沿って実行できる類似部品探索の説明は、下記に図６-１０を参照しながら記す。
【００８７】
探索基準をステップS.53で入力した後、ステーション・モジュールはステップS.55で、通信ネットワーク26とネットワーク・データベース・モジュール34を介してデータベース30の探索を実行できる。探索の結果はステーション・モジュールに戻され、ステップS.57でオペレータまたはユーザーが新しい仕事または類似の以前の仕事に関する情報を要請したのか、または要請が以前の仕事の完全な繰り返しに関するものなのかを決めるために解析される。
【００８８】
同一のものが見いだされる（たとえば同じ部品または参照番号が突きとめられる）と、以前の仕事の繰り返しが決定され、仕事に関する格納されている設計と製造情報がデータベース30からステーション・モジュールに転送され、ステップS.59に一般的に示しているように、オペレータが見られるように表示される。ステーション・モジュールは一つまたは一つ以上のメニュー表示画面または登録簿をもち、オペレータがデータベース30から検索された色々な情報を選択し、表示できるようになっている。オペレータは表示された情報をレビューし、ステップS.61における3-D曲げシミュレーションのような、色々なシミュレーションを走らせて、その仕事の曲げ手順の色々な段階を観察し、部品の幾何学を理解することができる。オペレータはまた、必要工具や仕事情報に記録されている他の特別な命令やメッセージのような他の情報をレビューすることもできる。仕事情報の確認が終わると、オペレータは曲げ、または他の必要な機械類を構成し（組立）、機械を操作して指定された薄板金属部品を製作することができる。データベース30から検索された仕事情報は、たとえば曲げステーション18の機械類を制御する曲げコードを含む最終曲げ計画データを含む。機械類の構成と実際の操作は、このようにして図５のステップS.63に一般的に示してあるように、オペレータによって遂行される。
【００８９】
もし同一または類似の仕事情報が捜し出されず、情報が新しい仕事（つまりサーバー・モジュール32には予備的な仕事情報のみ入力され、完全な仕事情報が作成されていない）に関するものであることが決定した場合、部分的な部品情報と曲げモデルデータはデータベース30から引き出されてステーション・モジュールに送られ、ステップS.77でオペレータによって観察される。要請した情報は新しい仕事に関するものなので、オペレータは必要な工具と曲げ手順を含む曲げ計画を作成し、入力する必要がある。下記により詳しくのべるように、曲げオペレータによる曲げ計画の作成を容易にするため、ステーション・モジュールにグラフイカル・ユーザー・インターフエース（GUI）や他の機能を備えることができる。GUIは、たとえば工具の選択、部品と工具間の潜在的な不一致の自動点検、及び提案された曲げ手順の各中間段階のシミュレーションを表示することによってオペレータが曲げ計画を作成するのを支援するために設けることができる。サーバー・モジュールで曲げ計画を作成し、入力したオペレータは、ステップS.80で曲げコード（曲げ機械で曲げ手順を実行するためのCNCまたはNCコード）を生成するために曲げ手順をプログラムする。曲げコードは直接サーバー・モジュールで入力するか、曲げ機械類のＣＮＣまたはNC制御装置とインターフエースしてサーバー・モジュールに取り入れることができる。しかる後、オペレータはステップS.81で、曲げ作業ステーションにおいてセットアップし、曲げ計画をテストすることができる。曲げ計画に必要なすべてのテストと必要な修正が完了すると、ステップS.83で最終的な曲げデータをデータベース30に入力し格納する。最終的な曲げデータは、曲げプログラムとともに、曲げ手順と工具構成情報を含む。この情報は、たとえば曲げステーション18のステーション・モジュールからデータベース30に送られ、新しい仕事に関する他の設計製造情報とともに格納される。
【００９０】
図５のステップS.57で、情報が以前の仕事の類似部品または同じ部品に関係しているが、たとえば異なる参照あるいは仕事番号またはバッチ量等をもつことが決定されれば、論理の流れはステップS.65に進む。ステップS.65では、以前の仕事情報がデータベース30から検索され、曲げステーション18で表示される。曲げオペレータまたはユーザーはデータを見て、類似部品に必要なデータの変更が何かを決める。この場合もステーション・モジュールは一連のメニュー表示画面または登録簿（ディレクトリ）を備えて、オペレータが、表示する情報と、情報をどのように表示または修正するかの選択ができるようにされている。たとえば、ステップS.69では、オペレータの類似部品の曲げ計画の作成を容易にするため、検索された情報にもとづいた3-D曲げシミュレーションを備えることができる。以前の仕事情報をレビューした後、オペレータはステップS.70で、曲げプログラムとともに、工具と曲げ情報を修正する。部品の寸法、参照番号やバッチ量のような他の仕事情報もステップS.70で修正し、編集することができる。これが終わると、ステップS.71で実際の工具セットアップとテストが、オペレータによって作業場において、修正された曲げ計画をテストするために行われる。テストと曲げ計画をさらに修正することが完了すれば、オペレータはステップS.73で最終的な曲げデータを入力し、それに新しい参照番号または仕事番号をつけてデータベース30に格納する。上記のように、以前の仕事情報もデータベース30に、他の格納された仕事フアイルとともに保持できる。さらに、色々なデータベース管理機能を、データベースに格納されているフアイルを格納、消去、再命名等するために備えることができる。
【００９１】
次に図６-１０を参照しながら、本発明の教えるところに従って実行できる類似部品探索機能の例を詳しく述べる。本発明の見地に沿って、特徴ベース形態類似性探索アルゴリズムを利用する類似部品探索手続きを、データベース30から以前の仕事情報を探索し、検索するのに備えることができる。類似部品探索は製作される部品に関する設計特徴及び/または製造情報にもとづいた同一及び/または類似部品の探索を含むことがある。また類似部品探索は、たとえばサーバー・モジュール32及び/または工場38内の色々なステーション・モジュールにあるソフトウエアまたはプログラム化論理の使用によっても実施できる。類似部品探索はサーバー・モジュール32または薄板金属曲げ工場38内の場所10,12,14...20のいずれかで実行できる。Ｃ++またはマイクロソフト社のビジュアルＣ++プログラム言語のような、高レベルのプログラム言語とオブジェクト指向プログラム技法が類似部品探索の色々な処理や操作を実施するのに利用することができる。
【００９２】
図６と７は利用できる類似部品探索アルゴリズムまたは処理の論理の流れを示す。図６に示すように、重要な部品モデルデータフアイルはステップS.100でアクセスできる。部品モデルには、たとえば設計事務所10に置かれたCADシステムで作成された曲げモデルデータ及び/またはサーバー・モジュール32で作成され、入力されたデータが含まれる。部品モデルには、たとえば部品の色々な表面または面及び曲げ線の向き、幾何学的関係及び相対位置を表す部品形態データ（部品トポロジーデータ）が含まれる。部品モデルデータが検索され、または曲げモデルデータが手動で入力された後、ステップS.102で、当該部品の曲げモデル及び/または部品形態データにもとづいた特徴抽出データを自動的に導出するための特徴抽出操作を行うことができる。
【００９３】
本発明の見地に沿って、特徴抽出データは、薄板金属部品の色々な特徴を解析することによって導出できる。たとえば、部品の色々な面の解析によって、隣り合わせの面が開放または接触コーナーをもつかどうかを決めることができる。平行曲げ、直列曲げ、共線曲げまた対向曲げのような他の特徴も、各部品の明確かつ独特な特徴を決定し、抽出するために解析することができる。
【００９４】
表1は類似部品探索を行うときに解析される色々な曲げと面の特徴を示す。特徴抽出操作に含めなければならない抽出特徴は、正の曲げ、負の曲げ特徴とともに接触コーナー、開放コーナー特徴である。さらに特徴抽出操作は、少なくとも平行曲げ、直列曲げ、共線曲げ、異相共線曲げ及び厚さオフセット曲げの特徴解析を含まなければならない。
【００９５】
ステップS.102で行った特徴抽出操作は、各特徴の曲げモデルデータと形態（トポロジー）の解析、形態の修正、今後の解析のための形態にもとづく特徴ベース行列（特徴に基づく行列）の作成からなる一連の操作を含むこともある。例証のため、図８（ａ）―９（ｄ）に接触コーナーをもつ4折り曲げ箱部品と開放コーナーをもつ４折り曲げ箱部品に対する特徴抽出操作を示す。
【００９６】
【表１】
0003884195.tif 000002
例証のため、図８（ａ）-９（ｄ）には隣接面のコーナー関係にもとづく特徴抽出が示されている。図８（ａ）に示す五つの面（1-5）をもつ閉じた4折り曲げ箱や、図８（ｂ）に示す五つの面（1-5）をもつ開いた4折り曲げ箱については、いずれの部品を表すにも、図８（ｃ）に示す同じ簡単な面形態が提供される。この形態は部品または曲げモデルデータとともに格納し、提供することができる。しかしながら、図８（ｃ）の単純な面形態（面トポロジー）は、部品の面(1-5)の間の関係の基本的な情報しか与えず、隣接する面間のコーナーの関係や曲げの種類のような部品の色々な特徴の情報は与えない。従って、特徴抽出操作時に、部品または曲げモデルデータとともに格納されている関連面形態をを解析することにより、基本的な面形態が部品の色々な特徴についての付加的な情報を含むように修正することができる。
【００９７】
たとえば、図８（ａ）の閉じた4折り曲げ箱の部品または曲げモデルデータを調べることにより、隣接面間のコーナーが解析でき、図９（ａ）に示されている修正された面形態が作成でき、これによって各面間の接触コーナー状況を示すことができる。同様に、図９（ａ）に示されている開いた4折り曲げ箱の部品または曲げモデルデータを調べることにより、図９（ｂ）に示す修正された面形態を作成し、それによって部品の色々な隣接する面の間の開放コーナー関係を示すことができる。図９（ａ）と９（ｂ）に示すように、面形態に面のコーナーの関係（たとえば接触または開放）を示す特別の連結線を加えることができる。他のデータも他の特徴（たとえば存在する曲げの形式）を示すため、及び特徴ベース面形態を作成するために加えることができる。特徴ベース情報が含められるように形態を修正した後、抽出情報をより簡単に解析し、比較するために行列を作成することができる。たとえば、図９（ａ）の特徴ベース面幾何学にもとづいて、図９（ｃ）に示す行列を作成し、これによって図８（ａ）の閉じた4折り曲げ箱の色々な特徴を示すことができる。同様に、開いた4折り曲げ箱に対しては、たとえば図９（ｂ）に示す特徴ベース面形態にもとづいて、図９（ｄ）に示す行列を作成できる。他の特徴抽出データ、たとえば部品の曲げ特徴（たとえば90゜正の曲げ角度または90゜負の曲げ角度等）も行列の中に示すことができる。
【００９８】
上記のように、ステップS.102の特徴抽出操作は、曲げモデルデータと形態を解析することによって、部品に色々な特徴が存在するかどうかを決めるために実施できる。本発明の見地に沿って、特徴抽出操作は部品に提供されている曲げモデルと形態データについて行うことができる。このデータは、面のデータ、曲げ線データ（たとえば曲げ線長さと位置等）、面―曲げ線関係データ、曲げ角度データ及び特別の特徴データ（たとえばZ―曲げや縁取り等）を含む、薄板金属部品に関するすべての重要な幾何学と位置のデータ（たとえば2-D空間（X,Y）及び/または3-D空間（X.Y.Z）における）を含む。線、曲げ線や他の構成要素はエンドポイント（端点）や/またはベクトルで定義することができる。たとえば各2D線は一組の2Dエンドポイント（たとえばX1,Y1とX2,Y2）、各3D線は一組の3Dエンドポイント（たとえばX1,Y1,Z1,とX2,Y2,Z2）で指定することができる。曲げ線は2Dまたは3D空間における場所とともに曲げ線の方向を示すベクトルで表すことができる。さらに、2Dの弧は2D空間データ（たとえば中心X、中心Y、半径、開始角度、終了角度）、3Dの弧は3D空間データ（たとえば中心X、中心Y、中心Z、ビユー行列、半径、角度開始、角度終了）で指定することができる。部品形態データも、部品の色々な面や曲げ線の場所やこれらの間の幾何学的関係を示すために提供することができる。各面は線と/または弧の集合または連結データリストで定義することができる。
【００９９】
部品の特徴を抽出するため、曲げモデルと形態データの特徴抽出操作を行い、解析することによって、ある特徴が部品に存在するかどうかを定めることができる。このプロセスは、抽出する各特徴間の色々な特色や関係にもとづく、曲げモデルと形態データの解析を含むこともできる。各特徴の特色と関係を知るための曲げモデルと形態データの解析によって、ある特徴（たとえば面間の接触コーナー、開放コーナー特性、または平行または直列曲げ特性）の存在が検出できる。異なるプロセスを、各特徴の特定の特性と関係を特徴抽出操作で検出するために備えることもできる。解析される各特徴間の特性と関係の類似性にもとづいて、部品に一つ以上の特徴が存在するかどうかをチェックするために幾つかのプロセスを組み合わせるか作成することもできる。
【０１００】
限定されない例として、ステップS.102における特徴抽出操作の際に、コーナーの特徴、たとえば同じ曲げ方向をもつ二つ面の接触コーナー特徴（表1のTouchCnr特徴）を抽出し、検出するために行うことができるプロセスについて述べる。下記のプロセスは、他の特徴の検出、たとえば逆曲げ方向をもつ二つの面の接触コーナー特徴（表1のtouchCnr特徴）または同じまたは逆曲げ方向を持つ二つの面の開放コーナー特徴（表1のOpenCnrとopenCnr特徴）に用いることもできる。プロセスを修正することによって、他の特徴も検出できる（たとえば平行曲げ、直列曲げ等）。さらに、面の可能な各組み合わせに関するデータを、抽出される各特徴の特性と関係を知るために解析することができる。
【０１０１】
たとえば、接触コーナーの特徴をもつTouchCnrの場合、検出する特徴または関係は：共通の面を持つ二つの面；同じ曲げ線方向；同じ頂点を（または頂点間の距離が事前に定めた範囲内にある頂点）をもつ曲げ線を含む。接触コーナーの特徴をもつtouchCnrの場合、同様の特性または関係を検出しなければならない；ただ同じ方向の曲げ線をもつ面ではなく、面は逆方向の曲げ線をもっていなければならない（たとえば表1をみよ）。開放コーナー特徴OpenCnrとopenCnrも同様に検出できるが、各特徴に接触コーナー関係の代わりに、面間に開放コーナーが存在する（たとえば面の曲げ線が事前設定の範囲の距離より大きく隔たっている）ことと、同じまたは逆の曲げ線方向（たとえば表1と表中のOpenCnrとopenCnrの定義をみよ）をもつ曲げ線を検出し、解析しなければならない。
【０１０２】
接触コーナー特徴（たとえば表1のTouchCnr特徴）を検出するためには、先ずある二つの面を解析し、二つの面が共通の面に接続しているかを決定する。これは各面の曲げ線データと各曲げ線の曲げ線―面関係データを探索して、共通面が存在するかどうかを決定することによって検出できる。もし二つの面が共通の面に接続していれば、各面の曲げ線方向を解析して同じ曲げ線方向（または、たとえばtouchCnr特徴を検出する場合は逆の曲げ線方向）をもつかを見る。これは、たとえば各面の曲げ線方向を示すベクトルデータを解析する事によって決められる。
【０１０３】
二つの面が共通の面をもち、曲げモデルと形態データにもとづいて同じ曲げ線方向をもつことが決定されると、データを検査することによって曲げ線が平行かどうかが検出される。色々な方法を用いて、曲げモデルと形態データにもとづいて曲げ線が平行かどうかを検出することができる。たとえば、平行曲げ線の検出は、曲げ線方向を定めるベクトルの外積をとることによって決められる。もしベクトルの外積がゼロ（または近似的にゼロ）であれば、曲げ線は平行であると決定される。もしベクトルの外積がゼロでなければ（または近似的にゼロでない）、二つの面の曲げ線は平行でない。
【０１０４】
二つの面が共通の面をもち、曲げ線方向が同じで曲げ線は平行ではないことが決まった後、面の間のコーナーの関係（たとえば接触か開放か）を決めるために、曲げモデルデータが解析される。二つの面のコーナー関係は、曲げモデルデータから、面の曲げ線が共通の頂点をもつかどうかを検出することによって決められる。曲げ線が共通の頂点をもっていれば、二つの面は同じ曲げ線方向の接触コーナー関係（表1のTouchCnr特徴）をもつ。曲げ線は共通の頂点をもっているが、二つの面の曲げ線方向が異なることが決まれば、二つの面は逆方向の接触コーナー関係（たとえば表1のtouchCnr特徴）をもつと決められる。
【０１０５】
二つの面が共通の頂点をもっていない場合でも、頂点間の距離が予め定められた範囲内であれば、二つの面は接触コーナー関係をもつと決定できる。しばしば部品の隣接する面の間に、たとえばパンチ工具を通すためのすき間として最小限のスペースが設けられることがある。このスペースは、通常フランジの高さのところでの工具の幅で決められる。例をあげれば、二つの面の曲げ線の頂点間の距離が0-5mm以内であれば、接触コーナー特徴の存在が決定できる。もし二つの面のコーナー間のスペースが、事前に定められた範囲より大きければ、開放コーナー特徴の存在が決定できる（たとえば表1のOpenCnrまたはopenCnr特徴）。
【０１０６】
上記のプロセスは部品の面のあらゆる組み合わせについて、各面のコーナー特徴を決めるために実施することができる。部品の面や曲げ線に関連する他の特徴も、同じように部品幾何学と形態データの解析によって行うことができる。ステップS.102における特徴抽出操作を実行するための典型的なコードを付録Aに示す。このコードはC++プログラム言語で書かれており、表1に記してあるような特徴を抽出検出するための色々なプロセスを含む。付録Aのコードには、使用されている論理やアルゴリズムの解析を容易にするためのコメントがついている。またこのコード例では、色々な特徴の理解を助けるために、表1と同じ特徴の用語が使われている。
【０１０７】
部品の色々な特徴が検出されると、部品の基本的な形態は修正され、抽出された特徴が含められる。特徴ベース形態を提供することは有用かもしれないが、このような形態をお互いに比較することは容易でない。その代わりに、本応用の発明者達は行列の形で提供された特徴抽出情報を比較する方が、より有効で容易であることを発見した。従って、本発明の一つの特徴として、特徴抽出操作の際に、検出された特徴にもとづいた特徴ベース部品行列（図９（ｃ）と９（ｄ）に示す代表的な行列のような）が作成される。作成された部品の特徴ベース行列は、他の所定の、格納された行列と比較することによって、どのような基本的な形や特徴が部品に含まれているかを決定する。
【０１０８】
特徴ベース行列は、部品の色々な特徴を検出し、抽出した後に、部品毎に作成され、格納される。図９（ｃ）と９（ｄ）に示すように、行列は対称的な2次元行列で部品の面の数に等しい次数をもつ。行列は部品のすべての検出された特徴情報を含み、各面の間の色々な特徴が行列の各場所に提供されている。特徴ベース行列は、一時的にサーバーまたはステーションモジュールの記憶装置に格納し、類似部品探索を実行するときにのみ使用し、所定の行列と比較することができる。あるいは、特徴ベース部品行列を永久的に他の仕事情報とともにデータベース30に格納し、工場内のどの場所でもアクセスできるようにすることができる。
【０１０９】
図６に戻ると、特徴抽出操作を行った後、引き出した特徴抽出データ行列を、特徴形態ライブラリに備えられている所定の特徴抽出データ行列と比較することができる。特徴形態ライブラリは、別のデータフアイルとして、データベース30のようなデータベース、またはサーバー・モジュールかステーション・モジュールに格納しておくことができる。特徴ライブラリは、基本的または基礎的な部品の形状（たとえば4折り曲げ箱、橋梁等）に対応するまたは定義する特徴抽出データを含む所定の行列よりなる。各所定特徴ベース行列は、特徴ベース部品行列とともに、ASCIIまたはテキストフアイルとして格納できる。ステップS.104のおける比較は、ステップS.106に図示されているように、薄板金属部品に存在する基本的または基礎的な形状/特徴を決めるために行われる。格納されたルックアップテーブルを、どの基礎的な形状が各所定特徴行列に対応するかを示すためにを備えておくことができる。一致するものが見いだされると、ステップS.106でどの基礎的形状が存在するかを決めるために、ルックアップテーブルがアクセスされる。事前定義ライブラリに存在する一致する行列は、特徴ベース部品行列と同じ次数であるか（この場合は部品はただ一つの基礎的形状を含み、精確に対応することが決定される）、または部品行列のサブ行列かもしれない（この場合は部品は一つ以上の基礎的形状を含むかもしれない）。
【０１１０】
特徴ベース部品行列を事前定義ライブラリにある行列と比較するために再帰プログラミング技法を利用することができる。含まれている情報を比較するとき、行列の指標を入れ替えることによって、データ割り当ての使用が避けられ、必要なプロセス時間が短縮される。再帰プログラミング技法と指標の入れ替えはまた、異なる次数と異なる基底面をもつ行列の比較を容易にする。
【０１１１】
本発明の見地に沿って、ステップS.104で実施される比較操作は、一連の比較よりなり、最初により複雑な形状（たとえば多数の曲げ、またはタブのような複雑な成形を含む形状）に関する行列の比較から開始し、より複雑でない形状（たとえば、より少ない曲げ、またはより複雑でない曲げ、より少ない数の面をもつ形状）へと進む。この一連の比較は部品に、所定数の基本的形状が見いだされるまで行われる。たとえば、比較操作はある特定の部品の三つの最も複雑な特徴または形状を抽出するために行うことができる。さらに、この操作を最初に、薄板金属部品によく、または度々みられる形状に関する行列のグループに対する一連の比較から始め、次により一般的でない形状に進むこともできる。部品を事前定義ライブラリと比較するために、色々な方法を有用な結果をうるために行うことができる。
【０１１２】
たとえば、一連の比較操作を先ず、多数の直角曲げを持つ長方形や正方形形状や直角曲げをもつ単純な部品のような、直角曲げをもつ基本形状を含む行列の直角グループに適用することができる。この行列のグループは、グループの中の、より複雑な行列（たとえば、タブをもつ四つ折り曲げ箱に対応する行列）からグループの中のより単純な行列（たとえば、単純ハット部品に関する行列）へと進める一連の比較にもとづいて探索することができる。それから一連の比較を多角形部品グループの行列に、さらに特別特徴グループの行列へ適用することができる。多角形部品グループは五つ以上の側面と、少なくとも90度以上の曲げを一つもつ部品を定める行列を含みうる。特別特徴グループの行列は、Z―曲げまたは縁取り曲げのような、特別な特徴または成形をもつ部品に関係する事前定義ライブラリ内の行列を含みうる。ここでもまた、部品の特徴ベース行列と各グループの所定行列との間の一連の比較は、複雑性の度合いの減少に従って行われる。この後に、部品の一つの面に二つまたは二つ以上の特徴をもつ多重特徴グループのような、所定行列の他のグループを比較することができる。
【０１１３】
複雑性の度合いに従って部品を事前定義ライブラリの行列と比較し、実現と使用頻度にもとづく行列のグループの一連の比較をすることによって、部品に存在する基本的な形状の決定するためのライブラリとのより効果的で有効な比較ができる。さらに、検出特徴の重複が防がれ、より複雑な形状のみが識別される。
【０１１４】
ステップS,108では、部品にある基本的な特徴または形状間の関係を決めるために特徴関係操作を行う。特徴または形状間の関係は距離によって定められる。二つの形状間の距離は、各々形状の基底面（基本面）の間の曲げ線または面の数にもとづいて決められる。あるいは、特徴間の関係は、部品及び、各特徴の基底面の相対位置と間隔を幾何学的に解析することにより、特徴間の物理的な距離または実際の寸法によって定めることができる。
【０１１５】
例示のため、ステップS.106で決定した部品の三つの最も複雑な特徴または形状は、図１０（ａ）に示す4折り曲げ箱と、ブリッジと、もう一つの4折り曲げ箱とであるとしよう。このような部品については、特徴関係操作を、たとえば各基本的特徴の基底表面または面の間の曲げ線の数を決めるために行うことができる。図１０（ｂ）で示すように、第一の4折り曲げ箱の基底（1）とブリッジの基底（2）の間の特徴関係は、二つの曲げ線の間隔である。さらに、第一の4折り曲げ箱の基底（1）と第二の4折り曲げ箱の基底（3）の間の関係は、四つの曲げ線の間隔であり、ブリッジの基底（2）と第二の4折り曲げ箱の基底（3）の間の関係は、二つの曲げ線の間隔である。
【０１１６】
いろいろなプロセスによって、部品の基本形状の基底面間の曲げ線の数を決めることができる。たとえば、特徴ベース部品行列と所定形状行列を利用して、ステップS.108で特徴関係を決めることができる。最初に、部品行列にある各基本形状に対応する基底面を捜し出す。これは所定形状行列の基底面を、部品行列の面指標と相関することによって行うことができる。前に論じたように、比較操作で切り離した所定形状行列は、部品行列のサブ行列かもしれない。部品行列で各基本形状に対応する基底面を捜し出すには、部品行列内の形状行列の位置と行列の指標の間の相関を解析する。各基本形状の基底面は、予め定められており形状行列の第1列に位置しているので、部品行列内の対応する位置と基底面を捜しだすことができる。
【０１１７】
特徴ベース部品行列内の各基本形状の基底面を決定した後、特徴関係を決めるために、各形状の基底面間の距離を解析する。この解析は、如何なる二つの基底面間の距離をも同定する探索プロセスを含んでいる。部品行列内の特徴と曲げ線情報を見ることによって、どの二つの基底面間の曲げ線の数でも決定できる。二つの面の間に一つ以上の経路が可能な場合には、最小距離を用いてステップS.108において特徴関係を定義することができる。
【０１１８】
特徴関係操作を終えた後の論理の流れはステップS.110に続く。図７に示すように、ステップS.110では、データベースの類似部品探索に用いる探索キーを決めるために、データベース探索キーの同定が行われる。探索キーは、部品に同定された特徴や特徴関係の幾通りもの組み合わせを含みうる。さらに、探索キーをアセンブルするのに、どのような基準の階層も用いることができる。限定されない例として、下記の基準に従って探索キーを作成することができる：（i）部品に同定された一番目と二番目に複雑な特徴または形状；（ii）最も複雑な二つの特徴間の距離または特徴関係；（iii）部品に同定された三番目に複雑な特徴または形状；及び（iv）部品に同定された一番目に複雑な特徴と三番目に複雑な特徴間の特徴関係または距離、及び二番目に複雑な特徴と三番目に複雑な特徴間の距離または特徴関係。図１０（ｃ）に図１０（ａ）の例にもとづいて開発された探索キーを示す。
【０１１９】
データベースの探索を容易にするために、探索キーは、形状ライブラリで定義された色々な基本形状に割り当てられた所定コードをもつ整数の列で表すことができる。たとえば、4折り曲げ箱に整数コード“16”が割り当てられ、ブリッジに整数コード“32”が割り当てられたとしよう。この場合、図１０（ｃ）の例の探索キーは、整数列“16,16,4,32,2,2”で表され、このなかで“4”と“2”は基本形状または特徴間の色々な距離を表す。しかしながら、探索キーの表示は、整数列に限定されるものではなく、どのような組み合わせの整数及び/または文字列を探索キーの表示に用いることができる。
【０１２０】
各部品の探索キーは、仕事情報とともに（別のフアイルまたは同じフアイルに）、データべース、たとえばデータベース30、に格納できる。特徴抽出データの代表的な探索キーは、手動で入力するか、上記のように自動的に作成できる。特徴ベース部品行列のような付加的特徴抽出データは、探索キーを用いて格納できる。探索キーが別のフアイルに格納してあるときには、各探索キーのセットと関連する部品情報を捜し出すための参照用テーブルを用意できる。あるいは、探索キーは部品情報を同定する（たとえば部品または参照番号によって）データフイールドとともに格納しておくことができる。
【０１２１】
ステップS.112では、同定された探索キーにもとづくデータベースの協調探索が行われる。協調探索は、協調データベース探索技法を用いる探索である。協調探索技法は、同一の探索キーをもつ部品ばかりでなく、類似の探索キーを持つ部品を捜し出す。これによってデータベースにある、類似および同一部品を同定することができる。特定の部品についての探索を行うと、その部品のものと同定された探索キーを、データベースにある他の探索キーデータと比較することができる。ステップS.112で行われる協調探索は、探索キーの順序を緩めるか修正することによって、データベースにある項目で、探索キーによって同定された特定の部品と正確に一致するか又は最も類似している項目を同定するように構成される。色々なプロセスと方法を、協調探索において探索キーを適合させるのに用いることができる。
たとえば、最初にデータベースの探索を、探索する部品のものと同定されたものと正確に一致する探索キーの順序をもつ部品を同定するために行うとする。これは同定された探索キーをデータベースに格納されている探索キーと比較することによって行われる。同じ探索キーをもつ部品（もしあれば）を同定した後、引き続き他の類似部品を捜しだすために、異なる修正された探索キー順序に基づくデータベースの探索を行うことができる。最初探索キーにある、あまり重要または敏感でない項目または基準（特徴関係または距離のような）は、より重要または敏感な探索項目（部品にある基本的な特徴または形状のような）を修正する前に修正し、探索することができる。さらに、これらの各項目は、項目の重要度に従って修正し、部品にある一番目と二番目に複雑な特徴または形状に関連する項目に、より高い重みまたは重要度を当てることができる。たとえば、ひき続き最初に行う探索は、三番目に複雑な特徴と一番目、二番目に複雑な特徴間の定義された距離を修正した後に行うことができる。この距離は、所定曲げ線数（たとえば1-3）だけ変更し又は現在の距離に基づいた距離の所定範囲を定義することによって修正できる。しかる後、一番目と二番目に複雑な特徴または形状間の距離を変更して、データベース探索用の修正された探索キーの組をもう一つ備えることができる。部品の特徴関係または距離の探索キーを修正した後、同定された形状を、協調探索における付加的な修正探索キーを導くために変えることができる。たとえば、三番目に複雑な特徴または形状に関する探索キー項目を、現在扱っているものの特徴または形状によって、関連するがより複雑でない形状に変えることができる（たとえばタブのある4折り曲げ箱を単純な4折り曲げ箱に）。さらに、一番目と二番目に複雑な特徴の探索キーを同じように変えることによって、さらに協調探索のための修正探索キーを加えることができる。
【０１２２】
探索キーに関係する距離と特徴/形状の、協調探索中の修正は、いろいろな方法と技法によって実行できる。上記のように、どのくらい距離を変えるかは、距離の現在値に依存する。距離の大きさ（たとえば4曲げ線）を、探索を拡張し、より協調的にするために距離の範囲（たとえば3-5）で修正することができる。特徴または形状についても、類似部品を同定するために探索キーを修正できる。特徴または形状は、特徴タイプの階層構造を通して修正できる。たとえば、現在扱っている特徴タイプ（たとえば4折り曲げ箱）を、関連し同じ特徴タイプに属するより複雑でない特徴タイプ（たとえば3折り曲げ箱）に修正することができる。特徴/形状を修正するに用いる階層構造は、複数の異なる技法、たとえば型抽象化階層（TAH）に基づいて事前に定義でき作成できる。TAHとTAH世代に関する詳しい情報は、たとえばチューら、ウエスリー、W（CHUWesley W.）による"型抽象化階層による協調的問い合わせ応答"（Cooperative Query Answering via Type Abstraction Hierarchy）CSD-900032,1990年10月、カリフォニア大学ロスアンジェレス（University of California,LosAngeles,October 1990）および1995年、コンピュータ科学哲学博士の博士論文、クオーロン・チアング“協調的問い合わせ応答のための型抽象化階層の自動生成”（CHIANG,Kuorong,Automatic Generation of   Type Abstraction Hierarchies for Cooperative Query Answering）にあり、そこに開示されている情報すべてを参照することによってここに取り入れられている。
【０１２３】
協調探索の間に、他のプロセスやステップを実施するこができる。たとえば、部品の特徴に関連していると同定された探索キーに基づいたデータベースの探索に加えて、部品の製造情報に関連した探索基準に基づいて探索することもできる。たとえば、付加的な探索キーを利用して、一例として各部品に必要な機械構成を比較することができる。機械構成情報は機械のタイプまたは部品を製作するために必要な機械類、部品を製作するために用いる工具類や工具構成および/または機械類のバックゲージング設定を含む。付加的探索キーは、機械構成情報および/または他の製造情報に基づいて開発することができ、本発明の協調探索をする際に、同定された探索キーとともに用いることができる。その結果、製作される部品と同一または類似な部品は、部品の設計と製造特徴両方に基づいて同定することができる。
【０１２４】
最も類似した部品を選ぶために、選択部品探索をステップS.114で実行し、協調探索の結果のより詳しい比較と、探索された部品と同じまたは最も類似している部品を所定数だけ選ぶ。選択部品探索は、協調探索で同定された各部品に対する付加的な情報や特性の解析を伴いうる。これは部品の寸法や部品にある孔や開口の形のような、捜し出された部品の色々な特徴の解析を含む。さらに各部品に要する機械構成のような、捜し出された各部品の製造情報の比較も含みうる。上記のように、機械構成情報は、部品の製作に要する機械の種類または機械類、部品の製作に用いる工具や工具構成、及び/または機械類のバックゲージング設定を含む。選択部品探索を行うために、各部品の曲げモデルや他の仕事情報が、協調探索で同定された探索キーに基づいてデータベースからアクセスされる。上記のように、各探索キーの組に対応する仕事参照番号またはコードを提供するために、ルックアップ表や付加的データフイルドを設けることができる。データベースから部品情報を検索した後、各部品の付加的情報（たとえば部品寸法、材料のタイプ、特別な成形、部品の孔または開口等）を、どの部品が探索された部品に最も類似しているかを決めるために解析できる。このプロセスはオプションで、データベースの部品で、当該部品に最も類似の部品を選び集約する付加的な選択プロセスの役割を果たす。この部品の付加的情報または特性を解析し、照合することによって、選択部品探索を、所定の数または組の最類似部品を同定または選択するために行うことができる。たとえば、選択部品探索で、照合探索キーの数と付加的部品特性の照合に基づいて、五つの最類似部品を同定できる。選択部品探索で選択される部品の数は五つに限らず、工場の必要性とデータベースに実際に格納されている部品の数に基づいて選ぶことができる。この数は、より有効で役立つ探索結果をうるために選択的に修正でき、またユーザーに探索の組を変えるために、この数を修正する機会を与えることもできる。
【０１２５】
選択部品探索を行った後、ステップS.116で部品をランク付けする（特徴の類似性や突き合わせ探索キーの数に従って）ために、類似性指標を計算することができる。類似性指標はステップS.116で計算され、サーバーまたはステーションモジュールの出力として提供され、これによってユーザーはどの仕事フアイルをデータベースから検索し、画面に映し出すかを選択できる。類似性指標によって、選択された部品と探索部品の特徴の類似性の程度に基づいて、選択部品のランク付け（たとえば各部品の仕事または参照番号を付してランク1から5）ができる。このためには各部品の特徴ベース行列を探索部品のものと比較する。特徴ベース行列の比較は、選択部品と探索部品の間の類似性をよりよく示す。前のべたように、特徴ベース部品行列は各部品の探索キーとともに格納できる。しかしながら、各以前の仕事の特徴ベース部品行列を探索キーとともに永久格納することは、不必要に大きな記憶スペースを占有する（特にデータベースに多数の部品が格納されている場合）。従って各部品の探索キー・データのみを格納し、類似部品探索を行うときに自動的に各選択部品の特徴ベース行列を生成することしかできない。  従って、選択部品の曲げモデルと他の仕事情報を検索した後、前にステップS.102についてのべたように、特徴ベース行列は本発明の特徴ベース抽出操作を通じて作成する。そのあとで、類似部品探索時に一時的に格納した探索部品の特徴ベース行列を、作成した選択部品の特徴ベース行列の各々と比較できる。色々な方法とプロセスを、部品の特徴ベース行列の比較と部品間の類似性の決定に利用できる。たとえば、各選択部品の特徴ベース行列について、行列内の場所を探索部品のものと比較できる。行列内の各場所は、再帰的プログラム技法に基づいて比較できる。行列内の情報は、各行列内の対応する基底面の場所を決め、行列の指標を交換することによって比較できる。選択部品は探索部品の副特徴に対応するか又はその形状をもつこともあり、又行列の指標が同一でないか、または同じ番号付けがされていないこともあるので、含まれている情報を比較するときに、部品行列内で比較できる面を捜しだして指標を振り替えなければならない。さらに探索部品の中に一つ以上の副特徴が存在する場合、行列内の情報を比較するとき、同じ次数の行列を提供するために、一つまたは一つ以上の擬似面（行列の行と列で情報が無いか空白のもの）を導入しなければならないことがある。
【０１２６】
行列の情報を比較するときに、各選択部品と探索部品の類似性の程度を決めるために、複数の異なる順序づけ方式を用いることができる。たとえば、所定ペナルティレベルまたは量を、行列内の整合しない各位置に割り当てるペナルティベース順序づけ方式を用いることができる。行列内のすべての情報を比較した後、各選択部品の総ペナルティレベルを用いて類似性の程度を決めることができる。最も低いペナルティレベルをもつ選択部品が、探索部品に最も類似した部品と決定される。他の選択部品も、各部品に付せられた総ペナルティレベルに基づいて順序づけできる（たとえばペナルティレベルが低いほど類似指標が高い）。
【０１２７】
本発明のさらなる見地に沿って、各非整合位置のペナルティレベルは、その位置にある情報のタイプに基づいて割り当てることができる。ペナルティレベルは整数量で非整合情報の重大性または重要性に応じて変えることができる。たとえば、異なる、関係のない特徴グループ（たとえば平行曲げ特徴対直列曲げ特徴）に関する非整合位置に対しては、高いペナルティレベルまたは量を割り当てることができる。これと対照的なのは、異なるが類似の特徴グループ（たとえば同じ曲げ線方向をもつ接触コーナー特徴対逆の曲げ線方向をもつ接触コーナー特徴）である。ペナルティレベルまたは量は、非整合位置に存在する情報のタイプと相違のタイプに従って事前に定義、類別される。
【０１２８】
ステップS.116における類似性指標操作の典型的なコードは付録Bに示されている。このコードはC++言語で書かれており、上に記述した行列の比較と非整合位置に対するペナルティレベルの割り当てに関する色々なプロセスと操作を含んでいる。上に付記したように、比較された各選択部品の結果としてえられた総ペナルティレベルは、類似性指標を導き、表示するのに用いることができる。付録Bにあるコード・リステイングには、記されている典型プログラム・コードの理解を助けるためのコメントも含まれている。
【０１２９】
次に図１１−２５を参照しながら、曲げモデルの開発と、色々な2-D、3-D図面に基づいた部品の2-D、3-Dモデルの開発を、本発明の見地に沿ってより詳しく記述する。前に論じたように、各薄板金属部品に関する曲げモデルデータは、部品の2-D、3-D表現両方に関連するデータを含んでいる。顧客の注文に基づいて提供または作成された原図のタイプに基づいて、色々な折りたたみと展開アルゴリズムや他のプロセスを2-D及び3-Dモデルの開発に利用できる。特に図１１-１８は、部品の元の2-D一方向図面（２次元単一図面）に基づいて、3-Dモデルを作成するに利用できる折りたたみアルゴリズムの論理の流れの例を示す。図１９は、3-D原図（厚さぬき）に基づいて2-Dモデルを作成するのに用いられる展開アルゴリズムや他のプロセスの基本的な論理の流れの例を示す。最後に図２０-２４と図２５は、2-D三方向図面（２次元三面図）と厚さありの3-D図面から、厚さぬきの3-Dモデルを作成するのに実施できる色々なプロセスや操作の論理の流れの例を示す。これらのプロセスや操作でえられた3-Dモデル（厚さぬき）は、文中に明示されているように、展開アルゴリズムまたはプロセスに基づいて2-Dモデルを作成するのに利用できる。
【０１３０】
図１１は2-D一方向図面から折りたたみアルゴリズムを用いて3-Dモデルを作成するプロセスと操作の論理の流れを示す。図１１の流れ図で行われる機能や操作は、たとえばサーバー・モジュール32にあるソフトウエアまたはプログラム論理によって実施できる。ステップS.120では、顧客の仕様に基づいて提供された、あるいは新たに作成された2-D一方向平面図が、サーバーモジュール32に入力または取り入れられる。2-D平面図はCADソフトウエアを用いて作成し、サーバー・モジュール32に入力するか、ベルムまたはキャドキーのような、適当なCADまたはCAD/CAMシステムとインターフエイスすることによってサーバー・モジュールに取り入れることができる。2-D図面は、たとえばDXFまたはIGESフアイルとして格納され、曲げられる打ち抜き及び/または切断材料を図示することができる。2-D図面はまた、薄板金属部品の表面や面の曲げ線の位置や、孔または開口を示すことができる。2-D図面を後で処理するための準備として、ステップS.124における次の面検出プロセスとステップS.126における曲げ線検出作業を行う前に、ステップS.122でサーバー・モジュール32によって自動クリーニングやクリーンアップ機能を実施することもできる。
【０１３１】
本発明の自動トリミングとクリーンアップ機能は、2-D平面図を、処理に対して準備するために備えられている。2-D平面図は、薄板金属部品の展開状態の2-D表示で、部品の幾何学を構成し表現する線及び曲線の如き部品要素（エンティティ）を含むとともに、部品に存在する開口または孔の位置を示す。通常このような2-D平面図の構成要素（エンティティ）は、CADまたはCAD/CAMシステムを使用して入力し、作成する。しかし、2-D平面図を作成するとき、このような要素はしばしば誤って連結または重ね合わされ、一つの要素が一つ以上の面の境界を示すのに用いられることがある。さらに、部品の境界を決めている外側線が、境界の隣接するコーナーで分断されていて、部品と各面の外側の寸法の検出を難しくしている。さらに、2-D平面図は、寸法情報やテキストのような本質的でない情報を含みうる。このような異常は、元の2-D図面を正確に解析し、部品の面や曲げ線を均一に検出するのを難しくする。本発明の自動トリミングとクリーンアップ操作を備えることによって、各面は連結された要素の一義的なセット（セット）で表現できる。その結果、2-D平面図は、引き続き行われる処理と最終的に行われる3-Dモデル表現作成のための折りたたみのために、より簡単かつ効率よく解析できる。
【０１３２】
図１２に示すように、元の2-D図面では面間のトリミングがされておらず、図中の一つの線要素が一つ以上の面の外側境界または複数の境界を定めていることがある。上記で論じたように、このような配置は各々の面の検出を困難にする。本発明の自動トリミング機能は、連結性情報を決定し、上記のような要素を交点で断ち切るために、各部品要素（線、弧や曲げ線のような）の終点と交点を解析するのに備えられている。このようなトリミング機能は、断ち切られた各要素の終点を決められた交点に設定する機能ももつ。たとえば、図１２に図示されている交点をトリミングすることによって、各々が交点に終点を共有する三つの要素（二つの線と一つの曲げ線）がえられる。このようなトリミング機能を備えることによって、要素解析と連結に基づいて部品の面をより容易に検出することができる。実施できる面検出操作のさらに詳しい記述は、下記に図１５（ａ）-１６（ｃ）を参照しながら提供される。
【０１３３】
色々なプロセスや操作を用いて2-D図面の要素の交点を検出することができる。このようなプロセスは、2-D図面のフアイルのデータのフオーマットと配列に基づいて作成できる。通例2-D平面図は幾何学データ（色々な部品要素を定義する）と非幾何学データ（たとえばテキスト等）を含む。幾何学データは、データの各行またはシーケンスにあるキーワードによって非幾何学データと区別できる。このようなキーワードは2-D図面のデータ書式に従って設定される。2-D、3-D図面によく用いられる書式としてDXFとTGES書式がある。各要素の幾何学データを解析することによって要素の終点や交点が検出でき、適当であればトリミングができる。
【０１３４】
上記で論じたように、線、曲げ線や他の要素は終点及び/またはベクトルで定義できる。たとえば2-D平面図では、各2-D線は2-D終点の組（たとえばX1,Y1とX2,Y2）で特定することができ、曲げ線は曲げ線の2-D空間位置とともに方向を示すベクトルで表すことができる。さらに2-D弧は2-D空間データ（たとえば中心X、中心Y、半径、開始角度、終了角度）で特定することができる。幾何学データはまた、色々なタイプの線要素（たとえば弧、実線、破線、鎖線等）を区別する属性をもつ。通常弧要素は薄板金属部品の孔や開口を、実線は部品の境界や形状を示すのに用いられる。曲げ線は普通破線で示され、部品の中心線は鎖線で示される。
【０１３５】
元の2-D図面の幾何学データを解析し、各要素の交点を決めることができる。データ割り当てやデータ反復のような、色々なデータ解析手法を2-D図面の各要素の幾何学データの解析に用いることができる。各要素の終点及び/または他の2-D空間データに基づいて、線や他の要素が交差するかどうかを決める簡単な幾何学解析をすることができる。二つの要素が交差することが決まれば、各要素を決定された交点で断ち切り、残った要素の終点には交点で定められた共有点を割り当てることができる。
【０１３６】
トリミングの方法は、交差することが検出された要素のタイプに基づいて行われる。たとえば二つの実線が交差することが検出されると、図１３（ａ）に示すように、各線要素を断ち切ることによって、定められた交点で接する四つの線要素がえられる。また線要素と弧要素が、図１３（ｂ）に示すように交差することが決まると、各要素を断ち切ることによって共通の終点をもつ二つの線要素と二つの弧要素をうることができる。しかしながら、要素の交差が検出されても、トリミングを必要としないこともある。たとえば、如何なる要素でも中心線（たとえば鎖線要素）と交差することが決定した場合、どの部品の中心線も部品の面または曲げ線を定めたり区別したりすることはないので、トリミングの必要はない。また、連結しない要素でも、開いている交点または面積が、所定の許容度内であれば切断できる。たとえば、潜在的に交差する線の終点が、実際に他の要素と交差するときの交点と、事前に定義した許容度または距離ε（たとえば0.0-0.01mmまたは0.0-0.001インチ）以内であれば、要素は投影された点で連結交差しているものと扱ってよい；そしてたとえば図１３（ｃ）に示すように、要素を断ち切ることができる。
【０１３７】
自動トリミングをした後、えられたデータを、非連結要素を検出し修正するためにクリーンアップ機能で処理することができる。しかしながら、本発明はこのような処理のみに限られていない；処理時間を短縮するためにクリーンアップ機能を、各要素が解析されている間に、自動トリミング機能と同時に行うことができる。クリーンアップの間に、2-D図面の幾何学データが、隣接する要素間の開いた交点または領域を検出するために解析される。自動トリミング機能と同様に、要素間の開いた交点の領域を検出するために、各要素の終点や他の2-D空間データも解析できる。このようなデータに簡単な幾何学的解析を加えることによって、要素の終点が互いに事前に定義した許容度または距離（0.0-0.01mmまたは0.0-0.001インチ）内にあるかどうかが決定できる。要素の終点がこのような開いた交点をもつことが決定されると、要素を連結し、図１４に示すように共通の終点を割り当てることができる。
【０１３８】
ここでもまた、クリーンアップ機能をどのように行うかは、開いた交点をもつことが検出された要素のタイプによる。二つの実線が開いた交点をもつことが検出された場合、各終点に共通の終点を割り当てることができる（たとえば図１４を見よ）。しかしある要素が部品の中心線（たとえば鎖線要素）と開いた交点をもつことが決まったときには、要素を連結したり共通の終点を割り当るべきでは無く、中心線は無視しなければならない。またクリーンアップ機能は、2-D図面から非幾何学データ（テキスト等）を消去するための付加的なプロセスまたは操作を含みうる。前述べたように、非幾何学データは、2-D図面データとともに用意されているキーワードに基づいて幾何学データと区別できる。クリーンアップ機能にはまた、後で本発明の2-Dクリーンアップ機能を参照しながらより詳しく説明するような、他のクリーンアップ機能を組み込むことができる（たとえば図２１-２３（ｂ）を見よ）。
【０１３９】
ステップS.122で自動トリミングとクリーンアップ機能を行った後、ステップS.124で処理された2-D図面について面検出の手続きを行うことができる。本発明の見地に沿って、面検出手順は要素（線や弧）とループ解析に基づいた部品の面の検出と定義付けを含む。図１５（ａ）-１６（ｄ）に面検出手続きで行われる色々なプロセスと操作の例を示す。ループ検出技法を本発明で部品の面を検出し、決定するのに用いることができる。面検出手続きは、たとえばサーバー・モジュール32にあるソフトウエアまたはプログラムされた論理によって実施できる。
【０１４０】
本発明の見地に沿って、部品の外側境界のループ検出解析に引き続く、部品の最小または内側ループの解析を用いて、面の各々を検出できる。薄板金属部品のユニークな幾何学のため、面と部品にある開口は、相対的極大（たとえば外側）と極小（たとえば内側）ループの順序の解析によって検出することができる。下記に論じるように、ループ解析は部品の線と弧要素の連結性にもとづいて行うことができる。ループ解析を部品の外側から部品の中心に向かって行うことにより、部品の開口や面を、循環順序（たとえば面材料、開口、面材料、開口等）に従って定義されたループ間の境界に基づいて検出することができる。
【０１４１】
図１５（ａ）に示すような、図示の各面の各種の線要素を含む2-D平面図が提供されたとしよう。上記のように、ループと要素解析は部品の外側から始めるように行う。部品の外側境界にあるどの要素を初期参照点にとってもよい。限定されない例として、図１５（ｂ）に示すように、最も左側の線要素を検出し、初期参照点に用いる。最も左側の線要素は、2-D図面にある各要素の幾何学データを比較し、どの要素が最も小さいX座標の値をもつかを決めることによって検出できる。最も左側の線要素を検出した後、点P1から部品の外観が導かれ、図１５（ｃ）に示すように部品の外側境界を検出される。点P1を決めるには、最も左側の線要素のいずれの終点を用いてもよい。図１５（ｃ）に示す実施例では、上側の終点（つまり最も大きなY座標の値をもつ終点）が点P1に用いられている。
【０１４２】
部品の外観、またはまわりのループを導くのには、通常のループ解析技法を使うことができる。たとえば、リード線ベクトルを、部品の外観を追ってゆくに従って、始点P1と連結している要素の終点から投影してゆくことができる。一つ一つの要素が検出され、通過される毎に、要素が選ばれたことを示すフラグを設定することができる（たとえば記憶内のフラグは、一度選ばれたことを示すために1に設定する）。ループの経路は始点P1からどちらの方向にも始められる。たとえば、リード線ベクトルを点P1から反時計方向（たとえばリード線ベクトルをY座標方向に投影する）に投影することができる。ループはループ経路が始点（つまり点P1）に戻ったところで完結する。
【０１４３】
上記のように、始点P1からリード線ベクトルを反時計方向に投影できる（たとえば最初のリード線ベクトルをY座標方向から始めることによって）。引き続きループの経路にある最初の要素を検出するために、各未検出要素が点P1のまわりにリード線ベクトルとなす角度を座標枠に基づいて測定し、解析してリード線ベクトルと最も小さい角度をもつ要素を選ぶ。外側ループでは、 各角度は要素線がリード線ベクトルとなす外側角度を測る。点P1の回りの要素は、どの要素が点P1と終点を共有するかによって決められる。各要素の未選択状況は、各要素に付したフラグを解析することによって決定できる。図１５（ｃ）に示すように、図示の2-D図面例では二つの要素線（X座標方向のものとY座標方向のもの）がP1のまわりにある。これらの要素の解析では、Y座標方向の線要素が、リード線ベクトルとなす角度（0度）が他の線要素がなす角度（270度）より小さいので選ばれる。
【０１４４】
続いてループ解析は選択された他の線要素の終点に進み、選択されたことを示すためにフラグが設定される。その終点で、別のリード線ベクトルが投影され、その点のまわりの非選択要素を比較することによって、どの要素がリード線ベクトルと最小の角度をもつかを決める。ここでもまた、角度はリード線の外側から測り、座標フレームを用いて角度の大きさを決める。弧要素に出会った場合は、リード線ベクトルの外側から弧の接線までの角度を測らなければならない。また、次の終点にある要素が一つのみであれば（部品のコーナー位置のように）、比較の必要はなく、単にその要素を選択してループに含めればよい。
【０１４５】
部品の外観に沿ってループ経路が進むにつれ、選択された各要素は、ループ内の要素の連結性を示すためにリンクされたリストに含めることができる。経路が始点P1に戻るとサイクルは完了し、外観と、部品の外側境界を示す要素または線のリンクされたリストに基づいてループを（L4）と定義できる。ループL4内の各線または要素は、各終点で連結できる。ループL4の方向を、外側ループであることを示すために、図１５（ｄ）に示すように、反対方向（つまり時計方向）に変えることができ。ループの方向は、ループL4で線がリンクされる順序に基づいて定義することができる；従って方向を、リンクされたリストの順序を逆にすることによって変えることができる。
【０１４６】
外側ループの完了後、外側ループ解析に用いたのと類似のプロセスで部品の内側ループの解析を行うことができる。ただ内側ループの解析では、各非選択要素は各要素がリード線ベクトルの内側となす角度に基づいて比較される。さらに、内側ループ解析では、ある点のまわりの両方の要素がすでに選択されていると示された場合（たとえば面を境する二つの外側線要素を比較するとき）でも、二つの要素が既に二度選択（2のフラッグ設定）されてない限り、二つの要素を比較することができる。少なくとも一度選択された要素（たとえば外側要素）と選択されていない要素の場合は比較は行わず、非選択要素をループの一部分として選択する。図１６（ａ）-１６（ｃ）に、図１５（ａ）に示す部品の面を検出し、規定するのに行うことができる内側ループが例示してある。
【０１４７】
内側ループ解析は、どの外側要素の終点からでも、あるいは選択されていない要素を検出することによって開始することができる。たとえば点P1を、内側ループ解析の始点に選び、リード線ベクトルを投影するのに用いることができる；あるいは外側ループ解析の際に選ばなかった内側の線要素の一つも解析の始点に用いることができる。外側ループ解析と同じように、リード線ベクトルを反時計方向（たとえば一番目のリード線ベクトルをY座標方向から始める）に延ばしてゆくことができる。次いで点P1のまわりの各要素を比較し、どの要素がリード線ベクトルと最小の角度をもつかを決める。リード線ベクトルとなす角度を決めるのに、座標枠を用いることができる。前記のように、内側ループ解析に際には、要素の比較は各要素がリード線ベクトルの外側でなく、内側となす角度をもとに行う。最初の要素が選ばれ、ループのリンクされたリストに含めたら、そのフラグを1だけ増分し、つぎのリード線ベクトルを投影することによって解析を進めることができる。このプロセスはループが最初の始点に戻るまで続けられ、そこで第一の内側ループが、対応する要素のリンクされたリストによって定義（たとえばL1）される。
【０１４８】
さらに部品の内部に進んで、同じように内側ループ解析を行うことができる。次の始点は、どの要素が一度しか選ばれていないかを決めることによって選ぶことができる。二度選ばれたフラグをもつ要素は、その要素がすでに外側ループ（たとえばL4）と少なくとも内側ループの一つ（たとえばL1）で選ばれた外側要素であることを示す。ここでもまた、各要素が選ばれるたびに、それが内側ループのリンク・リストに含まれたことを示すために、フラグを1だけ増分する。
【０１４９】
すべての内側ループが定められた後（たとえば図１６（ｃ）の例ですべての要素が二度選ばれた後）、えられたループを用いてループツリー（ループ木）を作成することができる。図１６（ｄ）に、検出されたループL1-L4に基づいて作成したループツリーの例を示す。部品の外側ループ（L4）はツリーの根（ルーツ）と定義し、外側ループと共通の要素をもつ各内側ループ（L1-L3）は、根の子どもと定義されている。共通要素の存在は、各ループを規定する要素のリンクされたリストの解析と比較によって検出できる。内側ループ内に、さらに要素（たとえば孔または開口）が検出された場合には、これらのループを、それが位置する内側ループの子ども（つまりループツリーの根の孫）と定義することができる。
【０１５０】
ステップS.124で面検出手続きを行った後、ステップS.126で曲げ線検出操作を行うことができる。たとえば図１７に示すように、ステップS.124で部品のループを検出し解析するときに、本発明の面検出論理は、面情報を規定し、検出された面を曲げグラフ・データ構造にノードとして格納するのに、ループツリーを利用することができる。部品の面は、ループツリーにおける外側と内側ループの順序から検出できる。上記のように、各ループは要素または線のリンクされたリストを含む。これらの要素は、部品の各面の境界を定めるのに用いられる。従ってステップS.126において曲げ線検出操作を行い、部品の面と曲げ線の間の関係を決めることができる。ステップS.126の曲げ線検出操作は、ある二つの隣接する面が共有する端または線要素を検出することによって、部品の色々な面間のすべての曲げ線を検出する曲げ線検出論理を含むことができる。また一つ以上の領域で接続している面（たとえば3-Dモデルに曲げ線検出アルゴリズムを適用する場合―たとえば下記に論ずる図１９を見よ）については、いろいろな発見的方法（ヒューリスティク）を適用して、部品の曲げ線の最小数を検出し、選択することができる。検出された曲げ線は、たとえば図１８に示すように、最終的な曲げグラフ・データ構造を作成するための、面の節（ノード）の間の連結エージェントとして格納しておこことができる。
【０１５１】
本発明の曲げ線検出操作は、たとえばサーバー・モジュール32に備えたソフトウエアまたはプログラムされた論理によって実施できる。曲げ線検出操作の目的は、部品が最も少ない数の曲げ線で連結されるように、部品の曲げ線を検出し、選択することにある。曲げ線検出操作は、部品の2-Dと3-Dバージョン両方に備えることができる。原3-Dモデルについての曲げ線検出の適用は、下記に図１９を参照しながら論ずる。上記のように、検出された曲げ線は、最終的な曲げグラフ・データ構造を作成するための面の節の間の連結エージェントとして格納できる。この最終的曲げグラフ・データ構造は、2-Dデータ・モデルから折りたたんで部品の3-Dバージョンを作成するのに利用できる。
【０１５２】
図１１のステップS.120で入力として提供された2-D図面は、曲げ線情報を含まないか、曲げ線情報が不明確で、一義的にまたは矛盾なく定義されていないことがある。その場合、曲げ線検出操作を、曲げ線を検出し、部品の検出された面との関係を検出するために行うことができる。このプロセスの間に、各面を定義する要素（エンティティ）のリンクされたリストを解析し、各面が部品の他の面と共にもつ隣接する端または線要素を決めることができる。これはある与えられた二つの面の間の可能なすべての接触を解析することによって行うことができる。接触は、長さが0以上の（つまり線要素が点ではなく、実際の線である）、共通する線要素（またはお互いに事前に定めた距離許容度にある複数の線要素）の存在によって決定できる。リンクされたリストにある幾何学データを解析することによって、部品のすべての二つの面間のこのような接触の存在を決めることができる。
【０１５３】
ある特定の面が、他の面と共通の端または接触領域を一つしかもっていない場合、両方の面に共通の要素は曲げ線であると定義することができる。一つ以上の領域で共通接触を持つ複数の面（たとえば3-Dモデル；ただし2-Dモデルでも起こりうる）については、色々な発見的方法（ヒューリスティック）を用いて部品の最小数の曲げ線を検出し、選択することができる。使用する発見的方法は、複数の面が曲げ線で連結され、複数の面にわたる連続ループが形成されないようになっていなければならない（このような曲げ薄板金属部品の製作は不可能なため）。
【０１５４】
利用できる発見的方法の例として、共通する領域で最も長い接触領域をもつものを曲げ線に選ぶ方法がある。ある面が、他の面と一つ以上の共通端をもっている場合、この発見的方法によって最も長い長さをもつ共通要素を面の曲げ線に選ぶことができる。この発見的方法は、曲げ薄板金属部品を製作するときに、通常長い接触領域を持っている方が良いという原則にもとづいている。使用できるもう一つの発見的方法は、異なる可能な曲げ線の組み合わせ（3-Dモデルの曲げ線を決めるときのような）に関係する。この発見的方法では、すべての可能な共通領域が検出され、曲げ線の色々な組み合わせが選択されると、曲げ線の組み合わせで最小の曲げ線の数をもつ組み合わせが選ばれる。
【０１５５】
曲げ線が検出されると、部品の面と決められた曲げ線は確認のためにオペレータに表示される。オペレータが部品の曲げ線の選択に満足しない場合には、曲げ線検出操作に手動選択機能を備えることによって、サーバー・モジュール32でオペレータが選択的に、薄板金属部品に好ましい曲げ線を指示できるようにすることができる。オペレータは、マウスやキーボード等、適当な入力手段を用いて、曲げ線を保持するか変更するかを指示することができる。しかる後、オペレータによって選ばれた修正された曲げ線を用いて、最終的な3-D（または2-D）部品を作成することができる。
【０１５６】
本発明の曲げ線検出操作を実施するために、色々なプロセスや操作を備えることができる。曲げ線検出操作を実施するためのコードの例を、付記の付録Cに与える。例示のコードはC++プログラム言語で書かれており、記述の論理フローの理解を助けるためのコメントが含まれている。例示コードは、2-Dまたは3-Dモデルについて行うことができる曲げ線検出操作の実施例で、曲げ線の最適選択を決める発見的方法（上述のような）を含む。
【０１５７】
検出された面と曲げ線情報は、本発明の折りたたみと展開プロセスに利用することができる。折りたたみまたは展開の際、各曲げ線の回りに3次元回転を行うと、結果として3-Dまたは2-Dモデルが導かれる。この仕事を行うには、単に部品の各面と他の要素に対して、回転と並進を含む行列変換を行えばよい。色々な市販で入手できる展開と折りたたみソフトウエア適用の特性を、本発明の基本的な展開または折りたたみステップを実施するのに利用できる。たとえばアマダ  アンフオルドとフオルド  システム・ソフトウエアをこれらの基本操作を行うのに利用できる。アマダ  アンフオルドとフオルド  システム・ソフトウエアはアマダ・アメリカ社（以前は社名U.S.アマダ社で業務）、ベユナ・パーク、カリフオルニアから入手できる。アマダアンフオルドとフオルド・システム・ソフトウエアについての情報は、オートキャドのためのアマダ・アンフオルド・マニュアル（1994年3月版）、キャドキーのためのアマダ・アンフオルド・マニュアル（1994年5月版）とキャドキーのためのアマダ・ウインドウズ・アンフオルド・マニュアルにあり、その明細を全般的に参照することによって本文書に明白に取り入れる。2-Dモデルから3-Dモデルを作成するための折りたたみ操作については、後でステップS.132を参照しながら論ずる。
図１１に戻って、曲げ線検出操作をステップS.126で行った後、サーバー・モジュール32がユーザーに対し、この後の折りたたみプロセスに用いる主要な曲げと差引高（縮小量）の情報を指令することがある。たとえば、ステップS.128で、サーバー・モジュール32はユーザーに、曲げ方向（たとえば前方、後方等）も含む曲げ角度及び/または曲げ内側半径を含む各曲げ線の曲げ高（曲げ量）の指示を求めることがある。ステップS.130で、サーバー・モジュール32はまたユーザーに対し、V―幅、材料のタイプ、及び/または差引高（縮小量）の入力を求めることがある。これらの情報は、折りたたみ操作における曲げ差引高（曲げ縮小量）を補償するのに利用できる。材料の厚さとタイプとともに、曲げ角度と使用するダイスのV-幅によって、実際の薄板金属部品は薄板金属部品を折りたたむときに、差引高だけ引き伸ばされる傾向がある。
【０１５８】
前記モデルでこの効果を補償するために、差引高情報を利用して、折りたたみ操作で3-Dモデルを作成するときに、曲げ線の各側で部品の面の寸法を差引高の半分だけ引き延ばす。本発明の見地に沿って、この差引高はユーザーによってサーバー・モジュール32に入力（たとえばキーボード等によって）できる。あるいは、部品の材料のタイプと厚さにもとづいた差引高を含む材料表をオペレータに表示することができる。材料表は、異なる曲げ角度やV―幅に対する色々な差引高を示す。ユーザーは、サーバー・モジュール32で表示された材料表から適切なV―幅と曲げ角度を選ぶ（たとえばマウスまたはキーボードを用いて）ことによって、自動的に差引高をセットすることができる。曲げ角度の内側半径も、適切なV―幅を選ぶときに、材料表を介してユーザーによって自動的にセットできる。オペレータが入力する（あるいはオペレータによる入力後に変換される）差引高は、部品幾何学データを表すものと同じ長さの単位（たとえばmm）である。折りたたみ操作時に、曲げ線の各側の各面の長さ寸法を、注目している曲げ線の差引高の半量だけ増やす。面の曲げ線に垂直な長さ寸法は、曲げ線の各側にある面の境界を定める要素の終点を引き伸ばすことによって増やすことができる。このような差引高補償は、各折り曲げについてオペレータによって供給された差引高にもとづいて、部品の他の曲げ線の各々について行うことができる。
【０１５９】
ステップS.132では、加工された2-D平面図にもとづいて、3-Dモデルを作成するための、差引高補償を含めた折りたたみ操作が行われる。前記のように、折りたたみ手続きは、行列変換の使用と最終的曲げグラフ・データ構造で定義されたそれぞれの曲げ線を回転軸に用いることを含む通常の幾何学的模型化法によって遂行することができる。さらに、差引高の効果を補償するために、3-Dモデルを作成する折りたたみの際に、部品の面を曲げ線の各側で差引高の半量だけ引き伸ばすことによって、薄板金属を実際に折り曲げるときの面の寸法の変化をより正確に反映することができる。
【０１６０】
たとえば、ステップS.132で折りたたみ操作を行う時に、曲げパラメータ（たとえば曲げ角度、内側半径）とともに、部品幾何学と形態データ（または曲げグラフ構造）を利用することができる。2-D空間で表わされた部品の各面、曲げ線、孔と成形についての変換行列を計算できる。通常の行列変換を、2-D平面図に適用することによって、3-D空間データをうることができる。変換は一般に回転に続く並進を含む。上記のように、回転は曲げ角度の大きさに従って、各曲げ線軸の回りに行われる。並進操作は、幾何学データを空間の中で移したり、動かしたりすることによって行われる。このような並進操作は、曲げ半径、曲げ角度と各曲げの差引高にもとづいて決められる。折りたたみの際に、差引高補償は前述べたように曲げ線の各側で、面の寸法を差引高の半量だけ伸ばすか増やすことによって行われる。このような差引高補償は、曲げ機で曲げられる2-D薄板金属部品の寸法を、より正確に反映する部品の3-D表現を与える。
【０１６１】
幾何学的モデル化と変換のさらに進んだ情報は、たとえば、その明細を全般的に参照することによって本文書に明白に取り入れられているモルテンソン、マイケル  M著、幾何学的モデル化、ジョン・ワイリー&サンズ、ニューヨーク（1988年）及びフオリーら著、ジェイムス  システム・プログラミング・シリーズ：会話形コンピュータ・グラフイックスの基礎、アデイソン・ウエスリー出版、レデイング、マセチューセッツ（1983年）を見られたい。モルテンソンの8章には、並進と回転を含む幾何学的変換が論じられている（たとえば345-354頁参照）。さらにフオリーらは7章、245-265頁で、2-Dと3-D変換の行列表示を含む、幾何学的変換の情報を与えている。モデル化と幾何学的変換についての付加的情報は、その明細を全般的に参照することによって本文書に明白に取り入れられている、マンテイラ、マルッテイ著、ソリッドモデル化入門、コンピュータ・サイエンス出版社、ロックビル、メリーランド（1988年）にも与えられている。座標変換に関する情報は、マンテイラの365-367頁にある。
【０１６２】
次に図１９を参照しながら、本発明の別の見地に沿って、元の厚さぬきの3-D平面図にもとづいて2-Dモデルを作成するプロセスと操作について説明する。図１１を参照しながら前に説明した折りたたみプロセスと同様に、3-D図面を展開し、2-Dモデルを作成する色々なプロセスや操作は、サーバー・モジュール32にあるソフトウエアや/またはプログラム化論理を用いて実施できる。図１９に示されているように、顧客の仕様にもとづいて提供され作成された元の3-D図面は、ステップS.140でサーバー・モジュール32に入力されるか取り入れられる。3-D図面はDXFまたはIGESフアイルとして格納され、サーバー・モジュール32からCADまたはCAD/CAMシステムとインターフエイスするか、利用するかして入力できる。3-D図面を入力後、ステップS.142でサーバー・モジュール32によって、引き続き行われる面検出や他のプロセスのための図面の準備のために、自動トリミングとクリーンアップ操作が行われる。
【０１６３】
図１２-１４に関連して論じたように、自動トリミングとクリーンアップ機能は、部品の色々な面が適正に検出定義されされるように、構成要素や表面を切り離したり、連結したりする。
【０１６４】
図１１と１２、１３に関連した上記の自動トリミングとクリーンアップ操作は、図１９のステップS.140で入力した3-D図面の幾何学データに対しても、同じように適用できる。データを2-D空間で解析する（2-D平面図の場合のように）代わりに、3-D図面に図示されている各構成要素（たとえば線、弧等）は、図中の3-D座標と空間情報にもとづいて解析することができる。交点と開放交差領域は、各構成要素（エンティティ）を個別的に解析し、他の構成要素の一つ一つと比較することによって解析できる。ここでもまた、構成要素の終点や他の属性の基本的な幾何学的解析を用いて、許容度内で交点と開放交差領域を決めることができる。
【０１６５】
前記３次元図面に対しての自動トリミング及びクリーンアップ機能を実行した後、ステップＳ１４４で、前記板金パーツの面の各々を検出し定義するために面検出操作が行なわれる。前記３次元図面についての面検出は２次元空間における各面を分析し且つ検出し且つ上記と同様にしてループツリーを生成することにより行なわれる。面検出は任意の所定のエンティティで開始することにより実行される。例えば、一番左側のエンティティ（即ち最小のｘ座標を有するエンティティ）が最初のエンティティとして使用される。その後、１つの面は前記最初の線分エンティティ及び他の連結するまたは隣接する線エンティティ（即ち前記最初のエンティティと共通の端点を有する任意のエンティティ）を取出すことにより定義される。面検出操作は次に、図１５（ａ）−１６（ｄ）に関連して上記に説明したようにループ及びエンティティ解析を用いて行なわれる。各エンティティは前記定義された２次元平面内で検出されるため、種々の外側及び内側ループが定義され、且つ前記エンティティがマークされ（即ち前記選択されたエンティティのフラグを設定し或いは増加することにより）、それらが、前記面における複数のループの１つを定義する連結されたリストに選択され且つ含まれたことを示す。
【０１６６】
引き続くループ解析は、次に前記３次元図面を構成する他の２次元平面において行なわれる。前記他のエンティティのループ解析を行なうために、前記３次元図面内でのマークされてない或いは選択されてないエンティティを検索することにより追加の平面が定義される。そのような平面は、２つの選択されてないエンティティの間或いは選択されてないエンティティと以前に選択されたエンティティとの間に定義される。追加の２次元平面の各々において、更なるループ解析が行なわれ前記内側及び外側ループを検出する。再び連結されたエンティティの連結リストが保持され、前記複数のループ経路の各々が定義されるにつれて、前記選択されたエンティティがマークされる（即ち前記選択されたエンティティに付随するフラグを増加することにより）。
【０１６７】
全てのエンティティが検出された後、すでに解析された２次元平面の各々についてのループツリーを生成するために、結果の複数のループが使用される。すでに述べたように、ループツリーは、板金パーツにおける複数の面及び開口部及び穴を定義するために提供される。３次元の図面については、ループツリーは、前記板金パーツの各面について生成される。各面内で検出された複数のループは、各ループツリーを生成するためにグループ化され分析される。各ツリーのルーツ（根）は前記平面において検出された外側ループとして定義される。前記外側ループと共通のエンティティを有する前記平面の各内側ループは前記ツールの子供として定義される。共通エンティティの存在は、各ループを定義する連結されたエンティティのリストの分析及び比較に基づいて検出される。追加のエンティティ（即ち穴或いは開口部）が前記平面の内側ループにおいて検出される時、これらのループはそれらがその内部に存在する内側ループの子供（即ち前記ループツリーのルーツの孫）として定義される。生成された複数のループツリーは次に、前記３次元図面の全ての面を検出するために用いられる。検出された面は次に曲げグラフデータ構造におけるノード（節）として格納される。
【０１６８】
前記結果としての曲げグラフ構造はステップＳ１４６における曲げ線検出操作の実行の後、連結する曲げ線連結エージェントにより補足される。曲げ線検出操作及び最終曲げグラフ構造またはパーツ・トポロジーの生成は図１７及び１８を参照して上記したと同様のやり方で実行される。
【０１６９】
上記したように、前記曲げ線検出操作を実行するための代表的なコードがここに添付された付録Ｃに提供される。このサンプルコードは、２次元或いは３次元モデルに対してなされる曲げ線検出操作のための代表的実行例であり、曲げ線の最適選択を決定するためのヒューリスティック（例えば上記したような）を含む。前記曲げ線検出操作は、検出された曲げ線に満足しない時、サーバモジュール３２におけるオペレータが前記板金パーツのための好ましい曲げ線を選択的に指定することを許すマニュアル選択特性を含む。前記オペレータは、マウスあるいはキーボード等のごとき適宜の入力手段により曲げ線を維持し或いは変更することを指示する。前記オペレータにより選択され改定された曲げ線は最終的２次元パーツを生成するために用いられる。
【０１７０】
最終的曲げグラフ構造の複数の曲げ線を中心とする展開工程を実行する前に、ユーザは、ステップＳ１４８でＶ幅、材料タイプ及びまたは縮小量について促される。上記したように、板金は折り曲げられる時伸びる傾向を有するため、３次元パーツの寸法は前記２次元平面パーツのそれより少し大きい。従って、板金パーツの展開の過程で、パーツの寸法は、選択された材料タイプ及びＶ幅に基づく縮小量だけ縮み或いは減少される。従ってこの発明の１つの側面によれば、３次元モデルを展開する際、前記２次元モデル及びその表面の各々の寸法をより正確に生成するために縮小操作が行なわれる。上記したように、前記縮小量は、前記ユーザにより直接入力され或いは所望のＶ幅及び曲げ角度を選択することによりユーザが自動的に前記縮小量を設定することができるように、材料テーブルが表示される。
【０１７１】
前記オペレータにより入力される前記縮小量は前記パーツ幾何学データにより表現されるそれと同じ長さの単位（例えばミリメートル）である（或いはオペレータによる入力の後その単位に変換される）。展開操作の間に、前記曲げ線の両側の面の各々の寸法長さは前記所定の曲げ線について入力された縮小量の半分だけ減少される。前記曲げ線に直交する前記面の寸法長さは前記曲げ線の両側に位置する前記面の境界を定義するエンティティの終点を減少することにより減少される。前記縮小補償は、各曲げについて前記オペレータにより提供される前記縮小量に基づいて、前記パーツの他の曲げ線のそれぞれにおいて行なわれる。
【０１７２】
前記全ての必要なデータの入力の後、ステップＳ１５０で、前記２次元モデルを生成するために展開プロセスが行なわれる。前記３次元曲げモデルを展開するために通常の方法が用いられ、それは前記複数の曲げ線の各々を回転軸として用いるマトリックス変換の使用を含む。この展開プロセスの間に各曲げ角度が測定され、前記平面曲げモデルを生成するために前記曲げ角度量だけ前記パーツは展開される。更に、前記入力された縮小量に基づいて、前記板金材料の物理的性質及び前記３次元及び２次元モデルの間の差をより正確にシミュレートするために、前記曲げ線の両側で前記縮小量の半分だけの前記面の寸法の縮小或いは減少が行なわれる。
【０１７３】
ステップＳ１５０で前記展開工程を実行する時、前記パーツの寸法及びトポロジーデータ（または曲げグラフ構造）が前記曲げパラメータ（例えば曲げ角度、内側半径等）と共に用いられる。前記３次元空間において表現された前記パーツにおける各面及び曲げ線及び穴及び成形部についての変換マトリックスが計算される。通常のマトリックス変換が前記２次元空間データを得るために前記３次元データに対して適用される。前記変換は一般的に回転を含み、その後に並進がくる。上記したように、回転は、曲げ角度量に応じて各曲げ線の周りに行なわれる。展開のために、２つの面の間に１８０°が存在するまで（即ち面が平面になるまで）回転は逆方向に行なわれる。並進は空間内で前記幾何学的データをシフトし移動するために行なわれる。そのような並進は、各曲げについての前記曲げ半径及び曲げ角度及び縮小量に基づいて決定される。展開の間、縮小補償は上記したように、曲げ線の両側で前記縮小量の半分だけ前記複数の面の寸法を縮め或いは減少せしめるために行なわれる。そのような縮小補償はそれが曲げ工程の間に折り曲げられる前の前記板金パーツの寸法をより正確に反映する前記パーツの２次元表示を提供する。
【０１７４】
再び幾何学的モデル化及び変換についての情報はモルテンソン、フォリー等及びマンティラに見出される。上記したように、モルテンソンの８章は変換及び回転（例えば３４５〜３５４頁を見よ）を含む幾何学的変換の議論を提供する。更にフォリー等は、７章の２４５〜２６５頁で２次元及び３次元変換のマトリックス表示を含む幾何学的変換についての情報を提供する。更に座標変換についての情報はマンティラの３６５頁〜３６７頁に見出される。
【０１７５】
図４を参照して上記したように、前記顧客の注文に基づいて、２次元３面図或いは厚さを有しない３次元ワイヤフレーム図が最初に提供され或いは生成される場合、厚さを有しない３次元モデルを生成するために更なる工程が必要とされる。そしてその後、前記厚さを有しない生成された３次元モデルは展開プロセス或いはアルゴリズムを適用することにより２次元モデルを生成するために用いられる。図２０−２４は、最初の２次元３面図に基づいて３次元モデルを生成するために適用される種々のプロセス或いは操作を図示する。更に図２５は、この発明の他の側面に応じて、厚さを有する最初の３次元ワイヤフレーム図から厚さを有しない３次元モデルを生成するために適用される追加のプロセス或いは操作を図示する。再び、図２０−２５において図示される種々のプロセス及び操作は、例えば前記サーバモジュール３２に存在するソフトウエア及びまたはプログラム論理により実行される。
【０１７６】
図２０を参照するに、この発明の教示に応じて、最初の２次元３面図に基づいて３次元モデル（厚さを有しない）を生成するために行なわれる操作或いはプロセスの論理フローの記載が提供される。最初、ステップＳ１６０で２次元３面図がサーバモジュール３２へ入力され或いは搬入される。前記最初の２次元３面図は、前記パーツの種々の図（例えば正面図及び平面図及び右側面図、例えば図２２（ａ）及び２２（ｂ）を見よ）を含み、前記サーバモジュール３２へダウンロードされ或いは搬入されるＤＸＦ或いはＩＧＥＳファイルのごときＣＡＤ図面である。しかる後、ステップＳ１６２で、前記３次元モデルへの引き続く操作のための図面を作成するために、サーバモジュール３２により２次元クリーンアップ操作が行なわれる。この２次元クリーンアップ操作は、前記パーツの実際の幾何学形状を表現しない余分な及び非幾何学的な情報、それはテキスト及び中心線及び寸法線を含む、を消去するために行なわれる。前記２次元クリーンアップ操作はまた全ての外側線分を、例えばそれらの接続端部で接続し、或いは任意の交差するライン或いはエンティティを分断し或いはトリミングするために行なわれる。図２１は、前記サーバモジュール３２により前記クリーンアップ操作が行なわれる際実行される種々のプロセスの論理フローの例を図示する。
【０１７７】
図２１に示されるように、最初に２次元図面が前記サーバモジュール３２により、ステップＳ１８０でデータファイルから読み取られ或いはロードされる。しかる後ステップＳ１８２でサーバモジュールは、２次元図面において各々のエンティティ或いは幾何学データを分析し次の工程のための図面を作成するために種々のエンティティを分割する。ステップＳ１８２において行なわれる前記分割或いはトリミング機能は、この発明の前記自動トリミング及びクリーンアップ機能に関連して上記に記載したと同様な方法で実行される。従ってステップＳ１８２で前記２次元３面図における全ての幾何学的データは、エンティティの交差点及び所定の誤差範囲内にある空白（開放）交差部を検出するために分析される。任意の交差線は分断され、結果のエンティティは交差点により定義される共通の終点で出会う。更に所定の誤差の範囲内にある（例えば０．０−０．０１ｍｍ或いは０．０−０．００１インチ）空白交差領域を有するエンティティについてはそれらのエンティティは、例えば図１２―１４に関連して上で記載されたと同様の方法で結合される。
【０１７８】
ステップＳ１８４で前記２次元図面シートの周辺が検索され任意の外部の線分またはデータ（例えば境界線分及び座標格子及び数字等）が消去される。図２２（ａ）に示されるように２次元３面図は、しばしば図面シート上に提供される。前記図面シートは前記板金パーツの種々の図面を生成するために必要でない余分な及び非幾何学的な情報を含む。従ってステップＳ１８４で、本発明の２次元クリーンアッププロセスを利用して、前記３次元モデルを展開するにあたってこのタイプの情報が検出され前記２次元図面から消去される。
【０１７９】
前記２次元図面データはそこに含まれるデータのタイプ（例えば幾何学的或いは非幾何学的／テキスト）を指示するためのキーワード或いはタイプフィールドを含む。従ってこれらのキーワードあるいはタイプフィールド（それらは図面ファイルのデータフォーマットに基づいて提供される）はテキスト或いは他の非幾何学的データのごとき種々の余分の情報を削除するために用いられる。しかし全ての不必要な図面シートデータを正しく削除するためには更なる操作が通常必要である。しばしば、前記境界線或いは他の外側情報はエンティティー（例えば線分等）として保存され、それらは前記データキーワード或いはタイプフィールドに基づいて容易に識別することができない。従ってこの発明の１つの側面によれば、前記２次元図面のデータを分析する際に連結性グラフ構造が生成される。この連結性グラフ構造は各エンティティーについて複数の付随的頂点のリスト及び連結されたエンティティーのリストを示す。各頂点については、隣接する複数の頂点のリスト及びそれが付随するところのエンティティーのリストが提供される。このグラフ構造により、（それはステップＳ１８２の分断及びトリミング機能を実行する際に生成されるが）、どのエンティティーがくっつき合う終点により結合されるかが決定される。結果として、境界線及び情報ボックス及び他の非幾何学的データのような余分なデータは削除される。これは、このデータは典型的に連結されたエンティティーで構成されることがなくまたそれを含まないからである。
【０１８０】
上記したように、２次元３面図は寸法線及び矢印線及び中心線及びテキストのような余分の情報を含み、それらは前記パーツの実際の幾何学形状を表現しない。これらのエンティティーはステップＳ１８６で検出され、次の工程のための２次元図面を作成するために前記２次元データファイルから削除される。これらの余分のエンティティーの検出はサーバモジュール３２により自動的に行なわれる（例えば前記パーツの実際の幾何学形状に関連しない２次元データファイル中の項目を検出することにより）。例えば、前記連結性データグラフ構造を用いて、両端が開放されたエンティティー（例えばテキストにアンダーラインをするため或いは寸法或いはパーツの中心線を示すために用いられる複数の線）が検出され消去される。矢印のごとき他のエンティティーもまた、浮動する終点或いはそのようなエンティティーの他の特徴の存在に基づいて検出される。全ての不必要なデータを効果的に削除するために、サーバモジュール３２は前記２次元図面中のいずれの項目が消去されるべきかを（例えばマウスまたはキーボードにより）オペレータをして指示することができるようにするためのマニュアル編集機能を提供する。オペレータのこの援助或いは確認により、追加の余分の情報が図面から除去される。
【０１８１】
ステップＳ１８６の後、前記２次元図面の種々の図が、ステップＳ１８８でグループ化され且つそれぞれ定義される。この発明の１つの側面によれば、サーバモジュール３２は、図２２（ｂ）及び２３（ａ）に示されるような平面図（上面図）及び正面図、右側面の配置のごとき、予め定められた或いは標準的な図と向きをサポートする。平面図及び正面或いは背面図及び右或いは左図のような他の図及びレイアウトもまたサポートされ得る。更に以下に記載されるように、サーバモジュール３２はまた前記２次元図面の図を前記パーツの３次元表現へ加工するために、回転された図（例えば図２３（ａ）を見よ）もサポートする。いずれにしても、パーツの３次元モデルが構成されるためには、厚さ表現を有するパーツの少なくとも２つ（そして好ましくは３つ）の異なる図が提供される必要がある。連結性グラフ構造において前記エンティティーの連結性及びグループ化を解析することにより、サーバモジュール３２は、複数の図の各々の相対的位置及び／又は座標位置に基づいて前記複数の図を分類し且つ定義する。
【０１８２】
限定しない事例として、サーバモジュール３２による前記図の定義は、予め定義された或いは通常の配置或いは前記データファイルにおける図の解析をするためのレイアウトにより、及び／又は前記複数の図の向きの検出及び前記図面の各々の図のそれぞれにおける前記パーツの種々の寸法の重ね合わせに基づいて実行される。図２３（ｂ）において示されるそれのごとき予め定義された或いは標準的フォームは、潜在的な図のタイプに応じて前記図の各々を決定し定義するために用いられる。種々の終点及び各グループを定義する複数のエンティティーの間の関係の幾何学的比較は、前記ステップＳ１８８を実行するために行なわれる。サーバモジュール３２の図検出特性（図検出機能）は、複数の潜在的図面タイプ（例えば平面図、正面図、背面図、左図、右図）の１つに応じて前記図面の各々にラベルを付ける。前記複数の図の各々の検出は、予め定義された或いは標準的図の配置或いは形状及び存在する図の各々の間の検出された関係に基づく。種々の工程或いは操作が、ステップＳ１８８で、前記２次元３面図における複数の図を分類し且つ定義するために使用される。例えば前記加工された２次元３面図にアクセスした後、前記サーバモジュール３２はまずこの図面データにおけるパーツの平面図を特定する。前記平面図は、予め定義された或いは標準的な形状または図配置（例えば図２３（ｂ）におけるそれのような）に基づいて検出される。仮に３つの異なる図が水平方向或いは垂直方向において検出される場合には、中央の図が平面図であると定義される。更に仮に３つの別個の図が検出されず且つ垂直方向においてただ２つの別個の図が検出される場合には、上側の図が平面図であると定義される。再び前記連結性グラフ構造における前記エンティティーの連結性及びグループ化が前記複数の図の各々を検出するために使用される。前記予め定義された或いは標準的形態を表現する、格納されたルックアップテーブル或いはマトリックスが前記２次元図面の各図を比較し且つ複数の図の各々を検出するために用いられる。
【０１８３】
前記２次元３面図データから平面図を検出した後、前記パーツの他の図は前記検出された平面図に対する前記複数の図の各々の相対的位置に基づいて検出される。例えば、図２３（ｂ）の標準的レイアウトに基づいて、例えば図グループが前記平面図の上に位置している場合には、その図は背面図であると定義される。しかしもし図グループが前記平面図の下に位置している場合には、その図は前記パーツの正面図であると定義される。更に右図及び左図は、前記平面図のそれぞれ対応する右側及び左側におけるそれらの相対的位置に基づいて検出される。しかる後、前記標準的形態（例えば図２３（ｂ））に合致しない任意の残りの図は前記検出された図（例えば検出された背面図或いは正面図）に対するそれらの相対的位置に基づいて検出される。例えば図２３（ａ）に示されるレイアウトＢについて、前記右図は前記平面図に対して回転された位置に設けてある。しかしながらレイアウトＢにおける右図は前記検出された正面図に対するその関係に基づいて検出される。即ち検出された背面図或いは正面図の右側或いは左側に存在する検出されていない図はそれぞれ前記パーツの右図或いは左図として定義される。
【０１８４】
種々の予め定義された或いは標準的な図のレイアウトが前記２次元３面図図面において複数の図を検出し且つ定義するために用いられる。標準的な形態（例えば図２３（ｂ）または図２３（ａ）におけるそれ）は、製造設備において広く行き渡っており或いは選択され／要求される図レイアウトに基づいて、及び／又はサポートされている図タイプの基づいて選択される。仮にいずれの図も検出されない場合には、サーバモジュールにより警告信号が提供され、オペレータは、好ましい図面レイアウトに応じて前記２次元３面図データを変形したり、他の適当な動作を行なう。前記２次元図面における複数の図を検出するための予め定められた或いは標準的形態の提供に加えて、予め定められた標準的形態（例えば図２３（ａ）のレイアウトＡのように）は検出された図を加工し前記パーツの３次元モデルを生成するために設けられる。従って更なる加工が行なわれる前に前記標準的形態に基づいて検出された図を正しく分類するために、回転された図の特徴が提供される。
【０１８５】
上記したように、前記２次元クリーンアップ操作は図面において複数の図を検出するための予め定められた、或いは標準的形態に合致しない回転された複数の図をサポートし且つ検出する。回転された図のオプションでは、検出された標準的でない複数の図は、パーツの３次元モデルを加工し且つ生成するために、前記複数の図の各々が前記予め定められた或いは標準的な図の形態に合致するように、回転され或いは並行移動される。前記パーツの複数の図を検出するために図２３（ｂ）に図示されるそれのような標準的形態を仮定して、図２３（ａ）におけるレイアウトＢにおける複数の図の各々は、上記したように、前記平面図及び他の検出された図に対する当該複数の図の相対的な位置に基づいて検出される。例えば仮に図２３（ａ）のレイアウトＡが、平面図及び正面図及び右図を有する２次元図面における種々の図を加工するための予め定められた或いは標準的図レイアウトとして使用される場合、ステップＳ１８８でレイアウトＢにおける右図は９０度回転されレイアウトＡと同様な、前記パーツの変形された図レイアウトを提供する。前記パーツの右図が前記パーツの平面図の右側に位置するように前記レイアウトＢにおいて右図を９０度回転することにより、図面中の前記複数の図はレイアウトＡで表現される標準的な形態に応じて加工される。格納されたルックアップテーブル或いは予め定められた或いは標準的な形態を表現するマトリックスが、前記２次元図面の複数の図を比較し且つどの図が回転或いは並進運動を必要とするかを決定するために用いられる。
【０１８６】
前記２次元図面における複数の図から前記パーツの正確な３次元モデルが生成されることを保証するために、前記複数の図の各々においてそれぞれの寸法が相互に矛盾がないか或いは一致しているかチェックされる。図２１において更に示されるようにステップＳ１９０で前記データファイルにおける前記複数の図の境界が、それぞれの図の全ての寸法が相互に同じ寸法であるかを確認するために検出される。仮に複数の図が所定の誤差の範囲内で（例えば０．０−０．０１インチ）一致しないことが判断されるとステップＳ１９０で、全ての複数の図が同じスケールになるように任意の特定の図の寸法を変更するために適宜の修正が行なわれる。図面の寸法が相互に一致せず現在存在する２次元図面データに対して必要な修正が行なわれるようにユーザに警告するためにサーバモジュール３２に警報要素が設けられる。
【０１８７】
前記パーツの各々の図における寸法の一貫性を検出し且つ確認するために種々の操作或いは工程が使用される。例えば、前記複数の図の各々の対応する寸法が、それらが相互に所定の誤差の範囲内にあるかどうかを決定するために比較される。そのような解析は、前記パーツの各図の境界線を定義する線分エンティティーを比較することを含む。図２３（ｂ）における標準的な形態を仮定して以下のようであれば平面図は右図または左図と一致すると検出される。即ちそれぞれの図について、最大Ｙ座標位置と最小Ｙ座標位置が所定の誤差範囲（例えば０．０−０．０１インチ）内にある。更に前記平面図は、以下の場合には正面図または背面図と一致すると検出される。即ち各図について、最大Ｘ座標位置と最小Ｘ座標位置とが所定の誤差範囲（例えば０．０−０．０１インチ）内にある。更に左図または右図は、最大Ｙ座標位置と最小Ｙ座標位置との間の差に比較して最大Ｘ座標位置と最小Ｘ座標位置との差が所定の誤差範囲（例えば０．０−０．０１インチ）内にあれば正面図または背面図と一致すると決定される。再び前記図の寸法或いは関連する面の寸法が一致しないとき前記２次元図面データに対して必要な修正が加えられるようにユーザに警告するように、サーバモジュール３２に警告要素或いはモジュールが設けられる。
【０１８８】
最後にステップＳ１９２で、本発明の面検出方法の教示に基づいて、前記パーツの内側ループ及び穴及び形状が検出される。各図の複数の面の内側に設けられている種々の穴或いは形状は、前記パーツの種々の線及び境界を通ってパーツの外側から中央へ向かってループを形成していくことにより検出される。ループ及びエンティティーの分析は、前記２次元図面における前記パーツの各図に対してなされる。前記パーツの外側から作用的に中央へ向かって内側へ各々の図を分析することにより、検出されたループは前記パーツの物質と開口部の境界及び領域を、周期的順番（即ち物質、開口部、物質等）に基づいて決定する。図１６（ｄ）におけるそれのごときループツリーが複数の面の位置及び各々の面の内部の任意の穴の位置を決定するために各図面について生成される。浮遊する円弧或いは線分のごとき前記パーツの面の内部で連結されないエンティティーは、ステップＳ１９２の中で検出され消去される。
【０１８９】
本発明の前記２次元クリーンアップ操作を行なうための代表的なコードは付録Ｄに提供される。このコードはＣ＋＋プログラム言語で記載されており、そこに使用される論理及びアルゴリズムの解析を円滑にするためのコメントを含む。そのコードは、図２１−２２（ｂ）を参照して上で議論したそれらのごとき、２次元クリーンアップモードの種々の工程及び操作を含む。
【０１９０】
図２０を再び参照するに、２次元クリーンアップ操作が行なわれた後論理フローはステップＳ１６４へ連続しそこで前記２次元図面が材料の厚さを表現しまたは含むか否か（即ち前記２次元図面が厚さを有するか否か）が決定される。もし前記２次元図面が厚さの量を含むと判断される場合には、ステップＳ１６６で３次元モデルへの引き続く操作のための２次元図面を作成するためにサーバモジュール３２により厚さ消去手続きが行なわれる。前記２次元図面における厚さの存在の判断は図面のデータに基づいてサーバモジュール３２により自動的に行なわれ、或いはオペレータからの援助或いは応答を介して前記サーバモジュールにより行なわれる（オペレータは厚さ除去が必要であるか或いは好ましいかを指示するように促される）。前記パーツの厚さは全ての板金パーツの独特の対称性により消去される。前記パーツの厚さを消去することにより、厚さを有しない、結果としての板金パーツは板金オペレータ或いは設計者により、より容易に分析される。更にこの出願の発明者は、前記２次元３面図の厚さを除去することにより、２次元図面を変換し３次元モデルを生成するに必要な時間が著しく短縮されることを見出した。
【０１９１】
殆どの２次元３面図は材料厚さ量を含むため、オペレータはしばしば、２次元図面から３次元モデルを作成するためにいずれの曲げ線が選択されなければならないかで混乱する。結果として、２次元３面図が３次元モデルへ変換されるように適切な曲げ線を選択する際に相当の時間が無駄になる。厚さを有する２次元３面図の例が図２４に示されている。この発明の１つの側面によれば、材質厚さを持つことなく表現され且つ処理されるが、当該材質厚さ量及び前記パーツの内側及び外側寸法を曲げモデルデータ中に保有する簡単化された２次元３面図モデルを表示するように、厚さ除去手続きが設けられている。図２４（ｂ）は前記厚さ除去工程を行なった後、前記サーバモジュール３２において前記オペレータに対して観察され且つ表示される簡単化された２次元３面図を図示する。
【０１９２】
前記厚さ除去手続きが実行される時、ユーザは、２次元３面図表示における材質厚さを特定するように促されてもよく、また前記表示内においていずれの寸法（即ち外側寸法或いは内側寸法）が保持されるべきであるかを特定するように促されても良い。オペレータは、例えばマウスを用いて複数の図の中の１つにおいて保持される厚さ及び表面を指示する。このユーザにより入力されたデータに基づいて、サーバモジュール３２は前記２次元３面図を修正し、ユーザにより指示された材料厚さを消去し、前記オペレータの選択に基づいて内側或いは外側寸法を残す。
【０１９３】
前記２次元３面図図面において厚さを消去するために、前記サーバモジュール３２は前記オペレータにより行なわれた選択に基づいて前記３つの図の各々を分析する。選択された表面は幾何学的計算により（即ち選択されたエンティティー線分或いは表面と同じＸ座標或いはＹ座標射影に存在する対応するエンティティーを検出することにより）他の図の１つへ射影され、前記複数の図の各々における対応するエンティティー及び線分を検出する。対応するエンティティーは、マークされ且つ保持され、合致しないエンティティー或いは表面は削除され或いは図２４（ｂ）に示されるそれのように、スクリーン上に表示されない。更にオペレータにより指示される厚さ寸法線は他の図の各々へ同様に射影され、合致する厚さ寸法線或いはエンティティーは図２４（ｂ）の例に更に示されるように削除される。結果として、図面内の複数の図の各々は適宜に修正され、前記サーバモジュール３２においてユーザに対して表示される。厚さを有しない、結果としての２次元３面図は前記パーツの３次元モデルを生成するために次の工程で使用される。
【０１９４】
この発明の厚さ削除手続は、各図において削除されるべき厚さ線及び残されるべき表面エンティティーをオペレータが選択的に指示するようにするためのマニュアル厚さ消去モードを含む。表示された図の各々においてどの領域が削除されるべきであり、どの表面が残されるべきであるかを指示するためにマウス或いは他の適当な入力装置がオペレータにより使用される。前記オペレータにより入力されるデータに基づいて前記サーバモジュール３２は、厚さを有しない図面を提供するために、前記２次元３面図からオペレータにより選択される各線分エンティティーを削除する。
【０１９５】
この発明はまた全ての厚さ表現が前記２次元３面図図面において正しく特定されたか否かを分析し且つ検出し且つ、マークされない厚さ要素が存在する時及び／又は図面データ中に矛盾が存在する時、ユーザに警告するための警告システム或いはモジュールを含む。例えば厚さ警告要素は、前記表示スクリーン上で潜在的なマークされない厚さ部分を強調するために設けられ、面警告要素は面の寸法が他の図における厚さのマークと一致しない時、前記スクリーン上で潜在的な一致しない面を強調するために設けられる。曲げ線警告要素は、また矛盾する曲げ線を強調し及び一致しない厚さ曲線を強調するために設けられる。曲線は、この曲線上に射影される少なくとも１つの曲げ線が２つの横断厚さ線分（厚み横断線）により挟まれないとき強調される。例えば図２４（ｃ）は、２つ或いは他の零でない偶数の横断厚さ線分（即ち各図において厚さを横断する短い線）により正しく挟まれている厚さ曲線を図示する。各曲げ線は２つ又は他の零でない偶数の横断厚さ線分により挟まれるべきである。各図面における前記パーツのこれらのエンティティーの分析は、ループ分析を実行し且つ各図を作り上げる線分及び円弧エンティティーの連結性を解析することに基づく。開放された厚さ線分は他の厚さ線分或いは曲線と接続しない少なくとも１つの端点を有する厚さ線分に基づいて定義される。１つの開放厚さ線分を含むサイドは開放厚さサイドと定義される。厚さ線分は、開放厚さ線分の開放厚さサイドが最小ループの境界ボックスに一致しない場合に強調される。前記加工された２次元３面図の像に関連する警告をユーザに与えることにより、ユーザは図面データ中の矛盾を警告され、ユーザはパーツの３次元モデルを生成するために更に加工を行なう前に、前記図面データを修正及び／又は訂正することができる。そのような警告システム及びユーザとの相互作用を含むことが３次元モデルによる前記パーツの表現の精密さを改善する。
【０１９６】
図２０のステップＳ１６８で、厚さを有しない加工された２次元３面図図面は３次元モデルへ変換され発展させられる。２次元３面図図面から前記３次元モデルへの変換及び展開は良く知られ或いは確立された射影及び／又は突出方法を用いて行なわれる。例えば前記２次元３面図から３次元モデルを生成するために、各図の深さが検出され３次元モデルを展開するために各図が射影される。結果としての３次元モデルは次に曲げモデルデータを生成する際に使用され、また上記した展開アルゴリズムを適用することにより単一の２次元平面図へ変換される。幾何学的モデル化技術についての更なる情報については、モルテンソン、フォリー等及びマンティラを見よ。２次元図面から３次元モデルを構成するための射影技術についての追加の情報については例えば以下を見よ。ウェズレイ等，Ｗ．Ａ．「投影図の肉付け」Ｉ．Ｂ．Ｍ．Ｊ，ＲＥＳ，ＤＥＶＥＬＯＰ、２５巻、ＮＯ．６、９３４―９５４頁（１９８１）、アオムラ・シゲル、「機械的図面を用いてソリッドモデルを形成すること」第６回コンピュータメカニクスコンファレンス、ＪＳＭＥ、ＮＯ．９３０−７１、日本、４９７−９８頁（１９９３）、アオムラ・シゲル、研究及び実際使用の最近の傾向及び将来の可能性（図面から３次元モデルの自動的再構成）東京工学株式会社、日本、６−１３頁（１９９５）。これらの開示はここにそれらの全てにおいて明示的に取り込まれる。
【０１９７】
ステップＳ１６８で３次元モデルを展開する際、結果としての３次元モデルを更に加工し且つ精密化するために追加のクリーンアップ工程が含まれる。この発明の１つの側面によれば、３次元クリーンアップ工程は、前記パーツの２次元３面図において存在し且つ前記パーツの生成された３次元表現において余計な或いは過剰な情報を生成する不明瞭さを補償するために設けられる。当業者に理解されるように、パーツの２次元３面図表現は３次元座標空間における前記パーツの種々の特徴の表現に関連して不明瞭さを含む。前記２次元３面図から３次元モデルを生成する際余計な且つ過剰な情報がこれらの不明瞭さの結果として生成される。従ってこの発明の側面によれば、前記３次元クリーンアップ工程は、１つの端部がつながっていない線分を検出し且つ除去すると共に曲げ線を検出し且つきれいにすると共に面をトリミングする工程を含む。前記３次元クリーンアッププロセスは前記パーツの結果としての３次元モデルを生成する際に自動的に行なわれ或いは前記生成された３次元モデルが追加の工程を要求すると判断される時、オペレータからの入力に基づいて選択的に行なわれる。
【０１９８】
前記３次元クリーンアップ工程によれば、前記生成された３次元図面データを分析することにより、一端部において他のエンティティーと接続されないと判断される全ての線分或いは曲線が特定され片側開放線分として定義される。片側開放線分であると判断される任意のエンティティーは前記パーツの３次元表現から除去される。一旦開放線分が除去されると、それは他の線分或いはエンティティーが開放されることを導くかもしれない。従って新しい片側開放線分がまた特定され、全ての開放線分或いはエンティティーが除去されるまで、繰り返し除去される。図６３は片側開放線分が除去される前のパーツの３次元表現の例を図示し、図６４は片側開放線分が前記３次元表現から除去された後の前記パーツを図示する。
【０１９９】
上記したように、ステップＳ１６８で行なわれる３次元クリーンアップ工程は曲げ線を検出しきれいにする工程も含む。曲げ線は、３次元空間におけるパーツの面情報の検出を促進するために特定され且つきれいにされる（例えばモールド線分を加えることにより）。前記生成された３次元モデルデータに基づいて、各曲げ線は、それぞれの中心により定義される同一の法線を有する一対の３次元曲線（例えばそれは図面データにおける曲線エンティティーにより表現される）の検出に基づいて同定される。この過程において、特定された前記曲げ線に対してモールド（形取り）線分が付加される。前記モールド線分は、３次元曲線の各対において対応する終点を特定し且つ前記３次元曲線の対応する終点の間でモールド線分（例えば線分エンティティーで表現される）を延長することにより追加される。図６５は曲げ線が特定される前のパーツの代表的３次元表示を図示し図６６は前記モールド線分（図において破線で表現される）が追加された後のパーツを図示する。
【０２００】
曲げ線が特定され且つモールド線分が追加された後、３次元クリーンアップ工程は更に前記パーツの全ての曲げ線をきれいにし且つ面をトリミングするために前記パーツの３次元表現を加工する。前記２次元３面図データの図における頻繁に生ずる不明瞭さにより、前記パーツの３次元表現に前記面の過剰な部分が生成される。前記３次元クリーンアップ工程は前記面の過剰な部分を特定しそして板金領域知識（例えば何が折り畳めないかについての知識）を用いて前記面をトリミングする。余分な穴或いは開口部のような他の余分な情報も特定され除去される。結果として前記パーツの過剰な部分は除去され前記３次元表現は前記板金パーツのより精密な表現を提供する。図６７は前記曲げ線をきれいにし且つ前記面をトリミングする前のパーツの代表的な部分を図示し、図６８は正常化及びトリミングがなされた後のパーツの前記部分を示す。
【０２０１】
図２５は材料厚さを持つ最初の３次元図面から材料厚さを持たない３次元図面を生成するためになされる工程及び操作の論理フローの例を示す。ステップＳ２００で、材料厚さを有する最初の３次元図面が入力されサーバモジュール３２へ搬入される。前記３次元モデルは材料厚さを有する３次元のワイヤフレーム図面で、ＤＸＦ或いはＩＧＥＳファイルのごときＣＡＤ図面ファイルである。前記３次元図面が前記サーバモジュール３２へ搬入された後、厚さ除去工程がステップＳ２０４で行なわれる。ステップＳ２０４における前記３次元モデルに対する厚さ除去工程は上記したアマダＵＮＦＯＬＤソフトウエア・システムにおいて提供されると同じ方法で行なわれる。前記３次元モデルにおいて厚さを消去するために、オペレータはまず厚さを指示し且つ残される面を選択するように促される。このオペレータの選択に基づいて厚さを定義するエンティティー線分の終点を解析することにより厚さが測定される。しかる後、選択された表面の境界が、前記ループ及びエンティティー解析工程に関連して上記したと類似の方法により探索される。そして保持されるエンティティーはマークされ（例えばフラグを設定し或いは増加することにより）、対応する厚さエンティティーは除去される。前記３次元パーツのエンティティーを探索する際、前記エンティティーは、ユーザにより選択された厚さエンティティーの長さに基づいて識別される。一般的に前記厚さエンティティーと同じ長さを有する全てのエンティティーは選択されず除去され、同じ長さでない他のエンティティーがマークされ残される。前記３次元パーツの表面の探索でマークされなかった残りのエンティティーもまた除去されることがある。再びサーバモジュール３２はマニュアル厚さ除去モードを提供し、そこではオペレータは除去されるべき３次元パーツにおける各エンティティーを手動で指示する。
【０２０２】
ステップＳ２０４の後、厚さを有しない、結果としての３次元モデルがステップＳ２０６で展開され及び／又はオペレータに対して表示される。展開アルゴリズム或いは工程が次にその材料厚さを有しない３次元モデルに適用され上に詳細に説明したように、曲げモデルデータについての単一の２次元平面図を生成する。上記したように前記データベース３０に格納されるデザイン及び製造情報は、板金要素についての製造データのみならず板金の幾何学形状及びトポロジーを含む曲げモデル・データファイルを含む。更にこの発明の種々の特徴を実行するために使用されるソフトウエアはＣ＋＋のごとき高度のプログラム言語を用い且つオブジェクト指向プログラム技術を用いて生成される。この発明の種々の特徴を実行するためには、Ｂｏｏｃｈ或いはＯＭＴのごとき異なるオブジェクト指向技術も使用される。オブジェクト指向プログラムが使用される場合は、前記板金パーツを表現するためにオブジェクト指向データが使用され、前記パーツのための曲げモデルは完全に自己充足的クラス・ライブラリを介して実行される。この発明の１つの側面により、オブジェクト指向プログラム技術に基づく、前記曲げモデルのための代表的データ構造及びアクセス・アルゴリズムの記述が提供される。図２６は、本願発明をオブジェクト指向プログラムにより実行する際使用される前記曲げモデルの代表的データ構造及びアクセスアルゴリズムを図示する。オブジェクト指向プログラムは、データを含む複数のオブジェクト或いはモジュールのみならずそのデータに作用する複数の指示を結合することにより現実世界をモデル化することができるソフトウエア展開の１つのタイプ或いは形態である。オブジェクト指向プログラムにおいては、オブジェクトは板金パーツのごとき、何か物理的なものをモデル化するソフトウエアエンティティーであり、或いはそれらはビジネス上の商取引のごとき仮想的な何かをモデル化するものである。オブジェクトはそのオブジェクトの状態を集合的に定義する１つもしくはそれ以上の属性（即ちフィールド）を含み、且つ全ての他のオブジェクトからそれを識別するための識別子を含む。更にオブジェクトはある種の条件の存在に基づいて、前記属性を修正し或いは前記オブジェクトに対して作用をなす一群の方法（即ち手続き）により定義される振る舞いを含む。
【０２０３】
この発明の実施例によれば、前記板金パーツはオブジェクト指向データモデルとして表現される。図２６に示されるように板金パーツの曲げモデルは完全に自己充足的なクラスライブラリとして定義される。前記板金パーツのための全ての要求されるデータ操作及び機能（例えば折曲げ、展開等）はこのクラスライブラリの要素機能として取り込まれる。全ての幾何学的或いはトポロジーデータは前記曲げモデルの中で分類される複数のオブジェクトの内部で定義される。前記曲げモデルクラスライブラリは複数のクラス或いはオブジェクトの階層であり、パーツクラスはその階層の最上レベルのクラスである。前記パーツクラスは種々のパーツ属性を有するパーツオブジェクトを含み、前記パーツ及び前記パーツに対してなされる複数の作用を定義する種々のオブジェクトを含む。
【０２０４】
図２６は、前記曲げモデルクラスライブラリにおいて分類される種々のオブジェクトの例を示す。例えば種々の属性５２を含むパーツクラス５０が提供される。前記パーツ属性５２はパーツ番号及び／又は名前、パーツ材料タイプ及びパーツの厚さのごとき種々のパーツ情報を含む。前記属性５２はまた、複数の曲げがなされる順番を指示するための曲げ順情報及び前記パーツの種々の寸法についての誤差要求のごとき他の製造情報を含む。前記パーツクラス５０はまた図２６に示されるように面オブジェクト５４、穴オブジェクト５６、成形部オブジェクト５８、及び曲げ線オブジェクト６０のごとき種々のオブジェクトを含む。前記オブジェクト５４，５６，５８及び６０の各々はそこに表現されたエンティティー（例えば面、穴、成形部、及び曲げ線）の各々についての一群のオブジェクトからなる。前記面オブジェクト５４、穴オブジェクト５６、成形部オブジェクト５８、及び曲げ線オブジェクト６０はそれぞれ幾何学形状及び寸法データ、２次元及び３次元空間表現における位置及び座標データ、及び前記パーツのそれらの各エンティティー（例えば面、穴、成形部、及び曲げ線）の端及び表面に関連するデータを含む。例えば、前記面オブジェクト５４は、前記複数の面の各々についての幾何学形状及び寸法データ、２次元及び３次元表現における前記複数の面の空間位置データ、及び前記複数の面の端及び表面についての端及び表面データを含む。更に、成形部オブジェクト５８は、前記パーツにおける特殊な成形部に関連するデータを含み、このデータは幾何学形状及び寸法データ、２次元及び３次元空間位置データ、及び端及び表面データを含む。
【０２０５】
図２６の実施例に更に示されるように、パーツクラス５０は更にトポロジー・オブジェクト６２及び曲げ特性オブジェクト６４を含む。前記トポロジーオブジェクト６２は、前記パーツの前記面、穴、成形部及び曲げ線についてのパーツトポロジーデータを含む。前記トポロジーオブジェクト６２におけるデータは前記パーツの前記種々の特徴の構造的及び幾何学的関係を示す。前記曲げ特性オブジェクト６４は前記パーツの１つ或いはそれ以上の特徴についての特殊な製造上の拘束に関する情報を含む。例えば如何に前記板金パーツが曲げられるべきであるかに関する曲げ特性情報が、前記曲げ特性オブジェクト６４に設けられる。前記曲げ特性情報は、異なる曲げ特性タイプ（例えば同時曲げ、同一直線上曲げ、Ｚ曲げ等）についての特殊製造データを含む。
【０２０６】
前記曲げ線オブジェクト６０は、また行なわれる曲げに関連する製造特殊データを含む。従って、各曲げ線についての幾何学的或いは寸法データ、２次元及び３次元空間位置データ、端データに加えて、前記曲げ線オブジェクト６０はまた、各曲げ線についてのＶ幅データ、曲げピッチデータ、曲げ数データ及び／又は配向データを含む。各曲げ線は、図２６に示すように付随する曲げ操作を含む。この曲げ操作は、各曲げ線において曲げを行なうためのデータ及び操作／指示を有する一群のオブジェクトとして実行される。仮にオブジェクトとして提供されると、各曲げ操作は、曲げ角度、曲げ半径及び／又は曲げ縮小量のごとき固有の曲げデータのみならず、如何に或いはどのタイプの曲げを行なうべきか（例えば円錐曲げ、Ｚ曲げ、ヘミング、円弧曲げ等）を指示するデータ及び指令を含む。
【０２０７】
前記パーツの曲げモデルを、オブジェクト指向データモデルを介して実行することにより、全ての複雑な数学的計算、計算幾何学及びマトリックス変換が単一のクラスライブラリに組み込まれる。ヘミング、Ｚ曲げ及び円弧曲げのごとき特殊な曲げ操作もそのクラスライブラリに取り込まれる。更にＶ幅及び曲げ縮小量及び曲げ順のごとき製造情報もそのクラスライブラリに取り込まれる。前記曲げモデルにより、前記２次元平面モデル及び３次元モデルの同時二重表示が図２６に示すように行なわれる。更に、前記曲げモデルの曲げ線オブジェクト６０に応じて曲げ加工が行なわれる。前記曲げモデル及びパーツ構造並びにそれらについての実行に関連する一般的なコメントはここに添付した付録Ｋに提供される。
【０２０８】
曲げモデルビューアが前記曲げモデルを解釈し、２次元及び／又は３次元表現における前記パーツの視覚的な画像を表示するために設けられる。図２７は、この発明の他の側面による、前記曲げモデルビューアの構造と前記曲げモデルとの関係のブロック図を図示する。前記曲げモデルビューアはオブジェクト指向プログラム技術を介して実行され、前記設備３８における種々の場所１０，１２，１４，…２０の前記ステーションモジュールにおけるユーザが前記曲げモデルに設けた情報に基づいて前記パーツの種々の図を表示できるようにするウインドウズに基づくアプリケーションである。前記曲げモデルビューアは、前記板金パーツを視覚化するために用いられる一群のアプリケーション・ライブラリ・モジュールを含む。更に、前記曲げモデルビューアは、ウインドウズ・アプリケーションの画像クラスとして設計され、従ってそれは任意のウインドウズ・アプリケーションについての基本的画像クラスとして使用される。前記２次元及び３次元モデルを見るための殆どの標準的操作（例えばズーム９２、回転９６、パン１００、寸法１０２等）は前記曲げモデルビューアの要素機能として実行される。幾何学的変換及び基本的コンピュータグラフィックス技術は、画像操作を実行する際に前記曲げモデルオブジェクトに対して適用される。更に、前記曲げモデルビューアは、画像モデル属性８８を含み、それはソリッド画像、ワイヤフレーム画像、２次元平面画像及び正射影画像を含む４つの主なる画像モードを有する。
【０２０９】
この発明の１つの側面によれば、前記曲げモデルクラスライブラリ８０は、選択された画像（例えばソリッド、ワイヤ、２次元平面又は正射影画像）に応じて、前記板金パーツに作用する一群の手続き又は機能を含む。前記曲げモデルビューア観察クラス８４は、ズーム９２、回転９６、パン１００及び寸法１０２のごとき、一連の標準的操作を含む。そして、前記曲げモデルビューアの状態に応じて、前記曲げモデルビューア観察クラスは、前記曲げモデル・クラス・ライブラリ８０から複数の機能を呼び出す。図２７に示されるように、ユーザにより選択される前記種々の観察モデル属性或いは特徴８８は、ソリッド画像、ワイヤフレーム画像、２次元平面画像及び正射影画像を含む。この発明に設けてあるこれらの種々の観察モードの記述は図２８−３１を参照して以下に提供される。
【０２１０】
基本的コンピュータグラフィックス及び幾何学的モデル化技術、例えば幾何学的変換及び３次元幾何学的技術は、前記曲げモデルの種々の特徴を実行し且つ異なる観察モード或いは機能を提供するために使用される。コンピュータに基づいた２次元及び３次元のモデル化及びシミュレーションにおける最近の発展及び展開、例えばグラフィックライブラリ或いはパッケージの効用はこの発明のこれらの特徴を実行するために適用される。更に、コンピュータグラフィックス及びモデル化については広い種類の刊行物或いは文献が利用可能である。例えば、モルテンソン、フォリー等、マンティラを見よ。それらの各々は上に記載した。
【０２１１】
この発明の種々の観察及びモデル化の特徴を提供するために各ステーションモジュール及びサーバモジュールは、８００×６００の解像度を有するＳＶＧＡスクリーンのごとき高解像度表示スクリーンを有する。ジョイスティック及び／或いはゲームカードも前記ステーションモジュール及びサーバモジュールに提供され、ユーザが、前記パーツの異なる２次元及び３次元表現を選択的に修正し且つ観察することを可能とする。ソフトウエアに基づいたグラフィックス・パッケージ、例えばオープンＧＬ（ＯｐｅｎＧＬ）及びレンダウェア（ＲｅｎｄｅｒＷａｒｅ）は、グラフィック計算を行なうために使用される。それらのグラフィックライブラリ或いはパッケージはウインドウズに基づいたアプリケーションで種々の観察モードを実行するために使用される。例えばオープンＧＬは前記曲げモデルに設けてあるパーツ幾何形状及びトポロジーデータに基づいて種々の２次元ワイヤフレーム画像を実行するために使用される。更にレンダウェアは前記曲げモデルに設けてあるパーツデータに基づいて、前記板金パーツの種々の２次元及び３次元ソリッド画像を表示するために使用される。オープンＧＬについての更なる情報については、例えばオープンＧＬ・レファレンスマニュアル及びオープンＧＬ・プログラミングガイド、リリース１、オープンＧＬ・アーキテクチャ・レビュー・ボード、アディソン−ウエズレイ発行社、リーディング、マサチューセッツ（１９９２）を見よ。レンダウェアの情報については例えばレンダウェアＡＰＩレファレンスマニュアルＶ２．０、クライテリオンソフトウエア株式会社、イギリス（１９９６）を見よ。
【０２１２】
前記パーツの種々の画像を表示するために、前記曲げモデルは例えばオペレータのステーションモジュールにより前記データベース３０からアクセスされる。前記曲げモデルデータは、使用されているグラフィック・ライブラリ或いはパッケージ（例えばオープンＧＬ又はレンダウェア）により使用されるデータフォーマットに応じて再フォーマット化される。しかる後、前記グラフィックデータは、オペレータにより選択された観察モード（ワイヤ、ソリッド等）を表示し、或いは前記ユーザにより実行された観察機能（ズーム、パン等）を実行するために種々のプログラムされた順序に従って加工される。
【０２１３】
特定の観察モードがオペレータにより選択される時、選択された観察モードは、前記画像の現在のズーム比率或いはファクター及び向きと共に検出される。この情報は、次に前記現在の表示を更新するために前記グラフィックパッケージに対して機能コールを行なうために使用される。前記グラフィックパッケージに対する機能コールは、表示される観察モード並びに実行されるズーム或いはその他の観察機能に応じて行なわれる。これらの機能コールに基づいて前記グラフィックパッケージは必要なデータを提供し、従って前記ステーションモジュールは前記オペレータに対して前記パーツの画像を表示する。前記ユーザによる前記２次元又は３次元表現の修正（例えばジョイスティック或いはマウスを移動することにより）に基づいて前記表示された画像を更新するために追加の機能コールは前記グラフィックライブラリに対してなされる。
【０２１４】
前記パーツのワイヤフレーム画像を提供するために、前記グラフィックパッケージに対して前記パーツの線分エンティティーデータが提供され必要なグラフィック計算がなされる。しかし、ソリッド画像については、前記面の各々について１つもしくはそれ以上の多角形（ポリゴン）が引き出され、前記画像を表示するために前記グラフィックパッケージへ入力として提供される。オープンＧＬ及びレンダウェアのようなグラフィックパッケージは、多角形データを入力として取得し、ソリッド画像を提供するために前記多角形により定義される領域を満たす。前記多角形は、前記曲げモデルにおける面及び曲げ線情報から導出され各面の境界を決定することにより導出される。前記多角形は前記パーツの各面を表示し且つ定義するために生成されなければならない。これらの面は次に、板金パーツ全体を表示するために、前記曲げモデルにおける前記パーツトポロジー及び他のデータに基づいて接続される。仮に面が開口部或いは穴を有する場合には、そのような開口部を囲まない幾つかの多角形を有する面を定義することが必要となる。正射図については、個々の図の各々（それはワイヤフレーム又はソリッドである。）についてのデータは前記グラフィックパッケージに送られ、図３１に示されるごとく、結果としての複数の図が単一の表示スクリーン上で結合される。前記曲げモデル像の種々の観察モード及び機能を実行するための代表的コードは付録Ｅに提供される。このサンプルコードはＣ＋＋で記載され前記プロセス及びそこで実行される操作に関連する複数のコメントを含む。適当なグラフィックパッケージ（例えばオープンＧＬ及びレンダウェア）との結合における前記コードは異なった図（例えば２次元及び３次元ワイヤフレーム或いはソリッド）を表示するために使用されるだけでなく、前記観察機能（例えばズーム、回転、パン等）の各々の機能を提供する。表示される種々の観察モード表示スクリーンの簡単な説明が以下に与えられる。
【０２１５】
ソリッド図モードは、前記曲げモデルにより定義される前記パーツの、ソリッドで表示される３次元図を表示する。図２８は前記板金設備３８内での位置１０，１２，１４，…２０のいずれかにおいて設けてある表示スクリーンへ出力として提供される代表的ソリッド図ウインドウを図示する。このソリッド図モードにおいて、ユーザ或いはオペレータは、３次元空間でのナビゲーション及び３次元自動寸法付けを操作するための複数の観察機能を与えられる。前記パーツのソリッド図を変更するために設けられる基本的な機能は回転、ズーミング、パンニング、及び／又は標準図選択を含む。前記ユーザにより与えられ或いは選択される前記標準図は以下を含む。即ち等測投影法図、平面図、底面図、正面図、背面図、左図、及び右図。自動及びマニュアル寸法付け操作がまた提供され、現在の観察角度に基づいて前記パーツの重要な寸法を表示する。この発明の寸法付け特性の代表的例が、図３２−３６を参照して以下に提供される。
【０２１６】
図２８に示されるようにソリッド図ウインドウはウインドウズに基づいたアプリケーションであり、従って前記パーツの複数のウインドウ或いは部分図が提供される。前記複数の図のウインドウは、ウインドウの中で１つの極めてクローズアップされた単一の図を提供する拡大図及び単一のウインドウにおいて前記パーツの極めて遠くからの図を与える鳥瞰図を含む。前記部分図はユーザにより選択されたオブジェクトの部分図を与える。前記種々の観察機能を制御するために、前記場所１０，１２，１４，…２０の各々の前記サーバモジュール３２及びステーションモジュールに、ジョイスティックインタフェースが設けられる。前記ジョイスティックだけ及び／又はキーボード上の所定のキー（例えばシフトキー又はコントロールキー）の操作との組み合わせの操作が、回転及びパンニング及びズーミングのごとき種々の機能を実行するためにユーザにより行なわれる。更に、前記パーツのソリッド図の表示される生地は、データベース内での前記パーツについて特定された材質をシミュレートするように選択される。この目的のために、スチール、ステンレススチール、アルミニウム等のごとき材料の生地のライブラリを有する材料生地ライブラリが提供される。格納された材料生地ライブラリはソリッド図が存在する時オペレータによりアクセスされ適用される。従って、表示されるパーツの表面は前記板金パーツの実際の生地をより忠実にシミュレートする。
【０２１７】
前記ワイヤフレーム図モードは、前記板金パーツのワイヤフレーム図のウインドウズに基づいた表示を提供する。ワイヤフレームウインドウの例が図２９に示されている。前記ワイヤフレームにおける３次元空間ナビゲーション及び３次元寸法付けを提供するためのキーの機能は、前記ソリッド図に関して上に記載したと類似である。例えば回転、ズーミング、パンニング及び標準図の選択のごとき機能が提供される。自動寸法付け、多重図ウインドウ及び断面図オプションも前記ワイヤフレーム図モードにおいて提供される。更に、ジョイスティック及び／又はキーボードインタフェースが、ユーザが前記種々の観察機能を選択し且つ活性化することができるように提供される。
【０２１８】
前記２次元平面図モードはワイヤフレーム表示において、前記パーツの展開された２次元平面図を表示する。２次元平面図ウインドウの例が図３０に示されている。この２次元平面図モードはユーザがウインドウ中の図を変更し又は改造するのを可能とするための複数の観察機能を有する。例えばユーザが前記２次元平面ワイヤフレーム図を選択的にズームし且つパンするのを可能とするようにズーミング及びパンニング機能が設けてある。更に、寸法付け及び多重ウインドウ観察機能が、前記ソリッド図モードに関して上記したと同様の態様で設けてある。ジョイスティック及び／又はキーボードインタフェースはユーザがパンし、ズームし他の観察機能を制御するのを可能とするように設けてある。前記パーツに設けられている特殊な成形部または形状は、特殊な成形部の指示又は記載と共に、前記成形領域の前記最も外側の境界についての成形または形状として表示される。
【０２１９】
図３１に図示されるような正射図ウインドウも前記曲げモデルビューアの一部として提供される。前記正射図モードはワイヤフレーム表示において平面図、正面図、右図及び等測投影法図を表示する。隠れ線オプションが、観察角度に基づいてブロックされた線を見えなくするために設けられる。この隠れ線オプションは各図のウインドウを簡単化するために用いられる。前記正射図モードにおいても種々の観察機能が提供され、ユーザが前記ウインドウにおいて現在の図を選択的に操作し且つ変更するのを可能とする。例えば、ズーミング及びパンニング機能が寸法付け及び多重ウインドウ観察機能と共に設けられる。上記したように、多重ウインドウ観察機能が設けられ、ユーザが、多重ウインドウにおいて前記正射図の拡大図及び／又は鳥瞰図を選択的に表示することを可能とする。ジョイスティック及び／又はキーボードインタフェースが、前記複数の場所の各々に設けられ、ユーザが、前記正射図モードにおいて前記複数の観察機能の各々を選択的に活性化し且つ操作するのを可能とする。
【０２２０】
上記した種々の図の表示の各々を表示せしめるのに加えて、前記曲げモデルビューア観察クラスは他の特徴と共に実行される。例えば前記曲げモデルビューアはオペレータにより選択され強調されている、現在の図における複数の項目或いはエンティティーを指示するための選択集合を含み且つ維持する。この発明の１つの側面によれば、オペレータは、選択された項目に関連するデータを修正し或いは前記パーツのそれらの項目の所定の操作を行なうために、前記表示されたパーツの面及び曲げ線及び他の特徴を選択することを可能とされる。例えばオペレータは、表示されたパーツの面を選択し、その面のその幅或いは長さに沿っての寸法データを変更することができる。オペレータはまた曲げ角度又はＶ幅のごとき各曲げ線に付随する種々の曲げデータを修正することができる。
【０２２１】
前記曲げモデルビューアはユーザにより選択されたエンティティー或いは項目（例えば面、曲げ線、面或いは曲げ線の端等）のリストを保持する。観察者はそのリストを更新する。従ってオペレータにより現在選択されている現在の項目は前記選択リストに常に保持される。この発明におけるソフトウエアの他の部分は、異なる手順（例えばマニュアル寸法付け等）を実行し或いは行なう際、選択されたエンティティーの前記現在のリストの図面クラスを呼び出す。
【０２２２】
更に前記曲げモデルビューアは観察可能性機能を提供する。それは現在表示されている図に基づいて観察可能性情報及び座標情報を提供する。以下に更に十分に説明されるように、前記観察可能性機能は前記パーツの特定な部分或いはエンティティーがスクリーン上で現在観察可能であるか否かについての情報を提供し且つスクリーンエンティティーが現在位置する場所についての座標情報を提供する。前記曲げモデルビューアの観察可能性機能は、前記パーツのどの部分が現在スクリーン上で観察可能であるかを決定するためにこの発明の寸法付け特性により呼び出される。従ってスクリーン上で観察可能である前記パーツの部分の寸法情報のみが観察者に対して表示される。この発明の寸法付け及び観察可能性機能のより詳細な説明は以下に提供される。更に前記曲げモデルビューアの観察可能性機能を実行するための代表的コードはここに添付する付録Ｊに提供される。
【０２２３】
図３２−３６を参照するに、この発明の１つの側面に基づく、寸法付け特性の事例が説明される。上記したように、観察モードの各々は現在の観察方向に基づいて、前記パーツの寸法を自動的に表示する寸法付け機能を含む。自動寸法付け機能は、現在の観察角度においては見ることができないフランジ或いは曲げ線の寸法がユーザに対して表示されないように提供される。前記自動寸法付け機能或いはモードが活性化される時、前記パーツの観察可能な寸法のみが、現在の観察角度に基づいて表示される。更に、自動寸法付けモードにおいては、所定の寸法（即ち前記曲げ操作に対して重要である寸法）のみが現在の観察角度の状態に基づいて表示される。マニュアルの寸法付けモードも提供され、ユーザがどの寸法が表示されるべきであるかを選択的に指示することを可能とする。このマニュアル寸法付けモードにおいては、ユーザにより選択された寸法事項のみが、現在のパーツの観察角度に基づいて表示される。いずれの寸法付けモードにおいても、表示された寸法事項は、前記パーツがズーム化され或いはパンされる時ウインドウ表示から消去され或いは除去される。
【０２２４】
図３２は自動寸法付けモードにおいて表示される種々の寸法事項の例を図示する。前記自動寸法付けモードにおいて表示される寸法事項は、曲げ操作に重要な事項（例えばフランジ長さ、曲げ線長さ、曲げ角度等）からなり、パンチ加工された穴或いは開口部の寸法のような余分な寸法事項ではない。前記表示される寸法事項は例えば前記板金パーツの幅、深さ、及び高さ並びにフランジ長さを含む。更に、各曲げ線の前記曲げ線長さＬ、曲げ角度Ａ、内側半径Ｒ及び曲げ縮小Ｄは単独で或いは一緒に、１つのウインドウに或いはグループ情報ボックスに表示される。上記したように、現在の観察角度に基づいて観察可能な寸法事項のみが表示される。更に前記オペレータが、前記パーツの観察角度を変えるために回転、ズーミング或いはパンニングをする時全ての寸法は表示から消去され或いは除去され、各操作が完了した時それらの寸法は再び表示される。表示情報（任意のテキスト或いは参照矢印）の寸法及び向きは、現在のズームの比率或いは観察角度ではなくスクリーンの寸法に対して常に寸法調整される。しかしながら、前記寸法情報の可読性を改良するために前記寸法情報の色、スタイル、重み及び／又はフォントはユーザがそれらを変更できるように形成可能である。結果としてオペレータ或いはデザイナーは、前記寸法情報の特殊の色、フォントサイズ等を選択することによりパーツにおける重要な寸法を強調することができる。例えば、寸法テキストの色、寸法又はフォント又は、寸法参照事項、線又は矢印の色、線の重み或いはスタイルは、パーツにおける重要な寸法を指示するために強調され或いは選択的に変更される。オペレータはまたウインドウ情報ボックスを色付けし満たし或いはスタイル付けし或いは特定の曲げ線を色付けし或いはパーツ内の他の重要な寸法を強調する。
【０２２５】
この発明の寸法付け特性を実行するために種々のプロセス或いは操作が利用される。更に上記したように本発明の寸法付け特性に対して観察可能性情報を提供する観察可能性機能を、前記曲げモデルビューアは備える。これらの機能或いは特性は、例えばサーバモジュール３２及び／又は工場全体に位置するステーションモジュールのそれぞれでソフトウエアにより実行される。この発明の自動寸法付け特性を実行するための代表的コードが付録Ｆ−Ｉに設けてある。更に、曲げモデルビューアの観察可能性機能のためのサンプルコードが付録Ｊに設けてある。これらの付録におけるコードはＣ＋＋プログラム言語で書かれており、そこで行なわれる手続き及び操作の論理フローの理解を容易にするためのコメントを含む。
【０２２６】
この発明の寸法付け特性の論理フローは一般的に３つの段階に分類される。第１の段階で、前記パーツの曲げモデル幾何形状及びトポロジーデータがデータベース３０からアクセスされ、前記パーツの全ての寸法並びにそれらの寸法が表示され得る全ての態様を計算するために使用される。前記パーツの各曲げ線及び面について、データが表示され得る全ての最も遠い点が計算され、これらの点について、寸法線或いは矢印が表示され得る全ての方法が計算される。前記寸法データ或いは他の情報が表示され得る場所を決定する際に一定のヒューリスティックが適用される。例えば一般的なルールとして、全ての情報は前記パーツの外側にのみ表示されると決定される。このようなヒューリスティックが、前記ビューアに対してより意味のあるそしてより込み合わない情報の表示を提供するために適用される。
【０２２７】
上記した第１の段階は、本発明の寸法付け特性がオペレータにより活性化された際常に実行される。或いは、前記第１段階の計算は前記パーツが最初にオペレータにより観察された際にのみ行なわれる。このような場合に、前記計算されたデータは次の使用のためにメモリに格納され、前記パーツの寸法或いは他の幾何学的データがユーザにより修正され或いは変更された時変更される。更に前記第１段階の全ての計算は図面スクリーンに対してではなくパーツの幾何学形状に対して行なわれる。従って前記データは、現在の図面に関わりなく或いはその図面が変更されても何時でも再び使用され得る。
【０２２８】
この発明の自動寸法付け特性の第２段階は前記パーツの図面が更新された時常に行なわれる。この第２段階の主たる目的は、変更された図において前記パーツのどのエンティティーが観察可能であるかに基づいて前記第１段階中に生成されたデータをふるいにかけることである。この第２段階において、現在の図において観察可能でない全てのデータはふるいにかけられ、現在観察可能である、前記第１段階において計算されたデータのみが残る。前記パーツのいずれの点あるいは部分が現在観察可能であるかを決定するために前記曲げモデルビューアに対する機能コールがなされる。上記したように、前記曲げモデルビューアは、表示されている現在の図に基づいて前記パーツの観察可能な部分についての情報を保持し且つ提供する観察機能を含む。前記パーツの向きに基づいて前記曲げモデルビューアは前記パーツのどの面及び曲げ線（並びにそれらの面及び曲げ線のどの端或いは部分）が観察可能であるか、そして何がスクリーン上で隠されているかを決定する。
【０２２９】
上記したように、前記曲げモデルビューアの観察可能機能を実行するためのサンプルコードは付録Ｊに提供される。前記パーツのいずれの点あるいは部分が観察可能であるかを決定するために、前記曲げモデルビューアは前記パーツの現在の図の向き及び現在のズーム面又は表示されているパーツの比率を決定し且つ維持する。前記曲げモデルビューアはこの現在の図の向きを決定し維持するために従来の透視図射影技術（モルテンソンの例えば１２章を見よ）を使用する。前記パーツの任意の点の観察可能性を決定する際に前記点の世界座標（即ちそこにおいて前記パーツが表現されているところの座標）を前記観察可能性機能は獲得する。次に、前記現在の図面の向き及びズーム面あるいは比率に基づいてその点について、前記世界座標に対応するスクリーン座標（即ちスクリーン上の画素の位置）が決定される。その後、前記スクリーン座標に基づいて、前記スクリーンの観察点の眺めから前記部品の任意のエンティティー或いは部分が問題の点の前方にあるか否かが決定される。前記パーツの上の点の隠されている特性は、前記パーツの他のエンティティー或いは部分が問題の点と同じスクリーン上の点を割り当てられているかどうかに基づいても決定され得る。グラフィックパッケージ或いはライブラリ（例えばオープンＧＬあるいはレンダウェア）への機能コールは、前記パーツの１つの点以上が同じスクリーン上の点に割り当てられているかどうかを決定するために使用される。もし何かが同じスクリーン上の点に割り当てられているならば、それらの点のそれぞれのＺバッファ深さに基づいて、前記パーツの点がそれの後ろにあるかどうかが決定される。前記Ｚバッファ深さはオープンＧＬ或いはレンダウェアのごときグラフィックパッケージにより使用され、観察点或いはカメラ位置からそれぞれの点への距離を定義する。前記Ｚ深さは、興味のある前記パーツの複数の点について前記グラフィックパッケージへ機能コールを行なうことにより決定される。
【０２３０】
前記曲げモデルビューアの観察可能性機能の前記プロセスはこの発明の自動寸法付け特性から前記曲げモデルビューアへ催促がある時いつでも実行される。そのようなプロセスは従って前記オペレータにより表示されているパーツの現在の図が修正され或いは変更される時いつでも実行される。上記したように、前記曲げモデルビューアは、表示された画像の向きに対して変更がなされる時は常に、現在の図の向き及びズーム比の状態を維持し且つ更新し、従って要求される時観察可能性情報を正確に提供する。
【０２３１】
どのデータが観察可能であるかを決定した後、自動寸法付け機能は、（例えば第１段階での計算に基づいて）前記寸法データ或いは他の情報が表示され得る全ての可能な方法及び位置を決定する。前記データが表示され得る全ての可能な方法からデータを表示するための最適の方法を選択するために一群のヒューリスティックが適用される。例えば第１のヒューリスティックは、観察者の観察点により近いスクリーン上の領域が好ましいと要求する。第２のヒューリスティックは、前記寸法を定義するための２つの可能な点の間の距離が最小であるところの領域により近い領域にデータは表示されるべきであると規定する。他のヒューリスティックはまた、スクリーン上での重なり合い或いは混雑を避けるために、他の寸法データ或いは他の情報の相対的位置に基づいて適用される。
【０２３２】
前記パーツの観察可能な部分及び前記観察可能な領域についての情報を表示するための最適の領域を決定した後、前記自動寸法付け機能の第３の段階は前記表示スクリーン上で種々の情報を描くために実行される。例えば、前記情報を表示するための領域の選択に基づいて、寸法情報は前記パーツの観察可能な寸法の各々についてスクリーン上に表示される。更にどの曲げ線が観察可能であるかに基づいて、曲げ線情報がまた、他のパーツ情報とオーバーラップしないスクリーンの領域において情報ボックス（例えば図３２に示されるそれ）に表示される。前記パーツの幅、高さ、及び深さを含むパーツの寸法はまた前記スクリーン上の所定の位置（例えば前記パーツの右下）或いは前記パーツに最も近く他の情報にオーバーラップしない或いはそれを邪魔しない位置に表示される。
【０２３３】
図３３−３６は前記寸法付けモードにおいて寸法事項を表示する際に、使用される種々の方法及び定義を図示する。特に図３３（ａ）−３３（ｂ）及び３３（ｃ）は、種々の異なるパーツについてフランジ寸法が定義される方法を図示する。この発明の１つの側面によれば、前記フランジ長さは、各曲げ線からフランジ上で最も遠い点として定義される。もし前記曲げ線と並行であるフランジの最も長い端部に前記フランジの最も遠い点が存在しない場合には、前記寸法付けモードにおいて最も長いフランジが追加され表示される。限定しない事例として図３４（ａ）及び３４（ｂ）は、２つの異なるタイプのパーツについて補助的なフランジ長さを追加することを図示する。前記パーツの厚さが表示される時、フランジ長さは外側寸法の外側として表示される。例えば図３５（ａ）、３５（ｂ）及び３５（ｃ）は、厚さを有して表示される種々のパーツについて前記フランジ長さが指示される態様を図示する。更に、鋭角の曲げを備えたパーツについて、前記フランジ長さは種々の方法で表示される。例えば図３６（ａ）に示されるように、フランジ長さは、接線寸法定義に基づいて表示され、そこでは前記フランジ長さは前記鋭角曲げから延長される接線から測定される。或いは、前記鋭角曲げ角度の２つの辺から延長された２つの直線の交差により定義される点に基づいてフランジ長さを定義するために、図３６（ｂ）に示されるそれのごとき交差寸法方法が使用される。オペレータは、前記フランジ長さを表示するために前記接線寸法或いは交差寸法方法のうちから選択することを可能とされ、及び／又は特定の寸法方法（例えば接線寸法方法）はデフォルト設定として提供される。
【０２３４】
曲げコード順番の生成を促進するために、種々の表示機能を有した図形的ユーザインタフェースが設けられ、オペレータによる曲げプランの生成を助ける。図３７−４４はこの発明の他の側面により、図形的ユーザインタフェースの使用により曲げコード順番を生成するために実行される種々の手続き及び操作を図示する。通常、最初の曲げモデルデータ及び他の作業情報はサーバモジュール３２において重要な幾何学的及び製造データを入力することにより設計プログラマにより生成される。結果としての曲げモデルファイルは次にデータベース３０に格納される。板金パーツが製造される前に、曲げオペレータが、所望の曲げ操作を実行するための曲げ順を生成する必要がある。この曲げオペレータは、どのタイプの工具が必要であるかを決定し且つ前記曲げ機械装置について工具取付けを定義しなければならない。この曲げプラン生成の工程は、図形的ユーザインタフェースの使用によりまたこの発明の種々の教示により援助され、且つより効率的となる。
【０２３５】
前記曲げプランを生成するために、例えば曲げステーション１８の曲げオペレータは、前記データベース３０から前記曲げモデル及び他の作業情報へアクセスし且つダウンロードする。前記関連するパーツについての曲げモデルは前記コミュニケーションネットワーク２６を介して曲げステーション１８における工場フロア上のステーションモジュールへ搬入され或いは移入される。この工程は、一般的に図３７のステップＳ２２０に示される。その後、ステップＳ２２４で曲げオペレータは、前記曲げモデルビューアを用いて前記パーツの形状及び寸法を調べる。ここで、前記曲げオペレータは、前記曲げステーションに位置付けられた表示スクリーンで前記パーツの種々の２次元及び３次元図を選択的にズームし且つパンする。この発明の自動寸法付け特性を活性化することにより、前記曲げオペレータはまた曲げ操作を実行するために前記パーツの重要な曲げ寸法を観察する。
【０２３６】
一旦オペレータが前記パーツの形状及び寸法を理解すると、この曲げオペレータはステップＳ２２８で曲げ順入力ウインドウを選択し且つ表示することにより前記曲げプランを生成することを開始する。前記曲げ順入力ウインドウは、曲げオペレータが曲げ順を生成し且つ修正し且つ消去するのを援助するために図形的ユーザインタフェースを提供し且つオペレータが、前記曲げ順における各段階についての種々の製造パラメータ（例えばバックゲージ位置、工具、ＮＣデータ等）を特定し且つ入力することを可能とする。前記曲げ順入力ウインドウは前記スクリーンの一部（例えばスクリーンの中央部或いはスクリーンの左側の方）に表示される前記パーツの２次元平面図画像を含む。前記２次元平面図画像は、前記パーツのフランジ、穴及び開口部を含む、前記展開パーツの種々の特徴を含む。前記曲げオペレータが前記複数の曲げ線及び各曲げ線についての曲げ順を選択し且つ指示すると、各曲げ段階における前記中間的パーツ形状のソリッド２次元或いは３次元画像が現れ、例えば図３８に示されるように、スクリーンの右側の端のごときスクリーンの一部にそれらが提供される。前記中間パーツ形状の画像は入力された曲げ順に対応した順番で表示され且つ（図３８の例に示されるように）前記パーツの２次元平面図と共にスクリーン上に同時に表示され、或いは別個のスクリーン表示に別個に表示される。
【０２３７】
更に各曲げ線が選択されるにつれて、前記曲げ線は強調され、図３９（ａ）に一例として示されるように、曲げ順番号及び挿入方向（例えば矢印で表現される）が前記曲げ線の上或いは近くに表示される。各曲げ線についての前記曲げ線番号は、それが選択される順番に基づいて自動的に設定され、或いは各曲げ線が選択された後オペレータによりマニュアルで入力される。曲げ角度、曲げ線長さ、及びバックゲージ位置のごとき曲げ線に関連する他の製造情報も、図４０及び４１に例として示されるように、各曲げ線が選択され強調されるとき入力され及び／又はスクリーン上に表示される。図４０及び４１に示すように、ダイアログ或いは情報ボックスがスクリーン上に表示され、曲げオペレータが各曲げ線に関連する製造情報及び他のパラメータを選択し、入力し或いは修正することを可能とする。
【０２３８】
前記ダイアログ或いは情報ボックスは、曲げオペレータが曲げ線を強調し或いは選択するのを可能とする。ホット機能キー或いは高速スイッチキーが前記曲げシーケンス入力ウインドウに表示され、オペレータが工具立てを選択し或いは入力し且つＮＣデータを監視し且つ修正するのを可能とする。例えば曲げオペレータは、工具機能キーを選択し、前記曲げ順入力ウインドウから、工具立て情報を入力するための工具入力表示スクリーン或いは複数の表示スクリーンへ切替える。ＮＣ機能制御キー（例えばＮＣ９ＥＸ）も設けられ、オペレータが実行されるべき曲げ操作に関連するＮＣデータを監視し及び／又は修正するのを可能とする。更に図４０及び４１に示されるように、曲げ線を定義し及び／又は修正すること及び関連する製造情報に関連して他の機能キー及び制御部が設けられている。例えばＺＯＯＭ  ＡＬＬキーが、前記２次元平面図画像をズームイン及びズームアウトするために設けられている。バックゲージキーは、前記バックゲージの位置を選択し或いは設定するために設けられている。グループ化及びグループ解除化制御キーは、一緒に曲げられる複数の曲げ線を可能とし或いは制御するために表示される。更に制御キー（例えばアマ曲げ）が特殊な曲げ操作を定義するために設けられている。他の機能キーも表示されオペレータが前記曲げ順を選択し、修正し及び／又は消去するために設けられている（例えばＲＥＭＯＶＥ  ＣＬＥＡＲ  ＦＷＤ、ＣＬＥＡＲ  ＡＬＬ、ＯＫ、ＣＡＮＣＥＬＬ）。この曲げ順入力ウインドウにより、曲げオペレータは、前記曲げ順及び種々の製造情報を効率的に監視し且つ修正することが可能となる。
【０２３９】
更にこの発明の他の側面によれば、前記パーツの断面図及び／又はパーツの曲げシミュレーションが、前記曲げ順における各曲げ工程についてスクリーン上に表示される（例えば図４１を見よ）。前記断面図及び曲げシミュレーションは前記スクリーン上に選択的に表示され、或いは曲げオペレータにより各曲げ線が選択される時表示される。前記断面図及び曲げシミュレーションは、例えば上下曲げ工具（例えばパンチ及びダイ）又はバックゲージ位置・設定の表現を含み、それらは前記２次元平面図画像と共に同時にスクリーン上に表示され或いは異なるスクリーン表示上に別個に表示される。前記バックゲージ位置は前記パーツのトポロジーに基づいて自動的に決定され或いはオペレータにより設定され或いは修正される。前記曲げ線のための工具立て情報が入力されておらず或いは曲げオペレータにより設定される場合には、前記断面図及び／又は曲げシミュレーションはスクリーン上に表示されず又は前記中間パーツ形状の表現及び計算され或いは定義されたバックゲージ位置のみが表示される。前記曲げシミュレーションは、前記パーツの所望の反転、前記パーツの操作及び配向動作及び／又は各曲げ線でなされる前記パーツの曲げ加工の表示されるシミュレーションを含む。前記表示スクリーン上に前記パーツの２次元平面図画像と共に、曲げ工程の前のパーツの断面図及び曲げ工程がなされた後の前記パーツの断面図を同時に表示することもまた可能である（例えば図４１を見よ）。これらの断面図は、スクリーンの右側に提供され前記曲げ順における各曲げ工程についての前記上下曲げ工具及びバックゲージの表現を含む。更にズーム制御或いは機能キー（ＺＯＯＭ  ＩＮ及びＺＯＯＭ  ＯＵＴ）が表示され、オペレータが、前記曲げ前及び曲げ後断面図に関連してズームの比或いは向きを制御することを可能とする。日本公告公報平７−１２１４１８（丹羽等の名前で１９９５年１２月１５日に発行）及び日本公開公報平１−３０９７２８（長沢等の名前で１９８９年１２月１４日に発行）に開示されるそれと類似の技術及び手続きが前記パーツの断面図或いは曲げシミュレーションを表示するために使用される。前記文献の開示はここにその全体において参考により積極的に取り込まれる。
【０２４０】
この発明の１つの側面によれば、選択された曲げ線に関連して前記パーツの短い或いは小さいサイドを計算することにより前記曲げについて挿入方向を自動的に決定するためのソフトウエア或いはプログラム論理が提供される。この発明の特徴に基づいて、各曲げ線はそのパーツを２つのサイドに分断するために使用される。挿入方向は、より小さい或いは短い長さ（例えば前記曲げ線に直交する辺の寸法）を有する前記パーツのサイドに基づいて或いは、より小さい全体的面積を有するサイドに基づいて各曲げ線について決定される。もしオペレータが前記選択された挿入方向に満足しない場合には、図３９（ｂ）に図示されるように、オペレータは挿入方向を反転する。オペレータは挿入方向を、例えば曲げ線が強調されている際にマウス或いはキーパッドの選択ボタンをクリックすることにより変更し或いは反転する。挿入方向情報は、曲げ装置或いは機械装置で前記パーツを曲げ加工するために、前記曲げ線により定義されるフランジの挿入方向を指示するための矢印及び／又はテキストを含む。前記挿入方向情報は、曲げ線の上或いは近く（例えば図３９（ａ）及び３９（ｂ）を見よ）或いは関連するフランジの端の上或いは近く（例えば図４０を見よ）に表示される。更に前記挿入方向情報は、各曲げ線が選択された時に表示され或いはジョイスティック装置、マウス装置、或いはキーボード装置から受け取った入力に基づいて選択的に表示される。
【０２４１】
従って図形的ユーザインタフェースの使用を介して、曲げオペレータは、種々の中間形状及び最終パーツの形を、オペレータにより入力された選択された曲げ順に基づいて見ることができる。再び、オペレータはジョイスティックインタフェース、マウスインタフェース及び又はキーボードインタフェースのごとき適宜の入力装置を通して前記スクリーン上にデータを入力し選択することができる。曲げオペレータが提案された曲げ順に満足しない場合には、曲げオペレータは、ステップＳ２３２に一般的に示されるように曲げプランを最終化する前に曲げ順を編集する。この曲げ順の編集は種々のやり方及び方法において実行される。特にこの発明の１つの側面によれば、ドラッグ及びドロップ編集特性が提供され図４２に示されるようにオペレータは単に、前記スクリーンの左側或いは右側に提供された中間的パーツ形状アイコン或いは表示の１つをつかみ且つそれを前記順番の所望の位置へドロップすることにより選択された曲げ順を編集する。その後、前記曲げ順に対する曲げオペレータの修正に基づいて前記スクリーン上の前記種々の中間パーツ形状が修正され、改定された曲げ順に基づく中間的曲げ段階を示す。更に前記曲げオペレータの前記曲げ順のドラッグ及びドロップ編集に基づいて、前記２次元平面図画像上の曲げ順番号が改定される。
【０２４２】
前記曲げ順が決定された後、オペレータは、ステップＳ２３６に示すように、格納された工具立てデータのライブラリから工具を選択することによりどのタイプの工具立てが使用されるべきであるかを決定する。関連する工具立て情報は、工場フロアの曲げオペレータに対して表示され、曲げオペレータが前記ライブラリから工具立てを選択するのを図形的に支援するために表示メニューが提供される。一旦特定の工具が前記ライブラリから選択されると、前記工具に関連するデータがスクリーン上に表示される。図４３は、マニュアル工具選択のために前記曲げオペレータに対して図形的に表示される種々の表示メニュー及びデータテーブルの事例を図示する。図４３の例では前記曲げオペレータが前記工具ライブラリから特定の工具を取り出すのを支援するために、連続的な表示メニュー或いはスクリーン表示が図形的に表示される。連続的に表示されるスクリーン表示は前記表示装置上に連続的に表示され（例えばオーバーラップする或いはカスケードする態様で）或いはそれは個々に表示され、そのスクリーンは次の引き続くスクリーン表示が表示される前にクリアされる。一旦特定の工具が選択されると、その工具に対する特定のデータがテーブルに提供され且つオペレータに表示される。工具ライブラリにおけるデータは、前記ソフトウエアの最初のセットアップ手続きにおいて、（例えばデータベース３０の中に）予め定義され且つ可能されている。
【０２４３】
この発明のマニュアル工具選択特性はオペレータが工具タイプを選択し且つ各タイプにおいて工具の形状を選択することを可能とする。例えば、パンチ、ダイ、ダイホルダ、及びダイレールを含む種々の工具タイプが選択される。各タイプは多数の形状からなり、且つ各形状に対して異なったサイズ及び寸法の多数の工具が存在する。１つの工具を選択するために、ユーザは、図４３に示されるような、表示される工具タイプアイコンから１つのアイコンを選択することにより１つの工具タイプをまず特定する。その後ユーザは選択された工具について利用できる異なる形状のメニューを提供される。工具形状を分析した後、ユーザは選択された工具について、表示された形状アイコンから１つの形状アイコンを選択することにより工具形状を選択する（例えば図４３では、グースネック形状パンチが選択された）。最後にユーザは選択された工具形状について適当なサイズ及び寸法を選択する。図４３に更に示されるように、選択された工具形状に対して利用可能な工具の異なるサイズ及び寸法を示すためのテーブルがユーザに対して表示される。このテーブルから１つの項目を選択することにより、選択された工具がアイコンとして表示され一般的な工具タイプアイコンに置き変わり、且つ工具の選択を確認する。
【０２４４】
ステップＳ２４０で、曲げオペレータは次に図形インタフェースの支援により、プレスブレーキにおける種々の工具段階（工具ステージ）を設定する。図４４は前記曲げプランにおいて使用される工具セットアップ（工具取り付け）の定義を容易にするために曲げオペレータに対して与えられる代表的工具セットアップウインドウを図示する。図４４に例として示されるように、種々のパンチ、ダイ及びレールのデータが前記ツールセットアップウインドウに表示される。前記板金パーツのための工具及びダイの情報はオペレータにより入力される。ジョイスティックが曲げオペレータのステーションモジュールに提供され曲げオペレータが工具位置を指示し且つ利用可能な工具及びダイのリストから工具及びリストを選択することを可能とする。この工具セットアップウインドウにおいてスクリーンの左側は現在の工具セットアップの断面形状を表し、スクリーンの右側はプレスブレーキにおける現在のセットアップの位置を表示する。現在のセットアップの位置は図４４に示されるように強調され或いは影が付けられる。
【０２４５】
最後にオペレータが曲げ順に満足すると前記工具立て及び曲げシーケンスを含む曲げプラン情報が、図３７におけるステップＳ２４２に一般的に示されるように、前記データベース３０の中に前記曲げモデルと共に保存される。前記曲げ順の実際のテストが、前記曲げオペレータにより選択された曲げ順を確認するためにプレスブレーキにより行なわれる。もし必要なら、前記工具立ての定義或いは曲げ順に対する更なる修正が、前記ステーションモジュールにおけるオペレータ或いはデザイナーにより実行される。
【０２４６】
この発明の種々の他の特徴は、前記曲げプランの生成における前記曲げオペレータを支援するために設けられる。例えばこの発明の他の側面によれば、工具立てエキスパートが設けられ、前記曲げオペレータに対して前記曲げモデルに格納されたパーツ形状及び他の情報に基づいて、工具立て及び曲げ順の示唆を自動的に与える。前記工具立てエキスパートからの示唆は当該示唆の分析の後、曲げオペレータにより改定される。更に、より複雑な工具立てエキスパートシステムが提供され、前記曲げファイルにおける前記パーツの形状、及び潜在的な衝突及び干渉をチェックするための工具の形状分析に基づいて更に複雑な操作について工具立て示唆及び曲げ順示唆を行なう。そのようなエキスパートシステムは手動或いはロボットにより支援された曲げ機械装置により使用され実行される。限定しない例として、この発明はデービッドＡボーン等の名前による「板金曲げプランを生成し且つ実行するための知的システム」と題される米国特許出願第０８−３８６．３６９、及びデービッドＡボーン等の名前による「ロボットウインドウの計画／制御の方法」と題される米国特許出願第０８−３３８．１１５号に開示される特徴及び教示により実行される。これらの開示はここに全体として参照により積極的に取り込まれる。上記したように図形的ユーザインタフェース或いは種々の機能は、板金パーツのための曲げプランを生成する際に曲げオペレータを支援するために設けられる。この発明の他の側面によれば、追加の特徴が更に設けられ、前記パーツの設計及び製造において支援を行なう。以下に更に十分に説明するように、音声的或いは視覚的情報の格納のごとき種々のマルチメディア機能が本発明において実行され前記曲げプランを生成し或いは曲げ順を実行する際に曲げオペレータに対して追加の支援を行なう。更に、中間の曲げ段階の各々において前記工具及びパーツの間の潜在的干渉及び衝突を自動的にチェックする衝突チェック機能が提供される。この衝突チェック機能は、工具形状及び、パーツにおける間隔の面倒で時間のかかるマニュアルチェックに置き変わるために提供される。前記マニュアルチェックは曲げプランを生成する際曲げオペレータにより通常行なわれる。これらの機能及びその他のものは添付する図面を参照して今から説明される。
【０２４７】
この発明の１つの側面によれば、前記曲げモデルデータと共に音声及び映像情報を格納するための方法が設けられる。種々の音声及び映像情報は、工場フロアにおいて記録され、例えば板金パーツの操作及び曲げ加工に関連する特殊な指令を提供する。この目的のためＣＣＤカメラ又はディジタルカメラが音声マイクロフォンと共に種々の場所１０，１２，１４，…２０のステーションモジュールの各々に設けられる。他の装置、例えばオーディオマイクロフォンを有するビデオカメラがオペレータ或いはユーザが音声或いは映像の情報を記録することを可能とするために前記ステーションモジュールに設けられる。前記種々の記録装置は工場フロアにおけるステーションモジュールコンピュータに接続される。限定しない事例としてインテルのＰＲＯＳＨＡＲＥ個人会議ＣＣＤカメラ（インテル株式会社から入手可能）が音声及び映像情報を記録するために使用される。他の商業的に入手可能なＣＣＤカメラ或いはディジタルカメラもそのような情報を記録するために使用される。
【０２４８】
前記曲げモデルデータと共に格納された種々の音声及び映像情報は種々の方法及び手続きにより、ユーザによりアクセスされ且つ読み出される。例えば格納された音声及び映像情報を再生するために、前記ステーションモジュールによりメニューオプションが表示される。更に、この発明の好適な実施例によれば、オペレータは、観察ウインドウに表示されるアイコンを選択し且つ生成することにより、格納されている音声及び映像情報を種々の表示スクリーン及びパーツの図に付随させる能力を有する。この機能は、ソフトウエア及びオブジェクト指向プログラム技術により実行される。これによりアイコンオブジェクトは曲げモデルデータ構造の中に生成され且つ格納される。このアイコンオブジェクトは、ある種の条件（例えばマウスのダブルクリック或いはジョイスティック或いは他の入力手段の使用による選択の指示によるオペレータによるアイコンの選択）に基づいてメモリから付随された音声及び映像情報を読み出すための手続きを含む。この発明のアイコンの特徴によりオペレータは異なる音声及び映像メッセージ或いは情報を前記板金パーツの異なる部分及び任意の表示に関連させる。このアイコンを前記パーツの表現に組み込むことにより、前記アイコンは、スクリーン上で画面が変わるにつれて前記パーツの２次元及び／又は３次元モデルの表示と共にズームし、回転し並進運動するように構成される。
【０２４９】
図４５は前記パーツの３次元ソリッドモデルに張り付けられたアイコンの使用を介して音声及び映像情報を添付する事例を図示する。ユーザが前記音声及び映像情報を記録した後、オペレータが前記３次元モデルウインドウの任意の位置にアイコンを張り付ける。前記アイコンがオペレータ或いはユーザにより次に選択される時、格納された音声及び映像情報は再生され、前記ウインドウに表示され、そのアイコンが配置された前記パーツのある部分或いは領域に関する特殊な指令又はメッセージを提供する。他の情報、例えば前記曲げ運動のシミュレーション或いは記録は前記パーツの種々の曲げ線の近傍にアイコンを置くことにより前記パーツに関連される。前記曲げ運動に関連する映像情報は次に前記アイコンが選択される時ユーザに対して再生される。
【０２５０】
オペレータ或いはユーザは、音声及び映像情報を記録し、或いは単に１つの音声メッセージ或いは静止或いは運動映像信号を記録し、それらはユーザに対して選択的に再生される。前記ウインドウ表示に対して付着されたアイコンは格納された情報のタイプを図形的に指示する（例えば、音声情報が格納されていることを示しているためにマイクロフォンのアイコンが表示され又は映像情報が格納されていることを示すために表示モニタのアイコンが表示される）。特殊なアイコンは、そのアイコンに音声及び映像情報が関連されていることを示すために設けられる（例えば「Ａ／Ｖ」の記号或いはマイクロフォンを含むビデオカメラのアイコン）。アイコンの一覧が設けられ且つ表示され、ユーザが、前記スクリーン表示或いは画像に対して音声及び或いは映像情報を添付する際に種々のアイコンから選択することを可能とする。
【０２５１】
図４６は格納された音声及び映像情報を読み出すためのアイコンを組み込んだ表示ウインドウの他の事例を図示する。図４６に表示された表示ウインドウは、図４２を参照して上で説明したそれのごとき、工具セットアップスクリーン画像に関連する。図４６の例では、音声情報が格納され、マイクロフォンのアイコンにより読み出される。そして別個の映像情報が格納され、前記表示ウインドウに対してビデオアイコンを張り付けることにより読み出される。前記音声及び映像情報は工具セットアップ或いは操作に関連する特殊な指令或いは情報に関連する。更に現在活性化されているウインドウ表示のタイプに関係なく、オペレータは、異なる音声及び映像情報を後に読み出すために、前記ウインドウ表示における種々の領域に必要なだけ多数のアイコンを張り付けることができる。
【０２５２】
この発明の他の側面によれば、画像編集ウインドウ特性が提供され、オペレータが格納された画像を選択しそれらを異なるスクリーンへ適用するのを容易にする。前記画像編集ウインドウ特性はウインドウに基づくアプリケーションとして提供され、それは例えばサーバモジュール３２或いは製造設備を通して設けられたステーションモジュールのいずれかにおいてアクセスされる。図４７は、この発明の教示により実行される画像編集（イメージ編集）ウインドウの例を図示する。前記イメージ編集ウインドウに表示される画像はディジタルカメラ或いはＣＡＤコーダによる画像写真を含む。前記スクリーンに表示される画像はオペレータにより（例えばマウス或いは他の適当なデータ入力手段により）選択的に選ばれ、他のスクリーンにコピーされ、それらはパーツの特定のモデルの図に関連させられる。オペレータは次にその画像或いはアイコンを前記モデルのウインドウ（例えば図４６に関連して上で示したそれのごとき前記パーツの３次元ソリッドモデルウインドウ）へ張り付ける。図４５、４６及び４７の画像は実際のスクリーン画像の写真再生である。実際の画像イメージは、使用されるカメラ或いはスクリーンの解像度に応じてそれ自体更に明瞭である。前記画像は例えば、曲げ操作に関連する特殊な操作或いは他の指令を議論し或いは図示する曲げオペレータの静止或いは運動映像イメージを含み、或いは板金曲げ操作の映像イメージである。換言するば、有用であると思われる実際の画像が取られ後に表示される。従って図４５−４７に示される実際の画像は例示的な目的のためのみのものである。図４８及び４９を参照するに、この発明の衝突チェック機能の例が設けてある。この発明の１つの側面によれば、衝突チェック機能が設けられ、ユーザは前記パーツ及びパンチ工具の間の潜在的な衝突を、図形的ユーザインタフェースの使用によりチェックすることを可能とする。前記衝突チェック機能はウインドウズに基づくアプリケーションであり、前記製造設備における任意のステーションモジュール或いは場所でアクセスされる。この発明の自動的衝突チェック機能は、前記曲げプランを生成する際に通常行なわれている伝統的なそして面倒なマニュアルの形状チェックに変わり曲げオペレータにより使用される。
【０２５３】
伝統的には、板金パーツの曲げプランを生成する際、曲げオペレータはまず前記パーツの曲げ順を決定する。前記曲げ順は前記板金パーツが製造の間に曲げられる順番或いは態様を決定する。その曲げ順が決定された後、曲げオペレータはその曲げ操作の各々を実行するために使用される工具を選択し定義する。この過程で、選択された前記工具の形状及び前記パーツの中間的形状が、前記曲げ工程の各々を実行する際に前記工具とパーツとの間の干渉あるいは衝突が存在しないことを確実にするために解析される。衝突或いは干渉が検出される場合には、選択された工具のタイプ（或いは必要に応じて曲げ順）は、前記工具と板金パーツとの間の干渉或いは衝突を生ずることなく曲げ操作が実行されるように修正されなければならない。
【０２５４】
潜在的な衝突或いは干渉を検出する際に、前記工具の形状と板金要素の曲げられた部分或いは形状との間のクリアランスを分析するために、曲げオペレータは伝統的にマニュアルの方法に頼っていた。典型的には、曲げオペレータにより工具形状のモデルが構成され使用されている。工具形状モデルは、板金の種々の中間的形状の工学的或いは技術的図面（前記工具形状モデルと同じスケールの寸法を有する）に対してマニュアルで合わせられ或いはその上に置かれる。この工具形状モデルを前記パーツの図面に対して適合させ及び合わせることにより前記曲げオペレータは、曲げ工程の各々において工具とパーツとの間に十分な空間或いはクリアランスがあるかどうかを決定することができる。しかしながらこの工程は面倒で且つ時間を浪費する傾向がある。
【０２５５】
この発明は自動的干渉チェック機能を設けることにより、そのような伝統的な方法の不利益を克服することである。この発明の干渉チェック機能は、図形的ユーザインタフェースを介して実行され、曲げオペレータが所定の曲げ順における各中間的工程において衝突をチェックするのを可能とする。図４８及び４９は図形的ユーザインタフェースを介して実行される衝突チェック機能の例を図示する。活性化される時、前記衝突チェック機能は前記曲げ順における前記パーツの各中間的形状とその順番に対して定義されるパンチ工具或いは複数の工具との間の衝突を自動的にチェックする。前記中間形状はスクリーンに表示され（例えば図４８及び４９を見よ）、衝突が発見されると、当該衝突が検出される工程がスクリーン上に強調される。更にテキストのごとき他の表示示唆が検出された衝突の数を指示するために提供される。図４８及び４９の例では、前記衝突情報は表示ウインドウの右上領域に提供される。更に、前記衝突がチェックされたパンチ工具或いは複数の工具のタイプは表示ウインドウの左上領域に表示され或いは指示される。
【０２５６】
衝突が、オペレータにより選択されたパンチ工具について検出される時、衝突が検出される中間的形状或いは段階がスクリーン上に強調される。この場合、オペレータはその特定の曲げ段階について他のパンチ工具を選択することもでき、前記パンチ工具の第２の選択について衝突が起きるか否か決定するために前記衝突チェック機能が再び実行される。オペレータは、各曲げについてパンチ工具を選択し、前記衝突チェック機能により衝突をチェックすることができる。ドラッグ及びドロップ編集が、中間的曲げ形状をドラッグし、それを前記提案された曲げ順内の所望の位置へドロップすることにより、前記ウインドウ表示中に表示された曲げ順をオペレータが変更することを可能とするように設けられてもよい。前記曲げ順は図４４を参照して上に記載したそれと同様の対応で、オペレータによりなされた前記ドラッグ及びドロップ編集に基づいて修正される。
【０２５７】
この発明の衝突チェック機能を実行するために種々の手続き及び操作が使用される。例えば潜在的な衝突を検出するために、選択された工具の幾何形状と中間的形状におけるパーツの幾何形状とがアクセスされる。各中間工程における前記パーツに関連する幾何形状データは前記曲げ順及びパーツ寸法及びトポロジーデータに基づいて生成される。前記パーツの各フランジは、前記曲げ順における各中間段階における前記パーツを表示するために、曲げデータ（例えば曲げ角度、曲げ線位置、縮小量等）に応じて折り曲げられる。上記折り曲げ工程及びこの発明の縮小量補償特性は各中間段階での前記パーツに対する幾何形状データを生成する際に適用される。この工具及びパーツの幾何形状により、前記曲げ段階の各々において前記工具の先端をパーツの曲げ線へ置くことにより、前記工具及びパーツが相互に配向される。衝突は、前記幾何学的データ及び前記工具とパーツとの境界を分析し、前記工具及びパーツにおいて共通な点或いは重なり合う点が存在するか否かを決定することにより検出される。衝突は、特定の曲げ工程で検出される時、その工程は、ユーザに対して衝突の検出を示すためにスクリーン上で強調される。衝突を検出するために使用される工具データは、ユーザによりなされる工具選択に基づいて、工具形状ライブラリから積極的に取り出される。任意の中間曲げ工程での衝突の再計算は異なる工具形状或いは曲げ順の修正に基づいて行なわれる。そのような機能を設け、ここに記載されるごとき、図形的ユーザインタファースを用いてそのような情報を表示することにより、衝突の可能性は、曲げオペレータにより、より容易に決定され且つ修正される。
【０２５８】
上記したように、ジョイスティック或いはマウス装置は、板金パーツの表示されるモデルを観察する際、ユーザが選択的に種々の観察機能（例えばズーム、パン、回転等）を活性化し及び制御することを可能とするために、前記製造設備を通して前記ステーションモジュールの各々及びそれらの場所に設けられる。前記ジョイスティック装置は多重の軸を有するジョイスティックで、選択或いは制御ボタンを有する。前記ジョイスティックはマイクロソフト・サイドワインダ・ジョイスティックを含む種々の商業的に入手可能なジョイスティック装置を介して実行され、各ステーションモジュール及び／又は当該設備の他の位置のコンピュータのゲームポートに差し込まれる。前記マウスはまたウンドウズ９５或いはウインドウズＮＴのごとき任意の商業的に入手可能なマウスをサポートするソフトウエア及び、各設備位置におけるコンピュータのゲームポート或いはマウスポートに差し込まれる任意の商業的に入手可能なマウス装置により実行される。
【０２５９】
限定しない事例として図５０−５５は、ジョイスティック装置或いはマウス装置を用いて、３次元幾何学的形状を操作し且つ前記パーツを表示するためのシステムの種々の側面を図示する。この発明の３次元ナビゲーションシステムは、ユーザが回転、ズーミング及びパンニングのごとき種々の観察機能を制御することを可能とする。この発明の１つの側面によれば、システムはまた３次元モデルを観察する際に、現在のズーム画像に基づいて計算される動力学的回転軸を用いる。この側面によれば、回転の中心は現在の図及びズーム比或いは係数に基づいて動力学的に変化され且つ計算され、従って前記パーツのズームされた領域は前記パーツが例えば高いズーム比或いは係数において回転される時、前記スクリーンから消えることがない。
【０２６０】
この発明の１つの側面によれば、３次元操作及びナビゲーションシステムが前記設備のステーションモジュール及び／又はサーバモジュールに提供される。３次元ナビゲーションシステムの工程及び操作は、ソフトウエア或いはプログラムされた論理を介して且つ広い範囲のプログラム言語及び教示の１つを用いて実行される。例えば前記システムはＣ＋＋のごとき高レベルのプログラム言語を用いて且つオブジェクト指向プログラム技術を用いて実行される。更に限定しない例として、ＶＩＳＵＡＬ  Ｃ＋＋が使用される。それはウィンドウズに基づくアプリケーションのためにマイクロソフト株式会社により提供されるＣ＋＋プログラム言語の１つのバージョンである。前記観察機能（例えばズーム、回転、パン等）は上記した本発明の曲げモデルビューアの観察クラスの要素機能として実行される（例えば図２７及び上記関連の開示を見よ）。前記現在ズーム係数及びパーツの位置（例えば３次元空間におけるパーツの位置）に関する情報は、また、前記動力学的回転軸を計算し且つ所望の観察機能を提供するために前記曲げモデルビューアからアクセスされる。
【０２６１】
種々のハードウエア成分及びインタフェースが、本発明の３次元ナビゲーションシステムを実行するために提供される。例えばシステムを実行するために使用されるソフトウエアが前記ステーションモジュール及びサーバモジュールのコンピュータ或いはパーソナルコンピュータに設けて有り或いは存在する。上で議論したように、前記コンピュータ或いはパーソナルコンピュータは、板金パーツの３次元表示をユーザに対して表示するために、高解像度モニタのごとき図形カード及び表示スクリーン或いはターミナルを含む。前記コンピュータ或いはパーソナルコンピュータはまた、前記マウス或いはジョイスティック装置と接続し及びインタフェースするためのマウス或いはゲームポートアダプタを含む。商業的に入手可能なソフトウエアも設けられており、ユーザにより操作されるマウス或いはジョイスティック装置からマウス或いはゲームアダプタカードにより受信される指令信号を解釈する。
【０２６２】
図５０ａ及び５０ｂは、例えば単純な３次元箱形状パーツを回転するために多重軸ジョイスティック１１２により行われる回転機能の例を図示する。上に述べたように、ジョイスティックは設備を通して設けられているステーションモジュール及び／又はサーバモジュールに設けられているコンピュータ或いは装置に設けられ且つ接続されている。図５０ａ及び５０ｂに示すように、前記パーツの回転は、前記ジョイスティック１１２を前後に且つ左右に移動することにより行なわれる。前記回転軸の方向或いは向きは前記ジョイスティック１１２（或いはマウス）の移動に基づいて設定される。例えば前記ジョイスティック１１２を前後に移動させることは、パーツを前記Ｘ座標軸に沿って定義される回転軸の周りに時計方向或いは反時計方向に回転させることをもたらす（例えば図５０ａを見よ）。更に前記ジョイスティック１１２を左右に動かすことは、前記パーツを前記Ｙ座標軸に沿って定義される回転軸を中心として時計方向或いは反時計方向に回転させることをもたらす（例えば図５０ｂを見よ）。
【０２６３】
現在の図のズーム比或いは係数が低く、パーツの全体表示がスクリーン上に提供される時、前記回転軸は前記パーツの幾何学的中心或いは図芯を通るように定義される。上記したように、前記ズーム係数及びスクリーン上のパーツの観察可能性は、本発明の曲げモデルビューアにより提供される観察可能性機能に基づいて決定される。スクリーン上にパーツ全体が表示されると判断される時（図５０ａ及び５０ｂにおけるそれのように）、回転軸を定義しそしてその回転軸を前記パーツの幾何学中心へ設定するために座標幾何技術が用いられる。前記パーツの回転は、次に、前記ジョイスティック装置のユーザにより定義された移動に基づき、且つこの発明の曲げモデルビューアの回転要素観察機能を介して実行される。しかし仮に前記オブジェクトの一部のみが画面に表示され、前記パーツの幾つかの部分は見えない場合（例えば高いズーム係数或いは比率が選択された時）、前記回転軸は、前記パーツの幾何学中心或いは図芯に維持されるべきではない。それはそのようにすることは、回転中に前記パーツのズーム化された部分がスクリーンから消えるからである。実際この発明によれば、ズーム比が増大される時、回転軸は動力学的に再計算され、前記スクリーンのセンターにおける観察点（或いはカメラ視野）に最も近い点の座標を通る。前記ズーム係数の変化に基づいて、前記回転軸を動力学的に再計算することにより、前記パーツは、前記パーツの観察可能な部分が回転の間に画面からはみ出すことにならない軸を中心として回転される。
【０２６４】
前記３次元モデルのズーミング及びパンニングを行なうために、前記ジョイスティック或いはマウス装置と別個に或いはそれと共に設けられたキーパッドに追加の制御ボタンが設けられる。例えばズームボタン１１４を押すと共に、ジョイスティック１１２を前後に移動することにより、図５１に示すように、所定の割合で前記パーツはズームインまたはズームアウトされる。上記したように、前記回転軸は各ズームウィンドウの中で再計算され、回転がなされる時、ユーザが前記パーツのズーム化された部分を観察することができるようにする。更に、３次元形状のパンニングは、図５２に示すように、パンボタン１１６を押圧し或いは活性化し且つジョイスティック１１２を移動することにより、ユーザにより制御される。前記ズームボタン１１４の場合と同様に、パンボタン１１６は前記設備の種々の位置の各々における前記ジョイスティックまたはマウス装置と別個に或いはそれらと一緒に設けられたディジタル入力パッドの上に設けてある。
【０２６５】
この発明の代表的な実施例に応じて、前記３次元ナビゲーション及び操作を実行するために設けられた種々の工程及び操作が図５３−５５を参照して以下に記載される。上に示したように、前記３次元ナビゲーションシステムの必要な工程及び操作はソフトウエア或いはプログラムロジック及びハードウエア成分及びインタフェースの組み合わせを介して実行される。ジョイスティック或いはマウス装置のごときユーザにより制御される装置からの入力信号は所望の表示されたパーツの運動及び再配向の量を決めるように解釈される。この発明によれば、表示されたパーツの回転軸は、回転中にパーツのズーム化された領域が画面から消えるのを防止するため、現在の画面及びズーム係数に基づいて動力学的に計算される。
【０２６６】
表示されたパーツの現在の画面を更新する際に、図５３のステップＳ３０１に一般的に示されるように、前記ジョイスティック或いはマウス装置の操作に基づいてユーザからの信号が受信される。ユーザにより前記ジョイスティック或いはマウス装置の特定の方向の運動及び／又は特殊な制御ボタンの活性化との組み合わせが、所定の観察機能（例えば回転、ズーム、パン等）及び表示されたパーツの所定の方向（例えば時計回り或いは反時計回り、ズームイン又はズームアウト、右又は左等）の運動を、図５０−５２に例えば示されるように、引き起こす。受信された信号は、それらがジョイスティックからであるかマウス装置であるかを問わず、カーソルの移動に写像され、ユーザにより所望されるスクリーン上の移動量を決定する。ユーザが前記観察機能モードのうちの１つに存在しない場合（例えばユーザがスクリーン上の情報を選択しているか或いはダイアログボックス或いはウィンドウ内の情報を観察している場合）、前記受信した信号の写像は要求されない。
【０２６７】
当業者により理解されるように、通常のジョイスティック或いはマウス装置から受信される信号はスクリーン空間のそれとは異なる座標或いは参照システムに基づいており、従ってそれらは前記スクリーン上のカーソル移動に関する意味のある情報を提供するために翻訳されなければならない。従って前記ユーザからの入力信号を受け取った後、ステップＳ３０３に示されるように、回転軸の計算及び表示されたパーツの現在の図を更新する前に受信された信号はカーソル移動に写像される。
【０２６８】
ユーザにより制御される装置からの入力信号をスクリーン空間上のカーソル運動に翻訳及び写像するために異なる方法及び工程が使用される。伝統的には、マウス装置の移動は、商業的に入手可能なソフトウエアによりカーソル移動へ翻訳され且つ写像されていた。例えばウィンドウズ９５及びウィンドウズＮＴは、マウス移動をカーソル移動へ翻訳するためのソフトウエアルーチンを含む。従って、マウス装置の移動は、そのような商業的に入手可能なソフトウエアによりカーソル移動に写像される。しかしながらユーザにジョイスティックインタフェースが与えられている場合、有用な情報を提供するには、前記ジョイスティック運動もカーソル運動へ翻訳され且つ写像されなければならない。前記ジョイスティック仮想空間におけるジョイスティックの運動をスクリーン空間におけるカーソル運動へ写像するために種々の方法及び技術が使用される。例えば、ジョイスティックの移動信号は、最終的にカーソル運動へ写像される前に、まずマウス運動へ加工され且つ翻訳される。或いは、前記ジョイスティック仮想空間のサイズに対するスクリーン空間のサイズの比率の関数として、前記ジョイスティック信号は直接カーソル運動へ写像される。
【０２６９】
図５４は、この発明の１つの側面に基づく、ジョイスティック運動のスクリーン空間内でのカーソル運動への写像の例を図示する。上に示したように、ジョイスティック装置は自身の仮想的座標システム或いは空間２１８を含む。前記ジョイスティック仮想空間２１８は、前記ジョイスティックが中心或いは中立位置  （即ちジョイスティックが移動しない位置）に存在する位置に対応する原点Ｊ１を含む。前記ジョイスティックが新しい位置（例えば図５４に示されるように現在の位置Ｊ２）へ移動する時、前記ジョイスティック装置は前記ジョイスティックの仮想空間内での新しい或いは現在の位置を示す信号を生成する。前記ジョイスティック仮想空間２１８は、しばしばスクリーン空間２１２よりも大きい（画素の意味で）ので、前記ジョイスティックの仮想座標及び移動は、所望のカーソル移動従ってスクリーン上でのパーツの移動を決定するためにスクリーン座標へ翻訳されなければならない。
【０２７０】
前記ジョイスティックの仮想座標移動をスクリーン座標移動へ写像し且つ翻訳するために種々の方法及び工程が使用される。例えば、前記ジョイスティック仮想空間サイズに対するスクリーン空間サイズの比率に基づいて、ジョイスティック運動はスクリーンカーソル運動へ写像される。より詳細には、観察機能モード（例えばズーム、回転、パン等）が活性化され、ジョイスティック装置がユーザにより操作された時、前回の点Ｃ１から現在の点Ｃ２へのカーソルの実際の移動は次の式で決定される。
【０２７１】
現在の点＝前回の点＋（スケール係数ｘ  Ｖ）
ここに「現在の点」はカーソルの現在の点Ｃ２であり、「前回の点」は前記カーソルの前回の点Ｃ１であり、「スケール係数」はジョイスティック仮想空間サイズに対するスクリーンサイズの比であり（いずれも画素において）、「Ｖ」はジョイスティック原点Ｊ１からジョイスティック現在位置Ｊ２へのジョイスティックの運動及び方向を表すベクトルである。従ってジョイスティック運動をカーソル運動へ写像するために、ジョイスティック装置がユーザにより操作される時ジョイスティック装置から受け取られる信号に基づいて、前記原点Ｊ１から現在位置Ｊ２へのジョイスティックの方向及び運動を示すベクトル「Ｖ」が最初に計算される。このベクトル「Ｖ」が計算された後、前記ジョイスティック運動は、前記方程式における前記ベクトル「Ｖ」量及び前記「スケール係数」量を用いてカーソル運動へ写像される。即ち、前記カーソルの新しい或いは現在の位置Ｃ２は、前記ベクトル「Ｖ」に前記ジョイスティック空間サイズに対するスクリーンサイズの比（即ちスケール係数）を掛け合わせ、次にこの計算の結果を以前のカーソル位置Ｃ１に足し合わせることにより計算される。
【０２７２】
前記スケール係数に応じて、前記スケール或いは運動の割合を所定の或いはユーザにより選択された調整係数だけ増大し又は減少することが必要となる。そのような場合には、そしてユーザの好みにより、前記スケールの割合を増大し又は減少するために、前記カーソルの現在位置を計算する時に、前記スケール係数に調整係数が掛けられる。例えば、前記ジョイスティック空間サイズに対するスクリーンサイズの割合がスケール係数１／６４を与える場合、ジョイスティックの運動とスクリーン上の表示されたパーツの運動の割合との間の一層満足できる関係を与えるために、スケールの割合を増大するのが望ましい。限定的でない例として、スケール係数１／６４について、前記表示されたパーツをズームし或いは回転する際調整係数３が用いられる。更にスケール係数１／６４について、表示されたパーツのパンニングが行なわれる際には調整係数６が使用される。勿論、スケーリング（縮尺）の割合は、ユーザの特定の必要に基づいて修正され、前記調整係数は予め決定され或いはユーザが、前記スケールの割合を修正するための調整係数を調整或いは選択するためにオプションを与える。更に上に議論した事例において示したように、前記調整係数は複数の観察機能の各々について同じ量に設定されてもよいし、前記観察機能の各々について、同じ或いは異なる量に個別に設定されてもよい。
【０２７３】
受信された信号が適当に写像され翻訳された後、前記パーツの回転軸が、図５３のステップＳ３０５に一般的に示されるように動力学的に計算される。前記パーツの現在の図に依存して、前記パーツが例えば高いズーム比率或いはファクターで回転される時、前記パーツのズーム化された領域がスクリーンから消えないように、前記回転軸は前記パーツの中心を通るか或いは他の点を通るか決定される。現在のズーム図に基づいて、前記パーツの回転軸を動力学的に再計算するために種々の方法及び工程が使用される。この発明の他の側面に応じて、図５５は前記パーツの図がユーザにより修正された時常に前記回転軸を計算するために行なわれるプロセス及び工程の代表的論理フロー及び手順を図示する。
【０２７４】
図５５に示されるように、現在のズーム係数或いは比率及びパーツの位置及び現在の図がステップＳ３１１及びＳ３１３で決定される。ユーザにより選択された表示パーツのズーム係数及び向きが、パーツ全体をスクリーン上で観察可能にする（即ち全体図）か、或いは前記パーツの一部のみをスクリーン上で観察可能にする（即ち部分図）。従って現在のズーム係数及びパーツの向きが、表示パーツの回転軸を適正に設定するために定められなければならない。前記パーツの現在の図を決定するために種々の方法及び工程が使用される。上に記載したように、観察可能性機能は、本発明の曲げモデルビューアを備え、表示される画像に対する変更が存在する場合には何時も、現在の図の向き及びズーム比率の状態を維持しそして更新する。前記曲げモデルビューアに対する機能コールがなされ、前記パーツのどの点或いは部分が現在観察可能であるかを決定する。スクリーン上に前記パーツの全てが表示されているかどうかは画像体積をパーツの境界基本線サイズと比較することにより決定される。
【０２７５】
ステップＳ３１５でパーツの全体図が現在スクリーン上で観察可能であると決定される場合には、ステップＳ３１７で前記回転軸は前記パーツの中心を通るように設定される。全体図が存在する時、前記パーツの中心を前記回転軸が通るように設定することは可能である。というのは全体が表示されたパーツはユーザにより回転される時スクリーン上で観察可能であるからである。スクリーン上で全てのパーツが観察可能である時、回転軸はパーツの幾何学中心或いは図芯を取るように定義される。従来の座標幾何学技術が、前記パーツの幾何学中心へ前記回転軸を定義し設定するために用いられる。更に前記回転軸の方向は、前記前回のカーソル位置から現在のカーソル位置へのベクトルに直交するベクトルとして定義されることもできる。
【０２７６】
ステップＳ３１５で、スクリーン上にパーツの部分図のみが現在観察可能であると判断される場合、ズーム化されたパーツがユーザにより回転される時表示されたパーツの一部がスクリーンから消えないようにするために、回転軸を計算するために、前記論理フローはステップＳ３１９−Ｓ３２５へ引き続く。上記したように、ユーザにより高いズーム係数が選択され前記パーツの一部のみがスクリーン上に表示される時、前記回転軸は、前記パーツの幾何学中心を通るように設定されてはならない。というのは、そのようにすることは、回転中に表示されたパーツのズーム化された部分（ズームアップされた部分）がスクリーンから消えるからである。パーツの表示された部分がスクリーンから見えなくなり或いは消えることを防止するために、スクリーンの中心における観察点（即ちカメラ）に最も近い点の座標を前記回転軸が通るようにされなければならない。そのような場合、回転軸の向きは前回のカーソル位置から今回のカーソル位置へのベクトルに直交するベクトルとして定義されても良い。
【０２７７】
従ってステップＳ３１９で、スクリーンの中心が決定され、カメラに最も近いスクリーンの中心におけるオブジェクト或いは前記パーツの部分が選択される。即ち、スクリーンのセンターに位置する表示パーツの部分及びカメラに最も近い或いはスクリーンのユーザの観察点に最も近い表示パーツの部分が取り出される。ステップＳ３２１で、前記カメラにおけるオブジェクトが存在すること（例えば前記スクリーンの中心に位置し且つ前記カメラに最も近い前記パーツのソリッド部分が存在すること）が決定される場合、ステップＳ３２５で前記回転軸は前記取り出された点を通るように設定される。上記したように、回転軸の方向は前回のカーソル位置から今回のカーソル位置へのベクトルに直交するベクトルとして定義されても良い。
【０２７８】
ステップＳ３２１でカメラにおけるオブジェクトが存在しない（例えば前記パーツは前記スクリーンの中心に位置し且つ前記カメラに最も近い穴或いは開口部を含む）と判断される場合、論理フローはステップＳ３２３へ引き続く。ステップＳ３２３で、前記回転軸は前記スクリーンの中心（例えば前記スクリーンの物理的中心のＸ及びＹ座標）を通り且つ前記パーツの幾何学中心に等しいＺ座標（深さ）にあるように定義される。従って回転軸は前記Ｘ，Ｙ，Ｚ座標を通るように設定され、回転軸の向きは前回のカーソル位置から今回のカーソル位置へのベクトルに直交するベクトルとして定義されても良い。
【０２７９】
図５３を再び参照するに、前記動力学的回転軸が決定された後、選択された観察機能（例えばズーム、回転、パン等）がステップＳ３０７で呼び出される。上記したように３次元操作システムの種々の観察機能は前記曲げモデルビューア観察クラスの要素機能として定義され実行される（例えば図２７及び関連する上記開示を見よ）。そのような場合、ユーザにより選択された観察機能に基づいて、機能コールが前記曲げモデルビューアになされ、ステップＳ３０９で表示されたパーツの現在の図が更新される。前記パーツの現在の図及び向きは、ユーザにより選択された観察機能及びユーザにより操作された入力装置（マウス或いはジョイスティック装置）からの受信された写像カーソル運動に基づいて更新される。オープンＧＬ或いはレンダウェアのごときグラフィックパッケージが、ユーザに提供される現在の図の更新を容易にするために提供される。図５３及び５５の代表的フローチャートにおいて行なわれる論理フロー及びプロセスはソフトウエアにより及び広い種類のプログラム言語及び技術を用いて実行される。例えばオブジェクト指向プログラム技術及びＣ＋＋が前記プロセス或いは操作を実行するために使用される。この発明の３次元操作システムを実行するための代表的コードが付録Ｌに提供される。代表的コードはＣ＋＋プログラム言語で書かれ、前記動力学的回転軸を計算するための種々の工程及び操作を含む。付録Ｌのコードにはコメントが提供され、そこに使用される論理及びアルゴリズムの解析を容易にする。
【０２８０】
上記３次元操作システムはジョイスティック装置及び制御ボタンの使用に関して記載されているが、このシステムは、マウス或いはキーボードを含む他の特定のタイプの入力手段により実行されることもできる。更に図５１−５２の上記実施例では、前記オブジェクトのスクリーンから無限への又はその反対のズーミング或いはパンニングを制限するために境界が定義される。というのは連続的なズーミング或いはパンニングはシステムを故障させ或いは破壊させるからである。
【０２８１】
更に、前記ジョイスティックインタフェースに関連して種々の他の機能が実行される。例えば、前記観察機能のいずれかにおける移動は、ジョイスティックがジョイスティックセンター位置から所定の範囲或いは距離を越えて移動されなければ実行されない。パーツの移動が許される前にそのようなジョイスティックの移動のしきい値を要求することは、前記中心点からの前記ジョイスティックの不注意な操作或いは押圧に基づいて、表示されたパーツの偶然の移動の発生を防止する。ユーザとのジョイスティックインタフェース及びシステム相互作用を改善するために他の機能がまた設けられる。例えばユーザによるジョイスティックの単一の操作に基づいて、前記観察機能（例えばズーム、回転、パン等）のいずれか１つにおける連続的或いは増加的（例えばステップごと）の移動が提供される。前記連続的或いは増加的移動の選択はまた単一の方向におけるジョイスティックの移動の量或いは時間に基づいて提供される。必要ならば表示されるパーツのスケール或いは移動の割合は、任意の方向におけるジョイスティックの運動の程度或いは時間に基づいて増加される。上記した速度調整係数の修正はまた、ユーザが前記スケールの比率を増加し或いは減少するために、マニュアルで調整係数に対する補正を入力することを可能とすることにより実行される。
【０２８２】
工場における部品の設計及び製造における支援を行なうために、本発明において種々の他の機能及び実施例が実行される。例えば各顧客のオーダに関する情報を追跡し且つアクセスするためにバーコードシステムが実行される。所定の参照番号或いは作業番号を有するバーコードが顧客により注文される各部品へ割り当てられる。このバーコードはデータベース３０にアクセスし作業情報を読み取るために用いられる。ユタ、サンディにおけるゼブラテクノロジＶＴＩからのバーコード・エニシング・バーコードＳＣＡＮ  ＣＣＤセンサのごときバーコードリーダ或いはスキャナが各場所に設けられ、ユーザが前記サーバモジュール或いはステーションモジュールにおいて所定の作業のためのバーコードをスキャンすることを可能にし、またデータベース３０に格納されているそのパーツに付随する重要な設計及び製造情報をアクセスし読み出すことを可能にする。前記バーコードリーダは各ステーションモジュール及び／或いはサーバモジュールのコンピュータに差し込まれている。前記バーコードは任意の通常のバーコードフォーマットに基づいてフォーマット化されている。例えばＵＰＳ−Ａ  ＣＯＤＡ  ＢＡＲ
ＣＯＤＥ３９  ＥＡＮ／ＪＡＮ−８或いはＰＬＥＳＳＥＹである。そして結果としてのバーコードナンバーはルックアップテーブルに基づいて翻訳され、前記データベースから作業情報を読み出すために、対応する作業参照番号及び／又はファイル名を検出する。或いは、前記作業番号は、工場全体にわたって存在する任意のステーションにおいて表示される指示へタイプ入力され或いはそこから選択され、瞬時にユーザの位置で作業情報を読み出し表示する。そのような情報を瞬時に読み出す能力は、コミュニケーションネットワーク２６の使用及びデータベース３０のごとき中央に位置するデータベースへの前記デザイン及び情報の格納により支援される。
【０２８３】
この発明の更に他の側面によれば、作業をスケジュールし割り当てるための装置及び方法が提案されるシステムに設けられる。従来、製造設備にわたる作業のスケジュール化及び割り当てはショップ或いは工場の工場長により行なわれた。工場長は、機械装置の現在のセットアップ及び利用可能性のみならず現在の仕事の状態を決定する。これらの情報を集め且つ分析した後、ショップ或いは工場の工場長はスケジュールを生成し且つ工場における種々の場所においてなされる作業について割り当てを分配する（例えば工場フロアに分配される作業スケジュールシートの形態で）。作業のスケジュール割り当ては、各顧客の作業がタイミングの良い形態で且つ所定の出荷日までに完了することを確実にするために行なわれる。作業のスケジュール化及び割り当ての従来の工程はしかし骨の折れるものであり、通常工場長によりマニュアルで行なわれていた。
【０２８４】
この発明の１つの側面によれば、ショップ或いは工場の工場長がその工場についての作業のスケジュールを立てることを支援するために、作業割り当て及びスケジュールシステムが設けられている。そのシステムはコミュニケーションネットワーク及びデータベース３０に格納されている曲げモデル情報を利用し、自動的に必要な情報を集め、従って工場長はより容易に作業スケジュールを生成することができる。このシステムは、前記サーバモジュール或いは工場にわたって配置されているステーションモジュールにおいてソフトウエア又はプログラムロジックを介して実行される。スケジュールされるべき種々の作業を入力することにより、システムソフトウエアはデザイン及びパーツ情報を分析し所定の作業を行なうためにどの機械が最も適しているかを決定する。この目的のため、工場における機械の現在の状態及びセットアップが定義され、データベース３０に格納され、作業スケジュールソフトウエアによりアクセスされる。種々の条件に基づいて、表示の形態で、特定の作業を実行するためにどの機械が利用可能であるか及びどの機械が他の仕事を実行することができないかを示唆する。この点について、特定の作業について機械の利用可能性をランク付けし且つ提案作業スケジュールを提供するテーブルが表示される。前記提案作業スケジュールは工場長により実行され或いは修正される。作業スケジュールを設定し且つ推薦するために使用される条件は広い種類の条件を含む。そしてそれは、工場における各マシンの現在のセットアップ、各作業について必要とされる曲げのタイプ及び工具、及び同じ時間枠或いは時間の間に実行されなければならない他のタイプの作業を含む。どの機械が特定の作業を実行できるかを決定するために、前記曲げ角度、フランジ長さ及び曲げのタイプを含む各パーツについての曲げモデルファイルからの情報が利用される。例えばデータベース３０に格納されているテーブルは前記工場フロアにおけるパンチング及び曲げ機械の各々の現在のセットアップ及び能力についての重要な情報を含む。
【０２８５】
提案された作業スケジュールに基づいて、工場長は、工場の生産及び出力能力を最大限にするために、複数の作業を工場全体にわたる種々の場所へ割り当てる。最後の作業スケジュール或いは割り当ては電子的に入力されコミュニケーションネットワーク２６を介して機械の各々へ送られる。
【０２８６】
ＬＥＤのごときパイロットランプが曲げ及び機械装置ワークステーションの各々に設けられ、そのステーションに作業が割り当てられ転送されたことを指示し且つ確認する。前記作業割り当て及びスケジュールは、工場内の任意の位置から瞬時にアクセス可能なサーバモジュールのファイルに格納される。上記機能に加えて、その他の機能が、この発明の教示に応じて実行される。例えば種々のステーションモジュール或いは位置にメニュースクリーンが設けられ且つ表示され、ユーザがこの発明の種々の表示及び機能モードを選択するのを容易にする。例えば図５６に示されるそれのごときメインのメニュースクリーンが、前記ステーションモジュールが開始される際にユーザに対して提供される。このメインメニューウインドウ表示はステーションモジュールにより提供される利用可能なウインドウ表示及び観察モードの各々のアイコン画像を含む。このメインメニュースクリーンはメニューボタン（例えばＦ１キー）が選択されるとき何時でも現れる。ユーザは、強調されたブロックを所望のウインドウアイコンへ移動しそれを選択することによりそのウインドウを選択する。そのような操作は、キーボード、マウス或いはジョイスティックの使用を介して行なわれる。
【０２８７】
他のウインドウスクリーンもユーザに対して提供され且つ表示され作業情報の入力及び表示を容易にする。例えばパーツ情報ウインドウは、ユーザがパーツ情報を入力し或いは修正するのを可能にするために表示される。パーツ情報ウインドウ表示の例が図５７に与えられる。このパーツ情報ウインドウは全ての関連するパーツ情報（例えばパーツ番号、材料タイプ、寸法等）を含み、板金パーツの２次元平面図及び等測投影法図を含む。曲げ線情報ウインドウ（例えば図５８に示されるもの）は、ユーザが各曲げ線についての曲げ順及び縮小量を含む種々の曲げ線情報を監視することを可能とするために設けられる。前記曲げ線情報ウインドウはユーザが、各曲げについての曲げ線情報を入力し或いは修正するのを可能とし、板金パーツの２次元平面図及び等測投影図を含む。
【０２８８】
オペレータの曲げ順の分析を容易にするために、追加のウインドウ表示が提供される。例えば曲げ順ウインドウ表示及び曲げシミュレーションウインドウ表示が提供され、前記パーツの種々の曲げ段階を表示し、且つ曲げ操作中におけるパーツの向きをシミュレートする。図５９に示されるような曲げ順ウインドウは前記メインメニュースクリーンから選択され曲げ順の各段階における前記パーツの（静止状態における）中間形状をユーザに対して表示する。曲げシミュレーションウインドウ（例えば図６０を見よ）もユーザにより選択され、曲げ段階の静止情報（スクリーンの右側に提供されるパーツアイコンの形態で）及び、曲げ順における各段階で行なわれる位置付け及び曲げの動的シミュレーション（表示装置の中央において）を提供する。スクリーン上のパーツアイコンを間欠的に選択することにより、ユーザは選択されたパーツアイコンにより表現される段階における、曲げ加工中でのパーツの向きの動的シミュレーションを見ることができる。各曲げ順を動的にシミュレートするために、パーツは反転され、並進移動され、曲げ線の周りで曲げられ／回転される。
【０２８９】
図５７−６０の上記ウインドウ表示の各々は、図５６のメインメニューウインドウ表示からユーザに対して選択され且つ表示される。更に、任意のステーションモジュールにおけるユーザは、メインメニューウインドウ表示において適宜のウインドウアイコンを選択し、この発明の観察モード（例えば２次元平面、ワイヤフレーム、ソリッド、正射図）に応じて表示されるパーツの２次元及び／又は３次元表示を得る。これは図２８−３１を参照して上で詳細に説明された。種々のメニューウインドウがまた例えばステーションモジュールに設けられ、この発明の特性及び機能の操作を容易にする。図６１は２次元から３次元操作のために表示される代表的メニューを図示する。更に図６２はこの発明の２次元クリーンアップ操作のための代表的メニュー構造を図示する。この発明はしかしこれらのメニュー配置に限定されるものではなく、他のメニュースクリーン及び／又は工具アイコンバーが設けられ、ユーザのシステムとの相互作用を容易にする。
【０２９０】
他の特性もまたこの発明において実行される。例えば、高いレベルの自動装置も提供され曲げプランの生成を容易にする。例えば曲げ及び工具立てエキスパートシステムが提供され、各作業についてのパーツの幾何形状及び形状に基づいて工具立てセットアップ及び曲げ順を生成し且つ提案する。それは例えば米国特許出願出願番号０８／３８６．３６９及び０８／３３８．１１５に開示されるようなものである。
【０２９１】
この発明は幾つかの代表的な実施例を参照して記載されたがここで用いられた用語は、限定の用語ではなく、記載及び説明の用語である。この発明の範囲及び精神及び種々の側面から逸脱することなく種々の変形がなされ得る。この発明はここで特定の手段、材料及び実施例を参照して記載されたが、発明はここに開示された特定のものに限定されるように意図されるものではない。むしろ発明は全ての機能的に等価な構造、方法及び使用に広がる。
【０２９２】
付録Ａ
曲げモデルパーツからのフィーチャエンティティ抽出の例
.int SPS_cal_part_matrix ( BM_PART *part, FENT **inp_sp,char*pname,int *inp_parrank, int*inp_part_numface,int *inp_part_numbend, int*inp_part_maxface ){// local variablesint parrank, part_numface, part_numbend, part_maxface ;int **imatrix = NULL ;int *nbl_face = NULL ;BENDFACE *facelist= NULL ;BENDLINE *bendlinelist = NULL ;ARTIFICIAL_FACE *bendfacelist = NULL ;int num_error = 0 ;//counter for the number of errors in the partint face_1, face_2, bend_1, bend_0, i ;long num_of_faces, num_of_bendlines, entity_id;BM_FACE     *face;BM_BENDLINE *bendline;BM_2D_BODY  *two_d_body;BM_3D_BODY  *three_d_body;BM_BEND_OP  *bend_op;BM_TOPOLOGY_RECORD  *topology_record;// get name and number of faces and bendlines of the partpart->get_name( pname ) ;double thickness = part->get_metal_thickness();num_of_faces = part->get_number_of_faces() ;num_of_bendlines = part->get_number_of_bendlines();if (num_of_faces == 0 || num_of_bendlines == 0)return ( -1 );// create local working arrayfacelist = new BENDFACE [num_of_faces];bendlinelist = new BENDLINE [num_of_bendlines];// count number of faces defined.double maxfacearea = -1.0 ;part_maxface = 0 ;part_numface = 0 ;face = part->get_face_list() ;for ( i = 0 ; face && i < num_of_faces ;i++, face = (BM_FACE *)(face->next())) { // Count the defined faces.// initialize the strucfacelist[i].faceid = 0 ;facelist[i].facept =NULL ;facelist[i].twodpt = NULL ;facelist[i].threedpt = NULL ;facelist[i].topologyrecpt = NULL ;facelist[i].numadjbody = 0 ;facelist[i].numadjbend = 0 ;facelist[i].numadjhole = 0 ;facelist[i].numadjface = 0 ;facelist[i].face_area = 0. ;if (face == NULL) break ;two_d_body = face->get_3D_version() ;if (two_d_body == NULL) continue ;// It is considered as a valid face, when its BM_2D_BODY exists.part_numface++ ;facelist[i].faceid =part_numface ;facelist[i].facept = face ;facelist[i].twodpt = two_d_body ;facelist[i].face_area = area_of_a_2D_body(two_d_body) ;if (maxfacearea < facelist[i].face_area) {maxfacearea = facelist[i].face_area ;part_maxface = facelist[i].faceid ;} three_d_body = two_d_body->get_3D_body() ;facelist[i].threedpt = three_d_body ;if (three_d_body == NULL) continue;entity_id = three_d_body->get_name() ;facelist[i].org_entity = entity_id ;topology_record = three_d_body->get_adj_list() ;facelist[i].topologyrecpt = topology_record ;if (topology_record == NULL) continue ;facelist[i].numadjbody = (int)topology_record->get_number_of_adjacent_bodies() ;facelist[i].numadjface = (int)topology_record->get_number_of_adjacent_faces() ;facelist[i].numadjhole = (int)topology_record->get_number_of_adjacent_holes() ;facelist[i].numadjbend = (int)topology_record->get_number_of_adjacent_bendlines() ;}if (num_error > 0) {clean_up ( part_numface, imatrix, nbl_face, facelist,bendlinelist, bendfacelist) ;return ( num_error ) ;}if (part_numface == 1) {// this is a trivial case, where the partonly has one flat face.*inp_part_numface = part_numface ;*inp_parrank =part_numface ;*inp_part_numbend = 0 ;*inp_part_maxface = 1 ;*inp_sp = new FENT [2] ;*inp_sp[2] = NullFent ;clean_up ( part_numface, imatrix, nbl_face, facelist, bendlinelist, bendfacelist) ;return ( 0 ) ;}// varify all the valid face, the current requirements are://1) A face cannot be adjacent to another face.//2)A face without an adjacent bendline is not allowed.//(Note: The single faced part has been processed.)// Also, creata pointer array that links assigned part_face_id// to the netry in the facelist.int *fid_pt = new int [part_numface] ;for ( i = 0 ; i < num_of_faces ; i++) {if (facelist[i].faceid) {fid_pt[facelist[i].faceid] = i ;if(facelist[i].numadjface ||facelist[i].numadjbend < 1) num_error++ ;}}if(fid_pt) delete [] fid_pt ;if (num_error > 0) {clean_up ( part_numface,imatrix, nbl_face, facelist, bendlinelist, bendfacelist) ;return ( num_error ) ;}// count the number of bendlines that is defined.part_numbend= 0 ;bendline = part->get_bendline_list() ;     for ( i = 0 ; bendline && i < num_of_bendlines ;i++, bendline = (BM_BENDLINE *)(bendline->next())) {// initialize the structbendlinelist[i].bendlineid = 0 ; bendlinelist[i].bendlinept = NULL ;// BM_BENDLINE pointer bendlinelist[i].bendoppt   = NULL ;// BM_BEND_OP pointerbendlinelist[i].twodpt    = NULL ;// BM_2D_BODY pointerbendlinelist[i].threedpt   = NULL ;// BM_3D_BODY pointerbendlinelist[i].topologyrecpt = NULL ;// BM_TOPOLOGY_RECORD pointerbendlinelist[i].numadjbody = 0 ;bendlinelist[i].numadjbend = 0 ;bendlinelist[i].numadjhole = 0 ;bendlinelist[i].numadjface = 0 ;    if (bendline == NULL) break ;two_d_body = bendline->get_3D_version() ;if (two_d_body == NULL) continue ;// It is considered as a valid bendline, when its BM_2D_BODY exists.part_numbend++ ;bendlinelist[i].bendlineid = part_numbend ; bendlinelist[i].bendlinept = bendline ;// BM_BENDLINE pointer bendlinelist[i].twodpt = two_d_body ; // BM_2D_BODY pointerbend_op = bendline->get_bend_op() ; bendlinelist[i].bendoppt = bend_op ;// BM_BEND_OP pointerif (bend_op == NULL) num_error++ ;// Note: Bend operation must be defined for each //       bendline, otherwise it is an error.three_d_body = two_d_body->get_3D_body() ;bendlinelist[i].threedpt = three_d_body ; // BM_3D_BODY pointerif (three_d_body == NULL) continue ;entity_id = three_d_body->get_name() ;facelist[i].org_entity = entity_id ;topology_record = three_d_body->get_adj_list() ;bendlinelist[i].topologyrecpt = topology_record ;if (topology_record == NULL) continue ;bendlinelist[i].numadjbody = (int) topology_record->get_number_of_adjacent_bodies() ;bendlinelist[i].numadjface = (int) topology_record->get_number_of_adjacent_faces() ;bendlinelist[i].numadjhole = (int) topology_record->get_number_of_adjacent_holes() ;bendlinelist[i].numadjbend = (int) topology_record->get_number_of_adjacent_bendlines() ;}if (num_error > 0) {clean_up ( part_numface, imatrix, nbl_face, facelist, bendlinelist, bendfacelist) ;return ( num_error ) ;}// varify all the valid bendlines, the current requirements are://1) The total number of bendlines should not be less than//    the totalnumber of faces  minus 1.// 2) A bendline without an adjacent face or bendline is not allowed.// 3) A bendline with more than two adjacent faces and bendlines is not allowed.//4)The adjacent face or bendline of a bendline must bea valid face or//    bendline that is defined in the facelist or bendlinelist.// 5) Two adjacent faces, face1 and face2, will be defined for each bendline//    a) If the bendline has an adjacent faces,then the face’s faceid is used//       as face1 or face2.//b) If the bendline has an adjacent bendline, thena bendline_only_face//       will be created inbetween these two bendlines.  The faceid of the // bendline_only_face will be used as face1 or face2.//c)If the bendline has only one adjacent face or adjacent bendline, then//a bendline_only_face will becreated for this bendline.  The faceid of//       the bendline_only_face is face2.// maxnewfaces is the maximum number of bendline_only_face need to be created// without encounter error in the part.if (part_numbend> part_numface-1) num_error++ ; // condition 1if (num_error > 0) {clean_up ( part_numface, imatrix, nbl_face,   facelist, bendlinelist, bendfacelist) ;return ( num_error ) ;}int maxnewfaces = part_numbend + 1 - part_numface ;if (maxnewfaces > 0) {bendfacelist = new ARTIFICIAL_FACE [maxnewfaces] ;bendfacelist[0].faceid = -part_numface ;}for ( i = 0 ; i < num_of_bendlines ; i++) {if (bendlinelist[i].bendlineid) {bend_0 = bendlinelist[i].bendlineid ;intnumadj = bendlinelist[i].numadjface + bendlinelist[i].numadjbend ;if (numadj < 1 || numadj > 2) num_error++ ; // condition2 & 3else {if (bendlinelist[i].numadjface > 0) { // condition 4 - firstfacethree_d_body = bendlinelist[i].topologyrecpt->get_first_face() ;face_1 = find_face_id( three_d_body, facelist, num_of_faces ) ;if (face_1 <= 0) num_error++ ;else bendlinelist[i].face1 = face_1 ; }if (bendlinelist[i].numadjface == 2) { // condition 4 - second facethree_d_body = bendlinelist[i].topologyrecpt->get_next_face() ;face_1 = find_face_id( three_d_body, facelist, num_of_faces ) ;if (face_1 <= 0) num_error++ ;else bendlinelist[i].face2 = face_1 ; }if (bendlinelist[i].numadjbend > 0) {   // condition 4 - first bendlinethree_d_body = bendlinelist[i].topologyrecpt->get_first_bendline() ;bend_1 = find_bendline_id( three_d_body, bendlinelist, num_of_bendlines ) ;if (bend_1 <= 0) num_error++ ;else {face_1= define_bendline_only_face ( bend_1, bend_0,bendfacelist, maxnewfaces );if (face_1 <= 0) num_error++ ;else {if (bendlinelist[i].numadjface > 0)  bendlinelist[i].face2 = face_1 ;else bendlinelist[i].face1 = face_1 ;}}}if (bendlinelist[i].numadjbend == 2) {   // condition 4 - second bendlinethree_d_body = bendlinelist[i].topologyrecpt->get_next_bendline() ;bend_1 = find_bendline_id( three_d_body, bendlinelist, num_of_bendlines );if (bend_1 <= 0) num_error++ ;else {face_1 = define_bendline_only_face( bend_1, bend_0, bendfacelist, maxnewfaces ) ;if (face_1 <= 0) num_error++ ;else bendlinelist[i].face2 = face_1 ;}}if (numadj == 1) {face_1 =define_bendline_only_face ( bend_0, 0,bendfacelist, maxnewfaces ) ;if (face_1 <= 0) num_error++ ;else bendlinelist[i].face2 = face_1 ;}}}}if (num_error > 0) {clean_up ( part_numface, imatrix, nbl_face,   facelist, bendlinelist, bendfacelist) ;return ( num_error ) ;}// now check whether there is any bendline only face been created// increase the part_numfaceif there is.int numregfaces = part_numface ;int numnewfaces = 0 ;if (maxnewfaces > 0) { for ( i = 0 ; i < maxnewfaces ; i++ ) {if (bendfacelist[i].faceid <= 0) {numnewfaces = i + 1 ;break ;}}part_numface += numnewfaces ;}//first create integer topological matrix to record all the topological relationsint j ;imatrix = new int *[part_numface] ;for ( i = 0 ; i< part_numface ; i++ ) {imatrix[i] = new int [part_numface] ;for( j = 0; j < part_numface; j++ ) imatrix[i][j] = 0;}for ( i = 0 ; i < num_of_bendlines ; i++ ) {// save the bendline entry + 1 in imatrixif (bendlinelist[i].bendlineid) {face_1 = bendlinelist[i].face1 ;face_2 = bendlinelist[i].face2 ;imatrix[face_1-1][face_2-1] = i+1 ;imatrix[faｃｅ＿2-1][face_1-1] = i+1 ;}}// from imatrix to find the number of bendlines of each face,nbl_face[i],// and to verify that each face has at least one bendlinenbl_face = new int [part_numface] ;for ( i = 0 ; i < part_numface ; i++ ){nbl_face[i] = 0 ;for ( j = 0 ; j < part_numface ; j++ ) {if ( imatrix[i][j] ) nbl_face[i]++;}if (!nbl_face[i]) num_error++ ;}if (num_error > 0){clean_up ( part_numface, imatrix, nbl_face,   facelist, bendlinelist,bendfacelist) ;return ( num_error ) ;}// create the Cbpart’s topological matrix’s input data FENT array// and initialize it.part->get_name( pname ) ;parrank = part_numface ;int spsize = parrank*(parrank + 1)/2 + 1;  // +1 is for End of FENT array indicator FENT *sp = new FENT [ spsize] ;for(i = 0; i < spsize-1 ; i++ )*(sp+i) = NoRelation ;*(sp+spsize-1)= NullFent ;// step 1: set up the positive or negative bend//         The included FENT’s are://*PosBend    =  ’+’;  // positive bend betweentwo faces//*NegBend    =  ’-’;  // negative bend between two faces      //*P90Bend=  ’A’;  // 90 deg positive bend angle//*N90Bend =  ’B’;  // 90 deg negative bend angle//MrPosBend  =  ’3’;  // multiple positive bendlines between two faces//MrNegBend  =  ’4’;  // multiple negative bendlines between two faces//* marks what is currently implemented.for ( i = 0 ; i < num_of_bendlines ; i++ ) {if (bendlinelist[i].bendlineid) {face_1 = bendlinelist[i].face1 ;face_2 = bendlinelist[i].face2 ;FENT btype = NegBend ;BM_BEND_OP_REGULAR *bendopregular = (BM_BEND_OP_REGULAR *)bendlinelist[i].bendoppt;if (bendopregular->get_bend_type()) btype = PosBend ;double angle = bendopregular->get_bend_angle() ;if (angle> PI) {// angle > PI => reverse bend direction and reset the bend angleangle = 2*PI - angle ;if (btype == PosBend)btype = NegBend ;elsebtype = PosBend ;}bendlinelist[i].bendangle = angle ;bendlinelist[i].bendtype  =btype ;// set up 90 degree bend typeif (angle == PI_over_2) {if (btype == PosBend)btype = P90Bend ;elsebtype = N90Bend ;}//set_FENT (sp, face_1,face_2, parrank, btype) ;}}// step 2: set up the corner relationships,which is the relation//between two faces that are connected to a commonface.//  The included FENT are://*TouchCnr   =    ’T’;  // two faces same bend dir//*OpenCnr    =    ’O’;  // two faces same bend dir//*PrllBend   =    ’P’;  // two parallel bendline same bend angle dir opposite bendline dir//*SerlBend   =    ’S’;  // two parallel bendline same bend angle dir same bendline dir//*cLnrBend   =    ’L’;  // colinear bendline same bend angle dir on one face//*DfClnrBend =    ’D’;  //colinear bendline same bend angle on different faces//*tHkOffBend =    ’H’;  // tHickness offset bendline same bend angle dir on two neighboring face//*touchCnr   =    ’t’;  // two faces opposite bend dir//*openCnr  =    ’o’;  // two faces opposite bend dir//*prllBend   =    ’p’;//two parallel bendline opposite bend angle dir opposite bendline dir//*serlBend   =    ’s’;  // two parallel bendline opposite bend angle dirsame bendline dir//*clnrBend   =    ’l’;  //colinear bendline opposite bend angle dir on one face//thkOffBend =    ’h’;  // tHickness offset bendline opposite bend angle dir on two neighboring face//* marks whatis currently implemented.// Algorithm : for every face that has more than one bend line then//a pair of any two bend lines will have relationship.for ( i = 0 ; i < part_numface ; i++ ) {if (nbl_face[i] > 1) {int face_c = i + 1 ;// create a list of faces that are connected to this face.for ( j = 0 ; j < part_numface ; j++ ) {if ( imatrix[i][j] ) {int bl_1 =imatrix[i][j] ;face_1 = j + 1 ;for ( int k = j+1 ;k < part_numface ; k++) {if ( imatrix[i][k] ) {int bl_2 = imatrix[i][k] ;face_2 = k + 1 ;// define the relation ship between the two bendlinesset_bendline_rel_FENT (sp, parrank,facelist, face_c, face_1, face_2,bendlinelist, bl_1, bl_2,outfile) ;}}}}}}//*tHkOffBend =    ’H’;  // tHickness offset bendlinesame bend angle dir on two neighboring face// from imatrix to find the faces that may be of the thickness offset bendlines//and verify these faces first based on touch cornerinfomation then based on// the bendlines’distance and parallel condition.for ( i = 0 ; i < part_numface ; i++ ){if ( nbl_face[i] < 2 ) continue ;// face i should have at least 2 bendlinesfor ( j = i+1 ; j < part_numface ; j++ ) {if ( !imatrix[i][j] || nbl_face[j] < 2 ) continue ;// faces i and j must have a common bendline//and face j should have at least 2 bendlinesfor ( int i2 = 0 ; i2 < part_numface ; i2++ ) {if ( !imatrix[i][i2] || i2 == j ) continue ;// faces iand i2 must have a common bendline// and face i2 is different from j//first requirement - bendlines imatrix[i][j] and// imatrix[i][i2] form atouch cornerif ( get_FENT(sp, j+1, i2+1, parrank) != TouchCnr ) continue;for ( int j2 = 0 ; j2 < part_numface ; j2++ ) {if ( !imatrix[j][j2] ||j2 == i ) continue ;// second requirement - bendlines imatrix[i][j] and// imatrix[j][j2] also form a touch cornerif ( get_FENT(sp, i+1, j2+1, parrank) != TouchCnr ) continue ;// comes here, we have obtained a candidate for the  // thickness offset bendlines, the two candidate  // bendlines are imatrix[i,i2] and imatrix[j][j2]  int bl_1 = imatrix[i][i2] ;intbl_2 = imatrix[j][j2] ;check_thkoffbend ( sp, parrank,facelist, i+1, i2+1, j+1,j2+1,bendlinelist, bl_1, bl_2, thickness, outfile);}}}}//DfClnrBend =    ’D’;  //colinear bendline same bend angle on different faces// Here is to find all the colinear bends that are colinear but not related to each other// with a common face.int num_undetermined = 0 ;UNDETERMINED *undetermined = new UNDETERMINED [num_of_bendlines] ;UNDETERMINED *undetpt = undetermined ;for ( i = 0 ; i < num_of_bendlines ; i++ ) {if (bendlinelist[i].bendlineid) {int face_i1 = bendlinelist[i].face1 ;int face_i2 = bendlinelist[i].face2 ;for ( j = i+1 ; j < num_of_bendlines ; j++ ) {if (bendlinelist[j].bendlineid) {int face_j1 = bendlinelist[j].face1 ;int face_j2 = bendlinelist[j].face2 ;if ( face_i1 == face_j1 || face_i1 == face_j2 ||face_i2 == face_j1 || face_i2 == face_j2 ) continue ;if( bendlinelist[j].bendtype  != bendlinelist[j].bendtype  ) continue ;if( bendlinelist[j].bendangle != bendlinelist[j].bendangle ) continue ;//come here when the two bend lines have the same bend angle and type,// and they do not share a common face.// now examine whether they are colinearint bl_i = i + 1 ;int bl_j = j + 1 ;int unknown = check_DfClnrBend (sp, parrank, facelist,face_i1, face_i2, face_j1, face_j2,bendlinelist, bl_i, bl_j,part_numface, imatrix, outfile) ;if (unknown) {undetermined[num_undetermined].bendline_i = bl_i ;undetermined[num_undetermined].bendline_j = bl_j ;num_undetermined++ ;}}}}}// Note: if num_undetermined is not zero, then there are confirmed DfClnrBend//but with undetermined facesfor specify this FENT.//A tree structure of all the faces that recordsthe connectivity between//faces need to be constructed.  And then each pair of undetermined//bendlines need to be processed to determine which two faces of the four//that connected with the two bendlines should be used torecord this FENT.// Currently, we will neglect these information and simply delete// undetermined array, which will not be used any more. delete [] undetermined ;// transfer all the data back *inp_part_numface =part_numface ;*inp_parrank = parrank ;*inp_part_numbend = part_numbend;*inp_part_maxface = part_maxface ;*inp_sp = sp ;num_error = fclose (outfile) ;clean_up ( part_numface, imatrix, nbl_face,   facelist, bendlinelist, bendfacelist) ;return ( num_error ) ; }
付録Ｂ
相似性指数特性の例。２つの部分のトポロジカルマトリクスを比較し、それらの最良の相似性指数を求める。相似性指数は、２つの部分のＦＥＮＴマトリクストポロジカルマトリクス）の不一致ＦＥＮＴｓの全てのペナルテイの和として与えられる。最良の相似性指数は最小値を持つものである。
【０２９３】
int matrix_similarity_index    ( FENT *newmatrix,int newmatrixdim,int *newmatchlist,      FENT *oldmatrix,int oldmatrixdim,int *oldmatchlist,  int nfacefixed,int requiredvalue,int *minimumvalue){   //input    //newmatrix- new part topological matrix to be matched on//  by the oldmatrix//newmatrixdim- matrix dimension of newmatrix//newmatchlist- the first nfacefixed entries should//  contain the entries (faces) of the new part//  matrix that has already been fixed for//  matching with the old part matrix.    //oldmatrix- old part matrix to match with the new part //   topological matrix//oldmatrixdim- matrix dimension of oldmatrix//oldmatchlist- the first nfacefixed entries should//  contain the entries (faces)of the old part//  matrix that has already been fixed for//  matching with the new part matrix.//nfacefixed- the number of entries in matchlistthat//  has already been matched.  Enter 0 when//  there is no prematched entries.//requiredvalue- the known or interested upper bound on the//  minimum similarity index.  When this value//  is inputed as a positivevalue, then a//  branch of the search tree in finding the//  minimum value of the similarity index may//  be cut off when the branch’s currentvalue//  becomes greater than this minimum value.//  set to 0 or a negative value when there is//  no restriction.  In this case, a minimumvalue//  and its corresponding macthlists will always//  be found and returned.      //output//newmatchlist- the first nfacefixed entries should//contain the entries (faces) of the new part//  matrix that has already been fixed for//  matching with the old part matrix.//oldmatchlist- the first nfacefixed entries should//  contain the entries (faces) of the oldpart//  matrix that has already been fixed for//  matching with the newpart matrix.//minimumvalue- the minimum similarity index, which is the//  smallest possible value of summation of all//  the penalties of the mismatched FENTs of the//  two part’s FENT matrix (topological matrix).//  This value may not exist, if the original//  inputed value (which isthe requirement) is//  too small.//return- index on whether or not foundthe minimum//  value.//= 1, found the minium value and its match. //= 0, a new minium value cannot be reached.//= -1, error in the input data newmatchlist.//= -2, error in the input data oldmatchlist.//= -3, error,the minimum similarity index of//  the given matrices are larger than the//  inputed minimumvalue.// create two integer pointer arrays to keep track the // corresponding entries of the two matrices that matches.int matrixdim = newmatrixdim ;if (matrixdim < oldmatrixdim) matrixdim = oldmatrixdim ;int *pnewmatchlist = new int[ matrixdim ];int *poldmatchlist =new int[ matrixdim ];if ( poldmatchlist && pnewmatchlist ) {int *p1 = pnewmatchlist;int *p2 = poldmatchlist;for ( int icol = 1; icol <= matrixdim; icol++,p1++,p2++)*p1 = *p2 = icol;}elsecout << "Unable to allocate memory..." << endl ;// if there are already fixed entries (nfacefixed > 0),then reset// the temporary working pointer arrays (newmatchlist & oldmatchlist)// to contain those fixed face list.if (nfacefixed > 0){for (inticol = 0; icol < nfacefixed; icol++) {int iface = *(newmatchlist+icol);for ( int jcol = icol; jcol < matrixdim; jcol++) {if (iface == *(pnewmatchlist+jcol)) {if (jcol != icol) {*(pnewmatchlist+jcol) = *(pnewmatchlist+icol) ;*(pnewmatchlist+icol) = iface ;}break ;}// comes here only ifthe inputed face number "iface"// from newmatchlist is wrongreturn (-1); }iface = *(oldmatchlist+icol) ;for ( jcol = icol; jcol < matrixdim; jcol++) {if (iface == *(poldmatchlist+jcol)) {if (jcol != icol) {*(poldmatchlist+jcol) = *(poldmatchlist+icol) ;*(poldmatchlist+icol) = iface ;}break ;}// comes here only if the inputed face number "iface"// from oldmatchlist is wrongreturn (-2) ; }}}// convert the FENT matrix to the counter part of integer matrix// at the same time, expand the smaller matrixto have the same dimension.int *pnewmatrix = new int[matrixdim*matrixdim];int *poldmatrix = new int[matrixdim*matrixdim];convert_fent_to_int (newmatrix, newmatrixdim, pnewmatrix, matrixdim) ;convert_fent_to_int (oldmatrix, oldmatrixdim, poldmatrix, matrixdim) ;// define required valueintrequiredv = requiredvalue ;if (requiredv <= 0) requiredv = matrixdim *400 ;// create the FENT counters and use calculate_partial_similarity_index// to calculate the initial similarity index and set the initial FENT// counts for each column of the fixed faces and that of all the// unfixed faces.FENTCOUNT *pcnew = new FENTCOUNT[matrixdim+1];FENTCOUNT *pcold= new FENTCOUNT[matrixdim+1];int currentvalue = calculate_partial_similarity_index    ( pnewmatrix, pnewmatchlist, pcnew,      poldmatrix, poldmatchlist, pcold,  matrixdim,  nfacefixed ) ;if (currentvalue > requiredv) return (-3) ;// reset the unfixed faces in pnewmatchlist to be in thesequence of// its total weighting.int  ncandidates = matrixdim - nfacefixed ;int *pcandidates = new int [ncandidates] ;int *pweights = new int [ncandidates] ;for ( int i = 0 ; i < ncandidates ; i++ ) {int facenew = *(pnewmatchlist+nfacefixed+i) ;*(pcandidates+i) = facenew ;int weight = 0;int *pnewi = pnewmatrix + (facenew-1)*matrixdim ;for ( int j = 0 ; j <matrixdim ; j++, pnewi++ )weight += fent_weight(*pnewi) ;*(pweights+i)= weight ;}sort_the_candidates (pcandidates, pweights, ncandidates) ;for( i = 0 ; i < ncandidates ; i++ ) *(pnewmatchlist+nfacefixed+i) = *(pcandidates+ncandidates-1-i) ;delete [] pcandidates ;delete [] pweights ;//call the internal routine recursively to perform similarity index// search.*minimumvalue = requiredv ;int recursive_level = 0;int *newminmatchlist = new int[matrixdim];int *oldminmatchlist = new int[matrixdim];int *returnlevelcounts = new int[matrixdim];int errorcode = matrix_similarity_index_loop    ( pnewmatrix, pnewmatchlist, newminmatchlist,      poldmatrix, poldmatchlist, oldminmatchlist,  pcnew, pcold, &currentvalue, matrixdim, nfacefixed,  &recursive_level, minimumvalue,  returnlevelcounts);// clean updelete [] pnewmatchlist ;delete [] poldmatchlist ;delete []pnewmatrix ;delete [] poldmatrix ;delete [] pcnew ;delete [] pcold ;delete [] returnlevelcounts ;delete [] newminmatchlist ;delete [] oldminmatchlist ;return (errorcode);}//  新しい部分マトリクスと一致する既存の部分マトリクスからエントリのリストを抽出する。部分マトリクスのデイメンシヨンはトポロジカルマトリクスのデイメンシヨンより大きいか等しくなければならない。注意：一致リストの第一要素は初期化されてトポロジカルマトリクスの第一面との一致のため部分マトリクスの面番号を含まなければならない。 ｎｍａｔｃｈｅｄが０より大きいときは、マッチリストの第一のｎｍａｔｃｈｅｄエントリは正の番号を含んで部分マトリクスの既に一致されたエントリを示さなければならない。//int matrix_similarity_index_loop    ( int *pnewmatrix,    int *pnewmatchlist, int *newminmatchlist,      int *poldmatrix,    int *poldmatchlist, int *oldminmatchlist,  FENTCOUNT *pcnew,   FENTCOUNT *pcold,   int *currentvalue,  int matrixdim,      int nfacefixed,     int *recursive_level,  int *minimumvalue,  int *returnlevelcounts){// input//pnewmatrix- the new part’s topological matrix, where//    the FENT contents have been changed to//                        their representing integers.//                        (integer array of matrixdim * matrixdim)//pnewmatchlist- the list of entries of the newmatrixthat //  has been matched by the oldmatrix.//                        (integer array of matrixdim)//newminmatchlist- the list of entries of the newmatrix that //  has been matched by the oldmatrix that//  provides theminimum value.//                        (integer array of matrixdim)  //poldmatrix- the old parts’s topological matrix, where//            the FENT contents have been changed to//    their representing integers.//                        (int array ofmatrixdim * matrixdim)//poldmatchlist- the list of entries of the oldmatrix that //  has matched with the newmatrix.//                        (integer array of matrixdim)//oldminmatchlist- the list of entries of theoldmatrix that //  has matched with the oldmatrix that//  provides the minimum value.//                        (integer array of matrixdim)//matrixdim- the matrix dimension of both matrices//nfacematched- the numberof entries (faces) that has//  been fixed in matching the two matrices.// recursive_level- this keep the number of times this procedure//  has been called recursivly.  This provides a//  way to detect the error before going into a//  infinite loop. (integer pointer)// output//return- error index,//= 0 means there is no error,//> 0 error code.//// verify therecursive levelif ( *recursive_level > matrixdim ) {cout << "??? Error -the recursive level is too high. ???\n";cout << "    The matrix dimension is " << matrixdim << ".\n";cout << "    The recursive level is  " <<*recursive_level << ".\n";return (9) ;}// Step 1) Choose a row to be matched with in the new matrix.// ( Currently, it uses whatever the next row in line.  Therefore,//   nothing to do at this moment.//   This may need to be changed to be properly matching up with//   the algorithm thatmay be used in defining the sequence of the//   candidate list.//   Note: If facenew is not next to the nfacefixed position, then//         it should be changed to that position. )int  facenew = *(pnewmatchlist+nfacefixed) ;// Step 2) Create a list of candidate face list in the old matrix.//         and calculate the increases in the similarity index for//       each of the candidates.// ( Currently we are using what ever thesequence that is inside//   the poldmatchlist.//   One may choose to usethe faces that at least matches up with//   the face connectivity of the chosen face in the new matrix.//   Note: The sequence of faces in pcandidates does not need to//         be corresponding to that in poldmatchlist. )int  ncandidates = matrixdim - nfacefixed ;int *pcandidates = newint [ncandidates] ;int *pincreases = new int [ncandidates] ;for ( int i= 0 ; i < ncandidates ; i++ ) {int faceold = *(poldmatchlist+nfacefixed+i) ;*(pcandｉｄａｔｅｓ＋i) = faceold ;int increase = increase_on_similarity_index    ( pnewmatrix,pnewmatchlist,facenew,        poldmatrix,poldmatchlist,faceold,    pcnew,pcold,currentvalue,    matrixdim,nfacefixed,minimumvalue) ;*(pincreases+i) = increase ;}// Step 3) Sort the candidate facebased on the increased values//         the candidates with the lower increase will be tried first.sort_the_candidates (pcandidates, pincreases, ncandidates) ;// Step 4) change the FENT counters of the newmatrix forfixing facenewint errorcode = change_counts_for_fix_one_face    ( pnewmatrix, pnewmatchlist, facenew, pcnew, matrixdim, nfacefixed) ;if (errorcode != 0) return (errorcode) ;// Step 5) Loop thru the candidate face and based on the increased value//         determines whether or not to continue to the lower level match.for ( int icandi = 0 ; icandi < ncandidates ; icandi++ ) {// get the candidate face number of the old matrix and// its corresponding amount of increase on similarity index.int faceold= *(pcandidates+icandi) ;int increase = *(pincreases+icandi) ; // Now check whether it is any need to continue the matching// If the current value plus the increase has already exceed the // minimum value, then thereis no need to continue the matching.// add the returnlevelcount and goto the next candidates.if (*currentvalue + increase >= *minimumvalue) {returnlevelcounts[nfacefixed] += 1 ;}else if (nfacefixed+1 == matrixdim){// A new minimum similarity index has been found, update// the minimumvalue*minimumvalue = *currentvalue + increase ;for ( i = 0 ; i < matrixdim ; i++ ) {newminmatchlist[i] = pnewmatchlist[i] ;oldminmatchlist[i] =poldmatchlist[i] ;}}else {// It is necessary to go down another level inthis recursive// call to define the similarity index.// change the FENTcounters of the oldmatrix for fixing faceolderrorcode = change_counts_for_fix_one_face ( poldmatrix,    poldmatchlist, faceold, pcold, matrixdim, nfacefixed) ;if (errorcode != 0) return (errorcode) ;// call recursively*currentvalue += increase ;*recursive_level += 1 ;errorcode = matrix_similarity_index_loop      ( pnewmatrix,pnewmatchlist,newminmatchlist,    poldmatrix,poldmatchlist,oldminmatchlist,  pcnew,   pcold,currentvalue,  matrixdim,nfacefixed+1,recursive_level,  minimumvalue,returnlevelcounts) ;if (errorcode != 0) return (errorcode) ;*recursive_level -= 1 ;*currentvalue -= increase ;// change the FENT counters of the oldmatrix for unfixing faceoldchange_counts_for_unfix_one_face ( poldmatrix,    poldmatchlist, pcold, matrixdim, nfacefixed+1) ;}}// change the FENT counters of the newmatrix for unfixing facenewchange_counts_for_unfix_one_face( pnewmatrix,    pnewmatchlist, pcnew, matrixdim, nfacefixed+1) ;//cleanupdelete [] pcandidates ;delete [] pincreases ;return (0);}////////////////////////////////////////////////////////////////// １以上の面を固定するためのカウンターを更新する。////////////////////////////////////////////////////////////////////int change_counts_for_fix_one_face    ( int*pnewmatrix,    int *pnewmatchlist, int facenew,  FENTCOUNT *pcnew,   int matrixdim,      int nfacefixed){// input//pnewmatrix- the new part’stopological matrix, where//                        the FENT contents have been changed to//                        their representing integers.//                        (integer array of matrixdim * matrixdim)//pnewmatchlist- the list of entries of the newmatrix that //  has been matchedby the oldmatrix.//                        (integer array of matrixdim)//facenew- the face that is to be fixed.//pcnew- the FENTCOUNT of all the faces.//matrixdim- the matrix dimension of both matrices//nfacematched- the number of entries (faces) that has//  been fixed in matching the two matrices.// output//pnewmatchlist- the updated list of entries of the//  newmatrix matched by the oldmatrix,//  with the facenew entry is moved to the //  nfacefixed+1 location. //pcnew- the updated FENTCOUNT of all the faces// switch the to be fixed face to the location of nfacefixed+1// in the pnewmatchlistint ifound = 0 ;for ( int i = nfacefixed ; i <matrixdim ; i++ ) {if (*(pnewmatchlist+i) == facenew) {*(pnewmatchlist+i) = *(pnewmatchlist+nfacefixed) ;*(pnewmatchlist+nfacefixed) = facenew ;ifound++ ;}}if ( ifound != 1 ) {cout << "Fatal error from change_counts_for_fix_one_face /n" ;return ( 91 ) ;}// define the pointer to the FENTon the to be fixed faceint *pnewrow = pnewmatrix + (facenew-1)*matrixdim;// first change the counters for the previously fixed facesfor ( i = 0; i < nfacefixed ; i++ ) {int newcol = *(pnewmatchlist+i) ;int pnewv  =*(pnewrow + newcol - 1) ;pcnew[newcol].count[pnewv]-- ;int igroup = fent_group (pnewv) ;pcnew[newcol].gcount[igroup]-- ;if ( pcnew[newcol].count[pnewv] < 0 ||     pcnew[newcol].gcount[igroup] < 0 ) {cout << "Fatal error from change_counts_for_fix_one_face /n" ;return ( 92 ) ;}}// secondchange the counters for the unfixed faces// use count_specified_fents to initialize the FENTCOUNT of// the newly seleted face and count the numbers of fents of // the undetermined columns on the to be fixed rowsintlistdim = matrixdim - nfacefixed ;pcnew[facenew] = count_specified_fents( pnewrow, pnewmatchlist+nfacefixed, matrixdim, listdim ) ; // decreasethe FENTCOUNT of the newly seleted face from that// in remaining unfixed facesfor ( i = 0; i < NumIntFent; i++ ) pcnew[0].count[i] -= pcnew[facenew].count[i] ;for ( i = 0; i < NumIntFentGroup; i++ ) pcnew[0].gcount[i] -= pcnew[facenew].gcount[i] ;return (0) ;}//////////////////////////////////////////////////////////////////////  この関数はカウンタを更新して固定面を開放する。解放された面は現在ｎｆａｃｅ////ｆｉｘｅｄ位置にある面である。//////////////////////////////////////////////////////////////////////void change_counts_for_unfix_one_face    ( int *pnewmatrix,    int *pnewmatchlist,  FENTCOUNT *pcnew,   int matrixdim,      int nfacefixed){// input//pnewmatrix- the new part’s topological matrix, where//                      the FENT contents have been changed to//              their representing integers.//                        (integer array of matrixdim * matrixdim)//pnewmatchlist- the list of entriesof the newmatrix that //  has been matched by the oldmatrix.//                (integer array of matrixdim)//pcnew- the FENTCOUNT of all the faces.//matrixdim- the matrix dimension of both matrices//nfacematched- the number of entries (faces) that has//  been fixed in matching the two matrices.// output//pcnew- the updated FENTCOUNT of all the faces// get the to be unfixed face number and// define the pointer to the FENT on the to be fixed faceint facenew = *(pnewmatchlist+nfacefixed-1) ;int *pnewrow = pnewmatrix + (facenew-1)*matrixdim ;// first change the counters for the previously fixed facesfor ( int i = 0 ; i < nfacefixed-1 ;i++ ) {int newcol = *(pnewmatchlist+i) ;int pnewv  = *(pnewrow + newcol- 1) ;pcnew[newcol].count[pnewv]++ ;int igroup = fent_group (pnewv) ;pcnew[newcol].gcount[igroup]++ ;}// second change the counters for the unfixed faces by// adding the FENTCOUNT of the to be released face to that// of the remaining unfixed facesfor ( i = 0; i < NumIntFent; i++ ) pcnew[0].count[i] += pcnew[facenew].count[i] ;for ( i = 0; i < NumIntFentGroup; i++ ) pcnew[0].gcount[i] += pcnew[facenew].gcount[i] ;}/////////////////////////////////////////////////////////////////////////  この関数は所与のｉｎｔｆｅｎｔの配列におけるＦＥＮＴｓの個数をカウントす////  る。/////////////////////////////////////////////////////////////////////////FENTCOUNT count_fents ( int *pintfentarray, int arraydim){// input//pintfentarray- the pointer to the intfent array//arraydim- the dimension ofthe intfent array// output//return- FENTCOUNT, the FENT count of the//  input array// define an FENT count and initialize itstatic FENTCOUNT fentc ;for ( int j = 0; j < NumIntFent; j++ ) fentc.count[j] = 0 ;for ( j= 0; j < NumIntFentGroup; j++ ) fentc.gcount[j] = 0 ;// Count the numbers of fents in an array of intfentfor ( int *i = pintfentarray ; i < pintfentarray+arraydim ; i++ ) {fentc.count[*i]++ ;fentc.gcount[fent_group(*i)]++ ;}return (fentc) ;}//////////////////////////////////////////////////////////////////////  この関数は特定の組のｉｎｔｆｅｎｔ配列におけるＦＥＮＴｓの個数をカウント////  する。//////////////////////////////////////////////////////////////////////FENTCOUNT count_specified_fents ( int *pintfentarray,int *locationlist, int arraydim, int listdim){// input//pintfentarray- the pointer to the intfent array//locationlist- the locations in the intfent array//  that are to be included in counting//arraydim- the dimension of the intfent array//listdim- the dimension of the location list// output//return- FENTCOUNT, the FENT count of the//  selected elements in the input array// define an FENT count and initialize itstatic FENTCOUNT fentc ;for ( int j = 0; j < NumIntFent; j++ ) fentc.count[j] = 0 ;for ( j = 0; j < NumIntFentGroup; j++ ) fentc.gcount[j] = 0 ;// Count the numbers of fents in an array of intfentfor ( int *i = locationlist ; i < locationlist+listdim ; i++ ) {int intfent = *(pintfentarray+(*i)-1) ;fentc.count[intfent]++ ;fentc.gcount[fent_group(intfent)]++ ;}return (fentc) ;}/////////////////////////////////////////////////////////////////////////////  この関数は特定の組のintfentマトリクスにおけるＦＥＮＴｓの個数をカウントする。////注意：ｉｎｔｆｅｎｔマトリクスは対称である。マトリクスの半分だけがカウントに含ま////      れる。/////////////////////////////////////////////////////////////////////////////FENTCOUNTcount_specified_fents_matrix ( int *pintfentmatrix,int *locationlist, int matrixdim, int listdim){// input//pintfentmatrix- the pointer to theintfent matrix//locationlist- the locations in the intfent matrix//  that are to be included in counting//matrixdim- the dimension of the intfent matrix//listdim- the dimension of the location list// output//return-FENTCOUNT, the FENT count of the//  selected elements in the input matrix// define an FENT count and initialize itstatic FENTCOUNT fentc ;for (int j = 0; j < NumIntFent; j++ ) fentc.count[j] = 0 ;for ( j = 0; j < NumIntFentGroup; j++ ) fentc.gcount[j] = 0 ;// Count the numbers of fentsin an matrix of intfentfor ( int i = 0 ; i < listdim ; i++ ) {int facenum = *(locationlist+i) ;int *pintfentrow = pintｆｅｎｔｍａｔｒｉｘ  + (facenum - 1)*matrixdim ;// Note: only half of the symmetric matrix is counted =>//     the k is atarted from i (diagonal included).for ( int k = i ; k < listdim ; k++ ) { int intfent = *(pintfentrow+(*(locationlist+k))-1) ;fentc.count[intfent]++ ;fentc.gcount[fent_group(intfent)]++ ;}}return (fentc) ;}/////////////////////////////////////////////////////////////////////  この関数は不一致な対のFENTに対してペナルテイを戻す。/////////////////////////////////////////////////////////////////////int penalty_of_fent_pair ( int intfent1, int intfent2){// input//intfent1- the intfent of part 1//intfent2- the intfent of part 2// output//return- the penalty forthe mismatched intfents.// No penalty, if they are the sameif (intfent1== intfent2) return (0) ;// add the penalty for mismatching the individual intfentint indexvalue = 0;indexvalue += fent_weight(intfent1) ;indexvalue += fent_weight(intfent2) ;// add the penalty for mismatching theirfent groupint fentgroup1 = fent_group(intfent1) ;int fentgroup2 = fent_group(intfent2) ;if (fentgroup1 != fentgroup2) {indexvalue += fent_group_weight(fentgroup1) ;indexvalue += fent_group_weight(fentgroup2) ;}return (indexvalue) ;}////////////////////////////////////////////////////////////////////  この関数は２つの最小可能不一致に対して最小ペナルテイを戻す。////////////////////////////////////////////////////////////////////int penalty_of_FENTCOUNT_pair ( FENTCOUNT const &fentcount1,FENTCOUNT const &fentcount2){// input//fentcount1- the FENTCOUNT of part 1//fentcount2- the FENTCOUNT of part 2// output//return- the minimum penalty on themismatches//                    of two FENTCOUNTs.// Now loop thru theFENTCOUNT, // currently method uses the penalty of the minimum possible  // individual mismatches as the penalty plus the penalty of// the minimum possible mismatched groupsint indexvalue = 0;for ( int i = 1; i < NumIntFent; i++ )if ( fentcount1.count[i] != fentcount2.count[i] )indexvalue += fent_weight(i) * abs ( fentcount1.count[i] - fentcount2.count[i] );for ( i = 1; i < NumIntFentGroup; i++ )if ( fentcount1.gcount[i] != fentcount2.gcount[i] )indexvalue += fent_group_weight(i) * abs ( fentcount1.gcount[i] - fentcount2.gcount[i] ) ;return (indexvalue) ;}////////////////////////////////////////////////////////////////////  この関数は不一致対のＦＥＮＴのペナルテイを戻す。//////////////////////////////////////////////////////////////////int change_from_seperate_fent_sets ( int ntnew, int ntold, int nsnew, int nsold ){// input//ntnew- number of FENT inthe whole set of the new part.//ntold- number of FENT in the whole setof the old part.//nsnew- number of FENT in the sub-set of the new part.//nsold- number of FENT in the sub-set of the old part.// output//return-the change in the number of counts of the mismatch//  due to the separation of the sub-set from the //  whole set.int difforg = abs( ntnew-ntold ) ;int diffsub = abs( nsnew-nsold ) ;int diffnew = abs( ntnew-nsnew-ntold+nsold ) ;int change = diffsub + diffnew - difforg ;return ( change );}///////////////////////////////////////////////////////////////////////////////  この関数は２つのＦＥＮＴＣＯＵＮＴの最小可能不一致に対する最小ペナルテイを戻す。///////////////////////////////////////////////////////////////////////////////int increase_from_separate_a_pair_of_fent (FENTCOUNT const &pcnew_total,FENTCOUNT const &pcold_total,int intfentnew_separ,int intfentold_separ ){// input//pcnew_total- the total FENTCOUNT of the new part//pcold_total- the total FENTCOUNT of the old part//intfentnew_separ - to be seperated FENT of the new part//intfentold_separ - tobe seperated FENT of the old part// output//return- the increase in thepenalty due to the//                    seperation of the FENTs.staticint ntnew, ntold, igroup ;static int increase ;if (intfentnew_separ == intfentold_separ) {ntnew = pcnew_total.count[intfentnew_separ] ;ntold = pcold_total.count[intfentnew_separ] ;increase = fent_weight(intfentnew_separ) *change_from_seperate_fent_sets(ntnew, ntold, 1, 1 ) ;igroup = fent_group(intfentnew_separ) ;ntnew = pcnew_total.gcount[igroup] ;ntold = pcold_total.gcount[igroup] ;increase += fent_group_weight(igroup) *change_from_seperate_fent_sets(ntnew, ntold, 1, 1 ) ;}else {ntnew = pcnew_total.count[intfentnew_separ] ;ntold = pcold_total.count[intfentnew_separ] ;increase = fent_weight(intfentnew_separ) *change_from_seperate_fent_sets(ntnew, ntold, 1, 0 ) ;ntnew = pcnew_total.count[intfentold_separ] ;ntold= pcold_total.count[intfentold_separ] ;increase += fent_weight(intfentold_separ) *change_from_seperate_fent_sets(ntnew, ntold, 0, 1 ) ;if (fent_group(intfentnew_separ) == fent_group(intfentold_separ)) {igroup = fent_group(intfentnew_separ) ;ntnew = pcnew_total.gcount[igroup] ;ntold = pcold_total.gcount[igroup] ;increase += fent_group_weight(igroup) *change_from_seperate_fent_sets(ntnew, ntold, 1, 1 ) ;}else {igroup = fent_group(intfentnew_separ) ;ntnew = pcnew_total.gcount[igroup] ;ntold = pcold_total.gcount[igroup] ;increase += fent_group_weight(igroup) *change_from_seperate_fent_sets(ntnew, ntold, 1, 0 ) ;igroup = fent_group(intfentold_separ) ;ntnew = pcnew_total.gcount[igroup] ;ntold = pcold_total.gcount[igroup] ;increase += fent_group_weight(igroup) *change_from_seperate_fent_sets(ntnew, ntold, 0, 1 ) ;}}return (increase) ;}/////////////////////////////////////////////////////////////////////////////  この関数は２つのＦＥＮＴＣＯＵＮＴの最小可能不一致に対する最小ペネルテイを戻す。/////////////////////////////////////////////////////////////////////////////intincrease_from_separate_a_pair_of_fentcount (FENTCOUNT const &pcnew_total,FENTCOUNT const &pcold_total,FENTCOUNT const &pcnew_separ,FENTCOUNT const &pcold_separ ){// input//pcnew_total- the total FENTCOUNT of the newpart//pcold_total- the total FENTCOUNT of the old part//pcnew_separ- tobe seperated FENTCOUNT of the new part//pcold_separ- to be seperated FENTCOUNT of the old part// output//return- the increase in the penalty due to the//                    seperation of the FENTCOUNTs.// Now loop thru the FENTCOUNT, // currently method uses the penalty of the minimum possible  // individual mismatches as the penalty plus the penalty of// the minimum possible mismatched groupsint change, increase ;increase  = 0;for ( int i = 1; i < NumIntFent; i++ ) {change = change_from_seperate_fent_sets (pcnew_total.count[i], pcold_total.count[i],pcnew_separ.count[i], pcold_separ.count[i] ) ;if ( change != 0 ) increase += fent_weight(i)* change ;}for ( i = 1; i < NumIntFentGroup; i++ ) {change = change_from_seperate_fent_sets (pcnew_total.gcount[i], pcold_total.gcount[i],pcnew_separ.gcount[i], pcold_separ.gcount[i] ) ;if ( change != 0 ) increase += fent_group_weight(i) * change ;}return (increase) ;}//////////////////////////////////////////////////////////////////////////  この関数は特定の固定した面までの所与の組の面に対して相似の指数を計算する。////  注意：マトリクスの半分だけが計算に含まれる。//////////////////////////////////////////////////////////////////////////int direct_calculate_similarity_index    ( int *pnewmatrix,    int *pnewmatchlist,      int *poldmatrix,    int *poldmatchlist,int matrixdim){// loop thru the faces and calculate the similarity indexint indexvalue = 0 ;for (int iface = 0; iface < matrixdim; iface++) {int facenew = *(pnewmatchlist+iface) ;int faceold =*(poldmatchlist+iface) ;int *pnewrow = pnewmatrix + (facenew - 1)*matrixdim ;int *poldrow = poldmatrix + (faceold - 1)*matrixdim ;// first fromthe mismatches of the fixed faces.// Note: the diagonal terms of the matrix are always iNoRelation.//       therefore, they are skip in the loop.//       also due to the symmetry, only half of the matrix are//included in the calculation of the similarity indexfor (int icol = iface; icol < matrixdim; icol++) {int newcol = *(pnewmatchlist+icol) ;int oldcol = *(poldmatchlist+icol) ;int pnewv = *(pnewrow + newcol - 1) ;int poldv = *(poldrow + oldcol - 1) ;if ( pnewv != poldv ) indexvalue += penalty_of_fent_pair(pnewv,poldv) ;}}return (indexvalue) ;}////////////////////////////////////////////////////////////////////////  この関数は特定の固定した面までの所与の組の面に対する相似の指数を計算する。////////////////////////////////////////////////////////////////////////int calculate_partial_similarity_index    ( int *pnewmatrix,    int *pnewmatchlist,FENTCOUNT *pcnew,      int *poldmatrix,    int *poldmatchlist,   FENTCOUNT*pcold,  int matrixdim,      int nfacefixed){// loop thru the faces andcalculate the similarity indexint indexvalue = 0 ;for (int iface = 0 ; iface < nfacefixed; iface++) {int facenew = *(pnewmatchlist+iface) ;int faceold = *(poldmatchlist+iface) ;int *pnewrow = pnewmatrix + (facenew -1)*matrixdim ;int *poldrow = poldmatrix + (faceold - 1)*matrixdim ;// first from the mismatches of the fixed faces.// Note: the diagonal terms of the matrix are always iNoRelation.//       therefore, they are skip inthe loop.//       also due to the symmetry, only half of the matrix are//       included in the calculation of the similarity indexfor (int icol = iface ; icol < nfacefixed; icol++) {int newcol = *(pnewmatchlist+icol) ;int oldcol = *(poldmatchlist+icol) ;int pnewv = *(pnewrow + newcol -1) ;int poldv = *(poldrow + oldcol - 1) ;if ( pnewv != poldv ) indexvalue += penalty_of_fent_pair(pnewv,poldv) ;}// use count_specified_fents to initialize the FENTCOUNT of// the facenew and faceold and to count thenumbers of fents of // the columns of the unfixed facesint listdim = matrixdim - nfacefixed ;pcnew[facenew] = count_specified_fents ( pnewrow,pnewmatchlist+nfacefixed, matrixdim, listdim ) ;pcold[faceold] = count_specified_fents ( poldrow, poldmatchlist+nfacefixed, matrixdim, listdim );// Now loop thru the FENTCOUNT of the facenew and faceold// and calculate the penalty of their mismatches.indexvalue += penalty_of_FENTCOUNT_pair ( pcnew[facenew],  pcold[faceold] ) ;}// use count_specified_fents_matrix to get the FENTCOUNT// of the unfixed faces of both matrices int listdim = matrixdim - nfacefixed ;pcnew[0] = count_specified_fents_matrix( pnewmatrix, pnewmatchlist+nfacefixed, matrixdim, listdim ) ;pcold[0]= count_specified_fents_matrix ( poldmatrix, poldmatchlist+nfacefixed, matrixdim, listdim ) ;// Finally calculate the penalty of the FENTCOUNT//of the unfixed faces of the two matrices.indexvalue += penalty_of_FENTCOUNT_pair (  pcnew[0],  pcold[0] ) ;// Return the amount of penalty on the two partially fixed// part matrices as its minimum possible similarityindex.return (indexvalue);}/////////////////////////////////////////////////////////////////////////  この関数は所与のｆａｃｅｎｅｗとｆａｃｅｏｌｄのミスマッチに対する相似の指////   数の増加を計算する。/////////////////////////////////////////////////////////////////////////int increase_on_similarity_index    ( int *pnewmatrix,    int *pnewmatchlist, intfacenew,      int *poldmatrix,    int *poldmatchlist, int faceold,  FENTCOUNT *pcnew,   FENTCOUNT *pcold,   int *currentvalue,  int matrixdim,    int nfacefixed,     int *minimumvalue){// loop thru the faces to seehow much increase is in the// current value.int increase = 0 ;int *pnewrow = pnewmatrix + (facenew-1)*matrixdim ;int *poldrow = poldmatrix + (faceold-1)*matrixdim ;// first loop thru the previously fixed faces and calculate// the increase for the mismatches between the chosen columnsfor( int i = 0; i < nfacefixed; i++ ) {int newcol = *(pnewmatchlist+i) ;int oldcol = *(poldmatchlist+i) ;int pnewv = *(pnewrow + newcol - 1) ;intpoldv = *(poldrow + oldcol - 1) ;if ( pnewv != poldv ) {FENTCOUNT pcnewcol = pcnew[newcol] ;FENTCOUNT pcoldcol = pcold[oldcol] ;increase += increase_from_separate_a_pair_of_fent (pcnewcol, pcoldcol, pnewv, poldv ) ;}}// use count_specified_fents to initialize the FENTCOUNT of// the newlyseleted face and count the numbers of fents of // the undetermined columns on the to be fixed rowsint listdim = matrixdim - nfacefixed ;pcnew[facenew] = count_specified_fents ( pnewrow, pnewmatchlist+nfacefixed, matrixdim, listdim ) ;pcold[faceold] = count_specified_fents ( poldrow, poldmatchlist+nfacefixed, matrixdim, listdim ) ;increase += increase_from_separate_a_pair_of_fentcount (pcnew[0], pcold[0], pcnew[facenew], pcold[faceold] ) ;// Return the amount of increase in the similarity index for// the matching of the chosen two faces, facenew in new part// and the faceold in the old part.return (increase);}
付録Ｃ
//  コメントを含むベンドライン検出の例。このモジュールはＢM PART:: 自動ベンド（ ）の実施を含む。
【０２９４】
//* ********** ********** ********** *********** *********  これは、部分の設計と構成に供する主要な高レベルベンドモデル関数である。その目的は、（もし可能なら）部分が接続されるようになるように面間にベンドラインを形成することにある。  この関数は部分の形成を容易にすることにある。通常は、第三パーテイのＣＡＤプログラムの部分を描画する。ベンドモデルはＣＡＤシステムにわたる制御をもたず、我々の目的に対してこの描画は丁度一組のエッジである。従って、この図は部分の構造を検出するために解析されなければならない。その後、我々は部分の面とベンドラインを形成することが出来る。しかし、入力された図はしばしば曖昧であり、ベンドラインは一意には定義されない。その場合、我々は一連の発見的手法を用いてベンドラインを形成する。この発見的手法は、多くのものが可能のとき一つの出力を取り出すための優先基準を規定する。
この問題は多くの応用に対して共通なので、この関数はベンドモデルの一部である。更に、ベンドモデルにおいてこの関数を実施すると、ＣＡＤシステムの一部でなければならない面検出ソフトウエアを簡単にする。この関数において、我々は、垂直な平面に一致するように左手側の規則に従って（これは平面の向きを規定する。）面のエッジが分類されると仮定する。基本的には、この関数は、全ての平面が、分離して見たとき、それ自身正しいと仮定する。しかし、この関数は、隣接する平面の向きがそれらの平面の間のベンドラインに関して正しいことを要求しない（後にそれを固定するベンドモデル関数が存在する。）。  この関数を用いて部分の３Ｄバージヨンおよび部分のフラットバージヨンの両者に対してベンドラインを生成することが出来る。しかし、部分はフラットまたは３Ｄバージヨンのいずれかを持つことが出来るが、両者を持つことは出来ない。換言すれば、３Ｄ体の全ての３Ｄバージヨンはゼロでなければならないか（その場合、我々はフラットバージヨンを持つ。）全てのフラットバージヨンがゼロでなければならないかのいずれかである。*//************ ********** ********** ********** ********** **********アルゴリズム／プロセス：  アルゴリズムの目的は、部分のトポロジーグラフにおいてループを形成しないという拘束が与えられたとき、全体の部分が接続されるようになるように（すなわち、全ての面が全てベンドラインを介して接続され、周囲にスタンドアロン面が垂れ下がることを望まない）最小数のベンドラインを形成することにある（何故なら、我々は部分を出来るだけ変化させたくない）。  入力部分がいかなるベンドラインも含まないということは要求されない。ＡｕｔｏＢｅｎｄは既存のベンドラインを考慮し、部分に新しいベンドラインを付加したものである。トップレベルでは、このアルゴリズムは最大スパンツリーアルゴリズムの一バージヨンを行う。任意の時間点で、アルゴリズムは現在接続された要素と一組のフリンジ面（これらは接続された要素の部分である。）を有している。これらのフリンジ面は接続要素の外側の面との接点を有する。一回の過程の間に、接続要素の外側にある一つの新しい面が接続要素に付加される。フリンジ面に当接する接続要素の外側の面の間で、Ａｕｔｏｂｅｎｄは最大のコンタクトを持つものを取り出す。  この最大のコンタクトを用いる発見的手法は、薄板製造において、通常、接触が大きければ大きい程より良好な結果が得られるという事実に基づいている。しかし、タイが存在するとき、すなわち、接続要素におけるフリンジ面と同じ最大コンタクトを持つ接続要素の外側に幾つかの面があるときは、我々は他の発見的手法を用いる。この発見的手法は部分の直径を最小にする面を取り出す。部分の直径は、部分のトポロジーグラフにおける任意の２つの面間の最大距離である。*********** ********** ********** ********** ********** *技術的注意：-この関数は、部分の厚みがゼロでないときは恐らく十分には作用しない。-この関数は、アルゴリズムにおける面ｌ（主として、垂直な面ｌ）に一致するベンドライン情報を生成する点に注目されたい。しかし、垂直な面２はこの情報と一致することは出来ないが、それは後に固定されなければならない。ＰＡ���Ｔ．ＨＸＸ．のコメントを参照されたい。#include <stdio.h>#include <stdlib.h>#include "GLOBAL.HXX"#include "ENTITY.HXX"#include "PLANE.HXX"#include "CYLINDER.HXX"#include "LINE.HXX"#include "LOOP.HXX"#include "2D_BODY.HXX"#include "FORMING.HXX"#include "FACE.HXX"#include "BEND_OP_R.HXX"#include "BEND_PRP.HXX"#include "BENDLINE.HXX"#include "PART.HXX"#include "DBM.HXX"/*この関数は、所定の２つの面の間の全てのコンタクトを計算する。コンタクト接触は、２つの面が互いに接触しているときに得られ（すなわち、ある非常に小さな距離公差内で）、それらを分離する線分は０より大きな長さを有する（すなわち、共通の線分は点ではなく、実際の線分である）。目的：与えられた２つの面の間の潜在的なベンドラインのを計算すること。仮定：-両面は、計算のために用いられる最新の非空３Ｄバージヨンを有する。-いずれかの面における全てのループは閉じられる。
要件：-両面は同じ面内になければならない。リターン：-コンタクトのリストこのリターンされたリストは構造を有する：ノード０：ｏｂｊは”コンタクトの個数”である。ノード２ｉ-１：ｏｂｊは”コンタクトｉの面ｌ側のリストのヘッド”である。ノード２ｉ：ｏｂｊはコンタクトｉの面２側のリストのヘッド”であり、ただし、ｉは、〔１、”コンタクトの個数”〕内にある。各々のコンタクトは”閉じた”コンタクトであり、すなわちコンタクトにはギャップは存在しない点に注目されたい。コンタクトのいずれかの側の各々のリストは、リスト中のラインの順序がスイープ方向とは逆の（現在はＸＺＹスイープ）ラインのリストである（実際にはラインに対するポインタ）。これはコンタクトのリストがどの様に見えるかを示すものである：コンタクトの＃-＞リスト１．面１．ヘッド-＞リスト１．面２．ヘッド-＞．．．-＞リストｉ．面１．ヘッド-＞リストｉ面２．ヘッド．｜｜｜｜ＶＶＶＶ面１におけるライン１  面２におけるライン１  面１におけるライン１面２におけるライン１｜｜｜｜ＶＶＶＶ．．．．．．．．．．．．｜｜｜｜ＶＶＶＶ面１におけるラインｉ面２におけるラインｊ面１におけるラインｋ面２におけるライン１この関数においては、ｋベンドのコリネアベンドラインは、ｋ個の個別コンタクトと考えられる。注意：――――――――デフォールトにより、我々は両面における全てのラインをベンドラインに対する候補と考える。しかし、もしユーザが、ベンドラインが何かを既に知っている（あるいは実際には、ベンドラインエッジが何であるかを知っている）ときは、ユーザはこれらのラインの名前を用いて、この関数がそれらのラインのみを考えるように指示することが出来る。この関数は、面１または面２のいずれかが、他の面のｉｄｘに等しい名称を持つか否かをチェックする（面１および面２は個別にチェックされる。）。もし、イエスなら、これらのラインのみがその面の側のベンドラインに対する候補と考えられることになる。*/static int BM_compute_all_face_to_face_contacts(BM_FACE & face1 /* IN */, BM_FACE & face2 /* IN */,BM_LINKED_LIST_NODE **list_of_contacts /* OUT */){// initialize global variables.// this is the contacts list we will be computing. initially list is NIL.*list_of_contacts = NULL ;// this points to the beginning of the contacts list.// it does not contain the number of contacts.// ie. points to "list_of_contacts[1]".BM_LINKED_LIST_NODE *contacts = NULL ;double *line_start_coordinates = NULL ; // used when the set of lines is sortedBM_LINE **line_pointers = NULL ; // an array of lines (actually pointers to lines) used to store // lines being swept.// once lines are sortedaccording to the XZY order, we will scan this array from the end// to the beginning -> this implements the sweep.// at the same time, we maintain a list of open lines. this is done by leaving line// pointers in thisarray "behind" as they are when we move forward in the array.// to erase a line from the open list, we simple set the pointer in the array to NULL.// endpoints of lines in face1 and face2 that are larger with respect to XZY ordering.// used when processing contacts.BM_POINT p_face1, p_face2 ;// some variables used in many places.long i, j ;BM_POINT p ;/********* ********** **********資格チェック********** ********** *********************/// both faces must be in the same partif (face1.get_part() == NULL || face1.get_part() != face2.get_part()) return 0 ;double local_tolerance = (face1.get_part())->get_distance_tolerance() ;// first try 3D-versions of faces. if both of them are empty, try flat versions.BM_2D_BODY *body1 = face1.get_current_3D_version() ;BM_2D_BODY *body2 = face2.get_current_3D_version() ;if (NULL == body1 && NULL == body2) {body1 = face1.get_flat() ;body2 = face2.get_flat() ;}// if either of the 3D-bodiesis NULL we are successfully done.if (NULL == body1 || NULL == body2) return 1 ;// both faces must have a plane as the underlying surfaceBM_SURFACE *surface1 = body1->get_surface() ;BM_SURFACE *surface2 = body2->get_surface() ;if (NULL == surface2 || NULL == surface2) return 0 ;if (! surface2->is(BM_TYPE_PLANE) || ! surface2->is(BM_TYPE_PLANE)) return 0 ;//if any of the faces has an empty bloop, we are successfully doneBM_LOOP*bloop1 = body1->get_bloop() ;BM_LOOP *bloop2 = body2->get_bloop() ;if (NULL == bloop1 || NULL == bloop2) return 1 ;/*********** ********** ********** ********** ********** ********** ********** ********** **********ここで、我々は、これらの面がともかく接触出来るか否かの非常に迅速なチェックを行う。  ここで、我々は、面２のｂループが接触するか（１点以上で）、面１の平面に交差するか否かをチェックする。  これは、これらの２つの面が明らかに接触出来ない時間を節約することになる。********** ********** ********** ********** ********** ********** ********** ********** ***********/// these variables will be used to do a quick check if these two// facescan possible touch each otherdouble distance_plane_to_bloop1, distance_plane_to_bloop2,distance_plane_to_bloop3, distance_plane_to_bloop4 ;intdistance_plane_to_bloop_count ;if (! bloop2->is_bbox_up_to_date()) bloop2->recompute_bbox() ;if (! BM_distance_between_point_and_plane(bloop2->get_bbox_p1(), (BM_PLANE&) (*surface1), &distance_plane_to_bloop1, NULL))return 0 ;if (! BM_distance_between_point_and_plane(bloop2->get_bbox_p2(), (BM_PLANE&) (*surface1), &distance_plane_to_bloop2, NULL)) return 0;if (! BM_distance_between_point_and_plane(bloop2->get_bbox_p3(), (BM_PLANE&) (*surface1), &distance_plane_to_bloop3, NULL)) return 0 ;if (! BM_distance_between_point_and_plane(bloop2->get_bbox_p4(), (BM_PLANE&) (*surface1), &distance_plane_to_bloop4, NULL)) return 0 ;distance_plane_to_bloop_count = 0 ;if (fabs(distance_plane_to_bloop1) >= local_tolerance) distance_plane_to_bloop_count++ ;if (fabs(distance_plane_to_bloop2) >= local_tolerance) distance_plane_to_bloop_count++ ;if (fabs(distance_plane_to_bloop3) >= local_tolerance) distance_plane_to_bloop_count++ ;if (fabs(distance_plane_to_bloop4) >= local_tolerance) distance_plane_to_bloop_count++ ;if (distance_plane_to_bloop_count > 2) {// at most one of the bloop corners is on the plane.// that means, bbox itself is not in contactwith face1.// however, it could be that different corners of bbox are on different sides of the plane.// here we will return if all bloop2 points are on one side of plane1// ie. these two faces cannot be in contact// // note : at most one of the 4 distance_plane_to_bloop-i can be zero.// // in the next line we pick "distance_plane_to_bloop1" for checking not because it is special,// but because any of the 4 would do.if (fabs(distance_plane_to_bloop1) >= local_tolerance) {if (distance_plane_to_bloop1*distance_plane_to_bloop2 >= 0.0 &&distance_plane_to_bloop1*distance_plane_to_bloop3 >= 0.0 &&distance_plane_to_bloop1*distance_plane_to_bloop4>= 0.0) return 1 ;}else {if (distance_plane_to_bloop2*distance_plane_to_bloop3 >= 0.0 &&distance_plane_to_bloop2*distance_plane_to_bloop4 >= 0.0) return 1 ;}}// if the count is 0, 1 or 2, it means that 2, 3 or 4 bbox corners are on the plane.// that means, it is possible that there is acontact./*  ここで、我々は、面２に関してｂボックス１に対して同じものをチェックする。*/if (! bloop1->is_bbox_up_to_date()) bloop1->recompute_bbox() ;if (! BM_distance_between_point_and_plane(bloop1->get_bbox_p1(), (BM_PLANE&) (*surface2), &distance_plane_to_bloop1, NULL)) return 0 ;if (! BM_distance_between_point_and_plane(bloop1->get_bbox_p2(), (BM_PLANE&)(*surface2), &distance_plane_to_bloop2, NULL)) return 0 ;if (! BM_distance_between_point_and_plane(bloop1->get_bbox_p3(), (BM_PLANE&) (*surface2), &distance_plane_to_bloop3, NULL)) return 0 ;if (! BM_distance_between_point_and_plane(bloop1->get_bbox_p4(), (BM_PLANE&) (*surface2), &distance_plane_to_bloop4, NULL)) return 0 ;distance_plane_to_bloop_count = 0;if (fabs(distance_plane_to_bloop1) >= local_tolerance) distance_plane_to_bloop_count++ ;if (fabs(distance_plane_to_bloop2) >= local_tolerance)distance_plane_to_bloop_count++ ;if (fabs(distance_plane_to_bloop3) >= local_tolerance) distance_plane_to_bloop_count++ ;if (fabs(distance_plane_to_bloop4) >= local_tolerance) distance_plane_to_bloop_count++ ;if (distance_plane_to_bloop_count > 2) {// at most one of the bloop corners ison the plane.// here we will return if all bloop1 points are on one sideof plane2// ie. these two faces cannot be in contactif (fabs(distance_plane_to_bloop1) >= local_tolerance) {if (distance_plane_to_bloop1*distance_plane_to_bloop2 >= 0.0 &&distance_plane_to_bloop1*distance_plane_to_bloop3 >= 0.0 &&distance_plane_to_bloop1*distance_plane_to_bloop4 >= 0.0)return 1 ;}else {if (distance_plane_to_bloop2*distance_plane_to_bloop3>= 0.0 &&distance_plane_to_bloop2*distance_plane_to_bloop4 >= 0.0) return 1 ;}}/*********** ********** ********** ********** ********** ********** ********** ********** **********  両面のラインの全数をカウントする。メモリを割当てる必要がある。  注意：ラインのみがベンドラインを作ることが出来るのでラインであるエッジを単にカウントする。  注意：ユーザが特定のベンドエッジを持つか否かをチェックする。ユーザは、どのエッジが可能なベンドエッジとして考えられるかを、それらのエッジの名称を設定することにより限定することが出来る。********** ********** ********** ********** ******************** ********** ********** ***********/long face1_has_user_defined_bend_edges = 0 ; // the number of user-speicifed bend edges in face1long face2_has_user_defined_bend_edges = 0 ; // the number of user-speicifed bend edges in face2long face1_line_count = 0, face2_line_count = 0 ;long line_count ; // sum of lines in faces 1 and 2 participating in the sweep.BM_LOOP *holes ;BM_EDGE *edges ;for (edges = bloop1->get_first_edge() ; edges ; edges = (BM_EDGE *) edges->next()) {if (! edges->is(BM_ENTITY_TYPE_LINE)) continue ;if (edges->get_name() == face2.get_idx()) face1_has_user_defined_bend_edges++ ;face1_line_count++ ;}for (holes = body1->get_first_hole() ; holes ; holes = (BM_LOOP *) holes->next()) {for (edges = holes->get_first_edge() ; edges ; edges = (BM_EDGE *) edges->next()) {if (! edges->is(BM_ENTITY_TYPE_LINE)) continue ;if (edges->get_name()== face2.get_idx()) face1_has_user_defined_bend_edges++ ;face1_line_count++ ;}}for (edges = bloop2->get_first_edge() ; edges ; edges = (BM_EDGE*) edges->next()) {if (! edges->is(BM_ENTITY_TYPE_LINE)) continue ;if (edges->get_name() == face1.get_idx()) face2_has_user_defined_bend_edges++ ;face2_line_count++ ;}for (holes = body2->get_first_hole() ; holes ; holes = (BM_LOOP *) holes->next()) {for (edges = holes->get_first_edge(); edges ; edges = (BM_EDGE *) edges->next()) {if (! edges->is(BM_ENTITY_TYPE_LINE)) continue ;if (edges->get_name() == face1.get_idx()) face2_has_user_defined_bend_edges++ ;face2_line_count++ ;}}// if there are no lines, we are successfully doneif (face1_has_user_defined_bend_edges) face1_line_count = face1_has_user_defined_bend_edges ;if (face2_has_user_defined_bend_edges) face2_line_count = face2_has_user_defined_bend_edges ;if (face1_line_count < 1 || face2_line_count < 1) return 1 ;line_count =face1_line_count + face2_line_count ;/*********** ********** ******************** ********** ********** ********** ********** **********メモリを割り当てる。********** ********** ********** ********** ********** ********** ********** ********** ***********/if (NULL == (line_pointers = new BM_LINE*[line_count])) return 0 ;if (NULL == (line_start_coordinates= new double[line_count])) {delete [] line_pointers ;}/*********** ********** ********** ********** ********** ********** ********** ********************先ず、ラインポインタ配列を充填する。必要なら、ユーザが特定したエッジだけを取る。**********  ********** ********** ********** ******************** ********** ********** ***********/i = 0 ;for (edges = bloop1->get_first_edge() ; edges ; edges = (BM_EDGE *) edges->next()) {if (! edges->is(BM_ENTITY_TYPE_LINE)) continue ;if (face1_has_user_defined_bend_edges && edges->get_name() != face2.get_idx()) continue ;line_pointers[i++] = (BM_LINE *) edges ;}for (holes = body1->get_first_hole() ; holes; holes = (BM_LOOP *) holes->next()) {for (edges = holes->get_first_edge() ; edges ; edges = (BM_EDGE *) edges->next())!160#{if (! edges->is(BM_ENTITY_TYPE_LINE)) continue ;if (face1_has_user_defined_bend_edges && edges->get_name() != face2.get_idx()) continue ;line_pointers[i++] = (BM_LINE*) edges ;}}for (edges = bloop2->get_first_edge() ; edges ; edges = (BM_EDGE *) edges->next()) {if (! edges->is(BM_ENTITY_TYPE_LINE)) continue ;if (face2_has_user_defined_bend_edges && edges->get_name() != face1.get_idx()) continue ;line_pointers[i++] = (BM_LINE *) edges ;}for (holes = body2->get_first_hole() ; holes ; holes = (BM_LOOP *) holes->next()) {for(edges = holes->get_first_edge() ; edges ; edges = (BM_EDGE *) edges->next()) {if (! edges->is(BM_ENTITY_TYPE_LINE)) continue ;if (face2_has_user_defined_bend_edges && edges->get_name() != face1.get_idx()) continue;line_pointers[i++] = (BM_LINE *) edges ;}}/*********** ********** ********** ********** ********** ********** ********** ********** **********Ｘ座標により、つぎにＺ座標により、さらにＹによりラインの配列を分類する。********** ********** ********** ********** ********** ********** ********** ********** ***********/{ // this is a block of code for sorting the array// first, construct the array of points and lines associated with themfor (i = 0 ; i < line_count ; i++) {p = BM_get_greater_point_by_XZY((line_pointers[i])->get_startpt(),(line_pointers[i])->get_endpt()) ;line_start_coordinates[i] = p.X() ;}// sort by XDBM_QuickSort_double(line_start_coordinates, line_count, (long *) line_pointers) ;// sort by Zdouble first_in_set_Z = line_start_coordinates[0] ;long set_Z_size = 1, first_in_set_Z_idx = 0 ;p = BM_get_greater_point_by_XZY((line_pointers[0])->get_startpt(),(line_pointers[0])->get_endpt()) ;line_start_coordinates[0] = p.Z() ;for (i = 1 ; i <= line_count ; i++) {if (i < line_count) {p =BM_get_greater_point_by_XZY((line_pointers[i])->get_startpt(),(line_pointers[i])->get_endpt()) ;if (line_start_coordinates[i] == first_in_set_Z) {set_Z_size++ ;line_start_coordinates[i] = p.Z() ;continue ;}}// elsewe have passed the end of the X-sequenceif (set_Z_size > 1) DBM_QuickSort_double(line_start_coordinates + first_in_set_Z_idx, set_Z_size, (long*) line_pointers + first_in_set_Z_idx) ;// sort by Ylong set_Z_end = first_in_set_Z_idx + set_Z_size ;double first_in_set_Y = line_start_coordinates[first_in_set_Z_idx] ;long set_Y_size = 1, first_in_set_Y_idx = first_in_set_Z_idx ;BM_POINT pY(BM_get_greater_point_by_XZY((line_pointers[first_in_set_Z_idx])->get_startpt(),(line_pointers[first_in_set_Z_idx])->get_endpt())) ;line_start_coordinates[first_in_set_Z_idx] = pY.Y() ;for(j = first_in_set_Z_idx + 1 ; j <= set_Z_end ; j++) {if (j < set_Z_end){pY = BM_get_greater_point_by_XZY((line_pointers[j])->get_startpt(),(line_pointers[j])->get_endpt()) ;if (line_start_coordinates[j] == first_in_set_Y) {set_Y_size++ ;line_start_coordinates[j] = pY.Y() ;continue ;}}//else, we have passed the end of the Z-sequenceif (set_Y_size > 1) DBM_QuickSort_double(line_start_coordinates + first_in_set_Y_idx, set_Y_size,(long *) line_pointers + first_in_set_Y_idx) ;if (j < set_Z_end) {set_Y_size = 1 ;first_in_set_Y_idx = j ;first_in_set_Y = line_start_coordinates[j] ;line_start_coordinates[j] = pY.Y() ;}}if (i < line_count) {set_Z_size = 1 ;first_in_set_Z_idx = i ;first_in_set_Z = line_start_coordinates[i] ;line_start_coordinates[i] = p.Z() ;}}} // end of the block of codefor sorting the array/*********** ********** ********** ********** ********** ********** ********** ********** **********ライン開始座標はこれ以上不要なので、削除する。********** ********** ********** ********** ********** ********** ********** ********** ***********/if (line_start_coordinates) {delete [] line_start_coordinates ;line_start_coordinates = NULL;}/*********** ********** ********** **********  主ループ。２面を掃引する。  開放ラインのトラックを常に保持する（出発点を我々が見たライン、しかし終点は未だ見ていないライン-実際には、開始-そして-終了-点ではなくて、ＸＺＹオーダリングに対してより大きくかつより小さい端点）。  始めに、開放ラインの組は空である。  全ての繰り返しの間次のことを行う：    -開放であったが、今は閉じられるべき全てのラインを除去する、    -現在のラインが開放ラインと重なるか否かをチェックする、    -このラインを開放ラインの組に加える。*/// these represent lists of contactsBM_LINKED_LIST_NODE *face1_list, *face2_list ;BM_LINKED_LIST_NODE *last_face1_list, *last_face2_list;BM_LINKED_LIST_NODE *left, *right ;BM_LINKED_LIST_NODE *new_left = NULL, *new_right = NULL ;BM_LINE *line_in_left, *line_in_right ;// these are the two lines we will be comparingBM_2D_BODY *face_of_line1, *face_of_line2 ;BM_LINE *line_in_face1, *line_in_face2 ;BM_LINE *line ;double k,dotp ;BM_POINT p_open ;BM_VECTOR v ;long num_of_contacts = 0 ;long open_line_idx ;for (i = line_count - 1 ; i >= 0 ; i--) {// initially face_of_line1 is the face of the current line.// however, later we will sort thecurrent-sweep-line and current-open-line pointers.face_of_line1 = ((line_pointers[i])->get_loop())->get_2D_body() ;p = BM_get_greater_point_by_XZY((line_pointers[i])->get_startpt(),(line_pointers[i])->get_endpt()) ;// compare this current line against all open lines in order to detect overlaps, ie. bendlines.for (open_line_idx = i + 1 ; open_line_idx < line_count ; open_line_idx++) {line = line_pointers[open_line_idx] ;if (NULL== line) {// time-saving trick. if this is the last pointer, there is no need to try it again.// reduce the index.if (open_line_idx == line_count - 1) {--line_count ;break ;}continue ;}// ********** ********** ********** ********** **********// check if this open line should really be removed.// it should be removed if its endpoint is larger than p (ie. the// startpoint of this line).// ********** ********** ********** ********** **********p_open = BM_get_smaller_point_by_XZY(line->get_startpt(),line->get_endpt()) ;if (BM_compare_points_by_XZY(p_open,p)) {// time-saving trick.// if the line we are removing from the open list is the last one, reduce the index// instead of setting the pointer to NULL. next timewe don’t even try this element// in the array, because it would be beyond the boundaryif (open_line_idx == line_count - 1) {--line_count ;break;}line_pointers[open_line_idx] = NULL ;continue ;}// ********** ********** ********** ********** **********// first, check if both lines are inthe same face. if yes, skip it.// ********** ********** ********** ********** **********face_of_line2 = (line->get_loop())->get_2D_body() ;if (face_of_line1 == face_of_line2) continue ;// ********** ********** ********** ********** **********// Check if this line and the open line overlap.// ********** ********** ********** ********** **********// First check if the startpoint is on the (open) line segment.if (! line->is_point_on_line(p,&k)) continue ;// Note that parameter k has to be in [0,1] now, because// the line "line" is open still, ie. it startpoint is "before"p// and endpoint is "after" p.// Now check if vectors are parallel.v =(line->get_v()) * ((line_pointers[i])->get_v()) ;if (v.Len() > BM_PRECISION) continue ;// Last thing, it could be that only endpoints of the lines overlap.dotp = (line->get_v()) % ((line_pointers[i])->get_v()) ;if (dotp < 0.0) { // lines are opposite// startpoint-startpoint/endpoint-endpoint should not matchif ((line->get_startpt()) == ((line_pointers[i])->get_startpt()) || (line->get_endpt()) == ((line_pointers[i])->get_endpt())) continue ;}else { // lines have the same direction// startpoint-endpoint/endpoint-startpoint should not matchif ((line->get_endpt()) == ((line_pointers[i])->get_startpt()) || (line->get_startpt()) == ((line_pointers[i])->get_endpt())) continue ;}// ********** ********** ********** ********** **********// Ok, these two lines overlap.// First, sort lines according to which face they are in// ********** ********** ********** ********** **********if (&face1 == (BM_FACE *) face_of_line1->get_3D_body()) {line_in_face1 = line_pointers[i] ;line_in_face2 = line ;p_face1 = p ;p_face2 = BM_get_greater_point_by_XZY(line->get_startpt(),line->get_endpt()) ;}else {line_in_face1 = line ;line_in_face2 = line_pointers[i] ;p_face1 = BM_get_greater_point_by_XZY(line->get_startpt(),line->get_endpt()) ;p_face2 = p ;}// ********** ********** ********** ********** **********// Scan all known contacts and check if this contact should be// addedto an existing contact// ********** ********** ********** ********** **********for (j = 0, last_face2_list = NULL ; j < num_of_contacts ; j++){if (NULL == last_face2_list) {last_face1_list = contacts ;last_face2_list = last_face1_list->next() ;}else {last_face1_list = last_face2_list->next() ;last_face2_list = last_face1_list->next() ;}left = (BM_LINKED_LIST_NODE *) last_face1_list->get_obj() ;right = (BM_LINKED_LIST_NODE *) last_face2_list->get_obj() ;line_in_left = (BM_LINE *) left->get_obj() ;line_in_right = (BM_LINE *) right->get_obj() ;// Check if the line of this existing contact overlaps the new contact.// condition is : point on the line and vectors are parallel.if (! line_in_left->is_point_on_line(p_face1,&k)) continue ;v = (line_in_left->get_v()) * (line_in_face1->get_v()) ;if (v.Len() > BM_PRECISION) continue ;// Check that lines in face1and face2 and exact extensions of left and right in this contact// thisis because we want every contact in the list of contacts to be a "closed" contact// note it could be that one of the new lines in already in this contact.// then we don’t need to check.if (line_in_left != line_in_face1) {dotp = (line_in_left->get_v()) % (line_in_face1->get_v()) ;if (dotp < 0.0) { // lines are opposite// startpoints must matchif ((line_in_left->get_startpt()) != (line_in_face1->get_startpt()) &&(line_in_left->get_endpt()) != (line_in_face1->get_endpt())) continue ;}else { // lines have the same direction// endpoints must matchif ((line_in_left->get_endpt()) != (line_in_face1->get_startpt()) &&(line_in_left->get_startpt()) != (line_in_face1->get_endpt())) continue ;}}if (line_iｎ＿right != line_in_face2) {dotp = (line_in_right->get_v()) % (line_in_face2->get_v()) ;if(dotp < 0.0) { // lines are opposite// startpoints must matchif ((line_in_right->get_startpt()) != (line_in_face2->get_startpt()) &&(line_in_right->get_endpt()) != (line_in_face2->get_endpt())) continue ;}else { // lines have the same direction// endpoints must matchif ((line_in_right->get_endpt()) != (line_in_face2->get_startpt()) &&(line_in_right->get_startpt()) != (line_in_face2->get_endpt())) continue ;}}// everything is fine. add lines to this contact.// note that is could be that the line is already in the contact.if (line_in_left != line_in_face1) {if (NULL == (new_left = new BM_LINKED_LIST_NODE(line_in_face1,NULL,left))) goto failure ;last_face1_list->set_obj((BM_BASIC *) new_left) ;new_left = NULL ;}if(line_in_right != line_in_face2) {if (NULL == (new_right = new BM_LINKED_LIST_NODE(line_in_face2,NULL,right))) goto failure ;last_face2_list->set_obj((BM_BASIC *) new_right) ;new_right = NULL ;}// now we have to break out of here. we added this contact to an existing contact.break ;}//check if we checked all contacts and could not find a matchif (j < num_of_contacts) continue ;// ********** ********** ********** ********** **********// Create a new contact.// ********** ********** ********** ********** **********// First, create nodes for both!160#lines.if (NULL == (left= new BM_LINKED_LIST_NODE(line_in_face1))) goto failure ;if (NULL == (right = new BM_LINKED_LIST_NODE(line_in_face2))) {delete left ;goto failure ;}// Create lists for both sides of the contact.if (NULL == (face2_list = new BM_LINKED_LIST_NODE((BM_BASIC *) right))) {delete left ;delete right ;goto failure ;}if (NULL == (face1_list = new BM_LINKED_LIST_NODE((BM_BASIC *) left,NULL,face2_list))) {delete left ;delete right ;delete face2_list ;goto failure ;}// add the new contact to the list of contactsif (num_of_contacts < 1) contacts = face1_list ;else last_face2_list->add_after(face1_list) ;++num_of_contacts ;}// we use i to index line_pointers[] array.// since i will be decremented shortly, line_pointers[i] will be "implictly" put on // the open list of sweep lines.}/*********** ********** ********** **********必要ならメモリを自由にする。********** ********** ********** ***********/if (line_start_coordinates) delete [] line_start_coordinates ;if (line_pointers) delete [] line_pointers ;// finally, create a node for the number of contactsif (NULL == (left = new BM_LINKED_LIST_NODE((BM_BASIC *) num_of_contacts,NULL,contacts))) goto failure ;*list_of_contacts = left ;return 1 ;failure :// free memory if necessaryif (line_start_coordinates) delete [] line_start_coordinates ;if (line_pointers) delete [] line_pointers ;BM_LINKED_LIST_NODE *list, *next_list ;BM_LINKED_LIST_NODE *line_in_list, *next_line_in_list ;for (list =contacts ; list ; list = next_list) {next_list = list->next() ;for (line_in_list = (BM_LINKED_LIST_NODE *) list->get_obj() ; line_in_list ; line_in_list = next_line_in_list) {next_line_in_list = line_in_list->next();delete line_in_list ;}delete list ;}if (new_left) delete new_left ;if(new_right) delete new_right ;return 0 ;}/*  この関数は２つの面の間のコンタクトのリストを掃引する  （ＢＭにより殆ど同様に生成される  全ての面から面の接点を計算する）そして全ての、ただし最大の接点を除去する。  基本的には、それは接点のリストを”濾過”し、最も長い接触部に属さない接触部を除去する。一般に、最も長い接触部は同時的なベンドラインのリストである点に注目されたい。かくして、接触部リストの基本構造は同じである。  例えば、リスト中の第一のノードは最も長いコンタクト中のコンタクトの数である。  この関数はまた最も長いコンタクトの長さに戻す。  この関数においては、全てのコンタクトが閉じられ、従ってコンタクト中のラインのリストにおいて、ラインの端点は次のラインの出発点に等しくなるという事実を利用している。  この方法で唯一のトリッキーな部分は、第一の、および最後のラインにおける重なり部分の長さを計算することにある。次に、リストの中間でラインの長さを付加する。
前の関数を参照されたい。*/static double BM_keep_largest_contact_remove_the_rest(BM_LINKED_LIST_NODE **list_of_contacts){long i, j ;if (NULL == list_of_contacts) return 0.0 ;BM_LINKED_LIST_NODE *contacts = *list_of_contacts ;if (NULL == contacts) return 0.0 ;// some of the most importantparameters we compute in this function.double length_of_largest_contact= 0.0 ;long largest_contact_i = -1 ;// we need to keep track of the lengths of contacts.// we need to store the length of every contact.// // NOTICE : here we try to save some heap allocation/release time by using apre-allocated// array if the list of contacts is not very long.// staticdouble static_contact_len_array[32] ;double *dynamic_contact_len_array= NULL ;double *contact_len_array = NULL ;// get the number of contactslong num_of_contacts = (long) contacts->get_obj() ;contacts = contacts->next() ;// if no contacts, delete the entire listif (num_of_contacts < 1){// there is no list. delete node 0 as well.delete *list_of_contacts ;*list_of_contacts = NULL ;return 0.0 ;}// allocate memory for the contactlength arrayif (num_of_contacts <= 32) {contact_len_array = static_contact_len_array ;}else {if (NULL == (dynamic_contact_len_array = new double[num_of_contacts])) goto computation_done__clean_up ;contact_len_array= dynamic_contact_len_array ;}// Scan all known contacts and compute thelength of every contact.// later we use these values to find the longest contact (which could be a simultaneous bendline).BM_LINKED_LIST_NODE *last_face1_list, *last_face2_list ;BM_LINKED_LIST_NODE *line_in_list ;double k ;double first_k1, first_k2 ;double last_k1, last_k2 ;last_face2_list = NULL ;for (i = 0 ; i < num_of_contacts ; i++) {if (NULL == last_face2_list) last_face1_list = contacts ;else last_face1_list = last_face2_list->next() ;last_face2_list = last_face1_list->next() ;BM_LINKED_LIST_NODE *left = (BM_LINKED_LIST_NODE *) last_face1_list->get_obj() ;BM_LINKED_LIST_NODE *right = (BM_LINKED_LIST_NODE *) last_face2_list->get_obj();BM_LINE *first_line_in_left = (BM_LINE *) left->get_obj() ;BM_LINE *first_line_in_right = (BM_LINE *) right->get_obj() ;// here is what we do.we know that the first lines in left and right have to have// an overlapping part. we compute overlapping parameters k1 and k2 with respect tothe// first line on the left, between the first lines. // the idea is that one of the points that corresponds to these parameters (k1 and k2)//is the extreme point of the contact. we just don’t know yet which one.// then we find the last points in both lists. we know that they must have non-empty// overlapping part as well. we compute k1 and k2 for these two lines as well.// then we compate k1,k2 for the first and last pairs to find the two// extreme points of the contact. distance between them isthe length of the contact.// compute k1 and k2 for the first lines.first_line_in_left->is_point_on_line(first_line_in_right->get_startpt(),&first_k1) ;first_line_in_left->is_point_on_line(first_line_in_right->get_endpt(),&first_k2) ;// we only want k1 and k2 within the first lineif (first_k1 < 0.0) first_k1 = 0.0 ;else if (first_k1 > 1.0) first_k1 = 1.0 ;if(first_k2 < 0.0) first_k2 = 0.0 ;else if (first_k2 > 1.0) first_k2 = 1.0 ;// sort k1 and k2if (first_k1 > first_k2) { k = first_k1 ; first_k1 =first_k2 ; first_k2 = k ; }// find the last line in the left.for (line_in_list = left->next() ; line_in_list ; line_in_list = line_in_list->next()) {left = line_in_list ;}// "left" is the last node in the left now.BM_LINE *last_line_in_left = (BM_LINE *) left->get_obj() ;// find the last line in the right.for (line_in_list = right->next() ; line_in_list ; line_in_list = line_in_list->next()) {right = line_in_list ;}// "right" is the last node in the left now.BM_LINE *last_line_in_right = (BM_LINE *) right->get_obj() ;// compute k1 and k2 for the first lines.last_line_in_left->is_point_on_line(last_line_in_right->get_startpt(),&last_k1) ;last_line_in_left->is_point_on_line(last_line_in_right->get_endpt(),&last_k2) ;// we only want k1 and k2 within the last lineif (last_k1 < 0.0) last_k1 = 0.0 ;else if (last_k1 > 1.0) last_k1 = 1.0 ;if (last_k2 < 0.0) last_k2 = 0.0 ;else if (last_k2 > 1.0) last_k2 = 1.0 ;// note that we have compute last k1 and k2 with respect to the last line in the left.// wereally need last k1 and k2 with respect to the first line in the left.BM_POINT lastk1(last_line_in_left->get_startpt() + last_k1*(last_line_in_left->get_v())) ;BM_POINT lastk2(last_line_in_left->get_startpt() + last_k2*(last_line_in_left->get_v())) ;first_line_in_left->is_point_on_line(lastk1,&last_k1) ;first_line_in_left->is_point_on_line(lastk2,&last_k2);// sort k1 and k2if (last_k1 > last_k2) { k = last_k1 ; last_k1 = last_k2 ; last_k2 = k ; }// now we need to take the extreme points of these two pairsif (first_k1 > last_k1) first_k1 = last_k1 ;if (first_k2 < last_k2) first_k2 = last_k2 ;contact_len_array[i] = (first_k2 - first_k1)*(first_line_in_left->get_len()) ;}// find the longest contact.// the main feature here is to check for simultaneous bendlineslast_face2_list = NULL;for (i = 0 ; i < num_of_contacts ; i++) {if (NULL == last_face2_list)last_face1_list = contacts ;else last_face1_list = last_face2_list->next() ;last_face2_list = last_face1_list->next() ;// make sure we don’t accept contacts that have zero length.if (contact_len_array[i] < BM_PRECISION) continue ;BM_LINKED_LIST_NODE *left = (BM_LINKED_LIST_NODE *) last_face1_list->get_obj() ;BM_LINE *first_line_in_left = (BM_LINE *) left->get_obj() ;// check if this contact is part of a simultaneous bendline.//if yes, add its length to the first bendline in the simultaneous bendline and// set this length here to -1.0, so that we know it laterBM_LINKED_LIST_NODE *temp_last_face1_list, *temp_last_face2_list = NULL ;for (j =0 ; j < i ; j++) {if (contact_len_array[i] < BM_PRECISION) continue ; // already part of something elseif (NULL == temp_last_face2_list) temp_last_face1_list = contacts ;else temp_last_face1_list = temp_last_face2_list->next() ;temp_last_face2_list = temp_last_face1_list->next() ;BM_LINKED_LIST_NODE *temp_left = (BM_LINKED_LIST_NODE *) temp_last_face1_list->get_obj() ;BM_LINE *temp_first_line_in_left = (BM_LINE *) temp_left->get_obj() ;// check if the lines overlapif (! first_line_in_left->is_point_on_line(temp_first_line_in_left->get_startpt(),NULL)) continue ;if (! first_line_in_left->is_point_on_line(temp_first_line_in_left->get_endpt(),NULL)) continue ;// ok, they overlap// add the length to the first in simultaneous bend and set this to -1.0contact_len_array[j] += contact_len_array[i] ;contact_len_array[i] = -1.0 ;break ;}}// in this loop we actually find the largestfor (i = 0 ; i < num_of_contacts ; i++) {// check to see if this new contact is the largestif (length_of_largest_contact <contact_len_array[i]) {length_of_largest_contact = contact_len_array[i];largest_contact_i = i ;}}computation_done__clean_up :// remove all other contacts that are not largestBM_LINKED_LIST_NODE *next_last_face1_list, *next_last_face2_list = NULL ;BM_LINKED_LIST_NODE *largest_contact_list_f1 = NULL, *largest_contact_list_f2 ;last_face1_list = contacts ;last_face2_list = last_face1_list->next() ;for (i = j = 0 ; i < num_of_contacts ; i++) {next_last_face1_list = last_face2_list->next() ;if (next_last_face1_list) next_last_face2_list = next_last_face1_list->next() ;else next_last_face2_list = NULL ;// make sure we don’t delete the largest contact// note : we skip two lists, face1 list and face2 listif (contact_len_array[i] < 0.0 || largest_contact_i == i) {if (NULL == largest_contact_list_f1) largest_contact_list_f1 = last_face1_list ;else largest_contact_list_f2->add_after(last_face1_list) ;largest_contact_list_f2 = last_face2_list ;// count the number of contacts++j ;last_face1_list = next_last_face1_list ;last_face2_list = next_last_face2_list ;continue ;}// ok,this is not the largest contact, delete both face1 and face2 sides of the contactBM_LINKED_LIST_NODE *next_line_in_list ;for (line_in_list = (BM_LINKED_LIST_NODE *) last_face1_list->get_obj() ; line_in_list ; line_in_list = next_line_in_list) {next_line_in_list = line_in_list->next() ;delete line_in_list ;}for (line_in_list = (BM_LINKED_LIST_NODE *) last_face2_list->get_obj() ; line_in_list ; line_in_list = next_line_in_list) {next_line_in_list = line_in_list->next() ;delete line_in_list ;}delete last_face1_list ;delete last_face2_list ;last_face1_list = next_last_face1_list ;last_face2_list = next_last_face2_list ;}// end the contact listwith a NULL pointerif (largest_contact_list_f2) largest_contact_list_f2->add_after(NULL) ;// write the number of contacts left in node 0. also,set the correct beginning of the list.// however, if there is no contact, erase the entire list.if (NULL == largest_contact_list_f1) {// thereis no list. delete node 0 as well.delete *list_of_contacts ;*list_of_contacts = NULL ;}else {(*list_of_contacts)->set_obj((BM_BASIC *) j) ;(*list_of_contacts)->add_after(largest_contact_list_f1) ;}// delete dynamic_contact_len_array if it was allocatedif (dynamic_contact_len_array) delete [] dynamic_contact_len_array ;return length_of_largest_contact ;}/*この関数は、サブルーチンとして静的なｉｎｔ  ＢＭ  ｃｒｅａｔｅ  ベンドライン（．．．）によってのみ用いられる。  現在の大きな問題は、我々が幾つかのラインを削除しているということである。  この問題は、我々が同時ベンドを持つとき、他のコンタクトはなお我々が丁度削除したこれらのラインを参照していることが出来るということである。  我々は進んでそれをチェックしなければならず、もし真なら、有効な参照によりポインタを我々が変更し／削除したラインに置き換えなければならない。  すなわち、影響されたラインは左側の最初のそして最後のラインである。  潜在的には、それらに対する参照は１１および１３を参照して置き換えられる必要がある。*/static void check_references_in_remaining_contacts(BM_LINKED_LIST_NODE *side_1, // current list we are working withBM_LINKED_LIST_NODE *side_2, // list on the other side of thecontactBM_LINE *line1, BM_LINE *line3, // these are old references, tobe checked if still validBM_LINE *l1, BM_LINE *l3 // l1 and l3 are the new references){BM_LINKED_LIST_NODE *side1 = side_1, *side2 = side_2 ;process_next_contact :// find the beginnings of lists in the next contactBM_LINKED_LIST_NODE *contact_list ;if (NULL == (contact_list = side1->next())) return ; // done, no more listsif (NULL == (side1 = contact_list->next())) return ; // done, no more listsif (NULL == (contact_list = side2->next())) return ; // done, no more listsif (NULL == (side2 = contact_list->next())) return ; // done, no more lists// now we need to check thebeginning of this contact and the end of this contact exactly the sameway.// we describe checking the beginning, check the end is the same.//whenever we find a match, we can go to the next list (ie. don’t have tocontinue with the// current list).// // we take first lines is side1 and side2. if the first line in side1 is either line1 or line3,// we checkwhich of l1 and l3 overlaps the first line in side2. we know that exactly one of// l1 and l3 has to overlap. then we replace the reference to line1/line3 with a reference to the// one of l1/l3 that overlaps the first line in side2.BM_LINKED_LIST_NODE *start_side1 = (BM_LINKED_LIST_NODE*) side1->get_obj() ;BM_LINKED_LIST_NODE *start_side2 = (BM_LINKED_LIST_NODE *) side2->get_obj() ;// check the beginning of the contactBM_LINE *line_in_side1 = (BM_LINE *) start_side1->get_obj() ;BM_LINE *line_in_side2 = (BM_LINE *) start_side2->get_obj() ;if (line_in_side1 == line1 || line_in_side1 == line3) {if (l1) { // check if l1 overlaps first line inside2if (line_in_side2->is_point_on_line_segment(l1->get_startpt(), NULL) ||line_in_side2->is_point_on_line_segment(l1->get_endpt(), NULL)) {start_side1->set_obj(l1) ;goto process_next_contact ;}}if (l3) { // check if l3 overlaps first line in side2if (line_in_side2->is_point_on_line_segment(l3->get_startpt(), NULL) ||line_in_side2->is_point_on_line_segment(l3->get_endpt(), NULL)) start_side1->set_obj(l3) ;}goto process_next_contact ;}BM_LINKED_LIST_NODE *line_in_list, *prev_line_in_list ;// find the last line in side2.for (line_in_list = start_side2->next() ; line_in_list ; line_in_list = line_in_list->next()) {prev_line_in_list = line_in_list ;}// "prev_line_in_list" is the last node in the left now.line_in_side2 = (BM_LINE *) prev_line_in_list->get_obj() ;// find the last line in side1.for (line_in_list = start_side1->next() ; line_in_list ; line_in_list = line_in_list->next()) {prev_line_in_list = line_in_list ;}// "prev_line_in_list" is the last node in side1 now.line_in_side1 = (BM_LINE*) prev_line_in_list->get_obj() ;// check the end of the contactif (line_in_side1 == line1 || line_in_side1 == line3) {if (l1) { // check if l1overlaps first line in side2if (line_in_side2->is_point_on_line_segment(l1->get_startpt(), NULL) ||line_in_side2->is_point_on_line_segment(l1->get_endpt(), NULL)) {prev_line_in_list->set_obj(l1) ;goto process_next_contact ;}}if (l3) { // check if l3 overlaps first line in side2if (line_in_side2->is_point_on_line_segment(l3->get_startpt(), NULL) ||line_in_side2->is_point_on_line_segment(l3->get_endpt(), NULL)) prev_line_in_list->set_obj(l3) ;}}goto process_next_contact ;}/*  この関数は、入力として与えられたコンタクトリストに基づいて、２つの面間に簡単な（規則的な）ベンドラインを形成する。一端これがなされると、それはコンタクトリストを消去する。  この関数では、面のエッジは左手の規則に従って分類されると仮定する。
この関数は、もし全てがファインのときは、ＴＲＵＥに戻す。  ＮＢ！ここでの問題点は、新しいベンドラインを形成したとき、何かを部分的に無効にすることではない。  それを完成するために、我々は、分離であるベンドｏｐを形成し（ベンドライン無しに）（原文理解出来ず）、後にそれをベンドラインに付加する。  更に、我々は、ベンドラインが形成され、部分に付加された後にのみトポロジーを形成する。  この関数は、面１（主として、垂直な面１）に一致するベンドライン情報を形成する点に注目されたい。  ただし、垂直な面２はこの情報と不一致でもよいが、後に固定されなければならない。*/static int BM_create_bendline(BM_PART & part, BM_LINKED_LIST_NODE **contact, BM_BENDLINE **bendline_created /* OUT */){// so far, nothing is created*bendline_created= NULL ;// it is possible, that we are building bendlines for the flat version of the part.// if this variables is TRUE, we are building bendlines for the 3D-version, otherwise for the flat.int using_3D_version = 1 ;// later we need to create a bendline centerline// these are the start-end points of the bendline centerline// note that they are points p1 andp2 on the face1 side of the bendline// this is done because sometimes (when the bendline is not bent) we use the// face1 surface as the bendlinesurface, ie. the bendline orientation is defined// with respect to face1BM_POINT bendline_centerline_p1, bendline_centerline_p2 ;// contact list parametersBM_LINKED_LIST_NODE *line_in_list, *next_line_in_list ;BM_LINKED_LIST_NODE *left, *right ;int number_of_lists = (long) (*contact)->get_obj() ;BM_LINKED_LIST_NODE *contact_list = (*contact)->next() ;left =(BM_LINKED_LIST_NODE *) contact_list->get_obj() ;right = (BM_LINKED_LIST_NODE *) (contact_list->next())->get_obj() ;BM_LINE *first_line_in_left= (BM_LINE *) left->get_obj() ;BM_LINE *first_line_in_right = (BM_LINE*) right->get_obj() ;BM_LINE *last_line_in_left ;BM_LINE *left_line, *right_line ;// get loops in both bodiesBM_LOOP *face1_loop = first_line_in_left->get_loop() ;BM_LOOP *face2_loop = first_line_in_right->get_loop();if (NULL == face1_loop || NULL == face2_loop) return 0 ;// 2D-bodies of either faceBM_2D_BODY *face1_body = face1_loop->get_2D_body() ;BM_2D_BODY *face2_body = face2_loop->get_2D_body() ;if (NULL == face1_body || NULL == face2_body) return 0 ;// get face1 and face2BM_FACE *face1 = (BM_FACE *) face1_body->get_3D_body() ;BM_FACE *face2 = (BM_FACE *) face2_body->get_3D_body() ;if (NULL == face1 || NULL == face2) return 0 ;// check whether we are using the flat version of the part, or 3D-version of the part.if (face1->get_current_3D_version() != face1_body || face2->get_current_3D_version() != face2_body) using_3D_version = 0 ;// get surfacesof either facesBM_PLANE *face1_plane, *face2_plane ;face1_plane = (BM_PLANE *) face1_body->get_surface() ;face2_plane = (BM_PLANE *) face2_body->get_surface() ;/*  先ず、ベンドラインと共にしなければならない全てのこと、ベンドラインを形成する、ベンドｏｐを形成する、ベンドｏｐパラメータを設定する、ベンドラインに対するシリンダを形成、設定する、ベンドライン、センタラインを設定するなどを行う。*/// try to figure out whether we have aFRONT or BACK bend.BM_VECTOR v_face2_body((face2_plane->get_normal())*(first_line_in_right->get_v())) ; // this vector// points towards the inside of face2 on the plane of face2BM_VECTOR v_face2_normal(v_face2_body*(first_line_in_left->get_v())) ; // this is the correct normal for face2?// compute the angle between facesdouble angle = v_face2_normal ^ (face1_plane->get_normal()) ;// compute bend type (FRONT/BACK)if (fabs(angle) <= BM_ANGLE_TOLERANCE) angle = PI ;else {BM_VECTOR v((face1_plane->get_normal())*v_face2_normal) ;if (v % (first_line_in_left->get_v()) > 0.0)angle = PI + angle ; // BACK bendelse angle = PI - angle ; // FRONT bend}// create a new empty bendline and add it to the partBM_2D_BODY *new_auto_bendline = new BM_2D_BODY ;if (NULL == new_auto_bendline) return 0 ;BM_BENDLINE *new_bendline = new BM_BENDLINE(&part, using_3D_version ? NULL : new_auto_bendline, using_3D_version ? new_auto_bendline : NULL) ;if(NULL == new_bendline) {delete new_auto_bendline ;return 0 ;}// createa regular bend op for the bendlineBM_BEND_OP_REGULAR *new_bend_op = newBM_BEND_OP_REGULAR(NULL,angle,0.0,0.0) ; // don’t attach to bendline yetif (NULL == new_bend_op) {delete new_bendline ;return 0 ;}// attach this bend op to the bendline. this will just assign the bend_op variable inthe bendlinenew_bendline->attach_bend_op(new_bend_op) ;// create bendline surface. if angle is not 180 degrees, we create a cylinder, otherwisea (face1) plane.BM_SURFACE *bend_surface ;if (fabs(angle - PI) <= BM_ANGLE_TOLERANCE) { // bendline not being bent// note : face1 plane is thebendline surfacebend_surface = new BM_PLANE(*face1_plane) ;new_bendline->Do_This_Bend(0) ; // this will invalidate 3D version as well. later wevalidate it.// set sense to the same as face1 sensenew_auto_bendline->set_sense(face1_body->get_sense()) ;}else {// first, compute vxBM_VECTOR v_face1_body((face1_plane->get_normal())*(first_line_in_left->get_v())) ;// v_face1_body points towards the inside of face1 on the plane of face1v_face1_body.set_length(-1.0) ; // invert and normalizev_face2_body.set_length(-1.0) ; // invert and normalize// this is the vx vector of the bendline surfaceBM_VECTOR vx(v_face1_body + v_face2_body) ;bend_surface =new BM_CYLINDER(first_line_in_left->get_startpt(), first_line_in_left->get_endpt(), vx, 0.0) ;new_bendline->Do_This_Bend(1) ; // this will invalidate 3D version as well. later we validate it.// set sense to 0, because we want the bendline (cylinder) to represent explicitly OUTSIDE// ie.thickness vector is opposite to the normal (= radius vector).new_auto_bendline->set_sense(0) ;}if (NULL == bend_surface) {delete new_bendline ;return 0 ;}new_auto_bendline->set_surface(bend_surface) ;// lastly we need to create the bendline centerline, but for that we need to know its length, and// start-end-points. However, for that we need to process the contact list which contains the// lines that are adjacent. We will do that next, and when done, will create bendline centerline./*  第二に、必要なら、幾つかのラインを破断し、全ての隣接ラインを１つの隣接ラインに結合する。更に、面１-ベンドラインと面２-ベンドラインの間の隣接情報を形成する。
*/// notice that processing one side of the contact is independent of the other side.// moreover, the logic is exactly the same. therefore, we will use the following code// to process both face1’ side and face2’ side.char face2_processed = 0 ;process_one_side_of_the_contact :// in general, the contact line (on the side of either face (face1 and face2)) will consist// of three lines - we have a list of lines, first line is theline before the contact, the// second line is the contact line, the lastline is the line after the contact.// these variables will be used to compute these three lines.double k ;double k0, k1, k2, k3 ; // parametersk for the first line in the leftdouble end_k1, end_k2 ; // parameters kfor the last line in the left listBM_POINT p0, p1, p2, p3 ; // p0 - p3are the endpoints of the edges that will be left (ie. endpoint of left_line, l2, l3).// p0 and p3 and the two extreme endpoints and trivial to find. we really need to compute only p1 and p2.BM_LINE *l1, *l2, *l3 ; //l1 is the line before l2, l2 is the line that is adjacent, l3 is the one after it.// process first line of the left sidek0 = 0.0 ;k3 = 1.0 ;first_line_in_left->is_point_on_line(first_line_in_right->get_startpt(),&k1) ;first_line_in_left->is_point_on_line(first_line_in_right->get_endpt(),&k2) ;if (k1 > 1.0) k1 = 1.0 ;else if (k1 < 0.0) k1 = 0.0 ;if (k2 > 1.0) k2 = 1.0 ;else if (k2 < 0.0) k2 = 0.0 ;if (k2 < k1) { k = k1 ; k1 = k2; k2 = k ; }// note that we cannot yet compute p0, p1 and p3 because wedon’t know the relative order// of the first and last lines in the left list// find and process the last linefor (line_in_list = left ; line_in_list ; line_in_list = next_line_in_list) {if (NULL == (next_line_in_list = line_in_list->next())) {left_line = (BM_LINE *) line_in_list->get_obj() ;// first, we have to find the end of the face2 listfor (line_in_list = right ; line_in_list ; line_in_list = next_line_in_list) {if (NULL== (next_line_in_list = line_in_list->next())) break ;}right_line = (BM_LINE *) line_in_list->get_obj() ;left_line->is_point_on_line(right_line->get_startpt(),&end_k1) ;left_line->is_point_on_line(right_line->get_endpt(),&end_k2) ;if (end_k1 > 1.0) end_k1 = 1.0 ;else if (end_k1 < 0.0) end_k1 = 0.0 ;if (end_k2 > 1.0) end_k2 = 1.0 ;else if (end_k2 < 0.0) end_k2 = 0.0 ;if (end_k2 < end_k1) { k = end_k1 ; end_k1 = end_k2 ; end_k2 =k ; }break ;}}// now we have to compute points p0, p1, p2 and p3.// butfirst we need to convert end-k parameters to equivalent parameters withrespect to the // first line in the leftp0 = left_line->get_startpt() ;p1 = left_line->get_startpt() + end_k1 * (left_line->get_v()) ;p2 = left_line->get_startpt() + end_k2 * (left_line->get_v()) ;p3 = left_line->get_endpt() ;// check k0first_line_in_left->is_point_on_line(p0,&k) ;if (k< k0) k0 = k ;// check k1first_line_in_left->is_point_on_line(p1,&k) ;if(k < k1) k1 = k ;// check k2first_line_in_left->is_point_on_line(p2,&k);if (k > k2) k2 = k ;// check k3first_line_in_left->is_point_on_line(p3,&k) ;if (k > k3) k3 = k ;// here we can compute p0, p1 and p3. later wecompute p2.p0 = first_line_in_left->get_startpt() + k0 * (first_line_in_left->get_v()) ;p1 = first_line_in_left->get_startpt() + k1 * (first_line_in_left->get_v()) ;p2 = first_line_in_left->get_startpt() + k2 * (first_line_in_left->get_v()) ;p3 = first_line_in_left->get_startpt() + k3 *(first_line_in_left->get_v()) ;// ok, we have computed p0-p3. now we will erase left list, except for the first line.// we need the first linelater.// actually, the first line will, in the future, point to new linel2.BM_LOOP *left_loop = first_line_in_left->get_loop() ;last_line_in_left = NULL ; // the last line in the left. we need it later to replace out-of-date pointers with valid ones.line_in_list = left->next() ; // thisis the second line in the left list.left->add_after(NULL) ;// note : wewill erase all lines in the left list, starting from the second line.for (; line_in_list ; line_in_list = next_line_in_list) {next_line_in_list= line_in_list->next() ;// store a pointer to the last linelast_line_in_left = (BM_LINE *) line_in_list->get_obj() ;left_loop->remove_edge(last_line_in_left) ;delete last_line_in_left ;delete line_in_list ;}// finally, create the adjacent line l2, and two more lines (l1 and l3) if necessary.if (p0 != p1) {l1 = first_line_in_left ;l1->set(p0,p1) ;l2 = new BM_LINE(p1,p2) ;left_loop->add_edge_after(l1,l2) ;}else {l1 = NULL ;l2 = first_line_in_left ;l2->set(p0,p2) ;}if (p2 != p3) {l3 = new BM_LINE(p2,p3) ;left_loop->add_edge_after(l2,l3) ;}else l3 = NULL ;// last thing, create topology by making this line adjacent to the bendlinel2->make_body_adjacent(new_bendline) ;// a big problem now is that we have deleted some lines.// the problem is that if we have a simultaneous bend, other contacts could still be refering// to these lines we just deleted.// we have to go and check that, and if true, replace pointers to the lines we have changed/deleted// with valid references.// // namely, lines that areaffected are the first and last lines in the left.// potentially references to them need to be replaced with references to l1 and l3.if (l1 || l3) check_references_in_remaining_contacts(face2_processed ? contact_list->next() : contact_list, // current list we are working withface2_processed ? contact_list : contact_list->next(), // list on the other side ofthe contactfirst_line_in_left, last_line_in_left, // these are old references, to be checked if still validl1, l3 // l1 and l3 are the new references) ;// we will use the same piece of code to process both sides of the contact.// if face2 side has not been processed, do it now.// however, first we need to set some values of variables that are commonly used.if (! face2_processed) {face2_processed = 1 ;// first, l2 should be the left line.// l2 is the real adjacent line (on the left). now it becomes the right line.left->set_obj(l2) ;// now we need to switch left and rightsides// switch linesfirst_line_in_left = first_line_in_right ;first_line_in_right = l2 ;// switch listsline_in_list = left ;left = right ;right= line_in_list ;// store bendline centerline start-end pointsbendline_centerline_p1 = p1 ;bendline_centerline_p2 = p2 ;goto process_one_side_of_the_contact ;}/*ここで、コンタクトリストを削除することが出来る。*/BM_LINKED_LIST_NODE *list, *next_list ;int lists_deleted = 0 ; // note, we can only delete first two listsfor (list = contact_list ; lists_deleted <2 && list ; list = next_list) {next_list = list->next() ;// delete the listfor (line_in_list = (BM_LINKED_LIST_NODE *) list->get_obj() ; line_in_list ; line_in_list = next_line_in_list) {next_line_in_list = line_in_list->next() ;delete line_in_list ;}delete list ;++lists_deleted ;}// setthe correct number of contacts left and update the pointerslong num_contacts = (long) (*contact)->get_obj() ;if (--num_contacts < 1) {// if nocontacts left, erase the whole contacts listdelete *contact ;*contact =NULL ;}else {(*contact)->set_obj((BM_BASIC *) num_contacts) ;(*contact)->add_after(list) ;}/*  最後に、センタラインを形成する。方向と長さが正しいことを確かにする。  ｐ１とｐ２は面１に関して規定される点に注目されたい。  すなわち、ｐ１-＞ｐ２は面１の側のコンタクトに対する方向である。*/BM_LINE centerline(bendline_centerline_p1,bendline_centerline_p2) ;if (fabs(angle - PI) <= BM_ANGLE_TOLERANCE) { // bendline not being bent// face1plane is the bendline surfaceif (face1->get_idx() > face2->get_idx()) centerline.reverse_line() ;}else if (angle < PI) {if (face1->get_idx() <face2->get_idx()) centerline.reverse_line() ;}else { // angle is > PIif(face1->get_idx() > face2->get_idx()) centerline.reverse_line() ;}new_auto_bendline->set_center_line(centerline) ;// if we are building bendlines for the 3D-version of the part, // make sure 3D-version of the bendline is validated because most likely we // want to UNFOLD right away.if (using_3D_version) new_bendline->validate_3D_version() ;*bendline_created= new_bendline ;return 1 ;}/*  この関数の目的は、面からなる切断された要素を持つ部分であって、この部分が、これらの新しいベンドラインを付加すると、接続されるようになるように最小数のベンドラインを形成することにある。This function assumes that the part has thickness 0.The basic idea we usein this function is maximum spanning tree.We model the part by an undirected graph, where faces are the nodes of the graph andthere is an edge between two nodes iff these two faces are in contact (ie. are touching each other),the cost (or length) of the edge is the length of the longestcontact between these two faces (ie. the length of the longest possiblebendline between the two faces).In order to create bendlines we computea maximum spanning tree for this graph and create abendline for every edge of the graph that is in the maximum spanning tree.There are two problems however :- It could be that the part already contains some bendlines(ie. some faces are already  connected).- When we compute the maximum spanning tree, we can have two fringe-edges that have the   same length.In that case, we don’t want to break ties randomly, but instead choosean   edge that would minimize the diameter of the spanning tree (the maximum distance between  any two vertices of the tree).Algorithm :-----------We will process faces one-by-one, starting from the first faces of the part and proceedinguntil the last faces, and building the maximum spanning tree along the way as we go.For every pair of faces, such that at least one of the is not yet in the spanning tree,we keep the longest contact between them. When we expand the spanning tree, we choosethe contactbetween a face in the tree and a face not in the tree that is the longest contactbetween any face in the tree and a face outside. If there is atie, we choose an edge thatwould minimize the *//*  面（面１）を与えると、この構造はこの面と他の面の間のコンタクトについての情報を含む。  任意の２つの面に対して、これらの面の間にコンタクトが有るか否かを知る必要があり、もしイエスなら、何がその長さであるかを知る必要がある。このデータを処理する最も簡単な方法はそれを二次元配列として記憶することにより与えられる。しかし、これは多くのスペースを取り、その殆どは無駄に使われ、というのは、通常は、多くの面があるときは、それらの殆どはそれらの面の間で何らのコンタクトも持たないことによる。  代わりに、我々は全ての面に対してこの情報を構造のリストとして記憶することになる。我々は、２つの面の間のコンタクトの長さが０より大きいときにのみこの記録を（すなわち、構造）生成する。*/typedef struct CONTACT_INFO {// here we will keep track what is the length of the longest contact between any two faces// this is really a two-dimensional arraydouble length ;// here we keep a pointer to the other faceBM_FACE *facｅ２ ;// here we will keep the longest contact for any two faces// this is really a two-dimensional array stored as a linked list of lists.BM_LINKED_LIST_NODE *contact ;// a pointer to the next structure in alistCONTACT_INFO *next ;}  contact_info ;/*これは、このファイルにおいて多くの関数により用いられる非常に基本的な関数である。  それはコンタクトリストを削除する。*/static void delete_contact_info_list(contact_info *list){contact_info *c, *c_next ;BM_LINKED_LIST_NODE *clist, *next_clist ;BM_LINKED_LIST_NODE *line_in_list, *next_line_in_list ;for (c = list ; c ;c = c_next) {c_next = c->next ;if (c->contact) {// skip the header = num of contactsfor (clist = (c->contact)->next() ; clist ; clist = next_clist) {next_clist = clist->next() ;// delete the listfor (line_in_list =(BM_LINKED_LIST_NODE *) clist->get_obj() ; line_in_list ; line_in_list =next_line_in_list) {next_line_in_list = line_in_list->next() ;delete line_in_list ;}delete clist ;}// delete the headerdelete c->contact ;}delete c ;}}static void delete_contact_info_structure(contact_info *c){BM_LINKED_LIST_NODE *clist, *next_clist ;BM_LINKED_LIST_NODE *line_in_list, *next_line_in_list ;if (NULL == c) return ;if (c->contact) {// skip the headerfor (clist = (c->contact)->next() ; clist ; clist = next_clist) {next_clist = clist->next() ;// delete the listfor (line_in_list = (BM_LINKED_LIST_NODE *) clist->get_obj() ; line_in_list ; line_in_list = next_line_in_list) {next_line_in_list = line_in_list->next() ;delete line_in_list ;}delete clist ;}// delete the headerdelete c->contact ;}delete c ;}/*  この関数は２つの面の間で最良の（すなわち、最も長い）コンタクトを計算し、格納する。*/static int compute_the_longest_contact_between_faces(BM_FACE & face1 /* IN */, BM_FACE & face2 /* IN */,contact_info **computed_contact_list /* OUT */){// so far we have computed nothing*computed_contact_list = NULL ;BM_LINKED_LIST_NODE *contact_list ; // a list of all contacts between face1 and face2 we will computeif (! BM_compute_all_face_to_face_contacts(face1, face2, &contact_list)) return 0 ;double x = BM_keep_largest_contact_remove_the_rest(&contact_list) ;if (x < BM_PRECISION) return 1 ; // no contact between these two facescontact_info *c ;if (NULL == (c = new contact_info)) {// delete contact listBM_LINKED_LIST_NODE *clist, *next_clist ;BM_LINKED_LIST_NODE *line_in_list, *next_line_in_list ;for (clist = contact_list->next() ; clist ; clist = next_clist) {next_clist = clist->next() ;// delete the listfor (line_in_list = (BM_LINKED_LIST_NODE *) clist->get_obj() ; line_in_list ; line_in_list = next_line_in_list) {next_line_in_list = line_in_list->next() ;delete line_in_list ;}delete clist ;}delete contact_list ;return 0 ;}// initialize the structurec->contact = contact_list ;c->next = NULL ;c->face2 = &face2 ;c->length = x ;*computed_contact_list = c ;return 1 ;}/*  この関数は現在接続された要素に新しい面を付加する。  それはまた、この新しい面と、処理されていない他の全ての面の間の最も長いコンタクトを計算する。*/static int add_face_to_connected_component(BM_PART *part, BM_FACE *face2 /* this is the face we are adding to the connected component */, long *end_id /* an index of the last face in the connected component. this is where face2 is. */, contact_info **all_contacts /* all contact info between face2 andother outside faces will be here *//* we will compute it and construct this list in this function */,BM_FACE **idx_to_face_mapping){BM_FACE *current_face ;contact_info *last_clist = NULL, *cl ;// just in case face2 has no adjacent faces outside the connected componentall_contacts[*end_id] = NULL ;// in this loop we want to compute all contacts between face2and all other// faces not yet in any connected component.for (current_face = part->get_face_list() ; current_face ; current_face = (BM_FACE *) current_face->next()) {if (current_face->get_user_id() >= 0) continue ; // current_face is in some other connected component// compute the best contact between face2 and current_faceif (! compute_the_longest_contact_between_faces(*face2, *current_face, &cl)) return 0 ;if (NULL == cl) continue ; // there is no contact between these two facesif (NULL == last_clist) all_contacts[*end_id] = cl ;else last_clist->next = cl ;last_clist= cl ;}face2->set_user_id(*end_id) ;idx_to_face_mapping[*end_id] = face2;++(*end_id) ;return 1 ;}/*  これらの２つの関数は、ユーザがトポロジーグラフにおける２つの面の間の距離を設定し得ることを許容する。  dist btw  面は二次元配列の上部右半部である。*/static long get_face2face_dist(unsigned char *dist_btw_faces,long number_of_faces, long dist_array_size, longj, long i){long k ;// distance between face_i and face_i is zeroif (i ==j) return 0 ;// sort indecesif (j < i) { k = i ; i = j ; j = k ; }k = number_of_faces - i ;return dist_btw_faces[dist_array_size - ((k*(k-1)) >> 1) + (j - i) - 1] ;}static void set_face2face_dist(unsigned char *dist_btw_faces,long number_of_faces, long dist_array_size, long j, long i, unsigned char distance){long k ;// distance between face_i and face_i cannot be setif (i == j) return ;// sort indecesif (j < i) { k = i ; i = j; j = k ; }k = number_of_faces - i ;dist_btw_faces[dist_array_size - ((k*(k-1)) >> 1) + (j - i) - 1] = distance ;}/*  この関数は接続された要素における所定の面と他の面の間の最大距離を戻す。*/static long get_largest_distance_for_face(unsigned char *dist_btw_faces,long number_of_faces, longdist_array_size, long start_id, long end_id, long face_id){long j, k ;if (NULL == dist_btw_faces) return 0 ;long current_face_to_face_distance= 0 ;for (j = start_id ; j < end_id ; j++) {k = get_face2face_dist(dist_btw_faces,number_of_faces,dist_array_size,j,face_id) ;if (k > current_face_to_face_distance) current_face_to_face_distance = k ;}return current_face_to_face_distance ;}/*  これは主要なＡｕｔｏｂｅｎｄ関数である。その目的は部分に対するベンドラインを自動的に生成することにある。*/int BM_PART::auto_bend(void){long i, j, k ;BM_FACE *current_face ;BM_FORMING *current_forming ;BM_BENDLINE *current_bendline ;// at end of the function werelease memory. this code for releasing memory is shared// between thecases when this function fails, or succeeds.// therefore, before we getto that code, we have to know the return code.int ret_value ;// these are the two faces we will be creating a bendline for (ie. between these two faces).BM_FACE *face1, *face2 ;// here we keep a list of information about contacts between every face and other faces.// this is an array lists.contact_info **all_contacts = NULL ;// here we will keep track what face corresponds to each row in face_to_face_length[] and all_contacts[]arraysBM_FACE **idx_to_face_mapping = NULL ;// this (two-dimensional) array is used to store distances between faces in the TOPOLOGY GRAPH.// these distance values are used to break ties in the maximum spanning treealgorithm when// two edges have the same length. Note that the distancebetween (i,j) is the same as// the distance between (j,i). This means that the distance matrix is a symmetric matrix, and we// only need to store one half (upper right triangle) to save space.// we will use this method of breaking ties only when the number of faces is less than 256.// this has two advantages : 1) the distance between any two faces is alwaysless than 256,// and therefore we only need a char (8 bits) to store thedistance values, 2) since we only// need a char for a pair, the total this array can take is 32K bytes, which is not too much memory.unsigned char *dist_btw_faces = NULL ;// this will be the size of the distance array, given some number of faceslong dist_array_size ;// we will have to create a heap because some portion of the part can already be connected//and we need to make sure we don’t create any bendlines for that portion of the part.// we will use a heap to traverse that portion of the part.long body_priority = number_of_formings + number_of_faces + number_of_bendlines ;// Check if there are any bodies. If no, we are done.if (body_priority < 1) return 1 ;// this is the heap we will allocate. this is used when we add a face to the connected component// to add all other faces connected to it as well. the problem is that the part could already//contain some bendlines.DBM_HEAP *heap = NULL ;// this is the start-index(in face_to_face_length[] and all_contacts[]) arrays // of the currentconnected componentlong start_id = 0 ;// this is the end-index (in face_to_face_length[] and all_contacts[]) arrays // of the current connectedcomponentlong end_id = 0 ;// if TRUE, we are starting a new connected componentint starting_new_connected_component = 1 ;// allocate memory forlocal variablesif (NULL == (all_contacts = new contact_info*[number_of_faces])) goto failure ;if (NULL == (idx_to_face_mapping = new BM_FACE*[number_of_faces])) goto failure ;if (NULL == (heap = new DBM_HEAP(0,NULL,NULL,body_priority))) goto failure ;if (number_of_faces < 256) { // allocate memory for the face-face distance array only when // the number of faces is not too largedist_array_size = (number_of_faces*(number_of_faces- 1)) >> 1 ;if (NULL == (dist_btw_faces = new unsigned char[dist_array_size])) goto failure ;}++body_priority ; // just in case, we don’t wantthe priority to go to 0 later.// initialize arraysfor (i = 0 ; i < number_of_faces ; i++) {all_contacts[i] = NULL ;idx_to_face_mapping[i] = NULL ;}// initially mark all faces as not processedfor (i = 0, current_face= first_face ; current_face ; current_face = (BM_FACE *) current_face->next()) {current_face->this_body_already_processed = 0 ;// this will tell us whether this face has been already processed.// if yes, this id isthe index in face_to_face_length[] and all_contacts[] arrays.current_face->set_user_id(-1) ;}/*  先ず、面の現在接続された要素の最大スパンツリーを拡大することを試みる。*/// these two variables are used in tie-breakinglong best_face_to_face_distance, current_face_to_face_distance ;// thisis the length of the best contact so far (ie. the longest contact)double best_length ;// this is a pointer to the best contact_info structure found so farcontact_info *best_cntct ;expand_spanning_tree :// first, check if all faces have been processed// end_id is where we will put the next face we add to the connected componentif (end_id >= number_of_faces)goto done ;contact_info *cntct, *cntct_next, *cntct_prev ;best_length =-1.0 ;best_face_to_face_distance = 999999 ; // a really large number// in this loop we check all faces already in the connected component and try// to find a face that has the largest contact between itself and an adjacent face outside the// current connected component.for (i = start_id; i < end_id ; i++) {// in this loop we are checking for a largest contact between the current face// in the connected component and all of itsadjacent faces outside the connected component.cntct_prev = NULL ;for (cntct = all_contacts[i] ; cntct ; cntct = cntct_next) {cntct_next = cntct->next ;// check if this adjacent face is already processedif ((cntct->face2)->get_user_id() >= 0) {// this means that face2 has already been added to the connected component// and we don’t really need the contact info stored in this structure any more.// we will delete it.// this willsome time in the future and free up some space.delete_contact_info_structure(cntct) ;if (NULL == cntct_prev) all_contacts[i] = cntct_next ;elsecntct_prev->next = cntct_next ;continue ;}// ok, this adjacent face notprocessed. // check if it is better than the previously known best.// first check if there is a tie, and if we have allocated a face-face distance array// then use the face-to-face distances to break the tieif (fabs(cntct->length - best_length) <= distance_tolerance && dist_btw_faces) {// if tie-breaking is used, compute the largest distance for this face (ie. face1)current_face_to_face_distance = get_largest_distance_for_face(dist_btw_faces,number_of_faces, dist_array_size, start_id, end_id, i) ;//prefer the one with the smaller largest distanceif (current_face_to_face_distance < best_face_to_face_distance) {face1 = idx_to_face_mapping[i];face2 = cntct->face2 ;best_length = cntct->length ;best_cntct = cntct;best_face_to_face_distance = current_face_to_face_distance ;}}// take simply the one that is betterelse if (cntct->length > best_length) {face1= idx_to_face_mapping[i] ;face2 = cntct->face2 ;best_length = cntct->length ;best_cntct = cntct ;// if tie-breaking is used, compute the largest distance for this face (ie. face1)best_face_to_face_distance = current_face_to_face_distance = get_largest_distance_for_face(dist_btw_faces,number_of_faces, dist_array_size, start_id, end_id, i) ;}cntct_prev = cntct ;}}// at the end of this loop,// face1, face2, best_cntct should havecorrect values, if best_length > 0.0, // that means we can expand the tree./*  我々がスパンツリーを拡大出来るか否かをチェックする。  我々が接続要素を拡大することに戻るまでまでのこの点に対して、我々は単に面２を用いつつ��り、すなわち、我々は面１を必要としていない。  唯一の場合は、我々が新しいベンドラインを生成するときであるが、我々はコンタクトリストから面ｉｄを抽出することが出来る。*/if (best_length < distance_tolerance) {// looks like we cannot expand the spanning tree// none of the faces in the current connected component has any adjacent faces// outside the connectedcomponent.// most likely this connected component is finished and, sincethere must be still faces left,// there is more than one connected component.// // next we try to find the first face in the next connected component so that we// can continue and create all bendlines for this new conencted component.for (current_face = first_face ; current_face ; current_face = (BM_FACE *) current_face->next()) {if (current_face->get_user_id() < 0) break ;}if (NULL == current_face) goto done ; // we should never get here// first, we can delete all contact information about the current (now old) connected componentfor (i = start_id ; i < end_id ; i++){delete_contact_info_list(all_contacts[i]) ;all_contacts[i] = NULL ;}//here we will be starting a new connected componentstarting_new_connected_component = 1 ;start_id = end_id ;// we will skip the bendline creationnormally needed when adding a face to a connected componentface2 = current_face ;}else {// ok, we are in the middle of a conencted componentstarting_new_connected_component = 0 ;// create a bendline between face1 and face2// notice : we might have to create a simultaneous bendlong num_contacts = (long) (best_cntct->contact)->get_obj() ;BM_BEND_PROPERTY_SIMULTANEOUS *sim_bend = NULL ;if (num_contacts > 1) {sim_bend = new BM_BEND_PROPERTY_SIMULTANEOUS(this, num_contacts, NULL) ;if (NULL == sim_bend)goto failure ;}BM_BENDLINE *new_bendline ;for (long contacts_done = 0 ;contacts_done < num_contacts ; contacts_done++) {if (! BM_create_bendline(*this, &(best_cntct->contact),&new_bendline)) goto failure ;// note that this function will delete one contact for which a bendline was created as wellif (num_contacts > 1) {// add this bendline to the simultaneouspropertynew_bendline->add_property(sim_bend) ;}}}// store "1 + the current index of the last connected-component-face"j = end_id ;// we could add face2 to the connected component right away, but we could save some time by// first checking if face2 has any other stuff (outside this connected component) connected to it.// if yes, we will be adding that stuffto this connected component right away,// but in that case there is no need for us to compute contacts between face2 and that other// stuff in the first place.// Therefore, we will just remember that face2 should beadded, will process adjacent stuff first,// and then will actually add face2 (and some more stuff may-be) to the connected component.// // Note: we will actully put face2 in the heap, and when we remove it from theheap,// we will remember to add it to the connected component/*  ここで，我々は、この面（すなわち、面２）がそれに接続された他の任意の３Ｄ体を有するか否かをチェックする必要がある。  もし、イエスなら、我々は、面２に接続された全ての面を現在接続された要素に付加するために、これらの接続を追求する必要がある。*/heap->empty() ;if (! heap->insert(body_priority--, (long) face2)) goto failure ;face2->this_body_already_processed = 1 ;// check if face2 has a parent face or not. if not, set the id in local arrayequal to // face2’s own id. this way we know it has no parent face.// // IMPORTANT : normally user_id of every face is a pointer to its index in the contact-info array.// temporarily we will use this information tokeep track which of the faces already processed// is the parent-face (inthe topology graph) of every new face added to the connected component.// this information will be used later to compute distances in the facetopology graph.// the following loop (controlled by the heap) stores allfaces not yet in the connected// component, but connected to this face2.// later when the actualy adding of new faces to the conencted component is done,// we overwrite user_id with the correct value.if (! starting_new_connected_component) face2->set_user_id(face1->get_user_id()) ;elseface2->set_user_id(end_id) ;// in the following while loop we will use this_body_already_processed member variable to keep// track whether a varible is processed; not processed, but sitting in the heap; or unseen yet.// 0 - unseen body// 1 - body in the heap// 2 - body already finished//also, in this while loop we will be using the user_defined_id of every3D-body to keep// track of the parent face of every 3D-body we traverse.// this has two benefits : 1) we will remember the parent face of everyface and can compute// distances between faces later, and // 2) this waywhen faces are later added to the spanning tree, distance between someother // face and this face will not be computed, since it is not necessary.BM_3D_BODY *body ;BM_TOPOLOGY_RECORD *toplgy ;while (heap->get_size() > 0) {if (! heap->remove(&i,(long *) &body)) goto failure ;// a safetycheckif (NULL == body) continue ;// check if this body is already finishedif (body->this_body_already_processed > 1) continue ;// get body topologytoplgy = body->get_adj_list() ;if (NULL == toplgy) continue ;// check if the body is a face. if yes, memorize.if (body->is(BM_ENTITY_TYPE_FACE)) {face2 = (BM_FACE *) body ;// memorize to add this face to the connected component lateridx_to_face_mapping[j++] = face2 ;}body->this_body_already_processed = 2 ;// process all adjacent bodiesfor (current_face =(BM_FACE *) toplgy->get_first_face() ; current_face ; current_face = (BM_FACE *) toplgy->get_next_face()) {// make sure that we don’t processfaces twiceif (current_face->this_body_already_processed) continue ;if (! heap->insert(body_priority--,(long) current_face)) goto failure ;current_face->this_body_already_processed = 1 ;// make sure we memorize the parent face index in the local spanning tree arraycurrent_face->set_user_id(body->get_user_id()) ;}for (current_forming = (BM_FORMING *) toplgy->get_first_forming() ; current_forming ; current_forming = (BM_FORMING *)toplgy->get_next_forming()) {if (current_forming->this_body_already_processed) continue ;if (! heap->insert(body_priority--,(long) current_forming)) goto failure ;current_forming->this_body_already_processed = 1 ;//make sure we memorize the parent face index in the local spanning treearrayif (body->is(BM_ENTITY_TYPE_FACE)) current_forming->set_user_id(j-1) ;else current_forming->set_user_id(body->get_user_id()) ;}for (current_bendline = (BM_BENDLINE *) toplgy->get_first_bendline() ; current_bendline ; current_bendline = (BM_BENDLINE *) toplgy->get_next_bendline()) {if (current_bendline->this_body_already_processed) continue ;if (! heap->insert(body_priority--,(long) current_bendline)) goto failure ;current_bendline->this_body_already_processed = 1 ;// make sure we memorize the parent face index in the local spanning tree arrayif (body->is(BM_ENTITY_TYPE_FACE)) current_bendline->set_user_id(j-1) ;else current_bendline->set_user_id(body->get_user_id()) ;}}// finally we need to compute contacts between this face and all other faces, that we postponed// and add them to the connected component.long face1_id ;for (i = end_id ; i < j ; i++) {face2 = idx_to_face_mapping[i] ;// first, compute distances in the TOPOLOGY GRAPH between this face (ie. face2) // and all faces previouslyin the connected component.// we will use the parent face id in the local spanning tree array for that.face1_id = face2->get_user_id() ; // note: face1_id is the parent id of face2 (ie. there is a bendline between face1_id and face2 that we count).if (dist_btw_faces && face1_id != i) {// if equal -> face2 has no parents, // ie. a new connected component (must be start_id = end_id).// actually, it must be here true that face1_id < ifor (k = start_id ; k < end_id ; k++) {set_face2face_dist(dist_btw_faces, number_of_faces, dist_array_size, k, i, get_face2face_dist(dist_btw_faces,number_of_faces,dist_array_size,k,face1_id) + 1) ;}}// else ifequal, it must be that i == ’the end_id’  ｉｎ  ｔｈｅ  ｂｅｇｉｎｎｉｎｇ  ｏｆ  ｔｈｉｓ  ｆｏｒ−ｌｏｏｐ．／／  ｎｏｔｅ  ｔｈａｔ  ｔｈｅ  ｎｅｘｔ  ｆｕｎｃｔｉｏｎ  （ａｄｄ＿ｆａｃｅ＿ｔｏ＿ｃｏｎｎｅｃｔｅｄ＿ｃｏｍｐｏｎｅｎｔ（．．．））  ｗｉｌｌ  ｉｎｃｒｅｍｅｎｔ  ｅｎｄ＿ｉｄ．ｉｆ  （！  ａｄｄ＿ｆａｃｅ＿ｔｏ＿ｃｏｎｎｅｃｔｅｄ＿ｃｏｍｐｏｎｅｎｔ（ｔｈｉｓ，  ｆａｃｅ２，  ＆ｅｎｄ＿ｉｄ，  ａｌｌ＿ｃｏｎｔａｃｔｓ，  ｉｄｘ＿ｔｏ＿ｆａｃｅ＿ｍａｐｐｉｎｇ））  ｇｏｔｏ  ｆａｉｌｕｒｅ  ；｝／／  ｏｋ，  ｔｈｅ  ｃｕｒｒｅｎｔ  ｃｏｎｎｅｃｔｅｄ  ｃｏｍｐｏｎｅｎｔ  ｈａｓ  ｎｏ  ｃｏｎｎｅｃｔｉｏｎｓ  ｔｏ  ｔｈｅ  ｏｕｔｓｉｄｅ．／／  ｔｒｙｔｏ  ｅｘｐａｎｄ  ｔｈｅ  ｓｐａｎｎｉｎｇ  ｔｒｅｅ．ｇｏｔｏ  ｅｘｐａｎｄ＿ｓｐａｎｎｉｎｇ＿ｔｒｅｅ  ；ｄｏｎｅ  ：ｒｅｔ＿ｖａｌｕｅ  ＝１  ；ｇｏｔｏ  ｒｅｌｅａｓｅ＿ｍｅｍｏｒｙ＿ａｎｄ＿ｒｅｔｕｒｎ  ；ｆａｉｌｕｒｅ  ：ｒｅｔ＿ｖａｌｕｅ  ＝  ０  ；ｒｅｌｅａｓｅ＿ｍｅｍｏｒｙ＿ａｎｄ＿ｒｅｔｕｒｎ  ：／／  ｆｒｅｅ  ｍｅｍｏｒｙ  ｉｆ  ｎｅｃｅｓｓａｒｙｆｏｒ  （ｉ  ＝  ０  ；  ｉ  ＜  ｎｕｍｂｅｒ＿ｏｆ＿ｆａｃｅｓ  ；  ｉ＋＋）  ｛ｄｅｌｅｔｅ＿ｃｏｎｔａｃｔ＿ｉｎｆｏ＿ｌｉｓｔ（ａｌｌ＿ｃｏｎｔａｃｔｓ［ｉ］）  ；｝ｉｆ  （ａｌｌ＿ｃｏｎｔａｃｔｓ）ｄｅｌｅｔｅ  ［］  ａｌｌ＿ｃｏｎｔａｃｔｓ  ；ｉｆ  （ｉｄｘ＿ｔｏ＿ｆａｃｅ＿ｍａｐｐｉｎｇ）  ｄｅｌｅｔｅ  ［］  ｉｄｘ＿ｔｏ＿ｆａｃｅ＿ｍａｐｐｉｎｇ  ；ｉｆ  （ｈｅａｐ）  ｄｅｌｅｔｅ  ｈｅａｐ  ；ｉｆ  （ｄｉｓｔ＿ｂｔｗ＿ｆａｃｅｓ）  ｄｅｌｅｔｅ  ［］  ｄｉｓｔ＿ｂｔｗ＿ｆａｃｅｓ  ；ｒｅｔｕｒｎ  ｒｅｔ＿ｖａｌｕｅ  ；｝
付録Ｄ
2dクリーアップ関数の例
#include <stdio.h>#include <stdlib.h>   #include <math.h>#include <memory.h>#include <string.h>/*  Function名称：1 control levelTestFindBoundaryTestFindDrawingSheetControlTestFindViewsControlTestFindBoundaryControlTestFindArrowControlTestFindOneSideOpenControlTestFindOneSideOpen2ControlTestFindCenterLineControlTestFindOneSideOpenConnectControlTestFindSameColorControlTestFindSelectSingleControlTestUnselectSingleControlTestClearControlTestClearKeepFlagsControlTestDeleteControlTestUndoControlTestUndoPreControlTestDeleteViewsControlTestSetUndoFlagViewsControl        TestBackColorControl2 applicate levelF2dCleanUpFindDrawingSheetF2dCleanUpFindViewsF2dCleanUpFindSameColorEntityF2dCleanUpFindCenterLineEntityF2dCleanUpFindOnesideOpenConnectEntityF2dCleanUpFindOneSideOpenEntity2F2dCleanUpClearDrawingEntityF2dCleanUpDeleteDrawingEntityF2dCleanUpDeleteViewsF2dCleanUpUndoF2dCleanUpUndoPreF2dCleanUpPickUpAllOneSideOpenEntityF2dCleanUpPickUpAllArcEntityF2dCleanUpFindLongestEntityF2dCleanUpFindGroupF2dCleanUpCheckEntityExistF2dCleanUpFindViewsRelationF2dCleanUpFindRelativeViewsF2dCleanUpFindOutSideLoopF2dCleanUpFindInSideEntityF2dCleanUpFindOneSideOpenEntityF2dCleanUpFindGroupMinXF2dCleanUpFindOutNextEntityF2dCleanUpFindOnesideOpenConnectEntityNextF2dCleanUpFindArrowF2dCleanUpFindArrowOneSideOpenEntityF2dCleanUpFindArrowEndEntityF2dCleanUpCheckStartEndEntityF2dCleanUpComputeCenterLineAngleF2dCleanUpFindArrowCenterEntityF2dCleanUpChangeArrowVertexFlagF2dCleanUpArcAngleF2dCleanUpLineAngleF2dCleanUpLineLengthF2dCleanUpChangeColorF2dCleanUpChangeDrawingColorF2dCleanUpChangeChildrenFlagF2dCleanUpChangeDrawingFlagF2dCleanUpClearDrawingKeepFlagsF2dVectorF2dVectorUnitF2dDistancePointLine*/#ifdef VELLUM#include "ck_cdlc.h"// VCI_VLM.DLL include files#include "system.h"// CadKey emulation files#include "vlm_ck.h"#endif#ifdef CKWIN#include "ck_cdlc.h"#include "ck_cde.h"#include <ckcdll.h>#include <ck_attr.h>#define ck_setattr2ck_setattr#endif#ifdef AUTOCAD#include <ACAD_VCI.H>#endif// 2d3d files#include "view3D.h"//#include "Proto.h"  // includes prototypes of all functions.                                     #define VLM_ID_2DTO3D32#define Regular    0#define ThreeViews 1//#define SECURITY// Some definitions//#undef DEBUG//// Following is the definition of the global variables//#ifdefCKWINint TopViewNum, IsometricViewNum;// These  variables are used onlywith CADKEY when changing to TopView or Isometric view.#endif// by Ji Feb.14,1996double F2dCleanUpTolerance = 0.01;//undo flag ( set a No. for views )extern int    F2dCleanUpExcutedNo = 0;extern int    WorkLevel, TrimLevel, VW3DLevel;                         // Three layers are useD: WorkLevel is used to highlight views and display temporary drawings.//                    TrimLevel is used to store the trimmed drawing.//                      VW3DLevel is used to store the projected 3D drawing.// these are the four drawings used.extern struct drawing input_drawing, projected_drawing, trim_drawing, final_drawing;  // Three drawing structures are constructed://                        InputDrawing is constructed from the input entities //                                     taken from from all the layers that are turned on.//  TrimmedDrawing is constructed from the trimmed entities. Once the//                                   Trimmed Drawing is constructed, the Input Drawing is not used.//                        ProjectedDrawing is constructed from the entities projected in a single flange.//            If ’DoneProjection’ is selected, then these entities are saved on VW3DLevel.//                        If ’UndoProjection’ is selected, these entities are discarded.extern struct planar_flange *AllFlanges;// this is a pointer to the list of flangesextern char Messages[MaxMessages][80];// This array stores the messages read from the message file.extern int message_flag;// This variable is assigned to ’1’ if the messages were read successfully from the message file.// Otherwise, it isset to ’0’.extern int number_of_views;// This vairbale stores the number of disconnected components discovered in the *input* drawing.externint number_of_entities;// This variable stores the number of entities loaded for the current drawing.extern int number_trimmed_entities;// Thisvariable stores the number of entities loaded for the trimmed drawing.extern int n_edges;// This variable stores the number of connecting edgesbetween the trimmed entities.extern double MatchTolerance, ConnectivityTolerance;// ConnectivityTolerance is used to determine whether two entities are close enough to be considered connected.// Matching Tolerance isused to determine whether two entities on different views are matching.extern double ArrowHeadAngle, ArrowHeadLength;// These variuables definethe structure of an arrow for the 2D clean up funciton.extern double view_boundaries[MaxNumberOfViews+1][4];// This array is used to store thebounding box of each connected component of the input drawing.//      once the views are detected, several components might be mapped to a single view.extern int    type_of_view[MaxNumberOfViews+1];// This array mapsevery view to its type, namely to one of Top, Left, Right, Front, Backview.// Its content is valid only after ’DoneViews’ was called.//int view_rotation_flag[MaxNumberOfViews+1];// This array is used for markingrotated views. // If the i’th element is ’1’ then the view is rotated.//extern static char original_lvmask[32] ;// At the beginning we save the (on,off) status of all the layers.//extern static char twoDmask[32] ;//extern static char threeDmask[32] ;// The masks used to display the 2Dand 3D models.//extern static int original_worklevel ;// Specifies theoriginal work level of the user when fold is started// static int original_setup_available = 0 ; // true iff original (layer) setup is available, ie. can be restoredextern int dialog_open_flag = 0;// This variable isa flag which specifies whether some dialog boxes were opened.extern intAtrimLineTypeSwitch, AtrimColorSwitch, AtrimWidthSwitch, AtrimCenterLineSwitch;// these switches are used to specify in which cases AutoTrim will trim lines.//struct node *F2dCleanUpInputEntity(char *, struct drawing *);//static int select_flange(struct resbuf *rb);typedefstruct Vector{doublex,y,z;};extern double BBminX,BBmaxX,BBminY,BBmaxY,BBminZ,BBmaxZ;/*関数： 名称： TestFindBoundaryDescription: It is a manual function. When user selected a boundary’s entity of a view, the function would findall of the connected entities for the view.戻り値：< 0: Error= 0: No proccess> 0: Completed successfully; the Number is the counter of  found entities.パラメータ：副関数：int F2dCleanUpFindArrowlook for arrow type entityint F2dCleanUpFindArrowEndEntityfind arrow end lineint F2dCleanUpFindArrowCenterEntityfind arrow center lineint F2dCleanUpFindArrowOneSideOpenEntityfind one side open entity for arrow typeint F2dCleanUpComputeCenterLineAnglecompute center line angleint F2dCleanUpCheckStartEndEntitycheck start and end entitiesint F2dCleanUpFindOutSideLooplook for out sideloop entitiesint F2dCleanUpFindOutNextEntitylook for connected entity with out side loop entitiesstruct node *F2dCleanUpFindGroupMinXlook for minimum X-value for a entities groupstruct node_list *F2dCleanUpFindGrouplook for a group entities connected with input entitystruct node *F2dCleanUpInputEntity ( old function )look for a selected entity on screenintF2dCleanUpLineAnglecompute a line type entity’s angle int F2dCleanUpArcAnglecompute a arc type entity’s angle.int F2dCleanUpChangeChildrenFlagchange entity’s children flagsint F2dCleanUpChangeArrowVertexFlagchangearrow top vertex’s flags and set arrow center line coordinatesint F2dCleanUpChangeColorchange entity’s colorint F2dCleanUpFindOneSideOpenEntitylook for one side open entities and they are vertical with arrow typeentities double F2dCleanUpLineLengthcompute line type entity’s length=================================================================*/intTestFindBoundary(){//external functionsint F2dCleanUpFindArrow();int F2dCleanUpChangeColor();int F2dCleanUpFindOneSideOpenEntity();int F2dCleanUpFindOutSideLoop();int F2dCleanUpChangeDrawingColor();struct node *F2dCleanUpInputEntity();struct node *F2dCleanUpFindGroupMinX();struct node_list *F2dCleanUpFindGroup();//entities counter and flagsint count = 0,assistant_line_flag = 0;//link list and temp liststruct node_list*Entities_change_color_list1; //selected entity and temp entitiesstruct node  *entity,*MinXvalueEntity;//Begin//----------------------------------//Step_1://check the number of entites//  get count of all entities// if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;for( ;; ){//---------------------------------//Step_2:select one entityentity= F2dCleanUpInputEntity( "Select a Boundary Entity for a view",&trim_drawing);if ( entity == 0 )return0;if ( entity->flags != 0 )continue;//---------------------------------//Step_3: find a connected entities groupEntities_change_color_list1 = F2dCleanUpFindGroup( entity, &count );if ( Entities_change_color_list1 == 0 )return0;//---------------------------------//Step_4: find arrow lineF2dCleanUpFindArrow( Entities_change_color_list1 );//---------------------------------//Step_5:find one side open entitiesassistant_line_flag = F2dCleanUpFindOneSideOpenEntity( Entities_change_color_list1 );//---------------------------------//Step_6:find outside loop entities without assistant entities//check a flag for outsideloop processif ( count < 1 )continue;MinXvalueEntity = F2dCleanUpFindGroupMinX(Entities_change_color_list1);if ( MinXvalueEntity == 0 )continue;//---------------------------------//Step_7://find outside loop entitiesF2dCleanUpFindOutSideLoop( MinXvalueEntity );//---------------------------------//Step_X://change color to Magenta for a selected boundary    //turn off input levels    ck_levels(CK_OFF,1,255);#ifdef CKWINF2dCleanUpChangeColor(Entities_change_color_list1);#endif#ifdef VELLUMF2dCleanUpChangeDrawingColor(&trim_drawing);#endif//clear a flag for outside loop processassistant_line_flag = 0;// turn ＯN the level used to store the trimmed entities.    ck_levels(CK_ON,TrimLevel, TrimLevel);#ifdef CKWINif (*SwitchRedraw == 1)ck_redraw( CK_PRIME_VP );#endif}return count;}/*=================================================================関数： 名称： F2dCleanUpFindGroup記述： look for a group entities connected with input entity 戻り値：= 0: Completed successfully;パラメータ：入力： Entity: a entity出力：NodeList: a node list connected with input entity =================================================================*/struct node_list *F2dCleanUpFindGroup(struct node *Entity, int *Cnt ){//entities counter and flagsint count = 0;//link list and temp liststruct node_list*EntitiesList1,*Out_temp_list,*temp_list, *temp_list1,*open_temp_list, *open_list; //selected entity and temp entitiesstruct node *Next_entity;//initializeEntitiesList1 =( struct node_list * ) calloc ( 1, sizeof ( struct node_list ));open_list =( struct node_list * ) calloc ( 1, sizeof ( struct node_list ));//set a flag for the boundary entitycount = 0;//set pointer to first entityopen_list->car = Entity;//set a open flagto the nodeopen_list->car->flags = 1;//set link addressopen_list->cdr = NULL;//set the pointer to output node listEntitiesList1->car = open_list->car;EntitiesList1->cdr = open_list->cdr;//---------------------------------//Step_3://find connected entitiesfor( temp_list = open_list;      ( temp_list     //&&(temp_list->cdr != 0)      );    ) {if ( temp_list->car == NULL )break;//get a pointer from open listNext_entity = temp_list->car;//set a closed flag to the nodeNext_entity->flags = 2;//close the node ( delete the node from open list )open_list = open_list->cdr;//count the number of entitiescount++;// look for first connected entity whose flags=0.for (temp_list1=Next_entity->connected_nodes; //     temp_list1 && temp_list1->car->flags==1;      ( temp_list1!=0 &&        temp_list1-!gt#car!=0);       temp_list1=temp_list1->cdr){    if ( temp_list1->car == NULL )break; // if found an unmarked connected entityif (temp_list1 && temp_list1->car->flags==0&& Entity->line_type == temp_list1->car->line_type&& Entity->color == temp_list1->car->color&& Entity->is_thickness == temp_list1->car->is_thickness   ) {// allocate memory for open list elementopen_temp_list = ( struct node_list * ) calloc ( 1, sizeof ( struct node_list));// allocate memory for output node list elementOut_temp_list = ( struct node_list * ) calloc ( 1, sizeof ( struct node_list ));// add this entity to the open listopen_temp_list->car = temp_list1->car;// add thisentity to the output node list Out_temp_list->car = temp_list1->car;//set a open flagto the nodeopen_temp_list->car->flags = 1; // connect to the open listopen_temp_list->cdr = open_list;// move the pointer of open list to the topopen_list = open_temp_list;// connect to the output node listOut_temp_list->cdr = EntitiesList1;// move the pointer of output nodelist to the topEntitiesList1 = Out_temp_list;}}// assign value to the loop variabletemp_list = open_list;}*Cnt = count;return EntitiesList1; }/*=================================================================  関数：  名称：      F2dCleanUpArcAngle  記述：アーク形エンティティの角度を計算する。  戻り値：RotateVertexFlag:方向フラグ                    =1:vertex1は回転ポイントである。                    =2:vertex2は回転ポイントである。  パラメータ：          入力：              1 OriginVertex:回転頂点              2 Entity:アーク形エンティティ          出力：    1 EntityAngle:方向角度（ラジアン）              2 EntityAngleAnother:  他のサイド方向角度================================================================*/int F2dCleanUpArcAngle(//inputstructplanar_vertex *OriginVertex,structnode *Entity,//outputdouble*EntityAngle,double*EntityAngleAnother){//return value intRotateVertexFlag=0;//length and angledoubleTolerance = 0.0;//set toleranceTolerance = F2dCleanUpTolerance;//select connected side of entityif ( Entity->vertex1 == OriginVertex ){//get arc start-angle//( direction : from circle-center to start-point )RotateVertexFlag= 1;*EntityAngle = ( Entity->AngBegin ) * pi / 180.0;//change angleto oppsite direction//( direction : from start-point to circle-center )*EntityAngle = *EntityAngle + pi;//check angle if ( *EntityAngle >(2.0*pi)) *EntityAngle = *EntityAngle - 2.0*pi;if ( fabs(*EntityAngle-2.0*pi) <Tolerance ) *EntityAngle = 0.0;//compute tangentline angle for the arcend-angle//( direction : from start-point to end-point )*EntityAngle = *EntityAngle + 1.5 * pi;//check angle if ( *EntityAngle >(2.0*pi)) *EntityAngle = *EntityAngle - 2.0*pi;if ( fabs(*EntityAngle-2.0*pi) < Tolerance ) *EntityAngle = 0.0;//get another side data//get arc start-angle//( direction : from circle-center to end-point )*EntityAngleAnother = ( Entity->AngEnd ) * pi / 180.0;//change angle to oppsite direction//( direction : from end-point to circle-center )*EntityAngleAnother = *EntityAngleAnother + pi;//check angle if ( *EntityAngleAnother > 2.0*pi )*EntityAngleAnother = *EntityAngleAnother - 2.0 * pi;elseif ( fabs(*EntityAngleAnother-2.0*pi) < Tolerance ) *EntityAngleAnother = 0.0;//compute tangentline angle for the arc end-angle//( direction : from end-point to start-point )*EntityAngleAnother = *EntityAngleAnother + 0.5 * pi;//check angleif ( *EntityAngleAnother > 2.0*pi )*EntityAngleAnother = *EntityAngleAnother - 2.0 * pi;else if ( fabs(*EntityAngleAnother-2.0*pi) < Tolerance )*EntityAngleAnother = 0.0;}else{//get arc end-angle//( direction : fromcircle-center to end-point )RotateVertexFlag= 2;*EntityAngle= ( Entity->AngEnd ) * pi / 180.0;//change angle to oppsite direction//( direction: from end-point to circle-center )*EntityAngle = *EntityAngle + pi;if (*EntityAngle > 2.0*pi ) *EntityAngle = *EntityAngle - 2.0*pi;if ( fabs(*EntityAngle - 2.0*pi) < Tolerance )*EntityAngle = 0.0;//compute tangentline angle for the arc end-angle//( direction : from end-point to start-point )*EntityAngle = *EntityAngle + 0.5 * pi;if ( *EntityAngle > 2.0*pi) *EntityAngle = *EntityAngle - 2.0*pi;if ( fabs(*EntityAngle - 2.0*pi)< Tolerance )*EntityAngle = 0.0;//get another side data//get arc start-angle//( direction : from circle-center to start-point )*EntityAngleAnother = ( Entity->AngBegin ) * pi / 180.0;//change angle to oppsite direction//( direction : from start-point to circle-center )*EntityAngleAnother = *EntityAngleAnother + pi;if ( *EntityAngleAnother > 2.0*pi )*EntityAngleAnother = *EntityAngleAnother - 2.0 * pi;if ( fabs(*EntityAngleAnother - 2.0*pi ) < Tolerance )*EntityAngleAnother = 0.0;//compute tangentline angle for the arc start-angle//( direction : from start-point to end-point )*EntityAngleAnother = *EntityAngleAnother + 1.5 * pi;if ( *EntityAngleAnother > 2.0*pi )*EntityAngleAnother = *EntityAngleAnother - 2.0 *pi;if ( fabs(*EntityAngleAnother - 2.0*pi ) < Tolerance )*EntityAngleAnother = 0.0;}//the end of this functionreturn RotateVertexFlag;}/*=================================================================関数： 名称：F2dCleanUpLineAngle記述： It is a function for control how to compute aline typeentity’s angle. 戻り値：RotateVertexFlag: direction flag=1: vertex1 is rotate point=2: vertex2 is rotate pointパラメータ：入力： 1 OriginVertex: rotationary vertex2 Entity: line type entity 出力：1 EntityAngle: direction angle ( radian )2 EntityAngleAnother: another side direction angle================================================================*/int F2dCleanUpLineAngle(//inputstructplanar_vertex *OriginVertex,structnode *Entity,//outputdouble*EntityAngle,double*EntityAngleAnother){//return value intRotateVertexFlag=0;//selected entity and temp entitiesstruct planar_vertex*VertexTemp,*VertexAnotherTemp;//length and angledoublediff_x = 0.0,diff_y = 0.0,Tolerance = 0.0;//set toleranceTolerance = F2dCleanUpTolerance;//select connected side of entityif ( Entity->vertex1== OriginVertex ){//get vertex1->vertex2 RotateVertexFlag= 1;VertexTemp=Entity->vertex1;VertexAnotherTemp= Entity->vertex2;}else{  //get vertex2->vertex1 RotateVertexFlag= 2;VertexTemp = Entity->vertex2;VertexAnotherTemp= Entity->vertex1;}//compute angleif ( fabs( VertexTemp->X - VertexAnotherTemp->X ) < Tolerance ){//angle = 0.5 * piif ( VertexTemp->Y < VertexAnotherTemp->Y )*EntityAngle = 0.5 * pi;//angle = 1.5 * pielse*EntityAngle = 1.5 * pi;}else{  //-pi< angle < pidiff_y = VertexAnotherTemp->Y- VertexTemp->Y;if ( fabs( diff_y ) > Tolerance ){diff_x = VertexAnotherTemp->X - VertexTemp->X;   *EntityAngle = atan2( diff_y, diff_x );//-pi< angle < 0.0if ( *EntityAngle < 0.0 ) *EntityAngle = *EntityAngle + 2.0*pi; }else{  //angle = 0.0or piif ( VertexAnotherTemp->X > VertexTemp->X )*EntityAngle = 0.0;else*EntityAngle = pi;}}if ( fabs(*EntityAngle - 2.0*pi) < Tolerance ) *EntityAngle = 0.0;//get another side angle*EntityAngleAnother = *EntityAngle + pi;//  check angleif ( *EntityAngleAnother> ( 2.0 * pi ) ){*EntityAngleAnother = *EntityAngleAnother - 2.0 * pi;}if ( fabs(*EntityAngleAnother - 2.0*pi) < Tolerance ) {*EntityAngleAnother = 0.0;}//the end of this functionreturn RotateVertexFlag;}/*=================================================================  関数：  名称：    F2dCleanUpChangeColor  記述：    エンティティの色を変更する関数。戻り値：          =0:成功裏に完了  パラメータ：            入力：        Entities_change_color_list ：変更された色であるノードリスト=================================================================*/int F2dCleanUpChangeColor(struct node_list *Entities_change_color_list){//link list and temp liststruct node_list*Color_temp_list;//selected entity and temp entitiesstruct node  *Next_entity;//entity’s specifitysCK_ENTATTattr;//specificity of entitiesint CountPrompt = 0;charmessage[64];#ifdef VELLUMCountPrompt++;sprintf( message,"Start Change Color Entity %d", CountPrompt );ck_prompt( message );  #endif#ifdef VELLUM    // clear views highlighting    ck_erase_level("VW_2D");//    ck_erase_level("VW_TRIM");#endif//check all of entities on the listfor( Color_temp_list=Entities_change_color_list;  Color_temp_list;  Color_temp_list = Color_temp_list->cdr){if ( Color_temp_list->car == NULL )break;Next_entity = Color_temp_list->car;switch ( Next_entity->flags ){case 1:attr.color = CK_GREEN;ck_setattr( Next_entity->id, CK_COLOR, NULL, &attr );break;case 3:attr.color =CK_GRAY;ck_setattr( Next_entity->id, CK_COLOR, NULL, &attr );break;case4:attr.color = CK_MAGENTA;ck_setattr( Next_entity->id, CK_COLOR, NULL, &attr );break;}}#ifdef VELLUMCountPrompt++;sprintf( message,"Finished change color Entity %d", CountPrompt );ck_prompt( message );  #endifreturn0;}/*=================================================================関数：  名称：      F2dCleanUpChangeDrawingColor  記述：      エンティティの色を変更する関数。  復帰値：      ＝０：成功裏に完了；  パラメータ：入力：              1 In drawing:図中で１：変更された色である図=================================================================*/intF2dCleanUpChangeDrawingColor(struct drawing *In_drawing){//extern functionsvoid draw_entity();//selected entity and temp entitiesstruct node *entity;int CountPrompt = 0;charmessage[64];//entity’s specifitysCK_ENTATTattr;//specificity of entities#ifdef VELLUM    // clear views highlighting    ck_erase_level("VW_2D");//    ck_erase_level("VW_TRIM");CountPrompt++;sprintf( message,"Start Change Color Sheet Entity %d", CountPrompt);ck_prompt( message );  #endif//check all of entities on the listfor( entity=In_drawing->objects;  entity;  entity = entity->next){switch ( entity->flags ){#ifdef VELLUMcase 0:draw_entity( entity, entity->color );break;case 1:draw_entity( entity, CK_GREEN );break;case 2:draw_entity( entity, entity->color );break;case 3:draw_entity( entity, CK_BLUE );break;case 4: draw_entity( entity, CK_MAGENTA );break;case 5:draw_entity( entity, entity->color );break;case 6: draw_entity( entity, CK_RED );break;case 7:draw_entity( entity, CK_YELLOW );break;case 8:draw_entity( entity, entity->color );break;case 9:draw_entity( entity, entity->color );break;case 10:draw_entity( entity, CK_CYAN );break;case 11:draw_entity( entity,entity->color );break; #endif #ifdef CKWINcase 1:attr.color = CK_L_GREEN;ck_setattr( entity->id, CK_COLOR, NULL, &attr );break;case 3:attr.color = CK_L_GRAY;ck_setattr( entity->id, CK_COLOR, NULL, &attr );break;case4:attr.color = CK_MAGENTA;ck_setattr( entity->id, CK_COLOR, NULL, &attr);break;case 6:attr.color = CK_L_RED;ck_setattr( entity->id, CK_COLOR,NULL, &attr );break;case 7:attr.color = CK_YELLOW;ck_setattr( entity->id, CK_COLOR, NULL, &attr );break;case 10:attr.color = CK_L_CYAN;ck_setattr( entity->id, CK_COLOR, NULL, &attr );break; #endif} if ( entity->next== NULL ) break;}#ifdef VELLUMCountPrompt++;sprintf( message,"Finished change color Sheet Entity %d", CountPrompt );ck_prompt( message );  #endifreturn 0;}/*=================================================================  関数：  名称：        F2dCleanUpUndoPre  記述：      取消関数のためのデータフラグを準備すること。  復帰値：      ＝０：成功裏に完了；パラメータ：          入力：            1 In drawing：  変更ステータスである図。=================================================================*/int F2dCleanUpUndoPre(struct drawing *In_drawing){//selected entity and temp entitiesstruct node *entity;//set flagF2dCleanUpExcutedNo = 2;//check all of entities on the listfor( entity=In_drawing->objects;  entity; entity = entity->next){entity->status = entity->flags;if ( entity->next == NULL )break;}return 0;}/*=================================================================関数： 名称： F2dCleanUpUndo記述： To undo. 戻り値：= 0: Completed successfully;パラメータ：入力： 1 In_drawing: drawing that will be undoed status=================================================================*/int F2dCleanUpUndo(struct drawing *In_drawing){//selected entity and temp entitiesstruct node *entity;//flagint NoChangeFlag = 0;                                                                //checkflagif ( F2dCleanUpExcutedNo == 0 )return NoChangeFlag;//check all of entities on the listfor( entity=In_drawing->objects;  entity; entity = entity->next){if ( entity->status != entity->flags ){NoChangeFlag = 1;entity->flags = entity->status;}if ( entity->next == NULL )break;} //check views flagif ( F2dCleanUpExcutedNo == 1 )In_drawing->views = NULL;//resetflag for viewsF2dCleanUpExcutedNo = 0;return NoChangeFlag;}/*=================================================================  関数：  名称：    F2dCleanUpChangeDrawingFlag  記述：      エンティティのフラグを変更する関数。  復帰値：      ＝0:成功裏に完了；  パラメータ：          入力：            1 In drawing:  変更された色である図=================================================================*/int F2dCleanUpChangeDrawingFlag(struct drawing *In_drawing){//selected entity and temp entitiesstruct node *entity;int CountPrompt = 0;charmessage[64];#ifdef VELLUMCountPrompt++;sprintf( message,"Start Flag Sheet Entity %d", CountPrompt );ck_prompt( message );  #endif//check all of entities on the listfor( entity=In_drawing->objects;  entity;  entity = entity->next){if ( entity->flags== 4 )  entity->flags = 3;#ifdef VELLUM//CountPrompt++;//sprintf( message,"Flag Sheet Entity %d", CountPrompt );//ck_prompt( message );  #endifif ( entity->next == NULL )break;}#ifdef VELLUMCountPrompt++;sprintf( message,"Finished Flag Sheet Entity %d", CountPrompt );ck_prompt( message );  #endifreturn 0;}/*=================================================================  関数：  名称：      F2dCleanUpFindSameColorEntity  記述：    同じ色のエンティティを見出す。  復帰値：        =0:  成功裏に完了；  パラメータ：          入力：            1 In entity:  エンティティ          2 In drawing:  変更された色である図================================================================*/int F2dCleanUpFindSameColorEntity(struct node *In_entity,struct drawing *In_drawing){//selected entity and temp entitiesstruct node *entity;int CountPrompt = 0;charmessage[64];#ifdef VELLUMCountPrompt++;sprintf( message,"Start Find same color Entity%d", CountPrompt );ck_prompt( message );  #endif//check all of entitieson the listfor( entity=In_drawing->objects;  entity;  entity = entity->next){if ( entity->color == In_entity->color && entity->flags == 0) entity->flags = 3;if ( entity->next == NULL )break;}#ifdef VELLUMCountPrompt++;sprintf( message,"Finished find same color Entity %d", CountPrompt );ck_prompt( message );  #endifreturn 0;}/*=================================================================  関数：  名称：    F2dCleanUpClearDrawingEntity  記述：    それは復帰エンティティの色である。  復帰値：＝０：成功裏に完了；  パラメータ：        入力：          1 In drawing：  変更された色である図==============================================================*/int F2dCleanUpClearDrawingEntity(struct drawing *In_drawing){//selected entity and temp entitiesstruct node *entity;//entity’sspecifitysCK_ENTATTattr;//specificity of entitiesint CountPrompt = 0;charmessage[64];#ifdef VELLUM    // clear views highlighting    ck_erase_level("VW_2D");//    ck_erase_level("VW_TRIM");//CountPrompt++;//sprintf(message,"Start Clear Entity %d", CountPrompt );//ck_prompt( message );#endif//check all of entities on the listfor( entity=In_drawing->objects;  entity;  entity = entity->next){ if ( entity == NULL )break;switch (entity->flags ){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9:case 10:entity->flags = 0;draw_entity( entity, entity->color );//attr.color = entity->color;//ck_setattr( entity->id, CK_COLOR, NULL, &attr );default:break;}}#ifdef VELLUM//CountPrompt++;//sprintf( message,"Finished clear Entity %d", CountPrompt );//ck_prompt( message );  #endif//clear views connectedIn_drawing->views = NULL;return 0;}                                     /*=================================================================  関数：  名称：F2dCleanUpClearDrawingKeepFlags  記述：    エンティティの色を復帰させるが、フラグは保��する。復帰値：      =0:成功裏に完了；  パラメータ：          入力：  1 In drawing:変更された色である図=================================================================*/int F2dCleanUpClearDrawingKeepFlags(structdrawing *In_drawing){//selected entity and temp entitiesstruct node *entity;//entity’s specifitysCK_ENTATTattr;//specificity of entitiesint CountPrompt = 0;charmessage[64];#ifdef VELLUM    // clear views highlighting    ck_erase_level("VW_2D");#endif//check all of entities on the listfor( entity=In_drawing->objects;  entity;  entity = entity->next){switch( entity->flags ){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case7:case 8:case 9:case 10://center linedraw_entity( entity, entity->color);//attr.color = entity->color;//ck_setattr( entity->id, CK_COLOR, NULL,&attr );}if ( entity->next == NULL )break;}return 0;}/*================================================================  関数：  名称：    F2dCleanUpDeleteViews  記述：     それは削除ビユーに対する関数である。  復帰値：        =0：成功裏に完了；  パラメータ：        入力：          1 Indrawing：図=================================================================*/int F2dCleanUpDeleteViews(struct drawing *In_drawing){//check drawingif ( In_drawing == NULL )return 0;    //delete views ( Not release memory )In_drawing->views == NULL;return 0;}/*=================================================================  関数：  名称：    F2dCleanUpDeleteDrawingEntity  記述：    それは削除エンティティに対する関数である。復帰値：      ＝０：成功裏に完了；  パラメータ：        入力：1 In drawing：図=================================================================*/int F2dCleanUpDeleteDrawingEntity(struct drawing *In_drawing){//selected entity and temp entitiesstruct node *entity;struct group *Gp;//groupstruct node_list *ETL;//Entity Temp ListintCountPrompt = 0;charmessage[64];#ifdef VELLUMCountPrompt++;sprintf( message,"Start Delete Entity %d", CountPrompt );ck_prompt( message );  #endif//check all of entities on the listfor( entity=In_drawing->objects;  entity;  entity = entity->next){if ( entity->flags == 3 || entity->flags == 6  || entity->flags== 0 || entity->flags == 10 ){#ifdef CKWINck_delent( entity->id );#endif#ifdef VELLUM//            remove_entity ( entity,  In_drawing );#endifentity->flags = 99;}if ( entity->next == NULL )break;}if ( In_drawing->views == NULL )return 0;//unuse group entitiesfor( Gp=In_drawing->views;Gp; Gp = Gp->next){if ( Gp == NULL )break;if ( Gp->index != 0 )continue;for ( ETL = Gp->entities; ETL; ETL = ETL->cdr ){#ifdef CKWINck_delent( ETL->car->id );#endif#ifdef VELLUM //           remove_entity ( ETL->car,  In_drawing );#endifETL->car->flags = 99; if ( ETL->cdr == NULL )break;}if ( Gp->next == NULL )break;}#ifdef VELLUMCountPrompt++;sprintf( message,"Finished Delete Entity %d", CountPrompt );ck_prompt( message );  #endifreturn 0;}/*=================================================================関数： 名称： F2dCleanUpCheckEntityExist記述： check an entity for current drawingif the entity is not same to database, drawing was changed 戻り値：= 0: No change;= 1: Changed;パラメータ：入力： 1 In_drawing: drawing ================================================================*/int F2dCleanUpCheckEntityExist(struct drawing *In_drawing){//selected entity and temp entitiesstruct node *entity;//defineint ReturnCode = 0, etype = 0;doublex1=0.0,y1=0.0,z1=0.0,x2=0.0,y2=0.0,z2=0.0,rad=0.0,ang1=0.0,ang2=0.0;//entity’s specifitysCK_ENTATTattr;//specificity of entities//check all of entities on the listif ( In_drawing->objects == NULL )  return1;for( entity=In_drawing->objects;  entity;  entity = entity->next){if ( entity->flags == 99 )continue;ReturnCode = ck_getentid( entity->id, &etype );if ( ReturnCode == CK_NO_ENT )return1;else{//check all ofentities on the listswitch ( entity->type ){case CK_ARC:ck_getarc ( entity->id, &x1,&y1,&z1,  &rad,&ang1,&ang2, &attr );break;  case CK_LINE: ck_getline( entity->id, &x1,&y1,&z1,  &x2,&y2,&z2, &attr );break;}if ( attr.level == 191 )return0;elsereturn1;}if ( entity->next == NULL )break;}return 1;}/*================================================================  関数：  名称：    F2dCleanUpChangeArrowVertexFlag  記述：      アラウトップ頂点フラグを変更し、アローセンタライン座標を設定する。  復帰値：＝０：成功裏に完了；  パラメータ：          入力：            1 Flags：フラグ            2 TopVertex：アロートップ頂点            3 Entiry：  アローセンタラインエンティティ=================================================================*/int F2dCleanUpChangeArrowVertexFlag(//inputint *flags,structplanar_vertex *TopVertex,structnode *Entity){//set flagto arrow top vertexTopVertex->flags = *flags;//set arrow center line coordinatesTopVertex->ArrowCenterLine_X1 = Entity->X1;TopVertex->ArrowCenterLine_Y1 = Entity->Y1;TopVertex->ArrowCenterLine_Z1 = Entity->Z1;TopVertex->ArrowCenterLine_X2 = Entity->X2;TopVertex->ArrowCenterLine_Y2 = Entity->Y2;TopVertex->ArrowCenterLine_Z2 = Entity->Z2;//endreturn 0;}/*=================================================================  関数：名称：    F2dCleanUpFindArrowCenterEntity  記述：    アローセンタラインを見出し、フラグをアローメンバに設定する。  復帰値：      ＝０：アロー無し；      ＝１：アロー  パラメータ：        入力：          1 Nodes：接続されたノード          2 TopVertex：アロートップ頂点          3 StartEntity：アロースタートラインエンティティ          4 EndEntity：アローエンドラインエンティティ          5 CenterLineAngleTemp：アローセンタライン角度=================================================================*/int F2dCleanUpFindArrowCenterEntity(//inputstruct node_list *Nodes,structplanar_vertex *TopVertex,structnode *StartEntity,structnode *EndEntity,double*CenterLineAngleTemp ){//external functionsint F2dCleanUpLineAngle(); int F2dCleanUpChangeChildrenFlag();int F2dCleanUpChangeArrowVertexFlag();double F2dCleanUpLineLength();//nodesstructnode *CenterEntity;//linklist and temp liststruct node_list*temp_list;//flagsint ReturnFlag = 0,ArrowFlags = 3; //doubledoubleCenterParentLength = 0.0,CenterParentAngle= 0.0,CenterParentAngleAnother = 0.0;doubleTolerance = 0.0;//set valueTolerance = F2dCleanUpTolerance;// look for arrow center linefor( temp_list = Nodes;  temp_list; temp_list = temp_list->cdr){//check pointer addressif ( StartEntity == temp_list->car  || EndEntity == temp_list->car)continue;//get new entityCenterEntity = temp_list->car;//check flags//if (CenterEntity->flags   != 2 //&& CenterEntity->flags != 3 )continue; if( CenterEntity->type != CK_LINE )continue;  if ( CenterEntity->line_type   != StartEntity->line_type && CenterEntity->color   != StartEntity->color && CenterEntity->is_thickness != StartEntity->is_thickness ) continue; if ( CenterEntity->no_connected_1 < 2  && CenterEntity->no_connected_2 < 2 ) continue;    //check lengthCenterParentLength = F2dCleanUpLineLength( CenterEntity->parent );if ( CenterParentLength < Tolerance ) continue;//arrow central-entity angleF2dCleanUpLineAngle(//inputTopVertex, CenterEntity->parent,//output&CenterParentAngle, &CenterParentAngleAnother);//check the angle for central entity if ( fabs( CenterParentAngle - *CenterLineAngleTemp )> Tolerance )  continue;// set flags for arrow’s entitiesReturnFlag = 1;//look for arrow entity’s childrenF2dCleanUpChangeChildrenFlag( StartEntity->parent );F2dCleanUpChangeChildrenFlag( EndEntity->parent );F2dCleanUpChangeChildrenFlag( CenterEntity->parent );//set flag to arrow top vertexF2dCleanUpChangeArrowVertexFlag( &ArrowFlags,TopVertex, CenterEntity );return ReturnFlag;if ( temp_list->cdr == NULL)break;}return ReturnFlag;}/*  関数：  名称：    F2dCleanUpFindArrowOneSideOpenEntity  記述：    １つのサイドオープンエンティティを見出す。  復帰値：      =0:  ノーオープン；      =1:  オープン      =2:  オープンパラメータ：        入力：        1 Nodes：接続されたノード================================================================*/int F2dCleanUpFindArrowOneSideOpenEntity( struct node_list *Nodes ){//link list and temp liststruct node_list*temp_list;//entities counter and flagsint open_entity_flag = 0;//startfor( temp_list = Nodes;  temp_list;  temp_list = temp_list->cdr){//ckeck another side connected’s counterif ( temp_list->car->no_connected_1 == 0 && temp_list->car->no_connected_2 > 1 ){open_entity_flag = 1;break;}if ( temp_list->car->no_connected_2 == 0 && temp_list->car->no_connected_1 > 1 ){open_entity_flag = 2;break;}if ( temp_list->cdr== NULL )break;}return open_entity_flag;}/*=================================================================  関数：  名称：    F2dClaenUpCheckStartEndEntity  記述：    開始および終了エンティティをチェックする    復帰値：      ＝０：  ノーアロー；= 1: goodパラメータ：入力： 1 StartEntity: アロー開始ラインエンティティ2 EndEntity: アロー終了ラインエンティティ=================================================================*/int F2dCleanUpCheckStartEndEntity(//inputstructnode *StartEntity,structnode *EndEntity ){//external functionsdouble F2dCleanUpLineLength();//doubledoublearrow_start_parent_length = 0.0,arrow_end_parent_length = 0.0,arrow_tolerance = 0.0;//set tolerancearrow_tolerance = F2dCleanUpTolerance;//start//compute entities’ parent lengtharrow_start_parent_length = F2dCleanUpLineLength( StartEntity );arrow_end_parent_length   = F2dCleanUpLineLength( EndEntity );//check lengthif ( arrow_start_parent_length < arrow_tolerance )return 0; if ( arrow_end_parent_length < arrow_tolerance )return 0; //check tloeranceif ( fabs( arrow_start_parent_length - arrow_end_parent_length )> arrow_tolerance )return 0;  //check angle:if entitiesare parallel, STOPif (sqrt(fabs((( StartEntity->X1 - StartEntity->X2 )    * ( EndEntity->Y1   - EndEntity->Y2 ))    -(( EndEntity->X1   - EndEntity->X2 )    * ( StartEntity->Y1 - StartEntity->Y2 ))))< arrow_tolerance )return 0;//normal endreturn 1;}/*================================================================関数： 名称： F2dCleanUpComputeCenterLineAngle記述： センタライン角度を計算する。戻り値：= 0: ノーアロー;= 1: 良好パラメータ：入力： 1 TopVertex: アロートップ頂点2 StartEntity: アロー開始ラインエンティティ 3 EndEntity: アロー終了ラインエンティティ出力：1 CenterLineAngle: アローセンターライン角度  ================================================================*/int F2dCleanUpComputeCenterLineAngle(//inputstructplanar_vertex *TopVertex,structnode *StartEntity,structnode*EndEntity,//outputdouble*CenterLineAngle ){//external functionsint F2dCleanUpLineAngle();//entities counter and flagsint ReturnFlag = 0;//doubledoublearrow_start_parent_angle = 0.0,arrow_end_parent_angle = 0.0,arrow_center_diff_angle = 0.0,RotateAxisAngleAnotherTemp = 0.0,arrow_center_parent_angle_temp = 0.0,arrow_tolerance = 0.0;//set tolerancearrow_tolerance = F2dCleanUpTolerance;//start// compute central angle of arrow////angle_center = 0.5 * ( angle_start + angle_end )//atan2 returns the arctangent of y/x//atan2 returns a value in the range -pi to pi radians//getarrow start angleF2dCleanUpLineAngle(//inputTopVertex, StartEntity,//output&arrow_start_parent_angle, &RotateAxisAngleAnotherTemp);//arrow end angleF2dCleanUpLineAngle(//inputTopVertex, EndEntity,//output&arrow_end_parent_angle, &RotateAxisAngleAnotherTemp);//get difference anglearrow_center_diff_angle = fabs( arrow_end_parent_angle   - arrow_start_parent_angle );//same angleif ( arrow_center_diff_angle < arrow_tolerance )return0;if ( arrow_center_diff_angle < pi ){//diff < piarrow_center_parent_angle_temp = 0.5 * (arrow_end_parent_angle + arrow_start_parent_angle );}else{//diff > pi ( take opposite angle ) arrow_center_parent_angle_temp =0.5 * (arrow_end_parent_angle + arrow_start_parent_angle ) + pi;//angle> 2*piif ( fabs ( arrow_center_parent_angle_temp - 2.0 * pi )< arrow_tolerance ){arrow_center_parent_angle_temp = 0.0;}else{if ( arrow_center_parent_angle_temp > ( 2.0 * pi ) ){arrow_center_parent_angle_temp = arrow_center_parent_angle_temp - 2.0 * pi;}}}*CenterLineAngle = arrow_center_parent_angle_temp;//normal endreturn 1;}/*=================================================================関数： 名称： F2dCleanUpFindArrowEndEntity記述： アロー終了ラインを見出す戻り値：= 0: ノーアロー;= 1: アローパラメータ：入力： 1 Nodes: 接続ノード2 TopVertex: アロートップ頂点3 StartEntity: アロー開始エンティティ================================================================*/int F2dCleanUpFindArrowEndEntity(//inputstructnode_list *Nodes,structplanar_vertex *TopVertex,structnode *StartEntity){//external functionsint F2dCleanUpFindArrowOneSideOpenEntity();int F2dCleanUpComputeCenterLineAngle();int F2dCleanUpCheckStartEndEntity();intF2dCleanUpFindArrowCenterEntity();//link list and temp liststruct node_list*temp_list; //selected entity and temp entitiesstruct node *Next_entity,*arrow_start_entity_parent,*arrow_end_entity,*arrow_end_entity_parent;//entities counter and flagsint assistant_line_flag = 0,ReturnFlag = 0;//doubledoublearrow_center_parent_angle_temp = 0.0;//startfor( temp_list=Nodes;   temp_list;  temp_list = temp_list->cdr){ if ( temp_list->car== NULL )break;Next_entity = temp_list->car;arrow_end_entity = temp_list->car;//if ( Next_entity->flags != 2 )continue;if ( Next_entity->type !=CK_LINE )continue;if ( Next_entity->line_type != StartEntity->line_type)continue;if ( Next_entity->color != StartEntity->color )continue;if (Next_entity->is_thickness != StartEntity->is_thickness )continue;   //set parentarrow_start_entity_parent = StartEntity->parent; arrow_end_entity_parent   = Next_entity->parent; //look for broken entity’s another side ReturnFlag = F2dCleanUpFindArrowOneSideOpenEntity( arrow_end_entity_parent->children ); if ( ReturnFlag == 0 )continue;//check parents entitiesReturnFlag = F2dCleanUpCheckStartEndEntity(  //inputarrow_start_entity_parent, arrow_end_entity_parent );if ( ReturnFlag == 0 )continue;// look for central entityof arrowReturnFlag = F2dCleanUpComputeCenterLineAngle(//inputTopVertex, arrow_start_entity_parent, arrow_end_entity_parent,//output&arrow_center_parent_angle_temp );if ( ReturnFlag == 0 )continue;// get central entity of arrowassistant_line_flag = F2dCleanUpFindArrowCenterEntity(//inputNodes, TopVertex, StartEntity, arrow_end_entity, &arrow_center_parent_angle_temp );return assistant_line_flag;}return assistant_line_flag;}/*=================================================================関数： 名称： F2dCleanUpChangeChildrenFlag記述： エンティティのチルドレンフラグを変更する関数戻り値：= 0: 成功裏に完了;パラメータ：入力： =================================================================*/int F2dCleanUpChangeChildrenFlag(struct node *Entity){//temp liststruct node_list*Temp_list;//check all of children of the entityfor( Temp_list=Entity->children;  Temp_list;  Temp_list = Temp_list->cdr){//change flag to light grayTemp_list->car->flags = 3; if ( Temp_list->cdr == NULL )break;}return 0;}/*=================================================================関数： 名称： F2dCleanUpLineLength記述： ライン形エンティティの長さを計算する関数 戻り値：= 長さ;パラメータ：入力： エンティティ: ペアレントエンティティ================================================================*/double F2dCleanUpLineLength(struct node *Entity){//definationdoubleEntityLength=0.0;//compute entities’ parent lengthEntityLength =sqrt(  ( Entity->X1 - Entity->X2 ) * ( Entity->X1 - Entity->X2 )+ ( Entity->Y1 - Entity->Y2 ) *( Entity->Y1 - Entity->Y2 ));returnEntityLength;}/*=================================================================関数： 名称： F2dCleanUpFindArrow記述： アロー型エンティティを求め、フ���グをそれらに設定する。 戻り値：= 0: 成功裏に完了;パラメータ：入力： 1 Entities_list: チェックされるノードリスト================================================================*/int F2dCleanUpFindArrow( struct node_list *Entities_list ){//external functionsint F2dCleanUpLineAngle();int F2dCleanUpFindArrowEndEntity(); //link list and temp liststruct node_list*temp_nodes1,*arrow_list,*temp_list; //selected entity and temp entitiesstruct node *Next_entity;struct planar_vertex*top_vertex;//entities counter and flagsint bug_flag = 0,ReturnFlag = 0,assistant_line_flag = 0;int CountPrompt = 0;charmessage[64];#ifdef VELLUMCountPrompt++;sprintf( message,"Start Find Arrow Entity %d", CountPrompt );ck_prompt( message );  #endif// Step_1:look for one side open entity//arrow start entityfor( temp_list=Entities_list;  temp_list;  temp_list = temp_list->cdr){Next_entity =temp_list->car;//if ( Next_entity->flags != 2 ) continue;if ( Next_entity->type != CK_LINE ) continue;if ( Next_entity->no_connected_1  == 0&&Next_entity->no_connected_2 < 2 )  continue;if ( Next_entity->no_connected_1    < 2&& Next_entity->no_connected_2 == 0 )  continue;    //selectentity’s sideif ( Next_entity->no_connected_1 == 0 ){// clear bug_flagbug_flag = 0;//look for broken entity’s another side for( arrow_list = Next_entity->parent->children;  arrow_list;  arrow_list = arrow_list->cdr){//ckeck another side vertex’s pointerif ( Next_entity->parent->vertex2 ==  arrow_list->car->vertex2 ){  bug_flag = 1;  break;}if ( arrow_list->cdr == NULL )break;}if ( bug_flag == 1 ){top_vertex = Next_entity->parent->vertex2;temp_nodes1 = arrow_list->car->connected_nodes_2;}}else{//clear bug_flagbug_flag = 0;//look for broken entity’s another side for(arrow_list = Next_entity->parent->children;  arrow_list;  arrow_list =arrow_list->cdr){//ckeck another side vertex’s pointerif ( Next_entity->parent->vertex1 ==  arrow_list->car->vertex1 ){  bug_flag = 1;  break;}if ( arrow_list->cdr == NULL )break;}if ( bug_flag == 1 ){top_vertex = Next_entity->parent->vertex1;temp_nodes1 = arrow_list->car->connected_nodes_1;}}if ( bug_flag != 1 )     continue;// get end entity of arrowReturnFlag = F2dCleanUpFindArrowEndEntity(//inputtemp_nodes1, top_vertex, Next_entity );if ( ReturnFlag == 1 )assistant_line_flag = 1;if ( temp_list->cdr == NULL )break;}#ifdef VELLUMCountPrompt++;sprintf( message,"Finished find arrows Entity %d", CountPrompt );ck_prompt( message );  #endifreturnassistant_line_flag;}/*=================================================================関数： 名称： F2dCleanUpFindOneSideOpenEntity記述：look for one side open entities and they are vertical with arrow type entities. 戻り値：= 0: Completed successfully and No found;= NUM: Open entities’ numberパラメータ：入力： 1 Entities_list: a node list that willbe checked================================================================*/int F2dCleanUpFindOneSideOpenEntity( struct node_list *Entities_list){//external functionsint F2dCleanUpChangeChildrenFlag();//link list and temp liststruct node_list *temp_list; //selected entity and temp entitiesstruct node *Next_entity;//entities counter and flagsint count = 0;//doubledoubleassistant_line_angle = 0.0,arrow_tolerance = 0.0;int CountPrompt = 0;charmessage[64];//set tolerancearrow_tolerance = F2dCleanUpTolerance;#ifdef VELLUMCountPrompt++;sprintf( message,"Start Find One side open Entity %d", CountPrompt );ck_prompt( message );  #endif    // checkall of entities which connected with outside loop    for( temp_list=Entities_list;  temp_list;  temp_list = temp_list->cdr){ if ( temp_list->car== NULL )break;Next_entity = temp_list->car;//check flags//if ( Next_entity->flags !=2 )continue;//check vertex’ flagif ( Next_entity->vertex1->flags != 3 && Next_entity->vertex2->flags != 3 )continue;//check linesverticallyif ( Next_entity->vertex1->flags == 3 ){assistant_line_angle= fabs (   ( Next_entity->X1 - Next_entity->X2 )* (Next_entity->vertex1->ArrowCenterLine_X1     - Next_entity->vertex1->ArrowCenterLine_X2 ) + (Next_entity->Y1 - Next_entity->Y2 ) * (Next_entity->vertex1->ArrowCenterLine_Y1     - Next_entity->vertex1->ArrowCenterLine_Y2 ) );}else{assistant_line_angle = fabs (   ( Next_entity->X1 - Next_entity->X2 )* (Next_entity->vertex2->ArrowCenterLine_X1     - Next_entity->vertex2->ArrowCenterLine_X2 ) + ( Next_entity->Y1 - Next_entity->Y2 ) * (Next_entity->vertex2->ArrowCenterLine_Y1     - Next_entity->vertex2->ArrowCenterLine_Y2 ));}//check the angle for central entity if ( sqrt(assistant_line_angle)> arrow_tolerance ) continue;//look for childrenF2dCleanUpChangeChildrenFlag( Next_entity->parent );count++;}#ifdef VELLUMCountPrompt++;sprintf( message,"Finished find one side open Entity %d", CountPrompt );ck_prompt( message );  #endif//normal endreturn count;}/*=================================================================関数： 名称： F2dCleanUpFindOneSideOpenEntity2記述： ビユーを見出した後に一側がオープンのエンティティとビユーの境界を横切るエンティティを見出す。戻り値：= 0: 成功裏に完了し、何も見出されない;= NUM: オープンエンティティの個数パラメータ：入力： 1In_drawing: 図================================================================*/int F2dCleanUpFindOneSideOpenEntity2( struct drawing *In_drawing ){//external functionsint F2dCleanUpChangeChildrenFlag();//link list and temp liststruct node_list *temp_list, *ConnectedNode; //selected entity and temp entitiesstruct node *Entity;//define flagintBoundaryFlag = 0; int CountPrompt = 0;charmessage[64];#ifdef VELLUMCountPrompt++;sprintf( message,"2 Start Find Oneside Open  Entity %d", CountPrompt );ck_prompt( message );  #endif   //check node listif ( In_drawing == NULL )return-1;if ( In_drawing->objects == NULL )return-1;    // check all of entities which connected with outside loop    for( Entity=In_drawing->objects;Entity;Entity = Entity->next ){//check connected nodes countif ( Entity== NULL )break;if (( Entity->no_connected_1 == 0 )  &&( Entity->no_connected_2 == 0 ))continue;//check flagsif (( Entity->flags == 3 ) &&( Entity->type == CK_LINE )  &&(( Entity->no_connected_1 == 0 )   ||( Entity->no_connected_2 == 0 ))){//one side open and line typeif ( Entity->no_connected_2 == 0 )    ConnectedNode = Entity->connected_nodes_1;else ConnectedNode = Entity->connected_nodes_2;//clear found boundary’s flagBoundaryFlag = 0;//check across with views’ boundaryif ( ConnectedNode != NULL){for ( temp_list = ConnectedNode; temp_list;temp_list = temp_list->cdr){//check wrong dataif ( temp_list->car == NULL )break;if ( temp_list->car->flags == 4 ){//find boundary’s entityBoundaryFlag = 1;break;}if (temp_list->cdr == NULL )break;}if ( BoundaryFlag == 1 )  //look for children F2dCleanUpChangeChildrenFlag( Entity->parent );}}//check arc if ((Entity->type == CK_ARC )  &&( Entity->flags != 99 )  &&(( Entity->no_connected_1 == 0 )   ||( Entity->no_connected_2 == 0 ))){//look for childrenF2dCleanUpChangeChildrenFlag( Entity->parent );}if ( Entity->next == NULL )break;}#ifdef VELLUMCountPrompt++;sprintf( message,"Finished 2 one side open Entity %d", CountPrompt );ck_prompt( message );  #endif//normalendreturn 0;}/*================================================================関数： 名称： F2dCleanUpFindGroupMinX記述： エンティティグループに対する最小Ｘ値を求める。戻り値：= 0: 成功裏に完了し、エンティティ無し;パラメータ：入力： 1 Entities_list: チェックされるノードリスト出力：1 Entity： エンティティは最小のＸ値を含む。================================================================*/struct node *F2dCleanUpFindGroupMinX( struct node_list *Entities_list ){//double F2dCleanUpLineLength();//entities counter and flagsint open_entity_flag = 0;//link list and temp liststruct node_list*EntitiesList2,*Out_temp_list2,*open_temp_list2, *open_list2, *temp_list1, *temp_list2; //selected entity and temp entitiesstructnode  *Next_entity, *MinXvalueEntity;//length and angledoubleMinXvalueGroup = 0.0;//check all of entities which connected with  outside loop//initializeEntitiesList2 =( struct node_list * ) calloc ( 1, sizeof ( struct node_list ));open_list2 = ( struct node_list * ) calloc ( 1, sizeof (struct node_list ));//check first entity//search connected entity untilreal entity be foundfor ( temp_list2 = Entities_list;//entity->connected_nodes;  ( temp_list2!=0 &&        temp_list2->car!=0 );      temp_list2=temp_list2->cdr){if ( temp_list2->car == NULL )break;if ( temp_list2->car->no_connected_1 == 0 ) continue;if ( temp_list2->car->no_connected_2== 0 ) continue;if ( temp_list2->car->flags == 2 ){//set pointer to first entityopen_list2->car = temp_list2->car;//set minimum X valueMinXvalueGroup = temp_list2->car->Min_X;MinXvalueEntity = temp_list2->car;break;}if ( temp_list2->cdr == NULL )break;}if ( open_list2->car == 0 )return 0;//set link addressopen_list2->cdr = NULL;//set the pointer to output node listEntitiesList2->car = open_list2->car;EntitiesList2->cdr = open_list2->cdr;////Step_6_1://find connected entitiesfor ( temp_list1 = open_list2;       ( temp_list1      //&&(temp_list->cdr != 0)       );    ) {//get a pointer from open listif ( temp_list1->car == NULL )break;Next_entity = temp_list1->car;//set a closed flag to the node//Next_entity->flags = 1;//close the node ( delete the node from open list )open_list2 = open_list2->cdr;// look for first connected entity whose flags=0.for ( temp_list2 = Next_entity->connected_nodes;  ( temp_list2!=0 &&        temp_list2->car!=0 );      temp_list2=temp_list2->cdr){     if ( temp_list2->car == NULL ) break;// if found an unmarked connected entityif ( temp_list2 && temp_list2->car->flags==2&& MinXvalueEntity->line_type == temp_list2->car->line_type&& MinXvalueEntity->color == temp_list2->car->color&& MinXvalueEntity->is_thickness == temp_list2->car->is_thickness      ){//check minimum Xif ( temp_list2->car->Min_X < MinXvalueGroup ){//change minimum X valueMinXvalueGroup  = temp_list2->car->Min_X;MinXvalueEntity = temp_list2->car; }// allocate memory for open list elementopen_temp_list2 = ( struct node_list * ) calloc ( 1, sizeof ( struct node_list ));// allocate memory for output node list elementOut_temp_list2 = ( structnode_list * ) calloc ( 1, sizeof ( struct node_list ));// add this entity to the open listopen_temp_list2->car = temp_list2->car;// add this entity to the output node list Out_temp_list2->car = temp_list2->car;//seta open flagto the nodeopen_temp_list2->car->flags = 1; // connect to the open listopen_temp_list2->cdr = open_list2;// move the pointer of openlist to the topopen_list2 = open_temp_list2;// connect to the output node listOut_temp_list2->cdr = EntitiesList2;// move the pointer of outputnode list to the topEntitiesList2 = Out_temp_list2;}if ( temp_list2->cdr == NULL )break;}// assign value to the loop variabletemp_list1 = open_list2;}return MinXvalueEntity;}/*=================================================================関数： 名称： F2dCleanUpFindOutNextEntity記述： アウトサイドループエンティティに接続されたエンティティを求める。戻り値：= 0: 成功裏に完了;パラメータ：入力： 1 In_entity: 軸エンティティを回転 2 In_Nodes:  エンティティのノード3 In_Vertex: エンティティの頂点4 *In_Angle: エンティティの角度================================================================*/int F2dCleanUpFindOutNextEntity(//input struct node*In_entity,struct node_list *In_Nodes, struct planar_vertex *In_Vertex,double *In_Angle){//external functionsint F2dCleanUpArcAngle(); int F2dCleanUpLineAngle();//link list and temp liststruct node_list*temp_list, *RotateNodes,*RotateNodesTemp,*RotateNodesAnother,*RotateNodesAnotherTemp;//selected entity and temp entitiesstruct node  *Next_entity, *RotateEntity;struct planar_vertex*RotateVertex,*RotateVertexTemp,*RotateVertexAnother,*RotateVertexAnotherTemp;int RotateVertexFlag = 0,RotateAxisEntityType = 0,RotateAxisEntityVertexFlag = 0,FindNextFlag = 0;//length and angledoubleRotateAxisAngleAnother = 0.0,RotateAxisAngleAnotherTemp = 0.0,RotateMinAngleTemp = 0.0,RotateDiffAngleTemp = 0.0,RotateAxisAngle = 0.0,RotateAxisAngleTemp = 0.0;//set tolerance TolerancedoubleTolerance  = 0.0;Tolerance = F2dCleanUpTolerance;//initializeRotateAxisAngleAnother= *In_Angle;RotateEntity= In_entity;RotateNodesAnother= In_Nodes;RotateVertexAnother= In_Vertex;//check all of entities which connected with outside loopfor( ; ; ){//set flag  for first entity on loopFindNextFlag = 0;RotateEntity->flags= 4;RotateAxisEntityType = RotateEntity->type;if ( RotateEntity->vertex1 == RotateVertexAnother )RotateAxisEntityVertexFlag = 1;else RotateAxisEntityVertexFlag = 2;//set standard axis for first searchRotateAxisAngle = RotateAxisAngleAnother;RotateMinAngleTemp= 2.0 * pi;RotateNodes= RotateNodesAnother;RotateVertex= RotateVertexAnother;    //check next connected entityif ( RotateNodes == 0 )break;//start loop process    for( temp_list=RotateNodes;  temp_list;  temp_list = temp_list->cdr){if ( temp_list->car == NULL )break;Next_entity = temp_list->car;//checkflagsif ( Next_entity->flags == 4 )break;if ( Next_entity->flags != 1 )continue;switch ( Next_entity->type ){//arc  type entitycaseCK_ARC:RotateVertexFlag = F2dCleanUpArcAngle(//inputRotateVertex, Next_entity,//output&RotateAxisAngleTemp, &RotateAxisAngleAnotherTemp);break;//line  typeentitycaseCK_LINE:RotateVertexFlag = F2dCleanUpLineAngle(//inputRotateVertex, Next_entity,//output&RotateAxisAngleTemp, &RotateAxisAngleAnotherTemp);break;//wrong type entitydefault:break;}//select connected side ofentityif ( RotateVertexFlag == 1 ){//get start->end //set rotation vertex nodeRotateNodesTemp = Next_entity->connected_nodes_1;RotateVertexTemp=Next_entity->vertex1;//set another side vertex nodeRotateNodesAnotherTemp = Next_entity->connected_nodes_2;RotateVertexAnotherTemp= Next_entity->vertex2;}else{//set rotation vertex nodeRotateNodesTemp = Next_entity->connected_nodes_2;RotateVertexTemp = Next_entity->vertex2;//set anotherside vertex nodeRotateNodesAnotherTemp = Next_entity->connected_nodes_1;RotateVertexAnotherTemp= Next_entity->vertex1;}//compute diff angle//for change current entityRotateDiffAngleTemp = RotateAxisAngleTemp - RotateAxisAngle;if ( fabs( RotateDiffAngleTemp ) < Tolerance ) {switch( RotateAxisEntityType ){caseCK_ARC:switch( RotateAxisEntityVertexFlag ){case1:RotateDiffAngleTemp = 2.0 * pi;break;case2:RotateDiffAngleTemp = 0.0;break;}break;caseCK_LINE:switch( RotateVertexFlag ){case1:RotateDiffAngleTemp = 0.0;break;case2:RotateDiffAngleTemp = 2.0 * pi;break;}break;}}if (RotateDiffAngleTemp < 0.0 ){RotateDiffAngleTemp = RotateDiffAngleTemp +2.0 * pi;}if ( fabs( RotateDiffAngleTemp - RotateMinAngleTemp ) < Tolerance ) {switch( Next_entity->type ){caseCK_ARC:switch( RotateEntity->type){caseCK_ARC:switch( RotateVertexFlag ){case1://no changebreak;case2:RotateEntity= Next_entity;RotateNodes   = RotateNodesTemp;RotateVertex= RotateVertexTemp;RotateNodesAnother = RotateNodesAnotherTemp;RotateVertexAnother = RotateVertexAnotherTemp;RotateAxisAngleAnother = RotateAxisAngleAnotherTemp;break;}break;caseCK_LINE:switch( RotateVertexFlag ){case1://no changebreak;case2:RotateEntity= Next_entity;RotateNodes   = RotateNodesTemp;RotateVertex= RotateVertexTemp;RotateNodesAnother = RotateNodesAnotherTemp;RotateVertexAnother = RotateVertexAnotherTemp;RotateAxisAngleAnother = RotateAxisAngleAnotherTemp;break;}break;}caseCK_LINE:switch( RotateEntity->type ){caseCK_ARC:if ( RotateEntity->vertex1 == RotateVertex ){RotateEntity= Next_entity;RotateNodes   = RotateNodesTemp;RotateVertex= RotateVertexTemp;RotateNodesAnother = RotateNodesAnotherTemp;RotateVertexAnother = RotateVertexAnotherTemp;RotateAxisAngleAnother = RotateAxisAngleAnotherTemp;}break;}}}if ( RotateDiffAngleTemp < RotateMinAngleTemp ){FindNextFlag = 1;RotateMinAngleTemp = RotateDiffAngleTemp;//set rotation entityRotateEntity= Next_entity;RotateNodes   = RotateNodesTemp;RotateVertex= RotateVertexTemp;RotateNodesAnother = RotateNodesAnotherTemp;RotateVertexAnother = RotateVertexAnotherTemp;RotateAxisAngleAnother =RotateAxisAngleAnotherTemp;}}//check flags//if loop meet closed entity if ( Next_entity->flags == 4 )break;if ( FindNextFlag == 0 ) break;}return 0;}/*=================================================================関数： 名称： F2dCleanUpFindOutSideLoop記述： アウトサイドループエンティティを求める。戻り値：= 0: アウトサイドループエンティティを求める。;= NUM: アウトサイドエンティティの個数パラメータ：入力： 1 Entity： エンティティはループの最小Ｘ値を含む。================================================================*/int F2dCleanUpFindOutSideLoop( struct node *MinXvalueEntity ){//external functionsint F2dCleanUpArcAngle(); int F2dCleanUpLineAngle();int F2dCleanUpFindOutFirstEntity();int F2dCleanUpFindOutNextEntity(); //entities counter and flagsint count = 0,count2 = 0,open_entity_flag = 0,RotateVertexFlag = 0,assistant_line_flag = 0;//link list and temp liststruct node_list*outside_loop_temp_list3, *RotateNodes,*RotateNodesTemp,*RotateNodesAnother,*RotateNodesAnotherTemp;//selected entity and temp entitiesstruct node  *Next_entity, *RotateEntity;struct planar_vertex*RotateVertex,*RotateVertexTemp,*RotateVertexAnother,*RotateVertexAnotherTemp;//length and angledoubleassistant_line_angle = 0.0,MinXvalueGroup = 0.0,RotateAxisAngleAnother = 0.0,RotateAxisAngleAnotherTemp =0.0,RotateMinAngleTemp = 0.0,RotateDiffAngle = 0.0,RotateDiffAngleTemp =0.0,RotateAxisAngle = 0.0,RotateAxisAngleTemp = 0.0;//set tolerance Tolerancedoubleloop_tolerance  = 0.00;loop_tolerance = F2dCleanUpTolerance;//loop direction : counter-clock//check a flag for outside loop process//if ( count2 > 0 ){//step_7_1:find first entity for the group//set standard axis for first searchRotateAxisAngle = 1.5 * pi;RotateMinAngleTemp=2.0 * pi;//step_7_1_1: only one entity//check entities’ angle//arc case: special case ( no vertex on min_x )if ( MinXvalueEntity->type == CK_ARC  && ( fabs ( MinXvalueEntity->Min_X - MinXvalueEntity->vertex1->X ) >loop_tolerance ) && ( fabs ( MinXvalueEntity->Min_X - MinXvalueEntity->vertex2->X ) > loop_tolerance ) ){//set rotation vertex nodeRotateNodesAnother = MinXvalueEntity->connected_nodes_2;RotateVertexAnother = MinXvalueEntity->vertex2;RotateEntity= MinXvalueEntity;//get arc end-angle //(direction : from circle-center to end-point )RotateAxisAngleAnotherTemp= ( MinXvalueEntity->AngEnd ) * pi / 180.0;//change angle to oppsite direction//( direction : from end-point to circle-center )RotateAxisAngleAnotherTemp = RotateAxisAngleAnotherTemp + pi;//check angle if ( RotateAxisAngleAnotherTemp > ( 2.0 * pi )){ RotateAxisAngleAnotherTemp = RotateAxisAngleAnotherTemp - 2.0 * pi;}if ( fabs ( RotateAxisAngleAnotherTemp -( 2.0 * pi )) < loop_tolerance ){RotateAxisAngleAnotherTemp = 0.0;}//compute tangentline angle for the arc end-angle//( direction : from end-point to start-point )RotateAxisAngleAnotherTemp = RotateAxisAngleAnotherTemp + 0.5 * pi;//check angle if ( RotateAxisAngleAnotherTemp > ( 2.0 * pi )){ RotateAxisAngleAnotherTemp = RotateAxisAngleAnotherTemp - 2.0 * pi;}if ( fabs ( RotateAxisAngleAnotherTemp - ( 2.0 * pi )) < loop_tolerance ){RotateAxisAngleAnotherTemp = 0.0;}//set rotation standard angle ( clock direction )RotateAxisAngleAnother = RotateAxisAngleAnotherTemp;}//step_7_1_2: multiple entities around Min_xelse{//select connected side ofentityif ( fabs ( MinXvalueEntity->Min_X - MinXvalueEntity->vertex1->X )< loop_tolerance )//get start->end //set rotation vertex nodeRotateVertex= MinXvalueEntity->vertex1;elseRotateVertex= MinXvalueEntity->vertex2;switch ( MinXvalueEntity->type ){//arc  type entitycaseCK_ARC:RotateVertexFlag = F2dCleanUpArcAngle(//inputRotateVertex, MinXvalueEntity,//output&RotateAxisAngleTemp, &RotateAxisAngleAnotherTemp);break;//line  type entitycaseCK_LINE:RotateVertexFlag = F2dCleanUpLineAngle(//inputRotateVertex, MinXvalueEntity,//output&RotateAxisAngleTemp, &RotateAxisAngleAnotherTemp);break;default:break;} //select connected side of entityif ( RotateVertexFlag == 1 ){//get start->end //set rotation vertex nodeRotateNodesTemp = MinXvalueEntity->connected_nodes_1;RotateVertexTemp= MinXvalueEntity->vertex1;//set another side vertex nodeRotateNodesAnotherTemp = MinXvalueEntity->connected_nodes_2;RotateVertexAnotherTemp= MinXvalueEntity->vertex2;}else{//set rotation vertex nodeRotateNodesTemp = MinXvalueEntity->connected_nodes_2;RotateVertexTemp = MinXvalueEntity->vertex2;//set another side vertex nodeRotateNodesAnotherTemp = MinXvalueEntity->connected_nodes_1;RotateVertexAnotherTemp= MinXvalueEntity->vertex1;}//compute diff angle//for change current entityRotateDiffAngleTemp = RotateAxisAngleTemp - RotateAxisAngle;if ( RotateDiffAngleTemp < 0.0 ){RotateDiffAngleTemp = RotateDiffAngleTemp + 2.0 * pi;}if ( RotateDiffAngleTemp < RotateMinAngleTemp ){RotateMinAngleTemp = RotateDiffAngleTemp;//set rotation entityRotateEntity= MinXvalueEntity;RotateNodes   = RotateNodesTemp;RotateVertex= RotateVertexTemp;RotateNodesAnother = RotateNodesAnotherTemp;RotateVertexAnother = RotateVertexAnotherTemp;RotateAxisAngleAnother =RotateAxisAngleAnotherTemp;}//step_7_1_3: find next connected entity with first entity around Min_x-vertex//check all of entities which connected with first entity    if ( RotateNodes != 0 ){    for( outside_loop_temp_list3=RotateNodes;  outside_loop_temp_list3;  outside_loop_temp_list3= outside_loop_temp_list3->cdr){if ( outside_loop_temp_list3->car == NULL )break;Next_entity = outside_loop_temp_list3->car;//check flagsif ( Next_entity->flags !=1 )continue;switch ( Next_entity->type ){//arc  typeentitycaseCK_ARC:RotateVertexFlag = F2dCleanUpArcAngle(//inputRotateVertex, Next_entity, //output&RotateAxisAngleTemp, &RotateAxisAngleAnotherTemp);break;//line  type entitycaseCK_LINE:RotateVertexFlag = F2dCleanUpLineAngle(//inputRotateVertex, Next_entity, //output&RotateAxisAngleTemp,&RotateAxisAngleAnotherTemp);break;//wrong type entitydefault:break;}//select connected side of entityif ( RotateVertexFlag == 1 ){//get start->end //set rotation vertex nodeRotateNodesTemp = Next_entity->connected_nodes_1;RotateVertexTemp= Next_entity->vertex1;//set another side vertexnodeRotateNodesAnotherTemp = Next_entity->connected_nodes_2;RotateVertexAnotherTemp= Next_entity->vertex2;}else{//set rotation vertex nodeRotateNodesTemp = Next_entity->connected_nodes_2;RotateVertexTemp = Next_entity->vertex2;//set another side vertex nodeRotateNodesAnotherTemp = Next_entity->connected_nodes_1;RotateVertexAnotherTemp= Next_entity->vertex1;}//compute diff angle//for change current entityRotateDiffAngleTemp = RotateAxisAngleTemp - RotateAxisAngle;if ( RotateDiffAngleTemp < 0.0 ){RotateDiffAngleTemp = RotateDiffAngleTemp + 2.0 * pi;}if ( fabs( RotateDiffAngleTemp - RotateMinAngleTemp ) < loop_tolerance ) {switch( Next_entity->type ){caseCK_ARC:switch( RotateEntity->type ){caseCK_ARC:switch( RotateVertexFlag ){case1://no changebreak;case2:RotateEntity= Next_entity;RotateNodes   = RotateNodesTemp;RotateVertex= RotateVertexTemp;RotateNodesAnother = RotateNodesAnotherTemp;RotateVertexAnother = RotateVertexAnotherTemp;RotateAxisAngleAnother = RotateAxisAngleAnotherTemp;break;}break;caseCK_LINE:switch( RotateVertexFlag ){case1://no changebreak;case2:RotateEntity= Next_entity;RotateNodes   = RotateNodesTemp;RotateVertex= RotateVertexTemp;RotateNodesAnother = RotateNodesAnotherTemp;RotateVertexAnother = RotateVertexAnotherTemp;RotateAxisAngleAnother = RotateAxisAngleAnotherTemp;break;}break;}caseCK_LINE:switch( RotateEntity->type ){caseCK_ARC:if ( RotateEntity->vertex1 == RotateVertex ){RotateEntity= Next_entity;RotateNodes   = RotateNodesTemp;RotateVertex= RotateVertexTemp;RotateNodesAnother = RotateNodesAnotherTemp;RotateVertexAnother = RotateVertexAnotherTemp;RotateAxisAngleAnother = RotateAxisAngleAnotherTemp;}break;}}}if ( RotateDiffAngleTemp < RotateMinAngleTemp ){RotateMinAngleTemp =RotateDiffAngleTemp;//set rotation entityRotateEntity= Next_entity;RotateNodes   = RotateNodesTemp;RotateVertex= RotateVertexTemp;RotateNodesAnother = RotateNodesAnotherTemp;RotateVertexAnother = RotateVertexAnotherTemp;RotateAxisAngleAnother = RotateAxisAngleAnotherTemp;}}}}//step_7_2:find next connected entity with first entity along the loopF2dCleanUpFindOutNextEntity(//input RotateEntity, RotateNodesAnother, RotateVertexAnother, &RotateAxisAngleAnother );return 0;}/*=================================================================関数： 名称： TestFindArrowControl記述： 手動関数。ビユーに対して全てのアロー型エンティティを求める。戻り値：< 0: エラー= 0: プロセスなし> 0: 成功裏に完了; 個数は見出されたエンティティのカウンタ値である。パラメータ：副関数：struct node_list *F2dCleanUpPickUpAllOneSideOpenEntity一側オープンのエンティティを求める。int F2dCleanUpFindArrowアロー型エンティティを求める。int F2dCleanUpFindArrowEndEntityアローエンドラインを見出す。int F2dCleanUpFindArrowCenterEntityアローセンターラインを見出す。int F2dCleanUpFindArrowOneSideOpenEntityアロー型の一側オープンのエンティティを見出す。int F2dCleanUpComputeCenterLineAngleセンターライン角度を計算する。int F2dCleanUpCheckStartEndEntityスタートエンティティおよびエンドエンティティをチェックする。int F2dCleanUpLineAngleラインタイプエンティティの角度を計算する。int F2dCleanUpArcAngle弓形のエンティティの角度を計算する。int F2dCleanUpChangeChildrenFlagエンティティのチルドレンフラグを変更する。int F2dCleanUpChangeArrowVertexFlagアロー頂点のフラグを変更し、アローセンターライン座標を設定する。int F2dCleanUpChangeDrawingColorエンティティの色を変更する。 double F2dCleanUpLineLengthライン型エンティティの長さを計算する。================================================================*/intTestFindArrowControl( int*SwitchRedraw ){//external functionsint F2dCleanUpFindArrow();int F2dCleanUpChangeDrawingColor();struct node_list *F2dCleanUpPickUpAllOneSideOpenEntity();//entities counter and flagsint count = 0,assistant_line_flag= 0;//link list and temp liststruct node_list*Entities_change_color_list1; //Begin//----------------------------------//Step_1://check the number of entites//  get count of all entities// if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;//---------------------------------//Step_3: pickup all one side open entitiesEntities_change_color_list1 = F2dCleanUpPickUpAllOneSideOpenEntity( &trim_drawing );  if (Entities_change_color_list1 == 0)  return 0;//---------------------------------//Step_4: find arrow lineF2dCleanUpFindArrow( Entities_change_color_list1 );//---------------------------------//Step_X://change color to Magenta for a selected boundary    // turn off input levels#ifdefCKWINif ( *SwitchRedraw == 1)ck_levels(CK_OFF,1,255);#endifif ( *SwitchRedraw == 1)F2dCleanUpChangeDrawingColor(&trim_drawing);//clear a flag for outside loop processassistant_line_flag = 0;// turn ON the level usedto store the trimmed entities.#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_ON,TrimLevel, TrimLevel);if ( *SwitchRedraw == 1)ck_redraw( CK_PRIME_VP );#endifreturn count;}/*=================================================================関数： 名称： TestFindOneSideOpen2Control記述：手動関数。 一側がオープンで、ビユーの境界を横切るエンティティを全て見出す。 戻り値：< 0: エラー= 0: プロセスなしパラメータ：副関数：int F2dCleanUpFindOneSideOpenEntity2一側がオープンで、ビユーの境界を横切るエンティティを全て求める。int F2dCleanUpChangeDrawingColorエンティティの色を変更する。================================================================*/intTestFindOneSideOpen2Control( int *SwitchRedraw ){//external functionsint F2dCleanUpFindOneSideOpenEntity2();int F2dCleanUpChangeDrawingColor();//Step_1:check the number of entites// if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;//Step_2:pickup all oneside open entitiesF2dCleanUpFindOneSideOpenEntity2( &trim_drawing );//Step_X:change color to Magenta for a selected boundary    // turn off input levels#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_OFF,1,255);#endifif ( *SwitchRedraw == 1)F2dCleanUpChangeDrawingColor(&trim_drawing);// turn ON the level used to store the trimmed entities.#ifdef CKWINif (*SwitchRedraw == 1)ck_levels(CK_ON,TrimLevel, TrimLevel);if ( *SwitchRedraw == 1)ck_redraw( CK_PRIME_VP );#endifreturn 0;}/*=================================================================関数： 名称： TestFindOneSideOpenControl記述： 手動関数。 ビユーに対して、一側が開放でアロー型エンティティに対して垂直のものを見出す。戻り値：< 0: エラー= 0: プロセスなし> 0: 成功裏に完了; この数は、見出されたエンティティの個数。パラメータ：副関数：struct node_list *F2dCleanUpPickUpAllOneSideOpenEntity一側開放エンティティを求める。int F2dCleanUpChangeChildrenFlagエンティティのチルドレンフラグを変更する。int F2dCleanUpChangeDrawingColorエンティティの色を変更する。int F2dCleanUpFindOneSideOpenEntity一側開放エンティティを求め、それらはアロー型エンティティに対して垂直である。================================================================*/intTestFindOneSideOpenControl( int *SwitchRedraw ){//external functionsint F2dCleanUpFindOneSideOpenEntity();int F2dCleanUpChangeDrawingColor();struct node_list *F2dCleanUpPickUpAllOneSideOpenEntity();//entities counter and flagsint count = 0,assistant_line_flag = 0;//link list and temp liststruct node_list*Entities_list; //Begin//----------------------------------//Step_1://check thenumber of entites// if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;//---------------------------------//Step_2:pickup all one side open entitiesEntities_list = F2dCleanUpPickUpAllOneSideOpenEntity( &trim_drawing );    if (Entities_list == 0)  return 0;//---------------------------------//Step_3: find lines vertical with arrow type entitiesF2dCleanUpFindOneSideOpenEntity( Entities_list );//---------------------------------//Step_X://change color to Magenta for a selected boundary    // turn off input levels#ifdef CKWINif ( *SwitchRedraw== 1)ck_levels(CK_OFF,1,255);#endifif ( *SwitchRedraw == 1)F2dCleanUpChangeDrawingColor(&trim_drawing);//clear a flag for outside loop processassistant_line_flag = 0;// turn ON the level used to store the trimmed entities.#ifdef!160#CKWINif ( *SwitchRedraw == 1)ck_levels(CK_ON,TrimLevel, TrimLevel);if ( *SwitchRedraw == 1)ck_redraw( CK_PRIME_VP );#endifreturn count;}/*=================================================================関数： 名称： F2dCleanUpPickUpAllOneSideOpenEntity記述： 選択図の全ての一側開放エンティティを求める。戻り値：= 0: 成功裏に完了;パラメータ：入力： In_drawing: 図出力：NodeList:全ての一側開放エンティティに対するノードリスト================================================================*/struct node_list *F2dCleanUpPickUpAllOneSideOpenEntity(struct drawing *In_drawing ){//entities counter and flagsint count = 0;//link list and temp liststruct node_list*EntitiesList1,*Out_temp_list; //selected entityand temp entitiesstruct node *entity;//initializeEntitiesList1 =( structnode_list * ) calloc ( 1, sizeof ( struct node_list ));//set a flag forthe boundary entitycount = 0;//check pointer about first entityif ( In_drawing->objects == 0 )  return0;//set a open flagto the node//open_list->car->flags = 1;//set the pointer to output node list//set pointer to first entityfor (entity=In_drawing->objects;      entity && (count<number_trimmed_entities);         entity=entity->next) {if ( entity == NULL )break;if ( entity->no_connected_1 > 0 && entity->no_connected_2 > 0 )continue;if ( entity->no_connected_1 == 0 && entity->no_connected_2 == 0 )continue;        if ( entity->type != CK_LINE )continue;EntitiesList1->car= entity;break;}//set link addressEntitiesList1->cdr = NULL;//---------------------------------//find connected entitiesif ( EntitiesList1 == 0) return 0;    if ( entity == 0 ) return 0;    if ( entity->next == 0 )return EntitiesList1;    for (entity=entity->next;      entity && (count<number_trimmed_entities);         entity=entity->next) {count++;if ( entity  == NULL )break;        if ( entity->type != CK_LINE )continue;if( entity->no_connected_1 > 0 && entity->no_connected_2 > 0 )continue;if( entity->no_connected_1 == 0 && entity->no_connected_2 == 0 )continue;// allocate memory for output node list elementOut_temp_list = ( struct node_list * ) calloc ( 1, sizeof ( struct node_list ));// add this entityto the output node list Out_temp_list->car = entity;// connect to the output node listOut_temp_list->cdr = EntitiesList1;// move the pointer ofoutput node list to the topEntitiesList1 = Out_temp_list;if ( entity->next  == NULL )break;}    if (count>=number_trimmed_entities) return 0;                             else return EntitiesList1;}/*=================================================================関数： 名称： F2dCleanUpPickUpAllArcEntity記述： 選択図の全てのアークエンティティを求める。戻り値：= 0: 成功裏に完了;パラメータ：入力： In_drawing: 図出力：NodeList:全てのアークエンティティに対するノードリスト================================================================*/struct node_list *F2dCleanUpPickUpAllArcEntity(struct drawing *In_drawing ){//entities counter and flagsint count = 0;//link list and temp liststruct node_list*EntitiesList1,*Out_temp_list; //selected entity and temp entitiesstruct node *entity;//initializeEntitiesList1 =( struct node_list * ) calloc ( 1, sizeof ( struct node_list ));//set a flag for the boundary entitycount = 0;//check pointer about first entityif ( In_drawing->objects == 0 )  return0;//set pointer to first entityfor (entity=In_drawing->objects;      entity && (count<number_trimmed_entities);         entity=entity->next) {        if (entity == NULL )break;        if ( entity->type != CK_ARC )continue;EntitiesList1->car = entity;break;}//set link addressEntitiesList1->cdr = NULL;//---------------------------------//find connected entitiesif ( EntitiesList1 == 0 ) return 0;    if ( entity == 0 ) return 0;    if ( entity->next == 0 ) return EntitiesList1;    for (entity=entity->next;entity && (count<number_trimmed_entities);         entity=entity->next){count++;if ( entity == NULL )break;        if ( entity->type != CK_ARC)continue;// allocate memory for output node list elementOut_temp_list =( struct node_list * ) calloc ( 1, sizeof ( struct node_list ));// addthis entity to the output node list Out_temp_list->car = entity;// connect to the output node listOut_temp_list->cdr = EntitiesList1;// move thepointer of output node list to the topEntitiesList1 = Out_temp_list;if( entity->next == NULL )break;}    if (count>=number_trimmed_entities) return 0;                               else return EntitiesList1;}/*=================================================================関数： 名称： F2dCleanUpFindCenterLineEntity記述： アークのセンタラインエンティティを求める。 戻り値：= 0: 成功裏に完了し、何も見出されない。= NUM: 開放エンティティの個数副関数：int F2dCleanUpChangeChildrenFlag未使用エンティティに対してフラグを設定する。doubleF2dDistancePointLineアークの中心点からエンティティまでの距離を計算する。パラメータ：入力： 1 In_Drawing: a図2In_Entities_list: 全てのアークに対するノードリスト================================================================*/int F2dCleanUpFindCenterLineEntity( struct drawing *In_drawing, struct node_list *In_Entities_list ){//external functionsint F2dCleanUpChangeChildrenFlag();doubleF2dDistancePointLine();double F2dCleanUpLineLength();//link list and temp liststruct node_list *temp_list, *temp_list2, *temp_list3, *temp_list4; //selected entity and temp entitiesstruct node *ArcEntity,*ViewEntity;//define 3D coordinates struct VectorVsp, Vep, Vp;//entities counter and flagsintcount = 0;//doubledoubleDistance = 0.0,DistanceViewEntity2Center = 0.0,DX = 0.0,DY = 0.0,ViewEntityLength = 0.0,Tolerance = 0.0;int CountPrompt= 0;charmessage[64];//set toleranceTolerance = F2dCleanUpTolerance;#ifdef VELLUMCountPrompt++;sprintf( message,"Start Find Center Entity %d", CountPrompt );ck_prompt( message );  #endif    // check all of entities which connected with outside loop    for( temp_list=In_Entities_list;  temp_list;  temp_list = temp_list->cdr){ if ( temp_list->car == NULL )break;ArcEntity = temp_list->car;//check all of entities in the viewfor( ViewEntity=In_drawing->objects;  ViewEntity;  ViewEntity = ViewEntity->next){//check flags: only no marks entities if ( ViewEntity->flags !=0 && ViewEntity->flags !=10 )continue;//check type : only line if ( ViewEntity->type != CK_LINE )continue;//check open side: only open lineif ( ViewEntity->no_connected_1 > 0 && ViewEntity->no_connected_2 > 0 )continue;//check open side: two side open line ( delete )if ( ViewEntity->no_connected_1 == 0 && ViewEntity->no_connected_2 == 0&& ViewEntity->line_type != CK_CENTER ){ViewEntity->flags = 3;continue;}//check parent open sideif ( ViewEntity->no_connected_1 == 0&& ViewEntity->line_type != CK_CENTER ){//set center line flags ( look for children )for( temp_list2=ViewEntity->parent->children;  temp_list2 && temp_list2->cdr;  temp_list2 = temp_list2->cdr){//change flag to light grayif ( temp_list2->car == NULL ) break;if ( temp_list2->car->vertex2 == ViewEntity->parent->vertex2 ) break;}if( temp_list2->car->no_connected_2 != 0) continue;}if ( ViewEntity->no_connected_2 == 0&& ViewEntity->line_type != CK_CENTER ){//set center lineflags ( look for children )for( temp_list3=ViewEntity->parent->children;  temp_list3 && temp_list3->cdr;  temp_list3 = temp_list3->cdr){//change flag to light grayif ( temp_list3->car == NULL ) break;if ( temp_list3->car->vertex1 == ViewEntity->parent->vertex1 ) break;}if ( temp_list3->car->no_connected_1 != 0) continue;}//check distance from arc’s centerto line entityVsp.x=ViewEntity->X1;Vsp.y=ViewEntity->Y1;Vsp.z=ViewEntity->Z1;Vep.x=ViewEntity->X2;Vep.y=ViewEntity->Y2;Vep.z=ViewEntity->Z2;Vp.x=ArcEntity->CenterX;Vp.y=ArcEntity->CenterY;Vp.z=ArcEntity->CenterZ;Distance = F2dDistancePointLine( Vsp, Vep, Vp );if ( Distance > Tolerance )continue;//check bounding box : only outside and no touchif (( ViewEntity->parent->Max_X >= ArcEntity->Min_X  && ViewEntity->parent->Max_X <= ArcEntity->Max_X )&& ( ViewEntity->parent->Max_Y >= ArcEntity->Min_Y   &&ViewEntity->parent->Max_Y <= ArcEntity->Max_Y )) {F2dCleanUpChangeChildrenFlag( ViewEntity->parent );continue;}if (( ViewEntity->parent->Min_X >= ArcEntity->Min_X  && ViewEntity->parent->Min_X <= ArcEntity->Max_X )&&( ViewEntity->parent->Min_Y >= ArcEntity->Min_Y   && ViewEntity->parent->Min_Y <= ArcEntity->Max_Y )) {F2dCleanUpChangeChildrenFlag( ViewEntity->parent );continue;}if (( ArcEntity->Max_X >= ViewEntity->parent->Min_X  && ArcEntity->Max_X <= ViewEntity->parent->Max_X )&& ( ArcEntity->Max_Y >= ViewEntity->parent->Min_Y   && ArcEntity->Max_Y <= ViewEntity->parent->Max_Y )) {F2dCleanUpChangeChildrenFlag( ViewEntity->parent );continue;}if (( ArcEntity->Min_X >= ViewEntity->parent->Min_X  && ArcEntity->Min_X <= ViewEntity->parent->Max_X )&& ( ArcEntity->Min_Y >= ViewEntity->parent->Min_Y   && ArcEntity->Min_Y <= ViewEntity->parent->Max_Y )) {F2dCleanUpChangeChildrenFlag( ViewEntity->parent );contiｎｕｅ；}//check distance from arc to entityViewEntityLength = F2dCleanUpLineLength(ViewEntity->parent);DX = 0.5*(ViewEntity->parent->Min_X+ViewEntity->parent->Max_X) -ArcEntity->CenterX;DY = 0.5*(ViewEntity->parent->Min_Y+ViewEntity->parent->Max_Y) - ArcEntity->CenterY;DistanceViewEntity2Center = sqrt(DX*DX+DY*DY) - ArcEntity->Radius - 0.5*ViewEntityLength;if ( DistanceViewEntity2Center <= ViewEntityLength ){F2dCleanUpChangeChildrenFlag( ViewEntity->parent );continue;}//set center line flags ( look for children )for( temp_list4=ViewEntity->parent->children;  temp_list4;  temp_list4 = temp_list4->cdr){//change flag to light grayif ( temp_list4->car == NULL ) break;temp_list4->car->flags = 10;count++;}if ( ViewEntity->next == NULL )break;}}#ifdef VELLUMCountPrompt++;sprintf( message,"Finished find centerEntity %d", CountPrompt );ck_prompt( message );  #endif//normal endreturn count;}/*=================================================================関数： 名称： F2dCleanUpFindInSideEntity記述： アウトサイドループに対するインサイドエンティティを求める。戻り値：= 0: 成功裏に完了し、何も見出されない;= NUM: 開放エンティティの個数副関数:int F2dCleanUpChangeChildrenFlag未使用エンティティに対するフラグを設定する。パラメータ：入力：1 In_Drawing: a図2 In_Entities_list: 外側ループに対するノードリスト================================================================*/int F2dCleanUpFindInSideEntity( struct drawing *In_drawing, struct node_list *In_Entities_list ){//external functionsint F2dCleanUpChangeChildrenFlag();//link list and temp liststruct node_list *temp_list, *temp_list2,*NewNodeList, *NewNodeListTemp; struct group *NewGroup,*temp_group_list; struct bounding_box  *NewBoundBox;//selected entity and temp entitiesstruct node*OutsideEntity,*ViewEntity;//entities counter and flagsint count = 0,NoFlag = 0;//doubledoubleTolerance = 0.0;//set toleranceTolerance = F2dCleanUpTolerance;//initializeNewGroup = (struct group *)calloc(1,sizeof(struct group ));NewBoundBox = (struct bounding_box *)calloc(1,sizeof(structbounding_box ));NewNodeList = (struct node_list *)calloc(1,sizeof(struct node_list ));//set group dataNewGroup->next = NULL;NewGroup->box = NewBoundBox;// check all of entities which connected with outside loop    for( temp_list=In_Entities_list;  temp_list; //&& temp_list->cdr;  temp_list = temp_list->cdr){if ( temp_list->car == NULL ) break;OutsideEntity= temp_list->car;//check entity : only boundary group ( flags = 1 and 4) if ( OutsideEntity->flags != 1 && OutsideEntity->flags != 4 )continue;if ( !OutsideEntity ){NoFlag = 1;break;}NewGroup->box->Min_X = OutsideEntity->Min_X;NewGroup->box->Max_X = OutsideEntity->Max_X;NewGroup->box->Min_Y = OutsideEntity->Min_Y;NewGroup->box->Max_Y = OutsideEntity->Max_Y;break;}if ( NoFlag == 1 )return0;    NewNodeList->car = OutsideEntity;NewNodeList->cdr = NULL;// check first groupif( In_drawing->views == NULL){NewGroup->index = 1;In_drawing->views = NewGroup;}else{//check group number    for( temp_group_list= In_drawing->views;  temp_group_list; //&&temp_group_list->next;  temp_group_list = temp_group_list->next){if ( temp_group_list->next == NULL ){NewGroup->index = (temp_group_list->index)+1;temp_group_list->next = NewGroup;break;}}}    // check connected entity    if ( !temp_list->cdr && temp_list->car->type != CK_ARC )return 0;    // check all of entities which connected with outside loop    if ( temp_list->cdr ){    for( temp_list2 = temp_list->cdr;  temp_list2;// &&temp_list2->cdr;  temp_list2 = temp_list2->cdr){if ( temp_list2->car ==NULL ) break;OutsideEntity = temp_list2->car;//check entity : only boundary group ( flags = 1 and 4 ) if ( OutsideEntity->flags != 1 && OutsideEntity->flags != 4 )continue;if ( NewGroup->box->Min_X > OutsideEntity->Min_X )NewGroup->box->Min_X = OutsideEntity->Min_X;if ( NewGroup->box->Max_X < OutsideEntity->Max_X )NewGroup->box->Max_X = OutsideEntity->Max_X;if ( NewGroup->box->Min_Y > OutsideEntity->Min_Y )NewGroup->box->Min_Y =OutsideEntity->Min_Y;if ( NewGroup->box->Max_Y < OutsideEntity->Max_Y )NewGroup->box->Max_Y = OutsideEntity->Max_Y;//allocate memory for node list NewNodeListTemp = (struct node_list *)calloc(1,sizeof(struct node_list ));//add this entity to node list NewNodeListTemp->car = OutsideEntity;//connect to the node list NewNodeListTemp->cdr = NewNodeList;//move the pointer of the node list to the topNewNodeList = NewNodeListTemp;count++;}}//check all of entities in the viewfor( ViewEntity=In_drawing->objects;  ViewEntity;  ViewEntity = ViewEntity->next){//check flags: only no marks entities if ( ViewEntity == NULL  )break;if ( ViewEntity->flags!=0  )continue;//check bounding box: only inside entities if (( NewGroup->box->Min_X <= ViewEntity->Min_X )  &&( NewGroup->box->Max_X >= ViewEntity->Max_X )  &&( NewGroup->box->Min_Y <= ViewEntity->Min_Y )  &&( NewGroup->box->Max_Y >= ViewEntity->Max_Y )){//set flag ViewEntity->flags = 7;//allocate memory for node list NewNodeListTemp = (struct node_list *)calloc(1,sizeof(struct node_list ));//add this entity to node list NewNodeListTemp->car = ViewEntity;//connect to the node list NewNodeListTemp->cdr = NewNodeList;//move the pointer of the node list to the topNewNodeList = NewNodeListTemp;count++;}}//set node list to group NewGroup->entities = NewNodeList;//normal endreturn count;}/*=================================================================関数： 名称： F2dCleanUpFindOnesideOpenConnectEntityNext記述： 一側オープンエンティティに接続された次のエンティティを求める。戻り値：= Out_entity: 成功裏に完了;パラメータ：入力： 1 In_entity: エンティティ ================================================================*/struct node *F2dCleanUpFindOnesideOpenConnectEntityNext(struct node *In_entity){//selected entity and temp entitiesstructnode *Out_entity;//link list and temp liststruct node_list *TempList1,*TempList2, *TempList3, *NextNodes;//defineintFlag1 = 0,Flag2 = 0,Count= 0;int CountPrompt = 0;charmessage[64];#ifdef VELLUMCountPrompt++;sprintf( message,"Start Find One Side Open Connected Entity %d", CountPrompt);ck_prompt( message );  #endif//initializeOut_entity = NULL;//check input entityif ( !In_entity )returnOut_entity;//check open sidefor( TempList1=In_entity->connected_nodes_1; TempList1; //&& TempList1->cdr; TempList1 = TempList1->cdr){if ( TempList1->car == NULL )break;if ( TempList1->car->flags == 6 )Flag1 = 1;}for( TempList2=In_entity->connected_nodes_2;TempList2; //&& TempList2->cdr; TempList2 = TempList2->cdr){if ( TempList2->car == NULL )break;if ( TempList2->car->flags == 6 )Flag2 = 1;}//first entity caseif ( Flag1 == 0 && Flag2 == 0 )  {if ( In_entity->no_connected_1 == 0 )Flag1 = 1;if ( In_entity->no_connected_2 == 0 )Flag2 = 1;}//finish case: returnif (( Flag1 == 0 && Flag2 == 0 )   ||( Flag1 == 1 && Flag2 == 1 ))returnOut_entity;//check all of entities connected with input entityif ( Flag1 == 1 )NextNodes = In_entity->connected_nodes_2;elseNextNodes = In_entity->connected_nodes_1;for( TempList3= NextNodes; TempList3; //&& TempList3->cdr;  TempList3 = TempList3->cdr){if ( TempList3->car == NULL )break;if ( TempList3->car->flags == 0 ){Out_entity = TempList3->car;Count++;}}//check resultif ( Count != 1 )Out_entity = NULL;#ifdef VELLUMCountPrompt++;sprintf( message,"Finished one side open connected Entity %d", CountPrompt );ck_prompt( message );  #endifreturnOut_entity;}/*=================================================================関数： 名称： F2dCleanUpFindOnesideOpenConnectEntity記述： 一側オープンエンティティおよびそれに接続された単一エンティティを求める。。戻り値：=0: 成功裏に完了;副関数：struct node *F2dCleanUpFindOnesideOpenConnectEntityNext一側開放エンティティに接続された次のエンティティを求める。パラメータ：入力： 1 In_drawing: 図 ================================================================*/int F2dCleanUpFindOnesideOpenConnectEntity(struct drawing *In_drawing){//external functionsstruct node *F2dCleanUpFindOnesideOpenConnectEntityNext();//selected entity and temp entitiesstruct node *entity, *FindEntity, *NextEntity;//check all of entities on the listfor( entity=In_drawing->objects;  entity;  entity = entity->next){if (entity == NULL )break; if ( entity->flags != 0 )continue; if ( entity->type != CK_LINE )continue; if ( entity->no_connected_1 > 0 && entity->no_connected_2 > 0 )continue;if ( entity->no_connected_1 == 0 && entity->no_connected_2 == 0 )continue;if ((entity->no_connected_1 == 0 && entity->no_connected_2 >= 1)  ||(entity->no_connected_2 == 0 && entity->no_connected_1 >= 1)) {//set flagentity->flags =6;FindEntity = entity;//find connected entityfor (;;){NextEntity = F2dCleanUpFindOnesideOpenConnectEntityNext( FindEntity );if ( NextEntity == NULL )break;//set flagFindEntity= NextEntity;FindEntity->flags =6;}}}return 0;}/*=================================================================関数： 名称： F2dCleanUpFindLongestEntity記述： 図に対して最も長いエンティティを求める。戻り値：=  Entity: 成功裏に完了;=  0: エンティティ無し;パラメータ：入力： 1 In_drawing: 図 ================================================================*/struct node *F2dCleanUpFindLongestEntity(struct drawing *In_drawing){//selected entity and temp entitiesstruct node *entity, *LongestEntity;//definedoubleLongestLength = 0.0,ArcLength = 0.0;//check all of entitieson the listfor( entity=In_drawing->objects;  entity;  entity = entity->next){//only not usedif ( entity == NULL )break;if ( entity->flags != 0 )continue;//check lengthif ( entity->parent->length <= LongestLength )continue;  //check arc lengthif ( entity->type == CK_ARC ){ArcLength = 2.0* entity->parent->Radius;if ( entity->parent->length < ArcLength)ArcLength = entity->parent->length;if ( ArcLength > LongestLength ){//change max value and entityLongestLength = ArcLength;LongestEntity = entity;}}else{//change max value and entityLongestLength = entity->parent->length;LongestEntity = entity;}}if ( LongestLength == 0.0 )returnNULL;elsereturnLongestEntity;}/*=================================================================関数： 名称： F2dCleanUpFindViews記述： 図に対するビユーのグループを求める。戻り値：=  Entity: 成功裏に完了;=  0: エンティティなし;副関数：struct node *F2dCleanUpFindLongestEntity図に対する最も長いエンティティを求める。struct node_list *F2dCleanUpFindGroup入力エンティティと接続されたグループエンティティを求める。struct node *F2dCleanUpFindGroupMinXエンティティグループに対する最小Ｘ値を求める。int F2dCleanUpFindOutSideLoopエンティティグループに対する最小Ｘ値を求める。int F2dCleanUpFindInSideEntity外側ループパラメータに対するインサイドエンティティを求める。パラメータ：入力： 1 In_drawing: 図 ================================================================*/int F2dCleanUpFindViews( struct drawing *In_drawing ){//external functionsstruct node *F2dCleanUpFindLongestEntity();struct node_list *F2dCleanUpFindGroup();struct node *F2dCleanUpFindGroupMinX();int F2dCleanUpFindOutSideLoop();int F2dCleanUpFindInSideEntity();//selected entity and temp entitiesstruct node *LongestEntity, *MinXvalueEntity;struct node_list *ViewGroup;//defineint ReturnFlag = 1,NoGroup= 0,Count = 0;doubleLongestLength = 0.0;int CountPrompt = 0;charmessage[64];//check all viewswhile( ReturnFlag ){#ifdef VELLUMCountPrompt++;sprintf( message,"Start Find Views Entity %d", CountPrompt );ck_prompt( message );  #endif//Step_1:find a longest entity for a drawingLongestEntity= F2dCleanUpFindLongestEntity( In_drawing );if ( LongestEntity == NULL )ReturnFlag = 0;else {//set flagNoGroup = 1;  //clear counterCount = 0;//Step_2:find connected group with the longest entityViewGroup = F2dCleanUpFindGroup( LongestEntity, &Count ); //Step_3:find outside loop entities//check a flag for outside loop processif ( Count > 1 )MinXvalueEntity =F2dCleanUpFindGroupMinX( ViewGroup );elseMinXvalueEntity = LongestEntity;if ( MinXvalueEntity == 0 )continue;//Step_4:find outside loop entitiesif ( Count > 1 )F2dCleanUpFindOutSideLoop( MinXvalueEntity );elseMinXvalueEntity->flags = 4;//Step_5:find inside entitiesF2dCleanUpFindInSideEntity( In_drawing, ViewGroup );}#ifdef VELLUMCountPrompt++;sprintf( message,"Finished find view Entity %d", CountPrompt );ck_prompt( message );#endif}if ( NoGroup == 0 )return-1;elsereturn0;}/*=================================================================関数： 名称： F2dCleanUpFindRelativeViews記述： 相対ビユーを求める。 戻り値：= 0: 成功裏に完了;= 1:相対ビ���ーが見出される。パラメータ：入力： 1 In_Drawing: 図2 In_Group:グループ3 In_ToleranceViews: ビユーに対する公差================================================================*/int F2dCleanUpFindRelativeViews(struct drawing*In_drawing,struct group*In_Group,double *In_ToleranceViews ) {//link list and temp liststruct group *TempGroup;struct group_list*TempGroupList; //entities counter and flagsint ReturnFlag = 0;//doubledoubleTolerance = 0.0;//set toleranceTolerance = *In_ToleranceViews;//check viewsif( In_drawing->views == NULL )return0;if( In_Group == NULL )return0;for( TempGroup= In_drawing->views;  TempGroup; //&& TempGroup->next;  TempGroup = TempGroup->next){//check same groupif ( TempGroup == NULL)break;if ( TempGroup == In_Group )continue;//Step_1:check top and bottom directionif ((TempGroup->box->Max_X>=((In_Group->box->Max_X)-Tolerance ))   &&(TempGroup->box->Max_X<=((In_Group->box->Max_X)+Tolerance ))  &&(TempGroup->box->Min_X>=((In_Group->box->Min_X)-Tolerance ))   &&(TempGroup->box->Min_X<=((In_Group->box->Min_X)+Tolerance ))) {//set return flagReturnFlag = 1;//Step_1_1:check top directionif ( TempGroup->box->Min_Y > In_Group->box->Max_Y ){//check top directionrelative viewsif ( In_Group->to_top == NULL ){TempGroupList = (struct group_list *)calloc(1,sizeof(struct group_list ));TempGroupList->car = TempGroup;TempGroupList->cdr = NULL;In_Group->to_top = TempGroupList;}else{//check distanceif ( In_Group->to_top->car->box->Min_Y > TempGroup->box->Min_Y ){//change top viewIn_Group->to_top->car = TempGroup;}}}else//Step_1_2:check bottom directionif ( TempGroup->box->Max_Y < In_Group->box->Min_Y ){//check top directionrelative viewsif ( In_Group->to_bottom == NULL ){TempGroupList = (struct group_list *)calloc(1,sizeof(struct group_list ));TempGroupList->car = TempGroup;TempGroupList->cdr = NULL;In_Group->to_bottom = TempGroupList;}else{//check distanceif ( In_Group->to_bottom->car->box->Max_Y < TempGroup->box->Max_Y ){//change top viewIn_Group->to_bottom->car = TempGroup;}}}}else//Step_2:check left and right directionif ((TempGroup->box->Max_Y>=((In_Group->box->Max_Y)-Tolerance ))   &&(TempGroup->box-!gt#Max_Y<=((In_Group->box->Max_Y)+Tolerance ))  &&(TempGroup->box->Min_Y>=((In_Group->box->Min_Y)-Tolerance ))   &&(TempGroup->box->Min_Y<=((In_Group->box->Min_Y)+Tolerance ))) {//set return flagReturnFlag = 1;//Step_2_1:check right directionif ( TempGroup->box->Min_X > In_Group->box->Max_X ){//check right direction relative viewsif ( In_Group->to_right == NULL ){TempGroupList = (struct group_list *)calloc(1,sizeof(struct group_list ));TempGroupList->car = TempGroup;TempGroupList->cdr = NULL;In_Group->to_right = TempGroupList;}else{//check distanceif ( In_Group->to_right->car->box->Min_X > TempGroup->box->Min_X ){//change left viewIn_Group->to_right->car = TempGroup;}}}else//Step_2_2:check left directionif ( TempGroup->box->Max_X < In_Group->box->Min_X ){//check left directionrelative viewsif ( In_Group->to_left == NULL ){TempGroupList = (struct group_list *)calloc(1,sizeof(struct group_list ));TempGroupList->car = TempGroup;TempGroupList->cdr = NULL;In_Group->to_left = TempGroupList;}else{//check distanceif ( In_Group->to_left->car->box->Max_X < TempGroup->box->Max_X ){//change right viewIn_Group->to_left->car = TempGroup;}}}}}//normal endreturn ReturnFlag;}/*=================================================================関数： 名称： F2dCleanUpFindViewsRelation記述： 図に対するビユー関係を求める。 戻り値：= 0: 成功裏に完了するが、何も見出されない。;=NUM: ビユーの個数副関数：int F2dCleanUpFindRelativeViews相対ビユーを求める。パラメータ：入力： 1 In_Drawing: a図================================================================*/int F2dCleanUpFindViewsRelation( struct drawing*In_drawing ) {//external functionsint F2dCleanUpFindRelativeViews();//link list and temp liststruct group *MaxGroup,*TempGroup,*NextGroup;struct group_list*OpenGroupList,*TempOpenGroupList,*TempGroupList;struct node_list *ETL;//Entity Temp List//entities counter and flagsintNoFlag = 0;//doubledoubleBiggestSize = 0.0, BiggestSizeTemp = 0.0;doubleTolerance = 0.0,ToleranceViews = 0.0;//set toleranceTolerance = F2dCleanUpTolerance;//check viewsif( In_drawing->views == NULL )return0;//Step_1:get the biggest group’s sizefor( TempGroup= In_drawing->views;  TempGroup; //&& TempGroup->next;  TempGroup = TempGroup->next){// clear flagsTempGroup->index = 0;// compute size for boxBiggestSizeTemp = fabs( TempGroup->box->Max_X - TempGroup->box->Min_X )  + fabs( TempGroup->box->Max_Y - TempGroup->box->Min_Y );//check sizeif ( BiggestSizeTemp > BiggestSize ){BiggestSize = BiggestSizeTemp;MaxGroup= TempGroup;}//check last oneif ( TempGroup->next == NULL )break;}//check views toleranceToleranceViews = 0.01 * BiggestSize;if ( ToleranceViews < Tolerance ) ToleranceViews = Tolerance;//Step_2:find relationship for each view//initialize a open list OpenGroupList = (struct group_list *)calloc(1,sizeof(struct group_list ));OpenGroupList->car = MaxGroup;OpenGroupList->cdr = NULL;// seta open flag to the groupMaxGroup->index = 1;for ( TempGroupList = OpenGroupList; TempGroupList; ){//get a pointer from open list if ( TempGroupList->car == NULL )break;NextGroup = TempGroupList->car;//set a closed flag to the groupNextGroup->index = 2;//close the group ( delete the groupfrom open list )OpenGroupList = OpenGroupList->cdr;//get relationNoFlag= F2dCleanUpFindRelativeViews( In_drawing, NextGroup, &ToleranceViews );if ( NoFlag == 0 )break;//check each direction for the viewif ( NextGroup->to_top != NULL ){if ( NextGroup->to_top->car->index == 0 ){TempOpenGroupList = (struct group_list *)calloc(1,sizeof(struct group_list ));TempOpenGroupList->car = NextGroup->to_top->car;TempOpenGroupList->cdr = OpenGroupList;TempOpenGroupList->car->index = 1;OpenGroupList = TempOpenGroupList;}}if ( NextGroup->to_bottom != NULL ){if ( NextGroup->to_bottom->car->index == 0 ){TempOpenGroupList = (struct group_list *)calloc(1,sizeof(struct group_list ));TempOpenGroupList->car = NextGroup->to_bottom->car;TempOpenGroupList->cdr = OpenGroupList;TempOpenGroupList->car->index= 1;OpenGroupList = TempOpenGroupList;}}if ( NextGroup->to_left != NULL){if ( NextGroup->to_left->car->index == 0 ){TempOpenGroupList = (struct group_list *)calloc(1,sizeof(struct group_list ));TempOpenGroupList->car = NextGroup->to_left->car;TempOpenGroupList->cdr = OpenGroupList;TempOpenGroupList->car->index = 1;OpenGroupList = TempOpenGroupList;}}if ( NextGroup->to_right != NULL ){if ( NextGroup->to_right->car->index == 0 ){TempOpenGroupList = (struct group_list *)calloc(1,sizeof(struct group_list ));TempOpenGroupList->car = NextGroup->to_right->car;TempOpenGroupList->cdr = OpenGroupList;TempOpenGroupList->car->index = 1;OpenGroupList= TempOpenGroupList;}}//assign value to the loop variableTempGroupList =OpenGroupList;}              //Step_3:clear flags for no relative groupsfor( NextGroup=In_drawing->views; NextGroup; NextGroup = NextGroup->next){if ( NextGroup == NULL )break;if ( NextGroup->index != 0 )continue;for ( ETL=NextGroup->entities; ETL; ETL=ETL->cdr ) {ETL->car->flags = 0;if ( ETL->cdr == NULL  )break;}}                       //normal endreturn 0;}/*=================================================================関数： 名称： F2dCleanUpFindDrawingSheet記述： 図に対する描画シートを求める。戻り値：= -1: エラーデータ;=  0: 成功裏に完了;=  1: シートなし;副関数：struct node_list *F2dCleanUpFindGroup入力エンティティと接続されたグループエンティティを求める。パラメータ：入力： 1 In_drawing: 図 ================================================================*/int F2dCleanUpFindDrawingSheet(struct drawing*In_drawing,struct bounding_box *InOut_BB,int *In_TimesFlag ){//externalfunctionsstruct node_list *F2dCleanUpFindGroup();//selected entity andtemp entitiesstruct node *entity, *LongestEntityX, *LongestEntityY;struct node_list*SheetGroup, *temp_list2; //bounding boxstruct bounding_box BB, EBB;//defineintSheetFlag = 0, count = 0,CountPrompt = 0;doubleLongestLengthX = 0.0,LongestLengthY = 0.0,AlphaX = 0.0, AlphaY = 0.0;charmessage[64]; doubleTolerance = 0.0;//set toleranceTolerance = F2dCleanUpTolerance;#ifdef VELLUMCountProｍｐｔ＋+;sprintf( message,"Start Find Sheet Entity%d", CountPrompt );ck_prompt( message );  #endif//STEP_1:look for the longest line type parent entity //check all of entities on the listfor( entity=In_drawing->objects;  entity;  entity = entity->next){//only linetypeif ( entity == NULL )break;if ( entity->type != CK_LINE )continue; //only not usedif ( entity->flags != 0 )continue;//check lengthif (( entity->parent->length <= LongestLengthX )  &&( entity->parent->length <= LongestLengthY ))continue;  //check horizontally and vertically //if angle(alpha) was smaller than ( sin ( alpha ) = alpha )AlphaX = fabs( ( entity->parent->Max_X - entity->parent->Min_X )/ entity->parent->length );AlphaY = fabs( ( entity->parent->Max_Y - entity->parent->Min_Y )/ entity->parent->length );if ( ( AlphaX > Tolerance ) && ( AlphaY > Tolerance ) )continue;//change max value and entityif ( AlphaY < Tolerance ){ if ( entity->parent->length > LongestLengthX ){  LongestLengthX = entity->parent->length;LongestEntityX = entity;}}else{ if ( entity->parent->length > LongestLengthY ){  LongestLengthY = entity->parent->length;LongestEntityY= entity;}} #ifdef VELLUM//CountPrompt++;//sprintf( message,"Sheet Entity %d", CountPrompt );//ck_prompt( message );  #endif}//check the longest entitiy’s lengthif (( LongestLengthX < Tolerance )  ||( LongestLengthY < Tolerance ))return-1;               //set bounding boxBB.Min_X = LongestEntityX->parent->Min_X;BB.Max_X = LongestEntityX->parent->Max_X;BB.Min_Y = LongestEntityY->parent->Min_Y;BB.Max_Y = LongestEntityY->parent->Max_Y;//check inside drawing sheet sizeif ( *In_TimesFlag == 1)*InOut_BB= BB;  //set valueselse{if ( (InOut_BB->Min_X == 0.0 ) && (InOut_BB->Max_X == 0.0 ) &&(InOut_BB->Min_Y == 0.0 ) && (InOut_BB->Max_Y == 0.0 )) return0;if (( BB.Max_X - BB.Min_X ) < Tolerance )return0;if ( fabs(( InOut_BB->Max_X - InOut_BB->Min_X ) / ( BB.Max_X - BB.Min_X )) > 1.2 )return0;}//set a flag to entityLongestEntityX->flags = 3; //STEP_2:look for connected entities group and make boundarySheetGroup = F2dCleanUpFindGroup( LongestEntityX, &count);if ( SheetGroup == 0 )return0;//STEP_3:clear flagsfor all entitiesfor(entity=In_drawing->objects;  entity;  entity = entity->next){if ( entity == NULL )break;if ( entity->flags == 3 )continue;if ( entity->flags ==4 )continue;entity->flags = 0; }//STEP_4:set flags the groupfor ( temp_list2 = SheetGroup; ( temp_list2!=0 &&        temp_list2->car!=0 );  temp_list2=temp_list2->cdr){if ( temp_list2->car == NULL )break;temp_list2->car->flags = 3; }//STEP_5:set expanding box ( 20% for +X,-X,+Y,-Y)EBB.Min_X = ( BB.Min_X ) - 0.2 * fabs(( BB.Max_X ) - ( BB.Min_X ));EBB.Max_X = ( BB.Max_X ) + 0.2 * fabs(( BB.Max_X ) - ( BB.Min_X ));EBB.Min_Y= ( BB.Min_Y ) - 0.2 * fabs(( BB.Max_Y ) - ( BB.Min_Y ));EBB.Max_Y = (BB.Max_Y ) + 0.2 * fabs(( BB.Max_Y ) - ( BB.Min_Y ));//STEP_6:check outside entity( out of the bounding box ) in the DRAWING//if any entity wasfound, no sheet was found for this drawingfor( entity=In_drawing->objects;  entity;  entity = entity->next){if ( entity == NULL )break; if ( entity->flags != 0 )continue;//look for out side entity if ( entity->Max_X> EBB.Max_X ){ SheetFlag = 1;break;}if ( entity->Max_Y > EBB.Max_Y ){ SheetFlag = 1;break;}if ( entity->Min_X < EBB.Min_X ){ SheetFlag = 1;break;}if ( entity->Min_Y < EBB.Min_Y ){ SheetFlag = 1;break;}}//STEP_7:lookfor sheet data ( out side of the boundary )if ( SheetFlag == 0 ){//lookfor sheet data for( entity=In_drawing->objects;  entity;  entity = entity->next){if ( entity == NULL )break; if ( entity->flags == 3 )entity->flags = 4; if ( entity->flags != 0 )continue; if (( entity->Min_X <= BB.Min_X )||( entity->Max_X >= BB.Max_X )  ||( entity->Min_Y <= BB.Min_Y )||(entity->Max_Y >= BB.Max_Y ))//set flagentity->flags =4;}//Goodreturn 0;}//STEP_8:clear flags ( No sheet was found ! )for( entity=In_drawing->objects;  entity;  entity = entity->next){if ( entity == NULL )break;if (entity->flags == 4 )continue; entity->flags = 0; }if ( SheetFlag != 0 )return 1;#ifdef VELLUMCountPrompt++;sprintf( message,"Finished find SheetEntity %d", CountPrompt );ck_prompt( message );  #endifreturn 0;}/*=================================================================関数： 名称： TestFindDrawingSheetControl 記述： 手動関数。図に対する描画シートを求める。戻り値：< 0: エラー= 0: プロセスなし> 0: 成功裏に完了；個数は見出されたエンティティのカウンタ値である。パラメータ：副関数：int F2dCleanUpFindDrawingSheet成功裏に完了；個数は見出されたエンティティのカウンタ値である。intF2dCleanUpChangeDrawingFlagエンティティのフラグを変更する( 4 >>3 )================================================================*/intTestFindDrawingSheetControl( int *SwitchRedraw ){//external functionsint F2dCleanUpFindDrawingSheet();int F2dCleanUpChangeDrawingColor();intF2dCleanUpChangeDrawingFlag();//definestruct bounding_box BB;intReturnFlag= 0; intTimesFlag = 0;//----------------------------------//Step_1:check the number of entites// if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;//---------------------------------//Step_2: find center line entitiesTimesFlag = 1;ReturnFlag = F2dCleanUpFindDrawingSheet( &trim_drawing, &BB, &TimesFlag );if( ReturnFlag == 1 ) return 0;if( ReturnFlag== -1 ) return 0;TimesFlag = 2;F2dCleanUpFindDrawingSheet( &trim_drawing, &BB, &TimesFlag );//---------------------------------//Step_3: changeflagsF2dCleanUpChangeDrawingFlag( &trim_drawing );//---------------------------------//Step_X:change color to light gray for a selected center lines    // turn off input levels#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_OFF,1,255);#endifif ( *SwitchRedraw == 1)F2dCleanUpChangeDrawingColor(&trim_drawing);// turn ON the level used to store the trimmed entities.#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_ON,TrimLevel, TrimLevel);//if ( *SwitchRedraw == 1)ck_redraw( CK_PRIME_VP );#endifreturn0;}/*=================================================================関数： 名称： TestFindViewsControl 記述： 手動関数。 図に対する描画シートを求める。戻り値：< 0: 図= 0: プロセスなし> 0: 成功裏に完了; 個数は見出されたエンティティのカウンタ値である。パラメータ：副関数：int F2dCleanUpFindViews図に対するビューのグループを求める。int F2dCleanUpFindViewsRelation図に対するビュー関係を求める。int F2dCleanUpChangeDrawingColor================================================================*/intTestFindViewsControl( int *SwitchRedraw ){//external functionsint F2dCleanUpFindViews();int F2dCleanUpFindViewsRelation();int F2dCleanUpChangeDrawingColor();//Step_1:check the number of entites// if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;//Step_2: find views’ group if ( F2dCleanUpFindViews( &trim_drawing ) ==  -1 ) return -1;//Step_3: find views’ relationship //move to delete function ( Mar. 29,1996 )//F2dCleanUpFindViewsRelation( &trim_drawing );//Step_X:change colorto light gray for a selected center lines    // turn off input levels#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_OFF,1,255);#endifif ( *SwitchRedraw == 1)F2dCleanUpChangeDrawingColor(&trim_drawing);// turn ON the level used to store the trimmed entities.#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_ON,TrimLevel, TrimLevel);if ( *SwitchRedraw == 1)ck_redraw( CK_PRIME_VP );#endifreturn 0;}/*=================================================================関数： 名称： TestFindBoundaryControl記述： 手動関数。 ユーザがビユーの境界のエンティティを選択したとき、この関数はビユーに対する接続されたエンティティの全てを見出す。戻り値：< 0:エラー= 0: プロセスなし> 0: 成功裏に完了; 成功裏に完了パラメータ：副関数：int F2dCleanUpFindOutSideLoopサイ���ループのエンティティを求める。int F2dCleanUpFindInSideEntity外側ループに対するサイドエンティティを求める。int F2dCleanUpFindOutNextEntity外側ループエンティティと接続されたエンティティを求める。struct node *F2dCleanUpFindGroupMinXエンティティグループに対する最小Ｘ値を求める。struct node_list *F2dCleanUpFindGroup入力エンティティと接続されたグループエンティティを求める。ystruct node *F2dCleanUpInputEntity ( old function )画面上の選択されたエンティティを求める。intF2dCleanUpLineAngleライン形エンティティの角度を計算する。int F2dCleanUpArcAngleアーク形エンティティの角度を求める。int F2dCleanUpChangeChildrenFlagエンティティのチルドレンフラグを変更する。int F2dCleanUpChangeArrowVertexFlagアロートップ頂点のフラグを変更し、アローセンタライン座標を設定する。int F2dCleanUpFindViewsRelationl図に対するビユー関係を求める。int F2dCleanUpChangeColorエンティティの色を変更する。 double F2dCleanUpLineLengthライン形エンティティの長さを計算する。================================================================*/intTestFindBoundaryControl( int *SwitchRedraw ){//external functions                                int F2dCleanUpChangeDrawingColor();int F2dCleanUpFindOutSideLoop();int F2dCleanUpFindInSideEntity();int F2dCleanUpFindViewsRelation();struct node *F2dCleanUpInputEntity();struct node *F2dCleanUpFindGroupMinX();struct node_list *F2dCleanUpFindGroup();//entities counter and flagsint count = 0;//link list and temp liststruct node_list *Entities_list; //selected entity and temp entitiesstruct node  *entity,*MinXvalueEntity;//Begin//----------------------------------//Step_1://check the number of entites//  get count of all entities// if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;for( ; ; ){//---------------------------------//Step_2:select one entityentity = F2dCleanUpInputEntity( "Select aBoundary Entity for a view",&trim_drawing);if ( entity == 0 )return0;if( entity->flags != 0 )continue;//---------------------------------//Step_3: find a connected entities groupEntities_list = F2dCleanUpFindGroup(entity, &count );//---------------------------------//Step_4:find outside loop entities without assistant entities//check a flag for outside loop processif ( count < 1 )continue;MinXvalueEntity = F2dCleanUpFindGroupMinX( Entities_list);if ( MinXvalueEntity == 0 )continue;//---------------------------------//Step_5:find outside loop entitiesF2dCleanUpFindOutSideLoop( MinXvalueEntity );//---------------------------------//Step_6:find inside entitiesF2dCleanUpFindInSideEntity( &trim_drawing, Entities_list );//---------------------------------//Step_7: find views’ relationship //move delete function (Mar.29, 1996 By Ji )//F2dCleanUpFindViewsRelation( &trim_drawing );//---------------------------------//Step_X:change color to Magenta for a selected boundary    // turn off input levels#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_OFF,1,255);#endifF2dCleanUpChangeDrawingColor(&trim_drawing);// turn ON the level used to storethe trimmed entities.#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_ON,TrimLevel, TrimLevel);if ( *SwitchRedraw == 1)ck_redraw( CK_PRIME_VP );#endif}return count;}/*=================================================================関数： 名称： TestFindCenterLineControl記述： 手動関数。ビユー中の全てのアークに対するセンタラインを見出す。戻り値：< 0: エラー= 0: プロセスなし> 0: 成功理に完了; 成功理に完了パラメータ：副関数：struct node_list *F2dCleanUpPickUpAllArcEntity選択された図中の全てのアークエンティティを求める。int F2dCleanUpChangeDrawingColorエンティティの色を変更する。================================================================*/intTestFindCenterLineControl( int *SwitchRedraw ){//external functionsint F2dCleanUpFindCenterLineEntity();int F2dCleanUpChangeDrawingColor();struct node_list *F2dCleanUpPickUpAllArcEntity();//link list and templiststruct node_list*Entities_list; //Begin//----------------------------------//Step_1:check the number of entites// if an error occurred, exitimmidiately.    if (number_of_entities<0)  return -1;//---------------------------------//Step_2: pickup all arc entitiesEntities_list = F2dCleanUpPickUpAllArcEntity( &trim_drawing );    if (Entities_list == 0)  return 0;//---------------------------------//Step_3: find center line entitiesF2dCleanUpFindCenterLineEntity( &trim_drawing, Entities_list );//---------------------------------//Step_X:change color to light gray for aselected center lines    // turn off input levels#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_OFF,1,255);#endifif ( *SwitchRedraw == 1)F2dCleanUpChangeDrawingColor(&trim_drawing);// turn ON the level used to store the trimmed entities.#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_ON,TrimLevel, TrimLevel);if ( *SwitchRedraw == 1)ck_redraw( CK_PRIME_VP);#endifreturn 0;}/*=================================================================関数： 名称： TestFindOneSideOpenConnectControl 記述： 手動関数。 一側オープン接続エンティティを見出す。戻り値：< 0: エラー= 0: プロセスなし> 0: 成功裏に完了; 数は見出されたエンティティのカウンタ値である。パラメータ：副関数：int F2dCleanUpFindOnesideOpenConnectEntity一側開放接続エンティティを求める。================================================================*/intTestFindOneSideOpenConnectControl( int *SwitchRedraw ){//external functionsint F2dCleanUpFindOnesideOpenConnectEntity();int F2dCleanUpChangeDrawingColor();//----------------------------------//Step_1:check the number of entites// if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;//---------------------------------//Step_2: find center line entitiesF2dCleanUpFindOnesideOpenConnectEntity( &trim_drawing );//---------------------------------//Step_X:change color to light gray for a selected center lines    // turn off input levels#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_OFF,1,255);#endifif ( *SwitchRedraw == 1)F2dCleanUpChangeDrawingColor(&trim_drawing);// turn ON the level used to store the trimmed entities.#ifdef CKWINif( *SwitchRedraw == 1)ck_levels(CK_ON,TrimLevel, TrimLevel);if ( *SwitchRedraw == 1)ck_redraw( CK_PRIME_VP );#endifreturn 0;}/*=================================================================関数： 名称： TestFindSameColorControl記述： 手動関数。同じ色のエンティティを見出す。戻り値：= 0:成功裏に完了；数は見出されたエンティティのカウンタ値である。パラメータ：副関数：struct node *F2dCleanUpInputEntity ( old function )画面上の選択されたエンティティを求める。int F2dCleanUpFindSameColorEntity選択されたエンティティにより同じ色のエンティティを求める。int F2dCleanUpChangeDrawingColorエンティティの色を変更する。================================================================*/intTestFindSameColorControl(){//externalfunctionsint F2dCleanUpChangeDrawingColor();int F2dCleanUpFindSameColorEntity();struct node *F2dCleanUpInputEntity();//selected entity and tempentitiesstruct node*entity;//Begin//----------------------------------//Step_1://check the number of entites// if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;for( ; ; ){//---------------------------------//Step_2:select one entityentity = F2dCleanUpInputEntity( "Select a Unuse Color Entity",&trim_drawing);if ( entity == 0 )return0;if ( entity->flags != 0 )continue;//---------------------------------//Step_3: find a connected entities groupF2dCleanUpFindSameColorEntity( entity, &trim_drawing );//---------------------------------//Step_X:change color to Magenta for a selected boundary    // turn off input levels#ifdef CKWIN    ck_levels(CK_OFF,1,255);#endifF2dCleanUpChangeDrawingColor(&trim_drawing);// turn ON the level used to store the trimmed entities.#ifdef CKWIN    ck_levels(CK_ON,TrimLevel, TrimLevel);if ( *SwitchRedraw == 1)ck_redraw( CK_PRIME_VP );#endif}return 0;}/*=================================================================関数： 名称： TestFindSelectSingleControl記述： 手動関数。使用エンティティを見出す。戻り値：= 0:成功裏に完了; パラメータ：副関数：struct node *F2dCleanUpInputEntity (古い関数 )画面上の選択されたエンティティを求める。================================================================*/intTestFindSelectSingleControl(){//external functionsstruct node *F2dCleanUpInputEntity();//selectedentity and temp entitiesstruct node*entity;//entity’s specifitysCK_ENTATTattr;//specificity of entities//Begin//----------------------------------//Step_1:check the number of entites// if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;for( ; ; ){//---------------------------------//Step_2:select one entityentity = F2dCleanUpInputEntity( "Select an Unuse Entity", &trim_drawing);if ( entity == 0 )return0;//---------------------------------//Step_3: change flagif ( entity->flags == 7 ){entity->flags = 0;attr.color      = CK_BLUE;      }elseif ( entity->flags == 0 ){entity->flags = 7;attr.color      = CK_YELLOW;}elsereturn0;//---------------------------------//Step_X:change color tolight gray for unuse entity    // turn off input levels//    ck_levels(CK_OFF,1,255);ck_setattr( entity->id, CK_COLOR, NULL, &attr );// turn ONthe level used to store the trimmed entities.//    ck_levels(CK_ON,TrimLevel, TrimLevel);ck_redraw( CK_PRIME_VP );}return 0;}/*=================================================================関数： 名称： TestUnselectSingleControl記述： 手動関数。使用エンティティをクリアする。戻り値：=0: 成功裏に完了;パラメータ：副関数：struct node *F2dCleanUpInputEntity (old function )画面上の選択されたエンティティを求める。================================================================*/intTestUnselectSingleControl(){//external functionsstruct node *F2dCleanUpInputEntity();//selected entity and temp entitiesstruct node*entity;//entity’s specifitysCK_ENTATTattr;//specificity of entities//Begin//----------------------------------//Step_1:check the number of entites// if an error occurred, exitimmidiately.    if (number_of_entities<0)  return -1;for( ; ; ){//---------------------------------//Step_2:select one entityentity = F2dCleanUpInputEntity( "Select an Entity to release",&trim_drawing);if ( entity == 0 )return0;//---------------------------------//Step_3: change flagif( entity->flags != 3&& entity->flags != 4 && entity->flags != 10 ) continue;entity->flags = 0;//---------------------------------//Step_X:changecolor to light gray for unuse entity    // turn off input levels    ck_levels(CK_OFF,1,255);attr.color = entity->color;ck_setattr( entity->id,CK_COLOR, NULL, &attr );// turn ON the level used to store the trimmed entities.    ck_levels(CK_ON,TrimLevel, TrimLevel);ck_redraw( CK_PRIME_VP);}return 0;}/*=================================================================関数： 名称： TestClearKeepFlagsControl記述： 手動関数。全ての選択されたエンティティを戻す。戻り値：= 0: 成功裏に完了;パラメータ：副関数：int F2dCleanUpClearDrawingKeepFlagsエンティティの色を元に変更するが、フラグは維持する。================================================================*/intTestClearKeepFlagsControl( int *SwitchRedraw ){//external functionsint F2dCleanUpClearDrawingKeepFlags();//Begin//----------------------------------//check the number of entites// if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;//---------------------------------    // turn off input levels                         #ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_OFF,1,255);#endifF2dCleanUpClearDrawingKeepFlags(&trim_drawing);if ( *SwitchRedraw == 1)ck_redraw( CK_PRIME_VP );// turn ON the level used tostore the trimmed entities.#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_ON,TrimLevel, TrimLevel);if ( *SwitchRedraw == 1)ck_redraw( CK_PRIME_VP );#endifreturn0;}/*=================================================================関数： 名称： TestClearControl記述： 手動関数。全ての選択されたエンティティを元に戻す。戻り値：= 0: 成功裏に完了;パラメータ：副関数：int F2dCleanUpClearDrawingEntityエンティティの色を元に戻す。================================================================*/intTestClearControl( int *SwitchRedraw ){//external functionsint F2dCleanUpClearDrawingEntity();//Begin//----------------------------------//check the number of entites// if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;//---------------------------------    // turn off input levels#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_OFF,1,255);#endifF2dCleanUpClearDrawingEntity(&trim_drawing);// turn ON the levelused to store the trimmed entities.#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_ON,TrimLevel, TrimLevel);if ( *SwitchRedraw == 1)ck_redraw(CK_PRIME_VP );#endifreturn0;}/*=================================================================関数： 名称： TestDeleteControl記述： 手動関数。全ての選択されたエンティティを削除する。戻り値：= 0: Completed successfully;パラメータ：副関数：int F2dCleanUpDeleteDrawingEntity全てエンティティを削除する。================================================================*/intTestDeleteControl( int *SwitchRedraw ){//external functionsint F2dCleanUpDeleteDrawingEntity();//Begin//----------------------------------//check the number of entites// if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;       //Step_7: find views’ relationship //move from find boundary function (Mar.29, 1996 By Ji)F2dCleanUpFindViewsRelation( &trim_drawing );//---------------------------------#ifdef CKWIN                                        if ( *SwitchRedraw == 1)ck_levels(CK_OFF,1,255);#endif// turn ON the level used tostore the trimmed entities.F2dCleanUpDeleteDrawingEntity(&trim_drawing);#ifdef VELLUMif ( *SwitchRedraw == 1)F2dCleanUpChangeDrawingColor(&trim_drawing);#endif#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_ON,TrimLevel, TrimLevel);if ( *SwitchRedraw == 1)ck_redraw( CK_PRIME_VP );#endifreturn0;}/*=================================================================関数： 名称： TestBackColorControl記述： 元に戻す。戻り値：= 0: 成功裏に完了;パラメータ：副関数：int F2dCleanUpUndo元に戻す。================================================================*/                                          intTestBackColorControl( int *SwitchRedraw ){//external functionsint F2dCleanUpChangeDrawingColor();if( *SwitchRedraw == 1)F2dCleanUpChangeDrawingColor(&trim_drawing);return0;}/*=================================================================関数： 名称： TestUndoControl記述： 元に戻す。戻り値：= 0: 成功裏に完了;パラメータ：副関数：int F2dCleanUpUndo元に戻す。================================================================*/intTestUndoControl( int *SwitchRedraw ){//external functionsint F2dCleanUpUndo();//check the number of entites :  if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;//Step_1: get flags if ( F2dCleanUpUndo( &trim_drawing) == 0 ) return 0;#ifdef CKWIN                                        if ( *SwitchRedraw == 1)ck_levels(CK_OFF,1,255);#endif// turn ON the level used to store the trimmed entities.#ifdef VELLUMif ( *SwitchRedraw ==1)F2dCleanUpChangeDrawingColor(&trim_drawing);#endif#ifdef CKWINif ( *SwitchRedraw == 1)ck_levels(CK_ON,TrimLevel, TrimLevel);if ( *SwitchRedraw== 1)ck_redraw( CK_PRIME_VP );#endifreturn0;}/*=================================================================関数： 名称： TestUndoPreControl記述： 元に戻す準��をする。戻り値：= 0: 成功裏に完了; パラメータ：副関数：int F2dCleanUpUndoPre元に戻す準備をする。================================================================*/intTestUndoPreControl( int *SwitchRedraw ){//external functionsint F2dCleanUpUndoPre();//check the numberof entites: if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;//Step_1: get flags F2dCleanUpUndoPre( &trim_drawing );return0;}/*=================================================================関数： 名称： TestSetUndoFlagViewsControl記述： 元に戻すためフラグを設定する。flag=0:ビューが存在しない。flag=1: ビューが存在する。戻り値：= 0: 成功裏に完了; パラメータ：================================================================*/intTestSetUndoFlagViewsControl( int *SwitchRedraw ){    //set flag    F2dCleanUpExcutedNo = 1;    return0;}/*関数：================================================================名称：TestDeleteViewsControl記述： ビユーを削除する。戻り値：= 0: 成功裏に完了; パラメータ：副関数：int F2dCleanUpDeleteViewsビユーを削除する。================================================================*/intTestDeleteViewsControl( int *SwitchRedraw ){//external functionsint F2dCleanUpDeleteViews();//check the number of entites: if an error occurred, exit immidiately.    if (number_of_entities<0)  return -1;//delete views F2dCleanUpDeleteViews( &trim_drawing );return0;}struct node  *F2dCleanUpInputEntity(char *prompt, struct drawing *select_drawing){int etype, count, stat;unsigned long entid;struct node  *entity;//CK_ENTATT attr;if (( ck_getent(prompt, &etype, &entid) != CK_NOERROR) || ( stat == CK_BACKUP ) || (stat == CK_ESCAPE )) return 0;#ifdef DEBUGprint("ID: %ld; #",entid);#endifcount=0;    for (entity=select_drawing->objects;          entity && (count<number_trimmed_entities) && (entity->id !=entid) && (entity->highlighted_id !=entid);          entity=entity->next)             count++;  if (count>=number_trimmed_entities) return 0;       else return entity;}/*=================================================================関数： 名称： F2dVector記述： ラインのユニットベクトルを計算する。戻り値：= Out_v: 成功裏に完了;パラメータ：入力： 1 In_sp: ラインエンティティ開始点座標2 In_ep: インエンティティ終了点座標出力：1Out_v: ラインエンティティベクトル================================================================*/struct Vector F2dVector( struct Vector In_sp, struct Vector In_ep ){struct VectorOut_v;Out_v.x = In_ep.x - In_sp.x;Out_v.y = In_ep.y - In_sp.y;Out_v.z = In_ep.z - In_sp.z;returnOut_v;}/*=================================================================関数： 名称： F2dVectorUnit記述： ラインのユニットベクトルを計算する。戻り値：= Out_n: 成功裏に完了;< 0: エラーパラメータ：入力： 1 In_v: ラインエンティティベクトル 出力：1 Out_n: ラインエンティティユニットベクトル=================================================================*/struct VectorF2dVectorUnit(struct VectorIn_v){struct VectorOut_n;doubleLength = 0.0;//tolerancedoubletolerance = 0.0;tolerance = F2dCleanUpTolerance;Length = sqrt( In_v.x*In_v.x + In_v.y*In_v.y + In_v.z*In_v.z );//check lengthif (Length < tolerance )returnOut_n;Out_n.x = In_v.x / Length;Out_n.y = In_v.y / Length;Out_n.z = In_v.z / Length;returnOut_n;}/*=================================================================関数： 名称： F2dDistancePointLine記述： 点からラインまでの距離を計算する。戻り値：= 0: 成功裏に完了;パラメータ：入力： 1 In_sp: ラインエンティティ開始点座標2 In_ep: ラインエンティティ終了点座標3 In_p:  点座標出力：1 Out_d: 距離 ================================================================*/doubleF2dDistancePointLine(//inputstruct Vector In_sp, struct Vector In_ep, struct Vector In_p ){//external functionsstruct Vector F2dVector();struct Vector F2dVectorUnit();//definestruct VectorVe, Vne, Vp;double Out_d=0.0;//get vectorVe = F2dVector( In_sp, In_ep );Vp = F2dVector( In_sp, In_p );//get unitvectorVne = F2dVectorUnit( Ve );//compute distanceOut_d = sqrt( Vp.x*Vp.x  + Vp.y*Vp.y-(Vp.x*Vne.x + Vp.y*Vne.y) * (Vp.x*Vne.x + Vp.y*Vne.y) );return  Out_d;}
付録Ｅ
ベンドモデルビユワ実施の例; CBendCADViewPartメンバ関数の実施およびメニュー駆動関数の実施を含む。
【０２９５】
//#include "stdafx.h"// include all BMAPI files#include "ALLBMAPI.HXX"//RW_DRAW library include file.#include "RW_DRAW.HXX"#include "BendCAD.h"#include "BendCADDoc.h"#include "BendCADViewPart.h"// RenderWare includefiles; found in \rwwin\include#include "rwlib.h"// OpenGL include files.#include "gl\gl.h"#include "gl\glu.h"// GL_LIST library include file.#include "GL_LIST.HXX"#include <stdlib.h>   // Orthoview dialog include file#include "OrthoViewDlg.h"/////////////////////////////////////////////////////////////////////////////#define WINDOWTITLE "BAJA CAD SYSTEM"static void multiply_pt_by_matrix(BM_POINT *point, float rot_matrix[4][4]);static RwClump * RWCALLBACK do_transformations(RwClump *clump, void *matrix);static RwClump * RWCALLBACK clear_scene(RwClump *clump);static RwPolygon3d * RWCALLBACK SetPolygonColor(RwPolygon3d *polygon, void *color);// The following variables are defined to set up the color palette of the screen.unsigned char threeto8[8] = {0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377};unsigned char twoto8[4] = {0, 0x55, 0xaa, 0xff};unsigned char oneto8[2] = {0, 255};static int defaultOverride[13] ={0, 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91};static PALETTEENTRY defaultPalEntry[20] = {{ 0,   0,   0,    0 },{ 0x80,0,   0,    0 },{ 0,   0x80,0,    0 },{ 0x80,0x80,0,    0 },{ 0,   0,   0x80, 0 },{ 0x80,0,   0x80, 0 },{ 0,   0x80,0x80, 0 },{ 0xC0,0xC0,0xC0, 0 },{ 192, 220,192,  0 },{ 166, 202, 240,  0 },{ 255, 251, 240,  0 },{ 160, 160, 164,0 },{ 0x80,0x80,0x80, 0 },{ 0xFF,0,   0,    0 },{ 0,   0xFF,0,    0 },{0xFF,0xFF,0,    0 },{ 0,   0,   0xFF, 0 },{ 0xFF,0,   0xFF, 0 },{ 0,   0xFF,0xFF, 0 },{ 0xFF,0xFF,0xFF, 0 }};void PrintString(char *s){}// Thisfunction initializes the RenderWare library, creates a scene, camera andlight.int CBendCADViewPart::Init3D(HWND window) {BOOL berr = FALSE;// Open the RenderWare library.    if (!RwOpen("MSWindows", NULL))    {    ::MessageBox(window,                   "Could not open the RenderWare library",                   WINDOWTITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);        return 0;    }// Create a camera.RwInt32 x_size, y_size;x_size = GetSystemMetrics(SM_CXFULLSCREEN); // The camera should be ableto displayy_size = GetSystemMetrics(SM_CYFULLSCREEN); // on the maximumsize allowed by the screen.    m_camera = RwCreateCamera(x_size, y_size, NULL);if( ! m_camera) {    ::MessageBox(window, "Could not create camera",                    WINDOWTITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);    return 0;}else {  RwSetCameraProjection(m_camera, rwPARALLEL);   RwWCMoveCamera(m_camera, 0.0f, 0.0f, 10000.0f); // Move camera far away from xy plane.  RwSetCameraViewport(m_camera, 0, 0, x_size, y_size); // Default sizes of viewing volume      RwSetCameraViewwindow(m_camera, (float)(x_size), (float)(y_size)); // and viewport.}// Create a scene.    m_scene = RwCreateScene();    if (m_scene == NULL)    {        RwDestroyCamera(m_camera);        m_camera = NULL;        RwClose();        ::MessageBox(window, "Could not create the 3D Scene",                   WINDOWTITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);        return 0;    }// Createlights.m_lights.RemoveAll();RwLight* light1 = RwCreateLight(rwDIRECTIONAL, 0.7f, -0.7f, -0.7f, 0.8f); //- good cornerRwLight* light2 = RwCreateLight(rwDIRECTIONAL, -1.0f, 1.0f, -1.0f, 0.25f);RwLight* light3 = RwCreateLight(rwPOINT, CREAL(0.0), CREAL(0.0), CREAL(0.0), CREAL(1.0));if(light1)  {m_lights.Add(light1);RwAddLightToScene(m_scene, light1);}elseberr= TRUE;if(light2)  {m_lights.Add(light2);RwAddLightToScene(m_scene, light2);}elseberr = TRUE;if(light3)  {m_lights.Add(light3);RwAddLightToScene(m_scene, light3);}elseberr = TRUE;if (berr) AfxMessageBox("Could not create light source");//RwSetLightState(m_light, rwON);//RwSetLightColor(m_light, CREAL(1.0), CREAL(1.0), CREAL(1.0));return 1;}// This function is used by the document class to initialize certain // parameters whenever a new part is loaded. What we do here is compute the centroid,// prepare RenderWare clumps and show the part as requested - wireframe/shaded if show_solid is 0/1,// flat/3d version of part if show_3d is 0/1.void CBendCADViewPart::new_part_init(int show_solid, int show_3d){  int i;  BM_PART *part = NULL;  CBendCADDoc* pDoc = GetDocument();  ASSERT_VALID(pDoc);  part = pDoc->get_part();  if(! part) {    mi_part_is_up_to_date = 0;  return;  }  mi_part_is_up_to_date = 1;  compute_part_centroid(part, 0, &m_flat_part_centroid); // Compute 3d and flat part centroids.  compute_part_centroid(part, 1, &m_3d_part_centroid);   m_part_centroid = m_3d_part_centroid;  mi_show_3d = show_3d;               mi_show_solid = show_solid;            // Clear out any RenderWare clumps around.  if(m_flat_base_clump) {    RwRemoveClumpFromScene(m_flat_base_clump);    RwDestroyClump(m_flat_base_clump);    m_flat_base_clump = NULL;  }  if(m_3d_base_clump) {    RwRemoveClumpFromScene(m_3d_base_clump);    RwDestroyClump(m_3d_base_clump);    m_3d_base_clump = NULL;  }  m_base_clump = NULL;  if(mi_show_3d) {     // Prepare 3d solid or 3d wireframe.    m_part_centroid = m_3d_part_centroid;  if(! mi_show_solid) {   // Prepare wireframe.      i =  prepare_display_list(part, mi_show_3d, 1, 0, 1, 1, md_face_color, md_bendline_color);      if(! i) {        mi_display_list_is_up_to_date = 0;      return;      }      mi_display_list_is_up_to_date = 1;      mi_3d_is_up_to_date = 1;    mi_flat_is_up_to_date = 0;  }  else {         // Prepare solid.      i = facet_part_rw(part, &m_3d_base_clump, mi_show_3d, md_part_color);    if( (! i) || (! m_3d_base_clump) ) return;    m_base_clump = m_3d_base_clump;    RwAddClumpToScene(m_scene, m_base_clump);      mi_display_list_is_up_to_date = 0;      mi_3d_is_up_to_date = 0;    mi_flat_is_up_to_date = 0;  }  }      else {           // Prepare flat solid or flat wireframe.    m_part_centroid = m_flat_part_centroid;   if(! mi_show_solid) {   // Prepare wireframe.      i =  prepare_display_list(part, mi_show_3d, 1, 0, 1, 1, md_face_color, md_bendline_color);      if(! i) {        mi_display_list_is_up_to_date = 0;      return;      }      mi_display_list_is_up_to_date = 1;      mi_flat_is_up_to_date = 1;      mi_3d_is_up_to_date = 0;  }  else {         // Preparesolid.      i = facet_part_rw(part, &m_flat_base_clump, mi_show_3d, md_part_color);    if( (! i) || (! m_flat_base_clump) ) return;    m_base_clump = m_flat_base_clump;    RwAddClumpToScene(m_scene, m_base_clump);    mi_display_list_is_up_to_date = 0;      mi_3d_is_up_to_date = 0;mi_flat_is_up_to_date = 0;  }  }       mi_bbox_is_up_to_date = 0;  ml_num_faces = part->get_number_of_faces();  ml_num_bendlines = part->get_number_of_bendlines();  ml_num_formings = part->get_number_of_formings();clear_selection_set();  reset_selection_buffer();  OnViewIsometric();}//This function destroys all parent clumps in the scene, and hence all clumps in the scene.// It always returns NULL.static RwClump * RWCALLBACKclear_scene(RwClump *clump){  int i = RwGetClumpNumChildren(clump);  if(i) RwDestroyClump(clump);       return NULL;} // This allows other classes to signal that the part has changed, and hence// current clumps/display lists are no longer valid. We recompute centroids, prepare new clumps// or display lists, and show the part in its current orientation and zoom.void CBendCADViewPart::invalidate_display(void) {  int i;  BM_PART *part = NULL;  CBendCADDoc* pDoc = GetDocument();  ASSERT_VALID(pDoc);  part = pDoc->get_part();  if(! part) {    mi_part_is_up_to_date = 0;  return;  }  mi_part_is_up_to_date = 1;  compute_part_centroid(part, 0, &m_flat_part_centroid); // Compute 3d and flat part centroids.  compute_part_centroid(part, 1, &m_3d_part_centroid);   mi_3d_is_up_to_date = 0;   mi_flat_is_up_to_date = 0;  // Clear out any RenderWare clumps around.  if(m_flat_base_clump) {    RwRemoveClumpFromScene(m_flat_base_clump);    RwDestroyClump(m_flat_base_clump);    m_flat_base_clump = NULL;  }  if(m_3d_base_clump) {    RwRemoveClumpFromScene(m_3d_base_clump);    RwDestroyClump(m_3d_base_clump);    m_3d_base_clump = NULL;  }  m_base_clump = NULL;  if(mi_show_3d) {     // Prepare 3d solid or 3d wireframe.    m_part_centroid = m_3d_part_centroid;  if(! mi_show_solid) {   // Prepare wireframe.      i =  prepare_display_list(part, mi_show_3d, 1, 0, 1, 1, md_face_color, md_bendline_color);      if(! i) {        mi_display_list_is_up_to_date = 0;      return;      }      mi_display_list_is_up_to_date =1;      mi_3d_is_up_to_date = 1;    mi_flat_is_up_to_date = 0;  }  else{         // Prepare solid.      i = facet_part_rw(part, &m_3d_base_clump, mi_show_3d, md_part_color);    if( (! i) || (! m_3d_base_clump) ) return;    m_base_clump = m_3d_base_clump;    RwAddClumpToScene(m_scene, m_base_clump);  }  }      else {           // Prepare flat solid or flatwireframe.    m_part_centroid = m_flat_part_centroid;   if(! mi_show_solid) {   // Prepare wireframe.      i =  prepare_display_list(part, mi_show_3d, 1, 0, 1, 1, md_face_color, md_bendline_color);      if(! i) {    mi_display_list_is_up_to_date = 0;      return;      }      mi_display_list_is_up_to_date = 1;      mi_flat_is_up_to_date = 1;      mi_3d_is_up_to_date = 0;  }  else {         // Prepare solid.      i = facet_part_rw(part, &m_flat_base_clump, mi_show_3d, md_part_color);    if( (! i)|| (! m_flat_base_clump) ) return;    m_base_clump = m_flat_base_clump;    RwAddClumpToScene(m_scene, m_base_clump);  }  }  mi_bbox_is_up_to_date = 0;  ｍｌ＿ｎｕｍ＿ｆａｃｅｓ  ＝  ｐａｒｔ−＞ｇｅｔ＿ｎｕｍｂｅｒ＿ｏｆ＿ｆａｃｅｓ（）；  ml_num_bendlines =part->get_number_of_bendlines();  ml_num_formings = part->get_number_of_formings();  clear_selection_set();  reset_selection_buffer();  ml_last_function_chosen = RETURN_FROM_DIALOG_MODE;  DrawPart(m_hdc);  ml_last_function_chosen = NO_FUNCTION_MODE;}void CBendCADViewPart::OnShowFlat() {  if(! mi_show_3d) return;  // Flat is already being shown.    int i;  BM_PART *part = NULL;  CBendCADDoc* pDoc = GetDocument();  ASSERT_VALID(pDoc);  part = pDoc->get_part();  if(! part) {    mi_part_is_up_to_date =0;  return;  }  // Store the current 3d view parameters.  md_old_x_trans = md_x_trans;  md_old_y_trans = md_y_trans;  for(i=0; i < 3; ++i) {  md_old_part_bbox_size[i] = md_part_bbox_size[i];  md_old_view_vol[i] =md_current_view_vol[i];  }  if(md_old_rot_matrix) RwDestroyMatrix(md_old_rot_matrix);  md_old_rot_matrix = RwDuplicateMatrix(md_rot_matrix);  mi_show_3d = 0;  m_part_centroid = m_flat_part_centroid;   if(! mi_show_solid) {// Compute the flat’s display list.     if(! mi_flat_is_up_to_date) {      i =  prepare_display_list(part, mi_show_3d, 1, 0, 1, 1, md_face_color, md_bendline_color);      if(! i) {        mi_display_list_is_up_to_date = 0;      return;      }    }    mi_display_list_is_up_to_date= 1;  mi_flat_is_up_to_date = 1;  mi_3d_is_up_to_date = 0;  }  else {//Compute flat’s clump if not already done.    if(m_3d_base_clump) RwRemoveClumpFromScene(m_3d_base_clump);  m_base_clump = NULL;   if(! m_flat_base_clump) {      i = facet_part_rw(part, &m_flat_base_clump, mi_show_3d, md_part_color);      if( (! i) || (! m_flat_base_clump) ) {        mi_display_list_is_up_to_date = 0;       return;      }  }    m_base_clump= m_flat_base_clump;// Set the base clump to be the flat’s base clump.    RwAddClumpToScene(m_scene, m_base_clump);  }  mi_bbox_is_up_to_date= 0;  OnViewTop();  }// Here we show the 3d version, in its old orientation and zoom (before flat was// asked to be shown).void CBendCADViewPart::OnShow3d() {  if(mi_show_3d) return;    // 3D view is already being shown.    int i;  BM_PART *part = NULL;  CBendCADDoc* pDoc = GetDocument();  ASSERT_VALID(pDoc);  part = pDoc->get_part();  if(! part) {    mi_part_is_up_to_date = 0;  return;  }  // Restore the old 3d view parameters.  md_x_trans = md_old_x_trans;  md_y_trans = md_old_y_trans;  for(i=0; i< 3; ++i) {    md_part_bbox_size[i] = md_old_part_bbox_size[i];  md_current_view_vol[i] = md_old_view_vol[i];  }  if(md_rot_matrix) RwDestroyMatrix(md_rot_matrix);  md_rot_matrix = RwDuplicateMatrix(md_old_rot_matrix);  mi_show_3d = 1;  m_part_centroid = m_3d_part_centroid;  if(! mi_show_solid) {    if(! mi_3d_is_up_to_date) {      i =  prepare_display_list(part, mi_show_3d, 1, 0, 1, 1, md_face_color, md_bendline_color);      if(! i) {        mi_display_list_is_up_to_date = 0;      return;      }    mi_display_list_is_up_to_date = 1;      mi_3d_is_up_to_date = 1;mi_flat_is_up_to_date = 0;    }  }  else {// Compute the 3d_version’s clumps if have not already done so.    if(m_flat_base_clump) RwRemoveClumpFromScene(m_flat_base_clump);  m_base_clump = NULL;    if(! m_3d_base_clump) {       i = facet_part_rw(part, &m_3d_base_clump, mi_show_3d, md_part_color);      if( (! i) || (! m_3d_base_clump) ) {        mi_display_list_is_up_to_date = 0;      return;      }    }    m_base_clump = m_3d_base_clump;// Set the base clump to be the 3d version’s base clump.RwAddClumpToScene(m_scene, m_base_clump);  }  mi_bbox_is_up_to_date = 0;  md_current_view_vol[1] = md_current_view_vol[0]/md_aspect;   RwSetCameraViewwindow(m_camera, (float)(md_current_view_vol[0]), (float)(md_current_view_vol[1]));   glMatrixMode(GL_PROJECTION);  glLoadIdentity();  glOrtho(- md_current_view_vol[0],md_current_view_vol[0],- md_current_view_vol[1], md_current_view_vol[1],//- 50000.0, 50000.0);          - md_current_view_vol[2], md_current_view_vol[2]);  glMatrixMode(GL_MODELVIEW);  DrawPart(m_hdc);  }void CBendCADViewPart::OnHide3d() {  OnShowFlat();// For now, just switch to showing flat.}void CBendCADViewPart::OnHideFlat(){  OnShow3d();// For now, just switch to showing 3D.}void CBendCADViewPart::OnViewWireframe() {  if(! mi_show_solid) return;    // Wireframe already being shown.  int i;  CreateRGBPalette(m_hdc);// when wireframe --recreate the palette -- AK  HGLRC hrc = wglGetCurrentContext(); // Therendering context of OpenGL.  wglMakeCurrent(NULL, NULL);  wglMakeCurrent(m_hdc, hrc);        // Associate the rendering context with this view.  BM_PART *part = NULL;  CBendCADDoc* pDoc = GetDocument();  ASSERT_VALID(pDoc);  part = pDoc->get_part();  if(! part) {    mi_part_is_up_to_date = 0;  return;  }  mi_show_solid = 0;  if(mi_show_3d) {    if(! mi_3d_is_up_to_date) {      i =  prepare_display_list(part, mi_show_3d, 1, 0, 1, 1, md_face_color, md_bendline_color);      if(! i) {        mi_display_list_is_up_to_date = 0;      return;      }      mi_display_list_is_up_to_date = 1;    mi_3d_is_up_to_date = 1;    mi_flat_is_up_to_date = 0;  }  }  else {    if(! mi_flat_is_up_to_date) {      i =  prepare_display_list(part, mi_show_3d, 1, 0, 1, 1, md_face_color, md_bendline_color);      if(! i) {        mi_display_list_is_up_to_date = 0;      return;    }      mi_display_list_is_up_to_date = 1;    mi_3d_is_up_to_date = 0;    mi_flat_is_up_to_date = 1;    }  }  ml_last_function_chosen = WIREFRAME_MODE;  DrawPart(m_hdc);  ml_last_function_chosen = NO_FUNCTION_MODE;    }void CBendCADViewPart::OnViewShaded() {  if(mi_show_solid) return;        // Solid already being shown.  int i;  BM_PART *part = NULL;  CBendCADDoc* pDoc = GetDocument();  ASSERT_VALID(pDoc);  part = pDoc->get_part();  if(! part) {    mi_part_is_up_to_date = 0;  return;  }  mi_show_solid = 1;  if(mi_show_3d) {    if(! m_3d_base_clump) {       i = facet_part_rw(part, &m_3d_base_clump, mi_show_3d, md_part_color);      if( (!i) || (! m_3d_base_clump) ) {        mi_display_list_is_up_to_date = 0;      return;      }    }RwRemoveClumpFromScene(m_base_clump);    m_base_clump = m_3d_base_clump;// Set the base clump to be the 3d version’s base clump.    RwAddClumpToScene(m_scene, m_base_clump);  }  else {    if(! m_flat_base_clump) {       i = facet_part_rw(part, &m_flat_base_clump, mi_show_3d, md_part_color);      if( (! i) || (! m_flat_base_clump) ){        mi_display_list_is_up_to_date = 0;      return;      }    }RwRemoveClumpFromScene(m_base_clump);    m_base_clump = m_flat_base_clump;//Set the base clump to be the 3d version’s base clump.    RwAddClumpToScene(m_scene, m_base_clump);  }  ml_last_function_chosen = SOLID_MODE;DrawPart(m_hdc);  ml_last_function_chosen = NO_FUNCTION_MODE;   }void CBendCADViewPart::OnZoomWindow() {  ml_last_function_chosen = ZOOM_WINDOW_MODE;    mi_bbox_is_up_to_date = 0;}void CBendCADViewPart::OnUpdateZoomWindow(CCmdUI* pCmdUI) {pCmdUI->SetCheck((ZOOM_WINDOW_MODE == ml_last_function_chosen) ? TRUE : FALSE);}void CBendCADViewPart::OnZoomInOut() {  ml_last_function_chosen = ZOOM_IN_OUT_MODE;    mi_bbox_is_up_to_date = 0;}void CBendCADViewPart::OnUpdateZoomInOut(CCmdUI* pCmdUI) {pCmdUI->SetCheck((ZOOM_IN_OUT_MODE == ml_last_function_chosen) ? TRUE : FALSE);}voidCBendCADViewPart::OnZoomAll() {  BM_PART *part = NULL;  CBendCADDoc* pDoc;  BM_VECTOR offset;  if(! mi_bbox_is_up_to_date) {    pDoc = GetDocument();    ASSERT_VALID(pDoc);    part = pDoc->get_part();    if(! part) return;if(! mi_part_is_up_to_date) {                            // By nowwe expect the centroid to have alreadycompute_part_centroid(part, 0, &m_flat_part_centroid);  // been computed; this is only a safety check. compute_part_centroid(part, 1, &m_3d_part_centroid); if(mi_show_3d) m_part_centroid = m_3d_part_centroid;else m_part_centroid =  m_flat_part_centroid;}compute_part_bbox(part, mi_show_3d, md_rot_matrix, m_part_centroid,md_part_bbox_size, &offset);    mi_bbox_is_up_to_date = 1;md_x_trans =-(offset.X());     // Adjust for the fact that bbox center maymd_y_trans= -(offset.Y());     // not coincide with centroid of part.  }  set_new_view_volume(md_part_bbox_size[0], md_part_bbox_size[1]);  ml_last_function_chosen = ZOOM_ALL_MODE;  DrawPart(m_hdc);  ml_last_function_chosen =NO_FUNCTION_MODE;  }void CBendCADViewPart::OnUpdateZoomAll(CCmdUI* pCmdUI) {pCmdUI->SetCheck((ZOOM_ALL_MODE == ml_last_function_chosen) ? TRUE: FALSE);}void CBendCADViewPart::OnViewIsometric() {  ml_last_function_chosen = ISOMETRIC_VIEW_MODE;  mi_bbox_is_up_to_date = 0;  md_z_angle = 270.0;  md_y_angle = 305.2643897;// 270 + tan^-1(1/sqrt(2))  RwRotateMatrix(RwScratchMatrix(), 0.0f, 0.0f, 1.0f, CREAL(md_z_angle), rwREPLACE);RwRotateMatrix(RwScratchMatrix(), 0.0f, 1.0f, 0.0f, CREAL(md_y_angle), rwPRECONCAT);  md_z_angle = 45.0;  RwRotateMatrix(RwScratchMatrix(), 0.0f, 0.0f, 1.0f, CREAL(md_z_angle), rwPRECONCAT);  if(md_rot_matrix) RwDestroyMatrix(md_rot_matrix);  md_rot_matrix = RwDuplicateMatrix(RwScratchMatrix());//  glPushMatrix();//  glLoadIdentity();//  glRotated(md_z_angle, 0.0, 0.0, 1.0);   // Rotation about z axis.//  glRotated(md_y_angle,0.0, 1.0, 0.0);  // Rotation about y axis.//  md_z_angle = 45.0;//  glRotated(md_z_angle, 0.0, 0.0, 1.0);//  glGetDoublev(GL_MODELVIEW_MATRIX, md_rot_matrix);//  glPopMatrix();  OnZoomAll();}void CBendCADViewPart::OnViewRight() { ml_last_function_chosen = RIGHT_VIEW_MODE;  mi_bbox_is_up_to_date = 0;  md_z_angle = 270.0;  md_y_angle = 270.0;  md_x_angle = 0.0;  RwRotateMatrix(RwScratchMatrix(), 0.0f, 0.0f, 1.0f, CREAL(md_z_angle), rwREPLACE);  RwRotateMatrix(RwScratchMatrix(), 0.0f, 1.0f, 0.0f, CREAL(md_y_angle), rwPRECONCAT);  if(md_rot_matrix) RwDestroyMatrix(md_rot_matrix);  md_rot_matrix = RwDuplicateMatrix(RwScratchMatrix());//  glPushMatrix();//  glLoadIdentity();//  glRotated(md_z_angle, 0.0, 0.0, 1.0);   // Rotation about z axis.//  glRotated(md_y_angle,  0.0, 1.0, 0.0);// Rotation about y axis.//  glGetDoublev(GL_MODELVIEW_MATRIX, md_rot_matrix);//  glPopMatrix();  OnZoomAll();}void CBendCADViewPart::OnViewFront() {  ml_last_function_chosen = FRONT_VIEW_MODE;  mi_bbox_is_up_to_date= 0;  md_y_angle = 0.0;  md_z_angle = 0.0;  md_x_angle = 270.0;  RwRotateMatrix(RwScratchMatrix(), 1.0f, 0.0f, 0.0f, CREAL(md_x_angle), rwREPLACE);  if(md_rot_matrix) RwDestroyMatrix(md_rot_matrix);  md_rot_matrix =RwDuplicateMatrix(RwScratchMatrix());//  glPushMatrix(); //  glLoadIdentity();//  glRotated(md_x_angle, 1.0, 0.0, 0.0);   // Rotation about x axis.//  glGetDoublev(GL_MODELVIEW_MATRIX, md_rot_matrix);//  glPopMatrix();  OnZoomAll();}void CBendCADViewPart::OnViewTop() {  ml_last_function_chosen = TOP_VIEW_MODE;  mi_bbox_is_up_to_date = 0;  RwIdentityMatrix(md_rot_matrix);  OnZoomAll();}void CBendCADViewPart::OnViewsOrtho() {if (NULL == GetDocument()->get_part()) { // no partreturn ;} COrthoViewDlg orhodlg(NULL, GetDocument()->get_part(), this) ;int ret = orhodlg.DoModal() ;// if we are in a Client Mode, the user cannot have entered anything.// we have to redisplay the main client menu bar.if (BENDCAD_CLIENT_MODE) {::PostMessage(this->GetSafeHwnd(),WM_COMMAND,MAKEWPARAM(ID_DISPLAY_CLIENT_MENU,1),NULL) ;return ;}// when OK pressed, get return valuesif (IDOK == ret) {}}void CBendCADViewPart::OnViewBack()  {  ml_last_function_chosen = BACK_VIEW_MODE;  mi_bbox_is_up_to_date = 0;  md_x_angle = 270.0;  md_y_angle = 0.0;  md_z_angle = 180.0;  RwRotateMatrix(RwScratchMatrix(), 1.0f, 0.0f, 0.0f, CREAL(md_x_angle), rwREPLACE);  RwRotateMatrix(RwScratchMatrix(), 0.0f, 0.0f, 0.1f, CREAL(md_z_angle), rwPRECONCAT);  if(md_rot_matrix) RwDestroyMatrix(md_rot_matrix);  md_rot_matrix = RwDuplicateMatrix(RwScratchMatrix());  OnZoomAll();}void CBendCADViewPart::OnViewBottom() {  ml_last_function_chosen = BOTTOM_VIEW_MODE;  mi_bbox_is_up_to_date = 0;  md_x_angle = 0.0;  md_y_angle = 180.0;  md_z_angle = 0.0;  RwRotateMatrix(RwScratchMatrix(), 0.0f, 1.0f, 0.0f, CREAL(md_y_angle),rwREPLACE);  if(md_rot_matrix) RwDestroyMatrix(md_rot_matrix);  md_rot_matrix = RwDuplicateMatrix(RwScratchMatrix());  OnZoomAll();}void CBendCADViewPart::OnViewLeft() {  ml_last_function_chosen = LEFT_VIEW_MODE;  mi_bbox_is_up_to_date = 0;  md_z_angle = 90.0;  md_y_angle = 90.0;  md_x_angle = 0.0;  RwRotateMatrix(RwScratchMatrix(), 0.0f, 0.0f, 1.0f, CREAL(md_z_angle), rwREPLACE);  RwRotateMatrix(RwScratchMatrix(), 0.0f, 1.0f,0.0f, CREAL(md_y_angle), rwPRECONCAT);  if(md_rot_matrix) RwDestroyMatrix(md_rot_matrix);  md_rot_matrix = RwDuplicateMatrix(RwScratchMatrix());  OnZoomAll();}   void CBendCADViewPart::OnRotate() {  ml_last_function_chosen = ROTATION_MODE;  mi_bbox_is_up_to_date = 0;}void CBendCADViewPart::OnUpdateRotate(CCmdUI* pCmdUI) {pCmdUI->SetCheck((ROTATION_MODE == ml_last_function_chosen) ? TRUE : FALSE);}void CBendCADViewPart::OnPan() {    ml_last_function_chosen = PAN_MODE;    mi_bbox_is_up_to_date = 0;}void CBendCADViewPart::OnUpdatePan(CCmdUI* pCmdUI) {pCmdUI->SetCheck((PAN_MODE == ml_last_function_chosen) ? TRUE : FALSE);}// This function computes the rotation angles about x and y axes.// It is called on mouse movement, if the rotation mode is on.void CBendCADViewPart::compute_rotation_angles(int x_flag){  double x_dir = (double)(m_current_point.x - m_previous_point.x);  double y_dir = (double)(m_current_point.y - m_previous_point.y);  double mag = sqrt(x_dir*x_dir + y_dir*y_dir);  // Create the rotation matrix corresponding to the axis computed.  if(mag > 0.1) {    RwRotateMatrix(RwScratchMatrix(), CREAL(y_dir/mag), CREAL(x_dir/mag), CREAL(0.0),                    CREAL(360.0*mag/(1.414*m_old_rect.bottom)),rwREPLACE);    RwTransformMatrix(RwScratchMatrix(), md_rot_matrix, rwPRECONCAT);    if(md_rot_matrix) RwDestroyMatrix(md_rot_matrix);    md_rot_matrix = RwDuplicateMatrix(RwScratchMatrix());  }    //  glPushMatrix();//  glLoadIdentity();//  glRotated(md_y_angle, 0.0, 1.0, 0.0);     // Rotation about y axis.//  if(x_flag)//    glRotated(md_x_angle,  1.0, 0.0,1.0);  // Rotation about x axis.//  else//    glRotated(md_z_angle,  0.0, 0.0, 1.0);  // Rotation about z axis.//  glMultMatrixd(md_rot_matrix);//  glGetDoublev(GL_MODELVIEW_MATRIX, md_rot_matrix);//  glPopMatrix();  } // This function computes the x and y translation values.// It is called on mouse movement, if the pan mode is on.void CBendCADViewPart::compute_pan_translation(void){  double x;  if( (x = (double)m_old_rect.right) > 0.0 )    md_x_trans += (m_current_point.x - m_previous_point.x)*                 md_current_view_vol[0]/x;  if( (x = (double)m_old_rect.bottom) > 0.0 )    md_y_trans += -(m_current_point.y - m_previous_point.y)*  // -ve sign for md_y_trans                    md_current_view_vol[1]/x;                 // bec. y axis points up screen.              }// This funciton computes translation values when user zooms in/out.void CBendCADViewPart::compute_zoom_in_out_translation(void){  double x;  if( (x= (double)m_old_rect.right) > 0.0 )    md_x_trans += -(m_current_point.x - m_previous_point.x)*                   md_current_view_vol[0]/x;}//This funciton computes translation values when user zooms into a // selected rectangular region.void CBendCADViewPart::compute_zoom_region_translation(void){  double x1 = ((double)(m_lt_btn_down_point.x + m_lt_btn_up_point.x))/2.0;  double delta_x = x1 - ((double)m_old_rect.right)/2.0;double y1 = ((double)(m_lt_btn_down_point.y + m_lt_btn_up_point.y))/2.0;  double delta_y = -( y1 - ((double)m_old_rect.bottom)/2.0 );  md_x_trans -= //m_part_centroid.X() - md_x_trans +                delta_x*2.0*md_current_view_vol[0]/((double)m_old_rect.right);  md_y_trans -= //m_part_centroid.Y() - md_y_trans +                delta_y*2.0*md_current_view_vol[1]/((double)m_old_rect.bottom);}// This function computes the new view volume when the user zooms in/out.// The part has already been translated appropriately.void CBendCADViewPart::compute_zoom_in_out_view_volume(void){  double x = -(m_current_point.y - m_previous_point.y);  md_current_view_vol[0] -= md_current_view_vol[0]*x/(double)m_old_rect.bottom;  md_current_view_vol[1] = md_current_view_vol[0]/md_aspect;  RwSetCameraViewwindow(m_camera, (float)(md_current_view_vol[0]), (float)(md_current_view_vol[1]));   glMatrixMode(GL_PROJECTION);  glLoadIdentity();  glOrtho(- md_current_view_vol[0],md_current_view_vol[0],- md_current_view_vol[1], md_current_view_vol[1],//- 50000.0, 50000.0);          - md_current_view_vol[2], md_current_view_vol[2]);  glMatrixMode(GL_MODELVIEW);}// This function computes and sets the new view volume when the user zooms into // a selected rectangular region. (In the case of zoom all, the selected// region is simply the bounding box of the part).// The part has already been translated appropriately.void CBendCADViewPart::set_new_view_volume(double x_extent, double y_extent){  double longer =  __max(x_extent, y_extent);  double shorter = __min(x_extent, y_extent);  if(longer ==x_extent) {    // The x extent is longer.    if(longer/md_aspect < shorter)        // y extent does not fit screen.  longer = shorter*md_aspect;md_current_view_vol[0] = 0.55*longer;md_current_view_vol[1] = 0.55*longer/md_aspect;md_current_view_vol[2] = __max(longer, md_part_bbox_size[2]);  }  else {  // The y extent is longer.    if(longer*md_aspect < shorter)       // x extent does not fit screen.  longer = shorter/md_aspect;md_current_view_vol[0] = 0.55*longer*md_aspect;md_current_view_vol[1] = 0.55*longer;md_current_view_vol[2] = __max(longer, md_part_bbox_size[2]);  }  RwSetCameraViewwindow(m_camera, (float)(md_current_view_vol[0]), (float)(md_current_view_vol[1]));   glMatrixMode(GL_PROJECTION);  glLoadIdentity();  glOrtho(- md_current_view_vol[0],md_current_view_vol[0],- md_current_view_vol[1], md_current_view_vol[1],//- 50000.0, 50000.0);    - md_current_view_vol[2], md_current_view_vol[2]);  glMatrixMode(GL_MODELVIEW);  glLoadIdentity();}// This function draws a part on the viewwindow. It is called by OnDraw.void CBendCADViewPart::DrawPart(HDC draw_dc) { long size, i, parent_tag, key;static long *selected_items = NULL;RwClump *picked_clump, *parent_clump;  static double red_color[3] = {1.0, 0.0, 0.0};  static double green_color[3] = {0.0, 1.0, 0.0};double array[16];BV_SELECT_DATA *data = NULL;static RwMatrix4d *old_matrix[50];static float rw_array[4][4];if(mi_simulation_is_on) {// Set camera parameters to view window values.  RwSetCameraViewport(m_camera, 0, 0, m_old_rect.right, m_old_rect.bottom);    glViewport(0, 0, m_old_rect.right, m_old_rect.bottom);   RwSetCameraViewwindow(m_camera, (float)(md_current_view_vol[0]), (float)(md_current_view_vol[1])); glMatrixMode(GL_PROJECTION);glLoadIdentity();glOrtho(- md_current_view_vol[0],md_current_view_vol[0],- md_current_view_vol[1], md_current_view_vol[1],//- 50000.0, 50000.0);            -md_current_view_vol[2], md_current_view_vol[2]);glMatrixMode(GL_MODELVIEW);}if(! mi_show_solid){     // Wireframe drawing; use OpenGL drawing commands.  glPushMatrix();glTranslated(m＿camera_position.X(), m_camera_position.Y(), m_camera_position.Z());gluLookAt(m_camera_position.X(), m_camera_position.Y(), m_camera_position.Z(),  m_camera_target.X(), m_camera_target.Y(), m_camera_target.Z(),          m_camera_look_up.X(), m_camera_look_up.Y(), m_camera_look_up.Z());    glTranslated(md_x_trans, md_y_trans, 0.0);  convert_rw_matrix_to_gl_array(md_rot_matrix, array);  glMultMatrixd(array);  glTranslated(- m_part_centroid.X(), - m_part_centroid.Y(), - m_part_centroid.Z());    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  if(ml_last_function_chosen == SELECT_OBJECTS_MODE)     glRenderMode(GL_SELECT);  else    glRenderMode(GL_RENDER);    glSelectBuffer(512, mw_selected_objects);  glInitNames();  glPushName(0);  if(! mi_simulation_is_on) {  // First drawthe selected items in red, if any.size = m_selection_set.list_size();if(size) {selected_items = new long [size*2 + 1];  // +1 for safety.m_selection_set.display(size, selected_items);glColor3d(1.0, 0.0, 0.0);for(i=0;i < size; ++i) {  data = (BV_SELECT_DATA *)selected_items[i*2 +1];if(!data) continue;if(data->edge) {                                       //Edge is available, => not a trivial  glCallList((unsigned int)selected_items[i<<1]); // bendline or body of something.}else {// Body of face/forming/bendline picked; highlight whole thing.key = selected_items[i<<1]/100000;glCallList((unsigned int)key*100000);}}  }  }  glCallList(1);glFinish();  glPopMatrix();     SwapBuffers(wglGetCurrentDC());}  else {  // Solid drawing; use RenderWare.  // Transform the part if necessary.  if(ml_last_function_chosen != NO_FUNCTION_MODE) {      RwTranslateMatrix(RwScratchMatrix(), CREAL(md_x_trans), CREAL(md_y_trans), CREAL(0.0),rwREPLACE);       RwTransformMatrix(RwScratchMatrix(), md_rot_matrix, rwPRECONCAT);      RwTranslateMatrix(RwScratchMatrix(), CREAL(- m_part_centroid.X()), CREAL(- m_part_centroid.Y()),                         CREAL(- m_part_centroid.Z()), rwPRECONCAT);       // RwForAllClumpsInScenePointer(m_scene, do_transformations, (void *)RwScratchMatrix());      RwTransformClump(m_base_clump, RwScratchMatrix(), rwREPLACE);   }/*RwClump *clump;  for(i=0; i < ml_num_faces + ml_num_bendlines + ml_num_formings; ++i) {        clump = RwFindTaggedClump(m_base_clump, i + 10001);if(! clump) continue;old_matrix[i] = RwCreateMatrix(); // clump の現在のモデル化マトリクスを記憶する.    RwGetClumpMatrix(clump, old_matrix[i]);RwGetMatrixElements(old_matrix[i], rw_array);    RwTranslateMatrix(RwScratchMatrix(), CREAL(md_x_trans), CREAL(md_y_trans), CREAL(0.0), rwREPLACE);RwTransformMatrix(RwScratchMatrix(), md_rot_matrix, rwPRECONCAT);    RwTranslateMatrix(RwScratchMatrix(), CREAL(- m_part_centroid.X()), CREAL(-m_part_centroid.Y()),                       CREAL(- m_part_centroid.Z()), rwPRECONCAT); //RwForAllClumpsInScenePointer(m_scene, do_transformations, (void *)RwScratchMatrix());RwTransformClump(clump, RwScratchMatrix(), rwPOSTCONCAT);   }*///Now set the color of the clumps in the selectionset to red.size = m_selection_set.list_size();if(size) {selected_items= new long [(size << 1) + 1];  // +1 for safety.m_selection_set.display(size, selected_items);for(i=0; i < size; ++i) {data = (BV_SELECT_DATA *)selected_items[i*2 +1];if(! data) continue;if(data->edge) {         // Edge is available, => not a trivial bendline or body of something.parent_tag = (selected_items[i<<1]/100000) + 10000;parent_clump = RwFindTaggedClump(m_base_clump, parent_tag);}else {key = selected_items[i<<1]%100000;  // Check if it is a trivial bendline.if((key/10000) == 6) {parent_tag= (selected_items[i<<1]/100000) + 10000;parent_clump = RwFindTaggedClump(m_base_clump, parent_tag);}else parent_clump = m_base_clump;}key = selected_items[i<<1]%100000;picked_clump = RwFindTaggedClump(parent_clump, key);RwForAllPolygonsInClumpPointer(picked_clump, SetPolygonColor, (void*)red_color); }}  // In case simulation is going on, we don’t want to show the m_sim_base_clump, only m_base_clump.  if(mi_simulation_is_on) {if(m_sim_base_clump) RwRemoveClumpFromScene(m_sim_base_clump);if(mi_show_3d) {m_base_clump = m_3d_base_clump;RwAddClumpToScene(m_scene, m_base_clump);}else {m_base_clump = m_flat_base_clump;RwAddClumpToScene(m_scene,m_base_clump);        }  }  // Now draw the part.  RwInvalidateCameraViewport(m_camera);                            RwBeginCameraUpdate(m_camera, (void *)m_hwnd);      RwClearCameraViewport(m_camera);      i = RwGetSceneNumClumps(m_scene);           // Render the scene.    RwRenderScene(m_scene);  RwEndCameraUpdate(m_camera);    RwShowCameraImage(m_camera, (void*)(DWORD)draw_dc);    //Show the image on the view window./*  for(i=0; i < ml_num_faces + ml_num_bendlines + ml_num_formings; ++i) {    clump = RwFindTaggedClump(m_base_clump, i + 10001);if(! clump) continue;RwTransformClump(clump, old_matrix[i], rwREPLACE);       RwGetClumpMatrix(clump, old_matrix[i]);  RwGetMatrixElements(old_matrix[i], rw_array);if(old_matrix[i]) RwDestroyMatrix(old_matrix[i]);} */  // Put the simulationclump back in the scene so that simulation can see it.  if(mi_simulation_is_on) {if(m_sim_base_clump) RwAddClumpToScene(m_scene, m_sim_base_clump);if(mi_show_3d) RwRemoveClumpFromScene(m_3d_base_clump);else RwRemoveClumpFromScene(m_flat_base_clump);m_base_clump = NULL;  }  // Now set thecolor of the clumps in the selection set back to their original colors.  if(size) {    m_selection_set.display(size, selected_items);    for(i=0; i < size; ++i) {data = (BV_SELECT_DATA *)selected_items[i*2 +1];if(data->edge) {         // Edge is available, => not a trivial bendline or body of something.parent_tag = (selected_items[i<<1]/100000) + 10000;parent_clump = RwFindTaggedClump(m_base_clump, parent_tag);}else {key = selected_items[i<<1]%100000;          // Check if it is a trivial bendline.if((key/10000) == 6) {parent_tag = (selected_items[i<<1]/100000) + 10000;parent_clump = RwFindTaggedClump(m_base_clump, parent_tag);  }  else   parent_clump = m_base_clump;   }key = selected_items[i<<1]%100000;picked_clump = RwFindTaggedClump(parent_clump, key);if( (! data->edge) && ((key/10000) == 6) )  // Trivial bendline.RwForAllPolygonsInClumpPointer(picked_clump, SetPolygonColor, (void *)green_color); elseRwForAllPolygonsInClumpPointer(picked_clump, SetPolygonColor, (void *)md_part_color);     }  }  if(selected_items) delete [] selected_items;  selected_items = NULL;}if(mi_simulation_is_on) {   // Restore camera parameters to simulationvalues.  RwSetCameraViewport(m_camera, 0, 0, mi_bitmap_w , mi_bitmap_h);    glViewport(0, 0, mi_bitmap_w, mi_bitmap_h);              RwSetCameraViewwindow(m_camera, (float)(md_sim_view_vol[0]), (float)(md_sim_view_vol[1])); glMatrixMode(GL_PROJECTION);glLoadIdentity();glOrtho(- md_sim_view_vol[0], md_sim_view_vol[0],- md_sim_view_vol[1], md_sim_view_vol[1],//- 50000.0, 50000.0);            - md_current_view_vol[2], md_current_view_vol[2]);glMatrixMode(GL_MODELVIEW);}}/*if(size) {  for(i=0 ; i < size; ++i) {    BM_3D_BODY *b3;long three_d_type;if(selected_items[i*2 +1]){                 // エッジが得られる => trivalベンドラインまたはフォーミングではない．  three_d_type = (selected_items[i<<1]%100000)/10000;  if((three_d_type >= 3) && (three_d_type < 6)) three_d_type = BM_ENTITY_TYPE_FACE;  else if((three_d_type >= 6) && (three_d_type < 9)) three_d_type = BM_ENTITY_TYPE_BENDLINE;  else if(three_d_type >= 9) three_d_type =BM_ENTITY_TYPE_FORMING;  parent_tag = (selected_items[i<<1]/100000) + 10000;  parent_clump = RwFindTaggedClump(m_base_clump, parent_tag);}else {          CBendCADDoc* pDoc = GetDocument();          ASSERT_VALID(pDoc);          BM_PART *part = pDoc->get_part();          if(! part) return;   // 注意: この段階で部分がNULLであることを期待しない。          BM_TOPOLOGY *topology = part->get_topology();          if(! topology) return;  three_d_type = selected_items[i<<1]/100000;        // 用語の注意: three_d_type は実際ではない。          b3 = topology->map_id_into_pointer(three_d_type); // b3->get_type()までthree_d_type.  three_d_type = b3->get_type();  parent_clump = m_base_clump;}if(three_d_type == BM_ENTITY_TYPE_FACE) {      for(j=0; j < 3; ++j) original_color[j] = md_face_color[j];}else if(three_d_type == BM_ENTITY_TYPE_BENDLINE) {      for(j=0; j < 3;++j) original_color[j] = md_bendline_color[j];}else if(three_d_type == BM_ENTITY_TYPE_FORMING) {      for(j=0; j < 3; ++j) original_color[j] = md_forming_color[j];}key = selected_items[i<<1];key = key%100000;    picked_clump = RwFindTaggedClump(parent_clump, key);    RwForAllPolygonsInClumpPointer(picked_clump, SetPolygonColor, (void *)original_color);   }}*/// This callback function performs the necessary transformations on each clump in the scene.// Transform only parent clumps, since this automatically transforms child clumps as well.static RwClump * RWCALLBACK do_transformations(RwClump *clump, void *matrix) {  int i = RwGetClumpNumChildren(clump);  if(i) {if( !(i = RwGetClumpNumPolygons(clump)) )      RwSetClumpState(clump, rwOFF);// Do not render this clump if it has no polygons.    RwTransformClump(clump, (RwMatrix4d *)matrix, rwREPLACE);   }     return clump;}// This callback function sets the color of the polygon to the required color.static RwPolygon3d * RWCALLBACK SetPolygonColor(RwPolygon3d *polygon, void *color) {     polygon = RwSetPolygonColor(polygon, CREAL(((double *)color)[0]), CREAL(((double *)color)[1]),                              CREAL(((double *)color)[2]));return polygon;}// This function sets the pixel format of the view window to the kindthat// OpenGL likes. Note: Pixel format of a window should be set onlyonce.BOOL CBendCADViewPart::SetupPixelFormat(HDC hDC){    static PIXELFORMATDESCRIPTOR pfd = {        sizeof(PIXELFORMATDESCRIPTOR),  // size ofthis pfd        1,                              // version number  PFD_DRAW_TO_WINDOW |            // support window          PFD_SUPPORT_OPENGL |          // support OpenGL          PFD_DOUBLEBUFFER,     // double buffered        PFD_TYPE_RGBA,                  // RGBA type        24,                             // 24-bit color depth0, 0, 0, 0, 0, 0,               // color bits ignored        0,                      // no alpha buffer        0,        // shift bit ignored        0,                              // no accumulation buffer        0, 0, 0, 0,                     // accum bits ignored        32,                             // 32-bit z-buffer    0,                              // no stencil buffer        0,                        // no auxiliary buffer        PFD_MAIN_PLANE,               // main layer        0,                              // reserved        0, 0, 0                         // layer masks ignored  };    int pixelformat;    if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 )    {        MessageBox("ChoosePixelFormat failed");return FALSE;    }    if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE)    {        MessageBox("SetPixelFormat failed");        return FALSE;    }    // don’t need this call any more; the function will be calledfrom OnActivateView()// and on OnViewWireframe() -- AK//CreateRGBPalette(hDC);    return TRUE;}unsigned char CBendCADViewPart::ComponentFromIndex(int i, UINT nbits, UINT shift){    unsigned char val;    val = (unsigned char) (i >> shift);    switch (nbits) {    case 1:        val &= 0x1;        return oneto8[val];    case 2:        val &= 0x3;        returntwoto8[val];    case 3:        val &= 0x7;        return threeto8[val];    default:        return 0;    }}void CBendCADViewPart::CreateRGBPalette(HDC hDC){    PIXELFORMATDESCRIPTOR pfd;    LOGPALETTE *pPal;    int n, i;    CDC dc;    n = ::GetPixelFormat(hDC);    ::DescribePixelFormat(hDC, n, sizeof(PIXELFORMATDESCRIPTOR), &pfd);    if (pfd.dwFlags & PFD_NEED_PALETTE)    {        n = 1 << pfd.cColorBits;        pPal = (PLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) +                n * sizeof(PALETTEENTRY));        pPal->palVersion = 0x300;        pPal->palNumEntries = n;        for (i=0; i<n; i++)        {            pPal->palPalEntry[i].peRed =                    ComponentFromIndex(i, pfd.cRedBits, pfd.cRedShift);            pPal->palPalEntry[i].peGreen =    ComponentFromIndex(i, pfd.cGreenBits, pfd.cGreenShift);            pPal->palPalEntry[i].peBlue =                    ComponentFromIndex(i, pfd.cBlueBits, pfd.cBlueShift);            pPal->palPalEntry[i].peFlags =0;        }        /* 省略時GDIパレットを含むようにパレットを固定する */        if ((pfd.cColorBits == 8)                           &&  (pfd.cRedBits   == 3) && (pfd.cRedShift   == 0) &&            (pfd.cGreenBits == 3) && (pfd.cGreenShift == 3) &&            (pfd.cBlueBits  ==2) && (pfd.cBlueShift  == 6)           )        {for (i = 1 ; i <= 12 ;i++)                pPal->palPalEntry[defaultOverride[i]] = defaultPalEntry[i];        }        dc.Attach(hDC);CPalette*pOldPal;        // since we call this function not only when creating a view,// but also each time activating, delete the prev palette (if any) -- AKint resp = m_cPal.DeleteObject();        m_cPal.CreatePalette(pPal);        LocalFree(pPal);        pOldPal = dc.SelectPalette(&m_cPal, FALSE);        dc.RealizePalette();        dc.Detach();    }}// This function computes the bounding box parameters of the given part -// the x, y and z extents, in globalcoordinates, for the orientation specified by orient_matrix.// The computation is done with respect to the BM_POINT centroid as origin.// It does so by taking the bbox of each face, projecting each onto the coordinate // axes, and then finding the extents along each axis. If threeD_flagis non-zero, the// three-d version’s bbox is computed; else, the flat’s bbox is computed. The results of the// computation are put into thearry bbox_size[3]; if this pointer is zero, no computation// is performed. The offset, ie. the vector from the centroid’s coords to the bbox center’s coords,// is passed back in the pointer to the BM_VECTOR.// Returns 1 if successful, 0 otherwise.int CBendCADViewPart::compute_part_bbox(BM_PART *part, int threeD_flag, RwMatrix4d *orient_matrix,                         BM_POINT centroid, double *bbox_size, BM_VECTOR*offset) {  BM_FACE *face = NULL;  BM_BENDLINE *bendline = NULL;  BM_2D_BODY *two_d_body = NULL;  BM_LOOP *loop = NULL;  BM_POINT dot1, dot2, dot3, dot4;  double left, right, top, bot, front, back;      // First tworefer to x direction,   // last two to z direction.  BM_VECTOR vec1;  int first_pass = 1;  float rot_matrix[4][4];   if(! part) return 0;  if((part->get_number_of_faces() == 0) && (part->get_number_of_bendlines() == 0) )    return 0;  if(! bbox_size) return 0;  if(! part->get_number_of_faces()) { // In this case, find bendline bboxes.    for(bendline = part->get_bendline_list(); bendline; bendline = (BM_BENDLINE *)bendline->next()) {  // First check that the bbox of the bloop is up to date; if notcompute bbox.  if(threeD_flag)    two_d_body = bendline->get_3D_version();  else    two_d_body = bendline->get_flat();  if(two_d_body) loop = two_d_body->get_bloop();  else continue;  if(! loop) continue;  if(!(loop->is_bbox_up_to_date())) loop->recompute_bbox();  // Now find the envelope (union) of the projected bboxes.  vec1 = BM_VECTOR(centroid.X(), centroid.Y(), centroid.Z());  dot1 = loop->get_bbox_p1() + (-1.0)*vec1;// The bbox coordinates,  dot2 = loop->get_bbox_p2() + (-1.0)*vec1;// with respect to the  dot3 = loop->get_bbox_p3() + (-1.0)*vec1;// centroid as origin.  dot4 = loop->get_bbox_p4() + (-1.0)*vec1;  RwGetMatrixElements(orient_matrix, rot_matrix);  multiply_pt_by_matrix(&dot1, rot_matrix);// Transform coords by the current  multiply_pt_by_matrix(&dot2, rot_matrix);// rotation matrix.  multiply_pt_by_matrix(&dot3, rot_matrix);  multiply_pt_by_matrix(&dot4, rot_matrix);  if(first_pass) {    left  = __min(dot1.X(), dot2.X());    right = __max(dot1.X(), dot2.X());    bot   = __min(dot1.Y(), dot2.Y());    top   = __max(dot1.Y(), dot2.Y());    back  =__min(dot1.Z(), dot2.Z());    front = __max(dot1.Z(), dot2.Z());    first_pass = 0; }  else {    left  = __min(left,  dot1.X());    left  = __min(left,  dot2.X());    right = __max(right, dot1.X());    right = __max(right, dot2.X());    bot   = __min(bot  , dot1.Y());    bot   = __min(bot  , dot2.Y());    top   = __max(top  , dot1.Y());    top   = __max(top  , dot2.Y());    back  = __min(back , dot1.Z());    back  = __min(back, dot2.Z());    front = __max(front, dot1.Z());    front = __max(front,dot2.Z());  }  left  = __min(left,  dot3.X());  left  = __min(left,  dot4.X());  right = __max(right, dot3.X());  right = __max(right, dot4.X());  bot   = __min(bot  , dot3.Y());  bot   = __min(bot  , dot4.Y());  top   = __max(top  , dot3.Y());  top   = __max(top  , dot4.Y());  back  = __min(back , dot3.Z());  back  = __min(back , dot4.Z());  front = __max(front, dot3.Z());  front = __max(front, dot4.Z());    }    bbox_size[0] =right - left;bbox_size[1] = top   - bot;// Copy bbox size into the array passed.bbox_size[2] = front - back;if(offset)     // Copy the bbox center into the pointer passed.  *offset = BM_VECTOR((right + left)/2.0, (top + bot)/2.0, (front + back)/2.0);mi_bbox_is_up_to_date = 1;  return 1;  }  // Faces are available, so find bbox of faces.  for(face = part->get_face_list(); face; face = (BM_FACE *)face->next()) {    if(! face) break;    // First check that the bbox of the bloop is up to date; if not compute bbox.if(threeD_flag)  two_d_body = face->get_3D_version();else  two_d_body = face->get_flat();if(two_d_body) loop = two_d_body->get_bloop();else continue;if(! loop) continue;if(!(loop->is_bbox_up_to_date())) loop->recompute_bbox();// Now find the envelope (union) of the projectedbboxes.vec1 = BM_VECTOR(centroid.X(), centroid.Y(), centroid.Z());dot1 =loop->get_bbox_p1() + (-1.0)*vec1;// The bbox coordinates,dot2 = loop->get_bbox_p2() + (-1.0)*vec1;// with respect to thedot3 = loop->get_bbox_p3() + (-1.0)*vec1;// centroid as origin.dot4 = loop->get_bbox_p4() + (-1.0)*vec1;    RwGetMatrixElements(orient_matrix, rot_matrix);multiply_pt_by_matrix(&dot1, rot_matrix);// Transform coords by the currentmultiply_pt_by_matrix(&dot2, rot_matrix);// rotation matrix.multiply_pt_by_matrix(&dot3, rot_matrix);multiply_pt_by_matrix(&dot4, rot_matrix);if(first_pass) {  left  = __min(dot1.X(), dot2.X());  right = __max(dot1.X(), dot2.X());  bot   = __min(dot1.Y(), dot2.Y());  top   = __max(dot1.Y(), dot2.Y());  back  = __min(dot1.Z(), dot2.Z());  front = __max(dot1.Z(), dot2.Z());  first_pass = 0;}else {  left  = __min(left,  dot1.X());  left  =__min(left,  dot2.X());  right = __max(right, dot1.X());  right = __max(right, dot2.X());  bot   = __min(bot  , dot1.Y());  bot   = __min(bot, dot2.Y());  top   = __max(top  , dot1.Y());  top   = __max(top  , dot2.Y());  back  = __min(back , dot1.Z());  back  = __min(back , dot2.Z());  front = __max(front, dot1.Z());  front = __max(front, dot2.Z());}left  = __min(left,  dot3.X());left  = __min(left,  dot4.X());right = __max(right, dot3.X());right = __max(right, dot4.X());bot   = __min(bot  , dot3.Y());bot   = __min(bot  , dot4.Y());top   = __max(top  , dot3.Y());top   = __max(top  , dot4.Y());back  = __min(back , dot3.Z());back  = __min(back , dot4.Z());front = __max(front, dot3.Z());front = __max(front, dot4.Z());  } bbox_size[0] = right - left;  bbox_size[1] = top   - bot;//Copy bbox size into the array passed.  bbox_size[2] = front - back;  if(offset)     // Copy the bbox center into the pointer passed.*offset = BM_VECTOR((right + left)/2.0, (top + bot)/2.0, (front + back)/2.0);  mi_bbox_is_up_to_date = 1;  return 1;}// This function computes the part’scentroid. This is done with respect to// the original (given) coordinates of the part. If threeD_flag is non-zero, the// three-d version’s centroid is computed; else, the flat’s centroid is computed.// The resultsare passed back in the pointer to a BM_POINT; if this pointer is NULL, no// computation is done. Returns 1 if successful, 0 otherwise.int CBendCADViewPart::compute_part_centroid(BM_PART *part, int threeD_flag, BM_POINT *centroid) {    BM_FACE *face;  BM_2D_BODY *two_d_body;  BM_LOOP *loop;  BM_POINT dot1, dot2, dot3, dot4;  double left, right, top, bot, front, back;  // First two refer to x direction,  // last two to z direction.  int first_pass = 1;  if(! part) return 0;  if( (part->get_number_of_faces == 0) && (part->get_number_of_bendlines == 0) )    return 0;  if(!centroid) return 0;  for(face = part->get_face_list(); face; face = (BM_FACE *)face->next()) {    if(! face) break;    // First check that the bbox of the bloop is up to date; if not compute bbox.if(threeD_flag)  two_d_body = face->get_3D_version();else  two_d_body = face->get_flat();if(two_d_body) loop = two_d_body->get_bloop();else continue;if(! loop) continue;if(!(loop->is_bbox_up_to_date())) loop->recompute_bbox();// Now find the envelope (union) of the projected bboxes.dot1 = loop->get_bbox_p1();dot2 = loop->get_bbox_p2();dot3 = loop->get_bbox_p3(); dot4 = loop->get_bbox_p4(); if(first_pass) {    left  = __min(dot1.X(), dot2.X());  right = __max(dot1.X(), dot2.X());  bot   = __min(dot1.Y(), dot2.Y());  top   = __max(dot1.Y(), dot2.Y());  back  = __min(dot1.Z(), dot2.Z());  front = __max(dot1.Z(), dot2.Z());  first_pass = 0;}else {  left  = __min(left,  dot1.X());  left  = __min(left,  dot2.X());  right = __max(right,dot1.X());  right = __max(right, dot2.X());  bot   = __min(bot  , dot1.Y());  bot   = __min(bot  , dot2.Y());  top   = __max(top  , dot1.Y());top   = __max(top  , dot2.Y());  back  = __min(back , dot1.Z());  back= __min(back , dot2.Z());  front = __max(front, dot1.Z());  front = __max(front, dot2.Z());}left  = __min(left,  dot3.X());left  = __min(left,dot4.X());right = __max(right, dot3.X());right = __max(right, dot4.X());bot   = __min(bot  , dot3.Y());bot   = __min(bot  , dot4.Y());top   = __max(top  , dot3.Y());top   = __max(top  , dot4.Y());back  = __min(back ,dot3.Z());back  = __min(back , dot4.Z());front = __max(front, dot3.Z());front = __max(front, dot4.Z());  }  *centroid = BM_POINT((right + left)/2.0, (top   + bot )/2.0, (front + back)/2.0); // Copy centroid into/*//ポインタが供給される。  if(threeD_flag) {    m_3d_part_centroid.set_X((right + left)/2.0);    m_3d_part_centroid.set_Y((top   + bot )/2.0);   // このpartは3d重心である。    m_3d_part_centroid.set_Z((front + back)/2.0);  }  else {    m_flat_part_centroid.set_X((right + left)/2.0);    m_flat_part_centroid.set_Y((top   + bot )/2.0);   // このpartは平面重心である。    m_flat_part_centroid.set_Z((front + back)/2.0);  }*/  return 1;}// This function multiplies a bend model point by a 4x4 RenderWare transform matrix.// The function is destructive.It is NOT a BMAPPView memberfunction.// Note that the point is considered to be a row vector; this is// RenderWare’s (and the Bend Model’s) convention. static void multiply_pt_by_matrix(BM_POINT *point, float rot_matrix[4][4]) {  double x = point->X();  double y = point->Y();  double z = point->Z();  point->set_X((x*rot_matrix[0][0] + y*rot_matrix[1][0] + z*rot_matrix[2][0]));  point->set_Y((x*rot_matrix[0][1] + y*rot_matrix[1][1] + z*rot_matrix[2][1]));  point->set_Z((x*rot_matrix[0][2] + y*rot_matrix[1][2] + z*rot_matrix[2][2]));}// This function outlines the rectangular region selected by theuser.void CBendCADViewPart::outline_region(void) {  CClientDC view_dc(this);  CPoint corner1_curr = m_lt_btn_down_point, corner2_curr = m_lt_btn_down_point;  CPoint corner1_prev = m_lt_btn_down_point, corner2_prev =m_lt_btn_down_point;  corner1_curr.Offset(m_current_point.x - m_lt_btn_down_point.x, 0);  corner2_curr.Offset(0, m_current_point.y - m_lt_btn_down_point.y);  corner1_prev.Offset(m_previous_point.x - m_lt_btn_down_point.x, 0);  corner2_prev.Offset(0, m_previous_point.y - m_lt_btn_down_point.y);  view_dc.SetROP2(R2_NOT);  view_dc.MoveTo(m_lt_btn_down_point);  view_dc.LineTo(corner1_prev);  view_dc.MoveTo(m_lt_btn_down_point);  view_dc.LineTo(corner2_prev);  view_dc.MoveTo(corner1_prev);  view_dc.LineTo(m_previous_point);  view_dc.MoveTo(corner2_prev);  view_dc.LineTo(m_previous_point);  view_dc.MoveTo(m_lt_btn_down_point);  view_dc.LineTo(corner1_curr);  view_dc.MoveTo(m_lt_btn_down_point);  view_dc.LineTo(corner2_curr);  view_dc.MoveTo(corner1_curr);  view_dc.LineTo(m_current_point);  view_dc.MoveTo(corner2_curr);  view_dc.LineTo(m_current_point);}//This function processes the hits record to pick out the edge(s) selectedby the// user. If add_hit_to_list is non-zero, which it is if the control button is held down,// the current hit, if any, is added to the selection set; else,  the selection set// is cleared and only the current hitis added to the list. If there is no hit, the // selection set is cleared as well, unless add_to_list is non-zero, in which case // nothing happens. // This function recognizes trivial bendlines and formings and modifies the selection set// appropriately. void CBendCADViewPart::process_hits_record(int add_hit_to_list){  RwClump *picked_clump = NULL;  RwClump *parent_clump = NULL;RwV3d vert;  long parent_tag, clump_tag, three_d_type = 0, offset = 0, key = 0;  int num_hits = -3, j;  unsigned long z_max = 0UL, z_min = ULONG_MAX, name_id = 0UL;  unsigned int *ptr = mw_selected_objects;  BM_EDGE *edge = NULL;long old_data;  if(mi_show_solid) {// RenderWare picking.    if(m_pick.type == rwNAPICKOBJECT) {      // No clump was picked.      if(add_hit_to_list) return;else clear_selection_set();return;    }    else if(m_pick.type == rwPICKCLUMP) {               // Some clump was picked; process it.      picked_clump =m_pick.object.clump.clump;vert = m_pick.object.clump.wcpoint;      RwTranslateMatrix(RwScratchMatrix(), CREAL(md_x_trans), CREAL(md_y_trans), CREAL(0.0), rwREPLACE);       RwTransformMatrix(RwScratchMatrix(), md_rot_matrix, rwPRECONCAT);      RwTranslateMatrix(RwScratchMatrix(), CREAL(-m_part_centroid.X()), CREAL(- m_part_centroid.Y()),     CREAL(- m_part_centroid.Z()), rwPRECONCAT);     RwMatrix4d *inverse= RwCreateMatrix();RwInvertMatrix(RwScratchMatrix(), inverse);RwTransformPoint(&vert, inverse);RwDestroyMatrix(inverse);parent_clump = RwGetClumpParent(picked_clump);parent_tag = RwGetClumpTag(parent_clump);clump_tag = RwGetClumpTag(picked_clump);if(parent_tag == 1) {// The body of a face/bendline/forming was picked.key = (clump_tag%10000)*100000 + clump_tag;     if(m_selection_set.find(key, NULL)) {               m_selection_set.remove(key, &old_data);        // Remove clump from selection set (toggle).if(old_data) delete (BV_SELECT_DATA *)old_data;return;}else {if(!add_hit_to_list) clear_selection_set();  // Remove everything else in selection set, BV_SELECT_DATA *data = new BV_SELECT_DATA;data->key = key;data->edge = NULL;          (data->world_pt) = BM_POINT(vert.x, vert.y, vert.z);m_selection_set.insert(key, (long)data);// insert this key and data.return;}}// Now an edge was picked.key = (parent_tag%10000)*100000 +clump_tag; if(clump_tag) {// Safety check; we expect clump_tag to be non-zero.if(m_selection_set.find(key, NULL)){  m_selection_set.remove(key,&old_data);        // Remove clump from selection set (toggle).if(old_data) delete (BV_SELECT_DATA *)old_data;}  else {if(! add_hit_to_list) clear_selection_set();  // Remove everything else in selection set. edge =map_list_name_to_bm_edge(parent_tag, clump_tag);BV_SELECT_DATA *data = new BV_SELECT_DATA;data->key = key;data->edge = edge;          (data->world_pt) = BM_POINT(vert.x, vert.y, vert.z);m_selection_set.insert(key, (long)data);// insert this key and data.}}    }  }  else {// OpenGL Picking.    num_hits = glRenderMode(GL_RENDER);                  // The numberof hits.    if(num_hits == -1) {                        // Selection buffer has overflowed.      AfxMessageBox("Too many entities selected; change view and try again.");return;    }    if(num_hits == 0) {                // No hit; only a miss.      if(add_hit_to_list) return;else clear_selection_set();return;    }    // Process the hits : find the edge with LOWEST z value of all the edges picked.    for(j=0; j < num_hits; ++j) {            ptr += 1;                      // Skip the 1st element bec. it will always be 1,      if( (unsigned long)(*ptr) < (unsigned long)z_min) {z_min = (unsigned long)(*ptr); ptr += 2;name_id = (long)(*ptr); ++ptr;}else ptr += 3;       }    // Find the bm edge corresp. to the name and add it to the selection set.    if(name_id) {                      // Something was selected.      if(m_selection_set.find(name_id, NULL)) {m_selection_set.remove(name_id, &old_data);    //Remove edge fromselection set (toggle).if(old_data) delete (BV_SELECT_DATA *)old_data;}else {if(! add_hit_to_list) clear_selection_set();// First, we massage the name_id into the format RenderWare picking uses.parent_tag = name_id/100000 + 10000;clump_tag = name_id%100000;edge = maｐ＿list_name_to_bm_edge(parent_tag, clump_tag);BV_SELECT_DATA *data = new BV_SELECT_DATA;data->key = key;data->edge = edge;        (data->world_pt) =BM_POINT(0.0, 0.0, 0.0);m_selection_set.insert(name_id, (long)data);// insert this key and data.}    }  }  return;}// This function maps a RenderWare parent clump and child clump pair to the // Bend Model edge whichthe child clump represents. The pointer to the edge is returned.// Thisfunction only needs to deal with "real" edges, ie. trivial bendlines and// formings are filtered out by process_hits_records itself.BM_EDGE *CBendCADViewPart::map_list_name_to_bm_edge(long parent_tag, long clump_tag){  long three_d_name, three_d_type, loop_name, edge_name, count = 0, offset = 0;  BM_3D_BODY *three_d_body = NULL;  BM_2D_BODY *two_d_body = NULL;  BM_LOOP *loop = NULL;  BM_EDGE *edge = NULL;  BM_PART *part = NULL;  BM_TOPOLOGY *topology = NULL;  CBendCADDoc* pDoc = GetDocument();  ASSERT_VALID(pDoc);  part = pDoc->get_part();  if(! part) return NULL;   //Note: we do not expect part to be NULL at this stage.  topology = part->get_topology();  if(! topology) return NULL;  three_d_name = parent_tag%10000;  three_d_body = topology->map_id_into_pointer(three_d_name);   // Now we have a pointer to the face/bendline to which the picked edge belongs.  three_d_type = three_d_body->get_type();  if(three_d_type == BM_ENTITY_TYPE_FACE)offset = 30000;  if(three_d_type == BM_ENTITY_TYPE_BENDLINE)offset = 60000;  if(three_d_type == BM_ENTITY_TYPE_FORMING)offset =90000;  loop_name = (clump_tag - offset)/100;  edge_name = (clump_tag -offset)%100;  if(loop_name == 0) return NULL;   // This should never bethe case.  // Now have the edge_name-th edge in the loop_name-th loop of the face/bendline/forming.  // Now we have the face/bendline to whichthe edge belongs.  if(mi_show_3d) two_d_body = three_d_body->get_3D_version();   else two_d_body = three_d_body->get_flat();  if(! two_d_body) return NULL;  if(loop_name == 1) loop = two_d_body->get_bloop();  else {    count = 1;    for(loop = two_d_body->get_first_hole(); loop; loop =(BM_LOOP *)loop->next()) {  if(! loop) return NULL;  ++count;  if(count== loop_name) break;}  }  // Now we have the loop to which the edge belongs.  if(loop == NULL) return NULL;            // A trivial bendline waspicked.  count = 0;  for(edge = loop->get_first_edge(); edge; edge = (BM_EDGE *)edge->next()) {if(! edge) break;++count;if(count == edge_name)break;  }  // Now we have the edge itself.  return edge;/*  three_d_name= list_name/10000;  loop_name = list_name%10000;   // loop_name-th の中の edge_name 番目の edge   loop_name /= 100;   // loop of the three_d_name 番目のthree-d-body,  edge_name = list_name%100;   //最初のthree-d-bodyとして最初のベンドラインと共にに開始.  if(three_d_name > (ml_num_bendlines + ml_num_faces))     return NULL;               // 描かれるものはフォーミングである。  if(! loop_name) return NULL;   // 描かれるものはトリビアルなベンドラインである。    if(three_d_name > ml_num_bendlines) {  // three_d_body は面である。    for(three_d_body = part->get_face_list();three_d_body;                           three_d_body = (BM_3D_BODY *)three_d_body->next()) {      if(! three_d_body) return NULL;  ++count;  if((ml_num_bendlines + count) == three_d_name) break;}  }  else {  // three_d_body はベンドラインである。    for(three_d_body = part->get_bendline_list(); three_d_body;                           three_d_body = (BM_3D_BODY *)three_d_body->next()) {      if(! three_d_body) return NULL;  ++count;  if(count == three_d_name) break;    }  }// この時点でエッジが属する面/ベンドラインを持つ。  if(mi_show_3d) two_d_body = three_d_body->get_3D_version();  else two_d_body = three_d_body->get_flat();  if(! two_d_body) return NULL;  if(loop_name == 1) loop = two_d_body->get_bloop();else {    count = 1;    for(loop = two_d_body->get_first_hole(); loop; loop = (BM_LOOP *)loop->next()) {  if(! loop) return NULL;  ++count;  if(count == loop_name) break;}  }// この時点でエッジが属するループを持つ。  count = 0;  for(edge = loop->get_first_edge(); edge; edge = (BM_EDGE *)edge->next()) {if(! edge) break;++count;if(count == edge_name) break;}  return edge;*/}  // This function returns the number of items currently in the selection set.long CBendCADViewPart::get_number_of_selected_items(void){  return m_selection_set.list_size();}/* これにより、他のクラスが選択セットを得ることができる。選択された項目は、配列selected_items_array 内でパスバックされる; それは、この配列が十分な大きさであることを保証するユーザの義務である。サイズnum_requested*2 の配列は確かに十分である。この関数は、もし多くのものが得られるときは、 num_requested 項目までパスバックする。戻り値は、実際にパスバックされた項目の個数である。配列中の復帰された項目のフォーマットは次のように与えられる。 selected_items_array[2*i -2] は描かれたエッジのOpenGL Display List idを含み、またselected_items_array[2*i -1] はそのエッジに対するベンドモデルポインタを含む。例えば、 selected_items_array[0], selected_items_array[1]は, 選択セットなど,選択セット中のnum_requested番目の項目に対する配列[2*num_requested -2],配列array[2*num_requested -1] までの全てのものを含む。エッジポインタがNULLのときは更に、 N をこのエッジのopenG1 display list id （N は長いタイプ）とする必要がある。ケース A):  もし N/10000 > (num_bendlines_in_part +num_faces_in_part) ならば、ユーザはN-(num  bendlines + num faces)のフォーミングを取り上げている。例えば、num bendlines = 4, num  faces = 3, num  formings = 5, N/10000 =9, などのエッジポインタは空である。このとき、ユーザは二回目のフォーミングを取り上げている。ケースB): もし(N%10000)/100== 0 (すなわち、N の100 番目の桁がゼロ) ならば、ユーザはトリビアル(曲げられてない)なベンドラインのセンタラインを取り上げている。ベンドラインは(N/10000) 番目のベンドラインである。例えば、N/10000 = 3,  エッジポインタはNULLであり,(N%10000)/100=0 である。ユーザは、たまたま曲げてない第三番面目のベンドラインを取り上げている。(あなたが驚いても、この部分は少なくとも3 個のベンドラインを持つことが保証される。)*/long CBendCADViewPart::get_selected_items(long num_requested, long *selected_items_array) {  if(selected_items_array == NULL) return 0;  long i = m_selection_set.display(num_requested, selected_items_array);  return i;}  // This allows others to clear the selection set.void CBendCADViewPart::clear_selection_set(void){int size = m_selection_set.list_size(); long *array = new long[(size<<1) + 1];                m_selection_set.display(size, array);for(long i=0; i < size; ++i) {  if(array[(i<<1) + 1]) delete (BV_SELECT_DATA*)array[(i<<1) + 1];}  m_selection_set.remove();delete [] array;}// Thisfunction writes a RenderWare matrix’s rotation part into an array[16],which can be used by// OpenGL. int CBendCADViewPart::convert_rw_matrix_to_gl_array(RwMatrix4d *rw_matrix, double *array){  RwReal rw_array[4][4], *test;  test = RwGetMatrixElements(rw_matrix, rw_array);  if(! test)return 0;  int i, j;  for(i=0; i < 4; ++i) {   for(j=0; j < 4; ++j)  array[4*i + j] = rw_array[i][j];  }  array[15] = 1.0;  array[3] = array[7] = array[11] = 0.0;    return 1;}  // This function allows you to set the drawing mode: show_solid = 1 for solid, 0 for wireframe.// This function assumes that the part has not changed.void CBendCADViewPart::set_drawing_mode(int show_solid){  if(show_solid) OnViewShaded();else OnViewWireframe();}// This function allows you to set the current view of thepart: show_3d = 1 for 3d version,// 0 for flat.// This function assumesthat the part has not changed.void CBendCADViewPart::set_current_view(int show_3d){if(show_3d) OnShow3d();else OnShowFlat();}// This allows youto set both solid/wireframe (show_solid = 0/1) and flat/3d_version (show_3d = 0/1).// If flat is asked for, the picture shown is top view, zoomed-all.// If 3d is asked for and flat is currently in view, the picture shown is 3d, isometric, zoomed-all.// If 3d is asked for and 3d is already currently in view, the view volume is not changed.// If part_has_changed is not zero, re-faceting is done.void CBendCADViewPart::set_drawing_view_mode(int show_solid, int show_3d, int part_has_changed){int show_3d_isometric = 0;if( (! mi_show_3d) && (show_3d) )show_3d_isometric = 1;mi_show_solid = show_solid;mi_show_3d = show_3d;  int i;  BM_PART *part = NULL;  CBendCADDoc* pDoc = GetDocument();  ASSERT_VALID(pDoc);  part = pDoc->get_part();  if(! part) {    mi_part_is_up_to_date = 0;  return;  }  mi_part_is_up_to_date = 1;if(part_has_changed) {    compute_part_centroid(part, 0, &m_flat_part_centroid); // Compute 3d and flat part centroids.    compute_part_centroid(part, 1, &m_3d_part_centroid);  }if(mi_show_solid) {  // Renderware stuff.if(mi_show_3d) {  if(part_has_changed ||(! m_3d_base_clump)) {        i = facet_part_rw(part, &m_3d_base_clump,mi_show_3d, md_part_color);      if( (! i) || (! m_3d_base_clump) ) return;}RwRemoveClumpFromScene(m_base_clump);    m_base_clump = m_3d_base_clump;    RwAddClumpToScene(m_scene, m_base_clump);}else {  if(part_has_changed || (! m_flat_base_clump)) {        i = facet_part_rw(part, &m_flat_base_clump, mi_show_3d, md_part_color);      if( (! i) || (! m_3d_base_clump) ) return;}RwRemoveClumpFromScene(m_base_clump);    m_base_clump =m_flat_base_clump;    RwAddClumpToScene(m_scene, m_base_clump);}}else {// OpenGl stuff.    i =  prepare_display_list(part, mi_show_3d, 1, 0, 1,1, md_face_color, md_bendline_color);    if(! i) {      mi_display_list_is_up_to_date = 0;    return;    }    mi_display_list_is_up_to_date = 1;  if(mi_show_3d) {         mi_3d_is_up_to_date = 1;    mi_flat_is_up_to_date = 0;}else {      mi_3d_is_up_to_date = 0;    mi_flat_is_up_to_date= 1;}}  mi_bbox_is_up_to_date = 0;if(mi_show_3d) m_part_centroid = m_3d_part_centroid;else m_part_centroid = m_flat_part_centroid;if(part_has_changed) {ml_num_faces = part->get_number_of_faces();ml_num_bendlines = part->get_number_of_bendlines();ml_num_formings = part->get_number_of_formings();}  ml_last_function_chosen = RETURN_FROM_DIALOG_MODE;if(show_3d_isometric) {  OnZoomAll();return;}if(! mi_show_3d) {  OnViewTop();return;}return;}
付録Ｆ
コメント付きファイルを含むメインを自動寸法化するBMAPIの例/
*一般的注意:---------------***************---------------一般的注意：−自動寸法化パッケージはそのパートが既に更新されている（すなわちパートの３Ｄバージヨンが既に計算されている）と仮定する。そのパートの現在の３Ｄバージヨンを取り、それを用いる。−04/02/96付の自動寸法化は、単にパートの３Ｄバージヨンに対する寸法を生成する。−04/02/96付の自動寸法化は、パートが厚みを持って示されていると仮定する（すなわち、それは、我々が薄板の一側を示していないと仮定する。）。概要 :---------------***************---------------自動寸法は２種類の描画を行う:- 全てのベンドラインに対するフランジ長さ- 全てのベンドラインに対するベンドライン情報ベンドライン情報は、それが係わるベンドラインを指示する小さなinfo-box内に描かれれる。このinfo-boxを描画する際の唯一の問題点は、ベンドラインが可視であるか、どこにinfo-boxを描くか（すなわち、それが良好に見え、他の成分に干渉せず、例えば、他の事物と重ならないようにそれを描く画面上の場所）、如何にそれをベンドラインと関係付けるかということにある。この成分は比較的容易である。ベンドラインのフランジ長さは、ベンドラインとこのベンドラインの側部の隣接フランジとの間の最大外側距離により与えられる。ベンドラインは高々２つの隣接フランジを持つことが出来、従って両隣接フランジに対してフランジ長さを描かなければならないという点に注意されたい。実際、フランジ長さは、我々がディメンションポイントと呼ぶ点の間で（距離として）描かれる。ここには２種類のディメンションポイントがある。第一のものはベンドラインディメンションポイントである。フランジ長さはベンドラインと隣接フランジの間の（最大外側）距離なので、ベンドラインの側部のこれらのディメンションポイントはベンドラインディメンションポイントと呼ばれる。それらの位置は厳密にベンドラインにより定義される。１本のベンドラインは隣接フランジの各々に関して正確に２つのベンドラインディメンションポイントを持つことが出来る（少なくとも、 BendModel/BendCADの現在のバージヨンでは）という点に注意されたい。２つのベンドラインディメンションポイントはそれぞれベンドラインの２つの端部に対応する。更に、通常は、両隣接フランジに対するこれらのベンドラインディメンションポイントの対は一致する点に注意されたい。すなわち、隣接フランジＡに対するンドラインディメンションポイント（Ａに対して２つのベンドラインディメンションポイントがある）と他の隣接フランジＢに対するベンドラインディメンションポイントと同じものがある。すなわち、それらは特に同一ではないが、同じ値を持つ。ベンドラインディメンションポイントはインタセクシヨン近似（ベンド角が９０度程度）またはタンジェント近似（ベンド角が９０度以上のとき）を用いて計算される。もしベンド角が９０程度のときは、インタセクシヨン近似点は一致するので、両隣接フランジに対するベンドラインディメンションポイントの対は同じになる。他の種類のディメンションポイントはフランジディメンションポイントである。それらは、ベンドラインカラ最も離れたベンドラインの側のベンドラインに隣接するフランジ上の点である。フランジが正しい（��なわち、非空）とすると、少なくとも１つのフランジディメンションポイントがある。ただし、理論的には、フランジディメンションポイントの個数には上限はない。次の重要な点に注目されたい。もしフランジＡが、ベンドラインＢに隣接し、更にその最遠点において（すなわち、Ｂに対するフランジディメンションポイントにおいて）ベンドラインＣに隣接すると、Ａに対するＢのフランジディメンションポイントは、実際にはＡに対するＣの同じベンドラインディメンションポイントである（あるいは、ベンドラインＢとＣが平行と仮定すると、さもなければ事態はトリッキーになり、それは最早真ではない。）。フランジディメンションポイントは、寸法はフランジの側で描かれなければならないので、フランジの角で計算される。以下は自動寸法化作業の方法である。:--------------------------------------**************************************--------------------------------------それは異なる２つのタスクに分割される。１つは全てのディメンションポイント（共に、ベンドラインディメンションポイントとフランジディメンションポイント）を計算するものである。この段階で、我々は、フランジ長さを描くことが出来る全てのディメンションポイントを計算する。潜在的には、これは単に一度行うことが出来、またもし部分が変化しないときは、我々は、自動寸法が描かれなければならない度にこの情報を後に再使用することが出来る。（ただし、部分は通常は変化しない−ユーザが部分を回転させるとき、ビユーアは、カメラ（これは通常なされる）ではなく、実際には部分を回転させる）従って、部分の３Ｄ座標は変化しない。しかし、この種の変化により影響されない部分のフラット部分に基づいて我々の計算をすることが出来るのであるが、幸運にも全てのディメンションポイントの計算はかなり早く、全ての時点でディメンションポイントを再計算することが可能であると思われる。私は丁度、我々が、もし必要なら、これらのディメンションポイントを一度予め計算し、後にそれらを再使用することにより時間を節約出来るということを指摘したい。我々が全てのディメンションポイントを計算すると、我々は寸法を描くことが出来る。ただし、われわれは先ず、ディメンションポイントのどれが可視であり、どれがそうでないかを解決しなければならない。割れれ我ワイヤフレーム像を持つときは、それはかなり容易である。ディメンションポイントは、もしそれがビユーウインド内にあるときは可視である。これのチェックは非常に速くできる。我々が中実（陰影）像を持つときは、通常ビユーアに近いフランジがはるかに離れた他のフランジのビユーをブロックし、同様に幾つかのディメンションポイントをブロックすることから、事態はより困難である。そこで、我々は或る種の隠されたラインの除去を行う必要がある。我々が、どのディメンションポイントが可視であるかを決定すると、フランジ長さは一連の異なる方法で描くことが出来、その場合我々は１つ、望ましくは最良のものを取り上げなければならない。注意：フランジ長さを示すためには、ベンドラインディメンションポイントとフランジディメンションポイントを必要とする。１つの発見的な方法は、ビユーアに近接し、サイドウエイ距離が最小のベン���ライン−フランジ−ディメンションポイントを用いることにより与えられる。我々が全てのベンドラインに対するディメンションポイントを取り出すと、我々は寸法を描くことが出来る。自動寸法化の主要データ構造:----------------------------------------****************************************----------------------------------------３種類の使用対象物がある。BM_AUTO_DIMENSION-----------------BM_AUTO_DIMENSIONは、トップレベルのAuto-Dimension対象物であり、通常はBM_PARTと共にBendCAD書類の一部である。それは、自動寸法が描かれるBM_PARTに対するポインタ、並びに書類、ビユーおよびデバイスコンテクトポインタを含む。それは更に、ビユーウインドサイズ、ベンドラインの個数、 BM_AD_bendline対象物などのようなハイレベルの情報を含む。将来（現在０４／０３／９６），それは、ラインカラーやライン幅、フォントサイズなどのようなペンやブラシ特性についての情報を格納すべきである。BM_AD_bendline--------------BM_AD_bendline は１つのＢＭ  ＡＤベンドラインに関係する全ての自動寸法情報を格納する。また、隣接フランジの各々に対して内蔵の２つのベンドラインディメンションポイントを有する。また、隣接フランジの各々に対してフランジディメンションポイントのリストへのポイントを有する。BM_AD_dim_corner----------------BM_AD_dim_cornerはディメンションポイント（ベンドラインかフランジのいずれか）である。ディメンションポイントは１または3BM_POINTのいずれかを有することが出来る。ディメンションポイントの１つの重要なメンバは開放方向である。それは、このディメンションポイントに関する実際のディメンションが描かれなければならない方向を指示する。更に、このディメンションポイントが可視である方向を指示する。もしそれが可視のときは、それはそのBM_POINTの全ての画面座標を格納する。*/#ifndef BMAPI_AUTO_DIM_HXX_INCLUDED#define BMAPI_AUTO_DIM_HXX_INCLUDED// include some BMAPI include files#include "POINT.HXX"#include "VECTOR.HXX"#include "LINE.HXX"#include "PLANE.HXX"#include "CYLINDER.HXX"#include "2D_BODY.HXX"#include "3D_BODY.HXX"#include "BEND_OP.HXX"#include "BENDLINE.HXX"#include "PART.HXX"// include header for mesh to determine clear regions for drawing#ifndef __AD_MESH_H__#include "AD_Mesh.h"#endif// some BendCAD classesclassCBendCADDoc ;class CBendCADViewPart ;// Auto-Dimension classesclass BM_AD_dim_corner ;class BM_AD_bendline ;class BM_AUTO_DIMENSION ;/*********** ********** ********** ********** ********** ********** ********** ********** ********** 自動寸法定数********** ********** ********** ********** ********** ********** ********** ********** ********** */// dimensionline length is 30 pixels#define PIXELS_PER_DIMENSION_LINE30.0// arrow angle is 30 degrees//#define ARROW_ANGLE0.524// arrow length is 15 pixels//#define PIXELS_PER_ARROW15.0// this is the distance tolerance used inAuto-Dimension#define AUTODIM_DISTANCE_TOLERANCE0.001/*********** ********** ********** ********** ********** ********** ********** ********** ********** この種の対象物は、ディメンションを描くことが出来るディメンションポイントを表す。********** ********** ********** ********** ******************** ********** ********** ********** */class BM_AD_dim_corner{friend BM_AUTO_DIMENSION ;friend BM_AD_bendline ;/*********** ********** ********** ********** ********** ********** ********** ********** **********全てのデータメンバはPrivateなものである。********** ********** ********** ********** ********** ********** ********** ********** ***********/private :// Auto-Dimension BM_AD_bendline object that owns this dimension point// BM_AD_bendline *bend ;// this is the 3D-body in the part thathas to be visible (actually some points on this// body have to be visible) in order for this dimension point to be drawable.// note : this is used only when we are in solid mode.// // usually, for bend-dim points, this points to the bendline, and for flange-dim points // points to the flange. // However, when this dimension point contains only one point (point p), some special // considerations come into effect.// BM_3D_BODY *body_required_visible ;// this variable is used only when we are drawing in a solid mode.// if TRUE, we will ignore this dimension point as if itwas not visible.// // in solid mode we will be using this heuristic in order to save time.// when two bendlines are using equivalent flange-dimension points for (potentially)// displaying flange-length, we will onlycompute the visibility information only// for the bendline (of these twobendlines) which has the larger idx.// // this is initialized to FALSE,and set to TRUE only after all other dim-point computations// have beendone.// int ignore_in_solid_mode ;// Sometimes when the point in the part for which we want to draw dimensions is a// bendline (either inside or outside) such that the radius and thickness both are not 0,// we haveto draw two short lines (as in the picture following) that connect the//outsides of adjacent flanges. However, sometimes (when both radius andthickness // are 0, or the point is just an outside edge of a face) we need only one point.// To capture these two cases, we either compute three points between which the // short line have to be drawn, or just one point (in which case no short lines are needed).// //         ------------     p2// |  \|///          |   p ----------bbFFFFFFFFFFFF//          |     |      bbb  F//   two    |     |   bbb   F// short -----> |  b   F//   lines        | b       bbFFFFFFFFFFFF//  |b     b //  |b   b //  bb //                b      b//   p1 FFFFFFFF//  F F//  F F//  F F//  F F//  F F// // this is the number of points that we have computed here. itis either 1 or 3.// int num_of_points ;// // p is always the centerpoint to which the dimension arrow should be connected to// (actually it iswhat we call a ’dimension-line-extension’).// if we have computed morethan 1 point, p1 and p2 are the side-points.// // IMPORTANT : p1 is onthe plane of the adjacent body for which the flange length is being drawn.// // Note : point p is always computed.// BM_POINT p, p1, p2 ;// thisvariable is used when this dimension point is a flange dimension point,and// the edge in the flange, for which this flange dimension points was computed, // is adjacent to a bendline. adj_bendline points to that bendline.// // this is used to avoid drawing some flange-length twice. forexample, in this picture// //   B2-----------------//   |//   | A//   |//   |//                ---------------B1// // we want to draw dimensions for face A in the middle only once. That means that if// we draw flange length for bendline B1 with respect to A, we should not draw it for //bendline B2 (with respect to A).// BM_BENDLINE *adj_bendline ;// this vector points to the direction in which the dimension should be drawn forthis dim-point.// // IMPORTANT : this vector should be normalized.// BM_VECTOR opening_direction ;// // if this is TRUE, we can reverse the opening_direction if we need.// sometimes the dimension point correcponds to an extreme point of an arc. in that case it does// not matter on whichside we are drawing the dimension arc (ie. we can reverse the opening direction).// int can_reverse_opening_dir ;// // these variable are usedonly when this dimension point is actually drawn.// pos_len is the length of the dimension-line-extension drawn in the direction of the openingvector.// neg_len is the length of the dimension-line-extension drawn inthe direction opposite to // the opening vector.// // they are initially set to 0 when the visibility of this point is computed.// // the purpose is that we can use them to avoid redrawing the same extension line, if several // other dimension points need it.// // Note : as of 04/02/96these points are not used. KK.// double pos_len, neg_len ;// +1, this dimension point is visible and the dimension arc can be drawn for this point.//  0, this dimension point is not visible.／/ -1, we don’t know if this dimension points is visible.// // initially we set this to -1 and use it to compute the visibility information on demand// (ie. only when wewant to know if this points is visible. sometimes we don’t care).// int visible ;// these are the actual view window coordinates of all 3 points.// int screen_x, screen_x1, screen_x2 ;int screen_y, screen_y1, screen_y2 ;// // this is the z-buffer value of the point p when rendered.// double z_buf_value ;// this is used to construct lists of dim-points.// BM_AD_dim_corner *next ;/*********** ********** ********** ********** ********** ********** ********** ********** **********Privateのメンバ関数。自動寸法によってのみ用いられる。********** ********** ********** ********** ********** ********** ********** ********** ***********/// this function computes the visibility of this dimension point.// it handles wireframe and solid modes separately.// this function checks strict visibility.// void compute_visibility(CBendCADViewPart *view) ;// this function will draw the dim-point in the given device context.// this is really just a debug function.// void draw_with_dim_line(CBendCADViewPart *view, CDC *dc, double object_space_per_pixel) ;// given a bendline dimension point and a list of flange dimension points, this function// returns TRUE iff there is a way to display the flange-length-dimension using these points // (ie. there is a pair of points that is visible) or FALSE if not.// If it returns TRUE, it also returns the best flange dimension point ;as well as// the distance between the bendline dimension point p and thebest flange dimension point p, // with respect to the bendline dimension point.// // Note that the best distance returned could be negative since it is the k-factor with respect// to the bendline-dimension-opening-direction-vector.// Remember : bendline-dimension-opening-direction-vector should be normalized.// // this function checks strict visibility.// friend int compute_best_dim_pair(CBendCADViewPart *view, BM_AD_dim_corner*bend_dim_point,BM_AD_dim_corner *flange_dim_list, double object_space_per_pixel, // OUTPUT parametersdouble *best_distance /* distance of thebest flange-dim points found */,BM_AD_dim_corner **best_flange_dim_point/* the best flange-dim points */) ;// this function draws one flange length dimension. the first argument is a bendline dimension point,// thesecond is a flange dimension point.// this function might allow cases where some dimension extension line is a little-bit// outside the view window.// however, endpoints of the dimension arrow have to be within the view window.// friend void draw_dim_point(BM_AD_dim_corner *bend_dim_point, BM_AD_dim_corner *flange_dim_point, CBendCADViewPart *view, CDC *dc,double object_space_per_pixel) ;/*********** ********** ********** ********** ********** ********** ********** ********** **********公共のメンバ関数********** ********** ********** ********** ********** ********** ********** ********** ***********/public :BM_AD_dim_corner(void) ;// thisconstructor is for creating a dimension point that has only one point (point p) in it.// BM_AD_dim_corner(BM_POINT const& p, BM_AD_bendline *bend, BM_3D_BODY *body_required_visible, BM_VECTOR const& opening_direction, int reverse_bit, BM_AD_dim_corner **prev, BM_BENDLINE *adj_bendline) ;// this constructor is for creating a dimension point that has 3 pointsin it.// BM_AD_dim_corner(BM_POINT const& p, BM_POINT const& p1, BM_POINT const& p2, BM_AD_bendline *bend, BM_3D_BODY *body_required_visible, BM_VECTOR const& opening_direction, int reverse_bit, BM_AD_dim_corner **prev, BM_BENDLINE *adj_bendline) ;// to assign one dimension point to another dimension point// it copies contents exactly. not sure if it is a very useful function.// void operator=(BM_AD_dim_corner const &) ;// thisfunction will return TRUE iff the given point is, for the purpose of drawing dimensions,// the same as this point. // Two dimension points points are equivalent iff the point p of one of them is on the// line definedby the line (point p, opening direction) of the other dimension point,// and their opening directions match.// // here we depend on the fact that opening vectors are normalized.// // it returns 2 iff both points p match, otherwise 1.// int operator==(BM_AD_dim_corner const& another_dim_point) ;} ;/*********** ********** ********** ********** ********** ********** ********** ********** ********** この種の対象物は、１ベンドラインに係わる自動寸法化データを表す。ベンドラインに対する基本のＡＤ操作は隣接するフランジ長さを描くことである。技術的注意 :- tベンドラインディメンションポイントとフランジディメンションポイントの開放方向ベクトルは相関付けされない。それは、あなたは、同じ開放方向を持つ２点に対シテチェックするべきである。- アルゴリスム：先ず、我々は全てのベンドラインに対する全てのベンドラインディメンションポイントを計算する。次に、我々は、全てのベンドラインに対する全てのフランジディメンションポイントを計算する。その理由は、我々がフランジディメンションポイントを計算するとき、フランジ内の、および他のベンドラインに隣接する幾つかのエッジがあるということである。全てのベンドラインディメンションを先ず計算するときは、他のBM_AD_bendline構造のベンドラインディメンションポイントからこれらのベクトルを取ることが出来る。********** ********** ********** ********** ********** ********** ********** ********** ********** */class BM_AD_bendline{friend BM_AUTO_DIMENSION ;friend BM_AD_dim_corner ;/*********** ********** ********** ********** ********** ********** ********** ********** **********全てのデータメンバはprivateなものである。********** ********** ********** ********** ********** ********** ********** ********** ***********/private :/*********** ********** ********** ********** ********** ********** ********** ********** **********これらのデータメンバはコンストラクタにより設定される。********** ********** ********** ********** ********** ********** ********** ********** ***********/// information stored in this BM_AD_bendline object refers to this bendline.// ie. this dimension point is drawn to show the flange length of this bendline.// BM_BENDLINE *bend ;// thisobject belongs to this Auto-Dimension object.// BM_AUTO_DIMENSION *parent ;/*********** ********** ********** ********** ********** ********** ********** ********** **********これらのデータメンバは、ベンドラインディメンションポイントデータ構造が、 BM_AD_bendline::compute_BM_AD_bendline(...).で計算されるとき計算される。********** ********** ********** ********** ********** ********** ********** ********** ***********/// if FALSE, this data for this object has not been yet computed, or the computation failed.// this means that this object will always be ignored, no matter what.// this can be set to TRUE only by BM_AD_bendline::compute_BM_AD_bendline(...).// int data_valid ;// number of adjacent bodies for whichwe have to draw dimensions. either 0, 1 or 2.// int num_of_adjacent_bodies ;// every bendline is adjacent to at most two bodies.// either of these can be NULL. you should always check for that.// // adj_body1 is theadjacent body that has the smaller idx.// adj_body2 is the adjacent bodythat has the larger idx.// BM_3D_BODY *adj_body1 ;BM_3D_BODY *adj_body2;// this is the flange length with respect to each of the adjacent bodies// double fl1 ;double fl2 ;/*These parameters are computed some time during the process and are needed later, so forperformance reasons we store them so that we don’t have to recompute them later.Each of them is avector pointing towards the adjacent body (from the bendline) and isona plane tangent to end end-point of the bend-arc touching the adjacent body.*/BM_VECTOR side_vector1 ;BM_VECTOR side_vector2 ;/*これらのパラメータは、プロセス中にしばしば計算され、後に必要とされ、そこで性能理由に対して我々はそれらを、我々がそれらを後に再計算する必要がないように格納する。それらの各々は（ベンドラインから）隣接体に向け指示するベクトルであり、隣接体に接触するベンドアークの端点に対して接線をなす平面上にある。  これらは主要データ構造の幾つかである。  各々の隣接体に対して、ベンドラインの各々の端点（すなわち、左および右）に対して１つの２つ端点を持つ。これらの点は、フランジ長に対する寸法がベンドラインで（すなわち、ベンドラインの側部で）描くことが出来る点を特定する。注意：現在（０４／０２／９６）、我々は全てのベンドラインにおいてディメンションを描くため正確に２つの可能な点を考える。これらの２つの点はベンドラインセンタラインの方向のベンドラインの２つの最端点である。注意：これらはベンドラインのベンドラインディメンションポイントと呼ばれる。注意：これらの点は、例えａｄｊ  ｂｏｄｙ１およびａｄｊ  ｂｏｄｙ２が空であっても常に計算される。*/BM_AD_dim_corner bend_body1_point_left, bend_body1_point_right ;BM_AD_dim_corner bend_body2_point_left, bend_body2_point_right ;// these variables indicate whether theleft(right) bendline dimension points // with respect to adj-body1 and adj-body2 are respectively equivalent.// these points should be computedright after bend_body1_point_left, bend_body1_point_right,// bend_body2_point_left, bend_body2_point_right are computed.// // if 0, they are notequivalent.// if 2, they are equivalent, and points p match.// if 1, they are equivalent, but points p don’t match (ie. on the same line, butsome distance apart).// // for us, equivalence value 2 is the only really useful one, because in that case we can // trust that when one is visible, the other is too, without checking. in that case they have the// same screen coordinates as well.// // note the same means not the same pointers, but the contents are equivalent.// int body12_left_the_same ;intbody12_right_the_same ;/*ここにディメンションポイントの２つのリストがある。１つはadj-bodyに関するもので、他はａｄｊ−ｂｏｄｙ２に関するものである。両リストはフランジ長ディメンションポイントである点を含む。注意：これらはベンドラインのフランジディメンションポイントと呼ばれる。*/BM_AD_dim_corner *body1_points ;BM_AD_dim_corner *body2_points ;/*********** ********** ********** ********** ********** ********** ********** ********************これらのデータメンバは、ディメンションが描かれるとき用いられる。********** ********** ********** ********** ********** ********** ********** ********** ***********/// if this is TRUE, this bendline structure should be ignored for the purpose of drawing dimensions.// this is usually used when we have a simultaneous bendline. in that case we have todraw// dimensions for only one of them, the rest should be ignored.// int ignore ;// if TRUE, the adjacent body already has its flange length drawn.// // if the value is 2, this bendline drew the flange dimension with respect to the adj body.// if the value is 1, some other bendline drewthe flange dimension with respect to the adj body.// int body1_drawn ;int body2_drawn ;// when we draw flange length for adjacent bodies, we will memorize the point at which the// dimensions were drawn.// actually the dimensions are always drawn between two points - one at the bendline,// the other at the farthest point on the adjacent body (ie. bendline dimension point and// flange dimension point).// // the reason we need tomemorize these points is that sometimes the flange-length-dimension// with respect to one bendline is also the flange-length dimension with respect to the// other bendline. in tｈａｔ  case we want to avoid drawing the same thing twice.// // the first two points are bendline dimension points.// other two are flange dimension points.// // reason #2 : when we drawbendline dimensions with respect to adj-body1 and adj-body2,// it depends whether the bend angle is acute or not. if the bend angle is not morethan// 90 degrees, then most likely we will be able to use the same dimension-point at the bendline// to draw both flange length’s. However, if the bend angle is more than 90 degrees, we will// be using the tangent-dimension-point at the bendline and these points are different for// each adjacent body. In general, we want to know, before we draw a dimension-point at a// bendline, if we can use any of the dimension-points already drawn at this bendline.// // note these points do not have to part ofthis AD_bendline structure.// BM_AD_dim_corner *drawn_bend_dim_point1 ;BM_AD_dim_corner *drawn_bend_dim_point2 ;BM_AD_dim_corner *drawn_flange_dim_point1 ;BM_AD_dim_corner *drawn_flange_dim_point2 ;/*********** ********** ********** ********** ********** ********** ********** ********************Privateメンバ−関数********** ********** ********** ********** ********** ********** ********** ********** ***********/// This function computes bendline dimension points of this BM_AD_bendline structure.// Note that bend-dimension points will always be computed, even if adj_body1 and adj_body2// are NULL.// int compute_BM_AD_bendline(void) ;// This function computes flange dimensions points of this BM_AD_bendline structure // with respect to one adjacent body.// int compute_BM_AD_flange_points(BM_3D_BODY *adj_body) ;// This function computes the visibility of all bendline dimension points of the bendline.// note the the visibility of bend-dimension points with respect to adj-body1 is always// computed, even if adj_body1 pointer is NULL.// This is needed for drawing bendline info-boxes.// void compute_bendline_dim_points_visibility(void) ;//this function computes which dimension points are best to draw flange length for this bendline.// // this function does it strictly for one bendline.// void compute_dim_points_to_display_indiv(BM_AD_bendline *best_AD_bendline[2] /* best AD_bendline structure so far */, BM_AD_dim_corner*bodies_bend_flange[6] /* 0,1 is bend-dim points; 3,4 is flange-dim points; 4,5 is flange lists */,double distance_and_z[4] /* 0,1 is distance;3,4 is z-buf */) ;// this function does it for a given bendline, takinginto account simultaneous bendlines.// this function uses the previous function.// void compute_dim_points_to_display(void) ;// this function draws flange length dimensions for this bendline.// it uses the information computed by compute_dim_points_to_display() function.// void draw_dimension_points(void) ;/*********** ********** ********** ********** ********** ********** ********** ********** **********公共メンバ−関数********** ********** ********** ********** ********** ********** ********** ********** ***********/              public :// some trivial constructors,destructors.BM_AD_bendline(BM_AUTO_DIMENSION *owner, BM_BENDLINE *bendline) ;~BM_AD_bendline(void) ;} ;/*********** ********** ********** ********** ********** ********** ********** ********** ********** この対象物は部分に対して自動ディメンションを生成するために用いることが出来る。********** ********** ********** ********** ********** ********** ********** ********** ********** */class BM_AUTO_DIMENSION{friend BM_AD_dim_corner ;friend BM_AD_bendline ;/*********** ********** ********** ********** ********** ********** ********** ********** **********すべてのデータメンバはprivateである。********** ********** ********** ********** ******************** ********** ********** ***********/private :// this is the document to which this auto-dim object is attached to.// also, this is where we get the part.// CBendCADDoc *doc ;// view in which we draw the dimensions.// usually the view attached to the document.// CBendCADViewPart*view ;int view_size_x, view_size_y ;// device context in which we drawthe dimensions.// CDC *dc ;// this is the part for which we will createdimensions.// BM_PART *part ;// is TRUE iff 3D view is being displayed,FALSE if flat.//int view_type ;// half of the metal thickness// double half_metal_thickness ;// if TRUE, we need to recompute auto dimension bendline and point data structures// int dirty ;// number of bendlines in the part// int num_of_bendlines ;// this is an array of bendlines for which flange length has to be drawn.// BM_AD_bendline **bends ;// this is the distance in object space that gets mapped into one pixel on the screen.// we use it to draw lines of fixed pixel length (in that case object-space length varies).// double object_space_per_pixel ;// if this variable is TRUE, it will set the flag which will trigger// auto-dimensions tobe drawn to FALSE in the view class, once dimensions are drawn.// however, once it is done, this variable will be set to FALSE automatically.//int reset_view_to_false_once_drawn ;// every time we construct new dim-point data structures, we set this to FALSE.// when points which can beignored in solid mode have been computed, we set it to TRUE.// int points_to_ignore_in_solid_computed ;// pointer to mesh for determining clearareas of the screen to draw dimension info//CAutoDimRgnMesh *pMesh;// region to keep track of dirty screen areas//CRgn* pDirtyRegion;public:// Booleans for the show state of dimension info//BOOL m_bShowFlangeDim;BOOLm_bShowBendDim;BOOL m_bShowPartDim;// COLORREFs for drawing dimensions//COLORREF m_crFlange;COLORREF m_crBend;COLORREF m_crPart;// pointers tofonts//CFont* m_pFlangeFont;CFont* m_pBendFont;CFont* m_pPartFont;// line and arrow parameters//int m_nLineStyle;int m_nLineWeight;// in pixelsint m_nArrowStyle;int m_nArrowAngle;// in degreesint m_nArrowLength;// inpixels/*********** ********** ********** ********** ********** ********** ********** ********** **********Privateメンバ関数********** ********** ********** ********** ********** ********** ********** ********** ***********/private :// This function is used to propagate the effects of drawing a flange length for a given bendline,// to account for the fact that the flange dimension point is adjacent to the given adj-body.// it returns TRUE iff the adj-bend will be marked as drawn as well with respectto the given flange.// int compute_effects_flange_length_drawn(BM_BENDLINE *bendline, BM_3D_BODY *adj_body /* flange length with respect to this body are being drawn */, BM_AD_dim_corner *bend_dim_point /* bend dimpoint for bendline */, BM_AD_dim_corner *flange_dim_point /* flange dimpoints for bendline */, BM_BENDLINE *adj_bend /* flange dim points is adjacent to this bendline */) ;// this function returns a pointer to the BM_AD_bendline structure that contains data // about the given bendline.// BM_AD_bendline *get_AD_bend_structure(BM_BENDLINE *bendline) ;// thisfunction will return TRUE iff adj_bend has a flange-dimension point withrespect to the// given flange, that is adjacent to the given bendline.// // a handy function.// int check_two_bendlines_adjacent_to_same_flange(BM_BENDLINE *bendline, BM_3D_BODY *flange, BM_BENDLINE *adj_bend) ;// just a debug function// void test_draw(void) ;// Check if we can ignore some points in solid mode.// // in solid mode we will be using this heuristic in order to save time.// when two bendlines are using equivalent flange-dimension points for (potentially)// displaying flange-length, we will only compute the visibility information only// for the bendline (ofthese two bendlines) which has the higher idx.// void compute_points_to_ignore_in_solid(void) ;// this function draws a box with bendline data for every bendline.// void draw_bendline_data(CDC *pdc) ;/*********** ********** ********** ********** ********** ********** ********** ********** **********公共メンバ関数********** ********** ********** ********** ********** ********** ********** ********** ***********/public :BM_AUTO_DIMENSION(CBendCADDoc *BendCAD_doc) ;~BM_AUTO_DIMENSION(void) ;// this function returns a (p->p2) vector for a given bendline with respect to a given adj-body.// // It also computes a line between the p2 points of thebend dimension points of the adjacent bendline // with respect to this flange.// BM_VECTOR const& compute_bend_direction_vector(BM_BENDLINE *bendline, BM_3D_BODY *adj_body, BM_LINE *p2_line) ;// destroy the contentsof this Auto-Dimensions object,// void delete_contents(void) ;// To seta new part. This updates the view class pointer as well.// void set_part(BM_PART *new_part) ;// to force AD to recompute the dimension points.//inline void invalidate(void) { dirty = 1 ; }// get current view type when points were computed// inline int get_view_type(void) const { returnview_type ; }// this function will build auto dimension bendline and point data structures.// // This is the main function for computing dimension points.// int compute_auto_dimension_data(void) ;// draw flange dimension data//void draw_dim_point(BM_AD_dim_corner *bend_dim_point, BM_AD_dim_corner *flange_dim_point, CBendCADViewPart *view, CDC *dc, double object_space_per_pixel);// to draw part dimensions in this device context//int draw_auto_dimensions(CDC *target_dc) ;// Used with draw_auto_dimensions to construct a geometric pen// with user-defined styles. This is necessary to draw patterned thick lines.//CPen* create_auto_dim_pen(CPen*pPen, int nLineStyle, int nLineWeight, COLORREF cr) ;// this will enableus to draw part dimension only once//inline void disable_view_dimensions_flag_next_time(void) { reset_view_to_false_once_drawn = 1 ; }} ;#endif// BMAPI_AUTO_DIM_HXX_INCLUDED
付録Ｇ
機能を描く自動寸法化の例。これらの関数は、デイメンシヨンポイントが既に計算されていることを仮定する。
【０２９６】
///*ディメンションポイントを計算する関数はAD_POINTS.CPP内にある。先ず、どのディメンションポイントが可視であるか、そうでないかを検出する必要がある。次に、フランジ長ディメンションを描く方法を決定しなければならない。*/#include "stdafx.h"#include "BendCAD.h"#include "BendCADDoc.h"#include "BendCADViewPart.h"#include "BCAD_CTXT.HXX"#include "AD_Arrow.h"#include"AUTODIM.HXX"/*********** ********** ********** ********** ********** ********** ********** ********** **********BM_AD_dim_cornerクラススタッフ********** ********** ********** ********** ********** ********** ********** ********** ***********//*この関数はディメンションポイントの可視度を計算する。*/void BM_AD_dim_corner::compute_visibility(CBendCADViewPart *view){int i, j, k ;double z_buf ;// by default, the points is not visiblevisible = 0 ;if (num_of_points < 1) return ;// note : when in wireframemode, we don’t have to check if points p1 and p2 actually// map into the same bendline/flange points. in solid mode we need to check.// checkif we have solid or wireframe mode.if (view->get_drawing_mode()) goto solid_picture ;/*ワイヤフレームは、このディメンションポイントが実際に最前面にある３Ｄ体か否かをチェックしない（原文不明） ワイヤフレームモードでは、我々は、ビユーウインドにおける全ての事態が可視であると仮定する。*///get visibility datai = view->map_point_to_closest_edge(p, &screen_x, &screen_y, &z_buf_value, NULL) ;if (! i) return ;if (num_of_points > 1) {i= view->map_point_to_closest_edge(p1, &screen_x1, &screen_y1, &z_buf, NULL) ;if (! i) return ;i = view->map_point_to_closest_edge(p2, &screen_x2, &screen_y2, &z_buf, NULL) ;if (! i) return ;}// process visibility datapos_len = neg_len = 0.0 ;visible = 1 ;return ;/*ソリッドモードで示されたパート*/solid_picture :// here we keep pointers to 3D-bodies that haveto be visible.BM_3D_BODY *visible_bodies[4] ;visible_bodies[0] = body_required_visible ;if (body_required_visible->is(BM_ENTITY_TYPE_BENDLINE)){visible_bodies[1] = (((BM_BENDLINE *) body_required_visible)->get_adj_list())->find_lowest_id_adj_body() ;visible_bodies[2] = (((BM_BENDLINE *) body_required_visible)->get_adj_list())->find_second_lowest_id_adj_body() ;visible_bodies[3] = NULL ;}else visible_bodies[1] = NULL ;// handlecases when there is just one point differently from when there are 3 points.// if there is only 1 point, we have a complete paper-part - thickness and radius both 0.// in that case there is really no bendline. we have to check any of the adjacent bodies.if (num_of_points < 2) {// if this is a bend-dimension point, the body_required_visible pointer should point to the // adjacent body with respect to this dimension point is computed.i = view->is_3d_body_near_point(p, visible_bodies, &i, &screen_x, &screen_y, &z_buf_value) ;if (! i) return ;}else {/*ソリッド発見手法:これはソリッドモードを操作する新しいバージヨンである。先ず、全ての３点ｐ，ｐ１および２がビユーウインド内にあるかをチェックする。もし真なら、我々は、ベンドアークのサイドプロフィルのセンタ点を計算し、この点におけるベンドラインが実際に可視か否かをチェックする。*/i = view->map_point_to_closest_edge(p, &screen_x, &screen_y, &z_buf_value, NULL) ;if (! i) return ;/*ソリッド発見手法 :開放方向が反転出来ないとき、それが指示していないかをチェックする。if (! can_reverse_opening_dir) {BM_POINT p_opening_direction(p+ opening_direction) ;view->map_point_to_closest_edge(p_opening_direction, &j, &k, &z_buf, NULL) ;if (z_buf > (z_buf_value + 0.001)) return ; // ここで、特定の大きな公差を用いる// 開放方向は指示している}*/// check if points p1 and p2 are in the view window as well.i = view->map_point_to_closest_edge(p1, &screen_x1, &screen_y1, &z_buf, NULL) ;if (! i) return;i = view->map_point_to_closest_edge(p2, &screen_x2, &screen_y2, &z_buf, NULL) ;if (! i) return ;BM_VECTOR v_pp1(p,p1) ;BM_VECTOR v_pp2(p,p2) ;BM_POINT p_center ;double angle_alpha = (v_pp1 ^ v_pp2)/2.0 ;if (angle_alpha < PI_over_2) {BM_VECTOR v_p1p2(0.5*(p2 - p1)) ;BM_POINT temp_p(p1 +v_p1p2) ;BM_VECTOR v_tip(p,temp_p) ;double z = (v_pp1.Len())/cos(angle_alpha) ;double y = z*sin(angle_alpha) ;v_tip.set_length((z - y) + (bend->parent)->half_metal_thickness) ;p_center = p + v_tip ;}else p_center =p ;i = view->is_3d_body_near_point(p_center, visible_bodies, &i, &j, &k,&z_buf) ;if (! i) return ;/*  これはソリッドモードを操作する古いバージヨンである。ここで我々は、ポイントpがビユーウインド内にあるか否かをチェックし、更にポイントp1およびp2が基礎をなす可視の３Ｄ体を持つか否かをチェックする。// もし我々が３点を持つときは、点ｐは３Ｄ体上にはない。従って、我々は、それが有るか否かをチェックするのみである。// ビユーウインド内に。view->is_3d_body_near_point(p, NULL, &i, &screen_x, &screen_y, &z_buf_value) ;if (! i) return ;// ポイントp1およびp2は3D体上になければならない。i = view->is_3d_body_near_point(p1, visible_bodies, &visibility_count, &screen_x1, &screen_y1, &z_buf) ;if (! i) return ;i = view->is_3d_body_near_point(p2, visible_bodies, &visibility_count, &screen_x2, &screen_y2, &z_buf) ;if (! i) return ;*/}// process visibility datapos_len = neg_len = 0.0 ;visible = 1 ;}/*この関数は所定のデバイスコンテクスト内にdim-pointを描く。これは実際にはデバッグ関数である。*/void BM_AD_dim_corner::draw_with_dim_line(CBendCADViewPart *view, CDC *dc, double object_space_per_pixel){int i, j ;double x ;static POINT points[3] ;BOOL res ;// if this point is not known to be visible, return.if (visible < 1) return ;if(num_of_points < 1) return ;points[1].x = screen_x ;points[1].y = screen_y ;// draw dimension lineBM_POINT p_dim_line(p + (PIXELS_PER_DIMENSION_LINE * object_space_per_pixel)*opening_direction) ;view->map_point_to_closest_edge(p_dim_line, &i, &j, &x, NULL) ;points[2].x = i ;points[2].y= j ;if (can_reverse_opening_dir) {p_dim_line = p + (-PIXELS_PER_DIMENSION_LINE * object_space_per_pixel)*opening_direction ;view->map_point_to_closest_edge(p_dim_line, &i, &j, &x, NULL) ;points[1].x = i ;points[1].y= j ;res = dc->Polyline(points + 1, 2) ;points[1].x = screen_x ;points[1].y = screen_y ;}else res = dc->Polyline(points + 1, 2) ;if (num_of_points < 2) return ;points[0].x = screen_x1 ;points[0].y = screen_y1 ;points[2].x = screen_x2 ;points[2].y = screen_y2 ;res = dc->Polyline(points,3) ;}/*この関数は１フランジ長ディメンションを描く。 第一の引数はベンドラインディメンションポイントであり、第二はフランジディメンションポイントである。*/void BM_AUTO_DIMENSION::draw_dim_point(BM_AD_dim_corner *bend_dim_point, BM_AD_dim_corner *flange_dim_point, CBendCADViewPart *view, CDC*dc, double object_space_per_pixel){int i, j ;double x, y, z, dotp, half_dim_line ;BOOL res ;// points with screen coordinates. Windows type.static POINT points[3] ;// these variable store the coordinates of the dim-line-extension endpointsdouble bend_end_x, flange_end_x ;BM_POINT bend_end_p, flange_end_p ;BM_VECTOR end_v(bend_dim_point->opening_direction);// these variables store arrow head endpointsBM_POINT bend_arrow_p, flange_arrow_p ;// compute the dimension line extensionBM_VECTOR v((flange_dim_point->p) - (bend_dim_point->p)) ;x = v % (bend_dim_point->opening_direction) ;if (fabs(x) > AUTODIM_DISTANCE_TOLERANCE) { // we have to extend at least one dimension linehalf_dim_line = (PIXELS_PER_DIMENSION_LINE * object_space_per_pixel)/2.0 ;// here we will first compute extensionlines, then the arrow, and then the dimension points themselvesif (x <0.0) {// here we assume that for bendline, we cannot reverse the openingdirection.// it must be that the flange-dim points has a valid openingdirection in the same direction// as the bend-dim point.// // arrow point is to the right of the bend-dim point.bend_arrow_p = (bend_dim_point->p) + half_dim_line*end_v ;if (! view->map_point_to_closest_edge(bend_arrow_p, &i, &j, &y, NULL)) return ;points[0].x = i ;points[0].y = j ;flange_arrow_p = (flange_dim_point->p) + (-x + half_dim_line)*end_v ;if (! view->map_point_to_closest_edge(flange_arrow_p, &i, &j, &y, NULL)) return;points[1].x = i ;points[1].y = j ;half_dim_line *= 2.0 ;bend_end_x = half_dim_line ;flange_end_x = -x + half_dim_line ;bend_end_p = bend_dim_point->p + bend_end_x*end_v ;flange_end_p = flange_dim_point->p + flange_end_x*end_v ;}else {// here we assume that for bendline, we cannot reverse the opening direction.dotp = (bend_dim_point->opening_direction) % (flange_dim_point->opening_direction) ;// first lets try if we can reversethe flange-dim point opening directionif (dotp < 0.0 || flange_dim_point->can_reverse_opening_dir) {// try to draw the arrow in the middle//// arrow point is midway between flange- and bend-dim points.z = x/2.0 ;bend_arrow_p = (bend_dim_point->p) + z*end_v ;if (! view->map_point_to_closest_edge(bend_arrow_p, &i, &j, &y, NULL)) goto try_other_direction ;points[0].x = i ;points[0].y = j ;flange_arrow_p = (flange_dim_point->p) + (-z)*end_v ;if (! view->map_point_to_closest_edge(flange_arrow_p, &i, &j,&y, NULL)) goto try_other_direction ;points[1].x = i ;points[1].y = j ;bend_end_x = z + half_dim_line ;flange_end_x = -x - half_dim_line ;bend_end_p = bend_dim_point->p + bend_end_x*end_v ;flange_end_p = flange_dim_point->p + flange_end_x*end_v ;goto begin_to_draw ;}try_other_direction :if (dotp > 0.0 || flange_dim_point->can_reverse_opening_dir) {// arrow point is to the right of the flange-dim point.bend_arrow_p = (bend_dim_point->p) + (x + half_dim_line)*end_v ;if (! view->map_point_to_closest_edge(bend_arrow_p, &i, &j, &y, NULL)) return ;points[0].x = i ;points[0].y= j ;flange_arrow_p = (flange_dim_point->p) + half_dim_line*end_v ;if (! view->map_point_to_closest_edge(flange_arrow_p, &i, &j, &y, NULL)) return ;points[1].x = i ;points[1].y = j ;half_dim_line *= 2.0 ;bend_end_x= x + half_dim_line ;flange_end_x = half_dim_line ;bend_end_p = bend_dim_point->p + bend_end_x*end_v ;flange_end_p = flange_dim_point->p + flange_end_x*end_v ;}else return ; // failure, cannot draw because opening direction don’t match or not visible.}}else { // no need to extend dimension lines// check the direction of opening vectorif (end_v % (flange_dim_point->opening_direction) < 0.0) {if (! flange_dim_point->can_reverse_opening_dir) end_v.reverse() ;}bend_end_x = flange_end_x = (PIXELS_PER_DIMENSION_LINE * object_space_per_pixel) ;bend_end_p = bend_dim_point->p +bend_end_x*end_v ;flange_end_p = flange_dim_point->p + flange_end_x*end_v ;bend_arrow_p = bend_dim_point->p + (bend_end_x/2.0)*end_v ;flange_arrow_p = flange_dim_point->p + (flange_end_x/2.0)*end_v ;// compute arrowendpointsif (! view->map_point_to_closest_edge(bend_arrow_p, &i, &j, &y, NULL)) return ;points[0].x = i ;points[0].y = j ;if (! view->map_point_to_closest_edge(flange_arrow_p, &i, &j, &y, NULL)) return ;points[1].x= i ;points[1].y = j ;}begin_to_draw :/*アローを描く。*/// draw arrow line. points[0] is the bend-dim-points side of the arrow.res = dc->Polyline(points, 2) ;// draw arrowsBM_VECTOR v_arrow(flange_arrow_p - bend_arrow_p) ;x = v_arrow.Len() ; // this is the real flange length// change tosolid pen for arrow headsCPen* pArrowPen = new CPen(PS_SOLID, BCAD_context.m_nFlangeLineWeight, BCAD_context.m_crFlange);CPen* pOldPen = dc->SelectObject(pArrowPen);// compute arrow head at bend sideCAutoDimArrow arrowBend(CPoint(points[0].x,points[0].y),CPoint(points[1].x,points[1].y),BCAD_context.m_nArrowAngle,BCAD_context.m_nArrowLength);arrowBend.DrawHead(dc);// compute arrow head at flange sideCAutoDimArrow arrowFlange(CPoint(points[1].x,points[1].y),CPoint(points[0].x,points[0].y),BCAD_context.m_nArrowAngle,BCAD_context.m_nArrowLength);arrowFlange.DrawHead(dc);dc->SelectObject(pOldPen);delete pArrowPen;// write flange length on the screenint center_x = (points[0].x + points[1].x) >> 1 ;int center_y = (points[0].y + points[1].y) >> 1 ;int font_height = 21 ;double dx = (double)(points[1].x - points[0].x) ;double dy = (double) (points[1].y - points[0].y) ;if (fabs(dx) > AUTODIM_DISTANCE_TOLERANCE) {if (dy/dx > 0.0) center_y -= font_height ;}center_x += 3 ; // move the beginning to the right so that it won’t overlap the arrow line.CString str;str.Format("%6.4f",x);CSize sizeTextExtent = dc->GetTextExtent(str);if (pDirtyRegion != NULL){CPoint pntText(center_x, center_y);CRect rectText(pntText, sizeTextExtent);if (!pDirtyRegion->RectInRegion(&rectText))dc->TextOut(center_x,center_y, str);CRgn rgn;rgn.CreateRectRgn(center_x, center_y, center_x+ sizeTextExtent.cx, center_y + sizeTextExtent.cy);pDirtyRegion->CombineRgn(pDirtyRegion, &rgn, RGN_OR);}else{pDirtyRegion = new CRgn();pDirtyRegion->CreateRectRgn(center_x, center_y, center_x + sizeTextExtent.cx, center_y + sizeTextExtent.cy);dc->TextOut(center_x, center_y, str);}/*bend-dim-pointsにp1,p2を描く必要があるならば*/points[1].x = bend_dim_point->screen_x ;points[1].y = bend_dim_point->screen_y ;if (bend_dim_point->num_of_points > 1) {points[0].x = bend_dim_point->screen_x1 ;points[0].y =bend_dim_point->screen_y1 ;points[2].x = bend_dim_point->screen_x2 ;points[2].y = bend_dim_point->screen_y2 ;res = dc->Polyline(points, 3) ;}//draw dimension line extensionview->map_point_to_closest_edge(bend_end_p, &i, &j, &x, NULL) ;points[2].x = i ;points[2].y = j ;res = dc->Polyline(points + 1, 2) ;/*flange-dim-pointsに対してp1,p2を描く必要があるならば*/points[1].x = flange_dim_point->screen_x ;points[1].y = flange_dim_point->screen_y ;if (flange_dim_point->num_of_points > 1) {points[0].x = flange_dim_point->screen_x1 ;points[0].y = flange_dim_point->screen_y1 ;points[2].x = flange_dim_point->screen_x2 ;points[2].y = flange_dim_point->screen_y2 ;res = dc->Polyline(points, 3) ;}// draw dimension line extensionview->map_point_to_closest_edge(flange_end_p, &i, &j, &x, NULL) ;points[2].x = i ;points[2].y = j ;res = dc->Polyline(points + 1, 2) ;}/*ベンドラインディメンションポイントおよびフランジディメンションポイントが与えられると、この関数は、もしこれらのポイントを用いてflange-length-dimensionを表示する方法が有るときはTRUEを戻し、（すなわち、全てが可視である）またはもしそうでないときはFALSEWO戻す。もしそれがTRUEのときは、それは更に最良のフランジディメンションポイントを戻し；同様にベンドラインディメンションポイントに関してベンドラインディメンションポイントpと最良のフランジディメンションポイントpの間の距離を戻す。戻された最良の距離は、それが、bendline-dimension-opening-direction-vectorに対してＫ因子のために負になり得る。ここでこの関数は、dimension-extension-linesが:1つのdimension-extension-lineが単位長さであり、また他のものが、第一のものに達するのに必要な程度に長いように描かれることを仮定する。すなわち、この関数はディメンションポイントの１つに隣接するディメンションアローを描く。すなわち、それは２つのディメンションポイントの間のラインの途中の或る点でディメンションポイントを描くことを試みない。想起：bendline-dimension-opening-direction-vectorは規格化されるべきである。注意：ここでこの関数は、dimension-extension-linesが:1つのdimension-extension-lineが単位長さであり、また他のものが、第一のものに達するのに必要な程度に長いように描かれることを仮定する。すなわち、この関数はディメンションポイントの１つに隣接するディメンションアローを描く。すなわち、それは２つのディメンションポイントの間のラインの途中の或る点でディメンショ��ポイントを描くことを試みない。注意：この関数において、dim pointが可視でない場合直接チェックしない（別の関数を呼び出す）。表示されているウインドウの中にいくつかのdimension-extension-lineがあるかをチェックする。注意：この関数において、ディメンションアローが進む点をチェックする。それらが厳密にビユー領域内に有ることを要求される。注意：この関数において、実際には近似位置を用いる。すなわち、発見手法として。*/int compute_best_dim_pair(CBendCADViewPart *view, BM_AD_dim_corner *bend_dim_point,BM_AD_dim_corner *flange_dim_list, double object_space_per_pixel, // OUTPUT parametersdouble *best_distance /* 見出された最良のflange-dim points の距離 */,BM_AD_dim_corner **best_flange_dim_point /* 最良のflange-dim points */){BM_VECTOR v ;BM_POINT dim_arrow_point ;int i, j,k ;double x, y, dotp ;// if the bendline dimension point is not known to be visible, return FALSE.// otherwise we might be wasting our time.if(bend_dim_point->visible < 1) return 0 ;// scan the list of flange dimension pointsBM_AD_dim_corner *temp_point, *best_fdp = NULL ;double best_distance_so_far ;for (temp_point = flange_dim_list ; temp_point ; temp_point = temp_point->next) {if (! temp_point->visible) continue ;/*ソリッド発見手法 :ソリッドモードにおいて、我々は時間を節約するためにこの発見的手法を用いている。２つのベンドラインがフランジ長を表示するために（潜在的に）等価なflange-dimension pointsを用いているときは、我々は単に、より高いidxを持つベンドライン（これらの２つのベンドラインの）に対してのみ可視度を計算する。*/if (view->get_drawing_mode() && temp_point->ignore_in_solid_mode) continue ;// compute a vector from bend-dim-p to flange-dim-pv = (temp_point->p) - (bend_dim_point->p) ;x = v % (bend_dim_point->opening_direction) ;// check that opening directions are valid.// idea : if bothvectors points in opposite directions are we cannot reverse them,// we cannot use these two dimension points to draw dimensions.dotp = (bend_dim_point->opening_direction) % (temp_point->opening_direction) ;if (dotp <0.0 && ! temp_point->can_reverse_opening_dir && ! bend_dim_point->can_reverse_opening_dir) continue ;// check that the point where the dimension arrow would go is in the view area// note : we will use half-of-the-minimal-extension-length as the unit separating // zero and non-zero length extension lines.if (fabs(x) > AUTODIM_DISTANCE_TOLERANCE) {k = 0 ; //if k is TRUE at the end, we can draw the dimension arrow pointif (x < 0.0) {// note : add space for a line segment where we will draw the arrow// // check if the directions agree. // we check this first, because it would give us a smaller distance.if (dotp > 0.0) {dim_arrow_point = (temp_point->p) + (-x)*(bend_dim_point->opening_direction) ;if (view->map_point_to_closest_edge(dim_arrow_point, &i, &j, &y, NULL)) k = 1 ;}// checkthat the extension of the bend-dim-line is visible.// in that case the opening direction of the flange-dime-line does not matter.if (!k && bend_dim_point->can_reverse_opening_dir) {dim_arrow_point = (bend_dim_point->p) + (x)*(bend_dim_point->opening_direction) ;if (view->map_point_to_closest_edge(dim_arrow_point, &i, &j, &y, NULL)) k = 1 ;}}else { // x > 0.0// note : add space for a line segment where we will draw the arrow.// // check if the extension line is visible.// we check this first, becauseit would give us a smaller distance.if (dotp < 0.0 || temp_point->can_reverse_opening_dir) {dim_arrow_point = (temp_point->p) + (-x)*(bend_dim_point->opening_direction) ;if (view->map_point_to_closest_edge(dim_arrow_point, &i, &j, &y, NULL)) k = 1 ;}// otherwise check if the directionsagree.if (!k) {dim_arrow_point = (bend_dim_point->p) + (x)*(bend_dim_point->opening_direction) ;if (view->map_point_to_closest_edge(dim_arrow_point, &i, &j, &y, NULL)) k = 1 ;}}if (!k) continue ; // cannot draw the dimension arrow point}// check if visibility information is already computed.// if not, compute it. if flange dimension points not visible, continue.if (temp_point->visible < 0) {temp_point->compute_visibility(view) ;if (! temp_point->visible) continue ;}// check if this new distance is the best distanceif (best_fdp) {if (fabs(best_distance_so_far) > fabs(x)){best_fdp = temp_point ;best_distance_so_far = x ;}}else {best_fdp = temp_point ;best_distance_so_far = x ;}// check if we are done.// if we have a point with a distance 0, we are done since we cannot find a betterpoint.if (best_fdp && fabs(best_distance_so_far) <= AUTODIM_DISTANCE_TOLERANCE) break ;}if (best_fdp) {*best_distance = best_distance_so_far ;*best_flange_dim_point = best_fdp ;return 1 ;}return 0 ;}/*********** ********** ********** ********** ********** ********** ********** ********************BM_AD_bendline クラススタッフ********** ********** ******************** ********** ********** ********** ********** ***********//*この関数はベンドラインの全てのベンドラインディメンションポイントの可視度を計算する。注意: 時間の節約のために、我々は、体1 、22の左( 右) ポイントが等価であるか否かをチェックする。*/void BM_AD_bendline::compute_bendline_dim_points_visibility(void){CBendCADViewPart *view = parent->view ;// here we always compute the visibility of adj-body1 bend-dimension points,// even though we don’t check if adj_body1 pointer is NULL or not,// because we might want to know the visibility even if they don’t exist.// // in practice this should not be a problem because almost always there are two// adjacent bodies.// bend_body1_point_left.compute_visibility(view) ;bend_body1_point_right.compute_visibility(view) ;if (adj_body2) {if(2 == body12_left_the_same) {if (bend_body2_point_left.visible = bend_body1_point_left.visible) {// note we are switching pointsbend_body2_point_left.screen_x = bend_body1_point_left.screen_x ;bend_body2_point_left.screen_y = bend_body1_point_left.screen_y ;bend_body2_point_left.screen_x1 = bend_body1_point_left.screen_x2 ;bend_body2_point_left.screen_y1 = bend_body1_point_left.screen_y2 ;bend_body2_point_left.screen_x2 = bend_body1_point_left.screen_x1 ;bend_body2_point_left.screen_y2 = bend_body1_point_left.screen_y1 ;bend_body2_point_left.z_buf_value = bend_body1_point_left.z_buf_value ;}}else bend_body2_point_left.compute_visibility(view) ;if (2 == body12_right_the_same) {if (bend_body2_point_right.visible= bend_body1_point_right.visible) {// note we are switching pointsbend_body2_point_right.screen_x = bend_body1_point_right.screen_x ;bend_body2_point_right.screen_y = bend_body1_point_right.screen_y ;bend_body2_point_right.screen_x1 = bend_body1_point_right.screen_x2 ;bend_body2_point_right.screen_y1 = bend_body1_point_right.screen_y2 ;bend_body2_point_right.screen_x2 = bend_body1_point_right.screen_x1 ;bend_body2_point_right.screen_y2 = bend_body1_point_right.screen_y1 ;bend_body2_point_right.z_buf_value = bend_body1_point_right.z_buf_value ;}}else bend_body2_point_right.compute_visibility(view) ;}// else adj_body2 is NULL and there is nothing to compute}/*この関数はそれを１つのベンドラインに対して厳密に行う。重要：それは単に、どの方法が最良なものかを決定するが、ＡＤが実際にそれをそのように行うか否かを決定することはない。ここで、それは他のデータ構造を更新する何らかかの方法を実施する。端的には、それはＡＤデータ構造のいずれかを変えることはない。注意：始めは何らのチェックもなされない。アイデア：この関数において、我々は、異なるbend-flange-dimポイントの組み合わせに対する値を割り当てる発見的手法を用いる。最終的には、我々は最良の組み合わせを選択する。我々が用いる発見的手法は、ベンドおよびフランジdimポイントの間の距離の組み合わせ、プラスビ���ー画面からのbend-pointの距離である。実際的なトリック：先ず我々は、最も良く知られた距離の値が既に０であるか否かをチェックする。もし０であるなら、我々は、この新しいｂｅｎｄ−ｄｉｍポイントが良好なｚ−ｂｕｆ値を持つときにのみ他のbend-dimポイントに対して最良の一致を見出そうとする。注意：４部分のテストの後、私は、これが丁度非常にわずかな改善を与えることを見出す。それは恐らく５−１０％ＫＫである（原文不明）。*/void BM_AD_bendline::compute_dim_points_to_display_indiv(BM_AD_bendline *best_AD_bendline[2] /* これまでの最良のADベンドライン構造*/,BM_AD_dim_corner *bodies_bend_flange[6] /* 0、1はbend-dim構造であり、３、４はflange-dimポイントであり、４、５はフランジリストである。 */,double distance_and_z[4] /* 0,1は距離であり、3、4はｚ−ｂｕｆである。*/){BM_AD_dim_corner *best_fdp ;double best_distance ;// check adjacent body1if (adj_body1 && ! (body1_drawn)) {// check if we already have a distance 0 bend-flange-dim points. if yes, go in only if the// new bend-dim points has astrictly better z-buf value.if ((NULL == best_AD_bendline[0]) || distance_and_z[2] > (bend_body1_point_left.z_buf_value + AUTODIM_DISTANCE_TOLERANCE) || distance_and_z[0] > AUTODIM_DISTANCE_TOLERANCE) {if (compute_best_dim_pair(parent->view, &bend_body1_point_left, body1_points, parent->object_space_per_pixel, &best_distance, &best_fdp)) {best_distance = fabs(best_distance) ;// check if the new point is betterif (best_AD_bendline[0]) {// heuristic : if the sum of the z-buf value and distance is smallerif ((best_distance + bend_body1_point_left.z_buf_value) < (distance_and_z[0] + distance_and_z[2])) {best_AD_bendline[0] = this ;bodies_bend_flange[0] = &bend_body1_point_left ;bodies_bend_flange[2] = best_fdp ;bodies_bend_flange[4] = body1_points ;distance_and_z[0] = best_distance ;distance_and_z[2] = bend_body1_point_left.z_buf_value ;}}else {best_AD_bendline[0] = this ;bodies_bend_flange[0] = &bend_body1_point_left ;bodies_bend_flange[2] = best_fdp ;bodies_bend_flange[4] = body1_points ;distance_and_z[0] = best_distance ;distance_and_z[2] = bend_body1_point_left.z_buf_value ;}}}// check if we already have a distance 0 bend-flange-dimpoints. if yes, go in only if the// new bend-dim points has a strictly better z-buf value.if (distance_and_z[2] > (bend_body1_point_right.z_buf_value + AUTODIM_DISTANCE_TOLERANCE) || (NULL == best_AD_bendline[0]) ||distance_and_z[0] > AUTODIM_DISTANCE_TOLERANCE) {if (compute_best_dim_pair(parent->view, &bend_body1_point_right, body1_points, parent->object_space_per_pixel, &best_distance, &best_fdp)) {best_distance = fabs(best_distance) ;// check if the new point is betterif (best_AD_bendline[0]) {// heuristic : if the sum of the z-buf value and distance is smallerif ((best_distance + bend_body1_point_right.z_buf_value) < (distance_and_z[0]+ distance_and_z[2])) {best_AD_bendline[0] = this ;bodies_bend_flange[0] = &bend_body1_point_right ;bodies_bend_flange[2] = best_fdp ;bodies_bend_flange[4] = body1_points ;distance_and_z[0] = best_distance ;distance_and_z[2] = bend_body1_point_right.z_buf_value ;}}else {best_AD_bendline[0] = this ;bodies_bend_flange[0] = &bend_body1_point_right ;bodies_bend_flange[2] = best_fdp ;bodies_bend_flange[4] = body1_points ;distance_and_z[0] = best_distance ;distance_and_z[2] = bend_body1_point_right.z_buf_value ;}}}}// check adjacent body2if (adj_body2 && ! (body2_drawn)) {//check if we already have a distance 0 bend-flange-dim points. if yes, go in only if the// new bend-dim points has a strictly better z-buf value.if ((NULL == best_AD_bendline[1]) || distance_and_z[3] > (bend_body2_point_left.z_buf_value + AUTODIM_DISTANCE_TOLERANCE) || distance_and_z[1]> AUTODIM_DISTANCE_TOLERANCE) {if (compute_best_dim_pair(parent->view, &bend_body2_point_left, body2_points, parent->object_space_per_pixel, &best_distance, &best_fdp)) {best_distance = fabs(best_distance) ;// checkif the new point is betterif (best_AD_bendline[1]) {// heuristic : if the sum of the z-buf value and distance is smallerif ((best_distance + bend_body2_point_left.z_buf_value) < (distance_and_z[1] + distance_and_z[3])) {best_AD_bendline[1] = this ;bodies_bend_flange[1] = &bend_body2_point_left ;bodies_bend_flange[3] = best_fdp ;bodies_bend_flange[5] = body2_points ;distance_and_z[1] = best_distance ;distance_and_z[3] = bend_body2_point_left.z_buf_value ;}}else {best_AD_bendline[1] = this ;bodies_bend_flange[1] = &bend_body2_point_left ;bodies_bend_flange[3] = best_fdp ;bodies_bend_flange[5] = body2_points ;distance_and_z[1] = best_distance;distance_and_z[3] = bend_body2_point_left.z_buf_value ;}}}// check if we already have a distance 0 bend-flange-dim points. if yes, go in only if the// new bend-dim points has a strictly better z-buf value.if (distance_and_z[3] > (bend_body2_point_right.z_buf_value + AUTODIM_DISTANCE_TOLERANCE) || (NULL == best_AD_bendline[1]) || distance_and_z[1] > AUTODIM_DISTANCE_TOLERANCE) {if (compute_best_dim_pair(parent->view, &bend_body2_point_right, body2_points, parent->object_space_per_pixel, &best_distance, &best_fdp)) {best_distance = fabs(best_distance) ;// check if the new point is betterif (best_AD_bendline[1]) {// heuristic : if the sum ofthe z-buf value and distance is smallerif ((best_distance + bend_body2_point_right.z_buf_value) < (distance_and_z[1] + distance_and_z[3])) {best_AD_bendline[1] = this ;bodies_bend_flange[1] = &bend_body2_point_right;bodies_bend_flange[3] = best_fdp ;bodies_bend_flange[5] = body2_points;distance_and_z[1] = best_distance ;distance_and_z[3] = bend_body2_point_right.z_buf_value ;}}else {best_AD_bendline[1] = this ;bodies_bend_flange[1] = &bend_body2_point_right ;bodies_bend_flange[3] = best_fdp ;bodies_bend_flange[5] = body2_points ;distance_and_z[1] = best_distance ;distance_and_z[3] = bend_body2_point_right.z_buf_value ;}}}}}/*この関数は、ベンドラインに対するフランジ長さを描く方法を決定する。これは、サブルーチントシテ以前の関数を用いるものにおける以前の関数とは異なっている。それは、ベンドラインに対するフランジ長ディメンションを描く方法、従って全てのデータ構造を更新する方法を決定する。更に、それは同時のベンドラインを考慮する。*/void BM_AD_bendline::compute_dim_points_to_display(void){// qualification checkif (NULL == bend) return ;BM_AD_bendline *bl ;long i ;// these variable store the bendline dimension data that will be used later to draw // 0,1 is with respect to adj-body1; 2,3 is with respect to adj-body2BM_AD_dim_corner *bodies_bend_flange_list[6] ; // 0,1 is bend-dim points; 2,3 is flange-dim points; 4,5 is flange listsdouble distance_and_z[4] ; // 0,1 is distance; 2,3 is z-buf// this is the bendline for whichwe will be drawing the dimensions.// this is trivial when there is no simultaneous bendlines.BM_AD_bendline *best_AD_bendline[2] = { NULL, NULL} ;/*フランジ長を描く最良の方法を計算する。同時のベンドラインを考慮する。*/// these variables are for handling simultaneous bendline property things.BM_BEND_PROPERTY *prop ;BM_LINKED_LIST_NODE *prop_list ;DBM_ARRAY*bendlines ;BM_BENDLINE *bnd ;long size, this_bend_seen = 0 ;for (prop_list = bend->get_properties() ; prop_list ; prop_list = prop_list->next()) {prop = (BM_BEND_PROPERTY *) prop_list->get_obj() ;if (prop->is(BM_TYPE_BEND_SIMULTANEOUS)) {bendlines = (DBM_ARRAY *) prop->get_bendlines() ;size = bendlines->get_size() ;for (i = 0 ; i < size ; i++) {// get a bendline in the bend property objectif (NULL == (bnd = (BM_BENDLINE *) bendlines->get(i))) continue ;bl = parent->get_AD_bend_structure(bnd) ;if (NULL == bl) continue ;if (bl == this) this_bend_seen = 1 ;if (! bl->data_valid || bl->ignore) continue ;// compute how to draw flange length dimensions for this one bendline.bl->compute_dim_points_to_display_indiv(best_AD_bendline, bodies_bend_flange_list, distance_and_z) ;}}}if (! this_bend_seen) { // make sure this bendline gets processedbl = parent->get_AD_bend_structure(bend) ;if (bl && bl->data_valid && ! bl->ignore) {bl->compute_dim_points_to_display_indiv(best_AD_bendline, bodies_bend_flange_list, distance_and_z) ;}}/*同時のベンドにおける全ての他のベンドラインを"ignore"としてマークする。*/for (prop_list = bend->get_properties() ; prop_list ; prop_list = prop_list->next()) {prop = (BM_BEND_PROPERTY *) prop_list->get_obj() ;if (prop->is(BM_TYPE_BEND_SIMULTANEOUS)) {bendlines =(DBM_ARRAY *) prop->get_bendlines() ;size = bendlines->get_size() ;for (i = 0 ; i < size ; i++) {// get next bendline in the bend property objectif (NULL == (bnd = (BM_BENDLINE *) bendlines->get(i))) continue ;bl = parent->get_AD_bend_structure(bnd) ;if (NULL == bl) continue ;// mark asignoreif (bl->adj_body1 && ! (bl->body1_drawn) && bl != best_AD_bendline[0]) {bl->body1_drawn = 1 ;bl->drawn_bend_dim_point1 = bodies_bend_flange_list[0] ;bl->drawn_flange_dim_point1 = bodies_bend_flange_list[2] ;}if(bl->adj_body1 && ! (bl->body2_drawn) && bl != best_AD_bendline[1]) {bl->body2_drawn = 1 ;bl->drawn_bend_dim_point2 = bodies_bend_flange_list[1] ;bl->drawn_flange_dim_point2 = bodies_bend_flange_list[3] ;}}}}/*このベンドラインを図に対してマークする。*/if (best_AD_bendline[0]) {best_AD_bendline[0]->body1_drawn = 2 ;best_AD_bendline[0]->drawn_bend_dim_point1= bodies_bend_flange_list[0] ;best_AD_bendline[0]->drawn_flange_dim_point1 = bodies_bend_flange_list[2] ;}if (best_AD_bendline[1]) {best_AD_bendline[1]->body2_drawn = 2 ;best_AD_bendline[1]->drawn_bend_dim_point2 =bodies_bend_flange_list[1] ;best_AD_bendline[1]->drawn_flange_dim_point2= bodies_bend_flange_list[3] ;}/*flange-dimポイントがベンドラインに隣接するか否かをチェックする。ここではわれわれは同時的なベンドはチェックしない、何故なら、我々が今ここで持つようにそれらは正確に同じフランジリストを持つべきだからである。*/BM_AD_dim_corner *temp_point ;if (best_AD_bendline[0]) {for (temp_point = bodies_bend_flange_list[4] ; temp_point ; temp_point = temp_point->next) {if (NULL == temp_point->adj_bendline) continue ;(best_AD_bendline[0]->parent)->compute_effects_flange_length_drawn(best_AD_bendline[0]->bend,best_AD_bendline[0]->adj_body1, bodies_bend_flange_list[0], bodies_bend_flange_list[2], temp_point->adj_bendline) ;}}if(best_AD_bendline[1]) {for (temp_point = bodies_bend_flange_list[5] ; temp_point ; temp_point = temp_point->next) {if (NULL == temp_point->adj_bendline) continue ;(best_AD_bendline[1]->parent)->compute_effects_flange_length_drawn(best_AD_bendline[1]->bend,best_AD_bendline[1]->adj_body2,bodies_bend_flange_list[1], bodies_bend_flange_list[3], temp_point->adj_bendline) ;}}}/*この関数はこのベンドラインに対するフランジ長さを描く。それは、compute dim points to display()関数により計算された情報を用いる。TODO : この関数においては、われわれは、ベンドラインデイメンシヨンポイントが既に描かれているトラックを保持することが出来る。adj-body1およびadj-body2に対するベンドラインデイメンシヨンポイントは一致する。その場合、それを一回だけ実際に描くべきである。*/void BM_AD_bendline::draw_dimension_points(){// qualification checkif (! data_valid || ignore) return ;if (adj_body1 && 2 == body1_drawn) {parent->draw_dim_point(drawn_bend_dim_point1, drawn_flange_dim_point1, parent->view, parent->dc, parent->object_space_per_pixel) ;}if (adj_body2 && 2 == body2_drawn) {parent->draw_dim_point(drawn_bend_dim_point2, drawn_flange_dim_point2, parent->view, parent->dc, parent->object_space_per_pixel) ;}}/*********** ********** ********** ********** ********** ********** ********** ********** **********BM_AUTO_DIMENSION class stuff.********** ********** ********** ******************** ********** ********** ********** ***********//*これはデバッグ関数である。*/void BM_AUTO_DIMENSION::test_draw(void){BM_AD_dim_corner *temp_point ;int i ;for (i = 0 ; i < num_of_bendlines ; i++) {if (! bends[i]->data_valid) continue ;if (bends[i]->adj_body1) {(bends[i]->bend_body1_point_left).draw_with_dim_line(view,dc,object_space_per_pixel) ;(bends[i]->bend_body1_point_right).draw_with_dim_line(view,dc,object_space_per_pixel) ;for (temp_point = bends[i]->body1_points ; temp_point ; temp_point = temp_point->next) {temp_point->draw_with_dim_line(view,dc,object_space_per_pixel) ;}}if (bends[i]->adj_body2) {(bends[i]->bend_body2_point_left).draw_with_dim_line(view,dc,object_space_per_pixel) ;(bends[i]->bend_body2_point_right).draw_with_dim_line(view,dc,object_space_per_pixel) ;for (temp_point = bends[i]->body2_points ; temp_point ; temp_point =temp_point->next) {temp_point->draw_with_dim_line(view,dc,object_space_per_pixel) ;}}}}/*この関数は全てのベンドラインに対してベンドラインデータと共にｉｎｆｏ−ｂｏｘを描く。アイデア：われわれは、ソリッドモードではレンダウエアはその種の情報を提示しないため、ビユー領域における部分の可視部分のboundingボックスをチェックしない。更に、しばしば、ユーザは部分のデイメンシヨンを診るためにズームインし、その場合、部分によりカバーされないビユーポートの部位はなく、すなわちｂｏｕｎｄｉｎｇボックスは全体のビー領域をカバーし、実際には無用である。代わりに、我々はビユー領域のエッジに沿いベンドライン情報ボックスを描いていることになる。我々はビユー領域を４領域に分割し、ｉｎｆｏ−ｂｏｘが関係するベンドポイントにどれがより近くても、それらの領域にベンドラインｉｎｆｏボックスを配置する。ここで当然、我々はビユーポートの左−右垂直エッジに沿いそれらのボックスを描く。*/void BM_AUTO_DIMENSION::draw_bendline_data(CDC *pdc){int i, j ;// these variablesare used to calculate the info-box size and to draw itint font_height =21 ;int font_avg_char_width = 8 ; // average width of a characterint box_height = (font_height << 1) /* テキストの2列 */ ;int half_box_height =box_height >> 1 ;int box_width!160#= font_avg_char_width * 15 ; // space for15 charactersint box_x ;int vert_space_per_box ;int offset ;// computemaximum number of info-boxes we can draw.int half_max_num_info_boxes = view_size_y / box_height ;if (half_max_num_info_boxes < 1) return ; // not enough screen spaceint max_num_info_boxes =  half_max_num_info_boxes << 1 ;/*我々が表示出来るベンドの個数を計算する。*/int num_bends_to_be_drawn = 0 ;for (i = 0 ; i < num_of_bendlines ; i++) {if (! bends[i]->data_valid || NULL == bends[i]->bend) continue ;// remember, visibility of adj_body1 bend-dimension points is always computed.// here we only check visibility with respect to adj_body1.// most likely visibility with respect to adj_body1 and adj_body2 is the same.if ((bends[i]->bend_body1_point_left).visible || (bends[i]->bend_body1_point_right).visible) {++num_bends_to_be_drawn ;}else continue ;if (num_bends_to_be_drawn >= max_num_info_boxes) break ; // out of view space}// check if there are any bendlines to be drawnif (0 == num_bends_to_be_drawn) return ;/*ベンドラインポインタおよびエンドポイントのy座標を記憶するためのスペースを割り当てる。*/BM_AD_bendline **bendlines = new BM_AD_bendline*[num_bends_to_be_drawn] ;if (NULL == bendlines) return ; // out of spacedouble *bend_y_coordinates = new double[num_bends_to_be_drawn] ;if (NULL == bend_y_coordinates) {// out of spacedelete [] bendlines ; return ; }BM_AD_dim_corner **bend_points = new BM_AD_dim_corner*[num_bends_to_be_drawn] ;if (NULL == bend_points) {delete [] bendlines ; delete [] bend_y_coordinates ; return ; }/*ベンドラインポインタおよびｂｅｎｄ−ｄｉｍ−ｐｏｉｎｔポインタを集める。*/for (i = j = 0 ; i < num_of_bendlines ; i++) {if (! bends[i]->data_valid || NULL == bends[i]->bend) continue ;if (! (bends[i]->bend_body1_point_left).visible && ! (bends[i]->bend_body1_point_right).visible) continue ;// first, decide which of the endpoints we will usebendlines[j] = bends[i] ;if ((bends[i]->bend_body1_point_left).visible) {if (! (bends[i]->bend_body1_point_right).visible) bend_points[j] = &(bends[i]->bend_body1_point_left) ;else {if ((bends[i]->bend_body1_point_left).z_buf_value< (bends[i]->bend扟摯ㅹ灟楯瑮牟杩瑨⸩彺畢彦慶畬⥥戠湥彤潰湩獴橛⁝‽愦灭⠻敢摮孳嵩☭瑧戻湥彤潢祤弱潰湩彴敬瑦 攻獬⁥敢摮灟楯瑮孳嵪㴠☠浡㭰戨湥獤楛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮牟杩瑨 紻敽獬⁥敢摮灟楯瑮孳嵪㴠☠浡㭰戨湥獤楛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮牟杩瑨 椻⁦⬨樫☠瑧㴻渠浵扟湥獤瑟彯敢摟慲湷 牢慥⁫※⼯漠瑵漠⁦楶睥猠慰散⽽椪普ⵯ潢貁铧ꊝ臣ꦁ臣뒁臣芁苣릁臣讁臣鎾臣ꚁ菣ꒂ菣袃苣蚈ꇩ馁苣芀敢摮氭湩ⵥ楤⵭潰湩貁铧ꊝ臣ꚷ臥ꮁ臣蒁藥ꚁ臣鲃菣꾂苣銂郥肂볯醰臣辁臣节꟥膂臣覼胣⪂椯瑮栠污彦捳敲湥㴠⠠楶睥獟穩彥⁸朦㭴朦㭴ㄠ 椻㴠〠㬠⼠ ⁩楷汬戠⁥潴橰㴠渠浵扟湥獤瑟彯敢摟慲湷ⴠㄠ㬠⼠ ⁪楷汬戠⁥潢瑴浯⼯眠⁥楷汬甠敳琠敨敳琠⁯整灭牯牡汩⁹瑳牯⁥瑳晵䉦彍䑁扟湥汤湩⁥瀪扟湥⁤䈻彍䑁摟浩损牯敮⁲瀪扟湥彤潰湩⁴眻楨敬⠠⁩氦㭴樠 睻楨敬⠠⁩氦㭴樠☠浡㭰愦灭※敢摮灟楯瑮孳嵩☭瑧猻牣敥彮⁸氦㭴栠污彦捳敲湥 ⭩‫眻楨敬⠠⁩氦㭴樠☠浡㭰愦灭※敢摮灟楯瑮孳嵪☭瑧猻牣敥彮⁸朦㭴‽慨晬獟牣敥⥮樠ⴭ㬠⼯猠楷捴⁨⁩湡⁤楪⁦椨☠瑬※⥪笠彰敢摮㴠戠湥汤湩獥楛⁝瀻扟湥彤潰湩⁴‽敢摮灟楯瑮孳嵩㬠敢摮楬敮孳嵩㴠戠湥汤湩獥橛⁝戻湥彤潰湩獴楛⁝‽敢摮灟楯瑮孳嵪㬠敢摮楬敮孳嵪㴠瀠扟湥⁤戻湥彤潰湩獴橛⁝‽彰敢摮灟楯瑮㬠絽晩⠠敢摮灟楯瑮孳嵩☭瑧猻牣敥彮⁸氦㭴栠污彦捳敲湥 ⭩‫⼻ ⁩潰湩獴琠⁯桴⁥楦獲⁴湩潦戭硯漠⁮桴⁥楲桧⁴楳敤⨯臣ꆁ苣꺁臥节볯馁臣辂臣膀럥銈迥覼뷤誂臣骤臣꺁湩潦戭硯苣覜臣ꪁ臣鎁臣銂菣Ꞃ菣꾂臣讂胣⪂椯⁦椨☠瑧※慨晬浟硡湟浵楟普彯潢數⥳笠⼯琠潯洠湡⁹潢數潳⁮桴⁥敬瑦猠摩⹥⼯猠牯⁴桴浥愠捣牯楤杮琠⁯⵸潣牯楤慮整⹳⼯琠楨⁳慷⁹敷楷汬洠癯⁥潰湩獴眠瑩⁨桴⁥慬杲獥⁴⵸潣牯楤瑡獥琠⁯桴⁥楲桧⁴楳敤昮牯⠠㵪〠㬠樠☠瑬※⁩※⭪⤫戠湥彤役潣牯楤慮整孳嵪㴠戠湥彤潰湩獴橛ⵝ朦㭴捳敲湥硟㬠䉄彍畑捩卫牯彴潤扵敬戨湥彤役潣牯楤慮整ⱳ⠠湵楳湧摥氠湯⥧椠‬氨湯⁧⤪戠湥汤湩獥 椻㴠栠污彦慭彸畮彭湩潦扟硯獥㬠敽獬⁥晩⠠渨浵扟湥獤瑟彯敢摟慲湷ⴠ椠☩瑧※慨晬浟硡湟浵楟普彯潢數⥳笠⼯琠潯洠湡⁹潢數⁳湯琠敨爠杩瑨猠摩⹥⼯猠牯瑴敨⁭捡潣摲湩⁧潴砠挭潯摲湩瑡獥⼮ 桴獩眠祡眠⁥楷汬洠癯⁥潰湩獴眠瑩⁨桴⁥浳污敬瑳砠挭潯摲慩整⁳潴琠敨氠晥⁴楳敤昮牯⠠⁪‽⁩※⁪氦㭴渠浵扟湥獤瑟彯敢摟慲湷㬠樠⬫ 敢摮祟损潯摲湩瑡獥橛⁝‽敢摮灟楯瑮孳嵪☭瑧猻牣敥彮⁸䐻䵂兟極正潓瑲摟畯汢⡥敢摮祟损潯摲湩瑡獥⬠椠‬用獮杩敮⁤潬杮 渨浵扟湥獤瑟彯敢摟慲湷ⴠ椠Ⱙ⠠潬杮⨠ 戨湥汤湩獥⬠椠⤩㬠⁩‽畮彭敢摮彳潴扟彥牤睡⁮‭慨晬浟硡湟浵楟普彯潢數⁳紻⼯椠⁴潣汵⁤慨敶戠敥⁮桴瑡眠敨⁮敷挠潨敳愠瀠楯瑮映牯⁡敢摮楬敮‬瑩椠⁳潮⁴桴⁥敢瑳瀠楯瑮⼮ 愨瑬潨杵⁨桴獩瀠楯瑮眠獡甠敳⁤潴瀠慬散琠楨⁳潰湩⁴湯琠敨氠晥⵴楲桧⁴楳敤⸩⼯椠慭楧敮愠瀠楯瑮漠⁮桴⁥敬瑦‮瑩挠畯摬戠⁥桴瑡戠瑯⁨湥灤楯瑮⁳牡⁥楶楳汢ⱥ戠瑵⼯漠瑵瀠楯瑮椠⁳潮⁴桴⁥敢瑳‬敢慣獵⁥桴⁥瑯敨⁲湥灤楯瑮漠⁦桴⁥敢摮楬敮椠⁳捡畴污祬琠⁯桴⽥氯晥⁴景漠牵瀠楯瑮昮牯⠠⁪‽‰※⁪氦㭴椠㬠樠⬫ ⽻ 档捥⁫晩眠⁥慨敶挠潨捩楥⁦ℨ⠠敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴敬瑦⸩楶楳汢⁥籼℠⠠敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴楲桧⥴瘮獩扩敬 潣瑮湩敵㬠晩⠠戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮江晥⥴献牣敥彮⁸氦㭴⠠敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴楲桧⥴献牣敥彮⥸敢摮灟楯瑮孳嵪㴠☠浡㭰戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮江晥⥴㬠汥敳戠湥彤潰湩獴橛⁝‽愦灭⠻敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴楲桧⥴㬠晽牯⠠⁪‽⁩※⁪氦㭴渠浵扟湥獤瑟彯敢摟慲湷㬠樠⬫ ⽻ 档捥⁫晩眠⁥慨敶挠潨捩楥⁦ℨ⠠敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴敬瑦⸩楶楳汢⁥籼℠⠠敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴楲桧⥴瘮獩扩敬 潣瑮湩敵㬠晩⠠戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮江晥⥴献牣敥彮♸瑧※戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮牟杩瑨⸩捳敲湥硟 敢摮灟楯瑮孳嵪㴠☠浡㭰戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮江晥⥴㬠汥敳戠湥彤潰湩獴橛⁝‽愦灭⠻敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴楲桧⥴㬠⽽ 瑳牯⁥桴⁥⵹潣牯楤慮整映牯儠極正潳瑲潦⡲⁪‽‰※⁪氦㭴渠浵扟湥獤瑟彯敢摟慲湷㬠樠⬫ 敢摮祟损潯摲湩瑡獥橛⁝‽敢摮灟楯瑮孳嵪☭瑧猻牣敥彮⁹⼻ 潳瑲戠瑯⁨楳敤⁳捡潣摲湩⁧潴琠敨猠牣敥⁮⵹潣牯楤慮整⼯渠瑯⁥⁡汧瑩档㨠眠楨敬琠敨戠湥汤湩獥嵛愠牲祡栠獡戠敥⁮数浲瑵摥‬桴扥湥彤潰湩獴嵛愠牲祡栠獡渠瑯戠敥⹮⼯椠⁮桴⁥敮瑸瀠牡条慲桰眠⁥敲瑳牯⁥桴⁥潰湩⁴牡慲⹹吠䑏⁏›慭⵹敢琠敨敲椠⁳⁡敢瑴牥猠汯瑵潩⹮⼯敷挠畯摬爠獥牯⁴桴⁥牡慲ⱹ戠瑵琠敨⁮敷渠敥⁤潴朠瑥漠楲楧慮⁬⵹潣牯楤慮整⁳牡慲⹹⼯敷挠畯摬樠獵⁴潣灭瑵⁥⁡敳慰慲整瀠牥畭慴楴湯愠牲祡‬畢⁴桴湥眠⁥敮摥猠慰散映牯椠ⱴ愠摮⼯桴⁥潣敤琠⁯潣灭瑵⁥桴⁥数浲瑵瑡潩Ɱ眠楨档椠⁳潮⵮楴楲楶污⼮ 湡睹祡‬潦⁲潮⁷敷樠獵⁴潤椠⁴桴⁥慥祳眠祡椮⁦椨☠瑧※⤰䐠䵂兟極正潓瑲摟畯汢⡥敢摮祟损潯摲湩瑡獥‬用獮杩敮⁤潬杮 Ⱪ⠠潬杮⨠ 敢摮楬敮⥳㬠晩⠠渨浵扟湥獤瑟彯敢摟慲湷ⴠ椠 朦㭴〠 䉄彍畑捩卫牯彴潤扵敬戨湥彤役潣牯楤慮整⁳椫‬用獮杩敮⁤潬杮 渨浵扟湥獤瑟彯敢摟慲湷ⴠ椠Ⱙ⠠潬杮⨠ 戨湥汤湩獥⬠椠⤩㬠潦⁲樨㴠〠㬠樠☠瑬※⁩※⭪⤫笠晩⠠戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮江晥⥴瘮獩扩敬 楻⁦ℨ⠠敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴楲桧⥴瘮獩扩敬 敢摮灟楯瑮孳嵪㴠☠浡㭰戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮江晥⥴㬠汥敳笠晩⠠戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮江晥⥴献牣敥彮⁸氦㭴⠠敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴楲桧⥴献牣敥彮⥸戠湥彤潰湩獴橛⁝‽愦灭⠻敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴敬瑦 攻獬⁥敢摮灟楯瑮孳嵪㴠☠浡㭰戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮牟杩瑨 紻敽獬⁥敢摮灟楯瑮孳嵪㴠☠浡㭰戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮牟杩瑨 紻潦⁲樨㴠椠㬠樠☠瑬渻浵扟湥獤瑟彯敢摟慲湷㬠樠⬫ 楻⁦⠨敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴敬瑦⸩楶楳汢⥥笠晩⠠‡戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮牟杩瑨⸩楶楳汢⥥戠湥彤潰湩獴橛⁝‽愦灭⠻敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴敬瑦 攻獬⁥楻⁦⠨敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴敬瑦⸩捳敲湥硟☠瑧※戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮牟杩瑨⸩捳敲湥硟 敢摮灟楯瑮孳嵪㴠☠浡㭰戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮江晥⥴㬠汥敳戠湥彤潰湩獴橛⁝‽愦灭⠻敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴楲桧⥴㬠絽汥敳戠湥彤潰湩獴橛⁝‽愦灭⠻敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴楲桧⥴㬠⽽鎁臣ꞁ迦뮔臣隺若貁껥蚺臣讂胣⪂猯慴楴⁣档牡椠普彯潢彸整瑸㉛㘵⁝猻慴楴⁣佐义⁔潢彸潣湲牥孳崵㬠瑳瑡捩倠䥏呎愠牲睯㍛⁝䈻彍䕂䑎䥌䕎⨠⁢䈻彍䕂䑎佟⁐截灯㬠䵂㉟彄佂奄截扟摯⁹⼻ꚷ臥銂迦辁胣⪂椯瑮氠晥⁴‽″椻瑮琠灯㬠晩⠠‰㴽椠 潧潴搠慲彷楲桧彴楳敤㬠⼯挠浯異整瘠牥楴慣⁬灳捡⁥数⁲湩潦戭硯敶瑲獟慰散灟牥扟硯㴠瘠敩彷楳敺祟⼠椠㬠⼯挠浯異整瘠牥楴慣⁬景獦瑥映牯琠敨琠灯氭晥⁴潣湲牥漠⁦桴楥普ⵯ潢潸晦敳⁴‽瘨牥彴灳捡彥数彲潢⁸‭潢彸敨杩瑨 朦㭴朦㭴ㄠ㬠潢彸潣湲牥孳崰砮㴠戠硯损牯敮獲㍛⹝⁸‽潢彸潣湲牥孳崴砮㴠氠晥⁴戻硯损牯敮獲ㅛ⹝⁸‽潢彸潣湲牥孳崲砮㴠氠晥⁴‫潢彸楷瑤⁨昻牯⠠⁪‽‰※⁪氦㭴椠†※⭪⤫笠⁢‽敢摮楬敮孳嵪☭瑧戻湥⁤戻灯㴠戠☭瑧朻瑥扟湥彤灯⤨㬠晩⠠啎䱌㴠‽潢⥰挠湯楴畮⁥⼻ 㐰㤳㘹䭋晩⠠楶睥瑟灹⥥戠扟摯⁹‽ⵢ朦㭴敧彴畣牲湥彴䐳癟牥楳湯⤨㬠汥敳戠扟摯⁹‽ⵢ朦㭴敧彴汦瑡⤨㬠潴⁰‽⩪敶瑲獟慰散灟牥扟硯⬠漠晦敳⁴戻硯损牯敮獲せ⹝⁹‽潢彸潣湲牥孳崱礮㴠戠硯损牯敮獲㑛⹝⁹‽潴⁰戻硯损牯敮獲㉛⹝⁹‽潢彸潣湲牥孳崳礮㴠琠灯⬠戠硯桟楥桧⁴猻牰湩晴椨普彯潢彸整瑸∬㩁㔥ㄮⱦ㩌㘥㈮≦⠬潢⵰朦㭴敧彴敢摮慟杮敬⠲⤩㔪⸷㤲㜵ⰸ戨扟摯⵹朦㭴敧彴畣牲湥彴散瑮牥江湩⡥⤩朮瑥江湥⤨ 瀻捤☭瑧吻硥佴瑵㔨‬潴Ɒ椠普彯潢彸整瑸‬瑳汲湥椨普彯潢彸整瑸⤩㬠睳瑩档⠠潢⵰朦㭴敧彴祴数⤨ 捻獡⁥䵂呟偙彅䕂䑎佟彐䕒啇䅌⁒猺牰湩晴椨普彯潢彸整瑸∬㩒㔥㈮ⱦ㩄㔥㈮≦⠬䈨彍䕂䑎佟彐䕒啇䅌⁒⤪戠灯⴩朦㭴敧彴敢摮牟摡畩⡳Ⱙ潢⵰朦㭴敧彴敢摮摟摥捵楴湯⤨ 瀻捤☭瑧吻硥佴瑵㔨‬潴⁰‫潦瑮桟楥桧ⱴ椠普彯潢彸整瑸‬瑳汲湥椨普彯潢彸整瑸⤩㬠牢慥⁫挻獡⁥䵂呟偙彅䕂䑎佟彐佃䥎⁃⼺ 佔佄㨠椠灭敬敭瑮潣楮⁣敢摮漠⹰牢慥⁫紻⼯搠慲⁷潢灸捤☭瑧倻汯汹湩⡥潢彸潣湲牥ⱳ㔠 ⼻ 牤睡牡潲慷牲睯せ⹝⁸‽敬瑦⬠戠硯睟摩桴㬠牡潲孷崰礮㴠琠灯⬠栠污彦潢彸敨杩瑨⼻ 慣捬汵瑡⁥牡潲⁷楴⁰瑡映硩摥瀠牥散瑮条⁥敬杮桴椠⁮牦浯攠摮瀠楯瑮偃楯瑮瀠䱴晥⡴敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴敬瑦献牣敥彮ⱸ戠湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮江晥⹴捳敲湥祟㬩偃楯瑮瀠剴杩瑨戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮牟杩瑨献牣敥彮ⱸ戠湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮牟杩瑨献牣敥彮⥹䌻楓敺楳敺楄晦㴠瀠剴杩瑨ⴠ瀠䱴晥㭴偃楯瑮瀠䅴牲睯楔㭰晩⠠戠湥彤潰湩獴橛⁝㴽☠浡㭰戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮江晥⥴⤠灻䅴牲睯楔⹰⁸‽瑰敌瑦砮⬠猠穩䑥晩⹦硣㠯瀻䅴牲睯楔⹰⁹‽瑰敌瑦礮⬠猠穩䑥晩⹦祣㠯紻汥敳灻䅴牲睯楔⹰⁸‽瑰楒桧⹴⁸‭楳敺楄晦挮⽸㬸瑰牁潲呷灩礮㴠瀠剴杩瑨礮ⴠ猠穩䑥晩⹦祣㠯紻牡潲孷崱砮㴠瀠䅴牲睯楔⹰㭸牡潲孷崱礮㴠瀠䅴牲睯楔⹰㭹摰ⵣ朦㭴潐祬楬敮愨牲睯‬⤲㬠⼯档湡敧琠⁯潳楬⁤数⁮潦⁲牡潲⁷敨摡䍳敐⩮瀠牁潲偷湥㴠渠睥䌠敐⡮卐卟䱏䑉䈬䅃彄潣瑮硥⹴彭䉮湥䱤湩坥楥桧ⱴ䈠䅃彄潣瑮硥⹴彭牣敂摮㬩偃湥‪佰摬敐⁮‽摰ⵣ朦㭴敓敬瑣扏敪瑣瀨牁潲偷湥㬩⼯挠浯異整愠牲睯栠慥䍤畁潴楄䅭牲睯愠牲睯敂摮瀨䅴牲睯楔Ɒ偃楯瑮愨牲睯せ⹝ⱸ牡潲孷崰礮Ⱙ䍂䑁损湯整瑸洮湟牁潲䅷杮敬䈬䅃彄潣瑮硥⹴彭䅮牲睯敌杮桴㬩⼯搠慲⁷牡潲⁷敨摡牡潲䉷湥⹤牄睡效摡搨⥣瀻捤☭瑧医汥捥佴橢捥⡴佰摬敐⥮搻汥瑥⁥䅰牲睯敐㭮⽽뎏臥銂迦辁胣⪂搯慲彷楲桧彴楳敤椺⁦〨㴠‽畮彭敢摮彳潴扟彥牤睡⁮‭⥩朠瑯⁯潤敮㬠潢彸⁸‽楶睥獟穩彥⁸‭潢彸楷瑤⁨‭″氻晥⁴‽潢彸⁸⼻ 潣灭瑵⁥敶瑲捩污猠慰散瀠牥椠普ⵯ潢癸牥彴灳捡彥数彲潢⁸‽楶睥獟穩彥⁹ 渨浵扟湥獤瑟彯敢摟慲湷ⴠ椠 ⼻ 潣灭瑵⁥敶瑲捩污漠晦敳⁴潦⁲桴⁥潴⵰敬瑦挠牯敮⁲景琠敨椠普ⵯ潢潸晦敳⁴‽瘨牥彴灳捡彥数彲潢⁸‭潢彸敨杩瑨 朦㭴朦㭴ㄠ㬠潢彸潣湲牥孳崰砮㴠戠硯损牯敮獲㍛⹝⁸‽潢彸潣湲牥孳崴砮㴠氠晥⁴戻硯损牯敮獲ㅛ⹝⁸‽潢彸潣湲牥孳崲砮㴠氠晥⁴‫潢彸楷瑤⁨戻硯硟⬠‽′昻牯⠠⁪‽⁩※⁪氦㭴渠浵扟湥獤瑟彯敢摟慲湷㬠樠⬫ 扻㴠戠湥汤湩獥橛ⵝ朦㭴敢摮㬠潢⁰‽ⵢ朦㭴敧彴敢摮潟⡰ 椻⁦丨䱕⁌㴽戠灯 潣瑮湩敵㬠⼯〠㌴㤹䬶楋⁦瘨敩彷祴数 形潢祤㴠戠☭瑧朻瑥损牵敲瑮㍟彄敶獲潩⡮ 攻獬⁥形潢祤㴠戠☭瑧朻瑥晟慬⡴ 琻灯㴠⠠⁪‭⥩瘪牥彴灳捡彥数彲潢⁸‫景獦瑥㬠潢彸潣湲牥孳崰礮㴠戠硯损牯敮獲ㅛ⹝⁹‽潢彸潣湲牥孳崴礮㴠琠灯㬠潢彸潣湲牥孳崲礮㴠戠硯损牯敮獲㍛⹝⁹‽潴⁰‫潢彸敨杩瑨㬠灳楲瑮⡦湩潦扟硯瑟硥ⱴ䄢┺⸵昱䰬┺⸶昲Ⱒ戨灯☭瑧朻瑥扟湥彤湡汧㉥⤨⨩㜵㈮㔹㠷⠬形潢祤☭瑧朻瑥损牵敲瑮损湥整彲楬敮⤨⸩敧彴敬⡮⤩㬠摰ⵣ朦㭴敔瑸畏⡴潢彸ⱸ琠灯‬湩潦扟硯瑟硥ⱴ猠牴敬⡮湩潦扟硯瑟硥⥴㬩睳瑩档⠠潢⵰朦㭴敧彴祴数⤨ 捻獡⁥䵂呟偙彅䕂䑎佟彐䕒啇䅌⁒猺牰湩晴椨普彯潢彸整瑸∬㩒㔥㈮ⱦ㩄㔥㈮≦⠬䈨彍䕂䑎佟彐䕒啇䅌⁒⤪戠灯⴩朦㭴敧彴敢摮牟摡畩⡳Ⱙ潢⵰朦㭴敧彴敢摮摟摥捵楴湯⤨ 瀻捤☭瑧吻硥佴瑵戨硯硟‬潴⁰‫潦瑮桟楥桧ⱴ椠普彯潢彸整瑸‬瑳汲湥椨普彯潢彸整瑸⤩㬠牢慥⁫挻獡⁥䵂呟偙彅䕂䑎佟彐佃䥎⁃⼺启䑏⁏›浩汰浥湥⁴潣楮⁣敢摮漠⹰牢慥⁫紻⼯搠慲⁷潢灸捤☭瑧倻汯汹湩⡥潢彸潣湲牥ⱳ㔠 ⼻ 牤睡愠牲睯牡潲孷崰砮㴠氠晥⁴愻牲睯せ⹝ⅹ㘱⌰‽潴⁰‫慨晬扟硯桟楥桧⁴⼻ 慣捬汵瑡⁥牡潲⁷楴⁰瑡映硩摥瀠牥散瑮条⁥敬杮桴椠⁮牦浯攠摮瀠楯瑮偃楯瑮瀠䱴晥⡴敢摮楬敮孳嵪☭瑧戻湥彤潢祤弱潰湩彴敬瑦献牣敥彮ⱸ戠湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮江晥⹴捳敲湥祟㬩偃楯瑮瀠剴杩瑨戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮牟杩瑨献牣敥彮ⱸ戠湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮牟杩瑨献牣敥彮⥹䌻楓敺猠穩䑥晩⁦‽瑰楒桧⁴‭瑰敌瑦䌻潐湩⁴瑰牁潲呷灩椻⁦ 敢摮灟楯瑮孳嵪㴽☠浡㭰戨湥汤湩獥橛ⵝ朦㭴敢摮扟摯ㅹ灟楯瑮江晥⥴⤠灻䅴牲睯楔⹰⁸‽瑰敌瑦砮⬠猠穩䑥晩⹦硣㠯瀻䅴牲睯楔⹰⁹‽瑰敌瑦礮⬠猠穩䑥晩⹦祣㠯紻汥敳灻䅴牲睯楔⹰⁸瀽剴杩瑨砮ⴠ猠穩䑥晩⹦硣㠯瀻䅴牲睯楔⹰⁹‽瑰楒桧⹴⁹‭楳敺楄晦挮⽹㬸慽牲睯ㅛ⹝⁸‽瑰牁潲呷灩砮愻牲睯ㅛ⹝⁹‽瑰牁潲呷灩礮瀻捤☭瑧倻汯汹湩⡥牡潲ⱷ㈠㬩⼯挠慨杮⁥潴猠汯摩瀠湥映牯愠牲睯栠慥獤偃湥‪䅰牲睯敐⁮‽敮⁷偃湥倨当体䥌ⱄ䈠䅃彄潣瑮硥⹴彭䉮湥䱤湩坥楥桧ⱴ䈠䅃彄潣瑮硥⹴彭牣敂摮㬩偃湥‪佰摬敐⁮‽摰ⵣ朦㭴敓敬瑣扏敪瑣瀨牁潲偷湥㬩⼯挠浯異整愠牲睯栠慥䍤畁潴楄䅭牲睯愠牲睯敂摮瀨䅴牲睯楔Ɒ偃楯瑮愨牲睯せ⹝ⱸ牡潲孷崰礮Ⱙ䍂䑁损湯整瑸洮湟牁潲䅷杮敬䈬䅃彄潣瑮硥⹴彭䅮牲睯敌杮桴㬩⼯搠慲⁷牡潲⁷敨摡牡潲䉷湥⹤牄睡效摡搨⥣瀻捤☭瑧医汥捥佴橢捥⡴佰摬敐⥮搻汥瑥⁥䅰牲睯敐㭮⽽늉苣鎽臣龁菣ꊃ菣銂雩뺔臣讂胣⪂搯湯⁥携汥瑥⁥嵛戠湥彤潰湩獴㬠敤敬整嬠⁝敢摮祟损潯摲湩瑡獥㬠敤敬整嵛戠湥汤湩獥㬠⽽螃菣ꒂ苣뎂菣蚃苣릂菣ꮁ菩蚈菣ꒂ菣뎃苣ꢃ菣銂迦辁胣⪂椯瑮䈠彍啁佔䑟䵉久䥓乏㨺牤睡慟瑵彯楤敭獮潩獮䌨䍄⨠慴杲瑥摟⥣䉻彍䑁摟浩损牯敮⩲整灭灟楯瑮㬠湩⁴⁩⼻ 档捥⁫桴瑡眠⁥慨敶愠瘠污摩搠楣⁦丨䱕⁌㴽琠牡敧彴捤 敲畴湲〠㬠⼯挠敨正椠⁦敷渠敥⁤潴爠捥浯異整琠敨搠瑡⁡瑳畲瑣牵獥晩⠠楤瑲⥹笠晩⠠‡潣灭瑵彥畡潴摟浩湥楳湯摟瑡⡡⤩爠瑥牵⁮‰椻⁦搨物祴 敲畴湲〠紻晩⠠啎䱌㴠‽慰瑲 敲畴湲ㄠ㬠捤㴠琠牡敧彴捤㬠⼯朠瑥瘠敩⁷楳敺楶睥獟穩彥⁸‽楶睥☭瑧朻瑥癟敩灷牯彴楷瑤⡨ 瘻敩彷楳敺祟㴠瘠敩⵷朦㭴敧彴楶睥潰瑲桟楥桧⡴ ⼻ 牣慥整愠洠獥⁨潴搠瑥牥業敮挠敬牡猠慰散⁳潴搠慲⁷楤敭獮潩獮☠浡㭰搠瑡灡敍桳㴠渠睥䌠畁潴楄剭湧敍桳瘨敩彷楳敺硟‬楶睥獟穩彥⥹⼻ 档捥⁫晩眠⁥敮摥潴挠浯異整瀠楯瑮⁳潴椠湧牯⁥湩猠汯摩晩⠠楶睥☭瑧朻瑥摟慲楷杮浟摯⡥ 愦灭☻浡㭰℠瀠楯瑮彳潴楟湧牯彥湩獟汯摩损浯異整⥤笠潣灭瑵彥潰湩獴瑟彯杩潮敲楟彮潳楬⡤㬩潽橢捥彴灳捡彥数彲楰數⁬‽楶睥☭瑧朻瑥潟橢捥彴潴摟癥捩彥慲楴⡯ ⼻ 湩瑩慩汬⁹敳⁴污⁬椢湧牯≥映慬獧琠⁯䅆卌⹅眠⁥桳畯摬渠瑯椠湧牯⁥湡瑹楨杮⼮ 污潳‬潮桴湩⁧獩搠慲湷礠瑥昮牯⠠⁩‽‰※⁩氦㭴渠浵潟彦敢摮楬敮⁳※⭩⤫笠敢摮孳嵩☭瑧椻湧牯⁥‽‰戻湥獤楛ⵝ朦㭴潢祤弱牤睡⁮‽敢摮孳嵩☭瑧戻摯㉹摟慲湷㴠〠㬠⽽ꢅ臣꺁菣뎃菣ꦃ苣뎃臣ꢅ臣꺁菣뎃菣ꦃ苣뎃菣ꒂ菣뎃苣ꢃ菣鶃苣뎃菣꺁菣뢂菣ꪃ菣ꒂ苣袨껧馁苣芀⼪潦⁲椨㴠〠㬠椠☠瑬※畮彭景扟湥汤湩獥㬠椠⬫ 楻⁦ℨ戠湥獤楛ⵝ朦㭴慤慴癟污摩 潣瑮湩敵㬠敢摮孳嵩☭瑧挻浯異整扟湥汤湩彥楤彭潰湩獴癟獩扩汩瑩⡹ 椻⁦戨湥獤楛ⵝ朦㭴摡彪潢祤⤱笠潦⁲琨浥彰潰湩⁴‽敢摮孳嵩☭瑧戻摯ㅹ灟楯瑮⁳琻浥彰潰湩⁴※整灭灟楯瑮㴠琠浥彰潰湩⵴朦㭴敮瑸 整灭灟楯瑮☭瑧瘻獩扩敬㴠ⴠ‱紻晩⠠敢摮孳嵩☭瑧愻橤扟摯㉹ 晻牯⠠整灭灟楯瑮㴠戠湥獤楛ⵝ朦㭴潢祤弱潰湩獴㬠琠浥彰潰湩⁴※整灭灟楯瑮㴠琠浥彰潰湩⵴朦㭴敮瑸 整灭灟楯瑮☭瑧瘻獩扩敬㴠ⴠ‱紻⽽ꢅ臣꺁菣뎃菣ꦃ苣뎃臣뺯臣ꚁ胣辏臣릁臣螃苣ꆃ菣랂菣뎃菣ꒂ菣袃苣袨껧馁苣芀⼪潦⁲椨㴠〠㬠椠☠瑬※畮彭景扟湥汤湩獥㬠椠⬫ 楻⁦ℨ戠湥獤楛ⵝ朦㭴慤慴癟污摩簠扼湥獤楛ⵝ朦㭴杩潮敲 潣瑮湩敵㬠敢摮孳嵩☭瑧挻浯異整摟浩灟楯瑮彳潴摟獩汰祡⤨㬠⽽醃菣袃苣辏臣骃菣銂铧邈臣讂胣閃菣뎃苣螃苣ꆃ菣랂菣뎃苣辏臣骃菣銂铧邈臣讂胣⪂⼯ 牣慥整琠敨瀠湥㨠琠灹ⱥ⠠楬敮眩摩桴‬潣潬⹲偃湥瀠湥汆湡敧䌻敐⩮瀠汆湡敧敐⁮‽牣慥整慟瑵彯楤彭数⡮愦灭瀻湥汆湡敧‬䍂䑁损湯整瑸洮湟汆湡敧楌敮瑓汹ⱥ䈠䅃彄潣瑮硥⹴彭䙮慬杮䱥湩坥楥桧ⱴ䈠䅃彄潣瑮硥⹴彭牣汆湡敧㬩⼯猠汥捥湴睥瀠湥‬慳敶漠摬瀠湥偃湥‪佰摬敐⁮‽捤☭瑧医汥捥佴橢捥⡴䙰慬杮健湥㬩佃佌剒䙅漠摬整瑸潣潬⁲‽捤☭瑧医瑥敔瑸潃潬⡲䍂䑁损湯整瑸洮损䙲慬杮⥥㬠湩⁴汯彤止浟摯⁥‽捤☭瑧医瑥歂潍敤吨䅒华䅐䕒呎 ⼻閃菣뎃苣랕臣螃苣ꆃ菣랂菣뎃苣ꢡꓧ馁苣芀⼪晩⠠䍂䑁损湯整瑸洮扟桓睯汆湡敧楄⥭晻牯⠠⁩‽‰※⁩氦㭴渠浵潟彦敢摮楬敮⁳※⭩⤫笠晩⠠‡敢摮孳嵩☭瑧搻瑡彡慶楬⁤籼戠湥獤楛ⵝ朦㭴杩潮敲 潣瑮湩敵㬠敢摮孳嵩☭瑧搻慲彷楤敭獮潩彮潰湩獴⤨紻⽽⼪ 菣벃菣ꒂꃩ龟臣ꢡꓧ銂菣릂菣馁苣芀䉃畲桳戠割摥刨䉇㈨㔵〬〬⤩䌻牂獵⩨瀠汏䉤畲桳㴠搠ⵣ朦㭴敓敬瑣扏敪瑣☨浡㭰牢敒⥤搻ⵣ朦㭴慐湩剴湧瀨楄瑲剹来潩⥮搻ⵣ朦㭴敓敬瑣扏敪瑣瀨汏䉤畲桳㬩⼪敤敬整瀠楄瑲剹来潩㭮䑰物祴敒楧湯㴠丠䱕㭌⨯菣뎃菣ꦃ苣뎃湩潦苣辏臣骃菣銂铧邈臣讂胣⪂⼯ 牣慥整琠敨瀠湥㨠琠灹ⱥ⠠楬敮眩摩桴‬潣潬⹲偃湥瀠湥敂摮䌻敐⩮瀠敂摮敐⁮‽牣慥整慟瑵彯楤彭数⡮愦灭瀻湥敂摮‬䍂䑁损湯整瑸洮湟敂摮楌敮瑓汹ⱥ䈠䅃彄潣瑮硥⹴彭䉮湥䱤湩坥楥桧ⱴ䈠䅃彄潣瑮硥⹴彭牣敂摮㬩⼯猠汥捥⁴桴⁥敮⁷数摮ⵣ朦㭴敓敬瑣扏敪瑣瀨敂摮敐⥮搻ⵣ朦㭴敓呴硥䍴汯牯䈨䅃彄潣瑮硥⹴彭牣敂摮㬩⨯菣뎃菣ꦃ苣뎃湩潦苣辏臣芀⼪晩⠠䍂䑁损湯整瑸洮扟桓睯敂摮楄⥭牤睡扟湥汤湩彥慤慴搨⥣㬠⼯䐠汥瑥⁥桴⁥敭桳渠睯琠慨⁴敷愠敲映湩獩敨⁤楷桴椠⹴⼯敤敬整瀠敍桳⼻꒏臣骃菣銂뻥낸臣鮁苣芀⼪捤☭瑧医汥捥佴橢捥⡴佰摬敐⥮㬠捤☭瑧医瑥敔瑸潃潬⡲汯瑤硥捴汯牯 搻ⵣ朦㭴敓䉴䵫摯⡥汯彤止浟摯⥥㬠⼯猠敥椠⁦敷栠癡⁥潴搠獩扡敬愠瑵ⵯ楤敭獮潩楮杮椠⁮桴⁥楶睥挠慬獳晩⠠敲敳彴楶睥瑟彯慦獬彥湯散摟慲湷 牻獥瑥癟敩彷潴晟污敳潟据彥牤睡⁮‽‰瘻敩⵷朦㭴敳彴畡潴摟浩湥楳湯⡳⤰㬠牽瑥牵⁮‱紻偃湥‪䵂䅟呕彏䥄䕍华佉㩎挺敲瑡彥畡潴摟浩灟湥䌨敐⩮瀠敐Ɱ椠瑮渠楌敮瑓汹ⱥ椠瑮䱮湩坥楥桧ⱴ䌠䱏剏䕒⁆牣笩晩⠠䱮湩坥楥桧⁴㴽ㄠ簠⁼䱮湩卥祴敬㴠‽卐卟䱏䑉瀩敐⵮朦㭴牃慥整敐⡮䱮湩卥祴敬‬䱮湩坥楥桧ⱴ挠⥲⼻ 潦⁲灳敥敤獬筥䉃畲桳戠畲桳敎⡷牣㬩佌䉇啒䡓氠㭢牢獵乨睥䜮瑥潌䉧畲桳☨浡㭰扬㬩坄剏⁄睤瑓汹䅥牲祡㙛㭝湩⁴卮祴敬潃湵⁴‽㬲坄剏⁄睤慄桳敌杮桴㴠㈠⬠⠠䱮湩坥楥桧⁴‪⤴䐻佗䑒搠䑷瑯敌杮桴㴠搠䑷獡䱨湥瑧⁨ 㬴坄剏⁄睤慇䱰湥瑧⁨‽睤慄桳敌杮桴⼠㈠猻楷捴⡨䱮湩卥祴敬笩慣敳倠当䅄䡓携卷祴敬牁慲孹崰㴠搠䑷獡䱨湥瑧㭨⼯瀠硩汥⁳湯睤瑓汹䅥牲祡ㅛ⁝‽睤慇䱰湥瑧㭨⼯瀠硩汥⁳景湦瑓汹䍥畯瑮㴠㈠戻敲歡挻獡⁥卐䑟呏携卷祴敬牁慲孹崰㴠搠䑷瑯敌杮桴⼻ 湯睤瑓汹䅥牲祡ㅛ⁝‽睤慇䱰湥瑧㭨⼯漠晦卮祴敬潃湵⁴‽㬲牢慥㭫慣敳倠当䅄䡓佄㩔睤瑓汹䅥牲祡せ⁝‽睤慄桳敌杮桴⼻漯摮卷祴敬牁慲孹崱㴠搠䝷灡敌杮桴⼻ 景摦卷祴敬牁慲孹崲㴠搠䑷瑯敌杮桴⼻漯摮卷祴敬牁慲孹崳㴠搠䝷灡敌杮桴⼻ 景湦瑓汹䍥畯瑮㴠㐠戻敲歡挻獡⁥卐䑟十䑈呏佄㩔睤瑓汹䅥牲祡せ⁝‽睤慄桳敌杮桴⼻ 湯睤瑓汹䅥牲祡ㅛ⁝‽睤慇䱰湥瑧㭨⼯漠晦睤瑓汹䅥牲祡㉛⁝‽睤潄䱴湥瑧㭨⼯漠摮卷祴敬牁慲孹崳㴠搠䝷灡敌杮桴⼻ 景摦卷祴敬牁慲孹崴㴠搠䑷瑯敌杮桴⼻ 湯睤瑓汹䅥牲祡㕛⁝‽睤慇䱰湥瑧㭨⼯漠晦卮祴敬潃湵⁴‽㬶牢慥㭫災敐⵮朦㭴牃慥整敐⡮卐䝟佅䕍剔䍉簠倠当单剅呓䱙ⱅ䱮湩坥楥桧ⱴ☠浡㭰扬‬卮祴敬潃湵ⱴ搠卷祴敬牁慲⥹紻敲畴湲瀠敐㭮白楯⁤䉃湥䍤䑁潄㩣伺䑮慲䅷瑵䑯浩⤨笠⼯椠⁦敷栠癡⁥潮搠浩湥楳湯漠橢捥ⱴ搠⁯潮桴湩⹧晩丨䱕⁌㴽愠瑵彯楤⥭笠畡潴摟浩㴠渠睥䈠彍啁佔䑟䵉久䥓乏琨楨⥳㬠楽⁦丨䱕⁌㴽畡潴摟浩 敲畴湲㬠䉃湥䍤䑁楖睥慐瑲⨠䅰瑣癩噥敩⁷‽䌨敂摮䅃噄敩偷牡⁴⤪敧彴楶睥䈨久䍄䑁噟䕉彗奔䕐偟剁⥔㬠晩⠠啎䱌㴠‽䅰瑣癩噥敩⥷爠瑥牵⁮椻⁦ℨ䅰瑣癩噥敩⵷朦㭴敧彴畡潴摟浩湥楳湯⡳⤩愠瑵彯楤⵭朦㭴楤慳汢彥楶睥摟浩湥楳湯彳汦条湟硥彴楴敭⤨㬠䅰瑣癩噥敩⵷朦㭴敳彴畡潴摟浩湥楳湯⡳⤱㬠⼯愠睬祡⁳敲潣灭瑵⁥楤敭獮潩⁮潰湩獴畡潴摟浩☭瑧椻癮污摩瑡⡥ 瀻捁楴敶楖睥☭瑧䤻癮污摩瑡⡥⤰㬠㱽牢ਾ믤늌볯㲨牢ਾ菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂꣨鞮臣讂蟨開꿥閳賥ꊖ闦꺁뻤芀菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣꾁胣閃菣뎃苣랕菣ꎂ菣뎃苣ꞃ菣貁迦讁苣讂觥ꮁ꣨鞮臣貂苣芀戼㹲邀볯銼볯鞼胣㲑牢ਾ⼯椣据畬敤∠瑳慤硦栮⌢湩汣摵⁥䈢湥䍤䑁栮⌢湩汣摵⁥䈢湥䍤䑁潄⹣≨椣据畬敤䈢湥䍤䑁楖睥慐瑲栮⌢湩汣摵⁥䄢呕䑏䵉䠮塘⼢⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪䈪彍䑁扟湥汤湩⁥汣獡⁳瑳晵⹦⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⼪⨯臣貂臣膀触躸臣몟뫦릂臣ꢂ菣뢂菣ꒂ菣袃臣鎖臣鶷鯩銂꣨鞮臣讂䵂䅟彄敢摮楬敮㨺潣灭瑵彥䵂䅟彄汦湡敧灟楯瑮⡳⸮ꮁ铧蒁苣貂苣궃菣ꮂ菣ꪁ雩낕臣芁苣芀臣꺁雩낕臣鶃苣뎃菣貁鿥隺菣ꒂ菣꺁볯ꒁ臣鎖臩ꎁ臣뒁臣芁苣뒠郥ꮁ䅆卌銂裦馁胣₂菣꾂菣ꮃ楤꾁菣讃菣袃菣꾂菣ꮃ臣芁苣릁臣ꞁ臣讂胣⪂猯慴楴⁣湩⁴潣灭瑵彥楤瑳湡散晟潲彭敲彦潰湩⡴䵂偟䥏呎挠湯瑳愦灭※瑰⼠‪楧敶⁮敲敦敲据⁥潰湩⁴⼪䈬彍䕖呃剏挠湯瑳愦灭※楤⁲⨯楤敲瑣潩⁮敶瑣牯⨠Ⱟ䈠彍佐义⁔瀪⼠‪潰湩⁴桷獯⁥楤瑳湡散眠⁥慷瑮琠⁯潣灭瑵⁥⼪‬潤扵敬☠浡㭰楤瑳湡散笩䵂噟䍅佔⁒⡶瀪ⴠ瀠⥴㬠潤扵敬砠㴠瘠┠搠物㬠晩⠠⁸氦㭴ⴠ啁佔䥄彍䥄呓乁䕃呟䱏剅乁䕃 敲畴湲〠㬠楤瑳湡散㴠砠㬠敲畴湲ㄠ㬠⽽䈪彍䑁扟湥汤湩㩥挺浯異整䉟彍䑁晟慬杮彥潰湩獴⸨⸮ꮁ苣誂铧蒁苣貂苣궃菣ꮂ菣ꊖ闦芀돦辄볯芏藧馁苣螃苣ꆃ菣랂菣뎃菣릂菣꾁菣ꦃ菣뢂菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣꺁菣릂菣ꞁ臣讂胣鶀럥鶀臣讖铦鞁臣ꪃ苣袃룤꺁菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣꺁胥낕臣鶀迥鶀臣讖铦鞁臣ꪃ苣袃룤꺁菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣꺁胥낕臣覭臣辁臣蒁臣趁胣螃苣ꆃ菣랂菣뎃菣릂菣꾁雩뺔臣芁苣芀臣貂臣骀룥ꪃ苣袃臣颻諥鞁臣肜뻥꺁菣ꦃ菣뢂菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣貁胢視臣讂胢ꮁ룤뒇臣讂菣ꦃ菣뢂菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂賦龁臣蒁臣ꢁ苣辄釥馁苣芀臣貂苣꾁臣릁臣膀껥鮚臣꾁냥螉臣蚈꟨閁苣龁菣ꒂ菣袼볯ꒁ臣ꦃ苣뎃臣袂臣ꮁꛨ袁苣覼苣醈胣貁賦ꒁ臣ꢁ臣몇鷦讂迥붃胦ꮁ苣誂苣龁苣閁苣讂胣鶁臣뒠郥膀菣벃苣꾁臣貂苣꺁냥螉苣讦臣袼볯ꒁ臣ꦃ苣뎃臣袂臣ꮁꛨ袁苣覼胣뺁臣醈胣꾁菣ꒂ菣袃苣钀룤ꞁ귦鎽臣閃菣뎃苣螃苣ꆃ菣랂菣뎃菣ꒂ菣袃臣莀臣讂臣ꢁ苣鮜臣ꪁ臣芀臣꺁雩낕臣膀裦薀臣肉룤꺁苣莃苣銂苣궂菣鞃臣膀菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂雩뺔臣뺁臣ꮁ臣讂臣ꢁ臣몇鷦讂臣趁臣咯啒銂裦鞁胣뺁臣膀裦薀臣膀迧ꢜ臣ꢂ菣뢂臣ꢂ菣覃菣ꒂ菣袃臣醼臣讁苣ꚷ臥螃苣ꆃ菣랂菣뎃菣ꒂ菣袃苣龔裦馁苣鎁臣ꮁ苣誂雩뺔菣ꎂ菣뎃苣ꞃ菣銂雩颁苣薿ꛨ貁臣讂臣趁臣䚯䱁䕓苣뮈臣芀鿥겜髧ꮁ臣膀臣꺁雩낕臣膀菣벃菣궸臣ꆬ臣ꢂ菣뢂臣ꆄꛨ閁苣ꪁ臣ꦃ苣뎃臣芁苣ꢁ臣꾁剔䕕苣뮈臣芀껥鮚臣꾁胣뒛臣뺹臣讁臣ꆝ믤銂믤ꂊ臣讂胣ꢳ蓦骼臣꺁雩낕臣膀苣莃苣꺁苣뎃菣鶃苣뎃菣貁菣ꦃ菣뢂闩鶷鯩ꮁ臣誂胣뺁臣醈胣貁胣鎁臣ꢂ菣覃菣ꒂ菣袃臣뺯臣讂볯閃菣뎃苣覼菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂迦辁臣趁臣銂胨袁臣蒁苣ꢁ臣ꮁ뇦膂苣貂苣芀⼪瑳瑡捩椠瑮氠慥敶摟浩湥楳湯潟数⡮䵂䕟䝄⁅攪杤⁥⨯挠牵敲瑮攠杤⁥⼪䈬彍佌偏⨠汢潯⁰⨯氠潯⁰桷牥⁥桴⁥畣牲湥⁴摥敧戠汥湯獧琠⁯⼪䈬彍䕖呃剏挠湯瑳愦灭※楳敤癟捥潴⁲⨯猠摩⁥敶瑣牯映牯琠敨挠牵敲瑮戠湥汤湩ⵥ橡彤汦湡敧瀠楡⁲⼪‬䵂噟䍅佔⁒潣獮♴浡㭰渠牯慭⁬⨯渠牯慭⁬景琠敨瀠慬敮甠摮牥祬湩⁧桴⁥摡慪散瑮映慬杮⁥⼪笩䵂䕟䝄⁅渪硥彴摥敧㴠⠠䵂䕟䝄⁅⤪攠杤ⵥ朦㭴敮瑸⤨椻⁦丨䱕⁌㴽渠硥彴摥敧 敮瑸敟杤⁥‽汢潯⵰朦㭴敧彴楦獲彴摥敧⤨㬠晩⠠敮瑸敟杤ⵥ朦㭴獩䈨彍久䥔奔呟偙彅䥌䕎⤩笠⼯瀠潲汢浥‮晩琠敨渠硥⁴摥敧⠠桷捩⁨獩愠楬敮 楷汬戠⁥杩潮敲Ɽ眠⁥敮摥琠⽯ 汣獯⁥桴⁥楤敭獮潩⁮敨敲䈮彍䕖呃剏琠浥彰⡶⠨䈨彍䥌䕎⨠ 敮瑸敟杤⥥☭瑧朻瑥癟⤨ ‪楳敤癟捥潴⥲㬠⼯椠⁦桴⁥敮瑸楬敮眠汩⁬潮⁴敢椠湧牯摥眠⁥慣⁮歳灩琠敨挠牵敲瑮攠杤⹥晩⠠整灭癟䰮湥⤨☠瑧䄻呕䑏䵉䑟卉䅔䍎彅佔䕌䅒䍎⁅愦灭☻浡㭰⠠整灭癟┠渠牯慭⥬☠瑬※⸰⤰笠⼯渠硥⁴摥敧椠慳氠湩⁥桴瑡眠汩⁬潮⁴敢椠湧牯摥⼮ 潮整琠慨⁴桴牥⁥獩愠瀠潲汢浥‮晩琠楨⁳摥敧椠⁳⁡楬敮‬湡⁤湯⁥景琠敨琠潷氠湩獥⼠ 爨浥浥扥牥‬敮瑸攠杤⁥獩愠楬敮 獩愠橤捡湥⁴潴愠戠湥汤湩⁥桴瑡⼠ 桴⁥瑯敨⁲獩渠瑯愠橤捡湥⁴潴‬敷猠潨汵⁤汣獯⁥桴⁥楤敭獮潩⹮晩⠠‡摥敧☭瑧椻⡳䵂䕟呎呉彙奔䕐䱟义⥅ 敲畴湲‱䈻彍䐳䉟䑏⁙愪⁢‽摥敧☭瑧朻瑥慟橤扟摯⡹ 䈻彍䐳䉟䑏⁙愪形敮瑸㴠渠硥彴摥敧☭瑧朻瑥慟橤扟摯⡹ 椻⁦ℨ愠⥢笠晩⠠‡扡湟硥⥴爠瑥牵⁮‱椻⁦ℨ愠形敮瑸☭瑧椻⡳䵂䕟呎呉彙奔䕐䉟久䱄义⥅ 敲畴湲ㄠ㬠敲畴湲〠㬠楽⁦ℨ愠形敮瑸 楻⁦ℨ愠ⵢ朦㭴獩䈨彍久䥔奔呟偙彅䕂䑎䥌䕎⤩爠瑥牵⁮‱爻瑥牵⁮‰紻晩⠠ℨ愠ⵢ朦㭴獩䈨彍久䥔奔呟偙彅䕂䑎䥌䕎 愦灭☻浡㭰℠愠形敮瑸☭瑧椻⡳䵂䕟呎呉彙奔䕐䉟久䱄义⥅ 籼扡㴠‽扡湟硥⥴爠瑥牵⁮‱紻⽽ 晩渠硥⁴摥敧椠⁳潮⁴⁡楬敮‬敷栠癡⁥潴挠潬敳琠敨灯湥搠浩湥楳湯敲畴湲〠㬠⽽䈪彍䑁扟湥汤湩㩥挺浯異整䉟彍䑁晟慬杮彥潰湩獴⸨⸮ꮁ苣誂铧蒁苣貂苣궃菣ꮂ菣ꪁ雩낕臣꺁雩낕臣肜苣肸裨蒚臣ꊽ藦ꞁ菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂铧邈臣讂胣醈胣꾁胣醈胣貁菣ꒂ菣ꮁ꿥馁苣螃苣ꆃ菣랂菣뎃菣ꒂ菣袃苣龔裦鞁臣蒁苣ꢁ믤骮臣讂胣鎁臣ꦃ苣뎃臣馃菣覃菣ꒂ菣ꮁ髩ꖎ臣讂臣ꢁ臣몇鷦讂胣⪂猯慴楴⁣䵂䅟彄楤彭潣湲牥⨠牣慥整摟浩灟楯瑮搨畯汢⁥⁤⨯戠湥汤湩⁥牡潣瑵楳敤氠湥瑧⁨牰橯捥整⁤湯潴漠牵瀠慬敮⨠Ⱟ⼠ 桴獥⁥牡⁥慢楳⁣慰慲敭整獲渠敥敤⁤潴搠慲⁷湡⁹楤敭獮潩⁮潰湩䉴彍佐义⁔潣獮♴浡㭰瀠⼠‪潰湩⁴⁰湩琠敨汦湡敧搠浩湥楳湯瀠楯瑮⨠Ⱟ䵂噟䍅佔⁒潣獮♴浡㭰爠⁶⨯爠晥牥湥散瘠捥潴⁲潴洠歡⁥畳敲瀠楯瑮瀠椠⁮桴⁥汦湡敧搠浩湥楳湯瀠楯瑮椠⁳湯琠敨猠浡⁥汰湡⁥獡搠晥湩摥戠⁹桴⁥敢摮楬敮搠浩湥楳湯瀠楯瑮⨠Ⱟ䵂噟䍅佔⁒潣獮♴浡㭰漠数楮杮摟物捥楴湯癟捥潴⁲⨯映牯映慬杮⁥楤敭獮潩⁮潰湩⁴⼪‬湩⁴灯湥湩彧敶瑣牯牟癥牥敳扟瑩䈬彍䑁扟湥汤湩⁥漪湷牥䈬彍䐳䉟䑏⁙䈪摯役敲畱物摥癟獩扩敬䈬彍䑁摟浩损牯敮⁲⨪牰癥⼠‪牰癥潩獵映慬杮⁥楤敭獮潩⁮潰湩⁴湩琠敨氠獩⁴景映慬杮⁥楤灭楯瑮⁳⼪䈬彍䕖呃剏挠湯瑳愦灭※楳敤癟捥潴Ⱳ⼠ 桴獥⁥慰慲敭整獲愠敲甠敳⁤桷湥琠敨氠湩⁥潦⁲桷捩⁨敷愠敲挠浯異楴杮琠敨搠浩湥楳湯瀠楯瑮椠⁳摡慪散瑮⼯潴愠潮桴牥戠湥汤湩⹥潤扵敬搠灟潲彪楳敤癟捥潴⁲⨯搠瀠潲敪瑣摥漠瑮⁯桴⁥楳敤瘭捥潴⁲›湡汧彥慦瑣牯搪椠⁮潣灭瑵彥䵂䅟彄汦湡敧灟楯瑮⡳⸮⤮⨠Ⱟ䵂噟䍅佔⁒愦灭※敢摮慟捲摟物捥楴湯⼠‪楤敲瑣潩⁮景琠敨戠湥⁤牡⁣牰橯捥整⁤湯潴漠牵瀠慬敮⨠⼯‪桳畯摬戠⁥楬敮☭瑧瘻⨠瀠慬敮湟牯慭⁬⼪䈬彍䕖呃剏☠浡㭰戠湥彤楤敲瑣潩⁮⨯瀠楯瑮⁳潴琠敨搠物捥楴湯椠⁮桷捩⁨桴⁥敢摮楬敮∠畴湲≳⨠⼯‪敤数摮⁳湯眠敨桴牥琠敨戠湥⁤湡汧⁥獩愠畣整漠⁲潮⹴⨠⼯‪晩愠畣整琠敨⁮慴杮湥瑴⁯桴⁥瑯敨⁲湥⁤景戠湥⁤牡⁣⼪⨯椠⁦潮⁴捡瑵ⱥ琠敨⁮湡攠摮潰湩⁴景琠敨慴杮湥⁴灡牰硯浩瑡潩⁮⼪⨯戠獡捩污祬琠楨⁳獩琠敨⠠⵰朦㭴㉰ 敶瑣牯映牯琠敨瑯敨⁲敢摮楬敮眠瑩⁨敲灳捥⁴潴琠楨⁳汦湡敧⨠Ⱟ䵂䉟久䱄义⁅愪橤扟湥汤湩⽥‪晩琠敨氠湩⁥獩愠橤捡湥⁴潴愠戠湥汤湩⁥桴獩椠⁳⁡潰湩整⁲潴椠⁴⼪⨯琠楨⁳慰慲敭整⁲獩猠潴敲⁤潴愠潶摩搠慲楷杮猠浯⁥楤敭楮湯⁳睴捩⁥⼪䈬彍䥌䕎潣獮♴浡㭰愠橤扟湥彤㉰江湩⁥⨯琠楨⁳獩琠敨氠湩⁥敢睴敥⁮㉰瀠楯瑮⁳景琠敨戠湥ⵤ楤敭獮潩⁮⼪⨯瀠楯瑮⁳景琠敨愠橤捡湥⁴敢摮楬敮眠瑩⁨敲灳捥⁴潴琠楨⁳汦湡敧⨠⼯‪潮整琠慨⁴畯⁲㉰瀠楯瑮栠獡琠⁯敢漠⁮桴瑡氠湩⹥⨠⼯‪獵慵汬⁹畯⁲⵰朦㭴㉰瘠捥潴⁲獩瀠牥数摮捩汵牡琠⁯桴獩氠湩ⱥ愠瑬潨杵⁨潮⁴污慷獹⨠⤯⽻琯楨⁳畯⁲潬慣⁬潣祰漠⁦桴⁥摡⵪敢摮楬敮瀭楯瑮牥䵂㍟彄佂奄⨠摡彪敢摮㴠愠橤扟湥汤湩⁥䈻彍佐义⁔彰潬慣⡬⁰‫癲 ⼻ 潮整㨠攠敶⁮晩琠楨⁳楬敮椠⁳摡慪散瑮琠⁯湡瑯敨⁲敢摮楬敮‬⼯戠瑵椠⁦桴⁥楬敮眠⁥牡⁥牣慥楴杮琠敨映慬杮⁥楤敭獮潩⁮潰湩⁴潦⁲獩渠瑯瀠牥数摮捩汵牡琠⽯ 桴⁥楳敤瘭捥潴Ⱳ眠⁥桳畯摬渠瑯洠浥牯穩⁥桴瑡琠楨⁳汦湡敧搠浩湥楳湯瀠楯瑮椠⁳摡慪散瑮琠⁯⼯愠戠湥汤湩ⱥ戠捥畡敳琠敨映慬杮⁥敬杮桴搠浩湥楳湯搠慲湷愠⁴桴獩映慬杮⁥楤敭獮潩⁮潰湩⁴⼯椠⁳潮⁴慰慲汬汥琠⁯桴⁥楳敤瘭捥潴⁲景琠敨愠橤捡湥⁴敢摮楬敮眠瑩⁨敲灳捥⁴潴琠楨⁳汦湡敧椮⁦愨橤扟湥汤湩⁥愦灭☻浡㭰映扡⡳敢摮慟捲摟物捥楴湯┠楳敤癟捥潴⥲☠瑬※戨湥彤牡彣楤敲瑣潩⹮敌⡮ ‭啁佔䥄彍䥄呓乁䕃呟䱏剅乁䕃⤩⽻ 潮⁴数灲湥楤畣慬慲橤扟湥汤湩⁥‽啎䱌㬠⽽ 档捥⁫晩琠敨氠湩⁥獩愠瑴捡敨⁤潴愠戠湥汤湩楥⁦搨☠瑬㴻䄠呕䑏䵉䑟卉䅔䍎彅佔䕌䅒䍎⥅笠⼯渠瑯愠瑴捡敨瑤⁯⁡敢摮楬敮‬牯戠瑯⁨桴捩湫獥⁳湡⁤敢摮楬敮爠摡畩⁳牡⁥⸰⼯挠敲瑡⁥⁡ⴱ潰湩⁴汦湡敧搭浩湥楳湯瀠楯瑮⼮ 潮整琠慨⁴潢祤牟煥極敲彤楶楳汢⁥潰湩獴潴琠敨映慬杮⁥楷桴爠獥数瑣琠⁯桷捩⁨⼯琠敨搠浩湥楳湯瀠楯瑮椠⁳潣灭瑵摥爮瑥牵⁮敮⁷䵂䅟彄楤彭潣湲牥瀨江捯污‬睯敮Ⱳ䈠摯役敲畱物摥癟獩扩敬‬灯湥湩彧楤敲瑣潩彮敶瑣牯‬灯湥湩彧敶瑣牯牟癥牥敳扟瑩‬牰癥‬摡彪敢摮楬敮 紻⼯潮整琠慨⁴楳据⁥敷栠癡⁥″潰湩獴渠睯‬桴獩氠湩⁥獩愠橤捡湥⁴潴愠潮桴牥敢摮楬敮⼮ 潣灭瑵⁥ㅰ‮彰潬慣⁬獩瀠⸱⼯挠浯異整瀠䵂偟䥏呎搠浩灟瀨江捯污‫彤牰橯獟摩彥敶瑣牯猪摩彥敶瑣牯 ⼻ 潣灭瑵⁥㉰敢摮慟捲摟物捥楴湯献瑥江湥瑧⡨⥤㬠䵂偟䥏呎搠浩灟⠲彰潬慣⁬‫敢摮慟捲摟物捥楴湯 ⼻ 潮⁷桴⁥牰扯敬⁭獩琠慨⁴楷桴爠獥数瑣琠⁯桴⁥摡慪散瑮戠湥汤湩ⱥ漠牵映慬杮⁥楤敭獮潩灮楯瑮⽳ ⁰湡⁤ㅰ洠杩瑨渠瑯戠⁥湯琠敨漠瑵楳敤ⴠ琠敨⁹潣汵⁤敢漠⁮桴⁥湩楳敤⼮ 桴⁥楤瑳湡散映潲⁭⁰潴瀠′敤数摮⁳湯琠慨⹴⼯栠睯癥牥‬敷欠潮⁷桴⁥㉰氭湩⁥景琠敨愠橤捡湥⁴敢摮楬敮⠠楷桴爠獥数瑣琠⁯畯⁲汦湡敧Ⱙ⼯猠⁯敷楷汬挠浯異整琠敨搠獩慴据⁥敢睴敥⁮桴瑡瀠ⴲ楬敮愠摮搠浩灟⸲⼠ 敷眠汩⁬獵⁥桴瑡琠⁯潣灭瑵⁥桴⁥潣牲捥⁴㉰瀠楯瑮映牯漠牵映慬杮⁥楤敭獮潩⁮渨瑯⁥桴瑡⼯漠牵瀠′潰湩⁴慨⁳潴戠⁥湯琠敨瀠ⴲ楬敮漠⁦桴⁥摡慪散瑮戠湥汤湩⥥搮畯汢⁥楤瑳湡散㬠䵂摟獩慴据彥敢睴敥彮潰湩彴湡彤楬敮搨浩灟ⰲ愠橤扟湥彤㉰江湩ⱥ☠浡㭰楤瑳湡散‬䈨彍佐义⁔⤪丠䱕⥌㬠敢摮摟物捥楴湯献瑥江湥瑧⡨楤瑳湡散 搻浩灟′‽楤彭㉰⬠戠湥彤楤敲瑣潩⁮⼻ 潮整琠慨⁴桴⁥潢祤牟煥極敲彤楶楳汢灥楯瑮牥瀠楯瑮⁳潮⁴潴琠楨⁳汦湡敧‬畢⁴潴琠敨⼠ 摡慪散瑮戭湥汤湩⁥湩瑳慥Ɽ䄠坌奁ⱓ攠敶⁮晩琠楨⁳汦湡敧搠浩瀠楯瑮眠汩⁬潮⁴敢洠牡敫⁤獡⼯愠橤捡湥⁴潴愠潮桴牥戠湥汤湩⹥敲畴湲渠睥䈠彍䑁摟浩损牯敮⡲楤彭Ɒ瀠江捯污‬楤彭㉰‬睯敮Ⱳ愠橤扟湥⁤‿摡彪敢摮㨠䈠摯役敲畱物摥癟獩扩敬‬灯湥湩彧楤敲瑣潩彮敶瑣牯‬灯湥湩彧敶瑣牯牟癥牥敳扟瑩‬牰癥‬摡彪敢摮楬敮 紻⨯臣꺁雩낕臣ꎚ軦閃菣뎃苣ꮁ꿥馁苣閃菣뎃苣螃苣ꆃ菣랂菣뎃菣ꒂ菣袃苣袨껧馁苣芀돦辄볯鎁臣ꊖ闦꺁鯧趉臣袨껧鞁臣몟뫦鶃苣뎃菣꾁胣醈胣貁믤辄臣꺨ꇩ꺁摡⵪潢祤鷩銂鏦鲽蟥ꖝ苣銂ꋧ龮臣馁苣龁苣ꮁ룤袁苣貂苣芀곧肸臣辕ꇩ꾁胣醈胣貁胣憁橤戭摯꺁볯ꆬ藥ⶃ邃菣뢂菣뎃臣銼곦莅‭潢祤臣侌呕䥓䕄臣龁臣䦯华䑉銂ꇨ馁臣ꦁ臣讁꟨覂臣蒁臣蒁臣鎁臣ꞁ臣讂胣醈胣꾁胣馃菣覃菣ꒂ菣ꮁ꿥馁苣馃菣覃菣ꒂ菣螃苣ꆃ菣랂菣뎃菣ꒂ菣袃臣侌呕䥓䕄菣ꒂ菣袃臣芁苣鎁臣銂鿧ꎁ臣蒁苣芀臣ꂁ臣膀愠橤戭摯貁飦궞臣䦫华䑉銂ꇨ馁臣蒁臣鎁臣貁臣誂뻥讂胣鶁臣뒠郥膀臣鎁臣袨껧鞁苣蚁臣鞁臣蒁苣ꢅ臣꺁菣ꒂ菣袃苣랂菣袃臣鮁苣ꚸ胩馃苣袃菣銂꣨鞮臣讂鿥隺菣ꒂ菣袃볯鎁苣꾁摡⵪潢祤臣隤臥ꊝ룤ꮁ臣讂볯ꮁ꿥鞁臣ꢔ臣覂苣讂胣뒛臣膀臣꺁룤늀菣꾂菣ꮃ苣ꢔ臣ꚁ胣閃菣뎃苣螃苣ꆃ菣랂菣뎃菣ꒂ菣袃臣鶃苣뎃菣炈誁苣뎁㉰臣ꎭ臣蒁臣蒁臣鎁臣銂ꋧ趪臣讂臣膂臣ꢔ臣讂胣袼苣鞁胣憁橤戭摯貁湩楳敤苣ꢡ臣ꢁ臣꾁胣醈胣꾁畯獴摩ꮁ꿥鞁臣龮髩ꮁ菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂꣨鞮臣膀菣ꒂ菣⢳⵰朦㭴㉰꾁돦辄臣ꚁ꟦邈臣貂臣醁苣낁臣覂臣膀臣貂臣ꦃ苣뎃瀨☭瑧瀻⤱苣誂鿧蒁胣覼돦辄볯鎁臣ꊖ闦꾁胣醈胣貁臣鎁臣袂苣骤臣꺁믤骮苣財臣貁䵂偁馀⁳䵂㉟彄佂奄㨺潣灭瑵彥畯獴摩彥楷瑤⡨⸮⤮雩낕臣麝룥ꮁ苣辁鯧벼臣ꚁ臣讂胣⪂椯瑮䈠彍䑁扟湥汤湩㩥挺浯異整䉟彍䑁晟慬杮彥潰湩獴䈨彍䐳䉟䑏⁙愪橤扟摯⥹⽻ 汦湡敧搠浩湥楳湯瀠楯瑮⁳敷愠敲潧湩⁧潴挠浯異整眠汩⁬敢猠潴敲⁤敨敲䵂䅟彄楤彭潣湲牥⨠氪獩彴景灟楯瑮⁳⼻ 楬瑳潟彦潰湩獴椠⁳桷牥⁥敷眠楲整琠敨瀠楯瑮牥琠⁯桴⁥⼯渠硥⁴汦湡敧搠浩湥楳湯瀠楯瑮䵂䅟彄楤彭潣湲牥⨠整灭摟⁰⼻ 桴獥⁥慰慲敭整獲愠敲甠敳⁤獡湩異⁴潴琠楨⁳畦据楴湯搮畯汢⁥汦湡敧江湥瑧⁨※⨯椠⁴獩椠灭牯慴瑮琠慨⁴桴⁥汦湡敧氠湥瑧⁨敢琠敨挠牯敲瑣映慬杮⁥敬杮桴⨠䈯彍佐义⁔敲彦潰湩⁴※⨯敲敦敲据⁥潰湩ⱴ搠晥湩獥琠敨爠杩瑨瀠慬敮映牯映慬杮⁥楤敭獮潩⁮潰湩獴⨠䈯彍䕖呃剏猠摩彥敶瑣牯㬠⼠‪桳畯摬戠⁥潮浲污穩摥⨠⼯ 档捥⁫桷捩⁨摡慪散瑮潢祤眠⁥潣灭瑵楥⁦愨橤扟摯⁹㴽愠橤扟摯ㅹ 晻慬杮彥敬杮桴㴠映ㅬ㬠楬瑳潟彦潰湩獴㴠☠浡㭰潢祤弱潰湩獴㬠敲彦潰湩⁴‽敢摮扟摯ㅹ灟楯瑮江晥⹴⁰猻摩彥敶瑣牯㴠猠摩彥敶瑣牯‱紻汥敳椠⁦愨橤扟摯⁹㴽愠橤扟摯㉹ 晻慬杮彥敬杮桴㴠映㉬氻獩彴景灟楯瑮⁳‽愦灭戻摯㉹灟楯瑮⁳爻晥灟楯瑮㴠戠湥彤潢祤弲潰湩彴敬瑦瀮㬠楳敤癟捥潴⁲‽楳敤癟捥潴㉲㬠敽獬⁥敲畴湲〠㬠⼠ 潮⁴湡愠橤散瑮戠摯⽹ 慶楲扡敬⁳潴猠潴敲琠浥潰慲祲瘠污敵䉳彍䕖呃剏琠浥彰⁶搻畯汢⁥整灭硟㬠⼯瀠牡浡瑥牥⁳潦⁲楦楸杮琠敨爠晥牥湥散瀠楯瑮䵂偟䥏呎爠⡰敲彦潰湩⥴㬠⼠ 桴獩愠氠捯污挠灯⁹景琠敨爠晥牥湥散瀠楯瑮‮敷眠汩⁬潭楤祦椠⹴䵂噟䍅佔⁒癲㬠⼠ 癡捥潴⁲潦⁲牴湡汳瑡湩⁧汦湡敧搠浩湥楳湯瀠楯瑮⹳湩⁴敲彦敶瑣牯癟污摩㴠〠※⼯椠⁦桴獩椠⁳剔䕕‬敷渠敥⁤潴琠慲獮慬整愠汬映慬杮⁥楤敭獮潩⁮潰湩獴⼮ 晩吠啒ⱅ琠敨漠汮⁹敲污祬琠楲正⁹慰瑲椠⁳潴挠湯瑳畲瑣琠敨瀠′潰湩⁴湩琠敨映慬杮⁥楤敭獮潩⁮潰湩⹴⼯焠慵楬楦慣楴湯挠敨正䵂㉟彄佂奄⨠摡彪楤灳慬敹彤敶獲潩⁮椻⁦瀨牡湥⵴朦㭴敧彴楶睥瑟灹⡥⤩愠橤摟獩汰祡摥癟牥楳湯㴠愠橤扟摯⵹朦㭴敧彴畣牲湥彴䐳癟牥楳湯⤨㬠汥敳愠橤摟獩汰祡摥癟牥楳湯㴠愠橤扟摯⵹朦㭴敧彴汦瑡⤨㬠晩⠠啎䱌㴠‽摡彪楤灳慬敹彤敶獲潩⥮爠瑥牵⁮‰䈻彍啓䙒䍁⁅猪牵慦散‽摡彪楤灳慬敹彤敶獲潩⵮朦㭴敧彴畳晲捡⡥ 椻⁦丨䱕⁌㴽猠牵慦散 敲畴湲〠㬠䵂䱟住⁐截潬灯㴠愠橤摟獩汰祡摥癟牥楳湯☭瑧朻瑥扟潬灯⤨㬠晩⠠啎䱌㴠‽汢潯⥰爠瑥牵⁮‰䈻彍䑅䕇⨠摥敧㬠⼠ 敨敲眠⁥楷汬猠潴敲攠杤獥愠⁳敷猠慣⁮桴⁥潬灯搮畯汢⁥楤瑳湡散ⰱ搠獩慴据㉥㬠⼠ 敨敲眠⁥楷汬猠潴敲琠敨搠獩慴据⁥景瀠楯瑮⁳敷猠敥潤扵敬搠ⰱ搠′※⼯栠牥⁥敷猠潴敲搠獩慴据⁥桴瑡栠獡琠⁯敢愠摤摥敢慣獵⁥景愠戠湥⁤牡⹣映牯氠湩獥愠橤捡湥⁴潴愠戠湥汤湩⹥潤扵敬琠ㅤ‬摴㬲⼠ 敨敲眠⁥瑳牯⁥桴⁥潴慴⁬楤瑳湡散眠楨档椠⁳桴⁥畳⁭景搠獩慴据塥⬠搠⹘䵂㍟彄佂奄⨠扡㬠⼠ 敨敲眠⁥瑳牯⁥⁡潰湩整⁲潴愠戠摯⁹桴瑡椠⁳摡慪散瑮潴琠敨挠牵敲瑮攠杤⹥䵂䉟久彄偏⨠潢⁰※⼯栠牥⁥敷猠潴敲愠瀠楯瑮牥琠⁯桴扥湥⁤灯愠獳捯慩整⁤楷桴琠敨戠湥汤湩⁥桴瑡椠⽳ 摡慪散瑮琠⁯桴⁥摥敧眠獥慣⁮瘨污摩漠汮⁹晩⁦桴⁥潢祤愠橤捡湥⁴潴琠敨攠杤⁥獩愠戠湥汤湩⥥䈮彍䕖呃剏爠杩瑨潟数楮杮摟物捥楴湯㬠⼠ 桴獩椠⁳桴⁥楲桧⵴楳敤漠数楮杮搠物捥楴湯瘠捥潴⹲䈠彍䕖呃剏氠晥彴灯湥湩彧楤敲瑣潩⁮※⼯琠楨⁳獩琠敨氠晥⵴楳敤漠数楮杮搠物捥楴湯瘠捥潴⹲椠瑮映彬楤彭灯湥㴠〠㬠⼠ 晩琠楨⁳獩吠啒ⱅ眠⁥慨敶挠敲瑡摥愠爠杩瑨猭摩⁥汦湡敧搠浩湥楳湯瀠楯瑮‬畢⽴ 潮挠牯敲灳湯楤杮氠晥⵴楳敤搠浩湥楳湯瀠楯瑮‮桔瑡椠ⱳ琠敨搠浩湥楳湯椠⁳漢数≮䈮彍䕖呃剏戠湥彤牡彣楤敲瑣潩⁮※⼯搠物捥楴湯漠⁦桴⁥敢摮愠捲瀠潲敪瑣摥漠瑮⁯畯⁲汰湡⽥猯潨汵⁤敢氠湩ⵥ朦㭴⁶‪汰湡彥潮浲污‮獕摥眠敨⁮⁡楬敮椠⁳摡慪散瑮琠⁯⁡敢摮楬敮䈮彍䕖呃剏戠湥彤楤敲瑣潩⁮※⼯瀠楯瑮⁳湩琠敨搠物捥楴湯椠⁮桷捩⁨桴扥湥汤湩⁥琢牵獮⼢ 敤数摮⁳湯眠敨桴牥琠敨戠湥⁤湡汧⁥獩愠畣整漠⁲潮⹴⼠ 晩愠畣整琠敨⁮慴杮湥⁴潴琠敨漠桴牥攠摮漠⁦敢摮愠捲⼮ 晩渠瑯愠畣整‬桴湥愠⁮湥灤楯瑮漠⁦桴⁥慴杮湥⁴灡牰硯浩瑡潩⹮⼯戠獡捩污祬琠楨⁳獩琠敨⠠⵰朦㭴㉰ 敶瑣牯映牯琠敨漠桴牥戠湥汤湩⁥楷桴爠獥数瑣琠⁯桴獩映慬杮⹥⼯琠楨⁳獩甠敳⁤桷湥愠氠湩⁥獩愠橤捡湥⁴潴愠戠湥汤湩ⱥ琠⁯潣灭瑵⁥桴⁥㉰瀠楯瑮映牯⼠ 桴⁥汦湡敧搠浩湥楳湯瀠楯瑮䈮彍䥌䕎愠橤扟湥彤㉰江湩⁥※⼯琠楨⁳獩琠敨氠晥⵴楲桧⵴㉰氠湩ⱥ漠⁦桴⁥摡慪散瑮戠湥汤湩ⱥ⼯眠瑩⁨敲灳捥⁴潴琠楨⁳汦湡敧⼮ 桴獩椠⁳獵摥眠敨⁮⁡楬敮椠⁳摡慪散瑮琠⁯⁡敢摮楬敮‬潴挠浯異整桴⁥㉰瀠楯瑮映牯⼠ 桴⁥汦湡敧搠浩湥楳湯瀠楯瑮搮畯汢⁥敢摮慟捲潟瑵楳敤江湥瑧彨牰橯㬠⼠ 敢摮楬敮愠捲漠瑵楳敤氠湥瑧⁨牰橯捥整⁤湯潴漠牵瀠慬敮⨯ꇨꊝ臣뾂苣鞃苣趓뷤馁苣芀⼪晩⠠畳晲捡ⵥ朦㭴獩䈨彍奔䕐偟䅌䕎⤩朠瑯⁯慨摮敬灟慬敮⁳⼻⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪肸駦蒚详龝볯醈胣꾁跥ꮁ맥ꊝ臣芁苣ꢡ鷩銂鏦鲽臣讂胣咂䑏骼믤꺁ꇨꊝ苣ꒂ菣銂鏦鲽臣讂胣⪂⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪⨪⼯甯歮潮湷猠牵慦散敲畴湲〠㬠⨯臣鎁臣膀맥ꊝ苣趓뷤馁苣芀⼪慨摮敬灟慬敮⁳›䵂偟䅌䕎⨠汰湡⁥‽䈨彍䱐乁⁅⤪猠牵慦散㬠⼯眠⁥獡畳敭琠慨⁴桴⁥敲敦敲据⁥潰湩⁴潣牲捥汴⁹敤楦敮⁳桴⁥汰湡⁥眨楨档椠⁳慰慲汬汥琠⁯畯⁲汰湡⥥⼯琠慨楴⁳桴⁥問協䑉⁅汰湡⹥⼯挠敨正椠⁦敲敦敲据⁥潰湩⁴獩漠⁮畯⁲汰湡⹥䤠⁦潮⡴湩琠慨⁴慣敳漠牵瀠慬敮爠灥敲敳瑮⁳桴⁥义䥓䕄⼯瀠慬敮 潣灭瑵⁥⁡牴湡汳瑡潩⁮敶瑣牯映牯洠癯湩⁧牦浯漠牵瀠慬敮琠⁯敲敦敲据⁥汰湡ⱥ⼯愠摮洠癯⁥桴⁥敲敦敲据⁥潰湩⁴潴漠牵瀠慬敮爮⁶‽汰湡ⵥ朦㭴敧彴潮浲污⤨㬠癲渮牯慭楬敳⤨琻浥彰⁶‽灲ⴠ⠠汰湡ⵥ朦㭴敧彴瑰⤨ 琻浥彰⁸‽整灭癟┠爠⁶椻⁦昨扡⡳整灭硟☩瑧※啁佔䥄彍䥄呓乁䕃呟䱏剅乁䕃 ⽻ 歯‬敮摥琠⁯牴湡汳瑡⁥污⁬楤敭獮潩⁮潰湩獴‮敲敦敲据⁥潰湩⁴潮⁴湯琠敨瀠慬敮爮晥癟捥潴彲慶楬⁤‽‱爻⹶敳彴敬杮桴琨浥彰⥸㬠灲㴠爠⁰‫⴨癲 紻汥敳爠⁶‽䵂湟汵彬敶瑣牯㬠⼯挠浯異整爠杩瑨‭湡⁤敬瑦猭摩⁥灯湥湩⁧敶瑣牯⹳楲桧彴灯湥湩彧楤敲瑣潩⁮‽楳敤癟捥潴⁲⠪汰湡ⵥ朦㭴敧彴潮浲污⤨ 爻杩瑨潟数楮杮摟物捥楴湯渮牯慭楬敳⤨㬠敬瑦潟数楮杮摟物捥楴湯㴠ⴠ爨杩瑨潟数楮杮摟物捥楴湯 ⼻⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪鎁臣ꊖ闦꺁룤膦菩蚈胣憂橤扟摯꺁鷦鮸菣벃菣銂軦閼臣膀菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂꟦邈臣讂胣肉룤꺁菣ꒂ菣讁苣肜苣ꂁ臣ꊛ苣龁苣莃苣꾁汢潯薆臣ꪁ臣貂臣ꪁ苣ꪁ臣꺁臣醈胣꾁跥ꮁ汢潯銂軦閼臣讂뿥膦臣芁苣릂臣ꢳ蓦閁苣龁臣芀⨪⨪⨪⨪⨪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪돦辄볯螃苣ꆃ菣랂菣뎃菣릂菣貁雩뺔臣ꢁ臣膀铧邈臣貂苣肜뻥꺁迥ⶳ臥螃苣ꆃ菣랂菣뎃菣ꒂ菣袃臣膀菣벃菣꺁꟥膂臣誁臣ꚁ迧ꢜ臣ꢂ菣뢂臣讖꟥ⶋ苧讁苣낕臣ꎁ臣蒁臣醁苣낁臣覂臣蒁胣⪂⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⼪⼯猠慣⁮污敬杤獥椠⁮桴⁥汢潯⽰ 楦獲ⱴ眠⁥慨敶愠瀠潲汢浥眠敨敲琠⁯瑳牡⁴捳湡楮杮⼮ 晩眠⁥瑳牡⁴牦浯琠敨映物瑳攠杤ⱥ眠⁥慢楳慣汬⁹瑳牡⁴牦浯愠⁮牡楢牴牡敹杤⹥⼯琠楨⁳業桧⁴潮⁴敢朠潯⁤楳据⁥敷洠杩瑨挠敲瑡⁥楤敭獮潩⁮潰湩獴眠摥湯胢璙爠慥汬⁹慷瑮⼮ 桴牥晥牯⁥敷眠汩⁬楦摮愠⁮摥敧琠慨⁴獩愠橤捡湥⁴潴漠牵戠湥汤湩⁥湡⁤瑳牡⁴牦浯琠慨⁴湡⽤ 楦楮桳眠敨⁮敷朠瑥戠捡⁫潴椠⹴䵂䕟䝄⁅猪慴瑲敟杤ⱥ⨠瑳灯敟杤ⱥ⨠敮瑸敟杤⁥昻牯⠠瑳牡彴摥敧㴠戠潬灯☭瑧朻瑥晟物瑳敟杤⡥ ※瑳牡彴摥敧㬠猠慴瑲敟杤⁥‽䈨彍䑅䕇⨠ 瑳牡彴摥敧☭瑧渻硥⡴⤩笠晩⠠瑳牡彴摥敧☭瑧朻瑥慟橤扟摯⡹ 㴽戠湥⥤戠敲歡㬠⼠ 摥敧愠橤捡湥⁴潴琠楨⁳敢摮楬敮椠⁳⁡潧摯猠慴瑲攭杤敥獬⁥晩⠠‡瑳牡彴摥敧☭瑧椻⡳䵂䕟呎呉彙奔䕐䱟义⥅ 牢慥⁫※⼯愠祮渠湯氭湩⁥獩愠朠潯⁤瑳牡⵴摥敧汥敳笠⼠ 湡⁹楬敮桴瑡眠汩⁬敢椠湧牯摥椠⁳污潳愠朠潯⁤汰捡⁥潴猠慴瑲整灭癟㴠⠠⠨䵂䱟义⁅⤪瑳牡彴摥敧⴩朦㭴敧彴⡶⤩⨠猠摩彥敶瑣牯㬠⼯椠⁮桴獥⁥睴⁯慣敳⁳桴獩氠湩⁥楷汬戠⁥杩潮敲楤⁦琨浥彰⹶敌⡮ 氦㭴‽啁佔䥄彍䥄呓乁䕃呟䱏剅乁䕃 牢慥⁫※⼯楬敮瀠牡污敬⁬潴琠敨猠摩ⵥ敶瑣牯晩⠠琨浥彰⁶‥汰湡ⵥ朦㭴敧彴潮浲污⤨ 朦㭴〠〮 牢慥⁫※⼯洠瑡牥慩⁬愢潢敶•桴⁥楬敮絽晩⠠啎䱌㴠‽瑳牡彴摥敧 ⩻楬瑳潟彦潰湩獴㴠丠䱕⁌爻瑥牵⁮‱紻⼯琠楨⁳獩琠敨洠楡⁮潬灯⼮ 湩瑩慩汬⁹敷猠瑥瑳灯敟杤⁥潴丠䱕⹌眠⁥潷汵⁤楬敫琠⁯敳⁴瑩琠⁯瑳牡⵴摥敧‬畢⁴敷挠湡潮ⱴ⼯戠捥畡敳椠⁮桴瑡挠獡⁥敷眠畯摬渠癥牥攠瑮牥琠敨氠潯⹰琠敨敲潦敲眠⁥敳楴⁴潴丠䱕⁌湡⁤楲桧⁴⼯愠瑦牥眠⁥湥整⁲桴⁥潬灯‬敷猠瑥椠⁴潴猠慴瑲敟杤⹥⼯⠠桴獩椠⁳浩潰瑲湡⁴湩琠敨挠獡⁥桷湥琠敨氠潯⁰潣獮獩獴漠⁦湯祬漠敮挠物汣⥥献潴彰摥敧㴠丠䱕⁌昻牯⠠摥敧㴠猠慴瑲敟杤⁥※摥敧℠‽瑳灯敟杤⁥※摥敧㴠渠硥彴摥敧 獻潴彰摥敧㴠猠慴瑲敟杤⁥⼻ 潣灭瑵⁥桴⁥敮瑸攠杤⁥敷眠汩⁬捳湡敮瑸敟杤⁥‽䈨彍䑅䕇⨠ 摥敧☭瑧渻硥⡴ 椻⁦丨䱕⁌㴽渠硥彴摥敧 敮瑸敟杤⁥‽汢潯⵰朦㭴敧彴楦獲彴摥敧⤨㬠睳瑩档⠠摥敧☭瑧朻瑥瑟灹⡥⤩笠慣敳䈠彍久䥔奔呟偙彅䥌䕎㨠笠⼠ 潣灭瑵⁥楤瑳湡散映牯猠慴瑲‭湡⁤湥ⵤ潰湩獴⼯映物瑳‬敷眠湡⁴潴椠湧牯⁥楬敮⁳桴瑡愠敲瀠牡污敬⁬潴琠敨猠摩ⵥ敶瑣牯⼮ 敷愠獬⁯慷瑮琠⁯杩潮敲氠湩獥琠慨⁴慨敶洠瑡牥慩⁬愢潢敶•桴浥眠敨⁮潬歯湩⁧湩琠敨⼯猠摩ⵥ敶瑣牯搠物捥楴湯⠠敢慣獵⁥桴祥挠湡潮⁴慨敶琠⁯慬杲獥⁴楷瑤ⱨ猠湩散洠瑡牥慩⁬獩⼯∠扡癯≥琠敨Ɑ琠敨敲洠獵⁴敢猠浯⁥瑯敨⁲摥敧戠畯摮湩⁧桴扥摯⁹牦浯愠潢敶⸩整灭癟㴠⠠⠨䵂䱟义⁅⤪攠杤⥥☭瑧朻瑥癟⤨ ‪楳敤癟捥潴⁲椻⁦琨浥彰⹶敌⡮ 氦㭴‽啁佔䥄彍䥄呓乁䕃呟䱏剅乁䕃 潣瑮湩敵㬠⼠ 楬敮瀠牡污敬⁬潴琠敨猠摩ⵥ敶瑣牯晩⠠琨浥彰⁶‥汰湡ⵥ朦㭴敧彴潮浲污⤨ 朦㭴〠〮 潣瑮湩敵※⼯洠瑡牥慩⁬愢潢敶•桴⁥楬敮⼯渠瑯⁥桴瑡琠楨⁳敬癡獥漠汮⁹楬敮⁳桷獯摥物捥楴湯瘭捥潴⁲潧獥琠⁯桴⁥氢晥≴⼯漠⁦桴⁥楳敤瘭捥潴⹲⼯眠⁥敮摥琠捯敨正椠⁦桴獩氠湩⁥獩愠橤捡湥⁴潴愠戠湥汤湩慥⁢‽摥敧☭瑧朻瑥慟橤扟摯⡹ ⼻ 档捥⁫晩琠楨⁳楬敮椠⁳摡慪散瑮琠⁯⁡慶楬⁤敢摮楬敮⠠敩‮湯⁥桴瑡椠⁳潮⁴桴⁥⼯戠湥汤湩⁥獡潳楣瑡摥眠瑩⁨桴獩䈠彍䑁扟湥汤湩⁥扯敪瑣⸩ㅤ㴠搠′戽湥彤牡彣畯獴摩彥敬杮桴灟潲⁪‽⸰‰椻⁦愨⁢愦灭☻浡㭰愠⁢㴡戠湥⁤愦灭☻浡㭰愠ⵢ朦㭴獩䈨彍久䥔奔呟偙彅䕂䑎䥌䕎⤩笠⼯挠敨正椠⁦桴⁥敢摮楬敮椠⁳敢湩⁧敢瑮潢⁰‽⠨䵂䉟久䱄义⁅⤪愠⥢☭瑧朻瑥扟湥彤灯⤨㬠晩⠠瀨牡湥⵴朦㭴敧彴楶睥瑟灹⡥⤩⼠‪慨敶琠桯癡⁥⁡䐳瘠敩⁷⼪☠浡㭰愦灭※⠨䵂䉟久䱄义⁅⤪愠⥢☭瑧朻瑥扟湥楤杮獟慴畴⡳ 愦灭☻浡㭰戠灯笩⼯愠瀠潲汢浥㨠椠⁴潣汵⁤敢琠慨⁴桴⁥敢摮楬敮椠⁳潮⁴数灲湥楤畣慬⁲潴琠敨猠摩ⵥ敶瑣牯⼮ 湩琠慨⁴慣敳眠⁥敮摥琠⁯牰橯捥⁴桴⁥敢摮愭捲愭灰潲楸慭楴湯瘭污敵漠瑮⁯桴⁥楳敤瘭捥潴⹲⼯映牯攠慸灭敬‬晩琠敨戠湥汤湩⁥獩瀠牡污敬⁬潴琠敨猠摩ⵥ敶瑣牯‬敷猠潨汵⁤潮⁴摡⽤ 桴⁥灡牰硯浩瑡潩⁮慶畬⁥瑡愠汬‬楳据⁥瑩瀠慬獹渠⁯潲敬椠⁮桴⁥楷瑤⁨潣灭瑵瑡潩⹮整灭硟㴠猠摩彥敶瑣牯⁞⠨䈨彍䥌䕎⨠ 摥敧⴩朦㭴敧彴⡶⤩㬠⼠ 整灭硟椠⁳愢杮敬晟捡潴≲晩⠠整灭硟朦㭴倠彉癯牥㉟ 整灭硟㴠倠⁉‭整灭硟㬠整灭硟㴠猠湩琨浥彰⥸㬠睳瑩档⠠潢⵰朦㭴敧彴祴数⤨ 捻獡⁥䵂呟偙彅䕂䑎佟彐䕒啇䅌⁒戺湥彤牡彣畯獴摩彥敬杮桴灟潲⁪⠽䈨彍䕂䑎佟彐䕒啇䅌⁒⤪戠灯⴩朦㭴潣灭瑵彥䐳潟瑵楳敤慟灰潲彸数彲楳敤⤨㬠ㅤ㴠整灭硟截湥彤牡彣畯獴摩彥敬杮桴灟潲⁪搻′‽ㅤ㬠⼠ ㉤椠⁳桴⁥慳敭愠⁳ㅤ戡敲歡㬠⼯吠䑏⁏›浩汰浥湥⁴潭敲戠湥⁤灯牥瑡潩獮栠牥⹥敤慦汵⁴›※⼯甠歮潮湷戠湥⁤灯⽽ 潣灭瑵⁥潳敭渠敥敤⁤慰慲敭整獲⼯挠浯異整㨠搠物捥楴湯漠瑦敨戠湥⁤牡⁣牰橯捥整⁤湯潴漠牵瀠慬敮敢摮慟捲摟物捥楴湯㴠⠠⠨䵂䱟义⁅⤪摥敧⴩朦㭴敧彴⡶⤩⨠瀠慬敮☭瑧朻瑥湟牯慭⡬ 戻湥彤楤敲瑣潩⁮‽慰敲瑮☭瑧挻浯異整扟湥彤楤敲瑣潩彮敶瑣牯⠨䵂䉟久䱄义⁅⤪愠Ɫ愠橤扟摯ⱹ☠浡㭰摡彪敢摮灟弲楬敮 紻敽獬⁥扡㴠丠䱕⁌※⼯洠歡⁥畳敲愠⁢潤獥渠瑯瀠楯瑮琠⁯湡瑹楨杮眠⁥潤馀睴湡⁴潴⼮ 慨摮敬琠潷挠獡獥猠灥牡瑡汥⁹‭敤数摮湩⁧湯眠敨桴牥琠敨搠浩湥楳湯氠獩⁴獩漠数⁮牯渠瑯椮⁦昨彬楤彭灯湥 ⽻ 晩琠敨搠浩湥楳湯椠⁳灯湥‬敷搠湯胢璙渠敥⁤潴挠敨正琠敨猠慴瑲瀭楯瑮漠⁦桴⁥楬敮⼬ 楳据⁥瑩椠⁳瑡琠敨汦湡敧氠湥瑧⁨楤瑳湡散愠祮慷⹹⼯⼠ 楦獲⁴敷眠汩⁬档捥⁫晩琠敨氠湩⁥獩数灲湥楤畣慬⁲潴琠敨猠摩ⵥ敶瑣牯晩⠠慦獢猨摩彥敶瑣牯┠⠠䈨彍䥌䕎⨠ 摥敧⴩朦㭴敧彴⡶⤩☠瑧※啁佔䥄彍䥄呓乁䕃呟䱏剅乁䕃 ⽻ 潮⁴数灲湥楤畣慬⹲⼯琠楨汳湩⁥慨⁳潴戠⁥挢浯湩⁧潤湷•戨捥畡敳椠⁴獩渠瑯瀠牥数摮捩汵牡琠⁯桴⽥ 楳敤瘭捥潴⁲湡⁤桴⁥楤敭獮潩⁮獩漠数Ɱ椠⹥椠⁴慣湮瑯戠⁥朢楯杮甠≰⸩⼯渠睯眠⁥慨敶琠⁯汣獯⁥桴⁥楤敭獮潩⁮祢挠敲瑡湩⁧⁡敬瑦栭湡ⵤ楳敤搠浩湥楳湯潰湩⽴ 牦浯琠敨猠慴瑲瀭楯瑮漠⁦桴⁥楬敮椮⁦琨浥彰灤㴠挠敲瑡彥楤彭潰湩⡴敢摮慟捲潟瑵楳敤江湥瑧彨牰橯‬⠨䵂䱟义⁅⤪攠杤⥥☭瑧朻瑥獟慴瑲瑰⤨‬癲‬敬瑦潟数楮杮摟物捥楴湯‬ⰰ琠楨ⱳ愠橤扟摯ⱹ氠獩彴景灟楯瑮ⱳ猠摩彥敶瑣牯‬ㅤ戬湥彤牡彣楤敲瑣潩Ɱ戠湥彤楤敲瑣潩Ɱ⠠䵂䉟久䱄义⁅⤪愠Ɫ愠橤扟湥彤㉰江湩⥥ 汻獩彴景灟楯瑮⁳‽愦灭⠻整灭摟⵰朦㭴敮瑸 紻汦摟浩潟数⁮‽‰紻汥敳笠⼯椠⁳数灲湥楤畣慬⹲⼯栠牥⁥敷渠敥⁤潴挠敨正琠敨琠灹⁥景琠敨渠硥⁴摥敧⼮ 晩椠楴⁳潮⁴楬敮‬敷渠敥⁤潴挠潬敳琠敨搠浩湥楳湯栠牥⁥祢挠敲瑡湩⁧⼯愠氠晥⵴慨摮猭摩⁥楤敭獮潩⁮潰湩⁴牦浯琠敨攠摮瀭楯瑮漠⁦桴⁥楬敮⼮ 晩琠敨渠硥整杤⁥獩愠氠湩ⱥ眠⁥慣⁮番瑳挠湯楴畮⹥晩⠠敬癡彥楤敭獮潩彮灯湥攨杤ⱥ汢潯Ɒ楳敤癟捥潴Ⱳ汰湡ⵥ朦㭴敧彴潮浲污⤨⤩戠敲歡㬠晩⠠整灭摟⁰‽牣慥整摟浩灟楯瑮戨湥彤牡彣畯獴摩彥敬杮桴灟潲ⱪ⠠䈨彍䥌䕎⨠ 摥敧⴩朦㭴敧彴湥灤⡴Ⱙ爠ⱶ氠晥彴灯湥湩彧楤敲瑣潩Ɱ〠‬桴獩‬摡彪潢祤‬楬瑳潟彦潰湩獴‬楳敤癟捥潴Ⱳ搠ⰱ敢摮慟捲摟物捥楴湯‬敢摮摟物捥楴湯‬䈨彍䕂䑎䥌䕎⨠ 扡‬摡彪敢摮灟弲楬敮⤩笠楬瑳潟彦潰湩獴㴠☠浡㭰琨浥彰灤☭瑧渻硥⥴㬠⽽ 歯‬汣獯⁥桴⁥楤敭獮潩⹮汦摟浩潟数⁮‽‰⼻ 桴獩椠⁳⁡浳污⁬牴捩⁫桴瑡眠汩⁬慳敶甠⁳潳敭琠浩⹥⼯椠⁦桴⁥敮瑸攠杤⁥獩愠氠湩⁥桴瑡眠汩⁬敢椠湧牯摥‬敷挠湡猠楫⁰獩爠杩瑨渠睯栠牥⹥晩⠠敮瑸敟杤ⵥ朦㭴獩䈨彍久䥔奔呟偙彅䥌䕎 愦灭☻浡㭰渠硥彴摥敧℠‽瑳灯敟杤⥥笠敮瑸敟杤⁥‽䈨彍䑅䕇⨠ 摥敧☭瑧渻硥⡴ 椻⁦丨䱕⁌㴽渠硥彴摥敧 敮瑸敟杤⁥‽汢潯⵰朦㭴敧彴楦獲彴摥敧⤨㬠絽牢慥⁫紻晩⠠‡潣灭瑵彥楤瑳湡散晟潲彭敲彦潰湩⡴灲‬楳敤癟捥潴Ⱳ攠杤ⵥ朦㭴敧彴摥敧獟慴瑲潰湩⡴Ⱙ搠獩慴据ㅥ⤩挠湯楴畮⁥椻⁦ℨ挠浯異整摟獩慴据彥牦浯牟晥灟楯瑮爨Ɒ猠摩彥敶瑣牯‬摥敧☭瑧朻瑥敟杤彥湥灤楯瑮⤨‬楤瑳湡散⤲ 潣瑮湩敵㬠摴‱‽楤瑳湡散‱‫ㅤ㬠摴′‽楤瑳湡散′‫㉤㬠⼯挠敨正椠⁦桴⁥瑳牡⵴潰湩⁴獩愠映慬杮⁥楤敭獮潩⁮潰湩楴⁦昨扡⡳摴‱‭汦湡敧江湥瑧⥨☠瑬㴻䄠呕䑏䵉䑟卉䅔䍎彅佔䕌䅒䍎⥅笠⼯挠敨正椠⁦桴⁥敳潣摮瀠楯瑮椠⁳⁡汦湡敧搠浩湥楳湯瀠楯瑮晩⠠慦獢琨㉤ⴠ映慬杮彥敬杮桴볯₉朦㭴䄠呕䑏䵉䑟卉䅔䍎彅佔䕌䅒䍎⥅笠⼯漠汮⁹瑳牡⵴潰湩⁴獩愠映慬杮⁥楤敭獮潩⁮潰湩⹴⼯挠敲瑡⁥⁡敬瑦爭杩瑨⠠敩‮湩戠瑯⁨楤敲瑣潩獮 汦湡敧搠浩瀠楯瑮愠摮挠湯楴畮⹥晩⠠整灭摟⁰‽牣慥整摟浩灟楯瑮戨湥彤牡彣畯獴摩彥敬杮桴灟潲ⱪ⠠䈨彍䥌䕎⨠ 摥敧⴩朦㭴敧彴瑳牡灴⡴Ⱙ爠ⱶㄡ〶爣杩瑨潟数楮杮摟物捥楴湯‬ⰱ琠楨ⱳ愠橤扟摯ⱹ楬瑳潟彦潰湩獴‬楳敤癟捥潴Ⱳ搠ⰱ戠湥彤牡彣楤敲瑣潩Ɱ戠湥彤楤敲瑣潩Ɱ⠠䵂䉟久䱄义⁅⤪愠Ɫ愠橤扟湥彤㉰江湩⥥ 汻獩彴景灟楯瑮⁳‽愦灭⠻整灭摟⵰朦㭴敮瑸 紻牢慥⁫紻⼯攠獬⁥灯湥琠敨搠浩湥楳湯氠獩⽴ 牣慥整爠杩瑨映慬杮⁥楤敭獮潩灮楯瑮映潲⁭瑳牡⵴潰湩楴⁦琨浥彰灤㴠挠敲瑡彥楤彭潰湩⡴敢摮慟捲潟瑵楳敤江湥瑧彨牰橯‬⠨䵂䱟义⁅⤪攠杤⥥☭瑧朻瑥獟慴瑲瑰⤨‬癲‬楲桧彴灯湥湩彧楤敲瑣潩Ɱ〠‬桴獩‬摡彪潢祤‬楬瑳潟彦潰湩獴‬楳敤癟捥潴Ⱳ搠ⰱ戠湥彤牡彣楤敲瑣潩Ɱ戠湥彤楤敲瑣潩Ɱ⠠䵂䉟久䱄义⁅⤪愠Ɫ愠橤扟湥彤㉰江湩⥥ 汻獩彴景灟楯瑮⁳‽愦灭⠻整灭摟⵰朦㭴敮瑸 紻⼯挠敨正椠⁦敷挠湡氠慥敶琠敨搠浩湥楳湯氠獩⁴灯湥湡⁤潣瑮湩敵晩⠠敬癡彥楤敭獮潩彮灯湥攨杤ⱥ汢潯Ɒ楳敤癟捥潴Ⱳ汰湡ⵥ朦㭴敧彴潮浲污⤨⤩笠汦摟浩潟数⁮‽‱戻敲歡㬠⽽ 牣慥整氠晥⁴汦湡敧搠浩瀠楯瑮映潲⁭湥ⵤ潰湩⹴晩⠠整灭摟⁰‽牣慥整摟浩灟楯瑮戨湥彤牡彣畯獴摩彥敬杮桴灟潲ⱪ⠨䵂䱟义⁅⤪攠杤⥥☭瑧朻瑥敟摮瑰⤨‬癲‬敬瑦潟数楮杮摟物捥楴湯‬ⰰ琠楨ⱳ愠橤扟摯ⱹ氠獩彴景灟楯瑮ⱳ猠摩彥敶瑣牯‬ㅤ‬敢摮慟捲摟物捥楴湯‬敢摮摟物捥楴湯‬䈨彍䕂䑎䥌䕎⨠ 扡‬摡彪敢摮灟弲楬敮⤩笠楬瑳潟彦潰湩獴㴠☠浡㭰琨浥彰灤☭瑧渻硥⥴㬠⽽ 歯‬汣獯⁥桴⁥楤敭獮潩⁮楬瑳昮彬楤彭灯湥㴠〠㬠⼯琠楨⁳獩愠浳污⁬牴捩⁫桴瑡眠汩⁬慳敶甠⁳潳敭琠浩⹥⼯椠⁦桴⁥敮瑸攠杤⁥獩愠氠湩⁥桴瑡眠汩⁬敢椠湧牯摥‬敷挠湡猠楫⁰獩爠杩瑨渠睯栠牥⹥晩⠠敮瑸敟杤ⵥ朦㭴獩䈨彍久䥔奔呟偙彅䥌䕎 愦灭☻浡㭰渠硥彴摥敧℠‽瑳灯敟杤⥥笠敮瑸敟杤⁥‽䈨彍䑅䕇⨠ 摥敧☭瑧渻硥⡴ 椻⁦丨䱕⁌㴽渠硥彴摥敧 敮瑸敟杤⁥‽汢潯⵰朦㭴敧彴楦獲彴摥敧⤨㬠扽敲歡㬠敽獬⁥晩⠠慦獢琨㉤ⴠ映慬杮彥敬杮桴 朦㭴䄠呕䑏䵉䑟卉䅔䍎彅佔䕌䅒䍎⥅⽻ 桴⁥瑳牡⵴潰湩⁴獩渠瑯愠映慬杮⁥楤敭獮潩⁮潰湩⽴ 晩琠敨攠摮瀭楯瑮獩愠獬⁯潮⁴⁡汦湡敧搠浩湥楳湯瀠楯瑮‬敷挠湡挠湯楴畮⹥潣瑮湩敵㬠⽽ 歯漬汮⁹桴⁥湥ⵤ潰湩⁴獩愠映慬杮⁥楤敭獮潩⁮潰湩⹴⼯琠潷瀠獯楳楢楬楴獥‮晩敷挠湡氠慥敶琠敨搠浩湥楳湯氠獩⁴灯湥⠠楲桧⁴潮⁷楤敭獮潩⁮獩⼠ 汣獯摥⤡敷搠湯胢璙攠敶⁮慨敶琠⁯灯湥椠ⱴ眠⁥慣⁮番瑳挠湯楴畮⹥晩⠠敬癡彥楤敭獮潩彮灯湥攨杤ⱥ汢潯Ɒ楳敤癟捥潴Ⱳ汰湡ⵥ朦㭴敧彴潮浲污⤨⤩戠敲歡㬠⼯猠捥湯⁤潰獳扩汩瑩⹹渠睯眠⁥慨敶琠⁯牣慥整愠氠晥⵴楲桧⁴汦湡敧搠浩湥楳湯瀠楯瑮⼮ 楤敭獮潩⁮楬瑳猠慴獹挠潬敳⹤晩⠠整灭摟⁰‽牣慥整摟浩灟楯瑮戨湥彤牡彣畯獴摩彥敬杮桴灟潲ⱪ⠠䈨彍䥌䕎⨠ 摥敧⴩朦㭴敧彴湥灤⡴Ⱙ爠ⱶ爠杩瑨潟数楮杮摟物捥楴湯‬ⰱ琠楨ⱳ愠橤扟摯ⱹ氠獩彴景灟楯瑮ⱳ猠摩彥敶瑣牯‬ㅤ‬敢摮慟捲摟物捥楴湯‬敢摮摟物捥楴湯‬䈨彍䕂䑎䥌䕎⨠ 扡‬摡彪敢摮灟弲楬敮⤩笠楬瑳潟彦潰湩獴㴠☠浡㭰琨浥彰灤☭瑧渻硥⥴㬠⽽ 桴獩椠⁳⁡浳污⁬牴捩⁫桴瑡眠汩⁬慳敶甠⁳潳敭琠浩⹥⼯椠⁦桴⁥敮瑸攠杤⁥獩愠氠湩⁥桴瑡眠汩⁬敢椠湧牯摥‬敷挠湡猠楫⁰獩爠杩瑨渠睯栠牥⹥晩⠠敮瑸敟杤ⵥ朦㭴獩䈨彍久䥔奔呟偙彅䥌䕎 愦灭☻浡㭰渠硥彴摥敧℠猽潴彰摥敧 湻硥彴摥敧㴠⠠䵂䕟䝄⁅⤪攠杤ⵥ朦㭴敮瑸⤨㬠晩⠠啎䱌㴠‽敮瑸敟杤⥥敮瑸敟杤⁥‽汢潯⵰朦㭴敧彴楦獲彴摥敧⤨㬠絽牢慥⁫挻獡⁥䵂䕟呎呉彙奔䕐䅟䍒㨠⽻ 潮整㨠眠⁥慣⁮污慷獹椠湧牯⁥桴⁥瑳牡⵴潰湩⁴景琠敨愠捲℠⼯戠捥畡敳景琠敨眠祡眠⁥敫灥琠慲正漠⁦桴⁥灯湥搠浩湥楳湯氠獩⹴⼯洠歡⁥畳敲琠敨搠浩湥楳湯氠獩⁴楷汬戠⁥汣獯摥昮彬楤彭灯湥㴠〠㬠⼯映物瑳‬潣灭瑵⁥瑳牡⵴愠摮湥ⵤ湡汧獥漠⁦桴⁥牡⁣楷桴爠獥数瑣琠⁯桴⁥楳敤瘠捥潴⹲⼯椠⹥挠湯敶瑲猠慴瑲‭湡⁤湥ⵤ湡汧獥猠⁯獡椠⁦桴⁥楳敤瘭捥潴⁲慷⁳桴⁥ⴰ湡汧⁥敶瑣牯搮畯汢⁥瑳牡慴杮㴠⠠䈨彍剁⁃⤪攠杤⥥☭瑧朻瑥獟慴瑲湡⡧ 搻畯汢⁥湥慤杮㴠⠠䈨彍剁⁃⤪攠杤⥥☭瑧朻瑥敟摮湡⡧ 琻浥彰⁶‽楳敤癟捥潴⩲⠨䈨彍剁⁃⤪攠杤⥥☭瑧朻瑥癟⡸⤩㬠潤扵敬搠汥慴慟杮敬㴠⠠整灭癟䰮湥⤨⼩⠨䈨彍剁⁃⤪攠杤⥥☭瑧朻瑥牟摡⤨㬩晩⠠敤瑬彡湡汧⁥氦㭴ⴠ⸱⤰搠汥慴慟杮敬㴠ⴠ⸱‰攻獬⁥晩⠠敤瑬彡湡汧⁥朦㭴ㄠ〮 敤瑬彡湡汧⁥‽⸱‰搻汥慴慟杮敬㴠愠楳⡮敤瑬彡湡汧⥥㬠晩⠠慦獢⠨⠨䵂䅟䍒⤪攠杤⥥☭瑧朻瑥湟牯慭⡬⤩琥浥彰⥶☠瑧※⸰⤰笠瑳牡慴杮⬠‽敤瑬彡湡汧⁥攻摮湡⭧‽敤瑬彡湡汧⁥椻⁦猨慴瑲湡⁧朦㭴倠彉楴敭彳⤲猠慴瑲湡⁧㴭倠彉楴敭彳′椻⁦攨摮湡⁧朦㭴倠彉楴敭彳⤲攠摮湡⁧㴭倠彉楴敭彳′紻汥敳笠瑳牡慴杮ⴠ‽敤瑬彡湡汧⁥攻摮湡⁧㴭搠汥慴慟杮敬㬠晩⠠瑳牡慴杮☠瑬※⸰⤰猠慴瑲湡⁧㴫倠彉楴敭彳′椻⡦湥慤杮☠瑬※⸰⤰攠摮湡⁧㴫倠彉楴敭彳′紻⼯挠浯異整琠敨攠瑸敲敭瀠楯瑮䵂偟䥏呎愠捲敟瑸敲敭灟楯瑮㬠⼯〠愭杮敬瀠楯瑮椠⁳桴⁥硥牴浥⁥潰湩楴⁦攨摮湡⁧氦㭴瑳牡慴杮 牡彣硥牴浥彥潰湩⁴‽⠨䵂䅟䍒⨠ 摥敧⴩朦㭴敧彴散瑮牥⤨⬠⠠⠨䵂䅟䍒⨠ 摥敧⴩朦㭴敧彴慲⡤⤩猪摩彥敶瑣牯㬠汥敳愠捲敟瑸敲敭灟楯瑮㴠⨠⠨䈨彍剁⩃ 摥敧⴩朦㭴敧彴摥敧敟摮潰湩⡴⤩㬠⼯挠敨正琠敨搠獩慴据⁥景琠敨攠瑸敲敭瀠楯瑮晩⠠‡潣灭瑵彥楤瑳湡散晟潲彭敲彦潰湩⡴灲‬楳敤癟捥潴Ⱳ☠浡㭰牡彣硥牴浥彥潰湩ⱴ搠獩慴据ㅥ⤩挠湯楴畮⁥椻⁦昨扡⡳楤瑳湡散‱‭汦湡敧江湥瑧⥨☠瑬㴻䄠呕䑏䵉䑟卉䅔䍎彅佔䕌䅒䍎⥅笠⼯椠⁦敷栠癡⁥桴⁥ⴰ湡汧⁥潰湩ⱴ挠敲瑡⁥⁡敬瑦爭杩瑨映慬杮⁥楤敭獮潩⁮潰湩⹴⼯漠桴牥楷敳椠⁦敮瑸氠湩⁥獩愠渠湯椭湧牯摥氠湩ⱥ搠湯胢璙搠⁯湡瑹楨杮⼬ 瑯敨睲獩⁥牣慥整愠氠晥⵴楲桧⁴汦湡敧搠浩湥楳湯瀠楯瑮椮⁦攨摮湡⁧朦㭴‽瑳牡慴杮☠浡㭰愦灭※敬癡彥楤敭獮潩彮灯湥攨杤ⱥ汢潯Ɒ楳敤癟捥潴Ⱳ汰湡ⵥ朦㭴敧彴潮浲污⤨⤩笠潣瑮湩敵㬠⽽ 牣慥整愠氠晥⵴楲桧⁴汦湡敧搠浩湥楳湯瀠楯瑮‮楤敭獮潩⁮楬瑳猠慴獹挠潬敳⹤⼯琠楨⁳獩愠ㄠ瀭楯瑮映慬杮⁥楤敭獮潩⁮潰湩⹴晩⠠整灭摟⁰‽敮⁷䵂䅟彄楤彭潣湲牥爨⁶‫牡彣硥牴浥彥潰湩ⱴ琠楨ⱳ愠橤扟摯ⱹ楲桧彴灯湥湩彧楤敲瑣潩Ɱㄠ‬楬瑳潟彦潰湩獴‬啎䱌⤩笠楬瑳潟彦潰湩獴㴠☠浡㭰琨浥彰灤☭瑧渻硥⥴㬠絽扽敲歡㬠慣敳䈠彍久䥔奔呟偙彅䥃䍒䕌㨠⼠ 楣捲敬⁳牡⁥⁡畭档猠浩汰牥瘠牥楳湯漠⁦桴⁥牡⁣慣敳笮䵂偟䥏呎挠物汣彥硥牴浥彥潰湩⁴‽⠨䵂䍟剉䱃⁅⤪攠杤⥥☭瑧朻瑥损湥整⡲ ‫⠨䈨彍䥃䍒䕌⨠ 摥敧⴩朦㭴敧彴慲⡤⤩猪摩彥敶瑣牯㬠⼯眠⁥潷馀⁴档捥⁫桴⁥楤瑳湡散猠湩散椠⁴畭瑳敢愠映慬杮⁥楤敭獮潩⁮潰湩⽴ 牣慥整愠氠晥⵴楲桧⁴汦湡敧搠浩湥楳湯瀠楯瑮⼮ 桴獩椠⁳⁡ⴱ潰湩⁴汦湡敧搠浩湥楳湯瀠楯瑮椮⁦琨浥彰灤㴠渠睥䈠彍䑁摟浩损牯敮⡲癲⬠挠物汣彥硥牴浥彥潰湩ⱴ琠楨ⱳ愠橤扟摯ⱹ楲桧彴灯湥湩彧楤敲瑣潩Ɱㄠ‬楬瑳潟彦潰湩獴‬啎䱌⤩笠楬瑳潟彦潰湩獴㴠☠浡㭰琨浥彰灤☭瑧渻硥⥴㬠絽牢慥㭫慣敳䈠彍久䥔奔呟偙彅䱅䥌卐⁅›⼯吠䑏⁏›浩汰浥湥⁴汥楬獰⁥敨敲‮桳畯摬敢猠浩汩牡琠⁯桴⁥慷⁹牡⁣獩栠湡汤摥挮湯楴畮⁥戻敲歡㬠敤慦汵⁴›潣瑮湩敵㬠⼠ 湵湫睯⁮摥敧琠灹絥⽽‪传膀藥ꚁ뗧蚺胣⪂⨯楬瑳潟彦潰湩獴㴠丠䱕⁌爻瑥牵⁮‱紻⨯臣꺁雩낕臣醼臣꺁䵂䅟彄敢摮楬敮꟦ꂀ臣뺯臣讂菣뎃菣ꦃ苣뎃菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂꣨鞮臣讂胣ꢳ蓦骼瀠꾁胣閃菣뎃苣랕臣辏臣貂苣ꎚ軦鎽臣뎹鷩誸臣芁苣芀꾁苣뎃苣鶃苣뎃菣ꞁ臣讂胣₂㉰臣馃菣覃菣ꒂ菣꺁臥ꢃ臣鶃苣뎃菣ꞁ臣讂胣ꢳ蓦骼臣꺁雩낕臣誁臣ꚁ臣膀裦薀臣뢸臣憫橤戭摯ㅹ臣袂臣憳橤戭摯㉹臣뺯臣讂菣뎃菣ⶉ菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂꣨鞮臣讂胣鎁臣馃菣覃菣ꒂ菣꾁뺁臣꾁꺁髩ꖎ뷤銂賦ꒁ臣ꢁ臣ꪁ苣貁胣醈胣꾁냥ꖝ臣貂苣꺁菣ꒂ菣袃臣鎃苣鎃菣蚃苣銂鿧讂뿥膦臣芁苣芀⼪湩⁴䵂䅟彄敢摮楬敮㨺潣灭瑵彥䵂䅟彄敢摮楬敮瘨楯⥤摻畯汢⁥敭慴彬桴捩湫獥⁳※⼯琠楨正敮獳漠⁦桴⁥桳敥浴瑥污䵂㉟彄佂奄⨠敢摮楬敮摟獩汰祡摥癟牥楳湯㬠⼠ 䐳瘭牥楳湯漠⁦桴⁥敢摮楬敮䵂噟䍅佔⁒整灭癟㬠⼠ 敶瑣牯獵摥映牯瘠牥⁹桳牯⁴数楲摯⁳潦⁲瑳牯湩⁧整灭牯牡⁹瑳晵⽦ 湩瑩污祬洠牡瑫敨戠湥汤湩⁥慤慴愠⁳湩慶楬Ɽ椠⁮慣敳眠⁥慦汩栠牥⹥慤慴癟污摩㴠〠㬠⼯焠慵楬楦慣楴湯挠敨正晩⠠啎䱌㴠‽敢摮 敲畴湲〠㬠晩⠠啎䱌㴠‽敢摮☭瑧朻瑥慟橤江獩⡴⤩爠瑥牵⁮‰椻⁦丨䱕⁌㴽戠湥ⵤ朦㭴敧彴慰瑲⤨ 敲畴湲〠㬠⼯琠楨⁳敢摮楬敮栠獡琠⁯慨敶愠㌠ⵄ敶獲潩楮⁦瀨牡湥⵴朦㭴敧彴楶睥瑟灹⡥⤩笠晩⠠啎䱌㴠‽戨湥汤湩彥楤灳慬敹彤敶獲潩⁮‽敢摮☭瑧朻瑥损牵敲瑮㍟彄敶獲潩⡮⤩ 敲畴湲〠㬠敽獬⁥楻⁦丨䱕⁌㴽⠠敢摮楬敮摟獩汰祡摥癟牥楳湯㴠戠湥ⵤ朦㭴敧彴汦瑡⤨⤩爠瑥牵の㬠浽瑥污瑟楨正敮獳㴠⠠敢摮☭瑧朻瑥灟牡⡴⤩☭瑧朻瑥浟瑥污瑟楨正敮獳⤨㬠⨯⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪鎁苣꾁룤芙髧ꪁ룦ꚺ臣芁苣芀裦薀臣颍臣辦觥蒚臣馃菣覃菣ꒂ菣銂蟥蚐臣讂胣馁臣辂臣膀蛥邌菣뎃菣ꦃ苣뎃臣ꆄꛨ馁苣芀㌰ㄯ⼶㘹‮䭋⨮椯⁦戨湥ⵤ朦㭴敧彴敢摮湩彧瑳瑡獵⤨☠浡㭰愦灭※敢摮☭瑧朻瑥扟湥彤灯⤨☠浡㭰愦灭※‡戨湥ⵤ朦㭴敧彴敢摮潟⡰⤩☭瑧椻⡳䵂呟偙彅䕂䑎佟彐䕒啇䅌⥒ 敲畴湲〠㬠⨯⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⼪⼯朠瑥琠敨渠浵敢⁲景愠橤捡湥⁴潢楤獥愮橤扟摯ㅹ㴠⠠敢摮☭瑧朻瑥慟橤江獩⡴⤩☭瑧昻湩彤潬敷瑳楟彤摡彪潢祤⤨㬠摡彪潢祤′‽戨湥ⵤ朦㭴敧彴摡彪楬瑳⤨⴩朦㭴楦摮獟捥湯彤潬敷瑳楟彤摡彪潢祤⤨㬠畮彭景慟橤捡湥彴潢楤獥㴠⠠摡彪潢祤㼱ㄠ㨠〠 ‫愨橤扟摯㉹㼠ㄠ㨠〠 ⼻떂苣覃菣꾂菣ꮃ苣袨껧馁苣芀⼪晩⠠摡彪潢祤⤱笠晩⠠‡敢摮楬敮摟獩汰祡摥癟牥楳湯☭瑧挻浯異整癟捥潴彲数灲瑟睯牡獤慟橤扟摯⡹摡彪潢祤ⰱ猠摩彥敶瑣牯⤱ 敲畴湲〠㬠楳敤癟捥潴ㅲ渮牯慭楬敳⤨㬠楽⡦摡彪潢祤⤲笠晩⠠‡敢摮楬敮摟獩汰祡摥癟牥楳湯☭瑧挻浯異整癟捥潴彲数灲瑟睯牡獤慟橤扟摯⡹摡彪潢祤ⰲ猠摩彥敶瑣牯⤲ 敲畴湲〠㬠楳敤癟捥潴㉲渮牯慭楬敳⤨紻⨯菣뎃菣ꦃ苣뎃菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂꣨鞮臣讂胣⪂椯⁦ℨ戠湥ⵤ朦㭴敧彴敢摮湩彧瑳瑡獵⤨⼠‪敢摮楬敮渠瑯戠湥⁴⼪簠⁼‡慰敲瑮☭瑧朻瑥癟敩彷祴数⤨⼠‪汦瑡瘠敩⁷⼪ ⽻ 潮整㨠栠牥⁥敷搠湯胢璙欠潮⁷桷瑥敨⁲桴⁥楤敭獮潩⁮潰湩⁴獩传呕䥓䕄漠⁲义䥓䕄⼮ 桴獩栠獡琠⁯敢琠歡湥椠瑮⁯捡潣湵⁴慬整⹲⼯栠睯癥牥‬瑩猠潨汵⁤潷歲攠瑩敨⁲慷⹹敢摮扟摯ㅹ灟楯瑮江晥⹴畮彭景灟楯瑮⁳‽敢摮扟摯ㅹ灟楯瑮牟杩瑨渮浵潟彦潰湩獴㴠ㄠ㬠敢摮扟摯ㅹ灟楯瑮江晥⹴慣彮敲敶獲彥灯湥湩彧楤⁲‽敢摮扟摯ㅹ灟楯瑮牟杩瑨挮湡牟癥牥敳潟数楮杮摟物㴠〠㬠敢摮扟摯ㅹ灟楯瑮江晥⹴⁰‽戨湥汤湩彥楤灳慬敹彤敶獲潩⵮朦㭴敧彴畣牲湥彴散瑮牥江湩⡥⤩朮瑥獟慴瑲瑰⤨㬠敢摮扟摯ㅹ灟楯瑮牟杩瑨瀮㴠⠠敢摮楬敮摟獩汰祡摥癟牥楳湯☭瑧朻瑥损牵敲瑮损湥整彲楬敮⤨⸩敧彴湥灤⡴ ⼻ 潮整漠数楮杮搠物捥楴湯⹳氠晥⁴楷汬朠瑥猠慴瑲瀭楯瑮‬楲桧⁴楷汬朠瑥攠摮瀭楯瑮‬敩‮敶瑣牯朠敯⁳敬瑦☭瑧爻杩瑨戮湥彤潢祤弱潰湩彴楲桧⹴灯湥湩彧楤敲瑣潩⁮‽戨湥汤湩彥楤灳慬敹彤敶獲潩⵮朦㭴敧彴畣牲湥彴散瑮牥江湩⡥⤩朮瑥癟⤨㬠戨湥彤潢祤弱潰湩彴楲桧⹴灯湥湩彧楤敲瑣潩⥮渮牯慭楬敳⤨㬠敢摮扟摯ㅹ灟楯瑮江晥⹴灯湥湩彧楤敲瑣潩⁮‽⠭敢摮扟摯ㅹ灟楯瑮牟杩瑨漮数楮杮摟物捥楴湯 ⼻ 潰湩獴眠瑩⁨敲灳捥⁴潴戠瑯慨橤捡湥⁴潢楤獥愠敲琠敨猠浡扥湥彤潢祤弲潰湩彴敬瑦渮浵潟彦潰湩獴㴠戠湥彤潢祤弲潰湩彴楲桧⹴畮彭景灟楯瑮⁳‽‱戻湥彤潢祤弲潰湩彴敬瑦挮湡牟癥牥敳潟数楮杮摟物㴠戠湥彤潢祤弲潰湩彴楲桧⹴慣彮敲敶獲彥灯湥湩彧楤⁲‽‰戻湥彤潢祤弲潰湩彴楲桧⹴灯湥湩彧楤敲瑣潩⁮‽敢摮扟摯ㅹ灟楯瑮牟杩瑨漮数楮杮摟物捥楴湯㬠敢摮扟摯㉹灟楯瑮江晥⹴灯湥湩彧楤敲瑣潩⁮‽敢摮扟摯ㅹ灟楯瑮江晥⹴灯湥湩彧楤敲瑣潩⁮戻湥彤潢祤弲潰湩彴敬瑦瀮㴠戠湥彤潢祤弱潰湩彴敬瑦瀮㬠敢摮扟摯㉹灟楯瑮牟杩瑨瀮㴠戠湥彤潢祤弱潰湩彴楲桧⹴⁰紻汥敳笠⼯映物瑳‬敧⁴潳敭戠湥楤杮瀠牡浡瑥牥䉳彍啓䙒䍁⁅猪牵慦散㴠戠湥汤湩彥楤灳慬敹彤敶獲潩⵮朦㭴敧彴畳晲捡⡥ 椻⁦丨䱕⁌㴽猠牵慦散 敲畴湲〠㬠䵂䉟久彄偏⨠潢⁰‽敢摮☭瑧朻瑥扟湥彤灯⤨㬠晩⠠啎䱌㴠‽潢⥰爠瑥牵⁮‰搻畯汢⁥敢摮慟杮敬㴠戠灯☭瑧朻瑥扟湥彤湡汧㉥⤨㬠潤扵敬戠湥彤牡彣湡汧⁥‽䥐ⴠ戠湥彤湡汧⁥搻畯汢⁥慨晬扟湥彤牡彣湡汧⁥‽敢摮慟捲慟杮敬㈯〮㬠睳瑩档⠠畳晲捡ⵥ朦㭴敧彴祴数⤨ 捻獡⁥䵂呟偙彅奃䥌䑎剅㨠笠⼠ 潮整琠慨⁴桴⁥敢摮漠⁰慣⁮敢戠瑯⁨敲畧慬⁲湡⁤潣楮䉣彍奃䥌䑎剅⨠祣楬摮牥㴠⠠䵂䍟䱙义䕄⁒⤪猠牵慦散㬠潤扵敬爠摡畩⁳‽祣楬摮牥☭瑧朻瑥牟摡⤨㬠潤扵敬漠瑵楳敤牟摡畩⁳‽慲楤獵㬠晩⠠敢摮楬敮摟獩汰祡摥癟牥楳湯☭瑧朻瑥獟湥敳⤨ 畯獴摩彥慲楤獵⬠‽敭慴彬桴捩湫獥⁳⼻ 敳⁴潳敭挠浯潭⁮慶畬獥敢摮扟摯ㅹ灟楯瑮江晥⹴慣彮敲敶獲彥灯湥湩彧楤⁲‽敢摮扟摯ㅹ灟楯瑮牟杩瑨挮湡牟癥牥敳潟数楮杮摟物㴠〠㬠敢摮扟摯ㅹ灟楯瑮牟杩瑨漮数楮杮摟物捥楴湯㴠戨湥汤湩彥楤灳慬敹彤敶獲潩⵮朦㭴敧彴畣牲湥彴散瑮牥江湩⡥⤩朮瑥隽볯⦈㬠戨湥彤潢祤弱潰湩彴楲桧⹴灯湥湩彧楤敲瑣潩⥮渮牯慭楬敳⤨㬠敢摮扟摯ㅹ灟楯瑮江晥⹴灯湥湩彧楤敲瑣潩⁮‽⠭敢摮扟摯ㅹ灟楯瑮牟杩瑨漮数楮杮摟物捥楴湯 椻⁦漨瑵楳敤牟摡畩⁳氦㭴‽啁佔䥄彍䥄呓乁䕃呟䱏剅乁䕃 ⽻ 灳捥慩⁬慣敳㨠漠瑵楳敤爠摡畩⁳‰‭牴癩慩⁬楤敭獮潩⁮潰湩⹴敢摮扟摯ㅹ灟楯瑮江晥⹴畮彭景灟楯瑮⁳‽敢摮扟摯ㅹ灟楯瑮牟杩瑨渮浵潟彦潰湩獴㴠ㄠ㬠敢摮扟摯ㅹ灟楯瑮江晥⹴⁰‽戨湥汤湩彥楤灳慬敹彤敶獲潩⵮朦㭴敧彴畣牲湥彴散瑮牥江湩⡥⤩朮瑥獟慴瑲瑰⤨㬠敢摮扟摯ㅹ灟楯瑮牟杩瑨瀮㴠⠠敢摮楬敮摟獩汰祡摥癟牥楳湯☭瑧朻瑥损牵敲瑮损湥整彲楬敮⤨⸩敧彴湥灤⡴ 戻湥彤潢祤弲潰湩彴敬瑦渮浵潟彦潰湩獴㴠戠湥彤潢祤弲潰湩彴楲桧⹴畮彭景灟楯瑮⁳‽‱戻湥彤潢祤弲潰湩彴敬瑦挮湡牟癥牥敳潟数楮杮摟物‽敢摮扟摯㉹灟楯瑮牟杩瑨挮湡牟癥牥敳潟数楮杮摟物㴠〠㬠敢摮扟摯㉹灟楯瑮牟杩瑨漮数楮杮摟物捥楴湯㴠戠湥彤潢祤弱潰湩彴楲桧⹴灯湥湩彧楤敲瑣潩⁮戻湥彤潢祤弲潰湩彴敬瑦漮数楮杮摟物捥楴湯㴠戠湥彤潢祤弱潰湩彴敬瑦漮数楮杮摟物捥楴湯㬠敢摮扟摯㉹灟楯瑮江晥⹴⁰‽敢摮扟摯ㅹ灟楯瑮江晥⹴⁰戻湥彤潢祤弲潰湩彴楲桧⹴⁰‽敢摮扟摯ㅹ灟楯瑮牟杩瑨瀮㬠敽獬⁥扻湥彤潢祤弱潰湩彴敬瑦渮浵潟彦潰湩獴㴠戠湥彤潢祤弱潰湩彴楲桧⹴畮彭景灟楯瑮⁳‽″⼻ 潣灭瑵⁥潰湩獴瀠‱潦⁲摡彪潢祤戱湥彤潢祤弱潰湩彴敬瑦瀮‱‽戨湥汤湩彥楤灳慬敹彤敶獲潩⵮朦㭴敧彴畣牲湥彴散瑮牥江湩⡥⤩朮瑥獟慴瑲瑰⤨㬠敢摮扟摯ㅹ灟楯瑮牟杩瑨瀮‱‽戨湥汤湩彥楤灳慬敹彤敶獲潩⵮朦㭴敧彴畣牲湥彴散瑮牥江湩⡥⤩朮瑥敟摮瑰⤨㬠⼯琠敨牰扯敬⁭潮⁷獩琠慨⁴瑩挠畯摬戠⁥桴瑡琠敨敳挠湥整汲湩⁥潰湩獴⠠桷捩⁨牡⽥ 湯琠敨猠牵慦散漠⁦桴⁥敢摮楬敮Ⱙ挠畯摬戠⁥湯祬椠獮摩⁥畳晲捡⁥景琠敨敢摮楬敮椮⁦戨湥汤湩彥楤灳慬敹彤敶獲潩⵮朦㭴敧彴敳獮⡥ 愦灭☻浡㭰洠瑥污瑟楨正敮獳朦㭴䄠呕䑏䵉䑟卉䅔䍎彅佔䕌䅒䍎⥅笠整灭癟㴠挠汹湩敤⵲朦㭴敧彴硶⤨㬠整灭癟献瑥江湥瑧⡨敭慴彬桴捩湫獥⥳㬠敢摮扟摯ㅹ灟楯瑮江晥⹴ㅰ㴠戠湥彤潢祤弱潰湩彴敬瑦瀮‱‫整灭癟㬠敢摮扟摯ㅹ灟楯瑮牟杩瑨瀮‱‽敢摮扟摯ㅹ灟楯瑮牟杩瑨瀮‱‫整灭癟㬠⽽ ⁡牢慥⁫湩琠敨挠浯異慴楴湯漠⁦摡彪潢祤⸱ㅰ⼮ 瑳牯⁥畣牲湥⁴ㅰ慶畬獥映牯愠橤扟摯㉹愠⁳敷汬‮桴獩眠汩⁬慳敶猠浯⁥楴敭⼮ ⼯渠瑯⁥桴瑡敷猠潨汵⁤潮⁴敲污祬挠浯異整愠橤扟摯㉹瀠楯瑮⁳湵敬獳愠橤扟摯㉹瀠楯瑮牥⼯獩渠瑯丠䱕⹌䠠睯癥牥‬桴獩瀠楯瑮⠠摡彪潢祤⸲ㅰ 獩瘠牥⁹獵晥汵映牯挠浯異楴杮⼯愠橤扟摯ㅹ瀮′椨⁦湡汧⁥獩愠畣整⸩猠⁯敷挠浯異整椠⁴湡睹祡戮湥彤潢祤弲潰湩彴敬瑦瀮‱‽敢摮扟摯ㅹ灟楯瑮江晥⹴ㅰ㬠敢摮扟摯㉹灟楯瑮牟杩瑨瀮㴱戠湥彤潢祤弱潰湩彴楲桧⹴ㅰ㬠⼯映湩獩⁨摡彪潢祤⸱ㅰ‮潲慴整瀠楯瑮⁳ㅰ椠瑮⁯桴楥⁲楦慮⁬潣牲捥⁴潬慣楴湯⼮ 潮整眠⁥潲慴整椠⁮桴⁥敮慧楴敶搠物捥楴湯猠湩散愠橤扟摯ㅹ椠⁳桴⁥浳污敬瑳椭摮硥⼯愠橤捡湥⁴潢祤愠⁳獩∠潴琭敨氭晥⵴景琭敨戭湥汤湩ⵥ散瑮牥楬敮Ⱒ眠楨档洠慥獮⼯爠瑯瑡湩⁧潴琠敨氠晥⹴⼯楦獲ⱴ挠浯異整琠敨爠杩瑨瘠捥潴⁲潦⁲桴⁥潲慴楴湯氠湩⹥䵂噟䍅佔⁒潲彴⡶祣楬摮牥☭瑧朻瑥癟⤨ 椻⁦爨瑯癟┠⠠戨湥汤湩彥楤灳慬敹彤敶獲潩⵮朦㭴敧彴畣牲湥彴散瑮牥江湩⡥⤩朮瑥癟⤨ 氦㭴〠〮 牻瑯癟爮癥牥敳⤨㬠䉽彍潲慴整灟楯瑮慟潲湵彤楬敮☨浡㭰戨湥彤潢祤弱潰湩彴敬瑦瀮⤱‬祣楬摮牥☭瑧朻瑥灟ㅴ⤨‬潲彴ⱶⴠ慨晬扟湥彤牡彣湡汧⥥㬠䵂牟瑯瑡彥潰湩彴牡畯摮江湩⡥愦灭⠻敢摮扟摯ㅹ灟楯瑮牟杩瑨瀮⤱挬汹湩敤⵲朦㭴敧彴瑰⠱Ⱙ爠瑯癟‬栭污彦敢摮慟捲慟杮敬 ⼻ 楦楮桳愠獬⁯摡彪潢祤⸲ㅰ‮潲慴整瀠楯瑮⁳ㅰ椠瑮⁯桴楥⁲楦慮⁬潣牲捥⁴潬慣楴湯䈮彍潲慴整灟楯瑮慟潲湵彤楬敮☨浡㭰戨湥彤潢祤弲潰湩彴敬瑦瀮⤱‬祣楬摮牥☭瑧朻瑥灟ㅴ⤨‬潲彴ⱶ慨晬扟湥彤牡彣湡汧⥥㬠䵂牟瑯瑡彥潰湩彴牡畯摮江湩⡥愦灭⠻敢摮扟摯㉹灟楯瑮牟杩瑨瀮⤱‬祣楬摮牥☭瑧朻瑥灟ㅴ⤨‬潲彴ⱶ栠污彦敢摮慟捲慟杮敬 ⼻ 潣灭瑵⁥潰湩獴瀠映牯愠橤扟摯ㅹ搮畯汢⁥⁸椻⁦戨灯☭瑧椻⡳䵂呟偙彅䕂䑎佟彐䕒啇䅌⥒ 硻‽⠨䵂䉟久彄偏剟䝅䱕剁⨠ 潢⥰☭瑧挻浯異整㍟彄畯獴摩彥灡牰硯灟牥獟摩⡥ 紻汥敳椠⁦戨灯☭瑧椻⡳䵂呟偙彅䕂䑎佟彐佃䥎⥃ ⽻ 佔佄㨠椠灭敬敭瑮挠湯捩戠湥汤湩⁥敨敲敲畴湲〠㬠瑽浥彰⁶‽砭猪摩彥敶瑣牯‱戻湥彤潢祤弱潰湩彴敬瑦瀮㴠戠湥彤潢祤弱潰湩彴敬瑦瀮‱‫整灭癟㬠敢摮扟摯ㅹ灟楯瑮牟杩瑨瀮㴠戠湥彤潢祤弱潰湩彴楲桧⹴ㅰ⬠琠浥彰⁶⼻ 潮整㨠愠橤扟摯ㅹ瀮′湡⁤摡彪潢祤⸲Ɒ愠橤扟摯㉹瀮′牡⁥敹⁴潴戠⁥潣灭瑵摥⼮ 潮⁷桴牥⁥牡⁥睴⁯慣敳⁳›⤱琠敨戠湥⁤牡⁣湡汧⁥獩愠畣整⠠敩‮潮洠牯⁥桴湡㤠‰敤牧敥⥳⼬ ⤲琠敨戠湥⁤牡⁣湡汧楥⁳潭敲琠慨⁮〹搠来敲獥椮⁦戨湥彤牡彣湡汧⁥朦㭴⠠䥐潟敶彲′‫䵂䅟䝎䕌呟䱏剅乁䕃⤩笠⼠ 獵⁥慴杮湥⁴灡牰硯浩瑡潩⽮ 敷眠汩⁬楦楮桳挠浯異楴杮愠橤扟摯ㅹ‮摡彪潢祤⸱㉰椠⁳敬瑦⼮ 摩慥㨠渠瑯捩⁥桴瑡愠橤扟摯ㅹ椠⁳潴琠敨氠晥潴⁦桴⁥敢摮楬敮挭湥整汲湩⽥ 敢慣獵⁥瑩椠⁳桴⁥潬敷瑳椭摮硥渠楥桧潢⹲吠敨敲潦敲琠敨挠潲獳瀭潲畤瑣⼯漠⁦散瑮牥楬敮瘭戠⁹整灭癟瀠楯瑮⁳潴慷摲⁳桴捥汹湩敤⁲愨瑣慵汬⁹瑩椠⁳慴杮湥⽴ 潴琠敨挠汹湩敤⥲䈮彍䕖呃剏琠湡敧瑮癟戨湥彤潢祤弱潰湩彴楲桧⹴灯湥湩彧楤敲瑣潩⁮‪整灭癟 琻湡敧瑮癟献瑥江湥瑧⡨⥸㬠敢摮扟摯ㅹ灟楯瑮江晥⹴㉰㴠戠湥彤潢祤弱潰湩彴敬瑦瀮⬠琠湡敧瑮癟㬠敢摮扟摯ㅹ灟楯瑮牟杩瑨瀮′‽敢摮扟摯ㅹ灟楯瑮牟杩瑨瀮⬠琠湡敧瑮癟㬠⼯渠瑯慥橤扟摯㉹瀮‱獩愠牬慥祤挠浯異整⹤映物瑳猠瑥猠浯⁥潣浭湯瘠污敵⹳敢摮扟摯㉹灟楯瑮江晥⹴畮彭景灟楯瑮⁳‽敢摮扟摯㉹灟楯瑮牟杩瑨渮浵潟彦潰湩獴㴠㌠㬠敢摮扟摯㉹灟楯瑮江晥⹴慣彮敲敶獲彥灯湥湩彧楤⁲‽敢摮扟摯㉹灟楯瑮牟杩瑨挮湡牟癥牥敳潟数楮杮摟物㴠〠㬠敢摮扟摯㉹灟楯瑮牟杩瑨漮数楮杮摟物捥楴湯㴠戠湥彤潢祤弱潰湩彴楲桧⹴灯湥湩彧楤敲瑣潩⁮戻湥彤潢祤弲潰湩彴敬瑦漮数楮杮摟物捥楴湯㴠戠湥彤潢祤弱潰湩彴敬瑦漮数楮杮摟物捥楴湯㬠⼯渠睯挠浯異整愠橤扟摯㉹瀮整灭癟㴠ⴠ⩸楳敤癟捥潴㉲㬠敢摮扟摯㉹灟楯瑮江晥⹴⁰‽敢摮扟摯㉹灟楯瑮江晥⹴ㅰ⬠琠浥彰⁶戻湥彤潢祤弲潰湩彴楲桧⹴⁰‽敢摮扟摯㉹灟楯瑮牟杩瑨瀮⬱琠浥彰⁶⼻ 楦慮汬ⱹ挠浯異整愠橤扟摯㉹瀮⼲ 潮整琠敨漠摲牥椠⁮桴⁥牣獯⵳牰摯捵⁴琡湡敧瑮癟㴠琠浥彰⁶‪敢摮扟摯㉹灟楯瑮牟杩瑨漮数楮杮摟物捥楴湯※慴杮湥彴⹶敳彴敬杮桴砨 戻湥彤潢祤弲潰湩彴敬瑦瀮′‽敢摮扟摯㉹灟楯瑮江晥⹴⁰‫慴杮湥彴⁶戻湥彤潢祤弲潰湩彴楲桧⹴㉰㴠戠湥彤潢祤弲潰湩彴楲桧⹴⭰琠湡敧瑮癟㬠敽獬⁥⁻⼯甠敳椠瑮牥敳瑣潩⁮灡牰硯浩瑡潩⽮ 潮整㨠愠橤扟摯㉹瀮′獩琠敨猠浡⁥獡愠橳扟摯ㅹ瀮⸱敢摮扟摯ㅹ灟楯瑮江晥⹴㉰㴠戠湥彤潢祤弲潰湩彴敬瑦瀮‱戻湥彤潢祤弱潰湩彴楲桧⹴㉰㴠戠湥彤潢祤弲潰湩彴楲桧⹴ㅰ㬠⼯桷湥甠楳杮椠瑮牥敳瑣潩⁮灡牰硯浩瑡潩Ɱ搠浩湥楳湯⁳潰湩獴眠瑩⁨敲灳捥⁴潴⼯戠瑯⁨摡慪散瑮戠摯敩⁳牡⁥桴⁥慳敭‬潳眠⁥番瑳挠灯⁹桴浥戮湥彤潢祤弲潰湩彴敬瑦渮浵潟彦潰湩獴㴠戠湥彤潢祤弲潰湩彴楲桧⹴畮彭景灟楯瑮⁳‽″戻湥彤潢祤弲潰湩彴敬瑦挮湡牟癥牥敳潟数楮杮摟物㴠戠湥彤潢祤弲潰湩彴楲桧⹴慣彮敲敶獲彥灯湥湩彧楤⁲‽‰戻湥彤潢祤弲潰湩彴楲桧⹴灯湥湩彧楤敲瑣潩⁮‽敢摮扟摯ㅹ灟楯瑮牟杩瑨漮数楮杮摟物捥楴湯㬠敢摮扟摯㉹灟楯瑮江晥⹴灯湥湩彧楤敲瑣潩⁮‽敢摮扟摯ㅹ灟楯瑮江晥⹴灯湥湩彧楤敲瑣潩⁮⼻ 潮整眠⁥牡⁥睳瑩档湩灧楯瑮扳湥彤潢祤弲潰湩彴敬瑦瀮′‽敢摮扟摯ㅹ灟楯瑮江晥⹴ㅰ㬠敢摮扟摯㉹灟楯瑮牟杩瑨瀮′‽敢摮扟摯ㅹ灟楯瑮牟杩瑨瀮‱戻湥彤潢祤弲潰湩彴敬瑦瀮㴠戠湥彤潢祤弱潰湩彴敬瑦瀮㬠敢摮扟摯㉹灟楯瑮牟杩瑨瀮㴠戠湥彤潢祤弱潰湩彴楲桧⹴⁰紻絽牢慥⁫挻獡⁥䵂呟偙彅佃䕎㨠牢慥⁫搻晥畡瑬㨠㬠⼠ 湵湫睯⁮牯椠汬来污畳晲捡⁥紻⽽ꎚ軦鎽臣蒐胣ꮁ꿥馁苣閃菣뎃苣랕苣袨껧馁苣芀⼪晩⠠摡彪潢祤⤱⽻ 晩琠敨映慬杮⁥敬杮桴挠浯異慴楴湯映楡獬‬牰瑥湥⁤桴⁥摡慪散瑮戠摯⁹潤獥渠瑯攠楸瑳‮潦⁲楳灭楬楣祴椮⁦ℨ戠湥ⵤ朦㭴潣灭瑵彥汦湡敧江湥瑧⡨慰敲瑮☭瑧朻瑥癟敩彷祴数⤨愬橤扟摯ㅹ昬ㅬ⤩笠摡彪潢祤‱‽啎䱌㬠ⴭ畮彭景慟橤捡湥彴潢楤獥㬠絽晩⠠摡彪潢祤⤲笠晩⠠‡敢摮☭瑧挻浯異整晟慬杮彥敬杮桴瀨牡湥⵴朦㭴敧彴楶睥瑟灹⡥Ⱙ摡彪潢祤ⰲ汦⤲ 慻橤扟摯㉹㴠丠䱕⁌ⴻ渭浵潟彦摡慪散瑮扟摯敩⁳紻⽽袂臣膀菣벃苣銂鳦릊臣节臣ꢁ臣ꚁ菣벃苣馁苣芀菣뎃菣ꦃ苣뎃菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣貁藥ꚁ臣馃菣覃菣ꒂ菣ꮁ꿥鞁臣袨껧閁苣讂臣膀裦薀臣貐꟦ꮁ럥讉臣馃菣覃菣ꒂ菣ꮁ꿥鞁臣閃菣뎃苣螃苣ꆃ菣랂菣뎃菣ꒂ菣袃苣袨껧馁苣鎁臣貁蟥ꖝ苣芀⼪慤慴癟污摩㴠ㄠ㬠⼯戠晥牯⁥敷挠湡爠瑥牵Ɱ眠⁥慨敶琠⁯档捥⁫晩戠摯ㅹ㈬氠晥⡴楲桧⥴戠湥汤湩⁥楤敭獮潩⁮潰湩獴⼠ 牡⁥桴⁥慳敭⼮ 潮整琠敨猠浡⁥敭湡湳瑯琠敨猠浡⁥潰湩整獲‬畢⁴桴⁥潣瑮湥獴愠敲攠畱癩污湥⹴晩⠠摡彪潢祤‱愦灭☻浡㭰摡彪潢祤⤲笠潢祤㈱江晥彴桴彥慳敭㴠⠠敢摮扟摯ㅹ灟楯瑮江晥⁴㴽戠湥彤潢祤弲潰湩彴敬瑦 戻摯ㅹ弲楲桧彴桴彥慳敭㴠⠠敢摮扟摯ㅹ灟楯瑮牟杩瑨㴠‽敢摮扟摯㉹灟楯瑮牟杩瑨 紻⨯蟩膦볯馃菣覃螃苣ꆃ菣랂菣뎃菣ꒂ菣袃臣蒁臣貂臣貁鶃苣뎃菣袼菣ꒂ菣袃覼臣뾁苣ꮐ苣ꢁ臣꾁胣龮髩ꮁ臣讦苣릁臣馃菣覃菣ꒂ菣貁臣蒁臣ꞁ潢祤牟煥極敲彤楶楳汢鶃苣뎃苣꾁髩ꖎ뷤銂賦몤臣讂臣趁臣芁苣芀⼪晩⠠‱㴽敢摮扟摯ㅹ灟楯瑮江晥⹴畮彭景灟楯瑮⥳戠湥彤潢祤弱潰湩彴敬瑦戮摯役敲畱物摥癟獩扩敬㴠愠橤扟摯ㅹ㬠晩⠠‱㴽戠湥彤潢祤弱潰湩彴楲桧⹴畮彭景灟楯瑮⥳戠湥彤潢祤弱潰湩彴楲桧⹴潢祤牟煥極敲彤楶楳汢⁥‽摡彪潢祤‱椻⁦ㄨ㴠‽敢摮扟摯㉹灟楯瑮江晥⹴畮彭景灟楯瑮⥳戠湥彤潢祤弲潰湩彴敬瑦戮摯役敲畱物摥癟獩扩敬‽摡彪潢祤′椻⁦ㄨ㴠‽敢摮扟摯㉹灟楯瑮牟杩瑨渮浵潟彦潰湩獴 敢摮扟摯㉹灟楯瑮牟杩瑨戮摯役敲畱物摥癟獩扩敬㴠愠橤扟摯㉹㬠敲畴湲ㄠ㬠⽽⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪䈪彍啁佔䑟䵉久䥓乏挠慬獳猠畴晦⨮⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪⨪⼯몢껥ꪁ駧讦髧讉돦骼苣ꪃ菣覃菣벃菣ꮁ臣蒁臣뺹臣讁臣鶃苣뎃菣銂裦薀臣ꆄꛨ몇鷦讂臣Ꚑ臣銂菣Ꞃ菣꾂臣讂胣붂菣莃菣ꊃ菣覃臣誁臣ꚁ臣膀裦薀臣芙雩꺁꿧蒴臣龁苣ꮁ臣꺁駧讦髧讉돦銂铧蒁臣蒁苣芀볯ꒁ臣馃菣覃菣ꒂ菣貁菣ꦃ菣뢂랕苣ꢡꓧ馁苣龁苣ꮁ볯鲽鳥蒚臣覼귧ꆾ臣閃菣뎃苣ⶸ菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂铧蒁臣蒁苣ꢁ臣꾁胣醈胣꾁跥ꮁ胣袂苣颫臣榄硤苣膌臣馃菣覃菣ꒂ菣袼臣貂苣꺁볯ꒁ臣馃菣覃菣ꒂ菣ꮁ꿥馁苣覼臣뺯臣ꚁ臣뾁菣뢂菣ꪃ菣ꒂ菦놠苣袨껧馁苣芀⼪潶摩䈠彍啁佔䑟䵉久䥓乏㨺潣灭瑵彥潰湩獴瑟彯杩潮敲楟彮潳楬⡤潶摩笩湩⁴⁩䈻彍䑁摟浩损牯敮⩲整灭灟楯瑮㬠潦⁲椨㴠〠㬠椠☠瑬※畮彭景扟湥汤湩獥㬠椠⬫ 楻⁦ℨ戠湥獤楛ⵝ朦㭴慤慴癟污摩 潣瑮湩敵㬠晩⠠敢摮孳嵩☭瑧愻橤扟摯ㅹ 晻牯⠠整灭灟楯瑮㴠戠湥獤楛ⵝ朦㭴潢祤弱潰湩獴㬠琠浥彰潰湩⁴※整灭灟楯瑮㴠琠浥彰潰湩⵴朦㭴敮瑸 楻⁦丨䱕㵌‽整灭灟楯瑮☭瑧愻橤扟湥汤湩⥥挠湯楴畮⁥椻⁦⠨整灭灟楯瑮☭瑧愻橤扟湥汤湩⥥☭瑧朻瑥楟硤⤨☠瑧※戨湥獤楛ⵝ朦㭴敢摮⴩朦㭴敧彴摩⡸⤩挠湯楴畮⁥椻⁦挨敨正瑟潷扟湥汤湩獥慟橤捡湥彴潴獟浡彥汦湡敧戨湥獤楛ⵝ朦㭴敢摮戬湥獤楛ⵝ朦㭴摡彪潢祤ⰱ整灭灟楯瑮☭瑧愻橤扟湥汤湩⥥ 瑻浥彰潰湩⵴朦㭴杩潮敲楟彮潳楬彤潭敤㴠ㄠ㬠絽楽⁦戨湥獤楛ⵝ朦㭴摡彪潢祤⤲笠潦⁲琨浥彰潰湩⁴‽敢摮孳嵩☭瑧戻摯㉹灟楯瑮⁳※整灭灟楯瑮㬠琠浥彰潰湩⁴‽整灭灟楯瑮☭瑧渻硥⥴笠晩⠠啎䱌㴠‽整灭灟楯瑮☭瑧愻橤扟湥汤湩⥥挠湯楴畮⁥椻⁦⠨整灭灟楯瑮☭瑧愻橤扟湥汤湩⥥☭瑧朻瑥楟硤⤨☠瑧※戨湥獤楛ⵝ朦㭴敢摮⴩朦㭴敧彴摩⡸⤩挠湯楴畮⁥椻⁦挨敨正瑟潷扟湥汤湩獥慟橤捡湥彴潴獟浡彥汦湡敧戨湥獤楛ⵝ朦㭴敢摮戬湥獤楛ⵝ朦㭴摡彪潢祤ⰲ整灭灟楯瑮☭瑧愻橤扟湥汤湩⥥ 瑻浥彰潰湩⵴朦㭴杩潮敲楟彮潳楬彤潭敤㴠ㄠ㬠絽絽潰湩獴瑟彯杩潮敲楟彮潳楬彤潣灭瑵摥㴠ㄠ㬠⽽鎁臣ꊖ闦꾁蟨開꿥閳賥馃菣覃菣ꒂ菣銂꟦邈臣膀菣벃苣讧胩銂賦몤臣讂胣鎁苣꾁菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂꣨鞮臣讂룤膦雩낕臣芁苣芀⼪湩⁴䵂䅟呕彏䥄䕍华佉㩎挺浯異整慟瑵彯楤敭獮潩彮慤慴瘨楯⥤楻瑮椠㬠⼯栠癡⁥潴栠癡⁥⁡潤畣敭瑮晩⠠啎䱌㴠‽潤⥣爠瑥牵⁮‰⼻ 晩渠⁯慰瑲‬牴⁹潴朠瑥愠渠睥瀠牡⁴牦浯琠敨搠捯浵湥楴⁦丨䱕⁌㴽瀠牡⥴笠敳彴慰瑲搨捯☭瑧朻瑥灟牡⡴⤩㬠楽⁦丨䱕⁌㴽瀠牡⥴笠楤瑲⁹〽㬠敲畴湲ㄠ㬠災楯瑮彳潴楟湧牯彥湩獟汯摩损浯異整⁤‽‰⼻鎃菣벃苣ꒂ菣銂뻥讂胣⪂椯⁦瘨敩⥷笠楶睥瑟灹⁥‽楶睥☭瑧朻瑥损牵敲瑮癟敩⡷ 紻汥敳笠⼯眠⁥牡⁥捳敲敷牤瑥牵⁮‰紻⨯藥ꚁ臣馃菣覃菣ꒂ菣ꮁ꿥鞁臣ꢅ臣꺁菣뎃菣ꦃ苣뎃菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂꣨鞮臣讂胣⪂是牯⠠⁩‽‰※⁩氦㭴渠浵潟彦敢摮楬敮⁳※⭩⤫笠敢摮孳嵩☭瑧挻浯異整䉟彍䑁扟湥汤湩⡥ 紻⨯藥ꚁ臣馃菣覃菣ꒂ菣ꮁ꿥鞁臣閃菣뎃苣螃苣ꆃ菣랂菣뎃菣ꒂ菣袃苣袨껧馁苣芀⼪潦⁲椨㴠〠㬠椠☠瑬※畮彭景扟湥汤湩獥※⭩⤫笠晩⠠敢摮孳嵩☭瑧搻瑡彡慶楬⥤笠晩⠠敢摮孳嵩☭瑧愻橤扟摯ㅹ 敢摮孳嵩☭瑧挻浯異整䉟彍䑁晟慬杮彥潰湩獴戨湥獤楛ⵝ朦㭴摡彪潢祤⤱㬠晩⠠敢摮孳嵩☭瑧愻橤扟摯㉹戩湥獤楛ⵝ朦㭴潣灭瑵彥䵂䅟彄汦湡敧灟楯瑮⡳敢摮孳嵩☭瑧愻橤扟摯㉹ 紻摽物祴㴠〠爻瑥牵⁮‱紻戼㹲颻賩ꦼ戼㹲뺹臣讁臣몟鳦蒚蟨開꿥閳賥ꊖ闦膀苣뎃苣袃菣꾂苣膀菣릂菣ꦃ苣뾂臣袂臣뺹臣讁臣隻臣몟鳦蒚雩낕臣设戼㹲⼊⌯湩汣摵⁥猢摴晡⹸≨椣据畬敤∠敂摮䅃⹄≨椣据畬敤∠敂摮䅃䑄捯栮⌢湩汣摵≥敂摮䅃噄敩偷牡⹴≨椣据畬敤∠啁佔䥄⹍塈≘⨯⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪䵂䅟彄楤彭潣湲牥挠慬獳猠畴晦⨮⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪⨪䈯彍䑁摟浩损牯敮㩲䈺彍䑁摟浩损牯敮⡲潶摩 登獩扩敬㴠ⴠ‱渻浵潟彦潰湩獴㴠〠㬠敢摮㴠丠䱕⁌渻硥⁴‽啎䱌㬠摡彪敢摮楬敮㴠丠䱕⁌戻摯役敲畱物摥癟獩扩敬㴠丠䱕⁌椻湧牯彥湩獟汯摩浟摯⁥‽‰紻⨯臣꺁苣뎃苣袃菣꾂苣꾁룤ꮁ臣ꂁ볯ꒁ臣鶃苣뎃菣袼菣ꒂ菣袃覼苣膌臣螃苣ꆃ菣랂菣뎃菣ꒂ菣袃苣龔裦馁苣龁苣꺁苣꺁臣芁苣芀⼪䵂䅟彄楤彭潣湲牥㨺䵂䅟彄楤彭潣湲牥䈨彍佐义⁔潣獮♴浡㭰倠‬䵂䅟彄敢摮楬敮⨠ⱂ䈠彍䐳䉟䑏⩙潂祤牟煥極敲彤楶楳汢ⱥ䵂噟䍅佔⁒潣獮♴浡㭰传ⱄ椠瑮删ⱂ䈠彍䑁摟浩损牯敮⁲⨪牰癥‬䵂䉟久䱄义⁅愪橤扟湥⥤登獩扩敬㴠ⴠ‱渻浵潟彦潰湩獴㴠ㄠ㬠⁰‽⁐戻湥⁤‽⁂漻数楮杮摟物捥楴湯㴠传⁄挻湡牟癥牥敳潟数楮杮摟物㴠删⁂渻硥⁴‽啎䱌戻摯役敲畱物摥癟獩扩敬㴠䈠摯役敲畱物摥癟獩扩敬㬠摡彪敢摮楬敮㴠愠橤扟湥㭤杩潮敲楟彮潳楬彤潭敤㴠〠㬠晩⠠牰癥 瀪敲⁶‽桴獩㬠⽽鎁臣뎂菣릂菣ꦃ苣뾂臣궸臣㎫菣ꒂ菣袃苣膌臣螃苣ꆃ菣랂菣뎃菣ꒂ菣袃苣龔裦馁苣龁苣꺁苣꺁臣芁苣芀⼪䵂䅟彄楤彭潣湲牥㨺䵂䅟彄楤彭潣湲牥䈨彍佐义⁔潣獮♴浡㭰倠‬䵂偟䥏呎挠湯瑳愦灭※ㅐ‬䵂偟䥏呎挠湯瑳愦灭※㉐‬䵂䅟彄敢摮楬敮⨠ⱂ䈠彍䐳䉟䑏⁙䈪摯役敲畱物摥癟獩扩敬䈬彍䕖呃剏挠湯瑳愦灭※䑏‬湩⁴䉒‬䵂䅟彄楤彭潣湲牥⨠瀪敲ⱶ䈠彍䕂䑎䥌䕎愪橤扟湥⥤登獩扩敬㴠ⴠ‱渻浵潟彦潰湩獴㴠㌠㬠⁰‽⁐瀻‱‽ㅐ㬠㉰㴠倠′戻湥⁤‽⁂漻数楮杮摟物捥楴湯㴠传⁄挻湡牟癥牥敳潟数楮杮摟物㴠删⁂渻硥⁴‽啎䱌㬠潢祤牟煥極敲彤楶楳汢⁥‽潂祤牟煥極敲彤楶楳汢⁥愻橤扟湥汤湩⁥‽摡彪敢摮㬠杩潮敲楟彮潳楬彤潭敤㴠〠㬠晩⠠牰癥 瀪敲⁶‽桴獩㬠⽽醼臣꺁菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣銂믤꺁菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣ꮁ觥誂뷥ꚁ苣芀臣꺁雩낕臣薆껥銂귦몢臣뎂菣벃臣讂胣鶁苣貁鷩뢸臣覜铧ꪁ雩낕臣芁苣讁郥讁臣몢껥ꞁ臣ꪁ臣芀⼪潶摩䵂䅟彄楤彭潣湲牥㨺灯牥瑡牯⠽䵂䅟彄楤彭潣湲牥挠湯瑳愦灭※楧敶彮潰湩⥴湻浵潟彦潰湩獴㴠朠癩湥灟楯瑮渮浵潟彦潰湩獴㬠⁰‽楧敶彮潰湩⹴⁰瀻‱‽楧敶彮潰湩⹴ㅰ㬠㉰㴠朠癩湥灟楯瑮瀮′戻湥⁤‽楧敶彮潰湩⹴敢摮㬠灯湥湩彧楤敲瑣潩⁮‽楧敶彮潰湩⹴灯湥湩彧楤敲瑣潩⁮挻湡牟癥牥敳潟数楮杮摟物㴠朠癩湥灟楯瑮挮湡牟癥牥敳潟数楮杮摟物㬠楶楳汢⁥‽楧敶彮潰湩⹴楶楳汢⁥猻牣敥彮⁸‽楧敶彮潰湩⹴捳敲湥硟㬠捳敲湥祟㴠朠癩湥灟楯瑮献牣敥彮⁹稻扟晵癟污敵㴠朠癩湥灟楯瑮種扟晵癟污敵㬠杩潮敲楟彮潳楬彤潭敤㴠朠癩湥灟楯瑮椮湧牯彥湩獟汯摩浟摯⁥紻⨯臣꺁雩낕臣膀苣鞁菣ꎂ菣뎃苣ꞃ菣銂迦辁臣膂臣肉껥꺁菣ꒂ菣袃臣鎁臣鶃苣뎃菣ꢁ郥颁臣趁臣咯啒銂裦馁胣銼臣꺁菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣꾁胣鶁苣覂臣醼臣꺁菣ꒂ菣袃貁믤꺁菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣꺁菣ꒂ菣袼菣ꒂ菣袃貼雩뺔雦醐볯ꮁ苣誂껥ꦾ臣貂苣ꦃ苣뎃룤ꮁ臣讂臣趁胣뺁臣鶁苣覂臣讖铦릖郥貁룤뒇臣讂臣趁胣覭뻤ꞁ臣讂胣鎁臣ꞁ裦薀臣膀雩뺔菣꾂菣ꮃ臣辦ꃦ隌臣貂苣ꢁ臣蚁뫤龮臣鶾귥馁苣芀瑩爠瑥牵獮㈠椠晦戠瑯⁨潰湩獴瀠洠瑡档‬瑯敨睲獩⁥⸱⼪湩⁴䵂䅟彄楤彭潣湲牥㨺灯牥瑡牯㴽䈨彍䑁摟浩损牯敮⁲潣獮♴浡㭰愠潮桴牥摟浩灟楯瑮笩湩⁴敲彴慶⁬‽‱搻畯汢⁥⁫椻⁦渨浵潟彦潰湩獴☠瑬※‱籼愠潮桴牥摟浩灟楯瑮渮浵潟彦潰湩獴☠瑬※⤱爠瑥牵⁮‰⼻ 潰湩⁴慨⁳潴戠⁥湯琠敨氠湩楥⁦ℨ䈠彍獩灟楯瑮潟彮楬敮瀨‬灯湥湩彧楤敲瑣潩Ɱ愠潮桴牥摟浩灟楯瑮瀮‬愦灭欻⤩爠瑥牵⁮‰椻⁦昨扡⡳⥫☠瑬㴻䈠彍剐䍅卉佉⥎爠瑥癟污㴠㈠㬠⼯猠湩散戠瑯⁨敶瑣牯⁳桳畯摬戠⁥潮浲污穩摥‬桴⁥潤⵴牰摯捵⁴獩琠敨挠獯漠⁦桴⁥湡汧⹥潤扵敬砠㴠漠数楮杮摟物捥楴湯┠愠潮桴牥摟浩灟楯瑮漮数楮杮摟物捥楴湯㬠⼯挠敨正椠⁦潢桴瘠捥潴獲愠牧敥晩⠠⁸朦㭴〠㤮⤹爠瑥牵⁮敲彴慶⁬⼻ 档捥⁫晩琠敨⁹慨敶漠灰獯瑩⁥楤敲瑣潩⁮湡⁤湯⁥景琠敨挠湡戠⁥敲敶獲摥晩⠠⁸氦㭴ⴠ⸰㤹 楻⁦挨湡牟癥牥敳潟数楮杮摟物簠⁼湡瑯敨彲楤彭潰湩⹴慣彮敲敶獲彥灯湥湩彧楤⥲爠瑥牵⁮敲彴慶⁬紻敲畴湲〠㬠⽽⨪⨪⨪⨪⨪⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪䵂䅟彄敢摮楬敮挠慬獳猠畴晦⨮⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪⨪䈯彍䑁扟湥汤湩㩥䈺彍䑁扟湥汤湩⡥䵂䅟呕彏䥄䕍华佉⁎漪湷牥‬䵂䉟久䱄义⁅截湥汤湩⥥灻牡湥⁴‽睯敮⁲戻湥⁤‽敢摮楬敮㬠慤慴癟污摩㴠〠㬠⼠ 慤慴渠瑯瘠污摩ⴠ渠⁯慤慴挠浯異整⁤敹扴湥彤潢祤弱潰湩彴敬瑦戮湥⁤‽敢摮扟摯ㅹ灟楯瑮牟杩瑨戮湥⁤‽桴獩㬠敢摮扟摯㉹灟楯瑮江晥⹴敢摮㴠戠湥彤潢祤弲潰湩彴楲桧⹴敢摮㴠琠楨⁳戻湥彤潢祤弱潰湩彴敬瑦戮摯役敲畱物摥癟獩扩敬㴠戠湥彤潢祤弱潰湩彴楲桧⹴潢祤牟煥極敲彤楶楳汢⁥‽敢摮㬠敢摮扟摯㉹灟楯瑮江晥⹴潢祤牟煥極敲彤楶楳汢⁥‽敢摮扟摯㉹灟楯瑮牟杩瑨戮摯役敲畱物摥癟獩扩敬㴠戠湥⁤戻摯ㅹ灟楯瑮⁳‽啎䱌㬠潢祤弲潰湩獴㴠丠䱕⁌紻䵂䅟彄敢摮楬敮㨺䉾彍䑁扟湥汤湩⡥潶摩笩䵂䅟彄楤彭潣湲牥⨠整灭灟楯瑮‬琪浥彰⁰⼻ 敤敬整氠獩獴漠⁦潰湩獴潦⁲琨浥彰潰湩⁴‽潢祤弱潰湩獴㬠琠浥彰潰湩⁴※整灭灟楯瑮㴠琠浥彰⥰笠整灭灟㴠琠浥彰潰湩⵴朦㭴敮瑸㬠敤敬整琠浥彰潰湩⁴紻潦⁲琨浥彰潰湩⁴‽潢祤弲潰湩獴㬠琠浥彰潰湩⁴※整灭灟楯瑮㴠琠浥彰⥰笠整灭灟㴠琠浥彰潰湩⵴朦㭴敮瑸㬠敤敬整琠浥彰潰湩⁴紻⽽⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪䈪彍啁佔䑟䵉久䥓乏挠慬獳猠畴晦⨮⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⼪䵂䅟呕彏䥄䕍华佉㩎䈺彍啁佔䑟䵉久䥓乏䌨敂摮䅃䑄捯䈪湥䍤䑁摟捯笩潤⁣‽敂摮䅃彄潤⁣瘻敩⁷‽䌨敂摮䅃噄敩偷牡⁴⤪搠捯☭瑧朻瑥癟敩⡷䕂䑎䅃彄䥖坅呟偙彅䅐呒 搻⁣‽啎䱌㬠慰瑲㴠丠䱕⁌搻物祴㴠ㄠ㬠楶睥瑟灹㵥ㄠ㬠⼠ 䐳瘠敩牷獥瑥癟敩彷潴晟污敳潟据彥牤睡⁮‽‰瀻楯瑮彳潴楟湧牯彥湩獟汯摩损浯異整⁤‽‰渻浵潟彦敢摮楬敮⁳‽‰戻湥獤㴠丠䱕⁌⼻ 湩瑩慩楬敺猠潨⁷瑳瑡獥映牯搠浩湥楳湯椠普浯扟桓睯汆湡敧楄⁭‽剔䕕活扟桓睯敂摮楄⁭‽剔䕕活扟桓睯慐瑲楄⁭‽䅆卌㭅⼯椠楮楴污穩⁥畁潴䐭浩挠汯牯浳损䙲慬杮⁥‽䝒⡂ⰰⰰ㔲⤵活损䉲湥⁤‽䝒⡂ⰰⰰ㔲⤵活损偲牡⁴‽䝒⡂ⰰⰰ㔲⤵⼻ 湩瑩慩楬敺映湯⁴潰湩整獲彭䙰慬杮䙥湯⁴‽啎䱌活灟敂摮潆瑮㴠丠䱕㭌彭偰牡䙴湯⁴‽啎䱌⼻ 湩瑩慩楬敺氠湩⁥湡⁤牡潲⁷瑳汹獥彭䱮湩卥祴敬㴠倠当体䥌㭄彭䱮湩坥楥桧㵴ㄠ⼻ 湩瀠硩汥浳湟牁潲卷祴敬㴠ㄠ活湟牁潲䅷杮敬㴠㌠㬰⼯椠⁮敤牧敥浳湟牁潲䱷湥瑧⁨‽㔱⼻ 湩瀠硩汥⽳ 湩瑩慩楬敺搠物祴爠来潩⁮潰湩整灲楄瑲剹来潩㵮丠䱕㭌䉽彍啁佔䑟䵉久䥓乏㨺䉾彍啁佔䑟䵉久䥓乏瘨楯⥤摻汥瑥彥潣瑮湥獴⤨㬠⽽鎁臣ꪇ该ⶕ꿥閳賥뺯뇨銂ꃧ誣臣讂胣⪂瘯楯⁤䵂䅟呕彏䥄䕍华佉㩎携汥瑥彥潣瑮湥獴瘨楯⥤楻瑮椠㬠晩⠠敢摮⥳笠潦⁲椨㴠〠㬠椠☠瑬※畮彭景扟湥汤湩獥㬠椠⬫ 楻⁦戨湥獤楛⥝搠汥瑥⁥敢摮孳嵩㬠摽汥瑥⁥嵛戠湥獤㬠敢摮⁳‽啎䱌㬠湽浵潟彦敢摮楬敮⁳‽‰瀻楯瑮彳潴楟湧牯彥湩獟汯摩损浯異整⁤‽‰瀻牡⁴‽啎䱌㬠楤瑲㵹ㄠ㬠⽽鎁臣ꊖ闦꾁触骮臣馃菣覃菣ꒂ菣ꮁ뿤辂苣螃苣ꆃ菣랂菣뎃菣벃苣銂郥肂䵂䅟彄敢摮楬敮꟦ꂀ臣뺯臣讂菣ꒂ菣뾂苣뮈臣芀⼪䵂䅟彄敢摮楬敮⨠䵂䅟呕彏䥄䕍华佉㩎机瑥䅟彄敢摮獟牴捵畴敲䈨彍䕂䑎䥌䕎⨠敢摮楬敮笩湩⁴⁩昻牯⠠⁩‽‰※♩瑬※畮彭景扟湥汤湩獥㬠椠⬫ 楻⁦戨湥獤楛ⵝ朦㭴敢摮㴠‽敢摮楬敮 敲畴湲戠湥獤楛⁝紻敲畴湲丠䱕⁌紻⨯臣꺁雩낕臣肉껥꺁摡⵪潢祤臣뺯臣讂触骮臣馃菣覃菣ꒂ菣ꮁ꿥馁苣⢋⵰朦㭴㉰馃苣袃菣銂裦馁胣鶁苣꾁臣龁臣꺁菣ꦃ菣뢂臣뺯臣讂髩ꖎ菣뎃菣ꦃ苣뎃臣馃菣覃菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣꺁㉰菣ꒂ菣袃臣鎖臣ꦃ苣뎃苣袨껧馁苣芀⼪䵂噟䍅佔⁒潣獮♴浡㭰䈠彍啁佔䑟䵉久䥓乏㨺潣灭瑵彥敢摮摟物捥楴湯癟捥潴⡲䵂䉟久䱄义⁅截湥汤湩ⱥ䈠彍䐳䉟䑏⁙愪橤扟摯ⱹ䈠彍䥌䕎⨠㉰江湩⥥獻慴楴⁣䵂噟䍅佔⁒⁶椻瑮椠㬠潦⁲椨㴠〠㬠椠☠瑬※畮彭景扟湥汤湩獥㬠椠⬫ 楻⁦戨湥獤楛ⵝ朦㭴慤慴癟污摩☠浡㭰愦灭※敢摮孳嵩☭瑧戻湥⁤㴽戠湥汤湩⥥笠晩⠠敢摮孳嵩☭瑧愻橤扟摯ㅹ㴠‽摡彪潢祤 登㴠⠠敢摮孳嵩☭瑧戻湥彤潢祤弱潰湩彴敬瑦⸩㉰ⴠ⠠敢摮孳嵩☭瑧戻湥彤潢祤弱潰湩彴敬瑦⸩⁰瀻弲楬敮☭瑧猻瑥⠨敢摮孳嵩☭瑧戻湥彤潢祤弱潰湩彴敬瑦⸩㉰⠬敢摮孳嵩☭瑧戻湥彤潢祤弱潰湩彴楲桧⥴瀮⤲㬠敲畴湲瘠㬠敽獬⁥晩⠠敢摮孳嵩☭瑧愻橤扟摯㉹㴽愠橤扟摯⥹笠⁶‽戨湥獤楛ⵝ朦㭴敢摮扟摯㉹灟楯瑮江晥⥴瀮′‭戨湥獤楛ⵝ朦㭴敢摮扟摯㉹灟楯瑮江晥⥴瀮㬠㉰江湩ⵥ朦㭴敳⡴戨湥獤楛ⵝ朦㭴敢摮扟摯㉹灟楯瑮江晥⥴瀮ⰲ戨湥獤楛ⵝ朦㭴敢摮扟摯㉹灟楯瑮牟杩瑨⸩㉰ 爻瑥牵⁮⁶紻絽敲畴湲䈠彍畮汬癟捥潴⁲紻⨯臣꺁雩낕臣膀菣ꦃ菣뢂菣ꎂ菣뎃苣ꞃ菣鶃苣뎃菣貁触骮臣憮橤戭摯ꮁ髩ꖎ臣讂臣蒁臣论껥銂胨꺅臣讂臣膂触骮臣馃菣覃菣ꒂ菣ꮁ꿥馁苣閃菣뎃苣랕苣辏臣릊黦銂볤겐臣鮁苣龁苣ꮁ铧蒁苣貂苣芀臣貂臣膀愠橤戭湥貁触骮臣閃菣뎃苣ꮁ꿥鞁臣貐꟦ꮁ迦讁苣讂苣꺁臣鞁臣麃菣꾂臣貂苣ꢁ臣咍啒銂裦馁胣⪂椯瑮䈠彍啁佔䑟䵉久䥓乏㨺潣灭瑵彥晥敦瑣彳汦湡敧江湥瑧彨牤睡⡮䵂䉟久䱄义⁅截湥汤湩ⱥ䈠彍䐳䉟䑏⁙愪橤扟摯ⱹ䈠彍䑁摟浩损牯敮⁲截湥彤楤彭潰湩⁴⨯戠湥⁤楤⁭潰湩⁴潦⁲敢摮楬敮⨠Ⱟ䈠彍䑁摟浩损牯敮⁲昪慬杮彥楤彭潰湩⁴⨯映慬杮⁥楤⁭潰湩獴映牯敢摮楬敮⨠Ⱟ䈠彍䕂䑎䥌䕎⨠摡彪敢摮笩䵂䅟彄楤彭潣湲牥⨠瀪扟摯役潰湩獴㬠湩⁴瀪扟摯役牤睡⁮䈻彍䑁摟浩损牯敮⁲⨪彰牤睡彮敢摮摟浩灟楯瑮㬠䵂䅟彄楤彭潣湲牥⨠瀪摟慲湷晟慬杮彥楤彭潰湩⁴椻瑮椠㬠⼯映物瑳眠⁥慨敶琠⁯楦摮愠䈠彍䑁扟湥汤湩⁥瑳畲瑣牵⁥潦⁲桴獩愠橤戭湥晤牯⠠⁩‽‰※⁩氦㭴渠浵潟彦敢摮楬敮⁳椻⬫ 楻⁦ℨ戠湥獤楛ⵝ朦㭴慤慴癟污摩簠⁼敢摮孳嵩☭瑧戻湥⁤㴡愠橤扟湥⁤籼戠湥獤楛ⵝ朦㭴杩潮敲 潣瑮湩敵㬠晩⠠敢摮孳嵩☭瑧愻橤扟摯ㅹ㴠‽摡彪潢祤 楻⁦戨湥獤楛ⵝ朦㭴潢祤弱牤睡⥮爠瑥牵⁮‰瀻扟摯役潰湩獴㴠☠浡㭰戨湥獤楛ⵝ朦㭴潢祤弱潰湩獴 瀻扟摯役牤睡⁮‽愦灭⠻敢摮孳嵩☭瑧戻摯ㅹ摟慲湷 瀻摟慲湷扟湥彤楤彭潰湩㵴☠浡㭰戨湥獤楛ⵝ朦㭴牤睡彮敢摮摟浩灟楯瑮⤱㬠彰牤睡彮汦湡敧摟浩灟楯瑮‽愦灭⠻敢摮孳嵩☭瑧搻慲湷晟慬杮彥楤彭潰湩ㅴ 戻敲歡㬠敽獬⁥晩⠠敢摮孳嵩☭瑧愻橤扟摯㉹㴠‽摡彪潢祤 楻⡦敢摮孳嵩☭瑧戻摯㉹摟慲湷 敲畴湲〠㬠彰潢祤灟楯瑮⁳‽愦灭⠻敢摮孳嵩☭瑧戻摯㉹灟楯瑮⥳㬠彰潢祤摟慲湷㴠☠浡㭰戨湥獤楛ⵝ朦㭴潢祤弲牤睡⥮㬠彰牤睡彮敢摮摟浩灟楯瑮㴠☠浡㭰戨湥獤楛ⵝ朦㭴牤睡彮敢摮摟浩灟楯瑮⤲㬠彰牤睡彮汦湡敧摟浩灟楯瑮㴠☠浡㭰戨湥獤楛ⵝ朦㭴牤睡彮汦湡敧摟浩灟楯瑮⤲㬠牢慥⁫紻汥敳爠瑥牵⁮‰紻晩⠠⁩朦㭴‽畮彭景扟湥汤湩獥 敲畴湲〠㬠⼯渠睯眠⁥敮摥琠⁯档捥⁫晩琠敨氠獩⁴景映慬杮⁥楤敭獮潩灮楯瑮⁳潦⁲桴獩渠睥祬映畯摮⼠ 䵂䅟彄敢摮楬敮猠牴捵畴敲挠湯慴湩⁳湡⁹汦湡敧搠浩湥楳湯瀠楯瑮⁳桴瑡愠敲愠橤捡湥⁴潴漠牵戠湥汤湩䉥彍䑁摟浩损牯敮⩲整灭灟楯瑮㬠潦⁲琨浥彰潰湩⁴‽瀪扟摯役潰湩獴㬠琠浥彰潰湩⁴※整灭灟楯瑮‽整灭灟楯瑮☭瑧渻硥⥴笠晩⠠整灭灟楯瑮☭瑧愻橤扟湥汤湩⁥㴽戠湥汤湩⥥戠敲歡㬠楽⁦丨䱕⁌㴽琠浥彰潰湩⥴爠瑥牵⁮‰⼻ 慭歲琠敨映慬杮⁥敬杮桴映牯琠敨愠橤戭湥⁤牤睡⁮楷桴爠獥数瑣琠⁯桴獩愠橤戭摯⩹彰潢祤摟慲湷㴠ㄠ㬠瀪摟慲湷扟湥彤楤彭潰湩⁴‽汦湡敧摟浩灟楯瑮㬠瀪摟慲湷晟慬杮彥楤彭潰湩⁴‽敢摮摟浩灟楯瑮爻瑥牵⁮‱紻⨯臣꺁雩낕臣膀愠橤扟湥貁胣肉껥꺁菣뎃菣ꦃ苣뎃臣ꎚ軦馁苣肉껥꺁菣ꦃ菣뢂臣뺯臣ꚁ菣ꦃ菣뢂螃苣ꆃ菣랂菣뎃菣ꒂ菣袃苣膌臣ꢁ臣咍啒銂裦馁胣⪂椯瑮䈠彍啁佔䑟䵉久䥓乏㨺档捥彫睴彯敢摮楬敮彳摡慪散瑮瑟彯慳敭晟慬杮⡥䵂䉟久䱄义⁅截湥汤湩ⱥ䈠彍䐳䉟䑏⁙昪慬杮ⱥ䈠彍䕂䑎䥌䕎⨠摡彪敢摮笩䵂䅟彄楤彭潣湲牥⨠瀪扟摯役潰湩獴㬠湩⁴⁩⼻ 楦獲⁴敷栠癡⁥潴映湩⁤⁡䵂䅟彄敢摮楬敮瑳畲瑣牵⁥潦⁲桴獩愠橤戭湥晤牯⠠⁩‽‰※⁩氦㭴渠浵潟彦敢摮楬敮⁳※⭩⤫笠晩ℨ戠湥獤楛ⵝ朦㭴慤慴癟污摩簠⁼敢摮孳嵩☭瑧戻湥⁤㴡愠橤扟湥⥤挠湯楴畮⁥椻⁦戨湥獤楛ⵝ朦㭴摡彪潢祤‱㴽映慬杮⥥笠彰潢祤灟楯瑮⁳‽愦灭⠻敢摮孳嵩☭瑧戻摯ㅹ灟楯瑮⥳戻敲歡㬠敽獬⁥晩⠠敢摮孳嵩☭瑧愻橤扟摯㉹㴠‽汦湡敧 灻扟摯役潰湩獴㴠☠浡㭰戨湥獤楛ⵝ朦㭴潢祤弲潰湩獴 戻敲歡㬠敽獬⁥敲畴湲〠㬠楽⁦椨☠瑧㴻渠浵潟彦敢摮楬敮⥳敲畴湲〠㬠⼯渠睯眠⁥敮摥琠⁯档捥⁫晩琠敨氠獩⁴景映慬杮⁥楤敭獮潩⁮潰湩獴潦⁲桴獩渠睥祬映畯摮⼠ 䵂䅟彄敢摮楬敮猠牴捵畴敲挠湯慴湩⁳⁡汦湡敧搠浩湥楳湯瀠楯瑮⁳桴瑡椠⁳摡慪散瑮琠⁯畯⁲敢摮楬敮䵂䅟彄楤彭潣湲牥⨠整灭灟楯瑮㬠潦⁲琨浥彰潰湩⁴‽瀪扟摯役潰湩獴㬠琠浥彰潰湩⁴※整灭灟楯瑮㴠琠浥彰潰湩⵴朦㭴敮瑸 楻⁦琨浥彰潰湩⵴朦㭴摡彪敢摮楬敮㴠‽敢摮楬敮 敲畴湲ㄠ㬠牽瑥牵⁮㬰⽽낖臣蒁菩蚈苣궨껥馁苣芀臣貂臣貐꟦ꮁ菣ꚃ菣꾂菣릂菣ꒂ菣뾂苣뒛雦鞁胣뺹臣讁臣隻臣醃菣ꆃ菣뾂苣궨껥馁苣芀⼪潶摩䈠彍啁佔䑟䵉久䥓乏㨺敳彴慰瑲䈨彍䅐呒⨠敮彷慰瑲笩䵂䉟久䱄义⁅截湥汤獩⁴椻瑮椠㬠敤敬整损湯整瑮⡳ 椻⁦丨䱕㵌‽潤⥣爠瑥牵⁮瀻牡⁴‽敮彷慰瑲㬠晩⠠啎䱌㴠‽慰瑲 敲畴湲㬠慨晬浟瑥污瑟楨正敮獳㴠⠠慰瑲☭瑧朻瑥浟瑥污瑟楨正敮獳⤨⼩⸲‰⼻ 污潬慣整琠敨戠湥汤獩楴⡦‰㴽⠠畮彭景扟湥汤湩獥㴠瀠牡⵴朦㭴敧彴畮扭牥潟彦敢摮楬敮⡳⤩ 敲畴湲㬠晩⠠啎䱌㴠‽戨湥獤㴠渠睥䈠彍䑁扟湥汤湩⩥湛浵潟彦敢摮楬敮嵳⤩朠瑯⁯慦汩牵⁥戻湥汤獩⁴‽慰瑲☭瑧朻瑥扟湥汤湩彥楬瑳⤨㬠潦⁲椨㴠〠㬠椠☠瑬※畮彭景扟湥汤湩獥㬠⭩⤫笠晩⠠敢摮楬瑳 扻湥獤楛⁝‽敮⁷䵂䅟彄敢摮楬敮琨楨ⱳ敢摮楬瑳 戻湥汤獩⁴‽䈨彍䕂䑎䥌䕎⨠ 敢摮楬瑳☭瑧渻硥⡴ 紻汥敳戠湥獤楛⁝‽啎䱌㬠⽽ 潮整‬楤瑲⁹獩吠啒牅瑥牵⁮昻楡畬敲㨠敤敬整损湯整瑮⡳ 紻戼㹲颻賩ꪼ戼㹲蒖鷦ꢃ裥ꮁ꿥馁苣ꢂ菣蚃苣蚃苣鎃苣鎃菣蚃苣ꊖ闦銂郥肂菣뎃菣ꊃ菣ꮃ菣ꚃ菣龮雦꺁뻤㲋牢ਾ椣据畬敤∠瑳慤硦栮⼢ 湩汣摵⁥污⁬䵂偁⁉楦敬⍳湩汣摵⁥䄢䱌䵂偁⹉塈≘⼯删彗剄坁氠扩慲祲椠据畬敤映汩⹥椣据畬敤∠坒䑟䅒⹗塈≘椣据畬敤∠敂摮䅃䑄捯栮⌢湩汣摵⁥䈢湥䍤䑁楖睥慐瑲栮⼢ 敒摮牥慗敲椠据畬敤映汩獥※潦湵⁤湩尠睲楷屮湩汣摵⍥湩汣摵⁥爢汷扩栮⼢ 灏湥䱇椠据畬敤映汩獥⌮湩汣摵⁥朢屬汧栮⌢湩汣摵⁥朢屬汧⹵≨⼯䜠彌䥌呓氠扩慲祲椠据畬敤映汩⹥椣据畬敤∠䱇䱟卉⹔塈≘椣据畬敤☠瑬猻摴楬⹢♨瑧※†⨯†菣벃菣覃뫥馨臣誁臣讂菣ꒂ菣袃苣ꢡ臣䊙彍佐义貁룤袁苣貂苣ꢁ胣몺臣鶁苣銂菣ꚃ菣Ꚃ苣뎃菣Ꞻ꣦誸臣蒰뷥馁苣鎁臣貁蟥ꖝ苣芀†⥁䤠瑦敨搠獩汰祡椠⁳桳睯湩⁧桴⁥体䥌⁄敶獲潩⁮景琠敨瀠牡ⱴ琠楨⁳畦据楴湯瀠獡敳⁳慢正愠瀠楯瑮牥琠⁯桴⁥††攠杤⁥汣獯獥⁴潴琠敨挠浡牥⁡桴瑡氠敩⁳湵敤瑲慨⁴牰橯捥整⁤潰湩⹴吠敨砠灟獯‬役潰ⱳ愠摮稠摟灥桴瀠楯瑮牥⁳慣牲⁹桴癥敩⁷楷摮睯挠潯摲湩瑡獥⠠楷桴琠灯氠晥⁴潣湲牥愠⁳〨〬 湡⁤桴⁥⵺畢晦牥慶畬⹥䤠⁦桴⁥牰橯捥整⁤潰湩⁴獩渠瑯椠⁮桴⁥楶睥湩⁧潶畬敭‬桴⁥敲畴湲瘠污敵椠⁳㬰琠敨⁮景挠畯獲⁥桴⁥摥敧†潰湩整⁲獩洠慥楮杮敬獳‬湡⁤獩猠瑥琠⁯啎䱌‮晉琠敨瀠潲敪瑣摥瀠楯瑮䤠⁓楷桴湩琠敨瘠敩楷杮瘠汯浵ⱥ†琠敨⁮桴牥瑥牵⁮慶畬⁥獩ㄠ‬湡⁤桴⁥摥敧瀠楯瑮牥瀠楯瑮⁳潴琠敨攠杤⁥桴瑡氠敩⁳湵敤⁲桴⁥牰橯捥整⁤潰湩⹴†晉琠敨瀠楯瑮牥椠⁳啎䱌‬潮攠杤⁥楬獥甠摮牥琠敨牰橯捥整⁤潰湩⹴†⥂䤠⁦桴⁥楤灳慬⁹獩猠潨楷杮琠敨圠剉䙅䅒䕍瘠牥楳湯漠瑦敨瀠牡ⱴ漠汮⁹桴⁥敲畴湲瘠污敵›‱晩眠瑩楨⁮††楶睥瘠汯浵ⱥ〠漠桴牥楷敳ⴠ猠潨汵⁤敢攠慸業敮⹤䤠⁦敲畴湲瘠污敵椠⁳ⰱ砠灟獯‬役潰⁳湡⁤彺敤瑰⁨慶畬獥栠癡⁥敭湡湩⹧吠敨攠杤⁥潰湩整⁲獩愠睬祡⁳啎䱌⨮椯瑮䌠敂摮䅃噄敩偷牡㩴洺灡灟楯瑮瑟彯汣獯獥彴摥敧䈨彍佐义⁔潣獮♴浡㭰琠牨敥摟灟楯瑮‬湩⁴砪灟獯椬瑮⨠役潰ⱳ††††††††††††††††††††††潤扵敬⨠彺敤瑰ⱨ䵂䕟䝄⁅⨪汣獯獥彴摥敧笩†湩⁴ⱸ礠‬楶楳汢⁥‽㬱†潤扵敬稠※†瘠獩扩敬‽慭彰搳瑟彯捳敲湥琨牨敥摟灟楯瑮‬愦灭砻‬愦灭礻‬愦灭稻㬩†晩 ‡楶楳汢⁥ ⁻†††⼠ 潐湩⁴獩漠瑵楳敤瘠敩楷杮瘠汯浵⹥††晩挨潬敳瑳敟杤⥥⨠汣獯獥彴摥敧㴠丠䱕㭌晩砨灟獯 砪灟獯㴠砠椻⡦役潰⥳⨠役潰⁳‽㭹晩稨摟灥桴 稪摟灥桴㴠稠爻瑥牵⁮㬰†⁽⼠ 潎⁷潰湩⁴獩椠獮摩⁥楶睥瘠汯浵⹥†晩砨灟獯 砪灟獯㴠砠※椠⡦役潰⥳⨠役潰⁳‽㭹†晩稨摟灥桴 稪摟灥桴㴠稠※椠⡦‡業獟潨彷潳楬⥤笠††††††††⼠ 楗敲牦浡⁥敢湩⁧牤睡㭮樠獵⁴敲畴湲琠慨⁴潰湩⁴獩††椠⡦汣獯獥彴摥敧 挪潬敳瑳敟杤⁥‽啎䱌※⼯眠瑩楨⁮楶睥瘠汯爮瑥牵⁮㬱†⁽⼠ 潎⁷潳楬⁤獩戠楥杮猠潨湷‮椠⡦‡汣獯獥彴摥敧 敲畴湲ㄠ※⼠倯楯瑮椠⁳楷桴湩瘠敩⁷潶畬敭‮楐正琠慨⁴潰湩⹴†楰正灟楯瑮牟⡷ⱸ礠‬汣獯獥彴摥敧㬩†敲畴湲ㄠ紻⼯吠楨⁳畦据楴湯爠瑥牵獮琠敨瘠敩⁷楷摮睯挠潯摲湩瑡獥漠⁦⁡潰湩ⱴ眠瑩⁨潴⁰敬瑦挠牯敮⁲獡⠠ⰰ⤰‬湡⁤桴⁥⼯稠戭晵敦⁲敤瑰ⱨ楧敶⁮桴⁥桴敲ⵥ楤敭獮潩慮⁬潷汲⁤潣牯楤慮整⁳景琠敨瀠楯瑮‮瑉搠敯⁳潳祢挠污楬杮攠瑩敨⁲⼯洠灡㍟彤潴獟牣敥彮潳楬⁤牯洠灡㍟彤潴獟牣敥彮楷敲‬敤数摮湩⁧湯眠敨桴牥眠物晥慲敭漠⁲潳楬⁤獩戠楥杮猠潨湷‮⼯传⁮敲畴湲‬晩⩦彸潰ⱳ⨠役潰⁳牡⁥潢桴稠牥Ɐ琠敨瀠楯瑮眠獡渠瑯洠灡数⁤湯潴琠敨猠牣敥⁮瑡愠汬椮瑮䌠敂摮䅃噄敩偷牡㩴洺灡㍟彤潴獟牣敥⡮䵂偟䥏呎琠牨敥摟灟楯瑮‬湩⩴彸潰ⱳ椠瑮⨠役潰ⱳ搠畯汢⁥稪摟灥桴笩†湩⁴楶楳汢㭥†椠⡦業獟潨彷潳楬⥤楶楳汢⁥‽慭彰搳瑟彯捳敲湥獟汯摩琨牨敥摟灟楯瑮‬彸潰ⱳ礠灟獯‬彺敤瑰⥨※攠獬⁥楶楳汢⁥‽慭彰搳瑟彯捳敲湥睟物⡥桴敲彥彤潰湩ⱴ砠灟獯‬役潰ⱳ稠摟灥桴㬩†敲畴湲瘠獩扩敬紻⼯吠楨⁳畦据楴湯爠瑥牵獮琠敨瘠敩⁷楷摮睯挠潯摲湩瑡獥漠⁦⁡潰湩ⱴ眠瑩⁨潴⁰敬瑦挠牯敮⁲獡⠠ⰰ⤰‬湡⁤桴⽥ ⵺畢晦牥搠灥桴本癩湥琠敨琠牨敥搭浩湥楳湯污眠牯摬挠潯摲湩瑡獥漠⁦桴⁥潰湩ⱴ甠楳杮传数䝮⁌瑵汩瑩敩⁳⼯⠠敩‮桷湥眠物晥慲敭椠⁳湯⸩䤠⁦敲畴湲瘠污敵椠⁳ⰰ瀠楯瑮椠⁳潮⁴慭灰摥漠瑮⁯捳敲湥‬敩‮潮⁴楶楳汢⹥湩⁴䉃湥䍤䑁楖睥慐瑲㨺慭彰搳瑟彯捳敲湥睟物⡥䵂偟䥏呎琠牨敥摟灟楯瑮‬湩⁴砪灟獯‬湩⁴礪灟獯‬潤扵敬⨠彺敤瑰⥨⁻†椠瑮瘠敩灷牯孴崴‬楶楳汢⁥‽㬱†潤扵敬眠摩桴‬敨杩瑨‬敤瑰㭨潤扵敬洠摯汥浟瑡ㅛ崶‬牰橯浟瑡ㅛ崶‬牡慲孹㘱㭝†⼯䜠瑥琠敨挠牵敲瑮瘠敩灷牯⁴潣牯獤‮朠䝬瑥湉整敧癲䜨彌䥖坅佐呒‬楶睥潰瑲㬩†⼯丠睯戠極摬愠洠摯汥楶睥洠瑡楲⁸畯⁴景琠敨挠牵敲瑮猠瑥漠⁦牴湡晳牯慭楴湯⹳†汧慍牴硩潍敤䜨彌位䕄噌䕉⥗※朠偬獵䵨瑡楲⡸㬩††汧牔湡汳瑡摥洨彤彸牴湡ⱳ洠彤役牴湡ⱳ〠〮㬩潣癮牥彴睲浟瑡楲彸潴束彬牡慲⡹摭牟瑯浟瑡楲ⱸ愠牲祡㬩汧畍瑬慍牴硩⡤牡慲⥹朻呬慲獮慬整⡤‭彭慰瑲损湥牴楯⹤⡘Ⱙⴠ洠灟牡彴散瑮潲摩央⤨‬‭彭慰瑲损湥牴楯⹤⡚⤩※†朠䝬瑥潄扵敬⡶䱇䵟䑏䱅䥖坅䵟呁䥒ⱘ洠摯汥浟瑡㬩††汧敇䑴畯汢癥䜨彌剐䩏䍅䥔乏䵟呁䥒ⱘ瀠潲彪慭⥴※朠偬灯慍牴硩⤨※朠畬牐橯捥⡴桴敲彥彤潰湩⹴⡘Ⱙ琠牨敥摟灟楯瑮央⤨‬桴敲彥彤潰湩⹴⡚Ⱙ洠摯汥浟瑡‬牰橯浟瑡‬†††††††††††楶睥潰瑲‬愦灭眻摩桴‬愦灭栻楥桧ⱴ☠浡㭰敤瑰⥨※椠⡦⠠椨瑮眩摩桴☠瑧※彭汯彤敲瑣爮杩瑨 籼⠠椨瑮眩摩桴☠瑬※⤰⤠瘠獩扩敬㴠〠※椠⡦⠠椨瑮栩楥桧⁴朦㭴洠潟摬牟捥⹴潢瑴浯 籼⠠椨瑮栩楥桧⁴氦㭴〠  楶楳汢⁥‽㬰†晩砨灟獯 砪灟獯㴠⠠湩⥴眠摩桴※椠⡦役潰⥳⨠役潰⁳‽洨潟摬牟捥⹴潢瑴浯ⴠ⠠湩⥴栠楥桧⥴※椠⡦彺敤瑰⥨⨠彺敤瑰⁨‽敤瑰㭨††敲畴湲瘠獩扩敬紻††⼯吠楨⁳畦据楴湯爠瑥牵獮琠敨瘠敩⁷楷摮睯挠潯摲湩瑡獥漠⁦⁡潰湩ⱴ眠瑩⁨潴⁰敬瑦挠牯敮⁲獡⠠ⰰ⤰‬湡⁤桴⽥ ⵺畢晦牥搠灥桴‬楧敶⁮桴⁥桴敲ⵥ楤敭獮潩慮⁬潷汲⁤潣牯楤慮整⁳景琠敨瀠楯瑮‬獵湩⁧敒摮牥慗敲甠楴楬楴獥⼠ 椨⹥眠敨⁮潳楬⁤獩漠⥮‮晉爠瑥牵⁮慶畬⁥獩〠‬潰湩⁴獩渠瑯洠灡数⁤湯潴琠敨猠牣敥Ɱ椠⹥潮⁴楶楳汢⹥⼯丠瑯㩥䄠⁴牰獥湥ⱴ猠浡⁥獡洠灡㍟彤潴獟牣敥彮楷敲椮瑮䌠敂摮䅃噄敩偷牡㩴洺灡㍟彤潴獟牣敥彮潳楬⡤䵂偟䥏呎琠牨敥摟灟楯瑮‬湩⁴砪灟獯椬瑮⨠役潰ⱳ搠畯汢⁥稪摟灥桴笩††湩⁴楶睥潰瑲㑛ⱝ瘠獩扩敬㴠ㄠ※搠畯汢睥摩桴‬敨杩瑨‬敤瑰㭨†潤扵敬洠摯汥浟瑡ㅛ崶‬牰橯浟瑡ㅛ崶‬牡慲孹㘱㭝†⼯䜠瑥琠敨挠牵敲瑮瘠敩灷牯⁴潣牯獤‮朠䝬瑥湉整敧癲䜨彌䥖坅佐呒‬楶睥潰瑲㬩†⼯丠睯戠極摬愠洠摯汥楶睥洠瑡楲⁸畯⁴景琠敨挠牵敲瑮猠瑥漠⁦牴湡晳牯慭楴湯⹳†汧慍牴硩潍敤䜨彌位䕄噌䕉⥗※朠偬獵䵨瑡楲⡸㬩††汧牔湡汳瑡摥洨彤彸牴湡ⱳ洠彤役牴湡ⱳ〠〮㬩潣癮牥彴睲浟瑡楲彸潴束彬牡慲⡹摭牟瑯浟瑡楲ⱸ愠牲祡㬩汧畍瑬慍牴硩⡤牡慲⥹朻呬慲獮慬整⡤‭彭慰瑲损湥牴楯⹤⡘Ⱙⴠ洠灟牡彴散瑮潲摩央⤨‬‭彭慰瑲损湥牴楯⹤⡚⤩※†朠䝬瑥潄扵敬⡶䱇䵟䑏䱅䥖坅䵟呁䥒ⱘ洠摯汥浟瑡㬩††汧敇䑴畯汢癥䜨彌剐䩏䍅䥔乏䵟呁䥒ⱘ瀠潲彪慭⥴※朠偬灯慍牴硩⤨※朠畬牐橯捥⡴桴敲彥彤潰湩⹴⡘Ⱙ琠牨敥摟灟楯瑮央⤨‬桴敲彥彤潰湩⹴⡚Ⱙ洠摯汥浟瑡‬牰橯浟瑡‬†††††††††††楶睥潰瑲‬愦灭眻摩桴‬愦灭栻楥桧ⱴ☠浡㭰敤瑰⥨※椠⡦⠠椨瑮眩摩桴☠瑧※彭汯彤敲瑣爮杩瑨 籼⠠椨瑮眩摩桴☠瑬※⤰⤠瘠獩扩敬㴠〠※椠⡦⠠椨瑮栩楥桧⁴朦㭴洠潟摬牟捥⹴潢瑴浯 籼⠠椨瑮栩楥桧⁴氦㭴〠 瘩獩扩敬㴠〠※椠⡦彸潰⥳⨠彸潰⁳‽椨瑮 楷瑤㭨†晩礨灟獯 礪灟獯㴠⠠彭汯彤敲瑣戮瑯潴⁭‭椨瑮 敨杩瑨㬩†晩稨摟灥桴 稪摟灥桴㴠搠灥桴※†爠瑥牵癮獩扩敬※素⼯吠楨⁳畦据楴湯瀠捩獫琠敨瀠楯瑮椠摮捩瑡摥戠⁹慭彰搳瑟彯捳敲湥‬獵湩⁧敒摮牥慗敲瀠捩楫杮‬潳琠楨⁳獩⼯挠污敬⁤湯祬眠敨⁮潳楬⁤獩戠楥杮猠潨湷‮潎整琠慨⁴桴⁥楰正瀠獯瑩潩⁮獩眠瑩⁨敲灳捥⁴潴琠敨琠灯氠晥⽴ 潣湲牥漠⁦桴⁥楶睥眠湩潤⁷敢湩⁧〨〬⸩䤠⁦桴⁥楰正爠獥汵獴椠⁮湡攠杤ⱥ愠潰湩整⁲潴琠敨攠杤⁥獩⼯瀠獡敳⁤慢正椠⁮楰正摥敟杤㭥攠獬ⱥ瀠捩敫彤摥敧椠⁳敳⁴潴渠汵⹬吠楨⁳潤獥渠瑯洠摯晩⁹桴⁥敳敬瑣潩⽮ 敳⁴湩愠祮眠祡瘮楯䍤敂摮䅃噄敩偷牡㩴瀺捩彫潰湩彴睲椨瑮砠灟獯‬湩⁴役潰ⱳ䈠彍䑅䕇⨠瀪捩敫彤摥敧 ⁻椠⡦楰正摥敟杤⁥㴽丠䱕⥌爠瑥牵㭮†晩 砨灟獯☠瑧※彭汯彤敲瑣爮杩瑨簩⁼礨灟獯☠瑧※彭汯彤敲瑣戮瑯潴⥭ ⁻⼠ 慍敫猠牵⁥潰湩⁴楧敶⁮獩眠瑩楨⩮楰正摥敟杤⁥‽啎䱌⼻ 楶睥潰瑲爮瑥牵㭮†⁽†睒汃浵⁰瀪捩敫彤汣浵⁰‽啎䱌※删䍷畬灭⨠慰敲瑮损畬灭㴠丠䱕㭌†潬杮瀠牡湥彴慴Ⱨ挠畬灭瑟条‬敫⁹‽㬰†䵂䕟䝄⁅攪杤⁥‽啎䱌※椠⡦‡睒楐正捓湥⡥彭捳湥ⱥ砠灟獯‬役潰ⱳ洠损浡牥ⱡ愦灭活灟捩⥫ ⁻⼯倠捩楫杮挠浯慭摮眠獡渠瑯猠捵散獳畦⹬††瀪捩敫彤摥敧㴠丠䱕㭌敲畴湲※素†晩洨灟捩⹫祴数㴠‽睲䅎䥐䭃䉏䕊呃 ⁻†††††††††⼯丠⁯汣浵⁰慷⁳楰正摥⨮楰正摥敟杤⁥‽啎䱌爻瑥牵㭮†⁽攠獬⁥晩洨灟捩⹫祴数㴠‽睲䥐䭃䱃䵕⥐笠†††††††††⼠ 潓敭挠畬灭眠獡瀠捩敫㭤瀠潲散獳椠⹴††楰正摥损畬灭㴠洠灟捩⹫扯敪瑣挮畬灭挮畬灭瀻牡湥彴汣浵⁰‽睒敇䍴畬灭慐敲瑮瀨捩敫彤汣浵⥰瀻牡湥彴慴⁧‽睒敇䍴畬灭慔⡧慰敲瑮损畬灭㬩汣浵彰慴⁧刽䝷瑥汃浵呰条瀨捩敫彤汣浵⥰椻⡦慰敲瑮瑟条㴠‽⤱笠†瀪捩敫彤摥敧㴠丠䱕㭌†敲畴湲※†††††††††††††††††††⼯䄠琠楲楶污戠湥汤湩⁥牯潦浲湩⁧慷⁳楰正摥‮†素††⼯丠睯猠浯⁥敲污攠杤⁥慷⁳楰正摥欮祥㴠⠠慰敲瑮瑟条ㄥ〰〰⨩〱〰〰⬠挠畬灭瑟条※晩挨畬灭瑟条 ⼯匠晡瑥⁹档捥㭫眠⁥硥数瑣挠畬灭瑟条琠⁯敢渠湯稭牥⹯†††瀪捩敫彤摥敧㴠洠灡江獩彴慮敭瑟彯浢敟杤⡥慰敲瑮瑟条‬汣浵彰慴⥧※††素⁽⼠ 桔獩映湵瑣潩⁮敲畴湲⁳桴⁥慲楴⁯景琠敨瘠敩⁷潶畬敭搠浩湥楳湯⠠扯敪瑣猠慰散搠浩湥楳湯⥳琠⽯ 桴⁥楶睥潰瑲楤敭獮潩⁮搨癥捩⁥灳捡⁥楤敭獮潩獮⸩潤扵敬䌠敂摮䅃噄敩偷牡㩴机瑥潟橢捥彴潴摟癥捩彥慲楴⡯潶摩笩†潤扵敬爠瑡潩※椠⡦彭汯彤敲瑣爮杩瑨 ††慲楴⁯㈽〮洪彤畣牲湥彴楶睥癟汯せ⽝搨畯汢⥥洨潟摬牟捥⹴楲桧⥴※攠獬⁥慲楴⁯‽⸰㬰†敲畴湲爠瑡潩紻⨯†楇敶⁮⁡䵂偟䥏呎‬桷捩⁨敲牰獥湥獴愠瀠楯瑮椠⁮潷汲捤潯摲湩瑡獥‬湯⁥慣⁮牰橯捥⁴瑩漠瑮⁯楶睥眠湩潤⁷潣牯楤慮整⹳吠楨⁳畦据楴湯映物瑳挠敨正⁳晩琠敨瀠潲敪瑣摥瀠楯瑮椠⁳楷桴湩琠敨瘠敩楷杮瘠汯浵⹥䤠⁦瑩䤠⁓楷桴湩瘠敩楷杮瘠汯浵ⱥ琠敨瀠楯瑮牥∠楶楳汢≥挠牡楲獥瘠污敵ㄠ※汥敳‬⸰䤠⁦桴⁥潰湩⁴獩渠瑯瘠獩扩敬‬潮漠桴牥瀠牡浡瑥牥⁳慨敶愠祮洠慥楮杮※桴⁥敲畴湲瘠污敵椠⁳⸰†潎⁷畳灰獯⁥桴⁥潰湩⁴獩瘠獩扩敬‮䄠 晉琠敨搠獩汰祡椠⁳桳睯湩⁧桴⁥体䥌⁄敶獲潩⁮景琠敨瀠牡ⱴ琠楨⁳畦据楴湯挠敨正⁳晩乁⁙景琠敨琠牨敥摟扟摯敩⁳湩琠敨愠牲祡∠桴敲彥扤慟牲祡•楬獥∠灡牰硯浩瑡汥⁹湵敤≲琠敨瀠潲敪瑣摥瀠楯瑮‮晉琠敨愠獮敷⁲獩礠獥‬敲畴湲瘠污敵椠⁳㬱攠獬ⱥ爠瑥牵⁮慶畬⁥獩稠牥⹯吠敨砠灟獯‬役潰ⱳ愠摮稠摟灥桴瀠楯瑮牥⁳慣牲⁹桴⁥楶睥眠湩潤⁷潣牯楤慮整⁳眨瑩⁨潴⁰敬瑦挠牯敮⁲獡⠠ⰰ⤰ 湡⁤桴⁥⵺畢晦牥瘠污敵‮桔⁥牡慲⁹琢敨彥扤慟牲祡•畭瑳戠⁥整浲湩瑡摥戠⁹⁡啎䱌瀠楯瑮牥琠⁯湩楤慣整攠摮漠⁦牡慲⹹†⥂䤠⁦桴⁥楤灳慬⁹獩猠潨楷杮琠敨圠剉䙅䅒䕍瘠牥楳湯漠⁦桴⁥慰瑲琠敨爠瑥牵⁮慶畬⁥獩愠睬祡⁳敺潲‮䤠⁦桴⁥潰湩⁴獩眠瑩楨⁮楶睥瘠汯浵ⱥ⨠楶楳汢⁥獩猠瑥琠⁯㬱攠獬ⱥ〠‮晉⨠楶楳汢⁥獩ㄠ‬彸潰ⱳ礠灟獯愠摮稠摟灥桴瘠污敵⁳慨敶琠敨洠慥楮杮洠湥楴湯摥愠潢敶‮⼪湩⁴䉃湥䍤䑁楖睥慐瑲㨺獩㍟彤潢祤湟慥彲潰湩⡴䵂偟䥏呎挠湯瑳愦灭※桴敲彥彤潰湩ⱴ䈠彍䐳䉟䑏⁙⨪桴敲彥扤慟牲祡‬†††††††††††††††††††椠瑮⨠楶楳汢ⱥ椠瑮⨠彸潰ⱳ椠瑮⨠役潰ⱳ搠畯汢⁥稪摟灥桴笩†湩⁴ⱸ礠‬獩癟獩扩敬‽㬱†潤扵敬稠※椠瑮映畯摮㴠〠※椠彳楶楳汢⁥‽慭彰搳瑟彯捳敲湥琨牨敥摟灟楯瑮‬愦灭砻‬愦灭礻‬愦灭稻㬩†晩 ‡獩癟獩扩敬 ⁻††††††⼯倠楯瑮椠⁳畯獴摩癥敩楷杮瘠汯浵⹥晩砨灟獯 砪灟獯㴠砠椻⡦役潰⥳⨠役潰⁳‽㭹晩稨摟灥桴 稪摟灥桴㴠稠椻⡦楶楳汢⥥⨠楶楳汢⁥‽㬰敲畴湲〠※素†⼯丠睯瀠楯瑮椠⁳湩楳敤楶睥瘠汯浵⹥†晩砨灟獯 砪灟獯㴠砠※椠⡦役潰⥳⨠役潰⁳‽㭹†晩稨摟灥桴⨩彺敤瑰⁨‽㭺†晩瘨獩扩敬 瘪獩扩敬㴠ㄠ※椠⡦‡業獟潨彷潳楬⥤笠††††⼠ 楗敲牦浡⁥敢湩⁧牤睡㭮樠獵⁴敲畴湲琠慨⁴潰湩⁴獩爠瑥牵⁮㬱⼠ 楷桴湩瘠敩⁷潶畬敭‮素†⼯丠睯猠汯摩椠⁳敢湩⁧桳睯⹮†晩ℨ琠牨敥摟形牡慲⥹爠瑥牵⁮㬰†⼯倠楯瑮椠⁳楷桴湩瘠敩⁷潶畬敭‮楐正瀠硩汥⁳湩愠琠楲湡汧⁥牡畯摮琠慨⁴潰湩⹴†潦湵⁤‽楰正灟楯瑮晟牯㍟扤牟⡷砨ⴠ㈠Ⱙ⠠⁹‭⤲‬桴敲彥扤慟牲祡㬩†晩昨畯摮 敲畴湲ㄠ※映畯摮㴠瀠捩彫潰湩彴潦彲搳形睲⠨⁸㈭Ⱙ⠠⁹‫⤲‬桴敲彥扤慟牲祡㬩†晩昨畯摮 敲畴湲ㄠ※映畯摮㴠瀠捩彫潰湩彴潦彲搳形睲⠨⁸‫⤲‬礨⬠㈠Ⱙ琠牨敥摟形牡慲⥹※椠⡦潦湵⥤爠瑥牵⁮㬱†潦湵㵤瀠捩彫潰湩彴潦彲搳形睲⠨⁸‫⤲‬礨ⴠ㈠Ⱙ琠牨敥摟形牡慲⥹※椠⡦潦湵⥤爠瑥牵⁮㬱†敲畴湲〠紻⼯吠楨⁳畦据楴湯瀠捩獫琠敨瀠楯瑮椠摮捩瑡摥‬獵湩⁧敒摮牥慗敲瀠捩楫杮‬潳琠楨⁳獩挠污敬⁤湯祬眠敨⁮潳楬⁤獩⼠ 敢湩⁧桳睯⹮丠瑯⁥桴瑡琠敨瀠捩⁫潰楳楴湯椠⁳楷桴爠獥数瑣琠⁯桴⁥潴⁰敬瑦挠牯敮⁲景琠敨楶睥眠湩潤⁷敢湩⁧⼯⠠ⰰ⤰‮晉琠敨瀠捩⁫敲畳瑬⁳湩愠琠牨敥摟扟摯馀⁳汣浵Ɒ愠摮琠敨瀠捩敫⁤汣浵⁰潣牲獥潰摮⁳潴䄠奎†景琠敨⼯琠牨敥摟扟摯敩⁳湩桴⁥牡慲⁹慰獳摥‬敲畴湲瘠污敵椠⁳㬱椠⁦潮洠瑡档漠⁲潮琠牨敥摟扟摯ⱹ爠瑥牵⁮獩〠⼮ 桔獩搠敯⁳潮⁴潭楤祦琠敨猠汥捥楴湯猠瑥椠⁮湡⁹慷⹹湩⁴䉃湥䍤䑁楖睥慐瑲㨺楰正灟楯瑮晟牯㍟扤牟⡷湩⁴彸潰ⱳ椠瑮礠灟獯‬䵂㍟彄佂奄⨠琪牨敥摟形牡慲⥹笠†晩琨牨敥摟形牡慲⁹㴽丠䱕⥌爠瑥牵⁮㬰†晩 砨灟獯☠瑧※彭汯彤敲瑣爮杩瑨 籼⠠役潰⁳朦㭴洠潟摬牟捥⹴潢瑴浯⤩笠†⼯䴠歡⁥畳敲瀠楯瑮朠癩湥椠⁳楷桴湩敲畴湲〠※†††††††††††††⼠ 楶睥潰瑲‮素†删䍷畬灭⨠楰正摥损畬灭㴠丠䱕㭌†睒汃浵⁰瀪牡湥彴汣浵⁰‽啎䱌※氠湯⁧慰敲瑮瑟条挬畬灭瑟条‬敲畱物摥楟㭤湩⁴潦湵⁤‽㬰†椠⡦‡睒楐正捓湥⡥彭捳湥ⱥ砠灟獯‬役潰ⱳ洠损浡牥ⱡ☠浡㭰彭楰正⤩笠⼠ 楐正湩⁧潣浭湡⁤慷⁳潮⁴畳捣獥晳汵爮瑥牵⁮㬰†⁽椠⡦彭楰正琮灹⁥㴽爠乷偁䍉佋䩂䍅⥔笠†††††††††⼠ 潎挠畬灭眠獡瀠捩敫⹤敲畴湲〠※素†汥敳椠⡦彭楰正琮灹⁥㴽爠偷䍉䍋啌偍 ⁻††††††⼠ 潓敭挠畬灭眠獡瀠捩敫㭤瀠潲散獳椠⹴††楰正摥损畬灭㴠洠灟捩⹫扯敪瑣挮畬灭挮畬灭瀻牡湥彴汣浵⁰‽睒敇䍴畬灭慐敲瑮瀨捩敫彤汣浵⥰瀻牡湥彴慴⁧‽睒敇䍴畬灭慔⡧慰敲瑮损畬灭㬩汣浵彰慴⁧‽睒敇䍴畬灭慔⡧楰正摥损畬灭㬩晩瀨牡湥彴慴⁧㴽ㄠ ⁻††††††††⼯䈠摯⁹景映捡⽥敢摮楬敮是牯業杮慷⁳楰正摥昮牯椨瑮椠〽※桴敲彥扤慟牲祡楛㭝⬠椫 ⁻⼯䌠敨正椠⁦瑩洠瑡档獥愠祮漠⁦桴⁥湯獥椠⁮牡慲⹹晩琨牨敥摟形牡慲孹嵩㴠‽啎䱌 牢慥㭫敲畱物摥楟⁤‽桴敲彥扤慟牲祡楛ⵝ朦㭴敧彴摩⡸㬩晩挨畬灭瑟条ㄥ〰〰㴠‽敲畱物摥楟⥤晻畯摮㴠ㄠ戻敲歡紻牽瑥牵⁮潦湵㭤⁽†⼠ 潎⁷潳敭攠杤馀⁳汣浵⁰慷⁳楰正摥‮桃捥⁫晩椠⁴慭捴敨⁳湡⁹景琠敨漠敮⁳湩愠牲祡昮牯椨瑮椠〽※桴敲彥扤慟牲祡楛㭝⬠椫 楻⡦桴敲彥扤慟牲祡楛⁝㴽丠䱕⥌戠敲歡爻煥極敲彤摩㴠琠牨敥摟形牡慲孹嵩☭瑧朻瑥楟硤⤨椻⡦慰敲瑮瑟条ㄥ〰〰㴠‽敲畱物摥楟⥤笠潦湵⁤‽㬱牢慥㭫⁽†素†⁽†爠瑥牵⁮潦湵㭤⁽⼠ 桔獩愠汬睯⁳桴⁥獵牥琠⁯湩敳瑲椠整獭湩潴琠敨猠汥捥楴湯猠瑥‮氢獩≴椠⁳湡愠牲祡漠⁦潰湩整獲⼯琠⁯桴敲ⵥⵤ潢楤獥‬整浲湩瑡摥戠⁹啎䱌琠⁯湩楤慣整攠摮漠⁦牡慲⹹䤠⁦楬瑳椠⁳慰獳摥愠⁳啎䱌‬癥牥⁹⼯琠牨敥搭戭摯⁹湩琠敨瀠牡⁴獩椠獮牥整⁤湩潴琠敨猠汥捥楴湯猠瑥‮潶摩䌠敂摮䅃噄敩偷牡㩴椺獮牥彴敳敬瑣潩彮敳⡴䵂㍟彄佂奄⨠氪獩⥴⁻椠瑮琠条䈻彖䕓䕌呃䑟呁⁁搪瑡⁡‽啎䱌※椠⡦‡楬瑳 ⁻†††††††⼠ 湉敳瑲攠敶祲琠牨敥摟扟摯⁹湩瀠牡⁴湩潴猠汥捥楴湯猠瑥䈮彍䅐呒⨠慰瑲㴠丠䱕㭌䉃湥䍤䑁潄⩣瀠潄⁣‽敇䑴捯浵湥⡴㬩十䕓呒噟䱁䑉瀨潄⥣瀻牡⁴‽䑰捯☭瑧朻瑥灟牡⡴㬩晩ℨ瀠牡⥴爠瑥牵㭮†䵂䙟䍁⁅昪捡⁥‽啎䱌䈻彍䕂䑎䥌䕎⨠敢摮楬敮㴠丠䱕㭌䵂䙟剏䥍䝎⨠潦浲湩⁧‽啎䱌昻牯昨捡⁥‽慰瑲☭瑧朻瑥晟捡彥楬瑳⤨※慦散※慦散㴠⠠䵂䙟䍁⁅⤪慦散☭瑧渻硥⡴⤩笠†晩ℨ映捡⥥挠湯楴畮㭥慴⁧‽〱〰〰⠪慦散☭瑧朻瑥楟硤⤨ ‫〱〰‰‫慦散☭瑧朻瑥楟硤⤨椻⡦‡彭敳敬瑣潩彮敳⹴楦摮琨条‬啎䱌⤩笠慤慴㴠渠睥䈠彖䕓䕌呃䑟呁㭁慤慴☭瑧欻祥㴠琠条搻瑡ⵡ朦㭴摥敧㴠丠䱕㭌慤慴☭瑧眻牯摬灟⁴‽䵂偟䥏呎〨〮‬⸰ⰰ〠〮㬩彭敳敬瑣潩彮敳⹴湩敳瑲琨条‬氨湯⥧慤慴㬩絽潦⡲敢摮楬敮㴠瀠牡⵴朦㭴敧彴敢摮楬敮江獩⡴㬩戠湥汤湩㭥戠湥汤湩⁥‽䈨彍䕂䑎䥌䕎⨠戩湥汤湩ⵥ朦㭴敮瑸⤨ ⁻椠⡦‡敢摮楬敮 潣瑮湩敵琻条㴠ㄠ〰〰⨰戨湥汤湩ⵥ朦㭴敧彴摩⡸⤩⬠ㄠ〰〰⬠戠湥汤湩ⵥ朦㭴敧彴摩⡸㬩晩ℨ洠獟汥捥楴湯獟瑥昮湩⡤慴Ⱨ啎䱌⤩笠慤慴㴠渠睥䈠彖䕓䕌呃䑟呁㭁慤慴☭瑧欻祥㴠琠条搻瑡ⵡ朦㭴摥敧㴠丠䱕㭌慤慴☭瑧眻牯摬灟⁴‽䵂偟䥏呎〨〮‬⸰ⰰ〠〮㬩彭敳敬瑣潩彮敳⹴湩敳瑲琨条‬氨湯⥧慤慴㬩絽潦⡲潦浲湩⁧‽慰瑲☭瑧朻瑥晟牯業杮江獩⡴㬩映牯業杮※潦浲湩⁧‽䈨彍但䵒义⁇⤪潦浲湩ⵧ朦㭴敮瑸⤨ ⁻椠⡦‡潦浲湩⥧挠湯楴畮㭥慴⁧‽〱〰〰⠪潦浲湩ⵧ朦㭴敧彴摩⡸⤩⬠ㄠ〰〰⬠映牯業杮☭瑧朻瑥楟硤⤨椻⡦‡彭敳敬瑣潩彮敳⹴楦摮琨条‬啎䱌⤩笠慤慴㴠渠睥䈠彖䕓䕌呃䑟呁㭁慤慴☭瑧欻祥㴠琠条搻瑡ⵡ朦㭴摥敧㴠丠䱕㭌慤慴☭瑧眻牯摬灟⁴‽䵂偟䥏呎〨〮‬⸰ⰰ〠〮㬩彭敳敬瑣潩彮敳⹴湩敳瑲琨条‬氨湯⥧慤慴㬩絽牄睡慐瑲洨桟捤㬩敲畴湲紻䵂㍟彄佂奄⨠桴敲彥彤潢祤氻湯⁧㭩潦⡲㵩ⰰ琠牨敥摟扟摯⁹‽楬瑳せ㭝琠牨敥摟扟摯㭹⬠椫‬桴敲彥彤潢祤㴠氠獩孴嵩 楻⡦‡桴敲彥彤潢祤 牢慥㭫慴⁧‽〱〰〰⠪桴敲彥彤潢祤☭瑧朻瑥楟硤⤨ ‫〱〰⬰琠牨敥摟扟摯⵹朦㭴敧彴摩⡸㬩晩ℨ洠獟汥捥楴湯獟瑥昮湩⡤慴Ⱨ丠䱕⥌ 摻瑡⁡渽睥䈠彖䕓䕌呃䑟呁㭁慤慴☭瑧欻祥㴠琠条搻瑡ⵡ朦㭴摥敧㴠丠䱕㭌慤慴☭瑧眻牯摬灟⁴‽䵂偟䥏呎〨〮‬⸰ⰰ〠〮㬩彭敳敬瑣潩彮敳⹴湩敳瑲琨条‬氨湯⥧慤慴㬩絽牄睡慐瑲洨桟捤㬩敲畴湲紻⼯吠楨⁳畦据楴湯爠瑥牵獮琠敨氠牡敧瑳漠⁦桴⁥ⱸ礠愠摮稠瀠潲敪瑣潩獮漠⁦桴⁥慰瑲胢玙⼯戠畯摮湩⁧潢⹸潤扵敬䌠敂摮䅃噄敩偷牡㩴机瑥慟灰潲彸慰瑲獟穩⡥潶摩笩†晩洨彤慰瑲扟潢彸楳敺 ⁻†搠畯汢⁥楳敺㴠张浟硡洨彤慰瑲扟潢彸楳敺せⱝ洠彤慰瑲扟潢彸楳敺ㅛ⥝※†猠穩⁥‽彟慭⡸楳敺‬摭灟牡彴扢硯獟穩孥崲㬩††敲畴湲猠穩㭥†⁽攠獬⁥敲畴湲〠〮紻⼯吠楨⁳畦据楴湯瀠獡敳⁳慢正琠敨戠畯摮湩⁧潢⁸楳敺漠⁦桴⁥慰瑲椠⁮瑩⁳牯杩湩污漠楲湥慴楴湯椬⁮桴⽥ 牡慲⁹搢浩湥楳湯≳‮桔獩愠牲祡猠潨汵⁤敢愠⁴敬獡⁴景猠穩⁥⸳删瑥牵獮ㄠ椠⁦畳捣獥晳汵‬‰瑯敨睲獩⹥⼯䌠畡楴湯›桔獩椠⁳⁡畱捩⁫湡⁤敨据⁥潮⁴敶祲愠捣牵瑡⁥慣捬汵瑡潩㭮椠⁦潹⁵慷瑮朠敲瑡牥瀠敲楣楳湯⼬ 牷瑩祥畯⁲睯⁮畦据楴湯椮瑮䌠敂摮䅃噄敩偷牡㩴机瑥灟牡彴楤敭獮潩獮搨畯汢⁥搪浩湥楳湯⥳⁻䌠敂摮䅃䑄捯‪䑰捯㴠䜠瑥潄畣敭瑮⤨椻⡦‡䑰捯 敲畴湲〠䈻彍䅐呒瀪牡⁴‽䑰捯☭瑧朻瑥灟牡⡴㬩晩ℨ瀠牡⥴爠瑥牵⁮㬰晩ℨ搠浩湥楳湯⥳爠瑥牵⁮㬰湩⁴㭩䵂偟䥏呎挠湥牴楯㭤睒慍牴硩搴⨠整灭㴠删䍷敲瑡䵥瑡楲⡸㬩⁩‽潣灭瑵彥慰瑲损湥牴楯⡤慰瑲‬ⰱ☠浡㭰散瑮潲摩㬩晩ℨ椠 敲畴湲〠※椠㴠挠浯異整灟牡彴扢硯瀨牡ⱴㄠ‬整灭‬散瑮潲摩‬楤敭獮潩獮‬啎䱌㬩椠⡦‡⥩爠瑥牵⁮㬰睒敄瑳潲䵹瑡楲⡸整灭㬩敲畴湲ㄠ紻戼㹲颻賩ꮼ戼㹲倊剁⹔塈꾁菣뎃菣ꊃ菣ꮃ臣袂臣ꢃ裥讧胩ꪁ臣ꮁ雩馁苣뎂菣뎃菣㲈牢ਾ⨯臣꺁菣ꆂ苣ꮃ臣䊯䅍䥐䈠彍䅐呒苣ꦃ苣꺁껥ꦾ苣ꮐ苣芀菩蚈雩낕臣蚮臣꾁䅐呒䌮偐臣芁苣芀苣뎃苣袃菣꾂苣ꢁ菣릂菣ꦃ苣뾂臣傯剁彔䕎⹗偃ꮁ臣讂胣랂菣ꊂ菣隌雩낕臣傯剁彔佌䑁硟䌮偐臣袂臣傳剁彔䅓䕖䌮偐臣芁苣芀菣ꦂ菣螃苣뎃苣ꊖ闦꾁但䑌䌮偐臣袂臣㎳彄商䍎䌮偐臣芁苣芀苣뎃菣ꦂ菣螃苣뎃苣ꊖ闦꾁乕但䑌䌮偐臣芁苣芀⨪⨪‪⨪⨪⨪⨪⨠⨪⨪⨪⨪⨠⨪⨪⨪⨪⨠⨪⨪⨪⨪⨠⨪⨪⨪⨪⨠⨪⨪⨪⨪귨隫볯⶚䵂偁꺁꣨袨軥蚐臣醼臣꾁胣ꢅ뷤꺁菩蚈苣骎臣ꢁ藥ꚁ臣节臣ꞁ귦몢臣ꢡ臣蚁臣馁苣鎁臣ꞁ臣讂胣鎁苣꺁裥릂臣醼臣꾁胣醈胣貁뷤讁苣辕臣袐苣鮁胣薿胩ꮁ귧袁苣鞾苣鎁臣貁蟥ꖝ苣ꢁ臣蚁臣ꢁ臣芁苣芀귧袁臣芁臣覂臣뺁臣꾁ꇨ閁苣ꪁ臣ꚁ苣膀臣貂臣릮飦ꮁ꣨鞮臣貂苣芀臣貂臣隻臣ꦈ苧꾁胣醈胣꾁궸껥ꪁ菩蚈ꢁ臣ꚁ菩蚈苣ꢡ臣ꚁ臣讂臣ꞁ胣ꢃ裥銂䐳菣螃菣隌臣讂臣ꢁ臣뒛臣ꮁ蟥ꖝ苣ꢁ臣蚁臣ꢁ臣芁苣芀蒖鷦꺁觧誮臣Ꞁ돨꺁볯ꒁ臣膀臣貂臣뺯꟧蒚臣芁苣鎁臣ꞁ臣讂胣醈胣꾁胣醈胣貁臣꺁菩蚈苣ꢡ臣膀臣貂臣ꒁ臣ꚁ郧놔믤醁臣讂臣趁臣꺁뫤龮臣ꦈ苧銂铧蒁苣鎁臣貁蟥ꖝ苣芀뻤袁臣膀裦薀臣蒖鷦꺁볯ꒁ臣뒁臣뾁苣膀臣꺁믤뒁臣醈胣貁軥閁菣꾂菣ꮃ苣ꖟ苣ꢁ껥ꦾ臣貂苣꺁臣膀ꇨ馁臣ꢁ臣몇鷦讂胣ⶂ볯ꒁ臣辕ꇩ꾁胣醈胣貁菩蚈臣閃菣莃菣邃菣뢂菣뎃苣躸臣覂苣龁臣趁볯鶁苣꾁胩뢸臣骎臣銂郥뺁臣蒁볯芦뷤ꮁ裦薀臣鶁苣讁苣ꢃ裥銂꟦邈臣讂臣ꢁ臣蚁臣ꢁ臣芁苣芀臣꺁菣ꦃ菣袃臣ꢃ裥꺁룤Ꞁ菣ꒂ菣銂ꇨ馁臣蒁臣鎁臣銂軦ꢔ臣讂臣㾋臣꺁䵂偁ꮁ臣蒁臣膀裦薀臣膀菣뎃菣ꊃ菣ꮃ臣芁臣覂臣뺁臣ꢡ臣貂苣ꢃ裥꺁菣ꦃ菣袃菣벃苣ꢃ菣꾁胣ꢃ裥貁菣莃菣鎃菣벃볯誸鷩뎛볯ꮁ臣讂臣趁雨뾝臣鲃菣ꂃ臥ꞁ臣讂臣蒁臣鎁臣銂軦ꢔ臣ꚁ臣讂胣隻臣趇ꛨꪁ苧꾁胣鎁臣閃菣莃菣邃菣뢂菣뎃臣墌夭鷩誸臣芁苣ꢁ臣蚁臣ꢁ臣芁苣芀臣꺁雦閳臣꾁胣设臣骎臣貁ꓥ隌臣ꚁ苣膀裦薀臣ꊃ菣ꮃ臣뺯臣讂ꓥ隌臣肜냥ꞁ臣讂胣ⶂ閃菣莃菣꾁雨뾝臣鲃菣ꂃ臥銂ꇨ馁臣膀菣ꦃ菣袃臣螃苣ꆃ菣랂菣뎃臣궸胦ꦃ苣뎃菣ꒂ菣뎃苣ꢃ菣銂ꇨ馁胣馁臣辂臣膀裦薀臣ꢃ裥銂鯦銁臣ꢁ臣膀鯦銁臣ꢃ裥꺁룤Ꞁ菣ꒂ菣꺁菣ꒂ菣뎃苣ꢃ菣꾁菣ꦃ菣袃菣ꒂ菣뎃苣ꢃ菣ꮁ룤뒇臣讂볯뺁臣꾁胣馃菣覃菣肃苣랂菣뎃臣袂苣骮뻧閁苣讂蟩ꂁ臣骁苣閁苣讂볯芀臣貂臣膀臣貂苣ꮁ꿥鞁臣薆臥㶴룤Ꞁ菣ꒂ菣㶳ꓥ뒁臣꺁臣ꊝ臣뺯臣ꚁ룤ꦁ裥ꞁ臣讂胣鞁臣鞁胣鶁苣꾁菣뎃菣ꦃ苣뎃臣뺯臣ꚁ蟩膦臣芁苣芀臣貂臣膀菣뎃菣ꦃ苣뎃臣몟ꓧ銂臣馁菣ꦃ菣袃臣馃菣覃苣벃苣꺁룤Ꞁ菣ꒂ菣誸臣麃菣鞃臣貂苣ꢁ臣蚁臣ꢁ苣辄釥馁苣芀‭菩蚈臣뎕臣貂苣ꢁ臣膀䵂偁꾁胩뢸臣馃菣릂鲃菣ꒂ臣㊮ⵄ朦㭴䐳ꓥ鮏苣覤賥閁臣讂臣ꢁ臣ꪁ臣芀臣讁臣膀菣벃苣ⶹ菣螃苣貁菣뎃菣ꦃ苣뎃臣芁苣膀菣뎃菣ꦃ菣벃苣꺁맥ꒁ臣銂볯设臣낁胣馃菣覃꟨覼ꓥ袁苣芙臣㊯ⵄ朦㭴䐳ꓥ鮏菣袃菣꾂苣꾁胢溙瑯甭⵰潴搭瑡馀臣麃菣꾂臣貂苣芀裦薀臣鎁臣꒏臣覤迦麃菣ꪃ苣릂苣ꢔ臣龁臣趁臣膀뗧鲞臣ꪂ臣ꪁ苣芀뻥ꎁ臣膀裦薀臣龮髩ꮁ迥蒁漨瑵漭ⵦ慤整覤迦麃菣ꪃ苣릂苣ꢔ臣讂臣ꢁ臣몇鷦ꪁ臣芀臣讁臣膀臣꺁ꃥ袐胣醈胣꾁胣覤迦麃菣ꪃ苣릂苣肸蟨麃菣ꪃ苣릂臣ꪃ苣莃菣馁苣鎁臣袂苣財臣릁臣뒛臣袂臣节臣銂賦ꒁ臣ꢁ臣ꪁ臣芀ꢅ臣꺁䐳뷤꺁苣ꒂ苣꾁볯骀苣꺁雦閳臣覤賥馁苣鎁臣貁蟥ꖝ苣芀藥骁胣节臣ꊝ臣膀菣뎃菣螃菣꾂苣ꢃ菣꺁跥蚈臣辇臣覭臣蒁蟩ꮁ苣誂菣ꪃ菣閁苣讂胣견뫤ꮁ胣ꢅ臣꺁菣螃苣꾁髩ꖎ臣讂菣뎃菣ꦃ苣뎃臣ꊖ臣ꚁ臣貂臣芿苣讂菣ꪃ菣뎃苣ꒀ苣膌臣鎁臣貁蟥ꖝ苣芀髩ꖎ菣뎃菣ꦃ苣뎃臣늛臣覂苣讂臣趁胣鎁臣鲃菣ꒂ臣鎁臣辇臣袂苣袃菣ꂃ臣貂苣芀䈭⁍偁꾁䵂偁閃苣ꒂ菣꺁藥ꚁ臣겅鿧꺁볯馁臣辂臣膀鳦醿臣誁苣뎁藥ꚁ臣鶈鳦꺁볯邃菣뢂菣뎃苣궃菣覃臣讂臣ꢁ臣몇鷦讂胣ⶂ菩蚈臣閃苣ꮃ菣閁苣龁臣趁胣㊁ⵄ朦㭴䐳ꓥ鮏臣뾁臣뒛臣ꮁ꣨鞮臣貂苣芀꣨鞮臣议菩꾁ꛨ花臣鲿臣ꚁ胣馁臣辂臣薿ꛨꪁ臣趁臣뢸臣ꪁ臣貂苣芀裦薀臣ꢃ裥銂苣뎃菣ꦂ菣覃臣讂臣趁臣膀藥ꚁ臣论藦膀臣ꪁ苣ꆁ䐳㈭覤迦誁苣뎁菩蚈臣閃菣莃菣邃菣뢂菣뎃臣뒛臣ꮁ꣨鞮臣貂苣芀ꢃ裥貁苣뎃菣ꦂ菣覃臣貂苣ꢁ臣꾁胣䊁䅍䥐臣膀䐳鲃菣ꒂ臣뺏鳥꺁䐳邃菣뢂菣뎃苣膀臣貂苣貁灵琭ⵯ慤整臣鞁臣麃菣꾂臣貂苣讁郥讁臣꾁蓧ꊖ뿤ꮁ胣ꢔ臣讂胣ⶂ䵂偟剁꾂菣릂臣ꢃ裥꺁铧邈苣릮飦ꮁ臣讂맥ꒁ臣꺁菣ꒂ菣馃菣꺁雩낕苣覜臣讂胣设臣낁胣鶁苣꾁胣ꢃ裥꺁菣ꦃ菣袃菣벃苣ꢃ菣銂ꓦ뮟臣膀ꛨ몇臣貂臣辕ꇩ릂苣몛껥馁苣ꊖ闦銂鳦馁苣芀鯦ꮁ胣鶁苣꾁胣醼뗧꺁鷩꺁臣貁룤袁苣貂臣ꢁ臣ꢃ裥ꮁ꿥馁苣馃菣覃菣ꒂ菣銂铧邈臣讂雩낕苣覜臣讂胣鎁苣覂臣膀ꓥ辁臣ꢔ胩ꮁ臣蒁臣놅胩꺁苣릂苣ꞁ臣讂菣ꒂ것菣ꮃ臣ꊖ闦ꞁ臣讂胣ⶂ菩蚈臣馃菣覃菣ꒂ菣ꮁ꿥鞁臣꾁胣鶁苣覂臣릉껥꺁苣뎃苣ꦃ苣뎃苣膌臣鎁臣貁뗧뺯뿥膦臣芁苣芀苣뎃苣ꦃ苣뎃臣ꪁ臣ꢁ胣馃菣覃菣ꒂ菣꾁껦ꦁ蓧ꢔ臣芁苣膀臣貂臣閃苣ꮃ菣閁苣讂臣ꢁ苣ꊂ菣閃苣ꮃ菣閁苣讂臣ꢁ苣몇鷦ꪁ臣芀菣뎃菣ꦃ苣뎃苣뎃苣ꦃ苣뎃臣鎼臣꺁鯧蒚臣龁苣ꮁ铧蒁苣貂苣骼馃菣覃菣ꒂ菣閃苣ꮃ菣ꒂ菣낂ꊂ菣閃苣ꮃ菣ꒂ菣낂臣龁苣芀馃菣覃菣ꒂ菣貁ꧧ꺁臣趁菣뎃菣ꦃ苣뎃菣銂ꇨ馁臣膂胣ⶂ菣뎃菣ꦃ苣뎃臣醐臣銂뇦骮臣讂臣膂胣뮂菣뾂菣ꒂ菣꾁胣閃菣莃菣邃菣뢂菣뎃臣肸껥꺁郥趁苣膌臣꺁臣袼臣ꪁ苣ꆁ胣閳럧꾁〨〬ㄬꞁ臣醁苣낁臣覂臣蒁胣覼胣ꢃ裥꺁䐲볯馁臣辂臣膀菣ꦃ菣袃볯邃菣뢂菣뎃臣誁臣ꚁ鳦节꺛髧蒚ꞁ臣讂臣蒁臣릂臣ꢳ蓦閁苣龁臣芀菩蚈臣㎮邃菣뢂菣뎃臣誁臣ꚁ臣膀苣뎃苣ꦃ苣뎃臣膀臣꺁蓦뎑臣膀ꓥ隌迥붃臣몟ꓧꢁ臣讂ꇨꊝ臣袂苣骮뻧閁苣讂臣ꞁ胣뺹苣讁뮸ꛨ蒚ꞁ臣讂胣设臣낁胣醈胣꾁胣ꢡ鷩袼臣貂臣薿蓧蒚臣蒖鷦銂ꓥ隌臣鮁臣蒁볯ꢃ裥銂菣ꪃ菣鞃臣讂臣ꢁ臣몇鷦膀臣龁뗧鲞臣鞁臣馃菣覃菣ꒂ菣꺁郥趁苣貐臣ꮁ뿤ꒁ臣膂臣貐꟦ꮁ苣뎃苣ꦃ苣뎃苣趏믨閁臣ꪁ臣貂臣ꪁ苣ꪁ臣芀ꢅ臣꺁菣뎃菣ꦃ苣뎃臣鶁苣ꮁ뿤辂苣뎃菣螃菣꾂苣ꢃ菣銂賦ꒁ胣₂臣꺁菣뎃菣螃菣꾂苣ꢃ菣꾁胣ꢃ裥貁菣ꦂ菣覃臣龁臣ꊂ菣閃苣ꮃ菣閁苣讂臣趁菩蚈菣ꒂ菣뎃苣ꢃ菣貁볯鎁臣馃菣覃菣ꒂ菣ꮁ臣蒁臣覼ꛥ閽臣覤賥馁苣讁苣뚈뻥馁苣芀菣뎃菣螃菣꾂苣ꢃ菣ꒀ臣ꎭ臣袂臣ꂲ臣ꆸ胨銂迥讂臣ꢁ臣몇鷦讂胣鶁苣貁귦ꞁ臣誂胣醈胣貁菩蚈苣閃苣ꮃ菣馁苣ꢁ臣꾁菩蚈臣螃苣ꆃ菣랂菣뎃臣ꆋꓥ鞁胣鶁苣貁단꺁臣趁臣ꢃ裥螃苣ꆃ菣랂菣뎃臣躏룧馁苣芀귦꺁菣뎃菣螃菣꾂苣ꢃ菣꾁苣뎃菣ꦂ菣螃苣뎃苣芙臣ꢃ裥銂菣ꦂ菣覃臣랂菣ꪃ菣꾂臣讂臣趁菩蚈苣ꆋꓥ馁苣鎁臣銂蓦뎑臣膀臣鞁臣鎾臣ꚁ단꺁菣뎃菣螃菣꾂苣ꢃ菣꾁苣뎃菣ꦂ菣螃苣뎃苣芙臣ꢃ裥銂菣ꦂ菣覃臣膀详Ꞥ臣讂臣趁菩蚈苣躏룧閁臣讂臣ꢁ苣辄釥馁苣ꎔꗦ몟뫦ꞁ臣讂볯ꢁ꣨辂苣龁볯芀䈭彍䅐呒臣膀菩蚈臣螃苣ꆃ菣랂菣뎃苣뚈뻥馁苣醃菣ꆃ菣뾂敢摮楬敮摟浩湥楳湯彳瑳瑡獵苣膌臣芀臣貂臣膀菩蚈臣궨꣨ꢁ铧邈苣릮飦ꮁ臣讂臣膂臣颻諥閁苣讂胣ꚃ菣뚂臣袼뻤袁臣覼ꓥ뒁臣覂ꓥ뒁臣ꢃ裥螃苣ꆃ菣랂菣뎃苣躸臣覂苣ꢁ臣蚁臣ꢁ臣鞁臣鞁臣략臣讂胣鎁苣覂臣螃苣ꆃ菣랂菣뎃臣ꮂ苣뾂菣ꮁ苣誂鯥骮臣貂胣릉껥閁苣讂胣蒖鷦궨꣨鞃菣뮂苣꺁苣벃菣꾁胣뎂菣閃菣莃菣貁菣ꦂ菣覃臣貂苣ꢁ臣鶁臣螃苣ꆃ菣랂菣뎃臣肉껥꺁菣ꒂ菣뎃苣ꢃ菣ꮁ귦몢臣肸蟨馁苣袂臣ꮁ臣꺁菩蚈臣閃菣莃菣銂铧邈臣讂臣ꢁ臣芁苣芀꣨袨菣궃苣릂臣誁臣ꚁ臣膀菣벃苣꾁룤ꎀ臣릖돦ꞁ菩蚈苣覤賥閁臣讂臣ꢁ臣몇鷦讂胣龁臣鞁胣鎁苣貁룤袁苣貂臣ꢁ臣膀裦薀臣뢸臣ꢃ裥螃苣ꆃ菣랂菣뎃苣覤賥鞁臣蒁苣蚁臣馁苣鎁臣銂鳦肂胣₂戠湥汤湩彥楤敭獮潩獮獟慴畴貁剔䕕臣ꢁ臣膀䵂偁꾁胣ꚃ菣뚂臣ꢃ裥込菣뎃菣ꦃ苣뎃菣ꦃ菣벃苣袼雨뾝臣骎臣뺁臣꾁菣뎃菣ꦃ苣뎃臣認뻥ꪁ臣꺁苣蚁臣覼苣覤賥閁臣讂臣趁胣꾏菨鎂苣낁룥ꮁ菩蚈菣ꒂ菣뎃苣ꢃ菣銂볯ꢅ臣꺁菣뎃菣ꦃ苣뎃臣誁臣ꚁ볯肸껥ꮁ뿤ꢁ臣ꢁ臣讂胣閁苣ꪁ臣貂臣膀裦薀臣ꢳ蓦鞁臣蒁胣ⶂ믤趉臣辕ꇩꢁ雩ꎀ臣ꚁ铧颁苣隻臣辕ꇩ꾁胣ꢃ裥뢯돦貁胩뢸臣侯呕䥓䕄䤯华䑉⽅䕎呕䅒螃苣ꆃ菣랂菣뎃臣鞁臣릉껥閁苣讂臣蒁臣鎁臣ꞁ臣讂胣设臣낁胣ꚃ菣뚂臣膀菣莃苣릂臣躸臣覂苣膀臣꺁ꓥ뒁菣ꒂ菣뎃苣ꢃ菣꾁〱砰〱ꞁ臣讂臣릉껥馁苣芀諦鎡髧ꮁ臣膀菣벃苣꾁胣閃菣莃菣誸臣鎁臣鲃菣꾂苣薆臣ꢅ臣꺁菣뎃菣ꦃ苣뎃臣隤臥螃苣ꆃ菣랂菣뎃苣ꢡ臣ꢁ臣蚁臣ꢁ苣릉껥鞁臣蒁苣芀뻤袁臣膀菣벃苣貁뻥ꮁ雨뾝臣骎臣銂ꓥ袁臣ꢁ臣膀ꓥ뒁菣ꒂ菣뎃苣ꢃ菣꾁郥颁臣뺁臣芁苣膀臣ꪁ苣ꆁ藥ꚁ臣颻諥閁苣龁軥閁臣鶀菣莃苣릂臣薆臥ꮁꇨ讁臣醁苣낁臣覂臣蒁胢肸裨ꮁ胣ꚃ菣뚂볯뺁臣꾁苣릂苣麃볯꾁胣貐臣ꊝ蛥ꞁ苣膀菩蚈菣ꒂ菣뎃苣ꢃ菣銂問協䑉⽅义䥓䕄丯啅剔䱁菣ꒂ菣뎃苣ꢃ菣ꢁ觧骮臣讂胣设臣낁胣ꚃ菣뚂臣膀菣莃苣릂苣ꪨ裥ꎁ臣螃苣ꆃ菣랂菣뎃臣膀볯뒁臣蒖鷦꺁蛥뒁臣覂믤뒁臣蒖鷦꺁ꓥ뒁臣ꢁ臣ꚁ룤袁苣貂苣ꢁ臣蚁臣ꢁ臣몇鷦讂胣₂醈胣꾁胣ꚃ菣뚂臣ꢃ裥螃苣ꆃ菣랂菣뎃苣肸껥ꮁ뿤鎁臣銂鳦肂臣Ꚑ臣꺁菣ꦃ菣꾂苣鶿賦馁苣覤闦銂菩蚈蛥ꮁ鳦馁苣芀苣鞁臣꺁ꓥ낕臣膀菣벃苣貁胣ꢃ裥螃苣ꆃ菣랂菣뎃臣肸껥ꮁ뿤膌臣貂苣鎁臣銂ꛨ花臣ꪁ臣袂臣ꮁ꣨骮臣貂苣ꢁ臣膀臣꺁义䥓䕄伯呕䥓䕄丯䕕剔䱁䰭义꺁菣꾃苣ꮃ菣뢂菣릂臣ꆄꛨ閁苣讂胣⪂⌯晩摮晥䈠彍䅐呒䡟塘䥟䍎啌䕄⍄敤楦敮䈠彍䅐呒䡟塘䥟䍎啌䕄⍄湩汣摵⁥氦㭴瑳楤⹯♨瑧⌻湩汣摵⁥䜢佌䅂⹌塈≘椣据畬敤∠久䥔奔䠮塘⌢湩汣摵⁥吢偏䱏䝏⹙塈≘汣獡⁳䵂偟剁⁔›異汢捩䈠彍久䥔奔晻楲湥⁤䵂䙟䍁⁅昻楲湥⁤䵂䡟䱏⁅昻楲湥⁤䵂䉟久䱄义⁅昻楲湥⁤䵂䙟剏䥍䝎㬠牦敩摮䈠彍佔佐佌奇㬠牦敩摮䵂呟偏䱏䝏彙䕒佃䑒㬠牦敩摮䈠彍䕂䑎偟佒䕐呒⁙昻楲湥⁤䵂䉟久彄剐偏剅奔卟䵉䱕䅔䕎問⁓⼻ 癥牥⁹慰瑲栠獡愠⠠獵牥搭晥湩摥 慮敭琠慨⁴瑩椠桮牥瑩⁳牦浯䵂䕟呎呉⹙⼯愠獬Ɐ琠敨琠灹⁥䈨彍久䥔奔呟偙彅䅐呒 獩猠潴敲⁤湩䈠彍久䥔奔瀮潲整瑣摥㨠⨯臣貂苣꺁ꓥ낕臣膀菣벃苣銂臣ꚁ郥趉苣膀闦膀鷦首臣꺨ꇩꪁ臣꺁菣ꦃ菣벃苣銂菩蚈臣ꊖ뿤閁臣讂胣⪂振慨⁲慭整楲污瑟灹孥㔲崶㬠档牡渠浡孥㔲崶挻慨⁲畮扭牥㍛崲㬠⨯臣貂苣꺁ꓥ낕臣邝雦ꢁ菣뾂菣릉胦銂꣨낿臣讂胣⪂搯畯汢⁥敭慴彬桴捩湫獥⁳⼻鎁臣ꢃ裥薆臣꾁胣銼臣꺁菣ꒂ菣袃臣膀苣鞁臣貂苣꺁雩꺁럨ꊛ臣鎁臣ꒀ꣧ꚺ臣ꢁ臣꾁郥颁臣芁苣ꢁ胨袁苣貂苣芀⼪潤扵敬搠獩慴据彥潴敬慲据㭥⨯藥ꚁ臣ꢃ裥꾁菣뎃菣릉胦꺁菣릂菣銂鳦馁苣芀菣뎃菣ꦃ苣뎃臣馃菣覃觧Ꞁ苣膌臣ꢁ臣꾁胣鎁臣릉胦꺁꿥ꆱ臣ꢃ裥ꮁ뿤辂苣馃菣覃觧Ꞁ臣ꪃ苣袃룤ꮁ臣醁苣낁臣覂臣蒁胣鎁苣꾁胣醈胣貁菩蚈苣뮂菣隃臣龁臣궃菣覃臣讂臣趁뿥膦臣閁苣讂胣鎁苣覂臣覤闦꾁胣薆菩ꮁ臣뾁뷤ꢔ臣貂苣芀䵂偁꺁菣벃苣꾁胣鎁苣覂臣覤闦ꮁ苣꾂苣릂苣膌臣ꪁ臣芀⼪潬杮渠浵敢彲景扟湥彤牰灯牥楴獥㬠䵂䉟久彄剐偏剅奔⨠楬瑳潟彦敢摮灟潲数瑲敩⁳⼻ꢃ裥꺁菣鶃菣뢂菣鎁臣ꞁ菣螃苣銂菣릂菣ꮁ鯧ꖎ믤ꂊ臣讂臣ꢁ臣꾏菨ꞁ臣ꪁ臣鎁臣ꮁ돦辄臣貂臣蒁胣鎁苣꾁胣鲃菣ꒂ臣ꢃ裥袃菣궃苣벃臣颻諥閁苣讂臣趁臣꺁臣ꪁ臣貂苣芀⼪䵂呟偏䱏䝏⁙潴潰潬祧㬠⼯渠浵敢⁲景搠晩敦敲瑮䐳戠摯敩⁳湩琠敨瀠牡⹴⼯琠敨敳渠浵敢獲猠潨汵⁤敢挠湯楳瑳湥⁴楷桴琠敨瀠牡⁴潴潰潬祧氮湯⁧畮扭牥潟彦慦散⁳氻湯⁧畮扭牥潟彦潨敬⁳氻湯⁧畮扭牥潟彦敢摮楬敮⁳氻湯⁧畮扭牥潟彦潦浲湩獧㬠⼯氠獩獴漠⁦慦散ⱳ栠汯獥愠摮戠湥汤湩獥漠⁦桴⁥慰瑲⼯丠瑯⁥桴瑡琠敨敳愠敲氠獩獴漠⁦䵂㍟彄佂奄胢玙䈮彍䅆䕃⨠楦獲彴慦散㬠䵂䡟䱏⁅昪物瑳桟汯⁥䈻彍䕂䑎䥌䕎⨠楦獲彴敢摮楬敮㬠䵂䙟剏䥍䝎⨠楦獲彴潦浲湩⁧⼻鎁苣覂臣醃菣ꆃ菣뾂臣ꢃ裥ꮁ뿤辂苣馃菣覃苣벃苣뎃苣銂ꇨ馁胣⪂氯湯⁧敢摮獟煥敵据彥楳敺㬠䵂䱟义䕋彄䥌呓也䑏⁅截湥彤敳畱湥散㬠⨯臣꺁菣ꦃ菣벃苣꾁菩蚈菣ꒂ菣뎃苣ꢃ菣銂裥ꆾ臣讂胣鶁苣貁剔䕕臣ꢁ臣꾁胣䊁䅍䥐臣膀菣벃苣貁볯蒖鷦꺁軥閁臣龁臣馃菣覃菣ꒂ菣꺁跥蒾臣ꦁ臣覼菩蚈馃菣覃菣ꒂ菣醃菣ꆃ菣뾂苣覤臣讂臣趁胣꾏菨ꪁ臣趁臣뢸臣膀菩蚈臣螃苣ꆃ菣랂菣뎃苣袼藥ꚁ臣馃菣覃菣ꒂ菣ꮁ臣蒁臣覼룤骮臣鶿臣蚁臣ꚩ臣讂胣閁苣ꪁ臣貂臣膀裦薀臣ꢳ蓦鞁臣蒁胣螃菣ꦂ菣ꮃ菣ꒀ臣ク臣芁苣膀菣ꒂ菣뎃苣ꢃ菣銂룤骮臣鶿賦馁苣薿ꛨ꾁臣蒁胣⪂振慨扲湥汤湩彥楤敭獮潩獮獟慴畴⁳瀻扵楬⁣⼺뎂菣릂菣ꦃ苣뾂臣螃苣袃菣꾂苣芀䅐呒也坅䌮偐臣誁臣ꚁ胣⪂䈯彍䅐呒瘨楯⥤㬠䵂偟剁⡔䵂偟剁⁔攪楸瑳湩彧慰瑲 縻䵂偟剁⡔潶摩 ⼻ 獵⁥桴獩琠⁯牥獡⁥桴⁥潣瑮湥⁴景琠敨瀠牡⹴琠敨瀠牡⁴楷汬敢攠灭祴⼮ 瑩眠汩⁬獵⁥潴潰潬祧㨺牥獡彥潣瑮湥⡴ 潴搠獥牴祯琠敨琠灯汯杯⁹湡⁤楷汬琠敨⁮⼯搠獥牴祯愠汬戠摯敩⁳湩琠敨瀠牡⹴潶摩攠慲敳损湯整瑮瘨楯⥤㬠潶摩朠瑥浟瑡牥慩彬祴数挨慨⁲漪瑵浟瑡瑟灹⥥㬠潶摩猠瑥浟瑡牥慩彬祴数挨慨⁲椪彮慭彴祴数 瘻楯⁤敧彴慮敭挨慨⁲漪瑵湟浡⥥㬠潶摩猠瑥湟浡⡥档牡⨠湩湟浡⥥㬠潶摩朠瑥灟牡彴畮扭牥挨慨⁲漪瑵湟浵敢⥲㬠潶摩猠瑥灟牡彴畮扭牥挨慨⁲椪彮畮扭牥 ⼻ 敧⁴畮扭牥漠⁦慦散ⱳ栠汯獥‬敢摮楬敮楳汮湩⁥潬杮朠瑥湟浵敢彲景晟捡獥瘨楯⥤挠湯瑳笠爠瑥牵⁮畮扭牥潟彦慦散⁳※楽汮湩⁥潬杮朠瑥湟浵敢彲景桟汯獥瘨楯⥤挠湯瑳笠爠瑥牵⁮畮扭牥潟彦潨敬⁳※楽汮湩⁥潬杮朠瑥湟浵敢彲景扟湥汤湩獥瘨楯⥤挠湯瑳笠爠瑥牵⁮畮扭牥潟彦敢摮楬敮⁳※楽汮湩⁥潬杮朠瑥湟浵敢彲景晟牯業杮⡳潶摩 潣獮⁴⁻敲畴湲渠浵敢彲景晟牯業杮⁳※⽽术瑥瀠楯瑮牥⁳潴氠獩獴漠⁦慦散ⱳ栠汯獥愠摮戠湥汤湩獥湩楬敮䈠彍䅆䕃⨠敧彴慦散江獩⡴潶摩 潣獮⁴⁻敲畴湲映物瑳晟捡⁥※楽汮湩⁥䵂䡟䱏⁅未瑥桟汯彥楬瑳瘨楯⥤挠湯瑳笠爠瑥牵⁮楦獲彴潨敬㬠素湩楬敮䈠彍䕂䑎䥌䕎⨠敧彴敢摮楬敮江獩⡴潶摩 潣獮⁴⁻敲畴湲映物瑳扟湥汤湩⁥※楽汮湩⁥䵂䙟剏䥍䝎⨠敧彴潦浲湩彧楬瑳瘨楯⥤挠湯瑳笠爠瑥牵⁮楦獲彴潦浲湩⁧※⽽ 潔朠瑥琠敨渠浵敢⁲景戠湥灤潲数瑲敩⁳湡⁤桴⁥楦獲⁴牰灯牥祴漠橢捥⁴湯琠敨氠獩⹴湩楬敮䈠彍䕂䑎偟佒䕐呒⁙未瑥江獩彴景扟湥彤牰灯牥楴獥瘨楯⥤挠湯瑳笠爠瑥牵⁮楬瑳潟彦敢摮灟潲数瑲敩⁳※楽汮湩⁥潬杮朠瑥湟浵敢彲景扟湥彤牰灯牥楴獥瘨楯⥤挠湯瑳笠爠瑥牵⁮畮扭牥潟彦敢摮灟潲数瑲敩⁳※⽽ 桴獩映湵瑣潩⁮牴敩⁳潴映湩⁤⁡潧摯搠晥畡瑬戠獡⁥慦散⼮ 瑩挠潨獯獥愠映捡⁥桴瑡栠獡琠敨氠牡敧瑳戠潢⹸䵂䙟䍁⁅未瑥摟晥畡瑬扟獡彥慦散瘨楯⥤㬠⨯菩蚈臣芿苣讂럨ꊛ藥꺷苣늍뻥鞁ꓥ隌臣鮁苣ꊖ闦⪰椯汮湩⁥潤扵敬朠瑥摟獩慴据彥潴敬慲据⡥潶摩 潣獮⁴⁻敲畴湲搠獩慴据彥潴敬慲据⁥※白楯⁤敳彴楤瑳湡散瑟汯牥湡散搨畯汢⁥敮彷楤瑳湡散瑟汯牥湡散 ⼻鎁臣ꢃ裥꺁迧ꢜ臣ꆃ苣ꮃ軥閁苣鞾苣芀⼪湩楬敮搠畯汢⁥敧彴敭慴彬桴捩湫獥⡳潶摩 潣獮⁴⁻敲畴湲洠瑥污瑟楨正敮獳㬠素⨯軥閁苣覤臣讂臣膀菩蚈臣骤臣꺁ꓥ隌臣龔臣讂胣ꊝ臣膀軥閁苣覤臣讂臣馃菣覃菣ꒂ菣节ꓥ隌臣鎘臣ꪁ苣꺁臣膀诨늹臣袃菣龃菣낂苣薿ꛨꢁ臣讂胣뒛臣膀鷩꺁䐲☭瑧㌻覤迦꾁鳦节ꓥ隌臣鎘臣芀臣貂臣膀菣뎃菣ꦃ苣뎃臣㎮ꊽ諧貁ꓥ隌臣讂臣芁苣蚁臣膂铧颁胣뺁臣閃菣莃菣꾁룤Ꞁꦃ苣뎃菣ꒂ菣뎃苣ꢃ菣銂ꇨ馁臣ꞁ胣ꢃ裥꺁䐳菣ꒂ菣뎃苣ꢃ菣꾁鳦节ꓥ隌臣鎘臣ꪁ苣芀菣뎃菣ꦃ苣뎃臣Ꞥ臣辁ꓥ隌臣讂臣ꢁ臣蚮臣몢臣ꞁ臣讂胣ꢅ臣꺁菣뎃菣ꦃ苣뎃臣垮䐳臣趆꣨鞮臣貂臣醁苣낁臣覂臣蒁胣뺁臣膀䐲☭瑧㌻覤迦节蛥袨껧閁苣ꪁ臣貂臣ꪁ苣ꪁ臣芀菩蚈蟨鎽臣膀軥閁苣覤臣龁뗧鲞臣鞁臣릂菣벃苣薆苣뮧该鞁臣蒁臣ꢁ臣ꢳ蓦閁苣龁臣芀臣讁臣膀菣뎃菣ꦃ苣뎃䐲☭瑧㌻覤迦꾁胢溙瑯甭⵰潴搭瑡馀臣鞁臣麃菣꾂臣貂苣芀臣貂苣銂鯦낖臣讂볯ꒁ臣릖돦꾁胣뮻蓦꺁鷩銂菣벃苣ⶹ鷩ꢁ臣ꚁ迥誂胣鶁臣ꢃ裥銂菣ⶪ菣ꦂ菣ꮃ菣馁苣鎁臣ꮁ苣誂룤袁苣貂苣袼臣貂臣膀臣꺁鳦낖臣㊮ⵄ朦㭴䐳覤迦銂賦ꒁꃥ袐臣꺁臣財苣貂苣覼胣ꢃ裥꾁郥颁ꃥ肉臣麻鳥鞁볯馃菣릂ꊝ臣ꦁ裥ꮁ믦ꢜ臣讂臣ꞁ볯膀臣龁菣뎃菣ꦃ苣뎃臣鶁苣覂臣뒛雦閁苣龁䐲☭瑧㌻⁄ꓥ鮏苣膌臣芀軥閁苣覤臣讂臣ꢁ臣膀菩蚈臣誁臣讂藥ꚁ臣鲃菣ꒂ臣㊯ⵄ朦㭴䐳覤迦銂賦ꆁ飦辁胣뺁臣ꆄ諥ꮁ臣貂臣㎟邃菣뢂菣뎃苣膌臣鎘臣꺁臣龮髩ꮁ臣袃菣莃苣벃臣芁苣芀闥財臣膀菣벃苣貁胩뢸臣ꢃ裥銂菣ⶪ菣ꦂ菣覃臣讂臣ꢁ苣鮜臣ꪁ臣ꢁ臣蚁臣ꢁ臣芁苣芀뻥ꎁ臣膀苣貂苣貂臣膀ꛥ閽臣낖臣蒁鳦릊臣㊪ⵄ朦㭴䐳覤迦銂蟨開髧ꮁ뻥讂臣銂ꓦ躨臣ꪁ臣貂臣ꪁ苣ꪁ臣芀臣꺁雩낕臣鶁苣銂臣閁臣蒁苧ꮁ돦辄臣貂臣蒁胣鎁苣꾁胣隈苣隻臣ꊖ闦ꮁ苣誂臣閁苣ꪁ臣貂臣ꪁ苣ꪁ臣论藦ꞁ臣讂胣鎁臣ꊖ闦꾁胣暁捡獥戭湥汤湩獥苣ꎭꋧꮁ룤뒇臣鮁苣蚁臣꾁臣ꪁ臣芀臣貂苣龮迧馁苣ꮁ臣膀臣꺁雩낕臣貾慭捴彨污彬慦散彳摡慪散瑮瑟彯敢摮楬敮⡳⸮⤮苣뎂菣ꮃ臣袂胣뒛臣膀雦鞁臣骎臣銂꣨骮臣膀곦ꮁ髩ꖎ鷩銂룤뒇臣鮁苣ꢁ藥ꮁ雦鞁臣肜雦꺁䐲☭瑧㌻覤迦銂꣨鞮臣讂敳彴敭慴彬桴捩湫獥彳灵慤整灟牡⡴⸮⤮苣ꢔ臣袂胣⪂瘯楯⁤敳彴敭慴彬桴捩湫獥⡳潤扵敬桴捩湫獥⥳㬠潶摩猠瑥浟瑥污瑟楨正敮獳畟摰瑡彥慰瑲搨畯汢⁥桴捩湫獥⥳㬠⨯臣꺁雩낕臣膀䐳苣骃菣릂臣誁臣ꚁ臣貂苣貁臣貂苣ꮁ髩ꖎ臣讂菣뎃菣ꦃ苣뎃臣ꎭꋧꮁ꟨貂苣袂臣ꮁ藥ꚁ臣ꊝ苣袃菣ꂃ臣讂볯薿ꛨꮁ뿥颁臣覼胣鎁臣ꊖ闦꾁胣骎臣貁ꓥ隌臣龁뻥ꮁ臣龁臣馃菣覃菣ꒂ菣醃菣ꆃ菣뾂臣覤賥鞁臣貾臣뎂菣ꮃ臣讂臣ꮁ苣蒁胣⪂瘯楯⁤慭捴彨污彬慦散彳摡慪散瑮瑟彯敢摮楬敮⡳潶摩 ⼻㌪鲃菣ꒂ볯ꊝ胣钭胣閃苣벃菣뎃苣뺁臣꾁菣뎃菣ꦃ苣뎃볯銂菩蚈臣颻諥馁苣芀믤ꂊ蟥ꖝ臣蒁臣趁臣䚯䱁䕓苣뮈臣芀臣꺁雩낕臣膀鿥겜髧ꮁ臣袃菣궃苣벃臣憮摤扟摯⡹ 敭扭牥雩낕苣뎂菣ꮃ臣讂胣⪂椯瑮愠摤㍟彤潢祤䈨彍䐳䉟䑏⁙截摯⥹㬠⼯朠瑥瀠牡⁴潴潰潬祧湩楬敮䈠彍佔佐佌奇⨠敧彴潴潰潬祧瘨楯⥤挠湯瑳笠爠瑥牵⁮䈨彍佔佐佌奇⨠ 愦灭琻灯汯杯⁹紻⨯臣貂苣꺁雩낕臣膀菣벃苣貁胣馃菣覃菣ꒂ菣ꮁ臣醁苣ꢃ裥螃苣ꆃ菣랂菣뎃臣꾏菨ꪁ臣趁臣뢸臣肸껥ꮁ뿤龁苣讂臣趁臣Ꚑ臣銂藧骼臣膀觧骮臣讂臣ꢁ苣놨껥馁苣芀⼪⼯琠⁯敧⁴桴⁥畣牲湥⁴瑳瑡獵湩楬敮椠瑮朠瑥扟湥汤湩彥楤敭獮潩獮獟慴畴⡳潶摩 潣獮⁴⁻敲畴湲戠湥汤湩彥楤敭獮潩獮獟慴畴⁳※⽽ 潴猠瑥琠敨渠睥猠慴畴⹳⼯映牯攠慸灭敬‬晩眠⁥敳⁴瑩琠⁯剔䕕‬桴湥映潲⁭桴獩瀠楯瑮漠Ɱ䈠䅍䥐⼯眠汩⁬牴⁹潴欠敥⁰潴挠牵敲瑮瀠牡⁴楤敭獮潩獮挠湯瑳湡⹴潶摩猠瑥扟湥汤湩彥楤敭獮潩獮獟慴畴⡳湩⁴敮彷敢摮楬敮摟浩湥楳湯彳瑳瑡獵 ⼻馃菣覃苣벃苣뎃苣ꊖ뿤ꊖ闦⪰瘯楯⁤敤敬整扟湥彤敳畱湥散瘨楯⥤㬠湩楬敮氠湯⁧敧彴敢摮獟煥敵据彥楳敺瘨楯⥤挠湯瑳笠爠瑥牵⁮敢摮獟煥敵据彥楳敺㬠素⼯琠楨⁳畦据楴湯爠瑥牵獮琠敨渠浵敢⁲景戠湥汤湩獥挠灯敩⁤湩潴传呕愠牲祡湩⁴敧彴敢摮獟煥敵据⡥䵂䉟久䱄义⁅截湥汤湩獥嵛‬潬杮戠湥汤湩獥慟牲祡江湥瑧⥨㬠⼯琠楨⁳畦据楴湯猠瑥⁳⁡敮⁷敢摮猠煥敵据⁥潦⁲桴獩戠湥汤湩楥瑮猠瑥扟湥彤敳畱湥散䈨彍䕂䑎䥌䕎⨠截湥汤湩獥‬潬杮戠湥汤湩獥慟牲祡江湥瑧⥨㬠⼯琠楨⁳畦据楴湯挠敨正楳⁳⁡敢摮楬敮椠⁳湩琠敨挠牵敲瑮戠湥⁤敳畱湥散漠⁦桴⁥慰瑲⼮ 晩礠獥‬瑩敲畴湲⁳瑩⁳湩敤⁸湩琠敨戠湥⁤敳畱湥散⠠敩‮桴⁥畮扭牥漠⁦桴獩戠湥汤湩⽥ 湩琠敨戠湥⁤敳畱湥散漠摲牥⸩吠楨⁳湩敤⁸獩映潲⁭‰桴潲杵⁨敳畱湥散江湥桧⁴‭⸱⼯椠⁦桴獩戠湥汤湩⁥獩渠瑯椠⁮桴⁥敢摮猠煥敵据ⱥ椠⁴敲畴湲⁳ㄭ椮瑮椠彳敢摮楬敮楟彮敢摮獟煥敵据⡥䵂䉟久䱄义⁅截湥汤湩⥥㬠⼯琠楨⁳畦据楴湯爠浥癯獥愠戠湥汤湩⁥牦浯琠敨戠湥⁤敳畱湥散⼮ 潮整琠慨⁴晩琠敨戠湥汤湩楥⁳湩愠猠浩汵慴敮畯⁳敢摮瀠潲数瑲ⱹ椠⁴楷汬爠灥慬散琠敨戠湥汤湩⽥ 楷桴湡瑯敨⁲敢摮楬敮映潲⁭桴⁥楳畭瑬湡潥獵戠湥⁤牰灯牥祴琠慨⁴獩渠瑯愠牬慥祤椠⁮桴⁥敢摮猠煥敵据⹥潶摩爠浥癯彥敢摮楬敮晟潲彭敢摮獟煥敵据⡥䵂䉟久䱄义⁅截湥汤湩⥥㬠⼯琠楨⁳畦据楴湯搠汥瑥獥琠敨挠牵敲瑮戠湥⁤敳畱湥散⠠晩漠敮攠楸瑳⥳愠摮挠敲瑡獥愠搠晥畡瑬⼠ 敢摮猠煥敵据⹥潶摩挠敲瑡彥敤慦汵彴敢摮獟煥敵据⡥潶摩 ⼻鎁臣ꊖ闦꾁胣钭苣ꮐ臣ꪁ臣ꢅ臣꺁菣뎃菣ꦃ苣뎃臣閃菣莃菣邃菣뢂菣뎃苣銎駩馁苣芀臣꺁雩낕臣膀菩蚈臣ꊂ菣閃苣ꮃ菣閁苣龁뻥覜铧ꮁ臣誂뻥讂胣骀룥꾁胣ꢃ裥꺁菣ꦂ菣覃臣貂臣邃菣뢂菣뎃臣袃菣鎃苣ꮃ臣ꪁ臣馃菣覃菣ꒂ菣袼臣ꪁ苣ꆁ胣め臣ꪁ臣ꒂ菣떂苣覃跥蒾臣袂臣⾳臣龁臣骎臣覼苣ꮐ苣芀菩蚈臣ꊂ菣閃苣ꮃ菣閁苣龁臣趁胣䊁䅍䥐臣鎁苣覂臣馃菣覃菣ꒂ菣銂胣鶁苣覂臣覜苣袂臣ꮁ귦몢臣閃菣莃菣邃菣뢂菣뎃臣覤迦馁苣芀臣ꢁ臣낁胣벂菣ꖻꓥ꺁軥뾁臣龁臣認뻥銂鳦馁苣馃菣覃菣ꒂ菣꺁䐳邃菣뢂菣뎃臣꾁胩뢸胣늛臣ꎁ臣Ꞽ臣辏臣貂苣芀臣貂臣뎹鷩邃菣뢂菣뎃臣馃菣覃菣ꒂ菣ꮁ菣莃菣뎃苣閁苣讂胣鎁苣꾁菣벃菣꺁맥ꊝ菣벃苣ꞃ菣ꮁ臣蒁臣膀菣뎃菣ꦃ苣뎃臣뺯뿥馁苣銼臣꺁鷩꺁雩ꮁ闩릖뷥貁귥ꢜ臣讂臣ꢁ苣辄釥馁苣芀臣ꂁ臣醈胣꾁胣鎁臣ꦟ뷥銂ꛨ龁臣ꪁ臣ꢁ臣貁臣讂胣鎁臣ꊖ闦꾁胣颍듧ꪁ맥ꊝ볯ꒁ臣誂맥ꊝ臣뒩臣ꪁ臣覼苣覜臣膀볯ꒁ臣ꊝ臣ꎭꋧꮁ髩ꖎ臣讂菣뎃菣ꦃ苣뎃臣醁苣ꚇ郧馁苣芀†臣꺁雩낕臣膀髩ꖎ臣讂臣릁臣꺁鷩銂裥誂迥ꎁ臣袼菣ꪃ菣뎃苣覼胣馃菣覃菣ꒂ菣꺁룤莿럧ꮁ軦ꚧ臣鮁胣馃菣覃菣ꒂ菣뎹鷩ꮁ臣醁苣馁臣ꚁ臣ꪼ볯ꮃ菣鞃볯銂觥꒙臣讂胣鎁臣ꊖ闦꾁胩뢸乕但䑌臣뒛뻥ꮁ뷤辂苣讂臣ꢁ臣ꢳ蓦鮁苣芀臣ꎁ臣鎂맥ꊝ臣袃菣龃菣낂臣貂苣ꢁ胣鶁苣꾁髩ꖎ臣讂鷩ꮁ苣ꦁ郥馁苣芀臣貂臣膀臣꺁雩낕臣蒁臣ꒁ臣꺁觧誮臣袃菣龃菣낂胥銂꣨鞮臣袂臣궨껥鞁胣貾臣ꦁ裦薀臣醃菣袃苣龁臣肂볯閃苣ꮃ菣馁苣覼臣趁臣膀鷩貁菣뎃菣ꦃ苣뎃臣ꎭꋧꮁ軦馁苣ꎭ臣蒁䐳邃菣뢂菣뎃苣鞾苣鎁臣銂蓦뎑臣讂胣鎁臣ꊖ闦꾁菣뎃菣ꦃ苣뎃苣覤臣ꪁ臣芀⼪潶摩攠楬業慮整獟浩汰彥敢摮楬敮彳湩晟慬彴敶獲潩彮⡁潶摩 ⼻鎁臣ꊖ闦꾁胣醃菣袃臣誁臣讂臣릁臣꺁䐳鲃菣ꎂ苣낵鿦鞁臣袼菣ꦂ菣龃菣낂苣꒙臣覼胣鶁苣覂臣뎹鷩邃菣뢂菣뎃苣뒕臣讂胣몟鳦蒚臣鎁臣ꊖ闦꾁胣醃菣袃臣誁臣讂臣릁臣꺁䐳扟摯袼菣ꦂ菣龃菣낂苣꒙臣覼臣뺯臣ꚁ䵂㉟彄佂奄㨺楦彸汦瑡⤨雩낕苣벑臣몇臣芀臣꺁雩낕臣뺏ꇨ꺁맥ꊝ菣벃苣ꞃ菣꺁臣銂菣Ꞃ菣꾂臣讂臣ꞁ돦辄臣袂胣鎁臣ꊖ闦꾁胣閽苣讁臣趓뷤貁ꓥ鞕臣讂臣袼臣뺁苣ꆃ菣ꪃ菣늉苣鎽臣覼胣뺁臣꾁臣꺁雩낕臣ꎧ뇦ꞁ臣ꪁ臣辕ꇩ銂駧讦臣龁臣趁臣䚫䥁啌䕒苣钿臣芀⼪湩⁴楦彸汦瑡瘨楯⥤㬠⨯臣꺁雩낕臣膀菣Ꞃ菣릂菣躃菣麃菣袼慦散渠牯慭覼臣馃菣覃菣ꒂ菣꺁껥ꦾ臣袐蟨鞁臣蒁苣鎁臣銂菣Ꞃ菣꾂臣讂胣龁臣袁臣膀慦散貁돦骷苣膌臣⢡ⰰⰰ⤱胣暁捡ㅥ臣暨捡㉥臣꺁雩ꮁ〹뫥꺁剆乏馃菣覃臣芁苣뒠郥膀慦散꺁돦骷臣⢯ㄭ〬〬ꮁ臣覂臣醁苣낁臣覂臣蒁胣겜鷦ꢁ臣蚀臣閳럧貁臣讂ꃥ袐胣鎁臣ꊖ闦꾁臣貂苣뒕臣讂胣閁苣ꪁ臣낁胣鎁臣ꊖ闦꾁闥財苣讦臣醁苣ꢁ䅆䱉剕銂뿨馁胣ꖅ諥ꊝ臣躸臣覂苣讂ꃥ袐胣鎁臣ꊖ闦꾁臣꺁鷩꺁룤莿臣趽뷧馁苣ꖎ뛧閁苣龁苣뎃菣벃菣뎃菣ꂁ臣銂菣Ꞃ菣꾂臣讂胣閁苣ꪁ臣낁胣鎁臣ꊖ闦꾁菣벃菣ꢅ뷤銂菣Ꞃ菣꾂臣讂胣鎁臣뒠郥膀臣꺁雩낕臣ꊝ苣膃苣莃苣馁苣蚠闧꾁胣ꊝ苣뎃菣莃苣릂臣蚠闧ꞁ臣讂胣鎁臣ꊖ闦꾁뿥膦臣膃苣莃苣銂臣辁臣讁ꇨꪁ臣袼臣ꢁ臣낁胣馃菣覃菣ꒂ菣貁鯦銁苣貂苣ꢁ臣膀臣貂臣抯湥⁤灯‬㍡ⵄ菣벃苣ꞃ菣袼臣貂臣목臣鎁臣节臣讂볯誁苣뎁苣벃菣Ꞃ苣銂賦龁臣醁苣낁臣覂臣蒁볯芀臣꺁雩낕臣膀臣릁臣꺁鷩誁苣뎁菣뎃菣ꦃ苣뎃臣㎮ⵄ菣벃苣ꞃ菣貁鳦낖臣节臣ꞁ臣讂臣Ꚑ臣銂菣Ꞃ菣꾂臣讂胣蒁臣貂臣貁鳦낖臣节臣ꞁ臣蒁ꃥ袐臣꾁胣鎁臣ꊖ闦꾁䅆䱉剕銂뿨馁胣鎁臣ꊖ闦꾁胣뺏ꇨ邃菣뢂菣뎃臣肜雦ꞁ臣讂臣Ꚑ臣銂菣Ꞃ菣꾂臣讂臣醁臣芁苣膀迧財菣벃苣ꞃ菣貁鳦낖臣ꪁ臣뒠郥꾁胣낖臣蒁䐳邃菣뢂菣뎃苣袨껧鞁臣蒁볯鎁臣ꊖ闦꾁胩뢸뇥讖볯ꊂ菣閃苣ꮃ菣覼臣貾臣뾽苣貂苣꺁臣膀臣꺁駦릂臣꾁뷤节꣨鞮臣龁臣ꪁ臣覼胣鎁臣ꊖ闦꾁ꧧꢁ菣ꦂ菣龃菣낂볯暈牯業杮覼苣ꆄꛨ馁苣芀湉㌠彄商䍎䌮偐⨮椯瑮映硩㍟彄慦散湟牯慭獬䈨彍䅆䕃⨠楧敶彮慢敳晟捡⁥‽啎䱌 ⼻鎁臣ꊖ闦꾁胣醃菣袃臣誁臣讂䐳鲃菣ꎂ苣膃苣莃苣鞁胣鎁苣貁ꛨꒁ臣讂闥財苣ꎧ뇦馁苣芀臣꺁雩낕臣뺏ꇨ꺁䐳邃菣뢂菣뎃臣뾁苣膃苣莃苣馁苣꺁臣ꢳ蓦鮁苣芀臣覂臣鎁臣ꊖ闦꾁胣閽苣꺁苣节蓧릊臣鞁臣蒁胣ꪏ믤鎁臣ꊖ闦꾁볯閃苣벃苣뮃菣벃菣ꮃ볯暈捡⁥潮浲污볯貁菣뎃菣ꦃ苣뎃臣骮뻧ꮁ郥뒇臣ꚁ臣讂臣ꢁ苣膃苣莃苣馁苣芀臣ꢁ臣낁胣暁捡ㅥ臣閳럧銂賦ꆁ〨〬ㄬ膀慦散ꢁ慦散ꢁ臣鎖臣㦫ꚺ臣䚮佒呎菣뎃菣貁臣讂ꃥ袐胣暁捡㉥臣閳럧꾁⴨ⰱⰰ⤰臣ꪁ苣ꪁ臣貂臣ꪁ苣ꪁ臣芀臣꺁雩낕臣膀뷤覂臣꺁鏦鲽臣놤闦馁苣讁볯ꒁ臣誂菣ꊃ菣벃觥誂뷥ꚁ볯膀臣龁臣鎁臣ꊖ闦貁꟨몱臣趁臣蒁闥財苣몙ꛨ鞁臣ꢁ臣ꮁ䅆䱉剕銂뿨馁胣䦂⁮䐳䙟乕⹃偃⹐⼪湩⁴楦彸䐳瘨楯⥤㬠⨯⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪臣貂臣膀菣벃菣꺁꣨袨臣袂臣못胩ꮁ铧蒁苣뮸ꛨꪁꯩ뒰뫦䊖湥⁤潍敤龩菨ꞁ臣讂胣鶁臣ꢔ胩꾁곦꺁胩誂臣芁苣㪋醃菣袃臣邵郥閁苣讂苣蚁臣袼迥붃臣芁苣뒠郥覼胣ꊝ臣ꊝ臣꺁雩ꮁ菣뎃菣ꦃ苣뎃苣鲽苣芀臣꺁雩낕臣膀菣벃菣뚈뷤銂郥蚐賥馁苣龁苣ꮁ뷤覂苣龁胣骀룥꾁菣벃菣銂迦辁臣ꮁ苣벃菣醃菣蚃苣꺁䅃鞃菣낂菣ꂃ臣뾽苣貂苣芀敂摮䴠摯汥臣䎯䑁苣릂菣ꂃ苣뎂菣袃菣벃菣鞁臣蒁臣ꞁ胣醈胣꺁鯧蒚臣ꢁ臣ꚁ臣꺁迦뮔볯覃菣벃苣뎃苣覼臣颍臣讂苣莃苣꺁鯩袐臣芁苣芀臣꺁臣膂胣醃菣袃臣讧胩銂ꛨꒁ臣讂臣꾁胣覃菣벃苣뎃苣銂裥邞臣ꪁ臣貂臣ꪁ苣ꪁ臣芀臣꺁뻥ꮁ裦薀臣膀菣벃菣꺁菣뎃菣ꦃ苣뎃臣ꊝ苣鲽苣鎁臣貁臣趁苣芀臣ꂁ臣膀臣꺁藥鮊菣궃菣ꒂ菣낂臣鞁臣鞁臣際飦ꞁ臣讂胣ꒁ臣誂胣ꊝ胣鶁臣ꚁ觧ꮁ菣뎃菣ꦃ苣뎃臣肸蓦ꮁ껥ꦾ臣貂臣蒁臣蒁胣鎁臣鎁臣貁ꓥ辁臣ꊂ菣ꪃ苣벃苣ꞃ菣ꮁ藥骀臣讂闥財臣芁苣龁苣膀臣꺁雩낕臣䊌湥⁤潍敤꺁룤ꢃ臣ꪁ臣ꚁ臣讂胣閁苣ꮁ胣䊁湥⁤潍敤ꮁ臣꺁雩낕苣龮ꏨ馁苣鎁臣ꮁ苣誂胣䎁䑁苣릂菣ꂃ臣肸菩銂뷥邈臣讂鷩鲤蟥붂菣袃苣Ꞃ苣銂냧ꖕ賥馁苣芀臣꺁雩낕臣誁臣ꚁ裦薀臣膀鷩꺁苣莃苣貁胣鞃菣벃菣뮃菣벃菣ꮃ볯뎹鷩꺁雦醐苣骮뻧馁苣覼臣뾪鋥馁苣릖돦ꞁ胣ꚷ臥꺁뷧骷볯ꮃ菣ꮃ볯ꮁ뻥ꎁ臣莏臣覂苣讂臣ꢁ苣뎃껥馁苣芀鿥겜髧ꮁ胣鎁臣ꊖ闦꾁胣蒐맥ꊝ苣蚈鯩鞁臣讦臣뒠郥ꮁ臣릁臣꺁맥ꊝ臣鶁苣ꪇ뷤ꞁ臩ꎭ臣芁苣鎁臣銂菦骮臣讂胣龁臣鞁臣꺁雩낕臣膀髩ꖎ맥ꊝ臣醐臣貁胣鶁苣覂臣鎖臣芁苣馃菣覃菣ꒂ菣ꮁ꿥鞁臣ꦁ귦ꞁ臣讂臣ꢁ苣膦뇦鞁臣蒁胣鎁臣ꊖ闦꾁胣醃菣袃臣骎臣貁苣궃믤隤臣뒠郥ꮁ胣邁苣辁觨붥臣龩菨鞁臣蒁胣鎁臣ꊖ闦꾁胣醃菣袃臣㎮ⵄ菣벃苣ꞃ菣ꢁ菣벃菣꺁맥ꊝ菣벃苣ꞃ菣꺁룤릖臣ꒁ臣ꚁ菣뎃菣ꦃ苣뎃苣龔裦馁苣꺁臣뾽臣讂胣龁臣鞁菣벃菣꾁胣醃菣袃臣뎹鷩邃菣뢂菣뎃臣뺁臣꾁䐳菣벃苣ꞃ菣꺁臣骁苣讁苣膌臣鎁臣貁臣趁胣鶁臣ꆸ雦銂賦ꒁ臣ꢁ臣ꞁ臣ꪁ臣芀臣ꪁ苣ꆁ胣㎁ⵄ菣螃苣꺁臣릁臣꺁䐳邃菣뢂菣뎃臣二䱕ꞁ臣讂臣袼臣꺁ꃥ袐裦薀臣뎹鷩邃菣뢂菣뎃苣鞾苣覼胣뺁臣꾁臣릁臣꺁맥ꊝ菣벃苣ꞃ菣貁啎䱌臣ꪁ臣貂臣ꪁ苣ꪁ臣芀浉汰浥湥慴楴湯椠⁳湩䄠呕彏䕂䑎䌮偐⨮椯瑮愠瑵彯敢摮瘨楯⥤㬠⨯臣꺁雩낕臣膀䅃랂苣蚃菣ꮁ苣ꎁ臣䊦湥⁤潍敤ꮁ胩ꆿ臣貂臣螃菣뾂臣覂菣벃菣銂裥鲽臣讂臣ꢁ苣莿胩馁苣龁苣ꮁ꣨袨臣貂臣芀闥財臣膀菦놠苣ꦈ铧ꞁ臣讂苣蚁臣馁苣龁苣膀臣낁臣낁菣벃菣貁菩蚈臣ꢁ臣못胩閁苣讂臣ꢁ臣芁苣芀臣ꂁ臣辕ꇩ꾁胣醈胣貁菣벃菣꺁菣螃苣銂믥ꂀ臣讂臣趁胣ꖅ諥螃菣뾂臣醃菣袃臣뎹鷩邃菣뢂菣뎃볯䚈䅌覼臣㎨邃菣뢂菣뎃臣蒁臣貂苣ꢡ苣鞁臣蒁苣꺁臣銂뫤趉臣ꖟ苣鎁臣貁臣趁臣蒁臣ꢁ臣芁苣芀胩뢸臣貂臣㎯彄敶獲潩ꞁ臣讂胣鎁臣龁苣醈胣꾁菣閃苣ꮃ菣ꞁ胣鶁苣貁䐳菣벃苣ꞃ菣ꞁ臣讂臣뎃껥馁苣芀뻥뮁臣膀菣벃菣꺁䐳鲃菣ꎂ臣馁臣ꚁ臣못胩閁苣龁駦릂臣膀裦薀臣ꖅ諥螃菣뾂臣㎌ⵄ菣벃苣ꞃ菣ꞁ臣讂臣ꢁ苣膃苣莃苣ꞁ臣讂胣节臣节䐳邃菣뢂菣뎃臣ꪁ臣貂臣膀裦薀臣馁臣ꚁ臣㎮ⵄ菣벃苣ꞃ菣銂맥ꊝ菣벃苣ꞃ菣ꮁ꟧閁臣醁苣낁臣覂臣蒁胣鎁臣ꊖ闦꾁胣鎁臣꺛髧꺁臣膂臣꺁臣궨꣨閁苣ꚁ臣誂胣隻臣蒁臣ꪁ苣꺛髧ꮁ苣뾽铧馁苣릁臣ꞁ臣蒁胣鎁臣ꊖ闦꺁ꫨꢔ臣膀苣릂菣ꂃ苣꾂菣莃苣ꖃ臣讂胣鎁臣ꊖ闦꾁臣骁裥膂臣膀菣螃苣꺁맥ꊝ菣벃苣ꞃ菣袼䱆呁볯貁啎䱌臣芁苣讁郥讁苣膃苣莃苣馁苣芀臣貂臣二䱕ꞁ臣蒁ꃥ袐胣鎁臣ꊖ闦꾁䐳邃菣뢂菣뎃苣뮧臣ꪁ臣芀吠䑏⁏›楲桧⁴潮ⱷ椠⁴湯祬洠癯獥映捡獥⨮瘯楯⁤䵂偟剁㩔洺癯彥䐳瑟彯汦瑡瘨楯⥤㬠⨯⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪䈪湥⁤潍敤꾁胣醃菣袃鏦鲽苣ꆸ雦꺁雦醐臣ꚇ郧ꞁ臣讂胣㪂醃菣袃臣㎮邃菣뢂菣뎃臣뒠郥膀菣벃菣꺁䐲볯뎹鷩覼菣벃苣ꞃ菣銂ꛨꒁ臣讂胣ⶂ䐲볯뎹鷩覼菣벃苣ꞃ菣꺁ꃥ袐胣鶁苣銂触骮臣袱鯦醃菣ꆃ菣뾂臣閃苣ꮃ菣馁苣芀䵂偁꾁臣ꢁ苣ꦁ臣뒠郥膀볯ꒁ臣邃菣뢂菣뎃볯㊈誁苣뎁䐳볯꺁菣벃菣銂鳦馁苣꺁臣膀臣貂苣꺁룤ꮲ胦銂뛧膌臣讂臣ꢁ臣趇ꛨꞁ臣讂胣䊂䅍䥐臣骀룥膀諥螎胦꺁郧놔臣覂胣醃菣袃臣㊮邃菣뢂菣뎃臣㎨邃菣뢂菣뎃苣躘ꓧ蒚臣꾁꣨鞮臣骁胣讁苣誂臣膦뇦ꮁ뿥颁臣袼菣벃苣벃臣袨껧銂ꛨ花臣讂臣趁臣뾁볯鶁苣覂苣袨껧馁苣芀臣ꢁ苣ꦁ臣뒠郥醈胣꾁胣芁苣肉껥꺁菣螃苣꺁菣벃苣ꞃ菣讁苣ꖈ臣鲃菣ꎂ臣邃菣뢂菣뎃臣鲽苣貂苣覤뷥袼菣ꦃ菣릂菣ꦂ菣ꆃ菣랂菣뎃볯銂鿧讂臣醁臣膍裥ꞁ臣讂胣㊂ⵄ朦㭴䐳ꓥꊽ臣㎨ⵄ朦㭴䐲ꓥꊽ臣꺁雩ꮁ臣醼臣꺁臩蒁臣芁苣芀胩뢸䐲☭瑧㌻覤뷥꾁菣벃苣벃臣袂臣ꚁ賦骮臣貂胣ꚃ菣뚂菣꾁믤辄臣릖돦ꞁ臣貂苣龮雦ꞁ臣讂볯閽苣讁臣蚐铧ꮁ苣誂뗧鲞臣趸귦ꮁ臣讂臣ꢁ臣芁苣貁胣ꢁ苣芁臣骁뷥ꊝ臣鶁臣鎁臣銂蓧隦臣讂볯芀䐳☭瑧㈻覤뷥꾁苣뎃菣ꦂ菣覃臣뺯뿥鞁胣鎁苣ꮁ臣醼臣꺁雦閳臣醁臣芁苣芀臣뺁苣膀触骮臣몛껥閁苣龁䐳邃菣뢂菣뎃臣ꒁ臣ꚁ胣肜뗧蒚臣醃菣袃臣뎹鷩邃菣뢂菣뎃臣醼臣ꂁ臣颭鳥馁苣芀菣ꦂ菣覃臣ꊂ菣閃苣ꮃ菣꾁臣骁苣节胣醃菣袃臣袱鯦薃ꃥ銂铧蒁臣膀臣릁臣꺁䐳菣螃苣銂郥薀臣袱鯦醃菣ꆃ菣뾂臣鎾臣ꚁ胥ꖈ臣袨껧馁苣芀룤겈臣膀臣貂苣꺁ꓥꊽ臣꾁胣醃菣袃蛥꺁臣릁臣꺁菣螃苣貁胢暙慬馀菣벃苣ꞃ菣讁臣龁臣馀䐳瘭牥楳湯胢銂鳦馁苣鎁臣貁ꛨ花臣貂苣芀臣뺁苣膀뷥鶈䐳菣벃苣ꞃ菣꺁菣벃菣貁臣讂ꃥ袐胣㊁ⵄ朦㭴䐳ꓥꊽ苣뾽铧馁苣趉臣膀臣貂苣ꊂ菣閃苣ꮃ菣鞁臣醁苣낁臣覂臣蒁胣ꊂ菣閃苣ꮃ菣꾁胢暙慬馀苣鲽苣몇臣芀菣ꦂ菣覃臣馀䐳瘭牥楳湯胢銂뷤誂蟥馁胣ꚃ菣뚂菣꾁鳦鶈臣膀菣ꦃ菣袃菣邃菣뢂菣뎃臣㎋ⵄ菣벃苣ꞃ菣꺁臣骁苣讁苣螌껥鞁臣醁苣낁臣覂臣蒁胣⪂⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⼪⨯臣꺁雩낕臣膀䵂偁ꮁ볯閃菣莃菣讁苣覼菣벃菣꺁䐳菣벃苣ꞃ菣銂볥뚈髧ꮁ꣨鞮臣鮁苣芀藥鎽髧ꮁ䵂偁꾁胣ꊝ裢뒩裢馃菣覃菣ꒂ菣꺁臣릁臣銂菣Ꞃ菣꾂臣膀䐳菣벃苣ꞃ菣貁雦鞁臣ꪁ臣貂臣膀䵂偁꾁䐲☭瑧㌻覤뷥銂铧蒁臣閃菣莃菣讁苣肜雦꺁䐳菣벃苣ꞃ菣銂꣨鞮臣讂胣㊂ⵄ朦㭴䐳ꓥꊽ臣낖臣辁臣蒁ꃥ袐胣䊁䅍䥐臣肜雦꺁鳦릊臣㊪ⵄ朦㭴䐳ꓥꊽ臣袨껧銂ꧨ뾁苣芀臣龁胣芁苣馃菣覃菣ꒂ菣ꮁ臣蒁臣낖臣蒁䐳邃菣뢂菣뎃臣袨껧閁苣讂臣趁胣䊁䅍䥐臣鶈苣ꮁ髩ꖎ臣讂菣뎃菣ꦃ苣뎃苣ꦁ郥閁臣讂胣⪂瘯楯⁤牢湩彧䐳畟彰潴摟瑡⡥潶摩 ⼻⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪㈪ⵄ朦㭴䐳ꓥꊽ雩낕⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⼪⨯臣꺁雩낕臣馁臣ꚁ臣覤뷥銂苣ꒂ菣뎃菣ꎂ菣ꎂꓥꊽ볯榈敤瑮瑩⁹牴湡晳牯慭楴湯볯ꮁ菣뮂菣袃臣讂胣閁苣ꮁ臣꺁雩낕臣膀臣릁臣꺁菣뎃菣ꦃ苣뎃臣誁臣讂胢抙湥楤杮獟慴畴馀ꓥ낕苣䚒䱁䕓臣궨껥馁苣芀臣覂臣鎁臣ꊖ闦꾁胣馁臣ꚁ臣ꊝ臣馁臣ꚁ臣㎮邃菣뢂菣뎃苣馀潮⵴灵琭ⵯ慤整胢袼鷩肜雦覼臣風臣貁胣龁臣鞁臣꺁蛥袨껧꾁ꇨꪁ苣ꪁ臣芀䐳☭瑧㈻覤뷥꾁菣뮂菣袃臣趁臣蒁臣ꞁ胣鎁臣ꊖ闦貁䐲☭瑧㌻覤뷥꺁臣銂菣뮂菣袃臣讂臣ꢁ臣ꢳ蓦鮁苣芀⼪潶摩爠獥瑥慟汬瑟慲獮潦浲瑡潩獮瘨楯⥤㬠⨯菣벃菣꺁䐲☭瑧㌻覤뷥銂菣뮂菣袃臣讂胣馀潢祤胢꾁胣ꊂ苣螃菣蚃苣蚃苣覤뷥ꮁ臣讂ꓥꊽ苣膌臣ꊝ臣芁苣芀믤꺁菣螃苣꾁胣鎁臣몟鳦鲃菣ꎂ볯馃菣릂菣鲃菣ꎂ볯ꮁ雩馁苣袱鯦薃ꃥꮁ뻥ꎁ臣膀郥薀臣覤뷥銂꣨骮臣讂胣鎁臣ꊖ闦꾁胣馁臣ꚁ臣覤뷥趯뷤袼菣袃菣莃苣릂볯銂鯦낖臣讂胣몟鳦蒚臣鎁臣ꊖ闦ꞁ臣膀菣벃苣벃臣醃菣袃藥鎽臣財臣ꎁ臣麛믨蒂꟧開臣馁臣ꚁ苣随苣袶臣袼苣뎃菣ꖂ菣覼臣趁苣芀⼪潶摩爠獥瑥灟牡彴䐲潴䐳瑟慲獮潦浲瑡潩獮䈨彍䐳䉟䑏⁙截獡彥潢祤 ⼻⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪鎁苣覂臣ꊖ闦꾁胣ꚃ菣뚂菣ꮁ菣벃菣꺁鯥ꊻ臣龁臣뮧该銂껥붖臣鮁苣芀臣ꢁ臣낁胣袱鯦꺁臣趁胣ꚃ菣뚂菣꾁菣벃菣꺁迥ꊻ苣貸鳦馁苣鎁臣貁臣讂胣鎁苣覂臣ꊖ闦꾁胣醃菣袃藥鎽臣螝룤ꮁ뷤ꢔ臣讂胣馁臣辂臣膀臣릁臣꺁鷩銈ꧧ銈菣뎃菣ꦃ苣뎃臣ꢅ臣貐꟦ꮁꓥ隌臣讂胣鎁苣覂臣ꊖ闦貁䐲☭瑧㌻覤뷥ꞁ臣讂臣ꢁ臣ꢳ蓦鮁苣芀臣ꪁ苣ꆁ胣鎁苣覂臣ꊖ闦꾁菣벃菣꺁䐳菣벃苣ꞃ菣ꂁ臣銂ꓥ뒛臣讂臣膀臣貂苣꺁雩낕臣醃菣袃臣뎹鷩邃菣뢂菣뎃臣袨껧銂ꛨ馁苣芀鿥겜髧ꮁ臣貂苣꺁雩낕臣龮雦馁苣꾔룤꺁臣ꢁ臣膀臣릁臣꺁菣螃苣ꮁ믤辚臣讂䐲㌭覤뷥銂ꓥ뒛臣膀臣릁臣꺁菣螃苣꺁䐳邃菣뢂菣뎃苣馀潮⵴灵琭ⵯ慤整胢袼鷩肜雦覼臣風臣鎁臣ꞁ臣讂胣⪂⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪⨪⼯醃菣袃藥鎽苣骷苣뢻臣肸껥꺁꟨ꚺ볯ꦃ苣ꊂ菣颍뷤覼臣麛믨閁臣讂胣ꎭ臣릖郥꾁胣骷臣릖郥銂ꛨ龁臣趁臣芙꣨麛苣ꞁ臣讂胣⪂瘯楯⁤潲慴整䈨彍䥌䕎挠湯瑳愦灭※楬敮‬潤扵敬挠湯瑳湡汧⥥㬠⨯菣벃菣ꢅ뷤銂臣꺁菣꾂菣ꮃ臣뮧该馁苣⪋瘯楯⁤牴湡汳瑡⡥䵂噟䍅佔⁒潣獮♴浡㭰琠慲獮慬楴湯癟捥潴⥲㬠⨯臣꺁ꓥꊽ苣醃菣袃臣ꦁ铧馁苣⪋瘯楯⁤牴湡晳牯⡭䵂呟䅒华但䵒挠湯瑳愦灭※牴湡晳牯慭楴湯 ⼻⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪但䑌雩낕胣䚂䱏⹄偃ꊃ苣ꖃ菣ꮃ蛥⪅⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪⨪⼯醃菣袃臣㎮邃菣뢂菣뎃苣袨껧馁苣芀臣꺁雩낕臣膀菣벃苣뮃菣螃苣ꮁ뻥ꎁ臣醃菣袃臣㎮邃菣뢂菣뎃苣袨껧馁苣芀臣뺁苣膀胢抙獡彥潢祤胢꾁闧뺁苣膀菣벃菣꺁껦誂臣ꢃ裥꾁该辁胣鎁苣뺁臣醃菣袃藥鎽臣麛믨蒂꟧開苣龮ꇨ鞁臣뒠郥膀鯥ꊻ臣龁臣뮧该꾁臣꺁鏦鲽臣貾臣节鳦릊臣芁苣꺁臣ꢳ蓦鮁苣芀胩뢸菣벃苣벃臣膀臣辁臣讁臣馃菣覃菣ꒂ菣뮃菣ꦃ菣벃苣銂꣨骮臣ꚁ臣覂胣鎁臣ꊖ闦銂釥뎁蟥鞁臣醃菣袃苣뒛雦馁苣鎁臣銂룥鮜臣讂胣鎁臣ꊖ闦꾁胣覤賥馁苣袼鳦辰駩ꚺ臣覤賥覼菣螃苣꺁ꓥꊽ꿦鎽臣醁苣袨껧馁苣芀郥鲃菣ꎂ臣㎮邃菣뢂菣뎃臣膦뇦ꮁ뿥颁臣袼菣벃苣벃臣袨껧銂ꛨ花臣讂臣趁臣뾁볯袨껧閁苣讂胣鎁臣ꊖ闦꾁胣蒐菣뎃菣ꦃ苣뎃臣ꆃ菣邃ꓥ낕胢抙湥楤杮獟慴畴馀苣ꢔ臣ꚁ胣馃菣覃菣ꒂ菣銂뇥늛臣讂臣Ꚑ臣銂뇦膂苣芀菣벃苣ⶹ菣螃苣꺁䐲☭瑧㌻覤뷥貁雦鞁臣ꪁ臣뒠郥膀但䑌臣鶁苣銂苣ꒂ菣뎃菣ꎂ菣ꎂꓥꊽ臣ꪃ苣莃菣馁苣꺁臣ꢳ蓦鮁苣芀⼪湩⁴潦摬䈨彍䐳䉟䑏⁙截獡彥潢祤 ⼻鎁臣ꊖ闦꾁胣蒐菣뎃菣ꦃ苣뎃臣ꆃ菣邃ꓥ낕胢抙湥楤杮獟慴畴馀臣䚌䱁䕓臣芁苣ꢁ菦骮臣袼䅆卌ꞁ臣蒁ꃥ袐臣膀臣꺁雩낕臣馀敢摮湩彧瑳瑡獵胢銂䅆卌ꮁ꣨骮臣讂볯膀臣覂臣袱鯦馁苣馃菣覃菣ꒂ菣꺁菣릂菣貁藩鞈胢抙湥汤湩彥牡慲馀臣芁苣ꢁ菦骮臣讂볯超裥꺁闩閁臣馀畮扭牥潟彦敢摮楬敮馀볯鎁臣銂駩趁胣貐臣鎁臣銂껥財臣讂胣鎁臣ꊖ闦貁뗧讂臣趁臣膀郥馃菣覃菣ꒂ菣꺁菣뎃菣覤闦馀敢摮湩彧瑳瑡獵胢꾁胣馃菣覃菣ꒂ菣貁뇥늛臣貂臣讁郥讁苣ꢡꓧ馁苣芀⼪湩⁴潦摬䈨彍䐳䉟䑏⁙截獡彥潢祤‬䵂䉟久䱄义⁅截湥汤湩彥牡慲孹ⱝ氠湯⁧畮扭牥潟彦敢摮楬敮⥳㬠⨯臣꺁雩낕臣膀菣벃菣꺁뇥늛ꃩ趽臣誁臣讂鳦鶈臣溮菣뎃菣ꦃ苣뎃苣閃苣ꮃ菣馁苣芀⼪湩⁴潦摬獟煥敵据⡥䵂㍟彄佂奄⨠慢敳扟摯ⱹ椠瑮渠 ⼻㌪鲃菣ꎂ臣馁臣ꮁ臣꺁䐲☭瑧㌻覤뷥趯뷤銂꣨鞮臣ꚁ臣讂ꃥ袐胣鎁臣ꊖ闦꾁触骮臣馃菣覃菣ꒂ菣ꮁ臣蒁臣覤뷥趯뷤銂꣨鞮臣讂胣鎁臣ꊖ闦꾁闦薀臣论鿦銂菦骮臣讂볯鎁苣覂臣论鿦꾁菣Ꞃ菣꾂臣貂臣蒁볯㪉鎁臣馃菣覃菣ꒂ菣꾁菣螃苣ꮁ髩ꖎ臣ꚁ臣讂胣ⶂ臣꺁菣螃苣꾁臣ꞁ臣肜雦꺁ꓥꊽ꿦鎽苣覜臣讂胣ⶂ臣꺁菣뎃菣ꦃ苣뎃臣肜雦꺁散瑮牥江湩彥䐲苣覜臣讂胣鎁苣覂볯ꒁ臣ꊖ闦ꞁ臣膀菣뎃菣ꦃ苣뎃臣㊌궸뿥骷苣覜臣讂臣ꢁ臣膦뇦閁苣讂臣ꞁ돦辄臣袂胣鎁苣꾁臣龁胣馃菣覃菣ꒂ菣ꮁ맥ꊝ臣芁苣鎁臣銂苣辄釥馁苣芀胦붃룤꺁郧놔臣覂胣鎁苣覂臣ꊖ闦꾁菣뎃菣ꦃ苣뎃臣誁臣讂맥ꊝ臣覜蓧銂菣Ꞃ菣꾂臣骁胣讁苣誂臣馃菣覃菣ꒂ菣ꮁ맥ꊝ臣芁苣节臣ꢁ菦骮臣膀臣貂苣뒛軦蒚臣芏藧馁苣芀臣꺁雩낕臣䚯䱏ꮁ苣ꎁ臣뾽苣貂苣芀⼪湩⁴敢摮扟湥汤湩彥牷彴䐳扟摯⡹䵂㍟彄佂奄⨠潢祤⼠‪楦楮桳摥戠摯⁹⼪‬䵂䉟久䱄义⩅畣牲湥彴敢摮楬敮⼠‪敢摮楬敮眠潨敳琠慲獮潦浲瑡潩⁮敷愠敲挠浯異楴杮⨠Ⱟ䵂呟䅒华但䵒⨠晴⼠‪瑳牡⁴楷桴琠楨⁳牴湡晳牯慭楴湯⨠⤯㬠⨯菣뎃菣ꦃ苣뎃臣馁臣ꮁ껥邈臣ꚁ臣誂胣醈胣貁䐳菣螃苣銂꣨鞮臣ꚁ臣讂臣ꢁ苣꒙臣膀郥颁胣咂楨⁳畦据楴湯椠⁳獵摥戠⁹但䑌⨮椯瑮戠湥彤䐳扟摯役牷彴敢摮楬敮䈨彍䕂䑎䥌䕎⨠畣牲湥彴敢摮楬敮⼠‪楦楮桳摥戠湥汤湩⁥⼪‬䵂㍟彄佂奄⨠潢祤⼠‪潢祤眠潨敳琠慲獮潦浲瑡潩⁮敷愠敲挠浯異楴杮⨠Ⱟ䈠彍剔乁䙓剏⁍琪⁦⨯猠慴瑲眠瑩⁨桴獩琠慲獮潦浲瑡潩⁮⼪ ⼻⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪唪䙎䱏ꊖ闦芀乕但䑌䌮偐菣뢂菣벃菣薆⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⼪⨯臣꺁雩낕臣醃菣袃藥鎽苣ꊂ菣閃苣ꮃ菣馁苣芀臣꺁雩낕臣膀軦骶臣貂臣醃菣袃臣蒐苣뎃菣벃菣뎃菣ꮁ臣趁胣螃菣ꦂ菣袃臣馃菣릂菣鲃菣ꎂ苣뢁諦馁苣芀臣꺁雩낕臣膀菣벃菣貁苣뎃菣ꦂ菣覃臣貂苣ꢁ臣ꮁ胣馃菣릂菣鲃菣ꎂ臣龎苧⢹ⰰⰰ⤰臣趇臣讂苣蚁臣醃菣袃苣墒夭맥ꊝ臣뮧该閁臣讂胣鎁臣ꊖ闦꾁鳦鶈臣蒐䐳菣螃苣ꮁ臣蒁臣㎦ⵄ朦㭴䐲ꓥꊽ苣袨껧鞁胣鶁苣讁苣蒐䐳鲃菣ꎂ臣ꒁ臣ꚁ晗慬銂꣨鞮臣膀곦ꮁ晗慬銂菣ꪃ菣뎃苣鞁胣肜뻥ꮁ맥ꊝ苣袨껧馁苣芀臣꺁雩낕臣膀菣벃苣ⶹ菣螃苣ꢁ臣ꚁ鷩⶞啎䱌臣閳럧銂賦ꆁ胣肜냥榏銂賦ꒁ鷩銂臩麊臣讂胣鎁苣貁룤꾏菨ꞁ臣讂ꃥ袐胣鎁臣ꊖ闦꾁胣馃菣릂鲃菣ꎂ臣鞁臣麝中䱕꺁돦骷苣袨껧馁苣鎁臣貁臣趁苣몟ꓧ꺁苣벃菣Ꞃ苣銂鳦馁苣肜裥꺁菣뎃菣ꦃ苣뎃苣뢁諦馁苣芀臣꺁雩낕臣膀䵂偟剁㩔町普汯⡤䵂㍟彄佂奄⨠慢敳扟摯⥹苣ꢔ臣ꚁ胣醃菣袃臣ꖎ뛧閁苣龁苣뎃菣벃菣뎃菣꺁臣릁臣銂苣뎃菣ꦂ菣覃臣讂胣鎁臣ꊖ闦꾁胣ꢅ鷩蒚臣邈諥鞁臣뒠郥ꮁ銂뿨鞁胣醃菣袃臣肸菩ꞁ苣뎃菣ꦂ菣覃臣놤闦鞁臣뒠郥ꮁ臣ク苣钿臣芀臣꺁雩낕臣뺁臣鶈苣ꮁ胣馁臣ꚁ臣閃苣벃苣뮃菣벃菣ꮃ臣뺏ꇨ꺁菣뎃菣ꦃ苣뎃臣뺯臣ꚁ臩ꎭ臣芁苣鎁臣銂菣Ꞃ菣꾂臣讂胣鎁臣ꊖ闦꾁胣蒐䐳鲃菣ꎂ臣뺏ꇨ㎌ⵄ菣벃苣ꞃ菣銂뷤ꢔ臣讂臣ꢁ臣ꢳ蓦鮁苣芀苣뎃菣ꦂ菣覃苣財臣蚁臣꾁胣馁臣ꚁ臣㎮ⵄ菣벃苣ꞃ菣貁雦鞁臣ꪁ臣ꚁ臣ꪁ臣貂臣ꪁ苣ꪁ臣芀臣꺁雩낕臣㎯鲃菣ꎂ臣낖臣蒁臣Ꚑ臣銂菣Ꞃ菣꾂臣骁胣龮髩ꮁ臣馁臣ꚁ臣㎮ⵄ菣螃苣銂鳦낖臣風臣芀臣覂臣鎁臣ꊖ闦꾁胣馁臣ꚁ臣馃菣覃菣ꒂ菣貁鳦릊臣㎪ⵄ룤莿럧銂賦ꎁ臣蒁苣ꢁ菦骮臣讂胣鎁臣ꞁ苣鎁臣ꊖ闦꾁䐳궸뿥骷苣膃苣莃苣鮁臣膀臣辂苣ꮁ迧財臣궸뿥骷苣龁臣颍臣릉蟥馁苣芀⼪湩⁴湵潦摬瘨楯⥤㬠⨯臣꺁雩낕臣膀菣벃苣ⶹ菣螃苣꺁釥늛苣궸뿥ꢁ臣讂菣벃菣꺁軦骶苣뎃菣벃菣뎃菣ꂁ臣銂苣뎃菣ꦂ菣覃臣讂胣鎁臣ꊖ闦꾁胣醃菣袃藥鎽苣ꊂ菣閃苣ꮃ菣馁苣䊋彍䅐呒㨺湵潦摬瘨楯⥤雩낕臣袂臣ꚁ뷤辂苣讂胣鎁臣ꊖ闦꾁胣ꖎ뛧뎂菣鶃菣趃菣袃臣蒐䐳鲃菣ꎂ臣ꒁ臣ꚁ雦鞁臣㎄ⵄ朦㭴䐲ꓥꊽ苣袨껧鞁胣ꆬ臣䊫彍䐳䉟䑏㩙挺浯異整晟慬彴牦浯㍟⡄ꊖ闦銂铧蒁臣蒐䐳鲃菣ꎂ臣ꒁ臣ꚁ雦鞁臣뎹鷩邃菣뢂菣뎃苣袨껧馁苣芀菣벃苣뮃菣螃苣貁鷩ꞁ臣誂胣ꖅ諥閃菣낂臣和啒ꮁ꣨骮臣貂臣蒁苣뒠郥膀臣꺁雩낕臣肜裥ꮁ껥財臣讂臣ꢁ臣膀臣릁臣꺁菣Ꞃ菣릂菣躃菣麃菣貁迧財臣馃菣覃菣ꒂ菣ꮁ꿥鞁臣ꦁ귦ꞁ臣讂臣ꢁ苣膃苣莃苣馁苣鎁臣ꞁ臣讂胣龁臣鞁臣貂臣膀臣꺁菣벃苣뮃菣螃苣袼鷩覼苣궸뿥ꢁ臣讂軦骶苣뎃菣벃菣뎃菣ꮁ駩覂苣讂胣鎁臣ꊖ闦꾁郥㎄ⵄ菣螃苣꺁迧財䐳邃菣뢂菣뎃苣뾽铧馁苣꺁臣ꢳ蓦鮁苣芀臣꺁雩낕苣벑臣몇臣趉臣膀臣릁臣꺁䐳邃菣뢂菣뎃臣肜雦ꞁ臣讂臣ꢁ苣몢ꫨ鮁苣芀臣꺁雩낕臣龮髩膀臣貂臣ꚇ郧馁苣馁臣ꚁ臣㎮ⵄ菣螃苣銂鳦낖臣風臣芀⼪湩⁴湵潦摬䈨彍䐳䉟䑏⁙截獡彥潢祤‬湩⁴档捥彫慦散湟牯慭獬㴠〠 ⼻㌪鲃菣ꎂ臣㎮ⵄ朦㭴䐲ꓥꊽ꿦鎽臣馁臣ꮁ꣨鞮룦뾁臣뒠郥膀臣꺁雩낕臣肉껥꺁菣뎃菣ꦃ苣뎃臣ꒁ臣ꚁꓥꊽ꿦鎽苣袨껧馁苣芀臣꺁雩낕臣낕胣꺁뫤蒟苣뎃껥馁苣袼臣貂苣꺁뫤蒟臣膃苣莃苣閁苣ꪁ臣覼ⴺ臣꺁菣뎃菣ꦃ苣뎃臣鲃菣ꎂ臣ꎚ軦鞁臣蒁苣芀鎁臣鲃菣ꎂ臣馁臣ꮁ鳦낖臣覤뷥趯뷤銂鳦馁苣芀鎁臣馃菣覃菣ꒂ菣꾁鳦낖臣掮湥整彲楬敮㍟銂鳦馁苣芀臣貂苣銼臣꺁雩낕臣꾁胣馃菣覃菣ꒂ菣貁룤莿럧銂鳦馁苣鎁臣貁ꛨ花臣貂苣꺁臣ꢳ蓦鮁苣芀臣貂臣뺁臣膀菣뎃菣ꦃ苣뎃臣麝中䱕꺁䐳邃菣뢂菣뎃臣芁苣鎁臣銂苣辄釥馁苣芀胦붃룤꺁郧놔臣覂胣鎁苣覂臣ꊖ闦꾁菣뎃菣ꦃ苣뎃臣麝中䱕꺁䐳邃菣뢂菣뎃臣芁苣鎁臣銂菣Ꞃ菣꾂臣骁胣讁苣誂臣馃菣覃菣ꒂ菣貁鷩⶞啎䱌臣㎮ⵄ菣벃苣ꞃ菣ꞁ臣讂苣꺁臣뎃껥鞁胣鶁苣銂鯧ꖎ髧ꮁ迥ꞅ臣讂胣鎁臣ꊖ闦꾁乕但䑌臣袂臣ꚁ뷤辂苣讂胣鎁臣ꊖ闦꾁껥鮚臣꾁敢摮扟湥汤湩彥牷彴䐳扟摯⡹⸮⤮臣蚀臣芁苣鎁臣ꮁ돦辄臣袂胣⪂椯瑮甠普汯彤敢摮楬敮睟瑲㍟彄潢祤䈨彍䐳䉟䑏⁙截摯⁹⨯映湩獩敨⁤潢祤⨠Ⱟ䈠彍䕂䑎䥌䕎⨠畣牲湥彴敢摮楬敮⼠‪敢摮楬敮眠潨敳琠慲獮潦浲瑡潩⁮敷愠敲挠浯異楴杮⨠Ⱟ䈠彍剔乁䙓剏⁍琪⁦⨯猠慴瑲眠瑩⁨桴獩琠慲獮潦浲瑡潩⁮⼪ ⼻馃菣覃菣ꒂ菣貁臣ꞁ臣貮裦鞁臣誁苣膀裦薀臣㎌鲃菣ꎂ苣袨껧鞁臣蒁苣鎁臣銂駩趁胣貐臣芀臣꺁雩낕臣喯䙎䱏ꮁ苣ꎁ臣뾽苣貂苣芀臣꺁雩낕臣龮髩ꮁ臣抯湥彤䐳扟摯役牷彴敢摮楬敮⸨⸮꺁胩ꞁ臣讂臣ꢁ臣ꢳ蓦鮁苣芀⼪湩⁴湵潦摬㍟彄潢祤睟瑲扟湥汤湩⡥䵂䉟久䱄义⁅挪牵敲瑮扟湥汤湩⁥⨯戠湥汤湩芵뫤⪆Ⱟ䈠彍䐳䉟䑏⁙截摯⁹⨯醈胣貁ꓥꊽ苣袨껧鞁臣蒁苣ꢁ臣趂臣鲃菣ꎂ⨠Ⱟ䈠彍剔乁䙓剏⁍琪⁦⨯鎁臣覤뷥讁苣讖꟥馁苣₋⼪ ⼻⨪⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪鎁臣ꊖ闦꾁瀢灡牥洠摯汥漠⁦桴獩瀠牡≴볯鎁臣醃菣袃臣骃菣醃菣뮃菣螃菣覼苣钿臣芀菣벃菣벃菣ꊃ菣ꮃ臣꾁胣骎臣貁ꞁ臣誂胣馃菣覃菣ꒂ菣꺁跥蒾臣袱鯦ꞎ駩节ꞁ臣讂菣벃菣ꞁ臣讂胣薿ꛨꮁ뿥颁臣꺁雩낕臣膀菣뎃菣ꦃ苣뎃臣ꚃ菣뚂椭馀臣覂胢薆菩認뻥馀臣馀뇥늛軦꒙胢銂菣莃菣뎃苣鞁臣邵黦銂뿨馁胣⪂⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪‪⨪⨪⨪⨪⨪⨠⨪⨪⨪⨪⨪䈯彍䅐呒⨠慭敫灟灡牥浟摯汥搨畯汢⁥⨪湩楳敤牟摡畩⁳⨯传呕⨠Ⱟ搠畯汢⁥⨪敢摮摟摥捵楴湯⼠‪問⁔⼪ ⼻鎁臣ꊖ闦꾁胣뺏ꇨ꺁菣벃菣銂触骮臣閃苣ꒂ菣ꮁ䝐ꊽ볥ꞁ뿤颭臣讂胣傂䙇뷥込臣䎯啍臣䊮湥䍤䑁菣궃苣ꦃ菣ꮁ苣ꎁ臣뾽苣貂苣芀裦誂胥骼룤论觨붥臣醃菣袃臣鶿귥閁苣龁ꃥ袐臣咫啒銂뿨馁胣⪂椯瑮猠癡彥䝐彆楦敬䘨䱉⁅昪汩⥥㬠湩⁴慳敶偟䙇晟汩⡥档牡⨠楦敬慮敭 ⼻궃菣覃雩낕臣傯剁彔佌䑁硟䌮偐臣芁苣芀⼪楶瑲慵⁬湩⁴潬摡䘨䱉⁅昪汩⥥㬠楶瑲慵⁬湩⁴潬摡挨慨⁲昪汩湥浡⽥‪畭瑳渠瑯戠⁥啎䱌⨠⤯㬠湩⁴䵂偟剁彔潌摡䘨䱉⁅昪汩ⱥ氠湯⁧敶獲潩⥮㬠⨯뿤颭雩낕臣傯剁彔䅓䕖䌮偐臣芁苣芀⼪楶瑲慵⁬湩⁴慳敶䘨䱉⁅昪汩⥥㬠楶瑲慵⁬湩⁴慳敶挨慨⁲昪汩湥浡⁥⨯洠獵⁴潮⁴敢丠䱕⁌⼪ 紻㬠攣摮晩⼠ 䵂偟剁彔塈彘义䱃䑕䑅戼㹲颻賩겼戼㹲㌊곦莅鏦鲽臣袂臣麛믨뢻臣開髧袨껧ꮁ苣讂菣鎃苣벃苣ꞃ菣꺁뻤㲋牢ਾ潶摩䌠敂摮䅃噄敩偷牡㩴伺䱮畂瑴湯灕唨义⁔䙮慬獧‬偃楯瑮瀠楯瑮 㩻刺汥慥敳慃瑰牵⡥㬩㨺汃灩畃獲牯丨䱕⥌⼻ 敒敬獡⁥潭獵ⱥ映敲⁥畣獲牯洮江彴瑢彮灵灟楯瑮㴠瀠楯瑮搻畯汢⁥彸硥整瑮‬役硥整瑮椻瑮愠摤桟瑩瑟彯楬瑳㴠〠椻瑮瘠敩灷牯孴崴䈻彍䕖呃剏漠晦敳㭴䵂偟剁⁔瀪牡⁴‽敇䑴捯浵湥⡴⴩朦㭴敧彴慰瑲⤨刻噷搳敶瑲猻楷捴⡨汭江獡彴畦据楴湯损潨敳⥮⁻挠獡⡥佚䵏坟义佄彗位䕄㨩晩洨彩祤慮業彣潲彴散瑮牥潟⥮笠⼯唠敳⁲慨⁳畦瑲敨⁲潺浯摥椠⹮挠浯異整湟湯摟湹敟畱癩污湥⡴㬩睒摉湥楴祴慍牴硩洨彤祤彮潲彴慭牴硩㬩捽浯異整穟潯彭敲楧湯瑟慲獮慬楴湯⤨砻敟瑸湥⁴‽慦獢⠨潤扵敬⠩彭瑬扟湴摟睯彮潰湩⹴⁸‭彭瑬扟湴畟彰潰湩⹴⥸⨩†††⸲⨰摭损牵敲瑮癟敩彷潶孬崰⠯潤扵敬⠩彭汯彤敲瑣爮杩瑨㬩役硥整瑮㴠映扡⡳搨畯汢⥥洨江彴瑢彮潤湷灟楯瑮礮ⴠ洠江彴瑢彮灵灟楯瑮礮⤩‪††㈠〮洪彤畣牲湥彴楶睥癟汯ㅛ⽝搨畯汢⥥洨潟摬牟捥⹴潢瑴浯㬩敳彴敮彷楶睥癟汯浵⡥彸硥整瑮‬役硥整瑮㬩††潣灭瑵彥慰瑲扟潢⡸慰瑲‬業獟潨彷搳‬摭牟瑯浟瑡楲ⱸ洠灟牡彴散瑮潲摩‬摭灟牡彴扢硯獟穩ⱥ☠浡㭰景獦瑥㬩†洠彩扢硯楟彳灵瑟彯慤整㴠〠⼻ 癅湥琠潨杵⁨扢硯挠浯異整Ɽ眠⁥慭歲愠⁳潮⁴灵琠⁯慤整猠⁯桴瑡稠潯⵭污䑬慲偷牡⡴彭摨⥣⼻ 楷汬眠牯⁫潣牲捥汴⹹⼯丠睯琠牵⁮湯搠湹浡捩爠瑯瑡潩⁮散瑮牥椠⁦敮摥戠⹥晩 洨彤慰瑲扟潢彸楳敺せ⁝††朦㭴⸲⨲摭损牵敲瑮癟敩彷潶孬崰 籼†⼯唠敳⁲慨⁳潺浯摥椠⁮潳琠慨⁴潮⁴污⁬†⠠摭灟牡彴扢硯獟穩孥崱☠瑧※⸲⨲摭损牵敲瑮癟敩彷潶孬崱  ⁻⼯漠⁦桴⁥慰瑲椠⁳湩瘠敩⁷潶畬敭椮⡦‡摭摟湹牟瑯浟瑡楲⥸洠彤祤彮潲彴慭牴硩㴠删䍷敲瑡䵥瑡楲⡸㬩†椠⡦業獟潨彷潳楬⥤笠⼯倠捩⁫桴⁥散瑮牥漠⁦桴⁥捳敲湥琠⁯楦摮瀠楯瑮漠⁮汣浵⁰潴爠瑯瑡⁥牡畯摮椮⡦睒楐正捓湥⡥彭捳湥ⱥ洠潟摬牟捥⹴楲桧⽴ⰲ洠潟摬牟捥⹴潢瑴浯㈯‬彭慣敭慲‬愦灭活灟捩⥫ 楻⡦彭楰正琮灹⁥㴽爠乷偁䍉佋䩂䍅⥔笠††††⼯丠⁯汣浵⁰慷⁳楰正摥‮††洠摟湹浡捩牟瑯损湥整⁲‽䵂偟䥏呎〨〮‬⸰ⰰ〠〮㬩敽獬⁥晩洨灟捩⹫祴数㴠‽睲䥐䭃䱃䵕⥐笠††††††††⼠ 潓敭挠畬灭眠獡瀠捩敫㭤瀠潲散獳椠⹴敶瑲㴠洠灟捩⹫扯敪瑣挮畬灭眮灣楯瑮※洠摟湹浡捩牟瑯损湥整⁲‽䵂偟䥏呎瘨牥⹴ⱸ瘠牥⹴ⱹ瘠牥⹴⥺紻絽汥敳笠†彭祤慮業彣潲彴散瑮牥㴠䈠彍佐义⡔⸰ⰰ〠〮‬⸰⤰紻業摟湹浡捩牟瑯损湥整彲湯㴠㬱敽獬⁥捻浯異整湟湯摟湹敟畱癩污湥⡴㬩晩洨彤祤彮潲彴慭牴硩 睒敄瑳潲䵹瑡楲⡸摭摟湹牟瑯浟瑡楲⥸活彤祤彮潲彴慭牴硩㴠丠䱕㭌†業摟湹浡捩牟瑯损湥整彲湯㴠〠紻†牢慥㭫†慣敳匨䱅䍅彔䉏䕊呃当位䕄㨩††晩渨汆条⁳愦灭※䭍䍟乏剔䱏愩摤桟瑩瑟彯楬瑳㴠ㄠ椻⡦‡業獟潨彷潳楬⥤笠††⼯圠物晥慲敭戠楥杮搠獩汰祡摥‬桷捩⁨敭湡⁳灏湥䱇瀠捩楫杮朮䝬瑥湉整敧癲䜨彌䥖坅佐呒‬楶睥潰瑲㬩汧慍牴硩潍敤䜨彌剐䩏䍅䥔乏㬩汧畐桳慍牴硩⤨朻䱬慯䥤敤瑮瑩⡹㬩汧偵捩䵫瑡楲⡸搨畯汢⥥潰湩⹴ⱸ⠠潤扵敬⠩彭汯彤敲瑣戮瑯潴⁭‭潰湩⹴⥹‬⸳ⰰ㌠〮‬楶睥潰瑲㬩汧牏桴⡯‭摭损牵敲瑮癟敩彷潶孬崰‬摭损牵敲瑮癟敩彷潶孬崰⴬洠彤畣牲湥彴楶睥癟汯ㅛⱝ洠彤畣牲湥彴楶睥癟汯ㅛⱝ‭摭损牵敲瑮癟敩彷潶孬崲‬摭损牵敲瑮癟敩彷潶孬崲㬩汧慍牴硩潍敤䜨彌位䕄噌䕉⥗䐻慲偷牡⡴彭摨⥣※†⼯䐠慲⁷桴⁥慰瑲椠⁮敳敬瑣潩⁮潭敤朮䵬瑡楲䵸摯⡥䱇偟佒䕊呃佉⥎朻偬灯慍牴硩⤨朻䵬瑡楲䵸摯⡥䱇䵟䑏䱅䥖坅㬩牰捯獥彳楨獴牟捥牯⡤摡彤楨彴潴江獩⥴活彬慬瑳晟湵瑣潩彮档獯湥㴠丠彏商䍎䥔乏䵟䑏㭅牄睡慐瑲洨桟捤㬩爠獥瑥獟汥捥楴湯扟晵敦⡲㬩敽獬⁥⁻⼯匠汯摩戠楥杮猠潨湷‬潳删湥敤坲牡⁥楰正湩⹧晩刨偷捩卫散敮洨獟散敮瀬楯瑮砮‬潰湩⹴ⱹ洠损浡牥ⱡ☠浡㭰彭楰正⤩†瀠潲散獳桟瑩彳敲潣摲愨摤桟瑩瑟彯楬瑳㬩汭江獡彴畦据楴湯损潨敳⁮‽低䙟乕呃佉彎位䕄䐻慲偷牡⡴彭摨⥣※⁽†††戠敲歡挻獡⡥佚䵏䥟彎問彔位䕄㨩††潣灭瑵彥慰瑲扟潢⡸慰瑲‬業獟潨彷搳‬摭牟瑯浟瑡楲ⱸ洠灟牡彴散瑮潲摩‬摭灟牡彴扢硯獟穩ⱥ☠浡㭰景獦瑥㬩†洠彩扢硯楟彳灵瑟彯慤整㴠〠椻⡦業摟湹浡捩牟瑯损湥整彲湯 ⽻ 獕牥栠獡映牵桴牥潺浯摥椠⹮挠浯異整湟湯摟湹敟畱癩污湥⡴㬩睒摉湥楴祴慍牴硩洨彤祤彮潲彴慭牴硩㬩⽽ 潎⁷畴湲漠⁮祤慮業⁣潲慴楴湯挠湥整⁲晩渠敥⁤敢椮⡦⠠摭灟牡彴扢硯獟穩孥崰☠瑧※⸲⨲摭损牵敲瑮癟敩彷潶孬崰 籼†⼯唠敳⁲慨⁳潺浯摥椠⁮潳琠慨湴瑯愠汬††洨彤慰瑲扟潢彸楳敺ㅛ⁝朦㭴㈠㈮洪彤畣牲湥彴楶睥癟汯ㅛ⥝⤠笠⼠ 景琠敨瀠牡⁴獩椠⁮楶睥瘠汯浵⹥業扟潢彸獩畟彰潴摟瑡⁥‽㬰⼯䔠敶⁮桴畯桧戠潢⁸潣灭瑵摥‬敷洠牡⁫獡渠瑯甠⁰潴搠瑡⁥潳琠慨⁴潺浯愭汬晩ℨ洠彤祤彮潲彴慭牴硩 摭摟湹牟瑯浟瑡楲⁸‽睒牃慥整慍牴硩⤨※†⼯眠汩⁬潷歲挠牯敲瑣祬椮⡦業獟潨彷潳楬⥤笠⼯倠捩⁫桴⁥散瑮牥漠⁦桴⁥捳敲湥琠⁯楦摮瀠楯瑮漠⁮汣浵瑰⁯潲慴整愠潲湵⹤晩刨偷捩卫散敮洨獟散敮‬彭汯彤敲瑣爮杩瑨㈯‬彭汯彤敲瑣戮瑯潴⽭ⰲ洠损浡牥ⱡ☠浡㭰彭楰正⤩笠晩洨灟捩⹫祴数㴠‽睲䅎䥐䭃䉏䕊呃 ⁻††††††⼠ 潎挠畬灭眠獡瀠捩敫⹤†††彭祤慮業彣潲彴散瑮牥㴠䈠彍佐义⡔⸰ⰰ〠〮‬⸰⤰紻汥敳椠⡦彭楰正琮灹⁥㴽爠偷䍉䍋啌偍 ⽻ 潓敭挠畬灭眠獡瀠捩敫㭤瀠潲散獳椠⹴敶瑲㴠洠灟捩⹫扯敪瑣挮畬灭眮灣楯瑮※††洠摟湹浡捩牟瑯损湥整⁲‽䵂偟䥏呎瘨牥⹴ⱸ瘠牥⹴ⱹ瘠牥⹴⥺紻絽汥敳笠†彭祤慮業彣潲彴散瑮牥㴠䈠彍佐义⡔⸰ⰰ〠〮‬⸰⤰紻業摟湹浡捩牟瑯损湥整彲湯㴠ㄠ紻汥敳笠晩洨彩祤慮業彣潲彴散瑮牥潟⥮笠潣灭瑵彥潮彮祤彮煥極慶敬瑮⤨椻⡦摭摟湹牟瑯浟瑡楲⥸删䑷獥牴祯慍牴硩洨彤祤彮潲彴慭牴硩㬩摭摟湹牟瑯浟瑡楲⁸‽啎䱌活彩祤慮業彣潲彴散瑮牥潟⁮‽㬰絽牢慥㭫†敤慦汵㩴戠敲歡紻活彬慬瑳晟湵瑣潩彮档獯湥㴠丠彏商䍎䥔乏䵟䑏㭅䉃湥䍤䑁楖睥㨺湏䉌瑵潴啮⡰䙮慬獧瀬楯瑮㬩㱽牢ਾ胣뎛鷩꺁냧颍臣겪飦醀戼㹲邀鯥醼胣鎁臣몙飦꺁껥붖뻤ꮁ鿥ꖁ臣ꚁ꟦邈臣貂臣膀胩ꦭ髧뾝蟩붣胩궨若꺁菣궃菣꾂菣ꒂ菣낂菣ꂃ鯥ꞁ臣讂胣㲂牢ਾ胣뎛볯醀臣꺁駧躘臣隻臣龮雦设臣몟臣蒁臣讧裦閁苣龁胩ꦭ髧뾝蟩붣胩궨若꺁菣궃菣꾂菣ꒂ菣낂菣ꂃ鯥ꞁ臣讂胣㲂牢ਾ胣뎛볯醀臣꺁駧躘臣醼臣꺁臥ꊝ臣袂苣膀苣벃菣ꊃ苣ꖃ菣ꮃ胣螃菣뾂菣벃苣誏臣릂菣벃苣ꞃ菣ꊃ苣ꖃ菣ꮃ臣鎖臣鶁苣麁苣꺁菣벃苣꺁뗦貂苣뎛ꓧ馁苣芀戼㹲邀鯥钼胣鎁臣몙飦꺁믤꺁臥ꊝ臣袂苣膀苣벃菣ꊃ苣ꖃ菣ꮃ臣袂苣龮ꇨ閁苣讂룤겈髧ꪁ럥讨迥뎁鏦鲽臣閃菣벃菣ꎃ菣袃臣芁苣芀戼㹲邀鯥閼胣鎁臣몙飦꺁闦몤臣袂苣膀觥風苣蚃菣랂菣뎃菣뢂菣벃菣꺁郥薀臣袂苣龮ꇨ閁苣讂鿥겜髧ꖷ꣧誏臣趓뷤꺁믤ꢡ髧閃菣벃菣ꎃ菣袃臣芁苣芀戼㹲邀鯥隼胣鎁臣몙飦꺁룤뒁鷩ꮁ苣讂ꇩ벼菣벃菣鲤듧ꊂ菣뒂菣몂菣隈臣꾁럥讨臣隫郧閃菣벃苣겪飦馁苣閃菣벃菣ꎃ菣袃臣芁苣芀戼㹲邀鯥鞼胣鎁臣몙飦꺁룤뒁鷩ꮁ苣讂ꇩ벼菣벃菣鲤듧ꊂ菣뒂菣몂菣隈臣꾁럥讨臣隫郧閃菣벃苣겪飦馁苣閃菣벃菣ꎃ菣袃臣芁苣芀戼㹲邀鯥颼胣뎛볯袼뷯覼胣袼뷯覼胣袼뷯覼臣鎁臣몙飦꺁臥ꊝ臣袂苣膀軦ꚧ臣龁꟨ꢃ苣覜臣讂볯늛臣놮迥뎁雩뺔臣貂臣銧菩銂鳦馁苣钼鯦銁껧ꮁ臣蒁臣꺁觧뒾諦몇鏦鲽苣겪飦馁苣芀戼㹲邀鯥馼胣뎛볯袼뷯覼胣袼뷯覼胣袼뷯覼迥뎁볯蒽볯꾁臣꺁駧躘臣뒁鷩ꮁ苣讂胣ꖎ꟨鞁臣銧菩銂鳦馁苣钼鯦銁껧誏臣讖铦閁苣龁꟨ꢃ苣覜臣讂볯늛臣놮臣ꒁ臣ꚁ臣릉뻥붊蟥趓뷤銂ꫨ躘臣讂胣㲂牢ਾ胣뎛볯邼胣뎛볯邼볯膽볯貼볯芽볯誏臣袼뷯覼臣膀臣꺁駧躘臣隻臣뒁鷩ꮁ苣讂胣钼鯦銁껧膀菣ꪃ菣뢂迥뎁믤꺁볯늛臣놮苣覜臣讂菣벃菣ꮁ臣蒁臣꺁ꓦꊴ苣벃苣릉껥馁苣龁苣꺁觧뒾雩ꎀ鏦鲽迥뎁럥讨苣겪飦馁苣芀戼㹲邀鯥醼볯醀鯥醼볯꾁胣颊苣늛臣ꊂ菣뒂菣몂菣銂铧蒁臣膀볯ꆬ藥颍룤뎛鷩뎛臣覂볯ꆬ藥ꊃ菣ꮃ苣龔裦馁苣龁苣ꮁ臣閁苣讂럥讨迥뎁鏦鲽臣隫郧閃菣벃苣겪飦馁苣閃菣벃菣ꎃ菣袃臣芁苣芀戼㹲邀鯥醼볯醀鷩鲤蟥ꖷ꣧꺁臣膂臣뎛鷩銂뷤邈臣讂臣膂臣財臣辂苣讂蟨開菣ꪃ菣뎃苣龩菨誏臣꾂菣벃菣ꊂ菣鞃ꧦ붃臣设苣겪飦馁苣芀戼㹲邀鯥醼볯醀鯥醼볯袼뷯覼胣袼뷯覼胣袼뷯覼臣膀鷩鲤蟥ꖷ꣧꺁臣膂臣뎛鷩銂뷤邈臣讂臣膂臣財臣辂苣讂蟨開菣ꪃ菣뎃苣龩菨誏臣꾂菣벃菣ꊂ菣鞃ꧦ붃臣设苣겪飦馁苣芀戼㹲邀鯥醼볯醀鷩鲤蟥ꖷ꣧꺁臣膂臣뎛鷩銂뷤邈臣讂臣膂臣財臣辂苣讂蟨開菣ꪃ菣뎃苣龩菨誏臣꾂菣벃菣ꊂ菣鞃ꧦ붃臣设苣겪飦馁苣芀戼㹲邀鯥醼볯醀鯥醼볯袼뷯覼胣袼뷯覼胣袼뷯覼胣袼뷯覼臣鎁臣몙飦꺁臥ꊝ臣袂苣膀鷩鲤蟥ꖷ꣧ꮁ臣蒁臣ꪁ臣貂苣꺨胣꺁럥讨迥뎁鏦鲽苣겪飦馁苣芀戼㹲邀鯥醼볯醀鯥醼볯袼뷯覼胣袼뷯覼胣袼뷯覼胣袼뷯覼臣鎁臣몙飦꺁臥ꊝ臣袂苣膀鷩鲤蟥ꖷ꣧ꮁ臣蒁臣ꪁ臣貂苣꺨胣꺁럥讨迥뎁鏦鲽苣겪飦馁苣芀戼㹲邀鯥醼볯醀臣꺁駧躘臣뒁鷩ꮁ苣讂胣ꊝꓦ몇럥讨迥뎁鯦銁럧鲤蟥ꖷ꣧꺁껥財臣覂鳦芵鯦銁苣ꦃ菣螃菣뾂臣龔裦銂ꫨ躘臣讂胣㲂牢ਾ胣뎛볯颼胣鎁臣몙飦꺁臥ꊝ臣袂苣膀鷩鲤蟥ꖷ꣧誏臣늛臣骷ꓦ몇럥讨臣龮ꇨ讁苣肜뗧늛臣낂菣閃菣벃苣꺁铧邈苣겪飦馁苣芀戼㹲邀鯥醼볯醀臣꺁駧躘臣馕ꓧꮁ苣讂胣閱雩ꊂ菣뒂菣몂菣誏臣隻臣ꖷ꣧銂铧蒁臣肜裥꺁볯ꆬ藥뎛鷩袼軥閁苣覜臣ꪁ臣覼臣몟臣蒁臣銼곦莅菣螃菣銂铧邈臣讂臣膂臣몟鳦蒚ꯨ蚐菣궃菣꺁菣궃菣膃菣벃菣ꞁ臣讂胣㲂牢ਾ胣뎛볯邼胣鎁臣몙飦꺁臥ꊝ臣袂苣膀볯ꆬ藥꾂菣벃菣ꊂ菣鞃鏦鲽苣ꢔ臣ꚁ鳦鶈臣銼곦莅볯ꊝ鯥ꮁ鿥ꖁ臣ꚁ볯ꆬ藥ꊃ菣ꮃ苣龔裦馁苣龁苣꺁鿥겜髧隫郧閃菣벃臣閃菣벃菣ꎃ菣袃臣芁苣芀戼㹲邀鯥銼볯醀臣꺁駧躘臣뒁鷩ꮁ苣讂胣銼곦莅볯ꊝ鯥ꮁ꿥鞁臣銼곦莅苣ꪃ菣뎃苣莃菣趓뷤銂ꇨꪁ臣龁苣꺁럥讨迥뎁鏦鲽臣몟鳦蒚ꯨ蚐菣궃菣꺁菣궃菣膃菣벃菣ꞁ臣讂胣㲂牢ਾ胣뎛볯銼胣뎛볯銼볯膽볯誏臣袼뷯覼臣膀臣꺁駧躘臣銼곦莅苣ꪃ菣뎃苣莃菣趓뷤ꮁ苣誂諥ꖷ臣貂苣ꎻꇨ蒚볯ꆬ藥鎼鷩뎛臣뎛迥뎁臥ꊝ苣겪飦馁苣芀戼㹲邀鯥銼볯醀鯥銼볯袼뷯覼臣鎁臣몙飦꺁볯ꆬ藥꾂菣벃菣ꊂ菣鞃鏦鲽臣麛믨閁苣龁鯥꺁觧뒾苣겪飦馁苣芀鯥銼볯袼뷯覼臣鎁臣몙飦꺁臥ꊝ臣袂苣膀臣꺁駧躘臣銼곦莅苣ꪃ菣뎃苣莃菣趓뷤ꮁ雩ꎀ臣讂꣦隺뷥讅苣겪飦馁苣芀戼㹲邀鯥銼볯醀鯥銼볯袼뷯覼迥뎁볯芽볯꾁胣鎁臣몙飦꺁闦몤臣袂苣膀軥閁苣覜臣讂볯ꆬ藥鎼鷩뎛迥뎁軥閁駩뮎럥讨苣ꢔ臣ꚁ铧邈臣貂苣骎臣銂鳦鞁臣蒁냧颍賥閁苣龁볯ꆬ藥鎼鷩뎛苣겪飦馁苣芀鯥銼볯袼뷯覼臣鎁臣몙飦꺁臥ꊝ臣袂苣膀믤ꢡ髧醃菣蒃臣ꪨ雦骎臣骷裥誏臣骎臣蚆볥꺁鯥ꞁ臣讂胣㲂牢ਾ胣뎛볯閼胣겜駧躘臣뒁鷩ꮁ苣讂胣骎臣銂鳦馁苣鎼곦莅鯥ꊝ臣覂軥閁苣覜臣ꪁ臣鎼곦莅菣螃菣銂뇥讖臣讂臣膂臣龮ꇨ閁苣讂꣧薀臣ꖷ꣧誏臣趓뷤꺁ꯨ蚐菣궃菣꺁菣궃菣膃菣벃菣ꞁ臣讂胣㲂牢ਾ胣뎛볯隼胣设臣낁苣隃苣Ꞃ苣袃賦醐菣궃苣ꦃ菣肊ꇨ銂胩鞁臣겜駧躘苣龮ꇨ馁苣鮚臣膀뷤ꢔ臣貂苣늛臣ꊃ菣ꮃ臣ꎻꇨ蒚菣벃苣讧胩誏臣ꊂ苣뮂苣ꊂ菣뒂菣몂菣銂ꫨ躘臣讂胣㲂牢ਾ胣뎛볯鞼胣鎁臣몙飦꺁믤꺁臥ꊝ臣袂苣膀鯦銁菣螃菣鎃菣벃苣꺁꟦ꂀ臣隃菣莃苣肃苣ꒃ苣ꦃ菣銂ꫨ躘臣讂胣㲂牢ਾ胣뎛볯颼胣ꢡꓧ릂苣ꪃ菣뎃臣몇諥ꢁ臣ꚁ迦鮾臣貂苣ꎻꇨ蒚苣ꪃ菣覃鯥Ꚃ苣뎃菣Ꚃꇨ몤苣겪飦馁苣芀戼㹲邀鯥銼볯醀ꇨ몤苣꾂菣벃菣뢁蟥鮊臣鞁臣邏뻤閁苣讂믤ꢡ髧꾃苣ꒃ菣것菣ꂃ鯥Ꚃ苣뎃菣Ꚃ苣겪飦馁苣芀戼㹲邀鯥鎼볯醀ꇨ몤苣꾂菣벃菣뢁蟥鮊臣鞁臣邏뻤閁苣讂볯ꆬ藥뎹鷩릂苣ꪃ菣뎃菥Ꚃ苣뎃菣Ꚃꇨ몤苣겪飦馁苣芀戼㹲邀鯥鎼볯醀ꇨ몤苣꾂菣벃菣뢁蟥鮊臣鞁臣邏뻤閁苣讂귦蒰뷥뎛苣꾂菣벃菣较苣겪飦馁苣芀戼㹲邀鯥鎼볯醀臣꺁駧躘臣ꪇ该뢯돦颻臣ꊃ菣覃臣誁臣ꚁꇨ몤臣貂苣꺨胣꺁꿥閳뫤薠臣设苣겪飦馁苣芀戼㹲邀鯥鎼볯醀鯥鎼볯袼뷯覼胣袼뷯覼迥뎁볯莽볯꾁胣鎁臣몙飦꺁볯ꒁ臣뒁鷩ꮁ苣讂胣꺨胣꺁闧ꪁ苣醃菣蒃臣ꒁ臣ꚁ菣ꦃ菣뢂闩閁臣骮뻧閁苣讂藦颧苣뎛ꓧ馁苣芀戼㹲邀鯥鎼볯醀鯥鎼볯袼뷯覼迥뎁볯芽볯꾁胣鎁臣몙飦꺁믤꺁臥ꊝ臣袂苣膀볯ꒁ臣낕臣讂苣ꒂ菣꺁菣벃菣ꮁ臣蒁臣鲣諥蒚臣閃菣뎃苣랕臣銂뿨ꂊ臣讂臣ꢁ苣뎛ꓧ馁苣芀戼㹲邀鯥鎼볯醀鯥鎼볯袼뷯覼胣袼뷯覼迥뎁볯莽볯꾁胣鎁臣몙飦꺁鯦ꮁ믤꺁臥ꊝ臣袂苣膀軥閁苣馂臣ꚁꇨ몤臣貂苣꺨胣꺁菣벃菣ꮁ臣蒁臣閃菣뎃苣랕臣貁賦몤臣貂苣讅꟦銂鯥몤臣讂胣㲂牢ਾ胣뎛볯隼胣뎛볯隼볯膽볯誏臣袼뷯覼臣膀臣꺁駧躘臣ꖎ럧뢯돦릖돦誏臣꒺럥뢯돦릖돦ꮁ苣讂胣궋꟨늛臣銧뫥銂鳦馁苣醃菣蒃臣閃菣뎃苣랕臣貁ꇨ몤臣貂苣讅꟦銂ꓧ馁胣㲂牢ਾ胣뎛볯鞼胣鎁臣몙飦꺁믤꺁臥ꊝ臣袂苣膀鯥ꊽ髧ꚃ菣뚂苣뎃苣閃苣벃苣꺁뷤ꢔ臣袂苣늛臣鞃菣뎃臣龔裦閁苣讂臣膂臣財臣辂苣讂럥讨迥뎁鏦鲽臣隫郧閃菣벃臣閃菣벃菣ꎃ菣袃臣芁苣芀戼㹲邀鯥鎼볯醀鯦銁ꃩ銂铧邈臣讂臣膂臣늛臣ꪂ菣것菣뾂臣뺯臣ꚁꇨ몤臣貂苣늛臣蚠藥鮊苣꾂菣벃菣较臣设苣뎛ꓧ馁苣芀戼㹲邀鯥鎼볯醀鯥鎼볯袼뷯覼迥뎁볯芽볯꾁胣鎁臣몙飦꺁믤꺁臥ꊝ臣袂苣膀鯦銁ꃩ꺁臩麊迥뎁賦ꖅ雦醐臣꺿귦꺁뻤銂ꓧ馁胣㲂牢ਾ胣뎛볯邼胣늛臣蚠藥鮊苣꾂菣벃菣뮔菥誏臣ꊖ胩馁苣릂苣ꪃ菣뎃ꇨ몤臣뒛臣讂뻤銂ꓧ馁胣㲂牢ਾ胣뎛볯醼胣늛臣蚠藥鮊苣꾂菣벃菣뮔菥誏臣ꊖ胩馁苣릂苣ꪃ菣뎃ꇨ몤臣뒛臣讂뻤銂ꓧ馁胣㲂牢ਾ胣뎛볯銼胣鎁臣몙飦꺁볯ꒁ臣뒁鷩ꮁ苣讂胣ꪂ菣것菣뾂臣邏ꇦ閁苣龁鯦銁ꃩ銂뿤ꎭ臣钸臣ꢷ鯩馁苣꺁苣릮飦ꮁ臣讂臣膂臣궨臣覂苣讂菣ꦃ菣낂迥뎁菣궃菣鞃럧蚛觧Ꞁ苣몤臣芀戼㹲邀鯥钼볯醀鯦銁苣骃菣벃苣貁럥랅苣뢁諦馁苣꺁苣꾔迦馁苣龁苣ꮁ鯥ꊽ髧ꮁꇨ몤臣貂苣꺨胣꺁ꇨ몤菣讃菣벃迥뎁菣벃苣蚃菣隃菣꺁뻤銂ꓧ馁胣㲂牢ਾ胣뎛볯钼胣邏ꇦ閁苣龁鯦銁菣ꦃ菣ꮁ臣蒁臣ꖷ藥꺁苣莃菣ꊂ菣鞃苣릮飦ꮁ臣讂臣膂臣늛臣ꪂ菣것菣뾂臣뺯臣ꚁꇨ몤臣貂苣ꎻꇨ蒚럥랅苣莃菣ꊂ菣鞃苣ꒂ菣覃苣銂ꓧ馁胣㲂牢ਾ胣뎛볯閼胣떼苣颻臣覂苣龁苣ꒂ苣뎃臣뾽铧銂믤鞁臣膀럦颻臣貂臣뎟ꏥ誏臣ꂘ菥薃ꃥ銂鳦馁苣鎼곦莅苣ꪃ菣覃鯥Ꚃ苣뎃菣ꢡꓧ꺁뻤銂ꓧ馁胣㲂牢ਾ胣뎛볯隼胣鎁臣몙飦꺁룤뒁鷩ꮁ苣讂胣베듧閁苣龁鿩낣迥뎁飦较菦놠苣궪臣몇臣龁苣꺁苣ꒂ苣뎃臣놅臣蒵臣벾臣貂臣ꢡꓧꚂ苣뎃菣Ꚃ臣隻臣设苣몤臣芀戼㹲邀鯥钼볯醀臣꺁駧躘臣馕ꓧꮁ鿥ꖁ臣ꚁ껥財臣貂苣ꒂ菣벃苣ꢷ鯩Ꚃ苣뎃菣Ꚃ臣设苣몤臣芀戼㹲邀鯥钼볯醀鯥ꊽ髧ꚃ菣뚂苣뎃苣閃苣벃苣銂믤鞁臣龮ꇨ閁苣讂臣꺁駧躘臣늹룦膃苣莃苣龩菨꺁뻤銂ꓧ馁胣㲂牢ਾ胣뎛볯馼胣뎛뷥蒚菣벃苣ꒂ菣뾂菣Ꞃ菣릂苣讻臣ꚁ껥財臣貂苣鎁臣몙飦꺁맥覸菣Ꞃ菣꾂ꧦ붃臣设苣몤臣芀戼㹲邀鯥閼볯醀鯥閼볯袼뷯覼迥뎁볯芽볯꾁胣设臣낁苣ꞃ苣릂菣ꎂ菣꾂苣ꢔ臣ꚁ볯ꆬ藥뺹뷤ꚭ뷥뚊臣麛믨誏臣ꢡꓧ銂鏦鲽臣讂臣膂臣膀臣꺁駧躘臣趓뷤랂苣蚃菣銂ꓧ馁胣㲂牢ਾ胣뎛볯醼胣设臣낁苣ꞃ苣릂菣ꎂ菣꾂迥뎁苣벃菣鲃苣뎃苣ꢔ臣ꚁ볯ꆬ藥뺹뷤ꚭ뷥뚊臣몂菣龃菣낂迥뎁ꇨ몤苣趓뷤馁苣龁苣꺁臣꺁駧躘臣趓뷤랂苣蚃菣銂ꓧ馁胣㲂牢ਾ胣뎛볯銼胣设臣낁苣ꞃ苣릂菣ꎂ菣꾂迥뎁菣뎃菣뾂菣銂铧蒁臣膀볯ꆬ藥뺹뷤ꚭ뷥뚊臣醃菣讃菣낂迥뎁ꇨ몤苣趓뷤馁苣龁苣꺁胣鎁臣몙飦꺁鏦鲽苣릂菣ꂃ苣몤臣芀戼㹲邀鯥閼볯醀臣꺁駧躘臣鎼곦莅菣鎃苣벃苣ꞃ菣誏臣趓뷤랂苣蚃菣銂껥財臣讂臣膂臣膀껥財臣貂苣ꖷ꣧誏臣趓뷤꺁믤ꢡ髧閃菣벃菣ꎃ菣袃臣芁苣芀戼㹲邀鯥閼볯醀臣꺁駧躘臣뒁鷩ꮁ苣讂胣뢂菣ꒂ苣蚃苣莃苣讁该銂苣벃苣ꮃ臩開臣馆菥馁苣设苣몤臣芀戼㹲邀鯥閼볯醀ꇨ몤臣貂臣醃菣蒃臣麛믨뢻苣開諥ꚭ髧ꮁ꣨鞮臣讂臣膂臣ꪁ臣貂苣ꖷ꣧誏臣趓뷤꺁믤ꢡ髧閃菣벃菣ꎃ菣袃臣芁苣芀戼㹲邀鯥閼볯醀뻤袁臣릂菣벃苣ꞃ菣ꊃ苣ꖃ菣ꮃ臣誁臣ꚁ꣨醁苣貂룤ꒁꇨ몤臣貂苣ꆃ苣뎃菣讃菣벃苣ꒂ菣覃苣ꢡꓧ꺁뻤銂ꓧ馁胣㲂牢ਾ胣뎛볯鞼胣ꚃ菣뚂臣醃菣蒃菦놠苣ꖅ諥鞁룤ꒁ뿤ꎭ臣讂臣ꢁ苣꾏菨ꢁ臣讂苣蚁臣궨臣覂苣龁믤ꢡ髧醃菣蒃菦놠苣ꒂ菣覃苣ꢡꓧ銂ꓧ馁胣㲂牢ਾ胣뎛볯颼胣ꚃ菣뚂臣늛臣薃ꃥ銂藥鮊臣钸臣꺿귦馁苣鎁臣銂迥붃臣馁苣袂臣ꮁ꣨醁苣貂臣ꎻꇨ蒚鯦銁럧薃ꃥꚂ苣뎃菣Ꚃꇨ몤苣몤臣芀戼㹲邀鯥閼볯醀鷦醇菣벃菣꺁룤鎖髧늛臣떮髩銂ꛨ龯臣讂臣膂臣膀臣꺁駧躘臣ꎻꇨ蒚鯦銁ꃩꚂ苣뎃菣Ꚃꇨ몤苣몤臣芀戼㹲邀鯥隼볯醀鷦醇菣벃菣꺁룤鎖鯦銁껦躚苣랂菣ꖃ菣벃菣馁苣龁苣꺁胣鎁臣몙飦꺁믤ꢡ髧늛臣랂菣ꖃ菣벃苣ꞃ菣Ꚃ苣뎃菣Ꚃꇨ몤苣몤臣芀戼㹲邀鯥隼볯醀볯ꆬ藥讁苣鎼곦莅臣꺁ꓥ鮏臣龁苣ꚃ菣뚂臣뺯臣ꚁ꣨醁苣貂룤ꒁꇨ몤臣貂苣膀臣꺁駧躘臣ꎻꇨ蒚菣讃菣벃苣꾂菣벃菣뎛迥뎁꟦ꂀ臣芁苣芀戼㹲邀鯥隼볯醀臣꺁駧躘臣銼곦莅苣ꪃ菣뎃苣莃菣趓뷤꺁臣膂臣ꎻꇨ蒚菣讃菣벃苣꾂菣벃菣뎛迥뎁꟦ꂀ臣芁苣芀戼㹲邀鯥隼볯醀룤꾫臣讖铦閁苣龁럧蚈臣꒙軥閁苣讂觥꺁菣벃菣꺁볯ꆬ藥ꢡꓧ꺁뻤銂ꓧ馁胣㲂牢ਾ胣뎛볯钼胣醃菣蒃臣銼곦莅볯ꊝ鯥讁苣醃菣蒃臣鎼곦莅菣螃菣銂铧邈臣讂髩ꮁ뷤ꢔ臣貂苣鎁臣몙飦꺁볯ꆬ藥꾂菣벃菣ꊂ菣鞃럥讨臣袂苣膀觥風룤릖臣讖铦閁苣龁럧蚈臣鎼곦莅ꇨ몤臣覂駩뮎臣貂臣貾臣醃菣蒃苣몤臣芀戼㹲邀鯥隼볯醀鯦銁럧貁觧骮臣貂苣趉臣醃菣蒃臣ꎻꇨ蒚볯ꆬ藥ꢡ迧銂ꓧ馁胣㲂牢ਾ胣뎛볯隼胣鎁臣몙飦꺁볯ꆬ藥꾂菣벃菣ꊂ菣鞃럥讨臣袂苣ꊃ菣ꮃ菣骷臣붿諥閁苣龁뻥꺁菣벃菣銂ꓧ馁胣㲂牢ਾ胣뎛볯鞼胣늛臣骷苣趁苣蒁臣鞁룤ꒁ鷩銂菣ꪃ菣뎃苣馁苣趉臣醃菣蒃臣ꎻꇨ蒚菩蚈苣몤臣芀戼㹲邀鯥隼볯醀臣꺁駧躘臣鎼곦莅苣ꪃ菣뎃苣莃菣ꖷ꣧ꮁ苣讂觥風귦뢸賥誏臣袃菣龃菣낂臣財臣辂苣龁뻥꺁菣벃菣꺁菩蚈苣몤臣芀⼼䥄㹖㰊䥄㹖䐼噉邀鯥醼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㌰⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯醀⼼䥄㹖 †††††㰠䥄㹖愼栠敲㵦〢〰㠳㐸㤱⸵楴≦〾〰㠳㐸㤱⸵楴쉦゠〰〰㰴愯㰾䐯噉ਾ††††䐼噉邀鯥鎼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㔰⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯醀⼼䥄㹖 †††††㰠䥄㹖愼栠敲㵦〢〰㠳㐸㤱⸵楴≦〾〰㠳㐸㤱⸵楴쉦゠〰〰㰶愯㰾䐯噉ਾ††††䐼噉邀鯥閼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㜰⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯醀⼼䥄㹖 †††††㰠䥄㹖愼栠敲㵦〢〰㠳㐸㤱⸵楴≦〾〰㠳㐸㤱⸵楴쉦゠〰〰㰸愯㰾䐯噉ਾ††††䐼噉邀鯥鞼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㤰⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯醀⼼䥄㹖 †††††㰠䥄㹖愼栠敲㵦〢〰㠳㐸㤱⸵楴≦〾〰㠳㐸㤱⸵楴쉦゠〰㄰㰰愯㰾䐯噉ਾ††††䐼噉邀鯥馼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰ㄱ⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯邼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㈱⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯醼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㌱⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯銼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㐱⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯鎼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㔱⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯钼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㘱⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯閼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㜱⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯隼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㠱⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯鞼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㤱⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯颼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰〲⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯馼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰ㄲ⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯邼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㈲⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯醼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㌲⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯銼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㐲⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯鎼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㔲⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯钼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㘲⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯閼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㜲⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯隼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㠲⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯鞼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㤲⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯颼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰〳⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯馼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰ㄳ⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯邼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㈳⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯醼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㌳⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯銼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㐳⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯鎼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㔳⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯钼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㘳⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯閼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㜳⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯隼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㠳⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯鞼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㤳⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯颼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰〴⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯馼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰ㄴ⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯邼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㈴⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯醼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㌴⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯銼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㐴⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯鎼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㔴⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯钼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㘴⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯閼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㜴⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯隼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㠴⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯鞼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㤴⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯颼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰〵⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯馼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰ㄵ⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯邼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㈵⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯醼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㌵⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯銼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㐵⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯鎼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㔵⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯钼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㘵⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯閼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㜵⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯隼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㠵⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯鞼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㤵⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯颼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰〶⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯馼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰ㄶ⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯邼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㈶⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯醼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㌶⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯銼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㐶⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯鎼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㔶⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯钼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㘶⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯閼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㜶⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯隼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㠶⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯鞼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰㤶⼼㹡⼼䥄㹖 †††㰠䥄㹖胣뎛볯颼胣㲑䐯噉ਾ††††††䐼噉㰾⁡牨晥∽〰㌰㠸ㄴ㔹琮晩㸢〰㌰㠸ㄴ㔹琮晩ꃂ〰〰〷⼼㹡⼼䥄㹖 †††㰠䐯噉ਾ⼼潢祤ਾ⼼瑨汭ਾ