Beispiel #1
0
const char *
socktohost(
    const sockaddr_u *sock
)
{
    const char		svc[] = "ntp";
    char *			pbuf;
    char *			pliar;
    int			gni_flags;
    struct addrinfo		hints;
    struct addrinfo *	alist;
    struct addrinfo *	ai;
    sockaddr_u		addr;
    size_t			octets;
    int			a_info;

    /* reverse the address to purported DNS name */
    LIB_GETBUF(pbuf);
    gni_flags = NI_DGRAM | NI_NAMEREQD;
    if (getnameinfo(&sock->sa, SOCKLEN(sock), pbuf, LIB_BUFLENGTH,
                    NULL, 0, gni_flags))
        return stoa(sock);	/* use address */

    TRACE(1, ("%s reversed to %s\n", stoa(sock), pbuf));

    /*
     * Resolve the reversed name and make sure the reversed address
     * is among the results.
     */
    ZERO(hints);
    hints.ai_family = AF(sock);
    hints.ai_protocol = IPPROTO_UDP;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags = 0;
    alist = NULL;

    a_info = getaddrinfo(pbuf, svc, &hints, &alist);
    if (a_info == EAI_NONAME
#ifdef EAI_NODATA
            || a_info == EAI_NODATA
#endif
       ) {
        hints.ai_flags = AI_CANONNAME;
#ifdef AI_ADDRCONFIG
        hints.ai_flags |= AI_ADDRCONFIG;
#endif
        a_info = getaddrinfo(pbuf, svc, &hints, &alist);
    }
#ifdef AI_ADDRCONFIG
    /* Some older implementations don't like AI_ADDRCONFIG. */
    if (a_info == EAI_BADFLAGS) {
        hints.ai_flags &= ~AI_ADDRCONFIG;
        a_info = getaddrinfo(pbuf, svc, &hints, &alist);
    }
#endif
    if (a_info)
        goto forward_fail;

    NTP_INSIST(alist != NULL);

    for (ai = alist; ai != NULL; ai = ai->ai_next) {
        /*
         * Make a convenience sockaddr_u copy from ai->ai_addr
         * because casting from sockaddr * to sockaddr_u * is
         * risking alignment problems on platforms where
         * sockaddr_u has stricter alignment than sockaddr,
         * such as sparc.
         */
        ZERO_SOCK(&addr);
        octets = min(sizeof(addr), ai->ai_addrlen);
        memcpy(&addr, ai->ai_addr, octets);
        if (SOCK_EQ(sock, &addr))
            break;
    }
    freeaddrinfo(alist);

    if (ai != NULL)
        return pbuf;	/* forward check passed */

forward_fail:
    TRACE(1, ("%s forward check lookup fail: %s\n", pbuf,
              gai_strerror(a_info)));
    LIB_GETBUF(pliar);
    snprintf(pliar, LIB_BUFLENGTH, "%s (%s)", stoa(sock), pbuf);

    return pliar;
}
Beispiel #2
0
static void call_ng_process_flags(struct sdp_ng_flags *out, bencode_item_t *input) {
	bencode_item_t *list, *it;
	int diridx;
	str s;

	ZERO(*out);

	if ((list = bencode_dictionary_get_expect(input, "flags", BENCODE_LIST))) {
		for (it = list->child; it; it = it->sibling) {
			if (!bencode_strcmp(it, "trust address"))
				out->trust_address = 1;
			else if (!bencode_strcmp(it, "asymmetric"))
				out->asymmetric = 1;
			else if (!bencode_strcmp(it, "trust-address"))
				out->trust_address = 1;
			else if (!bencode_strcmp(it, "strict source"))
				out->strict_source = 1;
			else if (!bencode_strcmp(it, "media handover"))
				out->media_handover = 1;
		}
	}

	if ((list = bencode_dictionary_get_expect(input, "replace", BENCODE_LIST))) {
		for (it = list->child; it; it = it->sibling) {
			if (!bencode_strcmp(it, "origin"))
				out->replace_origin = 1;
			else if (!bencode_strcmp(it, "session connection"))
				out->replace_sess_conn = 1;
			else if (!bencode_strcmp(it, "session-connection"))
				out->replace_sess_conn = 1;
		}
	}

	diridx = 0;
	if ((list = bencode_dictionary_get_expect(input, "direction", BENCODE_LIST))) {
		for (it = list->child; it && diridx < 2; it = it->sibling) {
			if (!bencode_strcmp(it, "internal"))
				out->directions[diridx++] = DIR_INTERNAL;
			else if (!bencode_strcmp(it, "external"))
				out->directions[diridx++] = DIR_EXTERNAL;
		}
	}

	list = bencode_dictionary_get_expect(input, "received from", BENCODE_LIST);
	if (!list)
		list = bencode_dictionary_get_expect(input, "received-from", BENCODE_LIST);
	if (list && (it = list->child)) {
		bencode_get_str(it, &out->received_from_family);
		bencode_get_str(it->sibling, &out->received_from_address);
	}

	if (bencode_dictionary_get_str(input, "ICE", &s)) {
		if (!str_cmp(&s, "remove"))
			out->ice_remove = 1;
		else if (!str_cmp(&s, "force"))
			out->ice_force = 1;
		else if (!str_cmp(&s, "force_relay"))
			out->ice_force_relay = 1;
	}

	if ((list = bencode_dictionary_get_expect(input, "rtcp-mux", BENCODE_LIST))) {
		for (it = list->child; it; it = it->sibling) {
			if (!bencode_strcmp(it, "offer"))
				out->rtcp_mux_offer = 1;
			else if (!bencode_strcmp(it, "demux"))
				out->rtcp_mux_demux = 1;
			else if (!bencode_strcmp(it, "accept"))
				out->rtcp_mux_accept = 1;
			else if (!bencode_strcmp(it, "reject"))
				out->rtcp_mux_reject = 1;
		}
	}

	bencode_dictionary_get_str(input, "transport protocol", &out->transport_protocol_str);
	if (!out->transport_protocol_str.s)
		bencode_dictionary_get_str(input, "transport-protocol", &out->transport_protocol_str);
	out->transport_protocol = transport_protocol(&out->transport_protocol_str);
	bencode_dictionary_get_str(input, "media address", &out->media_address);
	if (bencode_dictionary_get_str(input, "address family", &out->address_family_str))
		out->address_family = address_family(&out->address_family_str);
}
void SolveSpace::ExportSectionTo(char *filename) {
    Vector gn = (SS.GW.projRight).Cross(SS.GW.projUp);
    gn = gn.WithMagnitude(1);

    Group *g = SK.GetGroup(SS.GW.activeGroup);
    g->GenerateDisplayItems();
    if(g->displayMesh.IsEmpty()) {
        Error("No solid model present; draw one with extrudes and revolves, "
              "or use Export 2d View to export bare lines and curves.");
        return;
    }
    
    // The plane in which the exported section lies; need this because we'll
    // reorient from that plane into the xy plane before exporting.
    Vector origin, u, v, n;
    double d;

    SS.GW.GroupSelection();
#define gs (SS.GW.gs)
    if((gs.n == 0 && g->activeWorkplane.v != Entity::FREE_IN_3D.v)) {
        Entity *wrkpl = SK.GetEntity(g->activeWorkplane);
        origin = wrkpl->WorkplaneGetOffset();
        n = wrkpl->Normal()->NormalN();
        u = wrkpl->Normal()->NormalU();
        v = wrkpl->Normal()->NormalV();
    } else if(gs.n == 1 && gs.faces == 1) {
        Entity *face = SK.GetEntity(gs.entity[0]);
        origin = face->FaceGetPointNum();
        n = face->FaceGetNormalNum();
        if(n.Dot(gn) < 0) n = n.ScaledBy(-1);
        u = n.Normal(0);
        v = n.Normal(1);
    } else if(gs.n == 3 && gs.vectors == 2 && gs.points == 1) {
        Vector ut = SK.GetEntity(gs.entity[0])->VectorGetNum(),
               vt = SK.GetEntity(gs.entity[1])->VectorGetNum();
        ut = ut.WithMagnitude(1);
        vt = vt.WithMagnitude(1);

        if(fabs(SS.GW.projUp.Dot(vt)) < fabs(SS.GW.projUp.Dot(ut))) {
            SWAP(Vector, ut, vt);
        }
        if(SS.GW.projRight.Dot(ut) < 0) ut = ut.ScaledBy(-1);
        if(SS.GW.projUp.   Dot(vt) < 0) vt = vt.ScaledBy(-1);

        origin = SK.GetEntity(gs.point[0])->PointGetNum();
        n = ut.Cross(vt);
        u = ut.WithMagnitude(1);
        v = (n.Cross(u)).WithMagnitude(1);
    } else {
        Error("Bad selection for export section. Please select:\n\n"
              "    * nothing, with an active workplane "
                        "(workplane is section plane)\n"
              "    * a face (section plane through face)\n"
              "    * a point and two line segments "
                        "(plane through point and parallel to lines)\n");
        return;
    }
    SS.GW.ClearSelection();

    n = n.WithMagnitude(1);
    d = origin.Dot(n);

    SEdgeList el;
    ZERO(&el);
    SBezierList bl;
    ZERO(&bl);

    // If there's a mesh, then grab the edges from it.
    g->runningMesh.MakeEdgesInPlaneInto(&el, n, d);

    // If there's a shell, then grab the edges and possibly Beziers.
    g->runningShell.MakeSectionEdgesInto(n, d,
       &el, 
       (SS.exportPwlCurves || fabs(SS.exportOffset) > LENGTH_EPS) ? NULL : &bl);

    // All of these are solid model edges, so use the appropriate style.
    SEdge *se;
    for(se = el.l.First(); se; se = el.l.NextAfter(se)) {
        se->auxA = Style::SOLID_EDGE;
    }
    SBezier *sb;
    for(sb = bl.l.First(); sb; sb = bl.l.NextAfter(sb)) {
        sb->auxA = Style::SOLID_EDGE;
    }

    el.CullExtraneousEdges();
    bl.CullIdenticalBeziers();

    // And write the edges.
    VectorFileWriter *out = VectorFileWriter::ForFile(filename);
    if(out) {
        // parallel projection (no perspective), and no mesh
        ExportLinesAndMesh(&el, &bl, NULL,
                           u, v, n, origin, 0,
                           out);
    }
    el.Clear();
    bl.Clear();
}
Beispiel #4
0
/*
 * sendrequest - format and send a request packet
 *
 * Historically, ntpdc has used a fixed-size request packet regardless
 * of the actual payload size.  When authenticating, the timestamp, key
 * ID, and digest have been placed just before the end of the packet.
 * With the introduction in late 2009 of support for authenticated
 * ntpdc requests using larger 20-octet digests (vs. 16 for MD5), we
 * come up four bytes short.
 *
 * To maintain interop while allowing for larger digests, the behavior
 * is unchanged when using 16-octet digests.  For larger digests, the
 * timestamp, key ID, and digest are placed immediately following the
 * request payload, with the overall packet size variable.  ntpd can
 * distinguish 16-octet digests by the overall request size being
 * REQ_LEN_NOMAC + 4 + 16 with the auth bit enabled.  When using a
 * longer digest, that request size should be avoided.
 *
 * With the form used with 20-octet and larger digests, the timestamp,
 * key ID, and digest are located by ntpd relative to the start of the
 * packet, and the size of the digest is then implied by the packet
 * size.
 */
static int
sendrequest(
	int implcode,
	int reqcode,
	int auth,
	u_int qitems,
	size_t qsize,
	char *qdata
	)
{
	struct req_pkt qpkt;
	size_t	datasize;
	size_t	reqsize;
	u_long	key_id;
	l_fp	ts;
	l_fp *	ptstamp;
	int	maclen;
	char *	pass;

	ZERO(qpkt);
	qpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0);
	qpkt.implementation = (u_char)implcode;
	qpkt.request = (u_char)reqcode;

	datasize = qitems * qsize;
	if (datasize && qdata != NULL) {
		memcpy(qpkt.u.data, qdata, datasize);
		qpkt.err_nitems = ERR_NITEMS(0, qitems);
		qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize);
	} else {
		qpkt.err_nitems = ERR_NITEMS(0, 0);
		qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize);  /* allow for optional first item */
	}

	if (!auth || (keyid_entered && info_auth_keyid == 0)) {
		qpkt.auth_seq = AUTH_SEQ(0, 0);
		return sendpkt(&qpkt, req_pkt_size);
	}

	if (info_auth_keyid == 0) {
		key_id = getkeyid("Keyid: ");
		if (!key_id) {
			fprintf(stderr, "Invalid key identifier\n");
			return 1;
		}
		info_auth_keyid = key_id;
	}
	if (!authistrusted(info_auth_keyid)) {
		pass = getpass_keytype(info_auth_keytype);
		if ('\0' == pass[0]) {
			fprintf(stderr, "Invalid password\n");
			return 1;
		}
		authusekey(info_auth_keyid, info_auth_keytype,
			   (u_char *)pass);
		authtrust(info_auth_keyid, 1);
	}
	qpkt.auth_seq = AUTH_SEQ(1, 0);
	if (info_auth_hashlen > 16) {
		/*
		 * Only ntpd which expects REQ_LEN_NOMAC plus maclen
		 * octets in an authenticated request using a 16 octet
		 * digest (that is, a newer ntpd) will handle digests
		 * larger than 16 octets, so for longer digests, do
		 * not attempt to shorten the requests for downlevel
		 * ntpd compatibility.
		 */
		if (REQ_LEN_NOMAC != req_pkt_size)
			return 1;
		reqsize = REQ_LEN_HDR + datasize + sizeof(*ptstamp);
		/* align to 32 bits */
		reqsize = (reqsize + 3) & ~3;
	} else
		reqsize = req_pkt_size;
	ptstamp = (void *)((char *)&qpkt + reqsize);
	ptstamp--;
	get_systime(&ts);
	L_ADD(&ts, &delay_time);
	HTONL_FP(&ts, ptstamp);
	maclen = authencrypt(info_auth_keyid, (void *)&qpkt, reqsize);
	if (!maclen) {  
		fprintf(stderr, "Key not found\n");
		return 1;
	} else if (maclen != (int)(info_auth_hashlen + sizeof(keyid_t))) {
		fprintf(stderr,
			"%d octet MAC, %zu expected with %zu octet digest\n",
			maclen, (info_auth_hashlen + sizeof(keyid_t)),
			info_auth_hashlen);
		return 1;
	}
	return sendpkt(&qpkt, reqsize + maclen);
}
Beispiel #5
0
//-----------------------------------------------------------------------------
// 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;
    }

    if(edge_inters != 0) dbp("bad, edge_inters=%d", edge_inters);

    // Next, check for edge-on-surface. The ray-casting for edge-inside-shell
    // would catch this too, but test separately, for speed (since many edges
    // are on surface) and for numerical stability, so we don't pick up
    // the additional error from the line intersection.

    for(srf = surface.First(); srf; srf = surface.NextAfter(srf)) {
        if(srf->LineEntirelyOutsideBbox(ea, eb, true)) continue;

        Point2d puv;
        srf->ClosestPointTo(p, &(puv.x), &(puv.y), false);
        Vector pp = srf->PointAt(puv);

        if((pp.Minus(p)).Magnitude() > LENGTH_EPS) continue;
        Point2d dummy = { 0, 0 };
        int c = srf->bsp->ClassifyPoint(puv, dummy, srf);
        if(c == SBspUv::OUTSIDE) continue;

        // Edge-on-face (unless edge-on-edge above superceded)
        Point2d pin, pout;
        srf->ClosestPointTo(p.Plus(edge_n_in),  &pin,  false);
        srf->ClosestPointTo(p.Plus(edge_n_out), &pout, false);

        Vector surf_n_in  = srf->NormalAt(pin),
               surf_n_out = srf->NormalAt(pout);

        *indir  = ClassifyRegion(edge_n_in,  surf_n_in,  surf_n);
        *outdir = ClassifyRegion(edge_n_out, surf_n_out, surf_n);
        return true;
    }

    // Edge is not on face or on edge; so it's either inside or outside
    // the shell, and we'll determine which by raycasting.
    int cnt = 0;
    for(;;) {
        // Cast a ray in a random direction (two-sided so that we test if
        // the point lies on a surface, but use only one side for in/out
        // testing)
        Vector ray = Vector::From(Random(1), Random(1), Random(1));

        AllPointsIntersecting(
            p.Minus(ray), p.Plus(ray), &l, false, true, false);
        
        // no intersections means it's outside
        *indir  = OUTSIDE;
        *outdir = OUTSIDE;
        double dmin = VERY_POSITIVE;
        bool onEdge = false;
        edge_inters = 0;

        SInter *si;
        for(si = l.First(); si; si = l.NextAfter(si)) {
            double t = ((si->p).Minus(p)).DivPivoting(ray);
            if(t*ray.Magnitude() < -LENGTH_EPS) {
                // wrong side, doesn't count
                continue;
            }

            double d = ((si->p).Minus(p)).Magnitude();

            // We actually should never hit this case; it should have been
            // handled above.
            if(d < LENGTH_EPS && si->onEdge) {
                edge_inters++;
            }

            if(d < dmin) {
                dmin = d;
                // Edge does not lie on surface; either strictly inside
                // or strictly outside
                if((si->surfNormal).Dot(ray) > 0) {
                    *indir  = INSIDE;
                    *outdir = INSIDE;
                } else {
                    *indir  = OUTSIDE;
                    *outdir = OUTSIDE;
                }
                onEdge = si->onEdge;
            }
        }
        l.Clear();

        // If the point being tested lies exactly on an edge of the shell,
        // then our ray always lies on edge, and that's okay. Otherwise
        // try again in a different random direction.
        if(!onEdge) break;
        if(cnt++ > 5) {
            dbp("can't find a ray that doesn't hit on edge!");
            dbp("on edge = %d, edge_inters = %d", onEdge, edge_inters);
            SS.nakedEdges.AddEdge(ea, eb);
            break;
        }
    }

    return true;
}
Beispiel #6
0
EditMenu::EditMenu()
{
	LOG->Trace( "ScreenEditMenu::ScreenEditMenu()" );

	int i;

	for( i=0; i<2; i++ )
	{
		m_sprArrows[i].Load( THEME->GetPathToG(ssprintf("EditMenu %s",(i==0?"left":"right"))) );
		m_sprArrows[i].SetX( ARROWS_X(i) );
		this->AddChild( &m_sprArrows[i] );
	}

	m_SelectedRow = (Row)0;

	ZERO( m_iSelection );

	
	// start out on easy, not beginner
	m_iSelection[ROW_DIFFICULTY] = DIFFICULTY_EASY;
	m_iSelection[ROW_SOURCE_DIFFICULTY] = DIFFICULTY_EASY;



	for( i=0; i<NUM_ROWS; i++ )
	{
		m_textLabel[i].LoadFromFont( THEME->GetPathToF("Common title") );
		m_textLabel[i].SetXY( ROW_LABELS_X, ROW_Y(i) );
		m_textLabel[i].SetText( RowToString((Row)i) );
		m_textLabel[i].SetZoom( 0.8f );
		m_textLabel[i].SetHorizAlign( Actor::align_left );
		this->AddChild( &m_textLabel[i] );

		m_textValue[i].LoadFromFont( THEME->GetPathToF("Common normal") );
		m_textValue[i].SetXY( ROW_VALUE_X(i), ROW_Y(i) );
		m_textValue[i].SetText( "blah" );
		m_textValue[i].SetZoom( 0.8f );
		this->AddChild( &m_textValue[i] );
	}

	m_GroupBanner.SetXY( GROUP_BANNER_X, GROUP_BANNER_Y );
	this->AddChild( &m_GroupBanner );

	m_SongBanner.SetXY( SONG_BANNER_X, SONG_BANNER_Y );
	this->AddChild( &m_SongBanner );

	m_SongTextBanner.SetName( "TextBanner" );
	m_SongTextBanner.SetXY( SONG_TEXT_BANNER_X, SONG_TEXT_BANNER_Y );
	this->AddChild( &m_SongTextBanner );
	
	m_Meter.SetName( "EditDifficultyMeter", "DifficultyMeter" );
	m_Meter.SetXY( METER_X, METER_Y );
	m_Meter.Load();
	this->AddChild( &m_Meter );
	
	m_SourceMeter.SetName( "EditDifficultyMeter", "DifficultyMeter" );
	m_SourceMeter.SetXY( SOURCE_METER_X, SOURCE_METER_Y );
	m_SourceMeter.Load();
	this->AddChild( &m_SourceMeter );
	

	m_soundChangeRow.Load( THEME->GetPathToS("EditMenu row") );
	m_soundChangeValue.Load( THEME->GetPathToS("EditMenu value") );


	// fill in data structures
	SONGMAN->GetGroupNames( m_sGroups );
	GAMEMAN->GetStepsTypesForGame( GAMESTATE->m_pCurGame, m_StepsTypes );
	
	ChangeToRow( (Row)0 );
	OnRowValueChanged( (Row)0 );

	// Select the current song if any
	if( GAMESTATE->m_pCurSong )
	{
		unsigned i;

		for( i=0; i<m_sGroups.size(); i++ )
			if( GAMESTATE->m_pCurSong->m_sGroupName == m_sGroups[i] )
				m_iSelection[ROW_GROUP] = i;
		OnRowValueChanged( ROW_GROUP );

		for( i=0; i<m_pSongs.size(); i++ )
			if( GAMESTATE->m_pCurSong == m_pSongs[i] )
				m_iSelection[ROW_SONG] = i;
		OnRowValueChanged( ROW_SONG );

		// Select the current StepsType and difficulty if any
		if( GAMESTATE->m_pCurSteps[PLAYER_1] )
		{
			for( i=0; i<m_StepsTypes.size(); i++ )
			{
				if( m_StepsTypes[i] == GAMESTATE->m_pCurSteps[PLAYER_1]->m_StepsType )
				{
					m_iSelection[ROW_STEPS_TYPE] = i;
					OnRowValueChanged( ROW_STEPS_TYPE );
					m_iSelection[ROW_DIFFICULTY] = GAMESTATE->m_pCurSteps[PLAYER_1]->GetDifficulty();
					OnRowValueChanged( ROW_DIFFICULTY );
					break;
				}
			}
		}

	}
}
Beispiel #7
0
/*
 * openhost - open a socket to a host
 */
