Revision: 77222
http://sourceforge.net/p/brlcad/code/77222
Author: starseeker
Date: 2020-09-25 13:41:24 +0000 (Fri, 25 Sep 2020)
Log Message:
-----------
Merge analyze command rework from branch, add doc update and NEWS items.
Immediate functionality is to use geometric inside/outside testing to peform
boolean ops on point clouds and generate new point sets, but should be
implemented in such a way as to allow for expansion of additional capabilities.
Modified Paths:
--------------
brlcad/trunk/NEWS
brlcad/trunk/doc/docbook/system/mann/analyze.xml
brlcad/trunk/doc/docbook/system/mann/kill.xml
brlcad/trunk/src/libged/analyze/CMakeLists.txt
brlcad/trunk/src/libged/kill/kill.c
brlcad/trunk/src/libged/pnts_util.c
brlcad/trunk/src/libged/pnts_util.h
brlcad/trunk/src/libged/tests/CMakeLists.txt
Added Paths:
-----------
brlcad/trunk/src/libged/analyze/analyze.cpp
brlcad/trunk/src/libged/analyze/arb8.cpp
brlcad/trunk/src/libged/analyze/arbn.cpp
brlcad/trunk/src/libged/analyze/ars.cpp
brlcad/trunk/src/libged/analyze/ged_analyze.h
brlcad/trunk/src/libged/analyze/op_pnts_vol.cpp
brlcad/trunk/src/libged/analyze/sketch.cpp
brlcad/trunk/src/libged/analyze/superell.cpp
brlcad/trunk/src/libged/analyze/util.cpp
brlcad/trunk/src/libged/tests/pnts_in_out.g
Removed Paths:
-------------
brlcad/trunk/src/libged/analyze/analyze.c
Property Changed:
----------------
brlcad/trunk/
brlcad/trunk/src/libged/kill/kill.c
Index: brlcad/trunk
===================================================================
--- brlcad/trunk 2020-09-25 12:41:33 UTC (rev 77221)
+++ brlcad/trunk 2020-09-25 13:41:24 UTC (rev 77222)
Property changes on: brlcad/trunk
___________________________________________________________________
Modified: svn:mergeinfo
## -1,4 +1,5 ##
/brlcad/branches/RELEASE:57439,57447-57860,69901-69913,70323-70333,71915-72242,72525-72534,72826-72858,74376-74454,74964-75140,75372-75685,76001-76451,76693-76768,77107-77132,77145-77155
+/brlcad/branches/analyze_cmd:76836-77221
/brlcad/branches/bioh:75720-75736,75740-75742,75860-75891,75894-75986,76088-76153,76354-76506,76577
/brlcad/branches/brep-debug:61373,61375,61404,61427,61429,61470,61544,61567,61576,61999,62018,62094,62098,62107,62117,62406,62416-62519,62521-62584,62593-62614,62623,62658,62660-62674,62681-62771,62876,62901,62907,62910,62925,62928,62931-63025,63027,63051,63054-63056,63069,63071-63073,63122,63160-63161,63165,63171,63184,63187,63189-63190,63193-63196,63200,63202,63205-63210,63213,63219-63225,63232-63233,63236,63238,63338,63350-63353,63481,63618,63669,64173-64174,64176-64177,64229-64233,64242,64244,64360-64362,65165,65245,65249,65334,65833-65834,66370-66375,66931-66932,66934,67012-67015,67018-67019,67021-67022,67406,67740,67746-67748,67950,67952,68144-68145,68636,68640-68643,68820,69081,69109,69168,69206,69289,69346,69460-69461,69582-69583,69719-69721,69857-69859,69927,69995-69996,70148-70149,70347-70349,70377,70526-70527,71006-71007,71009-71022,71046-71047,71049,71096-71100
/brlcad/branches/bullet:62518
Modified: brlcad/trunk/NEWS
===================================================================
--- brlcad/trunk/NEWS 2020-09-25 12:41:33 UTC (rev 77221)
+++ brlcad/trunk/NEWS 2020-09-25 13:41:24 UTC (rev 77222)
@@ -13,6 +13,10 @@
--- 2020-xx-xx Release 7.32.2 ---
----------------------------------------------------------------------
+* added subtract subcommand to MGED analyze command - Cliff Yapp
+* added intersect subcommand to MGED analyze command - Cliff Yapp
+* added summarize subcommand to MGED analyze command - Cliff Yapp
+* added quiet (-q) flag to MGED kill command - Cliff Yapp
* added MGED stat command for reporting of object info - Cliff Yapp
* corrected examples in gdiff man page - Cliff Yapp
* fixed help message for -F option on gdiff command - Cliff Yapp
Modified: brlcad/trunk/doc/docbook/system/mann/analyze.xml
===================================================================
--- brlcad/trunk/doc/docbook/system/mann/analyze.xml 2020-09-25 12:41:33 UTC
(rev 77221)
+++ brlcad/trunk/doc/docbook/system/mann/analyze.xml 2020-09-25 13:41:24 UTC
(rev 77222)
@@ -10,9 +10,7 @@
<refnamediv xml:id="name">
<refname>analyze</refname>
<refpurpose>
- Displays the rotation and fallback angles, surface area, and
- plane equation for each face of the ARB specified on the command line.
The total
- surface area, volume, and the length of each edge are also displayed.
+ Report and/or compute analytical information about the listed objects.
</refpurpose>
</refnamediv>
@@ -20,39 +18,243 @@
<refsynopsisdiv xml:id="synopsis">
<cmdsynopsis sepchar=" ">
<command>analyze</command>
- <arg choice="req"
rep="norepeat"><replaceable>arb_name</replaceable></arg>
+ <arg choice="opt" rep="repeat"><replaceable>options</replaceable></arg>
+ <arg choice="opt"
rep="norepeat"><replaceable>subcommand</replaceable></arg>
</cmdsynopsis>
+ <variablelist>
+
+ <varlistentry><term></term><listitem>
+ <cmdsynopsis sepchar=" ">
+ <command>summarize</command>
+ <arg choice="req" rep="repeat">obj</arg>
+ </cmdsynopsis>
+ </listitem></varlistentry>
+
+ <varlistentry><term></term><listitem>
+ <cmdsynopsis sepchar=" ">
+ <command>intersect</command>
+ <arg choice="opt" rep="repeat"><replaceable>options</replaceable></arg>
+ <arg choice="req" rep="repeat">obj1 obj2 [...]</arg>
+ </cmdsynopsis>
+ </listitem></varlistentry>
+
+ <varlistentry><term></term><listitem>
+ <cmdsynopsis sepchar=" ">
+ <command>subtract</command>
+ <arg choice="opt" rep="repeat"><replaceable>options</replaceable></arg>
+ <arg choice="req" rep="repeat">obj1 obj2 [...]</arg>
+ </cmdsynopsis>
+ </listitem></varlistentry>
+ </variablelist>
</refsynopsisdiv>
<refsection xml:id="description"><title>DESCRIPTION</title>
<para>
- The <command>analyze</command> command displays the rotation and fallback
- angles, surface area, and plane equation for each face of the ARB
specified
- on the command line. The total surface area, volume, and the length of
each
- edge are also displayed. If executed while editing an ARB, the arb_name
may
- be omitted, and the ARB being edited will be analyzed.
+ The <command>analyze</command> command provides an array of reporting and
+ shape generation capabilities. The classic behavior (and the behavior
users
+ will see if calling without specifying a subcommand) is a report
summarizing
+ geometric information about the specified solid(s). This behavior may
also
+ be explicitly invoked by the <command>summarize</command> subcommand.
</para>
+
+ <para>
+ The <command>intersect</command> will take the first object specified and
+ intersect it with any subsequently specified objects - in effect,
building
+ up a new object with the geoemtry common to all objects specified.
+ </para>
+
+ <para>
+ The <command>subtract</command> will take the first object specified and
+ subtract from it any subsequently specified objects.
+ </para>
+
</refsection>
<refsection xml:id="examples"><title>EXAMPLES</title>
- <para>
- The example shows how to display information about an ARB's rotation and
- fallback angles, surface area, and plane equation for its face.
- Edge information is also displayed.
- </para>
<example><title>Analyze a particular <emphasis>ARB</emphasis></title>
+ <para>
+ <prompt>mged></prompt> <userinput>analyze box.s</userinput>
+ </para>
+ <literallayout>
+box.s: ARB8
+ 1 (30.0283, -5.21153, -16.3791)
+ 2 (30.0283, 21.5812, -16.3791)
+ 3 (30.0283, 21.5812, 10.4137)
+ 4 (30.0283, -5.21153, 10.4137)
+ 5 (3.23558, -5.21153, -16.3791)
+ 6 (3.23558, 21.5812, -16.3791)
+ 7 (3.23558, 21.5812, 10.4137)
+ 8 (3.23558, -5.21153, 10.4137)
++------+---------------------------+-------------------------------------------------+--------------+
+| FACE | ROT FB | PLANE EQUATION
| SURFACE AREA |
++------+---------------------------+-------------------------------------------------+--------------+
+| 1234 | 0.00000000 0.00000000 | 1.00000000 0.00000000 0.00000000
30.02833557 | 717.85172729 |
+| 5678 | 180.00000000 -0.00000000 | -1.00000000 -0.00000000 -0.00000000
-3.23558044 | 717.85172729 |
+| 1584 | 270.00000000 -0.00000000 | -0.00000000 -1.00000000 -0.00000000
5.21152973 | 717.85172729 |
+| 2376 | 90.00000000 -0.00000000 | -0.00000000 1.00000000 -0.00000000
21.58122540 | 717.85172729 |
+| 1265 | 0.00000000 -90.00000000 | -0.00000000 0.00000000 -1.00000000
16.37908936 | 717.85172729 |
+| 4378 | 0.00000000 90.00000000 | 0.00000000 -0.00000000 1.00000000
10.41366577 | 717.85172729 |
++------+---------------------------+-------------------------------------------------+--------------+
+
+
+--------------------+--------------------+--------------------+--------------------+
+ | EDGE LENGTH | EDGE LENGTH | EDGE LENGTH | EDGE
LENGTH |
+
+--------------------+--------------------+--------------------+--------------------+
+ | 12 26.79275513 | 23 26.79275513 | 34 26.79275513 | 14
26.79275513 |
+ | 15 26.79275513 | 56 26.79275513 | 26 26.79275513 | 67
26.79275513 |
+ | 78 26.79275513 | 58 26.79275513 | 48 26.79275513 | 37
26.79275513 |
+
+--------------------+--------------------+--------------------+--------------------+
+
+ +-------------------------------+
+ | Volume = 19233.22554681 |
+ | Surface Area = 4307.11036376 |
+ | Gallons = 0.00508088 |
+ +-------------------------------+
+ </literallayout>
+ </example>
+
+ <example><title>Analyze a particular <emphasis>TOR</emphasis></title>
<para>
- <prompt>mged></prompt> <userinput>analyze arb_name</userinput>
+ <prompt>mged></prompt> <userinput>analyze tor</userinput>
</para>
+ <literallayout>
+tor: torus (TOR)
+ V (4.91624, -32.8022, 31.7118), r1=25.4 (A), r2=5.08 (H)
+ N=(0, 1, 0)
+ A=(0, -0, 1)
+ B=(1, 0, -0)
+ vector to inner edge = (0, -0, 20.32)
+ vector to outer edge = (0, -0, 30.48)
+
+ Centroid: (4.91624, -32.8022, 31.7118)
+
+ +-------------------------------+
+ | Volume = 12938.70529707 |
+ | Surface Area = 5093.97853992 |
+ | Gallons = 0.00341804 |
+ +-------------------------------+
+ </literallayout>
+ </example>
+
+ <example><title>Points inside a sphere</title>
+
<para>
- Rotation and fallback angles, surface area, and plane equation for
- each face of the ARB specified on the command line are displayed along
- with edge information.
+ <prompt>mged></prompt> <userinput>l sph.s</userinput>
</para>
+ <literallayout>
+sph.s: ellipsoid (ELL)
+ V (0, 0, 0)
+ A (10, 0, 0) mag=10
+ B (0, 10, 0) mag=10
+ C (0, 0, 10) mag=10
+ A direction cosines=(0, 90, 90)
+ A rotation angle=0, fallback angle=0
+ B direction cosines=(90, 0, 90)
+ B rotation angle=90, fallback angle=0
+ C direction cosines=(90, 90, 0)
+ C rotation angle=0, fallback angle=90
+ </literallayout>
+
+ <para>
+ <prompt>mged></prompt> <userinput>l pnts.s</userinput>
+ </para>
+ <literallayout>
+pnts.s: Point Cloud (PNTS)
+Total number of points: 6
+Default scale: 0.000000
+point#, (point)
+1, (2.000000 2.000000 2.000000)
+2, (0.000000 0.000000 -5.000000)
+3, (0.000000 0.000000 10.000000)
+4, (0.000000 0.000000 20.000000)
+5, (10.000000 0.000000 10.000000)
+6, (0.000000 10.000000 20.000000)
+ </literallayout>
+
+ <para>
+ <prompt>mged></prompt> <userinput>analyze intersect -o inside.s
pnts.s sph.s</userinput>
+ </para>
+ <literallayout>
+3
+ </literallayout>
+
+ <para>
+ <prompt>mged></prompt> <userinput>l inside.s</userinput>
+ </para>
+ <literallayout>
+inside.s: Point Cloud (PNTS)
+Total number of points: 3
+Default scale: 0.000000
+point#, (point)
+1, (0.000000 0.000000 10.000000)
+2, (0.000000 0.000000 -5.000000)
+3, (2.000000 2.000000 2.000000)
+ </literallayout>
+
</example>
+
+
+ <example><title>Points outside a sphere</title>
+
+ <para>
+ <prompt>mged></prompt> <userinput>l sph.s</userinput>
+ </para>
+ <literallayout>
+sph.s: ellipsoid (ELL)
+ V (0, 0, 0)
+ A (10, 0, 0) mag=10
+ B (0, 10, 0) mag=10
+ C (0, 0, 10) mag=10
+ A direction cosines=(0, 90, 90)
+ A rotation angle=0, fallback angle=0
+ B direction cosines=(90, 0, 90)
+ B rotation angle=90, fallback angle=0
+ C direction cosines=(90, 90, 0)
+ C rotation angle=0, fallback angle=90
+ </literallayout>
+
+ <para>
+ <prompt>mged></prompt> <userinput>l pnts.s</userinput>
+ </para>
+ <literallayout>
+pnts.s: Point Cloud (PNTS)
+Total number of points: 6
+Default scale: 0.000000
+point#, (point)
+1, (2.000000 2.000000 2.000000)
+2, (0.000000 0.000000 -5.000000)
+3, (0.000000 0.000000 10.000000)
+4, (0.000000 0.000000 20.000000)
+5, (10.000000 0.000000 10.000000)
+6, (0.000000 10.000000 20.000000)
+ </literallayout>
+
+ <para>
+ <prompt>mged></prompt> <userinput>analyze subtract -o outside.s
pnts.s sph</userinput>
+ </para>
+ <literallayout>
+3
+ </literallayout>
+
+ <para>
+ <prompt>mged></prompt> <userinput>l outside.s</userinput>
+ </para>
+ <literallayout>
+outside.s: Point Cloud (PNTS)
+Total number of points: 3
+Default scale: 0.000000
+point#, (point)
+1, (0.000000 10.000000 20.000000)
+2, (10.000000 0.000000 10.000000)
+3, (0.000000 0.000000 20.000000)
+ </literallayout>
+
+
+ </example>
+
+
</refsection>
<refsection xml:id="author"><title>AUTHOR</title>
Modified: brlcad/trunk/doc/docbook/system/mann/kill.xml
===================================================================
--- brlcad/trunk/doc/docbook/system/mann/kill.xml 2020-09-25 12:41:33 UTC
(rev 77221)
+++ brlcad/trunk/doc/docbook/system/mann/kill.xml 2020-09-25 13:41:24 UTC
(rev 77222)
@@ -1,61 +1,79 @@
<refentry xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="kill">
-<refmeta>
- <refentrytitle>KILL</refentrytitle>
- <manvolnum>nged</manvolnum>
- <refmiscinfo class="source">BRL-CAD</refmiscinfo>
- <refmiscinfo class="manual">BRL-CAD User Commands</refmiscinfo>
-</refmeta>
+ <refmeta>
+ <refentrytitle>KILL</refentrytitle>
+ <manvolnum>nged</manvolnum>
+ <refmiscinfo class="source">BRL-CAD</refmiscinfo>
+ <refmiscinfo class="manual">BRL-CAD User Commands</refmiscinfo>
+ </refmeta>
-<refnamediv xml:id="name">
- <refname>kill</refname>
- <refpurpose>Deletes specified <emphasis>objects</emphasis> from the current
database.
- </refpurpose>
-</refnamediv>
+ <refnamediv xml:id="name">
+ <refname>kill</refname>
+ <refpurpose>Deletes specified <emphasis>objects</emphasis> from the
current database.
+ </refpurpose>
+ </refnamediv>
-<!-- body begins here -->
-<refsynopsisdiv xml:id="synopsis">
- <cmdsynopsis sepchar=" ">
- <command>kill</command>
- <arg choice="opt" rep="norepeat">-f</arg>
- <arg choice="req" rep="norepeat"><replaceable>objects</replaceable></arg>
- </cmdsynopsis>
-</refsynopsisdiv>
+ <!-- body begins here -->
+ <refsynopsisdiv xml:id="synopsis">
+ <cmdsynopsis sepchar=" ">
+ <command>kill</command>
+ <arg choice="opt" rep="norepeat">-f</arg>
+ <arg choice="req" rep="norepeat"><replaceable>objects</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
-<refsection xml:id="description"><title>DESCRIPTION</title>
+ <refsection xml:id="description"><title>DESCRIPTION</title>
<para>
- Deletes the specified <emphasis>objects</emphasis> from the current
database.
- This command affects only the <emphasis>objects</emphasis> actually
listed on the command line. If a combination is killed, its members are
not affected. If the <emphasis>-f </emphasis>option is specified, then kill
will not complain if some, or all, of the <emphasis>objects</emphasis>
specified do not actually exist in the database. Note that the
<emphasis>objects</emphasis> are killed immediately. There is no need for a
<command> write file</command> command in MGED, and there is no
<command>undo</command> command. <emphasis remap="B" role="bold">Use this
command with caution.</emphasis> Other commands that remove objects from
the database are <command>killall</command> and <command>killtree
</command>.
+ Deletes the specified <emphasis>objects</emphasis> from the current
database. This command
+ affects only the <emphasis>objects</emphasis> actually listed on the
command line. If a
+ combination is killed, its members are not affected. If the
<emphasis>-f</emphasis>option
+ is specified, then kill will not complain if some, or all, of the
<emphasis>objects</emphasis>
+ specified do not actually exist in the database. Note that the
<emphasis>objects</emphasis>
+ are killed immediately. There is no need for a <command>write
file</command> command in MGED,
+ and there is no <command>undo</command> command. <emphasis remap="B"
role="bold">Use this
+ command with caution.</emphasis> Other commands that remove objects from
the database are
+ <command>killall</command> and <command>killtree</command>.
</para>
-</refsection>
+ <para>
+ The <option>-q</option> option may be added to suppress database object
lookup messages
+ reporting failure, which will otherwise let the user know an invalid
object was specified.
+ </para>
+ </refsection>
-<refsection xml:id="examples"><title>EXAMPLES</title>
-
- <para>The example shows the use of the <command>kill</command> command to
delete specified objects from the database.
+ <refsection xml:id="examples"><title>EXAMPLES</title>
+ <para>
+ The example shows the use of the <command>kill</command> command to delete
specified objects
+ from the database.
</para>
<example><title>Delete objects from the database.</title>
- <variablelist>
- <varlistentry>
- <term><prompt>mged></prompt> <userinput>kill group1 region2
shapeb</userinput></term>
- <listitem>
- <para>Deletes <emphasis>group1, region2</emphasis>, and
<emphasis>shapeb</emphasis> from the database.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
+ <variablelist>
+ <varlistentry>
+ <term><prompt>mged></prompt> <userinput>kill group1 region2
shapeb</userinput></term>
+ <listitem>
+ <para>
+ Deletes <emphasis>group1, region2</emphasis>, and
<emphasis>shapeb</emphasis> from
+ the database.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
</example>
-</refsection>
+ </refsection>
-<refsection xml:id="author"><title>AUTHOR</title><para>BRL-CAD
Team</para></refsection>
+ <refsection xml:id="author"><title>AUTHOR</title>
+ <para>
+ BRL-CAD Team
+ </para>
+ </refsection>
-<refsection xml:id="bug_reports"><title>BUG REPORTS</title>
+ <refsection xml:id="bug_reports"><title>BUG REPORTS</title>
<para>
Reports of bugs or problems should be submitted via electronic
mail to <email>[email protected]</email>
</para>
-</refsection>
+ </refsection>
</refentry>
Modified: brlcad/trunk/src/libged/analyze/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/libged/analyze/CMakeLists.txt 2020-09-25 12:41:33 UTC
(rev 77221)
+++ brlcad/trunk/src/libged/analyze/CMakeLists.txt 2020-09-25 13:41:24 UTC
(rev 77222)
@@ -6,9 +6,20 @@
${GED_INCLUDE_DIRS}
)
+set(analyze_srcs
+ analyze.cpp
+ arb8.cpp
+ arbn.cpp
+ ars.cpp
+ superell.cpp
+ sketch.cpp
+ util.cpp
+ op_pnts_vol.cpp
+ )
+
add_definitions(-DGED_PLUGIN)
-ged_plugin_library(ged-analyze SHARED analyze.c)
-target_link_libraries(ged-analyze libged libbu)
+ged_plugin_library(ged-analyze SHARED ${analyze_srcs})
+target_link_libraries(ged-analyze libged libanalyze libbu)
set_property(TARGET ged-analyze APPEND PROPERTY COMPILE_DEFINITIONS
BRLCADBUILD HAVE_CONFIG_H)
VALIDATE_STYLE(ged-analyze analyze.c)
PLUGIN_SETUP(ged-analyze ged)
@@ -15,7 +26,8 @@
CMAKEFILES(
CMakeLists.txt
- analyze.c
+ ${analyze_srcs}
+ ged_analyze.h
)
# Local Variables:
Deleted: brlcad/trunk/src/libged/analyze/analyze.c
===================================================================
--- brlcad/trunk/src/libged/analyze/analyze.c 2020-09-25 12:41:33 UTC (rev
77221)
+++ brlcad/trunk/src/libged/analyze/analyze.c 2020-09-25 13:41:24 UTC (rev
77222)
@@ -1,1341 +0,0 @@
-/* A N A L Y Z E . C
- * BRL-CAD
- *
- * Copyright (c) 1985-2020 United States Government as represented by
- * the U.S. Army Research Laboratory.
- *
- * This program 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.
- *
- * This program 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 file; see the file named COPYING for more
- * information.
- */
-/** @file libged/analyze.c
- *
- * The analyze command.
- *
- */
-
-#include "common.h"
-
-#include <math.h>
-#include <string.h>
-#include <assert.h>
-
-#include "vmath.h"
-#include "bn.h"
-#include "bg/polygon.h"
-#include "rt/arb_edit.h"
-#include "raytrace.h"
-#include "rt/geom.h"
-
-#include "../ged_private.h"
-
-/**
- * TODO: primitives that still need implementing
- * ehy
- * metaball
- * nmg
- */
-
-/* Conversion factor for Gallons to cubic millimeters */
-#define GALLONS_TO_MM3 3785411.784
-
-
-/* ARB face printout array */
-static const int prface[5][6] = {
- {123, 124, 234, 134, -111, -111}, /* ARB4 */
- {1234, 125, 235, 345, 145, -111}, /* ARB5 */
- {1234, 2365, 1564, 512, 634, -111}, /* ARB6 */
- {1234, 567, 145, 2376, 1265, 4375}, /* ARB7 */
- {1234, 5678, 1584, 2376, 1265, 4378}, /* ARB8 */
-};
-
-
-/* edge definition array */
-static const int nedge[5][24] = {
- {0, 1, 1, 2, 2, 0, 0, 3, 3, 2, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1}, /* ARB4 */
- {0, 1, 1, 2, 2, 3, 0, 3, 0, 4, 1, 4, 2, 4, 3, 4, -1, -1, -1, -1, -1, -1,
-1, -1}, /* ARB5 */
- {0, 1, 1, 2, 2, 3, 0, 3, 0, 4, 1, 4, 2, 5, 3, 5, 4, 5, -1, -1, -1, -1, -1,
-1}, /* ARB6 */
- {0, 1, 1, 2, 2, 3, 0, 3, 0, 4, 3, 4, 1, 5, 2, 6, 4, 5, 5, 6, 4, 6, -1,
-1}, /* ARB7 */
- {0, 1, 1, 2, 2, 3, 0, 3, 0, 4, 4, 5, 1, 5, 5, 6, 6, 7, 4, 7, 3, 7, 2, 6},
/* ARB8 */
-};
-
-
-/* contains information used to analyze a polygonal face */
-struct poly_face
-{
- char label[5];
- size_t npts;
- point_t *pts;
- plane_t plane_eqn;
- fastf_t area;
-};
-
-
-#define POLY_FACE_INIT_ZERO { { 0, 0, 0, 0, 0 }, 0, NULL, HINIT_ZERO, 0.0 }
-
-#define ADD_PT(face, pt) do { VMOVE((face).pts[(face).npts], (pt));
(face).npts++; } while (0)
-
-/* structures and subroutines for analyze pretty printing */
-
-#define FBUFSIZ 100
-#define NFIELDS 9
-#define NOT_A_PLANE -1
-typedef struct row_field
-{
- int nchars;
- char buf[FBUFSIZ];
-} field_t;
-
-typedef struct table_row
-{
- int nfields;
- field_t fields[NFIELDS];
-} row_t;
-
-typedef struct table
-{
- int nrows;
- row_t *rows;
-} table_t;
-
-void get_dashes(field_t *f, const int ndashes)
-{
- int i;
- f->buf[0] = '\0';
- for (i = 0; i < ndashes; ++i) {
- bu_strlcat(f->buf, "-", FBUFSIZ);
- }
- f->nchars = ndashes;
-}
-
-
-void print_volume_table(struct ged *gedp
- , const fastf_t tot_vol
- , const fastf_t tot_area
- , const fastf_t tot_gallons
- )
-{
-
-/* table format
-
- +------------------------------------+
- | Volume = 7999999999.99999905 |
- | Surface Area = 24000000.00000000 |
- | Gallons = 2113.37641887 |
- +------------------------------------+
-
-*/
- /* track actual table column widths */
- /* this table has 1 column (plus a name column) */
- int maxwidth[2] = {0, 0};
- field_t dashes;
- char* fnames[3] = {"Volume",
- "Surface Area",
- "Gallons"};
- int indent = 4; /* number spaces to indent the table */
- int table_width_chars;
- table_t table;
- int i, nd, field;
-
- table.nrows = 3;
- table.rows = (row_t *)bu_calloc(3, sizeof(row_t), "print_volume_table:
rows");
- for (i = 0; i < table.nrows; ++i) {
- fastf_t val = 0.0;
-
- /* field 0 */
- field = 0;
- table.rows[i].fields[0].nchars =
snprintf(table.rows[i].fields[field].buf, FBUFSIZ, "%s",
- fnames[i]);
- if (maxwidth[field] < table.rows[i].fields[field].nchars)
- maxwidth[field] = table.rows[i].fields[field].nchars;
-
- if (i == 0) {
- val = tot_vol;
- } else if (i == 1) {
- val = tot_area;
- } else if (i == 2) {
- val = tot_gallons;
- }
-
- /* field 1 */
- field = 1;
- if (val < 0) {
- table.rows[i].fields[1].nchars =
snprintf(table.rows[i].fields[field].buf, FBUFSIZ, "COULD NOT DETERMINE");
- } else {
- table.rows[i].fields[1].nchars =
snprintf(table.rows[i].fields[field].buf, FBUFSIZ, "%10.8f", val);
- }
- if (maxwidth[field] < table.rows[i].fields[field].nchars)
- maxwidth[field] = table.rows[i].fields[field].nchars;
- }
-
- /* get total table width */
- table_width_chars = maxwidth[0] + maxwidth[1];
- table_width_chars += 2 + 2; /* 2 chars at each end of a row */
- table_width_chars += 3; /* ' = ' between the two fields of a row */
-
- /* newline following previous table */
- bu_vls_printf(gedp->ged_result_str, "\n");
-
- /* header row 1 */
- nd = table_width_chars - 4;
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%-*.*s+-%-*.*s-+\n",
- indent, indent, " ",
- nd, nd, dashes.buf);
-
- /* the three data rows */
- for (i = 0; i < table.nrows; ++i) {
- bu_vls_printf(gedp->ged_result_str, "%-*.*s| %-*.*s = %*.*s |\n",
- indent, indent, " ",
- maxwidth[0], maxwidth[0], table.rows[i].fields[0].buf,
- maxwidth[1], maxwidth[1], table.rows[i].fields[1].buf);
- }
-
- /* closing table row */
- bu_vls_printf(gedp->ged_result_str, "%-*.*s+-%-*.*s-+\n",
- indent, indent, " ",
- nd, nd, dashes.buf);
- bu_free((char *)table.rows, "print_volume_table: rows");
-}
-
-
-void print_edges_table(struct ged *gedp, table_t *table)
-{
-
-/* table header
-
-
+--------------------+--------------------+--------------------+--------------------+
- | EDGE LEN | EDGE LEN | EDGE LEN | EDGE
LEN |
-
+--------------------+--------------------+--------------------+--------------------+
-
-*/
-
- int i;
- int tcol, nd, nrow, nrows;
- int maxwidth[] = {0, 0, 0,
- 0, 0, 0,
- 0, 0};
- int indent = 2;
- field_t dashes;
- char EDGE[] = {"EDGE"};
- int elen = strlen(EDGE);
- char LEN[] = {"LENGTH"};
- int llen = strlen(LEN);
- char buf[FBUFSIZ];
-
- /* put four edges per row making 8 columns */
- /* this table has 8 columns per row: 2 columns per edge; 4 edges per row */
-
- /* collect max table column widths */
- tcol = 0;
- for (i = 0; i < table->nrows; ++i) {
- /* field 0 */
- int field = 0;
- if (maxwidth[tcol] < table->rows[i].fields[field].nchars)
- maxwidth[tcol] = table->rows[i].fields[field].nchars;
- if (maxwidth[tcol] < elen)
- maxwidth[tcol] = elen;
-
- /* field 1 */
- field = 1;
- if (maxwidth[tcol+1] < table->rows[i].fields[field].nchars)
- maxwidth[tcol+1] = table->rows[i].fields[field].nchars;
- if (maxwidth[tcol] < llen)
- maxwidth[tcol] = llen;
-
- /* iterate on columns */
- tcol += 2;
- tcol = tcol > 6 ? 0 : tcol;
- }
-
- /* header row 1 */
- /* print dashes in 4 sets */
- nd = maxwidth[0] + maxwidth[1] + 3; /* 1 space between numbers and one at
each end */
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%-*.*s+%-*.*s",
- indent, indent, " ",
- nd, nd, dashes.buf);
- nd = maxwidth[2] + maxwidth[3] + 3; /* 1 space between numbers and one at
each end */
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "+%-*.*s",
- nd, nd, dashes.buf);
- nd = maxwidth[4] + maxwidth[5] + 3; /* 1 space between numbers and one at
each end */
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "+%-*.*s",
- nd, nd, dashes.buf);
- nd = maxwidth[6] + maxwidth[7] + 3; /* 1 space between numbers and one at
each end */
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "+%-*.*s+\n",
- nd, nd, dashes.buf);
-
- /* header row 2 */
- /* print titles in 4 sets */
-
- /* bu_vls_printf can't handle this at the moment */
- bu_vls_printf(gedp->ged_result_str, "%-*.*s| %-*.*s %*.*s ",
- indent, indent, " ",
- maxwidth[0], maxwidth[0], EDGE,
- maxwidth[1], maxwidth[1], LEN);
- bu_vls_printf(gedp->ged_result_str, "| %-*.*s %*.*s ",
- maxwidth[2], maxwidth[2], EDGE,
- maxwidth[3], maxwidth[3], LEN);
- bu_vls_printf(gedp->ged_result_str, "| %-*.*s %*.*s ",
- maxwidth[4], maxwidth[4], EDGE,
- maxwidth[5], maxwidth[5], LEN);
- bu_vls_printf(gedp->ged_result_str, "| %-*.*s %*.*s |\n",
- maxwidth[6], maxwidth[6], EDGE,
- maxwidth[7], maxwidth[7], LEN);
-
- /* header row 3 */
- /* print dashes in 4 sets */
- nd = maxwidth[0] + maxwidth[1] + 3; /* 1 space between numbers and one at
each end */
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%-*.*s+%-*.*s",
- indent, indent, " ",
- nd, nd, dashes.buf);
- nd = maxwidth[2] + maxwidth[3] + 3; /* 1 space between numbers and one at
each end */
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "+%-*.*s",
- nd, nd, dashes.buf);
- nd = maxwidth[4] + maxwidth[5] + 3; /* 1 space between numbers and one at
each end */
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "+%-*.*s",
- nd, nd, dashes.buf);
- nd = maxwidth[6] + maxwidth[7] + 3; /* 1 space between numbers and one at
each end */
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "+%-*.*s+\n",
- nd, nd, dashes.buf);
-
- /* print the data lines */
- /* collect max table column widths */
- tcol = 0;
- nrow = 0;
- for (i = 0; i < table->nrows; ++i) {
- int field;
-
- if (tcol == 0) {
- /* need to start a row */
- snprintf(buf, FBUFSIZ, "%-*.*s|",
- indent, indent, " ");
- bu_vls_printf(gedp->ged_result_str, "%s", buf);
- }
-
- /* data in sets of two */
- /* field 0 */
- field = 0;
- /* FIXME: using snprintf because bu_vls_printf is broken for complex
formats */
- snprintf(buf, FBUFSIZ, " %-*.*s",
- maxwidth[tcol], maxwidth[tcol],
table->rows[i].fields[field].buf);
- bu_vls_printf(gedp->ged_result_str, "%s", buf);
-
- /* field 1 */
- field = 1;
- /* FIXME: using snprintf because bu_vls_printf is broken for complex
formats */
- snprintf(buf, FBUFSIZ, " %-*.*s |",
- maxwidth[tcol+1], maxwidth[tcol+1],
table->rows[i].fields[field].buf);
- bu_vls_printf(gedp->ged_result_str, "%s", buf);
-
- /* iterate on columns */
- tcol += 2;
-
- if (tcol > 6) {
- /* time for a newline to end the row */
- bu_vls_printf(gedp->ged_result_str, "\n");
- tcol = 0;
- ++nrow;
- }
- }
-
- /* we may have a row to finish */
- nrows = table->nrows % 4;
- if (nrows) {
- assert(tcol < 8);
-
- /* write blanks */
- while (tcol < 7) {
-
- /* data in sets of two */
- /* this is field 0 */
- /* FIXME: using snprintf because bu_vls_printf is broken for
complex formats */
- snprintf(buf, FBUFSIZ, " %-*.*s",
- maxwidth[tcol], maxwidth[tcol], " ");
- bu_vls_printf(gedp->ged_result_str, "%s", buf);
-
- /* this is field 1 */
- /* FIXME: using snprintf because bu_vls_printf is broken for
complex formats */
- snprintf(buf, FBUFSIZ, " %-*.*s |",
- maxwidth[tcol+1], maxwidth[tcol+1], " ");
- bu_vls_printf(gedp->ged_result_str, "%s", buf);
-
- /* iterate on columns */
- tcol += 2;
-
- if (tcol > 6) {
- /* time for a newline to end the row */
- bu_vls_printf(gedp->ged_result_str, "\n");
- }
- }
- }
-
- /* close the table */
- /* print dashes in 4 sets */
- nd = maxwidth[0] + maxwidth[1] + 3; /* 1 space between numbers and one at
each end */
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%-*.*s+%-*.*s",
- indent, indent, " ",
- nd, nd, dashes.buf);
- nd = maxwidth[2] + maxwidth[3] + 3; /* 1 space between numbers and one at
each end */
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "+%-*.*s",
- nd, nd, dashes.buf);
- nd = maxwidth[4] + maxwidth[5] + 3; /* 1 space between numbers and one at
each end */
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "+%-*.*s",
- nd, nd, dashes.buf);
- nd = maxwidth[6] + maxwidth[7] + 3; /* 1 space between numbers and one at
each end */
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "+%-*.*s+\n",
- nd, nd, dashes.buf);
-}
-
-
-void print_faces_table(struct ged *gedp, table_t *table)
-{
-
-/* table header
-
-
+------+-----------------------------+--------------------------------------------------+-----------------+
- | FACE | ROT FB | PLANE EQUATION
| SURFACE AREA |
-
+------+-----------------------------+--------------------------------------------------+-----------------+
-
-*/
-
- /* track actual table column widths */
- /* this table has 8 columns */
- int maxwidth[8] = {0, 0, 0,
- 0, 0, 0,
- 0, 0};
- int i, j;
- int c0, h1a, h1b, h1c;
- int h2a, h2b, h2c;
- int c2, c2a, c2b, c2c;
- int f7, f7a, f7b, f7c;
- int nd, tnd;
- field_t dashes;
- char ROT[] = {"ROT"};
- char FB[] = {"FB"};
- char PA[] = {"PLANE EQUATION"};
- char SA[] = {"SURFACE AREA"};
-
- /* get max fields widths */
- for (i = 0; i < table->nrows; ++i) {
- for (j = 0; j < table->rows[i].nfields; ++j) {
- if (table->rows[i].fields[j].nchars > maxwidth[j])
- maxwidth[j] = table->rows[i].fields[j].nchars;
- }
- }
-
- /* blank line following previous table */
- bu_vls_printf(gedp->ged_result_str, "\n");
-
- /* get max width of header columns (not counting single space on either
side) */
- c0 = maxwidth[0] > 4 ? maxwidth[0] : 4;
-
- /* print "ROT" in center of field 1 space */
- h1b = strlen(ROT);
- h1a = (maxwidth[1] - h1b)/2;
- h1c = (maxwidth[1] - h1b - h1a);
-
- /* print "FB" in center of field 2 space */
- h2b = strlen(FB);
- h2a = (maxwidth[2] - h2b)/2;
- h2c = (maxwidth[2] - h2b - h2a);
-
- /* get width of subcolumns of header column 2 */
- /* print "PLANE EQUATION" in center of columns 2 space */
- c2 = maxwidth[3] + maxwidth[4] + maxwidth[5] + maxwidth[6] + 3; /* 3
spaces between fields */
- c2b = strlen(PA);
- c2a = (c2 - c2b)/2;
- c2c = (c2 - c2b - c2a);
-
- /* print "SURFACE AREA" in center of field 7 space */
- f7b = strlen(SA);
- f7 = maxwidth[7] > f7b ? maxwidth[7] : f7b;
- f7a = (f7 - f7b)/2;
- f7c = (f7 - f7b - f7a);
-
- /* print the pieces */
-
- /* header row 1 */
- bu_vls_printf(gedp->ged_result_str, "+-");
- nd = c0; tnd = nd;
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%-*.*s",
- nd, nd, dashes.buf);
- bu_vls_printf(gedp->ged_result_str, "-+-");
- nd = h1a + h1b + h1c + 1 + h2a + h2b + h2c; tnd += nd + 3;
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%*.*s",
- nd, nd, dashes.buf);
- bu_vls_printf(gedp->ged_result_str, "-+-");
- nd = c2a + c2b + c2c; tnd += nd + 3;
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%*.*s",
- nd, nd, dashes.buf);
- bu_vls_printf(gedp->ged_result_str, "-+-");
- nd = f7a + f7b + f7c; tnd += nd + 3;
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%*.*s",
- nd, nd, dashes.buf);
- bu_vls_printf(gedp->ged_result_str, "-+\n");
-
- /* header row 2 */
- bu_vls_printf(gedp->ged_result_str, "| ");
-
- bu_vls_printf(gedp->ged_result_str, "%-*.*s", c0, c0, "FACE");
-
- bu_vls_printf(gedp->ged_result_str, " | ");
-
-
- bu_vls_printf(gedp->ged_result_str, "%*.*s", h1a, h1a, " ");
-
- bu_vls_printf(gedp->ged_result_str, "%*.*s", h1b, h1b, ROT);
-
- bu_vls_printf(gedp->ged_result_str, "%*.*s", h1c+h2a, h1c+h2a, " ");
-
- bu_vls_printf(gedp->ged_result_str, "%*.*s", h2b, h2b, FB);
-
- bu_vls_printf(gedp->ged_result_str, "%*.*s ", h2c, h2c, " ");
-
-
- bu_vls_printf(gedp->ged_result_str, " | ");
-
-
- bu_vls_printf(gedp->ged_result_str, "%*.*s", c2a, c2a, " ");
-
- bu_vls_printf(gedp->ged_result_str, "%*.*s", c2b, c2b, PA);
-
- bu_vls_printf(gedp->ged_result_str, "%*.*s", c2c, c2c, " ");
-
-
- bu_vls_printf(gedp->ged_result_str, " | ");
-
- bu_vls_printf(gedp->ged_result_str, "%*.*s", f7a, f7a, " ");
-
- bu_vls_printf(gedp->ged_result_str, "%*.*s", f7b, f7b, SA);
-
- bu_vls_printf(gedp->ged_result_str, "%*.*s", f7c, f7c, " ");
-
- bu_vls_printf(gedp->ged_result_str, " |\n");
-
- /* header row 3 */
- bu_vls_printf(gedp->ged_result_str, "+-");
- nd = c0; tnd = nd;
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%-*.*s",
- nd, nd, dashes.buf);
- bu_vls_printf(gedp->ged_result_str, "-+-");
- nd = h1a + h1b + h1c + 1 + h2a + h2b + h2c; tnd += nd + 3;
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%*.*s",
- nd, nd, dashes.buf);
- bu_vls_printf(gedp->ged_result_str, "-+-");
- nd = c2a + c2b + c2c; tnd += nd + 3;
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%*.*s",
- nd, nd, dashes.buf);
- bu_vls_printf(gedp->ged_result_str, "-+-");
- nd = f7a + f7b + f7c; tnd += nd + 3;
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%*.*s",
- nd, nd, dashes.buf);
- bu_vls_printf(gedp->ged_result_str, "-+\n");
-
- /* output table data rows */
- for (i = 0; i < table->nrows; ++i) {
- /* may not have a row with data */
- if (table->rows[i].nfields == 0)
- continue;
- if (table->rows[i].nfields == NOT_A_PLANE)
- bu_vls_printf(gedp->ged_result_str, "***NOT A PLANE ***");
-
- bu_vls_printf(gedp->ged_result_str, "|");
- for (j = 0; j < table->rows[i].nfields; ++j) {
- assert(table->rows[i].fields[j].buf);
- bu_vls_printf(gedp->ged_result_str, " %*.*s",
- maxwidth[j], maxwidth[j],
- table->rows[i].fields[j].buf);
- /* do we need a separator? */
- if (j == 0 || j == 2 || j == 6 || j == 7)
- bu_vls_printf(gedp->ged_result_str, " |");
- }
- /* close the row */
- bu_vls_printf(gedp->ged_result_str, "\n");
- }
-
- /* close the table with the ender row */
- bu_vls_printf(gedp->ged_result_str, "+-");
- nd = c0; tnd = nd;
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%-*.*s",
- nd, nd, dashes.buf);
- bu_vls_printf(gedp->ged_result_str, "-+-");
- nd = h1a + h1b + h1c + 1 + h2a + h2b + h2c; tnd += nd + 3;
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%*.*s",
- nd, nd, dashes.buf);
- bu_vls_printf(gedp->ged_result_str, "-+-");
- nd = c2a + c2b + c2c; tnd += nd + 3;
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%*.*s",
- nd, nd, dashes.buf);
- bu_vls_printf(gedp->ged_result_str, "-+-");
- nd = f7a + f7b + f7c; tnd += nd + 3;
- get_dashes(&dashes, nd);
- bu_vls_printf(gedp->ged_result_str, "%*.*s",
- nd, nd, dashes.buf);
- bu_vls_printf(gedp->ged_result_str, "-+\n");
-}
-
-
-/**
- * general analyze function for primitives that can be analyzed using volume
- * and surface area functions from the rt_functab.
- * Currently used for:
- * - ell
- * - tor
- * - tgc
- * - rpc
- * - eto
- * - epa
- * - part
- * - rhc
- */
-HIDDEN void
-analyze_general(struct ged *gedp, const struct rt_db_internal *ip)
-{
- fastf_t vol, area;
- point_t centroid;
-
- vol = area = -1.0;
-
- if (OBJ[ip->idb_minor_type].ft_volume) {
- OBJ[ip->idb_minor_type].ft_volume(&vol, ip);
- }
- if (OBJ[ip->idb_minor_type].ft_surf_area) {
- OBJ[ip->idb_minor_type].ft_surf_area(&area, ip);
- }
-
- if (OBJ[ip->idb_minor_type].ft_centroid) {
- OBJ[ip->idb_minor_type].ft_centroid(¢roid, ip);
- bu_vls_printf(gedp->ged_result_str, "\n Centroid: (%g, %g, %g)\n",
- centroid[X] * gedp->ged_wdbp->dbip->dbi_base2local,
- centroid[Y] * gedp->ged_wdbp->dbip->dbi_base2local,
- centroid[Z] * gedp->ged_wdbp->dbip->dbi_base2local);
- }
-
- print_volume_table(gedp,
- vol
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local,
- area
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local,
- vol/GALLONS_TO_MM3
- );
-}
-
-
-/**
- * finds direction cosines and rotation, fallback angles of a unit vector
- * angles = pointer to 5 fastf_t's to store angles
- * unitv = pointer to the unit vector (previously computed)
- */
-HIDDEN void
-findang(fastf_t *angles, fastf_t *unitv)
-{
- int i;
- fastf_t f;
-
- /* convert direction cosines into axis angles */
- for (i = X; i <= Z; i++) {
- if (unitv[i] <= -1.0)
- angles[i] = -90.0;
- else if (unitv[i] >= 1.0)
- angles[i] = 90.0;
- else
- angles[i] = acos(unitv[i]) * RAD2DEG;
- }
-
- /* fallback angle */
- if (unitv[Z] <= -1.0)
- unitv[Z] = -1.0;
- else if (unitv[Z] >= 1.0)
- unitv[Z] = 1.0;
- angles[4] = asin(unitv[Z]);
-
- /* rotation angle */
- /* For the tolerance below, on an SGI 4D/70, cos(asin(1.0)) != 0.0
- * with an epsilon of +/- 1.0e-17, so the tolerance below was
- * substituted for the original +/- 1.0e-20.
- */
- if ((f = cos(angles[4])) > 1.0e-16 || f < -1.0e-16) {
- f = unitv[X]/f;
- if (f <= -1.0)
- angles[3] = 180.0;
- else if (f >= 1.0)
- angles[3] = 0.0;
- else
- angles[3] = RAD2DEG * acos(f);
- } else
- angles[3] = 0.0;
-
- if (unitv[Y] < 0)
- angles[3] = 360.0 - angles[3];
-
- angles[4] *= RAD2DEG;
-}
-
-
-/**
- * general analyze function for polygonal faces.
- * Currently used for:
- * - arb8
- * - arbn
- * - ars
- *
- * returns:
- * - area in face->area
- * - print_faces_table() information in row
- * - sorts vertices in face->pts into ccw order
- */
-HIDDEN void
-analyze_poly_face(struct ged *gedp, struct poly_face *face, row_t *row)
-{
- fastf_t angles[5];
-
- findang(angles, face->plane_eqn);
-
- /* sort points */
- bg_3d_polygon_sort_ccw(face->npts, face->pts, face->plane_eqn);
- bg_3d_polygon_area(&face->area, face->npts, (const point_t *)face->pts);
-
- /* store face information for pretty printing */
- row->nfields = 8;
- row->fields[0].nchars = sprintf(row->fields[0].buf, "%4s", face->label);
- row->fields[1].nchars = sprintf(row->fields[1].buf, "%10.8f", angles[3]);
- row->fields[2].nchars = sprintf(row->fields[2].buf, "%10.8f", angles[4]);
- row->fields[3].nchars = sprintf(row->fields[3].buf, "%10.8f",
face->plane_eqn[X]);
- row->fields[4].nchars = sprintf(row->fields[4].buf, "%10.8f",
face->plane_eqn[Y]);
- row->fields[5].nchars = sprintf(row->fields[5].buf, "%10.8f",
face->plane_eqn[Z]);
- row->fields[6].nchars = sprintf(row->fields[6].buf, "%10.8f",
-
face->plane_eqn[W]*gedp->ged_wdbp->dbip->dbi_base2local);
- row->fields[7].nchars = sprintf(row->fields[7].buf, "%10.8f",
-
face->area*gedp->ged_wdbp->dbip->dbi_base2local*gedp->ged_wdbp->dbip->dbi_base2local);
-}
-
-
-HIDDEN void
-analyze_edge(struct ged *gedp, const int edge, const struct rt_arb_internal
*arb,
- const int type, row_t *row)
-{
- int a = nedge[type][edge*2];
- int b = nedge[type][edge*2+1];
-
- if (b == -1) {
- row->nfields = 0;
- return;
- }
-
- row->nfields = 2;
- row->fields[0].nchars = sprintf(row->fields[0].buf, "%d%d", a + 1, b + 1);
- row->fields[1].nchars = sprintf(row->fields[1].buf, "%10.8f",
- DIST_PNT_PNT(arb->pt[a],
arb->pt[b])*gedp->ged_wdbp->dbip->dbi_base2local);
-}
-
-
-HIDDEN void
-analyze_arb8(struct ged *gedp, const struct rt_db_internal *ip)
-{
- int i, type;
- int cgtype; /* COMGEOM arb type: # of vertices */
- table_t table; /* holds table data from child functions */
- fastf_t tot_vol = 0.0, tot_area = 0.0;
- point_t center_pt = VINIT_ZERO;
- struct poly_face face = POLY_FACE_INIT_ZERO;
- struct rt_arb_internal earb;
- struct rt_arb_internal *arb = (struct rt_arb_internal *)ip->idb_ptr;
- const int arb_faces[5][24] = rt_arb_faces;
- RT_ARB_CK_MAGIC(arb);
-
- /* find the specific arb type, in GIFT order. */
- if ((cgtype = rt_arb_std_type(ip, &gedp->ged_wdbp->wdb_tol)) == 0) {
- bu_vls_printf(gedp->ged_result_str, "analyze_arb: bad ARB\n");
- return;
- }
-
- type = cgtype - 4;
-
- /* to get formatting correct, we need to collect the actual string
- * lengths for each field BEFORE we start printing a table (fields
- * are allowed to overflow the stated printf field width) */
-
- /* TABLE 1 =========================================== */
- /* analyze each face, use center point of arb for reference */
- rt_arb_centroid(¢er_pt, ip);
-
- /* allocate pts array, maximum 4 verts per arb8 face */
- face.pts = (point_t *)bu_calloc(4, sizeof(point_t), "analyze_arb8: pts");
- /* allocate table rows, 12 rows needed for arb8 edges */
- table.rows = (row_t *)bu_calloc(12, sizeof(row_t), "analyze_arb8: rows");
-
- table.nrows = 0;
- for (face.npts = 0, i = 0; i < 6; face.npts = 0, i++) {
- int a, b, c, d; /* 4 indices to face vertices */
-
- a = arb_faces[type][i*4+0];
- b = arb_faces[type][i*4+1];
- c = arb_faces[type][i*4+2];
- d = arb_faces[type][i*4+3];
-
- if (a == -1) {
- table.rows[i].nfields = 0;
- continue;
- }
-
- /* find plane eqn for this face */
- if (bn_make_plane_3pnts(face.plane_eqn, arb->pt[a], arb->pt[b],
arb->pt[c], &gedp->ged_wdbp->wdb_tol) < 0) {
- bu_vls_printf(gedp->ged_result_str, "| %d%d%d%d | ***NOT A
PLANE*** |\n",
- a+1, b+1, c+1, d+1);
- /* this row has 1 special fields */
- table.rows[i].nfields = NOT_A_PLANE;
- continue;
- }
-
- ADD_PT(face, arb->pt[a]);
- ADD_PT(face, arb->pt[b]);
- ADD_PT(face, arb->pt[c]);
- ADD_PT(face, arb->pt[d]);
-
- /* The plane equations returned by bn_make_plane_3pnts above do
- * not necessarily point outward. Use the reference center
- * point for the arb and reverse direction for any errant planes.
- * This corrects the output rotation, fallback angles so that
- * they always give the outward pointing normal vector. */
- if (DIST_PNT_PLANE(center_pt, face.plane_eqn) > 0.0) {
- HREVERSE(face.plane_eqn, face.plane_eqn);
- }
-
- snprintf(face.label, sizeof(face.label), "%d", prface[type][i]);
-
- analyze_poly_face(gedp, &face, &(table.rows[i]));
- tot_area += face.area;
- table.nrows++;
- }
-
- /* and print it */
- print_faces_table(gedp, &table);
-
- /* TABLE 2 =========================================== */
- /* analyze each edge */
-
- /* blank line following previous table */
- bu_vls_printf(gedp->ged_result_str, "\n");
-
- /* set up the records for arb4's and arb6's */
- earb = *arb; /* struct copy */
- if (cgtype == 4) {
- VMOVE(earb.pt[3], earb.pt[4]);
- } else if (cgtype == 6) {
- VMOVE(earb.pt[5], earb.pt[6]);
- }
-
- table.nrows = 0;
- for (i = 0; i < 12; i++) {
- analyze_edge(gedp, i, &earb, type, &(table.rows[i]));
- if (nedge[type][i*2] == -1) {
- break;
- }
- table.nrows += 1;
- }
-
- print_edges_table(gedp, &table);
-
- /* TABLE 3 =========================================== */
- /* find the volume - break arb8 into 6 arb4s */
-
- if (OBJ[ID_ARB8].ft_volume)
- OBJ[ID_ARB8].ft_volume(&tot_vol, ip);
-
- print_volume_table(gedp,
- tot_vol
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local,
- tot_area
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local,
- tot_vol/GALLONS_TO_MM3
- );
-
- bu_free((char *)face.pts, "analyze_arb8: pts");
- bu_free((char *)table.rows, "analyze_arb8: rows");
-}
-
-
-HIDDEN void
-analyze_arbn(struct ged *gedp, const struct rt_db_internal *ip)
-{
- size_t i;
- fastf_t tot_vol = 0.0, tot_area = 0.0;
- table_t table;
- struct poly_face *faces;
- struct bu_vls tmpstr = BU_VLS_INIT_ZERO;
- struct rt_arbn_internal *aip = (struct rt_arbn_internal *)ip->idb_ptr;
- size_t *npts = (size_t *)bu_calloc(aip->neqn, sizeof(size_t),
"analyze_arbn: npts");
- point_t **tmp_pts = (point_t **)bu_calloc(aip->neqn, sizeof(point_t *),
"analyze_arbn: tmp_pts");
- plane_t *eqs= (plane_t *)bu_calloc(aip->neqn, sizeof(plane_t),
"analyze_arbn: eqs");
-
- /* allocate array of face structs */
- faces = (struct poly_face *)bu_calloc(aip->neqn, sizeof(struct poly_face),
"analyze_arbn: faces");
- for (i = 0; i < aip->neqn; i++) {
- HMOVE(faces[i].plane_eqn, aip->eqn[i]);
- VUNITIZE(faces[i].plane_eqn);
- /* allocate array of pt structs, max number of verts per faces = (# of
faces) - 1 */
- faces[i].pts = (point_t *)bu_calloc(aip->neqn - 1, sizeof(point_t),
"analyze_arbn: pts");
- tmp_pts[i] = faces[i].pts;
- HMOVE(eqs[i], faces[i].plane_eqn);
- }
- /* allocate table rows, 1 row per plane eqn */
- table.rows = (row_t *)bu_calloc(aip->neqn, sizeof(row_t), "analyze_arbn:
rows");
- table.nrows = aip->neqn;
-
- bg_3d_polygon_make_pnts_planes(npts, tmp_pts, aip->neqn, (const plane_t
*)eqs);
-
- for (i = 0; i < aip->neqn; i++) {
- vect_t tmp;
- bu_vls_sprintf(&tmpstr, "%4zu", i);
- snprintf(faces[i].label, sizeof(faces[i].label), "%s",
bu_vls_addr(&tmpstr));
-
- faces[i].npts = npts[i];
-
- /* calculate surface area */
- analyze_poly_face(gedp, &faces[i], &table.rows[i]);
- tot_area += faces[i].area;
-
- /* calculate volume */
- VSCALE(tmp, faces[i].plane_eqn, faces[i].area);
- tot_vol += VDOT(faces[i].pts[0], tmp);
- }
- tot_vol /= 3.0;
-
- print_faces_table(gedp, &table);
- print_volume_table(gedp,
- tot_vol
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local,
- tot_area
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local,
- tot_vol/GALLONS_TO_MM3
- );
-
- for (i = 0; i < aip->neqn; i++) {
- bu_free((char *)faces[i].pts, "analyze_arbn: pts");
- }
- bu_free((char *)faces, "analyze_arbn: faces");
- bu_free((char *)table.rows, "analyze_arbn: rows");
- bu_free((char *)tmp_pts, "analyze_arbn: tmp_pts");
- bu_free((char *)npts, "analyze_arbn: npts");
- bu_free((char *)eqs, "analyze_arbn: eqs");
- bu_vls_free(&tmpstr);
-}
-
-
-#define ARS_PT(ii, jj) (&arip->curves[i+(ii)][(j+(jj))*ELEMENTS_PER_VECT])
-
-HIDDEN void
-analyze_ars(struct ged *gedp, const struct rt_db_internal *ip)
-{
- size_t i, j, k;
- size_t nfaces = 0;
- fastf_t tot_area = 0.0, tot_vol = 0.0;
- table_t table;
- plane_t old_plane = HINIT_ZERO;
- struct bu_vls tmpstr = BU_VLS_INIT_ZERO;
- struct poly_face face = POLY_FACE_INIT_ZERO;
- struct rt_ars_internal *arip = (struct rt_ars_internal *)ip->idb_ptr;
- RT_ARS_CK_MAGIC(arip);
-
- /* allocate pts array, max 3 pts per triangular face */
- face.pts = (point_t *)bu_calloc(3, sizeof(point_t), "analyze_ars: pts");
- /* allocate table rows, probably overestimating the number of rows needed
*/
- table.rows = (row_t *)bu_calloc((arip->ncurves - 1) * 2 *
arip->pts_per_curve, sizeof(row_t), "analyze_ars: rows");
-
- k = arip->pts_per_curve - 2;
- for (i = 0; i < arip->ncurves - 1; i++) {
- int double_ended = k != 1 &&
VEQUAL(&arip->curves[i][ELEMENTS_PER_VECT], &arip->curves[i][k *
ELEMENTS_PER_VECT]);
-
- for (j = 0; j < arip->pts_per_curve; j++) {
- vect_t tmp;
-
- if (double_ended && i != 0 && (j == 0 || j == k || j ==
arip->pts_per_curve - 1)) continue;
-
- /* first triangular face, make sure it's not a duplicate */
- if (bn_make_plane_3pnts(face.plane_eqn, ARS_PT(0, 0), ARS_PT(1, 1),
ARS_PT(0, 1), &gedp->ged_wdbp->wdb_tol) == 0
- && !HEQUAL(old_plane, face.plane_eqn)) {
- HMOVE(old_plane, face.plane_eqn);
- ADD_PT(face, ARS_PT(0, 1));
- ADD_PT(face, ARS_PT(0, 0));
- ADD_PT(face, ARS_PT(1, 1));
-
- bu_vls_sprintf(&tmpstr, "%zu%zu", i, j);
- snprintf(face.label, sizeof(face.label), "%s",
bu_vls_addr(&tmpstr));
-
- /* surface area */
- analyze_poly_face(gedp, &face, &(table.rows[nfaces]));
- tot_area += face.area;
-
- /* volume */
- VSCALE(tmp, face.plane_eqn, face.area);
- tot_vol += fabs(VDOT(face.pts[0], tmp));
-
- face.npts = 0;
- nfaces++;
- }
-
- /* second triangular face, make sure it's not a duplicate */
- if (bn_make_plane_3pnts(face.plane_eqn, ARS_PT(1, 0), ARS_PT(1, 1),
ARS_PT(0, 0), &gedp->ged_wdbp->wdb_tol) == 0
- && !HEQUAL(old_plane, face.plane_eqn)) {
- HMOVE(old_plane, face.plane_eqn);
- ADD_PT(face, ARS_PT(1, 0));
- ADD_PT(face, ARS_PT(0, 0));
- ADD_PT(face, ARS_PT(1, 1));
-
- bu_vls_sprintf(&tmpstr, "%zu%zu", i, j);
- snprintf(face.label, sizeof(face.label), "%s",
bu_vls_addr(&tmpstr));
-
- analyze_poly_face(gedp, &face, &table.rows[nfaces]);
- tot_area += face.area;
-
- VSCALE(tmp, face.plane_eqn, face.area);
- tot_vol += fabs(VDOT(face.pts[0], tmp));
-
- face.npts = 0;
- nfaces++;
- }
- }
- }
- tot_vol /= 3.0;
- table.nrows = nfaces;
-
- print_faces_table(gedp, &table);
- print_volume_table(gedp,
- tot_vol
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local,
- tot_area
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local,
- tot_vol/GALLONS_TO_MM3
- );
-
- bu_free((char *)face.pts, "analyze_ars: pts");
- bu_free((char *)table.rows, "analyze_ars: rows");
- bu_vls_free(&tmpstr);
-}
-
-
-#define PROLATE 1
-#define OBLATE 2
-
-HIDDEN void
-analyze_superell(struct ged *gedp, const struct rt_db_internal *ip)
-{
- struct rt_superell_internal *superell = (struct rt_superell_internal
*)ip->idb_ptr;
- fastf_t ma, mb, mc;
- fastf_t ecc, major_mag, minor_mag;
- fastf_t vol, sur_area;
- int type;
-
- RT_SUPERELL_CK_MAGIC(superell);
-
- ma = MAGNITUDE(superell->a);
- mb = MAGNITUDE(superell->b);
- mc = MAGNITUDE(superell->c);
-
- type = 0;
-
- vol = 4.0 * M_PI * ma * mb * mc / 3.0;
-
- if (fabs(ma-mb) < .00001 && fabs(mb-mc) < .00001) {
- /* have a sphere */
- sur_area = 4.0 * M_PI * ma * ma;
- goto print_results;
- }
- if (fabs(ma-mb) < .00001) {
- /* A == B */
- if (mc > ma) {
- /* oblate spheroid */
- type = OBLATE;
- major_mag = mc;
- minor_mag = ma;
- } else {
- /* prolate spheroid */
- type = PROLATE;
- major_mag = ma;
- minor_mag = mc;
- }
- } else
- if (fabs(ma-mc) < .00001) {
- /* A == C */
- if (mb > ma) {
- /* oblate spheroid */
- type = OBLATE;
- major_mag = mb;
- minor_mag = ma;
- } else {
- /* prolate spheroid */
- type = PROLATE;
- major_mag = ma;
- minor_mag = mb;
- }
- } else
- if (fabs(mb-mc) < .00001) {
- /* B == C */
- if (ma > mb) {
- /* oblate spheroid */
- type = OBLATE;
- major_mag = ma;
- minor_mag = mb;
- } else {
- /* prolate spheroid */
- type = PROLATE;
- major_mag = mb;
- minor_mag = ma;
- }
- } else {
- bu_vls_printf(gedp->ged_result_str, " Cannot find surface
area\n");
- return;
- }
- ecc = sqrt(major_mag*major_mag - minor_mag*minor_mag) / major_mag;
- if (type == PROLATE) {
- sur_area = M_2PI * minor_mag * minor_mag +
- (M_2PI * (major_mag*minor_mag/ecc) * asin(ecc));
- } else {
- /* type == OBLATE */
- sur_area = M_2PI * major_mag * major_mag +
- (M_PI * (minor_mag*minor_mag/ecc) * log((1.0+ecc)/(1.0-ecc)));
- }
-
-print_results:
- print_volume_table(gedp,
- vol
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local,
- sur_area
- * gedp->ged_wdbp->dbip->dbi_base2local
- * gedp->ged_wdbp->dbip->dbi_base2local,
- vol/GALLONS_TO_MM3
- );
-}
-
-
-HIDDEN void
-analyze_sketch(struct ged *gedp, const struct rt_db_internal *ip)
-{
- fastf_t area = -1;
- point_t centroid;
-
- if (OBJ[ID_SKETCH].ft_surf_area)
- OBJ[ID_SKETCH].ft_surf_area(&area, ip);
-
- if (area > 0.0) {
- bu_vls_printf(gedp->ged_result_str, "\nTotal Area: %10.8f",
- area
- * gedp->ged_wdbp->dbip->dbi_local2base
- * gedp->ged_wdbp->dbip->dbi_local2base
- );
- }
-
- if (OBJ[ID_SKETCH].ft_centroid) {
- OBJ[ID_SKETCH].ft_centroid(¢roid, ip);
- bu_vls_printf(gedp->ged_result_str, "\n Centroid: (%g, %g, %g)\n",
- centroid[X] * gedp->ged_wdbp->dbip->dbi_base2local,
- centroid[Y] * gedp->ged_wdbp->dbip->dbi_base2local,
- centroid[Z] * gedp->ged_wdbp->dbip->dbi_base2local);
- }
-}
-
-
-/**
- * Analyze command - prints loads of info about a solid
- * Format: analyze [name]
- * if 'name' is missing use solid being edited
- */
-
-/* Analyze solid in internal form */
-HIDDEN void
-analyze_do(struct ged *gedp, const struct rt_db_internal *ip)
-{
- /* XXX Could give solid name, and current units, here */
-
- switch (ip->idb_type) {
-
- case ID_ARB8:
- analyze_arb8(gedp, ip);
- break;
-
- case ID_BOT:
- analyze_general(gedp, ip);
- break;
-
- case ID_ARBN:
- analyze_arbn(gedp, ip);
- break;
-
- case ID_ARS:
- analyze_ars(gedp, ip);
- break;
-
- case ID_TGC:
- analyze_general(gedp, ip);
- break;
-
- case ID_ELL:
- analyze_general(gedp, ip);
- break;
-
- case ID_TOR:
- analyze_general(gedp, ip);
- break;
-
- case ID_RPC:
- analyze_general(gedp, ip);
- break;
-
- case ID_ETO:
- analyze_general(gedp, ip);
- break;
-
- case ID_EPA:
- analyze_general(gedp, ip);
- break;
-
- case ID_PARTICLE:
- analyze_general(gedp, ip);
- break;
-
- case ID_SUPERELL:
- analyze_superell(gedp, ip);
- break;
-
- case ID_SKETCH:
- analyze_sketch(gedp, ip);
- break;
-
- case ID_HYP:
- analyze_general(gedp, ip);
- break;
-
- case ID_PIPE:
- analyze_general(gedp, ip);
- break;
-
- case ID_VOL:
- analyze_general(gedp, ip);
- break;
-
- case ID_EXTRUDE:
- analyze_general(gedp, ip);
- break;
-
- case ID_RHC:
- analyze_general(gedp, ip);
- break;
-
- default:
- bu_vls_printf(gedp->ged_result_str, "\nanalyze: unable to process
%s solid\n",
- OBJ[ip->idb_type].ft_name);
- break;
- }
-}
-
-
-int
-ged_analyze_core(struct ged *gedp, int argc, const char *argv[])
-{
- struct directory *ndp;
- int i;
- struct rt_db_internal intern;
- static const char *usage = "object(s)";
-
- GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
- GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
-
- /* initialize result */
- bu_vls_trunc(gedp->ged_result_str, 0);
-
- /* must be wanting help */
- if (argc == 1) {
- bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
- return GED_HELP;
- }
-
- /* use the names that were input */
- for (i = 1; i < argc; i++) {
- if ((ndp = db_lookup(gedp->ged_wdbp->dbip, argv[i], LOOKUP_NOISY)) ==
RT_DIR_NULL)
- continue;
-
- GED_DB_GET_INTERNAL(gedp, &intern, ndp, bn_mat_identity,
&rt_uniresource, GED_ERROR);
-
- _ged_do_list(gedp, ndp, 1);
- analyze_do(gedp, &intern);
- rt_db_free_internal(&intern);
- }
-
- return GED_OK;
-}
-
-
-#ifdef GED_PLUGIN
-#include "../include/plugin.h"
-struct ged_cmd_impl analyze_cmd_impl = {
- "analyze",
- ged_analyze_core,
- GED_CMD_DEFAULT
-};
-
-const struct ged_cmd analyze_cmd = { &analyze_cmd_impl };
-const struct ged_cmd *analyze_cmds[] = { &analyze_cmd, NULL };
-
-static const struct ged_plugin pinfo = { GED_API, analyze_cmds, 1 };
-
-COMPILER_DLLEXPORT const struct ged_plugin *ged_plugin_info()
-{
- return &pinfo;
-}
-#endif /* GED_PLUGIN */
-
-/*
- * Local Variables:
- * mode: C
- * tab-width: 8
- * indent-tabs-mode: t
- * c-file-style: "stroustrup"
- * End:
- * ex: shiftwidth=4 tabstop=8
- */
Copied: brlcad/trunk/src/libged/analyze/analyze.cpp (from rev 77221,
brlcad/branches/analyze_cmd/src/libged/analyze/analyze.cpp)
===================================================================
--- brlcad/trunk/src/libged/analyze/analyze.cpp (rev 0)
+++ brlcad/trunk/src/libged/analyze/analyze.cpp 2020-09-25 13:41:24 UTC (rev
77222)
@@ -0,0 +1,748 @@
+/* A N A L Y Z E . C P P
+ * BRL-CAD
+ *
+ * Copyright (c) 2020 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * 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.
+ *
+ * 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 file; see the file named COPYING for more
+ * information.
+ */
+/** @file analyze.cpp
+ *
+ * The analyze command
+ *
+ */
+
+#include "common.h"
+
+extern "C" {
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+}
+
+#include <limits>
+
+extern "C" {
+#include "bu/cmd.h"
+#include "bu/opt.h"
+#include "../ged_private.h"
+#include "./ged_analyze.h"
+}
+
+#define DB_SOLID INT_MAX
+#define DB_NON_SOLID INT_MAX - 1
+
+
+#define HELPFLAG "--print-help"
+#define PURPOSEFLAG "--print-purpose"
+
+struct _ged_analyze_info {
+ struct ged *gedp = NULL;
+ const struct bu_cmdtab *cmds = NULL;
+ struct bu_opt_desc *gopts = NULL;
+ int verbosity = 0;
+ std::map<std::pair<int, int>, op_func_ptr> *union_map;
+ std::map<std::pair<int, int>, op_func_ptr> *isect_map;
+ std::map<std::pair<int, int>, op_func_ptr> *subtr_map;
+};
+
+
+static struct _ged_analyze_info *
+_analyze_info_create()
+{
+ struct _ged_analyze_info *gc = new struct _ged_analyze_info;
+ gc->verbosity = 0;
+ gc->union_map = new std::map<std::pair<int, int>, op_func_ptr>;
+ gc->isect_map = new std::map<std::pair<int, int>, op_func_ptr>;
+ gc->subtr_map = new std::map<std::pair<int, int>, op_func_ptr>;
+
+
+ // Populate the maps with known pair analysis functions
+ (*gc->union_map)[std::make_pair(DB5_MINORTYPE_BRLCAD_PNTS, DB_SOLID)] =
op_pnts_vol;
+ (*gc->isect_map)[std::make_pair(DB5_MINORTYPE_BRLCAD_PNTS, DB_SOLID)] =
op_pnts_vol;
+ (*gc->subtr_map)[std::make_pair(DB5_MINORTYPE_BRLCAD_PNTS, DB_SOLID)] =
op_pnts_vol;
+
+ return gc;
+}
+
+static void
+_analyze_info_destroy(struct _ged_analyze_info *s)
+{
+ delete s->union_map;
+ delete s->isect_map;
+ delete s->subtr_map;
+ delete s;
+}
+
+static bool
+db_solid_type(int type)
+{
+ switch (type) {
+ case DB5_MINORTYPE_BRLCAD_ARB8:
+ case DB5_MINORTYPE_BRLCAD_ARBN:
+ case DB5_MINORTYPE_BRLCAD_ARS:
+ case DB5_MINORTYPE_BRLCAD_BOT:
+ case DB5_MINORTYPE_BRLCAD_BREP:
+ case DB5_MINORTYPE_BRLCAD_BSPLINE:
+ case DB5_MINORTYPE_BRLCAD_CLINE:
+ case DB5_MINORTYPE_BRLCAD_COMBINATION:
+ case DB5_MINORTYPE_BRLCAD_DSP:
+ case DB5_MINORTYPE_BRLCAD_EBM:
+ case DB5_MINORTYPE_BRLCAD_EHY:
+ case DB5_MINORTYPE_BRLCAD_ELL:
+ case DB5_MINORTYPE_BRLCAD_EPA:
+ case DB5_MINORTYPE_BRLCAD_ETO:
+ case DB5_MINORTYPE_BRLCAD_EXTRUDE:
+ case DB5_MINORTYPE_BRLCAD_HALF:
+ case DB5_MINORTYPE_BRLCAD_HF:
+ case DB5_MINORTYPE_BRLCAD_HRT:
+ case DB5_MINORTYPE_BRLCAD_HYP:
+ case DB5_MINORTYPE_BRLCAD_METABALL:
+ case DB5_MINORTYPE_BRLCAD_NMG:
+ case DB5_MINORTYPE_BRLCAD_PARTICLE:
+ case DB5_MINORTYPE_BRLCAD_PIPE:
+ case DB5_MINORTYPE_BRLCAD_POLY:
+ case DB5_MINORTYPE_BRLCAD_REC:
+ case DB5_MINORTYPE_BRLCAD_REVOLVE:
+ case DB5_MINORTYPE_BRLCAD_RHC:
+ case DB5_MINORTYPE_BRLCAD_RPC:
+ case DB5_MINORTYPE_BRLCAD_SKETCH:
+ case DB5_MINORTYPE_BRLCAD_SPH:
+ case DB5_MINORTYPE_BRLCAD_SUBMODEL:
+ case DB5_MINORTYPE_BRLCAD_SUPERELL:
+ case DB5_MINORTYPE_BRLCAD_TGC:
+ case DB5_MINORTYPE_BRLCAD_TOR:
+ case DB5_MINORTYPE_BRLCAD_VOL:
+ return true;
+ case DB5_MINORTYPE_BRLCAD_ANNOT:
+ case DB5_MINORTYPE_BRLCAD_CONSTRAINT:
+ case DB5_MINORTYPE_BRLCAD_DATUM:
+ case DB5_MINORTYPE_BRLCAD_GRIP:
+ case DB5_MINORTYPE_BRLCAD_JOINT:
+ case DB5_MINORTYPE_BRLCAD_PNTS:
+ case DB5_MINORTYPE_BRLCAD_SCRIPT:
+ default:
+ return false;
+ };
+}
+
+static op_func_ptr
+_analyze_find_processor(struct _ged_analyze_info *s, db_op_t op, int t1, int
t2)
+{
+ int type1 = t1;
+ int type2 = t2;
+ std::map<std::pair<int, int>, op_func_ptr> *omap;
+ switch (op) {
+ case DB_OP_UNION:
+ omap = s->union_map;
+ break;
+ case DB_OP_INTERSECT:
+ omap = s->isect_map;
+ break;
+ case DB_OP_SUBTRACT:
+ omap = s->subtr_map;
+ break;
+ default:
+ return NULL;
+ }
+
+ if (omap->find(std::make_pair(type1, type2)) != omap->end()) {
+ return (*omap)[std::make_pair(t1, t2)];
+ }
+
+ // If there isn't a specific type, see if there's a generic match for t2
+ type2 = (db_solid_type(t2)) ? DB_SOLID : DB_NON_SOLID;
+ if (omap->find(std::make_pair(type1, type2)) != omap->end()) {
+ return (*omap)[std::make_pair(type1, type2)];
+ }
+
+ // If there isn't a specific type, see if there's a generic match for t1
+ type1 = (db_solid_type(t1)) ? DB_SOLID : DB_NON_SOLID;
+ type2 = t2;
+ if (omap->find(std::make_pair(type1, type2)) != omap->end()) {
+ return (*omap)[std::make_pair(type1, type2)];
+ }
+ // If there isn't a match, see if there's a generic match for t1 and t2
+ type1 = (db_solid_type(t1)) ? DB_SOLID : DB_NON_SOLID;
+ type2 = (db_solid_type(t2)) ? DB_SOLID : DB_NON_SOLID;
+ if (omap->find(std::make_pair(type1, type2)) != omap->end()) {
+ return (*omap)[std::make_pair(type1, type2)];
+ }
+
+ // Nope, nothing
+ return NULL;
+}
+
+static int
+_analyze_cmd_msgs(void *cs, int argc, const char **argv, const char *us, const
char *ps)
+{
+ struct _ged_analyze_info *gc = (struct _ged_analyze_info *)cs;
+ if (argc == 2 && BU_STR_EQUAL(argv[1], HELPFLAG)) {
+ bu_vls_printf(gc->gedp->ged_result_str, "%s\n%s\n", us, ps);
+ return 1;
+ }
+ if (argc == 2 && BU_STR_EQUAL(argv[1], PURPOSEFLAG)) {
+ bu_vls_printf(gc->gedp->ged_result_str, "%s\n", ps);
+ return 1;
+ }
+ return 0;
+}
+
+/* Analyze solid in internal form.
+ * TODO - this switch table probably indicates this should
+ * be a functab callback... */
+/**
+ * TODO: primitives that still need implementing
+ * ehy
+ * metaball
+ * nmg
+ */
+static void
+analyze_do_summary(struct ged *gedp, const struct rt_db_internal *ip)
+{
+ /* XXX Could give solid name, and current units, here */
+
+ switch (ip->idb_type) {
+
+ case ID_ARB8:
+ analyze_arb8(gedp, ip);
+ break;
+
+ case ID_BOT:
+ analyze_general(gedp, ip);
+ break;
+
+ case ID_ARBN:
+ analyze_arbn(gedp, ip);
+ break;
+
+ case ID_ARS:
+ analyze_ars(gedp, ip);
+ break;
+
+ case ID_TGC:
+ analyze_general(gedp, ip);
+ break;
+
+ case ID_ELL:
+ analyze_general(gedp, ip);
+ break;
+
+ case ID_TOR:
+ analyze_general(gedp, ip);
+ break;
+
+ case ID_RPC:
+ analyze_general(gedp, ip);
+ break;
+
+ case ID_ETO:
+ analyze_general(gedp, ip);
+ break;
+
+ case ID_EPA:
+ analyze_general(gedp, ip);
+ break;
+
+ case ID_PARTICLE:
+ analyze_general(gedp, ip);
+ break;
+
+ case ID_SUPERELL:
+ analyze_superell(gedp, ip);
+ break;
+
+ case ID_SKETCH:
+ analyze_sketch(gedp, ip);
+ break;
+
+ case ID_HYP:
+ analyze_general(gedp, ip);
+ break;
+
+ case ID_PIPE:
+ analyze_general(gedp, ip);
+ break;
+
+ case ID_VOL:
+ analyze_general(gedp, ip);
+ break;
+
+ case ID_EXTRUDE:
+ analyze_general(gedp, ip);
+ break;
+
+ case ID_RHC:
+ analyze_general(gedp, ip);
+ break;
+
+ default:
+ bu_vls_printf(gedp->ged_result_str, "\nanalyze: unable to process
%s solid\n",
+ OBJ[ip->idb_type].ft_name);
+ break;
+ }
+}
+
+extern "C" int
+_analyze_cmd_summarize(void *bs, int argc, const char **argv)
+{
+ const char *usage_string = "analyze [options] summarize obj1 <obj2 ...>";
+ const char *purpose_string = "Summary of analytical information about
listed objects";
+ if (_analyze_cmd_msgs(bs, argc, argv, usage_string, purpose_string)) {
+ return GED_OK;
+ }
+
+ struct _ged_analyze_info *gc = (struct _ged_analyze_info *)bs;
+ struct ged *gedp = gc->gedp;
+ struct rt_db_internal intern;
+
+ argc--; argv++;
+ if (!argc) {
+ bu_vls_printf(gc->gedp->ged_result_str, "%s\n", usage_string);
+ return GED_ERROR;
+ }
+
+ GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
+ GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
+
+ /* initialize result */
+ bu_vls_trunc(gedp->ged_result_str, 0);
+
+ /* use the names that were input */
+ for (int i = 0; i < argc; i++) {
+ struct directory *ndp = db_lookup(gedp->ged_wdbp->dbip, argv[i],
LOOKUP_NOISY);
+ if (ndp == RT_DIR_NULL)
+ continue;
+
+ GED_DB_GET_INTERNAL(gedp, &intern, ndp, bn_mat_identity,
&rt_uniresource, GED_ERROR);
+
+ _ged_do_list(gedp, ndp, 1);
+ analyze_do_summary(gedp, &intern);
+ rt_db_free_internal(&intern);
+ }
+
+ return GED_OK;
+}
+
+static void
+clear_obj(struct ged *gedp, const char *name)
+{
+ struct bu_vls tmpstr = BU_VLS_INIT_ZERO;
+ bu_vls_sprintf(&tmpstr, "%s", bu_vls_cstr(gedp->ged_result_str));
+ const char *av[4];
+ av[0] = "kill";
+ av[1] = "-f";
+ av[2] = "-q";
+ av[3] = name;
+ ged_kill(gedp, 4, (const char **)av);
+ bu_vls_sprintf(gedp->ged_result_str, "%s", bu_vls_cstr(&tmpstr));
+}
+
+
+static void
+mv_obj(struct ged *gedp, const char *n1, const char *n2)
+{
+ clear_obj(gedp, n2);
+ struct bu_vls tmpstr = BU_VLS_INIT_ZERO;
+ bu_vls_sprintf(&tmpstr, "%s", bu_vls_cstr(gedp->ged_result_str));
+ const char *av[3];
+ av[0] = "mv";
+ av[1] = n1;
+ av[2] = n2;
+ ged_move(gedp, 3, (const char **)av);
+ bu_vls_sprintf(gedp->ged_result_str, "%s", bu_vls_cstr(&tmpstr));
+}
+
+extern "C" int
+_analyze_cmd_intersect(void *bs, int argc, const char **argv)
+{
+ const char *usage_string = "analyze [options] intersect [-o out_obj] obj1
obj2 <...>";
+ const char *purpose_string = "Intersect obj1 with obj2 and any subsequent
objs";
+ if (_analyze_cmd_msgs(bs, argc, argv, usage_string, purpose_string)) {
+ return GED_OK;
+ }
+
+ struct _ged_analyze_info *gc = (struct _ged_analyze_info *)bs;
+ struct ged *gedp = gc->gedp;
+
+ argc--; argv++;
+ if (!argc) {
+ bu_vls_printf(gc->gedp->ged_result_str, "%s\n", usage_string);
+ return GED_ERROR;
+ }
+
+ GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
+ GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
+
+ /* initialize result */
+ bu_vls_trunc(gedp->ged_result_str, 0);
+
+ // See if we are going to output an object
+ int help = 0;
+ struct bu_vls oname = BU_VLS_INIT_ZERO;
+ struct bu_opt_desc d[3];
+ BU_OPT(d[0], "h", "help", "", NULL, &help, "Print help");
+ BU_OPT(d[1], "o", "output", "name", &bu_opt_vls, &oname, "Specify output
object");
+ BU_OPT_NULL(d[2]);
+
+ int ac = bu_opt_parse(NULL, argc, argv, d);
+ if (help) {
+ bu_vls_printf(gc->gedp->ged_result_str, "%s\n", usage_string);
+ return GED_HELP;
+ }
+ if (ac < 2) {
+ bu_vls_printf(gc->gedp->ged_result_str, "%s\n", usage_string);
+ return GED_HELP;
+ }
+ argc = ac;
+
+ if (bu_vls_strlen(&oname)) {
+ struct directory *dp_out = db_lookup(gedp->ged_wdbp->dbip,
bu_vls_cstr(&oname), LOOKUP_QUIET);
+ if (dp_out != RT_DIR_NULL) {
+ bu_vls_sprintf(gedp->ged_result_str, "specified output object %s
already exists.\n", bu_vls_cstr(&oname));
+ bu_vls_free(&oname);
+ return GED_ERROR;
+ }
+ }
+
+ long ret = 0;
+ const char *tmpname = "___analyze_cmd_intersect_tmp_obj__";
+ struct directory *dp1 = db_lookup(gedp->ged_wdbp->dbip, argv[0],
LOOKUP_NOISY);
+ struct directory *dp2 = db_lookup(gedp->ged_wdbp->dbip, argv[1],
LOOKUP_NOISY);
+ op_func_ptr of = _analyze_find_processor(gc, DB_OP_INTERSECT,
dp1->d_minor_type, dp2->d_minor_type);
+ if (!of) {
+ bu_vls_sprintf(gedp->ged_result_str, "Unsupported type pairing\n");
+ bu_vls_free(&oname);
+ return GED_ERROR;
+ }
+ clear_obj(gc->gedp, tmpname);
+ ret = (*of)(tmpname, gc->gedp, DB_OP_INTERSECT, argv[0], argv[1]);
+ if (ret == -1) {
+ clear_obj(gc->gedp, tmpname);
+ bu_vls_free(&oname);
+ return GED_ERROR;
+ }
+
+ if (argc > 2) {
+ const char *tmpname2 = "___analyze_cmd_intersect_tmp_obj_2__";
+ for (int i = 2; i < argc; i++) {
+ const char *n1 = tmpname;
+ const char *n2 = argv[i];
+ dp1 = db_lookup(gedp->ged_wdbp->dbip, n1, LOOKUP_NOISY);
+ dp2 = db_lookup(gedp->ged_wdbp->dbip, n2, LOOKUP_NOISY);
+ of = _analyze_find_processor(gc, DB_OP_INTERSECT,
dp1->d_minor_type, dp2->d_minor_type);
+ if (!of) {
+ bu_vls_sprintf(gedp->ged_result_str, "Unsupported type
pairing\n");
+ clear_obj(gc->gedp, tmpname);
+ clear_obj(gc->gedp, tmpname2);
+ bu_vls_free(&oname);
+ return GED_ERROR;
+ }
+ ret = (*of)(tmpname2, gc->gedp, DB_OP_INTERSECT, n1, n2);
+ mv_obj(gc->gedp, tmpname2, tmpname);
+ if (ret == -1) {
+ clear_obj(gc->gedp, tmpname);
+ clear_obj(gc->gedp, tmpname2);
+ bu_vls_free(&oname);
+ return GED_ERROR;
+ }
+ }
+ }
+
+ if (bu_vls_strlen(&oname)) {
+ mv_obj(gc->gedp, tmpname, bu_vls_cstr(&oname));
+ }
+
+ clear_obj(gc->gedp, tmpname);
+
+ bu_vls_sprintf(gedp->ged_result_str, "%ld\n", ret);
+ bu_vls_free(&oname);
+
+ return GED_OK;
+}
+
+extern "C" int
+_analyze_cmd_subtract(void *bs, int argc, const char **argv)
+{
+ const char *usage_string = "analyze [options] subtract [-o out_obj] obj1
obj2 <...>";
+ const char *purpose_string = "Subtract obj2 (and any subsequent objects)
from obj1";
+ if (_analyze_cmd_msgs(bs, argc, argv, usage_string, purpose_string)) {
+ return GED_OK;
+ }
+
+ struct _ged_analyze_info *gc = (struct _ged_analyze_info *)bs;
+ struct ged *gedp = gc->gedp;
+
+ argc--; argv++;
+ if (!argc) {
+ bu_vls_printf(gc->gedp->ged_result_str, "%s\n", usage_string);
+ return GED_ERROR;
+ }
+
+ GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
+ GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);
+
+ /* initialize result */
+ bu_vls_trunc(gedp->ged_result_str, 0);
+
+ // See if we are going to output an object
+ int help = 0;
+ struct bu_vls oname = BU_VLS_INIT_ZERO;
+ struct bu_opt_desc d[3];
+ BU_OPT(d[0], "h", "help", "", NULL, &help, "Print help");
+ BU_OPT(d[1], "o", "output", "name", &bu_opt_vls, &oname, "Specify output
object");
+ BU_OPT_NULL(d[2]);
+
+ int ac = bu_opt_parse(NULL, argc, argv, d);
+ if (help) {
+ bu_vls_printf(gc->gedp->ged_result_str, "%s\n", usage_string);
+ return GED_HELP;
+ }
+ if (ac < 2) {
+ bu_vls_printf(gc->gedp->ged_result_str, "%s\n", usage_string);
+ return GED_HELP;
+ }
+ argc = ac;
+
+ if (bu_vls_strlen(&oname)) {
+ struct directory *dp_out = db_lookup(gedp->ged_wdbp->dbip,
bu_vls_cstr(&oname), LOOKUP_QUIET);
+ if (dp_out != RT_DIR_NULL) {
+ bu_vls_sprintf(gedp->ged_result_str, "specified output object %s
already exists.\n", bu_vls_cstr(&oname));
+ bu_vls_free(&oname);
+ return GED_ERROR;
+ }
+ }
+
+ long ret = 0;
+ const char *tmpname = "___analyze_cmd_subtract_tmp_obj__";
+ struct directory *dp1 = db_lookup(gedp->ged_wdbp->dbip, argv[0],
LOOKUP_NOISY);
+ struct directory *dp2 = db_lookup(gedp->ged_wdbp->dbip, argv[1],
LOOKUP_NOISY);
+ op_func_ptr of = _analyze_find_processor(gc, DB_OP_SUBTRACT,
dp1->d_minor_type, dp2->d_minor_type);
+ if (!of) {
+ bu_vls_sprintf(gedp->ged_result_str, "Unsupported type pairing\n");
+ bu_vls_free(&oname);
+ return GED_ERROR;
+ }
+ clear_obj(gc->gedp, tmpname);
+ ret = (*of)(tmpname, gc->gedp, DB_OP_SUBTRACT, argv[0], argv[1]);
+ if (ret == -1) {
+ clear_obj(gc->gedp, tmpname);
+ bu_vls_free(&oname);
+ return GED_ERROR;
+ }
+
+ if (argc > 2) {
+ const char *tmpname2 = "___analyze_cmd_subtract_tmp_obj_2__";
+ for (int i = 2; i < argc; i++) {
+ const char *n1 = tmpname;
+ const char *n2 = argv[i];
+ dp1 = db_lookup(gedp->ged_wdbp->dbip, n1, LOOKUP_NOISY);
+ dp2 = db_lookup(gedp->ged_wdbp->dbip, n2, LOOKUP_NOISY);
+ of = _analyze_find_processor(gc, DB_OP_SUBTRACT, dp1->d_minor_type,
dp2->d_minor_type);
+ if (!of) {
+ bu_vls_sprintf(gedp->ged_result_str, "Unsupported type
pairing\n");
+ clear_obj(gc->gedp, tmpname);
+ clear_obj(gc->gedp, tmpname2);
+ bu_vls_free(&oname);
+ return GED_ERROR;
+ }
+ ret = (*of)(tmpname2, gc->gedp, DB_OP_SUBTRACT, n1, n2);
+ mv_obj(gc->gedp, tmpname2, tmpname);
+ if (ret == -1) {
+ clear_obj(gc->gedp, tmpname);
+ clear_obj(gc->gedp, tmpname2);
+ bu_vls_free(&oname);
+ return GED_ERROR;
+ }
+ }
+ }
+
+ if (bu_vls_strlen(&oname)) {
+ mv_obj(gc->gedp, tmpname, bu_vls_cstr(&oname));
+ }
+
+ clear_obj(gc->gedp, tmpname);
+
+ bu_vls_sprintf(gedp->ged_result_str, "%ld\n", ret);
+ bu_vls_free(&oname);
+
+ return GED_OK;
+}
+
+extern "C" int
+_analyze_cmd_help(void *bs, int argc, const char **argv)
+{
+ struct _ged_analyze_info *gc = (struct _ged_analyze_info *)bs;
+ if (!argc || !argv || BU_STR_EQUAL(argv[0], "help")) {
+ bu_vls_printf(gc->gedp->ged_result_str, "analyze [options] subcommand
[args]\n");
+ if (gc->gopts) {
+ char *option_help = bu_opt_describe(gc->gopts, NULL);
+ if (option_help) {
+ bu_vls_printf(gc->gedp->ged_result_str, "Options:\n%s\n",
option_help);
+ bu_free(option_help, "help str");
+ }
+ }
+ bu_vls_printf(gc->gedp->ged_result_str, "Available subcommands:\n");
+ const struct bu_cmdtab *ctp = NULL;
+ int ret;
+ const char *helpflag[2];
+ helpflag[1] = PURPOSEFLAG;
+ size_t maxcmdlen = 0;
+ for (ctp = gc->cmds; ctp->ct_name != (char *)NULL; ctp++) {
+ maxcmdlen = (maxcmdlen > strlen(ctp->ct_name)) ? maxcmdlen :
strlen(ctp->ct_name);
+ }
+ for (ctp = gc->cmds; ctp->ct_name != (char *)NULL; ctp++) {
+ bu_vls_printf(gc->gedp->ged_result_str, " %s%*s", ctp->ct_name,
(int)(maxcmdlen - strlen(ctp->ct_name)) + 2, " ");
+ if (!BU_STR_EQUAL(ctp->ct_name, "help")) {
+ helpflag[0] = ctp->ct_name;
+ bu_cmd(gc->cmds, 2, helpflag, 0, (void *)gc, &ret);
+ } else {
+ bu_vls_printf(gc->gedp->ged_result_str, "print help and
exit\n");
+ }
+ }
+ } else {
+ int ret;
+ const char **helpargv = (const char **)bu_calloc(argc+1, sizeof(char
*), "help argv");
+ helpargv[0] = argv[0];
+ helpargv[1] = HELPFLAG;
+ for (int i = 1; i < argc; i++) {
+ helpargv[i+1] = argv[i];
+ }
+ bu_cmd(gc->cmds, argc+1, helpargv, 0, (void *)gc, &ret);
+ bu_free(helpargv, "help argv");
+ return ret;
+ }
+
+ return GED_OK;
+}
+
+
+const struct bu_cmdtab _analyze_cmds[] = {
+ { "summarize", _analyze_cmd_summarize},
+ { "intersect", _analyze_cmd_intersect},
+ { "subtract", _analyze_cmd_subtract},
+ { (char *)NULL, NULL}
+ };
+
+
+extern "C" int
+ged_analyze_core(struct ged *gedp, int argc, const char *argv[])
+{
+ int help = 0;
+ struct _ged_analyze_info *gc = _analyze_info_create();
+ gc->gedp = gedp;
+ gc->cmds = _analyze_cmds;
+
+ // Sanity
+ if (UNLIKELY(!gedp || !argc || !argv)) {
+ _analyze_info_destroy(gc);
+ return GED_ERROR;
+ }
+
+ // Clear results
+ bu_vls_trunc(gedp->ged_result_str, 0);
+
+ // See if we have any high level options set
+ struct bu_opt_desc d[3];
+ BU_OPT(d[0], "h", "help", "", NULL, &help, "Print help");
+ BU_OPT(d[1], "v", "verbose", "", NULL, &gc->verbosity, "Verbose output");
+ BU_OPT_NULL(d[2]);
+
+ gc->gopts = d;
+
+ if (argc == 1) {
+ _analyze_cmd_help(gc, 0, NULL);
+ _analyze_info_destroy(gc);
+ return GED_OK;
+ }
+
+ // High level options are only defined prior to the subcommand
+ int cmd_pos = -1;
+ for (int i = 1; i < argc; i++) {
+ if (bu_cmd_valid(_analyze_cmds, argv[i]) == BRLCAD_OK) {
+ cmd_pos = i;
+ break;
+ }
+ }
+
+ int acnt = (cmd_pos >= 0) ? cmd_pos : argc;
+
+ bu_opt_parse(NULL, acnt, argv, d);
+
+ if (help) {
+ if (cmd_pos >= 0) {
+ argc = argc - cmd_pos;
+ argv = &argv[cmd_pos];
+ _analyze_cmd_help(gc, argc, argv);
+ } else {
+ _analyze_cmd_help(gc, 0, NULL);
+ }
+ _analyze_info_destroy(gc);
+ return GED_OK;
+ }
+
+
+ // Jump the processing past any options specified. If we don't have a
+ // subcommand, assume all args are geometry objects and the command mode is
+ // summarize. This will get us the old behavior, except in the case where
+ // we happen to have an object with a name that matches a subcommand of
+ // analyze. In that case, the full "analyze summarize objname" is needed.
+ const char *scmd = "summarize";
+ if (cmd_pos != -1) {
+ argc = argc - cmd_pos;
+ argv = &argv[cmd_pos];
+ } else {
+ argv[0] = scmd;
+ }
+
+ int ret;
+ if (bu_cmd(_analyze_cmds, argc, argv, 0, (void *)gc, &ret) == BRLCAD_OK) {
+ _analyze_info_destroy(gc);
+ return ret;
+ } else {
+ bu_vls_printf(gedp->ged_result_str, "subcommand %s not defined",
argv[0]);
+ }
+
+ _analyze_info_destroy(gc);
+ return GED_ERROR;
+}
+
+// Local Variables:
+
+#ifdef GED_PLUGIN
+#include "../include/plugin.h"
+extern "C" {
+ struct ged_cmd_impl analyze_cmd_impl = { "analyze", ged_analyze_core,
GED_CMD_DEFAULT };
+ const struct ged_cmd analyze_cmd = { &analyze_cmd_impl };
+
+ const struct ged_cmd *analyze_cmds[] = { &analyze_cmd, NULL };
+
+ static const struct ged_plugin pinfo = { GED_API, analyze_cmds, 1 };
+
+ COMPILER_DLLEXPORT const struct ged_plugin *ged_plugin_info()
+ {
+ return &pinfo;
+ }
+}
+#endif
+
+// Local Variables:
+// tab-width: 8
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: t
+// c-file-style: "stroustrup"
+// End:
+// ex: shiftwidth=4 tabstop=8
+
Copied: brlcad/trunk/src/libged/analyze/arb8.cpp (from rev 77221,
brlcad/branches/analyze_cmd/src/libged/analyze/arb8.cpp)
===================================================================
--- brlcad/trunk/src/libged/analyze/arb8.cpp (rev 0)
+++ brlcad/trunk/src/libged/analyze/arb8.cpp 2020-09-25 13:41:24 UTC (rev
77222)
@@ -0,0 +1,209 @@
+/* A R B 8 . C P P
+ * BRL-CAD
+ *
+ * Copyright (c) 2020 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * 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.
+ *
+ * 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 file; see the file named COPYING for more
+ * information.
+ */
+/** @file arb8.cpp
+ *
+ * Brief description
+ *
+ */
+
+#include "common.h"
+
+#include "vmath.h"
+
+#include "bg/polygon.h"
+#include "rt/arb_edit.h"
+#include "rt/geom.h"
+#include "ged/defines.h"
+#include "../ged_private.h"
+#include "./ged_analyze.h"
+
+/* edge definition array */
+static const int nedge[5][24] = {
+ {0, 1, 1, 2, 2, 0, 0, 3, 3, 2, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1}, /* ARB4 */
+ {0, 1, 1, 2, 2, 3, 0, 3, 0, 4, 1, 4, 2, 4, 3, 4, -1, -1, -1, -1, -1, -1,
-1, -1}, /* ARB5 */
+ {0, 1, 1, 2, 2, 3, 0, 3, 0, 4, 1, 4, 2, 5, 3, 5, 4, 5, -1, -1, -1, -1, -1,
-1}, /* ARB6 */
+ {0, 1, 1, 2, 2, 3, 0, 3, 0, 4, 3, 4, 1, 5, 2, 6, 4, 5, 5, 6, 4, 6, -1,
-1}, /* ARB7 */
+ {0, 1, 1, 2, 2, 3, 0, 3, 0, 4, 4, 5, 1, 5, 5, 6, 6, 7, 4, 7, 3, 7, 2, 6},
/* ARB8 */
+};
+
+/* ARB face printout array */
+static const int prface[5][6] = {
+ {123, 124, 234, 134, -111, -111}, /* ARB4 */
+ {1234, 125, 235, 345, 145, -111}, /* ARB5 */
+ {1234, 2365, 1564, 512, 634, -111}, /* ARB6 */
+ {1234, 567, 145, 2376, 1265, 4375}, /* ARB7 */
+ {1234, 5678, 1584, 2376, 1265, 4378}, /* ARB8 */
+};
+
+void
+analyze_edge(struct ged *gedp, const int edge, const struct rt_arb_internal
*arb,
+ const int type, row_t *row)
+{
+ int a = nedge[type][edge*2];
+ int b = nedge[type][edge*2+1];
+
+ if (b == -1) {
+ row->nfields = 0;
+ return;
+ }
+
+ row->nfields = 2;
+ row->fields[0].nchars = sprintf(row->fields[0].buf, "%d%d", a + 1, b + 1);
+ row->fields[1].nchars = sprintf(row->fields[1].buf, "%10.8f",
+ DIST_PNT_PNT(arb->pt[a],
arb->pt[b])*gedp->ged_wdbp->dbip->dbi_base2local);
+}
+
+
+
+void
+analyze_arb8(struct ged *gedp, const struct rt_db_internal *ip)
+{
+ int i, type;
+ int cgtype; /* COMGEOM arb type: # of vertices */
+ table_t table; /* holds table data from child functions */
+ fastf_t tot_vol = 0.0, tot_area = 0.0;
+ point_t center_pt = VINIT_ZERO;
+ struct poly_face face = POLY_FACE_INIT_ZERO;
+ struct rt_arb_internal earb;
+ struct rt_arb_internal *arb = (struct rt_arb_internal *)ip->idb_ptr;
+ const int arb_faces[5][24] = rt_arb_faces;
+ RT_ARB_CK_MAGIC(arb);
+
+ /* find the specific arb type, in GIFT order. */
+ if ((cgtype = rt_arb_std_type(ip, &gedp->ged_wdbp->wdb_tol)) == 0) {
+ bu_vls_printf(gedp->ged_result_str, "analyze_arb: bad ARB\n");
+ return;
+ }
+
+ type = cgtype - 4;
+
+ /* to get formatting correct, we need to collect the actual string
+ * lengths for each field BEFORE we start printing a table (fields
+ * are allowed to overflow the stated printf field width) */
+
+ /* TABLE 1 =========================================== */
+ /* analyze each face, use center point of arb for reference */
+ rt_arb_centroid(¢er_pt, ip);
+
+ /* allocate pts array, maximum 4 verts per arb8 face */
+ face.pts = (point_t *)bu_calloc(4, sizeof(point_t), "analyze_arb8: pts");
+ /* allocate table rows, 12 rows needed for arb8 edges */
+ table.rows = (row_t *)bu_calloc(12, sizeof(row_t), "analyze_arb8: rows");
+
+ table.nrows = 0;
+ for (face.npts = 0, i = 0; i < 6; face.npts = 0, i++) {
+ int a, b, c, d; /* 4 indices to face vertices */
+
+ a = arb_faces[type][i*4+0];
+ b = arb_faces[type][i*4+1];
+ c = arb_faces[type][i*4+2];
+ d = arb_faces[type][i*4+3];
+
+ if (a == -1) {
+ table.rows[i].nfields = 0;
+ continue;
+ }
+
+ /* find plane eqn for this face */
+ if (bn_make_plane_3pnts(face.plane_eqn, arb->pt[a], arb->pt[b],
arb->pt[c], &gedp->ged_wdbp->wdb_tol) < 0) {
+ bu_vls_printf(gedp->ged_result_str, "| %d%d%d%d | ***NOT A
PLANE*** |\n",
+ a+1, b+1, c+1, d+1);
+ /* this row has 1 special fields */
+ table.rows[i].nfields = NOT_A_PLANE;
+ continue;
+ }
+
+ ADD_PT(face, arb->pt[a]);
+ ADD_PT(face, arb->pt[b]);
+ ADD_PT(face, arb->pt[c]);
+ ADD_PT(face, arb->pt[d]);
+
+ /* The plane equations returned by bn_make_plane_3pnts above do
+ * not necessarily point outward. Use the reference center
+ * point for the arb and reverse direction for any errant planes.
+ * This corrects the output rotation, fallback angles so that
+ * they always give the outward pointing normal vector. */
+ if (DIST_PNT_PLANE(center_pt, face.plane_eqn) > 0.0) {
+ HREVERSE(face.plane_eqn, face.plane_eqn);
+ }
+
+ snprintf(face.label, sizeof(face.label), "%d", prface[type][i]);
+
+ analyze_poly_face(gedp, &face, &(table.rows[i]));
+ tot_area += face.area;
+ table.nrows++;
+ }
+
+ /* and print it */
+ print_faces_table(gedp, &table);
+
+ /* TABLE 2 =========================================== */
+ /* analyze each edge */
+
+ /* blank line following previous table */
+ bu_vls_printf(gedp->ged_result_str, "\n");
+
+ /* set up the records for arb4's and arb6's */
+ earb = *arb; /* struct copy */
+ if (cgtype == 4) {
+ VMOVE(earb.pt[3], earb.pt[4]);
+ } else if (cgtype == 6) {
+ VMOVE(earb.pt[5], earb.pt[6]);
+ }
+
+ table.nrows = 0;
+ for (i = 0; i < 12; i++) {
+ analyze_edge(gedp, i, &earb, type, &(table.rows[i]));
+ if (nedge[type][i*2] == -1) {
+ break;
+ }
+ table.nrows += 1;
+ }
+
+ print_edges_table(gedp, &table);
+
+ /* TABLE 3 =========================================== */
+ /* find the volume - break arb8 into 6 arb4s */
+
+ if (OBJ[ID_ARB8].ft_volume)
+ OBJ[ID_ARB8].ft_volume(&tot_vol, ip);
+
+ print_volume_table(gedp,
+ tot_vol
+ * gedp->ged_wdbp->dbip->dbi_base2local
+ * gedp->ged_wdbp->dbip->dbi_base2local
+ * gedp->ged_wdbp->dbip->dbi_base2local,
+ tot_area
+ * gedp->ged_wdbp->dbip->dbi_base2local
+ * gedp->ged_wdbp->dbip->dbi_base2local,
+ tot_vol/GALLONS_TO_MM3
+ );
+
+ bu_free((char *)face.pts, "analyze_arb8: pts");
+ bu_free((char *)table.rows, "analyze_arb8: rows");
+}
+// Local Variables:
+// tab-width: 8
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: t
+// c-file-style: "stroustrup"
+// End:
+// ex: shiftwidth=4 tabstop=8
Copied: brlcad/trunk/src/libged/analyze/arbn.cpp (from rev 77221,
brlcad/branches/analyze_cmd/src/libged/analyze/arbn.cpp)
===================================================================
--- brlcad/trunk/src/libged/analyze/arbn.cpp (rev 0)
+++ brlcad/trunk/src/libged/analyze/arbn.cpp 2020-09-25 13:41:24 UTC (rev
77222)
@@ -0,0 +1,112 @@
+/* A R B N . C P P
+ * BRL-CAD
+ *
+ * Copyright (c) 2020 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * 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.
+ *
+ * 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 file; see the file named COPYING for more
+ * information.
+ */
+/** @file arbn.cpp
+ *
+ * Brief description
+ *
+ */
+
+#include "common.h"
+
+#include "vmath.h"
+
+#include "rt/geom.h"
+#include "ged/defines.h"
+#include "../ged_private.h"
+#include "./ged_analyze.h"
+
+void
+analyze_arbn(struct ged *gedp, const struct rt_db_internal *ip)
+{
+ size_t i;
+ fastf_t tot_vol = 0.0, tot_area = 0.0;
+ table_t table;
+ struct poly_face *faces;
+ struct bu_vls tmpstr = BU_VLS_INIT_ZERO;
+ struct rt_arbn_internal *aip = (struct rt_arbn_internal *)ip->idb_ptr;
+ size_t *npts = (size_t *)bu_calloc(aip->neqn, sizeof(size_t),
"analyze_arbn: npts");
+ point_t **tmp_pts = (point_t **)bu_calloc(aip->neqn, sizeof(point_t *),
"analyze_arbn: tmp_pts");
+ plane_t *eqs= (plane_t *)bu_calloc(aip->neqn, sizeof(plane_t),
"analyze_arbn: eqs");
+
+ /* allocate array of face structs */
+ faces = (struct poly_face *)bu_calloc(aip->neqn, sizeof(struct poly_face),
"analyze_arbn: faces");
+ for (i = 0; i < aip->neqn; i++) {
+ HMOVE(faces[i].plane_eqn, aip->eqn[i]);
+ VUNITIZE(faces[i].plane_eqn);
+ /* allocate array of pt structs, max number of verts per faces = (# of
faces) - 1 */
+ faces[i].pts = (point_t *)bu_calloc(aip->neqn - 1, sizeof(point_t),
"analyze_arbn: pts");
+ tmp_pts[i] = faces[i].pts;
+ HMOVE(eqs[i], faces[i].plane_eqn);
+ }
+ /* allocate table rows, 1 row per plane eqn */
+ table.rows = (row_t *)bu_calloc(aip->neqn, sizeof(row_t), "analyze_arbn:
rows");
+ table.nrows = aip->neqn;
+
+ bg_3d_polygon_make_pnts_planes(npts, tmp_pts, aip->neqn, (const plane_t
*)eqs);
+
+ for (i = 0; i < aip->neqn; i++) {
+ vect_t tmp;
+ bu_vls_sprintf(&tmpstr, "%4zu", i);
+ snprintf(faces[i].label, sizeof(faces[i].label), "%s",
bu_vls_addr(&tmpstr));
+
+ faces[i].npts = npts[i];
+
+ /* calculate surface area */
+ analyze_poly_face(gedp, &faces[i], &table.rows[i]);
+ tot_area += faces[i].area;
+
+ /* calculate volume */
+ VSCALE(tmp, faces[i].plane_eqn, faces[i].area);
+ tot_vol += VDOT(faces[i].pts[0], tmp);
+ }
+ tot_vol /= 3.0;
+
+ print_faces_table(gedp, &table);
+ print_volume_table(gedp,
+ tot_vol
+ * gedp->ged_wdbp->dbip->dbi_base2local
+ * gedp->ged_wdbp->dbip->dbi_base2local
+ * gedp->ged_wdbp->dbip->dbi_base2local,
+ tot_area
+ * gedp->ged_wdbp->dbip->dbi_base2local
+ * gedp->ged_wdbp->dbip->dbi_base2local,
+ tot_vol/GALLONS_TO_MM3
+ );
+
+ for (i = 0; i < aip->neqn; i++) {
+ bu_free((char *)faces[i].pts, "analyze_arbn: pts");
+ }
+ bu_free((char *)faces, "analyze_arbn: faces");
+ bu_free((char *)table.rows, "analyze_arbn: rows");
+ bu_free((char *)tmp_pts, "analyze_arbn: tmp_pts");
+ bu_free((char *)npts, "analyze_arbn: npts");
+ bu_free((char *)eqs, "analyze_arbn: eqs");
+ bu_vls_free(&tmpstr);
+}
+
+
+// Local Variables:
+// tab-width: 8
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: t
+// c-file-style: "stroustrup"
+// End:
+// ex: shiftwidth=4 tabstop=8
Copied: brlcad/trunk/src/libged/analyze/ars.cpp (from rev 77221,
brlcad/branches/analyze_cmd/src/libged/analyze/ars.cpp)
===================================================================
--- brlcad/trunk/src/libged/analyze/ars.cpp (rev 0)
+++ brlcad/trunk/src/libged/analyze/ars.cpp 2020-09-25 13:41:24 UTC (rev
77222)
@@ -0,0 +1,138 @@
+/* A R S . C P P
+ * BRL-CAD
+ *
+ * Copyright (c) 2020 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * 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.
+ *
+ * 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 file; see the file named COPYING for more
+ * information.
+ */
+/** @file ars.cpp
+ *
+ * Brief description
+ *
+ */
+
+#include "common.h"
+
+#include "vmath.h"
+
+#include "rt/geom.h"
+#include "ged/defines.h"
+#include "../ged_private.h"
+#include "./ged_analyze.h"
+
+#define ARS_PT(ii, jj) (&arip->curves[i+(ii)][(j+(jj))*ELEMENTS_PER_VECT])
+
+void
+analyze_ars(struct ged *gedp, const struct rt_db_internal *ip)
+{
+ size_t i, j, k;
+ size_t nfaces = 0;
+ fastf_t tot_area = 0.0, tot_vol = 0.0;
+ table_t table;
+ plane_t old_plane = HINIT_ZERO;
+ struct bu_vls tmpstr = BU_VLS_INIT_ZERO;
+ struct poly_face face = POLY_FACE_INIT_ZERO;
+ struct rt_ars_internal *arip = (struct rt_ars_internal *)ip->idb_ptr;
+ RT_ARS_CK_MAGIC(arip);
+
+ /* allocate pts array, max 3 pts per triangular face */
+ face.pts = (point_t *)bu_calloc(3, sizeof(point_t), "analyze_ars: pts");
+ /* allocate table rows, probably overestimating the number of rows needed
*/
+ table.rows = (row_t *)bu_calloc((arip->ncurves - 1) * 2 *
arip->pts_per_curve, sizeof(row_t), "analyze_ars: rows");
+
+ k = arip->pts_per_curve - 2;
+ for (i = 0; i < arip->ncurves - 1; i++) {
+ int double_ended = k != 1 &&
VEQUAL(&arip->curves[i][ELEMENTS_PER_VECT], &arip->curves[i][k *
ELEMENTS_PER_VECT]);
+
+ for (j = 0; j < arip->pts_per_curve; j++) {
+ vect_t tmp;
+
+ if (double_ended && i != 0 && (j == 0 || j == k || j ==
arip->pts_per_curve - 1)) continue;
+
+ /* first triangular face, make sure it's not a duplicate */
+ if (bn_make_plane_3pnts(face.plane_eqn, ARS_PT(0, 0), ARS_PT(1, 1),
ARS_PT(0, 1), &gedp->ged_wdbp->wdb_tol) == 0
+ && !HEQUAL(old_plane, face.plane_eqn)) {
+ HMOVE(old_plane, face.plane_eqn);
+ ADD_PT(face, ARS_PT(0, 1));
+ ADD_PT(face, ARS_PT(0, 0));
+ ADD_PT(face, ARS_PT(1, 1));
+
+ bu_vls_sprintf(&tmpstr, "%zu%zu", i, j);
+ snprintf(face.label, sizeof(face.label), "%s",
bu_vls_addr(&tmpstr));
+
+ /* surface area */
+ analyze_poly_face(gedp, &face, &(table.rows[nfaces]));
+ tot_area += face.area;
+
+ /* volume */
+ VSCALE(tmp, face.plane_eqn, face.area);
+ tot_vol += fabs(VDOT(face.pts[0], tmp));
+
+ face.npts = 0;
+ nfaces++;
+ }
+
+ /* second triangular face, make sure it's not a duplicate */
+ if (bn_make_plane_3pnts(face.plane_eqn, ARS_PT(1, 0), ARS_PT(1, 1),
ARS_PT(0, 0), &gedp->ged_wdbp->wdb_tol) == 0
+ && !HEQUAL(old_plane, face.plane_eqn)) {
+ HMOVE(old_plane, face.plane_eqn);
+ ADD_PT(face, ARS_PT(1, 0));
+ ADD_PT(face, ARS_PT(0, 0));
+ ADD_PT(face, ARS_PT(1, 1));
+
+ bu_vls_sprintf(&tmpstr, "%zu%zu", i, j);
+ snprintf(face.label, sizeof(face.label), "%s",
bu_vls_addr(&tmpstr));
+
+ analyze_poly_face(gedp, &face, &table.rows[nfaces]);
+ tot_area += face.area;
+
+ VSCALE(tmp, face.plane_eqn, face.area);
+ tot_vol += fabs(VDOT(face.pts[0], tmp));
+
+ face.npts = 0;
+ nfaces++;
+ }
+ }
+ }
+ tot_vol /= 3.0;
+ table.nrows = nfaces;
+
+ print_faces_table(gedp, &table);
+ print_volume_table(gedp,
+ tot_vol
+ * gedp->ged_wdbp->dbip->dbi_base2local
+ * gedp->ged_wdbp->dbip->dbi_base2local
+ * gedp->ged_wdbp->dbip->dbi_base2local,
+ tot_area
+ * gedp->ged_wdbp->dbip->dbi_base2local
+ * gedp->ged_wdbp->dbip->dbi_base2local,
+ tot_vol/GALLONS_TO_MM3
+ );
+
+ bu_free((char *)face.pts, "analyze_ars: pts");
+ bu_free((char *)table.rows, "analyze_ars: rows");
+ bu_vls_free(&tmpstr);
+}
+
+
+
+// Local Variables:
+// tab-width: 8
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: t
+// c-file-style: "stroustrup"
+// End:
+// ex: shiftwidth=4 tabstop=8
Copied: brlcad/trunk/src/libged/analyze/ged_analyze.h (from rev 77221,
brlcad/branches/analyze_cmd/src/libged/analyze/ged_analyze.h)
===================================================================
--- brlcad/trunk/src/libged/analyze/ged_analyze.h
(rev 0)
+++ brlcad/trunk/src/libged/analyze/ged_analyze.h 2020-09-25 13:41:24 UTC
(rev 77222)
@@ -0,0 +1,157 @@
+/* G E D _ A N A L Y Z E . H
+ * BRL-CAD
+ *
+ * Copyright (c) 2020 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * 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.
+ *
+ * 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 file; see the file named COPYING for more
+ * information.
+ */
+/** @file ged_cg.h
+ *
+ * Brief description
+ *
+ */
+
+#ifndef LIBGED_ANALYZE_GED_PRIVATE_H
+#define LIBGED_ANALYZE_GED_PRIVATE_H
+
+#include "common.h"
+
+#include "vmath.h"
+#include "rt/op.h"
+#include "./ged/defines.h"
+
+__BEGIN_DECLS
+
+/* Conversion factor for Gallons to cubic millimeters */
+#define GALLONS_TO_MM3 3785411.784
+#define NOT_A_PLANE -1
+
+#define FBUFSIZ 100
+#define NFIELDS 9
+
+typedef struct row_field
+{
+ int nchars;
+ char buf[FBUFSIZ];
+} field_t;
+
+typedef struct table_row
+{
+ int nfields;
+ field_t fields[NFIELDS];
+} row_t;
+
+typedef struct table
+{
+ int nrows;
+ row_t *rows;
+} table_t;
+
+#define ADD_PT(face, pt) do { VMOVE((face).pts[(face).npts], (pt));
(face).npts++; } while (0)
+
+/* contains information used to analyze a polygonal face */
+struct poly_face
+{
+ char label[5];
+ size_t npts;
+ point_t *pts;
+ plane_t plane_eqn;
+ fastf_t area;
+};
+
+GED_EXPORT extern void
+print_edges_table(struct ged *gedp, table_t *table);
+
+GED_EXPORT extern void
+print_faces_table(struct ged *gedp, table_t *table);
+
+GED_EXPORT extern void
+print_volume_table(
+ struct ged *gedp,
+ const fastf_t tot_vol,
+ const fastf_t tot_area,
+ const fastf_t tot_gallons
+ );
+
+#define POLY_FACE_INIT_ZERO { { 0, 0, 0, 0, 0 }, 0, NULL, HINIT_ZERO, 0.0 }
+
+GED_EXPORT extern void
+analyze_poly_face(struct ged *gedp, struct poly_face *face, row_t *row);
+
+GED_EXPORT extern void
+print_faces_table(struct ged *gedp, table_t *table);
+
+
+GED_EXPORT extern void
+analyze_arb8(struct ged *gedp, const struct rt_db_internal *ip);
+
+GED_EXPORT extern void
+analyze_arbn(struct ged *gedp, const struct rt_db_internal *ip);
+
+GED_EXPORT extern void
+analyze_ars(struct ged *gedp, const struct rt_db_internal *ip);
+
+GED_EXPORT extern void
+analyze_superell(struct ged *gedp, const struct rt_db_internal *ip);
+
+GED_EXPORT extern void
+analyze_sketch(struct ged *gedp, const struct rt_db_internal *ip);
+
+GED_EXPORT extern void
+analyze_general(struct ged *gedp, const struct rt_db_internal *ip);
+
+
+
+/**
+ * Functions for performing union/intersection/subtraction analysis operations
+ * on various type combinations.
+ *
+ * output_obj is optional. If non-NULL, it is the name used to produce a new
+ * geometry database object with the results of the operation (if any).
+ *
+ * The trivial case would be an op_vol_vol that takes two csg solids or combs
+ * and returns a new implicit comb with them unioned (always), intersected (if
+ * there is overlap) or subtracted (if there is overlap).
+ *
+ * More interesting are cases like op_pnts_vol that will produce new pnts
+ * objects based on boolean set operation analysis.
+ */
+
+typedef long (*op_func_ptr)(const char *, struct ged *, db_op_t, const char *,
const char *);
+
+GED_EXPORT extern long
+op_pnts_vol(
+ const char *output_obj,
+ struct ged *gedp,
+ db_op_t op,
+ const char *pnt_obj,
+ const char *vol_obj
+ );
+
+
+__END_DECLS
+
+#endif /* LIBGED_ANALYZE_GED_PRIVATE_H */
+
+/** @} */
+/*
+ * Local Variables:
+ * mode: C
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */
Copied: brlcad/trunk/src/libged/analyze/op_pnts_vol.cpp (from rev 77221,
brlcad/branches/analyze_cmd/src/libged/analyze/op_pnts_vol.cpp)
===================================================================
--- brlcad/trunk/src/libged/analyze/op_pnts_vol.cpp
(rev 0)
+++ brlcad/trunk/src/libged/analyze/op_pnts_vol.cpp 2020-09-25 13:41:24 UTC
(rev 77222)
@@ -0,0 +1,427 @@
+/* O P _ P N T S _ V O L . C P P
+ * BRL-CAD
+ *
+ * Copyright (c) 2020 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * 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.
+ *
+ * This library is distributed in the hope that it will be useful, but
@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits