JP3884195B2 - Apparatus and method for distributing design and fabrication information throughout a sheet metal fabrication facility - Google Patents

Apparatus and method for distributing design and fabrication information throughout a sheet metal fabrication facility Download PDF

Info

Publication number
JP3884195B2
JP3884195B2 JP27347499A JP27347499A JP3884195B2 JP 3884195 B2 JP3884195 B2 JP 3884195B2 JP 27347499 A JP27347499 A JP 27347499A JP 27347499 A JP27347499 A JP 27347499A JP 3884195 B2 JP3884195 B2 JP 3884195B2
Authority
JP
Japan
Prior art keywords
bending
information
data
bend
observation
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Expired - Fee Related
Application number
JP27347499A
Other languages
Japanese (ja)
Other versions
JP2000090144A (en
JP2000090144A5 (en
Inventor
ハザマ ケンスケ
カスク カレブ
サカイ サトシ
ハリハラン サバラマン アーナンド
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Amada Co Ltd
Original Assignee
Amada Co Ltd
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Amada Co Ltd filed Critical Amada Co Ltd
Publication of JP2000090144A publication Critical patent/JP2000090144A/en
Publication of JP2000090144A5 publication Critical patent/JP2000090144A5/ja
Application granted granted Critical
Publication of JP3884195B2 publication Critical patent/JP3884195B2/en
Anticipated expiration legal-status Critical
Expired - Fee Related legal-status Critical Current

Links

Images

Classifications

    • YGENERAL TAGGING OF NEW TECHNOLOGICAL DEVELOPMENTS; GENERAL TAGGING OF CROSS-SECTIONAL TECHNOLOGIES SPANNING OVER SEVERAL SECTIONS OF THE IPC; TECHNICAL SUBJECTS COVERED BY FORMER USPC CROSS-REFERENCE ART COLLECTIONS [XRACs] AND DIGESTS
    • Y02TECHNOLOGIES OR APPLICATIONS FOR MITIGATION OR ADAPTATION AGAINST CLIMATE CHANGE
    • Y02PCLIMATE CHANGE MITIGATION TECHNOLOGIES IN THE PRODUCTION OR PROCESSING OF GOODS
    • Y02P90/00Enabling technologies with a potential contribution to greenhouse gas [GHG] emissions mitigation
    • Y02P90/02Total factory control, e.g. smart factories, flexible manufacturing systems [FMS] or integrated manufacturing systems [IMS]
    • YGENERAL TAGGING OF NEW TECHNOLOGICAL DEVELOPMENTS; GENERAL TAGGING OF CROSS-SECTIONAL TECHNOLOGIES SPANNING OVER SEVERAL SECTIONS OF THE IPC; TECHNICAL SUBJECTS COVERED BY FORMER USPC CROSS-REFERENCE ART COLLECTIONS [XRACs] AND DIGESTS
    • Y02TECHNOLOGIES OR APPLICATIONS FOR MITIGATION OR ADAPTATION AGAINST CLIMATE CHANGE
    • Y02PCLIMATE CHANGE MITIGATION TECHNOLOGIES IN THE PRODUCTION OR PROCESSING OF GOODS
    • Y02P90/00Enabling technologies with a potential contribution to greenhouse gas [GHG] emissions mitigation
    • Y02P90/30Computing systems specially adapted for manufacturing

Description

【0001】
関連出願データ
本出願は1996年5月6日出願の「薄板金属製作設備全体に亘って設計製作情報を管理し分配する装置と方法」と題したU.S.仮出願No. 60/016,948に準拠し、その明細書を全般的に参照する事によって本明細書に明白にとりいれていることを主張する。
【0002】
著作権についての注意書き
本特許文書の明細書の一部は、著作権保護の対象になっている。著作権保有者はU.S.特許・商標局の特許フアイルや記録に記載されている特許明細書の何人かによる複写には異議を申し立てないが、それ以外のものについては著作権保有者は著作権すべてを保留する。
【0003】
発明の背景
発明の分野
本発明は一般的に、製造分野及び薄板金属部品のような部品の製作に関するものである。特に、本発明は曲げ薄板金属部品の製作を容易にするために設計・製作情報を工場全体にわたって管理・分配する装置と方法に関するものである。
【0004】
背景情報
伝統的に、たとえば薄板金属の進歩的な製造設備での曲げ薄板金属の製作は、連続的な製作製造段階を含む。第一段階は設計段階で、そこでは顧客の仕様にもとづいて薄板金属部品の設計が行われる。通例顧客は特定の薄板金属部品の設備での製作を注文する。顧客の注文は通例、部品を工場で製造するのに必要な製品と設計の情報を含んでいる。この情報は、たとえば部品の幾何学的寸法、部品に必要な材料(たとえば鋼鉄、ステインレス鋼、またはアルミニウム)、特殊な成形の情報、分量、引き渡し年月日等を含むことがある。客先から要請された薄板金属部品は広範囲の種類の応用に設計・製作することが出来る。たとえば、製作された部品は最終的にはコンピュータのケース、配電盤、航空機の肘掛け、または自動車のドアのパネルに使われるかもしれない。
設計段階では、薄板金属部品の設計は、適当なコンピュータ支援設計(CAD)システムによって製造設備の設計部でなされる。顧客の仕様に応じて、プログラマーがCADシステムを用いて薄板金属部品の2次元(2ーD)モデルを作成することもできる。通例、客先は部品の重要な幾何学的寸法を含む青写真を提供する。この青写真は、部品に含まれる特別の成形や記号、または薄板金属部品の表面の孔や他の開口を示すこともある。設計プログラマーはCADシステムで2ーDモデルを作成するため、この青写真を度々用いる。この2ーDモデルはまた、薄板金属部品の曲げ線及び/または寸法情報を含む平面図と、一つまたは一つ以上の透視図を含むこともある。
【0005】
実際に薄板金属部品の曲げ加工を開始する前に、先ず原材料から部品を打ち抜き切断するか/または切断しなければならない。在庫材料の処理に当たって、打ち抜きプレスやプラズマまたはレーザー切断機を制御作動するのに、普通コンピュータ数値制御(CNC)または数値制御(NC)が用いられる。この在庫材料の処理を容易にするため、設計プログラマーは、コンピュータ支援製造(CAM)システムまたはCAD/CAM システムを用いて2ーDモデルにもとづいた制御コードを作成することが出来る。この制御コードには、打ち抜きプレス及び/または切断機にとりいれて、在庫材料からの薄板金属部品の打ち抜き、または切断に利用できる部品プログラムが含められていることもある。
【0006】
製造プロセスの次の段階は曲げ加工計画段階である.この段階で、曲げ加工計画が作業場で曲げ加工オペレータによって立てられる。オペレータには通常切断または打ち抜かれた一つまたは一つ以上の在庫材料とともに、部品の青写真または2ーD図面が渡される。これらの材料で曲げ加工オペレータは使用する工具と実施される曲げの手順を定める曲げ加工計画を立てる。曲げ作業場には、オペレータがデータを入力した曲げコード、または曲げ計画にもとづいたプログラムが作成できるCNCプレスブレーキのようなCNC金属曲げ機も含まれる。
【0007】
曲げ加工計画が作成されると、オペレータは曲げ加工の順序の初期テストのための作業場を設置する。このテスト段階では、打ち抜きまたは切断された材料はプレスブレーキに手で組み込まれ、プレスブレーキはプログラムされた順序に従って製作品に曲げを加工するように操作される。オペレータは出来上がった曲げ薄板金属部品を分析して顧客の仕様に適合しているかどうかを検査する。このプレスブレーキの初期作業の結果によって、オペレータは曲げプログラムを編集し、曲げ順序を修正することもある。オペレータはまた、薄板金属部品の設計が適当に修正出来るように、設計部に結果をフイードバックすることもある。テストは通常曲げ薄板金属部品が要求されている設計仕様内におさまるまで続けて行われる。
【0008】
製作プロセスの最後の段階の一つは曲げ段階である。曲げ計画が作成され、テストされた後、曲げオペレータは曲げ加工場に必要な工具を装備し、曲げ計画と記憶されている曲げプログラムまたはコードに従ってプレスブレーキを作動する。曲げ加工場に必要な量の打ち抜きまたは切断された材料が確保されるように、また他の作業が指定された引き渡し年月日までに完了しているように、作業日程も作成される。作業日程は製作過程の初期段階と/または全過程に平行して作業場監督によって作成または修正されることもある。最後の曲げ薄板金属部品の製作が完了すると、顧客への引き渡しのために部品は集められ、梱包される。
【0009】
通常の製作、製造過程は幾つかの欠点や不利な点がある。たとえば、各々顧客の設計製造データは通常物理的に(たとえば紙によってフアイルキャビネットに)、電子的に(たとえばデイスクまたは磁気テープに)保管されるが、こうしたデータは普通別々に保管されていて検索するのが容易でない。さらに、多くの工場環境では、重要な仕事情報の分配は工場全体にわたって配布される仕事または企画用紙の形をとる。その結果、データがしばしば紛失または損傷し、以前または類似の仕事に関する設計製造データを検索するのが困難になる。加うるに、データの保管方法の不備によって、設計製造情報を全工場の作業場やその他の場所に配布するのに貴重な時間が失われる。また部品の設計や曲げ計画の作成は、主として設計プログラマーと曲げオペレータによって行われ、個人の知識、手腕と経験によるところが大きいので、薄板金属部品と曲げ計画の作成の間に製造時間がかなり失われる。
【0010】
近年、慣習的な薄板金属製造過程を改善し、過程全体にわたる効率を改善するための開発と試みがなされてきた。たとえば、市販のCAD/CAMシステムにおける2次元(2-D)および3次元(3-D)モデル作成の使用と開発によって曲げ薄板金属の製作過程とモデル作成を促進され、改善された。今では設計プログラマーやオペレーターは2ーD及び3ーD表示を用いて、部品の形状をよりよく理解し、部品設計と曲げコードの順序をより効率的’に作成出来るようになっている。データを電子的に記憶し、トランスフアーする機能は、設計部から作業場への情報の流れを改善した。コンピュータとデータ通信ネットワークの進歩により、最早古い紙テープや磁気デイスクをキャビネットまたはフアイルから探し出すことが不要になった。
【0011】
こうした進歩があるにもかかわらず、組織と工場環境全体にわたる設計と製造情報の組織化と流れを改善する必要がまだある。たとえば、在来の製造システムでは、各顧客の注文の重要な設計及び製造情報が、工場のどの場所でも容易にアクセスでき、検索できるような論理的関係づけがなされていない。今までのシステムはまた、薄板金属部品の特徴や特質のような、色々な特色にもとづいた仕事情報を探索する機能をもたない。たとえば同一または類似の部品の探索にもとづいた、以前の仕事情報が探索でき、検索出来ることは、全体的な製作プロセスを大幅に増強し、将来の仕事の必要製造時間を短縮する。
【0012】
過去の試みはまた、設計プログラマーや作業場オペレータによる薄板金属部品の設計を容易にすることに欠けている。2ーDや3ーDモデリング・システムによって、設計者は部品の形状や幾何学をよりよく理解出来るようになったが、このシステムによって設計プログラマーや作業場オペレータに科せられた負担は軽減されていない。たとえば、これらのシステムによって設計プログラマーが現存の2ーD CADモデルを簡単に3ーD表示に変換することはできない。また作業場オペレータに曲げ加工計画を立てる助けとなる部品の2ーD及び/また3-D図面が提供されても、オペレータは必要な工具や曲げ手順を手で/または試行によって決めなければならない。
【0013】
発明の要約
上記に照らして、本発明は、発明の一つまたは一つ以上の見地、実施例及び/または特色あ、るいはサブコンポーネントを通して、以下にに特記する一つまたは一つ以上の目的と利点をもたらすために供するものである。
【0014】
本発明の一般的な目的は、曲げ薄板金属部品のような部品の製作を促進するために、設計と製造情報を全工場に亘って管理し、分配する装置と方法の提供である。
【0015】
さらに本発明の目的としては、たとえば進歩的な薄板金属製作設備における重要な仕事情報の紛失または破壊を防止し、専門的知識の蓄積の有効活用と整理を助長する装置と方法の提供がある。
【0016】
もう一つの本発明の目的は、各顧客の注文の設計と製造情報の双方を、論理的に記憶する装置と方法を備えることによって、工場のどの場所でも容易にアクセスでき、検索できるようにすることにある。
【0017】
さらにもう一つの本発明の目的は、仕事データが中央のデータベースまたはフアイルサーバーに、全工場のどの場所でも容易に探索し、検索できるよう論理的に記憶されている設計と製造情報を管理し、分配する装置と方法の提供にある。仕事データは仕事に関連した設計と製造情報ばかりでなく、必要な曲げ操作を遂行するための実際の曲げコードも提供できる。
【0018】
またさらに本発明の目的は、色々な探索基準にもとづいた、設計と製造情報を含む以前の仕事情報を探索する装置と方法の提供である。探索基準は、たとえばこれから製造される薄板金属部品の特色や特徴を含むことができ、これによって同一または類似の部品に関連した以前の仕事情報を、将来の仕事の全体的な製造時間の短縮に利用できる。
【0019】
本発明のもう一つの目的は、各顧客の注文に関連した従来の書類仕事または企画用紙を、工場の何処からでも瞬間的にアクセスできる電子的ジョッブシートに置き換えることである。電子的なジョッブシートはどの場所でも表示でき、部品の2ーD及び/または3-Dモデル像、工具の選択、最適曲げ手順、必要なステイジング情報やバーコードまたは認識番号を含む、仕事に関連した重要な設計と製造情報を含む。この電子的ジョッブシートには、曲げオペレータによって将来再び同じ、または類似の仕事を行うときに役立つと思われる、特別の指図または手順を録音録画したオーデイオ及び/またはビデオ部品も備えられる。
【0020】
本発明のもう一つの目的は薄板金属部品の2ーDと3-Dコンピュータ画像を提供することによって部品図面の解析に要する時間を短縮する事にある。固体3ーD画像モード、3ーDワイヤフレーム画像モード、2-D平面画像モード及び正射画像モードを含む、色々な画像が提供できる。薄板金属部品の解析に役立つズーミング、パンニング、回転及び自動寸法入れを含む色々な異なる画像機能も備えられる。
【0021】
さらに本発明は設計者の薄板金属部品の設計と曲げ計画の製作を容易にする装置と方法を提供する目的を持つ。たとえば、現存する部品の2ーDモデルから部品の3ーD表示を容易に製作することができるようにするのも本発明の目的である。さらにもう一つの本発明の目的として、曲げ計画とプログラムされた曲げコードを作成する時間を短縮するためのグラフィックスインターフエイスの提供がある。
【0022】
上記に鑑みてこの発明は設備において製造されるべきパーツ(例えば板金パーツ)を表現するためにコンピュータ可読媒体に格納されたオブジェクト指向ベンドモデルに向けられる。このオブジェクト指向ベンドモデルは、前記パーツの特徴に関連するパーツ情報及びこのパーツになされる曲げ操作に関連する曲げ情報を有する複数のオブジェクトを含むパーツクラスを備える。前記パーツ情報は、パーツの設計及び製造情報を含む。前記パーツ設計情報は2次元及び3次元座標空間における前記パーツの表現に関連する。更に、前記曲げ情報は、前記パーツの曲げ線において曲げ操作を行なうための曲げデータ及び命令を備えた一群のオブジェクトを有する。曲げデータは、曲げ角度量及び曲げ半径量を含む。
【0023】
この発明の1つの側面によれば、前記パーツクラスは前記曲げ操作が前記パーツになされるところの順番に関連する曲げシーケンス情報を備える属性を含む。前記属性はパーツ材質タイプ及びパーツ厚さを備える。更に上記複数のオブジェクトは、面オブジェクトを備え、この面オブジェクトは、前記パーツの各面の寸法に関連する設計データ及び少なくとも1つの座標空間内における前記パーツの各面の表現に関連する1データを含む。前記複数のオブジェクトは更に、曲げ線オブジェクトを含む。前記曲げ線オブジェクトは前記パーツの各曲げ線の寸法に関連する設計データ及び少なくとも1つの所定の座標空間内での前記パーツの各曲げ線の表現に関連する1データを含む。前記曲げ線オブジェクトは更に、前記パーツになされる曲げ操作に関連する曲げ製造データを含む。前記曲げ製造データは、前記パーツの各曲げ線についての部位幅データ及び曲げピッチ及び配向データを含む。
【0024】
前記曲げモデルの複数のオブジェクトはまた穴オブジェクト及び成形オブジェクトを含む。この穴オブジェクトは、前記パーツにおける少なくとも1つの穴の寸法に関連する設計データ及び少なくとも1つの所定の座標空間内での前記パーツの各穴の表現に関連する1データとを含む。前記成形オブジェクトは、前記パーツの各々の成形部の寸法に関連する設計データ及び少なくとも1つの座標空間内における前記パーツの各成形部の表現に関連する1データとを含む。トポロジーオブジェクトと曲げ特性オブジェクトが更に設けてある。前記トポロジーオブジェクトは、前記パーツの特徴に関連するパーツトポロジーデータを含み、前記パーツの特徴は、前記パーツの面または穴または成形部または曲げ線の少なくとも1つを含む。更に前記曲げ特性オブジェクトは、前記パーツに関連する製造拘束データを含む。この発明はまた製造設備において製造されるべき板金パーツを表現するための、コンピュータ可読媒体に格納されたオブジェクト指向曲げモデルに向けられる。前記オブジェクト指向モデルは、複数のパーツ特性を有するパーツオブジェクトと2次元座標空間及び3次元座標空間において板金パーツを表現するための複数のオブジェクトを含むパーツクラスを備える。前記複数のオブジェクトは、前記板金パーツの特徴に関連する設計情報及び前記板金パーツに少なくとも1つの曲げ操作を行なうための曲げ情報を含む。前記パーツの特徴は、面及び穴及び成形部及びまたは曲げ線を含み、前記複数のオブジェクトは、面オブジェクト及び穴オブジェクト及び成形オブジェクト及びまたは曲げ線オブジェクトを備える。
【0025】
前記曲げ情報は、前記板金パーツになされる複数の曲げ操作に関連する。前記曲げ情報は、前記板金パーツに少なくとも1つの曲げ操作を行なうための曲げデータ及び命令を備えた一群のオブジェクトを備える。前記曲げデータは、例えば、曲げ角度量及び曲げ半径量を含む。更に前記曲げ属性は、前記曲げ操作が前記板金パーツに対してなされる順番に関連する曲げシーケンス情報を備える。前記パーツ属性はまた、パーツ材料タイプ及びパーツ厚さを備える。
【0026】
この発明の他の側面によれば、コンピュータ制御システムにおいて用いられるように構成されたオブジェクト指向曲げモデルビューアが提供される。前記コンピュータ制御システムは、前記パーツに関連する曲げモデルデータを格納するデータベースと前記パーツの画像を表示するための表示装置とを含む。前記オブジェクト指向曲げモデルビューアは、曲げモデルビューア観察クラスを備え、この曲げモデルビューア観察クラスは、観察モデル属性と前記ベンドモデルビューア観察クラスの要素機能として実行される少なくとも1つの観察機能とを含む。前記パーツの少なくとも1つの画像が、前記曲げモデルデータ及び観察モデル属性とに基づいて、前記コンピュータ制御システムの表示装置上に表示される。
【0027】
種々の追加的特徴が、この発明のオブジェクト指向曲げモデルビューアに設けてある。例えば、前記観察モデル属性は所定の観察モード或いは複数のモードに関連する表示情報を備え、前記所定の観察モード或いは複数の観察モードは実線観察モードまたはワイヤフレーム観察モード、2次元平面図モード、及びまたは斜視図モードを含む。前記曲げモデルビューア観察クラスはまた、1つまたはそれ以上の観察機能に応じて前記パーツの画像を修正するための情報を含む。前記観察機能は、例えば、ズーミング機能または回転機能またはタンニング機能及びまたは寸法付け機能を含む。前記ズーミング機能は、表示装置上で前記パーツの画像をズームするための操作を含み、前記回転機能は前記パーツの画像を回転するための操作を含む。前記タンニング機能は、前記表示装置上で前記パーツの画像をタンニングする操作を含み、前記寸法機能は、前記パーツの少なくとも1つの特徴に関連する寸法情報を追加的に表示するために前記パーツの画像を修正する操作を含む。前記寸法情報は、前記パーツの少なくとも1つの曲げ線の長さまたは前記パーツの各曲げ線の曲げ角度及びまたは前記パーツの少なくとも1つのフランジ部の長さを含む。
【0028】
前記オブジェクト指向曲げモデルビューアは、前記パーツの画像の現在表示されている姿に基づいて前記表示装置上において観察可能な前記パーツの特徴に関連する観察可能性情報を維持し提供するための観察可能性機能を有する。前記曲げモデルビューア観察クラスは、少なくとも1つの観察機能に応じてパーツの画像を修正するための情報を含む。前記観察機能は、観察可能性情報に基づいて前記パーツの画像を修正しパーツの観察可能な特徴に関連する寸法情報を表現するための操作を含む寸法機能を備える。更にオブジェクト指向曲げモデルビューアは、前記表示装置上のパーツの画像の現在表示されている姿のズーム係数に関連するズーム係数情報を含む。
【0029】
本発明の更に他の側面によれば、パーツの表示されている画像を操作するためのシステムが提供される。前記パーツの表示されているイメージは3次元座標空間においてスクリーン上に表示される。このシステムは以下を含む。指令信号を生成するための入力装置(例えばジョイスティック装置或いはマウス装置)ここに前記指令信号は前記パーツの表示されている画像を修正するように構成された少なくとも1つの所定の観察機能に関連する。表示されている画像の現在の姿を決定するための現在姿決定システム。表示されているイメージの現在の姿に基づいて前記パーツの回転軸を動力学的に設定するための設定システム。前記観察機能に応じて、前記指令信号及び回転軸に基づいて前記パーツの表示されている画像を修正するための画像修正システム。
【0030】
所定の観察機能は、回転機能を備え、前記画像修正システムは前記指令信号に基づいて前記回転軸を中心としてパーツの表示されている画像を回転するように構成されている。更に現在姿決定システムは、パーツの表示されている画像の現在の姿がパーツの全体の姿であるか或いはパーツの部分的姿であるかを決定するように構成されている。前記設定システムは、前記現在姿決定システムが前記パーツの表示されているイメージの現在の姿は全体の姿であると決定する時、前記パーツの幾何学的中心を前記パーツの回転軸が通るように設定するように構成されている。更に前記設定システムは、前記現在姿決定システムがパーツの表示されている現在の姿が部分的姿であると決定する時、前記パーツの回転軸が前記スクリーンのセンターを通るように設定するように構成されている。
【0031】
前記システムには他の特徴が設けてある。例えばパーツ観察可能システムが設けてあり、それは現在の姿に基づいてパーツの一部がスクリーンの中心に観察可能であるか否かを決定する。その場合には、前記パーツ観察可能性システムが前記パーツの前記一部が観察可能であると決定する時前記回転軸が前記スクリーンの中心における前記パーツの前記一部を通るように設定するように構成されている。更に前記設定システムは、前記パーツ観察可能性システムが前記パーツの前記部分がスクリーンの中心において観察可能ではないと決定する時、前記パーツの幾何学的中心のZ座標軸における前記スクリーンの中心を前記回転軸が通るように設定するように構成されている。
【0032】
前記現在姿決定システムがパーツの表示されている画像の現在の姿は部分的姿であると決定する時、前記スクリーンの中心に位置し且つ前記スクリーンのカメラ視野に最も近い前記パーツの部分を特定するためのシステムが設けてある。前記パーツの特定された部分が前記パーツの開口部に対応するかどうかを決定するためのオブジェクト検出システムがまた設けてある。このオブジェクト検出システムが、パーツの特定された部分はパーツの開口部に関係しないと決定する時、前記計算システムは、前記回転軸が前記パーツの前記特定された部分を通るように設定するように構成されている。更に前記オブジェクト検出システムが前記パーツの特定された部分が当該パーツの開口部に関連すると決定する時、前記パーツの幾何学的中心のZ座標に対応する深さにおいて前記スクリーンの中心を前記回転軸が設定されるように前記設定システムは構成されている。
【0033】
前記入力装置はジョイスティック装置及びまたはマウス装置を備えている。前記ジョイスティック装置は、ジョイスティック仮想空間を含み、当該装置からの指令信号は前記ジョイスティック仮想空間内での前記ジョイスティック装置の移動に関連する情報を含む。前記画像修正システムは、前記ジョイスティック仮想空間内でのジョイスティック装置の移動をスクリーンのスクリーン空間内での仮想の移動に写像するための写像システムを有する。従って、前記画像修正システムはジョイスティック移動から写像されたカーソルの移動に基づいて前記パーツの表示された画像を修正する。前記写像システムは、前記ジョイスティック仮想空間の寸法に対する前記スクリーン空間の寸法の比率に基づいて、前記ジョイスティック装置の移動を前記スクリーン空間内でのカーソルの移動へ写像するように構成されている。例えば前記カーソルの移動は以下の式に基づいて前記写像システムにより写像される。
【0034】
現在位置=従前位置+(スケール係数×V)
ここに現在位置はスクリーン空間内でのカーソルの現在の位置であり、従前位置は前記スクリーン空間内でのカーソルの従前の位置であり、スケール係数はジョイスティック仮想空間の寸法に対するスクリーン空間の寸法の比率であり、Vは前記ジョイスティック仮想空間内でのジョイスティック原点からジョイスティック現在位置へのジョイスティック装置の移動及び方向に関連するベクトルである。
【0035】
この発明の他の特徴によれば、前記写像システムは、前記写像システムにより必要されるスケール係数を調整するためのスケール調整システムを備える。このスケール調整システムは、前記スクリーン空間の寸法の前記ジョイスティック仮想空間の寸法に対する比率に所定の調整係数を掛け合わせ調整されたスケール係数を提供するように構成されている。前記写像システムは前記ジョイスティック運動を写像する際にこの調整されたスケール係数を用いるように構成されている。非限定的な事例として、3という調整係数が使用される。
【0036】
この発明はまたパーツの表示された画像を操作する方法を含む。ここに前記パーツの前記表示された画像は3次元座標空間においてスクリーン上に表示される。前記方法は以下の工程を含む。入力装置から生成された指令信号を受け取る工程。ここに前記指令信号は前記パーツの表示された画像を修正するように構成された少なくとも1つの所定の観察機能に関連する。スクリーン上においてパーツの表示された画像の現在の姿を決定する工程。前記パーツの現在の姿に基づいて前記パーツの回転軸を動力学的に設定する工程。前記観察機能に応じて、前記指令信号及び回転軸に基づいて前記パーツの表示された画像を修正する工程。
【0037】
この発明の上記した方法によれば、前記所定の観察機能は、回転機能を備え、これにより前記パーツの表示された画像は指令信号に基づいて前記回転軸を中心として回転される。更に前記設定の工程は、前記パーツの表示された画像の現在の姿が全体の姿であると決定される時、前記パーツの幾何学的中心を前記パーツの回転軸が通るように設定する操作を含む。前記設定の工程はまた、前記パーツの表示された画像の現在の姿が部分的な姿であると決定される時、前記パーツの回転軸が前記スクリーンの中心を通るように設定する操作を含む。
【0038】
この発明の他の側面によれば、パーツの画像と共に寸法情報をスクリーン上に表示するシステム及び方法が提供される。前記方法は以下の工程を含む。前記パーツの表示された画像の現在の姿を決定し且つ前記現在の姿に基づいてスクリーン上で複数の特徴のうちのいずれが観察可能であるかを決定する工程。前記パーツの表示された画像と共にスクリーン上に、スクリーン上で観察可能であると決定されたパーツの特徴の各々についてのみの寸法情報を選択的に表示する工程。前記方法は更に、前記パーツに関連する曲げモデルデータにアクセスし、この曲げモデルデータに基づいて前記パーツの特徴の各々についての寸法情報を表示するためのスクリーン上の全ての可能な位置を決定する。更に、前記選択的に表示する工程は所定のヒューリスティックを適用し、前記可能な位置に基づいて前記観察可能な特徴の寸法情報を表示する場所を決定する。前記ヒューリスティックは、前記パーツの表示された画像の外側に存在するスクリーン上の位置に前記寸法情報を表示する動作と観察者の観察点に近い方のスクリーン上の位置に前記寸法情報を表示する動作と及びまたはスクリーン上で寸法情報が重なり合わないように前記寸法情報を表示する動作を備える。
【0039】
表示される前記寸法情報は、前記パーツの各曲げ線についての曲げ長さ及び曲げ角度を備える。前記寸法情報はまた、前記パーツの各曲げ線に関連する内側曲げ半径及び曲げ縮小量を含む。ここに前記表示の工程は、前記現在姿に基づいて観察可能であると決定される前記パーツの各曲げ線についての曲げ線長さ、曲げ角度、曲げ半径及びまたは曲げ縮小量を表示する。前記パーツの各フランジ部のフランジ長さのような他の寸法情報も表示される。追加の情報例えばパーツの幅及び深さ及び高さも表示される。
【0040】
選択的に表示する工程は、パーツの所定の特徴のみの寸法情報を表示するための自動寸法付け操作を行なうことを含む。従って観察可能であると決定される所定の特徴のみについて寸法情報が表示される。更に前記選択的表示の工程は、パーツの特徴に関連するユーザにより選択された寸法情報を表示するためのマニュアル寸法付け操作を実行することを含む。従ってユーザに選択された寸法情報の各々は観察可能であると決定されるパーツの特徴についてのみ表示される。スクリーン上に表示されたパーツの画像と共に寸法情報を表示するシステムも提供される。このシステムはパーツの表示された画像の現在の姿を決定し且つ現在の姿に基づいて複数の特徴のうちのいずれがスクリーン上で観察可能であるかを決定するためのシステムと前記パーツの表示されたイメージと共にスクリーン上に、スクリーン上で観察可能であると決定されたパーツの特徴のみについて寸法情報を選択的に表示するシステムとを含む。
【0041】
パーツに関連する曲げモデルデータにアクセスするためのアクセスシステムのみならずこの曲げモデルデータに基づいてパーツの複数の特徴の各々についての寸法情報を表示するためのスクリーン上の全ての可能な位置を決定するためのシステムが設けてある。前記選択的表示システムは、所定のヒューリスティックを適用し前記可能な位置に基づいて観察可能な特徴の寸法情報を表示すべき場所を決定するためのシステムを含む。表示される前記寸法情報は、前記現在姿に基づいて観察可能であると判断される前記パーツの各曲げ線についての曲げ線長さ、曲げ角度、曲げ半径及びまたは曲げ縮小量を含む。他の寸法情報、例えばパーツの各フランジ部のフランジ長さはまた表示される。追加の情報例えばパーツの幅及び深さ及び高さもこの発明によれば表示される。
【0042】
上記の特徴に加えて、さらに特徴と/またはその変形を設けることができる、たとえば、発明を上述した特徴の色々な組み合わせ、または再組み合わせ及び/または下記の詳細な記述にある幾つかの特徴の組み合わせとの再組み合わせに適用させることができる。
【0043】
上に列記したものや他の本発明の対象物、特徴及び利点については、この後により詳細に記述する。
【0044】
付録の要約
本発明の詳細な記述をさらに促進するため、付記の限定されない本発明の望ましい実施例の例に沿っての発明の色々な特徴、操作及び機能に関するソースコードの例やコメントを記した、以下の多数の付録を参照する:
付録の要約
本発明の詳細な記述をさらに促進するため、付記の限定されない本発明の望ましい実施例の例に沿っての発明の色々な特徴、操作及び機能に関するソースコードの例やコメントを記した、以下の多数の付録を参照する:
付録Aはたとえば一つの類似部品を探索するときの特徴抽出演算実行の典型的なソースコードであり;
付録Bはたとえば本発明の幾つかの類似部品の探索時に類似指数演算を行使する典型的なソースコードであり;
付録Cはこの発明で曲げ線検出操作を行う典型的なソースコードであり;
付録Dは本発明の2-Dクリーンアップを実行するための典型的なソースコードであり、これによって薄板金属部品の3-Dモデルを元の3方向からの2-D図面にもとづいて作成するのに使用出来;
付録Eは本発明の曲げモデルビューアーに色々なビュー モードや機能を実行するための典型的ソースコードであり;
付録F,G,HとIは本発明の自動寸法入れ特性を実行するための典型的なソースコードとコメントであり;
付録Jは本発明の曲げモデルビューアーの、部品・エンテイテイの観察可能性機能を実行するための典型的なソースコードであり;
付録Kは曲げモデルの実施と部品構造の構成に関する、本発明の色々な教訓をふまえた一般的なコメントを含み、
付録Lは与えられた部品の回転軸の動的計算による3-D操作とナビゲーションシステムを実行する典型的なソースコードである。
【0045】
本発明はこの後の詳細記述で限定されない本発明の望ましい実施例の例についての多数の図面を参照しながら記述されており、記述の中の同じ参照番号は全図面中の類似の部品を示す。
【0046】
詳細な説明
本発明の見地に沿って、全工場に亘って設計製造情報を管理分配し、工場内での部品の製造を促進するための装置と方法が具備される。この本発明の特徴は広範囲の工場環境や装置に利用することができ、特にこの発明は一続きの製作製造段階が異なる場所で行われる工場環境の充足に利用できる。限定されない実施例や種々の例を通じて、本発明を、たとえば進歩的な薄板金属製造設備における曲げ薄板金属部品の製作を参照しながら記述する。
【0047】
図1に、本発明の実施例に従って、進歩的な薄板金属製造設備38一般が、ブロック線図で図示されている。図1に示すように、薄板金属製造設備または工場38は全工場に分散している多数の場所10,12,14...20をもつ。
【0048】
これらの場所には設計事務所10、出荷作業場14、打ち抜き作業場16、曲げ作業場18及び溶接作業場20が含まれる。図1に画かれている薄板金属工場38には分離した場所が六つしかないが、勿論工場は六つ以上の分離した場所をもちうるし、また図1に画かれている各タイプの事務所または作業場は一つ以上の場所を占めることもある。たとえば設備38の大きさと製産必要容量により、一つ以上の打ち抜き作業場16、曲げ作業場18と/または溶接作業場20を設けることができる。さらに工場38は一つ以上の設計事務所10、組立作業場12または出荷作業場14をもちうるし、曲げ薄板金属部品の製作製造を促進するための他のタイプの場所をもちうる。
【0049】
工場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打ち抜きプレスと/または切断機を制御する部品プログラムが作成できる。
【0050】
打ち抜き作業場16と曲げ作業場18は各々CNC及び/またはNC機械工具のどのような組み合わせでも備えられる。たとえば打ち抜き作業場16は、コマ・シリーズ及び/またはペガ・シリーズのアマダ・タレット打ち抜きプレス、あるいは他の市販されているCNC及び/またはNC打ち抜きプレス一つまたは一つ以上もつことができ、また曲げ作業場18は、RGシリーズ アマダ・プレスブレーキまたは他の市販されている多軸ゲージング・プレスブレーキのようなCNC及び/またはNCプレスブレーキを一つまたは一つ以上もつことができる。さらに溶接作業場20は、薄板金属部品に対して必要な如何なる溶接をも果たすために適当な溶接機器を備えることができる。打ち抜き作業場16、曲げ作業場18と溶接作業場20は設備38の工場内のどの場所にも設置出来、熟練オペレータ(たとえば打ち抜きプレスオペレータ、曲げ機オペレータ等)によって手動で動かすことができる機械も備えている。アマダ セルロボミニやアマダ プロムキャムのような全自動またはロボット支援機械もこれらの場所に備えることができる。必要な打ち抜きと曲げの作業、あるいは必要な如何なる溶接作業もこれらの作業場で製作過程中に行うことができる。
【0051】
さらに図1に示すように、進歩的な薄板金属設備38は組立作業場12と出荷作業場14も含む。組立作業場12と出荷作業場14には、顧客への製造部品の組立と出荷を促進するために必要な梱包、ルート割り当て及び/または輸送機器も含まれる。
部品の組立と出荷は工場職員によって手動で行使または管理されるが、機械自動化及び/または機械支援にすることもできる。さらに組立作業場12と出荷作業場14は、物理的に工場作業場(たとえば打ち抜き作業場16、曲げ作業場18及び/または‘溶接作業場20に近接した)に近い場所に置くか、または薄板金属工場38とは別の設備または区域に置くことができる。
本発明の見地に沿って、重要な設計と製造情報の管理と分配は、設計と製造情報を電子的に記憶し、分配することによって行われる。伝統的な紙上の仕事の段取りまたはワークシートを、工場のどの場所からでも瞬時的にアクセスできる電子的なジョッブシートに置き換え、または補足することによって、本発明は工場の全体的な効率を改善することができる。加えて、本発明の色々な側面や特徴によって、記憶された設計製造情報の編成とアクセスが改善される。さらに類似または同一の薄板金属部品に関する以前の仕事情報のアクセスや検索が、この発明の色々な特徴を通じて出来るようになっている。
【0052】
この目的のため、本発明の色々な側面は、サーバーモジュール32とデータベース30を薄板金属設備38内の多数の場所10,12,14...20各々と結ぶ通信ネットワーク26を設けることによって実行される。このあと論ずるように、各場所10,12,14...20は通信ネットワーク26とデータベース30にインターフエイスするステーションモジュールをもつ。図1、2と3に発明のこれらの特色と実装の限定されない例を示す。
【0053】
図1と2に示すように、通信ネットワーク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のような機械類のインターフエイス/制御システムの一部であるコンピュータであってもよい。
【0054】
サーバーモジュール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と物理的に離れた場所に置かれていて、図2に示すように通信ネットワーク26とネットワークデータベースモジュール34を介してつなぐことができる。
【0055】
本発明の望ましい実施例に沿った限定されない例として、サーバーモジュール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)サーバーの全面的な支援を具備できる。
【0056】
色々なデータベース言語と管理システムはまたデータベースに記憶された情報を創りだしたり、保持したり見たりすることに用いられる。構造的問い合わせ言語(SQL)のようなデータベース言語をデータベース30のデータを確定したり、操作したり、制御したりするのに用いることができる。たとえば、SQLサーバー(マイクロソフト社から入手できる小売り製品)は本発明の実施に利用できる。さらに、この発明は開放データベース連結オープン・データベース・コネクテイビテイー(ODBC)互換ドライバーを備えることによって通信ネットワーク26を通してのデータベース30からの情報のアクセスを促進できる。ODBCに関するより詳しい情報はマイクロソフトオープン・データベース。コネクテイビテイー・ソフトウエア開発キットプログラマー用レフアランス・マニュエルでえられる。
【0057】
図2は本発明の別の実施例に従って建設された進歩的な薄板金属製造設備のブロック線図である。図2の実施例では、データベース30とサーバーモジュール32は別々に設置されており、データベース30はネットワークデータベースモジュール34を介して通信ネットワーク26につながれている。上記のように、本発明はこの構成に限定されたものではなく、データベース30とサーバーモジュール32は一緒に設置でき(たとえば図1に示すように)、ネットワークデータベースモジュール34のデータベースにアクセスする機能をサーバーモジュールに取り入れることができる。図2はまた、薄板金属製造設備38内の色々な場所10,12,14...20に設置できるステイションモジュール36の例を示す。図示の目的で、図2には曲げステイション18に設置されたステイションモジュール36が例示されている。図2の例には示されていないが、同様のステーションモジュール36を設備38内の他の場所にも設置できる。
【0058】
図2に示すように、各モジュール(サーバーモジュール32、ネットワークデータベースモジュール34及びステイションモジュール36)はネットワークインターフエイスカードまたはポート42を介して通信ネットワーク26につなぐことができる。ネットワークインターフエイスカード26はベンダー専用で、選ばれた通信ネットワークの形式にもとづいて選択できる。 各モジュール32、34、36は通信ネットワーク26とインターフエイスするためのネットワークソフトウエアまたはプログラムされた論理を含むことができる。 通信ネットワーク26はイーサネット(Ethernet)で、10ベース/T(ツイスト対)、10ベース/2(同軸)、または10ベース/5(厚膜ケーブル)のような多くのタイプの市販ケーブルから設備38の大きさと必要なケーブル長さにもとづいて選んだタイプのケーブルを用いたものであってもよい。
【0059】
図2でサーバモジュール32はデイスプレイモニターまたはCRT44とキーボード、マウス及び/またはジョイステイックを含む入力/出力デバイスをもつパソコンを含めうる。ネットワークインターフエスカード42は備えられている拡張スロットまたはパソコン40のポートに挿入できる。さらに、パソコン40は100-200MHzの処理速度とペンテイアムまたはペンテイアム・プロ マイクロプロセッサーを含むことができる。パソコン40はまた、たとえば32MBまたはそれ以上の主記憶装置と1.2GBまたはそれ以上のランダムアクセス記憶装置(RAM)を含むことができる。
デイスプレイ44は高解像度の表示画面、たとえば800×600の解像度をもつ市販のSVGAモニターを含むことができる。デイスプレイ44に表示された色々なグラフ一クスや情報を支援するため、パソコン40はまた、PCIグラフイックス・カードのような市販のグラフイックスクス・カードを含むことができる。さらに、コンピュータ40はサウンド・ブラスター、または互換の音声及びゲームポートアダプターカードを含み、入力/出力装置46はキーボード、ジョイステイックと/またはマウスを含むことができる。
【0060】
この発明の色々な特徴を実行するために、サーバーモジュール32にはソフトウエアや色々なパッケージソフトが備えられている。たとえば、サーバーモジュール32はマイクロソフト ウインドウズ NT(ワーク ステーション型)またはウインドウズ95を備えている。さらに、サーバーモジュールにこの発明特有の機能と特徴(たとえば図4を見よ)を持たせるために、サーバーモジュール32はソフトウエアまたはプログラムされた論理を備えたルーチンを含ませることができる。後でより詳しく論ずるように、これらのルーチンは、C++のような高レベルのプログラム言語とオブジェクト指向プログラミングによって作成できる。サーバーモジュール32はまた、顧客の仕様にもとづいた2-D及び3-D図面を入力及び/または作成するために、ベルムまたはアマダAP40またはAP60ソフトウエアのようなCADまたはCAD/CAMソフトウエアを含むか、インタフエースできるようになっている。この理由で、サーバーモジュールは製造設備38の設計事務所10におくことができる。データベース30からデータをアクセスするために、サーバーモジュール32は、マイクロソフトODBドライバーのようなODBCドライバーをもち、またSQLをデータ アクセスの標準に用いることができる。OLE2サーバーのようなOLEサーバーを、データをリンクするために備えることができる。
【0061】
図2の実施例では、データベース30はサーバーモジュール32から分離して備えられており、ネットワーク データベース モジュール34を経由して通信ネットワーク26につなげられている。先に述べたように、データベース30は工場38の規模と、データベースに記憶させる部品情報の量にもとづいて選ばれた、適当な記憶スペースをもったSCSIデイスク(たとえば1-4 GB)を含むことができる。ネットワーク データベース モジュール34は、ペンテイウム マイクロプロセッサーを備えたIBM互換機のようなパソコン40と、通信ネットワーク26とインターフェースするためのネットワーク インターフエース カード42を備えた拡張スロットを含むことができる。データベース30はデータ母線を介してパソコン40に連結でき、パソコン40は標準的なデイスプレイやデイスプレイ モニターまたはCRTとキーボードのような入力/出力デバイス(図2には示されていない)も含む。
【0062】
SQLに基づいたデータベース30へのアクセスを容易にするため、ネットワークデータベース モジュール 34のパソコン40は、 マイクロソフトSQLサーバーやオラクルSQLサーバーのような、市販のSQLサーバーと合わせて設置することができる。OLE2サーバーのようなOLEサーバーをデータをリンクするために備えておくことができる。パソコン40もDOSやマイクロソフト・ウインドウズNT(サーバー バージョン)のような、色々なソフトウエアを備えておくことができる。
図2の実施例は一つのステーションモジュール36の典型的な実装例を含んでいる。この実施例では、ステーションモジュール36は、曲げステーション18に装備されている。図2に示すように、ステーションモジュール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のジョイステイックまたはマウスを含むことができる。
【0063】
この発明の色々な特徴を実行するために、ステイション・モジュール36はソフトウエアといろいろな市販ソフトウエアが配置されている。たとえば、ステーション・モジュール36はマイクロソフト・ウインドウズ95またはウインドウズNT(ワークステーション版)のような基本ソフトが備えられている。さらに、ステーション・モジュールに、この発明固有の機能と特徴をもたせるために(たとえば図5を見よ)、ステーション・モジュール36にソフトウエアまたはプログラム化論理装備ルチーンが備えられる。後でより詳しく論ずるように、これらのルチーンは高レベルのプログラム言語、たとえばC++、及びオブジェクト指向プログラミング技術を用いることによって開発できる。データをアクセスし、リンクするために、ステーション・モジュール36はマイクロシフトOBCDドライバーとOLE2サーバーのようなOLEサーバーが含まれている。サーバー・モジュール32と同様、ステーション・モジュールもSQLをデータベース30からデータをアクセスする基準に用いることができる。
【0064】
曲げステーション18のステーション・モジュール36が自立型パソコンとして備えられている場合、曲げコードデータを作成するためと曲げ機械類25(たとえばCNCまたはNC制御プレス・ブレーキ)とインターフエースするためのソフトウエアを装備できる。図2の実施例では、コンピュータ36はパソコンとして装備され、標準RS-232-C配線インターフエースを通じて曲げ機械25とインターフエースするソフトウエアを配備しているように画かれている。このインターフエースはステーション・モジュール36が、RS-232-Cインターフエースを通じて曲げ機械25と通信し、曲げコードを送受できるために装備されている。このインターフエースの実行はベンダー用であり、曲げ機械25に用いられるデータ書式と命令セットに依存する。ステーション・モジュール36から曲げ機械25に送られるすべてのデータは、機械に決められている機械命令セットにもとづいてフオーマットしたものでなければならない。ステーション・モジュール36のコンピュータ48は、曲げコード生成のため、市販で入手できるCNCまたはNCソフトウエアを備えることにより、このような機械類のためにCNCまたはNCシステム(たとえばアマダAMNC)の組み込みコンピュータに通常備わっている機能をシミュレートできる。
【0065】
図3はデータのサーバー・モジュール32、データベース30と薄板金属製造設備38の間のそれぞれのデータの流れを示す実施例の典型である。図で表すためと実施例におけるそれぞれのデータの流れの記述を容易にするため、図3ではサーバー・モジュール32とデータベース30(ネットワーク・データベース・モジュール34に統合されている)は、各々別々に通信ネットワーク26と直接に接続されていて、これらの構成要素間のデータの流れは通信ネットワークを通して行われる。勿論、この技術に熟練した人なら分かるように、これら構成要素間には多種多様のデータの流れ方式を用いることができる;また、データベース30がサーバー・モジュール32に直接接続されている場合、データと情報はサーバー・モジュールからデータベースに直接に、通信ネットワーク26を用いることなく伝達できる。さらに、記述を容易にするため、図3の通信ネットワーク26は簡略化されており、図には打ち抜きステーション16と曲げステーション18しか示されていない。しかしながら、場所10,12,14...20(工場内の他のあらゆる場所や区域も含めて)からのデータのやりとりの流れは、打ち抜きステーション16と曲げステーション18について示したのと同様の方法で行うことができる。
【0066】
各顧客の注文に関連した設計製造情報は、編成してデータベース30に記憶することができる。最初に顧客から注文を受けると、基本的な製品と設計情報がサーバー・モジュール32に入力され、それからデータベース30に伝送され、記憶される。前に論じたように、サーバー・モジュール32は、キーボードを備えたパソコン等のような、データを入力する適当な手段を備えている。サーバー・モジュール32でパソコンが用いられるとき、工場職員によるデータの入力を容易にするため、メニュー方式画面を生成するソフトウエアを備えることができる。データ入力プログラムは、たとえばマイクロソフト・ウインドウズをベースとしたアプリケーションで、ヘルプ及び/またはメニュー画面をもつものであってよい。限定されない例として、サーバー・モジュール32に入力され/または作成されて、データベース30に転送されたデータは、図3に一般的に示してあるように、部品情報、曲げモデル、特徴抽出データ及び曲げ線情報を含むことができる。
【0067】
部品情報は、たとえば部品または注文参照番号、顧客の名前、部品の簡単な説明、バッチの大きさまたは量及び引き渡し予定日を含むことができる。曲げモデルデータは、たとえば部品の全体的な寸法(たとえば幅、高さ、深さ)と材料のタイプ(たとえば鋼鉄、ステインレス鋼またはアルミニウム)、厚さ及び引っ張り強さのような部品材料の情報を含むことができる。さらに、特徴抽出データは手動による入力と/または自動的に生成することによって、部品の主要な特徴を識別し、データベースの類似部品の探索やその他の探索を容易にする。特徴抽出データはデータベース30の別のフアイルに格納するか、曲げモデルデータや各部品の仕事情報と一緒に格納することができる。特徴抽出データは、たとえば表面や面の数、曲げタイプの数(たとえば二面間の正の折り曲げ、または二面間の負の折り曲げ)、面の間の関係及び/または部品にある孔や他のタイプの開口の数を含むことができる。後でより詳しく論ずるように、このようなデータは特徴ベース部品マトリクスと/または逐次探索キー(たとえば下記の図6-10を見よ)によって表現し、編成できる。最後に、曲げ線情報はデータベース30に格納するため、サーバー・モジュール32に入力できる。曲げ線情報は、たとえば部品の各折り曲げの曲げ角度、曲げ長さ、曲げの内半径(IR)、縮小量及び曲げ方向(たとえば前方または後方)を含む主要な曲げ線情報を含む。
【0068】
通信ネットワーク26を通じてデータベース30へデータを送受信するため、各場所10,12,14...20は通信ネットワークに接続されているステーション・モジュール(前に述べたステーション・モジュール36のような)を含めることができる。図3には、打ち抜きステーション16と曲げステーション18は一般的にステーション・モジュールと合わせたブロック線図で示されている。前に論じたように、ステーション・モジュールは、たとえばソフトウエア、または制御論理と独立型パソコン、またはその場所に備えられた装置または機械類の一部である汎用コンピュータを含む。各顧客の注文に応じて、設計製造情報(部品情報、曲げ線情報および曲げモデル・データを含む)が、所定参照番号またはコードを入力することによってアクセスでき、検索できる。参照番号またはコードは手動(たとえばキーボードまたはデジタル入力パッドによって)またはバー・コードを、ステーション・モジュールに備えられているバー・コード読みとり装置またはスキャナーでスキャンすることによって入力できる。さらに、本発明の見地に沿って、以前の仕事情報はデータベース30から、工場内のどの場所10,12,14...20からでも、同様の部品探索を行うことによってアクセスし、検索できる。引き続く詳しい記述で論ずるように、類似部品の探索は、特徴抽出データ、またはデータベース30に記憶されている探索キーにもとづいて行うことができ、これによって同一または類似の部品に関する以前の仕事情報が検索され、将来の仕事の全体的な製造時間の短縮に利用できる。
【0069】
データベース30から検索された製造情報は、作業場オペレータが曲げ計画を作成し、テストするのに用いられる。たとえば、曲げステーション18の曲げオペレータは、薄板金属部品に必要な工具や最適な曲げ手順を決めるために、データベース30から部品情報、曲げ線情報や曲げモデル・データをアクセスし、検索することができる。本発明の見地に沿って、ODBCドライバーを備えることにより、各ステーション・モジュールがデータベース30とインターフエースし、データベースに記憶されている情報を表示できるようにすることができる。さらに、サーバー・モジュール32またはデータベース30のネットワーク・データベース・モジュールは、データベースに記憶されているデータのアクセスと検索を容易にするために、SQLサーバーを含むことができる。最終曲げ計画に基づいて曲げコードがプログラムされると、曲げコードは曲げ手順とともに、図3に一般的に示すように通信ネットワーク30を通じて、曲げステーションのステーション・モジュール18からデータベース30に送られる。この情報は、当該の仕事に関連する他の設計製造情報とともに記憶される。
【0070】
他の情報もデータベース30に記憶することができる。たとえば、部品の2-D及び/または3-D画像表現は曲げモデルデータとともに記憶することができる。この2-Dまたは3-D画像表現は設計ステーション10または他の場所でCAD/CAMシステムを用いて作成し、設計ステーション(あるいは他の適当な場所)のステーション・モジュールを介して通信ネットワーク26を通じ、データベース30に転送できる。あるいはまた、2-Dまたは3-D画像はサーバー・モジュール32で、後でより詳しく述べるように、適当なCAD/CAMシステムまたはモデル化ソフトウエアを用いて、一連の機能または演算を実行することによって作成できる。
【0071】
図4と5を参照しながら、サーバー・モジュール32と各場所10,12,14...20においてプログラムされ実行される処理や演算について詳述する。図4と5はサーバー・モジュール32と薄板金属製造設備38内の各場所10,12,14...20で実行される基本論理の流れの流れ図である。図5は、たとえば曲げステーション18で実行される典型的な処理や操作に対するものであるが、設備38内の特定な場所で実行される操作によっては、これ以外の処理やステップも実行できることは理解できよう。以下に述べる処理や操作はソフトウエア、または多種類のプログラム作成言語と技法の一つを利用することによって実施できる。たとえば、本発明の見地に沿って、関連図面を参照しながら記述する下記の処理や操作は、C++のような高レベルのプログラム作成言語とオブジェクト指向プログラミング技法を用いることによって実施できる。さらに、限定されない例として、ウインドウズ・ベースアプリケーション用にマイクロソフト社が作成した、プログラム作成言語のバージョンであるヴイジュアルC++を利用することができる。
【0072】
図4は本発明の見地に沿って、サーバー・モジュール 32が行う基本的な処理と操作の流れ図である。図4はサーバー・モジュール32がソフトウエアまたはプログラム化論理によって実行する処理と操作の基本論理フローである。サーバー・モジュール32は、オペレータまたはユーザーがサーバー・モジュールの色々な処理や操作の選択と実行を支援するためにツール・バーやヘルプ及び/またはメニュー画面をもつウインドウズ・ベース アプリケーションを含むことができる。処理は薄板金属製造設備38で顧客の注文を受けたステップS.1から開始される。顧客の注文は通常部品が工場で製造するのに必要な製品と設計の情報を含む。この情報は、たとえば部品の幾何学的寸法、部品に必要な材料や他の設計情報も含む。顧客から受けた情報をもとに、サーバー・モジュール32は、ステップS.3に画かれているように、データベース30に記憶されている以前の仕事情報の探索を実行する。データベース30に記憶されている仕事情報は多様な探索基準にもとづいて探索できる。たとえば、情報は事前定義参照または仕事番号にもとづいて探索でき、あるいは類似部品の探索は部品のある設計特徴にもとづいて実行でき、これによって同一または類似の部品に関する以前の仕事情報が現在の仕事のために検索でき、利用できる。利用できる類似部品探索のさらに詳しい記述は、図6-10を参照しながら以下に記す。
【0073】
ステップS.5では、データベースの検索結果が解析され、現在の顧客の注文が新しい部品か、以前の仕事に類似の部品か、あるいは以前の仕事の繰り返しかが決定される。同一の照合が見いだされる(たとえば同じ部品または参照番号が見いだされる)と、顧客の現在の注文は工場で行った以前の仕事の完全な繰り返しになり、仕事情報に対するこれ以上の修正は不必要で、以前の仕事情報をデータベース30からアクセスしてステップS.11に示すように現在の顧客の注文の遂行に利用できる。データベースの探索は以前の仕事の部品または参照番号及び/またはフアイル名を与え、それによってサーバー・モジュール32またはどのステーション・モジュールにいるオペレータでもデータベースから仕事情報をアクセスすることができる。部品または参照番号しかえられない場合、変換テーブルを備えることによって、オペレータが部品参照または仕事番号を入力することによって以前の仕事情報のフアイル名を決定し、アクセスできる。従って、たとえばサーバー・モジュール32にいるオペレータは、仕事情報と2-Dと3-Dモデル化情報をデータベース30からアクセスすることによって部品の幾何学を解析し、繰り返しの注文と類似であることを確認することができる。注文が繰り返しの注文であることが確認されると、曲げステーション18のステーション・モジュールにいる曲げオペレータは、さらに以前の仕事情報をアクセスし、曲げコードのデータと工具段取り情報を含む製造情報を曲げと部品の製作に利用することができる。かかる記憶された専門的知識を利用することによって、このようにして、繰り返しの注文をより効率的に、以前に入力され開発された仕事情報を必要とせずに製造することを可能にする。
【0074】
しかしステップS.5で、もし現在の顧客の注文が以前の仕事と類似か、以前の仕事と同じであるが、たとえば仕事または参照番号またはバッチの大きさ等の修正が必要と決定されれば、ステップS.7での探索で捜し出した以前の仕事情報データはデータベース30から検索され、サーバー・モジュール32にいるオペレータによって編集し、修正される。編集機能を備えることによって、以前の仕事データを編集し、修正して新しい仕事データを作成し、現在の顧客の注文のためにデータベース30に格納できる。必要とする編集の量は、以前の仕事と現在の仕事間の類似性の程度による。編集の量は、参照または仕事番号またはバッチの大きさの単なる修正から/または、部品の寸法や定められた曲げ手順の編集のような、より広範囲な修正を含むものにわたる。以前の仕事情報の編集が終わると、修正された仕事情報はステップS.9でデータベース30に格納される。修正された仕事情報は新しい参照または仕事番号で格納できる。さらに、色々なデータベース管理機能(コーピー、削除、保管、再命名等)を備えることによって、特別なコマンドの入力でデータベース30の以前の仕事情報の保持、または以前の仕事情報の消去または上書きができる。
【0075】
現在の仕事に適合する類似または同一のものが無く、従って現在の顧客の注文は新しい仕事に関係することが決定されると、論理フローは図4に示すステップS.15に進む。この場合、現在の仕事は新しい仕事に関するものになるので、設計製造情報を独立に作成し、入力しなければならない。サーバー・モジュール32からメニュー及び/またはヘルプ画面を提供することによって、オペレータが必要な仕事情報すべてを入力するのを支援することができる。本発明の見地に沿って、サーバー・モジュール32のオペレータは、最初に新しい仕事の基本的な部品情報を入力することによって新しいフアイルを作成できる。部品情報は、たとえば参照または仕事番号、顧客の名前、部品の簡単な記述、仕事に必要なバッチの大きさまたは量及び予定引き渡し年月日を含む。特徴抽出データまたは探索キーもステップS.15で入力できるし、また、以下に記すように、このデータを自動的に作成するか、曲げモデルデータの作成と同時に抽出することができる。他のデータや情報もステップS.15で入力するか、部品の各曲げ線の曲げ角度、半径や長さを含む曲げ線情報のような曲げモデルデータの入力後か入力中に入力できる。ステップS.15に引き続き、論理フローは図4に示すように、オペレータによって曲げモデルデータがサーバー・モジュール32で開発され、入力されるように進む。
【0076】
曲げモデルの開発と入力は、顧客から提供された原図や情報に依存する。顧客の注文は、たとえば製造される部品の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図面の提供と表現は、設計プログラマー、曲げオペレータや他のユーザがより容易に解釈され理解される部品のモデリングとシミュレーションの図を与える。厚さ情報を省くことはまた、サーバー・モジュールやステーション・モジュールで、文中に記述の本発明の色々な特徴を実行し達成するのに要する処理時間を短縮し、改善する。このような特徴のより詳細な記述や、本発明で利用することができる折りたたみと展開アルゴりズムについては、以下に付図を参照しながら記述する。
【0077】
図4は曲げモデルを開発するときに行われる一般的な処理と操作を示す。受理した、または顧客の注文にもとづいて開発され、曲げモデルデータを作成するために入力できる色々なタイプの図面は、一般的にステップ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に取り入れられる。
【0078】
一方向平面図が提供された場合は、曲げモデルを作成する処理は、図4に示すようにステップS.19から始められる。ステップS.19で、受理または作成された2-D平面図はサーバー・モジュール32に入力される。部品の全体的な寸法(幅、高さ、深さ)のような他の曲げモデルデータ及び部品材料情報もステップS.19で入力できる。その後、折りたたみアルゴリズムまたは処理を用いて、ステップS.21に一般的に示されているように、元の2-D一方向図面にもとづいて3-Dモデル(材料の厚さのない)を作成することができる。2-D平面図から3-Dモデルを作成するのに行われる処理や操作の例は、図11-18を参照しながら後で述べる。
【0079】
部品の3-Dワイヤーフレーム図(材料厚さの無い)が受理または作成された場合、図の情報はステップS.27で入力される。さらに、他の曲げモデルデータ、たとえば部品の全体的な寸法(幅、高さ、深さ)及び部品材料情報もステップS.27で入力できる。この後に、ステップS.27に示すように、部品の2-Dモデルを作成するために、サーバー・モジュール32で展開のアルゴリズムまたは処理が実行される。2-Dモデルを3-D図面(厚さのない)から作成するために行われる処理と操作の例は、たとえば図19を参照しながら後で述べる。
【0080】
部品の2-Dと3-Dモデル表示は、その部品のための曲げモデルの一部として格納される。さらに、前に注記したように、2-Dと3-Dモデルの作成と格納の間に、他の曲げモデルデータ(部品材料情報やその他の製造情報のような)も入力し、曲げモデルデータとともにデータベース30に格納できる。曲げモデルデータを編成し、格納するために実施できる、いろいろな機能やデータ構造配列についてはあとでより詳しく記述する(たとえば図26と27を見よ)。
【0081】
図4に示すように、簡単な3-D図面(材料厚さなしの)がもともと作成または受理されていない場合は、最終的な2-Dモデルを作成するのに必要な展開アルゴリズムまたは処理を行う前に、部品の3-Dモデル(厚さなし)を作成するための付加的な処理が必要となる。ステップS.23、S.25、S.31とS.33は、ステップS.29で展開アルゴリズムを実行し、2-Dモデルを作成する前に、サーバー・モジュール32で一般に実施される付加的な処理と操作を示す。
【0082】
たとえば、部品の2-D、三方向図面(三面図)がはじめに提供または作成されている場合、ステップS.23で図面はサーバー・モジュール32に入力または取り入れることができる。さらに部品の全体的な寸法(幅、高さ、深さ)のような他の曲げモデルデータや部品材料情報もS.23で入力できる。引き続きステップS.25では、入力された2-D三方向図面にもとづいて、部品の簡単な3-D平面図が作成できる。作成された3-D図面は、図4に示すように、ステップS.29で2-Dモデルを作成するのに用いられる。3-Dモデルを2-D三方向図面から作成する処理と操作の例は、あとでたとえば図20を参照しながら述べる。
【0083】
しかしながら、もし材料厚さが入っている3-D図面がもともと受理または作成されている場合、展開アルゴリズムを適用する前に、さらに先の処理のため図面情報をステップS.31で入力する事ができる。他の曲げモデルデータ、部品の全体的な寸法(幅、高さ、深さ)と部品材料情報もステップS.31で入力できる。そのあとステップS.33で、3-D図面にある厚さを削除するための厚さ削除手順を行うことができる。本発明の見地に沿って、サーバー・モジュール32は、オペレータまたはユーザーが厚さ削除手順を実行するとき、図面に厚さを示し、どの表面(外側か内側か)を保存するかを示すように促すことがある。本発明で利用できる厚さ削除手順については、たとえば図24(a)と24(b)を参照しながら下記に述べる。ステップS.33で3-D図面の厚さが削除された後、論理の流れはステップS.29に進み、そこでは最終的2-Dモデルを作成するために、改訂された厚さの無い3-Dモデルを利用して適当な展開アルゴリズムまたは処理が施される。3-D図面から2-Dモデル作成するための展開処理と色々な処理や操作は、たとえば図19を参照しながら下記に述べる。
【0084】
図4に示すように、すべての重要な情報が作成され、入力された後、顧客の注文に関連する部品情報、曲げモデル情報及びその他のデータは、ステップS.35でサーバー・モジュール32からデータベース30に移されて格納される。データベース30に格納されたデータは、データベース探索を行うときに利用できる特徴抽出または探索データも含む。下記に述べるように、特徴抽出または探索データは、各仕事に関連した部品の基本的または主要な特徴を指示するデータも含まれ、これによって仕事情報や格納されている同一または類似部品に関する専門的知識の探索が実施できる。サーバー・モジュール32に入力されたデータと情報は、たとえば図3に示すように、直接データベース30に、または通信ネットワーク26を介して転送することができる。上述のように、曲げモデルデータを作成するときに、色々な図面に対して実施できる各種の処理や操作についての詳しい記述は、下記に付図を参照しながら記す。
【0085】
図5は薄板製造設備38の場所10,12,14...20に設けられ、各ステーション・モジュールで実施される基本的な処理や操作の流れ図を示す。例証のため、図5は、たとえば曲げステーション18に置かれたステーション・モジュールで実施される基本的な処理や操作の基本論理の流れの例を示す。本発明の教示にもとづく技術に熟練した者には理解できるように、図5に示す論理の流れは、各場所で実施される操作や処理の性格により、各ステーション・モジュールで修正できることは勿論である。さらに、サーバー・モジュール32と同様、下記に述べるステーション・モジュールでの処理や操作にはソフトウエアまたはプログラム化論理を装備できる。加うるに、ステーション・モジュールは、オペレータまたはユーザーによる色々な処理や操作の選択と実施を容易にするために、ツール・バー・アイコンまたはヘルプ及び/またはメニュー画面をもつウインドウズ・ベース・アプリケーションを含むことができる。このようなヘルプ及び/またはメニュー画面は、ステーション・モジュールにおいてデータの入力または転送を容易にするためにも設けることができる。
【0086】
図5に示すように、ステップS.51でステーション・モジュールを初期設定した後、オペレータはステップS.53で一つまたは一つ以上のデータベース探索基準またはキー項目を入力することができる。探索基準は、データベース30に格納されている以前の仕事情報、または新しいまたは現在の仕事に関する仕事情報を捜し出すために入力できる。オペレータは、たとえばデータベース30から特定の仕事情報を検索するために、予め定められた番号またはコードを入力できる。たとえば、本発明の見地に沿って、バーコード をルーチングシートに付すか、せん孔された材料につけて、ステーション・モジュールでバーコード読みとり装置でスキャンすることによって情報をアクセスすることができる。あるいは、参照コードまたは番号を、ステーション・モジュールでキーボードまたはデイジタル入力パッドを介して手動で入力できる。変換テーブルを備えることによって、部品参照または仕事番号のオペレータによる入力によって、以前の仕事情報を定めることもできる。さらに、探索基準またはキーを入力することによって、以前に格納した仕事情報の類似部品探索を行うことも予想される。このような探索は、部品の色々な設計特性または特徴抽出データにもとづいて行うことができる。本発明の見地に沿って実行できる類似部品探索の説明は、下記に図6-10を参照しながら記す。
【0087】
探索基準をステップS.53で入力した後、ステーション・モジュールはステップS.55で、通信ネットワーク26とネットワーク・データベース・モジュール34を介してデータベース30の探索を実行できる。探索の結果はステーション・モジュールに戻され、ステップS.57でオペレータまたはユーザーが新しい仕事または類似の以前の仕事に関する情報を要請したのか、または要請が以前の仕事の完全な繰り返しに関するものなのかを決めるために解析される。
【0088】
同一のものが見いだされる(たとえば同じ部品または参照番号が突きとめられる)と、以前の仕事の繰り返しが決定され、仕事に関する格納されている設計と製造情報がデータベース30からステーション・モジュールに転送され、ステップS.59に一般的に示しているように、オペレータが見られるように表示される。ステーション・モジュールは一つまたは一つ以上のメニュー表示画面または登録簿をもち、オペレータがデータベース30から検索された色々な情報を選択し、表示できるようになっている。オペレータは表示された情報をレビューし、ステップS.61における3-D曲げシミュレーションのような、色々なシミュレーションを走らせて、その仕事の曲げ手順の色々な段階を観察し、部品の幾何学を理解することができる。オペレータはまた、必要工具や仕事情報に記録されている他の特別な命令やメッセージのような他の情報をレビューすることもできる。仕事情報の確認が終わると、オペレータは曲げ、または他の必要な機械類を構成し(組立)、機械を操作して指定された薄板金属部品を製作することができる。データベース30から検索された仕事情報は、たとえば曲げステーション18の機械類を制御する曲げコードを含む最終曲げ計画データを含む。機械類の構成と実際の操作は、このようにして図5のステップS.63に一般的に示してあるように、オペレータによって遂行される。
【0089】
もし同一または類似の仕事情報が捜し出されず、情報が新しい仕事(つまりサーバー・モジュール32には予備的な仕事情報のみ入力され、完全な仕事情報が作成されていない)に関するものであることが決定した場合、部分的な部品情報と曲げモデルデータはデータベース30から引き出されてステーション・モジュールに送られ、ステップS.77でオペレータによって観察される。要請した情報は新しい仕事に関するものなので、オペレータは必要な工具と曲げ手順を含む曲げ計画を作成し、入力する必要がある。下記により詳しくのべるように、曲げオペレータによる曲げ計画の作成を容易にするため、ステーション・モジュールにグラフイカル・ユーザー・インターフエース(GUI)や他の機能を備えることができる。GUIは、たとえば工具の選択、部品と工具間の潜在的な不一致の自動点検、及び提案された曲げ手順の各中間段階のシミュレーションを表示することによってオペレータが曲げ計画を作成するのを支援するために設けることができる。サーバー・モジュールで曲げ計画を作成し、入力したオペレータは、ステップS.80で曲げコード(曲げ機械で曲げ手順を実行するためのCNCまたはNCコード)を生成するために曲げ手順をプログラムする。曲げコードは直接サーバー・モジュールで入力するか、曲げ機械類のCNCまたはNC制御装置とインターフエースしてサーバー・モジュールに取り入れることができる。しかる後、オペレータはステップS.81で、曲げ作業ステーションにおいてセットアップし、曲げ計画をテストすることができる。曲げ計画に必要なすべてのテストと必要な修正が完了すると、ステップS.83で最終的な曲げデータをデータベース30に入力し格納する。最終的な曲げデータは、曲げプログラムとともに、曲げ手順と工具構成情報を含む。この情報は、たとえば曲げステーション18のステーション・モジュールからデータベース30に送られ、新しい仕事に関する他の設計製造情報とともに格納される。
【0090】
図5のステップS.57で、情報が以前の仕事の類似部品または同じ部品に関係しているが、たとえば異なる参照あるいは仕事番号またはバッチ量等をもつことが決定されれば、論理の流れはステップS.65に進む。ステップS.65では、以前の仕事情報がデータベース30から検索され、曲げステーション18で表示される。曲げオペレータまたはユーザーはデータを見て、類似部品に必要なデータの変更が何かを決める。この場合もステーション・モジュールは一連のメニュー表示画面または登録簿(ディレクトリ)を備えて、オペレータが、表示する情報と、情報をどのように表示または修正するかの選択ができるようにされている。たとえば、ステップS.69では、オペレータの類似部品の曲げ計画の作成を容易にするため、検索された情報にもとづいた3-D曲げシミュレーションを備えることができる。以前の仕事情報をレビューした後、オペレータはステップS.70で、曲げプログラムとともに、工具と曲げ情報を修正する。部品の寸法、参照番号やバッチ量のような他の仕事情報もステップS.70で修正し、編集することができる。これが終わると、ステップS.71で実際の工具セットアップとテストが、オペレータによって作業場において、修正された曲げ計画をテストするために行われる。テストと曲げ計画をさらに修正することが完了すれば、オペレータはステップS.73で最終的な曲げデータを入力し、それに新しい参照番号または仕事番号をつけてデータベース30に格納する。上記のように、以前の仕事情報もデータベース30に、他の格納された仕事フアイルとともに保持できる。さらに、色々なデータベース管理機能を、データベースに格納されているフアイルを格納、消去、再命名等するために備えることができる。
【0091】
次に図6-10を参照しながら、本発明の教えるところに従って実行できる類似部品探索機能の例を詳しく述べる。本発明の見地に沿って、特徴ベース形態類似性探索アルゴリズムを利用する類似部品探索手続きを、データベース30から以前の仕事情報を探索し、検索するのに備えることができる。類似部品探索は製作される部品に関する設計特徴及び/または製造情報にもとづいた同一及び/または類似部品の探索を含むことがある。また類似部品探索は、たとえばサーバー・モジュール32及び/または工場38内の色々なステーション・モジュールにあるソフトウエアまたはプログラム化論理の使用によっても実施できる。類似部品探索はサーバー・モジュール32または薄板金属曲げ工場38内の場所10,12,14...20のいずれかで実行できる。C++またはマイクロソフト社のビジュアルC++プログラム言語のような、高レベルのプログラム言語とオブジェクト指向プログラム技法が類似部品探索の色々な処理や操作を実施するのに利用することができる。
【0092】
図6と7は利用できる類似部品探索アルゴリズムまたは処理の論理の流れを示す。図6に示すように、重要な部品モデルデータフアイルはステップS.100でアクセスできる。部品モデルには、たとえば設計事務所10に置かれたCADシステムで作成された曲げモデルデータ及び/またはサーバー・モジュール32で作成され、入力されたデータが含まれる。部品モデルには、たとえば部品の色々な表面または面及び曲げ線の向き、幾何学的関係及び相対位置を表す部品形態データ(部品トポロジーデータ)が含まれる。部品モデルデータが検索され、または曲げモデルデータが手動で入力された後、ステップS.102で、当該部品の曲げモデル及び/または部品形態データにもとづいた特徴抽出データを自動的に導出するための特徴抽出操作を行うことができる。
【0093】
本発明の見地に沿って、特徴抽出データは、薄板金属部品の色々な特徴を解析することによって導出できる。たとえば、部品の色々な面の解析によって、隣り合わせの面が開放または接触コーナーをもつかどうかを決めることができる。平行曲げ、直列曲げ、共線曲げまた対向曲げのような他の特徴も、各部品の明確かつ独特な特徴を決定し、抽出するために解析することができる。
【0094】
表1は類似部品探索を行うときに解析される色々な曲げと面の特徴を示す。特徴抽出操作に含めなければならない抽出特徴は、正の曲げ、負の曲げ特徴とともに接触コーナー、開放コーナー特徴である。さらに特徴抽出操作は、少なくとも平行曲げ、直列曲げ、共線曲げ、異相共線曲げ及び厚さオフセット曲げの特徴解析を含まなければならない。
【0095】
ステップS.102で行った特徴抽出操作は、各特徴の曲げモデルデータと形態(トポロジー)の解析、形態の修正、今後の解析のための形態にもとづく特徴ベース行列(特徴に基づく行列)の作成からなる一連の操作を含むこともある。例証のため、図8(a)―9(d)に接触コーナーをもつ4折り曲げ箱部品と開放コーナーをもつ4折り曲げ箱部品に対する特徴抽出操作を示す。
【0096】
【表1】

Figure 0003884195
例証のため、図8(a)-9(d)には隣接面のコーナー関係にもとづく特徴抽出が示されている。図8(a)に示す五つの面(1-5)をもつ閉じた4折り曲げ箱や、図8(b)に示す五つの面(1-5)をもつ開いた4折り曲げ箱については、いずれの部品を表すにも、図8(c)に示す同じ簡単な面形態が提供される。この形態は部品または曲げモデルデータとともに格納し、提供することができる。しかしながら、図8(c)の単純な面形態(面トポロジー)は、部品の面(1-5)の間の関係の基本的な情報しか与えず、隣接する面間のコーナーの関係や曲げの種類のような部品の色々な特徴の情報は与えない。従って、特徴抽出操作時に、部品または曲げモデルデータとともに格納されている関連面形態をを解析することにより、基本的な面形態が部品の色々な特徴についての付加的な情報を含むように修正することができる。
【0097】
たとえば、図8(a)の閉じた4折り曲げ箱の部品または曲げモデルデータを調べることにより、隣接面間のコーナーが解析でき、図9(a)に示されている修正された面形態が作成でき、これによって各面間の接触コーナー状況を示すことができる。同様に、図9(a)に示されている開いた4折り曲げ箱の部品または曲げモデルデータを調べることにより、図9(b)に示す修正された面形態を作成し、それによって部品の色々な隣接する面の間の開放コーナー関係を示すことができる。図9(a)と9(b)に示すように、面形態に面のコーナーの関係(たとえば接触または開放)を示す特別の連結線を加えることができる。他のデータも他の特徴(たとえば存在する曲げの形式)を示すため、及び特徴ベース面形態を作成するために加えることができる。特徴ベース情報が含められるように形態を修正した後、抽出情報をより簡単に解析し、比較するために行列を作成することができる。たとえば、図9(a)の特徴ベース面幾何学にもとづいて、図9(c)に示す行列を作成し、これによって図8(a)の閉じた4折り曲げ箱の色々な特徴を示すことができる。同様に、開いた4折り曲げ箱に対しては、たとえば図9(b)に示す特徴ベース面形態にもとづいて、図9(d)に示す行列を作成できる。他の特徴抽出データ、たとえば部品の曲げ特徴(たとえば90゜正の曲げ角度または90゜負の曲げ角度等)も行列の中に示すことができる。
【0098】
上記のように、ステップ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、ビユー行列、半径、角度開始、角度終了)で指定することができる。部品形態データも、部品の色々な面や曲げ線の場所やこれらの間の幾何学的関係を示すために提供することができる。各面は線と/または弧の集合または連結データリストで定義することができる。
【0099】
部品の特徴を抽出するため、曲げモデルと形態データの特徴抽出操作を行い、解析することによって、ある特徴が部品に存在するかどうかを定めることができる。このプロセスは、抽出する各特徴間の色々な特色や関係にもとづく、曲げモデルと形態データの解析を含むこともできる。各特徴の特色と関係を知るための曲げモデルと形態データの解析によって、ある特徴(たとえば面間の接触コーナー、開放コーナー特性、または平行または直列曲げ特性)の存在が検出できる。異なるプロセスを、各特徴の特定の特性と関係を特徴抽出操作で検出するために備えることもできる。解析される各特徴間の特性と関係の類似性にもとづいて、部品に一つ以上の特徴が存在するかどうかをチェックするために幾つかのプロセスを組み合わせるか作成することもできる。
【0100】
限定されない例として、ステップS.102における特徴抽出操作の際に、コーナーの特徴、たとえば同じ曲げ方向をもつ二つ面の接触コーナー特徴(表1のTouchCnr特徴)を抽出し、検出するために行うことができるプロセスについて述べる。下記のプロセスは、他の特徴の検出、たとえば逆曲げ方向をもつ二つの面の接触コーナー特徴(表1のtouchCnr特徴)または同じまたは逆曲げ方向を持つ二つの面の開放コーナー特徴(表1のOpenCnrとopenCnr特徴)に用いることもできる。プロセスを修正することによって、他の特徴も検出できる(たとえば平行曲げ、直列曲げ等)。さらに、面の可能な各組み合わせに関するデータを、抽出される各特徴の特性と関係を知るために解析することができる。
【0101】
たとえば、接触コーナーの特徴をもつTouchCnrの場合、検出する特徴または関係は:共通の面を持つ二つの面;同じ曲げ線方向;同じ頂点を(または頂点間の距離が事前に定めた範囲内にある頂点)をもつ曲げ線を含む。接触コーナーの特徴をもつtouchCnrの場合、同様の特性または関係を検出しなければならない;ただ同じ方向の曲げ線をもつ面ではなく、面は逆方向の曲げ線をもっていなければならない(たとえば表1をみよ)。開放コーナー特徴OpenCnrとopenCnrも同様に検出できるが、各特徴に接触コーナー関係の代わりに、面間に開放コーナーが存在する(たとえば面の曲げ線が事前設定の範囲の距離より大きく隔たっている)ことと、同じまたは逆の曲げ線方向(たとえば表1と表中のOpenCnrとopenCnrの定義をみよ)をもつ曲げ線を検出し、解析しなければならない。
【0102】
接触コーナー特徴(たとえば表1のTouchCnr特徴)を検出するためには、先ずある二つの面を解析し、二つの面が共通の面に接続しているかを決定する。これは各面の曲げ線データと各曲げ線の曲げ線―面関係データを探索して、共通面が存在するかどうかを決定することによって検出できる。もし二つの面が共通の面に接続していれば、各面の曲げ線方向を解析して同じ曲げ線方向(または、たとえばtouchCnr特徴を検出する場合は逆の曲げ線方向)をもつかを見る。これは、たとえば各面の曲げ線方向を示すベクトルデータを解析する事によって決められる。
【0103】
二つの面が共通の面をもち、曲げモデルと形態データにもとづいて同じ曲げ線方向をもつことが決定されると、データを検査することによって曲げ線が平行かどうかが検出される。色々な方法を用いて、曲げモデルと形態データにもとづいて曲げ線が平行かどうかを検出することができる。たとえば、平行曲げ線の検出は、曲げ線方向を定めるベクトルの外積をとることによって決められる。もしベクトルの外積がゼロ(または近似的にゼロ)であれば、曲げ線は平行であると決定される。もしベクトルの外積がゼロでなければ(または近似的にゼロでない)、二つの面の曲げ線は平行でない。
【0104】
二つの面が共通の面をもち、曲げ線方向が同じで曲げ線は平行ではないことが決まった後、面の間のコーナーの関係(たとえば接触か開放か)を決めるために、曲げモデルデータが解析される。二つの面のコーナー関係は、曲げモデルデータから、面の曲げ線が共通の頂点をもつかどうかを検出することによって決められる。曲げ線が共通の頂点をもっていれば、二つの面は同じ曲げ線方向の接触コーナー関係(表1のTouchCnr特徴)をもつ。曲げ線は共通の頂点をもっているが、二つの面の曲げ線方向が異なることが決まれば、二つの面は逆方向の接触コーナー関係(たとえば表1のtouchCnr特徴)をもつと決められる。
【0105】
二つの面が共通の頂点をもっていない場合でも、頂点間の距離が予め定められた範囲内であれば、二つの面は接触コーナー関係をもつと決定できる。しばしば部品の隣接する面の間に、たとえばパンチ工具を通すためのすき間として最小限のスペースが設けられることがある。このスペースは、通常フランジの高さのところでの工具の幅で決められる。例をあげれば、二つの面の曲げ線の頂点間の距離が0-5mm以内であれば、接触コーナー特徴の存在が決定できる。もし二つの面のコーナー間のスペースが、事前に定められた範囲より大きければ、開放コーナー特徴の存在が決定できる(たとえば表1のOpenCnrまたはopenCnr特徴)。
【0106】
上記のプロセスは部品の面のあらゆる組み合わせについて、各面のコーナー特徴を決めるために実施することができる。部品の面や曲げ線に関連する他の特徴も、同じように部品幾何学と形態データの解析によって行うことができる。ステップS.102における特徴抽出操作を実行するための典型的なコードを付録Aに示す。このコードはC++プログラム言語で書かれており、表1に記してあるような特徴を抽出検出するための色々なプロセスを含む。付録Aのコードには、使用されている論理やアルゴリズムの解析を容易にするためのコメントがついている。またこのコード例では、色々な特徴の理解を助けるために、表1と同じ特徴の用語が使われている。
【0107】
部品の色々な特徴が検出されると、部品の基本的な形態は修正され、抽出された特徴が含められる。特徴ベース形態を提供することは有用かもしれないが、このような形態をお互いに比較することは容易でない。その代わりに、本応用の発明者達は行列の形で提供された特徴抽出情報を比較する方が、より有効で容易であることを発見した。従って、本発明の一つの特徴として、特徴抽出操作の際に、検出された特徴にもとづいた特徴ベース部品行列(図9(c)と9(d)に示す代表的な行列のような)が作成される。作成された部品の特徴ベース行列は、他の所定の、格納された行列と比較することによって、どのような基本的な形や特徴が部品に含まれているかを決定する。
【0108】
特徴ベース行列は、部品の色々な特徴を検出し、抽出した後に、部品毎に作成され、格納される。図9(c)と9(d)に示すように、行列は対称的な2次元行列で部品の面の数に等しい次数をもつ。行列は部品のすべての検出された特徴情報を含み、各面の間の色々な特徴が行列の各場所に提供されている。特徴ベース行列は、一時的にサーバーまたはステーションモジュールの記憶装置に格納し、類似部品探索を実行するときにのみ使用し、所定の行列と比較することができる。あるいは、特徴ベース部品行列を永久的に他の仕事情報とともにデータベース30に格納し、工場内のどの場所でもアクセスできるようにすることができる。
【0109】
図6に戻ると、特徴抽出操作を行った後、引き出した特徴抽出データ行列を、特徴形態ライブラリに備えられている所定の特徴抽出データ行列と比較することができる。特徴形態ライブラリは、別のデータフアイルとして、データベース30のようなデータベース、またはサーバー・モジュールかステーション・モジュールに格納しておくことができる。特徴ライブラリは、基本的または基礎的な部品の形状(たとえば4折り曲げ箱、橋梁等)に対応するまたは定義する特徴抽出データを含む所定の行列よりなる。各所定特徴ベース行列は、特徴ベース部品行列とともに、ASCIIまたはテキストフアイルとして格納できる。ステップS.104のおける比較は、ステップS.106に図示されているように、薄板金属部品に存在する基本的または基礎的な形状/特徴を決めるために行われる。格納されたルックアップテーブルを、どの基礎的な形状が各所定特徴行列に対応するかを示すためにを備えておくことができる。一致するものが見いだされると、ステップS.106でどの基礎的形状が存在するかを決めるために、ルックアップテーブルがアクセスされる。事前定義ライブラリに存在する一致する行列は、特徴ベース部品行列と同じ次数であるか(この場合は部品はただ一つの基礎的形状を含み、精確に対応することが決定される)、または部品行列のサブ行列かもしれない(この場合は部品は一つ以上の基礎的形状を含むかもしれない)。
【0110】
特徴ベース部品行列を事前定義ライブラリにある行列と比較するために再帰プログラミング技法を利用することができる。含まれている情報を比較するとき、行列の指標を入れ替えることによって、データ割り当ての使用が避けられ、必要なプロセス時間が短縮される。再帰プログラミング技法と指標の入れ替えはまた、異なる次数と異なる基底面をもつ行列の比較を容易にする。
【0111】
本発明の見地に沿って、ステップS.104で実施される比較操作は、一連の比較よりなり、最初により複雑な形状(たとえば多数の曲げ、またはタブのような複雑な成形を含む形状)に関する行列の比較から開始し、より複雑でない形状(たとえば、より少ない曲げ、またはより複雑でない曲げ、より少ない数の面をもつ形状)へと進む。この一連の比較は部品に、所定数の基本的形状が見いだされるまで行われる。たとえば、比較操作はある特定の部品の三つの最も複雑な特徴または形状を抽出するために行うことができる。さらに、この操作を最初に、薄板金属部品によく、または度々みられる形状に関する行列のグループに対する一連の比較から始め、次により一般的でない形状に進むこともできる。部品を事前定義ライブラリと比較するために、色々な方法を有用な結果をうるために行うことができる。
【0112】
たとえば、一連の比較操作を先ず、多数の直角曲げを持つ長方形や正方形形状や直角曲げをもつ単純な部品のような、直角曲げをもつ基本形状を含む行列の直角グループに適用することができる。この行列のグループは、グループの中の、より複雑な行列(たとえば、タブをもつ四つ折り曲げ箱に対応する行列)からグループの中のより単純な行列(たとえば、単純ハット部品に関する行列)へと進める一連の比較にもとづいて探索することができる。それから一連の比較を多角形部品グループの行列に、さらに特別特徴グループの行列へ適用することができる。多角形部品グループは五つ以上の側面と、少なくとも90度以上の曲げを一つもつ部品を定める行列を含みうる。特別特徴グループの行列は、Z―曲げまたは縁取り曲げのような、特別な特徴または成形をもつ部品に関係する事前定義ライブラリ内の行列を含みうる。ここでもまた、部品の特徴ベース行列と各グループの所定行列との間の一連の比較は、複雑性の度合いの減少に従って行われる。この後に、部品の一つの面に二つまたは二つ以上の特徴をもつ多重特徴グループのような、所定行列の他のグループを比較することができる。
【0113】
複雑性の度合いに従って部品を事前定義ライブラリの行列と比較し、実現と使用頻度にもとづく行列のグループの一連の比較をすることによって、部品に存在する基本的な形状の決定するためのライブラリとのより効果的で有効な比較ができる。さらに、検出特徴の重複が防がれ、より複雑な形状のみが識別される。
【0114】
ステップS,108では、部品にある基本的な特徴または形状間の関係を決めるために特徴関係操作を行う。特徴または形状間の関係は距離によって定められる。二つの形状間の距離は、各々形状の基底面(基本面)の間の曲げ線または面の数にもとづいて決められる。あるいは、特徴間の関係は、部品及び、各特徴の基底面の相対位置と間隔を幾何学的に解析することにより、特徴間の物理的な距離または実際の寸法によって定めることができる。
【0115】
例示のため、ステップS.106で決定した部品の三つの最も複雑な特徴または形状は、図10(a)に示す4折り曲げ箱と、ブリッジと、もう一つの4折り曲げ箱とであるとしよう。このような部品については、特徴関係操作を、たとえば各基本的特徴の基底表面または面の間の曲げ線の数を決めるために行うことができる。図10(b)で示すように、第一の4折り曲げ箱の基底(1)とブリッジの基底(2)の間の特徴関係は、二つの曲げ線の間隔である。さらに、第一の4折り曲げ箱の基底(1)と第二の4折り曲げ箱の基底(3)の間の関係は、四つの曲げ線の間隔であり、ブリッジの基底(2)と第二の4折り曲げ箱の基底(3)の間の関係は、二つの曲げ線の間隔である。
【0116】
いろいろなプロセスによって、部品の基本形状の基底面間の曲げ線の数を決めることができる。たとえば、特徴ベース部品行列と所定形状行列を利用して、ステップS.108で特徴関係を決めることができる。最初に、部品行列にある各基本形状に対応する基底面を捜し出す。これは所定形状行列の基底面を、部品行列の面指標と相関することによって行うことができる。前に論じたように、比較操作で切り離した所定形状行列は、部品行列のサブ行列かもしれない。部品行列で各基本形状に対応する基底面を捜し出すには、部品行列内の形状行列の位置と行列の指標の間の相関を解析する。各基本形状の基底面は、予め定められており形状行列の第1列に位置しているので、部品行列内の対応する位置と基底面を捜しだすことができる。
【0117】
特徴ベース部品行列内の各基本形状の基底面を決定した後、特徴関係を決めるために、各形状の基底面間の距離を解析する。この解析は、如何なる二つの基底面間の距離をも同定する探索プロセスを含んでいる。部品行列内の特徴と曲げ線情報を見ることによって、どの二つの基底面間の曲げ線の数でも決定できる。二つの面の間に一つ以上の経路が可能な場合には、最小距離を用いてステップS.108において特徴関係を定義することができる。
【0118】
特徴関係操作を終えた後の論理の流れはステップS.110に続く。図7に示すように、ステップS.110では、データベースの類似部品探索に用いる探索キーを決めるために、データベース探索キーの同定が行われる。探索キーは、部品に同定された特徴や特徴関係の幾通りもの組み合わせを含みうる。さらに、探索キーをアセンブルするのに、どのような基準の階層も用いることができる。限定されない例として、下記の基準に従って探索キーを作成することができる:(i)部品に同定された一番目と二番目に複雑な特徴または形状;(ii)最も複雑な二つの特徴間の距離または特徴関係;(iii)部品に同定された三番目に複雑な特徴または形状;及び(iv)部品に同定された一番目に複雑な特徴と三番目に複雑な特徴間の特徴関係または距離、及び二番目に複雑な特徴と三番目に複雑な特徴間の距離または特徴関係。図10(c)に図10(a)の例にもとづいて開発された探索キーを示す。
【0119】
データベースの探索を容易にするために、探索キーは、形状ライブラリで定義された色々な基本形状に割り当てられた所定コードをもつ整数の列で表すことができる。たとえば、4折り曲げ箱に整数コード“16”が割り当てられ、ブリッジに整数コード“32”が割り当てられたとしよう。この場合、図10(c)の例の探索キーは、整数列“16,16,4,32,2,2”で表され、このなかで“4”と“2”は基本形状または特徴間の色々な距離を表す。しかしながら、探索キーの表示は、整数列に限定されるものではなく、どのような組み合わせの整数及び/または文字列を探索キーの表示に用いることができる。
【0120】
各部品の探索キーは、仕事情報とともに(別のフアイルまたは同じフアイルに)、データべース、たとえばデータベース30、に格納できる。特徴抽出データの代表的な探索キーは、手動で入力するか、上記のように自動的に作成できる。特徴ベース部品行列のような付加的特徴抽出データは、探索キーを用いて格納できる。探索キーが別のフアイルに格納してあるときには、各探索キーのセットと関連する部品情報を捜し出すための参照用テーブルを用意できる。あるいは、探索キーは部品情報を同定する(たとえば部品または参照番号によって)データフイールドとともに格納しておくことができる。
【0121】
ステップS.112では、同定された探索キーにもとづくデータベースの協調探索が行われる。協調探索は、協調データベース探索技法を用いる探索である。協調探索技法は、同一の探索キーをもつ部品ばかりでなく、類似の探索キーを持つ部品を捜し出す。これによってデータベースにある、類似および同一部品を同定することができる。特定の部品についての探索を行うと、その部品のものと同定された探索キーを、データベースにある他の探索キーデータと比較することができる。ステップS.112で行われる協調探索は、探索キーの順序を緩めるか修正することによって、データベースにある項目で、探索キーによって同定された特定の部品と正確に一致するか又は最も類似している項目を同定するように構成される。色々なプロセスと方法を、協調探索において探索キーを適合させるのに用いることができる。
たとえば、最初にデータベースの探索を、探索する部品のものと同定されたものと正確に一致する探索キーの順序をもつ部品を同定するために行うとする。これは同定された探索キーをデータベースに格納されている探索キーと比較することによって行われる。同じ探索キーをもつ部品(もしあれば)を同定した後、引き続き他の類似部品を捜しだすために、異なる修正された探索キー順序に基づくデータベースの探索を行うことができる。最初探索キーにある、あまり重要または敏感でない項目または基準(特徴関係または距離のような)は、より重要または敏感な探索項目(部品にある基本的な特徴または形状のような)を修正する前に修正し、探索することができる。さらに、これらの各項目は、項目の重要度に従って修正し、部品にある一番目と二番目に複雑な特徴または形状に関連する項目に、より高い重みまたは重要度を当てることができる。たとえば、ひき続き最初に行う探索は、三番目に複雑な特徴と一番目、二番目に複雑な特徴間の定義された距離を修正した後に行うことができる。この距離は、所定曲げ線数(たとえば1-3)だけ変更し又は現在の距離に基づいた距離の所定範囲を定義することによって修正できる。しかる後、一番目と二番目に複雑な特徴または形状間の距離を変更して、データベース探索用の修正された探索キーの組をもう一つ備えることができる。部品の特徴関係または距離の探索キーを修正した後、同定された形状を、協調探索における付加的な修正探索キーを導くために変えることができる。たとえば、三番目に複雑な特徴または形状に関する探索キー項目を、現在扱っているものの特徴または形状によって、関連するがより複雑でない形状に変えることができる(たとえばタブのある4折り曲げ箱を単純な4折り曲げ箱に)。さらに、一番目と二番目に複雑な特徴の探索キーを同じように変えることによって、さらに協調探索のための修正探索キーを加えることができる。
【0122】
探索キーに関係する距離と特徴/形状の、協調探索中の修正は、いろいろな方法と技法によって実行できる。上記のように、どのくらい距離を変えるかは、距離の現在値に依存する。距離の大きさ(たとえば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)にあり、そこに開示されている情報すべてを参照することによってここに取り入れられている。
【0123】
協調探索の間に、他のプロセスやステップを実施するこができる。たとえば、部品の特徴に関連していると同定された探索キーに基づいたデータベースの探索に加えて、部品の製造情報に関連した探索基準に基づいて探索することもできる。たとえば、付加的な探索キーを利用して、一例として各部品に必要な機械構成を比較することができる。機械構成情報は機械のタイプまたは部品を製作するために必要な機械類、部品を製作するために用いる工具類や工具構成および/または機械類のバックゲージング設定を含む。付加的探索キーは、機械構成情報および/または他の製造情報に基づいて開発することができ、本発明の協調探索をする際に、同定された探索キーとともに用いることができる。その結果、製作される部品と同一または類似な部品は、部品の設計と製造特徴両方に基づいて同定することができる。
【0124】
最も類似した部品を選ぶために、選択部品探索をステップS.114で実行し、協調探索の結果のより詳しい比較と、探索された部品と同じまたは最も類似している部品を所定数だけ選ぶ。選択部品探索は、協調探索で同定された各部品に対する付加的な情報や特性の解析を伴いうる。これは部品の寸法や部品にある孔や開口の形のような、捜し出された部品の色々な特徴の解析を含む。さらに各部品に要する機械構成のような、捜し出された各部品の製造情報の比較も含みうる。上記のように、機械構成情報は、部品の製作に要する機械の種類または機械類、部品の製作に用いる工具や工具構成、及び/または機械類のバックゲージング設定を含む。選択部品探索を行うために、各部品の曲げモデルや他の仕事情報が、協調探索で同定された探索キーに基づいてデータベースからアクセスされる。上記のように、各探索キーの組に対応する仕事参照番号またはコードを提供するために、ルックアップ表や付加的データフイルドを設けることができる。データベースから部品情報を検索した後、各部品の付加的情報(たとえば部品寸法、材料のタイプ、特別な成形、部品の孔または開口等)を、どの部品が探索された部品に最も類似しているかを決めるために解析できる。このプロセスはオプションで、データベースの部品で、当該部品に最も類似の部品を選び集約する付加的な選択プロセスの役割を果たす。この部品の付加的情報または特性を解析し、照合することによって、選択部品探索を、所定の数または組の最類似部品を同定または選択するために行うことができる。たとえば、選択部品探索で、照合探索キーの数と付加的部品特性の照合に基づいて、五つの最類似部品を同定できる。選択部品探索で選択される部品の数は五つに限らず、工場の必要性とデータベースに実際に格納されている部品の数に基づいて選ぶことができる。この数は、より有効で役立つ探索結果をうるために選択的に修正でき、またユーザーに探索の組を変えるために、この数を修正する機会を与えることもできる。
【0125】
選択部品探索を行った後、ステップS.116で部品をランク付けする(特徴の類似性や突き合わせ探索キーの数に従って)ために、類似性指標を計算することができる。類似性指標はステップS.116で計算され、サーバーまたはステーションモジュールの出力として提供され、これによってユーザーはどの仕事フアイルをデータベースから検索し、画面に映し出すかを選択できる。類似性指標によって、選択された部品と探索部品の特徴の類似性の程度に基づいて、選択部品のランク付け(たとえば各部品の仕事または参照番号を付してランク1から5)ができる。このためには各部品の特徴ベース行列を探索部品のものと比較する。特徴ベース行列の比較は、選択部品と探索部品の間の類似性をよりよく示す。前のべたように、特徴ベース部品行列は各部品の探索キーとともに格納できる。しかしながら、各以前の仕事の特徴ベース部品行列を探索キーとともに永久格納することは、不必要に大きな記憶スペースを占有する(特にデータベースに多数の部品が格納されている場合)。従って各部品の探索キー・データのみを格納し、類似部品探索を行うときに自動的に各選択部品の特徴ベース行列を生成することしかできない。 従って、選択部品の曲げモデルと他の仕事情報を検索した後、前にステップS.102についてのべたように、特徴ベース行列は本発明の特徴ベース抽出操作を通じて作成する。そのあとで、類似部品探索時に一時的に格納した探索部品の特徴ベース行列を、作成した選択部品の特徴ベース行列の各々と比較できる。色々な方法とプロセスを、部品の特徴ベース行列の比較と部品間の類似性の決定に利用できる。たとえば、各選択部品の特徴ベース行列について、行列内の場所を探索部品のものと比較できる。行列内の各場所は、再帰的プログラム技法に基づいて比較できる。行列内の情報は、各行列内の対応する基底面の場所を決め、行列の指標を交換することによって比較できる。選択部品は探索部品の副特徴に対応するか又はその形状をもつこともあり、又行列の指標が同一でないか、または同じ番号付けがされていないこともあるので、含まれている情報を比較するときに、部品行列内で比較できる面を捜しだして指標を振り替えなければならない。さらに探索部品の中に一つ以上の副特徴が存在する場合、行列内の情報を比較するとき、同じ次数の行列を提供するために、一つまたは一つ以上の擬似面(行列の行と列で情報が無いか空白のもの)を導入しなければならないことがある。
【0126】
行列の情報を比較するときに、各選択部品と探索部品の類似性の程度を決めるために、複数の異なる順序づけ方式を用いることができる。たとえば、所定ペナルティレベルまたは量を、行列内の整合しない各位置に割り当てるペナルティベース順序づけ方式を用いることができる。行列内のすべての情報を比較した後、各選択部品の総ペナルティレベルを用いて類似性の程度を決めることができる。最も低いペナルティレベルをもつ選択部品が、探索部品に最も類似した部品と決定される。他の選択部品も、各部品に付せられた総ペナルティレベルに基づいて順序づけできる(たとえばペナルティレベルが低いほど類似指標が高い)。
【0127】
本発明のさらなる見地に沿って、各非整合位置のペナルティレベルは、その位置にある情報のタイプに基づいて割り当てることができる。ペナルティレベルは整数量で非整合情報の重大性または重要性に応じて変えることができる。たとえば、異なる、関係のない特徴グループ(たとえば平行曲げ特徴対直列曲げ特徴)に関する非整合位置に対しては、高いペナルティレベルまたは量を割り当てることができる。これと対照的なのは、異なるが類似の特徴グループ(たとえば同じ曲げ線方向をもつ接触コーナー特徴対逆の曲げ線方向をもつ接触コーナー特徴)である。ペナルティレベルまたは量は、非整合位置に存在する情報のタイプと相違のタイプに従って事前に定義、類別される。
【0128】
ステップS.116における類似性指標操作の典型的なコードは付録Bに示されている。このコードはC++言語で書かれており、上に記述した行列の比較と非整合位置に対するペナルティレベルの割り当てに関する色々なプロセスと操作を含んでいる。上に付記したように、比較された各選択部品の結果としてえられた総ペナルティレベルは、類似性指標を導き、表示するのに用いることができる。付録Bにあるコード・リステイングには、記されている典型プログラム・コードの理解を助けるためのコメントも含まれている。
【0129】
次に図11−25を参照しながら、曲げモデルの開発と、色々な2-D、3-D図面に基づいた部品の2-D、3-Dモデルの開発を、本発明の見地に沿ってより詳しく記述する。前に論じたように、各薄板金属部品に関する曲げモデルデータは、部品の2-D、3-D表現両方に関連するデータを含んでいる。顧客の注文に基づいて提供または作成された原図のタイプに基づいて、色々な折りたたみと展開アルゴリズムや他のプロセスを2-D及び3-Dモデルの開発に利用できる。特に図11-18は、部品の元の2-D一方向図面(2次元単一図面)に基づいて、3-Dモデルを作成するに利用できる折りたたみアルゴリズムの論理の流れの例を示す。図19は、3-D原図(厚さぬき)に基づいて2-Dモデルを作成するのに用いられる展開アルゴリズムや他のプロセスの基本的な論理の流れの例を示す。最後に図20-24と図25は、2-D三方向図面(2次元三面図)と厚さありの3-D図面から、厚さぬきの3-Dモデルを作成するのに実施できる色々なプロセスや操作の論理の流れの例を示す。これらのプロセスや操作でえられた3-Dモデル(厚さぬき)は、文中に明示されているように、展開アルゴリズムまたはプロセスに基づいて2-Dモデルを作成するのに利用できる。
【0130】
図11は2-D一方向図面から折りたたみアルゴリズムを用いて3-Dモデルを作成するプロセスと操作の論理の流れを示す。図11の流れ図で行われる機能や操作は、たとえばサーバー・モジュール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によって自動クリーニングやクリーンアップ機能を実施することもできる。
【0131】
本発明の自動トリミングとクリーンアップ機能は、2-D平面図を、処理に対して準備するために備えられている。2-D平面図は、薄板金属部品の展開状態の2-D表示で、部品の幾何学を構成し表現する線及び曲線の如き部品要素(エンティティ)を含むとともに、部品に存在する開口または孔の位置を示す。通常このような2-D平面図の構成要素(エンティティ)は、CADまたはCAD/CAMシステムを使用して入力し、作成する。しかし、2-D平面図を作成するとき、このような要素はしばしば誤って連結または重ね合わされ、一つの要素が一つ以上の面の境界を示すのに用いられることがある。さらに、部品の境界を決めている外側線が、境界の隣接するコーナーで分断されていて、部品と各面の外側の寸法の検出を難しくしている。さらに、2-D平面図は、寸法情報やテキストのような本質的でない情報を含みうる。このような異常は、元の2-D図面を正確に解析し、部品の面や曲げ線を均一に検出するのを難しくする。本発明の自動トリミングとクリーンアップ操作を備えることによって、各面は連結された要素の一義的なセット(セット)で表現できる。その結果、2-D平面図は、引き続き行われる処理と最終的に行われる3-Dモデル表現作成のための折りたたみのために、より簡単かつ効率よく解析できる。
【0132】
図12に示すように、元の2-D図面では面間のトリミングがされておらず、図中の一つの線要素が一つ以上の面の外側境界または複数の境界を定めていることがある。上記で論じたように、このような配置は各々の面の検出を困難にする。本発明の自動トリミング機能は、連結性情報を決定し、上記のような要素を交点で断ち切るために、各部品要素(線、弧や曲げ線のような)の終点と交点を解析するのに備えられている。このようなトリミング機能は、断ち切られた各要素の終点を決められた交点に設定する機能ももつ。たとえば、図12に図示されている交点をトリミングすることによって、各々が交点に終点を共有する三つの要素(二つの線と一つの曲げ線)がえられる。このようなトリミング機能を備えることによって、要素解析と連結に基づいて部品の面をより容易に検出することができる。実施できる面検出操作のさらに詳しい記述は、下記に図15(a)-16(c)を参照しながら提供される。
【0133】
色々なプロセスや操作を用いて2-D図面の要素の交点を検出することができる。このようなプロセスは、2-D図面のフアイルのデータのフオーマットと配列に基づいて作成できる。通例2-D平面図は幾何学データ(色々な部品要素を定義する)と非幾何学データ(たとえばテキスト等)を含む。幾何学データは、データの各行またはシーケンスにあるキーワードによって非幾何学データと区別できる。このようなキーワードは2-D図面のデータ書式に従って設定される。2-D、3-D図面によく用いられる書式としてDXFとTGES書式がある。各要素の幾何学データを解析することによって要素の終点や交点が検出でき、適当であればトリミングができる。
【0134】
上記で論じたように、線、曲げ線や他の要素は終点及び/またはベクトルで定義できる。たとえば2-D平面図では、各2-D線は2-D終点の組(たとえばX1,Y1とX2,Y2)で特定することができ、曲げ線は曲げ線の2-D空間位置とともに方向を示すベクトルで表すことができる。さらに2-D弧は2-D空間データ(たとえば中心X、中心Y、半径、開始角度、終了角度)で特定することができる。幾何学データはまた、色々なタイプの線要素(たとえば弧、実線、破線、鎖線等)を区別する属性をもつ。通常弧要素は薄板金属部品の孔や開口を、実線は部品の境界や形状を示すのに用いられる。曲げ線は普通破線で示され、部品の中心線は鎖線で示される。
【0135】
元の2-D図面の幾何学データを解析し、各要素の交点を決めることができる。データ割り当てやデータ反復のような、色々なデータ解析手法を2-D図面の各要素の幾何学データの解析に用いることができる。各要素の終点及び/または他の2-D空間データに基づいて、線や他の要素が交差するかどうかを決める簡単な幾何学解析をすることができる。二つの要素が交差することが決まれば、各要素を決定された交点で断ち切り、残った要素の終点には交点で定められた共有点を割り当てることができる。
【0136】
トリミングの方法は、交差することが検出された要素のタイプに基づいて行われる。たとえば二つの実線が交差することが検出されると、図13(a)に示すように、各線要素を断ち切ることによって、定められた交点で接する四つの線要素がえられる。また線要素と弧要素が、図13(b)に示すように交差することが決まると、各要素を断ち切ることによって共通の終点をもつ二つの線要素と二つの弧要素をうることができる。しかしながら、要素の交差が検出されても、トリミングを必要としないこともある。たとえば、如何なる要素でも中心線(たとえば鎖線要素)と交差することが決定した場合、どの部品の中心線も部品の面または曲げ線を定めたり区別したりすることはないので、トリミングの必要はない。また、連結しない要素でも、開いている交点または面積が、所定の許容度内であれば切断できる。たとえば、潜在的に交差する線の終点が、実際に他の要素と交差するときの交点と、事前に定義した許容度または距離ε(たとえば0.0-0.01mmまたは0.0-0.001インチ)以内であれば、要素は投影された点で連結交差しているものと扱ってよい;そしてたとえば図13(c)に示すように、要素を断ち切ることができる。
【0137】
自動トリミングをした後、えられたデータを、非連結要素を検出し修正するためにクリーンアップ機能で処理することができる。しかしながら、本発明はこのような処理のみに限られていない;処理時間を短縮するためにクリーンアップ機能を、各要素が解析されている間に、自動トリミング機能と同時に行うことができる。クリーンアップの間に、2-D図面の幾何学データが、隣接する要素間の開いた交点または領域を検出するために解析される。自動トリミング機能と同様に、要素間の開いた交点の領域を検出するために、各要素の終点や他の2-D空間データも解析できる。このようなデータに簡単な幾何学的解析を加えることによって、要素の終点が互いに事前に定義した許容度または距離(0.0-0.01mmまたは0.0-0.001インチ)内にあるかどうかが決定できる。要素の終点がこのような開いた交点をもつことが決定されると、要素を連結し、図14に示すように共通の終点を割り当てることができる。
【0138】
ここでもまた、クリーンアップ機能をどのように行うかは、開いた交点をもつことが検出された要素のタイプによる。二つの実線が開いた交点をもつことが検出された場合、各終点に共通の終点を割り当てることができる(たとえば図14を見よ)。しかしある要素が部品の中心線(たとえば鎖線要素)と開いた交点をもつことが決まったときには、要素を連結したり共通の終点を割り当るべきでは無く、中心線は無視しなければならない。またクリーンアップ機能は、2-D図面から非幾何学データ(テキスト等)を消去するための付加的なプロセスまたは操作を含みうる。前述べたように、非幾何学データは、2-D図面データとともに用意されているキーワードに基づいて幾何学データと区別できる。クリーンアップ機能にはまた、後で本発明の2-Dクリーンアップ機能を参照しながらより詳しく説明するような、他のクリーンアップ機能を組み込むことができる(たとえば図21-23(b)を見よ)。
【0139】
ステップS.122で自動トリミングとクリーンアップ機能を行った後、ステップS.124で処理された2-D図面について面検出の手続きを行うことができる。本発明の見地に沿って、面検出手順は要素(線や弧)とループ解析に基づいた部品の面の検出と定義付けを含む。図15(a)-16(d)に面検出手続きで行われる色々なプロセスと操作の例を示す。ループ検出技法を本発明で部品の面を検出し、決定するのに用いることができる。面検出手続きは、たとえばサーバー・モジュール32にあるソフトウエアまたはプログラムされた論理によって実施できる。
【0140】
本発明の見地に沿って、部品の外側境界のループ検出解析に引き続く、部品の最小または内側ループの解析を用いて、面の各々を検出できる。薄板金属部品のユニークな幾何学のため、面と部品にある開口は、相対的極大(たとえば外側)と極小(たとえば内側)ループの順序の解析によって検出することができる。下記に論じるように、ループ解析は部品の線と弧要素の連結性にもとづいて行うことができる。ループ解析を部品の外側から部品の中心に向かって行うことにより、部品の開口や面を、循環順序(たとえば面材料、開口、面材料、開口等)に従って定義されたループ間の境界に基づいて検出することができる。
【0141】
図15(a)に示すような、図示の各面の各種の線要素を含む2-D平面図が提供されたとしよう。上記のように、ループと要素解析は部品の外側から始めるように行う。部品の外側境界にあるどの要素を初期参照点にとってもよい。限定されない例として、図15(b)に示すように、最も左側の線要素を検出し、初期参照点に用いる。最も左側の線要素は、2-D図面にある各要素の幾何学データを比較し、どの要素が最も小さいX座標の値をもつかを決めることによって検出できる。最も左側の線要素を検出した後、点P1から部品の外観が導かれ、図15(c)に示すように部品の外側境界を検出される。点P1を決めるには、最も左側の線要素のいずれの終点を用いてもよい。図15(c)に示す実施例では、上側の終点(つまり最も大きなY座標の値をもつ終点)が点P1に用いられている。
【0142】
部品の外観、またはまわりのループを導くのには、通常のループ解析技法を使うことができる。たとえば、リード線ベクトルを、部品の外観を追ってゆくに従って、始点P1と連結している要素の終点から投影してゆくことができる。一つ一つの要素が検出され、通過される毎に、要素が選ばれたことを示すフラグを設定することができる(たとえば記憶内のフラグは、一度選ばれたことを示すために1に設定する)。ループの経路は始点P1からどちらの方向にも始められる。たとえば、リード線ベクトルを点P1から反時計方向(たとえばリード線ベクトルをY座標方向に投影する)に投影することができる。ループはループ経路が始点(つまり点P1)に戻ったところで完結する。
【0143】
上記のように、始点P1からリード線ベクトルを反時計方向に投影できる(たとえば最初のリード線ベクトルをY座標方向から始めることによって)。引き続きループの経路にある最初の要素を検出するために、各未検出要素が点P1のまわりにリード線ベクトルとなす角度を座標枠に基づいて測定し、解析してリード線ベクトルと最も小さい角度をもつ要素を選ぶ。外側ループでは、 各角度は要素線がリード線ベクトルとなす外側角度を測る。点P1の回りの要素は、どの要素が点P1と終点を共有するかによって決められる。各要素の未選択状況は、各要素に付したフラグを解析することによって決定できる。図15(c)に示すように、図示の2-D図面例では二つの要素線(X座標方向のものとY座標方向のもの)がP1のまわりにある。これらの要素の解析では、Y座標方向の線要素が、リード線ベクトルとなす角度(0度)が他の線要素がなす角度(270度)より小さいので選ばれる。
【0144】
続いてループ解析は選択された他の線要素の終点に進み、選択されたことを示すためにフラグが設定される。その終点で、別のリード線ベクトルが投影され、その点のまわりの非選択要素を比較することによって、どの要素がリード線ベクトルと最小の角度をもつかを決める。ここでもまた、角度はリード線の外側から測り、座標フレームを用いて角度の大きさを決める。弧要素に出会った場合は、リード線ベクトルの外側から弧の接線までの角度を測らなければならない。また、次の終点にある要素が一つのみであれば(部品のコーナー位置のように)、比較の必要はなく、単にその要素を選択してループに含めればよい。
【0145】
部品の外観に沿ってループ経路が進むにつれ、選択された各要素は、ループ内の要素の連結性を示すためにリンクされたリストに含めることができる。経路が始点P1に戻るとサイクルは完了し、外観と、部品の外側境界を示す要素または線のリンクされたリストに基づいてループを(L4)と定義できる。ループL4内の各線または要素は、各終点で連結できる。ループL4の方向を、外側ループであることを示すために、図15(d)に示すように、反対方向(つまり時計方向)に変えることができ。ループの方向は、ループL4で線がリンクされる順序に基づいて定義することができる;従って方向を、リンクされたリストの順序を逆にすることによって変えることができる。
【0146】
外側ループの完了後、外側ループ解析に用いたのと類似のプロセスで部品の内側ループの解析を行うことができる。ただ内側ループの解析では、各非選択要素は各要素がリード線ベクトルの内側となす角度に基づいて比較される。さらに、内側ループ解析では、ある点のまわりの両方の要素がすでに選択されていると示された場合(たとえば面を境する二つの外側線要素を比較するとき)でも、二つの要素が既に二度選択(2のフラッグ設定)されてない限り、二つの要素を比較することができる。少なくとも一度選択された要素(たとえば外側要素)と選択されていない要素の場合は比較は行わず、非選択要素をループの一部分として選択する。図16(a)-16(c)に、図15(a)に示す部品の面を検出し、規定するのに行うことができる内側ループが例示してある。
【0147】
内側ループ解析は、どの外側要素の終点からでも、あるいは選択されていない要素を検出することによって開始することができる。たとえば点P1を、内側ループ解析の始点に選び、リード線ベクトルを投影するのに用いることができる;あるいは外側ループ解析の際に選ばなかった内側の線要素の一つも解析の始点に用いることができる。外側ループ解析と同じように、リード線ベクトルを反時計方向(たとえば一番目のリード線ベクトルをY座標方向から始める)に延ばしてゆくことができる。次いで点P1のまわりの各要素を比較し、どの要素がリード線ベクトルと最小の角度をもつかを決める。リード線ベクトルとなす角度を決めるのに、座標枠を用いることができる。前記のように、内側ループ解析に際には、要素の比較は各要素がリード線ベクトルの外側でなく、内側となす角度をもとに行う。最初の要素が選ばれ、ループのリンクされたリストに含めたら、そのフラグを1だけ増分し、つぎのリード線ベクトルを投影することによって解析を進めることができる。このプロセスはループが最初の始点に戻るまで続けられ、そこで第一の内側ループが、対応する要素のリンクされたリストによって定義(たとえばL1)される。
【0148】
さらに部品の内部に進んで、同じように内側ループ解析を行うことができる。次の始点は、どの要素が一度しか選ばれていないかを決めることによって選ぶことができる。二度選ばれたフラグをもつ要素は、その要素がすでに外側ループ(たとえばL4)と少なくとも内側ループの一つ(たとえばL1)で選ばれた外側要素であることを示す。ここでもまた、各要素が選ばれるたびに、それが内側ループのリンク・リストに含まれたことを示すために、フラグを1だけ増分する。
【0149】
すべての内側ループが定められた後(たとえば図16(c)の例ですべての要素が二度選ばれた後)、えられたループを用いてループツリー(ループ木)を作成することができる。図16(d)に、検出されたループL1-L4に基づいて作成したループツリーの例を示す。部品の外側ループ(L4)はツリーの根(ルーツ)と定義し、外側ループと共通の要素をもつ各内側ループ(L1-L3)は、根の子どもと定義されている。共通要素の存在は、各ループを規定する要素のリンクされたリストの解析と比較によって検出できる。内側ループ内に、さらに要素(たとえば孔または開口)が検出された場合には、これらのループを、それが位置する内側ループの子ども(つまりループツリーの根の孫)と定義することができる。
【0150】
ステップS.124で面検出手続きを行った後、ステップS.126で曲げ線検出操作を行うことができる。たとえば図17に示すように、ステップS.124で部品のループを検出し解析するときに、本発明の面検出論理は、面情報を規定し、検出された面を曲げグラフ・データ構造にノードとして格納するのに、ループツリーを利用することができる。部品の面は、ループツリーにおける外側と内側ループの順序から検出できる。上記のように、各ループは要素または線のリンクされたリストを含む。これらの要素は、部品の各面の境界を定めるのに用いられる。従ってステップS.126において曲げ線検出操作を行い、部品の面と曲げ線の間の関係を決めることができる。ステップS.126の曲げ線検出操作は、ある二つの隣接する面が共有する端または線要素を検出することによって、部品の色々な面間のすべての曲げ線を検出する曲げ線検出論理を含むことができる。また一つ以上の領域で接続している面(たとえば3-Dモデルに曲げ線検出アルゴリズムを適用する場合―たとえば下記に論ずる図19を見よ)については、いろいろな発見的方法(ヒューリスティク)を適用して、部品の曲げ線の最小数を検出し、選択することができる。検出された曲げ線は、たとえば図18に示すように、最終的な曲げグラフ・データ構造を作成するための、面の節(ノード)の間の連結エージェントとして格納しておこことができる。
【0151】
本発明の曲げ線検出操作は、たとえばサーバー・モジュール32に備えたソフトウエアまたはプログラムされた論理によって実施できる。曲げ線検出操作の目的は、部品が最も少ない数の曲げ線で連結されるように、部品の曲げ線を検出し、選択することにある。曲げ線検出操作は、部品の2-Dと3-Dバージョン両方に備えることができる。原3-Dモデルについての曲げ線検出の適用は、下記に図19を参照しながら論ずる。上記のように、検出された曲げ線は、最終的な曲げグラフ・データ構造を作成するための面の節の間の連結エージェントとして格納できる。この最終的曲げグラフ・データ構造は、2-Dデータ・モデルから折りたたんで部品の3-Dバージョンを作成するのに利用できる。
【0152】
図11のステップS.120で入力として提供された2-D図面は、曲げ線情報を含まないか、曲げ線情報が不明確で、一義的にまたは矛盾なく定義されていないことがある。その場合、曲げ線検出操作を、曲げ線を検出し、部品の検出された面との関係を検出するために行うことができる。このプロセスの間に、各面を定義する要素(エンティティ)のリンクされたリストを解析し、各面が部品の他の面と共にもつ隣接する端または線要素を決めることができる。これはある与えられた二つの面の間の可能なすべての接触を解析することによって行うことができる。接触は、長さが0以上の(つまり線要素が点ではなく、実際の線である)、共通する線要素(またはお互いに事前に定めた距離許容度にある複数の線要素)の存在によって決定できる。リンクされたリストにある幾何学データを解析することによって、部品のすべての二つの面間のこのような接触の存在を決めることができる。
【0153】
ある特定の面が、他の面と共通の端または接触領域を一つしかもっていない場合、両方の面に共通の要素は曲げ線であると定義することができる。一つ以上の領域で共通接触を持つ複数の面(たとえば3-Dモデル;ただし2-Dモデルでも起こりうる)については、色々な発見的方法(ヒューリスティック)を用いて部品の最小数の曲げ線を検出し、選択することができる。使用する発見的方法は、複数の面が曲げ線で連結され、複数の面にわたる連続ループが形成されないようになっていなければならない(このような曲げ薄板金属部品の製作は不可能なため)。
【0154】
利用できる発見的方法の例として、共通する領域で最も長い接触領域をもつものを曲げ線に選ぶ方法がある。ある面が、他の面と一つ以上の共通端をもっている場合、この発見的方法によって最も長い長さをもつ共通要素を面の曲げ線に選ぶことができる。この発見的方法は、曲げ薄板金属部品を製作するときに、通常長い接触領域を持っている方が良いという原則にもとづいている。使用できるもう一つの発見的方法は、異なる可能な曲げ線の組み合わせ(3-Dモデルの曲げ線を決めるときのような)に関係する。この発見的方法では、すべての可能な共通領域が検出され、曲げ線の色々な組み合わせが選択されると、曲げ線の組み合わせで最小の曲げ線の数をもつ組み合わせが選ばれる。
【0155】
曲げ線が検出されると、部品の面と決められた曲げ線は確認のためにオペレータに表示される。オペレータが部品の曲げ線の選択に満足しない場合には、曲げ線検出操作に手動選択機能を備えることによって、サーバー・モジュール32でオペレータが選択的に、薄板金属部品に好ましい曲げ線を指示できるようにすることができる。オペレータは、マウスやキーボード等、適当な入力手段を用いて、曲げ線を保持するか変更するかを指示することができる。しかる後、オペレータによって選ばれた修正された曲げ線を用いて、最終的な3-D(または2-D)部品を作成することができる。
【0156】
本発明の曲げ線検出操作を実施するために、色々なプロセスや操作を備えることができる。曲げ線検出操作を実施するためのコードの例を、付記の付録Cに与える。例示のコードはC++プログラム言語で書かれており、記述の論理フローの理解を助けるためのコメントが含まれている。例示コードは、2-Dまたは3-Dモデルについて行うことができる曲げ線検出操作の実施例で、曲げ線の最適選択を決める発見的方法(上述のような)を含む。
【0157】
検出された面と曲げ線情報は、本発明の折りたたみと展開プロセスに利用することができる。折りたたみまたは展開の際、各曲げ線の回りに3次元回転を行うと、結果として3-Dまたは2-Dモデルが導かれる。この仕事を行うには、単に部品の各面と他の要素に対して、回転と並進を含む行列変換を行えばよい。色々な市販で入手できる展開と折りたたみソフトウエア適用の特性を、本発明の基本的な展開または折りたたみステップを実施するのに利用できる。たとえばアマダ アンフオルドとフオルド システム・ソフトウエアをこれらの基本操作を行うのに利用できる。アマダ アンフオルドとフオルド システム・ソフトウエアはアマダ・アメリカ社(以前は社名U.S.アマダ社で業務)、ベユナ・パーク、カリフオルニアから入手できる。アマダアンフオルドとフオルド・システム・ソフトウエアについての情報は、オートキャドのためのアマダ・アンフオルド・マニュアル(1994年3月版)、キャドキーのためのアマダ・アンフオルド・マニュアル(1994年5月版)とキャドキーのためのアマダ・ウインドウズ・アンフオルド・マニュアルにあり、その明細を全般的に参照することによって本文書に明白に取り入れる。2-Dモデルから3-Dモデルを作成するための折りたたみ操作については、後でステップS.132を参照しながら論ずる。
図11に戻って、曲げ線検出操作をステップS.126で行った後、サーバー・モジュール32がユーザーに対し、この後の折りたたみプロセスに用いる主要な曲げと差引高(縮小量)の情報を指令することがある。たとえば、ステップS.128で、サーバー・モジュール32はユーザーに、曲げ方向(たとえば前方、後方等)も含む曲げ角度及び/または曲げ内側半径を含む各曲げ線の曲げ高(曲げ量)の指示を求めることがある。ステップS.130で、サーバー・モジュール32はまたユーザーに対し、V―幅、材料のタイプ、及び/または差引高(縮小量)の入力を求めることがある。これらの情報は、折りたたみ操作における曲げ差引高(曲げ縮小量)を補償するのに利用できる。材料の厚さとタイプとともに、曲げ角度と使用するダイスのV-幅によって、実際の薄板金属部品は薄板金属部品を折りたたむときに、差引高だけ引き伸ばされる傾向がある。
【0158】
前記モデルでこの効果を補償するために、差引高情報を利用して、折りたたみ操作で3-Dモデルを作成するときに、曲げ線の各側で部品の面の寸法を差引高の半分だけ引き延ばす。本発明の見地に沿って、この差引高はユーザーによってサーバー・モジュール32に入力(たとえばキーボード等によって)できる。あるいは、部品の材料のタイプと厚さにもとづいた差引高を含む材料表をオペレータに表示することができる。材料表は、異なる曲げ角度やV―幅に対する色々な差引高を示す。ユーザーは、サーバー・モジュール32で表示された材料表から適切なV―幅と曲げ角度を選ぶ(たとえばマウスまたはキーボードを用いて)ことによって、自動的に差引高をセットすることができる。曲げ角度の内側半径も、適切なV―幅を選ぶときに、材料表を介してユーザーによって自動的にセットできる。オペレータが入力する(あるいはオペレータによる入力後に変換される)差引高は、部品幾何学データを表すものと同じ長さの単位(たとえばmm)である。折りたたみ操作時に、曲げ線の各側の各面の長さ寸法を、注目している曲げ線の差引高の半量だけ増やす。面の曲げ線に垂直な長さ寸法は、曲げ線の各側にある面の境界を定める要素の終点を引き伸ばすことによって増やすことができる。このような差引高補償は、各折り曲げについてオペレータによって供給された差引高にもとづいて、部品の他の曲げ線の各々について行うことができる。
【0159】
ステップS.132では、加工された2-D平面図にもとづいて、3-Dモデルを作成するための、差引高補償を含めた折りたたみ操作が行われる。前記のように、折りたたみ手続きは、行列変換の使用と最終的曲げグラフ・データ構造で定義されたそれぞれの曲げ線を回転軸に用いることを含む通常の幾何学的模型化法によって遂行することができる。さらに、差引高の効果を補償するために、3-Dモデルを作成する折りたたみの際に、部品の面を曲げ線の各側で差引高の半量だけ引き伸ばすことによって、薄板金属を実際に折り曲げるときの面の寸法の変化をより正確に反映することができる。
【0160】
たとえば、ステップS.132で折りたたみ操作を行う時に、曲げパラメータ(たとえば曲げ角度、内側半径)とともに、部品幾何学と形態データ(または曲げグラフ構造)を利用することができる。2-D空間で表わされた部品の各面、曲げ線、孔と成形についての変換行列を計算できる。通常の行列変換を、2-D平面図に適用することによって、3-D空間データをうることができる。変換は一般に回転に続く並進を含む。上記のように、回転は曲げ角度の大きさに従って、各曲げ線軸の回りに行われる。並進操作は、幾何学データを空間の中で移したり、動かしたりすることによって行われる。このような並進操作は、曲げ半径、曲げ角度と各曲げの差引高にもとづいて決められる。折りたたみの際に、差引高補償は前述べたように曲げ線の各側で、面の寸法を差引高の半量だけ伸ばすか増やすことによって行われる。このような差引高補償は、曲げ機で曲げられる2-D薄板金属部品の寸法を、より正確に反映する部品の3-D表現を与える。
【0161】
幾何学的モデル化と変換のさらに進んだ情報は、たとえば、その明細を全般的に参照することによって本文書に明白に取り入れられているモルテンソン、マイケル M著、幾何学的モデル化、ジョン・ワイリー&サンズ、ニューヨーク(1988年)及びフオリーら著、ジェイムス システム・プログラミング・シリーズ:会話形コンピュータ・グラフイックスの基礎、アデイソン・ウエスリー出版、レデイング、マセチューセッツ(1983年)を見られたい。モルテンソンの8章には、並進と回転を含む幾何学的変換が論じられている(たとえば345-354頁参照)。さらにフオリーらは7章、245-265頁で、2-Dと3-D変換の行列表示を含む、幾何学的変換の情報を与えている。モデル化と幾何学的変換についての付加的情報は、その明細を全般的に参照することによって本文書に明白に取り入れられている、マンテイラ、マルッテイ著、ソリッドモデル化入門、コンピュータ・サイエンス出版社、ロックビル、メリーランド(1988年)にも与えられている。座標変換に関する情報は、マンテイラの365-367頁にある。
【0162】
次に図19を参照しながら、本発明の別の見地に沿って、元の厚さぬきの3-D平面図にもとづいて2-Dモデルを作成するプロセスと操作について説明する。図11を参照しながら前に説明した折りたたみプロセスと同様に、3-D図面を展開し、2-Dモデルを作成する色々なプロセスや操作は、サーバー・モジュール32にあるソフトウエアや/またはプログラム化論理を用いて実施できる。図19に示されているように、顧客の仕様にもとづいて提供され作成された元の3-D図面は、ステップS.140でサーバー・モジュール32に入力されるか取り入れられる。3-D図面はDXFまたはIGESフアイルとして格納され、サーバー・モジュール32からCADまたはCAD/CAMシステムとインターフエイスするか、利用するかして入力できる。3-D図面を入力後、ステップS.142でサーバー・モジュール32によって、引き続き行われる面検出や他のプロセスのための図面の準備のために、自動トリミングとクリーンアップ操作が行われる。
【0163】
図12-14に関連して論じたように、自動トリミングとクリーンアップ機能は、部品の色々な面が適正に検出定義されされるように、構成要素や表面を切り離したり、連結したりする。
【0164】
図11と12、13に関連した上記の自動トリミングとクリーンアップ操作は、図19のステップS.140で入力した3-D図面の幾何学データに対しても、同じように適用できる。データを2-D空間で解析する(2-D平面図の場合のように)代わりに、3-D図面に図示されている各構成要素(たとえば線、弧等)は、図中の3-D座標と空間情報にもとづいて解析することができる。交点と開放交差領域は、各構成要素(エンティティ)を個別的に解析し、他の構成要素の一つ一つと比較することによって解析できる。ここでもまた、構成要素の終点や他の属性の基本的な幾何学的解析を用いて、許容度内で交点と開放交差領域を決めることができる。
【0165】
前記3次元図面に対しての自動トリミング及びクリーンアップ機能を実行した後、ステップS144で、前記板金パーツの面の各々を検出し定義するために面検出操作が行なわれる。前記3次元図面についての面検出は2次元空間における各面を分析し且つ検出し且つ上記と同様にしてループツリーを生成することにより行なわれる。面検出は任意の所定のエンティティで開始することにより実行される。例えば、一番左側のエンティティ(即ち最小のx座標を有するエンティティ)が最初のエンティティとして使用される。その後、1つの面は前記最初の線分エンティティ及び他の連結するまたは隣接する線エンティティ(即ち前記最初のエンティティと共通の端点を有する任意のエンティティ)を取出すことにより定義される。面検出操作は次に、図15(a)−16(d)に関連して上記に説明したようにループ及びエンティティ解析を用いて行なわれる。各エンティティは前記定義された2次元平面内で検出されるため、種々の外側及び内側ループが定義され、且つ前記エンティティがマークされ(即ち前記選択されたエンティティのフラグを設定し或いは増加することにより)、それらが、前記面における複数のループの1つを定義する連結されたリストに選択され且つ含まれたことを示す。
【0166】
引き続くループ解析は、次に前記3次元図面を構成する他の2次元平面において行なわれる。前記他のエンティティのループ解析を行なうために、前記3次元図面内でのマークされてない或いは選択されてないエンティティを検索することにより追加の平面が定義される。そのような平面は、2つの選択されてないエンティティの間或いは選択されてないエンティティと以前に選択されたエンティティとの間に定義される。追加の2次元平面の各々において、更なるループ解析が行なわれ前記内側及び外側ループを検出する。再び連結されたエンティティの連結リストが保持され、前記複数のループ経路の各々が定義されるにつれて、前記選択されたエンティティがマークされる(即ち前記選択されたエンティティに付随するフラグを増加することにより)。
【0167】
全てのエンティティが検出された後、すでに解析された2次元平面の各々についてのループツリーを生成するために、結果の複数のループが使用される。すでに述べたように、ループツリーは、板金パーツにおける複数の面及び開口部及び穴を定義するために提供される。3次元の図面については、ループツリーは、前記板金パーツの各面について生成される。各面内で検出された複数のループは、各ループツリーを生成するためにグループ化され分析される。各ツリーのルーツ(根)は前記平面において検出された外側ループとして定義される。前記外側ループと共通のエンティティを有する前記平面の各内側ループは前記ツールの子供として定義される。共通エンティティの存在は、各ループを定義する連結されたエンティティのリストの分析及び比較に基づいて検出される。追加のエンティティ(即ち穴或いは開口部)が前記平面の内側ループにおいて検出される時、これらのループはそれらがその内部に存在する内側ループの子供(即ち前記ループツリーのルーツの孫)として定義される。生成された複数のループツリーは次に、前記3次元図面の全ての面を検出するために用いられる。検出された面は次に曲げグラフデータ構造におけるノード(節)として格納される。
【0168】
前記結果としての曲げグラフ構造はステップS146における曲げ線検出操作の実行の後、連結する曲げ線連結エージェントにより補足される。曲げ線検出操作及び最終曲げグラフ構造またはパーツ・トポロジーの生成は図17及び18を参照して上記したと同様のやり方で実行される。
【0169】
上記したように、前記曲げ線検出操作を実行するための代表的なコードがここに添付された付録Cに提供される。このサンプルコードは、2次元或いは3次元モデルに対してなされる曲げ線検出操作のための代表的実行例であり、曲げ線の最適選択を決定するためのヒューリスティック(例えば上記したような)を含む。前記曲げ線検出操作は、検出された曲げ線に満足しない時、サーバモジュール32におけるオペレータが前記板金パーツのための好ましい曲げ線を選択的に指定することを許すマニュアル選択特性を含む。前記オペレータは、マウスあるいはキーボード等のごとき適宜の入力手段により曲げ線を維持し或いは変更することを指示する。前記オペレータにより選択され改定された曲げ線は最終的2次元パーツを生成するために用いられる。
【0170】
最終的曲げグラフ構造の複数の曲げ線を中心とする展開工程を実行する前に、ユーザは、ステップS148でV幅、材料タイプ及びまたは縮小量について促される。上記したように、板金は折り曲げられる時伸びる傾向を有するため、3次元パーツの寸法は前記2次元平面パーツのそれより少し大きい。従って、板金パーツの展開の過程で、パーツの寸法は、選択された材料タイプ及びV幅に基づく縮小量だけ縮み或いは減少される。従ってこの発明の1つの側面によれば、3次元モデルを展開する際、前記2次元モデル及びその表面の各々の寸法をより正確に生成するために縮小操作が行なわれる。上記したように、前記縮小量は、前記ユーザにより直接入力され或いは所望のV幅及び曲げ角度を選択することによりユーザが自動的に前記縮小量を設定することができるように、材料テーブルが表示される。
【0171】
前記オペレータにより入力される前記縮小量は前記パーツ幾何学データにより表現されるそれと同じ長さの単位(例えばミリメートル)である(或いはオペレータによる入力の後その単位に変換される)。展開操作の間に、前記曲げ線の両側の面の各々の寸法長さは前記所定の曲げ線について入力された縮小量の半分だけ減少される。前記曲げ線に直交する前記面の寸法長さは前記曲げ線の両側に位置する前記面の境界を定義するエンティティの終点を減少することにより減少される。前記縮小補償は、各曲げについて前記オペレータにより提供される前記縮小量に基づいて、前記パーツの他の曲げ線のそれぞれにおいて行なわれる。
【0172】
前記全ての必要なデータの入力の後、ステップS150で、前記2次元モデルを生成するために展開プロセスが行なわれる。前記3次元曲げモデルを展開するために通常の方法が用いられ、それは前記複数の曲げ線の各々を回転軸として用いるマトリックス変換の使用を含む。この展開プロセスの間に各曲げ角度が測定され、前記平面曲げモデルを生成するために前記曲げ角度量だけ前記パーツは展開される。更に、前記入力された縮小量に基づいて、前記板金材料の物理的性質及び前記3次元及び2次元モデルの間の差をより正確にシミュレートするために、前記曲げ線の両側で前記縮小量の半分だけの前記面の寸法の縮小或いは減少が行なわれる。
【0173】
ステップS150で前記展開工程を実行する時、前記パーツの寸法及びトポロジーデータ(または曲げグラフ構造)が前記曲げパラメータ(例えば曲げ角度、内側半径等)と共に用いられる。前記3次元空間において表現された前記パーツにおける各面及び曲げ線及び穴及び成形部についての変換マトリックスが計算される。通常のマトリックス変換が前記2次元空間データを得るために前記3次元データに対して適用される。前記変換は一般的に回転を含み、その後に並進がくる。上記したように、回転は、曲げ角度量に応じて各曲げ線の周りに行なわれる。展開のために、2つの面の間に180°が存在するまで(即ち面が平面になるまで)回転は逆方向に行なわれる。並進は空間内で前記幾何学的データをシフトし移動するために行なわれる。そのような並進は、各曲げについての前記曲げ半径及び曲げ角度及び縮小量に基づいて決定される。展開の間、縮小補償は上記したように、曲げ線の両側で前記縮小量の半分だけ前記複数の面の寸法を縮め或いは減少せしめるために行なわれる。そのような縮小補償はそれが曲げ工程の間に折り曲げられる前の前記板金パーツの寸法をより正確に反映する前記パーツの2次元表示を提供する。
【0174】
再び幾何学的モデル化及び変換についての情報はモルテンソン、フォリー等及びマンティラに見出される。上記したように、モルテンソンの8章は変換及び回転(例えば345〜354頁を見よ)を含む幾何学的変換の議論を提供する。更にフォリー等は、7章の245〜265頁で2次元及び3次元変換のマトリックス表示を含む幾何学的変換についての情報を提供する。更に座標変換についての情報はマンティラの365頁〜367頁に見出される。
【0175】
図4を参照して上記したように、前記顧客の注文に基づいて、2次元3面図或いは厚さを有しない3次元ワイヤフレーム図が最初に提供され或いは生成される場合、厚さを有しない3次元モデルを生成するために更なる工程が必要とされる。そしてその後、前記厚さを有しない生成された3次元モデルは展開プロセス或いはアルゴリズムを適用することにより2次元モデルを生成するために用いられる。図20−24は、最初の2次元3面図に基づいて3次元モデルを生成するために適用される種々のプロセス或いは操作を図示する。更に図25は、この発明の他の側面に応じて、厚さを有する最初の3次元ワイヤフレーム図から厚さを有しない3次元モデルを生成するために適用される追加のプロセス或いは操作を図示する。再び、図20−25において図示される種々のプロセス及び操作は、例えば前記サーバモジュール32に存在するソフトウエア及びまたはプログラム論理により実行される。
【0176】
図20を参照するに、この発明の教示に応じて、最初の2次元3面図に基づいて3次元モデル(厚さを有しない)を生成するために行なわれる操作或いはプロセスの論理フローの記載が提供される。最初、ステップS160で2次元3面図がサーバモジュール32へ入力され或いは搬入される。前記最初の2次元3面図は、前記パーツの種々の図(例えば正面図及び平面図及び右側面図、例えば図22(a)及び22(b)を見よ)を含み、前記サーバモジュール32へダウンロードされ或いは搬入されるDXF或いはIGESファイルのごときCAD図面である。しかる後、ステップS162で、前記3次元モデルへの引き続く操作のための図面を作成するために、サーバモジュール32により2次元クリーンアップ操作が行なわれる。この2次元クリーンアップ操作は、前記パーツの実際の幾何学形状を表現しない余分な及び非幾何学的な情報、それはテキスト及び中心線及び寸法線を含む、を消去するために行なわれる。前記2次元クリーンアップ操作はまた全ての外側線分を、例えばそれらの接続端部で接続し、或いは任意の交差するライン或いはエンティティを分断し或いはトリミングするために行なわれる。図21は、前記サーバモジュール32により前記クリーンアップ操作が行なわれる際実行される種々のプロセスの論理フローの例を図示する。
【0177】
図21に示されるように、最初に2次元図面が前記サーバモジュール32により、ステップS180でデータファイルから読み取られ或いはロードされる。しかる後ステップS182でサーバモジュールは、2次元図面において各々のエンティティ或いは幾何学データを分析し次の工程のための図面を作成するために種々のエンティティを分割する。ステップS182において行なわれる前記分割或いはトリミング機能は、この発明の前記自動トリミング及びクリーンアップ機能に関連して上記に記載したと同様な方法で実行される。従ってステップS182で前記2次元3面図における全ての幾何学的データは、エンティティの交差点及び所定の誤差範囲内にある空白(開放)交差部を検出するために分析される。任意の交差線は分断され、結果のエンティティは交差点により定義される共通の終点で出会う。更に所定の誤差の範囲内にある(例えば0.0−0.01mm或いは0.0−0.001インチ)空白交差領域を有するエンティティについてはそれらのエンティティは、例えば図12―14に関連して上で記載されたと同様の方法で結合される。
【0178】
ステップS184で前記2次元図面シートの周辺が検索され任意の外部の線分またはデータ(例えば境界線分及び座標格子及び数字等)が消去される。図22(a)に示されるように2次元3面図は、しばしば図面シート上に提供される。前記図面シートは前記板金パーツの種々の図面を生成するために必要でない余分な及び非幾何学的な情報を含む。従ってステップS184で、本発明の2次元クリーンアッププロセスを利用して、前記3次元モデルを展開するにあたってこのタイプの情報が検出され前記2次元図面から消去される。
【0179】
前記2次元図面データはそこに含まれるデータのタイプ(例えば幾何学的或いは非幾何学的/テキスト)を指示するためのキーワード或いはタイプフィールドを含む。従ってこれらのキーワードあるいはタイプフィールド(それらは図面ファイルのデータフォーマットに基づいて提供される)はテキスト或いは他の非幾何学的データのごとき種々の余分の情報を削除するために用いられる。しかし全ての不必要な図面シートデータを正しく削除するためには更なる操作が通常必要である。しばしば、前記境界線或いは他の外側情報はエンティティー(例えば線分等)として保存され、それらは前記データキーワード或いはタイプフィールドに基づいて容易に識別することができない。従ってこの発明の1つの側面によれば、前記2次元図面のデータを分析する際に連結性グラフ構造が生成される。この連結性グラフ構造は各エンティティーについて複数の付随的頂点のリスト及び連結されたエンティティーのリストを示す。各頂点については、隣接する複数の頂点のリスト及びそれが付随するところのエンティティーのリストが提供される。このグラフ構造により、(それはステップS182の分断及びトリミング機能を実行する際に生成されるが)、どのエンティティーがくっつき合う終点により結合されるかが決定される。結果として、境界線及び情報ボックス及び他の非幾何学的データのような余分なデータは削除される。これは、このデータは典型的に連結されたエンティティーで構成されることがなくまたそれを含まないからである。
【0180】
上記したように、2次元3面図は寸法線及び矢印線及び中心線及びテキストのような余分の情報を含み、それらは前記パーツの実際の幾何学形状を表現しない。これらのエンティティーはステップS186で検出され、次の工程のための2次元図面を作成するために前記2次元データファイルから削除される。これらの余分のエンティティーの検出はサーバモジュール32により自動的に行なわれる(例えば前記パーツの実際の幾何学形状に関連しない2次元データファイル中の項目を検出することにより)。例えば、前記連結性データグラフ構造を用いて、両端が開放されたエンティティー(例えばテキストにアンダーラインをするため或いは寸法或いはパーツの中心線を示すために用いられる複数の線)が検出され消去される。矢印のごとき他のエンティティーもまた、浮動する終点或いはそのようなエンティティーの他の特徴の存在に基づいて検出される。全ての不必要なデータを効果的に削除するために、サーバモジュール32は前記2次元図面中のいずれの項目が消去されるべきかを(例えばマウスまたはキーボードにより)オペレータをして指示することができるようにするためのマニュアル編集機能を提供する。オペレータのこの援助或いは確認により、追加の余分の情報が図面から除去される。
【0181】
ステップS186の後、前記2次元図面の種々の図が、ステップS188でグループ化され且つそれぞれ定義される。この発明の1つの側面によれば、サーバモジュール32は、図22(b)及び23(a)に示されるような平面図(上面図)及び正面図、右側面の配置のごとき、予め定められた或いは標準的な図と向きをサポートする。平面図及び正面或いは背面図及び右或いは左図のような他の図及びレイアウトもまたサポートされ得る。更に以下に記載されるように、サーバモジュール32はまた前記2次元図面の図を前記パーツの3次元表現へ加工するために、回転された図(例えば図23(a)を見よ)もサポートする。いずれにしても、パーツの3次元モデルが構成されるためには、厚さ表現を有するパーツの少なくとも2つ(そして好ましくは3つ)の異なる図が提供される必要がある。連結性グラフ構造において前記エンティティーの連結性及びグループ化を解析することにより、サーバモジュール32は、複数の図の各々の相対的位置及び/又は座標位置に基づいて前記複数の図を分類し且つ定義する。
【0182】
限定しない事例として、サーバモジュール32による前記図の定義は、予め定義された或いは通常の配置或いは前記データファイルにおける図の解析をするためのレイアウトにより、及び/又は前記複数の図の向きの検出及び前記図面の各々の図のそれぞれにおける前記パーツの種々の寸法の重ね合わせに基づいて実行される。図23(b)において示されるそれのごとき予め定義された或いは標準的フォームは、潜在的な図のタイプに応じて前記図の各々を決定し定義するために用いられる。種々の終点及び各グループを定義する複数のエンティティーの間の関係の幾何学的比較は、前記ステップS188を実行するために行なわれる。サーバモジュール32の図検出特性(図検出機能)は、複数の潜在的図面タイプ(例えば平面図、正面図、背面図、左図、右図)の1つに応じて前記図面の各々にラベルを付ける。前記複数の図の各々の検出は、予め定義された或いは標準的図の配置或いは形状及び存在する図の各々の間の検出された関係に基づく。種々の工程或いは操作が、ステップS188で、前記2次元3面図における複数の図を分類し且つ定義するために使用される。例えば前記加工された2次元3面図にアクセスした後、前記サーバモジュール32はまずこの図面データにおけるパーツの平面図を特定する。前記平面図は、予め定義された或いは標準的な形状または図配置(例えば図23(b)におけるそれのような)に基づいて検出される。仮に3つの異なる図が水平方向或いは垂直方向において検出される場合には、中央の図が平面図であると定義される。更に仮に3つの別個の図が検出されず且つ垂直方向においてただ2つの別個の図が検出される場合には、上側の図が平面図であると定義される。再び前記連結性グラフ構造における前記エンティティーの連結性及びグループ化が前記複数の図の各々を検出するために使用される。前記予め定義された或いは標準的形態を表現する、格納されたルックアップテーブル或いはマトリックスが前記2次元図面の各図を比較し且つ複数の図の各々を検出するために用いられる。
【0183】
前記2次元3面図データから平面図を検出した後、前記パーツの他の図は前記検出された平面図に対する前記複数の図の各々の相対的位置に基づいて検出される。例えば、図23(b)の標準的レイアウトに基づいて、例えば図グループが前記平面図の上に位置している場合には、その図は背面図であると定義される。しかしもし図グループが前記平面図の下に位置している場合には、その図は前記パーツの正面図であると定義される。更に右図及び左図は、前記平面図のそれぞれ対応する右側及び左側におけるそれらの相対的位置に基づいて検出される。しかる後、前記標準的形態(例えば図23(b))に合致しない任意の残りの図は前記検出された図(例えば検出された背面図或いは正面図)に対するそれらの相対的位置に基づいて検出される。例えば図23(a)に示されるレイアウトBについて、前記右図は前記平面図に対して回転された位置に設けてある。しかしながらレイアウトBにおける右図は前記検出された正面図に対するその関係に基づいて検出される。即ち検出された背面図或いは正面図の右側或いは左側に存在する検出されていない図はそれぞれ前記パーツの右図或いは左図として定義される。
【0184】
種々の予め定義された或いは標準的な図のレイアウトが前記2次元3面図図面において複数の図を検出し且つ定義するために用いられる。標準的な形態(例えば図23(b)または図23(a)におけるそれ)は、製造設備において広く行き渡っており或いは選択され/要求される図レイアウトに基づいて、及び/又はサポートされている図タイプの基づいて選択される。仮にいずれの図も検出されない場合には、サーバモジュールにより警告信号が提供され、オペレータは、好ましい図面レイアウトに応じて前記2次元3面図データを変形したり、他の適当な動作を行なう。前記2次元図面における複数の図を検出するための予め定められた或いは標準的形態の提供に加えて、予め定められた標準的形態(例えば図23(a)のレイアウトAのように)は検出された図を加工し前記パーツの3次元モデルを生成するために設けられる。従って更なる加工が行なわれる前に前記標準的形態に基づいて検出された図を正しく分類するために、回転された図の特徴が提供される。
【0185】
上記したように、前記2次元クリーンアップ操作は図面において複数の図を検出するための予め定められた、或いは標準的形態に合致しない回転された複数の図をサポートし且つ検出する。回転された図のオプションでは、検出された標準的でない複数の図は、パーツの3次元モデルを加工し且つ生成するために、前記複数の図の各々が前記予め定められた或いは標準的な図の形態に合致するように、回転され或いは並行移動される。前記パーツの複数の図を検出するために図23(b)に図示されるそれのような標準的形態を仮定して、図23(a)におけるレイアウトBにおける複数の図の各々は、上記したように、前記平面図及び他の検出された図に対する当該複数の図の相対的な位置に基づいて検出される。例えば仮に図23(a)のレイアウトAが、平面図及び正面図及び右図を有する2次元図面における種々の図を加工するための予め定められた或いは標準的図レイアウトとして使用される場合、ステップS188でレイアウトBにおける右図は90度回転されレイアウトAと同様な、前記パーツの変形された図レイアウトを提供する。前記パーツの右図が前記パーツの平面図の右側に位置するように前記レイアウトBにおいて右図を90度回転することにより、図面中の前記複数の図はレイアウトAで表現される標準的な形態に応じて加工される。格納されたルックアップテーブル或いは予め定められた或いは標準的な形態を表現するマトリックスが、前記2次元図面の複数の図を比較し且つどの図が回転或いは並進運動を必要とするかを決定するために用いられる。
【0186】
前記2次元図面における複数の図から前記パーツの正確な3次元モデルが生成されることを保証するために、前記複数の図の各々においてそれぞれの寸法が相互に矛盾がないか或いは一致しているかチェックされる。図21において更に示されるようにステップS190で前記データファイルにおける前記複数の図の境界が、それぞれの図の全ての寸法が相互に同じ寸法であるかを確認するために検出される。仮に複数の図が所定の誤差の範囲内で(例えば0.0−0.01インチ)一致しないことが判断されるとステップS190で、全ての複数の図が同じスケールになるように任意の特定の図の寸法を変更するために適宜の修正が行なわれる。図面の寸法が相互に一致せず現在存在する2次元図面データに対して必要な修正が行なわれるようにユーザに警告するためにサーバモジュール32に警報要素が設けられる。
【0187】
前記パーツの各々の図における寸法の一貫性を検出し且つ確認するために種々の操作或いは工程が使用される。例えば、前記複数の図の各々の対応する寸法が、それらが相互に所定の誤差の範囲内にあるかどうかを決定するために比較される。そのような解析は、前記パーツの各図の境界線を定義する線分エンティティーを比較することを含む。図23(b)における標準的な形態を仮定して以下のようであれば平面図は右図または左図と一致すると検出される。即ちそれぞれの図について、最大Y座標位置と最小Y座標位置が所定の誤差範囲(例えば0.0−0.01インチ)内にある。更に前記平面図は、以下の場合には正面図または背面図と一致すると検出される。即ち各図について、最大X座標位置と最小X座標位置とが所定の誤差範囲(例えば0.0−0.01インチ)内にある。更に左図または右図は、最大Y座標位置と最小Y座標位置との間の差に比較して最大X座標位置と最小X座標位置との差が所定の誤差範囲(例えば0.0−0.01インチ)内にあれば正面図または背面図と一致すると決定される。再び前記図の寸法或いは関連する面の寸法が一致しないとき前記2次元図面データに対して必要な修正が加えられるようにユーザに警告するように、サーバモジュール32に警告要素或いはモジュールが設けられる。
【0188】
最後にステップS192で、本発明の面検出方法の教示に基づいて、前記パーツの内側ループ及び穴及び形状が検出される。各図の複数の面の内側に設けられている種々の穴或いは形状は、前記パーツの種々の線及び境界を通ってパーツの外側から中央へ向かってループを形成していくことにより検出される。ループ及びエンティティーの分析は、前記2次元図面における前記パーツの各図に対してなされる。前記パーツの外側から作用的に中央へ向かって内側へ各々の図を分析することにより、検出されたループは前記パーツの物質と開口部の境界及び領域を、周期的順番(即ち物質、開口部、物質等)に基づいて決定する。図16(d)におけるそれのごときループツリーが複数の面の位置及び各々の面の内部の任意の穴の位置を決定するために各図面について生成される。浮遊する円弧或いは線分のごとき前記パーツの面の内部で連結されないエンティティーは、ステップS192の中で検出され消去される。
【0189】
本発明の前記2次元クリーンアップ操作を行なうための代表的なコードは付録Dに提供される。このコードはC++プログラム言語で記載されており、そこに使用される論理及びアルゴリズムの解析を円滑にするためのコメントを含む。そのコードは、図21−22(b)を参照して上で議論したそれらのごとき、2次元クリーンアップモードの種々の工程及び操作を含む。
【0190】
図20を再び参照するに、2次元クリーンアップ操作が行なわれた後論理フローはステップS164へ連続しそこで前記2次元図面が材料の厚さを表現しまたは含むか否か(即ち前記2次元図面が厚さを有するか否か)が決定される。もし前記2次元図面が厚さの量を含むと判断される場合には、ステップS166で3次元モデルへの引き続く操作のための2次元図面を作成するためにサーバモジュール32により厚さ消去手続きが行なわれる。前記2次元図面における厚さの存在の判断は図面のデータに基づいてサーバモジュール32により自動的に行なわれ、或いはオペレータからの援助或いは応答を介して前記サーバモジュールにより行なわれる(オペレータは厚さ除去が必要であるか或いは好ましいかを指示するように促される)。前記パーツの厚さは全ての板金パーツの独特の対称性により消去される。前記パーツの厚さを消去することにより、厚さを有しない、結果としての板金パーツは板金オペレータ或いは設計者により、より容易に分析される。更にこの出願の発明者は、前記2次元3面図の厚さを除去することにより、2次元図面を変換し3次元モデルを生成するに必要な時間が著しく短縮されることを見出した。
【0191】
殆どの2次元3面図は材料厚さ量を含むため、オペレータはしばしば、2次元図面から3次元モデルを作成するためにいずれの曲げ線が選択されなければならないかで混乱する。結果として、2次元3面図が3次元モデルへ変換されるように適切な曲げ線を選択する際に相当の時間が無駄になる。厚さを有する2次元3面図の例が図24に示されている。この発明の1つの側面によれば、材質厚さを持つことなく表現され且つ処理されるが、当該材質厚さ量及び前記パーツの内側及び外側寸法を曲げモデルデータ中に保有する簡単化された2次元3面図モデルを表示するように、厚さ除去手続きが設けられている。図24(b)は前記厚さ除去工程を行なった後、前記サーバモジュール32において前記オペレータに対して観察され且つ表示される簡単化された2次元3面図を図示する。
【0192】
前記厚さ除去手続きが実行される時、ユーザは、2次元3面図表示における材質厚さを特定するように促されてもよく、また前記表示内においていずれの寸法(即ち外側寸法或いは内側寸法)が保持されるべきであるかを特定するように促されても良い。オペレータは、例えばマウスを用いて複数の図の中の1つにおいて保持される厚さ及び表面を指示する。このユーザにより入力されたデータに基づいて、サーバモジュール32は前記2次元3面図を修正し、ユーザにより指示された材料厚さを消去し、前記オペレータの選択に基づいて内側或いは外側寸法を残す。
【0193】
前記2次元3面図図面において厚さを消去するために、前記サーバモジュール32は前記オペレータにより行なわれた選択に基づいて前記3つの図の各々を分析する。選択された表面は幾何学的計算により(即ち選択されたエンティティー線分或いは表面と同じX座標或いはY座標射影に存在する対応するエンティティーを検出することにより)他の図の1つへ射影され、前記複数の図の各々における対応するエンティティー及び線分を検出する。対応するエンティティーは、マークされ且つ保持され、合致しないエンティティー或いは表面は削除され或いは図24(b)に示されるそれのように、スクリーン上に表示されない。更にオペレータにより指示される厚さ寸法線は他の図の各々へ同様に射影され、合致する厚さ寸法線或いはエンティティーは図24(b)の例に更に示されるように削除される。結果として、図面内の複数の図の各々は適宜に修正され、前記サーバモジュール32においてユーザに対して表示される。厚さを有しない、結果としての2次元3面図は前記パーツの3次元モデルを生成するために次の工程で使用される。
【0194】
この発明の厚さ削除手続は、各図において削除されるべき厚さ線及び残されるべき表面エンティティーをオペレータが選択的に指示するようにするためのマニュアル厚さ消去モードを含む。表示された図の各々においてどの領域が削除されるべきであり、どの表面が残されるべきであるかを指示するためにマウス或いは他の適当な入力装置がオペレータにより使用される。前記オペレータにより入力されるデータに基づいて前記サーバモジュール32は、厚さを有しない図面を提供するために、前記2次元3面図からオペレータにより選択される各線分エンティティーを削除する。
【0195】
この発明はまた全ての厚さ表現が前記2次元3面図図面において正しく特定されたか否かを分析し且つ検出し且つ、マークされない厚さ要素が存在する時及び/又は図面データ中に矛盾が存在する時、ユーザに警告するための警告システム或いはモジュールを含む。例えば厚さ警告要素は、前記表示スクリーン上で潜在的なマークされない厚さ部分を強調するために設けられ、面警告要素は面の寸法が他の図における厚さのマークと一致しない時、前記スクリーン上で潜在的な一致しない面を強調するために設けられる。曲げ線警告要素は、また矛盾する曲げ線を強調し及び一致しない厚さ曲線を強調するために設けられる。曲線は、この曲線上に射影される少なくとも1つの曲げ線が2つの横断厚さ線分(厚み横断線)により挟まれないとき強調される。例えば図24(c)は、2つ或いは他の零でない偶数の横断厚さ線分(即ち各図において厚さを横断する短い線)により正しく挟まれている厚さ曲線を図示する。各曲げ線は2つ又は他の零でない偶数の横断厚さ線分により挟まれるべきである。各図面における前記パーツのこれらのエンティティーの分析は、ループ分析を実行し且つ各図を作り上げる線分及び円弧エンティティーの連結性を解析することに基づく。開放された厚さ線分は他の厚さ線分或いは曲線と接続しない少なくとも1つの端点を有する厚さ線分に基づいて定義される。1つの開放厚さ線分を含むサイドは開放厚さサイドと定義される。厚さ線分は、開放厚さ線分の開放厚さサイドが最小ループの境界ボックスに一致しない場合に強調される。前記加工された2次元3面図の像に関連する警告をユーザに与えることにより、ユーザは図面データ中の矛盾を警告され、ユーザはパーツの3次元モデルを生成するために更に加工を行なう前に、前記図面データを修正及び/又は訂正することができる。そのような警告システム及びユーザとの相互作用を含むことが3次元モデルによる前記パーツの表現の精密さを改善する。
【0196】
図20のステップS168で、厚さを有しない加工された2次元3面図図面は3次元モデルへ変換され発展させられる。2次元3面図図面から前記3次元モデルへの変換及び展開は良く知られ或いは確立された射影及び/又は突出方法を用いて行なわれる。例えば前記2次元3面図から3次元モデルを生成するために、各図の深さが検出され3次元モデルを展開するために各図が射影される。結果としての3次元モデルは次に曲げモデルデータを生成する際に使用され、また上記した展開アルゴリズムを適用することにより単一の2次元平面図へ変換される。幾何学的モデル化技術についての更なる情報については、モルテンソン、フォリー等及びマンティラを見よ。2次元図面から3次元モデルを構成するための射影技術についての追加の情報については例えば以下を見よ。ウェズレイ等,W.A.「投影図の肉付け」I.B.M.J,RES,DEVELOP、25巻、NO.6、934―954頁(1981)、アオムラ・シゲル、「機械的図面を用いてソリッドモデルを形成すること」第6回コンピュータメカニクスコンファレンス、JSME、NO.930−71、日本、497−98頁(1993)、アオムラ・シゲル、研究及び実際使用の最近の傾向及び将来の可能性(図面から3次元モデルの自動的再構成)東京工学株式会社、日本、6−13頁(1995)。これらの開示はここにそれらの全てにおいて明示的に取り込まれる。
【0197】
ステップS168で3次元モデルを展開する際、結果としての3次元モデルを更に加工し且つ精密化するために追加のクリーンアップ工程が含まれる。この発明の1つの側面によれば、3次元クリーンアップ工程は、前記パーツの2次元3面図において存在し且つ前記パーツの生成された3次元表現において余計な或いは過剰な情報を生成する不明瞭さを補償するために設けられる。当業者に理解されるように、パーツの2次元3面図表現は3次元座標空間における前記パーツの種々の特徴の表現に関連して不明瞭さを含む。前記2次元3面図から3次元モデルを生成する際余計な且つ過剰な情報がこれらの不明瞭さの結果として生成される。従ってこの発明の側面によれば、前記3次元クリーンアップ工程は、1つの端部がつながっていない線分を検出し且つ除去すると共に曲げ線を検出し且つきれいにすると共に面をトリミングする工程を含む。前記3次元クリーンアッププロセスは前記パーツの結果としての3次元モデルを生成する際に自動的に行なわれ或いは前記生成された3次元モデルが追加の工程を要求すると判断される時、オペレータからの入力に基づいて選択的に行なわれる。
【0198】
前記3次元クリーンアップ工程によれば、前記生成された3次元図面データを分析することにより、一端部において他のエンティティーと接続されないと判断される全ての線分或いは曲線が特定され片側開放線分として定義される。片側開放線分であると判断される任意のエンティティーは前記パーツの3次元表現から除去される。一旦開放線分が除去されると、それは他の線分或いはエンティティーが開放されることを導くかもしれない。従って新しい片側開放線分がまた特定され、全ての開放線分或いはエンティティーが除去されるまで、繰り返し除去される。図63は片側開放線分が除去される前のパーツの3次元表現の例を図示し、図64は片側開放線分が前記3次元表現から除去された後の前記パーツを図示する。
【0199】
上記したように、ステップS168で行なわれる3次元クリーンアップ工程は曲げ線を検出しきれいにする工程も含む。曲げ線は、3次元空間におけるパーツの面情報の検出を促進するために特定され且つきれいにされる(例えばモールド線分を加えることにより)。前記生成された3次元モデルデータに基づいて、各曲げ線は、それぞれの中心により定義される同一の法線を有する一対の3次元曲線(例えばそれは図面データにおける曲線エンティティーにより表現される)の検出に基づいて同定される。この過程において、特定された前記曲げ線に対してモールド(形取り)線分が付加される。前記モールド線分は、3次元曲線の各対において対応する終点を特定し且つ前記3次元曲線の対応する終点の間でモールド線分(例えば線分エンティティーで表現される)を延長することにより追加される。図65は曲げ線が特定される前のパーツの代表的3次元表示を図示し図66は前記モールド線分(図において破線で表現される)が追加された後のパーツを図示する。
【0200】
曲げ線が特定され且つモールド線分が追加された後、3次元クリーンアップ工程は更に前記パーツの全ての曲げ線をきれいにし且つ面をトリミングするために前記パーツの3次元表現を加工する。前記2次元3面図データの図における頻繁に生ずる不明瞭さにより、前記パーツの3次元表現に前記面の過剰な部分が生成される。前記3次元クリーンアップ工程は前記面の過剰な部分を特定しそして板金領域知識(例えば何が折り畳めないかについての知識)を用いて前記面をトリミングする。余分な穴或いは開口部のような他の余分な情報も特定され除去される。結果として前記パーツの過剰な部分は除去され前記3次元表現は前記板金パーツのより精密な表現を提供する。図67は前記曲げ線をきれいにし且つ前記面をトリミングする前のパーツの代表的な部分を図示し、図68は正常化及びトリミングがなされた後のパーツの前記部分を示す。
【0201】
図25は材料厚さを持つ最初の3次元図面から材料厚さを持たない3次元図面を生成するためになされる工程及び操作の論理フローの例を示す。ステップS200で、材料厚さを有する最初の3次元図面が入力されサーバモジュール32へ搬入される。前記3次元モデルは材料厚さを有する3次元のワイヤフレーム図面で、DXF或いはIGESファイルのごときCAD図面ファイルである。前記3次元図面が前記サーバモジュール32へ搬入された後、厚さ除去工程がステップS204で行なわれる。ステップS204における前記3次元モデルに対する厚さ除去工程は上記したアマダUNFOLDソフトウエア・システムにおいて提供されると同じ方法で行なわれる。前記3次元モデルにおいて厚さを消去するために、オペレータはまず厚さを指示し且つ残される面を選択するように促される。このオペレータの選択に基づいて厚さを定義するエンティティー線分の終点を解析することにより厚さが測定される。しかる後、選択された表面の境界が、前記ループ及びエンティティー解析工程に関連して上記したと類似の方法により探索される。そして保持されるエンティティーはマークされ(例えばフラグを設定し或いは増加することにより)、対応する厚さエンティティーは除去される。前記3次元パーツのエンティティーを探索する際、前記エンティティーは、ユーザにより選択された厚さエンティティーの長さに基づいて識別される。一般的に前記厚さエンティティーと同じ長さを有する全てのエンティティーは選択されず除去され、同じ長さでない他のエンティティーがマークされ残される。前記3次元パーツの表面の探索でマークされなかった残りのエンティティーもまた除去されることがある。再びサーバモジュール32はマニュアル厚さ除去モードを提供し、そこではオペレータは除去されるべき3次元パーツにおける各エンティティーを手動で指示する。
【0202】
ステップS204の後、厚さを有しない、結果としての3次元モデルがステップS206で展開され及び/又はオペレータに対して表示される。展開アルゴリズム或いは工程が次にその材料厚さを有しない3次元モデルに適用され上に詳細に説明したように、曲げモデルデータについての単一の2次元平面図を生成する。上記したように前記データベース30に格納されるデザイン及び製造情報は、板金要素についての製造データのみならず板金の幾何学形状及びトポロジーを含む曲げモデル・データファイルを含む。更にこの発明の種々の特徴を実行するために使用されるソフトウエアはC++のごとき高度のプログラム言語を用い且つオブジェクト指向プログラム技術を用いて生成される。この発明の種々の特徴を実行するためには、Booch或いはOMTのごとき異なるオブジェクト指向技術も使用される。オブジェクト指向プログラムが使用される場合は、前記板金パーツを表現するためにオブジェクト指向データが使用され、前記パーツのための曲げモデルは完全に自己充足的クラス・ライブラリを介して実行される。この発明の1つの側面により、オブジェクト指向プログラム技術に基づく、前記曲げモデルのための代表的データ構造及びアクセス・アルゴリズムの記述が提供される。図26は、本願発明をオブジェクト指向プログラムにより実行する際使用される前記曲げモデルの代表的データ構造及びアクセスアルゴリズムを図示する。オブジェクト指向プログラムは、データを含む複数のオブジェクト或いはモジュールのみならずそのデータに作用する複数の指示を結合することにより現実世界をモデル化することができるソフトウエア展開の1つのタイプ或いは形態である。オブジェクト指向プログラムにおいては、オブジェクトは板金パーツのごとき、何か物理的なものをモデル化するソフトウエアエンティティーであり、或いはそれらはビジネス上の商取引のごとき仮想的な何かをモデル化するものである。オブジェクトはそのオブジェクトの状態を集合的に定義する1つもしくはそれ以上の属性(即ちフィールド)を含み、且つ全ての他のオブジェクトからそれを識別するための識別子を含む。更にオブジェクトはある種の条件の存在に基づいて、前記属性を修正し或いは前記オブジェクトに対して作用をなす一群の方法(即ち手続き)により定義される振る舞いを含む。
【0203】
この発明の実施例によれば、前記板金パーツはオブジェクト指向データモデルとして表現される。図26に示されるように板金パーツの曲げモデルは完全に自己充足的なクラスライブラリとして定義される。前記板金パーツのための全ての要求されるデータ操作及び機能(例えば折曲げ、展開等)はこのクラスライブラリの要素機能として取り込まれる。全ての幾何学的或いはトポロジーデータは前記曲げモデルの中で分類される複数のオブジェクトの内部で定義される。前記曲げモデルクラスライブラリは複数のクラス或いはオブジェクトの階層であり、パーツクラスはその階層の最上レベルのクラスである。前記パーツクラスは種々のパーツ属性を有するパーツオブジェクトを含み、前記パーツ及び前記パーツに対してなされる複数の作用を定義する種々のオブジェクトを含む。
【0204】
図26は、前記曲げモデルクラスライブラリにおいて分類される種々のオブジェクトの例を示す。例えば種々の属性52を含むパーツクラス50が提供される。前記パーツ属性52はパーツ番号及び/又は名前、パーツ材料タイプ及びパーツの厚さのごとき種々のパーツ情報を含む。前記属性52はまた、複数の曲げがなされる順番を指示するための曲げ順情報及び前記パーツの種々の寸法についての誤差要求のごとき他の製造情報を含む。前記パーツクラス50はまた図26に示されるように面オブジェクト54、穴オブジェクト56、成形部オブジェクト58、及び曲げ線オブジェクト60のごとき種々のオブジェクトを含む。前記オブジェクト54,56,58及び60の各々はそこに表現されたエンティティー(例えば面、穴、成形部、及び曲げ線)の各々についての一群のオブジェクトからなる。前記面オブジェクト54、穴オブジェクト56、成形部オブジェクト58、及び曲げ線オブジェクト60はそれぞれ幾何学形状及び寸法データ、2次元及び3次元空間表現における位置及び座標データ、及び前記パーツのそれらの各エンティティー(例えば面、穴、成形部、及び曲げ線)の端及び表面に関連するデータを含む。例えば、前記面オブジェクト54は、前記複数の面の各々についての幾何学形状及び寸法データ、2次元及び3次元表現における前記複数の面の空間位置データ、及び前記複数の面の端及び表面についての端及び表面データを含む。更に、成形部オブジェクト58は、前記パーツにおける特殊な成形部に関連するデータを含み、このデータは幾何学形状及び寸法データ、2次元及び3次元空間位置データ、及び端及び表面データを含む。
【0205】
図26の実施例に更に示されるように、パーツクラス50は更にトポロジー・オブジェクト62及び曲げ特性オブジェクト64を含む。前記トポロジーオブジェクト62は、前記パーツの前記面、穴、成形部及び曲げ線についてのパーツトポロジーデータを含む。前記トポロジーオブジェクト62におけるデータは前記パーツの前記種々の特徴の構造的及び幾何学的関係を示す。前記曲げ特性オブジェクト64は前記パーツの1つ或いはそれ以上の特徴についての特殊な製造上の拘束に関する情報を含む。例えば如何に前記板金パーツが曲げられるべきであるかに関する曲げ特性情報が、前記曲げ特性オブジェクト64に設けられる。前記曲げ特性情報は、異なる曲げ特性タイプ(例えば同時曲げ、同一直線上曲げ、Z曲げ等)についての特殊製造データを含む。
【0206】
前記曲げ線オブジェクト60は、また行なわれる曲げに関連する製造特殊データを含む。従って、各曲げ線についての幾何学的或いは寸法データ、2次元及び3次元空間位置データ、端データに加えて、前記曲げ線オブジェクト60はまた、各曲げ線についてのV幅データ、曲げピッチデータ、曲げ数データ及び/又は配向データを含む。各曲げ線は、図26に示すように付随する曲げ操作を含む。この曲げ操作は、各曲げ線において曲げを行なうためのデータ及び操作/指示を有する一群のオブジェクトとして実行される。仮にオブジェクトとして提供されると、各曲げ操作は、曲げ角度、曲げ半径及び/又は曲げ縮小量のごとき固有の曲げデータのみならず、如何に或いはどのタイプの曲げを行なうべきか(例えば円錐曲げ、Z曲げ、ヘミング、円弧曲げ等)を指示するデータ及び指令を含む。
【0207】
前記パーツの曲げモデルを、オブジェクト指向データモデルを介して実行することにより、全ての複雑な数学的計算、計算幾何学及びマトリックス変換が単一のクラスライブラリに組み込まれる。ヘミング、Z曲げ及び円弧曲げのごとき特殊な曲げ操作もそのクラスライブラリに取り込まれる。更にV幅及び曲げ縮小量及び曲げ順のごとき製造情報もそのクラスライブラリに取り込まれる。前記曲げモデルにより、前記2次元平面モデル及び3次元モデルの同時二重表示が図26に示すように行なわれる。更に、前記曲げモデルの曲げ線オブジェクト60に応じて曲げ加工が行なわれる。前記曲げモデル及びパーツ構造並びにそれらについての実行に関連する一般的なコメントはここに添付した付録Kに提供される。
【0208】
曲げモデルビューアが前記曲げモデルを解釈し、2次元及び/又は3次元表現における前記パーツの視覚的な画像を表示するために設けられる。図27は、この発明の他の側面による、前記曲げモデルビューアの構造と前記曲げモデルとの関係のブロック図を図示する。前記曲げモデルビューアはオブジェクト指向プログラム技術を介して実行され、前記設備38における種々の場所10,12,14,…20の前記ステーションモジュールにおけるユーザが前記曲げモデルに設けた情報に基づいて前記パーツの種々の図を表示できるようにするウインドウズに基づくアプリケーションである。前記曲げモデルビューアは、前記板金パーツを視覚化するために用いられる一群のアプリケーション・ライブラリ・モジュールを含む。更に、前記曲げモデルビューアは、ウインドウズ・アプリケーションの画像クラスとして設計され、従ってそれは任意のウインドウズ・アプリケーションについての基本的画像クラスとして使用される。前記2次元及び3次元モデルを見るための殆どの標準的操作(例えばズーム92、回転96、パン100、寸法102等)は前記曲げモデルビューアの要素機能として実行される。幾何学的変換及び基本的コンピュータグラフィックス技術は、画像操作を実行する際に前記曲げモデルオブジェクトに対して適用される。更に、前記曲げモデルビューアは、画像モデル属性88を含み、それはソリッド画像、ワイヤフレーム画像、2次元平面画像及び正射影画像を含む4つの主なる画像モードを有する。
【0209】
この発明の1つの側面によれば、前記曲げモデルクラスライブラリ80は、選択された画像(例えばソリッド、ワイヤ、2次元平面又は正射影画像)に応じて、前記板金パーツに作用する一群の手続き又は機能を含む。前記曲げモデルビューア観察クラス84は、ズーム92、回転96、パン100及び寸法102のごとき、一連の標準的操作を含む。そして、前記曲げモデルビューアの状態に応じて、前記曲げモデルビューア観察クラスは、前記曲げモデル・クラス・ライブラリ80から複数の機能を呼び出す。図27に示されるように、ユーザにより選択される前記種々の観察モデル属性或いは特徴88は、ソリッド画像、ワイヤフレーム画像、2次元平面画像及び正射影画像を含む。この発明に設けてあるこれらの種々の観察モードの記述は図28−31を参照して以下に提供される。
【0210】
基本的コンピュータグラフィックス及び幾何学的モデル化技術、例えば幾何学的変換及び3次元幾何学的技術は、前記曲げモデルの種々の特徴を実行し且つ異なる観察モード或いは機能を提供するために使用される。コンピュータに基づいた2次元及び3次元のモデル化及びシミュレーションにおける最近の発展及び展開、例えばグラフィックライブラリ或いはパッケージの効用はこの発明のこれらの特徴を実行するために適用される。更に、コンピュータグラフィックス及びモデル化については広い種類の刊行物或いは文献が利用可能である。例えば、モルテンソン、フォリー等、マンティラを見よ。それらの各々は上に記載した。
【0211】
この発明の種々の観察及びモデル化の特徴を提供するために各ステーションモジュール及びサーバモジュールは、800×600の解像度を有するSVGAスクリーンのごとき高解像度表示スクリーンを有する。ジョイスティック及び/或いはゲームカードも前記ステーションモジュール及びサーバモジュールに提供され、ユーザが、前記パーツの異なる2次元及び3次元表現を選択的に修正し且つ観察することを可能とする。ソフトウエアに基づいたグラフィックス・パッケージ、例えばオープンGL(OpenGL)及びレンダウェア(RenderWare)は、グラフィック計算を行なうために使用される。それらのグラフィックライブラリ或いはパッケージはウインドウズに基づいたアプリケーションで種々の観察モードを実行するために使用される。例えばオープンGLは前記曲げモデルに設けてあるパーツ幾何形状及びトポロジーデータに基づいて種々の2次元ワイヤフレーム画像を実行するために使用される。更にレンダウェアは前記曲げモデルに設けてあるパーツデータに基づいて、前記板金パーツの種々の2次元及び3次元ソリッド画像を表示するために使用される。オープンGLについての更なる情報については、例えばオープンGL・レファレンスマニュアル及びオープンGL・プログラミングガイド、リリース1、オープンGL・アーキテクチャ・レビュー・ボード、アディソン−ウエズレイ発行社、リーディング、マサチューセッツ(1992)を見よ。レンダウェアの情報については例えばレンダウェアAPIレファレンスマニュアルV2.0、クライテリオンソフトウエア株式会社、イギリス(1996)を見よ。
【0212】
前記パーツの種々の画像を表示するために、前記曲げモデルは例えばオペレータのステーションモジュールにより前記データベース30からアクセスされる。前記曲げモデルデータは、使用されているグラフィック・ライブラリ或いはパッケージ(例えばオープンGL又はレンダウェア)により使用されるデータフォーマットに応じて再フォーマット化される。しかる後、前記グラフィックデータは、オペレータにより選択された観察モード(ワイヤ、ソリッド等)を表示し、或いは前記ユーザにより実行された観察機能(ズーム、パン等)を実行するために種々のプログラムされた順序に従って加工される。
【0213】
特定の観察モードがオペレータにより選択される時、選択された観察モードは、前記画像の現在のズーム比率或いはファクター及び向きと共に検出される。この情報は、次に前記現在の表示を更新するために前記グラフィックパッケージに対して機能コールを行なうために使用される。前記グラフィックパッケージに対する機能コールは、表示される観察モード並びに実行されるズーム或いはその他の観察機能に応じて行なわれる。これらの機能コールに基づいて前記グラフィックパッケージは必要なデータを提供し、従って前記ステーションモジュールは前記オペレータに対して前記パーツの画像を表示する。前記ユーザによる前記2次元又は3次元表現の修正(例えばジョイスティック或いはマウスを移動することにより)に基づいて前記表示された画像を更新するために追加の機能コールは前記グラフィックライブラリに対してなされる。
【0214】
前記パーツのワイヤフレーム画像を提供するために、前記グラフィックパッケージに対して前記パーツの線分エンティティーデータが提供され必要なグラフィック計算がなされる。しかし、ソリッド画像については、前記面の各々について1つもしくはそれ以上の多角形(ポリゴン)が引き出され、前記画像を表示するために前記グラフィックパッケージへ入力として提供される。オープンGL及びレンダウェアのようなグラフィックパッケージは、多角形データを入力として取得し、ソリッド画像を提供するために前記多角形により定義される領域を満たす。前記多角形は、前記曲げモデルにおける面及び曲げ線情報から導出され各面の境界を決定することにより導出される。前記多角形は前記パーツの各面を表示し且つ定義するために生成されなければならない。これらの面は次に、板金パーツ全体を表示するために、前記曲げモデルにおける前記パーツトポロジー及び他のデータに基づいて接続される。仮に面が開口部或いは穴を有する場合には、そのような開口部を囲まない幾つかの多角形を有する面を定義することが必要となる。正射図については、個々の図の各々(それはワイヤフレーム又はソリッドである。)についてのデータは前記グラフィックパッケージに送られ、図31に示されるごとく、結果としての複数の図が単一の表示スクリーン上で結合される。前記曲げモデル像の種々の観察モード及び機能を実行するための代表的コードは付録Eに提供される。このサンプルコードはC++で記載され前記プロセス及びそこで実行される操作に関連する複数のコメントを含む。適当なグラフィックパッケージ(例えばオープンGL及びレンダウェア)との結合における前記コードは異なった図(例えば2次元及び3次元ワイヤフレーム或いはソリッド)を表示するために使用されるだけでなく、前記観察機能(例えばズーム、回転、パン等)の各々の機能を提供する。表示される種々の観察モード表示スクリーンの簡単な説明が以下に与えられる。
【0215】
ソリッド図モードは、前記曲げモデルにより定義される前記パーツの、ソリッドで表示される3次元図を表示する。図28は前記板金設備38内での位置10,12,14,…20のいずれかにおいて設けてある表示スクリーンへ出力として提供される代表的ソリッド図ウインドウを図示する。このソリッド図モードにおいて、ユーザ或いはオペレータは、3次元空間でのナビゲーション及び3次元自動寸法付けを操作するための複数の観察機能を与えられる。前記パーツのソリッド図を変更するために設けられる基本的な機能は回転、ズーミング、パンニング、及び/又は標準図選択を含む。前記ユーザにより与えられ或いは選択される前記標準図は以下を含む。即ち等測投影法図、平面図、底面図、正面図、背面図、左図、及び右図。自動及びマニュアル寸法付け操作がまた提供され、現在の観察角度に基づいて前記パーツの重要な寸法を表示する。この発明の寸法付け特性の代表的例が、図32−36を参照して以下に提供される。
【0216】
図28に示されるようにソリッド図ウインドウはウインドウズに基づいたアプリケーションであり、従って前記パーツの複数のウインドウ或いは部分図が提供される。前記複数の図のウインドウは、ウインドウの中で1つの極めてクローズアップされた単一の図を提供する拡大図及び単一のウインドウにおいて前記パーツの極めて遠くからの図を与える鳥瞰図を含む。前記部分図はユーザにより選択されたオブジェクトの部分図を与える。前記種々の観察機能を制御するために、前記場所10,12,14,…20の各々の前記サーバモジュール32及びステーションモジュールに、ジョイスティックインタフェースが設けられる。前記ジョイスティックだけ及び/又はキーボード上の所定のキー(例えばシフトキー又はコントロールキー)の操作との組み合わせの操作が、回転及びパンニング及びズーミングのごとき種々の機能を実行するためにユーザにより行なわれる。更に、前記パーツのソリッド図の表示される生地は、データベース内での前記パーツについて特定された材質をシミュレートするように選択される。この目的のために、スチール、ステンレススチール、アルミニウム等のごとき材料の生地のライブラリを有する材料生地ライブラリが提供される。格納された材料生地ライブラリはソリッド図が存在する時オペレータによりアクセスされ適用される。従って、表示されるパーツの表面は前記板金パーツの実際の生地をより忠実にシミュレートする。
【0217】
前記ワイヤフレーム図モードは、前記板金パーツのワイヤフレーム図のウインドウズに基づいた表示を提供する。ワイヤフレームウインドウの例が図29に示されている。前記ワイヤフレームにおける3次元空間ナビゲーション及び3次元寸法付けを提供するためのキーの機能は、前記ソリッド図に関して上に記載したと類似である。例えば回転、ズーミング、パンニング及び標準図の選択のごとき機能が提供される。自動寸法付け、多重図ウインドウ及び断面図オプションも前記ワイヤフレーム図モードにおいて提供される。更に、ジョイスティック及び/又はキーボードインタフェースが、ユーザが前記種々の観察機能を選択し且つ活性化することができるように提供される。
【0218】
前記2次元平面図モードはワイヤフレーム表示において、前記パーツの展開された2次元平面図を表示する。2次元平面図ウインドウの例が図30に示されている。この2次元平面図モードはユーザがウインドウ中の図を変更し又は改造するのを可能とするための複数の観察機能を有する。例えばユーザが前記2次元平面ワイヤフレーム図を選択的にズームし且つパンするのを可能とするようにズーミング及びパンニング機能が設けてある。更に、寸法付け及び多重ウインドウ観察機能が、前記ソリッド図モードに関して上記したと同様の態様で設けてある。ジョイスティック及び/又はキーボードインタフェースはユーザがパンし、ズームし他の観察機能を制御するのを可能とするように設けてある。前記パーツに設けられている特殊な成形部または形状は、特殊な成形部の指示又は記載と共に、前記成形領域の前記最も外側の境界についての成形または形状として表示される。
【0219】
図31に図示されるような正射図ウインドウも前記曲げモデルビューアの一部として提供される。前記正射図モードはワイヤフレーム表示において平面図、正面図、右図及び等測投影法図を表示する。隠れ線オプションが、観察角度に基づいてブロックされた線を見えなくするために設けられる。この隠れ線オプションは各図のウインドウを簡単化するために用いられる。前記正射図モードにおいても種々の観察機能が提供され、ユーザが前記ウインドウにおいて現在の図を選択的に操作し且つ変更するのを可能とする。例えば、ズーミング及びパンニング機能が寸法付け及び多重ウインドウ観察機能と共に設けられる。上記したように、多重ウインドウ観察機能が設けられ、ユーザが、多重ウインドウにおいて前記正射図の拡大図及び/又は鳥瞰図を選択的に表示することを可能とする。ジョイスティック及び/又はキーボードインタフェースが、前記複数の場所の各々に設けられ、ユーザが、前記正射図モードにおいて前記複数の観察機能の各々を選択的に活性化し且つ操作するのを可能とする。
【0220】
上記した種々の図の表示の各々を表示せしめるのに加えて、前記曲げモデルビューア観察クラスは他の特徴と共に実行される。例えば前記曲げモデルビューアはオペレータにより選択され強調されている、現在の図における複数の項目或いはエンティティーを指示するための選択集合を含み且つ維持する。この発明の1つの側面によれば、オペレータは、選択された項目に関連するデータを修正し或いは前記パーツのそれらの項目の所定の操作を行なうために、前記表示されたパーツの面及び曲げ線及び他の特徴を選択することを可能とされる。例えばオペレータは、表示されたパーツの面を選択し、その面のその幅或いは長さに沿っての寸法データを変更することができる。オペレータはまた曲げ角度又はV幅のごとき各曲げ線に付随する種々の曲げデータを修正することができる。
【0221】
前記曲げモデルビューアはユーザにより選択されたエンティティー或いは項目(例えば面、曲げ線、面或いは曲げ線の端等)のリストを保持する。観察者はそのリストを更新する。従ってオペレータにより現在選択されている現在の項目は前記選択リストに常に保持される。この発明におけるソフトウエアの他の部分は、異なる手順(例えばマニュアル寸法付け等)を実行し或いは行なう際、選択されたエンティティーの前記現在のリストの図面クラスを呼び出す。
【0222】
更に前記曲げモデルビューアは観察可能性機能を提供する。それは現在表示されている図に基づいて観察可能性情報及び座標情報を提供する。以下に更に十分に説明されるように、前記観察可能性機能は前記パーツの特定な部分或いはエンティティーがスクリーン上で現在観察可能であるか否かについての情報を提供し且つスクリーンエンティティーが現在位置する場所についての座標情報を提供する。前記曲げモデルビューアの観察可能性機能は、前記パーツのどの部分が現在スクリーン上で観察可能であるかを決定するためにこの発明の寸法付け特性により呼び出される。従ってスクリーン上で観察可能である前記パーツの部分の寸法情報のみが観察者に対して表示される。この発明の寸法付け及び観察可能性機能のより詳細な説明は以下に提供される。更に前記曲げモデルビューアの観察可能性機能を実行するための代表的コードはここに添付する付録Jに提供される。
【0223】
図32−36を参照するに、この発明の1つの側面に基づく、寸法付け特性の事例が説明される。上記したように、観察モードの各々は現在の観察方向に基づいて、前記パーツの寸法を自動的に表示する寸法付け機能を含む。自動寸法付け機能は、現在の観察角度においては見ることができないフランジ或いは曲げ線の寸法がユーザに対して表示されないように提供される。前記自動寸法付け機能或いはモードが活性化される時、前記パーツの観察可能な寸法のみが、現在の観察角度に基づいて表示される。更に、自動寸法付けモードにおいては、所定の寸法(即ち前記曲げ操作に対して重要である寸法)のみが現在の観察角度の状態に基づいて表示される。マニュアルの寸法付けモードも提供され、ユーザがどの寸法が表示されるべきであるかを選択的に指示することを可能とする。このマニュアル寸法付けモードにおいては、ユーザにより選択された寸法事項のみが、現在のパーツの観察角度に基づいて表示される。いずれの寸法付けモードにおいても、表示された寸法事項は、前記パーツがズーム化され或いはパンされる時ウインドウ表示から消去され或いは除去される。
【0224】
図32は自動寸法付けモードにおいて表示される種々の寸法事項の例を図示する。前記自動寸法付けモードにおいて表示される寸法事項は、曲げ操作に重要な事項(例えばフランジ長さ、曲げ線長さ、曲げ角度等)からなり、パンチ加工された穴或いは開口部の寸法のような余分な寸法事項ではない。前記表示される寸法事項は例えば前記板金パーツの幅、深さ、及び高さ並びにフランジ長さを含む。更に、各曲げ線の前記曲げ線長さL、曲げ角度A、内側半径R及び曲げ縮小Dは単独で或いは一緒に、1つのウインドウに或いはグループ情報ボックスに表示される。上記したように、現在の観察角度に基づいて観察可能な寸法事項のみが表示される。更に前記オペレータが、前記パーツの観察角度を変えるために回転、ズーミング或いはパンニングをする時全ての寸法は表示から消去され或いは除去され、各操作が完了した時それらの寸法は再び表示される。表示情報(任意のテキスト或いは参照矢印)の寸法及び向きは、現在のズームの比率或いは観察角度ではなくスクリーンの寸法に対して常に寸法調整される。しかしながら、前記寸法情報の可読性を改良するために前記寸法情報の色、スタイル、重み及び/又はフォントはユーザがそれらを変更できるように形成可能である。結果としてオペレータ或いはデザイナーは、前記寸法情報の特殊の色、フォントサイズ等を選択することによりパーツにおける重要な寸法を強調することができる。例えば、寸法テキストの色、寸法又はフォント又は、寸法参照事項、線又は矢印の色、線の重み或いはスタイルは、パーツにおける重要な寸法を指示するために強調され或いは選択的に変更される。オペレータはまたウインドウ情報ボックスを色付けし満たし或いはスタイル付けし或いは特定の曲げ線を色付けし或いはパーツ内の他の重要な寸法を強調する。
【0225】
この発明の寸法付け特性を実行するために種々のプロセス或いは操作が利用される。更に上記したように本発明の寸法付け特性に対して観察可能性情報を提供する観察可能性機能を、前記曲げモデルビューアは備える。これらの機能或いは特性は、例えばサーバモジュール32及び/又は工場全体に位置するステーションモジュールのそれぞれでソフトウエアにより実行される。この発明の自動寸法付け特性を実行するための代表的コードが付録F−Iに設けてある。更に、曲げモデルビューアの観察可能性機能のためのサンプルコードが付録Jに設けてある。これらの付録におけるコードはC++プログラム言語で書かれており、そこで行なわれる手続き及び操作の論理フローの理解を容易にするためのコメントを含む。
【0226】
この発明の寸法付け特性の論理フローは一般的に3つの段階に分類される。第1の段階で、前記パーツの曲げモデル幾何形状及びトポロジーデータがデータベース30からアクセスされ、前記パーツの全ての寸法並びにそれらの寸法が表示され得る全ての態様を計算するために使用される。前記パーツの各曲げ線及び面について、データが表示され得る全ての最も遠い点が計算され、これらの点について、寸法線或いは矢印が表示され得る全ての方法が計算される。前記寸法データ或いは他の情報が表示され得る場所を決定する際に一定のヒューリスティックが適用される。例えば一般的なルールとして、全ての情報は前記パーツの外側にのみ表示されると決定される。このようなヒューリスティックが、前記ビューアに対してより意味のあるそしてより込み合わない情報の表示を提供するために適用される。
【0227】
上記した第1の段階は、本発明の寸法付け特性がオペレータにより活性化された際常に実行される。或いは、前記第1段階の計算は前記パーツが最初にオペレータにより観察された際にのみ行なわれる。このような場合に、前記計算されたデータは次の使用のためにメモリに格納され、前記パーツの寸法或いは他の幾何学的データがユーザにより修正され或いは変更された時変更される。更に前記第1段階の全ての計算は図面スクリーンに対してではなくパーツの幾何学形状に対して行なわれる。従って前記データは、現在の図面に関わりなく或いはその図面が変更されても何時でも再び使用され得る。
【0228】
この発明の自動寸法付け特性の第2段階は前記パーツの図面が更新された時常に行なわれる。この第2段階の主たる目的は、変更された図において前記パーツのどのエンティティーが観察可能であるかに基づいて前記第1段階中に生成されたデータをふるいにかけることである。この第2段階において、現在の図において観察可能でない全てのデータはふるいにかけられ、現在観察可能である、前記第1段階において計算されたデータのみが残る。前記パーツのいずれの点あるいは部分が現在観察可能であるかを決定するために前記曲げモデルビューアに対する機能コールがなされる。上記したように、前記曲げモデルビューアは、表示されている現在の図に基づいて前記パーツの観察可能な部分についての情報を保持し且つ提供する観察機能を含む。前記パーツの向きに基づいて前記曲げモデルビューアは前記パーツのどの面及び曲げ線(並びにそれらの面及び曲げ線のどの端或いは部分)が観察可能であるか、そして何がスクリーン上で隠されているかを決定する。
【0229】
上記したように、前記曲げモデルビューアの観察可能機能を実行するためのサンプルコードは付録Jに提供される。前記パーツのいずれの点あるいは部分が観察可能であるかを決定するために、前記曲げモデルビューアは前記パーツの現在の図の向き及び現在のズーム面又は表示されているパーツの比率を決定し且つ維持する。前記曲げモデルビューアはこの現在の図の向きを決定し維持するために従来の透視図射影技術(モルテンソンの例えば12章を見よ)を使用する。前記パーツの任意の点の観察可能性を決定する際に前記点の世界座標(即ちそこにおいて前記パーツが表現されているところの座標)を前記観察可能性機能は獲得する。次に、前記現在の図面の向き及びズーム面あるいは比率に基づいてその点について、前記世界座標に対応するスクリーン座標(即ちスクリーン上の画素の位置)が決定される。その後、前記スクリーン座標に基づいて、前記スクリーンの観察点の眺めから前記部品の任意のエンティティー或いは部分が問題の点の前方にあるか否かが決定される。前記パーツの上の点の隠されている特性は、前記パーツの他のエンティティー或いは部分が問題の点と同じスクリーン上の点を割り当てられているかどうかに基づいても決定され得る。グラフィックパッケージ或いはライブラリ(例えばオープンGLあるいはレンダウェア)への機能コールは、前記パーツの1つの点以上が同じスクリーン上の点に割り当てられているかどうかを決定するために使用される。もし何かが同じスクリーン上の点に割り当てられているならば、それらの点のそれぞれのZバッファ深さに基づいて、前記パーツの点がそれの後ろにあるかどうかが決定される。前記Zバッファ深さはオープンGL或いはレンダウェアのごときグラフィックパッケージにより使用され、観察点或いはカメラ位置からそれぞれの点への距離を定義する。前記Z深さは、興味のある前記パーツの複数の点について前記グラフィックパッケージへ機能コールを行なうことにより決定される。
【0230】
前記曲げモデルビューアの観察可能性機能の前記プロセスはこの発明の自動寸法付け特性から前記曲げモデルビューアへ催促がある時いつでも実行される。そのようなプロセスは従って前記オペレータにより表示されているパーツの現在の図が修正され或いは変更される時いつでも実行される。上記したように、前記曲げモデルビューアは、表示された画像の向きに対して変更がなされる時は常に、現在の図の向き及びズーム比の状態を維持し且つ更新し、従って要求される時観察可能性情報を正確に提供する。
【0231】
どのデータが観察可能であるかを決定した後、自動寸法付け機能は、(例えば第1段階での計算に基づいて)前記寸法データ或いは他の情報が表示され得る全ての可能な方法及び位置を決定する。前記データが表示され得る全ての可能な方法からデータを表示するための最適の方法を選択するために一群のヒューリスティックが適用される。例えば第1のヒューリスティックは、観察者の観察点により近いスクリーン上の領域が好ましいと要求する。第2のヒューリスティックは、前記寸法を定義するための2つの可能な点の間の距離が最小であるところの領域により近い領域にデータは表示されるべきであると規定する。他のヒューリスティックはまた、スクリーン上での重なり合い或いは混雑を避けるために、他の寸法データ或いは他の情報の相対的位置に基づいて適用される。
【0232】
前記パーツの観察可能な部分及び前記観察可能な領域についての情報を表示するための最適の領域を決定した後、前記自動寸法付け機能の第3の段階は前記表示スクリーン上で種々の情報を描くために実行される。例えば、前記情報を表示するための領域の選択に基づいて、寸法情報は前記パーツの観察可能な寸法の各々についてスクリーン上に表示される。更にどの曲げ線が観察可能であるかに基づいて、曲げ線情報がまた、他のパーツ情報とオーバーラップしないスクリーンの領域において情報ボックス(例えば図32に示されるそれ)に表示される。前記パーツの幅、高さ、及び深さを含むパーツの寸法はまた前記スクリーン上の所定の位置(例えば前記パーツの右下)或いは前記パーツに最も近く他の情報にオーバーラップしない或いはそれを邪魔しない位置に表示される。
【0233】
図33−36は前記寸法付けモードにおいて寸法事項を表示する際に、使用される種々の方法及び定義を図示する。特に図33(a)−33(b)及び33(c)は、種々の異なるパーツについてフランジ寸法が定義される方法を図示する。この発明の1つの側面によれば、前記フランジ長さは、各曲げ線からフランジ上で最も遠い点として定義される。もし前記曲げ線と並行であるフランジの最も長い端部に前記フランジの最も遠い点が存在しない場合には、前記寸法付けモードにおいて最も長いフランジが追加され表示される。限定しない事例として図34(a)及び34(b)は、2つの異なるタイプのパーツについて補助的なフランジ長さを追加することを図示する。前記パーツの厚さが表示される時、フランジ長さは外側寸法の外側として表示される。例えば図35(a)、35(b)及び35(c)は、厚さを有して表示される種々のパーツについて前記フランジ長さが指示される態様を図示する。更に、鋭角の曲げを備えたパーツについて、前記フランジ長さは種々の方法で表示される。例えば図36(a)に示されるように、フランジ長さは、接線寸法定義に基づいて表示され、そこでは前記フランジ長さは前記鋭角曲げから延長される接線から測定される。或いは、前記鋭角曲げ角度の2つの辺から延長された2つの直線の交差により定義される点に基づいてフランジ長さを定義するために、図36(b)に示されるそれのごとき交差寸法方法が使用される。オペレータは、前記フランジ長さを表示するために前記接線寸法或いは交差寸法方法のうちから選択することを可能とされ、及び/又は特定の寸法方法(例えば接線寸法方法)はデフォルト設定として提供される。
【0234】
曲げコード順番の生成を促進するために、種々の表示機能を有した図形的ユーザインタフェースが設けられ、オペレータによる曲げプランの生成を助ける。図37−44はこの発明の他の側面により、図形的ユーザインタフェースの使用により曲げコード順番を生成するために実行される種々の手続き及び操作を図示する。通常、最初の曲げモデルデータ及び他の作業情報はサーバモジュール32において重要な幾何学的及び製造データを入力することにより設計プログラマにより生成される。結果としての曲げモデルファイルは次にデータベース30に格納される。板金パーツが製造される前に、曲げオペレータが、所望の曲げ操作を実行するための曲げ順を生成する必要がある。この曲げオペレータは、どのタイプの工具が必要であるかを決定し且つ前記曲げ機械装置について工具取付けを定義しなければならない。この曲げプラン生成の工程は、図形的ユーザインタフェースの使用によりまたこの発明の種々の教示により援助され、且つより効率的となる。
【0235】
前記曲げプランを生成するために、例えば曲げステーション18の曲げオペレータは、前記データベース30から前記曲げモデル及び他の作業情報へアクセスし且つダウンロードする。前記関連するパーツについての曲げモデルは前記コミュニケーションネットワーク26を介して曲げステーション18における工場フロア上のステーションモジュールへ搬入され或いは移入される。この工程は、一般的に図37のステップS220に示される。その後、ステップS224で曲げオペレータは、前記曲げモデルビューアを用いて前記パーツの形状及び寸法を調べる。ここで、前記曲げオペレータは、前記曲げステーションに位置付けられた表示スクリーンで前記パーツの種々の2次元及び3次元図を選択的にズームし且つパンする。この発明の自動寸法付け特性を活性化することにより、前記曲げオペレータはまた曲げ操作を実行するために前記パーツの重要な曲げ寸法を観察する。
【0236】
一旦オペレータが前記パーツの形状及び寸法を理解すると、この曲げオペレータはステップS228で曲げ順入力ウインドウを選択し且つ表示することにより前記曲げプランを生成することを開始する。前記曲げ順入力ウインドウは、曲げオペレータが曲げ順を生成し且つ修正し且つ消去するのを援助するために図形的ユーザインタフェースを提供し且つオペレータが、前記曲げ順における各段階についての種々の製造パラメータ(例えばバックゲージ位置、工具、NCデータ等)を特定し且つ入力することを可能とする。前記曲げ順入力ウインドウは前記スクリーンの一部(例えばスクリーンの中央部或いはスクリーンの左側の方)に表示される前記パーツの2次元平面図画像を含む。前記2次元平面図画像は、前記パーツのフランジ、穴及び開口部を含む、前記展開パーツの種々の特徴を含む。前記曲げオペレータが前記複数の曲げ線及び各曲げ線についての曲げ順を選択し且つ指示すると、各曲げ段階における前記中間的パーツ形状のソリッド2次元或いは3次元画像が現れ、例えば図38に示されるように、スクリーンの右側の端のごときスクリーンの一部にそれらが提供される。前記中間パーツ形状の画像は入力された曲げ順に対応した順番で表示され且つ(図38の例に示されるように)前記パーツの2次元平面図と共にスクリーン上に同時に表示され、或いは別個のスクリーン表示に別個に表示される。
【0237】
更に各曲げ線が選択されるにつれて、前記曲げ線は強調され、図39(a)に一例として示されるように、曲げ順番号及び挿入方向(例えば矢印で表現される)が前記曲げ線の上或いは近くに表示される。各曲げ線についての前記曲げ線番号は、それが選択される順番に基づいて自動的に設定され、或いは各曲げ線が選択された後オペレータによりマニュアルで入力される。曲げ角度、曲げ線長さ、及びバックゲージ位置のごとき曲げ線に関連する他の製造情報も、図40及び41に例として示されるように、各曲げ線が選択され強調されるとき入力され及び/又はスクリーン上に表示される。図40及び41に示すように、ダイアログ或いは情報ボックスがスクリーン上に表示され、曲げオペレータが各曲げ線に関連する製造情報及び他のパラメータを選択し、入力し或いは修正することを可能とする。
【0238】
前記ダイアログ或いは情報ボックスは、曲げオペレータが曲げ線を強調し或いは選択するのを可能とする。ホット機能キー或いは高速スイッチキーが前記曲げシーケンス入力ウインドウに表示され、オペレータが工具立てを選択し或いは入力し且つNCデータを監視し且つ修正するのを可能とする。例えば曲げオペレータは、工具機能キーを選択し、前記曲げ順入力ウインドウから、工具立て情報を入力するための工具入力表示スクリーン或いは複数の表示スクリーンへ切替える。NC機能制御キー(例えばNC9EX)も設けられ、オペレータが実行されるべき曲げ操作に関連するNCデータを監視し及び/又は修正するのを可能とする。更に図40及び41に示されるように、曲げ線を定義し及び/又は修正すること及び関連する製造情報に関連して他の機能キー及び制御部が設けられている。例えばZOOM ALLキーが、前記2次元平面図画像をズームイン及びズームアウトするために設けられている。バックゲージキーは、前記バックゲージの位置を選択し或いは設定するために設けられている。グループ化及びグループ解除化制御キーは、一緒に曲げられる複数の曲げ線を可能とし或いは制御するために表示される。更に制御キー(例えばアマ曲げ)が特殊な曲げ操作を定義するために設けられている。他の機能キーも表示されオペレータが前記曲げ順を選択し、修正し及び/又は消去するために設けられている(例えばREMOVE CLEAR FWD、CLEAR ALL、OK、CANCELL)。この曲げ順入力ウインドウにより、曲げオペレータは、前記曲げ順及び種々の製造情報を効率的に監視し且つ修正することが可能となる。
【0239】
更にこの発明の他の側面によれば、前記パーツの断面図及び/又はパーツの曲げシミュレーションが、前記曲げ順における各曲げ工程についてスクリーン上に表示される(例えば図41を見よ)。前記断面図及び曲げシミュレーションは前記スクリーン上に選択的に表示され、或いは曲げオペレータにより各曲げ線が選択される時表示される。前記断面図及び曲げシミュレーションは、例えば上下曲げ工具(例えばパンチ及びダイ)又はバックゲージ位置・設定の表現を含み、それらは前記2次元平面図画像と共に同時にスクリーン上に表示され或いは異なるスクリーン表示上に別個に表示される。前記バックゲージ位置は前記パーツのトポロジーに基づいて自動的に決定され或いはオペレータにより設定され或いは修正される。前記曲げ線のための工具立て情報が入力されておらず或いは曲げオペレータにより設定される場合には、前記断面図及び/又は曲げシミュレーションはスクリーン上に表示されず又は前記中間パーツ形状の表現及び計算され或いは定義されたバックゲージ位置のみが表示される。前記曲げシミュレーションは、前記パーツの所望の反転、前記パーツの操作及び配向動作及び/又は各曲げ線でなされる前記パーツの曲げ加工の表示されるシミュレーションを含む。前記表示スクリーン上に前記パーツの2次元平面図画像と共に、曲げ工程の前のパーツの断面図及び曲げ工程がなされた後の前記パーツの断面図を同時に表示することもまた可能である(例えば図41を見よ)。これらの断面図は、スクリーンの右側に提供され前記曲げ順における各曲げ工程についての前記上下曲げ工具及びバックゲージの表現を含む。更にズーム制御或いは機能キー(ZOOM IN及びZOOM OUT)が表示され、オペレータが、前記曲げ前及び曲げ後断面図に関連してズームの比或いは向きを制御することを可能とする。日本公告公報平7−121418(丹羽等の名前で1995年12月15日に発行)及び日本公開公報平1−309728(長沢等の名前で1989年12月14日に発行)に開示されるそれと類似の技術及び手続きが前記パーツの断面図或いは曲げシミュレーションを表示するために使用される。前記文献の開示はここにその全体において参考により積極的に取り込まれる。
【0240】
この発明の1つの側面によれば、選択された曲げ線に関連して前記パーツの短い或いは小さいサイドを計算することにより前記曲げについて挿入方向を自動的に決定するためのソフトウエア或いはプログラム論理が提供される。この発明の特徴に基づいて、各曲げ線はそのパーツを2つのサイドに分断するために使用される。挿入方向は、より小さい或いは短い長さ(例えば前記曲げ線に直交する辺の寸法)を有する前記パーツのサイドに基づいて或いは、より小さい全体的面積を有するサイドに基づいて各曲げ線について決定される。もしオペレータが前記選択された挿入方向に満足しない場合には、図39(b)に図示されるように、オペレータは挿入方向を反転する。オペレータは挿入方向を、例えば曲げ線が強調されている際にマウス或いはキーパッドの選択ボタンをクリックすることにより変更し或いは反転する。挿入方向情報は、曲げ装置或いは機械装置で前記パーツを曲げ加工するために、前記曲げ線により定義されるフランジの挿入方向を指示するための矢印及び/又はテキストを含む。前記挿入方向情報は、曲げ線の上或いは近く(例えば図39(a)及び39(b)を見よ)或いは関連するフランジの端の上或いは近く(例えば図40を見よ)に表示される。更に前記挿入方向情報は、各曲げ線が選択された時に表示され或いはジョイスティック装置、マウス装置、或いはキーボード装置から受け取った入力に基づいて選択的に表示される。
【0241】
従って図形的ユーザインタフェースの使用を介して、曲げオペレータは、種々の中間形状及び最終パーツの形を、オペレータにより入力された選択された曲げ順に基づいて見ることができる。再び、オペレータはジョイスティックインタフェース、マウスインタフェース及び又はキーボードインタフェースのごとき適宜の入力装置を通して前記スクリーン上にデータを入力し選択することができる。曲げオペレータが提案された曲げ順に満足しない場合には、曲げオペレータは、ステップS232に一般的に示されるように曲げプランを最終化する前に曲げ順を編集する。この曲げ順の編集は種々のやり方及び方法において実行される。特にこの発明の1つの側面によれば、ドラッグ及びドロップ編集特性が提供され図42に示されるようにオペレータは単に、前記スクリーンの左側或いは右側に提供された中間的パーツ形状アイコン或いは表示の1つをつかみ且つそれを前記順番の所望の位置へドロップすることにより選択された曲げ順を編集する。その後、前記曲げ順に対する曲げオペレータの修正に基づいて前記スクリーン上の前記種々の中間パーツ形状が修正され、改定された曲げ順に基づく中間的曲げ段階を示す。更に前記曲げオペレータの前記曲げ順のドラッグ及びドロップ編集に基づいて、前記2次元平面図画像上の曲げ順番号が改定される。
【0242】
前記曲げ順が決定された後、オペレータは、ステップS236に示すように、格納された工具立てデータのライブラリから工具を選択することによりどのタイプの工具立てが使用されるべきであるかを決定する。関連する工具立て情報は、工場フロアの曲げオペレータに対して表示され、曲げオペレータが前記ライブラリから工具立てを選択するのを図形的に支援するために表示メニューが提供される。一旦特定の工具が前記ライブラリから選択されると、前記工具に関連するデータがスクリーン上に表示される。図43は、マニュアル工具選択のために前記曲げオペレータに対して図形的に表示される種々の表示メニュー及びデータテーブルの事例を図示する。図43の例では前記曲げオペレータが前記工具ライブラリから特定の工具を取り出すのを支援するために、連続的な表示メニュー或いはスクリーン表示が図形的に表示される。連続的に表示されるスクリーン表示は前記表示装置上に連続的に表示され(例えばオーバーラップする或いはカスケードする態様で)或いはそれは個々に表示され、そのスクリーンは次の引き続くスクリーン表示が表示される前にクリアされる。一旦特定の工具が選択されると、その工具に対する特定のデータがテーブルに提供され且つオペレータに表示される。工具ライブラリにおけるデータは、前記ソフトウエアの最初のセットアップ手続きにおいて、(例えばデータベース30の中に)予め定義され且つ可能されている。
【0243】
この発明のマニュアル工具選択特性はオペレータが工具タイプを選択し且つ各タイプにおいて工具の形状を選択することを可能とする。例えば、パンチ、ダイ、ダイホルダ、及びダイレールを含む種々の工具タイプが選択される。各タイプは多数の形状からなり、且つ各形状に対して異なったサイズ及び寸法の多数の工具が存在する。1つの工具を選択するために、ユーザは、図43に示されるような、表示される工具タイプアイコンから1つのアイコンを選択することにより1つの工具タイプをまず特定する。その後ユーザは選択された工具について利用できる異なる形状のメニューを提供される。工具形状を分析した後、ユーザは選択された工具について、表示された形状アイコンから1つの形状アイコンを選択することにより工具形状を選択する(例えば図43では、グースネック形状パンチが選択された)。最後にユーザは選択された工具形状について適当なサイズ及び寸法を選択する。図43に更に示されるように、選択された工具形状に対して利用可能な工具の異なるサイズ及び寸法を示すためのテーブルがユーザに対して表示される。このテーブルから1つの項目を選択することにより、選択された工具がアイコンとして表示され一般的な工具タイプアイコンに置き変わり、且つ工具の選択を確認する。
【0244】
ステップS240で、曲げオペレータは次に図形インタフェースの支援により、プレスブレーキにおける種々の工具段階(工具ステージ)を設定する。図44は前記曲げプランにおいて使用される工具セットアップ(工具取り付け)の定義を容易にするために曲げオペレータに対して与えられる代表的工具セットアップウインドウを図示する。図44に例として示されるように、種々のパンチ、ダイ及びレールのデータが前記ツールセットアップウインドウに表示される。前記板金パーツのための工具及びダイの情報はオペレータにより入力される。ジョイスティックが曲げオペレータのステーションモジュールに提供され曲げオペレータが工具位置を指示し且つ利用可能な工具及びダイのリストから工具及びリストを選択することを可能とする。この工具セットアップウインドウにおいてスクリーンの左側は現在の工具セットアップの断面形状を表し、スクリーンの右側はプレスブレーキにおける現在のセットアップの位置を表示する。現在のセットアップの位置は図44に示されるように強調され或いは影が付けられる。
【0245】
最後にオペレータが曲げ順に満足すると前記工具立て及び曲げシーケンスを含む曲げプラン情報が、図37におけるステップS242に一般的に示されるように、前記データベース30の中に前記曲げモデルと共に保存される。前記曲げ順の実際のテストが、前記曲げオペレータにより選択された曲げ順を確認するためにプレスブレーキにより行なわれる。もし必要なら、前記工具立ての定義或いは曲げ順に対する更なる修正が、前記ステーションモジュールにおけるオペレータ或いはデザイナーにより実行される。
【0246】
この発明の種々の他の特徴は、前記曲げプランの生成における前記曲げオペレータを支援するために設けられる。例えばこの発明の他の側面によれば、工具立てエキスパートが設けられ、前記曲げオペレータに対して前記曲げモデルに格納されたパーツ形状及び他の情報に基づいて、工具立て及び曲げ順の示唆を自動的に与える。前記工具立てエキスパートからの示唆は当該示唆の分析の後、曲げオペレータにより改定される。更に、より複雑な工具立てエキスパートシステムが提供され、前記曲げファイルにおける前記パーツの形状、及び潜在的な衝突及び干渉をチェックするための工具の形状分析に基づいて更に複雑な操作について工具立て示唆及び曲げ順示唆を行なう。そのようなエキスパートシステムは手動或いはロボットにより支援された曲げ機械装置により使用され実行される。限定しない例として、この発明はデービッドAボーン等の名前による「板金曲げプランを生成し且つ実行するための知的システム」と題される米国特許出願第08−386.369、及びデービッドAボーン等の名前による「ロボットウインドウの計画/制御の方法」と題される米国特許出願第08−338.115号に開示される特徴及び教示により実行される。これらの開示はここに全体として参照により積極的に取り込まれる。上記したように図形的ユーザインタフェース或いは種々の機能は、板金パーツのための曲げプランを生成する際に曲げオペレータを支援するために設けられる。この発明の他の側面によれば、追加の特徴が更に設けられ、前記パーツの設計及び製造において支援を行なう。以下に更に十分に説明するように、音声的或いは視覚的情報の格納のごとき種々のマルチメディア機能が本発明において実行され前記曲げプランを生成し或いは曲げ順を実行する際に曲げオペレータに対して追加の支援を行なう。更に、中間の曲げ段階の各々において前記工具及びパーツの間の潜在的干渉及び衝突を自動的にチェックする衝突チェック機能が提供される。この衝突チェック機能は、工具形状及び、パーツにおける間隔の面倒で時間のかかるマニュアルチェックに置き変わるために提供される。前記マニュアルチェックは曲げプランを生成する際曲げオペレータにより通常行なわれる。これらの機能及びその他のものは添付する図面を参照して今から説明される。
【0247】
この発明の1つの側面によれば、前記曲げモデルデータと共に音声及び映像情報を格納するための方法が設けられる。種々の音声及び映像情報は、工場フロアにおいて記録され、例えば板金パーツの操作及び曲げ加工に関連する特殊な指令を提供する。この目的のためCCDカメラ又はディジタルカメラが音声マイクロフォンと共に種々の場所10,12,14,…20のステーションモジュールの各々に設けられる。他の装置、例えばオーディオマイクロフォンを有するビデオカメラがオペレータ或いはユーザが音声或いは映像の情報を記録することを可能とするために前記ステーションモジュールに設けられる。前記種々の記録装置は工場フロアにおけるステーションモジュールコンピュータに接続される。限定しない事例としてインテルのPROSHARE個人会議CCDカメラ(インテル株式会社から入手可能)が音声及び映像情報を記録するために使用される。他の商業的に入手可能なCCDカメラ或いはディジタルカメラもそのような情報を記録するために使用される。
【0248】
前記曲げモデルデータと共に格納された種々の音声及び映像情報は種々の方法及び手続きにより、ユーザによりアクセスされ且つ読み出される。例えば格納された音声及び映像情報を再生するために、前記ステーションモジュールによりメニューオプションが表示される。更に、この発明の好適な実施例によれば、オペレータは、観察ウインドウに表示されるアイコンを選択し且つ生成することにより、格納されている音声及び映像情報を種々の表示スクリーン及びパーツの図に付随させる能力を有する。この機能は、ソフトウエア及びオブジェクト指向プログラム技術により実行される。これによりアイコンオブジェクトは曲げモデルデータ構造の中に生成され且つ格納される。このアイコンオブジェクトは、ある種の条件(例えばマウスのダブルクリック或いはジョイスティック或いは他の入力手段の使用による選択の指示によるオペレータによるアイコンの選択)に基づいてメモリから付随された音声及び映像情報を読み出すための手続きを含む。この発明のアイコンの特徴によりオペレータは異なる音声及び映像メッセージ或いは情報を前記板金パーツの異なる部分及び任意の表示に関連させる。このアイコンを前記パーツの表現に組み込むことにより、前記アイコンは、スクリーン上で画面が変わるにつれて前記パーツの2次元及び/又は3次元モデルの表示と共にズームし、回転し並進運動するように構成される。
【0249】
図45は前記パーツの3次元ソリッドモデルに張り付けられたアイコンの使用を介して音声及び映像情報を添付する事例を図示する。ユーザが前記音声及び映像情報を記録した後、オペレータが前記3次元モデルウインドウの任意の位置にアイコンを張り付ける。前記アイコンがオペレータ或いはユーザにより次に選択される時、格納された音声及び映像情報は再生され、前記ウインドウに表示され、そのアイコンが配置された前記パーツのある部分或いは領域に関する特殊な指令又はメッセージを提供する。他の情報、例えば前記曲げ運動のシミュレーション或いは記録は前記パーツの種々の曲げ線の近傍にアイコンを置くことにより前記パーツに関連される。前記曲げ運動に関連する映像情報は次に前記アイコンが選択される時ユーザに対して再生される。
【0250】
オペレータ或いはユーザは、音声及び映像情報を記録し、或いは単に1つの音声メッセージ或いは静止或いは運動映像信号を記録し、それらはユーザに対して選択的に再生される。前記ウインドウ表示に対して付着されたアイコンは格納された情報のタイプを図形的に指示する(例えば、音声情報が格納されていることを示しているためにマイクロフォンのアイコンが表示され又は映像情報が格納されていることを示すために表示モニタのアイコンが表示される)。特殊なアイコンは、そのアイコンに音声及び映像情報が関連されていることを示すために設けられる(例えば「A/V」の記号或いはマイクロフォンを含むビデオカメラのアイコン)。アイコンの一覧が設けられ且つ表示され、ユーザが、前記スクリーン表示或いは画像に対して音声及び或いは映像情報を添付する際に種々のアイコンから選択することを可能とする。
【0251】
図46は格納された音声及び映像情報を読み出すためのアイコンを組み込んだ表示ウインドウの他の事例を図示する。図46に表示された表示ウインドウは、図42を参照して上で説明したそれのごとき、工具セットアップスクリーン画像に関連する。図46の例では、音声情報が格納され、マイクロフォンのアイコンにより読み出される。そして別個の映像情報が格納され、前記表示ウインドウに対してビデオアイコンを張り付けることにより読み出される。前記音声及び映像情報は工具セットアップ或いは操作に関連する特殊な指令或いは情報に関連する。更に現在活性化されているウインドウ表示のタイプに関係なく、オペレータは、異なる音声及び映像情報を後に読み出すために、前記ウインドウ表示における種々の領域に必要なだけ多数のアイコンを張り付けることができる。
【0252】
この発明の他の側面によれば、画像編集ウインドウ特性が提供され、オペレータが格納された画像を選択しそれらを異なるスクリーンへ適用するのを容易にする。前記画像編集ウインドウ特性はウインドウに基づくアプリケーションとして提供され、それは例えばサーバモジュール32或いは製造設備を通して設けられたステーションモジュールのいずれかにおいてアクセスされる。図47は、この発明の教示により実行される画像編集(イメージ編集)ウインドウの例を図示する。前記イメージ編集ウインドウに表示される画像はディジタルカメラ或いはCADコーダによる画像写真を含む。前記スクリーンに表示される画像はオペレータにより(例えばマウス或いは他の適当なデータ入力手段により)選択的に選ばれ、他のスクリーンにコピーされ、それらはパーツの特定のモデルの図に関連させられる。オペレータは次にその画像或いはアイコンを前記モデルのウインドウ(例えば図46に関連して上で示したそれのごとき前記パーツの3次元ソリッドモデルウインドウ)へ張り付ける。図45、46及び47の画像は実際のスクリーン画像の写真再生である。実際の画像イメージは、使用されるカメラ或いはスクリーンの解像度に応じてそれ自体更に明瞭である。前記画像は例えば、曲げ操作に関連する特殊な操作或いは他の指令を議論し或いは図示する曲げオペレータの静止或いは運動映像イメージを含み、或いは板金曲げ操作の映像イメージである。換言するば、有用であると思われる実際の画像が取られ後に表示される。従って図45−47に示される実際の画像は例示的な目的のためのみのものである。図48及び49を参照するに、この発明の衝突チェック機能の例が設けてある。この発明の1つの側面によれば、衝突チェック機能が設けられ、ユーザは前記パーツ及びパンチ工具の間の潜在的な衝突を、図形的ユーザインタフェースの使用によりチェックすることを可能とする。前記衝突チェック機能はウインドウズに基づくアプリケーションであり、前記製造設備における任意のステーションモジュール或いは場所でアクセスされる。この発明の自動的衝突チェック機能は、前記曲げプランを生成する際に通常行なわれている伝統的なそして面倒なマニュアルの形状チェックに変わり曲げオペレータにより使用される。
【0253】
伝統的には、板金パーツの曲げプランを生成する際、曲げオペレータはまず前記パーツの曲げ順を決定する。前記曲げ順は前記板金パーツが製造の間に曲げられる順番或いは態様を決定する。その曲げ順が決定された後、曲げオペレータはその曲げ操作の各々を実行するために使用される工具を選択し定義する。この過程で、選択された前記工具の形状及び前記パーツの中間的形状が、前記曲げ工程の各々を実行する際に前記工具とパーツとの間の干渉あるいは衝突が存在しないことを確実にするために解析される。衝突或いは干渉が検出される場合には、選択された工具のタイプ(或いは必要に応じて曲げ順)は、前記工具と板金パーツとの間の干渉或いは衝突を生ずることなく曲げ操作が実行されるように修正されなければならない。
【0254】
潜在的な衝突或いは干渉を検出する際に、前記工具の形状と板金要素の曲げられた部分或いは形状との間のクリアランスを分析するために、曲げオペレータは伝統的にマニュアルの方法に頼っていた。典型的には、曲げオペレータにより工具形状のモデルが構成され使用されている。工具形状モデルは、板金の種々の中間的形状の工学的或いは技術的図面(前記工具形状モデルと同じスケールの寸法を有する)に対してマニュアルで合わせられ或いはその上に置かれる。この工具形状モデルを前記パーツの図面に対して適合させ及び合わせることにより前記曲げオペレータは、曲げ工程の各々において工具とパーツとの間に十分な空間或いはクリアランスがあるかどうかを決定することができる。しかしながらこの工程は面倒で且つ時間を浪費する傾向がある。
【0255】
この発明は自動的干渉チェック機能を設けることにより、そのような伝統的な方法の不利益を克服することである。この発明の干渉チェック機能は、図形的ユーザインタフェースを介して実行され、曲げオペレータが所定の曲げ順における各中間的工程において衝突をチェックするのを可能とする。図48及び49は図形的ユーザインタフェースを介して実行される衝突チェック機能の例を図示する。活性化される時、前記衝突チェック機能は前記曲げ順における前記パーツの各中間的形状とその順番に対して定義されるパンチ工具或いは複数の工具との間の衝突を自動的にチェックする。前記中間形状はスクリーンに表示され(例えば図48及び49を見よ)、衝突が発見されると、当該衝突が検出される工程がスクリーン上に強調される。更にテキストのごとき他の表示示唆が検出された衝突の数を指示するために提供される。図48及び49の例では、前記衝突情報は表示ウインドウの右上領域に提供される。更に、前記衝突がチェックされたパンチ工具或いは複数の工具のタイプは表示ウインドウの左上領域に表示され或いは指示される。
【0256】
衝突が、オペレータにより選択されたパンチ工具について検出される時、衝突が検出される中間的形状或いは段階がスクリーン上に強調される。この場合、オペレータはその特定の曲げ段階について他のパンチ工具を選択することもでき、前記パンチ工具の第2の選択について衝突が起きるか否か決定するために前記衝突チェック機能が再び実行される。オペレータは、各曲げについてパンチ工具を選択し、前記衝突チェック機能により衝突をチェックすることができる。ドラッグ及びドロップ編集が、中間的曲げ形状をドラッグし、それを前記提案された曲げ順内の所望の位置へドロップすることにより、前記ウインドウ表示中に表示された曲げ順をオペレータが変更することを可能とするように設けられてもよい。前記曲げ順は図44を参照して上に記載したそれと同様の対応で、オペレータによりなされた前記ドラッグ及びドロップ編集に基づいて修正される。
【0257】
この発明の衝突チェック機能を実行するために種々の手続き及び操作が使用される。例えば潜在的な衝突を検出するために、選択された工具の幾何形状と中間的形状におけるパーツの幾何形状とがアクセスされる。各中間工程における前記パーツに関連する幾何形状データは前記曲げ順及びパーツ寸法及びトポロジーデータに基づいて生成される。前記パーツの各フランジは、前記曲げ順における各中間段階における前記パーツを表示するために、曲げデータ(例えば曲げ角度、曲げ線位置、縮小量等)に応じて折り曲げられる。上記折り曲げ工程及びこの発明の縮小量補償特性は各中間段階での前記パーツに対する幾何形状データを生成する際に適用される。この工具及びパーツの幾何形状により、前記曲げ段階の各々において前記工具の先端をパーツの曲げ線へ置くことにより、前記工具及びパーツが相互に配向される。衝突は、前記幾何学的データ及び前記工具とパーツとの境界を分析し、前記工具及びパーツにおいて共通な点或いは重なり合う点が存在するか否かを決定することにより検出される。衝突は、特定の曲げ工程で検出される時、その工程は、ユーザに対して衝突の検出を示すためにスクリーン上で強調される。衝突を検出するために使用される工具データは、ユーザによりなされる工具選択に基づいて、工具形状ライブラリから積極的に取り出される。任意の中間曲げ工程での衝突の再計算は異なる工具形状或いは曲げ順の修正に基づいて行なわれる。そのような機能を設け、ここに記載されるごとき、図形的ユーザインタファースを用いてそのような情報を表示することにより、衝突の可能性は、曲げオペレータにより、より容易に決定され且つ修正される。
【0258】
上記したように、ジョイスティック或いはマウス装置は、板金パーツの表示されるモデルを観察する際、ユーザが選択的に種々の観察機能(例えばズーム、パン、回転等)を活性化し及び制御することを可能とするために、前記製造設備を通して前記ステーションモジュールの各々及びそれらの場所に設けられる。前記ジョイスティック装置は多重の軸を有するジョイスティックで、選択或いは制御ボタンを有する。前記ジョイスティックはマイクロソフト・サイドワインダ・ジョイスティックを含む種々の商業的に入手可能なジョイスティック装置を介して実行され、各ステーションモジュール及び/又は当該設備の他の位置のコンピュータのゲームポートに差し込まれる。前記マウスはまたウンドウズ95或いはウインドウズNTのごとき任意の商業的に入手可能なマウスをサポートするソフトウエア及び、各設備位置におけるコンピュータのゲームポート或いはマウスポートに差し込まれる任意の商業的に入手可能なマウス装置により実行される。
【0259】
限定しない事例として図50−55は、ジョイスティック装置或いはマウス装置を用いて、3次元幾何学的形状を操作し且つ前記パーツを表示するためのシステムの種々の側面を図示する。この発明の3次元ナビゲーションシステムは、ユーザが回転、ズーミング及びパンニングのごとき種々の観察機能を制御することを可能とする。この発明の1つの側面によれば、システムはまた3次元モデルを観察する際に、現在のズーム画像に基づいて計算される動力学的回転軸を用いる。この側面によれば、回転の中心は現在の図及びズーム比或いは係数に基づいて動力学的に変化され且つ計算され、従って前記パーツのズームされた領域は前記パーツが例えば高いズーム比或いは係数において回転される時、前記スクリーンから消えることがない。
【0260】
この発明の1つの側面によれば、3次元操作及びナビゲーションシステムが前記設備のステーションモジュール及び/又はサーバモジュールに提供される。3次元ナビゲーションシステムの工程及び操作は、ソフトウエア或いはプログラムされた論理を介して且つ広い範囲のプログラム言語及び教示の1つを用いて実行される。例えば前記システムはC++のごとき高レベルのプログラム言語を用いて且つオブジェクト指向プログラム技術を用いて実行される。更に限定しない例として、VISUAL C++が使用される。それはウィンドウズに基づくアプリケーションのためにマイクロソフト株式会社により提供されるC++プログラム言語の1つのバージョンである。前記観察機能(例えばズーム、回転、パン等)は上記した本発明の曲げモデルビューアの観察クラスの要素機能として実行される(例えば図27及び上記関連の開示を見よ)。前記現在ズーム係数及びパーツの位置(例えば3次元空間におけるパーツの位置)に関する情報は、また、前記動力学的回転軸を計算し且つ所望の観察機能を提供するために前記曲げモデルビューアからアクセスされる。
【0261】
種々のハードウエア成分及びインタフェースが、本発明の3次元ナビゲーションシステムを実行するために提供される。例えばシステムを実行するために使用されるソフトウエアが前記ステーションモジュール及びサーバモジュールのコンピュータ或いはパーソナルコンピュータに設けて有り或いは存在する。上で議論したように、前記コンピュータ或いはパーソナルコンピュータは、板金パーツの3次元表示をユーザに対して表示するために、高解像度モニタのごとき図形カード及び表示スクリーン或いはターミナルを含む。前記コンピュータ或いはパーソナルコンピュータはまた、前記マウス或いはジョイスティック装置と接続し及びインタフェースするためのマウス或いはゲームポートアダプタを含む。商業的に入手可能なソフトウエアも設けられており、ユーザにより操作されるマウス或いはジョイスティック装置からマウス或いはゲームアダプタカードにより受信される指令信号を解釈する。
【0262】
図50a及び50bは、例えば単純な3次元箱形状パーツを回転するために多重軸ジョイスティック112により行われる回転機能の例を図示する。上に述べたように、ジョイスティックは設備を通して設けられているステーションモジュール及び/又はサーバモジュールに設けられているコンピュータ或いは装置に設けられ且つ接続されている。図50a及び50bに示すように、前記パーツの回転は、前記ジョイスティック112を前後に且つ左右に移動することにより行なわれる。前記回転軸の方向或いは向きは前記ジョイスティック112(或いはマウス)の移動に基づいて設定される。例えば前記ジョイスティック112を前後に移動させることは、パーツを前記X座標軸に沿って定義される回転軸の周りに時計方向或いは反時計方向に回転させることをもたらす(例えば図50aを見よ)。更に前記ジョイスティック112を左右に動かすことは、前記パーツを前記Y座標軸に沿って定義される回転軸を中心として時計方向或いは反時計方向に回転させることをもたらす(例えば図50bを見よ)。
【0263】
現在の図のズーム比或いは係数が低く、パーツの全体表示がスクリーン上に提供される時、前記回転軸は前記パーツの幾何学的中心或いは図芯を通るように定義される。上記したように、前記ズーム係数及びスクリーン上のパーツの観察可能性は、本発明の曲げモデルビューアにより提供される観察可能性機能に基づいて決定される。スクリーン上にパーツ全体が表示されると判断される時(図50a及び50bにおけるそれのように)、回転軸を定義しそしてその回転軸を前記パーツの幾何学中心へ設定するために座標幾何技術が用いられる。前記パーツの回転は、次に、前記ジョイスティック装置のユーザにより定義された移動に基づき、且つこの発明の曲げモデルビューアの回転要素観察機能を介して実行される。しかし仮に前記オブジェクトの一部のみが画面に表示され、前記パーツの幾つかの部分は見えない場合(例えば高いズーム係数或いは比率が選択された時)、前記回転軸は、前記パーツの幾何学中心或いは図芯に維持されるべきではない。それはそのようにすることは、回転中に前記パーツのズーム化された部分がスクリーンから消えるからである。実際この発明によれば、ズーム比が増大される時、回転軸は動力学的に再計算され、前記スクリーンのセンターにおける観察点(或いはカメラ視野)に最も近い点の座標を通る。前記ズーム係数の変化に基づいて、前記回転軸を動力学的に再計算することにより、前記パーツは、前記パーツの観察可能な部分が回転の間に画面からはみ出すことにならない軸を中心として回転される。
【0264】
前記3次元モデルのズーミング及びパンニングを行なうために、前記ジョイスティック或いはマウス装置と別個に或いはそれと共に設けられたキーパッドに追加の制御ボタンが設けられる。例えばズームボタン114を押すと共に、ジョイスティック112を前後に移動することにより、図51に示すように、所定の割合で前記パーツはズームインまたはズームアウトされる。上記したように、前記回転軸は各ズームウィンドウの中で再計算され、回転がなされる時、ユーザが前記パーツのズーム化された部分を観察することができるようにする。更に、3次元形状のパンニングは、図52に示すように、パンボタン116を押圧し或いは活性化し且つジョイスティック112を移動することにより、ユーザにより制御される。前記ズームボタン114の場合と同様に、パンボタン116は前記設備の種々の位置の各々における前記ジョイスティックまたはマウス装置と別個に或いはそれらと一緒に設けられたディジタル入力パッドの上に設けてある。
【0265】
この発明の代表的な実施例に応じて、前記3次元ナビゲーション及び操作を実行するために設けられた種々の工程及び操作が図53−55を参照して以下に記載される。上に示したように、前記3次元ナビゲーションシステムの必要な工程及び操作はソフトウエア或いはプログラムロジック及びハードウエア成分及びインタフェースの組み合わせを介して実行される。ジョイスティック或いはマウス装置のごときユーザにより制御される装置からの入力信号は所望の表示されたパーツの運動及び再配向の量を決めるように解釈される。この発明によれば、表示されたパーツの回転軸は、回転中にパーツのズーム化された領域が画面から消えるのを防止するため、現在の画面及びズーム係数に基づいて動力学的に計算される。
【0266】
表示されたパーツの現在の画面を更新する際に、図53のステップS301に一般的に示されるように、前記ジョイスティック或いはマウス装置の操作に基づいてユーザからの信号が受信される。ユーザにより前記ジョイスティック或いはマウス装置の特定の方向の運動及び/又は特殊な制御ボタンの活性化との組み合わせが、所定の観察機能(例えば回転、ズーム、パン等)及び表示されたパーツの所定の方向(例えば時計回り或いは反時計回り、ズームイン又はズームアウト、右又は左等)の運動を、図50−52に例えば示されるように、引き起こす。受信された信号は、それらがジョイスティックからであるかマウス装置であるかを問わず、カーソルの移動に写像され、ユーザにより所望されるスクリーン上の移動量を決定する。ユーザが前記観察機能モードのうちの1つに存在しない場合(例えばユーザがスクリーン上の情報を選択しているか或いはダイアログボックス或いはウィンドウ内の情報を観察している場合)、前記受信した信号の写像は要求されない。
【0267】
当業者により理解されるように、通常のジョイスティック或いはマウス装置から受信される信号はスクリーン空間のそれとは異なる座標或いは参照システムに基づいており、従ってそれらは前記スクリーン上のカーソル移動に関する意味のある情報を提供するために翻訳されなければならない。従って前記ユーザからの入力信号を受け取った後、ステップS303に示されるように、回転軸の計算及び表示されたパーツの現在の図を更新する前に受信された信号はカーソル移動に写像される。
【0268】
ユーザにより制御される装置からの入力信号をスクリーン空間上のカーソル運動に翻訳及び写像するために異なる方法及び工程が使用される。伝統的には、マウス装置の移動は、商業的に入手可能なソフトウエアによりカーソル移動へ翻訳され且つ写像されていた。例えばウィンドウズ95及びウィンドウズNTは、マウス移動をカーソル移動へ翻訳するためのソフトウエアルーチンを含む。従って、マウス装置の移動は、そのような商業的に入手可能なソフトウエアによりカーソル移動に写像される。しかしながらユーザにジョイスティックインタフェースが与えられている場合、有用な情報を提供するには、前記ジョイスティック運動もカーソル運動へ翻訳され且つ写像されなければならない。前記ジョイスティック仮想空間におけるジョイスティックの運動をスクリーン空間におけるカーソル運動へ写像するために種々の方法及び技術が使用される。例えば、ジョイスティックの移動信号は、最終的にカーソル運動へ写像される前に、まずマウス運動へ加工され且つ翻訳される。或いは、前記ジョイスティック仮想空間のサイズに対するスクリーン空間のサイズの比率の関数として、前記ジョイスティック信号は直接カーソル運動へ写像される。
【0269】
図54は、この発明の1つの側面に基づく、ジョイスティック運動のスクリーン空間内でのカーソル運動への写像の例を図示する。上に示したように、ジョイスティック装置は自身の仮想的座標システム或いは空間218を含む。前記ジョイスティック仮想空間218は、前記ジョイスティックが中心或いは中立位置 (即ちジョイスティックが移動しない位置)に存在する位置に対応する原点J1を含む。前記ジョイスティックが新しい位置(例えば図54に示されるように現在の位置J2)へ移動する時、前記ジョイスティック装置は前記ジョイスティックの仮想空間内での新しい或いは現在の位置を示す信号を生成する。前記ジョイスティック仮想空間218は、しばしばスクリーン空間212よりも大きい(画素の意味で)ので、前記ジョイスティックの仮想座標及び移動は、所望のカーソル移動従ってスクリーン上でのパーツの移動を決定するためにスクリーン座標へ翻訳されなければならない。
【0270】
前記ジョイスティックの仮想座標移動をスクリーン座標移動へ写像し且つ翻訳するために種々の方法及び工程が使用される。例えば、前記ジョイスティック仮想空間サイズに対するスクリーン空間サイズの比率に基づいて、ジョイスティック運動はスクリーンカーソル運動へ写像される。より詳細には、観察機能モード(例えばズーム、回転、パン等)が活性化され、ジョイスティック装置がユーザにより操作された時、前回の点C1から現在の点C2へのカーソルの実際の移動は次の式で決定される。
【0271】
現在の点=前回の点+(スケール係数x V)
ここに「現在の点」はカーソルの現在の点C2であり、「前回の点」は前記カーソルの前回の点C1であり、「スケール係数」はジョイスティック仮想空間サイズに対するスクリーンサイズの比であり(いずれも画素において)、「V」はジョイスティック原点J1からジョイスティック現在位置J2へのジョイスティックの運動及び方向を表すベクトルである。従ってジョイスティック運動をカーソル運動へ写像するために、ジョイスティック装置がユーザにより操作される時ジョイスティック装置から受け取られる信号に基づいて、前記原点J1から現在位置J2へのジョイスティックの方向及び運動を示すベクトル「V」が最初に計算される。このベクトル「V」が計算された後、前記ジョイスティック運動は、前記方程式における前記ベクトル「V」量及び前記「スケール係数」量を用いてカーソル運動へ写像される。即ち、前記カーソルの新しい或いは現在の位置C2は、前記ベクトル「V」に前記ジョイスティック空間サイズに対するスクリーンサイズの比(即ちスケール係数)を掛け合わせ、次にこの計算の結果を以前のカーソル位置C1に足し合わせることにより計算される。
【0272】
前記スケール係数に応じて、前記スケール或いは運動の割合を所定の或いはユーザにより選択された調整係数だけ増大し又は減少することが必要となる。そのような場合には、そしてユーザの好みにより、前記スケールの割合を増大し又は減少するために、前記カーソルの現在位置を計算する時に、前記スケール係数に調整係数が掛けられる。例えば、前記ジョイスティック空間サイズに対するスクリーンサイズの割合がスケール係数1/64を与える場合、ジョイスティックの運動とスクリーン上の表示されたパーツの運動の割合との間の一層満足できる関係を与えるために、スケールの割合を増大するのが望ましい。限定的でない例として、スケール係数1/64について、前記表示されたパーツをズームし或いは回転する際調整係数3が用いられる。更にスケール係数1/64について、表示されたパーツのパンニングが行なわれる際には調整係数6が使用される。勿論、スケーリング(縮尺)の割合は、ユーザの特定の必要に基づいて修正され、前記調整係数は予め決定され或いはユーザが、前記スケールの割合を修正するための調整係数を調整或いは選択するためにオプションを与える。更に上に議論した事例において示したように、前記調整係数は複数の観察機能の各々について同じ量に設定されてもよいし、前記観察機能の各々について、同じ或いは異なる量に個別に設定されてもよい。
【0273】
受信された信号が適当に写像され翻訳された後、前記パーツの回転軸が、図53のステップS305に一般的に示されるように動力学的に計算される。前記パーツの現在の図に依存して、前記パーツが例えば高いズーム比率或いはファクターで回転される時、前記パーツのズーム化された領域がスクリーンから消えないように、前記回転軸は前記パーツの中心を通るか或いは他の点を通るか決定される。現在のズーム図に基づいて、前記パーツの回転軸を動力学的に再計算するために種々の方法及び工程が使用される。この発明の他の側面に応じて、図55は前記パーツの図がユーザにより修正された時常に前記回転軸を計算するために行なわれるプロセス及び工程の代表的論理フロー及び手順を図示する。
【0274】
図55に示されるように、現在のズーム係数或いは比率及びパーツの位置及び現在の図がステップS311及びS313で決定される。ユーザにより選択された表示パーツのズーム係数及び向きが、パーツ全体をスクリーン上で観察可能にする(即ち全体図)か、或いは前記パーツの一部のみをスクリーン上で観察可能にする(即ち部分図)。従って現在のズーム係数及びパーツの向きが、表示パーツの回転軸を適正に設定するために定められなければならない。前記パーツの現在の図を決定するために種々の方法及び工程が使用される。上に記載したように、観察可能性機能は、本発明の曲げモデルビューアを備え、表示される画像に対する変更が存在する場合には何時も、現在の図の向き及びズーム比率の状態を維持しそして更新する。前記曲げモデルビューアに対する機能コールがなされ、前記パーツのどの点或いは部分が現在観察可能であるかを決定する。スクリーン上に前記パーツの全てが表示されているかどうかは画像体積をパーツの境界基本線サイズと比較することにより決定される。
【0275】
ステップS315でパーツの全体図が現在スクリーン上で観察可能であると決定される場合には、ステップS317で前記回転軸は前記パーツの中心を通るように設定される。全体図が存在する時、前記パーツの中心を前記回転軸が通るように設定することは可能である。というのは全体が表示されたパーツはユーザにより回転される時スクリーン上で観察可能であるからである。スクリーン上で全てのパーツが観察可能である時、回転軸はパーツの幾何学中心或いは図芯を取るように定義される。従来の座標幾何学技術が、前記パーツの幾何学中心へ前記回転軸を定義し設定するために用いられる。更に前記回転軸の方向は、前記前回のカーソル位置から現在のカーソル位置へのベクトルに直交するベクトルとして定義されることもできる。
【0276】
ステップS315で、スクリーン上にパーツの部分図のみが現在観察可能であると判断される場合、ズーム化されたパーツがユーザにより回転される時表示されたパーツの一部がスクリーンから消えないようにするために、回転軸を計算するために、前記論理フローはステップS319−S325へ引き続く。上記したように、ユーザにより高いズーム係数が選択され前記パーツの一部のみがスクリーン上に表示される時、前記回転軸は、前記パーツの幾何学中心を通るように設定されてはならない。というのは、そのようにすることは、回転中に表示されたパーツのズーム化された部分(ズームアップされた部分)がスクリーンから消えるからである。パーツの表示された部分がスクリーンから見えなくなり或いは消えることを防止するために、スクリーンの中心における観察点(即ちカメラ)に最も近い点の座標を前記回転軸が通るようにされなければならない。そのような場合、回転軸の向きは前回のカーソル位置から今回のカーソル位置へのベクトルに直交するベクトルとして定義されても良い。
【0277】
従ってステップS319で、スクリーンの中心が決定され、カメラに最も近いスクリーンの中心におけるオブジェクト或いは前記パーツの部分が選択される。即ち、スクリーンのセンターに位置する表示パーツの部分及びカメラに最も近い或いはスクリーンのユーザの観察点に最も近い表示パーツの部分が取り出される。ステップS321で、前記カメラにおけるオブジェクトが存在すること(例えば前記スクリーンの中心に位置し且つ前記カメラに最も近い前記パーツのソリッド部分が存在すること)が決定される場合、ステップS325で前記回転軸は前記取り出された点を通るように設定される。上記したように、回転軸の方向は前回のカーソル位置から今回のカーソル位置へのベクトルに直交するベクトルとして定義されても良い。
【0278】
ステップS321でカメラにおけるオブジェクトが存在しない(例えば前記パーツは前記スクリーンの中心に位置し且つ前記カメラに最も近い穴或いは開口部を含む)と判断される場合、論理フローはステップS323へ引き続く。ステップS323で、前記回転軸は前記スクリーンの中心(例えば前記スクリーンの物理的中心のX及びY座標)を通り且つ前記パーツの幾何学中心に等しいZ座標(深さ)にあるように定義される。従って回転軸は前記X,Y,Z座標を通るように設定され、回転軸の向きは前回のカーソル位置から今回のカーソル位置へのベクトルに直交するベクトルとして定義されても良い。
【0279】
図53を再び参照するに、前記動力学的回転軸が決定された後、選択された観察機能(例えばズーム、回転、パン等)がステップS307で呼び出される。上記したように3次元操作システムの種々の観察機能は前記曲げモデルビューア観察クラスの要素機能として定義され実行される(例えば図27及び関連する上記開示を見よ)。そのような場合、ユーザにより選択された観察機能に基づいて、機能コールが前記曲げモデルビューアになされ、ステップS309で表示されたパーツの現在の図が更新される。前記パーツの現在の図及び向きは、ユーザにより選択された観察機能及びユーザにより操作された入力装置(マウス或いはジョイスティック装置)からの受信された写像カーソル運動に基づいて更新される。オープンGL或いはレンダウェアのごときグラフィックパッケージが、ユーザに提供される現在の図の更新を容易にするために提供される。図53及び55の代表的フローチャートにおいて行なわれる論理フロー及びプロセスはソフトウエアにより及び広い種類のプログラム言語及び技術を用いて実行される。例えばオブジェクト指向プログラム技術及びC++が前記プロセス或いは操作を実行するために使用される。この発明の3次元操作システムを実行するための代表的コードが付録Lに提供される。代表的コードはC++プログラム言語で書かれ、前記動力学的回転軸を計算するための種々の工程及び操作を含む。付録Lのコードにはコメントが提供され、そこに使用される論理及びアルゴリズムの解析を容易にする。
【0280】
上記3次元操作システムはジョイスティック装置及び制御ボタンの使用に関して記載されているが、このシステムは、マウス或いはキーボードを含む他の特定のタイプの入力手段により実行されることもできる。更に図51−52の上記実施例では、前記オブジェクトのスクリーンから無限への又はその反対のズーミング或いはパンニングを制限するために境界が定義される。というのは連続的なズーミング或いはパンニングはシステムを故障させ或いは破壊させるからである。
【0281】
更に、前記ジョイスティックインタフェースに関連して種々の他の機能が実行される。例えば、前記観察機能のいずれかにおける移動は、ジョイスティックがジョイスティックセンター位置から所定の範囲或いは距離を越えて移動されなければ実行されない。パーツの移動が許される前にそのようなジョイスティックの移動のしきい値を要求することは、前記中心点からの前記ジョイスティックの不注意な操作或いは押圧に基づいて、表示されたパーツの偶然の移動の発生を防止する。ユーザとのジョイスティックインタフェース及びシステム相互作用を改善するために他の機能がまた設けられる。例えばユーザによるジョイスティックの単一の操作に基づいて、前記観察機能(例えばズーム、回転、パン等)のいずれか1つにおける連続的或いは増加的(例えばステップごと)の移動が提供される。前記連続的或いは増加的移動の選択はまた単一の方向におけるジョイスティックの移動の量或いは時間に基づいて提供される。必要ならば表示されるパーツのスケール或いは移動の割合は、任意の方向におけるジョイスティックの運動の程度或いは時間に基づいて増加される。上記した速度調整係数の修正はまた、ユーザが前記スケールの比率を増加し或いは減少するために、マニュアルで調整係数に対する補正を入力することを可能とすることにより実行される。
【0282】
工場における部品の設計及び製造における支援を行なうために、本発明において種々の他の機能及び実施例が実行される。例えば各顧客のオーダに関する情報を追跡し且つアクセスするためにバーコードシステムが実行される。所定の参照番号或いは作業番号を有するバーコードが顧客により注文される各部品へ割り当てられる。このバーコードはデータベース30にアクセスし作業情報を読み取るために用いられる。ユタ、サンディにおけるゼブラテクノロジVTIからのバーコード・エニシング・バーコードSCAN CCDセンサのごときバーコードリーダ或いはスキャナが各場所に設けられ、ユーザが前記サーバモジュール或いはステーションモジュールにおいて所定の作業のためのバーコードをスキャンすることを可能にし、またデータベース30に格納されているそのパーツに付随する重要な設計及び製造情報をアクセスし読み出すことを可能にする。前記バーコードリーダは各ステーションモジュール及び/或いはサーバモジュールのコンピュータに差し込まれている。前記バーコードは任意の通常のバーコードフォーマットに基づいてフォーマット化されている。例えばUPS−A CODA BAR
CODE39 EAN/JAN−8或いはPLESSEYである。そして結果としてのバーコードナンバーはルックアップテーブルに基づいて翻訳され、前記データベースから作業情報を読み出すために、対応する作業参照番号及び/又はファイル名を検出する。或いは、前記作業番号は、工場全体にわたって存在する任意のステーションにおいて表示される指示へタイプ入力され或いはそこから選択され、瞬時にユーザの位置で作業情報を読み出し表示する。そのような情報を瞬時に読み出す能力は、コミュニケーションネットワーク26の使用及びデータベース30のごとき中央に位置するデータベースへの前記デザイン及び情報の格納により支援される。
【0283】
この発明の更に他の側面によれば、作業をスケジュールし割り当てるための装置及び方法が提案されるシステムに設けられる。従来、製造設備にわたる作業のスケジュール化及び割り当てはショップ或いは工場の工場長により行なわれた。工場長は、機械装置の現在のセットアップ及び利用可能性のみならず現在の仕事の状態を決定する。これらの情報を集め且つ分析した後、ショップ或いは工場の工場長はスケジュールを生成し且つ工場における種々の場所においてなされる作業について割り当てを分配する(例えば工場フロアに分配される作業スケジュールシートの形態で)。作業のスケジュール割り当ては、各顧客の作業がタイミングの良い形態で且つ所定の出荷日までに完了することを確実にするために行なわれる。作業のスケジュール化及び割り当ての従来の工程はしかし骨の折れるものであり、通常工場長によりマニュアルで行なわれていた。
【0284】
この発明の1つの側面によれば、ショップ或いは工場の工場長がその工場についての作業のスケジュールを立てることを支援するために、作業割り当て及びスケジュールシステムが設けられている。そのシステムはコミュニケーションネットワーク及びデータベース30に格納されている曲げモデル情報を利用し、自動的に必要な情報を集め、従って工場長はより容易に作業スケジュールを生成することができる。このシステムは、前記サーバモジュール或いは工場にわたって配置されているステーションモジュールにおいてソフトウエア又はプログラムロジックを介して実行される。スケジュールされるべき種々の作業を入力することにより、システムソフトウエアはデザイン及びパーツ情報を分析し所定の作業を行なうためにどの機械が最も適しているかを決定する。この目的のため、工場における機械の現在の状態及びセットアップが定義され、データベース30に格納され、作業スケジュールソフトウエアによりアクセスされる。種々の条件に基づいて、表示の形態で、特定の作業を実行するためにどの機械が利用可能であるか及びどの機械が他の仕事を実行することができないかを示唆する。この点について、特定の作業について機械の利用可能性をランク付けし且つ提案作業スケジュールを提供するテーブルが表示される。前記提案作業スケジュールは工場長により実行され或いは修正される。作業スケジュールを設定し且つ推薦するために使用される条件は広い種類の条件を含む。そしてそれは、工場における各マシンの現在のセットアップ、各作業について必要とされる曲げのタイプ及び工具、及び同じ時間枠或いは時間の間に実行されなければならない他のタイプの作業を含む。どの機械が特定の作業を実行できるかを決定するために、前記曲げ角度、フランジ長さ及び曲げのタイプを含む各パーツについての曲げモデルファイルからの情報が利用される。例えばデータベース30に格納されているテーブルは前記工場フロアにおけるパンチング及び曲げ機械の各々の現在のセットアップ及び能力についての重要な情報を含む。
【0285】
提案された作業スケジュールに基づいて、工場長は、工場の生産及び出力能力を最大限にするために、複数の作業を工場全体にわたる種々の場所へ割り当てる。最後の作業スケジュール或いは割り当ては電子的に入力されコミュニケーションネットワーク26を介して機械の各々へ送られる。
【0286】
LEDのごときパイロットランプが曲げ及び機械装置ワークステーションの各々に設けられ、そのステーションに作業が割り当てられ転送されたことを指示し且つ確認する。前記作業割り当て及びスケジュールは、工場内の任意の位置から瞬時にアクセス可能なサーバモジュールのファイルに格納される。上記機能に加えて、その他の機能が、この発明の教示に応じて実行される。例えば種々のステーションモジュール或いは位置にメニュースクリーンが設けられ且つ表示され、ユーザがこの発明の種々の表示及び機能モードを選択するのを容易にする。例えば図56に示されるそれのごときメインのメニュースクリーンが、前記ステーションモジュールが開始される際にユーザに対して提供される。このメインメニューウインドウ表示はステーションモジュールにより提供される利用可能なウインドウ表示及び観察モードの各々のアイコン画像を含む。このメインメニュースクリーンはメニューボタン(例えばF1キー)が選択されるとき何時でも現れる。ユーザは、強調されたブロックを所望のウインドウアイコンへ移動しそれを選択することによりそのウインドウを選択する。そのような操作は、キーボード、マウス或いはジョイスティックの使用を介して行なわれる。
【0287】
他のウインドウスクリーンもユーザに対して提供され且つ表示され作業情報の入力及び表示を容易にする。例えばパーツ情報ウインドウは、ユーザがパーツ情報を入力し或いは修正するのを可能にするために表示される。パーツ情報ウインドウ表示の例が図57に与えられる。このパーツ情報ウインドウは全ての関連するパーツ情報(例えばパーツ番号、材料タイプ、寸法等)を含み、板金パーツの2次元平面図及び等測投影法図を含む。曲げ線情報ウインドウ(例えば図58に示されるもの)は、ユーザが各曲げ線についての曲げ順及び縮小量を含む種々の曲げ線情報を監視することを可能とするために設けられる。前記曲げ線情報ウインドウはユーザが、各曲げについての曲げ線情報を入力し或いは修正するのを可能とし、板金パーツの2次元平面図及び等測投影図を含む。
【0288】
オペレータの曲げ順の分析を容易にするために、追加のウインドウ表示が提供される。例えば曲げ順ウインドウ表示及び曲げシミュレーションウインドウ表示が提供され、前記パーツの種々の曲げ段階を表示し、且つ曲げ操作中におけるパーツの向きをシミュレートする。図59に示されるような曲げ順ウインドウは前記メインメニュースクリーンから選択され曲げ順の各段階における前記パーツの(静止状態における)中間形状をユーザに対して表示する。曲げシミュレーションウインドウ(例えば図60を見よ)もユーザにより選択され、曲げ段階の静止情報(スクリーンの右側に提供されるパーツアイコンの形態で)及び、曲げ順における各段階で行なわれる位置付け及び曲げの動的シミュレーション(表示装置の中央において)を提供する。スクリーン上のパーツアイコンを間欠的に選択することにより、ユーザは選択されたパーツアイコンにより表現される段階における、曲げ加工中でのパーツの向きの動的シミュレーションを見ることができる。各曲げ順を動的にシミュレートするために、パーツは反転され、並進移動され、曲げ線の周りで曲げられ/回転される。
【0289】
図57−60の上記ウインドウ表示の各々は、図56のメインメニューウインドウ表示からユーザに対して選択され且つ表示される。更に、任意のステーションモジュールにおけるユーザは、メインメニューウインドウ表示において適宜のウインドウアイコンを選択し、この発明の観察モード(例えば2次元平面、ワイヤフレーム、ソリッド、正射図)に応じて表示されるパーツの2次元及び/又は3次元表示を得る。これは図28−31を参照して上で詳細に説明された。種々のメニューウインドウがまた例えばステーションモジュールに設けられ、この発明の特性及び機能の操作を容易にする。図61は2次元から3次元操作のために表示される代表的メニューを図示する。更に図62はこの発明の2次元クリーンアップ操作のための代表的メニュー構造を図示する。この発明はしかしこれらのメニュー配置に限定されるものではなく、他のメニュースクリーン及び/又は工具アイコンバーが設けられ、ユーザのシステムとの相互作用を容易にする。
【0290】
他の特性もまたこの発明において実行される。例えば、高いレベルの自動装置も提供され曲げプランの生成を容易にする。例えば曲げ及び工具立てエキスパートシステムが提供され、各作業についてのパーツの幾何形状及び形状に基づいて工具立てセットアップ及び曲げ順を生成し且つ提案する。それは例えば米国特許出願出願番号08/386.369及び08/338.115に開示されるようなものである。
【0291】
この発明は幾つかの代表的な実施例を参照して記載されたがここで用いられた用語は、限定の用語ではなく、記載及び説明の用語である。この発明の範囲及び精神及び種々の側面から逸脱することなく種々の変形がなされ得る。この発明はここで特定の手段、材料及び実施例を参照して記載されたが、発明はここに開示された特定のものに限定されるように意図されるものではない。むしろ発明は全ての機能的に等価な構造、方法及び使用に広がる。
【0292】
付録A
曲げモデルパーツからのフィーチャエンティティ抽出の例
.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[face_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 ) ; }
付録B
相似性指数特性の例。2つの部分のトポロジカルマトリクスを比較し、それらの最良の相似性指数を求める。相似性指数は、2つの部分のFENTマトリクストポロジカルマトリクス)の不一致FENTsの全てのペナルテイの和として与えられる。最良の相似性指数は最小値を持つものである。
【0293】
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);}// 新しい部分マトリクスと一致する既存の部分マトリクスからエントリのリストを抽出する。部分マトリクスのデイメンシヨンはトポロジカルマトリクスのデイメンシヨンより大きいか等しくなければならない。注意:一致リストの第一要素は初期化されてトポロジカルマトリクスの第一面との一致のため部分マトリクスの面番号を含まなければならない。 nmatchedが0より大きいときは、マッチリストの第一のnmatchedエントリは正の番号を含んで部分マトリクスの既に一致されたエントリを示さなければならない。//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) ;*(pcandidates+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);}////////////////////////////////////////////////////////////////// 1以上の面を固定するためのカウンターを更新する。////////////////////////////////////////////////////////////////////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) ;}////////////////////////////////////////////////////////////////////// この関数はカウンタを更新して固定面を開放する。解放された面は現在nface////fixed位置にある面である。//////////////////////////////////////////////////////////////////////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] ;}///////////////////////////////////////////////////////////////////////// この関数は所与のintfentの配列におけるFENTsの個数をカウントす//// る。/////////////////////////////////////////////////////////////////////////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) ;}////////////////////////////////////////////////////////////////////// この関数は特定の組のintfent配列におけるFENTsの個数をカウント//// する。//////////////////////////////////////////////////////////////////////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マトリクスにおけるFENTsの個数をカウントする。////注意: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 = pintfentmatrix + (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) ;}//////////////////////////////////////////////////////////////////// この関数は2つの最小可能不一致に対して最小ペナルテイを戻す。////////////////////////////////////////////////////////////////////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) ;}//////////////////////////////////////////////////////////////////// この関数は不一致対のFENTのペナルテイを戻す。//////////////////////////////////////////////////////////////////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 );}/////////////////////////////////////////////////////////////////////////////// この関数は2つのFENTCOUNTの最小可能不一致に対する最小ペナルテイを戻す。///////////////////////////////////////////////////////////////////////////////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) ;}///////////////////////////////////////////////////////////////////////////// この関数は2つのFENTCOUNTの最小可能不一致に対する最小ペネルテイを戻す。/////////////////////////////////////////////////////////////////////////////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);}///////////////////////////////////////////////////////////////////////// この関数は所与のfacenewとfaceoldのミスマッチに対する相似の指//// 数の増加を計算する。/////////////////////////////////////////////////////////////////////////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);}
付録C
// コメントを含むベンドライン検出の例。このモジュールはBM PART:: 自動ベンド( )の実施を含む。
【0294】
//* ********** ********** ********** *********** ********* これは、部分の設計と構成に供する主要な高レベルベンドモデル関数である。その目的は、(もし可能なら)部分が接続されるようになるように面間にベンドラインを形成することにある。 この関数は部分の形成を容易にすることにある。通常は、第三パーテイのCADプログラムの部分を描画する。ベンドモデルはCADシステムにわたる制御をもたず、我々の目的に対してこの描画は丁度一組のエッジである。従って、この図は部分の構造を検出するために解析されなければならない。その後、我々は部分の面とベンドラインを形成することが出来る。しかし、入力された図はしばしば曖昧であり、ベンドラインは一意には定義されない。その場合、我々は一連の発見的手法を用いてベンドラインを形成する。この発見的手法は、多くのものが可能のとき一つの出力を取り出すための優先基準を規定する。
この問題は多くの応用に対して共通なので、この関数はベンドモデルの一部である。更に、ベンドモデルにおいてこの関数を実施すると、CADシステムの一部でなければならない面検出ソフトウエアを簡単にする。この関数において、我々は、垂直な平面に一致するように左手側の規則に従って(これは平面の向きを規定する。)面のエッジが分類されると仮定する。基本的には、この関数は、全ての平面が、分離して見たとき、それ自身正しいと仮定する。しかし、この関数は、隣接する平面の向きがそれらの平面の間のベンドラインに関して正しいことを要求しない(後にそれを固定するベンドモデル関数が存在する。)。 この関数を用いて部分の3Dバージヨンおよび部分のフラットバージヨンの両者に対してベンドラインを生成することが出来る。しかし、部分はフラットまたは3Dバージヨンのいずれかを持つことが出来るが、両者を持つことは出来ない。換言すれば、3D体の全ての3Dバージヨンはゼロでなければならないか(その場合、我々はフラットバージヨンを持つ。)全てのフラットバージヨンがゼロでなければならないかのいずれかである。*//************ ********** ********** ********** ********** **********アルゴリズム/プロセス: アルゴリズムの目的は、部分のトポロジーグラフにおいてループを形成しないという拘束が与えられたとき、全体の部分が接続されるようになるように(すなわち、全ての面が全てベンドラインを介して接続され、周囲にスタンドアロン面が垂れ下がることを望まない)最小数のベンドラインを形成することにある(何故なら、我々は部分を出来るだけ変化させたくない)。 入力部分がいかなるベンドラインも含まないということは要求されない。AutoBendは既存のベンドラインを考慮し、部分に新しいベンドラインを付加したものである。トップレベルでは、このアルゴリズムは最大スパンツリーアルゴリズムの一バージヨンを行う。任意の時間点で、アルゴリズムは現在接続された要素と一組のフリンジ面(これらは接続された要素の部分である。)を有している。これらのフリンジ面は接続要素の外側の面との接点を有する。一回の過程の間に、接続要素の外側にある一つの新しい面が接続要素に付加される。フリンジ面に当接する接続要素の外側の面の間で、Autobendは最大のコンタクトを持つものを取り出す。 この最大のコンタクトを用いる発見的手法は、薄板製造において、通常、接触が大きければ大きい程より良好な結果が得られるという事実に基づいている。しかし、タイが存在するとき、すなわち、接続要素におけるフリンジ面と同じ最大コンタクトを持つ接続要素の外側に幾つかの面があるときは、我々は他の発見的手法を用いる。この発見的手法は部分の直径を最小にする面を取り出す。部分の直径は、部分のトポロジーグラフにおける任意の2つの面間の最大距離である。*********** ********** ********** ********** ********** *技術的注意:-この関数は、部分の厚みがゼロでないときは恐らく十分には作用しない。-この関数は、アルゴリズムにおける面l(主として、垂直な面l)に一致するベンドライン情報を生成する点に注目されたい。しかし、垂直な面2はこの情報と一致することは出来ないが、それは後に固定されなければならない。PART.HXX.のコメントを参照されたい。#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"/*この関数は、所定の2つの面の間の全てのコンタクトを計算する。コンタクト接触は、2つの面が互いに接触しているときに得られ(すなわち、ある非常に小さな距離公差内で)、それらを分離する線分は0より大きな長さを有する(すなわち、共通の線分は点ではなく、実際の線分である)。目的:与えられた2つの面の間の潜在的なベンドラインのを計算すること。仮定:-両面は、計算のために用いられる最新の非空3Dバージヨンを有する。-いずれかの面における全てのループは閉じられる。
要件:-両面は同じ面内になければならない。リターン:-コンタクトのリストこのリターンされたリストは構造を有する:ノード0:objは”コンタクトの個数”である。ノード2i-1:objは”コンタクトiの面l側のリストのヘッド”である。ノード2i:objはコンタクトiの面2側のリストのヘッド”であり、ただし、iは、〔1、”コンタクトの個数”〕内にある。各々のコンタクトは”閉じた”コンタクトであり、すなわちコンタクトにはギャップは存在しない点に注目されたい。コンタクトのいずれかの側の各々のリストは、リスト中のラインの順序がスイープ方向とは逆の(現在はXZYスイープ)ラインのリストである(実際にはラインに対するポインタ)。これはコンタクトのリストがどの様に見えるかを示すものである:コンタクトの#->リスト1.面1.ヘッド->リスト1.面2.ヘッド->...->リストi.面1.ヘッド->リストi面2.ヘッド.||||VVVV面1におけるライン1 面2におけるライン1 面1におけるライン1面2におけるライン1||||VVVV............||||VVVV面1におけるラインi面2におけるラインj面1におけるラインk面2におけるライン1この関数においては、kベンドのコリネアベンドラインは、k個の個別コンタクトと考えられる。注意:――――――――デフォールトにより、我々は両面における全てのラインをベンドラインに対する候補と考える。しかし、もしユーザが、ベンドラインが何かを既に知っている(あるいは実際には、ベンドラインエッジが何であるかを知っている)ときは、ユーザはこれらのラインの名前を用いて、この関数がそれらのラインのみを考えるように指示することが出来る。この関数は、面1または面2のいずれかが、他の面のidxに等しい名称を持つか否かをチェックする(面1および面2は個別にチェックされる。)。もし、イエスなら、これらのラインのみがその面の側のベンドラインに対する候補と考えられることになる。*/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 ;/*********** ********** ********** ********** ********** ********** ********** ********** **********ここで、我々は、これらの面がともかく接触出来るか否かの非常に迅速なチェックを行う。 ここで、我々は、面2のbループが接触するか(1点以上で)、面1の平面に交差するか否かをチェックする。 これは、これらの2つの面が明らかに接触出来ない時間を節約することになる。********** ********** ********** ********** ********** ********** ********** ********** ***********/// 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./* ここで、我々は、面2に関してbボックス1に対して同じものをチェックする。*/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 ;}}/*********** ********** ********** ********** ********** ********** ********** ********** **********X座標により、つぎにZ座標により、さらにYによりラインの配列を分類する。********** ********** ********** ********** ********** ********** ********** ********** ***********/{ // 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;}/*********** ********** ********** ********** 主ループ。2面を掃引する。 開放ラインのトラックを常に保持する(出発点を我々が見たライン、しかし終点は未だ見ていないライン-実際には、開始-そして-終了-点ではなくて、XZYオーダリングに対してより大きくかつより小さい端点)。 始めに、開放ラインの組は空である。 全ての繰り返しの間次のことを行う: -開放であったが、今は閉じられるべき全てのラインを除去する、 -現在のラインが開放ラインと重なるか否かをチェックする、 -このラインを開放ラインの組に加える。*/// 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_in_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 ;}/* この関数は2つの面の間のコンタクトのリストを掃引する (BMにより殆ど同様に生成される 全ての面から面の接点を計算する)そして全ての、ただし最大の接点を除去する。 基本的には、それは接点のリストを”濾過”し、最も長い接触部に属さない接触部を除去する。一般に、最も長い接触部は同時的なベンドラインのリストである点に注目されたい。かくして、接触部リストの基本構造は同じである。 例えば、リスト中の第一のノードは最も長いコンタクト中のコンタクトの数である。 この関数はまた最も長いコンタクトの長さに戻す。 この関数においては、全てのコンタクトが閉じられ、従ってコンタクト中のラインのリストにおいて、ラインの端点は次のラインの出発点に等しくなるという事実を利用している。 この方法で唯一のトリッキーな部分は、第一の、および最後のラインにおける重なり部分の長さを計算することにある。次に、リストの中間でラインの長さを付加する。
前の関数を参照されたい。*/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 ;}/*この関数は、サブルーチンとして静的なint BM create ベンドライン(...)によってのみ用いられる。 現在の大きな問題は、我々が幾つかのラインを削除しているということである。 この問題は、我々が同時ベンドを持つとき、他のコンタクトはなお我々が丁度削除したこれらのラインを参照していることが出来るということである。 我々は進んでそれをチェックしなければならず、もし真なら、有効な参照によりポインタを我々が変更し/削除したラインに置き換えなければならない。 すなわち、影響されたラインは左側の最初のそして最後のラインである。 潜在的には、それらに対する参照は11および13を参照して置き換えられる必要がある。*/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 ;}/* この関数は、入力として与えられたコンタクトリストに基づいて、2つの面間に簡単な(規則的な)ベンドラインを形成する。一端これがなされると、それはコンタクトリストを消去する。 この関数では、面のエッジは左手の規則に従って分類されると仮定する。
この関数は、もし全てがファインのときは、TRUEに戻す。 NB!ここでの問題点は、新しいベンドラインを形成したとき、何かを部分的に無効にすることではない。 それを完成するために、我々は、分離であるベンドopを形成し(ベンドライン無しに)(原文理解出来ず)、後にそれをベンドラインに付加する。 更に、我々は、ベンドラインが形成され、部分に付加された後にのみトポロジーを形成する。 この関数は、面1(主として、垂直な面1)に一致するベンドライン情報を形成する点に注目されたい。 ただし、垂直な面2はこの情報と不一致でもよいが、後に固定されなければならない。*/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() ;/* 先ず、ベンドラインと共にしなければならない全てのこと、ベンドラインを形成する、ベンドopを形成する、ベンドopパラメータを設定する、ベンドラインに対するシリンダを形成、設定する、ベンドライン、センタラインを設定するなどを行う。*/// 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./* 第二に、必要なら、幾つかのラインを破断し、全ての隣接ラインを1つの隣接ラインに結合する。更に、面1-ベンドラインと面2-ベンドラインの間の隣接情報を形成する。
*/// 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) ;}/* 最後に、センタラインを形成する。方向と長さが正しいことを確かにする。 p1とp2は面1に関して規定される点に注目されたい。 すなわち、p1->p2は面1の側のコンタクトに対する方向である。*/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 *//* 面(面1)を与えると、この構造はこの面と他の面の間のコンタクトについての情報を含む。 任意の2つの面に対して、これらの面の間にコンタクトが有るか否かを知る必要があり、もしイエスなら、何がその長さであるかを知る必要がある。このデータを処理する最も簡単な方法はそれを二次元配列として記憶することにより与えられる。しかし、これは多くのスペースを取り、その殆どは無駄に使われ、というのは、通常は、多くの面があるときは、それらの殆どはそれらの面の間で何らのコンタクトも持たないことによる。 代わりに、我々は全ての面に対してこの情報を構造のリストとして記憶することになる。我々は、2つの面の間のコンタクトの長さが0より大きいときにのみこの記録を(すなわち、構造)生成する。*/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 *face2 ;// 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 ;}/* この関数は2つの面の間で最良の(すなわち、最も長い)コンタクトを計算し、格納する。*/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 ;}/* これらの2つの関数は、ユーザがトポロジーグラフにおける2つの面の間の距離を設定し得ることを許容する。 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 ;}/* これは主要なAutobend関数である。その目的は部分に対するベンドラインを自動的に生成することにある。*/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./* 我々がスパンツリーを拡大出来るか否かをチェックする。 我々が接続要素を拡大することに戻るまでまでのこの点に対して、我々は単に面2を用いつつあり、すなわち、我々は面1を必要としていない。 唯一の場合は、我々が新しいベンドラインを生成するときであるが、我々はコンタクトリストから面idを抽出することが出来る。*/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/* ここで,我々は、この面(すなわち、面2)がそれに接続された他の任意の3D体を有するか否かをチェックする必要がある。 もし、イエスなら、我々は、面2に接続された全ての面を現在接続された要素に付加するために、これらの接続を追求する必要がある。*/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’ in the beginning of this for−loop.// note that the next function (add_face_to_connected_component(...)) will increment end_id.if (! add_face_to_connected_component(this, face2, &end_id, all_contacts, idx_to_face_mapping)) goto failure ;}// ok, the current connected component has no connections to the outside.// tryto expand the spanning tree.goto expand_spanning_tree ;done :ret_value =1 ;goto release_memory_and_return ;failure :ret_value = 0 ;release_memory_and_return :// free memory if necessaryfor (i = 0 ; i < number_of_faces ; i++) {delete_contact_info_list(all_contacts[i]) ;}if (all_contacts)delete [] all_contacts ;if (idx_to_face_mapping) delete [] idx_to_face_mapping ;if (heap) delete heap ;if (dist_btw_faces) delete [] dist_btw_faces ;return ret_value ;}
付録D
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 ON 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 記述: エンティティの色を変更する関数。 復帰値: =0:成功裏に完了; パラメータ:入力: 1 In drawing:図中で1:変更された色である図=================================================================*/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 記述: 取消関数のためのデータフラグを準備すること。 復帰値: =0:成功裏に完了;パラメータ: 入力: 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 記述: それは復帰エンティティの色である。 復帰値:=0:成功裏に完了; パラメータ: 入力: 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 記述: それは削除エンティティに対する関数である。復帰値: =0:成功裏に完了; パラメータ: 入力: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 記述: アラウトップ頂点フラグを変更し、アローセンタライン座標を設定する。 復帰値:=0:成功裏に完了; パラメータ: 入力: 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 記述: アローセンタラインを見出し、フラグをアローメンバに設定する。 復帰値: =0:アロー無し; =1:アロー パラメータ: 入力: 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 記述: 1つのサイドオープンエンティティを見出す。 復帰値: =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 記述: 開始および終了エンティティをチェックする 復帰値: =0: ノーアロー;= 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記述: エンティティグループに対する最小X値を求める。戻り値:= 0: 成功裏に完了し、エンティティ無し;パラメータ:入力: 1 Entities_list: チェックされるノードリスト出力:1 Entity: エンティティは最小のX値を含む。================================================================*/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: エンティティはループの最小X値を含む。================================================================*/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 );continue;}//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エンティティグループに対する最小X値を求める。int F2dCleanUpFindOutSideLoopエンティティグループに対する最小X値を求める。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 VELLUMCountPrompt++;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エンティティグループに対する最小X値を求める。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;}
付録E
ベンドモデルビユワ実施の例; CBendCADViewPartメンバ関数の実施およびメニュー駆動関数の実施を含む。
【0295】
//#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_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(); 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 = 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(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;}
付録F
コメント付きファイルを含むメインを自動寸法化するBMAPIの例/
*一般的注意:---------------***************---------------一般的注意:−自動寸法化パッケージはそのパートが既に更新されている(すなわちパートの3Dバージヨンが既に計算されている)と仮定する。そのパートの現在の3Dバージヨンを取り、それを用いる。−04/02/96付の自動寸法化は、単にパートの3Dバージヨンに対する寸法を生成する。−04/02/96付の自動寸法化は、パートが厚みを持って示されていると仮定する(すなわち、それは、我々が薄板の一側を示していないと仮定する。)。概要 :---------------***************---------------自動寸法は2種類の描画を行う:- 全てのベンドラインに対するフランジ長さ- 全てのベンドラインに対するベンドライン情報ベンドライン情報は、それが係わるベンドラインを指示する小さなinfo-box内に描かれれる。このinfo-boxを描画する際の唯一の問題点は、ベンドラインが可視であるか、どこにinfo-boxを描くか(すなわち、それが良好に見え、他の成分に干渉せず、例えば、他の事物と重ならないようにそれを描く画面上の場所)、如何にそれをベンドラインと関係付けるかということにある。この成分は比較的容易である。ベンドラインのフランジ長さは、ベンドラインとこのベンドラインの側部の隣接フランジとの間の最大外側距離により与えられる。ベンドラインは高々2つの隣接フランジを持つことが出来、従って両隣接フランジに対してフランジ長さを描かなければならないという点に注意されたい。実際、フランジ長さは、我々がディメンションポイントと呼ぶ点の間で(距離として)描かれる。ここには2種類のディメンションポイントがある。第一のものはベンドラインディメンションポイントである。フランジ長さはベンドラインと隣接フランジの間の(最大外側)距離なので、ベンドラインの側部のこれらのディメンションポイントはベンドラインディメンションポイントと呼ばれる。それらの位置は厳密にベンドラインにより定義される。1本のベンドラインは隣接フランジの各々に関して正確に2つのベンドラインディメンションポイントを持つことが出来る(少なくとも、 BendModel/BendCADの現在のバージヨンでは)という点に注意されたい。2つのベンドラインディメンションポイントはそれぞれベンドラインの2つの端部に対応する。更に、通常は、両隣接フランジに対するこれらのベンドラインディメンションポイントの対は一致する点に注意されたい。すなわち、隣接フランジAに対するンドラインディメンションポイント(Aに対して2つのベンドラインディメンションポイントがある)と他の隣接フランジBに対するベンドラインディメンションポイントと同じものがある。すなわち、それらは特に同一ではないが、同じ値を持つ。ベンドラインディメンションポイントはインタセクシヨン近似(ベンド角が90度程度)またはタンジェント近似(ベンド角が90度以上のとき)を用いて計算される。もしベンド角が90程度のときは、インタセクシヨン近似点は一致するので、両隣接フランジに対するベンドラインディメンションポイントの対は同じになる。他の種類のディメンションポイントはフランジディメンションポイントである。それらは、ベンドラインカラ最も離れたベンドラインの側のベンドラインに隣接するフランジ上の点である。フランジが正しい(すなわち、非空)とすると、少なくとも1つのフランジディメンションポイントがある。ただし、理論的には、フランジディメンションポイントの個数には上限はない。次の重要な点に注目されたい。もしフランジAが、ベンドラインBに隣接し、更にその最遠点において(すなわち、Bに対するフランジディメンションポイントにおいて)ベンドラインCに隣接すると、Aに対するBのフランジディメンションポイントは、実際にはAに対するCの同じベンドラインディメンションポイントである(あるいは、ベンドラインBとCが平行と仮定すると、さもなければ事態はトリッキーになり、それは最早真ではない。)。フランジディメンションポイントは、寸法はフランジの側で描かれなければならないので、フランジの角で計算される。以下は自動寸法化作業の方法である。:--------------------------------------**************************************--------------------------------------それは異なる2つのタスクに分割される。1つは全てのディメンションポイント(共に、ベンドラインディメンションポイントとフランジディメンションポイント)を計算するものである。この段階で、我々は、フランジ長さを描くことが出来る全てのディメンションポイントを計算する。潜在的には、これは単に一度行うことが出来、またもし部分が変化しないときは、我々は、自動寸法が描かれなければならない度にこの情報を後に再使用することが出来る。(ただし、部分は通常は変化しない−ユーザが部分を回転させるとき、ビユーアは、カメラ(これは通常なされる)ではなく、実際には部分を回転させる)従って、部分の3D座標は変化しない。しかし、この種の変化により影響されない部分のフラット部分に基づいて我々の計算をすることが出来るのであるが、幸運にも全てのディメンションポイントの計算はかなり早く、全ての時点でディメンションポイントを再計算することが可能であると思われる。私は丁度、我々が、もし必要なら、これらのディメンションポイントを一度予め計算し、後にそれらを再使用することにより時間を節約出来るということを指摘したい。我々が全てのディメンションポイントを計算すると、我々は寸法を描くことが出来る。ただし、われわれは先ず、ディメンションポイントのどれが可視であり、どれがそうでないかを解決しなければならない。割れれ我ワイヤフレーム像を持つときは、それはかなり容易である。ディメンションポイントは、もしそれがビユーウインド内にあるときは可視である。これのチェックは非常に速くできる。我々が中実(陰影)像を持つときは、通常ビユーアに近いフランジがはるかに離れた他のフランジのビユーをブロックし、同様に幾つかのディメンションポイントをブロックすることから、事態はより困難である。そこで、我々は或る種の隠されたラインの除去を行う必要がある。我々が、どのディメンションポイントが可視であるかを決定すると、フランジ長さは一連の異なる方法で描くことが出来、その場合我々は1つ、望ましくは最良のものを取り上げなければならない。注意:フランジ長さを示すためには、ベンドラインディメンションポイントとフランジディメンションポイントを必要とする。1つの発見的な方法は、ビユーアに近接し、サイドウエイ距離が最小のベンドライン−フランジ−ディメンションポイントを用いることにより与えられる。我々が全てのベンドラインに対するディメンションポイントを取り出すと、我々は寸法を描くことが出来る。自動寸法化の主要データ構造:----------------------------------------****************************************----------------------------------------3種類の使用対象物がある。BM_AUTO_DIMENSION-----------------BM_AUTO_DIMENSIONは、トップレベルのAuto-Dimension対象物であり、通常はBM_PARTと共にBendCAD書類の一部である。それは、自動寸法が描かれるBM_PARTに対するポインタ、並びに書類、ビユーおよびデバイスコンテクトポインタを含む。それは更に、ビユーウインドサイズ、ベンドラインの個数、 BM_AD_bendline対象物などのようなハイレベルの情報を含む。将来(現在04/03/96),それは、ラインカラーやライン幅、フォントサイズなどのようなペンやブラシ特性についての情報を格納すべきである。BM_AD_bendline--------------BM_AD_bendline は1つのBM ADベンドラインに関係する全ての自動寸法情報を格納する。また、隣接フランジの各々に対して内蔵の2つのベンドラインディメンションポイントを有する。また、隣接フランジの各々に対してフランジディメンションポイントのリストへのポイントを有する。BM_AD_dim_corner----------------BM_AD_dim_cornerはディメンションポイント(ベンドラインかフランジのいずれか)である。ディメンションポイントは1または3BM_POINTのいずれかを有することが出来る。ディメンションポイントの1つの重要なメンバは開放方向である。それは、このディメンションポイントに関する実際のディメンションが描かれなければならない方向を指示する。更に、このディメンションポイントが可視である方向を指示する。もしそれが可視のときは、それはその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) ;} ;/*********** ********** ********** ********** ********** ********** ********** ********** ********** この種の対象物は、1ベンドラインに係わる自動寸法化データを表す。ベンドラインに対する基本のAD操作は隣接するフランジ長さを描くことである。技術的注意 :- tベンドラインディメンションポイントとフランジディメンションポイントの開放方向ベクトルは相関付けされない。それは、あなたは、同じ開放方向を持つ2点に対シテチェックするべきである。- アルゴリスム:先ず、我々は全てのベンドラインに対する全てのベンドラインディメンションポイントを計算する。次に、我々は、全てのベンドラインに対する全てのフランジディメンションポイントを計算する。その理由は、我々がフランジディメンションポイントを計算するとき、フランジ内の、および他のベンドラインに隣接する幾つかのエッジがあるということである。全てのベンドラインディメンションを先ず計算するときは、他の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 ;/*これらのパラメータは、プロセス中にしばしば計算され、後に必要とされ、そこで性能理由に対して我々はそれらを、我々がそれらを後に再計算する必要がないように格納する。それらの各々は(ベンドラインから)隣接体に向け指示するベクトルであり、隣接体に接触するベンドアークの端点に対して接線をなす平面上にある。 これらは主要データ構造の幾つかである。 各々の隣接体に対して、ベンドラインの各々の端点(すなわち、左および右)に対して1つの2つ端点を持つ。これらの点は、フランジ長に対する寸法がベンドラインで(すなわち、ベンドラインの側部で)描くことが出来る点を特定する。注意:現在(04/02/96)、我々は全てのベンドラインにおいてディメンションを描くため正確に2つの可能な点を考える。これらの2つの点はベンドラインセンタラインの方向のベンドラインの2つの最端点である。注意:これらはベンドラインのベンドラインディメンションポイントと呼ばれる。注意:これらの点は、例えadj body1およびadj body2が空であっても常に計算される。*/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 ;/*ここにディメンションポイントの2つのリストがある。1つはadj-bodyに関するもので、他はadj−body2に関するものである。両リストはフランジ長ディメンションポイントである点を含む。注意:これらはベンドラインのフランジディメンションポイントと呼ばれる。*/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 that 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
付録G
機能を描く自動寸法化の例。これらの関数は、デイメンシヨンポイントが既に計算されていることを仮定する。
【0296】
///*ディメンションポイントを計算する関数は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 ;/*ワイヤフレームは、このディメンションポイントが実際に最前面にある3D体か否かをチェックしない(原文不明) ワイヤフレームモードでは、我々は、ビユーウインドにおける全ての事態が可視であると仮定する。*///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 {/*ソリッド発見手法:これはソリッドモードを操作する新しいバージヨンである。先ず、全ての3点p,p1および2がビユーウインド内にあるかをチェックする。もし真なら、我々は、ベンドアークのサイドプロフィルのセンタ点を計算し、この点におけるベンドラインが実際に可視か否かをチェックする。*/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が基礎をなす可視の3D体を持つか否かをチェックする。// もし我々が3点を持つときは、点pは3D体上にはない。従って、我々は、それが有るか否かをチェックするのみである。// ビユーウインド内に。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) ;}/*この関数は1フランジ長ディメンションを描く。 第一の引数はベンドラインディメンションポイントであり、第二はフランジディメンションポイントである。*/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に対してK因子のために負になり得る。ここでこの関数は、dimension-extension-linesが:1つのdimension-extension-lineが単位長さであり、また他のものが、第一のものに達するのに必要な程度に長いように描かれることを仮定する。すなわち、この関数はディメンションポイントの1つに隣接するディメンションアローを描く。すなわち、それは2つのディメンションポイントの間のラインの途中の或る点でディメンションポイントを描くことを試みない。想起:bendline-dimension-opening-direction-vectorは規格化されるべきである。注意:ここでこの関数は、dimension-extension-linesが:1つのdimension-extension-lineが単位長さであり、また他のものが、第一のものに達するのに必要な程度に長いように描かれることを仮定する。すなわち、この関数はディメンションポイントの1つに隣接するディメンションアローを描く。すなわち、それは2つのディメンションポイントの間のラインの途中の或る点でディメンションポイントを描くことを試みない。注意:この関数において、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 ;/*ソリッド発見手法 :ソリッドモードにおいて、我々は時間を節約するためにこの発見的手法を用いている。2つのベンドラインがフランジ長を表示するために(潜在的に)等価なflange-dimension pointsを用いているときは、我々は単に、より高いidxを持つベンドライン(これらの2つのベンドラインの)に対してのみ可視度を計算する。*/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}/*この関数はそれを1つのベンドラインに対して厳密に行う。重要:それは単に、どの方法が最良なものかを決定するが、ADが実際にそれをそのように行うか否かを決定することはない。ここで、それは他のデータ構造を更新する何らかかの方法を実施する。端的には、それはADデータ構造のいずれかを変えることはない。注意:始めは何らのチェックもなされない。アイデア:この関数において、我々は、異なるbend-flange-dimポイントの組み合わせに対する値を割り当てる発見的手法を用いる。最終的には、我々は最良の組み合わせを選択する。我々が用いる発見的手法は、ベンドおよびフランジdimポイントの間の距離の組み合わせ、プラスビユー画面からのbend-pointの距離である。実際的なトリック:先ず我々は、最も良く知られた距離の値が既に0であるか否かをチェックする。もし0であるなら、我々は、この新しいbend−dimポイントが良好なz−buf値を持つときにのみ他のbend-dimポイントに対して最良の一致を見出そうとする。注意:4部分のテストの後、私は、これが丁度非常にわずかな改善を与えることを見出す。それは恐らく5−10%KKである(原文不明)。*/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構造であり、3、4はflange-dimポイントであり、4、5はフランジリストである。 */,double distance_and_z[4] /* 0,1は距離であり、3、4はz−bufである。*/){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) ;}}}}/*この関数は全てのベンドラインに対してベンドラインデータと共にinfo−boxを描く。アイデア:われわれは、ソリッドモードではレンダウエアはその種の情報を提示しないため、ビユー領域における部分の可視部分のboundingボックスをチェックしない。更に、しばしば、ユーザは部分のデイメンシヨンを診るためにズームインし、その場合、部分によりカバーされないビユーポートの部位はなく、すなわちboundingボックスは全体のビー領域をカバーし、実際には無用である。代わりに、我々はビユー領域のエッジに沿いベンドライン情報ボックスを描いていることになる。我々はビユー領域を4領域に分割し、info−boxが関係するベンドポイントにどれがより近くても、それらの領域にベンドラインinfoボックスを配置する。ここで当然、我々はビユーポートの左−右垂直エッジに沿いそれらのボックスを描く。*/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 ; }/*ベンドラインポインタおよびbend−dim−pointポインタを集める。*/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_body1_point_right).z_buf_value) bend_points[j] = &(bends[i]->bend_body1_point_left) ;else bend_points[j] = &(bends[i]->bend_body1_point_right) ;}}else bend_points[j] = &(bends[i]->bend_body1_point_right) ;if (++j >= num_bends_to_be_drawn) break ; // out of view space}/*info-boxが画面のどの側にあるべきかに従ってポイントを分類する。bend-line-dim-pointが画面の左側にない全てのボックスを含む(少なくとも始めは)。*/int half_screen = (view_size_x >> 1) ;i = 0 ; // i will be topj = num_bends_to_be_drawn - 1 ; // j will be bottom// we will use these to temporarily store stuffBM_AD_bendline *p_bend ;BM_AD_dim_corner *p_bend_point ;while (i < j) {while (i < j && bend_points[i]->screen_x < half_screen) i++ ;while (i < j && bend_points[j]->screen_x >= half_screen) j-- ;// switch i and jif (i < j) {p_bend = bendlines[i] ;p_bend_point = bend_points[i] ;bendlines[i] = bendlines[j] ;bend_points[i] = bend_points[j] ;bendlines[j] = p_bend ;bend_points[j] = p_bend_point ;}}if (bend_points[i]->screen_x < half_screen) i++ ;// i points to the first info-box on the right side/*どちらの側も(すなわち、左−右)余りに多くのinfo-boxを有さないことをチェックする。*/if (i > half_max_num_info_boxes) {// too many boxeson the left side.// sort them according to x-coordinates.// this way wewill move points with the largest x-coordiates to the right side.for (j= 0 ; j < i ; j++) bend_y_coordinates[j] = bend_points[j]->screen_x ;DBM_QuickSort_double(bend_y_coordinates, (unsigned long) i, (long *) bendlines) ;i = half_max_num_info_boxes ;}else if ((num_bends_to_be_drawn - i)> half_max_num_info_boxes) {// too many boxes on the right side.// sortthem according to x-coordinates.// this way we will move points with the smallest x-coordiates to the left side.for (j = i ; j < num_bends_to_be_drawn ; j++) bend_y_coordinates[j] = bend_points[j]->screen_x ;DBM_QuickSort_double(bend_y_coordinates + i, (unsigned long) (num_bends_to_be_drawn - i), (long *) (bendlines + i)) ;i = num_bends_to_be_drawn - half_max_num_info_boxes ;}// it could have been that when we chose a point fora bendline, it is not the best point.// (although this point was used to place this point on the left-right side).// imagine a point on the left. it could be that both endpoints are visible, but// out point is not the best, because the other endpoint of the bendline is actually to the//left of our point.for (j = 0 ; j < i ; j++) {// check if we have choiceif (! (bendlines[j]->bend_body1_point_left).visible || ! (bendlines[j]->bend_body1_point_right).visible) continue ;if ((bendlines[j]->bend_body1_point_left).screen_x < (bendlines[j]->bend_body1_point_right).screen_x)bend_points[j] = &(bendlines[j]->bend_body1_point_left) ;else bend_points[j] = &(bendlines[j]->bend_body1_point_right) ;}for (j = i ; j < num_bends_to_be_drawn ; j++) {// check if we have choiceif (! (bendlines[j]->bend_body1_point_left).visible || ! (bendlines[j]->bend_body1_point_right).visible) continue ;if ((bendlines[j]->bend_body1_point_left).screen_x> (bendlines[j]->bend_body1_point_right).screen_x) bend_points[j] = &(bendlines[j]->bend_body1_point_left) ;else bend_points[j] = &(bendlines[j]->bend_body1_point_right) ;}// store the y-coordinate for Quicksortfor(j = 0 ; j < num_bends_to_be_drawn ; j++) bend_y_coordinates[j] = bend_points[j]->screen_y ;// sort both sides according to the screen y-coordinate// note a glitch : while the bendlines[] array has been permuted, thebend_points[] array has not been.// in the next paragraph we restore the point array. TODO : may-be there is a better solution.//we could resort the array, but then we need to get original y-coordinates array.//we could just compute a separate permutation array, but then we need space for it, and//the code to compute the permutation, which is non-tirivial.// anyway, for now we just do it the easy way.if (i > 0) DBM_QuickSort_double(bend_y_coordinates, (unsigned long) i, (long *) bendlines) ;if ((num_bends_to_be_drawn - i) > 0) DBM_QuickSort_double(bend_y_coordinates +i, (unsigned long) (num_bends_to_be_drawn - i), (long *) (bendlines + i)) ;for (j = 0 ; j < i ; j++) {if ((bendlines[j]->bend_body1_point_left).visible) {if (! (bendlines[j]->bend_body1_point_right).visible) bend_points[j] = &(bendlines[j]->bend_body1_point_left) ;else {if ((bendlines[j]->bend_body1_point_left).screen_x < (bendlines[j]->bend_body1_point_right).screen_x) bend_points[j] = &(bendlines[j]->bend_body1_point_left) ;else bend_points[j] = &(bendlines[j]->bend_body1_point_right) ;}}else bend_points[j] = &(bendlines[j]->bend_body1_point_right) ;}for (j = i ; j <num_bends_to_be_drawn ; j++) {if ((bendlines[j]->bend_body1_point_left).visible) {if (! (bendlines[j]->bend_body1_point_right).visible) bend_points[j] = &(bendlines[j]->bend_body1_point_left) ;else {if ((bendlines[j]->bend_body1_point_left).screen_x > (bendlines[j]->bend_body1_point_right).screen_x) bend_points[j] = &(bendlines[j]->bend_body1_point_left) ;else bend_points[j] = &(bendlines[j]->bend_body1_point_right) ;}}else bend_points[j] = &(bendlines[j]->bend_body1_point_right) ;}/*ここで描画の準備が完了する。*/static char info_box_text[256] ;static POINT box_corners[5] ;static POINT arrow[3] ;BM_BENDLINE *b ;BM_BEND_OP *bop ;BM_2D_BODY*b_body ;/*左側を描く。*/int left = 3 ;int top ;if (0 == i) goto draw_right_side ;// compute vertical space per info-boxvert_space_per_box = view_size_y / i ;// compute vertical offset for the top-left corner of theinfo-boxoffset = (vert_space_per_box - box_height) >> 1 ;box_corners[0].x = box_corners[3].x = box_corners[4].x = left ;box_corners[1].x = box_corners[2].x = left + box_width ;for (j = 0 ; j < i ; j++) {b = bendlines[j]->bend ;bop = b->get_bend_op() ;if (NULL == bop) continue ;// 043996KKif (view_type) b_body = b->get_current_3D_version() ;else b_body = b->get_flat() ;top = j*vert_space_per_box + offset ;box_corners[0].y = box_corners[1].y = box_corners[4].y = top ;box_corners[2].y = box_corners[3].y = top + box_height ;sprintf(info_box_text,"A:%5.1f,L:%6.2f",(bop->get_bend_angle2())*57.29578,(b_body->get_current_center_line()).get_len()) ;pdc->TextOut(5, top, info_box_text, strlen(info_box_text)) ;switch (bop->get_type()) {case BM_TYPE_BEND_OP_REGULAR :sprintf(info_box_text,"R:%5.2f,D:%5.2f",((BM_BEND_OP_REGULAR *) bop)->get_bend_radius(),bop->get_bend_deduction()) ;pdc->TextOut(5, top + font_height, info_box_text, strlen(info_box_text)) ;break ;case BM_TYPE_BEND_OP_CONIC :// TODO : implementconic bend op.break ;}// draw boxpdc->Polyline(box_corners, 5) ;// drawarrowarrow[0].x = left + box_width ;arrow[0].y = top + half_box_height;// calculate arrow tip at fixed percentage length in from end pointCPoint ptLeft(bendlines[j]->bend_body1_point_left.screen_x, bendlines[j]->bend_body1_point_left.screen_y);CPoint ptRight(bendlines[j]->bend_body1_point_right.screen_x, bendlines[j]->bend_body1_point_right.screen_y);CSizesizeDiff = ptRight - ptLeft;CPoint ptArrowTip;if ( bend_points[j] == &(bendlines[j]->bend_body1_point_left) ){ptArrowTip.x = ptLeft.x + sizeDiff.cx/8;ptArrowTip.y = ptLeft.y + sizeDiff.cy/8;}else{ptArrowTip.x = ptRight.x - sizeDiff.cx/8;ptArrowTip.y = ptRight.y - sizeDiff.cy/8;}arrow[1].x = ptArrowTip.x;arrow[1].y = ptArrowTip.y;pdc->Polyline(arrow, 2) ;//change to solid pen for arrow headsCPen* pArrowPen = new CPen(PS_SOLID,BCAD_context.m_nBendLineWeight, BCAD_context.m_crBend);CPen* pOldPen = pdc->SelectObject(pArrowPen);// compute arrow headCAutoDimArrow arrowBend(ptArrowTip,CPoint(arrow[0].x,arrow[0].y),BCAD_context.m_nArrowAngle,BCAD_context.m_nArrowLength);// draw arrow headarrowBend.DrawHead(dc);pdc->SelectObject(pOldPen);delete pArrowPen;}/*右側を描く。*/draw_right_side:if (0 == num_bends_to_be_drawn - i) goto done ;box_x = view_size_x - box_width - 3 ;left = box_x ;// compute vertical space per info-boxvert_space_per_box = view_size_y / (num_bends_to_be_drawn - i) ;// compute vertical offset for the top-left corner of the info-boxoffset = (vert_space_per_box - box_height) >> 1 ;box_corners[0].x = box_corners[3].x = box_corners[4].x = left ;box_corners[1].x = box_corners[2].x = left + box_width ;box_x += 2 ;for (j = i ; j < num_bends_to_be_drawn ; j++) {b = bendlines[j]->bend ;bop = b->get_bend_op() ;if (NULL == bop) continue ;// 043996KKif (view_type) b_body = b->get_current_3D_version() ;else b_body = b->get_flat() ;top = (j - i)*vert_space_per_box + offset ;box_corners[0].y = box_corners[1].y = box_corners[4].y = top ;box_corners[2].y = box_corners[3].y = top + box_height ;sprintf(info_box_text,"A:%5.1f,L:%6.2f",(bop->get_bend_angle2())*57.29578,(b_body->get_current_center_line()).get_len()) ;pdc->TextOut(box_x, top, info_box_text, strlen(info_box_text));switch (bop->get_type()) {case BM_TYPE_BEND_OP_REGULAR :sprintf(info_box_text,"R:%5.2f,D:%5.2f",((BM_BEND_OP_REGULAR *) bop)->get_bend_radius(),bop->get_bend_deduction()) ;pdc->TextOut(box_x, top + font_height, info_box_text, strlen(info_box_text)) ;break ;case BM_TYPE_BEND_OP_CONIC ://TODO : implement conic bend op.break ;}// draw boxpdc->Polyline(box_corners, 5) ;// draw arrowarrow[0].x = left ;arrow[0].y!160#= top + half_box_height ;// calculate arrow tip at fixed percentage length in from end pointCPoint ptLeft(bendlines[j]->bend_body1_point_left.screen_x, bendlines[j]->bend_body1_point_left.screen_y);CPoint ptRight(bendlines[j]->bend_body1_point_right.screen_x, bendlines[j]->bend_body1_point_right.screen_y);CSize sizeDiff = ptRight - ptLeft;CPoint ptArrowTip;if ( bend_points[j]== &(bendlines[j]->bend_body1_point_left) ){ptArrowTip.x = ptLeft.x + sizeDiff.cx/8;ptArrowTip.y = ptLeft.y + sizeDiff.cy/8;}else{ptArrowTip.x =ptRight.x - sizeDiff.cx/8;ptArrowTip.y = ptRight.y - sizeDiff.cy/8;}arrow[1].x = ptArrowTip.x;arrow[1].y = ptArrowTip.y;pdc->Polyline(arrow, 2);// change to solid pen for arrow headsCPen* pArrowPen = new CPen(PS_SOLID, BCAD_context.m_nBendLineWeight, BCAD_context.m_crBend);CPen* pOldPen = pdc->SelectObject(pArrowPen);// compute arrow headCAutoDimArrow arrowBend(ptArrowTip,CPoint(arrow[0].x,arrow[0].y),BCAD_context.m_nArrowAngle,BCAD_context.m_nArrowLength);// draw arrow headarrowBend.DrawHead(dc);pdc->SelectObject(pOldPen);delete pArrowPen;}/*割り当てたメモリを開放する。*/done :delete [] bend_points ;delete [] bend_y_coordinates ;delete[] bendlines ;}/*デバイスコンテクストに部分デイメンシヨンを描く。*/int BM_AUTO_DIMENSION::draw_auto_dimensions(CDC *target_dc){BM_AD_dim_corner*temp_point ;int i ;// check that we have a valid dcif (NULL == target_dc) return 0 ;// check if we need to recompute the data structuresif (dirty) {if (! compute_auto_dimension_data()) return 0 ;if (dirty) return 0;}if (NULL == part) return 1 ;dc = target_dc ;// get view sizeview_size_x = view->get_viewport_width() ;view_size_y = view->get_viewport_height() ;// create a mesh to determine clear spaces to draw dimensions & datapMesh = new CAutoDimRgnMesh(view_size_x, view_size_y);// check if we needto compute points to ignore in solidif (view->get_drawing_mode() && ! points_to_ignore_in_solid_computed) {compute_points_to_ignore_in_solid();}object_space_per_pixel = view->get_object_to_device_ratio() ;// initially set all "ignore" flags to FALSE. we should not ignore anything.// also, nothing is drawn yet.for (i = 0 ; i < num_of_bendlines ; i++) {bends[i]->ignore = 0 ;bends[i]->body1_drawn = bends[i]->body2_drawn = 0 ;}/*全てのベンドラインの全てのベンドラインデイメンシヨンポイントのビジビリテイを計算する。*/for (i = 0 ; i < num_of_bendlines ; i++) {if (! bends[i]->data_valid) continue ;bends[i]->compute_bendline_dim_points_visibility() ;if (bends[i]->adj_body1) {for (temp_point = bends[i]->body1_points ;temp_point ; temp_point = temp_point->next) temp_point->visible = -1 ;}if (bends[i]->adj_body2) {for (temp_point = bends[i]->body1_points ; temp_point ; temp_point = temp_point->next) temp_point->visible = -1 ;}}/*全てのベンドラインに対して、描くべきデイメンシヨンポイントを計算する。*/for (i = 0 ; i < num_of_bendlines ; i++) {if (! bends[i]->data_valid ||bends[i]->ignore) continue ;bends[i]->compute_dim_points_to_display() ;}/*パートを描くペンを生成する。フランジデイメンシヨンを描くペンを生成する。*/// create the pen : type, (line)width, color.CPen penFlange;CPen* pFlangePen = create_auto_dim_pen(&penFlange, BCAD_context.m_nFlangeLineStyle, BCAD_context.m_nFlangeLineWeight, BCAD_context.m_crFlange);// selectnew pen, save old penCPen* pOldPen = dc->SelectObject(pFlangePen);COLORREF oldtextcolor = dc->SetTextColor(BCAD_context.m_crFlange) ;int old_bk_mode = dc->SetBkMode(TRANSPARENT) ;/*フランジ長さディメンシヨンを表示する。*/if (BCAD_context.m_bShowFlangeDim){for (i = 0 ; i < num_of_bendlines ; i++) {if (! bends[i]->data_valid || bends[i]->ignore) continue ;bends[i]->draw_dimension_points();}}/*// ダーテイ領域の表示をテストする。CBrush brRed(RGB(255,0,0));CBrush* pOldBrush = dc->SelectObject(&brRed);dc->PaintRgn(pDirtyRegion);dc->SelectObject(pOldBrush);*/delete pDirtyRegion;pDirtyRegion = NULL;/*ベンドラインinfoを描くペンを生成する。*/// create the pen : type, (line)width, color.CPen penBend;CPen* pBendPen = create_auto_dim_pen(&penBend, BCAD_context.m_nBendLineStyle, BCAD_context.m_nBendLineWeight, BCAD_context.m_crBend);// select the new pendc->SelectObject(pBendPen);dc->SetTextColor(BCAD_context.m_crBend);/*ベンドラインinfoを描く。*/if (BCAD_context.m_bShowBendDim)draw_bendline_data(dc) ;// Delete the mesh now that we are finished with it.//delete pMesh;/*古いペンを復帰させる。*/dc->SelectObject(pOldPen) ;dc->SetTextColor(oldtextcolor) ;dc->SetBkMode(old_bk_mode) ;// see if we have to disable auto-dimensioning in the view classif (reset_view_to_false_once_drawn) {reset_view_to_false_once_drawn = 0 ;view->set_auto_dimensions(0) ;}return 1 ;}CPen* BM_AUTO_DIMENSION::create_auto_dim_pen(CPen* pPen, int nLineStyle, intnLineWeight, COLORREF cr){if (nLineWeight == 1 || nLineStyle == PS_SOLID)pPen->CreatePen(nLineStyle, nLineWeight, cr);// for speedelse{CBrush brushNew(cr);LOGBRUSH lb;brushNew.GetLogBrush(&lb);DWORD dwStyleArray[6];int nStyleCount = 2;DWORD dwDashLength = 2 + (nLineWeight * 4);DWORD dwDotLength = dwDashLength / 4;DWORD dwGapLength = dwDashLength / 2;switch(nLineStyle){case PS_DASH:dwStyleArray[0] = dwDashLength;// pixels ondwStyleArray[1] = dwGapLength;// pixels offnStyleCount = 2;break;case PS_DOT:dwStyleArray[0] = dwDotLength;// ondwStyleArray[1] = dwGapLength;// offnStyleCount = 2;break;case PS_DASHDOT:dwStyleArray[0] = dwDashLength;//ondwStyleArray[1] = dwGapLength;// offdwStyleArray[2] = dwDotLength;//ondwStyleArray[3] = dwGapLength;// offnStyleCount = 4;break;case PS_DASHDOTDOT:dwStyleArray[0] = dwDashLength;// ondwStyleArray[1] = dwGapLength;// offdwStyleArray[2] = dwDotLength;// ondwStyleArray[3] = dwGapLength;// offdwStyleArray[4] = dwDotLength;// ondwStyleArray[5] = dwGapLength;// offnStyleCount = 6;break;}pPen->CreatePen(PS_GEOMETRIC | PS_USERSTYLE,nLineWeight, &lb, nStyleCount, dwStyleArray);}return pPen;}void CBendCADDoc::OnDrawAutoDim() {// if we have no dimension object, do nothing.if(NULL == auto_dim) {auto_dim = new BM_AUTO_DIMENSION(this) ;}if (NULL ==auto_dim) return ;CBendCADViewPart *pActiveView = (CBendCADViewPart *)get_view(BENDCAD_VIEW_TYPE_PART) ;if (NULL == pActiveView) return ;if (!pActiveView->get_auto_dimensions()) auto_dim->disable_view_dimensions_flag_next_time() ;pActiveView->set_auto_dimensions(1) ;// always recompute dimension pointsauto_dim->invalidate() ;pActiveView->Invalidate(0) ;}
付録H
ディメンションポイントを計算する自動寸法化関数の例。ディメンションポイントは、フランジ長ディメンションが描かれる前に計算される。
【0297】
//#include "stdafx.h"#include "BendCAD.h"#include "BendCADDoc.h"#include"BendCADViewPart.h"#include "AUTODIM.HXX"/*********** ********** ********** ********** ********** ********** ********** ********** **********BM_AD_bendline class stuff.********** ********** ********** ********** ********** ********** ********** ********** ***********//*これは、所与の基準点とエッジポイントの間の距離を計算するBM_AD_bendline::compute_BM_AD_flange_points(..)に用いられるローカルな関数である。この関数はポイントが基準ラインの1つの間違った側である場合にFALSEを戻す。 ベクトルdirはユニットベクトルであるべきである。*/static int compute_distance_from_ref_point(BM_POINT const& pt /* given reference point */,BM_VECTOR const& dir /*direction vector */, BM_POINT *p /* point whose distance we want to compute */, double &distance){BM_VECTOR v(*p - pt) ;double x = v % dir ;if (x < -AUTODIM_DISTANCE_TOLERANCE) return 0 ;distance = x ;return 1 ;}/*BM_AD_bendline::compute_BM_AD_flange_points(...)により用いられるローカル関数。注意:参照するディメンションリストはフランジディメンションポイントのリストである。”左”に開放したリスト中のディメンションポイントの個数が”右”に開放したリスト中のディメンションポイントの個数に等しくないとき、ディメンションリストは開放である。これは通常リストに付加した最後のフランジディメンションポイントが”閉じる”に一致するフランジディメンションポイントを持たないことを意味する。これらはすべて、実際には小片に分解されたライン(1つのラインのように見える)を我々が持つことが出来る可能性によりもたらされる。その場合、ユーザはそれらの小片を見ず(1つのラインのように見える)、また我々はポイントを途中で正当なフランジディメンションポイントと考えることを望まない。この関数は、我々が所与のエッジをスキップし、ディメンションポイントを開放のままにすることが出来るときはTRUEを戻し、また、我々が、現在のエッジのエンドポイントの1つから左側ディメンションポイントを生成することにより開放ディメンションを閉じる必要があるときはFALSEを戻す。基本的には、この関数は、ループ中の次のエッジが無視されないラインであるときはTRUEを戻す。実際には、更に幾つかの条件を付加する。注意:この関数は、エッジのエンドポイントがフランジ長距離にあり、また我々が、このエンドポイントに対する(フランジ)ディメンションポイントを描くべきかを考えているときに求められる。*/static int leave_dimension_open(BM_EDGE *edge /* current edge */,BM_LOOP *bloop /* loop where the current edge belongs to */,BM_VECTOR const& side_vector /* side vector for the current bendline-ajd_flange pair */, BM_VECTOR const& normal /* normal of the plane underlying the adjacent flange */){BM_EDGE *next_edge = (BM_EDGE *) edge->next();if (NULL == next_edge) next_edge = bloop->get_first_edge() ;if (next_edge->is(BM_ENTITY_TYPE_LINE)) {// problem. if the next edge (which is aline) will be ignored, we need to// close the dimension here.BM_VECTOR temp_v((((BM_LINE *) next_edge)->get_v()) * side_vector) ;// if the nextline will not be ignored we can skip the current edge.if (temp_v.Len() >AUTODIM_DISTANCE_TOLERANCE && (temp_v % normal) < 0.0) {// next edge isa line that will not be ignored.// note that there is a problem. if this edge is a line, and one of the two lines // (rememeber, next edge is aline) is adjacent to a bendline that // the other is not adjacent to, we should close the dimension.if (! edge->is(BM_ENTITY_TYPE_LINE)) return1 ;BM_3D_BODY *ab = edge->get_adj_body() ;BM_3D_BODY *ab_next = next_edge->get_adj_body() ;if (! ab) {if (! ab_next) return 1 ;if (! ab_next->is(BM_ENTITY_TYPE_BENDLINE)) return 1 ;return 0 ;}if (! ab_next) {if (! ab->is(BM_ENTITY_TYPE_BENDLINE)) return 1 ;return 0 ;}if ((! ab->is(BM_ENTITY_TYPE_BENDLINE) && ! ab_next->is(BM_ENTITY_TYPE_BENDLINE)) ||ab == ab_next) return 1 ;}}// if next edge is not a line, we have to close theopen dimensionreturn 0 ;}/*BM_AD_bendline::compute_BM_AD_flange_points(...)により用いられるローカルな関数この関数は最も一般的な形態でディメンションポイントを生成する。我々は、我々がラインに対するディメンションポイントを生成していると仮定する。このラインはベンドラインに隣接することが出来る。*/static BM_AD_dim_corner *create_dim_point(double d /* bendline arcoutside length projected onto our plane */, // these are basic parameters needed to draw any dimension pointBM_POINT const& p /* point p in theflange dimension point */,BM_VECTOR const& rv /* reference vector to make sure point p in the flange dimension point is on the same plane as defined by the bendline dimension point */,BM_VECTOR const& opening_direction_vector /* for flange dimension point */, int opening_vector_reverse_bit,BM_AD_bendline *owner,BM_3D_BODY *Body_required_visible,BM_AD_dim_corner **prev /* previous flange dimension point in the list of flange dimpoints */,BM_VECTOR const& side_vector, // these parameters are used when the line for which we are computing the dimension point is adjacent//to another bendline.double d_proj_side_vector /* d projected onto the side-vector : angle_factor*d in compute_BM_AD_flange_points(...) */,BM_VECTOR & bend_arc_direction /* direction of the bend arc projected onto our plane *//* should be line->v * plane_normal */,BM_VECTOR & bend_direction /* points to the direction in which the bendline "turns" *//* depends on whether the bend angle is acute or not. *//* if acute then tangentto the other end of bend arc *//* if not acute, then an endpoint of thetangent approximation *//* basically this is the (p->p2) vector for theother bendline with respect to this flange */,BM_BENDLINE *adj_bendline/* if the line is adjacent to a bendline this is a pointer to it *//* this parameter is stored to avoid drawing some dimenions twice */,BM_LINEconst& adj_bend_p2_line /* this is the line between p2 points of the bend-dimension *//* points of the adjacent bendline with respect to this flange *//* note that our p2 point has to be on that line. *//* usually our p->p2 vector is perpendicular to this line, although not always */){//this our local copy of the adj-bendline-pointerBM_3D_BODY *adj_bend = adj_bendline ;BM_POINT p_local(p + rv) ;// note : even if this line is adjacent to another bendline, // but if the line we are creating the flange dimension point for is not perpendicular to// the side-vector, we should not memorize that this flange dimension point is adjacent to // a bendline, because the flange length dimension drawn at this flange dimension point // is not parallel to the side-vector of the adjacent bendline with respect to this flange.if (adj_bendline && fabs(bend_arc_direction %side_vector) < (bend_arc_direction.Len() - AUTODIM_DISTANCE_TOLERANCE)){// not perpendicularadj_bendline = NULL ;}// check if the line is attached to a bendlineif (d <= AUTODIM_DISTANCE_TOLERANCE) {// not attachedto a bendline, or both thickness and bendline radius are 0.// create a 1-point flange-dimension point.// note that body_required_visible pointsto the flange with respect to which // the dimension point is computed.return new BM_AD_dim_corner(p_local, owner, Body_required_visible, opening_direction_vector, opening_vector_reverse_bit, prev, adj_bendline) ;}//note that since we have 3 points now, this line is adjacent to anotherbendline.// compute p1. p_local is p1.// compute pBM_POINT dim_p(p_local+ d_proj_side_vector*side_vector) ;// compute p2bend_arc_direction.set_length(d) ;BM_POINT dim_p2(p_local + bend_arc_direction) ;// now the problem is that with respect to the adjacent bendline, our flange dimensionpoints// p and p1 might not be on the outside - they could be on the inside.// the distance from p to p2 depends on that.// however, we know the p2-line of the adjacent bendline (with respect to our flange),// so wewill compute the distance between that p2-line and dim_p2. // we will use that to compute the correct p2 point for our flange dimension (note that// our p2 point has to be on the p2-line of the adjacent bendline).double distance ;BM_distance_between_point_and_line(dim_p2, adj_bend_p2_line, &distance, (BM_POINT *) NULL) ;bend_direction.set_length(distance) ;dim_p2 = dim_p2 + bend_direction ;// note that the body_required_visiblepointer points not to this flange, but to the // adjacent-bendline instead, ALWAYS, even if this flange dim point will not be marked as// adjacent to another bendline.return new BM_AD_dim_corner(dim_p, p_local, dim_p2, owner, adj_bend ? adj_bend : Body_required_visible, opening_direction_vector, opening_vector_reverse_bit, prev, adj_bendline) ;}/*この関数は隣接フランジに対するフランジディメンションポイントを計算する。注意:この関数の直前に計算した基準ポイントは、我々が任意の種類のadj-body面を操作出来るを確実にするために与えられる。第一の問題は、我々が、adj-bodyの3次元- バージヨンの2次元- bodyがOUTSIDEまたはINSIDEを表すかどうか解らないということである。我々は、ベンドラインに対するベンドラインディメンションポイントがOUTSIDEポイントであることを知っている。ただし、 adj-bodyが明瞭にINSIDEを表すということがあり得る。その場合、ここで計算しようとしている全てのポイントをシフトさせる並進ベクトルを計算する基準ポイント(これはadj-bodyの外側面上にある)に対して用いられる。更に、この並進ベクトルを用いて、フランジディメンションポイントのポイントp1およびp2が正しいということを確認するために用いる。(もし、adj-bodyがinsideを表すときは、我々はoutsideに対して実際にディメンションポイントを計算し、ライン(p->p2)は注意して構成されなければならず、それはライン(p->p1)より短い。)注意:この関数は、我々がここでより多くの仮定を行うがBMAPI’s BM_2D_BODY::compute_outside_width(...)関数に非常によく相似している。*/int BM_AD_bendline::compute_BM_AD_flange_points(BM_3D_BODY *adj_body){// flange dimension points we aregoing to compute will be stored hereBM_AD_dim_corner **list_of_points ;// list_of_points is where we write the pointer to the // next flange dimension pointBM_AD_dim_corner *temp_dp ;// these parameters are used asinput to this function.double flange_length ; /* it is important that the flange length be the correct flange length */BM_POINT ref_point ; /*reference point, defines the right plane for flange dimension points */BM_VECTOR side_vector ; /* should be normalized */// check which adjacentbody we computeif (adj_body == adj_body1) {flange_length = fl1 ;list_of_points = &body1_points ;ref_point = bend_body1_point_left.p ;side_vector = side_vector1 ;}else if (adj_body == adj_body2) {flange_length = fl2;list_of_points = &body2_points ;ref_point = bend_body2_point_left.p ;side_vector = side_vector2 ;}else return 0 ; // not an adjcent body// variables to store temporary valuesBM_VECTOR temp_v ;double temp_x ;// parameters for fixing the reference pointBM_POINT rp(ref_point) ; // this a local copy of the reference point. we will modify it.BM_VECTOR rv ; // avector for translating flange dimension points.int ref_vector_valid = 0; // if this is TRUE, we need to translate all flange dimension points.// if TRUE, the only really tricky part is to construct the p2 point in the flange dimension point.// qualification checkBM_2D_BODY *adj_displayed_version ;if (parent->get_view_type()) adj_displayed_version = adj_body->get_current_3D_version() ;else adj_displayed_version = adj_body->get_flat() ;if (NULL == adj_displayed_version) return 0 ;BM_SURFACE *surface= adj_displayed_version->get_surface() ;if (NULL == surface) return 0 ;BM_LOOP *bloop = adj_displayed_version->get_bloop() ;if (NULL == bloop) return 0 ;BM_EDGE *edge ; // here we will store edges as we scan the loop.double distance1, distance2 ; // here we will store the distance of points we seedouble d1, d2 ; // here we store distance that has to be addedbecause of a bend arc. for lines adjacent to a bendline.double td1, td2; // here we store the total distance which is the sum of distanceX + dX.BM_3D_BODY *ab ; // here we store a pointer to a body that is adjacentto the current edge.BM_BEND_OP *bop ; // here we store a pointer to thebend op associated with the bendline that is// adjacent to the edge wescan (valid only iff the body adjacent to the edge is a bendline).BM_VECTOR right_opening_direction ; // this is the right-side opening direction vector. BM_VECTOR left_opening_direction ; // this is the left-side opening direction vector. int fl_dim_open = 0 ; // if this is TRUE, we have created a right-side flange dimension point, but// no corresponding left-side dimension point. That is, the dimension is "open".BM_VECTOR bend_arc_direction ; // direction of the bend arc projected onto our plane//should be line->v * plane_normal. Used when a line is adjacent to a bendline.BM_VECTOR bend_direction ; // points in the direction in which thebendline "turns"// depends on whether the bend angle is acute or not. // if acute then tangent to the other end of bend arc.// if not acute, then an endpoint of the tangent approximation.// basically this is the (p->p2) vector for the other bendline with respect to this flange.// this is used when a line is adjacent to a bendline, to compute the p2 point for // the flange dimension point.BM_LINE adj_bend_p2_line ; // this is the left-right-p2 line, of the adjacent bendline,// with respect to this flange.// this is used when a line is adjacent to a bendline, to computethe p2 point for // the flange dimension point.double bend_arc_outside_length_proj ; // bendline arc outside length projected onto our plane/*表面のタイプを操作する。*/if (surface->is(BM_TYPE_PLANE)) goto handle_planes ;/*********** ********** ********** ********** ********** ******************** ********** ********** 一時的拘束:我々は単に平面である表面を操作する。TODO:他の表面タイプを操作する。********** ********** ********** ********** ********** ********** ********** ********** ***********///unknown surfacereturn 0 ;/*ここで、平面を操作する。*/handle_planes : BM_PLANE *plane = (BM_PLANE *) surface ;// we assume that the reference point correctly defines the plane (which is parallel to our plane)// thatis the OUTSIDE plane.// check if reference point is on our plane. If not(in that case our plane represents the INSIDE// plane) compute a translation vector for moving from our plane to reference plane,// and move the reference point to our plane.rv = plane->get_normal() ;rv.normalise();temp_v = rp - (plane->get_pt()) ;temp_x = temp_v % rv ;if (fabs(temp_x)> AUTODIM_DISTANCE_TOLERANCE) {// ok, need to translate all dimension points. reference point not on the plane.ref_vector_valid = 1 ;rv.set_length(temp_x) ;rp = rp + (-rv) ;}else rv = BM_null_vector ;// compute right- and left-side opening vectors.right_opening_direction = side_vector *(plane->get_normal()) ;right_opening_direction.normalise() ;left_opening_direction = -(right_opening_direction) ;/*********** ********** ********** ********** ********** ********** ********** ********** **********この関数の主要部分。adj_bodyの束縛ループを掃引し、ディメンションポイントを構成する。所与のラインから最も遠く離れたエッジはbloop内になければならないので我々は単にbloopを掃引する必要がある点に注意されたい。******************** ********** ********** ********** ********** ********** ********** ********** 注意:ディメンションリストが開放のとき、生成される最後の右-側ディメンションポイントは、ループの始めにおいて現在のエッジの開始-点から異なっていなければならない。********** ********** ********** ********** ********** ********** ********** ********** ********** */// scan alledges in the bloop// first, we have a problem where to start scanning.// if we start from the first edge, we basically start from an arbitraryedge.// this might not be good since we might create dimension points wedon’t really want.// therefore we will find an edge that is adjacent to our bendline and start from that and// finish when we get back to it.BM_EDGE *start_edge, *stop_edge, *next_edge ;for (start_edge = bloop->get_first_edge() ; start_edge ; start_edge = (BM_EDGE *) start_edge->next()) {if (start_edge->get_adj_body() == bend) break ; // edge adjacent to this bendline is a good start-edgeelse if (! start_edge->is(BM_ENTITY_TYPE_LINE)) break ; // any non-line is a good start-edgeelse { // any linethat will be ignored is also a good place to starttemp_v = (((BM_LINE *)start_edge)->get_v()) * side_vector ;// in these two cases this line will be ignoredif (temp_v.Len() <= AUTODIM_DISTANCE_TOLERANCE) break ; //line parallel to the side-vectorif ((temp_v % plane->get_normal()) > 0.0) break ; // material "above" the line}}if (NULL == start_edge) {*list_of_points = NULL ;return 1 ;}// this is the main loop.// initially we setstop_edge to NULL. we would like to set it to start-edge, but we cannot,// because in that case we would never enter the loop. therefore we setit to NULL and right // after we enter the loop, we set it to start_edge.// (this is important in the case when the loop consists of only one circle).stop_edge = NULL ;for (edge = start_edge ; edge != stop_edge ; edge = next_edge) {stop_edge = start_edge ;// compute the next edge we will scannext_edge = (BM_EDGE *) edge->next() ;if (NULL == next_edge) next_edge = bloop->get_first_edge() ;switch (edge->get_type()) {case BM_ENTITY_TYPE_LINE : { // compute distance for start- and end-points// first, we want to ignore lines that are parallel to the side-vector.// we also want to ignore lines that have material "above" them when looking in the// side-vector direction (because they cannot have to largest width, since material is// "above" them, there must be some other edge bounding thebody from above).temp_v = (((BM_LINE *) edge)->get_v()) * side_vector ;if (temp_v.Len() <= AUTODIM_DISTANCE_TOLERANCE) continue ; // line parallel to the side-vectorif ((temp_v % plane->get_normal()) > 0.0) continue; // material "above" the line// note that this leaves only lines whosedirection-vector goes to the "left"// of the side-vector.// we need tocheck if this line is adjacent to a bendlineab = edge->get_adj_body() ;// check if this line is adjacent to a valid bendline (ie. one that is not the // bendline associated with this BM_AD_bendline object).d1 = d2 =bend_arc_outside_length_proj = 0.0 ;if (ab && ab != bend && ab->is(BM_ENTITY_TYPE_BENDLINE)) {// check if the bendline is being bentbop = ((BM_BENDLINE *) ab)->get_bend_op() ;if ((parent->get_view_type()) /* have tohave a 3D view */ && ((BM_BENDLINE *) ab)->get_bending_status() && bop){// a problem : it could be that the bendline is not perpendicular to the side-vector.// in that case we need to project the bend-arc-approximation-value onto the side-vector.// for example, if the bendline is parallel to the side-vector, we should not add// the approximation value at all, since it plays no role in the width computation.temp_x = side_vector^ (((BM_LINE *) edge)->get_v()) ; // temp_x is "angle_factor"if (temp_x> PI_over_2) temp_x = PI - temp_x ;temp_x = sin(temp_x) ;switch (bop->get_type()) {case BM_TYPE_BEND_OP_REGULAR :bend_arc_outside_length_proj =((BM_BEND_OP_REGULAR *) bop)->compute_3D_outside_approx_per_side() ;d1 =temp_x*bend_arc_outside_length_proj ;d2 = d1 ; // d2 is the same as d1!break ;// TODO : implement more bend operations here.default : ; // unknown bend op}// compute some needed parameters// compute : direction ofthe bend arc projected onto our planebend_arc_direction = (((BM_LINE *)edge)->get_v()) * plane->get_normal() ;bend_direction = parent->compute_bend_direction_vector((BM_BENDLINE *) ab, adj_body, &adj_bend_p2_line) ;}}else ab = NULL ; // make sure ab does not point to anything we don’twant to.// handle two cases separately - depending on whether the dimension list is open or not.if (fl_dim_open) {// if the dimension is open, we don’t need to check the start-point of the line,// since it is at theflange length distance anyway.// // first we will check if the line isperpendicular to the side-vectorif (fabs(side_vector % ((BM_LINE *) edge)->get_v()) > AUTODIM_DISTANCE_TOLERANCE) {// not perpendicular.// thisline has to be "coming down" (because it is not perpendicular to the// side-vector and the dimension is open, ie. it cannot be "going up").// now we have to close the dimension by creating a left-hand-side dimensionpoint// from the start-point of the line.if (temp_dp = create_dim_point(bend_arc_outside_length_proj, ((BM_LINE *) edge)->get_startpt(), rv, left_opening_direction, 0, this, adj_body, list_of_points, side_vector, d1,bend_arc_direction, bend_direction, (BM_BENDLINE *) ab, adj_bend_p2_line)) {list_of_points = &(temp_dp->next) ;}fl_dim_open = 0 ;}else {// is perpendicular.// here we need to check the type of the next edge.// if itis not line, we need to close the dimension here by creating // a left-hand-side dimension point from the end-point of the line.// if the nextedge is a line, we can just continue.if (leave_dimension_open(edge,bloop,side_vector,plane->get_normal())) break ;if (temp_dp = create_dim_point(bend_arc_outside_length_proj, ((BM_LINE *) edge)->get_endpt(), rv, left_opening_direction, 0, this, adj_body, list_of_points, side_vector, d1,bend_arc_direction, bend_direction, (BM_BENDLINE *) ab, adj_bend_p2_line)) {list_of_points = &(temp_dp->next) ;}// ok, close the dimension.fl_dim_open = 0 ;// this is a small trick that will save us some time.// if the next edge is a line that will be ignored, we can skip is right now here.if (next_edge->is(BM_ENTITY_TYPE_LINE) && next_edge != stop_edge) {next_edge = (BM_EDGE *) edge->next() ;if (NULL == next_edge) next_edge = bloop->get_first_edge() ;}}break ;}if (! compute_distance_from_ref_point(rp, side_vector, edge->get_edge_startpoint(), distance1)) continue ;if (! compute_distance_from_ref_point(rp, side_vector, edge->get_edge_endpoint(), distance2)) continue ;td1 = distance1 + d1 ;td2 = distance2 + d2 ;// check if the start-point is a flange dimension pointif (fabs(td1 - flange_length) <= AUTODIM_DISTANCE_TOLERANCE) {// check if the second point is a flange dimension pointif (fabs(td2 - flange_length) > AUTODIM_DISTANCE_TOLERANCE) {// only start-point is a flange dimension point.// create a left-right (ie. in both directions) flange dim point and continue.if (temp_dp = create_dim_point(bend_arc_outside_length_proj, ((BM_LINE *) edge)->get_startpt(), rv,!160#right_opening_direction, 1, this, adj_body,list_of_points, side_vector, d1, bend_arc_direction, bend_direction, (BM_BENDLINE *) ab, adj_bend_p2_line)) {list_of_points = &(temp_dp->next) ;}break ;}// else open the dimension list// create right flange dimensionpoint from start-pointif (temp_dp = create_dim_point(bend_arc_outside_length_proj, ((BM_LINE *) edge)->get_startpt(), rv, right_opening_direction, 0, this, adj_body, list_of_points, side_vector, d1, bend_arc_direction, bend_direction, (BM_BENDLINE *) ab, adj_bend_p2_line)) {list_of_points = &(temp_dp->next) ;}// check if we can leave the dimension list openand continueif (leave_dimension_open(edge,bloop,side_vector,plane->get_normal())) {fl_dim_open = 1 ;break ;}// create left flange dim point from end-point.if (temp_dp = create_dim_point(bend_arc_outside_length_proj,((BM_LINE *) edge)->get_endpt(), rv, left_opening_direction, 0, this, adj_body, list_of_points, side_vector, d1, bend_arc_direction, bend_direction, (BM_BENDLINE *) ab, adj_bend_p2_line)) {list_of_points = &(temp_dp->next) ;}// ok, close the dimension list.fl_dim_open = 0 ;// this is asmall trick that will save us some time.// if the next edge is a line that will be ignored, we can skip is right now here.if (next_edge->is(BM_ENTITY_TYPE_LINE) && next_edge != stop_edge) {next_edge = (BM_EDGE *) edge->next() ;if (NULL == next_edge) next_edge = bloop->get_first_edge() ;}break ;}else if (fabs(td2 - flange_length) > AUTODIM_DISTANCE_TOLERANCE){// the start-point is not a flange dimension point// if the end-pointis also not a flange dimension point, we can continue.continue ;}// ok,only the end-point is a flange dimension point.// two possibilities. ifwe can leave the dimension list open (right now dimension is // closed!)we don’t even have to open it, we can just continue.if (leave_dimension_open(edge,bloop,side_vector,plane->get_normal())) break ;// second possibility. now we have to create a left-right flange dimension point.// dimension list stays closed.if (temp_dp = create_dim_point(bend_arc_outside_length_proj, ((BM_LINE *) edge)->get_endpt(), rv, right_opening_direction, 1, this, adj_body, list_of_points, side_vector, d1, bend_arc_direction, bend_direction, (BM_BENDLINE *) ab, adj_bend_p2_line)) {list_of_points = &(temp_dp->next) ;}// this is a small trick that will save us some time.// if the next edge is a line that will be ignored, we can skip is right now here.if (next_edge->is(BM_ENTITY_TYPE_LINE) && next_edge !=stop_edge) {next_edge = (BM_EDGE *) edge->next() ;if (NULL == next_edge)next_edge = bloop->get_first_edge() ;}}break ;case BM_ENTITY_TYPE_ARC :{// note : we can always ignore the start-point of the arc !// becauseof the way we keep track of the open dimension list.// make sure the dimension list will be closed.fl_dim_open = 0 ;// first, compute start- andend-angles of the arc with respect to the side vector.// ie. convert start- and end-angles so as if the side-vector was the 0-angle vector.double startang = ((BM_ARC *) edge)->get_startang() ;double endang = ((BM_ARC *) edge)->get_endang() ;temp_v = side_vector*(((BM_ARC *) edge)->get_vx()) ;double delta_angle = (temp_v.Len())/(((BM_ARC *) edge)->get_rad());if (delta_angle < -1.0) delta_angle = -1.0 ;else if (delta_angle > 1.0) delta_angle = 1.0 ;delta_angle = asin(delta_angle) ;if (fabs((((BM_ARC*) edge)->get_normal())%temp_v) > 0.0) {startang += delta_angle ;endang+= delta_angle ;if (startang > PI_times_2) startang -= PI_times_2 ;if (endang > PI_times_2) endang -= PI_times_2 ;}else {startang -= delta_angle ;endang -= delta_angle ;if (startang < 0.0) startang += PI_times_2 ;if(endang < 0.0) endang += PI_times_2 ;}// compute the extreme pointBM_POINT arc_extreme_point ;// 0-angle point is the extreme pointif (endang <startang) arc_extreme_point = ((BM_ARC *) edge)->get_center() + (((BM_ARC *) edge)->get_rad())*side_vector ;else arc_extreme_point = *(((BM_ARC*) edge)->get_edge_endpoint()) ;// check the distance of the extreme pointif (! compute_distance_from_ref_point(rp, side_vector, &arc_extreme_point, distance1)) continue ;if (fabs(distance1 - flange_length) <= AUTODIM_DISTANCE_TOLERANCE) {// if we have the 0-angle point, create a left-right flange dimension point.// otherwise if next line is a non-ignored line, don’t do anything,// otherwise create a left-right flange dimension point.if (endang >= startang && leave_dimension_open(edge,bloop,side_vector,plane->get_normal())) {continue ;}// create a left-right flange dimension point. dimension list stays closed.// this is a 1-point flange dimension point.if (temp_dp = new BM_AD_dim_corner(rv + arc_extreme_point, this, adj_body,right_opening_direction, 1, list_of_points, NULL)) {list_of_points = &(temp_dp->next) ;}}}break ;case BM_ENTITY_TYPE_CIRCLE : // circles are a much simpler version of the arc case.{BM_POINT circle_extreme_point = ((BM_CIRCLE *) edge)->get_center() + (((BM_CIRCLE *) edge)->get_rad())*side_vector ;// we won’t check the distance since it mustbe a flange dimension point// create a left-right flange dimension point.// this is a 1-point flange dimension point.if (temp_dp = new BM_AD_dim_corner(rv + circle_extreme_point, this, adj_body,right_opening_direction, 1, list_of_points, NULL)) {list_of_points = &(temp_dp->next) ;}}break;case BM_ENTITY_TYPE_ELLIPSE : // TODO : implement ellipse here. shouldbe similar to the way arc is handled.continue ;break ;default : continue ; // unknown edge type}}/* OK、全て終了。*/*list_of_points = NULL ;return 1 ;}/*この関数は1つのBM_AD_bendline構造に対するベンドラインディメンションポイントを計算する。注意: p1は、フランジ長が描かれる隣接体の平面上にある。pはセンタポイントである。 p2はベンドラインの側部のポイントである。注意:この関数においては、我々は常にadj-body1およびadj-body2に対するベンド-ディメンションポイントを計算する。このベンドラインは1または0の隣接体を持つことになるが、我々は将来これらのポイントのビジビリテイを知る必要がある。*/int BM_AD_bendline::compute_BM_AD_bendline(void){double metal_thickness ; // thickness of the sheetmetalBM_2D_BODY *bendline_displayed_version ; // 3D-version of the bendlineBM_VECTOR temp_v ; // vectorused for very short periods for storing temporary stuff// initally markthe bendline data as invalid, in case we fail here.data_valid = 0 ;// qualification checkif (NULL == bend) return 0 ;if (NULL == bend->get_adj_list()) return 0 ;if (NULL == bend->get_part()) return 0 ;// this bendline has to have a 3D-versionif (parent->get_view_type()) {if (NULL == (bendline_displayed_version = bend->get_current_3D_version())) return 0 ;}else {if (NULL == (bendline_displayed_version = bend->get_flat())) return0 ;}metal_thickness = (bend->get_part())->get_metal_thickness() ;/* ********** ********** ********** ********** ********** ********** ********** ********** **********これは一時的な測度である。我々は単に規則的なベンドラインを処理する。すなわち、円錐ベンドラインは無視する。03/16/96. KK.*/if (bend->get_bending_status() && bend->get_bend_op() && ! (bend->get_bend_op())->is(BM_TYPE_BEND_OP_REGULAR)) return 0 ;/* ********** ********** ********** ********** ********** ********** ********** ********** ********** */// get the number of adjacent bodies.adj_body1 = (bend->get_adj_list())->find_lowest_id_adj_body() ;adj_body2 = (bend->get_adj_list())->find_second_lowest_id_adj_body() ;num_of_adjacent_bodies = (adj_body1? 1 : 0) + (adj_body2 ? 1 : 0) ;/*サイドベクトルを計算する。*/if (adj_body1) {if (! bendline_displayed_version->compute_vector_perp_towards_adj_body(adj_body1, side_vector1)) return 0 ;side_vector1.normalise() ;}if(adj_body2) {if (! bendline_displayed_version->compute_vector_perp_towards_adj_body(adj_body2, side_vector2)) return 0 ;side_vector2.normalise();}/*ベンドラインディメンションポイントを計算する。*/if (! bend->get_bending_status() /* bendline not bent */ || ! parent->get_view_type() /* flat view */) {// note : here we don’t know whether the dimension point is OUTSIDE or INSIDE.// this has to be taken into account later.// however, it should work either way.bend_body1_point_left.num_of_points = bend_body1_point_right.num_of_points = 1 ;bend_body1_point_left.can_reverse_opening_dir = bend_body1_point_right.can_reverse_opening_dir = 0 ;bend_body1_point_left.p = (bendline_displayed_version->get_current_center_line()).get_startpt() ;bend_body1_point_right.p = (bendline_displayed_version->get_current_center_line()).get_endpt() ;// note opening directions. left will get start-point, right will get end-point, ie. vector goes left->right.bend_body1_point_right.opening_direction = (bendline_displayed_version->get_current_center_line()).get_v() ;(bend_body1_point_right.opening_direction).normalise() ;bend_body1_point_left.opening_direction = -(bend_body1_point_right.opening_direction) ;// points with respect to bothadjacent bodies are the samebend_body2_point_left.num_of_points = bend_body2_point_right.num_of_points = 1 ;bend_body2_point_left.can_reverse_opening_dir = bend_body2_point_right.can_reverse_opening_dir = 0 ;bend_body2_point_right.opening_direction = bend_body1_point_right.opening_direction ;bend_body2_point_left.opening_direction = bend_body1_point_left.opening_direction ;bend_body2_point_left.p = bend_body1_point_left.p ;bend_body2_point_right.p = bend_body1_point_right.p ;}else {// first, get some bending parametersBM_SURFACE *surface = bendline_displayed_version->get_surface() ;if (NULL == surface) return 0 ;BM_BEND_OP *bop = bend->get_bend_op() ;if (NULL == bop) return 0 ;double bend_angle = bop->get_bend_angle2() ;double bend_arc_angle = PI - bend_angle ;double half_bend_arc_angle = bend_arc_angle/2.0 ;switch (surface->get_type()) {case BM_TYPE_CYLINDER : { // note that the bend op can be both regular and conicBM_CYLINDER *cylinder = (BM_CYLINDER *) surface ;double radius = cylinder->get_rad() ;double outside_radius = radius ;if (bendline_displayed_version->get_sense()) outside_radius += metal_thickness ;// set some common valuesbend_body1_point_left.can_reverse_opening_dir = bend_body1_point_right.can_reverse_opening_dir = 0 ;bend_body1_point_right.opening_direction =(bendline_displayed_version->get_current_center_line()).get_v() ;(bend_body1_point_right.opening_direction).normalise() ;bend_body1_point_left.opening_direction = -(bend_body1_point_right.opening_direction) ;if (outside_radius <= AUTODIM_DISTANCE_TOLERANCE) {// special case : outside radius 0 - trivial dimension point.bend_body1_point_left.num_of_points = bend_body1_point_right.num_of_points = 1 ;bend_body1_point_left.p = (bendline_displayed_version->get_current_center_line()).get_startpt() ;bend_body1_point_right.p = (bendline_displayed_version->get_current_center_line()).get_endpt() ;bend_body2_point_left.num_of_points = bend_body2_point_right.num_of_points = 1 ;bend_body2_point_left.can_reverse_opening_dir= bend_body2_point_right.can_reverse_opening_dir = 0 ;bend_body2_point_right.opening_direction = bend_body1_point_right.opening_direction ;bend_body2_point_left.opening_direction = bend_body1_point_left.opening_direction ;bend_body2_point_left.p = bend_body1_point_left.p ;bend_body2_point_right.p = bend_body1_point_right.p ;}else {bend_body1_point_left.num_of_points = bend_body1_point_right.num_of_points = 3 ;// compute points p1 for adj_body1bend_body1_point_left.p1 = (bendline_displayed_version->get_current_center_line()).get_startpt() ;bend_body1_point_right.p1 = (bendline_displayed_version->get_current_center_line()).get_endpt() ;// theproblem now is that it could be that these centerline points (which are// on the surface of the bendline), could be only inside surface of thebendline.if (bendline_displayed_version->get_sense() && metal_thickness> AUTODIM_DISTANCE_TOLERANCE) {temp_v = cylinder->get_vx() ;temp_v.set_length(metal_thickness) ;bend_body1_point_left.p1 = bend_body1_point_left.p1 + temp_v ;bend_body1_point_right.p1 = bend_body1_point_right.p1 + temp_v ;}// a break in the computation of adj_body1.p1.// store current p1values for adj_body2 as well. this will save some time.// // note thatwe should not really compute adj_body2 points unless adj_body2 pointer//is not NULL. However, this point (adj_body2.p1) is very useful for computing// adj_body1.p2 (if angle is acute). so we compute it anyway.bend_body2_point_left.p1 = bend_body1_point_left.p1 ;bend_body2_point_right.p1= bend_body1_point_right.p1 ;// finish adj_body1.p1. rotate points p1 into their final correct location.// note we rotate in the negative direction since adj_body1 is the smallest-index// adjacent body as is "to-the-left-of-the-bendline-centerline", which means// rotating to the left.//first, compute the right vector for the rotation line.BM_VECTOR rot_v(cylinder->get_v()) ;if (rot_v % ((bendline_displayed_version->get_current_center_line()).get_v()) < 0.0) {rot_v.reverse() ;}BM_rotate_point_around_line(&(bend_body1_point_left.p1), cylinder->get_pt1(), rot_v, -half_bend_arc_angle) ;BM_rotate_point_around_line(&(bend_body1_point_right.p1),cylinder->get_pt1(), rot_v, -half_bend_arc_angle) ;// finish also adj_body2.p1. rotate points p1 into their final correct location.BM_rotate_point_around_line(&(bend_body2_point_left.p1), cylinder->get_pt1(), rot_v,half_bend_arc_angle) ;BM_rotate_point_around_line(&(bend_body2_point_right.p1), cylinder->get_pt1(), rot_v, half_bend_arc_angle) ;// compute points p for adj_body1.double x ;if (bop->is(BM_TYPE_BEND_OP_REGULAR)) {x= ((BM_BEND_OP_REGULAR *) bop)->compute_3D_outside_approx_per_side() ;}else if (bop->is(BM_TYPE_BEND_OP_CONIC)) {// TODO : implement conic bendline herereturn 0 ;}temp_v = -x*side_vector1 ;bend_body1_point_left.p = bend_body1_point_left.p1 + temp_v ;bend_body1_point_right.p = bend_body1_point_right.p1 + temp_v ;// note : adj_body1.p2 and adj_body2.p, adj_body2.p2 are yet to be computed.// now there are two cases : 1) the bend arc angle is acute (ie. no more than 90 degrees),// 2) the bend arc angleis more than 90 degrees.if (bend_arc_angle > (PI_over_2 + BM_ANGLE_TOLERANCE)) { // use tangent approximation// we will finish computing adj_body1. adj_body1.p2 is left.// idea : notice that adj_body1 is to the leftof the bendline-centerline// because it is the lowest-index neighbor. Therefore the cross-product// of centerline-v by temp_v points towards thecylinder (actually it is tangent// to the cylinder).BM_VECTOR tangent_v(bend_body1_point_right.opening_direction * temp_v) ;tangent_v.set_length(x) ;bend_body1_point_left.p2 = bend_body1_point_left.p + tangent_v ;bend_body1_point_right.p2 = bend_body1_point_right.p + tangent_v ;// noteadj_body2.p1 is already computed. first set some common values.bend_body2_point_left.num_of_points = bend_body2_point_right.num_of_points = 3 ;bend_body2_point_left.can_reverse_opening_dir = bend_body2_point_right.can_reverse_opening_dir = 0 ;bend_body2_point_right.opening_direction = bend_body1_point_right.opening_direction ;bend_body2_point_left.opening_direction = bend_body1_point_left.opening_direction ;// now compute adj_body2.ptemp_v = -x*side_vector2 ;bend_body2_point_left.p = bend_body2_point_left.p1 + temp_v ;bend_body2_point_right.p = bend_body2_point_right.p1+ temp_v ;// finally, compute adj_body2.p2// note the order in the cross-product !tangent_v = temp_v * bend_body2_point_right.opening_direction; tangent_v.set_length(x) ;bend_body2_point_left.p2 = bend_body2_point_left.p + tangent_v ;bend_body2_point_right.p2 = bend_body2_point_right.p+ tangent_v ;}else { // use intersection approximation// note : adj_body2.p2 is the same as asj_body1.p1.bend_body1_point_left.p2 = bend_body2_point_left.p1 ;bend_body1_point_right.p2 = bend_body2_point_right.p1 ;//when using intersection approximation, dimensions points with respect to// both adjacent bodies are the same, so we just copy them.bend_body2_point_left.num_of_points = bend_body2_point_right.num_of_points = 3 ;bend_body2_point_left.can_reverse_opening_dir = bend_body2_point_right.can_reverse_opening_dir = 0 ;bend_body2_point_right.opening_direction = bend_body1_point_right.opening_direction ;bend_body2_point_left.opening_direction = bend_body1_point_left.opening_direction ;// note we are switchingpointsbend_body2_point_left.p2 = bend_body1_point_left.p1 ;bend_body2_point_right.p2 = bend_body1_point_right.p1 ;bend_body2_point_left.p = bend_body1_point_left.p ;bend_body2_point_right.p = bend_body1_point_right.p ;}}}break ;case BM_TYPE_CONE :break ;default : ; // unknown or illegalsurface ;}}/*隣接体の各々に対するフランジ長を計算する。*/if (adj_body1){// if the flange length computation fails, pretend the adjacent body does not exist. for simplicity.if (! bend->compute_flange_length(parent->get_view_type(),adj_body1,fl1)) {adj_body1 = NULL ;--num_of_adjacent_bodies ;}}if (adj_body2) {if (! bend->compute_flange_length(parent->get_view_type(),adj_body2,fl2)) {adj_body2 = NULL ;--num_of_adjacent_bodies ;}}/*よし、データを有効なものとしてマークする。ベンドラインディメンションポイントが全てのベンドラインに対して計算されると、我々は同様に巣手のベンドラインに対してフランジディメンションポイントを計算することが出来る。*/data_valid = 1 ;// before we can return, we have to check if body1,2 left(right) bendline dimension points // are the same.// note the same meansnot the same pointers, but the contents are equivalent.if (adj_body1 &&adj_body2) {body12_left_the_same = (bend_body1_point_left == bend_body2_point_left) ;body12_right_the_same = (bend_body1_point_right == bend_body2_point_right) ;}/*重要:ベンド-ディメンションポイントのいずれかが1ポイント(ポイントp)のみを含むときは、実際には見るべきベンドラインがないのでbody_required_visibleポインタは隣接体を指示するべきである。*/if (1 ==bend_body1_point_left.num_of_points) bend_body1_point_left.body_required_visible = adj_body1 ;if (1 == bend_body1_point_right.num_of_points) bend_body1_point_right.body_required_visible = adj_body1 ;if (1 == bend_body2_point_left.num_of_points) bend_body2_point_left.body_required_visible= adj_body2 ;if (1 == bend_body2_point_right.num_of_points) bend_body2_point_right.body_required_visible = adj_body2 ;return 1 ;}/*********** ********** ********** ********** ********** ********** ********** ********** **********BM_AUTO_DIMENSION class stuff.********** ********** ********** ********** ********** ********** ********** ********** ***********//*確実な発見的手法:ソリッドモードにおいて幾つかのポイントを我々が無視出来るか否かをチェックする。ソリッドモードにおいては、我々は時間の節約のためにこの発見的手法を用いている。2つのベンドラインがフランジ-長を表示するために(潜在的に)等価なフランジ-ディメンションポイントを用いているときは、我々は単に、より高いidxを持つベンドライン(これらの2つのベンドラインに対する)に対してのみビジビリテイ情報を計算する。*/void BM_AUTO_DIMENSION::compute_points_to_ignore_in_solid(void){int i ;BM_AD_dim_corner*temp_point ;for (i = 0 ; i < num_of_bendlines ; i++) {if (! bends[i]->data_valid) continue ;if (bends[i]->adj_body1) {for (temp_point = bends[i]->body1_points ; temp_point ; temp_point = temp_point->next) {if (NULL== temp_point->adj_bendline) continue ;if ((temp_point->adj_bendline)->get_idx() > (bends[i]->bend)->get_idx()) continue ;if (check_two_bendlines_adjacent_to_same_flange(bends[i]->bend,bends[i]->adj_body1,temp_point->adj_bendline)) {temp_point->ignore_in_solid_mode = 1 ;}}}if (bends[i]->adj_body2) {for (temp_point = bends[i]->body2_points ; temp_point ; temp_point = temp_point->next) {if (NULL == temp_point->adj_bendline) continue ;if ((temp_point->adj_bendline)->get_idx() > (bends[i]->bend)->get_idx()) continue ;if (check_two_bendlines_adjacent_to_same_flange(bends[i]->bend,bends[i]->adj_body2,temp_point->adj_bendline)) {temp_point->ignore_in_solid_mode = 1 ;}}}}points_to_ignore_in_solid_computed = 1 ;}/*この関数は自動寸法化ベンドラインを構成し、データ構造を指示する。これはディメンションポイントを計算する主要関数である。*/int BM_AUTO_DIMENSION::compute_auto_dimension_data(void){int i ;// have to have a documentif (NULL == doc) return 0 ;// if no part, try to get a new part from the documentif (NULL == part) {set_part(doc->get_part()) ;}if (NULL == part) {dirty =0 ;return 1 ;}points_to_ignore_in_solid_computed = 0 ;/*ビユータイプを得る。*/if (view) {view_type = view->get_current_view() ;}else {// we are screwedreturn 0 ;}/*全てのベンドラインに対して全てのベンドラインディメンションポイントを計算する。*/for (i = 0 ; i < num_of_bendlines ; i++) {bends[i]->compute_BM_AD_bendline() ;}/*全てのベンドラインに対してフランジディメンションポイントを計算する。*/for (i = 0 ; i < num_of_bendlines; i++) {if (bends[i]->data_valid) {if (bends[i]->adj_body1) bends[i]->compute_BM_AD_flange_points(bends[i]->adj_body1) ;if (bends[i]->adj_body2)bends[i]->compute_BM_AD_flange_points(bends[i]->adj_body2) ;}}dirty = 0;return 1 ;}
付録I
幾つかの基本的自動寸法化関数、コンストラクタ、デストラクタおよび幾つかの他の基本的関数の例
//#include "stdafx.h"#include "BendCAD.h"#include "BendCADDoc.h"#include"BendCADViewPart.h"#include "AUTODIM.HXX"/*********** ********** ********** ********** ********** ********** ********** ********** **********BM_AD_dim_corner class stuff.********** ********** ********** ********** ********** ********** ********** ********** ***********/BM_AD_dim_corner::BM_AD_dim_corner(void) {visible = -1 ;num_of_points = 0 ;bend = NULL ;next = NULL ;adj_bendline = NULL ;body_required_visible = NULL ;ignore_in_solid_mode = 0 ;}/*このコンストラクタは中にただ1つのポイント(ポイントp)を持つディメンションポイントを生成するためのものである。*/BM_AD_dim_corner::BM_AD_dim_corner(BM_POINT const& P, BM_AD_bendline *B, BM_3D_BODY*Body_required_visible,BM_VECTOR const& OD, int RB, BM_AD_dim_corner **prev, BM_BENDLINE *adj_bend){visible = -1 ;num_of_points = 1 ;p = P ;bend = B ;opening_direction = OD ;can_reverse_opening_dir = RB ;next = NULL;body_required_visible = Body_required_visible ;adj_bendline = adj_bend;ignore_in_solid_mode = 0 ;if (prev) *prev = this ;}/*このコンストラクタは中に3ポイントを持つディメンションポイントを生成するためのものである。*/BM_AD_dim_corner::BM_AD_dim_corner(BM_POINT const& P, BM_POINT const& P1, BM_POINT const& P2, BM_AD_bendline *B, BM_3D_BODY *Body_required_visible,BM_VECTOR const& OD, int RB, BM_AD_dim_corner **prev, BM_BENDLINE*adj_bend){visible = -1 ;num_of_points = 3 ;p = P ;p1 = P1 ;p2 = P2 ;bend = B ;opening_direction = OD ;can_reverse_opening_dir = RB ;next = NULL ;body_required_visible = Body_required_visible ;adj_bendline = adj_bend ;ignore_in_solid_mode = 0 ;if (prev) *prev = this ;}/*1つのディメンションポイントを他のディメンションポイントに割り当てる。この関数は内容を正確にコピーする。それが非常に有用な関数であるか否かは確実ではない。*/voidBM_AD_dim_corner::operator=(BM_AD_dim_corner const& given_point){num_of_points = given_point.num_of_points ;p = given_point.p ;p1 = given_point.p1 ;p2 = given_point.p2 ;bend = given_point.bend ;opening_direction = given_point.opening_direction ;can_reverse_opening_dir = given_point.can_reverse_opening_dir ;visible = given_point.visible ;screen_x = given_point.screen_x ;screen_y = given_point.screen_y ;z_buf_value = given_point.z_buf_value ;ignore_in_solid_mode = given_point.ignore_in_solid_mode ;}/*この関数は、もしディメンションを描くために所定のポイントがこのポイントと同じときはTRUEを戻す。2つのディメンションポイントは、それらの1つのポイントpが他のディメンションポイントのライン(ポイントp,開放方向)により定義されるライン上にあるとき、またそれらの開放方向が一致するとき、等価である。ここで我々は、開放ベクトルが規格化されるという事実に依存する。it returns 2 iff both points p match, otherwise 1.*/int BM_AD_dim_corner::operator==(BM_AD_dim_corner const& another_dim_point){int ret_val = 1 ;double k ;if (num_of_points < 1 || another_dim_point.num_of_points < 1) return 0 ;// point has to be on the lineif (! BM_is_point_on_line(p, opening_direction, another_dim_point.p, &k)) return 0 ;if (fabs(k) <= BM_PRECISION) ret_val = 2 ;// since both vectors should be normalized, the dot-product is the cos of the angle.double x = opening_direction % another_dim_point.opening_direction ;// check if both vectors agreeif (x > 0.99) return ret_val ;// check if they have opposite direction and one of the can be reversedif (x < -0.99) {if (can_reverse_opening_dir || another_dim_point.can_reverse_opening_dir) return ret_val ;}return 0 ;}/********************* ********** ********** ********** ********** ********** ********** **********BM_AD_bendline class stuff.********** ********** ********** ********** ********** ********** ********** ********** ***********/BM_AD_bendline::BM_AD_bendline(BM_AUTO_DIMENSION *owner, BM_BENDLINE *bendline){parent = owner ;bend = bendline ;data_valid = 0 ; // data not valid - no data computed yetbend_body1_point_left.bend = bend_body1_point_right.bend = this ;bend_body2_point_left.bend = bend_body2_point_right.bend = this ;bend_body1_point_left.body_required_visible = bend_body1_point_right.body_required_visible = bend ;bend_body2_point_left.body_required_visible = bend_body2_point_right.body_required_visible = bend ;body1_points = NULL ;body2_points = NULL ;}BM_AD_bendline::~BM_AD_bendline(void){BM_AD_dim_corner *temp_point, *temp_p ;// delete lists of pointsfor (temp_point = body1_points ; temp_point ; temp_point = temp_p) {temp_p = temp_point->next ;delete temp_point ;}for (temp_point = body2_points ; temp_point ; temp_point = temp_p) {temp_p = temp_point->next ;delete temp_point ;}}/*********** ********** ********** ********** ********** ********** ********** ********** **********BM_AUTO_DIMENSION class stuff.********** ********** ********** ********** ********** ********** ******************** ***********/BM_AUTO_DIMENSION::BM_AUTO_DIMENSION(CBendCADDoc*BendCAD_doc){doc = BendCAD_doc ;view = (CBendCADViewPart *) doc->get_view(BENDCAD_VIEW_TYPE_PART) ;dc = NULL ;part = NULL ;dirty = 1 ;view_type= 1 ; // 3D viewreset_view_to_false_once_drawn = 0 ;points_to_ignore_in_solid_computed = 0 ;num_of_bendlines = 0 ;bends = NULL ;// initialize show states for dimension infom_bShowFlangeDim = TRUE;m_bShowBendDim = TRUE;m_bShowPartDim = FALSE;// initialize Auto-Dim colorsm_crFlange = RGB(0,0,255);m_crBend = RGB(0,0,255);m_crPart = RGB(0,0,255);// initialize font pointersm_pFlangeFont = NULL;m_pBendFont = NULL;m_pPartFont = NULL;// initialize line and arrow stylesm_nLineStyle = PS_SOLID;m_nLineWeight= 1;// in pixelsm_nArrowStyle = 1;m_nArrowAngle = 30;// in degreesm_nArrowLength = 15;// in pixels// initialize dirty region pointerpDirtyRegion= NULL;}BM_AUTO_DIMENSION::~BM_AUTO_DIMENSION(void){delete_contents() ;}/*この自動-寸法化対象を破壊する。*/void BM_AUTO_DIMENSION::delete_contents(void){int i ;if (bends) {for (i = 0 ; i < num_of_bendlines ; i++) {if (bends[i]) delete bends[i] ;}delete [] bends ;bends = NULL ;}num_of_bendlines = 0 ;points_to_ignore_in_solid_computed = 0 ;part = NULL ;dirty= 1 ;}/*この関数は所定のベンドラインに係わるディメンションデータを含むBM_AD_bendline構造に対するポインタを戻す。*/BM_AD_bendline *BM_AUTO_DIMENSION::get_AD_bend_structure(BM_BENDLINE *bendline){int i ;for (i = 0 ; i< num_of_bendlines ; i++) {if (bends[i]->bend == bendline) return bends[i] ;}return NULL ;}/*この関数は所定のadj-bodyに対する所定のベンドラインに対する(p->p2)ベクトルを戻す。それはまたこのフランジに対する隣接ベンドラインのベンドディメンションポイントのp2ポイントの間のラインを計算する。*/BM_VECTOR const& BM_AUTO_DIMENSION::compute_bend_direction_vector(BM_BENDLINE *bendline, BM_3D_BODY *adj_body, BM_LINE *p2_line){static BM_VECTOR v ;int i ;for (i = 0 ; i < num_of_bendlines ; i++) {if (bends[i]->data_valid && bends[i]->bend == bendline) {if (bends[i]->adj_body1 == adj_body) {v = (bends[i]->bend_body1_point_left).p2 - (bends[i]->bend_body1_point_left).p ;p2_line->set((bends[i]->bend_body1_point_left).p2,(bends[i]->bend_body1_point_right).p2) ;return v ;}else if (bends[i]->adj_body2== adj_body) {v = (bends[i]->bend_body2_point_left).p2 - (bends[i]->bend_body2_point_left).p ;p2_line->set((bends[i]->bend_body2_point_left).p2,(bends[i]->bend_body2_point_right).p2) ;return v ;}}}return BM_null_vector ;}/*この関数は、フランジディメンションポイントが所定のadj-bodyに隣接するという事実を考慮するため所定のベンドラインに対するフランジ長を描く効果を伝搬させるために用いられる。それは、 adj-bendが所定のフランジに対して同様に描かれるものとしてマークされるときTRUEを戻す。*/int BM_AUTO_DIMENSION::compute_effects_flange_length_drawn(BM_BENDLINE *bendline, BM_3D_BODY *adj_body, BM_AD_dim_corner *bend_dim_point /* bend dim point for bendline */, BM_AD_dim_corner *flange_dim_point /* flange dim points forbendline */, BM_BENDLINE *adj_bend){BM_AD_dim_corner **p_body_points ;int *p_body_drawn ;BM_AD_dim_corner **p_drawn_bend_dim_point ;BM_AD_dim_corner **p_drawn_flange_dim_point ;int i ;// first we have to find a BM_AD_bendline structure for this adj-bendfor (i = 0 ; i < num_of_bendlines ;i++) {if (! bends[i]->data_valid || bends[i]->bend != adj_bend || bends[i]->ignore) continue ;if (bends[i]->adj_body1 == adj_body) {if (bends[i]->body1_drawn) return 0 ;p_body_points = &(bends[i]->body1_points) ;p_body_drawn = &(bends[i]->body1_drawn) ;p_drawn_bend_dim_point= &(bends[i]->drawn_bend_dim_point1) ;p_drawn_flange_dim_point= &(bends[i]->drawn_flange_dim_point1) ;break ;}else if (bends[i]->adj_body2 == adj_body) {if(bends[i]->body2_drawn) return 0 ;p_body_points = &(bends[i]->body2_points) ;p_body_drawn = &(bends[i]->body2_drawn) ;p_drawn_bend_dim_point = &(bends[i]->drawn_bend_dim_point2) ;p_drawn_flange_dim_point = &(bends[i]->drawn_flange_dim_point2) ;break ;}else return 0 ;}if (i >= num_of_bendlines) return 0 ;// now we need to check if the list of flange dimensionpoints for this newly found // BM_AD_bendline structure contains any flange dimension points that are adjacent to our bendlineBM_AD_dim_corner*temp_point ;for (temp_point = *p_body_points ; temp_point ; temp_point= temp_point->next) {if (temp_point->adj_bendline == bendline) break ;}if (NULL == temp_point) return 0 ;// mark the flange length for the adj-bend drawn with respect to this adj-body*p_body_drawn = 1 ;*p_drawn_bend_dim_point = flange_dim_point ;*p_drawn_flange_dim_point = bend_dim_point;return 1 ;}/*この関数は、 adj_bendが、所定のベンドラインに隣接する所定のフランジに対してフランジ-ディメンションポイントを持つときTRUEを戻す。*/int BM_AUTO_DIMENSION::check_two_bendlines_adjacent_to_same_flange(BM_BENDLINE *bendline, BM_3D_BODY *flange, BM_BENDLINE *adj_bend){BM_AD_dim_corner **p_body_points ;int i ;// first we have to find a BM_AD_bendlinestructure for this adj-bendfor (i = 0 ; i < num_of_bendlines ; i++) {if(! bends[i]->data_valid || bends[i]->bend != adj_bend) continue ;if (bends[i]->adj_body1 == flange) {p_body_points = &(bends[i]->body1_points);break ;}else if (bends[i]->adj_body2 == flange) {p_body_points = &(bends[i]->body2_points) ;break ;}else return 0 ;}if (i >= num_of_bendlines)return 0 ;// now we need to check if the list of flange dimension pointsfor this newly found // BM_AD_bendline structure contains a flange dimension points that is adjacent to our bendlineBM_AD_dim_corner *temp_point ;for (temp_point = *p_body_points ; temp_point ; temp_point = temp_point->next) {if (temp_point->adj_bendline == bendline) return 1 ;}return 0;}/*新しい部分を設定する。これは同様にビユークラスポインタを更新し、幾つかの他のパラメータを設定する。*/void BM_AUTO_DIMENSION::set_part(BM_PART *new_part){BM_BENDLINE *bendlist ;int i ;delete_contents() ;if (NULL== doc) return ;part = new_part ;if (NULL == part) return ;half_metal_thickness = (part->get_metal_thickness())/2.0 ;// allocate the bendlistif(0 == (num_of_bendlines = part->get_number_of_bendlines())) return ;if (NULL == (bends = new BM_AD_bendline*[num_of_bendlines])) goto failure ;bendlist = part->get_bendline_list() ;for (i = 0 ; i < num_of_bendlines ;i++) {if (bendlist) {bends[i] = new BM_AD_bendline(this,bendlist) ;bendlist = (BM_BENDLINE *) bendlist->next() ;}else bends[i] = NULL ;}// note, dirty is TRUEreturn ;failure :delete_contents() ;}
付録J
薄板部分に対するエンティティビジビリテイ関数を含むベンドモデルビユワ実施の例
#include "stdafx.h"// include all BMAPI files#include "ALLBMAPI.HXX"// RW_DRAW library include file.#include "RW_DRAW.HXX"#include "BendCADDoc.h"#include "BendCADViewPart.h"// RenderWare include files; 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> /* ワールド座標におけるポイントを表すBM_POINTが与えられると、人はそれをビユーウインド座標上に射影することが出来る。 A) Ifthe display is showing the SOLID version of the part, this function passes back a pointer to the edge closest to the camera that lies underthat projected point. The x_pos, y_pos, and z_depth pointers carry theview window coordinates (with top left corner as (0,0) and the z-buffervalue. If the projected point is not in the viewing volume, the return value is 0; then of course the edge pointer is meaningless, and is set to NULL. If the projected point IS within the viewing volume, then thereturn value is 1, and the edge pointer points to the edge that lies under the projected point. If the pointer is NULL, no edge lies under theprojected point. B) If the display is showing the WIREFRAME version ofthe part, only the return value: 1 if within view volume, 0 otherwise - should be examined. If return value is 1, x_pos, y_pos and z_depth values have meaning. The edge pointer is always NULL.*/int CBendCADViewPart::map_point_to_closest_edge(BM_POINT const& three_d_point, int *x_pos,int *y_pos, double *z_depth,BM_EDGE **closest_edge){ int x, y, visible = 1; double z; visible= map_3d_to_screen(three_d_point, &x, &y, &z); if( ! visible ) { // Point is outside viewing volume. if(closest_edge) *closest_edge = NULL;if(x_pos) *x_pos = x;if(y_pos) *y_pos = y;if(z_depth) *z_depth = z;return 0; } // Now point is inside view volume. if(x_pos) *x_pos = x; if(y_pos) *y_pos = y; if(z_depth) *z_depth = z; if(! mi_show_solid) { // Wireframe being drawn; just return that point is if(closest_edge) *closest_edge = NULL; // within view vol.return 1; } // Now solid is being shown. if(! closest_edge) return 1; //Point is within view volume. Pick that point. pick_point_rw(x, y, closest_edge); return 1;}// This function returns the view window coordinates of a point, with top left corner as (0,0), and the // z-buffer depth,given the three-dimensional world coordinates of the point. It does soby calling either // map_3d_to_screen_solid or map_3d_to_screen_wire, depending on whether wireframe or solid is being shown. // On return, iff*x_pos, *y_pos are both zero, the point was not mapped onto the screen at all.int CBendCADViewPart::map_3d_to_screen(BM_POINT three_d_point, int*x_pos, int *y_pos, double *z_depth){ int visible; if(mi_show_solid)visible = map_3d_to_screen_solid(three_d_point, x_pos, y_pos, z_depth); else visible = map_3d_to_screen_wire(three_d_point, x_pos, y_pos, z_depth); return visible;}// This function returns the view window coordinates of a point, with top left corner as (0,0), and the// z-buffer depth,given the three-dimensional world coordinates of the point, using OpenGL utilities // (ie. when wireframe is on). If return value is 0, point is not mapped onto screen, ie. not visible.int CBendCADViewPart::map_3d_to_screen_wire(BM_POINT three_d_point, int *x_pos, int *y_pos, double *z_depth){ int viewport[4], visible = 1; double width, height, depth;double model_mat[16], proj_mat[16], array[16]; // Get the current viewport coords. glGetIntegerv(GL_VIEWPORT, viewport); // Now build a modelview matrix out of the current set of transformations. glMatrixMode(GL_MODELVIEW); glPushMatrix(); 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()); glGetDoublev(GL_MODELVIEW_MATRIX, model_mat); glGetDoublev(GL_PROJECTION_MATRIX, proj_mat); glPopMatrix(); gluProject(three_d_point.X(), three_d_point.Y(), three_d_point.Z(), model_mat, proj_mat, viewport, &width, &height, &depth); if( ((int)width > m_old_rect.right) || ((int)width < 0) ) visible = 0; if( ((int)height > m_old_rect.bottom) || ((int)height < 0) ) visible = 0; if(x_pos) *x_pos = (int) width; if(y_pos) *y_pos = (m_old_rect.bottom - (int) height); if(z_depth) *z_depth = depth; return visible;} // This function returns the view window coordinates of a point, with top left corner as (0,0), and the// z-buffer depth, given the three-dimensional world coordinates of the point, using RenderWare utilities // (ie. when solid is on). If return value is 0, point is not mapped onto the screen, ie.not visible.// Note: At present, same as map_3d_to_screen_wire.int CBendCADViewPart::map_3d_to_screen_solid(BM_POINT three_d_point, int *x_pos,int *y_pos, double *z_depth){ int viewport[4], visible = 1; doublewidth, height, depth; double model_mat[16], proj_mat[16], array[16]; // Get the current viewport coords. glGetIntegerv(GL_VIEWPORT, viewport); // Now build a modelview matrix out of the current set of transformations. glMatrixMode(GL_MODELVIEW); glPushMatrix(); 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()); glGetDoublev(GL_MODELVIEW_MATRIX, model_mat); glGetDoublev(GL_PROJECTION_MATRIX, proj_mat); glPopMatrix(); gluProject(three_d_point.X(), three_d_point.Y(), three_d_point.Z(), model_mat, proj_mat, viewport, &width, &height, &depth); if( ((int)width > m_old_rect.right) || ((int)width < 0) ) visible = 0; if( ((int)height > m_old_rect.bottom) || ((int)height < 0) )visible = 0; if(x_pos) *x_pos = (int) width; if(y_pos) *y_pos = (m_old_rect.bottom - (int) height); if(z_depth) *z_depth = depth; returnvisible; }// This function picks the point indicated by map_3d_to_screen, using RenderWare picking, so this is// called only when solid is being shown. Note that the pick position is with respect to the top left// corner of the view window being (0,0). If the pick results in an edge, apointer to the edge is// passed back in picked_edge; else, picked_edge is set to null. This does not modify the selection// set in any way.voidCBendCADViewPart::pick_point_rw(int x_pos, int y_pos, BM_EDGE **picked_edge) { if(picked_edge == NULL) return; if( (x_pos > m_old_rect.right)|| (y_pos > m_old_rect.bottom)) { // Make sure point given is within*picked_edge = NULL;// viewport.return; } RwClump *picked_clump = NULL; RwClump *parent_clump = NULL; long parent_tag, clump_tag, key = 0; BM_EDGE *edge = NULL; if(! RwPickScene(m_scene, x_pos, y_pos, m_camera,&m_pick)) { // Picking command was not successful. *picked_edge = NULL;return; } if(m_pick.type == rwNAPICKOBJECT) { // No clump was picked.*picked_edge = NULL;return; } else if(m_pick.type == rwPICKCLUMP) { // Some clump was picked; process it. picked_clump = m_pick.object.clump.clump;parent_clump = RwGetClumpParent(picked_clump);parent_tag = RwGetClumpTag(parent_clump);clump_tag =RwGetClumpTag(picked_clump);if(parent_tag == 1) { *picked_edge = NULL; return; // A trivial bendline orforming was picked. } // Now some real edge was picked.key = (parent_tag%10000)*100000 + clump_tag; if(clump_tag) // Safety check; we expect clump_tag to be non-zero. *picked_edge = map_list_name_to_bm_edge(parent_tag, clump_tag); }} // This function returns the ratio of the view volume dimension (object space dimensions) to// the viewportdimension (device space dimensions).double CBendCADViewPart::get_object_to_device_ratio(void){ double ratio; if(m_old_rect.right) ratio =2.0*md_current_view_vol[0]/(double)(m_old_rect.right); else ratio = 0.0; return ratio;}/* Given a BM_POINT, which represents a point in worldcoordinates, one can project it onto view window coordinates. This function first checks if the projected point is within the viewing volume. If it IS within viewing volume, the pointer "visible" carries value 1; else, 0. If the point is not visible, no other parameters have any meaning; the return value is 0. Now suppose the point is visible. A) If the display is showing the SOLID version of the part, this function checks ifANY of the three_d_bodies in the array "three_db_array" lies "approximately under" the projected point. If the answer is yes, return value is 1; else, return value is zero. The x_pos, y_pos, and z_depth pointers carry the view window coordinates (with top left corner as (0,0)) and the z-buffer value. The array "thee_db_array" must be terminated by a NULL pointer to indicate end of array. B) If the display is showing the WIREFRAME version of the part the return value is always zero. If the point is within view volume, *visible is set to 1; else, 0. If *visible is 1, x_pos, y_pos and z_depth values have the meaning mentioned above. */int CBendCADViewPart::is_3d_body_near_point(BM_POINT const& three_d_point, BM_3D_BODY **three_db_array, int *visible, int *x_pos, int *y_pos, double *z_depth){ int x, y, is_visible= 1; double z; int found = 0; is_visible = map_3d_to_screen(three_d_point, &x, &y, &z); if( ! is_visible) { // Point is outsideviewing volume.if(x_pos) *x_pos = x;if(y_pos) *y_pos = y;if(z_depth) *z_depth = z;if(visible) *visible = 0;return 0; } // Now point is insideview volume. if(x_pos) *x_pos = x; if(y_pos) *y_pos = y; if(z_depth)*z_depth = z; if(visible) *visible = 1; if(! mi_show_solid) { // Wireframe being drawn; just return that point is return 1; // within view volume. } // Now solid is being shown. if(! three_db_array) return 0; // Point is within view volume. Pick pixels in a triangle around that point. found = pick_point_for_3db_rw((x - 2), (y - 2), three_db_array); if(found) return 1; found = pick_point_for_3db_rw((x -2), (y + 2), three_db_array); if(found) return 1; found = pick_point_for_3db_rw((x + 2), (y + 2), three_db_array); if(found) return 1; found= pick_point_for_3db_rw((x + 2), (y - 2), three_db_array); if(found) return 1; return 0;}// This function picks the point indicated, using RenderWare picking, so this is called only when solid is // being shown. Note that the pick position is with respect to the top left corner of theview window being // (0,0). If the pick results in a three_d_body’s clump, and the picked clump corresponds to ANY of the// three_d_bodies inthe array passed, return value is 1; if no match or no three_d_body, return is 0.// This does not modify the selection set in any way.int CBendCADViewPart::pick_point_for_3db_rw(int x_pos, int y_pos, BM_3D_BODY **three_db_array) { if(three_db_array == NULL) return 0; if( (x_pos > m_old_rect.right) || (y_pos > m_old_rect.bottom)) { // Make sure point given is withinreturn 0; // viewport. } RwClump *picked_clump = NULL; RwClump *parent_clump = NULL; long parent_tag,clump_tag, required_id;int found = 0; if(! RwPickScene(m_scene, x_pos, y_pos, m_camera, &m_pick)) { // Picking command was not successful.return 0; } if(m_pick.type == rwNAPICKOBJECT) { // No clump was picked.return 0; } else if(m_pick.type == rwPICKCLUMP) { // Some clump was picked; process it. picked_clump = m_pick.object.clump.clump;parent_clump = RwGetClumpParent(picked_clump);parent_tag = RwGetClumpTag(parent_clump);clump_tag = RwGetClumpTag(picked_clump);if(parent_tag == 1) { // Body of face/bendline/formingwas picked.for(int i=0; three_db_array[i]; ++i) { // Check if it matches any of the ones in array.if(three_db_array[i] == NULL) break;required_id = three_db_array[i]->get_idx();if(clump_tag%10000 == required_id){found = 1;break;}}return found;} // Now some edge’s clump was picked. Check if it matches any of the ones in array.for(int i=0; three_db_array[i]; ++i) {if(three_db_array[i] == NULL) break;required_id = three_db_array[i]->get_idx();if(parent_tag%10000 == required_id) {found = 1;break;} } } return found;} // This allows the user to insert itemsinto the selection set. "list" is an array of pointers// to three-d-bodies, terminated by NULL to indicate end of array. If list is passed as NULL, every // three-d-body in the part is inserted into the selection set. void CBendCADViewPart::insert_selection_set(BM_3D_BODY **list){ int tag;BV_SELECT_DATA *data = NULL; if(! list) { // Insert every three_d_body in part into selection set.BM_PART *part = NULL;CBendCADDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);part = pDoc->get_part();if(! part) return; BM_FACE *face = NULL;BM_BENDLINE *bendline = NULL;BM_FORMING *forming = NULL;for(face = part->get_face_list(); face; face = (BM_FACE *)face->next()) { if(! face) continue;tag = 100000*(face->get_idx()) + 10000 + face->get_idx();if(! m_selection_set.find(tag, NULL)) {data = new BV_SELECT_DATA;data->key = tag;data->edge = NULL;data->world_pt = BM_POINT(0.0, 0.0, 0.0);m_selection_set.insert(tag, (long)data);}}for(bendline = part->get_bendline_list(); bendline; bendline = (BM_BENDLINE *)bendline->next()) { if(! bendline) continue;tag = 100000*(bendline->get_idx()) + 10000 + bendline->get_idx();if(! m_selection_set.find(tag,NULL)) {data = new BV_SELECT_DATA;data->key = tag;data->edge = NULL;data->world_pt = BM_POINT(0.0, 0.0, 0.0);m_selection_set.insert(tag, (long)data);}}for(forming = part->get_forming_list(); forming; forming = (BM_FORMING *)forming->next()) { if(! forming) continue;tag = 100000*(forming->get_idx()) + 10000 + forming->get_idx();if(! m_selection_set.find(tag, NULL)) {data = new BV_SELECT_DATA;data->key = tag;data->edge = NULL;data->world_pt = BM_POINT(0.0, 0.0, 0.0);m_selection_set.insert(tag, (long)data);}}DrawPart(m_hdc);return;}BM_3D_BODY *three_d_body;long i;for(i=0, three_d_body = list[0]; three_d_body; ++i, three_d_body = list[i]) {if(! three_d_body) break;tag = 100000*(three_d_body->get_idx()) + 10000+ three_d_body->get_idx();if(! m_selection_set.find(tag, NULL)) {data =new BV_SELECT_DATA;data->key = tag;data->edge = NULL;data->world_pt = BM_POINT(0.0, 0.0, 0.0);m_selection_set.insert(tag, (long)data);}}DrawPart(m_hdc);return;}// This function returns the largest of the x, y and z projections of the part’s// bounding box.double CBendCADViewPart::get_approx_part_size(void){ if(md_part_bbox_size) { double size = __max(md_part_bbox_size[0], md_part_bbox_size[1]); size = __max(size, md_part_bbox_size[2]); return size; } else return 0.0;}// This function passes back the bounding box size of the part in its original orientation,in the// array "dimensions". This array should be at least of size 3. Returns 1 if successful, 0 otherwise.// Caution: This is a quick and hence not very accurate calculation; if you want greater precision,// writeyour own function.int CBendCADViewPart::get_part_dimensions(double *dimensions){ CBendCADDoc* pDoc = GetDocument();if(! pDoc) return 0;BM_PART*part = pDoc->get_part();if(! part) return 0;if(! dimensions) return 0;int i;BM_POINT centroid;RwMatrix4d *temp = RwCreateMatrix();i = compute_part_centroid(part, 1, &centroid);if(! i) return 0; i = compute_part_bbox(part, 1, temp, centroid, dimensions, NULL); if(! i) return 0;RwDestroyMatrix(temp);return 1;}
付録K
PART.HXXはベンドモデルおよび部分構造などに関するコメント
/*このファイルはBMAPI BM_PARTクラスの定義を含む。部分関数の殆どはPART.CPPにある。コンストラクタとデストラクタはPART_NEW.CPPにある。シリアル化関数はPART_LOAD_x.CPPおよびPART_SAVE.CPPにある。フォルデイング関数はFOLD.CPPおよび3D_FUNC.CPPにある。アンフォルデイング関数はUNFOLD.CPPにある。***** ******** ********* ********* ********* ********* *********議論:-BMAPIの設計原理の1つは、全体の部分を厚さと全てのもので正確に表そうとすることである。これの利点の1つは、我々が何かを問い合わせ、迅速に答えを得ることが出来るということにある。答えがあからさまには表されなくても、それは容易に計算される。それの他の利点は、我々は"中実な部分"として部分を表しているので、部分を3Dモデル化することが直ちに出来るということにある。-薄板の特殊な性質の1つは、それが対称的であることである。我々は、我々がその部分を表し、それについて理由付けするときこの事実の利点を用いることが出来る。例えば、我々は薄板の1つの側のみを、その他側は我々が厚さベクトルを知ると定義されるので、表すことが出来る。-1つの問題は、我々が部分のフラットバージヨンを与えられたとき(それは通常は厚さを含まない)如何に我々はそれから部分を構成するかということにある。このフラットは部分の中性ラインを表すということを採用するか?このBMAPIにおいて、我々は、ベンドモデルであからさまに表される部分のフラットバージヨンは、部分がトップビユー(上面図)にあるとき薄板のボトム側であるということを採用している。他の重要な点は、このフラットバージヨンがX-Y面上にあるということである。この方法では、例え厚さが変化しても、我々のモデルに対する変化は最小である。- フラットは薄板のボトム側を表すが、フラットのデイメンシヨンは中性ラインデイメンシヨンを表す。すなわち、我々が部分を曲げたとき、曲げた部分の中性ラインのデイメンシヨンはフラットデイメンシヨンに一致する(または、ベンドデダクシヨンにより定義される量だけずらされる)。これは、それらに対して内側=中性ライン=外側なので面に対して不適切である。しかし、それはベンドラインに対して重要である。それは、ベンドラインの基礎をなすフラットがベンドアークの中性ライン上にマップされるということを意味する。- 部分が畳まれるとき、BMAPIは通常はベース-ボデイの2D->3D変換を変化させることはない。しかし、ベース-ボデイがベンドラインであり、ベンパラメータの幾つかを(例えば、ベンド角)変える時は2D->3D変換マトリクスは’not-up-to-date’とマークされる。我々がこの古い変換マトリクスを用いたときは、結果は悪くなる。従って、我々は実際に古い(out-of-date)変換マトリクスを用いることは出来ない。しかし、その場合、我々は、変換マトリクスを一致マトリクスにリセットすることより行うべき更によいものを持つことはない。-全ての3D体のサイズは2通りの方法で変化することが出来る。先ず、もし面が、ベンドデダクシヨンの半分の量に等しい量によりトリムされる。第二に、全てのボデイは隣接するベンドラインに関してそれに係わるトリミング値を持つことが出来る。隣接ベンドラインが曲げられるとき、このボデイはこの量によりトリムされる。-BM APIはBMAPIファイルの全ての公知の(すなわち、最近のおよび全ての初期の)バージヨンをロードすることが出来る。-部分がフォルドされたとき、2D->3D変換のみが直ちに計算される。計算の残部は要求に応じて、すなわち必要なときは常になされる。我々が部分をアンフォルドするときは、全ての事態、すなわち3D-2D変換および部分のフラットバージヨンが直ちに計算される。-部分がアンフォルドされるときは、BMAPIは、3D-ボデイの現在の3D-バージヨンを、それらがup-to-dateとしてマークされるか否かとは無関係に、用いる。-BM_PARTクラスは部分の生成を容易にする幾つかのハイレベルの関数を有する。例えば、それは、部分のフラットバージヨンを検査し、見出された問題点を固定する関数を有する。更に、それは、1組の面のみが与えられたとき部分に対するベンドラインを生成する関数を有する。これらは、多くの用途において共通のタスクであるハイ-レベルの関数である。-部分のベンドラインに対しては、それらが特定のセンタラインを持つことが絶対必要である。センタラインがないと、ベンドラインは殆ど無用であり、それはフォルドされることもアンフォルドされることも出来ない。ベンドラインセンタラインは3つの目的のために用いられる:-ベンドラインフォルデイング-アンフォルデイングのため。-ベンドラインが空のときベンドラインンを表すため。-ベンドラインの向きを決定するため。センタラインは、フラットバージヨンが一定の向きを持つので(すなわち、法線は(0,0,1)でなければならない。)、部分の2D(すなわち、フラット)バージヨンにおいて最も"目的的"であるという点に注意されたい。部分の3Dバージヨンにおいては、センタラインは、その意味が、変化可能な基礎となる表面により定義されるので、幾らか"主観的"である。例えば、我々は、表面(これは必然的に薄板を変化させない)部分をフリップすることが出来、また結果としてベンドラインの向きを同じに保つために同様にセンタラインを反転させなければならない。-全てのベンドラインはそれに係わるンドデダクシヨンを持つ。 このベンドデダクシヨンは、部分がフォルドまたはアンフォルドされるとき部分デイメンシヨンが(このベンドラインにおいて)如何に変化するかを制御する。ベンドデダクシヨン値は正および負の両者を取ることが出来る。それが正であり、我々が部分をフォルドするときは部分のデイメンシヨンは拡大し、それが負のときは部分デイメンシヨンは収縮する。正のベンドデダクシヨンはアンフォルデイング時に部分をフォルドしシュリンクするとき部分を拡大することを意味し、そして従って負のベンドデダクシヨンはアンフォルデイング時に部分をフォルドし、拡大するとき部分を収縮させることを意味する産業基準である(と言われた)。-BM_PARTは、部分のデイメンシヨンを制御するパラメータbendline_dimensions_statusを持つ。それは、部分の設計と生成を容易にするために付加される。ユーザが(例えば)外側から外側へ部分デイメンシヨンを与えられということはしばしば起こる。これらのデイメンシヨンはカスタマにより固定され、特定される。薄板設計プロセスのゴールは、コノフラットがフォルドされるときそのデイメンシヨンが所定のデイメンシヨンに正確に一致するようにこの部分のフラットを生成することにある。設計プロセスにおいては、ユーザは一連の方法で部分を変化させることが出来る。ただし、これが与えられたとき、我々は常に部分デイメンシヨンを変化しないようにすることを望む。 bendline_dimensions_statusがTRUEのとき、BMAPIは、ユーザが部分/ベンドラインパラメータ(薄板の厚さまたはベンドラインの半径などのような)を変化させるとき、可能んらば常に部分デイメンシヨンを(全てのベンドラインにおいて)一定に保とうとする。さもなければ、我々は注意しない。-以前の問題と関連して生じる他の問題は、部分寸法が通常はOUTSIDE/INSIDE/NEUTRALデイメンシヨンとして特定されるということである。例えば、ユーザは、ボックスが与えられ、その外側デイメンシヨンは100x100であると特定する。技術的には、ユーザは、フラット上でこのボックス内の全てのベンドラインが外側デイメンシヨンを表すということを特定している。例えば、ユーザが後に薄板の厚さを変えたとき、外側デイメンシヨンは同じままであり、すなわち全ての付加された厚さは”ボックスの内側に行かなければならない”一般に、ユーザ(またはカスタマ)は、同じ面内でも、部分デイメンシヨンをOUTSIDE/INSIDE/NEUTRALデイメンシヨンと特定する。例えば、ユーザは、ボックスを横切ってデイメンシヨンが、1側の薄板の内側から他側の薄板の外側へとして与えられるということが出来る。 我々は、ユーザが部分デイメンシヨンを一定に保ことを望むか否かのトラックを保持する変数を部分内に有する。もしこの変数が、ユーザが、部分デイメンシヨンが一定に保持されることを要求しないように設定されるとき、このINSIDE/OUTSIDE/NUETRAL-LINEのホワイルビジネスは無視される。*/#ifndef BM_PART_HXX_INCLUDED#define BM_PART_HXX_INCLUDED#include <stdio.h>#include "GLOBAL.HXX"#include "ENTITY.HXX"#include "TOPOLOGY.HXX"class BM_PART : public BM_ENTITY{friend BM_FACE ;friend BM_HOLE ;friend BM_BENDLINE ;friend BM_FORMING ;friend BM_TOPOLOGY ;friendBM_TOPOLOGY_RECORD ;friend BM_BEND_PROPERTY ;friend BM_BEND_PROPERTY_SIMULTANEOUS ;// every part has a (user-defined) name that it inherits fromBM_ENTITY.// also, the type (BM_ENTITY_TYPE_PART) is stored in BM_ENTITY.protected :/*これらの変数は、ユーザをして名前や、数、材料の種類などのパラメータを部分と関係させる。*/char material_type[256] ;char name[256];char number[32] ;/*これらの変数は材料とメタル特性を記述する。*/double metal_thickness ;/*この部分内では、2つのポイントは、もしそれらの間の距離がこの値程度のときは同じであると考えられる。*/double distance_tolerance;/*全ての部分はベンド特性のリストを有する。ベンドラインがベンド特性を持つときは、この特性の対象は部分に係わるベンド特性のリスト上になければならない。これは、我々が部分をセーブまたはロードするとき必要とされる。これらの変数は、内部にのみ使用される。BMAPIのユーザは、これらの変数にアクセスを持たない。*/long number_of_bend_properties ;BM_BEND_PROPERTY *list_of_bend_properties ;/*部分のトポロジーここでボデイをリストに直接付加することは可能ではないことに注意されたい。これは、ボデイが部分トポロジーに付加されるときにのみなされる。*/BM_TOPOLOGY topology ;// number of different3D bodies in the part.// these numbers should be consistent with the part topology.long number_of_faces ;long number_of_holes ;long number_of_bendlines ;long number_of_formings ;// lists of faces, holes and bendlines of the part// Note that these are lists of BM_3D_BODY’s.BM_FACE *first_face ;BM_HOLE *first_hole ;BM_BENDLINE *first_bendline ;BM_FORMING *first_forming ;/*これらのパラメータは部分に係わるベンドシーケンスを表す。*/long bend_sequence_size ;BM_LINKED_LIST_NODE *bend_sequence ;/*このパラメータは部分デイメンシヨンを制御する。それがTRUEのときは、BMAPIは、ユーザが(薄板の厚さまたはベンドラインの半径などの)部分/ベンドラインパラメータを変えるとき、可能なときは常に、部分のデイメンシヨンを(全てのベンドラインにおいて)一定に保とうと試みる。さもなければ、我々は注意しない。デフォールト値は0であり、デイメンシヨンを一定に保持する必要はない。*/charbendline_dimensions_status ;public :/*コンストラクタとデストラクタ。PART_NEW.CPPにおいて。*/BM_PART(void) ;BM_PART(BM_PART *existing_part) ;~BM_PART(void) ;// use this to erase the content of the part. the part willbe empty.// it will use topology::erase_content() to destroy the topology and will then // destroy all bodies in the part.void erase_content(void) ;void get_material_type(char *out_mat_type) ;void set_material_type(char *in_mat_type) ;void get_name(char *out_name) ;void set_name(char *in_name) ;void get_part_number(char *out_number) ;void set_part_number(char *in_number) ;// get number of faces, holes, bendlinesinline long get_number_of_faces(void) const { return number_of_faces ; }inline long get_number_of_holes(void) const { return number_of_holes ; }inline long get_number_of_bendlines(void) const { return number_of_bendlines ; }inline long get_number_of_formings(void) const { return number_of_formings ; }//get pointers to lists of faces, holes and bendlinesinline BM_FACE *get_face_list(void) const { return first_face ; }inline BM_HOLE *get_hole_list(void) const { return first_hole ; }inline BM_BENDLINE *get_bendline_list(void) const { return first_bendline ; }inline BM_FORMING *get_forming_list(void) const { return first_forming ; }// To get the number of bendproperties and the first property object on the list.inline BM_BEND_PROPERTY *get_list_of_bend_properties(void) const { return list_of_bend_properties ; }inline long get_number_of_bend_properties(void) const { return number_of_bend_properties ; }// this function tries to find a good default base face.// it chooses a face that has the largest bbox.BM_FACE *get_default_base_face(void) ;/*部分に係わる距離公差を獲得し変化させる関数*/inline double get_distance_tolerance(void) const { return distance_tolerance ; }void set_distance_tolerance(double new_distance_tolerance) ;/*この部分の現在のメタル厚さを得る。*/inline double get_metal_thickness(void) const { return metal_thickness ; }/*厚さを変えると、部分に多くの変化が生じる。面は、厚さを変えるとベンドラインも変化し易くなるので、若干のトリミングを必要とする。更に、面の2D->3D変換は最も変化し易い。これは、ベンドラインの3D形状が変化するであろうため生じ、またフラットは中性-ラインデイメンシヨンを表すので、部分の3Dデイメンシヨンは最も変化し易くなる。ベンドラインは大きく変化することは殆ど確かである。全てのベンドラインのW3Dは再計算されなければならない。また、2D->3D変換も再計算されなければならない。部分自体は、厚さを変えた結果としてスペース内を移動しないことに注意されたい。しかし、ベンドライン2D->3D変換は’not-up-to-date’としてマークされる。それらを更新する1つの方法は、任意の面をベース-面として取り、その部分をリ-フォールドすることにより与えられる(これは、その最新の2D->3D 変換を持つ場合にのみ行われる)。部分は同じ場所に滞在し(ベース-面は適切に滞在するので)、またベンドラインはそれらの更新された2D->3D 変換を持つ。厚さを変えることは、部分における全てのボデイは2D->3D 変換を持ち易く、また無効にされた3Dバージヨンを持ち易いので実際にはトリッキーである。問題は、ユーザが通常は部分をリ-フォルドすることを望まないということである。従って、われわれは、如何に新しい有効な2D->3D 変換を自動的に得るかを検討しなければならない。この関数はそれをなさない点に注意されたい。これは、或る他の関数によりなされなければならない事態である。この関数は、faces-bendlinesを正確に一致させようとはしない。それを実現するには、この関数の後match_all_faces_adjacent_to_bendlines(...)をコールせよ。更に、新しい厚さを設定し、次に隣接面を一致させると共に新しい最新の2D->3D変換を計算するset_metal_thickness_update_part(...)を用いよ。*/void set_metal_thickness(doublethickness) ;void set_metal_thickness_update_part(double thickness) ;/*この関数は、3Dスペースにおいてそれらがそれらに隣接するベンドラインに正確に触れるように全ての面をトリムする(必要に応じて)。この関数は、厚さが変化した後にまたはベンドラインパラメータが変化した後にコールするのによい。*/void match_all_faces_adjacent_to_bendlines(void) ;/*3Dボデイ(面、孔、フォーミングまたはベンドライン)を部分に付加する。付加出来ないときはFALSEを戻す。この関数は、基本的にはトポロジーのadd_body() member関数をコールする。*/int add_3d_body(BM_3D_BODY *body) ;// get part topologyinline BM_TOPOLOGY *get_topology(void) const { return (BM_TOPOLOGY *) &topology ;}/*これらの関数は、ユーザが、ベンドラインにおける部分デイメンシヨンが可能なときは常に一定に保たれるべきか否かを照会し、特定することを許容する。*/// to get the current statusinline int get_bendline_dimensions_status(void) const { return bendline_dimensions_status ; }// to set the new status.// for example, if we set it to TRUE, then from this point on, BMAPI// will try to keep to current part dimensions constant.void set_bendline_dimensions_status(int new_bendline_dimensions_status) ;/*ベンドシーケンス関係関数*/void delete_bend_sequence(void) ;inline long get_bend_sequence_size(void) const { return bend_sequence_size ; }// this function returns the number of bendlines copied into OUT arrayint get_bend_sequence(BM_BENDLINE *bendlines[], long bendlines_array_length) ;// this function sets a new bend sequence for this bendlineint set_bend_sequence(BM_BENDLINE **bendlines, long bendlines_array_length) ;// this function checksis a bendline is in the current bend sequence of the part.// if yes, itreturns its index in the bend sequence (ie. the number of this bendline// in the bend sequence order). This index is from 0 through sequence_lenght - 1.// if this bendline is not in the bend sequence, it returns -1.int is_bendline_in_bend_sequence(BM_BENDLINE *bendline) ;// this function removes a bendline from the bend sequence.// note that if the bendlineis in a simultaneous bend property, it will replace the bendline// withanother bendline from the simultaneous bend property that is not already in the bend sequence.void remove_bendline_from_bend_sequence(BM_BENDLINE *bendline) ;// this function deletes the current bend sequence (if one exists) and creates a default // bend sequence.void create_default_bend_sequence(void) ;/*この関数は、孔を含まない全てのベンドラインのフラットバージヨンを排除する。この関数は、部分がアンフォルドされた後有用になり得る。通常は、部分のフォルドされたバージヨンはトリビアルでないベンドライン(すなわち、0でないインサイド半径および/または厚さ)を含む。部分がアンフォルドされたとき、BMAPIはこれらのベンドラインを、それらが有るように正確にフラットバージヨンに変換する。たとえば、ゼロ以外の厚みまたは半径を有するベンドラインの3D-バージョンには通常、曲がった弧が描かれる。これは平面バージョンのベンドラインにマッピングされる。これはパートの平面バージョンにおいて、ベンドラインに対応する2つの面の間に長方形が存在することを意味する。ただし我々は、この矩形を見たくないときがある。この関数は、単純な平面(つまり平面に穴がない)を有し、2つの面に正確に隣接するベンドラインだけを処理する。 この関数は、隣接するすべての面を切り取って(トリミング)、ベンドラインの中心線に接触させ、ベンドライン平面におけるすべての輪(ループ)を削除する。この関数は通常UNFOLDの直後に使われることに注意せよ。いったん平面がトリミングされると、それは隣接する面にも適合する。これは、この関数がいくつかの特殊なトリミング値を計算および設定し、後ほど我々がパートをたたむ(フォルドする)ときに、面がベンドラインに正確に接する正しい3D-バージョンを得ることを意味する。この関数はベンドラインを変えない。*/void eliminate_simple_bendlines_in_flat_version_A(void) ;/*この関数は、パートにおけるすべての3D-ボディを走査して(フォーミングを除く)、それらの平面バージョンを整える。基本的にこの関数は、パートにおけるすべての3D_body(フォーミングを除く)に対してBM_2D_BODY::fix_flat()関数を呼び出す。この関数は現行の平面バージョンのみをチェックするので注意せよ。この関数は、何らかの操作が失敗するか(つまりメモリー割り当て)、またはこの関数が解決できない問題を発見したときにFAILUREを返す。*/int fix_flat(void) ;/*この関数は、フェース・ノーマル(face normal)がベンドラインの定義に合致していることをチェックする。たとえば、face1が法線を持ち(0,0,1)、face1とface2との間に90度のFRONTベンドがある場合、face2の法線は(-1,0,0)にならなければならない。本来とは逆の法線がある場合、この関数はそれを整える。さもなくば、この関数は問題を見つけるとFAILUREを返す。入力面が与えられる場合、この関数はその面の中心に位置する接続されたコンポーネントだけをチェックする。さもなくば、この関数はパート全体をチェックする。この場合、この関数が面をチェックする順番は、面インデックスの順番である。この関数は必要なチェックをいくつか行なう(たとえば、ベンドラインが曲げられるとき、それはbend op, a3D-バージョン(それは空のこともある)およびサーフェスを持たなければならない)。この関数は、すべての面およびベンドラインの3D-バージョンが最新のものであるか否かをチェックする。いずれかが最新のものでない場合には、この関数はFAILUREを返す。この関数は、現行バージョンが最新であるか否かをチェックするだけであり、現行バージョンが最新でない場合は、新しい3D-バージョンを計算しない(この関数は通常展開(アンフォルド)の後に使われるので、この時点では何も計算したくない)。この関数は穴とフォーミング(formings)を無視する。In 3D_FUNC.CPP.*/int fix_3D_face_normals(BM_FACE *given_base_face = NULL) ;/*この関数は、パートにおける3D-ボディをチェックし、これが見つける問題を解決する。この関数は現行の3D-バージョンのみをチェックするので注意せよ。さらにこの関数は、何ものをも無効にしない。只今この関数は:フェース・ノーマル(face normal)がベンドラインの定義に合致していることをチェックする。たとえば、face1が法線を持ち(0,0,1)、face1とface2との間に90度のFRONTベンドがある場合、face2の法線は(-1,0,0)にならなければならない。この関数は、何らかの操作が失敗するか(つまりメモリー割り当て)、またはこの関数が解決できない問題を発見したときにFAILUREを返す。In 3D_FUNC.CPP.*/int fix_3D(void) ;/*********** ********** ********** ********** ********** ********** ********** ********** **********これは、パートの設計および建造に用いる主要な高水準Bend Model機能である。その用途は次の通りである:-パートが結合されるように(可能である場合)、面と面との間にベンドラインを作る。この関数は、パート制作を合理化するために作られた。通常はパートを描くのにサードパーティのCADプログラムが使われる。Bend ModelはCADシステムをコントロールしないので、我々の目的にとってこの描画(ドローイング)は単なるエッジの集合である。このため、パートの構造を見つけるには、ドローイングを分析しなければならない。その後に我々は、パートのベンドラインと面を作ることができる。ただし、この入力ドローイングはしばしば曖昧である。つまり、面、そして特にベンドラインは一意に定義されていない。このことが多くのアプリケーションに共通する問題であるため、この関数がBend Modelの一部になっている。さらに、Bend Modelにこの関数を実装することにより、CADシステムの一部を形成する面検出ソフトウェアを簡略化する。この関数において我々は、面のエッジが、プレーン・ノーマル(平面の方向を定義する)と調和する方法で、左側の罫線(ルール)に従って揃えられることを想定する。基本的に、この関数は、各平面を分離して見た場合にすべての平面がそれ自体で適正であることを想定する。ただしこの関数は、隣接平面の向きが、それらの間にあるベンドラインに対して適正であることを要求しない。この関数は、パートの厚さがゼロ以外の場合に、恐らく良好に機能しない。この関数は、パートの3D-バージョンとパートの平面バージョンの両方についてベンドラインを生成するのに使える。ただしパートは、パートの平面バージョンかまたは3Dバージョンのいずれかを持つことができ、その両方を持つことはできない。すなわち、3D-ボディのすべての3D-バージョンがNULLであるか(この場合我々は平面バージョンを得る)、またはすべての平面バージョンがNULLでなければならない。Implementation is in AUTO_BEND.CPP.*/int auto_bend(void) ;/*この関数は、CADシステムによってBend Modelに送信されたデータからパートを制作することを促進するために設計された。問題は、情報を利用できるようにするため、しばしばパートが部分ごとに建造されることである。ただし問題は、我々がパートのボディを建造するとき、入力データがパートの平面バージョン(FLAT)と3Dバージョンのいずれを表わしているのかを事前に知ることができないことである。通常それは3D_versionである。このため我々はデフォルトで、それが3Dバージョンであると想定する。後ほど、パートの3D-ボディのすべてが建造された時点で、我々は入力データが3D-バージョンであることをチェックできる。もしも3D-バージョンでなければ、我々はすべての3D-バージョンを平面バージョンに移さなければならない。この関数は、この目的のためにのみ設計されており、他のいかなる目的にも使用するべきでない。この関数の誤用は、システムをクラッシュする。この関数はまず初めに、ボディの平面バージョン(FLAT)がNULLであるか否かをチェックする。これがNULLでない場合、この関数は3D-バージョンを移さない。 TODO : right now, it only moves faces.*/void BM_PART::move_3D_to_flat(void) ;/*********** ******************** ********** ********** ********** ********** ********** **********Bend Modelは、パート操作を両方の方向で処理できる。:-パートの3Dバージョンの場合、パートの2D(平面)バージョンを見つける。-2D(平面)バージョンの場合、それを所定の屈曲パラメータでフォルドする。BMAPIはほとんどの場合、2つのバージョン(2Dおよび3D)のパートを有するので、それらの一貫性を維持することが重要である。BMAPIは通常、効率性の理由から、パートの2Dバージョンと3Dバージョンを明示的には計算せず、かわりに要求に応じて(ユーザーが計算を要求するときのみ)それらを計算する。ほとんどの場合我々は、ある所定のボディのバージョンから別のボディのバージョンが作られる変形(トランスフォーメーション)を知るだけで十分である。2D->3D変形と3D->2D変形との間には1つの違いがある。通常2D->3D変形はユーザーによって指定され、ユーザーは任意の方法でそれを実施できる(何らかの理由により結果が不正になることがあるが、とりあえず当面はそのことを無視する)。3D->2D変形はアンフォルドに対応し、これには1つの方法だけがある。つまり、所定の固定された3D-バージョンについて、最終的なパートの平面バージョンが1つだけ存在する。フォルドとアンフォルドはいずれも、パートの屈曲情報を用いて、すべての3Dボディを各々の屈曲パラメータに従って個別に計算する。一般に、これらの変形では、パート内のすべてのボディが’flat’バージョンかまたは’3D-version’を有することが要求される。つまり、当初3Dバージョンのパートがある場合、2D->3D変形を使用する前に、それをアンフォルドしなければならない。アンフォルドは’flat’を作り出す。フォルドは’3D-version’を作り出す。ユーザーは最初に、フラット・バージョンか3D-バージョンのいずれかを指定しなければならない。********** ********** ********** ********** ********** ********** ******************** ***********//*この関数は、BMAPIに(フラットから)パートの3Dバージョンを強制的に計算させる。具体的にBMAPIは、面−穴−ベンドラインのすべてをチェックし、3Dバージョンが新しくなければ、BMAPIは2D->3D変形を用いてフラットから最新の3Dバージョンを計算する。2D->3D変形が新しくない場合、BMAPIは最新の有効な2D->3D変形の計算を試みる。また、あるベンドラインについて新しい3D-バージョンが計算されるとき、BMAPIは初めに隣接するベンドラインを適合させる。*/void bring_3D_up_to_date(void) ;/*********** ********** ********** ********** ********** ********** ********** ********** **********2D->3D変形関数********** ********** ********** ********** ********** ********** ********** ********** ***********//*この関数はすべての変形をアイデンティティ変形(identity transformation)にリセットする。さらにこの関数は、すべてのベンドラインにおける’bending_status’変数をFALSEに設定する。さらにこの関数は、すべての面のすべての3Dバージョンを’not-up-to-date’(非最新)と記すが、ただしその再計算は行なわない。3D->2D変形はリセットできないので、この関数が2D->3D変形のみをリセットすることに注意せよ。*/void reset_all_transformations(void) ;/*パートの2D->3D変形をリセットする。’body’は、アイデンティティ変形になる変形を持つ面である。他のボディは、この基本ボディ(ベース・ボディ)に関する屈曲情報に従って、各々の変形を設定する。この関数は、すべての変形母体(マトリックス)を更新する。基本的にこの関数では、ユーザーがパート全体に行なった回転や移動のすべてを取り消し(アンドゥー)できる。*/void reset_part_2Dto3D_transformations(BM_3D_BODY *base_body) ;/*********** ********** ********** ********** ********** ********** ********** ********** **********これらの関数は、ユーザーにパートの回転または移動を実施させる。たとえば、屈曲のとき、ユーザーはパートの反転を希望することがある。これらの関数は、パート全体に均一に作用する。すなわち、すべての面−穴−ベンドラインが全く同様に変化する。これらの関数が2D->3D変形であることに注意せよ。すなわち、これらの関数はパートの3Dバージョンだけを変更するが、これらの関数はパートの平面バージョンの計算を要する。基本的にこれらの関数が実施する唯一のことは、すべてのボディに付随する2D-3D変形を変更し、すべてのボディの3D-バージョンを’not-up-to-date’(非最新)と記すことである。********** ********** ********** ********** ********** ********** ********** ********** ***********//*パート全体を線を軸に一定の角度(ラジアン単位)で回転させる。正の方向は、線の方向を見たときの時計回りである。*/void rotate(BM_LINE const& line, double constangle) ;/*パート全体をこのベクトルで移動する*/void translate(BM_VECTOR const& translation_vector) ;/*この変形をパートに適用する*/void transform(BM_TRANSFORM const& transformation) ;/*********** ********** ******************** ********** ********** ********** ********** **********FOLD関数。FOLD.CPPモジュール内********** ********** ********** ********** ********** ********** ********** ********** ***********//*パートの3Dバージョンを計算する。この関数は、ベース・ボディに従ってパートの3Dバージョンを計算する。つまり、’base_body’は留まり、パートの残りの部分は動く。これまでパート全体に回転や移動を実行した場合、回転または移動はこの操作の後にも有効であるので注意せよ。通常ユーザーは、いくつかのベンドライン・パラメータを設定してから、この関数を呼び出してパートを更新することを希望する。この関数は、変化する(最小限度の変化)ボディの変形母体だけを計算する。各ボディの3Dバージョンは要求に応じて(ユーザーが計算を要求するときのみ)計算される。この関数は、各ベンドラインのメンバ変数’bending_status’を用いて、ベンドラインを屈曲するか否かを決める。ベース-ボディの2D->3D変形が新しくない場合、FOLDはそれをアイデンティティ変形にリセットするので注意せよ。*/int fold(BM_3D_BODY *base_body) ;/*この関数は、各ベンドラインのメンバ変数’bending_status’がFALSEであると想定し(FALSEでない場合は、この関数が’bending_status’をFALSEに設定する)、さらに屈曲するベンドラインのリストが配列’bendline_array’にあると想定する(配列の長さは’number_of_bendlines’)ことを除き、同じことを実行する。この関数が終るときに、各ベンドラインのメンバ変数’bending_status’は、ベンドラインが屈曲されたか否かを表示する。*/int fold(BM_3D_BODY *base_body, BM_BENDLINE *bendline_array[], long number_of_bendlines) ;/*この関数は、パートの屈曲順位における最初のnベンドラインをフォルドする。*/int fold_sequence(BM_3D_BODY *base_body, int n) ;/*3Dボディがすでにその2D->3D変形母体を計算している場合、この関数は所定のベンドラインについて変形母体を計算する。この関数は数々の事柄を想定する(これらの事柄はチェックされない):-このベンドラインはボディに隣接している。-このボディはすでに最新の変形母体を有する。-このベンドラインは最新のcenter_line_2Dを有する。これら2つの関数では、ベンドラインが2D中心線を有することが要求されるので注意せよ。これはまた、ベンドラインに平面があることをも意味する。性能上の理由から、これらの関数はベンドラインにおける平面の有無をチェックせず、かわりにベンドラインに平面があるものと想定し、それを直接的に参照する。この関数はFOLDによって使われる。*/int bend_bendline_wrt_3D_body(BM_3D_BODY *body /* finished body */, BM_BENDLINE*current_bendline /* bendline whose transformation we are computing */,BM_TRANSFORM *tf /* start with this transformation */) ;/*ベンドラインがすでに完成しており、我々が3Dボディを計算していることを除き、同じ。This function is used by FOLD.*/int bend_3D_body_wrt_bendline(BM_BENDLINE *current_bendline /* finished bendline */, BM_3D_BODY *body /* body whose transformation we are computing */, BM_TRANSFORM *tf /* start with this transformation */) ;/*********** ********** ********** ********** ********** ********** ********** ********** **********UNFOLD関数。UNFOLD.CPPモジュール内********** ********** ********** ********** ********** ********** ********** ********** ***********//*この関数はパート全体をアンフォルドする。この関数は、接続されたパートの各コンポーネントにつき、デフォルトのベース・ボディを選択する。この関数は、パートがアンフォルドされるときに、ベース・ボディが原点(0,0,0)に重なるようにパートをX-Y平面に移動させる。この関数は最初に各3Dボディについて3D->2D変形を計算し、それから各3D-ボディについてWflatを計算し、次にWflatをトリミングし、最後に平面を計算する。この関数は、ベース-ボディとして非-NULLの法線を持ち、最小idを持つ面を選択する。これが不可能である場合、この関数は、ベース-ボディとして非-NULLの法線を計算することができる基礎のサーフェスを有する最初のベンドラインを選択する。この関数は、BM_PART::unfold(BM_3D_BODY *base_body)を用いて、パートの接続されたコンポーネントのすべてをアンフォルドする。この関数は、全面的に成功した場合に1を返し、パートの一部でアンフォルドに失敗した場合には0を返す。この関数はまず初めに、すべてのフェース・ノーマルが現行のベンドラインに対して適正であることをチェックする。この関数は、各3D-ボディの現行3D-バージョンを使用することに注意せよ。アンフォルドを行なうには、すべての3D-バージョンが新しくなっていなければならない。この関数は3Dボディが新しいか否かをチェックせず、実際にはすべての3D-ボディを最新と記す。さらにこの関数は、すべてのベンドラインが有効な3D-中心線を持っていると想定する。ここでもこの関数は3D-中心線をチェックせず、かわりに現行の中心線をただ単に批准する。*/int unfold(void) ;/*この関数は、ベース-ボディの周囲を中心とするパートの接続コンポーネントだけをアンフォルドする。この関数は、パート全体をアンフォルドするBM_PART::unfold(void)関数によって使われる。この関数は、接続コンポーネントの各3D-ボディについて新しい3D->2D変形を計算し、次にBM_3D_BODY::compute_flat_from_3D()関数を用いて各3D-ボディについて新しい平面バージョンを計算する。ベース・ボディが面であり、入力フラグがTRUEに設定されている場合、この関数が最初に実行することは、すべてのフェース・ノーマルが現行のベンドラインに対して適正であることをチェックすることである。ただしこれは、そのベース・ボディ(面)を中心とする接続コンポーネントに限られる。この関数は各3D-ボディの現行3D-バージョンを使用するので注意せよ。この関数を呼び出す前に、すべての3D-バージョンが最新であることを確認せよ。この関数は実際、それが処理するすべての3D-ボディを最新と記す。*/int unfold(BM_3D_BODY *base_body, int check_face_normals = 0) ;/*3Dボディの3D->2D変形母体がすでに計算済みの場合、この関数は所定のベンドラインについて変形母体を計算する。この関数は数々の事柄を想定する(これらの事柄はチェックされない):-このベンドラインはボディに隣接している。-このボディはすでに最新の変形母体を有する。-このベンドラインは最新のcenter_line_3Dを有する。これら2つの関数では、ベンドラインが中心線を有することが要求されるので注意せよ。これはまた、ベンドラインが非-NULLの3D-バージョンであることをも意味する。性能上の理由から、これらの関数はベンドラインが非-NULLの3D-バージョンであることをチェックせず、かわりにベンドラインが非-NULLの3D-バージョンであるものと想定し、それを直接的に参照する。この関数はUNFOLDによって使われる。この関数は実際にはbend_bendline_wrt_3D_body(...)の逆であることに注意せよ。*/int unfold_bendline_wrt_3D_body(BM_3D_BODY *body /* finished body */, BM_BENDLINE *current_bendline /* bendline whose transformation we are computing */, BM_TRANSFORM *tf /* start with this transformation */) ;/*ベンドラインがすでに完成しており、我々が3Dボディを計算していることを除き、同じ。この関数はUNFOLDによって使われる。この関数は実際にはbend_3D_body_wrt_bendline(...)の逆であることに注意せよ。*/int unfold_3D_body_wrt_bendline(BM_BENDLINE *current_bendline /* bendline終了*/, BM_3D_BODY *body /* 我々が変形を計算しているところのボディ */, BM_TRANSFORM *tf /* この変形から開始する */) ;/*********** ********** ********** ********** ********** ********** ********** ********** **********この関数は"paper model of this part"(このパートのペーパー・モデル)を返す。ペーパー・モデルとは、厚みが0であり、ベンドラインの半径と屈曲控除も0であるパートである。必要に応じこの関数は、ベンドラインのユーザ-id’から’内部半径’と’屈曲控除’をマッピングした結果を返す。********** ********** ********** ********** ********** ********** ********** ********** ***********/BM_PART *make_paper_model(double **inside_radius /* OUT */, double **bend_deduction /* OUT */) ;/*この関数は、現行のパートを所定のファイルにPGF形式で保存する。PGF形式はCMUのBendCADプログラムによって使われる。戻り値:万事良好でパートが保存された場合にTRUEを返す。*/int save_PGF_file(FILE *file) ;int save_PGF_file(char *filename) ;/*ロード関数はPART_LOAD_x.CPPにある。*/virtual int load(FILE *file) ;virtual int load(char *filename/* must not be NULL */) ;int BM_PART_Load(FILE *file, long version) ;/*保存関数はPART_SAVE.CPPにある。*/virtual int save(FILE *file) ;virtual int save(char *filename /* must not be NULL */) ;} ;#endif // BM_PART_HXX_INCLUDED
付録L
3次元操作および回転軸の動的計算によるナビゲーションの例
void CBendCADViewPart::OnLButtonUp(UINT nFlags, CPoint point) {::ReleaseCapture();::ClipCursor(NULL);// Release mouse, free cursor.m_lt_btn_up_point = point;double x_extent, y_extent;int add_hit_to_list = 0;int viewport[4];BM_VECTOR offset;BM_PART *part = GetDocument()->get_part();RwV3dvert;switch(ml_last_function_chosen){ case(ZOOM_WINDOW_MODE):if(mi_dynamic_rot_center_on) {// User has further zoomed in. compute_non_dyn_equivalent();RwIdentityMatrix(md_dyn_rot_matrix);}compute_zoom_region_translation();x_extent = fabs((double)(m_lt_btn_down_point.x - m_lt_btn_up_point.x))* 2.0*md_current_view_vol[0]/(double)(m_old_rect.right);y_extent = fabs((double)(m_lt_btn_down_point.y - m_lt_btn_up_point.y))* 2.0*md_current_view_vol[1]/(double)(m_old_rect.bottom);set_new_view_volume(x_extent, y_extent); compute_part_bbox(part, mi_show_3d, md_rot_matrix, m_part_centroid, md_part_bbox_size, &offset); mi_bbox_is_up_to_date = 0;// Even though bbox computed, we mark as not up to date so that zoom-allDrawPart(m_hdc);// will work correctly.// Now turn on dynamic rotation center if need be.if( (md_part_bbox_size[0] >2.2*md_current_view_vol[0]) || // User has zoomed in so that not all (md_part_bbox_size[1] > 2.2*md_current_view_vol[1]) ) { // of the part is in view volume.if(! md_dyn_rot_matrix) md_dyn_rot_matrix = RwCreateMatrix(); if(mi_show_solid) {// Pick the center of the screen to find point on clump to rotate around.if(RwPickScene(m_scene, m_old_rect.right/2, m_old_rect.bottom/2, m_camera, &m_pick)) {if(m_pick.type == rwNAPICKOBJECT) { // No clump was picked. m_dynamic_rot_center = BM_POINT(0.0, 0.0, 0.0);}else if(m_pick.type == rwPICKCLUMP) { // Some clump was picked; process it.vert = m_pick.object.clump.wcpoint; m_dynamic_rot_center = BM_POINT(vert.x, vert.y, vert.z);}}}else { m_dynamic_rot_center = BM_POINT(0.0, 0.0, 0.0);}mi_dynamic_rot_center_on =1;}else {compute_non_dyn_equivalent();if(md_dyn_rot_matrix) RwDestroyMatrix(md_dyn_rot_matrix);md_dyn_rot_matrix = NULL; mi_dynamic_rot_center_on = 0;} break; case(SELECT_OBJECTS_MODE): if(nFlags & MK_CONTROL)add_hit_to_list = 1;if(! mi_show_solid) { // Wireframe being displayed, which means OpenGL picking.glGetIntegerv(GL_VIEWPORT, viewport);glMatrixMode(GL_PROJECTION);glPushMatrix();glLoadIdentity();gluPickMatrix((double)point.x, (double)(m_old_rect.bottom - point.y), 3.0, 3.0, viewport);glOrtho(- md_current_view_vol[0], md_current_view_vol[0],- md_current_view_vol[1], md_current_view_vol[1],- md_current_view_vol[2], md_current_view_vol[2]);glMatrixMode(GL_MODELVIEW);DrawPart(m_hdc); // Draw the part in selection mode.glMatrixMode(GL_PROJECTION);glPopMatrix();glMatrixMode(GL_MODELVIEW);process_hits_record(add_hit_to_list);ml_last_function_chosen = NO_FUNCTION_MODE;DrawPart(m_hdc); reset_selection_buffer();}else { // Solid being shown, so RenderWare picking.if(RwPickScene(m_scene,point.x, point.y, m_camera, &m_pick)) process_hits_record(add_hit_to_list);ml_last_function_chosen = NO_FUNCTION_MODE;DrawPart(m_hdc); } break;case(ZOOM_IN_OUT_MODE): compute_part_bbox(part, mi_show_3d, md_rot_matrix, m_part_centroid, md_part_bbox_size, &offset); mi_bbox_is_up_to_date = 0;if(mi_dynamic_rot_center_on) {// User has furtherzoomed in. compute_non_dyn_equivalent();RwIdentityMatrix(md_dyn_rot_matrix);}// Now turn on dynamic rotation center if need be.if( (md_part_bbox_size[0] > 2.2*md_current_view_vol[0]) || // User has zoomed in so thatnot all (md_part_bbox_size[1] > 2.2*md_current_view_vol[1]) ) { // of the part is in view volume.mi_bbox_is_up_to_date = 0;// Even though bbox computed, we mark as not up to date so that zoom-allif(! md_dyn_rot_matrix) md_dyn_rot_matrix = RwCreateMatrix(); // will work correctly.if(mi_show_solid) {// Pick the center of the screen to find point on clumpto rotate around.if(RwPickScene(m_scene, m_old_rect.right/2, m_old_rect.bottom/2, m_camera, &m_pick)) {if(m_pick.type == rwNAPICKOBJECT) { // No clump was picked. m_dynamic_rot_center = BM_POINT(0.0, 0.0, 0.0);}else if(m_pick.type == rwPICKCLUMP) {// Some clump was picked; process it.vert = m_pick.object.clump.wcpoint; m_dynamic_rot_center = BM_POINT(vert.x, vert.y, vert.z);}}}else { m_dynamic_rot_center = BM_POINT(0.0, 0.0, 0.0);}mi_dynamic_rot_center_on = 1;}else {if(mi_dynamic_rot_center_on) {compute_non_dyn_equivalent();if(md_dyn_rot_matrix) RwDestroyMatrix(md_dyn_rot_matrix);md_dyn_rot_matrix = NULL;mi_dynamic_rot_center_on = 0;}}break; default: break;};ml_last_function_chosen = NO_FUNCTION_MODE;CBendCADView::OnLButtonUp(nFlags,point);}
【図面の簡単な説明】
【図1】この発明の実施例に基づいて構成された、進歩的板金製造設備のブロックダイヤグラム図である。
【図2】この発明の他の実施例に基づいて構成された進歩的板金製造設備のブロックダイヤグラム図である。
【図3】この発明の1つの側面による、サーバモジュール、データベース及びステーションモジュールの間のそれぞれのデータの流れを図示する。
【図4】この発明の他の側面による、サーバモジュールにより実行される一般的な工程及び操作のフローチャートである。
【図5】この発明の教示による、前記ステーションモジュールの各々により実行される基本的工程及び操作の代表的フローチャートである。
【図6】この発明の一側面による類似パーツ検索アルゴリズム或いは工程の論理フローを説明するフローチャートである。
【図7】この発明の一側面による類似パーツ検索アルゴリズム或いは工程の論理フローを説明するフローチャートである。
【図8】図8(a)、(b)、(c)はこの発明の側面による、接触した角部を有する4曲げ箱及び開放された角部を有する4曲げ箱についての特徴抽出操作を説明する。
【図9】図9(a)、(b)、(c)及び(d)はこの発明の側面による、接触した角部を有する4曲げ箱及び開放された角部を有する4曲げ箱についての特徴抽出操作を説明する。
【図10】図10(a),(b)及び(c)は、この発明の他の側面による、4曲げ箱、ブリッジ及び他の4曲げ箱を有するパーツについての検索キーを特定するための特徴関連操作及び工程を説明する。
【図11】図11は、折り曲げアルゴリズムを用いて、2次元単一図面図から3次元モデルを生成するためになされる工程及び操作の論理フローを説明するフローチャートである。
【図12】面検出工程のための図面を作成するために行なわれる自動トリミング機能及びクリーンアップ機能の例を説明する。
【図13】図13(a)、(b)、(c)は、面検出工程のための図面を作成するために行なわれる自動トリミング機能及びクリーンアップ機能の例を説明する。
【図14】面検出工程のための図面を作成するために行なわれる自動トリミング機能及びクリーンアップ機能の例を説明する。
【図15】図15(a)、(b)、(c)、(d)はこの発明の側面による、面検出工程においてなされる種々の工程及び操作を説明する。
【図16】図16(a)、(b)、(c)、(d)はこの発明の側面による、面検出工程においてなされる種々の工程及び操作を説明する。
【図17】この発明の側面による、面検出工程及び曲げ線検出工程の実行から最終曲げグラフデータの生成を説明する。
【図18】この発明の側面による、面検出工程及び曲げ線検出工程の実行から最終曲げグラフデータの生成を説明する。
【図19】この発明の教示による、展開アルゴリズム及び他の工程を用いて最初の3次元図面(厚さを有しない)に基づいて2次元モデルを生成するための基本的論理フローのフローチャートである。
【図20】この発明の側面による、2次元クリーンアップ操作を用いて最初の2次元3面図に基づいて3次元モデルを生成するための基本的論理フローのフローチャートである。
【図21】この発明の側面による、2次元3面図に対して2次元クリーンアップ操作を行なうための工程及び操作の基本的論理フローのフローチャートである。
【図22】図22(a)及び(b)は、この発明の2次元クリーンアップ操作により加工される代表的2次元3面図の図及び側面を説明する。
【図23】図23(a)はこの発明の2次元クリーンアップ操作の回転された図の特徴を説明する。図23(b)はこの発明の側面による、この発明の2次元クリーンアップ操作に関連する標準形態を説明する。
【図24】図24(a)及び(b)は、この発明の教示による、厚さを有する2次元3面図及び厚さ除去工程を用いて生成される厚さを有しない簡単化された2次元3面図を説明する。図24(c)はこの発明の側面による、代表的パーツの横断厚さ線分及び厚さ円弧の図である。
【図25】本発明の側面による、厚さを有する3次元図面から厚さを有しない3次元モデルを展開するために実行される種々の工程及び操作の論理フローのフローチャートである。
【図26】例えばオブジェクト指向プログラム技術を通して本発明を実行する際に、使用される曲げモデルの代表的データ構造及びアクセスアルゴリズムを説明する。
【図27】この発明の他の側面による、曲げモデルビューアの構造のブロックダイヤグラムを説明する。
【図28】表示スクリーンへ出力として提供される代表的ソリッド図ウインドウ表示を説明する。
【図29】表示スクリーンへ出力として提供される代表的ワイヤフレーム図ウインドウを説明する。
【図30】表示スクリーンへ出力として提供される2次元平面スクリーン像ウインドウ表示を説明する。
【図31】表示スクリーンへ出力として提供される正射影図スクリーン像を説明する。
【図32】この発明の自動寸法付けモードにおいて表示される種々の寸法事項の例を説明する。
【図33】図33(a)、(b)及び(c)は、この発明の1つの側面による、種々の異なるパーツについてフランジ長さが定義される態様を図示する。
【図34】図34(a)及び(b)は、この発明の他の側面による、2つの異なるタイプのパーツについて補助的なフランジ長さを追加することを図示する。
【図35】図35(a)、(b)及び(c)は、この発明の更に他の側面による、厚さを備えて表示される種々のパーツについてフランジ長さが指示される態様を図示する。
【図36】図36(a)及び(b)は、この発明の接線寸法方法及び交差寸法方法による、鋭角曲げ角度を有するパーツのフランジ長さが表示される態様を示す。
【図37】この発明の他の側面による、図形的ユーザインタフェースの使用により曲げプランが生成されるために行なわれる工程及び操作の論理フローのフローチャートである。
【図38】曲げ順を生成するために曲げオペレータに対して表示される曲げ順入力スクリーン像の例を図示する。
【図39】図39(a)及び(b)は、この発明の他の側面による、曲げ順の選択及び挿入方向の修正の例を示す。
【図40】曲げ順入力スクリーン画像及び関連するスクリーン表示の更なる例を示す。
【図41】曲げ順入力スクリーン画像及び関連するスクリーン表示の更なる例を示す。
【図42】この発明の1つの側面による、オペレータが提案された曲げ順を修正し且つ編集するのを容易にするために設けられるドラッグ及びドロップ編集特性を示す。
【図43】曲げオペレータが工具を選択するのを支援するために図形的に表示される種々の表示メニュー及びデータテーブルの例を示す。
【図44】提案された曲げプランにおいて工具のセットアップを容易にするために曲げオペレータに対して表示される代表的工具セットアップウインドウを示す。
【図45】張り付けられたアイコンの使用を介して、添付された音声及び映像情報を有する3次元ソリッド図ウインド表示の例を示す。
【図46】この発明の一側面による、格納された音声及び映像情報を読み出すためのアイコンと共に組み込まれた表示ウインドウの他の例を示す。
【図47】この発明の教示に基づいて実行されるイメージ編集ウインドウの例を示す。
【図48】図形的ユーザインタフェースを介して実行されるこの発明の干渉チェック機能の例を示す。
【図49】図形的ユーザインタフェースを介して実行されるこの発明の干渉チェック機能の例を示す。
【図50】図50(a)及び(b)は、例えばジョイスティックを用いて3次元幾何学形状の回転及び表示を操作するための、この発明の操作システムを示す。
【図51】例えばジョイスティック及びズームボタンを用いて3次元幾何学形状のズーミング及び表示を操作するためのこの発明の操作システムを示す。
【図52】例えばジョイスティック及びパンボタンを用いて、3次元幾何学形状のパンニング及び表示を操作するための、この発明の操作システムを示す。
【図53】この発明の3次元ナビゲーション及び操作システムを実行するために、実行される工程及び操作の代表的フローチャートである。
【図54】この発明の側面による、ジョイスティック運動をカーソル運動へ写像する例を示す。
【図55】表示されたパーツの回転軸を動力学的に計算するためになされる工程及び操作の代表的フローチャートである。
【図56】例えばステーションモジュールにおいて設けられ且つ表示されるメインメニューウインドウ表示の例を示す。
【図57】ユーザがパーツ情報を入力し且つ修正することを可能とするように設けられた代表的パーツ情報ウインドウ表示を示す。
【図58】ユーザが曲げ情報を入力し且つ修正することを可能とするように設けられた代表的曲げ線情報ウインドウ表示を示す。
【図59】板金パーツの中間的曲げ段階を観察するための、この発明の代表的曲げ順ウインドウ表示を示す。
【図60】板金パーツの中間曲げ段階をシミュレートするための、この発明の代表的曲げシミュレーションウインドウ表示を示す。
【図61】2次元から3次元への変換のためユーザに対して設けられ且つ表示される、この発明の代表的メニュースクリーン図及び構造である。
【図62】この発明の2次元クリーンアップ操作のための代表的メニュースクリーン図及び構造である。
【図63】一端が開放された線分が除去される前のパーツの3次元表示の例を示す。
【図64】パーツの2次元3面図からパーツの3次元モデルを生成する際に使用されるこの発明の3次元クリーンアップ工程による、前記一方が開放された線分が3次元表示から除去された後のパーツを示す。
【図65】曲げ線が特定される前のパーツの代表的3次元表現を示す。
【図66】この発明の3次元クリーンアップ工程によるモールド線が追加された後のパーツを示す。
【図67】曲げ線をきれいにし且つ面をトリミングする前のパーツの代表的部分を示す。
【図68】この発明の3次元クリーンアップ工程による前記正常化及びトリミングが行なわれた後のパーツの部分を示す。[0001]
Related application data
This application is in accordance with US Provisional Application No. 60 / 016,948 entitled “Apparatus and Method for Managing and Distributing Design and Manufacturing Information Throughout the Sheet Metal Fabrication Equipment” filed on May 6, 1996. It is claimed that it is expressly incorporated herein by reference in its entirety.
[0002]
Copyright notice
Part of the specification of this patent document is subject to copyright protection. The copyright holder does not object to the copying by some of the patent specifications listed in the US Patent and Trademark Office patent files or records, but for all others, the copyright holder has all the copyrights Hold on.
[0003]
Background of the Invention
Field of Invention
The present invention relates generally to the manufacturing field and the fabrication of parts such as sheet metal parts. In particular, the present invention relates to an apparatus and method for managing and distributing design / manufacturing information throughout a factory to facilitate the manufacture of bent sheet metal parts.
[0004]
Background information
Traditionally, for example, the fabrication of bent sheet metal in a sheet metal progressive manufacturing facility involves successive fabrication and manufacturing stages. The first stage is the design stage, where thin metal parts are designed based on customer specifications. Typically, the customer orders the production of specific sheet metal parts equipment. Customer orders typically include product and design information needed to produce parts in the factory. This information may include, for example, the part's geometric dimensions, the material required for the part (eg, steel, stainless steel, or aluminum), special forming information, quantity, delivery date, and the like. Thin metal parts requested by customers can be designed and manufactured for a wide variety of applications. For example, the fabricated parts may eventually be used in computer cases, switchboards, aircraft armrests, or automobile door panels.
At the design stage, the design of the sheet metal parts is done in the design department of the manufacturing facility by means of a suitable computer aided design (CAD) system. Depending on customer specifications, programmers can also create 2D models of sheet metal parts using CAD systems. Typically, the customer provides a blueprint that includes the important geometric dimensions of the part. This blueprint may show special shaping or symbols included in the part, or holes or other openings in the surface of the sheet metal part. Design programmers often use this blueprint to create 2-D models with CAD systems. The 2-D model may also include a plan view including bend lines and / or dimensional information of the sheet metal part and one or more perspective views.
[0005]
Before actually bending a sheet metal part, the part must first be stamped and / or cut from the raw material. In processing stock materials, computer numerical control (CNC) or numerical control (NC) is usually used to control and operate a punch press or plasma or laser cutting machine. To facilitate the processing of this inventory material, design programmers can create control codes based on 2-D models using computer-aided manufacturing (CAM) systems or CAD / CAM systems. This control code may include a part program that can be incorporated into a punching press and / or cutting machine and used to punch or cut sheet metal parts from stock materials.
[0006]
The next stage of the manufacturing process is the bending planning stage. At this stage, a bending plan is established by the bending operator at the workplace. The operator is usually given a blueprint or 2-D drawing of the part along with one or more stock materials that have been cut or punched. With these materials, the bending operator develops a bending plan that defines the tool to be used and the bending procedure to be performed. Bending workshops also include CNC metal bending machines, such as CNC press brakes, which can be programmed based on a bending code or a bending plan in which the operator has entered data.
[0007]
Once the bending plan is created, the operator sets up a workshop for initial testing of the bending sequence. In this test phase, the stamped or cut material is manually incorporated into the press brake, which is operated to machine the bend into the workpiece according to a programmed sequence. The operator analyzes the finished bent sheet metal parts to check whether they meet customer specifications. Depending on the result of the initial work of the press brake, the operator may edit the bending program and correct the bending sequence. The operator may also feed the results back to the design section so that the design of the sheet metal part can be modified appropriately. Testing is usually continued until the bent sheet metal parts are within the required design specifications.
[0008]
One of the final stages of the fabrication process is the bending stage. After the bending plan is created and tested, the bending operator equips the bending shop with the necessary tools and activates the press brake according to the bending plan and the stored bending program or code. Work schedules are also created to ensure that the required amount of stamped or cut material is secured at the bending site and that other work has been completed by the designated delivery date. Work schedules may be created or modified by the workshop supervisor in the early stages of the production process and / or in parallel with the entire process. Once the final bent sheet metal part has been fabricated, the parts are collected and packaged for delivery to the customer.
[0009]
Normal manufacturing and manufacturing processes have several drawbacks and disadvantages. For example, each customer's design and manufacturing data is usually stored physically (eg, in a paper cabinet by paper) and electronically (eg, on a disk or magnetic tape), but such data is usually stored separately and retrieved. It is not easy. Furthermore, in many factory environments, the distribution of important work information takes the form of work or planning forms distributed throughout the factory. As a result, data is often lost or damaged, making it difficult to retrieve design manufacturing data for previous or similar tasks. In addition, the lack of data storage means that valuable time is lost in distributing design and manufacturing information to all factory workplaces and other locations. Also, part design and bend planning are mainly done by design programmers and bend operators, and it depends heavily on personal knowledge, skills and experience, so manufacturing time is lost significantly between sheet metal parts and bend plans. .
[0010]
In recent years, developments and attempts have been made to improve conventional sheet metal manufacturing processes and improve efficiency throughout the process. For example, the use and development of 2D (2-D) and 3D (3-D) modeling in commercial CAD / CAM systems has facilitated and improved the bending sheet metal fabrication process and modeling. Now, design programmers and operators can use 2-D and 3-D displays to better understand the shape of parts and to create part designs and bend code sequences more efficiently. The ability to store and transfer data electronically improved the flow of information from the design department to the workplace. Advances in computers and data communication networks have made it unnecessary to locate old paper tapes and magnetic disks from cabinets or files.
[0011]
Despite these advances, there is still a need to improve the organization and flow of design and manufacturing information throughout the organization and factory environment. For example, in a conventional manufacturing system, the critical design and manufacturing information for each customer order is not logically related so that it can be easily accessed and searched anywhere in the factory. Previous systems also do not have the ability to search for job information based on various features, such as the features and characteristics of sheet metal parts. The ability to search and retrieve previous job information, eg, based on searching for identical or similar parts, greatly enhances the overall manufacturing process and reduces the required manufacturing time for future jobs.
[0012]
Past attempts are also lacking in facilitating the design of sheet metal parts by design programmers and workshop operators. 2-D and 3-D modeling systems help designers better understand the shape and geometry of parts, but this system does not reduce the burden placed on design programmers and workplace operators. . For example, these systems do not allow design programmers to easily convert an existing 2-D CAD model into a 3-D display. Also, even though 2-D and / or 3-D drawings of parts are provided to help the shop operator make a bending plan, the operator must determine the necessary tools and bending procedures by hand and / or trial.
[0013]
Summary of invention
In light of the above, the present invention, through one or more aspects, embodiments and / or features or features or subcomponents of the invention, has one or more of the objects and advantages noted below. It is meant to bring.
[0014]
It is a general object of the present invention to provide an apparatus and method for managing and distributing design and manufacturing information throughout a factory to facilitate the production of parts such as bent sheet metal parts.
[0015]
A further object of the present invention is to provide an apparatus and method for preventing the loss or destruction of important work information in, for example, an advanced sheet metal fabrication facility, and facilitating the effective utilization and organization of the accumulation of specialized knowledge.
[0016]
Another object of the present invention is to provide an apparatus and method for logically storing both the design and manufacturing information of each customer's order so that it can be easily accessed and searched anywhere in the factory. There is.
[0017]
Yet another object of the present invention is to manage design and manufacturing information that is logically stored so that work data can be easily searched and searched in a central database or file server anywhere in the whole plant, To provide an apparatus and method for dispensing. Work data can provide not only work-related design and manufacturing information, but also actual bending codes to perform the required bending operations.
[0018]
A still further object of the present invention is to provide an apparatus and method for searching previous work information including design and manufacturing information based on various search criteria. The search criteria can include, for example, the features and characteristics of the sheet metal parts that are to be produced, so that previous job information related to the same or similar parts can be reduced to reduce the overall production time for future jobs. Available.
[0019]
Another object of the present invention is to replace the traditional paperwork or planning paper associated with each customer order with an electronic job sheet that can be instantly accessed from anywhere in the factory. Electronic job sheets can be displayed anywhere and are relevant to the job, including 2-D and / or 3-D model images of the part, tool selection, optimal bending procedure, and the required staging information and barcode or identification number Includes important design and manufacturing information. The electronic job sheet is also equipped with audio and / or video components that record and record special instructions or procedures that may be useful in the future when the bending operator performs the same or similar work again.
[0020]
Another object of the present invention is to reduce the time required to analyze part drawings by providing 2-D and 3-D computer images of sheet metal parts. Various images can be provided, including solid 3D image mode, 3D wireframe image mode, 2-D planar image mode and orthographic image mode. A variety of different image functions are also provided, including zooming, panning, rotation and automatic dimensioning, which are useful for the analysis of sheet metal parts.
[0021]
It is a further object of the present invention to provide an apparatus and method that facilitates a designer's design of sheet metal parts and production of bending plans. For example, it is an object of the present invention to make it possible to easily produce a 3-D display of a part from a 2-D model of an existing part. Yet another object of the present invention is to provide a graphics interface for reducing the time to create bend plans and programmed bend codes.
[0022]
In view of the above, the present invention is directed to an object oriented bend model stored on a computer readable medium to represent a part (eg, a sheet metal part) to be manufactured in an installation. The object-oriented bend model includes a part class including a plurality of objects having part information related to the feature of the part and bending information related to a bending operation performed on the part. The part information includes part design and manufacturing information. The part design information relates to the representation of the part in 2D and 3D coordinate spaces. Furthermore, the bending information comprises a group of objects with bending data and instructions for performing bending operations on the bend lines of the parts. The bending data includes a bending angle amount and a bending radius amount.
[0023]
According to one aspect of the invention, the part class includes attributes comprising bending sequence information related to the order in which the bending operations are performed on the part. The attribute includes a part material type and a part thickness. Further, the plurality of objects include a surface object, and the surface object includes design data related to a dimension of each surface of the part and one data related to a representation of each surface of the part in at least one coordinate space. Including. The plurality of objects further include bend line objects. The bend line object includes design data associated with the dimensions of each bend line of the part and one data associated with a representation of each bend line of the part in at least one predetermined coordinate space. The bend line object further includes bend manufacturing data associated with a bend operation performed on the part. The bending manufacturing data includes part width data, bending pitch and orientation data for each bending line of the part.
[0024]
The plurality of objects of the bending model also includes a hole object and a forming object. The hole object includes design data related to the dimensions of at least one hole in the part and one data related to a representation of each hole in the part in at least one predetermined coordinate space. The molding object includes design data relating to the dimensions of each molding part of the part and one data relating to the representation of each molding part of the part in at least one coordinate space. A topology object and a bending property object are further provided. The topology object includes part topology data related to the feature of the part, and the feature of the part includes at least one of a surface or hole of the part, a forming part, or a bend line. The bending property object further includes manufacturing constraint data associated with the part. The present invention is also directed to an object oriented bending model stored on a computer readable medium for representing sheet metal parts to be manufactured in a manufacturing facility. The object-oriented model includes a part class including a part object having a plurality of part characteristics and a plurality of objects for representing a sheet metal part in a two-dimensional coordinate space and a three-dimensional coordinate space. The plurality of objects include design information related to characteristics of the sheet metal part and bending information for performing at least one bending operation on the sheet metal part. The feature of the part includes a surface, a hole, a forming portion, and / or a bending line, and the plurality of objects include a surface object, a hole object, a forming object, and / or a bending line object.
[0025]
The bending information relates to a plurality of bending operations performed on the sheet metal part. The bending information comprises a group of objects with bending data and instructions for performing at least one bending operation on the sheet metal part. The bending data includes, for example, a bending angle amount and a bending radius amount. Further, the bending attribute includes bending sequence information related to the order in which the bending operation is performed on the sheet metal part. The part attributes also comprise part material type and part thickness.
[0026]
According to another aspect of the invention, an object-oriented bending model viewer configured for use in a computer control system is provided. The computer control system includes a database storing bending model data related to the part and a display device for displaying an image of the part. The object-oriented bending model viewer includes a bending model viewer observation class, and the bending model viewer observation class includes an observation model attribute and at least one observation function executed as an element function of the bend model viewer observation class. At least one image of the part is displayed on a display device of the computer control system based on the bending model data and the observation model attributes.
[0027]
Various additional features are provided in the object-oriented bending model viewer of the present invention. For example, the observation model attribute includes display information related to a predetermined observation mode or a plurality of modes, and the predetermined observation mode or the plurality of observation modes is a solid line observation mode or a wire frame observation mode, a two-dimensional plan view mode, and Or it includes a perspective view mode. The bending model viewer viewing class also includes information for modifying the image of the part in response to one or more viewing functions. The observation function includes, for example, a zooming function or a rotation function or a tanning function and / or a dimensioning function. The zooming function includes an operation for zooming the image of the part on a display device, and the rotation function includes an operation for rotating the image of the part. The tanning function includes an operation of tanning an image of the part on the display device, and the dimension function is configured to display an image of the part to additionally display dimensional information related to at least one feature of the part. Including operations to correct The dimensional information includes a length of at least one bend line of the part or a bend angle of each bend line of the part and / or a length of at least one flange portion of the part.
[0028]
The object-oriented bending model viewer is observable for maintaining and providing observability information related to the feature of the part that is observable on the display device based on the currently displayed image of the part Has sexual function. The bending model viewer observation class includes information for correcting an image of a part according to at least one observation function. The observation function includes a dimension function including an operation for correcting the image of the part based on the observation possibility information and expressing the dimension information related to the observable characteristic of the part. The object-oriented bending model viewer further includes zoom factor information related to the zoom factor of the currently displayed image of the part image on the display device.
[0029]
In accordance with yet another aspect of the present invention, a system for manipulating a displayed image of a part is provided. The displayed image of the part is displayed on a screen in a three-dimensional coordinate space. The system includes: An input device (eg, a joystick device or a mouse device) for generating a command signal, wherein the command signal relates to at least one predetermined viewing function configured to modify the displayed image of the part. A current appearance determination system for determining the current appearance of the displayed image. A setting system for dynamically setting the rotation axis of the part based on the current appearance of the displayed image. An image correction system for correcting an image displayed on the part based on the command signal and a rotation axis in accordance with the observation function.
[0030]
The predetermined observation function includes a rotation function, and the image correction system is configured to rotate an image on which a part is displayed around the rotation axis based on the command signal. Further, the current appearance determination system is configured to determine whether the current appearance of the displayed image of the part is the entire appearance of the part or a partial appearance of the part. When the current appearance determination system determines that the current appearance of the displayed image of the part is the entire appearance, the setting system causes the rotation axis of the part to pass through the geometric center of the part. Is configured to set to Further, the setting system sets the rotation axis of the part to pass through the center of the screen when the current figure determination system determines that the current figure on which the part is displayed is a partial figure. It is configured.
[0031]
The system has other features. For example, a parts observable system is provided that determines whether a part of the part is observable in the center of the screen based on its current appearance. In that case, when the parts observability system determines that the part of the part is observable, the rotation axis is set to pass through the part of the part at the center of the screen. It is configured. Further, the setting system rotates the center of the screen about the Z coordinate axis of the geometric center of the part when the part observability system determines that the portion of the part is not observable at the center of the screen. It is comprised so that an axis may pass.
[0032]
When the current figure determination system determines that the current figure of the displayed image of the part is a partial figure, the part of the part located in the center of the screen and closest to the camera field of view of the screen is identified. There is a system to do this. An object detection system is also provided for determining whether a specified portion of the part corresponds to an opening in the part. When the object detection system determines that the identified part of the part is not related to the opening of the part, the calculation system sets the rotation axis to pass through the identified part of the part. It is configured. Further, when the object detection system determines that the identified portion of the part is related to the opening of the part, the center of the screen is set to the rotational axis at a depth corresponding to the Z coordinate of the geometric center of the part. The setting system is configured such that is set.
[0033]
The input device includes a joystick device and / or a mouse device. The joystick device includes a joystick virtual space, and a command signal from the device includes information related to movement of the joystick device within the joystick virtual space. The image correction system has a mapping system for mapping movement of the joystick device in the joystick virtual space to virtual movement in the screen space of the screen. Therefore, the image correction system corrects the displayed image of the part based on the movement of the cursor mapped from the joystick movement. The mapping system is configured to map movement of the joystick device to movement of a cursor in the screen space based on a ratio of the size of the screen space to the size of the joystick virtual space. For example, the movement of the cursor is mapped by the mapping system based on the following equation.
[0034]
Current position = previous position + (scale factor x V)
Here, the current position is the current position of the cursor in the screen space, the previous position is the previous position of the cursor in the screen space, and the scale factor is a ratio of the dimension of the screen space to the dimension of the joystick virtual space. V is a vector related to the movement and direction of the joystick device from the joystick origin to the current joystick position in the joystick virtual space.
[0035]
According to another feature of the invention, the mapping system comprises a scale adjustment system for adjusting a scale factor required by the mapping system. The scale adjustment system is configured to provide a scale factor that is adjusted by multiplying a ratio of the screen space dimension to the joystick virtual space dimension by a predetermined adjustment factor. The mapping system is configured to use the adjusted scale factor when mapping the joystick motion. As a non-limiting example, an adjustment factor of 3 is used.
[0036]
The invention also includes a method of manipulating the displayed image of the part. Here, the displayed image of the part is displayed on a screen in a three-dimensional coordinate space. The method includes the following steps. Receiving a command signal generated from the input device; Here, the command signal relates to at least one predetermined viewing function configured to modify the displayed image of the part. The process of determining the current appearance of the displayed image of the part on the screen. Dynamically setting the rotational axis of the part based on the current appearance of the part. A step of correcting the displayed image of the part based on the command signal and the rotation axis according to the observation function.
[0037]
According to the above-described method of the present invention, the predetermined observation function includes a rotation function, whereby the displayed image of the part is rotated around the rotation axis based on a command signal. Further, the setting step includes an operation of setting the geometric center of the part so that the rotation axis of the part passes through when the current appearance of the displayed image of the part is determined to be the whole figure. including. The setting step also includes an operation of setting the rotation axis of the part to pass through the center of the screen when it is determined that the current appearance of the displayed image of the part is a partial appearance. .
[0038]
In accordance with another aspect of the present invention, a system and method for displaying dimensional information along with an image of a part on a screen is provided. The method includes the following steps. Determining a current appearance of the displayed image of the part and determining which of a plurality of features are observable on a screen based on the current appearance. Selectively displaying on the screen together with the displayed image of the part dimensional information only about each of the part features determined to be observable on the screen. The method further accesses bend model data associated with the part and determines all possible positions on the screen for displaying dimensional information for each of the part features based on the bend model data. . Further, the selectively displaying step applies a predetermined heuristic to determine a location for displaying the dimensional information of the observable feature based on the possible position. The heuristic displays the dimensional information at a position on the screen existing outside the displayed image of the part, and displays the dimensional information at a position on the screen closer to the observer's observation point. And / or displaying the dimension information so that the dimension information does not overlap on the screen.
[0039]
The displayed dimensional information includes a bending length and a bending angle for each bending line of the part. The dimensional information also includes an inner bend radius and a bend reduction amount associated with each bend line of the part. Here, the display step displays a bend line length, a bend angle, a bend radius, and / or a bend reduction amount for each bend line of the part determined to be observable based on the current appearance. Other dimensional information such as the flange length of each flange portion of the part is also displayed. Additional information is also displayed, such as the part width and depth and height.
[0040]
The step of selectively displaying includes performing an automatic dimensioning operation for displaying dimension information of only predetermined features of the part. Accordingly, dimensional information is displayed only for certain features that are determined to be observable. Further, the step of selectively displaying includes performing a manual dimensioning operation to display dimension information selected by a user related to the feature of the part. Accordingly, each piece of dimension information selected by the user is displayed only for the features of the parts that are determined to be observable. A system is also provided for displaying dimensional information along with an image of the part displayed on the screen. The system determines a current appearance of a displayed image of a part and, based on the current appearance, a system for determining which of a plurality of features are observable on a screen and the display of the part And a system for selectively displaying dimensional information on only the features of the parts that have been determined to be observable on the screen along with the rendered image.
[0041]
Based on this bend model data as well as an access system for accessing the bend model data associated with the part, all possible positions on the screen to display dimensional information for each of the part features are determined. There is a system to do this. The selective display system includes a system for applying a predetermined heuristic to determine where to display dimensional information of observable features based on the possible positions. The displayed dimension information includes a bend line length, a bend angle, a bend radius, and / or a bend reduction amount for each bend line of the part that is determined to be observable based on the current appearance. Other dimensional information is also displayed, such as the flange length of each flange portion of the part. Additional information such as part width and depth and height is also displayed according to the present invention.
[0042]
In addition to the features described above, further features and / or variations thereof can be provided, for example, various combinations or recombinations of the features described above and / or several features described in the detailed description below. It can be applied to recombination with a combination.
[0043]
Those listed above and other objects, features and advantages of the present invention will be described in more detail below.
[0044]
Appendix summary
To further facilitate the detailed description of the present invention, the following source code examples and comments regarding the various features, operations and functions of the invention along with the non-limiting examples of preferred embodiments of the present invention are given below. Browse a number of appendices:
Appendix summary
To further facilitate the detailed description of the present invention, the following source code examples and comments regarding the various features, operations and functions of the invention along with the non-limiting examples of preferred embodiments of the present invention are given below. Browse a number of appendices:
Appendix A is a typical source code for performing a feature extraction operation, for example when searching for one similar part;
Appendix B is typical source code that exercises the similarity index operation, for example, when searching for several similar parts of the present invention;
Appendix C is typical source code for performing bend line detection operations in this invention;
Appendix D is typical source code for performing the 2-D cleanup of the present invention, which creates a 3-D model of a sheet metal part based on the original 3-D drawing from three directions Can be used for:
Appendix E is typical source code for performing various view modes and functions in the bending model viewer of the present invention;
Appendices F, G, H and I are typical source code and comments for implementing the automatic dimensioning characteristics of the present invention;
Appendix J is typical source code for performing the part / entity observability function of the bending model viewer of the present invention;
Appendix K contains general comments based on various lessons of the present invention regarding the implementation of the bending model and the construction of the part structure,
Appendix L is typical source code that implements a 3-D operation and navigation system with dynamic calculation of the rotation axis of a given part.
[0045]
The present invention has been described with reference to numerous figures for examples of preferred embodiments of the invention not limited by the following detailed description, wherein like reference numerals in the description indicate like parts throughout the drawings. .
[0046]
Detailed description
In accordance with the present invention, there is provided an apparatus and method for managing and distributing design and manufacturing information across all factories and facilitating the production of parts within the plant. This feature of the present invention can be used in a wide range of factory environments and devices, and in particular, the present invention can be used to satisfy factory environments that are performed at different locations in a series of manufacturing and manufacturing stages. Through non-limiting examples and various examples, the present invention is described with reference to the fabrication of bent sheet metal parts, for example, in an advanced sheet metal manufacturing facility.
[0047]
In FIG. 1, a general sheet metal manufacturing facility 38 in general according to an embodiment of the present invention is illustrated in block diagram form. As shown in FIG. 1, a sheet metal manufacturing facility or factory 38 has a number of locations 10,12,14 ... 20 distributed throughout the factory.
[0048]
These locations include a design office 10, a shipping workshop 14, a punching workshop 16, a bending workshop 18 and a welding workshop 20. The sheet metal factory 38 shown in Fig. 1 has only six separate locations, but of course the factory can have more than six separate locations, and each type of office shown in Fig. 1 Or the workplace may occupy more than one place. For example, one or more punching workshops 16, bending workshops 18, and / or welding workshops 20 can be provided depending on the size of the equipment 38 and the production capacity requirements. In addition, the factory 38 may have one or more design offices 10, assembly workshops 12 or shipping workshops 14, and may have other types of locations to facilitate the fabrication of bent sheet metal parts.
[0049]
Each location 10, 12, 14,... 20 in the factory 38 is equipped with tools to perform and perform one or more separate production steps or processes associated with the production of the part. For example, design office 10 may have a suitable CAD / CAM system to facilitate the design of sheet metal parts based on customer specifications. The CAD / CAM system may include one or more personal computers and displays, printers and commercially available CAD / CAM software. As a non-limiting example, the CAD / CAM system at design office 10 is Autocad or Cadkey, or Amada America, Inc. (formerly US Amada Corporation) Amada AP40 or AP60 CAD / CAM available from Bijuena Park, Calif. A system can be included. You can also use Windows-based CAD systems available from Ashler, such as Baerum. Using this CAD / CAM system, design programmers can create 2-D models and / or 3-D models of sheet metal parts based on drawings and data on customer orders. The design programmer also creates a control code based on the design of the sheet metal part, so that the part program that controls the CNC punching press and / or the cutting machine, for example to punch or cut the sheet metal part from the workpiece, Can be created.
[0050]
The punching workshop 16 and the bending workshop 18 are each provided with any combination of CNC and / or NC machine tools. For example, the punching workshop 16 may have one or more Koma series and / or Pega series Amada turret punching presses, or other commercially available CNC and / or NC punching presses, and a bending workshop. 18 can have one or more CNC and / or NC press brakes such as RG series Amada press brakes or other commercially available multi-axis gauging press brakes. In addition, the welding workshop 20 can be equipped with suitable welding equipment to perform any necessary welding to the sheet metal parts. The punching work place 16, the bending work place 18 and the welding work place 20 can be installed anywhere in the factory of the equipment 38, and are equipped with machines that can be moved manually by skilled operators (eg punching press operators, bending machine operators, etc.). . Fully automatic or robot-assisted machines such as Amada Cellulomini and Amada Promcam can also be provided at these locations. The necessary punching and bending operations, or any necessary welding operations, can be performed during the manufacturing process at these workshops.
[0051]
In addition, as shown in FIG. 1, the progressive sheet metal equipment 38 also includes an assembly workshop 12 and a shipping workshop 14. Assembly workshop 12 and shipping workshop 14 also include packaging, route assignment and / or transportation equipment necessary to facilitate assembly and shipment of manufactured parts to customers.
The assembly and shipment of parts is manually exercised or controlled by factory personnel, but can also be machine automated and / or machine assisted. Furthermore, the assembly workshop 12 and the shipping workshop 14 are physically located close to the factory workshop (eg, near the punching workshop 16, bending workshop 18 and / or 'welding workshop 20), or separate from the sheet metal mill 38. Can be placed in any facility or area.
In keeping with the aspects of the present invention, important design and manufacturing information management and distribution is performed by electronically storing and distributing design and manufacturing information. By replacing or supplementing traditional paper work setups or worksheets with electronic job sheets that can be accessed instantly from anywhere in the factory, the present invention improves the overall efficiency of the factory. Can do. In addition, various aspects and features of the present invention improve the organization and access of stored design and manufacturing information. Furthermore, access to and retrieval of previous job information regarding similar or identical sheet metal parts can be made through various features of the present invention.
[0052]
For this purpose, the various aspects of the present invention are implemented by providing a communication network 26 that connects the server module 32 and database 30 to each of a number of locations 10, 12, 14 ... 20 within the sheet metal facility 38. The As will be discussed later, each location 10, 12, 14... 20 has a station module that interfaces to the communication network 26 and database 30. Figures 1, 2 and 3 show non-limiting examples of these features and implementations of the invention.
[0053]
As shown in FIGS. 1 and 2, the communication network 26 connects each of the various locations 10, 12, 14... 20 of the equipment 38, the server module 32, and the database 30. The communication network 26 may be any network that can transmit data and information between the locations 10, 12, 14,... 20 and the server module 32 and the database 30. Transmission is performed electronically or optically by radio frequency transmission or far infrared transmission. By way of non-limiting example, the communication network 26 can be configured with a local area network (LAN), an ethernet, or similar network structure. As will be discussed further below, each of the locations 10, 12, 14,... 20 also includes a network termination connection device (eg, a computer, minicomputer or workstation) and / or for transmitting and receiving information over the communications network 26 and / or Or you can have peripherals (eg display monitors or screens, printers, CD-ROMs, and / or modems). The network termination equipment and peripherals include hardware and appropriate software or program logic for interfacing with the communications network 26 and, as will be discussed in detail later, to provide the various features and aspects of the present invention. When installing a computer in a factory location, the computer may be a stand-alone computer or a general-purpose computer that is a part of the equipment or mechanical interface device in the location. For example, the computer may be an IBM compatible personal computer or a computer that is part of a machinery interface / control system such as Amada AMNC.
[0054]
Server module 32 and database 30 are also connected to a communications network.
Server module 32 includes a personal computer, minicomputer or miniframe having hardware and software suitable for interfacing with communications network 26. Server module 32 may also include software and firmware that meet the various features of the invention, as will be described in detail later. Further in line with the present invention, the server module 32 may have a database 30 for storing design and manufacturing information related to customer orders. The database 30 includes a commercially available database having a sufficient storage capacity, and can store design and manufacturing information and other data, tables, and / or programs of factory customers. For example, the database 30 may include a squeegee (SCSI) memory disk with a storage capacity of 4 GB or more. Design and manufacturing information stored in the database 30 can be accessed and distributed to various locations 10, 12, 14,... 20 of the sheet metal facility 38 through the communication network 26. Various data formats, such as structural query language (SQL), can be used to access or store data in the database 30. Further, the information stored in the database 30 can be backed up and stored in various types of storage media, such as a magnetic tape, an optical disk, or a floppy disk. The connection between the server module 32 and the communication network 26 of the database 30 may be in a separate area or location within the factory 38 (see, eg, FIG. 1), in a predetermined station (eg, in a design office), or This can be done in close proximity. In the embodiment of FIG. 1, database 30 is depicted as part of server module 32 interfacing with communications network 26 and server module, but database 30 is of course physically separated from server module 32. It can be connected to the communication network 26 and the network database module 34 as shown in FIG.
[0055]
As a non-limiting example in accordance with a preferred embodiment of the present invention, the server module 32 and each location 10,12,14 ... 20 is a 100-200 MHz central processing unit (CPU) including a Pentium or equivalent microprocessor. Including PCs such as IBM compatible machines with high resolution display screens such as SVGA monitors with a storage capacity of at least 32MB and a commercially available 800x600 resolution. Server module 32 and locations 10,12,14 ... 20 also include Joystick or mouse and sound blaster or alternative acoustic and game port adapter cards for information display and control and control It is. Execution system software to support communication is also provided. For example, server module 32 includes Microsoft Windows New Technology (NT) or Windows 95 execution system software (both available from Microsoft, Redmond, WA), and each location 10,12,14 ... 20 Includes Microsoft Windows 95 execution system software. In addition, the server module 32 and locations 10,12,14 ... 20 can support multiple languages (eg English, Japanese, etc.), and the full range of object link and embedded (OLE) servers like OLE2 servers Support.
[0056]
Various database languages and management systems are also used to create, maintain and view information stored in the database. A database language such as Structural Query Language (SQL) can be used to determine, manipulate, and control data in database 30. For example, a SQL server (a retail product available from Microsoft) can be used to implement the present invention. Further, the present invention can facilitate access of information from the database 30 through the communication network 26 by providing an open database-linked open database connectivity (ODBC) compatible driver. For more information on ODBC, see Microsoft Open Database. Connectivity Software Development Kit Available for programmer reference.
[0057]
FIG. 2 is a block diagram of an advanced sheet metal manufacturing facility constructed in accordance with another embodiment of the present invention. In the embodiment of FIG. 2, the database 30 and the server module 32 are installed separately, and the database 30 is connected to the communication network 26 via the network database module 34. As described above, the present invention is not limited to this configuration, and the database 30 and the server module 32 can be installed together (for example, as shown in FIG. 1), and have the function of accessing the database of the network database module 34. Can be incorporated into server modules. FIG. 2 also shows an example of a station module 36 that can be installed at various locations 10, 12, 14... 20 within the sheet metal manufacturing facility 38. For the purposes of illustration, FIG. 2 illustrates a station module 36 installed in the bending station 18. Although not shown in the example of FIG. 2, a similar station module 36 can be installed elsewhere in the facility 38.
[0058]
As shown in FIG. 2, each module (server module 32, network database module 34 and station module 36) can be connected to the communication network 26 via a network interface card or port 42. The network interface card 26 is dedicated to the vendor and can be selected based on the type of communication network selected. Each module 32, 34, 36 may include network software or programmed logic for interfacing with the communication network 26. Communication network 26 is Ethernet (Ethernet), from many types of commercial cables such as 10 base / T (twisted pair), 10 base / 2 (coaxial), or 10 base / 5 (thick film cable) to equipment 38 A cable of a type selected based on the size and the required cable length may be used.
[0059]
In FIG. 2, the server module 32 may include a display monitor or personal computer having a CRT 44 and input / output devices including a keyboard, mouse and / or joystick. The network interface card 42 can be inserted into an expansion slot provided or a port of the personal computer 40. In addition, the personal computer 40 can include a processing speed of 100-200 MHz and a Pentium or Pentium Pro microprocessor. The personal computer 40 may also include, for example, 32 MB or more main storage and 1.2 GB or more random access storage (RAM).
Display 44 may include a high resolution display screen, such as a commercially available SVGA monitor with a resolution of 800 × 600. To support the various graphics and information displayed on the display 44, the personal computer 40 can also include a commercially available graphics card such as a PCI graphics card. Further, the computer 40 may include a sound blaster, or compatible voice and game port adapter card, and the input / output device 46 may include a keyboard, joystick and / or mouse.
[0060]
In order to implement the various features of the present invention, the server module 32 is provided with software and various package software. For example, the server module 32 includes Microsoft Windows NT (workstation type) or Windows 95. In addition, server module 32 can include software or routines with programmed logic to provide the server module with features and features unique to the present invention (see, eg, FIG. 4). As will be discussed in more detail later, these routines can be created by high-level programming languages such as C ++ and object-oriented programming. Server module 32 also includes CAD or CAD / CAM software such as Belm or Amada AP40 or AP60 software to input and / or create 2-D and 3-D drawings based on customer specifications. Or it can be interfaced. For this reason, the server module can be placed in the design office 10 of the manufacturing facility 38. In order to access data from the database 30, the server module 32 has an ODBC driver, such as a Microsoft ODB driver, and can use SQL as a data access standard. An OLE server, such as an OLE2 server, can be provided for linking data.
[0061]
In the embodiment of FIG. 2, the database 30 is provided separately from the server module 32 and is connected to the communication network 26 via the network database module 34. As mentioned earlier, the database 30 should contain a SCSI disk (eg 1-4 GB) with appropriate storage space chosen based on the size of the factory 38 and the amount of component information stored in the database. Can do. The network database module 34 may include an expansion slot with a personal computer 40, such as an IBM compatible with a Pentium microprocessor, and a network interface card 42 for interfacing with the communications network 26. The database 30 can be connected to a personal computer 40 via a data bus, and the personal computer 40 also includes standard displays, display monitors, or input / output devices such as CRTs and keyboards (not shown in FIG. 2).
[0062]
In order to facilitate access to the database 30 based on SQL, the personal computer 40 of the network database module 34 can be installed in conjunction with a commercially available SQL server such as a Microsoft SQL server or an Oracle SQL server. An OLE server, such as an OLE2 server, can be provided for linking data. The personal computer 40 can also be equipped with various software such as DOS and Microsoft Windows NT (server version).
The embodiment of FIG. 2 includes an exemplary implementation of one station module 36. In this embodiment, the station module 36 is installed in the bending station 18. As shown in FIG. 2, the station module 36 includes the same hardware as the server module 32. That is, each station module (eg, the other station shown in FIG. 1) includes a computer 48 having a display monitor or CRT 44 and an input / output device 46 including a joystick or mouse. The network interface card 42 can be plugged into an expansion slot or port provided in the computer 40. As previously discussed, the station module 36 computer may be a stand-alone computer or a general-purpose computer that is part of a personal computer, or an interface device of equipment or machinery provided at the location. For example, the computer 48 may be a self-supporting personal computer such as an IBM compatible with a 100-200 MHz operating speed and a Pentium or Pentium Pro microprocessor, or the computer 48 may be a mechanical device such as an Amada AMNC system. It may be a part of the interface / control system or a computer embedded in the system. The computer 48 may also have, for example, 32 MB or more main memory and 1.2 GB or more random access memory (RAM). The display 44 may include a high resolution display screen, a commercially available SVGA monitor having a resolution of 800 × 600, for example. To support the various graphics and information that are displayed on the display 44, the computer 48 can include a commercially available graphics card, such as a PCI graphics card. In addition, the computer 48 may include a sound blaster or compatible acoustic and game port adapter and a joystick or mouse for the input / output device 46 supporting it.
[0063]
In order to implement the various features of the present invention, the station module 36 includes software and various commercially available software. For example, the station module 36 includes basic software such as Microsoft Windows 95 or Windows NT (workstation version). In addition, the station module 36 is provided with software or programmed logic equipment routines to provide the station module with features and features unique to the present invention (see, eg, FIG. 5). As will be discussed in more detail later, these routines can be developed by using high-level programming languages such as C ++ and object-oriented programming techniques. To access and link data, the station module 36 includes an OLE server such as a microshift OBCD driver and an OLE2 server. Like the server module 32, the station module can also use SQL as a basis for accessing data from the database 30.
[0064]
If the station module 36 of the bending station 18 is provided as a free-standing personal computer, software for creating bending code data and interfacing with bending machinery 25 (eg CNC or NC controlled press brake) Can be equipped. In the embodiment of FIG. 2, the computer 36 is equipped as a personal computer and is depicted as having software that interfaces with the bending machine 25 through a standard RS-232-C wiring interface. This interface is equipped so that the station module 36 can communicate with the bending machine 25 through the RS-232-C interface and send and receive bending codes. The implementation of this interface is for the vendor and depends on the data format and instruction set used in the bending machine 25. All data sent from the station module 36 to the bending machine 25 must be formatted according to the machine instruction set assigned to the machine. The computer 48 of the station module 36 is equipped with a commercially available CNC or NC software for bending code generation, so that it can be integrated into a CNC or NC system (eg Amada AMNC) embedded computer for such machinery. Simulate the normal functions.
[0065]
FIG. 3 is an exemplary embodiment showing the respective data flow between the data server module 32, the database 30 and the sheet metal manufacturing facility 38. In FIG. 3, the server module 32 and the database 30 (integrated in the network database module 34) communicate with each other separately for the sake of illustration and to facilitate the description of the respective data flow in the embodiment. Directly connected to the network 26, the data flow between these components takes place through a communication network. Of course, as those skilled in the art will appreciate, a wide variety of data flow schemes can be used between these components; and if the database 30 is directly connected to the server module 32, the data Can be transmitted directly from the server module to the database without using the communication network 26. Further, for ease of description, the communication network 26 of FIG. 3 has been simplified, and only the punching station 16 and bending station 18 are shown in the figure. However, the flow of data exchange from locations 10,12,14 ... 20 (including any other location or area in the factory) is similar to that shown for punching station 16 and bending station 18. Can be done.
[0066]
Design and manufacturing information associated with each customer order can be organized and stored in the database 30. When an order is first received from a customer, basic product and design information is entered into the server module 32 and then transmitted to the database 30 for storage. As previously discussed, the server module 32 includes suitable means for entering data, such as a personal computer with a keyboard. When a personal computer is used in the server module 32, software for generating a menu screen can be provided to facilitate data entry by factory staff. The data input program may be an application based on Microsoft Windows, for example, and may have a help and / or menu screen. By way of non-limiting example, the data that is input / created into the server module 32 and transferred to the database 30 includes part information, bending models, feature extraction data, and bending as generally shown in FIG. Line information can be included.
[0067]
The part information can include, for example, the part or order reference number, the customer's name, a brief description of the part, the batch size or quantity, and the scheduled delivery date. Bending model data includes part material information such as overall part dimensions (eg width, height, depth) and material type (eg steel, stainless steel or aluminum), thickness and tensile strength. Can be included. In addition, feature extraction data can be manually entered and / or automatically generated to identify key features of the part and facilitate searching for similar parts in the database and other searches. The feature extraction data can be stored in a separate file in the database 30, or can be stored together with the bending model data and the work information of each part. Feature extraction data can include, for example, the number of surfaces and faces, the number of bend types (eg, positive bends between two faces, or negative bends between two faces), relationships between faces and / or holes in the part Can include a number of openings of the type As discussed in more detail below, such data can be represented and organized by a feature-based part matrix and / or a sequential search key (see, eg, FIGS. 6-10 below). Finally, the bend line information can be entered into the server module 32 for storage in the database 30. The bend line information includes main bend line information including, for example, a bend angle, a bend length, a bend inner radius (IR), a reduction amount, and a bend direction (for example, front or rear) of each bend of the part.
[0068]
Each location 10,12,14 ... 20 includes a station module (such as station module 36 described above) connected to the communication network for transmitting and receiving data to and from database 30 through communication network 26. be able to. In FIG. 3, the punching station 16 and the bending station 18 are generally shown in block diagram with the station module. As previously discussed, the station module includes, for example, software, or control logic and a stand-alone personal computer, or a general purpose computer that is part of the equipment or machinery provided in its place. Depending on each customer order, design and manufacturing information (including part information, bend line information and bend model data) can be accessed and retrieved by entering a predetermined reference number or code. The reference number or code can be entered manually (eg, via a keyboard or digital input pad) or by scanning a bar code with a bar code reader or scanner provided with the station module. Further, in accordance with the present invention, previous work information can be accessed and retrieved from the database 30 from any location 10, 12, 14,... As will be discussed in the detailed description that follows, the search for similar parts can be based on feature extraction data or search keys stored in the database 30 to retrieve previous job information for the same or similar parts. And can be used to shorten the overall manufacturing time for future work.
[0069]
The manufacturing information retrieved from the database 30 is used by the workplace operator to create and test a bending plan. For example, the bending operator at bending station 18 can access and retrieve part information, bend line information and bending model data from database 30 to determine the tools and optimal bending procedures required for sheet metal parts. . In line with the present invention, an ODBC driver can be provided so that each station module can interface with the database 30 and display information stored in the database. Further, the server database 32 or the network database module of the database 30 can include an SQL server to facilitate access and retrieval of data stored in the database. Once the bend code is programmed based on the final bend plan, the bend code is sent along with the bend procedure from the bend station station module 18 to the database 30 through the communication network 30 as generally shown in FIG. This information is stored along with other design and manufacturing information related to the job.
[0070]
Other information can also be stored in the database 30. For example, a 2-D and / or 3-D image representation of a part can be stored with the bending model data. This 2-D or 3-D image representation is created using a CAD / CAM system at the design station 10 or elsewhere, and through the communication network 26 via the station module of the design station (or other suitable location). Can be transferred to the database 30. Alternatively, the 2-D or 3-D image may be performed by the server module 32 using a suitable CAD / CAM system or modeling software, as described in more detail later, to perform a series of functions or operations. Can be created.
[0071]
With reference to FIGS. 4 and 5, the processes and operations programmed and executed in the server module 32 and each location 10, 12, 14,... 20 will be described in detail. 4 and 5 are flow charts of the basic logic executed at each location 10, 12, 14,... 20 in the server module 32 and sheet metal manufacturing facility 38. FIG. FIG. 5 is for a typical process or operation performed, for example, at the bending station 18, but it will be understood that other processes and steps may be performed depending on the operation performed at a particular location within the facility 38. I can do it. The processes and operations described below can be implemented using software or one of many programming languages and techniques. For example, in the context of the present invention, the following processes and operations described with reference to the associated drawings can be implemented using a high level programming language such as C ++ and object oriented programming techniques. Further, as a non-limiting example, Visual C ++, a version of a programming language created by Microsoft for Windows-based applications, can be used.
[0072]
FIG. 4 is a flowchart of basic processing and operation performed by the server module 32 in accordance with the present invention. FIG. 4 is a basic logic flow of processing and operation executed by the server module 32 by software or programmed logic. Server module 32 may include a Windows-based application with a tool bar and help and / or menu screens to assist an operator or user in selecting and executing various processes and operations of the server module. The process starts from step S.1 when the customer's order is received at the sheet metal manufacturing facility 38. Customer orders usually include product and design information required for the parts to be manufactured in the factory. This information includes, for example, the geometric dimensions of the part, the material required for the part, and other design information. Based on the information received from the customer, the server module 32 performs a search for previous job information stored in the database 30 as depicted in step S.3. The work information stored in the database 30 can be searched based on various search criteria. For example, information can be searched based on predefined references or work numbers, or similar parts can be searched based on certain design features of parts, so that previous work information about the same or similar parts can be Searchable and available for. A more detailed description of available similar parts search is given below with reference to FIGS. 6-10.
[0073]
In step S.5, the database search results are analyzed to determine whether the current customer order is a new part, a part similar to the previous job, or a repeat of the previous job. If an identical match is found (for example, the same part or reference number is found), the customer's current order is a complete repeat of the previous work done at the factory and no further modification to the work information is required. Previous job information can be accessed from the database 30 and used to fulfill the current customer order as shown in step S.11. Searching the database gives the part or reference number and / or file name of the previous job so that any operator in the server module 32 or any station module can access the job information from the database. If only the part or reference number is available, the conversion table is provided so that the operator can determine and access the file name of the previous work information by entering the part reference or work number. Thus, for example, an operator in server module 32 analyzes part geometry by accessing work information and 2-D and 3-D modeling information from database 30 and sees that it is similar to repeated orders. Can be confirmed. If the order is confirmed to be a repetitive order, the bending operator in the station module at bending station 18 will further access previous work information and bend manufacturing information including bending code data and tool setup information. And can be used to make parts. By utilizing such stored expertise, it is thus possible to produce repetitive orders more efficiently and without the need for previously entered and developed work information.
[0074]
But in step S.5, if it is determined that the current customer's order is similar to the previous job or the same as the previous job, but the job or reference number or batch size needs to be modified, for example The previous job information data found in the search in step S.7 is retrieved from the database 30 and edited and modified by the operator in the server module 32. By providing an editing function, previous work data can be edited, modified to create new work data, and stored in the database 30 for current customer orders. The amount of editing required depends on the degree of similarity between the previous job and the current job. The amount of editing ranges from a simple modification of the reference or work number or batch size and / or including a more extensive modification, such as editing of part dimensions or defined bending procedures. When the previous task information is edited, the modified task information is stored in the database 30 in step S.9. The modified task information can be stored with a new reference or task number. In addition, various database management functions (copy, delete, save, rename, etc.) can be used to retain previous work information in the database 30 or erase or overwrite previous work information by entering special commands. .
[0075]
If it is determined that there is no similar or identical match for the current job, and therefore the current customer order is related to the new job, the logic flow proceeds to step S.15 shown in FIG. In this case, since the current job is related to a new job, the design and manufacturing information must be created and input independently. Providing menus and / or help screens from the server module 32 can assist the operator in entering all necessary work information. In line with the present invention, the server module 32 operator can create a new file by first entering basic part information for a new job. The part information includes, for example, a reference or work number, a customer name, a brief description of the part, a batch size or quantity required for the work, and a scheduled delivery date. Feature extraction data or search keys can also be entered in step S.15, and as described below, this data can be created automatically or extracted simultaneously with the creation of bending model data. Other data and information can also be entered in step S.15, or after or during entry of bend model data such as bend line information including the bend angle, radius and length of each bend line of the part. Following step S.15, the logic flow proceeds as the bending model data is developed and entered in the server module 32 by the operator, as shown in FIG.
[0076]
The development and input of the bending model depends on the original drawings and information provided by the customer. A customer order may include, for example, a 2-D one-way plan view of the part being manufactured and / or a 2-D, three-way view (eg, top, front, side view) of the part. Occasionally, customers may offer 3-D wireframes for parts with or without component material thickness shown in the figure. In accordance with the aspect of the present invention, the bending model data includes both development (2-D plane display) and folding (3-D display) information of the manufactured part. Thus, if the customer only provides a 2-D plan view, it is necessary to create a 3-D drawing, for example, by applying a folding algorithm or process to the 2-D drawing. In contrast, if a 3-D drawing of a part is provided, a 2-D floor plan must be created by applying a development algorithm or process to the 3-D drawing. In accordance with another aspect of the present invention, the 2-D and 3-D models stored in the bending model can be created and represented without sheet material thickness (ie, no thickness). This is possible due to the symmetry inherent in all sheet metal parts. Providing and representing 2-D and 3-D drawings without thickness provides modeling and simulation diagrams for parts that are more easily interpreted and understood by design programmers, bending operators and other users. Omitting the thickness information also reduces and improves the processing time required to implement and achieve the various features of the present invention described in the text in the server module and station module. A more detailed description of such features and the folding and unfolding algorithms that can be used in the present invention are described below with reference to the accompanying drawings.
[0077]
FIG. 4 shows the general processing and operation performed when developing a bending model. The various types of drawings that are accepted or developed based on customer orders and that can be entered to create bending model data are generally described in steps S.19, S.23, S.27, and S.31. It is shown. A tool icon bar and menu and / or help screen can be provided by the server module 32 to assist the operator in selecting and performing each of these steps. The process of creating 2-D and 3-D models of parts for bending models from these drawings depends on the type of drawing originally provided. These drawings can be entered or created manually by the server module 32 or downloaded from tape or disk. Server module 32 may, for example, interface with a CAD / CAM system at design office 10, or server module 32 may have a stand-alone CAD / CAM system. In addition, 2-D and 3-D drawings are stored as DXF or IGES files and incorporated into the server module 32.
[0078]
If a one-way plan view is provided, the process of creating a bending model begins at step S.19 as shown in FIG. In step S.19, the accepted or created 2-D plan view is input to the server module 32. Other bending model data and part material information such as the overall dimensions (width, height, depth) of the part can also be entered at step S.19. Then, using a folding algorithm or process, create a 3-D model (without material thickness) based on the original 2-D one-way drawing, as generally shown in step S.21 can do. Examples of processing and operations performed to create a 3-D model from a 2-D plan view will be described later with reference to FIGS. 11-18.
[0079]
If a 3-D wireframe diagram (without material thickness) of the part is accepted or created, the diagram information is entered in step S.27. In addition, other bending model data, such as the overall dimensions (width, height, depth) of the part and part material information can also be entered in step S.27. After this, as shown in step S.27, a deployment algorithm or process is executed in the server module 32 to create a 2-D model of the part. An example of processing and operations performed to create a 2-D model from a 3-D drawing (without thickness) will be described later with reference to FIG. 19, for example.
[0080]
The 2-D and 3-D model representation of a part is stored as part of the bending model for that part. In addition, as noted above, during the creation and storage of 2-D and 3-D models, other bending model data (such as part material information and other manufacturing information) can also be entered to bend model data. And can be stored in the database 30 together. Various functions and data structure arrangements that can be implemented to organize and store the bending model data will be described in more detail later (see, eg, FIGS. 26 and 27).
[0081]
As shown in Figure 4, if a simple 3-D drawing (without material thickness) was not originally created or accepted, the unfolding algorithm or processing necessary to create the final 2-D model is Before doing so, additional processing is required to create a 3-D model (no thickness) of the part. Steps S.23, S.25, S.31 and S.33 are additional steps typically performed in server module 32 before executing the deployment algorithm in step S.29 and creating a 2-D model. Process and operation.
[0082]
For example, if a 2-D, three-way drawing (three-side view) of a part is initially provided or created, the drawing can be entered or imported into the server module 32 at step S.23. In addition, other bending model data such as overall part dimensions (width, height, depth) and part material information can be entered in S.23. In step S.25, a simple 3-D plan view of the part can be created based on the input 2-D three-way drawing. The created 3-D drawing is used to create a 2-D model in step S.29, as shown in FIG. An example of processing and operation for creating a 3-D model from a 2-D three-way drawing will be described later with reference to FIG.
[0083]
However, if a 3-D drawing containing material thickness is originally accepted or created, drawing information may be entered in step S.31 for further processing before applying the unfolding algorithm. it can. Other bending model data, overall dimensions of the part (width, height, depth) and part material information can also be entered in step S.31. Thereafter, in step S.33, a thickness deletion procedure for deleting the thickness in the 3-D drawing can be performed. In line with the present invention, the server module 32 indicates the thickness in the drawing and indicates which surface (outside or inside) to save when an operator or user performs a thickness removal procedure. May prompt. The thickness deletion procedure that can be used in the present invention will be described below with reference to FIGS. 24 (a) and 24 (b), for example. After the 3-D drawing thickness is deleted in step S.33, the logic flow proceeds to step S.29 where there is no revised thickness to create the final 2-D model. An appropriate expansion algorithm or process is applied using the 3-D model. The development process and various processes and operations for creating a 2-D model from a 3-D drawing will be described below with reference to FIG. 19, for example.
[0084]
As shown in FIG. 4, after all the important information has been created and entered, the part information, bending model information and other data related to the customer's order is stored in the database from the server module 32 in step S.35. Moved to 30 and stored. The data stored in the database 30 also includes feature extraction or search data that can be used when performing a database search. As described below, feature extraction or search data also includes data indicating the basic or key features of the part associated with each job, thereby providing professional information about the job information or stored identical or similar parts. Search for knowledge. Data and information entered into the server module 32 can be transferred directly to the database 30 or via the communication network 26, for example, as shown in FIG. As described above, detailed descriptions of various processes and operations that can be performed on various drawings when creating bending model data will be described below with reference to the accompanying drawings.
[0085]
FIG. 5 shows a flow chart of basic processes and operations which are provided at the locations 10, 12, 14,... For purposes of illustration, FIG. 5 shows an example of the basic logic flow of basic processing and operations performed, for example, in a station module located at the bending station 18. As will be appreciated by those skilled in the art based on the teachings of the present invention, the flow of logic shown in FIG. 5 can of course be modified at each station module depending on the nature of the operations and processing performed at each location. is there. Further, as with the server module 32, software or programmed logic can be provided for processing and operation in the station module described below. In addition, the station module includes a Windows-based application with a toolbar icon or help and / or menu screen to facilitate the selection and execution of various processes and operations by the operator or user. be able to. Such help and / or menu screens can also be provided to facilitate data entry or transfer in the station module.
[0086]
As shown in FIG. 5, after initializing the station module in step S.51, the operator can enter one or more database search criteria or key items in step S.53. Search criteria can be entered to locate previous job information stored in the database 30, or job information relating to a new or current job. The operator can enter a predetermined number or code, for example, to retrieve specific job information from the database 30. For example, in accordance with aspects of the present invention, information can be accessed by attaching a barcode to a routing sheet or attached to perforated material and scanning with a barcode reader on the station module. Alternatively, the reference code or number can be entered manually on the station module via a keyboard or digital input pad. By providing a conversion table, previous work information can be defined by part reference or by input of a work number by an operator. Furthermore, it is expected that a similar part search of previously stored work information is performed by inputting a search criterion or a key. Such a search can be performed based on various design characteristics or feature extraction data of the part. A description of similar parts search that can be performed in accordance with the aspect of the present invention is described below with reference to FIGS. 6-10.
[0087]
After entering the search criteria at step S.53, the station module can perform a search of the database 30 via the communication network 26 and the network database module 34 at step S.55. The results of the search are returned to the station module, and in step S.57 whether the operator or user has requested information about a new or similar previous job, or whether the request is for a complete repetition of the previous job. Analyzed to determine.
[0088]
If the same is found (for example, the same part or reference number is found), iterative of previous work is determined and stored design and manufacturing information about the work is transferred from database 30 to the station module, As shown generally in step S.59, it is displayed for viewing by the operator. The station module has one or more menu display screens or a registry so that the operator can select and display various information retrieved from the database 30. The operator reviews the displayed information and runs various simulations, such as the 3-D bending simulation in step S.61, to observe the various stages of the bending procedure of the work and understand the part geometry can do. The operator can also review other information such as necessary special tools and other special instructions and messages recorded in the work information. Once the work information has been verified, the operator can bend or configure other required machinery (assembly) and operate the machine to produce the specified sheet metal parts. The work information retrieved from the database 30 includes final bending plan data including, for example, bending codes that control the bending station 18 machinery. The construction of the machinery and the actual operation are thus carried out by the operator, as generally indicated in step S.63 of FIG.
[0089]
If the same or similar job information is not found and the information is about a new job (ie, only preliminary job information has been entered into the server module 32 and no complete job information has been created) If so, partial part information and bending model data are retrieved from the database 30 and sent to the station module for observation by the operator at step S.77. Since the requested information is about a new job, the operator needs to create and enter a bending plan that includes the necessary tools and bending procedures. As will be described in more detail below, the station module can be equipped with a graphical user interface (GUI) and other functions to facilitate the creation of a bending plan by the bending operator. A GUI to assist the operator in creating a bending plan, for example by displaying a simulation of each intermediate stage of the proposed bending procedure, and tool selection, automatic inspection of potential discrepancies between parts and tools Can be provided. An operator who has created and entered a bending plan in the server module programs the bending procedure to generate a bending code (CNC or NC code for performing the bending procedure on the bending machine) in step S.80. The bend code can be entered directly on the server module, or it can be incorporated into the server module by interfacing with the CNC or NC controller of the bending machinery. Thereafter, in step S.81, the operator can set up at the bending work station and test the bending plan. When all the tests and necessary corrections necessary for the bending plan are completed, the final bending data is input and stored in the database 30 in step S.83. The final bending data includes bending procedures and tool configuration information along with the bending program. This information is sent to the database 30 from, for example, the station module of the bending station 18 and stored along with other design and manufacturing information about the new job.
[0090]
If it is determined in step S.57 of FIG. 5 that the information relates to similar parts or the same part of the previous job, but has different references or work numbers or batch quantities, for example, the logic flow is Proceed to step S.65. In step S.65, previous work information is retrieved from database 30 and displayed at bending station 18. The bending operator or user looks at the data to determine what data changes are required for similar parts. In this case, the station module also includes a series of menu display screens or a directory (directory) so that an operator can select information to be displayed and how to display or modify the information. For example, in step S.69, a 3-D bending simulation based on the retrieved information can be provided to facilitate the creation of a bending plan for similar parts by the operator. After reviewing previous work information, the operator modifies the tool and bending information along with the bending program in step S.70. Other task information such as part dimensions, reference numbers and batch quantities can also be modified and edited in step S.70. Once this is done, in step S.71, the actual tool setup and test is performed by the operator to test the modified bending plan at the workplace. If further modification of the test and bending plan is complete, the operator enters the final bending data in step S.73 and stores it in the database 30 with a new reference number or work number. As described above, previous work information can also be maintained in the database 30 along with other stored work files. In addition, various database management functions can be provided to store, delete, rename, etc. files stored in the database.
[0091]
An example of a similar parts search function that can be performed in accordance with the teachings of the present invention will now be described in detail with reference to FIGS. In line with the present invention, a similar parts search procedure that utilizes a feature-based form similarity search algorithm can be provided for searching and searching previous job information from the database 30. Similar part searching may include searching for identical and / or similar parts based on design features and / or manufacturing information about the part being manufactured. Similar parts search can also be performed by using software or programmed logic in various station modules within the server module 32 and / or factory 38, for example. Similar parts search can be performed either at server module 32 or at locations 10, 12, 14,... 20 within sheet metal bending plant 38. High-level programming languages and object-oriented programming techniques, such as C ++ or Microsoft Visual C ++ programming language, can be used to perform various processes and operations for similar parts search.
[0092]
FIGS. 6 and 7 show the logic flow of available similar part search algorithms or processing. As shown in FIG. 6, important part model data files can be accessed in step S.100. The part model includes, for example, bending model data created by a CAD system placed in the design office 10 and / or data created and inputted by the server module 32. The part model includes, for example, part form data (part topology data) representing various surfaces or faces of parts and the directions of bending lines, geometric relationships, and relative positions. After the part model data is retrieved or the bending model data is manually input, in step S.102, feature extraction data based on the bending model and / or part form data of the part is automatically derived. Feature extraction operations can be performed.
[0093]
In line with the present invention, feature extraction data can be derived by analyzing various features of sheet metal parts. For example, analysis of various surfaces of a part can determine whether adjacent surfaces have open or contact corners. Other features such as parallel bend, series bend, collinear bend or opposed bend can also be analyzed to determine and extract the distinct and unique features of each part.
[0094]
Table 1 shows the various bend and surface features that are analyzed when searching for similar parts. The extracted features that must be included in the feature extraction operation are the positive corner and negative corner features as well as the contact corner and open corner features. Further, the feature extraction operation must include at least feature analysis of parallel bending, series bending, collinear bending, out-of-phase collinear bending, and thickness offset bending.
[0095]
The feature extraction operation performed in step S.102 consists of analyzing the bending model data and form (topology) of each feature, correcting the form, and creating a feature-based matrix (matrix based on the feature) based on the form for future analysis. May include a series of operations consisting of For illustrative purposes, FIGS. 8 (a) -9 (d) show feature extraction operations for a 4-fold box part with a contact corner and a 4-fold box part with an open corner.
[0096]
[Table 1]
Figure 0003884195
For illustrative purposes, FIGS. 8 (a) -9 (d) show feature extraction based on the corner relationships of adjacent faces. For the closed 4-fold box with five faces (1-5) shown in Fig. 8 (a) and the open 4-fold box with five faces (1-5) shown in Fig. 8 (b), The same simple surface form shown in FIG. 8C is also provided. This form can be stored and provided with the part or bending model data. However, the simple surface form (surface topology) in FIG. 8 (c) provides only basic information on the relationship between the component surfaces (1-5), and the relationship between corners and bending between adjacent surfaces. It does not give information on various characteristics of parts such as types. Therefore, during the feature extraction operation, the basic surface form is modified to include additional information about the various features of the part by analyzing the associated face form stored with the part or bending model data. be able to.
[0097]
For example, by examining the part or bending model data of the closed 4-fold box in FIG. 8 (a), the corners between adjacent faces can be analyzed, and the modified surface form shown in FIG. 9 (a) is created. This can indicate the contact corner situation between each surface. Similarly, by examining the open quadruple box part or bend model data shown in FIG. 9 (a), the modified surface configuration shown in FIG. 9 (b) is created, thereby varying the variety of parts. An open corner relationship between adjacent surfaces can be shown. As shown in FIGS. 9 (a) and 9 (b), special connection lines can be added to the surface configuration to indicate the relationship between the corners of the surface (for example, contact or release). Other data can also be added to indicate other features (eg, existing bend types) and to create feature-based surface features. After modifying the form to include feature-based information, a matrix can be created for easier analysis and comparison of the extracted information. For example, based on the feature-based surface geometry of FIG. 9 (a), the matrix shown in FIG. 9 (c) is created, thereby showing various features of the closed 4-fold box of FIG. 8 (a). it can. Similarly, for an open 4-fold box, the matrix shown in FIG. 9 (d) can be created based on the feature base surface form shown in FIG. 9 (b), for example. Other feature extraction data, such as part bending characteristics (eg, 90 ° positive bending angle or 90 ° negative bending angle, etc.) can also be shown in the matrix.
[0098]
As described above, the feature extraction operation of step S.102 can be performed to determine whether various features exist in the part by analyzing the bending model data and the form. In accordance with the aspect of the present invention, feature extraction operations can be performed on the bending model and morphological data provided to the part. This data includes sheet data, bend line data (eg bend line length and position), face-bend line relationship data, bend angle data and special feature data (eg Z-bend and edging etc.) Contains all important geometry and position data for the part (eg in 2-D space (X, Y) and / or 3-D space (XYZ)). Lines, bend lines and other components can be defined by end points and / or vectors. For example, each 2D line is specified by a set of 2D endpoints (for example, X1, Y1 and X2, Y2), and each 3D line is specified by a set of 3D endpoints (for example, X1, Y1, Z1, and X2, Y2, Z2) be able to. The bend line can be represented by a vector indicating the direction of the bend line along with its location in 2D or 3D space. In addition, 2D arcs are 2D spatial data (eg center X, center Y, radius, start angle, end angle), 3D arcs are 3D spatial data (eg center X, center Y, center Z, view matrix, radius, angle) (Start, end of angle). Part form data can also be provided to indicate the various faces of the part, the location of the bend lines, and the geometric relationships between them. Each face can be defined by a set of lines and / or arcs or a linked data list.
[0099]
In order to extract a feature of a part, it is possible to determine whether or not a certain feature exists in the part by performing a feature extraction operation of the bending model and form data and analyzing it. This process can also include analysis of bending models and morphological data based on various features and relationships between each feature to be extracted. The presence of certain features (eg, contact corners between surfaces, open corner characteristics, or parallel or series bending characteristics) can be detected by analyzing the bend model and morphology data to know the features and relationships of each feature. Different processes can also be provided for detecting specific characteristics and relationships of each feature in the feature extraction operation. Several processes can be combined or created to check if one or more features are present in a part based on the similarity of properties and relationships between each feature being analyzed.
[0100]
As a non-limiting example, in the feature extraction operation in step S.102, a corner feature, for example, a contact corner feature of two surfaces having the same bending direction (TouchCnr feature in Table 1) is extracted and detected. Describe the processes that can be used. The following process detects other features, such as two corner contact corner features with reverse bending direction (touchCnr feature in Table 1) or two corner open corner features with the same or reverse bending direction (Table 1 It can also be used for OpenCnr and openCnr features. Other features can also be detected by modifying the process (eg, parallel bending, serial bending, etc.). In addition, data for each possible combination of faces can be analyzed to know the characteristics and relationships of each extracted feature.
[0101]
For example, for TouchCnr with contact corner features, the detected features or relationships are: two faces with a common face; the same bend line direction; the same vertex (or the distance between vertices within a predetermined range) Includes a bend line with a vertex. For touchCnr with contact corner features, similar characteristics or relationships must be detected; the surface must have a reverse bend line, not just a surface with the same direction bend line (eg Table 1) See). Open corner features OpenCnr and openCnr can be detected as well, but each feature has an open corner between faces instead of a contact corner relationship (for example, the bend line of the face is separated by more than a preset range distance) And bend lines with the same or opposite bend line direction (see Table 1 and the OpenCnr and openCnr definitions in the table) must be detected and analyzed.
[0102]
In order to detect a contact corner feature (for example, TouchCnr feature in Table 1), first, two surfaces are analyzed to determine whether the two surfaces are connected to a common surface. This can be detected by searching the bend line data for each surface and the bend line-surface relationship data for each bend line to determine whether a common surface exists. If the two faces are connected to a common face, analyze the bend line direction of each face to see if they have the same bend line direction (or the opposite bend line direction when detecting touchCnr features, for example) to see. This is determined, for example, by analyzing vector data indicating the bending line direction of each surface.
[0103]
If it is determined that the two surfaces have a common surface and have the same bend line direction based on the bend model and morphological data, it is detected by examining the data whether the bend lines are parallel. Various methods can be used to detect whether the bend lines are parallel based on the bend model and the form data. For example, the detection of a parallel bend line is determined by taking the outer product of vectors that define the bend line direction. If the vector cross product is zero (or approximately zero), the bend lines are determined to be parallel. If the vector cross product is not zero (or approximately non-zero), the bend lines of the two faces are not parallel.
[0104]
After determining that the two faces have a common face, the bend line direction is the same, and the bend lines are not parallel, the bend model data is used to determine the corner relationship between the faces (eg contact or open). Is analyzed. The corner relationship between the two surfaces is determined by detecting whether the bend line of the surface has a common vertex from the bending model data. If the bend lines have a common apex, the two faces have the same bend line contact corner relationship (TouchCnr features in Table 1). Although the bend lines have a common vertex, if it is determined that the two lines have different bend line directions, the two faces are determined to have contact corner relationships in opposite directions (for example, the touchCnr feature in Table 1).
[0105]
Even if the two faces do not have a common vertex, it can be determined that the two faces have a contact corner relationship if the distance between the vertices is within a predetermined range. Often, there may be minimal space between adjacent surfaces of the part, for example as a gap for passing a punch tool. This space is usually determined by the width of the tool at the height of the flange. For example, the presence of a contact corner feature can be determined if the distance between the vertices of the bend lines of the two faces is within 0-5 mm. If the space between the corners of the two faces is greater than a predetermined range, the presence of an open corner feature can be determined (eg, OpenCnr or openCnr feature in Table 1).
[0106]
The above process can be performed to determine the corner characteristics of each surface for any combination of component surfaces. Other features related to part surfaces and bend lines can be similarly performed by analysis of part geometry and morphological data. Appendix A shows typical code for performing the feature extraction operation in step S.102. The code is written in the C ++ programming language and includes various processes for extracting and detecting features such as those listed in Table 1. The code in Appendix A has comments to make it easier to analyze the logic and algorithms used. This code example also uses terminology with the same features as in Table 1 to help you understand the various features.
[0107]
When various features of the part are detected, the basic form of the part is modified to include the extracted features. While it may be useful to provide feature-based forms, it is not easy to compare such forms to each other. Instead, the inventors of this application have discovered that it is more effective and easier to compare feature extraction information provided in the form of a matrix. Therefore, as one feature of the present invention, a feature-based component matrix (such as the representative matrix shown in FIGS. 9C and 9D) based on the detected feature during the feature extraction operation is provided. Created. The created feature base matrix of the part determines what basic form or feature is contained in the part by comparing it with other predetermined stored matrices.
[0108]
The feature base matrix is created and stored for each component after detecting and extracting various features of the component. As shown in FIGS. 9 (c) and 9 (d), the matrix is a symmetrical two-dimensional matrix and has an order equal to the number of parts faces. The matrix contains all detected feature information of the part, and various features between each face are provided at each location of the matrix. The feature-based matrix can be temporarily stored in the storage device of the server or station module, used only when performing a similar part search, and compared with a predetermined matrix. Alternatively, the feature-based part matrix can be permanently stored in the database 30 along with other work information so that it can be accessed anywhere in the factory.
[0109]
Returning to FIG. 6, after performing the feature extraction operation, the extracted feature extraction data matrix can be compared with a predetermined feature extraction data matrix provided in the feature form library. The feature library can be stored as a separate data file in a database such as database 30 or in a server module or station module. The feature library consists of a predetermined matrix containing feature extraction data corresponding to or defining the shape of a basic or basic part (eg, 4-fold box, bridge, etc.). Each predetermined feature base matrix can be stored as an ASCII or text file along with a feature base component matrix. The comparison in step S.104 is made to determine the basic or basic shape / feature present in the sheet metal part, as illustrated in step S.106. A stored look-up table may be provided to indicate which basic shape corresponds to each predetermined feature matrix. If a match is found, the look-up table is accessed to determine which basic shape exists at step S.106. The matching matrix present in the predefined library is of the same order as the feature-based part matrix (in this case the part contains only one basic shape and is determined to correspond exactly) or part matrix (In this case, the part may contain one or more basic shapes).
[0110]
Recursive programming techniques can be used to compare the feature-based component matrix with the matrix in the predefined library. When comparing the contained information, the use of data allocation is avoided and the required process time is reduced by replacing the matrix indices. Recursive programming techniques and index swapping also facilitate the comparison of matrices with different orders and different bases.
[0111]
In accordance with the present invention, the comparison operation performed in step S.104 consists of a series of comparisons and initially relates to more complex shapes (eg, shapes that include complex bends such as multiple bends or tabs). Start with a matrix comparison and move to less complex shapes (eg, less bends, or less complex bends, shapes with fewer faces). This series of comparisons is performed until a predetermined number of basic shapes are found on the part. For example, a comparison operation can be performed to extract the three most complex features or shapes of a particular part. In addition, this operation can be started first with a series of comparisons to a group of matrices related to shapes that are common or often found in sheet metal parts, and then proceed to less common shapes. In order to compare a part with a predefined library, various methods can be performed to obtain useful results.
[0112]
For example, a series of comparison operations can first be applied to a right-angle group of matrices containing a basic shape with a right-angle bend, such as a rectangular or square shape with a number of right-angle bends or a simple part with a right-angle bend. This group of matrices goes from the more complex matrix in the group (for example, the matrix corresponding to a quadruple box with tabs) to the simpler matrix in the group (for example, a matrix for simple hat parts). You can search based on a series of comparisons that you make. A series of comparisons can then be applied to the matrix of polygon part groups and further to the matrix of special feature groups. A polygonal part group may include a matrix defining parts having five or more sides and one bend of at least 90 degrees or more. The matrix of special feature groups may include a matrix in a predefined library relating to parts with special features or forming, such as Z-bend or edge bend. Again, a series of comparisons between the part feature base matrix and the predetermined matrix for each group is performed according to a decreasing degree of complexity. After this, other groups of the given matrix can be compared, such as multiple feature groups with two or more features on one side of the part.
[0113]
Compare a part with a matrix in a predefined library according to the degree of complexity, and compare with a library to determine the basic shape present in the part by making a series of comparisons of groups of matrices based on realization and frequency of use. A more effective and effective comparison. Furthermore, duplication of detection features is prevented and only more complex shapes are identified.
[0114]
In steps S and 108, a feature relationship operation is performed to determine the relationship between basic features or shapes in the part. The relationship between features or shapes is determined by distance. The distance between the two shapes is determined based on the number of bend lines or surfaces between the base surfaces (basic surfaces) of the shapes. Alternatively, the relationship between features can be defined by the physical distance between features or actual dimensions by geometrically analyzing the relative positions and spacing of the parts and the base of each feature.
[0115]
For illustration purposes, the three most complex features or shapes of the part determined in step S.106 will be the 4-fold box, the bridge, and the other 4-fold box shown in FIG. For such parts, feature relationship operations can be performed, for example, to determine the number of bend lines between the base surfaces or faces of each basic feature. As shown in FIG. 10B, the characteristic relationship between the base (1) of the first 4-fold box and the base (2) of the bridge is the distance between the two bending lines. Furthermore, the relationship between the base of the first 4-fold box (1) and the base of the second 4-fold box (3) is the spacing of the four bend lines, the bridge base (2) and the second base The relationship between the bases (3) of the 4-fold box is the distance between the two bend lines.
[0116]
Various processes can determine the number of bend lines between the base surfaces of the basic shape of the part. For example, the feature relationship can be determined in step S.108 using the feature base component matrix and the predetermined shape matrix. First, the base plane corresponding to each basic shape in the part matrix is searched. This can be done by correlating the base of the predetermined shape matrix with the surface index of the component matrix. As previously discussed, the predetermined shape matrix separated by the comparison operation may be a sub-matrix of the component matrix. To find the base plane corresponding to each basic shape in the part matrix, the correlation between the position of the shape matrix in the part matrix and the matrix index is analyzed. Since the base surface of each basic shape is determined in advance and is located in the first column of the shape matrix, the corresponding position and base surface in the part matrix can be found.
[0117]
After determining the base surface of each basic shape in the feature base component matrix, the distance between the base surfaces of each shape is analyzed to determine the feature relationship. This analysis includes a search process that identifies the distance between any two basal planes. By looking at the features and bend line information in the part matrix, the number of bend lines between any two basal planes can be determined. If more than one path is possible between two surfaces, a feature relationship can be defined in step S.108 using the minimum distance.
[0118]
The logic flow after finishing the feature relationship operation continues to step S.110. As shown in FIG. 7, in step S.110, a database search key is identified to determine a search key used for searching for similar parts in the database. The search key may include various combinations of features and feature relationships identified in the part. Furthermore, any reference hierarchy can be used to assemble the search key. As a non-limiting example, a search key can be created according to the following criteria: (i) the first and second most complex feature or shape identified in the part; (ii) the distance between the two most complex features Or (iii) the third complex feature or shape identified in the part; and (iv) the feature relation or distance between the first complex feature and the third complex feature identified in the part; And the distance or feature relationship between the second and third complex features. FIG. 10C shows a search key developed based on the example of FIG.
[0119]
In order to facilitate searching the database, the search key can be represented by a string of integers with predetermined codes assigned to the various basic shapes defined in the shape library. For example, suppose an integer code “16” is assigned to a 4-fold box and an integer code “32” is assigned to a bridge. In this case, the search key in the example of FIG. 10C is represented by an integer string “16, 16, 4, 32, 2, 2”, among which “4” and “2” are between basic shapes or features. Represents various distances. However, the display of the search key is not limited to the integer string, and any combination of integer and / or character string can be used to display the search key.
[0120]
The search key for each part can be stored in a database, such as the database 30, along with work information (in a separate file or the same file). A typical search key for feature extraction data can be entered manually or automatically created as described above. Additional feature extraction data such as a feature-based component matrix can be stored using a search key. When the search key is stored in another file, a reference table for searching for parts information associated with each set of search keys can be prepared. Alternatively, the search key can be stored with the data field identifying part information (eg, by part or reference number).
[0121]
In step S.112, a collaborative search of the database based on the identified search key is performed. A collaborative search is a search that uses a collaborative database search technique. The cooperative search technique searches not only parts having the same search key but also parts having similar search keys. This makes it possible to identify similar and identical parts in the database. When searching for a particular part, the search key identified as that part can be compared with other search key data in the database. The collaborative search performed in step S.112 exactly matches or most closely matches the specific part identified by the search key, with items in the database, by loosening or modifying the order of the search keys Configured to identify items. Various processes and methods can be used to adapt search keys in a collaborative search.
For example, suppose that a database search is first performed to identify parts with a search key order that exactly matches those identified for the part being searched. This is done by comparing the identified search key with the search key stored in the database. After identifying parts (if any) with the same search key, a database search based on a different modified search key order can be performed to continue searching for other similar parts. Less important or sensitive items or criteria (such as feature relationships or distances) in the first search key before modifying more important or sensitive search items (such as basic features or shapes in the part) Can be modified and searched. In addition, each of these items can be modified according to the importance of the item, giving higher weight or importance to items associated with the first and second most complex features or shapes in the part. For example, the first search performed can be performed after correcting the defined distance between the third complex feature and the first and second complex features. This distance can be modified by changing a predetermined number of bend lines (eg, 1-3) or defining a predetermined range of distances based on the current distance. Thereafter, the distance between the first and second complex features or shapes can be changed to provide another modified search key set for database searching. After modifying the part feature or distance search key, the identified shape can be changed to derive additional modified search keys in a collaborative search. For example, the search key item for the third most complex feature or shape can be changed to a related but less complex shape depending on the feature or shape of what you are currently dealing with (for example, a 4-fold box with tabs is a simple 4 In the folding box). Further, by changing the search keys for the first and second complex features in the same way, it is possible to add a modified search key for collaborative search.
[0122]
Modifications during the collaborative search of distances and features / shapes related to the search key can be performed by various methods and techniques. As described above, how much the distance is changed depends on the current value of the distance. The distance magnitude (eg 4 bend lines) can be modified in the range of distances (eg 3-5) to expand the search and make it more cooperative. For features or shapes, the search key can be modified to identify similar parts. Features or shapes can be modified through a hierarchical structure of feature types. For example, a currently handled feature type (eg, a 4-fold box) can be modified to a less complex feature type (eg, a 3-fold box) that is related and belongs to the same feature type. The hierarchical structure used to modify features / shapes can be predefined and created based on a number of different techniques, such as type abstraction hierarchy (TAH). For more information on TAH and the TAH generation, see, for example, “Cooperative Query Answering via Type Abstraction Hierarchy” by CSD-900032, October 1990, by Chu et al., Wesley, W. , University of California, Los Angeles (October 1990) and 1995, PhD thesis of Doctor of Computer Science Philosophy, Quoron Cheung “Automatic Generation of Type Abstraction Hierarchies for Collaborative Query Response” (CHIANG, Kuorong, Automatic Generation of Type Abstraction Hierarchies for Cooperative Query Answering), incorporated herein by reference to all of the information disclosed therein.
[0123]
Other processes and steps can be performed during the collaborative search. For example, in addition to searching a database based on a search key identified as being associated with a feature of a part, the search may be based on a search criterion associated with part manufacturing information. For example, the machine configuration required for each part can be compared using an additional search key as an example. The machine configuration information includes the machines required to make the machine type or part, the tools used to make the part, the tool configuration and / or the machine backgauging settings. Additional search keys can be developed based on machine configuration information and / or other manufacturing information, and can be used with the identified search keys when performing collaborative searches of the present invention. As a result, parts that are the same or similar to the part being manufactured can be identified based on both the design and manufacturing characteristics of the part.
[0124]
In order to select the most similar parts, a selected parts search is performed in step S.114, and a more detailed comparison of the results of the cooperative search and a predetermined number of parts that are the same or most similar to the searched parts are selected. The selected component search may involve analysis of additional information and characteristics for each component identified by the collaborative search. This includes analysis of various characteristics of the sought part, such as the dimensions of the part and the shape of the holes and openings in the part. It can also include a comparison of manufacturing information for each found part, such as the machine configuration required for each part. As described above, the machine configuration information includes the type or machinery of the machine required for manufacturing the part, the tool or tool configuration used for manufacturing the part, and / or the back gauging setting of the machine. In order to perform the selected part search, the bending model and other work information of each part are accessed from the database based on the search key identified in the cooperative search. As noted above, look-up tables and additional data fields can be provided to provide a work reference number or code corresponding to each search key set. After retrieving the part information from the database, which part is most similar to the part searched for additional information (eg part dimensions, material type, special molding, part holes or openings, etc.) for each part Can be analyzed to determine This process optionally serves as an additional selection process that selects and aggregates parts of the database that are most similar to the part. By analyzing and collating additional information or characteristics of this part, a selected part search can be performed to identify or select a predetermined number or set of most similar parts. For example, in the selected parts search, the five most similar parts can be identified based on the number of matching search keys and matching of additional part characteristics. The number of parts selected in the selected parts search is not limited to five, but can be selected based on the necessity of the factory and the number of parts actually stored in the database. This number can be selectively modified to obtain more useful and useful search results, and can also give the user an opportunity to modify this number to change the search set.
[0125]
After performing the selected parts search, a similarity index can be calculated to rank the parts (according to the feature similarity and the number of matching search keys) in step S.116. The similarity index is calculated in step S.116 and provided as the output of the server or station module, which allows the user to select which work files are retrieved from the database and displayed on the screen. Based on the degree of similarity between the characteristics of the selected part and the search part, the similarity index can rank the selected parts (for example, ranks 1 to 5 with the work or reference number of each part). For this purpose, the feature base matrix of each part is compared with that of the search part. Comparison of feature base matrices better indicates the similarity between the selected part and the search part. As before, the feature-based part matrix can be stored with the search key for each part. However, permanently storing the feature-based part matrix of each previous work along with the search key occupies an unnecessarily large storage space (especially when a large number of parts are stored in the database). Therefore, it is only possible to store only the search key data of each part and automatically generate the feature base matrix of each selected part when performing a similar part search. Thus, after retrieving the bending model and other work information of the selected part, the feature base matrix is created through the feature base extraction operation of the present invention as previously described for step S.102. Thereafter, the feature base matrix of the search part temporarily stored during the search for similar parts can be compared with each of the feature base matrix of the created selected part. Various methods and processes can be used to compare part feature-based matrices and determine similarity between parts. For example, for the feature base matrix of each selected part, the location in the matrix can be compared with that of the search part. Each location in the matrix can be compared based on recursive programming techniques. Information in the matrix can be compared by determining the location of the corresponding basal plane in each matrix and exchanging matrix indices. The selected part may correspond to or have the shape of a sub-feature of the search part, and the matrix indices may not be the same or numbered, so compare the contained information When you do, you have to search for a comparable surface in the parts matrix and transfer the indicators. In addition, if one or more subfeatures are present in the search component, when comparing information in the matrix, one or more pseudo-surfaces (matrix rows and Sometimes it is necessary to introduce a column that has no information or is blank.
[0126]
When comparing matrix information, a plurality of different ordering schemes can be used to determine the degree of similarity between each selected component and the search component. For example, a penalty-based ordering scheme can be used that assigns a predetermined penalty level or amount to each inconsistent position in the matrix. After comparing all the information in the matrix, the total penalty level of each selected part can be used to determine the degree of similarity. The selected part with the lowest penalty level is determined as the part most similar to the search part. Other selected parts can also be ordered based on the total penalty level assigned to each part (eg, the lower the penalty level, the higher the similarity index).
[0127]
In accordance with a further aspect of the invention, the penalty level for each non-aligned location can be assigned based on the type of information at that location. The penalty level is an integer amount that can vary depending on the severity or importance of the inconsistent information. For example, high penalty levels or amounts can be assigned to non-aligned positions for different, unrelated feature groups (eg, parallel versus serial bending features). In contrast, different but similar feature groups (eg, contact corner features with the same bend line direction versus contact corner features with opposite bend line directions). Penalty levels or amounts are pre-defined and categorized according to the type of information present at the inconsistent location and the type of difference.
[0128]
A typical code for similarity index manipulation in step S.116 is shown in Appendix B. The code is written in the C ++ language and includes various processes and operations related to comparing the matrices described above and assigning penalty levels to inconsistent positions. As noted above, the total penalty level obtained as a result of each selected part compared can be used to derive and display a similarity measure. The code listing in Appendix B also includes comments to help you understand the typical program code shown.
[0129]
Next, with reference to FIGS. 11-25, the development of the bending model and the development of the 2-D and 3-D models of the parts based on various 2-D and 3-D drawings are in accordance with the viewpoint of the present invention. Describe in more detail. As previously discussed, the bending model data for each sheet metal part includes data related to both the 2-D and 3-D representations of the part. Various folding and unfolding algorithms and other processes can be used to develop 2-D and 3-D models based on the type of original drawings provided or created based on customer orders. In particular, FIGS. 11-18 show an example of the logic flow of a folding algorithm that can be used to create a 3-D model based on the original 2-D one-way drawing (two-dimensional single drawing) of the part. FIG. 19 shows an example of a basic logic flow of a development algorithm and other processes used to create a 2-D model based on a 3-D original drawing (without thickness). Finally, Fig.20-24 and Fig.25 show various things that can be done to create a 3-D model without thickness from 2-D three-way drawing (two-dimensional three-dimensional drawing) and 3-D drawing with thickness. An example of the logic flow of processes and operations is shown. The 3-D model (thicknessless) obtained from these processes and operations can be used to create a 2-D model based on a deployment algorithm or process, as specified in the text.
[0130]
FIG. 11 shows the logic flow of the process and operation of creating a 3-D model using a folding algorithm from a 2-D one-way drawing. The functions and operations performed in the flowchart of FIG. 11 can be implemented by software or program logic in the server module 32, for example. In step S.120, a 2-D unidirectional plan view provided or newly created based on customer specifications is input or incorporated into the server module 32. 2-D floor plans are created using CAD software and entered into the server module 32, or imported into the server module by interfacing with an appropriate CAD or CAD / CAM system, such as a bell or cadkey. be able to. A 2-D drawing can be stored as a DXF or IGES file, for example, to illustrate a punched and / or cut material that is bent. 2-D drawings can also indicate the location of the bend lines, holes, or openings in the surface or face of the sheet metal part. In preparation for later processing of the 2-D drawing, the server module 32 automatically performs step S.122 before the next surface detection process in step S.124 and the bend line detection operation in step S.126. Cleaning and cleanup functions can also be implemented.
[0131]
The automatic trimming and cleanup function of the present invention is provided to prepare a 2-D plan view for processing. A 2-D plan view is a 2-D representation of the unfolded state of a sheet metal part, including part elements (entities) such as lines and curves that constitute and represent the geometry of the part, as well as openings or holes that exist in the part. Indicates the position. Normally, the components (entities) of such a 2-D plan view are input and created using a CAD or CAD / CAM system. However, when creating 2-D plan views, such elements are often mistakenly connected or superimposed, and one element can be used to indicate the boundaries of one or more faces. Furthermore, the outer lines that define the boundaries of the parts are divided at the corners adjacent to the boundaries, making it difficult to detect the dimensions of the parts and the outside of each surface. In addition, 2-D plan views can include non-essential information such as dimensional information and text. Such an anomaly makes it difficult to accurately analyze the original 2-D drawing and to detect the part surface and bend line uniformly. By providing the automatic trimming and cleanup operations of the present invention, each surface can be represented by a unique set of connected elements. As a result, the 2-D plan view can be analyzed more easily and efficiently for subsequent processing and final folding for 3-D model representation creation.
[0132]
As shown in FIG. 12, the original 2-D drawing is not trimmed between the faces, and one line element in the figure defines an outer boundary or a plurality of boundaries of one or more faces. is there. As discussed above, such an arrangement makes each surface difficult to detect. The automatic trimming function of the present invention determines the connectivity information and analyzes the end point and intersection of each component element (such as a line, arc or bend line) to cut off such elements at the intersection. Is provided. Such a trimming function also has a function of setting the end point of each cut-off element at a predetermined intersection. For example, by trimming the intersection shown in FIG. 12, three elements (two lines and one bend line) each sharing an end point at the intersection are obtained. By providing such a trimming function, the surface of the component can be detected more easily based on element analysis and connection. A more detailed description of the surface detection operations that can be performed is provided below with reference to FIGS. 15 (a) -16 (c).
[0133]
Intersections of 2-D drawing elements can be detected using various processes and operations. Such a process can be created based on the format and arrangement of the file data in the 2-D drawing. Typically 2-D floor plans contain geometric data (defining various component elements) and non-geometric data (eg text). Geometric data can be distinguished from non-geometric data by keywords in each row or sequence of data. Such keywords are set according to the data format of the 2-D drawing. DXF and TGES formats are often used for 2-D and 3-D drawings. By analyzing the geometric data of each element, the end point and intersection of the element can be detected, and trimming can be performed if appropriate.
[0134]
As discussed above, lines, bend lines and other elements can be defined by endpoints and / or vectors. For example, in a 2-D plan view, each 2-D line can be identified by a pair of 2-D endpoints (eg, X1, Y1 and X2, Y2), and the bend line is oriented along with the 2-D spatial position of the bend line. Can be represented by a vector indicating. Further, the 2-D arc can be specified by 2-D space data (for example, center X, center Y, radius, start angle, end angle). Geometric data also has attributes that distinguish different types of line elements (eg, arcs, solid lines, dashed lines, chain lines, etc.). Normally, arc elements are used to indicate holes and openings in sheet metal parts, and solid lines are used to indicate the boundaries and shapes of parts. The bend line is usually indicated by a broken line and the center line of the part is indicated by a chain line.
[0135]
Analyze the original 2-D drawing geometry data to determine the intersection of each element. Various data analysis techniques, such as data allocation and data repetition, can be used to analyze the geometric data of each element in a 2-D drawing. Based on the end points of each element and / or other 2-D spatial data, a simple geometric analysis can be made to determine whether lines or other elements intersect. If it is determined that two elements intersect, each element can be cut off at the determined intersection, and a common point determined by the intersection can be assigned to the end point of the remaining element.
[0136]
The trimming method is performed based on the type of element detected to intersect. For example, when it is detected that two solid lines intersect, as shown in FIG. 13A, by cutting off each line element, four line elements in contact with each other at a predetermined intersection are obtained. If it is determined that the line element and the arc element intersect as shown in FIG. 13B, two line elements and two arc elements having a common end point can be obtained by cutting each element. However, trimming may not be required even if an element crossing is detected. For example, if any element is determined to intersect a center line (eg, a chain line element), no center line of any part defines or distinguishes the part's face or bend line, so there is no need for trimming . Even elements that are not connected can be cut if the open intersection or area is within a predetermined tolerance. For example, if the end point of a potentially intersecting line is within an intersection point when actually intersecting another element and a predefined tolerance or distance ε (eg 0.0-0.01mm or 0.0-0.001 inch) The elements may be treated as being connected and intersected at the projected points; and the elements can be cut off, for example as shown in FIG.
[0137]
After automatic trimming, the obtained data can be processed with a cleanup function to detect and correct unconnected elements. However, the present invention is not limited to such processing; a cleanup function can be performed simultaneously with an automatic trimming function while each element is being analyzed to reduce processing time. During cleanup, the geometric data of the 2-D drawing is analyzed to detect open intersections or regions between adjacent elements. Similar to the auto-trimming function, the end points of each element and other 2-D spatial data can be analyzed to detect the area of the open intersection between elements. By applying a simple geometric analysis to such data, it can be determined whether the end points of the elements are within a predefined tolerance or distance (0.0-0.01 mm or 0.0-0.001 inches) of each other. Once it is determined that the end points of the elements have such open intersections, the elements can be concatenated and assigned a common end point as shown in FIG.
[0138]
Again, how the cleanup function is performed depends on the type of element detected to have an open intersection. If it is detected that the two solid lines have open intersections, a common endpoint can be assigned to each endpoint (see, eg, FIG. 14). However, when an element is determined to have an open intersection with a part centerline (eg, a chain line element), the elements should not be connected or assigned a common endpoint, and the centerline must be ignored. The cleanup function may also include an additional process or operation for erasing non-geometric data (such as text) from the 2-D drawing. As described above, non-geometric data can be distinguished from geometric data based on keywords prepared together with 2-D drawing data. The cleanup function can also incorporate other cleanup functions as will be described in more detail later with reference to the 2-D cleanup function of the present invention (see, eg, FIGS. 21-23 (b)). ).
[0139]
After performing the automatic trimming and cleanup function in step S.122, the surface detection procedure can be performed for the 2-D drawing processed in step S.124. In line with the present invention, the surface detection procedure involves detecting and defining the surface of the part based on elements (lines and arcs) and loop analysis. FIGS. 15A to 16D show examples of various processes and operations performed in the surface detection procedure. Loop detection techniques can be used in the present invention to detect and determine the face of a part. The face detection procedure can be implemented by software or programmed logic residing in the server module 32, for example.
[0140]
In accordance with aspects of the present invention, each of the faces can be detected using a minimum or inner loop analysis of the part, followed by a loop detection analysis of the outer boundary of the part. Due to the unique geometry of sheet metal parts, openings in faces and parts can be detected by analysis of the order of relative maximum (eg, outer) and minimum (eg, inner) loops. As discussed below, loop analysis can be performed based on the connectivity of part lines and arc elements. By performing the loop analysis from the outside of the part to the center of the part, the opening or face of the part is based on the boundary between the loops defined according to the circulation order (eg face material, opening, face material, opening, etc.) Can be detected.
[0141]
Suppose a 2-D plan view is provided that includes various line elements on each face as shown in FIG. 15 (a). As described above, the loop and element analysis are performed starting from the outside of the part. Any element at the outer boundary of the part may be the initial reference point. As a non-limiting example, as shown in FIG. 15B, the leftmost line element is detected and used as the initial reference point. The leftmost line element can be detected by comparing the geometric data of each element in the 2-D drawing and determining which element has the smallest X coordinate value. After detecting the leftmost line element, the appearance of the part is derived from the point P1, and the outer boundary of the part is detected as shown in FIG. To determine the point P1, any end point of the leftmost line element may be used. In the embodiment shown in FIG. 15C, the upper end point (that is, the end point having the largest Y coordinate value) is used for the point P1.
[0142]
Conventional loop analysis techniques can be used to guide the appearance of the part or surrounding loops. For example, the lead line vector can be projected from the end point of the element connected to the start point P1 as the appearance of the part is followed. Each time an element is detected and passed, a flag can be set to indicate that the element has been selected (eg the flag in memory is set to 1 to indicate that it has been selected once) To do). The loop path can be started in either direction from the starting point P1. For example, the lead wire vector can be projected from the point P1 in the counterclockwise direction (for example, the lead wire vector is projected in the Y coordinate direction). The loop is completed when the loop path returns to the starting point (ie, point P1).
[0143]
As described above, the lead wire vector can be projected counterclockwise from the starting point P1 (for example, by starting the first lead wire vector from the Y coordinate direction). In order to continue to detect the first element in the loop path, the angle that each undetected element makes with the lead wire vector around point P1 is measured based on the coordinate frame and analyzed to analyze the smallest angle with the lead wire vector Select an element with. In the outer loop, each angle measures the outer angle that the element line makes with the lead vector. The elements around the point P1 are determined by which elements share the end point with the point P1. The unselected status of each element can be determined by analyzing a flag attached to each element. As shown in FIG. 15C, in the illustrated 2-D drawing example, there are two element lines (one in the X coordinate direction and one in the Y coordinate direction) around P1. In the analysis of these elements, the line element in the Y coordinate direction is selected because the angle (0 degree) formed with the lead wire vector is smaller than the angle (270 degrees) formed with the other line elements.
[0144]
The loop analysis then proceeds to the end point of the other selected line element and a flag is set to indicate that it has been selected. At that end point, another lead vector is projected and the non-selected elements around that point are compared to determine which element has the smallest angle with the lead vector. Again, the angle is measured from the outside of the lead and the size of the angle is determined using a coordinate frame. If an arc element is encountered, the angle from the outside of the lead vector to the arc tangent must be measured. Also, if there is only one element at the next end point (as in the corner position of the part), there is no need for comparison, and that element can simply be selected and included in the loop.
[0145]
As the loop path progresses along the appearance of the part, each selected element can be included in a linked list to indicate the connectivity of the elements in the loop. When the path returns to the starting point P1, the cycle is complete and a loop can be defined as (L4) based on the appearance and a linked list of elements or lines indicating the outer boundary of the part. Each line or element in the loop L4 can be connected at each end point. The direction of loop L4 can be changed to the opposite direction (ie, clockwise) as shown in FIG. 15 (d) to indicate that it is an outer loop. The direction of the loop can be defined based on the order in which the lines are linked in loop L4; thus the direction can be changed by reversing the order of the linked list.
[0146]
After completion of the outer loop, the inner loop of the part can be analyzed in a similar process as used for outer loop analysis. However, in the analysis of the inner loop, each non-selected element is compared based on the angle that each element makes with the inside of the lead wire vector. Furthermore, even if the inner loop analysis shows that both elements around a point have already been selected (for example, when comparing two outer line elements that bound a face), the two elements are already two. As long as the degree is not selected (2 flag setting), the two elements can be compared. In the case of an element selected at least once (for example, an outer element) and an element not selected, no comparison is performed, and an unselected element is selected as a part of the loop. 16 (a) -16 (c) illustrate an inner loop that can be used to detect and define the face of the component shown in FIG. 15 (a).
[0147]
Inner loop analysis can be started from the end of any outer element or by detecting an unselected element. For example, point P1 can be selected as the starting point for the inner loop analysis and used to project the lead vector; or one of the inner line elements not selected for the outer loop analysis can also be used as the starting point for the analysis. it can. As with the outer loop analysis, the lead vector can be extended counterclockwise (eg, the first lead vector starts in the Y coordinate direction). Each element around point P1 is then compared to determine which element has the smallest angle with the lead vector. A coordinate frame can be used to determine the angle formed with the lead wire vector. As described above, in the inner loop analysis, the elements are compared based on the angle that each element makes with the inside rather than the outside of the lead wire vector. Once the first element has been selected and included in the linked list of loops, the analysis can proceed by incrementing the flag by 1 and projecting the next lead vector. This process continues until the loop returns to the initial starting point, where the first inner loop is defined (eg, L1) by a linked list of corresponding elements.
[0148]
You can also go inside the part and do the inner loop analysis in the same way. The next starting point can be selected by determining which elements are selected only once. An element with a flag selected twice indicates that the element is already an outer element selected in an outer loop (eg, L4) and at least one of the inner loops (eg, L1). Again, as each element is selected, the flag is incremented by 1 to indicate that it was included in the inner loop linked list.
[0149]
After all inner loops have been defined (for example, after all the elements have been selected twice in the example of FIG. 16C), a loop tree (loop tree) can be created using the resulting loop. . FIG. 16D shows an example of a loop tree created based on the detected loops L1-L4. The outer loop (L4) of the part is defined as the root of the tree, and each inner loop (L1-L3) that has elements in common with the outer loop is defined as a child of the root. The presence of a common element can be detected by analysis and comparison of a linked list of elements that define each loop. If more elements (eg, holes or openings) are detected within the inner loop, these loops can be defined as children of the inner loop in which they are located (ie, the grandchildren of the root of the loop tree).
[0150]
After performing the surface detection procedure in step S.124, a bending line detection operation can be performed in step S.126. For example, as shown in FIG. 17, when detecting and analyzing a loop of parts in step S.124, the surface detection logic of the present invention defines surface information and nodes detected into a bend graph data structure. You can use a loop tree to store as The face of the part can be detected from the order of the outer and inner loops in the loop tree. As described above, each loop contains a linked list of elements or lines. These elements are used to delimit each side of the part. Therefore, a bend line detection operation can be performed in step S.126 to determine the relationship between the part surface and the bend line. The bend line detection operation of step S.126 includes bend line detection logic that detects all bend lines between the various faces of a part by detecting an edge or line element shared by two adjacent faces. be able to. Also, for surfaces connected in more than one region (for example, when applying the bend line detection algorithm to a 3-D model—see, for example, Figure 19 discussed below), various heuristics can be used. Apply to detect and select the minimum number of bend lines in the part. For example, as shown in FIG. 18, the detected bend line can be stored and connected as a connection agent between nodes (nodes) for creating a final bend graph data structure.
[0151]
The bend line detection operation of the present invention can be implemented, for example, by software provided in the server module 32 or programmed logic. The purpose of the bend line detection operation is to detect and select the bend lines of the parts so that the parts are connected by the least number of bend lines. Bend line detection operations can be provided for both 2-D and 3-D versions of parts. The application of bend line detection for the original 3-D model is discussed below with reference to FIG. As described above, the detected bend line can be stored as a connection agent between the nodes of the surface to create the final bend graph data structure. This final bend graph data structure can be used to fold from a 2-D data model to create a 3-D version of the part.
[0152]
The 2-D drawing provided as input in step S.120 of FIG. 11 may not include bend line information, or the bend line information may be unclear and not uniquely or consistently defined. In that case, a bend line detection operation can be performed to detect the bend line and to detect the relationship with the detected surface of the part. During this process, a linked list of elements (entities) defining each face can be analyzed to determine the adjacent end or line elements that each face has with the other faces of the part. This can be done by analyzing all possible contacts between a given two faces. Contact is due to the presence of a common line element (or multiple line elements that are at a predetermined distance tolerance from each other) that are 0 or more in length (ie, the line element is not a point but an actual line) Can be determined. By analyzing the geometric data in the linked list, the presence of such contact between all two faces of the part can be determined.
[0153]
If a particular face has only one common edge or contact area with the other face, the element common to both faces can be defined as a bend line. For multiple faces with common contact in one or more areas (eg 3-D model; but can also occur in 2-D model), the minimum number of bend lines of the part using various heuristics (heuristics) Can be detected and selected. The heuristic method used should be such that the faces are connected by bend lines so that continuous loops across the faces are not formed (since it is not possible to make such bent sheet metal parts).
[0154]
An example of a heuristic that can be used is to select the bend line that has the longest contact area in common areas. If a face has one or more common edges with another face, this heuristic can select the longest common element as the bend line of the face. This heuristic is based on the principle that it is usually better to have a long contact area when making bent sheet metal parts. Another heuristic that can be used involves different possible bend line combinations (such as when determining the bend lines of a 3-D model). In this heuristic, all possible common areas are detected, and when various combinations of bend lines are selected, the combination of bend lines with the smallest number of bend lines is selected.
[0155]
When a bend line is detected, the bend line determined to be the part surface is displayed to the operator for confirmation. If the operator is not satisfied with the selection of the bend line for the part, the bend line detection operation is provided with a manual selection function so that the server module 32 can selectively indicate the preferred bend line for the sheet metal part. Can be. The operator can instruct whether to hold or change the bend line using appropriate input means such as a mouse or a keyboard. Thereafter, the final 3-D (or 2-D) part can be created using the modified bend line selected by the operator.
[0156]
In order to carry out the bending line detection operation of the present invention, various processes and operations can be provided. An example of a code for performing a bend line detection operation is given in Appendix C. The example code is written in the C ++ programming language and includes comments to help understand the logic flow of the description. The example code is an example of a bend line detection operation that can be performed on a 2-D or 3-D model and includes a heuristic (as described above) that determines the optimal selection of bend lines.
[0157]
The detected surface and bend line information can be used in the folding and unfolding process of the present invention. When folding or unfolding, a 3D rotation around each bend line results in a 3-D or 2-D model. To perform this task, simply perform matrix transformations, including rotation and translation, on each side of the part and other elements. Various commercially available deployment and folding software application characteristics can be used to perform the basic deployment or folding steps of the present invention. For example, Amada Anfold and Folder System Software can be used to perform these basic operations. Amada Anford and Fold System software are available from Amada America (formerly US Amada), Beyuna Park, Calif. For information about Amada Anford and Fold System Software, see Amada Anford Manual for Autocad (March 1994), Amada Anford Manual for Cadkey (May 1994) and Cadkey In the Amada Windows Unfold Manual for and is expressly incorporated herein by reference in its entirety. The folding operation for creating the 3-D model from the 2-D model will be discussed later with reference to step S.132.
Returning to FIG. 11, after the bend line detection operation is performed in step S.126, the server module 32 instructs the user on the information of main bending and subtraction height (reduction amount) used in the subsequent folding process. There are things to do. For example, in step S.128, the server module 32 prompts the user for the bending angle including the bending direction (eg, forward, backward, etc.) and / or the bending height (bending amount) of each bending line including the bending inner radius. There are times when it asks. At step S.130, the server module 32 may also prompt the user for V-width, material type, and / or deduction height (reduction amount). These pieces of information can be used to compensate for the bending subtraction height (bending reduction amount) in the folding operation. Depending on the bend angle and the V-width of the die used, as well as the thickness and type of the material, the actual sheet metal part tends to be stretched by the difference height when the sheet metal part is folded.
[0158]
To compensate for this effect in the model, when creating a 3-D model in a folding operation using the difference height information, the dimensions of the part surface are stretched by half the difference height on each side of the bend line. . In line with the present invention, this amount can be entered by the user into the server module 32 (eg, via a keyboard or the like). Alternatively, a material table that includes a deduction amount based on the material type and thickness of the part can be displayed to the operator. The bill of material shows the different deduction heights for different bending angles and V-widths. The user can automatically set the deduction height by selecting the appropriate V-width and bending angle from the bill of material displayed on the server module 32 (eg, using a mouse or keyboard). The inner radius of the bending angle can also be set automatically by the user via the bill of materials when choosing the appropriate V-width. The amount of subtraction input by the operator (or converted after input by the operator) is a unit of the same length (for example, mm) as that representing the part geometric data. During the folding operation, the length dimension of each side of the bend line is increased by half the deduction height of the bend line of interest. The length dimension perpendicular to the bend line of the surface can be increased by stretching the end points of the elements that bound the surface on each side of the bend line. Such deduction height compensation can be performed for each of the other bend lines of the part based on the deduction height supplied by the operator for each bend.
[0159]
In step S.132, a folding operation including a compensation for subtraction height for creating a 3-D model is performed based on the processed 2-D plan view. As mentioned above, the folding procedure can be performed by conventional geometric modeling methods including the use of matrix transformations and using each bend line defined in the final bend graph data structure for the rotation axis. it can. In addition, to compensate for the effect of the net height, when folding a 3-D model, the sheet metal is actually folded by stretching the surface of the part by half the net height on each side of the bend line. It is possible to more accurately reflect the change in the dimension of the surface.
[0160]
For example, when the folding operation is performed in step S.132, the part geometry and the form data (or the bending graph structure) can be used together with the bending parameters (for example, the bending angle and the inner radius). A transformation matrix can be calculated for each face, bend line, hole and forming of a part expressed in 2-D space. 3-D spatial data can be obtained by applying a normal matrix transformation to the 2-D plan view. Transformation generally involves translation following rotation. As described above, the rotation is performed around each bend line axis according to the magnitude of the bending angle. The translation operation is performed by moving or moving geometric data in the space. Such a translation operation is determined based on a bending radius, a bending angle, and a subtraction height of each bending. At the time of folding, the compensation for the difference in height is performed by extending or increasing the surface dimensions by half the amount of the difference on each side of the bend line as described above. Such subtraction height compensation provides a 3-D representation of the part that more accurately reflects the dimensions of the 2-D sheet metal part that is bent by the bending machine.
[0161]
Further information on geometric modeling and transformations can be found in, for example, Mortenson, Michael M, Geometric Modeling, John, which is expressly incorporated into this document by referring generally to the specification. See Wiley & Sons, New York (1988) and Foley et al., James System Programming Series: Basics of Interactive Computer Graphics, Addison Wesley Publishing, Reading, Massachusetts (1983). In Chapter 8 of Mortenson, geometric transformations including translation and rotation are discussed (see eg pages 345-354). In addition, Foley et al. In Chapter 7, pages 245-265 give information on geometric transformations, including matrix representations of 2-D and 3-D transformations. Additional information about modeling and geometric transformations is expressly incorporated into this document by referring generally to the specification, by Mantira, Martti, Introduction to Solid Modeling, Computer Science Publishers, Also given to Rockville, Maryland (1988). Information on coordinate transformation can be found on pages 365-367 of Manteira.
[0162]
Next, a process and operation for creating a 2-D model based on the original 3-D plan view without thickness will be described according to another aspect of the present invention with reference to FIG. Similar to the folding process described above with reference to FIG. 11, the various processes and operations for unfolding a 3-D drawing and creating a 2-D model are performed by software and / or programs in the server module 32. It can be implemented using the logic. As shown in FIG. 19, the original 3-D drawing provided and created based on customer specifications is input or incorporated into the server module 32 at step S.140. 3-D drawings are stored as DXF or IGES files and can be entered from the server module 32 by interfacing with or using a CAD or CAD / CAM system. After entering the 3-D drawing, automatic trimming and cleanup operations are performed by the server module 32 in step S.142 to prepare the drawing for subsequent surface detection and other processes.
[0163]
As discussed in connection with FIGS. 12-14, the automatic trimming and cleanup feature separates and connects components and surfaces so that various aspects of the part are properly detected and defined.
[0164]
The above-described automatic trimming and cleanup operations related to FIGS. 11, 12, and 13 can be similarly applied to the geometric data of the 3-D drawing input in step S.140 of FIG. 19. Instead of analyzing the data in 2-D space (as in the 2-D plan view), each component shown in the 3-D drawing (eg, line, arc, etc.) Analysis can be performed based on D coordinates and spatial information. The intersection and open intersection area can be analyzed by analyzing each component (entity) individually and comparing each component with each other. Again, using basic geometric analysis of component endpoints and other attributes, intersections and open intersection regions can be determined within tolerance.
[0165]
After performing the automatic trimming and cleanup function on the three-dimensional drawing, in step S144, a surface detection operation is performed to detect and define each of the surfaces of the sheet metal part. Surface detection for the three-dimensional drawing is performed by analyzing and detecting each surface in a two-dimensional space and generating a loop tree as described above. Surface detection is performed by starting with any given entity. For example, the leftmost entity (ie, the entity with the smallest x coordinate) is used as the first entity. A plane is then defined by taking out the first line segment entity and other connected or adjacent line entities (ie, any entity having a common endpoint with the first entity). The face detection operation is then performed using loop and entity analysis as described above in connection with FIGS. 15 (a) -16 (d). Since each entity is detected in the defined 2D plane, various outer and inner loops are defined, and the entity is marked (ie by setting or incrementing the flag of the selected entity). ), Indicating that they have been selected and included in a linked list defining one of a plurality of loops in the face.
[0166]
Subsequent loop analysis is then performed on the other two-dimensional planes that make up the three-dimensional drawing. To perform loop analysis of the other entities, additional planes are defined by searching for unmarked or unselected entities in the 3D drawing. Such a plane is defined between two unselected entities or between an unselected entity and a previously selected entity. In each additional two-dimensional plane, further loop analysis is performed to detect the inner and outer loops. A linked list of reconnected entities is maintained, and as each of the plurality of loop paths is defined, the selected entity is marked (ie, by incrementing a flag associated with the selected entity). ).
[0167]
After all entities have been detected, the resulting multiple loops are used to generate a loop tree for each of the already analyzed two-dimensional planes. As already mentioned, a loop tree is provided for defining a plurality of faces and openings and holes in a sheet metal part. For a three-dimensional drawing, a loop tree is generated for each side of the sheet metal part. The multiple loops detected in each plane are grouped and analyzed to generate each loop tree. The root of each tree is defined as the outer loop detected in the plane. Each inner loop of the plane having an entity in common with the outer loop is defined as a child of the tool. The presence of a common entity is detected based on analysis and comparison of the list of linked entities that define each loop. When additional entities (ie holes or openings) are detected in the inner loop of the plane, these loops are defined as children of the inner loop in which they reside (ie the grandchild of the root of the loop tree). The The generated loop trees are then used to detect all the faces of the 3D drawing. The detected faces are then stored as nodes in the bend graph data structure.
[0168]
The resulting bend graph structure is supplemented by the connecting bend line connection agent after execution of the bend line detection operation in step S146. The bend line detection operation and generation of the final bend graph structure or part topology is performed in a manner similar to that described above with reference to FIGS.
[0169]
As noted above, exemplary code for performing the bend line detection operation is provided in Appendix C attached hereto. This sample code is a representative implementation for a bend line detection operation made on a 2D or 3D model and includes heuristics (eg, as described above) for determining the optimal selection of bend lines. . The bend line detection operation includes a manual selection feature that allows an operator in the server module 32 to selectively specify a preferred bend line for the sheet metal part when not satisfied with the detected bend line. The operator instructs to maintain or change the bend line by appropriate input means such as a mouse or a keyboard. The bend line selected and revised by the operator is used to generate the final two-dimensional part.
[0170]
Prior to performing the unfolding process centered on multiple bend lines of the final bend graph structure, the user is prompted for V width, material type and / or reduction amount in step S148. As described above, since the sheet metal has a tendency to stretch when bent, the dimension of the three-dimensional part is slightly larger than that of the two-dimensional planar part. Accordingly, in the process of unfolding the sheet metal part, the part dimensions are reduced or reduced by a reduction amount based on the selected material type and V-width. Therefore, according to one aspect of the present invention, when developing a three-dimensional model, a reduction operation is performed in order to more accurately generate the dimensions of the two-dimensional model and its surface. As described above, the reduction amount is directly input by the user, or a material table is displayed so that the user can automatically set the reduction amount by selecting a desired V width and bending angle. Is done.
[0171]
The reduction amount input by the operator is a unit (for example, millimeter) having the same length as that expressed by the part geometric data (or converted into the unit after the input by the operator). During the unfolding operation, the dimensional length of each side of the bend line is reduced by half the amount of reduction entered for the given bend line. The dimension length of the surface perpendicular to the bend line is reduced by reducing the endpoints of the entities that define the boundaries of the surface located on either side of the bend line. The reduction compensation is performed at each of the other bend lines of the part based on the amount of reduction provided by the operator for each bend.
[0172]
After the input of all necessary data, in step S150, a development process is performed to generate the two-dimensional model. Conventional methods are used to develop the three-dimensional bending model, including the use of a matrix transformation that uses each of the plurality of bending lines as a rotation axis. During this unfolding process, each bend angle is measured and the part is unfolded by the bend angle amount to produce the planar bend model. Further, based on the input reduction amount, the reduction amount on both sides of the bend line is used to more accurately simulate the physical properties of the sheet metal material and the difference between the three-dimensional and two-dimensional models. The size of the surface is reduced or reduced by half.
[0173]
When performing the unfolding step in step S150, the part dimensions and topology data (or bend graph structure) are used along with the bend parameters (eg, bend angle, inner radius, etc.). A transformation matrix is calculated for each face, bend line, hole and molded part in the part represented in the three-dimensional space. A normal matrix transformation is applied to the 3D data to obtain the 2D spatial data. The transformation generally involves rotation followed by translation. As described above, the rotation is performed around each bend line in accordance with the bending angle amount. For deployment, rotation is done in the opposite direction until there is 180 ° between the two faces (ie until the face is flat). Translation is performed to shift and move the geometric data in space. Such translation is determined based on the bend radius and bend angle and reduction amount for each bend. During expansion, reduction compensation is performed to reduce or reduce the dimensions of the surfaces by half of the reduction amount on either side of the bend line, as described above. Such reduction compensation provides a two-dimensional representation of the part that more accurately reflects the dimensions of the sheet metal part before it is folded during the bending process.
[0174]
Again information about geometric modeling and transformation can be found in Mortenson, Folly et al. And Mantila. As noted above, Chapter 8 of Mortenson provides a discussion of geometric transformations including transformations and rotations (see, eg, pages 345-354). Furthermore, Foley et al. Provides information on geometric transformations, including matrix representations of two-dimensional and three-dimensional transformations, on pages 245-265 of Chapter 7. Further information on coordinate transformations can be found on pages 365-367 of Mantila.
[0175]
As described above with reference to FIG. 4, based on the customer's order, if a two-dimensional three-dimensional view or a three-dimensional wireframe diagram without thickness is first provided or generated, it has a thickness. Further steps are required to generate a non-reacting 3D model. Thereafter, the generated three-dimensional model without the thickness is used to generate a two-dimensional model by applying a development process or algorithm. 20-24 illustrate various processes or operations applied to generate a three-dimensional model based on the initial two-dimensional three-dimensional view. Further, FIG. 25 illustrates additional processes or operations applied to generate a three-dimensional model without thickness from an initial three-dimensional wireframe diagram with thickness according to another aspect of the invention. To do. Again, the various processes and operations illustrated in FIGS. 20-25 are performed by software and / or program logic residing in the server module 32, for example.
[0176]
Referring to FIG. 20, in accordance with the teachings of the present invention, a description of the logical flow of operations or processes performed to generate a 3D model (without thickness) based on the initial 2D 3D view. Is provided. First, in step S160, a two-dimensional three-dimensional view is input to or loaded into the server module 32. The first two-dimensional three-side view includes various views of the part (eg, front view, plan view, and right side view, see, eg, FIGS. 22 (a) and 22 (b)) to the server module 32. A CAD drawing such as a DXF or IGES file that is downloaded or imported. Thereafter, in step S162, a two-dimensional cleanup operation is performed by the server module 32 to create a drawing for subsequent operations on the three-dimensional model. This two-dimensional cleanup operation is performed to eliminate extra and non-geometric information that does not represent the actual geometric shape of the part, including text and centerlines and dimension lines. The two-dimensional cleanup operation is also performed to connect all outer line segments, for example at their connecting ends, or to break or trim any intersecting lines or entities. FIG. 21 illustrates an example of the logical flow of various processes executed when the cleanup operation is performed by the server module 32.
[0177]
As shown in FIG. 21, first, a two-dimensional drawing is read or loaded from the data file by the server module 32 in step S180. Thereafter, in step S182, the server module analyzes each entity or geometric data in the two-dimensional drawing and divides the various entities to create a drawing for the next process. The division or trimming function performed in step S182 is performed in the same manner as described above in connection with the automatic trimming and cleanup function of the present invention. Thus, in step S182, all geometric data in the two-dimensional three-dimensional view is analyzed to detect entity intersections and blank (open) intersections within a predetermined error range. Any intersection line is broken and the resulting entity meets at a common endpoint defined by the intersection. In addition, for entities that have a blank crossing area that is within a predetermined error (eg, 0.0-0.01 mm or 0.0-0.001 inch), those entities may be associated with, eg, FIGS. 12-14. They are combined in a manner similar to that described above.
[0178]
In step S184, the periphery of the two-dimensional drawing sheet is searched, and arbitrary external line segments or data (for example, boundary line segments, coordinate grids, and numbers) are deleted. As shown in FIG. 22 (a), a two-dimensional three-dimensional view is often provided on a drawing sheet. The drawing sheet includes extra and non-geometric information that is not necessary to generate various drawings of the sheet metal part. Therefore, in step S184, this type of information is detected and deleted from the two-dimensional drawing in developing the three-dimensional model using the two-dimensional cleanup process of the present invention.
[0179]
The two-dimensional drawing data includes a keyword or type field for indicating the type of data (eg, geometric or non-geometric / text) contained therein. Thus, these keyword or type fields (which are provided based on the data format of the drawing file) are used to delete various extra information such as text or other non-geometric data. However, further operations are usually necessary to correctly delete all unnecessary drawing sheet data. Often, the boundary lines or other outside information is stored as entities (eg, line segments, etc.) that cannot be easily identified based on the data keyword or type field. Therefore, according to one aspect of the present invention, a connectivity graph structure is generated when analyzing the data of the two-dimensional drawing. This connectivity graph structure shows a list of multiple incidental vertices and a list of connected entities for each entity. For each vertex, a list of adjacent vertices and the entity to which it is attached is provided. This graph structure (which is generated when performing the severing and trimming function of step S182) determines which entities are joined by the end points that stick together. As a result, extra data such as borders and information boxes and other non-geometric data is deleted. This is because this data typically does not consist of and does not contain connected entities.
[0180]
As mentioned above, the two-dimensional three-dimensional view includes extra information such as dimension lines and arrow lines and centerlines and text, which do not represent the actual geometry of the part. These entities are detected in step S186 and deleted from the 2D data file to create a 2D drawing for the next process. Detection of these extra entities is done automatically by the server module 32 (eg, by detecting items in the two-dimensional data file that are not related to the actual geometry of the part). For example, using the connectivity data graph structure, entities that are open at both ends (eg, multiple lines used to underline text or indicate dimensions or part centerlines) are detected and deleted. The Other entities such as arrows are also detected based on the presence of floating endpoints or other features of such entities. In order to effectively delete all unnecessary data, the server module 32 may instruct the operator (eg, with a mouse or keyboard) which items in the two-dimensional drawing should be deleted. Provides a manual editing function to enable it. With this operator assistance or confirmation, additional extra information is removed from the drawing.
[0181]
After step S186, the various views of the two-dimensional drawing are grouped and defined in step S188. According to one aspect of the present invention, the server module 32 is predetermined as shown in a plan view (top view), a front view, and a right side arrangement as shown in FIGS. 22 (b) and 23 (a). Or support standard drawings and orientations. Other views and layouts can also be supported, such as top and front or back views and right or left views. As described further below, the server module 32 also supports rotated figures (see, eg, FIG. 23 (a)) to process the two-dimensional drawing figures into a three-dimensional representation of the part. . In any case, in order for a three-dimensional model of a part to be constructed, at least two (and preferably three) different views of the part having a thickness representation need to be provided. By analyzing the connectivity and grouping of the entities in the connectivity graph structure, the server module 32 classifies the plurality of diagrams based on the relative position and / or coordinate position of each of the diagrams and Define.
[0182]
By way of non-limiting example, the definition of the figure by the server module 32 may be a predefined or normal arrangement or layout for analyzing the figure in the data file and / or detecting the orientation of the figures. This is performed based on the superposition of various dimensions of the parts in each of the figures of the drawing. A predefined or standard form, such as that shown in FIG. 23 (b), is used to determine and define each of the diagrams depending on the potential diagram type. A geometric comparison of the relationship between the various endpoints and the entities defining each group is performed to perform step S188. The figure detection characteristic (figure detection function) of the server module 32 labels each of the drawings according to one of a plurality of potential drawing types (eg plan view, front view, rear view, left view, right view). wear. Detection of each of the plurality of figures is based on a predefined or standard figure arrangement or shape and a detected relationship between each of the existing figures. Various processes or operations are used in step S188 to classify and define a plurality of diagrams in the two-dimensional three-dimensional view. For example, after accessing the processed two-dimensional three-view drawing, the server module 32 first specifies a plan view of parts in the drawing data. The plan view is detected based on a predefined or standard shape or figure arrangement (such as that in FIG. 23 (b), for example). If three different figures are detected in the horizontal or vertical direction, the central figure is defined as a plan view. Furthermore, if three separate figures are not detected and only two separate figures are detected in the vertical direction, the upper figure is defined as a plan view. Again, the connectivity and grouping of the entities in the connectivity graph structure is used to detect each of the plurality of diagrams. A stored look-up table or matrix that represents the predefined or standard form is used to compare the figures of the two-dimensional drawing and detect each of the figures.
[0183]
After detecting a plan view from the two-dimensional three-view plan data, another view of the part is detected based on the relative position of each of the plurality of views with respect to the detected plan view. For example, based on the standard layout of FIG. 23B, if a figure group is positioned on the plan view, the figure is defined as a rear view. However, if a figure group is located below the plan view, the figure is defined as a front view of the part. Further, the right figure and the left figure are detected based on their relative positions on the corresponding right and left sides of the plan view, respectively. Thereafter, any remaining views that do not match the standard form (eg, FIG. 23 (b)) are detected based on their relative positions with respect to the detected view (eg, detected rear view or front view). Is done. For example, for the layout B shown in FIG. 23A, the right figure is provided at a position rotated with respect to the plan view. However, the right diagram in layout B is detected based on its relationship to the detected front view. That is, undetected views present on the right or left side of the detected rear view or front view are defined as the right view or left view of the part, respectively.
[0184]
Various predefined or standard diagram layouts are used to detect and define multiple diagrams in the two-dimensional three-dimensional drawing. Standard forms (eg, those in FIG. 23 (b) or FIG. 23 (a)) are widely prevalent in manufacturing facilities or are based on and / or supported by the selected / required diagram layout. Selected based on type. If none of the figures are detected, a warning signal is provided by the server module, and the operator modifies the two-dimensional three-dimensional drawing data or performs other appropriate operations according to the preferred drawing layout. In addition to providing a predetermined or standard form for detecting a plurality of figures in the two-dimensional drawing, a predetermined standard form (such as layout A in FIG. 23 (a)) is detected. It is provided for processing the generated figure and generating a three-dimensional model of the part. Thus, rotated figure features are provided to correctly classify the figure detected based on the standard form before further processing.
[0185]
As described above, the two-dimensional cleanup operation supports and detects rotated figures that do not conform to a predetermined or standard form for detecting figures in the drawing. In the rotated figure option, the detected non-standard figures are used to process and generate a three-dimensional model of the part, each of the plurality of figures being the predetermined or standard figure. It is rotated or translated so as to conform to the form. Assuming a standard form such as that illustrated in FIG. 23 (b) to detect multiple views of the part, each of the multiple views in layout B in FIG. 23 (a) is described above. In this way, detection is based on the relative position of the plurality of figures with respect to the plan view and other detected figures. For example, if layout A in FIG. 23 (a) is used as a predetermined or standard diagram layout for processing various views in a two-dimensional drawing having a plan view, a front view, and a right view, steps In S188, the right diagram in layout B is rotated 90 degrees to provide a modified diagram layout of the parts, similar to layout A. By rotating the right diagram 90 degrees in the layout B so that the right diagram of the part is located on the right side of the plan view of the part, the plurality of diagrams in the drawing are represented in a standard form represented by the layout A It is processed according to. A stored look-up table or a matrix representing a predetermined or standard form compares multiple figures of the two-dimensional drawing and determines which figure requires rotational or translational motion. Used for.
[0186]
In order to ensure that an accurate three-dimensional model of the part is generated from a plurality of diagrams in the two-dimensional drawing, the dimensions of each of the plurality of diagrams are consistent or consistent with each other. Checked. As further shown in FIG. 21, in step S190, the boundaries of the plurality of figures in the data file are detected in order to check whether all the dimensions of each figure are the same. If it is determined that the plurality of figures do not match within a predetermined error range (for example, 0.0-0.01 inch), in step S190, an arbitrary specification is made so that all the plurality of figures have the same scale. Appropriate modifications are made to change the dimensions of the figure. An alarm element is provided in the server module 32 to alert the user that the necessary modifications are made to the currently existing 2D drawing data whose drawing dimensions do not match each other.
[0187]
Various operations or processes are used to detect and confirm dimensional consistency in each figure of the part. For example, the corresponding dimensions of each of the plurality of figures are compared to determine whether they are within a predetermined error from each other. Such an analysis includes comparing line segment entities that define the boundaries of each drawing of the part. Assuming the standard form in FIG. 23B, the plan view is detected as being coincident with the right figure or the left figure as follows. That is, for each figure, the maximum Y coordinate position and the minimum Y coordinate position are within a predetermined error range (for example, 0.0-0.01 inch). Further, the plan view is detected to coincide with the front view or the rear view in the following cases. That is, for each figure, the maximum X coordinate position and the minimum X coordinate position are within a predetermined error range (for example, 0.0-0.01 inch). Further, in the left figure or the right figure, the difference between the maximum X coordinate position and the minimum X coordinate position is a predetermined error range (for example, 0.0-0) compared to the difference between the maximum Y coordinate position and the minimum Y coordinate position. .01 inch) is determined to coincide with the front view or the rear view. Again, a warning element or module is provided in the server module 32 to warn the user that necessary modifications are made to the two-dimensional drawing data when the dimensions of the figure or the dimensions of the associated surface do not match.
[0188]
Finally, in step S192, the inner loop, hole and shape of the part are detected based on the teaching of the surface detection method of the present invention. Various holes or shapes on the inside of multiple faces in each figure are detected by forming loops from the outside to the center of the part through the various lines and boundaries of the part. . Loop and entity analysis is performed on each view of the part in the two-dimensional drawing. By analyzing each figure operatively from the outside of the part to the center and inward, the detected loops move the boundary and area between the part and the opening of the part in a periodic order (ie, substance, opening). , Substances, etc.). A loop tree, such as that in FIG. 16 (d), is generated for each drawing to determine the location of multiple faces and the location of any holes within each face. Entities that are not connected within the surface of the part, such as floating arcs or line segments, are detected and deleted in step S192.
[0189]
Exemplary code for performing the two-dimensional cleanup operation of the present invention is provided in Appendix D. This code is written in the C ++ programming language and includes comments to facilitate the analysis of the logic and algorithms used therein. The code includes various steps and operations of the two-dimensional cleanup mode, such as those discussed above with reference to FIGS. 21-22 (b).
[0190]
Referring again to FIG. 20, after a two-dimensional cleanup operation has been performed, the logic flow continues to step S164 where the two-dimensional drawing represents or includes material thickness (ie, the two-dimensional drawing). Whether or not has a thickness). If it is determined that the two-dimensional drawing includes a thickness amount, the server module 32 performs a thickness erasure procedure to create a two-dimensional drawing for subsequent operation on the three-dimensional model in step S166. Done. The determination of the presence of thickness in the two-dimensional drawing is automatically performed by the server module 32 based on the drawing data, or by the server module through assistance or response from the operator (the operator can remove the thickness). Is prompted to indicate whether is needed or preferred). The thickness of the part is erased by the unique symmetry of all sheet metal parts. By erasing the thickness of the part, the resulting sheet metal part having no thickness is more easily analyzed by the sheet metal operator or designer. Furthermore, the inventor of this application has found that the time required to convert a two-dimensional drawing and generate a three-dimensional model is significantly reduced by removing the thickness of the two-dimensional three-dimensional view.
[0191]
Since most 2D 3D views contain material thickness quantities, operators are often confused about which bend lines must be selected to create a 3D model from a 2D drawing. As a result, considerable time is wasted in selecting an appropriate bend line so that a two-dimensional three-dimensional view is converted into a three-dimensional model. An example of a two-dimensional three-view diagram with thickness is shown in FIG. According to one aspect of the invention, a simplified representation of the material thickness amount and the inner and outer dimensions of the part in the bending model data is represented and processed without having a material thickness. A thickness removal procedure is provided to display a two-dimensional three-view model. FIG. 24 (b) illustrates a simplified two-dimensional three-dimensional view that is observed and displayed to the operator in the server module 32 after performing the thickness removal step.
[0192]
When the thickness removal procedure is performed, the user may be prompted to specify the material thickness in the two-dimensional three-view display, and any dimension (ie, outer dimension or inner dimension) in the display. ) May be prompted to specify whether it should be retained. The operator uses, for example, a mouse to indicate the thickness and surface held in one of the figures. Based on the data entered by the user, the server module 32 modifies the two-dimensional three-dimensional view, erases the material thickness indicated by the user, and leaves the inner or outer dimensions based on the operator's selection. .
[0193]
To erase the thickness in the two-dimensional three-view drawing, the server module 32 analyzes each of the three views based on the selection made by the operator. The selected surface is projected onto one of the other figures by geometric calculation (ie, by detecting the corresponding entity existing in the same X or Y coordinate projection as the selected entity line or surface). And detecting a corresponding entity and line segment in each of the plurality of figures. Corresponding entities are marked and retained, non-matching entities or surfaces are deleted or not displayed on the screen, like that shown in FIG. 24 (b). In addition, the thickness dimension line indicated by the operator is similarly projected to each of the other figures, and the matching thickness dimension line or entity is deleted as further shown in the example of FIG. 24 (b). As a result, each of the drawings in the drawing is appropriately modified and displayed to the user in the server module 32. The resulting 2D 3D view without thickness is used in the next step to generate a 3D model of the part.
[0194]
The thickness deletion procedure of the present invention includes a manual thickness erase mode for allowing the operator to selectively indicate the thickness lines to be deleted and the surface entities to be left in each figure. A mouse or other suitable input device is used by the operator to indicate which areas should be deleted and which surfaces should be left in each of the displayed figures. Based on the data entered by the operator, the server module 32 deletes each line segment entity selected by the operator from the two-dimensional three-dimensional view to provide a drawing having no thickness.
[0195]
The present invention also analyzes and detects whether all thickness representations have been correctly specified in the two-dimensional three-dimensional drawing, and there are inconsistencies in the drawing data when there are unmarked thickness elements. Includes a warning system or module to alert the user when present. For example, a thickness warning element may be provided to highlight potential unmarked thickness portions on the display screen, and the surface warning element may be used when the surface dimensions do not match the thickness marks in other figures. Provided to highlight potential non-matching surfaces on the screen. A bend line warning element is also provided to highlight contradictory bend lines and highlight non-matching thickness curves. A curve is emphasized when at least one bend line projected onto this curve is not sandwiched by two transverse thickness segments (thickness transverse lines). For example, FIG. 24 (c) illustrates a thickness curve that is correctly sandwiched by two or other non-zero even number of transverse thickness segments (ie, a short line across the thickness in each figure). Each bend line should be sandwiched by two or other non-zero even number of transverse thickness segments. Analysis of these entities of the part in each drawing is based on performing a loop analysis and analyzing the connectivity of the line segments and arc entities that make up each drawing. An open thickness line is defined based on a thickness line having at least one end point that is not connected to another thickness line or curve. A side containing one open thickness line segment is defined as an open thickness side. The thickness line segment is highlighted if the open thickness side of the open thickness line segment does not match the minimum loop bounding box. By giving the user a warning related to the processed two-dimensional three-dimensional view image, the user is warned of inconsistencies in the drawing data and the user is further processed to generate a three-dimensional model of the part. In addition, the drawing data can be corrected and / or corrected. Including such a warning system and user interaction improves the accuracy of the representation of the part by a three-dimensional model.
[0196]
In step S168 of FIG. 20, the processed two-dimensional three-dimensional drawing having no thickness is converted into a three-dimensional model and developed. Conversion and expansion from a two-dimensional three-dimensional drawing to the three-dimensional model is performed using well known or established projection and / or projection methods. For example, in order to generate a three-dimensional model from the two-dimensional three-view drawing, the depth of each figure is detected, and each figure is projected to develop the three-dimensional model. The resulting 3D model is then used in generating the bending model data and converted to a single 2D plan view by applying the expansion algorithm described above. For more information on geometric modeling techniques, see Mortenson, Folly et al. And Mantilla. See, for example, below for additional information about projection techniques for constructing 3D models from 2D drawings. Wesley et al. A. “Meshing projections” B. M.M. J, RES, DEVELOP, 25, NO. 6, pp. 934-954 (1981), Aomura Sigel, “Forming a Solid Model Using Mechanical Drawings”, 6th Computer Mechanics Conference, JSME, NO. 930-71, Japan, 497-98 (1993), Aomura Sigel, recent trends in research and actual use and future possibilities (automatic reconstruction of 3D models from drawings) Tokyo Engineering Co., Ltd., Japan, 6-13 (1995). These disclosures are expressly incorporated herein in all of them.
[0197]
When developing the 3D model in step S168, an additional cleanup step is included to further process and refine the resulting 3D model. According to one aspect of the invention, the 3D cleanup process is obscured that exists in a 2D 3D view of the part and generates extra or excessive information in the generated 3D representation of the part. It is provided to compensate for this. As will be appreciated by those skilled in the art, a two-dimensional three-dimensional representation of a part includes ambiguities associated with the representation of various features of the part in a three-dimensional coordinate space. Excessive and excessive information is generated as a result of these ambiguities when generating a 3D model from the 2D 3D view. Therefore, according to an aspect of the present invention, the three-dimensional cleanup process includes the steps of detecting and removing a line segment that is not connected to one end, detecting and cleaning a bend line, and trimming the surface. . The 3D cleanup process is performed automatically when generating a 3D model as a result of the part or input from an operator when it is determined that the generated 3D model requires additional steps. Is selectively performed on the basis of
[0198]
According to the three-dimensional cleanup process, by analyzing the generated three-dimensional drawing data, all line segments or curves determined not to be connected to other entities at one end are identified, and one-side open lines Defined as minutes. Any entity that is determined to be a one-sided open line segment is removed from the three-dimensional representation of the part. Once an open line is removed, it may lead to other lines or entities being released. Thus, a new one-sided open line is also identified and removed repeatedly until all open lines or entities are removed. FIG. 63 illustrates an example of a three-dimensional representation of a part before the one-side open line segment is removed, and FIG. 64 illustrates the part after the one-side open line segment is removed from the three-dimensional representation.
[0199]
As described above, the three-dimensional cleanup process performed in step S168 includes a process of detecting and cleaning a bend line. Bend lines are identified and cleaned to facilitate detection of part surface information in three-dimensional space (eg, by adding mold lines). Based on the generated 3D model data, each bend line is a pair of 3D curves having the same normal defined by their respective centers (eg, it is represented by a curve entity in the drawing data). Identified based on detection. In this process, a mold line is added to the specified bending line. The mold line segment identifies a corresponding endpoint in each pair of 3D curves and extends a mold line segment (eg, represented by a line segment entity) between the corresponding endpoints of the 3D curve. Added. FIG. 65 illustrates a representative three-dimensional representation of the part before the bend line is identified, and FIG. 66 illustrates the part after the mold line segment (represented by the dashed line in the figure) has been added.
[0200]
After the bend lines are identified and the mold lines are added, the 3D cleanup process further processes the 3D representation of the part to clean all the bend lines of the part and trim the surface. Due to frequent ambiguities in the two-dimensional three-view drawing diagram, an excess portion of the surface is generated in the three-dimensional representation of the part. The three-dimensional cleanup process identifies excess portions of the surface and trims the surface using sheet metal domain knowledge (eg, knowledge of what cannot be folded). Other extra information, such as extra holes or openings, is also identified and removed. As a result, the excess part of the part is removed and the three-dimensional representation provides a more precise representation of the sheet metal part. FIG. 67 illustrates a representative portion of the part before the bend line is cleaned and the surface is trimmed, and FIG. 68 illustrates the portion of the part after normalization and trimming.
[0201]
FIG. 25 shows an example of the logical flow of steps and operations performed to generate a 3D drawing without material thickness from an initial 3D drawing with material thickness. In step S200, the first three-dimensional drawing having the material thickness is input and carried into the server module 32. The three-dimensional model is a three-dimensional wire frame drawing having a material thickness, and is a CAD drawing file such as a DXF or IGES file. After the three-dimensional drawing is carried into the server module 32, a thickness removing process is performed in step S204. The thickness removal process for the three-dimensional model in step S204 is performed in the same manner as provided in the Amada UNFOLD software system described above. To erase the thickness in the three-dimensional model, the operator is first prompted to indicate the thickness and select the surface to be left. The thickness is measured by analyzing the endpoint of the entity line segment that defines the thickness based on the operator's choice. Thereafter, the boundary of the selected surface is searched in a manner similar to that described above in connection with the loop and entity analysis steps. The retained entity is then marked (for example by setting or incrementing a flag) and the corresponding thickness entity is removed. In searching for the entity of the 3D part, the entity is identified based on the length of the thickness entity selected by the user. In general, all entities having the same length as the thickness entity are not selected and removed, and other entities that are not the same length are marked and left. The remaining entities that were not marked in the search of the surface of the 3D part may also be removed. Again, the server module 32 provides a manual thickness removal mode in which the operator manually indicates each entity in the 3D part to be removed.
[0202]
After step S204, the resulting 3D model without thickness is developed and / or displayed to the operator in step S206. An unfolding algorithm or process is then applied to the three-dimensional model that does not have that material thickness to generate a single two-dimensional plan view for the bending model data as described in detail above. As described above, the design and manufacturing information stored in the database 30 includes a bending model data file including not only manufacturing data on sheet metal elements but also sheet metal geometry and topology. In addition, the software used to implement the various features of the present invention is generated using advanced programming languages such as C ++ and using object-oriented programming techniques. Different object-oriented techniques such as Boot or OMT are also used to implement the various features of the present invention. If an object-oriented program is used, object-oriented data is used to represent the sheet metal part, and the bending model for the part is executed through a fully self-contained class library. One aspect of the invention provides a description of representative data structures and access algorithms for the bending model based on object-oriented programming techniques. FIG. 26 illustrates a typical data structure and access algorithm of the bending model used when the present invention is executed by an object-oriented program. An object-oriented program is one type or form of software development that can model the real world by combining not only a plurality of objects or modules containing data but also a plurality of instructions that operate on the data. In an object-oriented program, an object is a software entity that models something physical, such as a sheet metal part, or they model something virtual, such as a business transaction. is there. An object includes one or more attributes (ie fields) that collectively define the state of the object and an identifier for identifying it from all other objects. Furthermore, an object includes behavior defined by a group of methods (ie, procedures) that modify the attribute or act on the object based on the presence of certain conditions.
[0203]
According to an embodiment of the present invention, the sheet metal part is represented as an object-oriented data model. As shown in FIG. 26, the bending model of a sheet metal part is defined as a completely self-contained class library. All required data operations and functions (eg folding, unfolding, etc.) for the sheet metal parts are captured as element functions of this class library. All geometric or topology data is defined within a plurality of objects classified in the bending model. The bending model class library is a hierarchy of a plurality of classes or objects, and the part class is a top-level class in the hierarchy. The part class includes part objects having various part attributes, and includes various objects that define the part and a plurality of actions to be performed on the part.
[0204]
FIG. 26 shows examples of various objects classified in the bending model class library. For example, a part class 50 including various attributes 52 is provided. The part attribute 52 includes various part information such as part number and / or name, part material type and part thickness. The attributes 52 also include other manufacturing information such as bending order information to indicate the order in which multiple bends are made and error requirements for various dimensions of the part. The part class 50 also includes various objects such as a plane object 54, a hole object 56, a forming part object 58, and a bend line object 60 as shown in FIG. Each of the objects 54, 56, 58 and 60 consists of a group of objects for each of the entities (eg, faces, holes, formed parts, and bend lines) represented therein. The plane object 54, the hole object 56, the forming part object 58, and the bend line object 60 are respectively geometric shape and dimension data, position and coordinate data in two-dimensional and three-dimensional spatial representations, and their respective entities. Includes data related to edges and surfaces (eg, faces, holes, shaped parts, and bend lines). For example, the plane object 54 includes geometric shape and dimension data for each of the plurality of planes, spatial position data of the plurality of planes in two-dimensional and three-dimensional representations, and end and surface of the plurality of planes. Includes edge and surface data. In addition, the molded part object 58 contains data relating to special molded parts in the part, which data includes geometric and dimensional data, two and three dimensional spatial position data, and edge and surface data.
[0205]
As further shown in the example of FIG. 26, the part class 50 further includes a topology object 62 and a bending property object 64. The topology object 62 includes part topology data for the face, hole, formed part and bend line of the part. Data in the topology object 62 indicates the structural and geometric relationships of the various features of the part. The bending property object 64 contains information regarding special manufacturing constraints for one or more features of the part. For example, bending characteristic information regarding how the sheet metal part should be bent is provided in the bending characteristic object 64. The bending property information includes special manufacturing data for different bending property types (eg, simultaneous bending, collinear bending, Z-bending, etc.).
[0206]
The bend line object 60 also includes manufacturing special data relating to the bending to be performed. Thus, in addition to geometric or dimensional data for each bend line, 2D and 3D spatial position data, end data, the bend line object 60 also includes V width data, bend pitch data for each bend line, Includes bend number data and / or orientation data. Each bend line includes an accompanying bend operation as shown in FIG. This bending operation is performed as a group of objects having data and operations / instructions for bending at each bend line. If provided as an object, each bend operation is not only specific bend data such as bend angle, bend radius and / or bend reduction, but how or what type of bend should be performed (eg, conical bend, Z-bending, hemming, arc-bending, etc.) and data and commands are included.
[0207]
By executing the bending model of the part via an object-oriented data model, all complex mathematical calculations, computational geometries and matrix transformations are incorporated into a single class library. Special bending operations such as hemming, Z bending and arc bending are also included in the class library. Further, manufacturing information such as V width, bending reduction amount and bending order is also taken into the class library. According to the bending model, simultaneous double display of the two-dimensional plane model and the three-dimensional model is performed as shown in FIG. Further, bending is performed according to the bending line object 60 of the bending model. General comments relating to the bending model and part structures and their execution are provided in Appendix K attached hereto.
[0208]
A bending model viewer is provided for interpreting the bending model and displaying a visual image of the part in a two-dimensional and / or three-dimensional representation. FIG. 27 illustrates a block diagram of the relationship between the bending model viewer structure and the bending model according to another aspect of the present invention. The bending model viewer is executed via an object-oriented programming technique, and based on information provided by the user in the station module at various locations 10, 12, 14,... Windows-based application that allows various diagrams to be displayed. The bend model viewer includes a group of application library modules that are used to visualize the sheet metal part. Furthermore, the bend model viewer is designed as an image class for Windows applications, so it is used as the basic image class for any Windows application. Most standard operations for viewing the 2D and 3D models (eg zoom 92, rotation 96, pan 100, dimension 102, etc.) are performed as elemental functions of the bending model viewer. Geometric transformations and basic computer graphics techniques are applied to the bend model object when performing image manipulation. In addition, the bending model viewer includes an image model attribute 88, which has four main image modes including a solid image, a wire frame image, a two-dimensional planar image, and an orthographic image.
[0209]
According to one aspect of the present invention, the bend model class library 80 can be configured to use a group of procedures or operations that operate on the sheet metal part, depending on a selected image (eg, solid, wire, two-dimensional plane, or orthographic image). Includes functionality. The bend model viewer observation class 84 includes a series of standard operations such as zoom 92, rotation 96, pan 100 and dimension 102. The bending model viewer observation class calls a plurality of functions from the bending model class library 80 according to the state of the bending model viewer. As shown in FIG. 27, the various observation model attributes or features 88 selected by the user include a solid image, a wire frame image, a two-dimensional planar image, and an orthogonal projection image. A description of these various viewing modes provided in the present invention is provided below with reference to FIGS. 28-31.
[0210]
Basic computer graphics and geometric modeling techniques, such as geometric transformations and 3D geometric techniques, are used to implement various features of the bending model and provide different viewing modes or functions. The Recent developments and developments in computer-based 2D and 3D modeling and simulation, such as the utility of graphic libraries or packages, are applied to implement these features of the present invention. In addition, a wide variety of publications or literature is available for computer graphics and modeling. See, for example, Muntilla, Mortenson, Folly, etc. Each of them is described above.
[0211]
In order to provide the various viewing and modeling features of the present invention, each station module and server module has a high resolution display screen such as an SVGA screen having a resolution of 800 × 600. Joysticks and / or game cards are also provided to the station module and server module to allow the user to selectively modify and view different 2D and 3D representations of the part. Software based graphics packages such as OpenGL and RenderWare are used to perform graphics calculations. These graphic libraries or packages are used to implement various viewing modes in Windows based applications. For example, open GL is used to execute various two-dimensional wire frame images based on part geometry and topology data provided in the bending model. Further, the renderware is used to display various two-dimensional and three-dimensional solid images of the sheet metal part based on part data provided in the bending model. For more information about OpenGL, see, for example, OpenGL Reference Manual and OpenGL Programming Guide, Release 1, OpenGL Architecture Review Board, Addison-Wesley Publisher, Reading, Massachusetts (1992). See, for example, Renderware API Reference Manual V2.0, Criterion Software, Inc., UK (1996) for renderware information.
[0212]
In order to display various images of the part, the bending model is accessed from the database 30 by, for example, an operator station module. The bend model data is reformatted according to the data format used by the graphic library or package being used (eg open GL or renderware). Thereafter, the graphic data is variously programmed to display the observation mode (wire, solid, etc.) selected by the operator, or to perform the observation function (zoom, pan, etc.) performed by the user. Processed according to order.
[0213]
When a particular viewing mode is selected by the operator, the selected viewing mode is detected along with the current zoom ratio or factor and orientation of the image. This information is then used to make a function call to the graphics package to update the current display. Function calls to the graphic package are made according to the viewing mode being displayed and the zoom or other viewing function being performed. Based on these function calls, the graphic package provides the necessary data so that the station module displays an image of the part to the operator. Additional function calls are made to the graphics library to update the displayed image based on modifications of the 2D or 3D representation by the user (eg, by moving a joystick or mouse).
[0214]
In order to provide a wireframe image of the part, line entity data of the part is provided to the graphic package and the necessary graphic calculations are performed. However, for a solid image, one or more polygons (polygons) are drawn for each of the faces and provided as input to the graphics package for displaying the image. Graphic packages such as Open GL and Renderware take polygon data as input and fill the area defined by the polygon to provide a solid image. The polygon is derived from surface and bend line information in the bending model and is determined by determining the boundary of each surface. The polygon must be generated to display and define each face of the part. These faces are then connected based on the part topology and other data in the bending model to display the entire sheet metal part. If the surface has openings or holes, it is necessary to define a surface having several polygons that do not enclose such openings. For orthographic maps, the data for each individual figure (which can be a wireframe or solid) is sent to the graphics package and the resulting figures are displayed in a single display as shown in FIG. Combined on the screen. Exemplary code for performing various viewing modes and functions of the bending model image is provided in Appendix E. This sample code is written in C ++ and includes a plurality of comments relating to the process and the operations performed therein. The code in combination with a suitable graphics package (eg open GL and renderware) is not only used to display different figures (eg 2D and 3D wireframes or solids) but also the observation function ( For example, zoom, rotation, pan, etc.) are provided. A brief description of the various viewing mode display screens displayed is given below.
[0215]
The solid view mode displays a three-dimensional view of the part defined by the bending model and displayed as a solid. FIG. 28 illustrates a representative solid view window that is provided as output to a display screen provided at any of positions 10, 12, 14,... In this solid view mode, the user or operator is provided with a plurality of observation functions for operating navigation in 3D space and 3D automatic dimensioning. The basic functions provided for changing the solid view of the part include rotation, zooming, panning, and / or standard drawing selection. The standard map provided or selected by the user includes: That is, an isometric projection diagram, a plan view, a bottom view, a front view, a rear view, a left view, and a right view. Automatic and manual dimensioning operations are also provided to display the critical dimensions of the part based on the current viewing angle. A representative example of the sizing characteristics of the present invention is provided below with reference to FIGS. 32-36.
[0216]
As shown in FIG. 28, the solid view window is a Windows based application, so multiple windows or partial views of the part are provided. The multiple-view windows include an enlarged view that provides a single, very close-up view within the window, and a bird's-eye view that provides a very far view of the part in a single window. The partial view provides a partial view of the object selected by the user. In order to control the various observation functions, a joystick interface is provided in the server module 32 and the station module in each of the locations 10, 12, 14,. Operations in combination with the operation of only the joystick and / or predetermined keys on the keyboard (eg, shift keys or control keys) are performed by the user to perform various functions such as rotation and panning and zooming. Further, the displayed fabric of the solid diagram of the part is selected to simulate the material specified for the part in the database. To this end, a material dough library is provided having a dough library of materials such as steel, stainless steel, aluminum and the like. The stored material dough library is accessed and applied by the operator when a solid view exists. Accordingly, the surface of the displayed part more closely simulates the actual texture of the sheet metal part.
[0217]
The wireframe diagram mode provides a windows-based display of the wireframe diagram of the sheet metal part. An example of a wireframe window is shown in FIG. The function of the keys to provide 3D spatial navigation and 3D dimensioning in the wireframe is similar to that described above with respect to the solid view. For example, functions such as rotation, zooming, panning and selection of standard drawings are provided. Automatic dimensioning, multiple view windows and cross section options are also provided in the wireframe view mode. In addition, a joystick and / or keyboard interface is provided to allow the user to select and activate the various viewing functions.
[0218]
The two-dimensional plan view mode displays a developed two-dimensional plan view of the part in wire frame display. An example of a two-dimensional plan view window is shown in FIG. This two-dimensional plan view mode has a plurality of viewing functions to allow the user to change or modify the view in the window. For example, zooming and panning functions are provided to allow the user to selectively zoom and pan the two-dimensional planar wireframe diagram. In addition, sizing and multiple window viewing functions are provided in a manner similar to that described above with respect to the solid view mode. A joystick and / or keyboard interface is provided to allow the user to pan, zoom and control other viewing functions. The special molding part or shape provided in the part is displayed as the molding or shape for the outermost boundary of the molding region together with an indication or description of the special molding part.
[0219]
An orthographic window as illustrated in FIG. 31 is also provided as part of the bending model viewer. The orthographic mode displays a plan view, a front view, a right view, and an isometric projection diagram in wire frame display. A hidden line option is provided to obscure the blocked line based on the viewing angle. This hidden line option is used to simplify the windows in each figure. Various viewing functions are also provided in the orthographic view mode, allowing the user to selectively manipulate and change the current view in the window. For example, zooming and panning functions are provided along with sizing and multiple window viewing functions. As described above, a multiple window observation function is provided to allow the user to selectively display an enlarged view and / or a bird's eye view of the orthographic view in the multiple window. A joystick and / or keyboard interface is provided at each of the plurality of locations to allow a user to selectively activate and operate each of the plurality of viewing functions in the orthographic mode.
[0220]
In addition to displaying each of the various graphical displays described above, the bending model viewer observation class is implemented with other features. For example, the bending model viewer includes and maintains a selection set for indicating a plurality of items or entities in the current diagram that have been selected and highlighted by an operator. According to one aspect of the present invention, the operator can modify the data associated with the selected item or perform a predetermined operation on those items of the part to display the surface and bend line of the displayed part. And other features can be selected. For example, the operator can select a surface of the displayed part and change the dimension data along the width or length of the surface. The operator can also modify various bend data associated with each bend line, such as bend angle or V-width.
[0221]
The bend model viewer maintains a list of entities or items (eg, faces, bend lines, faces or bend line edges, etc.) selected by the user. The observer updates the list. Therefore, the current item currently selected by the operator is always held in the selection list. Other parts of the software in the present invention recall the drawing class of the current list of selected entities when performing or performing different procedures (eg manual dimensioning, etc.).
[0222]
Furthermore, the bending model viewer provides an observability function. It provides observability information and coordinate information based on the currently displayed diagram. As will be described more fully below, the observability function provides information about whether a particular part or entity of the part is currently observable on the screen and the screen entity is currently Provides coordinate information about the location. The bend model viewer's observability function is invoked by the dimensioning characteristics of the present invention to determine which part of the part is currently observable on the screen. Therefore, only the dimension information of the parts that can be observed on the screen is displayed to the observer. A more detailed description of the sizing and observability features of the present invention is provided below. Further exemplary code for performing the bend model viewer observability function is provided in Appendix J attached hereto.
[0223]
With reference to FIGS. 32-36, an example of dimensioning characteristics according to one aspect of the present invention will be described. As described above, each of the observation modes includes a dimensioning function that automatically displays the dimensions of the part based on the current viewing direction. An automatic dimensioning function is provided so that flange or bend line dimensions that are not visible at the current viewing angle are not displayed to the user. When the automatic dimensioning function or mode is activated, only the observable dimensions of the part are displayed based on the current viewing angle. Furthermore, in the automatic dimensioning mode, only predetermined dimensions (ie dimensions that are important for the bending operation) are displayed based on the current viewing angle state. A manual dimensioning mode is also provided to allow the user to selectively indicate which dimensions should be displayed. In this manual dimensioning mode, only the dimension items selected by the user are displayed based on the current viewing angle of the part. In either dimensioning mode, the displayed dimension items are erased or removed from the window display when the part is zoomed or panned.
[0224]
FIG. 32 illustrates examples of various dimension items displayed in the automatic dimensioning mode. The dimension items displayed in the automatic dimensioning mode are items important for the bending operation (for example, flange length, bend line length, bend angle, etc.), such as the size of punched holes or openings. It is not an extra dimension. The displayed dimensions include, for example, the width, depth, and height of the sheet metal part and the flange length. Further, the bend line length L, bend angle A, inner radius R and bend reduction D of each bend line are displayed alone or together in one window or in a group information box. As described above, only the dimension items that can be observed based on the current observation angle are displayed. Further, when the operator rotates, zooms, or pans to change the viewing angle of the part, all dimensions are erased or removed from the display, and those dimensions are displayed again when each operation is completed. The size and orientation of the display information (arbitrary text or reference arrow) is always scaled relative to the screen size, not the current zoom ratio or viewing angle. However, to improve the readability of the dimension information, the color, style, weight and / or font of the dimension information can be configured so that the user can change them. As a result, the operator or designer can highlight important dimensions in the part by selecting a special color, font size, etc. of the dimension information. For example, the size text color, size or font or size reference, line or arrow color, line weight or style may be highlighted or selectively changed to indicate important dimensions in the part. The operator also colors, fills, or styles the window information box, colors specific bend lines, or highlights other important dimensions in the part.
[0225]
Various processes or operations are utilized to implement the dimensioning characteristics of the present invention. Furthermore, as described above, the bending model viewer has an observability function that provides observability information for the dimensioning characteristics of the present invention. These functions or characteristics are executed by software in each of the server module 32 and / or the station module located in the whole factory, for example. Representative code for implementing the automatic dimensioning characteristics of the present invention is provided in Appendix FI. In addition, Appendix J provides sample code for the bend model viewer observability feature. The code in these appendices is written in the C ++ programming language and includes comments to facilitate understanding of the logical flow of procedures and operations performed there.
[0226]
The logical flow of dimensioning characteristics of the present invention is generally divided into three stages. In the first stage, the bending model geometry and topology data of the part is accessed from the database 30 and used to calculate all dimensions of the part and all aspects in which those dimensions can be displayed. For each bend line and face of the part, all the furthest points at which data can be displayed are calculated, and for these points all the ways in which dimension lines or arrows can be displayed are calculated. Certain heuristics are applied in determining where the dimensional data or other information can be displayed. For example, as a general rule, it is determined that all information is displayed only outside the part. Such heuristics are applied to provide a more meaningful and less crowded display of information to the viewer.
[0227]
The first stage described above is performed whenever the sizing feature of the present invention is activated by the operator. Alternatively, the first stage calculation is performed only when the part is first observed by an operator. In such cases, the calculated data is stored in memory for subsequent use and is changed when the dimensions of the part or other geometric data are modified or changed by the user. Furthermore, all calculations in the first stage are performed on the part geometry, not on the drawing screen. Therefore, the data can be used again regardless of the current drawing or whenever the drawing is changed.
[0228]
The second stage of the automatic dimensioning feature of the present invention is always performed when the drawing of the part is updated. The main purpose of this second stage is to screen the data generated during the first stage based on which entities of the part are observable in the modified diagram. In this second stage, all data that is not observable in the current diagram is screened, leaving only the data calculated in the first stage that is currently observable. A function call is made to the bending model viewer to determine which points or parts of the part are currently observable. As described above, the bending model viewer includes an observation function that maintains and provides information about the observable portion of the part based on the current diagram being displayed. Based on the orientation of the part, the bend model viewer can see which faces and bend lines of the part (and which edges or portions of those faces and bend lines) are observable, and what is hidden on the screen. To determine.
[0229]
As noted above, sample code for performing the observable function of the bending model viewer is provided in Appendix J. In order to determine which points or parts of the part are observable, the bend model viewer determines the current drawing orientation of the part and the current zoom plane or the proportion of the displayed part and maintain. The bending model viewer uses conventional perspective projection techniques (see, for example, Chapter 12 of Mortenson) to determine and maintain this current view orientation. In determining the observability of any point on the part, the observability function obtains the world coordinates of the point (ie the coordinates where the part is represented). Next, based on the current drawing orientation and zoom plane or ratio, for that point, the screen coordinates corresponding to the world coordinates (ie, pixel locations on the screen) are determined. Then, based on the screen coordinates, it is determined from the view of the viewing point of the screen whether any entity or part of the part is in front of the point of interest. The hidden characteristics of points on the part can also be determined based on whether other entities or parts of the part are assigned the same point on the screen as the point of interest. A function call to a graphic package or library (eg, open GL or renderware) is used to determine if one or more points of the part are assigned to points on the same screen. If something is assigned to a point on the same screen, based on the respective Z-buffer depth of those points, it is determined whether the point of the part is behind it. The Z buffer depth is used by graphic packages such as open GL or renderware, and defines the distance from the observation point or camera position to each point. The Z depth is determined by making a function call to the graphics package for points of the part of interest.
[0230]
The process of the bend model viewer observability function is performed whenever there is a prompt from the automatic dimensioning feature of the present invention to the bend model viewer. Such a process is therefore performed whenever the current view of the part being displayed by the operator is modified or changed. As noted above, the bend model viewer will maintain and update the current figure orientation and zoom ratio state whenever a change is made to the orientation of the displayed image, and therefore when required. Provide accurate observability information.
[0231]
After determining what data is observable, the automatic dimensioning function will determine all possible methods and locations where the dimension data or other information can be displayed (eg, based on calculations in the first step). decide. A group of heuristics is applied to select the best way to display the data from all possible ways in which the data can be displayed. For example, the first heuristic requires that an area on the screen that is closer to the observer's viewing point is preferred. The second heuristic specifies that the data should be displayed in an area that is closer to the area where the distance between two possible points for defining the dimension is minimal. Other heuristics are also applied based on the relative position of other dimensional data or other information to avoid overlap or congestion on the screen.
[0232]
After determining the optimal area for displaying information about the observable part of the part and the observable area, the third stage of the automatic dimensioning function draws various information on the display screen. To be executed. For example, dimensional information is displayed on the screen for each of the observable dimensions of the part based on the selection of an area for displaying the information. Further, based on which bend lines are observable, bend line information is also displayed in an information box (eg, that shown in FIG. 32) in an area of the screen that does not overlap with other part information. The dimensions of the part, including the width, height, and depth of the part, also do not overlap or interfere with a given location on the screen (eg, lower right of the part) or other information closest to the part. It is displayed at the position where it is not.
[0233]
Figures 33-36 illustrate various methods and definitions used in displaying dimension items in the dimensioning mode. In particular, FIGS. 33 (a) -33 (b) and 33 (c) illustrate how the flange dimensions are defined for a variety of different parts. According to one aspect of the invention, the flange length is defined as the furthest point on the flange from each bend line. If the furthest point of the flange does not exist at the longest end of the flange parallel to the bend line, the longest flange is added and displayed in the dimensioning mode. As a non-limiting example, FIGS. 34 (a) and 34 (b) illustrate the addition of auxiliary flange lengths for two different types of parts. When the thickness of the part is displayed, the flange length is displayed as outside the outer dimension. For example, FIGS. 35 (a), 35 (b) and 35 (c) illustrate the manner in which the flange length is indicated for various parts displayed with thickness. In addition, for parts with sharp bends, the flange length is displayed in various ways. For example, as shown in FIG. 36 (a), the flange length is displayed based on a tangential dimension definition, where the flange length is measured from a tangent extending from the acute bend. Alternatively, in order to define the flange length based on the point defined by the intersection of two straight lines extended from the two sides of the acute bending angle, a cross dimension method such as that shown in FIG. Is used. An operator may be allowed to select between the tangent dimension or cross dimension method to display the flange length and / or a specific dimension method (eg, tangential dimension method) is provided as a default setting. .
[0234]
To facilitate the generation of bending code sequences, a graphical user interface with various display functions is provided to assist the operator in generating bending plans. FIGS. 37-44 illustrate various procedures and operations performed to generate a bend code sequence by use of a graphical user interface according to another aspect of the invention. Typically, the initial bend model data and other work information is generated by the design programmer by entering important geometric and manufacturing data at the server module 32. The resulting bending model file is then stored in the database 30. Before a sheet metal part is manufactured, the bending operator needs to generate a bending sequence to perform the desired bending operation. The bending operator must determine what type of tool is needed and define the tool attachment for the bending machine. This bending plan generation process is assisted and more efficient by the use of a graphical user interface and by the various teachings of the present invention.
[0235]
To generate the bending plan, for example, a bending operator at bending station 18 accesses and downloads the bending model and other work information from the database 30. The bend model for the relevant part is transferred or transferred to the station module on the factory floor at the bending station 18 via the communication network 26. This process is generally shown in step S220 of FIG. Thereafter, in step S224, the bending operator checks the shape and dimensions of the part using the bending model viewer. Here, the bending operator selectively zooms and pans the various 2D and 3D views of the part on a display screen positioned at the bending station. By activating the automatic dimensioning feature of the present invention, the bending operator also observes the critical bending dimensions of the part to perform the bending operation.
[0236]
Once the operator understands the shape and dimensions of the part, the bending operator begins generating the bending plan by selecting and displaying a bending order input window in step S228. The bend order input window provides a graphical user interface to assist the bend operator to create, modify and delete bend orders and allows the operator to set various manufacturing parameters for each step in the bend order. (E.g., back gauge position, tool, NC data, etc.) can be specified and entered. The bending order input window includes a two-dimensional plan view image of the part displayed on a part of the screen (for example, the center of the screen or the left side of the screen). The two-dimensional plan view image includes various features of the unfolded part, including flanges, holes, and openings in the part. When the bending operator selects and indicates the plurality of bend lines and the bend order for each bend line, a solid 2D or 3D image of the intermediate part shape at each bend stage appears, for example as shown in FIG. As such, they are provided to a portion of the screen, such as the right edge of the screen. The images of the intermediate part shapes are displayed in an order corresponding to the entered bending order and are displayed simultaneously on the screen with the two-dimensional plan view of the part (as shown in the example of FIG. 38) or as a separate screen display. Are displayed separately.
[0237]
Further, as each bend line is selected, the bend line is emphasized, and as shown in FIG. 39 (a) as an example, the bend sequence number and the insertion direction (represented by an arrow, for example) are above the bend line. Or it is displayed nearby. The bend line number for each bend line is automatically set based on the order in which it is selected, or manually entered by the operator after each bend line is selected. Other manufacturing information related to the bend line, such as bend angle, bend line length, and back gauge position, is also entered as each bend line is selected and highlighted, as shown by way of example in FIGS. / Or displayed on the screen. A dialog or information box is displayed on the screen, as shown in FIGS. 40 and 41, allowing the bending operator to select, enter or modify manufacturing information and other parameters associated with each bend line.
[0238]
The dialog or information box allows the bending operator to highlight or select a bend line. Hot function keys or fast switch keys are displayed in the bend sequence entry window to allow the operator to select or enter tool stand and monitor and modify NC data. For example, the bending operator selects a tool function key, and switches from the bending order input window to a tool input display screen or a plurality of display screens for inputting tool stand information. An NC function control key (eg NC9EX) is also provided to allow the operator to monitor and / or modify NC data related to the bending operation to be performed. In addition, as shown in FIGS. 40 and 41, other function keys and controls are provided in connection with defining and / or modifying bend lines and associated manufacturing information. For example, a ZOOM ALL key is provided for zooming in and out of the two-dimensional plan view image. The back gauge key is provided for selecting or setting the position of the back gauge. Grouping and ungrouping control keys are displayed to enable or control multiple bend lines that are bent together. In addition, control keys (eg, ama bending) are provided to define special bending operations. Other function keys are also displayed and provided for the operator to select, modify and / or delete the bending order (eg, REMOVE CLEAR FWD, CLEAR ALL, OK, CANCEL). This bending order input window allows the bending operator to efficiently monitor and modify the bending order and various manufacturing information.
[0239]
According to yet another aspect of the invention, a cross-sectional view of the part and / or a bending simulation of the part is displayed on the screen for each bending step in the bending sequence (see, eg, FIG. 41). The cross-sectional view and bending simulation are selectively displayed on the screen, or displayed when each bend line is selected by a bending operator. The cross-sectional view and the bending simulation include, for example, representations of vertical bending tools (eg punch and die) or backgauge positions / settings that are displayed on the screen simultaneously with the two-dimensional plan view image or on different screen displays. It is displayed separately. The back gauge position is automatically determined based on the topology of the part, or is set or corrected by an operator. If tool stand information for the bend line has not been entered or is set by a bend operator, the cross-sectional view and / or bend simulation is not displayed on the screen or represents and calculates the intermediate part shape. Only the backgauge positions that are defined or defined are displayed. The bending simulation includes a displayed simulation of the desired inversion of the part, manipulation and orientation of the part and / or bending of the part made at each bend line. It is also possible to simultaneously display a cross-sectional view of the part before the bending process and a cross-sectional view of the part after the bending process together with a two-dimensional plan view image of the part on the display screen (for example, FIG. See 41). These cross-sectional views are provided on the right side of the screen and include representations of the up and down bending tool and back gauge for each bending step in the bending sequence. In addition, zoom control or function keys (ZOOM IN and ZOOM OUT) are displayed to allow the operator to control the zoom ratio or orientation in relation to the pre-bend and post-bend cross-sectional views. It is disclosed in Japanese public notice gazette 7-1212418 (issued on December 15, 1995 under the name of Niwa) and Japanese publication gazette 1-309728 (issued on December 14, 1989 under the name of Nagasawa). Similar techniques and procedures are used to display a cross-sectional view or bending simulation of the part. The disclosure of said document is hereby incorporated by reference in its entirety.
[0240]
According to one aspect of the present invention, there is software or program logic for automatically determining the insertion direction for the bend by calculating the short or small side of the part relative to the selected bend line. Provided. Based on the features of this invention, each bend line is used to divide the part into two sides. The insertion direction is determined for each bend line based on the side of the part having a smaller or shorter length (eg, the dimension of the side perpendicular to the bend line) or on the side having a smaller overall area. The If the operator is not satisfied with the selected insertion direction, the operator reverses the insertion direction as shown in FIG. The operator changes or reverses the insertion direction, for example, by clicking a mouse or keypad selection button when the bend line is highlighted. The insertion direction information includes an arrow and / or text for indicating the insertion direction of the flange defined by the bend line in order to bend the part by a bending device or a mechanical device. The insertion direction information is displayed on or near the bend line (eg, see FIGS. 39 (a) and 39 (b)) or on or near the end of the associated flange (eg, see FIG. 40). Further, the insertion direction information is displayed when each bending line is selected or selectively displayed based on an input received from a joystick device, a mouse device, or a keyboard device.
[0241]
Thus, through the use of a graphical user interface, the bending operator can view various intermediate shapes and final part shapes based on the selected bending order entered by the operator. Again, the operator can enter and select data on the screen through a suitable input device such as a joystick interface, mouse interface and / or keyboard interface. If the bending operator is not satisfied with the proposed bending order, the bending operator edits the bending order before finalizing the bending plan as generally shown in step S232. This bending order editing is performed in various ways and methods. In particular, according to one aspect of the present invention, drag and drop editing characteristics are provided and the operator simply selects one of the intermediate part shape icons or displays provided on the left or right side of the screen as shown in FIG. And edit the selected bend order by dropping it into the desired position in the order. Thereafter, the various intermediate part shapes on the screen are modified based on a bending operator modification to the bending order to indicate an intermediate bending step based on the revised bending order. Furthermore, the bending order number on the two-dimensional plan view image is revised based on the bending operator dragging and dropping the bending order.
[0242]
After the bending order is determined, the operator determines what type of tool stand should be used by selecting a tool from a library of stored tool set data, as shown in step S236. . The associated tool stand information is displayed to the factory floor bending operator and a display menu is provided to graphically assist the bending operator in selecting a tool stand from the library. Once a particular tool is selected from the library, data associated with the tool is displayed on the screen. FIG. 43 illustrates examples of various display menus and data tables that are graphically displayed to the bending operator for manual tool selection. In the example of FIG. 43, a continuous display menu or screen display is graphically displayed to assist the bending operator in retrieving a specific tool from the tool library. A continuously displayed screen display is displayed continuously on the display device (eg in an overlapping or cascaded manner) or it is displayed individually, and the screen is displayed before the next subsequent screen display is displayed. Cleared. Once a specific tool is selected, specific data for that tool is provided in a table and displayed to the operator. Data in the tool library is pre-defined and enabled (eg, in the database 30) during the initial setup procedure of the software.
[0243]
The manual tool selection characteristics of the present invention allow the operator to select tool types and the tool shape for each type. For example, various tool types are selected including punches, dies, die holders, and die rails. Each type consists of multiple shapes, and there are multiple tools of different sizes and dimensions for each shape. To select one tool, the user first identifies one tool type by selecting one icon from the displayed tool type icons as shown in FIG. The user is then provided with a different shaped menu available for the selected tool. After analyzing the tool shape, the user selects the tool shape by selecting one shape icon from the displayed shape icons for the selected tool (eg, gooseneck shape punch is selected in FIG. 43). Finally, the user selects the appropriate size and dimensions for the selected tool shape. As further shown in FIG. 43, a table is displayed to the user to indicate the different sizes and dimensions of the tools available for the selected tool shape. By selecting one item from this table, the selected tool is displayed as an icon and replaced with a general tool type icon, and the selection of the tool is confirmed.
[0244]
In step S240, the bending operator then sets various tool stages (tool stages) in the press brake with the aid of the graphic interface. FIG. 44 illustrates an exemplary tool setup window provided to the bending operator to facilitate the definition of the tool setup used in the bending plan. As shown by way of example in FIG. 44, various punch, die and rail data are displayed in the tool setup window. Tool and die information for the sheet metal part is input by an operator. A joystick is provided to the bending operator's station module to allow the bending operator to indicate tool position and to select a tool and list from a list of available tools and dies. In the tool setup window, the left side of the screen represents the cross-sectional shape of the current tool setup, and the right side of the screen displays the current setup position on the press brake. The current setup location is highlighted or shaded as shown in FIG.
[0245]
Finally, when the operator is satisfied with the bending order, bending plan information including the tool stand and bending sequence is stored with the bending model in the database 30 as generally shown in step S242 in FIG. An actual test of the bending order is performed with a press brake to confirm the bending order selected by the bending operator. If necessary, further modifications to the tool stand definition or bending sequence are performed by an operator or designer in the station module.
[0246]
Various other features of the invention are provided to assist the bending operator in generating the bending plan. For example, according to another aspect of the invention, a tool stand expert is provided to automatically suggest tool stand and bending order based on the part shape and other information stored in the bending model for the bending operator. Give it. Suggestions from the tooling expert are revised by the bending operator after analysis of the suggestions. In addition, a more complex tooling expert system is provided that provides tooling suggestions for more complex operations based on the shape of the part in the bending file and tool shape analysis to check for potential collisions and interference. Suggest bending order. Such expert systems are used and implemented manually or by robotic assisted bending machinery. By way of non-limiting example, the present invention relates to US patent application Ser. No. 08-386.369 entitled “Intelligent System for Generating and Executing Sheet Metal Bending Plans” by name such as David A Bone, and David A Bone, etc. In accordance with the features and teachings disclosed in US patent application Ser. No. 08-338.115 entitled “Robot Window Planning / Control Method”. These disclosures are hereby incorporated by reference herein in their entirety. As noted above, a graphical user interface or various functions are provided to assist the bending operator in generating a bending plan for the sheet metal part. According to another aspect of the invention, additional features are further provided to assist in the design and manufacture of the part. As described more fully below, various multimedia functions, such as storing audio or visual information, may be implemented in the present invention for the bending operator in generating the bending plan or performing the bending sequence. Provide additional support. In addition, a collision check function is provided that automatically checks for potential interference and collisions between the tool and part at each intermediate bending stage. This collision check function is provided to replace the time-consuming manual check of the tool shape and the interval between parts. The manual check is usually performed by a bending operator when generating a bending plan. These functions and others will now be described with reference to the accompanying drawings.
[0247]
According to one aspect of the invention, a method is provided for storing audio and video information along with the bending model data. Various audio and video information is recorded at the factory floor and provides special commands related to, for example, the manipulation and bending of sheet metal parts. For this purpose, a CCD camera or a digital camera is provided in each of the station modules at various locations 10, 12, 14,. Other devices, such as a video camera with an audio microphone, are provided in the station module to allow an operator or user to record audio or video information. The various recording devices are connected to a station module computer on the factory floor. As a non-limiting example, an Intel PROSHARE personal conference CCD camera (available from Intel Corporation) is used to record audio and video information. Other commercially available CCD cameras or digital cameras are also used to record such information.
[0248]
Various audio and video information stored with the bending model data can be accessed and read by the user by various methods and procedures. For example, menu options are displayed by the station module to reproduce stored audio and video information. Further in accordance with a preferred embodiment of the present invention, the operator selects and generates icons to be displayed in the observation window, thereby allowing stored audio and video information to be displayed on various display screens and parts. Has the ability to accompany it. This function is performed by software and object-oriented program technology. Thereby, the icon object is generated and stored in the bending model data structure. This icon object is used to read audio and video information associated with the memory based on a certain condition (for example, selection of an icon by an operator by a double click of the mouse or a selection instruction by using a joystick or other input means). Including procedures. The icon feature of the present invention allows the operator to associate different audio and video messages or information with different parts of the sheet metal part and any display. By incorporating this icon into the representation of the part, the icon is configured to zoom, rotate and translate with the display of the 2D and / or 3D model of the part as the screen changes on the screen. .
[0249]
FIG. 45 illustrates an example of attaching audio and video information through the use of icons attached to the three-dimensional solid model of the part. After the user records the audio and video information, the operator pastes an icon at an arbitrary position in the 3D model window. When the icon is next selected by an operator or user, the stored audio and video information is played back and displayed in the window, and a special command or message relating to a part or area of the part where the icon is located I will provide a. Other information, such as simulation or recording of the bending motion, is associated with the part by placing icons near the various bend lines of the part. Video information related to the bending motion is then played back to the user the next time the icon is selected.
[0250]
The operator or user records audio and video information, or simply records one audio message or still or motion video signal, which is selectively played back to the user. The icon attached to the window display graphically indicates the type of information stored (eg, a microphone icon is displayed to indicate that audio information is stored or video information is Display monitor icon is displayed to indicate storage). A special icon is provided to indicate that audio and video information is associated with the icon (eg, an “A / V” symbol or a video camera icon that includes a microphone). A list of icons is provided and displayed, allowing the user to select from a variety of icons when attaching audio and / or video information to the screen display or image.
[0251]
FIG. 46 illustrates another example of a display window incorporating an icon for reading stored audio and video information. The display window displayed in FIG. 46 is associated with a tool setup screen image, such as that described above with reference to FIG. In the example of FIG. 46, audio information is stored and read by a microphone icon. Separate video information is stored and read by pasting a video icon on the display window. The audio and video information relates to special commands or information related to tool setup or operation. Furthermore, regardless of the type of window display currently activated, the operator can paste as many icons as necessary in various areas of the window display to later retrieve different audio and video information.
[0252]
In accordance with another aspect of the present invention, image editing window characteristics are provided to facilitate an operator to select stored images and apply them to different screens. The image editing window characteristics are provided as a window-based application, which is accessed either in the server module 32 or a station module provided through a manufacturing facility, for example. FIG. 47 illustrates an example of an image editing (image editing) window executed in accordance with the teachings of the present invention. The image displayed in the image editing window includes a picture photographed by a digital camera or a CAD coder. The images displayed on the screen are selectively selected by an operator (eg, with a mouse or other suitable data input means) and copied to another screen, which is associated with a particular model diagram of the part. The operator then pastes the image or icon into the model window (eg, the 3D solid model window of the part as shown above in connection with FIG. 46). 45, 46 and 47 are photographic reproductions of actual screen images. The actual image is itself more distinct depending on the camera or screen resolution used. The image includes, for example, a static or motion video image of a bending operator that discusses or illustrates a special operation or other command associated with the bending operation, or is a video image of a sheet metal bending operation. In other words, the actual image that appears to be useful is taken and displayed later. Accordingly, the actual images shown in FIGS. 45-47 are for illustrative purposes only. 48 and 49, an example of the collision check function of the present invention is provided. In accordance with one aspect of the present invention, a collision check function is provided that allows the user to check for potential collisions between the part and the punch tool by using a graphical user interface. The collision check function is a Windows based application that is accessed at any station module or location in the manufacturing facility. The automatic collision check function of the present invention is used by the bending operator in place of the traditional and cumbersome manual shape checking that is normally performed when generating the bending plan.
[0253]
Traditionally, when generating a bending plan for a sheet metal part, the bending operator first determines the bending order of the part. The bending order determines the order or manner in which the sheet metal parts are bent during manufacture. After the bending order is determined, the bending operator selects and defines the tool used to perform each of the bending operations. In this process, the selected tool shape and the intermediate shape of the part ensure that there is no interference or collision between the tool and the part when performing each of the bending steps. Is analyzed. If a collision or interference is detected, the selected tool type (or bending order as required) allows the bending operation to be performed without causing interference or collision between the tool and the sheet metal part. Must be modified as follows.
[0254]
Bend operators have traditionally relied on manual methods to analyze the clearance between the shape of the tool and the bent portion or shape of the sheet metal element in detecting potential collisions or interference. . Typically, a tool shape model is constructed and used by a bending operator. The tool shape model is manually matched to or placed on an engineering or technical drawing of various intermediate shapes of sheet metal (having dimensions of the same scale as the tool shape model). By fitting and fitting this tool shape model to the drawing of the part, the bending operator can determine whether there is sufficient space or clearance between the tool and the part in each bending process. . However, this process tends to be cumbersome and time consuming.
[0255]
The present invention overcomes the disadvantages of such traditional methods by providing an automatic interference check function. The interference check function of the present invention is performed via a graphical user interface and allows the bending operator to check for collisions at each intermediate step in a predetermined bending sequence. Figures 48 and 49 illustrate an example of a collision check function performed via a graphical user interface. When activated, the collision check function automatically checks for collisions between the intermediate shapes of the parts in the bending order and the punch tool or tools defined for that order. The intermediate shape is displayed on the screen (see, eg, FIGS. 48 and 49), and when a collision is found, the process of detecting the collision is highlighted on the screen. In addition, other display suggestions such as text are provided to indicate the number of collisions detected. 48 and 49, the collision information is provided in the upper right area of the display window. Further, the type of punch tool or the plurality of tools whose collision has been checked is displayed or indicated in the upper left area of the display window.
[0256]
When a collision is detected for a punch tool selected by the operator, the intermediate shape or stage at which the collision is detected is highlighted on the screen. In this case, the operator can also select another punch tool for that particular bending stage and the collision check function is performed again to determine if a collision will occur for the second selection of the punch tool. . The operator can select a punch tool for each bend and check the collision by the collision check function. Drag and drop editing allows the operator to change the bend order displayed in the window display by dragging an intermediate bend shape and dropping it to the desired position within the proposed bend order. It may be provided to allow. The bend order is modified based on the drag and drop edits made by the operator in a manner similar to that described above with reference to FIG.
[0257]
Various procedures and operations are used to implement the collision check function of the present invention. For example, to detect potential collisions, the selected tool geometry and the part geometry at the intermediate shape are accessed. Geometric data related to the part in each intermediate process is generated based on the bending order, part dimensions and topology data. Each flange of the part is bent according to bending data (for example, bending angle, bending line position, reduction amount, etc.) to display the part at each intermediate stage in the bending order. The bending process and the reduction amount compensation characteristic of the present invention are applied when generating geometric data for the part at each intermediate stage. Due to the geometry of the tool and part, the tool and part are orientated relative to each other by placing the tip of the tool on the bend line of the part in each of the bending stages. Collisions are detected by analyzing the geometric data and the boundary between the tool and the part and determining whether there are common or overlapping points in the tool and part. When a collision is detected in a particular bending process, that process is highlighted on the screen to indicate the detection of the collision to the user. Tool data used to detect a collision is actively retrieved from the tool geometry library based on tool selection made by the user. The recalculation of the collision at any intermediate bending step is based on a different tool shape or bend sequence modification. By providing such functionality and displaying such information using a graphical user interface as described herein, the likelihood of a collision is more easily determined and corrected by the bending operator. The
[0258]
As described above, the joystick or mouse device allows the user to selectively activate and control various observation functions (for example, zoom, pan, rotation, etc.) when observing the displayed model of the sheet metal part. In order to achieve this, each of the station modules and their locations are provided through the manufacturing facility. The joystick device is a joystick having multiple axes and has a selection or control button. The joystick is implemented through a variety of commercially available joystick devices, including a Microsoft Sidewinder joystick, and plugged into the game port of the computer at each station module and / or other location of the facility. The mouse is also software that supports any commercially available mouse, such as Windows 95 or Windows NT, and any commercially available mouse that plugs into a computer game port or mouse port at each facility location. Executed by the device.
[0259]
As a non-limiting example, FIGS. 50-55 illustrate various aspects of a system for manipulating a three-dimensional geometry and displaying the part using a joystick device or a mouse device. The three-dimensional navigation system of the present invention allows the user to control various observation functions such as rotation, zooming and panning. According to one aspect of the invention, the system also uses a dynamic rotation axis that is calculated based on the current zoom image when observing the three-dimensional model. According to this aspect, the center of rotation is dynamically changed and calculated based on the current figure and zoom ratio or factor, so the zoomed area of the part is such that the part is at a high zoom ratio or factor, for example. When rotated, it does not disappear from the screen.
[0260]
According to one aspect of the invention, a three-dimensional operation and navigation system is provided in the station module and / or server module of the facility. The steps and operation of the three-dimensional navigation system are performed via software or programmed logic and using one of a wide range of programming languages and teachings. For example, the system is implemented using a high level programming language such as C ++ and using object oriented programming techniques. As a further non-limiting example, VISUAL C ++ is used. It is one version of the C ++ programming language provided by Microsoft Corporation for Windows-based applications. The observation functions (eg, zoom, rotation, pan, etc.) are executed as element functions of the observation class of the bending model viewer of the present invention described above (see, eg, FIG. 27 and the related disclosure above). Information regarding the current zoom factor and part position (eg, part position in 3D space) is also accessed from the bend model viewer to calculate the dynamic axis of rotation and provide the desired viewing function. The
[0261]
Various hardware components and interfaces are provided to implement the three-dimensional navigation system of the present invention. For example, software used for executing the system is provided or exists in the computer or personal computer of the station module and the server module. As discussed above, the computer or personal computer includes a graphics card such as a high resolution monitor and a display screen or terminal for displaying a three-dimensional display of sheet metal parts to the user. The computer or personal computer also includes a mouse or game port adapter for connecting and interfacing with the mouse or joystick device. Commercially available software is also provided to interpret command signals received by the mouse or game adapter card from a mouse or joystick device operated by the user.
[0262]
FIGS. 50a and 50b illustrate examples of rotation functions performed by the multi-axis joystick 112 to rotate, for example, a simple three-dimensional box-shaped part. As described above, the joystick is provided and connected to a computer or device provided in the station module and / or server module provided through the equipment. As shown in FIGS. 50a and 50b, the rotation of the part is performed by moving the joystick 112 back and forth and left and right. The direction or direction of the rotation axis is set based on the movement of the joystick 112 (or mouse). For example, moving the joystick 112 back and forth results in rotating the part clockwise or counterclockwise about a rotation axis defined along the X coordinate axis (see, eg, FIG. 50a). Further, moving the joystick 112 to the left or right results in rotating the part clockwise or counterclockwise about a rotation axis defined along the Y coordinate axis (see, eg, FIG. 50b).
[0263]
When the zoom ratio or factor of the current figure is low and a full view of the part is provided on the screen, the axis of rotation is defined to pass through the geometric center or centroid of the part. As described above, the zoom factor and the observability of the part on the screen are determined based on the observability function provided by the bending model viewer of the present invention. When it is determined that the entire part is displayed on the screen (as in FIGS. 50a and 50b), a coordinate geometry technique is used to define the rotation axis and set the rotation axis to the geometric center of the part. Is used. The rotation of the part is then performed based on the movement defined by the user of the joystick device and via the rotating element observation function of the bending model viewer of the present invention. However, if only part of the object is displayed on the screen and some parts of the part are not visible (eg when a high zoom factor or ratio is selected), the axis of rotation is the geometric center of the part Or it should not be maintained in the centroid. That is because the zoomed part of the part disappears from the screen during rotation. Indeed, according to the present invention, when the zoom ratio is increased, the axis of rotation is dynamically recalculated and passes the coordinates of the point closest to the observation point (or camera field of view) at the center of the screen. By dynamically recalculating the axis of rotation based on the change in the zoom factor, the part rotates around an axis where an observable part of the part does not protrude from the screen during rotation. Is done.
[0264]
In order to zoom and pan the three-dimensional model, additional control buttons are provided on a keypad provided separately from or in conjunction with the joystick or mouse device. For example, by pressing the zoom button 114 and moving the joystick 112 back and forth, the part is zoomed in or out at a predetermined rate as shown in FIG. As described above, the axis of rotation is recalculated within each zoom window, allowing the user to observe the zoomed portion of the part as it is rotated. Further, the panning of the three-dimensional shape is controlled by the user by pressing or activating the pan button 116 and moving the joystick 112 as shown in FIG. As with the zoom button 114, the pan button 116 is provided on a digital input pad provided separately or with the joystick or mouse device at each of the various locations of the equipment.
[0265]
In accordance with an exemplary embodiment of the present invention, various steps and operations provided to perform the three-dimensional navigation and operation are described below with reference to FIGS. 53-55. As indicated above, the necessary steps and operations of the three-dimensional navigation system are performed through a combination of software or program logic and hardware components and interfaces. Input signals from a user controlled device, such as a joystick or mouse device, are interpreted to determine the amount of movement and reorientation desired. According to this invention, the rotation axis of the displayed part is dynamically calculated based on the current screen and zoom factor to prevent the zoomed area of the part from disappearing from the screen during rotation. The
[0266]
When updating the current screen of the displayed part, a signal from the user is received based on the operation of the joystick or mouse device, as generally shown in step S301 of FIG. The combination of the movement of the joystick or mouse device in a specific direction and / or activation of a special control button by the user with a predetermined observation function (eg rotation, zoom, pan, etc.) and a predetermined direction of the displayed part A motion (eg, clockwise or counterclockwise, zoom in or zoom out, right or left, etc.) is caused, for example, as shown in FIGS. 50-52. The received signals are mapped to the movement of the cursor, whether they are from a joystick or a mouse device, and determine the amount of movement on the screen desired by the user. A mapping of the received signal if the user is not in one of the viewing function modes (eg if the user is selecting information on the screen or observing information in a dialog box or window) Is not required.
[0267]
As will be appreciated by those skilled in the art, the signals received from a normal joystick or mouse device are based on a coordinate or reference system different from that in screen space, so they are meaningful information regarding cursor movement on the screen. Must be translated to provide. Therefore, after receiving the input signal from the user, as shown in step S303, the received signal is mapped to the cursor movement before calculating the rotation axis and updating the current view of the displayed part.
[0268]
Different methods and processes are used to translate and map input signals from user controlled devices into cursor movements in screen space. Traditionally, movement of the mouse device has been translated and mapped into cursor movement by commercially available software. For example, Windows 95 and Windows NT include software routines for translating mouse movements into cursor movements. Thus, movement of the mouse device is mapped to cursor movement by such commercially available software. However, if the user is provided with a joystick interface, the joystick movement must also be translated and mapped into a cursor movement to provide useful information. Various methods and techniques are used to map joystick movement in the joystick virtual space to cursor movement in screen space. For example, joystick movement signals are first processed and translated into mouse movements before being finally mapped to cursor movements. Alternatively, the joystick signal is directly mapped to cursor movement as a function of the ratio of the screen space size to the joystick virtual space size.
[0269]
FIG. 54 illustrates an example of mapping of joystick motion to cursor motion in screen space according to one aspect of the present invention. As indicated above, the joystick device includes its own virtual coordinate system or space 218. The joystick virtual space 218 includes an origin J1 corresponding to a position where the joystick is present at the center or neutral position (that is, the position where the joystick does not move). When the joystick moves to a new position (eg, the current position J2 as shown in FIG. 54), the joystick device generates a signal indicating the new or current position in the joystick virtual space. Since the joystick virtual space 218 is often larger (in the sense of pixels) than the screen space 212, the virtual coordinates and movement of the joystick is determined by the screen coordinates to determine the desired cursor movement and thus the movement of the part on the screen. Must be translated into
[0270]
Various methods and processes are used to map and translate the virtual coordinate movement of the joystick into a screen coordinate movement. For example, joystick motion is mapped to screen cursor motion based on the ratio of the screen space size to the joystick virtual space size. More specifically, when the observation function mode (eg, zoom, rotation, pan, etc.) is activated and the joystick device is operated by the user, the actual movement of the cursor from the previous point C1 to the current point C2 is as follows. It is determined by the following formula.
[0271]
Current point = previous point + (scale factor x V)
Here, “current point” is the current point C2 of the cursor, “previous point” is the previous point C1 of the cursor, and “scale factor” is the ratio of the screen size to the joystick virtual space size ( “V” is a vector representing the movement and direction of the joystick from the joystick origin J1 to the joystick current position J2. Therefore, in order to map the joystick movement to the cursor movement, a vector “V indicating the direction and movement of the joystick from the origin J1 to the current position J2 based on a signal received from the joystick device when the joystick device is operated by the user. "Is calculated first. After this vector “V” is calculated, the joystick motion is mapped to a cursor motion using the vector “V” quantity and the “scale factor” quantity in the equation. That is, the new or current position C2 of the cursor is multiplied by the vector “V” by the ratio of the screen size to the joystick space size (ie, the scale factor), and then the result of this calculation is multiplied by the previous cursor position C1. Calculated by adding together.
[0272]
Depending on the scale factor, it is necessary to increase or decrease the scale or rate of movement by a predetermined or user-selected adjustment factor. In such cases, and depending on user preference, the scale factor is multiplied by an adjustment factor when calculating the current position of the cursor to increase or decrease the scale percentage. For example, if the ratio of the screen size to the joystick space size gives a scale factor of 1/64, to give a more satisfactory relationship between the joystick movement and the movement ratio of the displayed part on the screen, It is desirable to increase the ratio of. As a non-limiting example, for a scale factor of 1/64, an adjustment factor of 3 is used when zooming or rotating the displayed part. Further, for the scale factor 1/64, the adjustment factor 6 is used when the displayed part is panned. Of course, the scaling ratio is modified based on the specific needs of the user, the adjustment factor is predetermined or the user can adjust or select the adjustment factor for correcting the scale ratio. Give options. Further, as shown in the case discussed above, the adjustment factor may be set to the same amount for each of a plurality of observation functions, or may be individually set to the same or different amounts for each of the observation functions. Also good.
[0273]
After the received signal is properly mapped and translated, the rotation axis of the part is dynamically calculated as generally shown in step S305 of FIG. Depending on the current view of the part, the rotation axis is the center of the part so that when the part is rotated, for example with a high zoom ratio or factor, the zoomed area of the part does not disappear from the screen. Through or other points. Based on the current zoom diagram, various methods and processes are used to dynamically recalculate the rotation axis of the part. In accordance with another aspect of the present invention, FIG. 55 illustrates a representative logic flow and sequence of processes and steps performed to calculate the axis of rotation whenever the drawing of the part is modified by a user.
[0274]
As shown in FIG. 55, the current zoom factor or ratio, the position of the part and the current figure are determined in steps S311 and S313. The zoom factor and orientation of the display part selected by the user allows the entire part to be viewed on the screen (ie, the full view) or only a portion of the part is viewable on the screen (ie, the partial view). ). Therefore, the current zoom factor and part orientation must be determined in order to properly set the rotation axis of the display part. Various methods and processes are used to determine the current view of the part. As described above, the observability feature comprises the bending model viewer of the present invention and maintains the current figure orientation and zoom ratio state whenever there is a change to the displayed image and Update. A function call is made to the bending model viewer to determine which points or parts of the part are currently observable. Whether or not all of the parts are displayed on the screen is determined by comparing the image volume with the boundary basic line size of the parts.
[0275]
If it is determined in step S315 that the entire view of the part is currently observable on the screen, the rotation axis is set to pass through the center of the part in step S317. When there is a general view, it is possible to set the rotation axis to pass through the center of the part. This is because the entire displayed part can be observed on the screen when rotated by the user. When all parts are observable on the screen, the axis of rotation is defined to take the geometric center or centroid of the part. Conventional coordinate geometry techniques are used to define and set the rotation axis to the geometric center of the part. Further, the direction of the rotation axis may be defined as a vector orthogonal to a vector from the previous cursor position to the current cursor position.
[0276]
If it is determined in step S315 that only a partial view of the part is currently observable on the screen, a portion of the displayed part will not disappear from the screen when the zoomed part is rotated by the user. To do this, the logic flow continues to steps S319-S325 to calculate the rotation axis. As described above, when a high zoom factor is selected by the user and only a part of the part is displayed on the screen, the rotation axis should not be set to pass through the geometric center of the part. This is because the zoomed part of the part displayed during rotation (zoomed up part) disappears from the screen. In order to prevent the displayed part of the part from disappearing or disappearing from the screen, the axis of rotation must pass through the coordinates of the point closest to the observation point (ie the camera) at the center of the screen. In such a case, the direction of the rotation axis may be defined as a vector orthogonal to the vector from the previous cursor position to the current cursor position.
[0277]
Accordingly, in step S319, the center of the screen is determined, and the object or part of the part at the center of the screen closest to the camera is selected. That is, the part of the display part located at the center of the screen and the part of the display part closest to the camera or the observation point of the user of the screen are taken out. If it is determined in step S321 that an object in the camera exists (eg, there is a solid portion of the part located in the center of the screen and closest to the camera), in step S325 the rotation axis is It is set to pass through the extracted point. As described above, the direction of the rotation axis may be defined as a vector orthogonal to the vector from the previous cursor position to the current cursor position.
[0278]
If it is determined in step S321 that there is no object in the camera (eg, the part is located in the center of the screen and includes a hole or opening closest to the camera), the logic flow continues to step S323. In step S323, the axis of rotation is defined to be at a Z coordinate (depth) that passes through the center of the screen (eg, the X and Y coordinates of the physical center of the screen) and is equal to the geometric center of the part. . Therefore, the rotation axis may be set so as to pass through the X, Y, and Z coordinates, and the direction of the rotation axis may be defined as a vector orthogonal to the vector from the previous cursor position to the current cursor position.
[0279]
Referring again to FIG. 53, after the dynamic rotation axis is determined, the selected observation function (eg, zoom, rotation, pan, etc.) is invoked at step S307. As described above, the various viewing functions of the 3D manipulation system are defined and implemented as elemental functions of the bending model viewer viewing class (see, eg, FIG. 27 and related disclosure above). In such a case, a function call is made to the bending model viewer based on the observation function selected by the user, and the current view of the part displayed in step S309 is updated. The current view and orientation of the part is updated based on the viewing function selected by the user and the mapping cursor movement received from the input device (mouse or joystick device) operated by the user. A graphic package such as open GL or renderware is provided to facilitate updating the current diagram provided to the user. The logical flows and processes performed in the exemplary flowcharts of FIGS. 53 and 55 are implemented by software and using a wide variety of programming languages and techniques. For example, object oriented programming techniques and C ++ are used to perform the process or operation. Representative code for implementing the three-dimensional operating system of the present invention is provided in Appendix L. Exemplary code is written in the C ++ programming language and includes various steps and operations for calculating the dynamic rotation axis. Comments are provided in the code of Appendix L to facilitate analysis of the logic and algorithms used therein.
[0280]
Although the above three-dimensional operating system has been described with respect to the use of joystick devices and control buttons, the system can also be implemented by other specific types of input means including a mouse or keyboard. Further in the above embodiment of FIGS. 51-52, boundaries are defined to limit zooming or panning of the object from the screen to infinity or vice versa. This is because continuous zooming or panning causes the system to fail or break.
[0281]
In addition, various other functions are performed in connection with the joystick interface. For example, movement in any of the observation functions is not performed unless the joystick is moved beyond a predetermined range or distance from the joystick center position. Requiring such a joystick movement threshold before the movement of the part is allowed may result in accidental movement of the displayed part based on inadvertent manipulation or pressing of the joystick from the center point. Preventing the occurrence of Other functions are also provided to improve the joystick interface and system interaction with the user. For example, based on a single operation of the joystick by the user, continuous or incremental (eg, step by step) movement in any one of the viewing functions (eg, zoom, rotate, pan, etc.) is provided. The choice of continuous or incremental movement is also provided based on the amount or time of joystick movement in a single direction. If necessary, the scale or rate of movement of the displayed part is increased based on the degree or time of joystick movement in any direction. The speed adjustment factor correction described above is also performed by allowing the user to manually enter a correction to the adjustment factor to increase or decrease the scale ratio.
[0282]
Various other functions and embodiments are implemented in the present invention to assist in the design and manufacture of parts in the factory. For example, a barcode system is implemented to track and access information about each customer order. A bar code having a predetermined reference number or work number is assigned to each part ordered by the customer. This bar code is used to access the database 30 and read work information. A barcode reader or scanner, such as a barcode-anything barcode SCAN CCD sensor from Zebra Technology VTI in Utah, Sandy, is provided at each location, and a barcode for a user to perform a predetermined work in the server module or station module. And important design and manufacturing information associated with that part stored in the database 30 can be accessed and retrieved. The bar code reader is inserted into the computer of each station module and / or server module. The barcode is formatted based on any normal barcode format. For example, UPS-A CODA BAR
CODE39 EAN / JAN-8 or PLESSEY. The resulting barcode number is then translated based on a look-up table and the corresponding work reference number and / or file name is detected to retrieve work information from the database. Alternatively, the work number is typed into or selected from instructions displayed at any station existing throughout the factory, and the work information is read and displayed at the user's location instantly. The ability to retrieve such information instantaneously is supported by the use of the communication network 26 and the storage of the design and information in a centrally located database such as the database 30.
[0283]
According to yet another aspect of the invention, an apparatus and method for scheduling and assigning work is provided in the proposed system. Traditionally, the scheduling and assignment of operations across manufacturing facilities has been performed by shop or factory managers. The plant manager determines the current work status as well as the current setup and availability of the machinery. After gathering and analyzing this information, the shop or factory manager generates schedules and distributes assignments for work done at various locations in the factory (eg in the form of work schedule sheets distributed to the factory floor). ). Work schedule assignment is performed to ensure that each customer's work is completed in a timely manner and by a predetermined shipping date. The conventional process of scheduling and assigning work, however, is laborious and is usually done manually by the factory manager.
[0284]
According to one aspect of the present invention, a work assignment and scheduling system is provided to assist a shop or factory manager in scheduling work for the factory. The system utilizes bend model information stored in the communication network and database 30 and automatically gathers the necessary information, so that the factory manager can more easily generate work schedules. This system is executed via software or program logic in the server module or station module located throughout the factory. By entering the various operations to be scheduled, the system software analyzes the design and part information to determine which machine is best suited to perform a given operation. For this purpose, the current state and setup of the machine in the factory is defined, stored in the database 30 and accessed by work scheduling software. Based on various conditions, in the form of a display, it suggests which machines are available to perform a particular task and which machines cannot perform other tasks. In this regard, a table is displayed that ranks machine availability for a particular task and provides a suggested task schedule. The proposed work schedule is executed or modified by the factory manager. The conditions used to set and recommend work schedules include a wide variety of conditions. And it includes the current setup of each machine in the factory, the types and tools of bending required for each operation, and other types of operations that must be performed during the same time frame or time. Information from the bend model file for each part, including the bend angle, flange length, and bend type, is utilized to determine which machine can perform a particular task. For example, a table stored in the database 30 contains important information about the current setup and capabilities of each of the punching and bending machines on the factory floor.
[0285]
Based on the proposed work schedule, the factory manager assigns multiple operations to various locations throughout the factory to maximize factory production and output capabilities. The last work schedule or assignment is entered electronically and sent to each of the machines via the communication network 26.
[0286]
A pilot lamp, such as an LED, is provided at each of the bending and machinery workstations to indicate and confirm that work has been assigned and transferred to that station. The work assignments and schedules are stored in server module files that are instantly accessible from any location in the factory. In addition to the functions described above, other functions are performed in accordance with the teachings of the present invention. For example, menu screens are provided and displayed at various station modules or locations to facilitate the user to select various display and function modes of the present invention. For example, a main menu screen such as that shown in FIG. 56 is provided to the user when the station module is started. The main menu window display includes icon images for each of the available window displays and viewing modes provided by the station module. This main menu screen appears whenever a menu button (eg, F1 key) is selected. The user selects the window by moving the highlighted block to the desired window icon and selecting it. Such an operation is performed through the use of a keyboard, mouse or joystick.
[0287]
Other window screens are also provided and displayed to the user to facilitate entry and display of work information. For example, the part information window is displayed to allow the user to enter or modify part information. An example of the part information window display is given in FIG. This part information window contains all relevant part information (eg, part number, material type, dimensions, etc.) and includes a two-dimensional plan view and isometric projection of the sheet metal part. A bend line information window (eg, as shown in FIG. 58) is provided to allow the user to monitor various bend line information including the bend order and reduction amount for each bend line. The bend line information window allows the user to enter or modify bend line information for each bend and includes a two-dimensional plan view and isometric view of the sheet metal part.
[0288]
An additional window display is provided to facilitate operator bending order analysis. For example, a bending order window display and a bending simulation window display are provided to display the various bending stages of the part and to simulate the orientation of the part during the bending operation. The bend order window as shown in FIG. 59 displays to the user the intermediate shape (in a stationary state) of the part at each stage of the bend order selected from the main menu screen. A bend simulation window (see, eg, FIG. 60) is also selected by the user to provide the bend stage static information (in the form of part icons provided on the right side of the screen) and positioning and bend movements performed at each stage in the bend sequence. A dynamic simulation (in the middle of the display). By intermittently selecting a part icon on the screen, the user can see a dynamic simulation of the orientation of the part during bending at the stage represented by the selected part icon. To dynamically simulate each bend sequence, the part is flipped, translated, bent / rotated around the bend line.
[0289]
Each of the window displays of FIGS. 57-60 is selected and displayed to the user from the main menu window display of FIG. Furthermore, the user in an arbitrary station module selects an appropriate window icon in the main menu window display, and the parts displayed according to the observation mode (for example, two-dimensional plane, wire frame, solid, orthographic view) of the present invention. To obtain a two-dimensional and / or three-dimensional representation. This was described in detail above with reference to FIGS. 28-31. Various menu windows are also provided, for example in the station module, to facilitate operation of the features and functions of the present invention. FIG. 61 illustrates an exemplary menu displayed for 2D to 3D operation. FIG. 62 further illustrates an exemplary menu structure for the two-dimensional cleanup operation of the present invention. The present invention, however, is not limited to these menu arrangements, and other menu screens and / or tool icon bars are provided to facilitate interaction with the user's system.
[0290]
Other characteristics are also implemented in the present invention. For example, a high level automatic device is also provided to facilitate the generation of bending plans. For example, a bending and tooling expert system is provided to generate and propose tooling setups and bending sequences based on the part geometry and shape for each operation. For example, as disclosed in US patent application Ser. Nos. 08 / 386.369 and 08 / 338.115.
[0291]
Although the invention has been described with reference to several exemplary embodiments, the terminology used herein is not a limitation term but a description and description terminology. Various modifications may be made without departing from the scope and spirit of the invention and various aspects. Although the invention has been described herein with reference to specific means, materials and examples, the invention is not intended to be limited to the specifics disclosed herein. Rather, the invention extends to all functionally equivalent structures, methods and uses.
[0292]
Appendix A
Example of feature entity extraction from bending model parts
.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_numbint, ** = 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_lines; / getology-lines (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_jacent; 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_parran k = 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 pointerbline 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 -___ cent_ (); 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) Th e 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. 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. .// maxnewfaces is the maximum number of bendline_only_face need to be created // without encou nter 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 [face_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_OPbREG *) ] .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 bendlin e 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 [_ .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 records the 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);}
Appendix B
An example of similarity index characteristics. Compare the topological matrices of the two parts and find their best similarity index. The similarity index is given as the sum of all penalties for the mismatched FENTs of the two part FENT matrix topological matrix). The best similarity index has the smallest value.
[0293]
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 // 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 inde x. 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 // inp uted value (which isthe requirement) is // too small.//return-index on whether or not found the 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), the 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 matrix to 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 the sequence 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);} // Extract a list of entries from an existing submatrix that matches the new submatrix. The submatrix dimensions must be greater than or equal to the topological matrix dimensions. Note: The first element of the match list must be initialized and include the submatrix face number for matching with the first face of the topological matrix. When nmatched is greater than 0, the first nmatched entry in the match list must contain a positive number and indicate an already matched entry in the submatrix. // 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, inlevel * relevel , 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 // h as 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. 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 use the 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); * (pcandidates + 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 th e newmatrix for unfixing facenewchange_counts_for_unfix_one_face (pnewmatrix, pnewmatchlist, pcnew, matrixdim, nfacefixed + 1); // cleanupdelete [] pcandidates; delete [] pincreases; return (0);} ///////////// ////////////////////////////////////////////////// /// Update the counter to fix one or more faces. ////////////////////////////////////////////////// ////////////////// 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 / // pcnew- the updated FENTCOUNT of all the faces // switch the to be fixed face to the location of nface fixed + 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);} ////////////////// ////////////////////////////////////////////////// // This function updates the counter and releases the fixed surface. The released surface is the surface that is currently in the nface //// fixed position. ////////////////////////////////////////////////// //////////////////// 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];} /////////////////////// ////////////////////////////////////////////////// This function counts the number of FENTs in a given int array. ////////////////////////////////////////////////// /////////////////////// FENTCOUNT count_fents (int * pintfentarray, int arraydim) {// input // pintfentarray- the pointer to the intfent array // arraydim -the dimension of the 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);} //////////// ////////////////////////////////////////////////// //////// This function counts the number of FENTs in a specific set of intent arrays. ////////////////////////////////////////////////// //////////////////// 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);} ////////////////////////////////////////////////// /////////////////////////// This function counts the number of FENTs in a particular set of intfent matrices. //// Note: The intent matrix is symmetric. Only half of the matrix is included in the count. ////////////////////////////////////////////////// /////////////////////////// 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 = pintfentmatrix + (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 );} /////////////////////////////////////////////// ////////////////////// This function returns a penalty for unmatched pairs of FENTs. ////////////////////////////////////////////////// /////////////////// 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 for the 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);} /////////////////////////////// ///////////////////////////////////// This function is the minimum penalty for the two smallest possible discrepancies To return. ////////////////////////////////////////////////// ////////////////// 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 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 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 );) ///////////////////// This function returns the FENT penalty for a mismatched pair. ////////////////////////////////////////////////// //////////////// 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);} ///////////////// ////////////////////////////////////////////////// //////////// This function returns the minimum penalty for the minimum possible mismatch of two FENTCOUNTs. ////////////////////////////////////////////////// //////////////////////////// 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] increase (igroup) * change_from_seperate_fent_sets (ntnew, nto ld, 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); 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 (= fent_group = int (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 (parfent_seint) ; 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.total [igroup]; ntold = pcold_total.gcount [igroup]; increase + = fent_gro up_weight (igroup) * change_from_seperate_fent_sets (ntnew, ntold, 0, 1);}} return (increase);} ////////////////////////// ////////////////////////////////////////////////// / This function returns the minimum penalty for the minimum possible mismatch of two FENTCOUNTs. ////////////////////////////////////////////////// /////////////////////////// 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);} ///////////////////////////////////// ///////////////////////////////////// This function is up to a given fixed surface Calculate the similarity index for a pair of faces. //// Note: Only half of the matrix is included in the calculation. ////////////////////////////////////////////////// //////////////////////// 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 from the 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);} ///////////////////////// /////////////////////////////////////////////// this function is Calculate the similarity index for a given set of faces up to a particular fixed face. ////////////////////////////////////////////////// ////////////////////// 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);} //////// ////////////////////////////////////////////////// ////////////// This function calculates the increase in the number of similar fingers //// for a given facenew and faceold mismatch. ////////////////////////////////////////////////// /////////////////////// 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 / FENTCOUNT to initialize the FENTCOUNT 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 t he old part.return (increase);}
Appendix C
// Example of bend line detection including comments. This module includes the implementation of BM PART :: Automatic Bend ().
[0294]
// * ********** ********** ********** *********** ****** *** This is the main high-level bend model function that serves the design and construction of the part. Its purpose is to form a bend line between the faces so that the parts are connected (if possible). This function is to facilitate the formation of the part. Normally, the CAD program portion of the third party is drawn. The bend model has no control over the CAD system, and for our purposes this drawing is just a set of edges. This figure must therefore be analyzed to detect the structure of the part. After that, we can form a bend line with the surface of the part. However, the diagrams entered are often ambiguous and bend lines are not uniquely defined. In that case, we use a series of heuristics to form the bend line. This heuristic defines a priority criterion for retrieving a single output when many are possible.
Since this problem is common to many applications, this function is part of the bend model. Furthermore, implementing this function in the bend model simplifies the surface detection software that must be part of the CAD system. In this function we assume that the edge of the surface is classified according to the left-hand rule (which defines the orientation of the plane) to coincide with the vertical plane. Basically, this function assumes that all planes are correct themselves when viewed separately. However, this function does not require that the orientation of adjacent planes is correct with respect to the bend line between those planes (there is a bend model function that fixes it later). This function can be used to generate bend lines for both partial 3D versions and partial flat versions. However, a part can have either a flat or 3D version, but not both. In other words, all 3D versions of the 3D body must either be zero (in which case we have a flat version), or all flat versions must be zero. * // ************ ********** ********** ********** ***** ***** ********** Algorithm / Process: The purpose of the algorithm is to connect the whole part when given a constraint that does not form a loop in the topology graph of the part (I.e., all surfaces are all connected via bend lines and the stand-alone surfaces do not want to hang around) forming a minimum number of bend lines (because we can make a part I just don't want to change it). It is not required that the input part does not contain any bend lines. AutoBend is a part in which a new bend line is added in consideration of an existing bend line. At the top level, this algorithm performs a version of the maximum span tree algorithm. At any point in time, the algorithm has a currently connected element and a set of fringe surfaces (these are part of the connected element). These fringe surfaces have contacts with the outer surface of the connecting element. During a single process, a new surface outside the connecting element is added to the connecting element. Between the outer surfaces of the connecting elements that abut the fringe surface, Autobend takes out the one with the largest contact. This heuristic approach using the largest contact is based on the fact that in sheet metal manufacturing, the larger the contact, the better results are usually obtained. However, when a tie is present, that is, when there are several faces outside the connecting element that have the same maximum contact as the fringe face in the connecting element, we use another heuristic. This heuristic technique extracts the surface that minimizes the diameter of the part. The diameter of a part is the maximum distance between any two faces in the topology graph of the part. *********** ********** ********** ********** ********* * * Technical note:-This function probably doesn't work well when the thickness of the part is not zero. Note that this function produces bend line information that matches the surface l (primarily the vertical surface l) in the algorithm. However, the vertical plane 2 cannot match this information, but it must be fixed later. PART. HXX. Please refer to the comments. #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 "/ * This function calculates all contacts between two given faces. Contact contact is obtained when two surfaces are in contact with each other (ie, within some very small distance tolerance), and the line segment separating them has a length greater than zero (ie, a common line) Minutes are not lines but actual line segments). Objective: To calculate the potential bend line between two given faces. Assumption:-Both sides have the latest non-empty 3D version used for the calculation. -All loops on either side are closed.
Requirements:-Both sides must be in the same plane. Returns:-List of contacts This returned list has the structure: Node 0: obj is "number of contacts". The node 2i-1: obj is "the head of the list on the surface l side of the contact i". Node 2i: obj is the head of the list on the side 2 side of contact i, where i is in [1, “number of contacts”]. Each contact is a “closed” contact, ie Note that there are no gaps in the contacts: Each list on either side of the contact is a list of lines in which the order of the lines in the list is opposite to the sweep direction (currently XZY sweep) ( (Actually a pointer to a line), which shows how the list of contacts looks: contact #-> list 1. surface 1. head 1. list 1. surface 2. head 2 .... .--> List i.Surface 1. Head-> List i-Surface 2.Head. |||| VVVV plane 1 line 1 plane 2 line 1 plane 1 plane 1 line 1 plane 2 1 ||| VVVV ...... ||| VVVV plane 1 in line i plane 2 in line j plane 1 in line k plane 2 in line 1 in this function, k bend The corynea bend line is considered to be k individual contacts Note: ----- By default, we consider all lines on both sides as candidates for the bend line, but if the user When the line already knows what it is (or actually knows what the bend line edge is), the user uses these line names and this function considers only those lines This function checks whether either surface 1 or surface 2 has a name equal to the idx of the other surface (surface 1 and Surface 2 is checked individually.) If yes, only these lines will be considered candidates for the bend line on the side of the surface. * / 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 sa 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; / ********* ********** ********** Quality Check ********** *** ******* ********************* /// 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 surface BM_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 done BM_LOOP * bloop1 = body1-> get_bloop (); BM_LOOP * bloop2 = body2-> get_bloop (); if (NULL == bloop1 || NULL == bloop2) return 1; / *********** ********** ********** ********** ********** ********** ********** ********** ********** Here we do a very quick check whether these surfaces can be touched anyway. Here we check whether the b-loop of surface 2 touches (at more than one point) or intersects the plane of surface 1. This saves time when these two surfaces are clearly not in contact. ********** ********** ********** ********** ********** ********** ********** ********** *********** /// 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-> rediute_b_b ________ (), (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, 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 (1), 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_4) , it means that 2, 3 or 4 bbox corners are on the plane.// that means, it is possible that there is acontact./* Here we check the same for b-box 1 with respect to plane 2 To do. * / 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)! 0 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 (), (_), return 0; if (! (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_toleranceif; distance_plane_count_pl ne_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;} } / *********** ********** ********** ********** ******* *** ********** ********** ********** ********** Count all lines on both sides To do. Memory needs to be allocated. Note: Since only lines can make bend lines, just count the edges that are lines. Note: Check if the user has a specific bend edge. The user can limit which edges are considered possible bend edges by setting the names of those edges. ********** ********** ********** ********** ********** ********** ********** ********** *********** / 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; (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_lines; if (face1_count1 <1 || face2_line_count <1) return 1; line_count = face1_line_count + face2_line_count; / *********** ********** **************** **** ********** ********** ********** ********** ****** **** Allocate memory. ********** ********** ********** ********** ********** ********** ********** ********** *********** / if (NULL == (line_pointers = new BM_LINE * [line_count])) return 0; if (NULL == (line_start_coordinates = new double [line_count])) (delete [] line_pointers;} / *********** ***** ***** ********** ********** ********** ********** ***** ***** ******************** First, fill the line pointer array. If necessary, only the edges specified by the user are taken. ********** ********** ********** ********** ********** ********** ********** ********** *********** / 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;}} / ****** ***** ********** ********** ********** ********** ***** ***** ********** ********** ********** The line is defined by the X coordinate, then the Z coordinate, and then the Y coordinate. Sort the sequence. ********** ********** ********** ********** ********** ********** ********** ********** *********** / {// 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] = pX ();} // 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]-> line_pointers [0])-> get_endpt ()); line_start_coordinates [0] = pZ (); 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 = pZ (); 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_ 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 ++; slinestart = 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] = pZ ();}}} // end of the block of codefor sorting the array / ******* **** ********** ********** ********** ********** ****** **** ********** ********** ********** The line start coordinates are no longer needed, so delete them. ********** ********** ********** ********** ********** ********** ********** ********** *********** / if (line_start_coordinates) {delete [] line_start_coordinates; line_start_coordinates = NULL;} / *********** ********** ********** ********** Main loop. Sweep two sides. Always keep track of the open line (the line we have seen the starting point, but the end point has not yet seen the line-actually the start-and -end-point, not the larger and the XZY ordering Smaller endpoint). Initially, the set of open lines is empty. Do the following during all iterations:-Remove all lines that were open but now should be closed-Check if the current line overlaps the open line,- Add to the open line set. * /// these represent lists of contacts 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; 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 in the 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_start_by_Z line-> get_end pt ()); p_face2 = p;} // ********** ********** ********** ******** ** ********** // Scan all known contacts and check if this contact should be // added to 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.i f (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_in_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.} / *********** ********** ********** ***** ***** Free memory if necessary. ********** ********** ********** *********** / 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 = contact; 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;} / * This function sweeps the list of contacts between two faces From all surfaces to be almost similarly generated by BM calculating the contact surface) and all, but to remove the greatest contact. Basically, it “filters” the list of contacts and removes contacts that do not belong to the longest contact. Note that, in general, the longest contact is a list of simultaneous bend lines. Thus, the basic structure of the contact list is the same. For example, the first node in the list is the number of contacts in the longest contact. This function also restores the longest contact length. This function takes advantage of the fact that all contacts are closed, so in the list of lines in the contact, the end point of the line is equal to the starting point of the next line. The only tricky part in this method is to calculate the length of the overlap in the first and last lines. Next, the line length is added in the middle of the list.
See the previous function. * / 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; = 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_list_NODE) ; 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 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. 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. 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 =} 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 later BM_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_DE_NO_____________________ -> 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_face_first_last_face_first_last_face_list_list_large_list_list_large_list_list_large_list_list_large_ = 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: 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_list_last_1 = next_last_face2_list; continue;} // ok, this is not the largest contact, delete both face1 and face2 sides of the contact BM_LINKED_LIST_NODE * next_line_in_list; for (line_in_list = (BM_LINKED_LIST_NODE *) last_face1_list-> get_obj =) {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_next_in_list _> _ next_in_list _> _ 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;} / * This function is a static int BM create bend line (. . . ) Only. The big problem now is that we are deleting some lines. The problem is that when we have simultaneous bends, other contacts can still refer to these lines we just deleted. We must go ahead and check it, and if true, replace the pointer with the line we modified / deleted with a valid reference. That is, the affected line is the first and last line on the left. Potentially references to them need to be replaced with reference to 11 and 13. * / 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 the contact BM_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 contact BM_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 * start_side_1 -> 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 proc ess_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 sid e2if (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 ) {// 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;} / * This function creates a simple (regular) bend line between two faces based on a contact list given as input. Once this is done, it erases the contact list. This function assumes that the edge of the face is classified according to the left-hand rule.
This function returns to TRUE if all are fine. NB! The problem here is not to partially invalidate something when a new bend line is formed. To complete it, we create a bend op that is a separation (without the bend line) (not understandable) and later add it to the bend line. Furthermore, we only form the topology after the bend lines are formed and added to the part. Note that this function forms bend line information that coincides with plane 1 (mainly vertical plane 1). However, the vertical plane 2 may not match this information, but it must be fixed later. * / 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 parameters ); 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_versio n ()! = 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 (); / * First, all you have to do with the bend line, form a bend line, create a bend op, set bend op parameters, create a cylinder for the bend line , Setting, setting a bend line, a center line, and the like. * /// 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_, 0.0, NULL, // 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 bendline / create bendline surface.if angle is not 180 degrees, we create a cylinder, otherwise a (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 wellate 3 later we validate it.// set sense to 0, because we want the bendline (cylinder) to represent explicitly O UTSIDE // 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 Second, if necessary, break several lines and join all adjacent lines into one adjacent line. Further, adjacent information between the surface 1-bend line and the surface 2-bend line is formed.
* /// 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 list BM_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: wewi ll 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 of the 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;} / * Here you can delete the contact list. * / 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 );} / * Finally, a center line is formed. Make sure the direction and length are correct. Note that p1 and p2 are defined with respect to plane 1. That is, p1-> p2 is a direction with respect to the contact on the surface 1 side. * / 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;} / * The purpose of this function is to have a part with a cut element consisting of faces, which will be connected if you add these new bend lines. It is to form a minimum number of bend lines so as to become like this. 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 -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 maximu m 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 * // * give the face (face 1) And this structure contains information about the contact between this surface and the other surface. For any two faces, you need to know if there is contact between these faces, and if yes, you need to know what is its length. The simplest way to process this data is given by storing it as a two-dimensional array. However, this takes up a lot of space, most of which is wasted, usually when there are many faces, most of them have no contact between them. by. Instead, we will store this information as a list of structures for all aspects. We generate this record (ie structure) only when the contact length between the two faces is greater than zero. * / 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 * face2 ; // 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; / * This is a very basic function used by many functions in this file. It deletes the contact list. * / 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_NOD E *) 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;} / * This function calculates and stores the best (ie, longest) contact between two faces. * / 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;} / * This function adds a new face to the currently connected element. It also calculates the longest contact between this new surface and all other untreated surfaces. * / 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;} / * These two functions are user-topology Allows the distance between two faces in the graph to be set. The dist btw plane is the upper right half of the two-dimensional array. * / 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;} / * This function returns the maximum distance between a given face and another face in the connected element. * / 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_for_distance = 0 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;} / to Its purpose is to automatically generate a bend line for the part. * / 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 tha t 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_f aces + 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);} / * First try to expand the maximum span tree of the currently connected elements of the face. * /// 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 (c ntct-> 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; 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 betterct-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, // cnt1, best_length__ , // that means we can expand the tree./* Check if we can expand the span tree. To this point until we return to expanding the connecting element, we are simply using surface 2, ie we do not need surface 1. The only case is when we create a new bend line, but we can extract the face id from the contact list. * / 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 (bull ==) 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 / * where we are the other that this face (ie face 2) is connected to it It is necessary to check whether it has an arbitrary 3D body. If yes, we need to pursue these connections in order to add all the faces connected to face 2 to the currently connected element. * / 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. 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) c ontinue; 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 = BM_ *) 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 t o 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 beequal, it end_id 'in the beginning of this for-loop. // note the next function (add_face_to_connected_component (...)) will increment end_id. if (! add_face_to_connected_component (this, face2, & end_id, all_contacts, idx_to_face_mapping)) // tryto expand the spanning tree. goto expand_spanning_tree; done: ret_value = 1; goto release_memory_and_return; failure: ret_value = 0; release_memory_and_return: // free memory if necessaryfor (i = 0; i <number_of_faces; i ++) {delete_contact_info_list (all_contacts [i]);} if (all_contacts ) Delete [] all_contacts; if (idx_to_face_mapping) delete [] idx_to_face_mapping; if (heap) delete hair ; If (dist_btw_faces) delete [] dist_btw_faces; return ret_value;}
Appendix D
Example of 2d cleanup function
#include <stdio.h>#include<stdlib.h>#include<math.h>#include<memory.h>#include<String.h> / * Function name: 1 control levelTestFindBoundaryTestFindDrawingSheetControlTestFindViewsControlTestFindBoundaryControlTestFindArrowControlTestFindOneSideOpenControlTestFindOneSideOpen2ControlTestFindCenterLineControlTestFindOneSideOpenConnectControlTestFindSameColorControlTestFindSelectSingleControlTestUnselectSingleControlTestClearControlTestClearKeepFlagsControlTestDeleteControlTestUndoControlTestUndoPreControlTestDeleteViewsControlTestSetUndoFlagViewsControl TestBackColorControl2 applicate * / # 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 only with 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 enti ties // 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 * // 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_tr immed_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 define the 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); typedef struct Vector {doublex, y, z;}; extern double BBminX, BBmaxX, BBminY, BBmaxY, BBminZ, BBmaxZ; / * Function: Name: 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. 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 entitiesGroup input nodeClean (old function) look for a selected entity on screenintF2dCleanUpLineAnglecompute a line type entity's angle int F2dCleanUpArcAnglecompute a arc type entity's angl e.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 F2dCleanUpLines length == ================================================== ==== * / intTestFindBoundary () {// external functionsint F2dCleanUpFindArrow (); int F2dCleanUpChangeColor (); int F2dCleanUpFindOneSideOpenEntity (); int F2dCleanUpFindOutSideLoop (); int F2dCleanUpChangeDrawingColor (); struct node * F2dCleanUp ); 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 ON 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;} / * ========================================== ======================= Function: Name: F2dCleanUpFindGroup Description: look for a group entities connected with input entity Return Value: = 0: Completed successfully; Parameters: Input: Entity: a entity output: 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;} / * ====== ================================================== ======== Function: Name: F2dCleanUpArcAngle Description: Calculates the angle of an arc-shaped entity. Return value: RotateVertexFlag: Direction flag = 1: Vertex1 is a rotation point. = 2: vertex2 is the rotation point. Parameters: Input: 1 OriginVertex: Rotation vertex 2 Entity: Arc-shaped entity Output: 1 EntityAngle: Direction angle (radian) 2 EntityAngleAnother: Other side direction angle ================ =============================================== * / 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;} / * ============================= ============================= Function: Name: F2dCleanUpLineAngle Description: It is a function for control how Return value: RotateVertexFlag: direction flag = 1: vertex1 is rotate point = 2: vertex2 is rotate point Parameter: Input: 1 OriginVertex: rotationary vertex2 Entity: line type entity Output: 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 = F2dCleanUpToleran ce; // 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;} / * ============================ ============================== Function: Name: F2dCleanUpChangeColor Description: Change entity color function. Return Value: = 0: Completed successfully Parameter: Input: Entities_change_color_list: Node list that has changed color ========================== ================================ * / 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 (N ext_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;} / * ==== ================================================== =========== Function: Name: F2dCleanUpChangeDrawingColor Description: A function that changes the color of an entity. Return value: = 0: Completed successfully; Parameter: Input: 1 In drawing: 1: In the figure, the figure is the changed color =================== ======================================= * / 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 (ent ity, 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 En tity% d ", CountPrompt); ck_prompt (message); #endifreturn 0;} / * ============================== ============================ Function: Name: F2dCleanUpUndoPre Description: Data flag for undo function To prepare. Return value: = 0: Completed successfully; Parameter: Input: 1 In drawing: Diagram of change status. ================================================== =============== * / 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;} / * ================================================== =============== Function: Name: F2dCleanUpUndo Description: To undo. Return Value: = 0: Completed successfully; Parameter: Input: 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! = ent ity-> 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;} / * ================================== =============================== Function: Name: F2dCleanUpChangeDrawingFlag Description: A function that changes the flag of an entity. Return value: = 0: Completed successfully; Parameter: Input: 1 In drawing: The figure that has changed color ======================== ================================== * / 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;} / * ============================= ==================================== Function: Name: F2dCleanUpFindSameColorEntity Description: Same Find the color of the entity. Return Value: = 0: Completed successfully; Parameter: Input: 1 In entity: Entity 2 In drawing: Diagram that has changed color =================== ====================================== * / 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 entities on 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;} / * ======================================== ========================= Function: Name: F2dCleanUpClearDrawingEntity Description: Titi's color. Return value: = 0: Completed successfully; Parameter: Input: 1 In drawing: The figure that has changed color ======================== =============================== * / 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;} / * ========= ================================================== ====== Function: Name: F2dCleanUpClearDrawingKeepFlags Description: Restores entity colors but retains flags. Return Value: = 0: Completed successfully; Parameter: Input: 1 In drawing: Changed color diagram ======================== ================================== * / 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 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;} / * ========================= ================================ Function: Name: F2dCleanUpDeleteViews Description: It is for delete view In function That. Return value: = 0: Completed successfully; Parameter: Input: 1 Indrawing: Figure =============================== =========================== * / int F2dCleanUpDeleteViews (struct drawing * In_drawing) {// check drawingif ( In_drawing == NULL) return 0; // delete views (Not release memory) In_drawing-> views == NULL; return 0;} / * =================== ============================================== Function: Name: F2dCleanUpDeleteDrawingEntity Description: It is a function for a deleted entity. Return Value: = 0: Completed successfully; Parameter: Input: 1 In drawing: Figure ============================== ============================ * / 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 = Gp -> next) {if (Gp == NULL) break; if (Gp-> index! = 0) continue; for (ET L = 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;} / * =================================== ======================= Function: Name: F2dCleanUpCheckEntityExist Description: check an entity for current drawingif the entity is not same to database , drawing was changed Return value: = 0: No change; = 1: Changed; Parameter: Input: 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;} / * ===================== ==================================== Function: Name: F2dCleanUpChangeArrowVertexFlag Description: Change the arrow top vertex flag and set the arrow center line coordinates. Return Value: = 0: Completed successfully; Parameter: Input: 1 Flags: Flag 2 TopVertex: Arrow Top Vertex 3 Entiry: Arrow Centerline Entity ================== =============================================== * / 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; / end 0;} / * ============================================= ==================== Function: Name: F2dCleanUpFindArrowCenterEntity Description: Finds the arrow center line and sets the flag to the arrow member. Return value: = 0: No arrow; = 1: Arrow Parameter: Input: 1 Nodes: Connected nodes 2 TopVertex: Arrow top vertex 3 StartEntity: Arrow start line entity 4 EndEntity: Arrow end line entity 5 CenterLineAngleTemp: Arrow center line Angle ================================================= ================ * / 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; // doubledoubleCenterParLength , CenterParentAngle = 0.0, CenterParentAngleAnother = 0.0; doubleTolerance = 0.0; // set valueTolerance = F2 dCleanUpTolerance; // 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 vertexF2dCleanUplag & ArrowFlags, TopVertex, CenterEntity); return ReturnFlag; if (temp_list-> cdr == NULL) break;} return ReturnFlag;} / * Function: Name: F2dCleanUpFindArrowOneSideOpenEntity Description: Find one side-open entity. Return value: = 0: No open; = 1: Open = 2: Open Parameter: Input: 1 Nodes: Connected 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;} / * ===================== ===================================== Function: Name: F2dClaenUpCheckStartEndEntity Description : Check start and end entities Return Value: = 0: No Arrow; = 1: goo d Parameters: Input: 1 StartEntity: Arrow start line entity 2 EndEntity: Arrow end line entity =============================== =========================== * / 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 = F2dCleanUpLine_Length2 ); // 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;} / * =================================== ============================ Function: Name: F2dCleanUpComputeCenterLineAngle Description: Calculates the center line angle. Return Value: = 0: No Arrow; = 1: Good Parameter: Input: 1 TopVertex: Arrow Top Vertex 2 StartEntity: Arrow Start Line Entity 3 EndEntity: Arrow End Line Entity Output: 1 CenterLineAngle: Arrow Center Line Angle ===== ================================================== ========= * / 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 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_s 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 (-parent_ arrow_ 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 ==; ================================================== ============ Function: Name: F2dCleanUpFindArrowEndEntity Description: Find arrow end line Return Value: = 0: No Arrow; = 1: Arrow Parameter: Input: 1 Nodes: Connection Node 2 TopVertex: Arrow Top Vertex 3 StartEntity: Arrow start entity =========================================== ==================== * / int F2dCleanUpFindArrowEndEntity (// inputstructnode_list * Nodes, structplanar_vertex * TopVertex, structnode * StartEntity) {// external functionsint F2dCleanUpFindArrowOneSideOpenEntity (); int F2dCleanUpComputeCenterLineAngle (); int F2dCleanUpCheckStartEndEntity (); intF2dCleanUpFindArrowCenterEntity (); // link list and temp liststru ct 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 = 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->Childrenlag); 0) continue; // check parents en titiesReturnFlag = F2dCleanUpCheckStartEndEntity (// inputarrow_start_entity_parent, arrow_end_entity_parent); if (ReturnFlag == 0) continuee; // look for central entityof arrowReturnFlag = F2dCleanUpComputeCenterLineAngle (// inputTopVertex, arrow_start_entity_parent, arrow_end_parent_ 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;} / * ======== ================================================== Function: Name: F2dCleanUpChangeChildrenFlag Description: Function to change the entity's children flag Return value: = 0: Completed successfully; Parameter: Input: ==================== ====================================== * / int F2dCleanUpChangeChildrenFlag ( struct node * Entity) {// temp liststruct node_list * Tem p_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;} / * ==================================== ============================ Function: Name: F2dCleanUpLineLength Description: Function to calculate the length of a line-type entity Return Value: = Length; Parameter: Input: Entity: Parent Entity ======================================= ========================= * / 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;} / * ============================================ ===================== Function: Name: F2dCleanUpFindArrow Description: Finds an arrow-type entity, Set them to Return Value: = 0: Completed successfully; Parameter: Input: 1 Entities_list: Node list to be checked =========================== ============================== * / 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_con nected_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 VELLUMCountPromp ++ ; sprintf (message, "Finished find arrows Entity% d", CountPrompt); ck_prompt (message); #endifreturnassistant_line_flag;} / * ====================== ==================================== Function: Name: F2dCleanUpFindOneSideOpenEntity Description: Return value: = 0: Completed successfully and No found; = NUM: Open entities' number Parameter: Input: 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 entitie sstruct 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 = FifdCleanUpTolerance; #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) + >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;} / * ================================================= ================ Function: Name: F2dCleanUpFindOneSideOpenEntity2 Description: After finding a view, find an entity whose one side crosses the boundary between the open entity and the view. Return Value: = 0: Completed successfully, nothing found; = NUM: Number of open entities Parameter: Input: 1In_drawing: Figure ================== ======================================= * / 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;} / * =============== ================================================= Function : Name: F2dCleanUpFindGroupMinX Description: Find the minimum X value for an entity group. Return Value: = 0: Completed successfully, no entity; Parameters: Input: 1 Entities_list: Checked node list output: 1 Entity: The entity contains the smallest X value. ================================================== ============== * / 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_lis t2->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 entities for (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;} / * ========== ================================================== ===== Function: Name: F2dCleanUpFindOutNextEntity Description: Find the entity connected to the outside loop entity. Return Value: = 0: Completed successfully; Parameter: Input: 1 In_entity: rotate axis entity 2 In_Nodes: entity node 3 In_Vertex: entity vertex 4 * In_Angle: entity 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, TRotVertexAnother, 0, RotateAxisEntityType = 0, RotateAxisEntityVertexFlag = 0, FindNextFlag = 0; // length and angledoubleRotateAxisAngleAnother = 0.0, RotateAxisAngleAnotherTemp = 0.0, RotateMi nAngleTemp = 0.0, RotateDiffAngleTemp = 0.0, RotateAxisAngle = 0.0, RotateAxisAngleTemp = 0.0; // set tolerance TolerancedoubleTolerance = 0.0; Tolerance = F2dCleanUpTolerance; // initializeRotateAxisAngleAnother = * In_Angle; RotateEntity = In_sentRotate 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 search RotateAxisAngle = RotateAxisAngleAnother; RotateMinAngleTemp = 2.0 * pi; RotateNodes = RotateNodesAnother; RotateVertex = RotateVertexAnother; // 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 & T RotateAxisAngle , &RotateAxisAngleAnotherTemp);break; // line typeentitycaseCK_LINE: RotateVertexFlag = F2dCleanUpLineAngle (// inputRotateVertex, Next_entity, // output & RotateAxisAngleTemp, &RotateAxisAngleAnotherTemp);break; // wrong typeity / if = Rotatetype entity / default; ) {// 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_entityel>selex2; {// set rotation vertex nodeRotateNodesTemp = Next_entity->connected_nodes_2; RotateVertexTemp = Next_entity->vertex2; // set anotherside vertex nodeRotateNodesAnotherTemp = Next_entity->connected_nodes_1; Rotat eVertexAnotherTemp = 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 (RotateVertexFempDate 0.0: case ( 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 = RotateVertex; RotateNodesAnother = RotateNodesAnotherTemp; RotateVertexAnother = RotateVertexAnotherTemp; RotateAxisAngleAnother = RotateAxisAngleAnotherTemp; break;} break; caseCK_LINE: switch (RotateVertexFate) {case1: // no changebreak; case2: RotateEntity = Next_Tate; = RotateVertexAnotherTemp; RotateAxisAngleAnother = RotateAxisAngleAnotherTemp; break;} break;} caseCK_LINE: switch (RotateEntity-> type) {caseCK_ARC: if (RotateEntity-> vertex1 == RotateVertex) {RotateEntity = Next_entity; RotateNodes = RotateNodesAnotherTemp; RotateVertexAnother = RotateVertexAnotherTemp; RotateAxisAngleAnother = RotateAxisAngleAnotherTemp;} break;}}} if (RotateDiffAngleTemp <RotateMinAngleTemp) {FindNextFlag = 1; RotateMinAngleTemp = RotateDiffAngleTemp; // set rotation entityRotateEntity = Next_entity; RotateNodes = RotateNodesTemp; RotateVertex = RotateVertexTemp; RotateNodesAnverTRot; meet closed entity if (Next_entity-> flags == 4) break; if (FindNextFlag == 0) break;} return 0;} / * =================== ============================================== Function: Name: F2dCleanUpFindOutSideLoop description: Find the outside loop entity. Return value: = 0: Find outside loop entity. ; = NUM: Number of outside entities Parameter: Input: 1 Entity: The entity contains the minimum X value of the loop. ================================================== ============== * / int F2dCleanUpFindOutSideLoop (struct node * MinXvalueEntity) {// external functionsint F2dCleanUpArcAngle (); int F2dCleanUpLineAngle (); int F2dCleanUpFindOutFirstEntity (); int F2dCleanUpFindOutNext; 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; entity and temp entitiesstruct node * Next_entity, * RotateEntity; struct planar_vertex * RotateVertex, * RotateVertexTemp, * RotateVertexAnotherTemp; // length and angledoubleassistant_line_angle = 0.0, MinXvalueGroup = 0.0, RotateAxisAngleAnemp = 0.0, RotateAM = 0.0, RotateDiffAngleTemp = 0.0, RotateAxisAngle = 0.0, RotateAxisAngleTemp = 0.0; // set tolerance Tolerancedoubleloop_toleranc e = 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 = RotateAxisAn gleAnotherTemp + 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 (RotateotherTemp> (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-> M vertex1-> X) <loop_tolerance) // get start-> end // set rotation vertex nodeRotateVertex = MinXvalueEntity->vertex1; elseRotateVertex = MinXvalueEntity->vertex2; switch (MinXvalueEntity-> type) {// arc type entitycaseCK_ARC: RotateVertexFlag = F2dCleanUpArcAngletex (// inputRotategle (// inputRotate , MinXvalueEntity, // output & RotateAxisAngleTemp, &RotateAxisAngleAnotherTemp);break; // line type entitycaseCK_LINE: RotateVertexFlag = F2dCleanUpLineAngle (// inputRotateVertex, MinXvalueEntity, // output & RotateAxisAngleTemp, &RotateAsidesif; 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 = 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; ifgle RotateDiff <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_ent = 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 &T;break; // line type entitycaseCK_LINE: RotateVertexFlag = F2dCleanUpLine Angle (// 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 {// entity_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 = RotateAglesRotate <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; RotateNodesTemp; RotatetexT =; RotateNodesAnother = RotateNodesAnotherTemp; RotateVertexAnother = RotateVertexAnotherTemp; RotateAxisAngleAnother = RotateAxisAngleAnotherTemp; break;} break; caseCK_LINE: switch (RotateVertexFate) {case1: // no changebreak; case2: RotateEntity = Next_Tate; = RotateVertexAnotherTemp; RotateAxisAngleAnother = RotateAxisAngleAnotherTemp; break;} break;} caseCK_LINE: switch (RotateEntity-> type) {caseCK_ARC: if (RotateEntity-> vertex1 == RotateVertex) {RotateEntity = Next_entity; RotateNodes = RotateNodesAnotherTemp; RotateVertexAnother = RotateVertexAnotherTemp; RotateAxisAngleAno ther = RotateAxisAngleAnotherTemp;} break;}}} if (RotateDiffAngleTemp <RotateMinAngleTemp) {RotateMinAngleTemp = RotateDiffAngleTemp; // set rotation entityRotateEntity = Next_entity; RotateNodes = RotateNodesTemp; RotateVertex = RotateVertexTemp; RotateNodesAnother = RotateNodesAnotherTemp; RotateVertexAnother = T entity along the loopF2dCleanUpFindOutNextEntity (// input RotateEntity, RotateNodesAnother, RotateVertexAnother, &RotateAxisAngleAnother); return 0;} / * =========================== =============================== Function: Name: TestFindArrowControl Description: Manual function. Find all arrow-type entities for the view. Return value: <0: error = 0: no process> 0: completed successfully; count is the counter value of the found entity. Parameters: Subfunction: struct node_list * F2dCleanUpPickUpAllOneSideOpenEntity Find a one-sided open entity. int F2dCleanUpFindArrow Find arrow type entity. int F2dCleanUpFindArrowEndEntity finds the arrow end line. int F2dCleanUpFindArrowCenterEntity Find the arrow center line. int F2dCleanUpFindArrowOneSideOpenEntity Find a one-sided open entity with an arrow type. int F2dCleanUpComputeCenterLineAngle Calculates the center line angle. int F2dCleanUpCheckStartEndEntity Check start and end entities. int F2dCleanUpLineAngle Calculates the angle of a line type entity. int F2dCleanUpArcAngle Calculates the angle of an arcuate entity. int F2dCleanUpChangeChildrenFlag Changes the children flag of the entity. int F2dCleanUpChangeArrowVertexFlag Changes the arrow vertex flag and sets the arrow center line coordinates. int F2dCleanUpChangeDrawingColor Changes the entity color. double F2dCleanUpLineLength Calculates the length of a line type entity. ================================================== ============== * / 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 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 count;} / * ====================================== =========================== Function: Name: TestFindOneSideOpen2Control Description: Manual function. Find all entities that are open on one side and cross the view boundary. Return value: <0: Error = 0: No process Parameter: Subfunction: int F2dCleanUpFindOneSideOpenEntity2 Find all entities that are open on one side and cross the view boundary. int F2dCleanUpChangeDrawingColor Changes the entity color. ================================================== ============== * / 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;} / * ============================= ============================= Function: Name: TestFindOneSideOpenControl Description: Manual function. Find a view that is open to one side and perpendicular to an arrow-type entity. Return value: <0: error = 0: no process> 0: completed successfully; this number is the number of entities found. Parameters: Subfunction: struct node_list * F2dCleanUpPickUpAllOneSideOpenEntity Find a one-side open entity. int F2dCleanUpChangeChildrenFlag Changes the children flag of the entity. int F2dCleanUpChangeDrawingColor Changes the entity color. int F2dCleanUpFindOneSideOpenEntity Find one-sided open entities and they are perpendicular to the arrow-type entity. ================================================== ============== * / intTestFindOneSideOpenControl (int * SwitchRedraw) {// external functionsint F2dCleanUpFindOneSideOpenEntity (); int F2dCleanUpChangeDrawingColor (); struct node_list * F2dCleanUpPickUpAllOneSideOpenEntity (); // entities counter = 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;} / * ============================= ============================= Function: Name: F2dCleanUpPickUpAllOneSideOpenEntity Description: All of the selected diagrams Seek one side open entity. Return value: = 0: Completed successfully; Parameter: Input: In_drawing: Figure output: NodeList: Node list for all one-side open entities =================== ============================================= * / 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 for the 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;} / * =========================== =============================== Function: Name: F2dCleanUpPickUpAllArcEntity Description: All of the selected diagram Find the arc entity. Return value: = 0: Completed successfully; Parameter: Input: In_drawing: Figure output: NodeList: Node list for all arc entities ===================== ==================================== * / 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;} / * =============== ================================================== Function: Name: F2dCleanUpFindCenterLineEntity Description: Find the arc center line entity. Return Value: = 0: Completed successfully and nothing is found. = NUM: Number of open entities Subfunction: int F2dCleanUpChangeChildrenFlag Set a flag for unused entities. doubleF2dDistancePointLine Calculates the distance from the center point of the arc to the entity. Parameters: Input: 1 In_Drawing: a Figure 2 In_Entities_list: Node list for all arcs ================================ ======================== * / 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 con nected 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-> pare nt->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);continue;} // 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;} / * ===================== ===================================== Function: Name: F2dCleanUpIdentifySideEntity description : Find the inside entity for the outside loop. Return Value: = 0: Completed successfully, nothing found; = NUM: Number of open entities Subfunction: int F2dCleanUpChangeChildrenFlag Set flags for unused entities. Parameter: Input: 1 In_Drawing: a Figure 2 In_Entities_list: Node list for outer loop ================================ ======================== * / int F2dCleanUpDetectnSideEntity (struct drawing * In_drawing, struct node_list * In_Entities_list) {// external functionsint F2dCleanUpChangeChildrenFlag (); // link list and temp liststruct node_list * temp_list, * temp_list2, * 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 = NewGr oup; 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;} / * ================== =============================================== Function: Name : F2dCleanUpFindOnesideOpenConnectEntityNext Description: Find the next entity connected to a one-side open entity. Return Value: = Out_entity: Completed successfully; Parameter: Input: 1 In_entity: 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;} / * ==== ================================================== =========== Function: Name: F2dCleanUpFindOnesideOpenConnectEntity : Obtaining one side open entity and a single entity connected to it. . Return value: = 0: Completed successfully; Subfunction: struct node * F2dCleanUpFindOnesideOpenConnectEntityNext Find the next entity connected to a one-side open entity. Parameters: Input: 1 In_drawing: Figure ========================================== ===================== * / 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;} / * ============================ ============================== Function: Name: F2dCleanUpFindLongestEntity Description: Longest for the diagram Ask for an entity. Return Value: = Entity: Completed successfully; = 0: No entity; Parameter: Input: 1 In_drawing: Figure ========================= ================================ * / struct node * F2dCleanUpFindLongestEntity (struct drawing * In_drawing ) {// selected entity and temp entitiesstruct node * entity, * LongestEntity; // definedoubleLongestLength = 0.0, ArcLength = 0.0; // check all of entities on 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;} / * ========================== ================================ Function: Name: F2dCleanUpFindViews Description: View to view Ask for a group. Return value: = Entity: Completed successfully; = 0: No entity; Subfunction: struct node * F2dCleanUpFindLongestEntity Find the longest entity for the diagram. struct node_list * F2dCleanUpFindGroup Find the group entity connected to the input entity. struct node * F2dCleanUpFindGroupMinX Determines the minimum X value for the entity group. int F2dCleanUpFindOutSideLoop Determines the minimum X value for an entity group. int F2dCleanUpLocateInsideEntity for outer loop parameter. Parameters: Input: 1 In_drawing: Figure ========================================== ====================== * / int F2dCleanUpFindViews (struct drawing * In_drawing) {// external functionsstruct node * F2dCleanUpFindLongestEntity (); struct node_list * F2dCleanUpFindGroup (); struct node * F2dCleanUpFindGroupMinX (); int F2dCleanUpFindOutSideLoop (); int F2dCleanUpDetectnSideEntity (); // 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 entityViewG roup = 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) find view Entity% d ", CountPrompt); ck_prompt (message); # endif} if (NoGroup == 0) return-1; elsereturn0;} / * ================ ================================================= Function : Name: F2dCleanUpFindRelativeViews Description: Relative view is calculated. Return Value: = 0: Completed successfully; = 1: A relative view is found. Parameters: Input: 1 In_Drawing: Figure 2 In_Group: Group 3 In_ToleranceViews: Tolerance for View ================================ ========================= * / 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;} / * ============ ================================================== === Function: Name: F2dCleanUpFindViewsRelation Description: Obtains the view relation for the figure. Return Value: = 0: Completes successfully, but nothing is found. ; = NUM: Number of views Subfunction: int F2dCleanUpFindRelativeViews Finds relative views. Parameter: Input: 1 In_Drawing: a diagram ========================================= ======================= * / int F2dCleanUpFindViewsRelation (struct drawing * In_drawing) (// external functionsint F2dCleanUpFindRelativeViews (); // link list and temp liststruct group * MaxGroup, * TempGroup, * NextGroup; struct group_list * OpenGroupList, * TempOpenGroupList, * TempGroupGroup; 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> Bi ggestSize) {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-> inde x = 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 valu e 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;} / * ======================================== ========================= Function: Name: F2dCleanUpFindDrawingSheet Description: Obtains a drawing sheet for the figure. Return value: = -1: Error data; = 0: Completed successfully; = 1: No sheet; Subfunction: struct node_list * F2dCleanUpFindGroup Find the group entity connected to the input entity. Parameters: Input: 1 In_drawing: Figure ========================================== ===================== * / 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 VELLUMCountPrompt ++; 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;} / * ========== ================================================== ==== Function: Name: TestFindDrawingSheetControl Description: Manual function. Find the drawing sheet for the figure. Return value: <0: Error = 0: No process> 0: Completed successfully; the count is the counter value of the found entity. Parameters: Subfunction: int F2dCleanUpFindDrawingSheet completed successfully; count is the counter value of the found entity. intF2dCleanUpChangeDrawingFlag Change entity flag (4 >> 3) ===================================== ==================== * / intTestFindDrawingSheetControl (int * SwitchRedraw) {// external functionsint F2dCleanUpFindDrawingSheet (); int F2dCleanUpChangeDrawingColor (); intF2dCleanUpChangeDrawinglag (); // 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, --------------------------------- // 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;} / * =================== ============================================== Function: Name: TestFindViewsControl Description: Manual function. Find the drawing sheet for the figure. Return value: <0: Figure = 0: No process> 0: Completed successfully; count is the counter value of the found entity. Parameters: Subfunction: int F2dCleanUpFindViews Determines the group of views for the diagram. int F2dCleanUpFindViewsRelation Finds the view relationship for the diagram. 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;} / * ======================================== ========================= Function: Name: TestFindBoundaryControl Description: Manual function. When the user selects a view boundary entity, this function finds all of the connected entities for the view. Return value: <0: Error = 0: No process> 0: Completed successfully; Successful completion Parameters: Subfunction: int F2dCleanUpFindOutSideLoop Find the side loop entity. int F2dCleanUpLocate the side entity for the outer loop. int F2dCleanUpFindOutNextEntity Find the entity connected to the outer loop entity. struct node * F2dCleanUpFindGroupMinX Determines the minimum X value for the entity group. struct node_list * F2dCleanUpFindGroup Find the group entity connected to the input entity. ystruct node * F2dCleanUpInputEntity (old function) Find the selected entity on the screen. intF2dCleanUpLineAngle Calculates the angle of a line entity. int F2dCleanUpArcAngle Find the angle of an arc entity. int F2dCleanUpChangeChildrenFlag Changes the children flag of the entity. int F2dCleanUpChangeArrowVertexFlag Changes the arrow top vertex flag and sets the arrow center line coordinates. int F2dCleanUpFindViewsRelationl Calculates the view relation for the figure. int F2dCleanUpChangeColor Changes the entity color. double F2dCleanUpLineLength Calculates the length of a line entity. ================================================== ============== * / intTestFindBoundaryControl (int * SwitchRedraw) {// external functions int F2dCleanUpChangeDrawingColor (); int F2dCleanUpFindOutSideLoop (); int F2dCleanUpDetectnSideEntity (); int F2dCleanUpFindViewsRelation (); int 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 entitiesF2dCleanUpfindnSideEntity (& 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. #endif} return count;} / * ========================================= ======================== Number: Name: TestFindCenterLineControl Description: manual function. Find the centerline for all arcs in the view. Return value: <0: Error = 0: No process> 0: Completed on success; Parameter completed on success: Subfunction: struct node_list * F2dCleanUpPickUpAllArcEntity Finds all arc entities in the selected diagram. int F2dCleanUpChangeDrawingColor Changes the entity color. ================================================== ============== * / 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;} / * ================================================ ================= Function: Name: TestFindOneSideOpenConnectControl Description: Manual function. Find a one-side open connection entity. Return value: <0: Error = 0: No process> 0: Completed successfully; the number is the counter value of the found entity. Parameters: Subfunction: int F2dCleanUpFindOnesideOpenConnectEntity Finds one open connection entity. ================================================== ============== * / 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;} / * ======== ================================================== ======= Function: Name: TestFindSameColorControl Description: Manual function. Find entities of the same color. Return value: = 0: completed successfully; the number is the counter value of the found entity. Parameters: Subfunction: struct node * F2dCleanUpInputEntity (old function) Find the selected entity on the screen. int F2dCleanUpFindSameColorEntity Find entities of the same color according to the selected entity. int F2dCleanUpChangeDrawingColor Changes the entity color. ================================================== ============== * / 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;} / * ============================================ ===================== Function: Name: TestFindSelectSingleControl Description: Manual function. Find the used entity. Return value: = 0: Completed successfully; Parameters: Subfunction: struct node * F2dCleanUpInputEntity (Old function) Find the selected entity on the screen. ================================================== ============== * / 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;} / * ===================== ===================================== Function: Name: TestUnselectSingleControl description : Manual function. Clear the used entity. Return value: = 0: Completed successfully; Parameters: Subfunction: struct node * F2dCleanUpInputEntity (old function) Find the selected entity on the screen. ================================================== ============== * / 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;} / * ================================ ================================= Function: Name: TestClearKeepFlagsControl Description: Manual function. Returns all selected entities. Return Value: = 0: Completed successfully; Parameter: Subfunction: int F2dCleanUpClearDrawingKeepFlags Changes the entity color based on it, but keeps the flag. ================================================== ============== * / 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 CK * SwitchRedraw == 1) ck_levels (CK_ON, TrimLevel, TrimLevel); if (* SwitchRedraw == 1) ck_redraw (CK_PRIME_VP); # endifreturn0;} / * ================ ================================================= Function : Name: TestClearControl Description: Manual function. Restore all selected entities. Return Value: = 0: Completed successfully; Parameters: Subfunction: int F2dCleanUpClearDrawingEntity Returns the entity color. ================================================== ============== * / 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;} / * ============================= ==================================== Function: Name: TestDeleteControl Description: Manual function. Delete all selected entities. Return value: = 0: Completed successfully; Parameter: Subfunction: int F2dCleanUpDeleteDrawingEntity Deletes all entities. ================================================== ============== * / 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, Switch 1) ck_redraw (CK_PRIME_VP); # endifreturn0;} / * ===================================== ============================ Function: Name: TestBackColorControl Description: Restore. Return Value: = 0: Completed successfully; Parameter: Subfunction: int F2dCleanUpUndo Restore original. ================================================== ============== * / intTestBackColorControl (int * SwitchRedraw) {// external functionsint F2dCleanUpChangeDrawingColor (); if (* SwitchRedraw == 1) F2dCleanUpChangeDrawingColor (&trim_drawing);return0;} / * = ================================================== ============== Function: Name: TestUndoControl Description: Restore to the original. Return Value: = 0: Completed successfully; Parameter: Subfunction: int F2dCleanUpUndo Restore original. ================================================== ============== * / 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); = 1) ck_redraw (CK_PRIME_VP); # endifreturn0;} / * ==================================== ============================= Function: Name: TestUndoPreControl Description: Prepare to undo. Return value: = 0: Completed successfully; Parameter: Subfunction: int F2dCleanUpUndoPre Prepare to restore. ================================================== ============== * / 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;} / * =========================== =============================== Function: Name: TestSetUndoFlagViewsControl Description: Flag to restore Set. flag = 0: No view exists. flag = 1: View exists. Return Value: = 0: Completed successfully; Parameters: ===================================== ==================== * / intTestSetUndoFlagViewsControl (int * SwitchRedraw) {// set flag F2dCleanUpExcutedNo = 1; return0;} / * functions : ================================================= =============== Name: TestDeleteViewsControl Description: Delete the view. Return Value: = 0: Completed successfully; Parameters: Subfunction: int F2dCleanUpDeleteViews Delete view. ================================================== ============== * / 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;} / * ================================================== =============== Function: Name: F2dVector Description: Calculates the unit vector of the line. Return Value: = Out_v: Completed successfully; Parameter: Input: 1 In_sp: Line entity start point coordinate 2 In_ep: In entity end point coordinate output: 1 Out_v: Line entity vector =========== ================================================== == * / 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;} / * ======================================= ========================== Function: Name: F2dVectorUnit Description: Calculates the unit vector of the line. Return Value: = Out_n: Completed successfully; <0: Error parameter: Input: 1 In_v: Line entity vector Output: 1 Out_n: Line entity unit vector =========================== =============================== * / 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;} / * ========== ================================================== ===== Function: Name: F2dDistancePointLine Description: Calculates the distance from a point to a line. Return value: = 0: Completed successfully; Parameter: Input: 1 In_sp: Line entity start point coordinate 2 In_ep: Line entity end point coordinate 3 In_p: Point coordinate output: 1 Out_d: Distance ======== ================================================== ====== * / 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;}
Appendix E
Example of bend model view implementation; including implementation of CBendCADViewPart member function and implementation of menu driven function.
[0295]
// # 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,0x C0, 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 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 = TRU E; 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. 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; 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; 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 {// t_part_ 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_d_ at_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_d_____ (! 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_of_to_to_to_to_to_to_to_to_to_to_to_to_to_to_to_to_to_to ; 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. 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; m3_3__ 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; _ = 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);}} 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 _) _ md_ (! 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; ; 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_td; * part = NULL; CBendCADDoc * pDoc = GetDocument (); ASSERT_VALID (pDoc); part = pDoc-> get_part (); if (! part) {mi_part_i s_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_ma __________________ = m_flat_part_centroid; if (! mi_show_solid) (// Compute the flat's display list. 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. ) {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_ base_clump; flat's base clump. RwAd dClumpToScene (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 = ______ = 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_list_up_to_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_d (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 RwAddClumpToScene (m_scene, m 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_vol1]; 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_voltrix2 () 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 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_to_date_to_date_ ; 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 = ____ return_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 () ; 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_ 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; // the set 3 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_clup) _______________________ } 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); 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 :: On_b = 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 * 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. 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. 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/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_ro t_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 (f), 1.0, RwRotateMatrix (f), 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_rottrixmatrix (RwRuplicate) / 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); // Rotatio n 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 = _angle = 0.0__angled = 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 (RwStrixchMa / (Pw) // 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 partre } COrthoViewDlg orhodlg (NULL, GetDocument ()-> get_part (), this); int ret = orhodlg.DoModal (); // if we are in a Clien t 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; mdtrix zwangle = 0.0; (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 = 0.0; md_x; ), 0.0f, 1.0f, 0.0f, CREAL (md_y_angle), rwREPLACE); if (md_rot_matrix) RwDestr oyMatrix (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.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_trix ); md_rot_matrix = RwDuplicateMatrix (RwScratchMatrix ()); OnZoomAll ();} void CBendCADViewPart :: OnRotate () {ml_last_function_chosen = ROTATION_MODE; mi_bbox_is_up_to_date = 0;} void CBendCADViewPart :: UIUpdatep 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_) )? TRUE: FALSE);} // T his 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 (RwScratchMatrix ( ), md_rot_matrix, rwPRECONCAT); if (md_rot_matrix) RwDestroyMatrix (md_rot_matrix); md_rot_matrix = RwDuplicateMatrix (RwScratchMatrix ());} // glPushMatrix (); // glLoadIdentity (); // glRotangle (_), 1.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 } // 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_r egion_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])); glMatrix Mode (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_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. ]);} 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_vol0] ,-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 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], 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 rix_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 (_); glPushis (_); 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. rwPRECONCAT); RwTranslateMatrix (RwScratchMatrix (), CREAL (-m_part_centroid.X ()), CREAL (-m_part_centroid.Y ()), CREAL (-m_part_centroid.Z ()), rwPRECONCAT); // RwForAllClumpsInScenePointer__ (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 (); // remember the current modeling matrix of 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), rwREPWRMatrix (R) ), md_rot_matrix, rwPRECONCAT); RwTranslateMatrix (RwScratchMatrix (), CREAL (-m_part_centroid.X ()), CREAL (-m_part_centroid.Y ()), CREAL (-m_part_centroid.Z ()), rwPRECONCl); 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 if (mi_simulation_is_on) (if (m_sim_base_clump) RwRemoveClumpFromScene (m_sim_base_clump); if (mi_show_3d) (m_3d_base_clump; RwAddClumpToScene (m_scene, m_base_cl__; Now draw the part.RwInvalidateCameraViewport (m_camera); RwBeginCameraUpdate (m_camera, (void *) m_hwnd); RwClearCameraViewport (m_camera); i = RwGetSceneNumClumps (m_scene); // Render the scene. (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 [ ); 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 = the color set 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. 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])); glPROX 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 [Mode]; GL_MODELVIEW);}} / * if (size) {for (i = 0; i <size; ++ i) {BM_3D_BODY * b3; long three_d_type; if (selected_items [i * 2 +1]) {// You can get an edge => This is not a trival bend line or forming. 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; // Note: Don't expect the part to be null at this stage. BM_TOPOLOGY * topology = part-> get_topology (); if (! Topology) return; three_d_type = selected_items [i <<1] / 100000; // Terminology note: three_d_type is not real. b3 = topology-> map_id_into_pointer (three_d_type); // up to 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 pi xel 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;} Fix * / 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 the 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 / the results of the // computation are put into thearry bbox_size [3]; if this pointer is zero, no computation // is pe / three-d version's bbox is computed; else, the flat's bbox is computed. rformed. 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 * 3 = dot; , 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. (), dot2.X ()); right = __max (dot1.X (), dot2.X ()); bot = __min (dot1.Y (), d ot2.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, if1; 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. 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; // 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; B M_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 (do t1.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 / * // pointer is supplied. if (threeD_flag) {m_3d_part_centroid.set_X ((right + left) /2.0); m_3d_part_centroid.set_Y ((top + bot) /2.0); // This part has a 3d centroid. 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); // This part is the plane center of gravity is there. 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_bt_down oint; 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_btxpre_v.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_bt_vn_down. (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_To_point_To_corn. 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 cu rrent 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 (), trix rtrix_) (RwScratchMatrix (), CREAL (-m_part_centroid.X ()), CREAL (-m_part_centroid.Y ()), CREAL (-m_part_centroid.Z ()), rwPRECONCAT); RwMatrix4d * inverse = RwCreateMatrix (); RwInvertMatrix (RwS ), 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) (/ 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 ov erflowed. 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 = 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 (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 e dge 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; CBCAD * 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_TY PE_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 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 return edge; / * three_d_name = list_name / 10000; loop_name = list_name% 10000; // edge_name edge loop_name in loop_name-th / = 100; // loop of the three_d_name th three-d-body, edge_name = list_name% 100; // Start with the first bend line as the first three-d-body. if (three_d_name> (ml_num_bendlines + ml_num_faces)) return NULL; // What is drawn is the forming. if (! loop_name) return NULL; // What is drawn is a trivial bend line. if (three_d_name> ml_num_bendlines) {// three_d_body is a face. 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 is a bend line. 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;}} // Has a face / bend line to which the edge belongs at this point. 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 ;}} // At this point we have a loop to which the edge belongs. 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 ();} / * This selects another class You can get a set. Selected items are passed back in the array selected_items_array; it is the user's obligation to ensure that this array is large enough. An array of size num_requested * 2 is certainly enough. This function will pass back to the num_requested item if more is available. The return value is the number of items actually passed back. The format of the returned item in the array is given as follows: selected_items_array [2 * i -2] contains the OpenGL Display List id of the drawn edge, and selected_items_array [2 * i -1] contains the bend model pointer for that edge. For example, selected_items_array [0], selected_items_array [1] are all items up to array [2 * num_requested -2] and array [2 * num_requested -1] for the num_requested-th item in the selection set, such as the selection set. Including. If the edge pointer is NULL, N must also be the edge's openG1 display list id (N is a long type). Case A): If N / 10000> (num_bendlines_in_part + num_faces_in_part), the user picks N- (num bendlines + num faces) forming. For example, edge pointers such as num bendlines = 4, num faces = 3, num formings = 5, N / 10000 = 9, etc. are empty. At this time, the user takes up the second forming. Case B): If (N% 10000) / 100 == 0 (ie, the 100th digit of N is zero), the user is taking the centerline of a trivial bend line. The bend line is the (N / 10000) th bend line. For example, N / 10000 = 3, the edge pointer is NULL, and (N% 10000) / 100 = 0. The user picks up the third bend line that does not happen to bend. (If you are surprised, this part is guaranteed to have at least 3 bend lines.) * / 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_solid = show_3_ ; 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_todate = 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 (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;} RwRemoveClbasemcl_cl_cl 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_basewmclumpe; {// 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_d__ = 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_cent_part_cent_part_cent_part_ ; 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 (! re_turn;} re () re_); ;}
Appendix F
Example of BMAPI that auto-sizes the main including files with comments /
* General notes: --------------- *************** --------------- General notes:-The auto-dimension package assumes that the part has already been updated (ie the 3D version of the part has already been calculated). Take the current 3D version of the part and use it. Automatic dimensioning with -04/02/96 simply generates dimensions for the 3D version of the part. The automatic dimensioning with -04/02/96 assumes that the part is shown with thickness (ie it assumes that we are not showing one side of the sheet). Overview: --------------- *************** --------------- Do two types of drawing:-Flange length for all bend lines-Bend line information for all bend lines Bend line information is drawn in a small info-box that points to the bend line to which it relates. The only problem with rendering this info-box is that the bend line is visible and where it is drawn (ie it looks good and does not interfere with other components, eg other The place on the screen where it is drawn so that it does not overlap with other things), how to relate it to the bend line. This component is relatively easy. The flange length of the bend line is given by the maximum outer distance between the bend line and the adjacent flange on the side of the bend line. Note that a bend line can have at most two adjacent flanges, so the flange length must be drawn for both adjacent flanges. In fact, the flange length is drawn (as a distance) between the points we call dimension points. There are two types of dimension points here. The first is the bend line dimension point. Since the flange length is the (maximum outer) distance between the bend line and the adjacent flange, these dimension points on the sides of the bend line are called bend line dimension points. Their positions are strictly defined by bend lines. Note that a bend line can have exactly two bend line dimension points for each of the adjacent flanges (at least in the current version of BendModel / BendCAD). Each of the two bend line dimension points corresponds to two ends of the bend line. Furthermore, it should be noted that normally these bend line dimension point pairs for both adjacent flanges coincide. That is, there are the same bend line dimension points for adjacent flange A (there are two bend line dimension points for A) and the other bend line dimension points for other adjacent flanges B. That is, they are not particularly identical but have the same value. The bend line dimension point is calculated using an intersection approximation (bend angle is about 90 degrees) or a tangent approximation (when the bend angle is 90 degrees or more). If the bend angle is on the order of 90, the intersection approximation points match, so the bend line dimension point pairs for both adjacent flanges are the same. Another type of dimension point is a flange dimension point. They are the points on the flange adjacent to the bend line on the side of the bend line collar furthest away. If the flange is correct (ie non-empty), there is at least one flange dimension point. In theory, however, there is no upper limit to the number of flange dimension points. Note the following important points: If flange A is adjacent to bend line B and further to its bend line C at its furthest point (ie, at the flange dimension point for B), B's flange dimension point for A is actually C for A Are the same bend line dimension points (or assuming bend lines B and C are parallel, otherwise the situation is tricky, which is no longer true). The flange dimension point is calculated at the corner of the flange, since the dimension must be drawn on the flange side. The following is an automatic dimensioning method. : -------------------------------------- *********** *************************** ----------------------- --------------- It is divided into two different tasks. One is to calculate all dimension points (both bend line dimension points and flange dimension points). At this stage, we calculate all the dimension points that can draw the flange length. Potentially, this can only be done once, and if the part does not change, we can later reuse this information every time an automatic dimension has to be drawn. (However, the part does not normally change-when the user rotates the part, the viewer actually rotates the part, not the camera (which is usually done)), so the 3D coordinates of the part do not change. However, we can do our calculations based on the flat part of the part that is not affected by this kind of change, but fortunately the calculation of all dimension points is quite fast and we recalculate the dimension points at all times. Seems to be possible. I just want to point out that we can save time by precalculating these dimension points once and reusing them later if needed. Once we have calculated all the dimension points, we can draw the dimensions. However, we must first resolve which of the dimension points are visible and which are not. It is fairly easy when you have a broken wireframe image. A dimension point is visible if it is in the view window. This can be checked very quickly. When we have a solid (shaded) image, things are more difficult because the flanges that are closer to the view usually block the views of other flanges that are far away, as well as some dimension points. is there. So we need to do some kind of hidden line removal. Once we determine which dimension points are visible, the flange length can be drawn in a series of different ways, in which case we must pick one, preferably the best one. Note: Bend line dimension points and flange dimension points are required to indicate the flange length. One heuristic is given by using bend line-flange-dimension points that are close to the viewer and have the smallest sideway distance. If we take the dimension points for all the bend lines, we can draw the dimensions. Main data structure of automatic dimensioning: ---------------------------------------- ** ************************************** ------------ ---------------------------- There are three types of objects to be used. BM_AUTO_DIMENSION ----------------- BM_AUTO_DIMENSION is a top-level Auto-Dimension object, usually part of a BendCAD document along with BM_PART. It includes a pointer to BM_PART where the automatic dimensions are drawn, as well as a document, view and device context pointer. It also contains high level information such as view window size, number of bend lines, BM_AD_bendline objects, etc. In the future (currently 04/03/96), it should store information about pen and brush characteristics such as line color, line width, font size, etc. BM_AD_bendline ------------- BM_AD_bendline stores all automatic dimension information related to one BM AD bendline. There are also two built-in bend line dimension points for each of the adjacent flanges. It also has a point to a list of flange dimension points for each of the adjacent flanges. BM_AD_dim_corner ---------------- BM_AD_dim_corner is a dimension point (either bend line or flange). A dimension point can have either 1 or 3BM_POINT. One important member of the dimension point is the opening direction. It indicates the direction in which the actual dimension for this dimension point must be drawn. Furthermore, it indicates the direction in which this dimension point is visible. If it is visible, it stores all screen coordinates of that 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; / *********** ********** * ********* ********** ********** ********** ********** * ********* ********** Automatic Dimension Constant ********* ********** ******** ** ********** ********** ********** ********** ******** ** ********** * /// 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_TOLERANCE 001 / *********** ********** ********** ********** ******* *** ********** ********** ********** ********** Represents a dimension point where a dimension can be drawn. ********** ********** ********** ********** ********** ********** ********** ********** ********** * / class BM_AD_dim_corner {friend BM_AUTO_DIMENSION; friend BM_AD_bendline ; / *********** ********** ********** ********** ******* *** ********** ********** ********** ********** All data members are private Is. ********** ********** ********** ********** ********** ********** ********** ********** *********** / 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 only compute 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 // | bb // | bb // bb // bb // p1 FFFFFFFF // FF // FF // FF // FF / / FF // // 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 on the 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 Member function. Used only by automatic dimensions. ********** ********** ********** ********** ********** ********** ********** ********** *********** /// 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_nge_dim _ * _ flare_best_ * 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 member functions ********** ********** ******** ** ********** ********** ********** ********** ******** ** *********** / 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 is for ain this dimension in // 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_end_to 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 defined by 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);}; / *********** ********** ********** **** ****** ********** ********** ********** ********** **** ****** This type of object represents auto-sizing data for one bend line. The basic AD operation for bend lines is to draw adjacent flange lengths. Technical note:-t Bend line dimension point and flange dimension point opening direction vector are not correlated. It should you check against two points with the same opening direction. -Algorithm: First, we calculate all bend line dimension points for all bend lines. Next, we calculate all flange dimension points for all bend lines. The reason is that when we calculate the flange dimension points, there are several edges in the flange and adjacent to other bend lines. When all bendline dimensions are calculated first, these vectors can be taken from the bendline dimension points of other BM_AD_bendline structures. ********** ********** ********** ********** ********** ********** ********** ********** ********** * / class BM_AD_bendline {friend BM_AUTO_DIMENSION; friend BM_AD_dim_corner ; / *********** ********** ********** ********** ******* *** ********** ********** ********** ********** All data members are private Is. ********** ********** ********** ********** ********** ********** ********** ********** *********** / private: / ***** ****** ********** ********** ********** ********** **** ****** ********** ********** ********** These data members are set by the constructor. ********** ********** ********** ********** ********** ********** ********** ********** *********** /// 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; / *********** ********** ********** ********** ** ******** ********** ********** ********** **********these The data member has a bendline dimension point data structure, BM_AD_bendline :: compute_BM_AD_bendline (. . . ). Calculated when calculated with. ********** ********** ********** ********** ********** ********** ********** ********** *********** /// 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; / * These parameters are often calculated during the process and are needed later, so for performance reasons we don't have to recalculate them later To store. Each of them is a vector pointing towards the neighbor (from the bend line) and lies on a plane tangent to the end point of the bend arc contacting the neighbor. These are some of the main data structures. For each neighbor, it has two endpoints, one for each endpoint (ie, left and right) of the bend line. These points specify the point at which the dimension for the flange length can be drawn at the bend line (ie, at the side of the bend line). Note: Currently (04/02/96) we consider exactly two possible points to draw dimensions on all bend lines. These two points are the two extreme points of the bend line in the direction of the bend line center line. Note: These are called bend line dimension points for bend lines. Note: These points are always calculated, even if adj body1 and adj body2 are empty. * / 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 each 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; / * Here are two lists of dimension points. One is related to adj-body, and the other is related to adj-body2. Both lists contain points that are flange length dimension points. Note: These are called bend line flange dimension points. * / BM_AD_dim_corner * body1_points; BM_AD_dim_corner * body2_points; / *********** ********** ********** ******** ** ********** ********** ********** ****************** ** These data members are used when the dimension is drawn. ********** ********** ********** ********** ********** ********** ********** ********** *********** /// 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 what 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 Member-Function ************ ********** ********** ****** **** ********** ********** ********** ********** ****** ***** /// 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 member-function ************ ********** ********** ********** ****** **** ********** ********** ********** *********** / public: // some trivial constructors, destructors. BM_AD_bendline (BM_AUTO_DIMENSION * owner, BM_BENDLINE * bendline); ~ BM_AD_bendline (void);}; / *********** ********** ********* * ********** ********** ********** ********** ********* * ********** This object can be used to generate an automatic dimension for a part. ********** ********** ********** ********** ********** ********** ********** ********** ********** * / class BM_AUTO_DIMENSION {friend BM_AD_dim_corner; friend BM_AD_bendline ; / *********** ********** ********** ********** ******* *** ********** ********** ********** ********** All data members are private is there. ********** ********** ********** ********** ********** ********** ********** ********** *********** / 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_pFlangeFontp; CFont ** / line and arrow parameters // int m_nLineStyle; int m_nLineWeight; // in pixelsint m_nArrowStyle; int m_nArrowAngle; // in degreesint m_nArrowLength; // inpixels / *********** ******* *** ********** ********** ********** ********** ******* *** ********** ********** Private Member Function ********** ********** **** ****** ********** ********** ********** ********** **** ****** *********** / private: // This function is used to propagate the effects of drawing a flange length for a given bendline, // to ac count 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_dimerpoints * nd_point_dim_corner * s , 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 member function ************ ********** ********** ********** ***** ***** ********** ********** ********** *********** / 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
Appendix G
An example of automatic sizing drawing function. These functions assume that dimension points have already been calculated.
[0296]
/// * Functions to calculate dimension points are in AD_POINTS.CPP. First, it is necessary to detect which dimension points are visible or not. Next, we must determine how to draw the flange length dimension. * / # 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 Class Staff **** ****** ********** ********** ********** ********** **** ****** ********** ********** *********** // * This function calculates the visibility of dimension points To do. * / 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; / * The wireframe doesn't check if this dimension point is actually the frontmost 3D body (original text unknown) In wireframe mode, We assume that everything in the view window is visible. * /// 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; / * Parts shown in solid mode * / 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_visiblej->))-> find_second_lowest_id_adj_body (); visible_bodies [3] = NULL;} else visible_bodies [1] = NULL; // handlecases when there is just one point differently fr om 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 {/ * Solid finding method: This is a new version that manipulates solid mode. First, it is checked whether all three points p, p1 and 2 are in the view window. If true, we calculate the center point of the bend arc side profile and check if the bend line at this point is actually visible. * / i = view-> map_point_to_closest_edge (p, & screen_x, & screen_y, & z_buf_value, NULL); if (! i) return; / * Solid detection method: If the opening direction cannot be reversed, check if it is not instructed To do. 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; // where a certain large difference /// Open direction is indicated} * /// 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; / * This is an old version that operates solid mode. Here we check whether the point p is in the view window, and further check whether the points p1 and p2 have an underlying visible 3D body. // If we have 3 points, the point p is not on the 3D body. Therefore we only check if it exists. // In the view window. view-> is_3d_body_near_point (p, NULL, & i, & screen_x, & screen_y, &z_buf_value); if (! i) return; // The points p1 and p2 must be on the 3D body. 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_f2, & _! i) return; * /} // process visibility datapos_len = neg_len = 0.0; visible = 1;} / * This function draws a dim-point in the given device context. This is actually a debug function. * / 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_ & 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;} elres 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);} / * This function draws one flange length dimension. The first argument is a bend line dimension point and the second is a flange dimension point. * / 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, halfOOL_line; / 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 re versethe 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:} _ 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)) retu rn; 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_p; 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_x_end_x_end_x_end_x_end_x_end_x_end_x_end_x_end_x__ ; 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, 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 an arrow. * /// 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);} / * If you need to draw p1 and p2 in bend-dim-points * / points [1] .x = bend_dim_point->screen_x; points [1] .y = bend_di m_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); / * If you need to draw p1, p2 for flange-dim-points * /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);} / * Bendra Given a dimension point and a flange dimension point, this function returns TRUE if there is a way to display the flange-length-dimension using these points (ie, everything is visible) or If not, return FALSEWO. If it is TRUE, it also returns the best flange dimension point; as well as the distance between the bend line dimension point p and the best flange dimension point p with respect to the bend line dimension point. The best distance returned can be negative due to the K factor for bendline-dimension-opening-direction-vector. Here this function is drawn so that dimension-extension-lines: one dimension-extension-line is unit length and the other is as long as necessary to reach the first Assume that. That is, the function draws a dimension arrow adjacent to one of the dimension points. That is, it does not attempt to draw a dimension point at some point in the middle of the line between two dimension points. Recall: bendline-dimension-opening-direction-vector should be standardized. Note: Here this function has dimension-extension-lines so that one dimension-extension-line is the unit length and the other is as long as necessary to reach the first one Assume that it is drawn. That is, the function draws a dimension arrow adjacent to one of the dimension points. That is, it does not attempt to draw a dimension point at some point in the middle of the line between two dimension points. Note: In this function, if the dim point is not visible, do not check directly (call another function). Check if there are some dimension-extension-lines in the displayed window. Note: This function checks where the dimension arrow advances. They are required to be strictly within the view area. Note: This function actually uses approximate positions. That is, as a discovery method. * / 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 / * best found flange-dim points distance * /, BM_dim _ ** _ best_dim_nge _ ** _ 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; / * Solid finding method: In solid mode, we use this heuristic to save time. When two bend lines are using (potentially) equivalent flange-dimension points to display the flange length, we simply have a bend line with a higher idx (of these two bend lines) Calculate visibility only for. * / 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 Class Staff ********** ********** ***** *************** ********** ********** ********** ***** ***** *********** // * This function calculates the visibility of all bend line dimension points in the bend line. Note: To save time, we check whether the left (right) points of fields 1 and 22 are equivalent. * / 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 a 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_2_point_left_screen_2) .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_point_screen_x2 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 == bend_right_1 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} / * This function is strictly for one bend line Cormorant. Important: It simply determines which method is best, but AD does not actually determine whether or not to do so. Here it implements some way of updating other data structures. In short, it does not change any of the AD data structures. Note: No checks are made at first. Idea: In this function, we use a heuristic that assigns values for different bend-flange-dim point combinations. In the end, we choose the best combination. The heuristic we use is a combination of the distance between the bend and flange dim point, the bend-point distance from the plus-view screen. Practical trick: First we check whether the best known distance value is already zero. If 0, we will try to find the best match for the other bend-dim points only when this new bend-dim point has a good z-buf value. Note: After a four-part test, I find this just gives a very slight improvement. It is probably 5-10% KK (original text unknown). * / void BM_AD_bendline :: 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 and 1 are bend-dim structures, 3 Is the flange-dim point, 4, 5 is the flange list * /, double distance_and_z [4] / * 0,1 is the distance, 3 and 4 are z-buf * /) {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_complier_best_dim -> view, & bend_body1_point_left, body1_points, parent-> object_space_per_pixel, & best_distance, & best_fdp)) (best_distance = fab s (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_andzand_distance_distance_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_and_distance_and_distance ] = 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_right_dim_pair_right_dim object_space_per_pixel, & best_distance, & best_fdp)) (best_dist ance = 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_andzand_distance_distance_ [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_and_distance_andstance ] = 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-> ob ject_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_pointz [1] _stance_distance_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_and_distance_ ] = 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_right_dim_pair_parent_body_, > object_space_per_pixel, & best_distance, & best_fdp)) (best_dis tance = fabs (best_distance); // check if 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_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_pointz_1_stance_distance_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_andstance1; ] = bend_body2_point_right.z_buf_value;}}}}} / * This function determines how to draw the flange length for the bend line. This is different from previous functions that use functions prior to subroutines. It determines how to draw the flange length dimension for the bend line, and thus how to update all data structures. Furthermore, it allows for simultaneous bend lines. * / 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}; / * Calculate the best way to draw the flange length. Consider simultaneous bend lines. * /// 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-> compute_dim_points_to_display_indiv (best_AD_bendline, bodies_bend_flange_list, distance_and_z);}} / * Mark all other bend lines in a simultaneous bend as "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 [nge_end_list_b 1]; bl-> drawn_flange_dim_point2 = bodies_bend_flange_list [3];}}}} / * Mark this bend line against the figure. * / 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_end1 [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 [flange_list [3] Check if it is adjacent to the line. Here we do not check for simultaneous bends, because they should have exactly the same flange list as we now have here. * / 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_bendline0 ->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_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 [best_AD_bendline [5] bend, best_AD_bendline [1]-> adj_body2, bodies_bend_flange_list [1], bodies_bend_flange_list [3], temp_point->adj_bendline);}}} / * This function draws the flange length for this bend line. It uses information calculated by the compute dim points to display () function. TODO: In this function, we can keep a track with bendline dimension points already drawn. The bend line dimension points for adj-body1 and adj-body2 match. In that case, you should actually draw it only once. * / 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. ******** ** ********** ********** ******************** ******** ** ********** ********** *********** // * This is a debugging function. * / 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 (space, per_pixel_object_space) );}} 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);}}}} / * This function is for all bend lines Draws an info-box with bend line data. Idea: We do not check the bounding box of the visible part of the view area, as renderware does not present that kind of information in solid mode. In addition, often the user zooms in to see a dimension of a part, in which case there are no parts of the viewport that are not covered by the part, ie the bounding box covers the entire bee area and is practically useless. Instead, we are drawing a bend line info box along the edge of the view area. We divide the view area into four areas and place bend line info boxes in those areas no matter which one is closer to the bend point to which the info-box is concerned. Here, of course, we draw those boxes along the left-right vertical edge of the viewport. * / 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 columns of text * /; 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; / * Calculate the number of bends we can display. * / 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; / * Allocates space to store the endpoint's y coordinate. * / 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_ / out ofdelete space) [] 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;} / * Collect point pointers. * / 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_body1_point_right) .z_buf_value) bend_points [j] = & (bends [i]->bend_body1_point_left); else bend_points [j] = & (bends [i]->bend_body1_point_right);}} else bend_point [j] = & (bends [i]->bend_body1_point_right); if (++ j> = num_bends_to_be_drawn) break; // point out according to which side of the screen the info-box should be Classify. bend-line-dim-point includes all boxes that are not on the left side of the screen (at least in the beginning). * / int half_screen = (view_size_x >>1); i = 0; // i will be topj = num_bends_to_be_drawn-1; // j will be bottom // we will use these to temporarily store stuffBM_AD_bendline * p_bend; BM_AD_dim_corner * p_bend_point; while (i <j) (while (i <j && bend_points [i]-> screen_x <half_screen) i ++; while (i <j && bend_points [j]->screen_x> = half_screen) j--; // switch i and jif (i <j) {p_bend = bendlines [i]; p_bend_point = bend_points [i]; bendlines [i] = bendlines [j]; bend_points [i] = bend_points [j]; bendlines [j] = p_bend; bend_points [j] = p_bend_point;}} if (bend_points [i]-> screen_x <half_screen) i ++; // i points to the first info-box on the right side / * Check that neither side (ie left-right) has too many info-boxes. * / if (i> half_max_num_info_boxes) (// too many boxeson the left side.// sort them according to x-coordinates.// this way wewill move points with the largest x-coordiates to the right side.for (j = 0; j <i; j ++) bend_y_coordinates [j] = bend_points [j]->screen_x; DBM_QuickSort_double (bend_y_coordinates, (unsigned long) i, (long *) bendlines); i = half_max_num_info_boxes;} else if ((num_bendsmax_to_be_n ) (// too many boxes on the right side.// sortthem according to x-coordinates.// this way we will move points with the smallest x-coordiates to the left side.for (j = i; j <num_bends_to_be_drawn; j ++) bend_y_coordinates [j] = bend_points [j]->screen_x; DBM_QuickSort_double (bend_y_coordinates + i, (unsigned long) (num_bends_to_be_drawn-i), (long *) (bendi____ ;} // it could have been that when we chose a point fora bendline, it is not the best point.// (although this point was used to place this point on the left-right side) .// imagine a point on it could be that both endpoints are visible, but // out point is not the best, because the other endpoint of the bendline is actually to the // left of our point.for (j = 0; j <i; j ++) (// check if we have choiceif (! (bendlines [j]-> bend_body1_point_left) .visible ||! (bendlines [j]-> bend_body1_point_right) .visible) continue; if ((bendlines [j] -> bend_body1_point_left) .screen_x <(bendlines [j]-> bend_body1_point_right) .screen_x) bend_points [j] = & (bendlines [j]->bend_body1_point_left); else bend_points [j] = & (bendlines [j]->bend_body1_point_right);} for (j = i; j <num_bends_to_be_drawn; j ++) (// check if we have choiceif (! (bendlines [j]-> bend_body1_point_left) .visible ||! (bendlines [j]-> bend_body1_point_right) .visible) continue; if ((bendlines [j] -> bend_body1_point_left) .screen_x> (bendlines [j]-> bend_body1_point_right) .screen_x) bend_points [j] = & (bendlines [j]->bend_body1_point_left); else bend_points [j] = & (bendlines [j]-> bend_body1 );} // store the y-coordinate for Quicksortfor (j = 0; j <num_bends_to_be_drawn; j ++) bend_y_coordinates [j] = bend_points [j]->screen_y; // sort both sides according to the screen y-coordinate // note a glitch: while the bendlines [] array has been permuted, thebend_points [] array has not been.// in the next paragraph we restore the point array.TODO: may-be there is a better solution.//we could resort the array, but then we need to get original y-coordinates array.//we could just compute a separate permutation array, but then we need space for it, and // the code to compute the permutation, which is non-tirivial.// anyway, for now we just do it the easy way.if (i> 0) DBM_QuickSort_double (bend_y_coordinates, (unsigned long) i, (long *) bendlines); if ((num_bends_to_be_drawn-i)> 0) DBM_QuickSort_double (bend_y_coordinates + i, (unsigned long) (num_bends_to_be_long-i) bendlines + i)); for (j = 0; j <i; j ++) (if ((bendlines [j]-> bend_body1_point_left) .visible) (if (! (bendlines [j]-> bend_body1_point_right) .visible) bend_points [j] = & (bendlines [j]-> bend_body1_point_left ); else (if ((bendlines [j]-> bend_body1_point_left) .screen_x <(bendlines [j]-> bend_body1_point_right) .screen_x) bend_points [j] = & (bendlines [j]->bend_body1_point_left); else bend_points [j] = & (bendlines [j]->bend_body1_point_right);}} else bend_points [j] = & (bendlines [j]->bend_body1_point_right);} for (j = i; j <num_bends_to_be_drawn; j ++) (if ((bendlines [j]-> bend_body1_point_left) .visible) (if (! (bendlines [j]-> bend_body1_point_right) .visible) bend_points [j] = & (bendlines [j]-> bend_body1_point_left ); else (if ((bendlines [j]-> bend_body1_point_left) .screen_x> (bendlines [j]-> bend_body1_point_right) .screen_x) bend_points [j] = & (bendlines [j]->bend_body1_point_left); else bend_points [j ] = & (bendlines [j]->bend_body1_point_right);}} else bend_points [j] = & (bendlines [j]->bend_body1_point_right);} / * Preparation for drawing is now complete. * / static char info_box_text [256]; static POINT box_corners [5]; static POINT arrow [3]; BM_BENDLINE * b; BM_BEND_OP * bop; BM_2D_BODY * b_body; / * Draw the left side. * / int left = 3; int top; if (0 == i) goto draw_right_side; // compute vertical space per info-boxvert_space_per_box = view_size_y / i; // compute vertical offset for the top-left corner of the info-boxoffset = (vert_space_per_box-box_height) >>1; box_corners [0] .x = box_corners [3] .x = box_corners [4] .x = left; box_corners [1] .x = box_corners [2] .x = left + box_width; for (j = 0; j <i; j ++) (b = bendlines [j]->bend; bop = b-> get_bend_op (); if (NULL == bop) continue; // 043996KKif (view_type) b_body = b-> get_current_3D_version (); else b_body = b-> get_flat (); top = j * vert_space_per_box + offset; box_corners [0] .y = box_corners [1] .y = box_corners [4] .y = top; box_corners [2] .y = box_corners [3 ] .y = top + box_height; sprintf (info_box_text, "A:% 5.1f, L:% 6.2f", (bop-> get_bend_angle2 ()) * 57.29578, (b_body-> get_current_center_line ()). get_len ()) ; pdc-> TextOut (5, top, info_box_text, strlen (info_box_text)); switch (bop-> get_type ()) (case BM_TYPE_BEND_OP_REGULAR: sprintf (info_box_text, "R:% 5.2f, D:% 5.2f", ( (BM_BEND_OP_REGULAR *) bop)-> get_bend_radius (), bop-> get_bend_deduction ()); pdc-> TextOut (5, top + font_height, info_box_text, strlen (info_box_text)); break; case BM_TYPE_BEND_OP_CONIC: op.break;} // draw boxpdc-> Polyline (box_corners, 5); // drawarrowarrow [0] .x = left + box_width; arrow [0] .y = top + half_box_height; // calculate arrow tip at fixed percentag e length in from end pointCPoint ptLeft (bendlines [j]-> bend_body1_point_left.screen_x, bendlines [j]->bend_body1_point_left.screen_y); CPoint ptRight (bendlines [j]-> bend_body1_point_right.screen_x, bendlines [j]-> _ bend_body screen_y); CSizesizeDiff = ptRight-ptLeft; CPoint ptArrowTip; if (bend_points [j] == & (bendlines [j]-> bend_body1_point_left)) {ptArrowTip.x = ptLeft.x + sizeDiff.cx/8;ptArrowTip.y = ptLeft.y + sizeDiff.cy/8;}else{ptArrowTip.x = ptRight.x-sizeDiff.cx/8;ptArrowTip.y = ptRight.y-sizeDiff.cy/8;}arrow[1].x = ptArrowTip .x; arrow [1] .y = ptArrowTip.y; pdc-> Polyline (arrow, 2); // change to solid pen for arrow headsCPen * pArrowPen = new CPen (PS_SOLID, BCAD_context.m_nBendLineWeight, BCAD_context.m_crBend); CPen * pOldPen = pdc-> SelectObject (pArrowPen); // compute arrow headCAutoDimArrow arrowBend (ptArrowTip, CPoint (arrow [0] .x, arrow [0] .y), BCAD_context.m_nArrowAngle, BCAD_context.m_nArrowLength); // draw arrow headarrowBend.DrawHead (dc); pdc-> SelectObject (pOldPen); delete pArrowPe n;} / * Draw the right side. * / draw_right_side: if (0 == num_bends_to_be_drawn-i) goto done; box_x = view_size_x-box_width-3; left = box_x; // compute vertical space per info-boxvert_space_per_box = view_size_y / (num_bends_to_be_drawn-i); / compute offset for the top-left corner of the info-boxoffset = (vert_space_per_box-box_height) >>1; box_corners [0] .x = box_corners [3] .x = box_corners [4] .x = left; box_corners [1]. x = box_corners [2] .x = left + box_width; box_x + = 2; for (j = i; j <num_bends_to_be_drawn; j ++) (b = bendlines [j]->bend; bop = b-> get_bend_op (); if (NULL == bop) continue; // 043996KKif (view_type) b_body = b-> get_current_3D_version (); else b_body = b-> get_flat (); top = (j-i) * vert_space_per_box + offset; box_corners [0] .y = box_corners [1] .y = box_corners [4] .y = top; box_corners [2] .y = box_corners [3] .y = top + box_height; sprintf (info_box_text, "A:% 5.1f, L:% 6.2f", (bop-> get_bend_angle2 ()) * 57.29578, (b_body-> get_current_center_line ()). get_len ()); pdc-> TextOut (box_x, top, info_box_text, strlen (info_box_text)); switch (bop-> get_type ()) (case BM_TYPE_BEND_OP_REGULAR: sprintf (info_box_text, "R:% 5.2f, D:% 5.2 f ", ((BM_BEND_OP_REGULAR *) bop)-> get_bend_radius (), bop-> get_bend_deduction ()); pdc-> TextOut (box_x, top + font_height, info_box_text, strlen (info_box_text)); break; case BM_TYPE_BEND_OP_CONIC TODO: implement conic bend op.break;} // draw boxpdc-> Polyline (box_corners, 5); // draw arrowarrow [0] .x = left; arrow [0] .y! 160 # = top + half_box_height; / / calculate a rrow tip at fixed percentage length in from end pointCPoint ptLeft (bendlines [j]-> bend_body1_point_left.screen_x, bendlines [j]->bend_body1_point_left.screen_y); CPoint ptRight (bendlines [j]-> bend_body1_point_right.screen_x, bendlines [x] ->bend_body1_point_right.screen_y); CSize sizeDiff = ptRight-ptLeft; CPoint ptArrowTip; if (bend_points [j] == & (bendlines [j]-> bend_body1_point_left)) {ptArrowTip.x = ptLeft.x + sizeDiff.x / 8 ; ptArrowTip.y = ptLeft.y + sizeDiff.cy/8;}else{ptArrowTip.x = ptRight.x-sizeDiff.cx/8;ptArrowTip.y = ptRight.y-sizeDiff.cy/8;}arrow[1 ] .x = ptArrowTip.x; arrow [1] .y = ptArrowTip.y; pdc-> Polyline (arrow, 2); // change to solid pen for arrow headsCPen * pArrowPen = new CPen (PS_SOLID, BCAD_context.m_nBendLineWeight, BCAD_context.m_crBend); CPen * pOldPen = pdc-> SelectObject (pArrowPen); // compute arrow headCAutoDimArrow arrowBend (ptArrowTip, CPoint (arrow [0] .x, arrow [0] .y), BCAD_context.m_nArrowAngle, BCAD_conrow.n_ ); // draw arrow headarrowBend.DrawHead (dc); pdc-> SelectObje ct (pOldPen); delete pArrowPen;} / * Free the allocated memory. * / done: delete [] bend_points; delete [] bend_y_coordinates; delete [] bendlines;} / * Draw partial dimensions in the device context. * / int BM_AUTO_DIMENSION :: draw_auto_dimensions (CDC * target_dc) {BM_AD_dim_corner * temp_point; int i; // check that we have a valid dcif (NULL == target_dc) return 0; // check if we need to recompute the data structuresif ( dirty) (if (! compute_auto_dimension_data ()) return 0; if (dirty) return 0;} if (NULL == part) return 1; dc = target_dc; // get view sizeview_size_x = view-> get_viewport_width (); view_size_y = view-> get_viewport_height (); // create a mesh to determine clear spaces to draw dimensions & datapMesh = new CAutoDimRgnMesh (view_size_x, view_size_y); // check if we needto compute points to ignore in solidif (view-> get_drawing_mode () && ! points_to_ignore_in_solid_computed) (compute_points_to_ignore_in_solid ();} object_space_per_pixel = view-> get_object_to_device_ratio (); // initially set all "ignore" flags to FALSE. we should not ignore anything.// also, nothing is drawn yet.for (i = 0 ; i <num_of_bendlines; i ++) (bends [i]-> ignore = 0; bends [i]-> body1_drawn = bends [i]-> body2_drawn = 0;} / * All bend line dimension points for all bend lines Calculate the visibility of * / for (i = 0; i <num_of_bendlines; i ++) (if (! bends [i]-> data_valid) continue; bends [i]-> compute_bendline_dim_points_visibility (); if (bends [i]-> adj_body1) (for (temp_point = bends [i]->body1_points;temp_point; temp_point = temp_point-> next) temp_point-> visible = -1;} if (bends [i]-> adj_body2) (for (temp_point = bends [i]->body1_points;temp_point; temp_point = temp_point-> next) temp_point-> visible = -1;}} / * Calculate the dimension points to be drawn for all bend lines. * / for (i = 0; i <num_of_bendlines; i ++) {if (! bends [i]-> data_valid || bends [i]-> ignore) continue; bends [i]-> compute_dim_points_to_display ();} / * Generate a pen that draws the part. Creates a pen that draws a flange dimension. * /// create the pen: type, (line) width, color.CPen penFlange; CPen * pFlangePen = create_auto_dim_pen (& penFlange, BCAD_context.m_nFlangeLineStyle, BCAD_context.m_nFlangeLineWeight, BCAD_context.m_crFlange); // selectnewCP * pOldPen = dc-> SelectObject (pFlangePen); COLORREF oldtextcolor = dc-> SetTextColor (BCAD_context.m_crFlange); int old_bk_mode = dc-> SetBkMode (TRANSPARENT); / * Display the flange length dimension. * / if (BCAD_context.m_bShowFlangeDim) {for (i = 0; i <num_of_bendlines; i ++) (if (! bends [i]-> data_valid || bends [i]-> ignore) continue; bends [i]-> draw_dimension_points ();}} / * // Test the display of the dirty area To do. CBrush brRed (RGB (255,0,0)); CBrush * pOldBrush = dc-> SelectObject (&brRed);dc-> PaintRgn (pDirtyRegion); dc-> SelectObject (pOldBrush); * / delete pDirtyRegion; pDirtyRegion = NULL; / * Create a pen that draws bend line info. * /// create the pen: type, (line) width, color.CPen penBend; CPen * pBendPen = create_auto_dim_pen (& penBend, BCAD_context.m_nBendLineStyle, BCAD_context.m_nBendLineWeight, BCAD_context.m_crBend); // select the new pendc-> Object (pBendPen); dc-> SetTextColor (BCAD_context.m_crBend); / * Draw a bend line info. * / if (BCAD_context.m_bShowBendDim) draw_bendline_data (dc); // Delete the mesh now that we are finished with it.//delete pMesh; / * Restore the old pen. * / dc-> SelectObject (pOldPen); dc-> SetTextColor (oldtextcolor); dc-> SetBkMode (old_bk_mode); // see if we have to disable auto-dimensioning in the view classif (reset_view_to_false_once_drawn) (reset_view_to_false_once_drawn = 0; view -> set_auto_dimensions (0);} return 1;} CPen * BM_AUTO_DIMENSION :: create_auto_dim_pen (CPen * pPen, int nLineStyle, intnLineWeight, COLORREF cr) {if (nLineWeight == 1 || nLineStyle == PS_SOLID) pPen-> CreatePen ( nLineStyle, nLineWeight, cr); // for speedelse {CBrush brushNew (cr); LOGBRUSH lb; brushNew.GetLogBrush (&lb); DWORD dwStyleArray [6]; int nStyleCount = 2; DWORD dwDashLength = 2 + (nLineWeight * 4); DWORD dwDotLength = dwDashLength / 4; DWORD dwGapLength = dwDashLength / 2; switch (nLineStyle) {case PS_DASH: dwStyleArray [0] = dwDashLength; // pixels ondwStyleArray [1] = dwGapLength; // pixels offnStyleCount = 2; break; case PS_DOT : dwStyleArray [0] = dwDotLength; // ondwStyleArray [1] = dwGapLength; // offnStyleCount = 2; break; case PS_DASHDOT: dwStyleArray [0] = dwDashLength; // ondwStyleA rray [1] = dwGapLength; // offdwStyleArray [2] = dwDotLength; // ondwStyleArray [3] = dwGapLength; // offnStyleCount = 4; break; case PS_DASHDOTDOT: dwStyleArray [0] = dwDashLength; // ondwStyleArray [1] = dwGapLength; // offdwStyleArray [2] = dwDotLength; // ondwStyleArray [3] = dwGapLength; // offdwStyleArray [4] = dwDotLength; // ondwStyleArray [5] = dwGapLength; // offnStyleCount = 6; break;} pPen-> CreatePen (PS_GEOMETRIC | PS_USERSTYLE, nLineWeight, & lb, nStyleCount, dwStyleArray);} return pPen;} void CBendCADDoc :: OnDrawAutoDim () {// if we have no dimension object, do nothing.if (NULL == auto_dim) (auto_dim = new BM_AUTO_DIMENSION (this);} if (NULL == auto_dim) return; CBendCADViewPart * pActiveView = (CBendCADViewPart *) get_view (BENDCAD_VIEW_TYPE_PART); if (NULL == pActiveView) return; if (! pActiveView-> get_auto_dimensions ()) auto_dim- > disable_view_dimensions_flag_next_time (); pActiveView-> set_auto_dimensions (1); // always recompute dimension pointsauto_dim-> invalidate (); pActiveView-> Invalidate (0);}
Appendix H
An example of an automatic dimensioning function that calculates dimension points. The dimension points are calculated before the flange length dimension is drawn.
[0297]
// # include "stdafx.h"#include"BendCAD.h"#include"BendCADDoc.h"#include"BendCADViewPart.h"#include"AUTODIM.HXX" / *********** * ********* ********** ********** ********** ********** * ********* ********** ********** BM_AD_bendline class stuff. ********** ******* *** ********** ********** ********** ********** ******* *** ********** *********** // * This calculates the distance between a given reference point and an edge point BM_AD_bendline :: compute_BM_AD_flange_points ( Local function used for ..). This function returns FALSE if the point is on one wrong side of the reference line. The vector dir should be a unit vector. * / static int compute_distance_from_ref_point (BM_POINT const & pt / * given reference point * /, BM_VECTOR const & dir / * direction vector * /, BM_POINT * p / * point whose distance we want to compute * /, double & distance) {BM_VECTOR v (* p-pt); double x = v% dir; if (x <-AUTODIM_DISTANCE_TOLERANCE) return 0; distance = x; return 1;} / * BM_AD_bendline :: compute_BM_AD_flange_points (...) local function used. Note: The referenced dimension list is a list of flange dimension points. A dimension list is open when the number of dimension points in the list opened to “left” is not equal to the number of dimension points in the list opened to “right”. This usually means that the last flange dimension point added to the list does not have a flange dimension point that matches "close". All of this comes from the possibility that we can actually have a line broken up into pieces (looks like one line). In that case, the user does not see those pieces (looks like a single line) and we do not want to consider the points as legitimate flange dimension points along the way. This function returns TRUE if we can skip the given edge and leave the dimension point open, and we will return the left dimension point from one of the current edge endpoints. Returns FALSE if the open dimension needs to be closed by creating it. Basically, this function returns TRUE if the next edge in the loop is a line that is not ignored. In practice, some additional conditions are added. Note: This function is required when the edge endpoint is at a flange long distance and we are considering whether to draw a (flange) dimension point for this endpoint. * / static int leave_dimension_open (BM_EDGE * edge / * current edge * /, BM_LOOP * bloop / * loop where the current edge belongs to * /, BM_VECTOR const & side_vector / * side vector for the current bendline-ajd_flange pair * /, BM_VECTOR const & normal / * normal of the plane underlying the adjacent flange * /) (BM_EDGE * next_edge = (BM_EDGE *) edge-> next (); if (NULL == next_edge) next_edge = bloop-> get_first_edge (); if (next_edge- > is (BM_ENTITY_TYPE_LINE)) (// problem.if the next edge (which is aline) will be ignored, we need to // close the dimension here.BM_VECTOR temp_v (((((BM_LINE *) next_edge)-> get_v () ) * side_vector); // if the nextline will not be ignored we can skip the current edge.if (temp_v.Len ()> AUTODIM_DISTANCE_TOLERANCE && (temp_v% normal) <0.0) (// next edge isa line that will not be ignored.// note that there is a problem.if this edge is a line, and one of the two lines // (rememeber, next edge is aline) is adjacent to a bendline that // the other is not adjacent to, we should close the dimension.if (! edge-> is (BM_ENTITY_TYPE_LINE)) return1; BM_3D_BODY * ab = edge-> get_adj_body (); BM_3D_BODY * ab_next = next_edge-> get_adj_body (); if (! ab) (if (! ab_next) return 1; if (! ab_next-> is (BM_ENTITY_TYPE_BENDLINE)) return 1; return 0;} if (! ab_next) (if (! ab-> is ( BM_ENTITY_TYPE_BENDLINE)) return 1; return 0;} if ((! Ab-> is (BM_ENTITY_TYPE_BENDLINE) &&! Ab_next-> is (BM_ENTITY_TYPE_BENDLINE)) || ab == ab_next) return 1;}} // if next edge is not a line, we have to close the open dimensionreturn 0;} / * BM_AD_bendline :: compute_BM_AD_flange_points (...) A local function used by this function to generate dimension points in the most general form. We assume that we are generating dimension points for the line. This line can be adjacent to the bend line. * / static BM_AD_dim_corner * create_dim_point (double d / * bendline arcoutside length projected onto our plane * /, // these are basic parameters needed to draw any dimension pointBM_POINT const & p / * point p in theflange dimension point * /, BM_VECTOR const & rv / * reference vector to make sure point p in the flange dimension point is on the same plane as defined by the bendline dimension point * /, BM_VECTOR const & opening_direction_vector / * for flange dimension point * /, int opening_vector_reverse_bit, BM_AD_bendline * owner, BM_3D_BODY * Body_required_visible , BM_AD_dim_corner ** prev / * previous flange dimension point in the list of flange dimpoints * /, BM_VECTOR const & side_vector, // these parameters are used when the line for which we are computing the dimension point is adjacent // to another bendline.double d_proj_side_vector / * d projected onto the side-vector: angle_factor * d in compute_BM_AD_flange_points (...) * /, BM_VECTOR & bend_arc_direction / * direction of the bend arc projected onto ou r plane * // * should be line-> v * plane_normal * /, BM_VECTOR & bend_direction / * points to the direction in which the bendline "turns" * // * depends on whether the bend angle is acute or not. * / / * if acute then tangentto the other end of bend arc * // * if not acute, then an endpoint of thetangent approximation * // * basically this is the (p-> p2) vector for theother bendline with respect to this flange * /, BM_BENDLINE * adj_bendline / * if the line is adjacent to a bendline this is a pointer to it * // * this parameter is stored to avoid drawing some dimenions twice * /, BM_LINEconst & adj_bend_p2_line / * this is the line between p2 points of the bend-dimension * // * points of the adjacent bendline with respect to this flange * // * note that our p2 point has to be on that line. * // * usually our p-> p2 vector is perpendicular to this line , although not always * /) {// this our local copy of the adj-bendline-pointerBM_3D_BODY * adj_bend = adj_bendline; BM_POINT p_local (p + rv); // note: even if this line is adjacent to another bendline, // but if the line we are creating the flange dimension point for is not perpendicular to // the side-vector, we should not memorize that this flange dimension point is adjacent to // a bendline, because the flange length dimension drawn at this flange dimension point // is not parallel to the side-vector of the adjacent bendline with respect to this flange.if (adj_bendline && fabs (bend_arc_direction% side_vector) <(bend_arc_direction.Len ()-AUTODIM_DISTANCE_TOLERANCE)) {// not perpendicularadj_bendline = NULL;} // check if the line is attached to a bendlineif (d <= AUTODIM_DISTANCE_TOLERANCE) (// not attachedto a bendline, or both thickness and bendline radius are 0.// create a 1-point flange-dimension point.// note that body_required_visible pointsto the flange with respect to which // the dimension point is computed.return new BM_AD_dim_corner (p_local, owner, Body_required_visible, opening_direction_vector, opening_vector_reverse_bit, prev, adj_bendline);} // note that since we have 3 points now, this line is adjacent to anotherbendline.// compute p1. p_local is p1. // compute pBM_POINT dim_p (p_local + d_proj_side_vector * side_vector); // compute p2bend_arc_direction.set_length (d); BM_POINT dim_p2 (p_local + bend_arc_direction); // now the problem is that with respect to the adjacent bendline, our flange dimensionpoints // p and p1 might not be on the outside-they could be on the inside.// the distance from p to p2 depends on that.// however, we know the p2-line of the adjacent bendline (with respect to our flange), // so wewill compute the dista nce between that p2-line and dim_p2. // we will use that to compute the correct p2 point for our flange dimension (note that // our p2 point has to be on the p2-line of the adjacent bendline) .double distance; BM_distance_between_point_and_line (dim_p2, adj_bend_p2_line, & distance, (BM_POINT *) NULL); bend_direction.set_length (distance); dim_p2 = bend_direction; // note that the body_required_visiblepointer points not to this flange, but to the // ALWAYS, even if this flange dim point will not be marked as // adjacent to another bendline.return new BM_AD_dim_corner (dim_p, p_local, dim_p2, owner, adj_bend? Adj_bend: Body_required_visible, opening_direction_vector, opening_vector_reverse_bit, prev, adj_bendline) This function calculates the flange dimension points for adjacent flanges. Note: The reference point calculated just before this function is given to ensure that we can manipulate any kind of adj-body surface. The first problem is that we don't know if adj-body's 3D-version's 2D-body represents OUTSIDE or INSIDE. We know that the bend line dimension point for the bend line is the OUTSIDE point. However, it is possible that adj-body clearly represents INSIDE. In that case, it is used for the reference point (which is on the outer surface of the adj-body) that calculates the translation vector that shifts all the points to be calculated here. Furthermore, this translation vector is used to confirm that the points p1 and p2 of the flange dimension point are correct. (If adj-body represents inside, we actually calculate the dimension points for outside, and the line (p-> p2) must be constructed with care, which is the line (p- > shorter than p1)) Note: This function is very similar to the BMAPI's BM_2D_BODY :: compute_outside_width (...) function, although we make more assumptions here. * / int BM_AD_bendline :: compute_BM_AD_flange_points (BM_3D_BODY * adj_body) {// flange dimension points we aregoing to compute will be stored here BM_AD_dim_corner ** list_of_points; // list_of_points is where we write the pointer to the // next flanged dimensionp // these parameters are used asinput to this function.double flange_length; / * it is important that the flange length be the correct flange length * / BM_POINT ref_point; / * reference point, defines the right plane for flange dimension points * / BM_VECTOR side_vector ; / * should be normalized * /// check which adjacentbody we computeif (adj_body == adj_body1) (flange_length = fl1; list_of_points = &body1_points; ref_point = bend_body1_point_left.p; side_vector = side_vector1;} else if (adj_body == adj_body2) { flange_length = fl2; list_of_points = &body2_points; ref_point = bend_body2_point_left.p; side_vector = side_vector2;} else return 0; // not an adjcent body // variables to store temporary values BM_VEC TOR temp_v; double temp_x; // parameters for fixing the reference pointBM_POINT rp (ref_point); // this a local copy of the reference point.we will modify it.BM_VECTOR rv; // avector for translating flange dimension points.int ref_vector_valid = 0; // if this is TRUE, we need to translate all flange dimension points.// if TRUE, the only really tricky part is to construct the p2 point in the flange dimension point.// qualification checkBM_2D_BODY * adj_displayed_version; if (parent -> get_view_type ()) adj_displayed_version = adj_body-> get_current_3D_version (); else adj_displayed_version = adj_body-> get_flat (); if (NULL == adj_displayed_version) return 0; BM_SURFACE * surface = adj_displayed_version-> get_surface = = surface) return 0; BM_LOOP * bloop = adj_displayed_version-> get_bloop (); if (NULL == bloop) return 0; BM_EDGE * edge; // here we will store edges as we scan the loop.double distance1, distance2; / / here we will store the distance of points we seedouble d1, d2; // her e we store distance that has to be addedbecause of a bend arc.for lines adjacent to a bendline.double td1, td2; // here we store the total distance which is the sum of distanceX + dX.BM_3D_BODY * ab; // here we store a pointer to a body that is adjacentto the current edge.BM_BEND_OP * bop; // here we store a pointer to thebend op associated with the bendline that is // adjacent to the edge wescan (valid only iff the body adjacent to the edge is a bendline) .BM_VECTOR right_opening_direction; // this is the right-side opening direction vector.BM_VECTOR left_opening_direction; // this is the left-side opening direction vector.int fl_dim_open = 0; // if this is TRUE, we have created a right-side flange dimension point, but // no corresponding left-side dimension point. That is, the dimension is "open" .BM_VECTOR bend_arc_direction; // direction of the bend arc projected onto our plane // should be line- > v * plane_normal.Used when a line is adjacent to a bendline.BM_VECTOR bend_direction ; // points in the direction in which thebendline "turns" // depends on whether the bend angle is acute or not. // if acute then tangent to the other end of bend arc.// if not acute, then an endpoint of the tangent approximation.// basically this is the (p-> p2) vector for the other bendline with respect to this flange.// this is used when a line is adjacent to a bendline, to compute the p2 point for // the flange dimension point.BM_LINE adj_bend_p2_line; // this is the left-right-p2 line, of the adjacent bendline, // with respect to this flange.// this is used when a line is adjacent to a bendline, to computethe p2 point for // the flange dimension point.double bend_arc_outside_length_proj; // bendline arc outside length projected onto our plane / * Manipulate the surface type. * / if (surface-> is (BM_TYPE_PLANE)) goto handle_planes; / *********** ********** ********** *** ******* ********** ******************** ********** *** ******* Temporary restraint: We only manipulate surfaces that are flat. TODO: Manipulate other surface types. ********** ********** ********** ********** ********** ********** ********** ********** *********** /// unknown surfacereturn 0; / * Here, the plane is manipulated. * / handle_planes: BM_PLANE * plane = (BM_PLANE *) surface; // we assume that the reference point correctly defines the plane (which is parallel to our plane) // thatis the OUTSIDE plane.// check if reference point is on our plane.If not (in that case our plane represents the INSIDE // plane) compute a translation vector for moving from our plane to reference plane, // and move the reference point to our plane.rv = plane-> get_normal (); rv.normalise (); temp_v = rp-(plane-> get_pt ()); temp_x = temp_v% rv; if (fabs (temp_x)> AUTODIM_DISTANCE_TOLERANCE) (// ok, need to translate all dimension points.reference point not on the plane.ref_vector_valid = 1; rv.set_length (temp_x); rp = rp + (-rv);} else rv = BM_null_vector; // compute right- and left-side opening vectors.right_opening_direction = side_vector * (plane-> get_normal ()); right_opening_direction.normalise (); left_opening_direction =-(right_opening_direction); / *********** ********** ********** * ********* ********** ********** ********** ********** ********** The main part of this function. Sweeps the binding loop of adj_body and constructs dimension points. Note that we just need to sweep the bloop because the edge furthest away from a given line must be in the bloop. ******************** ********** ********** ********** ********** ********** ********** ********** Note: Generated when dimension list is open The last right-side dimension point to be done must be different from the start-point of the current edge at the beginning of the loop. ********** ********** ********** ********** ********** ********** ********** ********** ********** * /// scan alledges in the bloop / / first, we have a problem where to start scanning.// if we start from the first edge, we basically start from an arbitraryedge.// this might not be good since we might create dimension points wedon't really want.// therefore we will find an edge that is adjacent to our bendline and start from that and // finish when we get back to it.BM_EDGE * start_edge, * stop_edge, * next_edge; for (start_edge = bloop-> get_first_edge (); start_edge; start_edge = (BM_EDGE *) start_edge-> next ()) (if (start_edge-> get_adj_body () == bend) break; // edge adjacent to this bendline is a good start-edgeelse if (! start_edge-> is (BM_ENTITY_TYPE_LINE )) break; // any non-line is a good start-edgeelse {// any linethat will be ignored is also a good place to starttemp_v = (((BM_LINE *) start_edge)-> get_v ()) * side_vector; / / in these two cases this line will be ignoredif (temp_v.Len () <= AUTODIM_DISTANCE_TOLERANCE) break; // line parallel to the side-vectorif ((temp_v% plane-> get_normal ())> 0.0) break; // material "above" the line}} if (NULL == start_edge) {* list_of_points = NULL; return 1;} // this is the main loop.// initially we setstop_edge to NULL. we would like to set it to start-edge, but we cannot, // because in that case we would never enter the therefore we setit to NULL and right // after we enter the loop, we set it to start_edge.// (this is important in the case when the loop consists of only one circle) .stop_edge = NULL; for (edge = start_edge; edge! = stop_edge; edge = next_edge) (stop_edge = start_edge; // compute the next edge we will scannext_edge = (BM_EDGE *) edge-> next (); if (NULL == next_edge) next_edge = bloop-> get_first_edge (); switch (edge-> get_type ()) (case BM_ENTITY_TYPE_LINE: {// compute distance for start- and end-points // first, we want to ignore lines that are parallel to the side-vector.// we also want to ignore lines that have material "above" them when looking in the // side-vector direction (because they cannot have to largest width, since material is // "above" them, there must be some other edge bounding thebody from above) .temp_v = ( ((BM_LINE *) edge)-> get_v ()) * side_vector; if (temp_v.Len () <= AUTODIM_DISTANCE_TOLERANCE) continue; // line parallel to the side-vectorif ((temp_v% plane-> get_normal ())> 0.0) continue; // material "above" the line // note that this leaves only lines whosedirection-vector goes to the "left" // of the side-vector.// we need tocheck if this line is adjacent to a bendlineab = edge-> get_adj_body (); // check if this line is adjacent to a valid bendline (ie. one that is not the // bendline associated with this BM_AD_bendline object) .d1 = d2 = bend_arc_outside_length_proj = 0.0; if (ab && ab! = bend &&ab-> is (BM_ENTITY_TYPE_BENDLINE)) (// check if the bendline is being bentbop = ((BM_BENDLINE *) ab)-> get_bend_op (); if ((parent-> get_view_type ()) / * have tohave a 3D view * / && ((BM_BENDLINE *) ab)-> get_bending_status () && bop) { // a problem: it could be that the bendline is not perpendicular to the side-vector.// in that case we need to project the bend-arc-approximation-value onto the side-vector.// for example, if the bendline is parallel to the side- vector, we should not add // the approximation value at all, since it plays no role in the width computation.temp_x = side_vector ^ (((BM_LINE *) edge)-> get_v ()); // temp_x is "angle_factor" if (temp_x> PI_over_2) temp_x = PI-temp_x; temp_x = sin (temp_x); switch (bop-> get_type ()) (case BM_TYPE_BEND_OP_REGULAR: bend_arc_outside_length_proj = ((BM_BEND_OP_REGULAR *) bop)-> perute_app_x * bend_arc_outside_length_proj; d2 = d1; // d2 is the same as d1! break; // TODO: implement more bend operations here.default:; // unknown bend op} // compute some needed parameters // compute: direction ofthe bend arc projected onto our planebend_arc_direction = (((BM_LINE *) edge)-> get_v ()) * plane-> get_normal (); bend_direction = parent-> compute_bend_direction_vector ((BM_BENDLINE *) ab, adj_body, &adj_bend_p2_line);}} else ab = NULL; // make sure ab does not point to anything we don'twant to.// handle two cases separately-depending on whether the dimension list is open or not.if (fl_dim_open) {// if the dimension is open, we don't need to check the start-point of the line, // since it is at theflange length distance anyway.// // first we will check if the line isperpendicular to the side-vectorif (fabs (side_vector% ((BM_LINE *) edge)-> get_v ())> AUTODIM_DISTANCE_TOLERANCE) (// not perpendicular.// thisline has to be "coming down" (because it is not perpendicular to the // side-vector and the dimension is open, ie. it cannot be "going up") .// now we have to close the dimension by creating a left-hand-side dimensionpoint // from the start- point of the line.if (temp_dp = create_dim_point (bend_arc_outside_length_proj, ((BM_LINE *) edge)-> get_startpt (), rv, left_opening_direction, 0, this, adj_body, list_of_points, side_vector, d1, bend_arc_direction, bend_direction, * BM_BEND ab, adj_bend_p2_line)) (list_of_points = &(temp_dp->next);} fl_dim_open = 0;} else (// is perpendicular.// here we need to check the type of the next edge.// if itis not line, w e need to close the dimension here by creating // a left-hand-side dimension point from the end-point of the line.// if the nextedge is a line, we can just continue.if (leave_dimension_open (edge, bloop, side_vector, plane-> get_normal ())) break; if (temp_dp = create_dim_point (bend_arc_outside_length_proj, ((BM_LINE *) edge)-> get_endpt (), rv, left_opening_direction, 0, this, adj_body, list_of_points, side_vector, d1, bend_direction , bend_direction, (BM_BENDLINE *) ab, adj_bend_p2_line)) (list_of_points = &(temp_dp->next);} // ok, close the dimension.fl_dim_open = 0; // this is a small trick that will save us some time. // if the next edge is a line that will be ignored, we can skip is right now here.if (next_edge-> is (BM_ENTITY_TYPE_LINE) && next_edge! = stop_edge) (next_edge = (BM_EDGE *) edge-> next () ; if (NULL == next_edge) next_edge = bloop-> get_first_edge ();}} break;} if (! compute_distance_from_ref_point (rp, side_vector, edge-> get_edge_startpoint (), distance1)) continue; if (! compute _distance_from_ref_point (rp, side_vector, edge-> get_edge_endpoint (), distance2)) continue; td1 = distance1 + d1; td2 = distance2 + d2; // check if the start-point is a flange dimension pointif (fabs (td1-flange_length) <= AUTODIM_DISTANCE_TOLERANCE) (// check if the second point is a flange dimension pointif (fabs (td2-flange_length)> AUTODIM_DISTANCE_TOLERANCE) (// only start-point is a flange dimension point.// create a left-right (ie. in both directions) flange dim point and continue.if (temp_dp = create_dim_point (bend_arc_outside_length_proj, ((BM_LINE *) edge)-> get_startpt (), rv,! 160 # right_opening_direction, 1, this, adj_body, list_of_points, side_vector, d1, bend_arc_direction, bend_direction, (BM_BENDLINE *) ab, adj_bend_p2_line)) (list_of_points = &(temp_dp->next);}break;} // else open the dimension list // create right flange dimensionpoint from start-pointif (temp_dp = create_dim_point ( bend_arc_outside_length_proj, ((BM_LINE *) edge)-> get_startpt (), rv, right_opening_direction, 0, this, adj_body, list_of_points, side_vector, d1, bend_arc_direction, bend_direction, (BM_BENDLINE *) ab, adj_bend_p2_line_p ->next);} // check if we can leave the dimension list opena nd continueif (leave_dimension_open (edge, bloop, side_vector, plane-> get_normal ())) (fl_dim_open = 1; break;} // create left flange dim point from end-point.if (temp_dp = create_dim_point (bend_arc_outside_length_proj, ((BM_LINE *) edge)-> get_endpt (), rv, left_opening_direction, 0, this, adj_body, list_of_points, side_vector, d1, bend_arc_direction, bend_direction, (BM_BENDLINE *) ab, adj_bend_p2_line)) (list_of_points = &(temp_dp-> next) } // ok, close the dimension list.fl_dim_open = 0; // this is asmall trick that will save us some time.// if the next edge is a line that will be ignored, we can skip is right now here.if (next_edge-> is (BM_ENTITY_TYPE_LINE) && next_edge! = stop_edge) (next_edge = (BM_EDGE *) edge-> next (); if (NULL == next_edge) next_edge = bloop-> get_first_edge ();} break;} else if (fabs (td2-flange_length)> AUTODIM_DISTANCE_TOLERANCE) {// the start-point is not a flange dimension point // if the end-pointis also not a flange dimension point, we can continue.continue;} // ok , only the end-point is a flange dimension point.// two possibilities.ifwe can leave the dimension list open (right now dimension is // closed!) we don't even have to open it, we can just continue.if (leave_dimension_open (edge, bloop, side_vector, plane-> get_normal ())) break; // second possibility. now we have to create a left-right flange dimension point.// dimension list stays closed.if (temp_dp = create_dim_point ( bend_arc_outside_length_proj, ((BM_LINE *) edge)-> get_endpt (), rv, right_opening_direction, 1, this, adj_body, list_of_points, side_vector, d1, bend_arc_direction, bend_direction, (BM_BENDLINE *) ab, adj_bend_p2_line_p ->next);} // this is a small trick that will save us some time.// if the next edge is a line that will be ignored, we can skip is right now here.if (next_edge-> is (BM_ENTITY_TYPE_LINE ) && next_edge! = stop_edge) (next_edge = (BM_EDGE *) edge-> next (); if (NULL == next_edge) next_edge = bloop-> get_first_edge ();}} break; case BM_ENTITY_TYPE_A RC: {// note: we can always ignore the start-point of the arc! // becauseof the way we keep track of the open dimension list.// make sure the dimension list will be closed.fl_dim_open = 0; // first, compute start- andend-angles of the arc with respect to the side vector.// ie. convert start- and end-angles so as if the side-vector was the 0-angle vector.double startang = ((BM_ARC * ) edge)-> get_startang (); double endang = ((BM_ARC *) edge)-> get_endang (); temp_v = side_vector * (((BM_ARC *) edge)-> get_vx ()); double delta_angle = (temp_v. Len ()) / (((BM_ARC *) edge)-> get_rad ()); if (delta_angle <-1.0) delta_angle = -1.0; else if (delta_angle> 1.0) delta_angle = 1.0; delta_angle = asin (delta_angle); if (fabs ((((BM_ARC *) edge)-> get_normal ())% temp_v)> 0.0 ) {startang + = delta_angle; endang + = delta_angle; if (startang> PI_times_2) startang-= PI_times_2; if (endang> PI_times_2) endang-= PI_times_2;} else {startang-= delta_angle; endang-= delta_angle; if (startang <0.0) startang + = PI_times_2; if (endang <0.0) endang + = PI_times_2;} // compute the extreme point BM_POINT arc_extreme_point; // 0-angle point is the extreme pointif (endang <startang) arc_extreme_point = ((BM_ARC *) edge)-> get_center () + (((BM_ARC *) edge)-> get_rad ()) * side_vector; else arc_extreme_point = * ((((BM_ARC *) edge)-> get_edge_endpoint ()); // check the distance of the extreme pointif (! compute_distance_from_ref_point (rp, side_vector, & arc_extreme_point, distance1)) continue; if (fabs (distance1-flange_length) <= AUTODIM_DISTANCE_TOLERANCE) (// if we have the 0-angle point, create a left-right flange dimension point.// otherwise if next line is a non-ignored line, don't do anything, // otherwise create a left -right flange dimension point.if (endang> = startang && leave_dimension_open (edge, bloop, side_vector, plane-> get_normal ())) (continue;} // create a left-right flange dimension point. dimension list stays closed./ / this is a 1-point flange dimension point.if (temp_dp = new BM_AD_dim_corner (rv + arc_extreme_point, this, adj_body, right_opening_direction, 1, list_of_points, NULL)) {list_of_points = &(temp_dp->next);}}}break; case BM_ENTITY_TYPE_CIRCLE: // circles are a much simpler version of the arc case. (BM_POINT circle_extreme_point = ((BM_CIRCLE *) edge)-> get_center () + (((BM_CIRCLE *) edge)-> get_rad ()) * side_vector ; // we won't check the distance since it mustbe a flange dimension point // create a left-right flange dimension point.// this is a 1-point flange dimension point.if (temp_dp = new BM_AD_dim_corner (rv + circle_extreme_point, this, adj_body, right_opening_direction, 1, list_of_points, NULL)) (list_of_points = &(temp_dp->next);}}break; case BM_ENTITY_TYPE_ELLIPSE: // TODO: implement ellipse here. shouldbe similar to the way arc is handled.continue; break; default: continue; // unknown edge type}} / * OK, everything ends. * / * list_of_points = NULL; return 1;} / * This function calculates the bend line dimension points for one BM_AD_bendline structure. Note: p1 is on the plane of the neighbor where the flange length is drawn. p is a center point. p2 is the side point of the bend line. Note: In this function, we always calculate the bend-dimension points for adj-body1 and adj-body2. This bend line will have 1 or 0 neighbors, but we need to know the visibility of these points in the future. * / int BM_AD_bendline :: compute_BM_AD_bendline (void) {double metal_thickness; // thickness of the sheetmetalBM_2D_BODY * bendline_displayed_version; // 3D-version of the bendlineBM_VECTOR temp_v; // vectorused for very short periods for storing temporary stuff // initally markthe bend as invalid, in case we fail here.data_valid = 0; // qualification checkif (NULL == bend) return 0; if (NULL == bend-> get_adj_list ()) return 0; if (NULL == bend-> get_part ()) return 0; // this bendline has to have a 3D-versionif (parent-> get_view_type ()) (if (NULL == (bendline_displayed_version = bend-> get_current_3D_version ())) return 0;} else (if ( NULL == (bendline_displayed_version = bend-> get_flat ())) return0;} metal_thickness = (bend-> get_part ())-> get_metal_thickness (); / * ********** ***** ***** ********** ********** ********** ********** ***** ***** ********** ********** This is a temporary measure. We simply handle regular bend lines. That is, the cone bend line is ignored. 03/16 / 96.KK. * / If (bend-> get_bending_status () &&bend-> get_bend_op () &&! (Bend-> get_bend_op ())-> is (BM_TYPE_BEND_OP_REGULAR)) return 0; / * *** ******* ********** ********** ********** ********** *** ******* ********** ********** ********** * /// get the number of adjacent bodies.adj_body1 = (bend-> get_adj_list ())-> find_lowest_id_adj_body (); adj_body2 = (bend-> get_adj_list ())-> find_second_lowest_id_adj_body (); num_of_adjacent_bodies = (adj_body1? 1: 0) + (adj_body2 Calculate the side vector. * / if (adj_body1) (if (! bendline_displayed_version-> compute_vector_perp_towards_adj_body (adj_body1, side_vector1)) return 0; side_vector1.normalise ();} if (adj_body2) (if (! bendline_displayed_version->compute_vector_adj_return_vector_perj_body_2; side_vector2.normalise ();} / * Calculate the bend line dimension point. * / if (! bend-> get_bending_status () / * bendline not bent * / ||! parent-> get_view_type () / * flat view * /) (// note: here we don't know whether the dimension point is OUTSIDE or INSIDE.// this has to be taken into account later.// however, it should work either way.bend_body1_point_left.num_of_points = bend_body1_point_right.num_of_points = 1; bend_body1_point_left.can_reverse_opening_dir = bend_body1_point_right_pend_body_p__________________. bendline_displayed_version-> get_current_center_line ()). get_startpt (); bend_body1_point_right.p = (bendline_displayed_version-> get_current_center_line ()). get_endpt (); // note opening directions.left will get start-point, right will get end-point, ie vector goes left-> right.bend_body1_point_right.opening_direction = (bendline_displayed_version-> get_current_center_line ()). get_v (); (bend_body1_point_right.opening_direction) .normalise (); bend_body1_point_left.opening_direction =-(bend_body1 ____ points with respect to bothadjacent bodies are the samebend_body2_point_left.num_of_points = bend_body2_point_right.num_of_points = 1; bend_body2_point_left.can_reverse_opening_dir = bend_body2_point_right.can_reverse_opening_dir = 0; bend_body2_point_right.opening_direction = bend_body1_point_right.opening_direction; bend_body2_point_left.opening_direction = bend_body1_point_left.opening_direction; bend_body2_point_left.p = bend_body1_point_left. p; bend_body2_point_right.p = bend_body1_point_right.p;} else {// first, get some bending parametersBM_SURFACE * surface = bendline_displayed_version-> get_surface (); if (NULL == surface) return 0; BM_BEND_OP * bop = bend-> get_bend_op ( ); if (NULL == bop) return 0; double bend_angle = bop-> get_bend_angle2 (); double bend_arc_angle = PI-bend_angle; double half_bend_arc_angle = bend_arc_angle / 2.0; switch (surface-> get_type ()) (case BM_TYPE_CYLINDER: { // note that the bend op can be both regular and conicBM_CYLINDER * cylinder = (BM_CYLINDER *) su rface; double radius = cylinder-> get_rad (); double outside_radius = radius; if (bendline_displayed_version-> get_sense ()) outside_radius + = metal_thickness; // set some common valuesbend_body1_point_left.can_reverse_opening_dir = bend_body1_point_right.can_reverse_open__ (bendline_displayed_version-> get_current_center_line ()). get_v (); (bend_body1_point_right.opening_direction) .normalise (); bend_body1_point_left.opening_direction =-(bend_body1_point_right.opening_direction); if (outside_radius <= AUTODIM_DISTANCE_TOLERANCE) (// special case: outside radius 0-trivial dimension point.bend_body1_point_left.num_of_points = bend_body1_point_right.num_of_points = 1; bend_body1_point_left.p = (bendline_displayed_version-> get_current_center_line_start_body_p . bendline_displayed_version-> get_current_center_line ()) get_endpt (); bend_body2_point_left.num_of_points = bend_body2_point_right.num_of_points = 1; bend_body2_point_left.can_reverse_opening_dir = bend_body2_point_right.can_reverse_opening_dir = 0; bend_body2_point_right.opening_direction = bend_body1_point_right.opening_direction; bend_body2_point_left.opening_direction = bend_body1_point_left.opening_direction; bend_body2_point_left. p = bend_body1_point_left.p; bend_body2_point_right.p = bend_body1_point_right.p;} else {bend_body1_point_left.num_of_points = bend_body1_point_right.num_of_points = 3; // compute points p1 for adj_body1bend_line1_b rrent_center_line ()). get_startpt (); bend_body1_point_right.p1 = (bendline_displayed_version-> get_current_center_line ()). get_endpt (); // theproblem now is that it could be that these centerline points (which are // on the surface of the bendline ), could be only inside surface of thebendline.if (bendline_displayed_version-> get_sense () &&metal_thickness> AUTODIM_DISTANCE_TOLERANCE) (temp_v = cylinder-> get_vx (); temp_v.set_length (metal_thickness); bend_body1_point_left.p1 + bend_p. bend_body1_point_right.p1 = bend_body1_point_right.p1 + temp_v;} // a break in the computation of adj_body1.p1.// store current p1values for adj_body2 as well. this will save some time.// // note thatwe should not really compute adj_body2 points unless adj_body2 pointer // is not NULL.However, this point (adj_body2.p1) is very useful for computing // adj_body1.p2 (if angle is acute) .so we compute it anyway.bend_body2_point_left.p1 = bend_body1_point_left.p1; bend_body2_point_right.p1 = b end_body1_point_right.p1; // finish adj_body1.p1. rotate points p1 into their final correct location.// note we rotate in the negative direction since adj_body1 is the smallest-index // adjacent body as is "to-the-left-of -the-bendline-centerline ", which means // rotating to the left.//first, compute the right vector for the rotation line.BM_VECTOR rot_v (cylinder-> get_v ()); if (rot_v% ((bendline_displayed_version-> get_current_center_line ()). get_v ()) <0.0) (rot_v.reverse ();} BM_rotate_point_around_line (& (bend_body1_point_left.p1), cylinder-> get_pt1 (), rot_v, -half_bend_arc_angle); BM_rotate_point_around_line (& (bend_body1_point_right.p1), pt1), pt1 , -half_bend_arc_angle); // finish also adj_body2.p1.rotate points p1 into their final correct location.BM_rotate_point_around_line (& (bend_body2_point_left.p1), cylinder-> get_pt1 (), rot_v, half_bend_arc_angle); BM_rotate_point1 ), cylinder-> get_pt1 (), rot_v, half_bend_arc_angle); // compute points p for adj_body1.double x; if (bop-> is (BM_TYPE_BEND_OP_REGULAR)) (x = ((BM_BEND_OP_REGULAR *) bop)->compute_3D_outside_app;} else if (bop-> is (BM_TYPE_BEND_OP_CONIC)) (// TODO: implement conic bendline herereturn 0;} temp_v = -x * side_vector1; bend_body1_point_left.p = bend_body1_point_left.p1 + temp_v; bend_body1_point_right_p_be_point_right_p_ temp_v; // note: adj_body1.p2 and adj_body2.p, adj_body2.p2 are yet to be computed.// now there are two cases: 1) the bend arc angle is acute (ie.no more than 90 degrees), // 2) the bend arc angleis more than 90 degrees.if (bend_arc_angle> (PI_over_2 + BM_ANGLE_TOLERANCE) ) {// use tangent approximation // we will finish computing adj_body1. adj_body1.p2 is left.// idea: notice that adj_body1 is to the leftof the bendline-centerline // because it is the lowest-index neighbor. -product // of centerline-v by temp_v points towards thecylinder (actually it is tangent // to the cylinder) .BM_VECTOR tangent_v (bend_body1_point_right.opening_direction * temp_v); tangent_v.set_length (x); bend_body1_point_left.p2 = bend_p tangent_v; bend_body1_point_right.p2 = bend_body1_point_right.p + tangent_v; // noteadj_body2.p1 is already computed.first set some common values.bend_body2_point_left.num_of_points = bend_body2_point_right.num_of_point _ = _ g_dir = 0; bend_body2_point_right.opening_direction = bend_body1_point_right.opening_direction; bend_body2_point_left.opening_direction = bend_body1_point_left.opening_direction; // now compute adj_body2.ptemp_v = -x * side_end_body_p ______________. temp_v; // finally, compute adj_body2.p2 // note the order in the cross-product! tangent_v = temp_v * bend_body2_point_right.opening_direction; tangent_v.set_length (x); bend_body2_point_left.p2 = bend_body2_point_left.p + tangentp2 = b_rightbodyp2 = bend_body2_point_right.p + tangent_v;} else {// use intersection approximation // note: adj_body2.p2 is the same as asj_body1.p1.bend_body1_point_left.p2 = bend_body2_point_left.p1; bend_body1_point_right.p2 = bend_body2_point_right , dimensions points with respect to // both adjacent bodies are the same, so we just copy them.bend_body2_point_left.nu m_of_points = bend_body2_point_right.num_of_points = 3; bend_body2_point_left.can_reverse_opening_dir = bend_body2_point_right.can_reverse_opening_dir = 0; bend_body2_point_right.opening_direction = bend_body1_point_right.opening_direction; bend_body2_point_left.opening_direction = bend_body1_point_left.opening_direction; // note we are switchingpointsbend_body2_point_left.p2 = bend_body1_point_left.p1; bend_body2_point_right.p2 = bend_body1_point_right.p1; bend_body2_point_left.p = bend_body1_point_left.p; bend_body2_point_right.p = bend_body1_point_right.p;}}} break; case BM_TYPE_CONE: break; default:; // flange for each unknown or illegal surface;}} / * Calculate the length. * / if (adj_body1) {// if the flange length computation fails, pretend the adjacent body does not exist.for simplicity.if (! bend-> compute_flange_length (parent-> get_view_type (), adj_body1, fl1)) (adj_body1 = NULL;-num_of_adjacent_bodies;}} if (adj_body2) {if (! Bend-> compute_flange_length (parent-> get_view_type (), adj_body2, fl2)) {adj_body2 = NULL;-num_of_adjacent_bodies;}} / * Mark as valid. Once the bend line dimension points are calculated for all bend lines, we can calculate the flange dimension points for the nest bend lines as well. * / data_valid = 1; // before we can return, we have to check if body1,2 left (right) bendline dimension points // are the same.// note the same meansnot the same pointers, but the contents are equivalent. if (adj_body1 && adj_body2) (body12_left_the_same = (bend_body1_point_left == bend_body2_point_left); body12_right_the_same = (bend_body1_point_right == bend_body2_point_right);} / Since there is no bend line to see, the body_required_visible pointer should point to the neighbor. * / if (1 == bend_body1_point_left.num_of_points) bend_body1_point_left.body_required_visible = adj_body1; if (1 == bend_body1_point_right.num_of_points) bend_body1_point_right.body_required_visible = adj_body1 be________________ == bend_body2_point_right.num_of_points) bend_body2_point_right.body_required_visible = adj_body2; return 1;} / *********** ********** ********** ** ******** ********** ********** ********** ********** ** ******** BM_AUTO_DIMENSION class stuff. ********** ********** ********** ******** ** ********** ********** ********** ********** ******** *** // * Certain heuristics: check if we can ignore some points in solid mode. In solid mode, we use this heuristic to save time. When two bend lines are using (potentially) equivalent flange-dimension points to display the flange-length, we simply bend lines with higher idx (for these two bend lines) Visibility information is calculated only for). * / void BM_AUTO_DIMENSION :: compute_points_to_ignore_in_solid (void) {int i; BM_AD_dim_corner * temp_point; for (i = 0; i <num_of_bendlines; i ++) (if (! bends [i]-> data_valid) continue; if (bends [i]-> adj_body1) (for (temp_point = bends [i]->body1_points;temp_point; temp_point = temp_point-> next ) (if (NULL == temp_point-> adj_bendline) continue; if ((temp_point->adj_bendline)-> get_idx ()> (bends [i]->bend)-> get_idx ()) continue; if (check_two_bendlines_adjacent_to_same_flange (bends [i]-> bend, bends [i]-> adj_body1, temp_point-> adj_bendline)) (temp_point-> ignore_in_solid_mode = 1;}}} if (bends [i]-> adj_body2) {for (temp_point = bends [i ]->body2_points;temp_point; temp_point = temp_point-> next) (if (NULL == temp_point-> adj_bendline) continue; if ((temp_point->adj_bendline)-> get_idx ()> (bends [i]-> bend) -> get_idx ()) continue; if (check_two_bendlines_adjacent_to_same_flange (bends [i]-> bend, bends [i]-> adj_body2, temp_point-> adj_bendline)) (temp_point-> ignore_in_solid_mode = 1;}}}} _ pointed_solid_ore_ } / * This function constructs an auto-dimension bend line and indicates the data structure. This is the main function that calculates dimension points. * / int BM_AUTO_DIMENSION :: compute_auto_dimension_data (void) {int i; // have to have a documentif (NULL == doc) return 0; // if no part, try to get a new part from the documentif (NULL == part ) {set_part (doc-> get_part ());} if (NULL == part) {dirty = 0; return 1;} points_to_ignore_in_solid_computed = 0; / * Get the view type. * / if (view) {view_type = view-> get_current_view ();} else {// we are screwedreturn 0;} / * Calculate all bend line dimension points for all bend lines. * / for (i = 0; i <num_of_bendlines; i ++) {bends [i]-> compute_BM_AD_bendline ();} / * Calculate flange dimension points for all bend lines. * / for (i = 0; i <num_of_bendlines; i ++) (if (bends [i]-> data_valid) (if (bends [i]-> adj_body1) bends [i]-> compute_BM_AD_flange_points (bends [i]->adj_body1); if (bends [i] -> adj_body2) bends [i]-> compute_BM_AD_flange_points (bends [i]->adj_body2);}} dirty = 0; return 1;}
Appendix I
Examples of some basic auto-sizing functions, constructors, destructors and some other basic functions
// # include "stdafx.h"#include"BendCAD.h"#include"BendCADDoc.h"#include"BendCADViewPart.h"#include"AUTODIM.HXX" / *********** * ********* ********** ********** ********** ********** * ********* ********** ********** BM_AD_dim_corner class stuff. ********** ******* *** ********** ********** ********** ********** ******* *** ********** *********** / BM_AD_dim_corner :: BM_AD_dim_corner (void) (visible = -1; num_of_points = 0; bend = NULL; next = NULL; adj_bendline = NULL; body_required_visible = NULL; ignore_in_solid_mode = 0;} / * This constructor is for creating a dimension point with only one point in it (point p). * / BM_AD_dim_corner :: BM_AD_dim_corner (BM_POINT const & P, BM_AD_bendline * B, BM_3D_BODY * Body_required_visible, BM_VECTOR const & OD, int RB, BM_AD_dim_corner ** prev, _BM_BendLINE * __ end_of = = B; opening_direction = OD; can_reverse_opening_dir = RB; next = NULL; body_required_visible = Body_required_visible; adj_bendline = adj_bend; ignore_in_solid_mode = 0; if (prev) * prev = this;} / * This constructor has 3 points inside Is for generating. * / BM_AD_dim_corner :: BM_AD_dim_corner (BM_POINT const & P, BM_POINT const & P1, BM_POINT const & P2, BM_AD_bendline * B, BM_3D_BODY * Body_required_visible, BM_VECTOR const & OD, int RB, BM_AD_ = 3; p = P; p1 = P1; p2 = P2; bend = B; opening_direction = OD; can_reverse_opening_dir = RB; next = NULL; body_required_visible = Body_required_visible; adj_bendline = adj_bend; ignore_in_solid_mode = 0; if (prev) * prev = this;} / * Assign one dimension point to another dimension point. This function copies the contents exactly. It is not certain whether it is a very useful function. * / voidBM_AD_dim_corner :: operator = (BM_AD_dim_corner const & given_point) {num_of_points = given_point.num_of_points; p = given_point.p; p1 = given_point.p1; p2 = given_point.p2; bend = given_point.bend; opening_reverse_direction_ = given_point.can_reverse_opening_dir; visible = given_point.visible; screen_x = given_point.screen_x; screen_y = given_point.screen_y; z_buf_value = given_point.z_buf_value; ignore_in_solid_mode = given_point.ignore_in_solid_mode;} / * Returns TRUE if the point is the same as this point. Two dimension points are equivalent when their one point p is on a line defined by another dimension point's line (point p, opening direction) and when their opening directions match. Here we rely on the fact that the open vector is normalized. it returns 2 iff both points p match, otherwise 1. * / int BM_AD_dim_corner :: operator == (BM_AD_dim_corner const & another_dim_point) {int ret_val = 1; double k; if (num_of_points <1 || another_dim_point.num_of_points <1) return 0; // point has to be on the lineif (! BM_is_point_on_line (p, opening_direction, another_dim_point.p, & k)) return 0; if (fabs (k) <= BM_PRECISION) ret_val = 2; // since both vectors should be normalized, the dot-product is the cos of the angle.double x = opening_direction% another_dim_point.opening_direction; // check if both vectors agreeif (x> 0.99) return ret_val; // check if they have opposite direction and one of the can be reversedif (x <-0.99) {if (can_reverse_opening_dir || another_dim_point.can_reverse_opening_dir) return ret_val;} return 0;} / ********************* ****** **** ********** ********** ********** ********** ****** **** ********** BM_AD_bendline class stuff. ********** ********** ********** ** ******** ********** ********** ********** ********** ** ********* / BM_AD_bendline :: BM_AD_bendline (BM_AUTO_DIMENSION * owner, BM_BENDLINE * bendline) {parent = owner; bend = bendline; data_valid = 0; // data not valid-no data computed yetbend_body1_point_left.bend = bend_body1_point_right .bend = this; bend_body2_point_left.bend = bend_body2_point_right.bend = this; bend_body1_point_left.body_required_visible = bend_body1_point_right.body_required_visible = bend; bend_body2_point_left.body_required_visible = bendright_body_respectively void) {BM_AD_dim_corner * temp_point, * temp_p; // delete lists of pointsfor (temp_point = b ody1_points; temp_point; temp_point = temp_p) (temp_p = temp_point->next; delete temp_point;} for (temp_point = body2_points; temp_point; temp_point = temp_p) (temp_p = temp_point->next; delete temp_point;}} / **** ******* ********** ********** ********** ********** *** ******* ********** ********** ********** BM_AUTO_DIMENSION class stuff. ********* * ********** ********** ********** ********** ********* * ******************** *********** / BM_AUTO_DIMENSION :: BM_AUTO_DIMENSION (CBendCADDoc * BendCAD_doc) {doc = BendCAD_doc; view = ( CBendCADViewPart *) doc-> get_view (BENDCAD_VIEW_TYPE_PART); dc = NULL; part = NULL; dirty = 1; view_type = 1; // 3D viewreset_view_to_false_once_drawn = 0; points_to_ignore_in_solid_computed = 0; num_of_bendlines =; / states for dimension infom_bShowFlangeDim = TRUE; m_bShowBendDim = TRUE; m_bShowPartDim = FALSE; // initialize Auto-Dim colorsm_crFlange = RGB (0,0,255); m_crBend = RGB (0,0,255); m_crPart = RGB (0,0,255); // initialize font poin tersm_pFlangeFont = NULL; m_pBendFont = NULL; m_pPartFont = NULL; // initialize line and arrow stylesm_nLineStyle = PS_SOLID; m_nLineWeight = 1; // in pixelsm_nArrowStyle = 1; m_nArrowAngle = 30; // in degreesm_nArrowLength = 15 // in pixels initialize dirty region pointerpDirtyRegion = NULL;} BM_AUTO_DIMENSION :: ~ BM_AUTO_DIMENSION (void) {delete_contents ();} / * Destroy this auto-dimension target. * / void BM_AUTO_DIMENSION :: delete_contents (void) {int i; if (bends) (for (i = 0; i <num_of_bendlines; i ++) (if (bends [i]) delete bends [i];} delete [] bends; bends = NULL;} num_of_bendlines = 0; points_to_ignore_in_solid_computed = 0; part = NULL; dirty = 1;} / * this The function returns a pointer to the BM_AD_bendline structure that contains the dimension data for a given bend line. * / BM_AD_bendline * BM_AUTO_DIMENSION :: get_AD_bend_structure (BM_BENDLINE * bendline) {int i; for (i = 0; i <num_of_bendlines; i ++) (if (bends [i]-> bend == bendline) return bends [i];} return NULL;} / * This function is for a given bendline for a given adj-body (p-> p2) Returns a vector. It also calculates the line between the p2 points of the bend dimension points of the adjacent bend lines for this flange. * / BM_VECTOR const & BM_AUTO_DIMENSION :: compute_bend_direction_vector (BM_BENDLINE * bendline, BM_3D_BODY * adj_body, BM_LINE * p2_line) {static BM_VECTOR v; int i; for (i = 0; i <num_of_bendlines; i ++) (if (bends [i]-> data_valid && bends [i]-> bend == bendline) (if (bends [i]-> adj_body1 == adj_body) (v = (bends [i]- > bend_body1_point_left) .p2-(bends [i]-> bend_body1_point_left) .p; p2_line-> set ((bends [i]-> bend_body1_point_left) .p2, (bends [i]-> bend_body1_point_right) .p2); return v ;} else if (bends [i]-> adj_body2 == adj_body) (v = (bends [i]-> bend_body2_point_left) .p2-(bends [i]-> bend_body2_point_left) .p; p2_line-> set ((bends [i]-> bend_body2_point_left) .p2, (bends [i]-> bend_body2_point_right) .p2); return v;}}} return BM_null_vector;} / * This function has a flange dimension point adjacent to a given adj-body It is used to propagate the effect of drawing the flange length for a given bend line to account for the fact that It returns TRUE when adj-bend is marked as drawn for a given flange as well. * / int BM_AUTO_DIMENSION :: compute_effects_flange_length_drawn (BM_BENDLINE * bendline, BM_3D_BODY * adj_body, BM_AD_dim_corner * bend_dim_point / * bend dim point for bendline * /, BM_AD_dim_corn_bend_end_ * ; int * p_body_drawn; BM_AD_dim_corner ** p_drawn_bend_dim_point; BM_AD_dim_corner ** p_drawn_flange_dim_point; int i; // first we have to find a BM_AD_bendline structure for this adj-bendfor (i = 0; i <num_of_bendlines; i ++) (if (! bends [i]-> data_valid || bends [i]-> bend! = adj_bend || bends [i]-> ignore) continue; if (bends [i]-> adj_body1 = = adj_body) (if (bends [i]-> body1_drawn) return 0; p_body_points = & (bends [i]->body1_points); p_body_drawn = & (bends [i]->body1_drawn); p_drawn_bend_dim_point = & (bends [i ]->drawn_bend_dim_point1); p_drawn_flange_dim_point = & (bends [i]->drawn_flange_dim_point1);break;} else if (bends [i]-> adj_body2 == adj_body) (if (bends [i]-> body2_drawn) return 0; p_body_points = & (bends [i]->body2_points); p_body_drawn = & (bends [i]->body2_drawn); p_drawn_bend_dim_point = & (bends [i]->drawn_bend_dim_point2); p_drawn_flange_dim_point = _- bend_dim_point = _ ); break;} else return 0;} if (i> = num_of_bendlines) return 0; // now we need to check if the list of flange dimensionpoints for this newly found // BM_AD_bendline structure contains any flange dimension points that are adjacent to our bendlineBM_AD_dim_corner * temp_point; for (temp_point = * p_body_points; temp_point; temp_point = temp_point-> next) (if (temp_point-> adj_bendline == bendline) break;} if (NULL == temp_point) return 0; // mark the flange length for the adj-bend drawn with respect to this adj -body * p_body_drawn = 1; * p_drawn_bend_dim_point = flange_dim_point; * p_drawn_flange_dim_point = bend_dim_point; return 1;} / * This function is used when adj_bend has a flange-dimension point for a given flange adjacent to a given bend line Returns TRUE. * / int BM_AUTO_DIMENSION :: check_two_bendlines_adjacent_to_same_flange (BM_BENDLINE * bendline, BM_3D_BODY * flange, BM_BENDLINE * adj_bend) {BM_AD_dim_corner ** p_body_points; int i; // firstBM_ i_ <num_of_bendlines; i ++) (if (! bends [i]-> data_valid || bends [i]-> bend! = adj_bend) continue; if (bends [i]-> adj_body1 == flange) (p_body_points = & (bends [i]->body1_points);break;} else if (bends [i]-> adj_body2 == flange) (p_body_points = & (bends [i]->body2_points);break;} else return 0;} if (i > = num_of_bendlines) return 0; // now we need to check if the list of flange dimension pointsfor this newly found // BM_AD_bendline structure contains a flange dimension points that is adjacent to our bendlineBM_AD_dim_corner * temp_point; for (temp_point = * p_body_points; temp_point temp_point = temp_point-> next) {if (temp_point-> adj_bendline == bendline) return 1;} return 0;} / * Set a new part. This also updates the view class pointer and sets some other parameters. * / void BM_AUTO_DIMENSION :: set_part (BM_PART * new_part) {BM_BENDLINE * bendlist; int i; delete_contents (); if (NULL == doc) return; part = new_part; if (NULL == part) return; half_metal_thickness = (part -> get_metal_thickness ()) / 2.0; // allocate the bendlistif (0 == (num_of_bendlines = part-> get_number_of_bendlines ())) return; if (NULL == (bends = new BM_AD_bendline * [num_of_bendlines])) goto failure; bendlist = part-> get_bendline_list (); for (i = 0; i <num_of_bendlines; i ++) (if (bendlist) {bends [i] = new BM_AD_bendline (this, bendlist); bendlist = (BM_BENDLINE *) bendlist-> next ();} else bends [i] = NULL;} // note , dirty is TRUEreturn; failure: delete_contents ();}
Appendix J
Example of a bend model view implementation including entity visibility functions for sheet metal parts
#include "stdafx.h" // include all BMAPI files # include "ALLBMAPI.HXX" // RW_DRAW library include file. # include "RW_DRAW.HXX"#include"BendCADDoc.h"#include"BendCADViewPart.h" // RenderWare include files; 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> / * Given a BM_POINT representing a point in world coordinates, one can project it onto view window coordinates. A) Ifthe display is showing the SOLID version of the part, this function passes back a pointer to the edge closest to the camera that lies underthat projected point.The x_pos, y_pos, and z_depth pointers carry theview window coordinates (with top left corner as (0,0) and the z-buffervalue.If the projected point is not in the viewing volume, the return value is 0; then of course the edge pointer is meaningless, and is set to NULL.If the projected point IS within the viewing volume, then thereturn value is 1, and the edge pointer points to the edge that lies under the projected point.If the pointer is NULL, no edge lies under the projected point.B) If the display is showing the WIREFRAME version of the part, only the return value: 1 if within view volume, 0 otherwise-should be examined.If return value is 1, x_pos, y_pos and z_depth values have meaning.The edge pointer is always NULL. * / int CBendCADViewPart :: map_point_to_closest_edge (BM_POINT const & three_d_point, int * x_pos, int * y_ pos, double * z_depth, BM_EDGE ** closest_edge) {int x, y, visible = 1; double z; visible = map_3d_to_screen (three_d_point, & x, & y, &z); if (! visible) {// Point is outside viewing volume if (closest_edge) * closest_edge = NULL; if (x_pos) * x_pos = x; if (y_pos) * y_pos = y; if (z_depth) * z_depth = z; return 0;} // Now point is inside view volume. if (x_pos) * x_pos = x; if (y_pos) * y_pos = y; if (z_depth) * z_depth = z; if (! mi_show_solid) {// Wireframe being drawn; just return that point is if (closest_edge) * closest_edge = NULL; // within view vol.return 1;} // Now solid is being shown.if (! Closest_edge) return 1; // Point is within view volume.Pick that point.pick_point_rw (x, y, closest_edge); return 1;} // This function returns the view window coordinates of a point, with top left corner as (0,0), and the // z-buffer depth, given the three-dimensional world coordinates of the point. soby calling either // map_3d_to_screen_solid or map_3d_to_screen_wire, depending on whether wireframe or // On return, iff * x_pos, * y_pos are both zero, the point was not mapped onto the screen at all.int CBendCADViewPart :: map_3d_to_screen (BM_POINT three_d_point, int * x_pos, int * y_pos, double * z_depth) {int visible; if (mi_show_solid) visible = map_3d_to_screen_solid (three_d_point, x_pos, y_pos, z_depth); else visible = map_3d_to_screen_wire (three_d_point, x_pos, y_pos, z_depth); return visible;} // This function returns the view window coordinates of a point, with top left corner as (0,0), and the // z-buffer depth, given the three-dimensional world coordinates of the point, using OpenGL utilities // (ie. when wireframe is on). return value is 0, point is not mapped onto screen, ie. not visible.int CBendCADViewPart :: map_3d_to_screen_wire (BM_POINT three_d_point, int * x_pos, int * y_pos, double * z_depth) {int viewport [4], visible = 1; double width, height, depth; double model_mat [16], proj_mat [16], array [16]; // Get the current viewport coords. glGetIntegerv (GL_VIEWPORT, viewPort); // Now build a modelview matrix out of the current set of transformations.glMatrixMode (GL_MODELVIEW); glPushMatrix (); glTranslated (md_x_trans, md_y_trans, 0.0); convert_rw_matrix_to_gl_array (md_rot_matrix, array); -m_part_centroid.X (),-m_part_centroid.Y (),-m_part_centroid.Z ()); glGetDoublev (GL_MODELVIEW_MATRIX, model_mat); glGetDoublev (GL_PROJECTION_MATRIX, proj_mat); glPopMatrix (); gluProject (three_d.point__ Y (), three_d_point.Z (), model_mat, proj_mat, viewport, & width, & height, &depth); if (((int) width> m_old_rect.right) || ((int) width <0)) visible = 0; if (((int) height> m_old_rect.bottom) || ((int) height <0)) visible = 0; if (x_pos) * x_pos = (int) width; if (y_pos) * y_pos = (m_old_rect.bottom-(int) height); if (z_depth) * z_depth = depth; return visible; } // This function returns the view window coordinates of a point, with top left corner as (0,0), and the // z-buffer depth, given the three-dimensional world coordinates of the point, using RenderWare utilities // (ie. when solid is on) .If return value is 0, point is not mapped onto the screen, ie.not visible.// Note: At present, same as map_3d_to_screen_wire.int CBendCADViewPart :: map_3d_to_screen_solid (BM_POINT three_d_point, int * x_pos, int * y_pos, double * z_depth) {int viewport [4], visible = 1; doublewidth, height, depth; double model_mat [16], proj_mat [16], array [16]; // Get the current viewport coords glGetIntegerv (GL_VIEWPORT, viewport); // Now build a modelview matrix out of the current set of transformations.glMatrixMode (GL_MODELVIEW); glPushMatrix (); glTranslated (md_x_trans, md_y_trans, 0.0); convert_rw_matrix_to_gl_array (md_ro t_matrix, array); glMultMatrixd (array); glTranslated (-m_part_centroid.X (),-m_part_centroid.Y (),-m_part_centroid.Z ()); glGetDoublev (GL_MODELVIEW_MATRIX, model_mat); glGetDoublev (GL_PROJECTION_MATRIX; prop_matP; ); gluProject (three_d_point.X (), three_d_point.Y (), three_d_point.Z (), model_mat, proj_mat, viewport, & width, & height, &depth); if ((((int) width> m_old_rect.right) || ( (int) width <0)) visible = 0; if (((int) height> m_old_rect.bottom) || ((int) height <0)) visible = 0; if (x_pos) * x_pos = (int) width; if (y_pos) * y_pos = (m_old_rect.bottom-(int) height); if (z_depth) * z_depth = depth; returnvisible;} // This function picks the point indicated by map_3d_to_screen, using RenderWare picking, so this is // called only when solid is being shown.Note that the pick position is with respect to the top left // corner of the view window being (0 , 0) .If the pick results in an edge, apointer to the edge is // passed back in picked_edge; else, picked_edge is set to null.This does not modify the selection // set in any way.voidCBendCADViewPart :: pick_point_rw ( int x_pos, int y_pos, BM_EDGE ** picked_edge) (if (picked_edge == NULL) return; if ((x_pos> m_old_rect.right) || (y_pos> m_old_rect.bottom)) (// Make sure point given is within * picked_edge = NULL; // viewport.return;} RwClump * picked_clump = NULL; RwClump * parent_clump = NULL; long parent_tag, clump_tag, key = 0; BM_EDGE * edge = NULL; if (! RwPickScene (m_scene, x_pos, y_pos, m_camera , & m_pick)) {// Picking command was not successful. * Picked_edge = NULL; return;} if (m_pick.type == rwNAPICKOBJECT) {// No clump was picked. * Picked_edge = NULL; return;} else if (m_pick.type == rwPICKCLUMP) (// Some clump was picked; process it. ) {* picked_edge = NULL; return; // A trivial bendline or forming was picked.} // Now some real edge was picked.key = (parent_tag% 10000) * 100000 + clump_tag; if (clump_tag) // Safety check; we expect clump_tag to be non-zero. * picked_edge = map_list_name_to_bm_edge (parent_tag, clump_tag);}} // This function returns the ratio of the view volume dimension (object space dimensions) to // the viewportdimension (device space dimensions) .double CBendCADViewPart :: get_object_to_device_ratio (void) {double ratio; if (m_old_rect.right) ratio = 2.0 * md_current_view_vol [0] / (double) (m_old_re ct.right); else ratio = 0.0; return ratio;} / * Given a BM_POINT, which represents a point in worldcoordinates, one can project it onto view window coordinates.This function first checks if the projected point is within the viewing volume. If it IS within viewing volume, the pointer "visible" carries value 1; else, 0.If the point is not visible, no other parameters have any meaning; the return value is 0. Now suppose the point is visible. the display is showing the SOLID version of the part, this function checks ifANY of the three_d_bodies in the array "three_db_array" lies "approximately under" the projected point.If the answer is yes, return value is 1; else, return value is zero The x_pos, y_pos, and z_depth pointers carry the view window coordinates (with top left corner as (0,0)) and the z-buffer value.The array "thee_db_array" must be terminated by a NULL pointer to indicate end of array B) If the display is showing the WIREFRAME version of the part the return value is always zero.If the point is within view volume, * visible is set to 1; else, 0.If * visible is 1, x_pos, y_pos and z_depth values have the meaning mentioned above. * / int CBendCADViewPart :: is_3d_body_near_point (BM_POINT const & three_d_point, BM_3D_BODY ** three_db_array, int * visible, int * x_pos, int * y_pos, double * z_depth) {int x, y, is_visible = 1; double z; int found = 0; is_visible = map_3d_to_screen (three_d_point, & x, & y , &z); if (! is_visible) {// Point is outsideviewing volume.if (x_pos) * x_pos = x; if (y_pos) * y_pos = y; if (z_depth) * z_depth = z; if (visible) * visible = 0; return 0;} // Now point is insideview volume.if (x_pos) * x_pos = x; if (y_pos) * y_pos = y; if (z_depth) * z_depth = z; if (visible) * visible = 1 ; if (! mi_show_solid) {// Wireframe being drawn; just return that point is return 1; // within view volume.} // Now solid is being shown.if (! three_db_array) return 0; // Point is within view volume.Pick pixels in a triangle around that point.found = pick_point_for_3db_rw ((x -2), (y-2), three_db_array); if (found) return 1; found = pick_point_for_3db_rw ((x -2), (y + 2), three_db_array); if (found) return 1; found = pick_point_for_3db_rw ( (x + 2), (y + 2), three_db_array); if (found) return 1; found = pick_point_for_3db_rw ((x + 2), (y-2), three_db_array); if (found) return 1; return 0 ;} // This function picks the point indicated, using RenderWare picking, so this is called only when solid is // being shown.Note that the pick position is with respect to the top left corner of theview window being // (0, 0) .If the pick results in a three_d_body's clump, and the picked clump corresponds to ANY of the // three_d_bodies inthe array passed, return value is 1; if no match or no three_d_body, return is 0.// This does not modify the selection set in any way.int CBendCADViewPart :: pick_point_for_3db_rw (int x_pos, int y_pos, BM_3D_BODY ** three_db_array) {if (three_db_array == NULL) return 0; if ((x_pos> m_old_rect.right) || (y_pos> m_old_rect .bottom)) {// Make sure p oint given is withinreturn 0; // viewport.} RwClump * picked_clump = NULL; RwClump * parent_clump = NULL; long parent_tag, clump_tag, required_id; int found = 0; if (! RwPickScene (m_scene, x_pos, y_pos, m_camera, & m_pick) ) {// Picking command was not successful.return 0;} if (m_pick.type == rwNAPICKOBJECT) {// No clump was picked.return 0;} else if (m_pick.type == rwPICKCLUMP) {// Some clump was picked; process it.picked_clump = m_pick.object.clump.clump; parent_clump = RwGetClumpParent (picked_clump); parent_tag = RwGetClumpTag (parent_clump); clump_tag = RwGetClumpTag (picked_clump); if (parent_tag == 1) {// Body of face / bendline / formingwas picked.for (int i = 0; three_db_array [i]; ++ i) {// Check if it matches any of the ones in array.if (three_db_array [i] == NULL) break; required_id = three_db_array [i]-> get_idx (); if (clump_tag% 10000 == required_id) {found = 1; break;}} return found;} // Now some edge's clump was picked. Check if it matches any of the ones in array.for (int i = 0; three_db_array [i]; + + i) (if (three_db_array [i] == NULL) break; required_id = three_db_array [i]-> get_idx (); if (parent_tag% 10000 == required_id) {found = 1; break;}}} return found; } // This allows the user to insert items into the selection set. "List" is an array of pointers // to three-d-bodies, terminated by NULL to indicate end of array.If list is passed as NULL, every // three-d-body in the part is inserted into the selection set.void CBendCADViewPart :: insert_selection_set (BM_3D_BODY ** list) {int tag; BV_SELECT_DATA * data = NULL; if (! list) {// Insert every three_d_body in part into selection set.BM_PART * part = NULL; CBendCADDoc * pDoc = GetDocument (); ASSERT_VALID (pDoc); part = pDoc-> get_part (); if (! part) return; BM_FACE * face = NULL; BM_BENDLINE * bendline = NULL; BM_FORMING * forming = NULL; for (face = part-> get_face_list (); face; face = (BM_FACE *) face-> next ()) {if (! Face) continue; tag = 100000 * (face-> get_idx ( )) + 10000 + face-> get_idx (); if (! M_selection_set.find (tag, NULL)) (data = new BV_SELECT_DATA; data- > key = tag; data-> edge = NULL; data-> world_pt = BM_POINT (0.0, 0.0, 0.0); m_selection_set.insert (tag, (long) data);}} for (bendline = part-> get_bendline_list () ; bendline; bendline = (BM_BENDLINE *) bendline-> next ()) (if (! bendline) continue; tag = 100000 * (bendline-> get_idx ()) + 10000 + bendline-> get_idx (); if (! m_selection_set .find (tag, NULL)) (data = new BV_SELECT_DATA; data-> key = tag; data-> edge = NULL; data-> world_pt = BM_POINT (0.0, 0.0, 0.0); m_selection_set.insert (tag, (long ) data);}} for (forming = part-> get_forming_list (); forming; forming = (BM_FORMING *) forming-> next ()) {if (! forming) continue; tag = 100000 * (forming-> get_idx ( )) + 10000 + forming-> get_idx (); if (! M_selection_set.find (tag, NULL)) (data = new BV_SELECT_DATA; data-> key = tag; data-> edge = NULL; data-> world_pt = BM_POINT (0.0, 0.0, 0.0); m_selection_set.insert (tag, (long) data);}} DrawPart (m_hdc); return;} BM_3D_BODY * three_d_body; long i; for (i = 0, three_d_body = list [0]; three_d_body; ++ i, three_d_body = list [i]) (if (! three_d_body) break; ta g = 100000 * (three_d_body-> get_idx ()) + 10000+ three_d_body-> get_idx (); if (! m_selection_set.find (tag, NULL)) (data = new BV_SELECT_DATA; data-> key = tag; data-> edge = NULL; data-> world_pt = BM_POINT (0.0, 0.0, 0.0); m_selection_set.insert (tag, (long) data);}} DrawPart (m_hdc); return;} // This function returns the largest of the x , y and z projections of the part's // bounding box.double CBendCADViewPart :: get_approx_part_size (void) {if (md_part_bbox_size) {double size = __max (md_part_bbox_size [0], md_part_bbox_size [1]); size = __max (size, md_part_box [2]); return size;} else return 0.0;} // This function passes back the bounding box size of the part in its original orientation, in the // array "dimensions". This array should be at least of size 3 Returns 1 if successful, 0 otherwise.// Caution: This is a quick and hence not very accurate calculation; if you want greater precision, // writeyour own function.int CBendCADViewPart :: get_part_dimensions (double * dimensions) {CBendCADDoc * pDoc = GetDocu ment (); if (! pDoc) return 0; BM_PART * part = pDoc-> get_part (); if (! part) return 0; if (! dimensions) return 0; int i; BM_POINT centroid; RwMatrix4d * temp = RwCreateMatrix (); i = compute_part_centroid (part, 1, &centroid); if (! i) return 0; i = compute_part_bbox (part, 1, temp, centroid, dimensions, NULL); if (! i) return 0; RwDestroyMatrix (temp ); return 1;}
Appendix K
PART.HXX comments on bend models and substructures
/ * This file contains the definition of the BMAPI BM_PART class. Most of the partial functions are in PART.CPP. Constructors and destructors are in PART_NEW.CPP. The serialization functions are in PART_LOAD_x.CPP and PART_SAVE.CPP. The folding functions are in FOLD.CPP and 3D_FUNC.CPP. The unfolding function is in UNFOLD.CPP. ***** ******** ********* ********* ********* ********* * ******** Discussion: One of the design principles of -BMAPI is to try to accurately represent the whole part in thickness and everything. One of the benefits of this is that we can ask for something and get an answer quickly. Even if the answer is not overtly expressed, it is easily calculated. Another advantage of it is that we represent the part as a "solid part", so we can immediately model the part in 3D. -One of the special properties of the sheet is that it is symmetrical. We can use the benefits of this fact when we represent that part and reason about it. For example, we can represent only one side of the sheet and the other is defined as we know the thickness vector. One problem is how we make up a part from it when we are given a flat version of the part (which usually does not include thickness). Do we adopt that this flat represents the neutral line of the part? In this BMAPI, we have a flat version of the part that is overtly represented in the bend model, when the part is on the top view (top view) The bottom side is adopted. Another important point is that this flat version is on the XY plane. In this way, even if the thickness changes, the change to our model is minimal. -Flat represents the bottom side of the sheet, while flat dimensions represent neutral line dimensions. That is, when we bend the part, the neutral line dimension of the bent part coincides with the flat dimension (or shifted by the amount defined by the bend deduction). This is inadequate for the surface because inside = neutral line = outside them. But it is important for bend lines. That means that the flat underlying the bend line is mapped onto the neutral line of the bend arc. -BMAPI normally does not change the base-body 2D-> 3D conversion when the part is collapsed. However, when the base-body is a bend line and changing some of the ben parameters (eg, bend angle), the 2D-> 3D conversion matrix is marked as 'not-up-to-date'. When we use this old transformation matrix, the results are bad. Therefore, we cannot actually use an out-of-date conversion matrix. In that case, however, we have nothing better to do than resetting the transformation matrix to a match matrix. -The size of all 3D bodies can be changed in two ways. First, if the surface is trimmed by an amount equal to half the amount of bend deduction. Second, every body can have a trim value associated with it for adjacent bend lines. This body is trimmed by this amount when the adjacent bend line is bent. -BM API can load all known (ie recent and all early) versions of BMAPI files. -When the part is folded, only 2D-> 3D conversion is calculated immediately. The remainder of the calculation is done on demand, ie whenever necessary. When we unfold a part, all things are calculated immediately, namely the 3D-2D transformation and the flat version of the part. -When parts are unfolded, BMAPI uses the current 3D-versions of the 3D-body, regardless of whether they are marked as up-to-date. The -BM_PART class has several high-level functions that facilitate part generation. For example, it has a function that checks the flat version of a part and fixes any problems found. Furthermore, it has a function that generates a bend line for a part when only one set of faces is given. These are high-level functions that are common tasks in many applications. -For partial bend lines, it is absolutely necessary that they have a specific center line. Without a center line, the bend line is almost useless and it cannot be folded or unfolded. Bend line center lines are used for three purposes:-Bend line folding-For unfolding. -To represent a bend line when the bend line is empty. -To determine the direction of the bend line. The centerline is the most “target” in the 2D (ie flat) version of the part, since the flat version has a fixed orientation (ie the normal must be (0,0,1)). Please note that. In partial 3D versions, the centerline is somewhat "subjective" because its meaning is defined by the underlying surface that can be changed. For example, we can flip the surface (which inevitably does not change the lamina) and as a result the center line must be reversed as well to keep the bend line orientation the same. -All bend lines have associated deductions. This bend reduction controls how the partial dimension changes (at this bend line) when the part is folded or unfolded. Bend deduction values can take both positive and negative values. When it is positive and we fold the part, the dimension of the part expands, and when it is negative, the part dimension shrinks. Positive bend deduction means folding the part when unfolding and shrinking the part when shrinking, and negative bend defolding therefore folds the part when unfolding and part when expanding. It is an industry standard that means shrinking. -BM_PART has a parameter bendline_dimensions_status that controls the dimensions of the part. It is added to facilitate part design and generation. It often happens that a user is given a partial dimension (for example) from outside to outside. These dimensions are fixed and specified by the customer. The goal of the sheet design process is to produce a flat in this part so that when the conoflat is folded, its dimension exactly matches the predetermined dimension. In the design process, the user can change parts in a series of ways. However, when this is given, we always want to keep the partial dimension unchanged. When bendline_dimensions_status is TRUE, BMAPI will always use partial dimensions (on all bend lines) whenever possible when the user changes part / bend line parameters (such as sheet thickness or bend line radius). ) Try to keep it constant. Otherwise we are not careful. -Another problem that arises in connection with the previous problem is that the partial dimensions are usually specified as OUTSIDE / INSIDE / NEUTRAL dimensions. For example, the user is given a box and specifies that its outer dimension is 100x100. Technically, the user has specified that all bend lines in this box on the flat represent outer dimensions. For example, when the user later changes the thickness of the sheet, the outer dimension remains the same, i.e. all added thicknesses "must go inside the box" In general, the user (or customer) Even within the same plane, partial dimensions are identified as OUTSIDE / INSIDE / NEUTRAL dimensions. For example, the user can say that across the box, the dimension is given from the inside of the sheet on one side to the outside of the sheet on the other side. We have a variable in the part that keeps track of whether the user wants to keep the part dimension constant. If this variable is set so that the user does not require that the partial dimension be held constant, this INSIDE / OUTSIDE / NUETRAL-LINE foil business is ignored. * / # ifndef BM_PART_HXX_INCLUDED # define BM_PART_HXX_INCLUDED # include <stdio. h>#include"GLOBAL. HXX "#include" ENTITY. HXX "#include" TOPOLOGY. HXX "class BM_PART: public BM_ENTITY {friend BM_FACE; friend BM_HOLE; friend BM_BENDLINE; friend BM_FORMING; friend BM_TOPOLOGY; friendBM_TOPOLOGY_RECORD; friend BM_BEND_PROPERTY; friend BM_BEND_PROPERTY_SIMULTANEOUS; /-every has_BM // also, the type (BM_ENTITY_TYPE_PART) is stored in BM_ENTITY. protected: / * These variables let the user associate parameters such as name, number, and material type with the part. * / char material_type [256]; char name [256]; char number [32]; / * These variables describe material and metal properties. * / double metal_thickness; / * Within this part, two points are considered to be the same if the distance between them is about this value. * / double distance_tolerance; / * All parts have a list of bend characteristics. When a bend line has a bend characteristic, the target of this characteristic must be on the list of bend characteristics associated with the part. This is required when we save or load a part. These variables are only used internally. BMAPI users do not have access to these variables. * / long number_of_bend_properties; BM_BEND_PROPERTY * list_of_bend_properties; / * part topology Note that it is not possible to add a body directly to the list here. This is done only when the body is added to the partial topology. * / BM_TOPOLOGY topology; // number of different3D bodies in the part. // these numbers should be consistent with the part topology. long number_of_faces; long number_of_holes; long number_of_bendlines; long number_of_formings; // lists of faces, holes and bendlines of the part // Note that these are lists of BM_3D_BODY's. BM_FACE * first_face; BM_HOLE * first_hole; BM_BENDLINE * first_bendline; BM_FORMING * first_forming; / * These parameters represent the bend sequence related to the part. * / long bend_sequence_size; BM_LINKED_LIST_NODE * bend_sequence; / * This parameter controls partial dimensions. When it is TRUE, BMAPI will change the dimension of a part (on all bend lines) whenever possible when the user changes the part / bend line parameters (such as sheet thickness or bend line radius). ) Try to keep it constant. Otherwise we are not careful. The default value is 0, and there is no need to keep the dimension constant. * / charbendline_dimensions_status; public: / * Constructors and destructors. PART_NEW. In CPP. * / BM_PART (void); BM_PART (BM_PART * existing_part); ~ BM_PART (void); // use this to erase the content of the part. the part willbe empty. // it will use topology :: erase_content () to destroy the topology and will then // destroy all bodies in the part. void erase_content (void); void get_material_type (char * out_mat_type); void set_material_type (char * in_mat_type); void get_name (char * out_name); void set_name (char * in_name); void get_part_number (char * out_number); void set_part_number (char * in_number); // get number of faces, holes, bendlinesinline long get_number_of_faces (void) const {return number_of_faces;} inline long get_number_of_holes (void) const {return number_of_holes;} inline long get_number_of_bendlines (void) const {return number_of_bendlines; long get_number_of_formings (void) const {return number_of_formings;} // get pointers to lists of faces, holes and bendlinesinline BM_FACE * get_face_list (void) const {return first_face;} inline BM_HOLE * get_hole_list (void) const {return first_hole;} inline BM_BENDLINE * get_bendline_list (void) const {return first_bendline;} inline BM_FORMING * get_forming_list (void) const {return first_forming;} // To get the number of bendproperties and the first property object on the list. inline BM_BEND_PROPERTY * get_list_of_bend_properties (void) const {return list_of_bend_properties;} inline long get_number_of_bend_properties (void) const {return number_of_bend_properties;} // this function tries to find a good default base face. // it chooses a face that has the largest bbox. BM_FACE * get_default_base_face (void); / * Function to obtain and change the distance tolerance for the part * / inline double get_distance_tolerance (void) const {return distance_tolerance;} void set_distance_tolerance (double new_distance_tolerance); / * Current metal thickness of this part Get * / inline double get_metal_thickness (void) const {return metal_thickness;} / * Changing the thickness causes many changes in the part. The surface needs to be slightly trimmed because the bend line is likely to change when the thickness is changed. Furthermore, the 2D-> 3D conversion of the surface is most likely to change. This occurs because the 3D shape of the bend line will change, and the flat represents a neutral-line dimension, so the 3D dimension of the part is most likely to change. It is almost certain that the bend line changes greatly. All bend line W3Ds must be recalculated. The 2D-> 3D conversion must also be recalculated. Note that the part itself does not move through the space as a result of changing thickness. However, the bend line 2D-> 3D conversion is marked as 'not-up-to-date'. One way to update them is given by taking any face as a base-face and re-folding that part (this is done only if it has its latest 2D-> 3D transformation) . The parts stay in the same place (because the base-surface stays properly), and the bend lines have their updated 2D-> 3D transformations. Changing the thickness is actually tricky because every body in a part is likely to have a 2D-> 3D conversion, and a disabled 3D version. The problem is that the user usually does not want to refold the part. We must therefore consider how to automatically obtain a new valid 2D-> 3D transform. Note that this function does not do that. This is a situation that must be done by some other function. This function does not attempt to match faces-bendlines exactly. To achieve that, after this function match_all_faces_adjacent_to_bendlines (. . . Call). In addition, set_metal_thickness_update_part (.sets a new thickness, then matches adjacent faces and computes a new updated 2D-> 3D transformation. . . ). * / void set_metal_thickness (doublethickness); void set_metal_thickness_update_part (double thickness); / * This function trims all faces in 3D space so that they touch the bend lines adjacent to them exactly (if necessary) . This function is good to call after the thickness has changed or after the bend line parameter has changed. * / void match_all_faces_adjacent_to_bendlines (void); / * Add 3D bodies (faces, holes, forming or bend lines) to the part. If it cannot be added, FALSE is returned. This function basically calls the add_body () member function of the topology. * / int add_3d_body (BM_3D_BODY * body); // get part topologyinline BM_TOPOLOGY * get_topology (void) const {return (BM_TOPOLOGY *) &topology;} / * These functions are available when the user can perform partial dimension on the bend line. Allows you to query and specify whether it should always be kept constant. * /// to get the current statusinline int get_bendline_dimensions_status (void) const {return bendline_dimensions_status;} // to set the new status. // for example, if we set it to TRUE, then from this point on, BMAPI // will try to keep to current part dimensions constant. void set_bendline_dimensions_status (int new_bendline_dimensions_status); / * Bend sequence-related functions * / void delete_bend_sequence (void); inline long get_bend_sequence_size (void) const {return bend_sequence_size;} // this function returns the number of bendlines copied into OUT arrayint get_Bend_sequence * _ bendlines [], long bendlines_array_length); // this function sets a new bend sequence for this bendlineint set_bend_sequence (BM_BENDLINE ** bendlines, long bendlines_array_length); // this function checksis a bendline is in the current bend sequence of the part. // if yes, itreturns its index in the bend sequence (ie. the number of this bendline // in the bend sequence order). This index is from 0 through sequence_lenght-1. // if this bendline is not in the bend sequence, it returns -1. int is_bendline_in_bend_sequence (BM_BENDLINE * bendline); // this function removes a bendline from the bend sequence. // note that if the bendlineis in a simultaneous bend property, it will replace the bendline // withanother bendline from the simultaneous bend property that is not already in the bend sequence. void remove_bendline_from_bend_sequence (BM_BENDLINE * bendline); // this function deletes the current bend sequence (if one exists) and creates a default // bend sequence. void create_default_bend_sequence (void); / * This function eliminates the flat version of all bend lines that do not contain holes. This function can be useful after the part is unfolded. Typically, a portion of the folded version includes a non-trivial bend line (ie, a non-zero inside radius and / or thickness). When parts are unfolded, BMAPI converts these bend lines to flat versions exactly as they are. For example, a 3D-version of a bend line with a thickness or radius other than zero is usually drawn with a curved arc. This maps to a planar version of the bend line. This means that in the planar version of the part, there is a rectangle between the two faces corresponding to the bend line. However, there are times when we don't want to see this rectangle. This function has a simple plane (ie, no holes in the plane) and processes only bend lines that are exactly adjacent to the two planes. This function cuts out all adjacent faces (trimming), touches the bend line centerline, and removes all rings (loops) in the bend line plane. Note that this function is usually used immediately after UNFOLD. Once a plane is trimmed, it also fits adjacent faces. This means that this function calculates and sets some special trimming values and later when we fold the part, we get the correct 3D-version where the face touches the bend line exactly . This function does not change the bend line. * / void eliminate_simple_bendlines_in_flat_version_A (void); / * This function scans all 3D-bodies in the part (except for forming) and trims their planar versions. Basically this function calls the BM_2D_BODY :: fix_flat () function for every 3D_body (except forming) in the part. Note that this function only checks the current planar version. This function returns FAILURE if any operation fails (ie memory allocation) or finds a problem that this function cannot solve. * / int fix_flat (void); / * This function checks that face normal meets the definition of the bend line. For example, if face1 has a normal (0,0,1) and there is a 90 degree front bend between face1 and face2, the normal of face2 must be (-1,0,0) . If there is an opposite normal, this function trims it. Otherwise, this function returns FAILURE if it finds a problem. If an input surface is given, this function checks only the connected components located at the center of that surface. Otherwise, this function checks the entire part. In this case, the order in which this function checks the faces is the face index order. This function performs some necessary checks (eg, when a bend line is bent, it must have a bend op, a3D-version (which can be empty) and a surface). This function checks whether the 3D-versions of all faces and bend lines are up to date. If either is not up-to-date, this function returns FAILURE. This function only checks if the current version is up-to-date, and if the current version is not up-to-date, it does not calculate a new 3D-version (since this function is normally used after unfolding, I don't want to calculate anything at this point). This function ignores holes and formings. In 3D_FUNC. CPP. * / int fix_3D_face_normals (BM_FACE * given_base_face = NULL); / * This function checks the 3D-body in the part and solves problems it finds. Note that this function only checks the current 3D-version. In addition, this function does not invalidate anything. Now this function: checks that face normal matches the bend line definition. For example, if face1 has a normal (0,0,1) and there is a 90 degree front bend between face1 and face2, the normal of face2 must be (-1,0,0) . This function returns FAILURE if any operation fails (ie memory allocation) or finds a problem that this function cannot solve. In 3D_FUNC. CPP. * / int fix_3D (void); / *********** ********** ********** ********** ********** ********** ********** ********** ********** This is the main high-level Bend Model function used for part design and construction. Its uses are as follows:-Create bend lines between faces so that the parts are combined (if possible). This function was created to streamline part production. A third-party CAD program is usually used to draw the part. The Bend Model does not control the CAD system, so for our purposes this drawing is just a collection of edges. For this reason, drawing must be analyzed to find the part structure. After that we can make bend lines and faces for the part. However, this input drawing is often ambiguous. In other words, faces, and especially bend lines, are not uniquely defined. Since this is a problem common to many applications, this function is part of the Bend Model. In addition, by implementing this function in the Bend Model, the surface detection software that forms part of the CAD system is simplified. In this function we assume that the edges of a face are aligned according to the left rule (rule) in a way that matches the plane normal (which defines the direction of the plane). Basically, this function assumes that all planes are correct by themselves when viewed separately. However, this function does not require that the orientation of adjacent planes be correct with respect to the bend line between them. This function probably does not work well when the part thickness is non-zero. This function can be used to generate bend lines for both the 3D-part version and the planar version of the part. However, a part can have either a planar or 3D version of the part, but not both. That is, all 3D-versions of the 3D-body must be null (in this case we get a planar version) or all planar versions must be null. Implementation is in AUTO_BEND. CPP. * / int auto_bend (void); / * This function was designed to facilitate the creation of parts from data sent to the Bend Model by the CAD system. The problem is that parts are often built piece by piece to make the information available. The problem, however, is that when we build the body of the part, we can't know in advance whether the input data represents a flat version (FLAT) or a 3D version of the part. Usually it is 3D_version. For this reason we assume by default that it is a 3D version. Later, when all of the part's 3D-body has been built, we can check that the input data is a 3D-version. If it is not a 3D-version, we must transfer all 3D-versions to the planar version. This function is designed for this purpose only and should not be used for any other purpose. Misuse of this function will crash the system. This function first checks if the plane version (FLAT) of the body is NULL. If this is not NULL, this function does not transfer the 3D-version. TODO: right now, it only moves faces. * / void BM_PART :: move_3D_to_flat (void); / *********** ******************** ******* *** ********** ********** ********** ********** ******* *** Bend Model can handle part operations in both directions. :-For the 3D version of the part, find the 2D (planar) version of the part. For the -2D (planar) version, fold it with the given bending parameters. Since BMAPI most often has two versions (2D and 3D) parts, it is important to maintain their consistency. BMAPI usually does not explicitly calculate the 2D and 3D versions of a part for efficiency reasons, but instead calculates them on demand (only when the user requests a calculation). In most cases we only need to know the transformation from one given body version to another body version. There is one difference between 2D-> 3D deformation and 3D-> 2D deformation. Usually 2D-> 3D transformations are specified by the user and can be implemented by the user in any way (the result may be incorrect for some reason, but for the time being ignore it for now). 3D-> 2D transformations correspond to unfolds, and there is only one way to do this. That is, for a given fixed 3D-version, there is only one planar version of the final part. Both folds and unfolds use part flexure information to calculate all 3D bodies individually according to their flex parameters. In general, these variants require that all bodies in the part have a 'flat' version or a '3D-version'. This means that if you have an initial 3D version of a part, you must unfold it before using the 2D-> 3D transformation. Unfold produces 'flat'. Fold creates '3D-version'. The user must first specify either the flat version or the 3D-version. ********** ********** ********** ********** ********** ********** ******************** *********** // * This function is in BMAPI Force the 3D version of the part (from flat) to be calculated. Specifically, BMAPI checks all face-hole-bend lines and if the 3D version is not new, BMAPI calculates the latest 3D version from flat using 2D-> 3D deformation. If the 2D-> 3D deformation is not new, BMAPI tries to calculate the latest valid 2D-> 3D deformation. Also, when a new 3D-version is calculated for a bend line, BMAPI first adapts the adjacent bend line. * / void bring_3D_up_to_date (void); / *********** ********** ********** ********** ********** ********** ********** ********** ********** 2D-> 3D transformation function ************ ********** ********** ********** **** ****** ********** ********** ********** *********** // * This function resets all transformations to identity transformation. This function also sets the 'bending_status' variable to FALSE on all bend lines. This function also marks all 3D versions of all faces as 'not-up-to-date', but does not recalculate them. Note that the 3D-> 2D deformation cannot be reset, so this function only resets the 2D-> 3D deformation. * / void reset_all_transformations (void); / * Reset the 2D-> 3D transformations of the part. 'body' is a surface with a deformation that becomes an identity deformation. The other bodies set their deformations according to the bending information related to the basic body (base body). This function updates all deformed matrices (matrix). Basically this function allows you to undo all the rotations and movements that the user has made to the entire part. * / void reset_part_2Dto3D_transformations (BM_3D_BODY * base_body); / *********** ********** ********** ******** ** ********** ********** ********** ********** ******** ** These functions let the user perform part rotation or movement. For example, when bending, the user may wish to reverse the part. These functions work uniformly throughout the part. That is, all face-hole-bend lines change in exactly the same way. Note that these functions are 2D-> 3D variants. That is, these functions only change the 3D version of the part, but these functions require computation of the planar version of the part. Basically the only thing these functions do is change the 2D-3D transformations associated with all bodies and change the 3D-versions of all bodies to 'not-up-to-date' (not up-to-date). It is to write. ********** ********** ********** ********** ********** ********** ********** ********** *********** // * The whole part is a line axis Rotate at a constant angle (in radians). The positive direction is clockwise when viewing the line direction. * / void rotate (BM_LINE const & line, double constangle); / * Translate the whole part with this vector * / void translate (BM_VECTOR const &translation_vector); / * Apply this transformation to the part * / void transform (BM_TRANSFORM const & transformation ); / *********** ********** ******************** ****** **** ********** ********** ********** ********** FOLD function. FOLD. Within the CPP module ************ ********** ********** ********** ******* *** ********** ********** ********** *********** // * Part 3D Calculate the version. This function calculates the 3D version of the part according to the base body. In other words, 'base_body' stays and the rest of the part moves. Note that if you have rotated or moved the entire part so far, the rotation or movement is still valid after this operation. Usually the user wants to set some bend line parameters and then call this function to update the part. This function calculates only the deformed body of the changing body (minimal change). The 3D version of each body is calculated on demand (only when the user requests a calculation). This function uses the member variable 'bending_status' of each bend line to determine whether to bend the bend line. Note that if the base-body 2D-> 3D transformation is not new, FOLD resets it to the identity transformation. * / int fold (BM_3D_BODY * base_body); / * This function assumes that each bend line member variable 'bending_status' is FALSE (if not, this function sets 'bending_status' to FALSE) Do the same, except that the list of bend lines to bend further is in the array 'bendline_array' (the length of the array is 'number_of_bendlines'). At the end of this function, each bend line member variable 'bending_status' indicates whether the bend line has been bent or not. * / int fold (BM_3D_BODY * base_body, BM_BENDLINE * bendline_array [], long number_of_bendlines); / * This function folds the first n bend lines in the bending order of the part. * / int fold_sequence (BM_3D_BODY * base_body, int n); / * If the 3D body has already calculated its 2D-> 3D deformation matrix, this function calculates the deformation matrix for a given bend line. This function assumes a number of things (these things are not checked):-This bend line is adjacent to the body. -This body already has the latest deformed matrix. -This bend line has the latest center_line_2D. Note that these two functions require the bend line to have a 2D centerline. This also means that the bend line is flat. For performance reasons, these functions do not check for the presence of a plane in the bend line, but instead assume that there is a plane in the bend line and reference it directly. This function is used by FOLD. * / int bend_bendline_wrt_3D_body (BM_3D_BODY * body / * finished body * /, BM_BENDLINE * current_bendline / * bendline whose transformation we are computing * /, BM_TRANSFORM * tf / * start with this transformation * /); / * The bendline has already been completed And the same except that we are calculating 3D bodies. This function is used by FOLD. * / int bend_3D_body_wrt_bendline (BM_BENDLINE * current_bendline / * finished bendline * /, BM_3D_BODY * body / * body whose transformation we are computing * /, BM_TRANSFORM * tf / * start with this transformation * /); / ******* **** ********** ********** ********** ********** ****** **** ********** ********** ********** UNFOLD function. UNFOLD. Within the CPP module ************ ********** ********** ********** ******* *** ********** ********** ********** ***********//*this function is Unfold the entire part. This function selects the default base body for each component of the connected part. This function moves the part to the XY plane so that the base body overlaps the origin (0,0,0) when the part is unfolded. The function first calculates the 3D-> 2D deformation for each 3D body, then calculates Wflat for each 3D-body, then trims Wflat and finally calculates the plane. This function selects the face that has a non-NULL normal as the base-body and the lowest id. If this is not possible, the function selects the first bend line with a base surface that can compute a non-null normal as the base-body. This function unfolds all connected components of the part using BM_PART :: unfold (BM_3D_BODY * base_body). This function returns 1 if it succeeds entirely, and 0 if it fails to unfold partly. This function first checks that all face normals are correct for the current bend line. Note that this function uses the current 3D-version of each 3D-body. All 3D-versions must be new to unfold. This function does not check if the 3D body is new, but actually marks all 3D bodies as current. The function also assumes that all bend lines have valid 3D-centerlines. Again, this function does not check the 3D-centerline, but instead just ratifies the current centerline. * / int unfold (void); / * This function unfolds only the connected components of the part centered around the base-body. This function is used by the BM_PART :: unfold (void) function to unfold the entire part. This function calculates a new 3D-> 2D deformation for each 3D-body of the connected component, and then calculates a new planar version for each 3D-body using the BM_3D_BODY :: compute_flat_from_3D () function. If the base body is a face and the input flag is set to TRUE, the first execution of this function will check that all face normals are correct for the current bend line. It is. However, this is limited to connecting components centered on the base body (surface). Note that this function uses the current 3D-version of each 3D-body. Make sure all 3D versions are up to date before calling this function. This function actually marks all 3D-bodies it processes as current. * / int unfold (BM_3D_BODY * base_body, int check_face_normals = 0); / * If the 3D-> 2D deformation matrix of the 3D body has already been calculated, this function calculates the deformation matrix for a given bend line. This function assumes a number of things (these things are not checked):-This bend line is adjacent to the body. -This body already has the latest deformed matrix. -This bend line has the latest center_line_3D. Note that these two functions require the bend line to have a centerline. This also means that the bend line is a non-NULL 3D-version. For performance reasons, these functions do not check that the bend line is a non-NULL 3D-version, but instead assume that the bend line is a non-NULL 3D-version and directly Refer to it. This function is used by UNFOLD. This function is actually bend_bendline_wrt_3D_body (. . . Note the opposite of). * / int unfold_bendline_wrt_3D_body (BM_3D_BODY * body / * finished body * /, BM_BENDLINE * current_bendline / * bendline whose transformation we are computing * /, BM_TRANSFORM * tf / * start with this transformation * /); / * The bendline has already been completed And the same except that we are calculating 3D bodies. This function is used by UNFOLD. This function is actually bend_3D_body_wrt_bendline (. . . Note the opposite of). * / int unfold_3D_body_wrt_bendline (BM_BENDLINE * current_bendline / * end of bendline * /, BM_3D_BODY * body / * the body where we are calculating the deformation * /, BM_TRANSFORM * tf / * start from this deformation * /); / * ********** ********** ********** ********** ********** ********** ********** ********** ********** This function is "paper model of this part" Returns the paper model for this part. A paper model is a part that has a thickness of 0 and a bend line radius and bend deduction of 0. If necessary, this function returns the result of mapping 'inner radius'and' bend deduction 'from bendline user-id'. ********** ********** ********** ********** ********** ********** ********** ********** *********** / BM_PART * make_paper_model (double ** inside_radius / * OUT * /, double ** bend_deduction / * OUT * /); / * This function saves the current part in a PGF format in a given file. The PGF format is used by CMU's BendCAD program. Return Value: Returns TRUE if everything is good and the part has been saved. * / int save_PGF_file (FILE * file); int save_PGF_file (char * filename); / * Load function is PART_LOAD_x. Located in CPP. * / virtual int load (FILE * file); virtual int load (char * filename / * must not be NULL * /); int BM_PART_Load (FILE * file, long version); / * Save function is PART_SAVE. Located in CPP. * / virtual int save (FILE * file); virtual int save (char * filename / * must not be NULL * /);}; #endif // BM_PART_HXX_INCLUDED
Appendix L
Example of navigation by 3D operation and dynamic calculation of rotation axis
void CBendCADViewPart :: OnLButtonUp (UINT nFlags, CPoint point) (:: ReleaseCapture (); :: ClipCursor (NULL); // Release mouse, free cursor.m_lt_btn_up_point = point; double x_extent, y_extent; int add_hit_to_list = 0; int viewport [4]; BM_VECTOR offset; BM_PART * part = GetDocument ()-> get_part (); RwV3dvert; switch (ml_last_function_chosen) {case (ZOOM_WINDOW_MODE): if (mi_dynamic_rot_center_on) (// User has further zoomed in.compute_non_dyn_equivalent (); RwIdent (md_dyn_rot_matrix);} compute_zoom_region_translation (); x_extent = fabs ((double) (m_lt_btn_down_point.x-m_lt_btn_up_point.x)) * 2.0 * md_current_view_vol [0] / (double) (m_old_rect.right); s (ex) (m_lt_btn_down_point.y-m_lt_btn_up_point.y)) * 2.0 * md_current_view_vol [1] / (double) (m_old_rect.bottom); set_new_view_volume (x_extent, y_extent); compute_part_bbox (part, mi_show_3d, md_rot_part_b = 0; // Even though bbox computed, we mark as not up to date so that zoom-allDr awPart (m_hdc); // will work correctly.// Now turn on dynamic rotation center if need be.if ((md_part_bbox_size [0]> 2.2 * md_current_view_vol [0]) || // User has zoomed in so that not all (md_part_bbox_size [1]> 2.2 * md_current_view_vol [1])) {// of the part is in view volume.if (! md_dyn_rot_matrix) md_dyn_rot_matrix = RwCreateMatrix (); if (mi_show_solid) (// Pick the center of the screen to find point on clump to rotate around.if (RwPickScene (m_scene, m_old_rect.right / 2, m_old_rect.bottom / 2, m_camera, & m_pick)) (if (m_pick.type == rwNAPICKOBJECT) {// No clump was picked.m_dynamic_rot_center = BM_POINT (0.0, 0.0, 0.0);} else if (m_pick.type == rwPICKCLUMP) {// Some clump was picked; process it.vert = m_pick.object.clump.wcpoint; m_dynamic_rot_center = BM_POINT (vert.x, vert.y, vert.z);}}} else {m_dynamic_rot_center = BM_POINT (0.0, 0.0, 0.0);} mi_dynamic_rot_center_on = 1;} else {compute_non_dyn_equivalent (); if (md_dyn_rot_matrix) RwDestroyMatrix (md_dyn_rot_yn_; mi_dynam ic_rot_center_on = 0;} break; case (SELECT_OBJECTS_MODE): if (nFlags & MK_CONTROL) add_hit_to_list = 1; if (! mi_show_solid) {// Wireframe being displayed, which means OpenGL picking.glGetIntegerv (GL_VIEWPORT, viewport); glMatrixMode (GL_PROJECTION) ; glPushMatrix (); glLoadIdentity (); gluPickMatrix ((double) point.x, (double) (m_old_rect.bottom-point.y), 3.0, 3.0, viewport); glOrtho (-md_current_view_vol [0], md_current_view_vol [0] ,-md_current_view_vol [1], md_current_view_vol [1],-md_current_view_vol [2], md_current_view_vol [2]); glMatrixMode (GL_MODELVIEW); DrawPart (m_hdc); // Draw the part in selection mode.glMatrixMode (GL_PROJtrix); gl ); glMatrixMode (GL_MODELVIEW); process_hits_record (add_hit_to_list); ml_last_function_chosen = NO_FUNCTION_MODE; DrawPart (m_hdc); reset_selection_buffer ();} else {// Solid being shown, so RenderWare picking.if (RwPickScene (x), y, m_camera, & m_pick)) process_hits_record (add_hit_to_list); ml_last_function_chosen = NO_FUNCTION_MODE; DrawPart (m_hdc) ;} break; case (ZOOM_IN_OUT_MODE): compute_part_bbox (part, mi_show_3d, md_rot_matrix, m_part_centroid, md_part_bbox_size, &offset); mi_bbox_is_up_to_date = 0; if (mi_dynamic_rot_center_yn) _ / trix UserR further_d // Now turn on dynamic rotation center if need be.if ((md_part_bbox_size [0]> 2.2 * md_current_view_vol [0]) || // User has zoomed in so thatnot all (md_part_bbox_size [1]> 2.2 * md_current_view_vol [1] )) (// of the part is in view volume.mi_bbox_is_up_to_date = 0; // Even though bbox computed, we mark as not up to date so that zoom-allif (! md_dyn_rot_matrix) md_dyn_rot_matrix = RwCreateMatrix (); // will work correctly.if (mi_show_solid) (// Pick the center of the screen to find point on clumpto rotate around.if (RwPickScene (m_scene, m_old_rect.right / 2, m_old_rect.bottom / 2, m_camera, & m_pick)) (if (m_pick .type == rwNAPICKOBJECT) {// No clump was picked.m_dynamic_rot_center = BM_POINT (0.0, 0.0, 0.0);} else if (m_pick .type == rwPICKCLUMP) (// Some clump was picked; process it.vert = m_pick.object.clump.wcpoint; m_dynamic_rot_center = BM_POINT (vert.x, vert.y, vert.z);}}} else {m_dynamic_rot_center = BM_POINT (0.0, 0.0, 0.0);} mi_dynamic_rot_center_on = 1;} else {if (mi_dynamic_rot_center_on) (compute_non_dyn_equivalent (); if (md_dyn_rot_matrix) RwDestroyMatrix (md_dyn_rot_matrix); md_dyn_center_dynamic _; __ break;}; ml_last_function_chosen = NO_FUNCTION_MODE; CBendCADView :: OnLButtonUp (nFlags, point);}
[Brief description of the drawings]
FIG. 1 is a block diagram of an advanced sheet metal manufacturing facility constructed according to an embodiment of the present invention.
FIG. 2 is a block diagram of an advanced sheet metal manufacturing facility constructed in accordance with another embodiment of the present invention.
FIG. 3 illustrates respective data flows between a server module, a database, and a station module according to one aspect of the invention.
FIG. 4 is a flowchart of general steps and operations performed by a server module according to another aspect of the invention.
FIG. 5 is a representative flowchart of the basic steps and operations performed by each of the station modules in accordance with the teachings of the present invention.
FIG. 6 is a flowchart illustrating a logical flow of a similar parts search algorithm or process according to one aspect of the present invention.
FIG. 7 is a flowchart illustrating a logical flow of a similar parts search algorithm or process according to one aspect of the present invention.
8 (a), (b), and (c) are feature extraction operations for a 4-bending box with contacted corners and a 4-bending box with open corners according to aspects of the present invention. explain.
9 (a), (b), (c) and (d) are diagrams of a 4-bending box with contacted corners and a 4-bending box with open corners according to aspects of the present invention. The feature extraction operation will be described.
FIGS. 10 (a), (b) and (c) are for identifying a search key for a 4-bending box, a bridge and other parts having a 4-bending box according to another aspect of the present invention. Feature-related operations and processes will be described.
FIG. 11 is a flowchart illustrating a logical flow of steps and operations performed to generate a three-dimensional model from a two-dimensional single drawing using a folding algorithm.
FIG. 12 illustrates an example of an automatic trimming function and a cleanup function performed to create a drawing for the surface detection process.
FIGS. 13A, 13B, and 13C illustrate an example of an automatic trimming function and a cleanup function performed to create a drawing for the surface detection process.
FIG. 14 illustrates an example of an automatic trimming function and a cleanup function performed to create a drawing for the surface detection process.
FIGS. 15 (a), (b), (c), and (d) illustrate various processes and operations performed in a surface detection process according to aspects of the present invention.
FIGS. 16 (a), (b), (c), and (d) illustrate various processes and operations performed in a surface detection process according to aspects of the present invention.
FIG. 17 illustrates generation of final bending graph data from execution of a surface detection step and a bend line detection step according to an aspect of the present invention.
FIG. 18 illustrates generation of final bending graph data from execution of a surface detection step and a bend line detection step according to an aspect of the present invention.
FIG. 19 is a flow chart of a basic logic flow for generating a two-dimensional model based on an initial three-dimensional drawing (without thickness) using a development algorithm and other steps in accordance with the teachings of the present invention. .
FIG. 20 is a flowchart of a basic logic flow for generating a 3D model based on an initial 2D 3 view using a 2D cleanup operation according to an aspect of the present invention.
FIG. 21 is a flowchart of a basic logic flow of steps and operations for performing a two-dimensional cleanup operation on a two-dimensional three-dimensional view according to an aspect of the present invention.
FIGS. 22 (a) and 22 (b) illustrate representative two-dimensional three-dimensional views and sides processed by the two-dimensional cleanup operation of the present invention.
FIG. 23 (a) illustrates the features of the rotated diagram of the two-dimensional cleanup operation of the present invention. FIG. 23 (b) illustrates a standard configuration associated with the two-dimensional cleanup operation of the present invention according to aspects of the present invention.
FIGS. 24 (a) and 24 (b) are simplified with no two-dimensional three views with thickness and no thickness generated using a thickness removal process in accordance with the teachings of the present invention. A two-dimensional three-side view will be described. FIG. 24 (c) is a diagram of a transversal thickness line and thickness arc of a representative part according to aspects of the present invention.
FIG. 25 is a flow chart of the logical flow of various steps and operations performed to develop a 3D model without thickness from a 3D drawing with thickness according to aspects of the present invention.
FIG. 26 illustrates an exemplary data structure and access algorithm for a bending model used in carrying out the present invention through, for example, object oriented programming techniques.
FIG. 27 illustrates a block diagram of the structure of a bending model viewer according to another aspect of the present invention.
FIG. 28 illustrates an exemplary solid diagram window display provided as output to a display screen.
FIG. 29 illustrates an exemplary wireframe diagram window provided as output to a display screen.
FIG. 30 illustrates a 2D planar screen image window display provided as output to a display screen.
FIG. 31 illustrates an orthographic screen image provided as output to a display screen.
FIG. 32 illustrates examples of various dimension items displayed in the automatic dimensioning mode of the present invention.
FIGS. 33 (a), (b) and (c) illustrate how the flange length is defined for a variety of different parts according to one aspect of the present invention.
FIGS. 34 (a) and (b) illustrate the addition of auxiliary flange lengths for two different types of parts according to other aspects of the invention. FIGS.
FIGS. 35 (a), (b) and (c) illustrate how flange lengths are indicated for various parts displayed with thicknesses according to yet another aspect of the present invention. To do.
36 (a) and 36 (b) show a manner in which the flange length of a part having an acute bending angle is displayed according to the tangential dimension method and the cross dimension method of the present invention.
FIG. 37 is a flow chart of the logical flow of steps and operations performed to generate a bending plan through the use of a graphical user interface according to another aspect of the invention.
FIG. 38 illustrates an example of a bend sequence input screen image displayed to a bend operator to generate a bend sequence.
FIGS. 39 (a) and 39 (b) show examples of bending order selection and insertion direction correction according to another aspect of the present invention. FIGS.
FIG. 40 shows a further example of a bending order input screen image and associated screen display.
FIG. 41 shows a further example of a bending order input screen image and associated screen display.
FIG. 42 illustrates drag and drop editing characteristics provided to facilitate an operator to modify and edit a proposed bend sequence according to one aspect of the present invention.
FIG. 43 shows examples of various display menus and data tables that are graphically displayed to assist the bending operator in selecting a tool.
FIG. 44 illustrates an exemplary tool setup window displayed to a bending operator to facilitate tool setup in a proposed bending plan.
FIG. 45 shows an example of a three-dimensional solid diagram window display with attached audio and video information through the use of pasted icons.
FIG. 46 shows another example of a display window incorporated with an icon for reading stored audio and video information according to one aspect of the present invention.
FIG. 47 shows an example of an image editing window executed based on the teaching of the present invention.
FIG. 48 shows an example of the interference check function of the present invention executed through a graphical user interface.
FIG. 49 shows an example of an interference check function of the present invention executed via a graphical user interface.
50 (a) and 50 (b) show the operating system of the present invention for manipulating the rotation and display of a three-dimensional geometric shape using, for example, a joystick.
FIG. 51 illustrates the operating system of the present invention for manipulating zooming and display of 3D geometric shapes using, for example, a joystick and zoom buttons.
FIG. 52 shows the operating system of the present invention for manipulating panning and display of a three-dimensional geometric shape using, for example, a joystick and a pan button.
FIG. 53 is a representative flowchart of steps and operations performed to implement the three-dimensional navigation and operation system of the present invention.
FIG. 54 illustrates an example of mapping joystick motion to cursor motion according to aspects of the present invention.
FIG. 55 is a representative flowchart of the steps and operations performed to dynamically calculate the rotation axis of the displayed part.
FIG. 56 shows an example of a main menu window display provided and displayed in the station module, for example.
FIG. 57 shows a representative part information window display provided to allow a user to enter and modify part information.
FIG. 58 shows an exemplary bend line information window display provided to allow a user to enter and modify bend information.
FIG. 59 shows an exemplary bending order window display of the present invention for observing intermediate bending stages of sheet metal parts.
FIG. 60 shows an exemplary bending simulation window display of the present invention for simulating an intermediate bending stage of a sheet metal part.
FIG. 61 is an exemplary menu screen diagram and structure of the present invention provided and displayed to a user for 2D to 3D conversion.
FIG. 62 is an exemplary menu screen diagram and structure for a two-dimensional cleanup operation of the present invention.
FIG. 63 shows an example of a three-dimensional display of a part before a line segment whose one end is opened is removed.
FIG. 64 is a diagram illustrating a method for removing a line segment that has been released from one of the three-dimensional displays according to the three-dimensional cleanup process of the present invention used when generating a three-dimensional model of a part from a two-dimensional three-dimensional view of the part; Shows the parts after.
FIG. 65 shows a representative three-dimensional representation of the part before the bend line is identified.
FIG. 66 shows the part after the mold line is added by the three-dimensional cleanup process of the present invention.
FIG. 67 shows a representative portion of the part before clearing the bend line and trimming the face.
FIG. 68 shows a part portion after the normalization and trimming are performed by the three-dimensional cleanup process of the present invention;

Claims (9)

コンピュータ制御システムにおいて使用されるように作られたオブジェクト指向曲げモデルビューアにして、前記コンピュータ制御システムは、前記部品に関連する曲げモデルデータを格納するためのデータベースと、前記部品の画像を表示するための表示装置とを備え、
前記オブジェクト指向曲げモデルビューアは、曲げモデルビューア観察クラスを備え;
曲げモデルビューア観察クラスは、観察モデル属性と、前記曲げモデルビューア観察クラスのメンバー機能として実行される少なくとも一つの観察機能を有し;
前記部品の少なくとも一つの画像は、前記曲げモデルデータおよび前記観察モデル属性に基づいて前記コンピュータ制御システムの前記表示装置に表示される。
In an object-oriented bending model viewer designed for use in a computer control system, the computer control system displays a database for storing bending model data associated with the part and an image of the part. A display device,
The object-oriented bending model viewer comprises a bending model viewer observation class;
The bending model viewer observation class has an observation model attribute and at least one observation function executed as a member function of the bending model viewer observation class;
At least one image of the part is displayed on the display device of the computer control system based on the bending model data and the observation model attributes.
請求項1のオブジェクト指向曲げモデルビューアにして、
前記観察モデル属性は、所定の観察モードに関連する表示情報を備え、前記所定の観察モードは、実線観察モード・ワイヤフレーム観察モード・2次元平面観察モード・正斜影観察モードの少なくとも一つを含む。
The object-oriented bending model viewer of claim 1
The observation model attribute includes display information related to a predetermined observation mode, and the predetermined observation mode includes at least one of a solid line observation mode, a wire frame observation mode, a two-dimensional plane observation mode, and an orthoclinic observation mode. .
請求項のオブジェクト指向曲げモデルビューアにして、前記曲げモデルビューア観察クラスは、前記少なくとも一つの観察機能に応じて前記部品の前記画像を変形する情報を更に備える。The object-oriented bending model viewer according to claim 1 , wherein the bending model viewer observation class further includes information for deforming the image of the part according to the at least one observation function. 請求項オブジェクト指向曲げモデルビューアにして、前記少なくとも一つの観察機能は、ズーム機能、回転機能、パンニング機能、又は寸法機能の内の少なくとも一つを有する。According to a third aspect of the present invention, the at least one observation function includes at least one of a zoom function, a rotation function, a panning function, and a dimension function. 請求項によるオブジェクト指向曲げモデルビューアにして前記寸法機能は前記部品の画像を変形し前記部品の少なくとも1つの特徴に関連する寸法情報を追加的に表示する動作を含み、前記寸法情報は、前記部品の少なくとも1つの曲げ線の長さと前記各曲げ線の曲げ角度とを含む。5. The object-oriented bending model viewer according to claim 4, wherein the dimension function includes an operation of deforming an image of the part and additionally displaying dimension information related to at least one feature of the part, Including a length of at least one bend line of the part and a bend angle of each bend line. 請求項のオブジェクト指向曲げモデルビューアにして、前記曲げモデルビューア観察クラスは、前記曲げモデルビューア観察クラスのメンバー機能として提供される複数の観察機能を備え、前記曲げモデルビューア観察クラスは更に、前記観察機能の各々に応じて前記部品の前記画像を変形するための情報を備える。The object-oriented bending model viewer according to claim 1 , wherein the bending model viewer observation class includes a plurality of observation functions provided as member functions of the bending model viewer observation class, and the bending model viewer observation class further includes the bending model viewer observation class. Information for transforming the image of the component according to each of the observation functions is provided. 請求項のオブジェクト指向曲げモデルビューアにして、更に前記部品の前記画像の現在表示されている画面に基づいて、前記表示装置上で観察可能な前記部品の特徴に関連する観察可能情報を提供し維持するための観察可能機能を有するもの。The object-oriented bending model viewer according to claim 1 , further comprising observable information related to characteristics of the part that can be observed on the display device based on a currently displayed screen of the image of the part. It has an observable function to maintain. 請求項によるオブジェクト指向曲げモデルビューアにして、前記曲げモデルビューア画像クラスは、前記少なくとも1つの撮影機能に応じて前記部品の画像を変更するための情報を含み、前記少なくとも1つの撮影機能は、寸法機能を含み、この寸法機能は前記可視性情報に基づき前記部品の画像を変形し前記部品の観察可能の特徴に関連する寸法情報を表示する操作を含む。The object-oriented bending model viewer according to claim 7 , wherein the bending model viewer image class includes information for changing an image of the part according to the at least one shooting function, and the at least one shooting function includes: A dimension function is included, and the dimension function includes an operation of deforming an image of the part based on the visibility information and displaying dimension information related to an observable characteristic of the part. コンピュータ制御システムにおいて使用されるように作られたオブジェクト指向曲げモデルビューアを格納したコンピュータ読取可能媒体にして、
前記コンピュータ制御システムは、前記部品に関連する曲げモデルデータを格納するためのデータベースと、前記部品の画像を表示するための表示装置とを備え、
前記オブジェクト指向曲げモデルビューアは、曲げモデルビューア観察クラスを備え;
曲げモデルビューア観察クラスは、観察モデル属性と、前記曲げモデルビューア観察クラスのメンバー機能として実行される少なくとも一つの観察機能を有し;
前記部品の少なくとも一つの画像は、前記曲げモデルデータおよび前記観察モデル属性に基づいて前記コンピュータ制御システムの前記表示装置に表示されるもの。
A computer readable medium containing an object oriented bending model viewer made for use in a computer control system,
The computer control system includes a database for storing bending model data related to the part, and a display device for displaying an image of the part.
The object-oriented bending model viewer comprises a bending model viewer observation class;
The bending model viewer observation class has an observation model attribute and at least one observation function executed as a member function of the bending model viewer observation class;
At least one image of the part is displayed on the display device of the computer control system based on the bending model data and the observation model attribute.
JP27347499A 1996-05-06 1999-09-27 Apparatus and method for distributing design and fabrication information throughout a sheet metal fabrication facility Expired - Fee Related JP3884195B2 (en)

Applications Claiming Priority (2)

Application Number Priority Date Filing Date Title
US1695896P 1996-05-06 1996-05-06
US60/016958 1996-05-06

Related Parent Applications (1)

Application Number Title Priority Date Filing Date
JP18338897A Division JP3265233B2 (en) 1996-05-06 1997-05-02 Computer-readable medium storing object-oriented bending model for representing parts

Publications (3)

Publication Number Publication Date
JP2000090144A JP2000090144A (en) 2000-03-31
JP2000090144A5 JP2000090144A5 (en) 2005-12-02
JP3884195B2 true JP3884195B2 (en) 2007-02-21

Family

ID=21779940

Family Applications (10)

Application Number Title Priority Date Filing Date
JP18339097A Expired - Fee Related JP2966376B2 (en) 1996-05-06 1997-05-02 Apparatus and method for distributing design and manufacturing information across sheet metal manufacturing equipment
JP18338797A Expired - Fee Related JP3009134B2 (en) 1996-05-06 1997-05-02 Apparatus and method for distributing design and manufacturing information across sheet metal manufacturing equipment
JP18338997A Expired - Fee Related JP3009135B2 (en) 1996-05-06 1997-05-02 Apparatus and method for distributing design and manufacturing information across sheet metal manufacturing equipment
JP18338897A Expired - Fee Related JP3265233B2 (en) 1996-05-06 1997-05-02 Computer-readable medium storing object-oriented bending model for representing parts
JP14216799A Expired - Fee Related JP3803509B2 (en) 1996-05-06 1999-04-05 Apparatus and method for distributing design and fabrication information throughout a sheet metal fabrication facility
JP11142166A Pending JP2000003384A (en) 1996-05-06 1999-04-05 Device and method for distributing design/manufacture information over whole sheet metal manufacturing equipment
JP10135799A Expired - Fee Related JP3803502B2 (en) 1996-05-06 1999-04-08 Apparatus and method for distributing design and fabrication information throughout a sheet metal fabrication facility
JP11102564A Pending JPH11345260A (en) 1996-05-06 1999-04-09 Device and method for distributing design and manufacturing information over whole thin sheet metal manufacturing facility
JP27347499A Expired - Fee Related JP3884195B2 (en) 1996-05-06 1999-09-27 Apparatus and method for distributing design and fabrication information throughout a sheet metal fabrication facility
JP11273475A Withdrawn JP2000090145A (en) 1996-05-06 1999-09-27 Distribution method and device for design and production information on entire production facility for sheet metal

Family Applications Before (8)

Application Number Title Priority Date Filing Date
JP18339097A Expired - Fee Related JP2966376B2 (en) 1996-05-06 1997-05-02 Apparatus and method for distributing design and manufacturing information across sheet metal manufacturing equipment
JP18338797A Expired - Fee Related JP3009134B2 (en) 1996-05-06 1997-05-02 Apparatus and method for distributing design and manufacturing information across sheet metal manufacturing equipment
JP18338997A Expired - Fee Related JP3009135B2 (en) 1996-05-06 1997-05-02 Apparatus and method for distributing design and manufacturing information across sheet metal manufacturing equipment
JP18338897A Expired - Fee Related JP3265233B2 (en) 1996-05-06 1997-05-02 Computer-readable medium storing object-oriented bending model for representing parts
JP14216799A Expired - Fee Related JP3803509B2 (en) 1996-05-06 1999-04-05 Apparatus and method for distributing design and fabrication information throughout a sheet metal fabrication facility
JP11142166A Pending JP2000003384A (en) 1996-05-06 1999-04-05 Device and method for distributing design/manufacture information over whole sheet metal manufacturing equipment
JP10135799A Expired - Fee Related JP3803502B2 (en) 1996-05-06 1999-04-08 Apparatus and method for distributing design and fabrication information throughout a sheet metal fabrication facility
JP11102564A Pending JPH11345260A (en) 1996-05-06 1999-04-09 Device and method for distributing design and manufacturing information over whole thin sheet metal manufacturing facility

Family Applications After (1)

Application Number Title Priority Date Filing Date
JP11273475A Withdrawn JP2000090145A (en) 1996-05-06 1999-09-27 Distribution method and device for design and production information on entire production facility for sheet metal

Country Status (1)

Country Link
JP (10) JP2966376B2 (en)

Families Citing this family (14)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JP4426717B2 (en) 2000-12-06 2010-03-03 ヤマハ発動機株式会社 Suspension for motorcycle
JP4727835B2 (en) * 2001-04-03 2011-07-20 株式会社アマダ Non-processable information teaching method and system
DE10131045A1 (en) * 2001-06-29 2003-01-09 Achim Fricker configurator
JP4755779B2 (en) * 2001-07-31 2011-08-24 株式会社アマダ 3D inspection and utilization method for sheet metal products and its system
JP2005092274A (en) * 2003-09-12 2005-04-07 Amada Co Ltd Sheet metal product manufacturing method and system therefor, and recording medium stored with sheet metal model
JP2006092484A (en) * 2004-09-27 2006-04-06 Matsushita Electric Works Ltd Design support system
JP2008030110A (en) * 2006-07-31 2008-02-14 Icgb Co Ltd Operation assisting device for press brake
JP5178483B2 (en) * 2008-12-05 2013-04-10 富士通株式会社 Program, information processing apparatus and display method
JP6097657B2 (en) * 2013-08-29 2017-03-15 株式会社アマダホールディングス Step bending recognition system and method
JP6237498B2 (en) * 2014-06-30 2017-11-29 カシオ計算機株式会社 Graphic display control device, display control method, and program
US10817526B2 (en) * 2014-07-16 2020-10-27 Machine Research Corporation Systems and methods for searching a machining knowledge database
JP2017080198A (en) * 2015-10-29 2017-05-18 キヤノンマーケティングジャパン株式会社 Information processing device, information processing method, and program
EP3502930A1 (en) * 2017-12-22 2019-06-26 Dassault Systèmes Method for computing an unfolded part of a modeled bended part of a 3d object
CN109992684A (en) * 2019-04-12 2019-07-09 中民筑友智能装备科技有限公司 Prefabricated components production line automatic projection method, apparatus, equipment, system and medium

Also Published As

Publication number Publication date
JPH10187793A (en) 1998-07-21
JP3009134B2 (en) 2000-02-14
JP2966376B2 (en) 1999-10-25
JP2000003384A (en) 2000-01-07
JPH10187795A (en) 1998-07-21
JPH11345260A (en) 1999-12-14
JP3803509B2 (en) 2006-08-02
JP3265233B2 (en) 2002-03-11
JPH11338909A (en) 1999-12-10
JP3803502B2 (en) 2006-08-02
JP2000090144A (en) 2000-03-31
JP2000003385A (en) 2000-01-07
JP3009135B2 (en) 2000-02-14
JPH10187794A (en) 1998-07-21
JPH10187796A (en) 1998-07-21
JP2000090145A (en) 2000-03-31

Similar Documents

Publication Publication Date Title
US6411862B1 (en) Apparatus and method for managing and distributing design and manufacturing information throughout a sheet metal production facility
US7197372B2 (en) Apparatus and method for managing and distributing design and manufacturing information throughout a sheet metal production facility
US5864482A (en) Apparatus and method for managing distributing design and manufacturing information throughout a sheet metal production facility
US5828575A (en) Apparatus and method for managing and distributing design and manufacturing information throughout a sheet metal production facility
WO1997042608A9 (en) Apparatus and method for generating a sheet-metal bend model
JP3884195B2 (en) Apparatus and method for distributing design and fabrication information throughout a sheet metal fabrication facility
US20140288892A1 (en) Modeless drawing windows for cad system
JP3308869B2 (en) Parts display image operation system and method
Kalay Worldview: An integrated geometric-modeling/drafting system
EP1830323A2 (en) Apparatus and method for managing and distributing design and manufacturing information throughout a sheet metal production facility

Legal Events

Date Code Title Description
A625 Written request for application examination (by other person)

Free format text: JAPANESE INTERMEDIATE CODE: A625

Effective date: 20040430

A521 Written amendment

Free format text: JAPANESE INTERMEDIATE CODE: A523

Effective date: 20051013

A711 Notification of change in applicant

Free format text: JAPANESE INTERMEDIATE CODE: A712

Effective date: 20051013

TRDD Decision of grant or rejection written
A01 Written decision to grant a patent or to grant a registration (utility model)

Free format text: JAPANESE INTERMEDIATE CODE: A01

Effective date: 20061114

A61 First payment of annual fees (during grant procedure)

Free format text: JAPANESE INTERMEDIATE CODE: A61

Effective date: 20061116

R150 Certificate of patent or registration of utility model

Free format text: JAPANESE INTERMEDIATE CODE: R150

FPAY Renewal fee payment (event date is renewal date of database)

Free format text: PAYMENT UNTIL: 20101124

Year of fee payment: 4

FPAY Renewal fee payment (event date is renewal date of database)

Free format text: PAYMENT UNTIL: 20101124

Year of fee payment: 4

FPAY Renewal fee payment (event date is renewal date of database)

Free format text: PAYMENT UNTIL: 20111124

Year of fee payment: 5

FPAY Renewal fee payment (event date is renewal date of database)

Free format text: PAYMENT UNTIL: 20111124

Year of fee payment: 5

FPAY Renewal fee payment (event date is renewal date of database)

Free format text: PAYMENT UNTIL: 20121124

Year of fee payment: 6

FPAY Renewal fee payment (event date is renewal date of database)

Free format text: PAYMENT UNTIL: 20121124

Year of fee payment: 6

FPAY Renewal fee payment (event date is renewal date of database)

Free format text: PAYMENT UNTIL: 20131124

Year of fee payment: 7

LAPS Cancellation because of no payment of annual fees