static int
openhost(
	const char *hname
	)
{
	char temphost[LENHOSTNAME];
	int a_info, i;
	struct addrinfo hints, *ai = NULL;
	sockaddr_u addr;
	size_t octets;
	register const char *cp;
	char name[LENHOSTNAME];
	char service[5];

	/*
	 * We need to get by the [] if they were entered 
	 */
	
	cp = hname;
	
	if (*cp == '[') {
		cp++;	
		for (i = 0; *cp && *cp != ']'; cp++, i++)
			name[i] = *cp;
		if (*cp == ']') {
			name[i] = '\0';
			hname = name;
		} else {
			return 0;
		}
	}	

	/*
	 * First try to resolve it as an ip address and if that fails,
	 * do a fullblown (dns) lookup. That way we only use the dns
	 * when it is needed and work around some implementations that
	 * will return an "IPv4-mapped IPv6 address" address if you
	 * give it an IPv4 address to lookup.
	 */
	strlcpy(service, "ntp", sizeof(service));
	ZERO(hints);
	hints.ai_family = ai_fam_templ;
	hints.ai_protocol = IPPROTO_UDP;
	hints.ai_socktype = SOCK_DGRAM;
	hints.ai_flags = Z_AI_NUMERICHOST;

	a_info = getaddrinfo(hname, service, &hints, &ai);
	if (a_info == EAI_NONAME
#ifdef EAI_NODATA
	    || a_info == EAI_NODATA
#endif
	   ) {
		hints.ai_flags = AI_CANONNAME;
#ifdef AI_ADDRCONFIG
		hints.ai_flags |= AI_ADDRCONFIG;
#endif
		a_info = getaddrinfo(hname, service, &hints, &ai);	
	}
	/* Some older implementations don't like AI_ADDRCONFIG. */
	if (a_info == EAI_BADFLAGS) {
		hints.ai_flags = AI_CANONNAME;
		a_info = getaddrinfo(hname, service, &hints, &ai);	
	}
	if (a_info != 0) {
		fprintf(stderr, "%s\n", gai_strerror(a_info));
		if (ai != NULL)
			freeaddrinfo(ai);
		return 0;
	}

	/* 
	 * getaddrinfo() has returned without error so ai should not 
	 * be NULL.
	 */
	INSIST(ai != NULL);
	ZERO(addr);
	octets = min(sizeof(addr), ai->ai_addrlen);
	memcpy(&addr, ai->ai_addr, octets);

	if (ai->ai_canonname == NULL)
		strlcpy(temphost, stoa(&addr), sizeof(temphost));
	else
		strlcpy(temphost, ai->ai_canonname, sizeof(temphost));

	if (debug > 2)
		printf("Opening host %s\n", temphost);

	if (havehost == 1) {
		if (debug > 2)
			printf("Closing old host %s\n", currenthost);
		closesocket(sockfd);
		havehost = 0;
	}
	strlcpy(currenthost, temphost, sizeof(currenthost));
	
	/* port maps to the same in both families */
	s_port = NSRCPORT(&addr);; 
#ifdef SYS_VXWORKS
	((struct sockaddr_in6 *)&hostaddr)->sin6_port = htons(SERVER_PORT_NUM);
	if (ai->ai_family == AF_INET)
		*(struct sockaddr_in *)&hostaddr= 
			*((struct sockaddr_in *)ai->ai_addr);
	else 
		*(struct sockaddr_in6 *)&hostaddr= 
			*((struct sockaddr_in6 *)ai->ai_addr);
#endif /* SYS_VXWORKS */

#ifdef SYS_WINNT
	{
		int optionValue = SO_SYNCHRONOUS_NONALERT;
		int err;

		err = setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&optionValue, sizeof(optionValue));
		if (err != NO_ERROR) {
			(void) fprintf(stderr, "cannot open nonoverlapped sockets\n");
			exit(1);
		}
	}
#endif /* SYS_WINNT */

	sockfd = socket(ai->ai_family, SOCK_DGRAM, 0);
	if (sockfd == INVALID_SOCKET) {
		error("socket");
		exit(-1);
	}
	
#ifdef NEED_RCVBUF_SLOP
# ifdef SO_RCVBUF
	{
		int rbufsize = INITDATASIZE + 2048; /* 2K for slop */

		if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
			       &rbufsize, sizeof(int)) == -1)
		    error("setsockopt");
	}
# endif
#endif

#ifdef SYS_VXWORKS
	if (connect(sockfd, (struct sockaddr *)&hostaddr, 
		    sizeof(hostaddr)) == -1) {
#else
	if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) == -1) {
#endif /* SYS_VXWORKS */
		error("connect");
		exit(-1);
	}

	freeaddrinfo(ai);
	havehost = 1;
	req_pkt_size = REQ_LEN_NOMAC;
	impl_ver = IMPL_XNTPD;
	return 1;
}


/* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
/*
 * sendpkt - send a packet to the remote host
 */
static int
sendpkt(
	void *	xdata,
	size_t	xdatalen
	)
{
	if (send(sockfd, xdata, xdatalen, 0) == -1) {
		warning("write to %s failed", currenthost);
		return -1;
	}

	return 0;
}


/*
 * growpktdata - grow the packet data area
 */
static void
growpktdata(void)
{
	size_t priorsz;

	priorsz = (size_t)pktdatasize;
	pktdatasize += INCDATASIZE;
	pktdata = erealloc_zero(pktdata, (size_t)pktdatasize, priorsz);
}
Beispiel #8
0
static int docset_check(Db *db, DocInfo *info, void *ctx)
{
    int errcode = 0;
    docset *ds = ctx;
    counterset *ctr = &ds->counters;
    Doc *doc;

    ctr->totaldocs++;
    if (info->deleted) {
        ctr->deleted++;
    }
    EQUAL_INFO_BUF(id);
    EQUAL_INFO_BUF(rev_meta);
    try(couchstore_open_doc_with_docinfo(db, info, &doc, DECOMPRESS_DOC_BODIES));
    if (testdocset.docs[testdocset.pos].data.size > 0) {
        assert(doc);
        EQUAL_DOC_BUF(data);
        EQUAL_DOC_BUF(id);
    }
    testdocset.pos++;
    couchstore_free_document(doc);
cleanup:
    assert(errcode == 0);
    return 0;
}

static int dociter_check(Db *db, DocInfo *info, void *ctx)
{
    int errcode = 0;
    docset *ds = ctx;
    counterset *ctr = &ds->counters;
    Doc *doc;

    ctr->totaldocs++;
    if (info->deleted) {
        ctr->deleted++;
    }
    try(couchstore_open_doc_with_docinfo(db, info, &doc, DECOMPRESS_DOC_BODIES));
    assert(doc);
    couchstore_free_document(doc);
cleanup:
    assert(errcode == 0);
    return 0;
}

static int dump_count(Db *db)
{
    int errcode = 0;
    ZERO(counters);
    try(couchstore_changes_since(db, 0, 0, counter_inc, &counters));
cleanup:
    assert(errcode == 0);
    return errcode;
}

static char zerometa[] = {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3};

static void test_save_docs(int count, const char *doc_tpl)
{
    int errcode = 0;
    int i;
    char *idBuf, *valueBuf;
    Doc **docptrs;
    DocInfo **nfoptrs;
    sized_buf *ids = NULL;
    uint64_t idtreesize = 0;
    uint64_t seqtreesize = 0;
    uint64_t docssize = 0;
    uint64_t dbfilesize = 0;
    uint64_t *sequences = NULL;
    const raw_by_id_reduce *reduce;
    Db *db;

    fprintf(stderr, "save_docs (doc count %d)... ", count);
    fflush(stderr);

    docset_init(count);
    srand(0xdeadbeef); /* doc IDs should be consistent across runs */
    for (i = 0; i < count; ++i) {
        int idsize;
        int valsize;

        idBuf = (char *) malloc(sizeof(char) * 32);
        assert(idBuf != NULL);
        idsize = sprintf(idBuf, "doc%d-%lu", i, (unsigned long)rand());
        valueBuf = (char *) malloc(sizeof(char) * (strlen(doc_tpl) + 20));
        assert(valueBuf != NULL);
        valsize = sprintf(valueBuf, doc_tpl, i + 1);
        setdoc(&testdocset.docs[i], &testdocset.infos[i],
                idBuf, idsize, valueBuf, valsize, zerometa, sizeof(zerometa));
        testdocset.datasize += valsize;
    }

    docptrs = (Doc **) malloc(sizeof(Doc*) * count);
    assert(docptrs != NULL);
    for (i = 0; i < count; ++i) {
        docptrs[i] = &testdocset.docs[i];
    }

    nfoptrs = (DocInfo **) malloc(sizeof(DocInfo*) * count);
    assert(nfoptrs != NULL);
    for (i = 0; i < count; ++i) {
        nfoptrs[i] = &testdocset.infos[i];
    }

    remove(testfilepath);
    try(couchstore_open_db(testfilepath, COUCHSTORE_OPEN_FLAG_CREATE, &db));
    assert(strcmp(couchstore_get_db_filename(db), testfilepath) == 0);
    try(couchstore_save_documents(db, docptrs, nfoptrs, count, 0));
    try(couchstore_commit(db));
    couchstore_close_db(db);

    try(couchstore_open_db(testfilepath, 0, &db));

    /* Read back by doc ID: */
    fprintf(stderr, "get by ID... ");
    testdocset.pos = 0;
    for (i = 0; i < count; ++i) {
        DocInfo* out_info;
        try(couchstore_docinfo_by_id(db, testdocset.docs[i].id.buf, testdocset.docs[i].id.size,
                                     &out_info));
        docset_check(db, out_info, &testdocset);
        couchstore_free_docinfo(out_info);
    }

    /* Read back in bulk by doc ID: */
    fprintf(stderr, "bulk IDs... ");
    ids = malloc(count * sizeof(sized_buf));
    for (i = 0; i < count; ++i) {
        ids[i] = docptrs[i]->id;
    }
    ZERO(testdocset.counters);
    try(couchstore_docinfos_by_id(db, ids, count, 0, dociter_check, &testdocset));
    assert(testdocset.counters.totaldocs == count);
    assert(testdocset.counters.deleted == 0);

    /* Read back by sequence: */
    fprintf(stderr, "get by sequence... ");
    sequences = malloc(count * sizeof(*sequences));
    testdocset.pos = 0;
    for (i = 0; i < count; ++i) {
        DocInfo* out_info;
        sequences[i] = testdocset.infos[i].db_seq;
        assert(sequences[i] == (uint64_t)i + 1);
        try(couchstore_docinfo_by_sequence(db, testdocset.infos[i].db_seq, &out_info));
        docset_check(db, out_info, &testdocset);
        couchstore_free_docinfo(out_info);
    }

    /* Read back in bulk by sequence: */
    fprintf(stderr, "bulk sequences... ");
    testdocset.pos = 0;
    ZERO(testdocset.counters);
    try(couchstore_docinfos_by_sequence(db, sequences, count, 0, docset_check, &testdocset));
    assert(testdocset.counters.totaldocs == count);
    assert(testdocset.counters.deleted == 0);

    /* Read back using changes_since: */
    fprintf(stderr, "changes_since... ");
    testdocset.pos = 0;
    ZERO(testdocset.counters);
    try(couchstore_changes_since(db, 0, 0, docset_check, &testdocset));
    assert(testdocset.counters.totaldocs == count);
    assert(testdocset.counters.deleted == 0);

    idtreesize = db->header.by_id_root->subtreesize;
    seqtreesize = db->header.by_seq_root->subtreesize;
    reduce = (const raw_by_id_reduce*)db->header.by_id_root->reduce_value.buf;
    docssize = decode_raw48(reduce->size);
    dbfilesize = db->file.pos;

    assert(dbfilesize > 0);
    assert(idtreesize > 0);
    assert(seqtreesize > 0);
    assert(docssize > 0);
    assert(idtreesize < dbfilesize);
    assert(seqtreesize < dbfilesize);
    assert(docssize < dbfilesize);
    assert(db->header.local_docs_root == NULL);
    assert((idtreesize + seqtreesize + docssize) < dbfilesize);

    couchstore_close_db(db);
cleanup:
    free(ids);
    free(sequences);
    for (i = 0; i < count; ++i) {
        free(docptrs[i]->id.buf);
        free(docptrs[i]->data.buf);
    }
    free(docptrs);
    free(nfoptrs);
    assert(errcode == 0);
}

static void test_save_doc(void)
{
    int errcode = 0;
    Db *db;
    unsigned i;
    DbInfo info;
    fprintf(stderr, "save_doc... ");
    fflush(stderr);
    docset_init(4);
    SETDOC(0, "doc1", "{\"test_doc_index\":1}", zerometa);
    SETDOC(1, "doc2", "{\"test_doc_index\":2}", zerometa);
    SETDOC(2, "doc3", "{\"test_doc_index\":3}", zerometa);
    SETDOC(3, "doc4", "{\"test_doc_index\":4}", zerometa);
    remove(testfilepath);
    try(couchstore_open_db(testfilepath, COUCHSTORE_OPEN_FLAG_CREATE, &db));
    try(couchstore_save_document(db, &testdocset.docs[0],
                                     &testdocset.infos[0], 0));
    try(couchstore_save_document(db, &testdocset.docs[1],
                                     &testdocset.infos[1], 0));
    try(couchstore_save_document(db, &testdocset.docs[2],
                                     &testdocset.infos[2], 0));
    try(couchstore_save_document(db, &testdocset.docs[3],
                                     &testdocset.infos[3], 0));
    try(couchstore_commit(db));
    couchstore_close_db(db);

    /* Check that sequence numbers got filled in */
    for (i = 0; i < 4; ++i) {
        assert(testdocset.infos[i].db_seq == i + 1);
    }

    /* Read back */
    try(couchstore_open_db(testfilepath, 0, &db));
    try(couchstore_changes_since(db, 0, 0, docset_check, &testdocset));
    assert(testdocset.counters.totaldocs == 4);
    assert(testdocset.counters.deleted == 0);

    assert(couchstore_db_info(db, &info) == COUCHSTORE_SUCCESS);
    assert(info.last_sequence == 4);
    assert(info.doc_count == 4);
    assert(info.deleted_count == 0);
    assert(info.header_position == 4096);

    couchstore_close_db(db);
cleanup:
    assert(errcode == 0);
}

