Beispiel #1
0
def PolyCutBar(ktbar, ktnode1, vc, vch, btop):
    assert not ktbar.bbardeleted, "polycutbar hits deletion"
    Dktbarstart = ktbar
    ktnoded1 = P3.Dot(vc, ktnode1.p)

    assert btop == (P3.Dot(vc, ktbar.nodemid.p) < vch), ("fg", btop,
                                                         P3.Dot(
                                                             vc,
                                                             ktbar.nodemid.p),
                                                         vch)
    #assert ktnoded0 < vch  # not necessarily true if bar points back with mid on end

    Dcount = 0
    while True:
        ktnode0 = ktnode1
        ktnode1 = ktbar.GetNodeFore(ktbar.nodeback == ktnode0)
        ktnoded0 = ktnoded1
        ktnoded1 = P3.Dot(vc, ktnode1.p)
        if btop == (ktnoded1 > vch):
            break
        ktbar = ktbar.GetForeRightBL(ktbar.nodefore == ktnode1)
        assert not ktbar.bbardeleted
        assert Dktbarstart != ktbar
        Dcount += 1
        assert Dcount < 1000
    ktbarlam = (vch - ktnoded0) / (ktnoded1 - ktnoded0)
    return ktnode0, ktbar, ktbarlam
Beispiel #2
0
    def getbarendclos(self, barstosplit):  # for plotting closest approaches
        pcs = []
        for bar in barstosplit:
            if bar.bbardeleted:
                continue
            if not ((bar.nodeback.pointzone.izone == barmesh.PZ_BEYOND_R) and
                    (bar.nodefore.pointzone.izone == barmesh.PZ_BEYOND_R)):
                continue
            vb = bar.nodefore.p - bar.nodeback.p
            vbsq = vb.Lensq()
            if bar.nodeback.pointzone.v is not None:
                lampcb = P3.Dot(bar.nodeback.pointzone.v, vb) / vbsq
                if 0 < lampcb < 1:
                    dvb = bar.nodeback.pointzone.v - vb * lampcb
                    assert abs(P3.Dot(dvb, vb)) < 0.001
                    dvbsq = dvb.Lensq()
                    if dvbsq < self.rdsq:
                        pcs.append(bar.nodeback.p + bar.nodeback.pointzone.v)

            if bar.nodefore.pointzone.v is not None:
                lampcf = -P3.Dot(bar.nodefore.pointzone.v, vb) / vbsq
                if 0 < lampcf < 1:
                    dvf = bar.nodefore.pointzone.v + vb * lampcf
                    assert abs(P3.Dot(dvf, vb)) < 0.001
                    dvfsq = dvf.Lensq()
                    if dvfsq < self.rdsq:
                        pcs.append(bar.nodeback.p + bar.nodefore.pointzone.v)
        return pcs
    def DistPtrianglePZ(self, p0, p1, p2):
        v1 = p1 - p0
        v2 = p2 - p0
        v1sq = v1.Lensq()
        v2sq = v2.Lensq()
        v1dv2 = P3.Dot(v1, v2)
        det = v1sq * v2sq - v1dv2**2
        if det == 0.0:
            return  # near zero width triangle has no face to touch
        invdet = 1.0 / det

        # should do distance by the dot on the crossproduct normal

        lv = self.p - p0
        v1dlv = P3.Dot(v1, lv)
        v2dlv = P3.Dot(v2, lv)

        # solve vd = lv - v1 * lam1 - v2 * lam2, where vd.v1 = vd.v2 = 0
        # (v1sq   v1dv2)   ( lam1 )   ( v1dlv )
        # (v1dv2   v2sq) . ( lam2 ) = ( v2dlv )
        lam1 = (v2sq * v1dlv - v1dv2 * v2dlv) * invdet
        lam2 = (-v1dv2 * v1dlv + v1sq * v2dlv) * invdet
        if 0 < lam1 and 0 < lam2 and lam1 + lam2 < 1:
            vd = lv - v1 * lam1 - v2 * lam2
            assert abs(P3.Dot(vd, v1)) < 0.001
            assert abs(P3.Dot(vd, v2)) < 0.001
            vdlen = vd.Len()
            if vdlen < self.r:
                self.r = vdlen
                self.v = -vd
