+++ /dev/null
-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.
#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)
//=======================================================================
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);
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);
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);
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,
if (aHPosition != LabelPosition_Left)
{
DrawExtension (thePresentation,
- anExtensionSize,
+ aDimensionAspect->ShortExtensionSize(),
aFirstArrowEnd,
aFirstExtensionDir,
THE_EMPTY_LABEL_STRING,
if (aHPosition != LabelPosition_Right)
{
DrawExtension (thePresentation,
- anExtensionSize,
+ aDimensionAspect->ShortExtensionSize(),
aSecondArrowEnd,
aSecondExtensionDir,
THE_EMPTY_LABEL_STRING,
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());
&& 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;
+ }
+
+}
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)
//! @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.
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();
gp_Pnt aFirstPnt (gp::Origin());
gp_Pnt aSecondPnt (gp::Origin());
- ComputeSidePoints (myCircle, GetPlane(), aFirstPnt, aSecondPnt);
+ ComputeSidePoints (myCircle, aFirstPnt, aSecondPnt);
DrawLinearDimension (thePresentation, theMode, aFirstPnt, aSecondPnt);
}
gp_Pnt aFirstPnt (gp::Origin());
gp_Pnt aSecondPnt (gp::Origin());
- ComputeSidePoints (myCircle, GetPlane(), aFirstPnt, aSecondPnt);
+ ComputeSidePoints (myCircle, aFirstPnt, aSecondPnt);
ComputeLinearFlyouts (theSelection, theEntityOwner, aFirstPnt, aSecondPnt);
}
//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);
}
//=======================================================================
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();
+}
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)
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);
#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>
#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>
#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)
: AIS_InteractiveObject(),
myCustomValue (0.0),
myIsValueCustom (Standard_False),
+ myLayoutMode (AIS_DLM_Automatic),
mySpecialSymbol (' '),
myDisplaySpecialSymbol (AIS_DSS_No),
myGeometryType (GeometryType_UndefShapes),
SetToUpdate();
}
+//=======================================================================
+//function : SetLayoutMode
+//purpose :
+//=======================================================================
+ void AIS_Dimension::SetLayoutMode (const AIS_DimensionLayoutMode theLayoutMode)
+ {
+ myLayoutMode = theLayoutMode;
+ }
+
//=======================================================================
//function : GetDisplayUnits
//purpose :
}
// 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();
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)
{
// 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
// 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);
}
// 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);
}
// 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);
}
theCircle = aMkCirc.Value()->Circ();
}
- gp_Vec aVec = gp_Vec (theCircle.Location(), aCurPos).Normalized();
aFirstPoint = ElCLib::Value (aFirstU, theCircle);
aLastPoint = ElCLib::Value (aLastU, theCircle);
}
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;
+ }
+}
#ifndef _AIS_Dimension_HeaderFile
#define _AIS_Dimension_HeaderFile
+#include <AIS_DimensionLayoutMode.hxx>
#include <AIS_DimensionSelectionMode.hxx>
#include <AIS_DimensionOwner.hxx>
#include <AIS_DisplaySpecialSymbol.hxx>
//! 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.
//! |flyout flyout|
//! | |
//! +-----------------------------------+
-//! attachement attachement
+//! attachment attachment
//! point point
//!
//! Angular dimensions:
//!
//! 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
//! 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.
//! 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.
//! @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.
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)
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
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.
}
}
- //! 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 );
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 );
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.
EntityOwner from SelectMgr,
TypeOfFacingModel from Aspect,
Array1OfPnt2d from TColgp,
- Transformation from Geom
+ Transformation from Geom,
+ SequenceOfShape from TopTools
is
-- 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;
#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()){
}
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)
{
Handle(AIS_InteractiveObject) anObj = DetectedCurrentObject();
if( !anObj.IsNull() && anObj != anIObj )
+ {
myAISDetectedSeq.Remove( i );
+ myAISDetectedShapes.Remove(i);
+ }
}
if(myLastinMain == anIObj)
#include <TColStd_ListIteratorOfListOfInteger.hxx>
#include <SelectMgr_Selection.hxx>
#include <SelectBasics_SensitiveEntity.hxx>
+#include <StdSelect_BRepOwner.hxx>
#ifdef IMP150501
#include <Visual3d_TransientManager.hxx>
//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
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
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;
}
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();
+}
//! @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;
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)
LocalStatus from AIS,
StatusOfPick from AIS,
StatusOfDetection from AIS,
- SequenceOfInteractive from AIS
+ SequenceOfInteractive from AIS,
+ SequenceOfShape from TopTools
is
myAISCurDetected : Integer from Standard;
-- This variables is used by following functions:
-- InitDetected(), MoreDetected(), NextDetected(), DetectedCurrentShape(), DetectedCurrentObject().
+ myAISDetectedShapes : SequenceOfShape from TopTools;
friends
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
if(myMainPM->IsDisplayed(aSelectable,Att->HilightMode()))
myMainPM->Erase(aSelectable,Att->HilightMode());
// myMainPM->Clear(aSelectable,Att->HilightMode());
- jobdone = Standard_True;
}
// if below intensity
else
{
Handle(AIS_InteractiveObject) anObj = DetectedCurrentObject();
if( !anObj.IsNull() && anObj != aSelectable )
+ {
myAISDetectedSeq.Remove( i );
+ myAISDetectedShapes.Remove( i );
+ }
}
Standard_Integer aHM = aSelectable->HasHilightMode() ? aSelectable->HilightMode() : 0;
//Nullify class members storing information about detected AIS objects.
myAISCurDetected = 0;
myAISDetectedSeq.Clear();
+ myAISDetectedShapes.Clear();
#endif
myCurDetected = 0;
myDetectedSeq.Clear();
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
}
}
}
}
if(EO.IsNull())
+ {
EO = new SelectMgr_EntityOwner(anIObj);
+ }
#ifndef OCC138
EO->State(1);
#endif
{
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;
}
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();
+}
//! 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);
//! 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.
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)
}
// insert the drawer in the BrepOwners for hilight...
- StdSelect::SetDrawerForBRepOwner(aSelection,myDrawer);
+ // StdSelect::SetDrawerForBRepOwner(aSelection,myDrawer);
}
Quantity_NameOfColor AIS_Shape::Color() const {
//
// 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.
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;
}
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);
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;
}
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);
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);
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);
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);
}
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();
}
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();
}
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();
}
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);
//
// 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;
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
}
//! 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;
--
-- 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.
---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,
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
---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;
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;
//
// 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.
#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;
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
}
}
-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,
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);
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);
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;
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.) {
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;
}
//=======================================================================
//=======================================================================
BRepFill_OffsetWire::BRepFill_OffsetWire()
-:myIsDone(Standard_False)
+ : myIsOpenResult(Standard_False),
+ myIsDone(Standard_False)
{
}
//=======================================================================
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);
}
//=======================================================================
//=======================================================================
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);
// 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);
}
{
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;
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())
{
{
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
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);
//********************************
// 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;
//---------------------------------------------------------------
// 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;
}
#ifdef DRAW
if ( AffichGeom) {
+ char name[256];
sprintf(name,"BISSEC_%d",NbBISSEC++);
DrawTrSurf::Set(name,Bisec.Value());
}
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.
}
}
-#ifdef DEB
+#ifdef DRAW
if (AffichEdge) {
cout << " End Construction of vertices on offsets"<<endl;
}
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));
}
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
#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 :
#ifdef DRAW
if ( AffichGeom && !OE.IsNull()) {
+ char name[256];
sprintf(name,"OFFSET_%d",++NbOFFSET);
DBRep::Set(name,OE);
}
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;
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
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);
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);
}
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 {
#ifdef DRAW
if (AffichGeom && !OE.IsNull()) {
+ char name[256];
sprintf(name,"OFFSET_%d",++NbOFFSET);
DBRep::Set(name,OE);
Standard_Real ii = 0;
}
}
-//=======================================================================
-//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
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;
// 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);
+ }
}
}
// 1) Preparation
Prepare();
- if (myStatus != GeomFill_PipeOk) {
+ if (myStatus != GeomFill_PipeOk ||
+ !mySection->NbLaw()) {
BRep_Builder B;
TopoDS_Shell Sh;
B.MakeShell(Sh);
//=======================================================================
Standard_Integer BRepFill_SectionLaw::NbLaw() const
{
+ if (myLaws.IsNull())
+ return 0;
return myLaws->Length();
}
// 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);
}
--
-- 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.
---Purpose:
uses
+ GeomAbs,
MAT2d,
MAT,
TCollection,
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
--- /dev/null
+-- 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;
+
+
--- /dev/null
+// 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);
+ }
+ }
+}
+
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
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;
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;
//=======================================================================
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);
}
//=======================================================================
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());
//=======================================================================
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;
}
//=======================================================================
//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;
}
//=======================================================================
//=======================================================================
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;
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;
}
// 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);
}
}
//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;
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
}
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
}
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();
+ //}
}
//=======================================================================
//=======================================================================
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;
//=======================================================================
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;
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;
}
//=============================================================================
//=============================================================================
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();
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)
//=======================================================================
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");
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());
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);
//=======================================================================
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;
//=======================================================================
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;
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();
}
// Encode the Regularities
BRepLib::EncodeRegularity(myShape);
-
+
}
{
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)));
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;
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);
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();
-
+
}
-
+
}
-
+
}
//=======================================================================
// 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();
}
}
}
TopLoc_Location loc;
TopoDS_Vertex v1f,v1l,v2f,v2l;
- GeomFill_SectionGenerator section;
Standard_Integer nbPnts = 21;
TColgp_Array2OfPnt points(1, nbPnts, 1, nbSects);
// 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 {
// 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);
B.Add(edge3, v2f);
B.Range(edge3, f2, l2);
if (uClosed) {
- couture = edge3;
+ couture = edge3;
}
}
else {
// 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);
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;
myShape = shell;
Done();
}
-
+
TopExp_Explorer ex(myShape,TopAbs_EDGE);
while (ex.More()) {
const TopoDS_Edge& CurE = TopoDS::Edge(ex.Current());
//=======================================================================
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;
// 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
// case of looping sections
if (j==jdeb && vClosed) {
- BS1 = BS;
+ BS1 = BS;
}
}
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;
-
+
}
//=======================================================================
//
// 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.
#include <BRepToIGES_BRShell.ixx>
#include <BRepToIGES_BRWire.hxx>
+#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepTools.hxx>
#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>
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;
// 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);
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()) {
}
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;
TrimmedSurf-> Init (ISurf, Flag, IOuter, Tab);
res = TrimmedSurf;
- if (IsReversed) myface.Reverse();
-
SetShapeResult ( start, res );
-
return res;
}
#include <gp_Trsf.hxx>
#include <gp_Trsf2d.hxx>
+#include <Geom_BSplineSurface.hxx>
#include <Geom_CartesianPoint.hxx>
#include <Geom_ConicalSurface.hxx>
#include <Geom_Curve.hxx>
#include <Precision.hxx>
+#include <ShapeAnalysis.hxx>
+
#include <TColStd_HSequenceOfTransient.hxx>
#include <TopoDS.hxx>
}
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))))) {
#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,
{
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)
{
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);
}
else {
Curve2d = Geom2dConvert::CurveToBSplineCurve(C2d);
- mylcu.Append(C2dBis);
+ //mylcu.Append(C2dBis);
+ Handle(Geom2d_Curve) aC2dBisBspl = Geom2dConvert::CurveToBSplineCurve(C2dBis);
+ mylcu.Append(aC2dBisBspl);
return Standard_True;
}
}
// 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();
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
#include <gp_GTrsf.hxx>
#include <gp_Mat.hxx>
#include <gp_Ax2.hxx>
+#include <gp_Sphere.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array2OfPnt.hxx>
#include <Geom_SphericalSurface.hxx>
#include <Geom_SurfaceOfRevolution.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
+#include <Geom_TrimmedCurve.hxx>
#include <Approx_SweepApproximation.hxx>
#include <AdvApprox_PrefAndRec.hxx>
#include <Precision.hxx>
#include <ElCLib.hxx>
+#include <ElSLib.hxx>
//=======================================================================
//class : GeomFill_Sweep_Eval
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;
#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>
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();
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;
--
-- 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.
-- Set of geometrys from Geom2d.
uses
-
+ GeomAbs,
MMgt,
gp,
Geom2d,
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);
--
-- 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.
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,
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
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;
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;
connexionMap : DataMapOfIntegerConnexion from MAT2d;
linkRefEqui : DataMapOfBiIntSequenceOfInteger from MAT2d;
linesLength : SequenceOfInteger from TColStd;
+ myJoinType : JoinType from GeomAbs;
+ myIsOpenResult : Boolean from Standard;
end Circuit;
//
// 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.
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;
}
//=============================================================================
// 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());
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 :
{
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. ) {
//--------------------------
// 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);
+ }
}
}
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()));
+ }
}
}
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();
}
-//=======================================================================
-//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;
- }
-}
--- /dev/null
+-- 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;
--- /dev/null
+// 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;
+}
+
--
-- 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.
uses
-
+ JoinType from GeomAbs,
Bisec from Bisector,
Side from MAT,
Bisector from MAT,
--- 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.
-- 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>
-- <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.
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>.
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
fields
theDirection : Real;
+ theJoinType : JoinType from GeomAbs;
theNumberOfBisectors : Integer;
theNumberOfPnts : Integer;
theNumberOfVecs : Integer;
//
// 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.
MAT2d_Tool2d::MAT2d_Tool2d()
{
theDirection = 1.;
+ theJoinType = GeomAbs_Arc; //default
theNumberOfBisectors = 0;
theNumberOfVecs = 0;
theNumberOfPnts = 0;
else theDirection = -1.;
}
+//=============================================================================
+//function : SetJoinType
+//purpose :
+//=============================================================================
+void MAT2d_Tool2d::SetJoinType(const GeomAbs_JoinType aJoinType)
+{
+ theJoinType = aJoinType;
+}
+
//=============================================================================
//function : NumberOfItems
//purpose :
//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);
}
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;
//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;
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;
//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();
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)) {
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));
}
}
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;
// 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
* 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) {
--- /dev/null
+// 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
+ }
+}
--- /dev/null
+// 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
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
* 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
//=======================================================================
NIS_DrawList::NIS_DrawList ()
+ : myIsCompiled(Standard_False)
{
#ifdef ARRAY_LISTS
myListID = 0;
//=======================================================================
NIS_DrawList::NIS_DrawList (const Handle_NIS_View& theView)
- : myView (theView)
+ : myView (theView),
+ myIsCompiled(Standard_False)
{
#ifdef ARRAY_LISTS
myListID = 0;
//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;
}
void NIS_DrawList::Call (const Standard_Integer theType)
{
- glCallList (GetListID (theType));
+ if (myIsCompiled)
+ glCallList (GetListID (theType));
}
//=======================================================================
* 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
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);
* 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.
NIS_DrawList (const NIS_DrawList& theOther);
// NIS_DrawList& operator = (const NIS_DrawList& theOther);
- private:
+ protected:
// ---------- PRIVATE FIELDS ----------
Handle_NIS_View myView;
Standard_Integer myListID[5];
#endif
Standard_Boolean myIsUpdated[5];
+ Standard_Boolean myIsCompiled;
NCollection_List<Handle_NIS_InteractiveObject> myDynHilighted;
};
#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
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];
}
//=======================================================================
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 :
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;
}
//=======================================================================
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) {
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);
//=======================================================================
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;
}
//=======================================================================
// 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);
{
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];
+ }
+}
#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
#include <NIS_DrawList.hxx>
#include <Bnd_B3f.hxx>
+#include <Quantity_Color.hxx>
#ifdef WNT
#pragma warning (push)
* 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:
/**
* 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.
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).
/**
* 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
* 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);
* 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.
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.
*/
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 ----------
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
//! 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 ----------
--- /dev/null
+// 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;
+}
+
--- /dev/null
+// 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
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()
//=======================================================================
NIS_InteractiveContext::NIS_InteractiveContext ()
- : myAllocator (new NIS_Allocator(1024*100)),
+ : myAllocator (new NIS_Allocator(aSizeAlloc)),
myLastObjectId (0),
myObjects (1000),
// myDrawers (101, myAllocator),
{
// 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;
+ }
}
//=======================================================================
{
// 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);
}
if (aDrawer.IsNull() == Standard_False)
aDrawer->myLists.Append(aDrawer->createDefaultList(theView));
}
+ if (myIsShareDrawList && NbObjects() > 0)
+ {
+ markAllDrawersUpdated( myDrawers );
+ }
}
}
}
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;
}
+ }
}
}
//=======================================================================
//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);
+ }
+ }
}
//=======================================================================
}
// Remove Drawers
myDrawers.Clear();
+ for (Standard_Integer anIter = 0; anIter < NIS_Drawer::Priority_LevelsNb; ++anIter)
+ {
+ myPriorities[anIter] = 0;
+ }
// Release memory
myAllocator->Reset();
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);
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;
void NIS_InteractiveContext::ProcessSelection
(const TColStd_PackedMapOfInteger& mapSel,
- const Standard_Boolean isMultiple)
+ const Standard_Boolean isModifierUsed)
{
//subtract non-selectable objects
TColStd_PackedMapOfInteger aMap;
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]);
}
}
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);
//=======================================================================
//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;
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)) {
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();
{
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);
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;
}
}
{
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) {
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);
}
}
// 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();
}
// 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()) {
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 :
}
}
}
+
+//=======================================================================
+//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;
+}
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
* <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
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
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
//@{
* 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);
/**
* 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);
/**
inline void SetShareDrawList (Standard_Boolean isShare)
{ myIsShareDrawList = isShare; }
+ /**
+ * Compresses the allocated memory.
+ */
+ Standard_EXPORT void CompactObjects();
+
//@}
// ====== END Selection API ================
//! 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
* @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.
Handle_NIS_Allocator
compactObjects ();
+ void detachView (NCollection_List<Handle_NIS_View>::Iterator&);
+
private:
// ---------- PRIVATE FIELDS ----------
*/
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.
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();
{
// 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)
(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;
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);
}
}
}
}
+
+//=======================================================================
+//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);
+}
* 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);
* {
* 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
* 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
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.
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 ----------
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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
* anIter.Next();
* }
* @endcode
+ * @ingroup nis_library
*/
class NIS_ObjectsIterator
--- /dev/null
+// 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
+}
--- /dev/null
+// 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
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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
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 :
return Standard_True;
}
-
class NIS_InteractiveObject;
class Handle_Standard_Type;
+class gp_Ax1;
/**
* Interface for selection filters. It can be used in NIS_InteractiveContext
* 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.
* 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.
protected:
// ---------- PROTECTED METHODS ----------
-
-
+ unsigned int myEventFlags;
public:
// Declaration of CASCADE RTTI
#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>
//=======================================================================
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();
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();
//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();
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
(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());
// 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++)
{
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);
}
//=======================================================================
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,
}
//=======================================================================
-//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);
}
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.
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);
}
}
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();
}
//=======================================================================
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);
}
//=======================================================================
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++) {
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 :
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) {
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;
}
}
} 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;
}
}
}
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) {
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)) {
}
}
} 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;
}
}
}
#define NIS_Surface_HeaderFile
#include <NIS_InteractiveObject.hxx>
+#include <NIS_IndexLists.hxx>
#include <NCollection_BaseAllocator.hxx>
#include <gp_XYZ.hxx>
* <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
};
/**
* 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);
/**
*/
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.
*/
/**
* 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.
/**
* 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));
}
/**
return &mypNormals[theIndex * 3];
}
+ /**
+ * Returns status of displayin of free boundaries
+ */
+ inline Standard_Boolean IsShowFreeBounds() const
+ {
+ return myIsShowFreeBoundary;
+ }
+
/**
* Create a default drawer instance.
*/
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.
*/
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.
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
* 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.
* 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.
* @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.
* 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:
* 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;
//! 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
#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)
(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;
}
//=======================================================================
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;
}
}
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] = {
};
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;
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);
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:
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);
}
{
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);
}
// 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));
}
//=======================================================================
//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]);
}
#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
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.
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.
*/
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;
--- /dev/null
+// 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 ()
+{
+}
--- /dev/null
+// 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
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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
--- /dev/null
+// 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();
+}
+
--- /dev/null
+// 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
#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)
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
: 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())
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
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,
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);
}
}
}
}
+//=======================================================================
+//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 :
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);
}
}
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);
}
}
}
}
+//=======================================================================
+//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 :
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);
}
//=======================================================================
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);
}
//=======================================================================
//=======================================================================
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);
}
//=======================================================================
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);
}
//=======================================================================
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);
}
//=======================================================================
}
//=======================================================================
-//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);
}
//=======================================================================
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;
}
}
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)
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;
}
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;
} 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),
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;
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;
}
}
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()) };
}
}
} 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()) };
}
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()) };
: 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
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],
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)
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;
}
}
}
return pResult;
}
+
#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
* 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
public:
/**
- * Enumerated type of polygon rendering.
+ * Enumerated type of polygon rendering
*/
enum PolygonType {
Polygon_Default = 0, //!< Polygon as LINE, Triangulation as FILL
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 ----------
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
(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
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
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
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
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
(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.
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],
*/
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.
*/
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 ----------
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
// commercial license or contractual agreement.
#include <NIS_TriangulatedDrawer.hxx>
-#include <NIS_InteractiveObject.hxx>
#include <NIS_Triangulated.hxx>
#ifdef _DEBUG
#include <Standard_ProgramError.hxx>
(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);
}
//=======================================================================
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;
}
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;
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:
#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);
}
glEnableClientState (GL_VERTEX_ARRAY);
glLineWidth (aLineWidth);
+ if (myLineType > 0)
+ {
+ glEnable(GL_LINE_STIPPLE);
+ glLineStipple(1, (GLushort)myLineType);
+ }
glShadeModel(GL_FLAT);
glDisable(GL_LIGHTING);
}
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);
+ }
}
//=======================================================================
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()) {
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));
}
}
}
-
}
-
/**
* Drawer for interactive object type NIS_Triangulated.
+ * @ingroup nis_library
*/
class NIS_TriangulatedDrawer : public NIS_Drawer
*/
Standard_Boolean myPolygonAsLineLoop;
- Quantity_Color myColor[5];
Standard_ShortReal myLineWidth;
+ Standard_Integer myLineType;
Standard_Boolean myIsDrawPolygons;
unsigned int myPolygonType;
// 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>
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()
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;
}
//=======================================================================
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;
}
// //=======================================================================
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);
}
}
}
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 :
}
}
+//=======================================================================
+//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);
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
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);
+ }
+ }
}
//=======================================================================
//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)
myDynHilighted = aSelected;
}
Redraw();
+ aResult = Standard_True;
}
+ return aResult;
}
//=======================================================================
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,
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();
}
//=======================================================================
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)
{
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();
}
//=======================================================================
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;
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);
}
//=======================================================================
//=======================================================================
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;
+}
#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;
/**
* </ul>
* The list of associated NIS_InteractiveContext can be modified by methods
* AddContext and RemoveContext.
+ * @ingroup nis_library
*/
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
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
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.
*/
/**
* 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);
/**
* 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);
* 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
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,
* 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
* 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
* 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
* @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.
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
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 ----------
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.
*/
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;
--- /dev/null
+// 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
--- /dev/null
+// 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 ()
+{
+}
--- /dev/null
+// 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
--- /dev/null
+// 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;
+}
+
--- /dev/null
+// 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
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>
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;
}
}
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;
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
*/
//! @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
}
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)
{
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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
--- /dev/null
+// 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;
+}
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.
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.
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;
}
//=======================================================================
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 :
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;
--
is redefined static private;
-
- Color(me:mutable; aColor: NameOfColor from Quantity)
- is static private;
BoundBox(me)
is static private;
fields
myStructure: Prs from PrsMgr;
- myDisplayReason: Boolean from Standard;
+ myDisplayForHighlight: Boolean from Standard;
myPresentableObject: PresentableObjectPointer from PrsMgr;
friends
class PresentationManager3d from PrsMgr,
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(),
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;
}
}
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() {
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();
}
-void PrsMgr_Presentation3d::Destroy () {
+void PrsMgr_Presentation3d::Destroy ()
+{
if (!myStructure.IsNull())
+ {
+ myStructure->Erase();
myStructure->Clear();
+ }
myStructure.Nullify();
}
else if(Presentation(aPresentableObject,aMode)->MustBeUpdated()){
Update(aPresentableObject,aMode);
}
- CastPresentation(aPresentableObject,aMode)->Color(aColor);
+ CastPresentation(aPresentableObject,aMode)->HighlightWithColor (aColor);
if(myImmediateMode)
Add(aPresentableObject,aMode);
#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;
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);
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
theFile.Close ();
return ReadMesh;
-
}
//=======================================================================
//function : ReadAscii
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();)
// 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"
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,
---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;
#include <Precision.hxx>
#include <ElCLib.hxx>
#include <CSLib_Class2d.hxx>
-
+#include <Extrema_ExtElC.hxx>
//==================================================
// Function: Creation
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);
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;
+}
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;
{return !myiniloc.IsIdentity();}
inline const TopLoc_Location& Select3D_SensitiveTriangulation::GetInitLocation() const
{return myiniloc;}
+
+inline Standard_Integer Select3D_SensitiveTriangulation::DetectedTriangle() const
+{
+ return myDetectedTr;
+}
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);
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);
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;
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;
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);
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);
}
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
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);
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)
//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);
+ }
}
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;
// 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);
}
else
myPrsSh = new StdSelect_Shape(myShape);
+
+ if (!myDrawer.IsNull())
+ myPrsSh->SetDrawer(myDrawer);
}
// highlight with color and set layer
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
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;
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;
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 ,
{
PrsMgr_PresentableObject::Compute(aProjector,aPresentation);
}
+
+void StdSelect_Shape::SetDrawer(const Handle(Prs3d_Drawer)& drawer)
+{
+ myDrawer = drawer;
+}
\ No newline at end of file
nbVertices++;
return nbVertices;
}
-
-
-
-
-
-
// 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;
}
}
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();
//purpose :
//=======================================================================
-inline Handle(TDataStd_TreeNode) TDataStd_ChildNodeIterator::Value() const
+inline const Handle(TDataStd_TreeNode)& TDataStd_ChildNodeIterator::Value() const
{
return myNode;
}
}
if (Father()->HasFirst()) {
- if (Handle(TDataStd_TreeNode)::DownCast(this) == Father()->First()) {
+ if (this == Father()->First().operator->()) {
if (HasNext()) {
Father()->SetFirst(Next());
}
}
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);
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;
}
}
//=======================================================================
-//function : Append
+//function : Paste
//purpose :
//=======================================================================
{
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;
{
if (Label().IsNull()) {
#ifdef DEB
- cout << "attention etat fantomatique" << endl;
+ //cout << "attention etat fantomatique" << endl;
#endif
return;
}
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->()) {
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);
if (oldShape.IsSame(newShape)) {
#ifdef DEB
- cout <<"TNaming_Builder::Generate : oldShape IsSame newShape"<<endl;
+ //cout <<"TNaming_Builder::Generate : oldShape IsSame newShape"<<endl;
#endif
return;
}
if (oldShape.IsSame(newShape)) {
#ifdef DEB
- cout <<"TNaming_Builder::Modify : oldShape IsSame newShape"<<endl;
+ //cout <<"TNaming_Builder::Modify : oldShape IsSame newShape"<<endl;
#endif
return;
}
else {
myNode = 0L;
#ifdef DEB
- cout <<"TNaming_Iterator : No Shape for this label"<<endl;
+ //cout <<"TNaming_Iterator : No Shape for this label"<<endl;
#endif
}
}
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;
}
}
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));
}
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
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()));
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;