static void test_compressed_doc_body(void)
{
    Db *db;
    Doc *docptrs[2];
    DocInfo *nfoptrs[2];
    int errcode = 0;

    fprintf(stderr, "compressed bodies... ");
    fflush(stderr);
    docset_init(2);
    SETDOC(0, "doc1", "{\"test_doc_index\":1, \"val\":\"blah blah blah blah blah blah\"}", zerometa);
    SETDOC(1, "doc2", "{\"test_doc_index\":2, \"val\":\"blah blah blah blah blah blah\"}", zerometa);

    docptrs[0] = &testdocset.docs[0];
    docptrs[1] = &testdocset.docs[1];
    nfoptrs[0] = &testdocset.infos[0];
    nfoptrs[1] = &testdocset.infos[1];

    /* Mark doc2 as to be snappied. */
    testdocset.infos[1].content_meta = COUCH_DOC_IS_COMPRESSED;
    remove(testfilepath);
    try(couchstore_open_db(testfilepath, COUCHSTORE_OPEN_FLAG_CREATE, &db));
    try(couchstore_save_documents(db, docptrs, nfoptrs, 2,
                                      COMPRESS_DOC_BODIES));
    try(couchstore_commit(db));
    couchstore_close_db(db);
    /* Read back */
    try(couchstore_open_db(testfilepath, 0, &db));
    try(couchstore_changes_since(db, 0, 0, docset_check, &testdocset));
    assert(testdocset.counters.totaldocs == 2);
    assert(testdocset.counters.deleted == 0);
    couchstore_close_db(db);
cleanup:
    assert(errcode == 0);
}

static void test_dump_empty_db(void)
{
    Db *db;
    couchstore_error_t errcode;
    DbInfo info;

    fprintf(stderr, "dump empty db... ");
    fflush(stderr);
    remove(testfilepath);

    try(couchstore_open_db(testfilepath, COUCHSTORE_OPEN_FLAG_CREATE, &db));
    try(couchstore_close_db(db));
    try(couchstore_open_db(testfilepath, 0, &db));
    dump_count(db);
    assert(counters.totaldocs == 0);
    assert(counters.deleted == 0);

    assert(couchstore_db_info(db, &info) == COUCHSTORE_SUCCESS);
    assert(strcmp(info.filename, testfilepath) == 0);
    assert(info.last_sequence == 0);
    assert(info.doc_count == 0);
    assert(info.deleted_count == 0);
    assert(info.space_used == 0);
    assert(info.header_position == 0);

    couchstore_close_db(db);
cleanup:
    assert(errcode == 0);
}

static void test_local_docs(void)
{
    int errcode = 0;
    Db *db;
    LocalDoc lDocWrite;
    LocalDoc *lDocRead = NULL;
    fprintf(stderr, "local docs... ");
    fflush(stderr);
    remove(testfilepath);
    try(couchstore_open_db(testfilepath, COUCHSTORE_OPEN_FLAG_CREATE, &db));
    lDocWrite.id.buf = "_local/testlocal";
    lDocWrite.id.size = 16;
    lDocWrite.json.buf = "{\"test\":true}";
    lDocWrite.json.size = 13;
    lDocWrite.deleted = 0;
    couchstore_save_local_document(db, &lDocWrite);
    couchstore_commit(db);
    couchstore_close_db(db);
    couchstore_open_db(testfilepath, 0, &db);
    couchstore_open_local_document(db, "_local/testlocal", 16, &lDocRead);
    assert(lDocRead);
    assert(lDocRead->json.size == 13);
    assert(memcmp(lDocRead->json.buf, "{\"test\":true}", 13) == 0);
    couchstore_free_local_document(lDocRead);
    couchstore_close_db(db);
cleanup:
    assert(errcode == 0);
}

static void test_open_file_error(void)
{
    Db *db = NULL;
    int errcode;

    fprintf(stderr, "opening nonexistent file errors... ");
    fflush(stderr);
    remove(testfilepath);
    errcode = couchstore_open_db(testfilepath, 0, &db);

    if (errcode != 0) {
        print_os_err(db);
    }

    assert(errcode == COUCHSTORE_ERROR_NO_SUCH_FILE);

    /* make sure os.c didn't accidentally call close(0): */
#ifndef WIN32
    assert(lseek(0, 0, SEEK_CUR) >= 0 || errno != EBADF);
#endif
}

static void shuffle(Doc **docs, DocInfo **docinfos, size_t n)
{
    if (n > 1) {
        size_t i;
        for (i = 0; i < n - 1; i++) {
          size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
          DocInfo *docinfo;
          Doc *doc = docs[j];
          docs[j] = docs[i];
          docs[i] = doc;

          docinfo = docinfos[j];
          docinfos[j] = docinfos[i];
          docinfos[i] = docinfo;
        }
    }
}

static int docmap_check(Db *db, DocInfo *info, void *ctx)
{
    char* docmap = (char*)ctx;
    int i;
    char buffer[100];
    (void)db;
    memcpy(buffer, info->id.buf, info->id.size);
    buffer[info->id.size] = 0; /* null terminate */
    sscanf(buffer, "doc%d", &i);
    assert(docmap[i] == 0);
    docmap[i] = 1;
    return 0;
}

static void test_changes_no_dups(void)
{
    int errcode = 0;
    int i;
    const int numdocs = 10000;
    int updatebatch = 1000;
    Doc **docptrs;
    DocInfo **nfoptrs;
    char *docmap;
    Db *db;
    DbInfo info;
    fprintf(stderr, "changes no dupes... ");
    fflush(stderr);

    docset_init(numdocs);
    for (i=0; i < numdocs; i++) {
        char* id = malloc(100);
        char* body = malloc(100);
        sprintf(id, "doc%d", i);
        sprintf(body, "{\"test_doc_index\":%d}", i);
        setdoc(&testdocset.docs[i], &testdocset.infos[i],
                id, strlen(id),
                body, strlen(body),
                zerometa, sizeof(zerometa));
    }
    docptrs = malloc(numdocs * sizeof(Doc*));
    nfoptrs = malloc(numdocs * sizeof(DocInfo*));
    docmap = malloc(numdocs);
    for (i=0; i < numdocs; i++) {
        docptrs[i] = &testdocset.docs[i];
        nfoptrs[i] = &testdocset.infos[i];
    }
    remove(testfilepath);
    try(couchstore_open_db(testfilepath, COUCHSTORE_OPEN_FLAG_CREATE, &db));
    /* only save half the docs at first. */
    try(couchstore_save_documents(db, docptrs, nfoptrs, numdocs/2, 0));
    try(couchstore_commit(db));
    couchstore_close_db(db);

    for (i=0; i < numdocs/2; i++) {
        /* increment the rev for already added docs */
        nfoptrs[i]->rev_seq++;
    }
    srand(10); /* make deterministic */
    /* now shuffle so some bulk updates contain previous docs and new docs */
    shuffle(docptrs, nfoptrs, numdocs);
    try(couchstore_open_db(testfilepath, 0, &db));
    for (i=0; i < numdocs; i += updatebatch) {
        /* now do bulk updates and check the changes for dups */
        try(couchstore_save_documents(db, docptrs + i, nfoptrs + i, updatebatch, 0));
        try(couchstore_commit(db));
        memset(docmap, 0, numdocs);
        try(couchstore_changes_since(db, 0, 0, docmap_check, docmap));
    }

    assert(couchstore_db_info(db, &info) == COUCHSTORE_SUCCESS);
    assert(info.last_sequence == (uint64_t)(numdocs + numdocs/2));
    assert(info.doc_count == (uint64_t)numdocs);
    assert(info.deleted_count == 0);

    couchstore_close_db(db);
cleanup:
    for (i=0; i < numdocs; i++) {
        free(docptrs[i]->id.buf);
        free(docptrs[i]->data.buf);
    }
    free(docptrs);
    free(nfoptrs);
    free(docmap);
    assert(errcode == 0);
}


static void mb5086(void)
{
    Db *db;
    Doc d;
    DocInfo i;
    couchstore_error_t err;

    fprintf(stderr, "regression mb-5086.... ");
    fflush(stderr);

    setdoc(&d, &i, "hi", 2, "foo", 3, NULL, 0);
    err = couchstore_open_db("mb5085.couch", COUCHSTORE_OPEN_FLAG_CREATE, &db);
    assert(err == COUCHSTORE_SUCCESS);
    assert(couchstore_save_document(db, &d, &i, 0) == COUCHSTORE_SUCCESS);
    assert(couchstore_commit(db) == COUCHSTORE_SUCCESS);
    assert(couchstore_close_db(db) == COUCHSTORE_SUCCESS);
    assert(remove("mb5085.couch") == 0);
}

static void test_asis_seqs(void)
{
   Db *db = NULL;
   Doc d;
   DocInfo i;
   DocInfo *ir;
   couchstore_error_t errcode;

   fprintf(stderr, "as-is seqs.... ");
   fflush(stderr);

   try(couchstore_open_db(testfilepath, COUCHSTORE_OPEN_FLAG_CREATE, &db));
   setdoc(&d, &i, "test", 4, "foo", 3, NULL, 0);
   i.db_seq = 1;
   try(couchstore_save_document(db, &d, &i, COUCHSTORE_SEQUENCE_AS_IS));
   assert(db->header.update_seq == 1);

   setdoc(&d, &i, "test_two", 8, "foo", 3, NULL, 0);
   i.db_seq = 12;
   try(couchstore_save_document(db, &d, &i, COUCHSTORE_SEQUENCE_AS_IS));
   assert(db->header.update_seq == 12);

   setdoc(&d, &i, "test_foo", 8, "foo", 3, NULL, 0);
   i.db_seq = 6;
   try(couchstore_save_document(db, &d, &i, COUCHSTORE_SEQUENCE_AS_IS));
   assert(db->header.update_seq == 12);

   try(couchstore_docinfo_by_id(db, "test", 4, &ir));
   assert(ir->db_seq == 1);
   couchstore_free_docinfo(ir);

   try(couchstore_docinfo_by_id(db, "test_two", 8, &ir));
   assert(ir->db_seq == 12);
   couchstore_free_docinfo(ir);

   try(couchstore_docinfo_by_id(db, "test_foo", 8, &ir));
   assert(ir->db_seq == 6);
   couchstore_free_docinfo(ir);

cleanup:
   if (db != NULL) {
       couchstore_close_db(db);
   }
   assert(errcode == COUCHSTORE_SUCCESS);
}

static void test_huge_revseq(void)
{
    Db *db;
    Doc d;
    DocInfo i;
    DocInfo *i2;
    couchstore_error_t err;

    fprintf(stderr, "huge rev_seq.... ");
    fflush(stderr);

    setdoc(&d, &i, "hi", 2, "foo", 3, NULL, 0);
    i.rev_seq = 5294967296;

    err = couchstore_open_db("bigrevseq.couch", COUCHSTORE_OPEN_FLAG_CREATE, &db);
    assert(err == COUCHSTORE_SUCCESS);
    assert(couchstore_save_document(db, &d, &i, 0) == COUCHSTORE_SUCCESS);
    assert(couchstore_commit(db) == COUCHSTORE_SUCCESS);
    assert(couchstore_docinfo_by_id(db, "hi", 2, &i2) == COUCHSTORE_SUCCESS);
    assert(i2->rev_seq == 5294967296);
    couchstore_free_docinfo(i2);
    assert(couchstore_close_db(db) == COUCHSTORE_SUCCESS);
    assert(remove("bigrevseq.couch") == 0);
}

static void test_dropped_handle(void)
{
   couchstore_error_t errcode;
   Db* db = NULL;
   Doc d;
   DocInfo i;
   Doc* rd;

   fprintf(stderr, "drop file handle.... ");
   fflush(stderr);

   try(couchstore_open_db(testfilepath, COUCHSTORE_OPEN_FLAG_CREATE, &db));
   setdoc(&d, &i, "test", 4, "foo", 3, NULL, 0);
   try(couchstore_save_document(db, &d, &i, 0));
   try(couchstore_commit(db));

   try(couchstore_drop_file(db));
   assert(couchstore_save_document(db, &d, &i, 0) == COUCHSTORE_ERROR_FILE_CLOSED);

   try(couchstore_reopen_file(db, testfilepath, 0));

   try(couchstore_open_document(db, "test", 4, &rd, 0));
   couchstore_free_document(rd);
cleanup:
   if (db != NULL) {
       couchstore_close_db(db);
   }
   assert(errcode == COUCHSTORE_SUCCESS);
}

int main(int argc, const char *argv[])
{
    int doc_counts[] = { 4, 69, 666, 9090 };
    unsigned i;
    const char *small_doc_tpl = "{\"test_doc_index\":%d}";
    const char *large_doc_tpl =
        "{"
        "\"test_doc_index\":%d,"
        "\"field1\": \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\","
        "\"field2\": \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\","
        "\"field3\": \"cccccccccccccccccccccccccccccccccccccccccccccccccc"
        "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
        "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
        "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
        "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
        "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
        "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\""
        "}";

    file_merger_tests();
    file_sorter_tests();

    if (argc > 1)
        strcpy(testfilepath, argv[1]);
    printf("Using test database at %s\n", testfilepath);

    test_bitfield_fns();

    test_open_file_error();
    fprintf(stderr, "OK \n");
    test_dump_empty_db();
    fprintf(stderr, " OK\n");
    test_save_doc();
    fprintf(stderr, " OK\n");
    for (i = 0; i < (sizeof(doc_counts) / sizeof(int)); ++i) {
        test_save_docs(doc_counts[i], small_doc_tpl);
        fprintf(stderr, " OK\n");
        test_save_docs(doc_counts[i], large_doc_tpl);
        fprintf(stderr, " OK\n");
    }
    test_local_docs();
    fprintf(stderr, " OK\n");
    test_compressed_doc_body();
    fprintf(stderr, " OK\n");
    test_changes_no_dups();
    fprintf(stderr, " OK\n");
    mb5086();
    fprintf(stderr, " OK\n");
    remove(testfilepath);
    test_huge_revseq();
    fprintf(stderr, " OK\n");
    remove(testfilepath);
    test_asis_seqs();
    fprintf(stderr, " OK\n");
    remove(testfilepath);
    test_dropped_handle();
    fprintf(stderr, " OK\n");
    remove(testfilepath);

    /* make sure os.c didn't accidentally call close(0): */
#ifndef WIN32
    assert(lseek(0, 0, SEEK_CUR) >= 0 || errno != EBADF);
#endif

    mapreduce_tests();
    view_tests();
    purge_tests();

    return 0;
}
Beispiel #9
0
/**
 * Zero the KUID.
 */