Beispiel #4
0
    def InsertNodeIntoBarF(self, bar, newnode, bcolinear):
        assert newnode.p != bar.nodeback.p and newnode.p != bar.nodefore.p, newnode.p
        assert newnode in self.nodes

        if __debug__:
            if bcolinear:
                Dv = bar.nodefore.p - bar.nodeback.p
                Dv0 = newnode.p - bar.nodeback.p
                Dlam = P3.Dot(Dv0, Dv) / Dv.Lensq()
                assert 0 < Dlam < 1, Dlam
                Dvd = Dv0 - Dv * Dlam
                assert abs(P3.Dot(Dvd, Dv)) < 0.001
                assert Dvd.Len() < 0.01, (Dv, Dv0)

        barforeleft = bar.GetBarForeLeft()
        barbackright = bar.GetBarBackRight()

        barback = Bar(bar.nodeback, newnode)
        barfore = Bar(bar.nodefore, newnode)

        if bcolinear:  # copy over so we can identify colinearity from creation and not attempt to split along it
            assert (bar.barvecN - barback.barvecN).Len() < 1e-5, (
                bar.nodeback.p, newnode.p, bar.nodefore.p)
            assert (bar.barvecN + barfore.barvecN).Len() < 1e-5, (
                bar.nodeback.p, newnode.p, bar.nodefore.p)
            barback.barvecN = bar.barvecN
            barfore.barvecN = -bar.barvecN

        barback.cellmarkleft, barback.cellmarkright = bar.cellmarkleft, bar.cellmarkright
        barfore.cellmarkright, barfore.cellmarkleft = bar.cellmarkleft, bar.cellmarkright

        if barbackright:
            barback.barforeright = barfore
            barfore.barbackleft = bar.barforeright
            barbackright.SetForeRightBL(barbackright.nodefore == bar.nodeback,
                                        barback)

        if barforeleft:
            barback.barbackleft = bar.barbackleft
            barfore.barforeright = barback
            barforeleft.SetForeRightBL(barforeleft.nodefore == bar.nodefore,
                                       barfore)

        assert not barforeleft or barback.GetBarForeLeft(
        ) == barfore, barback.GetBarForeLeft()
        assert not barbackright or barfore.GetBarForeLeft(
        ) == barback, barfore.GetBarForeLeft()

        self.bars.append(barback)
        self.bars.append(barfore)

        bar.barforeright = barfore
        bar.barbackleft = barback
        bar.bbardeleted = True

        return newnode
 def DistPedgePZ(self, p0, p1):
     lv = self.p - p0
     v = p1 - p0
     vsq = v.Lensq()
     lam = P3.Dot(v, lv) / vsq
     if 0.0 < lam < 1.0:
         vd = lv - v * lam
         assert abs(P3.Dot(vd, v)) < 0.0001
         vdlen = vd.Len()
         if vdlen < self.r:
             self.r = vdlen
             self.v = -vd
    def DistLamPedgePZ(self, p0, p1):
        v = p1 - p0
        vsq = v.Lensq()

        lv = self.p - p0
        # solve |lv + vp * lam - v * mu| == r, where (lv + vp * lam - v * mu) . vp == 0
        mu0 = P3.Dot(lv, v) / vsq
        lvf = lv - v * mu0
        vpdv = P3.Dot(self.vp, v)
        muvp = vpdv / vsq

        vpf = self.vp - v * muvp
        vpfsq = vpf.Lensq()
        if vpfsq == 0.0:
            return
        assert abs(vpfsq - (self.vpsq - muvp * vpdv)) < 0.001

        lvfdvpf = P3.Dot(lvf, vpf)
        lamc = -lvfdvpf / vpfsq
        cp = lvf + vpf * lamc
        cpsq = cp.Lensq()
        lvfsq = lvf.Lensq()
        assert abs(cpsq -
                   (lvfsq + 2 * lvfdvpf * lamc + vpfsq * lamc * lamc)) < 0.001
        assert abs(P3.Dot(cp, vpf)) < 0.001
        llamdsq = self.rsq - cp.Lensq()
        if llamdsq < 0.0:
            return
        lamd = math.sqrt(llamdsq / vpfsq)
        if lamc + lamd < 0.0:
            return
        lam = lamc - lamd
        if lam < 0.0:
            return  # check closer stuff
        if lam > self.lam:
            return
        mu = mu0 + muvp * lam
        if mu < 0 or mu > 1:
            return
        dv = lv + self.vp * lam - v * mu
        assert abs(dv.Len() - self.r) < 0.001
        assert abs(P3.Dot(dv, v)) < 0.001
        self.lam = lam
