Home > User Guide > Display and User Input
PHL V5
The Precise Hidden Line Removal V5 Component (PHL V5), calculates hidden line data and draws hidden line representations of the model. The data is stored on the model as attributes.
PHL V5 also creates silhouette edges for nonplanar faces and provides sets of classified PHL V5 segments for all regular edges and silhouette edges in an ACIS model. Bodies can be manifold, nonmanifold, or open shelled. Wireframe data is ignored. Self-intersecting bodies and sets of intersecting bodies are not supported; however no check is made for this condition.
Topics include:
Model Analysis
PHL V5 analyzes the model from a particular viewpoint, creating a line-segment representation of the model. For each segment, PHL V5 calculates parameter range values and assigns status and visibility information.
The status information is either:
- Outer
- A silhouette edge.
- Inner
- A true edge.
The visibility information is one of the following:
- Visible
- An edge that has no solid material or edges in front of it from the current perspective. For example, the front edges of a cube are visible.
- Hidden
- An edge that is obscured by material in the current perspective. For example, in a slightly non-orthogonal view of a cube, portions of the rear edges are hidden.
- Occluded
- An edge that is obscured by another edge. For example, in a 45-degree view of a cube, the rear vertical edge is occluded by the front vertical edge. When viewing a visible edge (solid line) overlaying an occluded edge (dashed line), the visual confusion is reduced by removing the occluded line.
- Smooth Visible
- An edge that is visible and has the condition of being smooth. Edges are defined as being smooth when their adjacent surfaces meet tangentially.
- Smooth Hidden
- An edge that is hidden and the condition of being smooth.
Hidden Line Data
Output of the PHL V5 programming interface is a linked list of PHLV5_EDGEs. Each of these edges contains pointers to modeling data, a pointer to a list of PHLV5_SEGMENTs and a pointer to a polyline representing the edge in 3D space. The polyline or the modeling data can be used to display the hidden line view in an end user application, however it is recommended that the polyline data is used as input to your display system. The modeling data can be queried by calling the GetCurve member function of the PHLV5_EDGE but this causes a performance penalty when the edge is a silhouette line. The PHLV5_SEGMENT contains information about each section of the edge, including its visibility and parameter range data.
Note: The scheme command phlv5:compute can be set to render the polyline data or the modeling curve returned from the PHLV5_EDGE To render the polyline data, set this global ACIS option to false (option:set "phlv5_render_curves" #f).
PHLV5_EDGEs, PHLV5_SEGMENTs, and attributes can be used to maintain persistence of the PHL V5 output. PHL V5 has the ability to store multiple lists or views of output data.
PHL V5 Options
Options for hidden line removal are supplied to APIs via the class phlv5_options. Use the "set" and "get" methods to build the object with the desired option settings, then pass this as the last argument to api_phlv5_compute.
The options that can be modified include:
- Surface approximation
- Resolution
- Sag resolution
- Smooth line cosine
- Self-calibrate resolutions
PHL V5 C++ Example
The following C++ code snippet illustrates how to parse and use the output display data.
// system include files
#include <stdlib.h>
#include <string.h>
// base header files
#include "position.hxx"
// kernel header files
#include "acis.hxx"
#include "api.hxx"
#include "kernapi.hxx"
#include "body.hxx"
#include "transfrm.hxx"
#include "curdef.hxx"
// phlv5 header files
#include "phlv5_api.hxx"
#include "phlv5_opts.hxx"
#include "phlv5_edge.hxx"
#include "phlv5_seg.hxx"
// error function
static FILE *errorFile;
void outcome_check(outcome res, char* string)
{
if (res.ok())
return;
fprintf(errorFile,"%s: %s\n",string,find_err_mess(res.error_number()));
}
void main()
{
// Set the appropriate path
errorFile = fopen("error.txt","w");
if (!errorFile)
return;
// Open SAT file; to run this you need a SAT file with this name in your working directory
FILE *helpFile = fopen("sample.sat", "r");
if (!helpFile)
return;
// Initialize the modeler and the precise hidden line component
outcome res = api_start_modeller(0);
outcome_check(res, "error initializing modeler");
if (!res.ok())
return;
res = api_initialize_hidden_line_removal();
outcome_check(res, "error initializing hidden line component");
if (!res.ok())
return;
// Get the body from the SAT file
ENTITY_LIST bodyList;
res = api_restore_entity_list(helpFile, TRUE, bodyList);
outcome_check(res, "error restoring bodyList");
fclose(helpFile);
// If we have a good SAT file; than do a precise hidden line
if (res.ok())
{
// Set up viewing data
SPAposition eyePos(0.0, 0.0, 1e10); // eye position
SPAposition targetPos(0.0, 0.0, 0.0); // target position
logical pFlag = 0; // perspective/parallel view
// Token's can be passed into the API to inact persistance of the phl data; 0 means no persistance
int token = 0;
// Specify PHLV5 options ...
logical self_calibrate_resolutions = TRUE; // this is default; we will calculate the general and
// sag resolutions for you based on model extents
double smooth_cosine = 0.95; // default is 0.00 which means do not detect any smooth lines
// we wish to pick-up smooth lines so use this value as the cosine
// of the angle between the two edges
logical use_surface_approximations = TRUE; // this is default; we use the surface approximations to speed
// up the hidden line algorithm
phlv5_options *phlv5Opt = new phlv5_options();
phlv5Opt->set_self_calibrate(self_calibrate_resolutions);
phlv5Opt->set_smooth_cosine(smooth_cosine);
phlv5Opt->set_self_approx_surface(use_surface_approximations);
// Note: the "set_hidden_line_style" is not an option used by the C++ API
// Calculate the precise hidden line
ENTITY_LIST edgeList;
res = api_phlv5_compute(bodyList, token, eyePos, targetPos, pFlag, edgeList, phlv5Opt);
outcome_check(res,"error computing phlv5");
ACIS_DELETE phlv5Opt;
// If the result is OK, anaylize the output
if (res.ok())
{
// Open up a file pointer to dump hidden line data
FILE* dfp = fopen("hidden_line_data.txt", "w");
// Loop through the PHLV5_EDGE(s)
for (int edge_index = 0; edge_index < edgeList.count(); edge_index++)
{
PHLV5_EDGE* phlv5Edge = (PHLV5_EDGE*) edgeList[edge_index];
// Process the segment data
ENTITY_LIST segList;
phlv5Edge->GetSegmentList(segList);
// Even though we loop here, on the current version of phlv5 there is only
// one segment per edge. Please write your application to loop however.
for (int seg_index = 0; seg_index < segList.count(); seg_index++)
{
PHLV5_SEGMENT* seg = (PHLV5_SEGMENT*) segList[seg_index];
if (seg == 0)
continue;
fprintf(dfp, "Segment: \n");
// Visibility Information ...
fprintf(dfp, "Visibility: ");
if (seg->visibility() == PHLV5_SEGMENT_VIS)
fprintf(dfp, "Visible\n");
if (seg->visibility() == PHLV5_SEGMENT_OCC)
fprintf(dfp, "Occluded\n");
if (seg->visibility() == PHLV5_SEGMENT_HID)
fprintf(dfp, "Hidden\n");
if (seg->visibility() == PHLV5_SEGMENT_VIS_SMOOTH)
fprintf(dfp, "Visible Smooth\n");
if (seg->visibility() == PHLV5_SEGMENT_HID_SMOOTH)
fprintf(dfp, "Hidden Smooth\n");
// State Information ...
fprintf(dfp, "In/Out Bit: ");
if (seg->state() == PHLV5_SEGMENT_INN)
fprintf(dfp, "In\n");
if (seg->state() == PHLV5_SEGMENT_OUT)
fprintf(dfp, "Out\n");
// Curve information; only call the curve if you absolutely need
// a true modeling curve. This is a performance hit if this phlv5 edge
// happens to be a silhouette line. Use the polyline data for quick and
// fast rendering.
CURVE* curvePtr = phlv5Edge->GetCurve();
// First make sure we did not return a NULL curve
if (curvePtr != NULL)
{
// Get the visibility parameters - this is the start
// and end of the visibility segment of the curve
SPAparameter start_parm = seg->start_pt();
SPAparameter end_parm = seg->end_pt();
// Check for a reversed edge
if (phlv5Edge->GetSense() > 0)
{
SPAparameter temp = - start_parm;
start_parm = - end_parm;
end_parm = temp;
}
// Evaluate the curve at the start, middle and end of
// it's visibility
curve const &curve = curvePtr->equation();
SPAposition start = curve.eval_position(start_parm);
SPAposition middle = curve.eval_position((start_parm + end_parm) / 2.0);
SPAposition end = curve.eval_position(end_parm);
// Apply any body transformation
BODY* bodyPtr = phlv5Edge->GetBody();
SPAtransf sketch_transform;
if (bodyPtr->transform())
sketch_transform = bodyPtr->transform()->transform();
start *= sketch_transform;
middle *= sketch_transform;
end *= sketch_transform;
// Remember these positions are in world coordinates; you will need to have the view of your
// display set
// to the same view that the api_phlv5_compute received as a calculation view
fprintf(dfp, "Curve evaluation positions: \n");
fprintf(dfp, "Start position: %lf %lf %lf\n", start.x(), start.y(), start.z());
fprintf(dfp, "Middle position: %lf %lf %lf\n", middle.x(), middle.y(), middle.z());
fprintf(dfp, "End position: %lf %lf %lf\n", end.x(), end.y(), end.z());
}
}
// We can also get polyline data back from the phlv5 edge. This is
// the fastest way to render your model. Note, we do not have to
// apply any body transformation to it. However, it is still in
// world coordinates.
float* f_pts;
int n;
n = phlv5Edge->GetNPoints();
f_pts = phlv5Edge->GetTabPoint();
fprintf(dfp, "Polyline positions: \n");
// We will only write the first and last positions to file
if (n > 0)
{
fprintf(dfp, "Start position: %lf %lf %lf\n", f_pts[0], f_pts[1], f_pts[2]);
fprintf(dfp, "End position: %lf %lf %lf\n", f_pts[(n-1)*3], f_pts[(n-1)*3+1], f_pts[(n-1)*3+2]);
}
// Note: we do not delete the f_pts
}
fclose(dfp);
}
// If we did not pass in a token to make the phlv5 data persitant - we
// want to delete these entities
if (token == 0)
{
for (int index = 0; index < edgeList.count(); index++)
api_del_entity((ENTITY*)edgeList[index]);
}
edgeList.clear();
}
// Delete our model
for (int index = 0;index < bodyList.count();index++)
{
res = api_del_entity(bodyList[index]);
outcome_check(res,"error deleting body from bodyList");
}
bodyList.clear();
// Terminate the component, stop the modeler and shut down
res = api_terminate_hidden_line_removal();
outcome_check(res,"error terminating hidden line component");
res = api_stop_modeller();
outcome_check(res,"error stopping modeler");
fclose(errorFile);
exit(0);
}[Top]
© 1989-2007 Spatial Corp., a Dassault Systèmes company. All rights reserved.