void
kuid_zero(kuid_t *res)
{
	ZERO(&res->v);
}
int
bn_mat_inverse(register mat_t output, const mat_t input)
{
    register int i, j;	/* Indices */
    int k;		/* Indices */
    int z[4];		/* Temporary */
    fastf_t b[4];	/* Temporary */
    fastf_t c[4];	/* Temporary */

    MAT_COPY(output, input);	/* Duplicate */

    /* Initialization */
    for (j = 0; j < 4; j++) {
	z[j] = j;
    }

    /* Main Loop */
    for (i = 0; i < 4; i++) {
	register fastf_t y;		/* local temporary */

	k = i;
	y = output[i * 4 + i];
	for (j = i + 1; j < 4; j++) {
	    register fastf_t w;		/* local temporary */

	    w = output[i * 4 + j];
	    if (fabs(w) > fabs(y)) {
		k = j;
		y = w;
	    }
	}

	if (ZERO(y)) {
	    /* SINGULAR */
	    return 0;
	}
	y = 1.0 / y;

	for (j = 0; j < 4; j++) {
	    register fastf_t temp;	/* Local */

	    c[j] = output[j * 4 + k];
	    output[j * 4 + k] = output[j * 4 + i];
	    output[j * 4 + i] = - c[j] * y;
	    temp = output[i * 4 + j] * y;
	    b[j] = temp;
	    output[i * 4 + j] = temp;
	}

	output[i * 4 + i] = y;
	j = z[i];
	z[i] = z[k];
	z[k] = j;
	for (k = 0; k < 4; k++) {
	    if (k == i) {
		continue;
	    }
	    for (j = 0; j < 4; j++) {
		if (j == i) {
		    continue;
		}
		output[k * 4 + j] = output[k * 4 + j] - b[j] * c[k];
	    }
	}
    }

    /* Second Loop */
    for (i = 0; i < 4; i++) {
	while ((k = z[i]) != i) {
	    int p;			/* Local temp */

	    for (j = 0; j < 4; j++) {
		register fastf_t w;	/* Local temp */

		w = output[i * 4 + j];
		output[i * 4 + j] = output[k * 4 + j];
		output[k * 4 + j] = w;
	    }
	    p = z[i];
	    z[i] = z[k];
	    z[k] = p;
	}
    }

    return 1;
}
void
bn_mat_angles(
    register fastf_t *mat,
    double alpha_in,
    double beta_in,
    double ggamma_in)
{
    double alpha, beta, ggamma;
    double calpha, cbeta, cgamma;
    double salpha, sbeta, sgamma;

    if (NEAR_ZERO(alpha_in, 0.0) && NEAR_ZERO(beta_in, 0.0) && NEAR_ZERO(ggamma_in, 0.0)) {
	MAT_IDN(mat);
	return;
    }

    alpha = alpha_in * DEG2RAD;
    beta = beta_in * DEG2RAD;
    ggamma = ggamma_in * DEG2RAD;

    calpha = cos(alpha);
    cbeta = cos(beta);
    cgamma = cos(ggamma);

    /* sine of "180*DEG2RAD" will not be exactly zero and will
     * result in errors when some codes try to convert this back to
     * azimuth and elevation.  do_frame() uses this technique!!!
     */
    if (ZERO(alpha_in - 180.0)) {
	salpha = 0.0;
    } else {
	salpha = sin(alpha);
    }

    if (ZERO(beta_in - 180.0)) {
	sbeta = 0.0;
    } else {
	sbeta = sin(beta);
    }

    if (ZERO(ggamma_in - 180.0)) {
	sgamma = 0.0;
    } else {
	sgamma = sin(ggamma);
    }

    mat[0] = cbeta * cgamma;
    mat[1] = -cbeta * sgamma;
    mat[2] = sbeta;
    mat[3] = 0.0;

    mat[4] = salpha * sbeta * cgamma + calpha * sgamma;
    mat[5] = -salpha * sbeta * sgamma + calpha * cgamma;
    mat[6] = -salpha * cbeta;
    mat[7] = 0.0;

    mat[8] = salpha * sgamma - calpha * sbeta * cgamma;
    mat[9] = salpha * cgamma + calpha * sbeta * sgamma;
    mat[10] = calpha * cbeta;
    mat[11] = 0.0;
    mat[12] = mat[13] = mat[14] = 0.0;
    mat[15] = 1.0;
}
Beispiel #12
0
static void control_udp_incoming(struct obj *obj, str *buf, struct sockaddr_in6 *sin, char *addr) {
	struct control_udp *u = (void *) obj;
	int ret;
	int ovec[100];
	char **out;
	struct msghdr mh;
	struct iovec iov[10];
	str cookie, *reply;

	ret = pcre_exec(u->parse_re, u->parse_ree, buf->s, buf->len, 0, 0, ovec, G_N_ELEMENTS(ovec));
	if (ret <= 0) {
		ret = pcre_exec(u->fallback_re, NULL, buf->s, buf->len, 0, 0, ovec, G_N_ELEMENTS(ovec));
		if (ret <= 0) {
			ilog(LOG_WARNING, "Unable to parse command line from udp:%s: %.*s", addr, STR_FMT(buf));
			return;
		}

		ilog(LOG_WARNING, "Failed to properly parse UDP command line '%.*s' from %s, using fallback RE", STR_FMT(buf), addr);

		pcre_get_substring_list(buf->s, ovec, ret, (const char ***) &out);

		ZERO(mh);
		mh.msg_name = sin;
		mh.msg_namelen = sizeof(*sin);
		mh.msg_iov = iov;

		iov[0].iov_base = (void *) out[RE_UDP_COOKIE];
		iov[0].iov_len = strlen(out[RE_UDP_COOKIE]);
		if (out[RE_UDP_UL_CMD] && (chrtoupper(out[RE_UDP_UL_CMD][0]) == 'U' || chrtoupper(out[RE_UDP_UL_CMD][0]) == 'L')) {
			iov[1].iov_base = (void *) out[4];
			iov[1].iov_len = strlen(out[4]);
			iov[2].iov_base = (void *) out[3];
			iov[2].iov_len = strlen(out[3]);
			iov[3].iov_base = "\n";
			iov[3].iov_len = 1;
			mh.msg_iovlen = 4;
		}
		else {
			iov[1].iov_base = " E8\n";
			iov[1].iov_len = 4;
			mh.msg_iovlen = 2;
		}

		sendmsg(u->udp_listener.fd, &mh, 0);

		pcre_free(out);

		return;
	}

	ilog(LOG_INFO, "Got valid command from udp:%s: %.*s", addr, STR_FMT(buf));

	pcre_get_substring_list(buf->s, ovec, ret, (const char ***) &out);

	str_init(&cookie, (void *) out[RE_UDP_COOKIE]);
	reply = cookie_cache_lookup(&u->cookie_cache, &cookie);
	if (reply) {
		ilog(LOG_INFO, "Detected command from udp:%s as a duplicate", addr);
		sendto(u->udp_listener.fd, reply->s, reply->len, 0, (struct sockaddr *) sin, sizeof(*sin));
		free(reply);
		goto out;
	}

	if (chrtoupper(out[RE_UDP_UL_CMD][0]) == 'U')
		reply = call_update_udp(out, u->callmaster);
	else if (chrtoupper(out[RE_UDP_UL_CMD][0]) == 'L')
		reply = call_lookup_udp(out, u->callmaster);
	else if (chrtoupper(out[RE_UDP_DQ_CMD][0]) == 'D')
		reply = call_delete_udp(out, u->callmaster);
	else if (chrtoupper(out[RE_UDP_DQ_CMD][0]) == 'Q')
		reply = call_query_udp(out, u->callmaster);
	else if (chrtoupper(out[RE_UDP_V_CMD][0]) == 'V') {
		ZERO(mh);
		mh.msg_name = sin;
		mh.msg_namelen = sizeof(*sin);
		mh.msg_iov = iov;
		mh.msg_iovlen = 2;

		iov[0].iov_base = (void *) out[RE_UDP_COOKIE];
		iov[0].iov_len = strlen(out[RE_UDP_COOKIE]);
		iov[1].iov_base = " ";
		iov[1].iov_len = 1;

		if (chrtoupper(out[RE_UDP_V_FLAGS][0]) == 'F') {
			ret = 0;
			if (!strcmp(out[RE_UDP_V_PARMS], "20040107"))
				ret = 1;
			else if (!strcmp(out[RE_UDP_V_PARMS], "20050322"))
				ret = 1;
			else if (!strcmp(out[RE_UDP_V_PARMS], "20060704"))
				ret = 1;
			iov[2].iov_base = ret ? "1\n" : "0\n";
			iov[2].iov_len = 2;
			mh.msg_iovlen++;
		}
		else {
			iov[2].iov_base = "20040107\n";
			iov[2].iov_len = 9;
			mh.msg_iovlen++;
		}
		sendmsg(u->udp_listener.fd, &mh, 0);
	}

	if (reply) {
		sendto(u->udp_listener.fd, reply->s, reply->len, 0, (struct sockaddr *) sin, sizeof(*sin));
		cookie_cache_insert(&u->cookie_cache, &cookie, reply);
		free(reply);
	}
	else
		cookie_cache_remove(&u->cookie_cache, &cookie);

out:
	pcre_free(out);
	log_info_clear();
}
Beispiel #13
0
SCLError  Siren_ComputeHash(    HASH_Algorithm  hash,
                            const char*         sirenData,
                            uint8_t*            hashOut,
                            bool                sorted)
{
    SCLError        err = kSCLError_NoErr;
    
    yajl_gen_status         stat = yajl_gen_status_ok;
    yajl_handle             pHand = NULL;
    SirenJSONcontext       *jctx = NULL;
    
    static yajl_callbacks callbacks = {
        NULL,
        sParse_bool,
        NULL,
        NULL,
        sParse_number,
        sParse_string,
        sParse_start_map,
        sParse_map_key,
        sParse_end_map,
        NULL,
        NULL
    };
    
    yajl_alloc_funcs allocFuncs = {
        yajlMalloc,
        yajlRealloc,
        yajlFree,
        (void *) NULL
    };
    
    
    jctx = XMALLOC(sizeof (SirenJSONcontext)); CKNULL(jctx);
    ZERO(jctx, sizeof(SirenJSONcontext));
    err  = HASH_Init(hash, &jctx->hash); CKERR;
    
    // use yajl to fill the hashableItems with tags and values we can hash
    pHand = yajl_alloc(&callbacks, &allocFuncs, (void *) jctx);
    yajl_config(pHand, yajl_allow_comments, 1);
    stat = (yajl_gen_status) yajl_parse(pHand, (uint8_t*)sirenData,  strlen(sirenData)); CKSTAT;
    stat = (yajl_gen_status) yajl_complete_parse(pHand); CKSTAT;
    
    
    // hash the items found in hashableItems using sHashable_tags_list order
    int items2Hash = jctx->hashableItemsCount;
    
#if DEBUG_HASH
    DPRINTF(XCODE_COLORS_RED_TXT,"\nSiren_ComputeHash %s\n",  sorted?"sorted":""  );
#endif
    
    if(sorted)
    {
        for(int j = 0; sHashable_tags_list[j] && items2Hash > 0; j++)
        {
            for(int i = 0; i < jctx->hashableItemsCount; i++)
            {
                char* tag = sHashable_tags_list[j];
                HashableItem *item = &jctx->hashableItems[i];
                
                if(item->tag && strncmp(tag, item->tag, strlen(tag)) == 0 )
                {
                    err = shashItem(jctx->hash, item);
                    items2Hash--;
                    break;
                }
            }
        }
    }
    else
    {
        for(int i = 0; i < items2Hash; i++)
        {
            HashableItem *item = &jctx->hashableItems[i];
            
            if(item->tag)
            {
                err = shashItem(jctx->hash, item);
            }
        }
        
    }
    
    err = HASH_Final(jctx->hash, hashOut); CKERR;
    
#if DEBUG_HASH
    DPRINTF(XCODE_COLORS_RED_TXT,"\n");
    dumpHex(hashOut,  32, 0);
    DPRINTF(XCODE_COLORS_RED_TXT,"\n");
#endif
    
done:
    
    if(IsntNull(jctx))
    {
        ZERO(jctx, sizeof(SirenJSONcontext));
        XFREE(jctx);
    }
    
    if(IsntNull(pHand))
        yajl_free(pHand);
    
    return err;
    
}
int
cyl(int entityno)
{
    fastf_t radius = 0.0;
    point_t base;		/* center point of base */
    vect_t height;
    vect_t hdir;		/* direction in which to grow height */
    fastf_t scale_height = 0.0;
    fastf_t x_1;
    fastf_t y_1;
    fastf_t z_1;
    fastf_t x_2;
    fastf_t y_2;
    fastf_t z_2;
    int sol_num;		/* IGES solid type number */

    /* Default values */
    x_1 = 0.0;
    y_1 = 0.0;
    z_1 = 0.0;
    x_2 = 0.0;
    y_2 = 0.0;
    z_2 = 1.0;

    /* Acquiring Data */
    if (dir[entityno]->param <= pstart) {
	bu_log("Illegal parameter pointer for entity D%07d (%s)\n" ,
	       dir[entityno]->direct, dir[entityno]->name);
	return 0;
    }
    Readrec(dir[entityno]->param);
    Readint(&sol_num, "");
    Readcnv(&scale_height, "");
    Readcnv(&radius, "");
    Readcnv(&x_1, "");
    Readcnv(&y_1, "");
    Readcnv(&z_1, "");
    Readcnv(&x_2, "");
    Readcnv(&y_2, "");
    Readcnv(&z_2, "");

    if (radius < SMALL_FASTF || scale_height < SMALL_FASTF) {
	bu_log("Illegal parameters for entity D%07d (%s)\n" ,
	       dir[entityno]->direct, dir[entityno]->name);
	if (ZERO(radius)) {
	    bu_log("\tradius of cylinder is zero!!!\n");
	    return 0;
	}
	if (ZERO(scale_height)) {
	    bu_log("\theight of cylinder is zero!!!\n");
	    return 0;
	}

	if (radius < 0.0) {
	    bu_log("\tUsing the absolute value of a negative radius\n");
	    radius = (-radius);
	}

	if (scale_height < 0.0) {
	    bu_log("\tUsing absolute value of a negative height and reversing axis direction\n");
	    scale_height = (-scale_height);
	    x_2 = (-x_2);
	    y_2 = (-y_2);
	    z_2 = (-z_2);
	}

    }


    /*
     * Making the necessaries. First an id is made for the new entity, then
     * the x, y, z coordinates for its vertices are converted to vectors with
     * VSET(), and finally the libwdb routine that makes an analogous BRL-CAD
     * solid is called.
     */

    VSET(base, x_1, y_1, z_1);
    VSET(hdir, x_2, y_2, z_2);
    VUNITIZE(hdir);

    /* Multiply the hdir * scale_height to obtain height. */

    VSCALE(height, hdir, scale_height);

    if (mk_rcc(fdout, dir[entityno]->name, base, height, radius) < 0) {
	bu_log("Unable to write entity D%07d (%s)\n" ,
	       dir[entityno]->direct, dir[entityno]->name);
	return 0;
    }
    return 1;

}
Beispiel #15
0
/* Define a function to create the states of the scanner. This function
 * is used by the create_keyword_scanner function below.
 *
 * This function takes a suffix of a keyword, the token to be returned on
 * recognizing the complete keyword, and any pre-existing state that exists
 * for some other keyword that has the same prefix as the current one.
 */
static u_short
create_scan_states(
	char *	text, 
	u_short	token, 
	follby	followedby,
	u_short	prev_state
	)
{
	u_short my_state;
	u_short return_state;
	u_short prev_char_s;
	u_short curr_char_s;

	return_state = prev_state;
	curr_char_s = prev_state;
	prev_char_s = 0;

	/* Find the correct position to insert the state. 
	 * All states should be in alphabetical order
	 */
	while (curr_char_s && (text[0] < sst[curr_char_s].ch)) {
		prev_char_s = curr_char_s;
		curr_char_s = sst[curr_char_s].other_next_s;
	}

	/* 
	 * Check if a previously seen keyword has the same prefix as
	 * the current keyword.  If so, simply use the state for that
	 * keyword as my_state, otherwise, allocate a new state.
	 */
	if (curr_char_s && (text[0] == sst[curr_char_s].ch)) {
		my_state = curr_char_s;
		if ('\0' == text[1]) {
			fprintf(stderr,
				"Duplicate entries for keyword '%s' in"
				" keyword_gen.c ntp_keywords[].\n",
				current_keyword);
			exit(2);
		}
	} else {
		do
			my_state = sst_highwater++;
		while (my_state < COUNTOF(sst)
		       && sst[my_state].finishes_token);
		if (my_state >= COUNTOF(sst)) {
			fprintf(stderr,
				"fatal, keyword scanner state array "
				"sst[%d] is too small, modify\n"
				"keyword-gen.c to increase.\n",
				(int)COUNTOF(sst));
			exit(3);
		}
		/* Store the next character of the keyword */
		sst[my_state].ch = text[0]; 
		sst[my_state].other_next_s = curr_char_s;
		sst[my_state].followedby = FOLLBY_NON_ACCEPTING;

		if (prev_char_s)
			sst[prev_char_s].other_next_s = my_state;
		else
			return_state = my_state;
	}

	/* Check if the next character is '\0'.
	 * If yes, we are done with the recognition and this is an accepting
	 * state.
	 * If not, we need to continue scanning
	 */
	if ('\0' == text[1]) {
		sst[my_state].finishes_token = (u_short)token;
		sst[my_state].followedby = (char)followedby;

		if (sst[token].finishes_token != (u_short)token) {
			fprintf(stderr,
				"fatal, sst[%d] not reserved for %s.\n",
				token, symbname(token));
			exit(6);
		}
		/* relocate so token id is sst[] index */
		if (my_state != token) {
			sst[token] = sst[my_state];
			ZERO(sst[my_state]);
			do
				sst_highwater--;
			while (sst[sst_highwater].finishes_token);
			my_state = token;
			if (prev_char_s)
				sst[prev_char_s].other_next_s = my_state;
			else
				return_state = my_state;
		}
	} else
		sst[my_state].match_next_s = 
		    create_scan_states(
			&text[1],
			token,
			followedby,
			sst[my_state].match_next_s);

	return return_state;
}
	acolorhash_hash()
	{
		ZERO( hash );
	}
Beispiel #17
0
/**
 * Returns -
 *  0 OK
 * !0 failure
 */
int
rt_arbn_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
{
    struct rt_arbn_internal *aip;
    vect_t work;
    fastf_t f;
    size_t i;
    size_t j;
    size_t k;
    int *used = (int *)0;	/* plane eqn use count */
    const struct bn_tol *tol = &rtip->rti_tol;

    RT_CK_DB_INTERNAL(ip);
    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(aip);

    used = (int *)bu_malloc(aip->neqn*sizeof(int), "arbn used[]");

    /*
     * ARBN must be convex.  Test for concavity.
     * Byproduct is an enumeration of all the vertices,
     * which are used to make the bounding RPP.  No need
     * to call the bbox routine, as the work must be duplicated
     * here to count faces.
     */

    /* Zero face use counts
     * and make sure normal vectors are unit vectors
     */
    for (i = 0; i < aip->neqn; i++) {
	double normalLen = MAGNITUDE(aip->eqn[i]);
	double scale;
	if (ZERO(normalLen)) {
	    bu_log("arbn has zero length normal vector\n");
	    return 1;
	}
	scale = 1.0 / normalLen;
	HSCALE(aip->eqn[i], aip->eqn[i], scale);
	used[i] = 0;
    }
    for (i = 0; i < aip->neqn-2; i++) {
	for (j=i+1; j<aip->neqn-1; j++) {
	    double dot;

	    /* If normals are parallel, no intersection */
	    dot = VDOT(aip->eqn[i], aip->eqn[j]);
	    if (BN_VECT_ARE_PARALLEL(dot, tol)) continue;

	    /* Have an edge line, isect with higher numbered planes */
	    for (k=j+1; k<aip->neqn; k++) {
		size_t m;
		size_t next_k;
		point_t pt;

		next_k = 0;

		if (bn_mkpoint_3planes(pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]) < 0) continue;

		/* See if point is outside arb */
		for (m = 0; m < aip->neqn; m++) {
		    if (i == m || j == m || k == m)
			continue;
		    if (VDOT(pt, aip->eqn[m])-aip->eqn[m][3] > tol->dist) {
			next_k = 1;
			break;
		    }
		}
		if (next_k != 0) continue;

		VMINMAX(stp->st_min, stp->st_max, pt);

		/* Increment "face used" counts */
		used[i]++;
		used[j]++;
		used[k]++;
	    }
	}
    }

    /* If any planes were not used, then arbn is not convex */
    for (i = 0; i < aip->neqn; i++) {
	if (used[i] != 0) continue;	/* face was used */
	bu_log("arbn(%s) face %zu unused, solid is not convex\n",
	       stp->st_name, i);
	bu_free((char *)used, "arbn used[]");
	return -1;		/* BAD */
    }
    bu_free((char *)used, "arbn used[]");

    stp->st_specific = (void *)aip;
    ip->idb_ptr = ((void *)0);	/* indicate we stole it */

    VADD2SCALE(stp->st_center, stp->st_min, stp->st_max, 0.5);
    VSUB2SCALE(work, stp->st_max, stp->st_min, 0.5);

    f = work[X];
    if (work[Y] > f) f = work[Y];
    if (work[Z] > f) f = work[Z];
    stp->st_aradius = f;
    stp->st_bradius = MAGNITUDE(work);
    return 0;			/* OK */
}
Beispiel #18
0
/*
 * getarg - interpret an argument token
 *
 * string is always set.
 * type is set to the decoded type.
 *
 * return:	 0 - failure
 *		 1 - success
 *		-1 - skip to next token
 */