Beispiel #7
0
    def calcsplithalfpos(self):
        # midpoint, but could be informed by multiple subdivisions on the rate of curvature
        # should also measure the bc.calccellcuttangency() and find a spot where it is properly wide and doesn't need to be tested
        vch = P3.Dot(self.vc, self.bar.nodemid.p + self.vc * 0.5)

        # find the splitting points
        self.ktnodetop, self.ktbartop, self.ktbartoplam = PolyCutBar(
            self.bar, self.node, self.vc, vch, True)
        self.ktnodebot, self.ktbarbot, self.ktbarbotlam = PolyCutBar(
            self.cbar, self.cbar.GetNodeFore(self.cbar.nodeback == self.cnode),
            self.vc, vch, False)
    def DistLamPtrianglePZ(self, p0, p1, p2):
        # solve vd = lv + vp * lam - v1 * lam1 - v2 * lam2, where |vd| = r and vd.v1 = vd.v2 = 0
        # solve +-r = (lv + vp * lam) . vnorm = lv . vnorm + vp . vnorm lam
        v1 = p1 - p0
        v2 = p2 - p0
        vcross = P3.Cross(v1, v2)
        assert abs(P3.Dot(vcross, v1)) < 0.001
        assert abs(P3.Dot(vcross, v2)) < 0.001
        vnorm = P3.ZNorm(vcross)

        lv = self.p - p0
        lvdvnorm = P3.Dot(lv, vnorm)
        vpdvnorm = P3.Dot(self.vp, vnorm)
        if vpdvnorm == 0.0:
            return
        # lam = (+-r - lvdvnorm)/vpdvnorm
        if vpdvnorm > 0.0:
            lam = (-self.r - lvdvnorm) / vpdvnorm
        else:
            lam = (self.r - lvdvnorm) / vpdvnorm
        if lam < 0 or lam > self.lam:
            return

        lvl = lv + self.vp * lam
        v1dlv = P3.Dot(v1, lvl)
        v2dlv = P3.Dot(v2, lvl)
        v1sq = v1.Lensq()
        v2sq = v2.Lensq()
        v1dv2 = P3.Dot(v1, v2)
        det = v1sq * v2sq - v1dv2**2
        if det == 0.0:
            return  # no face size
        invdet = 1.0 / det

        # solve vd = lv - v1 * lam1 - v2 * lam2, where vd.v1 = vd.v2 = 0
        # (v1sq   v1dv2)   ( lam1 )   ( v1dlv )
        # (v1dv2   v2sq) . ( lam2 ) = ( v2dlv )
        lam1 = (v2sq * v1dlv - v1dv2 * v2dlv) * invdet
        lam2 = (-v1dv2 * v1dlv + v1sq * v2dlv) * invdet
        if 0 < lam1 and 0 < lam2 and lam1 + lam2 < 1:
            vd = lvl - v1 * lam1 - v2 * lam2
            assert abs(P3.Dot(vd, v1)) < 0.001
            assert abs(P3.Dot(vd, v2)) < 0.001
            assert abs(vd.Len() - self.r) < 0.001
            self.lam = lam
