本文整理汇总了C++中SSurface::NormalAt方法的典型用法代码示例。如果您正苦于以下问题:C++ SSurface::NormalAt方法的具体用法?C++ SSurface::NormalAt怎么用?C++ SSurface::NormalAt使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SSurface
的用法示例。
在下文中一共展示了SSurface::NormalAt方法的5个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: MakeFromRevolutionOf
//.........这里部分代码省略.........
ss->ctrl[0][2]);
sc.exact.weight[1] = ss->weight[0][1];
(sc.exact).MakePwlInto(&(sc.pts));
sc.surfA = revs.d[j];
sc.surfB = revsp.d[j];
hSCurve hcc = curve.AddAndAssignId(&sc);
STrimBy stb;
stb = STrimBy::EntireCurve(this, hcc, false);
(surface.FindById(sc.surfA))->trim.Add(&stb);
stb = STrimBy::EntireCurve(this, hcc, true);
(surface.FindById(sc.surfB))->trim.Add(&stb);
}
}
}
hsl.Clear();
}
for(i = i0; i < surface.n; i++) {
SSurface *srf = &(surface.elem[i]);
// Revolution of a line; this is potentially a plane, which we can
// rewrite to have degree (1, 1).
if(srf->degm == 1 && srf->degn == 2) {
// close start, far start, far finish
Vector cs, fs, ff;
double d0, d1;
d0 = (srf->ctrl[0][0]).DistanceToLine(pt, axis);
d1 = (srf->ctrl[1][0]).DistanceToLine(pt, axis);
if(d0 > d1) {
cs = srf->ctrl[1][0];
fs = srf->ctrl[0][0];
ff = srf->ctrl[0][2];
} else {
cs = srf->ctrl[0][0];
fs = srf->ctrl[1][0];
ff = srf->ctrl[1][2];
}
// origin close, origin far
Vector oc = cs.ClosestPointOnLine(pt, axis),
of = fs.ClosestPointOnLine(pt, axis);
if(oc.Equals(of)) {
// This is a plane, not a (non-degenerate) cone.
Vector oldn = srf->NormalAt(0.5, 0.5);
Vector u = fs.Minus(of), v;
v = (axis.Cross(u)).WithMagnitude(1);
double vm = (ff.Minus(of)).Dot(v);
v = v.ScaledBy(vm);
srf->degm = 1;
srf->degn = 1;
srf->ctrl[0][0] = of;
srf->ctrl[0][1] = of.Plus(u);
srf->ctrl[1][0] = of.Plus(v);
srf->ctrl[1][1] = of.Plus(u).Plus(v);
srf->weight[0][0] = 1;
srf->weight[0][1] = 1;
srf->weight[1][0] = 1;
srf->weight[1][1] = 1;
if(oldn.Dot(srf->NormalAt(0.5, 0.5)) < 0) {
swap(srf->ctrl[0][0], srf->ctrl[1][0]);
swap(srf->ctrl[0][1], srf->ctrl[1][1]);
}
continue;
}
if(fabs(d0 - d1) < LENGTH_EPS) {
// This is a cylinder; so transpose it so that we'll recognize
// it as a surface of extrusion.
SSurface sn = *srf;
// Transposing u and v flips the normal, so reverse u to
// flip it again and put it back where we started.
sn.degm = 2;
sn.degn = 1;
int dm, dn;
for(dm = 0; dm <= 1; dm++) {
for(dn = 0; dn <= 2; dn++) {
sn.ctrl [dn][dm] = srf->ctrl [1-dm][dn];
sn.weight[dn][dm] = srf->weight[1-dm][dn];
}
}
*srf = sn;
continue;
}
}
}
}
示例2: MakeCopyTrimAgainst
//-----------------------------------------------------------------------------
// Trim this surface against the specified shell, in the way that's appropriate
// for the specified Boolean operation type (and which operand we are). We
// also need a pointer to the shell that contains our own surface, since that
// contains our original trim curves.
//-----------------------------------------------------------------------------
SSurface SSurface::MakeCopyTrimAgainst(SShell *parent,
SShell *sha, SShell *shb,
SShell *into,
int type)
{
bool opA = (parent == sha);
SShell *agnst = opA ? shb : sha;
SSurface ret;
// The returned surface is identical, just the trim curves change
ret = *this;
ret.trim = {};
// First, build a list of the existing trim curves; update them to use
// the split curves.
STrimBy *stb;
for(stb = trim.First(); stb; stb = trim.NextAfter(stb)) {
STrimBy stn = *stb;
stn.curve = (parent->curve.FindById(stn.curve))->newH;
ret.trim.Add(&stn);
}
if(type == SShell::AS_DIFFERENCE && !opA) {
// The second operand of a Boolean difference gets turned inside out
ret.Reverse();
}
// Build up our original trim polygon; remember the coordinates could
// be changed if we just flipped the surface normal, and we are using
// the split curves (not the original curves).
SEdgeList orig = {};
ret.MakeEdgesInto(into, &orig, AS_UV);
ret.trim.Clear();
// which means that we can't necessarily use the old BSP...
SBspUv *origBsp = SBspUv::From(&orig, &ret);
// And now intersect the other shell against us
SEdgeList inter = {};
SSurface *ss;
for(ss = agnst->surface.First(); ss; ss = agnst->surface.NextAfter(ss)) {
SCurve *sc;
for(sc = into->curve.First(); sc; sc = into->curve.NextAfter(sc)) {
if(sc->source != SCurve::FROM_INTERSECTION) continue;
if(opA) {
if(sc->surfA.v != h.v || sc->surfB.v != ss->h.v) continue;
} else {
if(sc->surfB.v != h.v || sc->surfA.v != ss->h.v) continue;
}
int i;
for(i = 1; i < sc->pts.n; i++) {
Vector a = sc->pts.elem[i-1].p,
b = sc->pts.elem[i].p;
Point2d auv, buv;
ss->ClosestPointTo(a, &(auv.x), &(auv.y));
ss->ClosestPointTo(b, &(buv.x), &(buv.y));
int c = (ss->bsp) ? ss->bsp->ClassifyEdge(auv, buv, ss) : SBspUv::OUTSIDE;
if(c != SBspUv::OUTSIDE) {
Vector ta = Vector::From(0, 0, 0);
Vector tb = Vector::From(0, 0, 0);
ret.ClosestPointTo(a, &(ta.x), &(ta.y));
ret.ClosestPointTo(b, &(tb.x), &(tb.y));
Vector tn = ret.NormalAt(ta.x, ta.y);
Vector sn = ss->NormalAt(auv.x, auv.y);
// We are subtracting the portion of our surface that
// lies in the shell, so the in-plane edge normal should
// point opposite to the surface normal.
bool bkwds = true;
if((tn.Cross(b.Minus(a))).Dot(sn) < 0) bkwds = !bkwds;
if(type == SShell::AS_DIFFERENCE && !opA) bkwds = !bkwds;
if(bkwds) {
inter.AddEdge(tb, ta, sc->h.v, 1);
} else {
inter.AddEdge(ta, tb, sc->h.v, 0);
}
}
}
}
}
// Record all the points where more than two edges join, which I will call
// the choosing points. If two edges join at a non-choosing point, then
// they must either both be kept or both be discarded (since that would
// otherwise create an open contour).
SPointList choosing = {};
SEdge *se;
for(se = orig.l.First(); se; se = orig.l.NextAfter(se)) {
choosing.IncrementTagFor(se->a);
choosing.IncrementTagFor(se->b);
//.........这里部分代码省略.........
示例3: IntersectAgainst
void SSurface::IntersectAgainst(SSurface *b, SShell *agnstA, SShell *agnstB,
SShell *into)
{
Vector amax, amin, bmax, bmin;
GetAxisAlignedBounding(&amax, &amin);
b->GetAxisAlignedBounding(&bmax, &bmin);
if(Vector::BoundingBoxesDisjoint(amax, amin, bmax, bmin)) {
// They cannot possibly intersect, no curves to generate
return;
}
Vector alongt, alongb;
SBezier oft, ofb;
bool isExtdt = this->IsExtrusion(&oft, &alongt),
isExtdb = b->IsExtrusion(&ofb, &alongb);
if(degm == 1 && degn == 1 && b->degm == 1 && b->degn == 1) {
// Line-line intersection; it's a plane or nothing.
Vector na = NormalAt(0, 0).WithMagnitude(1),
nb = b->NormalAt(0, 0).WithMagnitude(1);
double da = na.Dot(PointAt(0, 0)),
db = nb.Dot(b->PointAt(0, 0));
Vector dl = na.Cross(nb);
if(dl.Magnitude() < LENGTH_EPS) return; // parallel planes
dl = dl.WithMagnitude(1);
Vector p = Vector::AtIntersectionOfPlanes(na, da, nb, db);
// Trim it to the region 0 <= {u,v} <= 1 for each plane; not strictly
// necessary, since line will be split and excess edges culled, but
// this improves speed and robustness.
int i;
double tmax = VERY_POSITIVE, tmin = VERY_NEGATIVE;
for(i = 0; i < 2; i++) {
SSurface *s = (i == 0) ? this : b;
Vector tu, tv;
s->TangentsAt(0, 0, &tu, &tv);
double up, vp, ud, vd;
s->ClosestPointTo(p, &up, &vp);
ud = (dl.Dot(tu)) / tu.MagSquared();
vd = (dl.Dot(tv)) / tv.MagSquared();
// so u = up + t*ud
// v = vp + t*vd
if(ud > LENGTH_EPS) {
tmin = max(tmin, -up/ud);
tmax = min(tmax, (1 - up)/ud);
} else if(ud < -LENGTH_EPS) {
tmax = min(tmax, -up/ud);
tmin = max(tmin, (1 - up)/ud);
} else {
if(up < -LENGTH_EPS || up > 1 + LENGTH_EPS) {
// u is constant, and outside [0, 1]
tmax = VERY_NEGATIVE;
}
}
if(vd > LENGTH_EPS) {
tmin = max(tmin, -vp/vd);
tmax = min(tmax, (1 - vp)/vd);
} else if(vd < -LENGTH_EPS) {
tmax = min(tmax, -vp/vd);
tmin = max(tmin, (1 - vp)/vd);
} else {
if(vp < -LENGTH_EPS || vp > 1 + LENGTH_EPS) {
// v is constant, and outside [0, 1]
tmax = VERY_NEGATIVE;
}
}
}
if(tmax > tmin + LENGTH_EPS) {
SBezier bezier = SBezier::From(p.Plus(dl.ScaledBy(tmin)),
p.Plus(dl.ScaledBy(tmax)));
AddExactIntersectionCurve(&bezier, b, agnstA, agnstB, into);
}
} else if((degm == 1 && degn == 1 && isExtdb) ||
(b->degm == 1 && b->degn == 1 && isExtdt))
{
// The intersection between a plane and a surface of extrusion
SSurface *splane, *sext;
if(degm == 1 && degn == 1) {
splane = this;
sext = b;
} else {
splane = b;
sext = this;
}
Vector n = splane->NormalAt(0, 0).WithMagnitude(1), along;
double d = n.Dot(splane->PointAt(0, 0));
SBezier bezier;
(void)sext->IsExtrusion(&bezier, &along);
if(fabs(n.Dot(along)) < LENGTH_EPS) {
// Direction of extrusion is parallel to plane; so intersection
// is zero or more lines. Build a line within the plane, and
// normal to the direction of extrusion, and intersect that line
// against the surface; each intersection point corresponds to
//.........这里部分代码省略.........
示例4: GenerateShellAndMesh
void Group::GenerateShellAndMesh(void) {
bool prevBooleanFailed = booleanFailed;
booleanFailed = false;
Group *srcg = this;
thisShell.Clear();
thisMesh.Clear();
runningShell.Clear();
runningMesh.Clear();
// Don't attempt a lathe or extrusion unless the source section is good:
// planar and not self-intersecting.
bool haveSrc = true;
if(type == EXTRUDE || type == LATHE) {
Group *src = SK.GetGroup(opA);
if(src->polyError.how != POLY_GOOD) {
haveSrc = false;
}
}
if(type == TRANSLATE || type == ROTATE) {
// A step and repeat gets merged against the group's prevous group,
// not our own previous group.
srcg = SK.GetGroup(opA);
GenerateForStepAndRepeat<SShell>(&(srcg->thisShell), &thisShell);
GenerateForStepAndRepeat<SMesh> (&(srcg->thisMesh), &thisMesh);
} else if(type == EXTRUDE && haveSrc) {
Group *src = SK.GetGroup(opA);
Vector translate = Vector::From(h.param(0), h.param(1), h.param(2));
Vector tbot, ttop;
if(subtype == ONE_SIDED) {
tbot = Vector::From(0, 0, 0); ttop = translate.ScaledBy(2);
} else {
tbot = translate.ScaledBy(-1); ttop = translate.ScaledBy(1);
}
SBezierLoopSetSet *sblss = &(src->bezierLoops);
SBezierLoopSet *sbls;
for(sbls = sblss->l.First(); sbls; sbls = sblss->l.NextAfter(sbls)) {
int is = thisShell.surface.n;
// Extrude this outer contour (plus its inner contours, if present)
thisShell.MakeFromExtrusionOf(sbls, tbot, ttop, color);
// And for any plane faces, annotate the model with the entity for
// that face, so that the user can select them with the mouse.
Vector onOrig = sbls->point;
int i;
for(i = is; i < thisShell.surface.n; i++) {
SSurface *ss = &(thisShell.surface.elem[i]);
hEntity face = Entity::NO_ENTITY;
Vector p = ss->PointAt(0, 0),
n = ss->NormalAt(0, 0).WithMagnitude(1);
double d = n.Dot(p);
if(i == is || i == (is + 1)) {
// These are the top and bottom of the shell.
if(fabs((onOrig.Plus(ttop)).Dot(n) - d) < LENGTH_EPS) {
face = Remap(Entity::NO_ENTITY, REMAP_TOP);
ss->face = face.v;
}
if(fabs((onOrig.Plus(tbot)).Dot(n) - d) < LENGTH_EPS) {
face = Remap(Entity::NO_ENTITY, REMAP_BOTTOM);
ss->face = face.v;
}
continue;
}
// So these are the sides
if(ss->degm != 1 || ss->degn != 1) continue;
Entity *e;
for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
if(e->group.v != opA.v) continue;
if(e->type != Entity::LINE_SEGMENT) continue;
Vector a = SK.GetEntity(e->point[0])->PointGetNum(),
b = SK.GetEntity(e->point[1])->PointGetNum();
a = a.Plus(ttop);
b = b.Plus(ttop);
// Could get taken backwards, so check all cases.
if((a.Equals(ss->ctrl[0][0]) && b.Equals(ss->ctrl[1][0])) ||
(b.Equals(ss->ctrl[0][0]) && a.Equals(ss->ctrl[1][0])) ||
(a.Equals(ss->ctrl[0][1]) && b.Equals(ss->ctrl[1][1])) ||
(b.Equals(ss->ctrl[0][1]) && a.Equals(ss->ctrl[1][1])))
{
face = Remap(e->h, REMAP_LINE_TO_FACE);
ss->face = face.v;
break;
}
}
}
}
} else if(type == LATHE && haveSrc) {
Group *src = SK.GetGroup(opA);
Vector pt = SK.GetEntity(predef.origin)->PointGetNum(),
//.........这里部分代码省略.........
示例5: ClassifyEdge
//-----------------------------------------------------------------------------
// Does the given point lie on our shell? There are many cases; inside and
// outside are obvious, but then there's all the edge-on-edge and edge-on-face
// possibilities.
//
// To calculate, we intersect a ray through p with our shell, and classify
// using the closest intersection point. If the ray hits a surface on edge,
// then just reattempt in a different random direction.
//-----------------------------------------------------------------------------
bool SShell::ClassifyEdge(int *indir, int *outdir,
Vector ea, Vector eb,
Vector p,
Vector edge_n_in, Vector edge_n_out, Vector surf_n)
{
List<SInter> l;
ZERO(&l);
srand(0);
// First, check for edge-on-edge
int edge_inters = 0;
Vector inter_surf_n[2], inter_edge_n[2];
SSurface *srf;
for(srf = surface.First(); srf; srf = surface.NextAfter(srf)) {
if(srf->LineEntirelyOutsideBbox(ea, eb, true)) continue;
SEdgeList *sel = &(srf->edges);
SEdge *se;
for(se = sel->l.First(); se; se = sel->l.NextAfter(se)) {
if((ea.Equals(se->a) && eb.Equals(se->b)) ||
(eb.Equals(se->a) && ea.Equals(se->b)) ||
p.OnLineSegment(se->a, se->b))
{
if(edge_inters < 2) {
// Edge-on-edge case
Point2d pm;
srf->ClosestPointTo(p, &pm, false);
// A vector normal to the surface, at the intersection point
inter_surf_n[edge_inters] = srf->NormalAt(pm);
// A vector normal to the intersecting edge (but within the
// intersecting surface) at the intersection point, pointing
// out.
inter_edge_n[edge_inters] =
(inter_surf_n[edge_inters]).Cross((se->b).Minus((se->a)));
}
edge_inters++;
}
}
}
if(edge_inters == 2) {
// TODO, make this use the appropriate curved normals
double dotp[2];
for(int i = 0; i < 2; i++) {
dotp[i] = edge_n_out.DirectionCosineWith(inter_surf_n[i]);
}
if(fabs(dotp[1]) < DOTP_TOL) {
SWAP(double, dotp[0], dotp[1]);
SWAP(Vector, inter_surf_n[0], inter_surf_n[1]);
SWAP(Vector, inter_edge_n[0], inter_edge_n[1]);
}
int coinc = (surf_n.Dot(inter_surf_n[0])) > 0 ? COINC_SAME : COINC_OPP;
if(fabs(dotp[0]) < DOTP_TOL && fabs(dotp[1]) < DOTP_TOL) {
// This is actually an edge on face case, just that the face
// is split into two pieces joining at our edge.
*indir = coinc;
*outdir = coinc;
} else if(fabs(dotp[0]) < DOTP_TOL && dotp[1] > DOTP_TOL) {
if(edge_n_out.Dot(inter_edge_n[0]) > 0) {
*indir = coinc;
*outdir = OUTSIDE;
} else {
*indir = INSIDE;
*outdir = coinc;
}
} else if(fabs(dotp[0]) < DOTP_TOL && dotp[1] < -DOTP_TOL) {
if(edge_n_out.Dot(inter_edge_n[0]) > 0) {
*indir = coinc;
*outdir = INSIDE;
} else {
*indir = OUTSIDE;
*outdir = coinc;
}
} else if(dotp[0] > DOTP_TOL && dotp[1] > DOTP_TOL) {
*indir = INSIDE;
*outdir = OUTSIDE;
} else if(dotp[0] < -DOTP_TOL && dotp[1] < -DOTP_TOL) {
*indir = OUTSIDE;
*outdir = INSIDE;
} else {
// Edge is tangent to the shell at shell's edge, so can't be
// a boundary of the surface.
return false;
}
return true;
}
//.........这里部分代码省略.........