static int
getarg(
	char *str,
	int code,
	arg_v *argp
	)
{
	int isneg;
	char *cp, *np;
	static const char *digits = "0123456789";

	ZERO(*argp);
	argp->string = str;
	argp->type   = code & ~OPT;

	switch (argp->type) {
	    case NTP_STR:
		break;
	    case NTP_ADD:
		if (!strcmp("-6", str)) {
			ai_fam_templ = AF_INET6;
			return -1;
		} else if (!strcmp("-4", str)) {
			ai_fam_templ = AF_INET;
			return -1;
		}
		if (!getnetnum(str, &(argp->netnum), (char *)0, 0)) {
			return 0;
		}
		break;
	    case NTP_INT:
	    case NTP_UINT:
		isneg = 0;
		np = str;
		if (*np == '-') {
			np++;
			isneg = 1;
		}

		argp->uval = 0;
		do {
			cp = strchr(digits, *np);
			if (cp == NULL) {
				(void) fprintf(stderr,
					       "***Illegal integer value %s\n", str);
				return 0;
			}
			argp->uval *= 10;
			argp->uval += (cp - digits);
		} while (*(++np) != '\0');

		if (isneg) {
			if ((code & ~OPT) == NTP_UINT) {
				(void) fprintf(stderr,
					       "***Value %s should be unsigned\n", str);
				return 0;
			}
			argp->ival = -argp->ival;
		}
		break;
	    case IP_VERSION:
		if (!strcmp("-6", str))
			argp->ival = 6 ;
		else if (!strcmp("-4", str))
			argp->ival = 4 ;
		else {
			(void) fprintf(stderr,
			    "***Version must be either 4 or 6\n");
			return 0;
		}
		break;
	}

	return 1;
}
Beispiel #19
0
int doAllFeatures()
{
	/* Initial biases */
	{
		int u,m,f;
		
		for(u=0;u<NUSERS;u++) {
			for(f=0;f<NFEATURES;f++)
			    bU[u][f]=drand48()*0.01-0.005;
		}
		for(m=0;m<NMOVIES;m++) {
			for(f=0;f<NFEATURES;f++)
			    bV[m][f]=drand48()*0.01-0.005;
		}
	}
	
	
	/* Initial estimation for current feature */
	{
		int u,m,f;
		
		for(u=0;u<NUSERS;u++) {
			for(f=0;f<NFEATURES;f++)
			    sU[u][f]=drand48()*0.1-0.04;
		}
		for(m=0;m<NMOVIES;m++) {
			for(f=0;f<NFEATURES;f++) {
			    sV[m][f]=drand48()*0.05-0.025;
			    sY[m][f]=drand48()*0.02-0.01;
			}
		}
	}
	
	/* Optimize current feature */
	double nrmse=2., last_rmse=10.;
	double thr=sqrt(1.-E);
	int loopcount=0;
	    //thr=sqrt(1.-E2);
	double Gamma2 = G2;
	double Gamma0 = G0;
	while( ( nrmse < (last_rmse-E) ) || loopcount++ < 20) {
		last_rmse=nrmse;
		clock_t t0=clock();

		int u,m, f;
		for(u=0;u<NUSERS;u++) {

			// Calculate sumY and NuSY for each factor
			double sumY[NFEATURES];
			ZERO(sumY);
			double lNuSY[NFEATURES];
			ZERO(lNuSY);
			int base0=useridx[u][0];
			int d0=UNTRAIN(u);
			int j;
			int f;
			int dall=UNALL(u);
			double NuS = 1.0/sqrt(dall);
			for(j=0;j<d0;j++) {
				int mm=userent[base0+j]&USER_MOVIEMASK;
				for(f=0;f<NFEATURES;f++)
					sumY[f]+=sY[mm][f];
			}
//if ( loopcount > 1 ) {
//printf("sumY: %f\n", sumY);
//fflush(stdout);
//}
			for(j=0;j<d0;j++) {
				int mm=userent[base0+j]&USER_MOVIEMASK;
				for(f=0;f<NFEATURES;f++) {
					lNuSY[f] = NuS * sumY[f]; 
//if ( loopcount > 1 ) {
//printf("lNuSY: %f\n", lNuSY[f]);
//fflush(stdout);
//}
				}
			}

			double ycontrib[NFEATURES];
			ZERO(ycontrib);

			// For all rated movies
			double bdampen = d0/1.1;
			for(j=0;j<d0;j++) {
				int m=userent[base0+j]&USER_MOVIEMASK;

				// Figure out the current error
				double ee=err[base0+j];
				double e2 = ee;
				for (f=0; f<NFEATURES; f++) {
				    e2 -= (bU[u][f] + bV[m][f]);
					e2 -= ((sU[u][f]+lNuSY[f])*sV[m][f]);
				}


				// update U V and slope component of Y
				//double yfactor = NuS/sqrt(moviecount[m]); 
				//double yfactor = NuS;
				double yfactor = NuS/d0;
				for (f=0; f<NFEATURES; f++) {

					// Train the biases
					double bUu = bU[u][f];
					double bVm = bV[m][f];
					bU[u][f] += Gamma0 * (e2 - bUu * L4) / bdampen;
					bV[m][f] += Gamma0 * (e2 - bVm * L4) / bdampen;

					double sUu = sU[u][f];
					double sVm = sV[m][f];

					sU[u][f] += (Gamma2 * ((e2 * sVm) - L8 * sUu));
					sV[m][f] += (Gamma2 * ((e2 * (sUu + lNuSY[f])) - L8 * sVm));
//printf("sU: %f\n", sU[u][f]);
//printf("sV: %f\n", sV[m][f]);
//fflush(stdout);

					ycontrib[f] += e2 * sVm * yfactor;
//printf("ycont: %f\n", ycontrib[f]);
//fflush(stdout);
				}
			}

			// Train Ys over all known movies for user
			for(j=0;j<dall;j++) {
				int m=userent[base0+j]&USER_MOVIEMASK;
				for (f=0; f<NFEATURES; f++) {
					double sYm = sY[m][f];
					sY[m][f] += Gamma2 * (ycontrib[f] - L7 * sYm);
//printf("before sY: %f\tycon: %f\tG2*ycon: %f\treg: %f\n", sY[m][f], ycontrib[f], (G2_Y*ycontrib[f]), G2_Y*L7_Y*sYm);
//printf("after sY: %f\tycon: %f\tG2*ycon: %f\treg: %f\n", sY[m][f], ycontrib[f], (G2_Y*ycontrib[f]), G2_Y*L7_Y*sYm);
//printf("sY: %f\tycon: %f\tG2*ycon: %f\n", sY[m][f], ycontrib[f], (G2*ycontrib[f]));
//fflush(stdout);
				}
			}
		}

		// Report rmse for main loop
		nrmse=0.;
		int ntrain=0;
		int elcnt=0;
		for(u=0;u<NUSERS;u++) {
			int base0=useridx[u][0];
			int d0=UNTRAIN(u);
			int j;

			// Setup the Ys again
			double sumY[NFEATURES];
			ZERO(sumY);
			double lNuSY[NFEATURES];
			ZERO(lNuSY);
			int dall=UNALL(u);
			double NuS = 1.0/sqrt(dall);
			for(j=0;j<d0;j++) {
				int mm=userent[base0+j]&USER_MOVIEMASK;
				for(f=0;f<NFEATURES;f++)
					sumY[f]+=sY[mm][f];
			}
			for(j=0;j<d0;j++) {
				int mm=userent[base0+j]&USER_MOVIEMASK;
				for(f=0;f<NFEATURES;f++) 
					lNuSY[f] = NuS * sumY[f]; 
			}

			for(j=0;j<d0;j++) {
				int m=userent[base0+j]&USER_MOVIEMASK;
				double ee = err[base0+j];
				double e2 = ee;
				for (f=0; f<NFEATURES; f++) {
				    e2 -= (bU[u][f] + bV[m][f]);
					e2 -= ( (sU[u][f] + lNuSY[f]) * sV[m][f]);
				}

if( elcnt++ == 5000 ) {
    printf("0 E: %f \t NE: %f\tNuSY: %f\tsV: %f\tsU: %f\tbU: %f\tbV: %f\tsY: %f\tU: %d\tM: %d\n", ee, e2, lNuSY[0], sV[m][0], sU[u][0], bU[u][0], bV[m][0], sY[m][0],u, m);
    printf("1 E: %f \t NE: %f\tNuSY: %f\tsV: %f\tsU: %f\tbU: %f\tbV: %f\tsY: %f\tU: %d\tM: %d\n", ee, e2, lNuSY[1], sV[m][1], sU[u][1], bU[u][1], bV[m][1], sY[m][1],u, m);
    printf("2 E: %f \t NE: %f\tNuSY: %f\tsV: %f\tsU: %f\tbU: %f\tbV: %f\tsY: %f\tU: %d\tM: %d\n", ee, e2, lNuSY[2], sV[m][2], sU[u][2], bU[u][2], bV[m][2], sY[m][2],u, m);
    printf("3 E: %f \t NE: %f\tNuSY: %f\tsV: %f\tsU: %f\tbU: %f\tbV: %f\tsY: %f\tU: %d\tM: %d\n", ee, e2, lNuSY[3], sV[m][3], sU[u][3], bU[u][3], bV[m][3], sY[m][3],u, m);
	fflush(stdout);
}
/*
if( e > 5.0 || e < -5.0 ) {
    printf("bad EE: %f\tU: %d\tM: %d\tNuSY: %f\te: %f\t sV: %f\tsU: %f\tbU: %f\tbV: %f\n", ee, u, m, NuSY, e, new_sV[m], new_sU[u], bUu, bVm);
	fflush(stdout);
}
*/

				nrmse+=e2*e2;
			}
			ntrain+=d0;
		}
		nrmse=sqrt(nrmse/ntrain);
		double prmse = rmseprobe();
		
		lg("%f\t%f\t%f\n",nrmse,prmse,(clock()-t0)/(double)CLOCKS_PER_SEC);
		//rmse_print(0);
		if ( loopcount < 6 ) {
		    Gamma2 *= 0.95;
		    Gamma0 *= 0.95;
		} else if ( loopcount < 14 ) {
		    Gamma2 *= 0.92;
		    Gamma0 *= 0.92;
		} else {
		    Gamma2 *= 0.90;
		    Gamma0 *= 0.90;
		}
	}
	
	/* Perform a final iteration in which the errors are clipped and stored */
	removeUV();
	
	//if(save_model) {
		//dappend_bin(fnameV,sV,NMOVIES);
		//dappend_bin(fnameU,sU,NUSERS);
	//}
	
	return 1;
}
Beispiel #20
0
/*
 * getresponse - get a (series of) response packet(s) and return the data
 */
