Compare commits
3
Commits
pgo
...
editchecks
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2923050080 | ||
|
|
9dd4023aa5 | ||
|
|
d39ca30602 |
+6
-4
@@ -510,7 +510,9 @@ rt_knob_edit_sca(
|
||||
int matrix_edit);
|
||||
|
||||
/* Equivalent to sedit - run editing logic after input data is set in
|
||||
* rt_edit container. Returns BRLCAD_ERROR if the primitive edit fails. */
|
||||
* rt_edit container. Transient input flags are consumed whether the edit
|
||||
* succeeds or fails; parameter values remain available to the caller.
|
||||
* Returns BRLCAD_ERROR if the primitive edit fails. */
|
||||
RT_EXPORT extern int
|
||||
rt_edit_process(struct rt_edit *s);
|
||||
|
||||
@@ -532,7 +534,7 @@ rt_edit_snap_point(point2d_t pt, const struct rt_edit *s);
|
||||
* restored later with rt_edit_revert().
|
||||
*
|
||||
* The snapshot is stored inside the rt_edit struct. Calling this
|
||||
* function again overwrites any previous snapshot (single-level undo).
|
||||
* function again replaces the previous snapshot only on success.
|
||||
*
|
||||
* @return BRLCAD_OK on success, BRLCAD_ERROR if the export failed.
|
||||
*/
|
||||
@@ -543,8 +545,8 @@ rt_edit_checkpoint(struct rt_edit *s);
|
||||
* Restore primitive parameters from the snapshot saved by
|
||||
* rt_edit_checkpoint().
|
||||
*
|
||||
* If no snapshot has been saved (or the last snapshot was already
|
||||
* consumed) this function logs a message and returns BRLCAD_ERROR.
|
||||
* The snapshot remains available for repeated restores. If none has
|
||||
* been saved, this function logs a message and returns BRLCAD_ERROR.
|
||||
*
|
||||
* @return BRLCAD_OK on success, BRLCAD_ERROR otherwise.
|
||||
*/
|
||||
|
||||
+61
-23
@@ -1107,6 +1107,14 @@ rt_knob_edit_sca(struct rt_edit *s, int matrix_edit)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rt_edit_clear_input(struct rt_edit *s)
|
||||
{
|
||||
s->e_inpara = 0;
|
||||
s->e_mvalid = 0;
|
||||
s->es_scale = 0.0;
|
||||
}
|
||||
|
||||
/*
|
||||
* A great deal of magic takes place here, to accomplish solid editing.
|
||||
*
|
||||
@@ -1122,7 +1130,20 @@ rt_edit_process(struct rt_edit *s)
|
||||
bu_clbk_t f = NULL;
|
||||
void *d = NULL;
|
||||
|
||||
++s->update_views;
|
||||
if (!s)
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
const int type = s->es_int.idb_type;
|
||||
if (type <= ID_NULL || type > ID_MAX_SOLID ||
|
||||
!s->es_int.idb_ptr || EDOBJ[type].magic != RT_FUNCTAB_MAGIC) {
|
||||
bu_vls_printf(s->log_str, "rt_edit_process: no editable solid\n");
|
||||
rt_edit_clear_input(s);
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
const int prior_update_views = s->update_views;
|
||||
if (!s->update_views)
|
||||
s->update_views = 1;
|
||||
|
||||
int had_method = 0;
|
||||
const struct rt_db_internal *ip = &s->es_int;
|
||||
@@ -1134,6 +1155,8 @@ rt_edit_process(struct rt_edit *s)
|
||||
if (f)
|
||||
(*f)(0, NULL, d, NULL);
|
||||
}
|
||||
s->update_views = prior_update_views;
|
||||
rt_edit_clear_input(s);
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
if (bu_vls_strlen(s->log_str)) {
|
||||
@@ -1149,7 +1172,7 @@ rt_edit_process(struct rt_edit *s)
|
||||
|
||||
case RT_EDIT_IDLE:
|
||||
/* do nothing more */
|
||||
--s->update_views;
|
||||
s->update_views = prior_update_views;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
@@ -1166,6 +1189,8 @@ rt_edit_process(struct rt_edit *s)
|
||||
rt_edit_map_clbk_get(&f, &d, s->m, ECMD_PRINT_RESULTS, BU_CLBK_DURING);
|
||||
if (f)
|
||||
(*f)(0, NULL, d, NULL);
|
||||
s->update_views = prior_update_views;
|
||||
rt_edit_clear_input(s);
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -1196,9 +1221,7 @@ rt_edit_process(struct rt_edit *s)
|
||||
}
|
||||
|
||||
// Inputs processed, reset
|
||||
s->e_inpara = 0;
|
||||
s->e_mvalid = 0;
|
||||
s->es_scale = 0.0;
|
||||
rt_edit_clear_input(s);
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
@@ -1221,15 +1244,15 @@ rt_edit_checkpoint(struct rt_edit *s)
|
||||
|
||||
RT_CK_DB_INTERNAL(&s->es_int);
|
||||
|
||||
/* Release any previous snapshot */
|
||||
bu_free_external(&s->es_ckpt);
|
||||
BU_EXTERNAL_INIT(&s->es_ckpt);
|
||||
|
||||
if (rt_obj_export(&s->es_ckpt, &s->es_int, 1.0, s->dbip) < 0) {
|
||||
struct bu_external candidate = BU_EXTERNAL_INIT_ZERO;
|
||||
if (rt_obj_export(&candidate, &s->es_int, 1.0, s->dbip) < 0) {
|
||||
bu_free_external(&candidate);
|
||||
bu_vls_printf(s->log_str, "rt_edit_checkpoint: export failed\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
bu_free_external(&s->es_ckpt);
|
||||
s->es_ckpt = candidate;
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
@@ -1245,26 +1268,41 @@ rt_edit_revert(struct rt_edit *s)
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
int type = s->es_int.idb_type;
|
||||
|
||||
/* Release current contents */
|
||||
rt_db_free_internal(&s->es_int);
|
||||
RT_DB_INTERNAL_INIT(&s->es_int);
|
||||
|
||||
/* rt_obj_import dispatches on ip->idb_minor_type, which RT_DB_INTERNAL_INIT
|
||||
* resets to -1. Restore the saved type so the right ft_importN is called. */
|
||||
s->es_int.idb_minor_type = type;
|
||||
const int type = s->es_int.idb_type;
|
||||
if (type <= ID_NULL || type > ID_MAX_SOLID || !s->es_int.idb_ptr) {
|
||||
bu_vls_printf(s->log_str, "rt_edit_revert: no editable solid\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
struct rt_db_internal restored;
|
||||
RT_DB_INTERNAL_INIT(&restored);
|
||||
restored.idb_minor_type = type;
|
||||
mat_t identity;
|
||||
MAT_IDN(identity);
|
||||
if (rt_obj_import(&s->es_int, &s->es_ckpt, identity, s->dbip) < 0) {
|
||||
int import_result = rt_obj_import(&restored, &s->es_ckpt, identity, s->dbip);
|
||||
/* SPH and REC import through the ELL and TGC internal formats. */
|
||||
bool compatible_type = restored.idb_type == type ||
|
||||
(type == ID_SPH && restored.idb_type == ID_ELL) ||
|
||||
(type == ID_REC && restored.idb_type == ID_TGC);
|
||||
if (import_result < 0 || !compatible_type || !restored.idb_ptr) {
|
||||
rt_db_free_internal(&restored);
|
||||
bu_vls_printf(s->log_str, "rt_edit_revert: import failed\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
/* If the type changed for some reason (shouldn't happen), keep the original */
|
||||
if (s->es_int.idb_type != type)
|
||||
s->es_int.idb_type = type;
|
||||
restored.idb_type = type;
|
||||
restored.idb_meth = &OBJ[type];
|
||||
|
||||
if (s->ipe_ptr && EDOBJ[type].ft_prim_edit_reset)
|
||||
(*EDOBJ[type].ft_prim_edit_reset)(s);
|
||||
rt_db_free_internal(&s->es_int);
|
||||
s->es_int = restored;
|
||||
rt_edit_clear_input(s);
|
||||
s->acc_sc_sol = 1.0;
|
||||
if (!s->e_keyfixed) {
|
||||
s->e_keytag = "";
|
||||
rt_get_solid_keypoint(s, &s->e_keypoint, &s->e_keytag, s->e_mat);
|
||||
}
|
||||
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
@@ -3277,26 +3277,23 @@ int
|
||||
rt_arb_calc_points(struct rt_arb_internal *arb, int cgtype, const plane_t planes[6], const struct bn_tol *tol)
|
||||
{
|
||||
int i;
|
||||
point_t pt[8];
|
||||
struct rt_arb_internal candidate;
|
||||
|
||||
RT_ARB_CK_MAGIC(arb);
|
||||
candidate = *arb;
|
||||
|
||||
/* find new points for entire solid */
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (rt_arb_3face_intersect(pt[i], planes, cgtype, i*3) < 0) {
|
||||
if (rt_arb_3face_intersect(candidate.pt[i], planes, cgtype, i*3) < 0) {
|
||||
bu_log("rt_arb_calc_points: Intersection of planes fails %d\n", i);
|
||||
return -1; /* FAIL */
|
||||
}
|
||||
}
|
||||
|
||||
/* Move new points to arb tol->dist))*/
|
||||
for (i = 0; i < 8; i++) {
|
||||
VMOVE(arb->pt[i], pt[i]);
|
||||
}
|
||||
|
||||
if (rt_arb_check_points(arb, cgtype, tol) < 0)
|
||||
if (rt_arb_check_points(&candidate, cgtype, tol) < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(arb->pt, candidate.pt, sizeof(arb->pt));
|
||||
return 0; /* success */
|
||||
}
|
||||
|
||||
@@ -3397,6 +3394,7 @@ rt_arb_calc_planes(struct bu_vls *error_msg_ret,
|
||||
const struct bn_tol *tol)
|
||||
{
|
||||
const int arb_faces[5][24] = rt_arb_faces;
|
||||
plane_t candidate[6];
|
||||
|
||||
/* ARB4 at location 0, ARB5 at 1, etc. */
|
||||
int type = cgtype - ARB4;
|
||||
@@ -3405,6 +3403,7 @@ rt_arb_calc_planes(struct bu_vls *error_msg_ret,
|
||||
|
||||
RT_ARB_CK_MAGIC(arb);
|
||||
BN_CK_TOL(tol);
|
||||
memcpy(candidate, planes, sizeof(candidate));
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (arb_faces[type][i*4] == -1)
|
||||
@@ -3414,7 +3413,7 @@ rt_arb_calc_planes(struct bu_vls *error_msg_ret,
|
||||
int p2 = arb_faces[type][i*4+1];
|
||||
int p3 = arb_faces[type][i*4+2];
|
||||
|
||||
if (bg_make_plane_3pnts(planes[i],
|
||||
if (bg_make_plane_3pnts(candidate[i],
|
||||
arb->pt[p1],
|
||||
arb->pt[p2],
|
||||
arb->pt[p3],
|
||||
@@ -3425,6 +3424,7 @@ rt_arb_calc_planes(struct bu_vls *error_msg_ret,
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(planes, candidate, sizeof(candidate));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1169,6 +1169,17 @@ rt_arb_edit(struct bu_vls *error_msg_ret,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Intersections and plane updates can fail after changing several points. */
|
||||
struct rt_arb_internal *original_arb = arb;
|
||||
plane_t *original_planes = planes;
|
||||
struct rt_arb_internal candidate = *arb;
|
||||
plane_t candidate_planes[6];
|
||||
vect_t edit_position;
|
||||
memcpy(candidate_planes, planes, sizeof(candidate_planes));
|
||||
VMOVE(edit_position, pos_model);
|
||||
arb = &candidate;
|
||||
planes = candidate_planes;
|
||||
|
||||
/* set the pointer */
|
||||
switch (arb_type) {
|
||||
case ARB4:
|
||||
@@ -1246,7 +1257,7 @@ rt_arb_edit(struct bu_vls *error_msg_ret,
|
||||
/* do the arb editing */
|
||||
if (edit_class == RT_ARB_EDIT_POINT) {
|
||||
/* moving a point - not an edge */
|
||||
VMOVE(arb->pt[edit_type], pos_model);
|
||||
VMOVE(arb->pt[edit_type], edit_position);
|
||||
edptr += 4;
|
||||
} else if (edit_class == RT_ARB_EDIT_EDGE) {
|
||||
vect_t edge_dir;
|
||||
@@ -1256,8 +1267,8 @@ rt_arb_edit(struct bu_vls *error_msg_ret,
|
||||
pt2 = *edptr++;
|
||||
|
||||
if (flags & RT_ARB_EDIT_EDGE_DIR) {
|
||||
VMOVE(edge_dir, pos_model);
|
||||
VMOVE(pos_model, arb->pt[pt1]);
|
||||
VMOVE(edge_dir, edit_position);
|
||||
VMOVE(edit_position, arb->pt[pt1]);
|
||||
} else {
|
||||
/* calculate edge direction */
|
||||
VSUB2(edge_dir, arb->pt[pt2], arb->pt[pt1]);
|
||||
@@ -1271,7 +1282,7 @@ rt_arb_edit(struct bu_vls *error_msg_ret,
|
||||
bp2 = *edptr++;
|
||||
|
||||
/* move the edge */
|
||||
if (rt_arb_move_edge(error_msg_ret, arb, pos_model, bp1, bp2, pt1, pt2,
|
||||
if (rt_arb_move_edge(error_msg_ret, arb, edit_position, bp1, bp2, pt1, pt2,
|
||||
edge_dir, planes, tol))
|
||||
goto err;
|
||||
}
|
||||
@@ -1377,6 +1388,8 @@ rt_arb_edit(struct bu_vls *error_msg_ret,
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(original_arb->pt, candidate.pt, sizeof(candidate.pt));
|
||||
memcpy(original_planes, candidate_planes, sizeof(candidate_planes));
|
||||
return 0; /* OK */
|
||||
|
||||
err:
|
||||
@@ -1501,6 +1514,48 @@ edarb_canonicalize(struct rt_edit *s, struct rt_arb_internal *arb)
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
arb_move_face_to_point(struct rt_edit *s, const point_t target)
|
||||
{
|
||||
struct rt_arb8_edit *a = (struct rt_arb8_edit *)s->ipe_ptr;
|
||||
struct rt_arb_internal *arb = (struct rt_arb_internal *)s->es_int.idb_ptr;
|
||||
struct rt_arb_internal candidate;
|
||||
plane_t planes[6];
|
||||
struct bu_vls error_msg = BU_VLS_INIT_ZERO;
|
||||
int arb_type;
|
||||
|
||||
RT_ARB_CK_MAGIC(arb);
|
||||
if (a->edit_menu < 0 || a->edit_menu >= ARB8_FACE_COUNT) {
|
||||
bu_vls_printf(s->log_str, "Invalid ARB face index %d\n", a->edit_menu);
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
candidate = *arb;
|
||||
memcpy(planes, a->es_peqn, sizeof(planes));
|
||||
planes[a->edit_menu][W] = VDOT(planes[a->edit_menu], target);
|
||||
arb_type = rt_arb_edit_type(s->log_str, s, arb, 0, s->tol);
|
||||
if (!arb_type)
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
if (rt_arb_calc_points(&candidate, arb_type, (const plane_t *)planes, s->tol)) {
|
||||
bu_vls_printf(s->log_str, "Cannot calculate ARB points\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
if (edarb_canonicalize(s, &candidate) != BRLCAD_OK)
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
if (rt_arb_calc_planes(&error_msg, &candidate, arb_type, planes, s->tol)) {
|
||||
bu_vls_printf(s->log_str, "%s", bu_vls_cstr(&error_msg));
|
||||
bu_vls_free(&error_msg);
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
bu_vls_free(&error_msg);
|
||||
|
||||
memcpy(arb->pt, candidate.pt, sizeof(arb->pt));
|
||||
memcpy(a->es_peqn, planes, sizeof(planes));
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
arb_numeric_target(point_t target, struct rt_edit *s, int *edit_menu)
|
||||
{
|
||||
@@ -1535,38 +1590,13 @@ ecmd_arb_move_face(struct rt_edit *s)
|
||||
{
|
||||
struct rt_arb8_edit *a = (struct rt_arb8_edit *)s->ipe_ptr;
|
||||
|
||||
/* move face through definite point */
|
||||
if (s->e_inpara) {
|
||||
if (!s->e_inpara)
|
||||
return BRLCAD_OK;
|
||||
|
||||
vect_t work;
|
||||
if (arb_numeric_target(work, s, &a->edit_menu) != BRLCAD_OK)
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
if (a->edit_menu < 0 || a->edit_menu >= ARB8_FACE_COUNT) {
|
||||
bu_vls_printf(s->log_str, "Invalid ARB face index %d\n", a->edit_menu);
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
struct rt_arb_internal *arb = (struct rt_arb_internal *)s->es_int.idb_ptr;
|
||||
RT_ARB_CK_MAGIC(arb);
|
||||
|
||||
/* change D of planar equation */
|
||||
a->es_peqn[a->edit_menu][W]=VDOT(&a->es_peqn[a->edit_menu][0], work);
|
||||
/* find new vertices, put in record in vector notation */
|
||||
|
||||
int arb_type = rt_arb_edit_type(s->log_str, s, arb, 0, s->tol);
|
||||
if (arb_type == 0)
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
if (rt_arb_calc_points(arb, arb_type, (const plane_t *)a->es_peqn, s->tol)) {
|
||||
bu_vls_printf(s->log_str, "Cannot calculate ARB8 points\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
if (edarb_canonicalize(s, arb) != BRLCAD_OK)
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
point_t target;
|
||||
if (arb_numeric_target(target, s, &a->edit_menu) != BRLCAD_OK)
|
||||
return BRLCAD_ERROR;
|
||||
return arb_move_face_to_point(s, target);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1757,11 +1787,16 @@ ecmd_arb_rotate_face(struct rt_edit *s)
|
||||
if (arb_type == 0)
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
(void)rt_arb_calc_points(arb, arb_type, (const plane_t *)a->es_peqn, s->tol);
|
||||
|
||||
if (rt_arb_calc_points(arb, arb_type, (const plane_t *)a->es_peqn, s->tol)) {
|
||||
bu_vls_printf(s->log_str, "Cannot calculate ARB points\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
if (edarb_canonicalize(s, arb) != BRLCAD_OK) {
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
if (rt_arb_calc_planes(s->log_str, arb, arb_type, a->es_peqn, s->tol))
|
||||
return BRLCAD_ERROR;
|
||||
MAT_IDN(s->incr_change);
|
||||
|
||||
s->e_inpara = 0;
|
||||
@@ -1850,7 +1885,6 @@ arb_mouse_move_element(struct rt_edit *s, const vect_t mousevec)
|
||||
static int
|
||||
edarb_move_face_mousevec(struct rt_edit *s, const vect_t mousevec)
|
||||
{
|
||||
struct rt_arb8_edit *a = (struct rt_arb8_edit *)s->ipe_ptr;
|
||||
vect_t pos_view = VINIT_ZERO; /* Unrotated view space pos */
|
||||
vect_t temp = VINIT_ZERO;
|
||||
vect_t pos_model = VINIT_ZERO; /* Rotated screen space pos */
|
||||
@@ -1859,24 +1893,7 @@ edarb_move_face_mousevec(struct rt_edit *s, const vect_t mousevec)
|
||||
pos_view[Y] = mousevec[Y];
|
||||
MAT4X3PNT(temp, s->vp->gv_view2model, pos_view);
|
||||
MAT4X3PNT(pos_model, s->e_invmat, temp);
|
||||
if (a->edit_menu < 0 || a->edit_menu >= ARB8_FACE_COUNT) {
|
||||
bu_vls_printf(s->log_str, "Invalid ARB face index %d\n", a->edit_menu);
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
/* change D of planar equation */
|
||||
a->es_peqn[a->edit_menu][W]=VDOT(&a->es_peqn[a->edit_menu][0], pos_model);
|
||||
struct rt_arb_internal *arb =
|
||||
(struct rt_arb_internal *)s->es_int.idb_ptr;
|
||||
RT_ARB_CK_MAGIC(arb);
|
||||
|
||||
int arb_type = rt_arb_edit_type(s->log_str, s, arb, 0, s->tol);
|
||||
if (arb_type == 0)
|
||||
return BRLCAD_ERROR;
|
||||
if (rt_arb_calc_points(arb, arb_type, (const plane_t *)a->es_peqn, s->tol)) {
|
||||
bu_vls_printf(s->log_str, "Cannot calculate ARB8 points\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
if (edarb_canonicalize(s, arb) != BRLCAD_OK)
|
||||
if (arb_move_face_to_point(s, pos_model) != BRLCAD_OK)
|
||||
return BRLCAD_ERROR;
|
||||
edit_abs_tra(s, pos_view);
|
||||
return BRLCAD_OK;
|
||||
@@ -1889,6 +1906,9 @@ rt_edit_arb_edit(struct rt_edit *s)
|
||||
struct rt_arb_internal *arb = (struct rt_arb_internal *)s->es_int.idb_ptr;
|
||||
struct rt_arb8_edit *a = (struct rt_arb8_edit *)s->ipe_ptr;
|
||||
RT_ARB_CK_MAGIC(arb);
|
||||
struct rt_arb_internal original_arb = *arb;
|
||||
plane_t original_planes[6];
|
||||
memcpy(original_planes, a->es_peqn, sizeof(original_planes));
|
||||
int ret = 0;
|
||||
|
||||
int arb_type = rt_arb_edit_type(s->log_str, s, arb, 0, s->tol);
|
||||
@@ -1928,11 +1948,27 @@ rt_edit_arb_edit(struct rt_edit *s)
|
||||
ecmd_arb_setup_rotface(s);
|
||||
break;
|
||||
case ECMD_ARB_ROTATE_FACE:
|
||||
{
|
||||
mat_t original_acc_rot, original_model_changes, original_incr_change;
|
||||
int original_menu = a->edit_menu;
|
||||
int original_fixv = a->fixv;
|
||||
MAT_COPY(original_acc_rot, s->acc_rot_sol);
|
||||
MAT_COPY(original_model_changes, s->model_changes);
|
||||
MAT_COPY(original_incr_change, s->incr_change);
|
||||
ret = ecmd_arb_rotate_face(s);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
memcpy(arb->pt, original_arb.pt, sizeof(arb->pt));
|
||||
memcpy(a->es_peqn, original_planes, sizeof(original_planes));
|
||||
MAT_COPY(s->acc_rot_sol, original_acc_rot);
|
||||
MAT_COPY(s->model_changes, original_model_changes);
|
||||
MAT_COPY(s->incr_change, original_incr_change);
|
||||
a->edit_menu = original_menu;
|
||||
a->fixv = original_fixv;
|
||||
return ret;
|
||||
}
|
||||
/* The plane is current; bypass arb_planecalc below. */
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
case PTARB: /* move an ARB point */
|
||||
case EARB: /* edit an ARB edge */
|
||||
return edit_arb_element(s);
|
||||
@@ -1942,19 +1978,29 @@ rt_edit_arb_edit(struct rt_edit *s)
|
||||
|
||||
arb_planecalc:
|
||||
|
||||
if (ret != BRLCAD_OK)
|
||||
goto arb_failed;
|
||||
if (edarb_canonicalize(s, arb) != BRLCAD_OK) {
|
||||
return BRLCAD_ERROR;
|
||||
goto arb_failed;
|
||||
}
|
||||
|
||||
/* must re-calculate the face plane equations for arbs */
|
||||
arb_type = rt_arb_edit_type(s->log_str, s, arb, 0, s->tol);
|
||||
if (arb_type == 0)
|
||||
return BRLCAD_ERROR;
|
||||
if (rt_arb_calc_planes(&error_msg, arb, arb_type, a->es_peqn, s->tol) < 0)
|
||||
goto arb_failed;
|
||||
if (rt_arb_calc_planes(&error_msg, arb, arb_type, a->es_peqn, s->tol) < 0) {
|
||||
bu_vls_printf(s->log_str, "%s", bu_vls_cstr(&error_msg));
|
||||
bu_vls_free(&error_msg);
|
||||
goto arb_failed;
|
||||
}
|
||||
bu_vls_free(&error_msg);
|
||||
|
||||
return ret;
|
||||
|
||||
arb_failed:
|
||||
memcpy(arb->pt, original_arb.pt, sizeof(arb->pt));
|
||||
memcpy(a->es_peqn, original_planes, sizeof(original_planes));
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
C_DECL int
|
||||
|
||||
@@ -608,6 +608,21 @@ ecmd_bot_movev_list(struct rt_edit *s)
|
||||
* triangles that share the new vertex.
|
||||
* No e_para needed.
|
||||
*/
|
||||
static int
|
||||
bot_face_edge_other(const int *face, int v0, int v1)
|
||||
{
|
||||
if ((face[0] == v0 && face[1] == v1) ||
|
||||
(face[0] == v1 && face[1] == v0))
|
||||
return face[2];
|
||||
if ((face[1] == v0 && face[2] == v1) ||
|
||||
(face[1] == v1 && face[2] == v0))
|
||||
return face[0];
|
||||
if ((face[2] == v0 && face[0] == v1) ||
|
||||
(face[2] == v1 && face[0] == v0))
|
||||
return face[1];
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
ecmd_bot_esplit(struct rt_edit *s)
|
||||
{
|
||||
@@ -618,13 +633,25 @@ ecmd_bot_esplit(struct rt_edit *s)
|
||||
|
||||
int v0 = b->bot_verts[0];
|
||||
int v1 = b->bot_verts[1];
|
||||
if (v0 < 0 || v1 < 0 || b->bot_verts[2] >= 0) {
|
||||
if (v0 < 0 || v1 < 0 || v0 == v1 ||
|
||||
(size_t)v0 >= bot->num_vertices || (size_t)v1 >= bot->num_vertices ||
|
||||
b->bot_verts[2] >= 0) {
|
||||
bu_vls_printf(s->log_str,
|
||||
"ERROR: ECMD_BOT_ESPLIT requires a single edge selection "
|
||||
"(ECMD_BOT_PICKE first)\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
size_t incident_faces = 0;
|
||||
for (size_t fi = 0; fi < bot->num_faces; fi++) {
|
||||
if (bot_face_edge_other(&bot->faces[fi * 3], v0, v1) >= 0)
|
||||
incident_faces++;
|
||||
}
|
||||
if (!incident_faces) {
|
||||
bu_vls_printf(s->log_str, "ERROR: selected BOT edge was not found\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
/* Compute midpoint */
|
||||
point_t mid;
|
||||
VADD2SCALE(mid, &bot->vertices[v0*3], &bot->vertices[v1*3], 0.5);
|
||||
@@ -642,19 +669,7 @@ ecmd_bot_esplit(struct rt_edit *s)
|
||||
(size_t *)bu_malloc(orig_nf * sizeof(size_t), "split BOT face parents") :
|
||||
NULL;
|
||||
for (size_t fi = 0; fi < orig_nf; fi++) {
|
||||
int f0 = bot->faces[fi*3];
|
||||
int f1 = bot->faces[fi*3+1];
|
||||
int f2 = bot->faces[fi*3+2];
|
||||
|
||||
/* Check whether this face contains the directed or reverse edge */
|
||||
int other = -1;
|
||||
if ((f0 == v0 && f1 == v1) || (f0 == v1 && f1 == v0)) {
|
||||
other = f2;
|
||||
} else if ((f1 == v0 && f2 == v1) || (f1 == v1 && f2 == v0)) {
|
||||
other = f0;
|
||||
} else if ((f2 == v0 && f0 == v1) || (f2 == v1 && f0 == v0)) {
|
||||
other = f1;
|
||||
}
|
||||
int other = bot_face_edge_other(&bot->faces[fi * 3], v0, v1);
|
||||
if (other < 0)
|
||||
continue; /* edge not in this face */
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ cline_scale(struct rt_edit *s)
|
||||
int
|
||||
ecmd_cline_move_h(struct rt_edit *s)
|
||||
{
|
||||
vect_t work;
|
||||
vect_t work, height;
|
||||
point_t model_point;
|
||||
struct rt_cline_internal *cli =
|
||||
(struct rt_cline_internal *)s->es_int.idb_ptr;
|
||||
@@ -182,6 +182,7 @@ ecmd_cline_move_h(struct rt_edit *s)
|
||||
void *d = NULL;
|
||||
|
||||
RT_CLINE_CK_MAGIC(cli);
|
||||
VMOVE(height, cli->h);
|
||||
|
||||
if (s->e_inpara) {
|
||||
if (s->e_inpara != 3) {
|
||||
@@ -194,24 +195,22 @@ ecmd_cline_move_h(struct rt_edit *s)
|
||||
|
||||
if (s->mv_context) {
|
||||
MAT4X3PNT(work, s->e_invmat, model_point);
|
||||
VSUB2(cli->h, work, cli->v);
|
||||
VSUB2(height, work, cli->v);
|
||||
} else
|
||||
VSUB2(cli->h, model_point, cli->v);
|
||||
VSUB2(height, model_point, cli->v);
|
||||
}
|
||||
/* check for zero H vector */
|
||||
if (MAGNITUDE(cli->h) <= SQRT_SMALL_FASTF) {
|
||||
bu_vls_printf(s->log_str, "Zero H vector not allowed, resetting to +Z\n");
|
||||
if (edit_validate_height(s, height) != BRLCAD_OK) {
|
||||
rt_edit_map_clbk_get(&f, &d, s->m, ECMD_PRINT_RESULTS, BU_CLBK_DURING);
|
||||
if (f)
|
||||
(*f)(0, NULL, d, NULL);
|
||||
VSET(cli->h, 0.0, 0.0, 1.0);
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
VMOVE(cli->h, height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
static int
|
||||
ecmd_cline_move_h_mousevec(struct rt_edit *s, const vect_t mousevec)
|
||||
{
|
||||
vect_t pos_view = VINIT_ZERO; /* Unrotated view space pos */
|
||||
@@ -228,8 +227,13 @@ ecmd_cline_move_h_mousevec(struct rt_edit *s, const vect_t mousevec)
|
||||
/* Do NOT change pos_view[Z] ! */
|
||||
MAT4X3PNT(temp, s->vp->gv_view2model, pos_view);
|
||||
MAT4X3PNT(tr_temp, s->e_invmat, temp);
|
||||
VSUB2(cli->h, tr_temp, cli->v);
|
||||
vect_t height;
|
||||
VSUB2(height, tr_temp, cli->v);
|
||||
if (edit_validate_height(s, height) != BRLCAD_OK)
|
||||
return BRLCAD_ERROR;
|
||||
VMOVE(cli->h, height);
|
||||
edit_abs_tra(s, pos_view);
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
C_DECL int
|
||||
@@ -279,8 +283,7 @@ rt_edit_cline_edit_xy(
|
||||
edit_stra_xy(&pos_view, s, mousevec);
|
||||
break;
|
||||
case ECMD_CLINE_MOVE_H:
|
||||
ecmd_cline_move_h_mousevec(s, mousevec);
|
||||
return BRLCAD_OK;
|
||||
return ecmd_cline_move_h_mousevec(s, mousevec);
|
||||
default:
|
||||
return edit_generic_xy(s, mousevec);
|
||||
}
|
||||
|
||||
@@ -114,6 +114,35 @@ edit_param_read_scalar(fastf_t *out, char **cursor, const char *label,
|
||||
return isfinite(*out) ? BRLCAD_OK : BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
edit_param_read_fields(const char *input, const struct edit_param_field *fields,
|
||||
size_t field_count)
|
||||
{
|
||||
if (!input || !fields || !field_count)
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
char *buffer = bu_strdup(input);
|
||||
char *cursor = buffer;
|
||||
int result = BRLCAD_OK;
|
||||
for (size_t i = 0; i < field_count; i++) {
|
||||
const struct edit_param_field *field = &fields[i];
|
||||
if (field->count == ELEMENTS_PER_VECT)
|
||||
result = edit_param_read_vector(field->value, &cursor,
|
||||
field->label, field->conversion);
|
||||
else if (field->count == 1)
|
||||
result = edit_param_read_scalar(field->value, &cursor,
|
||||
field->label, field->conversion);
|
||||
else
|
||||
result = BRLCAD_ERROR;
|
||||
if (result != BRLCAD_OK)
|
||||
break;
|
||||
}
|
||||
if (result == BRLCAD_OK && edit_param_next_line(&cursor))
|
||||
result = BRLCAD_ERROR;
|
||||
bu_free(buffer, "primitive parameter text");
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
edit_repair_parse_options(struct bu_vls *log_str, int argc,
|
||||
const char **argv, const struct bu_opt_desc *options)
|
||||
@@ -194,6 +223,7 @@ edit_sscale(struct rt_edit *s)
|
||||
{
|
||||
mat_t mat, mat1, scalemat;
|
||||
struct rt_db_internal *ip = &s->es_int;
|
||||
fastf_t scale = s->es_scale;
|
||||
|
||||
if (s->e_inpara > 1) {
|
||||
bu_vls_printf(s->log_str, "ERROR: only one argument needed\n");
|
||||
@@ -202,23 +232,37 @@ edit_sscale(struct rt_edit *s)
|
||||
}
|
||||
|
||||
if (s->e_inpara) {
|
||||
/* accumulate the scale factor */
|
||||
s->es_scale = s->e_para[0] / s->acc_sc_sol;
|
||||
s->acc_sc_sol = s->e_para[0];
|
||||
if (!isfinite(s->e_para[0]) || s->e_para[0] <= 0.0 ||
|
||||
!isfinite(s->acc_sc_sol) || s->acc_sc_sol <= 0.0) {
|
||||
bu_vls_printf(s->log_str, "ERROR: scale must be finite and positive\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
scale = s->e_para[0] / s->acc_sc_sol;
|
||||
}
|
||||
|
||||
/* No pending scale operation — nothing to apply. */
|
||||
if (!s->e_inpara && s->es_scale < SMALL_FASTF)
|
||||
|
||||
if (!s->e_inpara && ZERO(scale))
|
||||
return 0;
|
||||
|
||||
bn_mat_scale_about_pnt(scalemat, s->e_keypoint, s->es_scale);
|
||||
if (!isfinite(scale) || scale <= 0.0 ||
|
||||
!OBJ[ip->idb_type].ft_mat ||
|
||||
bn_mat_scale_about_pnt(scalemat, s->e_keypoint, scale)) {
|
||||
bu_vls_printf(s->log_str, "ERROR: cannot apply solid scale\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
bn_mat_mul(mat1, scalemat, s->e_mat);
|
||||
bn_mat_mul(mat, s->e_invmat, mat1);
|
||||
if (OBJ[ip->idb_type].ft_mat)
|
||||
(*OBJ[ip->idb_type].ft_mat)(ip, mat, ip);
|
||||
if ((*OBJ[ip->idb_type].ft_mat)(ip, mat, ip)) {
|
||||
bu_vls_printf(s->log_str, "ERROR: solid scale failed\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
/* reset solid scale factor */
|
||||
s->es_scale = 1.0;
|
||||
if (s->e_inpara)
|
||||
s->acc_sc_sol = s->e_para[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -312,6 +356,19 @@ edit_scale_equal_axes(struct rt_edit *s, vect_t a, vect_t b, vect_t c)
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
int
|
||||
edit_validate_height(struct rt_edit *s, const vect_t height)
|
||||
{
|
||||
fastf_t length = MAGNITUDE(height);
|
||||
fastf_t min_length = s->tol ? fmax(s->tol->dist, SQRT_SMALL_FASTF) :
|
||||
SQRT_SMALL_FASTF;
|
||||
if (!isfinite(length) || length <= min_length) {
|
||||
bu_vls_printf(s->log_str, "Zero or invalid H vector not allowed\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
void
|
||||
edit_stra(struct rt_edit *s)
|
||||
{
|
||||
@@ -467,8 +524,7 @@ edit_generic(
|
||||
switch (s->edit_flag) {
|
||||
case RT_PARAMS_EDIT_SCALE:
|
||||
/* scale the solid uniformly about its vertex point */
|
||||
edit_sscale(s);
|
||||
return BRLCAD_OK;
|
||||
return edit_sscale(s);
|
||||
case RT_PARAMS_EDIT_TRANS:
|
||||
/* translate solid */
|
||||
edit_stra(s);
|
||||
|
||||
@@ -67,6 +67,10 @@ edit_scale_length(struct rt_edit *s, vect_t *axis, fastf_t *scalar);
|
||||
int
|
||||
edit_scale_equal_axes(struct rt_edit *s, vect_t a, vect_t b, vect_t c);
|
||||
|
||||
/* Reject height endpoint edits that would collapse the primitive. */
|
||||
int
|
||||
edit_validate_height(struct rt_edit *s, const vect_t height);
|
||||
|
||||
/* Validate dimension counts before converting numeric edit parameters. */
|
||||
int
|
||||
edit_parse_sample_count(uint32_t *count, fastf_t value);
|
||||
@@ -95,6 +99,17 @@ int
|
||||
edit_param_read_scalar(fastf_t *out, char **cursor, const char *label,
|
||||
fastf_t local2base);
|
||||
|
||||
struct edit_param_field {
|
||||
const char *label;
|
||||
fastf_t *value;
|
||||
int count;
|
||||
fastf_t conversion;
|
||||
};
|
||||
|
||||
int
|
||||
edit_param_read_fields(const char *text, const struct edit_param_field *fields,
|
||||
size_t field_count);
|
||||
|
||||
/* translate solid */
|
||||
void
|
||||
edit_stra(struct rt_edit *s);
|
||||
|
||||
@@ -223,16 +223,6 @@ rt_edit_ehy_write_params(
|
||||
bu_vls_printf(p, "Dist to asymptotes: %.9f\n", ehy->ehy_c * base2local);
|
||||
}
|
||||
|
||||
#define read_params_line_incr \
|
||||
lc = (ln) ? (ln + lcj) : NULL; \
|
||||
if (!lc) { \
|
||||
bu_free(wc, "wc"); \
|
||||
return BRLCAD_ERROR; \
|
||||
} \
|
||||
ln = strchr(lc, tc); \
|
||||
if (ln) *ln = '\0'; \
|
||||
while (lc && strchr(lc, ':')) lc++
|
||||
|
||||
C_DECL int
|
||||
rt_edit_ehy_read_params(
|
||||
struct rt_db_internal *ip,
|
||||
@@ -241,74 +231,22 @@ rt_edit_ehy_read_params(
|
||||
fastf_t local2base
|
||||
)
|
||||
{
|
||||
double a = 0.0;
|
||||
double b = 0.0;
|
||||
double c = 0.0;
|
||||
struct rt_ehy_internal *ehy = (struct rt_ehy_internal *)ip->idb_ptr;
|
||||
RT_EHY_CK_MAGIC(ehy);
|
||||
|
||||
if (!fc)
|
||||
struct rt_ehy_internal candidate = *ehy;
|
||||
const struct edit_param_field fields[] = {
|
||||
{"Vertex", candidate.ehy_V, ELEMENTS_PER_VECT, local2base},
|
||||
{"Height", candidate.ehy_H, ELEMENTS_PER_VECT, local2base},
|
||||
{"Semi-major axis", candidate.ehy_Au, ELEMENTS_PER_VECT, 1.0},
|
||||
{"Semi-major length", &candidate.ehy_r1, 1, local2base},
|
||||
{"Semi-minor length", &candidate.ehy_r2, 1, local2base},
|
||||
{"Dist to asymptotes", &candidate.ehy_c, 1, local2base}
|
||||
};
|
||||
if (edit_param_read_fields(fc, fields, sizeof(fields) / sizeof(fields[0])) != BRLCAD_OK ||
|
||||
ZERO(MAGNITUDE(candidate.ehy_Au)))
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
// We're getting the file contents as a string, so we need to split it up
|
||||
// to process lines. See https://stackoverflow.com/a/17983619
|
||||
|
||||
// Figure out if we need to deal with Windows line endings
|
||||
const char *crpos = strchr(fc, '\r');
|
||||
int crlf = (crpos && crpos[1] == '\n') ? 1 : 0;
|
||||
char tc = (crlf) ? '\r' : '\n';
|
||||
// If we're CRLF jump ahead another character.
|
||||
int lcj = (crlf) ? 2 : 1;
|
||||
|
||||
char *ln = NULL;
|
||||
char *wc = bu_strdup(fc);
|
||||
char *lc = wc;
|
||||
|
||||
// Set up initial line
|
||||
ln = strchr(lc, tc);
|
||||
if (ln) *ln = '\0';
|
||||
|
||||
// Trim off prefixes, if user left them in
|
||||
while (lc && strchr(lc, ':')) lc++;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(ehy->ehy_V, a, b, c);
|
||||
VSCALE(ehy->ehy_V, ehy->ehy_V, local2base);
|
||||
|
||||
// Set up Height line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(ehy->ehy_H, a, b, c);
|
||||
VSCALE(ehy->ehy_H, ehy->ehy_H, local2base);
|
||||
|
||||
// Set up Semi-major axis line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(ehy->ehy_Au, a, b, c);
|
||||
VUNITIZE(ehy->ehy_Au);
|
||||
|
||||
// Set up Semi-major length line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf", &a);
|
||||
ehy->ehy_r1 = a * local2base;
|
||||
|
||||
// Set up Semi-minor length line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf", &a);
|
||||
ehy->ehy_r2 = a * local2base;
|
||||
|
||||
// Set up distance to asymptotes line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf", &a);
|
||||
ehy->ehy_c = a * local2base;
|
||||
|
||||
// Cleanup
|
||||
bu_free(wc, "wc");
|
||||
VUNITIZE(candidate.ehy_Au);
|
||||
*ehy = candidate;
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -196,16 +196,6 @@ rt_edit_epa_write_params(
|
||||
bu_vls_printf(p, "Semi-minor length: %.9f\n", epa->epa_r2 * base2local);
|
||||
}
|
||||
|
||||
#define read_params_line_incr \
|
||||
lc = (ln) ? (ln + lcj) : NULL; \
|
||||
if (!lc) { \
|
||||
bu_free(wc, "wc"); \
|
||||
return BRLCAD_ERROR; \
|
||||
} \
|
||||
ln = strchr(lc, tc); \
|
||||
if (ln) *ln = '\0'; \
|
||||
while (lc && strchr(lc, ':')) lc++
|
||||
|
||||
C_DECL int
|
||||
rt_edit_epa_read_params(
|
||||
struct rt_db_internal *ip,
|
||||
@@ -214,68 +204,21 @@ rt_edit_epa_read_params(
|
||||
fastf_t local2base
|
||||
)
|
||||
{
|
||||
double a = 0.0;
|
||||
double b = 0.0;
|
||||
double c = 0.0;
|
||||
struct rt_epa_internal *epa = (struct rt_epa_internal *)ip->idb_ptr;
|
||||
RT_EPA_CK_MAGIC(epa);
|
||||
|
||||
if (!fc)
|
||||
struct rt_epa_internal candidate = *epa;
|
||||
const struct edit_param_field fields[] = {
|
||||
{"Vertex", candidate.epa_V, ELEMENTS_PER_VECT, local2base},
|
||||
{"Height", candidate.epa_H, ELEMENTS_PER_VECT, local2base},
|
||||
{"Semi-major axis", candidate.epa_Au, ELEMENTS_PER_VECT, 1.0},
|
||||
{"Semi-major length", &candidate.epa_r1, 1, local2base},
|
||||
{"Semi-minor length", &candidate.epa_r2, 1, local2base}
|
||||
};
|
||||
if (edit_param_read_fields(fc, fields, sizeof(fields) / sizeof(fields[0])) != BRLCAD_OK ||
|
||||
ZERO(MAGNITUDE(candidate.epa_Au)))
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
// We're getting the file contents as a string, so we need to split it up
|
||||
// to process lines. See https://stackoverflow.com/a/17983619
|
||||
|
||||
// Figure out if we need to deal with Windows line endings
|
||||
const char *crpos = strchr(fc, '\r');
|
||||
int crlf = (crpos && crpos[1] == '\n') ? 1 : 0;
|
||||
char tc = (crlf) ? '\r' : '\n';
|
||||
// If we're CRLF jump ahead another character.
|
||||
int lcj = (crlf) ? 2 : 1;
|
||||
|
||||
char *ln = NULL;
|
||||
char *wc = bu_strdup(fc);
|
||||
char *lc = wc;
|
||||
|
||||
// Set up initial line (Vertex)
|
||||
ln = strchr(lc, tc);
|
||||
if (ln) *ln = '\0';
|
||||
|
||||
// Trim off prefixes, if user left them in
|
||||
while (lc && strchr(lc, ':')) lc++;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(epa->epa_V, a, b, c);
|
||||
VSCALE(epa->epa_V, epa->epa_V, local2base);
|
||||
|
||||
// Set up Height line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(epa->epa_H, a, b, c);
|
||||
VSCALE(epa->epa_H, epa->epa_H, local2base);
|
||||
|
||||
// Set up Semi-major axis line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(epa->epa_Au, a, b, c);
|
||||
VUNITIZE(epa->epa_Au);
|
||||
|
||||
// Set up Semi-major length line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf", &a);
|
||||
epa->epa_r1 = a * local2base;
|
||||
|
||||
// Set up Semi-minor length line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf", &a);
|
||||
epa->epa_r2 = a * local2base;
|
||||
|
||||
// Cleanup
|
||||
bu_free(wc, "wc");
|
||||
VUNITIZE(candidate.epa_Au);
|
||||
*epa = candidate;
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -148,16 +148,6 @@ rt_edit_eto_write_params(
|
||||
bu_vls_printf(p, "Radius of rotation: %.9f\n", eto->eto_r * base2local);
|
||||
}
|
||||
|
||||
#define read_params_line_incr \
|
||||
lc = (ln) ? (ln + lcj) : NULL; \
|
||||
if (!lc) { \
|
||||
bu_free(wc, "wc"); \
|
||||
return BRLCAD_ERROR; \
|
||||
} \
|
||||
ln = strchr(lc, tc); \
|
||||
if (ln) *ln = '\0'; \
|
||||
while (lc && strchr(lc, ':')) lc++
|
||||
|
||||
C_DECL int
|
||||
rt_edit_eto_read_params(
|
||||
struct rt_db_internal *ip,
|
||||
@@ -166,68 +156,21 @@ rt_edit_eto_read_params(
|
||||
fastf_t local2base
|
||||
)
|
||||
{
|
||||
double a = 0.0;
|
||||
double b = 0.0;
|
||||
double c = 0.0;
|
||||
struct rt_eto_internal *eto = (struct rt_eto_internal *)ip->idb_ptr;
|
||||
RT_ETO_CK_MAGIC(eto);
|
||||
|
||||
if (!fc)
|
||||
struct rt_eto_internal candidate = *eto;
|
||||
const struct edit_param_field fields[] = {
|
||||
{"Vertex", candidate.eto_V, ELEMENTS_PER_VECT, local2base},
|
||||
{"Normal", candidate.eto_N, ELEMENTS_PER_VECT, 1.0},
|
||||
{"Semi-major axis", candidate.eto_C, ELEMENTS_PER_VECT, local2base},
|
||||
{"Semi-minor length", &candidate.eto_rd, 1, local2base},
|
||||
{"Radius of rotation", &candidate.eto_r, 1, local2base}
|
||||
};
|
||||
if (edit_param_read_fields(fc, fields, sizeof(fields) / sizeof(fields[0])) != BRLCAD_OK ||
|
||||
ZERO(MAGNITUDE(candidate.eto_N)))
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
// We're getting the file contents as a string, so we need to split it up
|
||||
// to process lines. See https://stackoverflow.com/a/17983619
|
||||
|
||||
// Figure out if we need to deal with Windows line endings
|
||||
const char *crpos = strchr(fc, '\r');
|
||||
int crlf = (crpos && crpos[1] == '\n') ? 1 : 0;
|
||||
char tc = (crlf) ? '\r' : '\n';
|
||||
// If we're CRLF jump ahead another character.
|
||||
int lcj = (crlf) ? 2 : 1;
|
||||
|
||||
char *ln = NULL;
|
||||
char *wc = bu_strdup(fc);
|
||||
char *lc = wc;
|
||||
|
||||
// Set up initial line (Vertex)
|
||||
ln = strchr(lc, tc);
|
||||
if (ln) *ln = '\0';
|
||||
|
||||
// Trim off prefixes, if user left them in
|
||||
while (lc && strchr(lc, ':')) lc++;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(eto->eto_V, a, b, c);
|
||||
VSCALE(eto->eto_V, eto->eto_V, local2base);
|
||||
|
||||
// Set up Normal line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(eto->eto_N, a, b, c);
|
||||
VUNITIZE(eto->eto_N);
|
||||
|
||||
// Set up Semi-major axis line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(eto->eto_C, a, b, c);
|
||||
VSCALE(eto->eto_C, eto->eto_C, local2base);
|
||||
|
||||
// Set up Semi-minor length line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf", &a);
|
||||
eto->eto_rd = a * local2base;
|
||||
|
||||
// Set up Radius of rotation line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf", &a);
|
||||
eto->eto_r = a * local2base;
|
||||
|
||||
// Cleanup
|
||||
bu_free(wc, "wc");
|
||||
VUNITIZE(candidate.eto_N);
|
||||
*eto = candidate;
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ ecmd_extr_skt_name(struct rt_edit *s)
|
||||
int
|
||||
ecmd_extr_mov_h(struct rt_edit *s)
|
||||
{
|
||||
vect_t work;
|
||||
vect_t work, height;
|
||||
point_t model_point;
|
||||
struct rt_extrude_internal *extr =
|
||||
(struct rt_extrude_internal *)s->es_int.idb_ptr;
|
||||
@@ -256,6 +256,7 @@ ecmd_extr_mov_h(struct rt_edit *s)
|
||||
void *d = NULL;
|
||||
|
||||
RT_EXTRUDE_CK_MAGIC(extr);
|
||||
VMOVE(height, extr->h);
|
||||
if (s->e_inpara) {
|
||||
if (s->e_inpara != 3) {
|
||||
bu_vls_printf(s->log_str, "ERROR: three arguments needed\n");
|
||||
@@ -268,22 +269,20 @@ ecmd_extr_mov_h(struct rt_edit *s)
|
||||
if (s->mv_context) {
|
||||
/* apply s->e_invmat to convert to real model coordinates */
|
||||
MAT4X3PNT(work, s->e_invmat, model_point);
|
||||
VSUB2(extr->h, work, extr->V);
|
||||
VSUB2(height, work, extr->V);
|
||||
} else {
|
||||
VSUB2(extr->h, model_point, extr->V);
|
||||
VSUB2(height, model_point, extr->V);
|
||||
}
|
||||
}
|
||||
|
||||
/* check for zero H vector */
|
||||
if (MAGNITUDE(extr->h) <= SQRT_SMALL_FASTF) {
|
||||
bu_vls_printf(s->log_str, "Zero H vector not allowed, resetting to +Z\n");
|
||||
if (edit_validate_height(s, height) != BRLCAD_OK) {
|
||||
rt_edit_map_clbk_get(&f, &d, s->m, ECMD_PRINT_RESULTS, BU_CLBK_DURING);
|
||||
if (f)
|
||||
(*f)(0, NULL, d, NULL);
|
||||
VSET(extr->h, 0.0, 0.0, 1.0);
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
VMOVE(extr->h, height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -380,7 +379,7 @@ ecmd_extr_rot_h(struct rt_edit *s)
|
||||
}
|
||||
|
||||
/* Use mouse to change location of point V+H */
|
||||
void
|
||||
static int
|
||||
ecmd_extr_mov_h_mousevec(struct rt_edit *s, const vect_t mousevec)
|
||||
{
|
||||
vect_t pos_view = VINIT_ZERO; /* Unrotated view space pos */
|
||||
@@ -396,8 +395,13 @@ ecmd_extr_mov_h_mousevec(struct rt_edit *s, const vect_t mousevec)
|
||||
/* Do NOT change pos_view[Z] ! */
|
||||
MAT4X3PNT(temp, s->vp->gv_view2model, pos_view);
|
||||
MAT4X3PNT(tr_temp, s->e_invmat, temp);
|
||||
VSUB2(extr->h, tr_temp, extr->V);
|
||||
vect_t height;
|
||||
VSUB2(height, tr_temp, extr->V);
|
||||
if (edit_validate_height(s, height) != BRLCAD_OK)
|
||||
return BRLCAD_ERROR;
|
||||
VMOVE(extr->h, height);
|
||||
edit_abs_tra(s, pos_view);
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -558,8 +562,7 @@ rt_edit_extrude_edit_xy(
|
||||
edit_stra_xy(&pos_view, s, mousevec);
|
||||
break;
|
||||
case ECMD_EXTR_MOV_H:
|
||||
ecmd_extr_mov_h_mousevec(s, mousevec);
|
||||
return BRLCAD_OK;
|
||||
return ecmd_extr_mov_h_mousevec(s, mousevec);
|
||||
default:
|
||||
return edit_generic_xy(s, mousevec);
|
||||
}
|
||||
|
||||
@@ -155,16 +155,6 @@ rt_edit_hyp_write_params(
|
||||
bu_vls_printf(p, "Ratio of Neck to Base: %.9f\n", hyp->hyp_bnr);
|
||||
}
|
||||
|
||||
#define read_params_line_incr \
|
||||
lc = (ln) ? (ln + lcj) : NULL; \
|
||||
if (!lc) { \
|
||||
bu_free(wc, "wc"); \
|
||||
return BRLCAD_ERROR; \
|
||||
} \
|
||||
ln = strchr(lc, tc); \
|
||||
if (ln) *ln = '\0'; \
|
||||
while (lc && strchr(lc, ':')) lc++
|
||||
|
||||
C_DECL int
|
||||
rt_edit_hyp_read_params(
|
||||
struct rt_db_internal *ip,
|
||||
@@ -173,68 +163,19 @@ rt_edit_hyp_read_params(
|
||||
fastf_t local2base
|
||||
)
|
||||
{
|
||||
double a = 0.0;
|
||||
double b = 0.0;
|
||||
double c = 0.0;
|
||||
struct rt_hyp_internal *hyp = (struct rt_hyp_internal *)ip->idb_ptr;
|
||||
RT_HYP_CK_MAGIC(hyp);
|
||||
|
||||
if (!fc)
|
||||
struct rt_hyp_internal candidate = *hyp;
|
||||
const struct edit_param_field fields[] = {
|
||||
{"Vertex", candidate.hyp_Vi, ELEMENTS_PER_VECT, local2base},
|
||||
{"Height", candidate.hyp_Hi, ELEMENTS_PER_VECT, local2base},
|
||||
{"Semi-major axis", candidate.hyp_A, ELEMENTS_PER_VECT, local2base},
|
||||
{"Semi-minor length", &candidate.hyp_b, 1, local2base},
|
||||
{"Ratio of Neck to Base", &candidate.hyp_bnr, 1, 1.0}
|
||||
};
|
||||
if (edit_param_read_fields(fc, fields, sizeof(fields) / sizeof(fields[0])) != BRLCAD_OK)
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
// We're getting the file contents as a string, so we need to split it up
|
||||
// to process lines. See https://stackoverflow.com/a/17983619
|
||||
|
||||
// Figure out if we need to deal with Windows line endings
|
||||
const char *crpos = strchr(fc, '\r');
|
||||
int crlf = (crpos && crpos[1] == '\n') ? 1 : 0;
|
||||
char tc = (crlf) ? '\r' : '\n';
|
||||
// If we're CRLF jump ahead another character.
|
||||
int lcj = (crlf) ? 2 : 1;
|
||||
|
||||
char *ln = NULL;
|
||||
char *wc = bu_strdup(fc);
|
||||
char *lc = wc;
|
||||
|
||||
// Set up initial line (Vertex)
|
||||
ln = strchr(lc, tc);
|
||||
if (ln) *ln = '\0';
|
||||
|
||||
// Trim off prefixes, if user left them in
|
||||
while (lc && strchr(lc, ':')) lc++;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(hyp->hyp_Vi, a, b, c);
|
||||
VSCALE(hyp->hyp_Vi, hyp->hyp_Vi, local2base);
|
||||
|
||||
// Set up Height line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(hyp->hyp_Hi, a, b, c);
|
||||
VSCALE(hyp->hyp_Hi, hyp->hyp_Hi, local2base);
|
||||
|
||||
// Set up Semi-major axis line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(hyp->hyp_A, a, b, c);
|
||||
VSCALE(hyp->hyp_A, hyp->hyp_A, local2base);
|
||||
|
||||
// Set up Semi-minor length line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf", &a);
|
||||
hyp->hyp_b = a * local2base;
|
||||
|
||||
// Set up Ratio of Neck to Base line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf", &a);
|
||||
hyp->hyp_bnr = a;
|
||||
|
||||
// Cleanup
|
||||
bu_free(wc, "wc");
|
||||
*hyp = candidate;
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -676,6 +676,52 @@ nmg_edit_target_point(point_t target, const struct rt_edit *s, const point_t loc
|
||||
VMOVE(target, base_point);
|
||||
}
|
||||
|
||||
static int
|
||||
nmg_edit_move_edge(struct rt_edit *s, const point_t new_pt)
|
||||
{
|
||||
struct rt_nmg_edit *n = (struct rt_nmg_edit *)s->ipe_ptr;
|
||||
struct model *original = (struct model *)s->es_int.idb_ptr;
|
||||
struct model *candidate;
|
||||
struct nmg_struct_counts counts;
|
||||
uint32_t **candidate_structs;
|
||||
struct edgeuse *candidate_eu;
|
||||
int result;
|
||||
|
||||
if (nmg_find_model(&n->es_eu->l.magic) != original)
|
||||
return 1;
|
||||
|
||||
/* A wire move cannot fail after it starts changing geometry. */
|
||||
if (!nmg_find_fu_of_eu(n->es_eu))
|
||||
return nmg_move_edge_thru_pnt(n->es_eu, new_pt, s->tol);
|
||||
|
||||
candidate = nmg_clone_model(original);
|
||||
if (!candidate)
|
||||
return 1;
|
||||
|
||||
candidate_structs = nmg_m_struct_count(&counts, candidate);
|
||||
candidate_eu = (struct edgeuse *)candidate_structs[n->es_eu->index];
|
||||
NMG_CK_EDGEUSE(candidate_eu);
|
||||
result = nmg_move_edge_thru_pnt(candidate_eu, new_pt, s->tol);
|
||||
if (result) {
|
||||
bu_free(candidate_structs, "NMG candidate structures");
|
||||
nmg_km(candidate);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Clone indices identify the corresponding selections in the new model. */
|
||||
n->es_eu = candidate_eu;
|
||||
if (n->es_v && nmg_find_model(&n->es_v->magic) == original)
|
||||
n->es_v = (struct vertex *)candidate_structs[n->es_v->index];
|
||||
if (n->es_fu && nmg_find_model(&n->es_fu->l.magic) == original)
|
||||
n->es_fu = (struct faceuse *)candidate_structs[n->es_fu->index];
|
||||
if (n->es_s && nmg_find_model(&n->es_s->l.magic) == original)
|
||||
n->es_s = (struct shell *)candidate_structs[n->es_s->index];
|
||||
bu_free(candidate_structs, "NMG candidate structures");
|
||||
s->es_int.idb_ptr = (void *)candidate;
|
||||
nmg_km(original);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ecmd_nmg_emove(struct rt_edit *s)
|
||||
{
|
||||
@@ -747,7 +793,7 @@ ecmd_nmg_emove(struct rt_edit *s)
|
||||
}
|
||||
}
|
||||
|
||||
if (nmg_move_edge_thru_pnt(n->es_eu, new_pt, s->tol) < 0) {
|
||||
if (nmg_edit_move_edge(s, new_pt)) {
|
||||
bu_vls_printf(s->log_str, "Edge Move: Unable to hit (%g %g %g)\n",
|
||||
V3ARGS(new_pt));
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
@@ -234,7 +234,14 @@ rt_edit_rec_edit(struct rt_edit *s)
|
||||
tgc = (struct rt_tgc_internal *)s->es_int.idb_ptr;
|
||||
RT_TGC_CK_MAGIC(tgc);
|
||||
if (s->e_inpara == 3) {
|
||||
VSCALE(tgc->v, s->e_para, s->local2base);
|
||||
point_t new_v;
|
||||
VSCALE(new_v, s->e_para, s->local2base);
|
||||
if (!isfinite(new_v[X]) || !isfinite(new_v[Y]) ||
|
||||
!isfinite(new_v[Z])) {
|
||||
bu_vls_printf(s->log_str, "ERROR: base center must be finite\n");
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
VMOVE(tgc->v, new_v);
|
||||
}
|
||||
return BRLCAD_OK;
|
||||
|
||||
@@ -244,11 +251,8 @@ rt_edit_rec_edit(struct rt_edit *s)
|
||||
if (s->e_inpara == 3) {
|
||||
vect_t new_h;
|
||||
VSCALE(new_h, s->e_para, s->local2base);
|
||||
if (MAGNITUDE(new_h) < SMALL_FASTF) {
|
||||
bu_vls_printf(s->log_str,
|
||||
"ERROR: H vector must have non-zero length\n");
|
||||
if (edit_validate_height(s, new_h) != BRLCAD_OK)
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
mag_a = MAGNITUDE(tgc->a);
|
||||
mag_b = MAGNITUDE(tgc->b);
|
||||
@@ -281,7 +285,7 @@ rt_edit_rec_edit(struct rt_edit *s)
|
||||
RT_TGC_CK_MAGIC(tgc);
|
||||
if (s->e_inpara == 1) {
|
||||
r = s->e_para[0] * s->local2base;
|
||||
if (r < SMALL_FASTF) {
|
||||
if (!isfinite(r) || r <= 0.0) {
|
||||
bu_vls_printf(s->log_str,
|
||||
"ERROR: radius must be positive\n");
|
||||
return BRLCAD_ERROR;
|
||||
@@ -298,7 +302,7 @@ rt_edit_rec_edit(struct rt_edit *s)
|
||||
RT_TGC_CK_MAGIC(tgc);
|
||||
if (s->e_inpara == 1) {
|
||||
r = s->e_para[0] * s->local2base;
|
||||
if (r < SMALL_FASTF) {
|
||||
if (!isfinite(r) || r <= 0.0) {
|
||||
bu_vls_printf(s->log_str,
|
||||
"ERROR: radius must be positive\n");
|
||||
return BRLCAD_ERROR;
|
||||
@@ -315,7 +319,7 @@ rt_edit_rec_edit(struct rt_edit *s)
|
||||
RT_TGC_CK_MAGIC(tgc);
|
||||
if (s->e_inpara == 1) {
|
||||
r = s->e_para[0] * s->local2base;
|
||||
if (r < SMALL_FASTF) {
|
||||
if (!isfinite(r) || r <= 0.0) {
|
||||
bu_vls_printf(s->log_str,
|
||||
"ERROR: radius must be positive\n");
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
@@ -222,16 +222,6 @@ rt_edit_rhc_write_params(
|
||||
bu_vls_printf(p, "Dist_to_asymptotes: %.9f\n", rhc->rhc_c * base2local);
|
||||
}
|
||||
|
||||
#define read_params_line_incr \
|
||||
lc = (ln) ? (ln + lcj) : NULL; \
|
||||
if (!lc) { \
|
||||
bu_free(wc, "wc"); \
|
||||
return BRLCAD_ERROR; \
|
||||
} \
|
||||
ln = strchr(lc, tc); \
|
||||
if (ln) *ln = '\0'; \
|
||||
while (lc && strchr(lc, ':')) lc++
|
||||
|
||||
C_DECL int
|
||||
rt_edit_rhc_read_params(
|
||||
struct rt_db_internal *ip,
|
||||
@@ -240,68 +230,19 @@ rt_edit_rhc_read_params(
|
||||
fastf_t local2base
|
||||
)
|
||||
{
|
||||
double a = 0.0;
|
||||
double b = 0.0;
|
||||
double c = 0.0;
|
||||
struct rt_rhc_internal *rhc = (struct rt_rhc_internal *)ip->idb_ptr;
|
||||
RT_RHC_CK_MAGIC(rhc);
|
||||
|
||||
if (!fc)
|
||||
struct rt_rhc_internal candidate = *rhc;
|
||||
const struct edit_param_field fields[] = {
|
||||
{"Vertex", candidate.rhc_V, ELEMENTS_PER_VECT, local2base},
|
||||
{"Height", candidate.rhc_H, ELEMENTS_PER_VECT, local2base},
|
||||
{"Breadth", candidate.rhc_B, ELEMENTS_PER_VECT, local2base},
|
||||
{"Half-width", &candidate.rhc_r, 1, local2base},
|
||||
{"Dist_to_asymptotes", &candidate.rhc_c, 1, local2base}
|
||||
};
|
||||
if (edit_param_read_fields(fc, fields, sizeof(fields) / sizeof(fields[0])) != BRLCAD_OK)
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
// We're getting the file contents as a string, so we need to split it up
|
||||
// to process lines. See https://stackoverflow.com/a/17983619
|
||||
|
||||
// Figure out if we need to deal with Windows line endings
|
||||
const char *crpos = strchr(fc, '\r');
|
||||
int crlf = (crpos && crpos[1] == '\n') ? 1 : 0;
|
||||
char tc = (crlf) ? '\r' : '\n';
|
||||
// If we're CRLF jump ahead another character.
|
||||
int lcj = (crlf) ? 2 : 1;
|
||||
|
||||
char *ln = NULL;
|
||||
char *wc = bu_strdup(fc);
|
||||
char *lc = wc;
|
||||
|
||||
// Set up initial line (Vertex)
|
||||
ln = strchr(lc, tc);
|
||||
if (ln) *ln = '\0';
|
||||
|
||||
// Trim off prefixes, if user left them in
|
||||
while (lc && strchr(lc, ':')) lc++;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(rhc->rhc_V, a, b, c);
|
||||
VSCALE(rhc->rhc_V, rhc->rhc_V, local2base);
|
||||
|
||||
// Set up Height line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(rhc->rhc_H, a, b, c);
|
||||
VSCALE(rhc->rhc_H, rhc->rhc_H, local2base);
|
||||
|
||||
// Set up Breadth line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(rhc->rhc_B, a, b, c);
|
||||
VSCALE(rhc->rhc_B, rhc->rhc_B, local2base);
|
||||
|
||||
// Set up Half-width line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf", &a);
|
||||
rhc->rhc_r = a * local2base;
|
||||
|
||||
// Set up distance to asymptotes line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf", &a);
|
||||
rhc->rhc_c = a * local2base;
|
||||
|
||||
// Cleanup
|
||||
bu_free(wc, "wc");
|
||||
*rhc = candidate;
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -195,16 +195,6 @@ rt_edit_rpc_write_params(
|
||||
}
|
||||
|
||||
|
||||
#define read_params_line_incr \
|
||||
lc = (ln) ? (ln + lcj) : NULL; \
|
||||
if (!lc) { \
|
||||
bu_free(wc, "wc"); \
|
||||
return BRLCAD_ERROR; \
|
||||
} \
|
||||
ln = strchr(lc, tc); \
|
||||
if (ln) *ln = '\0'; \
|
||||
while (lc && strchr(lc, ':')) lc++
|
||||
|
||||
C_DECL int
|
||||
rt_edit_rpc_read_params(
|
||||
struct rt_db_internal *ip,
|
||||
@@ -213,62 +203,18 @@ rt_edit_rpc_read_params(
|
||||
fastf_t local2base
|
||||
)
|
||||
{
|
||||
double a = 0.0;
|
||||
double b = 0.0;
|
||||
double c = 0.0;
|
||||
struct rt_rpc_internal *rpc = (struct rt_rpc_internal *)ip->idb_ptr;
|
||||
RT_RPC_CK_MAGIC(rpc);
|
||||
|
||||
if (!fc)
|
||||
struct rt_rpc_internal candidate = *rpc;
|
||||
const struct edit_param_field fields[] = {
|
||||
{"Vertex", candidate.rpc_V, ELEMENTS_PER_VECT, local2base},
|
||||
{"Height", candidate.rpc_H, ELEMENTS_PER_VECT, local2base},
|
||||
{"Breadth", candidate.rpc_B, ELEMENTS_PER_VECT, local2base},
|
||||
{"Half-width", &candidate.rpc_r, 1, local2base}
|
||||
};
|
||||
if (edit_param_read_fields(fc, fields, sizeof(fields) / sizeof(fields[0])) != BRLCAD_OK)
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
// We're getting the file contents as a string, so we need to split it up
|
||||
// to process lines. See https://stackoverflow.com/a/17983619
|
||||
|
||||
// Figure out if we need to deal with Windows line endings
|
||||
const char *crpos = strchr(fc, '\r');
|
||||
int crlf = (crpos && crpos[1] == '\n') ? 1 : 0;
|
||||
char tc = (crlf) ? '\r' : '\n';
|
||||
// If we're CRLF jump ahead another character.
|
||||
int lcj = (crlf) ? 2 : 1;
|
||||
|
||||
char *ln = NULL;
|
||||
char *wc = bu_strdup(fc);
|
||||
char *lc = wc;
|
||||
|
||||
// Set up initial line (Vertex)
|
||||
ln = strchr(lc, tc);
|
||||
if (ln) *ln = '\0';
|
||||
|
||||
// Trim off prefixes, if user left them in
|
||||
while (lc && strchr(lc, ':')) lc++;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(rpc->rpc_V, a, b, c);
|
||||
VSCALE(rpc->rpc_V, rpc->rpc_V, local2base);
|
||||
|
||||
// Set up Height line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(rpc->rpc_H, a, b, c);
|
||||
VSCALE(rpc->rpc_H, rpc->rpc_H, local2base);
|
||||
|
||||
// Set up Breadth line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(rpc->rpc_B, a, b, c);
|
||||
VSCALE(rpc->rpc_B, rpc->rpc_B, local2base);
|
||||
|
||||
// Set up Half-width line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf", &a);
|
||||
rpc->rpc_r = a * local2base;
|
||||
|
||||
// Cleanup
|
||||
bu_free(wc, "wc");
|
||||
*rpc = candidate;
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -460,16 +460,6 @@ rt_edit_tgc_write_params(
|
||||
bu_vls_printf(p, "D: %.9f %.9f %.9f\n", V3BASE2LOCAL(tgc->d));
|
||||
}
|
||||
|
||||
#define read_params_line_incr \
|
||||
lc = (ln) ? (ln + lcj) : NULL; \
|
||||
if (!lc) { \
|
||||
bu_free(wc, "wc"); \
|
||||
return BRLCAD_ERROR; \
|
||||
} \
|
||||
ln = strchr(lc, tc); \
|
||||
if (ln) *ln = '\0'; \
|
||||
while (lc && strchr(lc, ':')) lc++
|
||||
|
||||
C_DECL int
|
||||
rt_edit_tgc_read_params(
|
||||
struct rt_db_internal *ip,
|
||||
@@ -478,77 +468,20 @@ rt_edit_tgc_read_params(
|
||||
fastf_t local2base
|
||||
)
|
||||
{
|
||||
double a = 0.0;
|
||||
double b = 0.0;
|
||||
double c = 0.0;
|
||||
struct rt_tgc_internal *tgc = (struct rt_tgc_internal *)ip->idb_ptr;
|
||||
RT_TGC_CK_MAGIC(tgc);
|
||||
|
||||
if (!fc)
|
||||
struct rt_tgc_internal candidate = *tgc;
|
||||
const struct edit_param_field fields[] = {
|
||||
{"Vertex", candidate.v, ELEMENTS_PER_VECT, local2base},
|
||||
{"Height", candidate.h, ELEMENTS_PER_VECT, local2base},
|
||||
{"A", candidate.a, ELEMENTS_PER_VECT, local2base},
|
||||
{"B", candidate.b, ELEMENTS_PER_VECT, local2base},
|
||||
{"C", candidate.c, ELEMENTS_PER_VECT, local2base},
|
||||
{"D", candidate.d, ELEMENTS_PER_VECT, local2base}
|
||||
};
|
||||
if (edit_param_read_fields(fc, fields, sizeof(fields) / sizeof(fields[0])) != BRLCAD_OK)
|
||||
return BRLCAD_ERROR;
|
||||
|
||||
// We're getting the file contents as a string, so we need to split it up
|
||||
// to process lines. See https://stackoverflow.com/a/17983619
|
||||
|
||||
// Figure out if we need to deal with Windows line endings
|
||||
const char *crpos = strchr(fc, '\r');
|
||||
int crlf = (crpos && crpos[1] == '\n') ? 1 : 0;
|
||||
char tc = (crlf) ? '\r' : '\n';
|
||||
// If we're CRLF jump ahead another character.
|
||||
int lcj = (crlf) ? 2 : 1;
|
||||
|
||||
char *ln = NULL;
|
||||
char *wc = bu_strdup(fc);
|
||||
char *lc = wc;
|
||||
|
||||
// Set up initial line (Vertex)
|
||||
ln = strchr(lc, tc);
|
||||
if (ln) *ln = '\0';
|
||||
|
||||
// Trim off prefixes, if user left them in
|
||||
while (lc && strchr(lc, ':')) lc++;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(tgc->v, a, b, c);
|
||||
VSCALE(tgc->v, tgc->v, local2base);
|
||||
|
||||
// Set up Height line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(tgc->h, a, b, c);
|
||||
VSCALE(tgc->h, tgc->h, local2base);
|
||||
|
||||
// Set up A line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(tgc->a, a, b, c);
|
||||
VSCALE(tgc->a, tgc->a, local2base);
|
||||
|
||||
// Set up B line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(tgc->b, a, b, c);
|
||||
VSCALE(tgc->b, tgc->b, local2base);
|
||||
|
||||
// Set up C line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(tgc->c, a, b, c);
|
||||
VSCALE(tgc->c, tgc->c, local2base);
|
||||
|
||||
// Set up D line
|
||||
read_params_line_incr;
|
||||
|
||||
sscanf(lc, "%lf %lf %lf", &a, &b, &c);
|
||||
VSET(tgc->d, a, b, c);
|
||||
VSCALE(tgc->d, tgc->d, local2base);
|
||||
|
||||
// Cleanup
|
||||
bu_free(wc, "wc");
|
||||
*tgc = candidate;
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
@@ -751,7 +684,7 @@ int
|
||||
ecmd_tgc_mv_h(struct rt_edit *s)
|
||||
{
|
||||
float la, lb, lc, ld; /* TGC: length of vectors */
|
||||
vect_t work;
|
||||
vect_t work, height;
|
||||
point_t model_point;
|
||||
struct rt_tgc_internal *tgc =
|
||||
(struct rt_tgc_internal *)s->es_int.idb_ptr;
|
||||
@@ -759,6 +692,7 @@ ecmd_tgc_mv_h(struct rt_edit *s)
|
||||
void *d = NULL;
|
||||
|
||||
RT_TGC_CK_MAGIC(tgc);
|
||||
VMOVE(height, tgc->h);
|
||||
if (s->e_inpara) {
|
||||
if (s->e_inpara != 3) {
|
||||
bu_vls_printf(s->log_str, "ERROR: three arguments needed\n");
|
||||
@@ -771,22 +705,21 @@ ecmd_tgc_mv_h(struct rt_edit *s)
|
||||
if (s->mv_context) {
|
||||
/* apply s->e_invmat to convert to real model coordinates */
|
||||
MAT4X3PNT(work, s->e_invmat, model_point);
|
||||
VSUB2(tgc->h, work, tgc->v);
|
||||
VSUB2(height, work, tgc->v);
|
||||
} else {
|
||||
VSUB2(tgc->h, model_point, tgc->v);
|
||||
VSUB2(height, model_point, tgc->v);
|
||||
}
|
||||
}
|
||||
|
||||
/* check for zero H vector */
|
||||
if (MAGNITUDE(tgc->h) <= SQRT_SMALL_FASTF) {
|
||||
bu_vls_printf(s->log_str, "Zero H vector not allowed, resetting to +Z\n");
|
||||
if (edit_validate_height(s, height) != BRLCAD_OK) {
|
||||
rt_edit_map_clbk_get(&f, &d, s->m, ECMD_PRINT_RESULTS, BU_CLBK_DURING);
|
||||
if (f)
|
||||
(*f)(0, NULL, d, NULL);
|
||||
VSET(tgc->h, 0.0, 0.0, 1.0);
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
VMOVE(tgc->h, height);
|
||||
|
||||
/* have new height vector -- redefine rest of tgc */
|
||||
la = MAGNITUDE(tgc->a);
|
||||
lb = MAGNITUDE(tgc->b);
|
||||
@@ -814,7 +747,7 @@ ecmd_tgc_mv_h(struct rt_edit *s)
|
||||
int
|
||||
ecmd_tgc_mv_hh(struct rt_edit *s)
|
||||
{
|
||||
vect_t work;
|
||||
vect_t work, height;
|
||||
point_t model_point;
|
||||
struct rt_tgc_internal *tgc =
|
||||
(struct rt_tgc_internal *)s->es_int.idb_ptr;
|
||||
@@ -822,6 +755,7 @@ ecmd_tgc_mv_hh(struct rt_edit *s)
|
||||
void *d = NULL;
|
||||
|
||||
RT_TGC_CK_MAGIC(tgc);
|
||||
VMOVE(height, tgc->h);
|
||||
if (s->e_inpara) {
|
||||
if (s->e_inpara != 3) {
|
||||
bu_vls_printf(s->log_str, "ERROR: three arguments needed\n");
|
||||
@@ -834,22 +768,20 @@ ecmd_tgc_mv_hh(struct rt_edit *s)
|
||||
if (s->mv_context) {
|
||||
/* apply s->e_invmat to convert to real model coordinates */
|
||||
MAT4X3PNT(work, s->e_invmat, model_point);
|
||||
VSUB2(tgc->h, work, tgc->v);
|
||||
VSUB2(height, work, tgc->v);
|
||||
} else {
|
||||
VSUB2(tgc->h, model_point, tgc->v);
|
||||
VSUB2(height, model_point, tgc->v);
|
||||
}
|
||||
}
|
||||
|
||||
/* check for zero H vector */
|
||||
if (MAGNITUDE(tgc->h) <= SQRT_SMALL_FASTF) {
|
||||
bu_vls_printf(s->log_str, "Zero H vector not allowed, resetting to +Z\n");
|
||||
if (edit_validate_height(s, height) != BRLCAD_OK) {
|
||||
rt_edit_map_clbk_get(&f, &d, s->m, ECMD_PRINT_RESULTS, BU_CLBK_DURING);
|
||||
if (f)
|
||||
(*f)(0, NULL, d, NULL);
|
||||
VSET(tgc->h, 0.0, 0.0, 1.0);
|
||||
return BRLCAD_ERROR;
|
||||
}
|
||||
|
||||
VMOVE(tgc->h, height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1005,7 +937,7 @@ ecmd_tgc_rot_ab(struct rt_edit *s)
|
||||
}
|
||||
|
||||
/* Use mouse to change location of point V+H */
|
||||
void
|
||||
static int
|
||||
ecmd_tgc_mv_h_mousevec(struct rt_edit *s, const vect_t mousevec)
|
||||
{
|
||||
struct rt_tgc_internal *tgc =
|
||||
@@ -1021,8 +953,13 @@ ecmd_tgc_mv_h_mousevec(struct rt_edit *s, const vect_t mousevec)
|
||||
/* Do NOT change pos_view[Z] ! */
|
||||
MAT4X3PNT(temp, s->vp->gv_view2model, pos_view);
|
||||
MAT4X3PNT(tr_temp, s->e_invmat, temp);
|
||||
VSUB2(tgc->h, tr_temp, tgc->v);
|
||||
vect_t height;
|
||||
VSUB2(height, tr_temp, tgc->v);
|
||||
if (edit_validate_height(s, height) != BRLCAD_OK)
|
||||
return BRLCAD_ERROR;
|
||||
VMOVE(tgc->h, height);
|
||||
edit_abs_tra(s, pos_view);
|
||||
return BRLCAD_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1188,8 +1125,7 @@ rt_edit_tgc_edit_xy(
|
||||
break;
|
||||
case ECMD_TGC_MV_H:
|
||||
case ECMD_TGC_MV_HH:
|
||||
ecmd_tgc_mv_h_mousevec(s, mousevec);
|
||||
return BRLCAD_OK;
|
||||
return ecmd_tgc_mv_h_mousevec(s, mousevec);
|
||||
case ECMD_TGC_ROT_H:
|
||||
case ECMD_TGC_ROT_AB:
|
||||
bu_vls_printf(s->log_str, "%s: XY edit undefined in solid edit mode %d\n", EDOBJ[ip->idb_type].ft_label, s->edit_flag);
|
||||
|
||||
@@ -778,6 +778,72 @@ bu_log("RT_MATRIX_EDIT_TRANS_MODEL_XYZ SUCCESS: "
|
||||
if (!edit_test_mouse_knobs_match(s, face_view_target))
|
||||
bu_exit(1, "ERROR: ARB8 mouse face knobs missed cursor\n");
|
||||
|
||||
/* A rejected drag must not become the starting geometry for the next. */
|
||||
struct rt_arb_internal valid_face_arb = *arb;
|
||||
plane_t valid_face_planes[ARB8_FACE_COUNT];
|
||||
memcpy(valid_face_planes, a->es_peqn, sizeof(valid_face_planes));
|
||||
s->local2base = 25.4;
|
||||
s->base2local = 1.0 / s->local2base;
|
||||
VSET(mousevec, 1.0, 0.0, 0.0); /* Collapse the moved face onto the opposite face. */
|
||||
if (EDOBJ[dp->d_minor_type].ft_edit_xy(s, mousevec) != BRLCAD_ERROR ||
|
||||
memcmp(arb->pt, valid_face_arb.pt, sizeof(arb->pt)) ||
|
||||
memcmp(a->es_peqn, valid_face_planes, sizeof(valid_face_planes)))
|
||||
bu_exit(1, "ERROR: rejected ARB8 mouse face move changed edit state\n");
|
||||
|
||||
const fastf_t face_drags[] = {0.3, 0.4, 0.25};
|
||||
const size_t drag_cycles = 32;
|
||||
const size_t drag_positions = sizeof(face_drags) / sizeof(face_drags[0]);
|
||||
for (size_t drag = 0; drag < drag_cycles * drag_positions; drag++) {
|
||||
fastf_t target_x = face_drags[drag % drag_positions];
|
||||
VSET(mousevec, target_x, 0.0, 0.0);
|
||||
if (EDOBJ[dp->d_minor_type].ft_edit_xy(s, mousevec) != BRLCAD_OK ||
|
||||
rt_edit_process(s) != BRLCAD_OK)
|
||||
bu_exit(1, "ERROR: ARB8 mouse face move failed after rejected drag\n");
|
||||
for (size_t i = 0; i < sizeof(face_points) / sizeof(face_points[0]); i++) {
|
||||
if (!NEAR_EQUAL(arb->pt[face_points[i]][X], target_x, VUNITIZE_TOL))
|
||||
bu_exit(1, "ERROR: repeated ARB8 mouse face move drifted\n");
|
||||
}
|
||||
}
|
||||
|
||||
struct rt_arb_internal before_rejected_calc = *arb;
|
||||
plane_t rejected_planes[ARB8_FACE_COUNT];
|
||||
memcpy(rejected_planes, a->es_peqn, sizeof(rejected_planes));
|
||||
rejected_planes[a->edit_menu][W] = VDOT(rejected_planes[a->edit_menu], arb->pt[1]);
|
||||
if (rt_arb_calc_points(arb, ARB8, (const plane_t *)rejected_planes, s->tol) >= 0 ||
|
||||
memcmp(arb->pt, before_rejected_calc.pt, sizeof(arb->pt)))
|
||||
bu_exit(1, "ERROR: rejected ARB point calculation changed geometry\n");
|
||||
|
||||
struct rt_arb_internal invalid_arb = *arb;
|
||||
VMOVE(invalid_arb.pt[6], invalid_arb.pt[5]);
|
||||
VMOVE(invalid_arb.pt[0], invalid_arb.pt[4]);
|
||||
memcpy(rejected_planes, a->es_peqn, sizeof(rejected_planes));
|
||||
plane_t unchanged_planes[ARB8_FACE_COUNT];
|
||||
memcpy(unchanged_planes, rejected_planes, sizeof(unchanged_planes));
|
||||
struct bu_vls rejected_plane_msg = BU_VLS_INIT_ZERO;
|
||||
if (rt_arb_calc_planes(&rejected_plane_msg, &invalid_arb, ARB8,
|
||||
rejected_planes, s->tol) >= 0 ||
|
||||
memcmp(rejected_planes, unchanged_planes, sizeof(rejected_planes)))
|
||||
bu_exit(1, "ERROR: rejected ARB plane calculation changed planes\n");
|
||||
bu_vls_free(&rejected_plane_msg);
|
||||
|
||||
struct rt_arb_internal before_rejected_edge = *arb;
|
||||
memcpy(rejected_planes, a->es_peqn, sizeof(rejected_planes));
|
||||
VSET(mousevec, 0.0, 1.0, 0.0); /* Move edge 12 onto the opposite edge. */
|
||||
if (rt_arb_edit(s->log_str, arb, NULL, ARB8, 0,
|
||||
RT_ARB_EDIT_DEFAULT, mousevec, rejected_planes, s->tol) == 0 ||
|
||||
memcmp(arb->pt, before_rejected_edge.pt, sizeof(arb->pt)) ||
|
||||
memcmp(rejected_planes, a->es_peqn, sizeof(rejected_planes)))
|
||||
bu_exit(1, "ERROR: rejected ARB edge edit changed geometry or planes\n");
|
||||
|
||||
memcpy(rejected_planes, a->es_peqn, sizeof(rejected_planes));
|
||||
VSETALL(mousevec, 0.0);
|
||||
if (rt_arb_edit(s->log_str, arb, NULL, ARB8, 0,
|
||||
RT_ARB_EDIT_EDGE_DIR, mousevec, rejected_planes, s->tol) == 0 ||
|
||||
!ZERO(MAGNITUDE(mousevec)) ||
|
||||
memcmp(arb->pt, before_rejected_edge.pt, sizeof(arb->pt)) ||
|
||||
memcmp(rejected_planes, a->es_peqn, sizeof(rejected_planes)))
|
||||
bu_exit(1, "ERROR: rejected ARB edge direction changed input or edit state\n");
|
||||
|
||||
s->local2base = 1.0;
|
||||
s->base2local = 1.0;
|
||||
|
||||
@@ -844,6 +910,29 @@ bu_log("RT_MATRIX_EDIT_TRANS_MODEL_XYZ SUCCESS: "
|
||||
ZERO(a->es_peqn[4][Y]))
|
||||
bu_exit(1, "ERROR: ARB extended face rotation changed input or left plane unchanged\n");
|
||||
|
||||
arb8_reset(s, arb, a);
|
||||
a->edit_menu = 0; /* Rotate the bottom plane onto a side plane. */
|
||||
a->fixv = 0;
|
||||
rt_edit_set_edflag(s, ECMD_ARB_ROTATE_FACE);
|
||||
s->mv_context = 0;
|
||||
s->e_inpara = 3;
|
||||
VSET(s->e_para, 0.0, 90.0, 0.0);
|
||||
MAT_IDN(s->acc_rot_sol);
|
||||
MAT_IDN(s->model_changes);
|
||||
MAT_IDN(s->incr_change);
|
||||
if (rt_arb_calc_planes(s->log_str, arb, ARB8, a->es_peqn, s->tol))
|
||||
bu_exit(1, "ERROR: ARB rejected-rotation setup failed\n");
|
||||
struct rt_arb_internal before_rejected_rotation = *arb;
|
||||
plane_t before_rotation_planes[ARB8_FACE_COUNT];
|
||||
mat_t before_rotation_acc;
|
||||
memcpy(before_rotation_planes, a->es_peqn, sizeof(before_rotation_planes));
|
||||
MAT_COPY(before_rotation_acc, s->acc_rot_sol);
|
||||
if (rt_edit_process(s) != BRLCAD_ERROR ||
|
||||
memcmp(arb->pt, before_rejected_rotation.pt, sizeof(arb->pt)) ||
|
||||
memcmp(a->es_peqn, before_rotation_planes, sizeof(before_rotation_planes)) ||
|
||||
memcmp(s->acc_rot_sol, before_rotation_acc, sizeof(before_rotation_acc)))
|
||||
bu_exit(1, "ERROR: rejected ARB face rotation changed edit state\n");
|
||||
|
||||
/* The same face operation must survive the interactive rotation knob
|
||||
* adapter, which supplies an incremental matrix rather than parameters.
|
||||
*/
|
||||
|
||||
@@ -402,6 +402,20 @@ rt_edit_test_bot(void)
|
||||
V3ARGS(&bot->vertices[4*3]));
|
||||
}
|
||||
|
||||
bot_reset(s, bot, b);
|
||||
/* An edge selection can become stale after a topology change. */
|
||||
bot->faces[0] = 0; bot->faces[1] = 2; bot->faces[2] = 3;
|
||||
bot->faces[3] = 1; bot->faces[4] = 2; bot->faces[5] = 3;
|
||||
int faces_before[12];
|
||||
memcpy(faces_before, bot->faces, sizeof(faces_before));
|
||||
b->bot_verts[0] = 0;
|
||||
b->bot_verts[1] = 1;
|
||||
EDOBJ[dp->d_minor_type].ft_set_edit_mode(s, ECMD_BOT_ESPLIT);
|
||||
if (rt_edit_process(s) != BRLCAD_ERROR ||
|
||||
bot->num_vertices != 4 || bot->num_faces != 4 ||
|
||||
memcmp(bot->faces, faces_before, sizeof(faces_before)))
|
||||
bu_exit(1, "ERROR: stale BOT edge split changed topology\n");
|
||||
|
||||
/* ================================================================
|
||||
* ECMD_BOT_FSPLIT: split face {0,2,3} of a fresh tetrahedron
|
||||
*
|
||||
|
||||
@@ -258,6 +258,27 @@ rt_edit_test_cline(void)
|
||||
rt_edit_process(s);
|
||||
if (cline_diff("ECMD_CLINE_MOVE_H", cmp, edit_cline))
|
||||
bu_exit(1, "ERROR: ECMD_CLINE_MOVE_H failed\n");
|
||||
|
||||
cline_reset(s, edit_cline, orig, cmp);
|
||||
s->e_inpara = 3;
|
||||
s->local2base = 25.4;
|
||||
s->base2local = 1.0 / s->local2base;
|
||||
VSCALE(s->e_para, orig->v, s->base2local);
|
||||
if (rt_edit_process(s) != BRLCAD_ERROR ||
|
||||
cline_diff("rejected zero-height move", cmp, edit_cline))
|
||||
bu_exit(1, "ERROR: rejected CLINE height move changed geometry\n");
|
||||
s->local2base = 1.0;
|
||||
s->base2local = 1.0;
|
||||
|
||||
cline_reset(s, edit_cline, orig, cmp);
|
||||
VMOVE(s->curr_e_axes_pos, orig->v);
|
||||
point_t rejected_view_target;
|
||||
MAT4X3PNT(rejected_view_target, v->gv_model2view, orig->v);
|
||||
VMOVE(mousevec, rejected_view_target);
|
||||
if (EDOBJ[dp->d_minor_type].ft_edit_xy(s, mousevec) != BRLCAD_ERROR ||
|
||||
cline_diff("rejected mouse zero-height move", cmp, edit_cline))
|
||||
bu_exit(1, "ERROR: rejected CLINE mouse height move changed geometry\n");
|
||||
VADD2(s->curr_e_axes_pos, orig->v, orig->h);
|
||||
bu_log("ECMD_CLINE_MOVE_H SUCCESS: h=%g,%g,%g\n", V3ARGS(edit_cline->h));
|
||||
|
||||
/* ================================================================
|
||||
|
||||
@@ -232,6 +232,27 @@ rt_edit_test_extrude(void)
|
||||
rt_edit_process(s);
|
||||
if (extr_diff("ECMD_EXTR_MOV_H", cmp, edit_extr))
|
||||
bu_exit(1, "ERROR: ECMD_EXTR_MOV_H failed\n");
|
||||
|
||||
extr_reset(s, edit_extr, orig, cmp);
|
||||
s->e_inpara = 3;
|
||||
s->local2base = 25.4;
|
||||
s->base2local = 1.0 / s->local2base;
|
||||
VSCALE(s->e_para, orig->V, s->base2local);
|
||||
if (rt_edit_process(s) != BRLCAD_ERROR ||
|
||||
extr_diff("rejected zero-height move", cmp, edit_extr))
|
||||
bu_exit(1, "ERROR: rejected EXTRUDE height move changed geometry\n");
|
||||
s->local2base = 1.0;
|
||||
s->base2local = 1.0;
|
||||
|
||||
extr_reset(s, edit_extr, orig, cmp);
|
||||
VMOVE(s->curr_e_axes_pos, orig->V);
|
||||
point_t rejected_view_target;
|
||||
MAT4X3PNT(rejected_view_target, v->gv_model2view, orig->V);
|
||||
VMOVE(mousevec, rejected_view_target);
|
||||
if (EDOBJ[dp->d_minor_type].ft_edit_xy(s, mousevec) != BRLCAD_ERROR ||
|
||||
extr_diff("rejected mouse zero-height move", cmp, edit_extr))
|
||||
bu_exit(1, "ERROR: rejected EXTRUDE mouse height move changed geometry\n");
|
||||
VADD2(s->curr_e_axes_pos, orig->V, orig->h);
|
||||
bu_log("ECMD_EXTR_MOV_H SUCCESS: h=%g,%g,%g\n", V3ARGS(edit_extr->h));
|
||||
|
||||
/* ================================================================
|
||||
|
||||
@@ -144,16 +144,66 @@ check_unit(fastf_t local2base, const char *unit)
|
||||
rt_edit_checkpoint(edit) != BRLCAD_OK)
|
||||
++failures;
|
||||
|
||||
uint8_t *saved_checkpoint = edit->es_ckpt.ext_buf;
|
||||
size_t saved_size = edit->es_ckpt.ext_nbytes;
|
||||
/* Force export failure without altering the saved checkpoint. */
|
||||
edit->es_int.idb_type = -1;
|
||||
int checkpoint_result = rt_edit_checkpoint(edit);
|
||||
edit->es_int.idb_type = ID_ELL;
|
||||
if (checkpoint_result != BRLCAD_ERROR ||
|
||||
edit->es_ckpt.ext_buf != saved_checkpoint ||
|
||||
edit->es_ckpt.ext_nbytes != saved_size || !same_ell(edit, 4))
|
||||
++failures;
|
||||
|
||||
/* This placeholder has no importer; failed revert must preserve ELL. */
|
||||
edit->es_int.idb_type = ID_UNUSED1;
|
||||
int revert_result = rt_edit_revert(edit);
|
||||
edit->es_int.idb_type = ID_ELL;
|
||||
if (revert_result != BRLCAD_ERROR || !same_ell(edit, 4) ||
|
||||
edit->es_ckpt.ext_buf != saved_checkpoint)
|
||||
++failures;
|
||||
bu_log("failed checkpoint/revert preserve state\t%s\t%s\n", unit,
|
||||
failures ? "fail" : "pass");
|
||||
|
||||
rt_edit_set_edflag(edit, RT_PARAMS_EDIT_SCALE);
|
||||
edit->update_views = 0;
|
||||
edit->e_inpara = 2;
|
||||
edit->e_mvalid = 1;
|
||||
edit->es_scale = 2.0;
|
||||
edit->e_para[0] = 2.0;
|
||||
edit->e_para[1] = 3.0;
|
||||
if (rt_edit_process(edit) != BRLCAD_ERROR ||
|
||||
edit->e_inpara || edit->e_mvalid || !ZERO(edit->es_scale) ||
|
||||
edit->update_views || !EQUAL(edit->e_para[0], 2.0) ||
|
||||
!same_ell(edit, 4))
|
||||
++failures;
|
||||
rt_edit_set_edflag(edit, ECMD_ELL_SCALE_A);
|
||||
if (rt_edit_process(edit) != BRLCAD_OK || !same_ell(edit, 4) ||
|
||||
edit->update_views != 1)
|
||||
++failures;
|
||||
if (rt_edit_process(edit) != BRLCAD_OK || edit->update_views != 1)
|
||||
++failures;
|
||||
bu_log("failed edit consumes input\t%s\t%s\n", unit,
|
||||
failures ? "fail" : "pass");
|
||||
|
||||
const fastf_t target_length = 2.0 * inch_to_mm;
|
||||
rt_edit_set_edflag(edit, ECMD_ELL_SCALE_A);
|
||||
edit->mv_context = 1;
|
||||
edit->e_inpara = 1;
|
||||
edit->e_para[0] = target_length / local2base;
|
||||
if (rt_edit_process(edit) != BRLCAD_OK ||
|
||||
!same_ell(edit, target_length) ||
|
||||
!NEAR_EQUAL(edit->e_para[0], target_length / local2base,
|
||||
VUNITIZE_TOL) ||
|
||||
rt_edit_revert(edit) != BRLCAD_OK || !same_ell(edit, 4))
|
||||
int edit_result = rt_edit_process(edit);
|
||||
bool scaled = same_ell(edit, target_length) &&
|
||||
NEAR_EQUAL(edit->e_para[0], target_length / local2base,
|
||||
VUNITIZE_TOL);
|
||||
edit->acc_sc_sol = 2.5;
|
||||
VSET(edit->e_keypoint, -1, -1, -1);
|
||||
point_t original_keypoint = {10, 5, 20};
|
||||
if (edit_result != BRLCAD_OK || !scaled ||
|
||||
rt_edit_revert(edit) != BRLCAD_OK || !same_ell(edit, 4) ||
|
||||
!EQUAL(edit->acc_sc_sol, 1.0) ||
|
||||
!VNEAR_EQUAL(edit->e_keypoint, original_keypoint, VUNITIZE_TOL))
|
||||
++failures;
|
||||
if (rt_edit_revert(edit) != BRLCAD_OK || !same_ell(edit, 4))
|
||||
++failures;
|
||||
bu_log("checkpoint/edit/revert\t%s\t%s\n", unit,
|
||||
failures ? "fail" : "pass");
|
||||
@@ -194,6 +244,18 @@ int
|
||||
rt_edit_test_lifecycle_matrix(void)
|
||||
{
|
||||
int failures = check_map();
|
||||
struct rt_edit *idle = rt_edit_create(NULL, NULL, NULL, NULL);
|
||||
if (!idle)
|
||||
return BRLCAD_ERROR;
|
||||
idle->e_inpara = 1;
|
||||
idle->e_mvalid = 1;
|
||||
idle->es_scale = 2.0;
|
||||
if (rt_edit_process(NULL) != BRLCAD_ERROR ||
|
||||
rt_edit_process(idle) != BRLCAD_ERROR ||
|
||||
idle->e_inpara || idle->e_mvalid || !ZERO(idle->es_scale) ||
|
||||
idle->update_views)
|
||||
++failures;
|
||||
rt_edit_destroy(idle);
|
||||
failures += check_unit(1.0, "mm");
|
||||
failures += check_unit(inch_to_mm, "in");
|
||||
return failures ? BRLCAD_ERROR : BRLCAD_OK;
|
||||
|
||||
@@ -282,6 +282,29 @@ nmg_tet_state(const struct rt_edit *edit,
|
||||
nmg_points_match(edit, expected, NMG_TET_VERTEX_COUNT);
|
||||
}
|
||||
|
||||
static bool
|
||||
nmg_tet_face_planes(const struct model *model,
|
||||
fastf_t planes[NMG_TET_FACE_COUNT][ELEMENTS_PER_PLANE])
|
||||
{
|
||||
size_t count = 0;
|
||||
struct nmgregion *region;
|
||||
for (BU_LIST_FOR(region, nmgregion, &model->r_hd)) {
|
||||
struct shell *shell;
|
||||
for (BU_LIST_FOR(shell, shell, ®ion->s_hd)) {
|
||||
struct faceuse *face;
|
||||
for (BU_LIST_FOR(face, faceuse, &shell->fu_hd)) {
|
||||
if (face->orientation != OT_SAME)
|
||||
continue;
|
||||
if (count == NMG_TET_FACE_COUNT || !face->f_p->g.plane_p)
|
||||
return false;
|
||||
memcpy(planes[count++], face->f_p->g.plane_p->N,
|
||||
sizeof(plane_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
return count == NMG_TET_FACE_COUNT;
|
||||
}
|
||||
|
||||
static int
|
||||
nmg_tet_step(struct rt_edit *edit, const char *unit, const char *name,
|
||||
int command, const fastf_t *params, int count,
|
||||
@@ -354,6 +377,34 @@ nmg_operation_matrix_unit(fastf_t local2base, const char *unit)
|
||||
ECMD_NMG_EKILL, NULL, 0, expected, -1, false, true);
|
||||
failures += nmg_tet_step(edit, unit, "reject extrusion without loop",
|
||||
ECMD_NMG_LEXTRU_DIR, extrude_direction, 4, expected, -1, false, true);
|
||||
|
||||
/* A target at the opposite face vertex makes its new plane degenerate. */
|
||||
struct rt_nmg_edit *selection = (struct rt_nmg_edit *)edit->ipe_ptr;
|
||||
struct model *model = (struct model *)edit->es_int.idb_ptr;
|
||||
struct nmgregion *region = BU_LIST_FIRST(nmgregion, &model->r_hd);
|
||||
struct shell *shell = BU_LIST_FIRST(shell, ®ion->s_hd);
|
||||
struct faceuse *face = BU_LIST_FIRST(faceuse, &shell->fu_hd);
|
||||
if (face->orientation != OT_SAME)
|
||||
face = face->fumate_p;
|
||||
struct loopuse *loop = BU_LIST_FIRST(loopuse, &face->lu_hd);
|
||||
selection->es_eu = BU_LIST_FIRST(edgeuse, &loop->down_hd);
|
||||
struct edgeuse *next = BU_LIST_PNEXT_CIRC(edgeuse, &selection->es_eu->l);
|
||||
point_t degenerate_target;
|
||||
VSCALE(degenerate_target, next->eumate_p->vu_p->v_p->vg_p->coord,
|
||||
1.0 / local2base);
|
||||
fastf_t before_planes[NMG_TET_FACE_COUNT][ELEMENTS_PER_PLANE];
|
||||
fastf_t after_planes[NMG_TET_FACE_COUNT][ELEMENTS_PER_PLANE];
|
||||
bool have_planes = nmg_tet_face_planes(model, before_planes);
|
||||
failures += nmg_tet_step(edit, unit, "reject degenerate edge move",
|
||||
ECMD_NMG_EMOVE, degenerate_target, 3, expected, -1, false, true);
|
||||
if (!have_planes || !nmg_tet_face_planes(
|
||||
(struct model *)edit->es_int.idb_ptr, after_planes) ||
|
||||
memcmp(before_planes, after_planes, sizeof(before_planes))) {
|
||||
bu_log("nmg\treject degenerate edge move planes\t%s\tfail\n", unit);
|
||||
++failures;
|
||||
}
|
||||
selection->es_eu = NULL;
|
||||
|
||||
failures += nmg_tet_step(edit, unit, "reject fractional vertex index",
|
||||
ECMD_NMG_VPICK, bad_pick, 1, expected, -1, false, true);
|
||||
failures += nmg_tet_step(edit, unit, "pick vertex",
|
||||
@@ -375,6 +426,45 @@ nmg_operation_matrix_unit(fastf_t local2base, const char *unit)
|
||||
failures += nmg_tet_step(edit, unit, "move face",
|
||||
ECMD_NMG_FMOVE, face_delta, 3, expected, 1, true);
|
||||
|
||||
/* A successful face-edge move must remap all live NMG selections. */
|
||||
model = (struct model *)edit->es_int.idb_ptr;
|
||||
region = BU_LIST_FIRST(nmgregion, &model->r_hd);
|
||||
shell = BU_LIST_FIRST(shell, ®ion->s_hd);
|
||||
face = BU_LIST_FIRST(faceuse, &shell->fu_hd);
|
||||
if (face->orientation != OT_SAME)
|
||||
face = face->fumate_p;
|
||||
loop = BU_LIST_FIRST(loopuse, &face->lu_hd);
|
||||
selection->es_eu = BU_LIST_FIRST(edgeuse, &loop->down_hd);
|
||||
point_t edge_target;
|
||||
VMOVE(edge_target, selection->es_eu->vu_p->v_p->vg_p->coord);
|
||||
edge_target[Y] += 0.1;
|
||||
edge_target[Z] += 0.1;
|
||||
rt_edit_set_edflag(edit, ECMD_NMG_EMOVE);
|
||||
edit->e_inpara = 3;
|
||||
VSCALE(edit->e_para, edge_target, 1.0 / local2base);
|
||||
int edge_result = rt_edit_process(edit);
|
||||
struct model *moved_model = (struct model *)edit->es_int.idb_ptr;
|
||||
if (edge_result != BRLCAD_OK || moved_model == model ||
|
||||
nmg_find_model(&selection->es_eu->l.magic) != moved_model ||
|
||||
nmg_find_model(&selection->es_v->magic) != moved_model ||
|
||||
nmg_find_model(&selection->es_fu->l.magic) != moved_model) {
|
||||
bu_log("nmg\tmove face edge and remap selections\t%s\tfail\n", unit);
|
||||
++failures;
|
||||
}
|
||||
|
||||
if (rt_edit_checkpoint(edit) != BRLCAD_OK) {
|
||||
bu_log("nmg\tcheckpoint selected model\t%s\tfail\n", unit);
|
||||
++failures;
|
||||
} else {
|
||||
selection->es_v->vg_p->coord[X] += 1.0;
|
||||
if (rt_edit_revert(edit) != BRLCAD_OK || selection->es_eu ||
|
||||
selection->es_v || selection->es_fu ||
|
||||
!edit->es_int.idb_ptr) {
|
||||
bu_log("nmg\trevert clears selected topology\t%s\tfail\n", unit);
|
||||
++failures;
|
||||
}
|
||||
}
|
||||
|
||||
rt_edit_destroy(edit);
|
||||
db_free_full_path(&path);
|
||||
db_close(dbip);
|
||||
@@ -702,6 +792,7 @@ rt_edit_test_nmg(void)
|
||||
bu_list_len(&wire_loop->down_hd) != edge_count ||
|
||||
!nmg_points_match(ws, wire_expected, NMG_WIRE_VERTEX_COUNT))
|
||||
bu_exit(1, "ERROR: NMG accepted a nonfinite edge split\n");
|
||||
ws->e_inpara = 3;
|
||||
VSCALE(ws->e_para, edge_midpoint, 1.0 / local2base);
|
||||
point_t split_input;
|
||||
VMOVE(split_input, ws->e_para);
|
||||
@@ -765,6 +856,7 @@ rt_edit_test_nmg(void)
|
||||
if (rt_edit_process(ws) == BRLCAD_OK ||
|
||||
!nmg_points_match(ws, wire_expected, NMG_WIRE_VERTEX_COUNT))
|
||||
bu_exit(1, "ERROR: NMG accepted a zero extrusion direction\n");
|
||||
ws->e_inpara = 4;
|
||||
ws->e_para[0] = 0.0; /* dir X */
|
||||
ws->e_para[1] = 0.0; /* dir Y */
|
||||
ws->e_para[2] = 1.0; /* dir Z */
|
||||
@@ -807,6 +899,7 @@ rt_edit_test_nmg(void)
|
||||
!nmg_points_match(ws, wire_and_prism_expected,
|
||||
NMG_WIRE_AND_PRISM_VERTEX_COUNT))
|
||||
bu_exit(1, "ERROR: NMG invalid preview target changed the solid\n");
|
||||
ws->e_inpara = 4;
|
||||
ws->e_para[Z] = 1.0;
|
||||
if (rt_edit_process(ws) != BRLCAD_OK)
|
||||
bu_exit(1, "ERROR: NMG repeated extrusion failed\n");
|
||||
@@ -834,6 +927,7 @@ rt_edit_test_nmg(void)
|
||||
!nmg_points_match(ws, wire_and_prism_expected,
|
||||
NMG_WIRE_AND_PRISM_VERTEX_COUNT))
|
||||
bu_exit(1, "ERROR: NMG accepted a nonfinite extrusion distance\n");
|
||||
ws->e_inpara = 1;
|
||||
ws->e_para[0] = 1.0 / local2base;
|
||||
if (rt_edit_process(ws) != BRLCAD_OK)
|
||||
bu_exit(1, "ERROR: NMG scalar extrusion failed\n");
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
#include "bu/log.h"
|
||||
@@ -262,6 +263,56 @@ same_arb_vertices(const struct rt_arb_internal *arb,
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
check_atomic_param_rejection(const struct param_case *test,
|
||||
struct rt_db_internal *ip, const struct bn_tol *tol,
|
||||
fastf_t local2base, const char *output)
|
||||
{
|
||||
std::string truncated(output);
|
||||
if (!truncated.empty() && truncated.back() == '\n')
|
||||
truncated.pop_back();
|
||||
size_t last_line = truncated.find_last_of('\n');
|
||||
if (last_line == std::string::npos)
|
||||
return 1;
|
||||
truncated.erase(last_line + 1);
|
||||
|
||||
const std::string invalid[] = {
|
||||
truncated,
|
||||
truncated + "invalid\n",
|
||||
std::string(output) + "unexpected: 1\n"
|
||||
};
|
||||
void *before = bu_malloc(test->parsed_size, "parameter reader snapshot");
|
||||
memcpy(before, test->parsed, test->parsed_size);
|
||||
int failures = 0;
|
||||
for (const std::string &text : invalid) {
|
||||
memcpy(test->parsed, before, test->parsed_size);
|
||||
int result = EDOBJ[test->type].ft_read_params(ip, text.c_str(), tol,
|
||||
local2base);
|
||||
if (result != BRLCAD_ERROR || !test->same(test->parsed, before))
|
||||
failures++;
|
||||
}
|
||||
memcpy(test->parsed, before, test->parsed_size);
|
||||
bu_free(before, "parameter reader snapshot");
|
||||
return failures;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_atomic_reader_type(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case ID_EPA:
|
||||
case ID_EHY:
|
||||
case ID_ETO:
|
||||
case ID_HYP:
|
||||
case ID_RPC:
|
||||
case ID_RHC:
|
||||
case ID_TGC:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
run_case(const struct param_case *test, fastf_t local2base, const char *unit)
|
||||
{
|
||||
@@ -296,6 +347,25 @@ run_case(const struct param_case *test, fastf_t local2base, const char *unit)
|
||||
bu_log("%s\tparams\t%s\twrong reconstructed geometry\n", test->name, unit);
|
||||
failed = 1;
|
||||
}
|
||||
if (check_atomic_reader_type(test->type)) {
|
||||
std::string crlf;
|
||||
for (const char *p = output; *p; ++p) {
|
||||
if (*p == '\n')
|
||||
crlf.push_back('\r');
|
||||
crlf.push_back(*p);
|
||||
}
|
||||
if (edit->ft_read_params(&ip, crlf.c_str(), &tol, local2base) != BRLCAD_OK ||
|
||||
!test->same(test->original, test->parsed)) {
|
||||
bu_log("%s\tparams\t%s\tCRLF reconstruction failed\n", test->name, unit);
|
||||
failed = 1;
|
||||
}
|
||||
}
|
||||
if (check_atomic_reader_type(test->type) &&
|
||||
check_atomic_param_rejection(test, &ip, &tol, local2base, output)) {
|
||||
bu_log("%s\tparams\t%s\trejected edit changed geometry\n",
|
||||
test->name, unit);
|
||||
failed = 1;
|
||||
}
|
||||
if (!failed)
|
||||
bu_log("%s\tparams\t%s\tpass\n", test->name, unit);
|
||||
bu_vls_free(&text);
|
||||
|
||||
@@ -1305,6 +1305,17 @@ bu_log("RT_MATRIX_EDIT_TRANS_MODEL_XYZ SUCCESS: "
|
||||
!NEAR_EQUAL(pipe_second(s)->pp_bendradius, 0.5 * inch, SMALL_FASTF))
|
||||
bu_exit(1, "ERROR: inch whole-pipe bend could not be set from zero\n");
|
||||
|
||||
pipe_full_reset(s, pe);
|
||||
if (rt_edit_checkpoint(s) != BRLCAD_OK)
|
||||
bu_exit(1, "ERROR: pipe checkpoint failed\n");
|
||||
pe->es_pipe_pnt = pipe_second(s);
|
||||
pipe_first(s)->pp_coord[X] = inch;
|
||||
VSET(s->e_keypoint, -1, -1, -1);
|
||||
if (rt_edit_revert(s) != BRLCAD_OK || pe->es_pipe_pnt ||
|
||||
!ZERO(pipe_first(s)->pp_coord[X]) ||
|
||||
!VNEAR_ZERO(s->e_keypoint, VUNITIZE_TOL))
|
||||
bu_exit(1, "ERROR: pipe revert retained stale geometry or selection\n");
|
||||
|
||||
int matrix_failures = pipe_transform_matrix(dbip, &fp, &tol, v);
|
||||
matrix_failures += pipe_dimension_matrix(dbip, &fp, &tol);
|
||||
matrix_failures += pipe_point_matrix(dbip, &fp, &tol);
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "vmath.h"
|
||||
#include "bu/log.h"
|
||||
#include "bu/malloc.h"
|
||||
@@ -156,6 +159,32 @@ check_rec_units(const fastf_t local2base)
|
||||
!NEAR_EQUAL(MAGNITUDE(rec->b), 2.5 * inch, VUNITIZE_TOL))
|
||||
bu_exit(1, "REC equal-radius edit did not use local units\n");
|
||||
|
||||
const struct rt_tgc_internal saved_rec = *rec;
|
||||
EDOBJ[ID_REC].ft_set_edit_mode(s, ECMD_REC_SET_V);
|
||||
s->e_inpara = 3;
|
||||
VSET(s->e_para, NAN, 0.0, 0.0);
|
||||
if (EDOBJ[ID_REC].ft_edit(s) != BRLCAD_ERROR ||
|
||||
memcmp(rec, &saved_rec, sizeof(saved_rec)))
|
||||
bu_exit(1, "REC accepted an invalid center or changed geometry\n");
|
||||
|
||||
EDOBJ[ID_REC].ft_set_edit_mode(s, ECMD_REC_SET_H);
|
||||
VSET(s->e_para, 0.0, 0.0, tol.dist * 0.5 / local2base);
|
||||
if (EDOBJ[ID_REC].ft_edit(s) != BRLCAD_ERROR ||
|
||||
memcmp(rec, &saved_rec, sizeof(saved_rec)))
|
||||
bu_exit(1, "REC accepted a near-zero height or changed geometry\n");
|
||||
|
||||
const int radius_commands[] = {
|
||||
ECMD_REC_SCALE_R1, ECMD_REC_SCALE_R2, ECMD_REC_SCALE_R
|
||||
};
|
||||
for (size_t i = 0; i < sizeof(radius_commands) / sizeof(radius_commands[0]); i++) {
|
||||
EDOBJ[ID_REC].ft_set_edit_mode(s, radius_commands[i]);
|
||||
s->e_inpara = 1;
|
||||
s->e_para[0] = NAN;
|
||||
if (EDOBJ[ID_REC].ft_edit(s) != BRLCAD_ERROR ||
|
||||
memcmp(rec, &saved_rec, sizeof(saved_rec)))
|
||||
bu_exit(1, "REC accepted an invalid radius or changed geometry\n");
|
||||
}
|
||||
|
||||
s->e_inpara = 1;
|
||||
s->e_para[0] = 0.0;
|
||||
if (EDOBJ[ID_REC].ft_edit(s) != BRLCAD_ERROR ||
|
||||
@@ -175,6 +204,16 @@ check_rec_units(const fastf_t local2base)
|
||||
EDOBJ[ID_REC].ft_edit_get_params(s, ECMD_REC_SCALE_R, NULL) >= 0)
|
||||
bu_exit(1, "REC getter accepted invalid arguments\n");
|
||||
|
||||
point_t saved_center;
|
||||
VMOVE(saved_center, rec->v);
|
||||
if (rt_edit_checkpoint(s) != BRLCAD_OK)
|
||||
bu_exit(1, "REC checkpoint failed\n");
|
||||
rec->v[X] += inch;
|
||||
if (rt_edit_revert(s) != BRLCAD_OK || s->es_int.idb_type != ID_REC ||
|
||||
!VNEAR_EQUAL(((struct rt_tgc_internal *)s->es_int.idb_ptr)->v,
|
||||
saved_center, VUNITIZE_TOL))
|
||||
bu_exit(1, "REC revert lost its type or geometry\n");
|
||||
|
||||
rt_edit_destroy(s);
|
||||
db_free_full_path(&fp);
|
||||
db_close(dbip);
|
||||
|
||||
@@ -420,6 +420,16 @@ rt_edit_test_sph(void)
|
||||
bu_exit(1, "SPH radius command did not restore degenerate axes\n");
|
||||
}
|
||||
|
||||
point_t saved_center;
|
||||
VMOVE(saved_center, ell->v);
|
||||
if (rt_edit_checkpoint(s) != BRLCAD_OK)
|
||||
bu_exit(1, "SPH checkpoint failed\n");
|
||||
ell->v[X] += 1.0;
|
||||
if (rt_edit_revert(s) != BRLCAD_OK || s->es_int.idb_type != ID_SPH ||
|
||||
!VNEAR_EQUAL(((struct rt_ell_internal *)s->es_int.idb_ptr)->v,
|
||||
saved_center, VUNITIZE_TOL))
|
||||
bu_exit(1, "SPH revert lost its type or geometry\n");
|
||||
|
||||
rt_edit_destroy(s);
|
||||
db_close(dbip);
|
||||
return 0;
|
||||
|
||||
@@ -386,6 +386,34 @@ rt_edit_test_tgc(void)
|
||||
bu_exit(1, "ERROR: ECMD_TGC_MV_HH failed\n");
|
||||
bu_log("ECMD_TGC_MV_HH SUCCESS: h=%g,%g,%g\n", V3ARGS(edit_tgc->h));
|
||||
|
||||
const int height_moves[] = {ECMD_TGC_MV_H, ECMD_TGC_MV_HH};
|
||||
for (size_t i = 0; i < sizeof(height_moves) / sizeof(height_moves[0]); i++) {
|
||||
tgc_reset(s, edit_tgc, orig_tgc, cmp_tgc);
|
||||
EDOBJ[dp->d_minor_type].ft_set_edit_mode(s, height_moves[i]);
|
||||
s->local2base = 25.4;
|
||||
s->base2local = 1.0 / s->local2base;
|
||||
s->e_inpara = 3;
|
||||
VSCALE(s->e_para, orig_tgc->v, s->base2local);
|
||||
int result = rt_edit_process(s);
|
||||
if (result != BRLCAD_ERROR ||
|
||||
tgc_diff("rejected zero-height move", cmp_tgc, edit_tgc))
|
||||
bu_exit(1, "ERROR: rejected TGC height move changed geometry (mode %d, result %d, h %g %g %g)\n",
|
||||
height_moves[i], result, V3ARGS(edit_tgc->h));
|
||||
s->local2base = 1.0;
|
||||
s->base2local = 1.0;
|
||||
}
|
||||
|
||||
tgc_reset(s, edit_tgc, orig_tgc, cmp_tgc);
|
||||
EDOBJ[dp->d_minor_type].ft_set_edit_mode(s, ECMD_TGC_MV_H);
|
||||
VMOVE(s->curr_e_axes_pos, orig_tgc->v);
|
||||
point_t rejected_view_target;
|
||||
MAT4X3PNT(rejected_view_target, v->gv_model2view, orig_tgc->v);
|
||||
VMOVE(mousevec, rejected_view_target);
|
||||
if (EDOBJ[dp->d_minor_type].ft_edit_xy(s, mousevec) != BRLCAD_ERROR ||
|
||||
tgc_diff("rejected mouse zero-height move", cmp_tgc, edit_tgc))
|
||||
bu_exit(1, "ERROR: rejected TGC mouse height move changed geometry\n");
|
||||
VADD2(s->curr_e_axes_pos, orig_tgc->v, orig_tgc->h);
|
||||
|
||||
/* ================================================================
|
||||
* ECMD_TGC_ROT_H (rotate H vector by (5,5,5) degrees about keypoint=v)
|
||||
* h_new = R * h where R = bn_mat_angles(5,5,5)
|
||||
|
||||
@@ -240,6 +240,22 @@ rt_edit_test_vol(void)
|
||||
bu_log("RT_PARAMS_EDIT_SCALE SUCCESS: mat[15]=%g (encodes scale=2)\n",
|
||||
edit_vol->mat[15]);
|
||||
|
||||
vol_reset(s, edit_vol);
|
||||
s->e_inpara = 2;
|
||||
s->e_para[0] = 2.0;
|
||||
s->e_para[1] = 3.0;
|
||||
if (rt_edit_process(s) != BRLCAD_ERROR ||
|
||||
!NEAR_EQUAL(edit_vol->mat[15], 1.0, VUNITIZE_TOL))
|
||||
bu_exit(1, "ERROR: rejected generic VOL scale changed geometry or succeeded\n");
|
||||
|
||||
vol_reset(s, edit_vol);
|
||||
s->e_inpara = 1;
|
||||
s->e_para[0] = 0.0;
|
||||
if (rt_edit_process(s) != BRLCAD_ERROR ||
|
||||
!NEAR_EQUAL(edit_vol->mat[15], 1.0, VUNITIZE_TOL) ||
|
||||
!NEAR_EQUAL(s->acc_sc_sol, 1.0, VUNITIZE_TOL))
|
||||
bu_exit(1, "ERROR: rejected zero VOL scale changed edit state\n");
|
||||
|
||||
/* ================================================================
|
||||
* RT_PARAMS_EDIT_TRANS (translate; keypoint (0,0,0) → e_para=(5,5,5))
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user