]> OCCT Git - occt-copy.git/commitdiff
CR670homag - Open CASCADE 6.7.0 with patches for HOMAG CR670homag
authorvro <vro@opencascade.com>
Fri, 22 May 2015 07:16:30 +0000 (10:16 +0300)
committervro <vro@opencascade.com>
Fri, 22 May 2015 07:16:30 +0000 (10:16 +0300)
133 files changed:
dox/LICENSE.md [deleted file]
src/AIS/AIS_AngleDimension.cxx
src/AIS/AIS_AngleDimension.hxx
src/AIS/AIS_DiameterDimension.cxx
src/AIS/AIS_DiameterDimension.hxx
src/AIS/AIS_Dimension.cxx
src/AIS/AIS_Dimension.hxx
src/AIS/AIS_InteractiveContext.cdl
src/AIS/AIS_InteractiveContext.cxx
src/AIS/AIS_InteractiveContext_1.cxx
src/AIS/AIS_LengthDimension.cxx
src/AIS/AIS_LengthDimension.hxx
src/AIS/AIS_LocalContext.cdl
src/AIS/AIS_LocalContext.cxx
src/AIS/AIS_LocalContext_1.cxx
src/AIS/AIS_RadiusDimension.cxx
src/AIS/AIS_RadiusDimension.hxx
src/AIS/AIS_Shape.cxx
src/BRep/BRep_Builder.cxx
src/BRepBuilderAPI/BRepBuilderAPI_VertexInspector.hxx
src/BRepFill/BRepFill_OffsetWire.cdl
src/BRepFill/BRepFill_OffsetWire.cxx
src/BRepFill/BRepFill_PipeShell.cxx
src/BRepFill/BRepFill_SectionLaw.cxx
src/BRepFill/BRepFill_Sweep.cxx
src/BRepMAT2d/BRepMAT2d.cdl
src/BRepMAT2d/BRepMAT2d_BisectingLocus.cdl [new file with mode: 0644]
src/BRepMAT2d/BRepMAT2d_BisectingLocus.cxx [new file with mode: 0644]
src/BRepOffsetAPI/BRepOffsetAPI_MakeOffset.cdl
src/BRepOffsetAPI/BRepOffsetAPI_MakeOffset.cxx
src/BRepOffsetAPI/BRepOffsetAPI_ThruSections.cxx
src/BRepToIGES/BRepToIGES_BRShell.cxx
src/BRepToIGES/BRepToIGES_BRWire.cxx
src/BRepTools/BRepTools_NurbsConvertModification.cxx
src/DsgPrs/DsgPrs_DiameterPresentation.cxx
src/GeomConvert/GeomConvert_1.cxx
src/GeomFill/GeomFill_Sweep.cxx
src/GeomToIGES/GeomToIGES_GeomSurface.cxx
src/MAT2d/MAT2d.cdl
src/MAT2d/MAT2d_Circuit.cdl
src/MAT2d/MAT2d_Circuit.cxx
src/MAT2d/MAT2d_Mat2d.cdl [new file with mode: 0644]
src/MAT2d/MAT2d_Mat2d.cxx [new file with mode: 0644]
src/MAT2d/MAT2d_Tool2d.cdl
src/MAT2d/MAT2d_Tool2d.cxx
src/NCollection/NCollection_UBTree.hxx
src/NCollection/NCollection_WinHeapAllocator.cxx [new file with mode: 0644]
src/NCollection/NCollection_WinHeapAllocator.hxx [new file with mode: 0644]
src/NIS/FILES
src/NIS/NIS_Allocator.hxx
src/NIS/NIS_DrawList.cxx
src/NIS/NIS_DrawList.hxx
src/NIS/NIS_Drawer.cxx
src/NIS/NIS_Drawer.hxx
src/NIS/NIS_IndexLists.cxx [new file with mode: 0644]
src/NIS/NIS_IndexLists.hxx [new file with mode: 0644]
src/NIS/NIS_InteractiveContext.cxx
src/NIS/NIS_InteractiveContext.hxx
src/NIS/NIS_InteractiveObject.cxx
src/NIS/NIS_InteractiveObject.hxx
src/NIS/NIS_Line.cxx [new file with mode: 0644]
src/NIS/NIS_Line.hxx [new file with mode: 0644]
src/NIS/NIS_LineDrawer.cxx [new file with mode: 0644]
src/NIS/NIS_LineDrawer.hxx [new file with mode: 0644]
src/NIS/NIS_ObjectsIterator.hxx
src/NIS/NIS_Point.cxx [new file with mode: 0644]
src/NIS/NIS_Point.hxx [new file with mode: 0644]
src/NIS/NIS_PointDrawer.cxx [new file with mode: 0644]
src/NIS/NIS_PointDrawer.hxx [new file with mode: 0644]
src/NIS/NIS_PolygonSelector.cxx [new file with mode: 0644]
src/NIS/NIS_PolygonSelector.hxx [new file with mode: 0644]
src/NIS/NIS_SelectFilter.cxx
src/NIS/NIS_SelectFilter.hxx
src/NIS/NIS_Surface.cxx
src/NIS/NIS_Surface.hxx
src/NIS/NIS_SurfaceDrawer.cxx
src/NIS/NIS_SurfaceDrawer.hxx
src/NIS/NIS_Text.cxx [new file with mode: 0644]
src/NIS/NIS_Text.hxx [new file with mode: 0644]
src/NIS/NIS_TextDrawer.cxx [new file with mode: 0644]
src/NIS/NIS_TextDrawer.hxx [new file with mode: 0644]
src/NIS/NIS_Tools.cxx [new file with mode: 0644]
src/NIS/NIS_Tools.hxx [new file with mode: 0644]
src/NIS/NIS_Triangulated.cxx
src/NIS/NIS_Triangulated.hxx
src/NIS/NIS_TriangulatedDrawer.cxx
src/NIS/NIS_TriangulatedDrawer.hxx
src/NIS/NIS_View.cxx
src/NIS/NIS_View.hxx
src/NIS/NIS_ViewData.hxx [new file with mode: 0644]
src/OSD/OSD_MPData.cxx [new file with mode: 0644]
src/OSD/OSD_MPData.hxx [new file with mode: 0644]
src/OSD/OSD_MProcess.cxx [new file with mode: 0644]
src/OSD/OSD_MProcess.hxx [new file with mode: 0644]
src/OSD/OSD_PerfMeter.cxx
src/OSD/OSD_PerfMeter.h
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_Workspace_3.cxx
src/Poly/Poly_IBuffer.cxx [new file with mode: 0644]
src/Poly/Poly_IBuffer.hxx [new file with mode: 0644]
src/Poly/Poly_IBuffer.lxx [new file with mode: 0644]
src/Prs3d/Prs3d_DimensionAspect.cdl
src/Prs3d/Prs3d_DimensionAspect.cxx
src/PrsMgr/PrsMgr_Presentation3d.cdl
src/PrsMgr/PrsMgr_Presentation3d.cxx
src/PrsMgr/PrsMgr_PresentationManager3d.cxx
src/RWStl/RWStl.cxx
src/Select3D/Select3D_SensitiveCurve.cdl
src/Select3D/Select3D_SensitiveCurve.cxx
src/Select3D/Select3D_SensitiveTriangulation.cxx
src/Select3D/Select3D_SensitiveTriangulation.lxx
src/ShapeAnalysis/ShapeAnalysis_CheckSmallFace.cxx
src/ShapeAnalysis/ShapeAnalysis_Edge.cxx
src/ShapeAnalysis/ShapeAnalysis_Wire.cxx
src/ShapeFix/ShapeFix_Wire.cxx
src/Standard/Standard_CString.cxx
src/Standard/Standard_CString.hxx
src/Standard/Standard_GUID.cxx
src/StdSelect/StdSelect.cxx
src/StdSelect/StdSelect_BRepOwner.cdl
src/StdSelect/StdSelect_BRepOwner.cxx
src/StdSelect/StdSelect_Shape.cdl
src/StdSelect/StdSelect_Shape.cxx
src/StlMesh/StlMesh_MeshDomain.cxx
src/TDF/TDF_Tool.cxx
src/TDataStd/TDataStd_ChildNodeIterator.lxx
src/TDataStd/TDataStd_TreeNode.cxx
src/TNaming/TNaming_Name.cxx
src/TNaming/TNaming_NamedShape.cxx
src/V3d/V3d_Viewer_2.cxx
src/Visual3d/Visual3d_View.cxx
src/VrmlData/VrmlData_IndexedFaceSet.cxx
src/VrmlData/VrmlData_ShapeConvert.cxx

diff --git a/dox/LICENSE.md b/dox/LICENSE.md
deleted file mode 100755 (executable)
index bc82745..0000000
+++ /dev/null
@@ -1,521 +0,0 @@
-License {#occt_public_license}
-=======
-
-Open CASCADE Technology is available under GNU Lesser General Public License 
-(LGPL) version 2.1 with additional exception.
-
-@section license_lgpl_21 GNU LESSER GENERAL PUBLIC LICENSE
-
-    Version 2.1, February 1999
-
-    Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-    51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-    Everyone is permitted to copy and distribute verbatim copies
-    of this license document, but changing it is not allowed.
-
-    [This is the first released version of the Lesser GPL.  It also counts
-    as the successor of the GNU Library Public License, version 2, hence
-    the version number 2.1.]
-
-### Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it.  You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
-  When we speak of free software, we are referring to freedom of use,
-not price.  Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
-  To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights.  These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  To protect each distributor, we want to make it very clear that
-there is no warranty for the free library.  Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
-  Finally, software patents pose a constant threat to the existence of
-any free program.  We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder.  Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
-  Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License.  This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License.  We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
-  When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library.  The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom.  The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
-  We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License.  It also provides other free software developers Less
-of an advantage over competing non-free programs.  These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries.  However, the Lesser license provides advantages in certain
-special circumstances.
-
-  For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard.  To achieve this, non-free programs must be
-allowed to use the library.  A more frequent case is that a free
-library does the same job as widely used non-free libraries.  In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
-  In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software.  For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
-  Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
-### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
--  0. This License Agreement applies to any software library or other
-   program which contains a notice placed by the copyright holder or
-   other authorized party saying it may be distributed under the terms of
-   this Lesser General Public License (also called "this License").
-   Each licensee is addressed as "you".
-
-   A "library" means a collection of software functions and/or data
-   prepared so as to be conveniently linked with application programs
-   (which use some of those functions and data) to form executables.
-
-   The "Library", below, refers to any such software library or work
-   which has been distributed under these terms.  A "work based on the
-   Library" means either the Library or any derivative work under
-   copyright law: that is to say, a work containing the Library or a
-   portion of it, either verbatim or with modifications and/or translated
-   straightforwardly into another language.  (Hereinafter, translation is
-   included without limitation in the term "modification".)
-
-   "Source code" for a work means the preferred form of the work for
-   making modifications to it.  For a library, complete source code means
-   all the source code for all modules it contains, plus any associated
-   interface definition files, plus the scripts used to control compilation
-   and installation of the library.
-
-   Activities other than copying, distribution and modification are not
-   covered by this License; they are outside its scope.  The act of
-   running a program using the Library is not restricted, and output from
-   such a program is covered only if its contents constitute a work based
-   on the Library (independent of the use of the Library in a tool for
-   writing it).  Whether that is true depends on what the Library does
-   and what the program that uses the Library does.
-  
-1. You may copy and distribute verbatim copies of the Library's
-   complete source code as you receive it, in any medium, provided that
-   you conspicuously and appropriately publish on each copy an
-   appropriate copyright notice and disclaimer of warranty; keep intact
-   all the notices that refer to this License and to the absence of any
-   warranty; and distribute a copy of this License along with the
-   Library.
-
-   You may charge a fee for the physical act of transferring a copy,
-   and you may at your option offer warranty protection in exchange for a
-   fee.
-
-2. You may modify your copy or copies of the Library or any portion
-   of it, thus forming a work based on the Library, and copy and
-   distribute such modifications or work under the terms of Section 1
-   above, provided that you also meet all of these conditions:
-
-   1. The modified work must itself be a software library.
-
-   2. You must cause the files modified to carry prominent notices
-      stating that you changed the files and the date of any change.
-
-   3. You must cause the whole of the work to be licensed at no
-      charge to all third parties under the terms of this License.
-
-   4. If a facility in the modified Library refers to a function or a
-      table of data to be supplied by an application program that uses
-      the facility, other than as an argument passed when the facility
-      is invoked, then you must make a good faith effort to ensure that,
-      in the event an application does not supply such function or
-      table, the facility still operates, and performs whatever part of
-      its purpose remains meaningful.
-
-      (For example, a function in a library to compute square roots has
-      a purpose that is entirely well-defined independent of the
-      application.  Therefore, Subsection 2d requires that any
-      application-supplied function or table used by this function must
-      be optional: if the application does not supply it, the square
-      root function must still compute square roots.)
-
-   These requirements apply to the modified work as a whole.  If
-   identifiable sections of that work are not derived from the Library,
-   and can be reasonably considered independent and separate works in
-   themselves, then this License, and its terms, do not apply to those
-   sections when you distribute them as separate works.  But when you
-   distribute the same sections as part of a whole which is a work based
-   on the Library, the distribution of the whole must be on the terms of
-   this License, whose permissions for other licensees extend to the
-   entire whole, and thus to each and every part regardless of who wrote
-   it.
-
-   Thus, it is not the intent of this section to claim rights or contest
-   your rights to work written entirely by you; rather, the intent is to
-   exercise the right to control the distribution of derivative or
-   collective works based on the Library.
-
-   In addition, mere aggregation of another work not based on the Library
-   with the Library (or with a work based on the Library) on a volume of
-   a storage or distribution medium does not bring the other work under
-   the scope of this License.
-
-3. You may opt to apply the terms of the ordinary GNU General Public
-   License instead of this License to a given copy of the Library.  To do
-   this, you must alter all the notices that refer to this License, so
-   that they refer to the ordinary GNU General Public License, version 2,
-   instead of to this License.  (If a newer version than version 2 of the
-   ordinary GNU General Public License has appeared, then you can specify
-   that version instead if you wish.)  Do not make any other change in
-   these notices.
-
-   Once this change is made in a given copy, it is irreversible for
-   that copy, so the ordinary GNU General Public License applies to all
-   subsequent copies and derivative works made from that copy.
-
-   This option is useful when you wish to copy part of the code of
-   the Library into a program that is not a library.
-
-4. You may copy and distribute the Library (or a portion or
-   derivative of it, under Section 2) in object code or executable form
-   under the terms of Sections 1 and 2 above provided that you accompany
-   it with the complete corresponding machine-readable source code, which
-   must be distributed under the terms of Sections 1 and 2 above on a
-   medium customarily used for software interchange.
-
-   If distribution of object code is made by offering access to copy
-   from a designated place, then offering equivalent access to copy the
-   source code from the same place satisfies the requirement to
-   distribute the source code, even though third parties are not
-   compelled to copy the source along with the object code.
-
-5. A program that contains no derivative of any portion of the
-   Library, but is designed to work with the Library by being compiled or
-   linked with it, is called a "work that uses the Library".  Such a
-   work, in isolation, is not a derivative work of the Library, and
-   therefore falls outside the scope of this License.
-
-   However, linking a "work that uses the Library" with the Library
-   creates an executable that is a derivative of the Library (because it
-   contains portions of the Library), rather than a "work that uses the
-   library".  The executable is therefore covered by this License.
-   Section 6 states terms for distribution of such executables.
-
-   When a "work that uses the Library" uses material from a header file
-   that is part of the Library, the object code for the work may be a
-   derivative work of the Library even though the source code is not.
-   Whether this is true is especially significant if the work can be
-   linked without the Library, or if the work is itself a library.  The
-   threshold for this to be true is not precisely defined by law.
-
-   If such an object file uses only numerical parameters, data
-   structure layouts and accessors, and small macros and small inline
-   functions (ten lines or less in length), then the use of the object
-   file is unrestricted, regardless of whether it is legally a derivative
-   work.  (Executables containing this object code plus portions of the
-   Library will still fall under Section 6.)
-
-   Otherwise, if the work is a derivative of the Library, you may
-   distribute the object code for the work under the terms of Section 6.
-   Any executables containing that work also fall under Section 6,
-   whether or not they are linked directly with the Library itself.
-
-6. As an exception to the Sections above, you may also combine or
-   link a "work that uses the Library" with the Library to produce a
-   work containing portions of the Library, and distribute that work
-   under terms of your choice, provided that the terms permit
-   modification of the work for the customer's own use and reverse
-   engineering for debugging such modifications.
-
-   You must give prominent notice with each copy of the work that the
-   Library is used in it and that the Library and its use are covered by
-   this License.  You must supply a copy of this License.  If the work
-   during execution displays copyright notices, you must include the
-   copyright notice for the Library among them, as well as a reference
-   directing the user to the copy of this License.  Also, you must do one
-   of these things:
-
-   1. Accompany the work with the complete corresponding
-      machine-readable source code for the Library including whatever
-      changes were used in the work (which must be distributed under
-      Sections 1 and 2 above); and, if the work is an executable linked
-      with the Library, with the complete machine-readable "work that
-      uses the Library", as object code and/or source code, so that the
-      user can modify the Library and then relink to produce a modified
-      executable containing the modified Library.  (It is understood
-      that the user who changes the contents of definitions files in the
-      Library will not necessarily be able to recompile the application
-      to use the modified definitions.)
-
-   2. Use a suitable shared library mechanism for linking with the
-      Library.  A suitable mechanism is one that (1) uses at run time a
-      copy of the library already present on the user's computer system,
-      rather than copying library functions into the executable, and (2)
-      will operate properly with a modified version of the library, if
-      the user installs one, as long as the modified version is
-      interface-compatible with the version that the work was made with.
-
-   3. Accompany the work with a written offer, valid for at
-      least three years, to give the same user the materials
-      specified in Subsection 6a, above, for a charge no more
-      than the cost of performing this distribution.
-
-   4. If distribution of the work is made by offering access to copy
-      from a designated place, offer equivalent access to copy the above
-      specified materials from the same place.
-
-   5. Verify that the user has already received a copy of these
-      materials or that you have already sent this user a copy.
-
-   For an executable, the required form of the "work that uses the
-   Library" must include any data and utility programs needed for
-   reproducing the executable from it.  However, as a special exception,
-   the materials to be distributed need not include anything that is
-   normally distributed (in either source or binary form) with the major
-   components (compiler, kernel, and so on) of the operating system on
-   which the executable runs, unless that component itself accompanies
-   the executable.
-
-   It may happen that this requirement contradicts the license
-   restrictions of other proprietary libraries that do not normally
-   accompany the operating system.  Such a contradiction means you cannot
-   use both them and the Library together in an executable that you
-   distribute.
-
-7. You may place library facilities that are a work based on the
-   Library side-by-side in a single library together with other library
-   facilities not covered by this License, and distribute such a combined
-   library, provided that the separate distribution of the work based on
-   the Library and of the other library facilities is otherwise
-   permitted, and provided that you do these two things:
-
-   1. Accompany the combined library with a copy of the same work
-      based on the Library, uncombined with any other library
-      facilities.  This must be distributed under the terms of the
-      Sections above.
-
-   2. Give prominent notice with the combined library of the fact
-      that part of it is a work based on the Library, and explaining
-      where to find the accompanying uncombined form of the same work.
-
-8. You may not copy, modify, sublicense, link with, or distribute
-   the Library except as expressly provided under this License.  Any
-   attempt otherwise to copy, modify, sublicense, link with, or
-   distribute the Library is void, and will automatically terminate your
-   rights under this License.  However, parties who have received copies,
-   or rights, from you under this License will not have their licenses
-   terminated so long as such parties remain in full compliance.
-
-9. You are not required to accept this License, since you have not
-   signed it.  However, nothing else grants you permission to modify or
-   distribute the Library or its derivative works.  These actions are
-   prohibited by law if you do not accept this License.  Therefore, by
-   modifying or distributing the Library (or any work based on the
-   Library), you indicate your acceptance of this License to do so, and
-   all its terms and conditions for copying, distributing or modifying
-   the Library or works based on it.
-
-10. Each time you redistribute the Library (or any work based on the
-   Library), the recipient automatically receives a license from the
-   original licensor to copy, distribute, link with or modify the Library
-   subject to these terms and conditions.  You may not impose any further
-   restrictions on the recipients' exercise of the rights granted herein.
-   You are not responsible for enforcing compliance by third parties with
-   this License.
-
-11. If, as a consequence of a court judgment or allegation of patent
-   infringement or for any other reason (not limited to patent issues),
-   conditions are imposed on you (whether by court order, agreement or
-   otherwise) that contradict the conditions of this License, they do not
-   excuse you from the conditions of this License.  If you cannot
-   distribute so as to satisfy simultaneously your obligations under this
-   License and any other pertinent obligations, then as a consequence you
-   may not distribute the Library at all.  For example, if a patent
-   license would not permit royalty-free redistribution of the Library by
-   all those who receive copies directly or indirectly through you, then
-   the only way you could satisfy both it and this License would be to
-   refrain entirely from distribution of the Library.
-
-   If any portion of this section is held invalid or unenforceable under any
-   particular circumstance, the balance of the section is intended to apply,
-   and the section as a whole is intended to apply in other circumstances.
-
-   It is not the purpose of this section to induce you to infringe any
-   patents or other property right claims or to contest validity of any
-   such claims; this section has the sole purpose of protecting the
-   integrity of the free software distribution system which is
-   implemented by public license practices.  Many people have made
-   generous contributions to the wide range of software distributed
-   through that system in reliance on consistent application of that
-   system; it is up to the author/donor to decide if he or she is willing
-   to distribute software through any other system and a licensee cannot
-   impose that choice.
-
-   This section is intended to make thoroughly clear what is believed to
-   be a consequence of the rest of this License.
-
-12. If the distribution and/or use of the Library is restricted in
-   certain countries either by patents or by copyrighted interfaces, the
-   original copyright holder who places the Library under this License may add
-   an explicit geographical distribution limitation excluding those countries,
-   so that distribution is permitted only in or among countries not thus
-   excluded.  In such case, this License incorporates the limitation as if
-   written in the body of this License.
-
-13. The Free Software Foundation may publish revised and/or new
-   versions of the Lesser General Public License from time to time.
-   Such new versions will be similar in spirit to the present version,
-   but may differ in detail to address new problems or concerns.
-
-   Each version is given a distinguishing version number.  If the Library
-   specifies a version number of this License which applies to it and
-   "any later version", you have the option of following the terms and
-   conditions either of that version or of any later version published by
-   the Free Software Foundation.  If the Library does not specify a
-   license version number, you may choose any version ever published by
-   the Free Software Foundation.
-
-14. If you wish to incorporate parts of the Library into other free
-   programs whose distribution conditions are incompatible with these,
-   write to the author to ask for permission.  For software which is
-   copyrighted by the Free Software Foundation, write to the Free
-   Software Foundation; we sometimes make exceptions for this.  Our
-   decision will be guided by the two goals of preserving the free status
-   of all derivatives of our free software and of promoting the sharing
-   and reuse of software generally.
-
-   **NO** **WARRANTY**
-
-15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-   WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-   EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-   OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-   KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-   PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-   LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-   THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-   WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-   AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-   FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-   CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-   LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-   RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-   FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-   SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-   DAMAGES.
-
-### END OF TERMS AND CONDITIONS
-
-### How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the library's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-    Yoyodyne, Inc., hereby disclaims all copyright interest in the
-    library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-    <signature of Ty Coon>, 1 April 1990
-    Ty Coon, President of Vice
-
-That's all there is to it!
-
-@section occt_lgpl_exception OPEN CASCADE EXCEPTION
-
-### Open CASCADE Exception (version 1.0) to GNU LGPL version 2.1.
-
-The object code (i.e. not a source) form of a "work that uses the Library"
-can incorporate material from a header file that is part of the Library.
-As a special exception to the GNU Lesser General Public License version 2.1,
-you may distribute such object code incorporating material from header files
-provided with the Open CASCADE Technology libraries (including code of CDL
-generic classes) under terms of your choice, provided that you give
-prominent notice in supporting documentation to this code that it makes use
-of or is based on facilities provided by the Open CASCADE Technology software.
index 6b841c8932b0b4f939ee6bdb5d8e29e7d4218843..57a62f2ef22fd80f64adebea7876c34c6d0f038d 100644 (file)
@@ -48,6 +48,7 @@
 #include <Select3D_SensitiveGroup.hxx>
 #include <Select3D_SensitiveSegment.hxx>
 #include <SelectMgr_Selection.hxx>
+#include <Standard_ProgramError.hxx>
 #include <UnitsAPI.hxx>
 
 IMPLEMENT_STANDARD_HANDLE (AIS_AngleDimension, AIS_Dimension)
@@ -300,7 +301,7 @@ void AIS_AngleDimension::Init()
 //=======================================================================
 gp_Pnt AIS_AngleDimension::GetCenterOnArc (const gp_Pnt& theFirstAttach,
                                            const gp_Pnt& theSecondAttach,
-                                           const gp_Pnt& theCenter)
+                                           const gp_Pnt& theCenter) const
 {
   // construct plane where the circle and the arc are located
   gce_MakePln aConstructPlane (theFirstAttach, theSecondAttach, theCenter);
@@ -623,30 +624,15 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
   gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
 
   // Handle user-defined and automatic arrow placement
-  bool isArrowsExternal = false;
-  switch (aDimensionAspect->ArrowOrientation())
-  {
-    case Prs3d_DAO_External: isArrowsExternal = true; break;
-    case Prs3d_DAO_Internal: isArrowsExternal = false; break;
-    case Prs3d_DAO_Fit:
-    {
-      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
-      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
-
-      // add margin to ensure a small tail between text and arrow
-      Standard_Real anArrowMargin   = aDimensionAspect->IsText3d() 
-                                    ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
-                                    : 0.0;
-
-      Standard_Real anArrowsWidth   = (anArrowLength + anArrowMargin) * 2.0;
-
-      isArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
-      break;
-    }
-  }
-
+  Standard_Boolean isArrowsExternal = Standard_False;
+  Standard_Integer aLabelPosition = LabelPosition_None;
+  
+  FitTextAlignment (aLabelPosition, isArrowsExternal);
+  
   //Arrows positions and directions
-  gp_Vec aWPDir = gp_Vec (GetPlane().Axis().Direction());
+  // Get normal to plane for extension directions computing.
+  // Stored in the working plane normal is not suitable if flyout is negative.
+  gp_Vec aWPDir = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
 
   gp_Dir aFirstExtensionDir  = aWPDir            ^ gp_Vec (myCenterPoint, aFirstAttach);
   gp_Dir aSecondExtensionDir = aWPDir.Reversed() ^ gp_Vec (myCenterPoint, aSecondAttach);
@@ -670,33 +656,6 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
   aFirstArrowEnd    = aFirstAttach.Translated (-aFirstArrowVec);
   aSecondArrowEnd   = aSecondAttach.Translated (-aSecondArrowVec);
 
-  Standard_Integer aLabelPosition = LabelPosition_None;
-
-  // Handle user-defined and automatic text placement
-  switch (aDimensionAspect->TextHorizontalPosition())
-  {
-    case Prs3d_DTHP_Left  : aLabelPosition |= LabelPosition_Left; break;
-    case Prs3d_DTHP_Right : aLabelPosition |= LabelPosition_Right; break;
-    case Prs3d_DTHP_Center: aLabelPosition |= LabelPosition_HCenter; break;
-    case Prs3d_DTHP_Fit:
-    {
-      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
-      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
-      Standard_Real anArrowsWidth   = anArrowLength * 2.0;
-      Standard_Real aContentWidth   = isArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
-
-      aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
-      break;
-    }
-  }
-
-  switch (aDimensionAspect->TextVerticalPosition())
-  {
-    case Prs3d_DTVP_Above  : aLabelPosition |= LabelPosition_Above; break;
-    case Prs3d_DTVP_Below  : aLabelPosition |= LabelPosition_Below; break;
-    case Prs3d_DTVP_Center : aLabelPosition |= LabelPosition_VCenter; break;
-  }
-
   // Group1: stenciling text and the angle dimension arc
   Prs3d_Root::NewGroup (thePresentation);
 
@@ -729,7 +688,8 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
       if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
       {
         gp_Vec aDimensionDir (aFirstAttach, aSecondAttach);
-        gp_Pnt aTextPos = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
+        gp_Pnt aTextPos = myIsTextPositionFixed ? myFixedTextPosition
+                                                : GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
         gp_Dir aTextDir = aDimensionDir;
 
         DrawText (thePresentation,
@@ -807,7 +767,7 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
     if (aHPosition != LabelPosition_Left)
     {
       DrawExtension (thePresentation,
-                     anExtensionSize,
+                     aDimensionAspect->ShortExtensionSize(),
                      aFirstArrowEnd,
                      aFirstExtensionDir,
                      THE_EMPTY_LABEL_STRING,
@@ -819,7 +779,7 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
     if (aHPosition != LabelPosition_Right)
     {
       DrawExtension (thePresentation,
-                     anExtensionSize,
+                     aDimensionAspect->ShortExtensionSize(),
                      aSecondArrowEnd,
                      aSecondExtensionDir,
                      THE_EMPTY_LABEL_STRING,
@@ -891,6 +851,11 @@ Standard_Boolean AIS_AngleDimension::InitTwoEdgesAngle (gp_Pln& theComputedPlane
   Standard_Boolean isParallelLines = Abs (aFirstLin.Angle (aSecondLin) - M_PI) <= Precision::Angular();
 
   gp_Pnt aPoint  = aFirstLine->Value (0.0);
+  if (isParallelLines && aFirstLin.Distance(aPoint) < Precision::Confusion())
+  {
+    // If two lines are parallel and distance between them is 0, we can't find a plane. 
+    return Standard_False;
+  }
   gp_Dir aNormal = isParallelLines
                      ? gp_Vec (aSecondLin.Normal (aPoint).Direction()) ^ gp_Vec (aSecondLin.Direction())
                      : gp_Vec (aFirstLin.Direction()) ^ gp_Vec (aSecondLin.Direction());
@@ -1184,3 +1149,272 @@ Standard_Boolean AIS_AngleDimension::IsValidPoints (const gp_Pnt& theFirstPoint,
       && gp_Vec (theCenterPoint, theFirstPoint).Angle (
            gp_Vec (theCenterPoint, theSecondPoint)) > Precision::Angular();
 }
+
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+const gp_Pnt AIS_AngleDimension::GetTextPosition() const
+{
+  if (!IsValid())
+  {
+    return gp::Origin();
+  }
+  
+  if (myIsTextPositionFixed)
+  {
+    return myFixedTextPosition;
+  }
+
+  // Counts text position according to the dimension parameters
+  gp_Pnt aTextPosition (gp::Origin());
+
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+  // Prepare label string and compute its geometrical width
+  Standard_Real aLabelWidth;
+  TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
+
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
+
+  // Handle user-defined and automatic arrow placement
+  Standard_Boolean isArrowsExternal = Standard_False;
+  Standard_Integer aLabelPosition = LabelPosition_None;
+  FitTextAlignment (aLabelPosition, isArrowsExternal);
+
+  // Get text position
+  switch (aLabelPosition & LabelPosition_HMask)
+  {
+  case LabelPosition_HCenter:
+    {
+      aTextPosition = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
+    }
+    break;
+  case LabelPosition_Left:
+    {
+      gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
+      gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aFirstAttach);
+      Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+      Standard_Real anOffset = isArrowsExternal
+          ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+          : anExtensionSize;
+      gp_Vec anExtensionVec  = gp_Vec(anExtensionDir)*(-anOffset);
+      aTextPosition = aFirstAttach.Translated (anExtensionVec);
+    }
+    break;
+  case LabelPosition_Right:
+    {
+      gp_Dir aPlaneNormal = gp_Vec (aFirstAttach, aSecondAttach) ^ gp_Vec (myCenterPoint, aFirstAttach);
+      gp_Dir anExtensionDir = aPlaneNormal ^ gp_Vec (myCenterPoint, aSecondAttach);
+      Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+      Standard_Real anOffset = isArrowsExternal
+          ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+          : anExtensionSize;
+      gp_Vec anExtensionVec  = gp_Vec(anExtensionDir)*(anOffset);
+      aTextPosition = aSecondAttach.Translated (anExtensionVec);
+    }
+    break;
+  }
+
+  return aTextPosition;
+}
+
+//=======================================================================
+//function : SetTextPosition
+//purpose  : 
+//=======================================================================
+void AIS_AngleDimension::SetTextPosition (const gp_Pnt& theTextPos)
+{
+  if (!IsValid())
+  {
+    return;
+  }
+
+  // The text position point for angle dimension should belong to the working plane.
+  if (!GetPlane().Contains (theTextPos, Precision::Confusion()))
+  {
+    Standard_ProgramError::Raise ("The text position point for angle dimension doesn't belong to the working plane.");
+  }
+
+  myIsTextPositionFixed = Standard_True;
+  myFixedTextPosition = theTextPos;
+
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+  // Compute flyout direction vector.
+  gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
+  gp_Dir aTargetPointsDir = gce_MakeDir (myFirstPoint, mySecondPoint);
+
+  // Build circle with radius that is equal to distance from text position to the center point.
+  Standard_Real aRadius = gp_Vec (myCenterPoint, theTextPos).Magnitude();
+
+  // Set attach points in positive direction of the flyout.
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * aRadius);
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * aRadius);
+
+  gce_MakeCirc aConstructCircle (myCenterPoint, GetPlane(), aRadius);
+  if (!aConstructCircle.IsDone())
+  {
+    return;
+  }
+  gp_Circ aCircle = aConstructCircle.Value();
+
+  // Default values
+  aDimensionAspect->SetExtensionSize (aDimensionAspect->ArrowAspect()->Length());
+  aDimensionAspect->SetTextHorizontalPosition (Prs3d_DTHP_Center);
+
+  Standard_Real aParamBeg = ElCLib::Parameter (aCircle, aFirstAttach);
+  Standard_Real aParamEnd = ElCLib::Parameter (aCircle, aSecondAttach);
+  ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
+  Standard_Real aTextPar = ElCLib::Parameter (aCircle , theTextPos);
+
+  // Horizontal center
+  if (aTextPar > aParamBeg && aTextPar < aParamEnd)
+  {
+    myFlyout = aRadius;
+
+    if (LayoutMode() == AIS_DLM_Automatic)
+    {
+      // Adjust text position so that text was aligned.
+      myFixedTextPosition = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
+    }
+    SetToUpdate();
+    return;
+  }
+
+  aParamBeg += M_PI;
+  aParamEnd += M_PI;
+  ElCLib::AdjustPeriodic (0.0, M_PI * 2, Precision::PConfusion(), aParamBeg, aParamEnd);
+
+  if (aTextPar > aParamBeg  && aTextPar < aParamEnd)
+  {
+    myFlyout = -aRadius;
+
+    if (LayoutMode() == AIS_DLM_Automatic)
+    {
+      // Adjust text position so that text was aligned.
+      aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
+      aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
+      myFixedTextPosition = GetCenterOnArc (aFirstAttach, aSecondAttach, myCenterPoint);
+    }
+    SetToUpdate();
+    return;
+  }
+
+  // Text on the extensions
+  gp_Lin aFirstLine = gce_MakeLin (myCenterPoint, myFirstPoint);
+  gp_Lin aSecondLine = gce_MakeLin (myCenterPoint, mySecondPoint);
+  gp_Pnt aFirstTextProj = AIS::Nearest (aFirstLine, theTextPos);
+  gp_Pnt aSecondTextProj = AIS::Nearest (aSecondLine, theTextPos);
+  Standard_Real aFirstDist = aFirstTextProj.Distance (theTextPos);
+  Standard_Real aSecondDist = aSecondTextProj.Distance (theTextPos);
+
+  if (aFirstDist <= aSecondDist)
+  {
+    aRadius = myCenterPoint.Distance (aFirstTextProj);
+    aDimensionAspect->SetExtensionSize (aFirstDist);
+    aDimensionAspect->SetTextHorizontalPosition (Prs3d_DTHP_Left);
+
+    gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, myFirstPoint).Normalized().Scaled (aRadius);
+
+    if (aFirstTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion())
+    {
+      myFlyout = -aRadius;
+    }
+    else
+    {
+      myFlyout = aRadius;
+    }
+  }
+  else
+  {
+    aRadius = myCenterPoint.Distance (aSecondTextProj);
+    aDimensionAspect->SetExtensionSize (aSecondDist);
+    aDimensionAspect->SetTextHorizontalPosition (Prs3d_DTHP_Right);
+
+    gp_Vec aPosFlyoutDir = gp_Vec (myCenterPoint, mySecondPoint).Normalized().Scaled (aRadius);
+
+    if (aSecondTextProj.Distance (myCenterPoint.Translated (aPosFlyoutDir)) > Precision::Confusion())
+    {
+      myFlyout = -aRadius;
+    }
+    else
+    {
+      myFlyout = aRadius;
+    }
+  }
+}
+
+//=======================================================================
+//function : FitTextAlignment
+//purpose  : 
+//=======================================================================
+void AIS_AngleDimension::FitTextAlignment (Standard_Integer& theLabelPosition,
+                                           Standard_Boolean& theIsArrowsExternal) const
+{
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+  Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
+
+  // Prepare label string and compute its geometrical width
+  Standard_Real aLabelWidth;
+  TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
+
+  // add margins to label width
+  if (aDimensionAspect->IsText3d())
+  {
+    aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
+  }
+
+  gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
+  gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
+
+  // Handle user-defined and automatic arrow placement
+  switch (aDimensionAspect->ArrowOrientation())
+  {
+    case Prs3d_DAO_External: theIsArrowsExternal = true; break;
+    case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
+    case Prs3d_DAO_Fit:
+    {
+      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
+      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
+
+      // Add margin to ensure a small tail between text and arrow
+      Standard_Real anArrowMargin   = aDimensionAspect->IsText3d() 
+                                    ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
+                                    : 0.0;
+
+      Standard_Real anArrowsWidth   = (anArrowLength + anArrowMargin) * 2.0;
+
+      theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
+      break;
+    }
+  }
+
+  // Handle user-defined and automatic text placement
+  switch (aDimensionAspect->TextHorizontalPosition())
+  {
+    case Prs3d_DTHP_Left  : theLabelPosition |= LabelPosition_Left; break;
+    case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
+    case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
+    case Prs3d_DTHP_Fit:
+    {
+      gp_Vec anAttachVector (aFirstAttach, aSecondAttach);
+      Standard_Real aDimensionWidth = anAttachVector.Magnitude();
+      Standard_Real anArrowsWidth   = anArrowLength * 2.0;
+      Standard_Real aContentWidth   = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
+
+      theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
+      break;
+    }
+  }
+
+  switch (aDimensionAspect->TextVerticalPosition())
+  {
+    case Prs3d_DTVP_Above  : theLabelPosition |= LabelPosition_Above; break;
+    case Prs3d_DTVP_Below  : theLabelPosition |= LabelPosition_Below; break;
+    case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
+  }
+
+}
index 31548dd8b882cbb581eaa00b34eb8a274249c84d..b48fb81a583361bf5cabd8b6e87a8b0b35e83cbb 100755 (executable)
@@ -197,6 +197,16 @@ public:
 
   Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& theUnits);
 
+  //! Principle of horizontal text alignment settings:
+  //! - divide circle into two halfs according to attachment points
+  //! - if aTextPos is between attach points -> Center + positive flyout
+  //! - if aTextPos is not between attach points but in this half -> Left or Right + positive flyout
+  //! - if aTextPos is between reflections of attach points -> Center + negative flyout
+  //! - if aTextPos is not between reflections of attach points -> Left or Right + negative flyout
+  Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos);
+
+  Standard_EXPORT virtual const gp_Pnt GetTextPosition () const;
+
 public:
 
   DEFINE_STANDARD_RTTI (AIS_AngleDimension)
@@ -212,7 +222,7 @@ protected:
   //! @return the center of the dimension arc (the main dimension line in case of angle). 
   Standard_EXPORT gp_Pnt GetCenterOnArc (const gp_Pnt& theFirstAttach,
                                          const gp_Pnt& theSecondAttach,
-                                         const gp_Pnt& theCenter);
+                                         const gp_Pnt& theCenter) const;
 
   //! Draws main dimension line (arc).
   //! @param thePresentation [in] the dimension presentation.
@@ -247,6 +257,15 @@ protected:
                                         const Standard_Integer theMode,
                                         const Standard_Integer theLabelPosition);
 
+  //! Fits text alignment relatively to the dimension line.
+  //! @param theLabelPosition [out] the label position, contains bits that defines
+  //! vertical and horizontal alignment. (for internal usage in count text position)
+  //! @param theIsArrowExternal [out] is the arrows external,
+  //! if arrow orientation in the dimension aspect is Prs3d_DAO_Fit, it fits arrow
+  //! orientation automatically.
+  Standard_EXPORT void FitTextAlignment (Standard_Integer& theLabelPosition,
+                                         Standard_Boolean& theIsArrowsExternal) const;
+
 protected:
 
   Standard_EXPORT virtual void ComputePlane();
index 761f701e72b0d1021faafb99d6b729985455b4de..f93938b13984061a2c60da7fd11366fe4585dddc 100644 (file)
@@ -296,7 +296,7 @@ void AIS_DiameterDimension::Compute (const Handle(PrsMgr_PresentationManager3d)&
 
   gp_Pnt aFirstPnt (gp::Origin());
   gp_Pnt aSecondPnt (gp::Origin());
-  ComputeSidePoints (myCircle, GetPlane(), aFirstPnt, aSecondPnt);
+  ComputeSidePoints (myCircle, aFirstPnt, aSecondPnt);
 
   DrawLinearDimension (thePresentation, theMode, aFirstPnt, aSecondPnt);
 }
@@ -315,7 +315,7 @@ void AIS_DiameterDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selec
 
   gp_Pnt aFirstPnt (gp::Origin());
   gp_Pnt aSecondPnt (gp::Origin());
-  ComputeSidePoints (myCircle, GetPlane(), aFirstPnt, aSecondPnt);
+  ComputeSidePoints (myCircle, aFirstPnt, aSecondPnt);
 
   ComputeLinearFlyouts (theSelection, theEntityOwner, aFirstPnt, aSecondPnt);
 }
@@ -324,15 +324,14 @@ void AIS_DiameterDimension::ComputeFlyoutSelection (const Handle(SelectMgr_Selec
 //function : ComputeSidePoints
 //purpose  : 
 //=======================================================================
-void AIS_DiameterDimension::ComputeSidePoints (const gp_Circ& /*theCircle*/,
-                                               const gp_Pln& /*thePlane*/,
+void AIS_DiameterDimension::ComputeSidePoints (const gp_Circ& theCircle,
                                                gp_Pnt& theFirstPnt,
                                                gp_Pnt& theSecondPnt)
 {
   theFirstPnt = AnchorPoint();
 
-  gp_Vec aRadiusVector (myCircle.Location(), theFirstPnt);
-  theSecondPnt = myCircle.Location().Translated (-aRadiusVector);
+  gp_Vec aRadiusVector (theCircle.Location(), theFirstPnt);
+  theSecondPnt = theCircle.Location().Translated (-aRadiusVector);
 }
 
 //=======================================================================
@@ -358,3 +357,33 @@ Standard_Boolean AIS_DiameterDimension::IsValidAnchor (const gp_Circ& theCircle,
   return Abs (anAnchorDist - aRadius) > Precision::Confusion()
       && aCirclePlane.Contains (theAnchor, Precision::Confusion());
 }
+
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+const gp_Pnt AIS_DiameterDimension::GetTextPosition () const
+{
+  if (myIsTextPositionFixed)
+  {
+    return myFixedTextPosition;
+  }
+  
+  // Counts text position according to the dimension parameters
+  return GetTextPositionForLinear (myAnchorPoint, myCircle.Location());
+}
+
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+void AIS_DiameterDimension::SetTextPosition (const gp_Pnt& theTextPos)
+{
+  if (!myIsValid)
+  {
+    return;
+  }
+
+  SetTextPositionForLinear (myAnchorPoint, myCircle.Location(), theTextPos);
+  SetToUpdate();
+}
index 7783f8c54c85b03ac0c7626405354f2f687dd7f4..508b15c0cb13dd00943cc1f0ff2c096c9a620be7 100644 (file)
@@ -114,15 +114,19 @@ public:
   Standard_EXPORT void SetMeasuredGeometry (const TopoDS_Shape& theShape);
 
   //! @return the display units string.
-  Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits () const;
+  Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits() const;
   
   //! @return the model units string.
-  Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits () const;
+  Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits() const;
 
   Standard_EXPORT virtual void SetDisplayUnits (const TCollection_AsciiString& theUnits);
 
   Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& theUnits);
 
+  Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos);
+
+  Standard_EXPORT virtual const gp_Pnt GetTextPosition() const;
+
 public:
 
   DEFINE_STANDARD_RTTI(AIS_DiameterDimension)
@@ -154,16 +158,14 @@ protected:
 
 protected:
 
-  //! Compute points on the circle sides for the specified dimension plane.
+  //! Compute points on the circle sides for the dimension plane.
   //! Program error exception is raised if the dimension plane "x" direction 
   //! is orthogonal to plane (the "impossible" case). The passed dimension plane
   //! is the one specially computed to locate dimension presentation in circle.
   //! @param theCircle [in] the circle.
-  //! @param thePlane [in] the dimension presentation plane computed.
   //! @param theFirstPnt [out] the first point.
   //! @param theSecondPnt [out] the second point.
   Standard_EXPORT void ComputeSidePoints (const gp_Circ& theCircle,
-                                          const gp_Pln& thePlane,
                                           gp_Pnt& theFirstPnt,
                                           gp_Pnt& theSecondPnt);
 
index e1c72fdeb83e7f1a218bb15e892b8be994f7fdea..4fb03f59d47fb2743a51efaed305196b7142f3a1 100755 (executable)
 #include <ElCLib.hxx>
 #include <Font_BRepFont.hxx>
 #include <GC_MakeCircle.hxx>
+#include <Geom_Line.hxx>
 #include <GeomAdaptor_Curve.hxx>
 #include <Geom_Circle.hxx>
 #include <Geom_TrimmedCurve.hxx>
 #include <gce_MakeDir.hxx>
 #include <gce_MakeLin.hxx>
+#include <gce_MakePln.hxx>
 #include <Graphic3d_ArrayOfSegments.hxx>
 #include <Graphic3d_ArrayOfTriangles.hxx>
 #include <Graphic3d_AspectLine3d.hxx>
@@ -57,6 +59,7 @@
 #include <Select3D_SensitiveFace.hxx>
 #include <Select3D_SensitiveTriangle.hxx>
 #include <Standard_CString.hxx>
+#include <Standard_ProgramError.hxx>
 #include <StdPrs_ShadedShape.hxx>
 #include <StdPrs_WFShape.hxx>
 #include <TCollection_AsciiString.hxx>
@@ -68,7 +71,6 @@
 #include <Units_UnitsDictionary.hxx>
 #include <UnitsAPI.hxx>
 #include <UnitsAPI_SystemUnits.hxx>
-#include <Standard_ProgramError.hxx>
 
 IMPLEMENT_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
 IMPLEMENT_STANDARD_RTTIEXT(AIS_Dimension, AIS_InteractiveObject)
@@ -97,6 +99,7 @@ AIS_Dimension::AIS_Dimension (const AIS_KindOfDimension theType)
 : AIS_InteractiveObject(),
   myCustomValue (0.0),
   myIsValueCustom (Standard_False),
+  myLayoutMode (AIS_DLM_Automatic),
   mySpecialSymbol (' '),
   myDisplaySpecialSymbol (AIS_DSS_No),
   myGeometryType (GeometryType_UndefShapes),
@@ -235,6 +238,15 @@ void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
   SetToUpdate();
 }
 
+//=======================================================================
+//function : SetLayoutMode
+//purpose  :
+//=======================================================================
+ void AIS_Dimension::SetLayoutMode (const AIS_DimensionLayoutMode theLayoutMode)
+ {
+   myLayoutMode = theLayoutMode;
+ }
+
 //=======================================================================
 //function : GetDisplayUnits
 //purpose  :
@@ -651,27 +663,11 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
   }
 
   // handle user-defined and automatic arrow placement
-  bool isArrowsExternal = false;
-  switch (aDimensionAspect->ArrowOrientation())
-  {
-    case Prs3d_DAO_External: isArrowsExternal = true; break;
-    case Prs3d_DAO_Internal: isArrowsExternal = false; break;
-    case Prs3d_DAO_Fit:
-    {
-      // add margin to ensure a small tail between text and arrow
-      Standard_Real anArrowMargin   = aDimensionAspect->IsText3d() 
-                                    ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
-                                    : 0.0;
-
-      Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
-      Standard_Real anArrowsWidth   = theIsOneSide 
-                                    ?  anArrowLength + anArrowMargin
-                                    : (anArrowLength + anArrowMargin) * 2.0;
+  Standard_Boolean isArrowsExternal = Standard_False;
+  Standard_Integer aLabelPosition = LabelPosition_None;
 
-      isArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
-      break;
-    }
-  }
+  FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide,
+                             aLabelPosition, isArrowsExternal);
 
   // compute arrows positions and directions
   gp_Dir aFirstArrowDir       = aDimensionLine.Direction().Reversed();
@@ -701,32 +697,6 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
   gp_Pnt aCenterLineEnd = isArrowsExternal || theIsOneSide
     ? aLineEndPoint : aSecondArrowEnd;
 
-  Standard_Integer aLabelPosition = LabelPosition_None;
-
-  // handle user-defined and automatic text placement
-  switch (aDimensionAspect->TextHorizontalPosition())
-  {
-    case Prs3d_DTHP_Left  : aLabelPosition |= LabelPosition_Left; break;
-    case Prs3d_DTHP_Right : aLabelPosition |= LabelPosition_Right; break;
-    case Prs3d_DTHP_Center: aLabelPosition |= LabelPosition_HCenter; break;
-    case Prs3d_DTHP_Fit:
-    {
-      Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
-      Standard_Real anArrowsWidth   = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
-      Standard_Real aContentWidth   = isArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
-
-      aLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
-      break;
-    }
-  }
-
-  // handle vertical text placement options
-  switch (aDimensionAspect->TextVerticalPosition())
-  {
-    case Prs3d_DTVP_Above  : aLabelPosition |= LabelPosition_Above; break;
-    case Prs3d_DTVP_Below  : aLabelPosition |= LabelPosition_Below; break;
-    case Prs3d_DTVP_Center : aLabelPosition |= LabelPosition_VCenter; break;
-  }
 
   switch (aLabelPosition & LabelPosition_HMask)
   {
@@ -738,7 +708,8 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
       // add label on dimension or extension line to presentation
       Prs3d_Root::NewGroup (thePresentation);
 
-      gp_Pnt aTextPos = (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
+      gp_Pnt aTextPos = myIsTextPositionFixed ? myFixedTextPosition
+                                              : (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
       gp_Dir aTextDir = aDimensionLine.Direction();
 
       // add text primitives
@@ -829,12 +800,12 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
         // add arrow extension lines to presentation
         Prs3d_Root::NewGroup (thePresentation);
 
-        DrawExtension (thePresentation, anExtensionSize,
+        DrawExtension (thePresentation, aDimensionAspect->ShortExtensionSize(),
                        aFirstArrowEnd, aFirstExtensionDir,
                        THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
         if (!theIsOneSide)
         {
-          DrawExtension (thePresentation, anExtensionSize,
+          DrawExtension (thePresentation, aDimensionAspect->ShortExtensionSize(),
                          aSecondArrowEnd, aSecondExtensionDir,
                          THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
         }
@@ -898,7 +869,7 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
         // add extension lines for external arrows
         Prs3d_Root::NewGroup (thePresentation);
 
-        DrawExtension (thePresentation, anExtensionSize,
+        DrawExtension (thePresentation, aDimensionAspect->ShortExtensionSize(),
                        aSecondArrowEnd, aSecondExtensionDir,
                        THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
       }
@@ -958,7 +929,7 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
         // add extension lines for external arrows
         Prs3d_Root::NewGroup (thePresentation);
 
-        DrawExtension (thePresentation, anExtensionSize,
+        DrawExtension (thePresentation, aDimensionAspect->ShortExtensionSize(),
                        aFirstArrowEnd, aFirstExtensionDir,
                        THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
       }
@@ -1142,7 +1113,6 @@ Standard_Boolean AIS_Dimension::InitCircularDimension (const TopoDS_Shape& theSh
         theCircle = aMkCirc.Value()->Circ();
       }
 
-      gp_Vec aVec = gp_Vec (theCircle.Location(), aCurPos).Normalized();
       aFirstPoint = ElCLib::Value (aFirstU, theCircle);
       aLastPoint = ElCLib::Value (aLastU,  theCircle);
     }
@@ -1357,3 +1327,283 @@ void AIS_Dimension::PointsForArrow (const gp_Pnt& thePeakPnt,
   theSidePnt1 = ElCLib::Value ( anEdgeLength, anEdgeLin);
   theSidePnt2 = ElCLib::Value (-anEdgeLength, anEdgeLin);
 }
+
+//=======================================================================
+//function : GetTextPositionForLinear
+//purpose  : 
+//=======================================================================
+Standard_Boolean AIS_Dimension::SetTextPositionForLinear (const gp_Pnt& theFirstPoint,
+                                                          const gp_Pnt& theSecondPoint,
+                                                          const gp_Pnt& theTextPos)
+{
+  if (!IsValid())
+  {
+    return Standard_False;
+  }
+
+  myIsTextPositionFixed = Standard_True;
+  myFixedTextPosition = theTextPos;
+
+#if 1  //HOMAG
+
+  //Don't set new plane if the text position lies on the attachment points line.
+  gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
+  gp_Lin aTargetPointsLin (theFirstPoint, aTargetPointsDir);
+  if (!aTargetPointsLin.Contains (theTextPos, Precision::Confusion()))
+  {
+    myPlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint);
+    myIsPlaneCustom = Standard_False;
+  }
+
+  // Compute dimension line points.
+  gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
+  gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
+
+  //check if the target and plane dir not parallel. Else the cross
+  //product fails.
+  if (aPlaneNormal.IsParallel(aTargetPointsDir, Precision::Angular()))
+      return Standard_False;
+#else
+
+  //Set new automatic plane.
+  myPlane = gce_MakePln (theTextPos, theFirstPoint, theSecondPoint);
+  myIsPlaneCustom = Standard_False;
+
+  // Compute dimension line points.
+  gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
+  gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
+  gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
+#endif
+
+  // Compute flyout direction vector.
+  gp_Dir aPositiveFlyout = aPlaneNormal ^ aTargetPointsDir;
+
+  // Set flyout.
+  gp_Vec aFirstToTextVec (theFirstPoint, theTextPos);
+
+  Standard_Real aCos = aFirstToTextVec.Normalized() * gp_Vec (aTargetPointsDir);
+
+  gp_Pnt aTextPosProj = theFirstPoint.Translated
+                        (gp_Vec (aTargetPointsDir)*aFirstToTextVec.Magnitude()*aCos);
+
+
+  // Compute flyout value and direction.
+  gp_Vec aFlyoutVector = gp_Vec (aTextPosProj, theTextPos);
+#if 1 //HOMAG
+  //Check if the vectors magnitude is not 0! Else
+  //it does generate an exception for IsOpposite.
+  myFlyout = 0.0;
+  if (aFlyoutVector.Magnitude() > Precision::Confusion())
+  {
+     myFlyout = (gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular()))
+                 ? -aFlyoutVector.Magnitude()
+                 : (aFlyoutVector.Magnitude());
+  }
+
+#else
+
+  myFlyout = (gp_Dir (aFlyoutVector).IsOpposite (aPositiveFlyout, Precision::Angular()))
+             ? -aFlyoutVector.Magnitude()
+             : (aFlyoutVector.Magnitude());
+
+#endif
+  // Set horisontal text alignment.
+   if (aCos < 0.0)
+  {
+    myDrawer->DimensionAspect()->SetTextHorizontalPosition (Prs3d_DTHP_Left);
+    myDrawer->DimensionAspect()->SetExtensionSize (theTextPos.Distance (theFirstPoint.Translated (aFlyoutVector)));
+  }
+  else if (aTextPosProj.Distance (theFirstPoint) > theFirstPoint.Distance (theSecondPoint))
+  {
+    myDrawer->DimensionAspect()->SetTextHorizontalPosition (Prs3d_DTHP_Right);
+    myDrawer->DimensionAspect()->SetExtensionSize (theTextPos.Distance (theSecondPoint.Translated (aFlyoutVector)));
+  }
+  else
+  {
+    myDrawer->DimensionAspect()->SetTextHorizontalPosition (Prs3d_DTHP_Center);
+
+    if (LayoutMode() == AIS_DLM_Automatic)
+    {
+      // Adjust text position so that text was aligned.
+      myFixedTextPosition = theFirstPoint.Translated (aTargetPointsVec * 0.5 + aFlyoutVector);
+    }
+  }
+  return Standard_True;
+}
+
+//=======================================================================
+//function : GetTextPositionForLinear
+//purpose  : 
+//=======================================================================
+gp_Pnt AIS_Dimension::GetTextPositionForLinear (const gp_Pnt& theFirstPoint,
+                                                const gp_Pnt& theSecondPoint,
+                                                const Standard_Boolean theIsOneSide) const
+{
+  if (!myIsValid)
+  {
+    return gp::Origin();
+  }
+
+  gp_Pnt aTextPosition (gp::Origin());
+
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+  // Get label alignment and arrow orientation.
+  Standard_Integer aLabelPosition = 0;
+  Standard_Boolean isArrowsExternal = Standard_False;
+  FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide,
+                             aLabelPosition, isArrowsExternal);
+
+  // Compute dimension line points.
+  gp_Dir aPlaneNormal = GetPlane().Axis().Direction();
+  gp_Vec aTargetPointsVec (theFirstPoint, theSecondPoint);
+
+  // Compute flyout direction vector
+  gp_Dir aFlyoutVector = aPlaneNormal ^ gp_Dir(aTargetPointsVec);
+
+  // create lines for layouts
+  gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
+  gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
+  // Get flyout end points
+  gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint)  + GetFlyout(), aLine1);
+  gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
+
+
+  // Get text position.
+  switch (aLabelPosition & LabelPosition_HMask)
+  {
+  case LabelPosition_Left:
+    {
+      gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
+      Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+      Standard_Real anOffset = isArrowsExternal
+          ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+          : anExtensionSize;
+      gp_Vec anExtensionVec  = gp_Vec(aTargetPointsDir)*(-anOffset);
+      aTextPosition = aLineEndPoint.Translated (anExtensionVec);
+    }
+    break;
+  case LabelPosition_Right:
+    {
+      gp_Dir aTargetPointsDir = gce_MakeDir (theFirstPoint, theSecondPoint);
+      Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
+      Standard_Real anOffset = isArrowsExternal
+          ? anExtensionSize + aDimensionAspect->ArrowAspect()->Length()
+          : anExtensionSize;
+      gp_Vec anExtensionVec  = gp_Vec(aTargetPointsDir)*(anOffset);
+      aTextPosition = aLineBegPoint.Translated (anExtensionVec);
+    }
+    break;
+  case LabelPosition_HCenter:
+    {
+      aTextPosition = (aLineBegPoint.XYZ() + aLineEndPoint.XYZ()) * 0.5;
+    }
+    break;
+  }
+
+  return aTextPosition;
+}
+
+//=======================================================================
+//function : FitTextAlignment
+//purpose  : 
+//=======================================================================
+void AIS_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
+                                               const gp_Pnt& theSecondPoint,
+                                               const Standard_Boolean theIsOneSide,
+                                               Standard_Integer& theLabelPosition,
+                                               Standard_Boolean& theIsArrowsExternal) const
+{
+  theLabelPosition = LabelPosition_None;
+  theIsArrowsExternal = Standard_False;
+
+  // Compute dimension line points
+  gp_Ax1 aPlaneNormal = GetPlane().Axis();
+  gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
+
+  // compute flyout direction vector
+  gp_Dir aFlyoutVector = aPlaneNormal.Direction() ^ aTargetPointsVector;
+
+  // create lines for layouts
+  gp_Lin aLine1 (theFirstPoint, aFlyoutVector);
+  gp_Lin aLine2 (theSecondPoint, aFlyoutVector);
+
+  // Get flyout end points
+  gp_Pnt aLineBegPoint = ElCLib::Value (ElCLib::Parameter (aLine1, theFirstPoint)  + GetFlyout(), aLine1);
+  gp_Pnt aLineEndPoint = ElCLib::Value (ElCLib::Parameter (aLine2, theSecondPoint) + GetFlyout(), aLine2);
+
+  Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
+
+  gp_Lin aDimensionLine = gce_MakeLin (aLineBegPoint, aLineEndPoint);
+
+  // For extensions we need to know arrow size, text size and extension size: get it from aspect
+  Quantity_Length anArrowLength   = aDimensionAspect->ArrowAspect()->Length();
+  // prepare label string and compute its geometrical width
+  Standard_Real aLabelWidth;
+  TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
+
+  // Add margins to cut dimension lines for 3d text
+  if (aDimensionAspect->IsText3d())
+  {
+    aLabelWidth += aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN * 2.0;
+  }
+
+  // Handle user-defined and automatic arrow placement
+  switch (aDimensionAspect->ArrowOrientation())
+  {
+    case Prs3d_DAO_External: theIsArrowsExternal = true; break;
+    case Prs3d_DAO_Internal: theIsArrowsExternal = false; break;
+    case Prs3d_DAO_Fit:
+    {
+      // Add margin to ensure a small tail between text and arrow
+      Standard_Real anArrowMargin   = aDimensionAspect->IsText3d() 
+                                    ? aDimensionAspect->TextAspect()->Height() * THE_3D_TEXT_MARGIN
+                                    : 0.0;
+
+      Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
+      Standard_Real anArrowsWidth   = theIsOneSide 
+                                    ?  anArrowLength + anArrowMargin
+                                    : (anArrowLength + anArrowMargin) * 2.0;
+
+      theIsArrowsExternal = aDimensionWidth < aLabelWidth + anArrowsWidth;
+      break;
+    }
+  }
+
+  // Compute arrows positions and directions
+  gp_Dir aFirstArrowDir       = aDimensionLine.Direction().Reversed();
+  gp_Dir aSecondArrowDir      = aDimensionLine.Direction();
+  gp_Dir aFirstExtensionDir   = aDimensionLine.Direction().Reversed();
+  gp_Dir aSecondExtensionDir  = aDimensionLine.Direction();
+
+  if (theIsArrowsExternal)
+  {
+    aFirstArrowDir.Reverse();
+    aSecondArrowDir.Reverse();
+  }
+
+  // Handle user-defined and automatic text placement
+  switch (aDimensionAspect->TextHorizontalPosition())
+  {
+    case Prs3d_DTHP_Left  : theLabelPosition |= LabelPosition_Left; break;
+    case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
+    case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
+    case Prs3d_DTHP_Fit:
+    {
+      Standard_Real aDimensionWidth = aLineBegPoint.Distance (aLineEndPoint);
+      Standard_Real anArrowsWidth   = theIsOneSide ? anArrowLength : 2.0 * anArrowLength;
+      Standard_Real aContentWidth   = theIsArrowsExternal ? aLabelWidth : aLabelWidth + anArrowsWidth;
+
+      theLabelPosition |= aDimensionWidth < aContentWidth ? LabelPosition_Left : LabelPosition_HCenter;
+      break;
+    }
+  }
+
+  // Handle vertical text placement options
+  switch (aDimensionAspect->TextVerticalPosition())
+  {
+    case Prs3d_DTVP_Above  : theLabelPosition |= LabelPosition_Above; break;
+    case Prs3d_DTVP_Below  : theLabelPosition |= LabelPosition_Below; break;
+    case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
+  }
+}
index 39e28dc4ec65599013b3d4e2d4303ba210cf4f03..3a50257b53d1ebf215ec37904e33b1a72bf5705a 100755 (executable)
@@ -16,6 +16,7 @@
 #ifndef _AIS_Dimension_HeaderFile
 #define _AIS_Dimension_HeaderFile
 
+#include <AIS_DimensionLayoutMode.hxx>
 #include <AIS_DimensionSelectionMode.hxx>
 #include <AIS_DimensionOwner.hxx>
 #include <AIS_DisplaySpecialSymbol.hxx>
@@ -56,11 +57,11 @@ DEFINE_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
 //! The specified by user units are stored in the dimension's drawer.
 //!
 //! As a drawing, the dimension is composed from the following components:
-//! - Attachement (binding) points. The points where the dimension lines attaches to, for
+//! - Attachment (binding) points. The points where the dimension lines attaches to, for
 //!   length dimensions the distances are measured between these points.
-//! - Main dimension line. The which extends from the attachement points in "up" direction,
+//! - Main dimension line. The which extends from the attachment points in "up" direction,
 //!   and which contains text label on it with value string.
-//! - Flyouts. The lines connecting the attachement points with main dimension line.
+//! - Flyouts. The lines connecting the attachment points with main dimension line.
 //! - Extension. The lines used to extend the main dimension line in the cases when text
 //!   or arrows do not fit into the main dimension line due to their size.
 //! - Arrows.
@@ -75,7 +76,7 @@ DEFINE_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
 //!          |flyout                       flyout|
 //!          |                                   |
 //!          +-----------------------------------+
-//! attachement                                attachement
+//! attachment                                attachment
 //!  point                                       point
 //!
 //!  Angular dimensions:
@@ -130,19 +131,46 @@ DEFINE_STANDARD_HANDLE(AIS_Dimension, AIS_InteractiveObject)
 //! 
 //! The dimension support two local selection modes: main dimension line selection and text label
 //! selection. These modes can be used to develop interactive modification of dimension presentations.
-//! The component hilighting in these selection modes is provided by AIS_DimensionOwner class.
+//! The component highlighting in these selection modes is provided by AIS_DimensionOwner class.
 //! Please note that selection is unavailable until the presentation is computed.
 //! 
 //! The specific drawing attributes are controlled through Prs3d_DimensionAspect. The one can change
 //! color, arrows, text and arrow style and specify positioning of value label by setting corresponding
 //! values to the aspect.
 //!
+//! Such set of parameters that consists of:
+//! - flyout size and direction,
+//! - user-defined  dimension plane,
+//! - horizontal and vertical text alignment
+//! can be uniquely replaced with text position in 3d space. Therefore, there are methods to convert
+//! this set of parameters to the text position and vice versa:
+//!
+//! - If the fixed text position is defined by user, called SetTextPosition (theTextPos) method converts
+//! this 3d point to the set of parameters including adjusting of the dimension plane (this plane will be
+//! automatic plane, NOT user-defined one).
+//! If the fixed text position is set, the flag myIsFixedTextPosition is set to TRUE.
+//! ATTENSION! myIsFixedTextPosition fixes all parameters of the set from recomputing inside
+//! SetMeasureGeometry() methods. Parameters from the set can be changed only directly by user with
+//! calls of setters. In this case changing of some parameter from the set leads to disabling the of
+//! fixed text position (myIsFixedTextPosition is set to FALSE).
+//! If the fixed text position is set and geometry is changed by user (SetMeasureGeometry() method
+//! is called) and the geometry doesn't satisfy computed dimension plane, the dimension is not valid.
+//!
+//! - If the set of parameters was set by user (may be without the user-defined plane or with it),
+//! it can be converted to the text position by calling the method GetTextPosition(). In this case
+//! the text position is NOT fixed, and SetMeasureGeometry() without user-defined plane adjusts
+//! the automatic plane according input geometry (if it is possible).
+//!
+//! ATTENSION! By default after SetTextPosition() call the text label is automatically aligned.
+//! This means that if text was placed not on the extensions (between attachment points), it will
+//! centered. If you want to uncentered text use SetLayoutMode (DLM_Manual), otherwise dimension
+//! layout mode will be set as automatic and text will be aligned and centered.
 class AIS_Dimension : public AIS_InteractiveObject
 {
 protected:
 
   //! Geometry type defines type of shapes on which the dimension is to be built.
-  //! Some type of geometry allows automatical plane computing and
+  //! Some type of geometry allows automatic plane computing and
   //! can be built without user-defined plane
   //! Another types can't be built without user-defined plane.
   enum GeometryType
@@ -212,8 +240,8 @@ public:
   //! By default, if plane is not defined by user, it is computed automatically
   //! after dimension geometry is computed.
   //! If computed dimension geometry (points) can't be placed on the user-defined
-  //! plane, dimension geometry was set as unvalid (validity flag is set to false)
-  //! and dimension presentation wil not be computed.
+  //! plane, dimension geometry was set as invalid (validity flag is set to false)
+  //! and dimension presentation will not be computed.
   //! If user-defined plane allow geometry placement on it, it will be used for
   //! computing of the dimension presentation.
   //! @return dimension plane used for presentation computing.
@@ -233,6 +261,22 @@ public:
   //! computed automatically.
   Standard_EXPORT void UnsetCustomPlane() { myIsPlaneCustom = Standard_False; }
 
+  //! @return TRUE if text position is set by user with method SetTextPosition().
+  Standard_Boolean IsTextPositionCustom () const
+  {
+    return myIsTextPositionFixed;
+  }
+
+  //! Fixes the absolute text position and adjusts flyout, plane and text alignment
+  //! according to it. Updates presentation if the text position is valid.
+  //! ATTENTION! It does not change vertical text alignment.
+  //! @param theTextPos [in] the point of text position.
+  virtual void SetTextPosition (const gp_Pnt& /*theTextPos*/) { }
+
+  //! Computes absolute text position from dimension parameters
+  //! (flyout, plane and text alignment).
+  virtual const gp_Pnt GetTextPosition () const { return gp_Pnt(); }
+
 public:
 
   //! Gets the dimension aspect from AIS object drawer.
@@ -256,7 +300,7 @@ public:
   //! @return the kind of interactive.
   virtual AIS_KindOfInteractive Type() const
   {
-    return AIS_KOI_Relation;
+    return AIS_KOI_Dimension;
   }
 
   //! Returns true if the class of objects accepts the display mode theMode.
@@ -321,13 +365,24 @@ public:
   Standard_EXPORT void SetFlyout (const Standard_Real theFlyout);
 
   //! Check that the input geometry for dimension is valid and the
-  //! presentation can be succesfully computed.
+  //! presentation can be successfully computed.
   //! @return TRUE if dimension geometry is ok.
   Standard_Boolean IsValid() const
   {
     return myIsValid;
   }
 
+  //! @return layout mode - how the label will be placed
+  //! relative to the dimension line.
+  AIS_DimensionLayoutMode LayoutMode() const 
+  {
+    return myLayoutMode;
+  }
+
+  //! Sets layout mode.
+  //! @param theLayoutMode [in] the layout mode.
+  Standard_EXPORT void SetLayoutMode (const AIS_DimensionLayoutMode theLayoutMode);
+
 public:
 
   DEFINE_STANDARD_RTTI(AIS_Dimension)
@@ -426,6 +481,42 @@ protected:
                                                           gp_Circ& theCircle,
                                                           gp_Pnt& theMiddleArcPoint,
                                                           Standard_Boolean& theIsClosed);
+  //! Produce points for triangular arrow face.
+  //! @param thePeakPnt [in] the arrow peak position.
+  //! @param theDirection [in] the arrow direction.
+  //! @param thePlane [in] the face plane.
+  //! @param theArrowLength [in] the length of arrow.
+  //! @param theArrowAngle [in] the angle of arrow.
+  //! @param thePeakPnt [in] the arrow peak point.
+  //! @param theSidePnt1 [in] the first side point.
+  //! @param theSidePnt2 [in] the second side point.
+  Standard_EXPORT void PointsForArrow (const gp_Pnt& thePeakPnt,
+                                       const gp_Dir& theDirection,
+                                       const gp_Dir& thePlane,
+                                       const Standard_Real theArrowLength,
+                                       const Standard_Real theArrowAngle,
+                                       gp_Pnt& theSidePnt1,
+                                       gp_Pnt& theSidePnt2);
+
+  //! Compute point of text position for dimension parameters
+  //! for linear kinds of dimensions (length, radius, diameter).
+  Standard_EXPORT gp_Pnt GetTextPositionForLinear (const gp_Pnt& theFirstPoint,
+                                                   const gp_Pnt& theSecondPoint,
+                                                   const Standard_Boolean theIsOneSide = Standard_False) const;
+
+  //! Adjust dimension parameters for the given point of new text position
+  //! for linear kinds of dimensions (length, radius, diameter).
+  Standard_EXPORT Standard_Boolean SetTextPositionForLinear (const gp_Pnt& theFirstPoint,
+                                                             const gp_Pnt& theSecondPoint,
+                                                             const gp_Pnt& theTextPos);
+
+  //! Fits text alignment relatively to the dimension line.
+  void FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
+                                  const gp_Pnt& theSecondPoint,
+                                  const Standard_Boolean theIsOneSide,
+                                  Standard_Integer& theLabelPosition,
+                                  Standard_Boolean& theIsArrowsExternal) const;
 
 protected: //! @name Behavior to implement
 
@@ -455,22 +546,6 @@ protected: //! @name Behavior to implement
   virtual void ComputeFlyoutSelection (const Handle(SelectMgr_Selection)&,
                                        const Handle(SelectMgr_EntityOwner)&) {}
 
-  //! Produce points for triangular arrow face.
-  //! @param thePeakPnt [in] the arrow peak position.
-  //! @param theDirection [in] the arrow direction.
-  //! @param thePlane [in] the face plane.
-  //! @param theArrowLength [in] the length of arrow.
-  //! @param theArrowAngle [in] the angle of arrow.
-  //! @param thePeakPnt [in] the arrow peak point.
-  //! @param theSidePnt1 [in] the first side point.
-  //! @param theSidePnt2 [in] the second side point.
-  Standard_EXPORT void PointsForArrow (const gp_Pnt& thePeakPnt,
-                                       const gp_Dir& theDirection,
-                                       const gp_Dir& thePlane,
-                                       const Standard_Real theArrowLength,
-                                       const Standard_Real theArrowAngle,
-                                       gp_Pnt& theSidePnt1,
-                                       gp_Pnt& theSidePnt2);
 
   //! Base procedure of computing selection (based on selection geometry data).
   //! @param theSelection [in] the selection structure to will with primitives.
@@ -525,7 +600,7 @@ protected: //! @name Selection geometry
       }
     }
 
-    //! Add new curve entry and return the referenece to populate it.
+    //! Add new curve entry and return the reference to populate it.
     Curve& NewCurve()
     {
       DimensionLine.Append( new Curve );
@@ -533,7 +608,7 @@ protected: //! @name Selection geometry
       return *aLastCurve;
     }
 
-    //! Add new arrow entry and return the referenece to populate it.
+    //! Add new arrow entry and return the reference to populate it.
     Arrow& NewArrow()
     {
       Arrows.Append( new Arrow );
@@ -550,6 +625,12 @@ protected: //! @name Value properties
   Standard_Real    myCustomValue;   //!< Value of the dimension (computed or user-defined).
   Standard_Boolean myIsValueCustom; //!< Is user-defined value.
 
+protected: //! @name Fixed text position properties
+
+  AIS_DimensionLayoutMode myLayoutMode; //!< controls how label will be placed relatively to the line.
+  gp_Pnt                  myFixedTextPosition;   //!< Stores text position fixed by user.
+  Standard_Boolean        myIsTextPositionFixed; //!< Is the text label position fixed by user.
+
 protected: //! @name Units properties
 
   Standard_ExtCharacter    mySpecialSymbol;        //!< Special symbol.
index 3eb225e01f1d5303b96ae0dc075af108c8a8472c..a80a04456b7c27515e3d59dd292cbfc9e21404a3 100644 (file)
@@ -138,7 +138,8 @@ uses
     EntityOwner           from SelectMgr,
     TypeOfFacingModel    from Aspect,
     Array1OfPnt2d         from TColgp,
-    Transformation       from Geom
+    Transformation        from Geom,
+    SequenceOfShape       from TopTools
 
 is
 
@@ -2104,6 +2105,7 @@ fields
     -- InitDetected(), MoreDetected(), NextDetected(), DetectedCurrentShape(), DetectedCurrentObject().
     myZDetectionFlag:  Boolean from Standard;
     -- This variables is used by SetZDetection() and ZDetection() methods
+    myAISDetectedShapes : SequenceOfShape from TopTools;
 
     -- abd:
     myIsAutoActivateSelMode : Boolean from Standard;
index 75d82a3d7ce4dbf76cb9817f6ee54336cb869489..56e490d017bd20b48f67bb245a05379fb5a0c7ee 100644 (file)
@@ -238,15 +238,14 @@ void AIS_InteractiveContext::DisplayedObjects(AIS_ListOfInteractive& aListOfIO,
 #endif
 
     //parse all local contexts...
+#ifdef DEBUG
     Standard_Integer NbDisp;
     for(AIS_DataMapIteratorOfDataMapOfILC it1(myLocalContexts);it1.More();it1.Next()){
       const Handle(AIS_LocalContext)& LC = it1.Value();
       NbDisp =  LC->DisplayedObjects(theMap);
-#ifdef DEBUG
       cout<<"\tIn Local Context "<<it1.Key()<<" : "<<NbDisp<<endl;
-#endif
-      
     }
+#endif
     Handle(AIS_InteractiveObject) curIO;
     Handle(Standard_Transient) Tr;
       for(TColStd_MapIteratorOfMapOfTransient it2(theMap);it2.More();it2.Next()){
@@ -816,11 +815,11 @@ void AIS_InteractiveContext::Remove(const Handle(AIS_InteractiveObject)& anIObj,
   }
   else
     {
-      Standard_Boolean  WasInCtx = myLocalContexts(myCurLocalIndex)->Remove(anIObj);
+      myLocalContexts(myCurLocalIndex)->Remove(anIObj);
       AIS_DataMapIteratorOfDataMapOfILC It(myLocalContexts);
       for (;It.More() ;It.Next()){
         if(It.Value()->AcceptErase())
-          WasInCtx = It.Value()->Remove(anIObj);
+          It.Value()->Remove(anIObj);
         
       }
       //      if(!WasInCtx)
@@ -2417,7 +2416,10 @@ void AIS_InteractiveContext::ClearGlobal(const Handle(AIS_InteractiveObject)& an
   {
     Handle(AIS_InteractiveObject) anObj = DetectedCurrentObject();
     if( !anObj.IsNull() && anObj != anIObj )
+    {
       myAISDetectedSeq.Remove( i );
+      myAISDetectedShapes.Remove(i);
+    }
   }
 
   if(myLastinMain == anIObj)
index b5094e517174f0576c12038a60e421b0142f7cd2..01c19aed9d81496fd9d44bd643ed60c761966fd1 100644 (file)
@@ -51,6 +51,7 @@
 #include <TColStd_ListIteratorOfListOfInteger.hxx>
 #include <SelectMgr_Selection.hxx>
 #include <SelectBasics_SensitiveEntity.hxx>
+#include <StdSelect_BRepOwner.hxx>
 
 #ifdef IMP150501
 #include <Visual3d_TransientManager.hxx>
@@ -146,6 +147,7 @@ AIS_StatusOfDetection AIS_InteractiveContext::MoveTo(const Standard_Integer XPix
     //Nullify class members storing information about detected AIS objects.
   myAISCurDetected = 0;
   myAISDetectedSeq.Clear();
+  myAISDetectedShapes.Clear();
 #endif
 
   // OCC11904 - local variables made non-static - it looks and works better like this
@@ -183,7 +185,16 @@ AIS_StatusOfDetection AIS_InteractiveContext::MoveTo(const Standard_Integer XPix
         Handle(AIS_InteractiveObject) anObj = 
                Handle(AIS_InteractiveObject)::DownCast(anEntityOwner->Selectable());
         if(!Handle(AIS_Shape)::DownCast(anObj).IsNull())
+        {
           myAISDetectedSeq.Append(anObj);
+          
+          // Memorize detected shape.
+          TopoDS_Shape detectedShape;
+          Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(anEntityOwner);
+          if (!aBRepOwner.IsNull() && aBRepOwner->HasShape())
+            detectedShape = aBRepOwner->Shape();
+          myAISDetectedShapes.Append(detectedShape);
+        }
       }
   }
 #endif
@@ -1418,7 +1429,11 @@ const TopoDS_Shape& AIS_InteractiveContext::DetectedCurrentShape() const
   static TopoDS_Shape bidsh;
   if(myAISCurDetected > 0 &&
      myAISCurDetected <= myAISDetectedSeq.Length())
-    return Handle(AIS_Shape)::DownCast(myAISDetectedSeq(myAISCurDetected))->Shape();
+  {
+    if (myAISDetectedShapes(myAISCurDetected).IsNull())
+      return Handle(AIS_Shape)::DownCast(myAISDetectedSeq(myAISCurDetected))->Shape();
+    return myAISDetectedShapes(myAISCurDetected);
+  }
   return bidsh;
 }
 
index 86b0ff47b859ff60c86b6f04f6fce97c79a84e67..b9226520fc563e5c8432e94905513184aea22301 100755 (executable)
@@ -708,3 +708,33 @@ Standard_Boolean AIS_LengthDimension::InitOneShapePoints (const TopoDS_Shape& th
 
   return IsValidPoints (myFirstPoint, mySecondPoint);
 }
+
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+const gp_Pnt AIS_LengthDimension::GetTextPosition () const
+{
+  if (myIsTextPositionFixed)
+  {
+    return myFixedTextPosition;
+  }
+  
+  // Counts text position according to the dimension parameters
+  return GetTextPositionForLinear (myFirstPoint, mySecondPoint);
+}
+
+//=======================================================================
+//function : SetTextPosition
+//purpose  : 
+//=======================================================================
+void AIS_LengthDimension::SetTextPosition (const gp_Pnt& theTextPos)
+{
+  if (!myIsValid)
+  {
+    return;
+  }
+
+  SetTextPositionForLinear (myFirstPoint, mySecondPoint, theTextPos);
+  SetToUpdate();
+}
index cd23349ab08d4422241d1a71ffce20864e952e3b..41b519e3ea7e9e33c308347ed20bb23f4e4ad9f3 100755 (executable)
@@ -188,7 +188,7 @@ public:
 
   //! @return the display units string.
   Standard_EXPORT virtual const TCollection_AsciiString& GetDisplayUnits () const;
-  
+
   //! @return the model units string.
   Standard_EXPORT virtual const TCollection_AsciiString& GetModelUnits () const;
 
@@ -196,6 +196,10 @@ public:
 
   Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& theUnits);
 
+  Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos);
+
+  Standard_EXPORT virtual const gp_Pnt GetTextPosition () const;
+
 public:
 
   DEFINE_STANDARD_RTTI(AIS_LengthDimension)
index 11341c07c0ed05bd13e1b824cec2d0cc3e8d65bd..15557c6c4dd2c8ba3052dc7c4993920c4409f786 100644 (file)
@@ -77,7 +77,8 @@ uses
     LocalStatus               from AIS, 
     StatusOfPick              from AIS,
     StatusOfDetection         from AIS,
-    SequenceOfInteractive     from AIS
+    SequenceOfInteractive     from AIS,
+    SequenceOfShape           from TopTools
 
 is
 
@@ -629,6 +630,7 @@ fields
     myAISCurDetected : Integer from Standard;
     -- This variables is used by following functions:
     -- InitDetected(), MoreDetected(), NextDetected(), DetectedCurrentShape(), DetectedCurrentObject().
+    myAISDetectedShapes : SequenceOfShape from TopTools;
     
 friends 
 
index 631edf9b25abcd15e6b07023e0a2b189419451dd..7707e1b3cfbeae5ea51c57e7042612a59f1a500e 100644 (file)
@@ -445,7 +445,6 @@ Standard_Boolean AIS_LocalContext::Remove(const Handle(AIS_InteractiveObject)& a
   const Handle(AIS_LocalStatus)& Att = myActiveObjects(aSelectable);
   
   TColStd_ListIteratorOfListOfInteger It;
-  Standard_Boolean jobdone(Standard_False);
   // it is checked which were the temporary attributes 
   // and they are set to 0
 
@@ -468,7 +467,6 @@ Standard_Boolean AIS_LocalContext::Remove(const Handle(AIS_InteractiveObject)& a
       if(myMainPM->IsDisplayed(aSelectable,Att->HilightMode()))
        myMainPM->Erase(aSelectable,Att->HilightMode());
       //       myMainPM->Clear(aSelectable,Att->HilightMode());
-      jobdone = Standard_True;
     }
   // if below intensity
   else
@@ -505,7 +503,10 @@ Standard_Boolean AIS_LocalContext::Remove(const Handle(AIS_InteractiveObject)& a
   {
     Handle(AIS_InteractiveObject) anObj = DetectedCurrentObject();
     if( !anObj.IsNull() && anObj != aSelectable )
+    {
       myAISDetectedSeq.Remove( i );
+      myAISDetectedShapes.Remove( i );
+    }
   }
 
   Standard_Integer aHM = aSelectable->HasHilightMode() ? aSelectable->HilightMode() : 0;
index 6ba62da5ffcb3213c6190c899fea626320dbbe15..2bac66b8632fc44fb0b94ad6a1d651b3b24caab6 100644 (file)
@@ -127,6 +127,7 @@ AIS_StatusOfDetection AIS_LocalContext::MoveTo(const Standard_Integer Xpix,
     //Nullify class members storing information about detected AIS objects.
     myAISCurDetected = 0;
     myAISDetectedSeq.Clear();
+    myAISDetectedShapes.Clear();
 #endif
     myCurDetected = 0;
     myDetectedSeq.Clear();
@@ -142,8 +143,20 @@ AIS_StatusOfDetection AIS_LocalContext::MoveTo(const Standard_Integer Xpix,
          myDetectedSeq.Append(i_detect); // normallly they are already arranged in correct order...
 #ifdef IMP160701
         Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast(EO->Selectable());
-        if(!Handle(AIS_Shape)::DownCast(anObj).IsNull())
+        Handle(AIS_Shape) aisShape = Handle(AIS_Shape)::DownCast(anObj);
+        if(!aisShape.IsNull())
+        {
           myAISDetectedSeq.Append(anObj);
+          
+          // Memorize detected shape.
+          TopoDS_Shape detectedShape;
+          Handle(StdSelect_BRepOwner) BO = Handle(StdSelect_BRepOwner)::DownCast(EO);
+          if (!BO.IsNull() && BO->HasShape())
+            detectedShape = BO->Shape();
+          else if (!aisShape->Shape().IsNull())
+            detectedShape = aisShape->Shape();
+          myAISDetectedShapes.Append(detectedShape);
+        }
 #endif
       }
     }
@@ -1017,7 +1030,9 @@ void AIS_LocalContext::AddOrRemoveSelected(const Handle(AIS_InteractiveObject)&
       }
     }
     if(EO.IsNull()) 
+    {
       EO = new SelectMgr_EntityOwner(anIObj);
+    }
 #ifndef OCC138
     EO->State(1);
 #endif
@@ -1596,7 +1611,11 @@ const TopoDS_Shape& AIS_LocalContext::DetectedCurrentShape() const
 {
   static TopoDS_Shape bidsh;
   if (MoreDetected())
-    return Handle(AIS_Shape)::DownCast(myAISDetectedSeq(myAISCurDetected))->Shape();
+  {
+    if (myAISDetectedShapes(myAISCurDetected).IsNull())
+      return Handle(AIS_Shape)::DownCast(myAISDetectedSeq(myAISCurDetected))->Shape();
+    return myAISDetectedShapes(myAISCurDetected);
+  }
   return bidsh;
 }
 
index ab737d099dea289d8026a103bea5db4a98c96652..ac0d07e07bd685856bf7e2b61903c0b8dd9b00eb 100644 (file)
@@ -262,3 +262,33 @@ Standard_Boolean AIS_RadiusDimension::IsValidAnchor (const gp_Circ& theCircle,
   return Abs (anAnchorDist - aRadius) > Precision::Confusion()
       && aCirclePlane.Contains (theAnchor, Precision::Confusion());
 }
+
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+const gp_Pnt AIS_RadiusDimension::GetTextPosition () const
+{
+  if (myIsTextPositionFixed)
+  {
+    return myFixedTextPosition;
+  }
+  
+  // Counts text position according to the dimension parameters
+  return GetTextPositionForLinear (myAnchorPoint, myCircle.Location(), Standard_True);
+}
+
+//=======================================================================
+//function : GetTextPosition
+//purpose  : 
+//=======================================================================
+void AIS_RadiusDimension::SetTextPosition (const gp_Pnt& theTextPos)
+{
+  if (!myIsValid)
+  {
+    return;
+  }
+
+  SetTextPositionForLinear (myAnchorPoint, myCircle.Location(), theTextPos);
+  SetToUpdate();
+}
index f501b9bd4eb16d1a76fe90cd8ca38ef71bb6d72e..18a40ca826b32f4d924c17ceef3126cf87868979 100644 (file)
@@ -50,7 +50,7 @@ public:
   //! orientation by location of the first point on that circle.
   //! @param theCircle [in] the circle to measure.
   //! @param theAnchorPoint [in] the point to define the position
-  //!        of the dimension attachement on the circle.
+  //!        of the dimension attachment on the circle.
   Standard_EXPORT AIS_RadiusDimension (const gp_Circ& theCircle,
                                        const gp_Pnt& theAnchorPoint);
 
@@ -88,7 +88,7 @@ public:
 
   //! Measure radius of the circle and orient the dimension so
   //! the dimension lines attaches to anchor point on the circle.
-  //! The dimension will become invalid if the radiuss of the circle
+  //! The dimension will become invalid if the radius of the circle
   //! is less than Precision::Confusion().
   //! @param theCircle [in] the circle to measure.
   //! @param theAnchorPoint [in] the point to attach the dimension lines.
@@ -111,6 +111,10 @@ public:
 
   Standard_EXPORT virtual void SetModelUnits (const TCollection_AsciiString& theUnits);
 
+  Standard_EXPORT virtual void SetTextPosition (const gp_Pnt& theTextPos);
+
+  Standard_EXPORT virtual const gp_Pnt GetTextPosition () const;
+
 public:
 
   DEFINE_STANDARD_RTTI (AIS_RadiusDimension)
index 09521e16231c263fc9725417ce8eb2fb0a09d369..bcbf06499a439f056774492f323693ce15c30a45 100644 (file)
@@ -464,7 +464,7 @@ void AIS_Shape::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
   }
 
   // insert the drawer in the BrepOwners for hilight...
-  StdSelect::SetDrawerForBRepOwner(aSelection,myDrawer);
+  // StdSelect::SetDrawerForBRepOwner(aSelection,myDrawer);
 }
 
 Quantity_NameOfColor AIS_Shape::Color() const {
index 9aebd3427b7505879bcd71e4aaab7b78024fafeb..6d1f20f8d602b8b3c41febfea41d4cea37bac82b 100644 (file)
@@ -5,8 +5,8 @@
 //
 // This file is part of Open CASCADE Technology software library.
 //
-// This library is free software; you can redistribute it and / or modify it
-// under the terms of the GNU Lesser General Public version 2.1 as published
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
 // by the Free Software Foundation, with special exception defined in the file
 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 // distribution for complete text of the license and disclaimer of any warranty.
@@ -234,11 +234,20 @@ static void UpdateCurves(BRep_ListOfCurveRepresentation& lcr,
   Handle(BRep_CurveRepresentation) cr;
   Handle(BRep_GCurve) GC;
   Standard_Real f = 0.,l = 0.;
+  Standard_Boolean rangeFound = Standard_False;
 
   while (itcr.More()) {
     GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
     if ( !GC.IsNull() ) {
-      GC->Range(f,l);
+      if (GC->IsCurve3D()) {
+        GC->Range(f,l);
+        Standard_Boolean undefined = (Precision::IsPositiveInfinite(l) ||
+                                      Precision::IsNegativeInfinite(f));
+          
+        if (!undefined) {
+          rangeFound = Standard_True;
+        }
+      }
       Standard_Boolean iscos = GC->IsCurveOnSurface(S,L);
       if (iscos) break;
     }
@@ -256,7 +265,7 @@ static void UpdateCurves(BRep_ListOfCurveRepresentation& lcr,
     Handle(BRep_CurveOnClosedSurface) COS =
       new BRep_CurveOnClosedSurface(C1,C2,S,L,GeomAbs_C0);
     // test if there is already a range
-    if (!GC.IsNull()) {
+    if (rangeFound) {
       COS->SetRange(f,l);
     }
     lcr.Append(COS);
@@ -281,11 +290,20 @@ static void UpdateCurves(BRep_ListOfCurveRepresentation& lcr,
   Handle(BRep_CurveRepresentation) cr;
   Handle(BRep_GCurve) GC;
   Standard_Real f = 0.,l = 0.;
+  Standard_Boolean rangeFound = Standard_False;
 
   while (itcr.More()) {
     GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
     if ( !GC.IsNull() ) {
-      GC->Range(f,l);
+      if (GC->IsCurve3D()) {
+        GC->Range(f,l);
+        Standard_Boolean undefined = (Precision::IsPositiveInfinite(l) ||
+                                      Precision::IsNegativeInfinite(f));
+          
+        if (!undefined) {
+          rangeFound = Standard_True;
+        }
+      }
       Standard_Boolean iscos = GC->IsCurveOnSurface(S,L);
       if (iscos) break;
     }
@@ -303,7 +321,7 @@ static void UpdateCurves(BRep_ListOfCurveRepresentation& lcr,
     Handle(BRep_CurveOnClosedSurface) COS =
       new BRep_CurveOnClosedSurface(C1,C2,S,L,GeomAbs_C0);
     // test if there is already a range
-    if (!GC.IsNull()) {
+    if (rangeFound) {
       COS->SetRange(f,l);
     }
     COS->SetUVPoints2(Pf,Pl);
@@ -546,7 +564,6 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge& E,
   const TopLoc_Location l = L.Predivided(E.Location());
 
   UpdateCurves(TE->ChangeCurves(),C,l);
-  if (!C.IsNull()) TE->Closed(C->IsClosed());
 
   TE->UpdateTolerance(Tol);
   TE->Modified(Standard_True);
@@ -613,8 +630,6 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge& E,
   const TopLoc_Location l = L.Predivided(E.Location());
 
   UpdateCurves(TE->ChangeCurves(),C1,C2,S,l);
-  if (!C1.IsNull() && !C2.IsNull()) 
-    TE->Closed(C1->IsClosed() && C2->IsClosed());
 
   TE->UpdateTolerance(Tol);
   TE->Modified(Standard_True);
@@ -639,9 +654,7 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge& E,
   const TopLoc_Location l = L.Predivided(E.Location());
 
   UpdateCurves(TE->ChangeCurves(),C1,C2,S,l,Pf,Pl);
-  if (!C1.IsNull() && !C2.IsNull()) 
-    TE->Closed(C1->IsClosed() && C2->IsClosed());
-  
+
   TE->UpdateTolerance(Tol);
   TE->Modified(Standard_True);
 }
@@ -705,14 +718,14 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge& E,
   while (itcr.More())
   {
     if (itcr.Value()->IsPolygonOnTriangulation(T,l))
-       {
+    {
       // cr is used to keep a reference on the curve representation
       // this avoid deleting it as its content may be referenced by T
       cr = itcr.Value();
       lcr.Remove(itcr);
       isModified = Standard_True;
       break;
-       }
+    }
     itcr.Next();
   }
 
@@ -996,23 +1009,8 @@ void  BRep_Builder::Range(const TopoDS_Edge&  E,
   
   while (itcr.More()) {
     GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
-    if (!GC.IsNull()) {
-      if (!Only3d || GC->IsCurve3D())
-       GC->SetRange(First,Last);
-      if (GC->IsCurve3D()) {
-        // Set the closedness flag to the correct value.
-        Handle(Geom_Curve) C = GC->Curve3D();
-        
-        //fixing a bug PRO18577 to avoid infinite values of First and Last 
-        if ( !C.IsNull() && 
-            !Precision::IsNegativeInfinite(First) && 
-            !Precision::IsPositiveInfinite(Last) )   {
-          Standard_Boolean closed = 
-            C->Value(First).IsEqual(C->Value(Last),BRep_Tool::Tolerance(E));
-          TE->Closed(closed);
-        }
-      }
-    }
+    if (!GC.IsNull() && (!Only3d || GC->IsCurve3D()))
+      GC->SetRange(First,Last);
     itcr.Next();
   }
   
@@ -1040,20 +1038,10 @@ void  BRep_Builder::Range(const TopoDS_Edge& E,
 
   while (itcr.More()) {
     GC = Handle(BRep_GCurve)::DownCast(itcr.Value());
-    if (!GC.IsNull()) {
-      if (GC->IsCurveOnSurface(S,l)) {
-        GC->SetRange(First,Last);
-
-        // Set the closedness flag to the correct value.
-        Handle(Geom2d_Curve) PC = GC->PCurve();
-        gp_Pnt2d P1 = PC->Value(First);
-        gp_Pnt2d P2 = PC->Value(Last);
-        gp_Pnt   PP1 = S->Value(P1.X(),P1.Y());
-        gp_Pnt   PP2 = S->Value(P2.X(),P2.Y());
-        Standard_Boolean closed = PP1.IsEqual(PP2,BRep_Tool::Tolerance(E));
-        TE->Closed(closed);
-        break;
-      }
+    if (!GC.IsNull() && GC->IsCurveOnSurface(S,l))
+    {
+      GC->SetRange(First,Last);
+      break;
     }
     itcr.Next();
   }
@@ -1076,7 +1064,7 @@ void  BRep_Builder::Transfert(const TopoDS_Edge& Ein,
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &Ein.TShape());
 
   const Standard_Real tol = TE->Tolerance();
-  
+
   BRep_ListOfCurveRepresentation& lcr = TE->ChangeCurves();
   BRep_ListIteratorOfListOfCurveRepresentation itcr(lcr);
   
index 018352393387571ec4ce28d6aa3623c7a200d299..ad763eb01a319d0342cb5a8501e9ca9ec5c24f15 100644 (file)
@@ -4,8 +4,8 @@
 //
 // This file is part of Open CASCADE Technology software library.
 //
-// This library is free software; you can redistribute it and / or modify it
-// under the terms of the GNU Lesser General Public version 2.1 as published
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
 // by the Free Software Foundation, with special exception defined in the file
 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 // distribution for complete text of the license and disclaimer of any warranty.
 #ifndef _BRepBuilderAPI_VertexInspector_Header
 #define _BRepBuilderAPI_VertexInspector_Header
 
-#ifndef _TColStd_ListOfInteger_HeaderFile
 #include <TColStd_ListOfInteger.hxx>
-#endif
-#ifndef NCollection_Vector_HeaderFile
 #include <NCollection_Vector.hxx>
-#endif
-#ifndef _gp_XY_HeaderFile
 #include <gp_XY.hxx>
-#endif
-#ifndef _gp_XYZ_HeaderFile
 #include <gp_XYZ.hxx>
-#endif
-
-#ifndef NCollection_CellFilter_HeaderFile
 #include <NCollection_CellFilter.hxx>
-#endif
 
 typedef NCollection_Vector<gp_XYZ> VectorOfPoint;
 
@@ -48,8 +37,7 @@ class BRepBuilderAPI_VertexInspector : public NCollection_CellFilter_InspectorXY
 public:
   typedef Standard_Integer Target;
   //! Constructor; remembers the tolerance
-  BRepBuilderAPI_VertexInspector (const Standard_Real theTol)
-                                  : myTol(theTol*theTol)
+  BRepBuilderAPI_VertexInspector (const Standard_Real theTol):myTol(theTol*theTol)
   {}
 
   //! Keep the points used for comparison
@@ -77,7 +65,7 @@ public:
   }
 
   //! Implementation of inspection method
-  NCollection_CellFilter_Action Inspect (const Standard_Integer theTarget); 
+  Standard_EXPORT NCollection_CellFilter_Action Inspect (const Standard_Integer theTarget); 
 
 private:
   Standard_Real myTol;
index 6c766f460fe64590666fba1cccf0edaa4cc8a6a1..092db05eeb61d43ac8b0742d53df489d9f1b287f 100644 (file)
@@ -5,8 +5,8 @@
 --
 -- This file is part of Open CASCADE Technology software library.
 --
--- This library is free software; you can redistribute it and / or modify it
--- under the terms of the GNU Lesser General Public version 2.1 as published
+-- This library is free software; you can redistribute it and/or modify it under
+-- the terms of the GNU Lesser General Public License version 2.1 as published
 -- by the Free Software Foundation, with special exception defined in the file
 -- OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 -- distribution for complete text of the license and disclaimer of any warranty.
@@ -18,17 +18,22 @@ class OffsetWire from BRepFill
 
        ---Purpose: Constructs a Offset Wire to a spine (wire or face) 
        --          on the left of spine.
-
+       --          The Wire or the Face must be planar.
 uses
 
     Face        from TopoDS,
     Shape       from TopoDS,
     JoinType    from GeomAbs,
     ListOfShape from TopTools,
+    SequenceOfShape from TopTools,
+    SequenceOfPnt from TColgp,
     DataMapOfShapeShape               from TopTools,
     IndexedDataMapOfOrientedShapeListOfShape from BRepFill,  
+    DataMapOfOrientedShapeListOfShape from BRepFill,  
     BisectingLocus                    from BRepMAT2d, 
-    LinkTopoBilo                      from BRepMAT2d
+    LinkTopoBilo                      from BRepMAT2d,
+    Bisec from Bisector,
+    TrimEdgeTool from BRepFill
     
 raises
     ConstructionError from Standard,
@@ -39,12 +44,14 @@ is
     Create returns OffsetWire from BRepFill;
 
     Create ( Spine : Face     from TopoDS; 
-            Join  : JoinType from GeomAbs  =  GeomAbs_Arc)
+            Join  : JoinType from GeomAbs  =  GeomAbs_Arc;
+            IsOpenResult : Boolean from Standard = Standard_False)
     returns OffsetWire from BRepFill;
 
     Init ( me    : in out;
           Spine : Face     from TopoDS; 
-          Join  : JoinType from GeomAbs  =  GeomAbs_Arc)
+          Join  : JoinType from GeomAbs  =  GeomAbs_Arc;
+          IsOpenResult : Boolean from Standard = Standard_False)
        ---Purpose: Initialize the evaluation of Offseting.
     raises
        ConstructionError from Standard
@@ -114,6 +121,16 @@ is
        ---Purpose: Add the OffsetWire <Other> to <me> and update <myMap>
     is static private;
     
+    UpdateDetromp (me; Detromp : in out DataMapOfOrientedShapeListOfShape from BRepFill;
+                      Shape1, Shape2 : Shape from TopoDS;
+                      Vertices : SequenceOfShape from TopTools;
+                      Params   : SequenceOfPnt   from TColgp;
+                      Bisec    : Bisec from Bisector;
+                      SOnE     : Boolean from Standard;
+                      EOnE     : Boolean from Standard;
+                      Trim     : TrimEdgeTool from BRepFill)
+    is static private;
+    
     MakeWires (me : in  out)
        ---Purpose: Constructs the wires with the trimmed offset edges.
     is static private;
@@ -127,6 +144,7 @@ fields
     mySpine     : Face      from TopoDS;
     myWorkSpine : Face      from TopoDS;
     myOffset    : Real      from Standard; -- >0 ;
+    myIsOpenResult : Boolean from Standard;
     myShape     : Shape     from TopoDS;
     myIsDone    : Boolean   from Standard;
     myJoinType  : JoinType  from GeomAbs;          
index ee07c071a41da03e7e3166180beed7206c5b2305..aed31f7483563cb06c59bc90173781978ab4abbf 100644 (file)
@@ -5,8 +5,8 @@
 //
 // This file is part of Open CASCADE Technology software library.
 //
-// This library is free software; you can redistribute it and / or modify it
-// under the terms of the GNU Lesser General Public version 2.1 as published
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
 // by the Free Software Foundation, with special exception defined in the file
 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 // distribution for complete text of the license and disclaimer of any warranty.
@@ -55,6 +55,7 @@
 #include <GeomAPI.hxx>
 #include <Geom_TrimmedCurve.hxx>
 #include <Geom_Circle.hxx>
+#include <Geom_Line.hxx>
 #include <Geom_OffsetCurve.hxx>
 #include <MAT_Arc.hxx>
 #include <MAT_Node.hxx>
 #include <DrawTrSurf.hxx>
 #include <DrawTrSurf_Curve2d.hxx>
 #include <DBRep.hxx>
-#endif
-
-#ifdef DEB
 static Standard_Boolean AffichGeom  = Standard_False;
 static Standard_Boolean Affich2d    = Standard_False;
 static Standard_Boolean AffichEdge  = Standard_False;
@@ -115,10 +113,6 @@ static Standard_Integer NbTRIMEDGES = 0;
 static Standard_Integer NbOFFSET    = 0;
 static Standard_Integer NbEDGES     = 0;
 static Standard_Integer NbBISSEC    = 0;
-#ifndef WNT
-static char tname[100];
-static Standard_CString name = tname ;
-#endif
 #endif
 
 //  Modified by Sergey KHROMOV - Thu Nov 16 17:24:39 2000 Begin
@@ -174,15 +168,6 @@ static void EdgeVertices (const TopoDS_Edge&   E,
   }
 }
                                      
-static void UpdateDetromp (TopTools_ListOfShape&           Detromp1, 
-                          TopTools_ListOfShape&           Detromp2, 
-                          const TopTools_SequenceOfShape& Vertices, 
-                          const TColgp_SequenceOfPnt&     Params, 
-                          const Bisector_Bisec&           Bisec,
-                          const Standard_Boolean          SOnE,
-                          const Standard_Boolean          EOnE,
-                          const BRepFill_TrimEdgeTool&    Trim);
-
 static Standard_Boolean VertexFromNode
 (const Handle(MAT_Node)&      aNode, 
  const Standard_Real          Offset,
@@ -196,10 +181,11 @@ static void StoreInMap (const TopoDS_Shape& V1,
 
 static void TrimEdge (const TopoDS_Edge&              CurrentEdge,
                      const TopTools_ListOfShape&     D,
-                           TopTools_SequenceOfShape& Sv,  
-                           TColStd_SequenceOfReal&   MapverPar,
-                           TopTools_SequenceOfShape& S,
-                           TopTools_IndexedDataMapOfShapeShape& MapVV);
+                      TopTools_SequenceOfShape& Sv,  
+                      TColStd_SequenceOfReal&   MapverPar,
+                      TopTools_SequenceOfShape& S,
+                      TopTools_IndexedDataMapOfShapeShape& MapVV,
+                      const Standard_Integer IndOfE);
 
 static Standard_Boolean DoubleOrNotInside (const TopTools_ListOfShape& EC,
                                           const TopoDS_Vertex&        V);
@@ -220,7 +206,9 @@ static void MakeOffset
  const TopoDS_Face&                          F,
  const Standard_Real                         Offset, 
  BRepFill_IndexedDataMapOfOrientedShapeListOfShape& Map,
- const Handle(Geom_Plane)&                   RefPlane);
+ const Handle(Geom_Plane)&                   RefPlane,
+ const Standard_Boolean                      IsOpenResult,
+ const TopoDS_Vertex *                       Ends);
 
 
 
@@ -265,9 +253,6 @@ static Standard_Boolean KPartCircle
     E = TopoDS::Edge(exp.Current());
     if (NbEdges > 1) return Standard_False;
   }
-  TopoDS_Vertex V1,V2;
-  TopExp::Vertices(E,V1,V2);
-  if (!V1.IsSame(V2)) return Standard_False;
 
   Standard_Real      f,l;
   TopLoc_Location    L;
@@ -278,15 +263,43 @@ static Standard_Boolean KPartCircle
     C = Ct->BasisCurve();
   }
 
-  if (!C->IsKind(STANDARD_TYPE(Geom_Circle))) return Standard_False;
-  Handle(Geom_Circle) CE = Handle(Geom_Circle)::DownCast(C);
-  Standard_Real anOffset = myOffset;
-  if (E.Orientation() == TopAbs_REVERSED) anOffset *= -1;
-  
-  if (anOffset < 0. || Abs(anOffset) < CE->Radius()) {
-    Handle(Geom_Circle) OC = new Geom_Circle (CE->Position(),CE->Radius() - anOffset);
-    myShape = BRepLib_MakeEdge(OC,f,l);
-
+  TopoDS_Vertex V1,V2;
+  TopExp::Vertices(E,V1,V2);
+  if (!V1.IsSame(V2) || //open result or closed circle
+      C->IsKind(STANDARD_TYPE(Geom_Circle))) 
+  {
+    Standard_Real anOffset = myOffset;
+    
+    Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(E, mySpine, f, l);
+    Handle(Geom2dAdaptor_HCurve) AHC = new Geom2dAdaptor_HCurve(aPCurve, f, l);
+    Handle(Geom2d_Curve) OC;
+    if (AHC->GetType() == GeomAbs_Line)
+    {
+      if (E.Orientation() == TopAbs_REVERSED)
+        anOffset *= -1;
+      Adaptor3d_OffsetCurve Off(AHC,anOffset);
+      OC = new Geom2d_Line(Off.Line());
+    }
+    else if (AHC->GetType() == GeomAbs_Circle)
+    {
+      if (E.Orientation() == TopAbs_FORWARD)
+        anOffset *= -1;
+      gp_Circ2d theCirc = AHC->Circle();
+      if (anOffset < 0. || Abs(anOffset) < theCirc.Radius())
+        OC = new Geom2d_Circle (theCirc.Position(), theCirc.Radius() - anOffset);
+    }
+    else
+    {
+      if (E.Orientation() == TopAbs_FORWARD)
+        anOffset *= -1;
+      Handle(Geom2d_TrimmedCurve) G2dT = new Geom2d_TrimmedCurve(aPCurve, f, l);
+      OC = new Geom2d_OffsetCurve( G2dT, anOffset);
+    }
+    Handle(Geom_Surface) aSurf = BRep_Tool::Surface(mySpine);
+    Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurf);
+    myShape = BRepLib_MakeEdge(OC, aPlane, f, l);
+    BRepLib::BuildCurve3d(TopoDS::Edge(myShape));
+    
     myShape.Orientation(E.Orientation());
     myShape.Location(L);
     if (Alt != 0.) {
@@ -298,13 +311,19 @@ static Standard_Boolean KPartCircle
       T.SetTranslation(Trans);
       myShape.Move(TopLoc_Location(T));
     }
-    
+      
     TopTools_ListOfShape LL;
     LL.Append(myShape);
     myMap.Add(E,LL);
+    
+    TopoDS_Edge myEdge = TopoDS::Edge(myShape);
+    myShape = BRepLib_MakeWire(myEdge);
+    
+    myIsDone = Standard_True;
+    return Standard_True;
   }
-  myIsDone = Standard_True;
-  return Standard_True;
+
+  return Standard_False;
 }
 
 //=======================================================================
@@ -313,7 +332,8 @@ static Standard_Boolean KPartCircle
 //=======================================================================
 
 BRepFill_OffsetWire::BRepFill_OffsetWire() 
-:myIsDone(Standard_False)
+  : myIsOpenResult(Standard_False),
+    myIsDone(Standard_False)
 {
 }
 
@@ -324,9 +344,10 @@ BRepFill_OffsetWire::BRepFill_OffsetWire()
 //=======================================================================
 
 BRepFill_OffsetWire::BRepFill_OffsetWire(const TopoDS_Face&     Spine,
-                                        const GeomAbs_JoinType Join )
+                                        const GeomAbs_JoinType Join,
+                                         const Standard_Boolean IsOpenResult)
 {
-  Init(Spine,Join);
+  Init(Spine,Join,IsOpenResult);
 }
 
 //=======================================================================
@@ -335,16 +356,15 @@ BRepFill_OffsetWire::BRepFill_OffsetWire(const TopoDS_Face&     Spine,
 //=======================================================================
 
 void BRepFill_OffsetWire::Init(const TopoDS_Face&     Spine,
-                              const GeomAbs_JoinType Join )
+                              const GeomAbs_JoinType Join,
+                               const Standard_Boolean IsOpenResult)
 {
-  Standard_NotImplemented_Raise_if(Join > GeomAbs_Arc,
-                                  "Only GeomAbs_Arc is implemented");
-
   myIsDone   = Standard_False;
   TopoDS_Shape aLocalShape = Spine.Oriented(TopAbs_FORWARD);
   mySpine    = TopoDS::Face(aLocalShape);
 //  mySpine    = TopoDS::Face(Spine.Oriented(TopAbs_FORWARD));
   myJoinType = Join;
+  myIsOpenResult = IsOpenResult;
 
   CheckFace(mySpine);
   
@@ -379,8 +399,8 @@ void BRepFill_OffsetWire::Init(const TopoDS_Face&     Spine,
 //   static BRepMAT2d_Explorer Exp;
 //  Modified by Sergey KHROMOV - Tue Nov 26 17:39:03 2002 End
   Exp.Perform(myWorkSpine);
-  myBilo.Compute(Exp,1,MAT_Left);
-  myLink.Perform(Exp,myBilo);
+  myBilo.Compute(Exp, 1 ,MAT_Left, myJoinType, myIsOpenResult);
+  myLink.Perform(Exp, myBilo);
 }
 
 
@@ -500,7 +520,7 @@ void BRepFill_OffsetWire::Perform (const Standard_Real Offset,
   {
     OCC_CATCH_SIGNALS
       myCallGen = Standard_False;
-    if (KPartCircle(mySpine,Offset,Alt,myShape,myMap,myIsDone)) return;
+    if (KPartCircle(myWorkSpine,Offset,Alt,myShape,myMap,myIsDone)) return;
 
     TopoDS_Face oldWorkSpain = myWorkSpine;
 
@@ -602,14 +622,12 @@ void BRepFill_OffsetWire::Perform (const Standard_Real Offset,
       
       if(aSubst.IsCopied(myWorkSpine)) {
         myWorkSpine = TopoDS::Face(aSubst.Copy(myWorkSpine).First());
-        //sprintf(name,"WS1");
-        //DBRep::Set(name,myWorkSpine);
 
         BRepMAT2d_Explorer newExp;
         newExp.Perform(myWorkSpine);
         BRepMAT2d_BisectingLocus newBilo;
         BRepMAT2d_LinkTopoBilo newLink;
-        newBilo.Compute(newExp,1,MAT_Left);
+        newBilo.Compute(newExp, 1, MAT_Left, myJoinType, myIsOpenResult);
 
         if(!newBilo.IsDone())
         {
@@ -635,24 +653,29 @@ void BRepFill_OffsetWire::Perform (const Standard_Real Offset,
   {
     myShape.Nullify();
     myIsDone = Standard_False;
+#ifdef BREPFILL_DEB
     cout<<"An exception was caught in BRepFill_OffsetWire::Perform : ";
     Standard_Failure::Caught()->Print(cout);
     cout<<endl;
+#endif
 
     return;
   }
 
   //  Modified by skv - Fri Jul  8 11:21:38 2005 OCC9145 End
   //  Modified by Sergey KHROMOV - Thu Mar 14 10:48:15 2002 Begin
-  TopExp_Explorer anExp(myShape, TopAbs_WIRE);
-
-  for (; anExp.More(); anExp.Next()) {
-    const TopoDS_Shape &aWire = anExp.Current();
-
-    if (!aWire.Closed()) {
-      myShape.Nullify();
-      myIsDone = Standard_False;
-      Standard_ConstructionError::Raise("Offset wire is not closed.");
+  if (!myIsOpenResult)
+  {
+    TopExp_Explorer anExp(myShape, TopAbs_WIRE);
+    
+    for (; anExp.More(); anExp.Next()) {
+      const TopoDS_Shape &aWire = anExp.Current();
+      
+      if (!aWire.Closed()) {
+        myShape.Nullify();
+        myIsDone = Standard_False;
+        Standard_ConstructionError::Raise("Offset wire is not closed.");
+      }
     }
   }
   //  Modified by Sergey KHROMOV - Thu Mar 14 10:48:16 2002 End
@@ -706,9 +729,6 @@ void BRepFill_OffsetWire::PerformWithBiLo
  const GeomAbs_JoinType          Join,
  const Standard_Real             Alt)
 {
-  Standard_NotImplemented_Raise_if (Join > GeomAbs_Arc,
-                                   "Only GeomAbs_Arc is implemented");
-
   myIsDone     = Standard_False;
   TopoDS_Shape aLocalShape = Spine.Oriented(TopAbs_FORWARD);
   myWorkSpine  = TopoDS::Face(aLocalShape);
@@ -734,7 +754,7 @@ void BRepFill_OffsetWire::PerformWithBiLo
   //********************************
   // Calculate for a non null offset 
   //********************************
-  if (KPartCircle(mySpine,Offset,Alt,myShape,myMap,myIsDone))
+  if (KPartCircle(myWorkSpine,Offset,Alt,myShape,myMap,myIsDone))
     return;
 
   BRep_Builder myBuilder;
@@ -770,25 +790,36 @@ void BRepFill_OffsetWire::PerformWithBiLo
   //---------------------------------------------------------------
   // Construction of Circles and OffsetCurves
   //---------------------------------------------------------------
+
+  TopoDS_Vertex Ends [2];
+  if (myIsOpenResult)
+  {
+    TopoDS_Wire theWire;
+    TopoDS_Iterator iter(mySpine);
+    theWire = TopoDS::Wire(iter.Value());
+    TopExp::Vertices(theWire, Ends[0], Ends[1]);
+  }
+  
   for (Standard_Integer ic = 1; ic <= Locus.NumberOfContours(); ic++) {
     TopoDS_Shape PEE = Link.GeneratingShape(Locus.BasicElt(ic,Locus.NumberOfElts(ic)));
     TopoDS_Shape& PE = PEE ;      
     for (Standard_Integer ie = 1; ie <= Locus.NumberOfElts(ic); ie++) {
       const TopoDS_Shape& SE = Link.GeneratingShape(Locus.BasicElt(ic,ie));
       if (SE.ShapeType() == TopAbs_VERTEX) {
-       MakeCircle (TopoDS::Edge(PE),TopoDS::Vertex(SE),
-                   myWorkSpine,myOffset,myMap,RefPlane);
+        if (!SE.IsSame(Ends[0]) && !SE.IsSame(Ends[1]))
+          MakeCircle (TopoDS::Edge(PE),TopoDS::Vertex(SE),
+                      myWorkSpine,myOffset,myMap,RefPlane);
       }
       else {
-       MakeOffset (TopoDS::Edge(SE),myWorkSpine,myOffset,myMap,RefPlane);
+       MakeOffset (TopoDS::Edge(SE),myWorkSpine,myOffset,myMap,RefPlane,
+                    myIsOpenResult, Ends);
        PE = SE;
       }
     }
   }
 
 
-#ifdef DEB
+#ifdef DRAW
   if (AffichEdge) {
     cout << " End Construction of geometric primitives "<<endl;
   }
@@ -816,6 +847,7 @@ void BRepFill_OffsetWire::PerformWithBiLo
     
 #ifdef DRAW
   if ( AffichGeom) {
+    char name[256];
     sprintf(name,"BISSEC_%d",NbBISSEC++);
     DrawTrSurf::Set(name,Bisec.Value());
   }
@@ -930,7 +962,7 @@ void BRepFill_OffsetWire::PerformWithBiLo
     if (!Detromp.IsBound(S[1])) Detromp.Bind(S[1],EmptyList);
 
     
-    UpdateDetromp (Detromp(S[0]), Detromp(S[1]), Vertices, Params, 
+    UpdateDetromp (Detromp, S[0], S[1], Vertices, Params, 
                   Bisec, StartOnEdge, EndOnEdge, Trim);
     //----------------------------------------------
     // Storage of vertices on parallel edges.
@@ -967,7 +999,7 @@ void BRepFill_OffsetWire::PerformWithBiLo
     }
   }
   
-#ifdef DEB 
+#ifdef DRAW
   if (AffichEdge) {
     cout << " End Construction of vertices on offsets"<<endl;
   }
@@ -990,11 +1022,19 @@ void BRepFill_OffsetWire::PerformWithBiLo
     if (MapBis.IsBound(CurrentEdge)) {
       TopTools_SequenceOfShape S;
       if (!MapBis(CurrentEdge).IsEmpty()) {
+        Standard_Integer IndOfE = 0;
+        if (myIsOpenResult)
+        {
+          if (j == 1)
+            IndOfE = 1;
+          else if (j == myMap.Extent())
+            IndOfE = -1;
+        }
        TrimEdge (CurrentEdge,
                  Detromp  (CurrentSpine),
                  MapBis   (CurrentEdge) ,  
                  MapVerPar(CurrentEdge) ,
-                 S, MapVV);
+                 S, MapVV, IndOfE);
        for ( k = 1; k <= S.Length(); k++) {
          myMap(j).Append(S.Value(k));
        }
@@ -1143,7 +1183,7 @@ void BRepFill_OffsetWire::PrepareSpine()
     TopExp::MapShapes(IteF.Value(), TopAbs_EDGE, EdgeMap);
     Standard_Integer nbEdges = EdgeMap.Extent();
     
-    if (nbEdges == 1)
+    if (nbEdges == 1 && !myIsOpenResult) //in case of open wire there's no need to do it
       ForcedCut = 2;
 //  Modified by Sergey KHROMOV - Thu Nov 16 17:29:48 2000 End
 
@@ -1192,13 +1232,108 @@ void BRepFill_OffsetWire::PrepareSpine()
 
 #ifdef DRAW
   if ( AffichEdge) {
-    sprintf(name,"WS");
-    DBRep::Set(name,myWorkSpine);
+    DBRep::Set("WS",myWorkSpine);
   }
 #endif
 
 }
 
+//=======================================================================
+//function : UpdateDetromp
+//purpose  : For each interval on bissectrice defined by parameters
+//           test if the medium point is at a distance > offset        
+//           in this case vertices corresponding to the extremities of the interval
+//           are ranked in the proofing.
+//           => If the same vertex appears in the proofing, the 
+//           border of the zone of proximity is tangent to the offset .
+//=======================================================================
+
+void BRepFill_OffsetWire::UpdateDetromp (BRepFill_DataMapOfOrientedShapeListOfShape& Detromp,
+                                         const TopoDS_Shape& Shape1,
+                                         const TopoDS_Shape& Shape2,
+                                         const TopTools_SequenceOfShape& Vertices, 
+                                         const TColgp_SequenceOfPnt&     Params, 
+                                         const Bisector_Bisec&           Bisec,
+                                         const Standard_Boolean          SOnE,
+                                         const Standard_Boolean          EOnE,
+                                         const BRepFill_TrimEdgeTool&    Trim) const
+{
+  if (myJoinType == GeomAbs_Intersection &&
+      Vertices.Length() == 1 &&
+      !EOnE)
+  {
+    TopTools_IndexedMapOfShape Vmap1, Vmap2;
+    TopExp::MapShapes(Shape1, TopAbs_VERTEX, Vmap1);
+    TopExp::MapShapes(Shape2, TopAbs_VERTEX, Vmap2);
+    Standard_Boolean Adjacent = Standard_False;
+    for (Standard_Integer i = 1; i <= Vmap1.Extent(); i++)
+      for (Standard_Integer j = 1; j <= Vmap2.Extent(); j++)
+        if (Vmap1(i).IsSame(Vmap2(j)))
+        {
+          Adjacent = Standard_True;
+          break;
+        }
+    if (Adjacent)
+    {
+      Detromp(Shape1).Append(Vertices.First());
+      Detromp(Shape2).Append(Vertices.First());
+      return;
+    }
+  }
+  
+  Standard_Integer ii = 1;
+  Standard_Real    U1,U2;
+  TopoDS_Vertex    V1,V2;
+
+  Handle(Geom2d_Curve) Bis = Bisec.Value();
+
+  U1 = Bis->FirstParameter();
+  
+  if (SOnE) { 
+    // the first point of the bissectrice is on the offset
+    V1 = TopoDS::Vertex(Vertices.Value(ii));
+    ii++; 
+  }
+
+  while (ii <= Vertices.Length()) {
+    U2 = Params.Value(ii).X();
+    V2 = TopoDS::Vertex(Vertices.Value(ii));
+
+    gp_Pnt2d P = Bis->Value((U2 + U1)*0.5);  
+    if (!Trim.IsInside(P)) {
+      if (!V1.IsNull()) {
+        Detromp(Shape1).Append(V1);
+        Detromp(Shape2).Append(V1);
+      }
+      Detromp(Shape1).Append(V2);
+      Detromp(Shape2).Append(V2);
+    }
+    U1 = U2;
+    V1 = V2;
+    ii ++;
+  }
+
+  // test medium point between the last parameter and the end of the bissectrice.
+  U2 = Bis->LastParameter();
+  if (!EOnE) {
+    if (!Precision::IsInfinite(U2)) {
+      gp_Pnt2d P = Bis->Value((U2 + U1)*0.5);  
+      if (!Trim.IsInside(P)) {
+       if (!V1.IsNull()) {
+         Detromp(Shape1).Append(V1);
+         Detromp(Shape2).Append(V1);
+       }
+      }
+    }
+    else {
+      if (!V1.IsNull()) {
+       Detromp(Shape1).Append(V1);
+       Detromp(Shape2).Append(V1);
+      }
+    }
+  }    
+}
+
 //=======================================================================
 //function : MakeWires
 //purpose  : 
@@ -1825,6 +1960,7 @@ void MakeCircle (const TopoDS_Edge&          E,
 
 #ifdef DRAW
   if ( AffichGeom && !OE.IsNull()) {
+    char name[256];
     sprintf(name,"OFFSET_%d",++NbOFFSET);
     DBRep::Set(name,OE);
   }
@@ -1840,7 +1976,9 @@ void MakeOffset (const TopoDS_Edge&        E,
                 const TopoDS_Face&        F,
                 const Standard_Real       Offset, 
                       BRepFill_IndexedDataMapOfOrientedShapeListOfShape& Map,
-                const Handle(Geom_Plane)& RefPlane)
+                const Handle(Geom_Plane)& RefPlane,
+                 const Standard_Boolean    IsOpenResult,
+                 const TopoDS_Vertex *     Ends)
 {
   Standard_Real f,l;
   Standard_Real anOffset = Offset;
@@ -1850,6 +1988,20 @@ void MakeOffset (const TopoDS_Edge&        E,
   Handle(Geom2d_Curve) G2d = BRep_Tool::CurveOnSurface(E,F,f,l);
   Handle(Geom2d_Curve) G2dOC;
 
+  Standard_Boolean ToExtendFirstPar = Standard_True;
+  Standard_Boolean ToExtendLastPar  = Standard_True;
+  if (IsOpenResult)
+  {
+    TopoDS_Vertex V1, V2;
+    TopExp::Vertices(E, V1, V2);
+    if (V1.IsSame(Ends[0]) ||
+        V1.IsSame(Ends[1]))
+      ToExtendFirstPar = Standard_False;
+    if (V2.IsSame(Ends[0]) ||
+        V2.IsSame(Ends[1]))
+      ToExtendLastPar  = Standard_False;
+  }
+
   Geom2dAdaptor_Curve  AC(G2d,f,l);
   if ( AC.GetType() == GeomAbs_Circle) {
     // if the offset is greater otr equal to the radius and the side of the  
@@ -1861,7 +2013,7 @@ void MakeOffset (const TopoDS_Edge&        E,
     Standard_Real Crossed = Xd.X()*Yd.Y()-Xd.Y()*Yd.X();
     Standard_Real Signe = ( Crossed > 0.) ? 1. : -1.;
 
-    if (anOffset*Signe < AC.Circle().Radius()) {
+    if (anOffset*Signe < AC.Circle().Radius() - Precision::Confusion()) {
 
       Handle(Geom2dAdaptor_HCurve) AHC = 
        new Geom2dAdaptor_HCurve(G2d);
@@ -1869,7 +2021,10 @@ void MakeOffset (const TopoDS_Edge&        E,
       Handle(Geom2d_Circle) CC = new Geom2d_Circle(Off.Circle());      
 
       Standard_Real Delta = 2*M_PI - l + f;
-      f -= 0.2*Delta; l += 0.2*Delta;
+      if (ToExtendFirstPar)
+        f -= 0.2*Delta;
+      if (ToExtendLastPar)
+        l += 0.2*Delta;
 
       G2dOC = new Geom2d_TrimmedCurve(CC,f,l);
     }
@@ -1880,7 +2035,10 @@ void MakeOffset (const TopoDS_Edge&        E,
     Adaptor3d_OffsetCurve Off(AHC,anOffset);
     Handle(Geom2d_Line)       CC = new Geom2d_Line(Off.Line());
     Standard_Real Delta = (l - f);
-    f -= Delta; l += Delta;
+    if (ToExtendFirstPar)
+      f -= Delta;
+    if (ToExtendLastPar)
+      l += Delta;
     G2dOC = new Geom2d_TrimmedCurve(CC,f,l);
   }
   else {
@@ -1901,6 +2059,7 @@ void MakeOffset (const TopoDS_Edge&        E,
 
 #ifdef DRAW  
     if (AffichGeom && !OE.IsNull()) {
+      char name[256];
       sprintf(name,"OFFSET_%d",++NbOFFSET);
       DBRep::Set(name,OE);
       Standard_Real ii = 0;
@@ -1910,77 +2069,6 @@ void MakeOffset (const TopoDS_Edge&        E,
   }
 }  
 
-//=======================================================================
-//function : UpdateDetromp
-//purpose  : For each interval on bissectrice defined by parameters
-//           test if the medium point is at a distance > offset        
-//           in this case vertices corresponding to the extremities of the interval
-//           are ranked in the proofing.
-//           => If the same vertex appears in the proofing, the 
-//           border of the zone of proximity is tangent to the offset .
-//=======================================================================
-
-void UpdateDetromp (TopTools_ListOfShape&           Detromp1,
-                   TopTools_ListOfShape&           Detromp2, 
-                   const TopTools_SequenceOfShape& Vertices, 
-                   const TColgp_SequenceOfPnt&     Params, 
-                   const Bisector_Bisec&           Bisec,
-                   const Standard_Boolean          SOnE,
-                   const Standard_Boolean          EOnE,
-                   const BRepFill_TrimEdgeTool&    Trim)
-{
-  Standard_Integer ii = 1;
-  Standard_Real    U1,U2;
-  TopoDS_Vertex    V1,V2;
-
-  Handle(Geom2d_Curve) Bis = Bisec.Value();
-
-  U1 = Bis->FirstParameter();
-  
-  if (SOnE) { 
-    // the first point of the bissectrice is on the offset
-    V1 = TopoDS::Vertex(Vertices.Value(ii));
-    ii++; 
-  }
-
-  while (ii <= Vertices.Length()) {
-    U2 = Params.Value(ii).X();
-    V2 = TopoDS::Vertex(Vertices.Value(ii));
-
-    gp_Pnt2d P = Bis->Value((U2 + U1)*0.5);  
-    if (!Trim.IsInside(P)) {
-      if (!V1.IsNull()) {
-         Detromp1.Append(V1);
-         Detromp2.Append(V1);
-      }
-      Detromp1.Append(V2);
-      Detromp2.Append(V2);
-    }
-    U1 = U2;
-    V1 = V2;
-    ii ++;
-  }
-
-  // test medium point between the last parameter and the end of the bissectrice.
-  U2 = Bis->LastParameter();
-  if (!EOnE) {
-    if (!Precision::IsInfinite(U2)) {
-      gp_Pnt2d P = Bis->Value((U2 + U1)*0.5);  
-      if (!Trim.IsInside(P)) {
-       if (!V1.IsNull()) {
-         Detromp1.Append(V1);
-         Detromp2.Append(V1);
-       }
-      }
-    }
-    else {
-      if (!V1.IsNull()) {
-       Detromp1.Append(V1);
-       Detromp2.Append(V1);
-      }
-    }
-  }    
-}
 
 //=======================================================================
 //function : VertexFromNode
@@ -2050,10 +2138,11 @@ void StoreInMap (const TopoDS_Shape& V1,
 
 void TrimEdge (const TopoDS_Edge&              E,
               const TopTools_ListOfShape&     Detromp,
-                    TopTools_SequenceOfShape& TheVer,
-                    TColStd_SequenceOfReal&   ThePar,
-                    TopTools_SequenceOfShape& S,
-                    TopTools_IndexedDataMapOfShapeShape& MapVV)
+               TopTools_SequenceOfShape& TheVer,
+               TColStd_SequenceOfReal&   ThePar,
+               TopTools_SequenceOfShape& S,
+               TopTools_IndexedDataMapOfShapeShape& MapVV,
+               const Standard_Integer IndOfE)
 {
   Standard_Boolean         Change = Standard_True;
   BRep_Builder             TheBuilder;
@@ -2124,44 +2213,93 @@ void TrimEdge (const TopoDS_Edge&              E,
   // the number of vertices should be even. The created edges  
   // go from a vertex with uneven index i to vertex i+1;
   //-----------------------------------------------------------
-  for (Standard_Integer k = 1; k < TheVer.Length(); k = k+2) {
+  if (IndOfE == 1 || IndOfE == -1) //open result and extreme edges of result
+  {
     TopoDS_Shape aLocalShape = E.EmptyCopied();
     TopoDS_Edge NewEdge = TopoDS::Edge(aLocalShape);
-//    TopoDS_Edge NewEdge = TopoDS::Edge(E.EmptyCopied());
-
-    if (NewEdge.Orientation() == TopAbs_REVERSED) {
-      TheBuilder.Add  (NewEdge,TheVer.Value(k)  .Oriented(TopAbs_REVERSED));
-      TheBuilder.Add  (NewEdge,TheVer.Value(k+1).Oriented(TopAbs_FORWARD));
+    TopoDS_Vertex V1, V2;
+    TopExp::Vertices(E, V1, V2);
+    Standard_Real fpar, lpar;
+    BRep_Tool::Range(E, fpar, lpar);
+    if (IndOfE == 1) //first edge of open wire
+    {
+      if (NewEdge.Orientation() == TopAbs_FORWARD)
+      {
+        TheBuilder.Add(NewEdge, V1.Oriented(TopAbs_FORWARD));
+        TheBuilder.Add(NewEdge, TheVer.First().Oriented(TopAbs_REVERSED));
+        TheBuilder.Range(NewEdge, fpar, ThePar.First());
+      }
+      else
+      {
+        //TheBuilder.Add(NewEdge, V1.Oriented(TopAbs_REVERSED));
+        //TheBuilder.Add(NewEdge, TheVer.First().Oriented(TopAbs_FORWARD));
+        TheBuilder.Add(NewEdge, TheVer.First().Oriented(TopAbs_REVERSED));
+        TheBuilder.Add(NewEdge, V2.Oriented(TopAbs_FORWARD));
+        TheBuilder.Range(NewEdge, ThePar.First(), lpar);
+      }
     }
-    else {      
-      TheBuilder.Add  (NewEdge,TheVer.Value(k)  .Oriented(TopAbs_FORWARD));
-      TheBuilder.Add  (NewEdge,TheVer.Value(k+1).Oriented(TopAbs_REVERSED));
+    else //last edge of open wire
+    {
+      if (NewEdge.Orientation() == TopAbs_FORWARD)
+      {
+        TheBuilder.Add(NewEdge, TheVer.First().Oriented(TopAbs_FORWARD));
+        TheBuilder.Add(NewEdge, V2.Oriented(TopAbs_REVERSED));
+        TheBuilder.Range(NewEdge, ThePar.First(), lpar);
+      }
+      else
+      {
+        //TheBuilder.Add(NewEdge, TheVer.First().Oriented(TopAbs_REVERSED));
+        //TheBuilder.Add(NewEdge, V2.Oriented(TopAbs_FORWARD));
+        TheBuilder.Add(NewEdge, V1.Oriented(TopAbs_REVERSED));
+        TheBuilder.Add(NewEdge, TheVer.First().Oriented(TopAbs_FORWARD));
+        TheBuilder.Range(NewEdge, fpar, ThePar.First());
+      }
     }
-
-
-    TheBuilder.Range(NewEdge,ThePar.Value(k),ThePar.Value(k+1));
-
+    S.Append(NewEdge);
+  }
+  else
+  {
+    for (Standard_Integer k = 1; k < TheVer.Length(); k = k+2) {
+      TopoDS_Shape aLocalShape = E.EmptyCopied();
+      TopoDS_Edge NewEdge = TopoDS::Edge(aLocalShape);
+      //    TopoDS_Edge NewEdge = TopoDS::Edge(E.EmptyCopied());
+      
+      if (NewEdge.Orientation() == TopAbs_REVERSED) {
+        TheBuilder.Add  (NewEdge,TheVer.Value(k)  .Oriented(TopAbs_REVERSED));
+        TheBuilder.Add  (NewEdge,TheVer.Value(k+1).Oriented(TopAbs_FORWARD));
+      }
+      else {      
+        TheBuilder.Add  (NewEdge,TheVer.Value(k)  .Oriented(TopAbs_FORWARD));
+        TheBuilder.Add  (NewEdge,TheVer.Value(k+1).Oriented(TopAbs_REVERSED));
+      }
+      
+      
+      TheBuilder.Range(NewEdge,ThePar.Value(k),ThePar.Value(k+1));
+      
 #ifdef DRAW
-    if ( AffichEdge) {
-      sprintf(name,"TRIMEDGE_%d",NbTRIMEDGES);
-      DBRep::Set(name,NewEdge);  
-    }
-    if (Affich2d) {
-      TopLoc_Location L;
-      Standard_Real f,l;
-      Handle(Geom_Surface) Surf;  
-      Handle(Geom2d_Curve) C;
-      BRep_Tool::CurveOnSurface(NewEdge,C,Surf,L,f,l);
-      sprintf(name,"OFFSET2d_%d",NbTRIMEDGES++);
-      Handle(Geom2d_TrimmedCurve) C2d = new Geom2d_TrimmedCurve(C,f,l);
-      Handle(DrawTrSurf_Curve2d) dr =
-       new DrawTrSurf_Curve2d(C2d,Standard_False);
-      dr->SetColor(Draw_bleu);
-      Draw::Set(name,dr);
-    }
+      if ( AffichEdge) {
+        char name[256];
+        sprintf(name,"TRIMEDGE_%d",NbTRIMEDGES);
+        DBRep::Set(name,NewEdge);  
+      }
+      if (Affich2d) {
+        TopLoc_Location L;
+        Standard_Real f,l;
+        Handle(Geom_Surface) Surf;  
+        Handle(Geom2d_Curve) C;
+        BRep_Tool::CurveOnSurface(NewEdge,C,Surf,L,f,l);
+        char name[256];
+        sprintf(name,"OFFSET2d_%d",NbTRIMEDGES++);
+        Handle(Geom2d_TrimmedCurve) C2d = new Geom2d_TrimmedCurve(C,f,l);
+        Handle(DrawTrSurf_Curve2d) dr =
+          new DrawTrSurf_Curve2d(C2d,Standard_False);
+        dr->SetColor(Draw_bleu);
+        Draw::Set(name,dr);
+      }
 #endif
-
-    S.Append(NewEdge);
+      
+      S.Append(NewEdge);
+    }
   }
 }
 
index 3b48a9c153341701781bc22b87e0471bfe97d48f..b66e786f32d93e2cbc80248177f2859b891ad8e0 100644 (file)
@@ -686,7 +686,8 @@ void BRepFill_PipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
   // 1) Preparation
   Prepare();
 
-  if (myStatus != GeomFill_PipeOk) {
+  if (myStatus != GeomFill_PipeOk ||
+      !mySection->NbLaw()) {
     BRep_Builder B;
     TopoDS_Shell Sh;
     B.MakeShell(Sh); 
index 62c1684008ff5b2f09883f11d793345eac0ca877..27db483714b589254831dabaa9c95821697be8b0 100644 (file)
@@ -44,6 +44,8 @@
 //=======================================================================
 Standard_Integer BRepFill_SectionLaw::NbLaw() const
 {
+  if (myLaws.IsNull())
+    return 0;
   return myLaws->Length();
 }
 
index 93c3d3d01c8099e4dcce1903c78dddcf087368fc..85077803a40da8542c78fd69ff888464eee32281 100644 (file)
@@ -1437,13 +1437,17 @@ static TopoDS_Edge BuildEdge(const Handle(Geom_Surface)& S,
   // Associate 2d
   Handle(Geom2d_Line) L;
   TopLoc_Location Loc;
+  Standard_Real Umin, Umax, Vmin, Vmax;
+  S->Bounds(Umin, Umax, Vmin, Vmax);
   if (isUiso) {
-    gp_Pnt2d P(ValIso, 0);
+    //gp_Pnt2d P(ValIso, 0);
+    gp_Pnt2d P( ValIso, Vmin - Iso->FirstParameter() );
     gp_Vec2d V(0., 1.);
     L = new (Geom2d_Line) (P, V);
   }
   else {
-    gp_Pnt2d P(0., ValIso);
+    //gp_Pnt2d P(0., ValIso);
+    gp_Pnt2d P( Umin -Iso->FirstParameter() , ValIso );
     gp_Vec2d V(1., 0.);
     L = new (Geom2d_Line) (P, V);
   }
index 53e478f6ec83c8f4a75f48ac535506c9d5a3eff2..5674253632c70e82b88fb9fb7c7c2240e3cc746c 100644 (file)
@@ -5,8 +5,8 @@
 --
 -- This file is part of Open CASCADE Technology software library.
 --
--- This library is free software; you can redistribute it and / or modify it
--- under the terms of the GNU Lesser General Public version 2.1 as published
+-- This library is free software; you can redistribute it and/or modify it under
+-- the terms of the GNU Lesser General Public License version 2.1 as published
 -- by the Free Software Foundation, with special exception defined in the file
 -- OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 -- distribution for complete text of the license and disclaimer of any warranty.
@@ -19,6 +19,7 @@ package BRepMAT2d
        ---Purpose: 
 
 uses
+    GeomAbs,
     MAT2d,
     MAT,
     TCollection,
@@ -27,29 +28,20 @@ uses
     Geom2d,
     gp,        
     TopoDS,
-    TopTools
+    TopTools,
+       Bisector
     
 is
     class Explorer;
-       ---Purpose: Construct an  explorer for  the computation of the 
-       --          bisecting locus  from a Wire, a  Face, or a set of 
-       --          curves from Geom2d.
 
-    class BisectingLocus instantiates BisectingLocus from MAT2d 
-                                         (Explorer  from BRepMAT2d);
-       ---Purpose: the map of bisecting locus.
-                                         
+    class BisectingLocus;
+
     class LinkTopoBilo;
-       ---Purpose: Constucts links between the Wire or the Face and
-       --          the BasicElts contained in the bisecting locus.
 
 
-    class SequenceOfBasicElt instantiates Sequence from TCollection
-                                                         (BasicElt from MAT); 
-                                                        
     class DataMapOfShapeSequenceOfBasicElt instantiates DataMap from TCollection 
                                              (Shape               from TopoDS, 
-                                              SequenceOfBasicElt  from  BRepMAT2d
+                                              SequenceOfBasicElt  from MAT
                                               ShapeMapHasher      from TopTools); 
     
     class DataMapOfBasicEltShape  instantiates
diff --git a/src/BRepMAT2d/BRepMAT2d_BisectingLocus.cdl b/src/BRepMAT2d/BRepMAT2d_BisectingLocus.cdl
new file mode 100644 (file)
index 0000000..9d258ba
--- /dev/null
@@ -0,0 +1,166 @@
+-- Created on: 1993-07-06
+-- Created by: Yves FRICAUD
+-- Copyright (c) 1993-1999 Matra Datavision
+-- Copyright (c) 1999-2014 OPEN CASCADE SAS
+--
+-- This file is part of Open CASCADE Technology software library.
+--
+-- This library is free software; you can redistribute it and/or modify it under
+-- the terms of the GNU Lesser General Public License version 2.1 as published
+-- by the Free Software Foundation, with special exception defined in the file
+-- OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+-- distribution for complete text of the license and disclaimer of any warranty.
+--
+-- Alternatively, this file may be used under the terms of Open CASCADE
+-- commercial license or contractual agreement.
+
+class BisectingLocus from BRepMAT2d 
+
+       ---Purpose  : BisectingLocus generates and contains the Bisecting_Locus
+       --            of a set of lines from Geom2d, defined by <ExploSet>.
+       --             
+       --            If the set of lines contains closed lines:
+       --            ------------------------------------------
+       --            These lines cut the plane  in areas. 
+       --            One map can  be  computed for each area.
+       --  
+       --            Bisecting locus computes a map in an area. 
+       --            The area is defined by a side (MAT_Left,MAT_Right) 
+       --            on one of the closed lines.
+       -- 
+       --            If the set of lines contains only open lines:
+       --            --------------------------------------------
+       --            the map recovers all the plane.
+       --  
+       --  Warning: Assume the orientation of the   closed  lines  are
+       --          compatible. 
+       --          
+       --          Assume the explo contains only lines located in the 
+       --          area where the bisecting locus will be computed.
+       --          
+       --          Assume a line don't cross itself or an other line.
+       --
+       --  Remark: 
+       --         the  curves  coming   from   the  explorer can   be
+       --         decomposed in different parts. It  the  case for the
+       --         curves other than circles or lines.
+       --         
+       --         The map of bisecting  locus is described by a graph.
+       --         - The  BasicsElements  correspond  to elements on
+       --           the figure described by the Explorer from BRepMAT2d.
+       --         - The Arcs correspond to the bisectors.
+       --         - The Nodes are the extremities of the arcs.
+
+uses
+    JoinType                 from GeomAbs,
+    Graph                    from MAT,
+    Arc                      from MAT,
+    BasicElt                 from MAT,
+    Node                     from MAT,
+    Side                     from MAT,
+    DataMapOfIntegerBasicElt from MAT,
+    DataMapOfBiIntInteger    from MAT2d,           
+    Bisec                    from Bisector,
+    Geometry                 from Geom2d,
+    Pnt2d                    from gp,
+    Tool2d                   from MAT2d,
+       Explorer                 from BRepMAT2d
+    
+is
+    Create returns BisectingLocus from BRepMAT2d;
+    
+---Category: Construction.
+
+    Compute (me        : in out ; 
+            anExplo   : in out Explorer from BRepMAT2d;
+             LineIndex :        Integer       = 1;
+             aSide     :        Side from MAT = MAT_Left;
+            aJoinType    :     JoinType from GeomAbs = GeomAbs_Arc;
+            IsOpenResult :     Boolean       = Standard_False)
+       --- Purpose : Computation of the Bisector_Locus in a set of Lines 
+       --            defined in <anExplo>.
+       --            The bisecting locus are computed on the side <aSide>
+       --            from the line <LineIndex> in <anExplo>. 
+    is static;
+    
+---Category: Querying.
+
+    IsDone (me) returns Boolean from Standard
+       ---Purpose: Returns True if Compute has succeeded.
+    is static;
+
+    Graph(me) returns Graph from MAT
+       --- Purpose : Returns <theGraph> of <me>.
+    is static;
+    
+    NumberOfContours (me)
+       ---Purpose: Returns the number of contours.
+    returns Integer from Standard
+    is static;
+    
+    NumberOfElts( me ; IndLine : Integer) 
+       ---Purpose: Returns the number of BasicElts on the line
+       --          <IndLine>.
+    returns Integer from Standard
+    is static;
+
+    NumberOfSections (me; IndLine : Integer; Index : Integer)
+       ---Purpose: Returns the number of sections of a curve.
+       --          this curve is the Indexth curve in the IndLineth contour
+       --          given by anExplo. 
+       --          
+    returns Integer from Standard
+    is static;
+    
+    BasicElt ( me ; IndLine : Integer ; Index : Integer)
+       ---Purpose: Returns the BasicElts located at the position
+       --          <Index> on the contour designed by <IndLine>.
+       --  Remark: the BasicElts on a contour are sorted.
+       --                    
+    returns BasicElt from MAT
+    is static;
+    
+    GeomElt(me ; aBasicElt : BasicElt from MAT) 
+       --- Purpose : Returns the geometry linked to the <BasicElt>.
+    returns Geometry from Geom2d
+    is static;
+    
+    GeomElt(me ; aNode : Node from MAT) 
+               --- Purpose : Returns the geometry of  type <gp> linked to
+       --            the <Node>.
+    returns Pnt2d from gp
+    is static;
+    
+    GeomBis(me ; anArc : Arc from MAT ; Reverse :in out Boolean from Standard) 
+               --- Purpose  : Returns the  geometry of type <Bissec> 
+       --             linked   to the arc <ARC>. 
+       --             <Reverse> is False when the FirstNode of <anArc>
+       --             correspond to the first point of geometry.
+       --             
+    returns Bisec from Bisector
+    is static;
+    
+---Category: private methods.
+    
+    Fusion(me : in out)
+    is static private;
+
+    RenumerationAndFusion
+       (me         : in out;
+        IndexLine  : Integer;
+       LengthLine : Integer;
+        IndexLast  : in out Integer;
+       NewMap     : in out DataMapOfIntegerBasicElt from MAT) 
+    is static private;
+    
+fields
+
+    theGraph    : Graph                 from MAT;
+    theTool     : Tool2d                from MAT2d;
+    isDone      : Boolean               from Standard;
+    nbSect      : DataMapOfBiIntInteger from MAT2d;
+    nbContours  : Integer               from Standard; 
+    
+end BisectingLocus;
+
+
diff --git a/src/BRepMAT2d/BRepMAT2d_BisectingLocus.cxx b/src/BRepMAT2d/BRepMAT2d_BisectingLocus.cxx
new file mode 100644 (file)
index 0000000..d96a6d8
--- /dev/null
@@ -0,0 +1,348 @@
+// Created on: 1993-07-13
+// Created by: Yves FRICAUD
+// Copyright (c) 1993-1999 Matra Datavision
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+# include <BRepMAT2d_BisectingLocus.ixx>
+
+# include <MAT2d_Mat2d.hxx>
+# include <MAT2d_Tool2d.hxx>
+# include <MAT2d_Circuit.hxx>
+# include <MAT2d_CutCurve.hxx>
+# include <MAT2d_BiInt.hxx>
+# include <MAT2d_SequenceOfSequenceOfGeometry.hxx>
+# include <MAT_Graph.hxx>
+# include <MAT_Arc.hxx>
+# include <MAT_BasicElt.hxx>
+# include <MAT_Node.hxx>
+# include <MAT_Bisector.hxx>
+# include <MAT_ListOfBisector.hxx>
+# include <MAT_DataMapOfIntegerBasicElt.hxx>
+# include <MAT_DataMapIteratorOfDataMapOfIntegerBasicElt.hxx>
+# include <Geom2d_Curve.hxx>
+# include <gp_Pnt2d.hxx>
+# include <TColGeom2d_SequenceOfGeometry.hxx>
+# include <Precision.hxx>
+
+#include <Standard_OutOfRange.hxx>
+
+static void CutSketch (MAT2d_SequenceOfSequenceOfGeometry&    Figure,
+                      MAT2d_DataMapOfBiIntInteger&           NbSect);
+
+
+//=============================================================================
+//function : BRepMAT2d_BisectingLocus
+//purpose  : Constructeur vide.
+//=============================================================================
+BRepMAT2d_BisectingLocus::BRepMAT2d_BisectingLocus()
+{
+}
+
+
+//=============================================================================
+//function : Compute
+//purpose  : Calcul de la carte des lieux bisecteurs sur le contour defini par
+//           <anExplo>.
+//=============================================================================
+void BRepMAT2d_BisectingLocus::Compute(BRepMAT2d_Explorer&        anExplo,
+                                       const Standard_Integer IndexLine,
+                                       const MAT_Side         aSide,
+                                       const GeomAbs_JoinType aJoinType,
+                                       const Standard_Boolean IsOpenResult)
+{
+  MAT2d_Mat2d                        TheMAT( IsOpenResult );
+  Handle(MAT_ListOfBisector)         TheRoots = new MAT_ListOfBisector();
+  MAT2d_SequenceOfSequenceOfGeometry Figure;
+  Standard_Integer                   i;
+
+  nbSect.Clear();
+  nbContours = anExplo.NumberOfContours();
+
+  //---------------------------------
+  // Lecture des donnees de anExplo.
+  //---------------------------------
+  for (i = 1; i <= anExplo.NumberOfContours(); i++) {
+    TColGeom2d_SequenceOfGeometry      Line;
+    Figure.Append(Line);
+    for (anExplo.Init(i); anExplo.More(); anExplo.Next()) {
+      Figure.ChangeValue(i).Append(anExplo.Value());
+    }
+  }
+
+  //-----------------------
+  // Decoupage des courbes.
+  //-----------------------
+  CutSketch(Figure,nbSect);
+
+  //----------------------------------------------------------
+  // Construction du circuit sur lequel est calcule la carte.
+  //----------------------------------------------------------
+  Handle(MAT2d_Circuit) ACircuit = new MAT2d_Circuit(aJoinType, IsOpenResult);
+//  Modified by Sergey KHROMOV - Wed Mar  6 17:43:47 2002 Begin
+//   ACircuit->Perform(Figure,IndexLine,(aSide == MAT_Left));
+  ACircuit->Perform(Figure,anExplo.GetIsClosed(), IndexLine,(aSide == MAT_Left));
+//  Modified by Sergey KHROMOV - Wed Mar  6 17:43:48 2002 End
+
+  // -----------------------
+  // Initialistion du Tool.
+  // -----------------------
+  theTool.Sense(aSide);
+  theTool.SetJoinType(aJoinType);
+  theTool.InitItems(ACircuit);
+
+  // --------------------------------------------
+  // Initialisation et execution de l algorithme.
+  // --------------------------------------------
+  if (IsOpenResult)
+    TheMAT.CreateMatOpen(theTool);
+  else
+    TheMAT.CreateMat(theTool);
+
+  isDone = TheMAT.IsDone(); if (!isDone) return;
+
+  // ----------------------------------------------------------------
+  // Recuperation du resultat de l algorithme et creation du graphe.
+  // ----------------------------------------------------------------
+  for (TheMAT.Init(); TheMAT.More(); TheMAT.Next()) {
+    TheRoots->BackAdd(TheMAT.Bisector());
+  }
+
+  theGraph = new MAT_Graph();
+  theGraph->Perform(TheMAT.SemiInfinite(),
+                   TheRoots, 
+                   theTool.NumberOfItems(), 
+                   TheMAT.NumberOfBisectors());
+
+  //-----------------------------------------------------------------------
+  // Fusion des elements de base doubles si plusieurs lignes dans Exploset.
+  //-----------------------------------------------------------------------
+  if (anExplo.NumberOfContours() > 1) {
+    MAT_DataMapOfIntegerBasicElt NewMap;
+    Standard_Integer             IndexLast  = 1;
+
+    //-----------------------------------------------------------------------
+    // Construction de NewMap dont les elements sont ordonnes suivant les
+    // lignes du contour et qui ne contient pas d element dupliques.
+    // em meme temps fusion des arcs dupliques et mise a jour des noeuds.
+    //-----------------------------------------------------------------------
+    for ( i = 1; i <= anExplo.NumberOfContours(); i++) {
+      RenumerationAndFusion(i,
+                           theTool.Circuit()->LineLength(i),
+                           IndexLast,
+                           NewMap);
+    }
+
+    //-----------------------------------------------------------------------
+    // Chargement dans le graph de la nouvelle map.
+    // et compactage de la map des Arcs (ie  Elimination des trous du a la
+    // fusion d arcs ).et  de celle des Nodes.
+    //-----------------------------------------------------------------------
+    theGraph->ChangeBasicElts(NewMap);    
+    theGraph->CompactArcs();
+    theGraph->CompactNodes();
+  }
+}
+
+//=============================================================================
+//function : RenumerationAndFusion
+//purpose  :
+//=============================================================================
+void BRepMAT2d_BisectingLocus::RenumerationAndFusion
+  (const Standard_Integer              ILine,
+   const Standard_Integer              LengthLine,
+         Standard_Integer&             IndexLast,
+         MAT_DataMapOfIntegerBasicElt& NewMap)
+{
+  Standard_Integer IndFirst;
+  Standard_Integer i,j;
+  Standard_Integer GeomIndexArc1,GeomIndexArc2,GeomIndexArc3,GeomIndexArc4;
+  Standard_Boolean MergeArc1,MergeArc2;
+
+  for ( i = 1; i <= LengthLine; i++) {
+    const TColStd_SequenceOfInteger& S = theTool.Circuit()->RefToEqui(ILine,i);
+
+    IndFirst = S.Value(1);
+    NewMap.Bind(IndexLast,theGraph->ChangeBasicElt(IndFirst));
+    IndexLast++;
+
+    for(j = 2; j <= S.Length(); j++){
+      theGraph->FusionOfBasicElts(IndFirst,
+                                 S.Value(j),
+                                 MergeArc1,
+                                 GeomIndexArc1,
+                                 GeomIndexArc2,
+                                 MergeArc2,
+                                 GeomIndexArc3,
+                                 GeomIndexArc4);
+      if(MergeArc1) {
+       theTool.BisecFusion(GeomIndexArc1,GeomIndexArc2);
+      }
+      if(MergeArc2) {
+       theTool.BisecFusion(GeomIndexArc3,GeomIndexArc4);
+      }
+    }
+  }
+}
+
+//=============================================================================
+//function : IsDone
+//Purpose  : 
+//=============================================================================
+Standard_Boolean BRepMAT2d_BisectingLocus::IsDone() const
+{
+  return isDone;
+}
+
+//=============================================================================
+//function : Graph
+//
+//=============================================================================
+Handle(MAT_Graph) BRepMAT2d_BisectingLocus::Graph() const
+{
+  return theGraph;
+}
+
+//=============================================================================
+//function : NumberOfContours
+//
+//=============================================================================
+Standard_Integer BRepMAT2d_BisectingLocus::NumberOfContours () const
+{
+  return nbContours;
+}
+
+//=============================================================================
+//function : NumberOfElts
+//
+//=============================================================================
+Standard_Integer BRepMAT2d_BisectingLocus::NumberOfElts 
+ (const Standard_Integer IndLine) const
+{
+  return theTool.Circuit()->LineLength(IndLine);
+}
+
+//=============================================================================
+//function : NumberOfSect
+//
+//=============================================================================
+Standard_Integer BRepMAT2d_BisectingLocus::NumberOfSections
+(const Standard_Integer IndLine,
+ const Standard_Integer Index  ) 
+     const
+{
+  MAT2d_BiInt B(IndLine,Index);
+  return nbSect(B);
+}
+
+//=============================================================================
+//function : BasicElt
+//
+//=============================================================================
+Handle(MAT_BasicElt) BRepMAT2d_BisectingLocus::BasicElt 
+       (const Standard_Integer IndLine,
+       const Standard_Integer Index  ) 
+     const
+{
+  Standard_Integer i;
+  Standard_Integer Ind = Index;
+
+  for (i = 1 ; i < IndLine ; i++){
+    Ind = Ind + theTool.Circuit()->LineLength(i);
+  }
+  return theGraph->BasicElt(Ind);
+}
+
+
+//=============================================================================
+//function : GeomBis
+//
+//=============================================================================
+Bisector_Bisec  BRepMAT2d_BisectingLocus::GeomBis (const Handle(MAT_Arc)&  anArc,
+                                                    Standard_Boolean& Reverse) 
+const 
+{
+  Reverse = Standard_False;
+
+  Handle(Geom2d_Curve) Bis = theTool.GeomBis(anArc->GeomIndex()).Value();
+
+  if (Bis->FirstParameter() <= -Precision::Infinite()) {
+    Reverse = Standard_True;
+  }
+  else if (Bis->LastParameter() < Precision::Infinite()) {
+    gp_Pnt2d PF    = Bis->Value(Bis->FirstParameter());
+    gp_Pnt2d PL    = Bis->Value(Bis->LastParameter());
+    gp_Pnt2d PNode = GeomElt(anArc->FirstNode());
+    if (PNode.SquareDistance(PF) > PNode.SquareDistance(PL)) 
+      Reverse = Standard_True;
+  }
+  return theTool.GeomBis(anArc->GeomIndex());
+}
+
+//=============================================================================
+//function : GeomElt
+//
+//=============================================================================
+Handle(Geom2d_Geometry)  BRepMAT2d_BisectingLocus::GeomElt
+                           (const Handle(MAT_BasicElt)& aBasicElt) const
+{
+  return  theTool.GeomElt(aBasicElt->GeomIndex());
+}
+
+
+//=============================================================================
+//function : GeomElt
+//
+//=============================================================================
+gp_Pnt2d  BRepMAT2d_BisectingLocus::GeomElt(const Handle(MAT_Node)& aNode) const
+{
+  return theTool.GeomPnt(aNode->GeomIndex());
+}
+
+
+//=============================================================================
+//function : CutSketch
+//
+//=============================================================================
+static void CutSketch (MAT2d_SequenceOfSequenceOfGeometry&    Figure,
+                      MAT2d_DataMapOfBiIntInteger&           NbSect)
+{
+  MAT2d_CutCurve   Cuter;
+  Standard_Integer i,j,k,ico;
+  Standard_Integer ICurveInit;
+  Standard_Integer NbSection;
+
+  for ( i = 1; i <= Figure.Length(); i++) {
+    TColGeom2d_SequenceOfGeometry& Contour = Figure.ChangeValue(i);  
+    ICurveInit = 0;
+
+    for ( j = 1; j <= Contour.Length(); j++) {
+      ICurveInit++;
+      Cuter.Perform(Handle(Geom2d_Curve)::DownCast(Contour.ChangeValue(j)));
+      NbSection = 1;
+      if (!Cuter.UnModified()) {
+       ico    = j;
+       NbSection = Cuter.NbCurves();
+       for ( k = 1; k <= NbSection; k++) {
+         Contour.InsertAfter(j,Cuter.Value(k));
+         j++;
+       }
+       Contour.Remove(ico);
+       j--;
+      }
+      MAT2d_BiInt B(i,ICurveInit);
+      NbSect.Bind(B,NbSection);
+    }
+  }
+}  
+
index 526bd856f78464f1fcb9b269db630bf8b50195b3..d2e1758c145d0ed36a976fbb95b5e10d642e12b6 100644 (file)
@@ -40,13 +40,15 @@ is
     Create returns MakeOffset from BRepOffsetAPI;
        ---Purpose: Constructs an algorithm for creating an empty offset
     Create( Spine : Face from TopoDS;
-           Join  : JoinType from GeomAbs = GeomAbs_Arc)
+           Join  : JoinType from GeomAbs = GeomAbs_Arc;
+           IsOpenResult : Boolean from Standard = Standard_False)
     returns MakeOffset from BRepOffsetAPI;
        ---Purpose: Constructs an algorithm for creating an algorithm
        -- to build parallels to the spine Spine   
     Init( me    : in out;
          Spine : Face     from TopoDS; 
-         Join  : JoinType from GeomAbs  =  GeomAbs_Arc)
+         Join  : JoinType from GeomAbs  =  GeomAbs_Arc;
+         IsOpenResult : Boolean from Standard = Standard_False)
        ---Purpose: Initializes the algorithm to construct parallels to the spine Spine.
        -- Join defines the type of parallel generated by the
        -- salient vertices of the spine. The default type is
@@ -55,11 +57,13 @@ is
     is static;
     
     Create( Spine : Wire from TopoDS;
-           Join  : JoinType from GeomAbs = GeomAbs_Arc)
+           Join  : JoinType from GeomAbs = GeomAbs_Arc;
+           IsOpenResult : Boolean from Standard = Standard_False)
     returns MakeOffset from BRepOffsetAPI;
     
     Init( me    : in out;
-         Join  : JoinType from GeomAbs  =  GeomAbs_Arc)
+         Join  : JoinType from GeomAbs  =  GeomAbs_Arc;
+         IsOpenResult : Boolean from Standard = Standard_False)
        ---Purpose: Initialize the evaluation of Offseting.
     is static;
 
@@ -99,6 +103,7 @@ fields
     myIsInitialized : Boolean          from Standard;
     myLastIsLeft    : Boolean          from Standard;
     myJoin          : JoinType         from GeomAbs;   
+    myIsOpenResult  : Boolean          from Standard;  
     myFace          : Face             from TopoDS;
     myWires         : ListOfShape      from TopTools;   
     myLeft          : ListOfOffsetWire from BRepFill;
index 243d287d9b1ac98770a8b252b31b4bc1998a2e22..2f2ea15b59c2740da34492e523ccf57b74718101 100644 (file)
@@ -54,9 +54,10 @@ BRepOffsetAPI_MakeOffset::BRepOffsetAPI_MakeOffset()
 //=======================================================================
 
 BRepOffsetAPI_MakeOffset::BRepOffsetAPI_MakeOffset(const TopoDS_Face& Spine, 
-  const GeomAbs_JoinType Join)
+                                                   const GeomAbs_JoinType Join,
+                                                   const Standard_Boolean IsOpenResult)
 {
-  Init(Spine, Join);
+  Init(Spine, Join, IsOpenResult);
 }
 
 
@@ -66,11 +67,13 @@ BRepOffsetAPI_MakeOffset::BRepOffsetAPI_MakeOffset(const TopoDS_Face& Spine,
 //=======================================================================
 
 void BRepOffsetAPI_MakeOffset::Init(const TopoDS_Face&     Spine,
-  const GeomAbs_JoinType Join)
+                                    const GeomAbs_JoinType Join,
+                                    const Standard_Boolean IsOpenResult)
 {
   myFace          = Spine;
   myIsInitialized = Standard_True;
   myJoin          = Join;
+  myIsOpenResult  = IsOpenResult;
   TopExp_Explorer exp;
   for (exp.Init(myFace,TopAbs_WIRE); exp.More();exp.Next()) {
     myWires.Append(exp.Current());
@@ -83,11 +86,13 @@ void BRepOffsetAPI_MakeOffset::Init(const TopoDS_Face&     Spine,
 //=======================================================================
 
 BRepOffsetAPI_MakeOffset::BRepOffsetAPI_MakeOffset(const TopoDS_Wire& Spine, 
-  const GeomAbs_JoinType Join)
+                                                   const GeomAbs_JoinType Join,
+                                                   const Standard_Boolean IsOpenResult)
 {
   myWires.Append(Spine);
   myIsInitialized = Standard_True;
   myJoin = Join;
+  myIsOpenResult  = IsOpenResult;
 }
 
 //=======================================================================
@@ -95,9 +100,11 @@ BRepOffsetAPI_MakeOffset::BRepOffsetAPI_MakeOffset(const TopoDS_Wire& Spine,
 //purpose  : 
 //=======================================================================
 
-void BRepOffsetAPI_MakeOffset::Init(const GeomAbs_JoinType Join)
+void BRepOffsetAPI_MakeOffset::Init(const GeomAbs_JoinType Join,
+                                    const Standard_Boolean IsOpenResult)
 {
   myJoin = Join;
+  myIsOpenResult  = IsOpenResult;
 }
 
 //=======================================================================
@@ -118,10 +125,11 @@ void BRepOffsetAPI_MakeOffset::AddWire(const TopoDS_Wire& Spine)
 //=======================================================================
 
 static void BuildDomains(TopoDS_Face&               myFace,
-  TopTools_ListOfShape&      WorkWires,
-  BRepFill_ListOfOffsetWire& myAlgos,
-  GeomAbs_JoinType           myJoin,
-  Standard_Boolean           isPositive)
+                         TopTools_ListOfShape&      WorkWires,
+                         BRepFill_ListOfOffsetWire& myAlgos,
+                         GeomAbs_JoinType           myJoin,
+                         Standard_Boolean           myIsOpenResult,
+                         Standard_Boolean           isPositive)
 {
   BRepAlgo_FaceRestrictor  FR;
   TopoDS_Vertex            VF,VL;
@@ -190,7 +198,7 @@ static void BuildDomains(TopoDS_Face&               myFace,
     for ( ; itW.More(); itW.Next()) {
       B.Add(F,itW.Value());
     }
-    BRepFill_OffsetWire Algo(F, myJoin);
+    BRepFill_OffsetWire Algo(F, myJoin, myIsOpenResult);
     myAlgos.Append(Algo);
     return;
   }
@@ -243,7 +251,7 @@ static void BuildDomains(TopoDS_Face&               myFace,
   // Creation of algorithms on each domain.
   //========================================
   for (itF.Initialize(Faces); itF.More(); itF.Next()) {
-    BRepFill_OffsetWire Algo(TopoDS::Face(itF.Value()), myJoin);
+    BRepFill_OffsetWire Algo(TopoDS::Face(itF.Value()), myJoin, myIsOpenResult);
     myAlgos.Append(Algo);
   }
 }
@@ -253,13 +261,13 @@ static void BuildDomains(TopoDS_Face&               myFace,
 //purpose  : 
 //=======================================================================
 
-void BRepOffsetAPI_MakeOffset::Perform( const Standard_Real Offset,
-  const Standard_Real Alt)
+void BRepOffsetAPI_MakeOffset::Perform(const Standard_Real Offset,
+                                       const Standard_Real Alt)
 {
   StdFail_NotDone_Raise_if ( !myIsInitialized,
     "BRepOffsetAPI_MakeOffset : Perform without Init");
 
-  try
+  //try
   {
     Standard_Integer i = 1;
     BRepFill_ListIteratorOfListOfOffsetWire itOW;
@@ -273,7 +281,7 @@ void BRepOffsetAPI_MakeOffset::Perform( const Standard_Real Offset,
       if( myLeft.IsEmpty() )
       {
         //  Modified by Sergey KHROMOV - Fri Apr 27 14:35:26 2001 Begin
-        BuildDomains(myFace,myWires,myLeft,myJoin, Standard_False);
+        BuildDomains(myFace,myWires,myLeft,myJoin,myIsOpenResult, Standard_False);
         //  Modified by Sergey KHROMOV - Fri Apr 27 14:35:26 2001 End
       }
 
@@ -296,7 +304,7 @@ void BRepOffsetAPI_MakeOffset::Perform( const Standard_Real Offset,
       if (myRight.IsEmpty())
       {
         //  Modified by Sergey KHROMOV - Fri Apr 27 14:35:28 2001 Begin
-        BuildDomains(myFace,myWires,myRight,myJoin, Standard_True);
+        BuildDomains(myFace,myWires,myRight,myJoin,myIsOpenResult, Standard_True);
         //  Modified by Sergey KHROMOV - Fri Apr 27 14:35:35 2001 End
       }
 
@@ -325,14 +333,14 @@ void BRepOffsetAPI_MakeOffset::Perform( const Standard_Real Offset,
     else
       Done();
   }
-  catch(...) //Every exception was caught.
-  {
-    cout<<"An exception was caught in BRepOffsetAPI_MakeOffset::Perform : ";
-    Standard_ConstructionError::Caught()->Print(cout); 
-    cout<<endl;
-    NotDone();
-    myShape.Nullify();
-  }
+  //catch(...) //Every exception was caught.
+  //{
+  //  cout<<"An exception was caught in BRepOffsetAPI_MakeOffset::Perform : ";
+  //  Standard_ConstructionError::Caught()->Print(cout); 
+  //  cout<<endl;
+  //  NotDone();
+  //  myShape.Nullify();
+  //}
 }
 
 //=======================================================================
index f618e41cc26a5e7ab04026594a3f92f1f3721a74..f9b79778848f078db680ef5343de96cf3a3a7454 100644 (file)
 //=======================================================================
 
 static Standard_Real PreciseUpar(const Standard_Real anUpar,
-                                 const Handle(Geom_BSplineSurface)& aSurface)
+  const Handle(Geom_BSplineSurface)& aSurface)
 {
   Standard_Real Tol = Precision::PConfusion();
   Standard_Integer i1, i2;
@@ -126,17 +126,17 @@ static Standard_Real PreciseUpar(const Standard_Real anUpar,
 //=======================================================================
 
 static Standard_Boolean PerformPlan(const TopoDS_Wire& W,
-                                   const Standard_Real presPln,
-                                   TopoDS_Face& theFace)
+  const Standard_Real presPln,
+  TopoDS_Face& theFace)
 {
   Standard_Boolean isDegen = Standard_True;
   TopoDS_Iterator iter(W);
   for (; iter.More(); iter.Next())
-    {
-      const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
-      if (!BRep_Tool::Degenerated(anEdge))
-       isDegen = Standard_False;
-    }
+  {
+    const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
+    if (!BRep_Tool::Degenerated(anEdge))
+      isDegen = Standard_False;
+  }
   if (isDegen)
     return Standard_True;
 
@@ -144,22 +144,22 @@ static Standard_Boolean PerformPlan(const TopoDS_Wire& W,
   if (!W.IsNull()) {
     BRepBuilderAPI_FindPlane Searcher( W, presPln );
     if (Searcher.Found())
-      {
-       theFace = BRepBuilderAPI_MakeFace(Searcher.Plane(), W);
-       Ok = Standard_True;
-      }
+    {
+      theFace = BRepBuilderAPI_MakeFace(Searcher.Plane(), W);
+      Ok = Standard_True;
+    }
     else // try to find another surface
+    {
+      BRepBuilderAPI_MakeFace MF( W );
+      if (MF.IsDone())
       {
-       BRepBuilderAPI_MakeFace MF( W );
-       if (MF.IsDone())
-         {
-           theFace = MF.Face();
-           Ok = Standard_True;
-         }
+        theFace = MF.Face();
+        Ok = Standard_True;
       }
+    }
   }
 
- return Ok;
 return Ok;
 }
 
 //=============================================================================
@@ -168,7 +168,7 @@ static Standard_Boolean PerformPlan(const TopoDS_Wire& W,
 //=============================================================================
 
 static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
-                                      const TopoDS_Shape& aShell)
+  const TopoDS_Shape& aShell)
 {
   TopExp_Explorer Explo(aFace, TopAbs_EDGE);
   TopoDS_Shape anEdge = Explo.Current();
@@ -180,11 +180,11 @@ static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
   const TopoDS_Shape& AdjacentFace = EFmap.FindFromKey(anEdge).First();
   TopoDS_Shape theEdge;
   for (Explo.Init(AdjacentFace, TopAbs_EDGE); Explo.More(); Explo.Next())
-    {
-      theEdge = Explo.Current();
-      if (theEdge.IsSame(anEdge))
-       break;
-    }
+  {
+    theEdge = Explo.Current();
+    if (theEdge.IsSame(anEdge))
+      break;
+  }
 
   TopAbs_Orientation Or2 = theEdge.Orientation();
   if (Or1 == Or2)
@@ -198,8 +198,8 @@ static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
 //=======================================================================
 
 static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
-                             const TopoDS_Wire& wire2, const Standard_Real presPln,
-                             TopoDS_Face& face1, TopoDS_Face& face2)
+  const TopoDS_Wire& wire2, const Standard_Real presPln,
+  TopoDS_Face& face1, TopoDS_Face& face2)
 {
   if (shell.IsNull())
     StdFail_NotDone::Raise("Thrusections is not build");
@@ -207,31 +207,31 @@ static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
   BRep_Builder BB;
 
   if (!B)
-    {
-      // It is necessary to close the extremities 
-      B =  PerformPlan(wire1, presPln, face1);
+  {
+    // It is necessary to close the extremities 
+    B =  PerformPlan(wire1, presPln, face1);
+    if (B) {
+      B =  PerformPlan(wire2, presPln, face2);
       if (B) {
-       B =  PerformPlan(wire2, presPln, face2);
-       if (B) {
-         if (!face1.IsNull() && !IsSameOriented( face1, shell ))
-           face1.Reverse();
-         if (!face2.IsNull() && !IsSameOriented( face2, shell ))
-           face2.Reverse();
-         
-         if (!face1.IsNull())
-           BB.Add(shell, face1);
-         if (!face2.IsNull())
-           BB.Add(shell, face2);
-         
-         shell.Closed(Standard_True);
-       }
+        if (!face1.IsNull() && !IsSameOriented( face1, shell ))
+          face1.Reverse();
+        if (!face2.IsNull() && !IsSameOriented( face2, shell ))
+          face2.Reverse();
+
+        if (!face1.IsNull())
+          BB.Add(shell, face1);
+        if (!face2.IsNull())
+          BB.Add(shell, face2);
+
+        shell.Closed(Standard_True);
       }
     }
+  }
 
   TopoDS_Solid solid;
   BB.MakeSolid(solid); 
   BB.Add(solid, shell);
-  
+
   // verify the orientation the solid
   BRepClass3d_SolidClassifier clas3d(solid);
   clas3d.PerformInfinitePoint(Precision::Confusion());
@@ -239,7 +239,7 @@ static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
     BB.MakeSolid(solid); 
     TopoDS_Shape aLocalShape = shell.Reversed();
     BB.Add(solid, TopoDS::Shell(aLocalShape));
-//    B.Add(solid, TopoDS::Shell(newShell.Reversed()));
+    //    B.Add(solid, TopoDS::Shell(newShell.Reversed()));
   }
 
   solid.Closed(Standard_True);
@@ -253,11 +253,11 @@ static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
 //=======================================================================
 
 BRepOffsetAPI_ThruSections::BRepOffsetAPI_ThruSections(const Standard_Boolean isSolid, const Standard_Boolean ruled,
-                                            const Standard_Real pres3d):
-                                            myIsSolid(isSolid), myIsRuled(ruled), myPres3d(pres3d)
+  const Standard_Real pres3d):
+myIsSolid(isSolid), myIsRuled(ruled), myPres3d(pres3d)
 {
   myWCheck = Standard_True;
-//----------------------------
+  //----------------------------
   myParamType = Approx_ChordLength; 
   myDegMax    = 8; 
   myContinuity = GeomAbs_C2;
@@ -274,13 +274,13 @@ BRepOffsetAPI_ThruSections::BRepOffsetAPI_ThruSections(const Standard_Boolean is
 //=======================================================================
 
 void BRepOffsetAPI_ThruSections::Init(const Standard_Boolean isSolid, const Standard_Boolean ruled,
-                                const Standard_Real pres3d)
+  const Standard_Real pres3d)
 {
   myIsSolid = isSolid;
   myIsRuled = ruled;
   myPres3d = pres3d;
   myWCheck = Standard_True;
-//----------------------------
+  //----------------------------
   myParamType = Approx_ChordLength; 
   myDegMax    = 6; 
   myContinuity = GeomAbs_C2;
@@ -348,39 +348,39 @@ void BRepOffsetAPI_ThruSections::Build()
   Standard_Integer i;
   TopExp_Explorer explo;
   for (i = 2; i <= myWires.Length()-1; i++)
+  {
+    Standard_Boolean wdeg = Standard_True;
+    for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
     {
-      Standard_Boolean wdeg = Standard_True;
-      for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
-       {
-         const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
-         wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
-       }
-      if (wdeg)
-       Standard_Failure::Raise("Wrong usage of punctual sections");
+      const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
+      wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
     }
+    if (wdeg)
+      Standard_Failure::Raise("Wrong usage of punctual sections");
+  }
   if (myWires.Length() <= 2)
-    {
-      Standard_Boolean wdeg = Standard_True;
-      for (i = 1; i <= myWires.Length(); i++)
-       for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
-         {
-           const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
-           wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
-         }
+  {
+    Standard_Boolean wdeg = Standard_True;
+    for (i = 1; i <= myWires.Length(); i++)
+      for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
+      {
+        const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
+        wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
+      }
       if (wdeg)
-       Standard_Failure::Raise("Wrong usage of punctual sections");
-    }
+        Standard_Failure::Raise("Wrong usage of punctual sections");
+  }
 
   if (myWCheck) {
     // compute origin and orientation on wires to avoid twisted results
     // and update wires to have same number of edges
-    
+
     // use BRepFill_CompatibleWires
     TopTools_SequenceOfShape WorkingSections;
     WorkingSections.Clear();
     TopTools_DataMapOfShapeListOfShape WorkingMap;
     WorkingMap.Clear();
-    
+
     // Calculate the working sections
     BRepFill_CompatibleWires Georges(myWires);
     Georges.Perform();
@@ -402,7 +402,7 @@ void BRepOffsetAPI_ThruSections::Build()
   }
   // Encode the Regularities
   BRepLib::EncodeRegularity(myShape);
-  
+
 }
 
 
@@ -415,7 +415,7 @@ void BRepOffsetAPI_ThruSections::CreateRuled()
 {
   Standard_Integer nbSects = myWires.Length();
   BRepFill_Generator aGene;
-//  for (Standard_Integer i=1; i<=nbSects; i++) {
+  //  for (Standard_Integer i=1; i<=nbSects; i++) {
   Standard_Integer i;
   for (i=1; i<=nbSects; i++) {
     aGene.AddWire(TopoDS::Wire(myWires(i)));
@@ -434,15 +434,15 @@ void BRepOffsetAPI_ThruSections::CreateRuled()
       BRep_Builder B;
       B.MakeSolid(solid); 
       B.Add(solid, shell);
-      
+
       // verify the orientation of the solid
       BRepClass3d_SolidClassifier clas3d(solid);
       clas3d.PerformInfinitePoint(Precision::Confusion());
       if (clas3d.State() == TopAbs_IN) {
-       B.MakeSolid(solid); 
-       TopoDS_Shape aLocalShape = shell.Reversed();
-       B.Add(solid, TopoDS::Shell(aLocalShape));
-//     B.Add(solid, TopoDS::Shell(shell.Reversed()));
+        B.MakeSolid(solid); 
+        TopoDS_Shape aLocalShape = shell.Reversed();
+        B.Add(solid, TopoDS::Shell(aLocalShape));
+        //     B.Add(solid, TopoDS::Shell(shell.Reversed()));
       }
       myShape = solid;
 
@@ -472,12 +472,12 @@ void BRepOffsetAPI_ThruSections::CreateRuled()
 
   TopTools_IndexedDataMapOfShapeListOfShape MV;
   TopExp::MapShapesAndAncestors(shell, TopAbs_VERTEX, TopAbs_FACE, MV);
-  
+
   for (i=1; i<=nbSects-1; i++) {
-    
+
     const TopoDS_Wire& wire1 = TopoDS::Wire(myWires(i));
     const TopoDS_Wire& wire2 = TopoDS::Wire(myWires(i+1));
-    
+
     anExp1.Init(wire1);
     anExp2.Init(wire2);
 
@@ -489,51 +489,51 @@ void BRepOffsetAPI_ThruSections::CreateRuled()
       const TopoDS_Shape& edge2 = anExp2.Current();
       Standard_Boolean degen1 = BRep_Tool::Degenerated(anExp1.Current());
       Standard_Boolean degen2 = BRep_Tool::Degenerated(anExp2.Current());
-      
+
       TopTools_MapOfShape MapFaces;
       if (degen2){
-       TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge2));
-       for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
-         MapFaces.Add(it.Value());
-       }
+        TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge2));
+        for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
+          MapFaces.Add(it.Value());
+        }
       }
       else {
-       for (it.Initialize(M.FindFromKey(edge2)); it.More(); it.Next()) {
-         MapFaces.Add(it.Value());
-       }
+        for (it.Initialize(M.FindFromKey(edge2)); it.More(); it.Next()) {
+          MapFaces.Add(it.Value());
+        }
       }
-      
+
       if (degen1) {
-       TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge1));
-       for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
-         const TopoDS_Shape& Face = it.Value();
-         if (MapFaces.Contains(Face)) {
-           myGenerated.Bind(edge1, Face);
-           break;
-         }
-       }
+        TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge1));
+        for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
+          const TopoDS_Shape& Face = it.Value();
+          if (MapFaces.Contains(Face)) {
+            myGenerated.Bind(edge1, Face);
+            break;
+          }
+        }
       }
       else {
-       for (it.Initialize(M.FindFromKey(edge1)); it.More(); it.Next()) {
-         const TopoDS_Shape& Face = it.Value();
-         if (MapFaces.Contains(Face)) {
-           myGenerated.Bind(edge1, Face);
-           break;
-         }
-       }
+        for (it.Initialize(M.FindFromKey(edge1)); it.More(); it.Next()) {
+          const TopoDS_Shape& Face = it.Value();
+          if (MapFaces.Contains(Face)) {
+            myGenerated.Bind(edge1, Face);
+            break;
+          }
+        }
       }
-      
+
       if (!degen1) anExp1.Next();
       if (!degen2) anExp2.Next();
-      
+
       tantque = anExp1.More() && anExp2.More();
       if (degen1) tantque = anExp2.More();
       if (degen2) tantque = anExp1.More();
-      
+
     }
-      
+
   }
-      
+
 }
 
 //=======================================================================
@@ -593,15 +593,15 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
       // if the wire is punctual
       anExp.Init(TopoDS::Wire(wire));
       for(j=1; j<=nbEdges; j++) {
-       nb++;
-       shapes(nb) = anExp.Current();
+        nb++;
+        shapes(nb) = anExp.Current();
       }
     }
     else {
       // otherwise
       for(anExp.Init(TopoDS::Wire(wire)); anExp.More(); anExp.Next()) {
-       nb++;
-       shapes(nb) = anExp.Current();
+        nb++;
+        shapes(nb) = anExp.Current();
       }
     }
   }
@@ -624,7 +624,6 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
   TopLoc_Location loc;
   TopoDS_Vertex v1f,v1l,v2f,v2l;
 
-  GeomFill_SectionGenerator section;
   Standard_Integer nbPnts = 21;
   TColgp_Array2OfPnt points(1, nbPnts, 1, nbSects);
 
@@ -668,17 +667,17 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
 
     // make the wire
     B.MakeWire(W);
-    
+
     // make the missing edges
     Standard_Real f1, f2, l1, l2;
     surface->Bounds(f1,l1,f2,l2);
-  
+
     // --- edge 1
     if ( w1Point ) {
       // copy the degenerated edge
       TopoDS_Shape aLocalShape = shapes(1).EmptyCopied();
       edge1 =  TopoDS::Edge(aLocalShape);
-//      edge1 =  TopoDS::Edge(shapes(1).EmptyCopied());
+      //      edge1 =  TopoDS::Edge(shapes(1).EmptyCopied());
       edge1.Orientation(TopAbs_FORWARD);
     }
     else {
@@ -693,21 +692,21 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
     // store edges of the 1st section
     if (vClosed)
       vcouture(i) = edge1;
-    
+
 
     // --- edge 2
     if (vClosed)
       edge2 = TopoDS::Edge(vcouture(i));
     else {
       if ( w2Point ) {
-       // copy of the degenerated edge
-       TopoDS_Shape aLocalShape = shapes(nbSects*nbEdges).EmptyCopied();
-       edge2 =  TopoDS::Edge(aLocalShape);
-//     edge2 =  TopoDS::Edge(shapes(nbSects*nbEdges).EmptyCopied());
-       edge2.Orientation(TopAbs_FORWARD);
+        // copy of the degenerated edge
+        TopoDS_Shape aLocalShape = shapes(nbSects*nbEdges).EmptyCopied();
+        edge2 =  TopoDS::Edge(aLocalShape);
+        //     edge2 =  TopoDS::Edge(shapes(nbSects*nbEdges).EmptyCopied());
+        edge2.Orientation(TopAbs_FORWARD);
       }
       else {
-       B.MakeEdge(edge2, surface->VIso(l2), Precision::Confusion());
+        B.MakeEdge(edge2, surface->VIso(l2), Precision::Confusion());
       }
       v2f.Orientation(TopAbs_FORWARD);
       B.Add(edge2, v2f);
@@ -727,7 +726,7 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
       B.Add(edge3, v2f);
       B.Range(edge3, f2, l2);
       if (uClosed) {
-       couture = edge3;
+        couture = edge3;
       }
     }
     else {
@@ -756,34 +755,34 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
     // set PCurve
     if (vClosed) {
       B.UpdateEdge(edge1,
-                  new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),
-                  new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
-                  Precision::Confusion());
+        new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),
+        new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
+        Precision::Confusion());
       B.Range(edge1,face,f1,l1);
     }
     else {
       B.UpdateEdge(edge1,new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),face,
-                  Precision::Confusion());
+        Precision::Confusion());
       B.Range(edge1,face,f1,l1);
       B.UpdateEdge(edge2,new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
-                  Precision::Confusion());
+        Precision::Confusion());
       B.Range(edge2,face,f1,l1);
     }
 
     if ( uClosed && nbEdges ==1 )  {
       B.UpdateEdge(edge3,
-                  new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),
-                  new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
-                  Precision::Confusion());
+        new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),
+        new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
+        Precision::Confusion());
       B.Range(edge3,face,f2,l2);
 
     }
     else {
       B.UpdateEdge(edge3,new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
-                  Precision::Confusion());
+        Precision::Confusion());
       B.Range(edge3,face,f2,l2);
       B.UpdateEdge(edge4,new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),face,
-                  Precision::Confusion());
+        Precision::Confusion());
       B.Range(edge4,face,f2,l2);
     }
     B.Add(face,W);
@@ -812,15 +811,15 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
       BRep_Builder B;
       B.MakeSolid(solid); 
       B.Add(solid, shell);
-      
+
       // verify the orientation the solid
       BRepClass3d_SolidClassifier clas3d(solid);
       clas3d.PerformInfinitePoint(Precision::Confusion());
       if (clas3d.State() == TopAbs_IN) {
-       B.MakeSolid(solid); 
-       TopoDS_Shape aLocalShape = shell.Reversed();
-       B.Add(solid, TopoDS::Shell(aLocalShape));
-//     B.Add(solid, TopoDS::Shell(shell.Reversed()));
+        B.MakeSolid(solid); 
+        TopoDS_Shape aLocalShape = shell.Reversed();
+        B.Add(solid, TopoDS::Shell(aLocalShape));
+        //     B.Add(solid, TopoDS::Shell(shell.Reversed()));
       }
       myShape = solid;
 
@@ -837,7 +836,7 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
     myShape = shell;
     Done();
   }
-  
+
   TopExp_Explorer ex(myShape,TopAbs_EDGE);
   while (ex.More()) {
     const TopoDS_Edge& CurE = TopoDS::Edge(ex.Current());
@@ -855,12 +854,12 @@ void BRepOffsetAPI_ThruSections::CreateSmoothed()
 //=======================================================================
 
 Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
-                                   TotalSurf(const TopTools_Array1OfShape& shapes,
-                                            const Standard_Integer NbSects,
-                                            const Standard_Integer NbEdges,
-                                            const Standard_Boolean w1Point,
-                                            const Standard_Boolean w2Point,
-                                            const Standard_Boolean vClosed) const
+  TotalSurf(const TopTools_Array1OfShape& shapes,
+  const Standard_Integer NbSects,
+  const Standard_Integer NbEdges,
+  const Standard_Boolean w1Point,
+  const Standard_Boolean w2Point,
+  const Standard_Boolean vClosed) const
 {
   Standard_Integer i,j,jdeb=1,jfin=NbSects;
   TopoDS_Edge edge;
@@ -908,95 +907,96 @@ Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
       // read the first edge to initialise CompBS;
       edge =  TopoDS::Edge(shapes((j-1)*NbEdges+1));
       if (BRep_Tool::Degenerated(edge)) {
-       // degenerated edge : construction of a punctual curve
-       TopExp::Vertices(edge,vl,vf);
-       TColgp_Array1OfPnt Extremities(1,2);
-       Extremities(1) = BRep_Tool::Pnt(vf);
-       Extremities(2) = BRep_Tool::Pnt(vl);
-       Handle(Geom_Curve) curv = new Geom_BezierCurve(Extremities);
-       curvTrim = new Geom_TrimmedCurve(curv,
-                                        curv->FirstParameter(),
-                                        curv->LastParameter());
+        // degenerated edge : construction of a punctual curve
+        TopExp::Vertices(edge,vl,vf);
+        TColgp_Array1OfPnt Extremities(1,2);
+        Extremities(1) = BRep_Tool::Pnt(vf);
+        Extremities(2) = BRep_Tool::Pnt(vl);
+        Handle(Geom_Curve) curv = new Geom_BezierCurve(Extremities);
+        curvTrim = new Geom_TrimmedCurve(curv,
+          curv->FirstParameter(),
+          curv->LastParameter());
       }
       else {
-       // recover the curve on the edge
-       Handle(Geom_Curve) curv = BRep_Tool::Curve(edge, loc, first, last);
-       curvTrim = new Geom_TrimmedCurve(curv, first, last);
-       curvTrim->Transform(loc.Transformation());
+        // recover the curve on the edge
+
+        Handle(Geom_Curve) curv = BRep_Tool::Curve(edge, loc, first, last);
+        curvTrim = new Geom_TrimmedCurve(curv, first, last);
+        curvTrim->Transform(loc.Transformation());
       }
       if (edge.Orientation() == TopAbs_REVERSED) {
-       curvTrim->Reverse();
+        curvTrim->Reverse();
       }
 
       // transformation into BSpline reparameterized on [i-1,i]
       curvBS = Handle(Geom_BSplineCurve)::DownCast(curvTrim);
       if (curvBS.IsNull()) { 
-       Handle(Geom_Curve) theCurve = curvTrim->BasisCurve();
-       if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic)))
-         {
-           GeomConvert_ApproxCurve appr(curvTrim, Precision::Confusion(), GeomAbs_C1, 16, 14);
-           if (appr.HasResult())
-             curvBS = appr.Curve();
-         }
-       if (curvBS.IsNull())
-         curvBS = GeomConvert::CurveToBSplineCurve(curvTrim);
+        Handle(Geom_Curve) theCurve = curvTrim->BasisCurve();
+        if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic)))
+        {
+          GeomConvert_ApproxCurve appr(curvTrim, Precision::Confusion(), GeomAbs_C1, 16, 14);
+          if (appr.HasResult())
+            curvBS = appr.Curve();
+        }
+        if (curvBS.IsNull())
+          curvBS = GeomConvert::CurveToBSplineCurve(curvTrim);
       }
       TColStd_Array1OfReal BSK(1,curvBS->NbKnots());
       curvBS->Knots(BSK);
       BSplCLib::Reparametrize(0.,1.,BSK);
       curvBS->SetKnots(BSK);
-      
+
       // initialization
       GeomConvert_CompCurveToBSplineCurve CompBS(curvBS);
 
       for (i=2; i<=NbEdges; i++) {  
-       // read the edge
-       edge =  TopoDS::Edge(shapes((j-1)*NbEdges+i));
-       if (BRep_Tool::Degenerated(edge)) {
-         // degenerated edge : construction of a punctual curve
-         TopExp::Vertices(edge,vl,vf);
-         TColgp_Array1OfPnt Extremities(1,2);
-         Extremities(1) = BRep_Tool::Pnt(vf);
-         Extremities(2) = BRep_Tool::Pnt(vl);
-         Handle(Geom_Curve) curv = new Geom_BezierCurve(Extremities);
-         curvTrim = new Geom_TrimmedCurve(curv,
-                                          curv->FirstParameter(),
-                                          curv->LastParameter());
-       }
-       else {
-         // return the curve on the edge
-         Handle(Geom_Curve) curv = BRep_Tool::Curve(edge, loc, first, last);
-         curvTrim = new Geom_TrimmedCurve(curv, first, last);
-         curvTrim->Transform(loc.Transformation());
-       }
-       if (edge.Orientation() == TopAbs_REVERSED) {
-         curvTrim->Reverse();
-       }
-
-       // transformation into BSpline reparameterized on [i-1,i]
-       curvBS = Handle(Geom_BSplineCurve)::DownCast(curvTrim);
-       if (curvBS.IsNull()) { 
-         Handle(Geom_Curve) theCurve = curvTrim->BasisCurve();
-         if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic)))
-           {
-             GeomConvert_ApproxCurve appr(curvTrim, Precision::Confusion(), GeomAbs_C1, 16, 14);
-             if (appr.HasResult())
-               curvBS = appr.Curve();
-           }
-         if (curvBS.IsNull())
-           curvBS = GeomConvert::CurveToBSplineCurve(curvTrim);
-       }
-       TColStd_Array1OfReal BSK(1,curvBS->NbKnots());
-       curvBS->Knots(BSK);
-       BSplCLib::Reparametrize(i-1,i,BSK);
-       curvBS->SetKnots(BSK);
-
-       // concatenation
-       CompBS.Add(curvBS, 
-                  Precision::Confusion(),
-                  Standard_True,
-                  Standard_False,
-                  1);
+        // read the edge
+        edge =  TopoDS::Edge(shapes((j-1)*NbEdges+i));
+        Standard_Real aTolV = Precision::Confusion();  
+        TopExp::Vertices(edge,vf,vl);
+        aTolV = Max(aTolV, BRep_Tool::Tolerance(vf));
+        aTolV = Max(aTolV, BRep_Tool::Tolerance(vl));
+        aTolV = Min(aTolV, 1.e-3);
+        if (BRep_Tool::Degenerated(edge)) {
+          // degenerated edge : construction of a punctual curve
+          TColgp_Array1OfPnt Extremities(1,2);
+          Extremities(1) = BRep_Tool::Pnt(vf);
+          Extremities(2) = BRep_Tool::Pnt(vl);
+          Handle(Geom_Curve) curv = new Geom_BezierCurve(Extremities);
+          curvTrim = new Geom_TrimmedCurve(curv,
+            curv->FirstParameter(),
+            curv->LastParameter());
+        }
+        else {
+          // return the curve on the edge
+          Handle(Geom_Curve) curv = BRep_Tool::Curve(edge, loc, first, last);
+          curvTrim = new Geom_TrimmedCurve(curv, first, last);
+          curvTrim->Transform(loc.Transformation());
+        }
+        if (edge.Orientation() == TopAbs_REVERSED) {
+          curvTrim->Reverse();
+        }
+
+        // transformation into BSpline reparameterized on [i-1,i]
+        curvBS = Handle(Geom_BSplineCurve)::DownCast(curvTrim);
+        if (curvBS.IsNull()) { 
+          Handle(Geom_Curve) theCurve = curvTrim->BasisCurve();
+          if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic)))
+          {
+            GeomConvert_ApproxCurve appr(curvTrim, Precision::Confusion(), GeomAbs_C1, 16, 14);
+            if (appr.HasResult())
+              curvBS = appr.Curve();
+          }
+          if (curvBS.IsNull())
+            curvBS = GeomConvert::CurveToBSplineCurve(curvTrim);
+        }
+        TColStd_Array1OfReal BSK(1,curvBS->NbKnots());
+        curvBS->Knots(BSK);
+        BSplCLib::Reparametrize(i-1,i,BSK);
+        curvBS->SetKnots(BSK);
+
+        // concatenation
+        CompBS.Add(curvBS, aTolV, Standard_True, Standard_False, 1);
       }
 
       // return the final section
@@ -1005,7 +1005,7 @@ Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
 
       // case of looping sections
       if (j==jdeb && vClosed) {
-       BS1 = BS;
+        BS1 = BS;
       }
 
     }
@@ -1053,13 +1053,13 @@ Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
   if(anApprox.IsDone()) {
     surface = 
       new Geom_BSplineSurface(anApprox.SurfPoles(), anApprox.SurfWeights(),
-                           anApprox.SurfUKnots(), anApprox.SurfVKnots(),
-                           anApprox.SurfUMults(), anApprox.SurfVMults(),
-                           anApprox.UDegree(), anApprox.VDegree());
+      anApprox.SurfUKnots(), anApprox.SurfVKnots(),
+      anApprox.SurfUMults(), anApprox.SurfVMults(),
+      anApprox.UDegree(), anApprox.VDegree());
   }
 
   return surface;
-  
+
 }
 
 //=======================================================================
index 9b0fd11dfa651d4b6ae735dcf5be09b49f7ec7fb..ed7ea181b8fc6419825455d53f5dd2f59ef241e2 100644 (file)
@@ -5,8 +5,8 @@
 //
 // This file is part of Open CASCADE Technology software library.
 //
-// This library is free software; you can redistribute it and / or modify it
-// under the terms of the GNU Lesser General Public version 2.1 as published
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
 // by the Free Software Foundation, with special exception defined in the file
 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 // distribution for complete text of the license and disclaimer of any warranty.
@@ -20,6 +20,7 @@
 #include <BRepToIGES_BRShell.ixx>
 #include <BRepToIGES_BRWire.hxx>
 
+#include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
 #include <BRepTools.hxx>
 
@@ -33,6 +34,7 @@
 #include <Geom_Surface.hxx>
 #include <Geom_SurfaceOfRevolution.hxx>
 #include <Geom_ToroidalSurface.hxx>
+#include <Geom2d_Curve.hxx>
 
 #include <GeomToIGES_GeomSurface.hxx>
 
 
 #include <Interface_Macros.hxx>
 
+#include <NCollection_Map.hxx>
+#include <NCollection_IncAllocator.hxx>
+
 #include <TColStd_HSequenceOfTransient.hxx>
 
 #include <TopLoc_Location.hxx>
 
+#include <TopTools_ShapeMapHasher.hxx>
+
 #include <TopoDS.hxx>
 #include <TopoDS_Vertex.hxx>
 #include <TopoDS_Edge.hxx>
@@ -132,6 +139,74 @@ Handle(IGESData_IGESEntity) BRepToIGES_BRShell ::TransferFace(const TopoDS_Face&
   if ( start.IsNull()) {
     return res;
   }
+
+  // pour explorer la face , il faut la mettre fORWARD.
+  TopoDS_Face myface;
+  if (start.Orientation() == TopAbs_REVERSED) {
+    //create face with redirected surface
+    BRep_Builder B;
+    TopLoc_Location aLoc;
+    Handle(Geom_Surface) aSurf = BRep_Tool::Surface(start, aLoc);
+    aSurf = aSurf->UReversed();
+    Standard_Real U1, U2, V1, V2;
+    aSurf->Bounds(U1, U2, V1, V2);
+    Standard_Real aTol = BRep_Tool::Tolerance(start);
+    B.MakeFace(myface, aSurf, aLoc ,aTol);
+    // set specifics flags of a Face
+         B.NaturalRestriction(myface, BRep_Tool::NaturalRestriction(start));
+    //add wires
+    TopoDS_Wire anOuter = TopoDS::Wire(ShapeAlgo::AlgoContainer()->OuterWire(start));
+    TopExp_Explorer ex;
+    for (ex.Init(start,TopAbs_WIRE); ex.More(); ex.Next()) {
+      TopoDS_Wire W = TopoDS::Wire(ex.Current());
+      if (!W.IsNull() && W.IsSame(anOuter)) {
+        B.Add(myface, W);
+        break;
+      }
+    }     
+    for (ex.Init(start,TopAbs_WIRE); ex.More(); ex.Next()) {
+      TopoDS_Wire W = TopoDS::Wire(ex.Current());
+      if (!W.IsNull() && !W.IsSame(anOuter)) {
+        B.Add(myface, W);
+      }
+    }
+    // mirror pcurves
+    NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher> aMap (101, new NCollection_IncAllocator);
+    for (ex.Init(myface,TopAbs_EDGE);ex.More(); ex.Next()) {
+      TopoDS_Edge anEdge = TopoDS::Edge(ex.Current());
+      if (!aMap.Add(anEdge))
+        // seam edge has been already updated
+        continue;
+      Standard_Real f, l;
+      Handle(Geom2d_Curve) aCurve1, aCurve2;
+      aCurve1 = BRep_Tool::CurveOnSurface(anEdge, start, f, l);
+      aTol = BRep_Tool::Tolerance(anEdge);
+      gp_Trsf2d T;
+      gp_Ax2d axis(gp_Pnt2d(0.5 * (U1 + U2), V1), gp_Dir2d(0.,1.));
+      T.SetMirror(axis);
+      if (!aCurve1.IsNull()) {
+        aCurve1 = Handle(Geom2d_Curve)::DownCast(aCurve1->Transformed(T));
+        if (BRepTools::IsReallyClosed(anEdge, start)) {
+          TopoDS_Edge revEdge = TopoDS::Edge(anEdge.Reversed());
+          aCurve2 = BRep_Tool::CurveOnSurface(revEdge, start, f, l);
+          if (!aCurve2.IsNull()) {
+            aCurve2 = Handle(Geom2d_Curve)::DownCast(aCurve2->Transformed(T));
+            B.UpdateEdge(anEdge, aCurve1, aCurve2, myface, aTol);
+          }
+          else {
+            B.UpdateEdge(anEdge, aCurve1, myface, aTol);
+          }
+        }
+        else {
+          B.UpdateEdge(anEdge, aCurve1, myface, aTol);
+        }
+      }
+    }
+  }
+  else {
+    myface = start;
+  }
+
   //Standard_Integer Nb = 0; //szv#4:S4163:12Mar99 unused
   Standard_Real Length = 1.;
   Handle(IGESData_IGESEntity) ISurf;
@@ -139,13 +214,13 @@ Handle(IGESData_IGESEntity) BRepToIGES_BRShell ::TransferFace(const TopoDS_Face&
   // returns the face surface
   // ------------------------
 
-  Handle(Geom_Surface) Surf = BRep_Tool::Surface(start);
+  Handle(Geom_Surface) Surf = BRep_Tool::Surface(myface);
   Handle(Geom_Surface) Surf1;
 
   if (!Surf.IsNull()) {
     Standard_Real U1, U2, V1, V2;
     // pour limiter les surfaces de base
-    BRepTools::UVBounds(start, U1, U2, V1, V2); 
+    BRepTools::UVBounds(myface, U1, U2, V1, V2);  
     GeomToIGES_GeomSurface GS;
     GS.SetModel(GetModel());
     ISurf = GS.TransferSurface(Surf, U1, U2, V1, V2);
@@ -172,16 +247,9 @@ Handle(IGESData_IGESEntity) BRepToIGES_BRShell ::TransferFace(const TopoDS_Face&
   Standard_Integer Imode = 0; 
   Standard_Integer Iprefer = 0; 
   Handle(IGESData_IGESEntity) ICurve2d;
-  // pour explorer la face , il faut la mettre fORWARD.
-  TopoDS_Face myface = start;
-  Standard_Boolean IsReversed = Standard_False;
-  if (start.Orientation() == TopAbs_REVERSED) {
-    myface.Reverse();
-    IsReversed = Standard_True;
-  }
 
   // outer wire
-//:n3  TopoDS_Wire Outer = BRepTools::OuterWire(myface);
+  //:n3  TopoDS_Wire Outer = BRepTools::OuterWire(myface);
   TopoDS_Wire Outer = ShapeAlgo::AlgoContainer()->OuterWire(myface); //:n3 
   Handle(IGESGeom_CurveOnSurface) IOuter = new IGESGeom_CurveOnSurface;
   if (!Outer.IsNull()) {
@@ -205,7 +273,7 @@ Handle(IGESData_IGESEntity) BRepToIGES_BRShell ::TransferFace(const TopoDS_Face&
     }
     else if (!W.IsSame(Outer)) {
       Handle(IGESData_IGESEntity) ICurve3d = 
-       BW.TransferWire(W, myface, ICurve2d, Length);
+             BW.TransferWire(W, myface, ICurve2d, Length);
       if ((!ICurve3d.IsNull()) && (!ICurve2d.IsNull())) Iprefer = 3; 
       if ((!ICurve3d.IsNull()) && (ICurve2d.IsNull())) Iprefer = 2; 
       if ((ICurve3d.IsNull()) && (!ICurve2d.IsNull())) Iprefer = 1; 
@@ -256,10 +324,7 @@ Handle(IGESData_IGESEntity) BRepToIGES_BRShell ::TransferFace(const TopoDS_Face&
     TrimmedSurf-> Init (ISurf, Flag, IOuter, Tab);
 
   res = TrimmedSurf;
-  if (IsReversed) myface.Reverse();
-
   SetShapeResult ( start, res );
-
   return res;
 }
 
index 25fbd446b4d11653c7ed6e32ef9b4769003b8bbf..b7a4f87d6c05c80a3ea952ed864b745c1234906c 100644 (file)
@@ -32,6 +32,7 @@
 #include <gp_Trsf.hxx>
 #include <gp_Trsf2d.hxx>
 
+#include <Geom_BSplineSurface.hxx>
 #include <Geom_CartesianPoint.hxx>
 #include <Geom_ConicalSurface.hxx>
 #include <Geom_Curve.hxx>
@@ -64,6 +65,8 @@
 
 #include <Precision.hxx>
 
+#include <ShapeAnalysis.hxx>
+
 #include <TColStd_HSequenceOfTransient.hxx>
 
 #include <TopoDS.hxx>
@@ -390,6 +393,25 @@ Handle(IGESData_IGESEntity) BRepToIGES_BRWire ::TransferEdge (const TopoDS_Edge&
     }
     else Curve2d = Handle(Geom2d_Curve)::DownCast(Curve2d->Copy());
 
+    //shift pcurves on periodic BSpline surfaces (issue 26138)
+    if (Surf->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) {
+      Handle(Geom_BSplineSurface) aBSpline = Handle(Geom_BSplineSurface)::DownCast(Surf);
+      Standard_Real uShift = 0., vShift = 0.;
+      Standard_Real U0, U1, V0, V1;
+      Surf->Bounds(U0, U1, V0, V1);
+      if (aBSpline->IsUPeriodic() && Abs(Ufirst - U0) > Precision::PConfusion()) {
+        uShift = ShapeAnalysis::AdjustToPeriod(Ufirst, U0, U1);
+      }
+      if (aBSpline->IsVPeriodic() && Abs(Vfirst - V0) > Precision::PConfusion()) {
+        vShift = ShapeAnalysis::AdjustToPeriod(Vfirst, V0, V1);
+      }
+      if (Abs(uShift) > Precision::PConfusion() || Abs(vShift) > Precision::PConfusion()) {
+        gp_Trsf2d TR;
+        TR.SetTranslation(gp_Pnt2d(0.,0.),gp_Pnt2d(uShift,vShift));
+        Curve2d = Handle(Geom2d_Curve)::DownCast(Curve2d->Transformed(TR));
+      }
+    }
+
     if (!analyticMode&&((Surf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)))  ||
                        (Surf->IsKind(STANDARD_TYPE(Geom_ConicalSurface)))      ||
                        (Surf->IsKind(STANDARD_TYPE(Geom_SphericalSurface))))) {
index 2d514ce18da1723dbdd4368cceb4a4ac1a077c30..0eb2856b732aac16c273a28d1c2479ad379605b5 100644 (file)
@@ -61,6 +61,8 @@
 #include <BRep_TEdge.hxx>
 #include <BRep_GCurve.hxx>
 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
+#include <TopExp_Explorer.hxx>
+#include <Geom2d_Line.hxx>
 
 static void GeomLib_ChangeUBounds(Handle(Geom_BSplineSurface)& aSurface,
                   const Standard_Real newU1,
@@ -152,7 +154,39 @@ Standard_Boolean BRepTools_NurbsConvertModification::NewSurface
   {
     Standard_Real Up = S->UPeriod();
     if (U2 - U1 > Up)
+    {
+      //Try to define "exact" U1 according to pcurve of seem edge
+      TopExp_Explorer anExp(F, TopAbs_EDGE);
+      for(; anExp.More(); anExp.Next())
+      {
+        const TopoDS_Edge& anE = TopoDS::Edge(anExp.Current());
+        if(BRep_Tool::IsClosed(anE, F))
+        {
+          Standard_Real f, l;
+          Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(anE, F, f, l);
+          Handle(Standard_Type) aType = aC2d->DynamicType();
+          if(aType == STANDARD_TYPE(Geom2d_TrimmedCurve))
+          {
+            Handle(Geom2d_TrimmedCurve) aC2dT = Handle(Geom2d_TrimmedCurve)::DownCast(aC2d);
+            aC2d = aC2dT->BasisCurve();
+            aType = aC2d->DynamicType();
+          }
+          if(aType == STANDARD_TYPE(Geom2d_Line))
+          {
+            Handle(Geom2d_Line) aLin = Handle(Geom2d_Line)::DownCast(aC2d);
+            gp_XY anYDir(0., 1.);
+            gp_XY aD = aLin->Direction().XY();
+            if(aD.IsEqual(anYDir, Precision::Confusion()) ||
+               aD.IsEqual(-anYDir, Precision::Confusion())  )
+            {
+              U1 = aLin->Location().X();
+              break;
+            }
+          }
+        }
+      }
       U2 = U1 + Up;
+    }
   }
   if (IsVp)
   {
@@ -494,7 +528,7 @@ Standard_Boolean BRepTools_NurbsConvertModification::NewCurve2d
       TopoDS_Edge ERevers = E;
       ERevers.Reverse();
       C2dBis = BRep_Tool::CurveOnSurface(ERevers,F,f2dBis,l2dBis);
-      Handle(Standard_Type) TheTypeC2dBis = C2dBis->DynamicType();
+      //Handle(Standard_Type) TheTypeC2dBis = C2dBis->DynamicType();
       C2dBis = new Geom2d_TrimmedCurve(C2dBis,f2dBis, l2dBis);
       Geom2dAdaptor_Curve   G2dACBis(C2dBis, f2dBis, l2dBis); 
       Handle(Geom2dAdaptor_HCurve) G2dAHCBis = new Geom2dAdaptor_HCurve(G2dACBis);
@@ -568,7 +602,9 @@ Standard_Boolean BRepTools_NurbsConvertModification::NewCurve2d
       }
       else {
         Curve2d = Geom2dConvert::CurveToBSplineCurve(C2d);
-        mylcu.Append(C2dBis);
+        //mylcu.Append(C2dBis);
+        Handle(Geom2d_Curve) aC2dBisBspl = Geom2dConvert::CurveToBSplineCurve(C2dBis);
+        mylcu.Append(aC2dBisBspl);
         return Standard_True;
       }
     }
index 1872775ced30019495a8b3737616a48b36f7409a..1025c35f30417b26c8a801effc825778ed285802 100644 (file)
@@ -65,6 +65,8 @@ void DsgPrs_DiameterPresentation::Add (const Handle(Prs3d_Presentation)& aPresen
   // sideline
   gp_Pnt        center  = aCircle.Location();
   gp_Vec        vecrap  (ptoncirc,center);
+  if (vecrap.SquareMagnitude() < Precision::Confusion())
+    return;
 
   Standard_Real dist    = center.Distance(AttachmentPoint);
   Standard_Real aRadius = aCircle.Radius();
index adb948335adcdc84b1f87db5c3e6ca1b4a0dc691..77d2617eb0071d78bdba877dd8dbb6d04e1934d6 100644 (file)
@@ -865,16 +865,31 @@ Handle(BSplineSurface) GeomConvert::SplitBSplineSurface
 
     else { // In other cases => Approx
       Standard_Real Tol3d=1.e-4;
-      Standard_Integer MaxDegree =14, MaxSeg;
-      GeomAbs_Shape cont;
+      Standard_Integer MaxDegree = 14, MaxSeg;
+      GeomAbs_Shape ucont = GeomAbs_C0, vcont = GeomAbs_C0;
       GeomAdaptor_Surface AS(Sr);
-      if (AS.NbUIntervals(GeomAbs_C2) > 1 || AS.NbVIntervals(GeomAbs_C2) > 1 ) 
-         cont=GeomAbs_C1;
-      else
-         cont=GeomAbs_C2;
+      //
+      if (Sr->IsCNu(2)) 
+      {
+        ucont=GeomAbs_C2;
+      }
+      else if(Sr->IsCNu(1)) 
+      {
+        ucont=GeomAbs_C1;
+      }
+      //
+      if (Sr->IsCNv(2)) 
+      {
+        vcont=GeomAbs_C2;
+      }
+      else if(Sr->IsCNv(1)) 
+      {
+        vcont=GeomAbs_C1;
+      }
+      //
       MaxSeg = 4*(AS.NbUIntervals(GeomAbs_CN)+1)*(AS.NbVIntervals(GeomAbs_CN)+1);      
-      GeomConvert_ApproxSurface BSpS(Sr,Tol3d,cont,cont,
-                                    MaxDegree,MaxDegree,MaxSeg,1);
+      GeomConvert_ApproxSurface BSpS(Sr, Tol3d, ucont, vcont,
+                                     MaxDegree, MaxDegree, MaxSeg, 1);
       TheSurface = BSpS.Surface();
     }
   } // Fin du cas direct
index d0f7ebc9741dad9823e08bb927049a7ed6019377..a0ea3fda5fe3059f5f1ee0578cfcea6804c4c691 100644 (file)
@@ -31,6 +31,7 @@
 #include <gp_GTrsf.hxx>
 #include <gp_Mat.hxx>
 #include <gp_Ax2.hxx>
+#include <gp_Sphere.hxx>
 
 #include <TColgp_Array1OfPnt.hxx>
 #include <TColgp_Array2OfPnt.hxx>
@@ -59,6 +60,7 @@
 #include <Geom_SphericalSurface.hxx>
 #include <Geom_SurfaceOfRevolution.hxx>
 #include <Geom_RectangularTrimmedSurface.hxx>
+#include <Geom_TrimmedCurve.hxx>
 
 #include <Approx_SweepApproximation.hxx>
 #include <AdvApprox_PrefAndRec.hxx>
@@ -67,6 +69,7 @@
 
 #include <Precision.hxx>
 #include <ElCLib.hxx>
+#include <ElSLib.hxx>
 
 //=======================================================================
 //class : GeomFill_Sweep_Eval
@@ -845,25 +848,33 @@ static Standard_Boolean IsSweepParallelSpine (const Handle(GeomFill_LocationLaw)
            Standard_Real f = UFirst , l =  ULast;
            SError = error;
            Centre.BaryCenter(1.0, C.Location(), 1.0); 
-           gp_Ax3 AxisOfSphere(Centre, DN, DS);  
-           S = new (Geom_SphericalSurface) 
-             (AxisOfSphere, (RotRadius + C.Radius())/2 );
+           gp_Ax3 AxisOfSphere(Centre, DN, DS);
+            gp_Sphere theSphere( AxisOfSphere, (RotRadius + C.Radius())/2 );
+           S = new Geom_SphericalSurface(theSphere);
            // Pour les spheres on ne peut pas controler le parametre
             // V (donc U car  myExchUV = Standard_True)
             // Il faut donc modifier UFirst, ULast...
-           if (C.Position().Direction().
-               IsOpposite(AxisOfSphere.YDirection(), 0.1) ) {
+            Standard_Real fpar = AC.FirstParameter();
+            Standard_Real lpar = AC.LastParameter();
+            Handle(Geom_Curve) theSection = new Geom_TrimmedCurve(Section, fpar, lpar);
+            theSection->Transform(Tf2);
+            gp_Pnt FirstPoint = theSection->Value(theSection->FirstParameter());
+            gp_Pnt LastPoint  = theSection->Value(theSection->LastParameter());
+            Standard_Real UfirstOnSec, VfirstOnSec, UlastOnSec, VlastOnSec;
+            ElSLib::Parameters(theSphere, FirstPoint, UfirstOnSec, VfirstOnSec);
+            ElSLib::Parameters(theSphere, LastPoint, UlastOnSec, VlastOnSec);
+            if (VfirstOnSec < VlastOnSec)
+            {
+              f = VfirstOnSec;
+              l = VlastOnSec;
+            }
+            else
+            {
              // L'orientation parametrique est inversee
-             l = 2*M_PI - UFirst;
-             f = 2*M_PI - ULast;
+              f = VlastOnSec;
+              l = VfirstOnSec;
              isUReversed = Standard_True;
            }
-           // On calcul le "glissement" parametrique.
-           Standard_Real rot; 
-           rot = C.Position().XDirection().AngleWithRef
-             (AxisOfSphere.XDirection(), AxisOfSphere.YDirection());
-           f -= rot;
-           l  -= rot;
 
            if ( (f >= -M_PI/2) && (l <= M_PI/2)) {
              Ok = Standard_True;
index 3dfc3ef5e52ab9e69a4b4e1fac24a366bd3233ab..54dd65ac9c74fed0ec2df218c71de8ddfb2fc415 100644 (file)
 
 #include <Precision.hxx>
 
+#include <ShapeAnalysis.hxx>
+#include <Standard_Failure.hxx>
+#include <Standard_ErrorHandler.hxx>
+
 #include <TColgp_HArray2OfXYZ.hxx>
 #include <TColStd_HArray1OfReal.hxx>
 #include <TColStd_HArray2OfReal.hxx>
@@ -244,29 +248,90 @@ Handle(IGESData_IGESEntity) GeomToIGES_GeomSurface::TransferSurface(const Handle
   
   Standard_Boolean PeriodU = start->IsUPeriodic();
   Standard_Boolean PeriodV = start->IsVPeriodic();
-  if (PeriodU || PeriodV) {
-    mysurface = Handle(Geom_BSplineSurface)::DownCast(start->Copy());
-
-    //szv#10:PRO19566:05Oct99
-    Standard_Boolean workaround = !(mysurface->IsURational() || mysurface->IsVRational());
-    if (workaround) mysurface->SetWeight(1,1,0.3);
-
-    if ( PeriodU ) mysurface->SetUNotPeriodic();
-    if ( PeriodV ) mysurface->SetVNotPeriodic();
-
-    //szv#10:PRO19566:05Oct99
-    if (workaround) mysurface->SetWeight(1,1,1.);
+  mysurface = Handle(Geom_BSplineSurface)::DownCast(start->Copy());
+
+  Standard_Real Umin = Udeb, Umax = Ufin, Vmin = Vdeb, Vmax = Vfin;
+  Standard_Real U0,U1,V0,V1;
+  Standard_Real uShift = 0, vShift = 0;
+  mysurface->Bounds(U0,U1,V0,V1);
+
+  // cut segment from periodic surfaces for syncronization of pcurves ranges
+  // and surface bounds (issue 26138)
+  if (!PeriodU) {
+    if (Umin < U0)
+      Umin = U0;
+    if (U1 < Umax)
+      Umax = U1;
   }
   else {
-    mysurface = start;
+    if (Abs(Umin - U0) < Precision::PConfusion())
+      Umin = U0;
+    if (Abs(Umax - U1) < Precision::PConfusion())
+      Umax = U1;
+    uShift = ShapeAnalysis::AdjustToPeriod(Umin, U0, U1);
+    Umin += uShift;
+    Umax += uShift;
   }
+  if (!PeriodV) {
+    if (Vmin < V0)
+      Vmin = V0;
+    if (V1 < Vmax)
+      Vmax = V1;
+  }
+  else {
+    if (Abs(Vmin - V0) < Precision::PConfusion())
+      Vmin = V0;
+    if (Abs(Vmax - V1) < Precision::PConfusion())
+      Vmax = V1;
+    vShift = ShapeAnalysis::AdjustToPeriod(Vmin, V0, V1);
+    Vmin += vShift;
+    Vmax += vShift;
+  }
+  if ( Abs(uShift) > Precision::PConfusion() || Abs(vShift) > Precision::PConfusion()) {
+    Standard_Boolean isNeedSegment = Standard_True;
+    isNeedSegment = Abs(Umax-Umin) > Precision::PConfusion() && 
+                    Abs(Vmax-Vmin) > Precision::PConfusion();
+    Standard_Real uMaxShift = 0, vMaxShift = 0;
+    uMaxShift = ShapeAnalysis::AdjustToPeriod(Ufin, U0, U1);
+    vMaxShift = ShapeAnalysis::AdjustToPeriod(Vfin, V0, V1);
+    isNeedSegment &= 
+      (PeriodU && Abs(uShift - uMaxShift) > Precision::PConfusion()) ||
+      (PeriodV && Abs(vShift - vMaxShift) > Precision::PConfusion());           
+    if (isNeedSegment) {
+      try {
+        OCC_CATCH_SIGNALS
+        Handle(Geom_BSplineSurface) bspl = Handle(Geom_BSplineSurface)::DownCast ( start->Copy() );
+        if ( ! bspl.IsNull() ) {
+          bspl->CheckAndSegment(Umin, Umax, Vmin, Vmax);
+          if ((U1 - U0) - (Umax - Umin) > Precision::PConfusion())
+            PeriodU = Standard_False;
+          if ((V1 - V0) - (Vmax - Vmin) > Precision::PConfusion())
+            PeriodV = Standard_False;
+               mysurface = bspl;
+        }
+      }
+      catch ( Standard_Failure ) {
+        #ifdef DEB
+        cout << "Warning: GeomToIGES_GeomSurface: can't trim bspline" << endl;
+        cout << "Warning: Exception in Segment(): " ;
+        Standard_Failure::Caught()->Print(cout);
+        #endif
+    }
+    }
+  }
+
+  //unperiodize surface to get neccessary for IGES standard number of knots and mults
+  if ( mysurface->IsUPeriodic() ) {
+    mysurface->SetUNotPeriodic();
+  }
+  if ( mysurface->IsVPeriodic() ) {
+    mysurface->SetVNotPeriodic();
+  } 
+
   Standard_Integer DegU = mysurface->UDegree();
   Standard_Integer DegV = mysurface->VDegree();
   Standard_Boolean CloseU = mysurface->IsUClosed();
   Standard_Boolean CloseV = mysurface->IsVClosed();
-  //Standard_Boolean PeriodU = start->IsUPeriodic();
-  //Standard_Boolean PeriodV = start->IsVPeriodic();
   Standard_Boolean RationU = mysurface->IsURational();
   Standard_Boolean RationV = mysurface->IsVRational();
   Standard_Integer NbUPoles = mysurface->NbUPoles();
@@ -349,18 +414,6 @@ Handle(IGESData_IGESEntity) GeomToIGES_GeomSurface::TransferSurface(const Handle
     VIndex = Poles->LowerCol();
   }
       
-  // mjm le 9/10/97 mise en place d`une protection
-  Standard_Real U1,U2,V1,V2;
-  Standard_Real Umin = Udeb;
-  Standard_Real Umax = Ufin;
-  Standard_Real Vmin = Vdeb;
-  Standard_Real Vmax = Vfin;
-  mysurface->Bounds(U1,U2,V1,V2);
-  if ( U1 > Umin ) Umin = U1;
-  if ( V1 > Vmin ) Vmin = V1;
-  if ( U2 < Umax ) Umax = U2;
-  if ( V2 < Vmax ) Vmax = V2;
-
   BSpline-> Init (IndexU, IndexV, DegU, DegV, CloseU, CloseV, Polynom, PeriodU, 
                  PeriodV, KnotsU, KnotsV, Weights, Poles, Umin, Umax, Vmin, Vmax);
   res = BSpline;
index 4c6b7081b032ab096ecd61c50184e7f2db2be9e0..71ec72cd5b6172f3dd003002ab3528fcb985169e 100644 (file)
@@ -5,8 +5,8 @@
 --
 -- This file is part of Open CASCADE Technology software library.
 --
--- This library is free software; you can redistribute it and / or modify it
--- under the terms of the GNU Lesser General Public version 2.1 as published
+-- This library is free software; you can redistribute it and/or modify it under
+-- the terms of the GNU Lesser General Public License version 2.1 as published
 -- by the Free Software Foundation, with special exception defined in the file
 -- OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 -- distribution for complete text of the license and disclaimer of any warranty.
@@ -20,7 +20,7 @@ package MAT2d
         --           Set of geometrys from Geom2d.
 
 uses
-
+    GeomAbs,
     MMgt,
     gp,
     Geom2d,
@@ -34,35 +34,18 @@ uses
 is
 
     deferred class SketchExplorer;
-       ---Purpose: SletchExplorer contains an iterator on a set of geometrys 
-       --          from Geom2d. It's use by BisectingLocus.
-     
-    generic class BisectingLocus;
-       ---Purpose: Constuction of the map of the bisector locus on a
-       --          set of geometrys from Geom2d.
-    
+
     class Tool2d;
-       ---Purpose: Tool2d contains  the geometrys of  the map. Tool2d
-       --          contains the set  of the geometric's methode  used for 
-        --          the map's  computation.
 
-    class Mat2d instantiates Mat from MAT (Tool2d);
+    class Mat2d;
 
     class Connexion;
-       ---Purpose: a Connexion links two lines.  
 
     class MiniPath;
-        ---Purpose: MiniPath computes one minimum path  to link all the
-        --          lines of a set. 
-                               
+
     class Circuit;
-       ---Purpose: EquiCircuit gives a Circuit passing by all the lines
-       --          in a set and all the connexions of the minipath associated.
-           
+
     class CutCurve;   
-       ---Purpose: Cuts a curve at the extremas of curvature
-       --          and at the inflections. Constructs a trimmed
-       --          Curve for each interval.
 
     class SequenceOfConnexion instantiates Sequence  from TCollection
                                                     (Connexion from  MAT2d); 
index 639aaba367476fe0cb950d1affc0337cee36fea7..6cbb70bd00f8a77ad796634a37ed615ce8b4c96b 100644 (file)
@@ -5,8 +5,8 @@
 --
 -- This file is part of Open CASCADE Technology software library.
 --
--- This library is free software; you can redistribute it and / or modify it
--- under the terms of the GNU Lesser General Public version 2.1 as published
+-- This library is free software; you can redistribute it and/or modify it under
+-- the terms of the GNU Lesser General Public License version 2.1 as published
 -- by the Free Software Foundation, with special exception defined in the file
 -- OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 -- distribution for complete text of the license and disclaimer of any warranty.
@@ -21,11 +21,12 @@ inherits
     TShared from MMgt
     
        ---Purpose: Constructs a circuit on a set of lines.
-       --          
+       --          EquiCircuit gives a Circuit passing by all the lines
+       --          in a set and all the connexions of the minipath associated.
        --           
 
 uses
-
+    JoinType                         from GeomAbs,
     SequenceOfInteger                from TColStd,
     Geometry                         from Geom2d,
     SequenceOfGeometry               from TColGeom2d,
@@ -40,7 +41,9 @@ uses
 
 is
 
-    Create returns mutable Circuit from MAT2d;
+    Create(aJoinType    : JoinType from GeomAbs  = GeomAbs_Arc;
+          IsOpenResult : Boolean  from Standard = Standard_False)
+    returns Circuit from MAT2d;
 
 ---Category:  Computation
 
@@ -51,6 +54,11 @@ is
             Trigo       :        Boolean)
     is static;     
     
+    IsSharpCorner(me; Geom1, Geom2 : Geometry from Geom2d;
+                     Direction : Real from Standard)
+    returns Boolean
+    is static private;
+    
     PassByLast(me ; C1,C2 : Connexion from MAT2d) 
     returns Boolean
     is static private;
@@ -75,7 +83,7 @@ is
     DoubleLine(me ; 
                Line       : in out  SequenceOfGeometry;
                Connexions : in out  SequenceOfConnexion from MAT2d; 
-              Father     : mutable Connexion from MAT2d;
+              Father     : Connexion from MAT2d;
               Side       : Real)
     is static private;
     
@@ -128,6 +136,8 @@ fields
     connexionMap : DataMapOfIntegerConnexion       from MAT2d;
     linkRefEqui  : DataMapOfBiIntSequenceOfInteger from MAT2d;
     linesLength  : SequenceOfInteger               from TColStd; 
+    myJoinType     : JoinType from GeomAbs;
+    myIsOpenResult : Boolean  from Standard;
     
 end Circuit;
 
index cac7673ed02dd98e80088d94edd5e1890f242fd9..7e4c702e59fc7ca6be103bed890bff66bb24d55f 100644 (file)
@@ -5,8 +5,8 @@
 //
 // This file is part of Open CASCADE Technology software library.
 //
-// This library is free software; you can redistribute it and / or modify it
-// under the terms of the GNU Lesser General Public version 2.1 as published
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
 // by the Free Software Foundation, with special exception defined in the file
 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 // distribution for complete text of the license and disclaimer of any warranty.
@@ -67,16 +67,16 @@ static Standard_Real CrossProd(const Handle(Geom2d_Geometry)& Geom1,
                               const Handle(Geom2d_Geometry)& Geom2,
                                     Standard_Real&           DotProd);
 
-static Standard_Boolean IsSharpCorner (const Handle(Geom2d_Geometry)& Geom1,
-                                      const Handle(Geom2d_Geometry)& Geom2,
-                                      const Standard_Real&           Direction);
 
 //=============================================================================
 //function : Constructor
 //purpose :
 //=============================================================================
-MAT2d_Circuit::MAT2d_Circuit()
+MAT2d_Circuit::MAT2d_Circuit(const GeomAbs_JoinType aJoinType,
+                             const Standard_Boolean IsOpenResult)
 {
+  myJoinType = aJoinType;
+  myIsOpenResult = IsOpenResult;
 }
 
 //=============================================================================
@@ -109,7 +109,7 @@ void  MAT2d_Circuit::Perform
   // Detection Lignes ouvertes.
   //----------------------------
   for ( i = 1; i <= NbLines; i++) {    
-    Handle_Geom2d_TrimmedCurve Curve;
+    Handle(Geom2d_TrimmedCurve) Curve;
     Curve = Handle(Geom2d_TrimmedCurve)::DownCast(FigItem.Value(i).First());
     gp_Pnt2d P1 = Curve->StartPoint();  
     Curve = Handle(Geom2d_TrimmedCurve)::DownCast(FigItem.Value(i).Last());
@@ -203,6 +203,133 @@ void  MAT2d_Circuit::Perform
   ConstructCircuit(FigItem,IndRefLine,Road);
 }
 
+//=======================================================================
+//function : IsSharpCorner
+//purpose  : Return True Si le point commun entre <Geom1> et <Geom2> est 
+//           une cassure saillante par rapport <Direction>
+//=======================================================================
+
+Standard_Boolean MAT2d_Circuit::IsSharpCorner(const Handle(Geom2d_Geometry)& Geom1,
+                                              const Handle(Geom2d_Geometry)& Geom2,
+                                              const Standard_Real Direction) const
+{
+  Standard_Real    DotProd;
+  Standard_Real    ProVec = CrossProd (Geom1,Geom2,DotProd);
+  Standard_Integer NbTest = 1;
+  Standard_Real    DU = Precision::Confusion();
+  Handle(Geom2d_TrimmedCurve) C1,C2;
+
+  C1= Handle(Geom2d_TrimmedCurve)::DownCast(Geom1);
+  C2= Handle(Geom2d_TrimmedCurve)::DownCast(Geom2);
+//  Modified by Sergey KHROMOV - Thu Oct 24 19:02:46 2002 Begin
+// Add the same criterion as it is in MAT2d_Circuit::InitOpen(..)
+//  Standard_Real  TolAng = 1.E-5;
+  Standard_Real  TolAng = 1.E-8;
+//  Modified by Sergey KHROMOV - Thu Oct 24 19:02:47 2002 End
+
+  if (myJoinType == GeomAbs_Arc)
+  {
+    while (NbTest <= 10) {
+      if      ((ProVec)*Direction < -TolAng)                 
+        return Standard_True;                // Saillant.
+      if      ((ProVec)*Direction >  TolAng)
+        return Standard_False;              // Rentrant.
+      else { 
+        if (DotProd > 0) {
+          return Standard_False;            // Plat.
+        }
+        TolAng = 1.E-8;
+        Standard_Real U1 = C1->LastParameter()  - NbTest*DU;
+        Standard_Real U2 = C2->FirstParameter() + NbTest*DU;
+        gp_Dir2d Dir1(C1->DN(U1,1));
+        gp_Dir2d Dir2(C2->DN(U2,1));
+        DotProd = Dir1.Dot(Dir2);
+        ProVec  =  Dir1^Dir2;
+        NbTest++;
+      } 
+    }
+    
+    
+    
+    // Rebroussement.
+    // on calculde des paralleles aux deux courbes du cote du domaine
+    // de calcul
+    // Si pas dintersection => saillant.
+    // Sinon                => rentrant.
+    Standard_Real D ;
+    Standard_Real Tol   = Precision::Confusion();
+    Standard_Real MilC1 = (C1->LastParameter() + C1->FirstParameter())*0.5;
+    Standard_Real MilC2 = (C2->LastParameter() + C2->FirstParameter())*0.5;
+    gp_Pnt2d      P     = C1->Value(C1->LastParameter());
+    gp_Pnt2d      P1    = C1->Value(MilC1);
+    gp_Pnt2d      P2    = C2->Value(MilC2);
+    
+    D = Min(P1.Distance(P),P2.Distance(P));
+    D /= 10;
+    
+    if (Direction > 0.) D = -D;
+    
+    Handle(Geom2dAdaptor_HCurve) HC1 = new Geom2dAdaptor_HCurve(C1);
+    Handle(Geom2dAdaptor_HCurve) HC2 = new Geom2dAdaptor_HCurve(C2);
+    Adaptor3d_OffsetCurve OC1(HC1,D,MilC1,C1->LastParameter());
+    Adaptor3d_OffsetCurve OC2(HC2,D,C2->FirstParameter(),MilC2);
+    Geom2dInt_GInter Intersect; 
+    Intersect.Perform(OC1,OC2,Tol,Tol);
+    
+#ifdef DEB
+    static Standard_Boolean Affich = 0;
+    if (Affich) {
+#ifdef DRAW
+      Standard_Real DU1 = (OC1.LastParameter() - OC1.FirstParameter())/9.;
+      Standard_Real DU2 = (OC2.LastParameter() - OC2.FirstParameter())/9.;
+      for (Standard_Integer ki = 0; ki <= 9; ki++) {
+        gp_Pnt2d P1 = OC1.Value(OC1.FirstParameter()+ki*DU1);
+        gp_Pnt2d P2 = OC2.Value(OC2.FirstParameter()+ki*DU2);
+        Handle(Draw_Marker2D) dr1 = new Draw_Marker2D(P1,Draw_Plus,Draw_vert);
+        Handle(Draw_Marker2D) dr2 = new Draw_Marker2D(P2,Draw_Plus,Draw_rouge); 
+        dout << dr1;
+        dout << dr2;
+      }
+      dout.Flush();
+#endif
+    }
+#endif
+    
+    if (Intersect.IsDone() && !Intersect.IsEmpty()) {
+      return Standard_False;
+    }
+    else {
+      return Standard_True;
+    }
+  } //end of if (myJoinType == GeomAbs_Arc)
+  else if (myJoinType == GeomAbs_Intersection)
+  {
+    if (Abs(ProVec) <= TolAng &&
+        DotProd < 0)
+    {
+      while (NbTest <= 10)
+      {
+        Standard_Real U1 = C1->LastParameter()  - NbTest*DU;
+        Standard_Real U2 = C2->FirstParameter() + NbTest*DU;
+        gp_Dir2d Dir1(C1->DN(U1,1));
+        gp_Dir2d Dir2(C2->DN(U2,1));
+        DotProd = Dir1.Dot(Dir2);
+        ProVec  =  Dir1^Dir2;
+        if      ((ProVec)*Direction < -TolAng)                 
+          return Standard_True;                // Saillant.
+        if      ((ProVec)*Direction >  TolAng)
+          return Standard_False;              // Rentrant.
+        
+        NbTest++;
+      }
+      return Standard_False;
+    }
+    else
+      return Standard_False;
+  }
+  return Standard_False;
+}
+
 //=======================================================================
 //function : SubSequence
 //purpose  : 
@@ -352,12 +479,12 @@ void MAT2d_Circuit::InitOpen (TColGeom2d_SequenceOfGeometry& Line) const
 { 
   Handle(Geom2d_TrimmedCurve) Curve;
   Standard_Real               DotProd;
+
   Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.First());
   Line.InsertBefore(1,new Geom2d_CartesianPoint(Curve->StartPoint()));
   Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Last());
   Line.Append(new Geom2d_CartesianPoint(Curve->EndPoint()));
-
+  
   for ( Standard_Integer i = 2; i <= Line.Length() - 2; i++) {
     if ( Abs(CrossProd(Line.Value(i),Line.Value(i+1),DotProd)) > 1.E-8 ||
         DotProd < 0. ) {
@@ -389,15 +516,18 @@ const
   //--------------------------
   // Completion de la ligne.
   //--------------------------
-  for ( i = NbItems - 1; i > 1; i--){
-    Type = Line.Value(i)->DynamicType();
-    if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){
-      Line.Append(Line.Value(i));
-    }
-    else {
-      Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(i)->Copy());
-      Curve->Reverse();
-      Line.Append(Curve);
+  if (!myIsOpenResult)
+  {
+    for ( i = NbItems - 1; i > 1; i--){
+      Type = Line.Value(i)->DynamicType();
+      if ( Type == STANDARD_TYPE(Geom2d_CartesianPoint) ){
+        Line.Append(Line.Value(i));
+      }
+      else {
+        Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(i)->Copy());
+        Curve->Reverse();
+        Line.Append(Curve);
+      }
     }
   }
 
@@ -485,30 +615,34 @@ const
     ICorres++;
   }
   Corres(ICorres) = IndLine;
-  
-  for (i = 1; i < 2*NbItems - 2; i++) {
-    if (Corres(i) == 0) Corres(i) = Corres(2*NbItems - i);
-  }
 
+  if (!myIsOpenResult)
+  {
+    for (i = 1; i < 2*NbItems - 2; i++) {
+      if (Corres(i) == 0)
+        Corres(i) = Corres(2*NbItems - i);
+    }
+    
 #ifdef DEB
-  if (AffichCircuit) {
-    for (i = 1; i <= 2*NbItems - 2; i++) {
-      cout<< "Correspondance "<< i<<" -> "<<Corres(i)<<endl;
+    if (AffichCircuit) {
+      for (i = 1; i <= 2*NbItems - 2; i++) {
+        cout<< "Correspondance "<< i<<" -> "<<Corres(i)<<endl;
+      }
     }
-  }
 #endif
-
-  //----------------------------
-  // Mise a jour des Connexions.
-  //----------------------------
-  for ( i = 1; i <= NbConnexions; i++){
-    CC = ConnexionFrom.ChangeValue(i);
-    CC->IndexItemOnFirst(Corres(CC->IndexItemOnFirst()));
-  }
-
-  if (!ConnexionFather.IsNull()) {
-    ConnexionFather
-      ->IndexItemOnSecond(Corres(ConnexionFather->IndexItemOnSecond()));
+    
+    //----------------------------
+    // Mise a jour des Connexions.
+    //----------------------------
+    for ( i = 1; i <= NbConnexions; i++){
+      CC = ConnexionFrom.ChangeValue(i);
+      CC->IndexItemOnFirst(Corres(CC->IndexItemOnFirst()));
+    }
+    
+    if (!ConnexionFather.IsNull()) {
+      ConnexionFather
+        ->IndexItemOnSecond(Corres(ConnexionFather->IndexItemOnSecond()));
+    }
   }
 }
 
@@ -531,8 +665,8 @@ void  MAT2d_Circuit::InsertCorner (TColGeom2d_SequenceOfGeometry& Line) const
   if (AffichCircuit) {
     if (Insert) {
       Curve      = Handle(Geom2d_TrimmedCurve)::DownCast(Line.Value(isuiv));
-      gp_Pnt2d P = Curve->StartPoint();
 #ifdef DRAW
+      gp_Pnt2d P = Curve->StartPoint();
       Handle(Draw_Marker2D) dr = new Draw_Marker2D(P,Draw_Plus,Draw_vert); 
       dout << dr;
       dout.Flush();
@@ -724,106 +858,6 @@ static Standard_Real CrossProd(const Handle(Geom2d_Geometry)& Geom1,
 }
 
 
-//=======================================================================
-//function : IsSharpCorner
-//purpose  : Return True Si le point commun entre <Geom1> et <Geom2> est 
-//           une cassure saillante par rapport <Direction>
-//=======================================================================
-
-static Standard_Boolean IsSharpCorner (const Handle(Geom2d_Geometry)& Geom1,
-                                      const Handle(Geom2d_Geometry)& Geom2,
-                                      const Standard_Real&           Direction)
-{    
-  Standard_Real    DotProd;
-  Standard_Real    ProVec = CrossProd (Geom1,Geom2,DotProd);
-  Standard_Integer NbTest = 1;
-  Standard_Real    DU = Precision::Confusion();
-  Handle(Geom2d_TrimmedCurve) C1,C2;
-
-  C1= Handle(Geom2d_TrimmedCurve)::DownCast(Geom1);
-  C2= Handle(Geom2d_TrimmedCurve)::DownCast(Geom2);
-//  Modified by Sergey KHROMOV - Thu Oct 24 19:02:46 2002 Begin
-// Add the same criterion as it is in MAT2d_Circuit::InitOpen(..)
-//  Standard_Real  TolAng = 1.E-5;
-  Standard_Real  TolAng = 1.E-8;
-//  Modified by Sergey KHROMOV - Thu Oct 24 19:02:47 2002 End
-
-  while (NbTest <= 10) {
-    if      ((ProVec)*Direction < -TolAng)                 
-      return Standard_True;                // Saillant.
-    if      ((ProVec)*Direction >  TolAng)
-      return Standard_False;              // Rentrant.
-    else { 
-      if (DotProd > 0) {
-       return Standard_False;            // Plat.
-      }
-      TolAng = 1.E-8;
-      Standard_Real U1 = C1->LastParameter()  - NbTest*DU;
-      Standard_Real U2 = C2->FirstParameter() + NbTest*DU;
-      gp_Dir2d Dir1(C1->DN(U1,1));
-      gp_Dir2d Dir2(C2->DN(U2,1));
-      DotProd = Dir1.Dot(Dir2);
-      ProVec  =  Dir1^Dir2;
-      NbTest++;
-    } 
-  }
-  
-
-  
-  // Rebroussement.
-  // on calculde des paralleles aux deux courbes du cote du domaine
-  // de calcul
-  // Si pas dintersection => saillant.
-  // Sinon                => rentrant.
-  Standard_Real D ;
-  Standard_Real Tol   = Precision::Confusion();
-  Standard_Real MilC1 = (C1->LastParameter() + C1->FirstParameter())*0.5;
-  Standard_Real MilC2 = (C2->LastParameter() + C2->FirstParameter())*0.5;
-  gp_Pnt2d      P     = C1->Value(C1->LastParameter());
-  gp_Pnt2d      P1    = C1->Value(MilC1);
-  gp_Pnt2d      P2    = C2->Value(MilC2);
-  
-  D = Min(P1.Distance(P),P2.Distance(P));
-  D /= 10;
-
-  if (Direction > 0.) D = -D;
-  
-  Handle(Geom2dAdaptor_HCurve) HC1 = new Geom2dAdaptor_HCurve(C1);
-  Handle(Geom2dAdaptor_HCurve) HC2 = new Geom2dAdaptor_HCurve(C2);
-  Adaptor3d_OffsetCurve OC1(HC1,D,MilC1,C1->LastParameter());
-  Adaptor3d_OffsetCurve OC2(HC2,D,C2->FirstParameter(),MilC2);
-  Geom2dInt_GInter Intersect; 
-  Intersect.Perform(OC1,OC2,Tol,Tol);
-  
-#ifdef DEB
-  static Standard_Boolean Affich = 0;
-  if (Affich) {
-    Standard_Real DU1 = (OC1.LastParameter() - OC1.FirstParameter())/9.;
-    Standard_Real DU2 = (OC2.LastParameter() - OC2.FirstParameter())/9.;
-    for (Standard_Integer ki = 0; ki <= 9; ki++) {
-      gp_Pnt2d P1 = OC1.Value(OC1.FirstParameter()+ki*DU1);
-      gp_Pnt2d P2 = OC2.Value(OC2.FirstParameter()+ki*DU2);
-#ifdef DRAW
-      Handle(Draw_Marker2D) dr1 = new Draw_Marker2D(P1,Draw_Plus,Draw_vert);
-      Handle(Draw_Marker2D) dr2 = new Draw_Marker2D(P2,Draw_Plus,Draw_rouge); 
-      dout << dr1;
-      dout << dr2;
-    }
-    dout.Flush();
-#else
-  }
-#endif
-  
-  }
-#endif
-  
-  if (Intersect.IsDone() && !Intersect.IsEmpty()) {
-    return Standard_False;
-  }
-  else {
-    return Standard_True;
-  }
-}
 
 
 
diff --git a/src/MAT2d/MAT2d_Mat2d.cdl b/src/MAT2d/MAT2d_Mat2d.cdl
new file mode 100644 (file)
index 0000000..2d83c6a
--- /dev/null
@@ -0,0 +1,114 @@
+-- Created on: 1992-09-22
+-- Created by: Gilles DEBARBOUILLE
+-- Copyright (c) 1992-1999 Matra Datavision
+-- Copyright (c) 1999-2014 OPEN CASCADE SAS
+--
+-- This file is part of Open CASCADE Technology software library.
+--
+-- This library is free software; you can redistribute it and/or modify it under
+-- the terms of the GNU Lesser General Public License version 2.1 as published
+-- by the Free Software Foundation, with special exception defined in the file
+-- OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+-- distribution for complete text of the license and disclaimer of any warranty.
+--
+-- Alternatively, this file may be used under the terms of Open CASCADE
+-- commercial license or contractual agreement.
+
+class Mat2d from MAT2d
+
+       ---Purpose: this class contains the generic algoritm of 
+       --          computation of the bisecting locus.
+
+uses
+    Side                     from MAT,
+    Bisector                 from MAT,
+    ListOfEdge               from MAT,
+    ListOfBisector           from MAT,
+    DataMapOfIntegerBisector from MAT,
+    DataMapOfIntegerInteger  from TColStd,
+       Tool2d                   from MAT2d
+    
+is
+
+    Create(IsOpenResult : Boolean from Standard = Standard_False)
+    ---Purpose: Empty construtor.
+    returns Mat2d from MAT2d;
+    
+--- Category : Computation.    
+    
+    CreateMat(me : in out ; aTool : in out Tool2d from MAT2d)
+       ---Purpose: Algoritm of computation of the bisecting locus.
+    is static;
+    
+    CreateMatOpen(me : in out ; aTool : in out Tool2d from MAT2d)
+       ---Purpose: Algoritm of computation of the bisecting locus for
+       --          open wire.
+    is static;
+    
+    IsDone(me) returns Boolean from Standard
+       ---Purpose:  Returns <TRUE> if CreateMat has succeeded. 
+    is static;
+
+    LoadBisectorsToRemove(me                    : in out ; 
+                         noofbisectorstoremove : in out Integer;
+                         distance1             :        Real;
+                         distance2             :        Real;
+                         bisector1             :        Bisector from MAT;
+                         bisector2             :        Bisector from MAT;
+                         bisector3             :        Bisector from MAT;
+                         bisector4             :        Bisector from MAT)
+    is static private;
+
+
+    Intersect( me                   : in out                   ;
+              atool                : in out  Tool2d from MAT2d;
+              aside                :         Integer          ;
+              noofbisectorstoremove: in out  Integer           ;
+              bisector1            : Bisector from MAT;
+              bisector2            : Bisector from MAT)
+    is static private;        
+                              
+
+--- Category : Querying.    
+    
+    Init(me : in out)
+       --- Purpose : Initialize an iterator on the set of the roots
+       --            of the trees of bisectors.
+    is static;
+    
+    More(me) returns Boolean
+       --- Purpose : Return False if there is no more roots.
+    is static;
+    
+    Next(me : in out)
+       --- Purpose : Move to the next root.
+    is static;
+    
+    Bisector(me) returns any Bisector from MAT
+       --- Purpose : Returns the current root.
+    is static;
+
+    SemiInfinite(me) returns Boolean from Standard
+       --- Purpose : Returns True if there are semi_infinite bisectors.
+       --            So there is a tree for each semi_infinte bisector.
+    is static;
+
+    NumberOfBisectors(me) returns Integer from Standard
+       --- Purpose : Returns the total number of bisectors.
+    is static;
+
+fields
+
+    myIsOpenResult        : Boolean;
+    thenumberofbisectors  : Integer;
+    thenumberofedges      : Integer;
+    semiInfinite          : Boolean;
+    theedgelist           : ListOfEdge               from MAT;
+    typeofbisectortoremove: DataMapOfIntegerInteger  from TColStd;
+    bisectoronetoremove   : DataMapOfIntegerBisector from MAT;
+    bisectortwotoremove   : DataMapOfIntegerBisector from MAT;
+    bisectormap           : DataMapOfIntegerBisector from MAT;
+    roots                 : ListOfBisector           from MAT;
+    isDone                : Boolean;             
+    
+end Mat2d;
diff --git a/src/MAT2d/MAT2d_Mat2d.cxx b/src/MAT2d/MAT2d_Mat2d.cxx
new file mode 100644 (file)
index 0000000..40595dd
--- /dev/null
@@ -0,0 +1,1662 @@
+// Created on: 1992-09-22
+// Created by: Gilles DEBARBOUILLE
+// Copyright (c) 1992-1999 Matra Datavision
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <MAT2d_Mat2d.ixx>
+
+#include <MAT_Edge.hxx>
+#include <MAT_ListOfEdge.hxx>
+#include <MAT_Bisector.hxx>
+#include <MAT_ListOfBisector.hxx>
+#include <TColStd_DataMapOfIntegerInteger.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <MAT_DataMapOfIntegerBisector.hxx>
+#include <Precision.hxx>
+#include <MAT2d_Tool2d.hxx>
+
+//========================================================================
+//  function : MAT2d_Mat2d
+//  purpose  :
+//========================================================================
+
+MAT2d_Mat2d::MAT2d_Mat2d(const Standard_Boolean IsOpenResult)
+{
+  myIsOpenResult = IsOpenResult;
+  thenumberofbisectors = 0;
+  thenumberofedges     = 0;
+}
+
+
+//========================================================================
+//  function : CreateMat
+//  purpose  : Calcul des lieux Bisecteurs.
+//
+//  Structure de la carte.
+//  ======================
+//  La carte des lieux bisecteurs se presente sous la forme d un ou plusieurs
+//  arbres de bisectrices.
+//  ( un arbre, si calcul a l interieur du contour, plusieurs sinon).
+//
+//  Les branches de plus bas niveau de l arbre separent deux elements voisins 
+//  du contour.
+// 
+//  Principe de l algorithme.
+//  -------------------------
+//  l arbre est construit des branches les plus basses vers les plus hautes.
+//
+//  0 . Calcul des bisectrices entre elements voisins du contour.
+//  1 . Elimination de certains element du contour => nouveau contour
+//  2 . Retour en 0.
+//  
+//  Principales etapes de l algorithme.
+//  ===================================
+//
+//  etape 1: Initialisation de l algorithme .
+//  -----------------------------------------
+//   Recuperation via le tool du nombre d'elements sur le contour
+//   Initialisation de <theedgelist>, un edge correspond a chaque 
+//   element du contour.
+//
+//  etape 2 : Boucle principale.
+//  ----------------------------  
+//    0 - Tant que Nombre d'edge > 1
+//         
+//      1. Pour chaque edge: construction de la bissectrice entre l edge 
+//         et l edge suivante.
+//         La bissectrice est semi_infinie, elle est soit trimmee par le
+//         point commun des deux edges, soit par l intersection de deux
+//         bissectrices antecedentes.
+//
+//      2. Intersection des Bisectrices issue du meme edge
+//         => une bisectrice est intersectee avec sa voisine a gauche
+//            et sa voisine a droite.
+//
+//      3. Analyse des intersections.
+//         Si pas d'intersection entre deux bisectrices B1 et B2
+//         - Recherche de l intersection la plus basse de B1 avec les 
+//           Bisectrices antecedentes a B2 du cote de B1. Soit Bi la 
+//           bissectrice intersectee. Toutes les bissectrices constituant la
+//           branche qui relie B2 a Bi sont marquees a effacer
+//         - idem pour B2.
+//  
+//      4. Suppresion des bisectrices a effacer.
+//         une bisectrise est a effacer :
+//          - Anulation de l intersection dont la bissectrice est issue
+//            => Prolongement des deux bisectrices posterieures.
+//          - Reinsertion des edge correspondant dans <theedgelist>.       
+//
+//      5. Pour chaque edge, analyse des distances entre les points d inter
+//         section et l edge.
+//         B1 B2 les bisectrices liee a l edge
+//         Soit P0 le point d intersection des bissectrices .
+//         Soit P1 le point d intersection de B1 avec son autre voisine .
+//         Soit P2 le point d intersection de B2 avec son autre voisine .
+//        
+//         si sur B1 le parametre de P0 < parametre de P1 et
+//         si sur B2 le parametre de P0 < parametre de P2 
+//         alors suppression de l edge de la liste des edges <theedgelist>.
+//
+//         rq: le parametre sur une bissectirce est croissant par rapport
+//         a la distance du point courant aux edges.
+
+//      6. Si aucune edge est elimine alors sortie de la boucle principale.
+//
+//      7. Retour en 0.
+//
+//  etape 3 : Creation des racines des arbres de bisectrices.
+//  ---------------------------------------------------------
+//            Recuperation des bissectrices calculees lors du dernier passage
+//            dans la boucle.
+//
+//========================================================================
+void MAT2d_Mat2d::CreateMatOpen(MAT2d_Tool2d& atool)
+{
+
+#ifdef ICONTINUE
+  Standard_Boolean Icontinue;
+#endif
+
+  Standard_Boolean interrupt = Standard_False;
+
+  Handle(MAT_Edge) edgetoremove;
+  Handle(MAT_Edge) previousedge,currentedge;
+
+  Standard_Integer      noofbisectorstoremove;
+  Handle(MAT_Bisector)  firstbisector,secondbisector;
+  Handle(MAT_Edge)      edge;
+  Standard_Integer      intersectionpoint;
+  Standard_Integer      beginbisector;
+  Standard_Integer      noofbisectors;
+
+  Standard_Integer     NbIterBis = 0;
+  Standard_Integer     EvenNbIterBis = 10;
+  TColStd_Array1OfInteger EdgeNumbers(1, EvenNbIterBis+1);
+  EdgeNumbers.Init(-1);
+  Standard_Boolean     ToNullifyNoofbisectorstoremove = Standard_False;
+
+  Handle(MAT_ListOfBisector) currentbisectorlist;
+
+  Handle(MAT_Bisector) bisectortoremove,lastbisector,currentbisector;
+  Handle(MAT_Bisector) previousbisector;
+
+  Standard_Integer     i,j,k,narea,shift,compact,all;
+  Standard_Integer     noofedges;
+  Standard_Integer     NumberMaxOfIte;
+  Standard_Real        toleranceofconfusion;
+
+  noofedges            = atool.NumberOfItems();
+  toleranceofconfusion = atool.ToleranceOfConfusion();
+  NumberMaxOfIte       = noofedges*noofedges;
+
+  TColStd_Array1OfInteger firstarea(0, noofedges);
+  TColStd_Array1OfInteger lastarea(0, noofedges);
+  TColStd_Array1OfInteger noofarea(0, noofedges);
+
+  Standard_Integer  parama[2];
+  Standard_Integer  paramb[2];
+
+// -----------------------------------------
+// Initialisation et remise a zero des maps.
+// -----------------------------------------
+  bisectoronetoremove.Clear();
+  bisectortwotoremove.Clear();
+  typeofbisectortoremove.Clear();
+  bisectormap.Clear();
+
+  isDone        = Standard_True;
+  noofbisectors = noofedges-1;
+  beginbisector = 0;
+
+// --------------------------------------------------------------------
+// Construction de <theedgelist> un edge correspond a un element simple
+// du contour.
+// --------------------------------------------------------------------
+  theedgelist = new MAT_ListOfEdge();
+
+  for(i=0; i<noofedges; i++) {
+    edge = new MAT_Edge();
+    edge->EdgeNumber(i+1);
+    edge->Distance(-1);
+    theedgelist->BackAdd(edge);
+  }
+  
+  theedgelist->Loop();
+
+//---------------------------------------------------
+// Initialisation des bissectrices issues du contour.
+//---------------------------------------------------
+  Standard_Real Dist;
+  theedgelist->First();
+
+  for(i=0; i<theedgelist->Number()-1; i++) {
+    bisectormap.Bind(i,new MAT_Bisector());
+    bisectormap(i)->IndexNumber(i);
+    bisectormap(i)->FirstEdge(theedgelist->Current());
+    bisectormap(i)->FirstVector
+      (atool.TangentBefore(theedgelist->Current()->EdgeNumber(), myIsOpenResult));
+    theedgelist->Next();
+    bisectormap(i)->SecondEdge(theedgelist->Current());
+    bisectormap(i)->IssuePoint
+      (atool.FirstPoint(theedgelist->Current()->EdgeNumber(),Dist));  
+    bisectormap(i)->DistIssuePoint(Dist);
+    bisectormap(i)->SecondVector
+      (atool.TangentAfter(theedgelist->Current()->EdgeNumber(), myIsOpenResult));
+  }
+
+//----------------------------------------------------
+// Affectation a chaque edge de ses deux bissectrices.
+//----------------------------------------------------
+  theedgelist->First();
+  theedgelist->Current()->FirstBisector(bisectormap(0));
+  theedgelist->Current()->SecondBisector(bisectormap(0));
+  theedgelist->Next();
+
+  for(i=1; i<theedgelist->Number()-1; i++) {
+    theedgelist->Current()->FirstBisector
+      (bisectormap(i-1));
+    theedgelist->Current()->SecondBisector
+      (bisectormap(i));
+    theedgelist->Next();
+  }
+
+  theedgelist->Current()->FirstBisector(bisectormap(theedgelist->Number()-2));
+  theedgelist->Current()->SecondBisector(bisectormap(theedgelist->Number()-2));
+
+//===========================================================================
+//                         Boucle Principale   (etape 2)
+//===========================================================================
+  Standard_Integer NumberOfIte = 0;
+
+  while(theedgelist->Number()>1) {
+
+
+    // ------------------------------------------------------------------
+    //  Creation des geometries des bissectrices via le tool. (etape 2.1)
+    // -------------------------------------------------------------------
+
+    for(i=beginbisector; i<noofbisectors; i++) {
+
+      atool.CreateBisector(bisectormap(i));
+      thenumberofbisectors++;
+      
+#ifdef DEBUG_Mat
+      atool.Dump(bisectormap(i)->BisectorNumber(),1);
+#ifdef ICONTINUE
+      cin>>Icontinue;
+#endif
+#endif
+    }
+
+    // ---------------------------------------------
+    //  Condition de sortie de la boucle principale.
+    // ---------------------------------------------
+
+//  Modified by Sergey KHROMOV - Fri Nov 17 10:28:28 2000 Begin
+    if (theedgelist->Number() < 3)
+      break;
+//  Modified by Sergey KHROMOV - Fri Nov 17 10:28:37 2000 End
+    
+    //---------------------------------------------------
+    // boucle 2 Tant qu il y a des bisectrices a effacer.
+    //---------------------------------------------------
+    for(;;) {
+      NbIterBis++;
+
+      noofbisectorstoremove = 0;
+      theedgelist->First();
+      theedgelist->Next();
+
+      //--------------------------------------------------------------
+      // Calcul des intersections des bisectrices voisines.(etape 2.2)
+      //--------------------------------------------------------------
+
+      if (NbIterBis <= EvenNbIterBis+1)
+       EdgeNumbers(NbIterBis) = theedgelist->Number();
+      else
+       {
+         for (k = 1; k <= EvenNbIterBis; k++)
+           EdgeNumbers(k) = EdgeNumbers(k+1);
+         EdgeNumbers(EvenNbIterBis+1) = theedgelist->Number();
+       }
+      if (EdgeNumbers(EvenNbIterBis+1) == EdgeNumbers(1))
+       ToNullifyNoofbisectorstoremove = Standard_True;
+
+      for(i=1; i<theedgelist->Number()-1; i++) {
+       edge = theedgelist->Current();
+       if(edge->Distance() == -1.) {
+         firstbisector = edge->FirstBisector();
+         secondbisector = edge->SecondBisector();
+         edge->Distance(atool.IntersectBisector
+                        (firstbisector,secondbisector,intersectionpoint));
+         edge->IntersectionPoint(intersectionpoint);
+
+         if(edge->Distance() == Precision::Infinite()) {
+           if(firstbisector->IndexNumber() >= beginbisector ||
+              secondbisector->IndexNumber() >= beginbisector) 
+             Intersect(atool,0,noofbisectorstoremove,
+                       firstbisector,secondbisector );
+         }
+         else {
+           if(firstbisector->IndexNumber() >= beginbisector) {
+             Intersect(atool,1,noofbisectorstoremove,
+                       firstbisector,secondbisector );
+           }
+           if(secondbisector->IndexNumber() >= beginbisector) {
+             Intersect(atool,2,noofbisectorstoremove,
+                       firstbisector,secondbisector );
+           }
+         }
+       }
+       theedgelist->Next();
+      }
+      
+      //-------------------------------
+      // Test de sortie de la boucle 2.
+      //-------------------------------
+
+      if (ToNullifyNoofbisectorstoremove)
+       noofbisectorstoremove = 0;
+      if(noofbisectorstoremove == 0) break;
+
+      //---------------------------------------------------
+      // Annulation des bissectrices a effacer. (etape 2.4)
+      //---------------------------------------------------
+
+      for(i=0; i<noofbisectorstoremove; i++) {
+
+       bisectortoremove = bisectoronetoremove(i);
+
+       //---------------------------------------------------------------
+       // Destruction des bisectrices descendantes de <bisectortoremove>
+       // On descend dans l arbre jusqu a ce qu on atteigne
+       // <bisectortwotoremove(i).
+       //---------------------------------------------------------------
+
+       for(;;){
+
+#ifdef DEBUG_Mat
+         atool.Dump(bisectortoremove->BisectorNumber(),0);
+#endif
+         // ----------------------------------
+         // Annulation de <bisectortoremove>.
+         // ----------------------------------
+         thenumberofbisectors--;
+         currentbisectorlist = bisectortoremove->List();
+         currentbisectorlist->First();
+         currentbisector = currentbisectorlist->FirstItem();
+         previousedge = currentbisector->FirstEdge();
+         theedgelist->Init(previousedge);
+         previousedge->Distance(-1.);
+         previousedge->FirstBisector()->SecondParameter(Precision::Infinite());
+         previousedge->SecondBisector()->FirstParameter(Precision::Infinite());
+
+         //------------------------------------------
+         // Annulation des fils de <currentbisector>.
+         //------------------------------------------
+
+         while(currentbisectorlist->More()) {
+           currentbisector = currentbisectorlist->Current();
+           currentedge  = currentbisector->SecondEdge();
+
+           //---------------------------------------
+           // Reinsertion de l edge dans le contour.
+           //---------------------------------------
+           theedgelist->LinkAfter(currentedge);
+           theedgelist->Next();
+           
+           currentedge->FirstBisector(currentbisector);
+           previousedge->SecondBisector(currentbisector);
+#ifdef DEBUG_Mat                     
+           atool.Dump(currentbisector->BisectorNumber(),0);
+#endif
+
+           //------------------------------------------------------
+           // Annulation de l intersection ie les fils qui
+           // ont generes l intersection sont prolonges a l infini.
+           //------------------------------------------------------
+
+           currentbisector->FirstParameter (Precision::Infinite());
+           currentbisector->SecondParameter(Precision::Infinite());
+                     
+           atool.TrimBisector(currentbisector);
+           
+#ifdef DEBUG_Mat
+           atool.Dump(currentbisector->BisectorNumber(),1);
+#endif
+           currentedge->Distance(-1.);
+           currentedge->FirstBisector()->SecondParameter(Precision::Infinite());
+           currentedge->SecondBisector()->FirstParameter(Precision::Infinite());
+           
+           previousedge = currentedge;
+           currentbisectorlist->Next();
+         }
+         
+         theedgelist->Unlink();
+
+         //-----------------------------------------------------------
+         // Test de sortie de la boucle d annulation des bissectrices.
+         //-----------------------------------------------------------
+
+         if(bisectortoremove->BisectorNumber() ==
+            bisectortwotoremove(i)->BisectorNumber()) break;
+
+         //-----------------------
+         // Descente dans l arbre.
+         //-----------------------
+
+         if(typeofbisectortoremove(i) == 1)
+           bisectortoremove = bisectortoremove->FirstBisector();
+         else
+           bisectortoremove = bisectortoremove->LastBisector();
+       
+       }  //----------------------------------------------------
+          // Fin boucle d annulation des bissectrices issue de 
+          // <bisectoronetoremove(i)>.
+          //----------------------------------------------------
+
+      } //------------------------------------------
+        // Fin boucle d annulation des bissectrices.
+        //-------------------------------------------
+
+#ifdef ICONTINUE
+      cin>>Icontinue;
+#endif
+    } //--------------
+      // Fin Boucle 2.
+      //--------------
+    
+    // ----------------------------------------------------------------------
+    // Analyse des parametres des intersections sur les bisectrices de chaque
+    // edge et determination des portions de contour a supprimees. (etape 2.5)
+    // ----------------------------------------------------------------------
+
+    theedgelist->First();
+    theedgelist->Next();
+      
+    currentbisector = theedgelist->Current()->FirstBisector();
+    if (currentbisector->FirstParameter()  == Precision::Infinite() &&
+       currentbisector->SecondParameter() == Precision::Infinite()) {
+      parama[0] = -1;
+      paramb[0] = -1;
+    }
+    else if(currentbisector->FirstParameter() == Precision::Infinite()) {
+      parama[0] = -1;
+      paramb[0] =  1;
+    }
+    else if(currentbisector->SecondParameter() == Precision::Infinite()) {
+      paramb[0] = -1;
+      parama[0] =  1;
+    }
+    else if (atool.Distance(currentbisector,
+                           currentbisector->FirstParameter(),
+                           currentbisector->SecondParameter()) 
+            > toleranceofconfusion) {
+      if((currentbisector->FirstParameter() - 
+         currentbisector->SecondParameter())
+        *currentbisector->Sense() > 0.) {      
+       parama[0] = -1;
+       paramb[0] =  1;
+      }
+      else {
+       paramb[0] = -1;
+       parama[0] =  1;
+      }
+    }
+    else {
+      parama[0] = 1;
+      paramb[0] = 1;
+    }
+    
+    narea = -1;
+    
+    for(i=1; i<theedgelist->Number()-1; i++) {
+      currentbisector = theedgelist->Current()->SecondBisector();
+      if (currentbisector->FirstParameter()  == Precision::Infinite() &&
+         currentbisector->SecondParameter() == Precision::Infinite()) {
+       parama[1] = -1;
+       paramb[1] = -1;
+      }
+      else if(currentbisector->FirstParameter() == Precision::Infinite()) {
+       parama[1] = -1;
+       paramb[1] =  1;
+      }
+      else if(currentbisector->SecondParameter() == Precision::Infinite()) {
+       paramb[1] = -1;
+       parama[1] =  1;
+      }
+      else if (atool.Distance(currentbisector,
+                             currentbisector->FirstParameter(),
+                             currentbisector->SecondParameter()) 
+              > toleranceofconfusion) {
+       if((currentbisector->FirstParameter() - 
+           currentbisector->SecondParameter()) 
+          *currentbisector->Sense() > 0.) {      
+         parama[1] = -1;
+         paramb[1] =  1;
+       }
+       else {
+         paramb[1] = -1;
+         parama[1] =  1;
+       }
+      }
+      else {
+       parama[1] = 1;
+       paramb[1] = 1;
+      }
+
+      //-----------------------------------------------------------------
+      // Test si l edge est a enlever du contour
+      // Construction des portions de contour a eliminer.
+      //
+      //  narea : nombre de portions continues du contour a eliminer.
+      //  firstarea[i] : indice premier edge de la portion i.
+      //  lastarea[i]  : indice dernier edge de la portion i.
+      //-----------------------------------------------------------------
+
+#ifdef DEBUG_Mat
+      cout <<" Test sur les parametres pour elimination"<<endl;
+      cout << " Edge number :"<<theedgelist->Current()->EdgeNumber()<<endl;
+#endif
+
+      if(paramb[0] > 0 && parama[1] > 0) {
+
+#ifdef DEBUG_Mat
+      cout <<" A ELIMINER "<<endl;
+#endif 
+       if(narea < 0) {
+         firstarea(++narea) = theedgelist->Index();
+         lastarea(narea) = firstarea(narea);
+         noofarea(narea) = 1;
+       }
+       else {
+         if(theedgelist->Index() == lastarea(narea)+1) {
+           lastarea(narea)++;
+           noofarea(narea)++;
+         }
+         else {
+           firstarea(++narea) = theedgelist->Index();
+           lastarea(narea) = firstarea(narea);
+           noofarea(narea) = 1;
+         }
+       }
+      }
+      parama[0] = parama[1];
+      paramb[0] = paramb[1];
+      theedgelist->Next();
+    
+    } 
+    
+    compact = 0;
+    if(narea > 0) {
+      if(lastarea(narea) == theedgelist->Number() && firstarea(0) == 1) {
+       firstarea(0) = firstarea(narea);
+       noofarea(0) = noofarea(0)+noofarea(narea);
+       compact = noofarea(narea);
+       narea--;
+      }
+    }
+    
+    narea++;
+
+    //------------------------------------------------------------------
+    // Sortie de la boucle principale si il n y a pas d edge a eliminer.
+    // (etape 2.6)
+    //------------------------------------------------------------------
+    if(narea == 0) {
+      interrupt = Standard_True;
+      break;
+    }
+    
+
+    //----------------------------------------------------------------
+    // Elimination des edges a enlever du contour
+    // => Mise a jour du nouveau contour.
+    // => Creation des bissectrices entre les nouvelles edges voisines.
+    //----------------------------------------------------------------
+
+    beginbisector = noofbisectors;
+    shift = 0;
+    all = 0;
+    if(narea == 1 && noofarea(0) == theedgelist->Number()) all = 1;
+
+    for(i=0; i<narea; i++) {
+      if(i == 1)shift = shift-compact;
+      theedgelist->First();
+      theedgelist->Next();
+      edgetoremove = theedgelist->Brackets(firstarea(i)-shift);
+      
+      edgetoremove->FirstBisector()->EndPoint(edgetoremove
+                                             ->IntersectionPoint());
+      
+#ifdef DEBUG_Mat
+      atool.Dump(edgetoremove->FirstBisector()->BisectorNumber(),0);
+#endif
+
+      edgetoremove->FirstBisector()->FirstParameter
+       (edgetoremove->FirstBisector()->SecondParameter());
+         
+#ifdef DEBUG_Mat
+      if(atool.TrimBisector(edgetoremove->FirstBisector()))
+       atool.Dump(edgetoremove->FirstBisector()->BisectorNumber(),1);
+#else
+      atool.TrimBisector(edgetoremove->FirstBisector());
+#endif
+
+      bisectormap.Bind(noofbisectors,new MAT_Bisector());
+      bisectormap(noofbisectors)->IndexNumber(noofbisectors);
+      bisectormap(noofbisectors)->DistIssuePoint(edgetoremove->Distance());
+      bisectormap(noofbisectors)->IssuePoint(edgetoremove
+                                               ->IntersectionPoint());
+      bisectormap(noofbisectors)->FirstEdge(theedgelist->PreviousItem());
+      bisectormap(noofbisectors)->AddBisector(edgetoremove
+                                                ->FirstBisector());
+
+      for(j=0; j<noofarea(i); j++) {
+       theedgelist->Unlink();
+       theedgelist->Next();
+       shift++;
+
+#ifdef DEBUG_Mat
+       cout<<" Suppression de l'arete : "<<edgetoremove->EdgeNumber()<<endl;
+#endif
+
+       if(all == 0 || j+1 != noofarea(i)) {
+         bisectormap(noofbisectors)->AddBisector(edgetoremove
+                                                    ->SecondBisector());
+       }
+       edgetoremove->SecondBisector()->EndPoint(edgetoremove
+                                                ->IntersectionPoint());
+
+#ifdef DEBUG_Mat
+       atool.Dump(edgetoremove->SecondBisector()->BisectorNumber(),0);
+#endif
+
+       edgetoremove->SecondBisector()->SecondParameter
+         (edgetoremove->SecondBisector()->FirstParameter());
+#ifdef DEBUG_Mat
+       if(atool.TrimBisector(edgetoremove->SecondBisector()))
+         atool.Dump(edgetoremove->SecondBisector()->BisectorNumber(),1);
+#else
+       atool.TrimBisector(edgetoremove->SecondBisector());
+#endif
+       edgetoremove = theedgelist->Current();
+      }
+      bisectormap(noofbisectors)->SecondEdge(theedgelist->Current());
+
+      theedgelist->PreviousItem()
+        ->SecondBisector(bisectormap(noofbisectors));
+      theedgelist->Current()->FirstBisector(bisectormap(noofbisectors));
+         
+      bisectormap(noofbisectors)->FirstVector
+       (atool.Tangent
+        (bisectormap(noofbisectors)->FirstBisector()
+         ->BisectorNumber()));
+      
+      bisectormap(noofbisectors)->SecondVector
+       (atool.Tangent
+        (bisectormap(noofbisectors)->LastBisector()
+         ->BisectorNumber()));
+      
+      noofbisectors++;
+      
+      theedgelist->PreviousItem()->Distance(-1);
+      theedgelist->Current()->Distance(-1);
+
+      theedgelist->PreviousItem()->FirstBisector()
+        ->SecondParameter(Precision::Infinite());
+      theedgelist->Current()->SecondBisector()->FirstParameter(Precision::Infinite());
+    }
+
+    //-----------------------------------------------------------------------
+    // Test sur le nombre d iterations :
+    // A chaque iteration est elimine un element du contour qui ne sera plus
+    // reinsere par la suite => le nombre d iterartions doit etre < au nombre
+    // d elements.
+    // Le nombre d iteration maximum est fixe a numberofedges*numberofedges.
+    //-----------------------------------------------------------------------
+    if (NumberOfIte > NumberMaxOfIte) {
+      isDone = Standard_False;             //Echec calcul de la carte.
+      break;
+    }
+    NumberOfIte++;
+
+  }  //===============================================
+     //            Fin Boucle Principale.
+     //===============================================
+     
+  //----------
+  // etape 3.
+  //----------
+
+
+  //----------------------------------------------
+  // interupt = True => bissectrices semi_infinies.
+  //----------------------------------------------
+  
+  if(interrupt)
+    semiInfinite = Standard_True;
+  else {
+    semiInfinite = Standard_False;
+
+    //------------------------------------------------------------------
+    // Si le nombre d edge > 1 => le nombre d edge = 2 
+    //              (cf test sortie boucle principale)
+    // Les deux dernieres bisectrices separent les memes edges .
+    // Soit elles sont confondues si calcul a l interieur, soit elles
+    // sont semi-Infinies (exemple : contour compose seulement de deux
+    // arcs de cercles).                          
+    //------------------------------------------------------------------
+
+    if(theedgelist->Number() > 1) { //Now this branch is never reachable
+                                    //because the case edgenumber = 2 is processed in the main loop
+      theedgelist->First();
+      edge = theedgelist->Current();
+      if(edge->FirstBisector()->IndexNumber() == noofbisectors-1) {
+//  Modified by skv - Tue Sep 13 12:13:28 2005 IDEM Begin
+       if (atool.TrimBisector(edge->SecondBisector(),
+                              edge->FirstBisector()->IssuePoint())) {
+         if (edge->SecondBisector()->EndPoint() == 0)
+           edge->SecondBisector()->EndPoint(edge->FirstBisector()->IssuePoint());
+         bisectormap(noofbisectors-1)->AddBisector(edge->SecondBisector());
+       } else
+         semiInfinite = Standard_True;
+//  Modified by skv - Tue Sep 13 12:13:28 2005 IDEM End
+      }
+      else {
+//  Modified by skv - Tue Sep 13 12:13:28 2005 IDEM Begin
+       if (atool.TrimBisector(edge->FirstBisector(),
+                              edge->SecondBisector()->IssuePoint())) {
+         if (edge->FirstBisector()->EndPoint() == 0)
+           edge->FirstBisector()->EndPoint(edge->SecondBisector()->IssuePoint());
+         bisectormap(noofbisectors-1)->AddBisector(edge->FirstBisector());
+       } else 
+         semiInfinite = Standard_True;
+//  Modified by skv - Tue Sep 13 12:13:28 2005 IDEM End
+      }
+      if (!semiInfinite) {     
+       thenumberofbisectors--;
+       bisectormap(noofbisectors-1)->SecondEdge(edge);
+       bisectormap(noofbisectors-1)->BisectorNumber(-1);
+      }
+    }
+  }
+
+  if(semiInfinite) {
+    beginbisector = noofbisectors;
+    theedgelist->First();
+    for(i=1; i<theedgelist->Number(); i++) {
+      edge = theedgelist->Current();
+      bisectormap.Bind(noofbisectors,edge->SecondBisector());
+      noofbisectors++;
+      theedgelist->Next();
+    }
+
+  }
+
+  //---------------------------
+  // Recuperations des racines.
+  //---------------------------
+
+  roots = new MAT_ListOfBisector;
+  
+  if (bisectormap(noofbisectors-1)->BisectorNumber() == -1) {
+    roots = bisectormap(noofbisectors-1)->List();
+    roots->First();
+    roots->Current()->FirstEdge()
+      ->Distance(bisectormap(noofbisectors-1)->DistIssuePoint());
+  }
+  else {
+    for (i=beginbisector;i<noofbisectors;i++) {
+      roots->BackAdd(bisectormap(i));
+    }
+  }
+  
+}
+
+void MAT2d_Mat2d::CreateMat(MAT2d_Tool2d& atool)
+{
+
+#ifdef ICONTINUE
+  Standard_Boolean Icontinue;
+#endif
+
+  Standard_Boolean interrupt = Standard_False;
+
+  Handle(MAT_Edge) edgetoremove;
+  Handle(MAT_Edge) previousedge,currentedge;
+
+  Standard_Integer      noofbisectorstoremove;
+  Handle(MAT_Bisector)  firstbisector,secondbisector;
+  Handle(MAT_Edge)      edge;
+  Standard_Integer      intersectionpoint;
+  Standard_Integer      beginbisector;
+  Standard_Integer      noofbisectors;
+
+  Standard_Integer     NbIterBis = 0;
+  Standard_Integer     EvenNbIterBis = 10;
+  TColStd_Array1OfInteger EdgeNumbers(1, EvenNbIterBis+1);
+  EdgeNumbers.Init(-1);
+  Standard_Boolean     ToNullifyNoofbisectorstoremove = Standard_False;
+
+  Handle(MAT_ListOfBisector) currentbisectorlist;
+
+  Handle(MAT_Bisector) bisectortoremove,lastbisector,currentbisector;
+  Handle(MAT_Bisector) previousbisector;
+
+  Standard_Integer     i,j,k,narea,shift,compact,all;
+  Standard_Integer     noofedges;
+  Standard_Integer     NumberMaxOfIte;
+  Standard_Real        toleranceofconfusion;
+
+  noofedges            = atool.NumberOfItems();
+  toleranceofconfusion = atool.ToleranceOfConfusion();
+  NumberMaxOfIte       = noofedges*noofedges;
+
+  TColStd_Array1OfInteger firstarea(0, noofedges);
+  TColStd_Array1OfInteger lastarea(0, noofedges);
+  TColStd_Array1OfInteger noofarea(0, noofedges);
+
+  Standard_Integer  parama[2];
+  Standard_Integer  paramb[2];
+
+// -----------------------------------------
+// Initialisation et remise a zero des maps.
+// -----------------------------------------
+  bisectoronetoremove.Clear();
+  bisectortwotoremove.Clear();
+  typeofbisectortoremove.Clear();
+  bisectormap.Clear();
+
+  isDone        = Standard_True;
+  noofbisectors = noofedges;
+  beginbisector = 0;
+
+// --------------------------------------------------------------------
+// Construction de <theedgelist> un edge correspond a un element simple
+// du contour.
+// --------------------------------------------------------------------
+  theedgelist = new MAT_ListOfEdge();
+
+  for(i=0; i<noofedges; i++) {
+    edge = new MAT_Edge();
+    edge->EdgeNumber(i+1);
+    edge->Distance(-1);
+    theedgelist->BackAdd(edge);
+  }
+  
+  theedgelist->Loop();
+
+//---------------------------------------------------
+// Initialisation des bissectrices issues du contour.
+//---------------------------------------------------
+  Standard_Real Dist;
+  theedgelist->First();
+
+  for(i=0; i<theedgelist->Number(); i++) {
+    bisectormap.Bind(i,new MAT_Bisector());
+    bisectormap(i)->IndexNumber(i);
+    bisectormap(i)->FirstEdge(theedgelist->Current());
+    bisectormap(i)->FirstVector
+      (atool.TangentBefore(theedgelist->Current()->EdgeNumber(), myIsOpenResult));
+    theedgelist->Next();
+    bisectormap(i)->SecondEdge(theedgelist->Current());
+    bisectormap(i)->IssuePoint
+      (atool.FirstPoint(theedgelist->Current()->EdgeNumber(),Dist));  
+    bisectormap(i)->DistIssuePoint(Dist);
+    bisectormap(i)->SecondVector
+      (atool.TangentAfter(theedgelist->Current()->EdgeNumber(), myIsOpenResult));
+  }
+
+//----------------------------------------------------
+// Affectation a chaque edge de ses deux bissectrices.
+//----------------------------------------------------
+  theedgelist->First();
+
+  for(i=0; i<theedgelist->Number(); i++) {
+    theedgelist->Current()->FirstBisector
+      (bisectormap((i-1+noofbisectors)%noofbisectors));
+    theedgelist->Current()->SecondBisector
+      (bisectormap(i));
+    theedgelist->Next();
+  }
+
+//===========================================================================
+//                         Boucle Principale   (etape 2)
+//===========================================================================
+  Standard_Integer NumberOfIte = 0;
+
+  while(theedgelist->Number()>1) {
+
+
+    // ------------------------------------------------------------------
+    //  Creation des geometries des bissectrices via le tool. (etape 2.1)
+    // -------------------------------------------------------------------
+
+    for(i=beginbisector; i<noofbisectors; i++) {
+
+      atool.CreateBisector(bisectormap(i));
+      thenumberofbisectors++;
+      
+#ifdef DEBUG_Mat
+      atool.Dump(bisectormap(i)->BisectorNumber(),1);
+#ifdef ICONTINUE
+      cin>>Icontinue;
+#endif
+#endif
+    }
+
+    // ---------------------------------------------
+    //  Condition de sortie de la boucle principale.
+    // ---------------------------------------------
+
+//  Modified by Sergey KHROMOV - Fri Nov 17 10:28:28 2000 Begin
+    if (theedgelist->Number() < 3)
+      break;
+//  Modified by Sergey KHROMOV - Fri Nov 17 10:28:37 2000 End
+    
+    //---------------------------------------------------
+    // boucle 2 Tant qu il y a des bisectrices a effacer.
+    //---------------------------------------------------
+    for(;;) {
+      NbIterBis++;
+
+      noofbisectorstoremove = 0;
+      theedgelist->First();
+
+      //--------------------------------------------------------------
+      // Calcul des intersections des bisectrices voisines.(etape 2.2)
+      //--------------------------------------------------------------
+
+      if (NbIterBis <= EvenNbIterBis+1)
+       EdgeNumbers(NbIterBis) = theedgelist->Number();
+      else
+       {
+         for (k = 1; k <= EvenNbIterBis; k++)
+           EdgeNumbers(k) = EdgeNumbers(k+1);
+         EdgeNumbers(EvenNbIterBis+1) = theedgelist->Number();
+       }
+      if (EdgeNumbers(EvenNbIterBis+1) == EdgeNumbers(1))
+       ToNullifyNoofbisectorstoremove = Standard_True;
+
+      for(i=0; i<theedgelist->Number(); i++) {
+       edge = theedgelist->Current();
+       if(edge->Distance() == -1.) {
+         firstbisector = edge->FirstBisector();
+         secondbisector = edge->SecondBisector();
+         edge->Distance(atool.IntersectBisector
+                        (firstbisector,secondbisector,intersectionpoint));
+         edge->IntersectionPoint(intersectionpoint);
+
+         if(edge->Distance() == Precision::Infinite()) {
+           if(firstbisector->IndexNumber() >= beginbisector ||
+              secondbisector->IndexNumber() >= beginbisector) 
+             Intersect(atool,0,noofbisectorstoremove,
+                       firstbisector,secondbisector );
+         }
+         else {
+           if(firstbisector->IndexNumber() >= beginbisector) {
+             Intersect(atool,1,noofbisectorstoremove,
+                       firstbisector,secondbisector );
+           }
+           if(secondbisector->IndexNumber() >= beginbisector) {
+             Intersect(atool,2,noofbisectorstoremove,
+                       firstbisector,secondbisector );
+           }
+         }
+       }
+       theedgelist->Next();
+      }
+      
+      //-------------------------------
+      // Test de sortie de la boucle 2.
+      //-------------------------------
+
+      if (ToNullifyNoofbisectorstoremove)
+       noofbisectorstoremove = 0;
+      if(noofbisectorstoremove == 0) break;
+
+      //---------------------------------------------------
+      // Annulation des bissectrices a effacer. (etape 2.4)
+      //---------------------------------------------------
+
+      for(i=0; i<noofbisectorstoremove; i++) {
+
+       bisectortoremove = bisectoronetoremove(i);
+
+       //---------------------------------------------------------------
+       // Destruction des bisectrices descendantes de <bisectortoremove>
+       // On descend dans l arbre jusqu a ce qu on atteigne
+       // <bisectortwotoremove(i).
+       //---------------------------------------------------------------
+
+       for(;;){
+
+#ifdef DEBUG_Mat
+         atool.Dump(bisectortoremove->BisectorNumber(),0);
+#endif
+         // ----------------------------------
+         // Annulation de <bisectortoremove>.
+         // ----------------------------------
+         thenumberofbisectors--;
+         currentbisectorlist = bisectortoremove->List();
+         currentbisectorlist->First();
+         currentbisector = currentbisectorlist->FirstItem();
+         previousedge = currentbisector->FirstEdge();
+         theedgelist->Init(previousedge);
+         previousedge->Distance(-1.);
+         previousedge->FirstBisector()->SecondParameter(Precision::Infinite());
+         previousedge->SecondBisector()->FirstParameter(Precision::Infinite());
+
+         //------------------------------------------
+         // Annulation des fils de <currentbisector>.
+         //------------------------------------------
+
+         while(currentbisectorlist->More()) {
+           currentbisector = currentbisectorlist->Current();
+           currentedge  = currentbisector->SecondEdge();
+
+           //---------------------------------------
+           // Reinsertion de l edge dans le contour.
+           //---------------------------------------
+           theedgelist->LinkAfter(currentedge);
+           theedgelist->Next();
+           
+           currentedge->FirstBisector(currentbisector);
+           previousedge->SecondBisector(currentbisector);
+#ifdef DEBUG_Mat                     
+           atool.Dump(currentbisector->BisectorNumber(),0);
+#endif
+
+           //------------------------------------------------------
+           // Annulation de l intersection ie les fils qui
+           // ont generes l intersection sont prolonges a l infini.
+           //------------------------------------------------------
+
+           currentbisector->FirstParameter (Precision::Infinite());
+           currentbisector->SecondParameter(Precision::Infinite());
+                     
+           atool.TrimBisector(currentbisector);
+           
+#ifdef DEBUG_Mat
+           atool.Dump(currentbisector->BisectorNumber(),1);
+#endif
+           currentedge->Distance(-1.);
+           currentedge->FirstBisector()->SecondParameter(Precision::Infinite());
+           currentedge->SecondBisector()->FirstParameter(Precision::Infinite());
+           
+           previousedge = currentedge;
+           currentbisectorlist->Next();
+         }
+         
+         theedgelist->Unlink();
+
+         //-----------------------------------------------------------
+         // Test de sortie de la boucle d annulation des bissectrices.
+         //-----------------------------------------------------------
+
+         if(bisectortoremove->BisectorNumber() ==
+            bisectortwotoremove(i)->BisectorNumber()) break;
+
+         //-----------------------
+         // Descente dans l arbre.
+         //-----------------------
+
+         if(typeofbisectortoremove(i) == 1)
+           bisectortoremove = bisectortoremove->FirstBisector();
+         else
+           bisectortoremove = bisectortoremove->LastBisector();
+       
+       }  //----------------------------------------------------
+          // Fin boucle d annulation des bissectrices issue de 
+          // <bisectoronetoremove(i)>.
+          //----------------------------------------------------
+
+      } //------------------------------------------
+        // Fin boucle d annulation des bissectrices.
+        //-------------------------------------------
+
+#ifdef ICONTINUE
+      cin>>Icontinue;
+#endif
+    } //--------------
+      // Fin Boucle 2.
+      //--------------
+    
+    // ----------------------------------------------------------------------
+    // Analyse des parametres des intersections sur les bisectrices de chaque
+    // edge et determination des portions de contour a supprimees. (etape 2.5)
+    // ----------------------------------------------------------------------
+
+    theedgelist->First();
+      
+    currentbisector = theedgelist->Current()->FirstBisector();
+    if (currentbisector->FirstParameter()  == Precision::Infinite() &&
+       currentbisector->SecondParameter() == Precision::Infinite()) {
+      parama[0] = -1;
+      paramb[0] = -1;
+    }
+    else if(currentbisector->FirstParameter() == Precision::Infinite()) {
+      parama[0] = -1;
+      paramb[0] =  1;
+    }
+    else if(currentbisector->SecondParameter() == Precision::Infinite()) {
+      paramb[0] = -1;
+      parama[0] =  1;
+    }
+    else if (atool.Distance(currentbisector,
+                           currentbisector->FirstParameter(),
+                           currentbisector->SecondParameter()) 
+            > toleranceofconfusion) {
+      if((currentbisector->FirstParameter() - 
+         currentbisector->SecondParameter())
+        *currentbisector->Sense() > 0.) {      
+       parama[0] = -1;
+       paramb[0] =  1;
+      }
+      else {
+       paramb[0] = -1;
+       parama[0] =  1;
+      }
+    }
+    else {
+      parama[0] = 1;
+      paramb[0] = 1;
+    }
+    
+    narea = -1;
+    
+    for(i=0; i<theedgelist->Number(); i++) {
+      currentbisector = theedgelist->Current()->SecondBisector();
+      if (currentbisector->FirstParameter()  == Precision::Infinite() &&
+         currentbisector->SecondParameter() == Precision::Infinite()) {
+       parama[1] = -1;
+       paramb[1] = -1;
+      }
+      else if(currentbisector->FirstParameter() == Precision::Infinite()) {
+       parama[1] = -1;
+       paramb[1] =  1;
+      }
+      else if(currentbisector->SecondParameter() == Precision::Infinite()) {
+       paramb[1] = -1;
+       parama[1] =  1;
+      }
+      else if (atool.Distance(currentbisector,
+                             currentbisector->FirstParameter(),
+                             currentbisector->SecondParameter()) 
+              > toleranceofconfusion) {
+       if((currentbisector->FirstParameter() - 
+           currentbisector->SecondParameter()) 
+          *currentbisector->Sense() > 0.) {      
+         parama[1] = -1;
+         paramb[1] =  1;
+       }
+       else {
+         paramb[1] = -1;
+         parama[1] =  1;
+       }
+      }
+      else {
+       parama[1] = 1;
+       paramb[1] = 1;
+      }
+
+      //-----------------------------------------------------------------
+      // Test si l edge est a enlever du contour
+      // Construction des portions de contour a eliminer.
+      //
+      //  narea : nombre de portions continues du contour a eliminer.
+      //  firstarea[i] : indice premier edge de la portion i.
+      //  lastarea[i]  : indice dernier edge de la portion i.
+      //-----------------------------------------------------------------
+
+#ifdef DEBUG_Mat
+      cout <<" Test sur les parametres pour elimination"<<endl;
+      cout << " Edge number :"<<theedgelist->Current()->EdgeNumber()<<endl;
+#endif
+
+      if(paramb[0] > 0 && parama[1] > 0) {
+
+#ifdef DEBUG_Mat
+      cout <<" A ELIMINER "<<endl;
+#endif 
+       if(narea < 0) {
+         firstarea(++narea) = theedgelist->Index();
+         lastarea(narea) = firstarea(narea);
+         noofarea(narea) = 1;
+       }
+       else {
+         if(theedgelist->Index() == lastarea(narea)+1) {
+           lastarea(narea)++;
+           noofarea(narea)++;
+         }
+         else {
+           firstarea(++narea) = theedgelist->Index();
+           lastarea(narea) = firstarea(narea);
+           noofarea(narea) = 1;
+         }
+       }
+      }
+      parama[0] = parama[1];
+      paramb[0] = paramb[1];
+      theedgelist->Next();
+    
+    } 
+    
+    compact = 0;
+    if(narea > 0) {
+      if(lastarea(narea) == theedgelist->Number() && firstarea(0) == 1) {
+       firstarea(0) = firstarea(narea);
+       noofarea(0) = noofarea(0)+noofarea(narea);
+       compact = noofarea(narea);
+       narea--;
+      }
+    }
+    
+    narea++;
+
+    //------------------------------------------------------------------
+    // Sortie de la boucle principale si il n y a pas d edge a eliminer.
+    // (etape 2.6)
+    //------------------------------------------------------------------
+    if(narea == 0) {
+      interrupt = Standard_True;
+      break;
+    }
+    
+
+    //----------------------------------------------------------------
+    // Elimination des edges a enlever du contour
+    // => Mise a jour du nouveau contour.
+    // => Creation des bissectrices entre les nouvelles edges voisines.
+    //----------------------------------------------------------------
+
+    beginbisector = noofbisectors;
+    shift = 0;
+    all = 0;
+    if(narea == 1 && noofarea(0) == theedgelist->Number()) all = 1;
+
+    for(i=0; i<narea; i++) {
+      if(i == 1)shift = shift-compact;
+      theedgelist->First();
+      edgetoremove = theedgelist->Brackets(firstarea(i)-shift);
+      
+      edgetoremove->FirstBisector()->EndPoint(edgetoremove
+                                             ->IntersectionPoint());
+      
+#ifdef DEBUG_Mat
+      atool.Dump(edgetoremove->FirstBisector()->BisectorNumber(),0);
+#endif
+
+      edgetoremove->FirstBisector()->FirstParameter
+       (edgetoremove->FirstBisector()->SecondParameter());
+         
+#ifdef DEBUG_Mat
+      if(atool.TrimBisector(edgetoremove->FirstBisector()))
+       atool.Dump(edgetoremove->FirstBisector()->BisectorNumber(),1);
+#else
+      atool.TrimBisector(edgetoremove->FirstBisector());
+#endif
+
+      bisectormap.Bind(noofbisectors,new MAT_Bisector());
+      bisectormap(noofbisectors)->IndexNumber(noofbisectors);
+      bisectormap(noofbisectors)->DistIssuePoint(edgetoremove->Distance());
+      bisectormap(noofbisectors)->IssuePoint(edgetoremove
+                                               ->IntersectionPoint());
+      bisectormap(noofbisectors)->FirstEdge(theedgelist->PreviousItem());
+      bisectormap(noofbisectors)->AddBisector(edgetoremove
+                                                ->FirstBisector());
+
+      for(j=0; j<noofarea(i); j++) {
+       theedgelist->Unlink();
+       theedgelist->Next();
+       shift++;
+
+#ifdef DEBUG_Mat
+       cout<<" Suppression de l'arete : "<<edgetoremove->EdgeNumber()<<endl;
+#endif
+
+       if(all == 0 || j+1 != noofarea(i)) {
+         bisectormap(noofbisectors)->AddBisector(edgetoremove
+                                                    ->SecondBisector());
+       }
+       edgetoremove->SecondBisector()->EndPoint(edgetoremove
+                                                ->IntersectionPoint());
+
+#ifdef DEBUG_Mat
+       atool.Dump(edgetoremove->SecondBisector()->BisectorNumber(),0);
+#endif
+
+       edgetoremove->SecondBisector()->SecondParameter
+         (edgetoremove->SecondBisector()->FirstParameter());
+#ifdef DEBUG_Mat
+       if(atool.TrimBisector(edgetoremove->SecondBisector()))
+         atool.Dump(edgetoremove->SecondBisector()->BisectorNumber(),1);
+#else
+       atool.TrimBisector(edgetoremove->SecondBisector());
+#endif
+       edgetoremove = theedgelist->Current();
+      }
+      bisectormap(noofbisectors)->SecondEdge(theedgelist->Current());
+         
+      theedgelist->PreviousItem()
+       ->SecondBisector(bisectormap(noofbisectors));
+      theedgelist->Current()->FirstBisector(bisectormap(noofbisectors));
+         
+      bisectormap(noofbisectors)->FirstVector
+       (atool.Tangent
+        (bisectormap(noofbisectors)->FirstBisector()
+         ->BisectorNumber()));
+      
+      bisectormap(noofbisectors)->SecondVector
+       (atool.Tangent
+        (bisectormap(noofbisectors)->LastBisector()
+         ->BisectorNumber()));
+      
+      noofbisectors++;
+      
+      theedgelist->PreviousItem()->Distance(-1);
+      theedgelist->Current()->Distance(-1);
+      
+      theedgelist->PreviousItem()->FirstBisector()
+       ->SecondParameter(Precision::Infinite());
+      theedgelist->Current()->SecondBisector()->FirstParameter(Precision::Infinite());
+    }
+
+    //-----------------------------------------------------------------------
+    // Test sur le nombre d iterations :
+    // A chaque iteration est elimine un element du contour qui ne sera plus
+    // reinsere par la suite => le nombre d iterartions doit etre < au nombre
+    // d elements.
+    // Le nombre d iteration maximum est fixe a numberofedges*numberofedges.
+    //-----------------------------------------------------------------------
+    if (NumberOfIte > NumberMaxOfIte) {
+      isDone = Standard_False;             //Echec calcul de la carte.
+      break;
+    }
+    NumberOfIte++;
+
+  }  //===============================================
+     //            Fin Boucle Principale.
+     //===============================================
+     
+  //----------
+  // etape 3.
+  //----------
+
+
+  //----------------------------------------------
+  // interupt = True => bissectrices semi_infinies.
+  //----------------------------------------------
+  
+  if(interrupt)
+    semiInfinite = Standard_True;
+  else {
+    semiInfinite = Standard_False;
+
+    //------------------------------------------------------------------
+    // Si le nombre d edge > 1 => le nombre d edge = 2 
+    //              (cf test sortie boucle principale)
+    // Les deux dernieres bisectrices separent les memes edges .
+    // Soit elles sont confondues si calcul a l interieur, soit elles
+    // sont semi-Infinies (exemple : contour compose seulement de deux
+    // arcs de cercles).                          
+    //------------------------------------------------------------------
+
+    if(theedgelist->Number() > 1) { //Now this branch is never reachable
+                                    //because the case edgenumber = 2 is processed in the main loop
+      theedgelist->First();
+      edge = theedgelist->Current();
+      if(edge->FirstBisector()->IndexNumber() == noofbisectors-1) {
+//  Modified by skv - Tue Sep 13 12:13:28 2005 IDEM Begin
+       if (atool.TrimBisector(edge->SecondBisector(),
+                              edge->FirstBisector()->IssuePoint())) {
+         if (edge->SecondBisector()->EndPoint() == 0)
+           edge->SecondBisector()->EndPoint(edge->FirstBisector()->IssuePoint());
+         bisectormap(noofbisectors-1)->AddBisector(edge->SecondBisector());
+       } else
+         semiInfinite = Standard_True;
+//  Modified by skv - Tue Sep 13 12:13:28 2005 IDEM End
+      }
+      else {
+//  Modified by skv - Tue Sep 13 12:13:28 2005 IDEM Begin
+       if (atool.TrimBisector(edge->FirstBisector(),
+                              edge->SecondBisector()->IssuePoint())) {
+         if (edge->FirstBisector()->EndPoint() == 0)
+           edge->FirstBisector()->EndPoint(edge->SecondBisector()->IssuePoint());
+         bisectormap(noofbisectors-1)->AddBisector(edge->FirstBisector());
+       } else 
+         semiInfinite = Standard_True;
+//  Modified by skv - Tue Sep 13 12:13:28 2005 IDEM End
+      }
+      if (!semiInfinite) {     
+       thenumberofbisectors--;
+       bisectormap(noofbisectors-1)->SecondEdge(edge);
+       bisectormap(noofbisectors-1)->BisectorNumber(-1);
+      }
+    }
+  }
+  if(semiInfinite) {
+    beginbisector = noofbisectors;
+    theedgelist->First();
+    for(i=0; i<theedgelist->Number(); i++) {
+      edge = theedgelist->Current();
+      bisectormap.Bind(noofbisectors,edge->SecondBisector());
+      noofbisectors++;
+      theedgelist->Next();
+    }
+
+  } 
+
+  //---------------------------
+  // Recuperations des racines.
+  //---------------------------
+
+  roots = new MAT_ListOfBisector;
+  
+  if (bisectormap(noofbisectors-1)->BisectorNumber() == -1) {
+    roots = bisectormap(noofbisectors-1)->List();
+    roots->First();
+    roots->Current()->FirstEdge()
+      ->Distance(bisectormap(noofbisectors-1)->DistIssuePoint());
+  }
+  else {
+    for (i=beginbisector;i<noofbisectors;i++) {
+      roots->BackAdd(bisectormap(i));
+    }
+  }
+  
+}
+
+//========================================================================
+//  function : LoadBisectorsToRemove
+//  purpose  : Chargement des bisectrices a effacer.
+//========================================================================
+void MAT2d_Mat2d::LoadBisectorsToRemove
+  (      Standard_Integer&     noofbisectorstoremove,
+   const Standard_Real         distance1,
+   const Standard_Real         distance2,
+   const Handle(MAT_Bisector)& firstbisectortoremove1,
+   const Handle(MAT_Bisector)& firstbisectortoremove2,
+   const Handle(MAT_Bisector)& lastbisectortoremove1,
+   const Handle(MAT_Bisector)& lastbisectortoremove2  )
+{
+
+  Standard_Integer found,index;
+  Handle(MAT_Bisector) firstbisectortoremove[2];
+  Handle(MAT_Bisector) lastbisectortoremove[2];
+
+  firstbisectortoremove[0] = firstbisectortoremove1;
+  firstbisectortoremove[1] = firstbisectortoremove2;
+  lastbisectortoremove[0]  = lastbisectortoremove1;
+  lastbisectortoremove[1]  = lastbisectortoremove2;
+  
+  if     (distance1  < Precision::Infinite() && 
+         distance2 == Precision::Infinite()    )   index =  0;
+  else if(distance2  < Precision::Infinite() && 
+         distance1 == Precision::Infinite()    )   index =  1;
+  else                                              index = -1;
+  
+  if(index != -1) {
+    found = noofbisectorstoremove;
+    for(int j=0; j<noofbisectorstoremove; j++) {
+      if(bisectoronetoremove(j)->BisectorNumber() ==
+        firstbisectortoremove[index]->BisectorNumber()) {
+       found = j;
+       if(bisectortwotoremove(j)->BisectorNumber() <
+          lastbisectortoremove[index]->BisectorNumber())found = -1;
+       break;
+      }
+    }
+    
+    if(found != -1) {
+#ifdef DEBUG_Mat
+      cout<<" first last bisector to remove :"<<
+       firstbisectortoremove[index]->BisectorNumber()<<" "<<
+         lastbisectortoremove[index]->BisectorNumber()<<endl;
+#endif
+      bisectoronetoremove.Bind(found,firstbisectortoremove[index]);
+      bisectortwotoremove.Bind(found,lastbisectortoremove[index]);
+      typeofbisectortoremove.Bind(found,index+1);
+      
+      if(found == noofbisectorstoremove)noofbisectorstoremove++;
+    }
+  }
+}
+
+//========================================================================
+//  function : Intersect
+//  purpose  : Si <aside=0> Intersection de <firstbisector> avec les
+//                 descendants de <secondbisector> les plus a gauche 
+//                (ie secondbisector->FirstBisector()->FirstBisector...)
+//                          Intersection de <secondbisector> avec les
+//                 descendants de <firstbisector> les plus a droite 
+//                (ie firstbisector->LastBisector()->LastBisector...)
+//                
+//             Si <aside=1> Intersection de <firstbisector> avec ses 
+//                descendants les plus a gauche et les plus a droite.
+//
+//             Si <aside=2> Intersection de <secondbisector> avec ses 
+//                descendants les plus a gauche et les plus a droite.
+//========================================================================v
+void MAT2d_Mat2d::Intersect(      MAT2d_Tool2d&                 atool,
+                       const Standard_Integer      aside,
+                             Standard_Integer&     noofbisectortoremove,
+                       const Handle(MAT_Bisector)& firstbisector,
+                       const Handle(MAT_Bisector)& secondbisector)
+{
+  Standard_Integer      bisectornumber;
+  Standard_Real         distant,saveparameter;
+  Standard_Real         distance[2];
+  Standard_Integer      intersectionpoint;
+  Handle(MAT_Bisector)  lastbisector,previousbisector;
+  Handle(MAT_Bisector)  firstbisectortoremove[2];
+  Handle(MAT_Bisector)  lastbisectortoremove[2];
+
+  distance[0] = Precision::Infinite();
+  distance[1] = Precision::Infinite();
+
+  for(bisectornumber = 0; bisectornumber<2; bisectornumber++) {
+    if(aside == 0) {
+      if(bisectornumber == 0) 
+       firstbisectortoremove[bisectornumber] = secondbisector;
+      else                    
+       firstbisectortoremove[bisectornumber] = firstbisector;
+    }
+    else if(aside == 1) {
+      firstbisectortoremove[bisectornumber] = firstbisector;
+    }
+    else {
+      firstbisectortoremove[bisectornumber] = secondbisector;
+    }
+    
+    lastbisector = firstbisectortoremove[bisectornumber];
+    
+    if(aside == 0) {
+      previousbisector = firstbisectortoremove[bisectornumber];
+    }
+    else {
+      if(firstbisectortoremove[bisectornumber]->List()->IsEmpty())continue;
+
+      if(bisectornumber == 0)
+       previousbisector = firstbisectortoremove[bisectornumber]
+                             ->FirstBisector();
+      else
+       previousbisector = firstbisectortoremove[bisectornumber]
+                             ->LastBisector();
+    }
+    
+    distant = distance[bisectornumber];
+    while(!previousbisector->List()->IsEmpty()) {
+
+      if(bisectornumber == 0)
+       previousbisector = previousbisector->FirstBisector();
+      else
+       previousbisector = previousbisector->LastBisector();
+      
+      if(aside == 1 || (aside == 0 && bisectornumber == 0)) {
+       saveparameter = previousbisector->FirstParameter();
+       distant = atool.IntersectBisector
+         (firstbisector,previousbisector,intersectionpoint);
+       previousbisector->FirstParameter(saveparameter);
+      }
+      else {
+       saveparameter = previousbisector->SecondParameter();
+       distant = atool.IntersectBisector
+         (previousbisector,secondbisector,intersectionpoint);
+       previousbisector->SecondParameter(saveparameter);
+      }
+      
+      if(distant < Precision::Infinite()) {
+       distance[bisectornumber] = distant;
+       lastbisectortoremove[bisectornumber] = lastbisector;
+      }
+         
+      lastbisector = previousbisector;
+    }
+  }
+
+  //---------------------------------------
+  // Chargement des bissectrices a effacer.
+  //---------------------------------------
+
+  LoadBisectorsToRemove(noofbisectortoremove,
+                       distance[0],distance[1],
+                       firstbisectortoremove[0],firstbisectortoremove[1],
+                       lastbisectortoremove[0] ,lastbisectortoremove[1]);
+}
+
+//========================================================================
+//  function : Init
+//  purpose  :
+//========================================================================
+void MAT2d_Mat2d::Init()
+{
+  roots->First();
+}
+
+//========================================================================
+//  function : More
+//  purpose  :
+//========================================================================
+Standard_Boolean MAT2d_Mat2d::More() const
+{
+  return roots->More();
+}
+
+//========================================================================
+//  function : Next
+//  purpose  :
+//========================================================================
+void MAT2d_Mat2d::Next()
+{
+  roots->Next();
+}
+
+//========================================================================
+//  function : Bisector 
+//  purpose  :
+//========================================================================
+Handle(MAT_Bisector) MAT2d_Mat2d::Bisector() const
+{
+  return roots->Current();
+}
+
+//========================================================================
+//  function : NumberOfBisectors
+//  purpose  :
+//========================================================================
+Standard_Integer MAT2d_Mat2d::NumberOfBisectors() const
+{
+  return thenumberofbisectors;
+}
+
+//========================================================================
+//  function : SemiInfinite
+//  purpose  :
+//========================================================================
+Standard_Boolean MAT2d_Mat2d::SemiInfinite() const
+{
+  return semiInfinite;
+}
+
+//========================================================================
+//  function : IsDone
+//  purpose  :
+//========================================================================
+Standard_Boolean MAT2d_Mat2d::IsDone() const
+{
+  return isDone;
+}
+
index e8c05eb7bc7b8c42435adbcb0276073cb1297772..8f32b1a134b15a05712823ae9995e2bded159187 100644 (file)
@@ -5,8 +5,8 @@
 --
 -- This file is part of Open CASCADE Technology software library.
 --
--- This library is free software; you can redistribute it and / or modify it
--- under the terms of the GNU Lesser General Public version 2.1 as published
+-- This library is free software; you can redistribute it and/or modify it under
+-- the terms of the GNU Lesser General Public License version 2.1 as published
 -- by the Free Software Foundation, with special exception defined in the file
 -- OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 -- distribution for complete text of the license and disclaimer of any warranty.
@@ -21,7 +21,7 @@ class Tool2d from MAT2d
 
 
 uses
-
+    JoinType                  from GeomAbs,
     Bisec                     from Bisector,
     Side                      from MAT,
     Bisector                  from MAT,
@@ -47,6 +47,9 @@ is
        --- Purpose :<aSide> defines the side of the computation of the map. 
     is static;
 
+    SetJoinType(me : in out ; aJoinType : JoinType from GeomAbs)
+    is static;
+
     InitItems(me          : in out                    ; 
               aCircuit    :        Circuit from MAT2d )
        --- Purpose : InitItems cuts the line in Items.
@@ -72,13 +75,15 @@ is
        --            Returns the index of this point in <theGeomPnts>.    
     returns Integer is static;
     
-    TangentBefore(me : in out ; anitem : Integer) 
+    TangentBefore(me : in out ; anitem : Integer;
+                               IsOpenResult : Boolean)
        --- Purpose : Creates the Tangent at the end of the Item defined
        --            by <anitem>. Returns the index of this vector in
        --            <theGeomVecs>
     returns Integer is static;
     
-    TangentAfter(me : in out ; anitem : Integer) 
+    TangentAfter(me : in out ; anitem : Integer;
+                              IsOpenResult : Boolean)
        --- Purpose : Creates the Reversed Tangent at the origin of the Item 
        --            defined by <anitem>. Returns the index of this vector in
        --            <theGeomVecs>
@@ -90,11 +95,11 @@ is
        --            <theGeomVecs>
     returns Integer is static;
     
-    CreateBisector(me : in out ; abisector : mutable Bisector from MAT)
+    CreateBisector(me : in out ; abisector : Bisector from MAT)
        --- Purpose : Creates the geometric bisector defined by <abisector>.
     is static;
     
-    TrimBisector(me : in out ; abisector : mutable Bisector from MAT)   
+    TrimBisector(me : in out ; abisector : Bisector from MAT)   
        --- Purpose : Trims the geometric bisector by the <firstparameter>
        --            of <abisector>.
        --            If the parameter is out of the bisector, Return FALSE.
@@ -102,7 +107,7 @@ is
     returns Boolean is static;
     
     TrimBisector(me        : in out ; 
-                abisector : mutable Bisector from MAT ;
+                abisector : Bisector from MAT ;
                  apoint    : Integer)
         --- Purpose : Trims the geometric bisector by the point of index
         --            <apoint> in <theGeomPnts>.
@@ -111,8 +116,8 @@ is
     returns Boolean is static;
 
     IntersectBisector(me          : in out ;
-                      bisectorone : mutable Bisector from MAT ;
-                      bisectortwo : mutable Bisector from MAT ;
+                      bisectorone : Bisector from MAT ;
+                      bisectortwo : Bisector from MAT ;
                       intpnt      : in out Integer)
         --- Purpose  : Computes  the point  of  intersection between  the
         --             bisectors defined  by  <bisectorone>  and  
@@ -220,6 +225,7 @@ is
 fields
 
     theDirection          : Real;
+    theJoinType           : JoinType from GeomAbs;
     theNumberOfBisectors  : Integer;
     theNumberOfPnts       : Integer;
     theNumberOfVecs       : Integer;
index 3eab062007c2745de92c2a0f58ee4614be2b4d1c..8e149853ada6ec0b97be3f6a4a90bffa172a899e 100644 (file)
@@ -5,8 +5,8 @@
 //
 // This file is part of Open CASCADE Technology software library.
 //
-// This library is free software; you can redistribute it and / or modify it
-// under the terms of the GNU Lesser General Public version 2.1 as published
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
 // by the Free Software Foundation, with special exception defined in the file
 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 // distribution for complete text of the license and disclaimer of any warranty.
@@ -100,6 +100,7 @@ static Standard_Real MAT2d_TOLCONF = 1.e-7;
 MAT2d_Tool2d::MAT2d_Tool2d()
 {
   theDirection         = 1.;
+  theJoinType = GeomAbs_Arc; //default
   theNumberOfBisectors = 0;
   theNumberOfVecs      = 0;
   theNumberOfPnts      = 0;
@@ -132,6 +133,15 @@ void MAT2d_Tool2d::Sense(const MAT_Side aside)
   else                  theDirection = -1.;
 }
 
+//=============================================================================
+//function : SetJoinType
+//purpose  :
+//=============================================================================
+void MAT2d_Tool2d::SetJoinType(const GeomAbs_JoinType aJoinType)
+{
+  theJoinType = aJoinType;
+}
+
 //=============================================================================
 //function : NumberOfItems
 //purpose  :
@@ -189,13 +199,17 @@ Standard_Integer MAT2d_Tool2d::FirstPoint(const Standard_Integer anitem,
 //function : TangentBefore
 //purpose  :
 //=============================================================================
-Standard_Integer MAT2d_Tool2d::TangentBefore(const Standard_Integer anitem) 
+Standard_Integer MAT2d_Tool2d::TangentBefore(const Standard_Integer anitem,
+                                             const Standard_Boolean IsOpenResult)
 {
   Standard_Integer     item;
   Handle(Geom2d_Curve) curve;
   theNumberOfVecs++;
-  
-  item  = (anitem == theCircuit->NumberOfItems()) ? 1 : (anitem + 1);
+
+  if (!IsOpenResult)
+    item  = (anitem == theCircuit->NumberOfItems()) ? 1 : (anitem + 1);
+  else
+    item = (anitem == theCircuit->NumberOfItems()) ? (anitem - 1) : (anitem + 1);
   if (theCircuit->ConnexionOn(item)){
     Standard_Real x1,y1,x2,y2;
     theCircuit->Connexion(item)->PointOnFirst().Coord(x1,y1);
@@ -212,7 +226,9 @@ Standard_Integer MAT2d_Tool2d::TangentBefore(const Standard_Integer anitem)
   }
   else {
     curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(item));
-    theGeomVecs.Bind(theNumberOfVecs,curve->DN(curve->FirstParameter(),1));
+    Standard_Real param = (IsOpenResult && anitem == theCircuit->NumberOfItems())?
+      curve->LastParameter() : curve->FirstParameter();
+    theGeomVecs.Bind(theNumberOfVecs,curve->DN(param,1));
   }
 
   return theNumberOfVecs;
@@ -222,7 +238,8 @@ Standard_Integer MAT2d_Tool2d::TangentBefore(const Standard_Integer anitem)
 //function : TangentAfter
 //purpose  :
 //=============================================================================
-Standard_Integer MAT2d_Tool2d::TangentAfter(const Standard_Integer anitem)
+Standard_Integer MAT2d_Tool2d::TangentAfter(const Standard_Integer anitem,
+                                            const Standard_Boolean IsOpenResult)
 {
   Standard_Integer     item;
   Handle(Geom2d_Curve) curve;
@@ -244,9 +261,14 @@ Standard_Integer MAT2d_Tool2d::TangentAfter(const Standard_Integer anitem)
     thevector = curve->DN(curve->FirstParameter(),1);
   }
   else {
-    item      = (anitem == 1) ? theCircuit->NumberOfItems() : (anitem - 1);
+    if (!IsOpenResult)
+      item      = (anitem == 1) ? theCircuit->NumberOfItems() : (anitem - 1);
+    else
+      item = (anitem == 1) ? 2 : (anitem - 1);
     curve     = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(item));
-    thevector = curve->DN(curve->LastParameter(),1);
+    Standard_Real param = (IsOpenResult && anitem == 1)?
+      curve->FirstParameter() : curve->LastParameter();
+    thevector = curve->DN(param,1);
   }
   theGeomVecs.Bind(theNumberOfVecs,thevector.Reversed());
   return theNumberOfVecs;
@@ -406,8 +428,7 @@ void MAT2d_Tool2d::TrimBisec (      Bisector_Bisec&  B1,
   
   //gp_Vec2d             Tan1,Tan2;
   gp_Pnt2d             Ori; //PEdge;
-  Standard_Integer     IPrec,INext;
-  IPrec = (IndexEdge == 1)  ? theCircuit->NumberOfItems() : (IndexEdge - 1);
+  Standard_Integer     INext;
   INext = (IndexEdge == theCircuit->NumberOfItems()) ? 1  : (IndexEdge + 1);
   
   Handle(Standard_Type) EdgeType = theCircuit->Value(IndexEdge)->DynamicType();
@@ -535,7 +556,6 @@ Standard_Boolean MAT2d_Tool2d::Projection (const Standard_Integer IEdge   ,
   Handle(Standard_Type)       Type   = Elt->DynamicType();     
   Handle(Geom2d_TrimmedCurve) Curve; 
   Standard_Integer            INext;   
-  Standard_Real               ParameterOnC;
   Standard_Real               Eps = MAT2d_TOLCONF;//*10.;
 
   if (Type == STANDARD_TYPE(Geom2d_CartesianPoint)) {  
@@ -586,7 +606,6 @@ Standard_Boolean MAT2d_Tool2d::Projection (const Standard_Integer IEdge   ,
       if (Extremas.NbExt() == 0 ) return Standard_False; // Pas de solution!
       for (Standard_Integer i = 1; i <= Extremas.NbExt(); i++) {
        if (Extremas.SquareDistance(i) < Distance * Distance) {
-         ParameterOnC  = Extremas.Point(i).Parameter();
          Distance      = sqrt (Extremas.SquareDistance(i));
        }
       }
@@ -640,6 +659,9 @@ Standard_Boolean MAT2d_Tool2d::IsSameDistance (
   Standard_Real EpsDist = MAT2d_TOLCONF*100. ;
   Distance = Dist(1);
   for (Standard_Integer i = 1; i <= 4; i++){
+    if (theJoinType == GeomAbs_Intersection &&
+        Precision::IsInfinite(Dist(i)))
+      continue;
     if (Abs(Dist(i) - Distance) > EpsDist) {
       Distance = Precision::Infinite();
       return Standard_False;
index 80ba7106fb4442e769f4b56a17a536a8a18054b6..696c15bf114ff1c675af9077ad6a8ad2bfd5bde3 100644 (file)
@@ -1,17 +1,22 @@
 // Created on: 2002-07-30
 // Created by: Michael SAZONOV
-// Copyright (c) 2002-2014 OPEN CASCADE SAS
+// Copyright (c) 2002-2012 OPEN CASCADE SAS
 //
-// This file is part of Open CASCADE Technology software library.
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
 //
-// This library is free software; you can redistribute it and / or modify it
-// under the terms of the GNU Lesser General Public version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
 //
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
 
 #ifndef NCollection_UBTree_HeaderFile
 #define NCollection_UBTree_HeaderFile
@@ -209,7 +214,7 @@ template <class TheObjType, class TheBndType> class NCollection_UBTree
      * This method should be used instead of operator delete.
      */ 
     static void delNode (TreeNode * theNode,
-                         Handle(NCollection_BaseAllocator)& theAlloc)
+                         const Handle(NCollection_BaseAllocator)& theAlloc)
     {
       if (theNode) {
         if (theNode -> myChildren) {
diff --git a/src/NCollection/NCollection_WinHeapAllocator.cxx b/src/NCollection/NCollection_WinHeapAllocator.cxx
new file mode 100644 (file)
index 0000000..d65814b
--- /dev/null
@@ -0,0 +1,87 @@
+// File:      NCollection_WinHeapAllocator.cxx
+// Created:   22.07.11
+// Author:    Kirill GAVRILOV
+// Copyright: Open Cascade 2011
+
+#include <NCollection_WinHeapAllocator.hxx>
+#include <Standard_OutOfMemory.hxx>
+
+#if(defined(_WIN32) || defined(__WIN32__))
+  #include <windows.h>
+#endif
+
+IMPLEMENT_STANDARD_HANDLE (NCollection_WinHeapAllocator,
+                           NCollection_BaseAllocator)
+IMPLEMENT_STANDARD_RTTIEXT(NCollection_WinHeapAllocator,
+                           NCollection_BaseAllocator)
+
+//=======================================================================
+//function : NCollection_WinHeapAllocator
+//purpose  : Main constructor
+//=======================================================================
+NCollection_WinHeapAllocator::NCollection_WinHeapAllocator
+                                        (const size_t theInitSizeBytes)
+: NCollection_BaseAllocator(),
+#if(defined(_WIN32) || defined(__WIN32__))
+  myHeapH (HeapCreate (0, theInitSizeBytes, 0)),
+#endif
+  myToZeroMemory (Standard_False)
+{
+#if(defined(_WIN32) || defined(__WIN32__))
+  // activate LHF to improve small size allocations
+  ULONG aHeapInfo = 2;
+  HeapSetInformation (myHeapH, HeapCompatibilityInformation,
+                      &aHeapInfo, sizeof(aHeapInfo));
+#endif
+}
+
+//=======================================================================
+//function : ~NCollection_WinHeapAllocator
+//purpose  : Destructor
+//=======================================================================
+NCollection_WinHeapAllocator::~NCollection_WinHeapAllocator()
+{
+#if(defined(_WIN32) || defined(__WIN32__))
+  HeapDestroy (myHeapH);
+#endif
+}
+
+
+//=======================================================================
+//function : Allocate
+//purpose  :
+//=======================================================================
+void* NCollection_WinHeapAllocator::Allocate (const Standard_Size theSize)
+{
+  // the size is rounded up to word size.
+  const Standard_Size aRoundSize = (theSize + 3) & ~0x3;
+#if(defined(_WIN32) || defined(__WIN32__))
+  void* aResult = HeapAlloc (myHeapH, myToZeroMemory ? HEAP_ZERO_MEMORY : 0,
+                             aRoundSize);
+#else
+  void* aResult = malloc (aRoundSize);
+#endif
+  if (aResult == NULL)
+  {
+    char aBuf[128];
+    sprintf (aBuf, "Failed to allocate %d bytes in local dynamic heap", theSize);
+    Standard_OutOfMemory::Raise (&aBuf[0]);
+  }
+  return aResult;
+}
+
+//=======================================================================
+//function : Free
+//purpose  :
+//=======================================================================
+void NCollection_WinHeapAllocator::Free (void* theAddress)
+{
+  if (theAddress != NULL)
+  {
+  #if(defined(_WIN32) || defined(__WIN32__))
+    HeapFree (myHeapH, 0, theAddress);
+  #else
+    free (theAddress);
+  #endif
+  }
+}
diff --git a/src/NCollection/NCollection_WinHeapAllocator.hxx b/src/NCollection/NCollection_WinHeapAllocator.hxx
new file mode 100644 (file)
index 0000000..1e5c13a
--- /dev/null
@@ -0,0 +1,55 @@
+// File:      NCollection_WinHeapAllocator.hxx
+// Created:   22.07.11
+// Author:    Kirill GAVRILOV
+// Copyright: Open Cascade 2011
+
+#ifndef NCollection_WinHeapAllocator_HeaderFile
+#define NCollection_WinHeapAllocator_HeaderFile
+
+#include <NCollection_BaseAllocator.hxx>
+
+//! This memory allocator creates dedicated heap for allocations.
+//! This technics available only on Windows platform
+//! (no alternative on Unix systems).
+//! It may be used to take control over memory fragmentation
+//! because on destruction ALL allocated memory will be released
+//! to the system.
+//!
+//! This allocator can also be created per each working thread
+//! hovewer it real multi-threading performance is dubious.
+//!
+//! Notice that this also means that existing pointers will be broken
+//! and you shoould control that allocator is alive along all objects
+//! allocated with him.
+class NCollection_WinHeapAllocator : public NCollection_BaseAllocator
+{
+public:
+
+  //! Main constructor
+  Standard_EXPORT NCollection_WinHeapAllocator (const size_t theInitSizeBytes = 0x80000);
+
+  Standard_EXPORT virtual ~NCollection_WinHeapAllocator();
+
+  Standard_EXPORT virtual void* Allocate (const Standard_Size theSize);
+
+  Standard_EXPORT virtual void  Free (void* theAddress);
+
+  // Declaration of CASCADE RTTI
+  DEFINE_STANDARD_RTTI(NCollection_WinHeapAllocator)
+
+private:
+  //! Copy constructor - prohibited
+  NCollection_WinHeapAllocator (const NCollection_WinHeapAllocator& );
+
+private:
+#if(defined(_WIN32) || defined(__WIN32__))
+  void* myHeapH;
+#endif
+  Standard_Boolean myToZeroMemory;
+
+};
+
+// Definition of HANDLE object using Standard_DefineHandle.hxx
+DEFINE_STANDARD_HANDLE (NCollection_WinHeapAllocator, NCollection_BaseAllocator)
+
+#endif //NCollection_WinHeapAllocator_HeaderFile
index 1bad545df1004769b7473c2bcbfbc8132237d597..94d18a96d39f9fe56acef5fe211c55cb94d545db 100755 (executable)
@@ -2,28 +2,49 @@ EXTERNLIB
 FILES
 NIS_Allocator.cxx
 NIS_Allocator.hxx
+NIS_DrawDirect.cxx
+NIS_DrawDirect.hxx
 NIS_Drawer.cxx
 NIS_Drawer.hxx
 NIS_DrawList.cxx
 NIS_DrawList.hxx
+NIS_IndexLists.cxx
+NIS_IndexLists.hxx
 NIS_InteractiveContext.cxx
 NIS_InteractiveContext.hxx
 NIS_InteractiveObject.cxx
 NIS_InteractiveObject.hxx
+NIS_Line.cxx
+NIS_Line.hxx
+NIS_LineDrawer.cxx
+NIS_LineDrawer.hxx
 NIS_ObjectsIterator.cxx
 NIS_ObjectsIterator.hxx
+NIS_Point.cxx
+NIS_Point.hxx
+NIS_PointDrawer.cxx
+NIS_PointDrawer.hxx
+NIS_PolygonSelector.cxx
+NIS_PolygonSelector.hxx
 NIS_SelectFilter.cxx
 NIS_SelectFilter.hxx
 NIS_Surface.cxx
 NIS_Surface.hxx
 NIS_SurfaceDrawer.cxx
 NIS_SurfaceDrawer.hxx
+NIS_Text.cxx
+NIS_Text.hxx
+NIS_TextDrawer.cxx
+NIS_TextDrawer.hxx
+NIS_Tools.cxx
+NIS_Tools.hxx
 NIS_Triangulated.cxx
 NIS_Triangulated.hxx
 NIS_TriangulatedDrawer.cxx
 NIS_TriangulatedDrawer.hxx
 NIS_View.cxx
 NIS_View.hxx
+NIS_ViewData.hxx
 Handle_NIS_InteractiveObject.hxx
 Handle_NIS_View.hxx
 NIS_CMPLRS.edl
index e21da0396e3dbfa5dc7e5c12bffd26c31cc364c1..64479d182d48214bf11cb64e6ced84fda5dae2ab 100644 (file)
@@ -22,6 +22,7 @@
  * Subclass of Incremental Allocator. It is aware of the total
  * allocated and released memory. Used in NIS_Interactive context as
  * private allocator that manages all memory used by interactive objects.
+ * @ingroup nis_library
  */
 
 class NIS_Allocator : public NCollection_IncAllocator
index 0cb6862ee3e828a4af5a5cd969f1ea3b2b82456c..44178a2a5c7823a610bd497067845c7c590c766d 100644 (file)
@@ -24,6 +24,7 @@
 //=======================================================================
 
 NIS_DrawList::NIS_DrawList ()
+  : myIsCompiled(Standard_False)
 {
 #ifdef ARRAY_LISTS
   myListID = 0;
@@ -47,7 +48,8 @@ NIS_DrawList::NIS_DrawList ()
 //=======================================================================
 
 NIS_DrawList::NIS_DrawList (const Handle_NIS_View& theView)
-  : myView      (theView)
+  : myView      (theView),
+    myIsCompiled(Standard_False)
 {
 #ifdef ARRAY_LISTS
   myListID = 0;
@@ -157,9 +159,12 @@ void NIS_DrawList::BeginPrepare (const Standard_Integer theType)
 //purpose  :
 //=======================================================================
 
-void NIS_DrawList::EndPrepare (const Standard_Integer theType)
+void NIS_DrawList::EndPrepare (const Standard_Integer theType,
+                               const Standard_Boolean isCompiled)
 {
-  glEndList ();
+  if (isCompiled)
+    glEndList ();
+  myIsCompiled = isCompiled;
   myIsUpdated[theType] = Standard_False;
 }
 
@@ -170,7 +175,8 @@ void NIS_DrawList::EndPrepare (const Standard_Integer theType)
 
 void NIS_DrawList::Call (const Standard_Integer theType)
 {
-  glCallList (GetListID (theType));
+  if (myIsCompiled)
+    glCallList (GetListID (theType));
 }
 
 //=======================================================================
index d2887f7023b08ae5094769afc1259fe1dad48a55..bd97997142df43cf4f19c8893fa2ea1a06fc3b2d 100644 (file)
@@ -27,6 +27,7 @@ class NIS_InteractiveContext;
  * in the given drawer are removed.
  * When the macro is undefined every draw list is created when needed and it is
  * destroyed when there is no objects to show in this draw list.
+ * @ingroup nis_library
  */
 //#define ARRAY_LISTS
 
@@ -47,7 +48,9 @@ class NIS_DrawList
   Standard_EXPORT NIS_DrawList ();
 
   /**
-   * Constructor
+   * Constructor.
+   * @param theView
+   *   View instance where the list is created; for shared lists it is NULL.
    */
   Standard_EXPORT NIS_DrawList (const Handle_NIS_View& theView);
 
@@ -95,8 +98,12 @@ class NIS_DrawList
    * by BeginPrepare.
    * @param theType
    *   Integer value coinciding with the enumerated NIS_Drawer::DrawType.
+   * @param isComp
+   *   Defines if the list should be compiled and then called. Otherwise
+   *   OpenGL list is not created but the commands are executed immediately.
    */
-  Standard_EXPORT virtual void  EndPrepare     (const Standard_Integer theType);
+  Standard_EXPORT virtual void  EndPrepare     (const Standard_Integer theType,
+                                                const Standard_Boolean isComp);
 
   /**
    * Call the previously prepared list when the screen is redrawn.
@@ -153,7 +160,7 @@ class NIS_DrawList
  NIS_DrawList             (const NIS_DrawList& theOther);
  // NIS_DrawList& operator = (const NIS_DrawList& theOther);
 
- private:
+ protected:
   // ---------- PRIVATE FIELDS ----------
 
   Handle_NIS_View                                myView;
@@ -163,6 +170,7 @@ class NIS_DrawList
   Standard_Integer                               myListID[5];
 #endif
   Standard_Boolean                               myIsUpdated[5];
+  Standard_Boolean                               myIsCompiled;
   NCollection_List<Handle_NIS_InteractiveObject> myDynHilighted;
 };
 
index fc2a57d776cf03dd9ad8e05e58702c4ce600a620..dc001574c9f0c8203b4246f3c8626a46f578973e 100644 (file)
 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
 #include <Standard_TypeMismatch.hxx>
 #include <Standard_NoSuchObject.hxx>
+#include <Standard_OutOfRange.hxx>
+#include <Standard_NullValue.hxx>
 
 IMPLEMENT_STANDARD_HANDLE  (NIS_Drawer, Standard_Transient)
 IMPLEMENT_STANDARD_RTTIEXT (NIS_Drawer, Standard_Transient)
 
+//=======================================================================
+//function : NIS_Drawer
+//purpose  : Constructor
+//=======================================================================
+
+NIS_Drawer::NIS_Drawer (const Quantity_Color& theHilight,
+                        const Quantity_Color& theDynHilight)
+: myTransparency     (0.f),
+  myIniId            (0),
+  myObjPerDrawer     (1024),
+  myPriority         (Priority_Default),
+  myIsCompiled       (Standard_True),
+  myCtx              (0L)
+{
+  myColor[Draw_Hilighted]    = theHilight;
+  myColor[Draw_DynHilighted] = theDynHilight;
+}
+
+//=======================================================================
+//function : SetCompiled
+//purpose  : 
+//=======================================================================
+
+void NIS_Drawer::SetCompiled (const Standard_Boolean isCompiled)
+{
+  if (isCompiled) {
+    if (myIsCompiled == Standard_False)
+      SetUpdated(Draw_Normal, Draw_Top, Draw_Transparent, Draw_Hilighted);
+  }
+  myIsCompiled = isCompiled;
+}
+
 //=======================================================================
 //function : NIS_Drawer
 //purpose  : Destructor
@@ -47,7 +81,14 @@ void NIS_Drawer::Assign (const Handle_NIS_Drawer& theOther)
     Standard_TypeMismatch::Raise ("NIS_Drawer::Assign");
   myIniId        = theOther->myIniId;
   myObjPerDrawer = theOther->myObjPerDrawer;
+  myPriority     = theOther->myPriority;
+  myIsCompiled   = theOther->myIsCompiled;
   myTransparency = theOther->myTransparency;
+  myColor[Draw_Normal]       = theOther->myColor[Draw_Normal];
+  myColor[Draw_Top]          = theOther->myColor[Draw_Top];
+  myColor[Draw_Transparent]  = theOther->myColor[Draw_Transparent];
+  myColor[Draw_Hilighted]    = theOther->myColor[Draw_Hilighted];
+  myColor[Draw_DynHilighted] = theOther->myColor[Draw_DynHilighted];
 }
 
 //=======================================================================
@@ -62,6 +103,18 @@ Standard_Integer NIS_Drawer::HashCode(const Standard_Integer theN) const
   return ((aKey & 0x7fffffff) % theN) + 1;
 }
 
+//=======================================================================
+//function : areEqual
+//purpose  : Compare two colors, return True if they seem to be equal
+//=======================================================================
+
+Standard_Boolean NIS_Drawer::areEqual (const Quantity_Color& theColor0,
+                                       const Quantity_Color& theColor1)
+{
+  static const Standard_Real anEps2 = 1e-7;
+  return (theColor0.SquareDistance(theColor1) < anEps2);
+}
+
 //=======================================================================
 //function : IsEqual
 //purpose  : 
@@ -69,17 +122,24 @@ Standard_Integer NIS_Drawer::HashCode(const Standard_Integer theN) const
 
 Standard_Boolean NIS_Drawer::IsEqual (const Handle_NIS_Drawer& theOther) const
 {
-  Standard_Boolean aResult (Standard_False);
-  if (theOther.IsNull() == Standard_False)
-    if (DynamicType() == theOther->DynamicType())
-      if (theOther->myIniId/theOther->myObjPerDrawer == myIniId/myObjPerDrawer)
-        aResult = Standard_True;
-
-  if (aResult)
-    if (fabs(myTransparency - theOther->myTransparency) > 0.01)
-      aResult = Standard_False;
+  if (theOther.IsNull()
+   || DynamicType() != theOther->DynamicType()
+   || (theOther->myIniId/theOther->myObjPerDrawer != myIniId/myObjPerDrawer)
+   || theOther->myPriority   != myPriority
+   || theOther->myIsCompiled != myIsCompiled
+   || fabs(myTransparency - theOther->myTransparency) > 0.01)
+  {
+    return Standard_False;
+  }
 
-  return aResult;
+  for (Standard_Integer i = 0; i < 5; i++)
+  {
+    if (!areEqual (theOther->myColor[i], myColor[i]))
+    {
+      return Standard_False;
+    }
+  }
+  return Standard_True;
 }
 
 //=======================================================================
@@ -147,10 +207,13 @@ void NIS_Drawer::redraw (const DrawType           theType,
       NIS_DrawList& aDrawList = * anIter.ChangeValue();
       const Handle_NIS_View& aView = aDrawList.GetView();
       if (aView == theView || aView.IsNull()) {
-        if (aDrawList.IsUpdated(theType)) {
+        if (aDrawList.IsUpdated(theType) || myIsCompiled == Standard_False) {
           // Get the IDs of objects concerned
           TColStd_PackedMapOfInteger mapObj;
-          mapObj.Intersection (myCtx->myMapObjects[theType], myMapID);
+          if (theType != NIS_Drawer::Draw_DynHilighted)
+          {
+            mapObj.Intersection (myCtx->GetObjectsOfType (theType), myMapID);
+          }
 #ifndef ARRAY_LISTS
           // Release the list that is no more in use
           if (mapObj.IsEmpty() && theType != Draw_DynHilighted) {
@@ -158,9 +221,10 @@ void NIS_Drawer::redraw (const DrawType           theType,
             break;
           }
 #endif
-          aDrawList.BeginPrepare(theType);
+          if (myIsCompiled)
+            aDrawList.BeginPrepare(theType);
           prepareList (theType, aDrawList, mapObj);
-          aDrawList.EndPrepare(theType);
+          aDrawList.EndPrepare(theType, myIsCompiled);
         }
         if (aDrawList.GetListID(theType) > 0)
           aDrawList.Call(theType);
@@ -282,21 +346,53 @@ void NIS_Drawer::SetDynamicHilighted
 //=======================================================================
 
 void NIS_Drawer::removeObject (const NIS_InteractiveObject * theObj,
-                               const Standard_Boolean      isUpdateViews)
+                               const Standard_Boolean        isUpdateViews)
 {
   const Standard_Integer anID = theObj->ID();
   myMapID.Remove (anID);
+
   // Stop dynamic hilighting if it has been activated
   if (theObj->IsDynHilighted())
+  {
     SetDynamicHilighted (Standard_False, theObj);
-  if (myMapID.IsEmpty()) {
+  }
+  if (myMapID.IsEmpty())
+  {
     UpdateExListId(NULL);
+
     // Remove the drawer from context.
-    myCtx->myDrawers.Remove(this);
+    if (myCtx->myDrawers.Remove(this))
+    {
+      --myCtx->myPriorities[myPriority];
+    }
   }
-  // Set Updated for the draw type.
   else if (theObj->IsHidden() == Standard_False && isUpdateViews)
+  {
+    // Set Updated for the draw type.
     SetUpdated (theObj->DrawType());
+  }
+}
+
+//=======================================================================
+//function : drawObject
+//purpose  : Draw a single object
+//=======================================================================
+
+Standard_Boolean NIS_Drawer::drawObject
+                            (const Handle_NIS_InteractiveObject& theObj,
+                             const DrawType                   theType,
+                             const NIS_DrawList&              theDrawList)
+{
+  Standard_Boolean aResult(Standard_False);
+  if (theObj->IsHidden() == Standard_False &&
+      theObj->GetDrawer().operator->() == this)
+  {
+    BeforeDraw(theType, theDrawList);
+    Draw(theObj, theType, theDrawList);
+    AfterDraw(theType, theDrawList);
+    aResult = Standard_True;
+  }
+  return aResult;
 }
 
 //=======================================================================
@@ -313,7 +409,8 @@ void NIS_Drawer::addObject (const NIS_InteractiveObject * theObj,
   // Fill the drawer (if new) with DrawList instances for available Views.
   if ( myLists.IsEmpty())
   {
-    if (isShareList)
+    // only compiled lists may be shared between views
+    if (isShareList && myIsCompiled)
       myLists.Append (createDefaultList(NULL));
     else {
       NCollection_List<Handle_NIS_View>::Iterator anIter(GetContext()->myViews);
@@ -412,3 +509,52 @@ NIS_DrawList* NIS_Drawer::createDefaultList
 {
   return new NIS_DrawList(theView);
 }
+
+//=======================================================================
+//function : SetColor
+//purpose  : Set the color for hilight or dynamic hilight presentation.
+//=======================================================================
+
+void NIS_Drawer::SetColor (const NIS_Drawer::DrawType theDrawType,
+                           const Quantity_Color&      theColor)
+{
+  Standard_OutOfRange_Raise_if(theDrawType < Draw_Normal ||
+                               theDrawType > Draw_DynHilighted,
+                               "NISDrawer::SetColor: Irrelevant DrawType"); 
+  if (theDrawType == Draw_Normal) {
+    myColor[Draw_Top] = theColor;
+    myColor[Draw_Transparent] = theColor;
+  }
+  myColor[theDrawType] = theColor;
+}
+
+//=======================================================================
+//function : GetColor
+//purpose  : Get Hilighted color of the presentation.
+//=======================================================================
+
+Quantity_Color NIS_Drawer::GetColor
+                                (const NIS_Drawer::DrawType theDrawType) const
+{
+  Standard_OutOfRange_Raise_if(theDrawType < Draw_Normal ||
+                               theDrawType > Draw_DynHilighted,
+                               "NISDrawer::GetColor: Irrelevant DrawType"); 
+  return myColor[theDrawType];
+}
+
+//=======================================================================
+//function : SetContext
+//purpose  : Sets the Interactive Context.
+//=======================================================================
+
+void NIS_Drawer::SetContext ( NIS_InteractiveContext *theCtx )
+{
+    Standard_NullValue_Raise_if
+        (theCtx == 0L, "NIS_InteractiveObject::SetContext: context is NULL");
+
+    myCtx = theCtx;
+    if (myCtx->myDrawers.Add (this))
+    {
+      ++myCtx->myPriorities[myPriority];
+    }
+}
index f97e581974f782071260af950df85db0810db971..53cbaefe083425bd66e7c9b09604c6f66ca1d3c4 100644 (file)
@@ -22,6 +22,7 @@
 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
 #include <NIS_DrawList.hxx>
 #include <Bnd_B3f.hxx>
+#include <Quantity_Color.hxx>
 
 #ifdef WNT
 #pragma warning (push)
@@ -102,26 +103,59 @@ template <class A> class NCollection_Vector;
  * Drawer instances coincide.
  * <p>
  * @section nis_drawer_cloning Cloning Drawer instances
- * It is possible to clone a Drawer instance with the viryual method Assign().
+ * It is possible to clone a Drawer instance with the virtual method Assign().
  * This method copies all visual properties and other important data from the
  * Drawer provided as parameter. Method Clone() also should be very carefully
  * implemented for any new Drawer type, to make sure that all necessary data
  * fields and structures are properly copied.
+ * <p>
+ * @section nis_drawer_compiled Compiled lists
+ * By default a drawer class maintains a number of draw lists each corresponding
+ * to a set of interactive objects shown inside a common OpenGl list. This is
+ * the optimal way to achieve the performance but some OpenGL features may be
+ * incompatible with it. For instance, if you need to provide a pixel position
+ * or width to GL command (like glDrawPixels) then GL lists will be irelevant -
+ * normally the lists are not recompiled at any change of viewport geometry.
+ * <br>
+ * To overcome this limitation you can define a drawer with IsCompiled property
+ * set to False, this will guarantee that every refresh will follow the whole
+ * code of Draw() method including the values that are variable or cannot be
+ * stored in GL lists. 
+ * @ingroup nis_library
  */
 
 class NIS_Drawer : public Standard_Transient
 {
  public:
-#if defined(WNT) && (_MSC_VER >= 1400)
-  enum DrawType : unsigned int {
+
+  //! Drawing scenarious
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+  enum DrawType : unsigned int
 #else
-  enum DrawType {
+  enum DrawType
 #endif
-    Draw_Normal         = 0,
-    Draw_Top            = 1,
-    Draw_Transparent    = 2,
-    Draw_Hilighted      = 3,
-    Draw_DynHilighted   = 4
+  {
+    Draw_Normal         = 0, //!< normal object
+    Draw_Top            = 1, //!< normal object witj topmost flag
+    Draw_Transparent    = 2, //!< transparent object, drawn after opaque objects
+    Draw_Hilighted      = 3, //!< hilighted (selected) object
+    Draw_DynHilighted   = 4, //!< dynamic hilighted (mouse picking without click)
+    Draw_TypeNb
+  };
+
+  //! Drawing priority (within drawing scenario)
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+  enum PriorityLevel : unsigned int
+#else
+  enum PriorityLevel
+#endif
+  {
+    Priority_Bottommost = 0, //!< objects to be drawn before others
+    Priority_Bottom     = 1, //!< objects to be drawn before others
+    Priority_Default    = 2, //!< default priority
+    Priority_Top        = 3, //!< objects to be drawn after  others
+    Priority_Topmost    = 4, //!< objects to be drawn after  others
+    Priority_LevelsNb
   };
 
  public:
@@ -131,12 +165,18 @@ class NIS_Drawer : public Standard_Transient
   /**
    * Empty constructor.
    */
-  inline NIS_Drawer ()
-   : myTransparency     (0.f),
-     myIniId            (0),
-     myObjPerDrawer     (1024),
-     myCtx              (0L)
-   {}
+  Standard_EXPORT NIS_Drawer
+                (const Quantity_Color &theHilight = Quantity_NOC_GRAY65,
+                 const Quantity_Color &theDynHilight = Quantity_NOC_CYAN1);
+
+  /**
+   * Set or reset the status 'Compiled'. By default it is "True" meaning that
+   * every draw list would be compiled once and then called multiple times
+   * when needed. The value "False" means that all GL commands will be executed
+   * as they are defined in methods BeforeDraw, Draw and AfterDraw without
+   * building an OpenGL list.
+   */
+  Standard_EXPORT void SetCompiled (const Standard_Boolean isCompiled);
 
   /**
    * Destructor.
@@ -149,6 +189,11 @@ class NIS_Drawer : public Standard_Transient
   inline NIS_InteractiveContext * GetContext () const
   { return myCtx; }
 
+  /**
+   * Sets the Interactive Context.
+   */
+  Standard_EXPORT void SetContext ( NIS_InteractiveContext *theCtx );
+
   /**
    * Copy the relevant information from another instance of Drawer.
    * raises exception if theOther has incompatible type (test IsKind).
@@ -166,19 +211,19 @@ class NIS_Drawer : public Standard_Transient
   /**
    * Mark all draw lists for update
    */
-  Standard_EXPORT void          SetUpdated (const DrawType theType) const;
+  Standard_EXPORT virtual void          SetUpdated (const DrawType theType) const;
 
-  Standard_EXPORT void          SetUpdated (const DrawType theType1,
-                                            const DrawType theType2) const;
+  Standard_EXPORT virtual void          SetUpdated (const DrawType theType1,
+                                                    const DrawType theType2) const;
 
-  Standard_EXPORT void          SetUpdated (const DrawType theType1,
-                                            const DrawType theType2,
-                                            const DrawType theType3) const;
+  Standard_EXPORT virtual void          SetUpdated (const DrawType theType1,
+                                                    const DrawType theType2,
+                                                    const DrawType theType3) const;
 
-  Standard_EXPORT void          SetUpdated (const DrawType theType1,
-                                            const DrawType theType2,
-                                            const DrawType theType3,
-                                            const DrawType theType4) const;
+  Standard_EXPORT virtual void          SetUpdated (const DrawType theType1,
+                                                    const DrawType theType2,
+                                                    const DrawType theType3,
+                                                    const DrawType theType4) const;
 
   /**
    * Switch on/off the dynamic hilight of the given object in the
@@ -191,7 +236,7 @@ class NIS_Drawer : public Standard_Transient
    *   View where the status of object must be changed. If NULL, the object
    *   is hilighted/unhilighted in all views.
    */
-  Standard_EXPORT void          SetDynamicHilighted
+  Standard_EXPORT virtual void  SetDynamicHilighted
                                    (const Standard_Boolean      isHilighted,
                                     const Handle_NIS_InteractiveObject& theObj,
                                     const Handle_NIS_View&      theView = 0L);
@@ -200,7 +245,7 @@ class NIS_Drawer : public Standard_Transient
    * Hash value, for Map interface.
    */ 
   Standard_EXPORT virtual Standard_Integer
-                                HashCode(const Standard_Integer theN) const;
+                                HashCode (const Standard_Integer theN) const;
 
   /**
    * Matching two instances, for Map interface.
@@ -208,6 +253,30 @@ class NIS_Drawer : public Standard_Transient
   Standard_EXPORT virtual Standard_Boolean
                                 IsEqual (const Handle_NIS_Drawer& theOth) const;
 
+  /**
+   * Set the color for presentation.
+   * @param theDrawType
+   *   Draw type for which the color is defined
+   * @param theColor
+   *   New color to use for the presentation.
+   */
+  Standard_EXPORT virtual void  SetColor (const DrawType        theDrawType,
+                                          const Quantity_Color& theColor);
+
+  /**
+   * Get color of the presentation in the given DrawType.
+   * @param theDrawType
+   *   The draw type, for which the color is retrieved.
+   */
+  Standard_EXPORT virtual Quantity_Color
+                                GetColor (const DrawType theDrawType) const;
+
+  /**
+   * Get the transparency value.
+   */
+  inline Standard_ShortReal     Transparency     () const
+  { return myTransparency; }
+
   /**
    * Obtain the iterator of IDs of associated objects.
    */
@@ -215,19 +284,47 @@ class NIS_Drawer : public Standard_Transient
                                 ObjectIterator   () const
   { return TColStd_MapIteratorOfPackedMapOfInteger (myMapID); }
 
+  /**
+   * Obtain map of IDs of associated objects.
+   */
+  inline const TColStd_PackedMapOfInteger& ObjectsMap() const
+  { return myMapID; }
+
   /**
    * Query associated draw lists.
    */
   inline NCollection_List<NIS_DrawList *>
-                                GetLists() const
+                                GetLists () const
   { return myLists; }
+
+  /**
+   * @return drawer priority within drawing scenario
+   */
+  inline PriorityLevel Priority() const
+  { return (PriorityLevel)myPriority; }
+
+  /**
+   * Setup drawer priority within drawing scenario
+   */
+  inline void SetPriority (const PriorityLevel thePriority)
+  { myPriority = thePriority; }
+
+  /**
+   * Draw a single object.
+   * @returns
+   *   True if the object was drawn, False if refused.
+   */
+  Standard_EXPORT virtual Standard_Boolean
+                        drawObject      (const Handle_NIS_InteractiveObject&,
+                                         const DrawType       theType,
+                                         const NIS_DrawList&  theDrawList);
+
 protected:
   /**
    * Called to add draw list IDs to ex-list Ids of view. These draw lists are
    * eventually released in the callback function, before anything is displayed
    */
-  Standard_EXPORT void UpdateExListId   (const Handle_NIS_View& theView) const;
+  Standard_EXPORT void UpdateExListId    (const Handle_NIS_View& theView) const;
 
   // ---------- PROTECTED METHODS ----------
 
@@ -265,6 +362,10 @@ protected:
   Standard_EXPORT virtual NIS_DrawList*
                         createDefaultList (const Handle_NIS_View&) const;
 
+  Standard_EXPORT static Standard_Boolean
+                        areEqual        (const Quantity_Color& theColor0,
+                                         const Quantity_Color& theColor1);
+
  protected:
   //! Get the number of interactive objects in this drawer
   inline Standard_Integer      NObjects() const
@@ -291,7 +392,11 @@ protected:
   //! Maximal range of IDs of objects in one drawer. Limits the size of
   //! draw lists. Can be initialized only in constructor (default 1024). It is
   //! strictly prohibited to change this value outside the constructor.
-  Standard_Integer                      myObjPerDrawer;
+  Standard_Integer                      myObjPerDrawer : 24;
+  Standard_Integer                      myPriority     : 3;
+  Standard_Boolean                      myIsCompiled   : 1;
+  //! Colors for different draw modes: Normal, Top, Transparent, Hilight, DynHi
+  Quantity_Color                        myColor[5];
 
  private:
   // ---------- PRIVATE FIELDS ----------
diff --git a/src/NIS/NIS_IndexLists.cxx b/src/NIS/NIS_IndexLists.cxx
new file mode 100644 (file)
index 0000000..5056d53
--- /dev/null
@@ -0,0 +1,291 @@
+// File:      NIS_IndexLists.cxx
+// Created:   19.07.2011 13:42
+// Author:    
+// Copyright: Open Cascade 2011
+
+#include <NIS_IndexLists.hxx>
+#include <NCollection_BaseAllocator.hxx>
+#include <Standard_OutOfRange.hxx>
+
+/**
+ * Compute the size in bytes of an index array.
+ */ 
+static inline Standard_Size    NBytesInd  (const Standard_Size nInd,
+                                           const unsigned int  theIndType)
+{
+  static const Standard_Size nBytes[] = { 1, 2, 4 };
+  return nInd * nBytes[theIndType];
+}
+
+//=======================================================================
+//function : Constructor
+//purpose  : 
+//=======================================================================
+
+NIS_IndexLists::NIS_IndexLists()
+  : mypIndexes          (0L),
+    myNbArrays          (0u),
+    myIndexType         (2u)
+{
+}
+
+//=======================================================================
+//function : Clear()
+//purpose  : 
+//=======================================================================
+
+void NIS_IndexLists::Clear (NCollection_BaseAllocator * theAlloc)
+{
+  if (theAlloc && theAlloc != UndefinedHandleAddress)
+  {
+    if (myNbArrays) {
+      for (unsigned int i = 0; i < myNbArrays; i++)
+        theAlloc->Free(mypIndexes[i]);
+      theAlloc->Free(mypIndexes);
+      myNbArrays = 0u;
+      mypIndexes = 0L;
+    }
+  }
+}
+
+//=======================================================================
+//function : Clone()
+//purpose  : 
+//=======================================================================
+
+void NIS_IndexLists::Clone (const Handle_NCollection_BaseAllocator& theAlloc,
+                            NIS_IndexLists&                      theDest) const
+{
+  theDest.myNbArrays = myNbArrays;
+  theDest.myIndexType = myIndexType;
+  if (myNbArrays) {
+    const Standard_Size nBytes = sizeof(Standard_Integer *) * myNbArrays;
+    theDest.mypIndexes = static_cast<Standard_Integer **>
+      (theAlloc->Allocate(nBytes));
+    for (unsigned int i = 0; i < myNbArrays; i++) {
+      const Standard_Size nIdx = NArrayIndexes(i);
+      const Standard_Size nBytes = NBytesInd(nIdx, myIndexType)+4;
+      theDest.mypIndexes[i] = static_cast <Standard_Integer *>
+        (theAlloc->Allocate (nBytes));
+      memcpy(theDest.mypIndexes[i], mypIndexes[i], nBytes);
+    }
+  }
+}
+
+//=======================================================================
+//function : InitArray 
+//purpose  : 
+//=======================================================================
+
+void NIS_IndexLists::InitArray (const unsigned int          theIndexType,
+                                const Standard_Integer      theNLists,
+                                NCollection_BaseAllocator * theAlloc)
+{
+  if (theNLists > 0)
+  {
+    Clear(theAlloc);
+    myIndexType = theIndexType;
+    myNbArrays = static_cast<unsigned int>(theNLists);
+    mypIndexes = static_cast<Standard_Integer **>
+      (theAlloc->Allocate(sizeof(Standard_Integer *) * theNLists));
+  }
+}
+
+//=======================================================================
+//function : SetRealNumbersOfArrays 
+//purpose  : 
+//=======================================================================
+
+void NIS_IndexLists::SetRealNumbersOfArrays (const Standard_Integer theNLists)
+{
+  if (theNLists < 0)
+    return;
+  if (theNLists > static_cast<Standard_Integer>(myNbArrays))
+    Standard_OutOfRange::Raise ("NIS_IndexLists::SetRealNumbersOfArrays");
+
+  myNbArrays = static_cast<unsigned int>(theNLists);
+}
+
+//=======================================================================
+//function : SetArrayIndex 
+//purpose  : 
+//=======================================================================
+
+void NIS_IndexLists::SetArrayIndex (const Standard_Size    theIndArray,
+                                    const Standard_Size    theIndInArray,
+                                    const Standard_Integer theIndex)
+{
+  Standard_OutOfRange_Raise_if (theIndArray >= myNbArrays,
+                                "NIS_IndexLists::SetArrayIndex");
+
+  Standard_Integer * aArray  = mypIndexes[theIndArray];
+  switch (myIndexType) {
+  case 0: // 8bit
+  {
+    const Standard_Size aNIdx = * (reinterpret_cast<unsigned int *>(aArray));
+    Standard_OutOfRange_Raise_if (theIndInArray >= aNIdx,
+                                  "NIS_IndexLists::SetArrayIndex");
+    unsigned char * pInd =
+      reinterpret_cast<unsigned char *>(aArray) + (theIndInArray + 4);
+    pInd[0] = static_cast<unsigned char>(theIndex);   
+  }
+  break;
+  case 1: // 16bit
+  {
+    const Standard_Size aNIdx = * (reinterpret_cast<unsigned int *>(aArray));
+    Standard_OutOfRange_Raise_if (theIndInArray >= aNIdx,
+                                  "NIS_IndexLists::SetArrayIndex");
+    unsigned short * pInd =
+      reinterpret_cast<unsigned short *>(aArray) + (theIndInArray + 2);
+    pInd[0] = static_cast<unsigned short>(theIndex);
+  }
+  break;
+  default: // 32bit
+    Standard_OutOfRange_Raise_if (static_cast<int>(theIndInArray) >= aArray[0],
+                                  "NIS_IndexLists::SetArrayIndex");
+    aArray[theIndInArray + 1] = theIndex;
+  }
+}
+
+//=======================================================================
+//function : SetArray 
+//purpose  : 
+//=======================================================================
+
+void NIS_IndexLists::SetArray (const Standard_Size         theIndArray,
+                               const Standard_Integer      theNbIndexes,
+                               NCollection_BaseAllocator * theAlloc)
+{
+  Standard_OutOfRange_Raise_if (theIndArray >= myNbArrays,
+                                "NIS_IndexLists::SetArray");
+  switch (myIndexType) {
+    case 0: // 8bit
+    {
+      unsigned char * anArray  = static_cast <unsigned char *>
+        (theAlloc->Allocate (sizeof(unsigned char) * (theNbIndexes+4)));
+      mypIndexes[theIndArray] = reinterpret_cast<Standard_Integer *> (anArray);
+      *(reinterpret_cast<unsigned int*>(anArray)) = theNbIndexes;
+    }
+    break;
+    case 1: // 16bit
+    {
+      unsigned short * anArray  = static_cast <unsigned short *>
+        (theAlloc->Allocate (sizeof(unsigned short) * (theNbIndexes+2)));
+      mypIndexes[theIndArray] = reinterpret_cast<Standard_Integer *> (anArray);
+      *(reinterpret_cast<unsigned int*>(anArray)) = theNbIndexes;
+    }
+    break;
+    default: // 32bit
+    {
+      Standard_Integer * anArray  = static_cast <Standard_Integer *>
+        (theAlloc->Allocate (sizeof(Standard_Integer) * (theNbIndexes+1)));
+      mypIndexes[theIndArray] = anArray;
+      anArray[0] = theNbIndexes;
+    }
+  } 
+}
+
+//=======================================================================
+//function : SetArray
+//purpose  : 
+//=======================================================================
+
+void NIS_IndexLists::SetArray (const Standard_Size         theIndArray,
+                               const Standard_Integer      theNbIndexes, 
+                               const int*                  theIdxList,
+                               NCollection_BaseAllocator * theAlloc,
+                               const Standard_Integer      theStartIdx)
+{
+  if (theIdxList)
+  {
+    SetArray (theIndArray, theNbIndexes, theAlloc);
+    if (mypIndexes)
+    {
+      for (Standard_Integer i = 0; i < theNbIndexes; i++)
+      {
+        Standard_Integer aN = theIdxList[i] + theStartIdx;   
+        SetArrayIndex (theIndArray, i, aN);
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : ArrayIndex
+//purpose  : 
+//=======================================================================
+
+Standard_Integer NIS_IndexLists::ArrayIndex
+                                (const Standard_Size    theIndArray,
+                                 const Standard_Integer theIndInArray) const
+{
+  Standard_Integer aResult(-1);
+  Standard_OutOfRange_Raise_if (theIndArray >= myNbArrays,
+                                "NIS_IndexLists::ArrayIndex");
+  const Standard_Integer * aArray  = mypIndexes[theIndArray];
+  switch (myIndexType) {
+    case 0: // 8bit
+    {
+      const unsigned char * pInd =
+        reinterpret_cast<const unsigned char *>(aArray);
+      Standard_OutOfRange_Raise_if (theIndInArray >= pInd[0],
+                                    "NIS_IndexLists::ArrayIndex");
+      aResult = static_cast<Standard_Integer>(pInd[theIndInArray + 4]);
+    }
+    break;
+    case 1: // 16bit
+    {
+      const unsigned short * pInd =
+        reinterpret_cast<const unsigned short *>(aArray);
+      Standard_OutOfRange_Raise_if (theIndInArray >= pInd[0],
+                                    "NIS_IndexLists::ArrayIndex");
+      aResult = static_cast<Standard_Integer>(pInd[theIndInArray + 2]);
+    }
+    break;
+    default: // 32bit
+    {
+      Standard_OutOfRange_Raise_if (theIndInArray >= aArray[0],
+                                    "NIS_IndexLists::ArrayIndex");
+      aResult = aArray[theIndInArray + 1];
+    }
+  }
+  return aResult;
+}
+
+//=======================================================================
+//function : NArraysIndexes
+//purpose  : 
+//=======================================================================
+
+Standard_Size NIS_IndexLists::NArrayIndexes
+                                (const Standard_Integer theIndArray) const
+{
+  Standard_Size aResult(0);
+  Standard_OutOfRange_Raise_if ((theIndArray >=
+                                 static_cast<Standard_Integer>(myNbArrays)),
+                                "NIS_IndexLists::NArraysIndexes");
+  const Standard_Integer * aArray = mypIndexes[theIndArray];
+  aResult = * (reinterpret_cast<const unsigned int *>(aArray));
+  return aResult;
+}
+
+//=======================================================================
+//function : ArraysIndexes
+//purpose  : 
+//=======================================================================
+
+void * NIS_IndexLists::ArrayIndexes(const Standard_Size theIndArray)const
+{
+  Standard_OutOfRange_Raise_if (theIndArray >= myNbArrays,
+                                "NIS_IndexLists::ArraysIndexes");
+  void * anArray;
+  if (myIndexType == 0)
+    anArray = reinterpret_cast<unsigned char *>(mypIndexes[theIndArray])+4;
+  else if (myIndexType == 1)
+    anArray = reinterpret_cast<unsigned short *>(mypIndexes[theIndArray])+2;
+  else
+    anArray = mypIndexes[theIndArray]+1;          
+
+  return anArray;
+}
+
diff --git a/src/NIS/NIS_IndexLists.hxx b/src/NIS/NIS_IndexLists.hxx
new file mode 100644 (file)
index 0000000..dbaf992
--- /dev/null
@@ -0,0 +1,160 @@
+// File:      NIS_IndexLists.hxx
+// Created:   19.07.2011 15:29
+// Author:    
+// Copyright: Open Cascade 2011
+
+#ifndef NIS_IndexLists_HeaderFile
+#define NIS_IndexLists_HeaderFile
+
+#include <Standard_TypeDef.hxx>
+class NCollection_BaseAllocator;
+class Handle_NCollection_BaseAllocator;
+
+class NIS_IndexLists 
+{
+ public:
+  // ---------- PUBLIC METHODS ----------
+
+
+  /**
+   * Constructor. 
+   */
+  Standard_EXPORT NIS_IndexLists        (); 
+
+  /**
+   * Reset all data memebers and free all allocated memory.
+   * Called from the destructor of the container class, also can be used
+   * to re-initialize the data set.
+   * The allocator parameter should be the same as previously passed to
+   * methods InitArray() and SetArray().
+   */
+  Standard_EXPORT void              Clear (NCollection_BaseAllocator* theAlloc);
+
+  /**
+   * Create a copy of object.
+   * @param theAl
+   *   Allocator where the Dest should store its private data.
+   * @param theDest
+   *   <tt>[in-out]</tt> The target object where the data are copied. If
+   *   passed NULL then the target should be created.
+   */
+  Standard_EXPORT void              Clone
+                                (const Handle_NCollection_BaseAllocator& theAl,
+                                 NIS_IndexLists&      theDest) const;
+
+
+  /**
+   * Initialize the array of indexes
+   * @param theIndexType
+   *   0:8bit, 1:16bit, 2:32bit
+   * @param theNLists
+   *   Number of separate array of indexes. If set to 0, array are cancelled
+   * @param theAlloc
+   *   Allocator that is called for array memory.
+   */
+  Standard_EXPORT void              InitArray
+                                        (const unsigned int      theIndexType,
+                                         const Standard_Integer  theNLists,
+                                         NCollection_BaseAllocator * theAlloc);
+
+  /**
+   * Set the actual number of used arrays. The length can not exceed value specified in InitArray
+   * @param theNLists
+   *   Number of separate array of indexes. If set to 0, array are cancelled
+   */
+  Standard_EXPORT void              SetRealNumbersOfArrays
+                                        (const Standard_Integer theNLists);
+
+  /**
+   * Store the element index in array
+   * @param theIndArray
+   *   Index of the Array, should be less than the number of arrays that is
+   *   defined in InitArray() and can be returned by NArrays().
+   * @param theIndInArray
+   *   Index of the element in the Array. Should be less than the parameter theSz
+   *   in the corresponding previous SetArray() call.
+   * @param theIndex
+   *   Index of the element in the given position of the Array. 
+   */
+  Standard_EXPORT void              SetArrayIndex
+                                        (const Standard_Size    theIndArray,
+                                         const Standard_Size    theIndInArray,
+                                         const Standard_Integer theIndex);
+
+  /**
+   * Allocate a single array. The array can be filled by indices using
+   * the method SetArrayIndex().
+   * @param theIndArray
+   *   Index of the array, should be [0...myNbArrays-1]
+   * @param theSz
+   *   Number of elements in the array.
+   * @param theAlloc
+   *   Allocator, should be the same as passed to InitArray() before.
+   */
+  Standard_EXPORT void              SetArray
+                                        (const Standard_Size      theIndArray,
+                                         const Standard_Integer   theSz,
+                                         NCollection_BaseAllocator * theAlloc);
+
+  /**
+   * Store the array elements indexes
+   * @param theIndArray
+   *   Index of the Array, should be less than the number of arrays that is
+   *   defined in InitArray() and can be returned by NArrays().
+   * @param theNbIndexes
+   *   size of array   
+   * @param theIdxList
+   *   Array of elements. The size must be equal theNbIndexes
+   * @param theAlloc
+   *   Allocator, should be the same as passed to InitArray() before.
+   * @param theStartIdx
+   *   Index that must be added to the element in the array to change
+   *   the indexation, 0 by default.
+   */
+  Standard_EXPORT void              SetArray
+                                        (const Standard_Size     theIndArray,
+                                         const Standard_Integer  theNbIndexes, 
+                                         const int*              theIdxList,
+                                         NCollection_BaseAllocator * theAlloc,
+                                         const Standard_Integer  theStartIdx=0);
+
+  /**
+   * Get the element with index 'theIndInArray' from the array
+   * number 'theIndArray'.
+   */
+  Standard_EXPORT Standard_Integer ArrayIndex
+                                     (const Standard_Size    theIndArray,
+                                      const Standard_Integer theIndInArr) const;
+
+  /**
+   * Get the number of elements for the array number 'theIndArray'.
+   */
+  Standard_EXPORT Standard_Size NArrayIndexes
+                                     (const Standard_Integer theIndArray) const;
+
+  /**
+   * Get the array of elements for the array number 'theIndArray'.
+   */
+  Standard_EXPORT void* ArrayIndexes (const Standard_Size theIndArray) const;
+
+  /**
+   * Query the number of arrays.
+   */
+  inline Standard_Integer           NArrays () const
+  { return static_cast<Standard_Integer>(myNbArrays); }
+
+ protected:
+  // ---------- PROTECTED METHODS ----------
+
+ private:
+  // ---------- PRIVATE (PROHIBITED) METHODS ----------
+
+ private:
+  // ---------- PRIVATE FIELDS ----------  
+  Standard_Integer**            mypIndexes;       ///< Array of indexes  
+
+  unsigned int                  myNbArrays  : 24; ///< Number of arrays
+  unsigned int                  myIndexType : 2;  ///< 0:8bit, 1:16bit, 2:32bit
+};
+
+#endif
index 11ed99ad977f3bc25cf37be2288614be671d8226..36a284ee3ef482dae8e9ead0086ab9676bded0af 100644 (file)
@@ -24,6 +24,15 @@ IMPLEMENT_STANDARD_HANDLE  (NIS_InteractiveContext, Standard_Transient)
 IMPLEMENT_STANDARD_RTTIEXT (NIS_InteractiveContext, Standard_Transient)
 
 static void markAllDrawersUpdated   (const NCollection_Map<Handle_NIS_Drawer>&);
+static Standard_Boolean CanBeAllocated(const Standard_Size theNeedTotal,
+                                          const Standard_Size theBlockSize);
+
+#ifdef WNT
+#include <windows.h>
+static const Standard_Integer aSizeAlloc = 0x80000; // 512k
+#else
+static const Standard_Integer aSizeAlloc = 0x20000; // 128k
+#endif
 
 //=======================================================================
 //function : NIS_InteractiveContext()
@@ -31,7 +40,7 @@ static void markAllDrawersUpdated   (const NCollection_Map<Handle_NIS_Drawer>&);
 //=======================================================================
 
 NIS_InteractiveContext::NIS_InteractiveContext ()
-  : myAllocator       (new NIS_Allocator(1024*100)),
+  : myAllocator       (new NIS_Allocator(aSizeAlloc)),
     myLastObjectId    (0),
     myObjects         (1000),
 //     myDrawers       (101, myAllocator),
@@ -40,6 +49,10 @@ NIS_InteractiveContext::NIS_InteractiveContext ()
 {
   // ID == 0 is invalid so we reserve this item from subsequent allocation.
   myObjects.SetValue(myLastObjectId, NULL);
+  for (Standard_Integer aPriority = 0; aPriority < NIS_Drawer::Priority_LevelsNb; ++aPriority)
+  {
+    myPriorities[aPriority] = 0;
+  }
 }
 
 //=======================================================================
@@ -51,15 +64,11 @@ NIS_InteractiveContext::~NIS_InteractiveContext ()
 {
   // Unregister this context in all referred views
   NCollection_List<Handle_NIS_View>::Iterator anIterV (myViews);
-  for (; anIterV.More(); anIterV.Next())
-    if (anIterV.Value().IsNull() == Standard_False)
-      anIterV.Value()->RemoveContext(this);
-
-//   // Unregister this context in all referred drawers
-//   NCollection_Map<Handle_NIS_Drawer>::Iterator anIterD (myDrawers);
-//   for (; anIterD.More(); anIterD.Next())
-//     if (anIterD.Value().IsNull() == Standard_False)
-//       anIterD.Value()->myCtx = 0L;
+  while (anIterV.More())
+    if (anIterV.Value().IsNull())
+      anIterV.Next();
+    else
+      detachView(anIterV);
 }
 
 
@@ -84,6 +93,10 @@ void NIS_InteractiveContext::AttachView (const Handle_NIS_View& theView)
         if (aDrawer.IsNull() == Standard_False)
           aDrawer->myLists.Append(aDrawer->createDefaultList(theView));
       }
+      if (myIsShareDrawList && NbObjects() > 0)
+      {
+          markAllDrawersUpdated( myDrawers );
+      }
     }
   }
 }
@@ -99,23 +112,45 @@ void NIS_InteractiveContext::DetachView (const Handle_NIS_View& theView)
     NCollection_List<Handle_NIS_View>::Iterator anIter (myViews);
     for (; anIter.More(); anIter.Next())
       if (anIter.Value() == theView) {
-        myViews.Remove(anIter);
-        theView->RemoveContext(this);
-        NCollection_Map<Handle_NIS_Drawer>::Iterator anIterD (myDrawers);
-        for (; anIterD.More(); anIterD.Next()) {
-          const Handle(NIS_Drawer)& aDrawer = anIterD.Value();
-          if (aDrawer.IsNull() == Standard_False) {
-            NCollection_List<NIS_DrawList*>::Iterator anIterL(aDrawer->myLists);
-            for (; anIterL.More(); anIterL.Next())
-              if (anIterL.Value()->GetView() == theView) {
-                delete anIterL.Value();
-                aDrawer->myLists.Remove (anIterL);
-                break;
-              }
+        detachView(anIter);
+        break;
+      }
+  }
+}
+
+//=======================================================================
+//function : detachView
+//purpose  : 
+//=======================================================================
+
+void NIS_InteractiveContext::detachView
+                (NCollection_List<Handle_NIS_View>::Iterator& theIter)
+{
+  if (theIter.More()) {
+    const Handle(NIS_View)& aView = theIter.Value();
+    // If draw lists are shared in this Context then they should be
+    // destroyed when we detach from the last view.
+    Standard_Boolean isForcedDestroy(Standard_False); 
+    aView->RemoveContext(this); // must be called before myViews.Remove()
+    myViews.Remove(theIter);
+    if (myIsShareDrawList && myViews.IsEmpty())
+      isForcedDestroy = Standard_True;
+
+    NCollection_Map<Handle_NIS_Drawer>::Iterator anIterD (myDrawers);
+    for (; anIterD.More(); anIterD.Next()) {
+      const Handle(NIS_Drawer)& aDrawer = anIterD.Value();
+      if (aDrawer.IsNull() == Standard_False) {
+        NCollection_List<NIS_DrawList*>::Iterator anIterL(aDrawer->myLists);
+        for (; anIterL.More(); anIterL.Next()) {
+          NIS_DrawList* pList = anIterL.Value();
+          if (isForcedDestroy || pList->GetView() == aView) {
+            delete pList;
+            aDrawer->myLists.Remove (anIterL);
+            break;
           }
         }
-        break;
       }
+    }
   }
 }
 
@@ -137,16 +172,28 @@ const Handle_NIS_InteractiveObject& NIS_InteractiveContext::GetObject
 
 //=======================================================================
 //function : redraw
-//purpose  : 
+//purpose  :
 //=======================================================================
 
-void NIS_InteractiveContext::redraw (const Handle(NIS_View)&    theView,
-                                     const NIS_Drawer::DrawType theType)
+void NIS_InteractiveContext::redraw (const Handle(NIS_View)&         theView,
+                                     const NIS_Drawer::DrawType      theType,
+                                     const NIS_Drawer::PriorityLevel thePriority)
 {
+  if (thePriority >= NIS_Drawer::Priority_LevelsNb
+   || myPriorities[thePriority] < 1)
+  {
+    return;
+  }
+
   NCollection_Map <Handle_NIS_Drawer>::Iterator anIter (myDrawers);
   for (; anIter.More(); anIter.Next())
-    if (anIter.Value().IsNull() == Standard_False)
+  {
+    if (anIter.Value().IsNull()    == Standard_False
+     && anIter.Value()->Priority() == thePriority)
+    {
       anIter.Value()->redraw (theType, theView);
+    }
+  }
 }
 
 //=======================================================================
@@ -379,6 +426,10 @@ void NIS_InteractiveContext::RemoveAll ()
   }
   // Remove Drawers
   myDrawers.Clear();
+  for (Standard_Integer anIter = 0; anIter < NIS_Drawer::Priority_LevelsNb; ++anIter)
+  {
+    myPriorities[anIter] = 0;
+  }
 
   // Release memory
   myAllocator->Reset();
@@ -474,7 +525,7 @@ Standard_Boolean NIS_InteractiveContext::SetSelected
 
 Standard_Boolean NIS_InteractiveContext::ProcessSelection
                         (const Handle_NIS_InteractiveObject& theObj,
-                         const Standard_Boolean              isMultiple)
+                         const Standard_Boolean              isModifierUsed)
 {
   Standard_Boolean aResult (Standard_False);
   Standard_Integer anID (0);
@@ -492,16 +543,18 @@ Standard_Boolean NIS_InteractiveContext::ProcessSelection
   switch (mySelectionMode) {
   case Mode_Normal:
   case Mode_Additive:
-    if (isMultiple == Standard_False) {
-      ClearSelected();
+    if (isModifierUsed == Standard_False) {
+      if (mySelectionMode == Mode_Normal)
+        ClearSelected();
+      wasSelected = myMapObjects[NIS_Drawer::Draw_Hilighted].Contains (anID);
       aResult = Standard_True;
-    } else if (wasSelected && mySelectionMode == Mode_Normal) {
+    } else if (wasSelected) {
       myMapObjects[NIS_Drawer::Draw_Hilighted].Remove( anID );
       deselectObj (theObj, anID);
       aResult = Standard_True;
       break;
     }
-    if (wasSelected == Standard_False && IsSelectable(anID) == Standard_True) {
+    if (wasSelected == Standard_False && IsSelectable(anID) == Standard_True && anID > 0) {
       myMapObjects[NIS_Drawer::Draw_Hilighted].Add( anID );
       selectObj (theObj, anID);
       aResult = Standard_True;
@@ -526,7 +579,7 @@ Standard_Boolean NIS_InteractiveContext::ProcessSelection
 
 void NIS_InteractiveContext::ProcessSelection
                         (const TColStd_PackedMapOfInteger& mapSel,
-                         const Standard_Boolean            isMultiple)
+                         const Standard_Boolean            isModifierUsed)
 {
   //subtract non-selectable objects
   TColStd_PackedMapOfInteger aMap;
@@ -535,14 +588,27 @@ void NIS_InteractiveContext::ProcessSelection
   TColStd_MapIteratorOfPackedMapOfInteger anIter;
   switch (mySelectionMode) {
   case Mode_Normal:
-    if (isMultiple == Standard_False) {
-      ClearSelected();
-      myMapObjects[NIS_Drawer::Draw_Hilighted] = aMap;
-      for (anIter.Initialize (aMap); anIter.More(); anIter.Next()) {
-        const Standard_Integer anID = anIter.Key();
-        selectObj (myObjects(anID), anID);
-      }
-    } else {
+  case Mode_Additive:
+    if (isModifierUsed == Standard_False) {
+        if (mySelectionMode == Mode_Normal)
+        {
+          ClearSelected();
+          myMapObjects[NIS_Drawer::Draw_Hilighted] = aMap;
+          for (anIter.Initialize (aMap); anIter.More(); anIter.Next()) {
+            const Standard_Integer anID = anIter.Key();
+            selectObj (myObjects(anID), anID);
+          }
+        }
+        else
+        {
+          aMap.Subtract (myMapObjects[NIS_Drawer::Draw_Hilighted]);
+          myMapObjects[NIS_Drawer::Draw_Hilighted].Unite (aMap);
+          for (anIter.Initialize (aMap); anIter.More(); anIter.Next()) {
+            const Standard_Integer anID = anIter.Key();
+            selectObj (myObjects(anID), anID);
+          }
+        }
+    } else { // the modifier is pressed
       TColStd_PackedMapOfInteger aMapSub;
       aMapSub.Intersection(aMap, myMapObjects[NIS_Drawer::Draw_Hilighted]);
       aMap.Subtract (myMapObjects[NIS_Drawer::Draw_Hilighted]);
@@ -558,14 +624,6 @@ void NIS_InteractiveContext::ProcessSelection
       }
     }
     break;
-  case Mode_Additive:
-    aMap.Subtract (myMapObjects[NIS_Drawer::Draw_Hilighted]);
-    myMapObjects[NIS_Drawer::Draw_Hilighted].Unite (aMap);
-    for (anIter.Initialize (aMap); anIter.More(); anIter.Next()) {
-      const Standard_Integer anID = anIter.Key();
-      selectObj (myObjects(anID), anID);
-    }
-    break;
   case Mode_Exclusive:
     aMap.Intersect (myMapObjects[NIS_Drawer::Draw_Hilighted]);
     myMapObjects[NIS_Drawer::Draw_Hilighted].Subtract (aMap);
@@ -650,58 +708,78 @@ void NIS_InteractiveContext::SetSelected
 
 //=======================================================================
 //function : selectObject
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 Standard_Real NIS_InteractiveContext::selectObject
-                                (Handle_NIS_InteractiveObject&  theSel,
-                                 NCollection_List<DetectedEnt>& theDetected,
+                                //(Handle_NIS_InteractiveObject&  theSel,
+                                (NCollection_List<DetectedEnt>& theDetected,
                                  const gp_Ax1&                  theAxis,
                                  const Standard_Real            theOver,
-                                 const Standard_Boolean         isOnlySel) const
+                                 const Standard_Boolean         isOnlySel,
+                                 const NIS_SelectFilter::Event  theEvent) const
 {
   static const Standard_Real anInfiniteDist = 0.5 * RealLast();
-  Standard_Real aMinDist(anInfiniteDist);
-  if (mySelectionMode != Mode_NoSelection || isOnlySel == Standard_False)
+  if (mySelectionMode == Mode_NoSelection && isOnlySel)
   {
-    DetectedEnt anEnt;
-    NCollection_SparseArray <Handle_NIS_InteractiveObject>::ConstIterator
-      anIter(myObjects);
-    for (; anIter.More(); anIter.Next()) {
-      const Handle(NIS_InteractiveObject)& anObj = anIter.Value();
-      if (anObj.IsNull() == Standard_False)
-        if (anObj->IsDisplayed() &&
-            (!myMapNonSelectableObjects.Contains (anObj->ID()) ||
-             isOnlySel == Standard_False))
+    return anInfiniteDist;
+  }
+
+  Standard_Real aMinDist = anInfiniteDist;
+  DetectedEnt anEnt;
+
+  for (NCollection_SparseArray <Handle_NIS_InteractiveObject>::ConstIterator anIter (myObjects);
+       anIter.More(); anIter.Next())
+  {
+    const Handle(NIS_InteractiveObject)& anObj = anIter.Value();
+
+    // check object is selectable
+    if (anObj.IsNull() || !anObj->IsDisplayed()
+     || (isOnlySel && myMapNonSelectableObjects.Contains (anObj->ID()))
+     // early-out - check the intersection with the bounding box
+     || anObj->IsOut (theAxis, Standard_False, theOver))
+    {
+      continue;
+    }
+
+    // pass the object through the SelectFilter if available
+    if (!mySelectFilter.IsNull())
+    {
+      if (!mySelectFilter->ActsOn (anObj->DynamicType())
+       || !mySelectFilter->IsOk   (anObj.operator->(), theAxis,
+                                   theOver, theEvent))
+      {
+        continue;
+      }
+    }
+
+    anEnt.Dist = anObj->Intersect (theAxis, theOver);
+    if (anEnt.Dist < anInfiniteDist)
+    {
+      // insert the detected entity in the sorted list
+      anEnt.PObj = anObj.operator->();
+      anEnt.Prio = anObj->GetDrawer()->Priority();
+      NCollection_List<DetectedEnt>::Iterator anIterD(theDetected);
+      for (; anIterD.More(); anIterD.Next())
+      {
+        const DetectedEnt& anEntOther = anIterD.Value();
+        if (anEnt.Dist < anEntOther.Dist - Precision::Confusion()
+         || (anEnt.Prio > anEntOther.Prio
+          && anEnt.Dist < anEntOther.Dist + Precision::Confusion())
+         || (anEnt.Prio == anEntOther.Prio
+          && anEnt.Dist <= anEntOther.Dist))
         {
-          // Pass the object through the SelectFilter if available
-          if (mySelectFilter.IsNull() == Standard_False)
-            if (mySelectFilter->IsOk (anObj.operator->()) == Standard_False)
-              continue;
-          // Check the intersection with the box
-          const Bnd_B3f& aBox = anObj->GetBox();
-          if (aBox.IsOut (theAxis, Standard_False, theOver) == Standard_False)
-          {
-            anEnt.Dist = anObj->Intersect (theAxis, theOver);
-            if (anEnt.Dist < anInfiniteDist) {
-              anEnt.PObj = anObj.operator->();
-              // Insert the detected entity in the sorted list
-              NCollection_List<DetectedEnt>::Iterator anIterD(theDetected);
-              for (; anIterD.More(); anIterD.Next()) {
-                if (anEnt.Dist < anIterD.Value().Dist) {
-                  theDetected.InsertBefore(anEnt, anIterD);
-                  break;
-                }
-              }
-              if (anIterD.More() == Standard_False)
-                theDetected.Append(anEnt);
-              if (anEnt.Dist < aMinDist) {
-                aMinDist = anEnt.Dist;
-                theSel = anObj;
-              }
-            }
-          }
+          theDetected.InsertBefore (anEnt, anIterD);
+          break;
         }
+      }
+
+      if (!anIterD.More())
+      {
+        theDetected.Append (anEnt);
+      }
+
+      aMinDist = Min (aMinDist, anEnt.Dist);
     }
   }
   return aMinDist;
@@ -754,9 +832,12 @@ Standard_Boolean NIS_InteractiveContext::selectObjects
       if (anObj.IsNull() == Standard_False)
         if (anObj->IsDisplayed()) {
           // Pass the object through the SelectFilter if available
-          if (mySelectFilter.IsNull() == Standard_False)
+          if (mySelectFilter.IsNull() == Standard_False) {
+            if (mySelectFilter->ActsOn(anObj->DynamicType()) == Standard_False)
+              continue;
             if (mySelectFilter->IsOk (anObj.operator->()) == Standard_False)
               continue;
+          }
           // Check the intersection with the box
           const Bnd_B3f& aBox = anObj->GetBox();
           if (aBox.IsIn (theBox, theTrf)) {
@@ -798,9 +879,12 @@ Standard_Boolean NIS_InteractiveContext::selectObjects
       if (anObj.IsNull() == Standard_False)
         if (anObj->IsDisplayed()) {
           // Pass the object through the SelectFilter if available
-          if (mySelectFilter.IsNull() == Standard_False)
+          if (mySelectFilter.IsNull() == Standard_False) {
+            if (!mySelectFilter->ActsOn(anObj->DynamicType()))
+              continue;
             if (mySelectFilter->IsOk (anObj.operator->()) == Standard_False)
               continue;
+          }
 
           // Comvert 3d box to 2d one
           const Bnd_B3f    &aBox = anObj->GetBox();
@@ -846,9 +930,11 @@ void NIS_InteractiveContext::deselectObj
 {
   if (theObj.IsNull() == Standard_False) {
     const Handle(NIS_Drawer)& aDrawer = theObj->GetDrawer();
+    NIS_Drawer::DrawType aType = theObj->myBaseType;
     if (theObj->IsTransparent()) {
       myMapObjects[NIS_Drawer::Draw_Transparent].Add(theID);
       aDrawer->SetUpdated(NIS_Drawer::Draw_Transparent);
+      aType = NIS_Drawer::Draw_Transparent;
     } else if (theObj->myBaseType == NIS_Drawer::Draw_Top) {
       myMapObjects[NIS_Drawer::Draw_Top].Add(theID);
       aDrawer->SetUpdated(NIS_Drawer::Draw_Top);
@@ -856,8 +942,8 @@ void NIS_InteractiveContext::deselectObj
       myMapObjects[NIS_Drawer::Draw_Normal].Add(theID);
       aDrawer->SetUpdated(NIS_Drawer::Draw_Normal);
     }
+    theObj->myDrawType = aType;
     aDrawer->SetUpdated(NIS_Drawer::Draw_Hilighted);
-    theObj->myDrawType = theObj->myBaseType;
   }
 }
 
@@ -872,7 +958,7 @@ void NIS_InteractiveContext::selectObj
 {
   if (theObj.IsNull() == Standard_False) {
     const Handle(NIS_Drawer)& aDrawer = theObj->GetDrawer();
-    if (theObj->IsTransparent()) {
+    if (theObj->myDrawType == NIS_Drawer::Draw_Transparent) {
       myMapObjects[NIS_Drawer::Draw_Transparent].Remove(theID);
       aDrawer->SetUpdated(NIS_Drawer::Draw_Transparent);
     } else if (theObj->myDrawType == NIS_Drawer::Draw_Top) {
@@ -882,8 +968,8 @@ void NIS_InteractiveContext::selectObj
       myMapObjects[NIS_Drawer::Draw_Normal].Remove(theID);
       aDrawer->SetUpdated(NIS_Drawer::Draw_Normal);
     }
-    aDrawer->SetUpdated(NIS_Drawer::Draw_Hilighted);
     theObj->myDrawType = NIS_Drawer::Draw_Hilighted;
+    aDrawer->SetUpdated(NIS_Drawer::Draw_Hilighted);
   }
 }
 
@@ -945,9 +1031,17 @@ Handle_NIS_Allocator NIS_InteractiveContext::compactObjects()
   // Check if the memory used by objects has to be compacted.
   const Standard_Size nAllocated = myAllocator->NAllocated();
 
-  if (nAllocated > 1024*1024) {
+  if (nAllocated > 4 * aSizeAlloc) {
     const Standard_Size nFreed = myAllocator->NFreed();
-    if ((nFreed * 5) / 3 > nAllocated || nFreed > 20*1024*1024)
+    Standard_Boolean toCompact = (nFreed * 5) / 2 > nAllocated;
+    if (toCompact)
+    {
+      // evaluate if there is enough memory to allocate clones
+      const Standard_Size nUsed = nAllocated - nFreed;
+      if (!CanBeAllocated(nUsed, aSizeAlloc))
+        toCompact = Standard_False;
+    }
+    if (toCompact)
     {
       for (anIterV.Init(myViews); anIterV.More(); anIterV.Next()) {
         const Handle(NIS_View)& aView = anIterV.Value();
@@ -958,7 +1052,7 @@ Handle_NIS_Allocator NIS_InteractiveContext::compactObjects()
       }
       // Compact the memory: clone all objects to a new allocator, release
       // the old allocator instance.
-      aNewAlloc = new NIS_Allocator;
+      aNewAlloc = new NIS_Allocator(aSizeAlloc);
       NCollection_SparseArray<Handle_NIS_InteractiveObject>::Iterator
         anIter(myObjects);
       for (; anIter.More(); anIter.Next()) {
@@ -974,6 +1068,18 @@ Handle_NIS_Allocator NIS_InteractiveContext::compactObjects()
   return aNewAlloc;
 }
 
+//=======================================================================
+//function : CompactObjects
+//purpose  : 
+//=======================================================================
+
+void NIS_InteractiveContext::CompactObjects()
+{
+    const Handle_NIS_Allocator aNewAlloc = compactObjects();
+    if (aNewAlloc.IsNull() == Standard_False)
+        myAllocator = aNewAlloc;
+}
+
 //=======================================================================
 //function : markAllDrawersUpdated
 //purpose  : 
@@ -992,3 +1098,54 @@ void markAllDrawersUpdated (const NCollection_Map<Handle_NIS_Drawer>& lstDrv)
     }
   }
 }
+
+//=======================================================================
+//function : GetObjectsOfType
+//purpose  : 
+//=======================================================================
+
+const TColStd_PackedMapOfInteger& NIS_InteractiveContext
+  ::GetObjectsOfType (const NIS_Drawer::DrawType theDrawType) const
+{
+  // notice that there are no map for Draw_DynHilighted type!
+  Standard_OutOfRange_Raise_if (theDrawType <  NIS_Drawer::Draw_Normal ||
+                                theDrawType >= NIS_Drawer::Draw_DynHilighted,
+                                "NIS_InteractiveContext::GetObjectsOfType: Irrelevant DrawType");
+  return myMapObjects[theDrawType];
+}
+
+//=======================================================================
+//function : CanBeAllocated
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean CanBeAllocated(const Standard_Size theNeedTotal,
+                                   const Standard_Size theBlockSize)
+{
+    NCollection_List<void*> aList;
+    Standard_Size aNAlloc = 0;
+    while (aNAlloc < theNeedTotal)
+    {
+#ifdef WNT
+        void* pMem = VirtualAlloc(NULL, theBlockSize, MEM_RESERVE, PAGE_READWRITE);
+#else
+        void* pMem = malloc(theBlockSize);
+#endif
+        if (!pMem)
+        {
+            break;
+        }
+        aNAlloc += theBlockSize;
+        aList.Append(pMem);
+    }
+    NCollection_List<void*>::Iterator it(aList);
+    for (; it.More(); it.Next())
+    {
+#ifdef WNT
+        VirtualFree(it.Value(), 0, MEM_RELEASE);
+#else
+        free(it.Value());
+#endif
+    }
+    return aNAlloc >= theNeedTotal;
+}
index cb9eb617443d12aa18b5f77525ebe0446a43f3a5..c1345b9a39ea43a19bdacb1d65cb2aeaa0b6658e 100644 (file)
@@ -34,6 +34,9 @@ class NIS_View;
 class Bnd_B3f;
 class Bnd_B2f;
 
+/**
+@defgroup nis_library NIS Library (New Interactive Services)
+*/
 /**
  * InteractiveContext is the central NIS structure that stores and manages
  * all NIS_InteractiveObject instances as well as the Drawers for their
@@ -122,6 +125,7 @@ class Bnd_B2f;
  * <p>
  * This mechanism works when either UpdateViews() or RebuildViews() is called
  * from time to time, only these two methods can call compactObjects().
+ * @ingroup nis_library
  */
 
 class NIS_InteractiveContext : public Standard_Transient
@@ -167,6 +171,12 @@ class NIS_InteractiveContext : public Standard_Transient
   Standard_EXPORT const Handle_NIS_InteractiveObject&
                        GetObject  (const Standard_Integer theID) const;
 
+  /**
+   * Access map of objects with specified draw type.
+   */
+  Standard_EXPORT const TColStd_PackedMapOfInteger&
+    GetObjectsOfType (const NIS_Drawer::DrawType theType) const;
+
   /**
    * Query the total number of InteractiveObject instances. This number can be
    * smaller than the greatest object ID, therefore you should not iterate till
@@ -193,6 +203,13 @@ class NIS_InteractiveContext : public Standard_Transient
                         GetDrawers () const
   { return NCollection_Map<Handle_NIS_Drawer>::Iterator(myDrawers); }
 
+  /**
+   * Access to views.
+   */
+  inline NCollection_List<Handle_NIS_View>::Iterator
+                        GetViews () const
+  { return NCollection_List<Handle_NIS_View>::Iterator(myViews); }
+
   // ================ BEGIN Mangement of Objects ================
   ///@name Management of Objects
   //@{
@@ -364,14 +381,16 @@ class NIS_InteractiveContext : public Standard_Transient
    * This method does not update the views.
    * @param O
    *   Object to be selected or deselected
-   * @param isMultiple
-   *   If True, then the objects are not automatically deselected.
+   * @param isModifierUsed
+   *   If True, then the modification of the current selection mode happens.
+   *   E.g. if True and selection mode is normal, the objects are not automatically
+   *   deselected.
    * @return
    *   True if the selection status has been changed, False if nothing changed
    */
   Standard_EXPORT Standard_Boolean
                         ProcessSelection(const Handle_NIS_InteractiveObject& O,
-                                         const Standard_Boolean     isMultiple
+                                         const Standard_Boolean     isModifierUsed
                                             = Standard_False);
 
   /**
@@ -380,11 +399,13 @@ class NIS_InteractiveContext : public Standard_Transient
    * selection mode is respected.
    * @param map
    *   Container of IDs of objects to be processed
-   * @param isMultiple
-   *   If True, then the objects are not automatically deselected.
+   * @param isModifierUsed
+   *   If True, then the modification of the current selection mode happens.
+   *   E.g. if True and selection mode is normal, the objects are not automatically
+   *   deselected.
    */
   Standard_EXPORT void  ProcessSelection(const TColStd_PackedMapOfInteger& map,
-                                         const Standard_Boolean     isMultiple
+                                         const Standard_Boolean     isModifierUsed
                                             = Standard_False);
 
   /**
@@ -464,6 +485,11 @@ class NIS_InteractiveContext : public Standard_Transient
   inline void             SetShareDrawList  (Standard_Boolean isShare)
   { myIsShareDrawList = isShare; }
 
+  /**
+   * Compresses the allocated memory.
+   */
+  Standard_EXPORT void CompactObjects();
+
   //@}
   // ====== END Selection API ================
 
@@ -471,19 +497,19 @@ class NIS_InteractiveContext : public Standard_Transient
   //! Structure referencing one detected (picked) interactive entity.
   struct DetectedEnt
   {
-    Standard_Real          Dist; //!< Distance on the view direction
-    NIS_InteractiveObject* PObj; //!< Pointer to interactive object
+    Standard_Real             Dist; //!< Distance on the view direction
+    NIS_InteractiveObject*    PObj; //!< Pointer to interactive object
+    NIS_Drawer::PriorityLevel Prio; //!< Selected object drawer priority
   };
 
   // ---------- PROTECTED METHODS ----------
 
-  Standard_EXPORT void redraw           (const Handle_NIS_View&     theView,
-                                         const NIS_Drawer::DrawType theType);
+  Standard_EXPORT void redraw (const Handle_NIS_View&          theView,
+                               const NIS_Drawer::DrawType      theType,
+                               const NIS_Drawer::PriorityLevel thePriority);
 
   /**
    * Detect the object selected by the given ray.
-   * @param theSel
-   *   <tt>[out]</tt> The selected object that has the lowest ray distance.
    * @param theDet
    *   <tt>[out]</tt> Sorted list of all detected objects with ray distances
    * @param theAxis
@@ -493,16 +519,17 @@ class NIS_InteractiveContext : public Standard_Transient
    * @param isOnlySelectable
    *   If False, any displayed object can be picked, otherwise only selectable
    *   ones.
+   * @param theEvent
+   *   Describes the evernt that invokes this method.
    * @return
    *   The ray distance of the intersection point between the ray and theSel. 
    */
   Standard_EXPORT Standard_Real
-                       selectObject     (Handle_NIS_InteractiveObject& theSel,
-                                         NCollection_List<DetectedEnt>& theDet,
-                                         const gp_Ax1&                 theAxis,
-                                         const Standard_Real           theOver,
-                                         const Standard_Boolean isOnlySelectable
-                                         = Standard_True) const;
+         selectObject (NCollection_List<DetectedEnt>& theDet,
+                       const gp_Ax1&                  theAxis,
+                       const Standard_Real            theOver,
+                       const Standard_Boolean         isOnlySelectable = Standard_True,
+                       const NIS_SelectFilter::Event  theEvent = NIS_SelectFilter::Indefinite) const;
 
   /**
    * Build a list of objects that are inside or touched by an oriented box.
@@ -572,6 +599,8 @@ private:
   Handle_NIS_Allocator
         compactObjects          ();
 
+  void  detachView              (NCollection_List<Handle_NIS_View>::Iterator&);
+
  private:
   // ---------- PRIVATE FIELDS ----------
 
@@ -611,6 +640,11 @@ private:
    */
   TColStd_PackedMapOfInteger                        myMapObjects[4];
 
+  /**
+   * Number of drawers per priority.
+   */
+  Standard_Integer myPriorities[NIS_Drawer::Priority_LevelsNb];
+
   /**
    * Objects contained in this map are ignored by SetSelected methods,
    * these objects are not selectable.
index ab355d5e142742f152c848fb885177e681a7494e..033408f0b0c559e5ef912461571e92f3ae323633 100644 (file)
@@ -41,7 +41,8 @@ const Handle_NIS_Drawer& NIS_InteractiveObject::SetDrawer
                                          const Standard_Boolean    setUpdated)
 {
   NIS_InteractiveContext * aCtx = theDrawer->GetContext();
-  if (myDrawer.IsNull() == Standard_False) {
+  if (myDrawer.IsNull() == Standard_False)
+  {
     if (aCtx == 0L)
     {
       aCtx = myDrawer->GetContext();
@@ -65,9 +66,12 @@ const Handle_NIS_Drawer& NIS_InteractiveObject::SetDrawer
   {
     // Move the Object from the old drawer to the new one.
     if (myDrawer.IsNull() == Standard_False)
+    {
       myDrawer->removeObject(this, Standard_True);
+    }
     myDrawer = aDrawer;
 
+    ++aCtx->myPriorities[myDrawer->Priority()];
     myDrawer->addObject(this, aCtx->myIsShareDrawList, Standard_True);
   }
   if (setUpdated)
@@ -107,7 +111,7 @@ void NIS_InteractiveObject::SetTransparency (const Standard_Real theValue)
         (aCtx == 0L, "NIS_InteractiveObject::SetTransparency: "
                      "NULL drawer context");
       if (IsTransparent()) {
-        if (myDrawType == NIS_Drawer::Draw_Normal) {
+        if (myDrawType != NIS_Drawer::Draw_Transparent) {
           aCtx->myMapObjects[NIS_Drawer::Draw_Transparent].Add(myID);
           aCtx->myMapObjects[NIS_Drawer::Draw_Normal].Remove(myID);
           myDrawType = NIS_Drawer::Draw_Transparent;
@@ -117,7 +121,7 @@ void NIS_InteractiveObject::SetTransparency (const Standard_Real theValue)
         if (myDrawType == NIS_Drawer::Draw_Transparent) {
           aCtx->myMapObjects[NIS_Drawer::Draw_Normal].Add(myID);
           aCtx->myMapObjects[NIS_Drawer::Draw_Transparent].Remove(myID);
-          myDrawType = NIS_Drawer::Draw_Normal;
+          myDrawType = myBaseType;
         }
         myDrawer->SetUpdated (NIS_Drawer::Draw_Transparent);
       }
@@ -238,3 +242,56 @@ void NIS_InteractiveObject::SetSelectable (const Standard_Boolean isSel) const
     }
   }
 }
+
+//=======================================================================
+//function : SetColor
+//purpose  : Set the color for presentation.
+//=======================================================================
+
+void NIS_InteractiveObject::SetColor (const Quantity_Color&      theColor,
+                                      const NIS_Drawer::DrawType theType)
+{
+  const Handle(NIS_Drawer) aDrawer = DefaultDrawer(0L);
+  aDrawer->Assign (GetDrawer());
+  aDrawer->SetColor(theType, theColor); 
+  SetDrawer (aDrawer);
+}
+
+//=======================================================================
+//function : GetColor
+//purpose  : Get the color for presentation.
+//=======================================================================
+
+Quantity_Color NIS_InteractiveObject::GetColor
+                        (const NIS_Drawer::DrawType theType) const
+{
+  return myDrawer.IsNull() ? Quantity_Color() : myDrawer->GetColor(theType);
+}
+
+//=======================================================================
+//function : SetHilightColors
+//purpose  : Set the colors for hilight and dynamic hilight presentations.
+//=======================================================================
+
+void NIS_InteractiveObject::SetHilightColors (const Quantity_Color& theHLColor,
+                                              const Quantity_Color& theDHLColor)
+{
+  const Handle(NIS_Drawer) aDrawer = DefaultDrawer(0L);
+  aDrawer->Assign (GetDrawer());
+  aDrawer->SetColor(NIS_Drawer::Draw_Hilighted, theHLColor); 
+  aDrawer->SetColor(NIS_Drawer::Draw_DynHilighted, theDHLColor); 
+  SetDrawer (aDrawer);
+}
+
+//=======================================================================
+//function : IsOut
+//purpose  : Check the intersection a line/ray with the bounding box of object.
+//=======================================================================
+
+Standard_Boolean NIS_InteractiveObject::IsOut
+                                        (const gp_Ax1&          theAxis,
+                                         const Standard_Boolean isRay,
+                                         const Standard_Real    theOver)
+{
+    return GetBox().IsOut (theAxis, isRay, theOver);
+}
index 14602d72e0e47d6c755e462e3f9f52c206325c4c..cec552d2acc5f64d475a2a1e7b769668d706487d 100644 (file)
@@ -48,7 +48,7 @@
  * method should not be called by any custom code, it is used internally by
  * NIS algorithms (in NIS_InteractiveContext::Display() for instance). If you
  * develop your own InteractiveObject type, you will need to call SetDrawer
- * whenever you change the visual aspect, for example:
+ * whenever you change a visual aspect, for example:
  * @code
  * void MyIOClass::SetColor (const Quantity_Color&  theColor);
  * {
@@ -74,7 +74,7 @@
  *     Parameter theOver provides the tolerance for intersection of thin
  *     geometries (lines, vertices)</li>
  * <li>Intersect (theBox, theTrsf, isFullIn) : check if the interactive object
- *     intersects with a 3D box. Transformation 'theTrf' is the <b>inverse</b>
+ *     intersects with a 3D box. Transformation 'theTrsf' is the <b>inverse</b>
  *     box transformation, so it is applied to the interactive object rather
  *     than to the 3D box (3D box stays axis-aligned during intersection
  *     test). Parameter IsFullIn defines the condition for the result: if
@@ -93,9 +93,9 @@
  * because NIS_InteractiveContext should completely manage all its objects,
  * meaning that it destroys/reallocates them automatically. To support that,
  * the virtual method Clone() should be correctly defined for every interactive
- * object subtype. Supposing that MyIOClass inherits MyBaseIOBase :
+ * object subtype. Supposing that MyIOClass inherits MyIOBase :
  * @code
- * void MyIOCalss::Clone (const Handle_NCollection_BaseAllocator& theAlloc,
+ * void MyIOClass::Clone (const Handle_NCollection_BaseAllocator& theAlloc,
  *                        Handle_NIS_InteractiveObject&           theDest) const
  * {
  *   Handle(MyIOClass) aNewObj;
  * stored as a pointer. It can accommodate an integer/float/boolean value or
  * a pointer to some structure. This attribute is NOT automatically destroyed
  * with the InteractiveObject.  
+ * @ingroup nis_library
  */
 
 class NIS_InteractiveObject : public Standard_Transient
@@ -341,6 +342,50 @@ class NIS_InteractiveObject : public Standard_Transient
        Intersect     (const NCollection_List<gp_XY> &thePolygon,
                       const gp_Trsf                 &theTrf,
                       const Standard_Boolean         isFull) const;
+  /**
+   * Set the color for presentation.
+   * @param theColor
+   *   New color to use for the presentation.
+   * @param theType
+   *   Draw type for which the color is defined
+   */
+  Standard_EXPORT virtual void SetColor
+        (const Quantity_Color&      theColor,
+         const NIS_Drawer::DrawType theType = NIS_Drawer::Draw_Normal);
+
+  /**
+   * Set the color for hilighted presentation.
+   * @param theColor
+   *   New color to use for the presentation.
+   */
+  inline void SetHilightColor (const Quantity_Color& theColor)
+  {
+    return SetColor (theColor, NIS_Drawer::Draw_Hilighted);
+  }
+
+  /**
+   * Set the color for dynamic hilight presentation.
+   * @param theColor
+   *   New color to use for the presentation.
+   */
+  inline void SetDynHilightColor (const Quantity_Color& theColor)
+  {
+    SetColor (theColor, NIS_Drawer::Draw_DynHilighted);
+  }
+
+  /**
+   * Set the colors for hilight and dynamic hilight presentations.
+   */
+  Standard_EXPORT void SetHilightColors(const Quantity_Color& theHLColor,
+                                        const Quantity_Color& theDHLColor);
+
+  /**
+   * Get Normal, Transparent or Hilighted color of the presentation.  
+   * @param theType
+   *   The draw type, for which the color is retrieved.
+   */
+  Standard_EXPORT Quantity_Color GetColor 
+        (const NIS_Drawer::DrawType theType = NIS_Drawer::Draw_Normal) const;
 
   /**
    * Set the pointer to custom (arbitrary) data associated with the Object.
@@ -354,6 +399,15 @@ class NIS_InteractiveObject : public Standard_Transient
   inline void *           GetAttribute  () const
   { return myAttributePtr; }
 
+  /**
+   * Check the intersection a line/ray with the bounding box of object.
+   * @see Bnd_B3f::IsOut().
+   */
+  Standard_EXPORT virtual Standard_Boolean
+                          IsOut         (const gp_Ax1&          theAxis,
+                                         const Standard_Boolean isRay = 0,
+                                         const Standard_Real    theOver = 0.0);
+
  protected:
   // ---------- PROTECTED METHODS ----------
 
diff --git a/src/NIS/NIS_Line.cxx b/src/NIS/NIS_Line.cxx
new file mode 100644 (file)
index 0000000..6af2817
--- /dev/null
@@ -0,0 +1,281 @@
+// File:      NIS_Line.cpp
+// Created:   11.05.12
+// Author:    Natalia Kopnova
+// Copyright: LPKF Laser and Electronics AG 2012
+
+#include <NIS_Line.hxx>
+#include <NIS_LineDrawer.hxx>
+#include <NIS_InteractiveContext.hxx>
+#include <Precision.hxx>
+#include <UnitsAPI.hxx>
+
+IMPLEMENT_STANDARD_HANDLE  (NIS_Line, NIS_InteractiveObject)
+IMPLEMENT_STANDARD_RTTIEXT (NIS_Line, NIS_InteractiveObject)
+
+#define MAX_WIDTH 500000.
+
+//=======================================================================
+//function : NIS_Line
+//purpose  : Constructor
+//=======================================================================
+
+NIS_Line::NIS_Line(const gp_Ax1& theAxis)
+{
+    //   SetAttributeId(0);
+    Init(theAxis);
+}
+
+//=======================================================================
+//function : Init
+//purpose  : Re-initialize the internal structures, re-compute the presentation
+//=======================================================================
+
+void NIS_Line::Init(const gp_Ax1& theAxis)
+{
+    myLine = theAxis;
+
+    const Handle(NIS_LineDrawer) aDrawer =
+        Handle(NIS_LineDrawer)::DownCast(GetDrawer());
+
+    // Standard_Real aLength = UnitsAPI::AnyToLS( 250000., "mm" );
+    const gp_XYZ aLength = (0.5 * MAX_WIDTH) * myLine.Direction().XYZ();
+
+    gp_XYZ aPoint1;
+
+    if(aDrawer.IsNull())
+    {
+        aPoint1 = myLine.Location().XYZ();
+    }
+    else
+    {
+        if ( aDrawer->myLineType == NIS_LT_Line )
+        {
+            aPoint1 = myLine.Location().XYZ() - aLength;
+        }
+        else
+        {
+            aPoint1 = myLine.Location().XYZ();
+        }
+    }
+
+    myPoint1[0] = static_cast<Standard_ShortReal> (aPoint1.X());
+    myPoint1[1] = static_cast<Standard_ShortReal> (aPoint1.Y());
+    myPoint1[2] = static_cast<Standard_ShortReal> (aPoint1.Z());
+
+    const gp_XYZ aPoint2 = myLine.Location().XYZ() + aLength;
+    myPoint2[0] = static_cast<Standard_ShortReal> (aPoint2.X());
+    myPoint2[1] = static_cast<Standard_ShortReal> (aPoint2.Y());
+    myPoint2[2] = static_cast<Standard_ShortReal> (aPoint2.Z());
+
+    // setIsUpdateBox(Standard_True);
+}
+
+//=======================================================================
+//function : ~NIS_Line
+//purpose  : Destructor
+//=======================================================================
+
+NIS_Line::~NIS_Line()
+{
+}
+
+//=======================================================================
+//function : DefaultDrawer
+//purpose  :
+//=======================================================================
+
+NIS_Drawer* NIS_Line::DefaultDrawer (NIS_Drawer* theDrawer) const
+{
+    if (theDrawer == 0L)
+    {
+        return new NIS_LineDrawer(Quantity_NOC_YELLOW);
+    }
+    NIS_LineDrawer* aDrawer = static_cast<NIS_LineDrawer*>(theDrawer);
+    return aDrawer;
+}
+
+//=======================================================================
+//function : Clone
+//purpose  : 
+//=======================================================================
+
+void NIS_Line::Clone
+                        (const Handle_NCollection_BaseAllocator& theAlloc,
+                         Handle_NIS_InteractiveObject&           theDest) const
+{
+    Handle(NIS_Line) aNewObj;
+    if (theDest.IsNull())
+    {
+        aNewObj = new NIS_Line(myLine);
+        theDest = aNewObj;
+    }
+    else
+    {
+        aNewObj = reinterpret_cast<NIS_Line*> (theDest.operator->());
+        aNewObj->myLine = myLine;
+        aNewObj->myPoint1[0] = myPoint1[0];
+        aNewObj->myPoint1[1] = myPoint1[1];
+        aNewObj->myPoint1[2] = myPoint1[2];
+        aNewObj->myPoint2[0] = myPoint2[0];
+        aNewObj->myPoint2[1] = myPoint2[1];
+        aNewObj->myPoint2[2] = myPoint2[2];
+    }
+    NIS_InteractiveObject::Clone(theAlloc, theDest);
+}
+
+//=======================================================================
+//function : SetLineWidth
+//purpose  : Set the line width in pixels.
+//=======================================================================
+
+void NIS_Line::SetLineWidth (const Standard_Real theSize)
+{
+    const Handle(NIS_LineDrawer) aDrawer =
+        static_cast<NIS_LineDrawer*>(DefaultDrawer(0L));
+    aDrawer->Assign(GetDrawer());
+    aDrawer->myLineWidth = static_cast<Standard_ShortReal>(theSize);
+    SetDrawer(aDrawer);
+}
+
+//=======================================================================
+//function : SetLineStyle
+//purpose  : Set the style of line presentation.
+//=======================================================================
+
+void NIS_Line::SetLineStyle  (const NIS_LineStyle theStyle)
+{
+    const Handle(NIS_LineDrawer) aDrawer =
+        static_cast<NIS_LineDrawer*>(DefaultDrawer(0L));
+    aDrawer->Assign(GetDrawer());
+    aDrawer->myType = static_cast<Standard_Integer>(theStyle);
+    SetDrawer(aDrawer);
+}
+
+
+//=======================================================================
+//function : SetLineType
+//purpose  : Set the type of line presentation.
+//=======================================================================
+
+void NIS_Line::SetLineType  (const NIS_LineType theType)
+{
+    const Handle(NIS_LineDrawer) aDrawer =
+        static_cast<NIS_LineDrawer*>(DefaultDrawer(0L));
+    aDrawer->Assign(GetDrawer());
+    aDrawer->myLineType = static_cast<Standard_Integer>(theType);
+    SetDrawer(aDrawer);
+}
+
+//=======================================================================
+//function : SetInvertColor
+//purpose  : Indicates whether to draw line depending on underlying objects
+//=======================================================================
+
+void NIS_Line::SetInvertColor (const Standard_Boolean theInvert)
+{
+    const Handle(NIS_LineDrawer) aDrawer =
+        static_cast<NIS_LineDrawer*>(DefaultDrawer(0L));
+    aDrawer->Assign(GetDrawer());
+    aDrawer->myInvertColor = static_cast<Standard_Boolean>(theInvert);
+    SetDrawer(aDrawer);
+}
+
+//=======================================================================
+//function : Intersect
+//purpose  :
+//=======================================================================
+
+Standard_Boolean NIS_Line::Intersect
+                                        (const Bnd_B3f&         theBox,
+                                         const gp_Trsf&         theTrf,
+                                         const Standard_Boolean /*isFullIn*/) const
+{
+    return !theBox.IsOut(myLine.Transformed(theTrf));
+}
+
+//=======================================================================
+//function : Intersect
+//purpose  :
+//=======================================================================
+
+Standard_Real NIS_Line::Intersect(const gp_Ax1&       theAxis,
+                                  const Standard_Real theOver) const
+{
+    Standard_Real aResult (RealLast());
+    const Standard_Real anOver2 = theOver*theOver;
+
+    const gp_XYZ anAxisDir = theAxis.Direction().XYZ();
+    const gp_XYZ aDir = myLine.Direction().XYZ();
+    const gp_XYZ aDirN = aDir ^ anAxisDir;  // normal direction to both lines
+    // vector between 'start' points of two lines
+    const gp_XYZ aDelta = myLine.Location().XYZ() - theAxis.Location().XYZ();
+
+    Standard_Real aMod2 = aDirN.SquareModulus();
+    if (aMod2 < Precision::Confusion() * 0.001)
+    {
+        // lines are parallel
+        if ( (aDelta ^ anAxisDir).SquareModulus() < anOver2 )
+        {
+            aResult = aDelta * anAxisDir;
+        }
+    }
+    else
+    {
+        // distance between two lines
+        Standard_Real aDist = aDelta * aDirN;
+        if (aDist * aDist < anOver2 * aMod2)
+        {
+            aResult = aDelta * anAxisDir;
+        }
+    }
+
+    return aResult;
+}
+
+//=======================================================================
+//function : Intersect
+//purpose  :
+//=======================================================================
+
+Standard_Boolean NIS_Line::Intersect
+                         (const NCollection_List<gp_XY> &thePolygon,
+                          const gp_Trsf                 &theTrf,
+                          const Standard_Boolean         /*isFullIn*/) const
+{
+    Standard_Boolean aResult = Standard_False;
+
+    gp_Ax1 aLine = myLine.Transformed(theTrf);
+    const gp_XYZ aLoc = aLine.Location().XYZ();
+    const gp_XYZ aDir = aLine.Direction().XYZ();
+
+    gp_XY aDir2d(aDir.X(), aDir.Y());
+    Standard_Real aDist = aDir2d.SquareModulus();
+    if (aDist > Precision::Confusion())
+    {
+        aDir2d.Divide(sqrt(aDist));
+
+        // check whether all polygon points in in the same side of line
+        // Line is presented in form Ax + By + C = 0
+        Standard_Real A =  aDir.Y();
+        Standard_Real B = -aDir.X();
+        Standard_Real C = -(A*aLoc.X() + B*aLoc.Y());
+
+        gp_XY aPoint = thePolygon.Last();
+        Standard_Real aSigned[2];
+        aSigned[0] = A*aPoint.X() + B*aPoint.Y() + C;
+
+        NCollection_List<gp_XY>::Iterator anIter(thePolygon);
+        for (; anIter.More(); anIter.Next())
+        {
+            aPoint = anIter.Value();
+            aSigned[1] = A*aPoint.X() + B*aPoint.Y() + C;
+            if (aSigned[0] * aSigned[1] <= Precision::Confusion())
+            {
+                aResult = Standard_True;
+                break;
+            }
+            aSigned[0] = aSigned[1];
+        }
+    }
+    return aResult;
+}
diff --git a/src/NIS/NIS_Line.hxx b/src/NIS/NIS_Line.hxx
new file mode 100644 (file)
index 0000000..06fe340
--- /dev/null
@@ -0,0 +1,213 @@
+// File:      NIS_Line.h
+// Created:   11.05.12
+// Author:    Natalia Kopnova
+// Copyright: LPKF Laser and Electronics AG 2012
+
+#ifndef NIS_Line_HeaderFile
+#define NIS_Line_HeaderFile
+
+#include <NIS_InteractiveObject.hxx>
+#include <NIS_LineDrawer.hxx>
+#include <gp_Ax1.hxx>
+
+class Handle_NIS_InteractiveContext;
+
+//! Line style enumeration
+//! @ingroup aisobject
+enum NIS_LineStyle {
+    NIS_LS_Solid = 0,
+    NIS_LS_Dash,
+    NIS_LS_Dot,
+    NIS_LS_DotDash,
+    NIS_LS_DoubleDotDash
+};
+
+//! Line type enumeration
+//! @ingroup aisobject
+enum NIS_LineType {
+    NIS_LT_Line = 0,
+    NIS_LT_Ray
+};
+
+/**
+ * Interactive Object for 2D/3D lines
+ * @ingroup aisobject
+ */
+
+class NIS_Line : public NIS_InteractiveObject
+{
+ public:
+  // ---------- PUBLIC METHODS ----------
+
+  /**
+   * Constructor.
+   */
+  Standard_EXPORT NIS_Line (const gp_Ax1& theAxis);
+
+  /**
+   * Destructor.
+   */
+  Standard_EXPORT virtual ~NIS_Line ();
+
+  /**
+   * Re-initialize the internal structures, re-compute the presentation
+   */
+  Standard_EXPORT void      Init           (const gp_Ax1& theAxis);
+
+  /**
+   * Create a default drawer instance.
+   */
+  Standard_EXPORT virtual NIS_Drawer*
+                            DefaultDrawer  (NIS_Drawer*) const;
+
+
+  /**
+   * Method required by NIS_InteractiveContext.
+   */
+  Standard_EXPORT virtual void
+                            Clone    (const Handle_NCollection_BaseAllocator&,
+                                      Handle_NIS_InteractiveObject&) const;
+
+  /**
+   * Set the line width in pixels.
+   * @param theSize
+   *   New line width to use for the presentation.
+   */
+  Standard_EXPORT void      SetLineWidth   (const Standard_Real theSize);
+
+  /**
+   * Set the line style.
+   * @param theStyle
+   *   Line style to be used for the presentation.
+   */
+  Standard_EXPORT void      SetLineStyle   (const NIS_LineStyle theStyle);
+
+   /**
+   * Set the line type.
+   * @param theType
+   *   Line type to be used for the presentation.
+   */
+  Standard_EXPORT void      SetLineType   (const NIS_LineType theType);
+
+  /**
+   * Set whether line color should be inverted depending on color of
+   * underlying objects.
+   * @param theInvert
+   *   True to invert color.
+   */
+  Standard_EXPORT void      SetInvertColor (const Standard_Boolean theInvert);
+
+  /**
+   * Intersect the InteractiveObject geometry with an oriented box.
+   * @param theBox
+   *   3D box of selection
+   * @param theTrf
+   *   Position/Orientation of the box.
+   * @param isFull
+   *   True if full inclusion is required, False - if partial.
+   * @return
+   *   True if the InteractiveObject geometry intersects the box or is inside it
+   */
+  Standard_EXPORT virtual Standard_Boolean
+                            Intersect      (const Bnd_B3f&         theBox,
+                                            const gp_Trsf&         theTrf,
+                                            const Standard_Boolean isFull)const;
+  /**
+   * Intersect the InteractiveObject geometry with a line/ray.
+   * @param theAxis
+   *   The line or ray in 3D space.
+   * @param theOver
+   *   Half-thickness of the selecting line.
+   * @return
+   *   If the return value is more than 0.1*RealLast() then no intersection is
+   *   detected. Otherwise returns the coordinate of thePnt on the ray. May be
+   *   negative.
+   */
+  Standard_EXPORT virtual Standard_Real
+                            Intersect      (const gp_Ax1&         theAxis,
+                                            const Standard_Real   theOver)const;
+
+  /**
+   * Intersect the InteractiveObject geometry with a selection polygon.
+   * @param thePolygon
+   *   the list of vertices of a free-form closed polygon without
+   *   self-intersections. The last point should not coincide with the first
+   *   point of the list. Any two neighbor points should not be confused.
+   * @param theTrf
+   *   Position/Orientation of the polygon.
+   * @param isFull
+   *   True if full inclusion is required, False - if partial.
+   * @return
+   *   True if the InteractiveObject geometry intersects the polygon or is
+   *   inside it
+   */
+  Standard_EXPORT virtual Standard_Boolean Intersect
+                    (const NCollection_List<gp_XY> &thePolygon,
+                     const gp_Trsf                 &theTrf,
+                     const Standard_Boolean         isFull) const;
+
+  /**
+   * Store an integer value as attribute of the Object.
+   */
+  inline void             SetAttributeId   (const Standard_Integer theId)
+  {
+    SetAttribute (reinterpret_cast <void*> (theId));
+  }
+
+  /**
+   * Returns the attribute value previously stored using SetAttributeId.
+   * Value 0 signifies that the AttributeId has not been set (as this is
+   * the constructor default value).
+   */
+  inline Standard_Integer GetAttributeId   () const
+  {
+    return reinterpret_cast <Standard_Integer> (GetAttribute());
+  } 
+
+  /**
+   * Query the point coordinates.
+   */
+  inline const Standard_ShortReal* GetPoint (const Standard_Integer ind) const
+  {
+    return (ind & 0x1) ? &myPoint1[0] : &myPoint2[0];
+  }
+
+ protected:
+
+  /**
+   * Create a 3D bounding box of the object.
+   * Does nothing because line is considered as infinitive
+   */
+  Standard_EXPORT virtual void  computeBox      ()
+  {}
+
+ private:
+  // ---------- PRIVATE METHODS ----------
+  NIS_Line (const NIS_Line& theOther);
+  NIS_Line& operator= (const NIS_Line& theOther);
+
+  static Handle_NIS_LineDrawer defaultDrawer();
+
+ private:
+  // ---------- PRIVATE FIELDS ----------
+
+  gp_Ax1                        myLine;
+
+  /**
+   * Array of coords
+   */
+  Standard_ShortReal            myPoint1[3];
+  Standard_ShortReal            myPoint2[3];
+
+ public:
+// Declaration of CASCADE RTTI
+DEFINE_STANDARD_RTTI (NIS_Line)
+
+  friend class NIS_LineDrawer;
+};
+
+// Definition of HANDLE object using Standard_DefineHandle.hxx
+DEFINE_STANDARD_HANDLE (NIS_Line, NIS_InteractiveObject)
+
+
+#endif
diff --git a/src/NIS/NIS_LineDrawer.cxx b/src/NIS/NIS_LineDrawer.cxx
new file mode 100644 (file)
index 0000000..b945ecc
--- /dev/null
@@ -0,0 +1,176 @@
+// File:      NIS_LineDrawer.cpp
+// Created:   11.05.12
+// Author:    Natalia Kopnova
+// Copyright: LPKF Laser and Electronics AG 2012
+
+#include <NIS_LineDrawer.hxx>
+#include <NIS_Line.hxx>
+#ifdef _DEBUG
+#include <Standard_ProgramError.hxx>
+#endif
+#ifdef WNT
+#include <windows.h>
+#include <GL/gl.h>
+#endif
+
+#define NUM_STYLES 5
+static GLushort pattern[NUM_STYLES] = {
+    0xFFFF,  // Solid
+    0xFFC0,  // Dash
+    0xCCCC,  // Dot
+    0xFF18,  // DotDash
+    0xFF24   // DoubleDotDash
+};
+
+IMPLEMENT_STANDARD_HANDLE  (NIS_LineDrawer, NIS_Drawer)
+IMPLEMENT_STANDARD_RTTIEXT (NIS_LineDrawer, NIS_Drawer)
+
+//=======================================================================
+//function : NIS_LineDrawer
+//purpose  : Constructor
+//=======================================================================
+
+NIS_LineDrawer::NIS_LineDrawer(const Quantity_Color& theColor)
+  : myLineWidth(1.f), myType(0), myLineType(0), myInvertColor(Standard_False)
+{
+    SetColor(Draw_Normal, theColor);
+    SetColor(Draw_Hilighted, Quantity_NOC_GRAY80);
+    SetColor(Draw_DynHilighted, Quantity_NOC_CYAN1);
+}
+
+//=======================================================================
+//function : Assign
+//purpose  :
+//=======================================================================
+
+void NIS_LineDrawer::Assign (const Handle_NIS_Drawer& theOther)
+{
+    if (theOther.IsNull() == Standard_False)
+    {
+        NIS_Drawer::Assign(theOther);
+        const Handle(NIS_LineDrawer)& anOther =
+            static_cast <const Handle(NIS_LineDrawer)&> (theOther);
+        myLineWidth = anOther->myLineWidth;
+        myType = anOther->myType;
+        myLineType = anOther->myLineType;
+        myInvertColor = anOther->myInvertColor;
+    }
+}
+
+//=======================================================================
+//function : IsEqual
+//purpose  : Comparison of two Drawers (for Map impementation)
+//=======================================================================
+
+Standard_Boolean NIS_LineDrawer::IsEqual
+                                (const Handle_NIS_Drawer& theOther) const
+{
+    static const Standard_Real anEpsilon2 (1e-7);
+    Standard_Boolean aResult (Standard_False);
+    const Handle(NIS_LineDrawer) anOther =
+        Handle(NIS_LineDrawer)::DownCast(theOther);
+    if (NIS_Drawer::IsEqual(theOther))
+    {
+        aResult = ((anOther->myLineWidth - myLineWidth) *
+                   (anOther->myLineWidth - myLineWidth) < 0.01 &&
+                   anOther->myType == myType &&
+                   anOther->myLineType == myLineType &&
+                   anOther->myInvertColor == myInvertColor);
+    }
+    return aResult;
+}
+
+//=======================================================================
+//function : BeforeDraw
+//purpose  :
+//=======================================================================
+
+void NIS_LineDrawer::BeforeDraw (const DrawType         theType,
+                                       const NIS_DrawList&    /*theDrawList*/)
+{
+    Quantity_Parameter   aValue[4];
+    aValue[3] = 1.;                               // opaque as default
+    Quantity_TypeOfColor bidTC (Quantity_TOC_RGB);
+    GLfloat aLineWidth (myLineWidth);
+
+    if (theType == Draw_DynHilighted)
+    {
+        aLineWidth = myLineWidth + 1.f;
+    }
+
+    if (myInvertColor)
+    {
+        glEnable(GL_COLOR_LOGIC_OP);
+        glLogicOp(GL_XOR);
+    }
+    else if (theType == Draw_Transparent)
+    {
+        aValue[3] = 1. - myTransparency;
+        glEnable(GL_BLEND);
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    }
+
+    GetColor(theType).Values(aValue[0], aValue[1], aValue[2], bidTC);
+    glColor4d (aValue[0], aValue[1], aValue[2], aValue[3]);
+    glDisable(GL_LIGHTING);
+
+    if (myType > 0 && myType < NUM_STYLES)
+    {
+        glEnable(GL_LINE_STIPPLE);
+        glLineStipple(1, pattern[myType]);
+    }
+
+    glLineWidth(aLineWidth);
+}
+
+//=======================================================================
+//function : AfterDraw
+//purpose  :
+//=======================================================================
+
+void NIS_LineDrawer::AfterDraw (const DrawType         theType,
+                                      const NIS_DrawList&    /*theDrawList*/)
+{
+    if (myInvertColor)
+    {
+        glDisable(GL_COLOR_LOGIC_OP);
+    }
+    else if (theType == Draw_Transparent)
+    {
+        glDisable(GL_BLEND);
+    }
+
+    if (myType > 0 && myType < NUM_STYLES)
+    {
+        glDisable(GL_LINE_STIPPLE);
+    }
+}
+
+//=======================================================================
+//function : Draw
+//purpose  :
+//=======================================================================
+
+void NIS_LineDrawer::Draw (const Handle_NIS_InteractiveObject& theObj,
+                                 const DrawType         /*theType*/,
+                                 const NIS_DrawList&    /*theDrawList*/)
+{
+    // Assertion for the type of the drawn object
+#ifdef _DEBUG
+    static const Handle(Standard_Type) ThisType =
+        STANDARD_TYPE(NIS_Line);
+    if (theObj->IsKind(ThisType) == Standard_False)
+    {
+        Standard_ProgramError::Raise("NIS_LineDrawer::Draw: "
+                                     "irrelevant object type");
+    }
+#endif
+    const NIS_Line* pObject =
+        static_cast <const NIS_Line*> (theObj.operator->());
+
+    // Draw line
+    glBegin(GL_LINES);
+    glVertex3fv(&pObject->myPoint1[0]);
+    glVertex3fv(&pObject->myPoint2[0]);
+    glEnd();
+}
diff --git a/src/NIS/NIS_LineDrawer.hxx b/src/NIS/NIS_LineDrawer.hxx
new file mode 100644 (file)
index 0000000..06c2bf1
--- /dev/null
@@ -0,0 +1,85 @@
+// File:      NIS_LineDrawer.h
+// Created:   11.05.12
+// Author:    Natalia Kopnova
+// Copyright: LPKF Laser and Electronics AG 2012
+
+#ifndef NIS_LineDrawer_HeaderFile
+#define NIS_LineDrawer_HeaderFile
+
+#include <NIS_Drawer.hxx>
+
+class NIS_Line;
+
+/**
+ * NIS drawer for NIS_Line interactive object type.
+ * @ingroup aisobject
+ */
+
+class NIS_LineDrawer : public NIS_Drawer
+{
+ public:
+  // ---------- PUBLIC METHODS ----------
+
+  /**
+   * Constructor.
+   */
+  Standard_EXPORT NIS_LineDrawer   (const Quantity_Color& theColor);
+
+  /**
+   * Copy the relevant information from another instance of Drawer.
+   * raises exception if theOther has incompatible type (test IsKind).
+   */
+  Standard_EXPORT virtual void Assign    (const Handle_NIS_Drawer& theOther);
+
+  /**
+   * Called before execution of Draw(), once per group of interactive objects.
+   */
+  Standard_EXPORT virtual void BeforeDraw(const DrawType         theType,
+                                          const NIS_DrawList&    theDrawList);
+
+  /**
+   * Called after execution of Draw(), once per group of interactive objects.
+   */
+  Standard_EXPORT virtual void AfterDraw(const DrawType         theType,
+                                         const NIS_DrawList&    theDrawList);
+
+  /**
+   * Main function: display the given interactive object in the given view.
+   */
+  Standard_EXPORT virtual void Draw      (const Handle_NIS_InteractiveObject&,
+                                          const DrawType         theType,
+                                          const NIS_DrawList&    theDrawList);
+
+  /**
+   * Matching two instances, for Map interface.
+   */
+  Standard_EXPORT virtual Standard_Boolean
+                               IsEqual   (const Handle_NIS_Drawer& theOth)const;
+
+
+ protected:
+  // ---------- PROTECTED METHODS ----------
+
+
+
+ private:
+  // ---------- PRIVATE FIELDS ----------
+
+  Standard_ShortReal  myLineWidth;
+  Standard_Integer    myType;
+  Standard_Integer    myLineType;
+  Standard_Boolean    myInvertColor;
+
+
+ public:
+// Declaration of CASCADE RTTI
+DEFINE_STANDARD_RTTI (NIS_LineDrawer)
+
+  friend class NIS_Line;
+};
+
+// Definition of HANDLE object using Standard_DefineHandle.hxx
+DEFINE_STANDARD_HANDLE (NIS_LineDrawer, NIS_Drawer)
+
+
+#endif
index fb582c0f27904c62a5eaececd14e5135e8524307..f4c65f33b368a1d429f637943b3d167540b30617 100644 (file)
@@ -38,6 +38,7 @@ class Handle_NIS_InteractiveContext;
  *   anIter.Next();
  * }
  * @endcode
+ * @ingroup nis_library
  */
 
 class NIS_ObjectsIterator 
diff --git a/src/NIS/NIS_Point.cxx b/src/NIS/NIS_Point.cxx
new file mode 100644 (file)
index 0000000..88f7d1a
--- /dev/null
@@ -0,0 +1,278 @@
+// File:      NIS_Point.cpp
+// Created:   12.02.09
+// Author:    Natalia Kopnova
+// Copyright: LPKF Laser and Electronics AG 2008
+
+#include <NIS_Point.hxx>
+#include <NIS_PointDrawer.hxx>
+#include <NIS_InteractiveContext.hxx>
+#include <NIS_Triangulated.hxx>
+#include <Precision.hxx>
+#include <gp_Ax1.hxx>
+
+IMPLEMENT_STANDARD_HANDLE  (NIS_Point, NIS_InteractiveObject)
+IMPLEMENT_STANDARD_RTTIEXT (NIS_Point, NIS_InteractiveObject)
+
+//=======================================================================
+//function : NIS_Point
+//purpose  : Constructor
+//=======================================================================
+
+NIS_Point::NIS_Point
+                (const gp_XY&                            thePoint,
+                 const Standard_Real                     theZ)
+  : myIs3D              (Standard_False)
+{
+    //   SetAttributeId(0); // agv: already initialized in the base class
+    Init(thePoint, theZ);
+}
+
+//=======================================================================
+//function : NIS_Point
+//purpose  : Constructor
+//=======================================================================
+
+NIS_Point::NIS_Point
+                (const gp_XYZ&                            thePoint)
+  : myIs3D              (Standard_True),
+    myZ                 (RealLast())
+{
+    //   SetAttributeId(0); // agv: already initialized in the base class
+    Init(thePoint);
+}
+
+//=======================================================================
+//function : Init
+//purpose  : Re-initialize the internal structures, re-compute the presentation
+//=======================================================================
+
+void NIS_Point::Init(const gp_XY&        thePoint,
+                           const Standard_Real theZ)
+{
+    myZ = theZ;
+
+    myCoords[0] = static_cast<Standard_ShortReal> (thePoint.X());
+    myCoords[1] = static_cast<Standard_ShortReal> (thePoint.Y());
+    myCoords[2] = static_cast<Standard_ShortReal> (myZ);
+
+    if (GetDrawer().IsNull() == Standard_False)
+    {
+        setDrawerUpdate();
+    }
+    setIsUpdateBox(Standard_True);
+}
+
+//=======================================================================
+//function : Init
+//purpose  : Re-initialize the internal structures, re-compute the presentation
+//=======================================================================
+
+void NIS_Point::Init(const gp_XYZ& thePoint)
+{
+    myCoords[0] = static_cast<Standard_ShortReal> (thePoint.X());
+    myCoords[1] = static_cast<Standard_ShortReal> (thePoint.Y());
+    myCoords[2] = static_cast<Standard_ShortReal> (thePoint.Z());
+
+    if (GetDrawer().IsNull() == Standard_False)
+    {
+        setDrawerUpdate();
+    }
+    setIsUpdateBox(Standard_True);
+}
+
+//=======================================================================
+//function : ~NIS_Point
+//purpose  : Destructor
+//=======================================================================
+
+NIS_Point::~NIS_Point()
+{
+}
+
+//=======================================================================
+//function : DefaultDrawer
+//purpose  :
+//=======================================================================
+
+NIS_Drawer* NIS_Point::DefaultDrawer (NIS_Drawer* theDrawer) const
+{
+    if (theDrawer == 0L)
+    {
+        return new NIS_PointDrawer(Quantity_NOC_GREEN);
+    }
+    return theDrawer;
+}
+
+//=======================================================================
+//function : Clone
+//purpose  : 
+//=======================================================================
+
+void NIS_Point::Clone
+                        (const Handle_NCollection_BaseAllocator& theAlloc,
+                         Handle_NIS_InteractiveObject&           theDest) const
+{
+    Handle(NIS_Point) aNewObj;
+    if (theDest.IsNull())
+    {
+        aNewObj = new NIS_Point;
+        theDest = aNewObj;
+    }
+    else
+    {
+        aNewObj = reinterpret_cast<NIS_Point*> (theDest.operator->());
+    }
+    NIS_InteractiveObject::Clone(theAlloc, theDest);
+    aNewObj->myIs3D = myIs3D;
+    aNewObj->myZ = myZ;
+    aNewObj->myCoords[0] = myCoords[0];
+    aNewObj->myCoords[1] = myCoords[1];
+    aNewObj->myCoords[2] = myCoords[2];
+}
+
+//=======================================================================
+//function : SetPointSize
+//purpose  : Set the size of point presentations in pixels.
+//=======================================================================
+
+void NIS_Point::SetPointSize (const Standard_Real theSize)
+{
+    const Handle(NIS_PointDrawer) aDrawer =
+        static_cast<NIS_PointDrawer*>(DefaultDrawer(0L));
+    aDrawer->Assign(GetDrawer());
+    aDrawer->myPointSize = static_cast<Standard_ShortReal>(theSize);
+    SetDrawer(aDrawer);
+}
+
+//=======================================================================
+//function : SetMarkerType
+//purpose  : Set the type of point presentation.
+//=======================================================================
+
+void NIS_Point::SetMarkerType (const NIS_MarkerType theType)
+{
+    const Handle(NIS_PointDrawer) aDrawer =
+        static_cast<NIS_PointDrawer*>(DefaultDrawer(0L));
+    aDrawer->Assign(GetDrawer());
+    aDrawer->myType = static_cast<Standard_Integer>(theType);
+    SetDrawer(aDrawer);
+}
+
+//=======================================================================
+//function : SetInvertColor
+//purpose  : Indicates whether to draw point depending on underlying objects
+//=======================================================================
+
+void NIS_Point::SetInvertColor (const Standard_Boolean theInvert)
+{
+    const Handle(NIS_PointDrawer) aDrawer =
+        static_cast<NIS_PointDrawer*>(DefaultDrawer(0L));
+    aDrawer->Assign(GetDrawer());
+    aDrawer->myInvertColor = static_cast<Standard_Boolean>(theInvert);
+    SetDrawer(aDrawer);
+    //   // Use "trasparency" layer for drawing (after all objects)
+    //   SetTransparency();
+}
+
+//=======================================================================
+//function : SetAngle
+//purpose  : 
+//=======================================================================
+
+void NIS_Point::SetAngle (const Standard_Real theAngle)
+{
+    const Handle(NIS_PointDrawer) aDrawer =
+        static_cast<NIS_PointDrawer*>(DefaultDrawer(0L));
+    aDrawer->Assign(GetDrawer());
+    Standard_Real anAngle = theAngle;
+    while (anAngle > M_PI / 2.0)
+    {
+        anAngle -= M_PI;
+    }
+    while (anAngle < - M_PI / 2.0)
+    {
+        anAngle += M_PI;
+    }
+    if (std::abs(aDrawer->myAngle - anAngle) > Precision::Angular())
+    {
+        aDrawer->myAngle = anAngle;
+        aDrawer->myIsUpdateAngle = Standard_True;
+    }
+    SetDrawer(aDrawer);
+}
+
+//=======================================================================
+//function : Intersect
+//purpose  :
+//=======================================================================
+
+Standard_Boolean NIS_Point::Intersect
+                                        (const Bnd_B3f&         theBox,
+                                         const gp_Trsf&         theTrf,
+                                         const Standard_Boolean /*isFullIn*/) const
+{
+    gp_XYZ aPnt (static_cast<Standard_Real>(myCoords[0]),
+                 static_cast<Standard_Real>(myCoords[1]),
+                 static_cast<Standard_Real>(myCoords[2]));
+    theTrf.Transforms(aPnt);
+    return !theBox.IsOut(aPnt);
+}
+
+//=======================================================================
+//function : Intersect
+//purpose  :
+//=======================================================================
+
+Standard_Real NIS_Point::Intersect  (const gp_Ax1&       theAxis,
+                                           const Standard_Real theOver) const
+{
+    Standard_Real aResult (RealLast());
+    // We extend the intersect distance to facilitate selection
+    const Standard_Real anOver2 = theOver * theOver * 5.;
+
+    // check if the point is closed to line
+    const gp_XYZ& aStart = theAxis.Location().XYZ();
+    const gp_XYZ& aDir = theAxis.Direction().XYZ();
+    const gp_XYZ aDelta(static_cast<Standard_Real>(myCoords[0]) - aStart.X(),
+                        static_cast<Standard_Real>(myCoords[1]) - aStart.Y(),
+                        static_cast<Standard_Real>(myCoords[2]) - aStart.Z());
+    if ((aDelta ^ aDir).SquareModulus() < anOver2)
+    {
+        aResult = aDelta * aDir;
+    }
+
+    return aResult;
+}
+
+//=======================================================================
+//function : Intersect
+//purpose  :
+//=======================================================================
+
+Standard_Boolean NIS_Point::Intersect
+                         (const NCollection_List<gp_XY> &thePolygon,
+                          const gp_Trsf                 &theTrf,
+                          const Standard_Boolean         /*isFullIn*/) const
+{
+    gp_XYZ aPnt (static_cast<Standard_Real>(myCoords[0]),
+                 static_cast<Standard_Real>(myCoords[1]),
+                 static_cast<Standard_Real>(myCoords[2]));
+    theTrf.Transforms(aPnt);
+
+    gp_XY aP2d(aPnt.X(), aPnt.Y());
+    return NIS_Triangulated::IsIn(thePolygon, aP2d);
+}
+
+//=======================================================================
+//function : computeBox
+//purpose  :
+//=======================================================================
+
+void NIS_Point::computeBox ()
+{
+    myBox.Clear();
+    myBox.Add (gp_XYZ(static_cast<Standard_Real>(myCoords[0]),
+                      static_cast<Standard_Real>(myCoords[1]),
+                      static_cast<Standard_Real>(myCoords[2])));
+    myBox.Enlarge(2.0f); // enlarge a sensetive area
+}
diff --git a/src/NIS/NIS_Point.hxx b/src/NIS/NIS_Point.hxx
new file mode 100644 (file)
index 0000000..a1e420e
--- /dev/null
@@ -0,0 +1,240 @@
+// File:      NIS_Point.h
+// Created:   11.05.12
+// Author:    Natalia Kopnova
+// Copyright: LPKF Laser and Electronics AG 2012
+
+#ifndef NIS_Point_HeaderFile
+#define NIS_Point_HeaderFile
+
+#include <NIS_InteractiveObject.hxx>
+
+//! Marker type enumeration.
+//! @ingroup aisobject
+enum NIS_MarkerType {
+    NIS_MT_POINT = 0,
+    NIS_MT_PLUS,
+    NIS_MT_STAR,
+    NIS_MT_CROSS,
+    NIS_MT_CIRCLE,
+    NIS_MT_FILLED_CIRCLE,
+    NIS_MT_ARROW_RIGHT,
+    NIS_MT_ARROW_UP,
+    NIS_MT_ARROW_LEFT,
+    NIS_MT_ARROW_DOWN,
+    NIS_MT_ARROW_UP_RIGHT,
+    NIS_MT_ARROW_UP_LEFT,
+    NIS_MT_ARROW_DOWN_LEFT,
+    NIS_MT_ARROW_DOWN_RIGHT,
+    NIS_MT_SQUARE,
+    NIS_MT_TRIANGLE,
+    NIS_MT_CIRCLE_BOLD,
+    NIS_MT_CROSS_BOLD,
+    NIS_MT_ROMB,
+    NIS_MT_CROSS_CIRCLE,
+    NIS_MT_LINE
+};
+
+/**
+ * Interactive Object for 2D/3D points
+ * @ingroup aisobject
+ */
+
+class NIS_Point : public NIS_InteractiveObject
+{
+public:
+ // ---------- PUBLIC METHODS ----------
+
+  /**
+   * Constructor for 2D point.
+   */
+  Standard_EXPORT NIS_Point (const gp_XY&        thePoint,
+                                   const Standard_Real theZ);
+
+  /**
+   * Constructor for 3D point.
+   */
+  Standard_EXPORT NIS_Point (const gp_XYZ& thePoint);
+
+  /**
+   * Destructor.
+   */
+  Standard_EXPORT virtual ~NIS_Point ();
+
+  /**
+   * Re-initialize the internal structures, re-compute the presentation
+   * If only Z is changed, then recompute is much faster.
+   */
+  Standard_EXPORT void      Init(const gp_XY&        thePoint,
+                                 const Standard_Real theZ);
+
+  /**
+   * Re-initialize the internal structures, re-compute the presentation
+   */
+  Standard_EXPORT void      Init(const gp_XYZ& thePoint);
+
+  /**
+   * Create a default drawer instance.
+   */
+  Standard_EXPORT virtual NIS_Drawer*
+                            DefaultDrawer  (NIS_Drawer*) const;
+
+
+  /**
+   * Method required by NIS_InteractiveContext.
+   */
+  Standard_EXPORT virtual void Clone (const Handle_NCollection_BaseAllocator&,
+                                      Handle_NIS_InteractiveObject&) const;
+
+  /**
+   * Return coordinates of the Point 
+   */
+  inline gp_Pnt GetLocation() const
+  {
+    return gp_Pnt(myCoords[0], myCoords[1], myCoords[2]);
+  }
+
+  /**
+   * Set the size of point presentations in pixels.
+   * @param theSize
+   *   New point size to use for the presentation.
+   */
+  Standard_EXPORT void      SetPointSize   (const Standard_Real    theSize);
+
+  /**
+   * Set the type of point presentations.
+   * @param theType
+   *   Type of marker to use for the presentation.
+   */
+  Standard_EXPORT void      SetMarkerType  (const NIS_MarkerType theType);
+
+  /**
+   * Set whether the point color should be inverted depending on
+   * the color of underlying objects.
+   * @param theInvert
+   *   True to invert color.
+   */
+  Standard_EXPORT void      SetInvertColor (const Standard_Boolean theInvert);
+  
+  /**
+   * Set the angle of the bitmap rotation.
+   * New bitmap will be generated if theAngle is not equal to zero.
+   * @param theAngle
+   *   The angle of the bitmap rotation.
+   */
+  Standard_EXPORT void      SetAngle       (const Standard_Real theAngle);
+
+  /**
+   * Intersect the InteractiveObject geometry with an oriented box.
+   * @param theBox
+   *   3D box of selection
+   * @param theTrf
+   *   Position/Orientation of the box.
+   * @param isFull
+   *   True if full inclusion is required, False - if partial.
+   * @return
+   *   True if the InteractiveObject geometry intersects the box or is inside it
+   */
+  Standard_EXPORT virtual Standard_Boolean
+                            Intersect      (const Bnd_B3f&         theBox,
+                                            const gp_Trsf&         theTrf,
+                                            const Standard_Boolean isFull)const;
+  /**
+   * Intersect the InteractiveObject geometry with a line/ray.
+   * @param theAxis
+   *   The line or ray in 3D space.
+   * @param theOver
+   *   Half-thickness of the selecting line.
+   * @return
+   *   If the return value is more than 0.1*RealLast() then no intersection is
+   *   detected. Otherwise returns the coordinate of thePnt on the ray. May be
+   *   negative.
+   */
+  Standard_EXPORT virtual Standard_Real
+                            Intersect      (const gp_Ax1&         theAxis,
+                                            const Standard_Real   theOver)const;
+
+  /**
+   * Intersect the InteractiveObject geometry with a selection polygon.
+   * @param thePolygon
+   *   the list of vertices of a free-form closed polygon without
+   *   self-intersections. The last point should not coincide with the first
+   *   point of the list. Any two neighbor points should not be confused.
+   * @param theTrf
+   *   Position/Orientation of the polygon.
+   * @param isFull
+   *   True if full inclusion is required, False - if partial.
+   * @return
+   *   True if the InteractiveObject geometry intersects the polygon or is
+   *   inside it
+   */
+  Standard_EXPORT virtual Standard_Boolean Intersect
+                    (const NCollection_List<gp_XY> &thePolygon,
+                     const gp_Trsf                 &theTrf,
+                     const Standard_Boolean         isFull) const;
+
+  /**
+   * Store an integer value as attribute of the Object.
+   */
+  inline void             SetAttributeId   (const Standard_Integer theId)
+  {
+    SetAttribute (reinterpret_cast <void*> (theId));
+  }
+
+  /**
+   * Returns the attribute value previously stored using SetAttributeId.
+   * Value 0 signifies that the AttributeId has not been set (as this is
+   * the constructor default value).
+   */
+  inline Standard_Integer GetAttributeId   () const
+  {
+    return reinterpret_cast <Standard_Integer> (GetAttribute());
+  } 
+
+  /**
+   * Query if the Point is a 3D object.
+   */
+  inline Standard_Boolean Is3D             () const
+  {
+    return myIs3D;
+  }
+
+
+ protected:
+
+  //! Empty constructor for method Clone()
+  inline NIS_Point()
+  {}
+
+  /**
+   * Create a 3D bounding box of the object.
+   */
+  Standard_EXPORT virtual void  computeBox      ();
+
+ private:
+  // ---------- PRIVATE METHODS ----------
+  NIS_Point (const NIS_Point& theOther);
+  NIS_Point& operator= (const NIS_Point& theOther);
+
+ protected:
+  // ---------- PRIVATE FIELDS ----------
+
+  Standard_Boolean              myIs3D;
+  Standard_Real                 myZ;
+
+  /**
+   * Array of coords
+   */
+  Standard_ShortReal            myCoords[3];
+
+
+public:
+// Declaration of CASCADE RTTI
+DEFINE_STANDARD_RTTI (NIS_Point)
+
+  friend class NIS_PointDrawer;
+};
+
+// Definition of HANDLE object using Standard_DefineHandle.hxx
+DEFINE_STANDARD_HANDLE (NIS_Point, NIS_InteractiveObject)
+
+#endif
diff --git a/src/NIS/NIS_PointDrawer.cxx b/src/NIS/NIS_PointDrawer.cxx
new file mode 100644 (file)
index 0000000..0a508ed
--- /dev/null
@@ -0,0 +1,1621 @@
+// File:      NIS_PointDrawer.cpp
+// Created:   11.05.12
+// Author:    Natalia Kopnova
+// Copyright: LPKF Laser and Electronics AG 2012
+
+#include <NIS_PointDrawer.hxx>
+#include <NIS_Point.hxx>
+#include <Precision.hxx>
+#ifdef _DEBUG
+#include <Standard_ProgramError.hxx>
+#endif
+#ifdef WNT
+#include <windows.h>
+#include <GL/gl.h>
+#endif
+
+//=======================================================================
+//purpose  : Marker definition
+//=======================================================================
+#define NUM_TYPES 20
+#define NUM_SIZES 5
+
+#define COUNT_PLUS_1 9*2
+#define COUNT_PLUS_2 11*2
+#define COUNT_PLUS_3 13*2
+#define COUNT_PLUS_4 15*2
+#define COUNT_PLUS_5 17*3
+
+#define COUNT_STAR_1 9
+#define COUNT_STAR_2 11*2
+#define COUNT_STAR_3 13*2
+#define COUNT_STAR_4 15*2
+#define COUNT_STAR_5 17*2
+
+#define COUNT_CROSS_1 7
+#define COUNT_CROSS_2 9*2
+#define COUNT_CROSS_3 11*2
+#define COUNT_CROSS_4 13*2
+#define COUNT_CROSS_5 15*2
+
+#define COUNT_CIRCLE_1 7
+#define COUNT_CIRCLE_2 8
+#define COUNT_CIRCLE_3 9*2
+#define COUNT_CIRCLE_4 11*2
+#define COUNT_CIRCLE_5 13*2
+
+#define COUNT_FILLED_CIRCLE_1 7
+#define COUNT_FILLED_CIRCLE_2 8
+#define COUNT_FILLED_CIRCLE_3 9*2
+#define COUNT_FILLED_CIRCLE_4 11*2
+#define COUNT_FILLED_CIRCLE_5 13*2
+
+#define COUNT_ANGLE0_1 7
+#define COUNT_ANGLE0_2 8
+#define COUNT_ANGLE0_3 11*2
+#define COUNT_ANGLE0_4 13*2
+#define COUNT_ANGLE0_5 15*2
+
+#define COUNT_ANGLE90_1 7
+#define COUNT_ANGLE90_2 8
+#define COUNT_ANGLE90_3 10*2
+#define COUNT_ANGLE90_4 13*2
+#define COUNT_ANGLE90_5 16*2
+
+#define COUNT_ANGLE180_1 7
+#define COUNT_ANGLE180_2 8
+#define COUNT_ANGLE180_3 11*2
+#define COUNT_ANGLE180_4 13*2
+#define COUNT_ANGLE180_5 15*2
+
+#define COUNT_ANGLE270_1 7
+#define COUNT_ANGLE270_2 8
+#define COUNT_ANGLE270_3 10*2
+#define COUNT_ANGLE270_4 13*2
+#define COUNT_ANGLE270_5 16*2
+
+#define COUNT_ANGLE45_1 8
+#define COUNT_ANGLE45_2 8
+#define COUNT_ANGLE45_3 11*2
+#define COUNT_ANGLE45_4 14*2
+#define COUNT_ANGLE45_5 16*2
+
+#define COUNT_ANGLE135_1 7
+#define COUNT_ANGLE135_2 8
+#define COUNT_ANGLE135_3 11*2
+#define COUNT_ANGLE135_4 14*2
+#define COUNT_ANGLE135_5 16*2
+
+#define COUNT_ANGLE225_1 8
+#define COUNT_ANGLE225_2 8
+#define COUNT_ANGLE225_3 11*2
+#define COUNT_ANGLE225_4 14*2
+#define COUNT_ANGLE225_5 16*2
+
+#define COUNT_ANGLE315_1 7
+#define COUNT_ANGLE315_2 8
+#define COUNT_ANGLE315_3 11*2
+#define COUNT_ANGLE315_4 14*2
+#define COUNT_ANGLE315_5 16*2
+
+#define COUNT_SQUARE_17x17 17*3
+
+#define COUNT_TRIANGLE_17x15 15*3
+
+#define COUNT_CIRCLE_BOLD_19x19 19*3
+
+#define COUNT_CROSS_BOLD_17x17 17*3
+
+#define COUNT_ROMB_19x19 19*3
+
+#define COUNT_CROSS_CIRCLE_19x19 19*3
+
+#define COUNT_LINE 24*3
+
+#define OFFSET_PLUS_1 0
+#define OFFSET_PLUS_2 OFFSET_PLUS_1 + COUNT_PLUS_1
+#define OFFSET_PLUS_3 OFFSET_PLUS_2 + COUNT_PLUS_2
+#define OFFSET_PLUS_4 OFFSET_PLUS_3 + COUNT_PLUS_3
+#define OFFSET_PLUS_5 OFFSET_PLUS_4 + COUNT_PLUS_4
+
+#define OFFSET_STAR_1 OFFSET_PLUS_5 + COUNT_PLUS_5
+#define OFFSET_STAR_2 OFFSET_STAR_1 + COUNT_STAR_1
+#define OFFSET_STAR_3 OFFSET_STAR_2 + COUNT_STAR_2
+#define OFFSET_STAR_4 OFFSET_STAR_3 + COUNT_STAR_3
+#define OFFSET_STAR_5 OFFSET_STAR_4 + COUNT_STAR_4
+
+#define OFFSET_CROSS_1 OFFSET_STAR_5 + COUNT_STAR_5
+#define OFFSET_CROSS_2 OFFSET_CROSS_1 + COUNT_CROSS_1
+#define OFFSET_CROSS_3 OFFSET_CROSS_2 + COUNT_CROSS_2
+#define OFFSET_CROSS_4 OFFSET_CROSS_3 + COUNT_CROSS_3
+#define OFFSET_CROSS_5 OFFSET_CROSS_4 + COUNT_CROSS_4
+
+#define OFFSET_CIRCLE_1 OFFSET_CROSS_5 + COUNT_CROSS_5
+#define OFFSET_CIRCLE_2 OFFSET_CIRCLE_1 + COUNT_CIRCLE_1
+#define OFFSET_CIRCLE_3 OFFSET_CIRCLE_2 + COUNT_CIRCLE_2
+#define OFFSET_CIRCLE_4 OFFSET_CIRCLE_3 + COUNT_CIRCLE_3
+#define OFFSET_CIRCLE_5 OFFSET_CIRCLE_4 + COUNT_CIRCLE_4
+
+#define OFFSET_FILLED_CIRCLE_1 OFFSET_CIRCLE_5 + COUNT_CIRCLE_5
+#define OFFSET_FILLED_CIRCLE_2 OFFSET_FILLED_CIRCLE_1 + COUNT_FILLED_CIRCLE_1
+#define OFFSET_FILLED_CIRCLE_3 OFFSET_FILLED_CIRCLE_2 + COUNT_FILLED_CIRCLE_2
+#define OFFSET_FILLED_CIRCLE_4 OFFSET_FILLED_CIRCLE_3 + COUNT_FILLED_CIRCLE_3
+#define OFFSET_FILLED_CIRCLE_5 OFFSET_FILLED_CIRCLE_4 + COUNT_FILLED_CIRCLE_4
+
+#define OFFSET_ANGLE0_1 OFFSET_FILLED_CIRCLE_5 + COUNT_FILLED_CIRCLE_5
+#define OFFSET_ANGLE0_2 OFFSET_ANGLE0_1 + COUNT_ANGLE0_1
+#define OFFSET_ANGLE0_3 OFFSET_ANGLE0_2 + COUNT_ANGLE0_2
+#define OFFSET_ANGLE0_4 OFFSET_ANGLE0_3 + COUNT_ANGLE0_3
+#define OFFSET_ANGLE0_5 OFFSET_ANGLE0_4 + COUNT_ANGLE0_4
+
+#define OFFSET_ANGLE90_1 OFFSET_ANGLE0_5 + COUNT_ANGLE0_5
+#define OFFSET_ANGLE90_2 OFFSET_ANGLE90_1 + COUNT_ANGLE90_1
+#define OFFSET_ANGLE90_3 OFFSET_ANGLE90_2 + COUNT_ANGLE90_2
+#define OFFSET_ANGLE90_4 OFFSET_ANGLE90_3 + COUNT_ANGLE90_3
+#define OFFSET_ANGLE90_5 OFFSET_ANGLE90_4 + COUNT_ANGLE90_4
+
+#define OFFSET_ANGLE180_1 OFFSET_ANGLE90_5 + COUNT_ANGLE90_5
+#define OFFSET_ANGLE180_2 OFFSET_ANGLE180_1 + COUNT_ANGLE180_1
+#define OFFSET_ANGLE180_3 OFFSET_ANGLE180_2 + COUNT_ANGLE180_2
+#define OFFSET_ANGLE180_4 OFFSET_ANGLE180_3 + COUNT_ANGLE180_3
+#define OFFSET_ANGLE180_5 OFFSET_ANGLE180_4 + COUNT_ANGLE180_4
+
+#define OFFSET_ANGLE270_1 OFFSET_ANGLE180_5 + COUNT_ANGLE180_5
+#define OFFSET_ANGLE270_2 OFFSET_ANGLE270_1 + COUNT_ANGLE270_1
+#define OFFSET_ANGLE270_3 OFFSET_ANGLE270_2 + COUNT_ANGLE270_2
+#define OFFSET_ANGLE270_4 OFFSET_ANGLE270_3 + COUNT_ANGLE270_3
+#define OFFSET_ANGLE270_5 OFFSET_ANGLE270_4 + COUNT_ANGLE270_4
+
+#define OFFSET_ANGLE45_1 OFFSET_ANGLE270_5 + COUNT_ANGLE270_5
+#define OFFSET_ANGLE45_2 OFFSET_ANGLE45_1 + COUNT_ANGLE45_1
+#define OFFSET_ANGLE45_3 OFFSET_ANGLE45_2 + COUNT_ANGLE45_2
+#define OFFSET_ANGLE45_4 OFFSET_ANGLE45_3 + COUNT_ANGLE45_3
+#define OFFSET_ANGLE45_5 OFFSET_ANGLE45_4 + COUNT_ANGLE45_4
+
+#define OFFSET_ANGLE135_1 OFFSET_ANGLE45_5 + COUNT_ANGLE45_5
+#define OFFSET_ANGLE135_2 OFFSET_ANGLE135_1 + COUNT_ANGLE135_1
+#define OFFSET_ANGLE135_3 OFFSET_ANGLE135_2 + COUNT_ANGLE135_2
+#define OFFSET_ANGLE135_4 OFFSET_ANGLE135_3 + COUNT_ANGLE135_3
+#define OFFSET_ANGLE135_5 OFFSET_ANGLE135_4 + COUNT_ANGLE135_4
+
+#define OFFSET_ANGLE225_1 OFFSET_ANGLE135_5 + COUNT_ANGLE135_5
+#define OFFSET_ANGLE225_2 OFFSET_ANGLE225_1 + COUNT_ANGLE225_1
+#define OFFSET_ANGLE225_3 OFFSET_ANGLE225_2 + COUNT_ANGLE225_2
+#define OFFSET_ANGLE225_4 OFFSET_ANGLE225_3 + COUNT_ANGLE225_3
+#define OFFSET_ANGLE225_5 OFFSET_ANGLE225_4 + COUNT_ANGLE225_4
+
+#define OFFSET_ANGLE315_1 OFFSET_ANGLE225_5 + COUNT_ANGLE225_5
+#define OFFSET_ANGLE315_2 OFFSET_ANGLE315_1 + COUNT_ANGLE315_1
+#define OFFSET_ANGLE315_3 OFFSET_ANGLE315_2 + COUNT_ANGLE315_2
+#define OFFSET_ANGLE315_4 OFFSET_ANGLE315_3 + COUNT_ANGLE315_3
+#define OFFSET_ANGLE315_5 OFFSET_ANGLE315_4 + COUNT_ANGLE315_4
+
+#define OFFSET_SQUARE_17x17       OFFSET_ANGLE315_5 + COUNT_ANGLE315_5
+
+#define OFFSET_TRIANGLE_17x15     OFFSET_SQUARE_17x17  + COUNT_SQUARE_17x17
+
+#define OFFSET_CIRCLE_BOLD_19x19  OFFSET_TRIANGLE_17x15 + COUNT_TRIANGLE_17x15
+
+#define OFFSET_CROSS_BOLD_17x17   OFFSET_CIRCLE_BOLD_19x19 + COUNT_CIRCLE_BOLD_19x19
+
+#define OFFSET_ROMB_19x19         OFFSET_CROSS_BOLD_17x17 + COUNT_CROSS_BOLD_17x17
+
+#define OFFSET_CROSS_CIRCLE_19x19 OFFSET_ROMB_19x19 + COUNT_ROMB_19x19
+
+#define OFFSET_LINE               OFFSET_CROSS_CIRCLE_19x19 + COUNT_CROSS_CIRCLE_19x19
+
+struct markerbase {
+    int width;
+    int height;
+    int offset;
+};
+
+static markerbase data[NUM_TYPES][NUM_SIZES] = {
+    { // Plus
+        { 9, 9, OFFSET_PLUS_1 },
+        { 11, 11, OFFSET_PLUS_2 },
+        { 13, 13, OFFSET_PLUS_3 },
+        { 15, 15, OFFSET_PLUS_4 },
+        { 17, 17, OFFSET_PLUS_5 }
+    },
+    { // Star
+        { 7, 9, OFFSET_STAR_1 },
+        { 9, 11, OFFSET_STAR_2 },
+        { 11, 13, OFFSET_STAR_3 },
+        { 13, 15, OFFSET_STAR_4 },
+        { 13, 17, OFFSET_STAR_5 }
+    },
+    { // Cross
+        { 7, 7, OFFSET_CROSS_1 },
+        { 9, 9, OFFSET_CROSS_2 },
+        { 11, 11, OFFSET_CROSS_3 },
+        { 13, 13, OFFSET_CROSS_4 },
+        { 15, 15, OFFSET_CROSS_5 }
+    },
+    { // Circle
+        { 7, 7, OFFSET_CIRCLE_1 },
+        { 8, 8, OFFSET_CIRCLE_2 },
+        { 9, 9, OFFSET_CIRCLE_3 },
+        { 11, 11, OFFSET_CIRCLE_4 },
+        { 13, 13, OFFSET_CIRCLE_5 }
+    },
+    { // Filled Circle
+        { 7, 7, OFFSET_FILLED_CIRCLE_1 },
+        { 8, 8, OFFSET_FILLED_CIRCLE_2 },
+        { 9, 9, OFFSET_FILLED_CIRCLE_3 },
+        { 11, 11, OFFSET_FILLED_CIRCLE_4 },
+        { 13, 13, OFFSET_FILLED_CIRCLE_5 }
+    },
+    { // Arrow right
+        { 7, 7, OFFSET_ANGLE0_1 },
+        { 8, 8, OFFSET_ANGLE0_2 },
+        { 10, 11, OFFSET_ANGLE0_3 },
+        { 13, 13, OFFSET_ANGLE0_4 },
+        { 16, 15, OFFSET_ANGLE0_5 }
+    },
+    { // Arrow up
+        { 7, 7, OFFSET_ANGLE90_1 },
+        { 8, 8, OFFSET_ANGLE90_2 },
+        { 11, 10, OFFSET_ANGLE90_3 },
+        { 13, 13, OFFSET_ANGLE90_4 },
+        { 15, 16, OFFSET_ANGLE90_5 }
+    },
+    { // Arrow left
+        { 7, 7, OFFSET_ANGLE180_1 },
+        { 8, 8, OFFSET_ANGLE180_2 },
+        { 10, 11, OFFSET_ANGLE180_3 },
+        { 13, 13, OFFSET_ANGLE180_4 },
+        { 16, 15, OFFSET_ANGLE180_5 }
+    },
+    { // Arrow down
+        { 7, 7, OFFSET_ANGLE270_1 },
+        { 8, 8, OFFSET_ANGLE270_2 },
+        { 11, 10, OFFSET_ANGLE270_3 },
+        { 13, 13, OFFSET_ANGLE270_4 },
+        { 15, 16, OFFSET_ANGLE270_5 }
+    },
+    { // Arrow up-right
+        { 8, 7, OFFSET_ANGLE45_1 },
+        { 8, 8, OFFSET_ANGLE45_2 },
+        { 11, 11, OFFSET_ANGLE45_3 },
+        { 14, 14, OFFSET_ANGLE45_4 },
+        { 16, 16, OFFSET_ANGLE45_5 }
+    },
+    { // Arrow up-left
+        { 7, 8, OFFSET_ANGLE135_1 },
+        { 8, 8, OFFSET_ANGLE135_2 },
+        { 11, 11, OFFSET_ANGLE135_3 },
+        { 14, 14, OFFSET_ANGLE135_4 },
+        { 16, 16, OFFSET_ANGLE135_5 }
+    },
+    { // Arrow down-left
+        { 8, 7, OFFSET_ANGLE225_1 },
+        { 8, 8, OFFSET_ANGLE225_2 },
+        { 11, 11, OFFSET_ANGLE225_3 },
+        { 14, 14, OFFSET_ANGLE225_4 },
+        { 16, 16, OFFSET_ANGLE225_5 }
+    },
+    { // Arrow down-right
+        { 7, 8, OFFSET_ANGLE315_1 },
+        { 8, 8, OFFSET_ANGLE315_2 },
+        { 11, 11, OFFSET_ANGLE315_3 },
+        { 14, 14, OFFSET_ANGLE315_4 },
+        { 16, 16, OFFSET_ANGLE315_5 }
+    },
+    {
+        { 17, 17, OFFSET_SQUARE_17x17 },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 }
+    },
+    {
+        { 17, 15, OFFSET_TRIANGLE_17x15 },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 }
+    },
+    {
+        { 19, 19, OFFSET_CIRCLE_BOLD_19x19 },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 }
+    },
+    {
+        { 17, 17, OFFSET_CROSS_BOLD_17x17 },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 }
+    },
+    {
+        { 19, 19, OFFSET_ROMB_19x19 },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 }
+    },
+    {
+        { 19, 19, OFFSET_CROSS_CIRCLE_19x19 },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 }
+    },
+    {
+        { 24, 24, OFFSET_LINE },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 },
+        { 0, 0, 0 }
+    }
+};
+
+static unsigned char raster[] = {
+    0x08,0x00,
+    0x08,0x00,
+    0x08,0x00,
+    0x08,0x00,
+    0xff,0x80,
+    0x08,0x00,
+    0x08,0x00,
+    0x08,0x00,
+    0x08,0x00,  // Plus 9x9
+
+    0x04,0x00,
+    0x04,0x00,
+    0x04,0x00,
+    0x04,0x00,
+    0x04,0x00,
+    0xff,0xe0,
+    0x04,0x00,
+    0x04,0x00,
+    0x04,0x00,
+    0x04,0x00,
+    0x04,0x00,  // Plus 11x11
+
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,
+    0xff,0xf8,
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,  // Plus 13x13
+
+    0x01,0x00,
+    0x01,0x00,
+    0x01,0x00,
+    0x01,0x00,
+    0x01,0x00,
+    0x01,0x00,
+    0x01,0x00,
+    0xff,0xfe,
+    0x01,0x00,
+    0x01,0x00,
+    0x01,0x00,
+    0x01,0x00,
+    0x01,0x00,
+    0x01,0x00,
+    0x01,0x00, // Plus 15x15
+
+    0x00,0x80,0x00,
+    0x00,0x80,0x00,
+    0x00,0x80,0x00,
+    0x00,0x80,0x00,
+    0x00,0x80,0x00,
+    0x00,0x80,0x00,
+    0x00,0x80,0x00,
+    0x00,0x80,0x00,
+    0xff,0xff,0x80,
+    0x00,0x80,0x00,
+    0x00,0x80,0x00,
+    0x00,0x80,0x00,
+    0x00,0x80,0x00,
+    0x00,0x80,0x00,
+    0x00,0x80,0x00,
+    0x00,0x80,0x00,
+    0x00,0x80,0x00, // Plus 17x17
+
+    0x10,
+    0x10,
+    0xd6,
+    0x38,
+    0x10,
+    0x38,
+    0xd6,
+    0x10,
+    0x10,  // Star 7x9
+
+    0x08,0x00,
+    0x08,0x00,
+    0x08,0x00,
+    0xc9,0x80,
+    0x3e,0x00,
+    0x08,0x00,
+    0x3e,0x00,
+    0xc9,0x80,
+    0x08,0x00,
+    0x08,0x00,
+    0x08,0x00,  // Star 9x11
+
+    0x04,0x00,
+    0x04,0x00,
+    0x04,0x00,
+    0x84,0x20,
+    0x64,0xc0,
+    0x1f,0x00,
+    0x04,0x00,
+    0x1f,0x00,
+    0x64,0xc0,
+    0x84,0x20,
+    0x04,0x00,
+    0x04,0x00,
+    0x04,0x00,  // Star 11x13
+
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,
+    0x82,0x18,
+    0x62,0x60,
+    0x1b,0x80,
+    0x06,0x00,
+    0x1b,0x80,
+    0x62,0x60,
+    0x82,0x18,
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,  // Start 13x15
+
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,
+    0x82,0x08,
+    0x62,0x30,
+    0x12,0x40,
+    0x0f,0x80,
+    0x02,0x00,
+    0x0f,0x80,
+    0x12,0x40,
+    0x62,0x30,
+    0x82,0x08,
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,
+    0x02,0x00,  // Star 13x17
+
+    0x82,
+    0x44,
+    0x28,
+    0x10,
+    0x28,
+    0x44,
+    0x82,  // Cross 7x7
+
+    0x80,0x80,
+    0x41,0x00,
+    0x22,0x00,
+    0x14,0x00,
+    0x08,0x00,
+    0x14,0x00,
+    0x22,0x00,
+    0x41,0x00,
+    0x80,0x80,  // Cross 9x9
+
+    0x80,0x20,
+    0x40,0x40,
+    0x20,0x80,
+    0x11,0x00,
+    0x0a,0x00,
+    0x04,0x00,
+    0x0a,0x00,
+    0x11,0x00,
+    0x20,0x80,
+    0x40,0x40,
+    0x80,0x20,  // Cross 11x11
+
+    0x80,0x08,
+    0x40,0x10,
+    0x20,0x20,
+    0x10,0x40,
+    0x08,0x80,
+    0x05,0x00,
+    0x02,0x00,
+    0x05,0x00,
+    0x08,0x80,
+    0x10,0x40,
+    0x20,0x20,
+    0x40,0x10,
+    0x80,0x08,  // Cross 13x13
+
+    0x80,0x02,
+    0x40,0x04,
+    0x20,0x08,
+    0x10,0x10,
+    0x08,0x20,
+    0x04,0x40,
+    0x02,0x80,
+    0x01,0x00,
+    0x02,0x80,
+    0x04,0x40,
+    0x08,0x20,
+    0x10,0x10,
+    0x20,0x08,
+    0x40,0x04,
+    0x80,0x02,  // Cross 15x15
+
+    0x38,
+    0x44,
+    0x82,
+    0x82,
+    0x82,
+    0x44,
+    0x38,  // Circle 7x7
+
+    0x3c,
+    0x42,
+    0x81,
+    0x81,
+    0x81,
+    0x81,
+    0x42,
+    0x3c,  // Circle 8x8
+
+    0x3e,0x00,
+    0x41,0x00,
+    0x81,0x80,
+    0x80,0x80,
+    0x80,0x80,
+    0x80,0x80,
+    0x81,0x80,
+    0x41,0x00,
+    0x3e,0x00,  // Circle 9x9
+
+    0x1f,0x00,
+    0x20,0x80,
+    0x40,0x40,
+    0x80,0x20,
+    0x80,0x20,
+    0x80,0x20,
+    0x80,0x20,
+    0x80,0x20,
+    0x40,0x40,
+    0x20,0x80,
+    0x1f,0x00,  // Circle 11x11
+
+    0x0f,0x80,
+    0x10,0x40,
+    0x20,0x20,
+    0x40,0x10,
+    0x80,0x08,
+    0x80,0x08,
+    0x80,0x08,
+    0x80,0x08,
+    0x80,0x08,
+    0x40,0x10,
+    0x20,0x20,
+    0x10,0x40,
+    0x0f,0x80,   // Circle 13x13
+
+    0x38,
+    0x7c,
+    0xfe,
+    0xfe,
+    0xfe,
+    0x7c,
+    0x38,  // Filled Circle 7x7
+
+    0x3c,
+    0x7e,
+    0xff,
+    0xff,
+    0xff,
+    0xff,
+    0x7e,
+    0x3c,  // Filled Circle 8x8
+
+    0x3e,0x00,
+    0x7f,0x00,
+    0xff,0x80,
+    0xff,0x80,
+    0xff,0x80,
+    0xff,0x80,
+    0xff,0x80,
+    0x7f,0x00,
+    0x3e,0x00,  // Filled Circle 9x9
+
+    0x1f,0x00,
+    0x3f,0x80,
+    0x7f,0xc0,
+    0xff,0xe0,
+    0xff,0xe0,
+    0xff,0xe0,
+    0xff,0xe0,
+    0xff,0xe0,
+    0x7f,0xc0,
+    0x3f,0x80,
+    0x1f,0x00,  // Filled Circle 11x11
+
+    0x0f,0x80,
+    0x1f,0xc0,
+    0x3f,0xe0,
+    0x7f,0xf0,
+    0xff,0xf8,
+    0xff,0xf8,
+    0xff,0xf8,
+    0xff,0xf8,
+    0xff,0xf8,
+    0x7f,0xf0,
+    0x3f,0xe0,
+    0x1f,0xc0,
+    0x0f,0x80,   // Filled Circle 13x13
+
+    0xc0,
+    0xf0,
+    0x3c,
+    0x3e,
+    0x3c,
+    0xf0,
+    0xc0,  // Arrow right 7x7
+
+    0xc0,
+    0x70,
+    0x7c,
+    0x3f,
+    0x3f,
+    0x7c,
+    0x70,
+    0xc0,  // Arrow right 8x8
+
+    0x80, 0x00,
+    0xe0, 0x00,
+    0x78, 0x00,
+    0x7e, 0x00,
+    0x3f, 0x80,
+    0x3f, 0xc0,
+    0x3f, 0x80,
+    0x7e, 0x00,
+    0x78, 0x00,
+    0xe0, 0x00,
+    0x80, 0x00,  // Arrow right 11x10
+
+    0x80, 0x00,
+    0xe0, 0x00,
+    0x78, 0x00,
+    0x7e, 0x00,
+    0x3f, 0x80,
+    0x3f, 0xe0,
+    0x1f, 0xf8,
+    0x3f, 0xe0,
+    0x3f, 0x80,
+    0x7e, 0x00,
+    0x78, 0x00,
+    0xe0, 0x00,
+    0x80, 0x00,  // Arrow right 13x13
+
+    0xc0, 0x00,
+    0x70, 0x00,
+    0x7c, 0x00,
+    0x3f, 0x00,
+    0x3f, 0xc0,
+    0x1f, 0xf0,
+    0x1f, 0xfc,
+    0x0f, 0xff,
+    0x1f, 0xfc,
+    0x1f, 0xf0,
+    0x3f, 0xc0,
+    0x3f, 0x00,
+    0x7c, 0x00,
+    0x70, 0x00,
+    0xc0, 0x00,  // Arrow right 16x15
+
+    0xc6,
+    0xc6,
+    0x7c,
+    0x7c,
+    0x38,
+    0x38,
+    0x10,  // Arrow up 7x7
+
+    0x81,
+    0xe7,
+    0x7e,
+    0x7e,
+    0x3c,
+    0x3c,
+    0x18,
+    0x18,  // Arrow up 8x8
+
+    0xc0, 0x60,
+    0x71, 0xc0,
+    0x7f, 0xc0,
+    0x3f, 0x80,
+    0x3f, 0x80,
+    0x1f, 0x00,
+    0x1f, 0x00,
+    0x0e, 0x00,
+    0x0e, 0x00,
+    0x04, 0x00,  // Arrow up 10x11
+
+    0xc0, 0x18,
+    0x70, 0x70,
+    0x7d, 0xf0,
+    0x3f, 0xe0,
+    0x3f, 0xe0,
+    0x1f, 0xc0,
+    0x1f, 0xc0,
+    0x1f, 0xc0,
+    0x0f, 0x80,
+    0x0f, 0x80,
+    0x07, 0x00,
+    0x07, 0x00,
+    0x02, 0x00,  // Arrow up 13x13
+
+    0x80, 0x02,
+    0xe0, 0x0e,
+    0x78, 0x3c,
+    0x7e, 0xfc,
+    0x3f, 0xf8,
+    0x3f, 0xf8,
+    0x1f, 0xf0,
+    0x1f, 0xf0,
+    0x0f, 0xe0,
+    0x0f, 0xe0,
+    0x07, 0xc0,
+    0x07, 0xc0,
+    0x03, 0x80,
+    0x03, 0x80,
+    0x01, 0x00,
+    0x01, 0x00,  // Arrow down 15x16
+
+    0x06,
+    0x1e,
+    0x78,
+    0xf8,
+    0x78,
+    0x1e,
+    0x06,  // Arrow left 7x7
+
+    0x03,
+    0x0e,
+    0x3e,
+    0xfc,
+    0xfc,
+    0x3e,
+    0x0e,
+    0x03,  // Arrow left 8x8
+
+    0x00, 0x40,
+    0x01, 0xc0,
+    0x07, 0x80,
+    0x1f, 0x80,
+    0x7f, 0x00,
+    0xff, 0x00,
+    0x7f, 0x00,
+    0x1f, 0x80,
+    0x07, 0x80,
+    0x01, 0xc0,
+    0x00, 0x40,  // Arrow left 11x10
+
+    0x00, 0x08,
+    0x00, 0x38,
+    0x00, 0xf0,
+    0x03, 0xf0,
+    0x0f, 0xe0,
+    0x3f, 0xe0,
+    0xff, 0xc0,
+    0x3f, 0xe0,
+    0x0f, 0xe0,
+    0x03, 0xf0,
+    0x00, 0xf0,
+    0x00, 0x38,
+    0x00, 0x08,  // Arrow left 13x13
+
+    0x00, 0x03,
+    0x00, 0x0e,
+    0x00, 0x3e,
+    0x00, 0xfc,
+    0x03, 0xfc,
+    0x0f, 0xf8,
+    0x3f, 0xf8,
+    0xff, 0xf0,
+    0x3f, 0xf8,
+    0x0f, 0xf8,
+    0x03, 0xfc,
+    0x00, 0xfc,
+    0x00, 0x3e,
+    0x00, 0x0e,
+    0x00, 0x03,  // Arrow left 16x15
+
+    0x10,
+    0x38,
+    0x38,
+    0x7c,
+    0x7c,
+    0xc6,
+    0xc6,  // Arrow down 7x7
+
+    0x18,
+    0x18,
+    0x3c,
+    0x3c,
+    0x7e,
+    0x7e,
+    0xe7,
+    0x81,  // Arrow down 8x8
+
+    0x04, 0x00,
+    0x0e, 0x00,
+    0x0e, 0x00,
+    0x1f, 0x00,
+    0x1f, 0x00,
+    0x3f, 0x80,
+    0x3f, 0x80,
+    0x7f, 0xc0,
+    0x71, 0xc0,
+    0xc0, 0x60,  // Arrow down 10x11
+
+    0x02, 0x00,
+    0x02, 0x00,
+    0x07, 0x00,
+    0x07, 0x00,
+    0x0f, 0x80,
+    0x0f, 0x80,
+    0x1f, 0xc0,
+    0x1f, 0xc0,
+    0x3f, 0xe0,
+    0x3f, 0xe0,
+    0x7d, 0xf0,
+    0x70, 0x70,
+    0xc0, 0x18,  // Arrow down 13x13
+
+    0x01, 0x00,
+    0x01, 0x00,
+    0x03, 0x80,
+    0x03, 0x80,
+    0x07, 0xc0,
+    0x07, 0xc0,
+    0x0f, 0xe0,
+    0x0f, 0xe0,
+    0x1f, 0xf0,
+    0x1f, 0xf0,
+    0x3f, 0xf8,
+    0x3f, 0xf8,
+    0x7e, 0xfc,
+    0x78, 0x3c,
+    0xe0, 0x0e,
+    0x80, 0x02,  // Arrow down 15x16
+
+    0x08,
+    0x08,
+    0x18,
+    0x1c,
+    0x7c,
+    0xfc,
+    0x1e,
+    0x02,  // Arrow up-right 7x8
+
+    0x0c,
+    0x0c,
+    0x0c,
+    0x1e,
+    0xfe,
+    0xfe,
+    0x1f,
+    0x03,  // Arrow up-right 8x8
+
+    0x02, 0x00,
+    0x03, 0x00,
+    0x03, 0x00,
+    0x07, 0x00,
+    0x07, 0x80,
+    0x1f, 0x80,
+    0xff, 0x80,
+    0x7f, 0xc0,
+    0x0f, 0xc0,
+    0x01, 0xc0,
+    0x00, 0x20,  // Arrow up-right 11x11
+
+    0x00, 0x40,
+    0x00, 0x40,
+    0x00, 0xc0,
+    0x00, 0xe0,
+    0x00, 0xe0,
+    0x01, 0xe0,
+    0x01, 0xf0,
+    0x07, 0xf0,
+    0x3f, 0xf0,
+    0xff, 0xf8,
+    0x1f, 0xf8,
+    0x03, 0xf8,
+    0x00, 0x7c,
+    0x00, 0x0c,  // Arrow up-right 14x14
+
+    0x00, 0x20,
+    0x00, 0x20,
+    0x00, 0x30,
+    0x00, 0x70,
+    0x00, 0x70,
+    0x00, 0x78,
+    0x00, 0xf8,
+    0x00, 0xf8,
+    0x03, 0xfc,
+    0x1f, 0xfc,
+    0xff, 0xfc,
+    0x3f, 0xfe,
+    0x0e, 0xfe,
+    0x00, 0xfe,
+    0x00, 0x1f,
+    0x00, 0x03,  // Arrow up-right 16x16
+
+    0x20,
+    0x30,
+    0x30,
+    0x7c,
+    0x7f,
+    0x78,
+    0xc0,  // Arrow up-left 8x7
+
+    0x30,
+    0x30,
+    0x30,
+    0x78,
+    0x7f,
+    0x7f,
+    0xf8,
+    0xc0,  // Arrow up-left 8x8
+
+    0x08, 0x00,
+    0x18, 0x00,
+    0x18, 0x00,
+    0x1c, 0x00,
+    0x3c, 0x00,
+    0x3f, 0x00,
+    0x3f, 0xe0,
+    0x7f, 0xc0,
+    0x7e, 0x00,
+    0x70, 0x00,
+    0x80, 0x00,  // Arrow up-left 11x11
+
+    0x08, 0x00,
+    0x08, 0x00,
+    0x0c, 0x00,
+    0x1c, 0x00,
+    0x1c, 0x00,
+    0x1e, 0x00,
+    0x3e, 0x00,
+    0x3f, 0x80,
+    0x3f, 0xf0,
+    0x7f, 0xfc,
+    0x7f, 0xe0,
+    0x7f, 0x00,
+    0xf8, 0x00,
+    0xc0, 0x00,  // Arrow up-left 14x14
+
+    0x04, 0x00,
+    0x04, 0x00,
+    0x0c, 0x00,
+    0x0e, 0x00,
+    0x0e, 0x00,
+    0x1e, 0x00,
+    0x1f, 0x00,
+    0x1f, 0x00,
+    0x3f, 0xc0,
+    0x3f, 0xf8,
+    0x3f, 0xff,
+    0x7f, 0xfc,
+    0x7f, 0xe0,
+    0x7f, 0x00,
+    0xf8, 0x00,
+    0xc0, 0x00,  // Arrow up-left 16x16
+
+    0x80,
+    0xf0,
+    0x7e,
+    0x7c,
+    0x70,
+    0x30,
+    0x20,
+    0x20,  // Arrow down-left 7x8
+
+    0xc0,
+    0xf8,
+    0x7f,
+    0x7f,
+    0x78,
+    0x30,
+    0x30,
+    0x30,  // Arrow down-left 8x8
+
+    0x80, 0x00,
+    0x70, 0x00,
+    0x7e, 0x00,
+    0x7f, 0xc0,
+    0x3f, 0xe0,
+    0x3f, 0x00,
+    0x3c, 0x00,
+    0x1c, 0x00,
+    0x18, 0x00,
+    0x18, 0x00,
+    0x08, 0x00,  // Arrow down-left 11x11
+
+    0xc0, 0x00,
+    0xf8, 0x00,
+    0x7f, 0x00,
+    0x7f, 0xe0,
+    0x7f, 0xfc,
+    0x3f, 0xf0,
+    0x3f, 0x80,
+    0x3e, 0x00,
+    0x1e, 0x00,
+    0x1c, 0x00,
+    0x1c, 0x00,
+    0x0c, 0x00,
+    0x08, 0x00,
+    0x08, 0x00,  // Arrow down-left 14x14
+
+    0xc0, 0x00,
+    0xf8, 0x00,
+    0x7f, 0x00,
+    0x7f, 0xe0,
+    0x7f, 0xfc,
+    0x3f, 0xff,
+    0x3f, 0xf8,
+    0x3f, 0xc0,
+    0x1f, 0x00,
+    0x1f, 0x00,
+    0x1e, 0x00,
+    0x0e, 0x00,
+    0x0e, 0x00,
+    0x0c, 0x00,
+    0x07, 0x00,
+    0x07, 0x00,  // Arrow down-left 16x16
+
+    0x03,
+    0x1e,
+    0xfe,
+    0x3e,
+    0x0c,
+    0x0c,
+    0x04,  // Arrow down-right 8x7
+
+    0x03,
+    0x1f,
+    0xfe,
+    0xfe,
+    0x1e,
+    0x0c,
+    0x0c,
+    0x0c,  // Arrow down-right 8x8
+
+    0x00, 0x20,
+    0x01, 0xc0,
+    0x0f, 0xc0,
+    0x7f, 0xc0,
+    0xff, 0x80,
+    0x1f, 0x80,
+    0x07, 0x80,
+    0x07, 0x00,
+    0x03, 0x00,
+    0x03, 0x00,
+    0x02, 0x00,  // Arrow down-right 11x11
+
+    0x00, 0x0c,
+    0x00, 0x7c,
+    0x03, 0xf8,
+    0x1f, 0xf8,
+    0xff, 0xf8,
+    0x3f, 0xf0,
+    0x07, 0xf0,
+    0x01, 0xf0,
+    0x01, 0xe0,
+    0x00, 0xe0,
+    0x00, 0xe0,
+    0x00, 0xc0,
+    0x00, 0x40,
+    0x00, 0x40,  // Arrow down-right 14x14
+
+    0x00, 0x03,
+    0x00, 0x1f,
+    0x00, 0xfe,
+    0x07, 0xfe,
+    0x3f, 0xfe,
+    0xff, 0xfc,
+    0x1f, 0xfc,
+    0x03, 0xfc,
+    0x00, 0xf8,
+    0x00, 0xf8,
+    0x00, 0x78,
+    0x00, 0x70,
+    0x00, 0x70,
+    0x00, 0x30,
+    0x00, 0x20,
+    0x00, 0x20,  // Arrow down-right 16x16
+
+    0xff, 0xff, 0x80,
+    0xff, 0xff, 0x80,
+    0xc0, 0x01, 0x80,
+    0xc0, 0x01, 0x80,
+    0xc0, 0x01, 0x80,
+    0xc0, 0x01, 0x80,
+    0xc0, 0x01, 0x80,
+    0xc0, 0x01, 0x80,
+    0xc0, 0x01, 0x80,
+    0xc0, 0x01, 0x80,
+    0xc0, 0x01, 0x80,
+    0xc0, 0x01, 0x80,
+    0xc0, 0x01, 0x80,
+    0xc0, 0x01, 0x80,
+    0xc0, 0x01, 0x80,
+    0xff, 0xff, 0x80,
+    0xff, 0xff, 0x80,  // Square 17x17
+
+    0x00,0x00,0x00,
+    0xff,0xff,0x80,
+    0xff,0xff,0x80,
+    0xc0,0x01,0x80,
+    0x60,0x03,0x00,
+    0x70,0x07,0x00,
+    0x38,0x0e,0x00,
+    0x18,0x0c,0x00,
+    0x1c,0x1c,0x00,
+    0x0c,0x18,0x00,
+    0x06,0x30,0x00,
+    0x07,0x70,0x00,
+    0x03,0x60,0x00,
+    0x01,0xc0,0x00,
+    0x01,0xc0,0x00,  // Triangle 17x15
+
+    0x01,0xf0,0x00,
+    0x07,0xfc,0x00,
+    0x1e,0x0f,0x00,
+    0x38,0x03,0x80,
+    0x30,0x01,0x80,
+    0x60,0x00,0xc0,
+    0x60,0x00,0xc0,
+    0xc0,0x00,0x60,
+    0xc0,0x00,0x60,
+    0xc0,0x00,0x60,
+    0xc0,0x00,0x60,
+    0xc0,0x00,0x60,
+    0x60,0x00,0xc0,
+    0x60,0x00,0xc0,
+    0x30,0x01,0x80,
+    0x38,0x03,0x80,
+    0x1e,0x0f,0x00,
+    0x07,0xfc,0x00,
+    0x01,0xf0,0x00,  // Circle bold 19x19
+
+    0xc0,0x01,0x80,
+    0x60,0x03,0x00,
+    0x30,0x06,0x00,
+    0x18,0x0c,0x00,
+    0x0c,0x18,0x00,
+    0x06,0x30,0x00,
+    0x03,0x60,0x00,
+    0x01,0xc0,0x00,
+    0x01,0xc0,0x00,
+    0x03,0x60,0x00,
+    0x06,0x30,0x00,
+    0x0c,0x18,0x00,
+    0x18,0x0c,0x00,
+    0x30,0x06,0x00,
+    0x60,0x03,0x00,
+    0xc0,0x01,0x80,
+    0x80,0x00,0x80,  // Cross bold 17x17
+
+    0x00, 0x40, 0x00,
+    0x00, 0xe0, 0x00,
+    0x01, 0xb0, 0x00,
+    0x03, 0x18, 0x00,
+    0x06, 0x0c, 0x00,
+    0x0c, 0x06, 0x00,
+    0x18, 0x03, 0x00,
+    0x30, 0x01, 0x80,
+    0x60, 0x00, 0xc0,
+    0xc0, 0x00, 0x60,
+    0x60, 0x00, 0xc0,
+    0x30, 0x01, 0x80,
+    0x18, 0x03, 0x00,
+    0x0c, 0x06, 0x00,
+    0x06, 0x0c, 0x00,
+    0x03, 0x18, 0x00,
+    0x01, 0xb0, 0x00,
+    0x00, 0xe0, 0x00,
+    0x00, 0x40, 0x00,  // Romb 19x19
+
+    0x01,0xf0,0x00,
+    0x07,0xfc,0x00,
+    0x1e,0x4f,0x00,
+    0x38,0x43,0x80,
+    0x30,0x41,0x80,
+    0x60,0x40,0xc0,
+    0x60,0x40,0xc0,
+    0xc0,0x40,0x60,
+    0xc0,0x40,0x60,
+    0xff,0xff,0xe0,
+    0xc0,0x40,0x60,
+    0xc0,0x40,0x60,
+    0x60,0x40,0xc0,
+    0x60,0x40,0xc0,
+    0x30,0x41,0x80,
+    0x38,0x43,0x80,
+    0x1e,0x4f,0x00,
+    0x07,0xfc,0x00,
+    0x01,0xf0,0x00,  // Cross circle 19x19
+
+    0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x38, 0x00,
+    0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00  //Line 3x19
+};
+
+//=======================================================================
+//function : GenBitmap
+//purpose  : 
+//=======================================================================
+static void GenBitmap(const unsigned char*   theOldBitmap,
+                      unsigned char*         theNewBitmap,
+                      const Standard_Integer theWidth,
+                      const Standard_Integer theHeight,
+                      const gp_Pnt2d&        theCenter,
+                      const Standard_Real    theAngle)
+{
+    Standard_Integer aWidthBitmap = (Standard_Integer)Ceiling(theWidth / 8.0);
+    Standard_Integer aHeightBitmap = theHeight;
+    memset (theNewBitmap, 0, aWidthBitmap * aHeightBitmap);
+    // Compute rotate transformation
+    gp_Trsf2d aTrsf;
+    aTrsf.SetRotation(theCenter, theAngle);
+    for (Standard_Integer anIterY = 0; anIterY < aHeightBitmap; anIterY++)
+    {
+        for (Standard_Integer anIterX = 0; anIterX < aWidthBitmap; anIterX++)
+        {
+            unsigned char aByte = theOldBitmap[anIterY * aWidthBitmap + anIterX];
+            for (Standard_Integer anIterBit = 0; anIterBit < 8; anIterBit++)
+            {
+                if (aByte & (1<<anIterBit))
+                {
+                    // Rotate each bit in bitmap
+                    gp_Pnt2d aPos(anIterX * 8 + (7 - anIterBit), anIterY);
+                    aPos.Transform(aTrsf.Inverted());
+                    // Round the computed position to integer
+                    aPos.SetXY(gp_XY(Round(aPos.X()), Round(aPos.Y())));
+
+                    unsigned char aNewByte = theNewBitmap[(Standard_Integer)aPos.Y() * aWidthBitmap +
+                                                          (Standard_Integer)aPos.X() / 8];
+                    aNewByte |= 1<<(7 - (Standard_Integer)aPos.X() % 8);
+                    theNewBitmap[(Standard_Integer)aPos.Y() * aWidthBitmap +
+                                 (Standard_Integer)aPos.X() / 8] = aNewByte;
+                }
+            }
+        }
+    }
+}
+
+
+//=======================================================================
+
+
+IMPLEMENT_STANDARD_HANDLE  (NIS_PointDrawer, NIS_Drawer)
+IMPLEMENT_STANDARD_RTTIEXT (NIS_PointDrawer, NIS_Drawer)
+
+//=======================================================================
+//function : NIS_PointDrawer
+//purpose  : Constructor
+//=======================================================================
+
+NIS_PointDrawer::NIS_PointDrawer(const Quantity_Color& theColor)
+  : myPointSize(5.f),
+    myType(0),
+    myInvertColor(Standard_False),
+    myIsWhite(Standard_False),
+    myAngle(0.0),
+    myIsUpdateAngle(Standard_False),
+    myRotatedRaster(NULL)
+{
+    SetColor(Draw_Normal, theColor);
+    SetColor(Draw_Hilighted, Quantity_NOC_GRAY80);
+    SetColor(Draw_DynHilighted, Quantity_NOC_CYAN1);
+}
+
+//=======================================================================
+//function : ~NIS_PointDrawer
+//purpose  : Destructor
+//=======================================================================
+
+NIS_PointDrawer::~NIS_PointDrawer()
+{
+    if (myRotatedRaster)
+    {
+        delete [] myRotatedRaster;
+        myRotatedRaster = NULL;
+    }
+}
+
+//=======================================================================
+//function : Assign
+//purpose  :
+//=======================================================================
+
+void NIS_PointDrawer::Assign (const Handle_NIS_Drawer& theOther)
+{
+    if (theOther.IsNull() == Standard_False)
+    {
+        NIS_Drawer::Assign(theOther);
+        const Handle(NIS_PointDrawer)& anOther =
+            static_cast <const Handle(NIS_PointDrawer)&> (theOther);
+        myPointSize = anOther->myPointSize;
+        myType = anOther->myType;
+        myInvertColor = anOther->myInvertColor;
+        myIsWhite = anOther->myIsWhite;
+        myAngle = anOther->myAngle;
+        myIsUpdateAngle = anOther->myIsUpdateAngle;
+    }
+}
+
+//=======================================================================
+//function : IsEqual
+//purpose  : Comparison of two Drawers (for Map impementation)
+//=======================================================================
+
+Standard_Boolean NIS_PointDrawer::IsEqual
+                                (const Handle_NIS_Drawer& theOther) const
+{
+    static const Standard_Real anEpsilon2 (1e-7);
+    Standard_Boolean aResult (Standard_False);
+    const Handle(NIS_PointDrawer) anOther =
+        Handle(NIS_PointDrawer)::DownCast(theOther);
+    if (NIS_Drawer::IsEqual(theOther))
+    {
+        aResult = ((anOther->myPointSize - myPointSize) *
+                   (anOther->myPointSize - myPointSize) < 0.01 &&
+                   anOther->myType == myType &&
+                   anOther->myInvertColor == myInvertColor &&
+                   anOther->myIsWhite == myIsWhite &&
+                   anOther->myAngle == myAngle &&
+                   anOther->myIsUpdateAngle == myIsUpdateAngle);
+    }
+    return aResult;
+}
+
+//=======================================================================
+//function : BeforeDraw
+//purpose  :
+//=======================================================================
+
+void NIS_PointDrawer::BeforeDraw (const DrawType         theType,
+                                  const NIS_DrawList&    /*theDrawList*/)
+{
+    Quantity_Parameter   aValue[4];
+    aValue[3] = 1.;                               // opaque as default
+    Quantity_TypeOfColor bidTC (Quantity_TOC_RGB);
+    GLfloat aPointSize (myPointSize);
+
+    if (theType == Draw_DynHilighted)
+    {
+        aPointSize = myPointSize + 2.f;
+    }
+
+    if (myInvertColor)
+    {
+        glEnable(GL_COLOR_LOGIC_OP);
+        glLogicOp(GL_XOR);
+    }
+    else if (theType == Draw_Transparent)
+    {
+        aValue[3] = 1. - myTransparency;
+        glEnable(GL_BLEND);
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    }
+
+    GetColor(theType).Values(aValue[0], aValue[1], aValue[2], bidTC);
+
+    // It's necessary for snap marker visualization to identify 
+    // whether the input color is white, because XOR mode for white 
+    // color is processed differently.
+    // Note that white color is represented as (1., 1., 1.)
+    if ( Abs(aValue[0] - 1.) <= Precision::Confusion() &&
+         Abs(aValue[1] - 1.) <= Precision::Confusion() &&
+         Abs(aValue[2] - 1.) <= Precision::Confusion())
+    {
+        myIsWhite = Standard_True;
+    }
+
+    glColor4d (aValue[0], aValue[1], aValue[2], aValue[3]);
+    //glEnableClientState (GL_VERTEX_ARRAY);
+    glDisable(GL_LIGHTING);
+
+    if (myType > 0 && myType <= NUM_TYPES)
+    {
+        mySizeIndex = 0;
+        for (int j = 0; j < NUM_SIZES; j++, mySizeIndex++)
+        {
+            if (aPointSize <= data[myType-1][j].height)
+            {
+                break;
+            }
+        }
+        if (mySizeIndex >= NUM_SIZES)
+        {
+            mySizeIndex = NUM_SIZES - 1;
+        }
+    }
+    else
+    {
+        glPointSize(aPointSize);
+    }
+}
+
+//=======================================================================
+//function : AfterDraw
+//purpose  :
+//=======================================================================
+
+void NIS_PointDrawer::AfterDraw (const DrawType         theType,
+                                 const NIS_DrawList&    /*theDrawList*/)
+{
+    if (myInvertColor)
+    {
+        glDisable(GL_COLOR_LOGIC_OP);
+    }
+    else if (theType == Draw_Transparent)
+    {
+        glDisable(GL_BLEND);
+    }
+    //glDisableClientState(GL_VERTEX_ARRAY);
+}
+
+//=======================================================================
+//function : Draw
+//purpose  :
+//=======================================================================
+
+void NIS_PointDrawer::Draw (const Handle_NIS_InteractiveObject& theObj,
+                            const DrawType                      /*theType*/,
+                            const NIS_DrawList&                 /*theDrawList*/)
+{
+    // Assertion for the type of the drawn object
+#ifdef _DEBUG
+    static const Handle(Standard_Type) ThisType =
+        STANDARD_TYPE(NIS_Point);
+    if (theObj->IsKind(ThisType) == Standard_False)
+    {
+        Standard_ProgramError::Raise("NIS_PointDrawer::Draw: "
+                                     "irrelevant object type");
+    }
+#endif
+    const NIS_Point* pObject = 
+        static_cast <const NIS_Point*> (theObj.operator->());
+
+    const Standard_ShortReal* aCoords = &pObject->myCoords[0];
+
+    // Draw single point (using bitmap)
+    if (myType > 0 && myType <= NUM_TYPES)
+    {
+        if (myIsWhite == Standard_False)
+        {
+            // Simple blending
+            glDisable (GL_LIGHTING);
+            glEnable (GL_BLEND);
+            glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
+
+            DrawPoint ( aCoords );
+
+            glDisable (GL_BLEND);
+            glEnable (GL_LIGHTING);
+        }
+        else
+        {
+            // White color invertion should be processed differntly
+
+            // Invert color
+            glEnable(GL_COLOR_LOGIC_OP);
+            glLogicOp(GL_INVERT);
+            // Draw point
+            DrawPoint ( aCoords );
+
+            glDisable(GL_COLOR_LOGIC_OP);
+
+            // Discret color
+            glColor3ub (224, 224, 224);
+            glEnable(GL_COLOR_LOGIC_OP);
+            glLogicOp(GL_AND);
+
+            // Draw point
+            DrawPoint ( aCoords );
+
+            glDisable(GL_COLOR_LOGIC_OP);
+
+            // Scale up
+            glEnable(GL_BLEND);
+            glColor3f(1.f, 1.f, 1.f);
+            glBlendFunc(GL_DST_COLOR, GL_ONE);
+
+            // Draw point
+            DrawPoint ( aCoords );
+
+            // Scale up again
+            // Draw point
+            DrawPoint ( aCoords );
+
+            // Draw point
+            DrawPoint ( aCoords );
+            glDisable(GL_BLEND);
+        }
+    }
+    else
+    {
+        glBegin(GL_POINTS);
+        glVertex3fv(aCoords);
+        glEnd();
+    }
+}
+
+//=======================================================================
+//function : DrawPoint
+//purpose  :
+//=======================================================================
+
+void NIS_PointDrawer::DrawPoint (const Standard_ShortReal* thePosition)
+{
+    glRasterPos3f((GLfloat)(thePosition[0]),
+                  (GLfloat)(thePosition[1]),
+                  (GLfloat)(thePosition[2]) );
+    int aWidth = data[myType-1][mySizeIndex].width;
+    int aHeight = data[myType-1][mySizeIndex].height;
+    const Standard_Size aNBytes = sizeof(unsigned char) *
+                                 (Standard_Integer)Ceiling(aWidth / 8.0) * aHeight;
+
+    if (std::abs(myAngle) < Precision::Confusion())
+    {
+        myRotatedRaster = new unsigned char[aNBytes];
+        memcpy(myRotatedRaster, &raster[data[myType-1][mySizeIndex].offset], aNBytes);
+    }
+    else if (myIsUpdateAngle)
+    {
+        if (myRotatedRaster != NULL)
+        {
+            delete[] myRotatedRaster;
+            myRotatedRaster = NULL;
+        }
+        // To generate the new rotated bitmap, the old bitmap should be square.
+        myRotatedRaster = new unsigned char[aNBytes];
+        GenBitmap((const GLubyte*) &raster[data[myType-1][mySizeIndex].offset],
+                  myRotatedRaster, aWidth, aHeight, gp_Pnt2d(aWidth/2, aHeight/2), myAngle);
+    }
+    myIsUpdateAngle = Standard_False;
+    glBitmap((GLsizei)aWidth, (GLsizei)aHeight,
+             (GLfloat)aWidth/2, (GLfloat)aHeight/2, 0., 0.,
+             (const GLubyte*) myRotatedRaster);
+}
diff --git a/src/NIS/NIS_PointDrawer.hxx b/src/NIS/NIS_PointDrawer.hxx
new file mode 100644 (file)
index 0000000..3f7fbea
--- /dev/null
@@ -0,0 +1,98 @@
+// File:      NIS_PointDrawer.h
+// Created:   11.05.12
+// Author:    Natalia Kopnova
+// Copyright: LPKF Laser and Electronics AG 2012
+
+#ifndef NIS_PointDrawer_HeaderFile
+#define NIS_PointDrawer_HeaderFile
+
+#include <NIS_Drawer.hxx>
+
+class NIS_Point;
+
+/**
+ * NIS drawer for AISObject_Point interactive object type.
+ * @ingroup aisobject
+ */
+
+class NIS_PointDrawer : public NIS_Drawer
+{
+ public:
+  // ---------- PUBLIC METHODS ----------
+
+  /**
+   * Constructor.
+   */
+  Standard_EXPORT NIS_PointDrawer (const Quantity_Color& theColor);
+
+  /**
+   * Destructor.
+   */
+  Standard_EXPORT virtual ~NIS_PointDrawer ();
+
+  /**
+   * Copy the relevant information from another instance of Drawer.
+   * raises exception if theOther has incompatible type (test IsKind).
+   */
+  Standard_EXPORT virtual void Assign    (const Handle_NIS_Drawer& theOther);
+
+  /**
+   * Called before execution of Draw(), once per group of interactive objects.
+   */
+  Standard_EXPORT virtual void BeforeDraw(const DrawType         theType,
+                                          const NIS_DrawList&    theDrawList);
+
+  /**
+   * Called after execution of Draw(), once per group of interactive objects.
+   */
+  Standard_EXPORT virtual void AfterDraw(const DrawType         theType,
+                                         const NIS_DrawList&    theDrawList);
+
+  /**
+   * Main function: display the given interactive object in the given view.
+   */
+  Standard_EXPORT virtual void Draw      (const Handle_NIS_InteractiveObject&,
+                                          const DrawType         theType,
+                                          const NIS_DrawList&    theDrawList);
+
+  /**
+   * Matching two instances, for Map interface.
+   */
+  Standard_EXPORT virtual Standard_Boolean
+                               IsEqual   (const Handle_NIS_Drawer& theOth)const;
+
+
+ protected:
+  // ---------- PROTECTED METHODS ----------
+
+  /**
+   * Draw single point represented as texture at input position 
+   */
+  Standard_EXPORT virtual void DrawPoint (const Standard_ShortReal* thePosition);
+
+
+ private:
+  // ---------- PRIVATE FIELDS ----------
+
+  Standard_ShortReal  myPointSize;
+  Standard_Integer    myType;
+  Standard_Integer    mySizeIndex;
+  Standard_Boolean    myInvertColor;
+  Standard_Boolean    myIsWhite;
+  Standard_Boolean    myIsUpdateAngle;
+  Standard_Real       myAngle;
+  unsigned char*      myRotatedRaster;
+
+
+ public:
+// Declaration of CASCADE RTTI
+DEFINE_STANDARD_RTTI (NIS_PointDrawer)
+
+  friend class NIS_Point;
+};
+
+// Definition of HANDLE object using Standard_DefineHandle.hxx
+DEFINE_STANDARD_HANDLE (NIS_PointDrawer, NIS_Drawer)
+
+
+#endif
diff --git a/src/NIS/NIS_PolygonSelector.cxx b/src/NIS/NIS_PolygonSelector.cxx
new file mode 100644 (file)
index 0000000..cf3012b
--- /dev/null
@@ -0,0 +1,407 @@
+// File:      NIS_PolygonSelector.cxx
+// Created:   26.10.11 21:26
+// Author:    Alexander GRIGORIEV
+// Copyright: Open Cascade 2011
+
+#include <NIS_PolygonSelector.hxx>
+#include <NIS_InteractiveContext.hxx>
+#include <NIS_View.hxx>
+#ifdef WIN32
+#include <windows.h>
+#endif
+#include <GL/gl.h>
+
+/**
+ * Drawer class for PolygonSelector.
+ */
+class NIS_PolygonSelectorDrawer : public NIS_Drawer
+{
+public:
+
+    /**
+     * Display the given interactive object in the given view.
+     */
+    virtual void Draw     (const Handle_NIS_InteractiveObject&,
+                           const DrawType         theType,
+                           const NIS_DrawList&    theDrawList);
+
+public:
+    // Declaration of CASCADE RTTI
+    DEFINE_STANDARD_RTTI (NIS_PolygonSelectorDrawer)
+};
+
+// Definition of HANDLE object using Standard_DefineHandle.hxx
+DEFINE_STANDARD_HANDLE (NIS_PolygonSelectorDrawer, NIS_Drawer)
+
+IMPLEMENT_STANDARD_HANDLE  (NIS_PolygonSelector, NIS_InteractiveObject)
+IMPLEMENT_STANDARD_RTTIEXT (NIS_PolygonSelector, NIS_InteractiveObject)
+IMPLEMENT_STANDARD_HANDLE  (NIS_PolygonSelectorDrawer, NIS_Drawer)
+IMPLEMENT_STANDARD_RTTIEXT (NIS_PolygonSelectorDrawer, NIS_Drawer)
+
+//=======================================================================
+//function : ~NIS_PolygonSelector
+//purpose  : Destructor
+//=======================================================================
+
+NIS_PolygonSelector::~NIS_PolygonSelector ()
+{
+}
+
+//=======================================================================
+//function : DefaultDrawer
+//purpose  : 
+//=======================================================================
+
+NIS_Drawer * NIS_PolygonSelector::DefaultDrawer(NIS_Drawer * theDrawer) const
+{
+  NIS_PolygonSelectorDrawer * aDrawer = 
+    theDrawer ? static_cast<NIS_PolygonSelectorDrawer *>(theDrawer)
+    : new NIS_PolygonSelectorDrawer();
+  aDrawer->SetCompiled(Standard_False);
+
+  return aDrawer;
+}
+
+//=======================================================================
+//function : Clone
+//purpose  : 
+//=======================================================================
+
+void NIS_PolygonSelector::Clone
+                        (const Handle_NCollection_BaseAllocator& theAlloc,
+                         Handle_NIS_InteractiveObject&           theDest) const
+{
+  Handle(NIS_PolygonSelector) aNewObj;
+  if (theDest.IsNull())
+  {
+    aNewObj = new NIS_PolygonSelector(myIsRectangle);
+    theDest = aNewObj;
+  }
+  else
+  {
+    aNewObj = reinterpret_cast<NIS_PolygonSelector*> (theDest.operator->());
+  }
+  NIS_InteractiveObject::Clone(theAlloc, theDest);
+  aNewObj->myView = myView;
+  aNewObj->myIsRectangle = myIsRectangle;
+  aNewObj->myIsLoop = myIsLoop;
+  if (myPoints.Extent() > 0)
+  {
+    aNewObj->myPoints = myPoints;
+    aNewObj->myVertexes =
+      new NCollection_Array1<Standard_ShortReal>(*myVertexes.operator->());
+  }
+}
+
+//=======================================================================
+//function : Intersect
+//purpose  : Not used
+//=======================================================================
+
+Standard_Real NIS_PolygonSelector::Intersect (const gp_Ax1&,
+                                             const Standard_Real) const
+{
+  return RealLast();
+}
+
+//=======================================================================
+//function : computeBox
+//purpose  : Not used
+//=======================================================================
+
+void NIS_PolygonSelector::computeBox ()
+{
+}
+
+//=======================================================================
+//function : AddPoint
+//purpose  : Add a point to polygon
+//=======================================================================
+
+void NIS_PolygonSelector::AddPoint (const Standard_Integer theX,
+                                    const Standard_Integer theY)
+{
+  // add the point to the list
+  gp_XYZ aPnt = convertPoint( theX, theY );
+  myPoints.Prepend( aPnt );
+
+  updateVertexes();
+}
+
+//=======================================================================
+//function : MovePoint
+//purpose  : Change the location of the last added point.
+//=======================================================================
+
+void NIS_PolygonSelector::MovePoint (const Standard_Integer theX,
+                                     const Standard_Integer theY)
+{
+  if (myPoints.IsEmpty())
+    AddPoint( theX, theY );
+  else if (myIsRectangle && myPoints.Extent() == 1)
+    AddPoint( theX, theY );
+  else {
+    gp_XYZ aMovedPnt = convertPoint( theX, theY );
+
+    gp_XYZ& aPnt = const_cast<gp_XYZ&>( myPoints.First() );
+    aPnt.SetX( aMovedPnt.X() );
+    aPnt.SetY( aMovedPnt.Y() );
+    aPnt.SetZ( aMovedPnt.Z() );
+
+    updateVertexes();
+  }
+}
+
+//=======================================================================
+//function : RemovePoint
+//purpose  : Remove the last added point
+//=======================================================================
+
+void NIS_PolygonSelector::RemovePoint ()
+{
+  if (NPoints() > 0)
+  {
+    myPoints.RemoveFirst();
+    updateVertexes();
+  }
+}
+
+//=======================================================================
+//function : Draw
+//purpose  : 
+//=======================================================================
+
+void NIS_PolygonSelectorDrawer::Draw(const Handle_NIS_InteractiveObject& theObj,
+                                     const DrawType         theType,
+                                     const NIS_DrawList&    theDrawList)
+{
+  if (theObj.IsNull() == Standard_False &&
+      theObj->IsKind(STANDARD_TYPE(NIS_PolygonSelector)))
+  {
+    const NIS_PolygonSelector * pObj =
+      static_cast<const NIS_PolygonSelector *>(theObj.operator->());
+    Standard_Integer nPnts = pObj->NPoints();
+    if (pObj->myView.IsNull() == Standard_False &&
+        theDrawList.GetView().IsNull() == Standard_False)
+    {
+      if (pObj->myView != theDrawList.GetView())
+        nPnts = 0;
+    }
+    if (nPnts > 0)
+    {
+      GLenum aMode;
+      glEnableClientState(GL_VERTEX_ARRAY);
+      const Standard_ShortReal* aVertexes =
+        &pObj->myVertexes->Value( pObj->myVertexes->Lower() );
+      glVertexPointer(3, GL_FLOAT, 0, aVertexes );
+      if (nPnts == 1)
+      {
+        glEnable(GL_POINT_SMOOTH);
+        glPointSize(3.f);
+        aMode = GL_POINTS;
+      }
+      else
+      {
+        glDisable(GL_LINE_SMOOTH);
+        //         glEnable(GL_LINE_STIPPLE);
+        //         glLineStipple(1, 0x3333);
+        glLineWidth(0.5f);
+        if (nPnts == 2)
+        {
+          aMode = GL_LINES;
+        }
+        else if (!pObj->myIsRectangle && !pObj->myIsLoop)
+        {
+          aMode = GL_LINE_STRIP;
+        }
+        else
+        {
+          aMode = GL_LINE_LOOP;
+        }
+      }
+      glDisable (GL_LIGHTING);
+      Quantity_Parameter R1, R2, R3;
+      GetColor(theType).Values(R1, R2, R3, Quantity_TOC_RGB);
+      glColor3d (R1, R2, R3);
+      glEnable(GL_BLEND);
+      glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
+      glDrawArrays(aMode, 0, nPnts);
+      glDisable(GL_BLEND);
+      //       glDisable(GL_LINE_STIPPLE);
+      glDisableClientState(GL_VERTEX_ARRAY);
+      glEnable (GL_LIGHTING);
+    }
+  }
+}
+
+//=======================================================================
+//function : convertPoint
+//purpose  : 
+//=======================================================================
+
+gp_XYZ NIS_PolygonSelector::convertPoint ( Standard_Integer theX,
+                                           Standard_Integer theY )
+{
+  Standard_Real aPickPnt[3];
+  const Handle(NIS_View) aView = getView();
+  if (aView.IsNull() == Standard_False)
+  {
+    aView->Convert (static_cast<Standard_Integer>(theX),
+                    static_cast<Standard_Integer>(theY),
+                    aPickPnt[0], aPickPnt[1], aPickPnt[2]);
+  }
+  return gp_XYZ( aPickPnt[0], aPickPnt[1], aPickPnt[2] );
+}
+
+//=======================================================================
+//function : getView
+//purpose  : 
+//=======================================================================
+
+const Handle_NIS_View& NIS_PolygonSelector::getView () const
+{
+  const Handle(NIS_Drawer)& aDrawer = GetDrawer();
+  if (aDrawer.IsNull() == Standard_False) {
+    const NIS_InteractiveContext * aCtx = aDrawer->GetContext();
+    if (aCtx != NULL) {
+      NCollection_List<Handle_NIS_View>::Iterator aViews = aCtx->GetViews();
+      if (aViews.More())
+        return aViews.Value();
+    }
+  }
+  static const Handle(NIS_View) aNull;
+  return aNull;
+}
+
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+
+void NIS_PolygonSelector::Perform (const Standard_Boolean isModifierUsed,
+                                   const Standard_Boolean isFullyIncluded,
+                                   const Standard_Boolean isRedraw) const
+{
+  // Find the View
+  Handle(NIS_View) aView = myView;
+  if (myView.IsNull() && GetDrawer().IsNull() == Standard_False)
+  {
+    const NIS_InteractiveContext * aCtx = GetDrawer()->GetContext();
+    if (aCtx != 0L)
+    {
+      NCollection_List<Handle_NIS_View>::Iterator anIterV = aCtx->GetViews();
+      if (anIterV.More())
+        aView = anIterV.Value();
+    }
+  }
+  if (aView.IsNull() == Standard_False)
+  {
+    NCollection_List<gp_XY> aSelectionPnts = GetPolygon();
+    if (myIsRectangle == Standard_False)
+    {
+      // Polygon selection
+      aView->Select( aSelectionPnts, isModifierUsed, isFullyIncluded, isRedraw );
+    }
+    else
+    {
+      // Rectangle selection
+      Standard_Integer aV[4] = { 
+        static_cast<Standard_Integer>( aSelectionPnts.First().X() + 0.1 ),
+        static_cast<Standard_Integer>( aSelectionPnts.First().Y() + 0.1 ),
+        static_cast<Standard_Integer>( aSelectionPnts.Last().X() + 0.1 ),
+        static_cast<Standard_Integer>( aSelectionPnts.Last().Y() + 0.1 )
+      };
+      if (aV[0] > aV[2]) {
+        const Standard_Integer aTmp = aV[0];
+        aV[0] = aV[2];
+        aV[2] = aTmp;
+      }
+      if (aV[1] > aV[3]) {
+        const Standard_Integer aTmp = aV[1];
+        aV[1] = aV[3];
+        aV[3] = aTmp;
+      }
+      aView->Select(aV[0], aV[1], aV[2], aV[3], isModifierUsed, isFullyIncluded, isRedraw);
+    }
+  }
+}
+
+//=======================================================================
+//function : GetPolygon
+//purpose  : 
+//=======================================================================
+
+NCollection_List<gp_XY> NIS_PolygonSelector::GetPolygon() const
+{
+  NCollection_List<gp_XY> aScreenCoords;
+  const Handle_NIS_View& aView = getView();
+  if (aView.IsNull() == Standard_False)
+  {
+    NCollection_List<gp_XYZ>::Iterator anIt(myPoints);
+    Standard_Integer aScreenX, aScreenY;
+    for (; anIt.More(); anIt.Next())
+    {
+      gp_XYZ aViewPnt = anIt.Value();
+      aView->Convert(aViewPnt.X(), aViewPnt.Y(), aViewPnt.Z(),
+                     aScreenX, aScreenY);
+      aScreenCoords.Append( gp_XY(aScreenX, aScreenY));
+    }
+  }
+  return aScreenCoords;
+}
+
+//=======================================================================
+//function : updateVertexes
+//purpose  : 
+//=======================================================================
+
+void NIS_PolygonSelector::updateVertexes()
+{
+  myVertexes = new NCollection_Array1<Standard_ShortReal>(0, NPoints() * 3);
+
+  if (myIsRectangle)
+  {
+    gp_XYZ aPnt1 = myPoints.Last();
+    gp_XYZ aPnt2 = myPoints.First();
+
+    Quantity_Parameter anUpX, anUpY, anUpZ;
+    Handle(NIS_View) aView = getView();
+    aView->Up( anUpX, anUpY, anUpZ );        
+    gp_XYZ anUp( anUpX, anUpY, anUpZ );
+
+    gp_XYZ aPnt3 = aPnt1 - anUp * (anUp * (aPnt1 - aPnt2));
+    gp_XYZ aPnt4 = aPnt2 + anUp * (anUp * (aPnt1 - aPnt2));
+
+    myVertexes->ChangeValue(0) = static_cast<Standard_ShortReal>(aPnt1.X());
+    myVertexes->ChangeValue(1) = static_cast<Standard_ShortReal>(aPnt1.Y());
+    myVertexes->ChangeValue(2) = static_cast<Standard_ShortReal>(aPnt1.Z());
+
+    myVertexes->ChangeValue(3) = static_cast<Standard_ShortReal>(aPnt3.X());
+    myVertexes->ChangeValue(4) = static_cast<Standard_ShortReal>(aPnt3.Y());
+    myVertexes->ChangeValue(5) = static_cast<Standard_ShortReal>(aPnt3.Z()); 
+
+    myVertexes->ChangeValue(6) = static_cast<Standard_ShortReal>(aPnt2.X());
+    myVertexes->ChangeValue(7) = static_cast<Standard_ShortReal>(aPnt2.Y());
+    myVertexes->ChangeValue(8) = static_cast<Standard_ShortReal>(aPnt2.Z()); 
+
+    myVertexes->ChangeValue(9) = static_cast<Standard_ShortReal>(aPnt4.X());
+    myVertexes->ChangeValue(10) = static_cast<Standard_ShortReal>(aPnt4.Y());
+    myVertexes->ChangeValue(11) = static_cast<Standard_ShortReal>(aPnt4.Z());
+  }
+  else
+  {
+    Standard_Integer i = 0;
+    NCollection_List<gp_XYZ>::Iterator anIter( myPoints );
+    for (; anIter.More(); anIter.Next())
+    {
+      myVertexes->ChangeValue(i++) =
+        static_cast<Standard_ShortReal>( anIter.Value().X() );
+      myVertexes->ChangeValue(i++) =
+        static_cast<Standard_ShortReal>( anIter.Value().Y() );
+      myVertexes->ChangeValue(i++) =
+        static_cast<Standard_ShortReal>( anIter.Value().Z() );
+    }
+  }
+
+  setDrawerUpdate();
+}
diff --git a/src/NIS/NIS_PolygonSelector.hxx b/src/NIS/NIS_PolygonSelector.hxx
new file mode 100644 (file)
index 0000000..c3c68e8
--- /dev/null
@@ -0,0 +1,141 @@
+// File:      NIS_PolygonSelector.hxx
+// Created:   26.10.11 21:17
+// Author:    Alexander GRIGORIEV
+// Copyright: Open Cascade 2011
+
+
+#ifndef NIS_PolygonSelector_HeaderFile
+#define NIS_PolygonSelector_HeaderFile
+
+#include <NIS_InteractiveObject.hxx>
+#include <NCollection_List.hxx>
+#include <NCollection_Array1.hxx>
+#include <NCollection_Handle.hxx>
+
+class NIS_PolygonSelectorDrawer;
+
+typedef NCollection_Array1<Standard_ShortReal> ShortRealArray;
+typedef NCollection_Handle<ShortRealArray> Handle(ShortRealArray);
+
+/**
+ * Data structure and presentation of a polygon or rectangle shown above all
+ * other objects in 3D viewer. Can be used for interactive seclection.
+ * @ingroup nis_library
+ */
+
+class NIS_PolygonSelector : public NIS_InteractiveObject
+{
+ public:
+  // ---------- PUBLIC METHODS ----------
+
+  /**
+   * Constructor.
+   * @param isRectangle
+   *   If True then a rectangle is drawn by 2 points, if False - a polygon on
+   *   a set of points.
+   * @param isLoop
+   *   This parameter makes sence only for polygon mode.
+   *   If 'false' the line between the first and the last points is nopt displayed.
+   *   otherwise these points are connected.
+   * @param theView
+   *   If defined then the polygon/rectangle will be shown only in tthis view.
+   *   If undefined then all views will contain the presentation.
+   */
+  inline NIS_PolygonSelector (const Standard_Boolean isRectangle,
+                              const Standard_Boolean isLoop = 1,
+                              const Handle_NIS_View& theView = 0L)
+  : myView        (theView),
+    myIsRectangle (isRectangle),
+    myIsLoop      (isLoop) {}
+
+  /**
+   * Query the number of polygon vertices.
+   */ 
+  inline Standard_Integer NPoints       () const
+  { return myIsRectangle ? 4 : myPoints.Extent(); }
+
+  /**
+   * Query the drawing mode.
+   */
+  inline Standard_Boolean IsRectangle   () const
+  { return myIsRectangle; }
+
+  Standard_EXPORT ~NIS_PolygonSelector ();
+
+  Standard_EXPORT virtual NIS_Drawer *
+                          DefaultDrawer (NIS_Drawer * theDrv) const;
+
+  /**
+   * Create a copy of theObject except its ID.
+   */
+  Standard_EXPORT virtual void
+                          Clone (const Handle_NCollection_BaseAllocator& theAll,
+                                 Handle_NIS_InteractiveObject& theDest) const;
+
+  Standard_EXPORT virtual Standard_Real
+                          Intersect     (const gp_Ax1&       theAxis,
+                                         const Standard_Real theOver)const;
+  Standard_EXPORT virtual void
+                          computeBox    ();
+
+  /**
+   * Add a point to polygon.
+   */
+  Standard_EXPORT void    AddPoint      (const Standard_Integer theX,
+                                         const Standard_Integer theY);
+
+  /**
+   * Change the location of the last added point.
+   */
+  Standard_EXPORT void    MovePoint     (const Standard_Integer theX,
+                                         const Standard_Integer theY);
+  /**
+   * Remove the last added point.
+   */
+  Standard_EXPORT void    RemovePoint   ();
+
+  /**
+   * Perform the selection in the current view (myView). If myView.IsNull() then
+   * the selection is performed in the first view attached to the Interactive
+   * context. The selection is only performed for NIS_InteractiveObjects; for
+   * AIS_InteractiveObject type use additional selection call.
+   * @param isModifierUsed
+   *    The modifier buttons state (e.g., when Shift is pressed).
+   * @param isFulInc
+   *    Tells if only those objects are selected that are fully inside the
+   *    selection area.
+   * @param isRedraw
+   *   True to redraw view automatically (default value).
+   */
+  Standard_EXPORT void    Perform       (const Standard_Boolean isModifierUsed,
+                                         const Standard_Boolean isFulInc,
+                                         const Standard_Boolean isRedraw = Standard_True) const;
+
+  Standard_EXPORT NCollection_List<gp_XY> GetPolygon    () const;
+
+ private:
+
+     const Handle_NIS_View&     getView         () const;
+
+     gp_XYZ                     convertPoint    (const Standard_Integer theX,
+                                                 const Standard_Integer theY);
+     void                       updateVertexes  ();
+
+  // ---------- PRIVATE FIELDS ----------
+
+  Handle_NIS_View              myView;
+  NCollection_List<gp_XYZ>     myPoints;
+  Handle(ShortRealArray)       myVertexes;
+  Standard_Boolean             myIsRectangle;
+  Standard_Boolean             myIsLoop;
+
+ public:
+// Declaration of CASCADE RTTI
+DEFINE_STANDARD_RTTI (NIS_PolygonSelector)
+  friend class NIS_PolygonSelectorDrawer;
+};
+
+// Definition of HANDLE object using Standard_DefineHandle.hxx
+DEFINE_STANDARD_HANDLE (NIS_PolygonSelector, NIS_InteractiveObject)
+
+#endif
index a24db385f95f175b8dc1ffbd1db89f16767312bd..989353999df9dffac64d173afa641b66d549452f 100644 (file)
 IMPLEMENT_STANDARD_HANDLE  (NIS_SelectFilter, Standard_Transient)
 IMPLEMENT_STANDARD_RTTIEXT (NIS_SelectFilter, Standard_Transient)
 
+//=======================================================================
+//function : IsOk
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean NIS_SelectFilter::IsOk
+                                (const NIS_InteractiveObject * theObject,
+                                 const gp_Ax1&,
+                                 const Standard_Real,
+                                 const Event theEvent) const
+{
+  Standard_Boolean aResult(Standard_False);
+  if (theEvent == Indefinite || (theEvent & myEventFlags) != 0)
+    aResult = IsOk(theObject, theEvent);
+  return aResult;
+}
+
 //=======================================================================
 //function : ActsOn
 //purpose  : 
@@ -28,4 +45,3 @@ Standard_Boolean NIS_SelectFilter::ActsOn (const Handle_Standard_Type&) const
   return Standard_True;
 }
 
-
index d09aee6370d2cf4b4f1622c693b2757b1576f16f..2370ae729025a78a32737ebedac0a8aa95d46442 100644 (file)
@@ -21,6 +21,7 @@
 
 class NIS_InteractiveObject;
 class Handle_Standard_Type;
+class gp_Ax1;
 
 /**
  * Interface for selection filters. It can be used in NIS_InteractiveContext
@@ -29,18 +30,32 @@ class Handle_Standard_Type;
  * you need more than one filter instance to work together, create a composite
  * NIS_SelectFilter specialization that would hold a list of simpler Filter
  * instances.
+ * @ingroup nis_library
  */
 
 class NIS_SelectFilter : public Standard_Transient
 {
  public:
   // ---------- PUBLIC METHODS ----------
-
+  //! binary flags (1,2,4,8,...) describing the events for which it responds
+  enum Event {
+    Indefinite   = 0,
+    Pick         = 1,
+    DynHilight   = 2,
+    Picked       = 4,
+    DynHilighted = 8
+  };
 
   /**
    * Empty constructor.
    */
-  inline NIS_SelectFilter () {}
+  inline NIS_SelectFilter () : myEventFlags (Pick | DynHilight) {}
+
+  /**
+   * Set the combination of events as bit flags defined in enum Event.
+   */ 
+  inline void SetEventFlags (const unsigned int theFlags)
+  { myEventFlags = theFlags; }
 
   /**
    * Indicate that the given NIS_InteractiveObject passes the Filter.
@@ -48,7 +63,32 @@ class NIS_SelectFilter : public Standard_Transient
    *   True - theObject is kept in the Selection, False - excluded from it.
    */
   virtual Standard_Boolean
-        IsOk    (const NIS_InteractiveObject * theObject)       const = 0;
+        IsOk    (const NIS_InteractiveObject * theObject,
+                 const Event                   theEvent = Indefinite) const = 0;
+
+  /**
+   * Indicate that the given NIS_InteractiveObject passes the Filter.
+   * This method is called during a selection by mouse click. If it returns
+   * True then the normal hilighting is performed. Otherwise the object
+   * is skipped from hilighted selection but this method may perform some
+   * special actions, if redefined. the default implementation just calls
+   * the previous method IsOk.
+   * @param theObject
+   *   Tested object.
+   * @param theAxis
+   *   Selection ray
+   * @param theOver
+   *   Thickness of the selecting ray
+   * @param theEvent
+   *   Event type that invokes this method.
+   * @return
+   *   True - theObject is kept in the Selection, False - excluded from it.
+   */
+  Standard_EXPORT virtual Standard_Boolean
+        IsOk    (const NIS_InteractiveObject * theObject,
+                 const gp_Ax1&                 theAxis,
+                 const Standard_Real           theOver,
+                 const Event                   theEvent = Indefinite) const;
 
   /**
    * Check if the type of InteractiveObject is allowed for selection.
@@ -64,8 +104,7 @@ class NIS_SelectFilter : public Standard_Transient
  protected:
   // ---------- PROTECTED METHODS ----------
 
-
-
+  unsigned int myEventFlags;
 
  public:
 // Declaration of CASCADE RTTI
index 6cf2bcaf17aaf3e9685c967c945ae9f1703b9ccb..a2502e7e24de25673d23fea33234424625ff924e 100644 (file)
@@ -31,6 +31,8 @@
 #include <TopExp_Explorer.hxx>
 #include <TopLoc_Location.hxx>
 #include <TopTools_MapOfShape.hxx>
+#include <TopTools_DataMapOfShapeInteger.hxx>
+#include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Edge.hxx>
@@ -57,15 +59,16 @@ inline Standard_Boolean IsEqual(const Handle_Poly_Triangulation& theT0,
 //=======================================================================
 
 NIS_Surface::NIS_Surface(const Handle_NCollection_BaseAllocator& theAlloc)
-  : myAlloc      (theAlloc),
-    mypNodes     (NULL),
-    mypNormals   (NULL),
-    mypTriangles (NULL),
-    mypEdges     (NULL),
-    myNNodes     (0),
-    myNTriangles (0),
-    myNEdges     (0),
-    myIsWireframe(0)
+  : myAlloc             (theAlloc),
+    mypNodes            (NULL),
+    mypNormals          (NULL),
+    mypTriangles        (NULL),
+    myNNodes            (0),
+    myNTriangles        (0),
+    myIsWireframe       (Standard_False),
+    myHilightIsWireframe(Standard_False),
+    myIsShowFreeBoundary(Standard_False),
+    myIsShowEdges       (Standard_True)
 {
   if (myAlloc.IsNull())
     myAlloc = NCollection_BaseAllocator::CommonBaseAllocator();  
@@ -78,14 +81,15 @@ NIS_Surface::NIS_Surface(const Handle_NCollection_BaseAllocator& theAlloc)
 
 NIS_Surface::NIS_Surface (const Handle(Poly_Triangulation)&       theTri,
                           const Handle_NCollection_BaseAllocator& theAlloc)
-  : myAlloc      (theAlloc),
-    mypNodes     (NULL),
-    mypNormals   (NULL),
-    mypEdges     (NULL),
-    myNNodes     (0),
-    myNTriangles (0),
-    myNEdges     (0),
-    myIsWireframe(0)
+  : myAlloc             (theAlloc),
+    mypNodes            (NULL),
+    mypNormals          (NULL),
+    myNNodes            (0),
+    myNTriangles        (0),
+    myIsWireframe       (Standard_False),
+    myHilightIsWireframe(Standard_False),
+    myIsShowFreeBoundary(Standard_False),
+    myIsShowEdges       (Standard_True)
 {
   if (myAlloc.IsNull())
     myAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
@@ -147,18 +151,20 @@ NIS_Surface::NIS_Surface (const Handle(Poly_Triangulation)&       theTri,
 //purpose  : Constructor
 //=======================================================================
 
-NIS_Surface::NIS_Surface (const TopoDS_Shape&                     theShape,
-                          const Standard_Real                     theDeflection,
+NIS_Surface::NIS_Surface (const TopoDS_Shape&                theShape,
+                          const Standard_Real                theDeflection,
+                          const Standard_Boolean             theIsFreeBoundary,
                           const Handle_NCollection_BaseAllocator& theAlloc)
-  : myAlloc       (theAlloc),
-    mypNodes      (NULL),
-    mypNormals    (NULL),
-    mypTriangles  (NULL),
-    mypEdges      (NULL),
-    myNNodes      (0),
-    myNTriangles  (0),
-    myNEdges      (0),
-    myIsWireframe (0)
+  : myAlloc             (theAlloc),
+    mypNodes            (NULL),
+    mypNormals          (NULL),
+    mypTriangles        (NULL),
+    myNNodes            (0),
+    myNTriangles        (0),
+    myIsWireframe       (Standard_False),
+    myHilightIsWireframe(Standard_False),
+    myIsShowFreeBoundary(theIsFreeBoundary),
+    myIsShowEdges       (Standard_True)
 {
   if (myAlloc.IsNull())
     myAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
@@ -174,35 +180,86 @@ void NIS_Surface::Init (const TopoDS_Shape& theShape,
                         const Standard_Real theDeflection)
 {
   TopLoc_Location  aLoc, aLocSurf;
+  Clear();
 
-  // Count the nodes and triangles in faces
-  NCollection_Map<Handle_Poly_Triangulation> mapTri;
+  //Upon initialization by TopoDS_Shape the check of triangulation is performed.
+  //If at least one face has no triangulation but has a surface then the whole
+  // shape is triangulated using BRepMesh. 
+  //The whole shape triangulation is required to respect boundary connection
+  Standard_Boolean hasTri = Standard_True;
+  TopExp_Explorer eexp;
   TopExp_Explorer fexp (theShape, TopAbs_FACE);
-  for (; fexp.More(); fexp.Next())
+  for (; fexp.More() && hasTri; fexp.Next())
   {
     const TopoDS_Face& aFace = TopoDS::Face(fexp.Current());
-    
+
     const Handle(Poly_Triangulation)& aTriangulation
       = BRep_Tool::Triangulation (aFace, aLoc);
+    const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface(aFace, aLoc);
+
+    if ((aTriangulation.IsNull() && Standard_False == aSurface.IsNull()) ||
+        (Standard_False == aTriangulation.IsNull() &&
+            theDeflection < aTriangulation->Deflection() ))
+    {
+      hasTri = Standard_False;
+      break;
+    }
+    for (eexp.Init(aFace, TopAbs_EDGE); eexp.More(); eexp.Next())
+    {
+      const TopoDS_Edge& anEdge = TopoDS::Edge(eexp.Current());          
+
+      const Handle(Poly_PolygonOnTriangulation)& aPolygon =
+        BRep_Tool::PolygonOnTriangulation(anEdge, aTriangulation, aLoc);
+      if (aPolygon.IsNull()) 
+      {
+        hasTri = Standard_False;
+        break;
+      }
+    }
+  }
+
+  if( hasTri == Standard_False )
+  {
+      const Standard_Real anAngularDeflection = 20.0 * M_PI / 180.0;
+      BRepMesh_IncrementalMesh aMeshTool(theShape, theDeflection,
+          Standard_False, anAngularDeflection);
+  }
+
+  // Count the nodes and triangles in faces
+  for (fexp.Init(theShape, TopAbs_FACE); fexp.More(); fexp.Next())
+  {
+    const TopoDS_Face& aFace = TopoDS::Face(fexp.Current());
     
-    if (aTriangulation.IsNull())
-      BRepMesh_IncrementalMesh aMeshTool(aFace, theDeflection); 
+    const Handle(Poly_Triangulation)& aTriangulation
+      = BRep_Tool::Triangulation (aFace, aLoc);
 
     if (aTriangulation.IsNull() == Standard_False)
     {
       myNNodes     += aTriangulation->NbNodes();
       myNTriangles += aTriangulation->NbTriangles();
-      mapTri.Add(aTriangulation);
     }
   }
 
   // Create map of edges, to build wireframe for all edges.
-  TopTools_MapOfShape mapEdges;
-  TopExp_Explorer eexp (theShape, TopAbs_EDGE);
-  for (; eexp.More(); eexp.Next())
+  TopTools_DataMapOfShapeInteger mapEdges;  
+  for (eexp.Init(theShape, TopAbs_EDGE); eexp.More(); eexp.Next())
   {
     const TopoDS_Shape& anEdge = eexp.Current();
-    mapEdges.Add(anEdge);
+    if (mapEdges.IsBound(anEdge))
+      mapEdges.ChangeFind(anEdge) += 1;
+    else
+      mapEdges.Bind(anEdge, 1);
+  }
+
+  Standard_Integer nbFreeEdges = 0, nbEdges = 0;
+  TopTools_DataMapIteratorOfDataMapOfShapeInteger anEIt(mapEdges);
+  for (; anEIt.More(); anEIt.Next())
+  {
+    const Standard_Integer nb = anEIt.Value();
+    if (nb > 1)
+      nbEdges += 1;      
+    else
+      nbFreeEdges += 1;      
   }
 
   // Allocate arrays of entities
@@ -213,13 +270,12 @@ void NIS_Surface::Init (const TopoDS_Shape& theShape,
       (myAlloc->Allocate(sizeof(Standard_ShortReal) * 3 * myNNodes));
     mypTriangles = static_cast<Standard_Integer *>
       (myAlloc->Allocate(sizeof(Standard_Integer) * 3 * myNTriangles));
-    mypEdges = static_cast<Standard_Integer **>
-      (myAlloc->Allocate(sizeof(Standard_Integer *) * mapEdges.Extent()));
-    myNEdges = 0;
+    myEdges.InitArray (2, nbEdges, myAlloc.operator->());
+    myFreeEdges.InitArray (2, nbFreeEdges, myAlloc.operator->());
 
     // The second loop: copy all nodes and triangles face-by-face
     const Standard_Real eps2 = Precision::SquareConfusion();
-    Standard_Integer nNodes (0), nTriangles (0);
+    Standard_Integer nNodes (0), nTriangles (0), nEdges (0), nFEdges (0);
     for (fexp.ReInit(); fexp.More(); fexp.Next())
     {
       const TopoDS_Face& aFace = TopoDS::Face(fexp.Current());
@@ -317,18 +373,21 @@ void NIS_Surface::Init (const TopoDS_Shape& theShape,
         // Store all edge polygons on the current face.
         for (eexp.Init(aFace, TopAbs_EDGE); eexp.More(); eexp.Next())
         {
-          const TopoDS_Edge& anEdge = TopoDS::Edge(eexp.Current());
-          if (mapEdges.Remove(anEdge)) {
+          const TopoDS_Edge& anEdge = TopoDS::Edge(eexp.Current());          
+          if (mapEdges.IsBound(anEdge)) {
+            Standard_Integer nbE = mapEdges.Find(anEdge);
+            mapEdges.UnBind(anEdge);
+
             const Handle(Poly_PolygonOnTriangulation)& aPolygon =
               BRep_Tool::PolygonOnTriangulation(anEdge, aTriangulation, aLoc);
             if (aPolygon.IsNull() == Standard_False) {
               const TColStd_Array1OfInteger& arrNode = aPolygon->Nodes();
               // Allocate memory to store the current polygon indices.
               Standard_Integer aLen = arrNode.Length();
-              Standard_Integer * pEdge = static_cast<Standard_Integer *>
-                (myAlloc->Allocate(sizeof(Standard_Integer) * (aLen + 1)));
+              int * pEdge = static_cast<int *>
+                (myAlloc->Allocate(sizeof(int) * (aLen)));
               const gp_Pnt* pLast = &tabNode(arrNode(arrNode.Lower()));
-              pEdge[1] = arrNode(arrNode.Lower()) + nNodes1;
+              pEdge[0] = arrNode(arrNode.Lower()) + nNodes1;              
               Standard_Integer iPNode(arrNode.Lower() + 1), iENode(1);
               for (; iPNode <= arrNode.Upper(); iPNode++)
               {
@@ -338,27 +397,33 @@ void NIS_Surface::Init (const TopoDS_Shape& theShape,
                   aLen--;
                 } else {
                   pLast = &tabNode(aN);
-                  pEdge[++iENode] = aN + nNodes1;
+                  pEdge[iENode++] = aN + nNodes1;
                 }
               }
               // Do not save very short polygons
               if (aLen > 1) {
-                pEdge[0] = aLen;
-                mypEdges[myNEdges++] = pEdge;
+                if (nbE > 1)
+                  myEdges.SetArray(nEdges++, aLen, pEdge, myAlloc.operator->());
+                else
+                  myFreeEdges.SetArray(nFEdges++, aLen, pEdge,
+                                       myAlloc.operator->());
               }
+              myAlloc->Free(pEdge);
             }
           }
         }
         nNodes += tabNode.Length();
       }
     }
+    myEdges.SetRealNumbersOfArrays(nEdges);
+    myFreeEdges.SetRealNumbersOfArrays(nFEdges);
     myNTriangles = nTriangles;
   }
   if (GetDrawer().IsNull() == Standard_False)
   {
     setDrawerUpdate();
   }
-  setIsUpdateBox(Standard_True);  
+  setIsUpdateBox(Standard_True);
 }
 
 //=======================================================================
@@ -387,13 +452,10 @@ void NIS_Surface::Clear ()
     myNTriangles = 0;
     myAlloc->Free(mypTriangles);
   }
-  if (mypEdges) {
-    for (Standard_Integer i = 0; i < myNEdges; i++) {
-      myAlloc->Free(mypEdges[i]);
-    }
-    myNEdges = 0;
-    myAlloc->Free(mypEdges);
-  }
+
+  myEdges.Clear(myAlloc.operator->());
+  myFreeEdges.Clear(myAlloc.operator->());
+  
   if (GetDrawer().IsNull() == Standard_False) {
     GetDrawer()->SetUpdated(NIS_Drawer::Draw_Normal,
                             NIS_Drawer::Draw_Top,
@@ -419,32 +481,30 @@ NIS_Drawer * NIS_Surface::DefaultDrawer (NIS_Drawer * theDrawer) const
 }
 
 //=======================================================================
-//function : SetColor
-//purpose  : Set the normal color for presentation.
+//function : SetBackColor
+//purpose  : Set the normal color for presentation of back side of triangles.
 //=======================================================================
 
-void NIS_Surface::SetColor (const Quantity_Color&  theColor)
+void NIS_Surface::SetBackColor (const Quantity_Color&  theColor)
 {
   const Handle(NIS_SurfaceDrawer) aDrawer =
     static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L));
   aDrawer->Assign (GetDrawer());
-  aDrawer->myColor[NIS_Drawer::Draw_Normal] = theColor;
-  aDrawer->myColor[NIS_Drawer::Draw_Top] = theColor;
-  aDrawer->myColor[NIS_Drawer::Draw_Transparent] = theColor;
+  aDrawer->myBackColor = theColor;
   SetDrawer (aDrawer);
 }
 
 //=======================================================================
-//function : SetBackColor
-//purpose  : Set the normal color for presentation of back side of triangles.
+//function : SetSpecularity
+//purpose  : 
 //=======================================================================
 
-void NIS_Surface::SetBackColor (const Quantity_Color&  theColor)
+void NIS_Surface::SetSpecularity (const Standard_Real  theValue)
 {
   const Handle(NIS_SurfaceDrawer) aDrawer =
     static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L));
   aDrawer->Assign (GetDrawer());
-  aDrawer->myBackColor = theColor;
+  aDrawer->SetSpecularity(theValue);
   SetDrawer (aDrawer);
 }
 
@@ -462,6 +522,21 @@ void NIS_Surface::SetPolygonOffset (const Standard_Real theValue)
   SetDrawer (aDrawer);
 }
 
+//=======================================================================
+//function : SetTransformation
+//purpose  : 
+//=======================================================================
+
+void NIS_Surface::SetTransformation (const gp_Trsf& theTrsf)
+{
+  const Handle(NIS_SurfaceDrawer) aDrawer =
+    static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L));
+  aDrawer->Assign (GetDrawer());
+  aDrawer->SetTransformation(theTrsf);
+  SetDrawer (aDrawer);
+  setIsUpdateBox(Standard_True);
+}
+
 //=======================================================================
 //function : SetDisplayMode
 //purpose  : Set the display mode: Shading or Wireframe.
@@ -473,20 +548,37 @@ void  NIS_Surface::SetDisplayMode (const NIS_Surface::DisplayMode theMode)
   if (myIsWireframe) {
     if (theMode != Wireframe) {
       myIsWireframe = Standard_False;
+      myIsShowEdges = (theMode != PureShading);
       isUpdate = Standard_True;
     }
   } else {
     if (theMode == Wireframe) {
       myIsWireframe = Standard_True;
+      myIsShowEdges = Standard_True;
       isUpdate = Standard_True;
     }
+    else {
+      if (myIsShowEdges) {
+        if (theMode == PureShading) {
+          myIsShowEdges = Standard_False;
+          isUpdate = Standard_True;
+        }
+      }
+      else {
+        if (theMode != PureShading) {
+          myIsShowEdges = Standard_True;
+          isUpdate = Standard_True;
+        }
+      }
+    }
   }
   if (isUpdate && !GetDrawer().IsNull()) {
     const Handle(NIS_SurfaceDrawer) aDrawer =
       static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L));
     aDrawer->Assign (GetDrawer());
     aDrawer->myIsWireframe = myIsWireframe;
-    SetDrawer(aDrawer);
+    aDrawer->myIsShowEdges = myIsShowEdges;
+    SetDrawer(aDrawer);    
   }
 }
 
@@ -497,7 +589,86 @@ void  NIS_Surface::SetDisplayMode (const NIS_Surface::DisplayMode theMode)
 
 NIS_Surface::DisplayMode NIS_Surface::GetDisplayMode () const
 {
-  return myIsWireframe ? Wireframe : Shading;
+  return myIsWireframe ? Wireframe : (myIsShowEdges ? Shading : PureShading);
+}
+
+//=======================================================================
+//function : SetHilightDisplayMode
+//purpose  : Set the hilight display mode: Shading or Wireframe.
+//=======================================================================
+
+void  NIS_Surface::SetHilightDisplayMode(const NIS_Surface::DisplayMode theMode)
+{
+  Standard_Boolean isUpdate = Standard_False;
+  if (myIsWireframe == Standard_True) 
+  {
+    if (myHilightIsWireframe) 
+    {
+      myHilightIsWireframe = Standard_False;
+      isUpdate = Standard_True;
+    }
+  } 
+  else 
+  {
+    if (myHilightIsWireframe) {
+      if (theMode != Wireframe) {
+        myHilightIsWireframe = Standard_False;
+        isUpdate = Standard_True;
+      }
+    } 
+    else {
+      if (theMode == Wireframe) {
+        myHilightIsWireframe = Standard_True;
+        isUpdate = Standard_True;
+      }
+    }
+  }
+  if (isUpdate) {
+    const Handle(NIS_Drawer)& aCurrDrawer = GetDrawer();
+    if (aCurrDrawer.IsNull() == Standard_False) {
+      const Handle(NIS_SurfaceDrawer) aDrawer =
+        static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L));
+      aDrawer->Assign (GetDrawer());
+      aDrawer->myHilightIsWireframe = myHilightIsWireframe;
+      SetDrawer(aDrawer);
+    }
+  }
+}
+
+//=======================================================================
+//function : GetHilightDisplayMode
+//purpose  : Query the current hilight display mode: Shading or Wireframe.
+//=======================================================================
+
+NIS_Surface::DisplayMode NIS_Surface::GetHilightDisplayMode () const
+{
+  return myHilightIsWireframe ? Wireframe : Shading;
+}
+
+//=======================================================================
+//function : ShowFreeBoundary 
+//purpose  : Display free boundary of the surface object with the
+//           specified color
+//=======================================================================
+void NIS_Surface::ShowFreeBoundary (const Quantity_Color& theColor)
+{
+  myIsShowFreeBoundary = Standard_True;
+  const Handle(NIS_SurfaceDrawer) aDrawer =
+    static_cast<NIS_SurfaceDrawer *>(DefaultDrawer(0L));
+  aDrawer->Assign (GetDrawer());
+  aDrawer->myFreeEdgeColor = theColor;
+  SetDrawer (aDrawer);
+//   setDrawerUpdate(); - already called in SetDrawer()
+}
+
+//=======================================================================
+//function : HideFreeBoundary
+//purpose  : Hides special precentation of free boundaries
+//=======================================================================
+void NIS_Surface::HideFreeBoundary ()
+{
+  myIsShowFreeBoundary = Standard_False;
+  setDrawerUpdate();
 }
 
 //=======================================================================
@@ -532,19 +703,34 @@ void NIS_Surface::Clone (const Handle_NCollection_BaseAllocator& theAlloc,
     aNewObj->mypTriangles = (Standard_Integer *)theAlloc->Allocate(nBytes);
     memcpy(aNewObj->mypTriangles, mypTriangles, nBytes);
   }
-  aNewObj->myNEdges = myNEdges;
-  if (myNEdges > 0) {
-    aNewObj->mypEdges = static_cast<Standard_Integer **>
-      (theAlloc->Allocate(sizeof(Standard_Integer *) * myNEdges));
-    for (Standard_Integer i = 0; i < myNEdges; i++) {
-      const Standard_Integer * pEdge = mypEdges[i];
-      const Standard_Size nBytes = sizeof(Standard_Integer) * (pEdge[0] + 1);
-      aNewObj->mypEdges[i] =
-        static_cast<Standard_Integer *> (theAlloc->Allocate(nBytes));
-      memcpy(aNewObj->mypEdges[i], pEdge, nBytes);
-    }
-  }
+
+  myEdges.Clone(theAlloc, aNewObj->myEdges);
+  myFreeEdges.Clone(theAlloc, aNewObj->myFreeEdges);
+  
   aNewObj->myIsWireframe = myIsWireframe;
+  aNewObj->myIsShowFreeBoundary = myIsShowFreeBoundary;
+  aNewObj->myIsShowEdges = myIsShowEdges;
+}
+
+//=======================================================================
+//function : NEdgeNodeInList 
+//purpose  : 
+//=======================================================================
+
+Standard_Integer NIS_Surface::NEdgeNodeInList (const Standard_Integer ind) const
+{
+  return myEdges.NArrayIndexes(ind);  
+}
+
+//=======================================================================
+//function : NFreeEdgeNodeInList 
+//purpose  : 
+//=======================================================================
+
+Standard_Integer NIS_Surface::NFreeEdgeNodeInList
+                                        (const Standard_Integer ind) const
+{
+  return myFreeEdges.NArrayIndexes(ind);  
 }
 
 //=======================================================================
@@ -556,10 +742,22 @@ Standard_Real NIS_Surface::Intersect (const gp_Ax1&       theAxis,
                                       const Standard_Real theOver) const
 {
   Standard_Real aResult (RealLast());
-  Standard_Real start[3], dir[3];
-  theAxis.Location().Coord(start[0], start[1], start[2]);
-  theAxis.Direction().Coord(dir[0], dir[1], dir[2]);
-  double anInter;
+  Standard_Real start[3], dir[3], anInter;
+
+  // Obtain the current Transformation from the Drawer
+  const Handle(NIS_SurfaceDrawer)& aDrawer =
+    static_cast<const Handle(NIS_SurfaceDrawer)&> (GetDrawer());
+
+  if (aDrawer.IsNull()) {
+    theAxis.Location().Coord(start[0], start[1], start[2]);
+    theAxis.Direction().Coord(dir[0], dir[1], dir[2]);
+  } else {
+    gp_Trsf aTrsf = aDrawer->GetTransformation();
+    aTrsf.Invert();
+    const gp_Ax1 anAxis = theAxis.Transformed(aTrsf);
+    anAxis.Location().Coord(start[0], start[1], start[2]);
+    anAxis.Direction().Coord(dir[0], dir[1], dir[2]);
+  }
 
   if (myIsWireframe == Standard_False)
     for (Standard_Integer i = 0; i < myNTriangles; i++) {
@@ -573,27 +771,100 @@ Standard_Real NIS_Surface::Intersect (const gp_Ax1&       theAxis,
           aResult = anInter;
     }
   else {
-    const Standard_Real anOver2 = theOver*theOver;
-    for (Standard_Integer iEdge = 0; iEdge < myNEdges; iEdge++) {
-      const Standard_Integer * anEdge = mypEdges[iEdge];
-      const Standard_Integer nNodes = anEdge[0];
-      for (Standard_Integer i = 1; i < nNodes; i++) {
-        // Node index is incremented for the head of polygon indice array
-        if (NIS_Triangulated::seg_line_intersect (theAxis.Location().XYZ(),
-                                                  theAxis.Direction().XYZ(),
-                                                  anOver2,
-                                                  &mypNodes[3*anEdge[i+0]],
-                                                  &mypNodes[3*anEdge[i+1]],
-                                                  &anInter))
-          if (anInter < aResult)
-            aResult = anInter;
-      }
-    }
+    anInter = intersectEdges(myEdges, theAxis, theOver);
+    if (anInter < aResult)
+      aResult = anInter;    
+    anInter = intersectEdges(myFreeEdges, theAxis, theOver);      
+    if (anInter < aResult)
+      aResult = anInter;    
   }
 
   return aResult;
 }
 
+//=======================================================================
+//function : Normal
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean NIS_Surface::Intersect (const gp_Ax1& theAxis, gp_Vec& theNormal) const
+{
+  Standard_Real aResult (RealLast());
+  Standard_Real start[3], dir[3], anInter;
+  Standard_Integer anIndex(-1);
+
+  // Obtain the current Transformation from the Drawer
+  const Handle(NIS_SurfaceDrawer)& aDrawer =
+    static_cast<const Handle(NIS_SurfaceDrawer)&> (GetDrawer());
+
+  if (aDrawer.IsNull()) {
+    theAxis.Location().Coord(start[0], start[1], start[2]);
+    theAxis.Direction().Coord(dir[0], dir[1], dir[2]);
+  } else {
+    gp_Trsf aTrsf = aDrawer->GetTransformation();
+    aTrsf.Invert();
+    const gp_Ax1 anAxis = theAxis.Transformed(aTrsf);
+    anAxis.Location().Coord(start[0], start[1], start[2]);
+    anAxis.Direction().Coord(dir[0], dir[1], dir[2]);
+  }
+
+  if (myIsWireframe == Standard_False)
+    for (Standard_Integer i = 0; i < myNTriangles; i++) {
+      const Standard_Integer * pTri = &mypTriangles[3*i];
+      if (NIS_Triangulated::tri_line_intersect (start, dir,
+                                                &mypNodes[3*pTri[0]],
+                                                &mypNodes[3*pTri[1]],
+                                                &mypNodes[3*pTri[2]],
+                                                &anInter))
+        if (anInter < aResult) {
+          aResult = anInter;
+          anIndex = i;
+        }
+    }
+
+  if (anIndex < 0) 
+    return Standard_False;
+
+  const Standard_Integer * pTri = &mypTriangles[3*anIndex];
+  gp_XYZ aPnt0(mypNodes[3*pTri[0]+0], mypNodes[3*pTri[0]+1], mypNodes[3*pTri[0]+2]);
+  gp_XYZ aPnt1(mypNodes[3*pTri[1]+0], mypNodes[3*pTri[1]+1], mypNodes[3*pTri[1]+2]);
+  gp_XYZ aPnt2(mypNodes[3*pTri[2]+0], mypNodes[3*pTri[2]+1], mypNodes[3*pTri[2]+2]);
+  theNormal.SetXYZ(((aPnt1 - aPnt0) ^ (aPnt2 - aPnt0)));
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : intersectEdges
+//purpose  : 
+//=======================================================================
+
+Standard_Real NIS_Surface::intersectEdges(const NIS_IndexLists&  theEdges, 
+                                          const gp_Ax1&       theAxis,
+                                          const Standard_Real theOver) const
+{
+  const Standard_Real anOver2 = theOver*theOver;
+  double anInter;
+  Standard_Real aResult (RealLast());
+  for (Standard_Integer iEdge = 0; iEdge < theEdges.NArrays(); iEdge++) {     
+    const Standard_Integer * anEdge =
+      static_cast <Standard_Integer *>(theEdges.ArrayIndexes(iEdge));
+    const Standard_Integer nNodes = theEdges.NArrayIndexes(iEdge);
+    for (Standard_Integer i = 0; i < nNodes-1; i++) {
+      // Node index is incremented for the head of polygon indice array
+      if (NIS_Triangulated::seg_line_intersect (theAxis.Location().XYZ(),
+                                                theAxis.Direction().XYZ(),
+                                                anOver2,
+                                                &mypNodes[3*anEdge[i+0]],
+                                                &mypNodes[3*anEdge[i+1]],
+                                                &anInter))
+      if (anInter < aResult)
+        aResult = anInter;
+    }
+  }
+  return aResult;
+}
+
 //=======================================================================
 //function : Intersect
 //purpose  : 
@@ -604,6 +875,14 @@ Standard_Boolean NIS_Surface::Intersect (const Bnd_B3f&         theBox,
                                          const Standard_Boolean isFullIn) const
 {
   Standard_Boolean aResult (isFullIn);
+  gp_Trsf aTrsf = theTrf;
+
+  // Obtain the current Transformation from the Drawer
+  const Handle(NIS_SurfaceDrawer)& aDrawer =
+    static_cast<const Handle(NIS_SurfaceDrawer)&> (GetDrawer());
+
+  if (aDrawer.IsNull() == Standard_False)
+    aTrsf *= aDrawer->GetTransformation();
 
   if (myIsWireframe == Standard_False) {
     if (myNTriangles > 0) {
@@ -611,7 +890,7 @@ Standard_Boolean NIS_Surface::Intersect (const Bnd_B3f&         theBox,
         gp_XYZ aPnt (static_cast<Standard_Real>(mypNodes[iNode+0]),
                      static_cast<Standard_Real>(mypNodes[iNode+1]),
                      static_cast<Standard_Real>(mypNodes[iNode+2]));
-        theTrf.Transforms(aPnt);
+        aTrsf.Transforms(aPnt);
         if (theBox.IsOut (aPnt) == isFullIn) {
           aResult = !isFullIn;
           break;
@@ -619,31 +898,48 @@ Standard_Boolean NIS_Surface::Intersect (const Bnd_B3f&         theBox,
       }
     }
   } else {
-    for (Standard_Integer iEdge = 0; iEdge < myNEdges; iEdge++) {
-      const Standard_Integer * anEdge = mypEdges[iEdge];
-      const Standard_Integer nNodes = anEdge[0];
-      for (Standard_Integer i = 1; i < nNodes; i++) {
-        // index is incremented by 1 for the head number in the array
-        gp_Pnt aPnt[2] = {
-          gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+0]),
-                 static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+1]),
-                 static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+2])),
-          gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+0]),
-                 static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+1]),
-                 static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+2]))
-        };
-        aPnt[0].Transform(theTrf);
-        aPnt[1].Transform(theTrf);
-        if (isFullIn) {
-          if (NIS_Triangulated::seg_box_included (theBox, aPnt) == 0) {
-            aResult = Standard_False;
-            break;
-          }
-        } else {
-          if (NIS_Triangulated::seg_box_intersect (theBox, aPnt)) {
-            aResult = Standard_True;
-            break;
-          }
+    aResult = intersectEdges(myEdges, aTrsf, theBox, isFullIn);
+    if(!aResult)
+      aResult = intersectEdges(myFreeEdges, aTrsf, theBox, isFullIn);    
+  }
+  return aResult;
+}
+
+//=======================================================================
+//function : intersectEdges
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean NIS_Surface::intersectEdges(const NIS_IndexLists&  theEdges, 
+                                             const gp_Trsf&         theTrf,
+                                             const Bnd_B3f&         theBox,
+                                             const Standard_Boolean isFullIn) const
+{
+  Standard_Boolean aResult (isFullIn);
+  for (Standard_Integer iEdge = 0; iEdge < theEdges.NArrays(); iEdge++) {     
+    const Standard_Integer * anEdge =
+      static_cast <Standard_Integer *>(theEdges.ArrayIndexes(iEdge));
+    const Standard_Integer nNodes = theEdges.NArrayIndexes(iEdge);
+    for (Standard_Integer i = 0; i < nNodes-1; i++) {        
+      gp_Pnt aPnt[2] = {
+        gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+0]),
+               static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+1]),
+               static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+2])),
+        gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+0]),
+               static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+1]),
+               static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+2]))
+      };
+      aPnt[0].Transform(theTrf);
+      aPnt[1].Transform(theTrf);
+      if (isFullIn) {
+        if (NIS_Triangulated::seg_box_included (theBox, aPnt) == 0) {
+          aResult = Standard_False;
+          break;
+        }
+      } else {
+        if (NIS_Triangulated::seg_box_intersect (theBox, aPnt)) {
+          aResult = Standard_True;
+          break;
         }
       }
     }
@@ -662,6 +958,14 @@ Standard_Boolean NIS_Surface::Intersect
                      const Standard_Boolean         isFullIn) const
 {
   Standard_Boolean aResult (isFullIn);
+  gp_Trsf aTrsf = theTrf;
+
+  // Obtain the current Transformation from the Drawer
+  const Handle(NIS_SurfaceDrawer)& aDrawer =
+    static_cast<const Handle(NIS_SurfaceDrawer)&> (GetDrawer());
+
+  if (aDrawer.IsNull() == Standard_False)
+    aTrsf *= aDrawer->GetTransformation();
 
   if (myIsWireframe == Standard_False) {
     if (myNTriangles > 0) {
@@ -669,7 +973,7 @@ Standard_Boolean NIS_Surface::Intersect
         gp_XYZ aPnt (static_cast<Standard_Real>(mypNodes[iNode+0]),
                      static_cast<Standard_Real>(mypNodes[iNode+1]),
                      static_cast<Standard_Real>(mypNodes[iNode+2]));
-        theTrf.Transforms(aPnt);
+        aTrsf.Transforms(aPnt);
         gp_XY aP2d(aPnt.X(), aPnt.Y());
 
         if (!NIS_Triangulated::IsIn(thePolygon, aP2d)) {
@@ -686,33 +990,52 @@ Standard_Boolean NIS_Surface::Intersect
       }
     }
   } else {
-    for (Standard_Integer iEdge = 0; iEdge < myNEdges; iEdge++) {
-      const Standard_Integer * anEdge = mypEdges[iEdge];
-      const Standard_Integer nNodes = anEdge[0];
-      for (Standard_Integer i = 1; i < nNodes; i++) {
-        // index is incremented by 1 for the head number in the array
-        gp_Pnt aPnt[2] = {
-          gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+0]),
-                 static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+1]),
-                 static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+2])),
-          gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+0]),
-                 static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+1]),
-                 static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+2]))
-        };
-        aPnt[0].Transform(theTrf);
-        aPnt[1].Transform(theTrf);
-        const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()),
-                                gp_XY(aPnt[1].X(), aPnt[1].Y()) };
-        if (isFullIn) {
-          if (NIS_Triangulated::seg_polygon_included (thePolygon, aP2d) == 0) {
-            aResult = Standard_False;
-            break;
-          }
-        } else {
-          if (NIS_Triangulated::seg_polygon_intersect (thePolygon, aP2d)) {
-            aResult = Standard_True;
-            break;
-          }
+    aResult = intersectEdges(myEdges, aTrsf, thePolygon, isFullIn);
+    if(!aResult)
+      aResult = intersectEdges(myFreeEdges, aTrsf, thePolygon, isFullIn);    
+  }
+  return aResult;
+}
+
+//=======================================================================
+//function : intersectEdges
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean NIS_Surface::intersectEdges
+                                (const NIS_IndexLists&          theEdges, 
+                                 const gp_Trsf&                 theTrf,
+                                 const NCollection_List<gp_XY>& thePolygon,
+                                 const Standard_Boolean         isFullIn) const
+{
+  Standard_Boolean aResult (isFullIn);
+  for (Standard_Integer iEdge = 0; iEdge < theEdges.NArrays(); iEdge++)
+  {     
+    const Standard_Integer * anEdge =
+      static_cast <Standard_Integer *>(theEdges.ArrayIndexes(iEdge));
+    const Standard_Integer nNodes = theEdges.NArrayIndexes(iEdge);
+    for (Standard_Integer i = 0; i < nNodes-1; i++) {                  
+      gp_Pnt aPnt[2] = {
+        gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+0]),
+               static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+1]),
+               static_cast<Standard_Real>(mypNodes[3*anEdge[i+0]+2])),
+        gp_Pnt(static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+0]),
+               static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+1]),
+               static_cast<Standard_Real>(mypNodes[3*anEdge[i+1]+2]))
+      };
+      aPnt[0].Transform(theTrf);
+      aPnt[1].Transform(theTrf);
+      const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()),
+                              gp_XY(aPnt[1].X(), aPnt[1].Y()) };
+      if (isFullIn) {
+        if (NIS_Triangulated::seg_polygon_included (thePolygon, aP2d) == 0) {
+          aResult = Standard_False;
+          break;
+        }
+      } else {
+        if (NIS_Triangulated::seg_polygon_intersect (thePolygon, aP2d)) {
+          aResult = Standard_True;
+          break;
         }
       }
     }
index f6db340267ea4e59823f16bca2bd71a48d7fa887..b48673e8200ec1e8f1ab0f8e6a7ba4836ca991d3 100644 (file)
@@ -17,6 +17,7 @@
 #define NIS_Surface_HeaderFile
 
 #include <NIS_InteractiveObject.hxx>
+#include <NIS_IndexLists.hxx>
 #include <NCollection_BaseAllocator.hxx>
 #include <gp_XYZ.hxx>
 
@@ -39,14 +40,16 @@ class TopoDS_Shape;
  * <p>
  * This class is conceived as replacement of AIS_Shape; both wireframe and
  * shading modes are available for dynamic switching.
+ * @ingroup nis_library
  */
 
 class NIS_Surface : public NIS_InteractiveObject
 {
 public:
   enum DisplayMode {
+    Wireframe,
     Shading,
-    Wireframe
+    PureShading
   };
 
   /**
@@ -61,11 +64,14 @@ public:
    *   Source geometry. It should contain triangulations inside.
    * @param theDeflection
    *   Absolute deflection for meshing 'theShape' if such meshing is needed.
+   * @param isFreeBnd
+   *   To show or not to show the free boundary.
    * @param theAl
    *   Allocator used for nodes and triangles in this presentation.
    */
-  Standard_EXPORT NIS_Surface(const TopoDS_Shape& theShape,
-                              const Standard_Real theDeflection,
+  Standard_EXPORT NIS_Surface(const TopoDS_Shape&    theShape,
+                              const Standard_Real    theDeflection,
+                              const Standard_Boolean isFreeBnd=Standard_False,
                               const Handle_NCollection_BaseAllocator& theAl=0L);
 
   /**
@@ -85,6 +91,18 @@ public:
    */
   Standard_EXPORT void              Clear       ();
 
+  /**
+   * Query the number of nodes in Edge List.
+   */
+  Standard_EXPORT Standard_Integer  NEdgeNodeInList
+                                            (const Standard_Integer ind) const;
+
+  /**
+   * Query the number of nodes in Free Edge List.
+   */
+  Standard_EXPORT Standard_Integer  NFreeEdgeNodeInList
+                                            (const Standard_Integer ind) const;
+
   /**
    * Query the number of nodes.
    */
@@ -98,7 +116,12 @@ public:
   /**
    * Query the number of edges for wireframe display.
    */
-  inline Standard_Integer           NEdges      () const { return myNEdges; }
+  inline Standard_Integer           NEdges      () const { return myEdges.NArrays(); }
+
+  /**
+   * Query the number of free edges for wireframe display.
+   */
+  inline Standard_Integer           NFreeEdges  () const { return myFreeEdges.NArrays(); }
 
   /**
    * Query the node by its index.
@@ -125,13 +148,23 @@ public:
   /**
    * Access to array of integers that represents an Edge.
    * @return
-   *   Pointer to array where the 0th element is the number of nodes in the edge
-   *   and the elements starting from the 1st are node indices.
+   *   Pointer to array without the 0 element.
    */
   inline const Standard_Integer*
                         Edge            (const Standard_Integer theIndex) const
   {
-    return mypEdges[theIndex];
+    return static_cast <Standard_Integer *>(myEdges.ArrayIndexes(theIndex));
+  }
+
+  /**
+   * Access to array of integers that represents an Free Edge.
+   * @return
+   *   Pointer to array without the 0 element.
+   */
+  inline const Standard_Integer*
+                        FreeEdge            (const Standard_Integer theIndex) const
+  {
+    return static_cast <Standard_Integer *>(myFreeEdges.ArrayIndexes(theIndex));
   }
 
   /**
@@ -145,6 +178,14 @@ public:
     return &mypNormals[theIndex * 3];
   }
 
+  /**
+   * Returns status of displayin of free boundaries 
+   */
+  inline Standard_Boolean IsShowFreeBounds() const                  
+  {
+    return myIsShowFreeBoundary;
+  }
+
   /**
    * Create a default drawer instance.
    */
@@ -152,18 +193,17 @@ public:
                         DefaultDrawer   (NIS_Drawer *) const;
 
   /**
-   * Set the normal color for presentation.
+   * Set the color for presentation of the back side of triangles.
    * @param theColor
    *   New color to use for the presentation.
    */
-  Standard_EXPORT void  SetColor        (const Quantity_Color& theColor);
+  Standard_EXPORT void  SetBackColor    (const Quantity_Color& theColor);
 
   /**
-   * Set the color for presentation of the back side of triangles.
-   * @param theColor
-   *   New color to use for the presentation.
+   * Define the specularity that is the property of displayed material for both
+   * Front and Back faces. Can be in the range 0 to 1. Default value is 0.58
    */
-  Standard_EXPORT void  SetBackColor    (const Quantity_Color& theColor);
+  Standard_EXPORT void  SetSpecularity  (const Standard_Real theValue);
 
   /**
    * Set the offset for the presentation.
@@ -172,6 +212,14 @@ public:
    */
   Standard_EXPORT void  SetPolygonOffset (const Standard_Real theValue);
 
+  /**
+   * Set the transformation for this object.
+   * This method is suitable if you need to define transformation for
+   * individual NIS_Surface. For a group of NIS_Surface instances you can
+   * consider the correspondin method of NIS_SurfaceDrawer (it will be faster) 
+   */
+  Standard_EXPORT void  SetTransformation(const gp_Trsf& theTrsf);
+
   /**
    * Set the display mode: Shading or Wireframe.
    * The default mode is Shading.
@@ -184,6 +232,32 @@ public:
   Standard_EXPORT DisplayMode
                         GetDisplayMode   () const;
 
+  /**
+   * Set the hilight display mode: Shading or Wireframe.
+   * The default mode is Shading.
+   * NOTE: this Function works only in a shading mode when rendering the shape.
+   * If the Shape is rendered in Wireframe mode - the hilight display mode
+   * is wireframe
+   */
+  Standard_EXPORT void  SetHilightDisplayMode   (const DisplayMode theMode);
+
+  /**
+   * Query the current hilight display mode: Shading or Wireframe.
+   */
+  Standard_EXPORT DisplayMode
+                        GetHilightDisplayMode   () const;
+
+  /**
+   * Display free boundary of the surface object with the
+   * specified color   
+   */
+  Standard_EXPORT void  ShowFreeBoundary (const Quantity_Color& theColor);
+
+  /**
+   * Hides special precentation of free boundaries
+   */
+  Standard_EXPORT void  HideFreeBoundary ();
+
   /**
    * Create a copy of theObject except its ID.
    * @param theAll
@@ -193,8 +267,8 @@ public:
    *   passed NULL then the target should be created.
    */
   Standard_EXPORT virtual void
-                          Clone (const Handle_NCollection_BaseAllocator& theAll,
-                                 Handle_NIS_InteractiveObject& theDest) const;
+                        Clone (const Handle_NCollection_BaseAllocator& theAll,
+                               Handle_NIS_InteractiveObject& theDest) const;
 
   /**
    * Intersect the surface shading/wireframe geometry with a line/ray.
@@ -208,8 +282,22 @@ public:
    *   on the ray. May be negative.
    */
   Standard_EXPORT virtual Standard_Real
-                          Intersect     (const gp_Ax1&       theAxis,
-                                         const Standard_Real theOver) const;
+                        Intersect     (const gp_Ax1&       theAxis,
+                                       const Standard_Real theOver) const;
+
+  /**
+   * Query the normal vector at the intersection point of the surface shading 
+   * geometry with a line/ray.
+   * @param theAxis
+   *   The line or ray in 3D space.
+   * @param theNormal
+   *   The normal direction of intersected triangle.
+   * @return
+   *   True if intersection is found and normal direction is computed.
+   */
+  Standard_EXPORT Standard_Boolean
+                        Intersect     (const gp_Ax1& theAxis,
+                                       gp_Vec&       theNormal) const;
 
   /**
    * Intersect the surface shading/wireframe geometry with an oriented box.
@@ -220,12 +308,12 @@ public:
    * @param isFull
    *   True if full inclusion is required, False - if partial.
    * @return
-   *   True if the InteractiveObject geometry intersects the box or is inside it
+   *   True if the InteractiveObject geometry intersects or is inside the box.
    */
   Standard_EXPORT virtual Standard_Boolean
-                             Intersect     (const Bnd_B3f&         theBox,
-                                            const gp_Trsf&         theTrf,
-                                            const Standard_Boolean isFull)const;
+                        Intersect     (const Bnd_B3f&         theBox,
+                                       const gp_Trsf&         theTrf,
+                                       const Standard_Boolean isFull) const;
 
   /**
    * Intersect the surface shading/wireframe geometry with a selection polygon.
@@ -241,10 +329,10 @@ public:
    *   True if the InteractiveObject geometry intersects the polygon or is
    *   inside it
    */
-  Standard_EXPORT virtual Standard_Boolean Intersect
-                    (const NCollection_List<gp_XY> &thePolygon,
-                     const gp_Trsf                 &theTrf,
-                     const Standard_Boolean         isFullIn) const;
+  Standard_EXPORT virtual Standard_Boolean
+                        Intersect  (const NCollection_List<gp_XY> &thePolygon,
+                                    const gp_Trsf                 &theTrf,
+                                    const Standard_Boolean      isFullIn) const;
 
 protected:
 
@@ -262,8 +350,38 @@ protected:
    * Compute normal to the surface at the node with the given index.
    * Returns true if the vertex is artificial at this node.
    */
-  Standard_Boolean computeNormal (Standard_Integer theIndex,
-                                  gp_XYZ& theNormal) const;
+  Standard_EXPORT Standard_Boolean
+                        computeNormal (Standard_Integer theIndex,
+                                       gp_XYZ&          theNormal) const;
+  
+  /**
+   * Auxiulary function computing intersection of an axis with edges.
+   * This function is used in "intersect" functions.
+   */
+  Standard_EXPORT Standard_Real
+                        intersectEdges(const NIS_IndexLists&    theEdges, 
+                                       const gp_Ax1&            theAxis,
+                                       const Standard_Real      theOver) const;
+
+  /**
+   * Auxiulary function computing intersection of an box (2d rectangle) with
+   * edges. This function is used in "intersect" functions.
+   */
+  Standard_EXPORT Standard_Boolean
+                        intersectEdges(const NIS_IndexLists&    theEdges, 
+                                       const gp_Trsf&           theTrf,
+                                       const Bnd_B3f&           theBox,
+                                       const Standard_Boolean   isFullIn)const;
+
+  /**
+   * Auxiulary function computing intersection of a 2d polygon with edges.
+   * This function is used in "intersect" functions.
+   */
+  Standard_EXPORT Standard_Boolean
+                        intersectEdges(const NIS_IndexLists&    theEdges, 
+                                       const gp_Trsf&           theTrf,
+                                       const NCollection_List<gp_XY> &thePolyg,
+                                       const Standard_Boolean   isFullIn)const;
 
 private:
   Handle_NCollection_BaseAllocator myAlloc;
@@ -274,12 +392,16 @@ private:
   //! Array of triangles (node indices)
   Standard_Integer                 * mypTriangles;
   //! Array of edges, each edge is an array of indices prefixed by N nodes
-  Standard_Integer                 ** mypEdges;
+  NIS_IndexLists                   myEdges;
+  //! Array of free edges, each edge is an array of indices prefixed by N nodes
+  NIS_IndexLists                   myFreeEdges;
   //! Number of nodes in triangles
   Standard_Integer                 myNNodes;
-  Standard_Integer                 myNTriangles;
-  Standard_Integer                 myNEdges;
-  Standard_Boolean                 myIsWireframe;
+  Standard_Integer                 myNTriangles         : 28;
+  Standard_Boolean                 myIsWireframe        :  1;
+  Standard_Boolean                 myHilightIsWireframe :  1;
+  Standard_Boolean                 myIsShowFreeBoundary :  1;
+  Standard_Boolean                 myIsShowEdges        :  1;
 
 public:
 // Declaration of CASCADE RTTI
index a7ec1a2b9637bbbeee78b7147196e37573cc2bf6..fdc75b1bd8f121851acdd3bf1dd79f8ce90c452e 100644 (file)
 
 #include <OpenGl_GlCore11.hxx>
 
-static void setColor(GLenum               theFace,
-                     Quantity_Parameter * theAmbient,
-                     const Standard_Real  theSpecularity,
-                     GLint                theShininess);
+static void setColor(Quantity_Parameter *     theAmbientFront,
+                     Quantity_Parameter *     theAmbientBack,
+                     const Standard_ShortReal theSpecularity,
+                     GLint                    theShininess);
 
 IMPLEMENT_STANDARD_HANDLE  (NIS_SurfaceDrawer, NIS_Drawer)
 IMPLEMENT_STANDARD_RTTIEXT (NIS_SurfaceDrawer, NIS_Drawer)
@@ -37,27 +37,17 @@ NIS_SurfaceDrawer::NIS_SurfaceDrawer
                                 (const Quantity_Color   &theNormal,
                                  const Quantity_Color   &theHilight,
                                  const Quantity_Color   &theDynHilight)
-  : myBackColor     (theNormal),
-    myPolygonOffset (0.f),
-    myIsWireframe   (Standard_False)
+  : NIS_Drawer(theHilight, theDynHilight),
+    myBackColor         (theNormal),
+    myFreeEdgeColor     (theNormal),
+    mySpecularity       (0.58f),
+    myPolygonOffset     (0.f),
+    myIsWireframe       (Standard_False),
+    myHilightIsWireframe(Standard_False),
+    myIsShowEdges       (Standard_True)
 {
-  myColor[Draw_Normal]       = theNormal;
-  myColor[Draw_Top]          = theNormal;
-  myColor[Draw_Transparent]  = theNormal;
-  myColor[Draw_Hilighted]    = theHilight;
-  myColor[Draw_DynHilighted] = theDynHilight;
-}
-
-//=======================================================================
-//function : SetColor
-//purpose  :
-//=======================================================================
-
-void NIS_SurfaceDrawer::SetColor(const Quantity_Color &theColor)
-{
-  myColor[Draw_Normal]      = theColor;
-  myColor[Draw_Top]         = theColor;
-  myColor[Draw_Transparent] = theColor;
+  SetColor(Draw_Normal, theNormal);
+  myObjPerDrawer = 4;
 }
 
 //=======================================================================
@@ -71,14 +61,14 @@ void NIS_SurfaceDrawer::Assign (const Handle_NIS_Drawer& theOther)
     NIS_Drawer::Assign (theOther);
     const Handle(NIS_SurfaceDrawer)& anOther =
       static_cast <const Handle(NIS_SurfaceDrawer)&> (theOther);
-    myColor[Draw_Normal]       = anOther->myColor[Draw_Normal];
-    myColor[Draw_Top]          = anOther->myColor[Draw_Top];
-    myColor[Draw_Transparent]  = anOther->myColor[Draw_Transparent];
-    myColor[Draw_Hilighted]    = anOther->myColor[Draw_Hilighted];
-    myColor[Draw_DynHilighted] = anOther->myColor[Draw_DynHilighted];
     myBackColor                = anOther->myBackColor;
+    myFreeEdgeColor            = anOther->myFreeEdgeColor;
+    mySpecularity              = anOther->mySpecularity;
     myPolygonOffset            = anOther->myPolygonOffset;
-    myIsWireframe              = anOther->myIsWireframe;
+    myIsWireframe              = anOther->myIsWireframe;    
+    myHilightIsWireframe       = anOther->myHilightIsWireframe;
+    myIsShowEdges              = anOther->myIsShowEdges;    
+    myTrsf                     = anOther->myTrsf;
   }
 }
 
@@ -90,20 +80,19 @@ void NIS_SurfaceDrawer::Assign (const Handle_NIS_Drawer& theOther)
 Standard_Boolean NIS_SurfaceDrawer::IsEqual
                                 (const Handle_NIS_Drawer& theOther)const
 {
-  static const Standard_Real       anEpsilon2 (1e-7);
   Standard_Boolean                 aResult (Standard_False);
   const Handle(NIS_SurfaceDrawer) anOther =
                         Handle(NIS_SurfaceDrawer)::DownCast (theOther);
   if (NIS_Drawer::IsEqual(theOther))
-    aResult = (anOther->myColor[Draw_Normal]
-               .SquareDistance (myColor[Draw_Normal]) < anEpsilon2 &&
-               anOther->myColor[Draw_Hilighted]
-               .SquareDistance (myColor[Draw_Hilighted]) < anEpsilon2 &&
-               anOther->myColor[Draw_DynHilighted]
-               .SquareDistance (myColor[Draw_DynHilighted]) < anEpsilon2 &&
-               anOther->myBackColor.SquareDistance(myBackColor) < anEpsilon2 &&
+    aResult = (areEqual(anOther->myBackColor, myBackColor) &&
+               areEqual(anOther->myFreeEdgeColor, myFreeEdgeColor) &&
+               fabs(anOther->mySpecularity - mySpecularity) < 0.01 &&
                fabs(anOther->myPolygonOffset - myPolygonOffset) < 0.999 &&
-               myIsWireframe == anOther->myIsWireframe);
+               myIsWireframe == anOther->myIsWireframe && 
+               myHilightIsWireframe == anOther->myHilightIsWireframe &&
+               myIsShowEdges == anOther->myIsShowEdges && 
+               fabs(anOther->myTrsf.TranslationPart().SquareModulus() -
+                    myTrsf.TranslationPart().SquareModulus()) < 0.0001);
   if (aResult) {
     // Arbitrary point for test
     gp_XYZ aPnt[2] = {
@@ -112,7 +101,7 @@ Standard_Boolean NIS_SurfaceDrawer::IsEqual
     };
     anOther->myTrsf.Transforms(aPnt[0]);
     myTrsf.Transforms(aPnt[1]);
-    if ((aPnt[0] - aPnt[1]).SquareModulus() > anEpsilon2)
+    if ((aPnt[0] - aPnt[1]).SquareModulus() > 1e-6)
       aResult = Standard_False;
   }
   return aResult;
@@ -152,7 +141,6 @@ void NIS_SurfaceDrawer::BeforeDraw (const DrawType      theType,
                                     const NIS_DrawList&)
 {
   glEnable(GL_LIGHTING);
-  //  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
   glEnableClientState (GL_VERTEX_ARRAY);
   if (myIsWireframe == Standard_False) {
     glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
@@ -160,24 +148,45 @@ void NIS_SurfaceDrawer::BeforeDraw (const DrawType      theType,
     glShadeModel(GL_SMOOTH);
   }
 
-  Quantity_Parameter   aValueCol[4] = {0., 0., 0., 1.};
+  Quantity_Parameter aValueCol[][4] = {
+    {0., 0., 0., 1. - myTransparency},           // front color
+    {0., 0., 0., 1. - myTransparency}            // back color
+  };
+  Quantity_Color aBackColor = myBackColor;
   Quantity_TypeOfColor bidTC (Quantity_TOC_RGB);
   GLfloat aLineWidth (1.f);
   GLfloat anOffset = myPolygonOffset;
-  static const GLfloat gColorN[4]  = {0.f, 0.f, 0.f, 1.f};
+  DrawType aDrawType = theType;
+  myIsBlend = Standard_False;
 
   switch (theType) {
-  case Draw_DynHilighted:
-    aLineWidth = 3.f;
-    myColor[theType].Values (aValueCol[0], aValueCol[1], aValueCol[2], bidTC);
-    setColor(GL_FRONT_AND_BACK, &aValueCol[0], 0.1, 5);
-    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &gColorN[0]);
-    glLineWidth (aLineWidth);
-    if (myIsWireframe == Standard_False)
-      glPolygonOffset(1.f, -(anOffset + 11.f));
-    return;
   case Draw_Hilighted:
+    if (myHilightIsWireframe)
+    {
+      aDrawType = Draw_Normal;
+      glEnableClientState (GL_NORMAL_ARRAY);
+      if (myTransparency > 0.) {
+        glEnable(GL_BLEND);
+        glEnable(GL_CULL_FACE);
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        // don't write triangles into depth test
+        glDepthMask(GL_FALSE);
+        myIsBlend = Standard_True;
+      }      
+  case Draw_DynHilighted:  
+      aLineWidth = 3.f;
+      GetColor(aDrawType).Values(aValueCol[0][0], aValueCol[0][1],
+                                 aValueCol[0][2], bidTC);
+      aBackColor.Values(aValueCol[1][0],aValueCol[1][1],aValueCol[1][2], bidTC);
+      setColor(aValueCol[0], aValueCol[1], mySpecularity, 10);
+
+      glLineWidth (aLineWidth);
+      if (myIsWireframe == Standard_False)
+        glPolygonOffset(1.f, -(anOffset + 11.f));
+      return;
+    }    
     anOffset += 10.f;
+    aBackColor = GetColor(theType);
   case Draw_Normal:
   case Draw_Top:
   case Draw_Transparent:
@@ -185,29 +194,23 @@ void NIS_SurfaceDrawer::BeforeDraw (const DrawType      theType,
       glPolygonOffset(1.f, -anOffset);
       glEnableClientState (GL_NORMAL_ARRAY);
     }
-    myColor[theType].Values (aValueCol[0], aValueCol[1], aValueCol[2], bidTC);
-    aValueCol[3] = 1. - myTransparency;
+    GetColor(theType).Values(aValueCol[0][0], aValueCol[0][1],
+                             aValueCol[0][2], bidTC);
+    aBackColor.Values(aValueCol[1][0], aValueCol[1][1], aValueCol[1][2], bidTC);
     if (theType == Draw_Transparent) {
       glEnable(GL_BLEND);
+      glEnable(GL_CULL_FACE);
       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-      // don't write triangles into depth test
-      glDepthMask(GL_FALSE);
+      myIsBlend = Standard_True;
     }
     break;
   default:
     return;
   }
-  //  glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
-  if (theType == Draw_Hilighted ||
-      myBackColor.SquareDistance(myColor[Draw_Normal]) < 1.e-7)
-  {
-    setColor(GL_FRONT_AND_BACK, &aValueCol[0], 0.5, 10);
-  } else {
-    setColor(GL_FRONT, &aValueCol[0], 0.4, 10);
-    myBackColor.Values (aValueCol[0], aValueCol[1], aValueCol[2], bidTC);
-    setColor(GL_BACK, &aValueCol[0], 0.8, 5);
-  }
-  glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &gColorN[0]);
+  glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
+  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
+  setColor(aValueCol[0], aValueCol[1], mySpecularity, 10);
+
   glLineWidth (aLineWidth);
 }
 
@@ -221,17 +224,23 @@ void NIS_SurfaceDrawer::AfterDraw (const DrawType      theType,
 {
   glDisable(GL_LIGHTING);
   glDisableClientState(GL_VERTEX_ARRAY);
-  switch (theType) {
-    case Draw_Transparent:
+  if (theType != Draw_DynHilighted)
+  {
+    if (myIsBlend)
+    {
       glDisable(GL_BLEND);
-      glDepthMask(GL_TRUE);
-    case Draw_Hilighted:
-    case Draw_Normal:
-    case Draw_Top:
-      if (myIsWireframe == Standard_False)
-        glDisableClientState(GL_NORMAL_ARRAY);
-    default:;
+      glDisable(GL_CULL_FACE);
+      if (theType == Draw_Hilighted)
+      {
+        glDepthMask (GL_TRUE);
+      }
+    }
+    if (myIsWireframe == Standard_False)
+    {
+      glDisableClientState(GL_NORMAL_ARRAY);      
+    }
   }
+  
   if (myIsWireframe == Standard_False)
     glDisable(GL_POLYGON_OFFSET_FILL);
 }
@@ -258,23 +267,67 @@ void NIS_SurfaceDrawer::Draw (const Handle_NIS_InteractiveObject& theObj,
   // In Highlited mode the shape must be shown as wireframe
   Standard_Boolean isWireframe(myIsWireframe);
   if (isWireframe == Standard_False && theType == Draw_DynHilighted)
-    if (pObject->NEdges() > 0)
+    if (pObject->NEdges() > 0 || pObject->NFreeEdges() > 0)
       isWireframe = Standard_True;
 
-  if (isWireframe)
-  {
-    for (Standard_Integer i = 0; i < pObject->NEdges(); i++) {
-      const GLint * pEdge = static_cast<const GLint *> (pObject->Edge(i));
-      glDrawElements (GL_LINE_STRIP, pEdge[0], GL_UNSIGNED_INT, &pEdge[1]);
-    }
-  } else {
+  if (!isWireframe)
+  {    
     if (pObject->NTriangles()) {
       if (theType != Draw_DynHilighted)
         glNormalPointer (GL_FLOAT, 0, pObject->Normal(0));
+      if (myIsBlend) {
+        // Drawing BACK faces before FRONT ones improves the transparency
+        glCullFace(GL_FRONT);
+        glDrawElements (GL_TRIANGLES, pObject->NTriangles()*3,
+                        GL_UNSIGNED_INT, pObject->Triangle(0));
+        glCullFace(GL_BACK);
+      }
       glDrawElements (GL_TRIANGLES, pObject->NTriangles()*3,
                       GL_UNSIGNED_INT, pObject->Triangle(0));
     }
   }
+  if (myIsShowEdges || isWireframe || pObject->IsShowFreeBounds() ||
+      (theType == Draw_Hilighted && myHilightIsWireframe == Standard_True))
+  {
+    if (pObject->NEdges() > 0 || pObject->NFreeEdges() > 0) {
+      glDisable (GL_LIGHTING);
+      Quantity_Parameter R1, R2, R3;
+      GetColor(theType).Values(R1, R2, R3, Quantity_TOC_RGB);
+      glColor3d (R1, R2, R3);
+      drawEdges(pObject, theType);
+      glEnable (GL_LIGHTING);
+    }
+  }
+}
+
+//=======================================================================
+//function : drawEdges 
+//purpose  : 
+//=======================================================================
+
+void NIS_SurfaceDrawer::drawEdges (const NIS_Surface * pObject,
+                                   const DrawType    theType)
+{
+  // Draw non-free edges
+  for (Standard_Integer i = 0; i < pObject->NEdges(); i++) {        
+    glDrawElements (GL_LINE_STRIP, pObject->NEdgeNodeInList(i),
+                    GL_UNSIGNED_INT, pObject->Edge(i));
+  }
+
+  // Set color to show free edges, if they are requested
+  if (pObject->IsShowFreeBounds() && theType != Draw_DynHilighted &&
+      !(theType == Draw_Hilighted && myHilightIsWireframe == Standard_True))
+  {
+    Quantity_Parameter R1, R2, R3;
+    myFreeEdgeColor.Values(R1, R2, R3, Quantity_TOC_RGB);
+    glColor3d (R1, R2, R3);
+    glLineWidth (2.5f);
+  }
+
+  // Draw free edges
+  for (Standard_Integer i = 0; i < pObject->NFreeEdges(); i++)
+    glDrawElements (GL_LINE_STRIP, pObject->NFreeEdgeNodeInList(i),
+                    GL_UNSIGNED_INT, pObject->FreeEdge(i));
 }
 
 //=======================================================================
@@ -282,24 +335,38 @@ void NIS_SurfaceDrawer::Draw (const Handle_NIS_InteractiveObject& theObj,
 //purpose  :
 //=======================================================================
 
-void setColor(GLenum               theFace,
-              Quantity_Parameter * theAmbient,
-              const Standard_Real  theSpecularity,
-              GLint                theShininess)
+void setColor(Quantity_Parameter *     theAmbientFront,
+              Quantity_Parameter *     theAmbientBack,
+              const Standard_ShortReal theSpecularity,
+              GLint                    theShininess)
 {
-  GLfloat aSpec = static_cast<GLfloat>(theSpecularity);
+  static const GLfloat gColorN[4]  = {0.f, 0.f, 0.f, 1.f};
   GLfloat aValueCol[4] = {
-    GLfloat(theAmbient[0]),
-    GLfloat(theAmbient[1]),
-    GLfloat(theAmbient[2]),
-    GLfloat(theAmbient[3])
+    GLfloat(theAmbientFront[0]),
+    GLfloat(theAmbientFront[1]),
+    GLfloat(theAmbientFront[2]),
+    GLfloat(theAmbientFront[3])
   };
-  glMaterialfv(theFace, GL_AMBIENT_AND_DIFFUSE, &aValueCol[0]);
-  aValueCol[0] = aSpec * (aValueCol[0] - 1.f) + 1.f;
-  aValueCol[1] = aSpec * (aValueCol[1] - 1.f) + 1.f;
-  aValueCol[2] = aSpec * (aValueCol[2] - 1.f) + 1.f;
+  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, &aValueCol[0]);
+
+  aValueCol[0] = GLfloat(theAmbientBack[0]);
+  aValueCol[1] = GLfloat(theAmbientBack[1]);
+  aValueCol[2] = GLfloat(theAmbientBack[2]);
+  aValueCol[3] = GLfloat(theAmbientBack[3]);
+  glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, &aValueCol[0]);
+
+  const GLfloat aSpec(theSpecularity < 0. ? 0.f :
+                      theSpecularity > 1.f ? 1.f :
+                      theSpecularity);
+  aValueCol[0] = aSpec;
+  aValueCol[1] = aSpec;
+  aValueCol[2] = aSpec;
   aValueCol[3] = 1.f;
-  glMaterialfv(theFace, GL_SPECULAR, &aValueCol[0]);
-  glMateriali(theFace, GL_SHININESS, theShininess);
+  glMaterialfv(GL_FRONT, GL_SPECULAR, &aValueCol[0]);
+  glMateriali(GL_FRONT, GL_SHININESS, theShininess);
+  glMaterialfv(GL_BACK, GL_SPECULAR, &aValueCol[0]);
+  glMateriali(GL_BACK, GL_SHININESS, theShininess);
+  glMaterialfv(GL_FRONT, GL_EMISSION, &gColorN[0]);
+  glMaterialfv(GL_BACK, GL_EMISSION, &gColorN[0]);
 }
 
index 7da1fc76f0d93bbdf1e855111c74000ddde6085c..b683d5317fecbcb01688b6bee42cf1ee3ba179ae 100644 (file)
 
 #include <NIS_Drawer.hxx>
 #include <gp_Trsf.hxx>
-#include <Quantity_Color.hxx>
+//#include <Quantity_Color.hxx>
 
 class NIS_Surface;
 
 /**
  * Drawer for interactive object type NIS_Surface.
+ * @ingroup nis_library
  */
 
 class NIS_SurfaceDrawer : public NIS_Drawer
@@ -40,11 +41,6 @@ class NIS_SurfaceDrawer : public NIS_Drawer
                                     const Quantity_Color   &theDynHilight
                                                         = Quantity_NOC_CYAN1);
 
-  /**
-   * Sets the color of the drawer.
-   */
-  Standard_EXPORT void         SetColor (const Quantity_Color &theColor);
-
   /**
    * Define the color used for the back side of rendered triangles.
    * By default this color is the same as the 'Normal' color. 
@@ -54,6 +50,15 @@ class NIS_SurfaceDrawer : public NIS_Drawer
     myBackColor = theColor;
   }
 
+  /**
+   * Define the specularity that is the property of displayed material for both
+   * Front and Back faces. Can be in the range 0 to 1. Default value is 0.58
+   */
+  inline void                   SetSpecularity   (const Standard_Real theValue)
+  {
+    mySpecularity = static_cast<Standard_ShortReal>(theValue);
+  } 
+
   /**
    * Sets the transformation to the drawer.
    */
@@ -117,17 +122,26 @@ class NIS_SurfaceDrawer : public NIS_Drawer
   Standard_EXPORT virtual Standard_Boolean
                                IsEqual  (const Handle_NIS_Drawer& theOth)const;
 
- protected:
+
+protected:
   Standard_EXPORT virtual void redraw   (const DrawType         theType,
                                          const Handle_NIS_View& theView);
 
+private:
+  void                  drawEdges       (const NIS_Surface *    pObject,
+                                         const DrawType         theType);
 
 private:
-  Quantity_Color      myColor[5];
   Quantity_Color      myBackColor;
+  Quantity_Color      myFreeEdgeColor;
+  Standard_ShortReal  mySpecularity;
   gp_Trsf             myTrsf;
   Standard_ShortReal  myPolygonOffset;
-  Standard_Boolean    myIsWireframe;
+  Standard_Boolean    myIsWireframe;  
+  Standard_Boolean    myHilightIsWireframe;  
+  Standard_Boolean    myIsShowEdges;  
+
+  Standard_Boolean    myIsBlend;        // defined and used internally
 
   friend class NIS_Surface;
 
diff --git a/src/NIS/NIS_Text.cxx b/src/NIS/NIS_Text.cxx
new file mode 100644 (file)
index 0000000..79e41d9
--- /dev/null
@@ -0,0 +1,210 @@
+// File:      NIS_Text.cxx
+// Created:   12.12.11 07:16
+// Author:    Alexander GRIGORIEV
+// Copyright: Open Cascade 2011
+
+#include <NIS_Text.hxx>
+#include <NIS_TextDrawer.hxx>
+
+IMPLEMENT_STANDARD_HANDLE  (NIS_Text, NIS_InteractiveObject)
+IMPLEMENT_STANDARD_RTTIEXT (NIS_Text, NIS_InteractiveObject)
+
+//=======================================================================
+//function : NIS_Text()
+//purpose  : Constructor
+//=======================================================================
+
+NIS_Text::NIS_Text (const char * theText)
+  : myText         (theText? theText : ""),
+    myPosition     (gp_XYZ(0., 0., 0.))
+{
+}
+
+//=======================================================================
+//function : SetText
+//purpose  : Initialization with a text string
+//=======================================================================
+
+void NIS_Text::SetText (const char * theText)
+{
+  myText = theText;
+  if (GetDrawer().IsNull() == Standard_False)
+    setDrawerUpdate();
+}
+
+//=======================================================================
+//function : SetPosition
+//purpose  : Initialization with the text position
+//=======================================================================
+
+void NIS_Text::SetPosition (const gp_XYZ& thePosition)
+{
+  myPosition = thePosition;
+  if (GetDrawer().IsNull() == Standard_False)
+    setDrawerUpdate();  
+}
+
+//=======================================================================
+//function : SetFontFamily
+//purpose  : Define the font type (family).
+//=======================================================================
+
+void NIS_Text::SetFontFamily (const FontFamily theFamily)
+{
+  const Handle(NIS_TextDrawer) aDrawer =
+    static_cast<NIS_TextDrawer *>(DefaultDrawer(0L));
+  aDrawer->Assign (GetDrawer());
+  aDrawer->myFontFamily = theFamily;
+  const NIS_TextDrawer * pDrawer =
+    static_cast<const NIS_TextDrawer *>(SetDrawer(aDrawer).operator->());
+  pDrawer->SetFontUpdated();
+}
+
+//=======================================================================
+//function : SetFontWeight
+//purpose  : Define the font weight.
+//=======================================================================
+
+void NIS_Text::SetFontWeight (const FontWeight theWeight)
+{
+  const Handle(NIS_TextDrawer) aDrawer =
+    static_cast<NIS_TextDrawer *>(DefaultDrawer(0L));
+  aDrawer->Assign (GetDrawer());
+  aDrawer->myFontWeight = theWeight;
+  const NIS_TextDrawer * pDrawer =
+    static_cast<const NIS_TextDrawer *>(SetDrawer(aDrawer).operator->());
+  pDrawer->SetFontUpdated();
+}
+
+//=======================================================================
+//function : SetFontCharset
+//purpose  : Define the charset of the created font.
+//=======================================================================
+
+void NIS_Text::SetFontCharset (const FontCharset theCharset)
+{
+  const Handle(NIS_TextDrawer) aDrawer =
+    static_cast<NIS_TextDrawer *>(DefaultDrawer(0L));
+  aDrawer->Assign (GetDrawer());
+  aDrawer->myFontCharset = theCharset;
+  const NIS_TextDrawer * pDrawer =
+    static_cast<const NIS_TextDrawer *>(SetDrawer(aDrawer).operator->());
+  pDrawer->SetFontUpdated();
+}
+
+//=======================================================================
+//function : SetFontHeight
+//purpose  : Define the character height in pixels.
+//=======================================================================
+
+void NIS_Text::SetFontHeight (const Standard_Integer theValue)
+{
+  const Handle(NIS_TextDrawer) aDrawer =
+    static_cast<NIS_TextDrawer *>(DefaultDrawer(0L));
+  aDrawer->Assign (GetDrawer());
+  aDrawer->myFontHeight = theValue;
+  const NIS_TextDrawer * pDrawer =
+    static_cast<const NIS_TextDrawer *>(SetDrawer(aDrawer).operator->());
+  pDrawer->SetFontUpdated();
+}
+
+//=======================================================================
+//function : SetFontAngle
+//purpose  : Define the angle of the text relative to OX.
+//=======================================================================
+
+void NIS_Text::SetFontAngle (const Standard_Real theValue)
+{
+  const Handle(NIS_TextDrawer) aDrawer =
+    static_cast<NIS_TextDrawer *>(DefaultDrawer(0L));
+  aDrawer->Assign (GetDrawer());
+  aDrawer->myFontAngle =
+    static_cast<Standard_Integer>(0.1 + (theValue * 1800) / M_PI);
+  const NIS_TextDrawer * pDrawer =
+    static_cast<const NIS_TextDrawer *>(SetDrawer(aDrawer).operator->());
+  pDrawer->SetFontUpdated();
+}
+
+//=======================================================================
+//function : SetItalic
+//purpose  : Defines if italic font type to use.
+//=======================================================================
+
+void NIS_Text::SetItalic (const Standard_Boolean isItalic)
+{
+  const Handle(NIS_TextDrawer) aDrawer =
+    static_cast<NIS_TextDrawer *>(DefaultDrawer(0L));
+  aDrawer->Assign (GetDrawer());
+  aDrawer->myIsItalic = isItalic;
+  const NIS_TextDrawer * pDrawer =
+    static_cast<const NIS_TextDrawer *>(SetDrawer(aDrawer).operator->());
+  pDrawer->SetFontUpdated();
+}
+
+//=======================================================================
+//function : SetUnderline
+//purpose  : Defines if Underline font to use.
+//=======================================================================
+
+void NIS_Text::SetUnderline (const Standard_Boolean isUnderline)
+{
+  const Handle(NIS_TextDrawer) aDrawer =
+    static_cast<NIS_TextDrawer *>(DefaultDrawer(0L));
+  aDrawer->Assign (GetDrawer());
+  aDrawer->myIsUnderline = isUnderline;
+  const NIS_TextDrawer * pDrawer =
+    static_cast<const NIS_TextDrawer *>(SetDrawer(aDrawer).operator->());
+  pDrawer->SetFontUpdated();
+}
+
+//=======================================================================
+//function : DefaultDrawer
+//purpose  : Create a default drawer instance.
+//=======================================================================
+
+NIS_Drawer * NIS_Text::DefaultDrawer (NIS_Drawer * theDrawer) const
+{
+  if (!theDrawer)
+    theDrawer = new NIS_TextDrawer;
+  return theDrawer;
+}
+
+//=======================================================================
+//function : Clone
+//purpose  : 
+//=======================================================================
+
+void NIS_Text::Clone (const Handle_NCollection_BaseAllocator& theAllocator,
+                      Handle_NIS_InteractiveObject&           theDest) const
+{
+  Handle(NIS_Text) aNewObj;
+  if (theDest.IsNull()) {
+    aNewObj = new NIS_Text();
+    theDest = aNewObj;
+  } else {
+    aNewObj = reinterpret_cast<NIS_Text*> (theDest.operator->());
+  }
+  NIS_InteractiveObject::Clone(theAllocator, theDest);  
+  aNewObj->myText = myText;
+  aNewObj->myPosition = myPosition;
+}
+
+//=======================================================================
+//function : Intersect
+//purpose  : 
+//=======================================================================
+
+Standard_Real NIS_Text::Intersect (const gp_Ax1&       /*theAxis*/,
+                                   const Standard_Real /*theOver*/) const
+{
+  return RealLast();
+}
+
+//=======================================================================
+//function : computeBox
+//purpose  : empty method
+//=======================================================================
+
+void NIS_Text::computeBox ()
+{
+}
diff --git a/src/NIS/NIS_Text.hxx b/src/NIS/NIS_Text.hxx
new file mode 100644 (file)
index 0000000..506d88e
--- /dev/null
@@ -0,0 +1,177 @@
+// File:      NIS_Text.hxx
+// Created:   12.12.11 06:54
+// Author:    Alexander GRIGORIEV
+// Copyright: Open Cascade 2011
+
+
+#ifndef NIS_Text_HeaderFile
+#define NIS_Text_HeaderFile
+
+#include <NIS_InteractiveObject.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <gp_XYZ.hxx>
+
+class NIS_TextDrawer;
+
+/**
+ * Bitmap Text presentation.
+ * @ingroup nis_library
+ */
+
+class NIS_Text : public NIS_InteractiveObject
+{
+ public:
+  enum FontFamily {
+    FontFamily_DEFAULT = 0,
+    FontFamily_Decorative,
+    FontFamily_Modern,
+    FontFamily_Roman,
+    FontFamily_Script,
+    FontFamily_Swiss,
+    FontFamily_Times,
+    FontFamily_Helvetica,
+    FontFamily_Lucida,
+    FontFamily_Courier,
+    FontFamily_Symbol
+  };
+
+  enum FontWeight {
+    FontWeight_DEFAULT = 0,
+    FontWeight_Thin,
+    FontWeight_Extralight,
+    FontWeight_Ultralight,
+    FontWeight_Light,
+    FontWeight_Book,
+    FontWeight_Normal,
+    FontWeight_Regular,
+    FontWeight_Medium,
+    FontWeight_Semibold,
+    FontWeight_Demibold,
+    FontWeight_Bold,
+    FontWeight_Extrabold,
+    FontWeight_Ultrabold,
+    FontWeight_Heavy,
+    FontWeight_Black
+  };
+
+  enum FontCharset {
+    FontCharset_DEFAULT = 0,
+    FontCharset_ANSI,
+    FontCharset_EastEurope,
+    FontCharset_Greek,
+    FontCharset_Russian,
+    FontCharset_Chinese,
+    FontCharset_Symbol,
+    FontCharset_Turkish,
+    FontCharset_Hebrew,
+    FontCharset_Arabic
+  };
+
+ public:
+  // ---------- PUBLIC METHODS ----------
+
+
+  /**
+   * Empty constructor.
+   */
+  Standard_EXPORT       NIS_Text        (const char * theText = 0L);
+
+  /**
+   * Initialization with a text string
+   */
+  Standard_EXPORT void  SetText         (const char * theText);
+
+  /**
+   * Initialization with the text position
+   */
+  Standard_EXPORT void  SetPosition     (const gp_XYZ& thePosition);
+
+  /**
+   * Define the font type (family).
+   */
+  Standard_EXPORT void  SetFontFamily   (const FontFamily theFamily);
+
+  /**
+   * Define the font weight.
+   */
+  Standard_EXPORT void  SetFontWeight   (const FontWeight theWeight);
+
+  /**
+   * Define the charset of the created font.
+   */
+  Standard_EXPORT void  SetFontCharset  (const FontCharset theCharset);
+
+  /**
+   * Define the character height in pixels.
+   */
+  Standard_EXPORT void  SetFontHeight   (const Standard_Integer theValue);
+
+  /**
+   * Define the angle of the text relative to OX.
+   */
+  Standard_EXPORT void  SetFontAngle    (const Standard_Real theValue);
+
+  /**
+   * Defines if italic font type to use.
+   */
+  Standard_EXPORT void  SetItalic
+                        (const Standard_Boolean isItalic = Standard_True);
+
+  /**
+   * Defines if Underline font to use.
+   */
+  Standard_EXPORT void  SetUnderline
+                        (const Standard_Boolean isUnderline = Standard_True);
+
+  /**
+   * Create a default drawer instance.
+   */
+  Standard_EXPORT virtual NIS_Drawer *
+                        DefaultDrawer   (NIS_Drawer *) const;
+
+  /**
+   * Create a copy of theObject except its ID.
+   * @param theAll
+   *   Allocator where the Dest should store its private data.
+   * @param theDest
+   *   <tt>[in-out]</tt> The target object where the data are copied. If
+   *   passed NULL then the target should be created.
+   */
+  Standard_EXPORT virtual void
+                        Clone (const Handle_NCollection_BaseAllocator& theAll,
+                               Handle_NIS_InteractiveObject& theDest) const;
+
+  /**
+   * Intersect method - empty implementation.
+   */
+  Standard_EXPORT virtual Standard_Real
+                        Intersect       (const gp_Ax1&       theAxis,
+                                         const Standard_Real theOver) const;
+
+
+ protected:
+  // ---------- PROTECTED METHODS ----------
+
+  /**
+   * Create a 3D bounding box of the object.
+   */
+  Standard_EXPORT virtual void
+                        computeBox      ();
+
+ private:
+  // ---------- PRIVATE FIELDS ----------
+
+  TCollection_AsciiString       myText;
+  gp_XYZ                        myPosition;
+
+ public:
+// Declaration of CASCADE RTTI
+DEFINE_STANDARD_RTTI (NIS_Text)
+friend class NIS_TextDrawer;
+};
+
+// Definition of HANDLE object using Standard_DefineHandle.hxx
+DEFINE_STANDARD_HANDLE (NIS_Text, NIS_InteractiveObject)
+
+
+#endif
diff --git a/src/NIS/NIS_TextDrawer.cxx b/src/NIS/NIS_TextDrawer.cxx
new file mode 100644 (file)
index 0000000..039fd1e
--- /dev/null
@@ -0,0 +1,297 @@
+// File:      NIS_TextDrawer.cxx
+// Created:   12.12.11 07:37
+// Author:    Alexander GRIGORIEV
+// Copyright: Open Cascade 2011
+
+#include <NIS_TextDrawer.hxx>
+#ifdef WNT
+#ifdef NOGDI
+#undef NOGDI
+#endif
+#ifdef NOUSER
+#undef NOUSER
+#endif
+#include <windows.h>
+#endif
+#include <GL/gl.h>
+
+IMPLEMENT_STANDARD_HANDLE  (NIS_TextDrawer, NIS_Drawer)
+IMPLEMENT_STANDARD_RTTIEXT (NIS_TextDrawer, NIS_Drawer)
+
+//=======================================================================
+//function : NIS_TextDrawer()
+//purpose  : Constructor
+//=======================================================================
+
+NIS_TextDrawer::NIS_TextDrawer (  )
+  : myFontFamily        (NIS_Text::FontFamily_DEFAULT),
+    myFontWeight        (NIS_Text::FontWeight_Normal),
+    myFontCharset       (NIS_Text::FontCharset_ANSI),
+    myFontHeight        (18),
+    myFontAngle         (0),
+    myIsItalic          (Standard_False),
+    myIsUnderline       (Standard_False)
+{
+  SetCompiled(Standard_False);
+}
+
+//=======================================================================
+//function : createDefaultList
+//purpose  : 
+//=======================================================================
+
+NIS_DrawList* NIS_TextDrawer::createDefaultList
+                        (const Handle_NIS_View& theView) const
+{
+  return new DrawList(theView);
+}
+
+//=======================================================================
+//function : SetListID
+//purpose  : 
+//=======================================================================
+
+void NIS_TextDrawer::DrawList::SetListID (const NIS_Drawer::DrawType theType,
+                                          const Standard_Size        nLists)
+{
+  myListID[theType] = (Standard_Integer)glGenLists(nLists);
+}
+
+//=======================================================================
+//function : Assign
+//purpose  : 
+//=======================================================================
+
+void NIS_TextDrawer::Assign (const Handle_NIS_Drawer& theOther)
+{
+  if (theOther.IsNull() == Standard_False) {
+    NIS_Drawer::Assign(theOther);
+    const Handle(NIS_TextDrawer)& anOther =
+      static_cast <const Handle(NIS_TextDrawer)&> (theOther);
+    myFontFamily  = anOther->myFontFamily;
+    myFontWeight  = anOther->myFontWeight;
+    myFontCharset = anOther->myFontCharset;
+    myFontHeight  = anOther->myFontHeight;
+    myFontAngle   = anOther->myFontAngle;
+    myIsItalic    = anOther->myIsItalic;
+    myIsUnderline = anOther->myIsUnderline;
+  }
+}
+
+//=======================================================================
+//function : IsEqual
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean NIS_TextDrawer::IsEqual
+                                (const Handle_NIS_Drawer& theOther) const
+{
+  Standard_Boolean aResult (Standard_False);
+  if (NIS_Drawer::IsEqual(theOther)) {
+    const Handle(NIS_TextDrawer) anOther =
+      Handle(NIS_TextDrawer)::DownCast(theOther);
+    aResult = (myFontFamily == anOther->myFontFamily &&
+               myFontWeight == anOther->myFontWeight &&
+               myFontCharset == anOther->myFontCharset &&
+               myFontHeight == anOther->myFontHeight &&
+               myFontAngle == anOther->myFontAngle &&
+               myIsItalic == anOther->myIsItalic &&
+               myIsUnderline == anOther->myIsUnderline);
+  }
+  return aResult;
+}
+
+//=======================================================================
+//function : SetFontUpdated
+//purpose  : 
+//=======================================================================
+
+void NIS_TextDrawer::SetFontUpdated () const
+{
+  NCollection_List<NIS_DrawList*>::Iterator anIter(myLists);
+  for (; anIter.More(); anIter.Next()) {
+    DrawList* pList = static_cast<DrawList *>(anIter.Value());
+    if (pList)
+      pList->IsFontUpdated = Standard_True;
+  }
+}
+
+//=======================================================================
+//function : BeforeDraw
+//purpose  : 
+//=======================================================================
+
+void NIS_TextDrawer::BeforeDraw(const DrawType      theType,
+                                const NIS_DrawList& theDrawList)
+{
+  // indicate start of glyph display lists
+  const DrawList& aList = static_cast<const DrawList&> (theDrawList);
+
+  if (aList.IsFontUpdated || aList.GetListID(Draw_Normal) == 0)
+    updateFontBitmaps(const_cast<DrawList&>(aList));
+  glListBase (aList.GetListID(Draw_Normal));
+
+  Quantity_Parameter aValue[4];
+  const Quantity_TypeOfColor bidTC (Quantity_TOC_RGB);
+  GetColor(theType).Values (aValue[0], aValue[1], aValue[2], bidTC);
+  aValue[3] = 1. - myTransparency;
+  if (theType == Draw_Transparent && myTransparency > 0.01) {
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  }
+  glColor4d (aValue[0], aValue[1], aValue[2], aValue[3]);
+
+  glDisable(GL_LIGHTING);  
+}
+
+//=======================================================================
+//function : AfterDraw
+//purpose  : 
+//=======================================================================
+
+void NIS_TextDrawer::AfterDraw(const DrawType         theType,
+                               const NIS_DrawList&    /*theDrawList*/)
+{
+  if (theType == Draw_Transparent && myTransparency > 0.01)
+    glDisable(GL_BLEND);
+}
+
+//=======================================================================
+//function : Draw
+//purpose  : Display the given interactive object in the given view.
+//=======================================================================
+
+void NIS_TextDrawer::Draw (const Handle_NIS_InteractiveObject& theObj,
+                           const DrawType                      /*theType*/,
+                           const NIS_DrawList&                 /*theDrawList*/)
+{
+  const NIS_Text * pObj = static_cast<const NIS_Text *>(theObj.operator->());
+
+  glRasterPos3d(pObj->myPosition.X(),pObj->myPosition.Y(),pObj->myPosition.Z());
+  // display a string:
+  glCallLists (pObj->myText.Length(), GL_UNSIGNED_BYTE,
+               pObj->myText.ToCString());
+}
+
+//=======================================================================
+//function : updateFontBitmaps
+//purpose  : 
+//=======================================================================
+
+void NIS_TextDrawer::updateFontBitmaps (NIS_TextDrawer::DrawList& theList)
+{
+  if (theList.GetListID(Draw_Normal) == 0) {
+    theList.SetListID(Draw_Normal, 256);
+  }
+
+#ifdef WNT
+  int aWeight, aFamily, aCharset;
+  switch (myFontWeight) {
+    default:
+    case NIS_Text::FontWeight_DEFAULT:
+      aWeight = FW_DONTCARE; break;
+    case NIS_Text::FontWeight_Thin:
+      aWeight = FW_THIN; break;      
+    case NIS_Text::FontWeight_Extralight:
+      aWeight = FW_EXTRALIGHT; break;      
+    case NIS_Text::FontWeight_Ultralight:
+      aWeight = FW_ULTRALIGHT; break;      
+    case NIS_Text::FontWeight_Book:
+    case NIS_Text::FontWeight_Light:
+      aWeight = FW_LIGHT; break;      
+    case NIS_Text::FontWeight_Normal:
+      aWeight = FW_NORMAL; break;      
+    case NIS_Text::FontWeight_Regular:
+      aWeight = FW_REGULAR; break;      
+    case NIS_Text::FontWeight_Medium:
+      aWeight = FW_MEDIUM; break;      
+    case NIS_Text::FontWeight_Semibold:
+      aWeight = FW_SEMIBOLD; break;      
+    case NIS_Text::FontWeight_Demibold:
+      aWeight = FW_DEMIBOLD; break;      
+    case NIS_Text::FontWeight_Bold:
+      aWeight = FW_BOLD; break;      
+    case NIS_Text::FontWeight_Extrabold:
+      aWeight = FW_EXTRABOLD; break;      
+    case NIS_Text::FontWeight_Ultrabold:
+      aWeight = FW_ULTRABOLD; break;      
+    case NIS_Text::FontWeight_Heavy:
+      aWeight = FW_HEAVY; break;      
+    case NIS_Text::FontWeight_Black:    
+      aWeight = FW_BLACK; break;      
+  }
+  switch (myFontFamily) {
+    case NIS_Text::FontFamily_Decorative:
+      aFamily = FF_DECORATIVE; break;
+    case NIS_Text::FontFamily_Courier:
+    case NIS_Text::FontFamily_Modern:
+      aFamily = FF_MODERN; break;
+    case NIS_Text::FontFamily_Times:
+    case NIS_Text::FontFamily_Roman:
+      aFamily = FF_ROMAN; break;
+    case NIS_Text::FontFamily_Lucida:
+    case NIS_Text::FontFamily_Script:
+      aFamily = FF_SCRIPT; break;
+    case NIS_Text::FontFamily_Helvetica:
+    case NIS_Text::FontFamily_Swiss:
+      aFamily = FF_SWISS; break;
+    case NIS_Text::FontFamily_Symbol:
+    default:
+    case NIS_Text::FontFamily_DEFAULT:
+      aFamily = FF_DONTCARE; break;
+  }
+  switch (myFontCharset) {
+    case NIS_Text::FontCharset_ANSI:
+      aCharset = ANSI_CHARSET; break;
+    case NIS_Text::FontCharset_EastEurope:
+      aCharset = EASTEUROPE_CHARSET; break;
+    case NIS_Text::FontCharset_Greek:
+      aCharset = GREEK_CHARSET; break;
+    case NIS_Text::FontCharset_Russian:
+      aCharset = RUSSIAN_CHARSET; break;
+    case NIS_Text::FontCharset_Chinese:
+      aCharset = CHINESEBIG5_CHARSET; break;
+    case NIS_Text::FontCharset_Symbol:
+      aCharset = SYMBOL_CHARSET; break;
+    case NIS_Text::FontCharset_Turkish:
+      aCharset = TURKISH_CHARSET; break;
+    case NIS_Text::FontCharset_Hebrew:
+      aCharset = HEBREW_CHARSET; break;
+    case NIS_Text::FontCharset_Arabic:
+      aCharset = ARABIC_CHARSET; break;
+    default:
+    case NIS_Text::FontCharset_DEFAULT:
+      aCharset = DEFAULT_CHARSET; break;
+  }
+  // create font
+  HFONT hFont = ::CreateFont
+    (myFontHeight,
+     0,                         // character width
+     myFontAngle,               // angle
+     0,                         // orientation
+     aWeight,
+     (DWORD)myIsItalic,
+     (DWORD)myIsUnderline,
+     FALSE,                     // strikeout
+     aCharset,
+     OUT_TT_PRECIS,             // output precision (TrueType font)
+     CLIP_DEFAULT_PRECIS,       // clipping precision (default)
+     NONANTIALIASED_QUALITY,    // output quality
+     aFamily,                   // pitch and family
+     NULL);                     // face name
+
+  HDC hdc = GetDC(NULL);    // screen device
+  HGDIOBJ aPrev = ::SelectObject(hdc, hFont);
+//  SelectObject (hdc, GetStockObject (SYSTEM_FONT));
+
+// create the bitmap display lists
+// we're making images of glyphs 0 thru 255
+  wglUseFontBitmaps (hdc, 0, 255, theList.GetListID(Draw_Normal));
+
+  aPrev = ::SelectObject(hdc, aPrev);
+  ::DeleteObject(aPrev);
+  ::ReleaseDC(NULL, hdc);
+#endif
+
+  theList.IsFontUpdated = Standard_False;
+}
diff --git a/src/NIS/NIS_TextDrawer.hxx b/src/NIS/NIS_TextDrawer.hxx
new file mode 100644 (file)
index 0000000..54e7968
--- /dev/null
@@ -0,0 +1,104 @@
+// File:      NIS_TextDrawer.hxx
+// Created:   12.12.11 07:31
+// Author:    Alexander GRIGORIEV
+// Copyright: Open Cascade 2011
+
+
+#ifndef NIS_TextDrawer_HeaderFile
+#define NIS_TextDrawer_HeaderFile
+
+#include <NIS_Drawer.hxx>
+#include <NIS_Text.hxx>
+
+/**
+ * Drawer for bitmap text object
+ * @ingroup nis_library
+ */
+
+class NIS_TextDrawer : public NIS_Drawer
+{
+ public:
+  // ---------- PUBLIC METHODS ----------
+  class DrawList : public NIS_DrawList
+  {
+  protected:
+    inline DrawList(const Handle_NIS_View& theView)
+      : NIS_DrawList (theView), IsFontUpdated(Standard_True) {}
+    //! Find an empty range of list IDs and allocate it.
+    Standard_EXPORT void SetListID (const NIS_Drawer::DrawType theType,
+                                    const Standard_Size        nLists);
+    Standard_Boolean IsFontUpdated;
+    friend class NIS_TextDrawer;
+  };
+
+  /**
+   * Empty constructor.
+   */
+  Standard_EXPORT NIS_TextDrawer ();
+
+  /**
+   * Special implementation - create DrawList for this object.
+   */
+  Standard_EXPORT virtual NIS_DrawList*
+                createDefaultList (const Handle_NIS_View& theView) const;
+
+  /**
+   * Copy the relevant information from another instance of Drawer.
+   * raises exception if theOther has incompatible type (test IsKind).
+   */
+  Standard_EXPORT virtual void Assign   (const Handle_NIS_Drawer& theOther);
+
+  /**
+   * Matching two instances, for Map interface.
+   */
+  Standard_EXPORT virtual Standard_Boolean
+                               IsEqual  (const Handle_NIS_Drawer& theOth)const;
+
+  /**
+   * Called before execution of Draw(), once per group of interactive objects.
+   */
+  Standard_EXPORT virtual void BeforeDraw(const DrawType         theType,
+                                          const NIS_DrawList&    theDrawList);
+
+  /**
+   * Main function: display the given interactive object in the given view.
+   */
+  Standard_EXPORT virtual void Draw     (const Handle_NIS_InteractiveObject&,
+                                         const DrawType         theType,
+                                         const NIS_DrawList&    theDrawList);
+
+  /**
+   * Called after execution of Draw(), once per group of interactive objects.
+   */
+  Standard_EXPORT virtual void AfterDraw(const DrawType         theType,
+                                         const NIS_DrawList&    theDrawList);
+
+ protected:
+  // ---------- PROTECTED METHODS ----------
+
+  Standard_EXPORT void SetFontUpdated   () const;
+
+ private:
+  void                 updateFontBitmaps(DrawList& theList);
+
+ private:
+  // ---------- PRIVATE FIELDS ----------
+  NIS_Text::FontFamily          myFontFamily;
+  NIS_Text::FontWeight          myFontWeight;
+  NIS_Text::FontCharset         myFontCharset;
+  Standard_Integer              myFontHeight;
+  Standard_Integer              myFontAngle;    //!< in tenths of degree
+  Standard_Boolean              myIsItalic;
+  Standard_Boolean              myIsUnderline;
+
+ public:
+// Declaration of CASCADE RTTI
+DEFINE_STANDARD_RTTI (NIS_TextDrawer)
+friend class NIS_Text;
+};
+
+// Definition of HANDLE object using Standard_DefineHandle.hxx
+DEFINE_STANDARD_HANDLE (NIS_TextDrawer, NIS_Drawer)
+
+
+#endif
diff --git a/src/NIS/NIS_Tools.cxx b/src/NIS/NIS_Tools.cxx
new file mode 100644 (file)
index 0000000..2ac9098
--- /dev/null
@@ -0,0 +1,110 @@
+// File:      NIS_Tools.cxx
+// Created:   29.07.11 08:46
+// Copyright: Open Cascade 2011
+
+
+#include <NIS_Tools.hxx>
+#include <NIS_Triangulated.hxx>
+#include <NIS_InteractiveContext.hxx>
+#include <NIS_Point.hxx>
+
+#include <TopExp_Explorer.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS.hxx>
+#include <Poly_Triangulation.hxx>
+#include <BRep_Tool.hxx>
+
+//=======================================================================
+//function : Decompose
+//purpose  : Function for creating the Local selection
+//=======================================================================
+
+Standard_Boolean NIS_Tools::Decompose
+                (const TopoDS_Shape&                            theSh,
+                 const Standard_Real                            theToler,
+                 const Standard_Integer                         theTypes,
+                 const Handle(NIS_InteractiveContext)&          theCtx,
+                 TopTools_DataMapOfIntegerShape&                theMap, 
+                 const Quantity_Color&                          theColor,
+                 const NIS_Surface::DisplayMode                 theHlgMode,
+                 const Standard_Real                            theLineWidth)
+{  
+  Standard_Boolean aRes = Standard_False;
+  if (theCtx.IsNull() || theSh.IsNull())
+    return aRes;
+
+  if (theTypes & Type_None)
+    return aRes;
+
+  TopTools_MapOfShape shMap;
+  if (theTypes & Type_Face)
+  {
+    TopExp_Explorer fexp (theSh, TopAbs_FACE);
+    for (; fexp.More(); fexp.Next())
+    {      
+      const TopoDS_Face& aFace = TopoDS::Face(fexp.Current());
+      if (!shMap.Add(aFace))
+        continue;
+
+      Standard_Real aToler = theToler;
+      TopLoc_Location aLoc;
+      Handle(Poly_Triangulation) aPolyTri = BRep_Tool::Triangulation(aFace, aLoc);
+      if (aPolyTri.IsNull() == Standard_False)
+      {
+        if (aPolyTri->Deflection() > theToler)
+        {
+          aToler = aPolyTri->Deflection();
+        }
+      }
+
+      Handle(NIS_Surface) aSurface = new NIS_Surface(aFace, aToler);
+      theCtx->Display(aSurface); 
+      aSurface->SetHilightDisplayMode(theHlgMode);
+      aSurface->SetColor(theColor);
+      aSurface->SetBackColor(theColor);
+      
+      if (!theMap.IsBound(aSurface->ID()))
+        theMap.Bind(aSurface->ID(), aFace);
+    }
+  }
+  if (theTypes & Type_Edge)
+  {
+    TopExp_Explorer eexp (theSh, TopAbs_EDGE);
+    for (; eexp.More(); eexp.Next())
+    {
+      const TopoDS_Edge& anEdge = TopoDS::Edge(eexp.Current());
+      if (!shMap.Add(anEdge))
+        continue;
+
+      Handle(NIS_Triangulated) aTri = new NIS_Triangulated(anEdge, theToler);
+      theCtx->Display(aTri);      
+      if (!theMap.IsBound(aTri->ID()))
+        theMap.Bind(aTri->ID(), anEdge);
+      aTri->SetColor(theColor);
+      aTri->SetLineWidth(theLineWidth);
+    }
+  }
+  if (theTypes & Type_Vertex)
+  {
+    TopExp_Explorer vexp (theSh, TopAbs_VERTEX);
+    for (; vexp.More(); vexp.Next())
+    {
+      const TopoDS_Vertex& aVertex = TopoDS::Vertex(vexp.Current());
+      if (!shMap.Add(aVertex))
+        continue;
+
+      Handle(NIS_Point) aPoint = new NIS_Point(BRep_Tool::Pnt(aVertex).XYZ());
+      theCtx->Display(aPoint);      
+      if (!theMap.IsBound(aPoint->ID()))
+        theMap.Bind(aPoint->ID(), aVertex);
+      aPoint->SetColor(theColor);
+      aPoint->SetMarkerType(NIS_MT_CIRCLE);
+    }
+  }    
+
+  return !theMap.IsEmpty();
+}
+
diff --git a/src/NIS/NIS_Tools.hxx b/src/NIS/NIS_Tools.hxx
new file mode 100644 (file)
index 0000000..673ca84
--- /dev/null
@@ -0,0 +1,77 @@
+// File:      NIS_Tools.hxx
+// Created:   09.07.11 23:47
+// Copyright: Open Cascade 2011
+
+
+#ifndef NIS_Tools_HeaderFile
+#define NIS_Tools_HeaderFile
+
+#include <NIS_Surface.hxx>
+
+#include <TopoDS_Shape.hxx>
+#include <TopTools_DataMapOfIntegerShape.hxx>
+
+template <class A> class NCollection_List;
+class Handle_NIS_InteractiveContext;
+
+/**
+ * class NIS_Tools
+ * Auxiliary algoritms and tools.
+ */
+class NIS_Tools 
+{
+ public:
+  // ---------- PUBLIC METHODS ----------
+
+  /**
+   * Enumerated types of object for local selection
+   */
+  enum DecomposeType {
+    Type_None   = 0x001,
+    Type_Face   = 0x002,
+    Type_Edge   = 0x004,
+    Type_Vertex = 0x008
+  };
+
+  struct PresentableShape {
+    TopoDS_Shape     Shape;
+    Standard_Integer PresentationID;
+  };
+
+  /**
+   * Function for creating the Local selection.
+   * Update of viewer should be called by GUI layer. This is done for
+   * performance reasons to have one update per all the operations.
+   * @param theShape
+   *   Original shape to be decomposed.
+   * @param theToler
+   *   Tolerance for triangulation/tessellation of subshapes.
+   * @param theTypes
+   *   Combination of bits, defined in enum DecomposeType.
+   * @param theCtx
+   *   The context where all created objects will be displayed.
+   * @param theMap
+   *   map of shapes
+   * @param theColor
+   *   Color for displaing of new IO in Normal mode
+   * @param theHlgMode
+   *   Set the hilight display mode for surface(Shading or Wirefram)
+   *   The default mode is Shading
+   * @returns
+   *   the list of ID of new presentations (NIS_Surface for Faces and
+   *   NIS_Triangulated for edges).
+   *   If theCtx is NULL then returns an empty list and false.
+   */
+  Standard_EXPORT static Standard_Boolean Decompose
+                (const TopoDS_Shape&                            theShape,
+                 const Standard_Real                            theToler,
+                 const Standard_Integer                         theTypes,
+                 const Handle_NIS_InteractiveContext&           theCtx, 
+                 TopTools_DataMapOfIntegerShape&                theMap,
+                 const Quantity_Color&                          theColor,
+                 const NIS_Surface::DisplayMode                 theHlgMode = NIS_Surface::Shading,
+                 const Standard_Real                            theLineWidth = 1.f);
+
+};
+
+#endif
index 03f26620e4bde9495159a92ddeb050ac9c1b64ce..3d323abcf1fba0362a6456b34a983239bbc0ac98 100644 (file)
 #include <NIS_Triangulated.hxx>
 #include <NIS_TriangulatedDrawer.hxx>
 #include <NIS_InteractiveContext.hxx>
+#include <TopoDS.hxx>
 #include <gp_Ax1.hxx>
 #include <Precision.hxx>
+#include <NCollection_DataMap.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <GCPnts_TangentialDeflection.hxx>
+#include <TopExp_Explorer.hxx>
+#include <BRep_Tool.hxx>
 
 IMPLEMENT_STANDARD_HANDLE  (NIS_Triangulated, NIS_InteractiveObject)
 IMPLEMENT_STANDARD_RTTIEXT (NIS_Triangulated, NIS_InteractiveObject)
@@ -47,6 +53,16 @@ static inline Standard_Size    NBytesInd  (const Standard_Integer nInd,
   return nBytes;
 }
 
+//=======================================================================
+//function : IsEqual
+//purpose  : 
+//=======================================================================
+inline Standard_Boolean IsEqual(const TopoDS_Shape& theS1,
+                                const TopoDS_Shape& theS2)
+{
+  return theS1.IsEqual(theS2);
+}
+
 //=======================================================================
 //function : NIS_Triangulated()
 //purpose  : Constructor
@@ -59,18 +75,15 @@ NIS_Triangulated::NIS_Triangulated
   : myAlloc             (0L),
     myType              (Type_None),
     mypNodes            (0L),
-    mypTriangles        (0L),
-    mypLines            (0L),
-    mypPolygons         (0L),
+    mypTriangles        (0L),    
     myNNodes            (0),
-    myNTriangles        (0),
-    myNLineNodes        (0),
-    myNPolygons         (0u),
+    myNTriangles        (0),    
     myIsDrawPolygons    (Standard_False),
     myIsCloned          (Standard_False),
     myIndexType         (2u),
     myNodeCoord         (is2D ? 2 : 3),
-    myPolygonType       (static_cast<unsigned int>(Polygon_Default))
+    myPolygonType       (static_cast<unsigned int>(Polygon_Default)),
+    myTriMode           (static_cast<unsigned int>(TriMode_Triangles))
 {
   
   if (theAlloc.IsNull())
@@ -80,6 +93,100 @@ NIS_Triangulated::NIS_Triangulated
   allocateNodes (nNodes);
 }
 
+//=======================================================================
+//function : NIS_Triangulated()
+//purpose  : Constructor
+//=======================================================================
+
+NIS_Triangulated::NIS_Triangulated
+                        (const TopoDS_Shape&                      theShape, 
+                         const Standard_Real                      theDeflection,
+                         const Handle(NCollection_BaseAllocator)& theAlloc)
+  : myAlloc             (0L),
+    myType              (Type_None),
+    mypNodes            (0L),
+    mypTriangles        (0L),    
+    myNNodes            (0),
+    myNTriangles        (0),    
+    myIsDrawPolygons    (Standard_False),
+    myIsCloned          (Standard_False),
+    myIndexType         (2u),
+    myNodeCoord         (3),
+    myPolygonType       (static_cast<unsigned int>(Polygon_Default)),
+    myTriMode           (static_cast<unsigned int>(TriMode_Triangles))
+{
+  
+  if (theAlloc.IsNull())
+    myAlloc = NCollection_BaseAllocator::CommonBaseAllocator().operator->();
+  else
+    myAlloc = theAlloc.operator->();
+
+  Init(theShape, theDeflection);
+}
+
+//=======================================================================
+//function : Init
+//purpose  : Initialize the instance with a TopoDS_Shape.
+//=======================================================================
+
+void NIS_Triangulated::Init (const TopoDS_Shape& theShape,
+                             const Standard_Real theDeflection,
+                             const Standard_Real theAngularDeflection)
+{
+  Clear();
+
+  NCollection_DataMap<TopoDS_Shape, GCPnts_TangentialDeflection>
+    mapEdges(100, myAlloc);
+  TopExp_Explorer eexp (theShape, TopAbs_EDGE);
+  Standard_Integer nbNodes = 0;
+  for (; eexp.More(); eexp.Next())
+  {
+    const TopoDS_Edge& anEdge = TopoDS::Edge(eexp.Current());
+    if (BRep_Tool::Degenerated(anEdge)) {
+      continue;
+    }
+
+    // perform discretization
+    BRepAdaptor_Curve anAdapCurve(anEdge);
+    GCPnts_TangentialDeflection aTD(anAdapCurve, theAngularDeflection, theDeflection);
+    Standard_Integer nPoints = aTD.NbPoints();
+    if (nPoints < 2)
+      continue;
+
+    if (!mapEdges.IsBound(anEdge))
+    {
+      mapEdges.Bind(anEdge, aTD);
+      nbNodes += nPoints;
+    }
+  }
+
+  Standard_Integer nbE = mapEdges.Extent();
+  if (nbE > 0)
+  {
+    myType |= Type_Line;
+    allocateNodes (nbNodes);  
+    myLines.InitArray(myIndexType, nbE, myAlloc);
+  
+    Standard_Integer aCurEdge = 0, aStartNode = 0;  
+    NCollection_DataMap<TopoDS_Shape, GCPnts_TangentialDeflection>::Iterator
+      anIt(mapEdges);
+    for (; anIt.More(); anIt.Next())
+    {
+      const GCPnts_TangentialDeflection& aTD = anIt.Value();
+      Standard_Integer nPoints = aTD.NbPoints();
+      myLines.SetArray(aCurEdge, nPoints, myAlloc);
+      for (Standard_Integer i = 0; i < nPoints; i++)
+      {
+        gp_XYZ aCurr = aTD.Value(i+1).XYZ();
+        SetNode(i + aStartNode, aCurr);
+        myLines.SetArrayIndex(aCurEdge, i, i + aStartNode);
+      }
+      aCurEdge++;
+      aStartNode += nPoints;
+    }
+  }
+}
+
 //=======================================================================
 //function : Clear
 //purpose  : Reset all internal data members and structures
@@ -96,22 +203,16 @@ void NIS_Triangulated::Clear ()
     myNTriangles = 0;
     myAlloc->Free(mypTriangles);
     mypTriangles = 0L;
-  }
-  if (myNLineNodes) {
-    myNLineNodes = 0;
-    myAlloc->Free( mypLines);
-    mypLines = 0L;
-  }
-  if (myNPolygons) {
-    for (unsigned int i = 0; i < myNPolygons; i++)
-      myAlloc->Free(mypPolygons[i]);
-    myAlloc->Free(mypPolygons);
-    myNPolygons = 0u;
-    mypPolygons = 0L;
-  }
+  }  
+
+  myLines.Clear(myAlloc);
+  myPolygons.Clear(myAlloc);
+  myFans.Clear(myAlloc);
   myType = Type_None;
   myIsDrawPolygons = Standard_False;
   myPolygonType = static_cast<unsigned int>(Polygon_Default);
+  myTriMode = static_cast<unsigned int>(TriMode_Triangles);
   if (GetDrawer().IsNull() == Standard_False) {
     GetDrawer()->SetUpdated(NIS_Drawer::Draw_Normal,
                             NIS_Drawer::Draw_Top,
@@ -131,16 +232,10 @@ void NIS_Triangulated::SetPolygonsPrs (const Standard_Integer nPolygons,
   if (nPolygons <= 0)
     myType &= ~Type_Polygons;
   else {
-    myType |= Type_Polygons;
-    if (myNPolygons) {
-      for (unsigned int i = 0; i < myNPolygons; i++)
-        myAlloc->Free(mypPolygons[i]);
-      myAlloc->Free(mypPolygons);
-    }
-    myNPolygons = static_cast<unsigned int>(nPolygons);
-    mypPolygons = static_cast<Standard_Integer **>
-      (myAlloc->Allocate(sizeof(Standard_Integer *)*nPolygons));
+    myType |= Type_Polygons;    
+    
     allocateNodes (nNodes);
+    myPolygons.InitArray(myIndexType, nPolygons, myAlloc);    
   }
 }
 
@@ -166,6 +261,29 @@ void NIS_Triangulated::SetTriangulationPrs (const Standard_Integer nTri,
   }
 }
 
+//=======================================================================
+//function : SetTriangulationFanPrs
+//purpose  : 
+//=======================================================================
+
+void NIS_Triangulated::SetTriangulationFanPrs
+                                        (const Standard_Integer nFanTriangles,
+                                         const Standard_Integer nNodes)
+{  
+  if (nFanTriangles <= 0)
+    myType &= ~Type_Triangulation;
+  else {
+    myTriMode = static_cast<unsigned int>(TriMode_Triangle_Fan);
+    if (!IsTriangulation())
+      myType |= Type_Triangulation;    
+    
+    if (nNodes != myNNodes)
+      allocateNodes (nNodes);
+
+    myFans.InitArray(myIndexType, nFanTriangles, myAlloc);    
+  }
+}
+
 //=======================================================================
 //function : SetLinePrs
 //purpose  : 
@@ -181,14 +299,12 @@ void NIS_Triangulated::SetLinePrs (const Standard_Integer nPoints,
     myType |= Type_Line;
     if (isClosed)
       myType |= Type_Loop;
-    if (myNLineNodes)
-      myAlloc->Free(mypLines);
+   
     myType &= ~Type_Segments;
     allocateNodes (nNodes);
 
-    myNLineNodes = nPoints;
-    const Standard_Size nBytes = NBytesInd(nPoints, myIndexType);
-    mypLines = static_cast<Standard_Integer *> (myAlloc->Allocate(nBytes));
+    myLines.InitArray(myIndexType, 1, myAlloc);
+    myLines.SetArray(0, nPoints, myAlloc);   
   }
 }
 
@@ -204,14 +320,12 @@ void NIS_Triangulated::SetSegmentPrs (const Standard_Integer nSegments,
     myType &= ~(Type_Loop | Type_Segments);
   else {
     myType |= Type_Segments;
-    if (myNLineNodes)
-      myAlloc->Free(mypLines);
+
     myType &= ~(Type_Line | Type_Loop);
     allocateNodes (nNodes);
-
-    myNLineNodes = nSegments*2;
-    const Standard_Size nBytes = NBytesInd(myNLineNodes, myIndexType);
-    mypLines = static_cast<Standard_Integer *> (myAlloc->Allocate(nBytes));
+    
+    myLines.InitArray(myIndexType, 1, myAlloc);
+    myLines.SetArray(0, nSegments*2, myAlloc);    
   }
 }
 
@@ -373,6 +487,29 @@ void NIS_Triangulated::SetTriangle   (const Standard_Integer  ind,
   }
 }
 
+//=======================================================================
+//function : NFanInList 
+//purpose  : 
+//=======================================================================
+
+Standard_Integer NIS_Triangulated::NFanInList (const Standard_Integer ind) const
+{
+  return myFans.NArrayIndexes(ind);  
+}
+
+//=======================================================================
+//function : SetFanTriangles
+//purpose  : 
+//=======================================================================
+
+void NIS_Triangulated::SetFanTriangles(const Standard_Integer ind,
+                                       const Standard_Integer nbTris,
+                                       const Standard_Integer startNodeIdx,
+                                       const int* triList)
+{  
+  myFans.SetArray (ind, nbTris+2, triList, myAlloc, startNodeIdx);
+}
+
 //=======================================================================
 //function : SetLineNode
 //purpose  : 
@@ -381,26 +518,7 @@ void NIS_Triangulated::SetTriangle   (const Standard_Integer  ind,
 void NIS_Triangulated::SetLineNode      (const Standard_Integer ind,
                                          const Standard_Integer iNode)
 {
-  if (ind >= myNLineNodes)
-    Standard_OutOfRange::Raise ("NIS_Triangulated::SetTriangle");
-  switch (myIndexType) {
-    case 0: // 8bit
-    {
-      unsigned char * pInd =
-        reinterpret_cast<unsigned char *>(mypLines) + ind;
-      pInd[0] = static_cast<unsigned char>(iNode);
-    }
-    break;
-    case 1: // 16bit
-    {
-      unsigned short * pInd =
-        reinterpret_cast<unsigned short *>(mypLines) + ind;
-      pInd[0] = static_cast<unsigned short>(iNode);
-    }
-    break;
-    default: // 32bit
-      mypLines[ind] = iNode;
-  }
+  myLines.SetArrayIndex(0, ind, iNode);
 }
 
 //=======================================================================
@@ -412,38 +530,7 @@ void NIS_Triangulated::SetPolygonNode         (const Standard_Integer indPoly,
                                                const Standard_Integer ind,
                                                const Standard_Integer iNode)
 {
-  if (indPoly >= static_cast<Standard_Integer>(myNPolygons))
-    Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygonNode");
-    
-  Standard_Integer * aPoly  = mypPolygons[indPoly];
-  switch (myIndexType) {
-  case 0: // 8bit
-  {
-    unsigned char aNNode =  * (reinterpret_cast<unsigned char *>(aPoly));
-    if (static_cast<unsigned char>(ind) >= aNNode)
-      Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygonNode");
-
-    unsigned char * pInd =
-      reinterpret_cast<unsigned char *>(aPoly) + ind + 1;
-    pInd[0] = static_cast<unsigned char>(iNode);   
-  }
-  break;
-  case 1: // 16bit
-  {
-    unsigned short aNNode =  * (reinterpret_cast<unsigned short *>(aPoly));
-    if (static_cast<unsigned short>(ind) >= aNNode)
-      Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygonNode");
-
-    unsigned short * pInd =
-      reinterpret_cast<unsigned short *>(aPoly) + ind + 1;
-    pInd[0] = static_cast<unsigned short>(iNode);
-  }
-  break;
-  default: // 32bit
-    if (ind >= aPoly[0])
-      Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygonNode");
-    aPoly[ind + 1] = iNode;
-  }
+  myPolygons.SetArrayIndex(indPoly, ind, iNode);
 }
 
 //=======================================================================
@@ -452,30 +539,8 @@ void NIS_Triangulated::SetPolygonNode         (const Standard_Integer indPoly,
 //=======================================================================
 Standard_Integer NIS_Triangulated::NPolygonNodes
                                          (const Standard_Integer indPoly)const
-{
-  Standard_Integer aResult(0);
-  if (indPoly >= static_cast<Standard_Integer>(myNPolygons))
-    Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
-  Standard_Integer * aPoly  = mypPolygons[indPoly];
-  switch (myIndexType) {
-    case 0: // 8bit
-    {
-      unsigned char aNNode =  * (reinterpret_cast<unsigned char *>(aPoly));
-      aResult = static_cast<Standard_Integer>(aNNode);
-    }
-    break;
-    case 1: // 16bit
-    {
-      unsigned short aNNode =  * (reinterpret_cast<unsigned short *>(aPoly));
-      aResult = static_cast<Standard_Integer>(aNNode);
-    }
-    break;
-    default: // 32bit
-    {
-      aResult = aPoly[0];
-    }
-  }
-  return aResult;
+{  
+  return myPolygons.NArrayIndexes(indPoly);  
 }
 
 //=======================================================================
@@ -486,40 +551,8 @@ Standard_Integer NIS_Triangulated::NPolygonNodes
 Standard_Integer NIS_Triangulated::PolygonNode 
                                             (const Standard_Integer indPoly,
                                              const Standard_Integer ind)const
-{
-  Standard_Integer aResult(-1);
-  if (indPoly >= static_cast<Standard_Integer>(myNPolygons))
-    Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
-  const Standard_Integer * aPoly  = mypPolygons[indPoly];
-  switch (myIndexType) {
-    case 0: // 8bit
-    {
-      const unsigned char * pInd =
-        reinterpret_cast<const unsigned char *>(aPoly);
-      if (static_cast<unsigned char>(ind) >= pInd[0])
-        Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
-
-      aResult = static_cast<Standard_Integer>(pInd[ind + 1]);
-    }
-    break;
-    case 1: // 16bit
-    {
-      const unsigned short * pInd =
-        reinterpret_cast<const unsigned short *>(aPoly);
-      if (static_cast<unsigned short>(ind) >= pInd[0])
-        Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
-
-      aResult = static_cast<Standard_Integer>(pInd[ind + 1]);
-    }
-    break;
-    default: // 32bit
-    {
-      if (ind >= aPoly[0])
-        Standard_OutOfRange::Raise ("NIS_Triangulated::PolygonNode");
-      aResult = aPoly[ind + 1];
-    }
-  }
-  return aResult;
+{  
+  return myPolygons.ArrayIndex(indPoly, ind);
 }
 
 //=======================================================================
@@ -529,34 +562,8 @@ Standard_Integer NIS_Triangulated::PolygonNode
 
 void NIS_Triangulated::SetPolygon (const Standard_Integer  ind,
                                    const Standard_Integer  theSz)
-{
-  if (ind >= static_cast<Standard_Integer>(myNPolygons))
-    Standard_OutOfRange::Raise ("NIS_Triangulated::SetPolygon");
-  switch (myIndexType) {
-    case 0: // 8bit
-    {
-      unsigned char * anArray  = static_cast <unsigned char *>
-        (myAlloc->Allocate (sizeof(unsigned char) * (theSz+1)));
-      mypPolygons[ind] = reinterpret_cast<Standard_Integer *> (anArray);
-      anArray[0] = static_cast<unsigned char>(theSz);
-    }
-    break;
-    case 1: // 16bit
-    {
-      unsigned short * anArray  = static_cast <unsigned short *>
-        (myAlloc->Allocate (sizeof(unsigned short) * (theSz+1)));
-      mypPolygons[ind] = reinterpret_cast<Standard_Integer *> (anArray);
-      anArray[0] = static_cast<unsigned short>(theSz);
-    }
-    break;
-    default: // 32bit
-    {
-      Standard_Integer * anArray  = static_cast <Standard_Integer *>
-        (myAlloc->Allocate (sizeof(Standard_Integer) * (theSz+1)));
-      mypPolygons[ind] = anArray;
-      anArray[0] = theSz;
-    }
-  } 
+{  
+  myPolygons.SetArray (ind, theSz, myAlloc);
 }
 
 //=======================================================================
@@ -603,78 +610,44 @@ void NIS_Triangulated::SetPolygonType
 }
 
 //=======================================================================
-//function : SetColor
-//purpose  : Set the normal color for presentation.
+//function : SetLineWidth
+//purpose  : Set the width of line presentations in pixels.
 //=======================================================================
 
-void NIS_Triangulated::SetColor (const Quantity_Color&  theColor)
+void NIS_Triangulated::SetLineWidth (const Standard_Real    theWidth)
 {
   const Handle(NIS_TriangulatedDrawer) aDrawer =
     static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
   aDrawer->Assign (GetDrawer());
-  aDrawer->myColor[NIS_Drawer::Draw_Normal] = theColor;
-  aDrawer->myColor[NIS_Drawer::Draw_Top] = theColor;
-  aDrawer->myColor[NIS_Drawer::Draw_Transparent] = theColor;
+  aDrawer->myLineWidth = (Standard_ShortReal) theWidth;
   SetDrawer (aDrawer);
 }
 
 //=======================================================================
-//function : GetColor
-//purpose  : Get Normal, Transparent or Hilighted color of the presentation.
-//=======================================================================
-
-Quantity_Color NIS_Triangulated::GetColor
-                        (const NIS_Drawer::DrawType theDrawType) const
-{
-  Handle(NIS_TriangulatedDrawer) aDrawer = 
-    Handle(NIS_TriangulatedDrawer)::DownCast( GetDrawer() );
-  if (aDrawer.IsNull() == Standard_False)
-  {
-    return aDrawer->myColor[theDrawType];
-  }
-  return Quantity_Color(); // return null color object
-}
-
-//=======================================================================
-//function : SetHilightColor
-//purpose  : Set the color for hilighted presentation.
+//function : GetLineWidth
+//purpose  : Get the width of line presentation in pixels.
 //=======================================================================
 
-void NIS_Triangulated::SetHilightColor (const Quantity_Color&  theColor)
+Standard_Real NIS_Triangulated::GetLineWidth () const
 {
-  const Handle(NIS_TriangulatedDrawer) aDrawer =
-    static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
-  aDrawer->Assign (GetDrawer());
-  aDrawer->myColor[NIS_Drawer::Draw_Hilighted] = theColor;
-  SetDrawer (aDrawer);
+    const Handle(NIS_TriangulatedDrawer) aDrawer =
+        static_cast<NIS_TriangulatedDrawer*>(DefaultDrawer(0L));
+    aDrawer->Assign(GetDrawer());
+    return (Standard_Real)(aDrawer->myLineWidth);
 }
 
 //=======================================================================
-//function : SetDynHilightColor
-//purpose  : Set the color for dynamic hilight presentation.
+//function : SetLineStyle
+//purpose  : Set the type of line presentation.
 //=======================================================================
 
-void NIS_Triangulated::SetDynHilightColor(const Quantity_Color&  theColor)
+void NIS_Triangulated::SetLineStyle  (const Standard_Integer theStyle)
 {
-  const Handle(NIS_TriangulatedDrawer) aDrawer =
-    static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
-  aDrawer->Assign (GetDrawer());
-  aDrawer->myColor[NIS_Drawer::Draw_DynHilighted] = theColor;
-  SetDrawer (aDrawer);
-}
-
-//=======================================================================
-//function : SetLineWidth
-//purpose  : Set the width of line presentations in pixels.
-//=======================================================================
-
-void NIS_Triangulated::SetLineWidth (const Standard_Real    theWidth)
-{
-  const Handle(NIS_TriangulatedDrawer) aDrawer =
-    static_cast<NIS_TriangulatedDrawer *>(DefaultDrawer(0L));
-  aDrawer->Assign (GetDrawer());
-  aDrawer->myLineWidth = (Standard_ShortReal) theWidth;
-  SetDrawer (aDrawer);
+    const Handle(NIS_TriangulatedDrawer) aDrawer =
+        static_cast<NIS_TriangulatedDrawer*>(DefaultDrawer(0L));
+    aDrawer->Assign(GetDrawer());
+    aDrawer->myLineType = theStyle;
+    SetDrawer(aDrawer);
 }
 
 //=======================================================================
@@ -712,27 +685,14 @@ void NIS_Triangulated::Clone (const Handle_NCollection_BaseAllocator& theAlloc,
       memcpy(aNewObj->mypTriangles, mypTriangles, nBytes);
     }
     // copy lines/segments
-    aNewObj->myNLineNodes = myNLineNodes;
-    if (myNLineNodes) {
-      const Standard_Size nBytes = NBytesInd(myNLineNodes, myIndexType);
-      aNewObj->mypLines = static_cast<Standard_Integer *>
-        (theAlloc->Allocate(nBytes));
-      memcpy(aNewObj->mypLines, mypLines, nBytes);
-    }
+    myLines.Clone(theAlloc, aNewObj->myLines);
+    
     // copy polygons
-    aNewObj->myNPolygons = myNPolygons;
-    if (myNPolygons) {
-      const Standard_Size nBytes = sizeof(Standard_Integer *)*myNPolygons;
-      aNewObj->mypPolygons = static_cast<Standard_Integer **>
-        (theAlloc->Allocate(nBytes));
-      for (unsigned int i = 0; i < myNPolygons; i++) {
-        const Standard_Integer nNodes = NPolygonNodes(i);
-        const Standard_Size nBytes = NBytesInd(nNodes+1, myIndexType);
-        aNewObj->mypPolygons[i] = static_cast <Standard_Integer *>
-          (theAlloc->Allocate (nBytes));
-        memcpy(aNewObj->mypPolygons[i], mypPolygons[i], nBytes);
-      }
-    }
+    myPolygons.Clone(theAlloc, aNewObj->myPolygons);
+    aNewObj->myTriMode = myTriMode;
+
+    // copy fans
+    myFans.Clone(theAlloc, aNewObj->myFans);    
   }
   aNewObj->myType = myType;
   aNewObj->myIsDrawPolygons = myIsDrawPolygons;
@@ -794,81 +754,49 @@ Standard_Boolean NIS_Triangulated::Intersect
     }
   }
   if (aResult == isFullIn) {
-    if (myType & Type_Segments) {
-      for (Standard_Integer i = 0; i < myNLineNodes; i+=2) {
-        const gp_Pnt aPnt[2] = {
-          nodeAtInd(mypLines, i+0).Transformed(theTrf),
-          nodeAtInd(mypLines, i+1).Transformed(theTrf)
-        };
-        if (isFullIn) {
-          if (seg_box_included (theBox, aPnt) == 0) {
-            aResult = Standard_False;
-            break;
-          }
-        } else {
-          if (seg_box_intersect (theBox, aPnt)) {
-            aResult = Standard_True;
-            break;
-          }
-        }
-      }
+    if ((myType & Type_Segments) && (NLineNodes() > 0)) {
+      const Standard_Integer * anSegs = static_cast <Standard_Integer *>(myLines.ArrayIndexes(0));
+      const Standard_Integer nNodes = myLines.NArrayIndexes(0);
+      aResult = intersectArray (anSegs, nNodes, theBox, theTrf, isFullIn, 2);      
     } else if (myType & Type_Line) {
-      for (Standard_Integer i = 1; i < myNLineNodes; i++) {
-        const gp_Pnt aPnt[2] = {
-          nodeAtInd(mypLines, i-1).Transformed(theTrf),
-          nodeAtInd(mypLines, i+0).Transformed(theTrf)
-        };
-        if (isFullIn) {
-          if (seg_box_included (theBox, aPnt) == 0) {
-            aResult = Standard_False;
-            break;
-          }
-        } else {
-          if (seg_box_intersect (theBox, aPnt)) {
-            aResult = Standard_True;
-            break;
-          }
-        }
-      }
-      if (aResult == isFullIn && (myType & Type_Loop)) {
-        const gp_Pnt aPntLast[2] = {
-          nodeAtInd(mypLines, myNLineNodes-1).Transformed(theTrf),
-          nodeAtInd(mypLines, 0).Transformed(theTrf)
-        };
-        if (isFullIn) {
-          if (seg_box_included (theBox, aPntLast) == 0)
-            aResult = Standard_False;
-        } else {
-          if (seg_box_intersect (theBox, aPntLast))
-            aResult = Standard_True;
-        }
-      }
-    } else if ((myType & Type_Polygons) && myIsDrawPolygons) {
-      for (unsigned int iPoly = 0; iPoly < myNPolygons; iPoly++) {
-        const Standard_Integer * aPoly = mypPolygons[iPoly];
-        const Standard_Integer nNodes = NPolygonNodes(iPoly);
-        for (Standard_Integer i = 1; i < nNodes; i++) {
-          // index is incremented by 1 for the head number in the array
-          const gp_Pnt aPnt[2] = {
-            nodeAtInd(aPoly, i+0).Transformed(theTrf),
-            nodeAtInd(aPoly, i+1).Transformed(theTrf)
+      for (Standard_Integer iLine = 0; iLine < NLines(); iLine++) {
+        const Standard_Integer* aLine = static_cast <Standard_Integer *>(myLines.ArrayIndexes(iLine));
+        const Standard_Integer nNodes = myLines.NArrayIndexes(iLine);
+        aResult = intersectArray (aLine, nNodes, theBox, theTrf, isFullIn);
+        
+        if (aResult == isFullIn && (myType & Type_Loop)) {          
+          // check edge between first and last points
+          const gp_Pnt aPntLast[2] = {
+            nodeAtInd(aLine, nNodes-1).Transformed(theTrf),
+            nodeAtInd(aLine, 0).Transformed(theTrf)
           };
           if (isFullIn) {
-            if (seg_box_included (theBox, aPnt) == 0) {
+            if (seg_box_included (theBox, aPntLast) == 0)
               aResult = Standard_False;
-              break;
-            }
           } else {
-            if (seg_box_intersect (theBox, aPnt)) {
+            if (seg_box_intersect (theBox, aPntLast))
               aResult = Standard_True;
-              break;
-            }
           }
         }
-        if (aResult == isFullIn) {
+        
+        if (aResult != isFullIn) {
+          // aResult==true, isFullIn==false, so at least one element is included
+          // or
+          // aResult==false, isFullIn==true, so at least one element is NOT included
+          break;
+        }
+      }
+    } else if ((myType & Type_Polygons) && myIsDrawPolygons) {      
+      for (Standard_Integer iPoly = 0; iPoly < NPolygons(); iPoly++) {
+        const Standard_Integer* aPoly = static_cast <Standard_Integer *>(myPolygons.ArrayIndexes(iPoly));
+        const Standard_Integer nNodes = myPolygons.NArrayIndexes(iPoly);
+        aResult = intersectArray (aPoly, nNodes, theBox, theTrf, isFullIn);
+
+        if (aResult == isFullIn) {          
+          // check edge between first and last points
           const gp_Pnt aPntLast[2] = {
-            nodeAtInd(aPoly, nNodes).Transformed(theTrf),
-            nodeAtInd(aPoly, 1).Transformed(theTrf)
+            nodeAtInd(aPoly, nNodes-1).Transformed(theTrf),
+            nodeAtInd(aPoly, 0).Transformed(theTrf)
           };
           if (isFullIn) {
             if (seg_box_included (theBox, aPntLast) == 0)
@@ -878,9 +806,54 @@ Standard_Boolean NIS_Triangulated::Intersect
               aResult = Standard_True;
           }
         }
+        
+        if (aResult != isFullIn) {
+          // aResult==true, isFullIn==false, so at least one element is included
+          // or
+          // aResult==false, isFullIn==true, so at least one element is NOT included
+          break;
+        }
+      }
+    }
+  }
+  return aResult;
+}
+
+//=======================================================================
+//function : intersectArray 
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean NIS_Triangulated::intersectArray
+                        (const Standard_Integer* theArray,
+                         const Standard_Integer theNNodes,
+                         const Bnd_B3f&         theBox,
+                         const gp_Trsf&         theTrf,
+                         const Standard_Boolean isFullIn,
+                         const Standard_Integer theIncremIdx) const 
+{
+  Standard_Boolean aResult = Standard_False;
+  if (!theArray)
+    return aResult;
+
+  for (Standard_Integer i = 0; i < theNNodes-1; i += theIncremIdx) {
+    const gp_Pnt aPnt[2] = {
+      nodeAtInd(theArray, i+0).Transformed(theTrf),
+      nodeAtInd(theArray, i+1).Transformed(theTrf)
+    };
+    if (isFullIn) {
+      if (seg_box_included (theBox, aPnt) == 0) {
+        aResult = Standard_False;
+        break;
+      }
+    } else {
+      if (seg_box_intersect (theBox, aPnt)) {
+        aResult = Standard_True;
+        break;
       }
     }
   }
+  
   return aResult;
 }
 
@@ -896,79 +869,95 @@ Standard_Real NIS_Triangulated::Intersect (const gp_Ax1&       theAxis,
   Standard_Real start[3], dir[3];
   theAxis.Location().Coord(start[0], start[1], start[2]);
   theAxis.Direction().Coord(dir[0], dir[1], dir[2]);
-  double anInter;
+  double anInter (RealLast());
+  const Standard_Real anOver2 = theOver*theOver;
 
   if ((myType & Type_Triangulation) && (myIsDrawPolygons == Standard_False))
+  {
     for (Standard_Integer i = 0; i < myNTriangles; i++) {
       Standard_Boolean isIntersect(Standard_False);
+      Standard_Integer idx1 = -1, idx2 = -1, idx3 = -1;
       if (myIndexType == 0) {
         const unsigned char * pTri =
           reinterpret_cast<unsigned char *>(mypTriangles) + (3 * i);
-        if (myNodeCoord > 2)
-          isIntersect = tri_line_intersect (start, dir,
-                                            &mypNodes[myNodeCoord * pTri[0]],
-                                            &mypNodes[myNodeCoord * pTri[1]],
-                                            &mypNodes[myNodeCoord * pTri[2]],
-                                            &anInter);
-        else
-          isIntersect = tri2d_line_intersect (start, dir,
-                                              &mypNodes[myNodeCoord * pTri[0]],
-                                              &mypNodes[myNodeCoord * pTri[1]],
-                                              &mypNodes[myNodeCoord * pTri[2]],
-                                              &anInter);
+        idx1 = myNodeCoord * pTri[0];
+        idx2 = myNodeCoord * pTri[1];
+        idx3 = myNodeCoord * pTri[2];
       } else if (myIndexType == 1) {
         const unsigned short * pTri =
           reinterpret_cast<unsigned short *>(mypTriangles) + (3 * i);
-        if (myNodeCoord > 2)
-          isIntersect = tri_line_intersect (start, dir,
-                                            &mypNodes[myNodeCoord * pTri[0]],
-                                            &mypNodes[myNodeCoord * pTri[1]],
-                                            &mypNodes[myNodeCoord * pTri[2]],
-                                            &anInter);
-        else
-          isIntersect = tri2d_line_intersect (start, dir,
-                                              &mypNodes[myNodeCoord * pTri[0]],
-                                              &mypNodes[myNodeCoord * pTri[1]],
-                                              &mypNodes[myNodeCoord * pTri[2]],
-                                              &anInter);
+        idx1 = myNodeCoord * pTri[0];
+        idx2 = myNodeCoord * pTri[1];
+        idx3 = myNodeCoord * pTri[2];
       } else {
         const Standard_Integer * pTri = &mypTriangles[3 * i];
-        if (myNodeCoord > 2)
-          isIntersect = tri_line_intersect (start, dir,
-                                            &mypNodes[myNodeCoord * pTri[0]],
-                                            &mypNodes[myNodeCoord * pTri[1]],
-                                            &mypNodes[myNodeCoord * pTri[2]],
-                                            &anInter);
-        else
-          isIntersect = tri2d_line_intersect (start, dir,
-                                              &mypNodes[myNodeCoord * pTri[0]],
-                                              &mypNodes[myNodeCoord * pTri[1]],
-                                              &mypNodes[myNodeCoord * pTri[2]],
-                                              &anInter);
+        idx1 = myNodeCoord * pTri[0];
+        idx2 = myNodeCoord * pTri[1];
+        idx3 = myNodeCoord * pTri[2];
       }
+
+      if (myNodeCoord > 2)
+        isIntersect = tri_line_intersect (start, dir,
+                                          &mypNodes[idx1],
+                                          &mypNodes[idx2],
+                                          &mypNodes[idx3],
+                                          &anInter);
+      else
+        isIntersect = tri2d_line_intersect (start, dir, anOver2,
+                                            &mypNodes[idx1],
+                                            &mypNodes[idx2],
+                                            &mypNodes[idx3],
+                                            &anInter);
       if (isIntersect && anInter < aResult)
         aResult = anInter;
     }
-
-  const Standard_Real anOver2 = theOver*theOver;
-  if (myType & Type_Segments) {
+    for (Standard_Integer i = 0; i < myFans.NArrays(); i++) 
+    {   
+       Standard_Integer idx1 = myFans.ArrayIndex(i, 0);
+       Standard_Integer nbTriIdx = myFans.NArrayIndexes(i);
+       for (Standard_Integer j = 1; j < nbTriIdx-1; j++) {
+         Standard_Boolean isIntersect(Standard_False);
+         Standard_Integer idx2 = myFans.ArrayIndex(i, j);
+         Standard_Integer idx3 = myFans.ArrayIndex(i, j+1);
+       
+         if (myNodeCoord > 2)
+           isIntersect = tri_line_intersect (start, dir,
+                                             Node(idx1),
+                                             Node(idx2),
+                                             Node(idx3),
+                                             &anInter);
+         else{
+           isIntersect = tri2d_line_intersect (start, dir, anOver2,
+                                               Node(idx1),
+                                               Node(idx2),
+                                               Node(idx3),
+                                               &anInter);           
+         }
+         if (isIntersect && anInter < aResult)
+           aResult = anInter;
+       }
+     }     
+  }
+  if ((myType & Type_Segments) && (NLineNodes() > 0)) {
     Standard_Integer i = 0;
-    if (myNodeCoord > 2)
-      for (; i < myNLineNodes; i+=2) {
+    Standard_Integer * aSegs = static_cast <Standard_Integer *>(myLines.ArrayIndexes(0));
+    if (myNodeCoord > 2) {      
+      for (; i < NLineNodes()-1; i+=2) {
         if (seg_line_intersect (theAxis.Location().XYZ(),
                                 theAxis.Direction().XYZ(), anOver2,
-                                nodeArrAtInd(mypLines, i+0),
-                                nodeArrAtInd(mypLines, i+1),
+                                nodeArrAtInd(aSegs, i+0),
+                                nodeArrAtInd(aSegs, i+1),
                                 &anInter))
           if (anInter < aResult)
             aResult = anInter;
       }
+    }
     else
-      for (; i < myNLineNodes; i+=2) {
+      for (; i < NLineNodes()-1; i+=2) {
         if (seg2d_line_intersect (theAxis.Location().XYZ(),
                                   theAxis.Direction().XYZ(), anOver2,
-                                  nodeArrAtInd(mypLines, i+0),
-                                  nodeArrAtInd(mypLines, i+1),
+                                  nodeArrAtInd(aSegs, i+0),
+                                  nodeArrAtInd(aSegs, i+1),
                                   &anInter))
           if (anInter < aResult)
             aResult = anInter;
@@ -976,52 +965,59 @@ Standard_Real NIS_Triangulated::Intersect (const gp_Ax1&       theAxis,
   } else if (myType & Type_Line) {
     Standard_Integer i = 1;
     if (myNodeCoord > 2) {
-      for (; i < myNLineNodes; i++) {
-        if (seg_line_intersect (theAxis.Location().XYZ(),
-                                theAxis.Direction().XYZ(), anOver2,
-                                nodeArrAtInd(mypLines, i-1),
-                                nodeArrAtInd(mypLines, i-0),
-                                &anInter))
-          if (anInter < aResult)
-            aResult = anInter;
-      }
-      if (myType & Type_Loop)
-        if (seg_line_intersect (theAxis.Location().XYZ(),
-                                theAxis.Direction().XYZ(), anOver2,
-                                nodeArrAtInd(mypLines, myNLineNodes-1),
-                                nodeArrAtInd(mypLines, 0),
-                                &anInter))
-          if (anInter < aResult)
-            aResult = anInter;
-    } else {
-      for (; i < myNLineNodes; i++) {
-        if (seg2d_line_intersect (theAxis.Location().XYZ(),
+      for (Standard_Integer iLine = 0; iLine < NLines(); iLine++) {
+        const Standard_Integer* aLine = static_cast <Standard_Integer *>(myLines.ArrayIndexes(iLine));
+        const Standard_Integer nNodes = NLineNodes(iLine);
+        for (; i < nNodes; i++) {      
+          if (seg_line_intersect (theAxis.Location().XYZ(),
+                                  theAxis.Direction().XYZ(), anOver2,
+                                  nodeArrAtInd(aLine, i-1),
+                                  nodeArrAtInd(aLine, i-0),
+                                  &anInter))
+            if (anInter < aResult)
+              aResult = anInter;
+        }
+        if (myType & Type_Loop)
+          if (seg_line_intersect (theAxis.Location().XYZ(),
                                   theAxis.Direction().XYZ(), anOver2,
-                                  nodeArrAtInd(mypLines, i-1),
-                                  nodeArrAtInd(mypLines, i-0),
+                                  nodeArrAtInd(aLine, nNodes-1),
+                                  nodeArrAtInd(aLine, 0),
                                   &anInter))
           if (anInter < aResult)
             aResult = anInter;
       }
-      if (myType & Type_Loop)
-        if (seg2d_line_intersect (theAxis.Location().XYZ(),
-                                  theAxis.Direction().XYZ(), anOver2,
-                                  nodeArrAtInd(mypLines, myNLineNodes-1),
-                                  nodeArrAtInd(mypLines, 0),
-                                  &anInter))
+    } else {
+      for (Standard_Integer iLine = 0; iLine < NLines(); iLine++) {
+        const Standard_Integer* aLine = static_cast <Standard_Integer *>(myLines.ArrayIndexes(iLine));
+        const Standard_Integer nNodes = NLineNodes(iLine);
+        for (; i < nNodes; i++) {      
+          if (seg2d_line_intersect (theAxis.Location().XYZ(),
+                                    theAxis.Direction().XYZ(), anOver2,
+                                    nodeArrAtInd(aLine, i-1),
+                                    nodeArrAtInd(aLine, i-0),
+                                    &anInter))
+            if (anInter < aResult)
+              aResult = anInter;
+        }
+        if (myType & Type_Loop)
+          if (seg2d_line_intersect (theAxis.Location().XYZ(),
+                                    theAxis.Direction().XYZ(), anOver2,
+                                    nodeArrAtInd(aLine, nNodes-1),
+                                    nodeArrAtInd(aLine, 0),
+                                    &anInter))
           if (anInter < aResult)
             aResult = anInter;
+      }
     }
   }
 
   if ((myType & Type_Polygons) && myIsDrawPolygons) {
-    for (unsigned int iPoly = 0; iPoly < myNPolygons; iPoly++) {
-      const Standard_Integer * aPoly = mypPolygons[iPoly];
-      const Standard_Integer nNodes = NPolygonNodes(iPoly);
-      Standard_Integer i = 1;
+    for (Standard_Integer iPoly = 0; iPoly < NPolygons(); iPoly++) {
+      const Standard_Integer * aPoly = static_cast <Standard_Integer *>(myPolygons.ArrayIndexes(iPoly));
+      const Standard_Integer nNodes = NPolygonNodes(iPoly) - 1;
+      Standard_Integer i = 0;
       if (myNodeCoord > 2) {
-        for (; i < nNodes; i++) {
-          // Node index is incremented for the head of polygon indice array
+        for (; i < nNodes; i++) {          
           if (seg_line_intersect (theAxis.Location().XYZ(),
                                   theAxis.Direction().XYZ(), anOver2,
                                   nodeArrAtInd(aPoly, i+0),
@@ -1033,7 +1029,7 @@ Standard_Real NIS_Triangulated::Intersect (const gp_Ax1&       theAxis,
         if (seg_line_intersect (theAxis.Location().XYZ(),
                                 theAxis.Direction().XYZ(), anOver2,
                                 nodeArrAtInd(aPoly, nNodes),
-                                nodeArrAtInd(aPoly, 1),
+                                nodeArrAtInd(aPoly, 0),
                                 &anInter))
           if (anInter < aResult)
             aResult = anInter;
@@ -1051,7 +1047,7 @@ Standard_Real NIS_Triangulated::Intersect (const gp_Ax1&       theAxis,
         if (seg2d_line_intersect (theAxis.Location().XYZ(),
                                   theAxis.Direction().XYZ(), anOver2,
                                   nodeArrAtInd(aPoly, nNodes),
-                                  nodeArrAtInd(aPoly, 1),
+                                  nodeArrAtInd(aPoly, 0),
                                   &anInter))
           if (anInter < aResult)
             aResult = anInter;
@@ -1098,11 +1094,12 @@ Standard_Boolean NIS_Triangulated::Intersect
     }
   }
   if (aResult == isFullIn) {
-    if (myType & Type_Segments) {
-      for (Standard_Integer i = 0; i < myNLineNodes; i+=2) {
+    if ((myType & Type_Segments) && (NLineNodes() > 0)) {
+      Standard_Integer * aSegs = static_cast <Standard_Integer *>(myLines.ArrayIndexes(0));
+      for (Standard_Integer i = 0; i < NLineNodes()-1; i+=2) {
         const gp_Pnt aPnt[2] = {
-          nodeAtInd(mypLines, i+0).Transformed(theTrf),
-          nodeAtInd(mypLines, i+1).Transformed(theTrf)
+          nodeAtInd(aSegs, i+0).Transformed(theTrf),
+          nodeAtInd(aSegs, i+1).Transformed(theTrf)
         };
         const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()),
                                 gp_XY(aPnt[1].X(), aPnt[1].Y()) };
@@ -1120,49 +1117,53 @@ Standard_Boolean NIS_Triangulated::Intersect
         }
       }
     } else if (myType & Type_Line) {
-      for (Standard_Integer i = 1; i < myNLineNodes; i++) {
-        const gp_Pnt aPnt[2] = {
-          nodeAtInd(mypLines, i-1).Transformed(theTrf),
-          nodeAtInd(mypLines, i+0).Transformed(theTrf)
-        };
-        const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()),
-                                gp_XY(aPnt[1].X(), aPnt[1].Y()) };
-        if (isFullIn) {
-          if (seg_polygon_included (thePolygon, aP2d) == 0) {
-            aResult = Standard_False;
-            break;
-          }
-        } else {
-          if (seg_polygon_intersect (thePolygon, aP2d)) {
-            aResult = Standard_True;
-            break;
+      for (Standard_Integer iLine = 0; iLine < NLines(); iLine++) {
+        const Standard_Integer* aLine = static_cast <Standard_Integer *>(myLines.ArrayIndexes(iLine));
+        const Standard_Integer nNodes = NLineNodes(iLine);
+        for (Standard_Integer i = 0; i < nNodes-1; i++) {      
+          const gp_Pnt aPnt[2] = {
+            nodeAtInd(aLine, i+0).Transformed(theTrf),
+            nodeAtInd(aLine, i+1).Transformed(theTrf)
+          };
+          const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()),
+                                  gp_XY(aPnt[1].X(), aPnt[1].Y()) };
+          if (isFullIn) {
+            if (seg_polygon_included (thePolygon, aP2d) == 0) {
+              aResult = Standard_False;
+              break;
+            }
+          } else {
+            if (seg_polygon_intersect (thePolygon, aP2d)) {
+              aResult = Standard_True;
+              break;
+            }
           }
         }
-      }
-      if (aResult == isFullIn && (myType & Type_Loop)) {
-        const gp_Pnt aPntLast[2] = {
-          nodeAtInd(mypLines, myNLineNodes-1).Transformed(theTrf),
-          nodeAtInd(mypLines, 0).Transformed(theTrf)
-        };
-        const gp_XY aP2dLast[2] = { gp_XY(aPntLast[0].X(), aPntLast[0].Y()),
-                                    gp_XY(aPntLast[1].X(), aPntLast[1].Y()) };
+        if (aResult == isFullIn && (myType & Type_Loop)) {
+          const gp_Pnt aPntLast[2] = {
+            nodeAtInd(aLine, nNodes-1).Transformed(theTrf),
+            nodeAtInd(aLine, 0).Transformed(theTrf)
+          };
+          const gp_XY aP2dLast[2] = { gp_XY(aPntLast[0].X(), aPntLast[0].Y()),
+                                      gp_XY(aPntLast[1].X(), aPntLast[1].Y()) };
 
-        if (isFullIn) {
-          if (seg_polygon_included (thePolygon, aP2dLast) == 0)
-            aResult = Standard_False;
-        } else {
-          if (seg_polygon_intersect (thePolygon, aP2dLast))
-            aResult = Standard_True;
+          if (isFullIn) {
+            if (seg_polygon_included (thePolygon, aP2dLast) == 0)
+              aResult = Standard_False;
+          } else {
+            if (seg_polygon_intersect (thePolygon, aP2dLast))
+              aResult = Standard_True;
+          }
         }
       }
     } else if ((myType & Type_Polygons) && myIsDrawPolygons) {
-      for (unsigned int iPoly = 0; iPoly < myNPolygons; iPoly++) {
-        const Standard_Integer * aPoly = mypPolygons[iPoly];
-        const Standard_Integer nNodes = NPolygonNodes(iPoly);
+      for (Standard_Integer iPoly = 0; iPoly < NPolygons(); iPoly++) {
+        const Standard_Integer * aPoly = static_cast <Standard_Integer *>(myPolygons.ArrayIndexes(iPoly));
+        const Standard_Integer nNodes = NPolygonNodes(iPoly);      
         for (Standard_Integer i = 1; i < nNodes; i++) {
           const gp_Pnt aPnt[2] = {
-            nodeAtInd(aPoly, i+0).Transformed(theTrf),
-            nodeAtInd(aPoly, i+1).Transformed(theTrf)
+            nodeAtInd(aPoly, i-1).Transformed(theTrf),
+            nodeAtInd(aPoly, i+0).Transformed(theTrf)
           };
           const gp_XY aP2d[2] = { gp_XY(aPnt[0].X(), aPnt[0].Y()),
                                   gp_XY(aPnt[1].X(), aPnt[1].Y()) };
@@ -1180,8 +1181,8 @@ Standard_Boolean NIS_Triangulated::Intersect
         }
         if (aResult == isFullIn) {
           const gp_Pnt aPntLast[2] = {
-            nodeAtInd(aPoly, nNodes).Transformed(theTrf),
-            nodeAtInd(aPoly, 1).Transformed(theTrf)
+            nodeAtInd(aPoly, nNodes-1).Transformed(theTrf),
+            nodeAtInd(aPoly, 0).Transformed(theTrf)
           };
           const gp_XY aP2dLast[2] = { gp_XY(aPntLast[0].X(), aPntLast[0].Y()),
                                       gp_XY(aPntLast[1].X(), aPntLast[1].Y()) };
@@ -1281,6 +1282,8 @@ Purpose    : Intersect a 2D triangle with a 3D line. Z coordinate of triangle
            : is zero
 Parameters : start  - coordinates of the origin of the line
              dir    - coordinates of the direction of the line (normalized)
+             over2  - maximal square distance between the line and one side of 
+                      triangle in intersection state.
              V0     - first vertex of the triangle
              V1     - second vertex of the triangle
              V2     - third vertex of the triangle
@@ -1291,6 +1294,7 @@ Returns    : int = 1 if intersection found, 0 otherwise
 
 int NIS_Triangulated::tri2d_line_intersect (const double      start[3],
                                             const double      dir[3],
+                                            const double      over2,
                                             const float       V0[2],
                                             const float       V1[2],
                                             const float       V2[2],
@@ -1321,14 +1325,49 @@ int NIS_Triangulated::tri2d_line_intersect (const double      start[3],
     const double dot11 = v[1][0]*v[1][0] + v[1][1]*v[1][1];
     const double dot12 = v[1][0]*v[2][0] + v[1][1]*v[2][1];
     const double denom = (dot00 * dot11 - dot01 * dot01);
-    if (denom * denom < conf) {
-      // Point on the 1st side of the triangle
-      res = (dot01 > -conf && dot00 < dot11 + conf);
+    if (denom * denom < conf * conf) {
+      // Find the bounding box of the triangle
+      double bbox[][2] = { { V0[0], V0[1] }, { V0[0], V0[1] }};
+      if (V1[0] < V0[0])
+        bbox[0][0] = V1[0];
+      else
+        bbox[1][0] = V1[0];
+      if (V1[1] < V0[1])
+        bbox[0][1] = V1[1];
+      else
+        bbox[1][1] = V1[1];
+      if (V2[0] < bbox[0][0])
+        bbox[0][0] = V2[0];
+      else if (V2[0] > bbox[1][0])
+        bbox[1][0] = V2[0];
+      if (V2[1] < bbox[0][1])
+        bbox[0][1] = V2[1];
+      else if (V2[1] > bbox[1][1])
+        bbox[1][1] = V2[1];
+      // Classify toward the bounding box
+      if (p2d[0] > bbox[0][0] - conf && p2d[0] < bbox[1][0] + conf &&
+          p2d[1] > bbox[0][1] - conf && p2d[1] < bbox[1][1] + conf)
+        // Point on the 1st side of the triangle
+        res = (dot01 > -conf && dot00 < dot11 + conf);
     } else {
       // Barycentric coordinates of the point
-      const double u = (dot11 * dot02 - dot01 * dot12) / denom;
-      const double v = (dot00 * dot12 - dot01 * dot02) / denom;
-      res = (u > -conf) && (v > -conf) && (u + v < 1. + conf);
+      const double uc = (dot11 * dot02 - dot01 * dot12) / denom;
+      const double vc = (dot00 * dot12 - dot01 * dot02) / denom;
+      if ((uc > -conf) && (vc > -conf) && (uc + vc < 1. + conf))
+        res = 1;
+      else if (over2 > conf) {
+        // seek the proximity to the border of the triangle - two sides enough
+        if (dot02 > 0. && dot02 < dot00) {
+          const double aD = v[0][0]*v[2][1] - v[0][1]*v[2][0];
+          if (aD * aD < dot00 * over2)
+            res = 1;
+        }
+        if (res == 0 && dot12 > 0. && dot12 < dot11) {
+          const double aD = v[1][0]*v[2][1] - v[1][1]*v[2][0];
+          if (aD * aD < dot11 * over2)
+            res = 1;
+        }
+      }
     }
   }
   if (res && tInter)
@@ -1736,12 +1775,13 @@ void NIS_Triangulated::allocateNodes (const Standard_Integer nNodes)
     myNNodes = nNodes;
     mypNodes = static_cast<Standard_ShortReal*>
       (myAlloc->Allocate(sizeof(Standard_ShortReal) * myNodeCoord * nNodes));
+
     if (nNodes < 256)
       myIndexType = 0;
     else if (nNodes < 65536)
       myIndexType = 1;
     else
-      myIndexType = 2;
+      myIndexType = 2;    
   }
 }
 
@@ -1799,3 +1839,4 @@ float* NIS_Triangulated::nodeArrAtInd (const Standard_Integer * theArray,
   }
   return pResult;
 }
+
index 375e90e914ec1c825b0a8dbf7e9916bb2156336a..c6d80d41e287f4d432fab10b9f25e9fd30366814 100644 (file)
 #define NIS_Triangulated_HeaderFile
 
 #include <NIS_InteractiveObject.hxx>
-#include <Quantity_Color.hxx>
+#include <NIS_IndexLists.hxx>
 
 class Handle_NIS_TriangulatedDrawer;
 class NCollection_BaseAllocator;
 class Handle_NCollection_BaseAllocator;
 class NIS_TriangulatedDrawer;
+class TopoDS_Shape;
 
 /**
  * Interactive object that consists of triangles, lines and polygons without
@@ -45,6 +46,7 @@ class NIS_TriangulatedDrawer;
  * constructor or in any Set* method. For example, if this number of nodes is
  * smaller than 256 then 8-bit representation is selected. The choice is stored
  * in 'myIndexType' data member.
+ * @ingroup nis_library
  */
 
 class NIS_Triangulated : public NIS_InteractiveObject
@@ -66,7 +68,7 @@ class NIS_Triangulated : public NIS_InteractiveObject
 
  public:
   /**
-   * Enumerated type of polygon rendering.
+   * Enumerated type of polygon rendering
    */
   enum PolygonType {
     Polygon_Default  = 0,  //!< Polygon as LINE, Triangulation as FILL
@@ -74,6 +76,30 @@ class NIS_Triangulated : public NIS_InteractiveObject
     Polygon_Fill     = 2   //!< Both Polygon and Triangulation as FILL
   };
 
+  /**
+   * Specifies what kind of primitives to render
+   */
+  enum TriMode {
+    /**
+     * Treats each triplet of vertices as an independent triangle.
+     * Vertices 3n2, 3n1, and 3n define triangle n. n/3 triangles are drawn.
+     */
+    TriMode_Triangles      = 0,
+    /**
+     * Draws a connected group of triangles. One triangle is defined for each
+     * vertex presented after the first two vertices. n+2 triangles are drawn.
+     * For odd n, vertices n, n+1, and n+2 define triangle n.
+     * For even n, vertices n+1, n, and n+2 define triangle n.
+     */
+    TriMode_Triangle_Strip = 1,
+    /**
+     * Draws a connected group of triangles. One triangle is defined for each
+     * vertex presented after the first two vertices. n+2 triangles are drawn.
+     * Vertices 1, n+1, and n+2 define triangle n.
+     */
+    TriMode_Triangle_Fan   = 2
+  };
+
  public:
   // ---------- PUBLIC METHODS ----------
 
@@ -95,6 +121,29 @@ class NIS_Triangulated : public NIS_InteractiveObject
                                    const Handle_NCollection_BaseAllocator&
                                    theAlloc = 0L);
 
+  /**
+   * Constructor. Create a presentation for edges from a given shape. 
+   * Used for local selection
+   * @param theEdges
+   *   Get the list of edges from the given shape for presentation.
+   * @param theDeflection
+   *   Deflection for descretizing 'theEdges'.
+   * @param theAlloc
+   *   Allocator for internal data
+   */
+  Standard_EXPORT NIS_Triangulated(const TopoDS_Shape& theEdges,    
+                                   const Standard_Real theDeflection,
+                                   const Handle_NCollection_BaseAllocator&
+                                   theAlloc = 0L);
+
+  /**
+   * Initialize the instance with a TopoDS_Shape. Used in constructor but can
+   * be called any time to redefine the geometry.
+   */
+  Standard_EXPORT void       Init (const TopoDS_Shape& theShape,
+                                   const Standard_Real theDefl,
+                                   const Standard_Real theAngularDefl = 0.1);
+
   /**
    * Define the polygonal presentration.
    * @param nPolygons
@@ -119,6 +168,18 @@ class NIS_Triangulated : public NIS_InteractiveObject
                                         (const Standard_Integer nTriangles,
                                          const Standard_Integer nNodes = 0);
 
+  /**
+   * Define the triangulated fan presentration.
+   * @param nFans
+   *   Number of fans. If set to 0, fan triangulation is cancelled  
+   * @param nNodes
+   *   Optional: Number of nodes to allocate. If left as 0, the previous nodes
+   *   allocation is used, otherwise a new allocation is created.
+   */ 
+  Standard_EXPORT void              SetTriangulationFanPrs
+                                        (const Standard_Integer nFans,
+                                         const Standard_Integer nNodes = 0);
+
   /**
    * Define the line presentration (polygon through points)
    * @param nPoints
@@ -171,6 +232,12 @@ class NIS_Triangulated : public NIS_InteractiveObject
   inline Standard_Boolean           IsSegments  () const
   { return (myType & Type_Segments) != 0; }
 
+  /**
+   * Query if there is fan triangulation component in the presentation.
+   */
+  inline Standard_Boolean           IsFanTriangulation  () const
+  { return (IsTriangulation() && (myTriMode == TriMode_Triangle_Fan)); }
+
   /**
    * Reset all data memebers and free all allocated memory.
    * Called from the destructor, also can be usedto re-initialize a given
@@ -209,6 +276,14 @@ class NIS_Triangulated : public NIS_InteractiveObject
                                                 const Standard_Integer  iNode1,
                                                 const Standard_Integer  iNode2);
 
+  /**
+   * Define the fan triangles list.
+   */
+  Standard_EXPORT void              SetFanTriangles(const Standard_Integer ind,
+                                                    const Standard_Integer nbTris, 
+                                                    const Standard_Integer startNodeIdx,
+                                                    const int* triList);
+
   /**
    * Allocate a single polygon, should be called for each polygon following
    * the call SetPolygonsPrs(). The polygon can be filled by node indices using
@@ -239,18 +314,24 @@ class NIS_Triangulated : public NIS_InteractiveObject
   inline Standard_Integer           NTriangles() const
   { return myNTriangles; }
 
+  /**
+   * Query the number of lines.
+   */
+  inline Standard_Integer           NLines() const
+  { return myLines.NArrays(); }
+
   /**
    * Query the number of line points.
    */
-  inline Standard_Integer           NLineNodes() const
-  { return myNLineNodes; }
+  inline Standard_Integer           NLineNodes(const Standard_Integer indLine = 0) const
+  { return (myLines.NArrays() == 0) ? 0 : myLines.NArrayIndexes(indLine); }    
 
   /**
    * Query the number of polygons.
    */
   inline Standard_Integer           NPolygons () const
-  { return static_cast<Standard_Integer>(myNPolygons); }
-
+  { return myPolygons.NArrays(); }
+  
   /**
    * Query the node by its index.
    * @return
@@ -259,6 +340,18 @@ class NIS_Triangulated : public NIS_InteractiveObject
   inline const Standard_ShortReal * Node      (const Standard_Integer ind) const
   { return &mypNodes[ind * myNodeCoord]; }
 
+  /**
+   * Query the coordinates number (2 or 3 coordinates).
+   */
+  inline Standard_Integer           NodeCoord  () const
+  { return myNodeCoord; }
+
+  /**
+   * Query the number of fan Triangles in List.
+   */
+  Standard_EXPORT Standard_Integer NFanInList (const Standard_Integer ind) const;
+  
+
   /**
    * Define the node of a polygon by index.
    * @param indPoly
@@ -304,40 +397,24 @@ class NIS_Triangulated : public NIS_InteractiveObject
                                         (const PolygonType      theType);
 
   /**
-   * Set the normal color for presentation.
-   * @param theColor
-   *   New color to use for the presentation.
-   */
-  Standard_EXPORT void              SetColor  (const Quantity_Color&  theColor);
-
-  /**
-   * Get Normal, Transparent or Hilighted color of the presentation.
-   * @param theDrawType
-   *   The draw type, for which the color is retrieved.
-   */
-  Standard_EXPORT Quantity_Color GetColor  
-                          (const NIS_Drawer::DrawType theDrawType) const;
-
-  /**
-   * Set the color for hilighted presentation.
-   * @param theColor
-   *   New color to use for the presentation.
+   * Set the width of line presentations in pixels.
+   * @param theWidth
+   *   New line width to use for the presentation.
    */
-  Standard_EXPORT void      SetHilightColor   (const Quantity_Color&  theColor);
+  Standard_EXPORT void      SetLineWidth      (const Standard_Real    theWidth);
 
   /**
-   * Set the color for dynamic hilight presentation.
-   * @param theColor
-   *   New color to use for the presentation.
+   * Get the width of line presentation in pixels.
    */
-  Standard_EXPORT void      SetDynHilightColor(const Quantity_Color&  theColor);
+  Standard_EXPORT Standard_Real    GetLineWidth () const;
 
   /**
-   * Set the width of line presentations in pixels.
-   * @param theWidth
-   *   New line width to use for the presentation.
+   * Set the line style.
+   * @param theStyle
+   *   Line style to be used for the presentation.
+   *   16-bit integer is passed as glLineStipple(1, theStyle)
    */
-  Standard_EXPORT void      SetLineWidth      (const Standard_Real    theWidth);
+  Standard_EXPORT void      SetLineStyle   (const Standard_Integer theStyle);
 
   /**
    * Create a copy of theObject except its ID.
@@ -410,6 +487,7 @@ class NIS_Triangulated : public NIS_InteractiveObject
 
   Standard_EXPORT static int tri2d_line_intersect(const double      start[3],
                                                   const double      dir[3],
+                                                  const double      over2,
                                                   const float       V0[2],
                                                   const float       V1[2],
                                                   const float       V2[2],
@@ -468,14 +546,14 @@ class NIS_Triangulated : public NIS_InteractiveObject
    */
   Standard_EXPORT virtual void Delete () const; 
 
- protected:
-
   /**
    * Allocator-based operator new for dynamic allocations in method Clone()
    */
   DEFINE_STANDARD_ALLOC
   DEFINE_NCOLLECTION_ALLOC
 
+ protected:
+
   /**
    * Create a 3D bounding box of the object.
    */
@@ -499,6 +577,19 @@ class NIS_Triangulated : public NIS_InteractiveObject
   Standard_EXPORT float*       nodeArrAtInd   (const Standard_Integer * theArr,
                                                const Standard_Integer i) const;
 
+  /**
+   * Auxiulary function computing of intersection with lines.
+   * This function is used in "intersect" functions.
+   */
+  Standard_EXPORT Standard_Boolean
+                intersectArray  (const Standard_Integer* theArray,
+                                 const Standard_Integer theNNodes,
+                                 const Bnd_B3f&         theBox,
+                                 const gp_Trsf&         theTrf,
+                                 const Standard_Boolean isFullIn,
+                                 const Standard_Integer theIncremIdx = 1) const;
+
+
  protected:
   // ---------- PROTECTED FIELDS ----------
 
@@ -506,17 +597,17 @@ class NIS_Triangulated : public NIS_InteractiveObject
   Standard_Integer           myType;    //!< Combination of Type_* constants
   Standard_ShortReal         *  mypNodes;
   Standard_Integer           *  mypTriangles;
-  Standard_Integer           *  mypLines;
-  Standard_Integer           ** mypPolygons;
+  NIS_IndexLists             myLines;
+  NIS_IndexLists             myPolygons;  
+  NIS_IndexLists             myFans;
   Standard_Integer           myNNodes;
-  Standard_Integer           myNTriangles;
-  Standard_Integer           myNLineNodes;
-  unsigned int               myNPolygons      : 24;
+  Standard_Integer           myNTriangles;  
   Standard_Boolean           myIsDrawPolygons : 1;
   Standard_Boolean           myIsCloned       : 1; //!< How it is allocated
   unsigned int               myIndexType      : 2; //!< 0:8bit, 1:16bit, 2:32bit
   unsigned int               myNodeCoord      : 2; //!< 2 or 3 coordinates
   unsigned int               myPolygonType    : 2;
+  unsigned int               myTriMode        : 2;
 
  public:
 // Declaration of CASCADE RTTI
index bb115bf7fcbbc78b09974522033cbfcdeb32081a..0a094f41c67717604715fa9d77834e373f27c1cd 100644 (file)
@@ -14,7 +14,6 @@
 // commercial license or contractual agreement.
 
 #include <NIS_TriangulatedDrawer.hxx>
-#include <NIS_InteractiveObject.hxx>
 #include <NIS_Triangulated.hxx>
 #ifdef _DEBUG
 #include <Standard_ProgramError.hxx>
@@ -44,16 +43,14 @@ NIS_TriangulatedDrawer::NIS_TriangulatedDrawer
                                 (const Quantity_Color theNormal,
                                  const Quantity_Color theHilight,
                                  const Quantity_Color theDynHilight)
-  : myPolygonAsLineLoop (Standard_False),
-    myLineWidth      (1.f),
-    myIsDrawPolygons (Standard_False),
-    myPolygonType    (NIS_Triangulated::Polygon_Default)
+  : NIS_Drawer          (theHilight, theDynHilight),
+    myPolygonAsLineLoop (Standard_False),
+    myLineWidth         (1.f),
+    myLineType          (0),
+    myIsDrawPolygons    (Standard_False),
+    myPolygonType       (NIS_Triangulated::Polygon_Default)
 {
-  myColor[Draw_Normal]       = theNormal;
-  myColor[Draw_Top]          = theNormal;
-  myColor[Draw_Transparent]  = theNormal;
-  myColor[Draw_Hilighted]    = theHilight;
-  myColor[Draw_DynHilighted] = theDynHilight;
+  SetColor(Draw_Normal, theNormal);
 }
 
 //=======================================================================
@@ -67,12 +64,8 @@ void NIS_TriangulatedDrawer::Assign (const Handle_NIS_Drawer& theOther)
     NIS_Drawer::Assign (theOther);
     const Handle(NIS_TriangulatedDrawer)& anOther =
       static_cast <const Handle(NIS_TriangulatedDrawer)&> (theOther);
-    myColor[Draw_Normal]       = anOther->myColor[Draw_Normal];
-    myColor[Draw_Top]          = anOther->myColor[Draw_Top];
-    myColor[Draw_Transparent]  = anOther->myColor[Draw_Transparent];
-    myColor[Draw_Hilighted]    = anOther->myColor[Draw_Hilighted];
-    myColor[Draw_DynHilighted] = anOther->myColor[Draw_DynHilighted];
     myLineWidth                = anOther->myLineWidth;
+    myLineType                 = anOther->myLineType;
     myIsDrawPolygons           = anOther->myIsDrawPolygons;
     myPolygonType              = anOther->myPolygonType;
   }
@@ -93,14 +86,9 @@ Standard_Boolean NIS_TriangulatedDrawer::IsEqual
   const Handle(NIS_TriangulatedDrawer) anOther =
     Handle(NIS_TriangulatedDrawer)::DownCast (theOther);
   if (NIS_Drawer::IsEqual(theOther))
-    aResult = (anOther->myColor[Draw_Normal]
-               .SquareDistance (myColor[Draw_Normal]) < anEpsilon2 &&
-               anOther->myColor[Draw_Hilighted]
-               .SquareDistance (myColor[Draw_Hilighted]) < anEpsilon2 &&
-               anOther->myColor[Draw_DynHilighted]
-               .SquareDistance (myColor[Draw_DynHilighted]) < anEpsilon2 &&
-               (anOther->myLineWidth - myLineWidth) *
+    aResult = ((anOther->myLineWidth - myLineWidth) *
                (anOther->myLineWidth - myLineWidth) < 0.01 &&
+               anOther->myLineType == myLineType &&
                anOther->myIsDrawPolygons == myIsDrawPolygons &&
                anOther->myPolygonType == myPolygonType);
   return aResult;
@@ -144,7 +132,7 @@ void NIS_TriangulatedDrawer::BeforeDraw (const DrawType      theType,
       anOffsetHilighted = 1;
 #endif
     }
-    myColor[theType].Values (aValue[0], aValue[1], aValue[2], bidTC);
+    GetColor(theType).Values (aValue[0], aValue[1], aValue[2], bidTC);
     glColor3d (aValue[0], aValue[1], aValue[2]);
     break;
   case Draw_Normal:
@@ -153,7 +141,7 @@ void NIS_TriangulatedDrawer::BeforeDraw (const DrawType      theType,
 #ifndef NEGATIVE_POFFSET
     anOffsetHilighted = 11;
 #endif
-    myColor[theType].Values (aValue[0], aValue[1], aValue[2], bidTC);
+    GetColor(theType).Values (aValue[0], aValue[1], aValue[2], bidTC);
     aValue[3] = 1. - myTransparency;
     if (myTransparency > 0.01) {
       glEnable(GL_BLEND);
@@ -182,6 +170,11 @@ void NIS_TriangulatedDrawer::BeforeDraw (const DrawType      theType,
     }
   glEnableClientState (GL_VERTEX_ARRAY);
   glLineWidth (aLineWidth);
+  if (myLineType > 0)
+  {
+      glEnable(GL_LINE_STIPPLE);
+      glLineStipple(1, (GLushort)myLineType);
+  }
   glShadeModel(GL_FLAT);
   glDisable(GL_LIGHTING);
 }
@@ -219,6 +212,11 @@ void NIS_TriangulatedDrawer::AfterDraw (const DrawType      theType,
   if (myPolygonType == NIS_Triangulated::Polygon_Line ||
       (myPolygonType == NIS_Triangulated::Polygon_Default && myIsDrawPolygons))
     glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+  
+  if (myLineType > 0)
+  {
+      glDisable(GL_LINE_STIPPLE);
+  }
 }
 
 //=======================================================================
@@ -249,8 +247,19 @@ void NIS_TriangulatedDrawer::Draw (const Handle_NIS_InteractiveObject& theObj,
 
   if (myIsDrawPolygons == Standard_False) {
     if (pObject->IsTriangulation()) {
-      glDrawElements (GL_TRIANGLES, pObject->NTriangles()*3,
-                      aType, pObject->mypTriangles);
+      if (pObject->IsFanTriangulation()) {        
+        Standard_Integer i;
+        for (i = 0; i < pObject->myFans.NArrays(); i++) 
+        {                       
+          Standard_Integer nbFanTri = pObject->NFanInList(i);
+          if (nbFanTri > 0) 
+            glDrawElements(GL_TRIANGLE_FAN, nbFanTri,
+                           aType, pObject->myFans.ArrayIndexes(i)); 
+        } 
+      }
+      if (pObject->NTriangles() > 0)
+        glDrawElements (GL_TRIANGLES, pObject->NTriangles()*3,
+                        aType, pObject->mypTriangles);
     }
   } else {
     if (pObject->IsPolygons()) {
@@ -263,35 +272,26 @@ void NIS_TriangulatedDrawer::Draw (const Handle_NIS_InteractiveObject& theObj,
       const Standard_Integer nPoly = pObject->NPolygons();
       for (Standard_Integer i = 0; i < nPoly; i++) {
         const Standard_Integer nSize = pObject->NPolygonNodes(i);
-        void* anArray;
-        if (pObject->myIndexType == 0)
-          anArray = reinterpret_cast<unsigned char *>(pObject->mypPolygons[i]) + 1;
-        else if (pObject->myIndexType == 1)
-          anArray = reinterpret_cast<unsigned short *>(pObject->mypPolygons[i]) + 1;
-        else
-          anArray = pObject->mypPolygons[i] + 1;
-        glDrawElements (aMode, nSize, aType, anArray);
+        glDrawElements (aMode, nSize, aType,
+                        pObject->myPolygons.ArrayIndexes(i));
       }
     }
   }
-  if (pObject->IsSegments())
-    glDrawElements (GL_LINES, pObject->NLineNodes(),
-                    aType, pObject->mypLines);
+  if (pObject->IsSegments() && pObject->NLineNodes() > 0) {    
+    glDrawElements (GL_LINES, pObject->NLineNodes(0),
+                    aType, pObject->myLines.ArrayIndexes(0));
+  }
   else {
     Standard_Boolean isLoop;
     if (pObject->IsLine(isLoop))
     {
-      if (isLoop) {
-//         glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
-        glDrawElements (GL_LINE_LOOP, pObject->NLineNodes(),
-                        aType, pObject->mypLines);
-//         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
-      } else {
-        glDrawElements (GL_LINE_STRIP, pObject->NLineNodes(),
-                        aType, pObject->mypLines);
+      const GLenum lineType = (isLoop ? GL_LINE_LOOP : GL_LINE_STRIP);
+      const Standard_Integer nLine = pObject->NLines();
+      for (Standard_Integer i = 0; i < nLine; i++) {
+        const Standard_Integer nSize = pObject->NLineNodes(i);
+        glDrawElements (lineType, nSize,
+                          aType, pObject->myLines.ArrayIndexes(i));
       }
     }
   }
-
 }
-
index 1dd77315468d4643017b3bac95245fde11c90001..9073c02c422d494632e4f83d85c84d54e5db8a59 100644 (file)
@@ -23,6 +23,7 @@ class NIS_Triangulated;
 
 /**
  * Drawer for interactive object type NIS_Triangulated.
+ * @ingroup nis_library
  */
 
 class NIS_TriangulatedDrawer : public NIS_Drawer
@@ -79,8 +80,8 @@ protected:
    */
   Standard_Boolean    myPolygonAsLineLoop;
 
-  Quantity_Color      myColor[5];
   Standard_ShortReal  myLineWidth;
+  Standard_Integer    myLineType;
   Standard_Boolean    myIsDrawPolygons;
   unsigned int        myPolygonType;
 
index 0d3e4a1f76ae8aa32deea6a3eb0f9dbd99c17453..d21ba446b63956274ea39c799f1820b0d1efc554 100644 (file)
@@ -13,6 +13,9 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
+#include <OpenGl_GlCore11.hxx>
+#include <OpenGl_Context.hxx>
+
 #include <NIS_View.hxx>
 #include <NIS_InteractiveContext.hxx>
 #include <NIS_InteractiveObject.hxx>
@@ -25,6 +28,8 @@
 
 IMPLEMENT_STANDARD_HANDLE  (NIS_View, V3d_OrthographicView)
 IMPLEMENT_STANDARD_RTTIEXT (NIS_View, V3d_OrthographicView)
+IMPLEMENT_STANDARD_HANDLE  (NIS_ViewData, Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT (NIS_ViewData, Standard_Transient)
 
 //=======================================================================
 //function : NIS_View()
@@ -34,11 +39,21 @@ IMPLEMENT_STANDARD_RTTIEXT (NIS_View, V3d_OrthographicView)
 NIS_View::NIS_View (const Handle(V3d_Viewer)&    theViewer,
                     const Handle(Aspect_Window)& theWindow)
   : V3d_OrthographicView (theViewer),
-    myIsTopHilight(Standard_False),
-    myDoHilightSelected(Standard_True)
+    myIsTopHilight       (Standard_False),
+    myIsTopDynHilight    (Standard_False),
+    myDoHilightSelected  (Standard_True),
+    myGlCtx              (NULL),
+    myHDC                (0L),
+    myHGLRC              (0L)
 {
-  if (!theWindow.IsNull())
+  if (!theWindow.IsNull()) {
+    myViewport[0] = -1;
     V3d_View::SetWindow (theWindow, NULL, &MyCallback, this);
+  }
+  myViewport[0] = 0;
+  myViewport[1] = 0;
+  myViewport[2] = 0;
+  myViewport[3] = 0;
 }
 
 //=======================================================================
@@ -48,7 +63,11 @@ NIS_View::NIS_View (const Handle(V3d_Viewer)&    theViewer,
 
 void NIS_View::SetWindow(const Handle(Aspect_Window) &theWindow)
 {
+  myViewport[0] = -1;
   V3d_View::SetWindow (theWindow, NULL, &MyCallback, this);
+  myViewport[0] = 0;
+  myHDC = 0L;
+  myHGLRC = 0L;
 }
 
 // //=======================================================================
@@ -90,11 +109,17 @@ void NIS_View::RemoveContext (NIS_InteractiveContext * theCtx)
       break;
     }
 
+  // If draw lists are shared in this Context then they should be
+  // destroyed when we detach from the last view (1 remaining view is detached).
+  Standard_Boolean isForcedDestroy(Standard_False);
+  if (theCtx->myIsShareDrawList && theCtx->myViews.Extent() == 1)
+    isForcedDestroy = Standard_True;
+
   NCollection_Map<Handle_NIS_Drawer>::Iterator anIterD (theCtx->GetDrawers ());
   for (; anIterD.More(); anIterD.Next()) {
     const Handle(NIS_Drawer)& aDrawer = anIterD.Value();
     if (aDrawer.IsNull() == Standard_False) {
-      aDrawer->UpdateExListId(this);
+      aDrawer->UpdateExListId(isForcedDestroy ? 0L : this);
     }
   }
 }
@@ -185,6 +210,46 @@ Standard_Boolean NIS_View::FitAll3d (const Quantity_Coefficient theCoef)
   return aResult;
 }
 
+//=======================================================================
+//function : GetViewData
+//purpose  : get or create a new ViewData instance.
+//           For thread safety the instances are kept in a list instead of
+//           map: operation List::Append is atomic thus safe.
+//=======================================================================
+
+Handle_NIS_ViewData& NIS_View::GetViewData (const char * theKey)
+{
+  NCollection_List<struct NamedViewData>::Iterator anIter(myViewData);
+  for (; anIter.More(); anIter.Next()) {
+    const NamedViewData& aData = anIter.Value();
+    if (aData.Name.IsEqual(theKey))
+      break;
+  }
+  if (anIter.More())
+    return anIter.ChangeValue().Data;
+  struct NamedViewData aNewData;
+  aNewData.Name = theKey;
+  return myViewData.Append(aNewData).Data; 
+}
+
+//=======================================================================
+//function : Remove
+//purpose  : Expressly close internal data structures
+//=======================================================================
+
+void NIS_View::Remove ()
+{
+  if (!myGlCtx.IsNull())
+  {
+    if (myGlCtx->MakeCurrent())
+    {
+      myGlCtx.Nullify();
+      myViewData.Clear();
+    }
+  }
+  V3d_View::Remove();
+}
+
 //=======================================================================
 //function : GetBndBox
 //purpose  :
@@ -262,42 +327,141 @@ void NIS_View::GetBndBox( Standard_Integer& theXMin, Standard_Integer& theXMax,
   }
 }
 
+//=======================================================================
+//function : MakeCurrent
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean NIS_View::MakeCurrent() const
+{
+  Standard_Boolean aResult(Standard_False);
+  HDC anActiveHdc     = wglGetCurrentDC();
+  HGLRC anActiveGlCtx = wglGetCurrentContext();
+  if (myHDC == anActiveHdc && myHGLRC == anActiveGlCtx)
+    aResult = Standard_True;
+  else if (wglMakeCurrent(reinterpret_cast<HDC>(myHDC),
+                          reinterpret_cast<HGLRC>(myHGLRC)))
+    aResult = Standard_True;
+  return aResult;
+}
 
 //=======================================================================
 //function : MyCallback
+//purpose  : 
+//=======================================================================
+
+int NIS_View::MyCallback (Aspect_Drawable /* Window ID */,
+                          void*                         theUserData, 
+                          Aspect_GraphicCallbackStruct* thecallData)
+{
+  // NKV 14.07.11: Avoid double rendering of the scene
+  // (workaround of integration from BUG OCC22377, that calls view
+  // call back twice: before drawing overlay layer and after drawing,
+  // see comments to OCC_PRE_OVERLAY definition)
+  NIS_View* thisView = static_cast<NIS_View*> (theUserData);
+  if ((thecallData->reason & OCC_PRE_OVERLAY) == 0) {
+    Handle(OpenGl_Context) aGlContext = 
+      Handle(OpenGl_Context)::DownCast(thecallData->glContext);
+    thisView->myGlCtx = aGlContext;
+    if (!thisView->myHDC)
+      thisView->myHDC = wglGetCurrentDC();
+    if (!thisView->myHGLRC)
+      thisView->myHGLRC = wglGetCurrentContext();
+    if (thisView->myViewport[0] >= 0) {
+      thisView->redrawCallback();
+    }
+  }
+
+  return 0;
+}
+
+//=======================================================================
+//function : redrawCallback
 //purpose  :
 //=======================================================================
 
-int NIS_View::MyCallback (Aspect_Drawable                /* Window ID */,
-                          void*                          ptrData,
-                          Aspect_GraphicCallbackStruct*  callData /* call data */)
+void NIS_View::redrawCallback()
 {
-  // Avoid multiple rendering of the scene ( accordingly with update of
-  // callback mechanism, that invokes additional callbacks before
-  // underlay and overlay redrawing with OCC_PRE_REDRAW and OCC_PRE_OVERLAY
-  // bits added to the "reason" value of the callback data structure;
-  // see comments to OCC_REDRAW_ADDITIONAL_CALLBACKS definition )
-  if (callData->reason & OCC_REDRAW_ADDITIONAL_CALLBACKS)
-    return 0;
-
-  const Handle(NIS_View) thisView (static_cast<NIS_View *> (ptrData));
-  NCollection_List<NIS_InteractiveContext *>::Iterator anIter;
+  // cache render mode state
+  GLint aRendMode = GL_RENDER;
+  glGetIntegerv (GL_RENDER_MODE, &aRendMode);
+
+  if (myGlCtx.IsNull() == Standard_False) {
+    myGlCtx->Init();
+    myGlCtx->SetFeedback (aRendMode == GL_FEEDBACK);
+  }
+
+  const Handle(NIS_View) thisView = this;
+
+  // ==== Get pixel size
+  {
+    glGetIntegerv(GL_VIEWPORT, myViewport);
+    Standard_Integer anX(myViewport[0] + myViewport[2]/2);
+    Standard_Integer anY(myViewport[1] + myViewport[3]/2);
+    const gp_XYZ aPnt[3] = {
+      UnConvert (anX, anY),
+      UnConvert (anX + 5, anY),
+      UnConvert (anX, anY + 5)
+    };
+    myPixelSize.SetCoord(0.2 * (aPnt[1] - aPnt[0]).Modulus(),
+                         0.2 * (aPnt[2] - aPnt[0]).Modulus());
+  }
+
+  // ==== Get view transformation
+  {
+    Standard_Real anX, anY, aZ;
+    // vector orthogonal to the view plane
+    Proj (anX, anY, aZ);
+    myProj.SetCoord (anX, anY, aZ);
+
+    // 3D point for the 3D coordinates
+    Convert(myViewport[0] + myViewport[2] / 2,
+            myViewport[1] + myViewport[3] / 2, anX, anY, aZ);
+    const gp_Pnt anEye (anX, anY, aZ);
+
+    // 3D point for the 3D coordinates
+    Convert(myViewport[0] + myViewport[2],
+            myViewport[1] + myViewport[3] / 2, anX, anY, aZ);
+    const gp_XYZ anXdir (gp_XYZ(anX, anY, aZ) - anEye.XYZ());
+    myViewSize.SetX(anXdir.Modulus());
+    Convert(myViewport[0] + myViewport[2] / 2, myViewport[1], anX, anY, aZ);
+    myViewSize.SetY((gp_XYZ(anX, anY, aZ) - anEye.XYZ()).Modulus());
+    if (anXdir.SquareModulus() > 1e-20) {
+      const gp_Ax3 anAx3 (anEye, myProj, anXdir);
+      myTrsf.SetTransformation (anAx3);
+    }
+  }
+
+  // ==== Manage the ViewData
+  NCollection_List<NamedViewData>::Iterator anIterVD(myViewData);
+  for (; anIterVD.More(); anIterVD.Next()) {
+    const Handle(NIS_ViewData)& aData = anIterVD.Value().Data;
+    if (aData.IsNull() == Standard_False) {
+      aData->Init();
+      if (aData->myView != this)
+        aData->myView = this;
+    }
+  }
+
 #ifdef CLIP
   // Find the bounding box of all displayed objects by summing the boxes stored
   // in the relevant DrawList instances.
   Bnd_B3f aBndBox;
-  for (anIter = thisView->myContexts; anIter.More(); anIter.Next())
+  NCollection_List<NIS_InteractiveContext *>::Iterator anIter = myContexts;
+  for (; anIter.More(); anIter.Next())
+  {
     anIter.Value()->GetBox (aBndBox, pView);
+  }
 
   if (aBndBox.IsVoid() == Standard_False) {
     const gp_XYZ aBoxSize   = 0.5 * (aBndBox.CornerMax() - aBndBox.CornerMin());
     const gp_XYZ aBoxCenter = 0.5 * (aBndBox.CornerMax() + aBndBox.CornerMin());
 
     // Find the ray passing through the clicked point in the view window.
-    Standard_Real anX, anY, aZ;
-    thisView->Convert(0, 0, anX, anY, aZ);  // 3D point for the 3D coordinates
+    Standard_Real aZ;
+    Convert(0, 0, anX, anY, aZ);  // 3D point for the 3D coordinates
     const gp_Pnt anEye (anX, anY, aZ);
-    thisView->Proj (anX, anY, aZ);  // vector orthogonal to the view plane
+    Proj (anX, anY, aZ);  // vector orthogonal to the view plane
     const gp_Dir aProj (anX, anY, aZ);
     const gp_Ax1 anAxis (anEye, aProj);
 
@@ -335,12 +499,13 @@ int NIS_View::MyCallback (Aspect_Drawable                /* Window ID */,
   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
   if (!isDepthTest) {
     glEnable(GL_DEPTH_TEST);
-    glDepthFunc(GL_LESS);
     glClearDepth(1.);
     glClear(GL_DEPTH_BUFFER_BIT);
   }
+  glDepthFunc(GL_LEQUAL);
+  glDepthMask(GL_TRUE);
 
-  TColStd_MapIteratorOfPackedMapOfInteger anIterM(thisView->myExListId);
+  TColStd_MapIteratorOfPackedMapOfInteger anIterM (myExListId);
   for (; anIterM.More(); anIterM.Next())
     if (anIterM.Key() != 0) {
 #ifdef ARRAY_LISTS
@@ -349,33 +514,56 @@ int NIS_View::MyCallback (Aspect_Drawable                /* Window ID */,
       glDeleteLists (anIterM.Key(), 1);
     }
 #endif
-  thisView->myExListId.Clear();
+  myExListId.Clear();
 
-  for (anIter = thisView->myContexts; anIter.More(); anIter.Next())
-    anIter.Value()->redraw (thisView, NIS_Drawer::Draw_Normal);
+  redraw (thisView, NIS_Drawer::Draw_Normal);
 
   // #818151 - selected object is hidden by covered unselected one
   // display hilighted objects always above the rest ones
-  if (thisView->myIsTopHilight == Standard_True) {
+  if (myIsTopHilight == Standard_True) {
     glDepthFunc(GL_ALWAYS);
   }
 
-  for (anIter = thisView->myContexts; anIter.More(); anIter.Next())
-    anIter.Value()->redraw (thisView, NIS_Drawer::Draw_Hilighted);
-  for (anIter = thisView->myContexts; anIter.More(); anIter.Next())
-    anIter.Value()->redraw (thisView, NIS_Drawer::Draw_DynHilighted);
-  for (anIter = thisView->myContexts; anIter.More(); anIter.Next())
-    anIter.Value()->redraw (thisView, NIS_Drawer::Draw_Transparent);
+  redraw (thisView, NIS_Drawer::Draw_Hilighted);
+
+  // Depth buffer should be read-only for transparent objects,
+  // the same for further types
+  glDepthMask(GL_FALSE);
+  redraw (thisView, NIS_Drawer::Draw_Transparent);
+  if (myIsTopDynHilight == Standard_False)
+  {
+    redraw (thisView, NIS_Drawer::Draw_DynHilighted);
+  }
 
   // draw top objects always above
-  if (thisView->myIsTopHilight == Standard_False) {
+  if (myIsTopHilight == Standard_False)
+  {
     glDepthFunc(GL_ALWAYS);
   }
+  if (myIsTopDynHilight == Standard_True)
+  {
+    redraw (thisView, NIS_Drawer::Draw_DynHilighted);
+  }
 
-  for (anIter = thisView->myContexts; anIter.More(); anIter.Next())
-    anIter.Value()->redraw (thisView, NIS_Drawer::Draw_Top);
+  redraw (thisView, NIS_Drawer::Draw_Top);
+}
 
-  return 0;
+//=======================================================================
+//function : redraw
+//purpose  :
+//=======================================================================
+
+void NIS_View::redraw (const Handle(NIS_View)&    theView,
+                       const NIS_Drawer::DrawType theType)
+{
+  for (Standard_Integer aPriority = 0; aPriority < NIS_Drawer::Priority_LevelsNb; ++aPriority)
+  {
+    for (NCollection_List<NIS_InteractiveContext *>::Iterator anIter = myContexts;
+         anIter.More(); anIter.Next())
+    {
+      anIter.Value()->redraw (theView, theType, (NIS_Drawer::PriorityLevel )aPriority);
+    }
+  }
 }
 
 //=======================================================================
@@ -383,19 +571,24 @@ int NIS_View::MyCallback (Aspect_Drawable                /* Window ID */,
 //purpose  :
 //=======================================================================
 
-void NIS_View::DynamicHilight  (const Standard_Integer theX,
-                                const Standard_Integer theY)
+Standard_Boolean NIS_View::DynamicHilight  (const Standard_Integer theX,
+                                            const Standard_Integer theY)
 {
+  Standard_Boolean aResult(Standard_False);
   myDetected.Clear();
-  const Handle(NIS_InteractiveObject) aSelected = Pick (theX, theY);
+
+  const Handle(NIS_InteractiveObject) aSelected =
+    Pick (theX, theY, NIS_SelectFilter::DynHilight);
 
   // ASV: if at least one Context returns IsSelectable()==False,
   // hilight is canceled, this method returns
-  if (aSelected.IsNull() == Standard_False) {
-    if (aSelected->IsSelectable() == Standard_False)
-      return;
-  }
-  if (aSelected != myDynHilighted) {
+  if ((aSelected.IsNull() == Standard_False &&
+       aSelected->IsSelectable() == Standard_False) ||
+      aSelected == myDynHilighted)
+  {
+    ;//DrawDirect(theX, theY);
+  } else {
+    //DrawDirect(theX, theY, Standard_False);
     const Handle(NIS_View) aView (this);
     if (myDynHilighted.IsNull() == Standard_False)
       if (myDynHilighted->GetDrawer().IsNull() == Standard_False)
@@ -415,7 +608,9 @@ void NIS_View::DynamicHilight  (const Standard_Integer theX,
       myDynHilighted = aSelected;
     }
     Redraw();
+    aResult = Standard_True;
   }
+  return aResult;
 }
 
 //=======================================================================
@@ -425,7 +620,7 @@ void NIS_View::DynamicHilight  (const Standard_Integer theX,
 
 void NIS_View::DynamicUnhilight(const Handle_NIS_InteractiveObject& theObj)
 {
-  if (theObj == myDynHilighted && theObj.IsNull() == Standard_False) {
+  if (theObj.IsNull() == Standard_False && theObj == myDynHilighted) {
     const Handle(NIS_View) aView (this);
     if (myDynHilighted->GetDrawer().IsNull() == Standard_False)
       myDynHilighted->GetDrawer()->SetDynamicHilighted (Standard_False,
@@ -442,21 +637,32 @@ void NIS_View::DynamicUnhilight(const Handle_NIS_InteractiveObject& theObj)
 
 void NIS_View::Select (const Standard_Integer theX,
                        const Standard_Integer theY,
-                       const Standard_Boolean isForceMultiple,
+                       const Standard_Boolean isModifierUsed,
                        const Standard_Boolean theRedraw)
 {
   myDetected.Clear();
-  const Handle(NIS_InteractiveObject) aSelected = Pick (theX, theY);
+  Standard_Real anOver;
+  const gp_Ax1 anAxis = PickAxis(theX, theY, anOver);
+  const Handle(NIS_InteractiveObject) aSelected =
+    Pick(anAxis, anOver, Standard_True, 0L, NIS_SelectFilter::Pick);
+
   NCollection_List<NIS_InteractiveContext *>::Iterator anIter (myContexts);
-  for (; anIter.More(); anIter.Next())
-    anIter.Value()->ProcessSelection (aSelected, isForceMultiple);
+  Standard_Boolean isProcessed(Standard_False);
+  for (; anIter.More(); anIter.Next()) {
+    NIS_InteractiveContext* aCtx = anIter.Value();
+    if (aCtx != 0L)
+      if (aCtx->ProcessSelection (aSelected, isModifierUsed))
+        isProcessed = Standard_True;
+  }
   if (aSelected == myDynHilighted && aSelected.IsNull() == Standard_False)
   {
     myDynHilighted.Nullify();
     const Handle(NIS_Drawer)& aDrawer = aSelected->GetDrawer();
     aDrawer->SetDynamicHilighted (Standard_False, aSelected, this);
+    isProcessed = Standard_True;
   }
-  if (theRedraw) Redraw();
+  if (theRedraw && isProcessed)
+    Redraw();
 }
 
 //=======================================================================
@@ -468,7 +674,7 @@ void NIS_View::Select (const Standard_Integer  theXmin,
                        const Standard_Integer  theYmin,
                        const Standard_Integer  theXmax,
                        const Standard_Integer  theYmax,
-                       const Standard_Boolean  isForceMult,
+                       const Standard_Boolean  isModifierUsed,
                        const Standard_Boolean  isFullyIncluded,
                        const Standard_Boolean  theRedraw)
 {
@@ -506,7 +712,7 @@ void NIS_View::Select (const Standard_Integer  theXmin,
     NIS_InteractiveContext * pCtx = anIterC.Value();
     mapSelected.Clear();
     pCtx->selectObjects (mapSelected, aBoxSel, aTrfInv, aTrf, isFullyIncluded);
-    pCtx->ProcessSelection (mapSelected, isForceMult);
+    pCtx->ProcessSelection (mapSelected, isModifierUsed);
   }
   if (theRedraw) Redraw();
 }
@@ -517,12 +723,12 @@ void NIS_View::Select (const Standard_Integer  theXmin,
 //=======================================================================
 
 void  NIS_View::Select (const NCollection_List<gp_XY> &thePolygon,
-                        const Standard_Boolean         isForceMult,
+                        const Standard_Boolean         isModifierUsed,
                         const Standard_Boolean         isFullyIncluded,
                         const Standard_Boolean         theRedraw)
 {
   myDetected.Clear();
-  if (thePolygon.IsEmpty())
+  if (thePolygon.Extent() < 3)
     return;
 
   Standard_Real anX, anY, aZ;
@@ -578,32 +784,50 @@ void  NIS_View::Select (const NCollection_List<gp_XY> &thePolygon,
     NIS_InteractiveContext * pCtx = anIterC.Value();
     mapSelected.Clear();
     pCtx->selectObjects (mapSelected, aPoints, aPolyBox, aTrf, isFullyIncluded);
-    pCtx->ProcessSelection (mapSelected, isForceMult);
+    pCtx->ProcessSelection (mapSelected, isModifierUsed);
   }
 
   if (theRedraw) Redraw();
 }
 
 //=======================================================================
-//function : Pick
+//function : PickAxis
 //purpose  :
 //=======================================================================
 
-Handle_NIS_InteractiveObject NIS_View::Pick (const Standard_Integer theX,
-                                             const Standard_Integer theY)
+gp_Ax1 NIS_View::PickAxis       (const Standard_Integer theX,
+                                 const Standard_Integer theY,
+                                 Standard_Real&         theOver)
 {
   // Find the ray passing through the clicked point in the view window.
-  Standard_Real anX, anY, aZ, anOver;
+  Standard_Real anX, anY, aZ;
   Convert(theX, theY, anX, anY, aZ);  // 3D point for the 3D coordinates
   const gp_Pnt anEye (anX, anY, aZ);
+#ifdef OBSOLETE
   Proj (anX, anY, aZ);                // vector orthogonal to the view plane
   const gp_Dir aProj (-anX, -anY, -aZ);
   const gp_Ax1 anAxis (anEye, aProj);
 
   Convert (theX+1, theY+1, anX, anY, aZ);
-  anOver = ((gp_XYZ(anX, anY, aZ) - anEye.XYZ()) ^ aProj.XYZ()).Modulus() * 1.5;
+  theOver= ((gp_XYZ(anX, anY, aZ) - anEye.XYZ()) ^ aProj.XYZ()).Modulus() * 1.5;
+#endif
+  theOver = 2 * myPixelSize.Modulus();
+  return gp_Ax1(anEye, -gp_Dir(myProj));
+}
 
-  return Pick(anAxis, anOver, Standard_True);
+//=======================================================================
+//function : Pick
+//purpose  : 
+//=======================================================================
+
+Handle_NIS_InteractiveObject NIS_View::Pick
+                                (const Standard_Integer theX,
+                                 const Standard_Integer theY,
+                                 const NIS_SelectFilter::Event theEvent)
+{
+  Standard_Real anOver;
+  const gp_Ax1 anAxis = PickAxis(theX, theY, anOver);
+  return Pick(anAxis, anOver, Standard_True, 0L, theEvent);
 }
 
 //=======================================================================
@@ -612,32 +836,101 @@ Handle_NIS_InteractiveObject NIS_View::Pick (const Standard_Integer theX,
 //=======================================================================
 
 Handle_NIS_InteractiveObject NIS_View::Pick
-                                (const gp_Ax1&          theAxis,
-                                 const Standard_Real    theOver,
-                                 const Standard_Boolean isOnlySelectable)
+                                (const gp_Ax1&           theAxis,
+                                 const Standard_Real     theOver,
+                                 const Standard_Boolean  isOnlySelectable,
+                                 Standard_Real*          theDistance,
+                                 const NIS_SelectFilter::Event theEvent)
 {
   typedef NCollection_List<NIS_InteractiveContext::DetectedEnt> LstDetected;
-  Standard_Real                 aDistance (0.1 * RealLast());
-  Handle(NIS_InteractiveObject) aSelected, aTmpSel;
   LstDetected aDetected;
-
-  NCollection_List<NIS_InteractiveContext *>::Iterator anIterC (myContexts);
-  for (; anIterC.More(); anIterC.Next()) {
-    const Standard_Real aDist =
-      anIterC.Value()->selectObject (aTmpSel, aDetected, theAxis, theOver,
-                                     isOnlySelectable);
-    if (aDist < aDistance) {
-      aDistance = aDist;
-      aSelected = aTmpSel;
-    }
+  for (NCollection_List<NIS_InteractiveContext*>::Iterator anIterC (myContexts);
+       anIterC.More(); anIterC.Next())
+  {
+    anIterC.Value()->selectObject (aDetected, theAxis, theOver, isOnlySelectable, theEvent);
   }
 
   // simple iterating is enough to create list of detected objects
   // in the order of increasing distance
   myDetected.Clear();
-  for (LstDetected::Iterator anIt(aDetected); anIt.More(); anIt.Next())
-    myDetected.Append(anIt.Value().PObj);
+  for (LstDetected::Iterator anIt (aDetected); anIt.More(); anIt.Next())
+  {
+    myDetected.Append (anIt.Value().PObj);
+  }
+
+  Handle(NIS_InteractiveObject) aSelected = aDetected.IsEmpty() ? (NIS_InteractiveObject* )NULL : aDetected.First().PObj;
+  if (theDistance != NULL)
+  {
+    *theDistance = aDetected.IsEmpty() ? (0.1 * RealLast()) : aDetected.First().Dist;
+  }
 
+  if (aSelected.IsNull())
+  {
+    return aSelected;
+  }
+
+  // notify the SelectFilter if available
+  NIS_InteractiveContext* aSelectedCtx = aSelected->GetDrawer()->GetContext();
+  if (aSelectedCtx != NULL
+   && !aSelectedCtx->GetFilter().IsNull()
+   && aSelectedCtx->GetFilter()->ActsOn (aSelected->DynamicType()))
+  {
+    NIS_SelectFilter::Event aFinalEvent = NIS_SelectFilter::Indefinite;
+    if (theEvent == NIS_SelectFilter::Pick)
+    {
+      aFinalEvent = NIS_SelectFilter::Picked;
+    }
+    else if (theEvent == NIS_SelectFilter::DynHilight)
+    {
+      aFinalEvent = NIS_SelectFilter::DynHilighted;
+    }
+    aSelectedCtx->GetFilter()->IsOk (aSelected.operator->(), theAxis,
+                                     theOver, aFinalEvent);
+  }
   return aSelected;
 }
 
+//=======================================================================
+//function : UnConvert
+//purpose  : 2d pixel coord => 3d point coord in Ortho viewer
+//=======================================================================
+
+gp_XYZ NIS_View::UnConvert (const Standard_Integer theX,
+                            const Standard_Integer theY) const
+{
+  const Visual3d_ViewOrientation anOri = ViewOrientation();
+  Standard_Real anX, anY, aZ, anXp, anYp;
+  anOri.ViewReferencePoint().Coord(anX, anY, aZ);
+  gp_XYZ anOrigin(anX, anY, aZ);
+  anOri.ViewReferencePlane().Coord(anX, anY, aZ);
+  gp_XYZ aNorm(anX, anY, aZ);
+  anOri.ViewReferenceUp().Coord(anX, anY, aZ);
+  gp_XYZ anYdir(anX, anY, aZ);
+  gp_XYZ anXdir = anYdir ^ aNorm;
+  Convert(theX, theY, anXp, anYp);
+  return (anOrigin + anXdir * anXp + anYdir * anYp);
+}
+
+//=======================================================================
+//function : ClipToViewport
+//purpose  : Test and clip the given coordinates to fit to the Viewport
+//=======================================================================
+
+Standard_Boolean NIS_View::ClipToViewport  (Standard_Integer& theX,
+                                            Standard_Integer& theY) const
+{
+  Standard_Integer iResult(0);
+  if (theX < myViewport[0])
+    theX = myViewport[0];
+  else if (theX >= myViewport[0] + myViewport[2])
+    theX = myViewport[0] + myViewport[2] - 1;
+  else
+    iResult |= 0x1; 
+  if (theY < myViewport[1])
+    theY = myViewport[1];
+  else if (theY >= myViewport[1] + myViewport[3])
+    theY = myViewport[1] + myViewport[3] - 1;
+  else
+    iResult |= 0x2;
+  return iResult == 0x3;
+}
index ff72eccfa213c9a6a5fb3a5cec726417e1b48826..59ca11dd81b8ad1ba66c62073c29119322440b2e 100644 (file)
 #ifndef NIS_View_HeaderFile
 #define NIS_View_HeaderFile
 
+#include <Handle_OpenGl_Context.hxx>
 #include <Handle_NIS_InteractiveObject.hxx>
-#include <V3d_OrthographicView.hxx>
-#include <Standard_DefineHandle.hxx>
+#include <Bnd_B3f.hxx>
 #include <NCollection_List.hxx>
 #include <NCollection_Vector.hxx>
-#include <Bnd_B3f.hxx>
+#include <NIS_Drawer.hxx>
+#include <NIS_SelectFilter.hxx>
+#include <NIS_ViewData.hxx>
+#include <Standard_DefineHandle.hxx>
+#include <TCollection_AsciiString.hxx>
 #include <TColStd_PackedMapOfInteger.hxx>
+#include <V3d_OrthographicView.hxx>
 #include <gp_XY.hxx>
 
 class NIS_InteractiveContext;
+class Handle_NIS_View;
 class gp_Ax1;
 
 /**
@@ -51,6 +57,7 @@ class gp_Ax1;
  * </ul>
  * The list of associated NIS_InteractiveContext can be modified by methods
  * AddContext and RemoveContext.
+ * @ingroup nis_library
  */
 
 class NIS_View : public V3d_OrthographicView
@@ -75,6 +82,12 @@ class NIS_View : public V3d_OrthographicView
    */
   inline void SetHilightOnTop(const Standard_Boolean theTop = Standard_True)
   { myIsTopHilight = theTop; }
+  
+  /**
+   * Indicate whether to draw dynamic hilighted objects on top of all other ones
+   */
+  inline void SetDynHilightOnTop(const Standard_Boolean theTop = Standard_True)
+  { myIsTopDynHilight = theTop; }
 
   /**
    * Indicate whether to hilight selected object dynamically
@@ -89,6 +102,12 @@ class NIS_View : public V3d_OrthographicView
                                          theHilight = Standard_True)
   { myDoHilightSelected = theHilight; }
 
+  /**
+   * Gets indentifier whether a selected object should be dynamically highlighted
+   */
+  inline Standard_Boolean GetDynHilightSelected () const
+  { return myDoHilightSelected; }
+
   /**
    * Zoom the view to fit to visible objects size and positions.
    * @param theCoef
@@ -101,6 +120,71 @@ class NIS_View : public V3d_OrthographicView
   Standard_EXPORT Standard_Boolean FitAll3d (const Quantity_Coefficient theCoef
                                              = 0.01);
 
+  /**
+   * Get the reference to GL context.
+   */
+  inline const Handle_OpenGl_Context& GetGlContext() const
+  { return myGlCtx; }
+
+  /**
+   * Get the reference to GL Data.
+   * @return
+   *   Handle to ViewData for the unique value of theKey.
+   *   If theKey is unknown, a ViewData handle is created and added to the Map
+   */
+  Standard_EXPORT Handle_NIS_ViewData& GetViewData (const char * theKey);
+
+  /**
+   * Expressly close internal data structures, particularly OpenGl buffer
+   * objects, that may be hard to close in usual way, using destructor.
+   */
+  Standard_EXPORT virtual void  Remove ();
+
+  /**
+   * Query the size of 1 pixel in the middle, in X and Y directions.
+   */
+  inline const gp_XY&           GetPixelSize    () const
+  { return myPixelSize; }
+
+  /**
+   * Query the view size. X and Y directions components are half dimensions
+   * of the view box. To obtain the view box you can use:
+   * @code
+   *   aViewBox.SetCenter(0., 0., 0.);
+   *   aViewBox.SetHSize(aV->GetViewSize().X(), aV->GetViewSize().Y(), 10000.);
+   * @endcode
+   * The last parameter (10000) is arbitrary.
+   */
+  inline const gp_XY&           GetViewSize     () const
+  { return myViewSize; }
+
+  /**
+   * Get the viewport values as returned by GL_VIEWPORT OpenGl call.
+   * Normally, Index 0 and 1 - upper left corner, index 2 and 3 - width and
+   * height in pixels.
+   */
+  inline Standard_Integer       Viewport        (const Standard_Integer i) const
+  { return myViewport[i&3]; }
+
+  /**
+   * Check the input X, Y coordinates if they are outside the viewport and
+   * if they happen to be then correct to match.
+   * @return
+   *   True if correction has been made
+   */
+  Standard_EXPORT  Standard_Boolean
+                                ClipToViewport  (Standard_Integer& theX,
+                                                 Standard_Integer& theY) const;
+
+  /**
+   * Get view transformation. If you apply it to a real-space object then the
+   * object is moved to the coordinate system of the view box (see GetViewSize)
+   * that has its center in the middle of the view area and is oriented
+   * according to the current view matrix.
+   */
+  inline const gp_Trsf&         Transformation  () const
+  { return myTrsf; }
+
   /**
    * Gets bounding box covering objects displayed in viewer.
    */
@@ -123,8 +207,10 @@ class NIS_View : public V3d_OrthographicView
   /**
    * Set or unset the dynamically hilighted object, depending on the
    * given mouse coordinates.
+   * @return True if hilighting/unhilighting takes place.
    */
-  Standard_EXPORT void  DynamicHilight  (const Standard_Integer theX,
+  Standard_EXPORT Standard_Boolean  DynamicHilight
+                                        (const Standard_Integer theX,
                                          const Standard_Integer theY);
 
   /**
@@ -145,15 +231,15 @@ class NIS_View : public V3d_OrthographicView
    *   X coordinate of the view window
    * @param theY
    *   X coordinate of the view window
-   * @param isForceMult
-   *   True if the effect of multi-Selection should be forced (e.g., when Shift
-   *   is pressed).
+   * @param isModifierUsed
+   *   The selection modifier state. If the effect of multi-Selection should be
+   *   forced in the Normal selection mode (the Shift is pressed).
    * @param theRedraw
    *   True to redraw view automatically (default value).
    */
   Standard_EXPORT void  Select          (const Standard_Integer theX,
                                          const Standard_Integer theY,
-                                         const Standard_Boolean isForceMult
+                                         const Standard_Boolean isModifierUsed
                                                          = Standard_False,
                                          const Standard_Boolean theRedraw
                                                          = Standard_True);
@@ -169,9 +255,9 @@ class NIS_View : public V3d_OrthographicView
    *   right X coordinate of the view window
    * @param theYmax
    *   upper Y coordinate of the view window
-   * @param isForceMult
-   *   True if the effect of multi-Selection should be forced (e.g., when Shift
-   *   is pressed).
+   * @param isModifierUsed
+   *   The selection modifier state. If the effect of multi-Selection should be
+   *   forced in the Normal selection mode (the Shift is pressed).
    * @param isFullyIncluded
    *   True if only those objects are processed that are fully inside the
    *   selection rectangle. False if objects fully or partially included in
@@ -183,7 +269,7 @@ class NIS_View : public V3d_OrthographicView
                                          const Standard_Integer  theYmin,
                                          const Standard_Integer  theXmax,
                                          const Standard_Integer  theYmax,
-                                         const Standard_Boolean  isForceMult
+                                         const Standard_Boolean  isModifierUsed
                                                          = Standard_False,
                                          const Standard_Boolean isFullyIncluded
                                                          = Standard_False,
@@ -198,9 +284,9 @@ class NIS_View : public V3d_OrthographicView
    *   self-intersections. The last point should not coincide with the first
    *   point of the list. Points are interpreted as X and Y integer coordinates
    *   of the view window. Any two neighbor points should not be confused.
-   * @param isForceMult
-   *   True if the effect of multi-Selection should be forced (e.g., when Shift
-   *   is pressed).
+   * @param isModifierUsed
+   *   The selection modifier state. If the effect of multi-Selection should be
+   *   forced in the Normal selection mode (the Shift is pressed).
    * @param isFullyIncluded
    *   True if only those objects are processed that are fully inside the
    *   selection rectangle. False if objects fully or partially included in
@@ -209,13 +295,28 @@ class NIS_View : public V3d_OrthographicView
    *   True to redraw view automatically (default value).
    */
   Standard_EXPORT void  Select   (const NCollection_List<gp_XY> &thePolygon,
-                                  const Standard_Boolean         isForceMult
+                                  const Standard_Boolean         isModifierUsed
                                                          = Standard_False,
                                   const Standard_Boolean         isFullyIncluded
                                                          = Standard_False,
                                   const Standard_Boolean theRedraw
                                                          = Standard_True);
 
+  /**
+   * Computation of 3D axis for objects selection
+   * @param theX
+   *   X coordinate of mouse pointer in the window.
+   * @param theY
+   *   Y coordinate of mouse pointer in the window.
+   * @param theOver
+   *   Overlap for the returned 3D axis
+   * @return
+   *   3D axis for objects selection
+   */
+  Standard_EXPORT gp_Ax1 PickAxis       (const Standard_Integer theX,
+                                         const Standard_Integer theY,
+                                         Standard_Real&         theOver);
+
   /**
    * Interactive selection by mouse click. Selection itself is performed in each
    * Interactive Context attached to this View, accordingto the local parameters
@@ -224,17 +325,21 @@ class NIS_View : public V3d_OrthographicView
    *   X coordinate of mouse pointer in the window.
    * @param theY
    *   Y coordinate of mouse pointer in the window.
+   * @param theEvent
+   *   Event that invokes this method
    * @return
    *   the selected object picked by the minimal intersection distance among
    *   all contexts attached to this View.
    */
   Standard_EXPORT Handle_NIS_InteractiveObject
                         Pick            (const Standard_Integer theX,
-                                         const Standard_Integer theY);
+                                         const Standard_Integer theY,
+                                         const NIS_SelectFilter::Event theEvent
+                                         = NIS_SelectFilter::Indefinite);
 
   /**
    * Interactive selection by mouse click. Selection itself is performed in each
-   * Interactive Context attached to this View, accordingto the local parameters
+   * Interactive Context attached to this View, according to the local parameters
    * (mode, filter) of selection in each context. 
    * @param theAxis
    *   3D axis for objects selection
@@ -243,6 +348,11 @@ class NIS_View : public V3d_OrthographicView
    * @param isOnlySel
    *   If False, any displayed object can be picked, otherwise only selectable
    *   ones.
+   * @param pDistance
+   *   Optional parameter, if defined then the shortest distance for picked
+   *   object along the axis to projection point will be stored in it.
+   * @param theEvent
+   *   Event that invokes this method
    * @return
    *   the selected object picked by the minimal intersection distance among
    *   all contexts attached to this View.
@@ -250,7 +360,25 @@ class NIS_View : public V3d_OrthographicView
   Standard_EXPORT Handle_NIS_InteractiveObject
                         Pick            (const gp_Ax1&          theAxis,
                                          const Standard_Real    theOver,
-                                         const Standard_Boolean isOnlySel);
+                                         const Standard_Boolean isOnlySel,
+                                         Standard_Real*         pDistance = 0L,
+                                         const NIS_SelectFilter::Event theEvent
+                                         = NIS_SelectFilter::Indefinite);
+
+  /**
+   * Having pixel coordinates (X, Y starting from the top left corner) returns
+   * 3D coordinates of the corresponding point on view plane.
+   */
+  Standard_EXPORT gp_XYZ UnConvert      (const Standard_Integer theX,
+                                         const Standard_Integer theY) const;
+
+  /**
+   * Called outside the loop of refresing the view. Makes this OpenGl context
+   * current for the actual thread.
+   * @return False if failed.
+   */
+  Standard_EXPORT Standard_Boolean
+                         MakeCurrent    () const;
 
   /**
    * Gets all objects detected by last call of Pick() method
@@ -264,6 +392,15 @@ class NIS_View : public V3d_OrthographicView
   inline TColStd_PackedMapOfInteger& GetExListId ()
   { return myExListId; }
 
+  /**
+   * Get all contexts of view
+   */
+  inline NCollection_List<NIS_InteractiveContext *> GetContexts () const
+  { return myContexts; }
+
+  inline const Handle_NIS_InteractiveObject& GetDynHilighted() const
+  { return myDynHilighted; }
+
  protected:
   // ---------- PROTECTED METHODS ----------
 
@@ -271,6 +408,14 @@ class NIS_View : public V3d_OrthographicView
                          void*                          /* user data */, 
                          Aspect_GraphicCallbackStruct*  /* call data */);
 
+  Standard_EXPORT void redrawCallback();
+
+  /**
+   * Redraw all interactive contexts.
+   */
+  Standard_EXPORT void redraw (const Handle_NIS_View&     theView,
+                               const NIS_Drawer::DrawType theType);
+
   /**
    * Register an interactive context for this view.
    */
@@ -283,13 +428,30 @@ class NIS_View : public V3d_OrthographicView
 
  private:
   // ---------- PRIVATE FIELDS ----------
+  struct NamedViewData {
+    TCollection_AsciiString Name;
+    Handle_NIS_ViewData     Data;
+  };
 
   NCollection_List<NIS_InteractiveContext *>       myContexts;
   Handle_NIS_InteractiveObject                     myDynHilighted;
   Standard_Boolean                                 myIsTopHilight      : 1;
+  Standard_Boolean                                 myIsTopDynHilight   : 1;
   Standard_Boolean                                 myDoHilightSelected : 1;
+  Standard_Boolean                                 myIsDrawArea        : 1;
   NCollection_Vector<NIS_InteractiveObject *>      myDetected;
   TColStd_PackedMapOfInteger                       myExListId;
+  Handle_OpenGl_Context                            myGlCtx;
+
+  Standard_Integer                                 myViewport[4];
+  gp_XY                                            myPixelSize;
+  gp_XY                                            myViewSize;
+  gp_XYZ                                           myProj;  // view Z direction
+  gp_Trsf                                          myTrsf;
+  NCollection_List<struct NamedViewData>           myViewData;
+
+  void *                                           myHDC;
+  void *                                           myHGLRC;
 
   friend class NIS_InteractiveContext;
 
diff --git a/src/NIS/NIS_ViewData.hxx b/src/NIS/NIS_ViewData.hxx
new file mode 100644 (file)
index 0000000..2783eeb
--- /dev/null
@@ -0,0 +1,57 @@
+// File:      NIS_ViewData.hxx
+// Created:   11.05.12 17:26
+// Author:    Alexander GRIGORIEV
+// Copyright: Open Cascade 2012
+
+
+#ifndef NIS_ViewData_HeaderFile
+#define NIS_ViewData_HeaderFile
+
+#include <Standard_Transient.hxx>
+#include <Standard_DefineHandle.hxx>
+class NIS_View;
+
+/**
+ * Data belonging to particular instances of NIS_View, to extend the basic features of NIS_View.
+ * There may be several data objects per View, distinguished by their names
+ * (method NIS_View::GetViewData)
+ * @see NIS_View
+ * @ingroup nis_library
+ */
+
+class NIS_ViewData : public Standard_Transient
+{
+ public:
+  // ---------- PUBLIC METHODS ----------
+
+
+  /**
+   * Empty constructor.
+   */
+  NIS_ViewData () : myView (0L) {}
+
+  /**
+   * Method that is called on every refresh cycle of NIS_View.
+   */
+  Standard_EXPORT virtual void Init () = 0;
+
+  /**
+   * Query the host view.
+   */
+  inline NIS_View* GetView () const
+  { return myView; }
+
+ private:
+  NIS_View*  myView;
+
+ public:
+// Declaration of CASCADE RTTI
+DEFINE_STANDARD_RTTI (NIS_ViewData)
+  friend class NIS_View;
+};
+
+// Definition of HANDLE object using Standard_DefineHandle.hxx
+DEFINE_STANDARD_HANDLE (NIS_ViewData, Standard_Transient)
+
+
+#endif
diff --git a/src/OSD/OSD_MPData.cxx b/src/OSD/OSD_MPData.cxx
new file mode 100644 (file)
index 0000000..45e7930
--- /dev/null
@@ -0,0 +1,114 @@
+// File:      OSD_MPData.cxx
+// Created:   29.06.09 09:19
+// Author:    Alexander GRIGORIEV
+// Copyright: Open Cascade 2009
+
+#include <OSD_MProcess.hxx>
+
+#ifdef WNT
+// 'this' : used in base member initializer list
+#pragma warning(disable:4355)
+#endif
+
+static const OSD_MProcess * DummyProcessor = 0L;
+
+//=======================================================================
+//function : OSD_MPData
+//purpose  : Empty constructor
+//=======================================================================
+
+OSD_MPData::OSD_MPData ()
+  : myID              (0u),
+    myPrevious        (this),
+    myNext            (this),
+    myThreadID        (UINT_MAX),
+    myProcessor       (* DummyProcessor),
+    myStatus          (StatusEmpty)    
+{
+  myThreadID = UINT_MAX;
+}
+
+//=======================================================================
+//function : OSD_MPData()
+//purpose  : Constructor
+//=======================================================================
+
+OSD_MPData::OSD_MPData (const OSD_MProcess& theProcessor)
+  : myPrevious  (this),
+    myNext      (this),
+    myThreadID  (UINT_MAX),
+    myProcessor (theProcessor),
+    myStatus    (StatusEmpty)
+{
+  static volatile Standard_Size MyCounter = 0u;
+  myID = MyCounter++;
+}
+
+//=======================================================================
+//function : ~OSD_MPData
+//purpose  : Destructor
+//=======================================================================
+
+OSD_MPData::~OSD_MPData ()
+{
+}
+
+//=======================================================================
+//function : AddBefore
+//purpose  : Insert a new data object in the queue
+//=======================================================================
+
+void OSD_MPData::AddBefore (OSD_MPData * theAdded)
+{
+  theAdded->myPrevious = myPrevious;
+  theAdded->myNext = this;
+  myPrevious->myNext = theAdded;
+  myPrevious = theAdded;
+}
+
+//=======================================================================
+//function : Detach
+//purpose  : Remove this data object from the queue
+//=======================================================================
+
+void OSD_MPData::Detach ()
+{
+  myPrevious->myNext = myNext;
+  myNext->myPrevious = myPrevious;
+//   myPrevious = this;
+//   myNext = this;
+  myThreadID = UINT_MAX;
+}
+
+//=======================================================================
+//function : ThreadAlloc
+//purpose  : Get the thread-owned allocator instance
+//=======================================================================
+
+const Handle_NCollection_IncAllocator& OSD_MPData::ThreadAlloc() const
+{
+  if (myThreadID == UINT_MAX) {
+    static Handle_NCollection_IncAllocator aNullAlloc;
+    aNullAlloc.Nullify();
+    return aNullAlloc;
+  }
+  return myProcessor.myArrThread[myThreadID].Allocator();
+}
+
+//=======================================================================
+//function : Process
+//purpose  : 
+//=======================================================================
+
+void OSD_MPData::Process ()
+{
+}
+
+//=======================================================================
+//function : PostProcess
+//purpose  : 
+//=======================================================================
+
+void OSD_MPData::PostProcess ()
+{
+}
diff --git a/src/OSD/OSD_MPData.hxx b/src/OSD/OSD_MPData.hxx
new file mode 100644 (file)
index 0000000..fec9af7
--- /dev/null
@@ -0,0 +1,96 @@
+// File:      OSD_MPData.hxx
+// Created:   29.06.09 09:01
+// Author:    Alexander GRIGORIEV
+// Copyright: Open Cascade 2009
+
+
+#ifndef OSD_MPData_HeaderFile
+#define OSD_MPData_HeaderFile
+
+#include <NCollection_IncAllocator.hxx>
+class OSD_MProcess;
+
+#ifdef WNT
+// Disable the warning "operator new unmatched by delete"
+#pragma warning (push)
+#pragma warning (disable:4291)
+#endif
+
+/**
+ * Data block processed by MP execution thread (OSD_MPThread)
+ */
+
+class OSD_MPData
+{
+ public:
+  // ---------- PUBLIC METHODS ----------
+  enum Status {
+    StatusEmpty = 0,            ///! empty data block, being initialized
+    StatusWait,                 ///! initialized with data, waiting for thread
+    StatusRequested,            ///! Data requested by thread but not assigned
+    StatusProcess,              ///! captured by thread, being processed
+    StatusDone,                 ///! released by thread after success
+    DummyData
+  };
+
+  //!Empty constructor.
+  Standard_EXPORT OSD_MPData ();
+
+  //! Consructor
+  Standard_EXPORT OSD_MPData (const OSD_MProcess& theProcessor);
+
+  //! Virtual destructor
+  Standard_EXPORT virtual ~OSD_MPData ();
+
+  //!! Allocator-based operator new for dynamic allocations
+  inline void* operator new (Standard_Size theSz,
+                             const Handle_NCollection_BaseAllocator& theAlloc)
+  { return theAlloc->Allocate(theSz); }
+
+  //! Query the unique ID of the data block
+  inline Standard_Size          ID       () const { return myID; }
+
+  //! Query the ID of the holding thread
+  inline unsigned int           ThreadID () const { return myThreadID; }
+
+  //! Get the thread-owned allocator instance
+  Standard_EXPORT const Handle_NCollection_IncAllocator&
+                                ThreadAlloc() const;
+
+  //! Processing of the data block, implements the algorithm executed by thread
+  Standard_EXPORT virtual void  Process  ();
+
+  //! Retrieving the calculated data (optional). This method is executed
+  //! in main thread, from OSD_MProcess::TakeData
+  Standard_EXPORT virtual void  PostProcess ();
+
+ private:
+  //! Insert a new data object in the queue
+  Standard_EXPORT void  AddBefore (OSD_MPData * theAdded);
+
+  //! Remove this data object from the queue.
+  Standard_EXPORT void  Detach    ();
+
+  OSD_MPData (const OSD_MPData& theOther);
+  OSD_MPData& operator= (const OSD_MPData& theOther);
+
+ private:
+  // ---------- PRIVATE FIELDS ----------
+  Standard_Size         myID;
+  OSD_MPData            * myPrevious;
+  OSD_MPData            * myNext;
+
+ protected:
+  // ---------- PROTECTED FIELDS ----------
+  const OSD_MProcess&   myProcessor;
+  volatile unsigned int myThreadID;
+  volatile Status       myStatus;
+
+  friend class OSD_MProcess;
+};
+
+#ifdef WNT
+#pragma warning (pop)
+#endif
+
+#endif
diff --git a/src/OSD/OSD_MProcess.cxx b/src/OSD/OSD_MProcess.cxx
new file mode 100644 (file)
index 0000000..ece69a9
--- /dev/null
@@ -0,0 +1,434 @@
+// File:      OSD_MProcess.cxx
+// Created:   29.06.09 09:40
+// Author:    Alexander GRIGORIEV
+// Copyright: Open Cascade 2009
+
+
+#include <OSD_MProcess.hxx>
+
+#ifdef WNT
+// 'this' : used in base member initializer list
+#pragma warning(disable:4355)
+#endif
+
+static Standard_Integer Delay (const unsigned int theValue);
+
+//=======================================================================
+//function : MPThread::MPThread
+//purpose  : Constructor
+//=======================================================================
+
+OSD_MProcess::MPThread::MPThread ()
+  : myProcessor (0L),
+    mypData     (0L),
+    myID        (UINT_MAX),
+    myNProcessed(0u),
+    myAlloc     (new NCollection_IncAllocator),
+    myIsBusy    (Standard_False),
+    myIsActive  (Standard_False),
+    myIsSleeping(Standard_False)
+{
+}
+
+//=======================================================================
+//function : Process
+//purpose  : Thread function
+//=======================================================================
+
+Standard_Address OSD_MProcess::MPThread::Process(Standard_Address pThread)
+{
+  MPThread& aThread = * reinterpret_cast<MPThread *> (pThread);
+  const OSD_MProcess& aMP = * aThread.myProcessor;
+  OSD_MPData * aBaseData = aThread.mypData;
+  OSD_MPData * aData = aBaseData;
+  aThread.myIsActive = Standard_True;
+  Standard_Integer aSleepCounter(0);
+  while (aThread.myIsActive) {
+    // Seek a waiting data block and process it
+    if (processData(aThread, aData, aBaseData, aSleepCounter))
+    {
+      if (aSleepCounter < 100 || aMP.AllowSleep() == Standard_False)
+        Delay(100);
+      else {
+        aThread.myIsBusy = Standard_False;
+        aThread.myIsSleeping = Standard_True;
+        Sleep(1);
+        aThread.myIsSleeping = Standard_False;
+      }
+      if (++aSleepCounter > 100)
+        aThread.myIsBusy = Standard_False;
+    }
+  }
+  return 0L;
+}
+
+//=======================================================================
+//function : processData
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean OSD_MProcess::processData (MPThread&         aThread,
+                                            OSD_MPData*&      theData,
+                                            OSD_MPData*       theBaseData,
+                                            Standard_Integer& aSleepCounter)
+{
+  const Standard_Size aThreadID = aThread.myID;
+  Standard_Boolean isWait(Standard_True);
+  if (theData) {
+    isWait = Standard_False;
+    OSD_MPData * aData = theData->myNext;
+    while (aData != theBaseData)
+    {
+      if (aData->myStatus == OSD_MPData::StatusWait)
+      {
+        InterlockedCompareExchange((volatile LONG *)&aData->myThreadID,
+                                   aThreadID, UINT_MAX);
+        if (aData->myThreadID == aThreadID)
+        {
+          aData->myStatus = OSD_MPData::StatusProcess;
+          aThread.myIsBusy = Standard_True;
+          aSleepCounter = 0;
+          aData->Process();
+          aThread.myNProcessed++;
+          aData->myStatus = OSD_MPData::StatusDone;           
+          aThread.mypData = aData;
+          break;
+        }
+      }
+      aData = aData->myNext;
+    }
+    if (aData == theBaseData) {
+      isWait = Standard_True;
+    }
+    theData = aData;
+  }
+  return isWait;
+}
+
+//=======================================================================
+//function : OSD_MProcess()
+//purpose  : Constructor
+//=======================================================================
+
+OSD_MProcess::OSD_MProcess ()
+  : myNThreads  (0),
+    myArrThread (0L),
+    myNDataAll  (0u),
+    myIsSleepy  (Standard_False)
+{
+  myData.myStatus = OSD_MPData::DummyData;
+}
+
+//=======================================================================
+//function : Init
+//purpose  : 
+//=======================================================================
+
+void OSD_MProcess::Init (const Standard_Size nThreads,
+                         const Standard_Integer thePriority)
+{
+  if (myNThreads)
+    Clear();
+  myAlloc = new NCollection_IncAllocator;
+  myNThreads = nThreads;
+  myIsSleepy = Standard_False;
+  myArrThread = new MPThread[nThreads + 1];
+  for (Standard_Size iThread = 0; iThread <= nThreads; iThread++) {
+    myArrThread[iThread].myProcessor = this;
+    myArrThread[iThread].myID = iThread;
+    myArrThread[iThread].mypData = &myData;
+    if (iThread) {
+      myArrThread[iThread].SetFunction(&MPThread::Process);
+      myArrThread[iThread].SetPriority(thePriority);
+      myArrThread[iThread].Run(&myArrThread[iThread]);
+    }
+  }
+}
+
+//=======================================================================
+//function : OSD_MProcess()
+//purpose  : Constructor
+//=======================================================================
+
+OSD_MProcess::OSD_MProcess (const Standard_Size nThreads,
+                            const Standard_Integer thePriority)
+  : myAlloc        (new NCollection_IncAllocator),
+    myNThreads     (nThreads),
+    myArrThread    (new MPThread[nThreads + 1]),
+    myNDataAll     (0u),
+    myIsSleepy     (Standard_False)
+{
+  myData.myStatus = OSD_MPData::DummyData;
+  for (Standard_Size iThread = 0; iThread <= nThreads; iThread++) {
+    myArrThread[iThread].myProcessor = this;
+    myArrThread[iThread].myID = iThread;
+    myArrThread[iThread].mypData = &myData;
+    if (iThread) {
+      myArrThread[iThread].SetFunction(&MPThread::Process);
+      myArrThread[iThread].SetPriority(thePriority);
+      myArrThread[iThread].Run(&myArrThread[iThread]);
+    }
+  }
+}
+
+//=======================================================================
+//function : ~OSD_MProcess
+//purpose  : Destructor
+//=======================================================================
+
+OSD_MProcess::~OSD_MProcess ()
+{
+  Clear();
+}
+
+//=======================================================================
+//function : NProcessed
+//purpose  : 
+//=======================================================================
+
+Standard_Size OSD_MProcess::NProcessed () const
+{
+  Standard_Size aSum(0u);
+  for (Standard_Size i = 0; i <= myNThreads; i++)
+    aSum += myArrThread[i].myNProcessed;
+  return aSum;
+}
+
+//=======================================================================
+//function : AddData
+//purpose  : Put a data block into the queue.
+//=======================================================================
+
+void OSD_MProcess::AddData (OSD_MPData * theData)
+{
+  theData->myStatus = OSD_MPData::StatusEmpty;
+  theData->myThreadID = UINT_MAX;
+  myData.AddBefore(theData);
+  myNDataAll++;
+
+  theData->myStatus = OSD_MPData::StatusWait;
+}
+
+//=======================================================================
+//function : TakeData
+//purpose  : Extract already processed data block, removing it from the queue.
+//=======================================================================
+
+OSD_MPData * OSD_MProcess::TakeData ()
+{
+  OSD_MPData * aData = 0L;
+  const OSD_MPData * pBaseData = &myData;
+  OSD_MPData * pData = pBaseData->myNext;
+  for (; pData != pBaseData; pData = pData->myNext) {
+    if (pData->myStatus == OSD_MPData::StatusDone) {
+      pData->PostProcess();
+      myNDataAll--;
+      pData->Detach();
+      aData = pData;
+      break;
+    }
+  }
+  return aData;
+}
+
+//=======================================================================
+//function : Wait
+//purpose  : Wait for the time theMillisec
+//=======================================================================
+
+Standard_Boolean OSD_MProcess::Wait (const Standard_Integer theMillisec,
+                                     const Standard_Boolean doTasks)
+{
+  // Wait till all threads conclude
+  Standard_Boolean aResult(Standard_True);
+  Standard_Size i;
+  if (theMillisec > 0)
+    Sleep(theMillisec);
+  else if (doTasks)
+    myArrThread[0].mypData = &myData;
+
+  for (;;)
+  {
+    for (i = 1; i <= myNThreads; i++) {
+      if (myArrThread[i].IsBusy()) {
+        aResult = Standard_False;
+        break;
+      }
+    }
+    if (aResult) {
+      OSD_MPData * pData = myData.myNext;
+      for (; pData != &myData; pData = pData->myNext) {
+        if (pData->myStatus != OSD_MPData::StatusDone) {
+          aResult = Standard_False;
+          break;
+        }
+      }
+      if (aResult)
+        break;
+    }
+    if (theMillisec > 0)
+      break;
+    if (doTasks) {
+      OSD_MPData * aData = myArrThread[0].mypData;
+      Standard_Integer aSleepCounter(0);
+      // Seek a waiting data block and process it
+      processData(myArrThread[0], aData, &myData, aSleepCounter);
+    } else if (myIsSleepy)
+      Sleep(1);
+    aResult = Standard_True;
+  }
+  return aResult;
+}
+
+//=======================================================================
+//function : Open
+//purpose  : 
+//=======================================================================
+
+void OSD_MProcess::Open() const
+{
+  Standard_Integer aCounter(5);
+  while (aCounter) {
+    for (Standard_Size i = 1; i <= myNThreads; i++) {
+      if (myArrThread[i].IsBusy())
+        return;
+    }
+    Standard_Integer aFlag(0);
+    OSD_MPData * pData = myData.myNext;
+    if (pData == &myData)
+      break;    // protect from the case when no Data are loaded
+    for (; pData != &myData; pData = pData->myNext) {
+      if (pData->myStatus == OSD_MPData::StatusDone)
+        aFlag |= 0x1;
+      else
+        aFlag |= 0x2;
+      if (aFlag == 3) {
+        aCounter--;
+        break;
+      }
+    }
+    if (aFlag == 0x1) // all having StatusDone
+      break;
+  }
+}
+
+//=======================================================================
+//function : Close
+//purpose  : 
+//=======================================================================
+
+void OSD_MProcess::Close()
+{
+  Wait(0, Standard_True);
+  OSD_MPData * pData = myData.myNext;
+  for (; pData != &myData; pData = pData->myNext) {
+    if (pData->myStatus == OSD_MPData::StatusDone) {
+      pData->PostProcess();
+      myNDataAll--;
+    }
+  }
+  myData.myPrevious = &myData;
+  myData.myNext = &myData;
+  myNDataAll = 0;
+  for (Standard_Size i = 0; i <= myNThreads; i++) {
+    const Handle(NCollection_IncAllocator)& anAlloc =
+      myArrThread[i].Allocator();
+    anAlloc->Reset(Standard_False);
+  }
+}
+
+//=======================================================================
+//function : Clear
+//purpose  : 
+//=======================================================================
+
+void OSD_MProcess::Clear(const Standard_Boolean isWait)
+{
+  // Stop all threads
+  for (Standard_Size iThread = 1; iThread <= myNThreads; iThread++) {
+    myArrThread[iThread].myIsActive = Standard_False;
+    if (isWait)
+      myArrThread[iThread].Wait();
+  }
+
+  // Collect the data
+  if (isWait) {
+    OSD_MPData * pData = myData.myNext;
+    for (; pData != &myData; pData = pData->myNext) {
+      if (pData->myStatus == OSD_MPData::StatusDone) {
+        pData->PostProcess();
+        myNDataAll--;
+      }
+    }
+  }
+
+  // Free the resources
+  myData.myPrevious = &myData;
+  myData.myNext = &myData;
+  if (myNThreads) {
+    myNThreads = 0;
+    delete [] myArrThread;
+    myAlloc.Nullify();
+    myNDataAll = 0;
+  }
+}
+
+//=======================================================================
+//function : Delay
+//purpose  : local function; delays proportionally to the given value
+//=======================================================================
+
+Standard_Integer Delay (const unsigned int theValue)
+{
+  volatile Standard_Integer aSum = 1; 
+  for (unsigned int i = 0; i < theValue; i++)
+    aSum += aSum / (i+1);
+  return aSum;
+}
+
+//=======================================================================
+//function : AllowSleep
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean OSD_MProcess::AllowSleep () const
+{
+  if (myIsSleepy)
+    return Standard_True;
+  Standard_Integer nAwake(myNThreads);
+  for (Standard_Size i = 1; i <= myNThreads; i++) {
+    if (myArrThread[i].myIsSleeping)
+      nAwake--;
+  }
+  return (nAwake >= GetMaxThreads());
+}
+
+//=======================================================================
+//function : getMaxThreads
+//purpose  : 
+//=======================================================================
+
+Standard_Integer OSD_MProcess::GetMaxThreads()
+{
+#ifdef WNT
+#pragma warning(disable:4996)
+#endif
+  static Standard_Integer nThreads(0);
+  if (nThreads == 0) {
+    char * strVar = getenv("OMP_NUM_THREADS");
+    if (strVar) {
+      nThreads = atoi(strVar);
+      if (nThreads == 0)
+        nThreads = -1;
+    }
+    if (nThreads < 0)
+      nThreads = 0;
+    else if (nThreads == 0) {
+      strVar = getenv("NUMBER_OF_PROCESSORS");
+      if (strVar)
+        nThreads = atoi(strVar);
+    }
+  }
+  return nThreads;
+}
+
diff --git a/src/OSD/OSD_MProcess.hxx b/src/OSD/OSD_MProcess.hxx
new file mode 100644 (file)
index 0000000..dbce223
--- /dev/null
@@ -0,0 +1,181 @@
+// File:      OSD_MProcess.hxx
+// Created:   29.06.09 09:34
+// Author:    Alexander GRIGORIEV
+// Copyright: Open Cascade 2009
+
+
+#ifndef OSD_MProcess_HeaderFile
+#define OSD_MProcess_HeaderFile
+
+#include <OSD_MPData.hxx>
+#include <OSD_Thread.hxx>
+
+/**
+ * Manager of calculations in multiple threads (OSD_MPThread)
+ */
+
+class OSD_MProcess
+{
+ public:
+  class MPThread : public OSD_Thread
+  {
+  public:
+    //! Constructor.
+    Standard_EXPORT MPThread ();
+
+    //! Thread function
+    static Standard_Address Process(Standard_Address);
+
+    //! Query if the thread is busy or idle.
+    inline Standard_Boolean IsBusy () const     { return myIsBusy; }
+
+    //! Get the thread-owned memory Allocator
+    inline const Handle_NCollection_IncAllocator&
+                            Allocator() const   { return myAlloc; }
+
+  private:
+    MPThread (const MPThread& theOther);
+    MPThread& operator= (const MPThread& theOther);
+
+  private:
+    // ---------- PRIVATE FIELDS ----------
+    const OSD_MProcess                  * myProcessor;
+    OSD_MPData                          * mypData;
+    unsigned int                        myID;
+    Standard_Boolean                    myIsBusy;
+    Standard_Size                       myNProcessed;
+    Handle_NCollection_IncAllocator     myAlloc;
+    volatile Standard_Boolean           myIsActive;
+    volatile Standard_Boolean           myIsSleeping;
+    friend class OSD_MProcess;
+  };
+
+  // ---------- PUBLIC METHODS ----------
+
+
+  /**
+   * Default constructor.
+   */
+  Standard_EXPORT OSD_MProcess ();
+
+  /**
+   * Constructor. Starts the threads immediately.
+   */
+  Standard_EXPORT OSD_MProcess    (const Standard_Size nThreads,
+                                   const Standard_Integer thePriority = 0);
+
+  /**
+   * Initialize threads and start them. Used after empty constructor or Close
+   */
+  Standard_EXPORT void Init       (const Standard_Size nThreads,
+                                   const Standard_Integer thePriority = 0);
+
+  /**
+   * Destructor.
+   */
+  Standard_EXPORT ~OSD_MProcess   ();
+
+  //! Query the maximal advisable number of threads for this system.
+  static Standard_EXPORT Standard_Integer
+                       GetMaxThreads ();
+
+  //! Query the number of opened threads
+  inline Standard_Size NThreads   () const      { return myNThreads; }
+
+  //! Query the length of the data queue
+  inline Standard_Size NData      () const      { return myNDataAll; }
+
+  //! Query the number of already processed data blocks
+  Standard_EXPORT Standard_Size
+                       NProcessed () const;
+
+  //! Get the Allocator, to allocate new OSD_MPData instances
+  inline const Handle_NCollection_IncAllocator&
+                       Allocator  () const      { return myAlloc; }
+
+  /**
+   * Put a data block into the queue.
+   */
+  Standard_EXPORT void AddData    (OSD_MPData * theData);
+
+  /**
+   * Extract already processed data block, removing it from the queue.
+   * Returns NULL if not available.
+   */
+  Standard_EXPORT OSD_MPData *
+                       TakeData   ();
+
+  /**
+   * Wait for the time theMsec then return True if the execution is finished
+   * or False if it still continues. If theMillisec <= 0, then the method
+   * waits until all threads are exhausted.
+   */
+  Standard_EXPORT Standard_Boolean
+                       Wait       (const Standard_Integer theMsec = 0,
+                                   const Standard_Boolean doTasks = 0u);
+
+  /**
+   * Avoid future sleeping of the managed threads, this reduces the delays
+   * during Open() and Close() calls. Call this method if it is expected to
+   * call Open/Close repeatedly for untensive processing.
+   */
+  inline void          GoAwake    ()
+  { myIsSleepy = Standard_False; }
+
+  /**
+   * Returns True if a Thread is allowed to sleep. Called from thread functions.
+   */
+  Standard_EXPORT Standard_Boolean
+                       AllowSleep () const;
+
+  /**
+   * Allow future sleeping of managed threads. This method shoul be called if
+   * there is not expected any intensive operation with repeated Open/Close.
+   */
+  inline void          GoSleepy   ()
+  { myIsSleepy = Standard_True; }
+
+  /**
+   * Query the Sleepy state
+   */
+  inline Standard_Boolean IsSleepy () const
+  { return myIsSleepy; }
+
+  /**
+   * Wait till the 1st task is started.
+   */
+  Standard_EXPORT void Open () const;
+
+  /**
+   * Closes the processing without stopping the threads.
+   */
+  Standard_EXPORT void Close ();
+
+  /**
+   * Stops the threads.
+   */
+  Standard_EXPORT void Clear (const Standard_Boolean isWait = Standard_True);
+
+ private:
+  OSD_MProcess (const OSD_MProcess& theOther);
+  OSD_MProcess& operator- (const OSD_MProcess& theOther);
+
+  static Standard_Boolean processData (MPThread&         aThread,
+                                       OSD_MPData*&      theData,
+                                       OSD_MPData*       theBaseData,
+                                       Standard_Integer& aSleepCounter);
+
+ private:
+  // ---------- PRIVATE FIELDS ----------
+  Handle_NCollection_IncAllocator       myAlloc;
+  Standard_Size                         myNThreads;
+  OSD_MPData                            myData;
+  MPThread                              * myArrThread;
+  Standard_Size                         myNDataAll;
+  Standard_Boolean                      myIsSleepy;
+
+  friend class OSD_MPData;
+};
+
+
+#endif
index c73593b99179ca5956ae53722bf9139c3c267217..72c6cf7d50cccccca893bfab31b53b116bc30638 100644 (file)
  commercial license or contractual agreement.
 */ 
 
-/*======================================================================
-*/ 
-/*Purpose :       Set of functions to measure the CPU user time
-*/ 
-/*25/09/2001 : AGV : (const char *) in prototypes;
-*/ 
-/*09/11/2001 : AGV : Add functions perf_*_imeter for performance
-*/ 
-/*Add function perf_tick_meter
-*/ 
-/*14/05/2002 : AGV : Portability UNIX/Windows
-*/ 
+/*======================================================================*/ 
+/*Purpose :       Set of functions to measure the CPU user time         */ 
+/*25/09/2001 : AGV : (const char *) in prototypes;                      */ 
+/*09/11/2001 : AGV : Add functions perf_*_imeter for performance        */ 
+/*                   Add function perf_tick_meter                       */ 
+/*14/05/2002 : AGV : Portability UNIX/Windows                           */
+/*22/09/2014 : AGV : Add function perf_output_all_meters
 /*======================================================================*/ 
 #include <string.h>
 #include <stdio.h>
@@ -223,13 +218,31 @@ Output   :      none
 Returns  :      none
 ======================================================================*/
 void perf_print_all_meters (void)
+{
+  perf_output_all_meters(NULL);
+}
+
+/*======================================================================
+Function :      perf_output_all_meters
+Purpose  :      Prints to open file stream the cumulated time and the number
+                of enters for each meter in MeterTable;
+                resets all meters
+                Useful in applications that have no stdout
+Output   :      none
+Returns  :      none
+======================================================================*/
+void perf_output_all_meters (void* theFile)
 {
   int i;
-  for (i=0; i<nb_meters; i++) {
+  for (i = 0; i < nb_meters; i++) {
     const t_TimeCounter * const ptc = &MeterTable[i];
     if (ptc && ptc->nb_enter) {
-      printf ("          Perf meter results               :"
-              "   enters  seconds  \xe6sec/enter\n");
+      const char* str = "          Perf meter results               :"
+        "   enters  seconds  \xe6sec/enter\n";
+      if (theFile)
+        fprintf((FILE *)theFile, str);
+      else
+        printf(str);
       break;
     }
   }
@@ -240,13 +253,20 @@ void perf_print_all_meters (void)
     if (ptc && ptc->nb_enter) {
       const double secs = ptc->cumul_time;
 
-      if (ptc->start_time)
-        printf ("Warning : meter %s has not been stopped\n", ptc->name);
-
-      printf ("%-42s : %7d %8.2f %10.2f\n",
-              ptc->name, ptc->nb_enter, secs,
-              (secs>0. ? 1000000 * secs/ptc->nb_enter : 0.));
-
+      if (theFile) {
+        if (ptc->start_time)
+          fprintf ((FILE *)theFile,
+                   "Warning : meter %s has not been stopped\n", ptc->name);
+        fprintf ((FILE *)theFile, "%-42s : %7d %8.2f %10.2f\n",
+                 ptc->name, ptc->nb_enter, secs,
+                 (secs>0. ? 1000000 * secs/ptc->nb_enter : 0.));
+      } else {
+        if (ptc->start_time)
+          printf ("Warning : meter %s has not been stopped\n", ptc->name);
+        printf ("%-42s : %7d %8.2f %10.2f\n",
+                ptc->name, ptc->nb_enter, secs,
+                (secs>0. ? 1000000 * secs/ptc->nb_enter : 0.));
+      }
       ptc->cumul_time = 0;
       ptc->start_time = 0;
       ptc->nb_enter   = 0;
index cc17650de8012a8678d403ad9059a29df4c7456b..b5df04508afbe696817b1d1b887a6d139e505f37 100644 (file)
@@ -147,6 +147,12 @@ Standard_EXPORTEXTERNC void    perf_print_all_meters   (void);
    Resets all meters
 */
 
+Standard_EXPORTEXTERNC void    perf_output_all_meters  (void* theFile);
+/* Prints to file the same output as perf_print_all_meters().
+   Parameter theFile is a file stream (FILE*) that should be opened and
+   closed in the caller.
+*/
+
 Standard_EXPORTEXTERNC void    perf_destroy_all_meters (void);
 /* Deletes all meters and frees memory
 */
index b37ec8e5fe644e9ce415743981abf1e5044c6b54..6602ad4af51bb9454f555201a2547c48ddbc58bd 100644 (file)
@@ -253,6 +253,14 @@ public:
   //! @return tool for management of shader programs within this context.
   inline const Handle(OpenGl_ShaderManager)& ShaderManager() const { return myShaderManager; }
 
+  //! @return a window - owner of GL context.
+#if defined(_WIN32) || !defined(__APPLE__) || defined(MACOSX_USE_GLX)
+  inline void* GetWindow()
+  {
+    return myWindow;
+  }
+#endif
+
 public:
 
   //! @return maximum degree of anisotropy texture filter
index 4678ed1210988f36313ebf0b6b8b18096418b475..6ec783eb6f24863506e6fc2e0f05a2c53621738e 100644 (file)
@@ -128,12 +128,25 @@ void OpenGl_Workspace::RedrawImmediatMode()
   }
   glDisable (GL_LIGHTING);
 
+  const GLboolean wasDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST);
+  if (wasDepthTestEnabled)
+  {
+    glDisable (GL_DEPTH_TEST);
+  }
+
   Handle(OpenGl_Workspace) aWS (this);
+  NamedStatus |= OPENGL_NS_IMMEDIATE;
   for (Standard_Integer anIter = 1; anIter <= myTransientList.Size(); ++anIter)
   {
     const OpenGl_Structure* aStructure = myTransientList.Value (anIter);
     aStructure->Render (aWS);
   }
+  NamedStatus &= ~OPENGL_NS_IMMEDIATE;
+
+  if (wasDepthTestEnabled)
+  {
+    glEnable (GL_DEPTH_TEST);
+  }
 
   if (isDoubleBuffer && myTransientDrawToFront)
   {
diff --git a/src/Poly/Poly_IBuffer.cxx b/src/Poly/Poly_IBuffer.cxx
new file mode 100644 (file)
index 0000000..d6b8821
--- /dev/null
@@ -0,0 +1,547 @@
+// File:      Poly_IBuffer.cxx
+// Created:   15.06.07 08:32
+// Author:    Alexander GRIGORIEV
+// Copyright: Open CASCADE 2007
+
+#include <Poly_IBuffer.hxx>
+#include <Precision.hxx>
+#include <NCollection_IncAllocator.hxx>
+#include <Standard_ProgramError.hxx>
+
+#pragma warning(disable:4291)
+
+IMPLEMENT_STANDARD_HANDLE (Poly_IBuffer, Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT(Poly_IBuffer, Standard_Transient)
+
+static const Standard_Size INDEXLEN = 10;
+#ifdef _DEBUG
+int Poly_IBuffer::GlobalCount = 0;
+#endif
+
+//=======================================================================
+//function : GetZ
+//purpose  : local function
+//=======================================================================
+
+inline Standard_Real GetZ (const Poly_IBuffer::Interval& theInt,
+                           const Standard_Real           theX)
+{
+  return (theInt.XZ(0).Y() + (theInt.XZ(1).Y() - theInt.XZ(0).Y()) *
+          (theX - theInt.XZ(0).X()) / (theInt.XZ(1).X() - theInt.XZ(0).X()));
+}
+
+//=======================================================================
+//function : Poly_IBuffer
+//purpose  : Constructor
+//=======================================================================
+
+Poly_IBuffer::Poly_IBuffer (const Poly_IBuffer::Interval&           theInterval,
+                            const Standard_Real                     theTol,
+                            const Handle_NCollection_BaseAllocator& theAlloc)
+{
+  Init (theInterval, theTol, theAlloc);
+#ifdef _DEBUG
+  myCount = GlobalCount++;
+#endif
+}
+
+//=======================================================================
+//function : Init
+//purpose  : Initialization, to be used after the default constructor.
+//=======================================================================
+
+void Poly_IBuffer::Init (const Interval&                         theInterval,
+                         const Standard_Real                     theTol,
+                         const Handle_NCollection_BaseAllocator& theAlloc)
+{
+  clearIntervals();
+  myTol = theTol;
+  if (theAlloc.IsNull())
+    myAllocator = new NCollection_IncAllocator(1000);
+  else
+    myAllocator = theAlloc;
+
+  myMinOrd = Precision::Infinite();
+  myMaxOrd = -Precision::Infinite();
+  myNIntervals = 1;
+
+  // Create the first interval covering all possible X coordinates 
+  Interval * pInt = &theInterval.Clone(myAllocator);
+  // Create the index array
+  myIndex = static_cast <PInterval *>
+    (myAllocator->Allocate((INDEXLEN+1) * sizeof(PInterval)));
+  const Standard_Real anXmin = theInterval.XZ(0).X();
+  const Standard_Real aXstep = (theInterval.XZ(1).X() - anXmin) / INDEXLEN;
+  for (Standard_Size i = 0; i <= INDEXLEN; i++) {
+    myIndex[i].X   = Standard_Real (anXmin + i*aXstep);
+    myIndex[i].Int = pInt;
+  }
+}
+
+//=======================================================================
+//function : ~Poly_IBuffer
+//purpose  : Destructor
+//=======================================================================
+
+Poly_IBuffer::~Poly_IBuffer ()
+{
+  clearIntervals();
+}
+
+//=======================================================================
+//function : Clone
+//purpose  : Create a copy of the given Interval in the given allocator.
+//=======================================================================
+
+Poly_IBuffer::Interval& Poly_IBuffer::Interval::Clone
+                        (const Handle_NCollection_BaseAllocator& theAlloc,
+                         Poly_IBuffer::Interval *                theDest) const
+{
+  if (theDest == 0L)
+    theDest = new (theAlloc) Interval(myXZ[0], myXZ[1], 0UL);
+  else {
+    theDest->myXZ[0] = myXZ[0];
+    theDest->myXZ[1] = myXZ[1];
+    theDest->myNext  = 0L;
+    theDest->myModID = 0UL;
+    theDest->U.myModX  = RealLast();
+  }
+  return * theDest;
+}
+
+//=======================================================================
+//function : NewRejectID
+//purpose  : Generator of unique Reject ID values.
+//=======================================================================
+
+unsigned long Poly_IBuffer::Interval::NewRejectID ()
+{
+  static unsigned long aValue(0UL);
+  aValue += 4;
+  return aValue;
+}
+
+//=======================================================================
+//function : IsIntersect
+//purpose  : Check for intersection, returns the intersection point abscissa.
+//   @return
+//   True if a modification or removal is required. The decision is based
+//   on 2 lower bits of myRejectID value:
+//    - 0 : remove this interval;
+//    - 1 : keep the lower abscisse part, remove the upper part;
+//    - 2 : keep the upper abscisse part, remove the lower part;
+//    - 3 : remove the middle.
+//=======================================================================
+
+Standard_Boolean Poly_IBuffer::Interval::IsIntersect
+                                     (const Poly_IBuffer::Interval& theInt,
+                                      const Standard_Real           theTol,
+                                      const unsigned long           theRejectID)
+{
+  Standard_Boolean aRes(Standard_False);
+  Standard_Integer aResult (-1);
+  Standard_Real anAbscisse (Precision::Infinite());
+  const Standard_Real anXtol[2] = {
+    myXZ[0].X() + theTol,
+    myXZ[1].X() - theTol
+  };
+  if (theInt.myXZ[0].X() < anXtol[1] && theInt.myXZ[1].X() > anXtol[0]) {
+    const gp_XY aVec[3] = {
+      gp_XY(theInt.myXZ[0] - myXZ[0]),
+      gp_XY(myXZ[1] - myXZ[0]),
+      gp_XY(theInt.myXZ[1] - theInt.myXZ[0])
+    };
+    const Standard_Real aDirProd = aVec[1] ^ aVec[2];
+    if (aDirProd  > Precision::Intersection()) {
+      // Intersection coefficients
+      const Standard_Real fInter[2] = {
+        (aVec[0] ^ aVec[2]) / aDirProd,
+        (aVec[0] ^ aVec[1]) / aDirProd
+      };
+      anAbscisse = (myXZ[1].X() * fInter[0] + myXZ[0].X() * (1.-fInter[0]));
+      if (anAbscisse > anXtol[0] && fInter[1] > 0.)
+        if (anAbscisse < anXtol[1] && fInter[1] < 1.) {
+          if (theInt.myXZ[0].X() < anXtol[0])
+            aResult = 2;  // keep upper abscissa
+          else {
+            anAbscisse = theInt.myXZ[0].X();
+            aResult = 3;
+          }
+        } else {
+          if (theInt.myXZ[0].X() > anXtol[0]) {
+            anAbscisse = theInt.myXZ[0].X();
+            if (theInt.myXZ[1].X() > anXtol[1])
+              aResult = 1; // keep lower abscissa
+            else
+              aResult = 3;
+          } else
+            if (theInt.myXZ[1].X() > anXtol[1])
+              aResult = 0; // remove
+            else {
+              anAbscisse = theInt.myXZ[1].X();
+              aResult = 2; // keep upper abscissa
+            }
+        }
+    } else {
+      Standard_Real fInter[2] = { 2., -1. };
+      if (aDirProd  < -Precision::Intersection()) {
+        // Intersection coefficients
+        fInter[0] = (aVec[0] ^ aVec[2]) / aDirProd;
+        fInter[1] = (aVec[0] ^ aVec[1]) / aDirProd;
+        anAbscisse = (myXZ[1].X() * fInter[0] + myXZ[0].X() * (1.-fInter[0]));
+      } else if (GetZ (theInt, myXZ[0].X()) < myXZ[0].Y())
+        anAbscisse = theInt.myXZ[0].X();
+
+      if (anAbscisse < anXtol[1] &&
+          fInter[1] < 1.-Precision::Intersection())
+        if (anAbscisse > anXtol[0] &&
+            fInter[1] > Precision::Intersection())
+        {
+          if (theInt.myXZ[1].X() > anXtol[1])
+            aResult = 1;  // keep lower abscissa
+          else
+            aResult = 3;
+        } else {
+          if (theInt.myXZ[0].X() > anXtol[0]) {
+            anAbscisse = theInt.myXZ[0].X();
+            if (theInt.myXZ[1].X() > anXtol[1])
+              aResult = 1; // keep lower abscissa
+            else
+              aResult = 3;
+          } else
+            if (theInt.myXZ[1].X() > anXtol[1]) {
+              aResult = 0; // remove
+              aRes = Standard_True;
+            } else {
+              anAbscisse = theInt.myXZ[1].X();
+              aResult = 2; //keep upper abscissa
+            }
+        }
+    }
+  }
+  if (aResult >= 0) {
+    myModID = theRejectID + aResult;
+    U.myModX = anAbscisse;
+    aRes = Standard_True;
+  }
+  return aRes;
+}
+
+//=======================================================================
+//function : Trim
+//purpose  : Shorten the interval to the new value of Xmax.
+//=======================================================================
+
+void Poly_IBuffer::Interval::Trim (const Standard_Real    theX,
+                                   const Standard_Integer theMode)
+{
+  const Standard_Real aZ = GetZ(* this, theX);
+  switch (theMode) {
+  case 3:
+    myModID = 0UL;
+  case 1:
+    Standard_ProgramError_Raise_if
+        (theX - myXZ[0].X() < Precision::Confusion() || theX > myXZ[1].X(),
+         "Trim error");
+    myXZ[1].SetCoord(theX, aZ);
+    break;
+  case 2:
+    Standard_ProgramError_Raise_if
+        (theX < myXZ[0].X() || myXZ[1].X() - theX < Precision::Confusion(),
+         "Trim error");
+    myXZ[0].SetCoord(theX, aZ);
+    break;
+  }
+}
+
+//=======================================================================
+//function : AddInterval
+//purpose  : Add one interval to buffer.
+//=======================================================================
+
+Poly_IBuffer::Interval * Poly_IBuffer::AddInterval
+                             (const Poly_IBuffer::Interval& theInterval,
+                              Poly_IBuffer::Interval *      theStart)
+{
+//  Variables:
+// aLastModified: Newly created interval in the buffer. It is returned by
+//                this method so that it can be passed as theStart
+//                for the next call (next interval).
+// aInt:          Currently checked/processed interval
+// aBracket[0,1]: The first and the last in the chain of intervals where
+//                the modification can be done, used for local optimisation.
+// pLastInt:      The last non-modified interval. This pointer is used to set
+//                pLastInt->Next() to the newly created interval.
+// isWaiting:     True if there have been removed intervals, to be replaced by
+//                a new interval.
+// aFirst.Int:    Same as pLastInt. probably we can get rid of pLastInt
+// aFirst.X:      Beginning of the new interval
+
+  Interval * aLastModified = 0L, * aStart;
+  if (theStart == 0L)
+    aStart = const_cast <Interval *>(myIndex[0].Int);
+  else
+    aStart = theStart;
+  Interval * anInt = aStart;
+  Interval * aBracket[2] = { 0L, 0L };
+  unsigned long aRejectID = Interval::NewRejectID();
+  Interval * pLastInt = theStart;
+
+  // Identify the intervals that should be modified
+  for (; anInt; anInt = anInt->Next()) {
+    if (anInt->XZ(0).X() > theInterval.XZ(1).X() - myTol)
+      break;
+    if (anInt->IsIntersect (theInterval, myTol, aRejectID)) {
+      if (aBracket[0] == 0L)
+        aBracket[0] = anInt;
+      aBracket[1] = anInt->Next();
+      const long aModMode = anInt->GetModificationID() - aRejectID;
+      if (aModMode == 3L) {
+        Interval& aNewInt = anInt->Clone(myAllocator);
+        anInt->Trim (anInt->GetModificationAbscisse(), aModMode);
+        aNewInt.myXZ[0] = anInt->XZ(1);
+        aNewInt.myNext = anInt->Next();
+        anInt->myNext = &aNewInt;
+        myNIntervals++;
+      }
+    } else if (aBracket[0] == 0L)
+      pLastInt = anInt;
+  }
+
+  // Modify the intervals
+  Standard_Boolean isWaiting (Standard_False);
+  PInterval aFirst;
+  aFirst.Int = theStart;
+  aFirst.X = aStart->XZ(0).X();
+  for (anInt = aBracket[0]; anInt; anInt = anInt->Next()) {
+    const unsigned long aCurrentID = anInt->GetModificationID();
+    if ((aCurrentID & ~0x3) != aRejectID) {
+      if (isWaiting) {
+        const Standard_Real anX[2] = {
+          aFirst.X,
+          anInt->XZ(0).X()
+        };
+        aLastModified = addInt (theInterval, anX, aFirst.Int);
+        if (aStart == 0L)
+          aStart = aLastModified;
+        aLastModified->myNext = anInt;
+        aFirst.Int = anInt;
+        isWaiting = Standard_False;
+      }
+      if (anInt == aBracket[1])
+        break;
+      pLastInt = anInt;
+    } else {
+      const long aModMode = aCurrentID - aRejectID;
+      switch (aModMode) {
+      case 0:
+        if (aStart == anInt)
+          aStart = 0L;
+        if (isWaiting == Standard_False) {
+          aFirst.Int = pLastInt;
+          aFirst.X = anInt->XZ(0).X();
+          isWaiting = Standard_True;
+        }
+        myNHoles++;
+        break;
+      case 1:
+        aFirst.X = anInt->GetModificationAbscisse();
+        aFirst.Int = anInt;
+        anInt->Trim (aFirst.X, 1);
+        pLastInt = anInt;
+        isWaiting = Standard_True;
+        break;
+      case 2:
+        {
+          if (isWaiting)
+            isWaiting = Standard_False;
+          else {
+            aFirst.Int = pLastInt;
+            aFirst.X = anInt->XZ(0).X();
+          }
+          anInt->Trim (anInt->GetModificationAbscisse(), 2);
+          const Standard_Real anX[2] = {
+            aFirst.X,
+            anInt->GetModificationAbscisse()
+          };
+          aLastModified = addInt (theInterval, anX, aFirst.Int);
+          if (aStart == 0L)
+            aStart = aLastModified;
+          aLastModified->myNext = anInt;
+          aFirst.Int = anInt;
+          pLastInt = anInt;
+        }
+        break;
+      default:
+        Standard_ProgramError::Raise ("Poly_IBuffer::AddInterval");
+      }
+    }
+  }
+  if (isWaiting) {
+    const Standard_Real anX[2] = {
+      aFirst.X,
+      myIndex[INDEXLEN].X
+    };
+    aLastModified = addInt (theInterval, anX, aFirst.Int);
+  }
+  return aLastModified;
+}
+
+//=======================================================================
+//function : CloseBuffer
+//purpose  : Called after all additions of intervals
+//=======================================================================
+
+void Poly_IBuffer::CloseBuffer (const Standard_Boolean isFiltering)
+{
+  const Standard_Real aConf2 =
+    0.01 * Precision::Confusion() * Precision::Confusion();
+  const Standard_Real aTol2 = myTol * myTol;
+  Interval * pPrev = 0L, * pInt = const_cast<Interval *>(myIndex[0].Int);
+  if (pInt) {
+    pInt->U.myPrev = 0L;
+    pInt->myModID = 0UL;
+    pPrev = pInt;
+    pInt = pInt->Next();
+  }
+  while (pInt) {
+    if (isFiltering &&
+        (pPrev->myXZ[1] - pInt->myXZ[0]).SquareModulus() < aConf2)
+    {
+      const gp_XY aV0 = pInt->myXZ[1] - pPrev->myXZ[0];
+      const Standard_Real aL0 = aV0.SquareModulus();
+      if (aL0 > aConf2) {
+        const Standard_Real aVProd = aV0 ^ (pPrev->myXZ[1] - pPrev->myXZ[0]);
+        if (aVProd * aVProd / aL0 < aTol2) {
+          // extend pPrev to take place of pInt
+          pPrev->myXZ[1] = pInt->myXZ[1];
+          pPrev->myNext = pInt->Next();
+          pInt = pInt->Next();
+          continue;
+        }
+      }
+    }
+    pInt->U.myPrev = pPrev;
+    pInt->myModID = 0UL;
+    pPrev = pInt;
+    pInt = pInt->Next();
+  }
+}
+
+//=======================================================================
+//function : addInt
+//purpose  : Internal method, called from AddInterval()
+//=======================================================================
+
+Poly_IBuffer::Interval * Poly_IBuffer::addInt
+                        (const Poly_IBuffer::Interval&  theInterval,
+                         const Standard_Real            theX[2],
+                         const Poly_IBuffer::Interval * thePrevious)
+{
+  const gp_XY aXZ[2] = {
+    gp_XY(theX[0], GetZ (theInterval, theX[0])),
+    gp_XY(theX[1], GetZ (theInterval, theX[1]))
+  };
+  Interval& aNewInt = theInterval.Clone(myAllocator);
+  aNewInt.myXZ[0] = aXZ[0];
+  aNewInt.myXZ[1] = aXZ[1];
+  myNIntervals++;
+  if (thePrevious)
+    const_cast<Interval *>(thePrevious)->myNext = &aNewInt;
+  else {
+    myIndex[0].Int = &aNewInt;
+    if (myMinOrd > aXZ[0].Y())
+      myMinOrd = aXZ[0].Y();
+    if (myMaxOrd < aXZ[0].Y())
+      myMaxOrd = aXZ[0].Y();
+  }
+  if (myMinOrd > aXZ[1].Y())
+    myMinOrd = aXZ[1].Y();
+  if (myMaxOrd < aXZ[1].Y())
+    myMaxOrd = aXZ[1].Y();
+  return &aNewInt;
+}
+
+//=======================================================================
+//function : clearIntervals
+//purpose  : 
+//=======================================================================
+
+void Poly_IBuffer::clearIntervals ()
+{
+  if (myAllocator.IsNull() == Standard_False)
+  {
+    Interval * anInt = const_cast <Interval *>(myIndex[0].Int);
+    while (anInt) {
+      Interval * anInt0 = anInt;
+      anInt = anInt->Next();
+      anInt0->Interval::~Interval();
+      myAllocator->Free(anInt0);
+    }
+    myAllocator->Free (myIndex);
+  }
+  myIndex = 0L;
+  myNIntervals = 0;
+  myNHoles = 0;
+}
+
+//=======================================================================
+//function : Dump
+//purpose  : Debug facility.
+//=======================================================================
+
+void Poly_IBuffer::Dump (Standard_OStream& theStream)
+{
+  const Interval * anInt = First();
+  int aCount(0);
+  for (; anInt; anInt = anInt->Next()) {
+    char buf[256];
+    // if (anInt->XZ(0).Y() > Precision::Infinite() * 0.1 &&
+    //     anInt->XZ(1).Y() > Precision::Infinite() * 0.1)
+    //   continue;
+    sprintf (buf, "%03d (%9.5f %9.5f) - (%9.5f %9.5f)", ++aCount,
+             anInt->XZ(0).X(), anInt->XZ(0).Y(),
+             anInt->XZ(1).X(), anInt->XZ(1).Y());
+    theStream << buf << endl;
+  }
+}
+
+//=======================================================================
+//function : DebugPolyline
+//purpose  : Debug facility.
+//=======================================================================
+
+void Poly_IBuffer::DebugPolyline (Standard_OStream&   theStream,
+                                  const Standard_Real theY)
+{
+  static int aTestCount (0);
+  const Interval * anInt = First();
+  Standard_Real aLastVal[2] = { Precision::Infinite(), Precision::Infinite() };
+  Standard_Boolean isStarted (Standard_True);
+  std::streamsize oldPrec = theStream.precision(8);
+  for (; anInt; anInt = anInt->Next()) {
+    if (anInt->XZ(0).Y() > Precision::Infinite() * 0.1 &&
+        anInt->XZ(1).Y() > Precision::Infinite() * 0.1)
+    {
+      if (isStarted == Standard_False) {
+        theStream << endl;
+        isStarted = Standard_True;
+      }
+      continue;
+    }
+    if (isStarted) {
+      theStream << "polyline ibuf" << aTestCount++;
+      isStarted = Standard_False;
+    }
+    if (fabs(anInt->XZ(0).X() - aLastVal[0]) > Precision::Confusion() ||
+        fabs(anInt->XZ(0).Y() - aLastVal[1]) > Precision::Confusion())
+      theStream << "  " << anInt->XZ(0).X() << ' '
+                << theY << ' ' << anInt->XZ(0).Y() << ' ';
+    theStream << "  " << anInt->XZ(1).X() << ' '
+              << theY << ' ' << anInt->XZ(1).Y() << ' ';
+    aLastVal[0] = anInt->XZ(1).X();
+    aLastVal[1] = anInt->XZ(1).Y();
+  }
+  theStream.precision(oldPrec);
+  theStream << endl;
+}
diff --git a/src/Poly/Poly_IBuffer.hxx b/src/Poly/Poly_IBuffer.hxx
new file mode 100644 (file)
index 0000000..fb65da7
--- /dev/null
@@ -0,0 +1,254 @@
+// File:      Poly_IBuffer.hxx
+// Created:   15.06.07 08:08
+// Author:    Alexander GRIGORIEV
+// Copyright: Open CASCADE 2007
+
+
+#ifndef Poly_IBuffer_HeaderFile
+#define Poly_IBuffer_HeaderFile
+
+#include <NCollection_BaseCollection.hxx>
+#include <NCollection_List.hxx>
+#include <gp_XY.hxx>
+#include <Standard_DefineHandle.hxx>
+
+DEFINE_STANDARD_HANDLE (Poly_IBuffer, Standard_Transient)
+
+typedef NCollection_List<Handle_Poly_IBuffer> Poly_ListOfIBuffer;
+
+//! Interval buffer to build outline curve on a set of polygons.
+class Poly_IBuffer: public Standard_Transient
+{
+ public:
+  class Interval
+  {
+  public:
+    // ---------- PUBLIC METHODS ----------
+    Interval (const gp_XY&              theXZfirst,
+              const gp_XY&              theXZlast,
+              const unsigned long       theModID = 0UL);
+
+    /**
+     * Allocator-based operator new for dynamic allocations
+     */
+    DEFINE_NCOLLECTION_ALLOC
+
+    /**
+     * Create a copy of the given Interval in the given allocator.
+     * If theDest==NULL then a new instance is created.
+     */
+    Standard_EXPORT virtual Interval&
+                         Clone        (const Handle_NCollection_BaseAllocator&,
+                                       Interval * theDest = NULL) const;
+
+    /**
+     * Query the abscisse of the interval.
+     */
+    const gp_XY&         XZ           (const Standard_Integer ind) const;
+
+    /**
+     * Query the interval for modification.
+     */ 
+    gp_XY&               XZ           (const Standard_Integer ind);
+
+    /**
+     * Shorten the interval to the new value of Xmax.
+     */
+    Standard_EXPORT void Trim         (const Standard_Real theX,
+                                       const Standard_Integer   theMode);
+    /**
+     * Query the previous interval in the buffer.
+     */
+    Interval *           Previous     () const;
+
+    /**
+     * Query the next interval in the buffer.
+     */
+    Interval *           Next         () const;
+
+    /**
+     * Query the RejectID indicating the modification status of the interval
+     */
+    unsigned long        GetModificationID   () const;
+
+    /**
+     * Query the abscisse value required for modification.
+     */
+    Standard_Real        GetModificationAbscisse() const;
+
+    /**
+     * Set the modification ID.
+     */
+    void                 SetModificationID   (const unsigned long theValue);
+
+    /**
+     * Check for intersection, returns the intersection point abscissa.
+     * @return
+     *   True if a modification or removal is required. The decision is based
+     *   on 2 lower bits of myRejectID value:
+     *    - 0 : remove this interval;
+     *    - 1 : keep the lower abscisse part, remove the upper part;
+     *    - 2 : keep the upper abscisse part, remove the lower part;
+     *    - 3 : remove the middle.
+     * @param theInt
+     *   The other interval that may intersect this one.
+     * @param theTol
+     *   Tolerance of intersection: smaller intersections are neglected.
+     * @param theRejectID
+     *   Base ID that is stored in the interval with the corresponding
+     *   modification status.
+     */
+    Standard_EXPORT Standard_Boolean
+                         IsIntersect  (const Interval&     theInt,
+                                       const Standard_Real theTol,
+                                       const unsigned long theRejectID);
+    /**
+     * Generator of unique Reject ID values.
+     */
+    static Standard_EXPORT unsigned long
+                         NewRejectID  ();
+
+  private:
+    // ---------- PRIVATE FIELDS ----------
+    Interval            * myNext;
+    gp_XY               myXZ[2];
+    union {
+      Standard_Real     myModX;
+      Interval          * myPrev;
+    }                   U;
+    unsigned long       myModID;
+    friend class Poly_IBuffer;
+  };
+  
+ public:
+  // ---------- PUBLIC METHODS ----------
+
+  /**
+   * Default constructor.
+   */
+  Poly_IBuffer ();
+
+  /**
+   * Constructor.
+   */
+  Standard_EXPORT Poly_IBuffer
+                        (const Interval&                         theInterval,
+                         const Standard_Real                     theTol,
+                         const Handle_NCollection_BaseAllocator& theAlloc = 0L);
+
+  /**
+   * Get the next IBuffer in the list.
+   */
+  //inline const Poly_IBuffer& YNext() const
+  //{ return * myNext; }
+  inline const Poly_IBuffer *& YNext() 
+  { return  myNext; }
+
+  /**
+   * Get the previous IBuffer in the list.
+   */
+  //inline const Poly_IBuffer& YPrevious() const
+  //{ return * myPrevious; }
+  inline const Poly_IBuffer *& YPrevious() 
+  { return  myPrevious; }
+
+  inline const Standard_Real MyY() const
+  { return myY; }
+
+  /**
+   * Set myY value.
+   */
+  inline void SetY (const Standard_Real theY)
+  { myY = theY; }
+
+#ifdef _DEBUG
+  inline int MyCount()
+  { return myCount; }
+#endif
+
+  /**
+   * Initialization, to be used after the default constructor.
+   */
+  Standard_EXPORT void Init
+                        (const Interval&                         theInterval,
+                         const Standard_Real                     theTol,
+                         const Handle_NCollection_BaseAllocator& theAlloc = 0L);
+
+  Standard_EXPORT ~Poly_IBuffer ();
+
+  Standard_EXPORT Interval *
+                       AddInterval        (const Interval&      theInterval,
+                                           Interval *           theStart = 0L);
+
+  /**
+   * Called when all intervals are added, just before extraction of data.
+   * This method sets the values 'myPrev' in all Intervals. Can be omittred
+   * if the method Previous() is not to be called afterwards.
+   * @param isFiltering
+   *   If True then the method would merge the intervals that form a straight
+   *   line. It can lead to loss of data attached to intervals, use this only
+   *   when you are only interested in geometry of intervals.
+   */
+  Standard_EXPORT void CloseBuffer        (const Standard_Boolean isFiltering
+                                           = Standard_False);
+
+  const Interval *     First              () const;
+
+  void                 GetOrdinateExtents (Standard_Real& theMin,
+                                           Standard_Real& theMax) const;
+  /**
+   * Debug facility.
+   */
+  Standard_EXPORT void Dump          (Standard_OStream& theStream);
+
+  /**
+   * Debug facility.
+   */
+  Standard_EXPORT void DebugPolyline (Standard_OStream&   theStream,
+                                      const Standard_Real theY = 1.);
+
+ protected:
+  // ---------- PROTECTED METHODS ----------
+
+  typedef struct {
+    Standard_Real  X;
+    const Interval * Int;
+  } PInterval;
+
+  Interval *      addInt        (const Interval&          theInterval,
+                                 const Standard_Real      theX[2],
+                                 const Interval         * thePrevious);
+  void            clearIntervals();
+
+ private:
+  Poly_IBuffer                (const Poly_IBuffer& theOther);
+  Poly_IBuffer& operator =    (const Poly_IBuffer& theOther);
+
+ private:
+  // ---------- PRIVATE FIELDS ----------
+
+  Handle_NCollection_BaseAllocator  myAllocator;
+  Standard_Real                     myTol;
+  Standard_Real                     myMinOrd;
+  Standard_Real                     myMaxOrd;
+  Standard_Size                     myNIntervals;
+  Standard_Size                     myNHoles;
+  PInterval                         * myIndex;
+  //Next IBuffer in the list
+  const Poly_IBuffer*               myNext;
+  //Previous IBuffer in the list
+  const Poly_IBuffer*               myPrevious;
+  Standard_Real                     myY;
+#ifdef _DEBUG
+  int                               myCount;
+  static int                        GlobalCount;
+#endif
+
+public:
+  // Declaration of CASCADE RTTI
+  DEFINE_STANDARD_RTTI (Poly_IBuffer)
+};
+
+#include <Poly_IBuffer.lxx>
+
+#endif
diff --git a/src/Poly/Poly_IBuffer.lxx b/src/Poly/Poly_IBuffer.lxx
new file mode 100644 (file)
index 0000000..adf9c99
--- /dev/null
@@ -0,0 +1,87 @@
+// File:      Poly_IBuffer.lxx
+// Created:   15.06.07 07:56
+// Author:    Alexander GRIGORIEV
+// Copyright: Open CASCADE 2007
+
+//! Constructor.
+inline Poly_IBuffer::Interval::Interval (const gp_XY&        theXZfirst,
+                                         const gp_XY&        theXZlast,
+                                         const unsigned long theModID)
+  : myNext      (0L),
+    myModID     (theModID)
+{
+  U.myModX = RealLast();
+  myXZ[0] = theXZfirst;
+  myXZ[1] = theXZlast;
+}
+
+//! Query the beginning (ind==0) or end (ind == 1) of the interval.
+inline const gp_XY& Poly_IBuffer::Interval::XZ (const Standard_Integer i) const
+{
+  return myXZ[i&0x1];
+}
+
+//! Query the beginning (ind==0) or end (ind == 1) of the interval for modif
+inline gp_XY& Poly_IBuffer::Interval::XZ (const Standard_Integer i)
+{
+  return myXZ[i&0x1];
+}
+
+//! Query the next interval in the buffer.
+inline Poly_IBuffer::Interval *  Poly_IBuffer::Interval::Next () const
+{
+  return myNext;
+}
+
+//! Query the previous interval in the buffer.
+inline Poly_IBuffer::Interval *  Poly_IBuffer::Interval::Previous () const
+{
+  return U.myPrev;
+}
+
+//! Set the modification ID.
+inline void Poly_IBuffer::Interval::SetModificationID
+                                        (const unsigned long theValue)
+{
+  myModID = theValue;
+}
+
+//! Query the RejectID field indicating the modification status of the interval
+inline unsigned long Poly_IBuffer::Interval::GetModificationID () const
+{
+  return myModID;
+}
+
+//! Query the abscisse value required for modification.
+inline Standard_Real Poly_IBuffer::Interval::GetModificationAbscisse() const
+{
+  return U.myModX;
+}
+
+//! Returns the head of the list of intervals.
+/** Other intervals can be obtained by iterative calling Next() of each
+ *  returned interval.
+ */
+inline const Poly_IBuffer::Interval * Poly_IBuffer::First () const
+{
+  return myIndex ? myIndex[0].Int : 0L;
+}
+
+//! Default constructor
+inline Poly_IBuffer::Poly_IBuffer()
+  : myTol       (0.),
+    myMinOrd    (0.),
+    myMaxOrd    (0.),
+    myNIntervals(0),
+    myNHoles    (0),
+    myIndex     (0L)
+{}
+
+//! Get extents of the buffer along the ordinate, excepting the 
+//! artificial intervals at infinite ordinate
+inline void Poly_IBuffer::GetOrdinateExtents (Standard_Real& theMin,
+                                              Standard_Real& theMax) const
+{
+  theMin = myMinOrd;
+  theMax = myMaxOrd;
+}
index f967c4b092cb37576c2d6e9f5276ba373c5293c8..ac296dfbf8ce689d2bfa75e8b68f2376444b42af 100644 (file)
@@ -106,6 +106,12 @@ is
     ExtensionSize (me) returns Real from Standard;
     ---Purpose: Returns extension size.
 
+    SetShortExtensionSize (me : mutable; theSize : Real from Standard);
+    ---Purpose: Set size for the short extension (without text).
+
+    ShortExtensionSize (me) returns Real from Standard;
+    ---Purpose: Returns extension size.
+
     SetValueStringFormat (me : mutable; theFormat : AsciiString from TCollection);
     ---Purpose: Sets "sprintf"-syntax format for formatting dimension value labels.
 
@@ -138,7 +144,10 @@ fields
 
     myExtensionSize : Real from Standard;
     ---Purpose: Size of arrow extensions.
-    -- The length of arrow tails if arrows are located outside dimension line.
+    -- The length of arrow tail with text if arrows are located outside dimension line.
+
+    myShortExtensionSize : Real from Standard;
+    ---Purpose: Size of the short extension (extension without text).
 
     myValueStringFormat : AsciiString from TCollection;
     ---Purpose: "sprintf"-syntax format for formatting dimension value labels.
index 6ab07165890ae8ea85e337766662c7f9fda02c44..cdee12fa6d65a4ad25cc0ea051d55548e2bd762c 100755 (executable)
@@ -46,9 +46,10 @@ Prs3d_DimensionAspect::Prs3d_DimensionAspect()
   myArrowAspect->SetColor (Quantity_NOC_LAWNGREEN);
   myArrowAspect->SetAngle (M_PI * 20.0 / 180.0);
   myArrowAspect->SetLength (6.0);
-  myExtensionSize     = 6.0;
-  myValueStringFormat = "%g";
-  myToDisplayUnits    = Standard_False;
+  myExtensionSize      = 6.0;
+  myShortExtensionSize = 6.0;
+  myValueStringFormat  = "%g";
+  myToDisplayUnits     = Standard_False;
 }
 
 //=======================================================================
@@ -261,6 +262,24 @@ Standard_Real Prs3d_DimensionAspect::ExtensionSize() const
   return myExtensionSize;
 }
 
+//=======================================================================
+//function : SetShortExtensionSize
+//purpose  : 
+//=======================================================================
+void Prs3d_DimensionAspect::SetShortExtensionSize (const Standard_Real theSize)
+{
+  myShortExtensionSize = theSize;
+}
+
+//=======================================================================
+//function : ShortExtensionSize
+//purpose  : 
+//=======================================================================
+Standard_Real Prs3d_DimensionAspect::ShortExtensionSize() const
+{
+  return myShortExtensionSize;
+}
+
 //=======================================================================
 //function : SetValueStringFormat
 //purpose  : 
index f1c0686ef820b480bea06962b108cee885a8b8a9..a097cba55b97504265d6935214e0031a5739727d 100644 (file)
@@ -62,6 +62,9 @@ is
     SetVisible (me: mutable; theValue: Boolean from Standard) is redefined static private;
 
     Highlight(me: mutable) is redefined static private;
+
+    HighlightWithColor(me:mutable; theColor: NameOfColor from Quantity)
+    is static private;
     
     Unhighlight (me) is redefined static private;
     
@@ -93,9 +96,6 @@ is
     --          
     is redefined static private;
 
-
-    Color(me:mutable; aColor: NameOfColor from Quantity)
-    is static private;
     
     BoundBox(me)
     is static private;
@@ -164,7 +164,7 @@ is
 fields
 
     myStructure: Prs from PrsMgr;
-    myDisplayReason: Boolean from Standard;
+    myDisplayForHighlight: Boolean from Standard;
     myPresentableObject: PresentableObjectPointer from PrsMgr;
 friends 
     class PresentationManager3d from PrsMgr,
index e127db4737a075aa5e8fac0a6a9d2ae062a0a91a..582687e7cedca18d853e6b73a4e55b172979a573 100644 (file)
@@ -32,7 +32,7 @@
 PrsMgr_Presentation3d::PrsMgr_Presentation3d (const Handle(PrsMgr_PresentationManager3d)& aPresentationManager, 
                                               const Handle(PrsMgr_PresentableObject)& aPresentableObject)
 : PrsMgr_Presentation(aPresentationManager), 
-  myDisplayReason(Standard_False),
+  myDisplayForHighlight(Standard_False),
   myPresentableObject (aPresentableObject.operator->())
 {
   myStructure = new PrsMgr_Prs(aPresentationManager->StructureManager(),
@@ -47,20 +47,19 @@ PrsMgr_KindOfPrs PrsMgr_Presentation3d::KindOfPresentation() const
 void PrsMgr_Presentation3d::Display()
 {
   Display (Standard_False);
-  myDisplayReason = Standard_False;
 }
 
-void PrsMgr_Presentation3d::Display(const Standard_Boolean theIsHighlight)
+void PrsMgr_Presentation3d::Display (const Standard_Boolean theIsHighlight)
 {
   if (!myStructure->IsDisplayed())
   {
     myStructure->Display();
-    myDisplayReason = theIsHighlight;
+    myDisplayForHighlight = theIsHighlight;
   }
   else if (!myStructure->IsVisible())
   {
     myStructure->SetVisible (Standard_True);
-    myDisplayReason = theIsHighlight;
+    //myDisplayReason = theIsHighlight;
   }
 }
 
@@ -80,13 +79,27 @@ void PrsMgr_Presentation3d::SetVisible (const Standard_Boolean theValue)
   myStructure->SetVisible (theValue);
 }
 
-void PrsMgr_Presentation3d::Highlight () {
+void PrsMgr_Presentation3d::Highlight ()
+{
   Display (Standard_True);
-  myStructure->Highlight();}
+  myStructure->Highlight();
+}
 
-void PrsMgr_Presentation3d::Unhighlight () const {
+void PrsMgr_Presentation3d::HighlightWithColor (const Quantity_NameOfColor theColor)
+{
+  Display (Standard_True);
+  myStructure->Color (theColor);
+}
+
+
+void PrsMgr_Presentation3d::Unhighlight () const
+{
   myStructure->UnHighlight();
-  if (myDisplayReason) myStructure->SetVisible (Standard_False);
+  if (myDisplayForHighlight)
+  {
+    myStructure->Erase ();
+  }
+  //if (myDisplayReason) myStructure->SetVisible (Standard_False);
 }
 
 void PrsMgr_Presentation3d::Clear() {
@@ -102,18 +115,14 @@ void PrsMgr_Presentation3d::Clear() {
   myStructure->RemoveAll();
 }
 
-void PrsMgr_Presentation3d::Color(const Quantity_NameOfColor aColor){
-  Display (Standard_True);
-  myStructure->Color(aColor);
-}
-
 void PrsMgr_Presentation3d::BoundBox() const {
    myStructure->BoundBox();
 }
 
-Standard_Boolean PrsMgr_Presentation3d::IsDisplayed () const {
-  return myStructure->IsDisplayed() && myStructure->IsVisible() && !myDisplayReason;
-}        
+Standard_Boolean PrsMgr_Presentation3d::IsDisplayed () const
+{
+  return myStructure->IsDisplayed() && myStructure->IsVisible() && !myDisplayForHighlight;
+}
 
 Standard_Boolean PrsMgr_Presentation3d::IsHighlighted () const {
   return myStructure->IsHighlighted();
@@ -365,9 +374,13 @@ Handle(Prs3d_Projector) PrsMgr_Presentation3d::Projector(const Handle(Graphic3d_
 
 }
 
-void PrsMgr_Presentation3d::Destroy () {
+void PrsMgr_Presentation3d::Destroy ()
+{
   if (!myStructure.IsNull())
+  {
+    myStructure->Erase();
     myStructure->Clear();
+  }
   myStructure.Nullify();
 }
 
index 2002494d02e0962f6c192c1fda50cca31c65d5b6..7c4698abe00740555be3229176d6c2e53c308a44 100644 (file)
@@ -86,7 +86,7 @@ void PrsMgr_PresentationManager3d::Color(const Handle(PrsMgr_PresentableObject)&
   else if(Presentation(aPresentableObject,aMode)->MustBeUpdated()){
     Update(aPresentableObject,aMode);
   }
-  CastPresentation(aPresentableObject,aMode)->Color(aColor); 
+  CastPresentation(aPresentableObject,aMode)->HighlightWithColor (aColor);
   
   if(myImmediateMode)
     Add(aPresentableObject,aMode);
index df2abf5741eb3ce9ed677f250983c3300e86d024..fd43db0de3e904dc5d652b8bdd10cdc0aba9782f 100644 (file)
 #include <stdio.h>
 #include <gp_Vec.hxx>
 
+#include <BRepBuilderAPI_CellFilter.hxx>
+#include <BRepBuilderAPI_VertexInspector.hxx>
+
+// A static method adding nodes to a mesh and keeping coincident (sharing) nodes.
+static Standard_Integer AddVertex(Handle(StlMesh_Mesh)& mesh,
+                                  BRepBuilderAPI_CellFilter& filter, 
+                                  BRepBuilderAPI_VertexInspector& inspector,
+                                  const gp_XYZ& p)
+{
+  Standard_Integer index;
+  inspector.SetCurrent(p);
+  gp_XYZ minp = inspector.Shift(p, -Precision::Confusion());
+  gp_XYZ maxp = inspector.Shift(p, +Precision::Confusion());
+  filter.Inspect(minp, maxp, inspector);
+  const TColStd_ListOfInteger& indices = inspector.ResInd();
+  if (indices.IsEmpty() == Standard_False)
+  {
+    index = indices.First(); // it should be only one
+    inspector.ClearResList();
+  }
+  else
+  {
+    index = mesh->AddVertex(p.X(), p.Y(), p.Z());
+    filter.Add(index, p);
+    inspector.Add(p);
+  }
+  return index;
+}
 
 // constants
 static const int HEADER_SIZE           =  84;
@@ -357,6 +385,10 @@ Handle_StlMesh_Mesh RWStl::ReadBinary (const OSD_Path& thePath,
   Handle(StlMesh_Mesh) ReadMesh = new StlMesh_Mesh ();
   ReadMesh->AddDomain ();
 
+  // Filter unique vertices to share the nodes of the mesh.
+  BRepBuilderAPI_CellFilter uniqueVertices(Precision::Confusion());
+  BRepBuilderAPI_VertexInspector inspector(Precision::Confusion());
+  
   for (ifacet=1; ifacet<=NBFACET; ++ifacet) {
     // read normal coordinates
     fx = ReadFloat2Double(theFile);
@@ -378,9 +410,12 @@ Handle_StlMesh_Mesh RWStl::ReadBinary (const OSD_Path& thePath,
     fy3 = ReadFloat2Double(theFile);
     fz3 = ReadFloat2Double(theFile);
 
-    i1 = ReadMesh->AddOnlyNewVertex (fx1,fy1,fz1);
-    i2 = ReadMesh->AddOnlyNewVertex (fx2,fy2,fz2);
-    i3 = ReadMesh->AddOnlyNewVertex (fx3,fy3,fz3);
+    // Add vertices.
+    i1 = AddVertex(ReadMesh, uniqueVertices, inspector, gp_XYZ(fx1, fy1, fz1));
+    i2 = AddVertex(ReadMesh, uniqueVertices, inspector, gp_XYZ(fx2, fy2, fz2));
+    i3 = AddVertex(ReadMesh, uniqueVertices, inspector, gp_XYZ(fx3, fy3, fz3));
+
+    // Add triangle.
     ReadMesh->AddTriangle (i1,i2,i3,fx,fy,fz);
 
     // skip extra bytes
@@ -389,7 +424,6 @@ Handle_StlMesh_Mesh RWStl::ReadBinary (const OSD_Path& thePath,
 
   theFile.Close ();
   return ReadMesh;
-
 }
 //=======================================================================
 //function : ReadAscii
@@ -442,6 +476,10 @@ Handle_StlMesh_Mesh RWStl::ReadAscii (const OSD_Path& thePath,
   ReadMesh = new StlMesh_Mesh();
   ReadMesh->AddDomain();
 
+  // Filter unique vertices to share the nodes of the mesh.
+  BRepBuilderAPI_CellFilter uniqueVertices(Precision::Confusion());
+  BRepBuilderAPI_VertexInspector inspector(Precision::Confusion());
+  
   // main reading
   Message_ProgressSentry aPS (theProgInd, "Triangles", 0, (nbTris - 1) * 1.0 / IND_THRESHOLD, 1);
   for (iTri = 0; iTri < nbTris && aPS.More();)
@@ -469,9 +507,9 @@ Handle_StlMesh_Mesh RWStl::ReadAscii (const OSD_Path& thePath,
 
     // here the facet must be built and put in the mesh datastructure
 
-    i1 = ReadMesh->AddOnlyNewVertex (aV1.X(), aV1.Y(), aV1.Z());
-    i2 = ReadMesh->AddOnlyNewVertex (aV2.X(), aV2.Y(), aV2.Z());
-    i3 = ReadMesh->AddOnlyNewVertex (aV3.X(), aV3.Y(), aV3.Z());
+    i1 = AddVertex(ReadMesh, uniqueVertices, inspector, aV1);
+    i2 = AddVertex(ReadMesh, uniqueVertices, inspector, aV2);
+    i3 = AddVertex(ReadMesh, uniqueVertices, inspector, aV3);
     ReadMesh->AddTriangle (i1, i2, i3, aN.X(), aN.Y(), aN.Z());
 
     // skip the keywords "endloop"
index b2a0bc63974fb7e5177fb7e3cad3f87787374465..b5c64ff4ecb2a581c34244e995d66d5b2d34c53c 100644 (file)
@@ -36,10 +36,11 @@ uses
     Curve           from Geom,
     Array1OfPnt     from TColgp,
     Array1OfPnt2d   from TColgp,
-    HArray1OfPnt     from TColgp,
+    HArray1OfPnt    from TColgp,
     Box2d           from Bnd,
-    Location                 from TopLoc, 
-    SensitiveEntity   from Select3D
+    Location        from TopLoc, 
+    SensitiveEntity from Select3D,
+    XYZ             from gp
 
 raises
     ConstructionError from Standard,
@@ -120,6 +121,17 @@ is
         ---Level: Public 
         ---Purpose: Returns the copy of this
 
+    ComputeDepth(me;
+                 thePickLine : Lin from gp;
+                 theP1       : XYZ from gp;
+                 theP2       : XYZ from gp;
+                 theDepth    : out Real from Standard)
+    ---Purpose: Computes the depth by means of intersection of
+    --          a segment of the curve defined by <theP1, theP2> and
+    --          the eye-line <thePickLine>.
+    returns Boolean from Standard
+    is protected;
+
 fields
     mylastseg : Integer        from Standard;
     myCurve  : Curve from Geom;
index 02f09274d2d50872ab375aaa71942dc8f527d994..19a9cf1759c80e9e27bce607693f17f66c658b95 100644 (file)
@@ -20,7 +20,7 @@
 #include <Precision.hxx>
 #include <ElCLib.hxx>
 #include <CSLib_Class2d.hxx>
-
+#include <Extrema_ExtElC.hxx>
 
 //==================================================
 // Function: Creation
@@ -187,20 +187,43 @@ void Select3D_SensitiveCurve::Dump(Standard_OStream& S,const Standard_Boolean Fu
 Standard_Real Select3D_SensitiveCurve::ComputeDepth (const gp_Lin& thePickLine,
                                                      const Standard_Integer theSegment) const
 {
+  Standard_Real aDepth = Precision::Infinite();
   if (theSegment == 0)
   {
-    return Precision::Infinite();
+    return aDepth;
   }
 
   // In case if theSegment and theSegment + 1 are not valid
   // the depth will be infinite
   if (theSegment >= mypolyg.Size())
   {
-    return Precision::Infinite();
+    return aDepth;
   }
 
   gp_XYZ aCDG = mypolyg.Pnt (theSegment);
 
+  // Check depth of a line forward within the curve.
+  if (theSegment + 1 < mypolyg.Size())
+  {
+    gp_XYZ aCDG1 = mypolyg.Pnt (theSegment + 1);
+    if (ComputeDepth(thePickLine, aCDG, aCDG1, aDepth))
+    {
+      return aDepth;
+    }
+  }
+
+  // Check depth of a line backward within the curve.
+  if (theSegment - 1 >= 0)
+  {
+    gp_XYZ aCDG1 = mypolyg.Pnt (theSegment - 1);
+    if (ComputeDepth(thePickLine, aCDG, aCDG1, aDepth))
+    {
+      return aDepth;
+    }
+  }
+
+  // Calculate the depth in the middle point of
+  // a next (forward) segment of the curve.
   if (theSegment + 1 < mypolyg.Size())
   {
     aCDG += mypolyg.Pnt(theSegment + 1);
@@ -244,3 +267,48 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitiveCurve::GetConnected(const Top
 
   return aNewEntity;
 }
+
+//=======================================================================
+//function : ComputeDepth()
+//purpose  : Computes the depth by means of intersection of
+//           a segment of the curve defined by <theP1, theP2> and
+//           the eye-line <thePickLine>.
+//=======================================================================
+
+Standard_Boolean Select3D_SensitiveCurve::ComputeDepth(const gp_Lin& thePickLine,
+                                                       const gp_XYZ& theP1,
+                                                       const gp_XYZ& theP2,
+                                                       Standard_Real& theDepth) const
+{
+  // The segment may have null length.
+  gp_XYZ aVec = theP2 - theP1;
+  Standard_Real aLength = aVec.Modulus();
+  if (aLength <= gp::Resolution())
+  {
+    theDepth = ElCLib::Parameter(thePickLine, theP1);
+    return Standard_True;
+  }
+
+  // Compute an intersection point of the segment-line and the eye-line.
+  gp_Lin aLine (theP1, aVec);
+  Extrema_ExtElC anExtrema(aLine, thePickLine, Precision::Angular());
+  if (anExtrema.IsDone() && !anExtrema.IsParallel() )
+  {
+    // Iterator on solutions (intersection points).
+    for (Standard_Integer i = 1; i <= anExtrema.NbExt(); i++)
+    {
+      // Get the intersection point.
+      Extrema_POnCurv aPointOnLine1, aPointOnLine2;
+      anExtrema.Points(i, aPointOnLine1, aPointOnLine2);
+
+      // Check bounds: the point of intersection should lie within the segment.
+      if (aPointOnLine1.Parameter() > 0.0 && aPointOnLine1.Parameter() < aLength)
+      {
+        theDepth = ElCLib::Parameter(thePickLine, aPointOnLine1.Value());
+        return Standard_True;
+      }
+    }
+  }
+
+  return Standard_False;
+}
index 60bd1d6eb0de252cce09485ea72eb85545f9577a..5628b7989aa6cd5a00c1b6f95f55bec7cb0821c4 100644 (file)
@@ -59,6 +59,9 @@ static Standard_Boolean S3D_STriangul_NearSegment (const gp_XY& p0, const gp_XY&
   gp_XY V01(p1);V01-=p0;
   gp_XY Vec(TheP);Vec -= p0;
 
+  if (V01.SquareModulus() < Precision::SquareConfusion())
+    return Standard_False;
+
   Standard_Real u = Vec*V01.Normalized();
   if(u<-aTol) return Standard_False;
   Standard_Real u1 = u-aTol;
index 370859d73c195cfefd659eed3f61267a90e4b0f1..d40f9e514a6f376901402947f3622dba6724fcb7 100644 (file)
@@ -35,3 +35,8 @@ inline Standard_Boolean Select3D_SensitiveTriangulation::HasInitLocation() const
 {return !myiniloc.IsIdentity();}
 inline const TopLoc_Location& Select3D_SensitiveTriangulation::GetInitLocation() const
 {return myiniloc;}
+
+inline Standard_Integer Select3D_SensitiveTriangulation::DetectedTriangle() const
+{
+  return myDetectedTr;
+}
index a5517794381e8d4fcdc0c4b7a03be7f192154f2c..b0c0f38d2d4e4e8f57cc6fdfbc7b9466ef5f282b 100644 (file)
@@ -345,6 +345,8 @@ static Standard_Boolean MinMaxSmall
       continue; // ignore seam edge
     TopoDS_Vertex V1,V2;
     TopExp::Vertices (E,V1,V2);
+    if (V1.IsNull() || V2.IsNull())
+      continue;
     gp_Pnt p1,p2;
     p1 = BRep_Tool::Pnt (V1);
     p2 = BRep_Tool::Pnt (V2);
index 5ff99e31030e8316bc7926a6b1cc11583b1e3596..cf599d03b2880eab87e9d4f876df27599eebdc3a 100644 (file)
@@ -432,8 +432,16 @@ Standard_Boolean ShapeAnalysis_Edge::CheckCurve3dWithPCurve (const TopoDS_Edge&
     return Standard_False;
   }
 
-  Standard_Real preci1 = BRep_Tool::Tolerance (FirstVertex (edge)),
-                preci2 = BRep_Tool::Tolerance (LastVertex (edge));
+  // Use tolerance of vertices to compare points 2d and 3d.
+  Standard_Real preci1 = Precision::Confusion(),
+                preci2 = Precision::Confusion();
+  TopoDS_Vertex V1 = FirstVertex(edge);
+  TopoDS_Vertex V2 = LastVertex(edge);
+  if (!V1.IsNull() && !V2.IsNull())
+  {
+    preci1 = BRep_Tool::Tolerance(V1),
+    preci2 = BRep_Tool::Tolerance(V2);
+  }
 
   gp_Pnt2d p2d1 = c2d->Value (f2d),
            p2d2 = c2d->Value (l2d);
@@ -559,6 +567,8 @@ Standard_Boolean ShapeAnalysis_Edge::CheckVerticesWithPCurve (const TopoDS_Edge&
   if (vtx != 2) { //  1er VTX
     gp_Pnt2d p1uv = c2d->Value (cf);  
     gp_Pnt p12d = surf->Value (p1uv.X(), p1uv.Y());
+    if (!loc.IsIdentity())
+      p12d.Transform(loc.Transformation());
     // szv#4:S4163:12Mar99 optimized
     if ( p1v.Distance(p12d) > (preci < 0 ? BRep_Tool::Tolerance (V1) : preci) )
       myStatus |= ShapeExtend_DONE1;
@@ -567,6 +577,8 @@ Standard_Boolean ShapeAnalysis_Edge::CheckVerticesWithPCurve (const TopoDS_Edge&
   if (vtx != 1) { //  2me VTX
     gp_Pnt2d p2uv = c2d->Value (cl);  
     gp_Pnt p22d = surf->Value (p2uv.X(), p2uv.Y());
+    if (!loc.IsIdentity())
+      p22d.Transform(loc.Transformation());
     // szv#4:S4163:12Mar99 optimized
     if ( p2v.Distance(p22d) > (preci < 0 ? BRep_Tool::Tolerance (V2) : preci) )
       myStatus |= ShapeExtend_DONE2;
index e726222b452c1141888967a65a0537634bf4ad89..49684f8d3585e8338c2fd4141f02dab40061d417 100644 (file)
@@ -807,6 +807,10 @@ Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated (const Standard_Integer nu
   TopoDS_Vertex V0 = sae.LastVertex  (E1);
   TopoDS_Vertex V1 = sae.FirstVertex (E2);
   TopoDS_Vertex V2 = sae.LastVertex  (E2);
+  if (Vp.IsNull() || V0.IsNull() || V1.IsNull() || V2.IsNull())
+  {
+    return Standard_False;
+  }
   gp_Pnt pp = BRep_Tool::Pnt (Vp); //:i9
   gp_Pnt p0 = BRep_Tool::Pnt (V0);
   gp_Pnt p1 = BRep_Tool::Pnt (V1);
index e128495c652a25f4126b22b7b6935dda13a19fef..b3d0b3a7b96f145e862ea15e597fd402fbd443f8 100644 (file)
@@ -1311,7 +1311,8 @@ Standard_Boolean ShapeFix_Wire::FixShifted()
     TopoDS_Edge E1 = sbwdOring->Edge ( i );
     if ( BRep_Tool::Degenerated(E1) && !sae.HasPCurve(E1,Face()))
       continue;
-    
+    if (sae.FirstVertex(E1).IsNull())
+      continue;
     sbwd->Add(E1);
   }
   
index c4fb2cb2d5d4d876e67c8990b7d65d40d6b96fcd..e8ce3605ad95f3a7251c59f0cee9bc6e373c1eb5 100755 (executable)
@@ -72,6 +72,24 @@ Standard_Integer HashCodes (const Standard_CString Value,
   return hash;
 }
 
+//============================================================================
+//==== HashCode of a CString (case-insensitive)
+//============================================================================
+Standard_Integer HASHCODES (const Standard_CString Value,
+                            const Standard_Integer Len)
+{
+  // compute DJB2 hash of a string
+  Standard_Integer hash = 0;
+  const Standard_Character *c = Value;
+  for (Standard_Integer i = 0; i < Len; i++, c++)
+  {
+    /* hash = hash * 33 ^ c */
+    hash = ((hash << 5) + hash) ^ (c[0] & 0xdf);
+  }
+
+  return hash;
+}
+
 //======================================================================
 // Locale-independent equivalents of C functions dealing with conversion
 // of string to real and vice-versa
index a52be218e58a208174503fe806cd9268369d6b1c..e1a6f2c647f51cd2465d808c10dfc94b4ee1ef0b 100644 (file)
@@ -59,6 +59,8 @@ inline Standard_Integer HashCode (const Standard_CString,
                                   Standard_Integer& );
 Standard_Integer HashCodes (const Standard_CString ,
                             const Standard_Integer  );
+__Standard_API Standard_Integer HASHCODES (const Standard_CString ,
+                                           const Standard_Integer  );
 
 //! Equivalents of functions from standard C library that use always C locale
 __Standard_API double Atof    (const char* theStr);
index ecf40fa0d452393344d61f9a7f70b784bd313d14..853c7712691a0547af5608f1c3576cf59935ebc1 100644 (file)
@@ -420,10 +420,22 @@ Standard_Integer Standard_GUID::Hash(const Standard_Integer Upper) const
       Raise("Standard_GUID::Hash: Try to apply HashCode method with negative or null argument.");
   }
 
-  char sguid[Standard_GUID_SIZE_ALLOC];
-  ToCString(sguid);
-
-  return ::HashCode(sguid,Upper);
+  // ==== AGV 16/12/2012: More optimal hash function ===
+   //char sguid[Standard_GUID_SIZE_ALLOC];
+   //ToCString(sguid);
+   //return ::HashCode(sguid,Upper);
+  // ===================================================
+  unsigned int aHash = ((static_cast<unsigned int>(my8b6) << 24) |
+                        (static_cast<unsigned int>(my8b5) << 16) |
+                        (static_cast<unsigned int>(my8b4) << 8) |
+                        (static_cast<unsigned int>(my8b3)));
+  aHash = (aHash ^ (aHash >> 11)) & 0x07ffffff;
+  aHash = (aHash * 31 + ((static_cast<unsigned int>(my8b2) << 24) |
+                         (static_cast<unsigned int>(my8b1) << 16) |
+                         (static_cast<unsigned int>(my16b3)))) & 0x07ffffff;
+  aHash = (aHash * 31 + ((static_cast<unsigned int>(my16b2) << 16) |
+                         (static_cast<unsigned int>(my16b1)))) & 0x07ffffff;
+  return (aHash * 31 + my32b) % Upper;
 }
 
 Standard_Boolean Standard_GUID::IsEqual(const Standard_GUID& aGuid1,const Standard_GUID& aGuid2)
index 0ef0b711d4ffa42bc57fd173ce014fca8afcf922..5fc4621c555d4c29b7396eeda369b9e708cf246a 100644 (file)
@@ -60,14 +60,15 @@ Handle(Select3D_Projector) StdSelect::GetProjector(const Handle(V3d_View)& aViou
 //purpose  : 
 //=======================================================================
 
-void StdSelect::SetDrawerForBRepOwner(const Handle(SelectMgr_Selection)& /*Sel*/,
-                                    const Handle(Prs3d_Drawer)& /*Drwr*/)
+void StdSelect::SetDrawerForBRepOwner(const Handle(SelectMgr_Selection)& Sel,
+                                    const Handle(Prs3d_Drawer)& Drwr)
 {
-//  Handle(StdSelect_BRepOwner) BROWN;
+    Handle(StdSelect_BRepOwner) BROWN;
 
-//   for(Sel->Init();Sel->More();Sel->Next()){
-//     BROWN = Handle(StdSelect_BRepOwner)::DownCast(Sel->Sensitive()->OwnerId());
-//     if(!BROWN.IsNull())
-//       BROWN->SetDrawer(Drwr);
-//   }
+    for(Sel->Init();Sel->More();Sel->Next())
+    {
+        BROWN = Handle(StdSelect_BRepOwner)::DownCast(Sel->Sensitive()->OwnerId());
+        if(!BROWN.IsNull())
+            BROWN->SetDrawer(Drwr);
+    }
 }
index 0642ba32ff3280c74a50665ef932bab5e443e60b..3d2b466bb2df3a261bda68c951c7dfad509505fd 100644 (file)
@@ -148,11 +148,18 @@ is
       is redefined virtual;
     ---Purpose: Set Z layer ID and update all presentations.
 
+    ---Purpose: Defines a drawer for highlighting of shapes.
+    SetDrawer(me : mutable; aDrawer : Drawer from Prs3d);
+    GetDrawer(me : mutable)
+    ---C++: return const &
+    returns Drawer from Prs3d;
+
 fields
     myPrsSh            : Shape   from StdSelect; 
     myCurMode          : Integer from Standard;
     myFromDecomposition : Boolean from Standard is protected;
     myShape             : Shape from TopoDS     is protected;
+    myDrawer                           : Drawer from Prs3d;
 end BRepOwner;
 
 
index 6052585670b2b18d1cc8f5c8a08e83880ac4db15..759cc9a3912f44141162d973aac8db2bbccaba4f 100644 (file)
@@ -100,7 +100,11 @@ void StdSelect_BRepOwner::Hilight(const Handle(PrsMgr_PresentationManager)& PM,
 
     // generate new presentable shape
     if(myPrsSh.IsNull())
-      myPrsSh = new StdSelect_Shape (myShape);
+    {
+      myPrsSh = new StdSelect_Shape(myShape);
+      if (!myDrawer.IsNull())
+          myPrsSh->SetDrawer(myDrawer);
+    }
 
     // highlight and set layer
     PM->Highlight (myPrsSh, M);
@@ -155,6 +159,9 @@ void StdSelect_BRepOwner::HilightWithColor(const Handle(PrsMgr_PresentationManag
       }
       else
         myPrsSh = new StdSelect_Shape(myShape);
+
+      if (!myDrawer.IsNull())
+        myPrsSh->SetDrawer(myDrawer);
     }
 
     // highlight with color and set layer
@@ -234,3 +241,13 @@ void StdSelect_BRepOwner::SetZLayer
   if (!myPrsSh.IsNull())
     thePrsMgr->SetZLayer (myPrsSh, theLayerId);
 }
+
+void StdSelect_BRepOwner::SetDrawer(const Handle(Prs3d_Drawer)& drawer)
+{
+    myDrawer = drawer;
+}
+
+const Handle(Prs3d_Drawer)& StdSelect_BRepOwner::GetDrawer()
+{
+    return myDrawer;
+}
\ No newline at end of file
index 7fdd0cf8713dce3aa7da82bc3fc701b6b3e66e20..339d0e2b329bb99862d1f2ba92d2434f073b8716 100644 (file)
@@ -23,7 +23,8 @@ uses
     Transformation        from Geom,
     Shape                 from TopoDS,
     PresentationManager3d from PrsMgr,
-    Presentation          from Prs3d
+    Presentation          from Prs3d,
+    Drawer                from Prs3d
 
 is
     Create(Sh:Shape from TopoDS) returns mutable Shape from StdSelect;
@@ -60,6 +61,9 @@ is
     Shape(me:mutable;sh : Shape from TopoDS);
        ---C++: inline
 
+    SetDrawer(me : mutable; aDrawer : Drawer from Prs3d);
+
 fields
     mysh : Shape  from TopoDS;
+    myDrawer : Drawer from Prs3d;
 end Shape;
index 71519e7d84a8e33bb85aaf0f498d27a44ea77131..9f4d499c5b31d073f6c29382b7b9eabde3b741b9 100644 (file)
@@ -28,34 +28,42 @@ StdSelect_Shape::StdSelect_Shape(const TopoDS_Shape& sh):
        mysh(sh)
 {}
      
-void StdSelect_Shape::Compute(const Handle(PrsMgr_PresentationManager3d)& /*PM*/,
+void StdSelect_Shape::Compute(const Handle(PrsMgr_PresentationManager3d)& PM,
                              const Handle(Prs3d_Presentation)& P,
                              const Standard_Integer aMode)
 {
   if(mysh.IsNull()) return;
   
-  static Handle(Prs3d_Drawer) DRWR;
-  if(DRWR.IsNull()){
-    DRWR = new Prs3d_Drawer();
-    DRWR->WireAspect()->SetWidth(2);
-    DRWR->LineAspect()->SetWidth(2.);
-    DRWR->PlaneAspect()->EdgesAspect()->SetWidth(2.);
-    DRWR->FreeBoundaryAspect()->SetWidth(2.);
-    DRWR->UnFreeBoundaryAspect()->SetWidth(2.);
-    Standard_Integer I = 5;//pour tests...
-    DRWR->PointAspect()->SetTypeOfMarker((Aspect_TypeOfMarker)I);
-    DRWR->PointAspect()->SetScale(2.);
-  }
+    Handle(Prs3d_Drawer) drawer;
+    if (myDrawer.IsNull())
+    {
+        static Handle(Prs3d_Drawer) DRWR;
+        if (DRWR.IsNull())
+        {
+            DRWR = new Prs3d_Drawer();
+            DRWR->WireAspect()->SetWidth(2);
+            DRWR->LineAspect()->SetWidth(2.);
+            DRWR->PlaneAspect()->EdgesAspect()->SetWidth(2.);
+            DRWR->FreeBoundaryAspect()->SetWidth(2.);
+            DRWR->UnFreeBoundaryAspect()->SetWidth(2.);
+            Standard_Integer I = 5;//pour tests...
+            DRWR->PointAspect()->SetTypeOfMarker((Aspect_TypeOfMarker)I);
+            DRWR->PointAspect()->SetScale(2.);
+        }
+        drawer = DRWR;
+    }
+    else
+        drawer = myDrawer;
   
   Standard_Boolean CanShade = (mysh.ShapeType()<5 || mysh.ShapeType()==8);
   if(aMode==1){
     if(CanShade)
-      StdPrs_ShadedShape::Add(P,mysh,DRWR);
+      StdPrs_ShadedShape::Add(P,mysh,drawer);
     else
-      StdPrs_WFShape::Add(P,mysh,DRWR);
+      StdPrs_WFShape::Add(P,mysh,drawer);
   }
-  else if (aMode==0)
-    StdPrs_WFShape::Add(P,mysh,DRWR);
+  else if (aMode<=0)
+    StdPrs_WFShape::Add(P,mysh,drawer);
 }
 
 void StdSelect_Shape::Compute(const Handle_Prs3d_Projector& aProjector ,
@@ -71,3 +79,8 @@ void StdSelect_Shape::Compute(const Handle_Prs3d_Projector& aProjector,
 {
   PrsMgr_PresentableObject::Compute(aProjector,aPresentation);
 }
+
+void StdSelect_Shape::SetDrawer(const Handle(Prs3d_Drawer)& drawer)
+{
+    myDrawer = drawer;
+}
\ No newline at end of file
index 977d81dbfd18343b3914d5ba1ab92ff33f6d9ee1..6210d63772c49c36c95fae5ae06ed20bd81ec136 100644 (file)
@@ -89,9 +89,3 @@ Standard_Integer StlMesh_MeshDomain::AddOnlyNewVertex(const Standard_Real X,
   nbVertices++;
   return nbVertices;
 }
-
-
-
-
-
-
index 4220f85ce0b9e8d76f6825b315a7d6ccb80e8905..66f3969dea0fd4f7f41154f8bba716b6790a1430 100644 (file)
@@ -248,10 +248,13 @@ static void TDF_Tool_OutReferers(const TDF_Label& aRefLabel,
       // const Handle(TDF_Attribute)& att = attMItr.Key();
       Handle(TDF_Attribute) att = attMItr.Key();
       // ENDCLE
-      if (aFilterForReferences.IsKept(att) && !att->Label().IsDescendant(aRefLabel)) {
-       atts.Add(itr.Value());
-       outRefFound = Standard_True;
-       break;
+      if (aFilterForReferences.IsKept(att) &&
+          !att->Label().IsNull() &&
+          !att->Label().IsDescendant(aRefLabel))
+      {
+        atts.Add(itr.Value());
+        outRefFound = Standard_True;
+        break;
       }
     }
 
@@ -318,8 +321,11 @@ static void TDF_Tool_OutReferences(const TDF_Label& aRefLabel,
     const TDF_AttributeMap& attMap = ds->Attributes();
     for (TDF_MapIteratorOfAttributeMap attMItr(attMap);attMItr.More();attMItr.Next()) {
       Handle(TDF_Attribute) att = attMItr.Key();
-      if (aFilterForReferences.IsKept(att) && !att->Label().IsDescendant(aRefLabel)) {
-       atts.Add(att);
+      if (aFilterForReferences.IsKept(att) &&
+          !att->Label().IsNull() &&
+          !att->Label().IsDescendant(aRefLabel))
+      {
+        atts.Add(att);
       }
     }
     const TDF_LabelMap& labMap = ds->Labels();
index 3d235d187e92e103b6805974edf719883a2b7286..9a4962a06bfedb89473e4eeb10855d6fc008c623 100644 (file)
@@ -28,7 +28,7 @@ inline Standard_Boolean TDataStd_ChildNodeIterator::More() const
 //purpose  : 
 //=======================================================================
 
-inline Handle(TDataStd_TreeNode) TDataStd_ChildNodeIterator::Value() const
+inline const Handle(TDataStd_TreeNode)& TDataStd_ChildNodeIterator::Value() const
 { 
   return myNode;
 }
index e7773e1feef236fa05df8bd245a625813a5b9c9a..943a1fa978c7128e989abc64091f3b2e36eecf06 100644 (file)
@@ -226,7 +226,7 @@ Standard_Boolean TDataStd_TreeNode::Remove ()
   }
 
   if (Father()->HasFirst()) {
-    if (Handle(TDataStd_TreeNode)::DownCast(this) == Father()->First()) {
+    if (this == Father()->First().operator->()) {
       if (HasNext()) {
            Father()->SetFirst(Next());
       }
@@ -235,12 +235,7 @@ Standard_Boolean TDataStd_TreeNode::Remove ()
   }
   
   if(Father()->HasLast()) {
-    if (Handle(TDataStd_TreeNode)::DownCast(this) == Father()->Last()) {
-      if(HasPrevious()) {
-        Father()->SetLast(Previous());
-      }
-      else Father()->SetLast(bid);
-    }
+    Father()->SetLast(bid);
   }
 
   SetFather(bid);
@@ -698,6 +693,10 @@ Standard_OStream& TDataStd_TreeNode::Dump (Standard_OStream& anOS) const
     anOS<<"  First=";
     if (!myFirst->Label().IsNull()) myFirst->Label().EntryDump(anOS);
   }
+  if (myLast) {
+    anOS<<"  Last=";
+    if (!myLast->Label().IsNull()) myLast->Label().EntryDump(anOS);
+  }
   anOS<<endl;
   return anOS;
 }
index 3a18f3343f2af0638677bcc03b2a211838509f73..545c3396c7cf7926b3ba4be1b03281bf4f2aecce 100644 (file)
@@ -308,7 +308,7 @@ TopAbs_ShapeEnum TNaming_Name::ShapeType() const
 }
 
 //=======================================================================
-//function : Append
+//function : Paste
 //purpose  : 
 //=======================================================================
 
@@ -317,7 +317,8 @@ void TNaming_Name::Paste (TNaming_Name& into,
 {
   into.myType      = myType;
   into.myShapeType = myShapeType;
-  into.myShape     = myShape; 
+  into.myShape     = myShape;
+  into.myIndex     = myIndex;
   into.myArgs.Clear();
 //  into.myOrientation = myOrientation;
   Handle(TNaming_NamedShape) NS;
index 466a2a9def80cc1ab64178b333b9f6750e257215..01291c5ee23cd092400de15c8a2d074d1508f8d2 100644 (file)
@@ -257,7 +257,7 @@ void TNaming_NamedShape::Clear()
 {
   if (Label().IsNull()) {
 #ifdef DEB
-    cout << "attention etat fantomatique" << endl;
+    //cout << "attention etat fantomatique" << endl;
 #endif
     return;
   }
@@ -666,7 +666,7 @@ void TNaming_Builder::Generated(const TopoDS_Shape& newShape)
   
   if (myShapes->myMap.IsBound(newShape)) {
 #ifdef DEB
-    cout <<"TNaming_Builder::Generate : the shape is already in the attribute"<<endl;
+    //cout <<"TNaming_Builder::Generate : the shape is already in the attribute"<<endl;
 #endif
     pns = myShapes->myMap.ChangeFind(newShape);
     if (pns->FirstUse()->myAtt  == myAtt.operator->()) {
@@ -707,7 +707,7 @@ void TNaming_Builder::Delete(const TopoDS_Shape& oldShape)
     pos = myShapes->myMap.ChangeFind(oldShape); 
   else {
 #ifdef DEB
-    cout <<"TNaming_Builder::Delete : the shape is not in the data"<<endl;
+    //cout <<"TNaming_Builder::Delete : the shape is not in the data"<<endl;
 #endif
     pos = new TNaming_RefShape(oldShape);  
     myShapes->myMap.Bind(oldShape, pos);
@@ -733,7 +733,7 @@ void TNaming_Builder::Generated(const TopoDS_Shape& oldShape,
 
   if (oldShape.IsSame(newShape)) {
 #ifdef DEB
-    cout <<"TNaming_Builder::Generate : oldShape IsSame newShape"<<endl;
+    //cout <<"TNaming_Builder::Generate : oldShape IsSame newShape"<<endl;
 #endif
     return;
   }
@@ -776,7 +776,7 @@ void TNaming_Builder::Modify(const TopoDS_Shape& oldShape,
 
   if (oldShape.IsSame(newShape)) {
 #ifdef DEB
-    cout <<"TNaming_Builder::Modify : oldShape IsSame newShape"<<endl;
+    //cout <<"TNaming_Builder::Modify : oldShape IsSame newShape"<<endl;
 #endif
     return;
   }
@@ -886,7 +886,7 @@ TNaming_Iterator::TNaming_Iterator(const TDF_Label&       Lab,
   else {
     myNode = 0L;
 #ifdef DEB
-    cout <<"TNaming_Iterator : No Shape for this label"<<endl;
+    //cout <<"TNaming_Iterator : No Shape for this label"<<endl;
 #endif
   }
 }
@@ -1458,7 +1458,7 @@ Standard_Boolean TNaming_Tool::HasLabel (const TDF_Label&    access,
     return (US->Map().IsBound(S));
   }
 #ifdef MDTV_DEB_HASL
-  cout << "##==> Sub-Shape has no Label!" <<endl;
+  //cout << "##==> Sub-Shape has no Label!" <<endl;
 #endif
   return Standard_False;
 }
index d2b922dc8bc5033b3d41f024635199f6097d8800..e76181b18012b9a503c074b2c0dd6c5255894bee 100644 (file)
@@ -108,5 +108,6 @@ void V3d_Viewer::SetDefaultLights()
   }
 
   SetLightOn (new V3d_DirectionalLight (this, V3d_Zneg, Quantity_NOC_WHITE, Standard_True));
-  SetLightOn (new V3d_AmbientLight (this));
+  // AGV 011014 : ambient already installed elsewhere
+  //SetLightOn (new V3d_AmbientLight (this));
 }
index ab03d7820a67562246148c4290abde98ffed4fd1..e2b3a3ca9429111a70b3b3532f31fe9e7fb9e45f 100644 (file)
@@ -974,7 +974,7 @@ void Visual3d_View::SetViewOrientation (const Visual3d_ViewOrientation& VO) {
             for (j = 0; j < 4; j++) {
              if (!CustomIsModified) CustomIsModified =
                MyCView.Orientation.ModelViewMatrix[i][j] != MyViewOrientation.MyModelViewMatrix->Value(i,j);
-            }
+              MyCView.Orientation.ModelViewMatrix[i][j] = MyViewOrientation.MyModelViewMatrix->Value(i,j);             }
         }
 
 #ifdef TRACE_TRSF
index e213b76aa60d332b3fc32457d64a47a7f851f215..24d32091e1cda97349e328645bfe979606cdc535 100644 (file)
@@ -193,7 +193,7 @@ const Handle(TopoDS_TShape)& VrmlData_IndexedFaceSet::TShape ()
               if (IndiceNormals(i, arrIndice) == 3) {
                 for (Standard_Integer j = 0; j < 3; j++) {
                   const gp_XYZ& aNormal = myNormals->Normal (arrIndice[j]);
-                  Standard_Integer anInd = arrNodes[j] * 3 + 1;
+                  Standard_Integer anInd = (mapNodeId(arrNodes[j]) - 1) * 3 + 1;
                   Normals->SetValue (anInd + 0, Standard_ShortReal (aNormal.X()));
                   Normals->SetValue (anInd + 1, Standard_ShortReal (aNormal.Y()));
                   Normals->SetValue (anInd + 2, Standard_ShortReal (aNormal.Z()));
index d195a1eb6e72921e4b1d3b022761feada15d2085..25daea5746b3f4bb64c4ef5b8a4eb9825bfdff19 100644 (file)
@@ -229,9 +229,9 @@ void VrmlData_ShapeConvert::Convert (const Standard_Boolean theExtractFaces,
                 TopLoc_Location aL;
 
                 Standard_Boolean found = Standard_False;
-                for(i = 1; ; i++) {
+                for(Standard_Integer j = 1; Standard_True; j++) {
                   
-                  BRep_Tool::PolygonOnTriangulation(aEdge, aPT, aT, aL, i);
+                  BRep_Tool::PolygonOnTriangulation(aEdge, aPT, aT, aL, j);
 
                   if(aPT.IsNull() || aT.IsNull()) break;