static int
getresponse(
	int implcode,
	int reqcode,
	int *ritems,
	int *rsize,
	char **rdata,
	int esize
	)
{
	struct resp_pkt rpkt;
	struct sock_timeval tvo;
	int items;
	int i;
	int size;
	int datasize;
	char *datap;
	char *tmp_data;
	char haveseq[MAXSEQ+1];
	int firstpkt;
	int lastseq;
	int numrecv;
	int seq;
	fd_set fds;
	ssize_t n;
	int pad;

	/*
	 * This is pretty tricky.  We may get between 1 and many packets
	 * back in response to the request.  We peel the data out of
	 * each packet and collect it in one long block.  When the last
	 * packet in the sequence is received we'll know how many we
	 * should have had.  Note we use one long time out, should reconsider.
	 */
	*ritems = 0;
	*rsize = 0;
	firstpkt = 1;
	numrecv = 0;
	*rdata = datap = pktdata;
	lastseq = 999;	/* too big to be a sequence number */
	ZERO(haveseq);
	FD_ZERO(&fds);

    again:
	if (firstpkt)
		tvo = tvout;
	else
		tvo = tvsout;
	
	FD_SET(sockfd, &fds);
	n = select(sockfd+1, &fds, (fd_set *)0, (fd_set *)0, &tvo);

	if (n == -1) {
		warning("select fails");
		return -1;
	}
	if (n == 0) {
		/*
		 * Timed out.  Return what we have
		 */
		if (firstpkt) {
			(void) fprintf(stderr,
				       "%s: timed out, nothing received\n", currenthost);
			return ERR_TIMEOUT;
		} else {
			(void) fprintf(stderr,
				       "%s: timed out with incomplete data\n",
				       currenthost);
			if (debug) {
				printf("Received sequence numbers");
				for (n = 0; n <= MAXSEQ; n++)
				    if (haveseq[n])
					printf(" %zd,", n);
				if (lastseq != 999)
				    printf(" last frame received\n");
				else
				    printf(" last frame not received\n");
			}
			return ERR_INCOMPLETE;
		}
	}

	n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
	if (n == -1) {
		warning("read");
		return -1;
	}


	/*
	 * Check for format errors.  Bug proofing.
	 */
	if (n < (ssize_t)RESP_HEADER_SIZE) {
		if (debug)
			printf("Short (%zd byte) packet received\n", n);
		goto again;
	}
	if (INFO_VERSION(rpkt.rm_vn_mode) > NTP_VERSION ||
	    INFO_VERSION(rpkt.rm_vn_mode) < NTP_OLDVERSION) {
		if (debug)
			printf("Packet received with version %d\n",
			       INFO_VERSION(rpkt.rm_vn_mode));
		goto again;
	}
	if (INFO_MODE(rpkt.rm_vn_mode) != MODE_PRIVATE) {
		if (debug)
			printf("Packet received with mode %d\n",
			       INFO_MODE(rpkt.rm_vn_mode));
		goto again;
	}
	if (INFO_IS_AUTH(rpkt.auth_seq)) {
		if (debug)
			printf("Encrypted packet received\n");
		goto again;
	}
	if (!ISRESPONSE(rpkt.rm_vn_mode)) {
		if (debug)
			printf("Received request packet, wanted response\n");
		goto again;
	}
	if (INFO_MBZ(rpkt.mbz_itemsize) != 0) {
		if (debug)
			printf("Received packet with nonzero MBZ field!\n");
		goto again;
	}

	/*
	 * Check implementation/request.  Could be old data getting to us.
	 */
	if (rpkt.implementation != implcode || rpkt.request != reqcode) {
		if (debug)
			printf(
			    "Received implementation/request of %d/%d, wanted %d/%d",
			    rpkt.implementation, rpkt.request,
			    implcode, reqcode);
		goto again;
	}

	/*
	 * Check the error code.  If non-zero, return it.
	 */
	if (INFO_ERR(rpkt.err_nitems) != INFO_OKAY) {
		if (debug && ISMORE(rpkt.rm_vn_mode)) {
			printf("Error code %d received on not-final packet\n",
			       INFO_ERR(rpkt.err_nitems));
		}
		return (int)INFO_ERR(rpkt.err_nitems);
	}

	/*
	 * Collect items and size.  Make sure they make sense.
	 */
	items = INFO_NITEMS(rpkt.err_nitems);
	size = INFO_ITEMSIZE(rpkt.mbz_itemsize);
	if (esize > size)
		pad = esize - size;
	else 
		pad = 0;
	datasize = items * size;
	if ((size_t)datasize > (n-RESP_HEADER_SIZE)) {
		if (debug)
		    printf(
			    "Received items %d, size %d (total %d), data in packet is %zu\n",
			    items, size, datasize, n-RESP_HEADER_SIZE);
		goto again;
	}

	/*
	 * If this isn't our first packet, make sure the size matches
	 * the other ones.
	 */
	if (!firstpkt && size != *rsize) {
		if (debug)
		    printf("Received itemsize %d, previous %d\n",
			   size, *rsize);
		goto again;
	}
	/*
	 * If we've received this before, +toss it
	 */
	seq = INFO_SEQ(rpkt.auth_seq);
	if (haveseq[seq]) {
		if (debug)
		    printf("Received duplicate sequence number %d\n", seq);
		goto again;
	}
	haveseq[seq] = 1;

	/*
	 * If this is the last in the sequence, record that.
	 */
	if (!ISMORE(rpkt.rm_vn_mode)) {
		if (lastseq != 999) {
			printf("Received second end sequence packet\n");
			goto again;
		}
		lastseq = seq;
	}

	/*
	 * So far, so good.  Copy this data into the output array.
	 */
	if ((datap + datasize + (pad * items)) > (pktdata + pktdatasize)) {
		int offset = datap - pktdata;
		growpktdata();
		*rdata = pktdata; /* might have been realloced ! */
		datap = pktdata + offset;
	}
	/* 
	 * We now move the pointer along according to size and number of
	 * items.  This is so we can play nice with older implementations
	 */

	tmp_data = rpkt.u.data;
	for (i = 0; i < items; i++) {
		memcpy(datap, tmp_data, (unsigned)size);
		tmp_data += size;
		zero_mem(datap + size, pad);
		datap += size + pad;
	}

	if (firstpkt) {
		firstpkt = 0;
		*rsize = size + pad;
	}
	*ritems += items;

	/*
	 * Finally, check the count of received packets.  If we've got them
	 * all, return
	 */
	++numrecv;
	if (numrecv <= lastseq)
		goto again;
	return INFO_OKAY;
}
Beispiel #21
0
void SolveSpace::DoLater(void) {
    if(later.generateAll) GenerateAll();
    if(later.showTW) TW.Show();
    ZERO(&later);
}
Beispiel #22
0
//-----------------------------------------------------------------------------
// Find all points where a line through a and b intersects our surface, and
// add them to the list. If seg is true then report only intersections that
// lie within the finite line segment (not including the endpoints); otherwise
// we work along the infinite line. And we report either just intersections
// inside the trim curve, or any intersection with u, v in [0, 1]. And we
// either disregard or report tangent points.
//-----------------------------------------------------------------------------
void SSurface::AllPointsIntersecting(Vector a, Vector b,
                                     List<SInter> *l,
                                     bool seg, bool trimmed, bool inclTangent)
{
    if(LineEntirelyOutsideBbox(a, b, seg)) return;

    Vector ba = b.Minus(a);
    double bam = ba.Magnitude();

    List<Inter> inters;
    ZERO(&inters);

    // All the intersections between the line and the surface; either special
    // cases that we can quickly solve in closed form, or general numerical.
    Vector center, axis, start, finish;
    double radius;
    if(degm == 1 && degn == 1) {
        // Against a plane, easy.
        Vector n = NormalAt(0, 0).WithMagnitude(1);
        double d = n.Dot(PointAt(0, 0));
        // Trim to line segment now if requested, don't generate points that
        // would just get discarded later.
        if(!seg ||
           (n.Dot(a) > d + LENGTH_EPS && n.Dot(b) < d - LENGTH_EPS) ||
           (n.Dot(b) > d + LENGTH_EPS && n.Dot(a) < d - LENGTH_EPS))
        {
            Vector p = Vector::AtIntersectionOfPlaneAndLine(n, d, a, b, NULL);
            Inter inter;
            ClosestPointTo(p, &(inter.p.x), &(inter.p.y));
            inters.Add(&inter);
        }
    } else if(IsCylinder(&axis, &center, &radius, &start, &finish)) {
        // This one can be solved in closed form too.
        Vector ab = b.Minus(a);
        if(axis.Cross(ab).Magnitude() < LENGTH_EPS) {
            // edge is parallel to axis of cylinder, no intersection points
            return;
        }
        // A coordinate system centered at the center of the circle, with
        // the edge under test horizontal
        Vector u, v, n = axis.WithMagnitude(1);
        u = (ab.Minus(n.ScaledBy(ab.Dot(n)))).WithMagnitude(1);
        v = n.Cross(u);
        Point2d ap = (a.Minus(center)).DotInToCsys(u, v, n).ProjectXy(),
                bp = (b.Minus(center)).DotInToCsys(u, v, n).ProjectXy(),
                sp = (start. Minus(center)).DotInToCsys(u, v, n).ProjectXy(),
                fp = (finish.Minus(center)).DotInToCsys(u, v, n).ProjectXy();

        double thetas = atan2(sp.y, sp.x), thetaf = atan2(fp.y, fp.x);

        Point2d ip[2];
        int ip_n = 0;
        if(fabs(fabs(ap.y) - radius) < LENGTH_EPS) {
            // tangent
            if(inclTangent) {
                ip[0] = Point2d::From(0, ap.y);
                ip_n = 1;
            }
        } else if(fabs(ap.y) < radius) {
            // two intersections
            double xint = sqrt(radius*radius - ap.y*ap.y);
            ip[0] = Point2d::From(-xint, ap.y);
            ip[1] = Point2d::From( xint, ap.y);
            ip_n = 2;
        }
        int i;
        for(i = 0; i < ip_n; i++) {
            double t = (ip[i].Minus(ap)).DivPivoting(bp.Minus(ap));
            // This is a point on the circle; but is it on the arc?
            Point2d pp = ap.Plus((bp.Minus(ap)).ScaledBy(t));
            double theta = atan2(pp.y, pp.x);
            double dp = WRAP_SYMMETRIC(theta  - thetas, 2*PI),
                   df = WRAP_SYMMETRIC(thetaf - thetas, 2*PI);
            double tol = LENGTH_EPS/radius;

            if((df > 0 && ((dp < -tol) || (dp > df + tol))) ||
               (df < 0 && ((dp >  tol) || (dp < df - tol))))
            {
                continue;
            }

            Vector p = a.Plus((b.Minus(a)).ScaledBy(t));

            Inter inter;
            ClosestPointTo(p, &(inter.p.x), &(inter.p.y));
            inters.Add(&inter);
        }
    } else {
        // General numerical solution by subdivision, fallback
        int cnt = 0, level = 0;
        AllPointsIntersectingUntrimmed(a, b, &cnt, &level, &inters, seg, this);
    }

    // Remove duplicate intersection points
    inters.ClearTags();
    int i, j;
    for(i = 0; i < inters.n; i++) {
        for(j = i + 1; j < inters.n; j++) {
            if(inters.elem[i].p.Equals(inters.elem[j].p)) {
                inters.elem[j].tag = 1;
            }
        }
    }
    inters.RemoveTagged();

    for(i = 0; i < inters.n; i++) {
        Point2d puv = inters.elem[i].p;

        // Make sure the point lies within the finite line segment
        Vector pxyz = PointAt(puv.x, puv.y);
        double t = (pxyz.Minus(a)).DivPivoting(ba);
        if(seg && (t > 1 - LENGTH_EPS/bam || t < LENGTH_EPS/bam)) {
            continue;
        }
       
        // And that it lies inside our trim region
        Point2d dummy = { 0, 0 };
        int c = bsp->ClassifyPoint(puv, dummy, this);
        if(trimmed && c == SBspUv::OUTSIDE) {
            continue;
        }

        // It does, so generate the intersection
        SInter si;
        si.p = pxyz;
        si.surfNormal = NormalAt(puv.x, puv.y);
        si.pinter = puv;
        si.srf = this;
        si.onEdge = (c != SBspUv::INSIDE);
        l->Add(&si);
    }

    inters.Clear();
}
Beispiel #23
0
void SolveSpace::MenuFile(int id) {
    if(id >= RECENT_OPEN && id < (RECENT_OPEN+MAX_RECENT)) {
        if(!SS.OkayToStartNewFile()) return;

        char newFile[MAX_PATH];
        strcpy(newFile, RecentFile[id-RECENT_OPEN]);
        RemoveFromRecentList(newFile);
        if(SS.LoadFromFile(newFile)) {
            strcpy(SS.saveFile, newFile);
            AddToRecentList(newFile);
        } else {
            strcpy(SS.saveFile, "");
            SS.NewFile();
        }
        SS.AfterNewFile();
        return;
    }

    switch(id) {
        case GraphicsWindow::MNU_NEW:
            if(!SS.OkayToStartNewFile()) break;

            strcpy(SS.saveFile, "");
            SS.NewFile();
            SS.AfterNewFile();
            break;

        case GraphicsWindow::MNU_OPEN: {
            if(!SS.OkayToStartNewFile()) break;

            char newFile[MAX_PATH] = "";
            if(GetOpenFile(newFile, SLVS_EXT, SLVS_PATTERN)) {
                if(SS.LoadFromFile(newFile)) {
                    strcpy(SS.saveFile, newFile);
                    AddToRecentList(newFile);
                } else {
                    strcpy(SS.saveFile, "");
                    SS.NewFile();
                }
                SS.AfterNewFile();
            }
            break;
        }

        case GraphicsWindow::MNU_SAVE:
            SS.GetFilenameAndSave(false);
            break;

        case GraphicsWindow::MNU_SAVE_AS:
            SS.GetFilenameAndSave(true);
            break;

        case GraphicsWindow::MNU_EXPORT_PNG: {
            char exportFile[MAX_PATH] = "";
            if(!GetSaveFile(exportFile, PNG_EXT, PNG_PATTERN)) break;
            SS.ExportAsPngTo(exportFile); 
            break;
        }

        case GraphicsWindow::MNU_EXPORT_VIEW: {
            char exportFile[MAX_PATH] = "";
            if(!GetSaveFile(exportFile, VEC_EXT, VEC_PATTERN)) break;

            // If the user is exporting something where it would be
            // inappropriate to include the constraints, then warn.
            if(SS.GW.showConstraints &&
                (StringEndsIn(exportFile, ".txt") ||
                 fabs(SS.exportOffset) > LENGTH_EPS))
            {
                Message("Constraints are currently shown, and will be exported "
                        "in the toolpath. This is probably not what you want; "
                        "hide them by clicking the link at the top of the "
                        "text window.");
            }

            SS.ExportViewOrWireframeTo(exportFile, false); 
            break;
        }

        case GraphicsWindow::MNU_EXPORT_WIREFRAME: {
            char exportFile[MAX_PATH] = "";
            if(!GetSaveFile(exportFile, V3D_EXT, V3D_PATTERN)) break;
            SS.ExportViewOrWireframeTo(exportFile, true); 
            break;
        }

        case GraphicsWindow::MNU_EXPORT_SECTION: {
            char exportFile[MAX_PATH] = "";
            if(!GetSaveFile(exportFile, VEC_EXT, VEC_PATTERN)) break;
            SS.ExportSectionTo(exportFile); 
            break;
        }

        case GraphicsWindow::MNU_EXPORT_MESH: {
            char exportFile[MAX_PATH] = "";
            if(!GetSaveFile(exportFile, MESH_EXT, MESH_PATTERN)) break;
            SS.ExportMeshTo(exportFile); 
            break;
        }

        case GraphicsWindow::MNU_EXPORT_SURFACES: {
            char exportFile[MAX_PATH] = "";
            if(!GetSaveFile(exportFile, SRF_EXT, SRF_PATTERN)) break;
            StepFileWriter sfw;
            ZERO(&sfw);
            sfw.ExportSurfacesTo(exportFile); 
            break;
        }

        case GraphicsWindow::MNU_EXIT:
            if(!SS.OkayToStartNewFile()) break;
            SS.Exit();
            break;

        default: oops();
    }

    SS.UpdateWindowTitle();
}
Beispiel #24
0
void PrefsManager::Init()
{
	m_iDisplayWidth = SCREEN_WIDTH;
	m_iDisplayHeight = SCREEN_HEIGHT;
	m_iDisplayColorDepth = 16;
	m_iTextureColorDepth = 16;		// default to 16 for better preformance on slower cards
	m_iMovieColorDepth = 16;
	m_iMaxTextureResolution = MAX_TEXTURE_RESOLUTION;
	m_iRefreshRate = REFRESH_DEFAULT;
	m_bOnlyDedicatedMenuButtons = false;
	m_bCelShadeModels = false;		// Work-In-Progress.. disable by default.
	m_fConstantUpdateDeltaSeconds = 0;
#ifdef DEBUG
	m_bShowStats = true;
#else
	m_bShowStats = false;
#endif
	m_bShowBanners = true ;
	m_BackgroundMode = BGMODE_ANIMATIONS;
	m_iNumBackgrounds = 8;
	m_bShowDanger = true;
	m_fBGBrightness = 0.8f;
	m_bMenuTimer = true;
	m_iNumArcadeStages = 3;
	m_bEventMode = false;
	m_bAutoPlay = false;
	m_fJudgeWindowScale = 1.0f;
	m_fJudgeWindowAdd = 0;
	m_fLifeDifficultyScale = 1.0f;
	m_fJudgeWindowSecondsMarvelous =		0.0225f;
	m_fJudgeWindowSecondsPerfect =			0.045f;
	m_fJudgeWindowSecondsGreat =			0.090f;
	m_fJudgeWindowSecondsGood =				0.135f;
	m_fJudgeWindowSecondsBoo =				0.180f;
	m_fJudgeWindowSecondsOK =				0.250f;	// allow enough time to take foot off and put back on
	m_fJudgeWindowSecondsMine =				0.090f;	// same as great
	m_fJudgeWindowSecondsAttack =			0.135f;
	m_fLifeDeltaPercentChangeMarvelous =	+0.008f;
	m_fLifeDeltaPercentChangePerfect =		+0.008f;
	m_fLifeDeltaPercentChangeGreat =		+0.004f;
	m_fLifeDeltaPercentChangeGood =			+0.000f;
	m_fLifeDeltaPercentChangeBoo =			-0.040f;
	m_fLifeDeltaPercentChangeMiss =			-0.080f;
	m_fLifeDeltaPercentChangeHitMine =		-0.160f;
	m_fLifeDeltaPercentChangeOK =			+0.008f;
	m_fLifeDeltaPercentChangeNG =			-0.080f;

	m_fTugMeterPercentChangeMarvelous =		+0.010f;
	m_fTugMeterPercentChangePerfect =		+0.008f;
	m_fTugMeterPercentChangeGreat =			+0.004f;
	m_fTugMeterPercentChangeGood =			+0.000f;
	m_fTugMeterPercentChangeBoo =			-0.010f;
	m_fTugMeterPercentChangeMiss =			-0.020f;
	m_fTugMeterPercentChangeHitMine =		-0.040f;
	m_fTugMeterPercentChangeOK =			+0.008f;
	m_fTugMeterPercentChangeNG =			-0.020f;

	m_iRegenComboAfterFail = 10; // cumulative
	m_iRegenComboAfterMiss = 5; // cumulative
	m_iMaxRegenComboAfterFail = 10;
	m_iMaxRegenComboAfterMiss = 10;
	m_bTwoPlayerRecovery = true;
	m_bMercifulDrain = true;
	m_bMinimum1FullSongInCourses = false;
	
	m_iPercentScoreWeightMarvelous = 3;
	m_iPercentScoreWeightPerfect = 2;
	m_iPercentScoreWeightGreat = 1;
	m_iPercentScoreWeightGood = 0;
	m_iPercentScoreWeightBoo = 0;
	m_iPercentScoreWeightMiss = 0;
	m_iPercentScoreWeightOK = 3;
	m_iPercentScoreWeightNG = 0;
	m_iPercentScoreWeightHitMine = -2;
	m_iGradeWeightMarvelous = 2;
	m_iGradeWeightPerfect = 2;
	m_iGradeWeightGreat = 1;
	m_iGradeWeightGood = 0;
	m_iGradeWeightBoo = -4;
	m_iGradeWeightMiss = -8;
	m_iGradeWeightHitMine = -8;
	m_iGradeWeightOK = 6;
	m_iGradeWeightNG = 0;
	m_iNumGradeTiersUsed = 7;
	ZERO( m_fGradePercent );
	m_fGradePercent[GRADE_TIER_1] = 1.0f;
	m_fGradePercent[GRADE_TIER_2] = 1.0f;
	m_fGradePercent[GRADE_TIER_3] = 0.93f;	// AA
	m_fGradePercent[GRADE_TIER_4] = 0.80f;	// A
	m_fGradePercent[GRADE_TIER_5] = 0.65f;	// B
	m_fGradePercent[GRADE_TIER_6] = 0.45f;	// C
	m_fGradePercent[GRADE_TIER_7] = -99999;	// D
	m_bGradeTier02IsAllPerfects = true;
	
	m_fSuperMeterPercentChangeMarvelous =	+0.05f;
	m_fSuperMeterPercentChangePerfect =		+0.04f;
	m_fSuperMeterPercentChangeGreat =		+0.02f;
	m_fSuperMeterPercentChangeGood =		+0.00f;
	m_fSuperMeterPercentChangeBoo =			-0.00f;
	m_fSuperMeterPercentChangeMiss =		-0.20f;
	m_fSuperMeterPercentChangeHitMine =		-0.40f;
	m_fSuperMeterPercentChangeOK =			+0.04f;
	m_fSuperMeterPercentChangeNG =			-0.20f;
	m_bMercifulSuperMeter = true;

	m_bDelayedEscape = true;
	m_bInstructions = true;
	m_bShowDontDie = true;
	m_bShowSelectGroup = true;
	m_bShowNative = true;
	m_bArcadeOptionsNavigation = false;
	m_bSoloSingle = false;
#ifdef PSP
	m_bDelayedTextureDelete = false;
#else
	m_bDelayedTextureDelete = true;
#endif
	m_bTexturePreload = false;
	m_bDelayedScreenLoad = false;
	m_bDelayedModelDelete = false;
#ifdef PSP
	m_BannerCache = BNCACHE_OFF;
#else
	m_BannerCache = BNCACHE_LOW_RES;
#endif
	m_bPalettedBannerCache = false;
	m_bFastLoad = true;
	m_MusicWheelUsesSections = ALWAYS;
	m_iMusicWheelSwitchSpeed = 10;
	m_bEasterEggs = true;
	m_iMarvelousTiming = 2;
	m_iCoinMode = COIN_HOME;
	m_iCoinsPerCredit = 1;
	m_Premium = NO_PREMIUM;
	m_bDelayedCreditsReconcile = false;
	m_iBoostAppPriority = -1;
	m_bSmoothLines = false;
	m_ShowSongOptions = YES;
	m_bDancePointsForOni = false;
	m_bPercentageScoring = false;
	m_fMinPercentageForMachineSongHighScore = 0.5f;
	m_fMinPercentageForMachineCourseHighScore = 0.001f;	// don't save course scores with 0 percentage
	m_bDisqualification = false;
	m_bShowLyrics = true;
	m_bAutogenSteps = true;
	m_bAutogenGroupCourses = true;
	m_bBreakComboToGetItem = false;
	m_bLockCourseDifficulties = true;
	m_ShowDancingCharacters = CO_RANDOM;
	m_bUseUnlockSystem = false;
	m_bFirstRun = true;
	m_bAutoMapOnJoyChange = true;
	m_fGlobalOffsetSeconds = 0;
	m_bShowBeginnerHelper = false;
	m_bEndlessBreakEnabled = true;
	m_iEndlessNumStagesUntilBreak = 5;
	m_iEndlessBreakLength = 5;
	m_bDisableScreenSaver = true;

	// set to 0 so people aren't shocked at first
	m_iProgressiveLifebar = 0;
	m_iProgressiveNonstopLifebar = 0;
	m_iProgressiveStageLifebar = 0;

	/* DDR Extreme-style extra stage support.
	 * Default off so people used to the current behavior (or those with extra
	 * stage CRS files) don't get it changed around on them. */
	m_bPickExtraStage = false;

	m_bComboContinuesBetweenSongs = false;

	// default to old sort order
	m_iCourseSortOrder = COURSE_SORT_SONGS;
	m_bMoveRandomToEnd = false;
	m_bSubSortByNumSteps = false;
	m_iScoringType = SCORING_MAX2;

	m_iGetRankingName = RANKING_ON;

	m_fLongVerSongSeconds = 60*2.5f;	// Dynamite Rave is 2:55
	m_fMarathonVerSongSeconds = 60*5.f;

	/* I'd rather get occasional people asking for support for this even though it's
	 * already here than lots of people asking why songs aren't being displayed. */
	m_bHiddenSongs = false;
	m_bVsync = true;
	m_sLanguage = "";	// ThemeManager will deal with this invalid language

	m_iCenterImageTranslateX = 0;
	m_iCenterImageTranslateY = 0;
	m_fCenterImageScaleX = 1;
	m_fCenterImageScaleY = 1;

	m_iAttractSoundFrequency = 1;
	m_bAllowExtraStage = true;
	m_bHideDefaultNoteSkin = false;
	m_iMaxHighScoresPerListForMachine = 10;
	m_iMaxHighScoresPerListForPlayer = 3;
	m_fPadStickSeconds = 0;
	m_bForceMipMaps = false;
	m_bTrilinearFiltering = false;
	m_bAnisotropicFiltering = false;
	g_bAutoRestart = false;

	/* XXX: Set these defaults for individual consoles using VideoCardDefaults.ini. */
	m_bPAL = false;
#ifndef _XBOX
	m_bInterlaced = false;
#endif

	/* Number of frames to write ahead; usually 44100 frames per second.
	 * (Number of millisec would be more flexible, but it's more useful to
	 * specify numbers directly.) This is purely a troubleshooting option
	 * and is not honored by all sound drivers. */
	m_iSoundWriteAhead = 0;
	m_fSoundVolume = DEFAULT_SOUND_VOLUME;

	// StepMania.cpp sets these on first run:
	m_iCpuClock = 333;

	m_bAllowUnacceleratedRenderer = false;
	m_bThreadedInput = true;
	m_bThreadedMovieDecode = true;
	m_bScreenTestMode = false;
	m_sMachineName = "NoName";
	m_sIgnoredMessageWindows = "";

	m_sCoursesToShowRanking = "";

#ifdef PSP
	m_bLogToDisk = false;
#else
	m_bLogToDisk = true;
#endif
	m_bForceLogFlush = false;
#ifdef DEBUG
	m_bShowLogOutput = true;
#else
	m_bShowLogOutput = false;
#endif
	m_bTimestamping = false;
	m_bLogSkips = false;
	m_bLogCheckpoints = false;
	m_bShowLoadingWindow = true;

	m_iProductID = 1;


	FOREACH_CONST( IPreference*, *g_pvpSubscribers, p ) (*p)->LoadDefault();
}
Beispiel #25
0
void SolveSpace::MenuAnalyze(int id) {
    SS.GW.GroupSelection();
#define gs (SS.GW.gs)

    switch(id) {
        case GraphicsWindow::MNU_STEP_DIM:
            if(gs.constraints == 1 && gs.n == 0) {
                Constraint *c = SK.GetConstraint(gs.constraint[0]);
                if(c->HasLabel() && !c->reference) {
                    SS.TW.shown.dimFinish = c->valA;
                    SS.TW.shown.dimSteps = 10;
                    SS.TW.shown.dimIsDistance =
                        (c->type != Constraint::ANGLE) &&
                        (c->type != Constraint::LENGTH_RATIO);
                    SS.TW.shown.constraint = c->h;
                    SS.TW.shown.screen = TextWindow::SCREEN_STEP_DIMENSION;

                    // The step params are specified in the text window,
                    // so force that to be shown.
                    SS.GW.ForceTextWindowShown();

                    SS.later.showTW = true;
                    SS.GW.ClearSelection();
                } else {
                    Error("Constraint must have a label, and must not be "
                          "a reference dimension.");
                }
            } else {
                Error("Bad selection for step dimension; select a constraint.");
            }
            break;

        case GraphicsWindow::MNU_NAKED_EDGES: {
            SS.nakedEdges.Clear();

            Group *g = SK.GetGroup(SS.GW.activeGroup);
            SMesh *m = &(g->displayMesh);
            SKdNode *root = SKdNode::From(m);
            bool inters, leaks;
            root->MakeCertainEdgesInto(&(SS.nakedEdges), 
                SKdNode::NAKED_OR_SELF_INTER_EDGES, true, &inters, &leaks);

            InvalidateGraphics();

            const char *intersMsg = inters ?
                "The mesh is self-intersecting (NOT okay, invalid)." :
                "The mesh is not self-intersecting (okay, valid).";
            const char *leaksMsg = leaks ?
                "The mesh has naked edges (NOT okay, invalid)." :
                "The mesh is watertight (okay, valid).";

            char cntMsg[1024];
            sprintf(cntMsg, "\n\nThe model contains %d triangles, from "
                            "%d surfaces.",
                g->displayMesh.l.n, g->runningShell.surface.n);

            if(SS.nakedEdges.l.n == 0) {
                Message("%s\n\n%s\n\nZero problematic edges, good.%s",
                    intersMsg, leaksMsg, cntMsg);
            } else {
                Error("%s\n\n%s\n\n%d problematic edges, bad.%s",
                    intersMsg, leaksMsg, SS.nakedEdges.l.n, cntMsg);
            }
            break;
        }

        case GraphicsWindow::MNU_INTERFERENCE: {
            SS.nakedEdges.Clear();

            SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
            SKdNode *root = SKdNode::From(m);
            bool inters, leaks;
            root->MakeCertainEdgesInto(&(SS.nakedEdges),
                SKdNode::SELF_INTER_EDGES, false, &inters, &leaks);

            InvalidateGraphics();

            if(inters) {
                Error("%d edges interfere with other triangles, bad.",
                    SS.nakedEdges.l.n);
            } else {
                Message("The assembly does not interfere, good.");
            }
            break;
        }

        case GraphicsWindow::MNU_VOLUME: {
            SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
           
            double vol = 0;
            int i;
            for(i = 0; i < m->l.n; i++) {
                STriangle tr = m->l.elem[i];

                // Translate to place vertex A at (x, y, 0)
                Vector trans = Vector::From(tr.a.x, tr.a.y, 0);
                tr.a = (tr.a).Minus(trans);
                tr.b = (tr.b).Minus(trans);
                tr.c = (tr.c).Minus(trans);

                // Rotate to place vertex B on the y-axis. Depending on
                // whether the triangle is CW or CCW, C is either to the
                // right or to the left of the y-axis. This handles the
                // sign of our normal.
                Vector u = Vector::From(-tr.b.y, tr.b.x, 0);
                u = u.WithMagnitude(1);
                Vector v = Vector::From(tr.b.x, tr.b.y, 0);
                v = v.WithMagnitude(1);
                Vector n = Vector::From(0, 0, 1);

                tr.a = (tr.a).DotInToCsys(u, v, n);
                tr.b = (tr.b).DotInToCsys(u, v, n);
                tr.c = (tr.c).DotInToCsys(u, v, n);

                n = tr.Normal().WithMagnitude(1);

                // Triangles on edge don't contribute
                if(fabs(n.z) < LENGTH_EPS) continue;
               
                // The plane has equation p dot n = a dot n
                double d = (tr.a).Dot(n);
                // nx*x + ny*y + nz*z = d
                // nz*z = d - nx*x - ny*y
                double A = -n.x/n.z, B = -n.y/n.z, C = d/n.z;

                double mac = tr.c.y/tr.c.x, mbc = (tr.c.y - tr.b.y)/tr.c.x;
                double xc = tr.c.x, yb = tr.b.y;
               
                // I asked Maple for
                //    int(int(A*x + B*y +C, y=mac*x..(mbc*x + yb)), x=0..xc);
                double integral = 
                    (1.0/3)*(
                        A*(mbc-mac)+
                        (1.0/2)*B*(mbc*mbc-mac*mac)
                    )*(xc*xc*xc)+
                    (1.0/2)*(A*yb+B*yb*mbc+C*(mbc-mac))*xc*xc+
                    C*yb*xc+
                    (1.0/2)*B*yb*yb*xc;

                vol += integral;
            }

            char msg[1024];
            sprintf(msg, "The volume of the solid model is:\n\n"
                         "    %.3f %s^3",
                vol / pow(SS.MmPerUnit(), 3),
                SS.UnitName());

            if(SS.viewUnits == SolveSpace::UNIT_MM) {
                sprintf(msg+strlen(msg), "\n    %.2f mL", vol/(10*10*10));
            }
            strcpy(msg+strlen(msg),
                "\n\nCurved surfaces have been approximated as triangles.\n"
                "This introduces error, typically of around 1%.");
            Message("%s", msg);
            break;
        }

        case GraphicsWindow::MNU_AREA: {
            Group *g = SK.GetGroup(SS.GW.activeGroup);
            if(g->polyError.how != Group::POLY_GOOD) {
                Error("This group does not contain a correctly-formed "
                      "2d closed area. It is open, not coplanar, or self-"
                      "intersecting.");
                break;
            }
            SEdgeList sel;
            ZERO(&sel);
            g->polyLoops.MakeEdgesInto(&sel);
            SPolygon sp;
            ZERO(&sp);
            sel.AssemblePolygon(&sp, NULL, true);
            sp.normal = sp.ComputeNormal();
            sp.FixContourDirections();
            double area = sp.SignedArea();
            double scale = SS.MmPerUnit();
            Message("The area of the region sketched in this group is:\n\n"
                    "    %.3f %s^2\n\n"
                    "Curves have been approximated as piecewise linear.\n"
                    "This introduces error, typically of around 1%%.",
                area / (scale*scale),
                SS.UnitName());
            sel.Clear();
            sp.Clear();
            break;
        }

        case GraphicsWindow::MNU_SHOW_DOF:
            // This works like a normal solve, except that it calculates
            // which variables are free/bound at the same time.
            SS.GenerateAll(0, INT_MAX, true);
            break;

        case GraphicsWindow::MNU_TRACE_PT:
            if(gs.points == 1 && gs.n == 1) {
                SS.traced.point = gs.point[0];
                SS.GW.ClearSelection();
            } else {
                Error("Bad selection for trace; select a single point.");
            }
            break;
            
        case GraphicsWindow::MNU_STOP_TRACING: {
            char exportFile[MAX_PATH] = "";
            if(GetSaveFile(exportFile, CSV_EXT, CSV_PATTERN)) {
                FILE *f = fopen(exportFile, "wb");
                if(f) {
                    int i;
                    SContour *sc = &(SS.traced.path);
                    for(i = 0; i < sc->l.n; i++) {
                        Vector p = sc->l.elem[i].p;
                        double s = SS.exportScale;
                        fprintf(f, "%.10f, %.10f, %.10f\r\n",
                            p.x/s, p.y/s, p.z/s);
                    }
                    fclose(f);
                } else {
                    Error("Couldn't write to '%s'", exportFile);
                }
            }
            // Clear the trace, and stop tracing
            SS.traced.point = Entity::NO_ENTITY;
            SS.traced.path.l.Clear();
            InvalidateGraphics();
            break;
        }

        default: oops();
    }
}
/*
 * pcf_poll - called by the transmit procedure
 */