Beispiel #9
0
 def shoulddivide(self, rd, contourdelta, contourdotdiff,
                  b2dcontournormals):
     if self.vc.Len() <= contourdelta:
         return False
     if b2dcontournormals:
         nd = P2.Dot(
             P2.ZNorm(
                 P2(self.bar.nodemid.pointzone.v.x,
                    self.bar.nodemid.pointzone.v.y)),
             P2.ZNorm(
                 P2(self.cbar.nodemid.pointzone.v.x,
                    self.cbar.nodemid.pointzone.v.y)))
     else:
         nd = P3.Dot(self.bar.nodemid.pointzone.v,
                     self.cbar.nodemid.pointzone.v) / (rd * rd)
     if nd >= contourdotdiff:
         return False
     return True
    def DistLamPpointPZ(self, p0):
        lv = p0 - self.p
        if lv.z < min(self.vp.z, 0) - self.r or lv.z > max(self.vp.z,
                                                           0) + self.r:
            return
        # |lv - vp * lam| = r
        # qa = vpsq
        qb2 = -P3.Dot(self.vp, lv)
        qc = lv.Lensq() - self.rsq

        qdq = qb2 * qb2 - self.vpsq * qc
        if qdq < 0.0:
            return
        qs = math.sqrt(qdq) / self.vpsq
        qm = -qb2 / self.vpsq
        assert abs(qc + (qm + qs) * (2 * qb2 + (qm + qs) * self.vpsq)) < 0.002
        if qm + qs <= 0.0:
            return
        laml = qm - qs
        if laml < 0.0:
            self.lam = 0.0  # shouldn't happen
        elif laml < self.lam:
            self.lam = laml
Beispiel #11
0
    def splitbarsdirectionchangesR(self, barstosplit):
        barsplitsdc = []
        bsdsq = self.barsplitdelta * self.barsplitdelta
        for bar in barstosplit:
            if bar.bbardeleted:
                continue
            if not ((bar.nodeback.pointzone.izone == barmesh.PZ_BEYOND_R) and
                    (bar.nodefore.pointzone.izone == barmesh.PZ_BEYOND_R)):
                continue
            vb = bar.nodefore.p - bar.nodeback.p
            vbsq = vb.Lensq()
            if vbsq < bsdsq:
                continue
            lamclossplit = -1
            dvbsq = -1
            if bar.nodeback.pointzone.v is not None:
                lampcb = P3.Dot(bar.nodeback.pointzone.v, vb) / vbsq
                if 0 < lampcb < 1:
                    dvb = bar.nodeback.pointzone.v - vb * lampcb
                    assert abs(P3.Dot(dvb, vb)) < 0.001
                    dvbsq = dvb.Lensq()
                    if dvbsq < self.rdsq:
                        lamclossplit = lampcb

            if bar.nodefore.pointzone.v is not None:
                lampcf = -P3.Dot(bar.nodefore.pointzone.v, vb) / vbsq
                if 0 < lampcf < 1:
                    dvf = bar.nodefore.pointzone.v + vb * lampcf
                    assert abs(P3.Dot(dvf, vb)) < 0.001
                    dvfsq = dvf.Lensq()
                    if dvfsq < self.rdsq:
                        if lamclossplit == -1 or dvfsq < dvbsq:
                            lamclossplit = 1 - lampcf

            if lamclossplit != -1:
                barsplitsdc.append((bar, lamclossplit))

        # split the bars
        nowsplitbars = []
        splitnodes = []
        for bar, lamc in barsplitsdc:
            splitnode = self.bm.InsertNodeIntoBarF(
                bar,
                self.bm.NewNode(Along(lamc, bar.nodeback.p, bar.nodefore.p)),
                True)
            assert bar.bbardeleted
            splitnodes.append(splitnode)
            nowsplitbars.append(bar.barforeright)
            nowsplitbars.append(bar.barbackleft)

        # make the measurements on all the new splitnodes
        self.MakePointZoneRFS(splitnodes)

        # make the measurements on all the new bars
        newbarpolycuts = []
        for bar in nowsplitbars:
            if IsCutBar(bar, barmesh.PZ_BEYOND_R):
                newbarpolycuts.append(bar)

        self.CutbarRFS(newbarpolycuts)
        #print("splitbarsdirectionchanges", len(barstosplit), len(nowsplitbars))
        return nowsplitbars
Beispiel #12
0
 def cperpbardotN(self, bar, v):
     assert self == bar.nodeback or self == bar.nodefore
     vb = (bar.nodefore.p - bar.nodeback.p)
     vbs = (self == bar.nodeback and +1 or -1)
     cperpvb = P3(vb.y * vbs, -vb.x * vbs, 0)
     return P3.Dot(cperpvb, v) / vb.Len()