static void
pcf_poll(
	int unit,
	struct peer *peer
	)
{
	struct refclockproc *pp;
	char buf[LENPCF];
	struct tm tm, *tp;
	time_t t;
	
	pp = peer->procptr;

	buf[0] = 0;
	if (read(pp->io.fd, buf, sizeof(buf)) < (ssize_t)sizeof(buf) || buf[0] != 9) {
		refclock_report(peer, CEVNT_FAULT);
		return;
	}

	ZERO(tm);

	tm.tm_mday = buf[11] * 10 + buf[10];
	tm.tm_mon = buf[13] * 10 + buf[12] - 1;
	tm.tm_year = buf[15] * 10 + buf[14];
	tm.tm_hour = buf[7] * 10 + buf[6];
	tm.tm_min = buf[5] * 10 + buf[4];
	tm.tm_sec = buf[3] * 10 + buf[2];
	tm.tm_isdst = (buf[8] & 1) ? 1 : (buf[8] & 2) ? 0 : -1;

	/*
	 * Y2K convert the 2-digit year
	 */
	if (tm.tm_year < 99)
		tm.tm_year += 100;
	
	t = mktime(&tm);
	if (t == (time_t) -1) {
		refclock_report(peer, CEVNT_BADTIME);
		return;
	}

#if defined(__GLIBC__) && defined(_BSD_SOURCE)
	if ((tm.tm_isdst > 0 && tm.tm_gmtoff != 7200)
	    || (tm.tm_isdst == 0 && tm.tm_gmtoff != 3600)
	    || tm.tm_isdst < 0) {
#ifdef DEBUG
		if (debug)
			printf ("local time zone not set to CET/CEST\n");
#endif
		refclock_report(peer, CEVNT_BADTIME);
		return;
	}
#endif

	pp->lencode = strftime(pp->a_lastcode, BMAX, "%Y %m %d %H %M %S", &tm);

#if defined(_REENTRANT) || defined(_THREAD_SAFE)
	tp = gmtime_r(&t, &tm);
#else
	tp = gmtime(&t);
#endif
	if (!tp) {
		refclock_report(peer, CEVNT_FAULT);
		return;
	}

	get_systime(&pp->lastrec);
	pp->polls++;
	pp->year = tp->tm_year + 1900;
	pp->day = tp->tm_yday + 1;
	pp->hour = tp->tm_hour;
	pp->minute = tp->tm_min;
	pp->second = tp->tm_sec;
	pp->nsec = buf[16] * 31250000;
	if (buf[17] & 1)
		pp->nsec += 500000000;

#ifdef DEBUG
	if (debug)
		printf ("pcf%d: time is %04d/%02d/%02d %02d:%02d:%02d UTC\n",
			unit, pp->year, tp->tm_mon + 1, tp->tm_mday, pp->hour,
			pp->minute, pp->second);
#endif

	if (!refclock_process(pp)) {
		refclock_report(peer, CEVNT_BADTIME);
		return;
	}
	record_clock_stats(&peer->srcadr, pp->a_lastcode);
	if ((buf[1] & 1) && !(pp->sloppyclockflag & CLK_FLAG2))
		pp->leap = LEAP_NOTINSYNC;
	else
		pp->leap = LEAP_NOWARNING;
	pp->lastref = pp->lastrec;
	refclock_receive(peer);
}
Beispiel #27
0
/*
 * local_clock - the NTP logical clock loop filter.
 *
 * Return codes:
 * -1	update ignored: exceeds panic threshold
 * 0	update ignored: popcorn or exceeds step threshold
 * 1	clock was slewed
 * 2	clock was stepped
 *
 * ENABLE_LOCKCLOCK: The only thing this routine does is set the
 * sys_rootdisp variable equal to the peer dispersion.
 */
int
local_clock(
	struct	peer *peer,	/* synch source peer structure */
	double	fp_offset	/* clock offset (s) */
	)
{
#ifdef ENABLE_LOCKCLOCK
	UNUSED_ARG(peer);
	UNUSED_ARG(fp_offset);
#else
	int	rval;		/* return code */
	int	osys_poll;	/* old system poll */
#ifdef HAVE_KERNEL_PLL
	int	ntp_adj_ret;	/* returned by ntp_adjtime */
#endif /* HAVE_KERNEL_PLL */
	double	mu;		/* interval since last update */
	double	clock_frequency; /* clock frequency */
	double	dtemp, etemp;	/* double temps */
	char	tbuf[80];	/* report buffer */
#endif /* ENABLE_LOCKCLOCK */

	/*
	 * If the loop is opened or the NIST lockclock scheme is in use,
	 * monitor and record the offsets anyway in order to determine
	 * the open-loop response and then go home.
	 */
#ifdef ENABLE_LOCKCLOCK
	{
#else
	if (!ntp_enable) {
#endif /* ENABLE_LOCKCLOCK */
		record_loop_stats(fp_offset, drift_comp, clock_jitter,
		    clock_stability, sys_poll);
		return (0);
	}

#ifndef ENABLE_LOCKCLOCK
	/*
	 * If the clock is way off, panic is declared. The clock_panic
	 * defaults to 1000 s; if set to zero, the panic will never
	 * occur. The allow_panic defaults to false, so the first panic
	 * will exit. It can be set true by a command line option, in
	 * which case the clock will be set anyway and time marches on.
	 * But, allow_panic will be set false when the update is less
	 * than the step threshold; so, subsequent panics will exit.
	 */
	if (fabs(fp_offset) > clock_panic && clock_panic > 0 &&
	    !allow_panic) {
		snprintf(tbuf, sizeof(tbuf),
		    "%+.0f s; set clock manually within %.0f s.",
		    fp_offset, clock_panic);
		report_event(EVNT_SYSFAULT, NULL, tbuf);
		return (-1);
	}

	/*
	 * This section simulates ntpdate. If the offset exceeds the
	 * step threshold (128 ms), step the clock to that time and
	 * exit. Otherwise, slew the clock to that time and exit. Note
	 * that the slew will persist and eventually complete beyond the
	 * life of this program. Note that while ntpdate is active, the
	 * terminal does not detach, so the termination message prints
	 * directly to the terminal.
	 */
	if (mode_ntpdate) {
		if (  ( fp_offset > clock_max_fwd  && clock_max_fwd  > 0)
		   || (-fp_offset > clock_max_back && clock_max_back > 0)) {
			step_systime(fp_offset, ntp_set_tod);
			msyslog(LOG_NOTICE, "ntpd: time set %+.6f s",
			    fp_offset);
			printf("ntpd: time set %+.6fs\n", fp_offset);
		} else {
			adj_systime(fp_offset, adjtime);
			msyslog(LOG_NOTICE, "ntpd: time slew %+.6f s",
			    fp_offset);
			printf("ntpd: time slew %+.6fs\n", fp_offset);
		}
		record_loop_stats(fp_offset, drift_comp, clock_jitter,
		    clock_stability, sys_poll);
		exit(0);
	}

	/*
	 * The huff-n'-puff filter finds the lowest delay in the recent
	 * interval. This is used to correct the offset by one-half the
	 * difference between the sample delay and minimum delay. This
	 * is most effective if the delays are highly asymmetric and
	 * clockhopping is avoided and the clock frequency wander is
	 * relatively small.
	 */
	if (sys_huffpuff != NULL) {
		if (peer->delay < sys_huffpuff[sys_huffptr])
			sys_huffpuff[sys_huffptr] = peer->delay;
		if (peer->delay < sys_mindly)
			sys_mindly = peer->delay;
		if (fp_offset > 0)
			dtemp = -(peer->delay - sys_mindly) / 2;
		else
			dtemp = (peer->delay - sys_mindly) / 2;
		fp_offset += dtemp;
#ifdef DEBUG
		if (debug)
			printf(
		    "local_clock: size %d mindly %.6f huffpuff %.6f\n",
			    sys_hufflen, sys_mindly, dtemp);
#endif
	}

	/*
	 * Clock state machine transition function which defines how the
	 * system reacts to large phase and frequency excursion. There
	 * are two main regimes: when the offset exceeds the step
	 * threshold (128 ms) and when it does not. Under certain
	 * conditions updates are suspended until the stepout threshold
	 * (900 s) is exceeded. See the documentation on how these
	 * thresholds interact with commands and command line options.
	 *
	 * Note the kernel is disabled if step is disabled or greater
	 * than 0.5 s or in ntpdate mode.
	 */
	osys_poll = sys_poll;
	if (sys_poll < peer->minpoll)
		sys_poll = peer->minpoll;
	if (sys_poll > peer->maxpoll)
		sys_poll = peer->maxpoll;
	mu = current_time - clock_epoch;
	clock_frequency = drift_comp;
	rval = 1;
	if (  ( fp_offset > clock_max_fwd  && clock_max_fwd  > 0)
	   || (-fp_offset > clock_max_back && clock_max_back > 0)
	   || force_step_once ) {
		if (force_step_once) {
			force_step_once = false;  /* we want this only once after startup */
			msyslog(LOG_NOTICE, "Doing intital time step" );
		}

		switch (state) {

		/*
		 * In SYNC state we ignore the first outlier and switch
		 * to SPIK state.
		 */
		case EVNT_SYNC:
			snprintf(tbuf, sizeof(tbuf), "%+.6f s",
			    fp_offset);
			report_event(EVNT_SPIK, NULL, tbuf);
			state = EVNT_SPIK;
			return (0);

		/*
		 * In FREQ state we ignore outliers and inliers. At the
		 * first outlier after the stepout threshold, compute
		 * the apparent frequency correction and step the phase.
		 */
		case EVNT_FREQ:
			if (mu < clock_minstep)
				return (0);

			clock_frequency = direct_freq(fp_offset);

			/* fall through to EVNT_SPIK */

		/*
		 * In SPIK state we ignore succeeding outliers until
		 * either an inlier is found or the stepout threshold is
		 * exceeded.
		 */
		case EVNT_SPIK:
			if (mu < clock_minstep)
				return (0);

			/* fall through to default */

		/*
		 * We get here by default in NSET and FSET states and
		 * from above in FREQ or SPIK states.
		 *
		 * In NSET state an initial frequency correction is not
		 * available, usually because the frequency file has not
		 * yet been written. Since the time is outside the step
		 * threshold, the clock is stepped. The frequency will
		 * be set directly following the stepout interval.
		 *
		 * In FSET state the initial frequency has been set from
		 * the frequency file. Since the time is outside the
		 * step threshold, the clock is stepped immediately,
		 * rather than after the stepout interval. Guys get
		 * nervous if it takes 15 minutes to set the clock for
		 * the first time.
		 *
		 * In FREQ and SPIK states the stepout threshold has
		 * expired and the phase is still above the step
		 * threshold. Note that a single spike greater than the
		 * step threshold is always suppressed, even with a
		 * long time constant.
		 */
		default:
			snprintf(tbuf, sizeof(tbuf), "%+.6f s",
			    fp_offset);
			report_event(EVNT_CLOCKRESET, NULL, tbuf);
			step_systime(fp_offset, ntp_set_tod);
			reinit_timer();
			tc_counter = 0;
			clock_jitter = LOGTOD(sys_precision);
			rval = 2;
			if (state == EVNT_NSET) {
				rstclock(EVNT_FREQ, 0);
				return (rval);
			}
			break;
		}
		rstclock(EVNT_SYNC, 0);
	} else {
		/*
		 * The offset is less than the step threshold. Calculate
		 * the jitter as the exponentially weighted offset
		 * differences.
		 */
		etemp = SQUARE(clock_jitter);
		dtemp = SQUARE(fp_offset - last_offset);
		clock_jitter = SQRT(etemp + (dtemp - etemp) / CLOCK_AVG);
		switch (state) {

		/*
		 * In NSET state this is the first update received and
		 * the frequency has not been initialized. Adjust the
		 * phase, but do not adjust the frequency until after
		 * the stepout threshold.
		 */
		case EVNT_NSET:
			adj_systime(fp_offset, adjtime);
			rstclock(EVNT_FREQ, fp_offset);
			break;

		/*
		 * In FREQ state ignore updates until the stepout
		 * threshold. After that, compute the new frequency, but
		 * do not adjust the frequency until the holdoff counter
		 * decrements to zero.
		 */
		case EVNT_FREQ:
			if (mu < clock_minstep)
				return (0);

			clock_frequency = direct_freq(fp_offset);
			/* fall through */

		/*
		 * We get here by default in FSET, SPIK and SYNC states.
		 * Here compute the frequency update due to PLL and FLL
		 * contributions. Note, we avoid frequency discipline at
		 * startup until the initial transient has subsided.
		 */
		default:
			allow_panic = false;
			if (freq_cnt == 0) {

				/*
				 * The FLL and PLL frequency gain constants
				 * depend on the time constant and Allan
				 * intercept. The PLL is always used, but
				 * becomes ineffective above the Allan intercept
				 * where the FLL becomes effective.
				 */
				if (sys_poll >= allan_xpt)
					clock_frequency += (fp_offset -
					    clock_offset) / (max(ULOGTOD(sys_poll),
					    mu) * CLOCK_FLL);

				/*
				 * The PLL frequency gain (numerator) depends on
				 * the minimum of the update interval and Allan
				 * intercept. This reduces the PLL gain when the
				 * FLL becomes effective.
				 */
				etemp = min(ULOGTOD(allan_xpt), mu);
				dtemp = 4 * CLOCK_PLL * ULOGTOD(sys_poll);
				clock_frequency += fp_offset * etemp / (dtemp *
				    dtemp);
			}
			rstclock(EVNT_SYNC, fp_offset);
			if (fabs(fp_offset) < CLOCK_FLOOR)
				freq_cnt = 0;
			break;
		}
	}

#ifdef HAVE_KERNEL_PLL
	/*
	 * This code segment works when clock adjustments are made using
	 * precision time kernel support and the ntp_adjtime() system
	 * call. This support is available in Solaris 2.6 and later,
	 * Digital Unix 4.0 and later, FreeBSD, Linux and specially
	 * modified kernels for HP-UX 9 and Ultrix 4. In the case of the
	 * DECstation 5000/240 and Alpha AXP, additional kernel
	 * modifications provide a true microsecond clock and nanosecond
	 * clock, respectively.
	 *
	 * Important note: The kernel discipline is used only if the
	 * step threshold is less than 0.5 s, as anything higher can
	 * lead to overflow problems. This might occur if some misguided
	 * lad set the step threshold to something ridiculous.
	 */
	if (pll_control && kern_enable && freq_cnt == 0) {

		/*
		 * We initialize the structure for the ntp_adjtime()
		 * system call. We have to convert everything to
		 * microseconds or nanoseconds first. Do not update the
		 * system variables if the ext_enable flag is set. In
		 * this case, the external clock driver will update the
		 * variables, which will be read later by the local
		 * clock driver. Afterwards, remember the time and
		 * frequency offsets for jitter and stability values and
		 * to update the frequency file.
		 */
		ZERO(ntv);
		if (ext_enable) {
			ntv.modes = MOD_STATUS;
		} else {
#ifdef STA_NANO
			ntv.modes = MOD_BITS | MOD_NANO;
#else /* STA_NANO */
			ntv.modes = MOD_BITS;
#endif /* STA_NANO */
			if (clock_offset < 0)
				dtemp = -.5;
			else
				dtemp = .5;
			ntv.offset = (long)(clock_offset * NANOSECONDS + dtemp);
#ifdef STA_NANO
			ntv.constant = sys_poll;
#else /* STA_NANO */
			ntv.constant = sys_poll - 4;
#endif /* STA_NANO */
			if (ntv.constant < 0)
				ntv.constant = 0;

			ntv.esterror = (long)(clock_jitter * MICROSECONDS);
			ntv.maxerror = (long)((sys_rootdelay / 2 +
			    sys_rootdisp) * MICROSECONDS);
			ntv.status = STA_PLL;

			/*
			 * Enable/disable the PPS if requested.
			 */
			if (hardpps_enable) {
				ntv.status |= (STA_PPSTIME | STA_PPSFREQ);
				if (!(pll_status & STA_PPSTIME))
					sync_status("PPS enabled",
						pll_status,
						ntv.status);
			} else {
				ntv.status &= ~(STA_PPSTIME | STA_PPSFREQ);
				if (pll_status & STA_PPSTIME)
					sync_status("PPS disabled",
						pll_status,
						ntv.status);
			}
			if (sys_leap == LEAP_ADDSECOND)
				ntv.status |= STA_INS;
			else if (sys_leap == LEAP_DELSECOND) ntv.status |= STA_DEL;
		}

		/*
		 * Pass the stuff to the kernel. If it squeals, turn off
		 * the pps. In any case, fetch the kernel offset,
		 * frequency and jitter.
		 */
		ntp_adj_ret = ntp_adjtime_ns(&ntv);
		/*
		 * A squeal is a return status < 0, or a state change.
		 */
		if ((0 > ntp_adj_ret) || (ntp_adj_ret != kernel_status)) {
			kernel_status = ntp_adj_ret;
			ntp_adjtime_error_handler(__func__, &ntv, ntp_adj_ret, errno, hardpps_enable, false, __LINE__ - 1);
		}
		pll_status = ntv.status;
		clock_offset = ntv.offset / NANOSECONDS;
		clock_frequency = FREQTOD(ntv.freq);

		/*
		 * If the kernel PPS is lit, monitor its performance.
		 */
		if (ntv.status & STA_PPSTIME) {
			clock_jitter = ntv.jitter / NANOSECONDS;
		}

#if defined(STA_NANO) && NTP_API == 4
		/*
		 * If the TAI changes, update the kernel TAI.
		 */
		if (loop_tai != sys_tai) {
			loop_tai = sys_tai;
			ntv.modes = MOD_TAI;
			ntv.constant = sys_tai;
			if ((ntp_adj_ret = ntp_adjtime_ns(&ntv)) != 0) {
			    ntp_adjtime_error_handler(__func__, &ntv, ntp_adj_ret, errno, false, true, __LINE__ - 1);
			}
		}
#endif /* STA_NANO */
	}
#endif /* HAVE_KERNEL_PLL */

	/*
	 * Clamp the frequency within the tolerance range and calculate
	 * the frequency difference since the last update.
	 */
	if (fabs(clock_frequency) > NTP_MAXFREQ)
		msyslog(LOG_NOTICE,
		    "frequency error %.0f PPM exceeds tolerance %.0f PPM",
		    clock_frequency * MICROSECONDS, NTP_MAXFREQ * MICROSECONDS);
	dtemp = SQUARE(clock_frequency - drift_comp);
	if (clock_frequency > NTP_MAXFREQ)
		drift_comp = NTP_MAXFREQ;
	else if (clock_frequency < -NTP_MAXFREQ)
		drift_comp = -NTP_MAXFREQ;
	else
		drift_comp = clock_frequency;

	/*
	 * Calculate the wander as the exponentially weighted RMS
	 * frequency differences. Record the change for the frequency
	 * file update.
	 */
	etemp = SQUARE(clock_stability);
	clock_stability = SQRT(etemp + (dtemp - etemp) / CLOCK_AVG);

	/*
	 * Here we adjust the time constant by comparing the current
	 * offset with the clock jitter. If the offset is less than the
	 * clock jitter times a constant, then the averaging interval is
	 * increased, otherwise it is decreased. A bit of hysteresis
	 * helps calm the dance. Works best using burst mode. Don't
	 * fiddle with the poll during the startup clamp period.
	 */
	if (freq_cnt > 0) {
		tc_counter = 0;
	} else if (fabs(clock_offset) < CLOCK_PGATE * clock_jitter) {
		tc_counter += sys_poll;
		if (tc_counter > CLOCK_LIMIT) {
			tc_counter = CLOCK_LIMIT;
			if (sys_poll < peer->maxpoll) {
				tc_counter = 0;
				sys_poll++;
			}
		}
	} else {
		tc_counter -= sys_poll << 1;
		if (tc_counter < -CLOCK_LIMIT) {
			tc_counter = -CLOCK_LIMIT;
			if (sys_poll > peer->minpoll) {
				tc_counter = 0;
				sys_poll--;
			}
		}
	}

	/*
	 * If the time constant has changed, update the poll variables.
	 */
	if (osys_poll != sys_poll)
		poll_update(peer, sys_poll);

	/*
	 * Yibbidy, yibbbidy, yibbidy; that'h all folks.
	 */
	record_loop_stats(clock_offset, drift_comp, clock_jitter,
	    clock_stability, sys_poll);
#ifdef DEBUG
	if (debug)
		printf(
		    "local_clock: offset %.9f jit %.9f freq %.3f stab %.3f poll %d\n",
		    clock_offset, clock_jitter, drift_comp * MICROSECONDS,
		    clock_stability * MICROSECONDS, sys_poll);
#endif /* DEBUG */
	return (rval);
#endif /* ENABLE_LOCKCLOCK */
}


/*
 * adj_host_clock - Called once every second to update the local clock.
 *
 * ENABLE_LOCKCLOCK: The only thing this routine does is increment the
 * sys_rootdisp variable.
 */
void
adj_host_clock(
	void
	)
{
#ifndef ENABLE_LOCKCLOCK
	double	offset_adj;
	double	freq_adj;
#endif /* ENABLE_LOCKCLOCK */
	
	/*
	 * Update the dispersion since the last update. In contrast to
	 * NTPv3, NTPv4 does not declare unsynchronized after one day,
	 * since the dispersion check serves this function. Also,
	 * since the poll interval can exceed one day, the old test
	 * would be counterproductive. During the startup clamp period, the
	 * time constant is clamped at 2.
	 */
	sys_rootdisp += clock_phi;
#ifndef ENABLE_LOCKCLOCK
	if (!ntp_enable || mode_ntpdate)
		return;
	/*
	 * Determine the phase adjustment. The gain factor (denominator)
	 * increases with poll interval, so is dominated by the FLL
	 * above the Allan intercept. Note the reduced time constant at
	 * startup.
	 */
	if (state != EVNT_SYNC) {
		offset_adj = 0.;
	} else if (freq_cnt > 0) {
		offset_adj = clock_offset / (CLOCK_PLL * ULOGTOD(1));
		freq_cnt--;
#ifdef HAVE_KERNEL_PLL
	} else if (pll_control && kern_enable) {
		offset_adj = 0.;
#endif /* HAVE_KERNEL_PLL */
	} else {
		offset_adj = clock_offset / (CLOCK_PLL * ULOGTOD(sys_poll));
	}

	/*
	 * If the kernel discipline is enabled the frequency correction
	 * drift_comp has already been engaged via ntp_adjtime() in
	 * set_freq().  Otherwise it is a component of the adj_systime()
	 * offset.
	 */
#ifdef HAVE_KERNEL_PLL
	if (pll_control && kern_enable)
		freq_adj = 0.;
	else
#endif /* HAVE_KERNEL_PLL */
		freq_adj = drift_comp;

	/* Bound absolute value of total adjustment to NTP_MAXFREQ. */
	if (offset_adj + freq_adj > NTP_MAXFREQ)
		offset_adj = NTP_MAXFREQ - freq_adj;
	else if (offset_adj + freq_adj < -NTP_MAXFREQ)
		offset_adj = -NTP_MAXFREQ - freq_adj;

	clock_offset -= offset_adj;
	/*
	 * FIXME: With the Windows legacy port officially gone, this
	 * could be called much less often.  However, leave some
	 * version of the comment below in place in case of a re-port.
	 * See also the related FIXME comment in libntp/systime.c
	 *
	 * Windows port adj_systime() must be called each second,
	 * even if the argument is zero, to ease emulation of
	 * adjtime() using Windows' slew API which controls the rate
	 * but does not automatically stop slewing when an offset
	 * has decayed to zero.
	 */
	adj_systime(offset_adj + freq_adj, adjtime);
#endif /* ENABLE_LOCKCLOCK */
}
void SolveSpace::ExportViewOrWireframeTo(char *filename, bool wireframe) {
    int i;
    SEdgeList edges;
    ZERO(&edges);
    SBezierList beziers;
    ZERO(&beziers);

    SMesh *sm = NULL;
    if(SS.GW.showShaded) {
        Group *g = SK.GetGroup(SS.GW.activeGroup);
        g->GenerateDisplayItems();
        sm = &(g->displayMesh);
    }
    if(sm && sm->IsEmpty()) {
        sm = NULL;
    }

    for(i = 0; i < SK.entity.n; i++) {
        Entity *e = &(SK.entity.elem[i]);
        if(!e->IsVisible()) continue;
        if(e->construction) continue;

        if(SS.exportPwlCurves || (sm && !SS.GW.showHdnLines) ||
                                 fabs(SS.exportOffset) > LENGTH_EPS)
        {
            // We will be doing hidden line removal, which we can't do on
            // exact curves; so we need things broken down to pwls. Same
            // problem with cutter radius compensation.
            e->GenerateEdges(&edges);
        } else {
            e->GenerateBezierCurves(&beziers);
        }
    }

    if(SS.GW.showEdges) {
        Group *g = SK.GetGroup(SS.GW.activeGroup);
        g->GenerateDisplayItems();
        SEdgeList *selr = &(g->displayEdges);
        SEdge *se;
        for(se = selr->l.First(); se; se = selr->l.NextAfter(se)) {
            edges.AddEdge(se->a, se->b, Style::SOLID_EDGE);
        }
    }

    if(SS.GW.showConstraints) {
        Constraint *c;
        for(c = SK.constraint.First(); c; c = SK.constraint.NextAfter(c)) {
            c->GetEdges(&edges);
        }
    }

    if(wireframe) {
        VectorFileWriter *out = VectorFileWriter::ForFile(filename);
        if(out) {
            ExportWireframeCurves(&edges, &beziers, out);
        }
    } else {
        Vector u = SS.GW.projRight,
               v = SS.GW.projUp,
               n = u.Cross(v),
               origin = SS.GW.offset.ScaledBy(-1);

        VectorFileWriter *out = VectorFileWriter::ForFile(filename);
        if(out) {
            ExportLinesAndMesh(&edges, &beziers, sm,
                               u, v, n, origin, SS.CameraTangent()*SS.GW.scale,
                               out);
        }

        if(out && !out->HasCanvasSize()) {
            // These file formats don't have a canvas size, so they just
            // get exported in the raw coordinate system. So indicate what
            // that was on-screen.
            SS.justExportedInfo.draw = true;
            SS.justExportedInfo.pt = origin;
            SS.justExportedInfo.u = u;
            SS.justExportedInfo.v = v;
            InvalidateGraphics();
        }
    }

    edges.Clear();
    beziers.Clear();
}
Beispiel #29
0
void
OPK_PLCG(const opk_index_t n, real_t p[], real_t q[], real_t r[],
         real_t x[], real_t z[], real_t rho[4], opk_cg_state_t *state)
{
  const real_t zero = OPK_REALCONST(0.0);
  real_t pq, alpha, beta;
  opk_index_t i;

  switch (*state) {

  case OPK_CG_START:

    /* Start with no initial guess: fill x with zeros,
       there is no needs to compute q = A.x0 since it is 0. */
    ZERO(n, x);
    rho[0] = rho[1] = rho[2] = rho[3] = zero;
    *state = OPK_CG_NEWX;
    return;

  case OPK_CG_RESTART:

    /* Start or restart with initial x given: copy initial x into p and
       request caller to compte: q = A.p */
    COPY(n, x, p);
    rho[0] = rho[1] = rho[2] = rho[3] = zero;
    *state = OPK_CG_AP;
    return;

  case OPK_CG_NEWX:

    if (z == NULL) {
      /* No preconditioning.  Take z = r and jump to next case to compute
         conjugate gradient direction. */
      z = r;
    } else {
      /* Preconditioned version of the algorithm.  Request caller to compute
         preconditioned residuals. */
      *state = OPK_CG_PRECOND;
      return;
    }

  case OPK_CG_PRECOND:

    /* Caller has been requested to compute preconditioned residuals.  Use
       conjugate gradients recurrence to compute next search direption p. */
    rho[1] = DOT(n, r, z);
    if (rho[1] <= zero) {
      /* If r'.z too small, then algorithm has converged
         or A is not positive definite. */
      *state = (rho[1] < zero ? OPK_CG_NON_CONVEX : OPK_CG_FINISH);
      return;
    }
    if (rho[0] > zero) {
      beta = rho[1]/rho[0];
      for (i = 0; i < n; ++i) {
        p[i] = z[i] + beta*p[i];
      }
    } else {
      beta = zero;
      COPY(n, z, p);
    }
    rho[3] = beta;

    /* Request caller to compute: q = A.p */
    *state = OPK_CG_AP;
    return;

  case OPK_CG_AP:

    if (rho[1] > zero) {
      /* Caller has been requested to compute q = A.p.  Compute optimal step
         size and update the variables and the residuals. */
      pq = DOT(n, p, q);
      if (pq <= zero) {
        /* Operator A is not positive definite. */
        *state = OPK_CG_NON_CONVEX;
        return;
      }
      alpha = rho[1]/pq; /* optimal step size */
      rho[2] = alpha; /* memorize optimal step size */
      if (alpha == zero) {
        /* If alpha too small, then algorithm has converged. */
        *state = OPK_CG_FINISH;
        return;
      }
      AXPY(n,  alpha, p, x);
      AXPY(n, -alpha, q, r);
      rho[0] = rho[1];
    } else {
      /* Caller has been requested to compute q = A.x0
         Update the residuals. */
      AXPY(n, -1.0, q, r);
    }

    /* Variables X and residuals R available for inspection. */
    *state = OPK_CG_NEWX;
    return;

  case OPK_CG_FINISH:
  case OPK_CG_NON_CONVEX:

    /* If state is OPK_CG_FINISH, the caller can restart the algorithm with
       final x, state set to OPK_CG_RESTART and r set to b. */
    return;

  default:

    /* There must be something wrong... */
    *state = OPK_CG_ERROR;
    return;
  }

}